ref: 5c30140aa4d842dbb700cd6c8b9d7296fd91da84
parent: 72db5b394c55a4fecc11f7af3faad04b5bc755ba
author: joe9 <joe9mail@gmail.com>
date: Fri Jul 16 19:27:44 EDT 2021
moving inferno os/boot away
--- a/os/boot/README
+++ /dev/null
@@ -1,33 +1,0 @@
-Often the devices we use now come with some
-form of bootstrap (often annoyingly complicated,
-which gets in the way). Older boards were sometimes
-bare, and we had to provide something (often annoyingly
-complicated...). On the PC it's currently helpful to
-have something that can boot from disc or ether;
-since it's a thankless task to write such a thing, we
-use Plan 9's, and thank its authors.
-
-The current scheme on newer devices is to have a simple
-program that can put a stripped-down Inferno kernel into
-flash, and use that to boot from other devices (including over the net)
-as required during development.
-
-There are two distinct models for bootstrap in this directory.
-
- Model I
-
-Each member of the first model is represented by a self-contained directory.
-They are derived from various ages of Plan 9's /sys/src/boot/pc.
-
-arm1110 arm a prefix to a gzip'd kernel to decompress it (runs after basic bootloader)
-pc 386 pc-specific bootstrap essentially identical to current Plan 9
- and covered by the Lucent Public License; it uses
-libflate - zlib-style inflate/deflate library
-mpc power PowerPC bootstrap for FADS board derived from an older version
- of Plan 9 but covered by our Inferno licence (because it came with Inferno)
-puma arm SA110 bootstrap for Teralogics Puma, also covered by the Inferno licence
-
- Model II
-omap purpose-built bootstrap for the OMAP processor
-
-Not all of these are being distributed.
--- a/os/boot/arm1110/Mk
+++ /dev/null
@@ -1,8 +1,0 @@
-#!/bin/rc
-rfork ne
-ROOT=/usr/inferno
-fn cd
-NPROC=3
-path=(/usr/inferno/Plan9/$cputype/bin $path)
-#bind /usr/inferno/mkconfig.dist /usr/inferno/mkconfig
-exec mk $*
--- a/os/boot/arm1110/dat.h
+++ /dev/null
@@ -1,1 +1,0 @@
-/* deliberately empty */
--- a/os/boot/arm1110/donprint.c
+++ /dev/null
@@ -1,332 +1,0 @@
-#include "u.h"
-#include "lib.h"
-
-#define PTR sizeof(char*)
-#define SHORT sizeof(int)
-#define INT sizeof(int)
-#define LONG sizeof(long)
-#define IDIGIT 30
-#define MAXCON 30
-
-#define FLONG (1<<0)
-#define FSHORT (1<<1)
-#define FUNSIGN (1<<2)
-
-typedef struct Op Op;
-struct Op
-{
- char *p;
- char *ep;
- void *argp;
- int f1;
- int f2;
- int f3;
-};
-
-static int noconv(Op*);
-static int cconv(Op*);
-static int dconv(Op*);
-static int hconv(Op*);
-static int lconv(Op*);
-static int oconv(Op*);
-static int sconv(Op*);
-static int uconv(Op*);
-static int xconv(Op*);
-static int Xconv(Op*);
-static int percent(Op*);
-
-static
-int (*fmtconv[MAXCON])(Op*) =
-{
- noconv,
- cconv, dconv, hconv, lconv,
- oconv, sconv, uconv, xconv,
- Xconv, percent,
-};
-static
-char fmtindex[128] =
-{
- ['c'] 1,
- ['d'] 2,
- ['h'] 3,
- ['l'] 4,
- ['o'] 5,
- ['s'] 6,
- ['u'] 7,
- ['x'] 8,
- ['X'] 9,
- ['%'] 10,
-};
-
-static int convcount = { 11 };
-static int ucase;
-
-static void
-PUT(Op *o, int c)
-{
- static int pos;
- int opos;
-
- if(c == '\t'){
- opos = pos;
- pos = (opos+8) & ~7;
- while(opos++ < pos && o->p < o->ep)
- *o->p++ = ' ';
- return;
- }
- if(o->p < o->ep){
- *o->p++ = c;
- pos++;
- }
- if(c == '\n')
- pos = 0;
-}
-
-int
-fmtinstall(char c, int (*f)(Op*))
-{
-
- c &= 0177;
- if(fmtindex[c] == 0) {
- if(convcount >= MAXCON)
- return 1;
- fmtindex[c] = convcount++;
- }
- fmtconv[fmtindex[c]] = f;
- return 0;
-}
-
-char*
-donprint(char *p, char *ep, char *fmt, void *argp)
-{
- int sf1, c;
- Op o;
-
- o.p = p;
- o.ep = ep;
- o.argp = argp;
-
-loop:
- c = *fmt++;
- if(c != '%') {
- if(c == 0) {
- if(o.p < o.ep)
- *o.p = 0;
- return o.p;
- }
- PUT(&o, c);
- goto loop;
- }
- o.f1 = 0;
- o.f2 = -1;
- o.f3 = 0;
- c = *fmt++;
- sf1 = 0;
- if(c == '-') {
- sf1 = 1;
- c = *fmt++;
- }
- while(c >= '0' && c <= '9') {
- o.f1 = o.f1*10 + c-'0';
- c = *fmt++;
- }
- if(sf1)
- o.f1 = -o.f1;
- if(c != '.')
- goto l1;
- c = *fmt++;
- while(c >= '0' && c <= '9') {
- if(o.f2 < 0)
- o.f2 = 0;
- o.f2 = o.f2*10 + c-'0';
- c = *fmt++;
- }
-l1:
- if(c == 0)
- fmt--;
- c = (*fmtconv[fmtindex[c&0177]])(&o);
- if(c < 0) {
- o.f3 |= -c;
- c = *fmt++;
- goto l1;
- }
- o.argp = (char*)o.argp + c;
- goto loop;
-}
-
-void
-strconv(char *o, Op *op, int f1, int f2)
-{
- int n, c;
- char *p;
-
- n = strlen(o);
- if(f1 >= 0)
- while(n < f1) {
- PUT(op, ' ');
- n++;
- }
- for(p=o; c = *p++;)
- if(f2 != 0) {
- PUT(op, c);
- f2--;
- }
- if(f1 < 0) {
- f1 = -f1;
- while(n < f1) {
- PUT(op, ' ');
- n++;
- }
- }
-}
-
-int
-numbconv(Op *op, int base)
-{
- char b[IDIGIT];
- int i, f, n, r;
- long v;
- short h;
-
- f = 0;
- switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
- case FLONG:
- v = *(long*)op->argp;
- r = LONG;
- break;
-
- case FUNSIGN|FLONG:
- v = *(ulong*)op->argp;
- r = LONG;
- break;
-
- case FSHORT:
- h = *(int*)op->argp;
- v = h;
- r = SHORT;
- break;
-
- case FUNSIGN|FSHORT:
- h = *(int*)op->argp;
- v = (ushort)h;
- r = SHORT;
- break;
-
- default:
- v = *(int*)op->argp;
- r = INT;
- break;
-
- case FUNSIGN:
- v = *(unsigned*)op->argp;
- r = INT;
- break;
- }
- if(!(op->f3 & FUNSIGN) && v < 0) {
- v = -v;
- f = 1;
- }
- b[IDIGIT-1] = 0;
- for(i = IDIGIT-2;; i--) {
- n = (ulong)v % base;
- n += '0';
- if(n > '9'){
- n += 'a' - ('9'+1);
- if(ucase)
- n += 'A'-'a';
- }
- b[i] = n;
- if(i < 2)
- break;
- v = (ulong)v / base;
- if(op->f2 >= 0 && i >= IDIGIT-op->f2)
- continue;
- if(v <= 0)
- break;
- }
- if(f)
- b[--i] = '-';
- strconv(b+i, op, op->f1, -1);
- return r;
-}
-
-static int
-noconv(Op *op)
-{
-
- strconv("***", op, 0, -1);
- return 0;
-}
-
-static int
-cconv(Op *op)
-{
- char b[2];
-
- b[0] = *(int*)op->argp;
- b[1] = 0;
- strconv(b, op, op->f1, -1);
- return INT;
-}
-
-static int
-dconv(Op *op)
-{
- return numbconv(op, 10);
-}
-
-static int
-hconv(Op*)
-{
- return -FSHORT;
-}
-
-static int
-lconv(Op*)
-{
- return -FLONG;
-}
-
-static int
-oconv(Op *op)
-{
- return numbconv(op, 8);
-}
-
-static int
-sconv(Op *op)
-{
- strconv(*(char**)op->argp, op, op->f1, op->f2);
- return PTR;
-}
-
-static int
-uconv(Op*)
-{
- return -FUNSIGN;
-}
-
-static int
-xconv(Op *op)
-{
- return numbconv(op, 16);
-}
-
-static int
-Xconv(Op *op)
-{
- int r;
-
- ucase = 1;
- r = numbconv(op, 16);
- ucase = 0;
- return r;
-}
-
-static int
-percent(Op *op)
-{
-
- PUT(op, '%');
- return 0;
-}
--- a/os/boot/arm1110/fns.h
+++ /dev/null
@@ -1,7 +1,0 @@
-/*
- * functions defined locally
- */
-extern int gunzip(uchar *out, int outn, uchar *in, int inn);
-extern void delay(int ms);
-extern void serialputs(char *str, int n);
-extern void draincache(void);
--- a/os/boot/arm1110/il.s
+++ /dev/null
@@ -1,99 +1,0 @@
-#include "mem.h"
-/*
- * Entered here from Compaq's bootldr. First relocate to
- * the location we're linked for and then copy back the
- * decompressed kernel.
- *
- * All
- */
-TEXT _start(SB), $-4
- MOVW $setR12(SB), R12 /* load the SB */
- MOVW $1, R0 /* dance to make 5l think that the magic */
- MOVW $1, R1 /* numbers in WORDs below are being used */
- CMP.S R0, R1 /* and to align them to where bootldr wants */
- BEQ _start2
- WORD $0x016f2818 /* magic number to say we are a kernel */
- WORD $0xc0008000 /* entry point address */
- WORD $0 /* size?, or end of data? */
-
-_start2:
-
- /* SVC mode, interrupts disabled */
- MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
- MOVW R1, CPSR
-
- /* disable the MMU */
- MOVW $0x130, R1
- MCR CpMMU, 0, R1, C(CpControl), C(0x0)
-
- /* enable caches */
- MRC CpMMU, 0, R0, C(CpControl), C(0x0)
- ORR $(CpCdcache|CpCicache|CpCwb), R0
- MCR CpMMU, 0, R0, C(CpControl), C(0x0)
-
- /* flush caches */
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
- /* drain prefetch */
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
-
- /* drain write buffer */
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
-
- /* relocate to where we expect to be */
- MOVW $(FLATESIZE),R3
- MOVW $0xC0008000,R1
- MOVW $0xC0200000,R2
- ADD R1,R3
-_relloop:
- MOVW (R1),R0
- MOVW R0,(R2)
- ADD $4,R1
- ADD $4,R2
- CMP.S R1,R3
- BNE _relloop
-
- MOVW $(MACHADDR+BY2PG), R13 /* stack */
- SUB $4, R13 /* link */
-
- /* jump to where we've been relocated */
- MOVW $_relocated(SB),R15
-
-TEXT _relocated(SB),$-4
- BL main(SB)
- BL exit(SB)
- /* we shouldn't get here */
-_mainloop:
- B _mainloop
- BL _div(SB) /* hack to get _div etc loaded */
-
-TEXT mypc(SB),$-4
- MOVW R14,R0
- RET
-
-TEXT draincache(SB),$-4
- /* write back any dirty data */
- MOVW $0xe0000000,R0
- ADD $(8*1024),R0,R1
-_cfloop:
- MOVW.P 32(R0),R2
- CMP.S R0,R1
- BNE _cfloop
-
- /* drain write buffer and invalidate i&d cache contents */
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
-
- /* drain prefetch */
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
-
- /* disable caches */
- MRC CpMMU, 0, R0, C(CpControl), C(0x0)
- BIC $(CpCdcache|CpCicache|CpCwb), R0
- MCR CpMMU, 0, R0, C(CpControl), C(0x0)
- RET
--- a/os/boot/arm1110/imain.c
+++ /dev/null
@@ -1,48 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "fns.h"
-#include "dat.h"
-#include "mem.h"
-
-void
-main(void)
-{
- void (*f)(void);
- ulong *kernel;
-
- print("inflating kernel\n");
-
- kernel = (ulong*)(0xc0200000+20*1024);
- if(gunzip((uchar*)0xc0008000, 2*1024*1024, (uchar*)kernel, FLATESIZE) > 0){
- f = (void (*)(void))0xc0008010;
- draincache();
- } else {
- print("inflation failed\n");
- f = nil;
- }
- (*f)();
-}
-
-void
-exit(void)
-{
-
- void (*f)(void);
-
- delay(1000);
-
- print("it's a wonderful day to die\n");
- f = nil;
- (*f)();
-}
-
-void
-delay(int ms)
-{
- int i;
-
- while(ms-- > 0){
- for(i = 0; i < 1000; i++)
- ;
- }
-}
--- a/os/boot/arm1110/inflate.c
+++ /dev/null
@@ -1,208 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include <flate.h>
-
-typedef struct Biobuf Biobuf;
-
-struct Biobuf
-{
- uchar *bp;
- uchar *p;
- uchar *ep;
-};
-
-static int header(Biobuf*);
-static int trailer(Biobuf*, Biobuf*);
-static int getc(void*);
-static ulong offset(Biobuf*);
-static int crcwrite(void *out, void *buf, int n);
-static ulong get4(Biobuf *b);
-static ulong Boffset(Biobuf *bp);
-
-/* GZIP flags */
-enum {
- Ftext= (1<<0),
- Fhcrc= (1<<1),
- Fextra= (1<<2),
- Fname= (1<<3),
- Fcomment= (1<<4),
-
- GZCRCPOLY = 0xedb88320UL,
-};
-
-static ulong *crctab;
-static ulong crc;
-
-int
-gunzip(uchar *out, int outn, uchar *in, int inn)
-{
- Biobuf bin, bout;
- int err;
-
- crc = 0;
- crctab = mkcrctab(GZCRCPOLY);
- err = inflateinit();
- if(err != FlateOk)
- print("inflateinit failed: %s\n", flateerr(err));
-
- bin.bp = bin.p = in;
- bin.ep = in+inn;
- bout.bp = bout.p = out;
- bout.ep = out+outn;
-
- err = header(&bin);
- if(err != FlateOk)
- return err;
-
- err = inflate(&bout, crcwrite, &bin, getc);
- if(err != FlateOk)
- print("inflate failed: %s\n", flateerr(err));
-
- err = trailer(&bout, &bin);
- if(err != FlateOk)
- return err;
-
- return Boffset(&bout);
-}
-
-static int
-header(Biobuf *bin)
-{
- int i, flag;
-
- if(getc(bin) != 0x1f || getc(bin) != 0x8b){
- print("bad magic\n");
- return FlateCorrupted;
- }
- if(getc(bin) != 8){
- print("unknown compression type\n");
- return FlateCorrupted;
- }
-
- flag = getc(bin);
-
- /* mod time */
- get4(bin);
-
- /* extra flags */
- getc(bin);
-
- /* OS type */
- getc(bin);
-
- if(flag & Fextra)
- for(i=getc(bin); i>0; i--)
- getc(bin);
-
- /* name */
- if(flag&Fname)
- while(getc(bin) != 0)
- ;
-
- /* comment */
- if(flag&Fcomment)
- while(getc(bin) != 0)
- ;
-
- /* crc16 */
- if(flag&Fhcrc) {
- getc(bin);
- getc(bin);
- }
-
- return FlateOk;
-}
-
-static int
-trailer(Biobuf *bout, Biobuf *bin)
-{
- /* crc32 */
- ulong x;
-
- x = get4(bin);
- if(crc != x){
- print("crc mismatch %lux %lux\n", crc, x);
- return FlateCorrupted;
- }
-
- /* length */
- if(get4(bin) != Boffset(bout)){
- print("bad output len\n");
- return FlateCorrupted;
- }
- return FlateOk;
-}
-
-static ulong
-get4(Biobuf *b)
-{
- ulong v;
- int i, c;
-
- v = 0;
- for(i = 0; i < 4; i++){
- c = getc(b);
- v |= c << (i * 8);
- }
- return v;
-}
-
-static int
-getc(void *in)
-{
- Biobuf *bp = in;
-
- if((bp->p - bp->bp) % 10000 == 0)
- print(".");
- if(bp->p >= bp->ep)
- return -1;
- return *bp->p++;
-}
-
-static ulong
-Boffset(Biobuf *bp)
-{
- return bp->p - bp->bp;
-}
-
-static int
-crcwrite(void *out, void *buf, int n)
-{
- Biobuf *bp;
-
- crc = blockcrc(crctab, crc, buf, n);
- bp = out;
- if(n > bp->ep-bp->p)
- n = bp->ep-bp->p;
- memmove(bp->p, buf, n);
- bp->p += n;
- return n;
-}
-
-#undef malloc
-#undef free
-
-static ulong ibrkp = ~0;
-
-void *
-malloc(ulong n)
-{
- ulong rv;
-
- if(ibrkp == ~0)
- ibrkp = ((ulong)end)+1024*1024;
- n = (n+3)>>2;
- n <<= 2;
- rv = ibrkp;
- ibrkp += n;
- return (void*)rv;
-}
-
-void
-free(void *)
-{
-}
--- a/os/boot/arm1110/io.h
+++ /dev/null
@@ -1,261 +1,0 @@
-/*
- * Definitions for IO devices. Used only in C.
- */
-
-enum
-{
- /* hardware counter frequency */
- ClockFreq= 3686400,
-};
-
-/*
- * IRQ's defined by SA1100
- */
-enum
-{
- IRQgpio0= 0,
- IRQgpio1= 1,
- IRQgpio2= 2,
- IRQgpio3= 3,
- IRQgpio4= 4,
- IRQgpio5= 5,
- IRQgpio6= 6,
- IRQgpio7= 7,
- IRQgpio8= 8,
- IRQgpio9= 9,
- IRQgpio10= 10,
- IRQgpiohi= 11,
- IRQlcd= 12,
- IRQudc= 13,
- IRQuart1b= 15,
- IRQuart2= 16,
- IRQuart3= 17,
- IRQmcp= 18,
- IRQssp= 19,
- IRQdma0= 20,
- IRQdma1= 21,
- IRQdma2= 22,
- IRQdma3= 23,
- IRQdma4= 24,
- IRQdma5= 25,
- IRQtimer0= 26,
- IRQtimer1= 27,
- IRQtimer2= 28,
- IRQtimer3= 29,
- IRQsecond= 30,
- IRQrtc= 31,
-};
-
-/*
- * GPIO lines (signal names from compaq document). _i indicates input
- * and _o output.
- */
-enum
-{
- GPIO_PWR_ON_i= 1<<0, /* power button */
- GPIO_UP_IRQ_i= 1<<1, /* microcontroller interrupts */
- GPIO_LDD8_o= 1<<2, /* LCD data 8-15 */
- GPIO_LDD9_o= 1<<3,
- GPIO_LDD10_o= 1<<4,
- GPIO_LDD11_o= 1<<5,
- GPIO_LDD12_o= 1<<6,
- GPIO_LDD13_o= 1<<7,
- GPIO_LDD14_o= 1<<8,
- GPIO_LDD15_o= 1<<9,
- GPIO_CARD_IND1_i= 1<<10, /* card inserted in PCMCIA socket 1 */
- GPIO_CARD_IRQ1_i= 1<<11, /* PCMCIA socket 1 interrupt */
- GPIO_CLK_SET0_o= 1<<12, /* clock selects for audio codec */
- GPIO_CLK_SET1_o= 1<<13,
- GPIO_L3_SDA_io= 1<<14, /* UDA1341 interface */
- GPIO_L3_MODE_o= 1<<15,
- GPIO_L3_SCLK_o= 1<<16,
- GPIO_CARD_IND0_i= 1<<17, /* card inserted in PCMCIA socket 0 */
- GPIO_KEY_ACT_i= 1<<18, /* hot key from cradle */
- GPIO_SYS_CLK_i= 1<<19, /* clock from codec */
- GPIO_BAT_FAULT_i= 1<<20, /* battery fault */
- GPIO_CARD_IRQ0_i= 1<<21, /* PCMCIA socket 0 interrupt */
- GPIO_LOCK_i= 1<<22, /* expansion pack lock/unlock */
- GPIO_COM_DCD_i= 1<<23, /* DCD from UART3 */
- GPIO_OPT_IRQ_i= 1<<24, /* expansion pack IRQ */
- GPIO_COM_CTS_i= 1<<25, /* CTS from UART3 */
- GPIO_COM_RTS_o= 1<<26, /* RTS to UART3 */
- GPIO_OPT_IND_i= 1<<27, /* expansion pack inserted */
-
-/* Peripheral Unit GPIO pin assignments: alternate functions */
- GPIO_SSP_TXD_o= 1<<10, /* SSP Transmit Data */
- GPIO_SSP_RXD_i= 1<<11, /* SSP Receive Data */
- GPIO_SSP_SCLK_o= 1<<12, /* SSP Sample CLocK */
- GPIO_SSP_SFRM_o= 1<<13, /* SSP Sample FRaMe */
- /* ser. port 1: */
- GPIO_UART_TXD_o= 1<<14, /* UART Transmit Data */
- GPIO_UART_RXD_i= 1<<15, /* UART Receive Data */
- GPIO_SDLC_SCLK_io= 1<<16, /* SDLC Sample CLocK (I/O) */
- GPIO_SDLC_AAF_o= 1<<17, /* SDLC Abort After Frame */
- GPIO_UART_SCLK1_i= 1<<18, /* UART Sample CLocK 1 */
- /* ser. port 4: */
- GPIO_SSP_CLK_i= 1<<19, /* SSP external CLocK */
- /* ser. port 3: */
- GPIO_UART_SCLK3_i= 1<<20, /* UART Sample CLocK 3 */
- /* ser. port 4: */
- GPIO_MCP_CLK_i= 1<<21, /* MCP CLocK */
- /* test controller: */
- GPIO_TIC_ACK_o= 1<<21, /* TIC ACKnowledge */
- GPIO_MBGNT_o= 1<<21, /* Memory Bus GraNT */
- GPIO_TREQA_i= 1<<22, /* TIC REQuest A */
- GPIO_MBREQ_i= 1<<22, /* Memory Bus REQuest */
- GPIO_TREQB_i= 1<<23, /* TIC REQuest B */
- GPIO_1Hz_o= 1<<25, /* 1 Hz clock */
- GPIO_RCLK_o= 1<<26, /* internal (R) CLocK (O, fcpu/2) */
- GPIO_32_768kHz_o= 1<<27, /* 32.768 kHz clock (O, RTC) */
-};
-
-/*
- * types of interrupts
- */
-enum
-{
- GPIOrising,
- GPIOfalling,
- GPIOboth,
- IRQ,
-};
-
-/* hardware registers */
-typedef struct Uartregs Uartregs;
-struct Uartregs
-{
- ulong ctl[4];
- ulong dummya;
- ulong data;
- ulong dummyb;
- ulong status[2];
-};
-Uartregs *uart3regs;
-
-/* general purpose I/O lines control registers */
-typedef struct GPIOregs GPIOregs;
-struct GPIOregs
-{
- ulong level; /* 1 == high */
- ulong direction; /* 1 == output */
- ulong set; /* a 1 sets the bit, 0 leaves it alone */
- ulong clear; /* a 1 clears the bit, 0 leaves it alone */
- ulong rising; /* rising edge detect enable */
- ulong falling; /* falling edge detect enable */
- ulong edgestatus; /* writing a 1 bit clears */
- ulong altfunc; /* turn on alternate function for any set bits */
-};
-
-extern GPIOregs *gpioregs;
-
-/* extra general purpose I/O bits, output only */
-enum
-{
- EGPIO_prog_flash= 1<<0,
- EGPIO_pcmcia_reset= 1<<1,
- EGPIO_exppack_reset= 1<<2,
- EGPIO_codec_reset= 1<<3,
- EGPIO_exp_nvram_power= 1<<4,
- EGPIO_exp_full_power= 1<<5,
- EGPIO_lcd_3v= 1<<6,
- EGPIO_rs232_power= 1<<7,
- EGPIO_lcd_ic_power= 1<<8,
- EGPIO_ir_power= 1<<9,
- EGPIO_audio_power= 1<<10,
- EGPIO_audio_ic_power= 1<<11,
- EGPIO_audio_mute= 1<<12,
- EGPIO_fir= 1<<13, /* not set is sir */
- EGPIO_lcd_5v= 1<<14,
- EGPIO_lcd_9v= 1<<15,
-};
-extern ulong *egpioreg;
-
-/* Peripheral pin controller registers */
-typedef struct PPCregs PPCregs;
-struct PPCregs {
- ulong direction;
- ulong state;
- ulong assignment;
- ulong sleepdir;
- ulong flags;
-};
-extern PPCregs *ppcregs;
-
-/* Synchronous Serial Port controller registers */
-typedef struct SSPregs SSPregs;
-struct SSPregs {
- ulong control0;
- ulong control1;
- ulong dummy0;
- ulong data;
- ulong dummy1;
- ulong status;
-};
-extern SSPregs *sspregs;
-
-/* Multimedia Communications Port controller registers */
-typedef struct MCPregs MCPregs;
-struct MCPregs {
- ulong control0;
- ulong reserved0;
- ulong data0;
- ulong data1;
- ulong data2;
- ulong reserved1;
- ulong status;
- ulong reserved[11];
- ulong control1;
-};
-extern MCPregs *mcpregs;
-
-/*
- * memory configuration
- */
-enum
-{
- /* bit shifts for pcmcia access time counters */
- MECR_io0= 0,
- MECR_attr0= 5,
- MECR_mem0= 10,
- MECR_fast0= 11,
- MECR_io1= MECR_io0+16,
- MECR_attr1= MECR_attr0+16,
- MECR_mem1= MECR_mem0+16,
- MECR_fast1= MECR_fast0+16,
-};
-
-typedef struct MemConfRegs MemConfRegs;
-struct MemConfRegs
-{
- ulong mdcnfg; /* dram */
- ulong mdcas00; /* dram banks 0/1 */
- ulong mdcas01;
- ulong mdcas02;
- ulong msc0; /* static */
- ulong msc1;
- ulong mecr; /* pcmcia */
- ulong mdrefr; /* dram refresh */
- ulong mdcas20; /* dram banks 2/3 */
- ulong mdcas21;
- ulong mdcas22;
- ulong msc2; /* static */
- ulong smcnfg; /* SMROM config */
-};
-extern MemConfRegs *memconfregs;
-
-/*
- * power management
- */
-typedef struct PowerRegs PowerRegs;
-struct PowerRegs
-{
- ulong pmcr; /* Power manager control register */
- ulong pssr; /* Power manager sleep status register */
- ulong pspr; /* Power manager scratch pad register */
- ulong pwer; /* Power manager wakeup enable register */
- ulong pcfr; /* Power manager general configuration register */
- ulong ppcr; /* Power manager PPL configuration register */
- ulong pgsr; /* Power manager GPIO sleep state register */
- ulong posr; /* Power manager oscillator status register */
-};
-extern PowerRegs *powerregs;
--- a/os/boot/arm1110/l.s
+++ /dev/null
@@ -1,454 +1,0 @@
-#include "mem.h"
-
-/*
- * Entered here from Compaq's bootldr with MMU disabled.
- */
-TEXT _start(SB), $-4
- MOVW $setR12(SB), R12 /* load the SB */
-_main:
- /* SVC mode, interrupts disabled */
- MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
- MOVW R1, CPSR
-
- /* disable the MMU */
- MOVW $0x130, R1
- MCR CpMMU, 0, R1, C(CpControl), C(0x0)
-
- /* flush caches */
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
- /* drain prefetch */
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
-
- /* drain write buffer */
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
-
- MOVW $(MACHADDR+BY2PG), R13 /* stack */
- SUB $4, R13 /* link */
- BL main(SB)
- BL exit(SB)
- /* we shouldn't get here */
-_mainloop:
- B _mainloop
- BL _div(SB) /* hack to get _div etc loaded */
-
-/* flush tlb's */
-TEXT mmuinvalidate(SB), $-4
- MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
- RET
-
-/* flush tlb's */
-TEXT mmuinvalidateaddr(SB), $-4
- MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1
- RET
-
-/* write back and invalidate i and d caches */
-TEXT cacheflush(SB), $-4
- /* write back any dirty data */
- MOVW $0xe0000000,R0
- ADD $(8*1024),R0,R1
-_cfloop:
- MOVW.P 32(R0),R2
- CMP.S R0,R1
- BNE _cfloop
-
- /* drain write buffer and invalidate i&d cache contents */
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
-
- /* drain prefetch */
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- RET
-
-/* write back d cache */
-TEXT cachewb(SB), $-4
- /* write back any dirty data */
-_cachewb:
- MOVW $0xe0000000,R0
- ADD $(8*1024),R0,R1
-_cwbloop:
- MOVW.P 32(R0),R2
- CMP.S R0,R1
- BNE _cwbloop
-
- /* drain write buffer */
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
- RET
-
-/* write back a single cache line */
-TEXT cachewbaddr(SB), $-4
- BIC $31,R0
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
- B _wbflush
-
-/* write back a region of cache lines */
-TEXT cachewbregion(SB), $-4
- MOVW 4(FP),R1
- CMP.S $(4*1024),R1
- BGT _cachewb
- ADD R0,R1
- BIC $31,R0
-_cwbrloop:
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
- ADD $32,R0
- CMP.S R0,R1
- BGT _cwbrloop
- B _wbflush
-
-/* invalidate the dcache */
-TEXT dcacheinvalidate(SB), $-4
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x6)
- RET
-
-/* invalidate the icache */
-TEXT icacheinvalidate(SB), $-4
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x9)
- RET
-
-/* drain write buffer */
-TEXT wbflush(SB), $-4
-_wbflush:
- MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
- RET
-
-/* return cpu id */
-TEXT getcpuid(SB), $-4
- MRC CpMMU, 0, R0, C(CpCPUID), C(0x0)
- RET
-
-/* return fault status */
-TEXT getfsr(SB), $-4
- MRC CpMMU, 0, R0, C(CpFSR), C(0x0)
- RET
-
-/* return fault address */
-TEXT getfar(SB), $-4
- MRC CpMMU, 0, R0, C(CpFAR), C(0x0)
- RET
-
-/* return fault address */
-TEXT putfar(SB), $-4
- MRC CpMMU, 0, R0, C(CpFAR), C(0x0)
- RET
-
-/* set the translation table base */
-TEXT putttb(SB), $-4
- MCR CpMMU, 0, R0, C(CpTTB), C(0x0)
- RET
-
-/*
- * enable mmu, i and d caches
- */
-TEXT mmuenable(SB), $-4
- MRC CpMMU, 0, R0, C(CpControl), C(0x0)
- ORR $(CpCmmuena|CpCdcache|CpCicache|CpCwb), R0
- MCR CpMMU, 0, R0, C(CpControl), C(0x0)
- RET
-
-TEXT mmudisable(SB), $-4
- MRC CpMMU, 0, R0, C(CpControl), C(0x0)
- BIC $(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCvivec), R0
- MCR CpMMU, 0, R0, C(CpControl), C(0x0)
- RET
-
-/*
- * use exception vectors at 0xffff0000
- */
-TEXT mappedIvecEnable(SB), $-4
- MRC CpMMU, 0, R0, C(CpControl), C(0x0)
- ORR $(CpCvivec), R0
- MCR CpMMU, 0, R0, C(CpControl), C(0x0)
- RET
-TEXT mappedIvecDisable(SB), $-4
- MRC CpMMU, 0, R0, C(CpControl), C(0x0)
- BIC $(CpCvivec), R0
- MCR CpMMU, 0, R0, C(CpControl), C(0x0)
- RET
-
-/* set the translation table base */
-TEXT putdac(SB), $-4
- MCR CpMMU, 0, R0, C(CpDAC), C(0x0)
- RET
-
-/* set address translation pid */
-TEXT putpid(SB), $-4
- MCR CpMMU, 0, R0, C(CpPID), C(0x0)
- RET
-
-/*
- * set the stack value for the mode passed in R0
- */
-TEXT setr13(SB), $-4
- MOVW 4(FP), R1
-
- MOVW CPSR, R2
- BIC $PsrMask, R2, R3
- ORR R0, R3
- MOVW R3, CPSR
-
- MOVW R13, R0
- MOVW R1, R13
-
- MOVW R2, CPSR
- RET
-
-/*
- * exception vectors, copied by trapinit() to somewhere useful
- */
-
-TEXT vectors(SB), $-4
- MOVW 0x18(R15), R15 /* reset */
- MOVW 0x18(R15), R15 /* undefined */
- MOVW 0x18(R15), R15 /* SWI */
- MOVW 0x18(R15), R15 /* prefetch abort */
- MOVW 0x18(R15), R15 /* data abort */
- MOVW 0x18(R15), R15 /* reserved */
- MOVW 0x18(R15), R15 /* IRQ */
- MOVW 0x18(R15), R15 /* FIQ */
-
-TEXT vtable(SB), $-4
- WORD $_vsvc(SB) /* reset, in svc mode already */
- WORD $_vund(SB) /* undefined, switch to svc mode */
- WORD $_vsvc(SB) /* swi, in svc mode already */
- WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */
- WORD $_vdabt(SB) /* data abort, switch to svc mode */
- WORD $_vsvc(SB) /* reserved */
- WORD $_virq(SB) /* IRQ, switch to svc mode */
- WORD $_vfiq(SB) /* FIQ, switch to svc mode */
-
-TEXT _vrst(SB), $-4
- BL resettrap(SB)
-
-TEXT _vsvc(SB), $-4 /* SWI */
- MOVW.W R14, -4(R13) /* ureg->pc = interupted PC */
- MOVW SPSR, R14 /* ureg->psr = SPSR */
- MOVW.W R14, -4(R13) /* ... */
- MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */
- MOVW.W R14, -4(R13) /* ... */
- MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */
- MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
- MOVW R13, R0 /* first arg is pointer to ureg */
- SUB $8, R13 /* space for argument+link */
-
- BL syscall(SB)
-
- ADD $(8+4*15), R13 /* make r13 point to ureg->type */
- MOVW 8(R13), R14 /* restore link */
- MOVW 4(R13), R0 /* restore SPSR */
- MOVW R0, SPSR /* ... */
- MOVM.DB.S (R13), [R0-R14] /* restore registers */
- ADD $8, R13 /* pop past ureg->{type+psr} */
- RFE /* MOVM.IA.S.W (R13), [R15] */
-
-TEXT _vund(SB), $-4 /* undefined */
- MOVM.IA [R0-R4], (R13) /* free some working space */
- MOVW $PsrMund, R0
- B _vswitch
-
-TEXT _vpabt(SB), $-4 /* prefetch abort */
- MOVM.IA [R0-R4], (R13) /* free some working space */
- MOVW $PsrMabt, R0 /* r0 = type */
- B _vswitch
-
-TEXT _vdabt(SB), $-4 /* prefetch abort */
- MOVM.IA [R0-R4], (R13) /* free some working space */
- MOVW $(PsrMabt+1), R0 /* r0 = type */
- B _vswitch
-
-TEXT _virq(SB), $-4 /* IRQ */
- MOVM.IA [R0-R4], (R13) /* free some working space */
- MOVW $PsrMirq, R0 /* r0 = type */
- B _vswitch
-
- /*
- * come here with type in R0 and R13 pointing above saved [r0-r4]
- * and type in r0. we'll switch to SVC mode and then call trap.
- */
-_vswitch:
- MOVW SPSR, R1 /* save SPSR for ureg */
- MOVW R14, R2 /* save interrupted pc for ureg */
- MOVW R13, R3 /* save pointer to where the original [R0-R3] are */
-
- /* switch to svc mode */
- MOVW CPSR, R14
- BIC $PsrMask, R14
- ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
- MOVW R14, CPSR
-
- /* interupted code kernel or user? */
- AND.S $0xf, R1, R4
- BEQ _userexcep
-
- /* here for trap from SVC mode */
- MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
- MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
- MOVM.DB.W [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
- MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
- MOVW R13, R0 /* first arg is pointer to ureg */
- SUB $8, R13 /* space for argument+link (for debugger) */
- MOVW $0xdeaddead,R11 /* marker */
-
- BL trap(SB)
-
- ADD $(8+4*15), R13 /* make r13 point to ureg->type */
- MOVW 8(R13), R14 /* restore link */
- MOVW 4(R13), R0 /* restore SPSR */
- MOVW R0, SPSR /* ... */
- MOVM.DB (R13), [R0-R14] /* restore registers */
- ADD $8, R13 /* pop past ureg->{type+psr} */
- RFE /* MOVM.IA.S.W (R13), [R15] */
-
- /* here for trap from USER mode */
-_userexcep:
- MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
- MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
- MOVM.DB.W.S [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
- MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
- MOVW R13, R0 /* first arg is pointer to ureg */
- SUB $8, R13 /* space for argument+link (for debugger) */
-
- BL trap(SB)
-
- ADD $(8+4*15), R13 /* make r13 point to ureg->type */
- MOVW 8(R13), R14 /* restore link */
- MOVW 4(R13), R0 /* restore SPSR */
- MOVW R0, SPSR /* ... */
- MOVM.DB.S (R13), [R0-R14] /* restore registers */
- ADD $8, R13 /* pop past ureg->{type+psr} */
- RFE /* MOVM.IA.S.W (R13), [R15] */
-
-TEXT _vfiq(SB), $-4 /* FIQ */
- RFE /* FIQ is special, ignore it for now */
-
-/*
- * This is the first jump from kernel to user mode.
- * Fake a return from interrupt.
- *
- * Enter with R0 containing the user stack pointer.
- * UTZERO + 0x20 is always the entry point.
- *
- */
-TEXT touser(SB),$-4
- /* store the user stack pointer into the USR_r13 */
- MOVM.DB.W [R0], (R13)
- MOVM.S.IA.W (R13),[R13]
-
- /* set up a PSR for user level */
- MOVW $(PsrMusr), R0
- MOVW R0,SPSR
-
- /* save the PC on the stack */
- MOVW $(UTZERO+0x20), R0
- MOVM.DB.W [R0],(R13)
-
- /* return from interrupt */
- RFE /* MOVM.IA.S.W (R13), [R15] */
-
-/*
- * here to jump to a newly forked process
- */
-TEXT forkret(SB),$-4
- ADD $(4*15), R13 /* make r13 point to ureg->type */
- MOVW 8(R13), R14 /* restore link */
- MOVW 4(R13), R0 /* restore SPSR */
- MOVW R0, SPSR /* ... */
- MOVM.DB.S (R13), [R0-R14] /* restore registers */
- ADD $8, R13 /* pop past ureg->{type+psr} */
- RFE /* MOVM.IA.S.W (R13), [R15] */
-
-TEXT splhi(SB), $-4
- /* save caller pc in Mach */
- MOVW $(MACHADDR+0x04),R2
- MOVW R14,0(R2)
- /* turn off interrupts */
- MOVW CPSR, R0
- ORR $(PsrDfiq|PsrDirq), R0, R1
- MOVW R1, CPSR
- RET
-
-TEXT spllo(SB), $-4
- MOVW CPSR, R0
- BIC $(PsrDfiq|PsrDirq), R0, R1
- MOVW R1, CPSR
- RET
-
-TEXT splx(SB), $-4
- /* save caller pc in Mach */
- MOVW $(MACHADDR+0x04),R2
- MOVW R14,0(R2)
- /* reset interrupt level */
- MOVW R0, R1
- MOVW CPSR, R0
- MOVW R1, CPSR
- RET
-
-TEXT splxpc(SB), $-4 /* for iunlock */
- MOVW R0, R1
- MOVW CPSR, R0
- MOVW R1, CPSR
- RET
-
-TEXT spldone(SB), $0
- RET
-
-TEXT islo(SB), $-4
- MOVW CPSR, R0
- AND $(PsrDfiq|PsrDirq), R0
- EOR $(PsrDfiq|PsrDirq), R0
- RET
-
-TEXT cpsrr(SB), $-4
- MOVW CPSR, R0
- RET
-
-TEXT spsrr(SB), $-4
- MOVW SPSR, R0
- RET
-
-TEXT getcallerpc(SB), $-4
- MOVW 0(R13), R0
- RET
-
-TEXT tas(SB), $-4
- MOVW R0, R1
- MOVW $0xDEADDEAD, R2
- SWPW R2, (R1), R0
- RET
-
-TEXT setlabel(SB), $-4
- MOVW R13, 0(R0) /* sp */
- MOVW R14, 4(R0) /* pc */
- MOVW $0, R0
- RET
-
-TEXT gotolabel(SB), $-4
- MOVW 0(R0), R13 /* sp */
- MOVW 4(R0), R14 /* pc */
- MOVW $1, R0
- RET
-
-
-/* The first MCR instruction of this function needs to be on a cache-line
- * boundary; to make this happen, it will be copied (in trap.c).
- *
- * Doze puts the machine into idle mode. Any interrupt will get it out
- * at the next instruction (the RET, to be precise).
- */
-TEXT _doze(SB), $-4
- MOVW $UCDRAMZERO, R1
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- MCR CpPWR, 0, R0, C(CpTest), C(0x2), 2
- MOVW (R1), R0
- MCR CpPWR, 0, R0, C(CpTest), C(0x8), 2
- RET
--- a/os/boot/arm1110/lib.h
+++ /dev/null
@@ -1,143 +1,0 @@
-/*
- * functions (possibly) linked in, complete, from libc.
- */
-
-/*
- * mem routines
- */
-extern void *memccpy(void*, void*, int, long);
-extern void *memset(void*, int, long);
-extern int memcmp(void*, void*, long);
-extern void *memmove(void*, void*, long);
-extern void *memchr(void*, int, long);
-
-/*
- * string routines
- */
-extern char *strcat(char*, char*);
-extern char *strchr(char*, char);
-extern char *strrchr(char*, char);
-extern int strcmp(char*, char*);
-extern char *strcpy(char*, char*);
-extern char *strncat(char*, char*, long);
-extern char *strncpy(char*, char*, long);
-extern int strncmp(char*, char*, long);
-extern long strlen(char*);
-extern char* strstr(char*, char*);
-extern int atoi(char*);
-
-enum
-{
- UTFmax = 3, /* maximum bytes per rune */
- Runesync = 0x80, /* cannot represent part of a UTF sequence */
- Runeself = 0x80, /* rune and UTF sequences are the same (<) */
- Runeerror = 0x80, /* decoding error in UTF */
-};
-
-/*
- * rune routines
- */
-extern int runetochar(char*, Rune*);
-extern int chartorune(Rune*, char*);
-extern char* utfrune(char*, long);
-extern int utflen(char*);
-extern int runelen(long);
-
-extern int abs(int);
-
-/*
- * print routines
- */
-typedef struct Cconv Fconv;
-extern char* donprint(char*, char*, char*, void*);
-extern int sprint(char*, char*, ...);
-extern char* seprint(char*, char*, char*, ...);
-extern int snprint(char*, int, char*, ...);
-extern int print(char*, ...);
-
-/*
- * one-of-a-kind
- */
-extern char* cleanname(char*);
-extern ulong getcallerpc(void*);
-extern long strtol(char*, char**, int);
-extern ulong strtoul(char*, char**, int);
-extern vlong strtoll(char*, char**, int);
-extern uvlong strtoull(char*, char**, int);
-extern char etext[];
-extern char edata[];
-extern char end[];
-extern int getfields(char*, char**, int, int, char*);
-
-/*
- * Syscall data structures
- */
-#define MORDER 0x0003 /* mask for bits defining order of mounting */
-#define MREPL 0x0000 /* mount replaces object */
-#define MBEFORE 0x0001 /* mount goes before others in union directory */
-#define MAFTER 0x0002 /* mount goes after others in union directory */
-#define MCREATE 0x0004 /* permit creation in mounted directory */
-#define MCACHE 0x0010 /* cache some data */
-#define MMASK 0x001F /* all bits on */
-
-#define OREAD 0 /* open for read */
-#define OWRITE 1 /* write */
-#define ORDWR 2 /* read and write */
-#define OEXEC 3 /* execute, == read but check execute permission */
-#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
-#define OCEXEC 32 /* or'ed in, close on exec */
-#define ORCLOSE 64 /* or'ed in, remove on close */
-
-#define NCONT 0 /* continue after note */
-#define NDFLT 1 /* terminate after note */
-#define NSAVE 2 /* clear note but hold state */
-#define NRSTR 3 /* restore saved state */
-
-typedef struct Qid Qid;
-typedef struct Dir Dir;
-typedef struct Waitmsg Waitmsg;
-
-#define ERRLEN 64
-#define DIRLEN 116
-#define NAMELEN 28
-
-struct Qid
-{
- ulong path;
- ulong vers;
-};
-
-struct Dir
-{
- char name[NAMELEN];
- char uid[NAMELEN];
- char gid[NAMELEN];
- Qid qid;
- ulong mode;
- long atime;
- long mtime;
- vlong length;
- short type;
- short dev;
-};
-
-struct Waitmsg
-{
- char pid[12]; /* of loved one */
- char time[3*12]; /* of loved one and descendants */
- char msg[ERRLEN];
-};
-
-/*
- * locks
- */
-typedef
-struct Lock {
- int val;
-} Lock;
-
-extern int _tas(int*);
-
-extern void lock(Lock*);
-extern void unlock(Lock*);
-extern int canlock(Lock*);
--- a/os/boot/arm1110/map
+++ /dev/null
@@ -1,10 +1,0 @@
-defn acidmap()
-{
- local dfoffset;
-
- dfoffset = map()[1][3];
- map({"text", _start, etext, 0x20});
- map({"data", etext+1, edata, dfoffset});
- print("Set map for plan 9 kernel image\n");
- print("btext ", _start, " etext ", etext, "\n");
-}
--- a/os/boot/arm1110/mem.h
+++ /dev/null
@@ -1,215 +1,0 @@
-/*
- * Memory and machine-specific definitions. Used in C and assembler.
- */
-
-/*
- * Sizes
- */
-#define BI2BY 8 /* bits per byte */
-#define BI2WD 32 /* bits per word */
-#define BY2WD 4 /* bytes per word */
-#define BY2V 8 /* bytes per double word */
-#define BY2PG 4096 /* bytes per page */
-#define WD2PG (BY2PG/BY2WD) /* words per page */
-#define PGSHIFT 12 /* log(BY2PG) */
-#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
-#define PGROUND(s) ROUND(s, BY2PG)
-#define BLOCKALIGN 8
-
-#define MAXMACH 1 /* max # cpus system can run */
-
-/*
- * Time
- */
-#define HZ (20) /* clock frequency */
-#define MS2HZ (1000/HZ) /* millisec per clock tick */
-#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
-#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
-#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
-
-/*
- * Virtual addresses:
- *
- * We direct map all discovered DRAM and the area twixt 0xe0000000 and
- * 0xe8000000 used to provide zeros for cache flushing.
- *
- * Flash is mapped to 0xb0000000 and special registers are mapped
- * on demand to areas starting at 0xa0000000.
- *
- * The direct mapping is convenient but not necessary. It means
- * that we don't have to turn on the MMU till well into the
- * kernel. This can be changed by providing a mapping in l.s
- * before calling main.
- */
-#define UZERO 0 /* base of user address space */
-#define UTZERO (UZERO+BY2PG) /* first address in user text */
-#define KZERO 0xC0000000 /* base of kernel address space */
-#define KTZERO 0xC0008000 /* first address in kernel text */
-#define EMEMZERO 0x90000000 /* 256 meg for add on memory */
-#define EMEMTOP 0xA0000000 /* ... */
-#define REGZERO 0xA0000000 /* 128 meg for mapspecial regs */
-#define REGTOP 0xA8000000 /* ... */
-#define FLASHZERO 0xB0000000 /* 128 meg for flash */
-#define FLASHTOP 0xB8000000 /* ... */
-#define DRAMZERO 0xC0000000 /* 128 meg for dram */
-#define DRAMTOP 0xC8000000 /* ... */
-#define UCDRAMZERO 0xC8000000 /* 128 meg for dram (uncached/unbuffered) */
-#define UCDRAMTOP 0xD0000000 /* ... */
-#define NULLZERO 0xE0000000 /* 128 meg for cache flush zeroes */
-#define NULLTOP 0xE8000000 /* ... */
-#define USTKTOP 0x2000000 /* byte just beyond user stack */
-#define USTKSIZE (8*1024*1024) /* size of user stack */
-#define TSTKTOP (USTKTOP-USTKSIZE) /* end of new stack in sysexec */
-#define TSTKSIZ 100
-#define MACHADDR (KZERO+0x00001000)
-#define EVECTORS 0xFFFF0000 /* virt base of exception vectors */
-
-#define KSTACK (16*1024) /* Size of kernel stack */
-
-#define FLATESIZE (700*1024) /* maximum size of compressed image */
-
-/*
- * Offsets into flash
- */
-#define Flash_bootldr (FLASHZERO+0x0) /* boot loader */
-#define Flash_kernel (FLASHZERO+0x10000) /* boot kernel */
-#define Flash_tar (FLASHZERO+0x100000) /* tar file containing fs.sac */
-
-/*
- * virtual MMU
- */
-#define PTEMAPMEM (1024*1024)
-#define PTEPERTAB (PTEMAPMEM/BY2PG)
-#define SEGMAPSIZE 1984
-#define SSEGMAPSIZE 16
-#define PPN(x) ((x)&~(BY2PG-1))
-
-/*
- * SA1110 definitions
- */
-
-/*
- * memory physical addresses
- */
-#define PHYSFLASH0 0x00000000
-#define PHYSDRAM0 0xC0000000
-#define PHYSNULL0 0xE0000000
-
-/*
- * peripheral control module physical addresses
- */
-#define USBREGS 0x80000000 /* serial port 0 - USB */
-#define UART1REGS 0x80010000 /* serial port 1 - UART */
-#define GPCLKREGS 0x80020060 /* serial port 1 - general purpose clock */
-#define UART2REGS 0x80030000 /* serial port 2 - low speed IR */
-#define HSSPREGS 0x80040060 /* serial port 2 - high speed IR */
-#define UART3REGS 0x80050000 /* serial port 3 - RS232 UART */
-#define MCPREGS 0x80060000 /* serial port 4 - multimedia comm port */
-#define SSPREGS 0x80070060 /* serial port 4 - synchronous serial port */
-#define OSTIMERREGS 0x90000000 /* operating system timer registers */
-#define POWERREGS 0x90020000 /* power management */
-#define GPIOREGS 0x90040000 /* 28 general purpose IO pins */
-#define INTRREGS 0x90050000 /* interrupt registers */
-#define PPCREGS 0x90060000 /* peripheral pin controller */
-#define MEMCONFREGS 0xA0000000 /* memory configuration */
-#define LCDREGS 0xB0100000 /* display */
-
-/*
- * PCMCIA addresses
- */
-#define PHYSPCM0REGS 0x20000000
-#define PYHSPCM0ATTR 0x28000000
-#define PYHSPCM0MEM 0x2C000000
-#define PHYSPCM1REGS 0x30000000
-#define PYHSPCM1ATTR 0x38000000
-#define PYHSPCM1MEM 0x3C000000
-
-/*
- * Program Status Registers
- */
-#define PsrMusr 0x00000010 /* mode */
-#define PsrMfiq 0x00000011
-#define PsrMirq 0x00000012
-#define PsrMsvc 0x00000013
-#define PsrMabt 0x00000017
-#define PsrMund 0x0000001B
-#define PsrMask 0x0000001F
-
-#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
-#define PsrDirq 0x00000080 /* disable IRQ interrupts */
-
-#define PsrV 0x10000000 /* overflow */
-#define PsrC 0x20000000 /* carry/borrow/extend */
-#define PsrZ 0x40000000 /* zero */
-#define PsrN 0x80000000 /* negative/less than */
-
-/*
- * Coprocessors
- */
-#define CpMMU 15
-#define CpPWR 15
-
-/*
- * Internal MMU coprocessor registers
- */
-#define CpCPUID 0 /* R: */
-#define CpControl 1 /* R: */
-#define CpTTB 2 /* RW: translation table base */
-#define CpDAC 3 /* RW: domain access control */
-#define CpFSR 5 /* RW: fault status */
-#define CpFAR 6 /* RW: fault address */
-#define CpCacheFlush 7 /* W: cache flushing, wb draining*/
-#define CpTLBFlush 8 /* W: TLB flushing */
-#define CpRBFlush 9 /* W: Read Buffer ops */
-#define CpPID 13 /* RW: PID for virtual mapping */
-#define CpBpt 14 /* W: Breakpoint register */
-#define CpTest 15 /* W: Test, Clock and Idle Control */
-
-/*
- * CpControl
- */
-#define CpCmmuena 0x00000001 /* M: MMU enable */
-#define CpCalign 0x00000002 /* A: alignment fault enable */
-#define CpCdcache 0x00000004 /* C: data cache on */
-#define CpCwb 0x00000008 /* W: write buffer turned on */
-#define CpCi32 0x00000010 /* P: 32-bit program space */
-#define CpCd32 0x00000020 /* D: 32-bit data space */
-#define CpCbe 0x00000080 /* B: big-endian operation */
-#define CpCsystem 0x00000100 /* S: system permission */
-#define CpCrom 0x00000200 /* R: ROM permission */
-#define CpCicache 0x00001000 /* I: instruction cache on */
-#define CpCvivec 0x00002000 /* X: virtual interrupt vector adjust */
-
-/*
- * fault codes
- */
-#define FCterm 0x2 /* terminal */
-#define FCvec 0x0 /* vector */
-#define FCalignf 0x1 /* unaligned full word data access */
-#define FCalignh 0x3 /* unaligned half word data access */
-#define FCl1abort 0xc /* level 1 external abort on translation */
-#define FCl2abort 0xe /* level 2 external abort on translation */
-#define FCtransSec 0x5 /* section translation */
-#define FCtransPage 0x7 /* page translation */
-#define FCdomainSec 0x9 /* section domain */
-#define FCdomainPage 0x11 /* page domain */
-#define FCpermSec 0x9 /* section permissions */
-#define FCpermPage 0x11 /* page permissions */
-#define FCabortLFSec 0x4 /* external abort on linefetch for section */
-#define FCabortLFPage 0x6 /* external abort on linefetch for page */
-#define FCabortNLFSec 0x8 /* external abort on non-linefetch for section */
-#define FCabortNLFPage 0xa /* external abort on non-linefetch for page */
-
-/*
- * PTE bits used by fault.h. mmu.c translates them to real values.
- */
-#define PTEVALID (1<<0)
-#define PTERONLY 0 /* this is implied by the absence of PTEWRITE */
-#define PTEWRITE (1<<1)
-#define PTEUNCACHED (1<<2)
-#define PTEKERNEL (1<<3) /* no user access */
-
-/*
- * H3650 specific definitions
- */
-#define EGPIOREGS 0x49000000 /* Additional GPIO register */
--- a/os/boot/arm1110/mkfile
+++ /dev/null
@@ -1,86 +1,0 @@
-<../../../mkconfig
-objtype=arm
-SYSTARG=$OSTARG
-OBJTYPE=arm
-BIN=$ROOT/Inferno/$OBJTYPE
-LIBDIR=$ROOT/Inferno/$OBJTYPE/lib
-LIBDIRS=../libflate $ROOT/libkern
-LIBS=\
- libflate\
- libkern\
-
-LIBFILES=${LIBS:%=$LIBDIR/%.a}
-<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
-
-BIN=$ROOT/Inferno/$OBJTYPE
-
-TARG=\
- inflate\
-
-INFLATE=\
- il.$O\
- imain.$O\
-
-CORE=\
- uart.$O\
- inflate.$O\
- donprint.$O\
- print.$O\
-
-HFILES=\
- mem.h\
-
-CFLAGS=-FVw -I. -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include
-
-all:V: $TARG
-
-install:V: $BIN/$TARG
-
-$BIN/%: %
- cp $stem $BIN/$stem
-
-inflate: $INFLATE $CORE $LIBFILES
- $LD -o s$target -R4 -T0xC0200010 -l $prereq
- $LD -o _$target -H5 -R4 -T0xC0200010 -l $prereq
- dd -conv sync -ibs 20k -if _$target -of $target
-
-%.$O: %.s
- $AS $stem.s
-
-%.$O: %.c
- $CC $CFLAGS $stem.c
-
-%.$O: $HFILES
-
-clean:
- rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG _$TARG s$TARG
-
-
-# added to cause libflate to be made automatically:
-
-$ROOT/Inferno/$OBJTYPE/lib/lib%.a:Q: all-$SHELLTYPE
- #
-
-rc-lib%.a nt-lib%.a:VQ:
- echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
- @{builtin cd $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
-
-sh-lib%.a:VQ:
- echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
- (cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
-
-%-sh:QV:
- for i in $LIBDIRS
- do
- echo "(cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem)"
- (cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem)
- done
-
-%-rc %-nt:QV:
- for (i in $LIBDIRS)
- {
- echo '@{cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem}'
- @{cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem}
- }
-
-nuke:V: clean nuke-$SHELLTYPE
--- a/os/boot/arm1110/print.c
+++ /dev/null
@@ -1,56 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "fns.h"
-#include "dat.h"
-
-
-#define SIZE 1024
-
-int
-print(char *fmt, ...)
-{
- char buf[SIZE], *out;
- va_list arg;
-
- va_start(arg, fmt);
- out = donprint(buf, buf+SIZE, fmt, arg);
- va_end(arg);
- serialputs(buf, out-buf);
- return out-buf;
-}
-
-int
-sprint(char *buf, char *fmt, ...)
-{
- char *out;
- va_list arg;
-
- va_start(arg, fmt);
- out = donprint(buf, buf+SIZE, fmt, arg);
- va_end(arg);
- return out-buf;
-}
-
-int
-snprint(char *buf, int len, char *fmt, ...)
-{
- char *out;
- va_list arg;
-
- va_start(arg, fmt);
- out = donprint(buf, buf+len, fmt, arg);
- va_end(arg);
- return out-buf;
-}
-
-char*
-seprint(char *buf, char *e, char *fmt, ...)
-{
- char *out;
- va_list arg;
-
- va_start(arg, fmt);
- out = donprint(buf, e, fmt, arg);
- va_end(arg);
- return out;
-}
--- a/os/boot/arm1110/uart.c
+++ /dev/null
@@ -1,69 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-enum
-{
- /* ctl[0] bits */
- Parity= 1<<0,
- Even= 1<<1,
- Stop2= 1<<2,
- Bits8= 1<<3,
- SCE= 1<<4, /* synchronous clock enable */
- RCE= 1<<5, /* rx on falling edge of clock */
- TCE= 1<<6, /* tx on falling edge of clock */
-
- /* ctl[3] bits */
- Rena= 1<<0, /* receiver enable */
- Tena= 1<<1, /* transmitter enable */
- Break= 1<<2, /* force TXD3 low */
- Rintena= 1<<3, /* enable receive interrupt */
- Tintena= 1<<4, /* enable transmitter interrupt */
- Loopback= 1<<5, /* loop back data */
-
- /* data bits */
- DEparity= 1<<8, /* parity error */
- DEframe= 1<<9, /* framing error */
- DEoverrun= 1<<10, /* overrun error */
-
- /* status[0] bits */
- Tint= 1<<0, /* transmit fifo half full interrupt */
- Rint0= 1<<1, /* receiver fifo 1/3-2/3 full */
- Rint1= 1<<2, /* receiver fifo not empty and receiver idle */
- Breakstart= 1<<3,
- Breakend= 1<<4,
- Fifoerror= 1<<5, /* fifo error */
-
- /* status[1] bits */
- Tbusy= 1<<0, /* transmitting */
- Rnotempty= 1<<1, /* receive fifo not empty */
- Tnotfull= 1<<2, /* transmit fifo not full */
- ParityError= 1<<3,
- FrameError= 1<<4,
- Overrun= 1<<5,
-};
-
-Uartregs *uart3regs = UART3REGS;
-
-
-/*
- * for iprint, just write it
- */
-void
-serialputs(char *str, int n)
-{
- Uartregs *ur;
-
- ur = uart3regs;
- while(n-- > 0){
- /* wait for output ready */
- while((ur->status[1] & Tnotfull) == 0)
- ;
- ur->data = *str++;
- }
- while((ur->status[1] & Tbusy))
- ;
-}
--- a/os/boot/libflate/LICENCE
+++ /dev/null
@@ -1,237 +1,0 @@
-Lucent Public License Version 1.02
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
-LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
-PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-1. DEFINITIONS
-
-"Contribution" means:
-
- a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
- Program, and
- b. in the case of each Contributor,
-
- i. changes to the Program, and
- ii. additions to the Program;
-
- where such changes and/or additions to the Program were added to the
- Program by such Contributor itself or anyone acting on such
- Contributor's behalf, and the Contributor explicitly consents, in
- accordance with Section 3C, to characterization of the changes and/or
- additions as Contributions.
-
-"Contributor" means LUCENT and any other entity that has Contributed a
-Contribution to the Program.
-
-"Distributor" means a Recipient that distributes the Program,
-modifications to the Program, or any part thereof.
-
-"Licensed Patents" mean patent claims licensable by a Contributor
-which are necessarily infringed by the use or sale of its Contribution
-alone or when combined with the Program.
-
-"Original Program" means the original version of the software
-accompanying this Agreement as released by LUCENT, including source
-code, object code and documentation, if any.
-
-"Program" means the Original Program and Contributions or any part
-thereof
-
-"Recipient" means anyone who receives the Program under this
-Agreement, including all Contributors.
-
-2. GRANT OF RIGHTS
-
- a. Subject to the terms of this Agreement, each Contributor hereby
- grants Recipient a non-exclusive, worldwide, royalty-free copyright
- license to reproduce, prepare derivative works of, publicly display,
- publicly perform, distribute and sublicense the Contribution of such
- Contributor, if any, and such derivative works, in source code and
- object code form.
-
- b. Subject to the terms of this Agreement, each Contributor hereby
- grants Recipient a non-exclusive, worldwide, royalty-free patent
- license under Licensed Patents to make, use, sell, offer to sell,
- import and otherwise transfer the Contribution of such Contributor, if
- any, in source code and object code form. The patent license granted
- by a Contributor shall also apply to the combination of the
- Contribution of that Contributor and the Program if, at the time the
- Contribution is added by the Contributor, such addition of the
- Contribution causes such combination to be covered by the Licensed
- Patents. The patent license granted by a Contributor shall not apply
- to (i) any other combinations which include the Contribution, nor to
- (ii) Contributions of other Contributors. No hardware per se is
- licensed hereunder.
-
- c. Recipient understands that although each Contributor grants the
- licenses to its Contributions set forth herein, no assurances are
- provided by any Contributor that the Program does not infringe the
- patent or other intellectual property rights of any other entity. Each
- Contributor disclaims any liability to Recipient for claims brought by
- any other entity based on infringement of intellectual property rights
- or otherwise. As a condition to exercising the rights and licenses
- granted hereunder, each Recipient hereby assumes sole responsibility
- to secure any other intellectual property rights needed, if any. For
- example, if a third party patent license is required to allow
- Recipient to distribute the Program, it is Recipient's responsibility
- to acquire that license before distributing the Program.
-
- d. Each Contributor represents that to its knowledge it has sufficient
- copyright rights in its Contribution, if any, to grant the copyright
- license set forth in this Agreement.
-
-3. REQUIREMENTS
-
-A. Distributor may choose to distribute the Program in any form under
-this Agreement or under its own license agreement, provided that:
-
- a. it complies with the terms and conditions of this Agreement;
-
- b. if the Program is distributed in source code or other tangible
- form, a copy of this Agreement or Distributor's own license agreement
- is included with each copy of the Program; and
-
- c. if distributed under Distributor's own license agreement, such
- license agreement:
-
- i. effectively disclaims on behalf of all Contributors all warranties
- and conditions, express and implied, including warranties or
- conditions of title and non-infringement, and implied warranties or
- conditions of merchantability and fitness for a particular purpose;
- ii. effectively excludes on behalf of all Contributors all liability
- for damages, including direct, indirect, special, incidental and
- consequential damages, such as lost profits; and
- iii. states that any provisions which differ from this Agreement are
- offered by that Contributor alone and not by any other party.
-
-B. Each Distributor must include the following in a conspicuous
- location in the Program:
-
- Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
- Reserved.
-
-C. In addition, each Contributor must identify itself as the
-originator of its Contribution in a manner that reasonably allows
-subsequent Recipients to identify the originator of the Contribution.
-Also, each Contributor must agree that the additions and/or changes
-are intended to be a Contribution. Once a Contribution is contributed,
-it may not thereafter be revoked.
-
-4. COMMERCIAL DISTRIBUTION
-
-Commercial distributors of software may accept certain
-responsibilities with respect to end users, business partners and the
-like. While this license is intended to facilitate the commercial use
-of the Program, the Distributor who includes the Program in a
-commercial product offering should do so in a manner which does not
-create potential liability for Contributors. Therefore, if a
-Distributor includes the Program in a commercial product offering,
-such Distributor ("Commercial Distributor") hereby agrees to defend
-and indemnify every Contributor ("Indemnified Contributor") against
-any losses, damages and costs (collectively"Losses") arising from
-claims, lawsuits and other legal actions brought by a third party
-against the Indemnified Contributor to the extent caused by the acts
-or omissions of such Commercial Distributor in connection with its
-distribution of the Program in a commercial product offering. The
-obligations in this section do not apply to any claims or Losses
-relating to any actual or alleged intellectual property infringement.
-In order to qualify, an Indemnified Contributor must: a) promptly
-notify the Commercial Distributor in writing of such claim, and b)
-allow the Commercial Distributor to control, and cooperate with the
-Commercial Distributor in, the defense and any related settlement
-negotiations. The Indemnified Contributor may participate in any such
-claim at its own expense.
-
-For example, a Distributor might include the Program in a commercial
-product offering, Product X. That Distributor is then a Commercial
-Distributor. If that Commercial Distributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Distributor's responsibility
-alone. Under this section, the Commercial Distributor would have to
-defend claims against the Contributors related to those performance
-claims and warranties, and if a court requires any Contributor to pay
-any damages as a result, the Commercial Distributor must pay those
-damages.
-
-5. NO WARRANTY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
-PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
-WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
-OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
-responsible for determining the appropriateness of using and
-distributing the Program and assumes all risks associated with its
-exercise of rights under this Agreement, including but not limited to
-the risks and costs of program errors, compliance with applicable
-laws, damage to or loss of data, programs or equipment, and
-unavailability or interruption of operations.
-
-6. DISCLAIMER OF LIABILITY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-7. EXPORT CONTROL
-
-Recipient agrees that Recipient alone is responsible for compliance
-with the United States export administration regulations (and the
-export control laws and regulation of any other countries).
-
-8. GENERAL
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further
-action by the parties hereto, such provision shall be reformed to the
-minimum extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against a Contributor with
-respect to a patent applicable to software (including a cross-claim or
-counterclaim in a lawsuit), then any patent licenses granted by that
-Contributor to such Recipient under this Agreement shall terminate as
-of the date such litigation is filed. In addition, if Recipient
-institutes patent litigation against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it
-fails to comply with any of the material terms or conditions of this
-Agreement and does not cure such failure in a reasonable period of
-time after becoming aware of such noncompliance. If all Recipient's
-rights under this Agreement terminate, Recipient agrees to cease use
-and distribution of the Program as soon as reasonably practicable.
-However, Recipient's obligations under this Agreement and any licenses
-granted by Recipient relating to the Program shall continue and
-survive.
-
-LUCENT may publish new versions (including revisions) of this
-Agreement from time to time. Each new version of the Agreement will be
-given a distinguishing version number. The Program (including
-Contributions) may always be distributed subject to the version of the
-Agreement under which it was received. In addition, after a new
-version of the Agreement is published, Contributor may elect to
-distribute the Program (including its Contributions) under the new
-version. No one other than LUCENT has the right to modify this
-Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
-Recipient receives no rights or licenses to the intellectual property
-of any Contributor under this Agreement, whether expressly, by
-implication, estoppel or otherwise. All rights in the Program not
-expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and
-the intellectual property laws of the United States of America. No
-party to this Agreement will bring a legal action under this Agreement
-more than one year after the cause of action arose. Each party waives
-its rights to a jury trial in any resulting litigation.
-
--- a/os/boot/libflate/NOTICE
+++ /dev/null
@@ -1,8 +1,0 @@
-Copyright © 2002 Lucent Technologies Inc.
-All Rights Reserved
-
-This software was originally developed for Plan 9.
-It is provided under the terms of the Lucent Public License, Version 1.02.
-
-Trivial modifications have been made to make it compile for Inferno.
- Vita Nuova Holdings Limited.
--- a/os/boot/libflate/adler.c
+++ /dev/null
@@ -1,71 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-enum
-{
- ADLERITERS = 5552, /* max iters before can overflow 32 bits */
- ADLERBASE = 65521 /* largest prime smaller than 65536 */
-};
-
-ulong
-adler32(ulong adler, void *vbuf, int n)
-{
- ulong s1, s2;
- uchar *buf, *ebuf;
- int m;
-
- buf = vbuf;
- s1 = adler & 0xffff;
- s2 = (adler >> 16) & 0xffff;
- for(; n >= 16; n -= m){
- m = n;
- if(m > ADLERITERS)
- m = ADLERITERS;
- m &= ~15;
- for(ebuf = buf + m; buf < ebuf; buf += 16){
- s1 += buf[0];
- s2 += s1;
- s1 += buf[1];
- s2 += s1;
- s1 += buf[2];
- s2 += s1;
- s1 += buf[3];
- s2 += s1;
- s1 += buf[4];
- s2 += s1;
- s1 += buf[5];
- s2 += s1;
- s1 += buf[6];
- s2 += s1;
- s1 += buf[7];
- s2 += s1;
- s1 += buf[8];
- s2 += s1;
- s1 += buf[9];
- s2 += s1;
- s1 += buf[10];
- s2 += s1;
- s1 += buf[11];
- s2 += s1;
- s1 += buf[12];
- s2 += s1;
- s1 += buf[13];
- s2 += s1;
- s1 += buf[14];
- s2 += s1;
- s1 += buf[15];
- s2 += s1;
- }
- s1 %= ADLERBASE;
- s2 %= ADLERBASE;
- }
- if(n){
- for(ebuf = buf + n; buf < ebuf; buf++){
- s1 += buf[0];
- s2 += s1;
- }
- s1 %= ADLERBASE;
- s2 %= ADLERBASE;
- }
- return (s2 << 16) + s1;
-}
--- a/os/boot/libflate/crc.c
+++ /dev/null
@@ -1,39 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-ulong*
-mkcrctab(ulong poly)
-{
- ulong *crctab;
- ulong crc;
- int i, j;
-
- crctab = malloc(256 * sizeof(ulong));
- if(crctab == nil)
- return nil;
-
- for(i = 0; i < 256; i++){
- crc = i;
- for(j = 0; j < 8; j++){
- if(crc & 1)
- crc = (crc >> 1) ^ poly;
- else
- crc >>= 1;
- }
- crctab[i] = crc;
- }
- return crctab;
-}
-
-ulong
-blockcrc(ulong *crctab, ulong crc, void *vbuf, int n)
-{
- uchar *buf, *ebuf;
-
- crc ^= 0xffffffff;
- buf = vbuf;
- ebuf = buf + n;
- while(buf < ebuf)
- crc = crctab[(crc & 0xff) ^ *buf++] ^ (crc >> 8);
- return crc ^ 0xffffffff;
-}
--- a/os/boot/libflate/deflate.c
+++ /dev/null
@@ -1,1358 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-typedef struct Chain Chain;
-typedef struct Chains Chains;
-typedef struct Dyncode Dyncode;
-typedef struct Huff Huff;
-typedef struct LZblock LZblock;
-typedef struct LZstate LZstate;
-
-enum
-{
- /*
- * deflate format paramaters
- */
- DeflateUnc = 0, /* uncompressed block */
- DeflateFix = 1, /* fixed huffman codes */
- DeflateDyn = 2, /* dynamic huffman codes */
-
- DeflateEob = 256, /* end of block code in lit/len book */
- DeflateMaxBlock = 64*1024-1, /* maximum size of uncompressed block */
-
- DeflateMaxExp = 10, /* maximum expansion for a block */
-
- LenStart = 257, /* start of length codes in litlen */
- Nlitlen = 288, /* number of litlen codes */
- Noff = 30, /* number of offset codes */
- Nclen = 19, /* number of codelen codes */
-
- MaxOff = 32*1024,
- MinMatch = 3, /* shortest match possible */
- MaxMatch = 258, /* longest match possible */
-
- /*
- * huffman code paramaters
- */
- MaxLeaf = Nlitlen,
- MaxHuffBits = 16, /* max bits in a huffman code */
- ChainMem = 2 * (MaxHuffBits - 1) * MaxHuffBits,
-
- /*
- * coding of the lz parse
- */
- LenFlag = 1 << 3,
- LenShift = 4, /* leaves enough space for MinMatchMaxOff */
- MaxLitRun = LenFlag - 1,
-
- /*
- * internal lz paramaters
- */
- DeflateOut = 4096, /* output buffer size */
- BlockSize = 8192, /* attempted input read quanta */
- DeflateBlock = DeflateMaxBlock & ~(BlockSize - 1),
- MinMatchMaxOff = 4096, /* max profitable offset for small match;
- * assumes 8 bits for len, 5+10 for offset
- * DONT CHANGE WITHOUT CHANGING LZPARSE CONSTANTS
- */
- HistSlop = 512, /* must be at lead MaxMatch */
- HistBlock = 64*1024,
- HistSize = HistBlock + HistSlop,
-
- HashLog = 13,
- HashSize = 1<<HashLog,
-
- MaxOffCode = 256, /* biggest offset looked up in direct table */
-
- EstLitBits = 8,
- EstLenBits = 4,
- EstOffBits = 5,
-};
-
-/*
- * knuth vol. 3 multiplicative hashing
- * each byte x chosen according to rules
- * 1/4 < x < 3/10, 1/3 x < < 3/7, 4/7 < x < 2/3, 7/10 < x < 3/4
- * with reasonable spread between the bytes & their complements
- *
- * the 3 byte value appears to be as almost good as the 4 byte value,
- * and might be faster on some machines
- */
-/*
-#define hashit(c) (((ulong)(c) * 0x6b43a9) >> (24 - HashLog))
-*/
-#define hashit(c) ((((ulong)(c) & 0xffffff) * 0x6b43a9b5) >> (32 - HashLog))
-
-/*
- * lempel-ziv style compression state
- */
-struct LZstate
-{
- uchar hist[HistSize];
- ulong pos; /* current location in history buffer */
- ulong avail; /* data available after pos */
- int eof;
- ushort hash[HashSize]; /* hash chains */
- ushort nexts[MaxOff];
- int now; /* pos in hash chains */
- int dot; /* dawn of time in history */
- int prevlen; /* lazy matching state */
- int prevoff;
- int maxcheck; /* compressor tuning */
-
- uchar obuf[DeflateOut];
- uchar *out; /* current position in the output buffer */
- uchar *eout;
- ulong bits; /* bit shift register */
- int nbits;
- int rbad; /* got an error reading the buffer */
- int wbad; /* got an error writing the buffer */
- int (*w)(void*, void*, int);
- void *wr;
-
- ulong totr; /* total input size */
- ulong totw; /* total output size */
- int debug;
-};
-
-struct LZblock
-{
- ushort parse[DeflateMaxBlock / 2 + 1];
- int lastv; /* value being constucted for parse */
- ulong litlencount[Nlitlen];
- ulong offcount[Noff];
- ushort *eparse; /* limit for parse table */
- int bytes; /* consumed from the input */
- int excost; /* cost of encoding extra len & off bits */
-};
-
-/*
- * huffman code table
- */
-struct Huff
-{
- short bits; /* length of the code */
- ushort encode; /* the code */
-};
-
-/*
- * encoding of dynamic huffman trees
- */
-struct Dyncode
-{
- int nlit;
- int noff;
- int nclen;
- int ncode;
- Huff codetab[Nclen];
- uchar codes[Nlitlen+Noff];
- uchar codeaux[Nlitlen+Noff];
-};
-
-static int deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int));
-static int lzcomp(LZstate*, LZblock*, uchar*, ushort*, int finish);
-static void wrblock(LZstate*, int, ushort*, ushort*, Huff*, Huff*);
-static int bitcost(Huff*, ulong*, int);
-static int huffcodes(Dyncode*, Huff*, Huff*);
-static void wrdyncode(LZstate*, Dyncode*);
-static void lzput(LZstate*, ulong bits, int nbits);
-static void lzflushbits(LZstate*);
-static void lzflush(LZstate *lz);
-static void lzwrite(LZstate *lz, void *buf, int n);
-
-static int hufftabinit(Huff*, int, ulong*, int);
-static int mkgzprecode(Huff*, ulong *, int, int);
-
-static int mkprecode(Huff*, ulong *, int, int, ulong*);
-static void nextchain(Chains*, int);
-static void leafsort(ulong*, ushort*, int, int);
-
-/* conversion from len to code word */
-static int lencode[MaxMatch];
-
-/*
- * conversion from off to code word
- * off <= MaxOffCode ? offcode[off] : bigoffcode[off >> 7]
-*/
-static int offcode[MaxOffCode];
-static int bigoffcode[256];
-
-/* litlen code words LenStart-285 extra bits */
-static int litlenbase[Nlitlen-LenStart];
-static int litlenextra[Nlitlen-LenStart] =
-{
-/* 257 */ 0, 0, 0,
-/* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
-/* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
-/* 280 */ 4, 5, 5, 5, 5, 0, 0, 0
-};
-
-/* offset code word extra bits */
-static int offbase[Noff];
-static int offextra[] =
-{
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
- 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
- 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
- 0, 0,
-};
-
-/* order code lengths */
-static int clenorder[Nclen] =
-{
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
-};
-
-/* static huffman tables */
-static Huff litlentab[Nlitlen];
-static Huff offtab[Noff];
-static Huff hofftab[Noff];
-
-/* bit reversal for brain dead endian swap in huffman codes */
-static uchar revtab[256];
-static ulong nlits;
-static ulong nmatches;
-
-int
-deflateinit(void)
-{
- ulong bitcount[MaxHuffBits];
- int i, j, ci, n;
-
- /* byte reverse table */
- for(i=0; i<256; i++)
- for(j=0; j<8; j++)
- if(i & (1<<j))
- revtab[i] |= 0x80 >> j;
-
- /* static Litlen bit lengths */
- for(i=0; i<144; i++)
- litlentab[i].bits = 8;
- for(i=144; i<256; i++)
- litlentab[i].bits = 9;
- for(i=256; i<280; i++)
- litlentab[i].bits = 7;
- for(i=280; i<Nlitlen; i++)
- litlentab[i].bits = 8;
-
- memset(bitcount, 0, sizeof(bitcount));
- bitcount[8] += 144 - 0;
- bitcount[9] += 256 - 144;
- bitcount[7] += 280 - 256;
- bitcount[8] += Nlitlen - 280;
-
- if(!hufftabinit(litlentab, Nlitlen, bitcount, 9))
- return FlateInternal;
-
- /* static offset bit lengths */
- for(i = 0; i < Noff; i++)
- offtab[i].bits = 5;
-
- memset(bitcount, 0, sizeof(bitcount));
- bitcount[5] = Noff;
-
- if(!hufftabinit(offtab, Noff, bitcount, 5))
- return FlateInternal;
-
- bitcount[0] = 0;
- bitcount[1] = 0;
- if(!mkgzprecode(hofftab, bitcount, 2, MaxHuffBits))
- return FlateInternal;
-
- /* conversion tables for lens & offs to codes */
- ci = 0;
- for(i = LenStart; i < 286; i++){
- n = ci + (1 << litlenextra[i - LenStart]);
- litlenbase[i - LenStart] = ci;
- for(; ci < n; ci++)
- lencode[ci] = i;
- }
- /* patch up special case for len MaxMatch */
- lencode[MaxMatch-MinMatch] = 285;
- litlenbase[285-LenStart] = MaxMatch-MinMatch;
-
- ci = 0;
- for(i = 0; i < 16; i++){
- n = ci + (1 << offextra[i]);
- offbase[i] = ci;
- for(; ci < n; ci++)
- offcode[ci] = i;
- }
-
- ci = ci >> 7;
- for(; i < 30; i++){
- n = ci + (1 << (offextra[i] - 7));
- offbase[i] = ci << 7;
- for(; ci < n; ci++)
- bigoffcode[ci] = i;
- }
- return FlateOk;
-}
-
-static void
-deflatereset(LZstate *lz, int level, int debug)
-{
- memset(lz->nexts, 0, sizeof lz->nexts);
- memset(lz->hash, 0, sizeof lz->hash);
- lz->totr = 0;
- lz->totw = 0;
- lz->pos = 0;
- lz->avail = 0;
- lz->out = lz->obuf;
- lz->eout = &lz->obuf[DeflateOut];
- lz->prevlen = MinMatch - 1;
- lz->prevoff = 0;
- lz->now = MaxOff + 1;
- lz->dot = lz->now;
- lz->bits = 0;
- lz->nbits = 0;
- lz->maxcheck = (1 << level);
- lz->maxcheck -= lz->maxcheck >> 2;
- if(lz->maxcheck < 2)
- lz->maxcheck = 2;
- else if(lz->maxcheck > 1024)
- lz->maxcheck = 1024;
-
- lz->debug = debug;
-}
-
-int
-deflate(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
-{
- LZstate *lz;
- LZblock *lzb;
- int ok;
-
- lz = malloc(sizeof *lz + sizeof *lzb);
- if(lz == nil)
- return FlateNoMem;
- lzb = (LZblock*)&lz[1];
-
- deflatereset(lz, level, debug);
- lz->w = w;
- lz->wr = wr;
- lz->wbad = 0;
- lz->rbad = 0;
- lz->eof = 0;
- ok = FlateOk;
- while(!lz->eof || lz->avail){
- ok = deflateb(lz, lzb, rr, r);
- if(ok != FlateOk)
- break;
- }
- if(ok == FlateOk && lz->rbad)
- ok = FlateInputFail;
- if(ok == FlateOk && lz->wbad)
- ok = FlateOutputFail;
- free(lz);
- return ok;
-}
-
-static int
-deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int))
-{
- Dyncode dyncode, hdyncode;
- Huff dlitlentab[Nlitlen], dofftab[Noff], hlitlentab[Nlitlen];
- ulong litcount[Nlitlen];
- long nunc, ndyn, nfix, nhuff;
- uchar *slop, *hslop;
- ulong ep;
- int i, n, m, mm, nslop;
-
- memset(lzb->litlencount, 0, sizeof lzb->litlencount);
- memset(lzb->offcount, 0, sizeof lzb->offcount);
- lzb->litlencount[DeflateEob]++;
-
- lzb->bytes = 0;
- lzb->eparse = lzb->parse;
- lzb->lastv = 0;
- lzb->excost = 0;
-
- slop = &lz->hist[lz->pos];
- n = lz->avail;
- while(n < DeflateBlock && (!lz->eof || lz->avail)){
- /*
- * fill the buffer as much as possible,
- * while leaving room for MaxOff history behind lz->pos,
- * and not reading more than we can handle.
- *
- * make sure we read at least HistSlop bytes.
- */
- if(!lz->eof){
- ep = lz->pos + lz->avail;
- if(ep >= HistBlock)
- ep -= HistBlock;
- m = HistBlock - MaxOff - lz->avail;
- if(m > HistBlock - n)
- m = HistBlock - n;
- if(m > (HistBlock + HistSlop) - ep)
- m = (HistBlock + HistSlop) - ep;
- if(m & ~(BlockSize - 1))
- m &= ~(BlockSize - 1);
-
- /*
- * be nice to the caller: stop reads that are too small.
- * can only get here when we've already filled the buffer some
- */
- if(m < HistSlop){
- if(!m || !lzb->bytes)
- return FlateInternal;
- break;
- }
-
- mm = (*r)(rr, &lz->hist[ep], m);
- if(mm > 0){
- /*
- * wrap data to end if we're read it from the beginning
- * this way, we don't have to wrap searches.
- *
- * wrap reads past the end to the beginning.
- * this way, we can guarantee minimum size reads.
- */
- if(ep < HistSlop)
- memmove(&lz->hist[ep + HistBlock], &lz->hist[ep], HistSlop - ep);
- else if(ep + mm > HistBlock)
- memmove(&lz->hist[0], &lz->hist[HistBlock], ep + mm - HistBlock);
-
- lz->totr += mm;
- n += mm;
- lz->avail += mm;
- }else{
- if(mm < 0)
- lz->rbad = 1;
- lz->eof = 1;
- }
- }
- ep = lz->pos + lz->avail;
- if(ep > HistSize)
- ep = HistSize;
- if(lzb->bytes + ep - lz->pos > DeflateMaxBlock)
- ep = lz->pos + DeflateMaxBlock - lzb->bytes;
- m = lzcomp(lz, lzb, &lz->hist[ep], lzb->eparse, lz->eof);
- lzb->bytes += m;
- lz->pos = (lz->pos + m) & (HistBlock - 1);
- lz->avail -= m;
- }
- if(lzb->lastv)
- *lzb->eparse++ = lzb->lastv;
- if(lzb->eparse > lzb->parse + nelem(lzb->parse))
- return FlateInternal;
- nunc = lzb->bytes;
-
- if(!mkgzprecode(dlitlentab, lzb->litlencount, Nlitlen, MaxHuffBits)
- || !mkgzprecode(dofftab, lzb->offcount, Noff, MaxHuffBits))
- return FlateInternal;
-
- ndyn = huffcodes(&dyncode, dlitlentab, dofftab);
- if(ndyn < 0)
- return FlateInternal;
- ndyn += bitcost(dlitlentab, lzb->litlencount, Nlitlen)
- + bitcost(dofftab, lzb->offcount, Noff)
- + lzb->excost;
-
- memset(litcount, 0, sizeof litcount);
-
- nslop = nunc;
- if(nslop > &lz->hist[HistSize] - slop)
- nslop = &lz->hist[HistSize] - slop;
-
- for(i = 0; i < nslop; i++)
- litcount[slop[i]]++;
- hslop = &lz->hist[HistSlop - nslop];
- for(; i < nunc; i++)
- litcount[hslop[i]]++;
- litcount[DeflateEob]++;
-
- if(!mkgzprecode(hlitlentab, litcount, Nlitlen, MaxHuffBits))
- return FlateInternal;
- nhuff = huffcodes(&hdyncode, hlitlentab, hofftab);
- if(nhuff < 0)
- return FlateInternal;
- nhuff += bitcost(hlitlentab, litcount, Nlitlen);
-
- nfix = bitcost(litlentab, lzb->litlencount, Nlitlen)
- + bitcost(offtab, lzb->offcount, Noff)
- + lzb->excost;
-
- lzput(lz, lz->eof && !lz->avail, 1);
-
- if(lz->debug){
- fprint(2, "block: bytes=%lud entries=%ld extra bits=%d\n\tuncompressed=%lud fixed=%lud dynamic=%lud huffman=%lud\n",
- nunc, lzb->eparse - lzb->parse, lzb->excost, (nunc + 4) * 8, nfix, ndyn, nhuff);
- fprint(2, "\tnlit=%lud matches=%lud eof=%d\n", nlits, nmatches, lz->eof && !lz->avail);
- }
-
- if((nunc + 4) * 8 < ndyn && (nunc + 4) * 8 < nfix && (nunc + 4) * 8 < nhuff){
- lzput(lz, DeflateUnc, 2);
- lzflushbits(lz);
-
- lzput(lz, nunc & 0xff, 8);
- lzput(lz, (nunc >> 8) & 0xff, 8);
- lzput(lz, ~nunc & 0xff, 8);
- lzput(lz, (~nunc >> 8) & 0xff, 8);
- lzflush(lz);
-
- lzwrite(lz, slop, nslop);
- lzwrite(lz, &lz->hist[HistSlop], nunc - nslop);
- }else if(ndyn < nfix && ndyn < nhuff){
- lzput(lz, DeflateDyn, 2);
-
- wrdyncode(lz, &dyncode);
- wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, dlitlentab, dofftab);
- lzput(lz, dlitlentab[DeflateEob].encode, dlitlentab[DeflateEob].bits);
- }else if(nhuff < nfix){
- lzput(lz, DeflateDyn, 2);
-
- wrdyncode(lz, &hdyncode);
-
- m = 0;
- for(i = nunc; i > MaxLitRun; i -= MaxLitRun)
- lzb->parse[m++] = MaxLitRun;
- lzb->parse[m++] = i;
-
- wrblock(lz, slop - lz->hist, lzb->parse, lzb->parse + m, hlitlentab, hofftab);
- lzput(lz, hlitlentab[DeflateEob].encode, hlitlentab[DeflateEob].bits);
- }else{
- lzput(lz, DeflateFix, 2);
-
- wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, litlentab, offtab);
- lzput(lz, litlentab[DeflateEob].encode, litlentab[DeflateEob].bits);
- }
-
- if(lz->eof && !lz->avail){
- lzflushbits(lz);
- lzflush(lz);
- }
- return FlateOk;
-}
-
-static void
-lzwrite(LZstate *lz, void *buf, int n)
-{
- int nw;
-
- if(n && lz->w){
- nw = (*lz->w)(lz->wr, buf, n);
- if(nw != n){
- lz->w = nil;
- lz->wbad = 1;
- }else
- lz->totw += n;
- }
-}
-
-static void
-lzflush(LZstate *lz)
-{
- lzwrite(lz, lz->obuf, lz->out - lz->obuf);
- lz->out = lz->obuf;
-}
-
-static void
-lzput(LZstate *lz, ulong bits, int nbits)
-{
- bits = (bits << lz->nbits) | lz->bits;
- for(nbits += lz->nbits; nbits >= 8; nbits -= 8){
- *lz->out++ = bits;
- if(lz->out == lz->eout)
- lzflush(lz);
- bits >>= 8;
- }
- lz->bits = bits;
- lz->nbits = nbits;
-}
-
-static void
-lzflushbits(LZstate *lz)
-{
- if(lz->nbits)
- lzput(lz, 0, 8 - (lz->nbits & 7));
-}
-
-/*
- * write out a block of n samples,
- * given lz encoding and counts for huffman tables
- */
-static void
-wrblock(LZstate *out, int litoff, ushort *soff, ushort *eoff, Huff *litlentab, Huff *offtab)
-{
- ushort *off;
- int i, run, offset, lit, len, c;
-
- if(out->debug > 2){
- for(off = soff; off < eoff; ){
- offset = *off++;
- run = offset & MaxLitRun;
- if(run){
- for(i = 0; i < run; i++){
- lit = out->hist[litoff & (HistBlock - 1)];
- litoff++;
- fprint(2, "\tlit %.2ux %c\n", lit, lit);
- }
- if(!(offset & LenFlag))
- continue;
- len = offset >> LenShift;
- offset = *off++;
- }else if(offset & LenFlag){
- len = offset >> LenShift;
- offset = *off++;
- }else{
- len = 0;
- offset >>= LenShift;
- }
- litoff += len + MinMatch;
- fprint(2, "\t<%d, %d>\n", offset + 1, len + MinMatch);
- }
- }
-
- for(off = soff; off < eoff; ){
- offset = *off++;
- run = offset & MaxLitRun;
- if(run){
- for(i = 0; i < run; i++){
- lit = out->hist[litoff & (HistBlock - 1)];
- litoff++;
- lzput(out, litlentab[lit].encode, litlentab[lit].bits);
- }
- if(!(offset & LenFlag))
- continue;
- len = offset >> LenShift;
- offset = *off++;
- }else if(offset & LenFlag){
- len = offset >> LenShift;
- offset = *off++;
- }else{
- len = 0;
- offset >>= LenShift;
- }
- litoff += len + MinMatch;
- c = lencode[len];
- lzput(out, litlentab[c].encode, litlentab[c].bits);
- c -= LenStart;
- if(litlenextra[c])
- lzput(out, len - litlenbase[c], litlenextra[c]);
-
- if(offset < MaxOffCode)
- c = offcode[offset];
- else
- c = bigoffcode[offset >> 7];
- lzput(out, offtab[c].encode, offtab[c].bits);
- if(offextra[c])
- lzput(out, offset - offbase[c], offextra[c]);
- }
-}
-
-/*
- * look for the longest, closest string which matches
- * the next prefix. the clever part here is looking for
- * a string 1 longer than the previous best match.
- *
- * follows the recommendation of limiting number of chains
- * which are checked. this appears to be the best heuristic.
- */
-static int
-lzmatch(int now, int then, uchar *p, uchar *es, ushort *nexts, uchar *hist, int runlen, int check, int *m)
-{
- uchar *s, *t;
- int ml, off, last;
-
- ml = check;
- if(runlen >= 8)
- check >>= 2;
- *m = 0;
- if(p + runlen >= es)
- return runlen;
- last = 0;
- for(; check-- > 0; then = nexts[then & (MaxOff-1)]){
- off = (ushort)(now - then);
- if(off <= last || off > MaxOff)
- break;
- s = p + runlen;
- t = hist + (((p - hist) - off) & (HistBlock-1));
- t += runlen;
- for(; s >= p; s--){
- if(*s != *t)
- goto matchloop;
- t--;
- }
-
- /*
- * we have a new best match.
- * extend it to it's maximum length
- */
- t += runlen + 2;
- s += runlen + 2;
- for(; s < es; s++){
- if(*s != *t)
- break;
- t++;
- }
- runlen = s - p;
- *m = off - 1;
- if(s == es || runlen > ml)
- break;
-matchloop:;
- last = off;
- }
- return runlen;
-}
-
-static int
-lzcomp(LZstate *lz, LZblock *lzb, uchar *ep, ushort *parse, int finish)
-{
- ulong cont, excost, *litlencount, *offcount;
- uchar *p, *q, *s, *es;
- ushort *nexts, *hash;
- int v, i, h, runlen, n, now, then, m, prevlen, prevoff, maxdefer;
-
- litlencount = lzb->litlencount;
- offcount = lzb->offcount;
- nexts = lz->nexts;
- hash = lz->hash;
- now = lz->now;
-
- p = &lz->hist[lz->pos];
- if(lz->prevlen != MinMatch - 1)
- p++;
-
- /*
- * hash in the links for any hanging link positions,
- * and calculate the hash for the current position.
- */
- n = MinMatch;
- if(n > ep - p)
- n = ep - p;
- cont = 0;
- for(i = 0; i < n - 1; i++){
- m = now - ((MinMatch-1) - i);
- if(m < lz->dot)
- continue;
- s = lz->hist + (((p - lz->hist) - (now - m)) & (HistBlock-1));
-
- cont = (s[0] << 16) | (s[1] << 8) | s[2];
- h = hashit(cont);
- prevoff = 0;
- for(then = hash[h]; ; then = nexts[then & (MaxOff-1)]){
- v = (ushort)(now - then);
- if(v <= prevoff || v >= (MinMatch-1) - i)
- break;
- prevoff = v;
- }
- if(then == (ushort)m)
- continue;
- nexts[m & (MaxOff-1)] = hash[h];
- hash[h] = m;
- }
- for(i = 0; i < n; i++)
- cont = (cont << 8) | p[i];
-
- /*
- * now must point to the index in the nexts array
- * corresponding to p's position in the history
- */
- prevlen = lz->prevlen;
- prevoff = lz->prevoff;
- maxdefer = lz->maxcheck >> 2;
- excost = 0;
- v = lzb->lastv;
- for(;;){
- es = p + MaxMatch;
- if(es > ep){
- if(!finish || p >= ep)
- break;
- es = ep;
- }
-
- h = hashit(cont);
- runlen = lzmatch(now, hash[h], p, es, nexts, lz->hist, prevlen, lz->maxcheck, &m);
-
- /*
- * back out of small matches too far in the past
- */
- if(runlen == MinMatch && m >= MinMatchMaxOff){
- runlen = MinMatch - 1;
- m = 0;
- }
-
- /*
- * record the encoding and increment counts for huffman trees
- * if we get a match, defer selecting it until we check for
- * a longer match at the next position.
- */
- if(prevlen >= runlen && prevlen != MinMatch - 1){
- /*
- * old match at least as good; use that one
- */
- n = prevlen - MinMatch;
- if(v || n){
- *parse++ = v | LenFlag | (n << LenShift);
- *parse++ = prevoff;
- }else
- *parse++ = prevoff << LenShift;
- v = 0;
-
- n = lencode[n];
- litlencount[n]++;
- excost += litlenextra[n - LenStart];
-
- if(prevoff < MaxOffCode)
- n = offcode[prevoff];
- else
- n = bigoffcode[prevoff >> 7];
- offcount[n]++;
- excost += offextra[n];
-
- runlen = prevlen - 1;
- prevlen = MinMatch - 1;
- nmatches++;
- }else if(runlen == MinMatch - 1){
- /*
- * no match; just put out the literal
- */
- if(++v == MaxLitRun){
- *parse++ = v;
- v = 0;
- }
- litlencount[*p]++;
- nlits++;
- runlen = 1;
- }else{
- if(prevlen != MinMatch - 1){
- /*
- * longer match now. output previous literal,
- * update current match, and try again
- */
- if(++v == MaxLitRun){
- *parse++ = v;
- v = 0;
- }
- litlencount[p[-1]]++;
- nlits++;
- }
-
- prevoff = m;
-
- if(runlen < maxdefer){
- prevlen = runlen;
- runlen = 1;
- }else{
- n = runlen - MinMatch;
- if(v || n){
- *parse++ = v | LenFlag | (n << LenShift);
- *parse++ = prevoff;
- }else
- *parse++ = prevoff << LenShift;
- v = 0;
-
- n = lencode[n];
- litlencount[n]++;
- excost += litlenextra[n - LenStart];
-
- if(prevoff < MaxOffCode)
- n = offcode[prevoff];
- else
- n = bigoffcode[prevoff >> 7];
- offcount[n]++;
- excost += offextra[n];
-
- prevlen = MinMatch - 1;
- nmatches++;
- }
- }
-
- /*
- * update the hash for the newly matched data
- * this is constructed so the link for the old
- * match in this position must be at the end of a chain,
- * and will expire when this match is added, ie it will
- * never be examined by the match loop.
- * add to the hash chain only if we have the real hash data.
- */
- for(q = p + runlen; p != q; p++){
- if(p + MinMatch <= ep){
- h = hashit(cont);
- nexts[now & (MaxOff-1)] = hash[h];
- hash[h] = now;
- if(p + MinMatch < ep)
- cont = (cont << 8) | p[MinMatch];
- }
- now++;
- }
- }
-
- /*
- * we can just store away the lazy state and
- * pick it up next time. the last block will have finish set
- * so we won't have any pending matches
- * however, we need to correct for how much we've encoded
- */
- if(prevlen != MinMatch - 1)
- p--;
-
- lzb->excost += excost;
- lzb->eparse = parse;
- lzb->lastv = v;
-
- lz->now = now;
- lz->prevlen = prevlen;
- lz->prevoff = prevoff;
-
- return p - &lz->hist[lz->pos];
-}
-
-/*
- * make up the dynamic code tables, and return the number of bits
- * needed to transmit them.
- */
-static int
-huffcodes(Dyncode *dc, Huff *littab, Huff *offtab)
-{
- Huff *codetab;
- uchar *codes, *codeaux;
- ulong codecount[Nclen], excost;
- int i, n, m, v, c, nlit, noff, ncode, nclen;
-
- codetab = dc->codetab;
- codes = dc->codes;
- codeaux = dc->codeaux;
-
- /*
- * trim the sizes of the tables
- */
- for(nlit = Nlitlen; nlit > 257 && littab[nlit-1].bits == 0; nlit--)
- ;
- for(noff = Noff; noff > 1 && offtab[noff-1].bits == 0; noff--)
- ;
-
- /*
- * make the code-length code
- */
- for(i = 0; i < nlit; i++)
- codes[i] = littab[i].bits;
- for(i = 0; i < noff; i++)
- codes[i + nlit] = offtab[i].bits;
-
- /*
- * run-length compress the code-length code
- */
- excost = 0;
- c = 0;
- ncode = nlit+noff;
- for(i = 0; i < ncode; ){
- n = i + 1;
- v = codes[i];
- while(n < ncode && v == codes[n])
- n++;
- n -= i;
- i += n;
- if(v == 0){
- while(n >= 11){
- m = n;
- if(m > 138)
- m = 138;
- codes[c] = 18;
- codeaux[c++] = m - 11;
- n -= m;
- excost += 7;
- }
- if(n >= 3){
- codes[c] = 17;
- codeaux[c++] = n - 3;
- n = 0;
- excost += 3;
- }
- }
- while(n--){
- codes[c++] = v;
- while(n >= 3){
- m = n;
- if(m > 6)
- m = 6;
- codes[c] = 16;
- codeaux[c++] = m - 3;
- n -= m;
- excost += 3;
- }
- }
- }
-
- memset(codecount, 0, sizeof codecount);
- for(i = 0; i < c; i++)
- codecount[codes[i]]++;
- if(!mkgzprecode(codetab, codecount, Nclen, 8))
- return -1;
-
- for(nclen = Nclen; nclen > 4 && codetab[clenorder[nclen-1]].bits == 0; nclen--)
- ;
-
- dc->nlit = nlit;
- dc->noff = noff;
- dc->nclen = nclen;
- dc->ncode = c;
-
- return 5 + 5 + 4 + nclen * 3 + bitcost(codetab, codecount, Nclen) + excost;
-}
-
-static void
-wrdyncode(LZstate *out, Dyncode *dc)
-{
- Huff *codetab;
- uchar *codes, *codeaux;
- int i, v, c;
-
- /*
- * write out header, then code length code lengths,
- * and code lengths
- */
- lzput(out, dc->nlit-257, 5);
- lzput(out, dc->noff-1, 5);
- lzput(out, dc->nclen-4, 4);
-
- codetab = dc->codetab;
- for(i = 0; i < dc->nclen; i++)
- lzput(out, codetab[clenorder[i]].bits, 3);
-
- codes = dc->codes;
- codeaux = dc->codeaux;
- c = dc->ncode;
- for(i = 0; i < c; i++){
- v = codes[i];
- lzput(out, codetab[v].encode, codetab[v].bits);
- if(v >= 16){
- if(v == 16)
- lzput(out, codeaux[i], 2);
- else if(v == 17)
- lzput(out, codeaux[i], 3);
- else /* v == 18 */
- lzput(out, codeaux[i], 7);
- }
- }
-}
-
-static int
-bitcost(Huff *tab, ulong *count, int n)
-{
- ulong tot;
- int i;
-
- tot = 0;
- for(i = 0; i < n; i++)
- tot += count[i] * tab[i].bits;
- return tot;
-}
-
-static int
-mkgzprecode(Huff *tab, ulong *count, int n, int maxbits)
-{
- ulong bitcount[MaxHuffBits];
- int i, nbits;
-
- nbits = mkprecode(tab, count, n, maxbits, bitcount);
- for(i = 0; i < n; i++){
- if(tab[i].bits == -1)
- tab[i].bits = 0;
- else if(tab[i].bits == 0){
- if(nbits != 0 || bitcount[0] != 1)
- return 0;
- bitcount[1] = 1;
- bitcount[0] = 0;
- nbits = 1;
- tab[i].bits = 1;
- }
- }
- if(bitcount[0] != 0)
- return 0;
- return hufftabinit(tab, n, bitcount, nbits);
-}
-
-static int
-hufftabinit(Huff *tab, int n, ulong *bitcount, int nbits)
-{
- ulong code, nc[MaxHuffBits];
- int i, bits;
-
- code = 0;
- for(bits = 1; bits <= nbits; bits++){
- code = (code + bitcount[bits-1]) << 1;
- nc[bits] = code;
- }
-
- for(i = 0; i < n; i++){
- bits = tab[i].bits;
- if(bits){
- code = nc[bits]++ << (16 - bits);
- if(code & ~0xffff)
- return 0;
- tab[i].encode = revtab[code >> 8] | (revtab[code & 0xff] << 8);
- }
- }
- return 1;
-}
-
-
-/*
- * this should be in a library
- */
-struct Chain
-{
- ulong count; /* occurances of everything in the chain */
- ushort leaf; /* leaves to the left of chain, or leaf value */
- char col; /* ref count for collecting unused chains */
- char gen; /* need to generate chains for next lower level */
- Chain *up; /* Chain up in the lists */
-};
-
-struct Chains
-{
- Chain *lists[(MaxHuffBits - 1) * 2];
- ulong leafcount[MaxLeaf]; /* sorted list of leaf counts */
- ushort leafmap[MaxLeaf]; /* map to actual leaf number */
- int nleaf; /* number of leaves */
- Chain chains[ChainMem];
- Chain *echains;
- Chain *free;
- char col;
- int nlists;
-};
-
-/*
- * fast, low space overhead algorithm for max depth huffman type codes
- *
- * J. Katajainen, A. Moffat and A. Turpin, "A fast and space-economical
- * algorithm for length-limited coding," Proc. Intl. Symp. on Algorithms
- * and Computation, Cairns, Australia, Dec. 1995, Lecture Notes in Computer
- * Science, Vol 1004, J. Staples, P. Eades, N. Katoh, and A. Moffat, eds.,
- * pp 12-21, Springer Verlag, New York, 1995.
- */
-static int
-mkprecode(Huff *tab, ulong *count, int n, int maxbits, ulong *bitcount)
-{
- Chains cs;
- Chain *c;
- int i, m, em, bits;
-
- /*
- * set up the sorted list of leaves
- */
- m = 0;
- for(i = 0; i < n; i++){
- tab[i].bits = -1;
- tab[i].encode = 0;
- if(count[i] != 0){
- cs.leafcount[m] = count[i];
- cs.leafmap[m] = i;
- m++;
- }
- }
- if(m < 2){
- if(m != 0){
- tab[cs.leafmap[0]].bits = 0;
- bitcount[0] = 1;
- }else
- bitcount[0] = 0;
- return 0;
- }
- cs.nleaf = m;
- leafsort(cs.leafcount, cs.leafmap, 0, m);
-
- for(i = 0; i < m; i++)
- cs.leafcount[i] = count[cs.leafmap[i]];
-
- /*
- * set up free list
- */
- cs.free = &cs.chains[2];
- cs.echains = &cs.chains[ChainMem];
- cs.col = 1;
-
- /*
- * initialize chains for each list
- */
- c = &cs.chains[0];
- c->count = cs.leafcount[0];
- c->leaf = 1;
- c->col = cs.col;
- c->up = nil;
- c->gen = 0;
- cs.chains[1] = cs.chains[0];
- cs.chains[1].leaf = 2;
- cs.chains[1].count = cs.leafcount[1];
- for(i = 0; i < maxbits-1; i++){
- cs.lists[i * 2] = &cs.chains[0];
- cs.lists[i * 2 + 1] = &cs.chains[1];
- }
-
- cs.nlists = 2 * (maxbits - 1);
- m = 2 * m - 2;
- for(i = 2; i < m; i++)
- nextchain(&cs, cs.nlists - 2);
-
- bits = 0;
- bitcount[0] = cs.nleaf;
- for(c = cs.lists[cs.nlists - 1]; c != nil; c = c->up){
- m = c->leaf;
- bitcount[bits++] -= m;
- bitcount[bits] = m;
- }
- m = 0;
- for(i = bits; i >= 0; i--)
- for(em = m + bitcount[i]; m < em; m++)
- tab[cs.leafmap[m]].bits = i;
-
- return bits;
-}
-
-/*
- * calculate the next chain on the list
- * we can always toss out the old chain
- */
-static void
-nextchain(Chains *cs, int list)
-{
- Chain *c, *oc;
- int i, nleaf, sumc;
-
- oc = cs->lists[list + 1];
- cs->lists[list] = oc;
- if(oc == nil)
- return;
-
- /*
- * make sure we have all chains needed to make sumc
- * note it is possible to generate only one of these,
- * use twice that value for sumc, and then generate
- * the second if that preliminary sumc would be chosen.
- * however, this appears to be slower on current tests
- */
- if(oc->gen){
- nextchain(cs, list - 2);
- nextchain(cs, list - 2);
- oc->gen = 0;
- }
-
- /*
- * pick up the chain we're going to add;
- * collect unused chains no free ones are left
- */
- for(c = cs->free; ; c++){
- if(c >= cs->echains){
- cs->col++;
- for(i = 0; i < cs->nlists; i++)
- for(c = cs->lists[i]; c != nil; c = c->up)
- c->col = cs->col;
- c = cs->chains;
- }
- if(c->col != cs->col)
- break;
- }
-
- /*
- * pick the cheapest of
- * 1) the next package from the previous list
- * 2) the next leaf
- */
- nleaf = oc->leaf;
- sumc = 0;
- if(list > 0 && cs->lists[list-1] != nil)
- sumc = cs->lists[list-2]->count + cs->lists[list-1]->count;
- if(sumc != 0 && (nleaf >= cs->nleaf || cs->leafcount[nleaf] > sumc)){
- c->count = sumc;
- c->leaf = oc->leaf;
- c->up = cs->lists[list-1];
- c->gen = 1;
- }else if(nleaf >= cs->nleaf){
- cs->lists[list + 1] = nil;
- return;
- }else{
- c->leaf = nleaf + 1;
- c->count = cs->leafcount[nleaf];
- c->up = oc->up;
- c->gen = 0;
- }
- cs->free = c + 1;
-
- cs->lists[list + 1] = c;
- c->col = cs->col;
-}
-
-static int
-pivot(ulong *c, int a, int n)
-{
- int j, pi, pj, pk;
-
- j = n/6;
- pi = a + j; /* 1/6 */
- j += j;
- pj = pi + j; /* 1/2 */
- pk = pj + j; /* 5/6 */
- if(c[pi] < c[pj]){
- if(c[pi] < c[pk]){
- if(c[pj] < c[pk])
- return pj;
- return pk;
- }
- return pi;
- }
- if(c[pj] < c[pk]){
- if(c[pi] < c[pk])
- return pi;
- return pk;
- }
- return pj;
-}
-
-static void
-leafsort(ulong *leafcount, ushort *leafmap, int a, int n)
-{
- ulong t;
- int j, pi, pj, pn;
-
- while(n > 1){
- if(n > 10){
- pi = pivot(leafcount, a, n);
- }else
- pi = a + (n>>1);
-
- t = leafcount[pi];
- leafcount[pi] = leafcount[a];
- leafcount[a] = t;
- t = leafmap[pi];
- leafmap[pi] = leafmap[a];
- leafmap[a] = t;
- pi = a;
- pn = a + n;
- pj = pn;
- for(;;){
- do
- pi++;
- while(pi < pn && (leafcount[pi] < leafcount[a] || leafcount[pi] == leafcount[a] && leafmap[pi] > leafmap[a]));
- do
- pj--;
- while(pj > a && (leafcount[pj] > leafcount[a] || leafcount[pj] == leafcount[a] && leafmap[pj] < leafmap[a]));
- if(pj < pi)
- break;
- t = leafcount[pi];
- leafcount[pi] = leafcount[pj];
- leafcount[pj] = t;
- t = leafmap[pi];
- leafmap[pi] = leafmap[pj];
- leafmap[pj] = t;
- }
- t = leafcount[a];
- leafcount[a] = leafcount[pj];
- leafcount[pj] = t;
- t = leafmap[a];
- leafmap[a] = leafmap[pj];
- leafmap[pj] = t;
- j = pj - a;
-
- n = n-j-1;
- if(j >= n){
- leafsort(leafcount, leafmap, a, j);
- a += j+1;
- }else{
- leafsort(leafcount, leafmap, a + (j+1), n);
- n = j;
- }
- }
-}
--- a/os/boot/libflate/deflateblock.c
+++ /dev/null
@@ -1,55 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-typedef struct Block Block;
-
-struct Block
-{
- uchar *pos;
- uchar *limit;
-};
-
-static int
-blread(void *vb, void *buf, int n)
-{
- Block *b;
-
- b = vb;
- if(n > b->limit - b->pos)
- n = b->limit - b->pos;
- memmove(buf, b->pos, n);
- b->pos += n;
- return n;
-}
-
-static int
-blwrite(void *vb, void *buf, int n)
-{
- Block *b;
-
- b = vb;
-
- if(n > b->limit - b->pos)
- n = b->limit - b->pos;
- memmove(b->pos, buf, n);
- b->pos += n;
- return n;
-}
-
-int
-deflateblock(uchar *dst, int dsize, uchar *src, int ssize, int level, int debug)
-{
- Block bd, bs;
- int ok;
-
- bs.pos = src;
- bs.limit = src + ssize;
-
- bd.pos = dst;
- bd.limit = dst + dsize;
-
- ok = deflate(&bd, blwrite, &bs, blread, level, debug);
- if(ok != FlateOk)
- return ok;
- return bd.pos - dst;
-}
--- a/os/boot/libflate/deflatezlib.c
+++ /dev/null
@@ -1,59 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-#include "zlib.h"
-
-typedef struct ZRead ZRead;
-
-struct ZRead
-{
- ulong adler;
- void *rr;
- int (*r)(void*, void*, int);
-};
-
-static int
-zlread(void *vzr, void *buf, int n)
-{
- ZRead *zr;
-
- zr = vzr;
- n = (*zr->r)(zr->rr, buf, n);
- if(n <= 0)
- return n;
- zr->adler = adler32(zr->adler, buf, n);
- return n;
-}
-
-int
-deflatezlib(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
-{
- ZRead zr;
- uchar buf[4];
- int ok;
-
- buf[0] = ZlibDeflate | ZlibWin32k;
-
- /* bogus zlib encoding of compression level */
- buf[1] = ((level > 2) + (level > 5) + (level > 8)) << 6;
-
- /* header check field */
- buf[1] |= 31 - ((buf[0] << 8) | buf[1]) % 31;
- if((*w)(wr, buf, 2) != 2)
- return FlateOutputFail;
-
- zr.rr = rr;
- zr.r = r;
- zr.adler = 1;
- ok = deflate(wr, w, &zr, zlread, level, debug);
- if(ok != FlateOk)
- return ok;
-
- buf[0] = zr.adler >> 24;
- buf[1] = zr.adler >> 16;
- buf[2] = zr.adler >> 8;
- buf[3] = zr.adler;
- if((*w)(wr, buf, 4) != 4)
- return FlateOutputFail;
-
- return FlateOk;
-}
--- a/os/boot/libflate/deflatezlibblock.c
+++ /dev/null
@@ -1,33 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-#include "zlib.h"
-
-int
-deflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize, int level, int debug)
-{
- ulong adler;
- int n;
-
- if(dsize < 6)
- return FlateOutputFail;
-
- n = deflateblock(dst + 2, dsize - 6, src, ssize, level, debug);
- if(n < 0)
- return n;
-
- dst[0] = ZlibDeflate | ZlibWin32k;
-
- /* bogus zlib encoding of compression level */
- dst[1] = ((level > 2) + (level > 5) + (level > 8)) << 6;
-
- /* header check field */
- dst[1] |= 31 - ((dst[0] << 8) | dst[1]) % 31;
-
- adler = adler32(1, src, ssize);
- dst[n + 2] = adler >> 24;
- dst[n + 3] = adler >> 16;
- dst[n + 4] = adler >> 8;
- dst[n + 5] = adler;
-
- return n + 6;
-}
--- a/os/boot/libflate/flateerr.c
+++ /dev/null
@@ -1,22 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-char *
-flateerr(int err)
-{
- switch(err){
- case FlateOk:
- return "no error";
- case FlateNoMem:
- return "out of memory";
- case FlateInputFail:
- return "input error";
- case FlateOutputFail:
- return "output error";
- case FlateCorrupted:
- return "corrupted data";
- case FlateInternal:
- return "internal error";
- }
- return "unknown error";
-}
--- a/os/boot/libflate/inflate.c
+++ /dev/null
@@ -1,692 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-enum {
- HistorySize= 32*1024,
- BufSize= 4*1024,
- MaxHuffBits= 17, /* maximum bits in a encoded code */
- Nlitlen= 288, /* number of litlen codes */
- Noff= 32, /* number of offset codes */
- Nclen= 19, /* number of codelen codes */
- LenShift= 10, /* code = len<<LenShift|code */
- LitlenBits= 7, /* number of bits in litlen decode table */
- OffBits= 6, /* number of bits in offset decode table */
- ClenBits= 6, /* number of bits in code len decode table */
- MaxFlatBits= LitlenBits,
- MaxLeaf= Nlitlen
-};
-
-typedef struct Input Input;
-typedef struct History History;
-typedef struct Huff Huff;
-
-struct Input
-{
- int error; /* first error encountered, or FlateOk */
- void *wr;
- int (*w)(void*, void*, int);
- void *getr;
- int (*get)(void*);
- ulong sreg;
- int nbits;
-};
-
-struct History
-{
- uchar his[HistorySize];
- uchar *cp; /* current pointer in history */
- int full; /* his has been filled up at least once */
-};
-
-struct Huff
-{
- int maxbits; /* max bits for any code */
- int minbits; /* min bits to get before looking in flat */
- int flatmask; /* bits used in "flat" fast decoding table */
- ulong flat[1<<MaxFlatBits];
- ulong maxcode[MaxHuffBits];
- ulong last[MaxHuffBits];
- ulong decode[MaxLeaf];
-};
-
-/* litlen code words 257-285 extra bits */
-static int litlenextra[Nlitlen-257] =
-{
-/* 257 */ 0, 0, 0,
-/* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
-/* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
-/* 280 */ 4, 5, 5, 5, 5, 0, 0, 0
-};
-
-static int litlenbase[Nlitlen-257];
-
-/* offset code word extra bits */
-static int offextra[Noff] =
-{
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
- 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
- 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
- 0, 0,
-};
-static int offbase[Noff];
-
-/* order code lengths */
-static int clenorder[Nclen] =
-{
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
-};
-
-/* for static huffman tables */
-static Huff litlentab;
-static Huff offtab;
-static uchar revtab[256];
-
-static int uncblock(Input *in, History*);
-static int fixedblock(Input *in, History*);
-static int dynamicblock(Input *in, History*);
-static int sregfill(Input *in, int n);
-static int sregunget(Input *in);
-static int decode(Input*, History*, Huff*, Huff*);
-static int hufftab(Huff*, char*, int, int);
-static int hdecsym(Input *in, Huff *h, int b);
-
-int
-inflateinit(void)
-{
- char *len;
- int i, j, base;
-
- /* byte reverse table */
- for(i=0; i<256; i++)
- for(j=0; j<8; j++)
- if(i & (1<<j))
- revtab[i] |= 0x80 >> j;
-
- for(i=257,base=3; i<Nlitlen; i++) {
- litlenbase[i-257] = base;
- base += 1<<litlenextra[i-257];
- }
- /* strange table entry in spec... */
- litlenbase[285-257]--;
-
- for(i=0,base=1; i<Noff; i++) {
- offbase[i] = base;
- base += 1<<offextra[i];
- }
-
- len = malloc(MaxLeaf);
- if(len == nil)
- return FlateNoMem;
-
- /* static Litlen bit lengths */
- for(i=0; i<144; i++)
- len[i] = 8;
- for(i=144; i<256; i++)
- len[i] = 9;
- for(i=256; i<280; i++)
- len[i] = 7;
- for(i=280; i<Nlitlen; i++)
- len[i] = 8;
-
- if(!hufftab(&litlentab, len, Nlitlen, MaxFlatBits))
- return FlateInternal;
-
- /* static Offset bit lengths */
- for(i=0; i<Noff; i++)
- len[i] = 5;
-
- if(!hufftab(&offtab, len, Noff, MaxFlatBits))
- return FlateInternal;
- free(len);
-
- return FlateOk;
-}
-
-int
-inflate(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
-{
- History *his;
- Input in;
- int final, type;
-
- his = malloc(sizeof(History));
- if(his == nil)
- return FlateNoMem;
- his->cp = his->his;
- his->full = 0;
- in.getr = getr;
- in.get = get;
- in.wr = wr;
- in.w = w;
- in.nbits = 0;
- in.sreg = 0;
- in.error = FlateOk;
-
- do {
- if(!sregfill(&in, 3))
- goto bad;
- final = in.sreg & 0x1;
- type = (in.sreg>>1) & 0x3;
- in.sreg >>= 3;
- in.nbits -= 3;
- switch(type) {
- default:
- in.error = FlateCorrupted;
- goto bad;
- case 0:
- /* uncompressed */
- if(!uncblock(&in, his))
- goto bad;
- break;
- case 1:
- /* fixed huffman */
- if(!fixedblock(&in, his))
- goto bad;
- break;
- case 2:
- /* dynamic huffman */
- if(!dynamicblock(&in, his))
- goto bad;
- break;
- }
- } while(!final);
-
- if(his->cp != his->his && (*w)(wr, his->his, his->cp - his->his) != his->cp - his->his) {
- in.error = FlateOutputFail;
- goto bad;
- }
-
- if(!sregunget(&in))
- goto bad;
-
- free(his);
- if(in.error != FlateOk)
- return FlateInternal;
- return FlateOk;
-
-bad:
- free(his);
- if(in.error == FlateOk)
- return FlateInternal;
- return in.error;
-}
-
-static int
-uncblock(Input *in, History *his)
-{
- int len, nlen, c;
- uchar *hs, *hp, *he;
-
- if(!sregunget(in))
- return 0;
- len = (*in->get)(in->getr);
- len |= (*in->get)(in->getr)<<8;
- nlen = (*in->get)(in->getr);
- nlen |= (*in->get)(in->getr)<<8;
- if(len != (~nlen&0xffff)) {
- in->error = FlateCorrupted;
- return 0;
- }
-
- hp = his->cp;
- hs = his->his;
- he = hs + HistorySize;
-
- while(len > 0) {
- c = (*in->get)(in->getr);
- if(c < 0)
- return 0;
- *hp++ = c;
- if(hp == he) {
- his->full = 1;
- if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
- in->error = FlateOutputFail;
- return 0;
- }
- hp = hs;
- }
- len--;
- }
-
- his->cp = hp;
-
- return 1;
-}
-
-static int
-fixedblock(Input *in, History *his)
-{
- return decode(in, his, &litlentab, &offtab);
-}
-
-static int
-dynamicblock(Input *in, History *his)
-{
- Huff *lentab, *offtab;
- char *len;
- int i, j, n, c, nlit, ndist, nclen, res, nb;
-
- if(!sregfill(in, 14))
- return 0;
- nlit = (in->sreg&0x1f) + 257;
- ndist = ((in->sreg>>5) & 0x1f) + 1;
- nclen = ((in->sreg>>10) & 0xf) + 4;
- in->sreg >>= 14;
- in->nbits -= 14;
-
- if(nlit > Nlitlen || ndist > Noff || nlit < 257) {
- in->error = FlateCorrupted;
- return 0;
- }
-
- /* huff table header */
- len = malloc(Nlitlen+Noff);
- lentab = malloc(sizeof(Huff));
- offtab = malloc(sizeof(Huff));
- if(len == nil || lentab == nil || offtab == nil){
- in->error = FlateNoMem;
- goto bad;
- }
- for(i=0; i < Nclen; i++)
- len[i] = 0;
- for(i=0; i<nclen; i++) {
- if(!sregfill(in, 3))
- goto bad;
- len[clenorder[i]] = in->sreg & 0x7;
- in->sreg >>= 3;
- in->nbits -= 3;
- }
-
- if(!hufftab(lentab, len, Nclen, ClenBits)){
- in->error = FlateCorrupted;
- goto bad;
- }
-
- n = nlit+ndist;
- for(i=0; i<n;) {
- nb = lentab->minbits;
- for(;;){
- if(in->nbits<nb && !sregfill(in, nb))
- goto bad;
- c = lentab->flat[in->sreg & lentab->flatmask];
- nb = c & 0xff;
- if(nb > in->nbits){
- if(nb != 0xff)
- continue;
- c = hdecsym(in, lentab, c);
- if(c < 0)
- goto bad;
- }else{
- c >>= 8;
- in->sreg >>= nb;
- in->nbits -= nb;
- }
- break;
- }
-
- if(c < 16) {
- j = 1;
- } else if(c == 16) {
- if(in->nbits<2 && !sregfill(in, 2))
- goto bad;
- j = (in->sreg&0x3)+3;
- in->sreg >>= 2;
- in->nbits -= 2;
- if(i == 0) {
- in->error = FlateCorrupted;
- goto bad;
- }
- c = len[i-1];
- } else if(c == 17) {
- if(in->nbits<3 && !sregfill(in, 3))
- goto bad;
- j = (in->sreg&0x7)+3;
- in->sreg >>= 3;
- in->nbits -= 3;
- c = 0;
- } else if(c == 18) {
- if(in->nbits<7 && !sregfill(in, 7))
- goto bad;
- j = (in->sreg&0x7f)+11;
- in->sreg >>= 7;
- in->nbits -= 7;
- c = 0;
- } else {
- in->error = FlateCorrupted;
- goto bad;
- }
-
- if(i+j > n) {
- in->error = FlateCorrupted;
- goto bad;
- }
-
- while(j) {
- len[i] = c;
- i++;
- j--;
- }
- }
-
- if(!hufftab(lentab, len, nlit, LitlenBits)
- || !hufftab(offtab, &len[nlit], ndist, OffBits)){
- in->error = FlateCorrupted;
- goto bad;
- }
-
- res = decode(in, his, lentab, offtab);
-
- free(len);
- free(lentab);
- free(offtab);
-
- return res;
-
-bad:
- free(len);
- free(lentab);
- free(offtab);
- return 0;
-}
-
-static int
-decode(Input *in, History *his, Huff *litlentab, Huff *offtab)
-{
- int len, off;
- uchar *hs, *hp, *hq, *he;
- int c;
- int nb;
-
- hs = his->his;
- he = hs + HistorySize;
- hp = his->cp;
-
- for(;;) {
- nb = litlentab->minbits;
- for(;;){
- if(in->nbits<nb && !sregfill(in, nb))
- return 0;
- c = litlentab->flat[in->sreg & litlentab->flatmask];
- nb = c & 0xff;
- if(nb > in->nbits){
- if(nb != 0xff)
- continue;
- c = hdecsym(in, litlentab, c);
- if(c < 0)
- return 0;
- }else{
- c >>= 8;
- in->sreg >>= nb;
- in->nbits -= nb;
- }
- break;
- }
-
- if(c < 256) {
- /* literal */
- *hp++ = c;
- if(hp == he) {
- his->full = 1;
- if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
- in->error = FlateOutputFail;
- return 0;
- }
- hp = hs;
- }
- continue;
- }
-
- if(c == 256)
- break;
-
- if(c > 285) {
- in->error = FlateCorrupted;
- return 0;
- }
-
- c -= 257;
- nb = litlenextra[c];
- if(in->nbits < nb && !sregfill(in, nb))
- return 0;
- len = litlenbase[c] + (in->sreg & ((1<<nb)-1));
- in->sreg >>= nb;
- in->nbits -= nb;
-
- /* get offset */
- nb = offtab->minbits;
- for(;;){
- if(in->nbits<nb && !sregfill(in, nb))
- return 0;
- c = offtab->flat[in->sreg & offtab->flatmask];
- nb = c & 0xff;
- if(nb > in->nbits){
- if(nb != 0xff)
- continue;
- c = hdecsym(in, offtab, c);
- if(c < 0)
- return 0;
- }else{
- c >>= 8;
- in->sreg >>= nb;
- in->nbits -= nb;
- }
- break;
- }
-
- if(c > 29) {
- in->error = FlateCorrupted;
- return 0;
- }
-
- nb = offextra[c];
- if(in->nbits < nb && !sregfill(in, nb))
- return 0;
-
- off = offbase[c] + (in->sreg & ((1<<nb)-1));
- in->sreg >>= nb;
- in->nbits -= nb;
-
- hq = hp - off;
- if(hq < hs) {
- if(!his->full) {
- in->error = FlateCorrupted;
- return 0;
- }
- hq += HistorySize;
- }
-
- /* slow but correct */
- while(len) {
- *hp = *hq;
- hq++;
- hp++;
- if(hq >= he)
- hq = hs;
- if(hp == he) {
- his->full = 1;
- if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
- in->error = FlateOutputFail;
- return 0;
- }
- hp = hs;
- }
- len--;
- }
-
- }
-
- his->cp = hp;
-
- return 1;
-}
-
-static int
-revcode(int c, int b)
-{
- /* shift encode up so it starts on bit 15 then reverse */
- c <<= (16-b);
- c = revtab[c>>8] | (revtab[c&0xff]<<8);
- return c;
-}
-
-/*
- * construct the huffman decoding arrays and a fast lookup table.
- * the fast lookup is a table indexed by the next flatbits bits,
- * which returns the symbol matched and the number of bits consumed,
- * or the minimum number of bits needed and 0xff if more than flatbits
- * bits are needed.
- *
- * flatbits can be longer than the smallest huffman code,
- * because shorter codes are assigned smaller lexical prefixes.
- * this means assuming zeros for the next few bits will give a
- * conservative answer, in the sense that it will either give the
- * correct answer, or return the minimum number of bits which
- * are needed for an answer.
- */
-static int
-hufftab(Huff *h, char *hb, int maxleaf, int flatbits)
-{
- ulong bitcount[MaxHuffBits];
- ulong c, fc, ec, mincode, code, nc[MaxHuffBits];
- int i, b, minbits, maxbits;
-
- for(i = 0; i < MaxHuffBits; i++)
- bitcount[i] = 0;
- maxbits = -1;
- minbits = MaxHuffBits + 1;
- for(i=0; i < maxleaf; i++){
- b = hb[i];
- if(b){
- bitcount[b]++;
- if(b < minbits)
- minbits = b;
- if(b > maxbits)
- maxbits = b;
- }
- }
-
- h->maxbits = maxbits;
- if(maxbits <= 0){
- h->maxbits = 0;
- h->minbits = 0;
- h->flatmask = 0;
- return 1;
- }
- code = 0;
- c = 0;
- for(b = 0; b <= maxbits; b++){
- h->last[b] = c;
- c += bitcount[b];
- mincode = code << 1;
- nc[b] = mincode;
- code = mincode + bitcount[b];
- if(code > (1 << b))
- return 0;
- h->maxcode[b] = code - 1;
- h->last[b] += code - 1;
- }
-
- if(flatbits > maxbits)
- flatbits = maxbits;
- h->flatmask = (1 << flatbits) - 1;
- if(minbits > flatbits)
- minbits = flatbits;
- h->minbits = minbits;
-
- b = 1 << flatbits;
- for(i = 0; i < b; i++)
- h->flat[i] = ~0;
-
- /*
- * initialize the flat table to include the minimum possible
- * bit length for each code prefix
- */
- for(b = maxbits; b > flatbits; b--){
- code = h->maxcode[b];
- if(code == -1)
- break;
- mincode = code + 1 - bitcount[b];
- mincode >>= b - flatbits;
- code >>= b - flatbits;
- for(; mincode <= code; mincode++)
- h->flat[revcode(mincode, flatbits)] = (b << 8) | 0xff;
- }
-
- for(i = 0; i < maxleaf; i++){
- b = hb[i];
- if(b <= 0)
- continue;
- c = nc[b]++;
- if(b <= flatbits){
- code = (i << 8) | b;
- ec = (c + 1) << (flatbits - b);
- if(ec > (1<<flatbits))
- return 0; /* this is actually an internal error */
- for(fc = c << (flatbits - b); fc < ec; fc++)
- h->flat[revcode(fc, flatbits)] = code;
- }
- if(b > minbits){
- c = h->last[b] - c;
- if(c >= maxleaf)
- return 0;
- h->decode[c] = i;
- }
- }
- return 1;
-}
-
-static int
-hdecsym(Input *in, Huff *h, int nb)
-{
- long c;
-
- if((nb & 0xff) == 0xff)
- nb = nb >> 8;
- else
- nb = nb & 0xff;
- for(; nb <= h->maxbits; nb++){
- if(in->nbits<nb && !sregfill(in, nb))
- return -1;
- c = revtab[in->sreg&0xff]<<8;
- c |= revtab[(in->sreg>>8)&0xff];
- c >>= (16-nb);
- if(c <= h->maxcode[nb]){
- in->sreg >>= nb;
- in->nbits -= nb;
- return h->decode[h->last[nb] - c];
- }
- }
- in->error = FlateCorrupted;
- return -1;
-}
-
-static int
-sregfill(Input *in, int n)
-{
- int c;
-
- while(n > in->nbits) {
- c = (*in->get)(in->getr);
- if(c < 0){
- in->error = FlateInputFail;
- return 0;
- }
- in->sreg |= c<<in->nbits;
- in->nbits += 8;
- }
- return 1;
-}
-
-static int
-sregunget(Input *in)
-{
- if(in->nbits >= 8) {
- in->error = FlateInternal;
- return 0;
- }
-
- /* throw other bits on the floor */
- in->nbits = 0;
- in->sreg = 0;
- return 1;
-}
--- a/os/boot/libflate/inflateblock.c
+++ /dev/null
@@ -1,53 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-
-typedef struct Block Block;
-
-struct Block
-{
- uchar *pos;
- uchar *limit;
-};
-
-static int
-blgetc(void *vb)
-{
- Block *b;
-
- b = vb;
- if(b->pos >= b->limit)
- return -1;
- return *b->pos++;
-}
-
-static int
-blwrite(void *vb, void *buf, int n)
-{
- Block *b;
-
- b = vb;
-
- if(n > b->limit - b->pos)
- n = b->limit - b->pos;
- memmove(b->pos, buf, n);
- b->pos += n;
- return n;
-}
-
-int
-inflateblock(uchar *dst, int dsize, uchar *src, int ssize)
-{
- Block bd, bs;
- int ok;
-
- bs.pos = src;
- bs.limit = src + ssize;
-
- bd.pos = dst;
- bd.limit = dst + dsize;
-
- ok = inflate(&bd, blwrite, &bs, blgetc);
- if(ok != FlateOk)
- return ok;
- return bd.pos - dst;
-}
--- a/os/boot/libflate/inflatezlib.c
+++ /dev/null
@@ -1,65 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-#include "zlib.h"
-
-typedef struct ZWrite ZWrite;
-
-struct ZWrite
-{
- ulong adler;
- void *wr;
- int (*w)(void*, void*, int);
-};
-
-static int
-zlwrite(void *vzw, void *buf, int n)
-{
- ZWrite *zw;
-
- zw = vzw;
- zw->adler = adler32(zw->adler, buf, n);
- n = (*zw->w)(zw->wr, buf, n);
- if(n <= 0)
- return n;
- return n;
-}
-
-int
-inflatezlib(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
-{
- ZWrite zw;
- ulong v;
- int c, i;
-
- c = (*get)(getr);
- if(c < 0)
- return FlateInputFail;
- i = (*get)(getr);
- if(i < 0)
- return FlateInputFail;
-
- if(((c << 8) | i) % 31)
- return FlateCorrupted;
- if((c & ZlibMeth) != ZlibDeflate
- || (c & ZlibCInfo) > ZlibWin32k)
- return FlateCorrupted;
-
- zw.wr = wr;
- zw.w = w;
- zw.adler = 1;
- i = inflate(&zw, zlwrite, getr, get);
- if(i != FlateOk)
- return i;
-
- v = 0;
- for(i = 0; i < 4; i++){
- c = (*get)(getr);
- if(c < 0)
- return FlateInputFail;
- v = (v << 8) | c;
- }
- if(zw.adler != v)
- return FlateCorrupted;
-
- return FlateOk;
-}
--- a/os/boot/libflate/inflatezlibblock.c
+++ /dev/null
@@ -1,67 +1,0 @@
-#include "lib9.h"
-#include <flate.h>
-#include "zlib.h"
-
-typedef struct Block Block;
-
-struct Block
-{
- uchar *pos;
- uchar *limit;
-};
-
-static int
-blgetc(void *vb)
-{
- Block *b;
-
- b = vb;
- if(b->pos >= b->limit)
- return -1;
- return *b->pos++;
-}
-
-static int
-blwrite(void *vb, void *buf, int n)
-{
- Block *b;
-
- b = vb;
-
- if(n > b->limit - b->pos)
- n = b->limit - b->pos;
- memmove(b->pos, buf, n);
- b->pos += n;
- return n;
-}
-
-int
-inflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize)
-{
- Block bd, bs;
- int ok;
-
- if(ssize < 6)
- return FlateInputFail;
-
- if(((src[0] << 8) | src[1]) % 31)
- return FlateCorrupted;
- if((src[0] & ZlibMeth) != ZlibDeflate
- || (src[0] & ZlibCInfo) > ZlibWin32k)
- return FlateCorrupted;
-
- bs.pos = src + 2;
- bs.limit = src + ssize - 6;
-
- bd.pos = dst;
- bd.limit = dst + dsize;
-
- ok = inflate(&bd, blwrite, &bs, blgetc);
- if(ok != FlateOk)
- return ok;
-
- if(adler32(1, dst, bs.pos - dst) != ((bs.pos[0] << 24) | (bs.pos[1] << 16) | (bs.pos[2] << 8) | bs.pos[3]))
- return FlateCorrupted;
-
- return bd.pos - dst;
-}
--- a/os/boot/libflate/mkfile
+++ /dev/null
@@ -1,21 +1,0 @@
-<../../../mkconfig
-
-LIB=libflate.a
-OFILES=\
- deflate.$O\
- deflatezlib.$O\
- deflateblock.$O\
- deflatezlibblock.$O\
- inflate.$O\
- inflatezlib.$O\
- inflateblock.$O\
- inflatezlibblock.$O\
- flateerr.$O\
- crc.$O\
- adler.$O\
-
-HFILES=\
- $ROOT/include/flate.h\
- zlib.h\
-
-<$ROOT/mkfiles/mksyslib-$SHELLTYPE
--- a/os/boot/libflate/zlib.h
+++ /dev/null
@@ -1,11 +1,0 @@
-/*
- * zlib header fields
- */
-enum
-{
- ZlibMeth = 0x0f, /* mask of compression methods */
- ZlibDeflate = 0x08,
-
- ZlibCInfo = 0xf0, /* mask of compression aux. info */
- ZlibWin32k = 0x70, /* 32k history window */
-};
--- a/os/boot/mpc/NOTICE
+++ /dev/null
@@ -1,3 +1,0 @@
-Inferno® Copyright © 1996-1999 Lucent Technologies Inc. All rights reserved.
-PowerPC support Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk). All rights reserved.
-MPC8xx Inferno PowerPC port Copyright © 1998-2003 Vita Nuova Holdings Limited. All rights reserved.
--- a/os/boot/mpc/alarm.c
+++ /dev/null
@@ -1,123 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#define MAXALARM 10
-
-Alarm alarmtab[MAXALARM];
-
-/*
- * Insert new into list after where
- */
-void
-insert(List **head, List *where, List *new)
-{
- if(where == 0){
- new->next = *head;
- *head = new;
- }else{
- new->next = where->next;
- where->next = new;
- }
-
-}
-
-/*
- * Delete old from list. where->next is known to be old.
- */
-void
-delete(List **head, List *where, List *old)
-{
- if(where == 0){
- *head = old->next;
- return;
- }
- where->next = old->next;
-}
-
-Alarm*
-newalarm(void)
-{
- int i;
- Alarm *a;
-
- for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
- if(a->busy==0 && a->f==0){
- a->f = 0;
- a->arg = 0;
- a->busy = 1;
- return a;
- }
- panic("newalarm");
- return 0; /* not reached */
-}
-
-Alarm*
-alarm(int ms, void (*f)(Alarm*), void *arg)
-{
- Alarm *a, *w, *pw;
- ulong s;
-
- if(ms < 0)
- ms = 0;
- s = splhi();
- a = newalarm();
- a->dt = MS2TK(ms);
- a->f = f;
- a->arg = arg;
- pw = 0;
- for(w=m->alarm; w; pw=w, w=w->next){
- if(w->dt <= a->dt){
- a->dt -= w->dt;
- continue;
- }
- w->dt -= a->dt;
- break;
- }
- insert(&m->alarm, pw, a);
- splx(s);
- return a;
-}
-
-void
-cancel(Alarm *a)
-{
- a->f = 0;
-}
-
-void
-alarminit(void)
-{
-}
-
-#define NA 10 /* alarms per clock tick */
-void
-checkalarms(void)
-{
- int i, n, s;
- Alarm *a;
- void (*f)(Alarm*);
- Alarm *alist[NA];
-
- s = splhi();
- a = m->alarm;
- if(a){
- for(n=0; a && a->dt<=0 && n<NA; n++){
- alist[n] = a;
- delete(&m->alarm, 0, a);
- a = m->alarm;
- }
- if(a)
- a->dt--;
-
- for(i = 0; i < n; i++){
- f = alist[i]->f; /* avoid race with cancel */
- if(f)
- (*f)(alist[i]);
- alist[i]->busy = 0;
- }
- }
- splx(s);
-}
--- a/os/boot/mpc/all.h
+++ /dev/null
@@ -1,6 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "dat.h"
-#include "fns.h"
-#include "mem.h"
-#include "io.h"
--- a/os/boot/mpc/archfads.c
+++ /dev/null
@@ -1,355 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "archfads.h"
-
-/*
- * board-specific support for the 8xxFADS (including 860/21 development system)
- */
-
-enum {
- USESDRAM = 0, /* set to 1 if kernel is to use SDRAM as well as DRAM */
-
- /* sccr */
- RTSEL = IBIT(8), /* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
- RTDIV = IBIT(7), /* =0, divide by 4; =1, divide by 512 */
- CRQEN = IBIT(9), /* =1, switch to high frequency when CPM active */
- PRQEN = IBIT(10), /* =1, switch to high frequency when interrupt pending */
-
- /* plprcr */
- CSRC = IBIT(21), /* =0, clock is DFNH; =1, clock is DFNL */
-};
-
-/*
- * called early in main.c, after machinit:
- * using board and architecture specific registers, initialise
- * 8xx registers that need it and complete initialisation of the Mach structure.
- */
-void
-archinit(void)
-{
- IMM *io;
- int mf, isfads, sysmhz, t;
- ulong v;
-
- v = getimmr() & 0xFFFF;
- isfads = 0; /* assume it's the 860/821 board */
- sysmhz = 40;
- switch(v>>8){
- case 0x00: t = 0x86000; break;
- case 0x20: t = 0x82300; isfads = 1; break;
- case 0x21: t = 0x823a0; isfads = 1; break;
- default: t = 0; break;
- }
- m->cputype = t;
- m->bcsr = KADDR(BCSRMEM);
- m->bcsr[1] |= DisableRS232a | DisableIR | DisableEther | DisablePCMCIA | DisableRS232b;
- m->bcsr[1] &= ~(DisableDRAM|DisableFlash);
- if(isfads){
- sysmhz = 50;
- m->bcsr[1] &= ~EnableSDRAM;
- m->bcsr[4] &= ~(EnableVideoClock|EnableVideoPort);
- m->bcsr[4] |= DisableVideoLamp;
- }
- io = m->iomem;
- if(1 || io->sccr & IBIT(7)){ /* RTDIV=1 */
- /* oscillator frequency can't be determined independently: check a switch */
- if((m->bcsr[2]>>19)&(1<<2))
- m->clockgen = 5*MHz;
- else
- m->clockgen = 4*MHz;
- } else
- m->clockgen = 32768;
- mf = (sysmhz*MHz)/m->clockgen;
- m->cpuhz = m->clockgen*mf;
- io->plprcrk = KEEP_ALIVE_KEY;
- io->plprcr &= ~IBIT(21); /* general system clock is DFNH */
- io->plprcr = (io->plprcr & ((1<<20)-1)) | ((mf-1)<<20);
- io->mptpr = 0x0400; /* memory prescaler = 16 for refresh */
- io->plprcrk = ~KEEP_ALIVE_KEY;
- if(isfads){
- m->bcsr[1] |= EnableSDRAM;
- sdraminit(SDRAMMEM);
- if(!USESDRAM)
- m->bcsr[1] &= ~EnableSDRAM; /* tells kernel not to map it */
- }
-}
-
-static void
-archidprint(void)
-{
- int f, i;
- ulong v;
-
- /* 8xx and FADS specific */
- print("IMMR: ");
- v = getimmr() & 0xFFFF;
- switch(v>>8){
- case 0x00: print("MPC860/821"); break;
- case 0x20: print("MPC823"); break;
- case 0x21: print("MPC823A"); break;
- default: print("Type #%lux", v>>8); break;
- }
- print(", mask #%lux\n", v&0xFF);
- v = m->bcsr[3]>>16;
- print("MPC8xxFADS rev %lud, DB: ", ((v>>4)&8)|((v>>1)&4)|(v&3));
- f = (v>>8)&0x3F;
- switch(f){
- default: print("ID#%x", f); break;
- case 0x00: print("MPC860/821"); break;
- case 0x01: print("MPC813"); break;
- case 0x02: print("MPC821"); break;
- case 0x03: print("MPC823"); break;
- case 0x20: print("MPC801"); break;
- case 0x21: print("MPC850"); break;
- case 0x22: print("MPC860"); break;
- case 0x23: print("MPC860SAR"); break;
- case 0x24: print("MPC860T"); break;
- }
- print("ADS, rev #%lux\n", (m->bcsr[2]>>16)&7);
- for(i=0; i<=4; i++)
- print("BCSR%d: %8.8lux\n", i, m->bcsr[i]);
- v = m->bcsr[2];
- f = (v>>28)&0xF;
- switch(f){
- default: print("Unknown"); break;
- case 4: print("SM732A2000/SM73228 - 8M SIMM"); break;
- case 5: print("SM732A1000A/SM73218 - 4M SIMM"); break;
- case 6: print("MCM29080 - 8M SIMM"); break;
- case 7: print("MCM29040 - 4M SIMM"); break;
- case 8: print("MCM29020 - 2M SIMM"); break;
- }
- switch((m->bcsr[3]>>20)&7){
- default: i = 0; break;
- case 1: i = 150; break;
- case 2: i = 120; break;
- case 3: i = 90; break;
- }
- print(" flash, %dns\n", i);
- f = (v>>23)&0xF;
- switch(f&3){
- case 0: i = 4; break;
- case 1: i = 32; break;
- case 2: i = 16; break;
- case 3: i = 8; break;
- }
- print("%dM SIMM, ", i);
- switch(f>>2){
- default: i = 0; break;
- case 2: i = 70; break;
- case 3: i = 60; break;
- }
- print("%dns\n", i);
- print("options: #%lux\n", (m->bcsr[2]>>19)&0xF);
- print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
-}
-
-void
-cpuidprint(void)
-{
- int t;
-
- print("PVR: ");
- t = getpvr()>>16;
- switch(t){
- case 0x01: print("MPC601"); break;
- case 0x03: print("MPC603"); break;
- case 0x04: print("MPC604"); break;
- case 0x06: print("MPC603e"); break;
- case 0x07: print("MPC603e-v7"); break;
- case 0x50: print("MPC8xx"); break;
- default: print("PowerPC version #%x", t); break;
- }
- print(", revision #%lux\n", getpvr()&0xffff);
- archidprint();
- print("%lud MHz system\n", m->cpuhz/MHz);
- print("\n");
-}
-
-static char* defplan9ini[2] = {
- /* 860/821 */
- "ether0=type=SCC port=1 ea=00108bf12900\r\n"
- "vgasize=640x480x8\r\n"
- "kernelpercent=40\r\n"
- "console=0 lcd\r\nbaud=9600\r\n",
-
- /* 823 */
- "ether0=type=SCC port=2 ea=00108bf12900\r\n"
- "vgasize=640x480x8\r\n"
- "kernelpercent=40\r\n"
- "console=0 lcd\r\nbaud=9600\r\n",
-};
-
-char *
-archconfig(void)
-{
- print("Using default configuration\n");
- return defplan9ini[MPCMODEL(m->cputype) == 0x823];
-}
-
-/*
- * provide value for #r/switch (devrtc.c)
- */
-int
-archoptionsw(void)
-{
- return (m->bcsr[2]>>19)&0xF; /* value of switch DS1 */
-}
-
-/*
- * invoked by clock.c:/^clockintr
- */
-static void
-twinkle(void)
-{
- if(m->ticks%MS2TK(1000) == 0)
- m->bcsr[4] ^= DisableLamp;
-}
-
-void (*archclocktick)(void) = twinkle;
-
-/*
- * for flash.c:/^flashreset
- * retrieve flash type, virtual base and length and return 0;
- * return -1 on error (no flash)
- */
-int
-archflashreset(char *type, void **addr, long *length)
-{
- char *t;
- int mbyte;
-
- if((m->iomem->memc[0].base & 1) == 0)
- return -1; /* shouldn't happen */
- switch((m->bcsr[2]>>28)&0xF){
- default: return -1; /* unknown or not there */
- case 4: mbyte=8; t = "SM732x8"; break;
- case 5: mbyte=4; t = "SM732x8"; break;
- case 6: mbyte=8; t = "AMD29F0x0"; break;
- case 7: mbyte=4; t = "AMD29F0x0"; break;
- case 8: mbyte=2; t = "AMD29F0x0"; break;
- }
- strcpy(type, t);
- *addr = KADDR(FLASHMEM);
- *length = mbyte*1024*1024;
- return 0;
-}
-
-/*
- * enable the clocks for the given SCC ether and reveal them to the caller.
- * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
- */
-int
-archetherenable(int cpmid, int *rcs, int *tcs)
-{
- IMM *io;
-
- switch(cpmid){
- default:
- /* no other SCCs are wired on the FADS board */
- return -1;
-
- case SCC2ID: /* assume 8xxFADS board with 823DABS */
- io = ioplock();
- m->bcsr[1] |= DisableIR|DisableRS232b;
- m->bcsr[1] &= ~DisableEther;
- io->papar |= SIBIT(6)|SIBIT(5); /* enable CLK2 and CLK3 */
- io->padir &= ~(SIBIT(6)|SIBIT(5));
-
- /* ETHLOOP etc set in BCSR elsewhere */
- *rcs = CLK2;
- *tcs = CLK3;
- iopunlock();
- break;
-
- case SCC1ID: /* assume 860/21 development board */
- io = ioplock();
- m->bcsr[1] |= DisableIR|DisableRS232b; /* TO DO: might not be shared with RS232b */
- m->bcsr[1] &= ~DisableEther;
- io->papar |= SIBIT(6)|SIBIT(7); /* enable CLK2 and CLK1 */
- io->padir &= ~(SIBIT(6)|SIBIT(7));
-
- /* settings peculiar to 860/821 development board */
- io->pcpar &= ~(SIBIT(4)|SIBIT(5)|SIBIT(6)); /* ETHLOOP, TPFULDL~, TPSQEL~ */
- io->pcdir |= SIBIT(4)|SIBIT(5)|SIBIT(6);
- io->pcdat &= ~SIBIT(4);
- io->pcdat |= SIBIT(5)|SIBIT(6);
- *rcs = CLK2;
- *tcs = CLK1;
- iopunlock();
- break;
- }
- return 0;
-}
-
-void
-archetherdisable(int id)
-{
- USED(id);
- m->bcsr[1] |= DisableEther|DisableIR|DisableRS232b;
-}
-
-/*
- * do anything extra required to enable the UART on the given CPM port
- */
-void
-archenableuart(int id, int irda)
-{
- switch(id){
- case SMC1ID:
- m->bcsr[1] &= ~DisableRS232a;
- break;
- case SCC2ID:
- m->bcsr[1] |= DisableEther|DisableIR|DisableRS232b;
- if(irda)
- m->bcsr[1] &= ~DisableIR;
- else
- m->bcsr[1] &= ~DisableRS232b;
- break;
- default:
- /* nothing special */
- break;
- }
-}
-
-/*
- * do anything extra required to disable the UART on the given CPM port
- */
-void
-archdisableuart(int id)
-{
- switch(id){
- case SMC1ID:
- m->bcsr[1] |= DisableRS232a;
- break;
- case SCC2ID:
- m->bcsr[1] |= DisableIR|DisableRS232b;
- break;
- default:
- /* nothing special */
- break;
- }
-}
-
-/*
- * enable/disable the LCD panel's backlight via
- * York touch panel interface (does no harm without it)
- */
-void
-archbacklight(int on)
-{
- IMM *io;
-
- delay(2);
- io = ioplock();
- io->papar &= ~SIBIT(4);
- io->padir |= SIBIT(4);
- if(on)
- io->padat |= SIBIT(4);
- else
- io->padat &= ~SIBIT(4);
- iopunlock();
-}
--- a/os/boot/mpc/archfads.h
+++ /dev/null
@@ -1,42 +1,0 @@
-
-enum {
- /* BCSR1 bits */
- DisableFlash= IBIT(0),
- DisableDRAM= IBIT(1),
- DisableEther= IBIT(2),
- DisableIR= IBIT(3),
- DisableRS232a= IBIT(7),
- DisablePCMCIA= IBIT(8),
- PCCVCCMask= IBIT(9)|IBIT(15),
- PCCVPPMask= IBIT(10)|IBIT(11),
- DisableRS232b= IBIT(13),
- EnableSDRAM= IBIT(14),
-
- PCCVCC0V= IBIT(15)|IBIT(9),
- PCCVCC5V= IBIT(9), /* active low */
- PCCVCC3V= IBIT(15), /* active low */
- PCCVPP0V= IBIT(10)|IBIT(11), /* active low */
- PCCVPP5V= IBIT(10), /* active low */
- PCCVPP12V= IBIT(11), /* active low */
- PCCVPPHiZ= IBIT(10)|IBIT(11),
-
- /* BCSR4 bits */
- DisableTPDuplex= IBIT(1),
- DisableLamp= IBIT(3),
- DisableUSB= IBIT(4),
- USBFullSpeed= IBIT(5),
- DisableUSBVcc= IBIT(6),
- DisableVideoLamp= IBIT(8),
- EnableVideoClock= IBIT(9),
- EnableVideoPort= IBIT(10),
- DisableModem= IBIT(11),
-};
-
-enum {
- /* memory controller CS assignment on FADS boards */
- BOOTCS = 0,
- BCSRCS = 1,
- DRAM1 = 2,
- DRAM2 = 3,
- SDRAM = 4,
-};
--- a/os/boot/mpc/archpaq.c
+++ /dev/null
@@ -1,240 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "archpaq.h"
-
-/*
- * board-specific support for the 82x PowerPAQ
- */
-
-enum {
- SYSMHZ = 50, /* desired system clock in MHz */
-
- /* sccr */
- RTSEL = IBIT(8), /* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
- RTDIV = IBIT(7), /* =0, divide by 4; =1, divide by 512 */
- CRQEN = IBIT(9), /* =1, switch to high frequency when CPM active */
- PRQEN = IBIT(10), /* =1, switch to high frequency when interrupt pending */
-
- /* plprcr */
- CSRC = IBIT(21), /* =0, clock is DFNH; =1, clock is DFNL */
-};
-
-/*
- * called early in main.c, after machinit:
- * using board and architecture specific registers, initialise
- * 8xx registers that need it and complete initialisation of the Mach structure.
- */
-void
-archinit(void)
-{
- IMM *io;
- int mf, t;
-
- switch((getimmr()>>8)&0xFF){
- case 0x00: t = 0x86000; break; /* also 821 */
- case 0x20: t = 0x82300; break;
- case 0x21: t = 0x823a0; break;
- default: t = 0; break;
- }
- m->cputype = t;
- m->bcsr = nil; /* there isn't one */
- m->clockgen = 32*1024; /* crystal frequency */
- io = m->iomem;
- io->sccrk = KEEP_ALIVE_KEY;
- io->sccr &= ~RTDIV; /* divide 32k by 4 */
- io->sccr |= RTSEL;
- io->sccrk = ~KEEP_ALIVE_KEY;
- mf = (SYSMHZ*MHz)/m->clockgen;
- m->cpuhz = m->clockgen*mf;
- io->plprcrk = KEEP_ALIVE_KEY;
- io->plprcr &= ~IBIT(21); /* general system clock is DFNH */
- io->plprcr = (io->plprcr & ((1<<20)-1)) | ((mf-1)<<20);
- io->mptpr = 0x0400; /* memory prescaler = 16 for refresh */
- io->plprcrk = ~KEEP_ALIVE_KEY;
-}
-
-void
-cpuidprint(void)
-{
- int t, v;
-
- print("PVR: ");
- t = getpvr()>>16;
- switch(t){
- case 0x01: print("MPC601"); break;
- case 0x03: print("MPC603"); break;
- case 0x04: print("MPC604"); break;
- case 0x06: print("MPC603e"); break;
- case 0x07: print("MPC603e-v7"); break;
- case 0x50: print("MPC8xx"); break;
- default: print("PowerPC version #%x", t); break;
- }
- print(", revision #%lux\n", getpvr()&0xffff);
- print("IMMR: ");
- v = getimmr() & 0xFFFF;
- switch(v>>8){
- case 0x00: print("MPC860/821"); break;
- case 0x20: print("MPC823"); break;
- case 0x21: print("MPC823A"); break;
- default: print("Type #%lux", v>>8); break;
- }
- print(", mask #%lux\n", v&0xFF);
- print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
- print("%lud MHz system\n", m->cpuhz/MHz);
- print("\n");
-}
-
-static char* defplan9ini[2] = {
- /* 860/821 */
- "ether0=type=SCC port=1 ea=00108bf12900\r\n"
- "vgasize=640x480x8\r\n"
- "kernelpercent=40\r\n"
- "console=0 lcd\r\nbaud=19200\r\n",
-
- /* 823 */
- "ether0=type=SCC port=2 ea=00108bf12900\r\n"
- "vgasize=640x480x8\r\n"
- "kernelpercent=40\r\n"
- "console=0 lcd\r\nbaud=19200\r\n",
-};
-
-char *
-archconfig(void)
-{
- print("Using default configuration\n");
- return defplan9ini[MPCMODEL(m->cputype) == 0x823];
-}
-
-/*
- * provide value for #r/switch (devrtc.c)
- */
-int
-archoptionsw(void)
-{
- return 0;
-}
-
-/*
- * invoked by clock.c:/^clockintr
- */
-static void
-twinkle(void)
-{
- /* no easy-to-use LED on PAQ (they use i2c) */
-}
-
-void (*archclocktick)(void) = twinkle;
-
-/*
- * for flash.c:/^flashinit
- * retrieve flash type, virtual base and length and return 0;
- * return -1 on error (no flash)
- */
-int
-archflashreset(char *type, void **addr, long *length)
-{
- strcpy(type, "AMD29F0x0");
- *addr = KADDR(FLASHMEM);
- *length = 8*1024*1024; /* 8mbytes on some models */
- return 0;
-}
-
-/*
- * enable the clocks for the given SCC ether and reveal them to the caller.
- * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
- */
-int
-archetherenable(int cpmid, int *rcs, int *tcs)
-{
- USED(cpmid, rcs, tcs);
- return -1; /* there isn't an ether on the PAQs */
-}
-
-void
-archetherdisable(int id)
-{
- USED(id);
-}
-
-/*
- * do anything extra required to enable the UART on the given CPM port
- */
-void
-archenableuart(int id, int irda)
-{
- IMM *io;
-
- USED(irda);
- switch(id){
- case SMC1ID:
- io = ioplock();
- io->pbodr &= ~0xc0;
- io->pbdat |= 0xc0;
- io->pcdat |= 0x400;
- io->pcpar &= ~0x400;
- io->pcdir |= 0x400;
- io->pcdat &= ~0x400; /* enable SMC RS232 buffer */
- iopunlock();
- break;
- case SCC2ID:
- /* TO DO */
- break;
- default:
- /* nothing special */
- break;
- }
-}
-
-/*
- * do anything extra required to disable the UART on the given CPM port
- */
-void
-archdisableuart(int id)
-{
- switch(id){
- case SMC1ID:
- /* TO DO */
- break;
- case SCC2ID:
- /* TO DO */
- break;
- default:
- /* nothing special */
- break;
- }
-}
-
-/*
- * enable/disable the LCD panel's backlight via i2c
- */
-void
-archbacklight(int on)
-{
- uchar msg;
- IMM *io;
-
- i2csetup();
- msg = ~7;
- i2csend(LEDRegI2C, &msg, 1);
- io = ioplock();
- io->pbpar &= ~EnableLCD;
- io->pbodr &= ~EnableLCD;
- io->pbdir |= EnableLCD;
- if(on)
- io->pbdat |= EnableLCD;
- else
- io->pbdat &= ~EnableLCD;
- iopunlock();
- if(on){
- msg = ~(DisablePanelVCC5|DisableTFT);
- i2csend(PanelI2C, &msg, 1);
- }else{
- msg = ~0;
- i2csend(PanelI2C, &msg, 1);
- }
-}
--- a/os/boot/mpc/archpaq.h
+++ /dev/null
@@ -1,29 +1,0 @@
-enum {
- /* memory controller CS assignment on PowerPAQ */
- BOOTCS = 0,
- DRAM1 = 1, /* UPMB */
- DRAM2 = 2, /* UPMB */
- /* CS3 also connected to DRAM */
- /* CS4 128mbyte 8-bit gpcm, trlx, 15 wait; it's DAC */
- /* CS5 is external*/
-};
-
-enum {
- /* I2C addresses */
- PanelI2C = 0x21<<1,
- /* the control bits are active low enables, or high disables */
- DisableVGA = ~0xFD, /* disable VGA signals */
- DisableTFT = ~0xFB, /* disable TFT panel signals */
- DisableSPIBus = ~0xF7, /* disable SPI/I2C to panel */
- DisablePanelVCC5 = ~0xEF, /* disable +5V to panel(s) */
- DisablePanelVCC3 = ~0xDF, /* disable +3.3V to panel(s) */
- DisableMonoPanel = ~0xBF, /* disable mono panel signals */
- DisableSPISelect = ~0x7F, /* disable SPI chip select to LVDS panel */
- ContrastI2C = 0x2E<<1,
- LEDRegI2C = 0x20<<1,
- DisableGreenLED = ~0xFE,
- DisableYellowLED = ~0xFD,
- DisableRedLED = ~0xFB,
-
- EnableLCD = IBIT(23), /* LCD enable bit in i/o port B */
-};
--- a/os/boot/mpc/boot.h
+++ /dev/null
@@ -1,8 +1,0 @@
-#include <u.h>
-#include "lib.h"
-
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
--- a/os/boot/mpc/bootp.c
+++ /dev/null
@@ -1,507 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ip.h"
-
-enum {
- CHECKSUM = 1, /* set zero if trouble booting from Linux */
-};
-
-uchar broadcast[Eaddrlen] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static ushort tftpport = 5000;
-static int Id = 1;
-static Netaddr myaddr;
-static Netaddr server;
-
-typedef struct {
- uchar header[4];
- uchar data[Segsize];
-} Tftp;
-static Tftp tftpb;
-
-static void
-hnputs(uchar *ptr, ushort val)
-{
- ptr[0] = val>>8;
- ptr[1] = val;
-}
-
-static void
-hnputl(uchar *ptr, ulong val)
-{
- ptr[0] = val>>24;
- ptr[1] = val>>16;
- ptr[2] = val>>8;
- ptr[3] = val;
-}
-
-static ulong
-nhgetl(uchar *ptr)
-{
- return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
-}
-
-static ushort
-nhgets(uchar *ptr)
-{
- return ((ptr[0]<<8) | ptr[1]);
-}
-
-static short endian = 1;
-static char* aendian = (char*)&endian;
-#define LITTLE *aendian
-
-static ushort
-ptcl_csum(void *a, int len)
-{
- uchar *addr;
- ulong t1, t2;
- ulong losum, hisum, mdsum, x;
-
- addr = a;
- losum = 0;
- hisum = 0;
- mdsum = 0;
-
- x = 0;
- if((ulong)addr & 1) {
- if(len) {
- hisum += addr[0];
- len--;
- addr++;
- }
- x = 1;
- }
- while(len >= 16) {
- t1 = *(ushort*)(addr+0);
- t2 = *(ushort*)(addr+2); mdsum += t1;
- t1 = *(ushort*)(addr+4); mdsum += t2;
- t2 = *(ushort*)(addr+6); mdsum += t1;
- t1 = *(ushort*)(addr+8); mdsum += t2;
- t2 = *(ushort*)(addr+10); mdsum += t1;
- t1 = *(ushort*)(addr+12); mdsum += t2;
- t2 = *(ushort*)(addr+14); mdsum += t1;
- mdsum += t2;
- len -= 16;
- addr += 16;
- }
- while(len >= 2) {
- mdsum += *(ushort*)addr;
- len -= 2;
- addr += 2;
- }
- if(x) {
- if(len)
- losum += addr[0];
- if(LITTLE)
- losum += mdsum;
- else
- hisum += mdsum;
- } else {
- if(len)
- hisum += addr[0];
- if(LITTLE)
- hisum += mdsum;
- else
- losum += mdsum;
- }
-
- losum += hisum >> 8;
- losum += (hisum & 0xff) << 8;
- while(hisum = losum>>16)
- losum = hisum + (losum & 0xffff);
-
- return ~losum;
-}
-
-static ushort
-ip_csum(uchar *addr)
-{
- int len;
- ulong sum = 0;
-
- len = (addr[0]&0xf)<<2;
-
- while(len > 0) {
- sum += addr[0]<<8 | addr[1] ;
- len -= 2;
- addr += 2;
- }
-
- sum = (sum & 0xffff) + (sum >> 16);
- sum = (sum & 0xffff) + (sum >> 16);
- return (sum^0xffff);
-}
-
-static void
-udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
-{
- Udphdr *uh;
- Etherhdr *ip;
- static Etherpkt pkt;
- int len, ptcllen;
-
-
- uh = (Udphdr*)&pkt;
-
- memset(uh, 0, sizeof(Etherpkt));
- memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
-
- /*
- * UDP portion
- */
- ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
- uh->ttl = 0;
- uh->udpproto = IP_UDPPROTO;
- uh->frag[0] = 0;
- uh->frag[1] = 0;
- hnputs(uh->udpplen, ptcllen);
- hnputl(uh->udpsrc, myaddr.ip);
- hnputs(uh->udpsport, myaddr.port);
- hnputl(uh->udpdst, a->ip);
- hnputs(uh->udpdport, a->port);
- hnputs(uh->udplen, ptcllen);
- uh->udpcksum[0] = 0;
- uh->udpcksum[1] = 0;
- /*dlen = (dlen+1)&~1; */
- hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
-
- /*
- * IP portion
- */
- ip = (Etherhdr*)&pkt;
- len = sizeof(Udphdr)+dlen;
- ip->vihl = IP_VER|IP_HLEN;
- ip->tos = 0;
- ip->ttl = 255;
- hnputs(ip->length, len-ETHER_HDR);
- hnputs(ip->id, Id++);
- ip->frag[0] = 0;
- ip->frag[1] = 0;
- ip->cksum[0] = 0;
- ip->cksum[1] = 0;
- hnputs(ip->cksum, ip_csum(&ip->vihl));
-
- /*
- * Ethernet MAC portion
- */
- hnputs(ip->type, ET_IP);
- memmove(ip->d, a->ea, sizeof(ip->d));
-
- ethertxpkt(ctlrno, &pkt, len, Timeout);
-}
-
-static void
-nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
-{
- int n;
- char buf[128];
-
- buf[0] = 0;
- buf[1] = Tftp_ERROR;
- buf[2] = 0;
- buf[3] = code;
- strcpy(buf+4, msg);
- n = strlen(msg) + 4 + 1;
- udpsend(ctlrno, a, buf, n);
- if(report)
- print("\ntftp: error(%d): %s\n", code, msg);
-}
-
-static int
-udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
-{
- int n, len;
- ushort csm;
- Udphdr *h;
- ulong addr, timo;
- static Etherpkt pkt;
- static int rxactive;
-
- if(rxactive == 0)
- timo = 1000;
- else
- timo = Timeout;
- timo += TK2MS(m->ticks);
- while(timo > TK2MS(m->ticks)){
- n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
- if(n <= 0)
- continue;
-
- h = (Udphdr*)&pkt;
- if(nhgets(h->type) != ET_IP)
- continue;
-
- if(ip_csum(&h->vihl)) {
- print("ip chksum error\n");
- continue;
- }
- if(h->vihl != (IP_VER|IP_HLEN)) {
- print("ip bad vers/hlen\n");
- continue;
- }
-
- if(h->udpproto != IP_UDPPROTO)
- continue;
-
- h->ttl = 0;
- len = nhgets(h->udplen);
- hnputs(h->udpplen, len);
-
- if(CHECKSUM && nhgets(h->udpcksum)) {
- csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
- if(csm != 0) {
- print("udp chksum error csum #%4lux len %d\n", csm, n);
- break;
- }
- }
-
- if(a->port != 0 && nhgets(h->udpsport) != a->port)
- continue;
-
- addr = nhgetl(h->udpsrc);
- if(a->ip != Bcastip && addr != a->ip)
- continue;
-
- len -= UDP_HDRSIZE-UDP_PHDRSIZE;
- if(len > dlen) {
- print("udp: packet too big\n");
- continue;
- }
-
- memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
- a->ip = addr;
- a->port = nhgets(h->udpsport);
- memmove(a->ea, pkt.s, sizeof(a->ea));
-
- rxactive = 1;
- return len;
- }
-
- return 0;
-}
-
-static int tftpblockno;
-
-static int
-tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
-{
- int i, len, rlen, oport;
- char buf[Segsize+2];
-
- buf[0] = 0;
- buf[1] = Tftp_READ;
- len = sprint(buf+2, "%s", name) + 2;
- len += sprint(buf+len+1, "octet") + 2;
-
- oport = a->port;
- for(i = 0; i < 5; i++){
- a->port = oport;
- udpsend(ctlrno, a, buf, len);
- a->port = 0;
- if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
- continue;
-
- switch((tftp->header[0]<<8)|tftp->header[1]){
-
- case Tftp_ERROR:
- print("tftpopen: error (%d): %s\n",
- (tftp->header[2]<<8)|tftp->header[3], tftp->data);
- return -1;
-
- case Tftp_DATA:
- tftpblockno = 1;
- len = (tftp->header[2]<<8)|tftp->header[3];
- if(len != tftpblockno){
- print("tftpopen: block error: %d\n", len);
- nak(ctlrno, a, 1, "block error", 0);
- return -1;
- }
- return rlen-sizeof(tftp->header);
- }
- }
-
- print("tftpopen: failed to connect to server\n");
- return -1;
-}
-
-static int
-tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
-{
- int blockno, len, retry;
- uchar buf[4];
-
- buf[0] = 0;
- buf[1] = Tftp_ACK;
- buf[2] = tftpblockno>>8;
- buf[3] = tftpblockno;
- tftpblockno++;
-
- dlen += sizeof(tftp->header);
-
- retry = 0;
-buggery:
- udpsend(ctlrno, a, buf, sizeof(buf));
-
- if((len = udprecv(ctlrno, a, tftp, dlen)) < dlen){
- print("tftpread: %d != %d\n", len, dlen);
- nak(ctlrno, a, 2, "short read", 0);
- if(retry++ < 5)
- goto buggery;
- return -1;
- }
-
- blockno = (tftp->header[2]<<8)|tftp->header[3];
- if(blockno != tftpblockno){
- print("?");
-
- if(blockno == tftpblockno-1 && retry++ < 8)
- goto buggery;
- print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
- nak(ctlrno, a, 1, "block error", 0);
-
- return -1;
- }
-
- return len-sizeof(tftp->header);
-}
-
-int
-bootp(int ctlrno, char *file)
-{
- Bootp req, rep;
- int i, dlen, segsize, text, data, bss, total;
- uchar *ea, *addr, *p;
- ulong entry;
- Exec *exec;
- char name[128], *filename, *sysname;
-
- if((ea = etheraddr(ctlrno)) == 0){
- print("invalid ctlrno %d\n", ctlrno);
- return -1;
- }
-
- filename = 0;
- sysname = 0;
- if(file && *file){
- strcpy(name, file);
- if(filename = strchr(name, ':')){
- if(filename != name && *(filename-1) != '\\'){
- sysname = name;
- *filename++ = 0;
- }
- }
- else
- filename = name;
- }
-
-
- memset(&req, 0, sizeof(req));
- req.op = Bootrequest;
- req.htype = 1; /* ethernet */
- req.hlen = Eaddrlen; /* ethernet */
- memmove(req.chaddr, ea, Eaddrlen);
-
- myaddr.ip = 0;
- myaddr.port = BPportsrc;
- memmove(myaddr.ea, ea, Eaddrlen);
-
- for(i = 0; i < 10; i++) {
- server.ip = Bcastip;
- server.port = BPportdst;
- memmove(server.ea, broadcast, sizeof(server.ea));
- udpsend(ctlrno, &server, &req, sizeof(req));
- if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
- continue;
- if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
- continue;
- if(rep.htype != 1 || rep.hlen != Eaddrlen)
- continue;
- if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
- break;
- }
- if(i >= 10) {
- print("bootp timed out\n");
- return -1;
- }
-
- if(filename == 0 || *filename == 0)
- filename = rep.file;
-
- if(rep.sname[0] != '\0')
- print("%s ", rep.sname);
- print("(%d.%d.%d.%d!%d): %s\n",
- rep.siaddr[0],
- rep.siaddr[1],
- rep.siaddr[2],
- rep.siaddr[3],
- server.port,
- filename);uartwait();
-
- myaddr.ip = nhgetl(rep.yiaddr);
- myaddr.port = tftpport++;
- server.ip = nhgetl(rep.siaddr);
- server.port = TFTPport;
-
- if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
- return -1;
- exec = (Exec*)(tftpb.data);
- if(dlen < sizeof(Exec) || GLLONG(exec->magic) != Q_MAGIC){
- nak(ctlrno, &server, 0, "bad magic number", 1);
- return -1;
- }
- text = GLLONG(exec->text);
- data = GLLONG(exec->data);
- bss = GLLONG(exec->bss);
- total = text+data+bss;
- entry = GLLONG(exec->entry);
-print("load@%8.8lux: ", PADDR(entry));uartwait();
- print("%d", text);
-
- addr = (uchar*)PADDR(entry);
- p = tftpb.data+sizeof(Exec);
- dlen -= sizeof(Exec);
- segsize = text;
- for(;;){
- if(dlen == 0){
- if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
- return -1;
- p = tftpb.data;
- }
- if(segsize <= dlen)
- i = segsize;
- else
- i = dlen;
- memmove(addr, p, i);
-
- addr += i;
- p += i;
- segsize -= i;
- dlen -= i;
-
- if(segsize <= 0){
- if(data == 0)
- break;
- print("+%d", data);
- segsize = data;
- data = 0;
- addr = (uchar*)PGROUND((ulong)addr);
- }
- }
- nak(ctlrno, &server, 3, "ok", 0); /* tftpclose */
- print("+%d=%d\n", bss, total);
- print("entry: 0x%lux\n", entry);
- uartwait();
- scc2stop();
- splhi();
- (*(void(*)(void))(PADDR(entry)))();
-
- return 0;
-}
--- a/os/boot/mpc/clock.c
+++ /dev/null
@@ -1,71 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-
-enum {
- Timebase = 4, /* system clock cycles per time base cycle */
-};
-
-void (*archclocktick)(void); /* set by arch*.c when desired */
-
-static ulong clkreload;
-
-void
-delay(int l)
-{
- ulong i, j;
-
- j = m->delayloop;
- while(l-- > 0)
- for(i=0; i < j; i++)
- ;
-}
-
-void
-microdelay(int l)
-{
- ulong i;
-
- l *= m->delayloop;
- l /= 1000;
- if(l <= 0)
- l = 1;
- for(i = 0; i < l; i++)
- ;
-}
-
-void
-clockintr(Ureg*, void*)
-{
- putdec(clkreload);
- m->ticks++;
- checkalarms();
- if(archclocktick != nil)
- archclocktick();
-}
-
-void
-clockinit(void)
-{
- long x;
-
- m->delayloop = m->cpuhz/1000; /* initial estimate */
- do {
- x = gettbl();
- delay(10);
- x = gettbl() - x;
- } while(x < 0);
-
- /*
- * fix count
- */
- m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase);
- if(m->delayloop == 0)
- m->delayloop = 1;
- clkreload = (m->clockgen/Timebase)/HZ-1;
- putdec(clkreload);
-}
--- a/os/boot/mpc/conf.c
+++ /dev/null
@@ -1,173 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "dosfs.h"
-
-static char *confname[MAXCONF];
-static char *confval[MAXCONF];
-static int nconf;
-
-extern char **ini;
-
-char*
-getconf(char *name)
-{
- int i;
-
- for(i = 0; i < nconf; i++)
- if(strcmp(confname[i], name) == 0)
- return confval[i];
- return 0;
-}
-
-/*
- * read configuration file
- */
-int
-plan9ini(Dos *dos, char *val)
-{
- Dosfile rc;
- int i, n;
- char *cp, *p, *q, *line[MAXCONF];
-
- cp = BOOTARGS;
- if(dos) {
- if(dosstat(dos, *ini, &rc) <= 0)
- return -1;
-
- *cp = 0;
- n = dosread(&rc, cp, BOOTARGSLEN-1);
- if(n <= 0)
- return -1;
- cp[n] = 0;
- } else if(val != nil){
- if(memchr(val, 0, BOOTARGSLEN-1) == nil)
- return -1;
- print("Using flash configuration\n");
- strcpy(cp, val);
- n = strlen(cp);
- }else{
- strcpy(cp, archconfig());
- n = strlen(cp);
- }
-
- /*
- * Make a working copy.
- * We could change this to pass the parsed strings
- * to the booted programme instead of the raw
- * string, then it only gets done once.
- */
- memmove(cp+BOOTARGSLEN, cp, n+1);
- cp += BOOTARGSLEN;
-
- /*
- * Strip out '\r', change '\t' -> ' '.
- */
- p = cp;
- for(q = cp; *q; q++){
- if(*q == '\r')
- continue;
- if(*q == '\t')
- *q = ' ';
- *p++ = *q;
- }
- *p = 0;
- n = getcfields(cp, line, MAXCONF, "\n");
- for(i = 0; i < n; i++){
- cp = strchr(line[i], '=');
- if(cp == 0)
- continue;
- *cp++ = 0;
- if(cp - line[i] >= NAMELEN+1)
- *(line[i]+NAMELEN-1) = 0;
- confname[nconf] = line[i];
- confval[nconf] = cp;
- nconf++;
- }
- return 0;
-}
-
-int
-parseether(uchar *to, char *from)
-{
- char nip[4];
- char *p;
- int i;
-
- p = from;
- while(*p == ' ')
- ++p;
- for(i = 0; i < 6; i++){
- if(*p == 0)
- return -1;
- nip[0] = *p++;
- if(*p == 0)
- return -1;
- nip[1] = *p++;
- nip[2] = 0;
- to[i] = strtoul(nip, 0, 16);
- if(*p == ':')
- p++;
- }
- return 0;
-}
-
-int
-isaconfig(char *class, int ctlrno, ISAConf *isa)
-{
- char cc[NAMELEN], *p, *q, *r;
- int n;
-
- sprint(cc, "%s%d", class, ctlrno);
- for(n = 0; n < nconf; n++){
- if(strncmp(confname[n], cc, NAMELEN))
- continue;
- isa->nopt = 0;
- p = confval[n];
- while(*p){
- while(*p == ' ' || *p == '\t')
- p++;
- if(*p == '\0')
- break;
- if(strncmp(p, "type=", 5) == 0){
- p += 5;
- for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
- if(*p == '\0' || *p == ' ' || *p == '\t')
- break;
- *q = *p++;
- }
- *q = '\0';
- }
- else if(strncmp(p, "port=", 5) == 0)
- isa->port = strtoul(p+5, &p, 0);
- else if(strncmp(p, "irq=", 4) == 0)
- isa->irq = strtoul(p+4, &p, 0);
- else if(strncmp(p, "mem=", 4) == 0)
- isa->mem = strtoul(p+4, &p, 0);
- else if(strncmp(p, "size=", 5) == 0)
- isa->size = strtoul(p+5, &p, 0);
- else if(strncmp(p, "ea=", 3) == 0){
- if(parseether(isa->ea, p+3) == -1)
- memset(isa->ea, 0, 6);
- }
- else if(isa->nopt < NISAOPT){
- r = isa->opt[isa->nopt];
- while(*p && *p != ' ' && *p != '\t'){
- *r++ = *p++;
- if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
- break;
- }
- *r = '\0';
- isa->nopt++;
- }
- while(*p && *p != ' ' && *p != '\t')
- p++;
- }
- return 1;
- }
- return 0;
-}
--- a/os/boot/mpc/console.c
+++ /dev/null
@@ -1,173 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-static Queue* consiq;
-static Queue* consoq;
-
-void
-bothputs(char *s, int n)
-{
- uartputs(s, n);
- screenputs(s, n);
-}
-
-static void (*consputs)(char*, int) = bothputs; /* or screenputs */
-
-void
-consinit(void)
-{
- char *p;
- int baud, port;
- static int cgadone;
-
- p = getconf("console");
- if(0)
- if(p == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
- consiq = qopen(4*1024, 0, 0, 0);
- consoq = qopen(8*1024, 0, 0, 0);
- consputs = screenputs;
- return;
- }
- if(p!=0 && strstr(p, "lcd") == 0)
- consputs = bothputs;
- else
- consputs = uartputs;
-//consputs = screenputs;
- port = 0;
- if(p)
- port = strtoul(p, 0, 0);
- baud = 0;
- if(p = getconf("baud"))
- baud = strtoul(p, 0, 0);
- if(baud == 0)
- baud = 9600;
- uartspecial(port, baud, &consiq, &consoq, kbdchar);
-}
-
-void
-kbdchar(Queue *q, int c)
-{
- c &= 0x7F;
- if(c == 0x10)
- panic("^p");
- qbputc(q, c);
-}
-
-static int
-getline(char *buf, int size, int dotimeout)
-{
- int c, i=0;
- ulong start;
- char echo;
-
- for (;;) {
- start = m->ticks;
- do{
- if(dotimeout && ((m->ticks - start) > 5*HZ))
- return -2;
- c = qbgetc(consiq);
- }while(c == -1);
- if(c == '\r')
- c = '\n'; /* turn carriage return into newline */
- if(c == '\177')
- c = '\010'; /* turn delete into backspace */
- if(c == '\025')
- echo = '\n'; /* echo ^U as a newline */
- else
- echo = c;
- (*consputs)(&echo, 1);
-
- if(c == '\010'){
- if(i > 0)
- i--; /* bs deletes last character */
- continue;
- }
- /* a newline ends a line */
- if (c == '\n')
- break;
- /* ^U wipes out the line */
- if (c =='\025')
- return -1;
- if(i == size)
- return size;
- buf[i++] = c;
- }
- buf[i] = 0;
- return i;
-}
-
-int
-getstr(char *prompt, char *buf, int size, char *def)
-{
- int len, isdefault;
-
- buf[0] = 0;
- isdefault = (def && *def);
- for (;;) {
- if(isdefault)
- print("%s[default==%s]: ", prompt, def);
- else
- print("%s: ", prompt);
- len = getline(buf, size, isdefault);
- switch(len){
- case -1:
- /* ^U typed */
- continue;
- case -2:
- /* timeout, use default */
- (*consputs)("\n", 1);
- len = 0;
- break;
- default:
- break;
- }
- if(len >= size){
- print("line too long\n");
- continue;
- }
- break;
- }
- if(len == 0 && isdefault)
- strcpy(buf, def);
- return 0;
-}
-
-int
-sprint(char *s, char *fmt, ...)
-{
- return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
-}
-
-int
-print(char *fmt, ...)
-{
- char buf[PRINTSIZE];
- int n;
-
- if(consputs == 0)
- return 0;
- n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
- (*consputs)(buf, n);
- return n;
-}
-
-void
-panic(char *fmt, ...)
-{
- char buf[PRINTSIZE];
- int n;
-
- if(consputs){
- (*consputs)("panic: ", 7);
- n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
- (*consputs)(buf, n);
- (*consputs)("\n", 1);
- }
- spllo();
- for(;;)
- idle();
-}
--- a/os/boot/mpc/cpm.c
+++ /dev/null
@@ -1,162 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-enum {
- BDSIZE= 1024, /* TO DO: check this */
-};
-
-static Map bdmapv[BDSIZE/sizeof(BD)];
-static RMap bdmap = {"buffer descriptors"};
-
-void
-cpminit(void)
-{
- IMM *io;
-
- io = m->iomem;
- io->sdcr = 1;
- io->lccr &= ~1; /* disable LCD */
- io->pcint = 0; /* disable all port C interrupts */
- io->pcso = 0;
- io->pcdir =0;
- io->pcpar = 0;
- io->pcdat = 0;
- io->papar = 0;
- io->padir = 0;
- io->paodr = 0;
- io->padat = 0;
- io->pbpar = 0;
- io->pbdir = 0;
- io->pbodr = 0;
- io->pbdat = 0;
- eieio();
-
- for(io->cpcr = 0x8001; io->cpcr & 1;) /* reset all CPM channels */
- eieio();
-
- mapinit(&bdmap, bdmapv, sizeof(bdmapv));
- mapfree(&bdmap, DPBASE, BDSIZE);
-}
-
-void
-cpmop(int op, int cno, int param)
-{
- IMM *io;
- int s;
-
- s = splhi();
- io = m->iomem;
- eieio();
- while(io->cpcr & 1)
- eieio();
- io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1;
- eieio();
- while(io->cpcr & 1)
- eieio();
- splx(s);
-}
-
-/*
- * connect SCCx clocks in NSMI mode (x=1 for USB)
- */
-void
-sccnmsi(int x, int rcs, int tcs)
-{
- IMM *io;
- ulong v;
- int sh;
-
- sh = (x-1)*8; /* each SCCx field in sicr is 8 bits */
- v = (((rcs&7)<<3) | (tcs&7)) << sh;
- io = ioplock();
- io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
- iopunlock();
-}
-
-void
-scc2stop(void)
-{
- SCC *scc;
-
- scc = IOREGS(0xA20, SCC);
- if(scc->gsmrl & (3<<4)){
- cpmop(GracefulStopTx, SCC2ID, 0);
- cpmop(CloseRxBD, SCC2ID, 0);
- delay(1);
- scc->gsmrl &= ~(3<<4); /* disable current use */
- archetherdisable(SCC2ID);
- }
-}
-
-BD *
-bdalloc(int n)
-{
- ulong a;
-
- a = mapalloc(&bdmap, 0, n*sizeof(BD), 0);
- if(a == 0)
- panic("bdalloc");
- return KADDR(a);
-}
-
-void
-bdfree(BD *b, int n)
-{
- if(b){
- eieio();
- mapfree(&bdmap, PADDR(b), n*sizeof(BD));
- }
-}
-
-/*
- * initialise receive and transmit buffer rings.
- */
-int
-ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
-{
- int i, x;
-
- /* the ring entries must be aligned on sizeof(BD) boundaries */
- r->nrdre = nrdre;
- if(r->rdr == nil)
- r->rdr = bdalloc(nrdre);
- /* the buffer size must align with cache lines since the cache doesn't snoop */
- bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1);
- if(r->rrb == nil)
- r->rrb = malloc(nrdre*bufsize);
- if(r->rdr == nil || r->rrb == nil)
- return -1;
- dcflush(r->rrb, nrdre*bufsize);
- x = PADDR(r->rrb);
- for(i = 0; i < nrdre; i++){
- r->rdr[i].length = 0;
- r->rdr[i].addr = x;
- r->rdr[i].status = BDEmpty|BDInt;
- x += bufsize;
- }
- r->rdr[i-1].status |= BDWrap;
- r->rdrx = 0;
-
- r->ntdre = ntdre;
- if(r->tdr == nil)
- r->tdr = bdalloc(ntdre);
- if(r->txb == nil)
- r->txb = malloc(ntdre*sizeof(Block*));
- if(r->tdr == nil || r->txb == nil)
- return -1;
- for(i = 0; i < ntdre; i++){
- r->txb[i] = nil;
- r->tdr[i].addr = 0;
- r->tdr[i].length = 0;
- r->tdr[i].status = 0;
- }
- r->tdr[i-1].status |= BDWrap;
- r->tdrh = 0;
- r->tdri = 0;
- r->ntq = 0;
- return 0;
-}
--- a/os/boot/mpc/crc32.c
+++ /dev/null
@@ -1,42 +1,0 @@
-#include "boot.h"
-
-/*
- * from Rob Warnock
- */
-static ulong crc32tab[256]; /* initialised on first call to crc32 */
-
-enum {
- CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
-};
-
-/*
- * Build auxiliary table for parallel byte-at-a-time CRC-32.
- */
-static void
-initcrc32(void)
-{
- int i, j;
- ulong c;
-
- for(i = 0; i < 256; i++) {
- for(c = i << 24, j = 8; j > 0; j--)
- if(c & (1<<31))
- c = (c<<1) ^ CRC32POLY;
- else
- c <<= 1;
- crc32tab[i] = c;
- }
-}
-
-ulong
-crc32(void *buf, int n, ulong crc)
-{
- uchar *p;
-
- if(crc32tab[1] == 0)
- initcrc32();
- crc = ~crc;
- for(p = buf; --n >= 0;)
- crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
- return ~crc;
-}
--- a/os/boot/mpc/dat.h
+++ /dev/null
@@ -1,217 +1,0 @@
-typedef struct Alarm Alarm;
-typedef struct Block Block;
-typedef struct IMM IMM;
-typedef struct Queue Queue;
-
-typedef struct List {
- void *next;
-} List;
-
-typedef struct {
- int fake;
- int pri;
-} Lock;
-#define lock(x)
-#define unlock(x)
-
-struct Alarm {
- List;
- int busy;
- long dt;
- void (*f)(Alarm*);
- void *arg;
-};
-
-enum {
- Eaddrlen = 6,
- ETHERMINTU = 60, /* minimum transmit size */
- ETHERMAXTU = 1514, /* maximum transmit size */
- ETHERHDRSIZE = 14, /* size of an ethernet header */
-
- MaxEther = 4,
-};
-
-typedef struct {
- uchar d[Eaddrlen];
- uchar s[Eaddrlen];
- uchar type[2];
- uchar data[1500];
- uchar crc[4];
-} Etherpkt;
-
-extern uchar broadcast[Eaddrlen];
-
-enum {
- Npart = 20+2, /* 8 sub partitions, disk, and partition */
- Maxxfer = 16*1024, /* maximum transfer size/cmd */
-};
-
-typedef struct {
- ulong start;
- ulong end;
- char name[NAMELEN+1];
-} Partition;
-
-typedef struct {
- int online;
- int npart; /* number of real partitions */
- Partition p[Npart];
- ulong offset;
- Partition *current; /* current partition */
-
- ulong cap; /* total bytes */
- int bytes; /* bytes/sector */
- int sectors; /* sectors/track */
- int heads; /* heads/cyl */
- long cyl; /* cylinders/drive */
-
- char lba; /* true if drive has logical block addressing */
- char multi; /* non-zero if drive does multiple block xfers */
-} Disc;
-
-enum {
- ScsiTestunit = 0x00,
- ScsiExtsens = 0x03,
- ScsiInquiry = 0x12,
- ScsiModesense = 0x1a,
- ScsiStartunit = 0x1B,
- ScsiStopunit = 0x1B,
- ScsiGetcap = 0x25,
- ScsiRead = 0x08,
- ScsiWrite = 0x0a,
- ScsiExtread = 0x28,
- ScsiExtwrite = 0x2a,
-
- /* data direction */
- ScsiIn = 1,
- ScsiOut = 0,
-};
-
-typedef struct Scsibuf Scsibuf;
-typedef struct Scsibuf {
- void* virt;
- void* phys;
- Scsibuf* next;
-};
-
-typedef struct Scsidata {
- uchar* base;
- uchar* lim;
- uchar* ptr;
-} Scsidata;
-
-typedef struct Ureg Ureg;
-
-typedef struct Scsi {
- ulong pid;
- ushort target;
- ushort lun;
- ushort rflag;
- ushort status;
- Scsidata cmd;
- Scsidata data;
- Scsibuf* b;
- uchar* save;
- uchar cmdblk[16];
-} Scsi;
-
-typedef struct Segdesc {
- ulong d0;
- ulong d1;
-} Segdesc;
-
-typedef struct Mach {
- ulong ticks; /* of the clock since boot time */
- ulong delayloop;
- long cpuhz; /* general system clock (cycles) */
- long clockgen; /* clock generator frequency (cycles) */
- ulong cpupvr; /* cpu type in processor version register */
- ulong cputype; /* cpu variant in BCD (eg, 0x823xx) */
- void* alarm; /* alarms bound to this clock */
- ulong* bcsr;
- IMM* iomem;
-} Mach;
-
-/* Mach.cputype */
-#define MPCREV(x) ((x) & 0xFF)
-#define MPCMODEL(x) (((x)>>8) & 0xFFF)
-#define MPCFAMILY(x) (((x)>>24) & 0x0F)
-
-
-extern Mach *m;
-
-#define Q_MAGIC ((((4*21)+0)*21)+7)
-
-typedef struct Exec Exec;
-struct Exec
-{
- uchar magic[4]; /* magic number */
- uchar text[4]; /* size of text segment */
- uchar data[4]; /* size of initialized data */
- uchar bss[4]; /* size of uninitialized data */
- uchar syms[4]; /* size of symbol table */
- uchar entry[4]; /* entry point */
- uchar spsz[4]; /* size of sp/pc offset table */
- uchar pcsz[4]; /* size of pc/line number table */
-};
-
-/*
- * bootline passed by boot program
- */
-#define BOOTLINE ((char *)0x200000-150)
-
-/*
- * Where we leave configuration info.
- */
-#define BOOTARGS ((char*)(0x200000))
-#define BOOTARGSLEN 1024
-#define MAXCONF 32
-
-/*
- * a parsed plan9.ini line
- */
-#define ISAOPTLEN 16
-#define NISAOPT 8
-
-typedef struct ISAConf {
- char type[NAMELEN];
- ulong port;
- ulong irq;
- ulong mem;
- ulong size;
- uchar ea[6];
-
- int nopt;
- char opt[NISAOPT][ISAOPTLEN];
-} ISAConf;
-
-typedef struct {
- int size;
- ulong addr;
-} Map;
-
-typedef struct {
- char* name;
- Map* map;
- Map* mapend;
-
- Lock;
-} RMap;
-
-typedef struct PCIcfg PCIcfg;
-
-extern uchar* vgamem;
-
-struct Block {
- uchar *rp;
- uchar *wp;
- uchar *lim;
- uchar *data;
- Block* next;
- ulong magic;
-};
-#define BLEN(b) ((b)->wp-(b)->rp)
-
-typedef struct QLock {
- int dummy;
-} QLock;
--- a/os/boot/mpc/defont0.c
+++ /dev/null
@@ -1,216 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <libg.h>
-#include <gnot.h>
-
-
-
-static ulong bits0[] = {
- 0x907070f0, 0xf0f07000, 0xf0888888, 0xf8707070, 0xe0e0e0e0, 0xe09070f0, 0x70f870f0, 0xf870f088,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000e0,
- 0xd0808080, 0x80808800, 0x8888c888, 0x80888888, 0x90909090, 0x90d08080, 0x80808080, 0x80888888,
- 0x00000000, 0x08000000, 0x0c300000, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000003c, 0xc03c0000,
- 0x00006000, 0x06001e00, 0x60181860, 0x78000000, 0x00000000, 0x00000000, 0x0000001c, 0x18380090,
- 0xb06060e0, 0xe0e0f800, 0xf088a888, 0x80808080, 0x90909090, 0x90b060e0, 0x808060e0, 0x80808888,
- 0x00182428, 0x3e707018, 0x18180000, 0x00000006, 0x3c183c3c, 0x1c3e3c7e, 0x3c3c0000, 0x0200403c,
- 0x3c187c1e, 0x787e7e1e, 0x663c7c66, 0x6066623c, 0x7c3c7c3c, 0x7e6266c2, 0x66667e30, 0xc00c1000,
- 0x08006000, 0x06003000, 0x60181860, 0x18000000, 0x00000000, 0x10000000, 0x00000030, 0x180c0090,
- 0x90101080, 0x80808818, 0x88f8a888, 0xe0807070, 0xe0e0e0e0, 0xe0901080, 0x70e01080, 0xe098f088,
- 0x00182428, 0x6adad818, 0x18181000, 0x0000000c, 0x66386666, 0x2c3e667e, 0x66660000, 0x06006066,
- 0x42186632, 0x6c606032, 0x66181864, 0x60667224, 0x66246666, 0x186262da, 0x62620630, 0x600c3800,
- 0x10006000, 0x06003000, 0x60000060, 0x18000000, 0x00000000, 0x30000000, 0x00000030, 0x180c00e0,
- 0x00e0e0f0, 0xf0f00018, 0x88889850, 0x80880808, 0x201c1c1c, 0x1c00e0f0, 0x0080e0f0, 0x80888888,
- 0x00182428, 0x68dad808, 0x300c5418, 0x0000000c, 0x66580606, 0x2c206002, 0x66661818, 0x0cfe3006,
- 0x9e2c6660, 0x66606060, 0x6618186c, 0x60667266, 0x66666660, 0x186262da, 0x36660c30, 0x600c2800,
- 0x103c6c3c, 0x3e3c7e3e, 0x6c787866, 0x18d46c3c, 0x6c3e763c, 0x7e6666c2, 0x66667e18, 0x18180000,
- 0x44180000, 0x18241c24, 0xf0888820, 0x8070f0f0, 0x20202020, 0x201c243e, 0x1cf8241c, 0x80708870,
- 0x0018247c, 0x78745008, 0x300c3818, 0x00000018, 0x66180606, 0x4c206006, 0x76661818, 0x18fe180c,
- 0xb62c6660, 0x66606060, 0x66181868, 0x607e5a66, 0x66666470, 0x186266da, 0x34340c30, 0x300c6c00,
- 0x18667666, 0x66663066, 0x76181864, 0x18fe7666, 0x76663666, 0x306662da, 0x62620608, 0x1810323c,
- 0x44247c7c, 0x24342042, 0x00000000, 0x00000000, 0x20202020, 0x20222408, 0x22002420, 0x00000000,
- 0x00180028, 0x3c287610, 0x300cee7e, 0x00fe0018, 0x66180c18, 0x4c3c7c0c, 0x3c3e0000, 0x30000c18,
- 0xb62c7c60, 0x667c7c6e, 0x7e181878, 0x605a5a66, 0x6466783c, 0x186234da, 0x18341830, 0x300c4400,
- 0x18066660, 0x66663066, 0x66181868, 0x18d66666, 0x66663860, 0x306662da, 0x34620c30, 0x180c5a20,
- 0x44241010, 0x242c2042, 0x0e3e103e, 0x3e3c1c3e, 0x3c1c1c1c, 0x1c3e1c08, 0x3e222418, 0x0e0e0e0e,
- 0x0008007c, 0x1e5cdc00, 0x300c387e, 0x00fe0030, 0x66181806, 0x7e066618, 0x6e060000, 0x18001818,
- 0xb67e6660, 0x66606066, 0x6618186c, 0x605a4e66, 0x78666c0e, 0x1862346c, 0x2c183030, 0x180c4400,
- 0x003e6660, 0x667e3066, 0x66181878, 0x18d66666, 0x6666303c, 0x306634da, 0x18341808, 0x18104c38,
- 0x3c181010, 0x18241c42, 0x11081008, 0x20222208, 0x00000000, 0x00220408, 0x22361804, 0x11111111,
- 0x00000028, 0x16b6cc00, 0x300c5418, 0x00000030, 0x66183006, 0x7e066618, 0x66060000, 0x0cfe3000,
- 0x9a466660, 0x66606066, 0x6618186c, 0x605a4e66, 0x60666606, 0x1862346c, 0x6c183030, 0x180c0000,
- 0x00666660, 0x66603066, 0x6618186c, 0x18d66666, 0x66663006, 0x3066346c, 0x2c343018, 0x18180020,
- 0x00091010, 0x000e0942, 0x10081008, 0x20222208, 0x0f06060f, 0x0a09041e, 0x002a0e38, 0x10101010,
- 0x00180028, 0x56b6cc00, 0x300c1018, 0x18001860, 0x66187e66, 0x0c666630, 0x66661818, 0x06fe6018,
- 0x40466632, 0x6c606036, 0x66181866, 0x605a4624, 0x60246666, 0x1834186c, 0x46186030, 0x0c0c0000,
- 0x006e6666, 0x6e66306e, 0x66181866, 0x18d66666, 0x666e3066, 0x306e186c, 0x46186030, 0x180c003c,
- 0x08090909, 0x1f110aff, 0x0e081008, 0x382c2208, 0x08020901, 0x0a0a0911, 0x09220907, 0x0e0e0e0e,
- 0x00180028, 0x7c1c7600, 0x18180000, 0x18001860, 0x3c7e7e3c, 0x0c3c3c30, 0x3c3c1818, 0x02004018,
- 0x3e467c1e, 0x787e601e, 0x663c1866, 0x7e42463c, 0x603c663c, 0x1818186c, 0x66187e30, 0x0c0c0000,
- 0x00367c3c, 0x363c7c36, 0x667e1866, 0x7ed6663c, 0x7c367c3c, 0x1e36186c, 0x66187e30, 0x180c0008,
- 0x080f0606, 0x04110c18, 0x01081008, 0x20222208, 0x0e020203, 0x0a0c0d1e, 0x0d220e08, 0x01010101,
- 0x00000000, 0x10000000, 0x18180000, 0x080000c0, 0x00000000, 0x00000000, 0x00000008, 0x00000000,
- 0x00000000, 0x00000000, 0x00001800, 0x00000000, 0x000c0000, 0x00000000, 0x00000030, 0x060c00fe,
- 0x00000000, 0x00000006, 0x00001800, 0x00000000, 0x60060000, 0x00000000, 0x0010001c, 0x18380008,
- 0x08090606, 0x040e0a18, 0x11081f08, 0x20221c3e, 0x08020401, 0x0f0a0b11, 0x0b220908, 0x11111111,
- 0x00000000, 0x00000000, 0x0c300000, 0x080000c0, 0x00000000, 0x00000000, 0x00000008, 0x00000000,
- 0x00000000, 0x00000000, 0x00007000, 0x00000000, 0x00060000, 0x00000000, 0x0000003c, 0x063c0000,
- 0x00000000, 0x00000066, 0x00001800, 0x00000000, 0x60060000, 0x00000000, 0x00300000, 0x00000008,
- 0x0f090909, 0x04030900, 0x0e000000, 0x00000000, 0x0f0f0f0f, 0x0209091e, 0x09000f07, 0x0e0e0e0e,
- 0x00000000, 0x00000000, 0x00000000, 0x10000000, 0x00000000, 0x00000000, 0x00000010, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x0000003c, 0x00007000, 0x00000000, 0x60060000, 0x00000000, 0x00600000, 0x0000000f,
-
-};
-
-static GBitmap strike0 = {
- bits0,
- 0,
- 32,
- 0,
- {0, 0, 1024, 14},
- {0, 0, 1024, 14},
-};
-
-static Fontchar info0[] = {
- { 0, 0, 14, 0, 8 },
- { 8, 0, 14, 0, 8 },
- { 16, 0, 14, 0, 8 },
- { 24, 0, 14, 0, 8 },
- { 32, 0, 14, 0, 8 },
- { 40, 0, 14, 0, 8 },
- { 48, 0, 14, 0, 8 },
- { 56, 0, 14, 0, 8 },
- { 64, 0, 14, 0, 8 },
- { 72, 0, 14, 0, 8 },
- { 80, 0, 14, 0, 8 },
- { 88, 0, 14, 0, 8 },
- { 96, 0, 14, 0, 8 },
- { 104, 0, 14, 0, 8 },
- { 112, 0, 14, 0, 8 },
- { 120, 0, 14, 0, 8 },
- { 128, 0, 14, 0, 8 },
- { 136, 0, 14, 0, 8 },
- { 144, 0, 14, 0, 8 },
- { 152, 0, 14, 0, 8 },
- { 160, 0, 14, 0, 8 },
- { 168, 0, 14, 0, 8 },
- { 176, 0, 14, 0, 8 },
- { 184, 0, 14, 0, 8 },
- { 192, 0, 14, 0, 8 },
- { 200, 0, 14, 0, 8 },
- { 208, 0, 14, 0, 8 },
- { 216, 0, 14, 0, 8 },
- { 224, 0, 14, 0, 8 },
- { 232, 0, 14, 0, 8 },
- { 240, 0, 14, 0, 8 },
- { 248, 0, 14, 0, 8 },
- { 256, 0, 0, 0, 8 },
- { 264, 2, 11, 0, 8 },
- { 272, 2, 6, 0, 8 },
- { 280, 2, 11, 0, 8 },
- { 288, 1, 12, 0, 8 },
- { 296, 2, 11, 0, 8 },
- { 304, 2, 11, 0, 8 },
- { 312, 2, 7, 0, 8 },
- { 320, 1, 13, 0, 8 },
- { 328, 1, 13, 0, 8 },
- { 336, 3, 10, 0, 8 },
- { 344, 4, 10, 0, 8 },
- { 352, 9, 14, 0, 8 },
- { 360, 6, 8, 0, 8 },
- { 368, 9, 11, 0, 8 },
- { 376, 1, 13, 0, 8 },
- { 384, 2, 11, 0, 8 },
- { 392, 2, 11, 0, 8 },
- { 400, 2, 11, 0, 8 },
- { 408, 2, 11, 0, 8 },
- { 416, 2, 11, 0, 8 },
- { 424, 2, 11, 0, 8 },
- { 432, 2, 11, 0, 8 },
- { 440, 2, 11, 0, 8 },
- { 448, 2, 11, 0, 8 },
- { 456, 2, 11, 0, 8 },
- { 464, 4, 11, 0, 8 },
- { 472, 4, 14, 0, 8 },
- { 480, 2, 11, 0, 8 },
- { 488, 4, 10, 0, 8 },
- { 496, 2, 11, 0, 8 },
- { 504, 2, 11, 0, 8 },
- { 512, 2, 11, 0, 8 },
- { 520, 2, 11, 0, 8 },
- { 528, 2, 11, 0, 8 },
- { 536, 2, 11, 0, 8 },
- { 544, 2, 11, 0, 8 },
- { 552, 2, 11, 0, 8 },
- { 560, 2, 11, 0, 8 },
- { 568, 2, 11, 0, 8 },
- { 576, 2, 11, 0, 8 },
- { 584, 2, 11, 0, 8 },
- { 592, 2, 13, 0, 8 },
- { 600, 2, 11, 0, 8 },
- { 608, 2, 11, 0, 8 },
- { 616, 2, 11, 0, 8 },
- { 624, 2, 11, 0, 8 },
- { 632, 2, 11, 0, 8 },
- { 640, 2, 11, 0, 8 },
- { 648, 2, 13, 0, 8 },
- { 656, 2, 11, 0, 8 },
- { 664, 2, 11, 0, 8 },
- { 672, 2, 11, 0, 8 },
- { 680, 2, 11, 0, 8 },
- { 688, 2, 11, 0, 8 },
- { 696, 2, 11, 0, 8 },
- { 704, 2, 11, 0, 8 },
- { 712, 2, 11, 0, 8 },
- { 720, 2, 11, 0, 8 },
- { 728, 1, 13, 0, 8 },
- { 736, 1, 13, 0, 8 },
- { 744, 1, 13, 0, 8 },
- { 752, 2, 8, 0, 8 },
- { 760, 11, 12, 0, 8 },
- { 768, 2, 7, 0, 8 },
- { 776, 4, 11, 0, 8 },
- { 784, 1, 11, 0, 8 },
- { 792, 4, 11, 0, 8 },
- { 800, 1, 11, 0, 8 },
- { 808, 4, 11, 0, 8 },
- { 816, 1, 11, 0, 8 },
- { 824, 4, 14, 0, 8 },
- { 832, 1, 11, 0, 8 },
- { 840, 1, 11, 0, 8 },
- { 848, 1, 14, 0, 8 },
- { 856, 1, 11, 0, 8 },
- { 864, 1, 11, 0, 8 },
- { 872, 4, 11, 0, 8 },
- { 880, 4, 11, 0, 8 },
- { 888, 4, 11, 0, 8 },
- { 896, 4, 14, 0, 8 },
- { 904, 4, 14, 0, 8 },
- { 912, 4, 11, 0, 8 },
- { 920, 4, 11, 0, 8 },
- { 928, 2, 11, 0, 8 },
- { 936, 4, 11, 0, 8 },
- { 944, 4, 11, 0, 8 },
- { 952, 4, 11, 0, 8 },
- { 960, 4, 11, 0, 8 },
- { 968, 4, 14, 0, 8 },
- { 976, 4, 11, 0, 8 },
- { 984, 1, 12, 0, 8 },
- { 992, 1, 12, 0, 8 },
- { 1000, 1, 12, 0, 8 },
- { 1008, 5, 8, 0, 8 },
- { 1016, 0, 14, 0, 8 },
- { 1024, 0, 14, 0, 8 },
- { 0, 0, 0, 0, 0 }
-};
-
-GSubfont defont0 = {
- 129,
- 14,
- 2,
- info0,
- &strike0,
-};
--- a/os/boot/mpc/devether.c
+++ /dev/null
@@ -1,157 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-static Ctlr ether[MaxEther];
-
-static struct {
- char *type;
- int (*reset)(Ctlr*);
-} cards[] = {
- { "SCC", sccethreset, },
- { "SCC2", sccethreset, },
- { 0, }
-};
-
-int
-etherinit(void)
-{
- Ctlr *ctlr;
- int ctlrno, i, mask, n;
-
- mask = 0;
- for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
- ctlr = ðer[ctlrno];
- memset(ctlr, 0, sizeof(Ctlr));
- if(isaconfig("ether", ctlrno, &ctlr->card) == 0)
- continue;
- for(n = 0; cards[n].type; n++){
- if(strcmp(cards[n].type, ctlr->card.type))
- continue;
- ctlr->ctlrno = ctlrno;
- if((*cards[n].reset)(ctlr))
- break;
-
- ctlr->iq = qopen(16*1024, 1, 0, 0);
- ctlr->oq = qopen(16*1024, 1, 0, 0);
-
- ctlr->present = 1;
- mask |= 1<<ctlrno;
-
- print("ether%d: %s: port 0x%luX irq %d",
- ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
- if(ctlr->card.mem)
- print(" addr 0x%luX", PADDR(ctlr->card.mem));
- if(ctlr->card.size)
- print(" size 0x%luX", ctlr->card.size);
- print(":");
- for(i = 0; i < sizeof(ctlr->card.ea); i++)
- print(" %2.2uX", ctlr->card.ea[i]);
- print("\n"); uartwait();
- setvec(VectorPIC + ctlr->card.irq, ctlr->card.intr, ctlr);
- break;
- }
- }
-
- return mask;
-}
-
-static Ctlr*
-attach(int ctlrno)
-{
- Ctlr *ctlr;
-
- if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
- return 0;
-
- ctlr = ðer[ctlrno];
- if(ctlr->present == 1){
- ctlr->present = 2;
- (*ctlr->card.attach)(ctlr);
- }
-
- return ctlr;
-}
-
-uchar*
-etheraddr(int ctlrno)
-{
- Ctlr *ctlr;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- return ctlr->card.ea;
-}
-
-int
-etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
-{
- int n;
- Ctlr *ctlr;
- Block *b;
- ulong start;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- start = m->ticks;
- while((b = qget(ctlr->iq)) == 0){
- if(TK2MS(m->ticks - start) >= timo){
- /*
- print("ether%d: rx timeout\n", ctlrno);
- */
- return 0;
- }
- }
-
- n = BLEN(b);
- memmove(pkt, b->rp, n);
- freeb(b);
-
- return n;
-}
-
-int
-etheriq(Ctlr *ctlr, Block *b, int freebp)
-{
- if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0 &&
- memcmp(((Etherpkt*)b->rp)->d, broadcast, Eaddrlen) != 0){
- if(freebp)
- freeb(b);
- return 0;
- }
- qbwrite(ctlr->iq, b);
- return 1;
-}
-
-int
-ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
-{
- Ctlr *ctlr;
- Block *b;
- int s;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- if(qlen(ctlr->oq) > 16*1024){
- print("ether%d: tx queue full\n", ctlrno);
- return 0;
- }
- b = iallocb(sizeof(Etherpkt));
- memmove(b->wp, pkt, len);
- memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
- b->wp += len;
- qbwrite(ctlr->oq, b);
- s = splhi();
- (*ctlr->card.transmit)(ctlr);
- splx(s);
-
- return 1;
-}
--- a/os/boot/mpc/devuart.c
+++ /dev/null
@@ -1,230 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-/*
- * SMC1 in UART mode
- */
-
-typedef struct Uartsmc Uartsmc;
-struct Uartsmc {
- IOCparam;
- ushort maxidl;
- ushort idlc;
- ushort brkln;
- ushort brkec;
- ushort brkcr;
- ushort rmask;
-};
-
-typedef struct Uart Uart;
-struct Uart
-{
- int port;
- int setup;
- uchar txbusy;
-
- Queue* iq;
- Queue* oq;
- void (*rx)(Queue*, int);
- void (*boot)(uchar*, int);
-
- ulong frame;
- ulong overrun;
- uchar rxbuf[128];
- char txbuf[16];
- BD* rxb;
- BD* txb;
-};
-
-Uart uart[1];
-int predawn = 1;
-
-static void uartintr(Ureg*, void*);
-static void uartkick(void*);
-
-static int
-baudgen(int baud)
-{
- int d;
-
- d = ((m->cpuhz/baud)+8)>>4;
- if(d >= (1<<12))
- return ((d+15)>>3)|1;
- return d<<1;
-}
-
-static void
-smcsetup(Uart *up, int baud)
-{
- IMM *io;
- Uartsmc *p;
- BD *bd;
- SMC *smc;
-
- archenableuart(SMC1ID, 0);
- io = m->iomem;
- io->pbpar |= IBIT(24)|IBIT(25); /* enable SMC1 TX/RX */
- io->pbdir &= ~(IBIT(24)|IBIT(25));
- io->brgc1 = baudgen(baud) | BaudEnable;
- io->simode &= ~0xF000; /* SMC1 to NMSI mode, Tx/Rx clocks are BRG1 */
-
- bd = bdalloc(1);
- p = (Uartsmc*)KADDR(SMC1P);
- p->rbase = (ushort)bd;
- up->rxb = bd;
- bd->status = BDEmpty|BDWrap|BDInt;
- bd->length = 0;
- bd->addr = PADDR(up->rxbuf);
- bd = bdalloc(1);
- p->tbase = (ushort)bd;
- up->txb = bd;
- bd->status = BDWrap|BDInt;
- bd->length = 0;
- bd->addr = PADDR(up->txbuf);
-
- cpmop(InitRxTx, SMC1ID, 0);
-
- /* protocol parameters */
- p->rfcr = 0x18;
- p->tfcr = 0x18;
- p->mrblr = 1;
- p->maxidl = 1;
- p->brkln = 0;
- p->brkec = 0;
- p->brkcr = 1;
- smc = IOREGS(0xA80, SMC);
- smc->smce = 0xff; /* clear events */
- smc->smcm = 0x17; /* enable all possible interrupts */
- setvec(VectorCPIC+4, uartintr, up);
- smc->smcmr = 0x4820; /* 8-bit mode, no parity, 1 stop bit, UART mode, ... */
- smc->smcmr |= 3; /* enable rx/tx */
-}
-
-static void
-uartintr(Ureg*, void *arg)
-{
- Uart *up;
- int ch, i;
- BD *bd;
- SMC *smc;
- Block *b;
-
- up = arg;
- smc = IOREGS(0xA80, SMC);
- smc->smce = 0xff; /* clear all events */
- if((bd = up->rxb) != nil && (bd->status & BDEmpty) == 0){
- if(up->iq != nil && bd->length > 0){
- if(up->boot != nil){
- up->boot(up->rxbuf, bd->length);
- }else if(up->rx != nil){
- for(i=0; i<bd->length; i++){
- ch = up->rxbuf[i];
- up->rx(up->iq, ch);
- }
- }else{
- b = iallocb(bd->length);
- memmove(b->wp, up->rxbuf, bd->length);
- b->wp += bd->length;
- qbwrite(up->iq, b);
- }
- }
- bd->status |= BDEmpty|BDInt;
- } else if((bd = up->txb) != nil && (bd->status & BDReady) == 0){
- ch = -1;
- if(up->oq)
- ch = qbgetc(up->oq);
- if(ch != -1){
- up->txbuf[0] = ch;
- bd->length = 1;
- bd->status |= BDReady;
- }else
- up->txbusy = 0;
- }
- /* TO DO: modem status, errors, etc */
-}
-
-static void
-uartkick(void *arg)
-{
- Uart *up = arg;
- int s, c, i;
-
- s = splhi();
- while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1){
- if(predawn){
- while(up->txb->status & BDReady)
- ;
- } else {
- for(i = 0; i < 100; i++){
- if((up->txb->status & BDReady) == 0)
- break;
- delay(1);
- }
- }
- up->txbuf[0] = c;
- up->txb->length = 1;
- up->txb->status |= BDReady;
- up->txbusy = !predawn;
- }
- splx(s);
-}
-
-void
-uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue*,int))
-{
- Uart *up = &uart[0];
-
- if(up->setup)
- return;
- up->setup = 1;
-
- *iq = up->iq = qopen(4*1024, 0, 0, 0);
- *oq = up->oq = qopen(16*1024, 0, uartkick, up);
- up->rx = rx;
- USED(port);
- up->port = SMC1ID;
- if(baud == 0)
- baud = 9600;
- smcsetup(up, baud);
- /* if using SCCn's UART, would also set DTR and RTS, but SMC doesn't use them */
-}
-
-void
-uartsetboot(void (*f)(uchar*, int))
-{
- uart[0].boot = f;
-}
-
-void
-uartputs(char *s, int n)
-{
- Uart *up = &uart[0];
- Block *b;
- int nl;
- char *p;
-
- nl = 0;
- for(p = s; p < s+n; p++)
- if(*p == '\n')
- nl++;
- b = iallocb(n+nl);
- while(n--){
- if(*s == '\n')
- *b->wp++ = '\r';
- *b->wp++ = *s++;
- }
- qbwrite(up->oq, b);
-}
-
-void
-uartwait(void)
-{
- Uart *up = &uart[0];
-
- while(up->txbusy)
- ;
-}
--- a/os/boot/mpc/dload.c
+++ /dev/null
@@ -1,103 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-static char *kernelfile = "/power/ipaq";
-ulong crc32(void *buf, int n, ulong crc);
-
-void
-main(int argc, char **argv)
-{
- int ifd, n;
- char buf[64], reply[1];
- int i, execsize;
- Fhdr f;
- ulong csum;
-
- ARGBEGIN{
- }ARGEND
- ifd = open(kernelfile, OREAD);
- if(ifd < 0){
- fprint(2, "dload: can't open %s: %r\n", kernelfile);
- exits("open");
- }
- i = 0;
- if(crackhdr(ifd, &f) == 0){
- fprint(2, "dload: not an executable file: %r\n");
- exits("format");
- }
- if(f.magic != Q_MAGIC){
- fprint(2, "dload: not a powerpc executable\n");
- exits("format");
- }
- execsize = f.txtsz + f.datsz + f.txtoff;
- seek(ifd, 0, 0);
- csum = ~0;
- while(execsize > 0 && (n = read(ifd, buf, sizeof(buf))) > 0){
- if(n > execsize)
- n = execsize;
- for(;;){
- if(write(1, buf, sizeof(buf)) != sizeof(buf)){ /* always writes full buffer */
- fprint(2, "dload: write error: %r\n");
- exits("write");
- }
- if(read(0, reply, 1) != 1){
- fprint(2, "dload: bad reply\n");
- exits("read");
- }
- if(reply[0] != 'n')
- break;
- fprint(2, "!");
- }
- if(reply[0] != 'y'){
- fprint(2, "dload: bad ack: %c\n", reply[0]);
- exits("reply");
- }
- if(++i%10 == 0)
- fprint(2, ".");
- execsize -= n;
- }
- exits(0);
-}
-
-/*
- * from Rob Warnock
- */
-static ulong crc32tab[256]; /* initialised on first call to crc32 */
-
-enum {
- CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
-};
-
-/*
- * Build auxiliary table for parallel byte-at-a-time CRC-32.
- */
-static void
-initcrc32(void)
-{
- int i, j;
- ulong c;
-
- for(i = 0; i < 256; i++) {
- for(c = i << 24, j = 8; j > 0; j--)
- if(c & (1<<31))
- c = (c<<1) ^ CRC32POLY;
- else
- c <<= 1;
- crc32tab[i] = c;
- }
-}
-
-ulong
-crc32(void *buf, int n, ulong crc)
-{
- uchar *p;
-
- if(crc32tab[1] == 0)
- initcrc32();
- crc = ~crc;
- for(p = buf; --n >= 0;)
- crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
- return ~crc;
-}
--- a/os/boot/mpc/donprint.c
+++ /dev/null
@@ -1,332 +1,0 @@
-#include "u.h"
-#include "lib.h"
-
-#define PTR sizeof(char*)
-#define SHORT sizeof(int)
-#define INT sizeof(int)
-#define LONG sizeof(long)
-#define IDIGIT 30
-#define MAXCON 30
-
-#define FLONG (1<<0)
-#define FSHORT (1<<1)
-#define FUNSIGN (1<<2)
-
-typedef struct Op Op;
-struct Op
-{
- char *p;
- char *ep;
- void *argp;
- int f1;
- int f2;
- int f3;
-};
-
-static int noconv(Op*);
-static int cconv(Op*);
-static int dconv(Op*);
-static int hconv(Op*);
-static int lconv(Op*);
-static int oconv(Op*);
-static int sconv(Op*);
-static int uconv(Op*);
-static int xconv(Op*);
-static int Xconv(Op*);
-static int percent(Op*);
-
-static
-int (*fmtconv[MAXCON])(Op*) =
-{
- noconv,
- cconv, dconv, hconv, lconv,
- oconv, sconv, uconv, xconv,
- Xconv, percent,
-};
-static
-char fmtindex[128] =
-{
- ['c'] 1,
- ['d'] 2,
- ['h'] 3,
- ['l'] 4,
- ['o'] 5,
- ['s'] 6,
- ['u'] 7,
- ['x'] 8,
- ['X'] 9,
- ['%'] 10,
-};
-
-static int convcount = { 11 };
-static int ucase;
-
-static void
-PUT(Op *o, int c)
-{
- static int pos;
- int opos;
-
- if(c == '\t'){
- opos = pos;
- pos = (opos+8) & ~7;
- while(opos++ < pos && o->p < o->ep)
- *o->p++ = ' ';
- return;
- }
- if(o->p < o->ep){
- *o->p++ = c;
- pos++;
- }
- if(c == '\n')
- pos = 0;
-}
-
-int
-fmtinstall(char c, int (*f)(Op*))
-{
-
- c &= 0177;
- if(fmtindex[c] == 0) {
- if(convcount >= MAXCON)
- return 1;
- fmtindex[c] = convcount++;
- }
- fmtconv[fmtindex[c]] = f;
- return 0;
-}
-
-char*
-donprint(char *p, char *ep, char *fmt, void *argp)
-{
- int sf1, c;
- Op o;
-
- o.p = p;
- o.ep = ep;
- o.argp = argp;
-
-loop:
- c = *fmt++;
- if(c != '%') {
- if(c == 0) {
- if(o.p < o.ep)
- *o.p = 0;
- return o.p;
- }
- PUT(&o, c);
- goto loop;
- }
- o.f1 = 0;
- o.f2 = -1;
- o.f3 = 0;
- c = *fmt++;
- sf1 = 0;
- if(c == '-') {
- sf1 = 1;
- c = *fmt++;
- }
- while(c >= '0' && c <= '9') {
- o.f1 = o.f1*10 + c-'0';
- c = *fmt++;
- }
- if(sf1)
- o.f1 = -o.f1;
- if(c != '.')
- goto l1;
- c = *fmt++;
- while(c >= '0' && c <= '9') {
- if(o.f2 < 0)
- o.f2 = 0;
- o.f2 = o.f2*10 + c-'0';
- c = *fmt++;
- }
-l1:
- if(c == 0)
- fmt--;
- c = (*fmtconv[fmtindex[c&0177]])(&o);
- if(c < 0) {
- o.f3 |= -c;
- c = *fmt++;
- goto l1;
- }
- o.argp = (char*)o.argp + c;
- goto loop;
-}
-
-void
-strconv(char *o, Op *op, int f1, int f2)
-{
- int n, c;
- char *p;
-
- n = strlen(o);
- if(f1 >= 0)
- while(n < f1) {
- PUT(op, ' ');
- n++;
- }
- for(p=o; c = *p++;)
- if(f2 != 0) {
- PUT(op, c);
- f2--;
- }
- if(f1 < 0) {
- f1 = -f1;
- while(n < f1) {
- PUT(op, ' ');
- n++;
- }
- }
-}
-
-int
-numbconv(Op *op, int base)
-{
- char b[IDIGIT];
- int i, f, n, r;
- long v;
- short h;
-
- f = 0;
- switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
- case FLONG:
- v = *(long*)op->argp;
- r = LONG;
- break;
-
- case FUNSIGN|FLONG:
- v = *(ulong*)op->argp;
- r = LONG;
- break;
-
- case FSHORT:
- h = *(int*)op->argp;
- v = h;
- r = SHORT;
- break;
-
- case FUNSIGN|FSHORT:
- h = *(int*)op->argp;
- v = (ushort)h;
- r = SHORT;
- break;
-
- default:
- v = *(int*)op->argp;
- r = INT;
- break;
-
- case FUNSIGN:
- v = *(unsigned*)op->argp;
- r = INT;
- break;
- }
- if(!(op->f3 & FUNSIGN) && v < 0) {
- v = -v;
- f = 1;
- }
- b[IDIGIT-1] = 0;
- for(i = IDIGIT-2;; i--) {
- n = (ulong)v % base;
- n += '0';
- if(n > '9'){
- n += 'a' - ('9'+1);
- if(ucase)
- n += 'A'-'a';
- }
- b[i] = n;
- if(i < 2)
- break;
- v = (ulong)v / base;
- if(op->f2 >= 0 && i >= IDIGIT-op->f2)
- continue;
- if(v <= 0)
- break;
- }
- if(f)
- b[--i] = '-';
- strconv(b+i, op, op->f1, -1);
- return r;
-}
-
-static int
-noconv(Op *op)
-{
-
- strconv("***", op, 0, -1);
- return 0;
-}
-
-static int
-cconv(Op *op)
-{
- char b[2];
-
- b[0] = *(int*)op->argp;
- b[1] = 0;
- strconv(b, op, op->f1, -1);
- return INT;
-}
-
-static int
-dconv(Op *op)
-{
- return numbconv(op, 10);
-}
-
-static int
-hconv(Op*)
-{
- return -FSHORT;
-}
-
-static int
-lconv(Op*)
-{
- return -FLONG;
-}
-
-static int
-oconv(Op *op)
-{
- return numbconv(op, 8);
-}
-
-static int
-sconv(Op *op)
-{
- strconv(*(char**)op->argp, op, op->f1, op->f2);
- return PTR;
-}
-
-static int
-uconv(Op*)
-{
- return -FUNSIGN;
-}
-
-static int
-xconv(Op *op)
-{
- return numbconv(op, 16);
-}
-
-static int
-Xconv(Op *op)
-{
- int r;
-
- ucase = 1;
- r = numbconv(op, 16);
- ucase = 0;
- return r;
-}
-
-static int
-percent(Op *op)
-{
-
- PUT(op, '%');
- return 0;
-}
--- a/os/boot/mpc/dosboot.c
+++ /dev/null
@@ -1,614 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "dosfs.h"
-
-extern char *premature;
-
-/*
- * predeclared
- */
-static void bootdump(Dosboot*);
-static void setname(Dosfile*, char*);
-long dosreadseg(Dosfile*, long, long);
-
-/*
- * debugging
- */
-#define chatty 1
-#define chat if(chatty)print
-
-/*
- * block io buffers
- */
-enum
-{
- Nbio= 16,
-};
-typedef struct Clustbuf Clustbuf;
-struct Clustbuf
-{
- int age;
- long sector;
- uchar *iobuf;
- Dos *dos;
- int size;
-};
-Clustbuf bio[Nbio];
-
-/*
- * get an io block from an io buffer
- */
-Clustbuf*
-getclust(Dos *dos, long sector)
-{
- Clustbuf *p, *oldest;
- int size;
-
- chat("getclust @ %d\n", sector);
-
- /*
- * if we have it, just return it
- */
- for(p = bio; p < &bio[Nbio]; p++){
- if(sector == p->sector && dos == p->dos){
- p->age = m->ticks;
- chat("getclust %d in cache\n", sector);
- return p;
- }
- }
-
- /*
- * otherwise, reuse the oldest entry
- */
- oldest = bio;
- for(p = &bio[1]; p < &bio[Nbio]; p++){
- if(p->age <= oldest->age)
- oldest = p;
- }
- p = oldest;
-
- /*
- * make sure the buffer is big enough
- */
- size = dos->clustsize*dos->sectsize;
- if(p->iobuf==0 || p->size < size)
- p->iobuf = ialloc(size, 0);
- p->size = size;
-
- /*
- * read in the cluster
- */
- chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
- if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
- chat("can't seek block\n");
- return 0;
- }
- if((*dos->read)(dos->dev, p->iobuf, size) != size){
- chat("can't read block\n");
- return 0;
- }
-
- p->age = m->ticks;
- p->dos = dos;
- p->sector = sector;
- chat("getclust %d read\n", sector);
- return p;
-}
-
-/*
- * walk the fat one level ( n is a current cluster number ).
- * return the new cluster number or -1 if no more.
- */
-static long
-fatwalk(Dos *dos, int n)
-{
- ulong k, sect;
- Clustbuf *p;
- int o;
-
- chat("fatwalk %d\n", n);
-
- if(n < 2 || n >= dos->fatclusters)
- return -1;
-
- switch(dos->fatbits){
- case 12:
- k = (3*n)/2; break;
- case 16:
- k = 2*n; break;
- default:
- return -1;
- }
- if(k >= dos->fatsize*dos->sectsize)
- panic("getfat");
-
- sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
- o = k%(dos->sectsize*dos->clustsize);
- p = getclust(dos, sect);
- k = p->iobuf[o++];
- if(o >= dos->sectsize*dos->clustsize){
- p = getclust(dos, sect+dos->clustsize);
- o = 0;
- }
- k |= p->iobuf[o]<<8;
- if(dos->fatbits == 12){
- if(n&1)
- k >>= 4;
- else
- k &= 0xfff;
- if(k >= 0xff8)
- k |= 0xf000;
- }
- k = k < 0xfff8 ? k : -1;
- chat("fatwalk %d -> %d\n", n, k);
- return k;
-}
-
-/*
- * map a file's logical cluster address to a physical sector address
- */
-static long
-fileaddr(Dosfile *fp, long ltarget)
-{
- Dos *dos = fp->dos;
- long l;
- long p;
-
- chat("fileaddr %8.8s %d\n", fp->name, ltarget);
- /*
- * root directory is contiguous and easy
- */
- if(fp->pstart == 0){
- if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
- return -1;
- l = dos->rootaddr + ltarget*dos->clustsize;
- chat("fileaddr %d -> %d\n", ltarget, l);
- return l;
- }
-
- /*
- * anything else requires a walk through the fat
- */
- if(ltarget >= fp->lcurrent && fp->pcurrent){
- /* start at the currrent point */
- l = fp->lcurrent;
- p = fp->pcurrent;
- } else {
- /* go back to the beginning */
- l = 0;
- p = fp->pstart;
- }
- while(l != ltarget){
- /* walk the fat */
- p = fatwalk(dos, p);
- if(p < 0)
- return -1;
- l++;
- }
- fp->lcurrent = l;
- fp->pcurrent = p;
-
- /*
- * clusters start at 2 instead of 0 (why? - presotto)
- */
- l = dos->dataaddr + (p-2)*dos->clustsize;
- chat("fileaddr %d -> %d\n", ltarget, l);
- return l;
-}
-
-/*
- * read from a dos file
- */
-long
-dosread(Dosfile *fp, void *a, long n)
-{
- long addr;
- long rv;
- int i;
- int off;
- Clustbuf *p;
- uchar *from, *to;
-
- if((fp->attr & DDIR) == 0){
- if(fp->offset >= fp->length)
- return 0;
- if(fp->offset+n > fp->length)
- n = fp->length - fp->offset;
- }
-
- to = a;
- for(rv = 0; rv < n; rv+=i){
- /*
- * read the cluster
- */
- addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
- if(addr < 0)
- return -1;
- p = getclust(fp->dos, addr);
- if(p == 0)
- return -1;
-
- /*
- * copy the bytes we need
- */
- off = fp->offset % fp->dos->clustbytes;
- from = &p->iobuf[off];
- i = n - rv;
- if(i > fp->dos->clustbytes - off)
- i = fp->dos->clustbytes - off;
- memmove(to, from, i);
- to += i;
- fp->offset += i;
- }
-
- return rv;
-}
-
-/*
- * walk a directory returns
- * -1 if something went wrong
- * 0 if not found
- * 1 if found
- */
-int
-doswalk(Dosfile *file, char *name)
-{
- Dosdir d;
- long n;
-
- if((file->attr & DDIR) == 0){
- chat("walking non-directory!\n");
- return -1;
- }
-
- setname(file, name);
-
- file->offset = 0; /* start at the beginning */
- while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
- chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
- if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
- continue;
- if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
- continue;
- if(d.attr & DVLABEL){
- chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
- continue;
- }
- file->attr = d.attr;
- file->pstart = GSHORT(d.start);
- file->length = GLONG(d.length);
- file->pcurrent = 0;
- file->lcurrent = 0;
- file->offset = 0;
- return 1;
- }
- return n >= 0 ? 0 : -1;
-}
-
-
-/*
- * instructions that boot blocks can start with
- */
-#define JMPSHORT 0xeb
-#define JMPNEAR 0xe9
-
-/*
- * read dos file system properties
- */
-int
-dosinit(Dos *dos, int start, int ishard)
-{
- Dosboot *b;
- int i;
- Clustbuf *p;
- Dospart *dp;
- ulong mbroffset, offset;
-
- /* defaults till we know better */
- dos->start = start;
- dos->sectsize = 512;
- dos->clustsize = 1;
- mbroffset = 0;
-
-dmddo:
- /* get first sector */
- p = getclust(dos, mbroffset);
- if(p == 0){
- chat("can't read boot block\n");
- return -1;
- }
-
- /*
- * If it's a hard disc then look for an MBR and pick either an
- * active partition or the FAT with the lowest starting LBA.
- * Things are tricky because we could be pointing to, amongst others:
- * 1) a floppy BPB;
- * 2) a hard disc MBR;
- * 3) a hard disc extended partition table;
- * 4) a logical drive on a hard disc;
- * 5) a disc-manager boot block.
- * They all have the same magic at the end of the block.
- */
- if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
- chat("not DOS\n");
- return -1;
- }
- p->dos = 0;
- b = (Dosboot *)p->iobuf;
- if(ishard && b->mediadesc != 0xF8){
- dp = (Dospart*)&p->iobuf[0x1BE];
- offset = 0xFFFFFFFF;
- for(i = 0; i < 4; i++, dp++){
- if(dp->type == DMDDO){
- mbroffset = 63;
- goto dmddo;
- }
- if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
- continue;
- if(dp->flag & 0x80){
- offset = GLONG(dp->start);
- break;
- }
- if(GLONG(dp->start) < offset)
- offset = GLONG(dp->start);
- }
- if(i != 4 || offset != 0xFFFFFFFF){
- dos->start = mbroffset+offset;
- p = getclust(dos, 0);
- if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
- return -1;
- }
- p->dos = 0;
- }
-
- b = (Dosboot *)p->iobuf;
- if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
- chat("no dos file system\n");
- return -1;
- }
-
- if(chatty)
- bootdump(b);
-
- /*
- * determine the systems' wondersous properties
- */
- dos->sectsize = GSHORT(b->sectsize);
- dos->clustsize = b->clustsize;
- dos->clustbytes = dos->sectsize*dos->clustsize;
- dos->nresrv = GSHORT(b->nresrv);
- dos->nfats = b->nfats;
- dos->rootsize = GSHORT(b->rootsize);
- dos->volsize = GSHORT(b->volsize);
- if(dos->volsize == 0)
- dos->volsize = GLONG(b->bigvolsize);
- dos->mediadesc = b->mediadesc;
- dos->fatsize = GSHORT(b->fatsize);
- dos->fataddr = dos->nresrv;
- dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
- i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
- i = i/dos->sectsize;
- dos->dataaddr = dos->rootaddr + i;
- dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
- if(dos->fatclusters < 4087)
- dos->fatbits = 12;
- else
- dos->fatbits = 16;
- dos->freeptr = 2;
-
- /*
- * set up the root
- */
- dos->root.dos = dos;
- dos->root.pstart = 0;
- dos->root.pcurrent = dos->root.lcurrent = 0;
- dos->root.offset = 0;
- dos->root.attr = DDIR;
- dos->root.length = dos->rootsize*sizeof(Dosdir);
-
- return 0;
-}
-
-static void
-bootdump(Dosboot *b)
-{
- if(chatty == 0)
- return;
- print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
- b->magic[0], b->magic[1], b->magic[2]);
- print("version: \"%8.8s\"\n", b->version);
- print("sectsize: %d\n", GSHORT(b->sectsize));
- print("allocsize: %d\n", b->clustsize);
- print("nresrv: %d\n", GSHORT(b->nresrv));
- print("nfats: %d\n", b->nfats);
- print("rootsize: %d\n", GSHORT(b->rootsize));
- print("volsize: %d\n", GSHORT(b->volsize));
- print("mediadesc: 0x%2.2x\n", b->mediadesc);
- print("fatsize: %d\n", GSHORT(b->fatsize));
- print("trksize: %d\n", GSHORT(b->trksize));
- print("nheads: %d\n", GSHORT(b->nheads));
- print("nhidden: %d\n", GLONG(b->nhidden));
- print("bigvolsize: %d\n", GLONG(b->bigvolsize));
- print("driveno: %d\n", b->driveno);
- print("reserved0: 0x%2.2x\n", b->reserved0);
- print("bootsig: 0x%2.2x\n", b->bootsig);
- print("volid: 0x%8.8x\n", GLONG(b->volid));
- print("label: \"%11.11s\"\n", b->label);
-}
-
-/*
- * grab next element from a path, return the pointer to unprocessed portion of
- * path.
- */
-static char *
-nextelem(char *path, char *elem)
-{
- int i;
-
- while(*path == '/')
- path++;
- if(*path==0 || *path==' ')
- return 0;
- for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
- if(i==28){
- print("name component too long\n");
- return 0;
- }
- *elem++ = *path++;
- }
- *elem = '\0';
- return path;
-}
-
-int
-dosstat(Dos *dos, char *path, Dosfile *f)
-{
- char element[NAMELEN];
-
- *f = dos->root;
- while(path = nextelem(path, element)){
- switch(doswalk(f, element)){
- case -1:
- return -1;
- case 0:
- return 0;
- }
- }
- return 1;
-}
-
-/*
- * boot
- */
-int
-dosboot(Dos *dos, char *path)
-{
- Dosfile file;
- long n;
- long addr;
- Exec *ep;
- void (*b)(void);
-
- switch(dosstat(dos, path, &file)){
-
- case -1:
- print("error walking to %s\n", path);
- return -1;
- case 0:
- print("%s not found\n", path);
- return -1;
- case 1:
- print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
- file.ext, file.attr, file.pstart, file.length);
- break;
- }
-
- /*
- * read header
- */
- ep = (Exec*)ialloc(sizeof(Exec), 0);
- n = sizeof(Exec);
- if(dosreadseg(&file, n, (ulong) ep) != n){
- print(premature);
- return -1;
- }
- if(GLLONG(ep->magic) != Q_MAGIC){
- print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
- return -1;
- }
-
- /*
- * read text
- */
- addr = PADDR(GLLONG(ep->entry));
- n = GLLONG(ep->text);
- print("+%d", n);
- if(dosreadseg(&file, n, addr) != n){
- print(premature);
- return -1;
- }
-
- /*
- * read data (starts at first page after kernel)
- */
- addr = PGROUND(addr+n);
- n = GLLONG(ep->data);
- print("+%d", n);
- if(dosreadseg(&file, n, addr) != n){
- print(premature);
- return -1;
- }
-
- /*
- * bss and entry point
- */
- print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
-
- /*
- * Go to new code. It's up to the program to get its PC relocated to
- * the right place.
- */
- b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
- (*b)();
- return 0;
-}
-
-/*
- * read in a segment
- */
-long
-dosreadseg(Dosfile *fp, long len, long addr)
-{
- char *a;
- long n, sofar;
-
- a = (char *)addr;
- for(sofar = 0; sofar < len; sofar += n){
- n = 8*1024;
- if(len - sofar < n)
- n = len - sofar;
- n = dosread(fp, a + sofar, n);
- if(n <= 0)
- break;
- print(".");
- }
- return sofar;
-}
-
-/*
- * set up a dos file name
- */
-static void
-setname(Dosfile *fp, char *from)
-{
- char *to;
-
- to = fp->name;
- for(; *from && to-fp->name < 8; from++, to++){
- if(*from == '.'){
- from++;
- break;
- }
- if(*from >= 'a' && *from <= 'z')
- *to = *from + 'A' - 'a';
- else
- *to = *from;
- }
- while(to - fp->name < 8)
- *to++ = ' ';
-
- to = fp->ext;
- for(; *from && to-fp->ext < 3; from++, to++){
- if(*from >= 'a' && *from <= 'z')
- *to = *from + 'A' - 'a';
- else
- *to = *from;
- }
- while(to-fp->ext < 3)
- *to++ = ' ';
-
- chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
-}
--- a/os/boot/mpc/dosfs.h
+++ /dev/null
@@ -1,110 +1,0 @@
-typedef struct Dosboot Dosboot;
-typedef struct Dos Dos;
-typedef struct Dosdir Dosdir;
-typedef struct Dosfile Dosfile;
-typedef struct Dospart Dospart;
-
-struct Dospart
-{
- uchar flag; /* active flag */
- uchar shead; /* starting head */
- uchar scs[2]; /* starting cylinder/sector */
- uchar type; /* partition type */
- uchar ehead; /* ending head */
- uchar ecs[2]; /* ending cylinder/sector */
- uchar start[4]; /* starting sector */
- uchar len[4]; /* length in sectors */
-};
-
-#define FAT12 0x01
-#define FAT16 0x04
-#define FATHUGE 0x06
-#define DMDDO 0x54
-
-struct Dosboot{
- uchar magic[3];
- uchar version[8];
- uchar sectsize[2];
- uchar clustsize;
- uchar nresrv[2];
- uchar nfats;
- uchar rootsize[2];
- uchar volsize[2];
- uchar mediadesc;
- uchar fatsize[2];
- uchar trksize[2];
- uchar nheads[2];
- uchar nhidden[4];
- uchar bigvolsize[4];
- uchar driveno;
- uchar reserved0;
- uchar bootsig;
- uchar volid[4];
- uchar label[11];
- uchar reserved1[8];
-};
-
-struct Dosfile{
- Dos *dos; /* owning dos file system */
- char name[8];
- char ext[3];
- uchar attr;
- long length;
- long pstart; /* physical start cluster address */
- long pcurrent; /* physical current cluster address */
- long lcurrent; /* logical current cluster address */
- long offset;
-};
-
-struct Dos{
- int dev; /* device id */
- long (*read)(int, void*, long); /* read routine */
- long (*seek)(int, long); /* seek routine */
-
- int start; /* start of file system */
- int sectsize; /* in bytes */
- int clustsize; /* in sectors */
- int clustbytes; /* in bytes */
- int nresrv; /* sectors */
- int nfats; /* usually 2 */
- int rootsize; /* number of entries */
- int volsize; /* in sectors */
- int mediadesc;
- int fatsize; /* in sectors */
- int fatclusters;
- int fatbits; /* 12 or 16 */
- long fataddr; /* sector number */
- long rootaddr;
- long dataaddr;
- long freeptr;
-
- Dosfile root;
-};
-
-struct Dosdir{
- uchar name[8];
- uchar ext[3];
- uchar attr;
- uchar reserved[10];
- uchar time[2];
- uchar date[2];
- uchar start[2];
- uchar length[4];
-};
-
-#define DRONLY 0x01
-#define DHIDDEN 0x02
-#define DSYSTEM 0x04
-#define DVLABEL 0x08
-#define DDIR 0x10
-#define DARCH 0x20
-
-extern int chatty;
-
-extern int dosboot(Dos*, char*);
-extern int dosinit(Dos*, int, int);
-extern long dosread(Dosfile*, void*, long);
-extern int dosstat(Dos*, char*, Dosfile*);
-extern int doswalk(Dosfile*, char*);
-
-extern int plan9ini(Dos*, char*);
--- a/os/boot/mpc/etherif.h
+++ /dev/null
@@ -1,59 +1,0 @@
-/*
- * All the goo for PC ethernet cards.
- */
-typedef struct Card Card;
-typedef struct Type Type;
-typedef struct Ctlr Ctlr;
-
-/*
- * Hardware interface.
- */
-struct Card {
- ISAConf;
-
- int (*reset)(Ctlr*);
- void (*attach)(Ctlr*);
-
- void *(*read)(Ctlr*, void*, ulong, ulong);
- void *(*write)(Ctlr*, ulong, void*, ulong);
-
- void (*receive)(Ctlr*);
- void (*transmit)(Ctlr*);
- void (*intr)(Ureg*, void*);
- void (*overflow)(Ctlr*);
-
- uchar bit16; /* true if a 16 bit interface */
- uchar ram; /* true if card has shared memory */
-
- ulong dp8390; /* I/O address of 8390 (if any) */
- ulong data; /* I/O data port if no shared memory */
- uchar nxtpkt; /* software bndry */
- uchar tstart; /* 8390 ring addresses */
- uchar pstart;
- uchar pstop;
-
- uchar dummyrr; /* do dummy remote read */
-};
-
-/*
- * Software controller.
- */
-struct Ctlr {
- Card card; /* hardware info */
- int ctlrno;
- int present;
-
- Queue* iq;
- Queue* oq;
-
- int inpackets;
- int outpackets;
- int crcs; /* input crc errors */
- int oerrs; /* output errors */
- int frames; /* framing errors */
- int overflows; /* packet overflows */
- int buffs; /* buffering errors */
-};
-
-extern int sccethreset(Ctlr*);
-extern int etheriq(Ctlr*, Block*, int);
--- a/os/boot/mpc/etherscc.c
+++ /dev/null
@@ -1,411 +1,0 @@
-/*
- * SCCn ethernet
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum {
- Nrdre = 32, /* receive descriptor ring entries */
- Ntdre = 4, /* transmit descriptor ring entries */
-
- Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
- Bufsize = (Rbsize+7)&~7, /* aligned */
-};
-
-enum {
- /* ether-specific Rx BD bits */
- RxMiss= 1<<8,
- RxeLG= 1<<5,
- RxeNO= 1<<4,
- RxeSH= 1<<3,
- RxeCR= 1<<2,
- RxeOV= 1<<1,
- RxeCL= 1<<0,
- RxError= (RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL), /* various error flags */
-
- /* ether-specific Tx BD bits */
- TxPad= 1<<14, /* pad short frames */
- TxTC= 1<<10, /* transmit CRC */
- TxeDEF= 1<<9,
- TxeHB= 1<<8,
- TxeLC= 1<<7,
- TxeRL= 1<<6,
- TxeUN= 1<<1,
- TxeCSL= 1<<0,
-
- /* scce */
- RXB= 1<<0,
- TXB= 1<<1,
- BSY= 1<<2,
- RXF= 1<<3,
- TXE= 1<<4,
-
- /* gsmrl */
- ENR= 1<<5,
- ENT= 1<<4,
-
- /* port A */
- RXD1= SIBIT(15),
- TXD1= SIBIT(14),
-
- /* port B */
- RTS1= IBIT(19),
-
- /* port C */
- CTS1= SIBIT(11),
- CD1= SIBIT(10),
-};
-
-typedef struct Etherparam Etherparam;
-struct Etherparam {
- SCCparam;
- ulong c_pres; /* preset CRC */
- ulong c_mask; /* constant mask for CRC */
- ulong crcec; /* CRC error counter */
- ulong alec; /* alighnment error counter */
- ulong disfc; /* discard frame counter */
- ushort pads; /* short frame PAD characters */
- ushort ret_lim; /* retry limit threshold */
- ushort ret_cnt; /* retry limit counter */
- ushort mflr; /* maximum frame length reg */
- ushort minflr; /* minimum frame length reg */
- ushort maxd1; /* maximum DMA1 length reg */
- ushort maxd2; /* maximum DMA2 length reg */
- ushort maxd; /* rx max DMA */
- ushort dma_cnt; /* rx dma counter */
- ushort max_b; /* max bd byte count */
- ushort gaddr[4]; /* group address filter */
- ulong tbuf0_data0; /* save area 0 - current frm */
- ulong tbuf0_data1; /* save area 1 - current frm */
- ulong tbuf0_rba0;
- ulong tbuf0_crc;
- ushort tbuf0_bcnt;
- ushort paddr[3]; /* physical address LSB to MSB increasing */
- ushort p_per; /* persistence */
- ushort rfbd_ptr; /* rx first bd pointer */
- ushort tfbd_ptr; /* tx first bd pointer */
- ushort tlbd_ptr; /* tx last bd pointer */
- ulong tbuf1_data0; /* save area 0 - next frame */
- ulong tbuf1_data1; /* save area 1 - next frame */
- ulong tbuf1_rba0;
- ulong tbuf1_crc;
- ushort tbuf1_bcnt;
- ushort tx_len; /* tx frame length counter */
- ushort iaddr[4]; /* individual address filter*/
- ushort boff_cnt; /* back-off counter */
- ushort taddr[3]; /* temp address */
-};
-
-typedef struct {
- SCC* scc;
- int port;
- int cpm;
-
- BD* rdr; /* receive descriptor ring */
- void* rrb; /* receive ring buffers */
- int rdrx; /* index into rdr */
-
- BD* tdr; /* transmit descriptor ring */
- void* trb; /* transmit ring buffers */
- int tdrx; /* index into tdr */
-} Mot;
-static Mot mot[MaxEther];
-
-static int sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID};
-static int sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P};
-static int sccreg[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60};
-static int sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B};
-
-static void
-attach(Ctlr *ctlr)
-{
- mot[ctlr->ctlrno].scc->gsmrl |= ENR|ENT;
- eieio();
-}
-
-static void
-transmit(Ctlr *ctlr)
-{
- int len;
- Mot *motp;
- Block *b;
- BD *tdre;
-
- motp = &mot[ctlr->ctlrno];
- while(((tdre = &motp->tdr[motp->tdrx])->status & BDReady) == 0){
- b = qget(ctlr->oq);
- if(b == 0)
- break;
-
- /*
- * Copy the packet to the transmit buffer.
- */
- len = BLEN(b);
- memmove(KADDR(tdre->addr), b->rp, len);
-
- /*
- * Give ownership of the descriptor to the chip, increment the
- * software ring descriptor pointer and tell the chip to poll.
- */
- tdre->length = len;
- eieio();
- tdre->status = (tdre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
- eieio();
- motp->scc->todr = 1<<15; /* transmit now */
- eieio();
- motp->tdrx = NEXT(motp->tdrx, Ntdre);
-
- freeb(b);
-
- }
-}
-
-static void
-interrupt(Ureg*, void *ap)
-{
- int len, events, status;
- Mot *motp;
- BD *rdre;
- Block *b;
- Ctlr *ctlr;
-
- ctlr = ap;
- motp = &mot[ctlr->ctlrno];
-
- /*
- * Acknowledge all interrupts and whine about those that shouldn't
- * happen.
- */
- events = motp->scc->scce;
- eieio();
- motp->scc->scce = events;
- eieio();
- if(events & (TXE|BSY|RXB))
- print("ETHER.SCC#%d: scce = 0x%uX\n", ctlr->ctlrno, events);
- //print(" %ux|", events);
- /*
- * Receiver interrupt: run round the descriptor ring logging
- * errors and passing valid receive data up to the higher levels
- * until we encounter a descriptor still owned by the chip.
- */
- if(events & (RXF|RXB) || 1){
- rdre = &motp->rdr[motp->rdrx];
- while(((status = rdre->status) & BDEmpty) == 0){
- if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
- //if(status & RxBuff)
- // ctlr->buffs++;
- if(status & (1<<2))
- ctlr->crcs++;
- if(status & (1<<1))
- ctlr->overflows++;
- //print("eth rx: %ux\n", status);
- if(status & RxError)
- print("~");
- else if((status & BDLast) == 0)
- print("@");
- }
- else{
- /*
- * We have a packet. Read it into the next
- * free ring buffer, if any.
- */
- len = rdre->length-4;
- if((b = iallocb(len)) != 0){
- memmove(b->wp, KADDR(rdre->addr), len);
- b->wp += len;
- etheriq(ctlr, b, 1);
- }
- }
-
- /*
- * Finished with this descriptor, reinitialise it,
- * give it back to the chip, then on to the next...
- */
- rdre->length = 0;
- rdre->status = (rdre->status & BDWrap) | BDEmpty | BDInt;
- eieio();
-
- motp->rdrx = NEXT(motp->rdrx, Nrdre);
- rdre = &motp->rdr[motp->rdrx];
- }
- }
-
- /*
- * Transmitter interrupt: handle anything queued for a free descriptor.
- */
- if(events & TXB)
- transmit(ctlr);
- if(events & TXE)
- cpmop(RestartTx, motp->cpm, 0);
-}
-
-static void
-ringinit(Mot* motp)
-{
- int i, x;
-
- /*
- * Initialise the receive and transmit buffer rings. The ring
- * entries must be aligned on 16-byte boundaries.
- */
- if(motp->rdr == 0)
- motp->rdr = bdalloc(Nrdre);
- if(motp->rrb == 0)
- motp->rrb = ialloc(Nrdre*Bufsize, 0);
- x = PADDR(motp->rrb);
- for(i = 0; i < Nrdre; i++){
- motp->rdr[i].length = 0;
- motp->rdr[i].addr = x;
- motp->rdr[i].status = BDEmpty|BDInt;
- x += Bufsize;
- }
- motp->rdr[i-1].status |= BDWrap;
- motp->rdrx = 0;
-
- if(motp->tdr == 0)
- motp->tdr = bdalloc(Ntdre);
- if(motp->trb == 0)
- motp->trb = ialloc(Ntdre*Bufsize, 0);
- x = PADDR(motp->trb);
- for(i = 0; i < Ntdre; i++){
- motp->tdr[i].addr = x;
- motp->tdr[i].length = 0;
- motp->tdr[i].status = TxPad|BDInt|BDLast|TxTC;
- x += Bufsize;
- }
- motp->tdr[i-1].status |= BDWrap;
- motp->tdrx = 0;
-}
-
-/*
- * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence,
- * except that it sets the right bits for the MPC823ADS board when SCC2 is used,
- * and those for the 860/821 development board for SCC1.
- */
-static void
-sccsetup(Mot *ctlr, SCC *scc, uchar *ea)
-{
- int i, rcs, tcs, w;
- Etherparam *p;
- IMM *io;
-
-
- i = 2*(ctlr->port-1);
- io = ioplock();
- w = (TXD1|RXD1)<<i; /* TXDn and RXDn in port A */
- io->papar |= w; /* enable TXDn and RXDn pins */
- io->padir &= ~w;
- io->paodr &= ~w; /* not open drain */
-
- w = (CD1|CTS1)<<i; /* CLSN and RENA: CDn and CTSn in port C */
- io->pcpar &= ~w; /* enable CLSN (CTSn) and RENA (CDn) */
- io->pcdir &= ~w;
- io->pcso |= w;
- iopunlock();
-
- /* clocks and transceiver control: details depend on the board's wiring */
- archetherenable(ctlr->cpm, &rcs, &tcs);
-
- sccnmsi(ctlr->port, rcs, tcs); /* connect the clocks */
-
- p = (Etherparam*)KADDR(sccparam[ctlr->port]);
- memset(p, 0, sizeof(*p));
- p->rfcr = 0x18;
- p->tfcr = 0x18;
- p->mrblr = Bufsize;
- p->rbase = PADDR(ctlr->rdr);
- p->tbase = PADDR(ctlr->tdr);
-
- cpmop(InitRxTx, ctlr->cpm, 0);
-
- p->c_pres = ~0;
- p->c_mask = 0xDEBB20E3;
- p->crcec = 0;
- p->alec = 0;
- p->disfc = 0;
- p->pads = 0x8888;
- p->ret_lim = 0xF;
- p->mflr = Rbsize;
- p->minflr = ETHERMINTU+4;
- p->maxd1 = Bufsize;
- p->maxd2 = Bufsize;
- p->p_per = 0; /* only moderate aggression */
-
- for(i=0; i<Eaddrlen; i+=2)
- p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i]; /* it's not the obvious byte order */
-
- scc->psmr = (2<<10)|(5<<1); /* 32-bit CRC, ignore 22 bits before SFD */
- scc->dsr = 0xd555;
- scc->gsmrh = 0; /* normal operation */
- scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC; /* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */
- eieio();
- scc->scce = ~0; /* clear all events */
- eieio();
- scc->sccm = TXE | RXF | TXB; /* enable interrupts */
- eieio();
-
- io = ioplock();
- w = RTS1<<(ctlr->port-1); /* enable TENA pin (RTSn) */
- io->pbpar |= w;
- io->pbdir |= w;
- iopunlock();
-
- /* gsmrl enable is deferred until attach */
-}
-
-/*
- * Prepare the SCCx ethernet for booting.
- */
-int
-sccethreset(Ctlr* ctlr)
-{
- uchar ea[Eaddrlen];
- Mot *motp;
- SCC *scc;
- char line[50], def[50];
-
- /*
- * Since there's no EPROM, insist that the configuration entry
- * (see conf.c and flash.c) holds the Ethernet address.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0){
- print("no preset Ether address\n");
- for(;;){
- strcpy(def, "00108bf12900"); /* valid MAC address to be used only for initial configuration */
- if(getstr("ether MAC address", line, sizeof(line), def) < 0)
- return -1;
- if(parseether(ctlr->card.ea, line) >= 0 || ctlr->card.ea[0] == 0xFF)
- break;
- print("invalid MAC address\n");
- }
- }
-
- scc = IOREGS(sccreg[ctlr->card.port], SCC);
- ctlr->card.irq = VectorCPIC+sccirq[ctlr->card.port];
-
- motp = &mot[ctlr->ctlrno];
- motp->scc = scc;
- motp->port = ctlr->card.port;
- motp->cpm = sccid[ctlr->card.port];
-
- ringinit(motp);
-
- sccsetup(motp, scc, ctlr->card.ea);
-
- /* enable is deferred until attach */
-
- ctlr->card.reset = sccethreset;
- ctlr->card.attach = attach;
- ctlr->card.transmit = transmit;
- ctlr->card.intr = interrupt;
-
- return 0;
-}
--- a/os/boot/mpc/fblt.c
+++ /dev/null
@@ -1,531 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <libg.h>
-#include <gnot.h>
-
-/*
- * bitblt operates a 'word' at a time.
- * WBITS is the number of bits in a word
- * LWBITS=log2(WBITS),
- * W2L is the number of words in a long
- * WMASK has bits set for the low order word of a long
- * WType is a pointer to a word
- */
-#ifndef WBITS
-#define WBITS 32
-#define LWBITS 5
-#define W2L 1
-#define WMASK ~0UL
-typedef ulong *WType;
-#endif
-
-#define DEBUG
-
-#ifdef TEST
-/*
- * globals used for testing
- */
-int FORCEFORW;
-int FORCEBAKW;
-GBitmap *curdm, *cursm;
-Point curpt;
-Rectangle curr;
-Fcode curf;
-void *mem;
-#endif
-
-static void
-gbitexplode(ulong sw, ulong *buf, int sdep, int x)
-{
- int j, o, q, n, nw, inc, qinc;
- ulong s, dw, pix;
-
- inc = 1 << sdep;
- pix = (1 << inc) - 1;
- nw = 1 << x;
- n = 32 >> x;
- qinc = (nw << sdep) - inc;
- for(o = 32 - n; o >= 0; o -= n){
- dw = 0;
- s = sw >> o;
- q = 0;
- for(j = 0; j < n; j += inc){
- dw |= (s & (pix << j)) << q;
- q += qinc;
- }
- for(j = 0; j < x; j++)
- dw |= dw << (inc << j);
- *buf++ = dw;
- }
-}
-
-/*
-void
-main(void)
-{
- ulong buf[128];
-
- gbitexplode(0x7777, buf, 0, 3);
- exits(0);
-}
-*/
-
-void
-gbitblt(GBitmap *dm, Point pt, GBitmap *sm, Rectangle r, Fcode fcode)
-{
- int width; /* width in bits of dst */
- int wwidth; /* floor width in words */
- int height; /* height in pixels minus 1 */
- int sdep; /* src ldepth */
- int ddep; /* dst ldepth */
- int deltadep; /* diff between ldepths */
- int sspan; /* words between scanlines in src */
- int dspan; /* words between scanlines in dst */
- int soff; /* bit offset of src start point */
- int sdest; /* bit offset of src start point that matches doff when expanded */
- int doff; /* bit offset of dst start point */
- int delta; /* amount to shift src by */
- int sign; /* of delta */
- ulong *saddr;
- ulong *daddr;
- ulong *s;
- ulong *d;
- ulong mask;
- ulong tmp; /* temp storage source word */
- ulong sw; /* source word constructed */
- ulong dw; /* dest word fetched */
- ulong lmask; /* affected pixels in leftmost dst word */
- ulong rmask; /* affected pixels in rightmost dst word */
- int i;
- int j;
- ulong buf[32]; /* for expanding a source */
- ulong *p; /* pointer into buf */
- int spare; /* number of words already converted */
-
-
-#ifdef TEST
- curdm = dm;
- cursm = sm;
- curpt = pt;
- curr = r;
- curf = fcode;
-#endif
-
- gbitbltclip(&dm);
-
- width = r.max.x - r.min.x;
- if(width <= 0)
- return;
- height = r.max.y - r.min.y - 1;
- if(height < 0)
- return;
-
- ddep = dm->ldepth;
- pt.x <<= ddep;
- width <<= ddep;
-
- sdep = sm->ldepth;
- r.min.x <<= sdep;
- r.max.x <<= sdep;
-
- dspan = dm->width * W2L;
- sspan = sm->width * W2L;
-
- daddr = (ulong*)((WType)dm->base
- + dm->zero*W2L + pt.y*dspan
- + (pt.x >> LWBITS));
- saddr = (ulong*)((WType)sm->base
- + sm->zero*W2L + r.min.y*sspan
- + (r.min.x >> LWBITS));
-
- doff = pt.x & (WBITS - 1);
- lmask = WMASK >> doff;
- rmask = (WMASK << (WBITS - ((doff+width) & (WBITS-1))))&WMASK;
- if(!rmask)
- rmask = WMASK;
- soff = r.min.x & (WBITS-1);
- wwidth = ((pt.x+width-1)>>LWBITS) - (pt.x>>LWBITS);
-
- if(sm == dm){
-#ifdef TEST
- if(!FORCEBAKW &&
- (FORCEFORW || sm != dm || saddr > daddr ||
- (saddr == daddr && soff > doff)))
- ;
- else{
- daddr += height * dspan;
- saddr += height * sspan;
- sspan -= 2 * W2L * sm->width;
- dspan -= 2 * W2L * dm->width;
- }
-#else
- if(r.min.y < pt.y){ /* bottom to top */
- daddr += height * dspan;
- saddr += height * sspan;
- sspan -= 2 * W2L * sm->width;
- dspan -= 2 * W2L * dm->width;
- }else if(r.min.y == pt.y && r.min.x < pt.x)
- abort()/*goto right*/;
-#endif
- }
- if(wwidth == 0) /* collapse masks for narrow cases */
- lmask &= rmask;
- fcode &= F;
-
- deltadep = ddep - sdep;
- sdest = doff >> deltadep;
- delta = soff - sdest;
- sign = 0;
- if(delta < 0){
- sign = 1;
- delta = -delta;
- }
-
- p = 0;
- for(j = 0; j <= height; j++){
- d = daddr;
- s = saddr;
- mask = lmask;
- tmp = 0;
- if(!sign)
- tmp = *s++;
- spare = 0;
- for(i = wwidth; i >= 0; i--){
- if(spare)
- sw = *p++;
- else{
- if(sign){
- sw = tmp << (WBITS-delta);
- tmp = *s++;
- sw |= tmp >> delta;
- }else{
- sw = tmp << delta;
- tmp = *s++;
- if(delta)
- sw |= tmp >> (WBITS-delta);
- }
- spare = 1 << deltadep;
- if(deltadep >= 1){
- gbitexplode(sw, buf, sdep, deltadep);
- p = buf;
- sw = *p++;
- }
- }
-
- dw = *d;
- switch(fcode){ /* ltor bit aligned */
- case Zero: *d = dw & ~mask; break;
- case DnorS: *d = dw ^ ((~sw | dw) & mask); break;
- case DandnotS: *d = dw ^ ((sw & dw) & mask); break;
- case notS: *d = dw ^ ((~sw ^ dw) & mask); break;
- case notDandS: *d = dw ^ ((sw | dw) & mask); break;
- case notD: *d = dw ^ mask; break;
- case DxorS: *d = dw ^ (sw & mask); break;
- case DnandS: *d = dw ^ ((sw | ~dw) & mask); break;
- case DandS: *d = dw ^ ((~sw & dw) & mask); break;
- case DxnorS: *d = dw ^ (~sw & mask); break;
- case D: break;
- case DornotS: *d = dw | (~sw & mask); break;
- case S: *d = dw ^ ((sw ^ dw) & mask); break;
- case notDorS: *d = dw ^ (~(sw & dw) & mask); break;
- case DorS: *d = dw | (sw & mask); break;
- case F: *d = dw | mask; break;
- }
- d++;
-
- mask = WMASK;
- if(i == 1)
- mask = rmask;
- spare--;
- }
- saddr += sspan;
- daddr += dspan;
- }
-}
-
-#ifdef TEST
-void prprog(void);
-GBitmap *bb1, *bb2;
-ulong *src, *dst, *xdst, *xans;
-int swds, dwds;
-long ticks;
-int timeit;
-
-long
-func(int f, long s, int sld, long d, int dld)
-{
- long a;
- int sh, i, db, sb;
-
- db = 1 << dld;
- sb = 1 << sld;
- sh = db - sb;
- if(sh > 0) {
- a = s;
- for(i = sb; i<db; i += sb){
- a <<= sb;
- s |= a;
- }
- } else if(sh < 0)
- s >>= -sh;
-
- switch(f){
- case Zero: d = 0; break;
- case DnorS: d = ~(d|s); break;
- case DandnotS: d = d & ~s; break;
- case notS: d = ~s; break;
- case notDandS: d = ~d & s; break;
- case notD: d = ~d; break;
- case DxorS: d = d ^ s; break;
- case DnandS: d = ~(d&s); break;
- case DandS: d = d & s; break;
- case DxnorS: d = ~(d^s); break;
- case S: d = s; break;
- case DornotS: d = d | ~s; break;
- case D: d = d; break;
- case notDorS: d = ~d | s; break;
- case DorS: d = d | s; break;
- case F: d = ~0; break;
- }
-
- d &= ((1<<db)-1);
- return d;
-}
-
-void
-run(int fr, int to, int w, int op)
-{
- int i, j, f, t, fy, ty;
- extern long *_clock;
-
- fr += bb2->r.min.x;
- to += bb1->r.min.x;
- fy = bb2->r.min.y + 1;
- ty = bb1->r.min.y + 1;
- if(timeit) {
- memcpy(dst, xdst, dwds * sizeof(long));
- ticks -= *_clock;
- gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
- ticks += *_clock;
- return;
- }
- f = fr;
- t = to;
- memcpy(dst, xdst, dwds * sizeof(long));
- for(i=0; i<w; i++) {
- gbitblt(bb1, Pt(t,ty), bb2, Rect(f,fy,f+1,fy+1), op);
- gbitblt(bb1, Pt(t,ty+1), bb2, Rect(f,fy+1,f+1,fy+2), op);
- f++;
- t++;
- }
- memcpy(xans, dst, dwds * sizeof(long));
-
- memcpy(dst, xdst, dwds * sizeof(long));
- gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
-
- if(memcmp(xans, dst, dwds * sizeof(long))) {
- /*
- * print src and dst row offset, width in bits, and forw/back
- * then print for each of the four rows: the source (s),
- * the dest (d), the good value of the answer (g),
- * and the actual bad value of the answer (b)
- */
- print("fr=%d to=%d w=%d fb=%d%d\n",
- fr, to, w, FORCEFORW, FORCEBAKW);
- print("dst bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
- bb1->base, bb1->zero, bb1->width, bb1->ldepth,
- bb1->r.min.x, bb1->r.min.y, bb1->r.max.x, bb1->r.max.y);
- print("src bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
- bb2->base, bb2->zero, bb2->width, bb2->ldepth,
- bb2->r.min.x, bb2->r.min.y, bb2->r.max.x, bb2->r.max.y);
- for(j=0; 7*j < dwds; j++) {
- print("\ns");
- for(i=0; i<7 && 7*j+i < dwds; i++)
- print(" %.8lux", src[7*j + i]);
- print("\nd");
- for(i=0; i<7 && 7*j+i < dwds; i++)
- print(" %.8lux", xdst[7*j + i]);
- print("\ng");
- for(i=0; i<7 && 7*j+i < dwds; i++)
- print(" %.8lux", xans[7*j + i]);
- print("\nb");
- for(i=0; i<7 && 7*j+i < dwds; i++)
- print(" %.8lux", dst[7*j + i]);
- print("\n");
- }
- prprog();
- }
-}
-
-void
-prprog(void)
-{
- exits(0);
-}
-
-int
-main(int argc, char *argv[])
-{
- int f, t, w, i, sld, dld, op, iters, simple;
- ulong s, d, spix, dpix, apix, fpix, m, *ps, *pd;
- Point sorg, dorg;
- GBitmap *bs, *bd;
- long seed;
- char *ct;
-
- sld = 0;
- dld = 0;
- timeit = 0;
- iters = 200;
- simple = 0;
- ARGBEGIN {
- case 'i':
- iters = atoi(ARGF());
- break;
- case 's':
- simple = 1;
- break;
- case 't':
- timeit = 1;
- ct = ARGF();
- if(ct)
- iters = atoi(ct);
- break;
- } ARGEND
- if(argc > 0)
- sld = atoi(argv[0]);
- if(argc > 1)
- dld = atoi(argv[1]);
- if(!timeit && !simple) {
- seed = time(0);
- print("seed %lux\n", seed); srand(seed); /**/
- }
-
- print("sld %d dld %d\n", sld, dld);
- op = 1;
-
- /* bitmaps for 1-bit tests */
- bd = gballoc(Rect(0,0,32,1), dld);
- bs = gballoc(Rect(0,0,32,1), sld);
- for(i=0; i<bs->width; i++)
- bs->base[i] = lrand();
-
- /* bitmaps for rect tests */
- if(simple) {
- dorg = Pt(0,0);
- sorg = Pt(0,0);
- } else {
- dorg = Pt(nrand(63)-31,nrand(63)-31);
- sorg = Pt(nrand(63)-31,nrand(63)-31);
- }
- bb1 = gballoc(Rpt(dorg,add(dorg,Pt(200,4))), dld);
- bb2 = gballoc(Rpt(sorg,add(sorg,Pt(200,4))), sld);
- dwds = bb1->width * Dy(bb1->r);
- swds = bb2->width * Dy(bb2->r);
- dst = bb1->base;
- src = bb2->base;
- xdst = malloc(dwds * sizeof(long));
- xans = malloc(dwds * sizeof(long));
- for(i=0; i<swds; i++)
- src[i] = lrand();
- for(i=0; i<dwds; i++)
- xdst[i] = lrand();
-
-loop:
- print("Op %d\n", op);
- if(!timeit) {
- print("one pixel\n");
- ps = bs->base;
- pd = bd->base;
- FORCEFORW = 1;
- FORCEBAKW = 0;
- for(i=0; i<1000; i++, FORCEFORW = !FORCEFORW, FORCEBAKW = !FORCEBAKW) {
- f = nrand(32 >> sld);
- t = nrand(32 >> dld);
- s = lrand();
- d = lrand();
- ps[0] = s;
- pd[0] = d;
-#ifdef T386
- spix = (byterev(s) >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
- dpix = (byterev(d) >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
-#else
- spix = (s >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
- dpix = (d >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
-#endif
-#ifdef T386
- apix = byterev(func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld)));
-#else
- apix = func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld));
-#endif
- gbitblt(bd, Pt(t,0), bs, Rect(f,0,f+1,1), op);
- if(ps[0] != s) {
- print("bb src %.8lux %.8lux %d %d\n", ps[0], s, f, t);
- exits("error");
- }
- m = ((1 << (1<<dld)) - 1) << (32 - ((t+1)<<dld));
-#ifdef T386
- m = byterev(m);
-#endif
- if((pd[0] & ~m) != (d & ~m)) {
- print("bb dst1 %.8lux %.8lux\n",
- s, d);
- print("bb %.8lux %.8lux %d %d\n",
- ps[0], pd[0], f, t);
- prprog();
- exits("error");
- }
- if((pd[0] & m) != apix) {
- spix <<= 32 - ((f+1)<<sld);
- dpix <<= 32 - ((t+1)<<dld);
-#ifdef T386
- spix = byterev(spix);
- dpix = byterev(dpix);
-#endif
- print("bb dst2 %.8lux %.8lux\n",
- s, d);
- print("bb %.8lux %.8lux %d %d\n",
- ps[0], pd[0], f, t);
- print("bb %.8lux %.8lux %.8lux %.8lux\n",
- spix, dpix, apix, pd[0] & m);
- prprog();
- exits("error");
- }
- }
- }
-
- print("for\n");
- FORCEFORW = 1;
- FORCEBAKW = 0;
-
- for(i=0; i<iters; i++) {
- f = nrand(64);
- t = nrand(64);
- w = nrand(130);
- run(f, t, w, op);
- }
-
- if(sld == dld) {
- print("bak\n");
- FORCEFORW = 0;
- FORCEBAKW = 1;
-
- for(i=0; i<iters; i++) {
- f = nrand(64);
- t = nrand(64);
- w = nrand(130);
- run(f, t, w, op);
- }
- }
-
- if(op < F) {
- op++;
- goto loop;
- }
- if(timeit)
- print("time: %d ticks\n", ticks);
- exits(0);
-}
-
-
-#endif
--- a/os/boot/mpc/flash.c
+++ /dev/null
@@ -1,212 +1,0 @@
-#include "boot.h"
-
-typedef struct Flashdev Flashdev;
-struct Flashdev {
- uchar* base;
- int size;
- uchar* exec;
- char* config;
- int conflen;
-};
-
-enum {
- FLASHSEG = 256*1024,
- CONFIGLIM = FLASHSEG,
- BOOTOFF = FLASHSEG,
- BOOTLEN = 3*FLASHSEG, /* third segment might be filsys */
- /* rest of flash is free */
-};
-
-static Flashdev flash;
-
-/*
- * configuration data is written between the bootstrap and
- * the end of region 0. the region ends with allocation descriptors
- * of the following form:
- *
- * byte order is big endian
- *
- * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
- */
-typedef struct Flalloc Flalloc;
-struct Flalloc {
- ulong check; /* checksum of data, or ~0 */
- ulong base; /* base of region; ~0 if unallocated, 0 if deleted */
- uchar len[3];
- uchar tag; /* see below */
- uchar sig[4];
-};
-
-enum {
- /* tags */
- Tdead= 0,
- Tboot= 0x01, /* space reserved for boot */
- Tconf= 0x02, /* configuration data */
- Tnone= 0xFF,
-
- Noval= ~0,
-};
-
-static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
-static char conftag[] = "#plan9.ini\n";
-
-static ulong
-checksum(uchar* p, int n)
-{
- ulong s;
-
- for(s=0; --n >= 0;)
- s += *p++;
- return s;
-}
-
-static int
-validptr(Flalloc *ap, uchar *p)
-{
- return p > (uchar*)&end && p < (uchar*)ap;
-}
-
-static int
-flashcheck(Flalloc *ap, char **val, int *len)
-{
- uchar *base;
- int n;
-
- if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
- return 0;
- base = flash.base+ap->base;
- if(!validptr(ap, base))
- return 0;
- n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
- if(n == 0xFFFFFF)
- n = 0;
- if(n < 0)
- return 0;
- if(n > 0 && !validptr(ap, base+n-1))
- return 0;
- if(ap->check != Noval && checksum(base, n) != ap->check){
- print("flash: bad checksum\n");
- return 0;
- }
- *val = (char*)base;
- *len = n;
- return 1;
-}
-
-int
-flashinit(void)
-{
- int len;
- char *val;
- Flalloc *ap;
- void *addr;
- long mbytes;
- char type[20];
-
- flash.base = 0;
- flash.exec = 0;
- flash.size = 0;
- if(archflashreset(type, &addr, &mbytes) < 0){
- print("flash: flash not present or not enabled\n"); /* shouldn't happen */
- return 0;
- }
- flash.size = mbytes;
- flash.base = addr;
- flash.exec = flash.base + BOOTOFF;
- flash.config = nil;
- flash.conflen = 0;
-
- for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
- if(0)
- print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
- if(ap->tag == Tconf &&
- flashcheck(ap, &val, &len) &&
- len >= sizeof(conftag)-1 &&
- memcmp(val, conftag, sizeof(conftag)-1) == 0){
- flash.config = val;
- flash.conflen = len;
- if(0)
- print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
- }
- }
- if(flash.config == nil)
- print("flash: no config\n");
- else
- print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
- if(issqueezed(flash.exec) == Q_MAGIC){
- print("flash: squeezed powerpc kernel installed\n");
- return 1<<0;
- }
- if(GLLONG(flash.exec) == Q_MAGIC){
- print("flash: unsqueezed powerpc kernel installed\n");
- return 1<<0;
- }
- flash.exec = 0;
- print("flash: no powerpc kernel in Flash\n");
- return 0;
-}
-
-char*
-flashconfig(int)
-{
- return flash.config;
-}
-
-int
-flashbootable(int)
-{
- return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == Q_MAGIC);
-}
-
-int
-flashboot(int)
-{
- ulong entry, addr;
- void (*b)(void);
- Exec *ep;
- Block in;
- long n;
- uchar *p;
-
- if(flash.exec == 0)
- return -1;
- p = flash.exec;
- if(GLLONG(p) == Q_MAGIC){
- /* unsqueezed: copy data and perhaps text, then jump to it */
- ep = (Exec*)p;
- entry = PADDR(GLLONG(ep->entry));
- p += sizeof(Exec);
- addr = entry;
- n = GLLONG(ep->text);
- if(addr != (ulong)p){
- memmove((void*)addr, p, n);
- print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
- }
- p += n;
- if(entry >= FLASHMEM)
- addr = 3*BY2PG; /* kernel text is in Flash, data in RAM */
- else
- addr = PGROUND(addr+n);
- n = GLLONG(ep->data);
- memmove((void*)addr, p, n);
- print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
- }else{
- in.data = p;
- in.rp = in.data;
- in.lim = p+BOOTLEN;
- in.wp = in.lim;
- n = unsqueezef(&in, &entry);
- if(n < 0)
- return -1;
- }
- print("entry=0x%lux\n", entry);
- uartwait();
- scc2stop();
- /*
- * Go to new code. It's up to the program to get its PC relocated to
- * the right place.
- */
- b = (void (*)(void))KADDR(PADDR(entry));
- (*b)();
- return -1;
-}
--- a/os/boot/mpc/fns.h
+++ /dev/null
@@ -1,117 +1,0 @@
-Alarm* alarm(int, void (*)(Alarm*), void*);
-void alarminit(void);
-void archbacklight(int);
-char* archconfig(void);
-void archdisableuart(int);
-void archenableuart(int, int);
-void archenableusb(int);
-void archetherdisable(int);
-int archetherenable(int, int*, int*);
-int archflashreset(char*, void**, long*);
-void archinit(void);
-int archoptionsw(void);
-int bootp(int, char*);
-void cancel(Alarm*);
-void checkalarms(void);
-void clockinit(void);
-void clockintr(Ureg*, void*);
-void consinit(void);
-void cpminit(void);
-void cpuidprint(void);
-#define dcflush(a,b)
-void delay(int);
-void eieio(void);
-uchar* etheraddr(int);
-int etherinit(void);
-int etherrxpkt(int, Etherpkt*, int);
-int ethertxpkt(int, Etherpkt*, int, int);
-void exception(void);
-int flashboot(int);
-int flashbootable(int);
-char* flashconfig(int);
-int flashinit(void);
-void free(void*);
-void freeb(Block*);
-int getcfields(char*, char**, int, char*);
-char* getconf(char*);
-ulong getdec(void);
-ulong gethid0(void);
-ulong getimmr(void);
-ulong getmsr(void);
-ulong getpvr(void);
-int getstr(char*, char*, int, char*);
-ulong gettbl(void);
-ulong gettbu(void);
-int hardinit(void);
-long hardread(int, void*, long);
-long hardseek(int, long);
-long hardwrite(int, void*, long);
-long i2csend(int, void*, long);
-void i2csetup(void);
-void* ialloc(ulong, int);
-Block* iallocb(int);
-void idle(void);
-int isaconfig(char*, int, ISAConf*);
-int issqueezed(uchar*);
-void kbdchar(Queue*, int);
-void kbdinit(void);
-void kbdreset(void);
-void machinit(void);
-void* malloc(ulong);
-ulong mapalloc(RMap*, ulong, int, int);
-void mapfree(RMap*, ulong, int);
-void mapinit(RMap*, Map*, int);
-void meminit(void);
-void microdelay(int);
-void mmuinit(void);
-int optionsw(void);
-void panic(char*, ...);
-int parseether(uchar*, char*);
-int plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
-void putdec(ulong);
-void puthid0(ulong);
-void putmsr(ulong);
-int qbgetc(Queue*);
-void qbputc(Queue*, int);
-void qbwrite(Queue*, Block*);
-Block* qget(Queue*);
-long qlen(Queue*);
-Queue* qopen(int, int, void (*)(void*), void*);
-#define qpass qbwrite
-void scc2stop(void);
-void sccnmsi(int, int, int);
-void sched(void);
-void screeninit(void);
-void screenputs(char*, int);
-void sdraminit(ulong);
-Partition* sethardpart(int, char*);
-Partition* setscsipart(int, char*);
-void setvec(int, void (*)(Ureg*, void*), void*);
-int splhi(void);
-int spllo(void);
-void splx(int);
-void trapinit(void);
-void uartputs(char*, int);
-void uartsetboot(void (*f)(uchar*, int));
-void uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
-void uartwait(void);
-long unsqueezef(Block*, ulong*);
-
-#define GSHORT(p) (((p)[1]<<8)|(p)[0])
-#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))
-#define GLSHORT(p) (((p)[0]<<8)|(p)[1])
-#define GLLONG(p) ((GLSHORT(p)<<16)|GLSHORT(p+2))
-
-#define KADDR(a) ((void*)((ulong)(a)|KZERO))
-#define PADDR(a) ((ulong)(a)&~KSEGM)
-
-/* IBM bit field order */
-#define IBIT(b) ((ulong)1<<(31-(b)))
-#define SIBIT(n) ((ushort)1<<(15-(n)))
-
-#define IOREGS(x, T) ((T*)((char*)m->iomem+(x)))
-
-int uartinit(void);
-Partition* setuartpart(int, char*);
-long uartread(int, void*, long);
-long uartseek(int, long);
--- a/os/boot/mpc/gbitbltclip.c
+++ /dev/null
@@ -1,52 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <libg.h>
-#include <gnot.h>
-
-void
-gbitbltclip(void *vp)
-{
- int dx, dy;
- int i;
- struct{
- GBitmap *dm;
- Point p;
- GBitmap *sm;
- Rectangle r;
- Fcode f;
- }*bp;
-
- bp = vp;
- dx = Dx(bp->r);
- dy = Dy(bp->r);
- if(bp->p.x < bp->dm->clipr.min.x){
- i = bp->dm->clipr.min.x-bp->p.x;
- bp->r.min.x += i;
- bp->p.x += i;
- dx -= i;
- }
- if(bp->p.y < bp->dm->clipr.min.y){
- i = bp->dm->clipr.min.y-bp->p.y;
- bp->r.min.y += i;
- bp->p.y += i;
- dy -= i;
- }
- if(bp->p.x+dx > bp->dm->clipr.max.x)
- bp->r.max.x -= bp->p.x+dx-bp->dm->clipr.max.x;
- if(bp->p.y+dy > bp->dm->clipr.max.y)
- bp->r.max.y -= bp->p.y+dy-bp->dm->clipr.max.y;
- if(bp->r.min.x < bp->sm->clipr.min.x){
- i = bp->sm->clipr.min.x-bp->r.min.x;
- bp->p.x += i;
- bp->r.min.x += i;
- }
- if(bp->r.min.y < bp->sm->clipr.min.y){
- i = bp->sm->clipr.min.y-bp->r.min.y;
- bp->p.y += i;
- bp->r.min.y += i;
- }
- if(bp->r.max.x > bp->sm->clipr.max.x)
- bp->r.max.x = bp->sm->clipr.max.x;
- if(bp->r.max.y > bp->sm->clipr.max.y)
- bp->r.max.y = bp->sm->clipr.max.y;
-}
--- a/os/boot/mpc/gnot.h
+++ /dev/null
@@ -1,71 +1,0 @@
-
-extern void *bbmalloc(int);
-extern void bbfree(void *, int);
-extern int bbonstack(void);
-extern void bbexec(void(*)(void), int, int);
-
-/*
- * Graphics types
- */
-
-typedef struct GBitmap GBitmap;
-typedef struct GFont GFont;
-typedef struct GSubfont GSubfont;
-typedef struct GCacheinfo GCacheinfo;
-
-struct GBitmap
-{
- ulong *base; /* pointer to start of data */
- long zero; /* base+zero=&word containing (0,0) */
- ulong width; /* width in 32 bit words of total data area */
- int ldepth; /* log base 2 of number of bits per pixel */
- Rectangle r; /* rectangle in data area, local coords */
- Rectangle clipr; /* clipping region */
- GBitmap *cache; /* zero; distinguishes bitmap from layer */
-};
-
-
-/*
- * GFont etc. are not used in the library, only in devbit.c.
- * GSubfont is only barely used.
- */
-struct GSubfont
-{
- short n; /* number of chars in font */
- char height; /* height of bitmap */
- char ascent; /* top of bitmap to baseline */
- Fontchar *info; /* n+1 character descriptors */
- GBitmap *bits; /* where the characters are */
-};
-struct GCacheinfo
-{
- ulong xright; /* right edge of bits */
- Fontchar;
-};
-
-struct GFont
-{
- uchar height; /* max height of bitmap, interline spacing */
- char ascent; /* top of bitmap to baseline */
- char width; /* widest so far; used in caching only */
- char ldepth; /* of images */
- short id; /* of font */
- int ncache; /* number of entries in cache */
- GCacheinfo *cache; /* cached characters */
- GBitmap *b; /* cached images */
-};
-
-extern ulong *gaddr(GBitmap*, Point);
-extern uchar *gbaddr(GBitmap*, Point);
-extern void gbitblt(GBitmap*, Point, GBitmap*, Rectangle, Fcode);
-extern void gbitbltclip(void*);
-extern void gtexture(GBitmap*, Rectangle, GBitmap*, Fcode);
-extern Point gsubfstrsize(GSubfont*, char*);
-extern int gsubfstrwidth(GSubfont*, char*);
-extern Point gsubfstring(GBitmap*, Point, GSubfont*, char*, Fcode);
-extern Point gbitbltstring(GBitmap*, Point, GSubfont*, char*, Fcode);
-extern void gsegment(GBitmap*, Point, Point, int, Fcode);
-extern void gpoint(GBitmap*, Point, int, Fcode);
-extern void gflushcpucache(void);
-extern GBitmap* gballoc(Rectangle, int);
-extern void gbfree(GBitmap*);
--- a/os/boot/mpc/i2c.c
+++ /dev/null
@@ -1,351 +1,0 @@
-#include "boot.h"
-
-/*
- * basic read/write interface to mpc8xx I2C bus (master mode)
- */
-
-typedef struct I2C I2C;
-
-struct I2C {
- uchar i2mod;
- uchar rsv12a[3];
- uchar i2add;
- uchar rsv12b[3];
- uchar i2brg;
- uchar rsv12c[3];
- uchar i2com;
- uchar rsv12d[3];
- uchar i2cer;
- uchar rsv12e[3];
- uchar i2cmr;
-};
-
-enum {
- /* i2c-specific BD flags */
- RxeOV= 1<<1, /* overrun */
- TxS= 1<<10, /* transmit start condition */
- TxeNAK= 1<<2, /* last transmitted byte not acknowledged */
- TxeUN= 1<<1, /* underflow */
- TxeCL= 1<<0, /* collision */
- TxERR= (TxeNAK|TxeUN|TxeCL),
-
- /* i2cmod */
- REVD= 1<<5, /* =1, LSB first */
- GCD= 1<<4, /* =1, general call address disabled */
- FLT= 1<<3, /* =0, not filtered; =1, filtered */
- PDIV= 3<<1, /* predivisor field */
- EN= 1<<0, /* enable */
-
- /* i2com */
- STR= 1<<7, /* start transmit */
- I2CM= 1<<0, /* master */
- I2CS= 0<<0, /* slave */
-
- /* i2cer */
- TXE = 1<<4,
- BSY = 1<<2,
- TXB = 1<<1,
- RXB = 1<<0,
-
- /* port B bits */
- I2CSDA = IBIT(27),
- I2CSCL = IBIT(26),
-
- Rbit = 1<<0, /* bit in address byte denoting read */
-
- /* maximum I2C I/O (can change) */
- Bufsize = 64,
- Tbuflen= Bufsize+4, /* extra address bytes and alignment */
- Freq = 100000,
- I2CTimeout = 250, /* msec */
-};
-
-/* data cache needn't be flushed if buffers allocated in uncached INTMEM */
-#define DCFLUSH(a,n)
-
-/*
- * I2C software structures
- */
-
-struct Ctlr {
- Lock;
- QLock io;
- int init;
- I2C* i2c;
- IOCparam* sp;
-
- BD* rd;
- BD* td;
- int phase;
- char* addr;
- char* txbuf;
- char* rxbuf;
-};
-typedef struct Ctlr Ctlr;
-
-static Ctlr i2ctlr[1];
-extern int predawn;
-
-static void interrupt(Ureg*, void*);
-
-static void
-enable(void)
-{
- I2C *i2c;
-
- i2c = i2ctlr->i2c;
- i2c->i2cer = ~0; /* clear events */
- eieio();
- i2c->i2mod |= EN;
- eieio();
- i2c->i2cmr = TXE|BSY|TXB|RXB; /* enable all interrupts */
- eieio();
-}
-
-static void
-disable(void)
-{
- I2C *i2c;
-
- i2c = i2ctlr->i2c;
- i2c->i2cmr = 0; /* mask all interrupts */
- i2c->i2mod &= ~EN;
-}
-
-/*
- * called by the reset routine of any driver using the I2C
- */
-void
-i2csetup(void)
-{
- IMM *io;
- I2C *i2c;
- IOCparam *sp;
- Ctlr *ctlr;
- long f, e, emin;
- int p, d, dmax;
-
- ctlr = i2ctlr;
- if(ctlr->init)
- return;
- print("i2c setup...\n");
- ctlr->init = 1;
- i2c = KADDR(INTMEM+0x860);
- ctlr->i2c = i2c;
- sp = KADDR(INTMEM+0x3c80);
- ctlr->sp = sp;
- disable();
-
- if(ctlr->txbuf == nil){
- ctlr->txbuf = ialloc(Tbuflen, 2);
- ctlr->addr = ctlr->txbuf+Bufsize;
- }
- if(ctlr->rxbuf == nil)
- ctlr->rxbuf = ialloc(Bufsize, 2);
- if(ctlr->rd == nil){
- ctlr->rd = bdalloc(1);
- ctlr->rd->addr = PADDR(ctlr->rxbuf);
- ctlr->rd->length = 0;
- ctlr->rd->status = BDWrap;
- }
- if(ctlr->td == nil){
- ctlr->td = bdalloc(2);
- ctlr->td->addr = PADDR(ctlr->txbuf);
- ctlr->td->length = 0;
- ctlr->td->status = BDWrap|BDLast;
- }
-
- /* select port pins */
- io = ioplock();
- io->pbdir |= I2CSDA | I2CSCL;
- io->pbodr |= I2CSDA | I2CSCL;
- io->pbpar |= I2CSDA | I2CSCL;
- iopunlock();
-
- /* explicitly initialise parameters, because InitRxTx can't be used (see i2c/spi relocation errata) */
- sp = ctlr->sp;
- sp->rbase = PADDR(ctlr->rd);
- sp->tbase = PADDR(ctlr->td);
- sp->rfcr = 0x18;
- sp->tfcr = 0x18;
- sp->mrblr = Bufsize;
- sp->rstate = 0;
- sp->rptr = 0;
- sp->rbptr = sp->rbase;
- sp->rcnt = 0;
- sp->tstate = 0;
- sp->tbptr = sp->tbase;
- sp->tptr = 0;
- sp->tcnt = 0;
- eieio();
-
- i2c->i2com = I2CM;
- i2c->i2mod = 0; /* normal mode */
- i2c->i2add = 0;
-
- emin = Freq;
- dmax = (m->cpuhz/Freq)/2-3;
- for(d=0; d < dmax; d++){
- for(p=3; p>=0; p--){
- f = (m->cpuhz>>(p+2))/(2*(d+3));
- e = Freq - f;
- if(e < 0)
- e = -e;
- if(e < emin){
- emin = e;
- i2c->i2brg = d;
- i2c->i2mod = (i2c->i2mod&~PDIV)|((3-p)<<1); /* set PDIV */
- }
- }
- }
- //print("i2brg=%d i2mod=#%2.2ux\n", i2c->i2brg, i2c->i2mod);
- setvec(VectorCPIC+0x10, interrupt, i2ctlr);
-}
-
-enum {
- Idling,
- Done,
- Busy,
- Sending,
- Recving,
-};
-
-static void
-interrupt(Ureg*, void *arg)
-{
- int events;
- Ctlr *ctlr;
- I2C *i2c;
-
- ctlr = arg;
- i2c = ctlr->i2c;
- events = i2c->i2cer;
- eieio();
- i2c->i2cer = events;
- if(events & (BSY|TXE)){
- //print("I2C#%x\n", events);
- if(ctlr->phase != Idling){
- ctlr->phase = Idling;
- }
- }else{
- if(events & TXB){
- //print("i2c: xmt %d %4.4ux %4.4ux\n", ctlr->phase, ctlr->td->status, ctlr->td[1].status);
- if(ctlr->phase == Sending){
- ctlr->phase = Done;
- }
- }
- if(events & RXB){
- //print("i2c: rcv %d %4.4ux %d\n", ctlr->phase, ctlr->rd->status, ctlr->rd->length);
- if(ctlr->phase == Recving){
- ctlr->phase = Done;
- }
- }
- }
-}
-
-static int
-done(void *a)
-{
- return ((Ctlr*)a)->phase < Busy;
-}
-
-static void
-i2cwait(Ctlr *ctlr)
-{
- /* TO DO: timeout */
- while(!done(ctlr)){
- if(predawn)
- interrupt(nil, ctlr);
- }
-}
-
-long
-i2csend(int addr, void *buf, long n)
-{
- Ctlr *ctlr;
- int i, p, s;
-
- ctlr = i2ctlr;
- if(n > Bufsize)
- return -1;
- i = 1;
- ctlr->txbuf[0] = addr & ~1;
- if(addr & 1){
- ctlr->txbuf[1] = addr>>8;
- i++;
- }
- memmove(ctlr->txbuf+i, buf, n);
- DCFLUSH(ctlr->txbuf, Tbuflen);
- ctlr->phase = Sending;
- ctlr->rd->status = BDEmpty|BDWrap|BDInt;
- ctlr->td->addr = PADDR(ctlr->txbuf);
- ctlr->td->length = n+i;
- ctlr->td->status = BDReady|BDWrap|BDLast|BDInt;
- enable();
- ctlr->i2c->i2com = STR|I2CM;
- eieio();
- i2cwait(ctlr);
- disable();
- p = ctlr->phase;
- s = ctlr->td->status;
- if(s & BDReady || s & TxERR || p != Done)
- return -1;
- return n;
-}
-
-long
-i2crecv(int addr, void *buf, long n)
-{
- Ctlr *ctlr;
- int p, s, flag;
- BD *td;
- long nr;
-
- ctlr = i2ctlr;
- if(n > Bufsize)
- return -1;
- ctlr->txbuf[0] = addr|Rbit;
- if(addr & 1){ /* special select sequence */
- ctlr->addr[0] = addr &~ 1;
- ctlr->addr[1] = addr>>8;
- }
- DCFLUSH(ctlr->txbuf, Tbuflen);
- DCFLUSH(ctlr->rxbuf, Bufsize);
- ctlr->phase = Recving;
- ctlr->rd->addr = PADDR(ctlr->rxbuf);
- ctlr->rd->status = BDEmpty|BDWrap|BDInt;
- flag = 0;
- td = ctlr->td;
- td[1].status = 0;
- if(addr & 1){
- /* special select sequence */
- td->addr = PADDR(ctlr->addr);
- td->length = 2;
- /* td->status made BDReady below */
- td++;
- flag = TxS;
- }
- td->addr = PADDR(ctlr->txbuf);
- td->length = n+1;
- td->status = BDReady|BDWrap|BDLast | flag; /* not BDInt: leave that to receive */
- if(flag)
- ctlr->td->status = BDReady;
- enable();
- ctlr->i2c->i2com = STR|I2CM;
- eieio();
- i2cwait(ctlr);
- disable();
- p = ctlr->phase;
- s = ctlr->td->status;
- if(flag)
- s |= ctlr->td[1].status;
- nr = ctlr->rd->length;
- if(nr > n)
- nr = n; /* shouldn't happen */
- if(s & TxERR || s & BDReady || ctlr->rd->status & BDEmpty)
- return -1;
- if(p != Done)
- return -1;
- memmove(buf, ctlr->rxbuf, nr);
- return nr;
-}
--- a/os/boot/mpc/initfads.c
+++ /dev/null
@@ -1,187 +1,0 @@
-/*
- * Called from l.s in EPROM to set up a minimal working environment.
- * Since there is no DRAM yet, and therefore no stack, no function
- * calls may be made from sysinit0, and values can't be stored,
- * except to INTMEM. Global values are accessed by offset from SB,
- * which has been set by l.s to point into EPROM.
- *
- * This is FADS-specific in CS assignment and access of the FADS BCSR
- * to discover memory size and speed.
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "archfads.h"
-
-#define MB (1024*1024)
-
-enum {
- UPMSIZE = 64, /* memory controller instruction RAM */
- SPEED = 50, /* maximum memory clock in MHz */
- SDRAMSIZE = 4*MB,
-
- /* mcr */
- WriteRAM = 0<<30,
- ReadRAM = 1<<30,
- ExecRAM = 2<<30,
-
- SelUPMA = 0<<23,
- SelUPMB = 1<<23,
-
- Once = 1<<8,
-};
-
-/*
- * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
- */
-static ulong upma50[UPMSIZE] = {
- 0x8FFFEC24, 0xFFFEC04, 0xCFFEC04, 0xFFEC04,
- 0xFFEC00, 0x37FFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x8FFFEC24, 0xFFFEC04, 0x8FFEC04, 0xFFEC0C,
- 0x3FFEC00, 0xFFEC44, 0xFFCC08, 0xCFFCC44,
- 0xFFEC0C, 0x3FFEC00, 0xFFEC44, 0xFFCC00,
- 0x3FFFC847, 0x3FFFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x11BFCC47,
- 0xC0FFCC84, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x3AFCC4C,
- 0xCAFCC00, 0x3AFCC4C, 0xCAFCC00, 0x3AFCC4C,
- 0xCAFCC00, 0x33BFCC4F, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xC0FFCC84, 0xFFCC04, 0x7FFCC04, 0x3FFFCC06,
- 0xFFFFCC85, 0xFFFFCC05, 0xFFFFCC05, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x33FFCC07, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-};
-
-/*
- * the FADS manual table 3-7 suggests the following for 60ns EDO DRAMs at 20MHz
- */
-static ulong upma20[UPMSIZE] = {
- 0x8FFFCC04, 0x08FFCC00, 0x33FFCC47, ~0, ~0, ~0, ~0, ~0,
- [0x08] 0x8FFFCC04, 0x08FFCC08, 0x08FFCC08, 0x08FFCC08, 0x08FFCC00, 0x3FFFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x18] 0x8FEFCC00, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x20] 0x8FEFCC00, 0x09AFCC48, 0x09AFCC48, 0x08AFCC48, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x30] 0x80FFCC84, 0x17FFCC04, 0xFFFFCC86, 0xFFFFCC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x3C] 0x33FFCC07, ~0, ~0, ~0,
-};
-
-void
-sysinit0(int inrom)
-{
- ulong *upm, *bcsr;
- IMM *io;
- int i, mb;
-
- io = (IMM*)INTMEM; /* running before maps, no KADDR */
-
- /* system interface unit initialisation, FADS manual table 3-2, except as noted */
- io->siumcr = 0x01012440;
- io->sypcr = 0xFFFFFF88;
- io->tbscrk = KEEP_ALIVE_KEY;
- io->tbscr = 0xC3; /* time base enabled */
- io->rtcsck = KEEP_ALIVE_KEY;
- io->rtcsc = 0xC1; /* don't FRZ, real-time clock enabled */
- io->rtcsck = ~KEEP_ALIVE_KEY;
- io->piscrk = KEEP_ALIVE_KEY;
- io->piscr = 0x82;
-
- io->memc[BCSRCS].option = 0xFFFF8110; /* 32k block, all types access, CS early negate, 1 ws */
- io->memc[BCSRCS].base = BCSRMEM | 1; /* base, 32-bit port, no parity, GPCM */
-
- io->memc[BOOTCS].base = FLASHMEM | 1;
- io->memc[BOOTCS].option = 0xFF800D54;
-
- if(!inrom)
- return; /* can't initialise DRAM controller from DRAM */
-
- bcsr = (ulong*)BCSRMEM;
-// bcsr[1] &= ~DisableDRAM;
- /* could check DRAM speed here; assume 60ns */
- switch((bcsr[2]>>23)&3){
- default: return; /* can't happen; for the compiler */
- case 0: mb = 4; break;
- case 1: mb = 32; break;
- case 2: mb = 16; break;
- case 3: mb = 8; break;
- }
-
- upm = upma50;
- for(i=0; i<UPMSIZE; i++){
- io->mdr = upm[i];
- io->mcr = WriteRAM | SelUPMA | i;
- }
- io->mptpr = 0x0400;
- if(SPEED >= 32)
- io->mamr = (0x9C<<24) | 0xA21114; /* 50MHz BRGCLK; FADS manual says 0xC0, mpc8bug sets 0x9C */
- else if(SPEED >= 20)
- io->mamr = (0x60<<24) | 0xA21114; /* 25MHz BRGCLK */
- else
- io->mamr = (0x40<<24) | 0xA21114; /* 16.67MHz BRGCLK */
- io->memc[DRAM1].option = ~((mb<<20)-1)|0x0800; /* address mask, SAM=1 */
- io->memc[DRAM1].base = 0 | 0x81; /* base at 0, 32-bit port size, no parity, UPMA */
-}
-
-/*
- * the FADS manual table 3-9's suggestion for MB811171622A-100 32+MHz-50MHz
- */
-static ulong upmb50[UPMSIZE] = {
- [0x00] 0x1F07FC04, 0xEEAEFC04, 0x11ADFC04, 0xEFBBBC00, 0x1FF77C47,
- [0x05] 0x1FF77C34, 0xEFEABC34, 0x1FB57C35,
- [0x08] 0x1F07FC04, 0xEEAEFC04, 0x10ADFC04, 0xF0AFFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x18] 0x1F27FC04, 0xEEAEBC00, 0x01B93C04, 0x1FF77C47, ~0, ~0, ~0, ~0,
- [0x20] 0x1F07FC04, 0xEEAEBC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x30] 0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC07, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x3C] 0x7FFFFC07, ~0, ~0, ~0,
-};
-
-/*
- * the FADS manual table 3-8's suggestion for MB811171622A-100 up to 32MHz
- */
-static ulong upmb32[UPMSIZE] = {
- [0x00] 0x126CC04, 0xFB98C00, 0x1FF74C45, ~0, ~0,
- [0x05] 0x1FE77C34, 0xEFAABC34, 0x1FA57C35,
- [0x08] 0x0026FC04, 0x10ADFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x18] 0x0E26BC04, 0x01B93C00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0,
- [0x20] 0x0E26BC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x30] 0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x3C] 0x7FFFFC07, ~0, ~0, ~0,
-};
-
-/*
- * optionally called by archfads.c:/^archinit to initialise access to SDRAM
- */
-void
-sdraminit(ulong base)
-{
- ulong *upm;
- IMM *io;
- int i;
-
- io = (IMM*)INTMEM; /* running before maps, no KADDR */
- if(SPEED > 32)
- upm = upmb50;
- else
- upm = upmb32;
- for(i=0; i<UPMSIZE; i++){
- io->mdr = upm[i];
- io->mcr = WriteRAM | SelUPMB | i;
- }
- io->memc[SDRAM].option = ~(SDRAMSIZE-1)|0x0A00; /* address mask, SAM=1, G5LS=1 */
- io->memc[SDRAM].base = base | 0xC1;
- if(SPEED > 32){
- io->mbmr = 0xD0802114; /* 50MHz BRGCLK */
- io->mar = 0x88;
- }else{
- io->mbmr = 0x80802114; /* 32MHz BRGCLK */
- io->mar = 0x48;
- }
- io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 5; /* run MRS command in locations 5-8 of UPMB */
- io->mbmr = (io->mbmr & ~0xF) | 8;
- io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 0x30; /* run refresh sequence */
- io->mbmr = (io->mbmr & ~0xF) | 4; /* 4-beat refresh bursts */
-}
--- a/os/boot/mpc/initpaq.c
+++ /dev/null
@@ -1,101 +1,0 @@
-/*
- * Called from l.s in EPROM to set up a minimal working environment.
- * Since there is no DRAM yet, and therefore no stack, no function
- * calls may be made from sysinit0, and values can't be stored,
- * except to INTMEM. Global values are accessed by offset from SB,
- * which has been set by l.s to point into EPROM.
- *
- * This is PowerPAQ-specific:
- * - assumes 8mbytes
- * - powerpaq CS assignment
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "archpaq.h"
-
-#define MB (1024*1024)
-
-enum {
- DRAMSIZE = 8*MB,
- FLASHSIZE = 8*MB,
-
- UPMSIZE = 64, /* memory controller instruction RAM */
- SPEED = 50, /* maximum memory clock in MHz */
-
- /* mcr */
- WriteRAM = 0<<30,
- ReadRAM = 1<<30,
- ExecRAM = 2<<30,
-
- SelUPMA = 0<<23,
- SelUPMB = 1<<23,
-
- Once = 1<<8,
-};
-
-/*
- * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
- */
-static ulong upmb50[UPMSIZE] = {
- 0x8FFFEC24, 0xFFFEC04, 0xCFFEC04, 0xFFEC04,
- 0xFFEC00, 0x37FFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x8FFFEC24, 0xFFFEC04, 0x8FFEC04, 0xFFEC0C,
- 0x3FFEC00, 0xFFEC44, 0xFFCC08, 0xCFFCC44,
- 0xFFEC0C, 0x3FFEC00, 0xFFEC44, 0xFFCC00,
- 0x3FFFC847, 0x3FFFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x11BFCC47,
- 0xC0FFCC84, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x3AFCC4C,
- 0xCAFCC00, 0x3AFCC4C, 0xCAFCC00, 0x3AFCC4C,
- 0xCAFCC00, 0x33BFCC4F, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xC0FFCC84, 0xFFCC04, 0x7FFCC04, 0x3FFFCC06,
- 0xFFFFCC85, 0xFFFFCC05, 0xFFFFCC05, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x33FFCC07, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-};
-
-void
-sysinit0(int inrom)
-{
- ulong *upm;
- IMM *io;
- int i;
-
- io = (IMM*)INTMEM; /* running before maps, no KADDR */
-
- /* system interface unit initialisation, FADS manual table 3-2, except as noted */
- io->siumcr = 0x01012440;
- io->sypcr = 0xFFFFFF88;
- io->tbscrk = KEEP_ALIVE_KEY;
- io->tbscr = 0xC3; /* time base enabled */
- io->rtcsck = KEEP_ALIVE_KEY;
- io->rtcsc = 0xC1; /* don't FRZ, real-time clock enabled */
- io->rtcsck = ~KEEP_ALIVE_KEY;
- io->piscrk = KEEP_ALIVE_KEY;
- io->piscr = 0x82;
-
- io->memc[BOOTCS].base = FLASHMEM | 1;
- io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(2<<4); /* mask, BIH, 2 wait states */
-
- if(!inrom)
- return; /* can't initialise DRAM controller from DRAM */
-
- /* could check DRAM speed here; assume 60ns */
- /* could probe DRAM for size here; assume DRAMSIZE */
- io->mptpr = 0x400; /* powerpaq flash has 0x1000 */
- io->mbmr = (0xC0<<24) | 0xA21114; /* 50MHz BRGCLK */
- upm = upmb50;
- for(i=0; i<UPMSIZE; i++){
- io->mdr = upm[i];
- io->mcr = WriteRAM | SelUPMB | i;
- }
- io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0800; /* address mask, SAM=1 */
- io->memc[DRAM1].base = 0 | 0xC1; /* base at 0, 32-bit port size, no parity, UPMB */
-}
--- a/os/boot/mpc/initrpcg.c
+++ /dev/null
@@ -1,91 +1,0 @@
-
-/*
- * Called from l.s in EPROM to set up a minimal working environment.
- * Since there is no DRAM yet, and therefore no stack, no function
- * calls may be made from sysinit, and values can't be stored,
- * except to INTMEM. Global values are accessed by offset from SB,
- * which has been set by l.s to point into EPROM.
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "archrpcg.h"
-
-#define MB (1024*1024)
-
-enum {
- UPMSIZE = 64, /* memory controller instruction RAM */
- DRAMSIZE = 16*MB,
- FLASHSIZE = 4*MB,
-
- WriteRAM = 0<<30,
- ReadRAM = 1<<30,
- ExecRAM = 2<<30,
-
- SelUPMA = 0<<23,
- SelUPMB = 1<<23,
-};
-/* RPCG values for RPXLite AW */
-static ulong upma50[UPMSIZE] = {
- 0xCFFFCC24, 0x0FFFCC04, 0x0CAFCC04, 0x03AFCC08,
- 0x3FBFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xCFFFCC24, 0x0FFFCC04, 0x0CAFCC84, 0x03AFCC88,
- 0x3FBFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC04, 0x03FFCC00,
- 0x3FFFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC84, 0x03FFCC84,
- 0x0CFFCC00, 0x33FFCC27, 0xFFFFCC25, 0xFFFFCC25,
- 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xC0FFCC24, 0x03FFCC24, 0x0FFFCC24, 0x0FFFCC24,
- 0x3FFFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
-};
-
-void
-sysinit0(int inrom)
-{
- ulong *upm;
- IMM *io;
- int i;
-
- io = (IMM*)INTMEM; /* running before maps, no KADDR */
- io->siumcr = 0x01012440;
- io->sypcr = 0xFFFFFF88;
- io->tbscrk = KEEP_ALIVE_KEY;
- io->tbscr = 0xC3;
- io->rtcsck = KEEP_ALIVE_KEY;
- io->rtcsc = 0xC1;
- io->rtcsck = ~KEEP_ALIVE_KEY;
- io->piscrk = KEEP_ALIVE_KEY;
- io->piscr = 0x82;
-return;
- io->memc[BCSRCS].option = 0xFFFF8910; /* 32k block, all types access, CSNT, CS early negate, burst inhibit, 1 ws */
- io->memc[BCSRCS].base = BCSRMEM | 1; /* base, 32-bit port, no parity, GPCM */
-
- io->memc[BOOTCS].base = FLASHMEM | 0x801; /* base, 16 bit port */
- io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(4<<4); /* mask, BIH, 4 wait states */
-
- if(1||!inrom)
- return; /* can't initialise DRAM controller from DRAM */
-
- /* TO DO: could check DRAM size and speed now */
-
- upm = upma50;
- for(i=0; i<nelem(upma50); i++){
- io->mdr = upm[i];
- io->mcr = WriteRAM | SelUPMA | i;
- }
- io->mptpr = 0x0800; /* divide by 8 */
- io->mamr = (0x58<<24) | 0xA01430; /* 40MHz BRGCLK */
- io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0E00; /* address mask, SAM=1, G5LA/S=3 */
- io->memc[DRAM1].base = 0 | 0x81; /* base at 0, 32-bit port size, no parity, UPMA */
-}
--- a/os/boot/mpc/io.h
+++ /dev/null
@@ -1,463 +1,0 @@
-enum
-{
- /* software interrupt vectors (SIU and CPM) */
- VectorPIC= 0, /* level 0 to level 7, assigned by software */
- CPIClevel= 4,
- VectorIRQ= VectorPIC+8, /* IRQ0 to IRQ7 */
- VectorCPIC= VectorIRQ+8, /* 32 CPM interrupts: 0 (error) to 0x1F (PC15) */
-};
-
-enum
-{
- BUSUNKNOWN = 0,
-};
-
-/*
- * Buffer Descriptors and IO Rings
- */
-
-typedef struct BD BD;
-struct BD {
- ushort status;
- ushort length;
- ulong addr;
-};
-
-BD* bdalloc(int);
-void bdfree(BD*, int);
-
-enum {
- /* Rx BDs, bits common to all protocols */
- BDEmpty= 1<<15,
- BDWrap= 1<<13,
- BDInt= 1<<12,
- BDLast= 1<<11,
- BDFirst= 1<<10,
-
- /* Tx BDs */
- BDReady= 1<<15,
- /* BDWrap, BDInt, BDLast */
-};
-
-typedef struct Ring Ring;
-struct Ring {
- BD* rdr; /* receive descriptor ring */
- void* rrb; /* receive ring buffers */
- int rdrx; /* index into rdr */
- int nrdre; /* length of rdr */
-
- BD* tdr; /* transmit descriptor ring */
- Block** txb; /* corresponding transmit ring buffers */
- int tdrh; /* host index into tdr */
- int tdri; /* interface index into tdr */
- int ntdre; /* length of tdr */
- int ntq; /* pending transmit requests */
-};
-
-#define NEXT(x, l) (((x)+1)%(l))
-#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
-#define HOWMANY(x, y) (((x)+((y)-1))/(y))
-#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
-
-int ioringinit(Ring*, int, int, int);
-
-/*
- * CPM
- */
-enum {
- /* commands */
- InitRxTx = 0,
- InitRx = 1,
- InitTx = 2,
- EnterHunt= 3,
- StopTx= 4,
- GracefulStopTx = 5,
- InitIDMA = 5,
- RestartTx = 6,
- CloseRxBD = 7,
- SetGroupAddr = 8,
- SetTimer = 8,
- GCITimeout = 9,
- GCIAbort = 10,
- StopIDMA = 11,
- StartDSP = 12,
- ArmIDMA = 13,
- InitDSP = 13,
- USBCmd = 15,
-
- /* channel IDs */
- SCC1ID= 0,
- USBID= 0,
- I2CID= 1,
- IDMA1ID= 1,
- SCC2ID= 4,
- SPIID= 5,
- IDMA2ID= 5,
- TIMERID= 5,
- SCC3ID= 8,
- SMC1ID= 9,
- DSP1ID=9,
- SCC4ID= 12,
- SMC2ID= 13,
- DSP2ID= 13,
-
- BaudEnable = 1<<16,
-
- /* sicr */
- CLK1 = 4, /* SCC1,2 */
- CLK2 = 5,
- CLK3 = 6,
- CLK4 = 7,
- CLK5 = CLK1, /* SCC3,4 */
- CLK6 = CLK2,
- CLK7 = CLK3,
- CLK8 = CLK4,
-};
-
-void cpmop(int, int, int);
-#define ioplock() (m->iomem)
-#define iopunlock()
-
-/*
- * the structures below follow hardware/firmware layouts in the 8xx manuals:
- * mind the data types, offsets and alignment
- */
-
-/*
- * basic IO controller parameters (SMC and SCC)
- */
-typedef struct IOCparam IOCparam;
-struct IOCparam {
- ushort rbase;
- ushort tbase;
- uchar rfcr;
- uchar tfcr;
- ushort mrblr;
- ulong rstate;
- ulong rptr;
- ushort rbptr;
- ushort rcnt;
- ulong rtmp;
- ulong tstate;
- ulong tptr;
- ushort tbptr;
- ushort tcnt;
- ulong ttmp;
-};
-
-typedef struct SCCparam SCCparam;
-struct SCCparam {
- IOCparam;
- ulong rcrc;
- ulong tcrc;
-};
-
-typedef struct SCC SCC;
-struct SCC {
- ulong gsmrl;
- ulong gsmrh;
- ushort psmr;
- uchar rsvscc0[2];
- ushort todr;
- ushort dsr;
- ushort scce;
- uchar rsvscc1[2];
- ushort sccm;
- uchar rsvscc3;
- uchar sccs;
- ushort irmode;
- ushort irsip;
-};
-
-typedef struct SMC SMC;
-struct SMC {
- uchar pad1[2];
- ushort smcmr;
- uchar pad2[2];
- uchar smce;
- uchar pad3[3];
- uchar smcm;
- uchar pad4[5];
-};
-
-typedef struct SPI SPI;
-struct SPI {
- ushort spmode;
- uchar res1[4];
- uchar spie;
- uchar res2[3];
- uchar spim;
- uchar res3[2];
- uchar spcom;
- uchar res4[10];
-};
-
-typedef struct USB USB;
-struct USB { /* 823 only */
- uchar usmod;
- uchar usadr;
- uchar uscom;
- uchar rsvu1;
- ushort usep[4];
- uchar rsvu2[4];
- ushort usber;
- uchar rsvu3[2];
- ushort usbmr;
- uchar rsvu4;
- uchar usbs;
- uchar rsvu5[8];
-};
-
-typedef struct IMM IMM;
-struct IMM {
- struct { /* general SIU */
- ulong siumcr;
- ulong sypcr;
- uchar rsv0[0xE-0x8];
- ushort swsr;
- ulong sipend;
- ulong simask;
- ulong siel;
- uchar sivec;
- uchar padv[3];
- ulong tesr;
- uchar rsv1[0x30-0x24];
- ulong sdcr;
- uchar rsv2[0x80-0x34];
- };
- struct { /* PCMCIA */
- struct {
- ulong base;
- ulong option;
- } pcmr[8];
- uchar rsv3[0xe0-0xc0];
- ulong pgcra;
- ulong pgcrb;
- ulong pscr;
- uchar rsv4[0xf0-0xec];
- ulong pipr;
- uchar rsv5[4];
- ulong per;
- uchar rsv6[4];
- };
- struct { /* MEMC */
- struct {
- ulong base;
- ulong option;
- } memc[8];
- uchar rsv7a[0x24];
- ulong mar;
- ulong mcr;
- uchar rsv7b[4];
- ulong mamr;
- ulong mbmr;
- ushort mstat;
- ushort mptpr;
- ulong mdr;
- uchar rsv7c[0x80];
- };
- struct { /* system integration timers */
- ushort tbscr;
- uchar rsv8a[2];
- ulong tbrefu;
- ulong tbrefl;
- uchar rsv8b[0x14];
- ushort rtcsc;
- uchar rsv8c[2];
- ulong rtc;
- ulong rtsec;
- ulong rtcal;
- uchar rsv8d[0x10];
- ushort piscr;
- ushort rsv8e;
- ulong pitc;
- ulong pitr;
- uchar rsv8f[0x34];
- };
- struct { /* 280: clocks and resets */
- ulong sccr;
- ulong plprcr;
- ulong rsr;
- uchar rsv9[0x300-0x28c];
- };
- struct { /* 300: system integration timers keys */
- ulong tbscrk;
- ulong tbrefuk;
- ulong tbreflk;
- ulong tbk;
- uchar rsv10a[0x10];
- ulong rtcsck;
- ulong rtck;
- ulong rtseck;
- ulong rtcalk;
- uchar rsv10b[0x10];
- ulong piscrk;
- ulong pitck;
- uchar rsv10c[0x38];
- };
- struct { /* 380: clocks and resets keys */
- ulong sccrk;
- ulong plprcrk;
- ulong rsrk;
- uchar rsv11[0x800-0x38C];
- };
- struct { /* 800: video controller */
- ushort vccr;
- ushort pad11a;
- uchar vsr;
- uchar pad11b;
- uchar vcmr;
- uchar pad11c;
- ulong vbcb;
- ulong pad11d;
- ulong vfcr0;
- ulong vfaa0;
- ulong vfba0;
- ulong vfcr1;
- ulong vfaa1;
- ulong vfba1;
- uchar rsv11a[0x840-0x828];
- };
- struct { /* 840: LCD */
- ulong lccr;
- ulong lchcr;
- ulong lcvcr;
- ulong rsv11b;
- ulong lcfaa;
- ulong lcfba;
- uchar lcsr;
- uchar rsv11c[0x860-0x859];
- };
- struct { /* 860: I2C */
- uchar i2mod;
- uchar rsv12a[3];
- uchar i2add;
- uchar rsv12b[3];
- uchar i2brg;
- uchar rsv12c[3];
- uchar i2com;
- uchar rsv12d[3];
- uchar i2cer;
- uchar rsv12e[3];
- uchar i2cmr;
- uchar rsv12[0x900-0x875];
- };
- struct { /* 900: DMA */
- uchar rsv13[4];
- ulong sdar;
- uchar sdsr;
- uchar pad1[3];
- uchar sdmr;
- uchar pad2[3];
- uchar idsr1;
- uchar pad3[3];
- uchar idmr1;
- uchar pad4[3];
- uchar idsr2;
- uchar pad5[3];
- uchar idmr2;
- uchar pad6[0x930-0x91D];
- };
- struct { /* CPM interrupt control */
- ushort civr;
- uchar pad7[0x940-0x932];
- ulong cicr;
- ulong cipr;
- ulong cimr;
- ulong cisr;
- };
- struct { /* input/output port */
- ushort padir;
- ushort papar;
- ushort paodr;
- ushort padat;
- uchar pad8[8];
- ushort pcdir;
- ushort pcpar;
- ushort pcso;
- ushort pcdat;
- ushort pcint;
- uchar pad9[6];
- ushort pddir;
- ushort pdpar;
- ushort rsv14a;
- ushort pddat;
- uchar rsv14[0x980-0x978];
- };
- struct { /* CPM timers */
- ushort tgcr;
- uchar rsv15a[0x990-0x982];
- ushort tmr1;
- ushort tmr2;
- ushort trr1;
- ushort trr2;
- ushort tcr1;
- ushort tcr2;
- ushort tcn1;
- ushort tcn2;
- ushort tmr3;
- ushort tmr4;
- ushort trr3;
- ushort trr4;
- ushort tcr3;
- ushort tcr4;
- ushort tcn3;
- ushort tcn4;
- ushort ter1;
- ushort ter2;
- ushort ter3;
- ushort ter4;
- uchar rsv15[0x9C0-0x9B8];
- };
- struct { /* CPM */
- ushort cpcr;
- uchar res0[2];
- ushort rccr;
- uchar res1;
- uchar rmds;
- uchar res2a[4];
- ushort rctr1;
- ushort rctr2;
- ushort rctr3;
- ushort rctr4;
- uchar res2[2];
- ushort rter;
- uchar res3[2];
- ushort rtmr;
- uchar rsv16[0x9F0-0x9DC];
- };
- union { /* BRG */
- struct {
- ulong brgc1;
- ulong brgc2;
- ulong brgc3;
- ulong brgc4;
- };
- ulong brgc[4];
- };
- uchar skip0[0xAB2-0xA00]; /* USB, SCC, SMC, SPI: address using cpmdev(CP...)->regs */
- struct { /* PIP */
- ushort pipc; /* not 823 */
- ushort ptpr; /* not 823 */
- ulong pbdir;
- ulong pbpar;
- uchar pad10[2];
- ushort pbodr;
- ulong pbdat;
- uchar pad11[0xAE0-0xAC8];
- };
- struct { /* SI */
- ulong simode;
- uchar sigmr;
- uchar pad12;
- uchar sistr;
- uchar sicmr;
- uchar pad13[4];
- ulong sicr;
- ulong sirp;
- uchar pad14[0xB00-0xAF4];
- };
- ulong vcram[64];
- ushort siram[256];
- ushort lcdmap[256];
-};
--- a/os/boot/mpc/ip.h
+++ /dev/null
@@ -1,98 +1,0 @@
-typedef struct Udphdr Udphdr;
-struct Udphdr
-{
- uchar d[6]; /* Ethernet destination */
- uchar s[6]; /* Ethernet source */
- uchar type[2]; /* Ethernet packet type */
-
- uchar vihl; /* Version and header length */
- uchar tos; /* Type of service */
- uchar length[2]; /* packet length */
- uchar id[2]; /* Identification */
- uchar frag[2]; /* Fragment information */
-
- /* Udp pseudo ip really starts here */
- uchar ttl;
- uchar udpproto; /* Protocol */
- uchar udpplen[2]; /* Header plus data length */
- uchar udpsrc[4]; /* Ip source */
- uchar udpdst[4]; /* Ip destination */
- uchar udpsport[2]; /* Source port */
- uchar udpdport[2]; /* Destination port */
- uchar udplen[2]; /* data length */
- uchar udpcksum[2]; /* Checksum */
-};
-
-typedef struct Etherhdr Etherhdr;
-struct Etherhdr
-{
- uchar d[6];
- uchar s[6];
- uchar type[2];
-
- /* Now we have the ip fields */
- uchar vihl; /* Version and header length */
- uchar tos; /* Type of service */
- uchar length[2]; /* packet length */
- uchar id[2]; /* Identification */
- uchar frag[2]; /* Fragment information */
- uchar ttl; /* Time to live */
- uchar proto; /* Protocol */
- uchar cksum[2]; /* Header checksum */
- uchar src[4]; /* Ip source */
- uchar dst[4]; /* Ip destination */
-};
-
-enum
-{
- IP_VER = 0x40,
- IP_HLEN = 0x05,
- UDP_EHSIZE = 22,
- UDP_PHDRSIZE = 12,
- UDP_HDRSIZE = 20,
- ETHER_HDR = 14,
- IP_UDPPROTO = 17,
- ET_IP = 0x800,
- Bcastip = 0xffffffff,
- BPportsrc = 68,
- BPportdst = 67,
- TFTPport = 69,
- Timeout = 5000, /* milliseconds */
- Bootrequest = 1,
- Bootreply = 2,
- Tftp_READ = 1,
- Tftp_WRITE = 2,
- Tftp_DATA = 3,
- Tftp_ACK = 4,
- Tftp_ERROR = 5,
- Segsize = 512,
- TFTPSZ = Segsize+10,
-};
-
-typedef struct Bootp Bootp;
-struct Bootp
-{
- uchar op; /* opcode */
- uchar htype; /* hardware type */
- uchar hlen; /* hardware address len */
- uchar hops; /* hops */
- uchar xid[4]; /* a random number */
- uchar secs[2]; /* elapsed snce client started booting */
- uchar pad[2];
- uchar ciaddr[4]; /* client IP address (client tells server) */
- uchar yiaddr[4]; /* client IP address (server tells client) */
- uchar siaddr[4]; /* server IP address */
- uchar giaddr[4]; /* gateway IP address */
- uchar chaddr[16]; /* client hardware address */
- char sname[64]; /* server host name (optional) */
- char file[128]; /* boot file name */
- char vend[128]; /* vendor-specific goo */
-};
-
-typedef struct Netaddr Netaddr;
-struct Netaddr
-{
- ulong ip;
- ushort port;
- char ea[Eaddrlen];
-};
--- a/os/boot/mpc/l.s
+++ /dev/null
@@ -1,370 +1,0 @@
-#include "mem.h"
-
-/* special instruction definitions */
-#define BDNE BC 0,2,
-#define BDNZ BC 16,0,
-#define NOOP OR R0,R0,R0
-
-/*
- * common ppc special purpose registers
- */
-#define DSISR 18
-#define DAR 19 /* Data Address Register */
-#define DEC 22 /* Decrementer */
-#define SRR0 26 /* Saved Registers (exception) */
-#define SRR1 27
-#define SPRG0 272 /* Supervisor Private Registers */
-#define SPRG1 273
-#define SPRG2 274
-#define SPRG3 275
-#define TBRU 269 /* Time base Upper/Lower (Reading) */
-#define TBRL 268
-#define TBWU 285 /* Time base Upper/Lower (Writing) */
-#define TBWL 284
-#define PVR 287 /* Processor Version */
-
-/*
- * mpc82x-specific special purpose registers of interest here
- */
-#define EIE 80
-#define EID 81
-#define NRI 82
-#define IMMR 638
-#define IC_CST 560
-#define IC_ADR 561
-#define IC_DAT 562
-#define DC_CST 568
-#define DC_ADR 569
-#define DC_DAT 570
-#define MI_CTR 784
-#define MI_AP 786
-#define MI_EPN 787
-#define MI_TWC 789
-#define MI_RPN 790
-#define MI_DBCAM 816
-#define MI_DBRAM0 817
-#define MI_DBRAM1 818
-#define MD_CTR 792
-#define M_CASID 793
-#define MD_AP 794
-#define MD_EPN 795
-#define M_TWB 796
-#define MD_TWC 797
-#define MD_RPN 798
-#define M_TW 799
-#define MD_DBCAM 824
-#define MD_DBRAM0 825
-#define MD_DBRAM1 826
-
-/* as on 603e, apparently mtmsr needs help in some chip revisions */
-#define WAITMSR SYNC; ISYNC
-
-/* use of SPRG registers in save/restore */
-#define SAVER0 SPRG0
-#define SAVER1 SPRG1
-#define SAVELR SPRG2
-#define SAVECR SPRG3
-
-#define UREGSIZE ((8+32)*4)
-#define UREGSPACE (UREGSIZE+8) /* allow for arg to trap, and align */
-
-/*
- * This code is loaded by the ROM loader at location 0x3000,
- * or lives in flash memory at 0x2800100.
- * Move it to high memory so that it can load the kernel at 0x0000.
- */
-
-#define LOADCODEBASE 0x3000 /* when downloaded in S records */
-#define FLASHCODEBASE (FLASHMEM+0x100) /* when in flash */
-
- TEXT start(SB), $-4
- MOVW MSR, R3
- MOVW $(EE|IP|RI), R4
- ANDN R4, R3
- OR $ME, R3
- SYNC
- MOVW R3, MSR /* turn off interrupts but enable traps */
- WAITMSR
-
-/*
- * reset the caches and disable them for now
- */
- MOVW SPR(IC_CST), R4 /* read and clear */
- MOVW $(5<<25), R4
- MOVW R4, SPR(IC_CST) /* unlock all */
- ISYNC
- MOVW $(6<<25), R4
- MOVW R4, SPR(IC_CST) /* invalidate all */
- ISYNC
- MOVW $(2<<25), R4
- MOVW R4, SPR(IC_CST) /* disable i-cache */
- ISYNC
-
- SYNC
- MOVW SPR(DC_CST), R4 /* read and clear */
- MOVW $(10<<24), R4
- MOVW R4, SPR(DC_CST) /* unlock all */
- ISYNC
- MOVW $(12<<24), R4
- MOVW R4, SPR(DC_CST) /* invalidate all */
- ISYNC
- MOVW $(4<<24), R4
- MOVW R4, SPR(DC_CST) /* disable i-cache */
- ISYNC
-
- MOVW $7, R4
-ANDN R4, R4, R4
- MOVW R4, SPR(158) /* cancel `show cycle' for normal instruction execution */
-
-/*
- * set other system configuration values
- */
- MOVW SPR(IMMR), R5 /* save initial space pointer */
- MOVW $INTMEM, R4
- MOVW R4, SPR(IMMR) /* set internal memory base */
- MOVW $0xFFFFFF88, R3
- MOVW R3, 4(R4) /* disable watchdog in sypcr */
- MOVW $0x01012440, R3
- MOVW R3, 0(R4) /* siumcr */
-
-/*
- * system initialisation (init and map DRAM)
- */
- MOVW $0, R0
- MOVW $setSB(SB), R2
- MOVW $(0xF000<<16), R3
-/*MOVW R0, R3*/
- ANDCC R5, R3 /* initial space is high? */
- BEQ notrom
- MOVW $FLASHCODEBASE, R5 /* where $start(SB) actually is now */
- MOVW $start(SB), R4 /* logical start address */
- SUB R4, R5, R6 /* text relocation value */
- MOVW $etext(SB), R7
- SUB R4, R7
- ADD R5, R7 /* data address in ROM */
- MOVW $bdata(SB), R8
- SUB R8, R2
- ADD R7, R2 /* relocate SB: SB' = romdata+(SB-bdata) */
- MOVW $sysinit0(SB), R4
- ADD R6, R4 /* relocate sysinit0's address */
- MOVW R4, CTR
- MOVW $inmem(SB), R4
- ADD R6, R4
- MOVW R4, LR /* and the return address */
- BR (CTR) /* call sysinit0 */
- TEXT inmem(SB), $-4
- MOVW $FLASHCODEBASE, R3
- BR cpu0
-notrom:
- MOVW $start(SB), R6
- SUB R6, R2
- ADD $LOADCODEBASE, R2
- BL sysinit0(SB)
- MOVW $LOADCODEBASE, R3
-
-/*
- * cpu 0
- * relocate bootstrap to our link addresses for text and data
- * set new PC
- */
-cpu0:
- MOVW $setSB(SB), R2 /* set correct static base register */
- MOVW $start(SB), R4
- MOVW $etext(SB), R5
- SUB R4, R5
- CMP R4, R3 /* already there? */
- BNE copytext
- ADD R5, R3 /* start of data image */
- BR copydata
-
-copytext:
- ADD $3, R5
- SRAW $2, R5
- MOVW R5, CTR
- SUB $4, R4
- SUB $4, R3
-copyt: /* copy text */
- MOVWU 4(R3), R5
- MOVWU R5, 4(R4)
- BDNZ copyt
- ADD $4, R3
-
-copydata:
- /* copy data */
- MOVW $bdata(SB), R4
- CMP R4, R3 /* already there? */
- BEQ loadkpc
- MOVW $edata(SB), R5
- SUB R4, R5
- ADD $3, R5
- SRAW $2, R5
- MOVW R5, CTR
- SUB $4, R4
- SUB $4, R3
-copyd:
- MOVWU 4(R3), R5
- MOVWU R5, 4(R4)
- BDNZ copyd
-
- /* load correct PC */
-loadkpc:
- MOVW $start1(SB), R3
- MOVW R3, LR
- BR (LR)
-TEXT start1(SB), $-4
- MOVW $edata(SB), R3
- MOVW $end(SB), R4
- SUBCC R3, R4
- BLE skipz
- SRAW $2, R4
- MOVW R4, CTR
- SUB $4, R3
- MOVW $0, R0
-zero:
- MOVWU R0, 4(R3)
- BDNZ zero
-skipz:
- MOVW $mach0(SB), R1
- MOVW R1, m(SB)
- ADD $(MACHSIZE-8), R1
- MOVW $0, R0
- BL main(SB)
- BR 0(PC)
-
-TEXT getmsr(SB), $0
- MOVW MSR, R3
- RETURN
-
-TEXT putmsr(SB), $0
- SYNC
- MOVW R3, MSR
- WAITMSR
- RETURN
-
-TEXT eieio(SB), $0
- EIEIO
- RETURN
-
-TEXT idle(SB), $0
- RETURN
-
-TEXT spllo(SB), $0
- MOVW MSR, R3
- OR $EE, R3, R4
- SYNC
- MOVW R4, MSR
- WAITMSR
- RETURN
-
-TEXT splhi(SB), $0
- MOVW MSR, R3
- RLWNM $0, R3, $~EE, R4
- SYNC
- MOVW R4, MSR
- WAITMSR
- RETURN
-
-TEXT splx(SB), $0
- MOVW MSR, R4
- RLWMI $0, R3, $EE, R4
- SYNC
- MOVW R4, MSR
- WAITMSR
- RETURN
-
-TEXT gettbl(SB), $0
-/* MOVW SPR(TBRL), R3 */
- WORD $0x7c6c42e6 /* mftbl on 8xx series */
- RETURN
-
-TEXT getpvr(SB), $0
- MOVW SPR(PVR), R3
- RETURN
-
-TEXT getimmr(SB), $0
- MOVW SPR(IMMR), R3
- RETURN
-
-TEXT getdec(SB), $0
- MOVW SPR(DEC), R3
- RETURN
-
-TEXT putdec(SB), $0
- MOVW R3, SPR(DEC)
- RETURN
-
-/*
- * save state in Ureg on kernel stack.
- * enter with R0 giving the PC from the call to `exception' from the vector.
- * on return, SB (R2) has been set, and R3 has the Ureg*
- */
-TEXT saveureg(SB), $-4
- SUB $UREGSPACE, R1
- MOVMW R2, 48(R1) /* r2:r31 */
- MOVW $setSB(SB), R2
- MOVW SPR(SAVER1), R4
- MOVW R4, 44(R1)
- MOVW SPR(SAVER0), R5
- MOVW R5, 40(R1)
- MOVW CTR, R6
- MOVW R6, 36(R1)
- MOVW XER, R4
- MOVW R4, 32(R1)
- MOVW SPR(SAVECR), R5 /* CR */
- MOVW R5, 28(R1)
- MOVW SPR(SAVELR), R6 /* LR */
- MOVW R6, 24(R1)
- /* pad at 20(R1) */
- MOVW SPR(SRR0), R4
- MOVW R4, 16(R1) /* old PC */
- MOVW SPR(SRR1), R5
- MOVW R5, 12(R1)
- MOVW R0, 8(R1) /* cause/vector, encoded in LR from vector */
- ADD $8, R1, R3 /* Ureg* */
- STWCCC R3, (R1) /* break any pending reservations */
- MOVW $0, R0 /* R0ISZERO */
- BR (LR)
-
-/*
- * restore state from Ureg
- * SB (R2) is unusable on return
- */
-TEXT restoreureg(SB), $-4
- MOVMW 48(R1), R2 /* r2:r31 */
- /* defer R1 */
- MOVW 40(R1), R0
- MOVW R0, SPR(SAVER0)
- MOVW 36(R1), R0
- MOVW R0, CTR
- MOVW 32(R1), R0
- MOVW R0, XER
- MOVW 28(R1), R0
- MOVW R0, CR /* CR */
- MOVW 24(R1), R0
- MOVW R0, SPR(SAVELR) /* LR */
- /* pad, skip */
- MOVW 16(R1), R0
- MOVW R0, SPR(SRR0) /* old PC */
- MOVW 12(R1), R0
- MOVW R0, SPR(SRR1) /* old MSR */
- /* cause, skip */
- MOVW 44(R1), R1 /* old SP */
- BR (LR)
-
-TEXT exception(SB), $-4
- MOVW R1, SPR(SAVER1)
- MOVW CR, R0
- MOVW R0, SPR(SAVECR)
- MOVW LR, R0
- BL saveureg(SB)
- MOVW $0, R0
- BL trap(SB)
- BL restoreureg(SB)
- MOVW SPR(SAVELR), R0
- MOVW R0, LR
- MOVW SPR(SAVER0), R0
- ISYNC
- RFI
-
-GLOBL mach0+0(SB), $MACHSIZE
-GLOBL m(SB), $4
--- a/os/boot/mpc/lib.h
+++ /dev/null
@@ -1,106 +1,0 @@
-/*
- * functions (possibly) linked in, complete, from libc.
- */
-
-/*
- * mem routines
- */
-extern void* memccpy(void*, void*, int, long);
-extern void* memset(void*, int, long);
-extern int memcmp(void*, void*, long);
-extern void* memmove(void*, void*, long);
-extern void* memchr(void*, int, long);
-
-/*
- * string routines
- */
-extern char* strcat(char*, char*);
-extern char* strchr(char*, char);
-extern int strcmp(char*, char*);
-extern char* strcpy(char*, char*);
-extern char* strncat(char*, char*, long);
-extern char* strncpy(char*, char*, long);
-extern int strncmp(char*, char*, long);
-extern long strlen(char*);
-extern char* strrchr(char*, char);
-extern char* strstr(char*, char*);
-
-/*
- * print routines
- * Fconv isn't used but is defined to satisfy prototypes in libg.h
- * that are never called.
- */
-typedef struct Fconv Fconv;
-
-extern char* donprint(char*, char*, char*, void*);
-extern int sprint(char*, char*, ...);
-extern int print(char*, ...);
-
-#define PRINTSIZE 256
-
-/*
- * one-of-a-kind
- */
-extern int atoi(char*);
-extern long strtol(char*, char**, int);
-extern ulong strtoul(char*, char**, int);
-extern long end;
-
-/*
- * Syscall data structures
- */
-
-#define MORDER 0x0003 /* mask for bits defining order of mounting */
-#define MREPL 0x0000 /* mount replaces object */
-#define MBEFORE 0x0001 /* mount goes before others in union directory */
-#define MAFTER 0x0002 /* mount goes after others in union directory */
-#define MCREATE 0x0004 /* permit creation in mounted directory */
-#define MMASK 0x0007 /* all bits on */
-
-#define OREAD 0 /* open for read */
-#define OWRITE 1 /* write */
-#define ORDWR 2 /* read and write */
-#define OEXEC 3 /* execute, == read but check execute permission */
-#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
-#define OCEXEC 32 /* or'ed in, close on exec */
-#define ORCLOSE 64 /* or'ed in, remove on close */
-
-#define NCONT 0 /* continue after note */
-#define NDFLT 1 /* terminate after note */
-
-typedef struct Qid Qid;
-typedef struct Dir Dir;
-typedef struct Waitmsg Waitmsg;
-
-#define ERRLEN 64
-#define DIRLEN 116
-#define NAMELEN 28
-
-struct Qid
-{
- ulong path;
- ulong vers;
-};
-
-struct Dir
-{
- char name[NAMELEN];
- char uid[NAMELEN];
- char gid[NAMELEN];
- Qid qid;
- ulong mode;
- long atime;
- long mtime;
- vlong length;
- short type;
- short dev;
-};
-
-struct Waitmsg
-{
- int pid; /* of loved one */
- int status; /* unused; a placeholder */
- ulong time[3]; /* of loved one */
- char msg[ERRLEN];
-};
-#define nelem(x) (sizeof(x)/sizeof((x)[0]))
--- a/os/boot/mpc/main.c
+++ /dev/null
@@ -1,524 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "dosfs.h"
-
-typedef struct Type Type;
-typedef struct Medium Medium;
-typedef struct Mode Mode;
-
-enum {
- Dany = -1,
- Nmedia = 16,
-
- /* DS1 switch options */
- Sflashfs = 1<<0, /* take local fs from flash */
- Snotflash = 1<<1, /* don't boot from flash */
-};
-
-enum { /* type */
- Tflash,
- Tuart,
- Tether,
- Thard,
-
- Tany = -1,
-};
-
-enum { /* flag and name */
- Fnone = 0x00,
-
- Fdos = 0x01,
- Ndos = 0x00,
- Fboot = 0x02,
- Nboot = 0x01,
- Fbootp = 0x04,
- Nbootp = 0x02,
- Fflash = 0x08,
- Fuart = 0x10,
- NName = 0x03,
-
- Fany = Fbootp|Fboot|Fdos|Fflash|Fuart,
-
- Fini = 0x10,
- Fprobe = 0x80,
-};
-
-enum { /* mode */
- Mauto = 0x00,
- Mlocal = 0x01,
- Manual = 0x02,
- NMode = 0x03,
-};
-
-typedef struct Type {
- int type;
- char *cname;
- int flag;
- int (*init)(void);
- long (*read)(int, void*, long);
- long (*seek)(int, long);
- Partition* (*setpart)(int, char*);
- char* name[NName];
-
- int mask;
- Medium* media;
-} Type;
-
-typedef struct Medium {
- Type* type;
- int flag;
- Partition* partition;
- Dos;
-
- Medium* next;
-} Medium;
-
-typedef struct Mode {
- char* name;
- int mode;
-} Mode;
-
-static Type types[] = {
- { Tflash, "flash",
- Fflash,
- flashinit, 0, 0, 0,
- { 0, "F", 0, }
- },
-/*
- { Tuart, "uart",
- Fuart|Fboot,
- uartinit, uartread, uartseek, setuartpart,
- { 0, "u", 0, }
- },
-*/
- { Tether, "ether",
- Fbootp,
- etherinit, 0, 0, 0,
- { 0, 0, "e", },
- },
- { Thard, "ata",
- Fini|Fboot|Fdos,
- 0, 0, 0, 0, /* not used now, will be later with PCMCIA */
- { "hd", "h", 0, },
- },
- {-1},
-};
-
-static Medium media[Nmedia];
-static Medium *curmedium = media;
-
-static Mode modes[NMode+1] = {
- [Mauto] { "auto", Mauto, },
- [Mlocal] { "local", Mlocal, },
- [Manual] { "manual", Manual, },
-};
-
-static char *inis[] = {
- "inferno/inferno.ini",
- "inferno.ini",
- "plan9/plan9.ini",
- "plan9.ini",
- 0,
-};
-char **ini;
-int predawn;
-
-static int
-parse(char *line, int *type, int *flag, int *dev, char *file)
-{
- Type *tp;
- char buf[2*NAMELEN], *v[4], *p;
- int i;
-
- strcpy(buf, line);
- switch(getcfields(buf, v, 4, "!")){
-
- case 3:
- break;
-
- case 2:
- v[2] = "";
- break;
-
- default:
- return 0;
- }
-
- *flag = 0;
- for(tp = types; tp->cname; tp++){
- for(i = 0; i < NName; i++){
-
- if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
- continue;
- *type = tp->type;
- *flag |= 1<<i;
-
- if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
- return 0;
-
- strcpy(file, v[2]);
-
- return 1;
- }
- }
-
- return 0;
-
-}
-
-static int
-boot(Medium *mp, int flag, char *file)
-{
- Dosfile df;
- char ixdos[128], *p;
- int r;
-
- uartsetboot(0);
- if(flag & Fbootp){
- sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
- return bootp(mp->dev, file);
- }
-
- if(flag & Fflash){
- if(mp->flag & Fflash && flashbootable(0))
- flashboot(mp->dev);
- }
-
- if(flag & Fboot){
-
- if(mp->flag & Fini){
- (*mp->type->setpart)(mp->dev, "disk");
- plan9ini(mp, nil);
- }
- if(file == 0 || *file == 0)
- file = mp->partition->name;
- (*mp->type->setpart)(mp->dev, file);
- sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
- r = plan9boot(mp->dev, mp->seek, mp->read);
- uartsetboot(0);
- return r;
- }
-
- if(flag & Fdos){
- if(mp->type->setpart)
- (*mp->type->setpart)(mp->dev, "disk");
- if(mp->flag & Fini)
- plan9ini(mp, nil);
- if(file == 0 || *file == 0){
- strcpy(ixdos, *ini);
- if(p = strrchr(ixdos, '/'))
- p++;
- else
- p = ixdos;
- strcpy(p, "impc");
- if(dosstat(mp, ixdos, &df) <= 0)
- return -1;
- }
- else
- strcpy(ixdos, file);
- sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
- return dosboot(mp, ixdos);
- }
-
- return -1;
-}
-
-static Medium*
-allocm(Type *tp)
-{
- Medium **l;
-
- if(curmedium >= &media[Nmedia])
- return 0;
-
- for(l = &tp->media; *l; l = &(*l)->next)
- ;
- *l = curmedium++;
- return *l;
-}
-
-Medium*
-probe(int type, int flag, int dev)
-{
- Type *tp;
- int dombr, i, start;
- Medium *mp;
- Dosfile df;
- Partition *pp;
-
- for(tp = types; tp->cname; tp++){
- if(type != Tany && type != tp->type || tp->init == 0)
- continue;
-
- if(flag != Fnone){
- for(mp = tp->media; mp; mp = mp->next){
- if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
- return mp;
- }
- }
- if((tp->flag & Fprobe) == 0){
- tp->flag |= Fprobe;
- tp->mask = (*tp->init)();
- }
-
- for(i = 0; tp->mask; i++){
- if((tp->mask & (1<<i)) == 0)
- continue;
- tp->mask &= ~(1<<i);
-
- if((mp = allocm(tp)) == 0)
- continue;
-
- mp->dev = i;
- mp->flag = tp->flag;
- mp->seek = tp->seek;
- mp->read = tp->read;
- mp->type = tp;
-
- if(mp->flag & Fboot){
- if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
- mp->flag &= ~Fboot;
- if((mp->flag & (Fflash|Fuart)) == 0)
- (*tp->setpart)(i, "disk");
- }
-
- if(mp->flag & Fdos){
- start = 0;
- dombr = 1;
- if(mp->type->setpart){
- if(pp = (*mp->type->setpart)(i, "dos")){
- if(start = pp->start)
- dombr = 0;
- }
- (*tp->setpart)(i, "disk");
- }
- if(dosinit(mp, start, dombr) < 0)
- mp->flag &= ~(Fini|Fdos);
- else
- print("dos init failed\n");
- }
-
- if(mp->flag & Fini){
- mp->flag &= ~Fini;
- for(ini = inis; *ini; ini++){
- if(dosstat(mp, *ini, &df) <= 0)
- continue;
- mp->flag |= Fini;
- break;
- }
- }
-
- if((flag & mp->flag) && (dev == Dany || dev == i))
- return mp;
- }
- }
-
- return 0;
-}
-
-void
-main(void)
-{
- Medium *mp;
- int dev, flag, i, mode, tried, type, options;
- char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
- Type *tp;
-
- machinit();
- archinit();
- meminit();
- cpminit();
- trapinit();
- consinit(); /* screen and keyboard initially */
- screeninit();
- cpuidprint();
- alarminit();
- clockinit();
- predawn = 0;
- spllo();
- options = archoptionsw();
-
- mp = 0;
- for(tp = types; tp->cname; tp++){
- if(tp->type == Tether)
- continue;
- if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
- plan9ini(mp, nil);
- break;
- }
- }
-
- if(mp == 0 || (mp->flag & Fini) == 0)
- plan9ini(nil, flashconfig(0));
-
- //consinit(); /* establish new console location */
-
- if((options & Snotflash) == 0 && flashbootable(0)){
- print("Flash boot\n");
- flashboot(0);
- }
-
- tried = 0;
- mode = Mauto;
- p = getconf("bootfile");
- flag = 0;
-
- if(p != 0) {
- mode = Manual;
- for(i = 0; i < NMode; i++){
- if(strcmp(p, modes[i].name) == 0){
- mode = modes[i].mode;
- goto done;
- }
- }
- if(parse(p, &type, &flag, &dev, file) == 0) {
- print("Bad bootfile syntax: %s\n", p);
- goto done;
- }
- mp = probe(type, flag, dev);
- if(mp == 0) {
- print("Cannot access device: %s\n", p);
- goto done;
- }
- tried = boot(mp, flag, file);
- }
-done:
- if(tried == 0 && mode != Manual){
- flag = Fany;
- if(mode == Mlocal)
- flag &= ~Fbootp;
- if(options & Snotflash)
- flag &= ~Fflash;
- if((mp = probe(Tany, flag, Dany)) != 0)
- boot(mp, flag & mp->flag, 0);
- }
-
- def[0] = 0;
- probe(Tany, Fnone, Dany);
-
- flag = 0;
- for(tp = types; tp->cname; tp++){
- for(mp = tp->media; mp; mp = mp->next){
- if(flag == 0){
- flag = 1;
- print("Boot devices:");
- }
-
- if(mp->flag & Fbootp)
- print(" %s!%d", mp->type->name[Nbootp], mp->dev);
- if(mp->flag & Fdos)
- print(" %s!%d", mp->type->name[Ndos], mp->dev);
- if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot)
- print(" %s!%d", mp->type->name[Nboot], mp->dev);
- }
- }
- if(flag)
- print("\n");
-
- for(;;){
- if(getstr("boot from", line, sizeof(line), def) >= 0){
- if(parse(line, &type, &flag, &dev, file)){
- if(mp = probe(type, flag, dev))
- boot(mp, flag, file);
- }
- }
- def[0] = 0;
- }
-}
-
-void
-machinit(void)
-{
- memset(m, 0, sizeof(*m));
- m->delayloop = 20000;
- m->cpupvr = getpvr();
- m->iomem = KADDR(INTMEM);
-}
-
-int
-getcfields(char* lp, char** fields, int n, char* sep)
-{
- int i;
-
- for(i = 0; lp && *lp && i < n; i++){
- while(*lp && strchr(sep, *lp) != 0)
- *lp++ = 0;
- if(*lp == 0)
- break;
- fields[i] = lp;
- while(*lp && strchr(sep, *lp) == 0){
- if(*lp == '\\' && *(lp+1) == '\n')
- *lp++ = ' ';
- lp++;
- }
- }
-
- return i;
-}
-
-static Map memv[512];
-static RMap rammap = {"physical memory"};
-
-void
-meminit(void)
-{
- ulong e;
-
- mapinit(&rammap, memv, sizeof(memv));
- e = PADDR(&end);
- mapfree(&rammap, e, 4*1024*1024-e); /* fixed 4Mbytes is plenty for bootstrap */
-}
-
-void*
-ialloc(ulong n, int align)
-{
- ulong a;
- int s;
-
- if(align <= 0)
- align = 4;
- s = splhi();
- a = mapalloc(&rammap, 0, n, align);
- splx(s);
- if(a == 0)
- panic("ialloc");
- return memset(KADDR(a), 0, n);
-}
-
-void*
-malloc(ulong n)
-{
- ulong *p;
-
- n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
- p = ialloc(n, sizeof(int));
- *p++ = 0xcafebeef;
- *p++ = n;
- return p;
-}
-
-void
-free(void *ap)
-{
- int s;
- ulong *p;
-
- p = ap;
- if(p){
- if(*(p -= 2) != 0xcafebeef)
- panic("free");
- s = splhi();
- mapfree(&rammap, (ulong)p, p[1]);
- splx(s);
- }
-}
-
-void
-sched(void)
-{
-}
--- a/os/boot/mpc/mem.h
+++ /dev/null
@@ -1,95 +1,0 @@
-/*
- * Memory and machine-specific definitions. Used in C and assembler.
- */
-
-/*
- * Sizes
- */
-#define BI2BY 8 /* bits per byte */
-#define BI2WD 32 /* bits per word */
-#define BY2WD 4 /* bytes per word */
-#define BY2PG 4096 /* bytes per page */
-#define WD2PG (BY2PG/BY2WD) /* words per page */
-#define PGSHIFT 12 /* log(BY2PG) */
-#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
-
-#define MAXMACH 1 /* max # cpus system can run */
-#define CACHELINELOG 4
-#define CACHELINESZ (1<<CACHELINELOG)
-
-/*
- * Time
- */
-#define HZ (50) /* clock frequency */
-#define MS2HZ (1000/HZ) /* millisec per clock tick */
-#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
-#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
-#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
-#define MHz 1000000
-
-/*
- * Fundamental values
- */
-
-#define KZERO 0 /* bootstrap runs in real mode */
-#define MACHSIZE 4096
-
-/*
- * physical MMU
- */
-#define KSEG0 0x20000000
-#define KSEGM 0xE0000000 /* mask to check which seg */
-
-/*
- * MSR bits
- */
-
-#define POW 0x40000 /* enable power mgmt */
-#define TGPR 0x20000 /* GPR0-3 remapped; 603/603e specific */
-#define ILE 0x10000 /* interrupts little endian */
-#define EE 0x08000 /* enable external/decrementer interrupts */
-#define PR 0x04000 /* =1, user mode */
-#define FPE 0x02000 /* enable floating point */
-#define ME 0x01000 /* enable machine check exceptions */
-#define FE0 0x00800
-#define SE 0x00400 /* single-step trace */
-#define BE 0x00200 /* branch trace */
-#define FE1 0x00100
-#define IP 0x00040 /* =0, vector to nnnnn; =1, vector to FFFnnnnn */
-#define IR 0x00020 /* enable instruction address translation */
-#define DR 0x00010 /* enable data address translation */
-#define RI 0x00002 /* exception is recoverable */
-#define LE 0x00001 /* little endian mode */
-
-#define KMSR (ME|FE0|FE1|FPE)
-#define UMSR (KMSR|PR|EE|IR|DR)
-
-/*
- * MPC82x addresses; mpc8bug is happy with these
- */
-#define BCSRMEM 0x02100000
-#define INTMEM 0x02200000
-#define FLASHMEM 0x02800000
-#define SDRAMMEM 0x03000000
-
-#define DPRAM (INTMEM+0x2000)
-#define DPLEN1 0x400
-#define DPLEN2 0x200
-#define DPLEN3 0x100
-#define DPBASE (DPRAM+DPLEN1)
-
-#define SCC1P (INTMEM+0x3C00)
-#define I2CP (INTMEM+0x3C80)
-#define MISCP (INTMEM+0x3CB0)
-#define IDMA1P (INTMEM+0x3CC0)
-#define SCC2P (INTMEM+0x3D00)
-#define SCC3P (INTMEM+0x3E00)
-#define SCC4P (INTMEM+0x3F00)
-#define SPIP (INTMEM+0x3D80)
-#define TIMERP (INTMEM+0x3DB0)
-#define SMC1P (INTMEM+0x3E80)
-#define DSP1P (INTMEM+0x3EC0)
-#define SMC2P (INTMEM+0x3F80)
-#define DSP2P (INTMEM+0x3FC0)
-
-#define KEEP_ALIVE_KEY 0x55ccaa33 /* clock and rtc register key */
--- a/os/boot/mpc/mkfile
+++ /dev/null
@@ -1,116 +1,0 @@
-objtype=power
-OBJTYPE=power # always
-<../../../mkconfig
-SYSTARG=$OSTARG # always
-<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
-INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin #path of directory where kernel is installed
-ARCH=fads # selects board dependent code
-TARG=qb$ARCH
-OFILES=\
- l.$O\
- arch$ARCH.$O\
- devuart.$O\
- uartboot.$O\
- alarm.$O\
- bootp.$O\
- clock.$O\
- conf.$O\
- console.$O\
- cpm.$O\
- defont0.$O\
- donprint.$O\
- dosboot.$O\
- devether.$O\
- etherscc.$O\
- fblt.$O\
- gbitbltclip.$O\
- flash.$O\
- main.$O\
- plan9boot.$O\
- qio.$O\
- rmap.$O\
- screen.$O\
- init$ARCH.$O\
- trap.$O\
- zqs.$O\
-
-HFILES=\
- boot.h\
- dat.h\
- fns.h\
- io.h\
- lib.h\
- mem.h\
- squeeze.h\
- gnot.h\
- arch$ARCH.h\
-
-LIBS=\
- kern\
-
-LIBDIRS=$LIBS
-LIBNAMES=${LIBS:%=lib%.a}
-LIBFILES=${LIBS:%=$ROOT/$TARGMODEL/$OBJTYPE/lib/lib%.a}
-
-#all:NV: $TARG k.mx f.mx
-all:NV: $TARG
-install:V: $INSTALLDIR/$TARG
-installall:V: $INSTALLDIR/$TARG
-
-$INSTALLDIR/%: %
- rm -f $INSTALLDIR/$stem && cp $stem $INSTALLDIR/$stem
-
-$TARG: $OFILES $LIBNAMES
- $LD -o $target -l -T0x140000 -R4 $OFILES $LIBFILES
- ls -l $target
-
-qbrom$ARCH: $OFILES $LIBNAMES
- $LD -o $target -l -T0x02800100 -R0 -D0x140000 $OFILES $LIBFILES
-
-k.mx: $TARG
- ms2 -S 0x100 -a 0x100 -p 4 $TARG >k.mx
-
-f.mx: qbrom$ARCH
- ms2 -S 0x100 -a 0x2800100 -p 4 $prereq >f.mx
-
-%.$O: %.s
- $AS $stem.s
-
-%.$O: %.c
- $CC $CFLAGS $stem.c
-
-%.$O: $HFILES
-
-lib%.a:V: $SHELLTYPE-lib%.a
-
-rc-lib%.a nt-lib%.a:VQ:
- echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
- @{builtin cd $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
-
-sh-lib%.a:VQ:
- echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
- (cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
-
-clock.$O floppy.$O trap.$O: ureg.h
-conf.$O dosboot.$O main.$O: dosfs.h
-ether.$O etherscc.$O: etherif.h
-bootp.$O: ip.h
-
-clean:V:
- rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG qboot k.mx f.mx romboot
-
-nuke-sh:QV:
- for i in $LIBDIRS
- do
- echo "(cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke)"
- (cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke)
- done
-
-nuke-rc nuke-nt:QV:
- for (i in $LIBDIRS)
- {
- echo '@{cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke}'
- @{cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke}
- }
-
-nuke:V: clean nuke-$SHELLTYPE
--- a/os/boot/mpc/ms2.c
+++ /dev/null
@@ -1,179 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-void record(uchar*, int);
-void usage(void);
-void dosegment(long, int);
-void trailer(ulong);
-
-enum
-{
- Recordsize = 32,
-};
-
-int dsegonly;
-int supressend;
-int binary;
-int addr4;
-ulong addr;
-ulong psize = 4096;
-ulong startaddr = 0x030000;
-Biobuf stdout;
-Biobuf bio;
-
-void
-main(int argc, char **argv)
-{
- Dir dir;
- Fhdr f;
- int fd;
-
- ARGBEGIN{
- case 'd':
- dsegonly++;
- break;
- case 's':
- supressend++;
- break;
- case 'a':
- addr = strtoul(ARGF(), 0, 0);
- break;
- case 'p':
- psize = strtoul(ARGF(), 0, 0);
- break;
- case 'b':
- binary++;
- break;
- case 'S':
- startaddr = strtoul(ARGF(), 0, 0);
- break;
- case '4':
- addr4++;
- break;
- default:
- usage();
- }ARGEND
-
- if(argc != 1)
- usage();
-
- Binit(&stdout, 1, OWRITE);
-
- fd = open(argv[0], OREAD);
- if(fd < 0) {
- fprint(2, "ms2: open %s: %r\n", argv[0]);
- exits("open");
- }
-
- if(binary) {
- if(dirfstat(fd, &dir) < 0) {
- fprint(2, "ms2: stat failed %r");
- exits("dirfstat");
- }
- Binit(&bio, fd, OREAD);
- dosegment(0, dir.length);
- if(supressend == 0)
- trailer(startaddr);
- Bterm(&stdout);
- Bterm(&bio);
- exits(0);
- }
-
- if(crackhdr(fd, &f) == 0){
- fprint(2, "ms2: bad magic: %r\n");
- exits("magic");
- }
- seek(fd, 0, 0);
-
- Binit(&bio, fd, OREAD);
-
- if(dsegonly)
- dosegment(f.datoff, f.datsz);
- else {
- dosegment(f.txtoff, f.txtsz);
- addr = (addr+(psize-1))&~(psize-1);
- dosegment(f.datoff, f.datsz);
- }
-
- if(supressend == 0)
- trailer(startaddr);
-
- Bterm(&stdout);
- Bterm(&bio);
- exits(0);
-}
-
-void
-dosegment(long foff, int len)
-{
- int l, n;
- uchar buf[2*Recordsize];
-
- Bseek(&bio, foff, 0);
- for(;;) {
- l = len;
- if(l > Recordsize)
- l = Recordsize;
- n = Bread(&bio, buf, l);
- if(n == 0)
- break;
- if(n < 0) {
- fprint(2, "ms2: read error: %r\n");
- exits("read");
- }
- record(buf, l);
- len -= l;
- }
-}
-
-void
-record(uchar *s, int l)
-{
- int i;
- ulong cksum;
-
- if(addr4 || addr & (0xFF<<24)){
- Bprint(&stdout, "S3%.2X%.8luX", l+5, addr);
- cksum = l+5;
- cksum += (addr>>24)&0xff;
- }else{
- Bprint(&stdout, "S2%.2X%.6X", l+4, addr);
- cksum = l+4;
- }
- cksum += addr&0xff;
- cksum += (addr>>8)&0xff;
- cksum += (addr>>16)&0xff;
-
- for(i = 0; i < l; i++) {
- cksum += *s;
- Bprint(&stdout, "%.2X", *s++);
- }
- Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
- addr += l;
-}
-
-void
-trailer(ulong a)
-{
- ulong cksum;
-
- cksum = 0;
- if(addr4 || a & (0xFF<<24)){
- Bprint(&stdout, "S7%.8luX", a);
- cksum += (a>>24)&0xff;
- }else
- Bprint(&stdout, "S9%.6X", a);
- cksum += a&0xff;
- cksum += (a>>8)&0xff;
- cksum += (a>>16)&0xff;
- Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
-}
-
-void
-usage(void)
-{
- fprint(2, "usage: ms2 [-ds] [-a address] [-p pagesize] ?.out\n");
- exits("usage");
-}
--- a/os/boot/mpc/plan9boot.c
+++ /dev/null
@@ -1,96 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-char *premature = "premature EOF\n";
-
-/*
- * read in a segment
- */
-static long
-readseg(int dev, long (*read)(int, void*, long), long len, long addr)
-{
- char *a;
- long n, sofar;
-
- a = (char *)addr;
- for(sofar = 0; sofar < len; sofar += n){
- n = 8*1024;
- if(len - sofar < n)
- n = len - sofar;
- n = (*read)(dev, a + sofar, n);
- if(n <= 0)
- break;
- print(".");
- }
- return sofar;
-}
-
-/*
- * boot
- */
-int
-plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
-{
- long n;
- long addr;
- void (*b)(void);
- Exec *ep;
-
- if((*seek)(dev, 0) < 0)
- return -1;
-
- /*
- * read header
- */
- ep = (Exec *) ialloc(sizeof(Exec), 0);
- n = sizeof(Exec);
- if(readseg(dev, read, n, (long) ep) != n){
- print(premature);
- return -1;
- }
- if(GLLONG(ep->magic) != Q_MAGIC){
- print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
- return -1;
- }
-
- /*
- * read text
- */
- addr = PADDR(GLLONG(ep->entry));
- n = GLLONG(ep->text);
- print("%d", n);
- if(readseg(dev, read, n, addr) != n){
- print(premature);
- return -1;
- }
-
- /*
- * read data (starts at first page after kernel)
- */
- addr = PGROUND(addr+n);
- n = GLLONG(ep->data);
- print("+%d@%8.8lux", n, addr);
- if(readseg(dev, read, n, addr) != n){
- print(premature);
- return -1;
- }
-
- /*
- * bss and entry point
- */
- print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
- uartwait();
- scc2stop();
- splhi();
-
- /*
- * Go to new code. It's up to the program to get its PC relocated to
- * the right place.
- */
- b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
- (*b)();
- return 0;
-}
--- a/os/boot/mpc/qio.c
+++ /dev/null
@@ -1,128 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-struct Queue {
- Block* first;
- Block* last;
- void (*kick)(void*);
- void* arg;
- long len;
-};
-
-Block *
-iallocb(int n)
-{
- Block *b;
-
- b = (Block*)malloc(sizeof(Block)+n);
- b->data = (uchar*)b + sizeof(Block);
- b->rp = b->wp = b->data;
- b->lim = b->data + n;
- b->next = 0;
- b->magic = 0xcafebee0;
- return b;
-}
-
-void
-freeb(Block *b)
-{
- if(b){
- if(b->magic != 0xcafebee0)
- panic("freeb");
- b->magic = 0;
- b->next = (Block*)0xdeadbabe;
- free(b);
- }
-}
-
-Queue *
-qopen(int limit, int msg, void (*kick)(void*), void *arg)
-{
- Queue *q;
-
- USED(limit, msg);
- q = (Queue*)malloc(sizeof(Queue));
- q->first = q->last = 0;
- q->kick = kick;
- q->arg = arg;
- q->len = 0;
- return q;
-}
-
-Block *
-qget(Queue *q)
-{
- int s;
- Block *b;
-
- s = splhi();
- if((b = q->first) != 0){
- q->first = b->next;
- b->next = 0;
- q->len -= BLEN(b);
- if(q->len < 0)
- panic("qget");
- }
- splx(s);
- return b;
-}
-
-void
-qbwrite(Queue *q, Block *b)
-{
- int s;
-
- s = splhi();
- b->next = 0;
- if(q->first == 0)
- q->first = b;
- else
- q->last->next = b;
- q->last = b;
- q->len += BLEN(b);
- splx(s);
- if(q->kick)
- q->kick(q->arg);
-}
-
-long
-qlen(Queue *q)
-{
- return q->len;
-}
-
-int
-qbgetc(Queue *q)
-{
- Block *b;
- int s, c;
-
- c = -1;
- s = splhi();
- while(c < 0 && (b = q->first) != nil){
- if(b->rp < b->wp){
- c = *b->rp++;
- q->len--;
- }
- if(b->rp >= b->wp){
- q->first = b->next;
- b->next = nil;
- }
- }
- splx(s);
- return c;
-}
-
-void
-qbputc(Queue *q, int c)
-{
- Block *b;
-
- b = iallocb(1);
- *b->wp++ = c;
- qbwrite(q, b);
-}
--- a/os/boot/mpc/rmap.c
+++ /dev/null
@@ -1,104 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-void
-mapinit(RMap *rmap, Map *map, int size)
-{
- lock(rmap);
- rmap->map = map;
- rmap->mapend = map+(size/sizeof(Map));
- unlock(rmap);
-}
-
-void
-mapfree(RMap* rmap, ulong addr, int size)
-{
- Map *mp;
- ulong t;
-
- if(size <= 0)
- return;
-
- lock(rmap);
- for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
- ;
-
- if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
- (mp-1)->size += size;
- if(addr+size == mp->addr){
- (mp-1)->size += mp->size;
- while(mp->size){
- mp++;
- (mp-1)->addr = mp->addr;
- (mp-1)->size = mp->size;
- }
- }
- }
- else{
- if(addr+size == mp->addr && mp->size){
- mp->addr -= size;
- mp->size += size;
- }
- else do{
- if(mp >= rmap->mapend){
- print("mapfree: %s: losing 0x%uX, %d\n",
- rmap->name, addr, size);
- break;
- }
- t = mp->addr;
- mp->addr = addr;
- addr = t;
- t = mp->size;
- mp->size = size;
- mp++;
- }while(size = t);
- }
- unlock(rmap);
-}
-
-ulong
-mapalloc(RMap* rmap, ulong addr, int size, int align)
-{
- Map *mp;
- ulong maddr, oaddr;
-
- lock(rmap);
- for(mp = rmap->map; mp->size; mp++){
- maddr = mp->addr;
-
- if(addr){
- if(maddr > addr)
- continue;
- if(addr+size > maddr+mp->size)
- break;
- maddr = addr;
- }
-
- if(align > 0)
- maddr = ((maddr+align-1)/align)*align;
- if(mp->addr+mp->size-maddr < size)
- continue;
-
- oaddr = mp->addr;
- mp->addr = maddr+size;
- mp->size -= maddr-oaddr+size;
- if(mp->size == 0){
- do{
- mp++;
- (mp-1)->addr = mp->addr;
- }while((mp-1)->size = mp->size);
- }
-
- unlock(rmap);
- if(oaddr != maddr)
- mapfree(rmap, oaddr, maddr-oaddr);
-
- return maddr;
- }
- unlock(rmap);
-
- return 0;
-}
--- a/os/boot/mpc/screen.c
+++ /dev/null
@@ -1,242 +1,0 @@
-#include "all.h"
-#include <libg.h>
-#include <gnot.h>
-
-enum {
- Colldepth = 3,
- Colmaxx = 640,
- Colmaxxvis = 640,
- Colmaxy = 480,
-};
-
-#define MINX 8
-
-extern GSubfont defont0;
-
-struct{
- Point pos;
- int bwid;
-}out;
-
-typedef struct Mode Mode;
-struct Mode {
- int x;
- int y;
- int d;
- char* aperture;
- int apsize;
-};
-
-GBitmap gscreen;
-Point gchar(GBitmap*, Point, GFont*, int, Fcode);
-int setcolor(ulong, ulong, ulong, ulong);
-static void lcdinit(Mode*);
-
-void
-screeninit(void)
-{
- Mode m;
-
- m.x = Colmaxx;
- m.y = Colmaxy;
- m.d = Colldepth;
- m.aperture = 0;
- lcdinit(&m);
- if(m.aperture == 0)
- return;
- gscreen.ldepth = 3;
- gscreen.base = (ulong*)m.aperture;
- gscreen.width = Colmaxx/BY2WD;
- gscreen.r = Rect(0, 0, Colmaxxvis, Colmaxy);
- gscreen.clipr = gscreen.r;
- /*
- * For now, just use a fixed colormap:
- * 0 == white and 255 == black
- */
- setcolor(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
- setcolor(255, 0x00000000, 0x00000000, 0x00000000);
-
- gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, Zero);
- out.pos.x = MINX;
- out.pos.y = 0;
- out.bwid = defont0.info[' '].width;
-}
-
-void
-screenputc(int c)
-{
- Fontchar *i;
- Point p;
-
- if(gscreen.base == nil)
- return;
- switch(c){
- case '\n':
- out.pos.x = MINX;
- out.pos.y += defont0.height;
- if(out.pos.y > gscreen.r.max.y-defont0.height)
- out.pos.y = gscreen.r.min.y;
- gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
- Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height),
- Zero);
- break;
- case '\t':
- out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
- if(out.pos.x >= gscreen.r.max.x)
- screenputc('\n');
- break;
- case '\b':
- if(out.pos.x >= out.bwid+MINX){
- out.pos.x -= out.bwid;
- screenputc(' ');
- out.pos.x -= out.bwid;
- }
- break;
- default:
- if(out.pos.x >= gscreen.r.max.x-out.bwid)
- screenputc('\n');
- c &= 0x7f;
- if(c <= 0 || c >= defont0.n)
- break;
- i = defont0.info + c;
- p = out.pos;
- gbitblt(&gscreen, Pt(p.x+i->left, p.y), defont0.bits,
- Rect(i[0].x, 0, i[1].x, defont0.height),
- S);
- out.pos.x = p.x + i->width;
- break;
- }
-}
-
-void
-screenputs(char *s, int n)
-{
- while(n-- > 0)
- screenputc(*s++);
-}
-
-/*
- * See section 5.2.1 (page 5-6) of the MPC823 manual
- */
-static uchar lcdclock[17] = { /* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */
- 0, 0, (1<<2), 1,
- (2<<2), 2, (1<<2)|1, 3,
- (3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1,
- (2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2),
- (4<<2)
-};
-
-/*
- * support for the Sharp LQ64D341 TFT colour display
- */
-
-enum {
- COLS = 640,
- ROWS = 480,
- LDEPTH = 3, /* screen depth */
- LCDFREQ = 25000000,
-
- /* lccr */
- ClockLow = 1<<11,
- OELow = 1<<10,
- HsyncLow = 1<<9,
- VsyncLow = 1<<8,
- DataLow = 1<<7,
- Passive8 = 1<<4,
- DualScan = 1<<3,
- IsColour = 1<<2,
- IsTFT = 1<<1,
- Enable = 1<<0,
-
- /* lchcr */
- BigEndian = 1<<24,
- AT7 = 7<<21, /* access type */
-
- /* sdcr */
- LAM = 1<<6, /* ``LCD aggressive mode'' */
-};
-
-/*
- * TO DO: most of the data could come from a table
- */
-static void
-lcdinit(Mode *mode)
-{
- IMM *io;
- int i, d;
- long hz;
-
- io = m->iomem;
- mode->y = ROWS;
- mode->x = COLS;
- mode->d = LDEPTH;
- mode->aperture = ialloc(mode->x*mode->y, 16);
- mode->apsize = mode->x*mode->y;
-
- io->sdcr &= ~LAM; /* MPC823 errata: turn off LAM before disabling controller */
- io->lcfaa = PADDR(mode->aperture);
- io->lccr = (((mode->x*mode->y*(1<<LDEPTH)+127)/128) << 17) | (LDEPTH << 5) | IsColour | IsTFT | OELow | VsyncLow | ClockLow;
-
- switch(LDEPTH){
- default:
- case 0:
- /* monochrome/greyscale identity map */
- for(i=0; i<16; i++)
- io->lcdmap[i] = i;
- break;
- case 2:
- /* 4-bit grey scale map */
- for(i=0; i<16; i++)
- io->lcdmap[0] = (i<<8)|(i<<4)|i;
- break;
- case 3:
- /* 8-bit linear map */
- for(i=0; i<256; i++)
- io->lcdmap[i] = (i<<8)|(i<<4)|i;
- break;
- }
-
- io->lcvcr = (mode->y << 11) | (1<<28) | 33; /* 2 line vsync pulse, 34 line wait between frames */
- io->lchcr = (mode->x<<10) | BigEndian | 228; /* clock cycles between lines */
-
- hz = m->cpuhz;
- d = hz/LCDFREQ;
- if(hz/d > LCDFREQ)
- d++;
- if(d >= 16)
- d = 16;
-
- /*
- * enable LCD outputs
- */
- io->pddat = 0;
- io->pdpar = 0x1fff;
-io->pdpar &= ~SIBIT(6); /* 823 bug fix? */
- io->pddir = 0x1fff;
- io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17);
- io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17);
- io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17));
-
- eieio();
- io->sccrk = KEEP_ALIVE_KEY;
- eieio();
- io->sccr = (io->sccr & ~0x1F) | lcdclock[d];
- eieio();
- io->sccrk = ~KEEP_ALIVE_KEY;
- eieio();
- gscreen.width = gscreen.width; /* access external memory before enabling (mpc823 errata) */
- io->lcsr = 7; /* clear status */
- eieio();
- io->lccr |= Enable;
- archbacklight(1);
-}
-
-int
-setcolor(ulong p, ulong r, ulong g, ulong b)
-{
- r >>= 28;
- g >>= 28;
- b >>= 28;
- m->iomem->lcdmap[~p&0xFF] = (r<<8) | (g<<4) | b; /* TO DO: it's a function of the ldepth */
- return 1;
-}
--- a/os/boot/mpc/sload.c
+++ /dev/null
@@ -1,71 +1,0 @@
-/*
- * send S records to rpcg
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-static int dbg;
-static char buf[2048];
-static int run=1;
-static void stuffbym(char*, int, int);
-static void getdot(void);
-
-void
-main(int argc, char **argv)
-{
- int n;
- char *l;
- Biobuf *f;
- static int p;
-
- ARGBEGIN{
- case 'd': dbg++; break;
- case 'n': run=0; break;
- }ARGEND
-
- f = Bopen(*argv? *argv: "k.mx", OREAD);
- if(f == 0) {
- fprint(2, "sload: cannot open k.mx: %r\n");
- exits("sload");
- }
- getdot();
- while((l = Brdline(f, '\n')) != 0) {
- l[Blinelen(f)-1] = '\r';
- stuffbym(l, Blinelen(f), 16);
- getdot();
- if(++p % 25 == 0)
- write(2, ".", 1);
- }
- exits(0);
-}
-
-static void
-stuffbym(char *l, int n, int m)
-{
- int nr, ns;
-
- while(n > 0) {
- ns = n;
- if(ns > m)
- ns = m;
- write(1, l, ns);
- l += ns;
- n -= ns;
- }
-}
-
-static void
-getdot(void)
-{
- char c;
-
- for(;;){
- if(read(0, &c, 1) != 1)
- exits("bang");
- write(2, &c, 1);
- if(c == '.')
- break;
- }
-}
--- a/os/boot/mpc/squeeze.h
+++ /dev/null
@@ -1,34 +1,0 @@
-
-/*
- * squeezed file format:
- * Sqhdr
- * original Exec header
- * two Squeeze tables
- * squeezed segment
- * unsqueezed segment, if any
- */
-#define SQMAGIC (ulong)0xFEEF0F1E
-
-typedef struct Sqhdr Sqhdr;
-struct Sqhdr {
- uchar magic[4]; /* SQMAGIC */
- uchar text[4]; /* squeezed length of text (excluding tables) */
- uchar data[4]; /* squeezed length of data (excluding tables) */
- uchar asis[4]; /* length of unsqueezed segment */
- uchar toptxt[4]; /* value for 0 encoding in text */
- uchar topdat[4]; /* value for 0 encoding in data */
- uchar sum[4]; /* simple checksum of unsqueezed data */
- uchar flags[4];
-};
-#define SQHDRLEN (8*4)
-
-/*
- * certain power instruction types are rearranged by sqz
- * so as to move the variable part of the instruction word to the
- * low order bits. note that the mapping is its own inverse.
- */
-#define QREMAP(X)\
- switch((X)>>26){\
- case 19: case 31: case 59: case 63:\
- (X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
- }
--- a/os/boot/mpc/trap.c
+++ /dev/null
@@ -1,233 +1,0 @@
-#include "boot.h"
-
-enum
-{
- Maxhandler= 32+16, /* max number of interrupt handlers */
-};
-
-typedef struct Handler Handler;
-struct Handler
-{
- void (*r)(Ureg*, void*);
- void *arg;
- Handler *next;
- int edge;
-};
-
-struct
-{
- Handler *ivec[128];
- Handler h[Maxhandler];
- int free;
-} halloc;
-
-char *excname[] = {
- "reserved 0",
- "system reset",
- "machine check",
- "data access",
- "instruction access",
- "external interrupt",
- "alignment",
- "program exception",
- "floating-point unavailable",
- "decrementer",
- "reserved A",
- "reserved B",
- "system call",
- "trace trap",
- "floating point assist",
- "reserved F",
- "software emulation",
- "ITLB miss",
- "DTLB miss",
- "ITLB error",
- "DTLB error",
-};
-
-char *regname[]={
- "CAUSE", "SRR1",
- "PC", "GOK",
- "LR", "CR",
- "XER", "CTR",
- "R0", "R1",
- "R2", "R3",
- "R4", "R5",
- "R6", "R7",
- "R8", "R9",
- "R10", "R11",
- "R12", "R13",
- "R14", "R15",
- "R16", "R17",
- "R18", "R19",
- "R20", "R21",
- "R22", "R23",
- "R24", "R25",
- "R26", "R27",
- "R28", "R29",
- "R30", "R31",
-};
-
-static void intr(Ureg*);
-
-void
-sethvec(int v, void (*r)(void))
-{
- ulong *vp, pa, o;
-
- if((ulong)r & 3)
- panic("sethvec");
- vp = (ulong*)KADDR(v);
- vp[0] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */
- vp[1] = 0x7c0802a6; /* MOVW LR, R0 */
- vp[2] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */
- pa = PADDR(r);
- o = pa >> 25;
- if(o != 0 && o != 0x7F){
- /* a branch too far: running from ROM */
- vp[3] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
- vp[4] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
- vp[5] = 0x7c0803a6; /* MOVW R0, LR */
- vp[6] = 0x4e800021; /* BL (LR) */
- }else
- vp[3] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
-}
-
-#define LEV(n) (((n)<<1)|1)
-#define IRQ(n) (((n)<<1)|0)
-
-void
-setvec(int v, void (*r)(Ureg*, void*), void *arg)
-{
- Handler *h;
- IMM *io;
-
- if(halloc.free >= Maxhandler)
- panic("out of interrupt handlers");
- v -= VectorPIC;
- h = &halloc.h[halloc.free++];
- h->next = halloc.ivec[v];
- h->r = r;
- h->arg = arg;
- halloc.ivec[v] = h;
-
- /*
- * enable corresponding interrupt in SIU/CPM
- */
-
- io = m->iomem;
- if(v >= VectorCPIC){
- v -= VectorCPIC;
- io->cimr |= 1<<(v&0x1F);
- }
- else if(v >= VectorIRQ)
- io->simask |= 1<<(31-IRQ(v&7));
- else
- io->simask |= 1<<(31-LEV(v));
-}
-
-void
-trapinit(void)
-{
- int i;
- IMM *io;
-
- io = m->iomem;
- io->sypcr &= ~(3<<2); /* disable watchdog (821/823) */
- io->simask = 0; /* mask all */
- io->siel = ~0; /* edge sensitive, wake on all */
- io->cicr = 0; /* disable CPM interrupts */
- io->cipr = ~0; /* clear all interrupts */
- io->cimr = 0; /* mask all events */
- io->cicr = (0xE1<<16)|(CPIClevel<<13)|(0x1F<<8);
- io->cicr |= 1 << 7; /* enable */
- io->tbscrk = KEEP_ALIVE_KEY;
- io->tbscr = 1; /* TBE */
- io->simask |= 1<<(31-LEV(CPIClevel)); /* CPM's level */
- io->tbk = KEEP_ALIVE_KEY;
- eieio();
- putdec(~0);
-
- /*
- * set all exceptions to trap
- */
- for(i = 0x0; i < 0x3000; i += 0x100)
- sethvec(i, exception);
-}
-
-void
-dumpregs(Ureg *ur)
-{
- int i;
- ulong *l;
- l = &ur->cause;
- for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
- print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
-}
-
-void
-trap(Ureg *ur)
-{
- int c;
-
- c = ur->cause >> 8;
- switch(c){
- default:
- {extern int predawn; predawn = 1;}
- if(c < 0 || c >= nelem(excname))
- print("exception/interrupt #%x\n", c);
- else
- print("exception %s\n", excname[c]);
- dumpregs(ur);
- /* spllo(); */
- print("^P to reset\n");
- for(;;)
- ;
-
- case 0x09: /* decrementer */
- clockintr(ur, 0);
- return;
-
- case 0x05: /* external interrupt */
- intr(ur);
- break;
- }
-}
-
-static void
-intr(Ureg *ur)
-{
- int b, v;
- Handler *h;
- IMM *io;
-
- io = m->iomem;
- b = io->sivec>>2;
- v = b>>1;
- if(b & 1) {
- if(v == CPIClevel){
- io->civr = 1;
- eieio();
- v = VectorCPIC+(io->civr>>11);
- }
- }else
- v += VectorIRQ;
- h = halloc.ivec[v];
- if(h == nil){
- for(;;)
- ;
- //print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
- return;
- }
- if(h->edge)
- io->sipend |= 1<<(31-b);
- /*
- * call the interrupt handlers
- */
- do {
- (*h->r)(ur, h->arg);
- h = h->next;
- } while(h != nil);
- if(v >= VectorCPIC)
- io->cisr |= 1<<(v-VectorCPIC);
-}
--- a/os/boot/mpc/uartboot.c
+++ /dev/null
@@ -1,189 +1,0 @@
-#include "boot.h"
-
-/*
- * this doesn't yet use the crc
- */
-
-typedef struct Uboot Uboot;
-struct Uboot {
- Queue* iq;
- Block* partial;
- ulong csum;
- long bno;
- uchar buf[64];
- int nleft;
- int ntimeout;
-};
-
-static Uboot uboot;
-ulong crc32(void *buf, int n, ulong crc);
-
-static void
-uartbrecv(uchar *p, int n)
-{
- Uboot *ub;
- Block *b;
-
- ub = &uboot;
- if(n > 0 && ub->iq != nil){
- b = iallocb(n);
- memmove(b->wp, p, n);
- b->wp += n;
- qbwrite(ub->iq, b);
- }
-}
-
-int
-uartinit(void)
-{
- return 1<<0;
-}
-
-Partition*
-setuartpart(int, char *s)
-{
- static Partition pp[1];
-
- if(strcmp(s, "boot") != 0 && strcmp(s, "disk") != 0)
- return 0;
- pp[0].start = 0;
- pp[0].end = 2*1024*1024;
- strcpy(pp[0].name, "boot");
- return pp;
-}
-
-long
-uartseek(int, long)
-{
- /* start the boot */
- if(uboot.iq == nil)
- uboot.iq = qopen(64*1024, 0, 0, 0);
- if(uboot.partial){
- freeb(uboot.partial);
- uboot.partial = 0;
- }
- print("uart: start transmission\n");
- uartsetboot(uartbrecv);
- uboot.csum = ~0;
- uboot.bno = 0;
- uboot.nleft = 0;
- uboot.ntimeout = 0;
- return 0;
-}
-
-static long
-uartreadn(void *buf, int nb)
-{
- ulong start;
- Uboot *ub;
- int l;
- Block *b;
- uchar *p;
-
- p = buf;
- ub = &uboot;
- start = m->ticks;
- while(nb > 0){
- b = ub->partial;
- ub->partial = nil;
- if(b == nil){
- ub->ntimeout = 0;
- while((b = qget(ub->iq)) == 0){
- if(TK2MS(m->ticks - start) >= 15*1000){
- if(++ub->ntimeout >= 3){
- print("uart: timeout\n");
- return 0;
- }
- uartputs("n", 1);
- }
- }
- }
- l = BLEN(b);
- if(l > nb)
- l = nb;
- memmove(p, b->rp, l);
- b->rp += l;
- if(b->rp >= b->wp)
- freeb(b);
- else
- ub->partial = b;
- nb -= l;
- p += l;
- }
- return p-(uchar*)buf;
-}
-
-long
-uartread(int, void *buf, long n)
-{
- uchar *p;
- int l;
- static uchar lbuf[64];
-
- p = buf;
- if((l = uboot.nleft) > 0){
- if(l > n)
- l = n;
- uboot.nleft -= l;
- memmove(p, uboot.buf, l);
- p += l;
- n -= l;
- }
- while(n > 0){
- l = uartreadn(lbuf, sizeof(lbuf));
- if(l < sizeof(lbuf))
- return 0;
- if(l > n){
- uboot.nleft = l-n;
- memmove(uboot.buf, lbuf+n, uboot.nleft);
- l = n;
- }
- memmove(p, lbuf, l);
- n -= l;
- p += l;
- uboot.bno++;
- uartputs("y", 1);
- }
- return p-(uchar*)buf;
-}
-
-/*
- * from Rob Warnock
- */
-static ulong crc32tab[256]; /* initialised on first call to crc32 */
-
-enum {
- CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
-};
-
-/*
- * Build auxiliary table for parallel byte-at-a-time CRC-32.
- */
-static void
-initcrc32(void)
-{
- int i, j;
- ulong c;
-
- for(i = 0; i < 256; i++) {
- for(c = i << 24, j = 8; j > 0; j--)
- if(c & (1<<31))
- c = (c<<1) ^ CRC32POLY;
- else
- c <<= 1;
- crc32tab[i] = c;
- }
-}
-
-ulong
-crc32(void *buf, int n, ulong crc)
-{
- uchar *p;
-
- if(crc32tab[1] == 0)
- initcrc32();
- crc = ~crc;
- for(p = buf; --n >= 0;)
- crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
- return ~crc;
-}
--- a/os/boot/mpc/ureg.h
+++ /dev/null
@@ -1,43 +1,0 @@
-struct Ureg
-{
- ulong cause;
- union { ulong srr1; ulong status;};
- ulong pc; /* SRR0 */
- ulong pad;
- ulong lr;
- ulong cr;
- ulong xer;
- ulong ctr;
- ulong r0;
- union{ ulong r1; ulong sp; ulong usp; };
- ulong r2;
- ulong r3;
- ulong r4;
- ulong r5;
- ulong r6;
- ulong r7;
- ulong r8;
- ulong r9;
- ulong r10;
- ulong r11;
- ulong r12;
- ulong r13;
- ulong r14;
- ulong r15;
- ulong r16;
- ulong r17;
- ulong r18;
- ulong r19;
- ulong r20;
- ulong r21;
- ulong r22;
- ulong r23;
- ulong r24;
- ulong r25;
- ulong r26;
- ulong r27;
- ulong r28;
- ulong r29;
- ulong r30;
- ulong r31;
-};
--- a/os/boot/mpc/zqs.c
+++ /dev/null
@@ -1,234 +1,0 @@
-#include "boot.h"
-#include "squeeze.h"
-
-/*
- * for details of `unsqueeze' see:
- *
- * %A Mark Taunton
- * %T Compressed Executables: An Exercise in Thinking Small
- * %P 385-404
- * %I USENIX
- * %B USENIX Conference Proceedings
- * %D Summer 1991
- * %C Nashville, TN
- *
- * several of the unimplemented improvements described in the paper
- * have been implemented here
- *
- * there is a further transformation on the powerpc (QFLAG!=0) to shuffle bits
- * in certain instructions so as to push the fixed bits to the top of the word.
- */
-
-#define EXECHDRLEN (8*4)
-
-typedef struct Squeeze Squeeze;
-struct Squeeze {
- int n;
- ulong tab[7*256];
-};
-
-#define GET4(p) (((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
-
-/*
- * for speed of unsqueezing from Flash, certain checks are
- * not done inside the loop (as they would be in the unsqueeze program zqs),
- * but instead the checksum is expected to catch corrupted files.
- * in fact the Squeeze array bounds can't be exceeded in practice
- * because the tables are always full for a squeezed kernel.
- */
-enum {
- QFLAG = 1, /* invert powerpc-specific code transformation */
- CHECK = 0, /* check precise bounds in Squeeze array (otherwise checksum detects error) */
-};
-
-static ulong chksum;
-static int rdtab(Block*, Squeeze*, int);
-static ulong* unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
-static uchar* unsqzseg(uchar*, Block*, long, long, char*);
-static Alarm* unsqzal;
-
-int
-issqueezed(uchar *b)
-{
- return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
-}
-
-static void
-unsqzdot(Alarm*)
-{
- unsqzal = alarm(500, unsqzdot, nil);
- print(".");
-}
-
-long
-unsqueezef(Block *b, ulong *entryp)
-{
- uchar *loada, *wp;
- ulong toptxt, topdat, oldsum;
- long asis, nst, nsd;
- Sqhdr *sqh;
- Exec *ex;
-
- if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
- return -1;
- sqh = (Sqhdr*)b->rp;
- if(GET4(sqh->magic) != SQMAGIC)
- return -1;
- chksum = 0;
- toptxt = GET4(sqh->toptxt);
- topdat = GET4(sqh->topdat);
- oldsum = GET4(sqh->sum);
- asis = GET4(sqh->asis);
- nst = GET4(sqh->text);
- nsd = GET4(sqh->data);
- b->rp += SQHDRLEN;
- ex = (Exec*)b->rp;
- if(GET4(ex->magic) != Q_MAGIC){
- print("zqs: not powerPC executable\n");
- return -1;
- }
- *entryp = GET4(ex->entry);
- b->rp += EXECHDRLEN;
- loada = KADDR(PADDR(*entryp));
- wp = unsqzseg(loada, b, nst, toptxt, "text");
- if(wp == nil){
- print("zqs: format error\n");
- return -1;
- }
- if(nsd){
- wp = (uchar*)PGROUND((ulong)wp);
- wp = unsqzseg(wp, b, nsd, topdat, "data");
- if(wp == nil){
- print("zqs: format error\n");
- return -1;
- }
- }
- if(asis){
- memmove(wp, b->rp, asis);
- wp += asis;
- b->rp += asis;
- }
- if(chksum != oldsum){
- print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
- return -1;
- }
- return wp-loada;
-}
-
-static uchar *
-unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
-{
- static Squeeze sq3, sq4;
-
- print("unpack %s %8.8lux %lud:", what, wp, ns);
- if(ns == 0)
- return wp;
- if(rdtab(b, &sq3, 0) < 0)
- return nil;
- if(rdtab(b, &sq4, 8) < 0)
- return nil;
- if(BLEN(b) < ns){
- print(" **size error\n");
- return nil;
- }
- unsqzal = alarm(500, unsqzdot, nil);
- wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
- cancel(unsqzal);
- unsqzal = nil;
- print("\n");
- if(wp == nil){
- print("zqs: corrupt squeezed data stream\n");
- return nil;
- }
- b->rp += ns;
- return wp;
-}
-
-static ulong*
-unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
-{
- ulong nx, csum;
- int code, n;
-
- if(QFLAG){
- QREMAP(top); /* adjust top just once, outside the loop */
- }
- csum = chksum;
- while(rp < ep){
- /* no function calls within this loop for speed */
- code = *rp;
- rp++;
- n = 0;
- nx = code>>4;
- do{
- if(nx == 0){
- nx = top;
- }else{
- if(nx==1){
- nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
- rp += 4;
- }else if(nx <= 8){ /* 2 to 8 */
- nx = ((nx-2)<<8) | rp[0];
- if(CHECK && nx >= sq4->n)
- return nil; /* corrupted file */
- nx = sq4->tab[nx] | rp[1];
- rp += 2;
- }else{ /* 9 to 15 */
- nx = ((nx-9)<<8) | rp[0];
- if(CHECK && nx >= sq3->n)
- return nil; /* corrupted file */
- nx = sq3->tab[nx];
- rp++;
- }
- if(rp > ep)
- return nil; /* corrupted file */
- if(QFLAG){
- QREMAP(nx);
- }
- }
- *wp = nx;
- wp++;
- csum += nx;
- nx = code & 0xF;
- }while(++n == 1);
- }
- chksum = csum;
- return wp;
-}
-
-static int
-rdtab(Block *b, Squeeze *sq, int shift)
-{
- uchar *p, *ep;
- ulong v, w;
- int i;
-
- if(BLEN(b) < 2)
- return -1;
- i = (b->rp[0]<<8) | b->rp[1];
- if(1)
- print(" T%d", i);
- b->rp += 2;
- if((i -= 2) > 0){
- if(BLEN(b) < i)
- return -1;
- }
- sq->n = 0;
- p = b->rp;
- ep = b->rp+i;
- b->rp += i;
- v = 0;
- while(p < ep){
- w = 0;
- do{
- if(p >= ep)
- return -1;
- w = (w<<7) | (*p & 0x7F);
- }while(*p++ & 0x80);
- v += w;
- if(0)
- print("%d %8.8lux %8.8lux\n", sq->n, v, w);
- sq->tab[sq->n++] = v<<shift;
- }
- return 0;
-}
--- a/os/boot/pc/8250.c
+++ /dev/null
@@ -1,308 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-/*
- * INS8250 uart
- */
-enum
-{
- /*
- * register numbers
- */
- Data= 0, /* xmit/rcv buffer */
- Iena= 1, /* interrupt enable */
- Ircv= (1<<0), /* for char rcv'd */
- Ixmt= (1<<1), /* for xmit buffer empty */
- Irstat=(1<<2), /* for change in rcv'er status */
- Imstat=(1<<3), /* for change in modem status */
- Istat= 2, /* interrupt flag (read) */
- Tctl= 2, /* test control (write) */
- Format= 3, /* byte format */
- Bits8= (3<<0), /* 8 bits/byte */
- Stop2= (1<<2), /* 2 stop bits */
- Pena= (1<<3), /* generate parity */
- Peven= (1<<4), /* even parity */
- Pforce=(1<<5), /* force parity */
- Break= (1<<6), /* generate a break */
- Dra= (1<<7), /* address the divisor */
- Mctl= 4, /* modem control */
- Dtr= (1<<0), /* data terminal ready */
- Rts= (1<<1), /* request to send */
- Ri= (1<<2), /* ring */
- Inton= (1<<3), /* turn on interrupts */
- Loop= (1<<4), /* loop back */
- Lstat= 5, /* line status */
- Inready=(1<<0), /* receive buffer full */
- Oerror=(1<<1), /* receiver overrun */
- Perror=(1<<2), /* receiver parity error */
- Ferror=(1<<3), /* rcv framing error */
- Outready=(1<<5), /* output buffer empty */
- Mstat= 6, /* modem status */
- Ctsc= (1<<0), /* clear to send changed */
- Dsrc= (1<<1), /* data set ready changed */
- Rire= (1<<2), /* rising edge of ring indicator */
- Dcdc= (1<<3), /* data carrier detect changed */
- Cts= (1<<4), /* complement of clear to send line */
- Dsr= (1<<5), /* complement of data set ready line */
- Ring= (1<<6), /* complement of ring indicator line */
- Dcd= (1<<7), /* complement of data carrier detect line */
- Scratch=7, /* scratchpad */
- Dlsb= 0, /* divisor lsb */
- Dmsb= 1, /* divisor msb */
-
- Serial= 0,
- Modem= 1,
-};
-
-typedef struct Uart Uart;
-struct Uart
-{
- int port;
- uchar sticky[8]; /* sticky write register values */
- uchar txbusy;
-
- void (*rx)(int); /* routine to take a received character */
- int (*tx)(void); /* routine to get a character to transmit */
-
- ulong frame;
- ulong overrun;
-};
-
-static Uart com[2];
-static Uart* uart;
-
-#define UartFREQ 1843200
-
-#define uartwrreg(u,r,v) outb((u)->port + r, (u)->sticky[r] | (v))
-#define uartrdreg(u,r) inb((u)->port + r)
-
-/*
- * set the baud rate by calculating and setting the baudrate
- * generator constant. This will work with fairly non-standard
- * baud rates.
- */
-static void
-uartsetbaud(Uart *up, int rate)
-{
- ulong brconst;
-
- brconst = (UartFREQ+8*rate-1)/(16*rate);
-
- uartwrreg(up, Format, Dra);
- outb(up->port+Dmsb, (brconst>>8) & 0xff);
- outb(up->port+Dlsb, brconst & 0xff);
- uartwrreg(up, Format, 0);
-}
-
-/*
- * toggle DTR
- */
-static void
-uartdtr(Uart *up, int n)
-{
- if(n)
- up->sticky[Mctl] |= Dtr;
- else
- up->sticky[Mctl] &= ~Dtr;
- uartwrreg(up, Mctl, 0);
-}
-
-/*
- * toggle RTS
- */
-static void
-uartrts(Uart *up, int n)
-{
- if(n)
- up->sticky[Mctl] |= Rts;
- else
- up->sticky[Mctl] &= ~Rts;
- uartwrreg(up, Mctl, 0);
-}
-
-static void
-uartintr(Ureg*, void *arg)
-{
- Uart *up;
- int ch;
- int s, l, loops;
-
- up = arg;
- for(loops = 0; loops < 1024; loops++){
- s = uartrdreg(up, Istat);
- switch(s & 0x3F){
- case 6: /* receiver line status */
- l = uartrdreg(up, Lstat);
- if(l & Ferror)
- up->frame++;
- if(l & Oerror)
- up->overrun++;
- break;
-
- case 4: /* received data available */
- case 12:
- ch = inb(up->port+Data);
- if(up->rx)
- (*up->rx)(ch);
- break;
-
- case 2: /* transmitter empty */
- ch = -1;
- if(up->tx)
- ch = (*up->tx)();
- if(ch != -1)
- outb(up->port+Data, ch);
- else
- up->txbusy = 0;
- break;
-
- case 0: /* modem status */
- uartrdreg(up, Mstat);
- break;
-
- default:
- if(s&1)
- return;
- print("weird modem interrupt #%2.2ux\n", s);
- break;
- }
- }
- panic("uartintr: 0x%2.2ux\n", uartrdreg(up, Istat));
-}
-
-/*
- * turn on a port's interrupts. set DTR and RTS
- */
-static void
-uartenable(Uart *up)
-{
- /*
- * turn on interrupts
- */
- up->sticky[Iena] = 0;
- if(up->tx)
- up->sticky[Iena] |= Ixmt;
- if(up->rx)
- up->sticky[Iena] |= Ircv|Irstat;
- uartwrreg(up, Iena, 0);
-
- /*
- * turn on DTR and RTS
- */
- uartdtr(up, 1);
- uartrts(up, 1);
-}
-
-static void
-uartdisable(Uart* up)
-{
- /*
- * Disable interrupts.
- */
- up->sticky[Iena] = 0;
- uartwrreg(up, Iena, 0);
- uartdtr(up, 0);
- uartrts(up, 0);
-}
-
-void
-uartspecial(int port, void (*rx)(int), int (*tx)(void), int baud)
-{
- Uart *up;
- int vector;
-
- switch(port){
- case 0:
- port = 0x3F8;
- vector = VectorUART0;
- up = &com[0];
- break;
- case 1:
- port = 0x2F8;
- vector = VectorUART1;
- up = &com[1];
- break;
- default:
- return;
- }
-
- if(uart != nil && uart != up)
- uartdisable(uart);
- uart = up;
-
- if(up->port == 0){
- up->port = port;
- setvec(vector, uartintr, up);
- }
-
- /*
- * set rate to 9600 baud.
- * 8 bits/character.
- * 1 stop bit.
- * interrupts enabled.
- */
- uartsetbaud(up, 9600);
- up->sticky[Format] = Bits8;
- uartwrreg(up, Format, 0);
- up->sticky[Mctl] |= Inton;
- uartwrreg(up, Mctl, 0x0);
-
- up->rx = rx;
- up->tx = tx;
- uartenable(up);
- if(baud)
- uartsetbaud(up, baud);
-}
-
-void
-uartputc(int c)
-{
- int i;
- Uart *up;
-
- if((up = uart) == nil)
- return;
- for(i = 0; i < 100; i++){
- if(uartrdreg(up, Lstat) & Outready)
- break;
- delay(1);
- }
- outb(up->port+Data, c);
-}
-
-void
-uartputs(IOQ *q, char *s, int n)
-{
- Uart *up;
- int c, x;
-
- if((up = uart) == nil)
- return;
- while(n--){
- if(*s == '\n')
- q->putc(q, '\r');
- q->putc(q, *s++);
- }
- x = splhi();
- if(up->txbusy == 0 && (c = q->getc(q)) != -1){
- uartputc(c & 0xFF);
- up->txbusy = 1;
- }
- splx(x);
-}
-
-void
-uartdrain(void)
-{
- Uart *up;
- int timeo;
-
- if((up = uart) == nil)
- return;
- for(timeo = 0; timeo < 10000 && up->txbusy; timeo++)
- delay(1);
-}
--- a/os/boot/pc/LICENCE
+++ /dev/null
@@ -1,237 +1,0 @@
-Lucent Public License Version 1.02
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
-LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
-PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-1. DEFINITIONS
-
-"Contribution" means:
-
- a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
- Program, and
- b. in the case of each Contributor,
-
- i. changes to the Program, and
- ii. additions to the Program;
-
- where such changes and/or additions to the Program were added to the
- Program by such Contributor itself or anyone acting on such
- Contributor's behalf, and the Contributor explicitly consents, in
- accordance with Section 3C, to characterization of the changes and/or
- additions as Contributions.
-
-"Contributor" means LUCENT and any other entity that has Contributed a
-Contribution to the Program.
-
-"Distributor" means a Recipient that distributes the Program,
-modifications to the Program, or any part thereof.
-
-"Licensed Patents" mean patent claims licensable by a Contributor
-which are necessarily infringed by the use or sale of its Contribution
-alone or when combined with the Program.
-
-"Original Program" means the original version of the software
-accompanying this Agreement as released by LUCENT, including source
-code, object code and documentation, if any.
-
-"Program" means the Original Program and Contributions or any part
-thereof
-
-"Recipient" means anyone who receives the Program under this
-Agreement, including all Contributors.
-
-2. GRANT OF RIGHTS
-
- a. Subject to the terms of this Agreement, each Contributor hereby
- grants Recipient a non-exclusive, worldwide, royalty-free copyright
- license to reproduce, prepare derivative works of, publicly display,
- publicly perform, distribute and sublicense the Contribution of such
- Contributor, if any, and such derivative works, in source code and
- object code form.
-
- b. Subject to the terms of this Agreement, each Contributor hereby
- grants Recipient a non-exclusive, worldwide, royalty-free patent
- license under Licensed Patents to make, use, sell, offer to sell,
- import and otherwise transfer the Contribution of such Contributor, if
- any, in source code and object code form. The patent license granted
- by a Contributor shall also apply to the combination of the
- Contribution of that Contributor and the Program if, at the time the
- Contribution is added by the Contributor, such addition of the
- Contribution causes such combination to be covered by the Licensed
- Patents. The patent license granted by a Contributor shall not apply
- to (i) any other combinations which include the Contribution, nor to
- (ii) Contributions of other Contributors. No hardware per se is
- licensed hereunder.
-
- c. Recipient understands that although each Contributor grants the
- licenses to its Contributions set forth herein, no assurances are
- provided by any Contributor that the Program does not infringe the
- patent or other intellectual property rights of any other entity. Each
- Contributor disclaims any liability to Recipient for claims brought by
- any other entity based on infringement of intellectual property rights
- or otherwise. As a condition to exercising the rights and licenses
- granted hereunder, each Recipient hereby assumes sole responsibility
- to secure any other intellectual property rights needed, if any. For
- example, if a third party patent license is required to allow
- Recipient to distribute the Program, it is Recipient's responsibility
- to acquire that license before distributing the Program.
-
- d. Each Contributor represents that to its knowledge it has sufficient
- copyright rights in its Contribution, if any, to grant the copyright
- license set forth in this Agreement.
-
-3. REQUIREMENTS
-
-A. Distributor may choose to distribute the Program in any form under
-this Agreement or under its own license agreement, provided that:
-
- a. it complies with the terms and conditions of this Agreement;
-
- b. if the Program is distributed in source code or other tangible
- form, a copy of this Agreement or Distributor's own license agreement
- is included with each copy of the Program; and
-
- c. if distributed under Distributor's own license agreement, such
- license agreement:
-
- i. effectively disclaims on behalf of all Contributors all warranties
- and conditions, express and implied, including warranties or
- conditions of title and non-infringement, and implied warranties or
- conditions of merchantability and fitness for a particular purpose;
- ii. effectively excludes on behalf of all Contributors all liability
- for damages, including direct, indirect, special, incidental and
- consequential damages, such as lost profits; and
- iii. states that any provisions which differ from this Agreement are
- offered by that Contributor alone and not by any other party.
-
-B. Each Distributor must include the following in a conspicuous
- location in the Program:
-
- Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
- Reserved.
-
-C. In addition, each Contributor must identify itself as the
-originator of its Contribution in a manner that reasonably allows
-subsequent Recipients to identify the originator of the Contribution.
-Also, each Contributor must agree that the additions and/or changes
-are intended to be a Contribution. Once a Contribution is contributed,
-it may not thereafter be revoked.
-
-4. COMMERCIAL DISTRIBUTION
-
-Commercial distributors of software may accept certain
-responsibilities with respect to end users, business partners and the
-like. While this license is intended to facilitate the commercial use
-of the Program, the Distributor who includes the Program in a
-commercial product offering should do so in a manner which does not
-create potential liability for Contributors. Therefore, if a
-Distributor includes the Program in a commercial product offering,
-such Distributor ("Commercial Distributor") hereby agrees to defend
-and indemnify every Contributor ("Indemnified Contributor") against
-any losses, damages and costs (collectively"Losses") arising from
-claims, lawsuits and other legal actions brought by a third party
-against the Indemnified Contributor to the extent caused by the acts
-or omissions of such Commercial Distributor in connection with its
-distribution of the Program in a commercial product offering. The
-obligations in this section do not apply to any claims or Losses
-relating to any actual or alleged intellectual property infringement.
-In order to qualify, an Indemnified Contributor must: a) promptly
-notify the Commercial Distributor in writing of such claim, and b)
-allow the Commercial Distributor to control, and cooperate with the
-Commercial Distributor in, the defense and any related settlement
-negotiations. The Indemnified Contributor may participate in any such
-claim at its own expense.
-
-For example, a Distributor might include the Program in a commercial
-product offering, Product X. That Distributor is then a Commercial
-Distributor. If that Commercial Distributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Distributor's responsibility
-alone. Under this section, the Commercial Distributor would have to
-defend claims against the Contributors related to those performance
-claims and warranties, and if a court requires any Contributor to pay
-any damages as a result, the Commercial Distributor must pay those
-damages.
-
-5. NO WARRANTY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
-PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
-WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
-OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
-responsible for determining the appropriateness of using and
-distributing the Program and assumes all risks associated with its
-exercise of rights under this Agreement, including but not limited to
-the risks and costs of program errors, compliance with applicable
-laws, damage to or loss of data, programs or equipment, and
-unavailability or interruption of operations.
-
-6. DISCLAIMER OF LIABILITY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-7. EXPORT CONTROL
-
-Recipient agrees that Recipient alone is responsible for compliance
-with the United States export administration regulations (and the
-export control laws and regulation of any other countries).
-
-8. GENERAL
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further
-action by the parties hereto, such provision shall be reformed to the
-minimum extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against a Contributor with
-respect to a patent applicable to software (including a cross-claim or
-counterclaim in a lawsuit), then any patent licenses granted by that
-Contributor to such Recipient under this Agreement shall terminate as
-of the date such litigation is filed. In addition, if Recipient
-institutes patent litigation against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it
-fails to comply with any of the material terms or conditions of this
-Agreement and does not cure such failure in a reasonable period of
-time after becoming aware of such noncompliance. If all Recipient's
-rights under this Agreement terminate, Recipient agrees to cease use
-and distribution of the Program as soon as reasonably practicable.
-However, Recipient's obligations under this Agreement and any licenses
-granted by Recipient relating to the Program shall continue and
-survive.
-
-LUCENT may publish new versions (including revisions) of this
-Agreement from time to time. Each new version of the Agreement will be
-given a distinguishing version number. The Program (including
-Contributions) may always be distributed subject to the version of the
-Agreement under which it was received. In addition, after a new
-version of the Agreement is published, Contributor may elect to
-distribute the Program (including its Contributions) under the new
-version. No one other than LUCENT has the right to modify this
-Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
-Recipient receives no rights or licenses to the intellectual property
-of any Contributor under this Agreement, whether expressly, by
-implication, estoppel or otherwise. All rights in the Program not
-expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and
-the intellectual property laws of the United States of America. No
-party to this Agreement will bring a legal action under this Agreement
-more than one year after the cause of action arose. Each party waives
-its rights to a jury trial in any resulting litigation.
-
--- a/os/boot/pc/NOTICE
+++ /dev/null
@@ -1,4 +1,0 @@
-Copyright © 1995-2007 Lucent Technologies Inc. and others. All rights reserved.
-Revisions for use with Inferno © 2003-2007 Vita Nuova Holdings Limited.
-
-This software is provided under the terms of the Lucent Public License, Version 1.02.
--- a/os/boot/pc/ahci.h
+++ /dev/null
@@ -1,275 +1,0 @@
-/*
- * advanced host controller interface (sata)
- * © 2007 coraid, inc
- */
-
-/* ata errors */
-enum {
- Emed = 1<<0, /* media error */
- Enm = 1<<1, /* no media */
- Eabrt = 1<<2, /* abort */
- Emcr = 1<<3, /* media change request */
- Eidnf = 1<<4, /* no user-accessible address */
- Emc = 1<<5, /* media change */
- Eunc = 1<<6, /* data error */
- Ewp = 1<<6, /* write protect */
- Eicrc = 1<<7, /* interface crc error */
-
- Efatal = Eidnf|Eicrc, /* must sw reset */
-};
-
-/* ata status */
-enum {
- ASerr = 1<<0, /* error */
- ASdrq = 1<<3, /* request */
- ASdf = 1<<5, /* fault */
- ASdrdy = 1<<6, /* ready */
- ASbsy = 1<<7, /* busy */
-
- ASobs = 1<<1|1<<2|1<<4,
-};
-
-/* pci configuration */
-enum {
- Abar = 5,
-};
-
-/*
- * ahci memory configuration
- *
- * 0000-0023 generic host control
- * 0024-009f reserved
- * 00a0-00ff vendor specific.
- * 0100-017f port 0
- * ...
- * 1080-1100 port 31
- */
-
-/* cap bits: supported features */
-enum {
- Hs64a = 1<<31, /* 64-bit addressing */
- Hsncq = 1<<30, /* ncq */
- Hssntf = 1<<29, /* snotification reg. */
- Hsmps = 1<<28, /* mech pres switch */
- Hsss = 1<<27, /* staggered spinup */
- Hsalp = 1<<26, /* aggressive link pm */
- Hsal = 1<<25, /* activity led */
- Hsclo = 1<<24, /* command-list override */
- Hiss = 1<<20, /* for interface speed */
-// Hsnzo = 1<<19,
- Hsam = 1<<18, /* ahci-mode only */
- Hspm = 1<<17, /* port multiplier */
-// Hfbss = 1<<16,
- Hpmb = 1<<15, /* multiple-block pio */
- Hssc = 1<<14, /* slumber state */
- Hpsc = 1<<13, /* partial-slumber state */
- Hncs = 1<<8, /* n command slots */
- Hcccs = 1<<7, /* coal */
- Hems = 1<<6, /* enclosure mgmt. */
- Hsxs = 1<<5, /* external sata */
- Hnp = 1<<0, /* n ports */
-};
-
-/* ghc bits */
-enum {
- Hae = 1<<31, /* enable ahci */
- Hie = 1<<1, /* " interrupts */
- Hhr = 1<<0, /* hba reset */
-};
-
-typedef struct {
- ulong cap;
- ulong ghc;
- ulong isr;
- ulong pi; /* ports implemented */
- ulong ver;
- ulong ccc; /* coaleasing control */
- ulong cccports;
- ulong emloc;
- ulong emctl;
-} Ahba;
-
-enum {
- Acpds = 1<<31, /* cold port detect status */
- Atfes = 1<<30, /* task file error status */
- Ahbfs = 1<<29, /* hba fatal */
- Ahbds = 1<<28, /* hba error (parity error) */
- Aifs = 1<<27, /* interface fatal §6.1.2 */
- Ainfs = 1<<26, /* interface error (recovered) */
- Aofs = 1<<24, /* too many bytes from disk */
- Aipms = 1<<23, /* incorrect prt mul status */
- Aprcs = 1<<22, /* PhyRdy change status Pxserr.diag.n */
- Adpms = 1<<7, /* mechanical presence status */
- Apcs = 1<<6, /* port connect diag.x */
- Adps = 1<<5, /* descriptor processed */
- Aufs = 1<<4, /* unknown fis diag.f */
- Asdbs = 1<<3, /* set device bits fis received w/ i bit set */
- Adss = 1<<2, /* dma setup */
- Apio = 1<<1, /* pio setup fis */
- Adhrs = 1<<0, /* device to host register fis */
-
- IEM = Acpds|Atfes|Ahbds|Ahbfs|Ahbds|Aifs|Ainfs|Aprcs|Apcs|Adps|
- Aufs|Asdbs|Adss|Adhrs,
- Ifatal = Atfes|Ahbfs|Ahbds|Aifs,
-};
-
-/* serror bits */
-enum {
- SerrX = 1<<26, /* exchanged */
- SerrF = 1<<25, /* unknown fis */
- SerrT = 1<<24, /* transition error */
- SerrS = 1<<23, /* link sequence */
- SerrH = 1<<22, /* handshake */
- SerrC = 1<<21, /* crc */
- SerrD = 1<<20, /* not used by ahci */
- SerrB = 1<<19, /* 10-tp-8 decode */
- SerrW = 1<<18, /* comm wake */
- SerrI = 1<<17, /* phy internal */
- SerrN = 1<<16, /* phyrdy change */
-
- ErrE = 1<<11, /* internal */
- ErrP = 1<<10, /* ata protocol violation */
- ErrC = 1<<9, /* communication */
- ErrT = 1<<8, /* transient */
- ErrM = 1<<1, /* recoverd comm */
- ErrI = 1<<0, /* recovered data integrety */
-
- ErrAll = ErrE|ErrP|ErrC|ErrT|ErrM|ErrI,
- SerrAll = SerrX|SerrF|SerrT|SerrS|SerrH|SerrC|SerrD|SerrB|SerrW|
- SerrI|SerrN|ErrAll,
- SerrBad = 0x7f<<19,
-};
-
-/* cmd register bits */
-enum {
- Aicc = 1<<28, /* interface communcations control. 4 bits */
- Aasp = 1<<27, /* agressive slumber & partial sleep */
- Aalpe = 1<<26, /* agressive link pm enable */
- Adlae = 1<<25, /* drive led on atapi */
- Aatapi = 1<<24, /* device is atapi */
- Aesp = 1<<21, /* external sata port */
- Acpd = 1<<20, /* cold presence detect */
- Ampsp = 1<<19, /* mechanical pres. */
- Ahpcp = 1<<18, /* hot plug capable */
- Apma = 1<<17, /* pm attached */
- Acps = 1<<16, /* cold presence state */
- Acr = 1<<15, /* cmdlist running */
- Afr = 1<<14, /* fis running */
- Ampss = 1<<13, /* mechanical presence switch state */
- Accs = 1<<8, /* current command slot 12:08 */
- Afre = 1<<4, /* fis enable receive */
- Aclo = 1<<3, /* command list override */
- Apod = 1<<2, /* power on dev (requires cold-pres. detect) */
- Asud = 1<<1, /* spin-up device; requires ss capability */
- Ast = 1<<0, /* start */
-
- Arun = Ast|Acr|Afre|Afr,
-};
-
-/* ctl register bits */
-enum {
- Aipm = 1<<8, /* interface power mgmt. 3=off */
- Aspd = 1<<4,
- Adet = 1<<0, /* device detection */
-};
-
-#define sstatus scr0
-#define sctl scr2
-#define serror scr1
-#define sactive scr3
-
-typedef struct {
- ulong list; /* PxCLB must be 1kb aligned. */
- ulong listhi;
- ulong fis; /* 256-byte aligned */
- ulong fishi;
- ulong isr;
- ulong ie; /* interrupt enable */
- ulong cmd;
- ulong res1;
- ulong task;
- ulong sig;
- ulong scr0;
- ulong scr2;
- ulong scr1;
- ulong scr3;
- ulong ci; /* command issue */
- ulong ntf;
- uchar res2[8];
- ulong vendor;
-} Aport;
-
-/* in host's memory; not memory mapped */
-typedef struct {
- uchar *base;
- uchar *d;
- uchar *p;
- uchar *r;
- uchar *u;
- ulong *devicebits;
-} Afis;
-
-enum {
- Lprdtl = 1<<16, /* physical region descriptor table len */
- Lpmp = 1<<12, /* port multiplier port */
- Lclear = 1<<10, /* clear busy on R_OK */
- Lbist = 1<<9,
- Lreset = 1<<8,
- Lpref = 1<<7, /* prefetchable */
- Lwrite = 1<<6,
- Latapi = 1<<5,
- Lcfl = 1<<0, /* command fis length in double words */
-};
-
-/* in hosts memory; memory mapped */
-typedef struct {
- ulong flags;
- ulong len;
- ulong ctab;
- ulong ctabhi;
- uchar reserved[16];
-} Alist;
-
-typedef struct {
- ulong dba;
- ulong dbahi;
- ulong pad;
- ulong count;
-} Aprdt;
-
-typedef struct {
- uchar cfis[0x40];
- uchar atapi[0x10];
- uchar pad[0x30];
- Aprdt prdt;
-} Actab;
-
-enum {
- Ferror = 1,
- Fdone = 2,
-};
-
-enum {
- Dllba = 1,
- Dsmart = 1<<1,
- Dpower = 1<<2,
- Dnop = 1<<3,
- Datapi = 1<<4,
- Datapi16= 1<<5,
-};
-
-typedef struct {
-// QLock;
-// Rendez;
- uchar flag;
- uchar feat;
- uchar smart;
- Afis fis;
- Alist *list;
- Actab *ctab;
-} Aportm;
-
-typedef struct {
- Aport *p;
- Aportm *m;
-} Aportc;
--- a/os/boot/pc/alarm.c
+++ /dev/null
@@ -1,123 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#define MAXALARM 10
-
-Alarm alarmtab[MAXALARM];
-
-/*
- * Insert new into list after where
- */
-void
-insert(List **head, List *where, List *new)
-{
- if(where == 0){
- new->next = *head;
- *head = new;
- }else{
- new->next = where->next;
- where->next = new;
- }
-
-}
-
-/*
- * Delete old from list. where->next is known to be old.
- */
-void
-delete(List **head, List *where, List *old)
-{
- if(where == 0){
- *head = old->next;
- return;
- }
- where->next = old->next;
-}
-
-Alarm*
-newalarm(void)
-{
- int i;
- Alarm *a;
-
- for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
- if(a->busy==0 && a->f==0){
- a->f = 0;
- a->arg = 0;
- a->busy = 1;
- return a;
- }
- panic("newalarm");
- return 0; /* not reached */
-}
-
-Alarm*
-alarm(int ms, void (*f)(Alarm*), void *arg)
-{
- Alarm *a, *w, *pw;
- ulong s;
-
- if(ms < 0)
- ms = 0;
- s = splhi();
- a = newalarm();
- a->dt = MS2TK(ms);
- a->f = f;
- a->arg = arg;
- pw = 0;
- for(w=m->alarm; w; pw=w, w=w->next){
- if(w->dt <= a->dt){
- a->dt -= w->dt;
- continue;
- }
- w->dt -= a->dt;
- break;
- }
- insert(&m->alarm, pw, a);
- splx(s);
- return a;
-}
-
-void
-cancel(Alarm *a)
-{
- a->f = 0;
-}
-
-void
-alarminit(void)
-{
-}
-
-#define NA 10 /* alarms per clock tick */
-void
-checkalarms(void)
-{
- int i, n, s;
- Alarm *a;
- void (*f)(Alarm*);
- Alarm *alist[NA];
-
- s = splhi();
- a = m->alarm;
- if(a){
- for(n=0; a && a->dt<=0 && n<NA; n++){
- alist[n] = a;
- delete(&m->alarm, 0, a);
- a = m->alarm;
- }
- if(a)
- a->dt--;
-
- for(i = 0; i < n; i++){
- f = alist[i]->f; /* avoid race with cancel */
- if(f)
- (*f)(alist[i]);
- alist[i]->busy = 0;
- }
- }
- splx(s);
-}
--- a/os/boot/pc/aoe.h
+++ /dev/null
@@ -1,76 +1,0 @@
-/*
- * ATA-over-Ethernet
- */
-enum {
- ACata,
- ACconfig,
-};
-
-enum {
- AQCread,
- AQCtest,
- AQCprefix,
- AQCset,
- AQCfset,
-};
-
-enum {
- AEcmd = 1,
- AEarg,
- AEdev,
- AEcfg,
- AEver,
-};
-
-enum {
- Aoetype = 0x88a2,
- Aoever = 1,
-
- AFerr = 1<<2,
- AFrsp = 1<<3,
-
- AAFwrite= 1,
- AAFext = 1<<6,
-};
-
-enum {
- Crd = 0x20,
- Crdext = 0x24,
- Cwr = 0x30,
- Cwrext = 0x34,
- Cid = 0xec,
-};
-
-typedef struct {
- uchar dst[Eaddrlen];
- uchar src[Eaddrlen];
- uchar type[2];
- uchar verflag;
- uchar error;
- uchar major[2];
- uchar minor;
- uchar cmd;
- uchar tag[4];
-} Aoehdr;
-
-typedef struct {
- Aoehdr;
- uchar aflag;
- uchar errfeat;
- uchar scnt;
- uchar cmdstat;
- uchar lba[6];
- uchar res[2];
-} Aoeata;
-
-typedef struct {
- Aoehdr;
- uchar bufcnt[2];
- uchar fwver[2];
- uchar scnt;
- uchar verccmd;
- uchar cslen[2];
-} Aoeqc;
-
-extern char Echange[];
-extern char Enotup[];
--- a/os/boot/pc/apm.c
+++ /dev/null
@@ -1,16 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-Apminfo apm;
-
-void
-apminit(void)
-{
- if(getconf("apm0") && apm.haveinfo)
- changeconf("apm0=ax=%x ebx=%x cx=%x dx=%x di=%x esi=%x\n",
- apm.ax, apm.ebx, apm.cx, apm.dx, apm.di, apm.esi);
-}
--- a/os/boot/pc/bcom.c
+++ /dev/null
@@ -1,463 +1,0 @@
-/*
- * ld - DOS boot loader of Plan 9
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "fs.h"
-
-Type types[] = {
- { Tfloppy,
- Fini|Ffs,
- floppyinit, floppyinitdev,
- floppygetfspart, 0, floppyboot,
- },
- { Tsd,
- Fini|Ffs,
- sdinit, sdinitdev,
- sdgetfspart, sdaddconf, sdboot,
- },
- { Tnil,
- 0,
- 0, 0,
- 0, 0, 0,
- },
-};
-
-#include "sd.h"
-
-extern SDifc sdataifc;
-extern SDifc sdmylexifc;
-extern SDifc sd53c8xxifc;
-SDifc* sdifc[] = {
- &sdataifc,
-// &sdmylexifc,
-// &sd53c8xxifc,
- nil,
-};
-
-typedef struct Mode Mode;
-
-enum {
- Maxdev = 7,
- Dany = -1,
- Nmedia = 16,
- Nini = 10,
-};
-
-enum { /* mode */
- Mauto = 0x00,
- Mlocal = 0x01,
- Manual = 0x02,
- NMode = 0x03,
-};
-
-typedef struct Medium Medium;
-struct Medium {
- Type* type;
- int flag;
- int dev;
- char name[NAMELEN];
- Fs* inifs;
-
- Medium* next;
-};
-
-typedef struct Mode {
- char* name;
- int mode;
-} Mode;
-
-static Medium media[Nmedia];
-static Medium *curmedium = media;
-
-static Mode modes[NMode+1] = {
- [Mauto] { "auto", Mauto, },
- [Mlocal] { "local", Mlocal, },
- [Manual] { "manual", Manual, },
-};
-
-char *defaultpartition = "new";
-
-static Medium*
-parse(char *line, char **file)
-{
- char *p;
- Type *tp;
- Medium *mp;
-
- if(p = strchr(line, '!')) {
- *p++ = 0;
- *file = p;
- } else
- *file = "";
-
- for(tp = types; tp->type != Tnil; tp++)
- for(mp = tp->media; mp; mp = mp->next)
- if(strcmp(mp->name, line) == 0)
- return mp;
- return nil;
-}
-
-static int
-boot(Medium *mp, char *file)
-{
- static Boot b;
-
- memset(&b, 0, sizeof b);
- b.state = INIT9LOAD;
-
-// sprint(BOOTLINE, "%s!%s", mp->name, file);
- return (*mp->type->boot)(mp->dev, file, &b);
-}
-
-static Medium*
-allocm(Type *tp)
-{
- Medium **l;
-
- if(curmedium >= &media[Nmedia])
- return 0;
-
- for(l = &tp->media; *l; l = &(*l)->next)
- ;
- *l = curmedium++;
- return *l;
-}
-
-char *parts[] = { "dos", "9fat", "fs", 0 };
-
-Medium*
-probe(int type, int flag, int dev)
-{
- Type *tp;
- int i;
- Medium *mp;
-
- for(tp = types; tp->type != Tnil; tp++){
- if(type != Tany && type != tp->type)
- continue;
-
- if(flag != Fnone){
- for(mp = tp->media; mp; mp = mp->next){
- if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
- return mp;
- }
- }
-
- if((tp->flag & Fprobe) == 0){
- tp->flag |= Fprobe;
- tp->mask = (*tp->init)();
- }
-
- for(i = 0; tp->mask; i++){
- if((tp->mask & (1<<i)) == 0)
- continue;
- tp->mask &= ~(1<<i);
-
- if((mp = allocm(tp)) == 0)
- continue;
-
- mp->dev = i;
- mp->flag = tp->flag;
- mp->type = tp;
- (*tp->initdev)(i, mp->name);
-
- if((flag & mp->flag) && (dev == Dany || dev == i))
- return mp;
- }
- }
-
- return 0;
-}
-
-extern int loopconst;
-void
-main(void)
-{
- Medium *mp;
- int flag;
- char def[2*NAMELEN], line[80], *p, *file;
- Type *tp;
-
- i8042a20();
- memset(m, 0, sizeof(Mach));
- trapinit();
- clockinit();
- alarminit();
- spllo();
-
- kbdinit();
-
- if((ulong)&end > (KZERO|(640*1024)))
- panic("i'm too big");
-
- /*
- * If there were any arguments, MS-DOS leaves a character
- * count followed by the arguments in the runtime header.
- * Step over the leading space.
- */
- p = (char*)0x80080080;
- if(p[0]){
- p[p[0]+1] = 0;
- p += 2;
- }
- else
- p = 0;
-
- /*
- * Advance command line to first option, if any
- */
- if(p) {
- while(*p==' ' || *p=='\t')
- p++;
- if(*p == 0)
- p = nil;
- }
-
- /*
- * Probe everything, to collect device names.
- */
- probe(Tany, Fnone, Dany);
-
- if(p != 0) {
- if((mp = parse(p, &file)) == nil) {
- print("bad loadfile syntax: %s\n", p);
- goto done;
- }
- boot(mp, file);
- }
-
-done:
- flag = 0;
- for(tp = types; tp->type != Tnil; tp++){
- for(mp = tp->media; mp; mp = mp->next){
- if(flag == 0){
- flag = 1;
- print("Load devices:");
- }
- print(" %s", mp->name);
- }
- }
- if(flag)
- print("\n");
-
- for(;;){
- if(getstr("load from", line, sizeof(line), nil, 0) >= 0)
- if(mp = parse(line, &file))
- boot(mp, file);
- def[0] = 0;
- }
-}
-
-int
-getfields(char *lp, char **fields, int n, char sep)
-{
- int i;
-
- for(i = 0; lp && *lp && i < n; i++){
- while(*lp == sep)
- *lp++ = 0;
- if(*lp == 0)
- break;
- fields[i] = lp;
- while(*lp && *lp != sep){
- if(*lp == '\\' && *(lp+1) == '\n')
- *lp++ = ' ';
- lp++;
- }
- }
- return i;
-}
-
-int
-cistrcmp(char *a, char *b)
-{
- int ac, bc;
-
- for(;;){
- ac = *a++;
- bc = *b++;
-
- if(ac >= 'A' && ac <= 'Z')
- ac = 'a' + (ac - 'A');
- if(bc >= 'A' && bc <= 'Z')
- bc = 'a' + (bc - 'A');
- ac -= bc;
- if(ac)
- return ac;
- if(bc == 0)
- break;
- }
- return 0;
-}
-
-int
-cistrncmp(char *a, char *b, int n)
-{
- unsigned ac, bc;
-
- while(n > 0){
- ac = *a++;
- bc = *b++;
- n--;
-
- if(ac >= 'A' && ac <= 'Z')
- ac = 'a' + (ac - 'A');
- if(bc >= 'A' && bc <= 'Z')
- bc = 'a' + (bc - 'A');
-
- ac -= bc;
- if(ac)
- return ac;
- if(bc == 0)
- break;
- }
-
- return 0;
-}
-
-void*
-ialloc(ulong n, int align)
-{
-
- static ulong palloc;
- ulong p;
- int a;
-
- if(palloc == 0)
- palloc = 3*1024*1024;
-
- p = palloc;
- if(align <= 0)
- align = 4;
- if(a = n % align)
- n += align - a;
- if(a = p % align)
- p += align - a;
-
- palloc = p+n;
-
- return memset((void*)(p|KZERO), 0, n);
-}
-
-void*
-xspanalloc(ulong size, int align, ulong span)
-{
- ulong a, v;
-
- a = (ulong)ialloc(size+align+span, 0);
-
- if(span > 2)
- v = (a + span) & ~(span-1);
- else
- v = a;
-
- if(align > 1)
- v = (v + align) & ~(align-1);
-
- return (void*)v;
-}
-
-static Block *allocbp;
-
-Block*
-allocb(int size)
-{
- Block *bp, **lbp;
- ulong addr;
-
- lbp = &allocbp;
- for(bp = *lbp; bp; bp = bp->next){
- if((bp->lim - bp->base) >= size){
- *lbp = bp->next;
- break;
- }
- lbp = &bp->next;
- }
- if(bp == 0){
- bp = ialloc(sizeof(Block)+size+64, 0);
- addr = (ulong)bp;
- addr = ROUNDUP(addr + sizeof(Block), 8);
- bp->base = (uchar*)addr;
- bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
- }
-
- if(bp->flag)
- panic("allocb reuse\n");
-
- bp->rp = bp->base;
- bp->wp = bp->rp;
- bp->next = 0;
- bp->flag = 1;
-
- return bp;
-}
-
-void
-freeb(Block* bp)
-{
- bp->next = allocbp;
- allocbp = bp;
-
- bp->flag = 0;
-}
-
-enum {
- Paddr= 0x70, /* address port */
- Pdata= 0x71, /* data port */
-};
-
-uchar
-nvramread(int offset)
-{
- outb(Paddr, offset);
- return inb(Pdata);
-}
-
-void (*etherdetach)(void);
-void (*floppydetach)(void);
-void (*sddetach)(void);
-
-void
-warp9(ulong entry)
-{
- if(etherdetach)
- etherdetach();
- consdrain();
- (*(void(*)(void))(PADDR(entry)))();
-}
-
-char*
-getconf(char*)
-{
- return nil;
-}
-
-void
-addconf(char*, ...)
-{
-}
-
-void
-uartspecial(int, void(*)(int), int(*)(void), int)
-{
-}
-
-void
-uartputs(IOQ*, char*, int)
-{
-}
-
-void
-uartputc(int)
-{}
-
-void
-uartdrain(void)
-{
-}
--- a/os/boot/pc/boot.c
+++ /dev/null
@@ -1,451 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "../../../utils/libmach/elf.h"
-
-static uchar elfident[7] = {
- '\177', 'E', 'L', 'F', '\1', '\1', '\1'
-};
-static Ehdr ehdr, rehdr;
-static Phdr *phdr;
-static int curphdr;
-static ulong curoff;
-static ulong elftotal;
-static long (*swal)(long);
-static ushort (*swab)(ushort);
-
-/*
- * big-endian short
- */
-ushort
-beswab(ushort s)
-{
- uchar *p;
-
- p = (uchar*)&s;
- return (p[0]<<8) | p[1];
-}
-
-/*
- * big-endian long
- */
-long
-beswal(long l)
-{
- uchar *p;
-
- p = (uchar*)&l;
- return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
-}
-
-/*
- * little-endian short
- */
-ushort
-leswab(ushort s)
-{
- uchar *p;
-
- p = (uchar*)&s;
- return (p[1]<<8) | p[0];
-}
-
-/*
- * little-endian long
- */
-long
-leswal(long l)
-{
- uchar *p;
-
- p = (uchar*)&l;
- return (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
-}
-
-/*
- * Convert header to canonical form
- */
-static void
-hswal(long *lp, int n, long (*swap) (long))
-{
- while (n--) {
- *lp = (*swap) (*lp);
- lp++;
- }
-}
-
-static int
-readehdr(Boot *b)
-{
- int i;
-
- /* bitswap the header according to the DATA format */
- if(ehdr.ident[CLASS] != ELFCLASS32) {
- print("bad ELF class - not 32 bit\n");
- return 0;
- }
- if(ehdr.ident[DATA] == ELFDATA2LSB) {
- swab = leswab;
- swal = leswal;
- } else if(ehdr.ident[DATA] == ELFDATA2MSB) {
- swab = beswab;
- swal = beswal;
- } else {
- print("bad ELF encoding - not big or little endian\n");
- return 0;
- }
- memmove(&rehdr, &ehdr, sizeof(Ehdr));
-
- ehdr.type = swab(ehdr.type);
- ehdr.machine = swab(ehdr.machine);
- ehdr.version = swal(ehdr.version);
- ehdr.elfentry = swal(ehdr.elfentry);
- ehdr.phoff = swal(ehdr.phoff);
- ehdr.shoff = swal(ehdr.shoff);
- ehdr.flags = swal(ehdr.flags);
- ehdr.ehsize = swab(ehdr.ehsize);
- ehdr.phentsize = swab(ehdr.phentsize);
- ehdr.phnum = swab(ehdr.phnum);
- ehdr.shentsize = swab(ehdr.shentsize);
- ehdr.shnum = swab(ehdr.shnum);
- ehdr.shstrndx = swab(ehdr.shstrndx);
- if(ehdr.type != EXEC || ehdr.version != CURRENT)
- return 0;
- if(ehdr.phentsize != sizeof(Phdr))
- return 0;
-
- if(debug)
- print("readehdr OK entry 0x%lux\n", ehdr.elfentry);
-
- curoff = sizeof(Ehdr);
- i = ehdr.phoff+ehdr.phentsize*ehdr.phnum - curoff;
- b->state = READPHDR;
- b->bp = (char*)malloc(i);
- b->wp = b->bp;
- b->ep = b->wp + i;
- phdr = (Phdr*)(b->bp + ehdr.phoff-sizeof(Ehdr));
- if(debug)
- print("phdr...");
-
- return 1;
-}
-
-static int
-nextphdr(Boot *b)
-{
- Phdr *php;
- ulong entry, offset;
- char *paddr;
-
- if(debug)
- print("readedata %d\n", curphdr);
-
- for(; curphdr < ehdr.phnum; curphdr++){
- php = phdr+curphdr;
- if(php->type != LOAD)
- continue;
- offset = php->offset;
- paddr = (char*)PADDR(php->paddr);
- if(offset < curoff){
- /*
- * Can't (be bothered to) rewind the
- * input, it might be from tftp. If we
- * did then we could boot FreeBSD kernels
- * too maybe.
- */
- return 0;
- }
- if(php->offset > curoff){
- b->state = READEPAD;
- b->bp = (char*)malloc(offset - curoff);
- b->wp = b->bp;
- b->ep = b->wp + offset - curoff;
- if(debug)
- print("nextphdr %lud...\n", offset - curoff);
- return 1;
- }
- b->state = READEDATA;
- b->bp = paddr;
- b->wp = b->bp;
- b->ep = b->wp+php->filesz;
- print("%ud+", php->filesz);
- elftotal += php->filesz;
- if(debug)
- print("nextphdr %ud@0x%p\n", php->filesz, paddr);
-
- return 1;
- }
-
- if(curphdr != 0){
- print("=%lud\n", elftotal);
- b->state = TRYBOOT;
- entry = ehdr.elfentry & ~0xF0000000;
- PLLONG(b->exec.entry, entry);
- return 1;
- }
-
- return 0;
-}
-
-static int
-readepad(Boot *b)
-{
- Phdr *php;
-
- php = phdr+curphdr;
- if(debug)
- print("readepad %d\n", curphdr);
- curoff = php->offset;
-
- return nextphdr(b);
-}
-
-static int
-readedata(Boot *b)
-{
- Phdr *php;
-
- php = phdr+curphdr;
- if(debug)
- print("readedata %d\n", curphdr);
- if(php->filesz < php->memsz){
- print("%lud", php->memsz-php->filesz);
- elftotal += php->memsz-php->filesz;
- memset((char*)(PADDR(php->paddr)+php->filesz), 0, php->memsz-php->filesz);
- }
- curoff = php->offset+php->filesz;
- curphdr++;
-
- return nextphdr(b);
-}
-
-static int
-readphdr(Boot *b)
-{
- Phdr *php;
-
- php = phdr;
- hswal((long*)php, ehdr.phentsize*ehdr.phnum/sizeof(long), swal);
- if(debug)
- print("phdr curoff %lud vaddr 0x%lux paddr 0x%lux\n",
- curoff, php->vaddr, php->paddr);
-
- curoff = ehdr.phoff+ehdr.phentsize*ehdr.phnum;
- curphdr = 0;
-
- return nextphdr(b);
-}
-
-static int
-addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
-{
- int n;
-
- n = edbuf - *dbuf;
- if(n <= 0)
- return 0;
- if(n > esbuf - *sbuf)
- n = esbuf - *sbuf;
- if(n <= 0)
- return -1;
-
- memmove(*dbuf, *sbuf, n);
- *sbuf += n;
- *dbuf += n;
- return edbuf - *dbuf;
-}
-
-int
-bootpass(Boot *b, void *vbuf, int nbuf)
-{
- char *buf, *ebuf;
- Exec *ep;
- ulong entry, data, text, bss;
-
- if(b->state == FAILED)
- return FAIL;
-
- if(nbuf == 0)
- goto Endofinput;
-
- buf = vbuf;
- ebuf = buf+nbuf;
- while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
- switch(b->state) {
- case INITKERNEL:
- b->state = READEXEC;
- b->bp = (char*)&b->exec;
- b->wp = b->bp;
- b->ep = b->bp+sizeof(Exec);
- break;
- case READEXEC:
- ep = &b->exec;
- if(GLLONG(ep->magic) == I_MAGIC) {
- b->state = READ9TEXT;
- b->bp = (char*)PADDR(GLLONG(ep->entry));
- b->wp = b->bp;
- b->ep = b->wp+GLLONG(ep->text);
- print("%lud", GLLONG(ep->text));
- break;
- }
-
- /* check for gzipped kernel */
- if(b->bp[0] == 0x1F && (uchar)b->bp[1] == 0x8B && b->bp[2] == 0x08) {
- b->state = READGZIP;
- b->bp = (char*)malloc(1440*1024);
- b->wp = b->bp;
- b->ep = b->wp + 1440*1024;
- memmove(b->bp, &b->exec, sizeof(Exec));
- b->wp += sizeof(Exec);
- print("gz...");
- break;
- }
-
- /*
- * Check for ELF.
- */
- if(memcmp(b->bp, elfident, 4) == 0){
- b->state = READEHDR;
- b->bp = (char*)&ehdr;
- b->wp = b->bp;
- b->ep = b->wp + sizeof(Ehdr);
- memmove(b->bp, &b->exec, sizeof(Exec));
- b->wp += sizeof(Exec);
- print("elf...");
- break;
- }
-
- print("bad kernel format\n");
- b->state = FAILED;
- return FAIL;
-
- case READ9TEXT:
- ep = &b->exec;
- b->state = READ9DATA;
- b->bp = (char*)PGROUND(PADDR(GLLONG(ep->entry))+GLLONG(ep->text));
- b->wp = b->bp;
- b->ep = b->wp + GLLONG(ep->data);
- print("+%ld", GLLONG(ep->data));
- break;
-
- case READ9DATA:
- ep = &b->exec;
- bss = GLLONG(ep->bss);
- print("+%ld=%ld\n",
- bss, GLLONG(ep->text)+GLLONG(ep->data)+bss);
- b->state = TRYBOOT;
- return ENOUGH;
-
- case READEHDR:
- if(!readehdr(b)){
- print("readehdr failed\n");
- b->state = FAILED;
- return FAIL;
- }
- break;
-
- case READPHDR:
- if(!readphdr(b)){
- b->state = FAILED;
- return FAIL;
- }
- break;
-
- case READEPAD:
- if(!readepad(b)){
- b->state = FAILED;
- return FAIL;
- }
- break;
-
- case READEDATA:
- if(!readedata(b)){
- b->state = FAILED;
- return FAIL;
- }
- if(b->state == TRYBOOT)
- return ENOUGH;
- break;
-
- case TRYBOOT:
- case READGZIP:
- return ENOUGH;
-
- case READ9LOAD:
- case INIT9LOAD:
- panic("9load");
-
- default:
- panic("bootstate");
- }
- }
- return MORE;
-
-
-Endofinput:
- /* end of input */
- switch(b->state) {
- case INITKERNEL:
- case READEXEC:
- case READ9TEXT:
- case READ9DATA:
- case READEHDR:
- case READPHDR:
- case READEPAD:
- case READEDATA:
- print("premature EOF\n");
- b->state = FAILED;
- return FAIL;
-
- case TRYBOOT:
- entry = GLLONG(b->exec.entry);
- print("entry: 0x%lux\n", entry);
- warp9(PADDR(entry));
- b->state = FAILED;
- return FAIL;
-
- case READGZIP:
- ep = &b->exec;
- if(b->bp[0] != 0x1F || (uchar)b->bp[1] != 0x8B || b->bp[2] != 0x08)
- print("lost magic\n");
-
- print("%ld => ", b->wp - b->bp);
- if(gunzip((uchar*)ep, sizeof(*ep), (uchar*)b->bp, b->wp - b->bp) < sizeof(*ep)) {
- print("badly compressed kernel\n");
- return FAIL;
- }
-
- entry = GLLONG(ep->entry);
- text = GLLONG(ep->text);
- data = GLLONG(ep->data);
- bss = GLLONG(ep->bss);
- print("%lud+%lud+%lud=%lud\n", text, data, bss, text+data+bss);
-
- if(gunzip((uchar*)PADDR(entry)-sizeof(Exec), sizeof(Exec)+text+data,
- (uchar*)b->bp, b->wp-b->bp) < sizeof(Exec)+text+data) {
- print("error uncompressing kernel\n");
- return FAIL;
- }
-
- /* relocate data to start at page boundary */
- memmove((void*)PGROUND(PADDR(entry+text)), (void*)(PADDR(entry+text)), data);
-
- print("entry: %lux\n", entry);
- warp9(PADDR(entry));
- b->state = FAILED;
- return FAIL;
-
- case INIT9LOAD:
- case READ9LOAD:
- panic("end 9load");
-
- default:
- panic("bootdone");
- }
- b->state = FAILED;
- return FAIL;
-}
--- a/os/boot/pc/bootld.c
+++ /dev/null
@@ -1,108 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-static int
-addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
-{
- int n;
-
- n = edbuf - *dbuf;
- if(n <= 0)
- return 0;
- if(n > esbuf - *sbuf)
- n = esbuf - *sbuf;
- if(n <= 0)
- return -1;
-
- memmove(*dbuf, *sbuf, n);
- *sbuf += n;
- *dbuf += n;
- return edbuf - *dbuf;
-}
-
-extern void origin(void);
-
-int
-bootpass(Boot *b, void *vbuf, int nbuf)
-{
- char *buf, *ebuf, *p, *q;
- ulong size;
-
- if(b->state == FAILED)
- return FAIL;
-
- if(nbuf == 0)
- goto Endofinput;
-
- buf = vbuf;
- ebuf = buf+nbuf;
- while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
- switch(b->state) {
- case INIT9LOAD:
- b->state = READ9LOAD;
- b->bp = (char*)0x10000;
- b->wp = b->bp;
- b->ep = b->bp + 256*1024;
- break;
-
- case READ9LOAD:
- return ENOUGH;
-
- default:
- panic("bootstate");
- }
- }
- return MORE;
-
-
-Endofinput:
- /* end of input */
- print("\n");
- switch(b->state) {
- case INIT9LOAD:
- print("premature EOF\n");
- b->state = FAILED;
- return FAIL;
-
- case READ9LOAD:
- size = b->wp - b->bp;
- if(memcmp(b->bp, origin, 16) != 0) {
- print("beginning of file does not look right\n");
- b->state = FAILED;
- return FAIL;
- }
- if(size < 32*1024 || size > 256*1024) {
- print("got %lud byte loader; not likely\n", size);
- b->state = FAILED;
- return FAIL;
- }
-
- p = b->bp;
- q = b->wp;
- if(q - p > 10000) /* don't search much past l.s */
- q = p+10000;
-
- /*
- * The string `JUMP' appears right before
- * tokzero, which is where we want to jump.
- */
- for(; p<q; p++) {
- if(strncmp(p, "JUMP", 4) == 0) {
- p += 4;
- warp9((ulong)p);
- }
- }
- print("could not find jump destination\n");
- b->state = FAILED;
- return FAIL;
-
- default:
- panic("bootdone");
- }
- b->state = FAILED;
- return FAIL;
-}
--- a/os/boot/pc/bootp.c
+++ /dev/null
@@ -1,659 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ip.h"
-
-extern int debugload;
-
-uchar broadcast[Eaddrlen] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static ushort tftpport = 5000;
-static int Id = 1;
-static Netaddr myaddr;
-static Netaddr server;
-
-typedef struct {
- uchar header[4];
- uchar data[Segsize];
-} Tftp;
-static Tftp tftpb;
-
-static void
-hnputs(uchar *ptr, ushort val)
-{
- ptr[0] = val>>8;
- ptr[1] = val;
-}
-
-static void
-hnputl(uchar *ptr, ulong val)
-{
- ptr[0] = val>>24;
- ptr[1] = val>>16;
- ptr[2] = val>>8;
- ptr[3] = val;
-}
-
-static ulong
-nhgetl(uchar *ptr)
-{
- return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
-}
-
-static ushort
-nhgets(uchar *ptr)
-{
- return ((ptr[0]<<8) | ptr[1]);
-}
-
-static short endian = 1;
-static char* aendian = (char*)&endian;
-#define LITTLE *aendian
-
-static ushort
-ptcl_csum(void *a, int len)
-{
- uchar *addr;
- ulong t1, t2;
- ulong losum, hisum, mdsum, x;
-
- addr = a;
- losum = 0;
- hisum = 0;
- mdsum = 0;
-
- x = 0;
- if((ulong)addr & 1) {
- if(len) {
- hisum += addr[0];
- len--;
- addr++;
- }
- x = 1;
- }
- while(len >= 16) {
- t1 = *(ushort*)(addr+0);
- t2 = *(ushort*)(addr+2); mdsum += t1;
- t1 = *(ushort*)(addr+4); mdsum += t2;
- t2 = *(ushort*)(addr+6); mdsum += t1;
- t1 = *(ushort*)(addr+8); mdsum += t2;
- t2 = *(ushort*)(addr+10); mdsum += t1;
- t1 = *(ushort*)(addr+12); mdsum += t2;
- t2 = *(ushort*)(addr+14); mdsum += t1;
- mdsum += t2;
- len -= 16;
- addr += 16;
- }
- while(len >= 2) {
- mdsum += *(ushort*)addr;
- len -= 2;
- addr += 2;
- }
- if(x) {
- if(len)
- losum += addr[0];
- if(LITTLE)
- losum += mdsum;
- else
- hisum += mdsum;
- } else {
- if(len)
- hisum += addr[0];
- if(LITTLE)
- hisum += mdsum;
- else
- losum += mdsum;
- }
-
- losum += hisum >> 8;
- losum += (hisum & 0xff) << 8;
- while(hisum = losum>>16)
- losum = hisum + (losum & 0xffff);
-
- return ~losum;
-}
-
-static ushort
-ip_csum(uchar *addr)
-{
- int len;
- ulong sum = 0;
-
- len = (addr[0]&0xf)<<2;
-
- while(len > 0) {
- sum += addr[0]<<8 | addr[1] ;
- len -= 2;
- addr += 2;
- }
-
- sum = (sum & 0xffff) + (sum >> 16);
- sum = (sum & 0xffff) + (sum >> 16);
- return (sum^0xffff);
-}
-
-enum {
- /* this is only true of IPv4, but we're not doing v6 yet */
- Min_udp_payload = ETHERMINTU - ETHERHDRSIZE - UDP_HDRSIZE,
-};
-
-static void
-udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
-{
- char payload[ETHERMAXTU];
- Udphdr *uh;
- Etherhdr *ip;
- Etherpkt pkt;
- int len, ptcllen;
-
- /*
- * if packet is too short, make it longer rather than relying
- * on ethernet interface or lower layers to pad it.
- */
- if (dlen < Min_udp_payload) {
- memmove(payload, data, dlen);
- data = payload;
- dlen = Min_udp_payload;
- }
-
- uh = (Udphdr*)&pkt;
-
- memset(uh, 0, sizeof(Etherpkt));
- memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
-
- /*
- * UDP portion
- */
- ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
- uh->ttl = 0;
- uh->udpproto = IP_UDPPROTO;
- uh->frag[0] = 0;
- uh->frag[1] = 0;
- hnputs(uh->udpplen, ptcllen);
- hnputl(uh->udpsrc, myaddr.ip);
- hnputs(uh->udpsport, myaddr.port);
- hnputl(uh->udpdst, a->ip);
- hnputs(uh->udpdport, a->port);
- hnputs(uh->udplen, ptcllen);
- uh->udpcksum[0] = 0;
- uh->udpcksum[1] = 0;
- dlen = (dlen+1)&~1;
- hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
-
- /*
- * IP portion
- */
- ip = (Etherhdr*)&pkt;
- len = UDP_EHSIZE+UDP_HDRSIZE+dlen; /* non-descriptive names */
- ip->vihl = IP_VER|IP_HLEN;
- ip->tos = 0;
- ip->ttl = 255;
- hnputs(ip->length, len-ETHER_HDR);
- hnputs(ip->id, Id++);
- ip->frag[0] = 0;
- ip->frag[1] = 0;
- ip->cksum[0] = 0;
- ip->cksum[1] = 0;
- hnputs(ip->cksum, ip_csum(&ip->vihl));
-
- /*
- * Ethernet MAC portion
- */
- hnputs(ip->type, ET_IP);
- memmove(ip->d, a->ea, sizeof(ip->d));
-
-if(debug) {
- print("udpsend ");
-}
- ethertxpkt(ctlrno, &pkt, len, Timeout);
-}
-
-static void
-nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
-{
- int n;
- char buf[128];
-
- buf[0] = 0;
- buf[1] = Tftp_ERROR;
- buf[2] = 0;
- buf[3] = code;
- strcpy(buf+4, msg);
- n = strlen(msg) + 4 + 1;
- udpsend(ctlrno, a, buf, n);
- if(report)
- print("\ntftp: error(%d): %s\n", code, msg);
-}
-
-static int
-udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
-{
- int n, len;
- ushort csm;
- Udphdr *h;
- ulong addr, timo;
- Etherpkt pkt;
- static int rxactive;
-
- if(rxactive == 0)
- timo = 1000;
- else
- timo = Timeout;
- timo += TK2MS(m->ticks);
- while(timo > TK2MS(m->ticks)){
- n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
- if(n <= 0)
- continue;
-
- h = (Udphdr*)&pkt;
- if(debug)
- print("udprecv %E to %E...\n", h->s, h->d);
-
- if(nhgets(h->type) != ET_IP) {
- if(debug)
- print("not ip...");
- continue;
- }
-
- if(ip_csum(&h->vihl)) {
- print("ip chksum error\n");
- continue;
- }
- if(h->vihl != (IP_VER|IP_HLEN)) {
- print("ip bad vers/hlen\n");
- continue;
- }
-
- if(h->udpproto != IP_UDPPROTO) {
- if(debug)
- print("not udp (%d)...", h->udpproto);
- continue;
- }
-
- if(debug)
- print("okay udp...");
-
- h->ttl = 0;
- len = nhgets(h->udplen);
- hnputs(h->udpplen, len);
-
- if(nhgets(h->udpcksum)) {
- csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
- if(csm != 0) {
- print("udp chksum error csum #%4ux len %d\n",
- csm, n);
- break;
- }
- }
-
- if(a->port != 0 && nhgets(h->udpsport) != a->port) {
- if(debug)
- print("udpport %ux not %ux\n",
- nhgets(h->udpsport), a->port);
- continue;
- }
-
- addr = nhgetl(h->udpsrc);
- if(a->ip != Bcastip && a->ip != addr) {
- if(debug)
- print("bad ip %lux not %lux\n", addr, a->ip);
- continue;
- }
-
- len -= UDP_HDRSIZE-UDP_PHDRSIZE;
- if(len > dlen) {
- print("udp: packet too big: %d > %d; from addr %E\n",
- len, dlen, h->udpsrc);
- continue;
- }
-
- memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
- a->ip = addr;
- a->port = nhgets(h->udpsport);
- memmove(a->ea, pkt.s, sizeof(a->ea));
-
- rxactive = 1;
- return len;
- }
-
- return 0;
-}
-
-static int tftpblockno;
-
-/*
- * format of a request packet, from the RFC:
- *
- 2 bytes string 1 byte string 1 byte
- ------------------------------------------------
- | Opcode | Filename | 0 | Mode | 0 |
- ------------------------------------------------
- */
-static int
-tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
-{
- int i, len, rlen, oport;
- char buf[Segsize+2];
-
- buf[0] = 0;
- buf[1] = Tftp_READ;
- len = 2 + sprint(buf+2, "%s", name) + 1;
- len += sprint(buf+len, "octet") + 1;
-
- oport = a->port;
- for(i = 0; i < 5; i++){
- a->port = oport;
- udpsend(ctlrno, a, buf, len);
- a->port = 0;
- if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
- continue;
-
- switch((tftp->header[0]<<8)|tftp->header[1]){
-
- case Tftp_ERROR:
- print("tftpopen: error (%d): %s\n",
- (tftp->header[2]<<8)|tftp->header[3], (char*)tftp->data);
- return -1;
-
- case Tftp_DATA:
- tftpblockno = 1;
- len = (tftp->header[2]<<8)|tftp->header[3];
- if(len != tftpblockno){
- print("tftpopen: block error: %d\n", len);
- nak(ctlrno, a, 1, "block error", 0);
- return -1;
- }
- rlen -= sizeof(tftp->header);
- if(rlen < Segsize){
- /* ACK now, in case we don't later */
- buf[0] = 0;
- buf[1] = Tftp_ACK;
- buf[2] = tftpblockno>>8;
- buf[3] = tftpblockno;
- udpsend(ctlrno, a, buf, sizeof(tftp->header));
- }
- return rlen;
- }
- }
-
- print("tftpopen: failed to connect to server\n");
- return -1;
-}
-
-static int
-tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
-{
- uchar buf[4];
- int try, blockno, len;
-
- dlen += sizeof(tftp->header);
-
- for(try = 0; try < 10; try++) {
- buf[0] = 0;
- buf[1] = Tftp_ACK;
- buf[2] = tftpblockno>>8;
- buf[3] = tftpblockno;
-
- udpsend(ctlrno, a, buf, sizeof(buf));
- len = udprecv(ctlrno, a, tftp, dlen);
- if(len <= sizeof(tftp->header)){
- if(debug)
- print("tftpread: too short %d <= %d\n",
- len, sizeof(tftp->header));
- continue;
- }
- blockno = (tftp->header[2]<<8)|tftp->header[3];
- if(blockno <= tftpblockno){
- if(debug)
- print("tftpread: blkno %d <= %d\n",
- blockno, tftpblockno);
- continue;
- }
-
- if(blockno == tftpblockno+1) {
- tftpblockno++;
- if(len < dlen) { /* last packet; send final ack */
- tftpblockno++;
- buf[0] = 0;
- buf[1] = Tftp_ACK;
- buf[2] = tftpblockno>>8;
- buf[3] = tftpblockno;
- udpsend(ctlrno, a, buf, sizeof(buf));
- }
- return len-sizeof(tftp->header);
- }
- print("tftpread: block error: %d, expected %d\n",
- blockno, tftpblockno+1);
- }
-
- return -1;
-}
-
-static int
-bootpopen(int ctlrno, char *file, Bootp *rep, int dotftpopen)
-{
- Bootp req;
- int i, n;
- uchar *ea;
- char name[128], *filename, *sysname;
-
- if (debugload)
- print("bootpopen: ether%d!%s...", ctlrno, file);
- if((ea = etheraddr(ctlrno)) == 0){
- print("invalid ctlrno %d\n", ctlrno);
- return -1;
- }
-
- filename = 0;
- sysname = 0;
- if(file && *file){
- strcpy(name, file);
- if(filename = strchr(name, '!')){
- sysname = name;
- *filename++ = 0;
- }
- else
- filename = name;
- }
-
- memset(&req, 0, sizeof(req));
- req.op = Bootrequest;
- req.htype = 1; /* ethernet */
- req.hlen = Eaddrlen; /* ethernet */
- memmove(req.chaddr, ea, Eaddrlen);
- if(filename != nil)
- strncpy(req.file, filename, sizeof(req.file));
- if(sysname != nil)
- strncpy(req.sname, sysname, sizeof(req.sname));
-
- myaddr.ip = 0;
- myaddr.port = BPportsrc;
- memmove(myaddr.ea, ea, Eaddrlen);
-
- etherrxflush(ctlrno);
- for(i = 0; i < 10; i++) {
- server.ip = Bcastip;
- server.port = BPportdst;
- memmove(server.ea, broadcast, sizeof(server.ea));
- udpsend(ctlrno, &server, &req, sizeof(req));
- if(udprecv(ctlrno, &server, rep, sizeof(*rep)) <= 0)
- continue;
- if(memcmp(req.chaddr, rep->chaddr, Eaddrlen))
- continue;
- if(rep->htype != 1 || rep->hlen != Eaddrlen)
- continue;
- if(sysname == 0 || strcmp(sysname, rep->sname) == 0)
- break;
- }
- if(i >= 10) {
- print("bootp timed out\n");
- return -1;
- }
-
- if(!dotftpopen)
- return 0;
-
- if(filename == 0 || *filename == 0){
- if(strcmp(rep->file, "/386/9pxeload") == 0)
- return -1;
- filename = rep->file;
- }
-
- if(rep->sname[0] != '\0')
- print("%s ", rep->sname);
- print("(%d.%d.%d.%d!%d): %s\n",
- rep->siaddr[0],
- rep->siaddr[1],
- rep->siaddr[2],
- rep->siaddr[3],
- server.port,
- filename);
-
- myaddr.ip = nhgetl(rep->yiaddr);
- myaddr.port = tftpport++;
- server.ip = nhgetl(rep->siaddr);
- server.port = TFTPport;
-
- if((n = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
- return -1;
-
- return n;
-}
-
-int
-bootpboot(int ctlrno, char *file, Boot *b)
-{
- int n;
- Bootp rep;
-
- if((n = bootpopen(ctlrno, file, &rep, 1)) < 0)
- return -1;
-
- while(bootpass(b, tftpb.data, n) == MORE){
- n = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data));
- if(n < sizeof(tftpb.data))
- break;
- }
-
- if(0 < n && n < sizeof(tftpb.data)) /* got to end of file */
- bootpass(b, tftpb.data, n);
- else
- nak(ctlrno, &server, 3, "ok", 0); /* tftpclose to abort transfer */
- bootpass(b, nil, 0); /* boot if possible */
- return -1;
-}
-
-#include "fs.h"
-
-#define INIPATHLEN 64
-
-static struct {
- Fs fs;
- char ini[INIPATHLEN];
-} pxether[MaxEther];
-
-static vlong
-pxediskseek(Fs*, vlong)
-{
- return -1LL;
-}
-
-static long
-pxediskread(Fs*, void*, long)
-{
- return -1;
-}
-
-static long
-pxeread(File* f, void* va, long len)
-{
- int n;
- Bootp rep;
- char *p, *v;
-
- if((n = bootpopen(f->fs->dev, pxether[f->fs->dev].ini, &rep, 1)) < 0)
- return -1;
-
- p = v = va;
- while(n > 0) {
- if((p-v)+n > len)
- n = len - (p-v);
- memmove(p, tftpb.data, n);
- p += n;
- if(n != Segsize)
- break;
- if((n = tftpread(f->fs->dev, &server, &tftpb, sizeof(tftpb.data))) < 0)
- return -1;
- }
- return p-v;
-}
-
-static int
-pxewalk(File* f, char* name)
-{
- Bootp rep;
- char *ini;
-
- switch(f->walked){
- default:
- return -1;
- case 0:
- if(strcmp(name, "cfg") == 0){
- f->walked = 1;
- return 1;
- }
- break;
- case 1:
- if(strcmp(name, "pxe") == 0){
- f->walked = 2;
- return 1;
- }
- break;
- case 2:
- if(strcmp(name, "%E") != 0)
- break;
- f->walked = 3;
-
- if(bootpopen(f->fs->dev, nil, &rep, 0) < 0)
- return 0;
-
- ini = pxether[f->fs->dev].ini;
- /* use our mac address instead of relying on a bootp answer */
- snprint(ini, INIPATHLEN, "/cfg/pxe/%E", (uchar *)myaddr.ea);
- f->path = ini;
-
- return 1;
- }
- return 0;
-}
-
-void*
-pxegetfspart(int ctlrno, char* part, int)
-{
- if(!pxe)
- return nil;
- if(strcmp(part, "*") != 0)
- return nil;
- if(ctlrno >= MaxEther)
- return nil;
- if(iniread && getconf("*pxeini") != nil)
- return nil;
-
- pxether[ctlrno].fs.dev = ctlrno;
- pxether[ctlrno].fs.diskread = pxediskread;
- pxether[ctlrno].fs.diskseek = pxediskseek;
-
- pxether[ctlrno].fs.read = pxeread;
- pxether[ctlrno].fs.walk = pxewalk;
-
- pxether[ctlrno].fs.root.fs = &pxether[ctlrno].fs;
- pxether[ctlrno].fs.root.walked = 0;
-
- return &pxether[ctlrno].fs;
-}
--- a/os/boot/pc/cga.c
+++ /dev/null
@@ -1,91 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-enum {
- Width = 160,
- Height = 25,
-
- Attr = 7, /* white on black */
-};
-
-#define CGASCREENBASE ((uchar*)KADDR(0xB8000))
-
-static int pos;
-static int screeninitdone;
-
-static uchar
-cgaregr(int index)
-{
- outb(0x3D4, index);
- return inb(0x3D4+1) & 0xFF;
-}
-
-static void
-cgaregw(int index, int data)
-{
- outb(0x3D4, index);
- outb(0x3D4+1, data);
-}
-
-static void
-movecursor(void)
-{
- cgaregw(0x0E, (pos/2>>8) & 0xFF);
- cgaregw(0x0F, pos/2 & 0xFF);
- CGASCREENBASE[pos+1] = Attr;
-}
-
-static void
-cgascreenputc(int c)
-{
- int i;
-
- if(c == '\n'){
- pos = pos/Width;
- pos = (pos+1)*Width;
- }
- else if(c == '\t'){
- i = 8 - ((pos/2)&7);
- while(i-->0)
- cgascreenputc(' ');
- }
- else if(c == '\b'){
- if(pos >= 2)
- pos -= 2;
- cgascreenputc(' ');
- pos -= 2;
- }
- else{
- CGASCREENBASE[pos++] = c;
- CGASCREENBASE[pos++] = Attr;
- }
- if(pos >= Width*Height){
- memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
- memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
- pos = Width*(Height-1);
- }
- movecursor();
-}
-
-static void
-screeninit(void)
-{
- if(screeninitdone == 0){
- pos = cgaregr(0x0E)<<8;
- pos |= cgaregr(0x0F);
- pos *= 2;
- screeninitdone = 1;
- }
-}
-
-void
-cgascreenputs(char* s, int n)
-{
- if(screeninitdone == 0)
- screeninit();
- while(n-- > 0)
- cgascreenputc(*s++);
-}
--- a/os/boot/pc/cis.c
+++ /dev/null
@@ -1,539 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "error.h"
-#include "io.h"
-
-enum{
- Linktarget = 0x13,
-};
-
-/*
- * read and crack the card information structure enough to set
- * important parameters like power
- */
-/* cis memory walking */
-typedef struct Cisdat {
- uchar *cisbase;
- int cispos;
- int cisskip;
- int cislen;
-} Cisdat;
-
-static void tcfig(PCMslot*, Cisdat*, int);
-static void tentry(PCMslot*, Cisdat*, int);
-static void tvers1(PCMslot*, Cisdat*, int);
-static void tlonglnkmfc(PCMslot*, Cisdat*, int);
-
-static int
-readc(Cisdat *cis, uchar *x)
-{
- if(cis->cispos >= cis->cislen)
- return 0;
- *x = cis->cisbase[cis->cisskip*cis->cispos];
- cis->cispos++;
- return 1;
-}
-
-static int
-xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
-{
- PCMmap *m;
- Cisdat cis;
- int i, l;
- uchar *p;
- uchar type, link, n, c;
- int this, subtype;
-
- m = pcmmap(slotno, 0, 0, attr);
- if(m == 0)
- return -1;
-
- cis.cisbase = KADDR(m->isa);
- cis.cispos = 0;
- cis.cisskip = attr ? 2 : 1;
- cis.cislen = m->len;
-
- /* loop through all the tuples */
- for(i = 0; i < 1000; i++){
- this = cis.cispos;
- if(readc(&cis, &type) != 1)
- break;
- if(type == 0xFF)
- break;
- if(readc(&cis, &link) != 1)
- break;
- if(link == 0xFF)
- break;
-
- n = link;
- if(link > 1 && subtuple != -1){
- if(readc(&cis, &c) != 1)
- break;
- subtype = c;
- n--;
- }else
- subtype = -1;
-
- if(type == tuple && subtype == subtuple){
- p = v;
- for(l=0; l<nv && l<n; l++)
- if(readc(&cis, p++) != 1)
- break;
- pcmunmap(slotno, m);
- return nv;
- }
- cis.cispos = this + (2+link);
- }
- pcmunmap(slotno, m);
- return -1;
-}
-
-int
-pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
-{
- int n;
-
- /* try attribute space, then memory */
- if((n = xcistuple(slotno, tuple, subtuple, v, nv, 1)) >= 0)
- return n;
- return xcistuple(slotno, tuple, subtuple, v, nv, 0);
-}
-
-void
-pcmcisread(PCMslot *pp)
-{
- int this;
- Cisdat cis;
- PCMmap *m;
- uchar type, link;
-
- memset(pp->ctab, 0, sizeof(pp->ctab));
- pp->ncfg = 0;
- memset(pp->cfg, 0, sizeof(pp->cfg));
- pp->configed = 0;
- pp->nctab = 0;
- pp->verstr[0] = 0;
-
- /*
- * Read all tuples in attribute space.
- */
- m = pcmmap(pp->slotno, 0, 0, 1);
- if(m == 0)
- return;
-
- cis.cisbase = KADDR(m->isa);
- cis.cispos = 0;
- cis.cisskip = 2;
- cis.cislen = m->len;
-
- /* loop through all the tuples */
- for(;;){
- this = cis.cispos;
- if(readc(&cis, &type) != 1)
- break;
- if(type == 0xFF)
- break;
- if(readc(&cis, &link) != 1)
- break;
-
- switch(type){
- default:
- break;
- case 6:
- tlonglnkmfc(pp, &cis, type);
- break;
- case 0x15:
- tvers1(pp, &cis, type);
- break;
- case 0x1A:
- tcfig(pp, &cis, type);
- break;
- case 0x1B:
- tentry(pp, &cis, type);
- break;
- }
-
- if(link == 0xFF)
- break;
- cis.cispos = this + (2+link);
- }
- pcmunmap(pp->slotno, m);
-}
-
-static ulong
-getlong(Cisdat *cis, int size)
-{
- uchar c;
- int i;
- ulong x;
-
- x = 0;
- for(i = 0; i < size; i++){
- if(readc(cis, &c) != 1)
- break;
- x |= c<<(i*8);
- }
- return x;
-}
-
-static void
-tcfig(PCMslot *pp, Cisdat *cis, int )
-{
- uchar size, rasize, rmsize;
- uchar last;
-
- if(readc(cis, &size) != 1)
- return;
- rasize = (size&0x3) + 1;
- rmsize = ((size>>2)&0xf) + 1;
- if(readc(cis, &last) != 1)
- return;
-
- if(pp->ncfg >= 8){
- print("tcfig: too many configuration registers\n");
- return;
- }
-
- pp->cfg[pp->ncfg].caddr = getlong(cis, rasize);
- pp->cfg[pp->ncfg].cpresent = getlong(cis, rmsize);
- pp->ncfg++;
-}
-
-static ulong vexp[8] =
-{
- 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
-};
-static ulong vmant[16] =
-{
- 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
-};
-
-static ulong
-microvolt(Cisdat *cis)
-{
- uchar c;
- ulong microvolts;
- ulong exp;
-
- if(readc(cis, &c) != 1)
- return 0;
- exp = vexp[c&0x7];
- microvolts = vmant[(c>>3)&0xf]*exp;
- while(c & 0x80){
- if(readc(cis, &c) != 1)
- return 0;
- switch(c){
- case 0x7d:
- break; /* high impedence when sleeping */
- case 0x7e:
- case 0x7f:
- microvolts = 0; /* no connection */
- break;
- default:
- exp /= 10;
- microvolts += exp*(c&0x7f);
- }
- }
- return microvolts;
-}
-
-static ulong
-nanoamps(Cisdat *cis)
-{
- uchar c;
- ulong nanoamps;
-
- if(readc(cis, &c) != 1)
- return 0;
- nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
- while(c & 0x80){
- if(readc(cis, &c) != 1)
- return 0;
- if(c == 0x7d || c == 0x7e || c == 0x7f)
- nanoamps = 0;
- }
- return nanoamps;
-}
-
-/*
- * only nominal voltage (feature 1) is important for config,
- * other features must read card to stay in sync.
- */
-static ulong
-power(Cisdat *cis)
-{
- uchar feature;
- ulong mv;
-
- mv = 0;
- if(readc(cis, &feature) != 1)
- return 0;
- if(feature & 1)
- mv = microvolt(cis);
- if(feature & 2)
- microvolt(cis);
- if(feature & 4)
- microvolt(cis);
- if(feature & 8)
- nanoamps(cis);
- if(feature & 0x10)
- nanoamps(cis);
- if(feature & 0x20)
- nanoamps(cis);
- if(feature & 0x40)
- nanoamps(cis);
- return mv/1000000;
-}
-
-static ulong mantissa[16] =
-{ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };
-
-static ulong exponent[8] =
-{ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };
-
-static ulong
-ttiming(Cisdat *cis, int scale)
-{
- uchar unscaled;
- ulong nanosecs;
-
- if(readc(cis, &unscaled) != 1)
- return 0;
- nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
- nanosecs = nanosecs * vexp[scale];
- return nanosecs;
-}
-
-static void
-timing(Cisdat *cis, PCMconftab *ct)
-{
- uchar c, i;
-
- if(readc(cis, &c) != 1)
- return;
- i = c&0x3;
- if(i != 3)
- ct->maxwait = ttiming(cis, i); /* max wait */
- i = (c>>2)&0x7;
- if(i != 7)
- ct->readywait = ttiming(cis, i); /* max ready/busy wait */
- i = (c>>5)&0x7;
- if(i != 7)
- ct->otherwait = ttiming(cis, i); /* reserved wait */
-}
-
-static void
-iospaces(Cisdat *cis, PCMconftab *ct)
-{
- uchar c;
- int i, nio;
-
- ct->nio = 0;
- if(readc(cis, &c) != 1)
- return;
-
- ct->bit16 = ((c>>5)&3) >= 2;
- if(!(c & 0x80)){
- ct->io[0].start = 0;
- ct->io[0].len = 1<<(c&0x1f);
- ct->nio = 1;
- return;
- }
-
- if(readc(cis, &c) != 1)
- return;
-
- /*
- * For each of the range descriptions read the
- * start address and the length (value is length-1).
- */
- nio = (c&0xf)+1;
- for(i = 0; i < nio; i++){
- ct->io[i].start = getlong(cis, (c>>4)&0x3);
- ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
- }
- ct->nio = nio;
-}
-
-static void
-irq(Cisdat *cis, PCMconftab *ct)
-{
- uchar c;
-
- if(readc(cis, &c) != 1)
- return;
- ct->irqtype = c & 0xe0;
- if(c & 0x10)
- ct->irqs = getlong(cis, 2);
- else
- ct->irqs = 1<<(c&0xf);
- ct->irqs &= 0xDEB8; /* levels available to card */
-}
-
-static void
-memspace(Cisdat *cis, int asize, int lsize, int host)
-{
- ulong haddress, address, len;
-
- len = getlong(cis, lsize)*256;
- address = getlong(cis, asize)*256;
- USED(len, address);
- if(host){
- haddress = getlong(cis, asize)*256;
- USED(haddress);
- }
-}
-
-static void
-tentry(PCMslot *pp, Cisdat *cis, int )
-{
- uchar c, i, feature;
- PCMconftab *ct;
-
- if(pp->nctab >= nelem(pp->ctab))
- return;
- if(readc(cis, &c) != 1)
- return;
- ct = &pp->ctab[pp->nctab++];
-
- /* copy from last default config */
- if(pp->def)
- *ct = *pp->def;
-
- ct->index = c & 0x3f;
-
- /* is this the new default? */
- if(c & 0x40)
- pp->def = ct;
-
- /* memory wait specified? */
- if(c & 0x80){
- if(readc(cis, &i) != 1)
- return;
- if(i&0x80)
- ct->memwait = 1;
- }
-
- if(readc(cis, &feature) != 1)
- return;
- switch(feature&0x3){
- case 1:
- ct->vpp1 = ct->vpp2 = power(cis);
- break;
- case 2:
- power(cis);
- ct->vpp1 = ct->vpp2 = power(cis);
- break;
- case 3:
- power(cis);
- ct->vpp1 = power(cis);
- ct->vpp2 = power(cis);
- break;
- default:
- break;
- }
- if(feature&0x4)
- timing(cis, ct);
- if(feature&0x8)
- iospaces(cis, ct);
- if(feature&0x10)
- irq(cis, ct);
- switch((feature>>5)&0x3){
- case 1:
- memspace(cis, 0, 2, 0);
- break;
- case 2:
- memspace(cis, 2, 2, 0);
- break;
- case 3:
- if(readc(cis, &c) != 1)
- return;
- for(i = 0; i <= (c&0x7); i++)
- memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
- break;
- }
- pp->configed++;
-}
-
-static void
-tvers1(PCMslot *pp, Cisdat *cis, int )
-{
- uchar c, major, minor, last;
- int i;
-
- if(readc(cis, &major) != 1)
- return;
- if(readc(cis, &minor) != 1)
- return;
- last = 0;
- for(i = 0; i < sizeof(pp->verstr)-1; i++){
- if(readc(cis, &c) != 1)
- return;
- if(c == 0)
- c = ';';
- if(c == '\n')
- c = ';';
- if(c == 0xff)
- break;
- if(c == ';' && last == ';')
- continue;
- pp->verstr[i] = c;
- last = c;
- }
- pp->verstr[i] = 0;
-}
-
-static void
-tlonglnkmfc(PCMslot *pp, Cisdat *cis, int)
-{
- int i, npos, opos;
- uchar nfn, space, expect, type, this, link;
-
- readc(cis, &nfn);
- for(i = 0; i < nfn; i++){
- readc(cis, &space);
- npos = getlong(cis, 4);
- opos = cis->cispos;
- cis->cispos = npos;
- expect = Linktarget;
-
- while(1){
- this = cis->cispos;
- if(readc(cis, &type) != 1)
- break;
- if(type == 0xFF)
- break;
- if(readc(cis, &link) != 1)
- break;
-
- if(expect && expect != type){
- print("tlonglnkmfc: expected %X found %X\n",
- expect, type);
- break;
- }
- expect = 0;
-
- switch(type){
- default:
- break;
- case 0x15:
- tvers1(pp, cis, type);
- break;
- case 0x1A:
- tcfig(pp, cis, type);
- break;
- case 0x1B:
- tentry(pp, cis, type);
- break;
- }
-
- if(link == 0xFF)
- break;
- cis->cispos = this + (2+link);
- }
- cis->cispos = opos;
- }
-}
--- a/os/boot/pc/clock.c
+++ /dev/null
@@ -1,309 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-
-/*
- * 8253 timer
- */
-enum
-{
- T0cntr= 0x40, /* counter ports */
- T1cntr= 0x41, /* ... */
- T2cntr= 0x42, /* ... */
- Tmode= 0x43, /* mode port */
-
- /* commands */
- Latch0= 0x00, /* latch counter 0's value */
- Load0= 0x30, /* load counter 0 with 2 bytes */
-
- /* modes */
- Square= 0x36, /* perioic square wave */
-
- Freq= 1193182, /* Real clock frequency */
-};
-
-static uvlong cpuhz = 66000000;
-static int cpumhz = 66;
-static int loopconst = 100;
-int cpuidax, cpuiddx;
-int havetsc;
-
-extern void _cycles(uvlong*); /* in l.s */
-extern void wrmsr(int, vlong);
-
-static void
-clockintr(Ureg*, void*)
-{
- m->ticks++;
- checkalarms();
-}
-
-#define STEPPING(x) ((x)&0xf)
-#define X86MODEL(x) (((x)>>4)&0xf)
-#define X86FAMILY(x) (((x)>>8)&0xf)
-
-enum
-{
- /* flags */
- CpuidFPU = 0x001, /* on-chip floating point unit */
- CpuidMCE = 0x080, /* machine check exception */
- CpuidCX8 = 0x100, /* CMPXCHG8B instruction */
-};
-
-typedef struct
-{
- int family;
- int model;
- int aalcycles;
- char *name;
-} X86type;
-
-X86type x86intel[] =
-{
- { 4, 0, 22, "486DX", }, /* known chips */
- { 4, 1, 22, "486DX50", },
- { 4, 2, 22, "486SX", },
- { 4, 3, 22, "486DX2", },
- { 4, 4, 22, "486SL", },
- { 4, 5, 22, "486SX2", },
- { 4, 7, 22, "DX2WB", }, /* P24D */
- { 4, 8, 22, "DX4", }, /* P24C */
- { 4, 9, 22, "DX4WB", }, /* P24CT */
- { 5, 0, 23, "P5", },
- { 5, 1, 23, "P5", },
- { 5, 2, 23, "P54C", },
- { 5, 3, 23, "P24T", },
- { 5, 4, 23, "P55C MMX", },
- { 5, 7, 23, "P54C VRT", },
- { 6, 1, 16, "PentiumPro", },/* trial and error */
- { 6, 3, 16, "PentiumII", },
- { 6, 5, 16, "PentiumII/Xeon", },
- { 6, 6, 16, "Celeron", },
- { 6, 7, 16, "PentiumIII/Xeon", },
- { 6, 8, 16, "PentiumIII/Xeon", },
- { 6, 0xB, 16, "PentiumIII/Xeon", },
- { 0xF, 1, 16, "P4", }, /* P4 */
- { 0xF, 2, 16, "PentiumIV/Xeon", },
-
- { 3, -1, 32, "386", }, /* family defaults */
- { 4, -1, 22, "486", },
- { 5, -1, 23, "P5", },
- { 6, -1, 16, "P6", },
- { 0xF, -1, 16, "P4", }, /* P4 */
-
- { -1, -1, 16, "unknown", }, /* total default */
-};
-
-
-/*
- * The AMD processors all implement the CPUID instruction.
- * The later ones also return the processor name via functions
- * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX
- * and DX:
- * K5 "AMD-K5(tm) Processor"
- * K6 "AMD-K6tm w/ multimedia extensions"
- * K6 3D "AMD-K6(tm) 3D processor"
- * K6 3D+ ?
- */
-static X86type x86amd[] =
-{
- { 5, 0, 23, "AMD-K5", }, /* guesswork */
- { 5, 1, 23, "AMD-K5", }, /* guesswork */
- { 5, 2, 23, "AMD-K5", }, /* guesswork */
- { 5, 3, 23, "AMD-K5", }, /* guesswork */
- { 5, 4, 23, "AMD Geode GX1", }, /* guesswork */
- { 5, 5, 23, "AMD Geode GX2", }, /* guesswork */
- { 5, 6, 11, "AMD-K6", }, /* trial and error */
- { 5, 7, 11, "AMD-K6", }, /* trial and error */
- { 5, 8, 11, "AMD-K6-2", }, /* trial and error */
- { 5, 9, 11, "AMD-K6-III", },/* trial and error */
- { 5, 0xa, 23, "AMD Geode LX", }, /* guesswork */
-
- { 6, 1, 11, "AMD-Athlon", },/* trial and error */
- { 6, 2, 11, "AMD-Athlon", },/* trial and error */
-
- { 4, -1, 22, "Am486", }, /* guesswork */
- { 5, -1, 23, "AMD-K5/K6", }, /* guesswork */
- { 6, -1, 11, "AMD-Athlon", },/* guesswork */
- { 0xF, -1, 11, "AMD64", }, /* guesswork */
-
- { -1, -1, 11, "unknown", }, /* total default */
-};
-
-static X86type *cputype;
-
-
-void
-delay(int millisecs)
-{
- millisecs *= loopconst;
- if(millisecs <= 0)
- millisecs = 1;
- aamloop(millisecs);
-}
-
-void
-microdelay(int microsecs)
-{
- microsecs *= loopconst;
- microsecs /= 1000;
- if(microsecs <= 0)
- microsecs = 1;
- aamloop(microsecs);
-}
-
-extern void cpuid(char*, int*, int*);
-
-X86type*
-cpuidentify(void)
-{
- int family, model;
- X86type *t;
- char cpuidid[16];
- int cpuidax, cpuiddx;
-
- cpuid(cpuidid, &cpuidax, &cpuiddx);
- if(strncmp(cpuidid, "AuthenticAMD", 12) == 0 ||
- strncmp(cpuidid, "Geode by NSC", 12) == 0)
- t = x86amd;
- else
- t = x86intel;
- family = X86FAMILY(cpuidax);
- model = X86MODEL(cpuidax);
- if (0)
- print("cpuidentify: cpuidax 0x%ux cpuiddx 0x%ux\n",
- cpuidax, cpuiddx);
- while(t->name){
- if((t->family == family && t->model == model)
- || (t->family == family && t->model == -1)
- || (t->family == -1))
- break;
- t++;
- }
- if(t->name == nil)
- panic("cpuidentify");
-
- if(cpuiddx & 0x10){
- havetsc = 1;
- if(cpuiddx & 0x20)
- wrmsr(0x10, 0);
- }
-
- return t;
-}
-
-void
-clockinit(void)
-{
- uvlong a, b, cpufreq;
- int loops, incr, x, y;
- X86type *t;
-
- /*
- * set vector for clock interrupts
- */
- setvec(VectorCLOCK, clockintr, 0);
-
- t = cpuidentify();
-
- /*
- * set clock for 1/HZ seconds
- */
- outb(Tmode, Load0|Square);
- outb(T0cntr, (Freq/HZ)); /* low byte */
- outb(T0cntr, (Freq/HZ)>>8); /* high byte */
-
- /*
- * Introduce a little delay to make sure the count is
- * latched and the timer is counting down; with a fast
- * enough processor this may not be the case.
- * The i8254 (which this probably is) has a read-back
- * command which can be used to make sure the counting
- * register has been written into the counting element.
- */
- x = (Freq/HZ);
- for(loops = 0; loops < 100000 && x >= (Freq/HZ); loops++){
- outb(Tmode, Latch0);
- x = inb(T0cntr);
- x |= inb(T0cntr)<<8;
- }
-
- /* find biggest loop that doesn't wrap */
- incr = 16000000/(t->aalcycles*HZ*2);
- x = 2000;
- for(loops = incr; loops < 64*1024; loops += incr) {
-
- /*
- * measure time for the loop
- *
- * MOVL loops,CX
- * aaml1: AAM
- * LOOP aaml1
- *
- * the time for the loop should be independent of external
- * cache and memory system since it fits in the execution
- * prefetch buffer.
- *
- */
- outb(Tmode, Latch0);
- if(havetsc)
- _cycles(&a);
- x = inb(T0cntr);
- x |= inb(T0cntr)<<8;
- aamloop(loops);
- outb(Tmode, Latch0);
- if(havetsc)
- _cycles(&b);
- y = inb(T0cntr);
- y |= inb(T0cntr)<<8;
- x -= y;
-
- if(x < 0)
- x += Freq/HZ;
-
- if(x > Freq/(3*HZ))
- break;
- }
-
- /*
- * figure out clock frequency and a loop multiplier for delay().
- * counter goes at twice the frequency, once per transition,
- * i.e., twice per square wave
- */
- cpufreq = (vlong)loops*((t->aalcycles*2*Freq)/x);
- loopconst = (cpufreq/1000)/t->aalcycles; /* AAM+LOOP's for 1 ms */
-
- if(havetsc){
- /* counter goes up by 2*Freq */
- b = (b-a)<<1;
- b *= Freq;
- b /= x;
-
- /*
- * round to the nearest megahz
- */
- cpumhz = (b+500000)/1000000L;
- cpuhz = b;
- }
- else{
- /*
- * add in possible .5% error and convert to MHz
- */
- cpumhz = (cpufreq + cpufreq/200)/1000000;
- cpuhz = cpufreq;
- }
-
- if(debug){
- int timeo;
-
- print("%dMHz %s loop %d\n", cpumhz, t->name, loopconst);
- print("tick...");
- for(timeo = 0; timeo < 10; timeo++)
- delay(1000);
- print("tock...\n");
- }
-}
--- a/os/boot/pc/conf.c
+++ /dev/null
@@ -1,537 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "fs.h"
-
-/*
- * Where configuration info is left for the loaded programme.
- * This will turn into a structure as more is done by the boot loader
- * (e.g. why parse the .ini file twice?).
- * There are 3584 bytes available at CONFADDR.
- *
- * The low-level boot routines in l.s leave data for us at CONFADDR,
- * which we pick up before reading the plan9.ini file.
- */
-#define BOOTLINELEN 64
-#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
-#define BOOTARGSLEN (3584-0x200-BOOTLINELEN)
-#define MAXCONF 100
-
-static char *confname[MAXCONF];
-static char *confval[MAXCONF];
-static int nconf;
-
-extern char **ini;
-
-typedef struct {
- char* name;
- int start;
- int end;
-} Mblock;
-
-typedef struct {
- char* tag;
- Mblock* mb;
-} Mitem;
-
-static Mblock mblock[MAXCONF];
-static int nmblock;
-static Mitem mitem[MAXCONF];
-static int nmitem;
-static char* mdefault;
-static char mdefaultbuf[10];
-static int mtimeout;
-
-static char*
-comma(char* line, char** residue)
-{
- char *q, *r;
-
- if((q = strchr(line, ',')) != nil){
- *q++ = 0;
- if(*q == ' ')
- q++;
- }
- *residue = q;
-
- if((r = strchr(line, ' ')) != nil)
- *r = 0;
-
- if(*line == ' ')
- line++;
- return line;
-}
-
-static Mblock*
-findblock(char* name, char** residue)
-{
- int i;
- char *p;
-
- p = comma(name, residue);
- for(i = 0; i < nmblock; i++){
- if(strcmp(p, mblock[i].name) == 0)
- return &mblock[i];
- }
- return nil;
-}
-
-static Mitem*
-finditem(char* name, char** residue)
-{
- int i;
- char *p;
-
- p = comma(name, residue);
- for(i = 0; i < nmitem; i++){
- if(strcmp(p, mitem[i].mb->name) == 0)
- return &mitem[i];
- }
- return nil;
-}
-
-static void
-parsemenu(char* str, char* scratch, int len)
-{
- Mitem *mi;
- Mblock *mb, *menu;
- char buf[20], *p, *q, *line[MAXCONF];
- int i, inblock, n, show;
-
- inblock = 0;
- menu = nil;
- memmove(scratch, str, len);
- n = getfields(scratch, line, MAXCONF, '\n');
- if(n >= MAXCONF)
- print("warning: possibly too many lines in plan9.ini\n");
- for(i = 0; i < n; i++){
- p = line[i];
- if(inblock && *p == '['){
- mblock[nmblock].end = i;
- if(strcmp(mblock[nmblock].name, "menu") == 0)
- menu = &mblock[nmblock];
- nmblock++;
- inblock = 0;
- }
- if(*p == '['){
- if(nmblock == 0 && i != 0){
- mblock[nmblock].name = "common";
- mblock[nmblock].start = 0;
- mblock[nmblock].end = i;
- nmblock++;
- }
- q = strchr(p+1, ']');
- if(q == nil || *(q+1) != 0){
- print("malformed menu block header - %s\n", p);
- return;
- }
- *q = 0;
- mblock[nmblock].name = p+1;
- mblock[nmblock].start = i+1;
- inblock = 1;
- }
- }
-
- if(inblock){
- mblock[nmblock].end = i;
- nmblock++;
- }
- if(menu == nil)
- return;
- if(nmblock < 2){
- print("incomplete menu specification\n");
- return;
- }
-
- for(i = menu->start; i < menu->end; i++){
- p = line[i];
- if(cistrncmp(p, "menuitem=", 9) == 0){
- p += 9;
- if((mb = findblock(p, &q)) == nil){
- print("no block for menuitem %s\n", p);
- return;
- }
- if(q != nil)
- mitem[nmitem].tag = q;
- else
- mitem[nmitem].tag = mb->name;
- mitem[nmitem].mb = mb;
- nmitem++;
- }
- else if(cistrncmp(p, "menudefault=", 12) == 0){
- p += 12;
- if((mi = finditem(p, &q)) == nil){
- print("no item for menudefault %s\n", p);
- return;
- }
- if(q != nil)
- mtimeout = strtol(q, 0, 0);
- sprint(mdefaultbuf, "%ld", mi-mitem+1);
- mdefault = mdefaultbuf;
- }
- else if(cistrncmp(p, "menuconsole=", 12) == 0){
- p += 12;
- p = comma(p, &q);
- consinit(p, q);
- }
- else{
- print("invalid line in [menu] block - %s\n", p);
- return;
- }
- }
-
-again:
- print("\nPlan 9 Startup Menu:\n====================\n");
- for(i = 0; i < nmitem; i++)
- print(" %d. %s\n", i+1, mitem[i].tag);
- for(;;){
- getstr("Selection", buf, sizeof(buf), mdefault, mtimeout);
- mtimeout = 0;
- i = strtol(buf, &p, 0)-1;
- if(i < 0 || i >= nmitem)
- goto again;
- switch(*p){
- case 'p':
- case 'P':
- show = 1;
- print("\n");
- break;
- case 0:
- show = 0;
- break;
- default:
- continue;
-
- }
- mi = &mitem[i];
-
- p = str;
- p += sprint(p, "menuitem=%s\n", mi->mb->name);
- for(i = 0; i < nmblock; i++){
- mb = &mblock[i];
- if(mi->mb != mb && cistrcmp(mb->name, "common") != 0)
- continue;
- for(n = mb->start; n < mb->end; n++)
- p += sprint(p, "%s\n", line[n]);
- }
-
- if(show){
- for(q = str; q < p; q += i){
- if((i = print(q)) <= 0)
- break;
- }
- goto again;
- }
- break;
- }
- print("\n");
-}
-
-/*
-static void
-msleep(int msec)
-{
- ulong start;
-
- for(start = m->ticks; TK2MS(m->ticks - start) < msec; )
- ;
-}
-*/
-
-void
-readlsconf(void)
-{
- uchar *p;
-
- p = (uchar*)CONFADDR;
- for(;;) {
- if(strcmp((char*)p, "APM") == 0){
- apm.haveinfo = 1;
- apm.ax = *(ushort*)(p+4);
- apm.cx = *(ushort*)(p+6);
- apm.dx = *(ushort*)(p+8);
- apm.di = *(ushort*)(p+10);
- apm.ebx = *(ulong*)(p+12);
- apm.esi = *(ulong*)(p+16);
- print("apm ax=%x cx=%x dx=%x di=%x ebx=%x esi=%x\n",
- apm.ax, apm.cx, apm.dx, apm.di, apm.ebx, apm.esi);
- p += 20;
- continue;
- }
- break;
- }
-}
-
-char*
-getconf(char *name)
-{
- int i, n, nmatch;
- char buf[20];
-
- nmatch = 0;
- for(i = 0; i < nconf; i++)
- if(cistrcmp(confname[i], name) == 0)
- nmatch++;
-
- switch(nmatch) {
- default:
- print("\n");
- nmatch = 0;
- for(i = 0; i < nconf; i++)
- if(cistrcmp(confname[i], name) == 0)
- print("%d. %s\n", ++nmatch, confval[i]);
- print("%d. none of the above\n", ++nmatch);
- do {
- getstr(name, buf, sizeof(buf), nil, 0);
- n = atoi(buf);
- } while(n < 1 || n > nmatch);
-
- for(i = 0; i < nconf; i++)
- if(cistrcmp(confname[i], name) == 0)
- if(--n == 0)
- return confval[i];
- break;
-
- case 1:
- for(i = 0; i < nconf; i++)
- if(cistrcmp(confname[i], name) == 0)
- return confval[i];
- break;
-
- case 0:
- break;
- }
- return nil;
-}
-
-void
-addconf(char *fmt, ...)
-{
- va_list arg;
-
- va_start(arg, fmt);
- vseprint(BOOTARGS+strlen(BOOTARGS), BOOTARGS+BOOTARGSLEN, fmt, arg);
- va_end(arg);
-}
-
-void
-changeconf(char *fmt, ...)
-{
- va_list arg;
- char *p, *q, pref[20], buf[128];
-
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof buf, fmt, arg);
- va_end(arg);
- strncpy(pref+1, buf, 19);
- pref[19] = '\0';
- if(p = strchr(pref, '='))
- *(p+1) = '\0';
- else
- print("warning: did not change %s in plan9.ini\n", buf);
-
- /* find old line by looking for \nwhat= */
- pref[0] = '\n';
- if(strncmp(BOOTARGS, pref+1, strlen(pref+1)) == 0)
- p = BOOTARGS;
- else if(p = strstr(BOOTARGS, pref))
- p++;
- else
- p = nil;
-
- /* move rest of args up, deleting what= line. */
- if(p != nil && (q = strchr(p, '\n')) != nil)
- memmove(p, q+1, strlen(q+1)+1);
-
- /* add replacement to end */
- addconf("%s", buf);
-}
-
-/*
- * read configuration file
- */
-static char inibuf[BOOTARGSLEN];
-static char id[8] = "ZORT 0\r\n";
-
-int
-dotini(Fs *fs)
-{
- File rc;
- int blankline, i, incomment, inspace, n;
- char *cp, *p, *q, *line[MAXCONF];
-
- if(fswalk(fs, *ini, &rc) <= 0)
- return -1;
-
- cp = inibuf;
- *cp = 0;
- n = fsread(&rc, cp, BOOTARGSLEN-1);
- if(n <= 0)
- return -1;
-
- cp[n] = 0;
-
- /*
- * Strip out '\r', change '\t' -> ' '.
- * Change runs of spaces into single spaces.
- * Strip out trailing spaces, blank lines.
- *
- * We do this before we make the copy so that if we
- * need to change the copy, it is already fairly clean.
- * The main need is in the case when plan9.ini has been
- * padded with lots of trailing spaces, as is the case
- * for those created during a distribution install.
- */
- p = cp;
- blankline = 1;
- incomment = inspace = 0;
- for(q = cp; *q; q++){
- if(*q == '\r')
- continue;
- if(*q == '\t')
- *q = ' ';
- if(*q == ' '){
- inspace = 1;
- continue;
- }
- if(*q == '\n'){
- if(!blankline){
- if(!incomment)
- *p++ = '\n';
- blankline = 1;
- }
- incomment = inspace = 0;
- continue;
- }
- if(inspace){
- if(!blankline && !incomment)
- *p++ = ' ';
- inspace = 0;
- }
- if(blankline && *q == '#')
- incomment = 1;
- blankline = 0;
- if(!incomment)
- *p++ = *q;
- }
- if(p > cp && p[-1] != '\n')
- *p++ = '\n';
- *p++ = 0;
- n = p-cp;
-
- parsemenu(cp, BOOTARGS, n);
-
- /*
- * Keep a copy.
- * We could change this to pass the parsed strings
- * to the booted programme instead of the raw
- * string, then it only gets done once.
- */
- if(strncmp(cp, id, sizeof(id))){
- memmove(BOOTARGS, id, sizeof(id));
- if(n+1+sizeof(id) >= BOOTARGSLEN)
- n -= sizeof(id);
- memmove(BOOTARGS+sizeof(id), cp, n+1);
- }
- else
- memmove(BOOTARGS, cp, n+1);
-
- n = getfields(cp, line, MAXCONF, '\n');
- for(i = 0; i < n; i++){
- cp = strchr(line[i], '=');
- if(cp == 0)
- continue;
- *cp++ = 0;
- if(cp - line[i] >= NAMELEN+1)
- *(line[i]+NAMELEN-1) = 0;
- confname[nconf] = line[i];
- confval[nconf] = cp;
- nconf++;
- }
- return 0;
-}
-
-static int
-parseether(uchar *to, char *from)
-{
- char nip[4];
- char *p;
- int i;
-
- p = from;
- while(*p == ' ')
- ++p;
- for(i = 0; i < 6; i++){
- if(*p == 0)
- return -1;
- nip[0] = *p++;
- if(*p == 0)
- return -1;
- nip[1] = *p++;
- nip[2] = 0;
- to[i] = strtoul(nip, 0, 16);
- if(*p == ':')
- p++;
- }
- return 0;
-}
-
-int
-isaconfig(char *class, int ctlrno, ISAConf *isa)
-{
- char cc[NAMELEN], *p, *q, *r;
- int n;
-
- sprint(cc, "%s%d", class, ctlrno);
- for(n = 0; n < nconf; n++){
- if(cistrncmp(confname[n], cc, NAMELEN))
- continue;
- isa->nopt = 0;
- p = confval[n];
- while(*p){
- while(*p == ' ' || *p == '\t')
- p++;
- if(*p == '\0')
- break;
- if(cistrncmp(p, "type=", 5) == 0){
- p += 5;
- for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
- if(*p == '\0' || *p == ' ' || *p == '\t')
- break;
- *q = *p++;
- }
- *q = '\0';
- }
- else if(cistrncmp(p, "port=", 5) == 0)
- isa->port = strtoul(p+5, &p, 0);
- else if(cistrncmp(p, "irq=", 4) == 0)
- isa->irq = strtoul(p+4, &p, 0);
- else if(cistrncmp(p, "mem=", 4) == 0)
- isa->mem = strtoul(p+4, &p, 0);
- else if(cistrncmp(p, "size=", 5) == 0)
- isa->size = strtoul(p+5, &p, 0);
- else if(cistrncmp(p, "ea=", 3) == 0){
- if(parseether(isa->ea, p+3) == -1)
- memset(isa->ea, 0, 6);
- }
- else if(isa->nopt < NISAOPT){
- r = isa->opt[isa->nopt];
- while(*p && *p != ' ' && *p != '\t'){
- *r++ = *p++;
- if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
- break;
- }
- *r = '\0';
- isa->nopt++;
- }
- while(*p && *p != ' ' && *p != '\t')
- p++;
- }
- return 1;
- }
- return 0;
-}
--- a/os/boot/pc/console.c
+++ /dev/null
@@ -1,236 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-IOQ consiq;
-IOQ consoq;
-
-static int useuart;
-
-int debug = 0;
-
-void
-kbdchar(int c)
-{
- c &= 0x7F;
- if(c == 0x10)
- warp86("\n^P\n", 0);
- if(c == 0x12)
- debug = !debug;
- consiq.putc(&consiq, c);
-}
-
-static int
-consputc(void)
-{
- return consoq.getc(&consoq);
-}
-
-void
-kbdinit(void)
-{
- i8042init();
- qinit(&consiq);
-}
-
-void
-consinit(char* name, char* speed)
-{
- int baud, port;
-
- if(name == nil || cistrcmp(name, "cga") == 0)
- return;
- port = strtoul(name, 0, 0);
- if(port < 0 || port > 1)
- return;
- if(speed == nil || (baud = strtoul(speed, 0, 0)) == 0)
- baud = 9600;
-
- qinit(&consoq);
-
- uartspecial(port, kbdchar, consputc, baud);
- useuart = 1;
- uartputs(&consoq, "\n", 1);
-}
-
-void
-consdrain(void)
-{
- if(useuart)
- uartdrain();
-}
-
-void
-consputs(char* s, int n)
-{
- cgascreenputs(s, n);
- if(useuart)
- uartputs(&consoq, s, n);
-}
-
-void
-warp86(char* s, ulong)
-{
- if(s != nil)
- print(s);
- spllo();
- consdrain();
-
- i8042reset();
- print("Takes a licking and keeps on ticking...\n");
- for(;;)
- idle();
-}
-
-static int
-getline(char *buf, int size, int timeout)
-{
- int c, i=0;
- ulong start;
- char echo;
-
- for (;;) {
- start = m->ticks;
- do{
- /* timeout seconds to first char */
- if(timeout && ((m->ticks - start) > timeout*HZ))
- return -2;
- c = consiq.getc(&consiq);
- }while(c == -1);
- timeout = 0;
-
- if(c == '\r')
- c = '\n'; /* turn carriage return into newline */
- if(c == '\177')
- c = '\010'; /* turn delete into backspace */
- if(c == '\025')
- echo = '\n'; /* echo ^U as a newline */
- else
- echo = c;
- consputs(&echo, 1);
-
- if(c == '\010'){
- if(i > 0)
- i--; /* bs deletes last character */
- continue;
- }
- /* a newline ends a line */
- if (c == '\n')
- break;
- /* ^U wipes out the line */
- if (c =='\025')
- return -1;
- if(i == size)
- return size;
- buf[i++] = c;
- }
- buf[i] = 0;
- return i;
-}
-
-int
-getstr(char *prompt, char *buf, int size, char *def, int timeout)
-{
- int len, isdefault;
- char pbuf[PRINTSIZE];
-
- buf[0] = 0;
- isdefault = (def && *def);
- if(isdefault == 0){
- timeout = 0;
- sprint(pbuf, "%s: ", prompt);
- }
- else if(timeout)
- sprint(pbuf, "%s[default==%s (%ds timeout)]: ", prompt, def, timeout);
- else
- sprint(pbuf, "%s[default==%s]: ", prompt, def);
- for (;;) {
- print(pbuf);
- len = getline(buf, size, timeout);
- switch(len){
- case 0:
- /* RETURN */
- if(isdefault)
- break;
- continue;
- case -1:
- /* ^U typed */
- continue;
- case -2:
- /* timeout, use default */
- consputs("\n", 1);
- len = 0;
- break;
- default:
- break;
- }
- if(len >= size){
- print("line too long\n");
- continue;
- }
- break;
- }
- if(len == 0 && isdefault)
- strcpy(buf, def);
- return 0;
-}
-
-int
-print(char *fmt, ...)
-{
- int n;
- va_list arg;
- char buf[PRINTSIZE];
-
- va_start(arg, fmt);
- n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
- va_end(arg);
- consputs(buf, n);
-
- return n;
-}
-
-int
-sprint(char *s, char *fmt, ...)
-{
- int n;
- va_list arg;
-
- va_start(arg, fmt);
- n = vseprint(s, s+PRINTSIZE, fmt, arg) - s;
- va_end(arg);
-
- return n;
-}
-
-void
-panic(char *fmt, ...)
-{
- int n;
- va_list arg;
- char buf[PRINTSIZE];
-
- strcpy(buf, "panic: ");
- va_start(arg, fmt);
- n = vseprint(buf+7, buf+sizeof(buf), fmt, arg) - buf;
- va_end(arg);
- buf[n] = '\n';
- consputs(buf, n+1);
-
-//floppymemwrite();
-//splhi(); for(;;);
- if(etherdetach)
- etherdetach();
- if(sddetach)
- sddetach();
-
- consputs("\nPress almost any key to reset...", 32);
- spllo();
- while(consiq.getc(&consiq) == -1)
- ;
-
- warp86(nil, 0);
-}
--- a/os/boot/pc/dat.h
+++ /dev/null
@@ -1,215 +1,0 @@
-typedef struct List {
- void *next;
-} List;
-
-typedef struct Alarm Alarm;
-typedef struct Alarm {
- List;
- int busy;
- long dt;
- void (*f)(Alarm*);
- void *arg;
-} Alarm;
-
-typedef struct Apminfo {
- int haveinfo;
- int ax;
- int cx;
- int dx;
- int di;
- int ebx;
- int esi;
-} Apminfo;
-
-typedef struct Block Block;
-struct Block {
- Block* next;
- uchar* rp; /* first unconsumed byte */
- uchar* wp; /* first empty byte */
- uchar* lim; /* 1 past the end of the buffer */
- uchar* base; /* start of the buffer */
- ulong flag;
-};
-#define BLEN(s) ((s)->wp - (s)->rp)
-
-typedef struct IOQ IOQ;
-typedef struct IOQ {
- uchar buf[4096];
- uchar *in;
- uchar *out;
- int state;
- int (*getc)(IOQ*);
- int (*putc)(IOQ*, int);
- void *ptr;
-};
-
-enum {
- Eaddrlen = 6,
- /* next two exclude 4-byte ether CRC */
- ETHERMINTU = 60, /* minimum transmit size */
- ETHERMAXTU = 1514, /* maximum transmit size */
- ETHERHDRSIZE = 14, /* size of an ethernet header */
-
- MaxEther = 6,
-};
-
-typedef struct {
- uchar d[Eaddrlen];
- uchar s[Eaddrlen];
- uchar type[2];
- uchar data[1500];
- uchar crc[4];
-} Etherpkt;
-
-extern uchar broadcast[Eaddrlen];
-
-typedef struct Ureg Ureg;
-#pragma incomplete Ureg
-
-typedef struct Segdesc {
- ulong d0;
- ulong d1;
-} Segdesc;
-
-typedef struct Mach {
- ulong ticks; /* of the clock since boot time */
- void *alarm; /* alarms bound to this clock */
-} Mach;
-
-extern Mach *m;
-
-#define I_MAGIC ((((4*11)+0)*11)+7)
-
-typedef struct Exec Exec;
-struct Exec
-{
- uchar magic[4]; /* magic number */
- uchar text[4]; /* size of text segment */
- uchar data[4]; /* size of initialized data */
- uchar bss[4]; /* size of uninitialized data */
- uchar syms[4]; /* size of symbol table */
- uchar entry[4]; /* entry point */
- uchar spsz[4]; /* size of sp/pc offset table */
- uchar pcsz[4]; /* size of pc/line number table */
-};
-
-/*
- * a parsed .ini line
- */
-#define ISAOPTLEN 32
-#define NISAOPT 8
-
-typedef struct ISAConf {
- char type[NAMELEN];
- ulong port;
- ulong irq;
- ulong mem;
- ulong size;
- uchar ea[6];
-
- int nopt;
- char opt[NISAOPT][ISAOPTLEN];
-} ISAConf;
-
-typedef struct Pcidev Pcidev;
-typedef struct PCMmap PCMmap;
-typedef struct PCMslot PCMslot;
-
-#define BOOTLINE ((char*)CONFADDR)
-
-enum {
- MB = (1024*1024),
-};
-#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1))
-
-
-typedef struct Type Type;
-typedef struct Medium Medium;
-typedef struct Boot Boot;
-
-enum { /* type */
- Tnil = 0x00,
-
- Tfloppy = 0x01,
- Tsd = 0x02,
- Tether = 0x03,
- Tcd = 0x04,
- Tbios = 0x05,
-
- Tany = -1,
-};
-
-enum { /* name and flag */
- Fnone = 0x00,
-
- Nfs = 0x00,
- Ffs = (1<<Nfs),
- Nboot = 0x01,
- Fboot = (1<<Nboot),
- Nbootp = 0x02,
- Fbootp = (1<<Nbootp),
- NName = 3,
-
- Fany = Fbootp|Fboot|Ffs,
-
- Fini = 0x10,
- Fprobe = 0x80,
-};
-
-typedef struct Type {
- int type;
- int flag;
- int (*init)(void);
- void (*initdev)(int, char*);
- void* (*getfspart)(int, char*, int); /* actually returns Dos* */
- void (*addconf)(int);
- int (*boot)(int, char*, Boot*);
- void (*printdevs)(int);
- char** parts;
- char** inis;
- int mask;
- Medium* media;
-} Type;
-
-extern void (*etherdetach)(void);
-extern void (*floppydetach)(void);
-extern void (*sddetach)(void);
-
-typedef struct Lock { /* for ilock, iunlock */
- int locked;
- int spl;
-} Lock;
-
-enum { /* returned by bootpass */
- MORE, ENOUGH, FAIL
-};
-enum {
- INITKERNEL,
- READEXEC,
- READ9TEXT,
- READ9DATA,
- READGZIP,
- READEHDR,
- READPHDR,
- READEPAD,
- READEDATA,
- TRYBOOT,
- INIT9LOAD,
- READ9LOAD,
- FAILED
-};
-
-struct Boot {
- int state;
-
- Exec exec;
- char *bp; /* base ptr */
- char *wp; /* write ptr */
- char *ep; /* end ptr */
-};
-
-extern int debug;
-extern Apminfo apm;
-extern char *defaultpartition;
-extern int iniread;
-extern int pxe;
--- a/os/boot/pc/devbios.c
+++ /dev/null
@@ -1,428 +1,0 @@
-/*
- * boot driver for BIOS devices
- */
-#include <u.h>
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "fs.h"
-
-typedef uvlong Devbytes, Devsects;
-
-typedef struct Biosdrive Biosdrive; /* 1 drive -> ndevs */
-typedef struct Biosdev Biosdev;
-
-enum {
- Debug = 0,
- Maxdevs = 4,
-
- CF = 1,
- Flopid = 0, /* first floppy */
- Baseid = 0x80, /* first disk */
-
- /* bios calls: int 13 disk services */
- Biosinit = 0, /* initialise disk & floppy ctlrs */
- Biosdrvsts,
- Bioschsrdsects,
- Biosdrvparam = 8,
- Biosctlrinit,
- Biosreset = 0xd, /* reset disk */
- Biosdrvrdy = 0x10,
- Biosdrvtype = 0x15,
- Biosckext = 0x41,
- Biosrdsect,
- Biosedrvparam = 0x48,
-
- /* disk types */
- Typenone = 0,
- Typedisk = 3,
-};
-
-struct Biosdrive {
- int ndevs;
-};
-struct Biosdev {
- Devbytes size;
- Devbytes offset;
- uchar id; /* drive number; e.g., 0x80 */
- char type;
- ushort sectsz;
-};
-
-typedef struct Extread {
- uchar size;
- uchar unused1;
- uchar nsects;
- uchar unused2;
- ulong addr; /* segment:offset */
- uvlong stsect; /* starting sector */
-} Extread;
-typedef struct Edrvparam {
- /* from edd 1.1 spec */
- ushort size; /* max. buffer size */
- ushort flags;
- ulong physcyls;
- ulong physheads;
- ulong phystracksects;
- uvlong physsects;
- ushort sectsz;
- void *dpte; /* ~0ull: invalid */
-
- /* remainder from edd 3.0 spec */
- ushort key; /* 0xbedd if present */
- uchar dpilen;
- uchar unused1;
- ushort unused2;
- char bustype[4]; /* "PCI" or "ISA" */
- char ifctype[8]; /* "ATA", "ATAPI", "SCSI", "USB", "1394", "FIBRE" */
- uvlong ifcpath;
- uvlong devpath;
- uchar unused3;
- uchar dpicksum;
-} Edrvparam;
-
-void realmode(int intr, Ureg *ureg); /* from trap.c */
-
-int onlybios0;
-int biosinited;
-
-static Biosdev bdev[Maxdevs];
-static Biosdrive bdrive;
-static Ureg regs;
-
-static int dreset(uchar drive);
-static Devbytes extgetsize(Biosdev *);
-static Devsects getsize(uchar drive, char *type);
-static int islba(uchar drive);
-
-static int
-biosdiskcall(Ureg *rp, uchar op, ulong bx, ulong dx, ulong si)
-{
- memset(rp, 0, sizeof *rp);
- rp->ax = op << 8;
- rp->bx = bx;
- rp->dx = dx; /* often drive id */
- rp->si = si;
- /* pass command in *rp, get results from there */
- realmode(0x13, rp);
- if (rp->flags & CF) {
-// print("biosdiskcall: int 13 op 0x%ux drive 0x%lux failed, "
-// "ah error code 0x%ux\n", op, dx, (uchar)(rp->ax >> 8));
- return -1;
- }
- return 0;
-}
-
-/*
- * Find out what the bios knows about devices.
- * our boot device could be usb; ghod only knows where it will appear.
- */
-int
-biosinit(void)
-{
- int devid, lba, mask, lastbit;
- Devbytes size;
- char type;
- Biosdev *bdp;
- static int beenhere;
-
- mask = lastbit = 0;
- if (beenhere)
- return mask;
- beenhere = 1;
- /* 9pxeload can't use bios int 13 calls; they wedge the machine */
- if (pxe || getconf("*nobiosload") != nil || onlybios0 || !biosinited)
- return mask;
- for (devid = 0; devid < (1 << 8) && bdrive.ndevs < Maxdevs; devid++) {
- lba = islba(devid);
- if(!lba /* || devid != Baseid && dreset(devid) < 0 */ )
- continue;
- type = Typedisk; /* HACK */
- if (getsize(devid, &type) == 0) { /* no device, end of range */
- devid &= ~0xf;
- devid += 0x10;
- devid--;
- continue;
- }
- lastbit = 1 << bdrive.ndevs;
- mask |= lastbit;
- bdp = &bdev[bdrive.ndevs];
- bdp->id = devid;
- bdp->type = type;
- size = extgetsize(bdp);
- bdp->size = size;
- print("bios%d: drive 0x%ux: %llud bytes, type %d\n",
- bdrive.ndevs, devid, size, type);
- bdrive.ndevs++;
- }
- /*
- * bioses seem to only be able to read from drive number 0x80
- * and certainly can't read from the highest drive number when we
- * call them, even if there is only one. attempting to read from
- * the last drive number yields a hung machine or a two-minute pause.
- */
- if (bdrive.ndevs > 0) {
- if (bdrive.ndevs == 1) {
- print("biosinit: sorry, only one bios drive; "
- "can't read last one\n");
- onlybios0 = 1;
- } else
- biosinited = 1;
- bdrive.ndevs--; /* omit last drive number; it can't be read */
- mask &= ~lastbit;
- }
- return mask;
-}
-
-void
-biosinitdev(int i, char *name)
-{
- if(i >= bdrive.ndevs)
- panic("biosinitdev");
- sprint(name, "bios%d", i);
-}
-
-void
-biosprintdevs(int i)
-{
- if(i >= bdrive.ndevs){
- print("got a print for %d, only got %d\n", i, bdrive.ndevs);
- panic("biosprintdevs");
- }
- print(" bios%d", i);
-}
-
-int
-biosboot(int dev, char *file, Boot *b)
-{
- Fs *fs;
-
- if(strncmp(file, "dos!", 4) == 0)
- file += 4;
- if(strchr(file, '!') != nil || strcmp(file, "") == 0) {
- print("syntax is bios0!file\n");
- return -1;
- }
-
- fs = biosgetfspart(dev, "9fat", 1);
- if(fs == nil)
- return -1;
- return fsboot(fs, file, b);
-}
-
-/* read n bytes at sector offset into a from drive id */
-long
-sectread(Biosdev *bdp, void *a, long n, Devsects offset)
-{
- uchar *biosparam, *cp;
- Extread *erp;
-
- if(n < 0 || n > bdp->sectsz)
- return -1;
- if(Debug)
- memset((uchar *)BIOSXCHG, 'r', bdp->sectsz); /* preclean the buffer. */
-
- biosdiskcall(®s, Biosdrvrdy, 0, bdp->id, 0);
-
- /* space for a BIG sector, just in case... */
- biosparam = (uchar *)BIOSXCHG + 2*1024;
-
- /* read into BIOSXCHG */
- erp = (Extread *)biosparam;
- memset(erp, 0, sizeof *erp);
- erp->size = sizeof *erp;
- erp->nsects = 1;
- erp->addr = PADDR(BIOSXCHG);
- erp->stsect = offset;
- if (biosdiskcall(®s, Biosrdsect, 0, bdp->id, PADDR(erp)) < 0) {
- print("sectread: bios failed to read %ld @ sector %lld of 0x%ux\n",
- n, offset, bdp->id);
- return -1;
- }
-
- /* copy into caller's buffer */
- memmove(a, (char *)BIOSXCHG, n);
- if(Debug){
- cp = (uchar *)BIOSXCHG;
- print("-%ux %ux %ux %ux--%16.16s-\n",
- cp[0], cp[1], cp[2], cp[3], (char *)cp + 480);
- }
- return n;
-}
-
-/* not tested yet. */
-static int
-dreset(uchar drive)
-{
-if (0) {
-print("devbios: resetting disk controllers...");
- biosdiskcall(®s, Biosinit, 0, drive, 0);
-print("\n");
-}
- return regs.ax? -1: 0; /* ax!=0 on error */
-}
-
-static int
-islba(uchar drive)
-{
- if (biosdiskcall(®s, Biosckext, 0x55aa, drive, 0) < 0)
- return 0;
- if(regs.bx != 0xaa55){
- print("islba: buggy bios\n");
- return 0;
- }
- if (Debug)
- print("islba: drive 0x%ux extensions version %d.%d cx 0x%lux\n",
- drive, (uchar)(regs.ax >> 8),
- (uchar)regs.ax, regs.cx); /* cx: 4=edd, 1=use dap */
- return regs.cx & 1; /* dap bit */
-}
-
-/*
- * works so so... some floppies are 0x80+x when they shouldn't be,
- * and report lba even if they cannot...
- */
-static Devsects
-getsize(uchar id, char *typep)
-{
- int dtype;
-
- if (biosdiskcall(®s, Biosdrvtype, 0x55aa, id, 0) < 0)
- return 0;
-
- dtype = (ushort)regs.ax >> 8;
- if(dtype == Typenone){
- print("no such device 0x%ux of type %d\n", id, dtype);
- return 0;
- }
- if(dtype != Typedisk){
- print("non-disk device 0x%ux of type %d\n", id, dtype);
- return 0;
- }
- *typep = dtype;
- return (ushort)regs.cx | regs.dx << 16;
-}
-
-/* extended get size */
-static Devbytes
-extgetsize(Biosdev *bdp)
-{
- Edrvparam *edp;
-
- edp = (Edrvparam *)BIOSXCHG;
- memset(edp, 0, sizeof *edp);
- edp->size = sizeof *edp;
- edp->dpilen = 36;
- if (biosdiskcall(®s, Biosedrvparam, 0, bdp->id, PADDR(edp)) < 0)
- return 0;
- if(Debug) {
- print("extgetsize: drive 0x%ux info flags 0x%ux",
- bdp->id, edp->flags);
- if (edp->key == 0xbedd)
- print(" %s %s", edp->bustype, edp->ifctype);
- print("\n");
- }
- if (edp->sectsz <= 0) {
- print("extgetsize: drive 0x%ux: non-positive sector size\n",
- bdp->id);
- edp->sectsz = 1; /* don't divide by zero */
- }
- bdp->sectsz = edp->sectsz;
- return edp->physsects * edp->sectsz;
-}
-
-long
-biosread(Fs *fs, void *a, long n)
-{
- int want, got, part;
- long totnr, stuck;
- Devbytes offset;
- Biosdev *bdp;
-
- if(fs->dev > bdrive.ndevs)
- return -1;
- if (n <= 0)
- return n;
- bdp = &bdev[fs->dev];
- offset = bdp->offset;
- stuck = 0;
- for (totnr = 0; totnr < n && stuck < 4; totnr += got) {
- want = bdp->sectsz;
- if (totnr + want > n)
- want = n - totnr;
- if(Debug)
- print("bios%d, read: %ld @ off %lld, want: %d, id: 0x%ux\n",
- fs->dev, n, offset, want, bdp->id);
- part = offset % bdp->sectsz;
- if (part != 0) { /* back up to start of sector */
- offset -= part;
- totnr -= part;
- if (totnr < 0) {
- print("biosread: negative count %ld\n", totnr);
- return -1;
- }
- }
- if ((vlong)offset < 0) {
- print("biosread: negative offset %lld\n", offset);
- return -1;
- }
- got = sectread(bdp, (char *)a + totnr, want, offset/bdp->sectsz);
- if(got <= 0){
-// print("biosread: failed to read %ld @ off %lld of 0x%ux, "
-// "want %d got %d\n",
-// n, offset, bdp->id, want, got);
- return -1;
- }
- offset += got;
- bdp->offset = offset;
- if (got < bdp->sectsz)
- stuck++; /* we'll have to re-read this sector */
- else
- stuck = 0;
- }
- return totnr;
-}
-
-vlong
-biosseek(Fs *fs, vlong off)
-{
- if (off < 0) {
- print("biosseek(fs, %lld) is illegal\n", off);
- return -1;
- }
- if(fs->dev > bdrive.ndevs) {
- print("biosseek: fs->dev %d > bdrive.ndevs %d\n",
- fs->dev, bdrive.ndevs);
- return -1;
- }
- bdev[fs->dev].offset = off; /* do not know size... (yet) */
- return off;
-}
-
-void *
-biosgetfspart(int i, char *name, int chatty)
-{
- static Fs fs;
-
- if(strcmp(name, "9fat") != 0){
- if(chatty)
- print("unknown partition bios%d!%s (use bios%d!9fat)\n",
- i, name, i);
- return nil;
- }
-
- fs.dev = i;
- fs.diskread = biosread;
- fs.diskseek = biosseek;
-
- if(dosinit(&fs) < 0){
- if(chatty)
- print("bios%d!%s does not contain a FAT file system\n",
- i, name);
- return nil;
- }
- return &fs;
-}
--- a/os/boot/pc/devbios.h
+++ /dev/null
@@ -1,22 +1,0 @@
-typedef uvlong Devbytes, Devsects;
-
-typedef struct Biosdrive Biosdrive; /* 1 drive -> ndevs */
-typedef struct Biosdev Biosdev;
-
-struct Biosdrive {
- int ndevs;
-};
-struct Biosdev {
- Devbytes size;
- Devbytes offset;
- uchar id;
- char type;
-};
-
-int biosboot(int dev, char *file, Boot *b);
-void* biosgetfspart(int i, char *name, int chatty);
-void biosinitdev(int i, char *name);
-int biosinit(void);
-void biosprintbootdevs(int dev);
-void biosprintdevs(int i);
-long biosread(Fs *fs, void *a, long n);
--- a/os/boot/pc/devfloppy.c
+++ /dev/null
@@ -1,853 +1,0 @@
-#include <u.h>
-
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-
-#include "fs.h"
-#include "devfloppy.h"
-
-
-/* Intel 82077A (8272A compatible) floppy controller */
-
-/* This module expects the following functions to be defined
- * elsewhere:
- *
- * inb()
- * outb()
- * floppyexec()
- * floppyeject()
- * floppysetup0()
- * floppysetup1()
- * dmainit()
- * dmasetup()
- * dmaend()
- *
- * On DMA systems, floppyexec() should be an empty function;
- * on non-DMA systems, dmaend() should be an empty function;
- * dmasetup() may enforce maximum transfer sizes.
- */
-
-enum {
- /* file types */
- Qdir= 0,
- Qdata= (1<<2),
- Qctl= (2<<2),
- Qmask= (3<<2),
-
- DMAchan= 2, /* floppy dma channel */
-};
-
-#define DPRINT if(0)print
-
-FType floppytype[] =
-{
- { "3½HD", T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54, 0, },
- { "3½DD", T1440kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
- { "3½DD", T720kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
- { "5¼HD", T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, },
- { "5¼DD", T1200kb, 512, 9, 2, 2, 40, 0x2A, 0x50, 1, },
- { "ATT3B1", T1200kb, 512, 8, 2, 2, 48, 0x2A, 0x50, 1, },
- { "5¼DD", T360kb, 512, 9, 2, 1, 40, 0x2A, 0x50, 2, },
-};
-
-/*
- * bytes per sector encoding for the controller.
- * - index for b2c is is (bytes per sector/128).
- * - index for c2b is code from b2c
- */
-static int b2c[] =
-{
-[1] 0,
-[2] 1,
-[4] 2,
-[8] 3,
-};
-static int c2b[] =
-{
- 128,
- 256,
- 512,
- 1024,
-};
-
-FController fl;
-
-#define MOTORBIT(i) (1<<((i)+4))
-
-/*
- * predeclared
- */
-static int cmddone(void*);
-static void floppyformat(FDrive*, char*);
-static void floppykproc(void*);
-static void floppypos(FDrive*,long);
-static int floppyrecal(FDrive*);
-static int floppyresult(void);
-static void floppyrevive(void);
-static vlong pcfloppyseek(FDrive*, vlong);
-static int floppysense(void);
-static void floppywait(int);
-static long floppyxfer(FDrive*, int, void*, long, long);
-
-static void
-fldump(void)
-{
- DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb),
- inb(Pdor), inb(Pmsr), inb(Pdir));
-}
-
-static void
-floppyalarm(Alarm* a)
-{
- FDrive *dp;
-
- for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
- if((fl.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5)
- floppyoff(dp);
- }
-
- alarm(5*1000, floppyalarm, 0);
- cancel(a);
-}
-
-/*
- * set floppy drive to its default type
- */
-static void
-floppysetdef(FDrive *dp)
-{
- FType *t;
-
- for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++)
- if(dp->dt == t->dt){
- dp->t = t;
- break;
- }
-}
-
-static void
-_floppydetach(void)
-{
- /*
- * stop the motors
- */
- fl.motor = 0;
- delay(10);
- outb(Pdor, fl.motor | Fintena | Fena);
- delay(10);
-}
-
-int
-floppyinit(void)
-{
- FDrive *dp;
- FType *t;
- ulong maxtsize;
- int mask;
-
- dmainit(DMAchan);
-
- floppysetup0(&fl);
-
- /*
- * init dependent parameters
- */
- maxtsize = 0;
- for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
- t->cap = t->bytes * t->heads * t->sectors * t->tracks;
- t->bcode = b2c[t->bytes/128];
- t->tsize = t->bytes * t->sectors;
- if(maxtsize < t->tsize)
- maxtsize = t->tsize;
- }
-
- fl.selected = fl.d;
-
- floppydetach = _floppydetach;
- floppydetach();
-
- /*
- * init drives
- */
- mask = 0;
- for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
- dp->dev = dp - fl.d;
- if(dp->dt == Tnone)
- continue;
- mask |= 1<<dp->dev;
- floppysetdef(dp);
- dp->cyl = -1; /* because we don't know */
- dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024);
- dp->ccyl = -1;
- dp->vers = 0;
- dp->maxtries = 5;
- }
-
- /*
- * first operation will recalibrate
- */
- fl.confused = 1;
-
- floppysetup1(&fl);
-
- /* to turn the motor off when inactive */
- alarm(5*1000, floppyalarm, 0);
-
- return mask;
-}
-
-void
-floppyinitdev(int i, char *name)
-{
- if(i >= fl.ndrive)
- panic("floppyinitdev");
- sprint(name, "fd%d", i);
-}
-
-void
-floppyprintdevs(int i)
-{
- if(i >= fl.ndrive)
- panic("floppyprintdevs");
- print(" fd%d", i);
-}
-
-int
-floppyboot(int dev, char *file, Boot *b)
-{
- Fs *fs;
-
- if(strncmp(file, "dos!", 4) == 0)
- file += 4;
- else if(strchr(file, '!') || strcmp(file, "")==0) {
- print("syntax is fd0!file\n");
- return -1;
- }
-
- fs = floppygetfspart(dev, "dos", 1);
- if(fs == nil)
- return -1;
-
- return fsboot(fs, file, b);
-}
-
-void
-floppyprintbootdevs(int dev)
-{
- print(" fd%d", dev);
-}
-
-/*
- * check if the floppy has been replaced under foot. cause
- * an error if it has.
- *
- * a seek and a read clears the condition. this was determined
- * experimentally, there has to be a better way.
- *
- * if the read fails, cycle through the possible floppy
- * density till one works or we've cycled through all
- * possibilities for this drive.
- */
-static int
-changed(FDrive *dp)
-{
- FType *start;
-
- /*
- * if floppy has changed or first time through
- */
- if((inb(Pdir)&Fchange) || dp->vers == 0){
- DPRINT("changed\n");
- fldump();
- dp->vers++;
- floppysetdef(dp);
- dp->maxtries = 3;
- start = dp->t;
-
- /* flopppyon fails if there's no drive */
- dp->confused = 1; /* make floppyon recal */
- if(floppyon(dp) < 0)
- return -1;
-
- pcfloppyseek(dp, dp->t->heads*dp->t->tsize);
-
- while(floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize) <= 0){
-
- /*
- * if the xfer attempt doesn't clear the changed bit,
- * there's no floppy in the drive
- */
- if(inb(Pdir)&Fchange)
- return -1;
-
- while(++dp->t){
- if(dp->t == &floppytype[nelem(floppytype)])
- dp->t = floppytype;
- if(dp->dt == dp->t->dt)
- break;
- }
-
- /* flopppyon fails if there's no drive */
- if(floppyon(dp) < 0)
- return -1;
-
- DPRINT("changed: trying %s\n", dp->t->name);
- fldump();
- if(dp->t == start)
- return -1;
- }
- }
-
- return 0;
-}
-
-static int
-readtrack(FDrive *dp, int cyl, int head)
-{
- int i, nn, sofar;
- ulong pos;
-
- nn = dp->t->tsize;
- if(dp->ccyl==cyl && dp->chead==head)
- return nn;
- pos = (cyl*dp->t->heads+head) * nn;
- for(sofar = 0; sofar < nn; sofar += i){
- dp->ccyl = -1;
- i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar);
- if(i <= 0)
- return -1;
- }
- dp->ccyl = cyl;
- dp->chead = head;
- return nn;
-}
-
-long
-floppyread(Fs *fs, void *a, long n)
-{
- FDrive *dp;
- long rv, offset;
- int sec, head, cyl;
- long len;
- uchar *aa;
-
- aa = a;
- dp = &fl.d[fs->dev];
-
- offset = dp->offset;
- floppyon(dp);
- if(changed(dp))
- return -1;
-
- for(rv = 0; rv < n; rv += len){
- /*
- * all xfers come out of the track cache
- */
- dp->len = n - rv;
- floppypos(dp, offset+rv);
- cyl = dp->tcyl;
- head = dp->thead;
- len = dp->len;
- sec = dp->tsec;
- if(readtrack(dp, cyl, head) < 0)
- break;
- memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);
- }
- dp->offset = offset+rv;
-
- return rv;
-}
-
-void*
-floppygetfspart(int i, char *name, int chatty)
-{
- static Fs fs;
-
- if(strcmp(name, "dos") != 0){
- if(chatty)
- print("unknown partition fd%d!%s (use fd%d!dos)\n", i, name, i);
- return nil;
- }
-
- fs.dev = i;
- fs.diskread = floppyread;
- fs.diskseek = floppyseek;
-
- /* sometimes we get spurious errors and doing it again works */
- if(dosinit(&fs) < 0 && dosinit(&fs) < 0){
- if(chatty)
- print("fd%d!%s does not contain a FAT file system\n", i, name);
- return nil;
- }
- return &fs;
-}
-
-static int
-return0(void*)
-{
- return 0;
-}
-
-static void
-timedsleep(int (*f)(void*), void* arg, int ms)
-{
- int s;
- ulong end;
-
- end = m->ticks + 1 + MS2TK(ms);
- while(m->ticks < end && !(*f)(arg)){
- s = spllo();
- delay(10);
- splx(s);
- }
-}
-
-/*
- * start a floppy drive's motor.
- */
-static int
-floppyon(FDrive *dp)
-{
- int alreadyon;
- int tries;
-
- if(fl.confused)
- floppyrevive();
-
- /* start motor and select drive */
- dp->lasttouched = m->ticks;
- alreadyon = fl.motor & MOTORBIT(dp->dev);
- if(!alreadyon){
- fl.motor |= MOTORBIT(dp->dev);
- outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
- /* wait for drive to spin up */
- timedsleep(return0, 0, 750);
-
- /* clear any pending interrupts */
- floppysense();
- }
-
- /* set transfer rate */
- if(fl.rate != dp->t->rate){
- fl.rate = dp->t->rate;
- outb(Pdsr, fl.rate);
- }
-
- /* get drive to a known cylinder */
- if(dp->confused)
- for(tries = 0; tries < 4; tries++)
- if(floppyrecal(dp) >= 0)
- break;
- dp->lasttouched = m->ticks;
- fl.selected = dp;
- if(dp->confused)
- return -1;
- return 0;
-}
-
-/*
- * stop the floppy if it hasn't been used in 5 seconds
- */
-static void
-floppyoff(FDrive *dp)
-{
- fl.motor &= ~MOTORBIT(dp->dev);
- outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
-}
-
-/*
- * send a command to the floppy
- */
-static int
-floppycmd(void)
-{
- int i;
- int tries;
-
- fl.nstat = 0;
- for(i = 0; i < fl.ncmd; i++){
- for(tries = 0; ; tries++){
- if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
- break;
- if(tries > 1000){
- DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
- fldump();
-
- /* empty fifo, might have been a bad command */
- floppyresult();
- return -1;
- }
- microdelay(1);
- }
- outb(Pfdata, fl.cmd[i]);
- }
- return 0;
-}
-
-/*
- * get a command result from the floppy
- *
- * when the controller goes ready waiting for a command
- * (instead of sending results), we're done
- *
- */
-static int
-floppyresult(void)
-{
- int i, s;
- int tries;
-
- /* get the result of the operation */
- for(i = 0; i < sizeof(fl.stat); i++){
- /* wait for status byte */
- for(tries = 0; ; tries++){
- s = inb(Pmsr)&(Ffrom|Fready);
- if(s == Fready){
- fl.nstat = i;
- return fl.nstat;
- }
- if(s == (Ffrom|Fready))
- break;
- if(tries > 1000){
- DPRINT("floppyresult: %d stats\n", i);
- fldump();
- fl.confused = 1;
- return -1;
- }
- microdelay(1);
- }
- fl.stat[i] = inb(Pfdata);
- }
- fl.nstat = sizeof(fl.stat);
- return fl.nstat;
-}
-
-/*
- * calculate physical address of a logical byte offset into the disk
- *
- * truncate dp->length if it crosses a track boundary
- */
-static void
-floppypos(FDrive *dp, long off)
-{
- int lsec;
- int ltrack;
- int end;
-
- lsec = off/dp->t->bytes;
- ltrack = lsec/dp->t->sectors;
- dp->tcyl = ltrack/dp->t->heads;
- dp->tsec = (lsec % dp->t->sectors) + 1;
- dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
-
- /*
- * can't read across track boundaries.
- * if so, decrement the bytes to be read.
- */
- end = (ltrack+1)*dp->t->sectors*dp->t->bytes;
- if(off+dp->len > end)
- dp->len = end - off;
-}
-
-/*
- * get the interrupt cause from the floppy.
- */
-static int
-floppysense(void)
-{
- fl.ncmd = 0;
- fl.cmd[fl.ncmd++] = Fsense;
- if(floppycmd() < 0)
- return -1;
- if(floppyresult() < 2){
- DPRINT("can't read sense response\n");
- fldump();
- fl.confused = 1;
- return -1;
- }
- return 0;
-}
-
-static int
-cmddone(void *a)
-{
- USED(a);
- return fl.ncmd == 0;
-}
-
-/*
- * Wait for a floppy interrupt. If none occurs in 5 seconds, we
- * may have missed one. This only happens on some portables which
- * do power management behind our backs. Call the interrupt
- * routine to try to clear any conditions.
- */
-static void
-floppywait(int slow)
-{
- timedsleep(cmddone, 0, slow ? 5000 : 1000);
- if(!cmddone(0)){
- floppyintr(0);
- fl.confused = 1;
- }
-}
-
-/*
- * we've lost the floppy position, go to cylinder 0.
- */
-static int
-floppyrecal(FDrive *dp)
-{
- dp->ccyl = -1;
- dp->cyl = -1;
-
- fl.ncmd = 0;
- fl.cmd[fl.ncmd++] = Frecal;
- fl.cmd[fl.ncmd++] = dp->dev;
- if(floppycmd() < 0)
- return -1;
- floppywait(1);
- if(fl.nstat < 2){
- DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
- fl.confused = 1;
- return -1;
- }
- if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
- DPRINT("recalibrate: failed\n");
- dp->confused = 1;
- return -1;
- }
- dp->cyl = fl.stat[1];
- if(dp->cyl != 0){
- DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl);
- dp->cyl = -1;
- dp->confused = 1;
- return -1;
- }
-
- dp->confused = 0;
- return 0;
-}
-
-/*
- * if the controller or a specific drive is in a confused state,
- * reset it and get back to a kown state
- */
-static void
-floppyrevive(void)
-{
- FDrive *dp;
-
- /*
- * reset the controller if it's confused
- */
- if(fl.confused){
- DPRINT("floppyrevive in\n");
- fldump();
-
- /* reset controller and turn all motors off */
- splhi();
- fl.ncmd = 1;
- fl.cmd[0] = 0;
- outb(Pdor, 0);
- delay(10);
- outb(Pdor, Fintena|Fena);
- delay(10);
- spllo();
- fl.motor = 0;
- fl.confused = 0;
- floppywait(0);
-
- /* mark all drives in an unknown state */
- for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)
- dp->confused = 1;
-
- /* set rate to a known value */
- outb(Pdsr, 0);
- fl.rate = 0;
-
- DPRINT("floppyrevive out\n");
- fldump();
- }
-}
-
-/*
- * seek to the target cylinder
- *
- * interrupt, no results
- */
-static vlong
-pcfloppyseek(FDrive *dp, vlong off)
-{
- floppypos(dp, off);
- if(dp->cyl == dp->tcyl){
- dp->offset = off;
- return off;
- }
- dp->cyl = -1;
-
- fl.ncmd = 0;
- fl.cmd[fl.ncmd++] = Fseek;
- fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
- fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
- if(floppycmd() < 0)
- return -1;
- floppywait(1);
- if(fl.nstat < 2){
- DPRINT("seek: confused\n");
- fl.confused = 1;
- return -1;
- }
- if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
- DPRINT("seek: failed\n");
- dp->confused = 1;
- return -1;
- }
-
- dp->cyl = dp->tcyl;
- dp->offset = off;
- DPRINT("seek to %d succeeded\n", dp->offset);
-
- return dp->offset;
-}
-
-/*
- * read or write to floppy. try up to three times.
- */
-static long
-floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
-{
- long offset;
- int tries;
-
- if(off >= dp->t->cap)
- return 0;
- if(off + n > dp->t->cap)
- n = dp->t->cap - off;
-
- /* retry on error (until it gets ridiculous) */
- for(tries = 0; tries < dp->maxtries; tries++){
-
- dp->len = n;
- if(pcfloppyseek(dp, off) < 0){
- DPRINT("xfer: seek failed\n");
- dp->confused = 1;
- continue;
- }
-
- /*
- * set up the dma (dp->len may be trimmed)
- */
- dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
- if(dp->len < 0){
- buggery:
- dmaend(DMAchan);
- continue;
- }
-
- /*
- * start operation
- */
- fl.ncmd = 0;
- fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);
- fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
- fl.cmd[fl.ncmd++] = dp->tcyl;
- fl.cmd[fl.ncmd++] = dp->thead;
- fl.cmd[fl.ncmd++] = dp->tsec;
- fl.cmd[fl.ncmd++] = dp->t->bcode;
- fl.cmd[fl.ncmd++] = dp->t->sectors;
- fl.cmd[fl.ncmd++] = dp->t->gpl;
- fl.cmd[fl.ncmd++] = 0xFF;
- if(floppycmd() < 0)
- goto buggery;
-
- /*
- * give bus to DMA, floppyintr() will read result
- */
- floppywait(0);
- dmaend(DMAchan);
-
- /*
- * check for errors
- */
- if(fl.nstat < 7){
- DPRINT("xfer: confused\n");
- fl.confused = 1;
- continue;
- }
- if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
- DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],
- fl.stat[1], fl.stat[2]);
- DPRINT("offset %lud len %ld\n", off, dp->len);
- if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){
- DPRINT("DMA overrun: retry\n");
- } else
- dp->confused = 1;
- continue;
- }
-
- /*
- * check for correct cylinder
- */
- offset = fl.stat[3] * dp->t->heads + fl.stat[4];
- offset = offset*dp->t->sectors + fl.stat[5] - 1;
- offset = offset * c2b[fl.stat[6]];
- if(offset != off+dp->len){
- DPRINT("xfer: ends on wrong cyl\n");
- dp->confused = 1;
- continue;
- }
-
- dp->lasttouched = m->ticks;
- dp->maxtries = 20;
- return dp->len;
- }
-
- return -1;
-}
-
-/*
-void
-floppymemwrite(void)
-{
- int i;
- int n;
- uchar *a;
- FDrive *dp;
-
- dp = &fl.d[0];
- a = (uchar*)0x80000000;
- n = 0;
- while(n < 1440*1024){
- i = floppyxfer(dp, Fwrite, a+n, n, 1440*1024-n);
- if(i <= 0)
- break;
- n += i;
- }
- print("floppymemwrite wrote %d bytes\n", n);
-splhi(); for(;;);
-}
-*/
-
-static void
-floppyintr(Ureg *ur)
-{
- USED(ur);
- switch(fl.cmd[0]&~Fmulti){
- case Fread:
- case Fwrite:
- case Fformat:
- case Fdumpreg:
- floppyresult();
- break;
- case Fseek:
- case Frecal:
- default:
- floppysense(); /* to clear interrupt */
- break;
- }
- fl.ncmd = 0;
-}
--- a/os/boot/pc/devfloppy.h
+++ /dev/null
@@ -1,196 +1,0 @@
-typedef struct FController FController;
-typedef struct FDrive FDrive;
-typedef struct FType FType;
-
-static void floppyintr(Ureg*);
-static int floppyon(FDrive*);
-static void floppyoff(FDrive*);
-static void floppysetdef(FDrive*);
-
-/*
- * a floppy drive
- */
-struct FDrive
-{
- FType *t; /* floppy type */
- int dt; /* drive type */
- int dev;
-
- ulong lasttouched; /* time last touched */
- int cyl; /* current arm position */
- int confused; /* needs to be recalibrated */
- int offset; /* current offset */
- int vers;
- int maxtries;
-
- int tcyl; /* target cylinder */
- int thead; /* target head */
- int tsec; /* target sector */
- long len; /* size of xfer */
-
- uchar *cache; /* track cache */
- int ccyl;
- int chead;
-
-// Rendez r; /* waiting here for motor to spin up */
- void *aux;
-};
-
-/*
- * controller for 4 floppys
- */
-struct FController
-{
-// QLock; /* exclusive access to the contoller */
-
- int ndrive;
- FDrive *d; /* the floppy drives */
- FDrive *selected;
- int rate; /* current rate selected */
- uchar cmd[14]; /* command */
- int ncmd; /* # command bytes */
- uchar stat[14]; /* command status */
- int nstat; /* # status bytes */
- int confused; /* controler needs to be reset */
-// Rendez r; /* wait here for command termination */
- int motor; /* bit mask of spinning disks */
-// Rendez kr; /* for motor watcher */
-};
-
-/*
- * floppy types (all MFM encoding)
- */
-struct FType
-{
- char *name;
- int dt; /* compatible drive type */
- int bytes; /* bytes/sector */
- int sectors; /* sectors/track */
- int heads; /* number of heads */
- int steps; /* steps per cylinder */
- int tracks; /* tracks/disk */
- int gpl; /* intersector gap length for read/write */
- int fgpl; /* intersector gap length for format */
- int rate; /* rate code */
-
- /*
- * these depend on previous entries and are set filled in
- * by floppyinit
- */
- int bcode; /* coded version of bytes for the controller */
- long cap; /* drive capacity in bytes */
- long tsize; /* track size in bytes */
-};
-/* bits in the registers */
-enum
-{
- /* status registers a & b */
- Psra= 0x3f0,
- Psrb= 0x3f1,
-
- /* digital output register */
- Pdor= 0x3f2,
- Fintena= 0x8, /* enable floppy interrupt */
- Fena= 0x4, /* 0 == reset controller */
-
- /* main status register */
- Pmsr= 0x3f4,
- Fready= 0x80, /* ready to be touched */
- Ffrom= 0x40, /* data from controller */
- Ffloppybusy= 0x10, /* operation not over */
-
- /* data register */
- Pfdata= 0x3f5,
- Frecal= 0x07, /* recalibrate cmd */
- Fseek= 0x0f, /* seek cmd */
- Fsense= 0x08, /* sense cmd */
- Fread= 0x66, /* read cmd */
- Freadid= 0x4a, /* read track id */
- Fspec= 0x03, /* set hold times */
- Fwrite= 0x45, /* write cmd */
- Fformat= 0x4d, /* format cmd */
- Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */
- Fdumpreg= 0x0e, /* dump internal registers */
-
- /* digital input register */
- Pdir= 0x3F7, /* disk changed port (read only) */
- Pdsr= 0x3F7, /* data rate select port (write only) */
- Fchange= 0x80, /* disk has changed */
-
- /* status 0 byte */
- Drivemask= 3<<0,
- Seekend= 1<<5,
- Codemask= (3<<6)|(3<<3),
- Cmdexec= 1<<6,
-
- /* status 1 byte */
- Overrun= 0x10,
-};
-
-/*
- * types of drive (from PC equipment byte)
- */
-enum
-{
- Tnone= 0,
- T360kb= 1,
- T1200kb= 2,
- T720kb= 3,
- T1440kb= 4,
-};
-
-static void
-pcfloppyintr(Ureg *ur, void *a)
-{
- USED(a);
-
- floppyintr(ur);
-}
-
-void
-floppysetup0(FController *fl)
-{
- uchar equip;
-
- /*
- * Read nvram for types of floppies 0 & 1.
- * Always try floppy 0.
- */
- equip = nvramread(0x10);
- fl->ndrive = 1;
-
- if(equip & 0xf)
- fl->ndrive++;
-
- /*
- * Allocate the drive storage.
- * There's always one.
- */
- fl->d = xalloc(fl->ndrive*sizeof(FDrive));
- fl->d[0].dt = (equip >> 4) & 0xf;
- if(fl->d[0].dt == Tnone)
- fl->d[0].dt = T1440kb;
-
- if(fl->ndrive == 2)
- fl->d[1].dt = equip & 0xf;
-}
-
-void
-floppysetup1(FController*)
-{
-// intrenable(VectorFLOPPY, pcfloppyintr, fl, BUSUNKNOWN);
- setvec(VectorFLOPPY, pcfloppyintr, 0);
-}
-
-
-static vlong pcfloppyseek(FDrive*, vlong);
-FController fl;
-
-vlong
-floppyseek(Fs *fs, vlong off)
-{
- FDrive *dp;
-
- dp = &fl.d[fs->dev];
- return pcfloppyseek(dp, off);
-}
--- a/os/boot/pc/devi82365.c
+++ /dev/null
@@ -1,742 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "error.h"
-#include "io.h"
-
-/*
- * Intel 82365SL PCIC controller and compatibles.
- */
-enum
-{
- /*
- * registers indices
- */
- Rid= 0x0, /* identification and revision */
- Ris= 0x1, /* interface status */
- Rpc= 0x2, /* power control */
- Foutena= (1<<7), /* output enable */
- Fautopower= (1<<5), /* automatic power switching */
- Fcardena= (1<<4), /* PC card enable */
- Rigc= 0x3, /* interrupt and general control */
- Fiocard= (1<<5), /* I/O card (vs memory) */
- Fnotreset= (1<<6), /* reset if not set */
- FSMIena= (1<<4), /* enable change interrupt on SMI */
- Rcsc= 0x4, /* card status change */
- Rcscic= 0x5, /* card status change interrupt config */
- Fchangeena= (1<<3), /* card changed */
- Fbwarnena= (1<<1), /* card battery warning */
- Fbdeadena= (1<<0), /* card battery dead */
- Rwe= 0x6, /* address window enable */
- Fmem16= (1<<5), /* use A23-A12 to decode address */
- Rio= 0x7, /* I/O control */
- Fwidth16= (1<<0), /* 16 bit data width */
- Fiocs16= (1<<1), /* IOCS16 determines data width */
- Fzerows= (1<<2), /* zero wait state */
- Ftiming= (1<<3), /* timing register to use */
- Riobtm0lo= 0x8, /* I/O address 0 start low byte */
- Riobtm0hi= 0x9, /* I/O address 0 start high byte */
- Riotop0lo= 0xa, /* I/O address 0 stop low byte */
- Riotop0hi= 0xb, /* I/O address 0 stop high byte */
- Riobtm1lo= 0xc, /* I/O address 1 start low byte */
- Riobtm1hi= 0xd, /* I/O address 1 start high byte */
- Riotop1lo= 0xe, /* I/O address 1 stop low byte */
- Riotop1hi= 0xf, /* I/O address 1 stop high byte */
- Rmap= 0x10, /* map 0 */
-
- /*
- * CL-PD67xx extension registers
- */
- Rmisc1= 0x16, /* misc control 1 */
- F5Vdetect= (1<<0),
- Fvcc3V= (1<<1),
- Fpmint= (1<<2),
- Fpsirq= (1<<3),
- Fspeaker= (1<<4),
- Finpack= (1<<7),
- Rfifo= 0x17, /* fifo control */
- Fflush= (1<<7), /* flush fifo */
- Rmisc2= 0x1E, /* misc control 2 */
- Flowpow= (1<<1), /* low power mode */
- Rchipinfo= 0x1F, /* chip information */
- Ratactl= 0x26, /* ATA control */
-
- /*
- * offsets into the system memory address maps
- */
- Mbtmlo= 0x0, /* System mem addr mapping start low byte */
- Mbtmhi= 0x1, /* System mem addr mapping start high byte */
- F16bit= (1<<7), /* 16-bit wide data path */
- Mtoplo= 0x2, /* System mem addr mapping stop low byte */
- Mtophi= 0x3, /* System mem addr mapping stop high byte */
- Ftimer1= (1<<6), /* timer set 1 */
- Mofflo= 0x4, /* Card memory offset address low byte */
- Moffhi= 0x5, /* Card memory offset address high byte */
- Fregactive= (1<<6), /* attribute memory */
-
- /*
- * configuration registers - they start at an offset in attribute
- * memory found in the CIS.
- */
- Rconfig= 0,
- Creset= (1<<7), /* reset device */
- Clevel= (1<<6), /* level sensitive interrupt line */
- Cirq= (1<<2), /* IRQ enable */
- Cdecode= (1<<1), /* address decode */
- Cfunc= (1<<0), /* function enable */
- Riobase0= 5,
- Riobase1= 6,
- Riosize= 9,
-};
-
-static int pcmcia_pcmspecial(char *, ISAConf *);
-static void pcmcia_pcmspecialclose(int);
-
-#define MAP(x,o) (Rmap + (x)*0x8 + o)
-
-typedef struct I82365 I82365;
-
-/* a controller */
-enum
-{
- Ti82365,
- Tpd6710,
- Tpd6720,
- Tvg46x,
-};
-struct I82365
-{
- int type;
- int dev;
- int nslot;
- int xreg; /* index register address */
- int dreg; /* data register address */
- int irq;
-};
-static I82365 *controller[4];
-static int ncontroller;
-static PCMslot *slot;
-static PCMslot *lastslot;
-static nslot;
-
-static void i82365intr(Ureg*, void*);
-static void i82365reset(void);
-static int pcmio(int, ISAConf*);
-
-static void i82365dump(PCMslot*);
-
-void
-devi82365link(void)
-{
- static int already;
- char *p;
-
- if(already)
- return;
- already = 1;
-
- if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0)
- return;
-
- if (_pcmspecial)
- return;
-
- _pcmspecial = pcmcia_pcmspecial;
- _pcmspecialclose = pcmcia_pcmspecialclose;
-}
-
-/*
- * reading and writing card registers
- */
-static uchar
-rdreg(PCMslot *pp, int index)
-{
- outb(((I82365*)pp->cp)->xreg, pp->base + index);
- return inb(((I82365*)pp->cp)->dreg);
-}
-static void
-wrreg(PCMslot *pp, int index, uchar val)
-{
- outb(((I82365*)pp->cp)->xreg, pp->base + index);
- outb(((I82365*)pp->cp)->dreg, val);
-}
-
-/*
- * get info about card
- */
-static void
-slotinfo(PCMslot *pp)
-{
- uchar isr;
-
- isr = rdreg(pp, Ris);
- pp->occupied = (isr & (3<<2)) == (3<<2);
- pp->powered = isr & (1<<6);
- pp->battery = (isr & 3) == 3;
- pp->wrprot = isr & (1<<4);
- pp->busy = isr & (1<<5);
- //pp->msec = TK2MS(MACHP(0)->ticks);
-}
-
-static int
-vcode(int volt)
-{
- switch(volt){
- case 5:
- return 1;
- case 12:
- return 2;
- default:
- return 0;
- }
-}
-
-/*
- * enable the slot card
- */
-static void
-slotena(PCMslot *pp)
-{
- if(pp->enabled)
- return;
-
- /* power up and unreset, wait's are empirical (???) */
- wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
- delay(300);
- wrreg(pp, Rigc, 0);
- delay(100);
- wrreg(pp, Rigc, Fnotreset);
- delay(500);
-
- /* get configuration */
- slotinfo(pp);
- if(pp->occupied){
- pcmcisread(pp);
- pp->enabled = 1;
- } else
- wrreg(pp, Rpc, Fautopower);
-}
-
-/*
- * disable the slot card
- */
-static void
-slotdis(PCMslot *pp)
-{
- wrreg(pp, Rpc, 0); /* turn off card power */
- wrreg(pp, Rwe, 0); /* no windows */
- pp->enabled = 0;
-}
-
-/*
- * status change interrupt
- */
-static void
-i82365intr(Ureg *, void *)
-{
- uchar csc, was;
- PCMslot *pp;
-
- if(slot == 0)
- return;
-
- for(pp = slot; pp < lastslot; pp++){
- csc = rdreg(pp, Rcsc);
- was = pp->occupied;
- slotinfo(pp);
- if(csc & (1<<3) && was != pp->occupied){
- if(!pp->occupied)
- slotdis(pp);
- }
- }
-}
-
-enum
-{
- Mshift= 12,
- Mgran= (1<<Mshift), /* granularity of maps */
- Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
-};
-
-/*
- * get a map for pc card region, return corrected len
- */
-PCMmap*
-pcmmap(int slotno, ulong offset, int len, int attr)
-{
- PCMslot *pp;
- uchar we, bit;
- PCMmap *m, *nm;
- int i;
- ulong e;
-
- pp = slot + slotno;
- lock(&pp->mlock);
-
- /* convert offset to granularity */
- if(len <= 0)
- len = 1;
- e = ROUND(offset+len, Mgran);
- offset &= Mmask;
- len = e - offset;
-
- /* look for a map that covers the right area */
- we = rdreg(pp, Rwe);
- bit = 1;
- nm = 0;
- for(m = pp->mmap; m < &pp->mmap[nelem(pp->mmap)]; m++){
- if((we & bit))
- if(m->attr == attr)
- if(offset >= m->ca && e <= m->cea){
-
- m->ref++;
- unlock(&pp->mlock);
- return m;
- }
- bit <<= 1;
- if(nm == 0 && m->ref == 0)
- nm = m;
- }
- m = nm;
- if(m == 0){
- unlock(&pp->mlock);
- return 0;
- }
-
- /* if isa space isn't big enough, free it and get more */
- if(m->len < len){
- if(m->isa){
- umbfree(m->isa, m->len);
- m->len = 0;
- }
- m->isa = PADDR(umbmalloc(0, len, Mgran));
- if(m->isa == 0){
- print("pcmmap %d: out of isa space\n", len);
- unlock(&pp->mlock);
- return 0;
- }
- m->len = len;
- }
-
- /* set up new map */
- m->ca = offset;
- m->cea = m->ca + m->len;
- m->attr = attr;
- i = m-pp->mmap;
- bit = 1<<i;
- wrreg(pp, Rwe, we & ~bit); /* disable map before changing it */
- wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift);
- wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
- wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
- wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
- offset -= m->isa;
- offset &= (1<<25)-1;
- offset >>= Mshift;
- wrreg(pp, MAP(i, Mofflo), offset);
- wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
- wrreg(pp, Rwe, we | bit); /* enable map */
- m->ref = 1;
-
- unlock(&pp->mlock);
- return m;
-}
-
-void
-pcmunmap(int slotno, PCMmap* m)
-{
- PCMslot *pp;
-
- pp = slot + slotno;
- lock(&pp->mlock);
- m->ref--;
- unlock(&pp->mlock);
-}
-
-static void
-increfp(PCMslot *pp)
-{
- lock(pp);
- if(pp->ref++ == 0)
- slotena(pp);
- unlock(pp);
-}
-
-static void
-decrefp(PCMslot *pp)
-{
- lock(pp);
- if(pp->ref-- == 1)
- slotdis(pp);
- unlock(pp);
-}
-
-/*
- * look for a card whose version contains 'idstr'
- */
-static int
-pcmcia_pcmspecial(char *idstr, ISAConf *isa)
-{
- PCMslot *pp;
- extern char *strstr(char*, char*);
- int enabled;
-
- i82365reset();
- for(pp = slot; pp < lastslot; pp++){
- if(pp->special)
- continue; /* already taken */
- enabled = 0;
- /* make sure we don't power on cards when we already know what's
- * in them. We'll reread every two minutes if necessary
- */
- if (pp->verstr[0] == '\0') {
- increfp(pp);
- enabled++;
- }
-
- if(pp->occupied) {
- if(strstr(pp->verstr, idstr)){
- if (!enabled){
- enabled = 1;
- increfp(pp);
- }
- if(isa == 0 || pcmio(pp->slotno, isa) == 0){
- pp->special = 1;
- return pp->slotno;
- }
- }
- } else
- pp->special = 1;
- if (enabled)
- decrefp(pp);
- }
- return -1;
-}
-
-static void
-pcmcia_pcmspecialclose(int slotno)
-{
- PCMslot *pp;
-
- print("pcmspecialclose called\n");
- if(slotno >= nslot)
- panic("pcmspecialclose");
- pp = slot + slotno;
- pp->special = 0;
- decrefp(pp);
-}
-
-static char *chipname[] =
-{
-[Ti82365] "Intel 82365SL",
-[Tpd6710] "Cirrus Logic PD6710",
-[Tpd6720] "Cirrus Logic PD6720",
-[Tvg46x] "Vadem VG-46x",
-};
-
-static I82365*
-i82365probe(int x, int d, int dev)
-{
- uchar c, id;
- I82365 *cp;
- ISAConf isa;
- int i, nslot;
-
- outb(x, Rid + (dev<<7));
- id = inb(d);
- if((id & 0xf0) != 0x80)
- return 0; /* not a memory & I/O card */
- if((id & 0x0f) == 0x00)
- return 0; /* no revision number, not possible */
-
- cp = xalloc(sizeof(I82365));
- cp->xreg = x;
- cp->dreg = d;
- cp->dev = dev;
- cp->type = Ti82365;
- cp->nslot = 2;
-
- switch(id){
- case 0x82:
- case 0x83:
- case 0x84:
- /* could be a cirrus */
- outb(x, Rchipinfo + (dev<<7));
- outb(d, 0);
- c = inb(d);
- if((c & 0xc0) != 0xc0)
- break;
- c = inb(d);
- if((c & 0xc0) != 0x00)
- break;
- if(c & 0x20){
- cp->type = Tpd6720;
- } else {
- cp->type = Tpd6710;
- cp->nslot = 1;
- }
-
- /* low power mode */
- outb(x, Rmisc2 + (dev<<7));
- c = inb(d);
- outb(d, c & ~Flowpow);
- break;
- }
-
- /* if it's not a Cirrus, it could be a Vadem... */
- if(cp->type == Ti82365){
- /* unlock the Vadem extended regs */
- outb(x, 0x0E + (dev<<7));
- outb(x, 0x37 + (dev<<7));
-
- /* make the id register show the Vadem id */
- outb(x, 0x3A + (dev<<7));
- c = inb(d);
- outb(d, c|0xC0);
- outb(x, Rid + (dev<<7));
- c = inb(d);
- if(c & 0x08)
- cp->type = Tvg46x;
-
- /* go back to Intel compatible id */
- outb(x, 0x3A + (dev<<7));
- c = inb(d);
- outb(d, c & ~0xC0);
- }
-
- memset(&isa, 0, sizeof(ISAConf));
- if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq)
- cp->irq = isa.irq;
- else
- cp->irq = VectorPCMCIA - VectorPIC;
-
- for(i = 0; i < isa.nopt; i++){
- if(cistrncmp(isa.opt[i], "nslot=", 6))
- continue;
- nslot = strtol(&isa.opt[i][6], nil, 0);
- if(nslot > 0 && nslot <= 2)
- cp->nslot = nslot;
- }
-
- controller[ncontroller++] = cp;
- return cp;
-}
-
-static void
-i82365dump(PCMslot *pp)
-{
- int i;
-
- for(i = 0; i < 0x40; i++){
- if((i&0x0F) == 0)
- print("\n%2.2uX: ", i);
- if(((i+1) & 0x0F) == 0x08)
- print(" - ");
- print("%2.2uX ", rdreg(pp, i));
- }
- print("\n");
-}
-
-/*
- * set up for slot cards
- */
-static void
-i82365reset(void)
-{
- static int already;
- int i, j;
- I82365 *cp;
- PCMslot *pp;
-
- if(already)
- return;
- already = 1;
-
-
- /* look for controllers */
- i82365probe(0x3E0, 0x3E1, 0);
- i82365probe(0x3E0, 0x3E1, 1);
- i82365probe(0x3E2, 0x3E3, 0);
- i82365probe(0x3E2, 0x3E3, 1);
-
- for(i = 0; i < ncontroller; i++)
- nslot += controller[i]->nslot;
- slot = xalloc(nslot * sizeof(PCMslot));
-
- lastslot = slot;
- for(i = 0; i < ncontroller; i++){
- cp = controller[i];
- print("#y%d: %d slot %s: port 0x%uX irq %d\n",
- i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq);
- for(j = 0; j < cp->nslot; j++){
- pp = lastslot++;
- pp->slotno = pp - slot;
- pp->memlen = 64*MB;
- pp->base = (cp->dev<<7) | (j<<6);
- pp->cp = cp;
- pp->msec = ~0;
- pp->verstr[0] = 0;
- slotdis(pp);
-
- /* interrupt on status change */
- wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena);
- rdreg(pp, Rcsc);
- }
-
- /* for card management interrupts */
- setvec(cp->irq+VectorPIC, i82365intr, 0);
- }
-}
-
-/*
- * configure the PCMslot for IO. We assume very heavily that we can read
- * configuration info from the CIS. If not, we won't set up correctly.
- */
-static int
-pcmio(int slotno, ISAConf *isa)
-{
- uchar we, x, *p;
- PCMslot *pp;
- PCMconftab *ct, *et, *t;
- PCMmap *m;
- int i, index, irq;
- char *cp;
-
- irq = isa->irq;
- if(irq == 2)
- irq = 9;
-
- if(slotno > nslot)
- return -1;
- pp = slot + slotno;
-
- if(!pp->occupied)
- return -1;
-
- et = &pp->ctab[pp->nctab];
-
- ct = 0;
- for(i = 0; i < isa->nopt; i++){
- if(strncmp(isa->opt[i], "index=", 6))
- continue;
- index = strtol(&isa->opt[i][6], &cp, 0);
- if(cp == &isa->opt[i][6] || index >= pp->nctab)
- return -1;
- ct = &pp->ctab[index];
- }
-
- if(ct == 0){
-
- /* assume default is right */
- if(pp->def)
- ct = pp->def;
- else
- ct = pp->ctab;
-
- /* try for best match */
- if(ct->nio == 0
- || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
- for(t = pp->ctab; t < et; t++)
- if(t->nio
- && t->io[0].start == isa->port
- && ((1<<irq) & t->irqs)){
- ct = t;
- break;
- }
- }
- if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
- for(t = pp->ctab; t < et; t++)
- if(t->nio && ((1<<irq) & t->irqs)){
- ct = t;
- break;
- }
- }
- if(ct->nio == 0){
- for(t = pp->ctab; t < et; t++)
- if(t->nio){
- ct = t;
- break;
- }
- }
- }
-
- if(ct == et || ct->nio == 0)
- return -1;
- if(isa->port == 0 && ct->io[0].start == 0)
- return -1;
-
- /* route interrupts */
- isa->irq = irq;
- wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
-
- /* set power and enable device */
- x = vcode(ct->vpp1);
- wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
-
- /* 16-bit data path */
- if(ct->bit16)
- x = Ftiming|Fiocs16|Fwidth16;
- else
- x = Ftiming;
- if(ct->nio == 2 && ct->io[1].start)
- x |= x<<4;
- wrreg(pp, Rio, x);
-
- /*
- * enable io port map 0
- * the 'top' register value includes the last valid address
- */
- if(isa->port == 0)
- isa->port = ct->io[0].start;
- we = rdreg(pp, Rwe);
- wrreg(pp, Riobtm0lo, isa->port);
- wrreg(pp, Riobtm0hi, isa->port>>8);
- i = isa->port+ct->io[0].len-1;
- wrreg(pp, Riotop0lo, i);
- wrreg(pp, Riotop0hi, i>>8);
- we |= 1<<6;
- if(ct->nio >= 2 && ct->io[1].start){
- wrreg(pp, Riobtm1lo, ct->io[1].start);
- wrreg(pp, Riobtm1hi, ct->io[1].start>>8);
- i = ct->io[1].start+ct->io[1].len-1;
- wrreg(pp, Riotop1lo, i);
- wrreg(pp, Riotop1hi, i>>8);
- we |= 1<<7;
- }
- wrreg(pp, Rwe, we);
-
- /* only touch Rconfig if it is present */
- m = pcmmap(slotno, pp->cfg[0].caddr + Rconfig, 0x20, 1);
- p = KADDR(m->isa + pp->cfg[0].caddr - m->ca);
- if(pp->cfg[0].cpresent & (1<<Rconfig)){
- /* Reset adapter */
-
- /* set configuration and interrupt type.
- * if level is possible on the card, use it.
- */
- x = ct->index;
- if(ct->irqtype & 0x20)
- x |= Clevel;
-
- /* enable the device, enable address decode and
- * irq enable.
- */
- x |= Cfunc|Cdecode|Cirq;
-
- p[0] = x;
- //delay(5);
- microdelay(40);
- }
-
- if(pp->cfg[0].cpresent & (1<<Riobase0)){
- /* set up the iobase 0 */
- p[Riobase0 << 1] = isa->port;
- p[Riobase1 << 1] = isa->port >> 8;
- }
-
- if(pp->cfg[0].cpresent & (1<<Riosize))
- p[Riosize << 1] = ct->io[0].len;
- pcmunmap(slotno, m);
- return 0;
-}
--- a/os/boot/pc/devpccard.c
+++ /dev/null
@@ -1,1606 +1,0 @@
-/*
- cardbus and pcmcia (grmph) support.
-*/
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "error.h"
-#include "io.h"
-
-extern int pciscan(int, Pcidev **);
-
-int (*_pcmspecial)(char *, ISAConf *);
-void (*_pcmspecialclose)(int);
-
-int
-pcmspecial(char *idstr, ISAConf *isa)
-{
- return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1;
-}
-
-void
-pcmspecialclose(int a)
-{
- if (_pcmspecialclose != nil)
- _pcmspecialclose(a);
-}
-
-static ulong
-ioreserve(ulong, int size, int align, char *)
-{
- static ulong isaend = 0x400; /*0xfd00*/
- ulong ioaddr;
-
- if (align)
- isaend = ((isaend + align - 1) / align) * align;
- ioaddr = isaend;
- isaend += size;
- return ioaddr;
-}
-
-#define MAP(x,o) (Rmap + (x)*0x8 + o)
-
-enum {
- TI_vid = 0x104c,
- TI_1131_did = 0xAC15,
- TI_1250_did = 0xAC16,
- TI_1450_did = 0xAC1B,
- TI_1251A_did = 0xAC1D,
- TI_1420_did = 0xAC51,
-
- Ricoh_vid = 0x1180,
- Ricoh_475_did = 0x0475,
- Ricoh_476_did = 0x0476,
- Ricoh_478_did = 0x0478,
-
- O2_vid = 0x1217,
- O2_OZ711M3_did = 0x7134,
-
- Nslots = 4, /* Maximum number of CardBus slots to use */
-
- K = 1024,
- M = K * K,
-
- LegacyAddr = 0x3e0,
- NUMEVENTS = 10,
-
- TI1131xSC = 0x80, // system control
- TI122X_SC_INTRTIE = 1 << 29,
- TI12xxIM = 0x8c, //
- TI1131xCC = 0x91, // card control
- TI113X_CC_RIENB = 1 << 7,
- TI113X_CC_ZVENABLE = 1 << 6,
- TI113X_CC_PCI_IRQ_ENA = 1 << 5,
- TI113X_CC_PCI_IREQ = 1 << 4,
- TI113X_CC_PCI_CSC = 1 << 3,
- TI113X_CC_SPKROUTEN = 1 << 1,
- TI113X_CC_IFG = 1 << 0,
- TI1131xDC = 0x92, // device control
-};
-
-typedef struct Variant Variant;
-struct Variant {
- ushort vid;
- ushort did;
- char *name;
-};
-
-static Variant variant[] = {
-{ Ricoh_vid, Ricoh_475_did, "Ricoh 475 PCI/Cardbus bridge", },
-{ Ricoh_vid, Ricoh_476_did, "Ricoh 476 PCI/Cardbus bridge", },
-{ Ricoh_vid, Ricoh_478_did, "Ricoh 478 PCI/Cardbus bridge", },
-{ TI_vid, TI_1131_did, "TI PCI-1131 Cardbus Controller", },
-{ TI_vid, TI_1250_did, "TI PCI-1250 Cardbus Controller", },
-{ TI_vid, TI_1450_did, "TI PCI-1450 Cardbus Controller", },
-{ TI_vid, TI_1251A_did, "TI PCI-1251A Cardbus Controller", },
-{ TI_vid, TI_1420_did, "TI PCI-1420 Cardbus Controller", },
-{ O2_vid, O2_OZ711M3_did, "O2Micro OZ711M3 MemoryCardBus", },
-};
-
-/* Cardbus registers */
-enum {
- SocketEvent = 0,
- SE_CCD = 3 << 1,
- SE_POWER = 1 << 3,
- SocketMask = 1,
- SocketState = 2,
- SS_CCD = 3 << 1,
- SS_POWER = 1 << 3,
- SS_PC16 = 1 << 4,
- SS_CBC = 1 << 5,
- SS_NOTCARD = 1 << 7,
- SS_BADVCC = 1 << 9,
- SS_5V = 1 << 10,
- SS_3V = 1 << 11,
- SocketForce = 3,
- SocketControl = 4,
- SC_5V = 0x22,
- SC_3V = 0x33,
-};
-
-enum {
- PciPCR_IO = 1 << 0,
- PciPCR_MEM = 1 << 1,
- PciPCR_Master = 1 << 2,
-
- PciPMC = 0xa4,
-
- Nbars = 6,
- Ncmd = 10,
- CBIRQ = 9,
-
- PC16,
- PC32,
-};
-
-enum {
- Ti82365,
- Tpd6710,
- Tpd6720,
- Tvg46x,
-};
-
-/*
- * Intel 82365SL PCIC controller for the PCMCIA or
- * Cirrus Logic PD6710/PD6720 which is mostly register compatible
- */
-enum
-{
- /*
- * registers indices
- */
- Rid= 0x0, /* identification and revision */
- Ris= 0x1, /* interface status */
- Rpc= 0x2, /* power control */
- Foutena= (1<<7), /* output enable */
- Fautopower= (1<<5), /* automatic power switching */
- Fcardena= (1<<4), /* PC card enable */
- Rigc= 0x3, /* interrupt and general control */
- Fiocard= (1<<5), /* I/O card (vs memory) */
- Fnotreset= (1<<6), /* reset if not set */
- FSMIena= (1<<4), /* enable change interrupt on SMI */
- Rcsc= 0x4, /* card status change */
- Rcscic= 0x5, /* card status change interrupt config */
- Fchangeena= (1<<3), /* card changed */
- Fbwarnena= (1<<1), /* card battery warning */
- Fbdeadena= (1<<0), /* card battery dead */
- Rwe= 0x6, /* address window enable */
- Fmem16= (1<<5), /* use A23-A12 to decode address */
- Rio= 0x7, /* I/O control */
- Fwidth16= (1<<0), /* 16 bit data width */
- Fiocs16= (1<<1), /* IOCS16 determines data width */
- Fzerows= (1<<2), /* zero wait state */
- Ftiming= (1<<3), /* timing register to use */
- Riobtm0lo= 0x8, /* I/O address 0 start low byte */
- Riobtm0hi= 0x9, /* I/O address 0 start high byte */
- Riotop0lo= 0xa, /* I/O address 0 stop low byte */
- Riotop0hi= 0xb, /* I/O address 0 stop high byte */
- Riobtm1lo= 0xc, /* I/O address 1 start low byte */
- Riobtm1hi= 0xd, /* I/O address 1 start high byte */
- Riotop1lo= 0xe, /* I/O address 1 stop low byte */
- Riotop1hi= 0xf, /* I/O address 1 stop high byte */
- Rmap= 0x10, /* map 0 */
-
- /*
- * CL-PD67xx extension registers
- */
- Rmisc1= 0x16, /* misc control 1 */
- F5Vdetect= (1<<0),
- Fvcc3V= (1<<1),
- Fpmint= (1<<2),
- Fpsirq= (1<<3),
- Fspeaker= (1<<4),
- Finpack= (1<<7),
- Rfifo= 0x17, /* fifo control */
- Fflush= (1<<7), /* flush fifo */
- Rmisc2= 0x1E, /* misc control 2 */
- Flowpow= (1<<1), /* low power mode */
- Rchipinfo= 0x1F, /* chip information */
- Ratactl= 0x26, /* ATA control */
-
- /*
- * offsets into the system memory address maps
- */
- Mbtmlo= 0x0, /* System mem addr mapping start low byte */
- Mbtmhi= 0x1, /* System mem addr mapping start high byte */
- F16bit= (1<<7), /* 16-bit wide data path */
- Mtoplo= 0x2, /* System mem addr mapping stop low byte */
- Mtophi= 0x3, /* System mem addr mapping stop high byte */
- Ftimer1= (1<<6), /* timer set 1 */
- Mofflo= 0x4, /* Card memory offset address low byte */
- Moffhi= 0x5, /* Card memory offset address high byte */
- Fregactive= (1<<6), /* attribute memory */
-
- /*
- * configuration registers - they start at an offset in attribute
- * memory found in the CIS.
- */
- Rconfig= 0,
- Creset= (1<<7), /* reset device */
- Clevel= (1<<6), /* level sensitive interrupt line */
-};
-
-/*
- * read and crack the card information structure enough to set
- * important parameters like power
- */
-/* cis memory walking */
-typedef struct Cisdat Cisdat;
-struct Cisdat {
- uchar *cisbase;
- int cispos;
- int cisskip;
- int cislen;
-};
-
-typedef struct Pcminfo Pcminfo;
-struct Pcminfo {
- char verstr[512]; /* Version string */
- PCMmap mmap[4]; /* maps, last is always for the kernel */
- ulong conf_addr; /* Config address */
- uchar conf_present; /* Config register present */
- int nctab; /* In use configuration tables */
- PCMconftab ctab[8]; /* Configuration tables */
- PCMconftab *defctab; /* Default conftab */
-
- int port; /* Actual port usage */
- int irq; /* Actual IRQ usage */
-};
-
-typedef struct Cardbus Cardbus;
-struct Cardbus {
- Lock;
- Variant *variant; /* Which CardBus chipset */
- Pcidev *pci; /* The bridge itself */
- ulong *regs; /* Cardbus registers */
- int ltype; /* Legacy type */
- int lindex; /* Legacy port index address */
- int ldata; /* Legacy port data address */
- int lbase; /* Base register for this socket */
-
- int state; /* Current state of card */
- int type; /* Type of card */
- Pcminfo linfo; /* PCMCIA slot info */
-
- int special; /* card is allocated to a driver */
-
- int refs; /* Number of refs to slot */
- Lock refslock; /* inc/dev ref lock */
-};
-
-enum {
- Mshift= 12,
- Mgran= (1<<Mshift), /* granularity of maps */
- Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
-};
-
-static Cardbus cbslots[Nslots];
-static int nslots;
-
-static ulong exponent[8] = {
- 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
-};
-
-static ulong vmant[16] = {
- 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
-};
-
-static ulong mantissa[16] = {
- 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80,
-};
-
-static void cbint(Ureg *, void *);
-static int powerup(Cardbus *);
-static void configure(Cardbus *);
-static void managecard(Cardbus *);
-static void cardmanager(void *);
-static void eject(Cardbus *);
-static void interrupt(Ureg *, void *);
-static void powerdown(Cardbus *cb);
-static void unconfigure(Cardbus *cb);
-
-static void i82365probe(Cardbus *cb, int lindex, int ldata);
-static void i82365configure(Cardbus *cb);
-static PCMmap *isamap(Cardbus *cb, ulong offset, int len, int attr);
-static void isaunmap(PCMmap* m);
-static uchar rdreg(Cardbus *cb, int index);
-static void wrreg(Cardbus *cb, int index, uchar val);
-static int readc(Cisdat *cis, uchar *x);
-static void tvers1(Cardbus *cb, Cisdat *cis, int );
-static void tcfig(Cardbus *cb, Cisdat *cis, int );
-static void tentry(Cardbus *cb, Cisdat *cis, int );
-static int vcode(int volt);
-static int pccard_pcmspecial(char *idstr, ISAConf *isa);
-static void pccard_pcmspecialclose(int slotno);
-
-enum {
- CardDetected,
- CardPowered,
- CardEjected,
- CardConfigured,
-};
-
-static char *messages[] = {
-[CardDetected] "CardDetected",
-[CardPowered] "CardPowered",
-[CardEjected] "CardEjected",
-[CardConfigured] "CardConfigured",
-};
-
-enum {
- SlotEmpty,
- SlotFull,
- SlotPowered,
- SlotConfigured,
-};
-
-static char *states[] = {
-[SlotEmpty] "SlotEmpty",
-[SlotFull] "SlotFull",
-[SlotPowered] "SlotPowered",
-[SlotConfigured] "SlotConfigured",
-};
-
-static void
-engine(Cardbus *cb, int message)
-{
- // print("engine(%d): %s(%s)\n",
- // (int)(cb - cbslots), states[cb->state], messages[message]);
- switch (cb->state) {
- case SlotEmpty:
-
- switch (message) {
- case CardDetected:
- cb->state = SlotFull;
- powerup(cb);
- break;
- case CardEjected:
- break;
- default:
- //print("#Y%d: Invalid message %s in SlotEmpty state\n",
- // (int)(cb - cbslots), messages[message]);
- break;
- }
- break;
-
- case SlotFull:
-
- switch (message) {
- case CardPowered:
- cb->state = SlotPowered;
- configure(cb);
- break;
- case CardEjected:
- cb->state = SlotEmpty;
- powerdown(cb);
- break;
- default:
- //print("#Y%d: Invalid message %s in SlotFull state\n",
- // (int)(cb - cbslots), messages[message]);
- break;
- }
- break;
-
- case SlotPowered:
-
- switch (message) {
- case CardConfigured:
- cb->state = SlotConfigured;
- break;
- case CardEjected:
- cb->state = SlotEmpty;
- unconfigure(cb);
- powerdown(cb);
- break;
- default:
- print("#Y%d: Invalid message %s in SlotPowered state\n",
- (int)(cb - cbslots), messages[message]);
- break;
- }
- break;
-
- case SlotConfigured:
-
- switch (message) {
- case CardEjected:
- cb->state = SlotEmpty;
- unconfigure(cb);
- powerdown(cb);
- break;
- default:
- //print("#Y%d: Invalid message %s in SlotConfigured state\n",
- // (int)(cb - cbslots), messages[message]);
- break;
- }
- break;
- }
-}
-
-void
-devpccardlink(void)
-{
- static int initialized;
- Pcidev *pci;
- int i;
- char *p;
-
- if (initialized)
- return;
- initialized = 1;
-
- if((p=getconf("pccard0")) && strncmp(p, "disabled", 8)==0)
- return;
-
- if(_pcmspecial)
- return;
-
-
- /* Allocate legacy space */
- if (ioalloc(LegacyAddr, 2, 0, "i82365.0") < 0)
- print("#Y: WARNING: Cannot allocate legacy ports\n");
-
- /* Find all CardBus controllers */
- pci = nil;
- while ((pci = pcimatch(pci, 0, 0)) != nil) {
- ulong baddr;
- uchar pin;
- Cardbus *cb;
- int slot;
-
- if(pci->ccrb != 6 || pci->ccru != 7)
- continue;
- for (i = 0; i != nelem(variant); i++)
- if (pci->vid == variant[i].vid && pci->did == variant[i].did)
- break;
- if (i == nelem(variant))
- continue;
-
- /* initialize this slot */
- slot = nslots++;
- cb = &cbslots[slot];
-
- cb->pci = pci;
- cb->variant = &variant[i];
-
- // Set up PCI bus numbers if needed.
- if (pcicfgr8(pci, PciSBN) == 0) {
- static int busbase = 0x20;
-
- pcicfgw8(pci, PciSBN, busbase);
- pcicfgw8(pci, PciUBN, busbase + 2);
- busbase += 3;
- }
-
- // Patch up intl if needed.
- if ((pin = pcicfgr8(pci, PciINTP)) != 0 &&
- (pci->intl == 0xff || pci->intl == 0)) {
- pci->intl = pciipin(nil, pin);
- pcicfgw8(pci, PciINTL, pci->intl);
-
- if (pci->intl == 0xff || pci->intl == 0)
- print("#Y%d: No interrupt?\n", (int)(cb - cbslots));
- }
-
- // Don't you love standards!
- if (pci->vid == TI_vid) {
- if (pci->did <= TI_1131_did) {
- uchar cc;
-
- cc = pcicfgr8(pci, TI1131xCC);
- cc &= ~(TI113X_CC_PCI_IRQ_ENA |
- TI113X_CC_PCI_IREQ |
- TI113X_CC_PCI_CSC |
- TI113X_CC_ZVENABLE);
- cc |= TI113X_CC_PCI_IRQ_ENA |
- TI113X_CC_PCI_IREQ |
- TI113X_CC_SPKROUTEN;
- pcicfgw8(pci, TI1131xCC, cc);
-
- // PCI interrupts only
- pcicfgw8(pci, TI1131xDC,
- pcicfgr8(pci, TI1131xDC) & ~6);
-
- // CSC ints to PCI bus.
- wrreg(cb, Rigc, rdreg(cb, Rigc) | 0x10);
- }
- else if (pci->did == TI_1250_did) {
- print("No support yet for the TI_1250_did, prod pb\n");
- }
- else if (pci->did == TI_1420_did) {
- // Disable Vcc protection
- pcicfgw32(cb->pci, 0x80,
- pcicfgr32(cb->pci, 0x80) | (1 << 21));
- }
-
- pcicfgw16(cb->pci, PciPMC, pcicfgr16(cb->pci, PciPMC) & ~3);
- }
-
- if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {
- int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
-
- baddr = upamalloc(baddr, size, size);
- pcicfgw32(cb->pci, PciBAR0, baddr);
- cb->regs = (ulong *)KADDR(baddr);
- }
- else
- cb->regs = (ulong *)KADDR(upamalloc(baddr, 4096, 0));
- cb->state = SlotEmpty;
-
- /* Don't really know what to do with this... */
- i82365probe(cb, LegacyAddr, LegacyAddr + 1);
-
- print("#Y%ld: %s, %.8ulX intl %d\n", cb - cbslots,
- variant[i].name, baddr, pci->intl);
- }
-
- if (nslots == 0)
- return;
-
- _pcmspecial = pccard_pcmspecial;
- _pcmspecialclose = pccard_pcmspecialclose;
-
- for (i = 0; i != nslots; i++) {
- Cardbus *cb = &cbslots[i];
-
- if ((cb->regs[SocketState] & SE_CCD) == 0)
- engine(cb, CardDetected);
- }
-
- delay(500); /* Allow time for power up */
-
- for (i = 0; i != nslots; i++) {
- Cardbus *cb = &cbslots[i];
-
- if (cb->regs[SocketState] & SE_POWER)
- engine(cb, CardPowered);
-
- /* Ack and enable interrupts on all events */
- //cb->regs[SocketEvent] = cb->regs[SocketEvent];
- //cb->regs[SocketMask] |= 0xF;
- //wrreg(cb, Rcscic, 0xC);
- }
-}
-
-static int
-powerup(Cardbus *cb)
-{
- ulong state;
- ushort bcr;
-
- state = cb->regs[SocketState];
- if (state & SS_PC16) {
-
- // print("#Y%ld: Probed a PC16 card, powering up card\n", cb - cbslots);
- cb->type = PC16;
- memset(&cb->linfo, 0, sizeof(Pcminfo));
-
- /* power up and unreset, wait's are empirical (???) */
- wrreg(cb, Rpc, Fautopower|Foutena|Fcardena);
- delay(300);
- wrreg(cb, Rigc, 0);
- delay(100);
- wrreg(cb, Rigc, Fnotreset);
- delay(500);
-
- return 1;
- }
-
- if (state & SS_CCD)
- return 0;
-
- if (state & SS_NOTCARD) {
- print("#Y%ld: No card inserted\n", cb - cbslots);
- return 0;
- }
-
- if (state & SS_BADVCC) {
- print("#Y%ld: Bad VCC request to card, powering down card!\n",
- cb - cbslots);
- cb->regs[SocketControl] = 0;
- return 0;
- }
-
- if ((state & SS_3V) == 0 && (state & SS_5V) == 0) {
- print("#Y%ld: Unsupported voltage, powering down card!\n",
- cb - cbslots);
- cb->regs[SocketControl] = 0;
- return 0;
- }
-
- //print("#Y%ld: card %spowered at %d volt\n", cb - cbslots,
- // (state & SS_POWER)? "": "not ",
- // (state & SS_3V)? 3: (state & SS_5V)? 5: -1);
-
- /* Power up the card
- * and make sure the secondary bus is not in reset.
- */
- cb->regs[SocketControl] = (state & SS_5V)? SC_5V: SC_3V;
- delay(50);
- bcr = pcicfgr16(cb->pci, PciBCR);
- bcr &= ~0x40;
- pcicfgw16(cb->pci, PciBCR, bcr);
- delay(100);
-
- cb->type = PC32;
-
- return 1;
-}
-
-static void
-powerdown(Cardbus *cb)
-{
- ushort bcr;
-
- if (cb->type == PC16) {
-
- wrreg(cb, Rpc, 0); /* turn off card power */
- wrreg(cb, Rwe, 0); /* no windows */
-
- cb->type = -1;
- return;
- }
-
- bcr = pcicfgr16(cb->pci, PciBCR);
- bcr |= 0x40;
- pcicfgw16(cb->pci, PciBCR, bcr);
- cb->regs[SocketControl] = 0;
- cb->type = -1;
-}
-
-static void
-configure(Cardbus *cb)
-{
- Pcidev *pci;
- ulong size, bar;
- int i, ioindex, memindex, r;
-
- //print("configuring slot %d (%s)\n", (int)(cb - cbslots), states[cb->state]);
- if (cb->state == SlotConfigured)
- return;
- engine(cb, CardConfigured);
-
- delay(50); /* Emperically established */
-
- if (cb->type == PC16) {
- i82365configure(cb);
- return;
- }
-
- /* Scan the CardBus for new PCI devices */
- pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge);
- pci = cb->pci->bridge;
- while (pci) {
- r = pcicfgr16(pci, PciPCR);
- r &= ~(PciPCR_IO|PciPCR_MEM);
- pcicfgw16(pci, PciPCR, r);
-
- /*
- * Treat the found device as an ordinary PCI card.
- * It seems that the CIS is not always present in
- * CardBus cards.
- * XXX, need to support multifunction cards
- */
- memindex = ioindex = 0;
- for (i = 0; i != Nbars; i++) {
-
- if (pci->mem[i].size == 0)
- continue;
- if (pci->mem[i].bar & 1) {
-
- // Allocate I/O space
- if (ioindex > 1) {
- print("#Y%ld: WARNING: Can only configure 2 I/O slots\n", cb - cbslots);
- continue;
- }
- bar = ioreserve(-1, pci->mem[i].size, 0, "cardbus");
- pci->mem[i].bar = bar | 1;
- pcicfgw32(pci, PciBAR0 + i * sizeof(ulong),
- pci->mem[i].bar);
- pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, bar);
- pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8,
- bar + pci->mem[i].size - 1);
- //print("ioindex[%d] %.8uX (%d)\n",
- // ioindex, bar, pci->mem[i].size);
- ioindex++;
- continue;
- }
-
- // Allocating memory space
- if (memindex > 1) {
- print("#Y%ld: WARNING: Can only configure 2 memory slots\n", cb - cbslots);
- continue;
- }
-
- bar = upamalloc(0, pci->mem[i].size, BY2PG);
- pci->mem[i].bar = bar | (pci->mem[i].bar & 0x80);
- pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), pci->mem[i].bar);
- pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, bar);
- pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8,
- bar + pci->mem[i].size - 1);
-
- if (pci->mem[i].bar & 0x80) {
- /* Enable prefetch */
- r = pcicfgr16(cb->pci, PciBCR);
- r |= 1 << (8 + memindex);
- pcicfgw16(cb->pci, PciBCR, r);
- }
-
- //print("memindex[%d] %.8uX (%d)\n",
- // memindex, bar, pci->mem[i].size);
- memindex++;
- }
-
- if ((size = pcibarsize(pci, PciEBAR0)) > 0) {
-
- if (memindex > 1)
- print("#Y%ld: WARNING: Too many memory spaces, not mapping ROM space\n",
- cb - cbslots);
- else {
- pci->rom.bar = upamalloc(0, size, BY2PG);
- pci->rom.size = size;
-
- pcicfgw32(pci, PciEBAR0, pci->rom.bar);
- pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8,
- pci->rom.bar);
- pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8,
- pci->rom.bar + pci->rom.size - 1);
- }
- }
-
- /* Set the basic PCI registers for the device */
- pci->pcr = pcicfgr16(pci, PciPCR);
- pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master;
- pci->cls = 8;
- pci->ltr = 64;
- pcicfgw16(pci, PciPCR, pci->pcr);
- pcicfgw8(pci, PciCLS, pci->cls);
- pcicfgw8(pci, PciLTR, pci->ltr);
-
- if (pcicfgr8(pci, PciINTP)) {
- pci->intl = pcicfgr8(cb->pci, PciINTL);
- pcicfgw8(pci, PciINTL, pci->intl);
-
- /* Route interrupts to INTA#/B# */
- pcicfgw16(cb->pci, PciBCR,
- pcicfgr16(cb->pci, PciBCR) & ~(1 << 7));
- }
-
- pci = pci->list;
- }
-}
-
-static void
-unconfigure(Cardbus *cb)
-{
- Pcidev *pci;
- int i, ioindex, memindex, r;
-
- if (cb->type == PC16) {
- print("#Y%d: Don't know how to unconfigure a PC16 card\n",
- (int)(cb - cbslots));
-
- memset(&cb->linfo, 0, sizeof(Pcminfo));
- return;
- }
-
- pci = cb->pci->bridge;
- if (pci == nil)
- return; /* Not configured */
- cb->pci->bridge = nil;
-
- memindex = ioindex = 0;
- while (pci) {
- Pcidev *_pci;
-
- for (i = 0; i != Nbars; i++) {
- if (pci->mem[i].size == 0)
- continue;
- if (pci->mem[i].bar & 1) {
- iofree(pci->mem[i].bar & ~1);
- pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8,
- (ushort)-1);
- pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0);
- ioindex++;
- continue;
- }
-
- upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size);
- pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
- pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
- r = pcicfgr16(cb->pci, PciBCR);
- r &= ~(1 << (8 + memindex));
- pcicfgw16(cb->pci, PciBCR, r);
- memindex++;
- }
-
- if (pci->rom.bar && memindex < 2) {
- upafree(pci->rom.bar & ~0xF, pci->rom.size);
- pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
- pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
- memindex++;
- }
-
- _pci = pci->list;
- free(_pci);
- pci = _pci;
- }
-}
-
-static void
-i82365configure(Cardbus *cb)
-{
- int this;
- Cisdat cis;
- PCMmap *m;
- uchar type, link;
-
- /*
- * Read all tuples in attribute space.
- */
- m = isamap(cb, 0, 0, 1);
- if(m == 0)
- return;
-
- cis.cisbase = KADDR(m->isa);
- cis.cispos = 0;
- cis.cisskip = 2;
- cis.cislen = m->len;
-
- /* loop through all the tuples */
- for(;;){
- this = cis.cispos;
- if(readc(&cis, &type) != 1)
- break;
- if(type == 0xFF)
- break;
- if(readc(&cis, &link) != 1)
- break;
-
- switch(type){
- default:
- break;
- case 0x15:
- tvers1(cb, &cis, type);
- break;
- case 0x1A:
- tcfig(cb, &cis, type);
- break;
- case 0x1B:
- tentry(cb, &cis, type);
- break;
- }
-
- if(link == 0xFF)
- break;
- cis.cispos = this + (2+link);
- }
- isaunmap(m);
-}
-
-/*
- * look for a card whose version contains 'idstr'
- */
-static int
-pccard_pcmspecial(char *idstr, ISAConf *isa)
-{
- int i, irq;
- PCMconftab *ct, *et;
- Pcminfo *pi;
- Cardbus *cb;
- uchar x, we, *p;
-
- cb = nil;
- for (i = 0; i != nslots; i++) {
- cb = &cbslots[i];
-
- lock(cb);
- if (cb->state == SlotConfigured &&
- cb->type == PC16 &&
- !cb->special &&
- strstr(cb->linfo.verstr, idstr))
- break;
- unlock(cb);
- }
-
- if (i == nslots) {
- // print("#Y: %s not found\n", idstr);
- return -1;
- }
-
- pi = &cb->linfo;
-
- /*
- * configure the PCMslot for IO. We assume very heavily that we can read
- * configuration info from the CIS. If not, we won't set up correctly.
- */
- irq = isa->irq;
- if(irq == 2)
- irq = 9;
-
- et = &pi->ctab[pi->nctab];
- ct = nil;
- for(i = 0; i < isa->nopt; i++){
- int index;
- char *cp;
-
- if(strncmp(isa->opt[i], "index=", 6))
- continue;
- index = strtol(&isa->opt[i][6], &cp, 0);
- if(cp == &isa->opt[i][6] || index >= pi->nctab) {
- unlock(cb);
- print("#Y%d: Cannot find index %d in conf table\n",
- (int)(cb - cbslots), index);
- return -1;
- }
- ct = &pi->ctab[index];
- }
-
- if(ct == nil){
- PCMconftab *t;
-
- /* assume default is right */
- if(pi->defctab)
- ct = pi->defctab;
- else
- ct = pi->ctab;
-
- /* try for best match */
- if(ct->nio == 0
- || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
- for(t = pi->ctab; t < et; t++)
- if(t->nio
- && t->io[0].start == isa->port
- && ((1<<irq) & t->irqs)){
- ct = t;
- break;
- }
- }
- if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
- for(t = pi->ctab; t < et; t++)
- if(t->nio && ((1<<irq) & t->irqs)){
- ct = t;
- break;
- }
- }
- if(ct->nio == 0){
- for(t = pi->ctab; t < et; t++)
- if(t->nio){
- ct = t;
- break;
- }
- }
- }
-
- if(ct == et || ct->nio == 0) {
- unlock(cb);
- print("#Y%d: No configuration?\n", (int)(cb - cbslots));
- return -1;
- }
- if(isa->port == 0 && ct->io[0].start == 0) {
- unlock(cb);
- print("#Y%d: No part or start address\n", (int)(cb - cbslots));
- return -1;
- }
-
- cb->special = 1; /* taken */
-
- /* route interrupts */
- isa->irq = irq;
- wrreg(cb, Rigc, irq | Fnotreset | Fiocard);
-
- /* set power and enable device */
- x = vcode(ct->vpp1);
- wrreg(cb, Rpc, x|Fautopower|Foutena|Fcardena);
-
- /* 16-bit data path */
- if(ct->bit16)
- x = Ftiming|Fiocs16|Fwidth16;
- else
- x = Ftiming;
- if(ct->nio == 2 && ct->io[1].start)
- x |= x<<4;
- wrreg(cb, Rio, x);
-
- /*
- * enable io port map 0
- * the 'top' register value includes the last valid address
- */
- if(isa->port == 0)
- isa->port = ct->io[0].start;
- we = rdreg(cb, Rwe);
- wrreg(cb, Riobtm0lo, isa->port);
- wrreg(cb, Riobtm0hi, isa->port>>8);
- i = isa->port+ct->io[0].len-1;
- wrreg(cb, Riotop0lo, i);
- wrreg(cb, Riotop0hi, i>>8);
- we |= 1<<6;
- if(ct->nio == 2 && ct->io[1].start){
- wrreg(cb, Riobtm1lo, ct->io[1].start);
- wrreg(cb, Riobtm1hi, ct->io[1].start>>8);
- i = ct->io[1].start+ct->io[1].len-1;
- wrreg(cb, Riotop1lo, i);
- wrreg(cb, Riotop1hi, i>>8);
- we |= 1<<7;
- }
- wrreg(cb, Rwe, we);
-
- /* only touch Rconfig if it is present */
- if(pi->conf_present & (1<<Rconfig)){
- PCMmap *m;
-
- /* Reset adapter */
- m = isamap(cb, pi->conf_addr + Rconfig, 1, 1);
- p = KADDR(m->isa + pi->conf_addr + Rconfig - m->ca);
-
- /* set configuration and interrupt type */
- x = ct->index;
- if((ct->irqtype & 0x20)/* && ((ct->irqtype & 0x40)==0 || isa->irq>7)*/)
- x |= Clevel;
- *p = x;
- delay(5);
-
- isaunmap(m);
- }
-
- pi->port = isa->port;
- pi->irq = isa->irq;
- unlock(cb);
-
- print("#Y%d: %s irq %ld, port %lX\n", (int)(cb - cbslots), pi->verstr, isa->irq, isa->port);
- return (int)(cb - cbslots);
-}
-
-static void
-pccard_pcmspecialclose(int slotno)
-{
- Cardbus *cb = &cbslots[slotno];
-
- wrreg(cb, Rwe, 0); /* no windows */
- cb->special = 0;
-}
-
-static int
-xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
-{
- PCMmap *m;
- Cisdat cis;
- int i, l;
- uchar *p;
- uchar type, link, n, c;
- int this, subtype;
- Cardbus *cb = &cbslots[slotno];
-
- m = isamap(cb, 0, 0, attr);
- if(m == 0)
- return -1;
-
- cis.cisbase = KADDR(m->isa);
- cis.cispos = 0;
- cis.cisskip = attr ? 2 : 1;
- cis.cislen = m->len;
-
- /* loop through all the tuples */
- for(i = 0; i < 1000; i++){
- this = cis.cispos;
- if(readc(&cis, &type) != 1)
- break;
- if(type == 0xFF)
- break;
- if(readc(&cis, &link) != 1)
- break;
- if(link == 0xFF)
- break;
-
- n = link;
- if (link > 1 && subtuple != -1) {
- if (readc(&cis, &c) != 1)
- break;
- subtype = c;
- n--;
- } else
- subtype = -1;
-
- if(type == tuple && subtype == subtuple) {
- p = v;
- for(l=0; l<nv && l<n; l++)
- if(readc(&cis, p++) != 1)
- break;
- isaunmap(m);
- return nv;
- }
- cis.cispos = this + (2+link);
- }
- isaunmap(m);
- return -1;
-}
-
-static PCMmap *
-isamap(Cardbus *cb, ulong offset, int len, int attr)
-{
- uchar we, bit;
- PCMmap *m, *nm;
- Pcminfo *pi;
- int i;
- ulong e;
-
- pi = &cb->linfo;
-
- /* convert offset to granularity */
- if(len <= 0)
- len = 1;
- e = ROUND(offset+len, Mgran);
- offset &= Mmask;
- len = e - offset;
-
- /* look for a map that covers the right area */
- we = rdreg(cb, Rwe);
- bit = 1;
- nm = 0;
- for(m = pi->mmap; m < &pi->mmap[nelem(pi->mmap)]; m++){
- if((we & bit))
- if(m->attr == attr)
- if(offset >= m->ca && e <= m->cea){
-
- m->ref++;
- return m;
- }
- bit <<= 1;
- if(nm == 0 && m->ref == 0)
- nm = m;
- }
- m = nm;
- if(m == 0)
- return 0;
-
- /* if isa space isn't big enough, free it and get more */
- if(m->len < len){
- if(m->isa){
- umbfree(m->isa, m->len);
- m->len = 0;
- }
- m->isa = PADDR(umbmalloc(0, len, Mgran));
- if(m->isa == 0){
- print("isamap: out of isa space\n");
- return 0;
- }
- m->len = len;
- }
-
- /* set up new map */
- m->ca = offset;
- m->cea = m->ca + m->len;
- m->attr = attr;
- i = m - pi->mmap;
- bit = 1<<i;
- wrreg(cb, Rwe, we & ~bit); /* disable map before changing it */
- wrreg(cb, MAP(i, Mbtmlo), m->isa>>Mshift);
- wrreg(cb, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
- wrreg(cb, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
- wrreg(cb, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
- offset -= m->isa;
- offset &= (1<<25)-1;
- offset >>= Mshift;
- wrreg(cb, MAP(i, Mofflo), offset);
- wrreg(cb, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
- wrreg(cb, Rwe, we | bit); /* enable map */
- m->ref = 1;
-
- return m;
-}
-
-static void
-isaunmap(PCMmap* m)
-{
- m->ref--;
-}
-
-/*
- * reading and writing card registers
- */
-static uchar
-rdreg(Cardbus *cb, int index)
-{
- outb(cb->lindex, cb->lbase + index);
- return inb(cb->ldata);
-}
-
-static void
-wrreg(Cardbus *cb, int index, uchar val)
-{
- outb(cb->lindex, cb->lbase + index);
- outb(cb->ldata, val);
-}
-
-static int
-readc(Cisdat *cis, uchar *x)
-{
- if(cis->cispos >= cis->cislen)
- return 0;
- *x = cis->cisbase[cis->cisskip*cis->cispos];
- cis->cispos++;
- return 1;
-}
-
-static ulong
-getlong(Cisdat *cis, int size)
-{
- uchar c;
- int i;
- ulong x;
-
- x = 0;
- for(i = 0; i < size; i++){
- if(readc(cis, &c) != 1)
- break;
- x |= c<<(i*8);
- }
- return x;
-}
-
-static void
-tcfig(Cardbus *cb, Cisdat *cis, int )
-{
- uchar size, rasize, rmsize;
- uchar last;
- Pcminfo *pi;
-
- if(readc(cis, &size) != 1)
- return;
- rasize = (size&0x3) + 1;
- rmsize = ((size>>2)&0xf) + 1;
- if(readc(cis, &last) != 1)
- return;
-
- pi = &cb->linfo;
- pi->conf_addr = getlong(cis, rasize);
- pi->conf_present = getlong(cis, rmsize);
-}
-
-static void
-tvers1(Cardbus *cb, Cisdat *cis, int )
-{
- uchar c, major, minor, last;
- int i;
- Pcminfo *pi;
-
- pi = &cb->linfo;
- if(readc(cis, &major) != 1)
- return;
- if(readc(cis, &minor) != 1)
- return;
- last = 0;
- for(i = 0; i < sizeof(pi->verstr) - 1; i++){
- if(readc(cis, &c) != 1)
- return;
- if(c == 0)
- c = ';';
- if(c == '\n')
- c = ';';
- if(c == 0xff)
- break;
- if(c == ';' && last == ';')
- continue;
- pi->verstr[i] = c;
- last = c;
- }
- pi->verstr[i] = 0;
-}
-
-static ulong
-microvolt(Cisdat *cis)
-{
- uchar c;
- ulong microvolts;
- ulong exp;
-
- if(readc(cis, &c) != 1)
- return 0;
- exp = exponent[c&0x7];
- microvolts = vmant[(c>>3)&0xf]*exp;
- while(c & 0x80){
- if(readc(cis, &c) != 1)
- return 0;
- switch(c){
- case 0x7d:
- break; /* high impedence when sleeping */
- case 0x7e:
- case 0x7f:
- microvolts = 0; /* no connection */
- break;
- default:
- exp /= 10;
- microvolts += exp*(c&0x7f);
- }
- }
- return microvolts;
-}
-
-static ulong
-nanoamps(Cisdat *cis)
-{
- uchar c;
- ulong nanoamps;
-
- if(readc(cis, &c) != 1)
- return 0;
- nanoamps = exponent[c&0x7]*vmant[(c>>3)&0xf];
- while(c & 0x80){
- if(readc(cis, &c) != 1)
- return 0;
- if(c == 0x7d || c == 0x7e || c == 0x7f)
- nanoamps = 0;
- }
- return nanoamps;
-}
-
-/*
- * only nominal voltage (feature 1) is important for config,
- * other features must read card to stay in sync.
- */
-static ulong
-power(Cisdat *cis)
-{
- uchar feature;
- ulong mv;
-
- mv = 0;
- if(readc(cis, &feature) != 1)
- return 0;
- if(feature & 1)
- mv = microvolt(cis);
- if(feature & 2)
- microvolt(cis);
- if(feature & 4)
- microvolt(cis);
- if(feature & 8)
- nanoamps(cis);
- if(feature & 0x10)
- nanoamps(cis);
- if(feature & 0x20)
- nanoamps(cis);
- if(feature & 0x40)
- nanoamps(cis);
- return mv/1000000;
-}
-
-static ulong
-ttiming(Cisdat *cis, int scale)
-{
- uchar unscaled;
- ulong nanosecs;
-
- if(readc(cis, &unscaled) != 1)
- return 0;
- nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
- nanosecs = nanosecs * exponent[scale];
- return nanosecs;
-}
-
-static void
-timing(Cisdat *cis, PCMconftab *ct)
-{
- uchar c, i;
-
- if(readc(cis, &c) != 1)
- return;
- i = c&0x3;
- if(i != 3)
- ct->maxwait = ttiming(cis, i); /* max wait */
- i = (c>>2)&0x7;
- if(i != 7)
- ct->readywait = ttiming(cis, i); /* max ready/busy wait */
- i = (c>>5)&0x7;
- if(i != 7)
- ct->otherwait = ttiming(cis, i); /* reserved wait */
-}
-
-static void
-iospaces(Cisdat *cis, PCMconftab *ct)
-{
- uchar c;
- int i, nio;
-
- ct->nio = 0;
- if(readc(cis, &c) != 1)
- return;
-
- ct->bit16 = ((c>>5)&3) >= 2;
- if(!(c & 0x80)){
- ct->io[0].start = 0;
- ct->io[0].len = 1<<(c&0x1f);
- ct->nio = 1;
- return;
- }
-
- if(readc(cis, &c) != 1)
- return;
-
- /*
- * For each of the range descriptions read the
- * start address and the length (value is length-1).
- */
- nio = (c&0xf)+1;
- for(i = 0; i < nio; i++){
- ct->io[i].start = getlong(cis, (c>>4)&0x3);
- ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
- }
- ct->nio = nio;
-}
-
-static void
-irq(Cisdat *cis, PCMconftab *ct)
-{
- uchar c;
-
- if(readc(cis, &c) != 1)
- return;
- ct->irqtype = c & 0xe0;
- if(c & 0x10)
- ct->irqs = getlong(cis, 2);
- else
- ct->irqs = 1<<(c&0xf);
- ct->irqs &= 0xDEB8; /* levels available to card */
-}
-
-static void
-memspace(Cisdat *cis, int asize, int lsize, int host)
-{
- ulong haddress, address, len;
-
- len = getlong(cis, lsize)*256;
- address = getlong(cis, asize)*256;
- USED(len, address);
- if(host){
- haddress = getlong(cis, asize)*256;
- USED(haddress);
- }
-}
-
-static void
-tentry(Cardbus *cb, Cisdat *cis, int )
-{
- uchar c, i, feature;
- PCMconftab *ct;
- Pcminfo *pi;
-
- pi = &cb->linfo;
- if(pi->nctab >= nelem(pi->ctab))
- return;
- if(readc(cis, &c) != 1)
- return;
- ct = &pi->ctab[pi->nctab++];
-
- /* copy from last default config */
- if(pi->defctab)
- *ct = *pi->defctab;
-
- ct->index = c & 0x3f;
-
- /* is this the new default? */
- if(c & 0x40)
- pi->defctab = ct;
-
- /* memory wait specified? */
- if(c & 0x80){
- if(readc(cis, &i) != 1)
- return;
- if(i&0x80)
- ct->memwait = 1;
- }
-
- if(readc(cis, &feature) != 1)
- return;
- switch(feature&0x3){
- case 1:
- ct->vpp1 = ct->vpp2 = power(cis);
- break;
- case 2:
- power(cis);
- ct->vpp1 = ct->vpp2 = power(cis);
- break;
- case 3:
- power(cis);
- ct->vpp1 = power(cis);
- ct->vpp2 = power(cis);
- break;
- default:
- break;
- }
- if(feature&0x4)
- timing(cis, ct);
- if(feature&0x8)
- iospaces(cis, ct);
- if(feature&0x10)
- irq(cis, ct);
- switch((feature>>5)&0x3){
- case 1:
- memspace(cis, 0, 2, 0);
- break;
- case 2:
- memspace(cis, 2, 2, 0);
- break;
- case 3:
- if(readc(cis, &c) != 1)
- return;
- for(i = 0; i <= (c&0x7); i++)
- memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
- break;
- }
-}
-
-static void
-i82365probe(Cardbus *cb, int lindex, int ldata)
-{
- uchar c, id;
- int dev = 0; /* According to the Ricoh spec 00->3F _and_ 80->BF seem
- to be the same socket A (ditto for B). */
-
- outb(lindex, Rid + (dev<<7));
- id = inb(ldata);
- if((id & 0xf0) != 0x80)
- return; /* not a memory & I/O card */
- if((id & 0x0f) == 0x00)
- return; /* no revision number, not possible */
-
- cb->lindex = lindex;
- cb->ldata = ldata;
- cb->ltype = Ti82365;
- cb->lbase = (int)(cb - cbslots) * 0x40;
-
- switch(id){
- case 0x82:
- case 0x83:
- case 0x84:
- /* could be a cirrus */
- outb(cb->lindex, Rchipinfo + (dev<<7));
- outb(cb->ldata, 0);
- c = inb(cb->ldata);
- if((c & 0xc0) != 0xc0)
- break;
- c = inb(cb->ldata);
- if((c & 0xc0) != 0x00)
- break;
- if(c & 0x20){
- cb->ltype = Tpd6720;
- } else {
- cb->ltype = Tpd6710;
- }
- break;
- }
-
- /* if it's not a Cirrus, it could be a Vadem... */
- if(cb->ltype == Ti82365){
- /* unlock the Vadem extended regs */
- outb(cb->lindex, 0x0E + (dev<<7));
- outb(cb->lindex, 0x37 + (dev<<7));
-
- /* make the id register show the Vadem id */
- outb(cb->lindex, 0x3A + (dev<<7));
- c = inb(cb->ldata);
- outb(cb->ldata, c|0xC0);
- outb(cb->lindex, Rid + (dev<<7));
- c = inb(cb->ldata);
- if(c & 0x08)
- cb->ltype = Tvg46x;
-
- /* go back to Intel compatible id */
- outb(cb->lindex, 0x3A + (dev<<7));
- c = inb(cb->ldata);
- outb(cb->ldata, c & ~0xC0);
- }
-}
-
-static int
-vcode(int volt)
-{
- switch(volt){
- case 5:
- return 1;
- case 12:
- return 2;
- default:
- return 0;
- }
-}
--- a/os/boot/pc/devsd.c
+++ /dev/null
@@ -1,631 +1,0 @@
-/*
- * Storage Device.
- */
-#include "u.h"
-#include "mem.h"
-#include "lib.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "error.h"
-
-#include "sd.h"
-#include "fs.h"
-
-#define parttrace 0
-
-
-extern SDifc* sdifc[];
-
-static SDev* sdlist;
-static SDunit** sdunit;
-static int sdnunit;
-static int _sdmask;
-static int cdmask;
-static int sdmask;
-
-enum {
- Rawcmd,
- Rawdata,
- Rawstatus,
-};
-
-void
-sdaddpart(SDunit* unit, char* name, uvlong start, uvlong end)
-{
- SDpart *pp;
- int i, partno;
-
- if(parttrace)
- print("add %d %s %s %lld %lld\n", unit->npart, unit->name, name, start, end);
- /*
- * Check name not already used
- * and look for a free slot.
- */
- if(unit->part != nil){
- partno = -1;
- for(i = 0; i < SDnpart; i++){
- pp = &unit->part[i];
- if(!pp->valid){
- if(partno == -1)
- partno = i;
- break;
- }
- if(strcmp(name, pp->name) == 0){
- if(pp->start == start && pp->end == end){
- if(parttrace)
- print("already present\n");
- return;
- }
- }
- }
- }else{
- if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil){
- if(parttrace)
- print("malloc failed\n");
- return;
- }
- partno = 0;
- }
-
- /*
- * Check there is a free slot and size and extent are valid.
- */
- if(partno == -1 || start > end || end > unit->sectors){
- print("cannot add %s!%s [%llud,%llud) to disk [0,%llud): %s\n",
- unit->name, name, start, end, unit->sectors,
- partno==-1 ? "no free partitions" : "partition boundaries out of range");
- return;
- }
- pp = &unit->part[partno];
- pp->start = start;
- pp->end = end;
- strncpy(pp->name, name, NAMELEN);
- pp->valid = 1;
- unit->npart++;
-}
-
-void
-sddelpart(SDunit* unit, char* name)
-{
- int i;
- SDpart *pp;
-
- if(parttrace)
- print("del %d %s %s\n", unit->npart, unit->name, name);
- /*
- * Look for the partition to delete.
- * Can't delete if someone still has it open.
- * If it's the last valid partition zap the
- * whole table.
- */
- pp = unit->part;
- for(i = 0; i < SDnpart; i++){
- if(strncmp(name, pp->name, NAMELEN) == 0)
- break;
- pp++;
- }
- if(i >= SDnpart)
- return;
- pp->valid = 0;
-
- unit->npart--;
- if(unit->npart == 0){
- free(unit->part);
- unit->part = nil;
- }
-}
-
-static int
-sdinitpart(SDunit* unit)
-{
- unit->sectors = unit->secsize = 0;
- unit->npart = 0;
- if(unit->part){
- free(unit->part);
- unit->part = nil;
- }
-
- if(unit->inquiry[0] & 0xC0)
- return 0;
- switch(unit->inquiry[0] & 0x1F){
- case 0x00: /* DA */
- case 0x04: /* WORM */
- case 0x05: /* CD-ROM */
- case 0x07: /* MO */
- break;
- default:
- return 0;
- }
-
- if(unit->dev->ifc->online == nil || unit->dev->ifc->online(unit) == 0)
- return 0;
- sdaddpart(unit, "data", 0, unit->sectors);
- return 1;
-}
-
-static SDunit*
-sdgetunit(SDev* sdev, int subno)
-{
- int index;
- SDunit *unit;
-
- /*
- * Associate a unit with a given device and sub-unit
- * number on that device.
- * The device will be probed if it has not already been
- * successfully accessed.
- */
- qlock(&sdqlock);
- index = sdev->index+subno;
- unit = sdunit[index];
- if(unit == nil){
- if((unit = malloc(sizeof(SDunit))) == nil){
- qunlock(&sdqlock);
- return nil;
- }
-
- if(sdev->enabled == 0 && sdev->ifc->enable)
- sdev->ifc->enable(sdev);
- sdev->enabled = 1;
-
- snprint(unit->name, NAMELEN, "sd%c%d", sdev->idno, subno);
- unit->subno = subno;
- unit->dev = sdev;
-
- /*
- * No need to lock anything here as this is only
- * called before the unit is made available in the
- * sdunit[] array.
- */
- if(unit->dev->ifc->verify(unit) == 0){
- qunlock(&sdqlock);
- free(unit);
- return nil;
- }
- sdunit[index] = unit;
- }
- qunlock(&sdqlock);
-
- return unit;
-}
-
-static SDunit*
-sdindex2unit(int index)
-{
- SDev *sdev;
-
- /*
- * Associate a unit with a given index into the top-level
- * device directory.
- * The device will be probed if it has not already been
- * successfully accessed.
- */
- for(sdev = sdlist; sdev != nil; sdev = sdev->next){
- if(index >= sdev->index && index < sdev->index+sdev->nunit)
- return sdgetunit(sdev, index-sdev->index);
- }
-
- return nil;
-}
-
-static void
-_sddetach(void)
-{
- SDev *sdev;
-
- for(sdev = sdlist; sdev != nil; sdev = sdev->next){
- if(sdev->enabled == 0)
- continue;
- if(sdev->ifc->disable)
- sdev->ifc->disable(sdev);
- sdev->enabled = 0;
- }
-}
-
-static void
-sddump(void)
-{
- SDev *sdev;
-
- print("sdevs:\n");
- for(sdev = sdlist; sdev != nil; sdev = sdev->next){
- print("sdev %c index %d nunit %d: ",
- sdev->idno, sdev->index, sdev->nunit);
- print("\n");
- }
-}
-
-static int
-_sdinit(void)
-{
- ulong m;
- int i;
- SDev *sdev, *tail;
- SDunit *unit;
-
- /*
- * Probe all configured controllers and make a list
- * of devices found, accumulating a possible maximum number
- * of units attached and marking each device with an index
- * into the linear top-level directory array of units.
- */
- tail = nil;
- for(i = 0; sdifc[i] != nil; i++){
- if((sdev = sdifc[i]->pnp()) == nil)
- continue;
- if(sdlist != nil)
- tail->next = sdev;
- else
- sdlist = sdev;
- for(tail = sdev; tail->next != nil; tail = tail->next){
- tail->index = sdnunit;
- sdnunit += tail->nunit;
- }
- tail->index = sdnunit;
- sdnunit += tail->nunit;
- }
- /*
- * Legacy and option code goes here. This will be hard...
- */
-
- /*
- * The maximum number of possible units is known, allocate
- * placeholders for their datastructures; the units will be
- * probed and structures allocated when attached.
- * Allocate controller names for the different types.
- */
- if(sdnunit == 0)
- return 0;
- if((sdunit = malloc(sdnunit*sizeof(SDunit*))) == nil)
- return 0;
- sddetach = _sddetach;
-
- for(i = 0; sdifc[i] != nil; i++){
- if(sdifc[i]->id)
- sdifc[i]->id(sdlist);
- }
- if (0)
- sddump();
-
- m = 0;
- cdmask = sdmask = 0;
- for(i=0; i<sdnunit && i < 32; i++) {
- unit = sdindex2unit(i);
- if(unit == nil)
- continue;
- sdinitpart(unit);
- partition(unit);
- if(unit->npart > 0){ /* BUG */
- if((unit->inquiry[0] & 0x1F) == 0x05)
- cdmask |= (1<<i);
- else
- sdmask |= (1<<i);
- m |= (1<<i);
- }
- }
-
-//notesdinfo();
- _sdmask = m;
- return m;
-}
-
-int
-cdinit(void)
-{
- if(sdnunit == 0)
- _sdinit();
- return cdmask;
-}
-
-int
-sdinit(void)
-{
- if(sdnunit == 0)
- _sdinit();
- return sdmask;
-}
-
-void
-sdinitdev(int i, char *s)
-{
- SDunit *unit;
-
- unit = sdindex2unit(i);
- strcpy(s, unit->name);
-}
-
-void
-sdprintdevs(int i)
-{
- char *s;
- SDunit *unit;
-
- unit = sdindex2unit(i);
- for(i=0; i<unit->npart; i++){
- s = unit->part[i].name;
- if(strncmp(s, "dos", 3) == 0
- || strncmp(s, "9fat", 4) == 0
- || strncmp(s, "fs", 2) == 0)
- print(" %s!%s", unit->name, s);
- }
-}
-
-SDpart*
-sdfindpart(SDunit *unit, char *name)
-{
- int i;
-
- if(parttrace)
- print("findpart %d %s %s\t\n", unit->npart, unit->name, name);
- for(i=0; i<unit->npart; i++) {
- if(parttrace)
- print("%s...", unit->part[i].name);
- if(strcmp(unit->part[i].name, name) == 0){
- if(parttrace)
- print("\n");
- return &unit->part[i];
- }
- }
- if(parttrace)
- print("not found\n");
- return nil;
-}
-
-typedef struct Scsicrud Scsicrud;
-struct Scsicrud {
- Fs fs;
- vlong offset;
- SDunit *unit;
- SDpart *part;
-};
-
-long
-sdread(Fs *vcrud, void *v, long n)
-{
- Scsicrud *crud;
- long x;
-
- crud = (Scsicrud*)vcrud;
- x = sdbio(crud->unit, crud->part, v, n, crud->offset);
- if(x > 0)
- crud->offset += x;
- return x;
-}
-
-vlong
-sdseek(Fs *vcrud, vlong seek)
-{
- ((Scsicrud*)vcrud)->offset = seek;
- return seek;
-}
-
-void*
-sdgetfspart(int i, char *s, int chatty)
-{
- SDunit *unit;
- SDpart *p;
- Scsicrud *crud;
-
- if(cdmask&(1<<i)){
- if(strcmp(s, "cdboot") != 0)
- return nil;
- }else if(sdmask&(1<<i)){
- if(strcmp(s, "cdboot") == 0)
- return nil;
- }
-
- unit = sdindex2unit(i);
- if((p = sdfindpart(unit, s)) == nil){
- if(chatty)
- print("unknown partition %s!%s\n", unit->name, s);
- return nil;
- }
- if(p->crud == nil) {
- crud = malloc(sizeof(Scsicrud));
- crud->fs.dev = i;
- crud->fs.diskread = sdread;
- crud->fs.diskseek = sdseek;
- // crud->start = 0;
- crud->unit = unit;
- crud->part = p;
- if(dosinit(&crud->fs) < 0 && dosinit(&crud->fs) < 0 && kfsinit(&crud->fs) < 0){
- if(chatty)
- print("partition %s!%s does not contain a DOS or KFS file system\n",
- unit->name, s);
- return nil;
- }
- p->crud = crud;
- }
- return p->crud;
-}
-
-/*
- * Leave partitions around for devsd to pick up.
- * (Needed by boot process; more extensive
- * partitioning is done by termrc or cpurc).
- */
-void
-sdaddconf(int i)
-{
- SDunit *unit;
- SDpart *pp;
-
- unit = sdindex2unit(i);
-
- /*
- * If there were no partitions (just data and partition), don't bother.
- */
- if(unit->npart<= 1 || (unit->npart==2 && strcmp(unit->part[1].name, "partition")==0))
- return;
-
- addconf("%spart=", unit->name);
- for(i=1, pp=&unit->part[i]; i<unit->npart; i++, pp++) /* skip 0, which is "data" */
- addconf("%s%s %lld %lld", i==1 ? "" : "/", pp->name,
- pp->start, pp->end);
- addconf("\n");
-}
-
-int
-sdboot(int dev, char *pname, Boot *b)
-{
- char *file;
- Fs *fs;
-
- if((file = strchr(pname, '!')) == nil) {
- print("syntax is sdC0!partition!file\n");
- return -1;
- }
- *file++ = '\0';
-
- fs = sdgetfspart(dev, pname, 1);
- if(fs == nil)
- return -1;
-
- return fsboot(fs, file, b);
-}
-
-long
-sdbio(SDunit *unit, SDpart *pp, void* va, long len, vlong off)
-{
- long l;
- ulong bno, max, nb, offset;
- static uchar *b;
- char *a;
- static ulong bsz;
-
- a = va;
-memset(a, 0xDA, len);
- qlock(&unit->ctl);
- if(unit->changed){
- qunlock(&unit->ctl);
- return 0;
- }
-
- /*
- * Check the request is within bounds.
- * Removeable drives are locked throughout the I/O
- * in case the media changes unexpectedly.
- * Non-removeable drives are not locked during the I/O
- * to allow the hardware to optimise if it can; this is
- * a little fast and loose.
- * It's assumed that non-removable media parameters
- * (sectors, secsize) can't change once the drive has
- * been brought online.
- */
- bno = (off/unit->secsize) + pp->start;
- nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
- max = SDmaxio/unit->secsize;
- if(nb > max)
- nb = max;
- if(bno+nb > pp->end)
- nb = pp->end - bno;
- if(bno >= pp->end || nb == 0){
- qunlock(&unit->ctl);
- return 0;
- }
- if(!(unit->inquiry[1] & 0x80))
- qunlock(&unit->ctl);
-
- if(bsz < nb*unit->secsize){
- b = malloc(nb*unit->secsize);
- bsz = nb*unit->secsize;
- }
-// b = sdmalloc(nb*unit->secsize);
-// if(b == nil)
-// return 0;
-
- offset = off%unit->secsize;
- if((l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno)) < 0) {
-// sdfree(b);
- return 0;
- }
-
- if(l < offset)
- len = 0;
- else if(len > l - offset)
- len = l - offset;
- if(len)
- memmove(a, b+offset, len);
-// sdfree(b);
-
- if(unit->inquiry[1] & 0x80)
- qunlock(&unit->ctl);
-
- return len;
-}
-
-#ifdef DMA
-long
-sdrio(SDreq *r, void* a, long n)
-{
- if(n >= SDmaxio || n < 0)
- return 0;
-
- r->data = nil;
- if(n){
- if((r->data = malloc(n)) == nil)
- return 0;
- if(r->write)
- memmove(r->data, a, n);
- }
- r->dlen = n;
-
- if(r->unit->dev->ifc->rio(r) != SDok){
-// cgascreenputs("1", 1);
- if(r->data != nil){
- sdfree(r->data);
- r->data = nil;
- }
- return 0;
- }
-// cgascreenputs("2", 1);
-
- if(!r->write && r->rlen > 0)
- memmove(a, r->data, r->rlen);
-// cgascreenputs("3", 1);
- if(r->data != nil){
- sdfree(r->data);
- r->data = nil;
- }
-
-// cgascreenputs("4", 1);
- return r->rlen;
-}
-#endif /* DMA */
-
-void
-sleep(void*, int (*fn)(void*), void *v)
-{
- int x;
- x = spllo();
- while(!fn(v))
- ;
- splx(x);
- return;
-}
-
-void
-tsleep(void*, int (*fn)(void*), void *v, int msec)
-{
- int x;
- ulong start;
-
- x = spllo();
- for(start = m->ticks; TK2MS(m->ticks - start) < msec
- && !fn(v); )
- ;
- splx(x);
- return;
-}
-
-void*
-sdmalloc(void *p, ulong sz)
-{
- if(p != nil) {
- memset(p, 0, sz);
- return p;
- }
- return malloc(sz);
-}
--- a/os/boot/pc/dma.c
+++ /dev/null
@@ -1,245 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-typedef struct DMAport DMAport;
-typedef struct DMA DMA;
-typedef struct DMAxfer DMAxfer;
-
-enum
-{
- /*
- * the byte registers for DMA0 are all one byte apart
- */
- Dma0= 0x00,
- Dma0status= Dma0+0x8, /* status port */
- Dma0reset= Dma0+0xD, /* reset port */
-
- /*
- * the byte registers for DMA1 are all two bytes apart (why?)
- */
- Dma1= 0xC0,
- Dma1status= Dma1+2*0x8, /* status port */
- Dma1reset= Dma1+2*0xD, /* reset port */
-};
-
-/*
- * state of a dma transfer
- */
-struct DMAxfer
-{
- ulong bpa; /* bounce buffer physical address */
- void* bva; /* bounce buffer virtual address */
- void* va; /* virtual address destination/src */
- long len; /* bytes to be transferred */
- int isread;
-};
-
-/*
- * the dma controllers. the first half of this structure specifies
- * the I/O ports used by the DMA controllers.
- */
-struct DMAport
-{
- uchar addr[4]; /* current address (4 channels) */
- uchar count[4]; /* current count (4 channels) */
- uchar page[4]; /* page registers (4 channels) */
- uchar cmd; /* command status register */
- uchar req; /* request registers */
- uchar sbm; /* single bit mask register */
- uchar mode; /* mode register */
- uchar cbp; /* clear byte pointer */
- uchar mc; /* master clear */
- uchar cmask; /* clear mask register */
- uchar wam; /* write all mask register bit */
-};
-
-struct DMA
-{
- DMAport;
- int shift;
- Lock;
- DMAxfer x[4];
-};
-
-DMA dma[2] = {
- { 0x00, 0x02, 0x04, 0x06,
- 0x01, 0x03, 0x05, 0x07,
- 0x87, 0x83, 0x81, 0x82,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0 },
-
- { 0xc0, 0xc4, 0xc8, 0xcc,
- 0xc2, 0xc6, 0xca, 0xce,
- 0x8f, 0x8b, 0x89, 0x8a,
- 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
- 1 },
-};
-
-/*
- * DMA must be in the first 16MB. This gets called early by the
- * initialisation routines of any devices which require DMA to ensure
- * the allocated bounce buffers are below the 16MB limit.
- */
-void
-dmainit(int chan)
-{
- DMA *dp;
- DMAxfer *xp;
- ulong v;
- static int once;
-
- if(once == 0){
-// if(ioalloc(0x00, 0x10, 0, "dma") < 0
-// || ioalloc(0x80, 0x10, 0, "dma") < 0
-// || ioalloc(0xd0, 0x10, 0, "dma") < 0)
-// panic("dmainit");
- outb(dma[0].mc, 0);
- outb(dma[1].mc, 0);
- outb(dma[0].cmask, 0);
- outb(dma[1].cmask, 0);
- outb(dma[1].mode, 0xC0);
- once = 1;
- }
-
- dp = &dma[(chan>>2)&1];
- chan = chan & 3;
- xp = &dp->x[chan];
- if(xp->bva != nil)
- return;
-
- v = (ulong)xalloc(BY2PG+BY2PG);
- if(v == 0 || PADDR(v) >= 16*MB){
- print("dmainit: chan %d: 0x%luX out of range\n", chan, v);
- xfree((void*)v);
- v = 0;
- }
- xp->bva = (void*)ROUND(v, BY2PG);
- xp->bpa = PADDR(xp->bva);
- xp->len = 0;
- xp->isread = 0;
-}
-
-/*
- * setup a dma transfer. if the destination is not in kernel
- * memory, allocate a page for the transfer.
- *
- * we assume BIOS has set up the command register before we
- * are booted.
- *
- * return the updated transfer length (we can't transfer across 64k
- * boundaries)
- */
-long
-dmasetup(int chan, void *va, long len, int isread)
-{
- DMA *dp;
- ulong pa;
- uchar mode;
- DMAxfer *xp;
-
- dp = &dma[(chan>>2)&1];
- chan = chan & 3;
- xp = &dp->x[chan];
-
- /*
- * if this isn't kernel memory or crossing 64k boundary or above 16 meg
- * use the allocated low memory page.
- */
- pa = PADDR(va);
- if((((ulong)va)&0xF0000000) != KZERO
- || (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)
- || pa > 16*MB) {
- if(xp->bva == nil)
- return -1;
- if(len > BY2PG)
- len = BY2PG;
- if(!isread)
- memmove(xp->bva, va, len);
- xp->va = va;
- xp->len = len;
- xp->isread = isread;
- pa = xp->bpa;
- }
- else
- xp->len = 0;
-
- /*
- * this setup must be atomic
- */
- ilock(dp);
- mode = (isread ? 0x44 : 0x48) | chan;
- outb(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */
- outb(dp->page[chan], pa>>16);
- outb(dp->cbp, 0); /* set count & address to their first byte */
- outb(dp->addr[chan], pa>>dp->shift); /* set address */
- outb(dp->addr[chan], pa>>(8+dp->shift));
- outb(dp->count[chan], (len>>dp->shift)-1); /* set count */
- outb(dp->count[chan], ((len>>dp->shift)-1)>>8);
- outb(dp->sbm, chan); /* enable the channel */
- iunlock(dp);
-
- return len;
-}
-
-int
-dmadone(int chan)
-{
- DMA *dp;
-
- dp = &dma[(chan>>2)&1];
- chan = chan & 3;
-
- return inb(dp->cmd) & (1<<chan);
-}
-
-/*
- * this must be called after a dma has been completed.
- *
- * if a page has been allocated for the dma,
- * copy the data into the actual destination
- * and free the page.
- */
-void
-dmaend(int chan)
-{
- DMA *dp;
- DMAxfer *xp;
-
- dp = &dma[(chan>>2)&1];
- chan = chan & 3;
-
- /*
- * disable the channel
- */
- ilock(dp);
- outb(dp->sbm, 4|chan);
- iunlock(dp);
-
- xp = &dp->x[chan];
- if(xp->len == 0 || !xp->isread)
- return;
-
- /*
- * copy out of temporary page
- */
- memmove(xp->va, xp->bva, xp->len);
- xp->len = 0;
-}
-
-/*
-int
-dmacount(int chan)
-{
- int retval;
- DMA *dp;
-
- dp = &dma[(chan>>2)&1];
- outb(dp->cbp, 0);
- retval = inb(dp->count[chan]);
- retval |= inb(dp->count[chan]) << 8;
- return((retval<<dp->shift)+1);
-}
- */
--- a/os/boot/pc/dosboot.c
+++ /dev/null
@@ -1,582 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "fs.h"
-
-struct Dosboot{
- uchar magic[3];
- uchar version[8];
- uchar sectsize[2];
- uchar clustsize;
- uchar nresrv[2];
- uchar nfats;
- uchar rootsize[2];
- uchar volsize[2];
- uchar mediadesc;
- uchar fatsize[2];
- uchar trksize[2];
- uchar nheads[2];
- uchar nhidden[4];
- uchar bigvolsize[4];
-/* fat 32 */
- uchar bigfatsize[4];
- uchar extflags[2];
- uchar fsversion[2];
- uchar rootdirstartclust[4];
- uchar fsinfosect[2];
- uchar backupbootsect[2];
-/* ???
- uchar driveno;
- uchar reserved0;
- uchar bootsig;
- uchar volid[4];
- uchar label[11];
- uchar reserved1[8];
-*/
-};
-
-struct Dosdir{
- uchar name[8];
- uchar ext[3];
- uchar attr;
- uchar lowercase;
- uchar hundredth;
- uchar ctime[2];
- uchar cdate[2];
- uchar adate[2];
- uchar highstart[2];
- uchar mtime[2];
- uchar mdate[2];
- uchar start[2];
- uchar length[4];
-};
-
-#define DOSRONLY 0x01
-#define DOSHIDDEN 0x02
-#define DOSSYSTEM 0x04
-#define DOSVLABEL 0x08
-#define DOSDIR 0x10
-#define DOSARCH 0x20
-
-/*
- * predeclared
- */
-static void bootdump(Dosboot*);
-static void setname(Dosfile*, char*);
-
-/*
- * debugging
- */
-#define chatty 0
-#define chat if(chatty)print
-
-/*
- * block io buffers
- */
-enum
-{
- Nbio= 16,
-};
-typedef struct Clustbuf Clustbuf;
-struct Clustbuf
-{
- int age;
- long sector;
- uchar *iobuf;
- Dos *dos;
- int size;
-};
-Clustbuf bio[Nbio];
-
-/*
- * get an io block from an io buffer
- */
-Clustbuf*
-getclust(Dos *dos, long sector)
-{
- Fs *fs;
- Clustbuf *p, *oldest;
- int size;
-
- chat("getclust @ %ld\n", sector);
-
- /*
- * if we have it, just return it
- */
- for(p = bio; p < &bio[Nbio]; p++){
- if(sector == p->sector && dos == p->dos){
- p->age = m->ticks;
- chat("getclust %ld in cache\n", sector);
- return p;
- }
- }
-
- /*
- * otherwise, reuse the oldest entry
- */
- oldest = bio;
- for(p = &bio[1]; p < &bio[Nbio]; p++){
- if(p->age <= oldest->age)
- oldest = p;
- }
- p = oldest;
-
- /*
- * make sure the buffer is big enough
- */
- size = dos->clustsize*dos->sectsize;
- if(p->iobuf==0 || p->size < size)
- p->iobuf = ialloc(size, 0);
- p->size = size;
-
- /*
- * read in the cluster
- */
- fs = (Fs*)dos;
- chat("getclust addr %lud %p %p %p\n", (ulong)((sector+dos->start)*(vlong)dos->sectsize),
- fs, fs->diskseek, fs->diskread);
- if(fs->diskseek(fs, (sector+dos->start)*(vlong)dos->sectsize) < 0){
- chat("can't seek block\n");
- return 0;
- }
- if(fs->diskread(fs, p->iobuf, size) != size){
- chat("can't read block\n");
- return 0;
- }
-
- p->age = m->ticks;
- p->dos = dos;
- p->sector = sector;
- chat("getclust %ld read\n", sector);
- return p;
-}
-
-/*
- * walk the fat one level ( n is a current cluster number ).
- * return the new cluster number or -1 if no more.
- */
-static long
-fatwalk(Dos *dos, int n)
-{
- ulong k, sect;
- Clustbuf *p;
- int o;
-
- chat("fatwalk %d\n", n);
-
- if(n < 2 || n >= dos->fatclusters)
- return -1;
-
- switch(dos->fatbits){
- case 12:
- k = (3*n)/2; break;
- case 16:
- k = 2*n; break;
- case 32:
- k = 4*n; break;
- default:
- return -1;
- }
- if(k >= dos->fatsize*dos->sectsize)
- panic("getfat");
-
- sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
- o = k%(dos->sectsize*dos->clustsize);
- p = getclust(dos, sect);
- k = p->iobuf[o++];
- if(o >= dos->sectsize*dos->clustsize){
- p = getclust(dos, sect+dos->clustsize);
- o = 0;
- }
- k |= p->iobuf[o++]<<8;
- if(dos->fatbits == 12){
- if(n&1)
- k >>= 4;
- else
- k &= 0xfff;
- if(k >= 0xff8)
- k = -1;
- }
- else if (dos->fatbits == 32){
- if(o >= dos->sectsize*dos->clustsize){
- p = getclust(dos, sect+dos->clustsize);
- o = 0;
- }
- k |= p->iobuf[o++]<<16;
- k |= p->iobuf[o]<<24;
- if (k >= 0xfffffff8)
- k = -1;
- }
- else
- k = k < 0xfff8 ? k : -1;
- chat("fatwalk %d -> %lud\n", n, k);
- return k;
-}
-
-/*
- * map a file's logical cluster address to a physical sector address
- */
-static long
-fileaddr(Dosfile *fp, long ltarget)
-{
- Dos *dos = fp->dos;
- long l;
- long p;
-
- chat("fileaddr %8.8s %ld\n", fp->name, ltarget);
- /*
- * root directory is contiguous and easy (unless FAT32)
- */
- if(fp->pstart == 0 && dos->rootsize != 0) {
- if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
- return -1;
- l = dos->rootaddr + ltarget*dos->clustsize;
- chat("fileaddr %ld -> %ld\n", ltarget, l);
- return l;
- }
-
- /*
- * anything else requires a walk through the fat
- */
- if(ltarget >= fp->lcurrent && fp->pcurrent){
- /* start at the currrent point */
- l = fp->lcurrent;
- p = fp->pcurrent;
- } else {
- /* go back to the beginning */
- l = 0;
- p = fp->pstart;
- }
- while(l != ltarget){
- /* walk the fat */
- p = fatwalk(dos, p);
- if(p < 0)
- return -1;
- l++;
- }
- fp->lcurrent = l;
- fp->pcurrent = p;
-
- /*
- * clusters start at 2 instead of 0 (why? - presotto)
- */
- l = dos->dataaddr + (p-2)*dos->clustsize;
- chat("fileaddr %ld -> %ld\n", ltarget, l);
- return l;
-}
-
-/*
- * read from a dos file
- */
-long
-dosread(Dosfile *fp, void *a, long n)
-{
- long addr;
- long rv;
- int i;
- int off;
- Clustbuf *p;
- uchar *from, *to;
-
- if((fp->attr & DOSDIR) == 0){
- if(fp->offset >= fp->length)
- return 0;
- if(fp->offset+n > fp->length)
- n = fp->length - fp->offset;
- }
-
- to = a;
- for(rv = 0; rv < n; rv+=i){
- /*
- * read the cluster
- */
- addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
- if(addr < 0)
- return -1;
- p = getclust(fp->dos, addr);
- if(p == 0)
- return -1;
-
- /*
- * copy the bytes we need
- */
- off = fp->offset % fp->dos->clustbytes;
- from = &p->iobuf[off];
- i = n - rv;
- if(i > fp->dos->clustbytes - off)
- i = fp->dos->clustbytes - off;
- memmove(to, from, i);
- to += i;
- fp->offset += i;
- }
-
- return rv;
-}
-
-/*
- * walk a directory returns
- * -1 if something went wrong
- * 0 if not found
- * 1 if found
- */
-int
-doswalk(File *f, char *name)
-{
- Dosdir d;
- long n;
- Dosfile *file;
-
- chat("doswalk %s\n", name);
-
- file = &f->dos;
-
- if((file->attr & DOSDIR) == 0){
- chat("walking non-directory!\n");
- return -1;
- }
-
- setname(file, name);
-
- file->offset = 0; /* start at the beginning */
- while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
- chat("comparing to %8.8s.%3.3s\n", (char*)d.name, (char*)d.ext);
- if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
- continue;
- if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
- continue;
- if(d.attr & DOSVLABEL){
- chat("%8.8s.%3.3s is a LABEL\n", (char*)d.name, (char*)d.ext);
- continue;
- }
- file->attr = d.attr;
- file->pstart = GSHORT(d.start);
- if (file->dos->fatbits == 32)
- file->pstart |= GSHORT(d.highstart) << 16;
- file->length = GLONG(d.length);
- file->pcurrent = 0;
- file->lcurrent = 0;
- file->offset = 0;
- return 1;
- }
- return n >= 0 ? 0 : -1;
-}
-
-/*
- * instructions that boot blocks can start with
- */
-#define JMPSHORT 0xeb
-#define JMPNEAR 0xe9
-
-/*
- * read in a segment
- */
-long
-dosreadseg(File *f, void *va, long len)
-{
- char *a;
- long n, sofar;
- Dosfile *fp;
-
- fp = &f->dos;
- a = va;
- for(sofar = 0; sofar < len; sofar += n){
- n = 8*1024;
- if(len - sofar < n)
- n = len - sofar;
- n = dosread(fp, a + sofar, n);
- if(n <= 0)
- break;
- print(".");
- }
- return sofar;
-}
-
-int
-dosinit(Fs *fs)
-{
- Clustbuf *p;
- Dosboot *b;
- int i;
- Dos *dos;
- Dosfile *root;
-
-chat("dosinit0 %p %p %p\n", fs, fs->diskseek, fs->diskread);
-
- dos = &fs->dos;
- /* defaults till we know better */
- dos->sectsize = 512;
- dos->clustsize = 1;
-
- /* get first sector */
- p = getclust(dos, 0);
- if(p == 0){
- chat("can't read boot block\n");
- return -1;
- }
-
-chat("dosinit0a\n");
-
- p->dos = 0;
- b = (Dosboot *)p->iobuf;
- if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
- chat("no dos file system %x %x %x %x\n",
- b->magic[0], b->magic[1], b->magic[2], b->magic[3]);
- return -1;
- }
-
- if(chatty)
- bootdump(b);
-
- if(b->clustsize == 0) {
-unreasonable:
- if(chatty){
- print("unreasonable FAT BPB: ");
- for(i=0; i<3+8+2+1; i++)
- print(" %.2ux", p->iobuf[i]);
- print("\n");
- }
- return -1;
- }
-
-chat("dosinit1\n");
-
- /*
- * Determine the systems' wondrous properties.
- * There are heuristics here, but there's no real way
- * of knowing if this is a reasonable FAT.
- */
- dos->fatbits = 0;
- dos->sectsize = GSHORT(b->sectsize);
- if(dos->sectsize & 0xFF)
- goto unreasonable;
- dos->clustsize = b->clustsize;
- dos->clustbytes = dos->sectsize*dos->clustsize;
- dos->nresrv = GSHORT(b->nresrv);
- dos->nfats = b->nfats;
- dos->fatsize = GSHORT(b->fatsize);
- dos->rootsize = GSHORT(b->rootsize);
- dos->volsize = GSHORT(b->volsize);
- if(dos->volsize == 0)
- dos->volsize = GLONG(b->bigvolsize);
- dos->mediadesc = b->mediadesc;
- if(dos->fatsize == 0) {
- chat("fat32\n");
- dos->rootsize = 0;
- dos->fatsize = GLONG(b->bigfatsize);
- dos->fatbits = 32;
- }
- dos->fataddr = dos->nresrv;
- if (dos->rootsize == 0) {
- dos->rootaddr = 0;
- dos->rootclust = GLONG(b->rootdirstartclust);
- dos->dataaddr = dos->fataddr + dos->nfats*dos->fatsize;
- } else {
- dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
- i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
- i = i/dos->sectsize;
- dos->dataaddr = dos->rootaddr + i;
- }
- dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
- if(dos->fatbits != 32) {
- if(dos->fatclusters < 4087)
- dos->fatbits = 12;
- else
- dos->fatbits = 16;
- }
- dos->freeptr = 2;
-
- if(dos->clustbytes < 512 || dos->clustbytes > 64*1024)
- goto unreasonable;
-
-chat("dosinit2\n");
-
- /*
- * set up the root
- */
-
- fs->root.fs = fs;
- root = &fs->root.dos;
- root->dos = dos;
- root->pstart = dos->rootsize == 0 ? dos->rootclust : 0;
- root->pcurrent = root->lcurrent = 0;
- root->offset = 0;
- root->attr = DOSDIR;
- root->length = dos->rootsize*sizeof(Dosdir);
-
-chat("dosinit3\n");
-
- fs->read = dosreadseg;
- fs->walk = doswalk;
- return 0;
-}
-
-static void
-bootdump(Dosboot *b)
-{
- if(chatty == 0)
- return;
- print("magic: 0x%2.2x 0x%2.2x 0x%2.2x ",
- b->magic[0], b->magic[1], b->magic[2]);
- print("version: \"%8.8s\"\n", (char*)b->version);
- print("sectsize: %d ", GSHORT(b->sectsize));
- print("allocsize: %d ", b->clustsize);
- print("nresrv: %d ", GSHORT(b->nresrv));
- print("nfats: %d\n", b->nfats);
- print("rootsize: %d ", GSHORT(b->rootsize));
- print("volsize: %d ", GSHORT(b->volsize));
- print("mediadesc: 0x%2.2x\n", b->mediadesc);
- print("fatsize: %d ", GSHORT(b->fatsize));
- print("trksize: %d ", GSHORT(b->trksize));
- print("nheads: %d ", GSHORT(b->nheads));
- print("nhidden: %d ", GLONG(b->nhidden));
- print("bigvolsize: %d\n", GLONG(b->bigvolsize));
-/*
- print("driveno: %d\n", b->driveno);
- print("reserved0: 0x%2.2x\n", b->reserved0);
- print("bootsig: 0x%2.2x\n", b->bootsig);
- print("volid: 0x%8.8x\n", GLONG(b->volid));
- print("label: \"%11.11s\"\n", b->label);
-*/
-}
-
-
-/*
- * set up a dos file name
- */
-static void
-setname(Dosfile *fp, char *from)
-{
- char *to;
-
- to = fp->name;
- for(; *from && to-fp->name < 8; from++, to++){
- if(*from == '.'){
- from++;
- break;
- }
- if(*from >= 'a' && *from <= 'z')
- *to = *from + 'A' - 'a';
- else
- *to = *from;
- }
- while(to - fp->name < 8)
- *to++ = ' ';
-
- /* from might be 12345678.123: don't save the '.' in ext */
- if(*from == '.')
- from++;
-
- to = fp->ext;
- for(; *from && to-fp->ext < 3; from++, to++){
- if(*from >= 'a' && *from <= 'z')
- *to = *from + 'A' - 'a';
- else
- *to = *from;
- }
- while(to-fp->ext < 3)
- *to++ = ' ';
-
- chat("name is %8.8s.%3.3s\n", fp->name, fp->ext);
-}
--- a/os/boot/pc/dosfs.h
+++ /dev/null
@@ -1,62 +1,0 @@
-typedef struct Dosboot Dosboot;
-typedef struct Dos Dos;
-typedef struct Dosdir Dosdir;
-typedef struct Dosfile Dosfile;
-typedef struct Dospart Dospart;
-
-struct Dospart
-{
- uchar flag; /* active flag */
- uchar shead; /* starting head */
- uchar scs[2]; /* starting cylinder/sector */
- uchar type; /* partition type */
- uchar ehead; /* ending head */
- uchar ecs[2]; /* ending cylinder/sector */
- uchar start[4]; /* starting sector */
- uchar len[4]; /* length in sectors */
-};
-
-#define FAT12 0x01
-#define FAT16 0x04
-#define EXTEND 0x05
-#define FATHUGE 0x06
-#define FAT32 0x0b
-#define FAT32X 0x0c
-#define EXTHUGE 0x0f
-#define DMDDO 0x54
-#define PLAN9 0x39
-#define LEXTEND 0x85
-
-struct Dosfile{
- Dos *dos; /* owning dos file system */
- char name[8];
- char ext[3];
- uchar attr;
- long length;
- long pstart; /* physical start cluster address */
- long pcurrent; /* physical current cluster address */
- long lcurrent; /* logical current cluster address */
- long offset;
-};
-
-struct Dos{
- long start; /* start of file system */
- int sectsize; /* in bytes */
- int clustsize; /* in sectors */
- int clustbytes; /* in bytes */
- int nresrv; /* sectors */
- int nfats; /* usually 2 */
- int rootsize; /* number of entries */
- int volsize; /* in sectors */
- int mediadesc;
- int fatsize; /* in sectors */
- int fatclusters;
- int fatbits; /* 12 or 16 */
- long fataddr; /* sector number */
- long rootaddr;
- long rootclust;
- long dataaddr;
- long freeptr;
-};
-
-extern int dosinit(Fs*);
--- a/os/boot/pc/eipfmt.c
+++ /dev/null
@@ -1,145 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "ip.h"
-
-
-enum
-{
- IPaddrlen= 16,
- IPv4addrlen= 4,
- IPv4off= 12,
- IPllen= 4,
-};
-extern int fmtstrcpy(Fmt*, char*);
-
-
-/*
- * prefix of all v4 addresses
- */
-uchar v4prefix[IPaddrlen] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0xff, 0xff,
- 0, 0, 0, 0
-};
-
-enum
-{
- Isprefix= 16,
-};
-
-uchar prefixvals[256] =
-{
-[0x00] 0 | Isprefix,
-[0x80] 1 | Isprefix,
-[0xC0] 2 | Isprefix,
-[0xE0] 3 | Isprefix,
-[0xF0] 4 | Isprefix,
-[0xF8] 5 | Isprefix,
-[0xFC] 6 | Isprefix,
-[0xFE] 7 | Isprefix,
-[0xFF] 8 | Isprefix,
-};
-
-void
-hnputl(void *p, uint v)
-{
- uchar *a;
-
- a = p;
- a[0] = v>>24;
- a[1] = v>>16;
- a[2] = v>>8;
- a[3] = v;
-}
-
-int
-eipfmt(Fmt *f)
-{
- char buf[5*8];
- static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
- static char *ifmt = "%d.%d.%d.%d";
- uchar *p, ip[16];
- ulong *lp;
- ushort s;
- int i, j, n, eln, eli;
-
- switch(f->r) {
- case 'E': /* Ethernet address */
- p = va_arg(f->args, uchar*);
- snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
- return fmtstrcpy(f, buf);
-
- case 'I': /* Ip address */
- p = va_arg(f->args, uchar*);
-common:
- if(memcmp(p, v4prefix, 12) == 0){
- snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]);
- return fmtstrcpy(f, buf);
- }
-
- /* find longest elision */
- eln = eli = -1;
- for(i = 0; i < 16; i += 2){
- for(j = i; j < 16; j += 2)
- if(p[j] != 0 || p[j+1] != 0)
- break;
- if(j > i && j - i > eln){
- eli = i;
- eln = j - i;
- }
- }
-
- /* print with possible elision */
- n = 0;
- for(i = 0; i < 16; i += 2){
- if(i == eli){
- n += sprint(buf+n, "::");
- i += eln;
- if(i >= 16)
- break;
- } else if(i != 0)
- n += sprint(buf+n, ":");
- s = (p[i]<<8) + p[i+1];
- n += sprint(buf+n, "%ux", s);
- }
- return fmtstrcpy(f, buf);
-
- case 'i': /* v6 address as 4 longs */
- lp = va_arg(f->args, ulong*);
- for(i = 0; i < 4; i++)
- hnputl(ip+4*i, *lp++);
- p = ip;
- goto common;
-
- case 'V': /* v4 ip address */
- p = va_arg(f->args, uchar*);
- snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]);
- return fmtstrcpy(f, buf);
-
- case 'M': /* ip mask */
- p = va_arg(f->args, uchar*);
-
- /* look for a prefix mask */
- for(i = 0; i < 16; i++)
- if(p[i] != 0xff)
- break;
- if(i < 16){
- if((prefixvals[p[i]] & Isprefix) == 0)
- goto common;
- for(j = i+1; j < 16; j++)
- if(p[j] != 0)
- goto common;
- n = 8*i + (prefixvals[p[i]] & ~Isprefix);
- } else
- n = 8*16;
-
- /* got one, use /xx format */
- snprint(buf, sizeof buf, "/%d", n);
- return fmtstrcpy(f, buf);
- }
- return fmtstrcpy(f, "(eipfmt)");
-}
--- a/os/boot/pc/error.h
+++ /dev/null
@@ -1,58 +1,0 @@
-extern char Enoerror[]; /* no error */
-extern char Emount[]; /* inconsistent mount */
-extern char Eunmount[]; /* not mounted */
-extern char Eunion[]; /* not in union */
-extern char Emountrpc[]; /* mount rpc error */
-extern char Eshutdown[]; /* mounted device shut down */
-extern char Enocreate[]; /* mounted directory forbids creation */
-extern char Enonexist[]; /* file does not exist */
-extern char Eexist[]; /* file already exists */
-extern char Ebadsharp[]; /* unknown device in # filename */
-extern char Enotdir[]; /* not a directory */
-extern char Eisdir[]; /* file is a directory */
-extern char Ebadchar[]; /* bad character in file name */
-extern char Efilename[]; /* file name syntax */
-extern char Eperm[]; /* permission denied */
-extern char Ebadusefd[]; /* inappropriate use of fd */
-extern char Ebadarg[]; /* bad arg in system call */
-extern char Einuse[]; /* device or object already in use */
-extern char Eio[]; /* i/o error */
-extern char Etoobig[]; /* read or write too large */
-extern char Etoosmall[]; /* read or write too small */
-extern char Enetaddr[]; /* bad network address */
-extern char Emsgsize[]; /* message is too big for protocol */
-extern char Enetbusy[]; /* network device is busy or allocated */
-extern char Enoproto[]; /* network protocol not supported */
-extern char Enoport[]; /* network port not available */
-extern char Enoifc[]; /* bad interface or no free interface slots */
-extern char Enolisten[]; /* not announced */
-extern char Ehungup[]; /* write to hungup channel */
-extern char Ebadctl[]; /* bad process or channel control request */
-extern char Enodev[]; /* no free devices */
-extern char Enoenv[]; /* no free environment resources */
-extern char Emuxshutdown[]; /* mux server shut down */
-extern char Emuxbusy[]; /* all mux channels busy */
-extern char Emuxmsg[]; /* bad mux message format or mismatch */
-extern char Eprocdied[]; /* process exited */
-extern char Enochild[]; /* no living children */
-extern char Eioload[]; /* i/o error in demand load */
-extern char Enovmem[]; /* virtual memory allocation failed */
-extern char Ebadld[]; /* illegal line discipline */
-extern char Ebadfd[]; /* fd out of range or not open */
-extern char Eisstream[]; /* seek on a stream */
-extern char Ebadexec[]; /* exec header invalid */
-extern char Etimedout[]; /* connection timed out */
-extern char Econrefused[]; /* connection refused */
-extern char Enetunreach[]; /* network unreachable */
-extern char Eintr[]; /* interrupted */
-extern char Eneedservice[]; /* service required for tcp/udp/il calls */
-extern char Enomem[]; /* kernel allocate failed */
-extern char Enoswap[]; /* swap space full */
-extern char Esfnotcached[]; /* subfont not cached */
-extern char Esoverlap[]; /* segments overlap */
-extern char Emouseset[]; /* mouse type already set */
-extern char Erecover[]; /* failed to recover fd */
-extern char Eshort[]; /* i/o count too small */
-extern char Egreg[]; /* ken scheduled it */
-extern char Ebadspec[]; /* bad attach specifier */
-extern char Enoreg[]; /* process has no saved registers */
--- a/os/boot/pc/ether.c
+++ /dev/null
@@ -1,291 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ip.h"
-
-#include "etherif.h"
-
-static Ether ether[MaxEther];
-
-extern int ether2114xreset(Ether*);
-extern int elnk3reset(Ether*);
-extern int i82557reset(Ether*);
-extern int igbepnp(Ether *);
-extern int i82563pnp(Ether *);
-extern int elnk3reset(Ether*);
-extern int ether589reset(Ether*);
-extern int ne2000reset(Ether*);
-extern int wd8003reset(Ether*);
-extern int ec2treset(Ether*);
-extern int amd79c970reset(Ether*);
-extern int rtl8139pnp(Ether*);
-extern int rtl8169pnp(Ether*);
-extern int ether83815reset(Ether*);
-extern int rhinepnp(Ether*);
-extern int ga620pnp(Ether*);
-extern int dp83820pnp(Ether*);
-
-struct {
- char *type;
- int (*reset)(Ether*);
- int noprobe;
-} ethercards[] = {
- { "21140", ether2114xreset, 0, },
- { "2114x", ether2114xreset, 0, },
- { "i82557", i82557reset, 0, },
- { "igbe", igbepnp, 0, },
- { "i82563",i82563pnp, 0, },
- { "igbepcie",i82563pnp, 0, },
- { "elnk3", elnk3reset, 0, },
- { "3C509", elnk3reset, 0, },
- { "3C575", elnk3reset, 0, },
- { "3C589", ether589reset, 1, },
- { "3C562", ether589reset, 1, },
- { "589E", ether589reset, 1, },
- { "NE2000", ne2000reset, 0, },
- { "WD8003", wd8003reset, 1, },
- { "EC2T", ec2treset, 0, },
- { "AMD79C970", amd79c970reset, 0, },
- { "RTL8139", rtl8139pnp, 0, },
- { "RTL8169", rtl8169pnp, 0, },
- { "83815", ether83815reset, 0, },
- { "rhine", rhinepnp, 0, },
- { "vt6102", rhinepnp, 0, },
- { "GA620", ga620pnp, 0, },
- { "83820", dp83820pnp, 0, },
- { "dp83820", dp83820pnp, 0, },
-
- { 0, }
-};
-
-static void xetherdetach(void);
-
-int
-etherinit(void)
-{
- Ether *ctlr;
- int ctlrno, i, mask, n, x;
-
- fmtinstall('E', eipfmt);
-
- etherdetach = xetherdetach;
- mask = 0;
- for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
- ctlr = ðer[ctlrno];
- memset(ctlr, 0, sizeof(Ether));
- if(iniread && isaconfig("ether", ctlrno, ctlr) == 0)
- continue;
-
- for(n = 0; ethercards[n].type; n++){
- if(!iniread){
- if(ethercards[n].noprobe)
- continue;
- memset(ctlr, 0, sizeof(Ether));
- strcpy(ctlr->type, ethercards[n].type);
- }
- else if(cistrcmp(ethercards[n].type, ctlr->type))
- continue;
- ctlr->ctlrno = ctlrno;
-
- x = splhi();
- if((*ethercards[n].reset)(ctlr)){
- splx(x);
- if(iniread)
- break;
- else
- continue;
- }
-
- ctlr->state = 1; /* card found */
- mask |= 1<<ctlrno;
- if(ctlr->irq == 2)
- ctlr->irq = 9;
- setvec(VectorPIC + ctlr->irq, ctlr->interrupt, ctlr);
-
- print("ether#%d: %s: port 0x%luX irq %lud",
- ctlr->ctlrno, ctlr->type, ctlr->port, ctlr->irq);
- if(ctlr->mem)
- print(" addr 0x%luX", ctlr->mem & ~KZERO);
- if(ctlr->size)
- print(" size 0x%luX", ctlr->size);
- print(": %E\n", ctlr->ea);
-
- if(ctlr->nrb == 0)
- ctlr->nrb = Nrb;
- ctlr->rb = ialloc(sizeof(RingBuf)*ctlr->nrb, 0);
- if(ctlr->ntb == 0)
- ctlr->ntb = Ntb;
- ctlr->tb = ialloc(sizeof(RingBuf)*ctlr->ntb, 0);
-
- ctlr->rh = 0;
- ctlr->ri = 0;
- for(i = 0; i < ctlr->nrb; i++)
- ctlr->rb[i].owner = Interface;
-
- ctlr->th = 0;
- ctlr->ti = 0;
- for(i = 0; i < ctlr->ntb; i++)
- ctlr->tb[i].owner = Host;
-
- splx(x);
- break;
- }
- }
-
- return mask;
-}
-
-void
-etherinitdev(int i, char *s)
-{
- sprint(s, "ether%d", i);
-}
-
-void
-etherprintdevs(int i)
-{
- print(" ether%d", i);
-}
-
-static Ether*
-attach(int ctlrno)
-{
- Ether *ctlr;
-
- if(ctlrno >= MaxEther || ether[ctlrno].state == 0)
- return 0;
-
- ctlr = ðer[ctlrno];
- if(ctlr->state == 1){ /* card found? */
- ctlr->state = 2; /* attaching */
- (*ctlr->attach)(ctlr);
- }
-
- return ctlr;
-}
-
-static void
-xetherdetach(void)
-{
- Ether *ctlr;
- int ctlrno, x;
-
- x = splhi();
- for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
- ctlr = ðer[ctlrno];
- if(ctlr->detach && ctlr->state != 0) /* found | attaching? */
- ctlr->detach(ctlr);
- }
- splx(x);
-}
-
-uchar*
-etheraddr(int ctlrno)
-{
- Ether *ctlr;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- return ctlr->ea;
-}
-
-static int
-wait(RingBuf* ring, uchar owner, int timo)
-{
- ulong start;
-
- start = m->ticks;
- while(TK2MS(m->ticks - start) < timo){
- if(ring->owner != owner)
- return 1;
- }
-
- return 0;
-}
-
-int
-etherrxpkt(int ctlrno, Etherpkt* pkt, int timo)
-{
- int n;
- Ether *ctlr;
- RingBuf *ring;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- ring = &ctlr->rb[ctlr->rh];
- if(wait(ring, Interface, timo) == 0){
- if(debug)
- print("ether%d: rx timeout\n", ctlrno);
- return 0;
- }
-
- n = ring->len;
- memmove(pkt, ring->pkt, n);
- ring->owner = Interface;
- ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
-
- return n;
-}
-
-int
-etherrxflush(int ctlrno)
-{
- int n;
- Ether *ctlr;
- RingBuf *ring;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- n = 0;
- for(;;){
- ring = &ctlr->rb[ctlr->rh];
- if(wait(ring, Interface, 100) == 0)
- break;
-
- ring->owner = Interface;
- ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
- n++;
- }
-
- return n;
-}
-
-int
-ethertxpkt(int ctlrno, Etherpkt* pkt, int len, int)
-{
- Ether *ctlr;
- RingBuf *ring;
- int s;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- ring = &ctlr->tb[ctlr->th];
- if(wait(ring, Interface, 1000) == 0){
- print("ether%d: tx buffer timeout\n", ctlrno);
- return 0;
- }
-
- memmove(pkt->s, ctlr->ea, Eaddrlen);
- if(debug)
- print("%E to %E...\n", pkt->s, pkt->d);
- memmove(ring->pkt, pkt, len);
- if(len < ETHERMINTU){
- memset(ring->pkt+len, 0, ETHERMINTU-len);
- len = ETHERMINTU;
- }
- ring->len = len;
- ring->owner = Interface;
- ctlr->th = NEXT(ctlr->th, ctlr->ntb);
- s = splhi();
- (*ctlr->transmit)(ctlr);
- splx(s);
-
- return 1;
-}
--- a/os/boot/pc/ether2000.c
+++ /dev/null
@@ -1,110 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ether8390.h"
-
-/*
- * Driver written for the 'Notebook Computer Ethernet LAN Adapter',
- * a plug-in to the bus-slot on the rear of the Gateway NOMAD 425DXL
- * laptop. The manual says NE2000 compatible.
- * The interface appears to be pretty well described in the National
- * Semiconductor Local Area Network Databook (1992) as one of the
- * AT evaluation cards.
- *
- * The NE2000 is really just a DP8390[12] plus a data port
- * and a reset port.
- */
-enum {
- Data = 0x10, /* offset from I/O base of data port */
- Reset = 0x1F, /* offset from I/O base of reset port */
-};
-
-int
-ne2000reset(Ether* ether)
-{
- ushort buf[16];
- ulong port;
- Dp8390 *ctlr;
- int i;
- uchar ea[Eaddrlen];
-
- /*
- * Set up the software configuration.
- * Use defaults for port, irq, mem and size
- * if not specified.
- */
- if(ether->port == 0)
- ether->port = 0x300;
- if(ether->irq == 0)
- ether->irq = 2;
- if(ether->mem == 0)
- ether->mem = 0x4000;
- if(ether->size == 0)
- ether->size = 16*1024;
- port = ether->port;
-
- ether->ctlr = malloc(sizeof(Dp8390));
- ctlr = ether->ctlr;
- ctlr->width = 2;
- ctlr->ram = 0;
-
- ctlr->port = port;
- ctlr->data = port+Data;
-
- ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz);
- ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
- ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz);
-
- ctlr->dummyrr = 1;
- for(i = 0; i < ether->nopt; i++){
- if(strcmp(ether->opt[i], "nodummyrr"))
- continue;
- ctlr->dummyrr = 0;
- break;
- }
-
- /*
- * Reset the board. This is done by doing a read
- * followed by a write to the Reset address.
- */
- buf[0] = inb(port+Reset);
- delay(2);
- outb(port+Reset, buf[0]);
- delay(2);
-
- /*
- * Init the (possible) chip, then use the (possible)
- * chip to read the (possible) PROM for ethernet address
- * and a marker byte.
- * Could just look at the DP8390 command register after
- * initialisation has been tried, but that wouldn't be
- * enough, there are other ethernet boards which could
- * match.
- */
- dp8390reset(ether);
- memset(buf, 0, sizeof(buf));
- dp8390read(ctlr, buf, 0, sizeof(buf));
- if((buf[0x0E] & 0xFF) != 0x57 || (buf[0x0F] & 0xFF) != 0x57){
- free(ether->ctlr);
- return -1;
- }
-
- /*
- * Stupid machine. Shorts were asked for,
- * shorts were delivered, although the PROM is a byte array.
- * Set the ethernet address.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, ether->ea, Eaddrlen) == 0){
- for(i = 0; i < sizeof(ether->ea); i++)
- ether->ea[i] = buf[i];
- }
- dp8390setea(ether);
-
- return 0;
-}
--- a/os/boot/pc/ether2114x.c
+++ /dev/null
@@ -1,1652 +1,0 @@
-/*
- * Digital Semiconductor DECchip 21140 PCI Fast Ethernet LAN Controller
- * as found on the Digital Fast EtherWORKS PCI 10/100 adapter (DE-500-X).
- * To do:
- * thresholds;
- * ring sizing;
- * handle more error conditions;
- * all the rest of it...
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-#define DEBUG (0)
-#define debug if(DEBUG)print
-
-enum {
- Nrde = 32,
- Ntde = 4,
-};
-
-#define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4)
-
-enum { /* CRS0 - Bus Mode */
- Swr = 0x00000001, /* Software Reset */
- Bar = 0x00000002, /* Bus Arbitration */
- Dsl = 0x0000007C, /* Descriptor Skip Length (field) */
- Ble = 0x00000080, /* Big/Little Endian */
- Pbl = 0x00003F00, /* Programmable Burst Length (field) */
- Cal = 0x0000C000, /* Cache Alignment (field) */
- Cal8 = 0x00004000, /* 8 longword boundary alignment */
- Cal16 = 0x00008000, /* 16 longword boundary alignment */
- Cal32 = 0x0000C000, /* 32 longword boundary alignment */
- Tap = 0x000E0000, /* Transmit Automatic Polling (field) */
- Dbo = 0x00100000, /* Descriptor Byte Ordering Mode */
- Rml = 0x00200000, /* Read Multiple */
-};
-
-enum { /* CSR[57] - Status and Interrupt Enable */
- Ti = 0x00000001, /* Transmit Interrupt */
- Tps = 0x00000002, /* Transmit Process Stopped */
- Tu = 0x00000004, /* Transmit buffer Unavailable */
- Tjt = 0x00000008, /* Transmit Jabber Timeout */
- Unf = 0x00000020, /* transmit UNderFlow */
- Ri = 0x00000040, /* Receive Interrupt */
- Ru = 0x00000080, /* Receive buffer Unavailable */
- Rps = 0x00000100, /* Receive Process Stopped */
- Rwt = 0x00000200, /* Receive Watchdog Timeout */
- Eti = 0x00000400, /* Early Transmit Interrupt */
- Gte = 0x00000800, /* General purpose Timer Expired */
- Fbe = 0x00002000, /* Fatal Bit Error */
- Ais = 0x00008000, /* Abnormal Interrupt Summary */
- Nis = 0x00010000, /* Normal Interrupt Summary */
- Rs = 0x000E0000, /* Receive process State (field) */
- Ts = 0x00700000, /* Transmit process State (field) */
- Eb = 0x03800000, /* Error bits */
-};
-
-enum { /* CSR6 - Operating Mode */
- Hp = 0x00000001, /* Hash/Perfect receive filtering mode */
- Sr = 0x00000002, /* Start/stop Receive */
- Ho = 0x00000004, /* Hash-Only filtering mode */
- Pb = 0x00000008, /* Pass Bad frames */
- If = 0x00000010, /* Inverse Filtering */
- Sb = 0x00000020, /* Start/stop Backoff counter */
- Pr = 0x00000040, /* Promiscuous Mode */
- Pm = 0x00000080, /* Pass all Multicast */
- Fd = 0x00000200, /* Full Duplex mode */
- Om = 0x00000C00, /* Operating Mode (field) */
- Fc = 0x00001000, /* Force Collision */
- St = 0x00002000, /* Start/stop Transmission Command */
- Tr = 0x0000C000, /* ThReshold control bits (field) */
- Tr128 = 0x00000000,
- Tr256 = 0x00004000,
- Tr512 = 0x00008000,
- Tr1024 = 0x0000C000,
- Ca = 0x00020000, /* CApture effect enable */
- Ps = 0x00040000, /* Port Select */
- Hbd = 0x00080000, /* HeartBeat Disable */
- Imm = 0x00100000, /* IMMediate mode */
- Sf = 0x00200000, /* Store and Forward */
- Ttm = 0x00400000, /* Transmit Threshold Mode */
- Pcs = 0x00800000, /* PCS function */
- Scr = 0x01000000, /* SCRambler mode */
- Mbo = 0x02000000, /* Must Be One */
- Ra = 0x40000000, /* Receive All */
- Sc = 0x80000000, /* Special Capture effect enable */
-
- TrMODE = Tr512, /* default transmission threshold */
-};
-
-enum { /* CSR9 - ROM and MII Management */
- Scs = 0x00000001, /* serial ROM chip select */
- Sclk = 0x00000002, /* serial ROM clock */
- Sdi = 0x00000004, /* serial ROM data in */
- Sdo = 0x00000008, /* serial ROM data out */
- Ss = 0x00000800, /* serial ROM select */
- Wr = 0x00002000, /* write */
- Rd = 0x00004000, /* read */
-
- Mdc = 0x00010000, /* MII management clock */
- Mdo = 0x00020000, /* MII management write data */
- Mii = 0x00040000, /* MII management operation mode (W) */
- Mdi = 0x00080000, /* MII management data in */
-};
-
-enum { /* CSR12 - General-Purpose Port */
- Gpc = 0x00000100, /* General Purpose Control */
-};
-
-typedef struct Des {
- int status;
- int control;
- ulong addr;
- void* bp;
-} Des;
-
-enum { /* status */
- Of = 0x00000001, /* Rx: OverFlow */
- Ce = 0x00000002, /* Rx: CRC Error */
- Db = 0x00000004, /* Rx: Dribbling Bit */
- Re = 0x00000008, /* Rx: Report on MII Error */
- Rw = 0x00000010, /* Rx: Receive Watchdog */
- Ft = 0x00000020, /* Rx: Frame Type */
- Cs = 0x00000040, /* Rx: Collision Seen */
- Tl = 0x00000080, /* Rx: Frame too Long */
- Ls = 0x00000100, /* Rx: Last deScriptor */
- Fs = 0x00000200, /* Rx: First deScriptor */
- Mf = 0x00000400, /* Rx: Multicast Frame */
- Rf = 0x00000800, /* Rx: Runt Frame */
- Dt = 0x00003000, /* Rx: Data Type (field) */
- De = 0x00004000, /* Rx: Descriptor Error */
- Fl = 0x3FFF0000, /* Rx: Frame Length (field) */
- Ff = 0x40000000, /* Rx: Filtering Fail */
-
- Def = 0x00000001, /* Tx: DEFerred */
- Uf = 0x00000002, /* Tx: UnderFlow error */
- Lf = 0x00000004, /* Tx: Link Fail report */
- Cc = 0x00000078, /* Tx: Collision Count (field) */
- Hf = 0x00000080, /* Tx: Heartbeat Fail */
- Ec = 0x00000100, /* Tx: Excessive Collisions */
- Lc = 0x00000200, /* Tx: Late Collision */
- Nc = 0x00000400, /* Tx: No Carrier */
- Lo = 0x00000800, /* Tx: LOss of carrier */
- To = 0x00004000, /* Tx: Transmission jabber timeOut */
-
- Es = 0x00008000, /* [RT]x: Error Summary */
- Own = 0x80000000, /* [RT]x: OWN bit */
-};
-
-enum { /* control */
- Bs1 = 0x000007FF, /* [RT]x: Buffer 1 Size */
- Bs2 = 0x003FF800, /* [RT]x: Buffer 2 Size */
-
- Ch = 0x01000000, /* [RT]x: second address CHained */
- Er = 0x02000000, /* [RT]x: End of Ring */
-
- Ft0 = 0x00400000, /* Tx: Filtering Type 0 */
- Dpd = 0x00800000, /* Tx: Disabled PaDding */
- Ac = 0x04000000, /* Tx: Add CRC disable */
- Set = 0x08000000, /* Tx: SETup packet */
- Ft1 = 0x10000000, /* Tx: Filtering Type 1 */
- Fseg = 0x20000000, /* Tx: First SEGment */
- Lseg = 0x40000000, /* Tx: Last SEGment */
- Ic = 0x80000000, /* Tx: Interrupt on Completion */
-};
-
-enum { /* PHY registers */
- Bmcr = 0, /* Basic Mode Control */
- Bmsr = 1, /* Basic Mode Status */
- Phyidr1 = 2, /* PHY Identifier #1 */
- Phyidr2 = 3, /* PHY Identifier #2 */
- Anar = 4, /* Auto-Negotiation Advertisment */
- Anlpar = 5, /* Auto-Negotiation Link Partner Ability */
- Aner = 6, /* Auto-Negotiation Expansion */
-};
-
-enum { /* Variants */
- Tulip0 = (0x0009<<16)|0x1011,
- Tulip1 = (0x0014<<16)|0x1011,
- Tulip3 = (0x0019<<16)|0x1011,
- Pnic = (0x0002<<16)|0x11AD,
- Pnic2 = (0xC115<<16)|0x11AD,
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
- int port;
- Pcidev* pcidev;
- Ctlr* next;
- int active;
- int id; /* (pcidev->did<<16)|pcidev->vid */
-
- uchar *srom;
- int sromsz;
- uchar* sromea; /* MAC address */
- uchar* leaf;
- int sct; /* selected connection type */
- int k; /* info block count */
- uchar* infoblock[16];
- int sctk; /* sct block index */
- int curk; /* current block index */
- uchar* type5block;
-
- int phy[32]; /* logical to physical map */
- int phyreset; /* reset bitmap */
- int curphyad;
- int fdx;
- int ttm;
-
- uchar fd; /* option */
- int medium; /* option */
-
- int csr6; /* CSR6 - operating mode */
- int mask; /* CSR[57] - interrupt mask */
- int mbps;
-
- Des* rdr; /* receive descriptor ring */
- int nrdr; /* size of rdr */
- int rdrx; /* index into rdr */
-
- Des* tdr; /* transmit descriptor ring */
- int ntdr; /* size of tdr */
- int tdrh; /* host index into tdr */
- int tdri; /* interface index into tdr */
- int ntq; /* descriptors active */
- Block* setupbp;
-
- ulong of; /* receive statistics */
- ulong ce;
- ulong cs;
- ulong tl;
- ulong rf;
- ulong de;
-
- ulong uf; /* transmit statistics */
- ulong ec;
- ulong lc;
- ulong nc;
- ulong lo;
- ulong to;
-
-} Ctlr;
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-#define csr32r(c, r) (inl((c)->port+((r)*8)))
-#define csr32w(c, r, l) (outl((c)->port+((r)*8), (ulong)(l)))
-
-static void
-attach(Ether* ether)
-{
- Ctlr *ctlr;
-
- ctlr = ether->ctlr;
- if(!(ctlr->csr6 & Sr)){
- ctlr->csr6 |= Sr;
- csr32w(ctlr, 6, ctlr->csr6);
- }
-}
-
-static void
-transmit(Ether* ether)
-{
- Ctlr *ctlr;
- Block *bp;
- Des *des;
- int control;
- RingBuf *tb;
-
- ctlr = ether->ctlr;
- while(ctlr->ntq < (ctlr->ntdr-1)){
- if(ctlr->setupbp){
- bp = ctlr->setupbp;
- ctlr->setupbp = 0;
- control = Ic|Set|BLEN(bp);
- }
- else{
- if(ether->ntb == 0)
- break;
- tb = ðer->tb[ether->ti];
- if(tb->owner != Interface)
- break;
- bp = allocb(tb->len);
- memmove(bp->wp, tb->pkt, tb->len);
- memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
- bp->wp += tb->len;
-
- tb->owner = Host;
- ether->ti = NEXT(ether->ti, ether->ntb);
-
- control = Ic|Lseg|Fseg|BLEN(bp);
- }
-
- ctlr->tdr[PREV(ctlr->tdrh, ctlr->ntdr)].control &= ~Ic;
- des = &ctlr->tdr[ctlr->tdrh];
- des->bp = bp;
- des->addr = PADDR(bp->rp);
- des->control |= control;
- ctlr->ntq++;
- //coherence();
- des->status = Own;
- csr32w(ctlr, 1, 0);
- ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
- }
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
- Ctlr *ctlr;
- Ether *ether;
- int len, status;
- Des *des;
- RingBuf *ring;
-
- ether = arg;
- ctlr = ether->ctlr;
-
- while((status = csr32r(ctlr, 5)) & (Nis|Ais)){
- /*
- * Acknowledge the interrupts and mask-out
- * the ones that are implicitly handled.
- */
- csr32w(ctlr, 5, status);
- status &= (ctlr->mask & ~(Nis|Ais|Ti));
-
- /*
- * Received packets.
- */
- if(status & Ri){
- des = &ctlr->rdr[ctlr->rdrx];
- while((des->status & Own) == 0){
- len = ((des->status & Fl)>>16)-4;
- if(des->status & Es){
- if(des->status & Of)
- ctlr->of++;
- if(des->status & Ce)
- ctlr->ce++;
- if(des->status & Cs)
- ctlr->cs++;
- if(des->status & Tl)
- ctlr->tl++;
- if(des->status & Rf)
- ctlr->rf++;
- if(des->status & De)
- ctlr->de++;
- }
- else{
- ring = ðer->rb[ether->ri];
- if(ring->owner == Interface){
- ring->owner = Host;
- ring->len = len;
- memmove(ring->pkt, des->bp, len);
- ether->ri = NEXT(ether->ri, ether->nrb);
- }
- }
-
- des->control &= Er;
- des->control |= Rbsz;
- des->status = Own;
-
- ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
- des = &ctlr->rdr[ctlr->rdrx];
- }
- status &= ~Ri;
- }
-
- /*
- * Check the transmit side:
- * check for Transmit Underflow and Adjust
- * the threshold upwards;
- * free any transmitted buffers and try to
- * top-up the ring.
- */
- if(status & Unf){
- csr32w(ctlr, 6, ctlr->csr6 & ~St);
- switch(ctlr->csr6 & Tr){
- case Tr128:
- len = Tr256;
- break;
- case Tr256:
- len = Tr512;
- break;
- case Tr512:
- len = Tr1024;
- break;
- default:
- case Tr1024:
- len = Sf;
- break;
- }
- ctlr->csr6 = (ctlr->csr6 & ~Tr)|len;
- csr32w(ctlr, 6, ctlr->csr6);
- csr32w(ctlr, 5, Tps);
- status &= ~(Unf|Tps);
- }
-
- while(ctlr->ntq){
- des = &ctlr->tdr[ctlr->tdri];
- if(des->status & Own)
- break;
-
- if(des->status & Es){
- if(des->status & Uf)
- ctlr->uf++;
- if(des->status & Ec)
- ctlr->ec++;
- if(des->status & Lc)
- ctlr->lc++;
- if(des->status & Nc)
- ctlr->nc++;
- if(des->status & Lo)
- ctlr->lo++;
- if(des->status & To)
- ctlr->to++;
- }
-
- freeb(des->bp);
- des->control &= Er;
-
- ctlr->ntq--;
- ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
- }
- transmit(ether);
-
- /*
- * Anything left not catered for?
- */
- if(status)
- panic("#l%d: status %8.8uX\n", ether->ctlrno, status);
- }
-}
-
-static void
-ctlrinit(Ether* ether)
-{
- Ctlr *ctlr;
- Des *des;
- Block *bp;
- int i;
- uchar bi[Eaddrlen*2];
-
- ctlr = ether->ctlr;
-
- /*
- * Allocate and initialise the receive ring;
- * allocate and initialise the transmit ring;
- * unmask interrupts and start the transmit side;
- * create and post a setup packet to initialise
- * the physical ethernet address.
- */
- ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des));
- for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
- des->bp = malloc(Rbsz);
- des->status = Own;
- des->control = Rbsz;
- des->addr = PADDR(des->bp);
- }
- ctlr->rdr[ctlr->nrdr-1].control |= Er;
- ctlr->rdrx = 0;
- csr32w(ctlr, 3, PADDR(ctlr->rdr));
-
- ctlr->tdr = ialloc(ctlr->ntdr*sizeof(Des), 32);
- ctlr->tdr[ctlr->ntdr-1].control |= Er;
- ctlr->tdrh = 0;
- ctlr->tdri = 0;
- csr32w(ctlr, 4, PADDR(ctlr->tdr));
-
- /*
- * Clear any bits in the Status Register (CSR5) as
- * the PNIC has a different reset value from a true 2114x.
- */
- ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti;
- csr32w(ctlr, 5, ctlr->mask);
- csr32w(ctlr, 7, ctlr->mask);
- ctlr->csr6 |= St;
- csr32w(ctlr, 6, ctlr->csr6);
-
- for(i = 0; i < Eaddrlen/2; i++){
- bi[i*4] = ether->ea[i*2];
- bi[i*4+1] = ether->ea[i*2+1];
- bi[i*4+2] = ether->ea[i*2+1];
- bi[i*4+3] = ether->ea[i*2];
- }
- bp = allocb(Eaddrlen*2*16);
- memset(bp->rp, 0xFF, sizeof(bi));
- for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi))
- memmove(bp->rp+i, bi, sizeof(bi));
- bp->wp += sizeof(bi)*16;
-
- ctlr->setupbp = bp;
- transmit(ether);
-}
-
-static void
-csr9w(Ctlr* ctlr, int data)
-{
- csr32w(ctlr, 9, data);
- microdelay(1);
-}
-
-static int
-miimdi(Ctlr* ctlr, int n)
-{
- int data, i;
-
- /*
- * Read n bits from the MII Management Register.
- */
- data = 0;
- for(i = n-1; i >= 0; i--){
- if(csr32r(ctlr, 9) & Mdi)
- data |= (1<<i);
- csr9w(ctlr, Mii|Mdc);
- csr9w(ctlr, Mii);
- }
- csr9w(ctlr, 0);
-
- return data;
-}
-
-static void
-miimdo(Ctlr* ctlr, int bits, int n)
-{
- int i, mdo;
-
- /*
- * Write n bits to the MII Management Register.
- */
- for(i = n-1; i >= 0; i--){
- if(bits & (1<<i))
- mdo = Mdo;
- else
- mdo = 0;
- csr9w(ctlr, mdo);
- csr9w(ctlr, mdo|Mdc);
- csr9w(ctlr, mdo);
- }
-}
-
-static int
-miir(Ctlr* ctlr, int phyad, int regad)
-{
- int data, i;
-
- if(ctlr->id == Pnic){
- i = 1000;
- csr32w(ctlr, 20, 0x60020000|(phyad<<23)|(regad<<18));
- do{
- microdelay(1);
- data = csr32r(ctlr, 20);
- }while((data & 0x80000000) && --i);
-
- if(i == 0)
- return -1;
- return data & 0xFFFF;
- }
-
- /*
- * Preamble;
- * ST+OP+PHYAD+REGAD;
- * TA + 16 data bits.
- */
- miimdo(ctlr, 0xFFFFFFFF, 32);
- miimdo(ctlr, 0x1800|(phyad<<5)|regad, 14);
- data = miimdi(ctlr, 18);
-
- if(data & 0x10000)
- return -1;
-
- return data & 0xFFFF;
-}
-
-static void
-miiw(Ctlr* ctlr, int phyad, int regad, int data)
-{
- /*
- * Preamble;
- * ST+OP+PHYAD+REGAD+TA + 16 data bits;
- * Z.
- */
- miimdo(ctlr, 0xFFFFFFFF, 32);
- data &= 0xFFFF;
- data |= (0x05<<(5+5+2+16))|(phyad<<(5+2+16))|(regad<<(2+16))|(0x02<<16);
- miimdo(ctlr, data, 32);
- csr9w(ctlr, Mdc);
- csr9w(ctlr, 0);
-}
-
-static int
-sromr(Ctlr* ctlr, int r)
-{
- int i, op, data, size;
-
- if(ctlr->id == Pnic){
- i = 1000;
- csr32w(ctlr, 19, 0x600|r);
- do{
- microdelay(1);
- data = csr32r(ctlr, 19);
- }while((data & 0x80000000) && --i);
-
- if(ctlr->sromsz == 0)
- ctlr->sromsz = 6;
-
- return csr32r(ctlr, 9) & 0xFFFF;
- }
-
- /*
- * This sequence for reading a 16-bit register 'r'
- * in the EEPROM is taken (pretty much) straight from Section
- * 7.4 of the 21140 Hardware Reference Manual.
- */
-reread:
- csr9w(ctlr, Rd|Ss);
- csr9w(ctlr, Rd|Ss|Scs);
- csr9w(ctlr, Rd|Ss|Sclk|Scs);
- csr9w(ctlr, Rd|Ss);
-
- op = 0x06;
- for(i = 3-1; i >= 0; i--){
- data = Rd|Ss|(((op>>i) & 0x01)<<2)|Scs;
- csr9w(ctlr, data);
- csr9w(ctlr, data|Sclk);
- csr9w(ctlr, data);
- }
-
- /*
- * First time through must work out the EEPROM size.
- * This doesn't seem to work on the 21041 as implemented
- * in Virtual PC for the Mac, so wire any 21041 to 6,
- * it's the only 21041 this code will ever likely see.
- */
- if((size = ctlr->sromsz) == 0){
- if(ctlr->id == Tulip1)
- ctlr->sromsz = size = 6;
- else
- size = 8;
- }
-
- for(size = size-1; size >= 0; size--){
- data = Rd|Ss|(((r>>size) & 0x01)<<2)|Scs;
- csr9w(ctlr, data);
- csr9w(ctlr, data|Sclk);
- csr9w(ctlr, data);
- microdelay(1);
- if(ctlr->sromsz == 0 && !(csr32r(ctlr, 9) & Sdo))
- break;
- }
-
- data = 0;
- for(i = 16-1; i >= 0; i--){
- csr9w(ctlr, Rd|Ss|Sclk|Scs);
- if(csr32r(ctlr, 9) & Sdo)
- data |= (1<<i);
- csr9w(ctlr, Rd|Ss|Scs);
- }
-
- csr9w(ctlr, 0);
-
- if(ctlr->sromsz == 0){
- ctlr->sromsz = 8-size;
- goto reread;
- }
-
- return data & 0xFFFF;
-}
-
-static void
-softreset(Ctlr* ctlr)
-{
- /*
- * Soft-reset the controller and initialise bus mode.
- * Delay should be >= 50 PCI cycles (2×S @ 25MHz).
- */
- csr32w(ctlr, 0, Swr);
- microdelay(10);
- csr32w(ctlr, 0, Rml|Cal16);
- delay(1);
-}
-
-static int
-type5block(Ctlr* ctlr, uchar* block)
-{
- int csr15, i, len;
-
- /*
- * Reset or GPR sequence. Reset should be once only,
- * before the GPR sequence.
- * Note 'block' is not a pointer to the block head but
- * a pointer to the data in the block starting at the
- * reset length value so type5block can be used for the
- * sequences contained in type 1 and type 3 blocks.
- * The SROM docs state the 21140 type 5 block is the
- * same as that for the 21143, but the two controllers
- * use different registers and sequence-element lengths
- * so the 21140 code here is a guess for a real type 5
- * sequence.
- */
- len = *block++;
- if(ctlr->id != Tulip3){
- for(i = 0; i < len; i++){
- csr32w(ctlr, 12, *block);
- block++;
- }
- return len;
- }
-
- for(i = 0; i < len; i++){
- csr15 = *block++<<16;
- csr15 |= *block++<<24;
- csr32w(ctlr, 15, csr15);
- debug("%8.8uX ", csr15);
- }
- return 2*len;
-}
-
-static int
-typephylink(Ctlr* ctlr, uchar*)
-{
- int an, bmcr, bmsr, csr6, x;
-
- /*
- * Fail if
- * auto-negotiataion enabled but not complete;
- * no valid link established.
- */
- bmcr = miir(ctlr, ctlr->curphyad, Bmcr);
- miir(ctlr, ctlr->curphyad, Bmsr);
- bmsr = miir(ctlr, ctlr->curphyad, Bmsr);
- debug("bmcr 0x%2.2uX bmsr 0x%2.2uX\n", bmcr, bmsr);
- if(((bmcr & 0x1000) && !(bmsr & 0x0020)) || !(bmsr & 0x0004))
- return 0;
-
- if(bmcr & 0x1000){
- an = miir(ctlr, ctlr->curphyad, Anar);
- an &= miir(ctlr, ctlr->curphyad, Anlpar) & 0x3E0;
- debug("an 0x%2.uX 0x%2.2uX 0x%2.2uX\n",
- miir(ctlr, ctlr->curphyad, Anar),
- miir(ctlr, ctlr->curphyad, Anlpar),
- an);
-
- if(an & 0x0100)
- x = 0x4000;
- else if(an & 0x0080)
- x = 0x2000;
- else if(an & 0x0040)
- x = 0x1000;
- else if(an & 0x0020)
- x = 0x0800;
- else
- x = 0;
- }
- else if((bmcr & 0x2100) == 0x2100)
- x = 0x4000;
- else if(bmcr & 0x2000){
- /*
- * If FD capable, force it if necessary.
- */
- if((bmsr & 0x4000) && ctlr->fd){
- miiw(ctlr, ctlr->curphyad, Bmcr, 0x2100);
- x = 0x4000;
- }
- else
- x = 0x2000;
- }
- else if(bmcr & 0x0100)
- x = 0x1000;
- else
- x = 0x0800;
-
- csr6 = Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
- if(ctlr->fdx & x)
- csr6 |= Fd;
- if(ctlr->ttm & x)
- csr6 |= Ttm;
- debug("csr6 0x%8.8uX 0x%8.8uX 0x%8.8luX\n",
- csr6, ctlr->csr6, csr32r(ctlr, 6));
- if(csr6 != ctlr->csr6){
- ctlr->csr6 = csr6;
- csr32w(ctlr, 6, csr6);
- }
-
- return 1;
-}
-
-static int
-typephymode(Ctlr* ctlr, uchar* block, int wait)
-{
- uchar *p;
- int len, mc, nway, phyx, timeo;
-
- if(DEBUG){
- int i;
-
- len = (block[0] & ~0x80)+1;
- for(i = 0; i < len; i++)
- debug("%2.2uX ", block[i]);
- debug("\n");
- }
-
- if(block[1] == 1)
- len = 1;
- else if(block[1] == 3)
- len = 2;
- else
- return -1;
-
- /*
- * Snarf the media capabilities, nway advertisment,
- * FDX and TTM bitmaps.
- */
- p = &block[5+len*block[3]+len*block[4+len*block[3]]];
- mc = *p++;
- mc |= *p++<<8;
- nway = *p++;
- nway |= *p++<<8;
- ctlr->fdx = *p++;
- ctlr->fdx |= *p++<<8;
- ctlr->ttm = *p++;
- ctlr->ttm |= *p<<8;
- debug("mc %4.4uX nway %4.4uX fdx %4.4uX ttm %4.4uX\n",
- mc, nway, ctlr->fdx, ctlr->ttm);
- USED(mc);
-
- phyx = block[2];
- ctlr->curphyad = ctlr->phy[phyx];
-
- ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
- //csr32w(ctlr, 6, ctlr->csr6);
- if(typephylink(ctlr, block))
- return 0;
-
- if(!(ctlr->phyreset & (1<<phyx))){
- debug("reset seq: len %d: ", block[3]);
- if(ctlr->type5block)
- type5block(ctlr, &ctlr->type5block[2]);
- else
- type5block(ctlr, &block[4+len*block[3]]);
- debug("\n");
- ctlr->phyreset |= (1<<phyx);
- }
-
- /*
- * GPR sequence.
- */
- debug("gpr seq: len %d: ", block[3]);
- type5block(ctlr, &block[3]);
- debug("\n");
-
- ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
- //csr32w(ctlr, 6, ctlr->csr6);
- if(typephylink(ctlr, block))
- return 0;
-
- /*
- * Turn off auto-negotiation, set the auto-negotiation
- * advertisment register then start the auto-negotiation
- * process again.
- */
- miiw(ctlr, ctlr->curphyad, Bmcr, 0);
- miiw(ctlr, ctlr->curphyad, Anar, nway|1);
- miiw(ctlr, ctlr->curphyad, Bmcr, 0x1000);
-
- if(!wait)
- return 0;
-
- for(timeo = 0; timeo < 30; timeo++){
- if(typephylink(ctlr, block))
- return 0;
- delay(100);
- }
-
- return -1;
-}
-
-static int
-typesymmode(Ctlr *ctlr, uchar *block, int wait)
-{
- uint gpmode, gpdata, command;
-
- USED(wait);
- gpmode = block[3] | ((uint) block[4] << 8);
- gpdata = block[5] | ((uint) block[6] << 8);
- command = (block[7] | ((uint) block[8] << 8)) & 0x71;
- if (command & 0x8000) {
- print("ether2114x.c: FIXME: handle type 4 mode blocks where cmd.active_invalid != 0\n");
- return -1;
- }
- csr32w(ctlr, 15, gpmode);
- csr32w(ctlr, 15, gpdata);
- ctlr->csr6 = (command & 0x71) << 18;
- csr32w(ctlr, 6, ctlr->csr6);
- return 0;
-}
-
-static int
-type2mode(Ctlr* ctlr, uchar* block, int)
-{
- uchar *p;
- int csr6, csr13, csr14, csr15, gpc, gpd;
-
- csr6 = Sc|Mbo|Ca|TrMODE|Sb;
- debug("type2mode: medium 0x%2.2uX\n", block[2]);
-
- /*
- * Don't attempt full-duplex
- * unless explicitly requested.
- */
- if((block[2] & 0x3F) == 0x04){ /* 10BASE-TFD */
- if(!ctlr->fd)
- return -1;
- csr6 |= Fd;
- }
-
- /*
- * Operating mode programming values from the datasheet
- * unless media specific data is explicitly given.
- */
- p = &block[3];
- if(block[2] & 0x40){
- csr13 = (block[4]<<8)|block[3];
- csr14 = (block[6]<<8)|block[5];
- csr15 = (block[8]<<8)|block[7];
- p += 6;
- }
- else switch(block[2] & 0x3F){
- default:
- return -1;
- case 0x00: /* 10BASE-T */
- csr13 = 0x00000001;
- csr14 = 0x00007F3F;
- csr15 = 0x00000008;
- break;
- case 0x01: /* 10BASE-2 */
- csr13 = 0x00000009;
- csr14 = 0x00000705;
- csr15 = 0x00000006;
- break;
- case 0x02: /* 10BASE-5 (AUI) */
- csr13 = 0x00000009;
- csr14 = 0x00000705;
- csr15 = 0x0000000E;
- break;
- case 0x04: /* 10BASE-TFD */
- csr13 = 0x00000001;
- csr14 = 0x00007F3D;
- csr15 = 0x00000008;
- break;
- }
- gpc = *p++<<16;
- gpc |= *p++<<24;
- gpd = *p++<<16;
- gpd |= *p<<24;
-
- csr32w(ctlr, 13, 0);
- csr32w(ctlr, 14, csr14);
- csr32w(ctlr, 15, gpc|csr15);
- delay(10);
- csr32w(ctlr, 15, gpd|csr15);
- csr32w(ctlr, 13, csr13);
-
- ctlr->csr6 = csr6;
- csr32w(ctlr, 6, ctlr->csr6);
-
- debug("type2mode: csr13 %8.8uX csr14 %8.8uX csr15 %8.8uX\n",
- csr13, csr14, csr15);
- debug("type2mode: gpc %8.8uX gpd %8.8uX csr6 %8.8uX\n",
- gpc, gpd, csr6);
-
- return 0;
-}
-
-static int
-type0link(Ctlr* ctlr, uchar* block)
-{
- int m, polarity, sense;
-
- m = (block[3]<<8)|block[2];
- sense = 1<<((m & 0x000E)>>1);
- if(m & 0x0080)
- polarity = sense;
- else
- polarity = 0;
-
- return (csr32r(ctlr, 12) & sense)^polarity;
-}
-
-static int
-type0mode(Ctlr* ctlr, uchar* block, int wait)
-{
- int csr6, m, timeo;
-
- csr6 = Sc|Mbo|Hbd|Ca|TrMODE|Sb;
-debug("type0: medium 0x%uX, fd %d: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
- ctlr->medium, ctlr->fd, block[0], block[1], block[2], block[3]);
- switch(block[0]){
- default:
- break;
-
- case 0x04: /* 10BASE-TFD */
- case 0x05: /* 100BASE-TXFD */
- case 0x08: /* 100BASE-FXFD */
- /*
- * Don't attempt full-duplex
- * unless explicitly requested.
- */
- if(!ctlr->fd)
- return -1;
- csr6 |= Fd;
- break;
- }
-
- m = (block[3]<<8)|block[2];
- if(m & 0x0001)
- csr6 |= Ps;
- if(m & 0x0010)
- csr6 |= Ttm;
- if(m & 0x0020)
- csr6 |= Pcs;
- if(m & 0x0040)
- csr6 |= Scr;
-
- csr32w(ctlr, 12, block[1]);
- microdelay(10);
- csr32w(ctlr, 6, csr6);
- ctlr->csr6 = csr6;
-
- if(!wait)
- return 0;
-
- for(timeo = 0; timeo < 30; timeo++){
- if(type0link(ctlr, block))
- return 0;
- delay(100);
- }
-
- return -1;
-}
-
-static int
-media21041(Ether* ether, int wait)
-{
- Ctlr* ctlr;
- uchar *block;
- int csr6, csr13, csr14, csr15, medium, timeo;
-
- ctlr = ether->ctlr;
- block = ctlr->infoblock[ctlr->curk];
- debug("media21041: block[0] %2.2uX, medium %4.4uX sct %4.4uX\n",
- block[0], ctlr->medium, ctlr->sct);
-
- medium = block[0] & 0x3F;
- if(ctlr->medium >= 0 && medium != ctlr->medium)
- return 0;
- if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != medium)
- return 0;
-
- csr6 = Sc|Mbo|Ca|TrMODE|Sb;
- if(block[0] & 0x40){
- csr13 = (block[2]<<8)|block[1];
- csr14 = (block[4]<<8)|block[3];
- csr15 = (block[6]<<8)|block[5];
- }
- else switch(medium){
- default:
- return -1;
- case 0x00: /* 10BASE-T */
- csr13 = 0xEF01;
- csr14 = 0xFF3F;
- csr15 = 0x0008;
- break;
- case 0x01: /* 10BASE-2 */
- csr13 = 0xEF09;
- csr14 = 0xF73D;
- csr15 = 0x0006;
- break;
- case 0x02: /* 10BASE-5 */
- csr13 = 0xEF09;
- csr14 = 0xF73D;
- csr15 = 0x000E;
- break;
- case 0x04: /* 10BASE-TFD */
- csr13 = 0xEF01;
- csr14 = 0xFF3D;
- csr15 = 0x0008;
- break;
- }
-
- csr32w(ctlr, 13, 0);
- csr32w(ctlr, 14, csr14);
- csr32w(ctlr, 15, csr15);
- csr32w(ctlr, 13, csr13);
- delay(10);
-
- if(medium == 0x04)
- csr6 |= Fd;
- ctlr->csr6 = csr6;
- csr32w(ctlr, 6, ctlr->csr6);
-
- debug("media21041: csr6 %8.8uX csr13 %4.4uX csr14 %4.4uX csr15 %4.4uX\n",
- csr6, csr13, csr14, csr15);
-
- if(!wait)
- return 0;
-
- for(timeo = 0; timeo < 30; timeo++){
- if(!(csr32r(ctlr, 12) & 0x0002)){
- debug("media21041: ok: csr12 %4.4luX timeo %d\n",
- csr32r(ctlr, 12), timeo);
- return 10;
- }
- delay(100);
- }
- debug("media21041: !ok: csr12 %4.4luX\n", csr32r(ctlr, 12));
-
- return -1;
-}
-
-static int
-mediaxx(Ether* ether, int wait)
-{
- Ctlr* ctlr;
- uchar *block;
-
- ctlr = ether->ctlr;
- block = ctlr->infoblock[ctlr->curk];
- if(block[0] & 0x80){
- switch(block[1]){
- default:
- return -1;
- case 0:
- if(ctlr->medium >= 0 && block[2] != ctlr->medium)
- return 0;
-/* need this test? */ if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[2])
- return 0;
- if(type0mode(ctlr, block+2, wait))
- return 0;
- break;
- case 1:
- if(typephymode(ctlr, block, wait))
- return 0;
- break;
- case 2:
- debug("type2: medium %d block[2] %d\n",
- ctlr->medium, block[2]);
- if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
- return 0;
- if(type2mode(ctlr, block, wait))
- return 0;
- break;
- case 3:
- if(typephymode(ctlr, block, wait))
- return 0;
- break;
- case 4:
- debug("type4: medium %d block[2] %d\n",
- ctlr->medium, block[2]);
- if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
- return 0;
- if(typesymmode(ctlr, block, wait))
- return 0;
- break;
- }
- }
- else{
- if(ctlr->medium >= 0 && block[0] != ctlr->medium)
- return 0;
-/* need this test? */if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[0])
- return 0;
- if(type0mode(ctlr, block, wait))
- return 0;
- }
-
- if(ctlr->csr6){
- if(!(ctlr->csr6 & Ps) || (ctlr->csr6 & Ttm))
- return 10;
- return 100;
- }
-
- return 0;
-}
-
-static int
-media(Ether* ether, int wait)
-{
- Ctlr* ctlr;
- int k, mbps;
-
- ctlr = ether->ctlr;
- for(k = 0; k < ctlr->k; k++){
- switch(ctlr->id){
- default:
- mbps = mediaxx(ether, wait);
- break;
- case Tulip1: /* 21041 */
- mbps = media21041(ether, wait);
- break;
- }
- if(mbps > 0)
- return mbps;
- if(ctlr->curk == 0)
- ctlr->curk = ctlr->k-1;
- else
- ctlr->curk--;
- }
-
- return 0;
-}
-
-static char* mediatable[9] = {
- "10BASE-T", /* TP */
- "10BASE-2", /* BNC */
- "10BASE-5", /* AUI */
- "100BASE-TX",
- "10BASE-TFD",
- "100BASE-TXFD",
- "100BASE-T4",
- "100BASE-FX",
- "100BASE-FXFD",
-};
-
-static uchar en1207[] = { /* Accton EN1207-COMBO */
- 0x00, 0x00, 0xE8, /* [0] vendor ethernet code */
- 0x00, /* [3] spare */
-
- 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */
- 0x1F, /* [6] general purpose control */
- 2, /* [7] block count */
-
- 0x00, /* [8] media code (10BASE-TX) */
- 0x0B, /* [9] general purpose port data */
- 0x9E, 0x00, /* [10] command (LSB+MSB = 0x009E) */
-
- 0x03, /* [8] media code (100BASE-TX) */
- 0x1B, /* [9] general purpose port data */
- 0x6D, 0x00, /* [10] command (LSB+MSB = 0x006D) */
-
- /* There is 10BASE-2 as well, but... */
-};
-
-static uchar ana6910fx[] = { /* Adaptec (Cogent) ANA-6910FX */
- 0x00, 0x00, 0x92, /* [0] vendor ethernet code */
- 0x00, /* [3] spare */
-
- 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */
- 0x3F, /* [6] general purpose control */
- 1, /* [7] block count */
-
- 0x07, /* [8] media code (100BASE-FX) */
- 0x03, /* [9] general purpose port data */
- 0x2D, 0x00 /* [10] command (LSB+MSB = 0x000D) */
-};
-
-static uchar smc9332[] = { /* SMC 9332 */
- 0x00, 0x00, 0xC0, /* [0] vendor ethernet code */
- 0x00, /* [3] spare */
-
- 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */
- 0x1F, /* [6] general purpose control */
- 2, /* [7] block count */
-
- 0x00, /* [8] media code (10BASE-TX) */
- 0x00, /* [9] general purpose port data */
- 0x9E, 0x00, /* [10] command (LSB+MSB = 0x009E) */
-
- 0x03, /* [8] media code (100BASE-TX) */
- 0x09, /* [9] general purpose port data */
- 0x6D, 0x00, /* [10] command (LSB+MSB = 0x006D) */
-};
-
-static uchar* leaf21140[] = {
- en1207, /* Accton EN1207-COMBO */
- ana6910fx, /* Adaptec (Cogent) ANA-6910FX */
- smc9332, /* SMC 9332 */
- 0,
-};
-
-/*
- * Copied to ctlr->srom at offset 20.
- */
-static uchar leafpnic[] = {
- 0x00, 0x00, 0x00, 0x00, /* MAC address */
- 0x00, 0x00,
- 0x00, /* controller 0 device number */
- 0x1E, 0x00, /* controller 0 info leaf offset */
- 0x00, /* reserved */
- 0x00, 0x08, /* selected connection type */
- 0x00, /* general purpose control */
- 0x01, /* block count */
-
- 0x8C, /* format indicator and count */
- 0x01, /* block type */
- 0x00, /* PHY number */
- 0x00, /* GPR sequence length */
- 0x00, /* reset sequence length */
- 0x00, 0x78, /* media capabilities */
- 0xE0, 0x01, /* Nway advertisment */
- 0x00, 0x50, /* FDX bitmap */
- 0x00, 0x18, /* TTM bitmap */
-};
-
-static int
-srom(Ctlr* ctlr)
-{
- int i, k, oui, phy, x;
- uchar *p;
-
- /*
- * This is a partial decoding of the SROM format described in
- * 'Digital Semiconductor 21X4 Serial ROM Format, Version 4.05,
- * 2-Mar-98'. Only the 2114[03] are handled, support for other
- * controllers can be added as needed.
- */
- sromr(ctlr, 0);
- if(ctlr->srom == nil)
- ctlr->srom = malloc((1<<ctlr->sromsz)*sizeof(ushort));
- for(i = 0; i < (1<<ctlr->sromsz); i++){
- x = sromr(ctlr, i);
- ctlr->srom[2*i] = x;
- ctlr->srom[2*i+1] = x>>8;
- }
-
- if(DEBUG){
- print("srom:");
- for(i = 0; i < ((1<<ctlr->sromsz)*sizeof(ushort)); i++){
- if(i && ((i & 0x0F) == 0))
- print("\n ");
- print(" %2.2uX", ctlr->srom[i]);
- }
- print("\n");
- }
-
- /*
- * There are 2 SROM layouts:
- * e.g. Digital EtherWORKS station address at offset 20;
- * this complies with the 21140A SROM
- * application note from Digital;
- * e.g. SMC9332 station address at offset 0 followed by
- * 2 additional bytes, repeated at offset
- * 6; the 8 bytes are also repeated in
- * reverse order at offset 8.
- * To check which it is, read the SROM and check for the repeating
- * patterns of the non-compliant cards; if that fails use the one at
- * offset 20.
- */
- ctlr->sromea = ctlr->srom;
- for(i = 0; i < 8; i++){
- x = ctlr->srom[i];
- if(x != ctlr->srom[15-i] || x != ctlr->srom[16+i]){
- ctlr->sromea = &ctlr->srom[20];
- break;
- }
- }
-
- /*
- * Fake up the SROM for the PNIC.
- * It looks like a 21140 with a PHY.
- * The MAC address is byte-swapped in the orginal SROM data.
- */
- if(ctlr->id == Pnic){
- memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));
- for(i = 0; i < Eaddrlen; i += 2){
- ctlr->srom[20+i] = ctlr->srom[i+1];
- ctlr->srom[20+i+1] = ctlr->srom[i];
- }
- }
-
- /*
- * Next, try to find the info leaf in the SROM for media detection.
- * If it's a non-conforming card try to match the vendor ethernet code
- * and point p at a fake info leaf with compact 21140 entries.
- */
- if(ctlr->sromea == ctlr->srom){
- p = nil;
- for(i = 0; leaf21140[i] != nil; i++){
- if(memcmp(leaf21140[i], ctlr->sromea, 3) == 0){
- p = &leaf21140[i][4];
- break;
- }
- }
- if(p == nil)
- return -1;
- }
- else
- p = &ctlr->srom[(ctlr->srom[28]<<8)|ctlr->srom[27]];
-
- /*
- * Set up the info needed for later media detection.
- * For the 21140, set the general-purpose mask in CSR12.
- * The info block entries are stored in order of increasing
- * precedence, so detection will work backwards through the
- * stored indexes into ctlr->srom.
- * If an entry is found which matches the selected connection
- * type, save the index. Otherwise, start at the last entry.
- * If any MII entries are found (type 1 and 3 blocks), scan
- * for PHYs.
- */
- ctlr->leaf = p;
- ctlr->sct = *p++;
- ctlr->sct |= *p++<<8;
- if(ctlr->id != Tulip3 && ctlr->id != Tulip1){
- csr32w(ctlr, 12, Gpc|*p++);
- delay(200);
- }
- ctlr->k = *p++;
- if(ctlr->k >= nelem(ctlr->infoblock))
- ctlr->k = nelem(ctlr->infoblock)-1;
- ctlr->sctk = ctlr->k-1;
- phy = 0;
- for(k = 0; k < ctlr->k; k++){
- ctlr->infoblock[k] = p;
- if(ctlr->id == Tulip1){
- debug("type21041: 0x%2.2uX\n", p[0]);
- if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
- ctlr->sctk = k;
- if(*p & 0x40)
- p += 7;
- else
- p += 1;
- }
- /*
- * The RAMIX PMC665 has a badly-coded SROM,
- * hence the test for 21143 and type 3.
- */
- else if((*p & 0x80) || (ctlr->id == Tulip3 && *(p+1) == 3)){
- *p |= 0x80;
- if(*(p+1) == 1 || *(p+1) == 3)
- phy = 1;
- if(*(p+1) == 5)
- ctlr->type5block = p;
- p += (*p & ~0x80)+1;
- }
- else{
- debug("type0: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
- p[0], p[1], p[2], p[3]);
- if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
- ctlr->sctk = k;
- p += 4;
- }
- }
- ctlr->curk = ctlr->sctk;
- debug("sct 0x%uX medium 0x%uX k %d curk %d phy %d\n",
- ctlr->sct, ctlr->medium, ctlr->k, ctlr->curk, phy);
-
- if(phy){
- x = 0;
- for(k = 0; k < nelem(ctlr->phy); k++){
- if((oui = miir(ctlr, k, 2)) == -1 || oui == 0)
- continue;
- if(DEBUG){
- oui = (oui & 0x3FF)<<6;
- oui |= miir(ctlr, k, 3)>>10;
- miir(ctlr, k, 1);
- debug("phy%d: index %d oui %uX reg1 %uX\n",
- x, k, oui, miir(ctlr, k, 1));
- USED(oui);
- }
- ctlr->phy[x] = k;
- }
- }
-
- ctlr->fd = 0;
- ctlr->medium = -1;
-
- return 0;
-}
-
-static void
-dec2114xpci(void)
-{
- Ctlr *ctlr;
- Pcidev *p;
- int x;
-
- p = nil;
- while(p = pcimatch(p, 0, 0)){
- if(p->ccrb != 0x02 || p->ccru != 0)
- continue;
- switch((p->did<<16)|p->vid){
- default:
- continue;
-
- case Tulip3: /* 21143 */
- /*
- * Exit sleep mode.
- */
- x = pcicfgr32(p, 0x40);
- x &= ~0xC0000000;
- pcicfgw32(p, 0x40, x);
- /*FALLTHROUGH*/
-
- case Pnic: /* PNIC */
- case Pnic2: /* PNIC-II */
- case Tulip0: /* 21140 */
- case Tulip1: /* 21041 */
- break;
- }
-
- /*
- * bar[0] is the I/O port register address and
- * bar[1] is the memory-mapped register address.
- */
- ctlr = malloc(sizeof(Ctlr));
- ctlr->port = p->mem[0].bar & ~0x01;
- ctlr->pcidev = p;
- ctlr->id = (p->did<<16)|p->vid;
- debug("2114x: type 0x%8.8uX rev 0x%4.4uX at port 0x%4.4uX\n",
- ctlr->id, p->rid, ctlr->port);
-
- /*
- * Some cards (e.g. ANA-6910FX) seem to need the Ps bit
- * set or they don't always work right after a hardware
- * reset.
- */
- csr32w(ctlr, 6, Mbo|Ps);
- softreset(ctlr);
-
- if(srom(ctlr)){
- free(ctlr);
- break;
- }
-
- switch(ctlr->id){
- default:
- break;
-
- case Pnic: /* PNIC */
- /*
- * Turn off the jabber timer.
- */
- csr32w(ctlr, 15, 0x00000001);
- break;
- }
-
- if(ctlrhead != nil)
- ctlrtail->next = ctlr;
- else
- ctlrhead = ctlr;
- ctlrtail = ctlr;
- }
-}
-
-static void
-detach(Ether* ether)
-{
- softreset(ether->ctlr);
-}
-
-int
-ether2114xreset(Ether* ether)
-{
- Ctlr *ctlr;
- int i, x;
- uchar ea[Eaddrlen];
- static int scandone;
-
- if(scandone == 0){
- dec2114xpci();
- scandone = 1;
- }
-
- /*
- * Any adapter matches if no ether->port is supplied,
- * otherwise the ports must match.
- */
- for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
- if(ctlr->active)
- continue;
- if(ether->port == 0 || ether->port == ctlr->port){
- ctlr->active = 1;
- break;
- }
- }
- if(ctlr == nil)
- return -1;
-
- ether->ctlr = ctlr;
- ether->port = ctlr->port;
- ether->irq = ctlr->pcidev->intl;
- ether->tbdf = ctlr->pcidev->tbdf;
-
- /*
- * Check if the adapter's station address is to be overridden.
- * If not, read it from the EEPROM and set in ether->ea prior to
- * loading the station address in the hardware.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, ether->ea, Eaddrlen) == 0)
- memmove(ether->ea, ctlr->sromea, Eaddrlen);
-
- /*
- * Look for a medium override in case there's no autonegotiation
- * (no MII) or the autonegotiation fails.
- */
- for(i = 0; i < ether->nopt; i++){
- if(cistrcmp(ether->opt[i], "FD") == 0){
- ctlr->fd = 1;
- continue;
- }
- for(x = 0; x < nelem(mediatable); x++){
- debug("compare <%s> <%s>\n", mediatable[x],
- ether->opt[i]);
- if(cistrcmp(mediatable[x], ether->opt[i]))
- continue;
- ctlr->medium = x;
-
- switch(ctlr->medium){
- default:
- ctlr->fd = 0;
- break;
-
- case 0x04: /* 10BASE-TFD */
- case 0x05: /* 100BASE-TXFD */
- case 0x08: /* 100BASE-FXFD */
- ctlr->fd = 1;
- break;
- }
- break;
- }
- }
-
- /*
- * Determine media.
- */
- ctlr->mbps = media(ether, 1);
-
- /*
- * Initialise descriptor rings, ethernet address.
- */
- ctlr->nrdr = Nrde;
- ctlr->ntdr = Ntde;
- pcisetbme(ctlr->pcidev);
- ctlrinit(ether);
-
- /*
- * Linkage to the generic ethernet driver.
- */
- ether->attach = attach;
- ether->transmit = transmit;
- ether->interrupt = interrupt;
- ether->detach = detach;
-
- return 0;
-}
--- a/os/boot/pc/ether589.c
+++ /dev/null
@@ -1,211 +1,0 @@
-/*
- * 3C589 and 3C562.
- * To do:
- * check xcvr10Base2 still works (is GlobalReset necessary?).
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "error.h"
-
-#include "etherif.h"
-
-enum { /* all windows */
- CommandR = 0x000E,
- IntStatusR = 0x000E,
-};
-
-enum { /* Commands */
- GlobalReset = 0x0000,
- SelectRegisterWindow = 0x0001,
- RxReset = 0x0005,
- TxReset = 0x000B,
- AcknowledgeInterrupt = 0x000D,
-};
-
-enum { /* IntStatus bits */
- commandInProgress = 0x1000,
-};
-
-#define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a))
-#define STATUS(port) ins((port)+IntStatusR)
-
-enum { /* Window 0 - setup */
- Wsetup = 0x0000,
- /* registers */
- ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */
- ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */
- ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */
- AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */
- ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */
- EepromCommand = 0x000A,
- EepromData = 0x000C,
- /* AddressConfig Bits */
- autoSelect9 = 0x0080,
- xcvrMask9 = 0xC000,
- /* ConfigControl bits */
- Ena = 0x0001,
- base10TAvailable9 = 0x0200,
- coaxAvailable9 = 0x1000,
- auiAvailable9 = 0x2000,
- /* EepromCommand bits */
- EepromReadRegister = 0x0080,
- EepromBusy = 0x8000,
-};
-
-enum { /* Window 1 - operating set */
- Wop = 0x0001,
-};
-
-enum { /* Window 3 - FIFO management */
- Wfifo = 0x0003,
- /* registers */
- InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */
- /* InternalConfig bits */
- xcvr10BaseT = 0x00000000,
- xcvr10Base2 = 0x00300000,
-};
-
-enum { /* Window 4 - diagnostic */
- Wdiagnostic = 0x0004,
- /* registers */
- MediaStatus = 0x000A,
- /* MediaStatus bits */
- linkBeatDetect = 0x0800,
-};
-
-extern int elnk3reset(Ether*);
-
-static char *tcmpcmcia[] = {
- "3C589", /* 3COM 589[ABCD] */
- "3C562", /* 3COM 562 */
- "589E", /* 3COM Megahertz 589E */
- nil,
-};
-
-static int
-configASIC(Ether* ether, int port, int xcvr)
-{
- int x;
-
- /* set Window 0 configuration registers */
- COMMAND(port, SelectRegisterWindow, Wsetup);
- outs(port+ConfigControl, Ena);
-
- /* IRQ must be 3 on 3C589/3C562 */
- outs(port + ResourceConfig, 0x3F00);
-
- x = ins(port+AddressConfig) & ~xcvrMask9;
- x |= (xcvr>>20)<<14;
- outs(port+AddressConfig, x);
-
- COMMAND(port, TxReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
- COMMAND(port, RxReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
-
- return elnk3reset(ether);
-}
-
-int
-ether589reset(Ether* ether)
-{
- int i, t, slot;
- char *type;
- int port;
- enum { WantAny, Want10BT, Want10B2 };
- int want;
- uchar ea[6];
- char *p;
-
- if(ether->irq == 0)
- ether->irq = 10;
- if(ether->port == 0)
- ether->port = 0x240;
- port = ether->port;
-
-// if(ioalloc(port, 0x10, 0, "3C589") < 0)
-// return -1;
-
- type = nil;
- slot = -1;
- for(i = 0; tcmpcmcia[i] != nil; i++){
- type = tcmpcmcia[i];
-if(debug) print("try %s...", type);
- if((slot = pcmspecial(type, ether)) >= 0)
- break;
- }
- if(slot < 0){
-if(debug) print("none found\n");
-// iofree(port);
- return -1;
- }
-
- /*
- * Read Ethernet address from card memory
- * on 3C562, but only if the user has not
- * overridden it.
- */
- memset(ea, 0, sizeof ea);
- if(memcmp(ea, ether->ea, 6) == 0 && strcmp(type, "3C562") == 0) {
- if(debug)
- print("read 562...");
- if(pcmcistuple(slot, 0x88, -1, ea, 6) == 6) {
- for(i = 0; i < 6; i += 2){
- t = ea[i];
- ea[i] = ea[i+1];
- ea[i+1] = t;
- }
- memmove(ether->ea, ea, 6);
- if(debug)
- print("ea %E", ea);
- }
- }
- /*
- * Allow user to specify desired media in plan9.ini
- */
- want = WantAny;
- for(i = 0; i < ether->nopt; i++){
- if(cistrncmp(ether->opt[i], "media=", 6) != 0)
- continue;
- p = ether->opt[i]+6;
- if(cistrcmp(p, "10base2") == 0)
- want = Want10B2;
- else if(cistrcmp(p, "10baseT") == 0)
- want = Want10BT;
- }
-
- /* try configuring as a 10BaseT */
- if(want==WantAny || want==Want10BT){
- if(configASIC(ether, port, xcvr10BaseT) < 0){
- pcmspecialclose(slot);
-// iofree(port);
- return -1;
- }
- delay(100);
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- if((ins(port+MediaStatus)&linkBeatDetect) || want==Want10BT){
- COMMAND(port, SelectRegisterWindow, Wop);
- print("#l%d: xcvr10BaseT %s\n", ether->ctlrno, type);
- return 0;
- }
- }
-
- /* try configuring as a 10base2 */
- if(want==WantAny || want==Want10B2){
- COMMAND(port, GlobalReset, 0);
- if(configASIC(ether, port, xcvr10Base2) < 0){
- pcmspecialclose(slot);
-// iofree(port);
- return -1;
- }
- print("#l%d: xcvr10Base2 %s\n", ether->ctlrno, type);
- return 0;
- }
- return -1; /* not reached */
-}
--- a/os/boot/pc/ether79c970.c
+++ /dev/null
@@ -1,539 +1,0 @@
-/*
- * AMD79C970
- * PCnet-PCI Single-Chip Ethernet Controller for PCI Local Bus
- * To do:
- * finish this rewrite
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum {
- Lognrdre = 6,
- Nrdre = (1<<Lognrdre),/* receive descriptor ring entries */
- Logntdre = 4,
- Ntdre = (1<<Logntdre),/* transmit descriptor ring entries */
-
- Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
-};
-
-enum { /* DWIO I/O resource map */
- Aprom = 0x0000, /* physical address */
- Rdp = 0x0010, /* register data port */
- Rap = 0x0014, /* register address port */
- Sreset = 0x0018, /* software reset */
- Bdp = 0x001C, /* bus configuration register data port */
-};
-
-enum { /* CSR0 */
- Init = 0x0001, /* begin initialisation */
- Strt = 0x0002, /* enable chip */
- Stop = 0x0004, /* disable chip */
- Tdmd = 0x0008, /* transmit demand */
- Txon = 0x0010, /* transmitter on */
- Rxon = 0x0020, /* receiver on */
- Iena = 0x0040, /* interrupt enable */
- Intr = 0x0080, /* interrupt flag */
- Idon = 0x0100, /* initialisation done */
- Tint = 0x0200, /* transmit interrupt */
- Rint = 0x0400, /* receive interrupt */
- Merr = 0x0800, /* memory error */
- Miss = 0x1000, /* missed frame */
- Cerr = 0x2000, /* collision */
- Babl = 0x4000, /* transmitter timeout */
- Err = 0x8000, /* Babl|Cerr|Miss|Merr */
-};
-
-enum { /* CSR3 */
- Bswp = 0x0004, /* byte swap */
- Emba = 0x0008, /* enable modified back-off algorithm */
- Dxmt2pd = 0x0010, /* disable transmit two part deferral */
- Lappen = 0x0020, /* look-ahead packet processing enable */
-};
-
-enum { /* CSR4 */
- ApadXmt = 0x0800, /* auto pad transmit */
-};
-
-enum { /* CSR15 */
- Prom = 0x8000, /* promiscuous mode */
-};
-
-typedef struct { /* Initialisation Block */
- ushort mode;
- uchar rlen; /* upper 4 bits */
- uchar tlen; /* upper 4 bits */
- uchar padr[6];
- uchar res[2];
- uchar ladr[8];
- ulong rdra;
- ulong tdra;
-} Iblock;
-
-typedef struct { /* descriptor ring entry */
- ulong addr;
- ulong md1; /* status|bcnt */
- ulong md2; /* rcc|rpc|mcnt */
- void* data;
-} Dre;
-
-enum { /* md1 */
- Enp = 0x01000000, /* end of packet */
- Stp = 0x02000000, /* start of packet */
- RxBuff = 0x04000000, /* buffer error */
- Def = 0x04000000, /* deferred */
- Crc = 0x08000000, /* CRC error */
- One = 0x08000000, /* one retry needed */
- Oflo = 0x10000000, /* overflow error */
- More = 0x10000000, /* more than one retry needed */
- Fram = 0x20000000, /* framing error */
- RxErr = 0x40000000, /* Fram|Oflo|Crc|RxBuff */
- TxErr = 0x40000000, /* Uflo|Lcol|Lcar|Rtry */
- Own = 0x80000000,
-};
-
-enum { /* md2 */
- Rtry = 0x04000000, /* failed after repeated retries */
- Lcar = 0x08000000, /* loss of carrier */
- Lcol = 0x10000000, /* late collision */
- Uflo = 0x40000000, /* underflow error */
- TxBuff = 0x80000000, /* buffer error */
-};
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
- Lock;
- int port;
- Pcidev* pcidev;
- Ctlr* next;
- int active;
-
- int init; /* initialisation in progress */
- Iblock iblock;
-
- Dre* rdr; /* receive descriptor ring */
- int rdrx;
-
- Dre* tdr; /* transmit descriptor ring */
- int tdrh; /* host index into tdr */
- int tdri; /* interface index into tdr */
- int ntq; /* descriptors active */
-
- ulong rxbuff; /* receive statistics */
- ulong crc;
- ulong oflo;
- ulong fram;
-
- ulong rtry; /* transmit statistics */
- ulong lcar;
- ulong lcol;
- ulong uflo;
- ulong txbuff;
-
- ulong merr; /* bobf is such a whiner */
- ulong miss;
- ulong babl;
-
- int (*ior)(Ctlr*, int);
- void (*iow)(Ctlr*, int, int);
-};
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-/*
- * The Rdp, Rap, Sreset, Bdp ports are 32-bit port offset in the enumeration above.
- * To get to 16-bit offsets, scale down with 0x10 staying the same.
- */
-static int
-io16r(Ctlr* c, int r)
-{
- if(r >= Rdp)
- r = (r-Rdp)/2+Rdp;
- return ins(c->port+r);
-}
-
-static void
-io16w(Ctlr* c, int r, int v)
-{
- if(r >= Rdp)
- r = (r-Rdp)/2+Rdp;
- outs(c->port+r, v);
-}
-
-static int
-io32r(Ctlr* c, int r)
-{
- return inl(c->port+r);
-}
-
-static void
-io32w(Ctlr* c, int r, int v)
-{
- outl(c->port+r, v);
-}
-
-static void
-attach(Ether*)
-{
-}
-
-static void
-detach(Ether* ether)
-{
- Ctlr *ctlr;
-
- ctlr = ether->ctlr;
- ctlr->iow(ctlr, Rdp, Iena|Stop);
-}
-
-static void
-ringinit(Ctlr* ctlr)
-{
- Dre *dre;
-
- /*
- * Initialise the receive and transmit buffer rings.
- * The ring entries must be aligned on 16-byte boundaries.
- *
- * This routine is protected by ctlr->init.
- */
- if(ctlr->rdr == 0){
- ctlr->rdr = ialloc(Nrdre*sizeof(Dre), 0x10);
- for(dre = ctlr->rdr; dre < &ctlr->rdr[Nrdre]; dre++){
- dre->data = malloc(Rbsize);
- dre->addr = PADDR(dre->data);
- dre->md2 = 0;
- dre->md1 = Own|(-Rbsize & 0xFFFF);
- }
- }
- ctlr->rdrx = 0;
-
- if(ctlr->tdr == 0)
- ctlr->tdr = ialloc(Ntdre*sizeof(Dre), 0x10);
- memset(ctlr->tdr, 0, Ntdre*sizeof(Dre));
- ctlr->tdrh = ctlr->tdri = 0;
-}
-
-static void
-transmit(Ether* ether)
-{
- Ctlr *ctlr;
- Block *bp;
- Dre *dre;
- RingBuf *tb;
-
- ctlr = ether->ctlr;
-
- if(ctlr->init)
- return;
-
- while(ctlr->ntq < (Ntdre-1)){
- tb = ðer->tb[ether->ti];
- if(tb->owner != Interface)
- break;
-
- bp = allocb(tb->len);
- memmove(bp->wp, tb->pkt, tb->len);
- memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
- bp->wp += tb->len;
-
- /*
- * Give ownership of the descriptor to the chip,
- * increment the software ring descriptor pointer
- * and tell the chip to poll.
- * There's no need to pad to ETHERMINTU
- * here as ApadXmt is set in CSR4.
- */
- dre = &ctlr->tdr[ctlr->tdrh];
- dre->data = bp;
- dre->addr = PADDR(bp->rp);
- dre->md2 = 0;
- dre->md1 = Own|Stp|Enp|Oflo|(-BLEN(bp) & 0xFFFF);
- ctlr->ntq++;
- ctlr->iow(ctlr, Rap, 0);
- ctlr->iow(ctlr, Rdp, Iena|Tdmd);
- ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
-
- tb->owner = Host;
- ether->ti = NEXT(ether->ti, ether->ntb);
- }
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
- Ctlr *ctlr;
- Ether *ether;
- int csr0;
- Dre *dre;
- RingBuf *rb;
-
- ether = arg;
- ctlr = ether->ctlr;
-
- /*
- * Acknowledge all interrupts and whine about those that shouldn't
- * happen.
- */
-intrloop:
- csr0 = ctlr->ior(ctlr, Rdp) & 0xFFFF;
- ctlr->iow(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena);
- if(csr0 & Merr)
- ctlr->merr++;
- if(csr0 & Miss)
- ctlr->miss++;
- if(csr0 & Babl)
- ctlr->babl++;
- //if(csr0 & (Babl|Miss|Merr))
- // print("#l%d: csr0 = 0x%uX\n", ether->ctlrno, csr0);
- if(!(csr0 & (Rint|Tint)))
- return;
-
- /*
- * Receiver interrupt: run round the descriptor ring logging
- * errors and passing valid receive data up to the higher levels
- * until a descriptor is encountered still owned by the chip.
- */
- if(csr0 & Rint){
- dre = &ctlr->rdr[ctlr->rdrx];
- while(!(dre->md1 & Own)){
- rb = ðer->rb[ether->ri];
- if(dre->md1 & RxErr){
- if(dre->md1 & RxBuff)
- ctlr->rxbuff++;
- if(dre->md1 & Crc)
- ctlr->crc++;
- if(dre->md1 & Oflo)
- ctlr->oflo++;
- if(dre->md1 & Fram)
- ctlr->fram++;
- }
- else if(rb->owner == Interface){
- rb->owner = Host;
- rb->len = (dre->md2 & 0x0FFF)-4;
- memmove(rb->pkt, dre->data, rb->len);
- ether->ri = NEXT(ether->ri, ether->nrb);
- }
-
- /*
- * Finished with this descriptor, reinitialise it,
- * give it back to the chip, then on to the next...
- */
- dre->md2 = 0;
- dre->md1 = Own|(-Rbsize & 0xFFFF);
-
- ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
- dre = &ctlr->rdr[ctlr->rdrx];
- }
- }
-
- /*
- * Transmitter interrupt: wakeup anyone waiting for a free descriptor.
- */
- if(csr0 & Tint){
- lock(ctlr);
- while(ctlr->ntq){
- dre = &ctlr->tdr[ctlr->tdri];
- if(dre->md1 & Own)
- break;
-
- if(dre->md1 & TxErr){
- if(dre->md2 & Rtry)
- ctlr->rtry++;
- if(dre->md2 & Lcar)
- ctlr->lcar++;
- if(dre->md2 & Lcol)
- ctlr->lcol++;
- if(dre->md2 & Uflo)
- ctlr->uflo++;
- if(dre->md2 & TxBuff)
- ctlr->txbuff++;
- }
-
- freeb(dre->data);
-
- ctlr->ntq--;
- ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
- }
- transmit(ether);
- unlock(ctlr);
- }
- goto intrloop;
-}
-
-static void
-amd79c970pci(void)
-{
- Ctlr *ctlr;
- Pcidev *p;
-
- p = nil;
- while(p = pcimatch(p, 0x1022, 0x2000)){
- ctlr = malloc(sizeof(Ctlr));
- ctlr->port = p->mem[0].bar & ~0x01;
- ctlr->pcidev = p;
-
- if(ctlrhead != nil)
- ctlrtail->next = ctlr;
- else
- ctlrhead = ctlr;
- ctlrtail = ctlr;
- }
-}
-
-int
-amd79c970reset(Ether* ether)
-{
- int x;
- uchar ea[Eaddrlen];
- Ctlr *ctlr;
-
- if(ctlrhead == nil)
- amd79c970pci();
-
- /*
- * Any adapter matches if no port is supplied,
- * otherwise the ports must match.
- */
- for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
- if(ctlr->active)
- continue;
- if(ether->port == 0 || ether->port == ctlr->port){
- ctlr->active = 1;
- break;
- }
- }
- if(ctlr == nil)
- return -1;
-
- /*
- * Allocate a controller structure and start to initialise it.
- */
- ether->ctlr = ctlr;
- ether->port = ctlr->port;
- ether->irq = ctlr->pcidev->intl;
- ether->tbdf = ctlr->pcidev->tbdf;
- pcisetbme(ctlr->pcidev);
- ilock(ctlr);
- ctlr->init = 1;
-
- io32r(ctlr, Sreset);
- io16r(ctlr, Sreset);
-
- if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){
- ctlr->ior = io16r;
- ctlr->iow = io16w;
- }else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){
- ctlr->ior = io32r;
- ctlr->iow = io32w;
- }else{
- print("#l%d: card doesn't talk right\n", ether->ctlrno);
- iunlock(ctlr);
- return -1;
- }
-
- ctlr->iow(ctlr, Rap, 88);
- x = ctlr->ior(ctlr, Rdp);
- ctlr->iow(ctlr, Rap, 89);
- x |= ctlr->ior(ctlr, Rdp)<<16;
-
- switch(x&0xFFFFFFF){
- case 0x2420003: /* PCnet/PCI 79C970 */
- case 0x2621003: /* PCnet/PCI II 79C970A */
- break;
- default:
- print("unknown PCnet card version %.7ux\n", x&0xFFFFFFF);
- iunlock(ctlr);
- return -1;
- }
-
- /*
- * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access.
- * Set the auto pad transmit in CSR4.
- */
- ctlr->iow(ctlr, Rap, 20);
- ctlr->iow(ctlr, Bdp, 0x0002);
-
- ctlr->iow(ctlr, Rap, 4);
- x = ctlr->ior(ctlr, Rdp) & 0xFFFF;
- ctlr->iow(ctlr, Rdp, ApadXmt|x);
-
- ctlr->iow(ctlr, Rap, 0);
-
- /*
- * Check if the adapter's station address is to be overridden.
- * If not, read it from the I/O-space and set in ether->ea prior to
- * loading the station address in the initialisation block.
- */
- memset(ea, 0, Eaddrlen);
- if(!memcmp(ea, ether->ea, Eaddrlen)){
- x = ctlr->ior(ctlr, Aprom);
- ether->ea[0] = x;
- ether->ea[1] = x>>8;
- if(ctlr->ior == io16r)
- x = ctlr->ior(ctlr, Aprom+2);
- else
- x >>= 16;
- ether->ea[2] = x;
- ether->ea[3] = x>>8;
- x = ctlr->ior(ctlr, Aprom+4);
- ether->ea[4] = x;
- ether->ea[5] = x>>8;
- }
-
- /*
- * Start to fill in the initialisation block
- * (must be DWORD aligned).
- */
- ctlr->iblock.rlen = Lognrdre<<4;
- ctlr->iblock.tlen = Logntdre<<4;
- memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr));
-
- ringinit(ctlr);
- ctlr->iblock.rdra = PADDR(ctlr->rdr);
- ctlr->iblock.tdra = PADDR(ctlr->tdr);
-
- /*
- * Point the chip at the initialisation block and tell it to go.
- * Mask the Idon interrupt and poll for completion. Strt and interrupt
- * enables will be set later when attaching to the network.
- */
- x = PADDR(&ctlr->iblock);
- ctlr->iow(ctlr, Rap, 1);
- ctlr->iow(ctlr, Rdp, x & 0xFFFF);
- ctlr->iow(ctlr, Rap, 2);
- ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF);
- ctlr->iow(ctlr, Rap, 3);
- ctlr->iow(ctlr, Rdp, Idon);
- ctlr->iow(ctlr, Rap, 0);
- ctlr->iow(ctlr, Rdp, Init);
-
- while(!(ctlr->ior(ctlr, Rdp) & Idon))
- ;
-
- /*
- * We used to set CSR0 to Idon|Stop here, and then
- * in attach change it to Iena|Strt. Apparently the simulated
- * 79C970 in VMware never enables after a write of Idon|Stop,
- * so we enable the device here now.
- */
- ctlr->iow(ctlr, Rdp, Iena|Strt);
- ctlr->init = 0;
- iunlock(ctlr);
-
- /*
- * Linkage to the generic ethernet driver.
- */
- ether->attach = attach;
- ether->transmit = transmit;
- ether->interrupt = interrupt;
- ether->detach = detach;
-
- return 0;
-}
--- a/os/boot/pc/ether8003.c
+++ /dev/null
@@ -1,258 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ether8390.h"
-
-/*
- * Western Digital/Standard Microsystems Corporation cards (WD80[01]3).
- * Also handles 8216 cards (Elite Ultra).
- * Configuration code based on that provided by SMC a long time ago.
- */
-enum { /* 83C584 Bus Interface Controller */
- Msr = 0x00, /* Memory Select Register */
- Icr = 0x01, /* Interface Configuration Register */
- Iar = 0x02, /* I/O Address Register */
- Bio = 0x03, /* BIOS ROM Address Register */
- Ear = 0x03, /* EEROM Address Register (shared with Bio) */
- Irr = 0x04, /* Interrupt Request Register */
- Hcr = 0x04, /* 8216 hardware control */
- Laar = 0x05, /* LA Address Register */
- Ijr = 0x06, /* Initialisation Jumpers */
- Gp2 = 0x07, /* General Purpose Data Register */
- Lar = 0x08, /* LAN Address Registers */
- Id = 0x0E, /* Card ID byte */
- Cksum = 0x0F, /* Checksum */
-};
-
-enum { /* Msr */
- Rst = 0x80, /* software reset */
- Menb = 0x40, /* memory enable */
-};
-
-enum { /* Icr */
- Bit16 = 0x01, /* 16-bit bus */
- Other = 0x02, /* other register access */
- Ir2 = 0x04, /* IR2 */
- Msz = 0x08, /* SRAM size */
- Rla = 0x10, /* recall LAN address */
- Rx7 = 0x20, /* recall all but I/O and LAN address */
- Rio = 0x40, /* recall I/O address from EEROM */
- Sto = 0x80, /* non-volatile EEROM store */
-};
-
-enum { /* Laar */
- ZeroWS16 = 0x20, /* zero wait states for 16-bit ops */
- L16en = 0x40, /* enable 16-bit LAN operation */
- M16en = 0x80, /* enable 16-bit memory access */
-};
-
-enum { /* Ijr */
- Ienable = 0x01, /* 8216 interrupt enable */
-};
-
-/*
- * Mapping from configuration bits to interrupt level.
- */
-static int irq8003[8] = {
- 9, 3, 5, 7, 10, 11, 15, 4,
-};
-
-static int irq8216[8] = {
- 0, 9, 3, 5, 7, 10, 11, 15,
-};
-
-static void
-reset8003(Ether* ether, uchar ea[Eaddrlen], uchar ic[8])
-{
- Dp8390 *ctlr;
- ulong port;
-
- ctlr = ether->ctlr;
- port = ether->port;
-
- /*
- * Check for old, dumb 8003E, which doesn't have an interface
- * chip. Only Msr exists out of the 1st eight registers, reads
- * of the others just alias the 2nd eight registers, the LAN
- * address ROM. Can check Icr, Irr and Laar against the ethernet
- * address read above and if they match it's an 8003E (or an
- * 8003EBT, 8003S, 8003SH or 8003WT, doesn't matter), in which
- * case the default irq gets used.
- */
- if(memcmp(&ea[1], &ic[1], 5) == 0){
- memset(ic, 0, sizeof(ic));
- ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
- }
- else{
- /*
- * As a final sanity check for the 8013EBT, which doesn't have
- * the 83C584 interface chip, but has 2 real registers, write Gp2
- * and if it reads back the same, it's not an 8013EBT.
- */
- outb(port+Gp2, 0xAA);
- inb(port+Msr); /* wiggle bus */
- if(inb(port+Gp2) != 0xAA){
- memset(ic, 0, sizeof(ic));
- ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
- }
- else
- ether->irq = irq8003[((ic[Irr]>>5) & 0x3)|(ic[Icr] & 0x4)];
-
- /*
- * Check if 16-bit card.
- * If Bit16 is read/write, then it's an 8-bit card.
- * If Bit16 is set, it's in a 16-bit slot.
- */
- outb(port+Icr, ic[Icr]^Bit16);
- inb(port+Msr); /* wiggle bus */
- if((inb(port+Icr) & Bit16) == (ic[Icr] & Bit16)){
- ctlr->width = 2;
- ic[Icr] &= ~Bit16;
- }
- outb(port+Icr, ic[Icr]);
-
- if(ctlr->width == 2 && (inb(port+Icr) & Bit16) == 0)
- ctlr->width = 1;
- }
-
- ether->mem = (ulong)KADDR((ic[Msr] & 0x3F)<<13);
- if(ctlr->width == 2)
- ether->mem |= (ic[Laar] & 0x1F)<<19;
- else
- ether->mem |= 0x80000;
-
- if(ic[Icr] & (1<<3))
- ether->size = 32*1024;
- if(ctlr->width == 2)
- ether->size <<= 1;
-
- /*
- * Enable interface RAM, set interface width.
- */
- outb(port+Msr, ic[Msr]|Menb);
- if(ctlr->width == 2)
- outb(port+Laar, ic[Laar]|L16en|M16en|ZeroWS16);
-}
-
-static void
-reset8216(Ether* ether, uchar[8])
-{
- uchar hcr, irq, x;
- ulong addr, port;
- Dp8390 *ctlr;
-
- ctlr = ether->ctlr;
- port = ether->port;
-
- ctlr->width = 2;
-
- /*
- * Switch to the alternate register set and retrieve the memory
- * and irq information.
- */
- hcr = inb(port+Hcr);
- outb(port+Hcr, 0x80|hcr);
- addr = inb(port+0x0B) & 0xFF;
- irq = inb(port+0x0D);
- outb(port+Hcr, hcr);
-
- ether->mem = (ulong)KADDR(0xC0000+((((addr>>2) & 0x30)|(addr & 0x0F))<<13));
- ether->size = 8192*(1<<((addr>>4) & 0x03));
- ether->irq = irq8216[((irq>>4) & 0x04)|((irq>>2) & 0x03)];
-
- /*
- * Enable interface RAM, set interface width, and enable interrupts.
- */
- x = inb(port+Msr) & ~Rst;
- outb(port+Msr, Menb|x);
- x = inb(port+Laar);
- outb(port+Laar, M16en|x);
- outb(port+Ijr, Ienable);
-}
-
-/*
- * Get configuration parameters, enable memory.
- * There are opportunities here for buckets of code, try to resist.
- */
-int
-wd8003reset(Ether* ether)
-{
- int i;
- uchar ea[Eaddrlen], ic[8], id, nullea[Eaddrlen], sum;
- ulong port;
- Dp8390 *ctlr;
-
- /*
- * Set up the software configuration.
- * Use defaults for port, irq, mem and size if not specified.
- * Defaults are set for the dumb 8003E which can't be
- * autoconfigured.
- */
- if(ether->port == 0)
- ether->port = 0x280;
- if(ether->irq == 0)
- ether->irq = 3;
- if(ether->mem == 0)
- ether->mem = 0xD0000;
- if(ether->size == 0)
- ether->size = 8*1024;
-
- /*
- * Look for the interface. Read the LAN address ROM
- * and validate the checksum - the sum of all 8 bytes
- * should be 0xFF.
- * At the same time, get the (possible) interface chip
- * registers, they'll be used later to check for aliasing.
- */
- port = ether->port;
- sum = 0;
- for(i = 0; i < sizeof(ea); i++){
- ea[i] = inb(port+Lar+i);
- sum += ea[i];
- ic[i] = inb(port+i);
- }
- id = inb(port+Id);
- sum += id;
- sum += inb(port+Cksum);
- if(sum != 0xFF)
- return -1;
-
- ether->ctlr = malloc(sizeof(Dp8390));
- ctlr = ether->ctlr;
- ctlr->ram = 1;
-
- if((id & 0xFE) == 0x2A)
- reset8216(ether, ic);
- else
- reset8003(ether, ea, ic);
-
- /*
- * Set the DP8390 ring addresses.
- */
- ctlr->port = port+0x10;
- ctlr->tstart = 0;
- ctlr->pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
- ctlr->pstop = HOWMANY(ether->size, Dp8390BufSz);
-
- /*
- * Finally, init the 8390, set the ethernet address
- * and claim the memory used.
- */
- dp8390reset(ether);
- memset(nullea, 0, Eaddrlen);
- if(memcmp(nullea, ether->ea, Eaddrlen) == 0){
- for(i = 0; i < sizeof(ether->ea); i++)
- ether->ea[i] = ea[i];
- }
- dp8390setea(ether);
-
- if(umbrwmalloc(PADDR(ether->mem), ether->size, 0) == 0)
- print("ether8003: warning - 0x%luX unavailable", PADDR(ether->mem));
-
- return 0;
-}
--- a/os/boot/pc/ether8139.c
+++ /dev/null
@@ -1,614 +1,0 @@
-/*
- * Realtek 8139 (but not the 8129).
- * Error recovery for the various over/under -flow conditions
- * may need work.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum { /* registers */
- Idr0 = 0x0000, /* MAC address */
- Mar0 = 0x0008, /* Multicast address */
- Tsd0 = 0x0010, /* Transmit Status Descriptor0 */
- Tsad0 = 0x0020, /* Transmit Start Address Descriptor0 */
- Rbstart = 0x0030, /* Receive Buffer Start Address */
- Erbcr = 0x0034, /* Early Receive Byte Count */
- Ersr = 0x0036, /* Early Receive Status */
- Cr = 0x0037, /* Command Register */
- Capr = 0x0038, /* Current Address of Packet Read */
- Cbr = 0x003A, /* Current Buffer Address */
- Imr = 0x003C, /* Interrupt Mask */
- Isr = 0x003E, /* Interrupt Status */
- Tcr = 0x0040, /* Transmit Configuration */
- Rcr = 0x0044, /* Receive Configuration */
- Tctr = 0x0048, /* Timer Count */
- Mpc = 0x004C, /* Missed Packet Counter */
- Cr9346 = 0x0050, /* 9346 Command Register */
- Config0 = 0x0051, /* Configuration Register 0 */
- Config1 = 0x0052, /* Configuration Register 1 */
- TimerInt = 0x0054, /* Timer Interrupt */
- Msr = 0x0058, /* Media Status */
- Config3 = 0x0059, /* Configuration Register 3 */
- Config4 = 0x005A, /* Configuration Register 4 */
- Mulint = 0x005C, /* Multiple Interrupt Select */
- RerID = 0x005E, /* PCI Revision ID */
- Tsad = 0x0060, /* Transmit Status of all Descriptors */
-
- Bmcr = 0x0062, /* Basic Mode Control */
- Bmsr = 0x0064, /* Basic Mode Status */
- Anar = 0x0066, /* Auto-Negotiation Advertisment */
- Anlpar = 0x0068, /* Auto-Negotiation Link Partner */
- Aner = 0x006A, /* Auto-Negotiation Expansion */
- Dis = 0x006C, /* Disconnect Counter */
- Fcsc = 0x006E, /* False Carrier Sense Counter */
- Nwaytr = 0x0070, /* N-way Test */
- Rec = 0x0072, /* RX_ER Counter */
- Cscr = 0x0074, /* CS Configuration */
- Phy1parm = 0x0078, /* PHY Parameter 1 */
- Twparm = 0x007C, /* Twister Parameter */
- Phy2parm = 0x0080, /* PHY Parameter 2 */
-};
-
-enum { /* Cr */
- Bufe = 0x01, /* Rx Buffer Empty */
- Te = 0x04, /* Transmitter Enable */
- Re = 0x08, /* Receiver Enable */
- Rst = 0x10, /* Software Reset */
-};
-
-enum { /* Imr/Isr */
- Rok = 0x0001, /* Receive OK */
- Rer = 0x0002, /* Receive Error */
- Tok = 0x0004, /* Transmit OK */
- Ter = 0x0008, /* Transmit Error */
- Rxovw = 0x0010, /* Receive Buffer Overflow */
- PunLc = 0x0020, /* Packet Underrun or Link Change */
- Fovw = 0x0040, /* Receive FIFO Overflow */
- Clc = 0x2000, /* Cable Length Change */
- Timer = 0x4000, /* Timer */
- Serr = 0x8000, /* System Error */
-};
-
-enum { /* Tcr */
- Clrabt = 0x00000001, /* Clear Abort */
- TxrrSHIFT = 4, /* Transmit Retry Count */
- TxrrMASK = 0x000000F0,
- MtxdmaSHIFT = 8, /* Max. DMA Burst Size */
- MtxdmaMASK = 0x00000700,
- Mtxdma2048 = 0x00000700,
- Acrc = 0x00010000, /* Append CRC (not) */
- LbkSHIFT = 17, /* Loopback Test */
- LbkMASK = 0x00060000,
- IfgSHIFT = 24, /* Interframe Gap */
- IfgMASK = 0x03000000,
- HwveridSHIFT = 22, /* Hardware Version ID */
- HwveridMASK = 0x7CC00000,
-};
-
-enum { /* Rcr */
- Aap = 0x00000001, /* Accept All Packets */
- Apm = 0x00000002, /* Accept Physical Match */
- Am = 0x00000004, /* Accept Multicast */
- Ab = 0x00000008, /* Accept Broadcast */
- Ar = 0x00000010, /* Accept Runt */
- Aer = 0x00000020, /* Accept Error */
- Sel9356 = 0x00000040, /* 9356 EEPROM used */
- Wrap = 0x00000080, /* Rx Buffer Wrap Control */
- MrxdmaSHIFT = 8, /* Max. DMA Burst Size */
- MrxdmaMASK = 0x00000700,
- Mrxdmaunlimited = 0x00000700,
- RblenSHIFT = 11, /* Receive Buffer Length */
- RblenMASK = 0x00001800,
- Rblen8K = 0x00000000, /* 8KB+16 */
- Rblen16K = 0x00000800, /* 16KB+16 */
- Rblen32K = 0x00001000, /* 32KB+16 */
- Rblen64K = 0x00001800, /* 64KB+16 */
- RxfthSHIFT = 13, /* Receive Buffer Length */
- RxfthMASK = 0x0000E000,
- Rxfth256 = 0x00008000,
- Rxfthnone = 0x0000E000,
- Rer8 = 0x00010000, /* Accept Error Packets > 8 bytes */
- MulERINT = 0x00020000, /* Multiple Early Interrupt Select */
- ErxthSHIFT = 24, /* Early Rx Threshold */
- ErxthMASK = 0x0F000000,
- Erxthnone = 0x00000000,
-};
-
-enum { /* Received Packet Status */
- Rcok = 0x0001, /* Receive Completed OK */
- Fae = 0x0002, /* Frame Alignment Error */
- Crc = 0x0004, /* CRC Error */
- Long = 0x0008, /* Long Packet */
- Runt = 0x0010, /* Runt Packet Received */
- Ise = 0x0020, /* Invalid Symbol Error */
- Bar = 0x2000, /* Broadcast Address Received */
- Pam = 0x4000, /* Physical Address Matched */
- Mar = 0x8000, /* Multicast Address Received */
-};
-
-enum { /* Media Status Register */
- Rxpf = 0x01, /* Pause Flag */
- Txpf = 0x02, /* Pause Flag */
- Linkb = 0x04, /* Inverse of Link Status */
- Speed10 = 0x08, /* 10Mbps */
- Auxstatus = 0x10, /* Aux. Power Present Status */
- Rxfce = 0x40, /* Receive Flow Control Enable */
- Txfce = 0x80, /* Transmit Flow Control Enable */
-};
-
-typedef struct { /* Soft Transmit Descriptor */
- int tsd;
- int tsad;
- uchar* data;
-} Td;
-
-enum { /* Tsd0 */
- SizeSHIFT = 0, /* Descriptor Size */
- SizeMASK = 0x00001FFF,
- Own = 0x00002000,
- Tun = 0x00004000, /* Transmit FIFO Underrun */
- Tcok = 0x00008000, /* Transmit COmpleted OK */
- EtxthSHIFT = 16, /* Early Tx Threshold */
- EtxthMASK = 0x001F0000,
- NccSHIFT = 24, /* Number of Collisions Count */
- NccMASK = 0x0F000000,
- Cdh = 0x10000000, /* CD Heartbeat */
- Owc = 0x20000000, /* Out of Window Collision */
- Tabt = 0x40000000, /* Transmit Abort */
- Crs = 0x80000000, /* Carrier Sense Lost */
-};
-
-enum {
- Rblen = Rblen64K, /* Receive Buffer Length */
- Ntd = 4, /* Number of Transmit Descriptors */
- Tdbsz = ROUNDUP(sizeof(Etherpkt), 4),
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
- int port;
- Pcidev* pcidev;
- Ctlr* next;
- int active;
- int id;
-
- Lock ilock; /* init */
- void* alloc; /* base of per-Ctlr allocated data */
-
- int rcr; /* receive configuration register */
- uchar* rbstart; /* receive buffer */
- int rblen; /* receive buffer length */
- int ierrs; /* receive errors */
-
- Lock tlock; /* transmit */
- Td td[Ntd];
- int ntd; /* descriptors active */
- int tdh; /* host index into td */
- int tdi; /* interface index into td */
- int etxth; /* early transmit threshold */
- int taligned; /* packet required no alignment */
- int tunaligned; /* packet required alignment */
-
- int dis; /* disconnect counter */
- int fcsc; /* false carrier sense counter */
- int rec; /* RX_ER counter */
-} Ctlr;
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-#define csr8r(c, r) (inb((c)->port+(r)))
-#define csr16r(c, r) (ins((c)->port+(r)))
-#define csr32r(c, r) (inl((c)->port+(r)))
-#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
-#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
-#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
-
-static int
-rtl8139reset(Ctlr* ctlr)
-{
- /*
- * Soft reset the controller.
- */
- csr8w(ctlr, Cr, Rst);
- while(csr8r(ctlr, Cr) & Rst)
- ;
-
- return 0;
-}
-
-static void
-rtl8139detach(Ether* edev)
-{
- rtl8139reset(edev->ctlr);
-}
-
-static void
-rtl8139halt(Ctlr* ctlr)
-{
- csr8w(ctlr, Cr, 0);
- csr16w(ctlr, Imr, 0);
- csr16w(ctlr, Isr, ~0);
-}
-
-static void
-rtl8139init(Ether* edev)
-{
- int i;
- ulong r;
- Ctlr *ctlr;
- uchar *alloc;
-
- ctlr = edev->ctlr;
- ilock(&ctlr->ilock);
-
- rtl8139halt(ctlr);
-
- /*
- * MAC Address.
- */
- r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
- csr32w(ctlr, Idr0, r);
- r = (edev->ea[5]<<8)|edev->ea[4];
- csr32w(ctlr, Idr0+4, r);
-
- /*
- * Receiver
- */
- alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 32);
- ctlr->rbstart = alloc;
- alloc += ctlr->rblen+16;
- memset(ctlr->rbstart, 0, ctlr->rblen+16);
- csr32w(ctlr, Rbstart, PADDR(ctlr->rbstart));
- ctlr->rcr = Rxfth256|Rblen|Mrxdmaunlimited|Ab|Apm;
-
- /*
- * Transmitter.
- */
- for(i = 0; i < Ntd; i++){
- ctlr->td[i].tsd = Tsd0+i*4;
- ctlr->td[i].tsad = Tsad0+i*4;
- ctlr->td[i].data = alloc;
- alloc += Tdbsz;
- }
- ctlr->ntd = ctlr->tdh = ctlr->tdi = 0;
- ctlr->etxth = 128/32;
-
- /*
- * Interrupts.
- */
- csr32w(ctlr, TimerInt, 0);
- csr16w(ctlr, Imr, Serr|Timer|Fovw|PunLc|Rxovw|Ter|Tok|Rer|Rok);
- csr32w(ctlr, Mpc, 0);
-
- /*
- * Enable receiver/transmitter.
- * Need to enable before writing the Rcr or it won't take.
- */
- csr8w(ctlr, Cr, Te|Re);
- csr32w(ctlr, Tcr, Mtxdma2048);
- csr32w(ctlr, Rcr, ctlr->rcr);
-
- iunlock(&ctlr->ilock);
-}
-
-static void
-rtl8139attach(Ether* edev)
-{
- Ctlr *ctlr;
-
- ctlr = edev->ctlr;
- if(ctlr->alloc == nil){
- ctlr->rblen = 1<<((Rblen>>RblenSHIFT)+13);
- ctlr->alloc = mallocz(ctlr->rblen+16 + Ntd*Tdbsz + 32, 0);
- rtl8139init(edev);
- }
-}
-
-static void
-rtl8139txstart(Ether* edev)
-{
- Td *td;
- Ctlr *ctlr;
- RingBuf *tb;
-
- ctlr = edev->ctlr;
- while(ctlr->ntd < Ntd){
- tb = &edev->tb[edev->ti];
- if(tb->owner != Interface)
- break;
-
- td = &ctlr->td[ctlr->tdh];
- memmove(td->data, tb->pkt, tb->len);
- csr32w(ctlr, td->tsad, PADDR(tb->pkt));
- csr32w(ctlr, td->tsd, (ctlr->etxth<<EtxthSHIFT)|tb->len);
-
- ctlr->ntd++;
- ctlr->tdh = NEXT(ctlr->tdh, Ntd);
- tb->owner = Host;
- edev->ti = NEXT(edev->ti, edev->ntb);
- }
-}
-
-static void
-rtl8139transmit(Ether* edev)
-{
- Ctlr *ctlr;
-
- ctlr = edev->ctlr;
- ilock(&ctlr->tlock);
- rtl8139txstart(edev);
- iunlock(&ctlr->tlock);
-}
-
-static void
-rtl8139receive(Ether* edev)
-{
- Ctlr *ctlr;
- RingBuf *rb;
- ushort capr;
- uchar cr, *p;
- int l, length, status;
-
- ctlr = edev->ctlr;
-
- /*
- * Capr is where the host is reading from,
- * Cbr is where the NIC is currently writing.
- */
- capr = (csr16r(ctlr, Capr)+16) % ctlr->rblen;
- while(!(csr8r(ctlr, Cr) & Bufe)){
- p = ctlr->rbstart+capr;
-
- /*
- * Apparently the packet length may be 0xFFF0 if
- * the NIC is still copying the packet into memory.
- */
- length = (*(p+3)<<8)|*(p+2);
- if(length == 0xFFF0)
- break;
- status = (*(p+1)<<8)|*p;
-
- if(!(status & Rcok)){
- /*
- * Reset the receiver.
- * Also may have to restore the multicast list
- * here too if it ever gets used.
- */
- cr = csr8r(ctlr, Cr);
- csr8w(ctlr, Cr, cr & ~Re);
- csr32w(ctlr, Rbstart, PADDR(ctlr->rbstart));
- csr8w(ctlr, Cr, cr);
- csr32w(ctlr, Rcr, ctlr->rcr);
-
- continue;
- }
-
- /*
- * Receive Completed OK.
- * Very simplistic; there are ways this could be done
- * without copying, but the juice probably isn't worth
- * the squeeze.
- * The packet length includes a 4 byte CRC on the end.
- */
- capr = (capr+4) % ctlr->rblen;
- p = ctlr->rbstart+capr;
- capr = (capr+length) % ctlr->rblen;
-
- rb = &edev->rb[edev->ri];
- l = 0;
- if(p+length >= ctlr->rbstart+ctlr->rblen){
- l = ctlr->rbstart+ctlr->rblen - p;
- if(rb->owner == Interface)
- memmove(rb->pkt, p, l);
- length -= l;
- p = ctlr->rbstart;
- }
- if(length > 0 && rb->owner == Interface){
- memmove(rb->pkt+l, p, length);
- l += length;
- }
- if(rb->owner == Interface){
- rb->owner = Host;
- rb->len = l-4;
- edev->ri = NEXT(edev->ri, edev->nrb);
- }
-
- capr = ROUNDUP(capr, 4);
- csr16w(ctlr, Capr, capr-16);
- }
-}
-
-static void
-rtl8139interrupt(Ureg*, void* arg)
-{
- Td *td;
- Ctlr *ctlr;
- Ether *edev;
- int isr, tsd;
-
- edev = arg;
- ctlr = edev->ctlr;
-
- while((isr = csr16r(ctlr, Isr)) != 0){
- csr16w(ctlr, Isr, isr);
- if(isr & (Fovw|PunLc|Rxovw|Rer|Rok)){
- rtl8139receive(edev);
- if(!(isr & Rok))
- ctlr->ierrs++;
- isr &= ~(Fovw|Rxovw|Rer|Rok);
- }
-
- if(isr & (Ter|Tok)){
- ilock(&ctlr->tlock);
- while(ctlr->ntd){
- td = &ctlr->td[ctlr->tdi];
- tsd = csr32r(ctlr, td->tsd);
- if(!(tsd & (Tabt|Tun|Tcok)))
- break;
-
- if(!(tsd & Tcok)){
- if(tsd & Tun){
- if(ctlr->etxth < ETHERMAXTU/32)
- ctlr->etxth++;
- }
- }
-
- ctlr->ntd--;
- ctlr->tdi = NEXT(ctlr->tdi, Ntd);
- }
- rtl8139txstart(edev);
- iunlock(&ctlr->tlock);
- isr &= ~(Ter|Tok);
- }
-
- if(isr & PunLc)
- isr &= ~(Clc|PunLc);
-
- /*
- * Only Serr|Timer should be left by now.
- * Should anything be done to tidy up? TimerInt isn't
- * used so that can be cleared. A PCI bus error is indicated
- * by Serr, that's pretty serious; is there anyhing to do
- * other than try to reinitialise the chip?
- */
- if((isr & (Serr|Timer)) != 0){
- print("rtl8139interrupt: imr %4.4uX isr %4.4uX\n",
- csr16r(ctlr, Imr), isr);
- if(isr & Timer)
- csr32w(ctlr, TimerInt, 0);
- if(isr & Serr)
- rtl8139init(edev);
- }
- }
-}
-
-static Ctlr*
-rtl8139match(Ether* edev, int id)
-{
- int port;
- Pcidev *p;
- Ctlr *ctlr;
-
- /*
- * Any adapter matches if no edev->port is supplied,
- * otherwise the ports must match.
- */
- for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
- if(ctlr->active)
- continue;
- p = ctlr->pcidev;
- if(((p->did<<16)|p->vid) != id)
- continue;
- port = p->mem[0].bar & ~0x01;
- if(edev->port != 0 && edev->port != port)
- continue;
-
- ctlr->port = port;
- if(rtl8139reset(ctlr))
- continue;
- pcisetbme(p);
-
- ctlr->active = 1;
- return ctlr;
- }
- return nil;
-}
-
-static struct {
- char* name;
- int id;
-} rtl8139pci[] = {
- { "rtl8139", (0x8139<<16)|0x10EC, }, /* generic */
- { "smc1211", (0x1211<<16)|0x1113, }, /* SMC EZ-Card */
- { "dfe-538tx", (0x1300<<16)|0x1186, }, /* D-Link DFE-538TX */
- { "dfe-560txd", (0x1340<<16)|0x1186, }, /* D-Link DFE-560TXD */
- { nil },
-};
-
-int
-rtl8139pnp(Ether* edev)
-{
- int i, id;
- Pcidev *p;
- Ctlr *ctlr;
- uchar ea[Eaddrlen];
-
- /*
- * Make a list of all ethernet controllers
- * if not already done.
- */
- if(ctlrhead == nil){
- p = nil;
- while(p = pcimatch(p, 0, 0)){
- if(p->ccrb != 0x02 || p->ccru != 0)
- continue;
- ctlr = malloc(sizeof(Ctlr));
- ctlr->pcidev = p;
- ctlr->id = (p->did<<16)|p->vid;
-
- if(ctlrhead != nil)
- ctlrtail->next = ctlr;
- else
- ctlrhead = ctlr;
- ctlrtail = ctlr;
- }
- }
-
- /*
- * Is it an RTL8139 under a different name?
- * Normally a search is made through all the found controllers
- * for one which matches any of the known vid+did pairs.
- * If a vid+did pair is specified a search is made for that
- * specific controller only.
- */
- id = 0;
- for(i = 0; i < edev->nopt; i++){
- if(cistrncmp(edev->opt[i], "id=", 3) == 0)
- id = strtol(&edev->opt[i][3], nil, 0);
- }
-
- ctlr = nil;
- if(id != 0)
- ctlr = rtl8139match(edev, id);
- else for(i = 0; rtl8139pci[i].name; i++){
- if((ctlr = rtl8139match(edev, rtl8139pci[i].id)) != nil)
- break;
- }
- if(ctlr == nil)
- return -1;
-
- edev->ctlr = ctlr;
- edev->port = ctlr->port;
- edev->irq = ctlr->pcidev->intl;
- edev->tbdf = ctlr->pcidev->tbdf;
-
- /*
- * Check if the adapter's station address is to be overridden.
- * If not, read it from the device and set in edev->ea.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, edev->ea, Eaddrlen) == 0){
- i = csr32r(ctlr, Idr0);
- edev->ea[0] = i;
- edev->ea[1] = i>>8;
- edev->ea[2] = i>>16;
- edev->ea[3] = i>>24;
- i = csr32r(ctlr, Idr0+4);
- edev->ea[4] = i;
- edev->ea[5] = i>>8;
- }
-
- edev->attach = rtl8139attach;
- edev->transmit = rtl8139transmit;
- edev->interrupt = rtl8139interrupt;
- edev->detach = rtl8139detach;
-
- return 0;
-}
--- a/os/boot/pc/ether8169.c
+++ /dev/null
@@ -1,958 +1,0 @@
-/*
- * Realtek RTL8110S/8169S.
- * Mostly there. There are some magic register values used
- * which are not described in any datasheet or driver but seem
- * to be necessary.
- * Why is the Fovf descriptor bit set for every received packet?
- * Occasionally the hardware indicates an input TCP checksum error
- * although the higher-level software seems to check the packet OK?
- * No tuning has been done. Only tested on an RTL8110S, there
- * are slight differences between the chips in the series so some
- * tweaks may be needed.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-typedef struct QLock { int r; } QLock;
-#define qlock(i) while(0)
-#define qunlock(i) while(0)
-#define iallocb allocb
-#define iprint print
-#define mallocalign(n, a, o, s) ialloc((n), (a))
-
-#include "etherif.h"
-#include "ethermii.h"
-
-enum { /* registers */
- Idr0 = 0x00, /* MAC address */
- Mar0 = 0x08, /* Multicast address */
- Dtccr = 0x10, /* Dump Tally Counter Command */
- Tnpds = 0x20, /* Transmit Normal Priority Descriptors */
- Thpds = 0x28, /* Transmit High Priority Descriptors */
- Flash = 0x30, /* Flash Memory Read/Write */
- Erbcr = 0x34, /* Early Receive Byte Count */
- Ersr = 0x36, /* Early Receive Status */
- Cr = 0x37, /* Command Register */
- Tppoll = 0x38, /* Transmit Priority Polling */
- Imr = 0x3C, /* Interrupt Mask */
- Isr = 0x3E, /* Interrupt Status */
- Tcr = 0x40, /* Transmit Configuration */
- Rcr = 0x44, /* Receive Configuration */
- Tctr = 0x48, /* Timer Count */
- Mpc = 0x4C, /* Missed Packet Counter */
- Cr9346 = 0x50, /* 9346 Command Register */
- Config0 = 0x51, /* Configuration Register 0 */
- Config1 = 0x52, /* Configuration Register 1 */
- Config2 = 0x53, /* Configuration Register 2 */
- Config3 = 0x54, /* Configuration Register 3 */
- Config4 = 0x55, /* Configuration Register 4 */
- Config5 = 0x56, /* Configuration Register 5 */
- Timerint = 0x58, /* Timer Interrupt */
- Mulint = 0x5C, /* Multiple Interrupt Select */
- Phyar = 0x60, /* PHY Access */
- Tbicsr0 = 0x64, /* TBI Control and Status */
- Tbianar = 0x68, /* TBI Auto-Negotiation Advertisment */
- Tbilpar = 0x6A, /* TBI Auto-Negotiation Link Partner */
- Phystatus = 0x6C, /* PHY Status */
-
- Rms = 0xDA, /* Receive Packet Maximum Size */
- Cplusc = 0xE0, /* C+ Command */
- Rdsar = 0xE4, /* Receive Descriptor Start Address */
- Mtps = 0xEC, /* Max. Transmit Packet Size */
-};
-
-enum { /* Dtccr */
- Cmd = 0x00000008, /* Command */
-};
-
-enum { /* Cr */
- Te = 0x04, /* Transmitter Enable */
- Re = 0x08, /* Receiver Enable */
- Rst = 0x10, /* Software Reset */
-};
-
-enum { /* Tppoll */
- Fswint = 0x01, /* Forced Software Interrupt */
- Npq = 0x40, /* Normal Priority Queue polling */
- Hpq = 0x80, /* High Priority Queue polling */
-};
-
-enum { /* Imr/Isr */
- Rok = 0x0001, /* Receive OK */
- Rer = 0x0002, /* Receive Error */
- Tok = 0x0004, /* Transmit OK */
- Ter = 0x0008, /* Transmit Error */
- Rdu = 0x0010, /* Receive Descriptor Unavailable */
- Punlc = 0x0020, /* Packet Underrun or Link Change */
- Fovw = 0x0040, /* Receive FIFO Overflow */
- Tdu = 0x0080, /* Transmit Descriptor Unavailable */
- Swint = 0x0100, /* Software Interrupt */
- Timeout = 0x4000, /* Timer */
- Serr = 0x8000, /* System Error */
-};
-
-enum { /* Tcr */
- MtxdmaSHIFT = 8, /* Max. DMA Burst Size */
- MtxdmaMASK = 0x00000700,
- Mtxdmaunlimited = 0x00000700,
- Acrc = 0x00010000, /* Append CRC (not) */
- Lbk0 = 0x00020000, /* Loopback Test 0 */
- Lbk1 = 0x00040000, /* Loopback Test 1 */
- Ifg2 = 0x00080000, /* Interframe Gap 2 */
- HwveridSHIFT = 23, /* Hardware Version ID */
- HwveridMASK = 0x7C800000,
- Macv01 = 0x00000000, /* RTL8169 */
- Macv02 = 0x00800000, /* RTL8169S/8110S */
- Macv03 = 0x04000000, /* RTL8169S/8110S */
- Macv04 = 0x10000000, /* RTL8169SB/8110SB */
- Macv05 = 0x18000000, /* RTL8169SC/8110SC */
- Macv11 = 0x30000000, /* RTL8168B/8111B */
- Macv12 = 0x38000000, /* RTL8169B/8111B */
- Macv13 = 0x34000000, /* RTL8101E */
- Macv14 = 0x30800000, /* RTL8100E */
- Macv15 = 0x38800000, /* RTL8100E */
- Ifg0 = 0x01000000, /* Interframe Gap 0 */
- Ifg1 = 0x02000000, /* Interframe Gap 1 */
-};
-
-enum { /* Rcr */
- Aap = 0x00000001, /* Accept All Packets */
- Apm = 0x00000002, /* Accept Physical Match */
- Am = 0x00000004, /* Accept Multicast */
- Ab = 0x00000008, /* Accept Broadcast */
- Ar = 0x00000010, /* Accept Runt */
- Aer = 0x00000020, /* Accept Error */
- Sel9356 = 0x00000040, /* 9356 EEPROM used */
- MrxdmaSHIFT = 8, /* Max. DMA Burst Size */
- MrxdmaMASK = 0x00000700,
- Mrxdmaunlimited = 0x00000700,
- RxfthSHIFT = 13, /* Receive Buffer Length */
- RxfthMASK = 0x0000E000,
- Rxfth256 = 0x00008000,
- Rxfthnone = 0x0000E000,
- Rer8 = 0x00010000, /* Accept Error Packets > 8 bytes */
- MulERINT = 0x01000000, /* Multiple Early Interrupt Select */
-};
-
-enum { /* Cr9346 */
- Eedo = 0x01, /* */
- Eedi = 0x02, /* */
- Eesk = 0x04, /* */
- Eecs = 0x08, /* */
- Eem0 = 0x40, /* Operating Mode */
- Eem1 = 0x80,
-};
-
-enum { /* Phyar */
- DataMASK = 0x0000FFFF, /* 16-bit GMII/MII Register Data */
- DataSHIFT = 0,
- RegaddrMASK = 0x001F0000, /* 5-bit GMII/MII Register Address */
- RegaddrSHIFT = 16,
- Flag = 0x80000000, /* */
-};
-
-enum { /* Phystatus */
- Fd = 0x01, /* Full Duplex */
- Linksts = 0x02, /* Link Status */
- Speed10 = 0x04, /* */
- Speed100 = 0x08, /* */
- Speed1000 = 0x10, /* */
- Rxflow = 0x20, /* */
- Txflow = 0x40, /* */
- Entbi = 0x80, /* */
-};
-
-enum { /* Cplusc */
- Mulrw = 0x0008, /* PCI Multiple R/W Enable */
- Dac = 0x0010, /* PCI Dual Address Cycle Enable */
- Rxchksum = 0x0020, /* Receive Checksum Offload Enable */
- Rxvlan = 0x0040, /* Receive VLAN De-tagging Enable */
- Endian = 0x0200, /* Endian Mode */
-};
-
-typedef struct D D; /* Transmit/Receive Descriptor */
-struct D {
- u32 control;
- u32 vlan;
- u32 addrlo;
- u32 addrhi;
-};
-
-enum { /* Transmit Descriptor control */
- TxflMASK = 0x0000FFFF, /* Transmit Frame Length */
- TxflSHIFT = 0,
- Tcps = 0x00010000, /* TCP Checksum Offload */
- Udpcs = 0x00020000, /* UDP Checksum Offload */
- Ipcs = 0x00040000, /* IP Checksum Offload */
- Lgsen = 0x08000000, /* Large Send */
-};
-
-enum { /* Receive Descriptor control */
- RxflMASK = 0x00003FFF, /* Receive Frame Length */
- RxflSHIFT = 0,
- Tcpf = 0x00004000, /* TCP Checksum Failure */
- Udpf = 0x00008000, /* UDP Checksum Failure */
- Ipf = 0x00010000, /* IP Checksum Failure */
- Pid0 = 0x00020000, /* Protocol ID0 */
- Pid1 = 0x00040000, /* Protocol ID1 */
- Crce = 0x00080000, /* CRC Error */
- Runt = 0x00100000, /* Runt Packet */
- Res = 0x00200000, /* Receive Error Summary */
- Rwt = 0x00400000, /* Receive Watchdog Timer Expired */
- Fovf = 0x00800000, /* FIFO Overflow */
- Bovf = 0x01000000, /* Buffer Overflow */
- Bar = 0x02000000, /* Broadcast Address Received */
- Pam = 0x04000000, /* Physical Address Matched */
- Mar = 0x08000000, /* Multicast Address Received */
-};
-
-enum { /* General Descriptor control */
- Ls = 0x10000000, /* Last Segment Descriptor */
- Fs = 0x20000000, /* First Segment Descriptor */
- Eor = 0x40000000, /* End of Descriptor Ring */
- Own = 0x80000000, /* Ownership */
-};
-
-/*
- */
-enum { /* Ring sizes (<= 1024) */
- Ntd = 8, /* Transmit Ring */
- Nrd = 32, /* Receive Ring */
-
- Mps = ROUNDUP(ETHERMAXTU+4, 128),
-};
-
-typedef struct Dtcc Dtcc;
-struct Dtcc {
- u64int txok;
- u64int rxok;
- u64int txer;
- u32 rxer;
- u16int misspkt;
- u16int fae;
- u32 tx1col;
- u32 txmcol;
- u64int rxokph;
- u64int rxokbrd;
- u32 rxokmu;
- u16int txabt;
- u16int txundrn;
-};
-
-enum { /* Variants */
- Rtl8100e = (0x8136<<16)|0x10EC, /* RTL810[01]E ? */
- Rtl8169c = (0x0116<<16)|0x16EC, /* RTL8169C+ (USR997902) */
- Rtl8169sc = (0x8167<<16)|0x10EC, /* RTL8169SC */
- Rtl8168b = (0x8168<<16)|0x10EC, /* RTL8168B */
- Rtl8169 = (0x8169<<16)|0x10EC, /* RTL8169 */
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
- int port;
- Pcidev* pcidev;
- Ctlr* next;
- int active;
-
- void* nic;
-
- QLock alock; /* attach */
- Lock ilock; /* init */
- int init; /* */
-
- int pciv; /* */
- int macv; /* MAC version */
- int phyv; /* PHY version */
-
- Mii* mii;
-
- Lock tlock; /* transmit */
- D* td; /* descriptor ring */
- Block** tb; /* transmit buffers */
- int ntd;
-
- int tdh; /* head - producer index (host) */
- int tdt; /* tail - consumer index (NIC) */
- int ntdfree;
- int ntq;
-
- int mtps; /* Max. Transmit Packet Size */
-
- Lock rlock; /* receive */
- D* rd; /* descriptor ring */
- void** rb; /* receive buffers */
- int nrd;
-
- int rdh; /* head - producer index (NIC) */
- int rdt; /* tail - consumer index (host) */
- int nrdfree;
-
- int rcr; /* receive configuration register */
-
- QLock slock; /* statistics */
- Dtcc* dtcc;
- uint txdu;
- uint tcpf;
- uint udpf;
- uint ipf;
- uint fovf;
- uint ierrs;
- uint rer;
- uint rdu;
- uint punlc;
- uint fovw;
-} Ctlr;
-
-static Ctlr* rtl8169ctlrhead;
-static Ctlr* rtl8169ctlrtail;
-
-#define csr8r(c, r) (inb((c)->port+(r)))
-#define csr16r(c, r) (ins((c)->port+(r)))
-#define csr32r(c, r) (inl((c)->port+(r)))
-#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
-#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
-#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
-
-static int
-rtl8169miimir(Mii* mii, int pa, int ra)
-{
- uint r;
- int timeo;
- Ctlr *ctlr;
-
- if(pa != 1)
- return -1;
- ctlr = mii->ctlr;
-
- r = (ra<<16) & RegaddrMASK;
- csr32w(ctlr, Phyar, r);
- delay(1);
- for(timeo = 0; timeo < 2000; timeo++){
- if((r = csr32r(ctlr, Phyar)) & Flag)
- break;
- microdelay(100);
- }
- if(!(r & Flag))
- return -1;
-
- return (r & DataMASK)>>DataSHIFT;
-}
-
-static int
-rtl8169miimiw(Mii* mii, int pa, int ra, int data)
-{
- uint r;
- int timeo;
- Ctlr *ctlr;
-
- if(pa != 1)
- return -1;
- ctlr = mii->ctlr;
-
- r = Flag|((ra<<16) & RegaddrMASK)|((data<<DataSHIFT) & DataMASK);
- csr32w(ctlr, Phyar, r);
- delay(1);
- for(timeo = 0; timeo < 2000; timeo++){
- if(!((r = csr32r(ctlr, Phyar)) & Flag))
- break;
- microdelay(100);
- }
- if(r & Flag)
- return -1;
-
- return 0;
-}
-
-static int
-rtl8169mii(Ctlr* ctlr)
-{
- MiiPhy *phy;
-
- /*
- * Link management.
- */
- if((ctlr->mii = malloc(sizeof(Mii))) == nil)
- return -1;
- ctlr->mii->mir = rtl8169miimir;
- ctlr->mii->miw = rtl8169miimiw;
- ctlr->mii->ctlr = ctlr;
-
- /*
- * Get rev number out of Phyidr2 so can config properly.
- * There's probably more special stuff for Macv0[234] needed here.
- */
- ctlr->phyv = rtl8169miimir(ctlr->mii, 1, Phyidr2) & 0x0F;
- if(ctlr->macv == Macv02){
- csr8w(ctlr, 0x82, 1); /* magic */
- rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000); /* magic */
- }
-
- if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){
- free(ctlr->mii);
- ctlr->mii = nil;
- return -1;
- }
- print("oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
- phy->oui, phy->phyno, ctlr->macv, ctlr->phyv);
-
- miiane(ctlr->mii, ~0, ~0, ~0);
-
- return 0;
-}
-
-static void
-rtl8169halt(Ctlr* ctlr)
-{
- csr8w(ctlr, Cr, 0);
- csr16w(ctlr, Imr, 0);
- csr16w(ctlr, Isr, ~0);
-}
-
-static int
-rtl8169reset(Ctlr* ctlr)
-{
- u32 r;
- int timeo;
-
- /*
- * Soft reset the controller.
- */
- csr8w(ctlr, Cr, Rst);
- for(r = timeo = 0; timeo < 1000; timeo++){
- r = csr8r(ctlr, Cr);
- if(!(r & Rst))
- break;
- delay(1);
- }
- rtl8169halt(ctlr);
-
- if(r & Rst)
- return -1;
- return 0;
-}
-
-static void
-rtl8169detach(Ether* edev)
-{
- rtl8169reset(edev->ctlr);
-}
-
-static void
-rtl8169replenish(Ctlr* ctlr)
-{
- D *d;
- int rdt;
- void *bp;
-
- rdt = ctlr->rdt;
- while(NEXT(rdt, ctlr->nrd) != ctlr->rdh){
- d = &ctlr->rd[rdt];
- if(ctlr->rb[rdt] == nil){
- /*
- * simple allocation for now
- */
- bp = mallocalign(Mps, 8, 0, 0);
- ctlr->rb[rdt] = bp;
- d->addrlo = PCIWADDR(bp);
- d->addrhi = 0;
- }
- coherence();
- d->control |= Own|Mps;
- rdt = NEXT(rdt, ctlr->nrd);
- ctlr->nrdfree++;
- }
- ctlr->rdt = rdt;
-}
-
-static int
-rtl8169init(Ether* edev)
-{
- u32 r;
- Ctlr *ctlr;
- u8int cplusc;
-
- ctlr = edev->ctlr;
- ilock(&ctlr->ilock);
-
- rtl8169halt(ctlr);
-
- /*
- * MAC Address.
- * Must put chip into config register write enable mode.
- */
- csr8w(ctlr, Cr9346, Eem1|Eem0);
- r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
- csr32w(ctlr, Idr0, r);
- r = (edev->ea[5]<<8)|edev->ea[4];
- csr32w(ctlr, Idr0+4, r);
-
- /*
- * Transmitter.
- */
- memset(ctlr->td, 0, sizeof(D)*ctlr->ntd);
- ctlr->tdh = ctlr->tdt = 0;
- ctlr->td[ctlr->ntd-1].control = Eor;
-
- /*
- * Receiver.
- * Need to do something here about the multicast filter.
- */
- memset(ctlr->rd, 0, sizeof(D)*ctlr->nrd);
- ctlr->rdh = ctlr->rdt = 0;
- ctlr->rd[ctlr->nrd-1].control = Eor;
- rtl8169replenish(ctlr);
- ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Apm;
-
- /*
- * Mtps is in units of 128 except for the RTL8169
- * where is is 32. If using jumbo frames should be
- * set to 0x3F.
- * Setting Mulrw in Cplusc disables the Tx/Rx DMA burst
- * settings in Tcr/Rcr; the (1<<14) is magic.
- */
- ctlr->mtps = HOWMANY(Mps, 128);
- cplusc = csr16r(ctlr, Cplusc) & ~(1<<14);
- cplusc |= Rxchksum|Mulrw;
- switch(ctlr->macv){
- default:
- return -1;
- case Macv01:
- ctlr->mtps = HOWMANY(Mps, 32);
- break;
- case Macv02:
- case Macv03:
- cplusc |= (1<<14); /* magic */
- break;
- case Macv05:
- /*
- * This is interpreted from clearly bogus code
- * in the manufacturer-supplied driver, it could
- * be wrong. Untested.
- */
- r = csr8r(ctlr, Config2) & 0x07;
- if(r == 0x01) /* 66MHz PCI */
- csr32w(ctlr, 0x7C, 0x0007FFFF); /* magic */
- else
- csr32w(ctlr, 0x7C, 0x0007FF00); /* magic */
- pciclrmwi(ctlr->pcidev);
- break;
- case Macv13:
- /*
- * This is interpreted from clearly bogus code
- * in the manufacturer-supplied driver, it could
- * be wrong. Untested.
- */
- pcicfgw8(ctlr->pcidev, 0x68, 0x00); /* magic */
- pcicfgw8(ctlr->pcidev, 0x69, 0x08); /* magic */
- break;
- case Macv04:
- case Macv11:
- case Macv12:
- case Macv14:
- case Macv15:
- break;
- }
-
- /*
- * Enable receiver/transmitter.
- * Need to do this first or some of the settings below
- * won't take.
- */
- switch(ctlr->pciv){
- default:
- csr8w(ctlr, Cr, Te|Re);
- csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
- csr32w(ctlr, Rcr, ctlr->rcr);
- case Rtl8169sc:
- case Rtl8168b:
- break;
- }
-
- /*
- * Interrupts.
- * Disable Tdu|Tok for now, the transmit routine will tidy.
- * Tdu means the NIC ran out of descriptors to send, so it
- * doesn't really need to ever be on.
- */
- csr32w(ctlr, Timerint, 0);
- csr16w(ctlr, Imr, Serr|Timeout|Fovw|Punlc|Rdu|Ter|Rer|Rok);
-
- /*
- * Clear missed-packet counter;
- * initial early transmit threshold value;
- * set the descriptor ring base addresses;
- * set the maximum receive packet size;
- * no early-receive interrupts.
- */
- csr32w(ctlr, Mpc, 0);
- csr8w(ctlr, Mtps, ctlr->mtps);
- csr32w(ctlr, Tnpds+4, 0);
- csr32w(ctlr, Tnpds, PCIWADDR(ctlr->td));
- csr32w(ctlr, Rdsar+4, 0);
- csr32w(ctlr, Rdsar, PCIWADDR(ctlr->rd));
- csr16w(ctlr, Rms, Mps);
- r = csr16r(ctlr, Mulint) & 0xF000;
- csr16w(ctlr, Mulint, r);
- csr16w(ctlr, Cplusc, cplusc);
-
- /*
- * Set configuration.
- */
- switch(ctlr->pciv){
- default:
- break;
- case Rtl8169sc:
- csr16w(ctlr, 0xE2, 0); /* magic */
- csr8w(ctlr, Cr, Te|Re);
- csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
- csr32w(ctlr, Rcr, ctlr->rcr);
- break;
- case Rtl8168b:
- case Rtl8169c:
- csr16w(ctlr, 0xE2, 0); /* magic */
- csr16w(ctlr, Cplusc, 0x2000); /* magic */
- csr8w(ctlr, Cr, Te|Re);
- csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
- csr32w(ctlr, Rcr, ctlr->rcr);
- csr16w(ctlr, Rms, 0x0800);
- csr8w(ctlr, Mtps, 0x3F);
- break;
- }
-
- csr8w(ctlr, Cr9346, 0);
-
- iunlock(&ctlr->ilock);
-
-// rtl8169mii(ctlr);
-
- return 0;
-}
-
-static void
-rtl8169attach(Ether* edev)
-{
- int timeo;
- Ctlr *ctlr;
-
- ctlr = edev->ctlr;
- qlock(&ctlr->alock);
- if(ctlr->init == 0){
- /*
- * Handle allocation/init errors here.
- */
- ctlr->td = xspanalloc(sizeof(D)*Ntd, 256, 0);
- ctlr->tb = malloc(Ntd*sizeof(Block*));
- ctlr->ntd = Ntd;
- ctlr->rd = xspanalloc(sizeof(D)*Nrd, 256, 0);
- ctlr->rb = malloc(Nrd*sizeof(Block*));
- ctlr->nrd = Nrd;
- ctlr->dtcc = xspanalloc(sizeof(Dtcc), 64, 0);
- rtl8169init(edev);
- ctlr->init = 1;
- }
- qunlock(&ctlr->alock);
-
- for(timeo = 0; timeo < 3500; timeo++){
- if(miistatus(ctlr->mii) == 0)
- break;
- delay(10);
- }
-}
-
-static void
-rtl8169transmit(Ether* edev)
-{
- D *d;
- Block *bp;
- Ctlr *ctlr;
- int control, x;
- RingBuf *tb;
-
- ctlr = edev->ctlr;
-
- ilock(&ctlr->tlock);
- for(x = ctlr->tdh; ctlr->ntq > 0; x = NEXT(x, ctlr->ntd)){
- d = &ctlr->td[x];
- if((control = d->control) & Own)
- break;
-
- /*
- * Check errors and log here.
- */
- USED(control);
-
- /*
- * Free it up.
- * Need to clean the descriptor here? Not really.
- * Simple freeb for now (no chain and freeblist).
- * Use ntq count for now.
- */
- freeb(ctlr->tb[x]);
- ctlr->tb[x] = nil;
- d->control &= Eor;
-
- ctlr->ntq--;
- }
- ctlr->tdh = x;
-
- x = ctlr->tdt;
- while(ctlr->ntq < (ctlr->ntd-1)){
- tb = &edev->tb[edev->ti];
- if(tb->owner != Interface)
- break;
-
- bp = allocb(tb->len);
- memmove(bp->wp, tb->pkt, tb->len);
- memmove(bp->wp+Eaddrlen, edev->ea, Eaddrlen);
- bp->wp += tb->len;
-
- tb->owner = Host;
- edev->ti = NEXT(edev->ti, edev->ntb);
-
- d = &ctlr->td[x];
- d->addrlo = PCIWADDR(bp->rp);
- d->addrhi = 0;
- ctlr->tb[x] = bp;
- coherence();
- d->control |= Own|Fs|Ls|((BLEN(bp)<<TxflSHIFT) & TxflMASK);
-
- x = NEXT(x, ctlr->ntd);
- ctlr->ntq++;
- }
- if(x != ctlr->tdt){
- ctlr->tdt = x;
- csr8w(ctlr, Tppoll, Npq);
- }
- else if(ctlr->ntq >= (ctlr->ntd-1))
- ctlr->txdu++;
-
- iunlock(&ctlr->tlock);
-}
-
-static void
-rtl8169receive(Ether* edev)
-{
- D *d;
- int len, rdh;
- Ctlr *ctlr;
- u32 control;
- RingBuf *ring;
-
- ctlr = edev->ctlr;
-
- rdh = ctlr->rdh;
- for(;;){
- d = &ctlr->rd[rdh];
-
- if(d->control & Own)
- break;
-
- control = d->control;
- if((control & (Fs|Ls|Res)) == (Fs|Ls)){
- len = ((control & RxflMASK)>>RxflSHIFT) - 4;
-
- ring = &edev->rb[edev->ri];
- if(ring->owner == Interface){
- ring->owner = Host;
- ring->len = len;
- memmove(ring->pkt, ctlr->rb[rdh], len);
- edev->ri = NEXT(edev->ri, edev->nrb);
- }
- }
- else{
- /*
- * Error stuff here.
- print("control %#8.8ux\n", control);
- */
- }
- d->control &= Eor;
- ctlr->nrdfree--;
- rdh = NEXT(rdh, ctlr->nrd);
- }
- ctlr->rdh = rdh;
-
- if(ctlr->nrdfree < ctlr->nrd/2)
- rtl8169replenish(ctlr);
-}
-
-static void
-rtl8169interrupt(Ureg*, void* arg)
-{
- Ctlr *ctlr;
- Ether *edev;
- u32 isr;
-
- edev = arg;
- ctlr = edev->ctlr;
-
- while((isr = csr16r(ctlr, Isr)) != 0 && isr != 0xFFFF){
- csr16w(ctlr, Isr, isr);
- if(isr & (Fovw|Punlc|Rdu|Rer|Rok)){
- rtl8169receive(edev);
- if(!(isr & (Punlc|Rok)))
- ctlr->ierrs++;
- if(isr & Rer)
- ctlr->rer++;
- if(isr & Rdu)
- ctlr->rdu++;
- if(isr & Punlc)
- ctlr->punlc++;
- if(isr & Fovw)
- ctlr->fovw++;
- isr &= ~(Fovw|Rdu|Rer|Rok);
- }
-
- if(isr & (Tdu|Ter|Tok)){
- rtl8169transmit(edev);
- isr &= ~(Tdu|Ter|Tok);
- }
-
- if(isr & Punlc){
-// rtl8169link(edev);
- isr &= ~Punlc;
- }
-
- /*
- * Some of the reserved bits get set sometimes...
- */
- if(isr & (Serr|Timeout|Tdu|Fovw|Punlc|Rdu|Ter|Tok|Rer|Rok))
- panic("rtl8169interrupt: imr %#4.4ux isr %#4.4ux\n",
- csr16r(ctlr, Imr), isr);
- }
-}
-
-static void
-rtl8169pci(void)
-{
- Pcidev *p;
- Ctlr *ctlr;
- int i, port;
- u32 bar;
-
- p = nil;
- while(p = pcimatch(p, 0, 0)){
- if(p->ccrb != 0x02 || p->ccru != 0)
- continue;
-
- switch(i = ((p->did<<16)|p->vid)){
- default:
- continue;
- case Rtl8100e: /* RTL810[01]E ? */
- case Rtl8169c: /* RTL8169C */
- case Rtl8169sc: /* RTL8169SC */
- case Rtl8168b: /* RTL8168B */
- case Rtl8169: /* RTL8169 */
- break;
- case (0xC107<<16)|0x1259: /* Corega CG-LAPCIGT */
- i = Rtl8169;
- break;
- }
-
- bar = p->mem[0].bar;
- port = bar & ~0x01;
- if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){
- print("rtl8169: port %#ux in use\n", port);
- continue;
- }
- ctlr = malloc(sizeof(Ctlr));
- ctlr->port = port;
- ctlr->pcidev = p;
- ctlr->pciv = i;
-
- if(pcigetpms(p) > 0){
- pcisetpms(p, 0);
-
- for(i = 0; i < 6; i++)
- pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
- pcicfgw8(p, PciINTL, p->intl);
- pcicfgw8(p, PciLTR, p->ltr);
- pcicfgw8(p, PciCLS, p->cls);
- pcicfgw16(p, PciPCR, p->pcr);
- }
-
- if(rtl8169reset(ctlr)){
- iofree(port);
- free(ctlr);
- continue;
- }
-
- /*
- * Extract the chip hardware version,
- * needed to configure each properly.
- */
- ctlr->macv = csr32r(ctlr, Tcr) & HwveridMASK;
-
- rtl8169mii(ctlr);
-
- pcisetbme(p);
-
- if(rtl8169ctlrhead != nil)
- rtl8169ctlrtail->next = ctlr;
- else
- rtl8169ctlrhead = ctlr;
- rtl8169ctlrtail = ctlr;
- }
-}
-
-int
-rtl8169pnp(Ether* edev)
-{
- u32 r;
- Ctlr *ctlr;
-
- if(rtl8169ctlrhead == nil)
- rtl8169pci();
-
- /*
- * Any adapter matches if no edev->port is supplied,
- * otherwise the ports must match.
- */
- for(ctlr = rtl8169ctlrhead; ctlr != nil; ctlr = ctlr->next){
- if(ctlr->active)
- continue;
- if(edev->port == 0 || edev->port == ctlr->port){
- ctlr->active = 1;
- break;
- }
- }
- if(ctlr == nil)
- return -1;
-
- edev->ctlr = ctlr;
- edev->port = ctlr->port;
- edev->irq = ctlr->pcidev->intl;
- edev->tbdf = ctlr->pcidev->tbdf;
-// edev->mbps = 100;
-
- /*
- * Pull the MAC address out of the chip.
- */
- r = csr32r(ctlr, Idr0);
- edev->ea[0] = r;
- edev->ea[1] = r>>8;
- edev->ea[2] = r>>16;
- edev->ea[3] = r>>24;
- r = csr32r(ctlr, Idr0+4);
- edev->ea[4] = r;
- edev->ea[5] = r>>8;
-
- /*
- * Linkage to the generic ethernet driver.
- */
- edev->attach = rtl8169attach;
- edev->transmit = rtl8169transmit;
- edev->interrupt = rtl8169interrupt;
- edev->detach = rtl8169detach;
-// edev->ifstat = rtl8169ifstat;
-// edev->ctl = nil;
-//
-// edev->arg = edev;
-// edev->promiscuous = rtl8169promiscuous;
-// edev->multicast = rtl8169multicast;
-
- return 0;
-}
--- a/os/boot/pc/ether82557.c
+++ /dev/null
@@ -1,882 +1,0 @@
-/*
- * Intel 82557 Fast Ethernet PCI Bus LAN Controller
- * as found on the Intel EtherExpress PRO/100B. This chip is full
- * of smarts, unfortunately none of them are in the right place.
- * To do:
- * the PCI scanning code could be made common to other adapters;
- * PCI code needs rewritten to handle byte, word, dword accesses
- * and using the devno as a bus+dev+function triplet.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum {
- Nrfd = 4, /* receive frame area */
-
- NullPointer = 0xFFFFFFFF, /* 82557 NULL pointer */
-};
-
-enum { /* CSR */
- Status = 0x00, /* byte or word (word includes Ack) */
- Ack = 0x01, /* byte */
- CommandR = 0x02, /* byte or word (word includes Interrupt) */
- Interrupt = 0x03, /* byte */
- Pointer = 0x04, /* dword */
- Port = 0x08, /* dword */
- Fcr = 0x0C, /* Flash control register */
- Ecr = 0x0E, /* EEPROM control register */
- Mcr = 0x10, /* MDI control register */
-};
-
-enum { /* Status */
- RUidle = 0x0000,
- RUsuspended = 0x0004,
- RUnoresources = 0x0008,
- RUready = 0x0010,
- RUrbd = 0x0020, /* bit */
- RUstatus = 0x003F, /* mask */
-
- CUidle = 0x0000,
- CUsuspended = 0x0040,
- CUactive = 0x0080,
- CUstatus = 0x00C0, /* mask */
-
- StatSWI = 0x0400, /* SoftWare generated Interrupt */
- StatMDI = 0x0800, /* MDI r/w done */
- StatRNR = 0x1000, /* Receive unit Not Ready */
- StatCNA = 0x2000, /* Command unit Not Active (Active->Idle) */
- StatFR = 0x4000, /* Finished Receiving */
- StatCX = 0x8000, /* Command eXecuted */
- StatTNO = 0x8000, /* Transmit NOT OK */
-};
-
-enum { /* Command (byte) */
- CUnop = 0x00,
- CUstart = 0x10,
- CUresume = 0x20,
- LoadDCA = 0x40, /* Load Dump Counters Address */
- DumpSC = 0x50, /* Dump Statistical Counters */
- LoadCUB = 0x60, /* Load CU Base */
- ResetSA = 0x70, /* Dump and Reset Statistical Counters */
-
- RUstart = 0x01,
- RUresume = 0x02,
- RUabort = 0x04,
- LoadHDS = 0x05, /* Load Header Data Size */
- LoadRUB = 0x06, /* Load RU Base */
- RBDresume = 0x07, /* Resume frame reception */
-};
-
-enum { /* Interrupt (byte) */
- InterruptM = 0x01, /* interrupt Mask */
- InterruptSI = 0x02, /* Software generated Interrupt */
-};
-
-enum { /* Ecr */
- EEsk = 0x01, /* serial clock */
- EEcs = 0x02, /* chip select */
- EEdi = 0x04, /* serial data in */
- EEdo = 0x08, /* serial data out */
-
- EEstart = 0x04, /* start bit */
- EEread = 0x02, /* read opcode */
-};
-
-enum { /* Mcr */
- MDIread = 0x08000000, /* read opcode */
- MDIwrite = 0x04000000, /* write opcode */
- MDIready = 0x10000000, /* ready bit */
- MDIie = 0x20000000, /* interrupt enable */
-};
-
-typedef struct Rfd {
- int field;
- ulong link;
- ulong rbd;
- ushort count;
- ushort size;
-
- Etherpkt;
-} Rfd;
-
-enum { /* field */
- RfdCollision = 0x00000001,
- RfdIA = 0x00000002, /* IA match */
- RfdRxerr = 0x00000010, /* PHY character error */
- RfdType = 0x00000020, /* Type frame */
- RfdRunt = 0x00000080,
- RfdOverrun = 0x00000100,
- RfdBuffer = 0x00000200,
- RfdAlignment = 0x00000400,
- RfdCRC = 0x00000800,
-
- RfdOK = 0x00002000, /* frame received OK */
- RfdC = 0x00008000, /* reception Complete */
- RfdSF = 0x00080000, /* Simplified or Flexible (1) Rfd */
- RfdH = 0x00100000, /* Header RFD */
-
- RfdI = 0x20000000, /* Interrupt after completion */
- RfdS = 0x40000000, /* Suspend after completion */
- RfdEL = 0x80000000, /* End of List */
-};
-
-enum { /* count */
- RfdF = 0x00004000,
- RfdEOF = 0x00008000,
-};
-
-typedef struct Cb {
- int command;
- ulong link;
- uchar data[24]; /* CbIAS + CbConfigure */
-} Cb;
-
-typedef struct TxCB {
- int command;
- ulong link;
- ulong tbd;
- ushort count;
- uchar threshold;
- uchar number;
-} TxCB;
-
-enum { /* action command */
- CbOK = 0x00002000, /* DMA completed OK */
- CbC = 0x00008000, /* execution Complete */
-
- CbNOP = 0x00000000,
- CbIAS = 0x00010000, /* Indvidual Address Setup */
- CbConfigure = 0x00020000,
- CbMAS = 0x00030000, /* Multicast Address Setup */
- CbTransmit = 0x00040000,
- CbDump = 0x00060000,
- CbDiagnose = 0x00070000,
- CbCommand = 0x00070000, /* mask */
-
- CbSF = 0x00080000, /* CbTransmit */
-
- CbI = 0x20000000, /* Interrupt after completion */
- CbS = 0x40000000, /* Suspend after completion */
- CbEL = 0x80000000, /* End of List */
-};
-
-enum { /* CbTransmit count */
- CbEOF = 0x00008000,
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
- int port;
- Pcidev* pcidev;
- Ctlr* next;
- int active;
-
- int eepromsz; /* address size in bits */
- ushort* eeprom;
-
- int ctlrno;
- char* type;
-
- uchar configdata[24];
-
- Rfd rfd[Nrfd];
- int rfdl;
- int rfdx;
-
- Block* cbqhead;
- Block* cbqtail;
- int cbqbusy;
-} Ctlr;
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-static uchar configdata[24] = {
- 0x16, /* byte count */
- 0x44, /* Rx/Tx FIFO limit */
- 0x00, /* adaptive IFS */
- 0x00,
- 0x04, /* Rx DMA maximum byte count */
- 0x84, /* Tx DMA maximum byte count */
- 0x33, /* late SCB, CNA interrupts */
- 0x01, /* discard short Rx frames */
- 0x00, /* 503/MII */
-
- 0x00,
- 0x2E, /* normal operation, NSAI */
- 0x00, /* linear priority */
- 0x60, /* inter-frame spacing */
- 0x00,
- 0xF2,
- 0x48, /* promiscuous mode off */
- 0x00,
- 0x40,
- 0xF2, /* transmit padding enable */
- 0x80, /* full duplex pin enable */
- 0x3F, /* no Multi IA */
- 0x05, /* no Multi Cast ALL */
-};
-
-#define csr8r(c, r) (inb((c)->port+(r)))
-#define csr16r(c, r) (ins((c)->port+(r)))
-#define csr32r(c, r) (inl((c)->port+(r)))
-#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
-#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
-#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
-
-static void
-custart(Ctlr* ctlr)
-{
- if(ctlr->cbqhead == 0){
- ctlr->cbqbusy = 0;
- return;
- }
- ctlr->cbqbusy = 1;
-
- csr32w(ctlr, Pointer, PADDR(ctlr->cbqhead->rp));
- while(csr8r(ctlr, CommandR))
- ;
- csr8w(ctlr, CommandR, CUstart);
-}
-
-static void
-action(Ctlr* ctlr, Block* bp)
-{
- Cb *cb;
-
- cb = (Cb*)bp->rp;
- cb->command |= CbEL;
-
- if(ctlr->cbqhead){
- ctlr->cbqtail->next = bp;
- cb = (Cb*)ctlr->cbqtail->rp;
- cb->link = PADDR(bp->rp);
- cb->command &= ~CbEL;
- }
- else
- ctlr->cbqhead = bp;
- ctlr->cbqtail = bp;
-
- if(ctlr->cbqbusy == 0)
- custart(ctlr);
-}
-
-static void
-attach(Ether* ether)
-{
- int status;
- Ctlr *ctlr;
-
- ctlr = ether->ctlr;
- status = csr16r(ctlr, Status);
- if((status & RUstatus) == RUidle){
- csr32w(ctlr, Pointer, PADDR(&ctlr->rfd[ctlr->rfdx]));
- while(csr8r(ctlr, CommandR))
- ;
- csr8w(ctlr, CommandR, RUstart);
- }
-}
-
-static void
-configure(void* arg, int promiscuous)
-{
- Ctlr *ctlr;
- Block *bp;
- Cb *cb;
-
- ctlr = ((Ether*)arg)->ctlr;
-
- bp = allocb(sizeof(Cb));
- cb = (Cb*)bp->rp;
- bp->wp += sizeof(Cb);
-
- cb->command = CbConfigure;
- cb->link = NullPointer;
- memmove(cb->data, ctlr->configdata, sizeof(ctlr->configdata));
- if(promiscuous)
- cb->data[15] |= 0x01;
- action(ctlr, bp);
-}
-
-static void
-transmit(Ether* ether)
-{
- Block *bp;
- TxCB *txcb;
- RingBuf *tb;
-
- for(tb = ðer->tb[ether->ti]; tb->owner == Interface; tb = ðer->tb[ether->ti]){
- bp = allocb(tb->len+sizeof(TxCB));
- txcb = (TxCB*)bp->wp;
- bp->wp += sizeof(TxCB);
-
- txcb->command = CbTransmit;
- txcb->link = NullPointer;
- txcb->tbd = NullPointer;
- txcb->count = CbEOF|tb->len;
- txcb->threshold = 2;
- txcb->number = 0;
-
- memmove(bp->wp, tb->pkt, tb->len);
- memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
- bp->wp += tb->len;
-
- action(ether->ctlr, bp);
-
- tb->owner = Host;
- ether->ti = NEXT(ether->ti, ether->ntb);
- }
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
- Rfd *rfd;
- Block *bp;
- Ctlr *ctlr;
- Ether *ether;
- int status;
- RingBuf *rb;
-
- ether = arg;
- ctlr = ether->ctlr;
-
- for(;;){
- status = csr16r(ctlr, Status);
- csr8w(ctlr, Ack, (status>>8) & 0xFF);
-
- if((status & (StatCX|StatFR|StatCNA|StatRNR)) == 0)
- return;
-
- if(status & StatFR){
- rfd = &ctlr->rfd[ctlr->rfdx];
- while(rfd->field & RfdC){
- rb = ðer->rb[ether->ri];
- if(rb->owner == Interface){
- rb->owner = Host;
- rb->len = rfd->count & 0x3FFF;
- memmove(rb->pkt, rfd->d, rfd->count & 0x3FFF);
- ether->ri = NEXT(ether->ri, ether->nrb);
- }
-
- /*
- * Reinitialise the frame for reception and bump
- * the receive frame processing index;
- * bump the sentinel index, mark the new sentinel
- * and clear the old sentinel suspend bit;
- * set bp and rfd for the next receive frame to
- * process.
- */
- rfd->field = 0;
- rfd->count = 0;
- ctlr->rfdx = NEXT(ctlr->rfdx, Nrfd);
-
- rfd = &ctlr->rfd[ctlr->rfdl];
- ctlr->rfdl = NEXT(ctlr->rfdl, Nrfd);
- ctlr->rfd[ctlr->rfdl].field |= RfdS;
- rfd->field &= ~RfdS;
-
- rfd = &ctlr->rfd[ctlr->rfdx];
- }
- status &= ~StatFR;
- }
-
- if(status & StatRNR){
- while(csr8r(ctlr, CommandR))
- ;
- csr8w(ctlr, CommandR, RUresume);
-
- status &= ~StatRNR;
- }
-
- if(status & StatCNA){
- while(bp = ctlr->cbqhead){
- if((((Cb*)bp->rp)->command & CbC) == 0)
- break;
- ctlr->cbqhead = bp->next;
- freeb(bp);
- }
- custart(ctlr);
-
- status &= ~StatCNA;
- }
-
- if(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI))
- panic("%s#%d: status %uX\n", ctlr->type, ctlr->ctlrno, status);
- }
-}
-
-static void
-ctlrinit(Ctlr* ctlr)
-{
- int i;
- Rfd *rfd;
- ulong link;
-
- link = NullPointer;
- for(i = Nrfd-1; i >= 0; i--){
- rfd = &ctlr->rfd[i];
-
- rfd->field = 0;
- rfd->link = link;
- link = PADDR(rfd);
- rfd->rbd = NullPointer;
- rfd->count = 0;
- rfd->size = sizeof(Etherpkt);
- }
- ctlr->rfd[Nrfd-1].link = PADDR(&ctlr->rfd[0]);
-
- ctlr->rfdl = 0;
- ctlr->rfd[0].field |= RfdS;
- ctlr->rfdx = 2;
-
- memmove(ctlr->configdata, configdata, sizeof(configdata));
-}
-
-static int
-miir(Ctlr* ctlr, int phyadd, int regadd)
-{
- int mcr, timo;
-
- csr32w(ctlr, Mcr, MDIread|(phyadd<<21)|(regadd<<16));
- mcr = 0;
- for(timo = 64; timo; timo--){
- mcr = csr32r(ctlr, Mcr);
- if(mcr & MDIready)
- break;
- microdelay(1);
- }
-
- if(mcr & MDIready)
- return mcr & 0xFFFF;
-
- return -1;
-}
-
-static int
-miiw(Ctlr* ctlr, int phyadd, int regadd, int data)
-{
- int mcr, timo;
-
- csr32w(ctlr, Mcr, MDIwrite|(phyadd<<21)|(regadd<<16)|(data & 0xFFFF));
- mcr = 0;
- for(timo = 64; timo; timo--){
- mcr = csr32r(ctlr, Mcr);
- if(mcr & MDIready)
- break;
- microdelay(1);
- }
-
- if(mcr & MDIready)
- return 0;
-
- return -1;
-}
-
-static int
-hy93c46r(Ctlr* ctlr, int r)
-{
- int data, i, op, size;
-
- /*
- * Hyundai HY93C46 or equivalent serial EEPROM.
- * This sequence for reading a 16-bit register 'r'
- * in the EEPROM is taken straight from Section
- * 3.3.4.2 of the Intel 82557 User's Guide.
- */
-reread:
- csr16w(ctlr, Ecr, EEcs);
- op = EEstart|EEread;
- for(i = 2; i >= 0; i--){
- data = (((op>>i) & 0x01)<<2)|EEcs;
- csr16w(ctlr, Ecr, data);
- csr16w(ctlr, Ecr, data|EEsk);
- microdelay(1);
- csr16w(ctlr, Ecr, data);
- microdelay(1);
- }
-
- /*
- * First time through must work out the EEPROM size.
- */
- if((size = ctlr->eepromsz) == 0)
- size = 8;
-
- for(size = size-1; size >= 0; size--){
- data = (((r>>size) & 0x01)<<2)|EEcs;
- csr16w(ctlr, Ecr, data);
- csr16w(ctlr, Ecr, data|EEsk);
- delay(1);
- csr16w(ctlr, Ecr, data);
- microdelay(1);
- if(!(csr16r(ctlr, Ecr) & EEdo))
- break;
- }
-
- data = 0;
- for(i = 15; i >= 0; i--){
- csr16w(ctlr, Ecr, EEcs|EEsk);
- microdelay(1);
- if(csr16r(ctlr, Ecr) & EEdo)
- data |= (1<<i);
- csr16w(ctlr, Ecr, EEcs);
- microdelay(1);
- }
-
- csr16w(ctlr, Ecr, 0);
-
- if(ctlr->eepromsz == 0){
- ctlr->eepromsz = 8-size;
- ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
- goto reread;
- }
-
- return data;
-}
-
-static void
-i82557pci(void)
-{
- Pcidev *p;
- Ctlr *ctlr;
-
- p = nil;
- while(p = pcimatch(p, 0x8086, 0)){
- switch(p->did){
- default:
- continue;
- case 0x1031: /* Intel 82562EM */
- case 0x1050: /* Intel 82562EZ */
- case 0x1039: /* Intel 82801BD PRO/100 VE */
- case 0x103A: /* Intel 82562 PRO/100 VE */
- case 0x1064: /* Intel 82562 PRO/100 VE */
- case 0x2449: /* Intel 82562ET */
- case 0x1209: /* Intel 82559ER */
- case 0x1229: /* Intel 8255[789] */
- case 0x1030: /* Intel 82559 InBusiness 10/100 */
- break;
- }
-
- /*
- * bar[0] is the memory-mapped register address (4KB),
- * bar[1] is the I/O port register address (32 bytes) and
- * bar[2] is for the flash ROM (1MB).
- */
- ctlr = malloc(sizeof(Ctlr));
- ctlr->port = p->mem[1].bar & ~0x01;
- ctlr->pcidev = p;
-
- if(ctlrhead != nil)
- ctlrtail->next = ctlr;
- else
- ctlrhead = ctlr;
- ctlrtail = ctlr;
-
- pcisetbme(p);
- }
-}
-
-static void
-detach(Ether* ether)
-{
- Ctlr *ctlr;
-
- ctlr = ether->ctlr;
-
- csr32w(ctlr, Port, 0);
- delay(1);
-
- while(csr8r(ctlr, CommandR))
- ;
-}
-
-static int
-scanphy(Ctlr* ctlr)
-{
- int i, oui, x;
-
- for(i = 0; i < 32; i++){
- if((oui = miir(ctlr, i, 2)) == -1 || oui == 0 || oui == 0xFFFF)
- continue;
- oui <<= 6;
- x = miir(ctlr, i, 3);
- oui |= x>>10;
- //print("phy%d: oui %uX reg1 %uX\n", i, oui, miir(ctlr, i, 1));
-
- if(oui == 0xAA00)
- ctlr->eeprom[6] = 0x07<<8;
- else if(oui == 0x80017){
- if(x & 0x01)
- ctlr->eeprom[6] = 0x0A<<8;
- else
- ctlr->eeprom[6] = 0x04<<8;
- }
- return i;
- }
- return -1;
-}
-
-int
-i82557reset(Ether* ether)
-{
- int anar, anlpar, bmcr, bmsr, force, i, phyaddr, x;
- unsigned short sum;
- Block *bp;
- uchar ea[Eaddrlen];
- Ctlr *ctlr;
- Cb *cb;
-
-
- if(ctlrhead == nil)
- i82557pci();
-
- /*
- * Any adapter matches if no ether->port is supplied,
- * otherwise the ports must match.
- */
- for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
- if(ctlr->active)
- continue;
- if(ether->port == 0 || ether->port == ctlr->port){
- ctlr->active = 1;
- break;
- }
- }
- if(ctlr == nil)
- return -1;
-
- /*
- * Initialise the Ctlr structure.
- * Perform a software reset after which need to ensure busmastering
- * is still enabled. The EtherExpress PRO/100B appears to leave
- * the PCI configuration alone (see the 'To do' list above) so punt
- * for now.
- * Load the RUB and CUB registers for linear addressing (0).
- */
- ether->ctlr = ctlr;
- ether->port = ctlr->port;
- ether->irq = ctlr->pcidev->intl;
- ether->tbdf = ctlr->pcidev->tbdf;
- ctlr->ctlrno = ether->ctlrno;
- ctlr->type = ether->type;
-
- csr32w(ctlr, Port, 0);
- delay(1);
-
- while(csr8r(ctlr, CommandR))
- ;
- csr32w(ctlr, Pointer, 0);
- csr8w(ctlr, CommandR, LoadRUB);
- while(csr8r(ctlr, CommandR))
- ;
- csr8w(ctlr, CommandR, LoadCUB);
-
- /*
- * Initialise the action and receive frame areas.
- */
- ctlrinit(ctlr);
-
- /*
- * Read the EEPROM.
- * Do a dummy read first to get the size
- * and allocate ctlr->eeprom.
- */
- hy93c46r(ctlr, 0);
- sum = 0;
- for(i = 0; i < (1<<ctlr->eepromsz); i++){
- x = hy93c46r(ctlr, i);
- ctlr->eeprom[i] = x;
- sum += x;
- }
- if(sum != 0xBABA)
- print("#l%d: EEPROM checksum - 0x%4.4uX\n", ether->ctlrno, sum);
-
- /*
- * Eeprom[6] indicates whether there is a PHY and whether
- * it's not 10Mb-only, in which case use the given PHY address
- * to set any PHY specific options and determine the speed.
- * Unfortunately, sometimes the EEPROM is blank except for
- * the ether address and checksum; in this case look at the
- * controller type and if it's am 82558 or 82559 it has an
- * embedded PHY so scan for that.
- * If no PHY, assume 82503 (serial) operation.
- */
- if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000))
- phyaddr = ctlr->eeprom[6] & 0x00FF;
- else
- switch(ctlr->pcidev->rid){
- case 0x01: /* 82557 A-step */
- case 0x02: /* 82557 B-step */
- case 0x03: /* 82557 C-step */
- default:
- phyaddr = -1;
- break;
- case 0x04: /* 82558 A-step */
- case 0x05: /* 82558 B-step */
- case 0x06: /* 82559 A-step */
- case 0x07: /* 82559 B-step */
- case 0x08: /* 82559 C-step */
- case 0x09: /* 82559ER A-step */
- phyaddr = scanphy(ctlr);
- break;
- }
- if(phyaddr >= 0){
- /*
- * Resolve the highest common ability of the two
- * link partners. In descending order:
- * 0x0100 100BASE-TX Full Duplex
- * 0x0200 100BASE-T4
- * 0x0080 100BASE-TX
- * 0x0040 10BASE-T Full Duplex
- * 0x0020 10BASE-T
- */
- anar = miir(ctlr, phyaddr, 0x04);
- anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;
- anar &= anlpar;
- bmcr = 0;
- if(anar & 0x380)
- bmcr = 0x2000;
- if(anar & 0x0140)
- bmcr |= 0x0100;
-
- switch((ctlr->eeprom[6]>>8) & 0x001F){
-
- case 0x04: /* DP83840 */
- case 0x0A: /* DP83840A */
- /*
- * The DP83840[A] requires some tweaking for
- * reliable operation.
- * The manual says bit 10 should be unconditionally
- * set although it supposedly only affects full-duplex
- * operation (an & 0x0140).
- */
- x = miir(ctlr, phyaddr, 0x17) & ~0x0520;
- x |= 0x0420;
- for(i = 0; i < ether->nopt; i++){
- if(cistrcmp(ether->opt[i], "congestioncontrol"))
- continue;
- x |= 0x0100;
- break;
- }
- miiw(ctlr, phyaddr, 0x17, x);
-
- /*
- * If the link partner can't autonegotiate, determine
- * the speed from elsewhere.
- */
- if(anlpar == 0){
- miir(ctlr, phyaddr, 0x01);
- bmsr = miir(ctlr, phyaddr, 0x01);
- x = miir(ctlr, phyaddr, 0x19);
- if((bmsr & 0x0004) && !(x & 0x0040))
- bmcr = 0x2000;
- }
- break;
-
- case 0x07: /* Intel 82555 */
- /*
- * Auto-negotiation may fail if the other end is
- * a DP83840A and the cable is short.
- */
- bmsr = miir(ctlr, phyaddr, 0x01);
- if((miir(ctlr, phyaddr, 0) & 0x1000) && !(bmsr & 0x0020)){
- miiw(ctlr, phyaddr, 0x1A, 0x2010);
- x = miir(ctlr, phyaddr, 0);
- miiw(ctlr, phyaddr, 0, 0x0200|x);
- for(i = 0; i < 3000; i++){
- delay(1);
- if(miir(ctlr, phyaddr, 0x01) & 0x0020)
- break;
- }
- miiw(ctlr, phyaddr, 0x1A, 0x2000);
-
- anar = miir(ctlr, phyaddr, 0x04);
- anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;
- anar &= anlpar;
- bmcr = 0;
- if(anar & 0x380)
- bmcr = 0x2000;
- if(anar & 0x0140)
- bmcr |= 0x0100;
- }
- break;
- }
-
- /*
- * Force speed and duplex if no auto-negotiation.
- */
- if(anlpar == 0){
- force = 0;
- for(i = 0; i < ether->nopt; i++){
- if(cistrcmp(ether->opt[i], "fullduplex") == 0){
- force = 1;
- bmcr |= 0x0100;
- ctlr->configdata[19] |= 0x40;
- }
- else if(cistrcmp(ether->opt[i], "speed") == 0){
- force = 1;
- x = strtol(ðer->opt[i][6], 0, 0);
- if(x == 10)
- bmcr &= ~0x2000;
- else if(x == 100)
- bmcr |= 0x2000;
- else
- force = 0;
- }
- }
- if(force)
- miiw(ctlr, phyaddr, 0x00, bmcr);
- }
-
- ctlr->configdata[8] = 1;
- ctlr->configdata[15] &= ~0x80;
- }
- else{
- ctlr->configdata[8] = 0;
- ctlr->configdata[15] |= 0x80;
- }
-
- /*
- * Load the chip configuration
- */
- configure(ether, 0);
-
- /*
- * Check if the adapter's station address is to be overridden.
- * If not, read it from the EEPROM and set in ether->ea prior to loading
- * the station address with the Individual Address Setup command.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, ether->ea, Eaddrlen) == 0){
- for(i = 0; i < Eaddrlen/2; i++){
- x = ctlr->eeprom[i];
- ether->ea[2*i] = x & 0xFF;
- ether->ea[2*i+1] = (x>>8) & 0xFF;
- }
- }
-
- bp = allocb(sizeof(Cb));
- cb = (Cb*)bp->rp;
- bp->wp += sizeof(Cb);
-
- cb->command = CbIAS;
- cb->link = NullPointer;
- memmove(cb->data, ether->ea, Eaddrlen);
- action(ctlr, bp);
-
- /*
- * Linkage to the generic ethernet driver.
- */
- ether->attach = attach;
- ether->transmit = transmit;
- ether->interrupt = interrupt;
- ether->detach = detach;
-
- return 0;
-}
--- a/os/boot/pc/ether82563.c
+++ /dev/null
@@ -1,977 +1,0 @@
-/*
- * bootstrap driver for
- * Intel 82563, 82571, 82573 Gigabit Ethernet PCI-Express Controllers
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-/* compatibility with cpu kernels */
-#define iallocb allocb
-#ifndef CACHELINESZ
-#define CACHELINESZ 32 /* pentium & later */
-#endif
-
-/* from pci.c */
-enum
-{ /* command register pcidev->pcr */
- IOen = 1<<0,
- MEMen = 1<<1,
- MASen = 1<<2,
- MemWrInv = 1<<4,
- PErrEn = 1<<6,
- SErrEn = 1<<8,
-};
-
-/*
- * these are in the order they appear in the manual, not numeric order.
- * It was too hard to find them in the book. Ref 21489, rev 2.6
- */
-
-enum {
- /* General */
-
- Ctrl = 0x00000000, /* Device Control */
- Status = 0x00000008, /* Device Status */
- Eec = 0x00000010, /* EEPROM/Flash Control/Data */
- Eerd = 0x00000014, /* EEPROM Read */
- Ctrlext = 0x00000018, /* Extended Device Control */
- Fla = 0x0000001c, /* Flash Access */
- Mdic = 0x00000020, /* MDI Control */
- Seresctl = 0x00000024, /* Serdes ana */
- Fcal = 0x00000028, /* Flow Control Address Low */
- Fcah = 0x0000002C, /* Flow Control Address High */
- Fct = 0x00000030, /* Flow Control Type */
- Kumctrlsta = 0x00000034, /* Kumeran Controll and Status Register */
- Vet = 0x00000038, /* VLAN EtherType */
- Fcttv = 0x00000170, /* Flow Control Transmit Timer Value */
- Txcw = 0x00000178, /* Transmit Configuration Word */
- Rxcw = 0x00000180, /* Receive Configuration Word */
- Ledctl = 0x00000E00, /* LED control */
- Pba = 0x00001000, /* Packet Buffer Allocation */
-
- /* Interrupt */
-
- Icr = 0x000000C0, /* Interrupt Cause Read */
- Ics = 0x000000C8, /* Interrupt Cause Set */
- Ims = 0x000000D0, /* Interrupt Mask Set/Read */
- Imc = 0x000000D8, /* Interrupt mask Clear */
- Iam = 0x000000E0, /* Interrupt acknowledge Auto Mask */
-
- /* Receive */
-
- Rctl = 0x00000100, /* Receive Control */
- Ert = 0x00002008, /* Early Receive Threshold (573[EVL] only) */
- Fcrtl = 0x00002160, /* Flow Control RX Threshold Low */
- Fcrth = 0x00002168, /* Flow Control Rx Threshold High */
- Psrctl = 0x00002170, /* Packet Split Receive Control */
- Rdbal = 0x00002800, /* Rdesc Base Address Low Queue 0 */
- Rdbah = 0x00002804, /* Rdesc Base Address High Queue 0 */
- Rdlen = 0x00002808, /* Receive Descriptor Length Queue 0 */
- Rdh = 0x00002810, /* Receive Descriptor Head Queue 0 */
- Rdt = 0x00002818, /* Receive Descriptor Tail Queue 0 */
- Rdtr = 0x00002820, /* Receive Descriptor Timer Ring */
- Rxdctl = 0x00002828, /* Receive Descriptor Control */
- Radv = 0x0000282C, /* Receive Interrupt Absolute Delay Timer */
- Rdbal1 = 0x00002900, /* Rdesc Base Address Low Queue 1 */
- Rdbah1 = 0x00002804, /* Rdesc Base Address High Queue 1 */
- Rdlen1 = 0x00002908, /* Receive Descriptor Length Queue 1 */
- Rdh1 = 0x00002910, /* Receive Descriptor Head Queue 1 */
- Rdt1 = 0x00002918, /* Receive Descriptor Tail Queue 1 */
- Rxdctl1 = 0x00002928, /* Receive Descriptor Control Queue 1 */
- Rsrpd = 0x00002c00, /* Receive Small Packet Detect */
- Raid = 0x00002c08, /* Receive ACK interrupt delay */
- Cpuvec = 0x00002c10, /* CPU Vector */
- Rxcsum = 0x00005000, /* Receive Checksum Control */
- Rfctl = 0x00005008, /* Receive Filter Control */
- Mta = 0x00005200, /* Multicast Table Array */
- Ral = 0x00005400, /* Receive Address Low */
- Rah = 0x00005404, /* Receive Address High */
- Vfta = 0x00005600, /* VLAN Filter Table Array */
- Mrqc = 0x00005818, /* Multiple Receive Queues Command */
- Rssim = 0x00005864, /* RSS Interrupt Mask */
- Rssir = 0x00005868, /* RSS Interrupt Request */
- Reta = 0x00005c00, /* Redirection Table */
- Rssrk = 0x00005c80, /* RSS Random Key */
-
- /* Transmit */
-
- Tctl = 0x00000400, /* Transmit Control */
- Tipg = 0x00000410, /* Transmit IPG */
- Tdbal = 0x00003800, /* Tdesc Base Address Low */
- Tdbah = 0x00003804, /* Tdesc Base Address High */
- Tdlen = 0x00003808, /* Transmit Descriptor Length */
- Tdh = 0x00003810, /* Transmit Descriptor Head */
- Tdt = 0x00003818, /* Transmit Descriptor Tail */
- Tidv = 0x00003820, /* Transmit Interrupt Delay Value */
- Txdctl = 0x00003828, /* Transmit Descriptor Control */
- Tadv = 0x0000382C, /* Transmit Interrupt Absolute Delay Timer */
- Tarc0 = 0x00003840, /* Transmit Arbitration Counter Queue 0 */
- Tdbal1 = 0x00003900, /* Transmit Descriptor Base Low Queue 1 */
- Tdbah1 = 0x00003904, /* Transmit Descriptor Base High Queue 1 */
- Tdlen1 = 0x00003908, /* Transmit Descriptor Length Queue 1 */
- Tdh1 = 0x00003910, /* Transmit Descriptor Head Queue 1 */
- Tdt1 = 0x00003918, /* Transmit Descriptor Tail Queue 1 */
- Txdctl1 = 0x00003928, /* Transmit Descriptor Control 1 */
- Tarc1 = 0x00003940, /* Transmit Arbitration Counter Queue 1 */
-
- /* Statistics */
-
- Statistics = 0x00004000, /* Start of Statistics Area */
- Gorcl = 0x88/4, /* Good Octets Received Count */
- Gotcl = 0x90/4, /* Good Octets Transmitted Count */
- Torl = 0xC0/4, /* Total Octets Received */
- Totl = 0xC8/4, /* Total Octets Transmitted */
- Nstatistics = 64,
-
-};
-
-enum { /* Ctrl */
- GIOmd = 1<<2, /* BIO master disable */
- Lrst = 1<<3, /* link reset */
- Slu = 1<<6, /* Set Link Up */
- SspeedMASK = 3<<8, /* Speed Selection */
- SspeedSHIFT = 8,
- Sspeed10 = 0x00000000, /* 10Mb/s */
- Sspeed100 = 0x00000100, /* 100Mb/s */
- Sspeed1000 = 0x00000200, /* 1000Mb/s */
- Frcspd = 1<<11, /* Force Speed */
- Frcdplx = 1<<12, /* Force Duplex */
- SwdpinsloMASK = 0x003C0000, /* Software Defined Pins - lo nibble */
- SwdpinsloSHIFT = 18,
- SwdpioloMASK = 0x03C00000, /* Software Defined Pins - I or O */
- SwdpioloSHIFT = 22,
- Devrst = 1<<26, /* Device Reset */
- Rfce = 1<<27, /* Receive Flow Control Enable */
- Tfce = 1<<28, /* Transmit Flow Control Enable */
- Vme = 1<<30, /* VLAN Mode Enable */
- Phy_rst = 1<<31, /* Phy Reset */
-};
-
-enum { /* Status */
- Lu = 1<<1, /* Link Up */
- Lanid = 3<<2, /* mask for Lan ID. */
- Txoff = 1<<4, /* Transmission Paused */
- Tbimode = 1<<5, /* TBI Mode Indication */
- SpeedMASK = 0x000000C0,
- Speed10 = 0x00000000, /* 10Mb/s */
- Speed100 = 0x00000040, /* 100Mb/s */
- Speed1000 = 0x00000080, /* 1000Mb/s */
- Phyra = 1<<10, /* PHY Reset Asserted */
- GIOme = 1<<19, /* GIO Master Enable Status */
-};
-
-enum { /* Ctrl and Status */
- Fd = 0x00000001, /* Full-Duplex */
- AsdvMASK = 0x00000300,
- Asdv10 = 0x00000000, /* 10Mb/s */
- Asdv100 = 0x00000100, /* 100Mb/s */
- Asdv1000 = 0x00000200, /* 1000Mb/s */
-};
-
-enum { /* Eec */
- Sk = 1<<0, /* Clock input to the EEPROM */
- Cs = 1<<1, /* Chip Select */
- Di = 1<<2, /* Data Input to the EEPROM */
- Do = 1<<3, /* Data Output from the EEPROM */
- Areq = 1<<6, /* EEPROM Access Request */
- Agnt = 1<<7, /* EEPROM Access Grant */
-};
-
-enum { /* Eerd */
- ee_start = 1<<0, /* Start Read */
- ee_done = 1<<1, /* Read done */
- ee_addr = 0xfff8<<2, /* Read address [15:2] */
- ee_data = 0xffff<<16, /* Read Data; Data returned from eeprom/nvm */
-};
-
-enum { /* Ctrlext */
- Asdchk = 1<<12, /* ASD Check */
- Eerst = 1<<13, /* EEPROM Reset */
- Spdbyps = 1<<15, /* Speed Select Bypass */
-};
-
-enum { /* EEPROM content offsets */
- Ea = 0x00, /* Ethernet Address */
- Cf = 0x03, /* Compatibility Field */
- Icw1 = 0x0A, /* Initialization Control Word 1 */
- Sid = 0x0B, /* Subsystem ID */
- Svid = 0x0C, /* Subsystem Vendor ID */
- Did = 0x0D, /* Device ID */
- Vid = 0x0E, /* Vendor ID */
- Icw2 = 0x0F, /* Initialization Control Word 2 */
-};
-
-enum { /* Mdic */
- MDIdMASK = 0x0000FFFF, /* Data */
- MDIdSHIFT = 0,
- MDIrMASK = 0x001F0000, /* PHY Register Address */
- MDIrSHIFT = 16,
- MDIpMASK = 0x03E00000, /* PHY Address */
- MDIpSHIFT = 21,
- MDIwop = 0x04000000, /* Write Operation */
- MDIrop = 0x08000000, /* Read Operation */
- MDIready = 0x10000000, /* End of Transaction */
- MDIie = 0x20000000, /* Interrupt Enable */
- MDIe = 0x40000000, /* Error */
-};
-
-enum { /* Icr, Ics, Ims, Imc */
- Txdw = 0x00000001, /* Transmit Descriptor Written Back */
- Txqe = 0x00000002, /* Transmit Queue Empty */
- Lsc = 0x00000004, /* Link Status Change */
- Rxseq = 0x00000008, /* Receive Sequence Error */
- Rxdmt0 = 0x00000010, /* Rdesc Minimum Threshold Reached */
- Rxo = 0x00000040, /* Receiver Overrun */
- Rxt0 = 0x00000080, /* Receiver Timer Interrupt */
- Mdac = 0x00000200, /* MDIO Access Completed */
- Rxcfg = 0x00000400, /* Receiving /C/ ordered sets */
- Gpi0 = 0x00000800, /* General Purpose Interrupts */
- Gpi1 = 0x00001000,
- Gpi2 = 0x00002000,
- Gpi3 = 0x00004000,
- Ack = 0x00020000, /* receive ACK frame */
-};
-
-enum { /* Txcw */
- TxcwFd = 0x00000020, /* Full Duplex */
- TxcwHd = 0x00000040, /* Half Duplex */
- TxcwPauseMASK = 0x00000180, /* Pause */
- TxcwPauseSHIFT = 7,
- TxcwPs = 1<<TxcwPauseSHIFT, /* Pause Supported */
- TxcwAs = 2<<TxcwPauseSHIFT, /* Asymmetric FC desired */
- TxcwRfiMASK = 0x00003000, /* Remote Fault Indication */
- TxcwRfiSHIFT = 12,
- TxcwNpr = 0x00008000, /* Next Page Request */
- TxcwConfig = 0x40000000, /* Transmit COnfig Control */
- TxcwAne = 0x80000000, /* Auto-Negotiation Enable */
-};
-
-enum { /* Rctl */
- Rrst = 0x00000001, /* Receiver Software Reset */
- Ren = 0x00000002, /* Receiver Enable */
- Sbp = 0x00000004, /* Store Bad Packets */
- Upe = 0x00000008, /* Unicast Promiscuous Enable */
- Mpe = 0x00000010, /* Multicast Promiscuous Enable */
- Lpe = 0x00000020, /* Long Packet Reception Enable */
- LbmMASK = 0x000000C0, /* Loopback Mode */
- LbmOFF = 0x00000000, /* No Loopback */
- LbmTBI = 0x00000040, /* TBI Loopback */
- LbmMII = 0x00000080, /* GMII/MII Loopback */
- LbmXCVR = 0x000000C0, /* Transceiver Loopback */
- RdtmsMASK = 0x00000300, /* Rdesc Minimum Threshold Size */
- RdtmsHALF = 0x00000000, /* Threshold is 1/2 Rdlen */
- RdtmsQUARTER = 0x00000100, /* Threshold is 1/4 Rdlen */
- RdtmsEIGHTH = 0x00000200, /* Threshold is 1/8 Rdlen */
- MoMASK = 0x00003000, /* Multicast Offset */
- Bam = 0x00008000, /* Broadcast Accept Mode */
- BsizeMASK = 0x00030000, /* Receive Buffer Size */
- Bsize2048 = 0x00000000,
- Bsize1024 = 0x00010000,
- Bsize512 = 0x00020000,
- Bsize256 = 0x00030000,
- Vfe = 0x00040000, /* VLAN Filter Enable */
- Cfien = 0x00080000, /* Canonical Form Indicator Enable */
- Cfi = 0x00100000, /* Canonical Form Indicator value */
- Dpf = 0x00400000, /* Discard Pause Frames */
- Pmcf = 0x00800000, /* Pass MAC Control Frames */
- Bsex = 0x02000000, /* Buffer Size Extension */
- Secrc = 0x04000000, /* Strip CRC from incoming packet */
-};
-
-enum { /* Tctl */
- Trst = 0x00000001, /* Transmitter Software Reset */
- Ten = 0x00000002, /* Transmit Enable */
- Psp = 0x00000008, /* Pad Short Packets */
- Mulr = 0x10000000, /* Allow multiple concurrent requests */
- CtMASK = 0x00000FF0, /* Collision Threshold */
- CtSHIFT = 4,
- ColdMASK = 0x003FF000, /* Collision Distance */
- ColdSHIFT = 12,
- Swxoff = 0x00400000, /* Sofware XOFF Transmission */
- Pbe = 0x00800000, /* Packet Burst Enable */
- Rtlc = 0x01000000, /* Re-transmit on Late Collision */
- Nrtu = 0x02000000, /* No Re-transmit on Underrrun */
-};
-
-enum { /* [RT]xdctl */
- PthreshMASK = 0x0000003F, /* Prefetch Threshold */
- PthreshSHIFT = 0,
- HthreshMASK = 0x00003F00, /* Host Threshold */
- HthreshSHIFT = 8,
- WthreshMASK = 0x003F0000, /* Writebacj Threshold */
- WthreshSHIFT = 16,
- Gran = 0x01000000, /* Granularity */
-};
-
-enum { /* Rxcsum */
- PcssMASK = 0x000000FF, /* Packet Checksum Start */
- PcssSHIFT = 0,
- Ipofl = 0x00000100, /* IP Checksum Off-load Enable */
- Tuofl = 0x00000200, /* TCP/UDP Checksum Off-load Enable */
-};
-
-typedef struct Rdesc { /* Receive Descriptor */
- uint addr[2];
- ushort length;
- ushort checksum;
- uchar status;
- uchar errors;
- ushort special;
-} Rdesc;
-
-enum { /* Rdesc status */
- Rdd = 0x01, /* Descriptor Done */
- Reop = 0x02, /* End of Packet */
- Ixsm = 0x04, /* Ignore Checksum Indication */
- Vp = 0x08, /* Packet is 802.1Q (matched VET) */
- Tcpcs = 0x20, /* TCP Checksum Calculated on Packet */
- Ipcs = 0x40, /* IP Checksum Calculated on Packet */
- Pif = 0x80, /* Passed in-exact filter */
-};
-
-enum { /* Rdesc errors */
- Ce = 0x01, /* CRC Error or Alignment Error */
- Se = 0x02, /* Symbol Error */
- Seq = 0x04, /* Sequence Error */
- Cxe = 0x10, /* Carrier Extension Error */
- Tcpe = 0x20, /* TCP/UDP Checksum Error */
- Ipe = 0x40, /* IP Checksum Error */
- Rxe = 0x80, /* RX Data Error */
-};
-
-typedef struct Tdesc { /* Legacy+Normal Transmit Descriptor */
- uint addr[2];
- uint control; /* varies with descriptor type */
- uint status; /* varies with descriptor type */
-} Tdesc;
-
-enum { /* Tdesc control */
- LenMASK = 0x000FFFFF, /* Data/Packet Length Field */
- LenSHIFT = 0,
- DtypeCD = 0x00000000, /* Data Type 'Context Descriptor' */
- DtypeDD = 0x00100000, /* Data Type 'Data Descriptor' */
- PtypeTCP = 0x01000000, /* TCP/UDP Packet Type (CD) */
- Teop = 0x01000000, /* End of Packet (DD) */
- PtypeIP = 0x02000000, /* IP Packet Type (CD) */
- Ifcs = 0x02000000, /* Insert FCS (DD) */
- Tse = 0x04000000, /* TCP Segmentation Enable */
- Rs = 0x08000000, /* Report Status */
- Rps = 0x10000000, /* Report Status Sent */
- Dext = 0x20000000, /* Descriptor Extension */
- Vle = 0x40000000, /* VLAN Packet Enable */
- Ide = 0x80000000, /* Interrupt Delay Enable */
-};
-
-enum { /* Tdesc status */
- Tdd = 0x00000001, /* Descriptor Done */
- Ec = 0x00000002, /* Excess Collisions */
- Lc = 0x00000004, /* Late Collision */
- Tu = 0x00000008, /* Transmit Underrun */
- CssMASK = 0x0000FF00, /* Checksum Start Field */
- CssSHIFT = 8,
-};
-
-enum {
- Nrdesc = 128, /* multiple of 8 */
- Ntdesc = 128, /* multiple of 8 */
-};
-
-enum {
- i82563,
- i82571,
- i82573,
-};
-
-static char *tname[] = {
- "i82563",
- "i82571",
- "i82573",
-};
-
-#define Type tname[ctlr->type]
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
- int port;
- Pcidev *pcidev;
- Ctlr *next;
- int active;
- int cls;
- ushort eeprom[0x40];
- uchar ra[Eaddrlen]; /* receive address */
- int type;
-
- int* nic;
- Lock imlock;
- int im; /* interrupt mask */
-
- Lock slock;
- uint statistics[Nstatistics];
-
- Rdesc *rdba; /* receive descriptor base address */
- Block **rb; /* receive buffers */
- int rdh; /* receive descriptor head */
- int rdt; /* receive descriptor tail */
-
- Tdesc *tdba; /* transmit descriptor base address */
- Lock tdlock;
- Block **tb; /* transmit buffers */
- int tdh; /* transmit descriptor head */
- int tdt; /* transmit descriptor tail */
-
- int txcw;
- int fcrtl;
- int fcrth;
-
- /* bootstrap goo */
- Block *bqhead; /* transmission queue */
- Block *bqtail;
-};
-
-static Ctlr *ctlrhead;
-static Ctlr *ctlrtail;
-
-#define csr32r(c, r) (*((c)->nic+((r)/4)))
-#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
-
-static void
-i82563im(Ctlr* ctlr, int im)
-{
- ilock(&ctlr->imlock);
- ctlr->im |= im;
- csr32w(ctlr, Ims, ctlr->im);
- iunlock(&ctlr->imlock);
-}
-
-static void
-i82563attach(Ether* edev)
-{
- int ctl;
- Ctlr *ctlr;
-
- ctlr = edev->ctlr;
- i82563im(ctlr, 0);
- ctl = csr32r(ctlr, Rctl)|Ren;
- csr32w(ctlr, Rctl, ctl);
- ctl = csr32r(ctlr, Tctl)|Ten;
- csr32w(ctlr, Tctl, ctl);
-}
-
-
-static void
-txstart(Ether *edev)
-{
- int tdh, tdt;
- Ctlr *ctlr = edev->ctlr;
- Block *bp;
- Tdesc *tdesc;
-
- /*
- * Try to fill the ring back up, moving buffers from the transmit q.
- */
- tdh = PREV(ctlr->tdh, Ntdesc);
- for(tdt = ctlr->tdt; tdt != tdh; tdt = NEXT(tdt, Ntdesc)){
- /* pull off the head of the transmission queue */
- if((bp = ctlr->bqhead) == nil) /* was qget(edev->oq) */
- break;
- ctlr->bqhead = bp->next;
- if (ctlr->bqtail == bp)
- ctlr->bqtail = nil;
-
- /* set up a descriptor for it */
- tdesc = &ctlr->tdba[tdt];
- tdesc->addr[0] = PCIWADDR(bp->rp);
- tdesc->addr[1] = 0;
- tdesc->control = /* Ide | */ Rs | Ifcs | Teop | BLEN(bp);
-
- ctlr->tb[tdt] = bp;
- }
- ctlr->tdt = tdt;
- csr32w(ctlr, Tdt, tdt);
- i82563im(ctlr, Txdw);
-}
-
-static Block *
-fromringbuf(Ether *ether)
-{
- RingBuf *tb = ðer->tb[ether->ti];
- Block *bp = allocb(tb->len);
-
- memmove(bp->wp, tb->pkt, tb->len);
- memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
- bp->wp += tb->len;
- return bp;
-}
-
-static void
-i82563transmit(Ether* edev)
-{
- Block *bp;
- Ctlr *ctlr;
- Tdesc *tdesc;
- RingBuf *tb;
- int tdh;
-
- ctlr = edev->ctlr;
- ilock(&ctlr->tdlock);
-
- /*
- * Free any completed packets
- * - try to get the soft tdh to catch the tdt;
- * - if the packet had an underrun bump the threshold
- * - the Tu bit doesn't seem to ever be set, perhaps
- * because Rs mode is used?
- */
- tdh = ctlr->tdh;
- for(;;){
- tdesc = &ctlr->tdba[tdh];
- if(!(tdesc->status & Tdd))
- break;
- if(ctlr->tb[tdh] != nil){
- freeb(ctlr->tb[tdh]);
- ctlr->tb[tdh] = nil;
- }
- tdesc->status = 0;
- tdh = NEXT(tdh, Ntdesc);
- }
- ctlr->tdh = tdh;
-
- /* copy packets from the software RingBuf to the transmission q */
- while((tb = &edev->tb[edev->ti])->owner == Interface){
- bp = fromringbuf(edev);
-// print("#l%d: tx %d %E %E\n", edev->ctlrno, edev->ti, bp->rp,
-// bp->rp+6);
-
- if(ctlr->bqhead)
- ctlr->bqtail->next = bp;
- else
- ctlr->bqhead = bp;
- ctlr->bqtail = bp;
-
- txstart(edev); /* kick transmitter */
- tb->owner = Host; /* give descriptor back */
- edev->ti = NEXT(edev->ti, edev->ntb);
- }
- iunlock(&ctlr->tdlock);
-}
-
-static void
-i82563replenish(Ctlr* ctlr)
-{
- int rdt;
- Block *bp;
- Rdesc *rdesc;
-
- rdt = ctlr->rdt;
- while(NEXT(rdt, Nrdesc) != ctlr->rdh){
- rdesc = &ctlr->rdba[rdt];
- if(ctlr->rb[rdt] != nil){
- /* nothing to do */
- }
- else if((bp = iallocb(2048)) != nil){
- ctlr->rb[rdt] = bp;
- rdesc->addr[0] = PCIWADDR(bp->rp);
- rdesc->addr[1] = 0;
- }
- else
- break;
- rdesc->status = 0;
-
- rdt = NEXT(rdt, Nrdesc);
- }
- ctlr->rdt = rdt;
- csr32w(ctlr, Rdt, rdt);
-}
-
-static void
-toringbuf(Ether *ether, Block *bp)
-{
- RingBuf *rb = ðer->rb[ether->ri];
-
- if (rb->owner == Interface) {
- rb->len = BLEN(bp);
- memmove(rb->pkt, bp->rp, rb->len);
- rb->owner = Host;
- ether->ri = NEXT(ether->ri, ether->nrb);
- } else if (debug)
- print("#l%d: toringbuf: dropping packets @ ri %d\n",
- ether->ctlrno, ether->ri);
-}
-
-static void
-i82563interrupt(Ureg*, void* arg)
-{
- int icr, im, rdh, txdw = 0;
- Block *bp;
- Ctlr *ctlr;
- Ether *edev;
- Rdesc *rdesc;
-
- edev = arg;
- ctlr = edev->ctlr;
-
- ilock(&ctlr->imlock);
- csr32w(ctlr, Imc, ~0);
- im = ctlr->im;
-
- for(icr = csr32r(ctlr, Icr); icr & ctlr->im; icr = csr32r(ctlr, Icr)){
- if(icr & (Rxseq|Lsc)){
- /* should be more here */
- }
-
- rdh = ctlr->rdh;
- for (;;) {
- rdesc = &ctlr->rdba[rdh];
- if(!(rdesc->status & Rdd))
- break;
- if ((rdesc->status & Reop) && rdesc->errors == 0) {
- bp = ctlr->rb[rdh];
- if(0 && memcmp(bp->rp, broadcast, 6) != 0)
- print("#l%d: rx %d %E %E %d\n",
- edev->ctlrno, rdh, bp->rp,
- bp->rp+6, rdesc->length);
- ctlr->rb[rdh] = nil;
- bp->wp += rdesc->length;
- toringbuf(edev, bp);
- freeb(bp);
- } else if (rdesc->status & Reop && rdesc->errors)
- print("%s: input packet error 0x%ux\n",
- Type, rdesc->errors);
- rdesc->status = 0;
- rdh = NEXT(rdh, Nrdesc);
- }
- ctlr->rdh = rdh;
- if(icr & Rxdmt0)
- i82563replenish(ctlr);
- if(icr & Txdw){
- im &= ~Txdw;
- txdw++;
- }
- }
- ctlr->im = im;
- csr32w(ctlr, Ims, im);
- iunlock(&ctlr->imlock);
- if(txdw)
- i82563transmit(edev);
-}
-
-static void
-i82563init(Ether* edev)
-{
- int csr, i, r;
- Ctlr *ctlr;
-
- ctlr = edev->ctlr;
- csr = edev->ea[3]<<24 | edev->ea[2]<<16 | edev->ea[1]<<8 | edev->ea[0];
- csr32w(ctlr, Ral, csr);
- csr = 0x80000000 | edev->ea[5]<<8 | edev->ea[4];
- csr32w(ctlr, Rah, csr);
- for (i = 1; i < 16; i++) {
- csr32w(ctlr, Ral+i*8, 0);
- csr32w(ctlr, Rah+i*8, 0);
- }
- for(i = 0; i < 128; i++)
- csr32w(ctlr, Mta+i*4, 0);
- csr32w(ctlr, Rctl, 0);
- ctlr->rdba = xspanalloc(Nrdesc*sizeof(Rdesc), 256, 0);
- csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
- csr32w(ctlr, Rdbah, 0);
- csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc));
- ctlr->rdh = 0;
- csr32w(ctlr, Rdh, ctlr->rdh);
- ctlr->rdt = 0;
- csr32w(ctlr, Rdt, ctlr->rdt);
- ctlr->rb = malloc(sizeof(Block*)*Nrdesc);
- i82563replenish(ctlr);
- csr32w(ctlr, Rdtr, 0);
- csr32w(ctlr, Rctl, Dpf | Bsize2048 | Bam | RdtmsHALF);
- i82563im(ctlr, Rxt0 | Rxo | Rxdmt0 | Rxseq | Ack);
-
- csr32w(ctlr, Tctl, 0x0F<<CtSHIFT | Psp | 0x3f<<ColdSHIFT | Mulr);
- csr32w(ctlr, Tipg, 6<<20 | 8<<10 | 8);
- csr32w(ctlr, Tidv, 1);
-
- ctlr->tdba = xspanalloc(Ntdesc*sizeof(Tdesc), 256, 0);
- memset(ctlr->tdba, 0, Ntdesc*sizeof(Tdesc));
- csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
-
- csr32w(ctlr, Tdbah, 0);
- csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc));
- ctlr->tdh = 0;
- csr32w(ctlr, Tdh, ctlr->tdh);
- ctlr->tdt = 0;
- csr32w(ctlr, Tdt, ctlr->tdt);
- ctlr->tb = malloc(sizeof(Block*)*Ntdesc);
-
-// r = 4<<WthreshSHIFT | 4<<HthreshSHIFT | 8<<PthreshSHIFT;
-// csr32w(ctlr, Txdctl, r);
- csr32w(ctlr, Rxcsum, Tuofl | Ipofl | ETHERHDRSIZE<<PcssSHIFT);
- r = csr32r(ctlr, Tctl);
- r |= Ten;
- csr32w(ctlr, Tctl, r);
-}
-
-
-static ushort
-eeread(Ctlr* ctlr, int adr)
-{
- csr32w(ctlr, Eerd, ee_start | adr << 2);
- while ((csr32r(ctlr, Eerd) & ee_done) == 0)
- ;
- return csr32r(ctlr, Eerd) >> 16;
-}
-
-static int
-eeload(Ctlr* ctlr)
-{
- ushort sum;
- int data, adr;
-
- sum = 0;
- for (adr = 0; adr < 0x40; adr++) {
- data = eeread(ctlr, adr);
- ctlr->eeprom[adr] = data;
- sum += data;
- }
- return sum;
-}
-
-
-static void
-detach(Ctlr *ctlr)
-{
- int r;
-
- csr32w(ctlr, Imc, ~0);
- csr32w(ctlr, Rctl, 0);
- csr32w(ctlr, Tctl, 0);
-
- delay(10);
-
- r = csr32r(ctlr, Ctrl);
- csr32w(ctlr, Ctrl, Devrst | r);
- /* apparently needed on multi-GHz processors to avoid infinite loops */
- delay(1);
- while(csr32r(ctlr, Ctrl) & Devrst)
- ;
-
- if(1 || ctlr->type != i82563){
- r = csr32r(ctlr, Ctrl);
- csr32w(ctlr, Ctrl, Slu | r);
- }
-
- csr32w(ctlr, Ctrlext, Eerst | csr32r(ctlr, Ctrlext));
- delay(1);
- while(csr32r(ctlr, Ctrlext) & Eerst)
- ;
-
- csr32w(ctlr, Imc, ~0);
- delay(1);
- while(csr32r(ctlr, Icr))
- ;
-}
-
-static void
-i82563detach(Ether *edev)
-{
- detach(edev->ctlr);
-}
-
-static void
-i82563shutdown(Ether* ether)
-{
- i82563detach(ether);
-}
-
-static int
-i82563reset(Ctlr* ctlr)
-{
- int i, r;
-
- detach(ctlr);
-
- r = eeload(ctlr);
- if (r != 0 && r != 0xBABA){
- print("%s: bad EEPROM checksum - 0x%4.4ux\n", Type, r);
- return -1;
- }
-
- for(i = Ea; i < Eaddrlen/2; i++){
- ctlr->ra[2*i] = ctlr->eeprom[i];
- ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
- }
- r = (csr32r(ctlr, Status) & Lanid) >> 2;
- ctlr->ra[5] += r; /* ea ctlr[1] = ea ctlr[0]+1 */
-
- r = ctlr->ra[3]<<24 | ctlr->ra[2]<<16 | ctlr->ra[1]<<8 | ctlr->ra[0];
- csr32w(ctlr, Ral, r);
- r = 0x80000000 | ctlr->ra[5]<<8 | ctlr->ra[4];
- csr32w(ctlr, Rah, r);
- for(i = 1; i < 16; i++){
- csr32w(ctlr, Ral+i*8, 0);
- csr32w(ctlr, Rah+i*8, 0);
- }
-
- for(i = 0; i < 128; i++)
- csr32w(ctlr, Mta+i*4, 0);
-
- csr32w(ctlr, Fcal, 0x00C28001);
- csr32w(ctlr, Fcah, 0x00000100);
- csr32w(ctlr, Fct, 0x00008808);
- csr32w(ctlr, Fcttv, 0x00000100);
-
- csr32w(ctlr, Fcrtl, ctlr->fcrtl);
- csr32w(ctlr, Fcrth, ctlr->fcrth);
-
- ilock(&ctlr->imlock);
- csr32w(ctlr, Imc, ~0);
- ctlr->im = 0; /* was = Lsc, which hangs some controllers */
- csr32w(ctlr, Ims, ctlr->im);
- iunlock(&ctlr->imlock);
-
- return 0;
-}
-
-static void
-i82563pci(void)
-{
- int port, type, cls;
- Pcidev *p;
- Ctlr *ctlr;
- static int first = 1;
-
- if (first)
- first = 0;
- else
- return;
-
- p = nil;
- while(p = pcimatch(p, 0x8086, 0)){
- switch(p->did){
- case 0x1096:
- case 0x10ba:
- type = i82563;
- break;
- case 0x108b: /* e */
- case 0x108c: /* e (iamt) */
- case 0x109a: /* l */
- type = i82573;
- break;
- default:
- continue;
- }
-
- port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
- if(port == 0){
- print("%s: can't map %d @ 0x%8.8lux\n", tname[type],
- p->mem[0].size, p->mem[0].bar);
- continue;
- }
-
- if(p->pcr & MemWrInv){
- cls = pcicfgr8(p, PciCLS) * 4;
- if(cls != CACHELINESZ)
- pcicfgw8(p, PciCLS, CACHELINESZ/4);
- }
-
- cls = pcicfgr8(p, PciCLS);
- switch(cls){
- default:
- print("%s: unexpected CLS - %d bytes\n",
- tname[type], cls*sizeof(long));
- break;
- case 0x00:
- case 0xFF:
- /* alphapc 164lx returns 0 */
- print("%s: unusable PciCLS: %d, using %d longs\n",
- tname[type], cls, CACHELINESZ/sizeof(long));
- cls = CACHELINESZ/sizeof(long);
- pcicfgw8(p, PciCLS, cls);
- break;
- case 0x08:
- case 0x10:
- break;
- }
-
- ctlr = malloc(sizeof(Ctlr));
- ctlr->port = port;
- ctlr->pcidev = p;
- ctlr->cls = cls*4;
- ctlr->type = type;
- ctlr->nic = KADDR(ctlr->port);
- if(i82563reset(ctlr)){
- free(ctlr);
- continue;
- }
- pcisetbme(p);
-
- if(ctlrhead != nil)
- ctlrtail->next = ctlr;
- else
- ctlrhead = ctlr;
- ctlrtail = ctlr;
- }
-}
-
-static uchar nilea[Eaddrlen];
-
-int
-i82563pnp(Ether* edev)
-{
- Ctlr *ctlr;
-
- if(ctlrhead == nil)
- i82563pci();
-
- /*
- * Any adapter matches if no edev->port is supplied,
- * otherwise the ports must match.
- */
- for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
- if(ctlr->active)
- continue;
- if(edev->port == 0 || edev->port == ctlr->port){
- ctlr->active = 1;
- break;
- }
- }
- if(ctlr == nil)
- return -1;
-
- edev->ctlr = ctlr;
- edev->port = ctlr->port;
- edev->irq = ctlr->pcidev->intl;
- edev->tbdf = ctlr->pcidev->tbdf;
-// edev->mbps = 1000;
-
- if(memcmp(edev->ea, nilea, Eaddrlen) == 0)
- memmove(edev->ea, ctlr->ra, Eaddrlen);
- i82563init(edev);
-
- /*
- * Linkage to the generic ethernet driver.
- */
- edev->attach = i82563attach;
- edev->transmit = i82563transmit;
- edev->interrupt = i82563interrupt;
- edev->detach = i82563detach;
-
- /*
- * with the current structure, there is no right place for this.
- * ideally, we recognize the interface, note it's down and move on.
- * currently either we can skip the interface or note it is down,
- * but not both.
- */
- if((csr32r(ctlr, Status)&Lu) == 0){
- print("ether#%d: 82563 (%s): link down\n", edev->ctlrno, Type);
- return -1;
- }
-
- return 0;
-}
--- a/os/boot/pc/ether83815.c
+++ /dev/null
@@ -1,820 +1,0 @@
-/*
- * National Semiconductor DP83815
- *
- * Supports only internal PHY and has been tested on:
- * Netgear FA311TX (using Netgear DS108 10/100 hub)
- * To do:
- * check Ethernet address;
- * test autonegotiation on 10 Mbit, and 100 Mbit full duplex;
- * external PHY via MII (should be common code for MII);
- * thresholds;
- * ring sizing;
- * physical link changes/disconnect;
- * push initialisation back to attach.
- *
- * C H Forsyth, forsyth@vitanuova.com, 18th June 2001.
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-#define DEBUG (1)
-#define debug if(DEBUG)print
-
-enum {
- Nrde = 8,
- Ntde = 8,
-};
-
-#define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4)
-
-typedef struct Des {
- ulong next;
- int cmdsts;
- ulong addr;
- Block* bp;
-} Des;
-
-enum { /* cmdsts */
- Own = 1<<31, /* set by data producer to hand to consumer */
- More = 1<<30, /* more of packet in next descriptor */
- Intr = 1<<29, /* interrupt when device is done with it */
- Supcrc = 1<<28, /* suppress crc on transmit */
- Inccrc = 1<<28, /* crc included on receive (always) */
- Ok = 1<<27, /* packet ok */
- Size = 0xFFF, /* packet size in bytes */
-
- /* transmit */
- Txa = 1<<26, /* transmission aborted */
- Tfu = 1<<25, /* transmit fifo underrun */
- Crs = 1<<24, /* carrier sense lost */
- Td = 1<<23, /* transmission deferred */
- Ed = 1<<22, /* excessive deferral */
- Owc = 1<<21, /* out of window collision */
- Ec = 1<<20, /* excessive collisions */
- /* 19-16 collision count */
-
- /* receive */
- Rxa = 1<<26, /* receive aborted (same as Rxo) */
- Rxo = 1<<25, /* receive overrun */
- Dest = 3<<23, /* destination class */
- Drej= 0<<23, /* packet was rejected */
- Duni= 1<<23, /* unicast */
- Dmulti= 2<<23, /* multicast */
- Dbroad= 3<<23, /* broadcast */
- Long = 1<<22, /* too long packet received */
- Runt = 1<<21, /* packet less than 64 bytes */
- Ise = 1<<20, /* invalid symbol */
- Crce = 1<<19, /* invalid crc */
- Fae = 1<<18, /* frame alignment error */
- Lbp = 1<<17, /* loopback packet */
- Col = 1<<16, /* collision during receive */
-};
-
-enum { /* Variants */
- Nat83815 = (0x0020<<16)|0x100B,
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
- int port;
- Pcidev* pcidev;
- Ctlr* next;
- int active;
- int id; /* (pcidev->did<<16)|pcidev->vid */
-
- ushort srom[0xB+1];
- uchar sromea[Eaddrlen]; /* MAC address */
-
- uchar fd; /* option or auto negotiation */
-
- int mbps;
-
- Lock ilock;
-
- Des* rdr; /* receive descriptor ring */
- int nrdr; /* size of rdr */
- int rdrx; /* index into rdr */
-
- Lock tlock;
- Des* tdr; /* transmit descriptor ring */
- int ntdr; /* size of tdr */
- int tdrh; /* host index into tdr */
- int tdri; /* interface index into tdr */
- int ntq; /* descriptors active */
- int ntqmax;
- Block* bqhead; /* transmission queue */
- Block* bqtail;
-
- ulong rxa; /* receive statistics */
- ulong rxo;
- ulong rlong;
- ulong runt;
- ulong ise;
- ulong crce;
- ulong fae;
- ulong lbp;
- ulong col;
- ulong rxsovr;
- ulong rxorn;
-
- ulong txa; /* transmit statistics */
- ulong tfu;
- ulong crs;
- ulong td;
- ulong ed;
- ulong owc;
- ulong ec;
- ulong txurn;
-
- ulong dperr; /* system errors */
- ulong rmabt;
- ulong rtabt;
- ulong sserr;
- ulong rxsover;
-} Ctlr;
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-enum {
- /* registers (could memory map) */
- Rcr= 0x00, /* command register */
- Rst= 1<<8,
- Rxr= 1<<5, /* receiver reset */
- Txr= 1<<4, /* transmitter reset */
- Rxd= 1<<3, /* receiver disable */
- Rxe= 1<<2, /* receiver enable */
- Txd= 1<<1, /* transmitter disable */
- Txe= 1<<0, /* transmitter enable */
- Rcfg= 0x04, /* configuration */
- Lnksts= 1<<31, /* link good */
- Speed100= 1<<30, /* 100 Mb/s link */
- Fdup= 1<<29, /* full duplex */
- Pol= 1<<28, /* polarity reversal (10baseT) */
- Aneg_dn= 1<<27, /* autonegotiation done */
- Pint_acen= 1<<17, /* PHY interrupt auto clear enable */
- Pause_adv= 1<<16, /* advertise pause during auto neg */
- Paneg_ena= 1<<13, /* auto negotiation enable */
- Paneg_all= 7<<13, /* auto negotiation enable 10/100 half & full */
- Ext_phy= 1<<12, /* enable MII for external PHY */
- Phy_rst= 1<<10, /* reset internal PHY */
- Phy_dis= 1<<9, /* disable internal PHY (eg, low power) */
- Req_alg= 1<<7, /* PCI bus request: set means less aggressive */
- Sb= 1<<6, /* single slot back-off not random */
- Pow= 1<<5, /* out of window timer selection */
- Exd= 1<<4, /* disable excessive deferral timer */
- Pesel= 1<<3, /* parity error algorithm selection */
- Brom_dis= 1<<2, /* disable boot rom interface */
- Bem= 1<<0, /* big-endian mode */
- Rmear= 0x08, /* eeprom access */
- Mdc= 1<<6, /* MII mangement check */
- Mddir= 1<<5, /* MII management direction */
- Mdio= 1<<4, /* MII mangement data */
- Eesel= 1<<3, /* EEPROM chip select */
- Eeclk= 1<<2, /* EEPROM clock */
- Eedo= 1<<1, /* EEPROM data out (from chip) */
- Eedi= 1<<0, /* EEPROM data in (to chip) */
- Rptscr= 0x0C, /* pci test control */
- Risr= 0x10, /* interrupt status */
- Txrcmp= 1<<25, /* transmit reset complete */
- Rxrcmp= 1<<24, /* receiver reset complete */
- Dperr= 1<<23, /* detected parity error */
- Sserr= 1<<22, /* signalled system error */
- Rmabt= 1<<21, /* received master abort */
- Rtabt= 1<<20, /* received target abort */
- Rxsovr= 1<<16, /* RX status FIFO overrun */
- Hiberr= 1<<15, /* high bits error set (OR of 25-16) */
- Phy= 1<<14, /* PHY interrupt */
- Pme= 1<<13, /* power management event (wake online) */
- Swi= 1<<12, /* software interrupt */
- Mib= 1<<11, /* MIB service */
- Txurn= 1<<10, /* TX underrun */
- Txidle= 1<<9, /* TX idle */
- Txerr= 1<<8, /* TX packet error */
- Txdesc= 1<<7, /* TX descriptor (with Intr bit done) */
- Txok= 1<<6, /* TX ok */
- Rxorn= 1<<5, /* RX overrun */
- Rxidle= 1<<4, /* RX idle */
- Rxearly= 1<<3, /* RX early threshold */
- Rxerr= 1<<2, /* RX packet error */
- Rxdesc= 1<<1, /* RX descriptor (with Intr bit done) */
- Rxok= 1<<0, /* RX ok */
- Rimr= 0x14, /* interrupt mask */
- Rier= 0x18, /* interrupt enable */
- Ie= 1<<0, /* interrupt enable */
- Rtxdp= 0x20, /* transmit descriptor pointer */
- Rtxcfg= 0x24, /* transmit configuration */
- Csi= 1<<31, /* carrier sense ignore (needed for full duplex) */
- Hbi= 1<<30, /* heartbeat ignore (needed for full duplex) */
- Atp= 1<<28, /* automatic padding of runt packets */
- Mxdma= 7<<20, /* maximum dma transfer field */
- Mxdma32= 4<<20, /* 4x32-bit words (32 bytes) */
- Mxdma64= 5<<20, /* 8x32-bit words (64 bytes) */
- Flth= 0x3F<<8, /* Tx fill threshold, units of 32 bytes (must be > Mxdma) */
- Drth= 0x3F<<0, /* Tx drain threshold (units of 32 bytes) */
- Flth128= 4<<8, /* fill at 128 bytes */
- Drth512= 16<<0, /* drain at 512 bytes */
- Rrxdp= 0x30, /* receive descriptor pointer */
- Rrxcfg= 0x34, /* receive configuration */
- Atx= 1<<28, /* accept transmit packets (needed for full duplex) */
- Rdrth= 0x1F<<1, /* Rx drain threshold (units of 32 bytes) */
- Rdrth64= 2<<1, /* drain at 64 bytes */
- Rccsr= 0x3C, /* CLKRUN control/status */
- Pmests= 1<<15, /* PME status */
- Rwcsr= 0x40, /* wake on lan control/status */
- Rpcr= 0x44, /* pause control/status */
- Rrfcr= 0x48, /* receive filter/match control */
- Rfen= 1<<31, /* receive filter enable */
- Aab= 1<<30, /* accept all broadcast */
- Aam= 1<<29, /* accept all multicast */
- Aau= 1<<28, /* accept all unicast */
- Apm= 1<<27, /* accept on perfect match */
- Apat= 0xF<<23, /* accept on pattern match */
- Aarp= 1<<22, /* accept ARP */
- Mhen= 1<<21, /* multicast hash enable */
- Uhen= 1<<20, /* unicast hash enable */
- Ulm= 1<<19, /* U/L bit mask */
- /* bits 0-9 are rfaddr */
- Rrfdr= 0x4C, /* receive filter/match data */
- Rbrar= 0x50, /* boot rom address */
- Rbrdr= 0x54, /* boot rom data */
- Rsrr= 0x58, /* silicon revision */
- Rmibc= 0x5C, /* MIB control */
- /* 60-78 MIB data */
-
- /* PHY registers */
- Rbmcr= 0x80, /* basic mode configuration */
- Reset= 1<<15,
- Sel100= 1<<13, /* select 100Mb/sec if no auto neg */
- Anena= 1<<12, /* auto negotiation enable */
- Anrestart= 1<<9, /* restart auto negotiation */
- Selfdx= 1<<8, /* select full duplex if no auto neg */
- Rbmsr= 0x84, /* basic mode status */
- Ancomp= 1<<5, /* autonegotiation complete */
- Rphyidr1= 0x88,
- Rphyidr2= 0x8C,
- Ranar= 0x90, /* autonegotiation advertisement */
- Ranlpar= 0x94, /* autonegotiation link partner ability */
- Raner= 0x98, /* autonegotiation expansion */
- Rannptr= 0x9C, /* autonegotiation next page TX */
- Rphysts= 0xC0, /* PHY status */
- Rmicr= 0xC4, /* MII control */
- Inten= 1<<1, /* PHY interrupt enable */
- Rmisr= 0xC8, /* MII status */
- Rfcscr= 0xD0, /* false carrier sense counter */
- Rrecr= 0xD4, /* receive error counter */
- Rpcsr= 0xD8, /* 100Mb config/status */
- Rphycr= 0xE4, /* PHY control */
- Rtbscr= 0xE8, /* 10BaseT status/control */
-};
-
-/*
- * eeprom addresses
- * 7 to 9 (16 bit words): mac address, shifted and reversed
- */
-
-#define csr32r(c, r) (inl((c)->port+(r)))
-#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
-#define csr16r(c, r) (ins((c)->port+(r)))
-#define csr16w(c, r, l) (outs((c)->port+(r), (ulong)(l)))
-
-static void
-dumpcregs(Ctlr *ctlr)
-{
- int i;
-
- for(i=0; i<=0x5C; i+=4)
- print("%2.2ux %8.8lux\n", i, csr32r(ctlr, i));
-}
-
-static void
-attach(Ether* ether)
-{
- Ctlr *ctlr;
-
- ctlr = ether->ctlr;
- ilock(&ctlr->ilock);
- if(0)
- dumpcregs(ctlr);
- csr32w(ctlr, Rcr, Rxe);
- iunlock(&ctlr->ilock);
-}
-
-static void
-detach(Ether* ether)
-{
- Ctlr *ctlr;
-
- ctlr = ether->ctlr;
- csr32w(ctlr, Rcr, 0);
- delay(1);
-}
-
-static void
-txstart(Ether* ether)
-{
- Ctlr *ctlr;
- Block *bp;
- Des *des;
- int started;
-
- ctlr = ether->ctlr;
- started = 0;
- while(ctlr->ntq < ctlr->ntdr-1){
- bp = ctlr->bqhead;
- if(bp == nil)
- break;
- ctlr->bqhead = bp->next;
- des = &ctlr->tdr[ctlr->tdrh];
- des->bp = bp;
- des->addr = PADDR(bp->rp);
- ctlr->ntq++;
- coherence();
- des->cmdsts = Own | BLEN(bp);
- ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
- started = 1;
- }
- if(started){
- coherence();
- csr32w(ctlr, Rcr, Txe); /* prompt */
- }
-
- if(ctlr->ntq > ctlr->ntqmax)
- ctlr->ntqmax = ctlr->ntq;
-}
-
-static void
-transmit(Ether* ether)
-{
- Ctlr *ctlr;
- Block *bp;
- RingBuf *tb;
-
- ctlr = ether->ctlr;
- ilock(&ctlr->tlock);
- while((tb = ðer->tb[ether->ti])->owner == Interface){
- bp = allocb(tb->len);
- memmove(bp->wp, tb->pkt, tb->len);
- memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
- bp->wp += tb->len;
- if(ctlr->bqhead)
- ctlr->bqtail->next = bp;
- else
- ctlr->bqhead = bp;
- ctlr->bqtail = bp;
- txstart(ether);
- tb->owner = Host;
- ether->ti = NEXT(ether->ti, ether->ntb);
- }
- iunlock(&ctlr->tlock);
-}
-
-static void
-txrxcfg(Ctlr *ctlr, int txdrth)
-{
- ulong rx, tx;
-
- rx = csr32r(ctlr, Rrxcfg);
- tx = csr32r(ctlr, Rtxcfg);
- if(ctlr->fd){
- rx |= Atx;
- tx |= Csi | Hbi;
- }else{
- rx &= ~Atx;
- tx &= ~(Csi | Hbi);
- }
- tx &= ~(Mxdma|Drth|Flth);
- tx |= Mxdma64 | Flth128 | txdrth;
- csr32w(ctlr, Rtxcfg, tx);
- rx &= ~(Mxdma|Rdrth);
- rx |= Mxdma64 | Rdrth64;
- csr32w(ctlr, Rrxcfg, rx);
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
- Ctlr *ctlr;
- Ether *ether;
- int status, cmdsts;
- Des *des;
- RingBuf *rb;
-
- ether = arg;
- ctlr = ether->ctlr;
-
- while((status = csr32r(ctlr, Risr)) != 0){
-
- status &= ~(Pme|Mib);
- status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);
-
- /*
- * Received packets.
- */
- if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){
- des = &ctlr->rdr[ctlr->rdrx];
- while((cmdsts = des->cmdsts) & Own){
- rb = ðer->rb[ether->ri];
- if(rb->owner == Interface && (cmdsts&Ok)){
- rb->len = (cmdsts&Size)-4;
- memmove(rb->pkt, des->bp->rp, rb->len);
- rb->owner = Host;
- ether->ri = NEXT(ether->ri, ether->nrb);
- }
-
- des->cmdsts = Rbsz;
- coherence();
-
- ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
- des = &ctlr->rdr[ctlr->rdrx];
- }
- status &= ~(Rxdesc|Rxok|Rxerr|Rxearly|Rxorn);
- }
-
- /*
- * Check the transmit side:
- * check for Transmit Underflow and Adjust
- * the threshold upwards;
- * free any transmitted buffers and try to
- * top-up the ring.
- */
- if(status & Txurn){
- ctlr->txurn++;
- ilock(&ctlr->ilock);
- /* change threshold */
- iunlock(&ctlr->ilock);
- status &= ~(Txurn);
- }
-
- ilock(&ctlr->tlock);
- while(ctlr->ntq){
- des = &ctlr->tdr[ctlr->tdri];
- cmdsts = des->cmdsts;
- if(cmdsts & Own)
- break;
-
- freeb(des->bp);
- des->bp = nil;
- des->cmdsts = 0;
-
- ctlr->ntq--;
- ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
- }
- txstart(ether);
- iunlock(&ctlr->tlock);
-
- status &= ~(Txurn|Txidle|Txerr|Txdesc|Txok);
-
- /*
- * Anything left not catered for?
- */
- if(status)
- print("#l%d: status %8.8uX\n", ether->ctlrno, status);
- }
-}
-
-static void
-ctlrinit(Ether* ether)
-{
- Ctlr *ctlr;
- Des *des, *last;
-
- ctlr = ether->ctlr;
-
- /*
- * Allocate and initialise the receive ring;
- * allocate and initialise the transmit ring;
- * unmask interrupts and start the transmit side
- */
- ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des));
- last = nil;
- for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
- des->bp = allocb(Rbsz);
- des->cmdsts = Rbsz;
- des->addr = PADDR(des->bp->rp);
- if(last != nil)
- last->next = PADDR(des);
- last = des;
- }
- ctlr->rdr[ctlr->nrdr-1].next = PADDR(ctlr->rdr);
- ctlr->rdrx = 0;
- csr32w(ctlr, Rrxdp, PADDR(ctlr->rdr));
-
- ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0);
- last = nil;
- for(des = ctlr->tdr; des < &ctlr->tdr[ctlr->ntdr]; des++){
- des->cmdsts = 0;
- des->bp = nil;
- des->addr = ~0;
- if(last != nil)
- last->next = PADDR(des);
- last = des;
- }
- ctlr->tdr[ctlr->ntdr-1].next = PADDR(ctlr->tdr);
- ctlr->tdrh = 0;
- ctlr->tdri = 0;
- csr32w(ctlr, Rtxdp, PADDR(ctlr->tdr));
-
- txrxcfg(ctlr, Drth512);
-
- csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok); /* Phy|Pme|Mib */
- csr32r(ctlr, Risr); /* clear status */
- csr32w(ctlr, Rier, Ie);
-}
-
-static void
-eeclk(Ctlr *ctlr, int clk)
-{
- csr32w(ctlr, Rmear, Eesel | clk);
- microdelay(2);
-}
-
-static void
-eeidle(Ctlr *ctlr)
-{
- int i;
-
- eeclk(ctlr, 0);
- eeclk(ctlr, Eeclk);
- for(i=0; i<25; i++){
- eeclk(ctlr, 0);
- eeclk(ctlr, Eeclk);
- }
- eeclk(ctlr, 0);
- csr32w(ctlr, Rmear, 0);
- microdelay(2);
-}
-
-static int
-eegetw(Ctlr *ctlr, int a)
-{
- int d, i, w, v;
-
- eeidle(ctlr);
- eeclk(ctlr, 0);
- eeclk(ctlr, Eeclk);
- d = 0x180 | a;
- for(i=0x400; i; i>>=1){
- v = (d & i) ? Eedi : 0;
- eeclk(ctlr, v);
- eeclk(ctlr, Eeclk|v);
- }
- eeclk(ctlr, 0);
-
- w = 0;
- for(i=0x8000; i; i >>= 1){
- eeclk(ctlr, Eeclk);
- if(csr32r(ctlr, Rmear) & Eedo)
- w |= i;
- microdelay(2);
- eeclk(ctlr, 0);
- }
- eeidle(ctlr);
- return w;
-}
-
-static void
-softreset(Ctlr* ctlr, int resetphys)
-{
- int i, w;
-
- /*
- * Soft-reset the controller
- */
- csr32w(ctlr, Rcr, Rst);
- for(i=0;; i++){
- if(i > 100)
- panic("ns83815: soft reset did not complete");
- microdelay(250);
- if((csr32r(ctlr, Rcr) & Rst) == 0)
- break;
- delay(1);
- }
-
- csr32w(ctlr, Rccsr, Pmests);
- csr32w(ctlr, Rccsr, 0);
- csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen);
-
- if(resetphys){
- /*
- * Soft-reset the PHY
- */
- csr32w(ctlr, Rbmcr, Reset);
- for(i=0;; i++){
- if(i > 100)
- panic("ns83815: PHY soft reset time out");
- if((csr32r(ctlr, Rbmcr) & Reset) == 0)
- break;
- delay(1);
- }
- }
-
- /*
- * Initialisation values, in sequence (see 4.4 Recommended Registers Configuration)
- */
- csr16w(ctlr, 0xCC, 0x0001); /* PGSEL */
- csr16w(ctlr, 0xE4, 0x189C); /* PMCCSR */
- csr16w(ctlr, 0xFC, 0x0000); /* TSTDAT */
- csr16w(ctlr, 0xF4, 0x5040); /* DSPCFG */
- csr16w(ctlr, 0xF8, 0x008C); /* SDCFG */
-
- /*
- * Auto negotiate
- */
- w = csr16r(ctlr, Rbmsr); /* clear latched bits */
- debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
- csr16w(ctlr, Rbmcr, Anena);
- if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){
- csr16w(ctlr, Rbmcr, Anena|Anrestart);
- for(i=0;; i++){
- if(i > 6000){
- print("ns83815: auto neg timed out\n");
- break;
- }
- if((w = csr16r(ctlr, Rbmsr)) & Ancomp)
- break;
- delay(1);
- }
- debug("%d ms\n", i);
- w &= 0xFFFF;
- debug("bmsr: %4.4ux\n", w);
- }
- debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
- debug("anlpar: %4.4ux\n", csr16r(ctlr, Ranlpar));
- debug("aner: %4.4ux\n", csr16r(ctlr, Raner));
- debug("physts: %4.4ux\n", csr16r(ctlr, Rphysts));
- debug("tbscr: %4.4ux\n", csr16r(ctlr, Rtbscr));
-}
-
-static char* mediatable[9] = {
- "10BASE-T", /* TP */
- "10BASE-2", /* BNC */
- "10BASE-5", /* AUI */
- "100BASE-TX",
- "10BASE-TFD",
- "100BASE-TXFD",
- "100BASE-T4",
- "100BASE-FX",
- "100BASE-FXFD",
-};
-
-static void
-srom(Ctlr* ctlr)
-{
- int i, j;
-
- for(i = 0; i < nelem(ctlr->srom); i++)
- ctlr->srom[i] = eegetw(ctlr, i);
-
- /*
- * the MAC address is reversed, straddling word boundaries
- */
- memset(ctlr->sromea, 0, sizeof(ctlr->sromea));
- j = 6*16 + 15;
- for(i=0; i<48; i++){
- ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7);
- j++;
- }
-}
-
-static void
-scanpci83815(void)
-{
- Ctlr *ctlr;
- Pcidev *p;
-
- p = nil;
- while(p = pcimatch(p, 0, 0)){
- if(p->ccrb != 0x02 || p->ccru != 0)
- continue;
- switch((p->did<<16)|p->vid){
- default:
- continue;
-
- case Nat83815:
- break;
- }
-
- /*
- * bar[0] is the I/O port register address and
- * bar[1] is the memory-mapped register address.
- */
- ctlr = malloc(sizeof(Ctlr));
- ctlr->port = p->mem[0].bar & ~0x01;
- ctlr->pcidev = p;
- ctlr->id = (p->did<<16)|p->vid;
-
- softreset(ctlr, 0);
- srom(ctlr);
-
- if(ctlrhead != nil)
- ctlrtail->next = ctlr;
- else
- ctlrhead = ctlr;
- ctlrtail = ctlr;
- }
-}
-
-int
-ether83815reset(Ether* ether)
-{
- Ctlr *ctlr;
- int i, x;
- uchar ea[Eaddrlen];
- static int scandone;
-
- if(scandone == 0){
- scanpci83815();
- scandone = 1;
- }
-
- /*
- * Any adapter matches if no ether->port is supplied,
- * otherwise the ports must match.
- */
- for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
- if(ctlr->active)
- continue;
- if(ether->port == 0 || ether->port == ctlr->port){
- ctlr->active = 1;
- break;
- }
- }
- if(ctlr == nil)
- return -1;
-
- ether->ctlr = ctlr;
- ether->port = ctlr->port;
- ether->irq = ctlr->pcidev->intl;
- ether->tbdf = ctlr->pcidev->tbdf;
-
- /*
- * Check if the adapter's station address is to be overridden.
- * If not, read it from the EEPROM and set in ether->ea prior to
- * loading the station address in the hardware.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, ether->ea, Eaddrlen) == 0)
- memmove(ether->ea, ctlr->sromea, Eaddrlen);
- for(i=0; i<Eaddrlen; i+=2){
- x = ether->ea[i] | (ether->ea[i+1]<<8);
- csr32w(ctlr, Rrfcr, i);
- csr32w(ctlr, Rrfdr, x);
- }
- csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);
-
- /*
- * Look for a medium override in case there's no autonegotiation
- * the autonegotiation fails.
- */
-
- for(i = 0; i < ether->nopt; i++){
- if(cistrcmp(ether->opt[i], "FD") == 0){
- ctlr->fd = 1;
- continue;
- }
- for(x = 0; x < nelem(mediatable); x++){
- debug("compare <%s> <%s>\n", mediatable[x],
- ether->opt[i]);
- if(cistrcmp(mediatable[x], ether->opt[i]) == 0){
- switch(x){
- default:
- ctlr->fd = 0;
- break;
-
- case 0x04: /* 10BASE-TFD */
- case 0x05: /* 100BASE-TXFD */
- case 0x08: /* 100BASE-FXFD */
- ctlr->fd = 1;
- break;
- }
- break;
- }
- }
- }
-
- /*
- * Initialise descriptor rings, ethernet address.
- */
- ctlr->nrdr = Nrde;
- ctlr->ntdr = Ntde;
- pcisetbme(ctlr->pcidev);
- ctlrinit(ether);
-
- /*
- * Linkage to the generic ethernet driver.
- */
- ether->attach = attach;
- ether->transmit = transmit;
- ether->interrupt = interrupt;
- ether->detach = detach;
-
- return 0;
-}
--- a/os/boot/pc/ether8390.c
+++ /dev/null
@@ -1,715 +1,0 @@
-/*
- * National Semiconductor DP8390 and clone
- * Network Interface Controller.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ether8390.h"
-
-enum { /* NIC core registers */
- Cr = 0x00, /* command register, all pages */
-
- /* Page 0, read */
- Clda0 = 0x01, /* current local DMA address 0 */
- Clda1 = 0x02, /* current local DMA address 1 */
- Bnry = 0x03, /* boundary pointer (R/W) */
- Tsr = 0x04, /* transmit status register */
- Ncr = 0x05, /* number of collisions register */
- Fifo = 0x06, /* FIFO */
- Isr = 0x07, /* interrupt status register (R/W) */
- Crda0 = 0x08, /* current remote DMA address 0 */
- Crda1 = 0x09, /* current remote DMA address 1 */
- Rsr = 0x0C, /* receive status register */
- Cntr0 = 0x0D, /* frame alignment errors */
- Cntr1 = 0x0E, /* CRC errors */
- Cntr2 = 0x0F, /* missed packet errors */
-
- /* Page 0, write */
- Pstart = 0x01, /* page start register */
- Pstop = 0x02, /* page stop register */
- Tpsr = 0x04, /* transmit page start address */
- Tbcr0 = 0x05, /* transmit byte count register 0 */
- Tbcr1 = 0x06, /* transmit byte count register 1 */
- Rsar0 = 0x08, /* remote start address register 0 */
- Rsar1 = 0x09, /* remote start address register 1 */
- Rbcr0 = 0x0A, /* remote byte count register 0 */
- Rbcr1 = 0x0B, /* remote byte count register 1 */
- Rcr = 0x0C, /* receive configuration register */
- Tcr = 0x0D, /* transmit configuration register */
- Dcr = 0x0E, /* data configuration register */
- Imr = 0x0F, /* interrupt mask */
-
- /* Page 1, read/write */
- Par0 = 0x01, /* physical address register 0 */
- Curr = 0x07, /* current page register */
- Mar0 = 0x08, /* multicast address register 0 */
-};
-
-enum { /* Cr */
- Stp = 0x01, /* stop */
- Sta = 0x02, /* start */
- Txp = 0x04, /* transmit packet */
- Rd0 = 0x08, /* remote DMA command */
- Rd1 = 0x10,
- Rd2 = 0x20,
- RdREAD = Rd0, /* remote read */
- RdWRITE = Rd1, /* remote write */
- RdSEND = Rd1|Rd0, /* send packet */
- RdABORT = Rd2, /* abort/complete remote DMA */
- Ps0 = 0x40, /* page select */
- Ps1 = 0x80,
- Page0 = 0x00,
- Page1 = Ps0,
- Page2 = Ps1,
-};
-
-enum { /* Isr/Imr */
- Prx = 0x01, /* packet received */
- Ptx = 0x02, /* packet transmitted */
- Rxe = 0x04, /* receive error */
- Txe = 0x08, /* transmit error */
- Ovw = 0x10, /* overwrite warning */
- Cnt = 0x20, /* counter overflow */
- Rdc = 0x40, /* remote DMA complete */
- Rst = 0x80, /* reset status */
-};
-
-enum { /* Dcr */
- Wts = 0x01, /* word transfer select */
- Bos = 0x02, /* byte order select */
- Las = 0x04, /* long address select */
- Ls = 0x08, /* loopback select */
- Arm = 0x10, /* auto-initialise remote */
- Ft0 = 0x20, /* FIFO threshold select */
- Ft1 = 0x40,
- Ft1WORD = 0x00,
- Ft2WORD = Ft0,
- Ft4WORD = Ft1,
- Ft6WORD = Ft1|Ft0,
-};
-
-enum { /* Tcr */
- Crc = 0x01, /* inhibit CRC */
- Lb0 = 0x02, /* encoded loopback control */
- Lb1 = 0x04,
- LpbkNORMAL = 0x00, /* normal operation */
- LpbkNIC = Lb0, /* internal NIC module loopback */
- LpbkENDEC = Lb1, /* internal ENDEC module loopback */
- LpbkEXTERNAL = Lb1|Lb0, /* external loopback */
- Atd = 0x08, /* auto transmit disable */
- Ofst = 0x10, /* collision offset enable */
-};
-
-enum { /* Tsr */
- Ptxok = 0x01, /* packet transmitted */
- Col = 0x04, /* transmit collided */
- Abt = 0x08, /* tranmit aborted */
- Crs = 0x10, /* carrier sense lost */
- Fu = 0x20, /* FIFO underrun */
- Cdh = 0x40, /* CD heartbeat */
- Owc = 0x80, /* out of window collision */
-};
-
-enum { /* Rcr */
- Sep = 0x01, /* save errored packets */
- Ar = 0x02, /* accept runt packets */
- Ab = 0x04, /* accept broadcast */
- Am = 0x08, /* accept multicast */
- Pro = 0x10, /* promiscuous physical */
- Mon = 0x20, /* monitor mode */
-};
-
-enum { /* Rsr */
- Prxok = 0x01, /* packet received intact */
- Crce = 0x02, /* CRC error */
- Fae = 0x04, /* frame alignment error */
- Fo = 0x08, /* FIFO overrun */
- Mpa = 0x10, /* missed packet */
- Phy = 0x20, /* physical/multicast address */
- Dis = 0x40, /* receiver disabled */
- Dfr = 0x80, /* deferring */
-};
-
-typedef struct {
- uchar status;
- uchar next;
- uchar len0;
- uchar len1;
-} Hdr;
-
-void
-dp8390getea(Ether* ether, uchar* ea)
-{
- Dp8390 *ctlr;
- uchar cr;
- int i;
-
- ctlr = ether->ctlr;
-
- /*
- * Get the ethernet address from the chip.
- * Take care to restore the command register
- * afterwards.
- */
- ilock(ctlr);
- cr = regr(ctlr, Cr) & ~Txp;
- regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
- for(i = 0; i < Eaddrlen; i++)
- ea[i] = regr(ctlr, Par0+i);
- regw(ctlr, Cr, cr);
- iunlock(ctlr);
-}
-
-void
-dp8390setea(Ether* ether)
-{
- int i;
- uchar cr;
- Dp8390 *ctlr;
-
- ctlr = ether->ctlr;
-
- /*
- * Set the ethernet address into the chip.
- * Take care to restore the command register
- * afterwards. Don't care about multicast
- * addresses as multicast is never enabled
- * (currently).
- */
- ilock(ctlr);
- cr = regr(ctlr, Cr) & ~Txp;
- regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
- for(i = 0; i < Eaddrlen; i++)
- regw(ctlr, Par0+i, ether->ea[i]);
- regw(ctlr, Cr, cr);
- iunlock(ctlr);
-}
-
-static void*
-_dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len)
-{
- uchar cr;
- int timo;
-
- /*
- * Read some data at offset 'from' in the card's memory
- * using the DP8390 remote DMA facility, and place it at
- * 'to' in main memory, via the I/O data port.
- */
- cr = regr(ctlr, Cr) & ~Txp;
- regw(ctlr, Cr, Page0|RdABORT|Sta);
- regw(ctlr, Isr, Rdc);
-
- /*
- * Set up the remote DMA address and count.
- */
- len = ROUNDUP(len, ctlr->width);
- regw(ctlr, Rbcr0, len & 0xFF);
- regw(ctlr, Rbcr1, (len>>8) & 0xFF);
- regw(ctlr, Rsar0, from & 0xFF);
- regw(ctlr, Rsar1, (from>>8) & 0xFF);
-
- /*
- * Start the remote DMA read and suck the data
- * out of the I/O port.
- */
- regw(ctlr, Cr, Page0|RdREAD|Sta);
- rdread(ctlr, to, len);
-
- /*
- * Wait for the remote DMA to complete. The timeout
- * is necessary because this routine may be called on
- * a non-existent chip during initialisation and, due
- * to the miracles of the bus, it's possible to get this
- * far and still be talking to a slot full of nothing.
- */
- for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--)
- ;
-
- regw(ctlr, Isr, Rdc);
- regw(ctlr, Cr, cr);
-
- return to;
-}
-
-void*
-dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len)
-{
- void *v;
-
- ilock(ctlr);
- v = _dp8390read(ctlr, to, from, len);
- iunlock(ctlr);
-
- return v;
-}
-
-static void*
-dp8390write(Dp8390* ctlr, ulong to, void* from, ulong len)
-{
- ulong crda;
- uchar cr;
- int timo, width;
-
-top:
- /*
- * Write some data to offset 'to' in the card's memory
- * using the DP8390 remote DMA facility, reading it at
- * 'from' in main memory, via the I/O data port.
- */
- cr = regr(ctlr, Cr) & ~Txp;
- regw(ctlr, Cr, Page0|RdABORT|Sta);
- regw(ctlr, Isr, Rdc);
-
- len = ROUNDUP(len, ctlr->width);
-
- /*
- * Set up the remote DMA address and count.
- * This is straight from the DP8390[12D] datasheet,
- * hence the initial set up for read.
- * Assumption here that the A7000 EtherV card will
- * never need a dummyrr.
- */
- if(ctlr->dummyrr && (ctlr->width == 1 || ctlr->width == 2)){
- if(ctlr->width == 2)
- width = 1;
- else
- width = 0;
- crda = to-1-width;
- regw(ctlr, Rbcr0, (len+1+width) & 0xFF);
- regw(ctlr, Rbcr1, ((len+1+width)>>8) & 0xFF);
- regw(ctlr, Rsar0, crda & 0xFF);
- regw(ctlr, Rsar1, (crda>>8) & 0xFF);
- regw(ctlr, Cr, Page0|RdREAD|Sta);
-
- for(timo=0;; timo++){
- if(timo > 10000){
- print("ether8390: dummyrr timeout; assuming nodummyrr\n");
- ctlr->dummyrr = 0;
- goto top;
- }
- crda = regr(ctlr, Crda0);
- crda |= regr(ctlr, Crda1)<<8;
- if(crda == to){
- /*
- * Start the remote DMA write and make sure
- * the registers are correct.
- */
- regw(ctlr, Cr, Page0|RdWRITE|Sta);
-
- crda = regr(ctlr, Crda0);
- crda |= regr(ctlr, Crda1)<<8;
- if(crda != to)
- panic("crda write %d to %d\n", crda, to);
-
- break;
- }
- }
- }
- else{
- regw(ctlr, Rsar0, to & 0xFF);
- regw(ctlr, Rsar1, (to>>8) & 0xFF);
- regw(ctlr, Rbcr0, len & 0xFF);
- regw(ctlr, Rbcr1, (len>>8) & 0xFF);
- regw(ctlr, Cr, Page0|RdWRITE|Sta);
- }
-
- /*
- * Pump the data into the I/O port
- * then wait for the remote DMA to finish.
- */
- rdwrite(ctlr, from, len);
- for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--)
- ;
-
- regw(ctlr, Isr, Rdc);
- regw(ctlr, Cr, cr);
-
- return (void*)to;
-}
-
-static void
-ringinit(Dp8390* ctlr)
-{
- regw(ctlr, Pstart, ctlr->pstart);
- regw(ctlr, Pstop, ctlr->pstop);
- regw(ctlr, Bnry, ctlr->pstop-1);
-
- regw(ctlr, Cr, Page1|RdABORT|Stp);
- regw(ctlr, Curr, ctlr->pstart);
- regw(ctlr, Cr, Page0|RdABORT|Stp);
-
- ctlr->nxtpkt = ctlr->pstart;
-}
-
-static uchar
-getcurr(Dp8390* ctlr)
-{
- uchar cr, curr;
-
- cr = regr(ctlr, Cr) & ~Txp;
- regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
- curr = regr(ctlr, Curr);
- regw(ctlr, Cr, cr);
-
- return curr;
-}
-
-static void
-receive(Ether* ether)
-{
- Dp8390 *ctlr;
- uchar curr, *p;
- Hdr hdr;
- ulong count, data, len;
- RingBuf *ring;
-
- ctlr = ether->ctlr;
- for(curr = getcurr(ctlr); ctlr->nxtpkt != curr; curr = getcurr(ctlr)){
- data = ctlr->nxtpkt*Dp8390BufSz;
- if(ctlr->ram)
- memmove(&hdr, (void*)(ether->mem+data), sizeof(Hdr));
- else
- _dp8390read(ctlr, &hdr, data, sizeof(Hdr));
-
- /*
- * Don't believe the upper byte count, work it
- * out from the software next-page pointer and
- * the current next-page pointer.
- */
- if(hdr.next > ctlr->nxtpkt)
- len = hdr.next - ctlr->nxtpkt - 1;
- else
- len = (ctlr->pstop-ctlr->nxtpkt) + (hdr.next-ctlr->pstart) - 1;
- if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr)))
- len--;
-
- len = ((len<<8)|hdr.len0)-4;
-
- /*
- * Chip is badly scrogged, reinitialise the ring.
- */
- if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop
- || len < 60 || len > sizeof(Etherpkt)){
- print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%lud\n",
- hdr.status, hdr.next, hdr.len0, hdr.len1, len);
- regw(ctlr, Cr, Page0|RdABORT|Stp);
- ringinit(ctlr);
- regw(ctlr, Cr, Page0|RdABORT|Sta);
-
- return;
- }
-
- /*
- * If it's a good packet read it in to the software buffer.
- * If the packet wraps round the hardware ring, read it in
- * two pieces.
- */
- ring = ðer->rb[ether->ri];
- if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && ring->owner == Interface){
- p = ring->pkt;
- ring->len = len;
- data += sizeof(Hdr);
-
- if((data+len) >= ctlr->pstop*Dp8390BufSz){
- count = ctlr->pstop*Dp8390BufSz - data;
- if(ctlr->ram)
- memmove(p, (void*)(ether->mem+data), count);
- else
- _dp8390read(ctlr, p, data, count);
- p += count;
- data = ctlr->pstart*Dp8390BufSz;
- len -= count;
- }
- if(len){
- if(ctlr->ram)
- memmove(p, (void*)(ether->mem+data), len);
- else
- _dp8390read(ctlr, p, data, len);
- }
-
- /*
- * Copy the packet to whoever wants it.
- */
- ring->owner = Host;
- ether->ri = NEXT(ether->ri, ether->nrb);
- }
-
- /*
- * Finished with this packet, update the
- * hardware and software ring pointers.
- */
- ctlr->nxtpkt = hdr.next;
-
- hdr.next--;
- if(hdr.next < ctlr->pstart)
- hdr.next = ctlr->pstop-1;
- regw(ctlr, Bnry, hdr.next);
- }
-}
-
-static void
-txstart(Ether* ether)
-{
- int len;
- Dp8390 *ctlr;
- RingBuf *ring;
- uchar minpkt[ETHERMINTU], *rp;
-
- ctlr = ether->ctlr;
-
- /*
- * This routine is called both from the top level and from interrupt
- * level and expects to be called with ctlr already locked.
- */
- if(ether->tbusy)
- return;
- ring = ðer->tb[ether->ti];
- if(ring->owner != Interface)
- return;
-
- /*
- * Make sure the packet is of minimum length;
- * copy it to the card's memory by the appropriate means;
- * start the transmission.
- */
- len = ring->len;
- rp = ring->pkt;
- if(len < ETHERMINTU){
- rp = minpkt;
- memmove(rp, ring->pkt, len);
- memset(rp+len, 0, ETHERMINTU-len);
- len = ETHERMINTU;
- }
-
- if(ctlr->ram)
- memmove((void*)(ether->mem+ctlr->tstart*Dp8390BufSz), rp, len);
- else
- dp8390write(ctlr, ctlr->tstart*Dp8390BufSz, rp, len);
-
- regw(ctlr, Tbcr0, len & 0xFF);
- regw(ctlr, Tbcr1, (len>>8) & 0xFF);
- regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);
-
- ether->tbusy = 1;
-}
-
-static void
-transmit(Ether* ether)
-{
- Dp8390 *ctlr;
-
- ctlr = ether->ctlr;
-
- ilock(ctlr);
- txstart(ether);
- iunlock(ctlr);
-}
-
-static void
-overflow(Ether *ether)
-{
- Dp8390 *ctlr;
- uchar txp;
- int resend;
-
- ctlr = ether->ctlr;
-
- /*
- * The following procedure is taken from the DP8390[12D] datasheet,
- * it seems pretty adamant that this is what has to be done.
- */
- txp = regr(ctlr, Cr) & Txp;
- regw(ctlr, Cr, Page0|RdABORT|Stp);
- delay(2);
- regw(ctlr, Rbcr0, 0);
- regw(ctlr, Rbcr1, 0);
-
- resend = 0;
- if(txp && (regr(ctlr, Isr) & (Txe|Ptx)) == 0)
- resend = 1;
-
- regw(ctlr, Tcr, LpbkNIC);
- regw(ctlr, Cr, Page0|RdABORT|Sta);
- receive(ether);
- regw(ctlr, Isr, Ovw);
- regw(ctlr, Tcr, LpbkNORMAL);
-
- if(resend)
- regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
- Ether *ether;
- Dp8390 *ctlr;
- RingBuf *ring;
- uchar isr, r;
-
- ether = arg;
- ctlr = ether->ctlr;
-
- /*
- * While there is something of interest,
- * clear all the interrupts and process.
- */
- ilock(ctlr);
- regw(ctlr, Imr, 0x00);
- while(isr = (regr(ctlr, Isr) & (Cnt|Ovw|Txe|Rxe|Ptx|Prx))){
- if(isr & Ovw){
- overflow(ether);
- regw(ctlr, Isr, Ovw);
- }
-
- /*
- * Packets have been received.
- * Take a spin round the ring.
- */
- if(isr & (Rxe|Prx)){
- receive(ether);
- regw(ctlr, Isr, Rxe|Prx);
- }
-
- /*
- * A packet completed transmission, successfully or
- * not. Start transmission on the next buffered packet,
- * and wake the output routine.
- */
- if(isr & (Txe|Ptx)){
- r = regr(ctlr, Tsr);
- if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){
- print("dp8390: Tsr#%2.2ux|", r);
- }
-
- regw(ctlr, Isr, Txe|Ptx);
-
- ring = ðer->tb[ether->ti];
- ring->owner = Host;
- ether->ti = NEXT(ether->ti, ether->ntb);
- ether->tbusy = 0;
- txstart(ether);
- }
-
- if(isr & Cnt){
- regr(ctlr, Cntr0);
- regr(ctlr, Cntr1);
- regr(ctlr, Cntr2);
- regw(ctlr, Isr, Cnt);
- }
- }
- regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
- iunlock(ctlr);
-}
-
-static void
-attach(Ether* ether)
-{
- Dp8390 *ctlr;
- uchar r;
-
- ctlr = ether->ctlr;
-
- /*
- * Enable the chip for transmit/receive.
- * The init routine leaves the chip in monitor
- * mode. Clear the missed-packet counter, it
- * increments while in monitor mode.
- * Sometimes there's an interrupt pending at this
- * point but there's nothing in the Isr, so
- * any pending interrupts are cleared and the
- * mask of acceptable interrupts is enabled here.
- */
- r = Ab;
- ilock(ctlr);
- regw(ctlr, Isr, 0xFF);
- regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
- regw(ctlr, Rcr, r);
- r = regr(ctlr, Cntr2);
- regw(ctlr, Tcr, LpbkNORMAL);
- iunlock(ctlr);
- USED(r);
-}
-
-static void
-detach(Ether* ether)
-{
- int timo;
- Dp8390 *ctlr;
-
- /*
- * Stop the chip. Set the Stp bit and wait for the chip
- * to finish whatever was on its tiny mind before it sets
- * the Rst bit.
- * The timeout is needed because there may not be a real
- * chip there if this is called when probing for a device
- * at boot.
- */
- ctlr = ether->ctlr;
- regw(ctlr, Cr, Page0|RdABORT|Stp);
- regw(ctlr, Rbcr0, 0);
- regw(ctlr, Rbcr1, 0);
- for(timo = 10000; (regr(ctlr, Isr) & Rst) == 0 && timo; timo--)
- ;
-}
-
-int
-dp8390reset(Ether* ether)
-{
- Dp8390 *ctlr;
-
- ctlr = ether->ctlr;
-
- /*
- * This is the initialisation procedure described
- * as 'mandatory' in the datasheet, with references
- * to the 3C503 technical reference manual.
- */
- detach(ether);
- if(ctlr->width != 1)
- regw(ctlr, Dcr, Ft4WORD|Ls|Wts);
- else
- regw(ctlr, Dcr, Ft4WORD|Ls);
-
- regw(ctlr, Rbcr0, 0);
- regw(ctlr, Rbcr1, 0);
-
- regw(ctlr, Tcr, LpbkNIC);
- regw(ctlr, Rcr, Mon);
-
- /*
- * Init the ring hardware and software ring pointers.
- * Can't initialise ethernet address as it may not be
- * known yet.
- */
- ringinit(ctlr);
- regw(ctlr, Tpsr, ctlr->tstart);
-
- /*
- * Clear any pending interrupts and mask then all off.
- */
- regw(ctlr, Isr, 0xFF);
- regw(ctlr, Imr, 0);
-
- /*
- * Leave the chip initialised,
- * but in monitor mode.
- */
- regw(ctlr, Cr, Page0|RdABORT|Sta);
-
- /*
- * Set up the software configuration.
- */
- ether->attach = attach;
- ether->transmit = transmit;
- ether->interrupt = interrupt;
- ether->detach = detach;
-
- return 0;
-}
--- a/os/boot/pc/ether8390.h
+++ /dev/null
@@ -1,71 +1,0 @@
-/*
- * Ctlr for the boards using the National Semiconductor DP8390
- * and SMC 83C90 Network Interface Controller.
- * Common code is in ether8390.c.
- */
-typedef struct {
- Lock;
-
- ulong port; /* I/O address of 8390 */
- ulong data; /* I/O data port if no shared memory */
-
- uchar width; /* data transfer width in bytes */
- uchar ram; /* true if card has shared memory */
- uchar dummyrr; /* do dummy remote read */
-
- uchar nxtpkt; /* receive: software bndry */
- uchar pstart;
- uchar pstop;
-
- int txbusy; /* transmit */
- uchar tstart; /* 8390 ring addresses */
-} Dp8390;
-
-#define Dp8390BufSz 256
-
-extern int dp8390reset(Ether*);
-extern void *dp8390read(Dp8390*, void*, ulong, ulong);
-extern void dp8390getea(Ether*, uchar*);
-extern void dp8390setea(Ether*);
-
-/*
- * x86-specific code.
- */
-#define regr(c, r) inb((c)->port+(r))
-#define regw(c, r, v) outb((c)->port+(r), (v))
-
-static void
-rdread(Dp8390* ctlr, void* to, int len)
-{
- switch(ctlr->width){
- default:
- panic("dp8390 rdread: width %d\n", ctlr->width);
- break;
-
- case 2:
- inss(ctlr->data, to, len/2);
- break;
-
- case 1:
- insb(ctlr->data, to, len);
- break;
- }
-}
-
-static void
-rdwrite(Dp8390* ctlr, void* from, int len)
-{
- switch(ctlr->width){
- default:
- panic("dp8390 rdwrite: width %d\n", ctlr->width);
- break;
-
- case 2:
- outss(ctlr->data, from, len/2);
- break;
-
- case 1:
- outsb(ctlr->data, from, len);
- break;
- }
-}
--- a/os/boot/pc/etherdp83820.c
+++ /dev/null
@@ -1,1222 +1,0 @@
-/*
- * boot driver for
- * National Semiconductor DP83820
- * 10/100/1000 Mb/s Ethernet Network Interface Controller
- * (Gig-NIC).
- * Driver assumes little-endian and 32-bit host throughout.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ethermii.h"
-
-#define iprint print
-#define waserror() (0)
-#define poperror()
-
-enum { /* Registers */
- Cr = 0x00, /* Command */
- Cfg = 0x04, /* Configuration and Media Status */
- Mear = 0x08, /* MII/EEPROM Access */
- Ptscr = 0x0C, /* PCI Test Control */
- Isr = 0x10, /* Interrupt Status */
- Imr = 0x14, /* Interrupt Mask */
- Ier = 0x18, /* Interrupt Enable */
- Ihr = 0x1C, /* Interrupt Holdoff */
- Txdp = 0x20, /* Transmit Descriptor Pointer */
- Txdphi = 0x24, /* Transmit Descriptor Pointer Hi */
- Txcfg = 0x28, /* Transmit Configuration */
- Gpior = 0x2C, /* General Purpose I/O Control */
- Rxdp = 0x30, /* Receive Descriptor Pointer */
- Rxdphi = 0x34, /* Receive Descriptor Pointer Hi */
- Rxcfg = 0x38, /* Receive Configuration */
- Pqcr = 0x3C, /* Priority Queueing Control */
- Wcsr = 0x40, /* Wake on LAN Control/Status */
- Pcr = 0x44, /* Pause Control/Status */
- Rfcr = 0x48, /* Receive Filter/Match Control */
- Rfdr = 0x4C, /* Receive Filter/Match Data */
- Brar = 0x50, /* Boot ROM Address */
- Brdr = 0x54, /* Boot ROM Data */
- Srr = 0x58, /* Silicon Revision */
- Mibc = 0x5C, /* MIB Control */
- Mibd = 0x60, /* MIB Data */
- Txdp1 = 0xA0, /* Txdp Priority 1 */
- Txdp2 = 0xA4, /* Txdp Priority 2 */
- Txdp3 = 0xA8, /* Txdp Priority 3 */
- Rxdp1 = 0xB0, /* Rxdp Priority 1 */
- Rxdp2 = 0xB4, /* Rxdp Priority 2 */
- Rxdp3 = 0xB8, /* Rxdp Priority 3 */
- Vrcr = 0xBC, /* VLAN/IP Receive Control */
- Vtcr = 0xC0, /* VLAN/IP Transmit Control */
- Vdr = 0xC4, /* VLAN Data */
- Ccsr = 0xCC, /* Clockrun Control/Status */
- Tbicr = 0xE0, /* TBI Control */
- Tbisr = 0xE4, /* TBI Status */
- Tanar = 0xE8, /* TBI ANAR */
- Tanlpar = 0xEC, /* TBI ANLPAR */
- Taner = 0xF0, /* TBI ANER */
- Tesr = 0xF4, /* TBI ESR */
-};
-
-enum { /* Cr */
- Txe = 0x00000001, /* Transmit Enable */
- Txd = 0x00000002, /* Transmit Disable */
- Rxe = 0x00000004, /* Receiver Enable */
- Rxd = 0x00000008, /* Receiver Disable */
- Txr = 0x00000010, /* Transmitter Reset */
- Rxr = 0x00000020, /* Receiver Reset */
- Swien = 0x00000080, /* Software Interrupt Enable */
- Rst = 0x00000100, /* Reset */
- TxpriSHFT = 9, /* Tx Priority Queue Select */
- TxpriMASK = 0x00001E00,
- RxpriSHFT = 13, /* Rx Priority Queue Select */
- RxpriMASK = 0x0001E000,
-};
-
-enum { /* Configuration and Media Status */
- Bem = 0x00000001, /* Big Endian Mode */
- Ext125 = 0x00000002, /* External 125MHz reference Select */
- Bromdis = 0x00000004, /* Disable Boot ROM interface */
- Pesel = 0x00000008, /* Parity Error Detection Action */
- Exd = 0x00000010, /* Excessive Deferral Abort */
- Pow = 0x00000020, /* Program Out of Window Timer */
- Sb = 0x00000040, /* Single Back-off */
- Reqalg = 0x00000080, /* PCI Bus Request Algorithm */
- Extstsen = 0x00000100, /* Extended Status Enable */
- Phydis = 0x00000200, /* Disable PHY */
- Phyrst = 0x00000400, /* Reset PHY */
- M64addren = 0x00000800, /* Master 64-bit Addressing Enable */
- Data64en = 0x00001000, /* 64-bit Data Enable */
- Pci64det = 0x00002000, /* PCI 64-bit Bus Detected */
- T64addren = 0x00004000, /* Target 64-bit Addressing Enable */
- Mwidis = 0x00008000, /* MWI Disable */
- Mrmdis = 0x00010000, /* MRM Disable */
- Tmrtest = 0x00020000, /* Timer Test Mode */
- Spdstsien = 0x00040000, /* PHY Spdsts Interrupt Enable */
- Lnkstsien = 0x00080000, /* PHY Lnksts Interrupt Enable */
- Dupstsien = 0x00100000, /* PHY Dupsts Interrupt Enable */
- Mode1000 = 0x00400000, /* 1000Mb/s Mode Control */
- Tbien = 0x01000000, /* Ten-Bit Interface Enable */
- Dupsts = 0x10000000, /* Full Duplex Status */
- Spdsts100 = 0x20000000, /* SPEED100 Input Pin Status */
- Spdsts1000 = 0x40000000, /* SPEED1000 Input Pin Status */
- Lnksts = 0x80000000, /* Link Status */
-};
-
-enum { /* MII/EEPROM Access */
- Eedi = 0x00000001, /* EEPROM Data In */
- Eedo = 0x00000002, /* EEPROM Data Out */
- Eeclk = 0x00000004, /* EEPROM Serial Clock */
- Eesel = 0x00000008, /* EEPROM Chip Select */
- Mdio = 0x00000010, /* MII Management Data */
- Mddir = 0x00000020, /* MII Management Direction */
- Mdc = 0x00000040, /* MII Management Clock */
-};
-
-enum { /* Interrupts */
- Rxok = 0x00000001, /* Rx OK */
- Rxdesc = 0x00000002, /* Rx Descriptor */
- Rxerr = 0x00000004, /* Rx Packet Error */
- Rxearly = 0x00000008, /* Rx Early Threshold */
- Rxidle = 0x00000010, /* Rx Idle */
- Rxorn = 0x00000020, /* Rx Overrun */
- Txok = 0x00000040, /* Tx Packet OK */
- Txdesc = 0x00000080, /* Tx Descriptor */
- Txerr = 0x00000100, /* Tx Packet Error */
- Txidle = 0x00000200, /* Tx Idle */
- Txurn = 0x00000400, /* Tx Underrun */
- Mib = 0x00000800, /* MIB Service */
- Swi = 0x00001000, /* Software Interrupt */
- Pme = 0x00002000, /* Power Management Event */
- Phy = 0x00004000, /* PHY Interrupt */
- Hibint = 0x00008000, /* High Bits Interrupt Set */
- Rxsovr = 0x00010000, /* Rx Status FIFO Overrun */
- Rtabt = 0x00020000, /* Received Target Abort */
- Rmabt = 0x00040000, /* Received Master Abort */
- Sserr = 0x00080000, /* Signalled System Error */
- Dperr = 0x00100000, /* Detected Parity Error */
- Rxrcmp = 0x00200000, /* Receive Reset Complete */
- Txrcmp = 0x00400000, /* Transmit Reset Complete */
- Rxdesc0 = 0x00800000, /* Rx Descriptor for Priority Queue 0 */
- Rxdesc1 = 0x01000000, /* Rx Descriptor for Priority Queue 1 */
- Rxdesc2 = 0x02000000, /* Rx Descriptor for Priority Queue 2 */
- Rxdesc3 = 0x04000000, /* Rx Descriptor for Priority Queue 3 */
- Txdesc0 = 0x08000000, /* Tx Descriptor for Priority Queue 0 */
- Txdesc1 = 0x10000000, /* Tx Descriptor for Priority Queue 1 */
- Txdesc2 = 0x20000000, /* Tx Descriptor for Priority Queue 2 */
- Txdesc3 = 0x40000000, /* Tx Descriptor for Priority Queue 3 */
-};
-
-enum { /* Interrupt Enable */
- Ien = 0x00000001, /* Interrupt Enable */
-};
-
-enum { /* Interrupt Holdoff */
- IhSHFT = 0, /* Interrupt Holdoff */
- IhMASK = 0x000000FF,
- Ihctl = 0x00000100, /* Interrupt Holdoff Control */
-};
-
-enum { /* Transmit Configuration */
- TxdrthSHFT = 0, /* Tx Drain Threshold */
- TxdrthMASK = 0x000000FF,
- FlthSHFT = 16, /* Tx Fill Threshold */
- FlthMASK = 0x0000FF00,
- Brstdis = 0x00080000, /* 1000Mb/s Burst Disable */
- MxdmaSHFT = 20, /* Max Size per Tx DMA Burst */
- MxdmaMASK = 0x00700000,
- Ecretryen = 0x00800000, /* Excessive Collision Retry Enable */
- Atp = 0x10000000, /* Automatic Transmit Padding */
- Mlb = 0x20000000, /* MAC Loopback */
- Hbi = 0x40000000, /* Heartbeat Ignore */
- Csi = 0x80000000, /* Carrier Sense Ignore */
-};
-
-enum { /* Receive Configuration */
- RxdrthSHFT = 1, /* Rx Drain Threshold */
- RxdrthMASK = 0x0000003E,
- Airl = 0x04000000, /* Accept In-Range Length Errored */
- Alp = 0x08000000, /* Accept Long Packets */
- Rxfd = 0x10000000, /* Receive Full Duplex */
- Stripcrc = 0x20000000, /* Strip CRC */
- Arp = 0x40000000, /* Accept Runt Packets */
- Aep = 0x80000000, /* Accept Errored Packets */
-};
-
-enum { /* Priority Queueing Control */
- Txpqen = 0x00000001, /* Transmit Priority Queuing Enable */
- Txfairen = 0x00000002, /* Transmit Fairness Enable */
- RxpqenSHFT = 2, /* Receive Priority Queue Enable */
- RxpqenMASK = 0x0000000C,
-};
-
-enum { /* Pause Control/Status */
- PscntSHFT = 0, /* Pause Counter Value */
- PscntMASK = 0x0000FFFF,
- Pstx = 0x00020000, /* Transmit Pause Frame */
- PsffloSHFT = 18, /* Rx Data FIFO Lo Threshold */
- PsffloMASK = 0x000C0000,
- PsffhiSHFT = 20, /* Rx Data FIFO Hi Threshold */
- PsffhiMASK = 0x00300000,
- PsstloSHFT = 22, /* Rx Stat FIFO Hi Threshold */
- PsstloMASK = 0x00C00000,
- PssthiSHFT = 24, /* Rx Stat FIFO Hi Threshold */
- PssthiMASK = 0x03000000,
- Psrcvd = 0x08000000, /* Pause Frame Received */
- Psact = 0x10000000, /* Pause Active */
- Psda = 0x20000000, /* Pause on Destination Address */
- Psmcast = 0x40000000, /* Pause on Multicast */
- Psen = 0x80000000, /* Pause Enable */
-};
-
-enum { /* Receive Filter/Match Control */
- RfaddrSHFT = 0, /* Extended Register Address */
- RfaddrMASK = 0x000003FF,
- Ulm = 0x00080000, /* U/L bit mask */
- Uhen = 0x00100000, /* Unicast Hash Enable */
- Mhen = 0x00200000, /* Multicast Hash Enable */
- Aarp = 0x00400000, /* Accept ARP Packets */
- ApatSHFT = 23, /* Accept on Pattern Match */
- ApatMASK = 0x07800000,
- Apm = 0x08000000, /* Accept on Perfect Match */
- Aau = 0x10000000, /* Accept All Unicast */
- Aam = 0x20000000, /* Accept All Multicast */
- Aab = 0x40000000, /* Accept All Broadcast */
- Rfen = 0x80000000, /* Rx Filter Enable */
-};
-
-enum { /* Receive Filter/Match Data */
- RfdataSHFT = 0, /* Receive Filter Data */
- RfdataMASK = 0x0000FFFF,
- BmaskSHFT = 16, /* Byte Mask */
- BmaskMASK = 0x00030000,
-};
-
-enum { /* MIB Control */
- Wrn = 0x00000001, /* Warning Test Indicator */
- Frz = 0x00000002, /* Freeze All Counters */
- Aclr = 0x00000004, /* Clear All Counters */
- Mibs = 0x00000008, /* MIB Counter Strobe */
-};
-
-enum { /* MIB Data */
- Nmibd = 11, /* Number of MIB Data Registers */
-};
-
-enum { /* VLAN/IP Receive Control */
- Vtden = 0x00000001, /* VLAN Tag Detection Enable */
- Vtren = 0x00000002, /* VLAN Tag Removal Enable */
- Dvtf = 0x00000004, /* Discard VLAN Tagged Frames */
- Dutf = 0x00000008, /* Discard Untagged Frames */
- Ipen = 0x00000010, /* IP Checksum Enable */
- Ripe = 0x00000020, /* Reject IP Checksum Errors */
- Rtcpe = 0x00000040, /* Reject TCP Checksum Errors */
- Rudpe = 0x00000080, /* Reject UDP Checksum Errors */
-};
-
-enum { /* VLAN/IP Transmit Control */
- Vgti = 0x00000001, /* VLAN Global Tag Insertion */
- Vppti = 0x00000002, /* VLAN Per-Packet Tag Insertion */
- Gchk = 0x00000004, /* Global Checksum Generation */
- Ppchk = 0x00000008, /* Per-Packet Checksum Generation */
-};
-
-enum { /* VLAN Data */
- VtypeSHFT = 0, /* VLAN Type Field */
- VtypeMASK = 0x0000FFFF,
- VtciSHFT = 16, /* VLAN Tag Control Information */
- VtciMASK = 0xFFFF0000,
-};
-
-enum { /* Clockrun Control/Status */
- Clkrunen = 0x00000001, /* CLKRUN Enable */
- Pmeen = 0x00000100, /* PME Enable */
- Pmests = 0x00008000, /* PME Status */
-};
-
-typedef struct {
- u32 link; /* Link to the next descriptor */
- u32 bufptr; /* pointer to data Buffer */
- int cmdsts; /* Command/Status */
- int extsts; /* optional Extended Status */
-
- Block* bp; /* Block containing bufptr */
- u32 unused; /* pad to 64-bit */
-} Desc;
-
-enum { /* Common cmdsts bits */
- SizeMASK = 0x0000FFFF, /* Descriptor Byte Count */
- SizeSHFT = 0,
- Ok = 0x08000000, /* Packet OK */
- Crc = 0x10000000, /* Suppress/Include CRC */
- Intr = 0x20000000, /* Interrupt on ownership transfer */
- More = 0x40000000, /* not last descriptor in a packet */
- Own = 0x80000000, /* Descriptor Ownership */
-};
-
-enum { /* Transmit cmdsts bits */
- CcntMASK = 0x000F0000, /* Collision Count */
- CcntSHFT = 16,
- Ec = 0x00100000, /* Excessive Collisions */
- Owc = 0x00200000, /* Out of Window Collision */
- Ed = 0x00400000, /* Excessive Deferral */
- Td = 0x00800000, /* Transmit Deferred */
- Crs = 0x01000000, /* Carrier Sense Lost */
- Tfu = 0x02000000, /* Transmit FIFO Underrun */
- Txa = 0x04000000, /* Transmit Abort */
-};
-
-enum { /* Receive cmdsts bits */
- Irl = 0x00010000, /* In-Range Length Error */
- Lbp = 0x00020000, /* Loopback Packet */
- Fae = 0x00040000, /* Frame Alignment Error */
- Crce = 0x00080000, /* CRC Error */
- Ise = 0x00100000, /* Invalid Symbol Error */
- Runt = 0x00200000, /* Runt Packet Received */
- Long = 0x00400000, /* Too Long Packet Received */
- DestMASK = 0x01800000, /* Destination Class */
- DestSHFT = 23,
- Rxo = 0x02000000, /* Receive Overrun */
- Rxa = 0x04000000, /* Receive Aborted */
-};
-
-enum { /* extsts bits */
- EvtciMASK = 0x0000FFFF, /* VLAN Tag Control Information */
- EvtciSHFT = 0,
- Vpkt = 0x00010000, /* VLAN Packet */
- Ippkt = 0x00020000, /* IP Packet */
- Iperr = 0x00040000, /* IP Checksum Error */
- Tcppkt = 0x00080000, /* TCP Packet */
- Tcperr = 0x00100000, /* TCP Checksum Error */
- Udppkt = 0x00200000, /* UDP Packet */
- Udperr = 0x00400000, /* UDP Checksum Error */
-};
-
-enum {
- Nrd = 32, /* was 256 */
- Nrbf = 4*Nrd,
- Rbsz = ROUNDUP(sizeof(Etherpkt)+8, 8),
- Ntd = 8, /* was 128 */
-};
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
- int port;
- Pcidev* pcidev;
- Ctlr* next;
- int active;
- int id;
-
- int eepromsz; /* address size in bits */
- ushort* eeprom;
-
- int* nic;
- int cfg;
- int imr;
-
- Lock alock; /* attach */
- Lock ilock; /* init */
- void* alloc; /* base of per-Ctlr allocated data */
-
- Mii* mii;
-
- Lock rdlock; /* receive */
- Desc* rd;
- int nrd;
- int nrb;
- int rdx;
- int rxcfg;
-
- Lock tlock; /* transmit */
- Desc* td;
- int ntd;
- int tdh;
- int tdt;
- int ntq;
- int txcfg;
-
- int rxidle;
-
- uint mibd[Nmibd];
-
- int ec;
- int owc;
- int ed;
- int crs;
- int tfu;
- int txa;
-};
-
-#define csr32r(c, r) (*((c)->nic+((r)/4)))
-#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
-
-static Ctlr* dp83820ctlrhead;
-static Ctlr* dp83820ctlrtail;
-
-static Lock dp83820rblock; /* free receive Blocks */
-static Block* dp83820rbpool;
-
-static char* dp83820mibs[Nmibd] = {
- "RXErroredPkts",
- "RXFCSErrors",
- "RXMsdPktErrors",
- "RXFAErrors",
- "RXSymbolErrors",
- "RXFrameToLong",
- "RXIRLErrors",
- "RXBadOpcodes",
- "RXPauseFrames",
- "TXPauseFrames",
- "TXSQEErrors",
-};
-
-static int
-mdior(Ctlr* ctlr, int n)
-{
- int data, i, mear, r;
-
- mear = csr32r(ctlr, Mear);
- r = ~(Mdc|Mddir) & mear;
- data = 0;
- for(i = n-1; i >= 0; i--){
- if(csr32r(ctlr, Mear) & Mdio)
- data |= (1<<i);
- csr32w(ctlr, Mear, Mdc|r);
- csr32w(ctlr, Mear, r);
- }
- csr32w(ctlr, Mear, mear);
-
- return data;
-}
-
-static void
-mdiow(Ctlr* ctlr, int bits, int n)
-{
- int i, mear, r;
-
- mear = csr32r(ctlr, Mear);
- r = Mddir|(~Mdc & mear);
- for(i = n-1; i >= 0; i--){
- if(bits & (1<<i))
- r |= Mdio;
- else
- r &= ~Mdio;
- csr32w(ctlr, Mear, r);
- csr32w(ctlr, Mear, Mdc|r);
- }
- csr32w(ctlr, Mear, mear);
-}
-
-static int
-dp83820miimir(Mii* mii, int pa, int ra)
-{
- int data;
- Ctlr *ctlr;
-
- ctlr = mii->ctlr;
-
- /*
- * MII Management Interface Read.
- *
- * Preamble;
- * ST+OP+PA+RA;
- * LT + 16 data bits.
- */
- mdiow(ctlr, 0xFFFFFFFF, 32);
- mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
- data = mdior(ctlr, 18);
-
- if(data & 0x10000)
- return -1;
-
- return data & 0xFFFF;
-}
-
-static int
-dp83820miimiw(Mii* mii, int pa, int ra, int data)
-{
- Ctlr *ctlr;
-
- ctlr = mii->ctlr;
-
- /*
- * MII Management Interface Write.
- *
- * Preamble;
- * ST+OP+PA+RA+LT + 16 data bits;
- * Z.
- */
- mdiow(ctlr, 0xFFFFFFFF, 32);
- data &= 0xFFFF;
- data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
- mdiow(ctlr, data, 32);
-
- return 0;
-}
-
-static Block *
-dp83820rballoc(Desc* desc)
-{
- Block *bp;
-
- if(desc->bp == nil){
- ilock(&dp83820rblock);
- if((bp = dp83820rbpool) == nil){
- iunlock(&dp83820rblock);
- desc->bp = nil;
- desc->cmdsts = Own;
- return nil;
- }
- dp83820rbpool = bp->next;
- bp->next = nil;
- iunlock(&dp83820rblock);
-
- desc->bufptr = PCIWADDR(bp->rp);
- desc->bp = bp;
- }
- else{
- bp = desc->bp;
- bp->rp = bp->lim - Rbsz;
- bp->wp = bp->rp;
- }
-
- coherence();
- desc->cmdsts = Intr|Rbsz;
-
- return bp;
-}
-
-static void
-dp83820rbfree(Block *bp)
-{
- bp->rp = bp->lim - Rbsz;
- bp->wp = bp->rp;
-
- ilock(&dp83820rblock);
- bp->next = dp83820rbpool;
- dp83820rbpool = bp;
- iunlock(&dp83820rblock);
-}
-
-static void
-dp83820halt(Ctlr* ctlr)
-{
- int i, timeo;
-
- ilock(&ctlr->ilock);
- csr32w(ctlr, Imr, 0);
- csr32w(ctlr, Ier, 0);
- csr32w(ctlr, Cr, Rxd|Txd);
- for(timeo = 0; timeo < 1000; timeo++){
- if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
- break;
- microdelay(1);
- }
- csr32w(ctlr, Mibc, Frz);
- iunlock(&ctlr->ilock);
-
- if(ctlr->rd != nil){
- for(i = 0; i < ctlr->nrd; i++){
- if(ctlr->rd[i].bp == nil)
- continue;
- freeb(ctlr->rd[i].bp);
- ctlr->rd[i].bp = nil;
- }
- }
- if(ctlr->td != nil){
- for(i = 0; i < ctlr->ntd; i++){
- if(ctlr->td[i].bp == nil)
- continue;
- freeb(ctlr->td[i].bp);
- ctlr->td[i].bp = nil;
- }
- }
-}
-
-static void
-dp83820cfg(Ctlr* ctlr)
-{
- int cfg;
-
- /*
- * Don't know how to deal with a TBI yet.
- */
- if(ctlr->mii == nil)
- return;
-
- /*
- * The polarity of these bits is at the mercy
- * of the board designer.
- * The correct answer for all speed and duplex questions
- * should be to query the phy.
- */
- cfg = csr32r(ctlr, Cfg);
- if(!(cfg & Dupsts)){
- ctlr->rxcfg |= Rxfd;
- ctlr->txcfg |= Csi|Hbi;
- iprint("83820: full duplex, ");
- }
- else{
- ctlr->rxcfg &= ~Rxfd;
- ctlr->txcfg &= ~(Csi|Hbi);
- iprint("83820: half duplex, ");
- }
- csr32w(ctlr, Rxcfg, ctlr->rxcfg);
- csr32w(ctlr, Txcfg, ctlr->txcfg);
-
- switch(cfg & (Spdsts1000|Spdsts100)){
- case Spdsts1000: /* 100Mbps */
- default: /* 10Mbps */
- ctlr->cfg &= ~Mode1000;
- if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
- iprint("100Mb/s\n");
- else
- iprint("10Mb/s\n");
- break;
- case Spdsts100: /* 1Gbps */
- ctlr->cfg |= Mode1000;
- iprint("1Gb/s\n");
- break;
- }
- csr32w(ctlr, Cfg, ctlr->cfg);
-}
-
-static void
-dp83820init(Ether* edev)
-{
- int i;
- Ctlr *ctlr;
- Desc *desc;
- uchar *alloc;
-
- ctlr = edev->ctlr;
-
- dp83820halt(ctlr);
-
- /*
- * Receiver
- */
- alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
- ctlr->rd = (Desc*)alloc;
- alloc += ctlr->nrd*sizeof(Desc);
- memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
- ctlr->rdx = 0;
- for(i = 0; i < ctlr->nrd; i++){
- desc = &ctlr->rd[i];
- desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
- if(dp83820rballoc(desc) == nil)
- continue;
- }
- csr32w(ctlr, Rxdphi, 0);
- csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
-
- for(i = 0; i < Eaddrlen; i += 2){
- csr32w(ctlr, Rfcr, i);
- csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
- }
- csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
-
- ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
- ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
-
- /*
- * Transmitter.
- */
- ctlr->td = (Desc*)alloc;
- memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
- ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
- for(i = 0; i < ctlr->ntd; i++){
- desc = &ctlr->td[i];
- desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
- }
- csr32w(ctlr, Txdphi, 0);
- csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
-
- ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
- ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
-
- ilock(&ctlr->ilock);
-
- dp83820cfg(ctlr);
-
- csr32w(ctlr, Mibc, Aclr);
- ctlr->imr |= Mib;
-
- csr32w(ctlr, Imr, ctlr->imr);
-
- /* try coalescing adjacent interrupts; use hold-off interval of 100µs */
- csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
-
- csr32w(ctlr, Ier, Ien);
- csr32w(ctlr, Cr, Rxe|Txe);
-
- iunlock(&ctlr->ilock);
-}
-
-static void
-dp83820attach(Ether* edev)
-{
- Block *bp;
- Ctlr *ctlr;
-
- ctlr = edev->ctlr;
- lock(&ctlr->alock);
- if(ctlr->alloc != nil){
- unlock(&ctlr->alock);
- return;
- }
-
- if(waserror()){
-err:
- if(ctlr->mii != nil){
- free(ctlr->mii);
- ctlr->mii = nil;
- }
- if(ctlr->alloc != nil){
- free(ctlr->alloc);
- ctlr->alloc = nil;
- }
- unlock(&ctlr->alock);
- return;
- }
-
- if(!(ctlr->cfg & Tbien)){
- if((ctlr->mii = malloc(sizeof(Mii))) == nil)
- goto err;
- ctlr->mii->ctlr = ctlr;
- ctlr->mii->mir = dp83820miimir;
- ctlr->mii->miw = dp83820miimiw;
- if(mii(ctlr->mii, ~0) == 0)
- goto err;
- ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
- ctlr->imr |= Phy;
- }
-
- ctlr->nrd = Nrd;
- ctlr->nrb = Nrbf;
- ctlr->ntd = Ntd;
- ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
- if(ctlr->alloc == nil)
- goto err;
-
- /*
- * the Bill Paul bsd drivers claim that receive buffers must be aligned
- * on 8-byte boundaries.
- */
- for(ctlr->nrb = 0; ctlr->nrb < Nrbf; ctlr->nrb++){
- if((bp = allocb(Rbsz+8-1)) == nil)
- break;
- bp->rp += 8 - (uintptr)bp->rp % 8;
- bp->wp = bp->rp;
-// bp->free = dp83820rbfree; /* TODO: fix */
- dp83820rbfree(bp);
- }
-
- dp83820init(edev);
-
- unlock(&ctlr->alock);
- poperror();
-}
-
-/*
- * free a list of blocks
- */
-static void
-freeblist(Block *b)
-{
- Block *next;
-
- for(; b != 0; b = next){
- next = b->next;
- b->next = 0;
- freeb(b);
- }
-}
-
-static void
-toringbuf(Ether *ether, Block *bp)
-{
- RingBuf *rb = ðer->rb[ether->ri];
-
- if (rb->owner == Interface) {
- rb->len = BLEN(bp);
- memmove(rb->pkt, bp->rp, rb->len);
- rb->owner = Host;
- ether->ri = NEXT(ether->ri, ether->nrb);
- }
- /* else no one is expecting packets from the network */
-}
-
-static Block *
-fromringbuf(Ether *ether)
-{
- RingBuf *tb = ðer->tb[ether->ti];
- Block *bp = allocb(tb->len);
-
- memmove(bp->wp, tb->pkt, tb->len);
- memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
- bp->wp += tb->len;
- return bp;
-}
-
-static void
-dp83820transmit(Ether* edev)
-{
- Block *bp;
- Ctlr *ctlr;
- Desc *desc;
- RingBuf *tb;
- int cmdsts, r, x;
-
- ctlr = edev->ctlr;
-
- ilock(&ctlr->tlock);
-
- bp = nil;
- for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
- desc = &ctlr->td[x];
- if((cmdsts = desc->cmdsts) & Own)
- break;
- if(!(cmdsts & Ok)){
- if(cmdsts & Ec)
- ctlr->ec++;
- if(cmdsts & Owc)
- ctlr->owc++;
- if(cmdsts & Ed)
- ctlr->ed++;
- if(cmdsts & Crs)
- ctlr->crs++;
- if(cmdsts & Tfu)
- ctlr->tfu++;
- if(cmdsts & Txa)
- ctlr->txa++;
- }
- desc->bp->next = bp;
- bp = desc->bp;
- desc->bp = nil;
-
- ctlr->ntq--;
- }
- ctlr->tdh = x;
- if(bp != nil)
- freeblist(bp);
-
- x = ctlr->tdt;
-// tb = &edev->tb[edev->ti];
- while(ctlr->ntq < ctlr->ntd - 1 /* && tb->owner == Interface */ ){
- bp = fromringbuf(edev);
- if (bp == nil)
- break;
-
- /* transmit packet from bp */
- desc = &ctlr->td[x];
- desc->bufptr = PCIWADDR(bp->rp);
- desc->bp = bp;
- ctlr->ntq++;
- coherence();
- desc->cmdsts = Own|Intr|BLEN(bp); /* kick transmitter */
-//print("t");
- tb = &edev->tb[edev->ti];
- tb->owner = Host; /* give descriptor back */
- edev->ti = NEXT(edev->ti, edev->ntb);
-
- x = NEXT(x, ctlr->ntd);
- }
- if(x != ctlr->tdt){
- ctlr->tdt = x;
- r = csr32r(ctlr, Cr);
- csr32w(ctlr, Cr, Txe|r);
- }
-
- iunlock(&ctlr->tlock);
-}
-
-static void
-dp83820interrupt(Ureg*, void* arg)
-{
- Block *bp;
- Ctlr *ctlr;
- Desc *desc;
- Ether *edev;
- int cmdsts, i, isr, r, x;
-
- edev = arg;
- ctlr = edev->ctlr;
-
- for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
- if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
- x = ctlr->rdx;
- desc = &ctlr->rd[x];
- while((cmdsts = desc->cmdsts) & Own){
- if((cmdsts & Ok) && desc->bp != nil){
- /* receive a packet into desc->bp */
- bp = desc->bp;
- desc->bp = nil;
- // bp->rp = desc->bufptr;
- bp->wp += cmdsts & SizeMASK;
-
- toringbuf(edev, bp);
-//print("r");
- }
- dp83820rballoc(desc);
-
- x = NEXT(x, ctlr->nrd);
- desc = &ctlr->rd[x];
- }
- ctlr->rdx = x;
-
- if(isr & Rxidle){
- r = csr32r(ctlr, Cr);
- csr32w(ctlr, Cr, Rxe|r);
- ctlr->rxidle++;
- }
-
- isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
- }
-
- if(isr & Txurn){
- x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
- r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
- if(x < ((TxdrthMASK)>>TxdrthSHFT)
- && x < (2048/32 - r)){
- ctlr->txcfg &= ~TxdrthMASK;
- x++;
- ctlr->txcfg |= x<<TxdrthSHFT;
- csr32w(ctlr, Txcfg, ctlr->txcfg);
- }
- }
-
- if(isr & (Txurn|Txidle|Txdesc|Txok)){
- dp83820transmit(edev);
- isr &= ~(Txurn|Txidle|Txdesc|Txok);
- }
-
- if(isr & Mib){
- for(i = 0; i < Nmibd; i++){
- r = csr32r(ctlr, Mibd+(i*sizeof(int)));
- ctlr->mibd[i] += r & 0xFFFF;
- }
- isr &= ~Mib;
- }
-
- if((isr & Phy) && ctlr->mii != nil){
- ctlr->mii->mir(ctlr->mii, 1, Bmsr);
- print("phy: cfg %8.8uX bmsr %4.4uX\n",
- csr32r(ctlr, Cfg),
- ctlr->mii->mir(ctlr->mii, 1, Bmsr));
- dp83820cfg(ctlr);
- isr &= ~Phy;
- }
-// TODO fix if(isr)
-// TODO fix iprint("dp83820: isr %8.8uX\n", isr);
- USED(isr);
- }
-}
-
-static int
-dp83820detach(Ctlr* ctlr)
-{
- /*
- * Soft reset the controller.
- */
- csr32w(ctlr, Cr, Rst);
- delay(1);
- while(csr32r(ctlr, Cr) & Rst)
- delay(1);
- return 0;
-}
-
-static void
-dp83820shutdown(Ether* ether)
-{
-print("dp83820shutdown\n");
- dp83820detach(ether->ctlr);
-}
-
-static int
-atc93c46r(Ctlr* ctlr, int address)
-{
- int data, i, mear, r, size;
-
- /*
- * Analog Technology, Inc. ATC93C46
- * or equivalent serial EEPROM.
- */
- mear = csr32r(ctlr, Mear);
- mear &= ~(Eesel|Eeclk|Eedo|Eedi);
- r = Eesel|mear;
-
-reread:
- csr32w(ctlr, Mear, r);
- data = 0x06;
- for(i = 3-1; i >= 0; i--){
- if(data & (1<<i))
- r |= Eedi;
- else
- r &= ~Eedi;
- csr32w(ctlr, Mear, r);
- csr32w(ctlr, Mear, Eeclk|r);
- microdelay(1);
- csr32w(ctlr, Mear, r);
- microdelay(1);
- }
-
- /*
- * First time through must work out the EEPROM size.
- */
- if((size = ctlr->eepromsz) == 0)
- size = 8;
-
- for(size = size-1; size >= 0; size--){
- if(address & (1<<size))
- r |= Eedi;
- else
- r &= ~Eedi;
- csr32w(ctlr, Mear, r);
- microdelay(1);
- csr32w(ctlr, Mear, Eeclk|r);
- microdelay(1);
- csr32w(ctlr, Mear, r);
- microdelay(1);
- if(!(csr32r(ctlr, Mear) & Eedo))
- break;
- }
- r &= ~Eedi;
-
- data = 0;
- for(i = 16-1; i >= 0; i--){
- csr32w(ctlr, Mear, Eeclk|r);
- microdelay(1);
- if(csr32r(ctlr, Mear) & Eedo)
- data |= (1<<i);
- csr32w(ctlr, Mear, r);
- microdelay(1);
- }
-
- csr32w(ctlr, Mear, mear);
-
- if(ctlr->eepromsz == 0){
- ctlr->eepromsz = 8-size;
- ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
- goto reread;
- }
-
- return data;
-}
-
-static int
-dp83820reset(Ctlr* ctlr)
-{
- int i, r;
- unsigned char sum;
-
- /*
- * Soft reset the controller;
- * read the EEPROM to get the initial settings
- * of the Cfg and Gpior bits which should be cleared by
- * the reset.
- */
- csr32w(ctlr, Cr, Rst);
- delay(1);
- while(csr32r(ctlr, Cr) & Rst)
- delay(1);
-
- atc93c46r(ctlr, 0);
- if(ctlr->eeprom == nil) {
- print("dp83820reset: no eeprom\n");
- return -1;
- }
- sum = 0;
- for(i = 0; i < 0x0E; i++){
- r = atc93c46r(ctlr, i);
- ctlr->eeprom[i] = r;
- sum += r;
- sum += r>>8;
- }
-
- if(sum != 0){
- print("dp83820reset: bad EEPROM checksum\n");
- return -1;
- }
-
-#ifdef notdef
- csr32w(ctlr, Gpior, ctlr->eeprom[4]);
-
- cfg = Extstsen|Exd;
- r = csr32r(ctlr, Cfg);
- if(ctlr->eeprom[5] & 0x0001)
- cfg |= Ext125;
- if(ctlr->eeprom[5] & 0x0002)
- cfg |= M64addren;
- if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
- cfg |= Data64en;
- if(ctlr->eeprom[5] & 0x0008)
- cfg |= T64addren;
- if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
- cfg |= Mwidis;
- if(ctlr->eeprom[5] & 0x0020)
- cfg |= Mrmdis;
- if(ctlr->eeprom[5] & 0x0080)
- cfg |= Mode1000;
- if(ctlr->eeprom[5] & 0x0200)
- cfg |= Tbien|Mode1000;
- /*
- * What about RO bits we might have destroyed with Rst?
- * What about Exd, Tmrtest, Extstsen, Pintctl?
- * Why does it think it has detected a 64-bit bus when
- * it hasn't?
- */
-#else
- //r = csr32r(ctlr, Cfg);
- //r &= ~(Mode1000|T64addren|Data64en|M64addren);
- //csr32w(ctlr, Cfg, r);
- //csr32w(ctlr, Cfg, 0x2000);
-#endif /* notdef */
- ctlr->cfg = csr32r(ctlr, Cfg);
-print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
- ctlr->cfg &= ~(T64addren|Data64en|M64addren);
- csr32w(ctlr, Cfg, ctlr->cfg);
- csr32w(ctlr, Mibc, Aclr|Frz);
-
- return 0;
-}
-
-static void
-dp83820pci(void)
-{
- int port;
- Pcidev *p;
- Ctlr *ctlr;
-
- p = nil;
- while(p = pcimatch(p, 0, 0)){
- if(p->ccrb != 0x02 || p->ccru != 0)
- continue;
-
- switch((p->did<<16)|p->vid){
- default:
- continue;
- case (0x0022<<16)|0x100B: /* DP83820 (Gig-NIC) */
- break;
- }
-
- port = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0);
- if(port == 0){
- print("dp83820: can't map %d @ 0x%8.8luX\n",
- p->mem[1].size, p->mem[1].bar);
- continue;
- }
-
- ctlr = malloc(sizeof(Ctlr));
- ctlr->port = port;
- ctlr->pcidev = p;
- ctlr->id = p->did<<16 | p->vid;
-
- ctlr->nic = KADDR(ctlr->port);
- if(dp83820reset(ctlr)){
- free(ctlr);
- continue;
- }
- pcisetbme(p);
-
- if(dp83820ctlrhead != nil)
- dp83820ctlrtail->next = ctlr;
- else
- dp83820ctlrhead = ctlr;
- dp83820ctlrtail = ctlr;
- }
-}
-
-int
-dp83820pnp(Ether* edev)
-{
- int i;
- Ctlr *ctlr;
- uchar ea[Eaddrlen];
-
- if(dp83820ctlrhead == nil)
- dp83820pci();
-
- /*
- * Any adapter matches if no edev->port is supplied,
- * otherwise the ports must match.
- */
- for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
- if(ctlr->active)
- continue;
- if(edev->port == 0 || edev->port == ctlr->port){
- ctlr->active = 1;
- break;
- }
- }
- if(ctlr == nil)
- return -1;
-
- edev->ctlr = ctlr;
- edev->port = ctlr->port;
- edev->irq = ctlr->pcidev->intl;
- edev->tbdf = ctlr->pcidev->tbdf;
-
- /*
- * Check if the adapter's station address is to be overridden.
- * If not, read it from the EEPROM and set in ether->ea prior to
- * loading the station address in the hardware.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, edev->ea, Eaddrlen) == 0)
- for(i = 0; i < Eaddrlen/2; i++){
- edev->ea[2*i] = ctlr->eeprom[0x0C-i];
- edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
- }
-
- edev->attach = dp83820attach;
- edev->transmit = dp83820transmit;
- edev->interrupt = dp83820interrupt;
- edev->detach = dp83820shutdown;
- return 0;
-}
--- a/os/boot/pc/etherec2t.c
+++ /dev/null
@@ -1,155 +1,0 @@
-/*
- * Supposed NE2000 PCMCIA clones, see the comments in ether2000.c
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ether8390.h"
-
-enum {
- Data = 0x10, /* offset from I/O base of data port */
- Reset = 0x1F, /* offset from I/O base of reset port */
-};
-
-static char* ec2tpcmcia[] = {
- "EC2T", /* Linksys Combo PCMCIA EthernetCard */
- "PCMPC100", /* EtherFast 10/100 PC Card */
- "EN2216", /* Accton EtherPair-PCMCIA */
- "FA410TX", /* Netgear FA410TX */
- "Network Everywhere", /* Linksys NP10T 10BaseT Card */
- nil,
-};
-
-int
-ec2treset(Ether* ether)
-{
- ushort buf[16];
- ulong port;
- Dp8390 *ctlr;
- int i, slot;
- uchar ea[Eaddrlen], sum, x;
- char *type;
-
- /*
- * Set up the software configuration.
- * Use defaults for port, irq, mem and size
- * if not specified.
- * The manual says 16KB memory, the box
- * says 32KB. The manual seems to be correct.
- */
- if(ether->port == 0)
- ether->port = 0x300;
- if(ether->irq == 0)
- ether->irq = 9;
- if(ether->mem == 0)
- ether->mem = 0x4000;
- if(ether->size == 0)
- ether->size = 16*1024;
- port = ether->port;
-
- //if(ioalloc(ether->port, 0x20, 0, "ec2t") < 0)
- // return -1;
- slot = -1;
- type = nil;
- for(i = 0; ec2tpcmcia[i] != nil; i++){
- type = ec2tpcmcia[i];
- if((slot = pcmspecial(type, ether)) >= 0)
- break;
- }
- if(ec2tpcmcia[i] == nil){
- for(i = 0; i < ether->nopt; i++){
- if(cistrncmp(ether->opt[i], "id=", 3))
- continue;
- type = ðer->opt[i][3];
- if((slot = pcmspecial(type, ether)) >= 0)
- break;
- }
- }
- if(slot < 0){
- // iofree(port);
- return -1;
- }
-
- ether->ctlr = malloc(sizeof(Dp8390));
- ctlr = ether->ctlr;
- ctlr->width = 2;
- ctlr->ram = 0;
-
- ctlr->port = port;
- ctlr->data = port+Data;
-
- ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz);
- ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
- ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz);
-
- ctlr->dummyrr = 0;
- for(i = 0; i < ether->nopt; i++){
- if(cistrcmp(ether->opt[i], "nodummyrr") == 0)
- ctlr->dummyrr = 0;
- else if(cistrncmp(ether->opt[i], "dummyrr=", 8) == 0)
- ctlr->dummyrr = strtol(ðer->opt[i][8], nil, 0);
- }
-
- /*
- * Reset the board. This is done by doing a read
- * followed by a write to the Reset address.
- */
- buf[0] = inb(port+Reset);
- delay(2);
- outb(port+Reset, buf[0]);
- delay(2);
-
- /*
- * Init the (possible) chip, then use the (possible)
- * chip to read the (possible) PROM for ethernet address
- * and a marker byte.
- * Could just look at the DP8390 command register after
- * initialisation has been tried, but that wouldn't be
- * enough, there are other ethernet boards which could
- * match.
- */
- dp8390reset(ether);
- sum = 0;
- if(cistrcmp(type, "PCMPC100") == 0 || cistrcmp(type, "FA410TX") == 0){
- /*
- * The PCMPC100 has the ethernet address in I/O space.
- * There's a checksum over 8 bytes which sums to 0xFF.
- */
- for(i = 0; i < 8; i++){
- x = inb(port+0x14+i);
- sum += x;
- buf[i] = (x<<8)|x;
- }
- }
- else{
- memset(buf, 0, sizeof(buf));
- dp8390read(ctlr, buf, 0, sizeof(buf));
- if((buf[0x0E] & 0xFF) == 0x57 && (buf[0x0F] & 0xFF) == 0x57)
- sum = 0xFF;
- }
- if(sum != 0xFF){
- pcmspecialclose(slot);
- //iofree(ether->port);
- free(ether->ctlr);
- return -1;
- }
-
- /*
- * Stupid machine. Shorts were asked for,
- * shorts were delivered, although the PROM is a byte array.
- * Set the ethernet address.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, ether->ea, Eaddrlen) == 0){
- for(i = 0; i < sizeof(ether->ea); i++)
- ether->ea[i] = buf[i];
- }
- dp8390setea(ether);
-
- return 0;
-}
--- a/os/boot/pc/etherelnk3.c
+++ /dev/null
@@ -1,1897 +1,0 @@
-/*
- * Etherlink III, Fast EtherLink and Fast EtherLink XL adapters.
- * To do:
- * check robustness in the face of errors (e.g. busmaster & rxUnderrun);
- * RxEarly and busmaster;
- * autoSelect;
- * PCI latency timer and master enable;
- * errata list;
- * rewrite all initialisation.
- *
- * Product ID:
- * 9150 ISA 3C509[B]
- * 9050 ISA 3C509[B]-TP
- * 9450 ISA 3C509[B]-COMBO
- * 9550 ISA 3C509[B]-TPO
- *
- * 9350 EISA 3C579
- * 9250 EISA 3C579-TP
- *
- * 5920 EISA 3C592-[TP|COMBO|TPO]
- * 5970 EISA 3C597-TX Fast Etherlink 10BASE-T/100BASE-TX
- * 5971 EISA 3C597-T4 Fast Etherlink 10BASE-T/100BASE-T4
- * 5972 EISA 3C597-MII Fast Etherlink 10BASE-T/MII
- *
- * 5900 PCI 3C590-[TP|COMBO|TPO]
- * 5950 PCI 3C595-TX Fast Etherlink Shared 10BASE-T/100BASE-TX
- * 5951 PCI 3C595-T4 Fast Etherlink Shared 10BASE-T/100BASE-T4
- * 5952 PCI 3C595-MII Fast Etherlink 10BASE-T/MII
- *
- * 9000 PCI 3C900-TPO Etherlink III XL PCI 10BASE-T
- * 9001 PCI 3C900-COMBO Etherlink III XL PCI 10BASE-T/10BASE-2/AUI
- * 9005 PCI 3C900B-COMBO Etherlink III XL PCI 10BASE-T/10BASE-2/AUI
- * 9050 PCI 3C905-TX Fast Etherlink XL Shared 10BASE-T/100BASE-TX
- * 9051 PCI 3C905-T4 Fast Etherlink Shared 10BASE-T/100BASE-T4
- * 9055 PCI 3C905B-TX Fast Etherlink Shared 10BASE-T/100BASE-TX
- * 9200 PCI 3C905C-TX Fast Etherlink Shared 10BASE-T/100BASE-TX
- *
- * 9058 PCMCIA 3C589[B]-[TP|COMBO]
- *
- * 627C MCA 3C529
- * 627D MCA 3C529-TP
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-#define XCVRDEBUG if(0)print
-
-enum {
- IDport = 0x0110, /* anywhere between 0x0100 and 0x01F0 */
-};
-
-enum { /* all windows */
- CommandR = 0x000E,
- IntStatusR = 0x000E,
-};
-
-enum { /* Commands */
- GlobalReset = 0x0000,
- SelectRegisterWindow = 0x0001,
- EnableDcConverter = 0x0002,
- RxDisable = 0x0003,
- RxEnable = 0x0004,
- RxReset = 0x0005,
- Stall = 0x0006, /* 3C90x */
- TxDone = 0x0007,
- RxDiscard = 0x0008,
- TxEnable = 0x0009,
- TxDisable = 0x000A,
- TxReset = 0x000B,
- RequestInterrupt = 0x000C,
- AcknowledgeInterrupt = 0x000D,
- SetInterruptEnable = 0x000E,
- SetIndicationEnable = 0x000F, /* SetReadZeroMask */
- SetRxFilter = 0x0010,
- SetRxEarlyThresh = 0x0011,
- SetTxAvailableThresh = 0x0012,
- SetTxStartThresh = 0x0013,
- StartDma = 0x0014, /* initiate busmaster operation */
- StatisticsEnable = 0x0015,
- StatisticsDisable = 0x0016,
- DisableDcConverter = 0x0017,
- SetTxReclaimThresh = 0x0018, /* PIO-only adapters */
- PowerUp = 0x001B, /* not all adapters */
- PowerDownFull = 0x001C, /* not all adapters */
- PowerAuto = 0x001D, /* not all adapters */
-};
-
-enum { /* (Global|Rx|Tx)Reset command bits */
- tpAuiReset = 0x0001, /* 10BaseT and AUI transceivers */
- endecReset = 0x0002, /* internal Ethernet encoder/decoder */
- networkReset = 0x0004, /* network interface logic */
- fifoReset = 0x0008, /* FIFO control logic */
- aismReset = 0x0010, /* autoinitialise state-machine logic */
- hostReset = 0x0020, /* bus interface logic */
- dmaReset = 0x0040, /* bus master logic */
- vcoReset = 0x0080, /* on-board 10Mbps VCO */
- updnReset = 0x0100, /* upload/download (Rx/TX) logic */
-
- resetMask = 0x01FF,
-};
-
-enum { /* Stall command bits */
- upStall = 0x0000,
- upUnStall = 0x0001,
- dnStall = 0x0002,
- dnUnStall = 0x0003,
-};
-
-enum { /* SetRxFilter command bits */
- receiveIndividual = 0x0001, /* match station address */
- receiveMulticast = 0x0002,
- receiveBroadcast = 0x0004,
- receiveAllFrames = 0x0008, /* promiscuous */
-};
-
-enum { /* StartDma command bits */
- Upload = 0x0000, /* transfer data from adapter to memory */
- Download = 0x0001, /* transfer data from memory to adapter */
-};
-
-enum { /* IntStatus bits */
- interruptLatch = 0x0001,
- hostError = 0x0002, /* Adapter Failure */
- txComplete = 0x0004,
- txAvailable = 0x0008,
- rxComplete = 0x0010,
- rxEarly = 0x0020,
- intRequested = 0x0040,
- updateStats = 0x0080,
- transferInt = 0x0100, /* Bus Master Transfer Complete */
- dnComplete = 0x0200,
- upComplete = 0x0400,
- busMasterInProgress = 0x0800,
- commandInProgress = 0x1000,
-
- interruptMask = 0x07FE,
-};
-
-#define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a))
-#define STATUS(port) ins((port)+IntStatusR)
-
-enum { /* Window 0 - setup */
- Wsetup = 0x0000,
- /* registers */
- ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */
- ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */
- ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */
- AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */
- ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */
- EepromCommand = 0x000A,
- EepromData = 0x000C,
- /* AddressConfig Bits */
- autoSelect9 = 0x0080,
- xcvrMask9 = 0xC000,
- /* ConfigControl bits */
- Ena = 0x0001,
- base10TAvailable9 = 0x0200,
- coaxAvailable9 = 0x1000,
- auiAvailable9 = 0x2000,
- /* EepromCommand bits */
- _EepromReadRegister = 0x0080,
- _EepromRead8bRegister = 0x0230,
- EepromBusy = 0x8000,
-};
-
-static int EepromReadRegister = _EepromReadRegister;
-
-#define EEPROMCMD(port, cmd, a) outs((port)+EepromCommand, (cmd)|(a))
-#define EEPROMBUSY(port) (ins((port)+EepromCommand) & EepromBusy)
-#define EEPROMDATA(port) ins((port)+EepromData)
-
-enum { /* Window 1 - operating set */
- Wop = 0x0001,
- /* registers */
- Fifo = 0x0000,
- RxError = 0x0004, /* 3C59[0257] only */
- RxStatus = 0x0008,
- Timer = 0x000A,
- TxStatus = 0x000B,
- TxFree = 0x000C,
- /* RxError bits */
- rxOverrun = 0x0001,
- runtFrame = 0x0002,
- alignmentError = 0x0004, /* Framing */
- crcError = 0x0008,
- oversizedFrame = 0x0010,
- dribbleBits = 0x0080,
- /* RxStatus bits */
- rxBytes = 0x1FFF, /* 3C59[0257] mask */
- rxBytes9 = 0x07FF, /* 3C5[078]9 mask */
- rxError9 = 0x3800, /* 3C5[078]9 error mask */
- rxOverrun9 = 0x0000,
- oversizedFrame9 = 0x0800,
- dribbleBits9 = 0x1000,
- runtFrame9 = 0x1800,
- alignmentError9 = 0x2000, /* Framing */
- crcError9 = 0x2800,
- rxError = 0x4000,
- rxIncomplete = 0x8000,
- /* TxStatus Bits */
- txStatusOverflow = 0x0004,
- maxCollisions = 0x0008,
- txUnderrun = 0x0010,
- txJabber = 0x0020,
- interruptRequested = 0x0040,
- txStatusComplete = 0x0080,
-};
-
-enum { /* Window 2 - station address */
- Wstation = 0x0002,
-
- ResetOp905B = 0x000C,
-};
-
-enum { /* Window 3 - FIFO management */
- Wfifo = 0x0003,
- /* registers */
- InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */
- OtherInt = 0x0004, /* 3C59[0257] */
- RomControl = 0x0006, /* 3C509B, 3C59[27] */
- MacControl = 0x0006, /* 3C59[0257] */
- ResetOptions = 0x0008, /* 3C59[0257] */
- MediaOptions = 0x0008, /* 3C905B */
- RxFree = 0x000A,
- /* InternalConfig bits */
- disableBadSsdDetect = 0x00000100,
- ramLocation = 0x00000200, /* 0 external, 1 internal */
- ramPartition5to3 = 0x00000000,
- ramPartition3to1 = 0x00010000,
- ramPartition1to1 = 0x00020000,
- ramPartition3to5 = 0x00030000,
- ramPartitionMask = 0x00030000,
- xcvr10BaseT = 0x00000000,
- xcvrAui = 0x00100000, /* 10BASE5 */
- xcvr10Base2 = 0x00300000,
- xcvr100BaseTX = 0x00400000,
- xcvr100BaseFX = 0x00500000,
- xcvrMii = 0x00600000,
- xcvrMask = 0x00700000,
- autoSelect = 0x01000000,
- /* MacControl bits */
- deferExtendEnable = 0x0001,
- deferTimerSelect = 0x001E, /* mask */
- fullDuplexEnable = 0x0020,
- allowLargePackets = 0x0040,
- extendAfterCollision = 0x0080, /* 3C90xB */
- flowControlEnable = 0x0100, /* 3C90xB */
- vltEnable = 0x0200, /* 3C90xB */
- /* ResetOptions bits */
- baseT4Available = 0x0001,
- baseTXAvailable = 0x0002,
- baseFXAvailable = 0x0004,
- base10TAvailable = 0x0008,
- coaxAvailable = 0x0010,
- auiAvailable = 0x0020,
- miiConnector = 0x0040,
-};
-
-enum { /* Window 4 - diagnostic */
- Wdiagnostic = 0x0004,
- /* registers */
- VcoDiagnostic = 0x0002,
- FifoDiagnostic = 0x0004,
- NetworkDiagnostic = 0x0006,
- PhysicalMgmt = 0x0008,
- MediaStatus = 0x000A,
- BadSSD = 0x000C,
- UpperBytesOk = 0x000D,
- /* FifoDiagnostic bits */
- txOverrun = 0x0400,
- rxUnderrun = 0x2000,
- receiving = 0x8000,
- /* PhysicalMgmt bits */
- mgmtClk = 0x0001,
- mgmtData = 0x0002,
- mgmtDir = 0x0004,
- cat5LinkTestDefeat = 0x8000,
- /* MediaStatus bits */
- dataRate100 = 0x0002,
- crcStripDisable = 0x0004,
- enableSqeStats = 0x0008,
- collisionDetect = 0x0010,
- carrierSense = 0x0020,
- jabberGuardEnable = 0x0040,
- linkBeatEnable = 0x0080,
- jabberDetect = 0x0200,
- polarityReversed = 0x0400,
- linkBeatDetect = 0x0800,
- txInProg = 0x1000,
- dcConverterEnabled = 0x4000,
- auiDisable = 0x8000, /* 10BaseT transceiver selected */
-};
-
-enum { /* Window 5 - internal state */
- Wstate = 0x0005,
- /* registers */
- TxStartThresh = 0x0000,
- TxAvailableThresh = 0x0002,
- RxEarlyThresh = 0x0006,
- RxFilter = 0x0008,
- InterruptEnable = 0x000A,
- IndicationEnable = 0x000C,
-};
-
-enum { /* Window 6 - statistics */
- Wstatistics = 0x0006,
- /* registers */
- CarrierLost = 0x0000,
- SqeErrors = 0x0001,
- MultipleColls = 0x0002,
- SingleCollFrames = 0x0003,
- LateCollisions = 0x0004,
- RxOverruns = 0x0005,
- FramesXmittedOk = 0x0006,
- FramesRcvdOk = 0x0007,
- FramesDeferred = 0x0008,
- UpperFramesOk = 0x0009,
- BytesRcvdOk = 0x000A,
- BytesXmittedOk = 0x000C,
-};
-
-enum { /* Window 7 - bus master operations */
- Wmaster = 0x0007,
- /* registers */
- MasterAddress = 0x0000,
- MasterLen = 0x0006,
- MasterStatus = 0x000C,
- /* MasterStatus bits */
- masterAbort = 0x0001,
- targetAbort = 0x0002,
- targetRetry = 0x0004,
- targetDisc = 0x0008,
- masterDownload = 0x1000,
- masterUpload = 0x4000,
- masterInProgress = 0x8000,
-
- masterMask = 0xD00F,
-};
-
-enum { /* 3C90x extended register set */
- Timer905 = 0x001A, /* 8-bits */
- TxStatus905 = 0x001B, /* 8-bits */
- PktStatus = 0x0020, /* 32-bits */
- DnListPtr = 0x0024, /* 32-bits, 8-byte aligned */
- FragAddr = 0x0028, /* 32-bits */
- FragLen = 0x002C, /* 16-bits */
- ListOffset = 0x002E, /* 8-bits */
- TxFreeThresh = 0x002F, /* 8-bits */
- UpPktStatus = 0x0030, /* 32-bits */
- FreeTimer = 0x0034, /* 16-bits */
- UpListPtr = 0x0038, /* 32-bits, 8-byte aligned */
-
- /* PktStatus bits */
- fragLast = 0x00000001,
- dnCmplReq = 0x00000002,
- dnStalled = 0x00000004,
- upCompleteX = 0x00000008,
- dnCompleteX = 0x00000010,
- upRxEarlyEnable = 0x00000020,
- armCountdown = 0x00000040,
- dnInProg = 0x00000080,
- counterSpeed = 0x00000010, /* 0 3.2uS, 1 320nS */
- countdownMode = 0x00000020,
- /* UpPktStatus bits (dpd->control) */
- upPktLenMask = 0x00001FFF,
- upStalled = 0x00002000,
- upError = 0x00004000,
- upPktComplete = 0x00008000,
- upOverrun = 0x00010000, /* RxError<<16 */
- upRuntFrame = 0x00020000,
- upAlignmentError = 0x00040000,
- upCRCError = 0x00080000,
- upOversizedFrame = 0x00100000,
- upDribbleBits = 0x00800000,
- upOverflow = 0x01000000,
-
- dnIndicate = 0x80000000, /* FrameStartHeader (dpd->control) */
-
- updnLastFrag = 0x80000000, /* (dpd->len) */
-
- Nup = 32,
- Ndn = 64,
-};
-
-/*
- * Up/Dn Packet Descriptors.
- * The hardware info (np, control, addr, len) must be 8-byte aligned
- * and this structure size must be a multiple of 8.
- */
-typedef struct Pd Pd;
-typedef struct Pd {
- ulong np; /* next pointer */
- ulong control; /* FSH or UpPktStatus */
- ulong addr;
- ulong len;
-
- Pd* next;
- void *vaddr;
-} Pd;
-
-typedef struct {
- Lock wlock; /* window access */
-
- int attached;
- int busmaster;
- Block* rbp; /* receive buffer */
-
- Block* txbp; /* FIFO -based transmission */
- int txthreshold;
- int txbusy;
-
- int nup; /* full-busmaster -based reception */
- void* upbase;
- Pd* upr;
- Pd* uphead;
-
- int ndn; /* full-busmaster -based transmission */
- void* dnbase;
- Pd* dnr;
- Pd* dnhead;
- Pd* dntail;
- int dnq;
-
- long interrupts; /* statistics */
- long timer[2];
- long stats[BytesRcvdOk+3];
-
- int upqmax;
- int upqmaxhw;
- ulong upinterrupts;
- ulong upqueued;
- ulong upstalls;
- int dnqmax;
- int dnqmaxhw;
- ulong dninterrupts;
- ulong dnqueued;
-
- int xcvr; /* transceiver type */
- int rxstatus9; /* old-style RxStatus register */
- int rxearly; /* RxEarlyThreshold */
- int ts; /* threshold shift */
- int upenabled;
- int dnenabled;
-} Ctlr;
-
-static void
-init905(Ctlr* ctlr)
-{
- Pd *pd, *prev;
- uchar *vaddr;
-
- /*
- * Create rings for the receive and transmit sides.
- * Take care with alignment:
- * make sure ring base is 8-byte aligned;
- * make sure each entry is 8-byte aligned.
- */
- ctlr->upbase = malloc((ctlr->nup+1)*sizeof(Pd));
- ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8);
- vaddr = ialloc((ctlr->nup+1)*ROUNDUP(sizeof(Etherpkt)+4, 8), 8);
-
- prev = ctlr->upr;
- for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){
- pd->np = PADDR(&prev->np);
- pd->control = 0;
- pd->vaddr = vaddr;
- pd->addr = PADDR(vaddr);
- vaddr += ROUNDUP(sizeof(Etherpkt)+4, 8);
- pd->len = updnLastFrag|sizeof(Etherpkt);
-
- pd->next = prev;
- prev = pd;
- }
- ctlr->uphead = ctlr->upr;
-
- ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd));
- ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8);
- vaddr = ialloc((ctlr->ndn+1)*ROUNDUP(sizeof(Etherpkt)+4, 8), 8);
-
- prev = ctlr->dnr;
- for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){
- pd->next = prev;
- pd->vaddr = vaddr;
- pd->addr = PADDR(vaddr);
- vaddr += ROUNDUP(sizeof(Etherpkt)+4, 8);
- prev = pd;
- }
- ctlr->dnhead = ctlr->dnr;
- ctlr->dntail = ctlr->dnr;
- ctlr->dnq = 0;
-}
-
-static Block*
-rbpalloc(Block* (*f)(int))
-{
- Block *bp;
- ulong addr;
-
- /*
- * The receive buffers must be on a 32-byte
- * boundary for EISA busmastering.
- */
- if(bp = f(ROUNDUP(sizeof(Etherpkt), 4) + 31)){
- addr = (ulong)bp->base;
- addr = ROUNDUP(addr, 32);
- bp->rp = (uchar*)addr;
- }
-
- return bp;
-}
-
-static uchar*
-startdma(Ether* ether, ulong address)
-{
- int port, status, w;
- uchar *wp;
-
- port = ether->port;
-
- w = (STATUS(port)>>13) & 0x07;
- COMMAND(port, SelectRegisterWindow, Wmaster);
-
- wp = KADDR(inl(port+MasterAddress));
- status = ins(port+MasterStatus);
- if(status & (masterInProgress|targetAbort|masterAbort))
- print("#l%d: BM status 0x%uX\n", ether->ctlrno, status);
- outs(port+MasterStatus, masterMask);
- outl(port+MasterAddress, address);
- outs(port+MasterLen, sizeof(Etherpkt));
- COMMAND(port, StartDma, Upload);
-
- COMMAND(port, SelectRegisterWindow, w);
- return wp;
-}
-
-/* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
-static void
-intrack3c575(ulong *cbfns)
-{
- cbfns[1] = 0x8000;
-}
-
-static void
-attach(Ether* ether)
-{
- int port, x;
- Ctlr *ctlr;
-
- ctlr = ether->ctlr;
- ilock(&ctlr->wlock);
- if(ctlr->attached){
- iunlock(&ctlr->wlock);
- return;
- }
-
- port = ether->port;
-
- COMMAND(port, SetRxFilter, receiveIndividual|receiveBroadcast);
- x = interruptMask;
- if(ctlr->busmaster == 1)
- x &= ~(rxEarly|rxComplete);
- else{
- if(ctlr->dnenabled)
- x &= ~transferInt;
- if(ctlr->upenabled)
- x &= ~(rxEarly|rxComplete);
- }
- COMMAND(port, SetIndicationEnable, x);
- COMMAND(port, SetInterruptEnable, x);
- COMMAND(port, RxEnable, 0);
- COMMAND(port, TxEnable, 0);
-
- if (ether->mem)
- /* This must be a cardbus card. Acknowledge the interrupt */
- intrack3c575(KADDR(ether->mem));
-
- /*
- * Prime the busmaster channel for receiving directly into a
- * receive packet buffer if necessary.
- */
- if(ctlr->busmaster == 1)
- startdma(ether, PADDR(ctlr->rbp->rp));
- else{
- if(ctlr->upenabled)
- outl(port+UpListPtr, PADDR(&ctlr->uphead->np));
- }
-
- ctlr->attached = 1;
- iunlock(&ctlr->wlock);
-
-}
-
-static void
-statistics(Ether* ether)
-{
- int port, i, u, w;
- Ctlr *ctlr;
-
- port = ether->port;
- ctlr = ether->ctlr;
-
- /*
- * 3C59[27] require a read between a PIO write and
- * reading a statistics register.
- */
- w = (STATUS(port)>>13) & 0x07;
- COMMAND(port, SelectRegisterWindow, Wstatistics);
- STATUS(port);
-
- for(i = 0; i < UpperFramesOk; i++)
- ctlr->stats[i] += inb(port+i) & 0xFF;
- u = inb(port+UpperFramesOk) & 0xFF;
- ctlr->stats[FramesXmittedOk] += (u & 0x30)<<4;
- ctlr->stats[FramesRcvdOk] += (u & 0x03)<<8;
- ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF;
- ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF;
-
- switch(ctlr->xcvr){
-
- case xcvrMii:
- case xcvr100BaseTX:
- case xcvr100BaseFX:
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- STATUS(port);
- ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD);
- break;
- }
-
- COMMAND(port, SelectRegisterWindow, w);
-}
-
-static void
-txstart(Ether* ether)
-{
- int port, len;
- Ctlr *ctlr;
- RingBuf *tb;
-
- port = ether->port;
- ctlr = ether->ctlr;
-
- /*
- * Attempt to top-up the transmit FIFO. If there's room simply
- * stuff in the packet length (unpadded to a dword boundary), the
- * packet data (padded) and remove the packet from the queue.
- * If there's no room post an interrupt for when there is.
- * This routine is called both from the top level and from interrupt
- * level and expects to be called with ctlr->wlock already locked
- * and the correct register window (Wop) in place.
- */
- for(tb = ðer->tb[ether->ti]; tb->owner == Interface; tb = ðer->tb[ether->ti]){
- len = ROUNDUP(tb->len, 4);
- if(len+4 <= ins(port+TxFree)){
- outl(port+Fifo, tb->len);
- outsl(port+Fifo, tb->pkt, len/4);
- tb->owner = Host;
- ether->ti = NEXT(ether->ti, ether->ntb);
- }
- else{
- if(ctlr->txbusy == 0){
- ctlr->txbusy = 1;
- COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts);
- }
- break;
- }
- }
-}
-
-static void
-txstart905(Ether* ether)
-{
- Ctlr *ctlr;
- int port, stalled, timeo;
- RingBuf *tb;
- Pd *pd;
-
- ctlr = ether->ctlr;
- port = ether->port;
-
- /*
- * Free any completed packets.
- */
- pd = ctlr->dntail;
- while(ctlr->dnq){
- if(PADDR(&pd->np) == inl(port+DnListPtr))
- break;
- ctlr->dnq--;
- pd = pd->next;
- }
- ctlr->dntail = pd;
-
- stalled = 0;
- while(ctlr->dnq < (ctlr->ndn-1)){
- tb = ðer->tb[ether->ti];
- if(tb->owner != Interface)
- break;
-
- pd = ctlr->dnhead->next;
- pd->np = 0;
- pd->control = dnIndicate|tb->len;
- memmove(pd->vaddr, tb->pkt, tb->len);
- pd->len = updnLastFrag|tb->len;
-
- tb->owner = Host;
- ether->ti = NEXT(ether->ti, ether->ntb);
-
- if(stalled == 0 && ctlr->dnq && inl(port+DnListPtr)){
- COMMAND(port, Stall, dnStall);
- for(timeo = 100; (STATUS(port) & commandInProgress) && timeo; timeo--)
- ;
- if(timeo == 0)
- print("#l%d: dnstall %d\n", ether->ctlrno, timeo);
- stalled = 1;
- }
-
- coherence();
- ctlr->dnhead->np = PADDR(&pd->np);
- ctlr->dnhead->control &= ~dnIndicate;
- ctlr->dnhead = pd;
- if(ctlr->dnq == 0)
- ctlr->dntail = pd;
- ctlr->dnq++;
-
- ctlr->dnqueued++;
- }
-
- if(ctlr->dnq > ctlr->dnqmax)
- ctlr->dnqmax = ctlr->dnq;
-
- /*
- * If the adapter is not currently processing anything
- * and there is something on the queue, start it processing.
- */
- if(inl(port+DnListPtr) == 0 && ctlr->dnq)
- outl(port+DnListPtr, PADDR(&ctlr->dnhead->np));
- if(stalled)
- COMMAND(port, Stall, dnUnStall);
-}
-
-static void
-transmit(Ether* ether)
-{
- Ctlr *ctlr;
- int port, w;
-
- port = ether->port;
- ctlr = ether->ctlr;
-
- ilock(&ctlr->wlock);
- if(ctlr->dnenabled)
- txstart905(ether);
- else{
- w = (STATUS(port)>>13) & 0x07;
- COMMAND(port, SelectRegisterWindow, Wop);
- txstart(ether);
- COMMAND(port, SelectRegisterWindow, w);
- }
- iunlock(&ctlr->wlock);
-}
-
-static void
-receive905(Ether* ether)
-{
- Ctlr *ctlr;
- int len, port, q;
- Pd *pd;
- RingBuf *rb;
-
- ctlr = ether->ctlr;
- port = ether->port;
-
- if(inl(port+UpPktStatus) & upStalled)
- ctlr->upstalls++;
- q = 0;
- for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){
- if(!(pd->control & upError)){
- rb = ðer->rb[ether->ri];
- if (rb->owner == Interface) {
- len = pd->control & rxBytes;
- rb->len = len;
- memmove(rb->pkt, pd->vaddr, len);
- rb->owner = Host;
- ether->ri = NEXT(ether->ri, ether->nrb);
- }
- }
-
- pd->control = 0;
- COMMAND(port, Stall, upUnStall);
-
- q++;
- }
- ctlr->uphead = pd;
-
- ctlr->upqueued += q;
- if(q > ctlr->upqmax)
- ctlr->upqmax = q;
-}
-
-static void
-receive(Ether* ether)
-{
- int len, port, rxstatus;
- RingBuf *rb;
- Ctlr *ctlr;
-
- port = ether->port;
- ctlr = ether->ctlr;
-
- while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
- if(ctlr->busmaster == 1 && (STATUS(port) & busMasterInProgress))
- break;
-
- /*
- * If there was an error, log it and continue.
- * Unfortunately the 3C5[078]9 has the error info in the status register
- * and the 3C59[0257] implement a separate RxError register.
- */
- if((rxstatus & rxError) == 0){
- /*
- * Packet received. Read it into the next free
- * ring buffer, if any. Must read len bytes padded
- * to a doubleword, can be picked out 32-bits at
- * a time. The CRC is already stripped off.
- */
- rb = ðer->rb[ether->ri];
- if(rb->owner == Interface){
- len = (rxstatus & rxBytes9);
- rb->len = len;
- insl(port+Fifo, rb->pkt, HOWMANY(len, 4));
-
- rb->owner = Host;
- ether->ri = NEXT(ether->ri, ether->nrb);
- }else
-if(debug) print("toss...");
- }
-else
-if(debug) print("error...");
-
- /*
- * All done, discard the packet.
- */
- COMMAND(port, RxDiscard, 0);
- while(STATUS(port) & commandInProgress)
- ;
- }
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
- Ether *ether;
- int port, status, s, txstatus, w, x;
- Ctlr *ctlr;
-
- ether = arg;
- port = ether->port;
- ctlr = ether->ctlr;
-
- ilock(&ctlr->wlock);
- status = STATUS(port);
- if(!(status & (interruptMask|interruptLatch))){
- iunlock(&ctlr->wlock);
- return;
- }
- w = (status>>13) & 0x07;
- COMMAND(port, SelectRegisterWindow, Wop);
-
- ctlr->interrupts++;
- if(ctlr->busmaster == 2)
- ctlr->timer[0] += inb(port+Timer905) & 0xFF;
- else
- ctlr->timer[0] += inb(port+Timer) & 0xFF;
-
- do{
- if(status & hostError){
- /*
- * Adapter failure, try to find out why, reset if
- * necessary. What happens if Tx is active and a reset
- * occurs, need to retransmit? This probably isn't right.
- */
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- x = ins(port+FifoDiagnostic);
- COMMAND(port, SelectRegisterWindow, Wop);
- print("#l%d: status 0x%uX, diag 0x%uX\n",
- ether->ctlrno, status, x);
-
- if(x & txOverrun){
- if(ctlr->busmaster == 0)
- COMMAND(port, TxReset, 0);
- else
- COMMAND(port, TxReset, (updnReset|dmaReset));
- COMMAND(port, TxEnable, 0);
- }
-
- if(x & rxUnderrun){
- /*
- * This shouldn't happen...
- * Reset the receiver and restore the filter and RxEarly
- * threshold before re-enabling.
- * Need to restart any busmastering?
- */
- COMMAND(port, SelectRegisterWindow, Wstate);
- s = (port+RxFilter) & 0x000F;
- COMMAND(port, SelectRegisterWindow, Wop);
- COMMAND(port, RxReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
- COMMAND(port, SetRxFilter, s);
- COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
- COMMAND(port, RxEnable, 0);
- }
-
- status &= ~hostError;
- }
-
- if(status & (transferInt|rxComplete)){
- receive(ether);
- status &= ~(transferInt|rxComplete);
- }
-
- if(status & (upComplete)){
- COMMAND(port, AcknowledgeInterrupt, upComplete);
- receive905(ether);
- status &= ~upComplete;
- ctlr->upinterrupts++;
- }
-
- if(status & txComplete){
- /*
- * Pop the TxStatus stack, accumulating errors.
- * Adjust the TX start threshold if there was an underrun.
- * If there was a Jabber or Underrun error, reset
- * the transmitter, taking care not to reset the dma logic
- * as a busmaster receive may be in progress.
- * For all conditions enable the transmitter.
- */
- if(ctlr->busmaster == 2)
- txstatus = port+TxStatus905;
- else
- txstatus = port+TxStatus;
- s = 0;
- do{
- if(x = inb(txstatus))
- outb(txstatus, 0);
- s |= x;
- }while(STATUS(port) & txComplete);
-
- if(s & txUnderrun){
- if(ctlr->dnenabled){
- while(inl(port+PktStatus) & dnInProg)
- ;
- }
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- while(ins(port+MediaStatus) & txInProg)
- ;
- COMMAND(port, SelectRegisterWindow, Wop);
- if(ctlr->txthreshold < ETHERMAXTU)
- ctlr->txthreshold += ETHERMINTU;
- }
-
- /*
- * According to the manual, maxCollisions does not require
- * a TxReset, merely a TxEnable. However, evidence points to
- * it being necessary on the 3C905. The jury is still out.
- * On busy or badly configured networks maxCollisions can
- * happen frequently enough for messages to be annoying so
- * keep quiet about them by popular request.
- */
- if(s & (txJabber|txUnderrun|maxCollisions)){
- if(ctlr->busmaster == 0)
- COMMAND(port, TxReset, 0);
- else
- COMMAND(port, TxReset, (updnReset|dmaReset));
- while(STATUS(port) & commandInProgress)
- ;
- COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
- if(ctlr->busmaster == 2)
- outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
- if(ctlr->dnenabled)
- status |= dnComplete;
- }
-
- if(s & ~(txStatusComplete|maxCollisions))
- print("#l%d: txstatus 0x%uX, threshold %d\n",
- ether->ctlrno, s, ctlr->txthreshold);
- COMMAND(port, TxEnable, 0);
- status &= ~txComplete;
- status |= txAvailable;
- }
-
- if(status & txAvailable){
- COMMAND(port, AcknowledgeInterrupt, txAvailable);
- ctlr->txbusy = 0;
- txstart(ether);
- status &= ~txAvailable;
- }
-
- if(status & dnComplete){
- COMMAND(port, AcknowledgeInterrupt, dnComplete);
- txstart905(ether);
- status &= ~dnComplete;
- ctlr->dninterrupts++;
- }
-
- if(status & updateStats){
- statistics(ether);
- status &= ~updateStats;
- }
-
- /*
- * Currently, this shouldn't happen.
- */
- if(status & rxEarly){
- COMMAND(port, AcknowledgeInterrupt, rxEarly);
- status &= ~rxEarly;
- }
-
- /*
- * Panic if there are any interrupts not dealt with.
- */
- if(status & interruptMask)
- panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
-
- COMMAND(port, AcknowledgeInterrupt, interruptLatch);
- if (ether->mem)
- intrack3c575((ulong *)KADDR(ether->mem));
-
- }while((status = STATUS(port)) & (interruptMask|interruptLatch));
-
- if(ctlr->busmaster == 2)
- ctlr->timer[1] += inb(port+Timer905) & 0xFF;
- else
- ctlr->timer[1] += inb(port+Timer) & 0xFF;
-
- COMMAND(port, SelectRegisterWindow, w);
- iunlock(&ctlr->wlock);
-}
-
-static void
-txrxreset(int port)
-{
- COMMAND(port, TxReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
- COMMAND(port, RxReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
-}
-
-typedef struct Adapter {
- int port;
- int irq;
- int tbdf;
- ulong cbfns;
-} Adapter;
-static Block* adapter;
-
-static void
-tcmadapter(int port, int irq, int tbdf, ulong cbfns)
-{
- Block *bp;
- Adapter *ap;
-
- bp = allocb(sizeof(Adapter));
- ap = (Adapter*)bp->rp;
- ap->port = port;
- ap->irq = irq;
- ap->tbdf = tbdf;
- ap->cbfns = cbfns;
-
- bp->next = adapter;
- adapter = bp;
-}
-
-/*
- * Write two 0 bytes to identify the IDport and then reset the
- * ID sequence. Then send the ID sequence to the card to get
- * the card into command state.
- */
-static void
-idseq(void)
-{
- int i;
- uchar al;
- static int reset, untag;
-
- /*
- * One time only:
- * reset any adapters listening
- */
- if(reset == 0){
- outb(IDport, 0);
- outb(IDport, 0);
- outb(IDport, 0xC0);
- delay(20);
- reset = 1;
- }
-
- outb(IDport, 0);
- outb(IDport, 0);
- for(al = 0xFF, i = 0; i < 255; i++){
- outb(IDport, al);
- if(al & 0x80){
- al <<= 1;
- al ^= 0xCF;
- }
- else
- al <<= 1;
- }
-
- /*
- * One time only:
- * write ID sequence to get the attention of all adapters;
- * untag all adapters.
- * If a global reset is done here on all adapters it will confuse
- * any ISA cards configured for EISA mode.
- */
- if(untag == 0){
- outb(IDport, 0xD0);
- untag = 1;
- }
-}
-
-static ulong
-activate(void)
-{
- int i;
- ushort x, acr;
-
- /*
- * Do the little configuration dance:
- *
- * 2. write the ID sequence to get to command state.
- */
- idseq();
-
- /*
- * 3. Read the Manufacturer ID from the EEPROM.
- * This is done by writing the IDPort with 0x87 (0x80
- * is the 'read EEPROM' command, 0x07 is the offset of
- * the Manufacturer ID field in the EEPROM).
- * The data comes back 1 bit at a time.
- * A delay seems necessary between reading the bits.
- *
- * If the ID doesn't match, there are no more adapters.
- */
- outb(IDport, 0x87);
- delay(20);
- for(x = 0, i = 0; i < 16; i++){
- delay(20);
- x <<= 1;
- x |= inb(IDport) & 0x01;
- }
- if(x != 0x6D50)
- return 0;
-
- /*
- * 3. Read the Address Configuration from the EEPROM.
- * The Address Configuration field is at offset 0x08 in the EEPROM).
- */
- outb(IDport, 0x88);
- for(acr = 0, i = 0; i < 16; i++){
- delay(20);
- acr <<= 1;
- acr |= inb(IDport) & 0x01;
- }
-
- return (acr & 0x1F)*0x10 + 0x200;
-}
-
-static void
-tcm509isa(void)
-{
- int irq, port;
-
- /*
- * Attempt to activate all adapters. If adapter is set for
- * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
- * it fully.
- */
- while(port = activate()){
- /*
- * 6. Tag the adapter so it won't respond in future.
- */
- outb(IDport, 0xD1);
- if(port == 0x3F0)
- continue;
-
- /*
- * 6. Activate the adapter by writing the Activate command
- * (0xFF).
- */
- outb(IDport, 0xFF);
- delay(20);
-
- /*
- * 8. Can now talk to the adapter's I/O base addresses.
- * Use the I/O base address from the acr just read.
- *
- * Enable the adapter and clear out any lingering status
- * and interrupts.
- */
- while(STATUS(port) & commandInProgress)
- ;
- COMMAND(port, SelectRegisterWindow, Wsetup);
- outs(port+ConfigControl, Ena);
-
- txrxreset(port);
- COMMAND(port, AcknowledgeInterrupt, 0xFF);
-
- irq = (ins(port+ResourceConfig)>>12) & 0x0F;
- tcmadapter(port, irq, BUSUNKNOWN, 0);
- }
-}
-
-static void
-tcm5XXeisa(void)
-{
- ushort x;
- int irq, port, slot;
-
- /*
- * Check if this is an EISA machine.
- * If not, nothing to do.
- */
- if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4))
- return;
-
- /*
- * Continue through the EISA slots looking for a match on both
- * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
- * If an adapter is found, select window 0, enable it and clear
- * out any lingering status and interrupts.
- */
- for(slot = 1; slot < MaxEISA; slot++){
- port = slot*0x1000;
- if(ins(port+0xC80+ManufacturerID) != 0x6D50)
- continue;
- x = ins(port+0xC80+ProductID);
- if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900)
- continue;
-
- COMMAND(port, SelectRegisterWindow, Wsetup);
- outs(port+ConfigControl, Ena);
-
- txrxreset(port);
- COMMAND(port, AcknowledgeInterrupt, 0xFF);
-
- irq = (ins(port+ResourceConfig)>>12) & 0x0F;
- tcmadapter(port, irq, BUSUNKNOWN, 0);
- }
-}
-
-static void
-tcm59Xpci(Ether *ether)
-{
- Pcidev *p;
- int irq, port;
- ulong bar;
-
- p = nil;
- while(p = pcimatch(p, 0x10B7, 0)){
- if (p->did == 0x5157) {
- EepromReadRegister = _EepromRead8bRegister;
-
- /* Map the CardBus functions */
- bar = pcicfgr32(p, PciBAR2);
- print("ether#%d: CardBus functions at %.8luX\n", ether->ctlrno, bar & ~KZERO);
- }
- else
- bar = 0;
-
- /*
- * Not prepared to deal with memory-mapped
- * devices yet.
- */
- if(!(p->mem[0].bar & 0x01))
- continue;
- port = p->mem[0].bar & ~0x01;
- irq = p->intl;
- COMMAND(port, GlobalReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
-
- tcmadapter(port, irq, p->tbdf, bar);
- pcisetbme(p);
- }
-}
-
-static char* tcmpcmcia[] = {
- "3C589", /* 3COM 589[ABCD] */
- "3C562", /* 3COM 562 */
- "589E", /* 3COM Megahertz 589E */
- nil,
-};
-
-static int
-tcm5XXpcmcia(Ether* ether)
-{
- int i;
-
- for(i = 0; tcmpcmcia[i] != nil; i++){
- if(!cistrcmp(ether->type, tcmpcmcia[i])){
- /*
- * No need for an ioalloc here, the 589 reset
- * code deals with it.
- if(ioalloc(ether->port, 0x10, 0, "tcm5XXpcmcia") < 0)
- return 0;
- */
- return ether->port;
- }
- }
-
- return 0;
-}
-
-static void
-setxcvr(int port, int xcvr, int is9)
-{
- int x;
-
- if(is9){
- COMMAND(port, SelectRegisterWindow, Wsetup);
- x = ins(port+AddressConfig) & ~xcvrMask9;
- x |= (xcvr>>20)<<14;
- outs(port+AddressConfig, x);
- }
- else{
- COMMAND(port, SelectRegisterWindow, Wfifo);
- x = inl(port+InternalConfig) & ~xcvrMask;
- x |= xcvr;
- outl(port+InternalConfig, x);
- }
-
- txrxreset(port);
-}
-
-static void
-setfullduplex(int port)
-{
- int x;
-
- COMMAND(port, SelectRegisterWindow, Wfifo);
- x = ins(port+MacControl);
- outs(port+MacControl, fullDuplexEnable|x);
-
- txrxreset(port);
-}
-
-static int
-miimdi(int port, int n)
-{
- int data, i;
-
- /*
- * Read n bits from the MII Management Register.
- */
- data = 0;
- for(i = n-1; i >= 0; i--){
- if(ins(port) & mgmtData)
- data |= (1<<i);
- microdelay(1);
- outs(port, mgmtClk);
- microdelay(1);
- outs(port, 0);
- microdelay(1);
- }
-
- return data;
-}
-
-static void
-miimdo(int port, int bits, int n)
-{
- int i, mdo;
-
- /*
- * Write n bits to the MII Management Register.
- */
- for(i = n-1; i >= 0; i--){
- if(bits & (1<<i))
- mdo = mgmtDir|mgmtData;
- else
- mdo = mgmtDir;
- outs(port, mdo);
- microdelay(1);
- outs(port, mdo|mgmtClk);
- microdelay(1);
- outs(port, mdo);
- microdelay(1);
- }
-}
-
-static int
-miir(int port, int phyad, int regad)
-{
- int data, w;
-
- w = (STATUS(port)>>13) & 0x07;
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- port += PhysicalMgmt;
-
- /*
- * Preamble;
- * ST+OP+PHYAD+REGAD;
- * TA + 16 data bits.
- */
- miimdo(port, 0xFFFFFFFF, 32);
- miimdo(port, 0x1800|(phyad<<5)|regad, 14);
- data = miimdi(port, 18);
-
- port -= PhysicalMgmt;
- COMMAND(port, SelectRegisterWindow, w);
-
- if(data & 0x10000)
- return -1;
-
- return data & 0xFFFF;
-}
-
-static void
-scanphy(int port)
-{
- int i, x;
-
- for(i = 0; i < 32; i++){
- if((x = miir(port, i, 2)) == -1 || x == 0)
- continue;
- x <<= 6;
- x |= miir(port, i, 3)>>10;
- XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
- USED(x);
- }
-}
-
-#ifdef notdef
-static struct xxx {
- int available;
- int next;
-} xxx[8] = {
- { base10TAvailable, 1, }, /* xcvr10BaseT -> xcvrAui */
- { auiAvailable, 3, }, /* xcvrAui -> xcvr10Base2 */
- { 0, -1, },
- { coaxAvailable, -1, }, /* xcvr10Base2 -> nowhere */
- { baseTXAvailable, 5, }, /* xcvr100BaseTX-> xcvr100BaseFX */
- { baseFXAvailable, -1, }, /* xcvr100BaseFX-> nowhere */
- { miiConnector, -1, }, /* xcvrMii -> nowhere */
- { 0, -1, },
-};
-#endif /* notdef */
-
-static struct {
- char *name;
- int avail;
- int xcvr;
-} media[] = {
- "10BaseT", base10TAvailable, xcvr10BaseT,
- "10Base2", coaxAvailable, xcvr10Base2,
- "100BaseTX", baseTXAvailable, xcvr100BaseTX,
- "100BaseFX", baseFXAvailable, xcvr100BaseFX,
- "aui", auiAvailable, xcvrAui,
- "mii", miiConnector, xcvrMii
-};
-
-static int
-autoselect(int port, int xcvr, int is9)
-{
- int media, x;
- USED(xcvr);
-
- /*
- * Pathetic attempt at automatic media selection.
- * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
- * cards operational.
- * It's a bonus if it works for anything else.
- */
- if(is9){
- COMMAND(port, SelectRegisterWindow, Wsetup);
- x = ins(port+ConfigControl);
- media = 0;
- if(x & base10TAvailable9)
- media |= base10TAvailable;
- if(x & coaxAvailable9)
- media |= coaxAvailable;
- if(x & auiAvailable9)
- media |= auiAvailable;
- }
- else{
- COMMAND(port, SelectRegisterWindow, Wfifo);
- media = ins(port+ResetOptions);
- }
- XCVRDEBUG("autoselect: media %uX\n", media);
-
- if(media & miiConnector)
- return xcvrMii;
-
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- XCVRDEBUG("autoselect: media status %uX\n", ins(port+MediaStatus));
-
- if(media & baseTXAvailable){
- /*
- * Must have InternalConfig register.
- */
- setxcvr(port, xcvr100BaseTX, is9);
-
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
- outs(port+MediaStatus, linkBeatEnable|x);
- delay(10);
-
- if(ins(port+MediaStatus) & linkBeatDetect)
- return xcvr100BaseTX;
- outs(port+MediaStatus, x);
- }
-
- if(media & base10TAvailable){
- setxcvr(port, xcvr10BaseT, is9);
-
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- x = ins(port+MediaStatus) & ~dcConverterEnabled;
- outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
- delay(100);
-
- XCVRDEBUG("autoselect: 10BaseT media status %uX\n", ins(port+MediaStatus));
- if(ins(port+MediaStatus) & linkBeatDetect)
- return xcvr10BaseT;
- outs(port+MediaStatus, x);
- }
-
- /*
- * Botch.
- */
- return autoSelect;
-}
-
-static int
-eepromdata(int port, int offset)
-{
- COMMAND(port, SelectRegisterWindow, Wsetup);
- while(EEPROMBUSY(port))
- ;
- EEPROMCMD(port, EepromReadRegister, offset);
- while(EEPROMBUSY(port))
- ;
- return EEPROMDATA(port);
-}
-
-int
-elnk3reset(Ether* ether)
-{
- int anar, anlpar, phyaddr, phystat, timeo, xcvr;
- int busmaster, did, i, j, port, rxearly, rxstatus9, x;
- Block *bp, **bpp;
- Adapter *ap;
- uchar ea[Eaddrlen];
- Ctlr *ctlr;
- static int scandone;
- char *p;
-
- /*
- * Scan for adapter on PCI, EISA and finally
- * using the little ISA configuration dance.
- */
- if(scandone == 0){
- tcm59Xpci(ether);
- tcm5XXeisa();
- tcm509isa();
- scandone = 1;
- }
-
- /*
- * Any adapter matches if no ether->port is supplied,
- * otherwise the ports must match.
- */
- port = 0;
- bpp = &adapter;
- for(bp = *bpp; bp; bp = bp->next){
- ap = (Adapter*)bp->rp;
- if(ether->port == 0 || ether->port == ap->port){
- port = ap->port;
- ether->irq = ap->irq;
- ether->tbdf = ap->tbdf;
- ether->mem = ap->cbfns; /* Misuse the mem ref for the cardbus functions */
- *bpp = bp->next;
- freeb(bp);
- break;
- }
- bpp = &bp->next;
- }
- if(port == 0 && (port = tcm5XXpcmcia(ether)) == 0)
- return -1;
-
- /*
- * Read the DeviceID from the EEPROM, it's at offset 0x03,
- * and do something depending on capabilities.
- */
- switch(did = eepromdata(port, 0x03)){
-
- case 0x5157: /* 3C575 Cyclone */
- case 0x4500: /* 3C450 HomePNA Tornado */
- case 0x6056:
- case 0x7646: /* 3CSOHO100-TX */
- case 0x9055: /* 3C905B-TX */
- case 0x9200: /* 3C905C-TX */
- /*FALLTHROUGH*/
- case 0x9000: /* 3C900-TPO */
- case 0x9001: /* 3C900-COMBO */
- case 0x9005: /* 3C900B-COMBO */
- case 0x9050: /* 3C905-TX */
- case 0x9051: /* 3C905-T4 */
- if(BUSTYPE(ether->tbdf) != BusPCI)
- goto buggery;
- busmaster = 2;
- goto vortex;
-
- case 0x5900: /* 3C590-[TP|COMBO|TPO] */
- case 0x5920: /* 3C592-[TP|COMBO|TPO] */
- case 0x5950: /* 3C595-TX */
- case 0x5951: /* 3C595-T4 */
- case 0x5952: /* 3C595-MII */
- case 0x5970: /* 3C597-TX */
- case 0x5971: /* 3C597-T4 */
- case 0x5972: /* 3C597-MII */
- busmaster = 1;
- vortex:
- COMMAND(port, SelectRegisterWindow, Wfifo);
- xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
- rxearly = 8188;
- rxstatus9 = 0;
- break;
-
- buggery:
- default:
- busmaster = 0;
- COMMAND(port, SelectRegisterWindow, Wsetup);
- x = ins(port+AddressConfig);
- xcvr = ((x & xcvrMask9)>>14)<<20;
- if(x & autoSelect9)
- xcvr |= autoSelect;
- rxearly = 2044;
- rxstatus9 = 1;
- break;
- }
-
- /*
- * Check if the adapter's station address is to be overridden.
- * If not, read it from the EEPROM and set in ether->ea prior to
- * loading the station address in Wstation.
- * The EEPROM returns 16-bits at a time.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, ether->ea, Eaddrlen) == 0){
- for(i = 0; i < Eaddrlen/2; i++){
- x = eepromdata(port, i);
- ether->ea[2*i] = x>>8;
- ether->ea[2*i+1] = x;
- }
- }
-
- COMMAND(port, SelectRegisterWindow, Wstation);
- for(i = 0; i < Eaddrlen; i++)
- outb(port+i, ether->ea[i]);
-
- /*
- * Enable the transceiver if necessary and determine whether
- * busmastering can be used. Due to bugs in the first revision
- * of the 3C59[05], don't use busmastering at 10Mbps.
- */
- XCVRDEBUG("reset: xcvr %uX\n", xcvr);
-
- /*
- * Allow user to specify desired media in plan9.ini
- */
- for(i = 0; i < ether->nopt; i++){
- if(cistrncmp(ether->opt[i], "media=", 6) != 0)
- continue;
- p = ether->opt[i]+6;
- for(j = 0; j < nelem(media); j++)
- if(cistrcmp(p, media[j].name) == 0)
- xcvr = media[j].xcvr;
- }
-
- /*
- * forgive me, but i am weak
- */
- switch(did){
- default:
- if(xcvr & autoSelect)
- xcvr = autoselect(port, xcvr, rxstatus9);
- break;
- case 0x4500:
- case 0x5157:
- case 0x6056:
- case 0x7646:
- case 0x9055:
- case 0x9200:
- xcvr = xcvrMii;
- txrxreset(port);
- XCVRDEBUG("905[BC] reset ops 0x%uX\n", ins(port+ResetOp905B));
-
- if (did == 0x5157) {
- ushort reset_opts;
-
- COMMAND(port, SelectRegisterWindow, Wstation);
- reset_opts = ins(port + ResetOp905B);
- reset_opts |= 0x0010; /* Invert LED */
- outs(port + ResetOp905B, reset_opts);
- }
- break;
- }
- XCVRDEBUG("autoselect returns: xcvr %uX, did 0x%uX\n", xcvr, did);
-
- switch(xcvr){
-
- case xcvrMii:
- /*
- * Quick hack.
- scanphy(port);
- */
- phyaddr = (did == 0x5157)? 0: 24;
- for(i = 0; i < 7; i++)
- XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
- XCVRDEBUG("\n");
-
- for(timeo = 0; timeo < 30; timeo++){
- phystat = miir(port, phyaddr, 0x01);
- if(phystat & 0x20)
- break;
- XCVRDEBUG(" %2.2uX", phystat);
- delay(100);
- }
- XCVRDEBUG(" %2.2uX", miir(port, phyaddr, 0x01));
- XCVRDEBUG("\n");
-
- anar = miir(port, phyaddr, 0x04);
- anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
- anar &= anlpar;
- miir(port, phyaddr, 0x00);
- XCVRDEBUG("mii an: %uX anlp: %uX r0:%uX r1:%uX\n",
- anar, anlpar, miir(port, phyaddr, 0x00),
- miir(port, phyaddr, 0x01));
- for(i = 0; i < ether->nopt; i++){
- if(cistrcmp(ether->opt[i], "fullduplex") == 0)
- anar |= 0x0100;
- else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
- anar |= 0x0100;
- else if(cistrcmp(ether->opt[i], "force100") == 0)
- anar |= 0x0080;
- }
- XCVRDEBUG("mii anar: %uX\n", anar);
- if(anar & 0x0100){ /* 100BASE-TXFD */
- setfullduplex(port);
- }
- else if(anar & 0x0200){ /* 100BASE-T4 */
- /* nothing to do */
- }
- else if(anar & 0x0080){ /* 100BASE-TX */
- /* nothing to do */;
- }
- else if(anar & 0x0040) /* 10BASE-TFD */
- setfullduplex(port);
- else{ /* 10BASE-T */
- /* nothing to do */;
- }
- break;
-
- case xcvr100BaseTX:
- case xcvr100BaseFX:
- COMMAND(port, SelectRegisterWindow, Wfifo);
- x = inl(port+InternalConfig) & ~ramPartitionMask;
- outl(port+InternalConfig, x|ramPartition1to1);
-
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
- x |= linkBeatEnable;
- outs(port+MediaStatus, x);
- break;
-
- case xcvr10BaseT:
- /*
- * Enable Link Beat and Jabber to start the
- * transceiver.
- */
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- x = ins(port+MediaStatus) & ~dcConverterEnabled;
- x |= linkBeatEnable|jabberGuardEnable;
- outs(port+MediaStatus, x);
-
- if((did & 0xFF00) == 0x5900)
- busmaster = 0;
- break;
-
- case xcvr10Base2:
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
- outs(port+MediaStatus, x);
-
- /*
- * Start the DC-DC converter.
- * Wait > 800 microseconds.
- */
- COMMAND(port, EnableDcConverter, 0);
- delay(1);
- break;
- }
-
- /*
- * Wop is the normal operating register set.
- * The 3C59[0257] adapters allow access to more than one register window
- * at a time, but there are situations where switching still needs to be
- * done, so just do it.
- * Clear out any lingering Tx status.
- */
- COMMAND(port, SelectRegisterWindow, Wop);
- if(busmaster == 2)
- x = port+TxStatus905;
- else
- x = port+TxStatus;
- while(inb(x))
- outb(x, 0);
-
- /*
- * Allocate a controller structure, clear out the
- * adapter statistics, clear the statistics logged into ctlr
- * and enable statistics collection. Xcvr is needed in order
- * to collect the BadSSD statistics.
- */
- ether->ctlr = malloc(sizeof(Ctlr));
- ctlr = ether->ctlr;
-
- ilock(&ctlr->wlock);
- ctlr->xcvr = xcvr;
- statistics(ether);
- memset(ctlr->stats, 0, sizeof(ctlr->stats));
-
- ctlr->busmaster = busmaster;
- ctlr->xcvr = xcvr;
- ctlr->rxstatus9 = rxstatus9;
- ctlr->rxearly = rxearly;
- if(rxearly >= 2048)
- ctlr->ts = 2;
-
- COMMAND(port, StatisticsEnable, 0);
-
- /*
- * Allocate any receive buffers.
- */
- if (ctlr->busmaster == 2) {
- ctlr->dnenabled = 1;
-
- /*
- * 10MUpldBug.
- * Disabling is too severe, can use receive busmastering at
- * 100Mbps OK, but how to tell which rate is actually being used -
- * the 3c905 always seems to have dataRate100 set?
- * Believe the bug doesn't apply if upRxEarlyEnable is set
- * and the threshold is set such that uploads won't start
- * until the whole packet has been received.
- */
- ctlr->upenabled = 1;
- x = eepromdata(port, 0x0F);
- if(!(x & 0x01))
- outl(port+PktStatus, upRxEarlyEnable);
-
- ctlr->nup = Nup;
- ctlr->ndn = Ndn;
- init905(ctlr);
- outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
- }
-
- /*
- * Set a base TxStartThresh which will be incremented
- * if any txUnderrun errors occur and ensure no RxEarly
- * interrupts happen.
- */
- ctlr->txthreshold = ETHERMAXTU/2;
- COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
- COMMAND(port, SetRxEarlyThresh, rxearly>>ctlr->ts);
-
- iunlock(&ctlr->wlock);
-
- /*
- * Linkage to the generic ethernet driver.
- */
- ether->port = port;
- ether->attach = attach;
- ether->transmit = transmit;
- ether->interrupt = interrupt;
-
- return 0;
-}
--- a/os/boot/pc/etherelnk3x.c
+++ /dev/null
@@ -1,1074 +1,0 @@
-/*
- * Etherlink III and Fast EtherLink adapters.
- * To do:
- * autoSelect;
- * busmaster channel;
- * PCMCIA;
- * PCI latency timer and master enable;
- * errata list.
- *
- * Product ID:
- * 9150 ISA 3C509[B]
- * 9050 ISA 3C509[B]-TP
- * 9450 ISA 3C509[B]-COMBO
- * 9550 ISA 3C509[B]-TPO
- *
- * 9350 EISA 3C579
- * 9250 EISA 3C579-TP
- *
- * 5920 EISA 3C592-[TP|COMBO|TPO]
- * 5970 EISA 3C597-TX Fast Etherlink 10BASE-T/100BASE-TX
- * 5971 EISA 3C597-T4 Fast Etherlink 10BASE-T/100BASE-T4
- * 5972 EISA 3C597-MII Fast Etherlink 10BASE-T/MII
- *
- * 5900 PCI 3C590-[TP|COMBO|TPO]
- * 5950 PCI 3C595-TX Fast Etherlink Shared 10BASE-T/100BASE-TX
- * 5951 PCI 3C595-T4 Fast Etherlink Shared 10BASE-T/100BASE-T4
- * 5952 PCI 3C595-MII Fast Etherlink 10BASE-T/MII
- *
- * 9058 PCMCIA 3C589[B]-[TP|COMBO]
- *
- * 627C MCA 3C529
- * 627D MCA 3C529-TP
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum {
- IDport = 0x0110, /* anywhere between 0x0100 and 0x01F0 */
-};
-
-enum { /* all windows */
- Command = 0x000E,
- IntStatus = 0x000E,
-};
-
-enum { /* Commands */
- GlobalReset = 0x0000,
- SelectRegisterWindow = 0x0001,
- EnableDcConverter = 0x0002,
- RxDisable = 0x0003,
- RxEnable = 0x0004,
- RxReset = 0x0005,
- TxDone = 0x0007,
- RxDiscard = 0x0008,
- TxEnable = 0x0009,
- TxDisable = 0x000A,
- TxReset = 0x000B,
- RequestInterrupt = 0x000C,
- AcknowledgeInterrupt = 0x000D,
- SetInterruptEnable = 0x000E,
- SetIndicationEnable = 0x000F, /* SetReadZeroMask */
- SetRxFilter = 0x0010,
- SetRxEarlyThresh = 0x0011,
- SetTxAvailableThresh = 0x0012,
- SetTxStartThresh = 0x0013,
- StartDma = 0x0014, /* initiate busmaster operation */
- StatisticsEnable = 0x0015,
- StatisticsDisable = 0x0016,
- DisableDcConverter = 0x0017,
- SetTxReclaimThresh = 0x0018, /* PIO-only adapters */
- PowerUp = 0x001B, /* not all adapters */
- PowerDownFull = 0x001C, /* not all adapters */
- PowerAuto = 0x001D, /* not all adapters */
-};
-
-enum { /* (Global|Rx|Tx)Reset command bits */
- tpAuiReset = 0x0001, /* 10BaseT and AUI transceivers */
- endecReset = 0x0002, /* internal Ethernet encoder/decoder */
- networkReset = 0x0004, /* network interface logic */
- fifoReset = 0x0008, /* FIFO control logic */
- aismReset = 0x0010, /* autoinitialise state-machine logic */
- hostReset = 0x0020, /* bus interface logic */
- dmaReset = 0x0040, /* bus master logic */
- vcoReset = 0x0080, /* on-board 10Mbps VCO */
-
- resetMask = 0x00FF,
-};
-
-enum { /* SetRxFilter command bits */
- receiveIndividual = 0x0001, /* match station address */
- receiveMulticast = 0x0002,
- receiveBroadcast = 0x0004,
- receiveAllFrames = 0x0008, /* promiscuous */
-};
-
-enum { /* StartDma command bits */
- Upload = 0x0000, /* transfer data from adapter to memory */
- Download = 0x0001, /* transfer data from memory to adapter */
-};
-
-enum { /* IntStatus bits */
- interruptLatch = 0x0001,
- hostError = 0x0002, /* Adapter Failure */
- txComplete = 0x0004,
- txAvailable = 0x0008,
- rxComplete = 0x0010,
- rxEarly = 0x0020,
- intRequested = 0x0040,
- updateStats = 0x0080,
- transferInt = 0x0100, /* Bus Master Transfer Complete */
- busMasterInProgress = 0x0800,
- commandInProgress = 0x1000,
-
- interruptMask = 0x01FE,
-};
-
-#define COMMAND(port, cmd, a) outs((port)+Command, ((cmd)<<11)|(a))
-#define STATUS(port) ins((port)+IntStatus)
-
-enum { /* Window 0 - setup */
- Wsetup = 0x0000,
- /* registers */
- ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */
- ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */
- ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */
- AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */
- ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */
- EepromCommand = 0x000A,
- EepromData = 0x000C,
- /* AddressConfig Bits */
- autoSelect9 = 0x0080,
- xcvrMask9 = 0xC000,
- /* ConfigControl bits */
- Ena = 0x0001,
- /* EepromCommand bits */
- EepromReadRegister = 0x0080,
- EepromBusy = 0x8000,
-};
-
-#define EEPROMCMD(port, cmd, a) outs((port)+EepromCommand, (cmd)|(a))
-#define EEPROMBUSY(port) (ins((port)+EepromCommand) & EepromBusy)
-#define EEPROMDATA(port) ins((port)+EepromData)
-
-enum { /* Window 1 - operating set */
- Wop = 0x0001,
- /* registers */
- Fifo = 0x0000,
- RxError = 0x0004, /* 3C59[0257] only */
- RxStatus = 0x0008,
- Timer = 0x000A,
- TxStatus = 0x000B,
- TxFree = 0x000C,
- /* RxError bits */
- rxOverrun = 0x0001,
- runtFrame = 0x0002,
- alignmentError = 0x0004, /* Framing */
- crcError = 0x0008,
- oversizedFrame = 0x0010,
- dribbleBits = 0x0080,
- /* RxStatus bits */
- rxBytes = 0x1FFF, /* 3C59[0257] mask */
- rxBytes9 = 0x07FF, /* 3C5[078]9 mask */
- rxError9 = 0x3800, /* 3C5[078]9 error mask */
- rxOverrun9 = 0x0000,
- oversizedFrame9 = 0x0800,
- dribbleBits9 = 0x1000,
- runtFrame9 = 0x1800,
- alignmentError9 = 0x2000, /* Framing */
- crcError9 = 0x2800,
- rxError = 0x4000,
- rxIncomplete = 0x8000,
- /* TxStatus Bits */
- txStatusOverflow = 0x0004,
- maxCollisions = 0x0008,
- txUnderrun = 0x0010,
- txJabber = 0x0020,
- interruptRequested = 0x0040,
- txStatusComplete = 0x0080,
-};
-
-enum { /* Window 2 - station address */
- Wstation = 0x0002,
-};
-
-enum { /* Window 3 - FIFO management */
- Wfifo = 0x0003,
- /* registers */
- InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */
- OtherInt = 0x0004, /* 3C59[0257] */
- RomControl = 0x0006, /* 3C509B, 3C59[27] */
- MacControl = 0x0006, /* 3C59[0257] */
- ResetOptions = 0x0008, /* 3C59[0257] */
- RxFree = 0x000A,
- /* InternalConfig bits */
- disableBadSsdDetect = 0x00000100,
- ramLocation = 0x00000200, /* 0 external, 1 internal */
- ramPartition5to3 = 0x00000000,
- ramPartition3to1 = 0x00010000,
- ramPartition1to1 = 0x00020000,
- ramPartition3to5 = 0x00030000,
- ramPartitionMask = 0x00030000,
- xcvr10BaseT = 0x00000000,
- xcvrAui = 0x00100000, /* 10BASE5 */
- xcvr10Base2 = 0x00300000,
- xcvr100BaseTX = 0x00400000,
- xcvr100BaseFX = 0x00500000,
- xcvrMii = 0x00600000,
- xcvrMask = 0x00700000,
- autoSelect = 0x01000000,
- /* MacControl bits */
- deferExtendEnable = 0x0001,
- deferTimerSelect = 0x001E, /* mask */
- fullDuplexEnable = 0x0020,
- allowLargePackets = 0x0040,
- /* ResetOptions bits */
- baseT4Available = 0x0001,
- baseTXAvailable = 0x0002,
- baseFXAvailable = 0x0004,
- base10TAvailable = 0x0008,
- coaxAvailable = 0x0010,
- auiAvailable = 0x0020,
- miiConnector = 0x0040,
-};
-
-enum { /* Window 4 - diagnostic */
- Wdiagnostic = 0x0004,
- /* registers */
- VcoDiagnostic = 0x0002,
- FifoDiagnostic = 0x0004,
- NetworkDiagnostic = 0x0006,
- PhysicalMgmt = 0x0008,
- MediaStatus = 0x000A,
- BadSSD = 0x000C,
- /* FifoDiagnostic bits */
- txOverrun = 0x0400,
- rxUnderrun = 0x2000,
- receiving = 0x8000,
- /* MediaStatus bits */
- dataRate100 = 0x0002,
- crcStripDisable = 0x0004,
- enableSqeStats = 0x0008,
- collisionDetect = 0x0010,
- carrierSense = 0x0020,
- jabberGuardEnable = 0x0040,
- linkBeatEnable = 0x0080,
- jabberDetect = 0x0200,
- polarityReversed = 0x0400,
- linkBeatDetect = 0x0800,
- txInProg = 0x1000,
- dcConverterEnabled = 0x4000,
- auiDisable = 0x8000,
-};
-
-enum { /* Window 5 - internal state */
- Wstate = 0x0005,
- /* registers */
- TxStartThresh = 0x0000,
- TxAvalableThresh = 0x0002,
- RxEarlyThresh = 0x0006,
- RxFilter = 0x0008,
- InterruptEnable = 0x000A,
- IndicationEnable = 0x000C,
-};
-
-enum { /* Window 6 - statistics */
- Wstatistics = 0x0006,
- /* registers */
- CarrierLost = 0x0000,
- SqeErrors = 0x0001,
- MultipleColls = 0x0002,
- SingleCollFrames = 0x0003,
- LateCollisions = 0x0004,
- RxOverruns = 0x0005,
- FramesXmittedOk = 0x0006,
- FramesRcvdOk = 0x0007,
- FramesDeferred = 0x0008,
- UpperFramesOk = 0x0009,
- BytesRcvdOk = 0x000A,
- BytesXmittedOk = 0x000C,
-};
-
-enum { /* Window 7 - bus master operations */
- Wmaster = 0x0007,
- /* registers */
- MasterAddress = 0x0000,
- MasterLen = 0x0006,
- MasterStatus = 0x000C,
- /* MasterStatus bits */
- masterAbort = 0x0001,
- targetAbort = 0x0002,
- targetRetry = 0x0004,
- targetDisc = 0x0008,
- masterDownload = 0x1000,
- masterUpload = 0x4000,
- masterInProgress = 0x8000,
-
- masterMask = 0xD00F,
-};
-
-typedef struct {
- int txthreshold;
-} Ctlr;
-
-static void
-attach(Ether* ether)
-{
- int port, x;
-
- port = ether->port;
-
- /*
- * Set the receiver packet filter for this and broadcast addresses,
- * set the interrupt masks for all interrupts, enable the receiver
- * and transmitter.
- */
- x = receiveBroadcast|receiveIndividual;
- COMMAND(port, SetRxFilter, x);
-
- x = interruptMask|interruptLatch;
- COMMAND(port, SetIndicationEnable, x);
- COMMAND(port, SetInterruptEnable, x);
-
- COMMAND(port, RxEnable, 0);
- COMMAND(port, TxEnable, 0);
-}
-
-static void
-transmit(Ether* ether)
-{
- int port, len;
- RingBuf *tb;
-
- /*
- * Attempt to top-up the transmit FIFO. If there's room simply
- * stuff in the packet length (unpadded to a dword boundary), the
- * packet data (padded) and remove the packet from the queue.
- * If there's no room post an interrupt for when there is.
- * This routine is called both from the top level and from interrupt
- * level.
- */
- port = ether->port;
- for(tb = ðer->tb[ether->ti]; tb->owner == Interface; tb = ðer->tb[ether->ti]){
- len = ROUNDUP(tb->len, 4);
- if(len+4 <= ins(port+TxFree)){
- outl(port+Fifo, tb->len);
- outsl(port+Fifo, tb->pkt, len/4);
- tb->owner = Host;
- ether->ti = NEXT(ether->ti, ether->ntb);
- }
- else{
- COMMAND(port, SetTxAvailableThresh, len);
- break;
- }
- }
-}
-
-static void
-receive(Ether* ether)
-{
- int len, port, rxstatus;
- RingBuf *rb;
-
- port = ether->port;
-
- while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
- /*
- * If there was an error, throw it away and continue.
- * The 3C5[078]9 has the error info in the status register
- * and the 3C59[0257] implement a separate RxError register.
- */
- if((rxstatus & rxError) == 0){
- /*
- * Packet received. Read it into the next free
- * ring buffer, if any. Must read len bytes padded
- * to a doubleword, can be picked out 32-bits at
- * a time. The CRC is already stripped off.
- */
- rb = ðer->rb[ether->ri];
- if(rb->owner == Interface){
- len = (rxstatus & rxBytes9);
- rb->len = len;
- insl(port+Fifo, rb->pkt, HOWMANY(len, 4));
-
- rb->owner = Host;
- ether->ri = NEXT(ether->ri, ether->nrb);
- }
- }
-
- /*
- * All done, discard the packet.
- */
- COMMAND(port, RxDiscard, 0);
- while(STATUS(port) & commandInProgress)
- ;
- }
-}
-
-static void
-statistics(Ether* ether)
-{
- int i, port, w;
-
- port = ether->port;
- w = (STATUS(port)>>13) & 0x07;
- COMMAND(port, SelectRegisterWindow, Wop);
- COMMAND(port, SelectRegisterWindow, Wstatistics);
-
- for(i = 0; i < 0x0A; i++)
- inb(port+i);
- ins(port+BytesRcvdOk);
- ins(port+BytesXmittedOk);
-
- COMMAND(port, SelectRegisterWindow, w);
-}
-
-static void
-interrupt(Ureg*, void* arg)
-{
- Ether *ether;
- int port, status, txstatus, w, x;
- Ctlr *ctlr;
-
- ether = arg;
- port = ether->port;
- ctlr = ether->ctlr;
-
- w = (STATUS(port)>>13) & 0x07;
- COMMAND(port, SelectRegisterWindow, Wop);
-
- for(;;){
- /*
- * Clear the interrupt latch.
- * It's possible to receive a packet and for another
- * to become complete before exiting the interrupt
- * handler so this must be done first to ensure another
- * interrupt will occur.
- */
- COMMAND(port, AcknowledgeInterrupt, interruptLatch);
- status = STATUS(port);
- if((status & interruptMask) == 0)
- break;
-
- if(status & hostError){
- /*
- * Adapter failure, try to find out why, reset if
- * necessary. What happens if Tx is active and a reset
- * occurs, need to retransmit? This probably isn't right.
- */
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- x = ins(port+FifoDiagnostic);
- COMMAND(port, SelectRegisterWindow, Wop);
- print("elnk3#%d: status 0x%uX, diag 0x%uX\n",
- ether->ctlrno, status, x);
-
- if(x & txOverrun){
- COMMAND(port, TxReset, 0);
- COMMAND(port, TxEnable, 0);
- }
-
- if(x & rxUnderrun){
- /*
- * This shouldn't happen...
- * Need to restart any busmastering?
- */
- COMMAND(port, RxReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
- COMMAND(port, RxEnable, 0);
- }
-
- status &= ~hostError;
- }
-
- if(status & (transferInt|rxComplete)){
- receive(ether);
- status &= ~(transferInt|rxComplete);
- }
-
- if(status & txComplete){
- /*
- * Pop the TxStatus stack, accumulating errors.
- * Adjust the TX start threshold if there was an underrun.
- * If there was a Jabber or Underrun error, reset
- * the transmitter.
- * For all conditions enable the transmitter.
- */
- txstatus = 0;
- do{
- if(x = inb(port+TxStatus))
- outb(port+TxStatus, 0);
- txstatus |= x;
- }while(STATUS(port) & txComplete);
-
- if(txstatus & txUnderrun){
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- while(ins(port+MediaStatus) & txInProg)
- ;
- COMMAND(port, SelectRegisterWindow, Wop);
- if(ctlr->txthreshold < ETHERMAXTU)
- ctlr->txthreshold += ETHERMINTU;
- }
-
- if(txstatus & (txJabber|txUnderrun)){
- COMMAND(port, TxReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
- COMMAND(port, SetTxStartThresh, ctlr->txthreshold);
- }
- COMMAND(port, TxEnable, 0);
- status &= ~txComplete;
- status |= txAvailable;
- }
-
- if(status & txAvailable){
- COMMAND(port, AcknowledgeInterrupt, txAvailable);
- transmit(ether);
- status &= ~txAvailable;
- }
-
- if(status & updateStats){
- statistics(ether);
- status &= ~updateStats;
- }
-
- /*
- * Panic if there are any interrupts not dealt with.
- */
- if(status & interruptMask)
- panic("elnk3#%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
- }
-
- COMMAND(port, SelectRegisterWindow, w);
-}
-
-typedef struct Adapter {
- int port;
- int irq;
- int tbdf;
-} Adapter;
-static Block* adapter;
-
-static void
-tcmadapter(int port, int irq, int tbdf)
-{
- Block *bp;
- Adapter *ap;
-
- bp = allocb(sizeof(Adapter));
- ap = (Adapter*)bp->rp;
- ap->port = port;
- ap->irq = irq;
- ap->tbdf = tbdf;
-
- bp->next = adapter;
- adapter = bp;
-}
-
-/*
- * Write two 0 bytes to identify the IDport and then reset the
- * ID sequence. Then send the ID sequence to the card to get
- * the card into command state.
- */
-static void
-idseq(void)
-{
- int i;
- uchar al;
- static int reset, untag;
-
- /*
- * One time only:
- * reset any adapters listening
- */
- if(reset == 0){
- outb(IDport, 0);
- outb(IDport, 0);
- outb(IDport, 0xC0);
- delay(20);
- reset = 1;
- }
-
- outb(IDport, 0);
- outb(IDport, 0);
- for(al = 0xFF, i = 0; i < 255; i++){
- outb(IDport, al);
- if(al & 0x80){
- al <<= 1;
- al ^= 0xCF;
- }
- else
- al <<= 1;
- }
-
- /*
- * One time only:
- * write ID sequence to get the attention of all adapters;
- * untag all adapters.
- * If we do a global reset here on all adapters we'll confuse any
- * ISA cards configured for EISA mode.
- */
- if(untag == 0){
- outb(IDport, 0xD0);
- untag = 1;
- }
-}
-
-static ulong
-activate(void)
-{
- int i;
- ushort x, acr;
-
- /*
- * Do the little configuration dance:
- *
- * 2. write the ID sequence to get to command state.
- */
- idseq();
-
- /*
- * 3. Read the Manufacturer ID from the EEPROM.
- * This is done by writing the IDPort with 0x87 (0x80
- * is the 'read EEPROM' command, 0x07 is the offset of
- * the Manufacturer ID field in the EEPROM).
- * The data comes back 1 bit at a time.
- * We seem to need a delay here between reading the bits.
- *
- * If the ID doesn't match, there are no more adapters.
- */
- outb(IDport, 0x87);
- delay(20);
- for(x = 0, i = 0; i < 16; i++){
- delay(20);
- x <<= 1;
- x |= inb(IDport) & 0x01;
- }
- if(x != 0x6D50)
- return 0;
-
- /*
- * 3. Read the Address Configuration from the EEPROM.
- * The Address Configuration field is at offset 0x08 in the EEPROM).
- */
- outb(IDport, 0x88);
- for(acr = 0, i = 0; i < 16; i++){
- delay(20);
- acr <<= 1;
- acr |= inb(IDport) & 0x01;
- }
-
- return (acr & 0x1F)*0x10 + 0x200;
-}
-
-#ifdef notjustpcmcia
-static void
-tcm509isa(void)
-{
- int irq, port;
-
- /*
- * Attempt to activate all adapters. If adapter is set for
- * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
- * it fully.
- */
- while(port = activate()){
- /*
- * 6. Tag the adapter so it won't respond in future.
- */
- outb(IDport, 0xD1);
- if(port == 0x3F0)
- continue;
-
- /*
- * 6. Activate the adapter by writing the Activate command
- * (0xFF).
- */
- outb(IDport, 0xFF);
- delay(20);
-
- /*
- * 8. Can now talk to the adapter's I/O base addresses.
- * Use the I/O base address from the acr just read.
- *
- * Enable the adapter and clear out any lingering status
- * and interrupts.
- */
- while(STATUS(port) & commandInProgress)
- ;
- COMMAND(port, SelectRegisterWindow, Wsetup);
- outs(port+ConfigControl, Ena);
-
- COMMAND(port, TxReset, 0);
- COMMAND(port, RxReset, 0);
- COMMAND(port, AcknowledgeInterrupt, 0xFF);
-
- irq = (ins(port+ResourceConfig)>>12) & 0x0F;
- tcmadapter(port, irq, BUSUNKNOWN);
- }
-}
-
-static void
-tcm5XXeisa(void)
-{
- ushort x;
- int irq, port, slot;
-
- /*
- * Check if this is an EISA machine.
- * If not, nothing to do.
- */
- if(strncmp((char*)(KZERO|0xFFFD9), "EISA", 4))
- return;
-
- /*
- * Continue through the EISA slots looking for a match on both
- * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
- * If an adapter is found, select window 0, enable it and clear
- * out any lingering status and interrupts.
- */
- for(slot = 1; slot < MaxEISA; slot++){
- port = slot*0x1000;
- if(ins(port+0xC80+ManufacturerID) != 0x6D50)
- continue;
- x = ins(port+0xC80+ProductID);
- if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900)
- continue;
-
- COMMAND(port, SelectRegisterWindow, Wsetup);
- outs(port+ConfigControl, Ena);
-
- COMMAND(port, TxReset, 0);
- COMMAND(port, RxReset, 0);
- COMMAND(port, AcknowledgeInterrupt, 0xFF);
-
- irq = (ins(port+ResourceConfig)>>12) & 0x0F;
- tcmadapter(port, irq, BUSUNKNOWN);
- }
-}
-
-static void
-tcm59Xpci(void)
-{
- Pcidev *p;
- int irq, port;
-
- p = nil;
- while(p = pcimatch(p, 0x10B7, 0)){
- port = p->mem[0].bar & ~0x01;
- irq = p->intl;
- COMMAND(port, GlobalReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
-
- tcmadapter(port, irq, p->tbdf);
- }
-}
-#endif /* notjustpcmcia */
-
-static char* tcmpcmcia[] = {
- "3C589", /* 3COM 589[ABCD] */
- "3C562", /* 3COM 562 */
- "589E", /* 3COM Megahertz 589E */
- nil,
-};
-
-static int
-tcm5XXpcmcia(Ether* ether)
-{
- int i;
-
- for(i = 0; tcmpcmcia[i] != nil; i++){
- if(!cistrcmp(ether->type, tcmpcmcia[i]))
- return ether->port;
- }
-
- return 0;
-}
-
-static int
-autoselect(int port, int rxstatus9)
-{
- int media, x;
-
- /*
- * Pathetic attempt at automatic media selection.
- * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
- * cards operational.
- */
- media = auiAvailable|coaxAvailable|base10TAvailable;
- if(rxstatus9 == 0){
- COMMAND(port, SelectRegisterWindow, Wfifo);
- media = ins(port+ResetOptions);
- }
-
- if(media & miiConnector)
- return xcvrMii;
-
- if(media & baseTXAvailable){
- /*
- * Must have InternalConfig register.
- */
- COMMAND(port, SelectRegisterWindow, Wfifo);
- x = inl(port+InternalConfig) & ~xcvrMask;
- x |= xcvr100BaseTX;
- outl(port+InternalConfig, x);
- COMMAND(port, TxReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
- COMMAND(port, RxReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
-
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
- outs(port+MediaStatus, linkBeatEnable|x);
- delay(10);
-
-{ int i, v;
- for(i = 0; i < 10000; i++){
- v = ins(port+MediaStatus);
- if(v & linkBeatDetect){
- print("count %d v %uX\n", i, v);
- return xcvr100BaseTX;
- }
- delay(1);
- }
-print("count %d v %uX\n", i, ins(port+MediaStatus));
-}
- if(ins(port+MediaStatus) & linkBeatDetect)
- return xcvr100BaseTX;
- outs(port+MediaStatus, x);
- }
-
- if(media & base10TAvailable){
- if(rxstatus9 == 0){
- COMMAND(port, SelectRegisterWindow, Wfifo);
- x = inl(port+InternalConfig) & ~xcvrMask;
- x |= xcvr10BaseT;
- outl(port+InternalConfig, x);
- }
- else{
- COMMAND(port, SelectRegisterWindow, Wsetup);
- x = ins(port+AddressConfig) & ~xcvrMask9;
- x |= (xcvr10BaseT>>20)<<14;
- outs(port+AddressConfig, x);
- }
- COMMAND(port, TxReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
- COMMAND(port, RxReset, 0);
- while(STATUS(port) & commandInProgress)
- ;
-
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- x = ins(port+MediaStatus) & ~dcConverterEnabled;
- outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
- delay(10);
-
- if(ins(port+MediaStatus) & linkBeatDetect)
- return xcvr10BaseT;
- outs(port+MediaStatus, x);
- }
-
- /*
- * Botch.
- */
- return autoSelect;
-}
-
-static int
-eepromdata(int port, int offset)
-{
- COMMAND(port, SelectRegisterWindow, Wsetup);
- while(EEPROMBUSY(port))
- ;
- EEPROMCMD(port, EepromReadRegister, offset);
- while(EEPROMBUSY(port))
- ;
- return EEPROMDATA(port);
-}
-
-int
-elnk3reset(Ether* ether)
-{
- int did, i, port, rxstatus9, x, xcvr;
- Block *bp, **bpp;
- Adapter *ap;
- uchar ea[Eaddrlen];
- Ctlr *ctlr;
-#ifdef notjustpcmcia
- static int scandone;
-
- /*
- * Scan for adapter on PCI, EISA and finally
- * using the little ISA configuration dance.
- */
- if(scandone == 0){
- tcm59Xpci();
- tcm5XXeisa();
- tcm509isa();
- scandone = 1;
- }
-#endif /* notjustpcmcia */
-
- /*
- * Any adapter matches if no ether->port is supplied,
- * otherwise the ports must match.
- */
- port = 0;
- bpp = &adapter;
- for(bp = *bpp; bp; bp = bp->next){
- ap = (Adapter*)bp->rp;
- if(ether->port == 0 || ether->port == ap->port){
- port = ap->port;
- ether->irq = ap->irq;
- ether->tbdf = ap->tbdf;
- *bpp = bp->next;
- freeb(bp);
- break;
- }
- bpp = &bp->next;
- }
- if(port == 0 && (port = tcm5XXpcmcia(ether)) == 0)
- return -1;
-
- /*
- * Read the DeviceID from the EEPROM, it's at offset 0x03,
- * and do something depending on capabilities.
- */
- switch(did = eepromdata(port, 0x03)){
-
- case 0x9000:
- case 0x9001:
- case 0x9050:
- case 0x9051:
- if(BUSTYPE(ether->tbdf) != BusPCI)
- goto buggery;
- goto vortex;
-
- case 0x5900:
- case 0x5920:
- case 0x5950:
- case 0x5951:
- case 0x5952:
- case 0x5970:
- case 0x5971:
- case 0x5972:
- vortex:
- COMMAND(port, SelectRegisterWindow, Wfifo);
- xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
- rxstatus9 = 0;
- break;
-
- buggery:
- default:
- COMMAND(port, SelectRegisterWindow, Wsetup);
- x = ins(port+AddressConfig);
- xcvr = ((x & xcvrMask9)>>14)<<20;
- if(x & autoSelect9)
- xcvr |= autoSelect;
- rxstatus9 = 1;
- break;
- }
- USED(did);
-
- /*
- * Check if the adapter's station address is to be overridden.
- * If not, read it from the EEPROM and set in ether->ea prior to loading the
- * station address in Wstation. The EEPROM returns 16-bits at a time.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, ether->ea, Eaddrlen) == 0){
- for(i = 0; i < Eaddrlen/2; i++){
- x = eepromdata(port, i);
- ether->ea[2*i] = x>>8;
- ether->ea[2*i+1] = x;
- }
- }
-
- COMMAND(port, SelectRegisterWindow, Wstation);
- for(i = 0; i < Eaddrlen; i++)
- outb(port+i, ether->ea[i]);
-
- /*
- * Enable the transceiver if necessary.
- */
- if(xcvr & autoSelect)
- xcvr = autoselect(port, rxstatus9);
- switch(xcvr){
-
- case xcvrMii:
- break;
-
- case xcvr100BaseTX:
- case xcvr100BaseFX:
- COMMAND(port, SelectRegisterWindow, Wfifo);
- x = inl(port+InternalConfig) & ~ramPartitionMask;
- outl(port+InternalConfig, x|ramPartition1to1);
-
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
- x |= linkBeatEnable;
- outs(port+MediaStatus, x);
- break;
-
- case xcvr10BaseT:
- /*
- * Enable Link Beat and Jabber to start the
- * transceiver.
- */
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- x = ins(port+MediaStatus) & ~dcConverterEnabled;
- x |= linkBeatEnable|jabberGuardEnable;
- outs(port+MediaStatus, x);
- break;
-
- case xcvr10Base2:
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
- outs(port+MediaStatus, x);
-
- /*
- * Start the DC-DC converter.
- * Wait > 800 microseconds.
- */
- COMMAND(port, EnableDcConverter, 0);
- delay(1);
- break;
- }
-
- /*
- * Wop is the normal operating register set.
- * The 3C59[0257] adapters allow access to more than one register window
- * at a time, but there are situations where switching still needs to be
- * done, so just do it.
- * Clear out any lingering Tx status.
- */
- COMMAND(port, SelectRegisterWindow, Wop);
- while(inb(port+TxStatus))
- outb(port+TxStatus, 0);
-
- /*
- * Allocate a controller structure and start
- * to initialise it.
- */
- ether->ctlr = malloc(sizeof(Ctlr));
- ctlr = ether->ctlr;
- memset(ctlr, 0, sizeof(Ctlr));
-
- /*
- * Set a base TxStartThresh which will be incremented
- * if any txUnderrun errors occur and ensure no RxEarly
- * interrupts happen.
- */
- ctlr->txthreshold = ETHERMINTU;
- COMMAND(port, SetTxStartThresh, ETHERMINTU);
- COMMAND(port, SetRxEarlyThresh, ETHERMAXTU);
-
- /*
- * Set up the software configuration.
- */
- ether->port = port;
- ether->attach = attach;
- ether->transmit = transmit;
- ether->interrupt = interrupt;
-
- return 0;
-}
--- a/os/boot/pc/etherga620.c
+++ /dev/null
@@ -1,1147 +1,0 @@
-/*
- * bootstrap driver for
- * Netgear GA620 Gigabit Ethernet Card.
- * Specific for the Alteon Tigon 2 and Intel Pentium or later.
- * To Do:
- * cache alignment for PCI Write-and-Invalidate
- * mini ring (what size)?
- * tune coalescing values
- * statistics formatting
- * don't update Spi if nothing to send
- * receive ring alignment
- * watchdog for link management?
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#define malign(n) xspanalloc((n), 32, 0)
-
-#include "etherif.h"
-#include "etherga620fw.h"
-
-enum {
- Mhc = 0x0040, /* Miscellaneous Host Control */
- Mlc = 0x0044, /* Miscellaneous Local Control */
- Mc = 0x0050, /* Miscellaneous Configuration */
- Ps = 0x005C, /* PCI State */
- Wba = 0x0068, /* Window Base Address */
- Wd = 0x006C, /* Window Data */
-
- DMAas = 0x011C, /* DMA Assist State */
-
- CPUAstate = 0x0140, /* CPU A State */
- CPUApc = 0x0144, /* CPU A Programme Counter */
-
- CPUBstate = 0x0240, /* CPU B State */
-
- Hi = 0x0504, /* Host In Interrupt Handler */
- Cpi = 0x050C, /* Command Producer Index */
- Spi = 0x0514, /* Send Producer Index */
- Rspi = 0x051C, /* Receive Standard Producer Index */
- Rjpi = 0x0524, /* Receive Jumbo Producer Index */
- Rmpi = 0x052C, /* Receive Mini Producer Index */
-
- Mac = 0x0600, /* MAC Address */
- Gip = 0x0608, /* General Information Pointer */
- Om = 0x0618, /* Operating Mode */
- DMArc = 0x061C, /* DMA Read Configuration */
- DMAwc = 0x0620, /* DMA Write Configuration */
- Tbr = 0x0624, /* Transmit Buffer Ratio */
- Eci = 0x0628, /* Event Consumer Index */
- Cci = 0x062C, /* Command Consumer Index */
-
- Rct = 0x0630, /* Receive Coalesced Ticks */
- Sct = 0x0634, /* Send Coalesced Ticks */
- St = 0x0638, /* Stat Ticks */
- SmcBD = 0x063C, /* Send Max. Coalesced BDs */
- RmcBD = 0x0640, /* Receive Max. Coalesced BDs */
- Nt = 0x0644, /* NIC Tracing */
- Gln = 0x0648, /* Gigabit Link Negotiation */
- Fln = 0x064C, /* 10/100 Link Negotiation */
- Ifx = 0x065C, /* Interface Index */
- IfMTU = 0x0660, /* Interface MTU */
- Mi = 0x0664, /* Mask Interrupts */
- Gls = 0x0668, /* Gigabit Link State */
- Fls = 0x066C, /* 10/100 Link State */
-
- Cr = 0x0700, /* Command Ring */
-
- Lmw = 0x0800, /* Local Memory Window */
-};
-
-enum { /* Mhc */
- Is = 0x00000001, /* Interrupt State */
- Ci = 0x00000002, /* Clear Interrupt */
- Hr = 0x00000008, /* Hard Reset */
- Eebs = 0x00000010, /* Enable Endian Byte Swap */
- Eews = 0x00000020, /* Enable Endian Word (64-bit) swap */
- Mpio = 0x00000040, /* Mask PCI Interrupt Output */
-};
-
-enum { /* Mlc */
- SRAM512 = 0x00000200, /* SRAM Bank Size of 512KB */
- SRAMmask = 0x00000300,
- EEclk = 0x00100000, /* Serial EEPROM Clock Output */
- EEdoe = 0x00200000, /* Serial EEPROM Data Out Enable */
- EEdo = 0x00400000, /* Serial EEPROM Data Out Value */
- EEdi = 0x00800000, /* Serial EEPROM Data Input */
-};
-
-enum { /* Mc */
- SyncSRAM = 0x00100000, /* Set Synchronous SRAM Timing */
-};
-
-enum { /* Ps */
- PCIwm32 = 0x000000C0, /* Write Max DMA 32 */
- PCImrm = 0x00020000, /* Use Memory Read Multiple Command */
- PCI66 = 0x00080000,
- PCI32 = 0x00100000,
- PCIrcmd = 0x06000000, /* PCI Read Command */
- PCIwcmd = 0x70000000, /* PCI Write Command */
-};
-
-enum { /* CPUAstate */
- CPUrf = 0x00000010, /* ROM Fail */
- CPUhalt = 0x00010000, /* Halt the internal CPU */
- CPUhie = 0x00040000, /* HALT instruction executed */
-};
-
-enum { /* Om */
- BswapBD = 0x00000002, /* Byte Swap Buffer Descriptors */
- WswapBD = 0x00000004, /* Word Swap Buffer Descriptors */
- Warn = 0x00000008,
- BswapDMA = 0x00000010, /* Byte Swap DMA Data */
- Only1DMA = 0x00000040, /* Only One DMA Active at a time */
- NoJFrag = 0x00000200, /* Don't Fragment Jumbo Frames */
- Fatal = 0x40000000,
-};
-
-enum { /* Lmw */
- Lmwsz = 2*1024, /* Local Memory Window Size */
-
- /*
- * legal values are 0x3800 iff Nsr is 128, 0x3000 iff Nsr is 256,
- * or 0x2000 iff Nsr is 512.
- */
- Sr = 0x3800, /* Send Ring (accessed via Lmw) */
-};
-
-enum { /* Link */
- Lpref = 0x00008000, /* Preferred Link */
- L10MB = 0x00010000,
- L100MB = 0x00020000,
- L1000MB = 0x00040000,
- Lfd = 0x00080000, /* Full Duplex */
- Lhd = 0x00100000, /* Half Duplex */
- Lefc = 0x00200000, /* Emit Flow Control Packets */
- Lofc = 0x00800000, /* Obey Flow Control Packets */
- Lean = 0x20000000, /* Enable Autonegotiation/Sensing */
- Le = 0x40000000, /* Link Enable */
-};
-
-typedef struct Host64 {
- uint hi;
- uint lo;
-} Host64;
-
-typedef struct Ere { /* Event Ring Element */
- int event; /* event<<24 | code<<12 | index */
- int unused;
-} Ere;
-
-typedef int Cmd; /* cmd<<24 | flags<<12 | index */
-
-typedef struct Rbd { /* Receive Buffer Descriptor */
- Host64 addr;
- int indexlen; /* ring-index<<16 | buffer-length */
- int flags; /* only lower 16-bits */
- int checksum; /* ip<<16 |tcp/udp */
- int error; /* only upper 16-bits */
- int reserved;
- void* opaque; /* passed to receive return ring */
-} Rbd;
-
-typedef struct Sbd { /* Send Buffer Descriptor */
- Host64 addr;
- int lenflags; /* len<<16 |flags */
- int reserved;
-} Sbd;
-
-enum { /* Buffer Descriptor Flags */
- Fend = 0x00000004, /* Frame Ends in this Buffer */
- Frjr = 0x00000010, /* Receive Jumbo Ring Buffer */
- Funicast = 0x00000020, /* Unicast packet (2-bit field) */
- Fmulticast = 0x00000040, /* Multicast packet */
- Fbroadcast = 0x00000060, /* Broadcast packet */
- Ferror = 0x00000400, /* Frame Has Error */
- Frmr = 0x00001000, /* Receive Mini Ring Buffer */
-};
-
-enum { /* Buffer Error Flags */
- Ecrc = 0x00010000, /* bad CRC */
- Ecollision = 0x00020000, /* collision */
- Elink = 0x00040000, /* link lost */
- Ephy = 0x00080000, /* unspecified PHY frame decode error */
- Eodd = 0x00100000, /* odd number of nibbles */
- Emac = 0x00200000, /* unspecified MAC abort */
- Elen64 = 0x00400000, /* short packet */
- Eresources = 0x00800000, /* MAC out of internal resources */
- Egiant = 0x01000000, /* packet too big */
-};
-
-typedef struct Rcb { /* Ring Control Block */
- Host64 addr; /* points to the Rbd ring */
- int control; /* max_len<<16 |flags */
- int unused;
-} Rcb;
-
-enum {
- TcpUdpCksum = 0x0001, /* Perform TCP or UDP checksum */
- IpCksum = 0x0002, /* Perform IP checksum */
- NoPseudoHdrCksum= 0x0008, /* Don't include the pseudo header */
- VlanAssist = 0x0010, /* Enable VLAN tagging */
- CoalUpdateOnly = 0x0020, /* Coalesce transmit interrupts */
- HostRing = 0x0040, /* Sr in host memory */
- SnapCksum = 0x0080, /* Parse + offload 802.3 SNAP frames */
- UseExtRxBd = 0x0100, /* Extended Rbd for Jumbo frames */
- RingDisabled = 0x0200, /* Jumbo or Mini RCB only */
-};
-
-typedef struct Gib { /* General Information Block */
- int statistics[256]; /* Statistics */
- Rcb ercb; /* Event Ring */
- Rcb crcb; /* Command Ring */
- Rcb srcb; /* Send Ring */
- Rcb rsrcb; /* Receive Standard Ring */
- Rcb rjrcb; /* Receive Jumbo Ring */
- Rcb rmrcb; /* Receive Mini Ring */
- Rcb rrrcb; /* Receive Return Ring */
- Host64 epp; /* Event Producer */
- Host64 rrrpp; /* Receive Return Ring Producer */
- Host64 scp; /* Send Consumer */
- Host64 rsp; /* Refresh Stats */
-} Gib;
-
-/*
- * these sizes are all fixed in the card,
- * except for Nsr, which has only 3 valid sizes.
- */
-enum { /* Host/NIC Interface ring sizes */
- Ner = 256, /* event ring */
- Ncr = 64, /* command ring */
- Nsr = 128, /* send ring: 128, 256 or 512 */
- Nrsr = 512, /* receive standard ring */
- Nrjr = 256, /* receive jumbo ring */
- Nrmr = 1024, /* receive mini ring, optional */
- Nrrr = 2048, /* receive return ring */
-};
-
-enum {
- NrsrHI = 72, /* Fill-level of Rsr (m.b. < Nrsr) */
- NrsrLO = 54, /* Level at which to top-up ring */
- NrjrHI = 0, /* Fill-level of Rjr (m.b. < Nrjr) */
- NrjrLO = 0, /* Level at which to top-up ring */
- NrmrHI = 0, /* Fill-level of Rmr (m.b. < Nrmr) */
- NrmrLO = 0, /* Level at which to top-up ring */
-};
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
- int port;
- Pcidev* pcidev;
- Ctlr* next;
- int active;
- int id;
-
- uchar ea[Eaddrlen];
-
- int* nic;
- Gib* gib;
-
- Ere* er;
-
- Lock srlock;
- Sbd* sr;
- Block** srb;
- int nsr; /* currently in send ring */
-
- Rbd* rsr;
- int nrsr; /* currently in Receive Standard Ring */
- Rbd* rjr;
- int nrjr; /* currently in Receive Jumbo Ring */
- Rbd* rmr;
- int nrmr; /* currently in Receive Mini Ring */
- Rbd* rrr;
- int rrrci; /* Receive Return Ring Consumer Index */
-
- int epi[2]; /* Event Producer Index */
- int rrrpi[2]; /* Receive Return Ring Producer Index */
- int sci[3]; /* Send Consumer Index ([2] is host) */
-
- int interrupts; /* statistics */
- int mi;
- uvlong ticks;
-
- int coalupdateonly; /* tuning */
- int hardwarecksum;
- int rct; /* Receive Coalesce Ticks */
- int sct; /* Send Coalesce Ticks */
- int st; /* Stat Ticks */
- int smcbd; /* Send Max. Coalesced BDs */
- int rmcbd; /* Receive Max. Coalesced BDs */
-};
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-#define csr32r(c, r) (*((c)->nic+((r)/4)))
-#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
-
-static void
-sethost64(Host64* host64, void* addr)
-{
- uvlong uvl;
-
- uvl = PCIWADDR(addr);
- host64->hi = uvl>>32;
- host64->lo = uvl & 0xFFFFFFFFL;
-}
-
-static void
-ga620command(Ctlr* ctlr, int cmd, int flags, int index)
-{
- int cpi;
-
- cpi = csr32r(ctlr, Cpi);
- csr32w(ctlr, Cr+(cpi*4), cmd<<24 | flags<<12 | index);
- cpi = NEXT(cpi, Ncr);
- csr32w(ctlr, Cpi, cpi);
-}
-
-static void
-ga620attach(Ether* )
-{
-}
-
-static void
-waitforlink(Ether *edev)
-{
- int i;
-
- if (edev->mbps == 0) {
- print("#l%d: ga620: waiting for link", edev->ctlrno);
- /* usually takes about 10 seconds */
- for (i = 0; i < 20 && edev->mbps == 0; i++) {
- print(".");
- delay(1000);
- }
- print("\n");
- if (i == 20 && edev->mbps == 0)
- edev->mbps = 1; /* buggered */
- }
-}
-
-static void
-toringbuf(Ether *ether, Block *bp)
-{
- RingBuf *rb = ðer->rb[ether->ri];
-
- if (rb->owner == Interface) {
- rb->len = BLEN(bp);
- memmove(rb->pkt, bp->rp, rb->len);
- rb->owner = Host;
- ether->ri = NEXT(ether->ri, ether->nrb);
- }
- /* else no one is expecting packets from the network */
-}
-
-static Block *
-fromringbuf(Ether *ether)
-{
- RingBuf *tb = ðer->tb[ether->ti];
- Block *bp = allocb(tb->len);
-
- if (bp == nil)
- panic("fromringbuf: nil allocb return");
- if (bp->wp == nil)
- panic("fromringbuf: nil bp->wb");
- memmove(bp->wp, tb->pkt, tb->len);
- memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
- bp->wp += tb->len;
- return bp;
-}
-
-static int
-_ga620transmit(Ether* edev)
-{
- Sbd *sbd;
- Block *bp;
- Ctlr *ctlr;
- RingBuf *tb;
- int sci, spi, work;
-
- /*
- * For now there are no smarts here, just empty the
- * ring and try to fill it back up. Tuning comes later.
- */
- ctlr = edev->ctlr;
- waitforlink(edev);
- ilock(&ctlr->srlock);
-
- /*
- * Free any completed packets.
- * Ctlr->sci[0] is where the NIC has got to consuming the ring.
- * Ctlr->sci[2] is where the host has got to tidying up after the
- * NIC has done with the packets.
- */
- work = 0;
- for(sci = ctlr->sci[2]; sci != ctlr->sci[0]; sci = NEXT(sci, Nsr)){
- if(ctlr->srb[sci] == nil)
- continue;
- freeb(ctlr->srb[sci]);
- ctlr->srb[sci] = nil;
- work++;
- }
- ctlr->sci[2] = sci;
-
- sci = PREV(sci, Nsr);
-
- tb = &edev->tb[edev->ti];
- for(spi = csr32r(ctlr, Spi); spi != sci && tb->owner == Interface;
- spi = NEXT(spi, Nsr)){
- bp = fromringbuf(edev);
-
- sbd = &ctlr->sr[spi];
- sethost64(&sbd->addr, bp->rp);
- sbd->lenflags = BLEN(bp)<<16 |Fend;
-
- ctlr->srb[spi] = bp;
- work++;
-
- tb->owner = Host;
- edev->ti = NEXT(edev->ti, edev->ntb);
- tb = &edev->tb[edev->ti];
- }
- csr32w(ctlr, Spi, spi);
-
- iunlock(&ctlr->srlock);
-
- return work;
-}
-
-static void
-ga620transmit(Ether* edev)
-{
- _ga620transmit(edev);
-}
-
-static void
-ga620replenish(Ctlr* ctlr)
-{
- Rbd *rbd;
- int rspi;
- Block *bp;
-
- rspi = csr32r(ctlr, Rspi);
- while(ctlr->nrsr < NrsrHI){
- if((bp = allocb(ETHERMAXTU+4)) == nil)
- break;
- rbd = &ctlr->rsr[rspi];
- sethost64(&rbd->addr, bp->rp);
- rbd->indexlen = rspi<<16 | (ETHERMAXTU+4);
- rbd->flags = 0;
- rbd->opaque = bp;
-
- rspi = NEXT(rspi, Nrsr);
- ctlr->nrsr++;
- }
- csr32w(ctlr, Rspi, rspi);
-}
-
-static void
-ga620event(Ether *edev, int eci, int epi)
-{
- unsigned event, code;
- Ctlr *ctlr;
-
- ctlr = edev->ctlr;
- while(eci != epi){
- event = ctlr->er[eci].event;
- code = (event >> 12) & ((1<<12)-1);
- switch(event>>24){
- case 0x01: /* firmware operational */
- /* host stack (us) is up. 3rd arg of 2 means down. */
- ga620command(ctlr, 0x01, 0x01, 0x00);
- /*
- * link negotiation: any speed is okay.
- * 3rd arg of 1 selects gigabit only; 2 10/100 only.
- */
- ga620command(ctlr, 0x0B, 0x00, 0x00);
- print("#l%d: ga620: port %8.8uX: firmware is up\n",
- edev->ctlrno, ctlr->port);
- break;
- case 0x04: /* statistics updated */
- break;
- case 0x06: /* link state changed */
- switch (code) {
- case 1:
- edev->mbps = 1000;
- break;
- case 2:
- print("#l%d: link down\n", edev->ctlrno);
- break;
- case 3:
- edev->mbps = 100; /* it's 10 or 100 */
- break;
- }
- if (code != 2)
- print("#l%d: %dMbps link up\n",
- edev->ctlrno, edev->mbps);
- break;
- case 0x07: /* event error */
- default:
- print("#l%d: ga620: er[%d] = %8.8uX\n", edev->ctlrno,
- eci, event);
- break;
- }
- eci = NEXT(eci, Ner);
- }
- csr32w(ctlr, Eci, eci);
-}
-
-static void
-ga620receive(Ether* edev)
-{
- int len;
- Rbd *rbd;
- Block *bp;
- Ctlr* ctlr;
-
- ctlr = edev->ctlr;
- while(ctlr->rrrci != ctlr->rrrpi[0]){
- rbd = &ctlr->rrr[ctlr->rrrci];
- /*
- * Errors are collected in the statistics block so
- * no need to tally them here, let ifstat do the work.
- */
- len = rbd->indexlen & 0xFFFF;
- if(!(rbd->flags & Ferror) && len != 0){
- bp = rbd->opaque;
- bp->wp = bp->rp+len;
-
- toringbuf(edev, bp);
- } else
- freeb(rbd->opaque);
- rbd->opaque = nil;
-
- if(rbd->flags & Frjr)
- ctlr->nrjr--;
- else if(rbd->flags & Frmr)
- ctlr->nrmr--;
- else
- ctlr->nrsr--;
-
- ctlr->rrrci = NEXT(ctlr->rrrci, Nrrr);
- }
-}
-
-static void
-ga620interrupt(Ureg*, void* arg)
-{
- int csr, ie, work;
- Ctlr *ctlr;
- Ether *edev;
-
- edev = arg;
- ctlr = edev->ctlr;
-
- if(!(csr32r(ctlr, Mhc) & Is))
- return;
-
- ctlr->interrupts++;
- csr32w(ctlr, Hi, 1);
-
- ie = 0;
- work = 0;
- while(ie < 2){
- if(ctlr->rrrci != ctlr->rrrpi[0]){
- ga620receive(edev);
- work = 1;
- }
-
- if(_ga620transmit(edev) != 0)
- work = 1;
-
- csr = csr32r(ctlr, Eci);
- if(csr != ctlr->epi[0]){
- ga620event(edev, csr, ctlr->epi[0]);
- work = 1;
- }
-
- if(ctlr->nrsr <= NrsrLO)
- ga620replenish(ctlr);
- if(work == 0){
- if(ie == 0)
- csr32w(ctlr, Hi, 0);
- ie++;
- }
- work = 0;
- }
-}
-
-static void
-ga620lmw(Ctlr* ctlr, int addr, int* data, int len)
-{
- int i, l, lmw, v;
-
- /*
- * Write to or clear ('data' == nil) 'len' bytes of the NIC
- * local memory at address 'addr'.
- * The destination address and count should be 32-bit aligned.
- */
- v = 0;
- while(len > 0){
- /*
- * 1) Set the window. The (Lmwsz-1) bits are ignored
- * in Wba when accessing through the local memory window;
- * 2) Find the minimum of how many bytes still to
- * transfer and how many left in this window;
- * 3) Create the offset into the local memory window in the
- * shared memory space then copy (or zero) the data;
- * 4) Bump the counts.
- */
- csr32w(ctlr, Wba, addr);
-
- l = ROUNDUP(addr+1, Lmwsz) - addr;
- if(l > len)
- l = len;
-
- lmw = Lmw + (addr & (Lmwsz-1));
- for(i = 0; i < l; i += 4){
- if(data != nil)
- v = *data++;
- csr32w(ctlr, lmw+i, v);
- }
-
- len -= l;
- addr += l;
- }
-}
-
-static int
-ga620init(Ether* edev)
-{
- Ctlr *ctlr;
- Host64 host64;
- int csr, ea, i, flags;
-
- ctlr = edev->ctlr;
-
- /*
- * Load the MAC address.
- */
- ea = edev->ea[0]<<8 | edev->ea[1];
- csr32w(ctlr, Mac, ea);
- ea = edev->ea[2]<<24 | edev->ea[3]<<16 | edev->ea[4]<<8 | edev->ea[5];
- csr32w(ctlr, Mac+4, ea);
-
- /*
- * General Information Block.
- */
- ctlr->gib = malloc(sizeof(Gib));
- sethost64(&host64, ctlr->gib);
- csr32w(ctlr, Gip, host64.hi);
- csr32w(ctlr, Gip+4, host64.lo);
-
- /*
- * Event Ring.
- * This is located in host memory. Allocate the ring,
- * tell the NIC where it is and initialise the indices.
- */
- ctlr->er = malign(sizeof(Ere)*Ner);
- sethost64(&ctlr->gib->ercb.addr, ctlr->er);
- sethost64(&ctlr->gib->epp, ctlr->epi);
- csr32w(ctlr, Eci, 0);
-
- /*
- * Command Ring.
- * This is located in the General Communications Region
- * and so the value placed in the Rcb is unused, the NIC
- * knows where it is. Stick in the value according to
- * the datasheet anyway.
- * Initialise the ring and indices.
- */
- ctlr->gib->crcb.addr.lo = Cr - 0x400;
- for(i = 0; i < Ncr*4; i += 4)
- csr32w(ctlr, Cr+i, 0);
- csr32w(ctlr, Cpi, 0);
- csr32w(ctlr, Cci, 0);
-
- /*
- * Send Ring.
- * This ring is either in NIC memory at a fixed location depending
- * on how big the ring is or it is in host memory. If in NIC
- * memory it is accessed via the Local Memory Window; with a send
- * ring size of 128 the window covers the whole ring and then need
- * only be set once:
- * ctlr->sr = (uchar*)ctlr->nic+Lmw;
- * ga620lmw(ctlr, Sr, nil, sizeof(Sbd)*Nsr);
- * ctlr->gib->srcb.addr.lo = Sr;
- * There is nowhere in the Sbd to hold the Block* associated
- * with this entry so an external array must be kept.
- */
- ctlr->sr = malign(sizeof(Sbd)*Nsr);
- sethost64(&ctlr->gib->srcb.addr, ctlr->sr);
- if(ctlr->hardwarecksum)
- flags = TcpUdpCksum|NoPseudoHdrCksum|HostRing;
- else
- flags = HostRing;
- if(ctlr->coalupdateonly)
- flags |= CoalUpdateOnly;
- ctlr->gib->srcb.control = Nsr<<16 | flags;
- sethost64(&ctlr->gib->scp, ctlr->sci);
- csr32w(ctlr, Spi, 0);
- ctlr->srb = malloc(sizeof(Block*)*Nsr);
-
- /*
- * Receive Standard Ring.
- */
- ctlr->rsr = malign(sizeof(Rbd)*Nrsr);
- sethost64(&ctlr->gib->rsrcb.addr, ctlr->rsr);
- if(ctlr->hardwarecksum)
- flags = TcpUdpCksum|NoPseudoHdrCksum;
- else
- flags = 0;
- ctlr->gib->rsrcb.control = (ETHERMAXTU+4)<<16 | flags;
- csr32w(ctlr, Rspi, 0);
-
- /*
- * Jumbo and Mini Rings. Unused for now.
- */
- ctlr->gib->rjrcb.control = RingDisabled;
- ctlr->gib->rmrcb.control = RingDisabled;
-
- /*
- * Receive Return Ring.
- * This is located in host memory. Allocate the ring,
- * tell the NIC where it is and initialise the indices.
- */
- ctlr->rrr = malign(sizeof(Rbd)*Nrrr);
- sethost64(&ctlr->gib->rrrcb.addr, ctlr->rrr);
- ctlr->gib->rrrcb.control = Nrrr<<16 | 0;
- sethost64(&ctlr->gib->rrrpp, ctlr->rrrpi);
- ctlr->rrrci = 0;
-
- /*
- * Refresh Stats Pointer.
- * For now just point it at the existing statistics block.
- */
- sethost64(&ctlr->gib->rsp, ctlr->gib->statistics);
-
- /*
- * DMA configuration.
- * Use the recommended values.
- */
- csr32w(ctlr, DMArc, 0x80);
- csr32w(ctlr, DMAwc, 0x80);
-
- /*
- * Transmit Buffer Ratio.
- * Set to 1/3 of available buffer space (units are 1/64ths)
- * if using Jumbo packets, ~64KB otherwise (assume 1MB on NIC).
- */
- if(NrjrHI > 0 || Nsr > 128)
- csr32w(ctlr, Tbr, 64/3);
- else
- csr32w(ctlr, Tbr, 4);
-
- /*
- * Tuneable parameters.
- * These defaults are based on the tuning hints in the Alteon
- * Host/NIC Software Interface Definition and example software.
- */
- ctlr->rct = 1 /*100*/;
- csr32w(ctlr, Rct, ctlr->rct);
- ctlr->sct = 0;
- csr32w(ctlr, Sct, ctlr->sct);
- ctlr->st = 1000000;
- csr32w(ctlr, St, ctlr->st);
- ctlr->smcbd = Nsr/4;
- csr32w(ctlr, SmcBD, ctlr->smcbd);
- ctlr->rmcbd = 4 /*6*/;
- csr32w(ctlr, RmcBD, ctlr->rmcbd);
-
- /*
- * Enable DMA Assist Logic.
- */
- csr = csr32r(ctlr, DMAas) & ~0x03;
- csr32w(ctlr, DMAas, csr|0x01);
-
- /*
- * Link negotiation.
- * The bits are set here but the NIC must be given a command
- * once it is running to set negotiation in motion.
- */
- csr32w(ctlr, Gln, Le|Lean|Lofc|Lfd|L1000MB|Lpref);
- csr32w(ctlr, Fln, Le|Lean|Lhd|Lfd|L100MB|L10MB);
-
- /*
- * A unique index for this controller and the maximum packet
- * length expected.
- * For now only standard packets are expected.
- */
- csr32w(ctlr, Ifx, 1);
- csr32w(ctlr, IfMTU, ETHERMAXTU+4);
-
- /*
- * Enable Interrupts.
- * There are 3 ways to mask interrupts - a bit in the Mhc (which
- * is already cleared), the Mi register and the Hi mailbox.
- * Writing to the Hi mailbox has the side-effect of clearing the
- * PCI interrupt.
- */
- csr32w(ctlr, Mi, 0);
- csr32w(ctlr, Hi, 0);
-
- /*
- * Start the firmware.
- */
- csr32w(ctlr, CPUApc, tigon2FwStartAddr);
- csr = csr32r(ctlr, CPUAstate) & ~CPUhalt;
- csr32w(ctlr, CPUAstate, csr);
-
- return 0;
-}
-
-static int
-at24c32io(Ctlr* ctlr, char* op, int data)
-{
- char *lp, *p;
- int i, loop, mlc, r;
-
- mlc = csr32r(ctlr, Mlc);
-
- r = 0;
- loop = -1;
- lp = nil;
- for(p = op; *p != '\0'; p++){
- switch(*p){
- default:
- return -1;
- case ' ':
- continue;
- case ':': /* start of 8-bit loop */
- if(lp != nil)
- return -1;
- lp = p;
- loop = 7;
- continue;
- case ';': /* end of 8-bit loop */
- if(lp == nil)
- return -1;
- loop--;
- if(loop >= 0)
- p = lp;
- else
- lp = nil;
- continue;
- case 'C': /* assert clock */
- mlc |= EEclk;
- break;
- case 'c': /* deassert clock */
- mlc &= ~EEclk;
- break;
- case 'D': /* next bit in 'data' byte */
- if(loop < 0)
- return -1;
- if(data & (1<<loop))
- mlc |= EEdo;
- else
- mlc &= ~EEdo;
- break;
- case 'E': /* enable data output */
- mlc |= EEdoe;
- break;
- case 'e': /* disable data output */
- mlc &= ~EEdoe;
- break;
- case 'I': /* input bit */
- i = (csr32r(ctlr, Mlc) & EEdi) != 0;
- if(loop >= 0)
- r |= (i<<loop);
- else
- r = i;
- continue;
- case 'O': /* assert data output */
- mlc |= EEdo;
- break;
- case 'o': /* deassert data output */
- mlc &= ~EEdo;
- break;
- }
- csr32w(ctlr, Mlc, mlc);
- microdelay(1);
- }
- if(loop >= 0)
- return -1;
- return r;
-}
-
-static int
-at24c32r(Ctlr* ctlr, int addr)
-{
- int data;
-
- /*
- * Read a byte at address 'addr' from the Atmel AT24C32
- * Serial EEPROM. The 2-wire EEPROM access is controlled
- * by 4 bits in Mlc. See the AT24C32 datasheet for
- * protocol details.
- */
- /*
- * Start condition - a high to low transition of data
- * with the clock high must precede any other command.
- */
- at24c32io(ctlr, "OECoc", 0);
-
- /*
- * Perform a random read at 'addr'. A dummy byte
- * write sequence is performed to clock in the device
- * and data word addresses (0 and 'addr' respectively).
- */
- data = -1;
- if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA0) != 0)
- goto stop;
- if(at24c32io(ctlr, "oE :DCc; oeCIc", addr>>8) != 0)
- goto stop;
- if(at24c32io(ctlr, "oE :DCc; oeCIc", addr) != 0)
- goto stop;
-
- /*
- * Now send another start condition followed by a
- * request to read the device. The EEPROM responds
- * by clocking out the data.
- */
- at24c32io(ctlr, "OECoc", 0);
- if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA1) != 0)
- goto stop;
- data = at24c32io(ctlr, ":CIc;", 0xA1);
-
-stop:
- /*
- * Stop condition - a low to high transition of data
- * with the clock high is a stop condition. After a read
- * sequence, the stop command will place the EEPROM in
- * a standby power mode.
- */
- at24c32io(ctlr, "oECOc", 0);
-
- return data;
-}
-
-static int
-ga620detach(Ctlr* ctlr)
-{
- int timeo;
-
- /*
- * Hard reset (don't know which endian so catch both);
- * enable for little-endian mode;
- * wait for code to be loaded from serial EEPROM or flash;
- * make sure CPU A is halted.
- */
- csr32w(ctlr, Mhc, Hr<<24 | Hr);
- csr32w(ctlr, Mhc, (Eews|Ci)<<24 | Eews|Ci);
-
- microdelay(1);
- for(timeo = 0; timeo < 500000; timeo++){
- if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) == CPUhie)
- break;
- microdelay(1);
- }
- if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) != CPUhie)
- return -1;
- csr32w(ctlr, CPUAstate, CPUhalt);
-
- /*
- * After reset, CPU B seems to be stuck in 'CPUrf'.
- * Worry about it later.
- */
- csr32w(ctlr, CPUBstate, CPUhalt);
-
- return 0;
-}
-
-static void
-ga620shutdown(Ether* ether)
-{
-print("ga620shutdown\n");
- ga620detach(ether->ctlr);
-}
-
-static int
-ga620reset(Ctlr* ctlr)
-{
- int cls, csr, i, r;
-
- if(ga620detach(ctlr) < 0)
- return -1;
-
- /*
- * Tigon 2 PCI NICs have 512KB SRAM per bank.
- * Clear out any lingering serial EEPROM state
- * bits.
- */
- csr = csr32r(ctlr, Mlc) & ~(EEdi|EEdo|EEdoe|EEclk|SRAMmask);
- csr32w(ctlr, Mlc, SRAM512|csr);
- csr = csr32r(ctlr, Mc);
- csr32w(ctlr, Mc, SyncSRAM|csr);
-
- /*
- * Initialise PCI State register.
- * If PCI Write-and-Invalidate is enabled set the max write DMA
- * value to the host cache-line size (32 on Pentium or later).
- */
- csr = csr32r(ctlr, Ps) & (PCI32|PCI66);
- csr |= PCIwcmd|PCIrcmd|PCImrm;
- if(ctlr->pcidev->pcr & 0x0010){
- cls = pcicfgr8(ctlr->pcidev, PciCLS) * 4;
- if(cls != 32)
- pcicfgw8(ctlr->pcidev, PciCLS, 32/4);
- csr |= PCIwm32;
- }
- csr32w(ctlr, Ps, csr);
-
- /*
- * Operating Mode.
- */
- csr32w(ctlr, Om, Fatal|NoJFrag|BswapDMA|WswapBD);
-
- /*
- * Snarf the MAC address from the serial EEPROM.
- */
- for(i = 0; i < Eaddrlen; i++){
- if((r = at24c32r(ctlr, 0x8E+i)) == -1)
- return -1;
- ctlr->ea[i] = r;
- }
-
- /*
- * Load the firmware.
- */
- ga620lmw(ctlr, tigon2FwTextAddr, tigon2FwText, tigon2FwTextLen);
- ga620lmw(ctlr, tigon2FwRodataAddr, tigon2FwRodata, tigon2FwRodataLen);
- ga620lmw(ctlr, tigon2FwDataAddr, tigon2FwData, tigon2FwDataLen);
- ga620lmw(ctlr, tigon2FwSbssAddr, nil, tigon2FwSbssLen);
- ga620lmw(ctlr, tigon2FwBssAddr, nil, tigon2FwBssLen);
-
- /*
- * we will eventually get events telling us that the firmware is
- * up and that the link is up.
- */
- return 0;
-}
-
-static void
-ga620pci(void)
-{
- int port;
- Pcidev *p;
- Ctlr *ctlr;
-
- p = nil;
- while(p = pcimatch(p, 0, 0)){
- if(p->ccrb != 0x02 || p->ccru != 0)
- continue;
-
- switch(p->did<<16 | p->vid){
- default:
- continue;
- case 0x620A<<16 | 0x1385: /* Netgear GA620 fiber */
- case 0x630A<<16 | 0x1385: /* Netgear GA620T copper */
- case 0x0001<<16 | 0x12AE: /* Alteon Acenic fiber
- * and DEC DEGPA-SA */
- case 0x0002<<16 | 0x12AE: /* Alteon Acenic copper */
- case 0x0009<<16 | 0x10A9: /* SGI Acenic */
- break;
- }
-
- port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
- if(port == 0){
- print("ga620: can't map %d @ 0x%8.8luX\n",
- p->mem[0].size, p->mem[0].bar);
- continue;
- }
-
- ctlr = malloc(sizeof(Ctlr));
- ctlr->port = port;
- ctlr->pcidev = p;
- ctlr->id = p->did<<16 | p->vid;
-
- ctlr->nic = KADDR(ctlr->port);
- if(ga620reset(ctlr)){
- free(ctlr);
- continue;
- }
-
- if(ctlrhead != nil)
- ctlrtail->next = ctlr;
- else
- ctlrhead = ctlr;
- ctlrtail = ctlr;
- }
-}
-
-int
-ga620pnp(Ether* edev)
-{
- Ctlr *ctlr;
- uchar ea[Eaddrlen];
-
- if(ctlrhead == nil)
- ga620pci();
-
- /*
- * Any adapter matches if no edev->port is supplied,
- * otherwise the ports must match.
- */
- for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
- if(ctlr->active)
- continue;
- if(edev->port == 0 || edev->port == ctlr->port){
- ctlr->active = 1;
- break;
- }
- }
- if(ctlr == nil)
- return -1;
-
- edev->ctlr = ctlr;
- edev->port = ctlr->port;
- edev->irq = ctlr->pcidev->intl;
- edev->tbdf = ctlr->pcidev->tbdf;
-
- /*
- * Check if the adapter's station address is to be overridden.
- * If not, read it from the EEPROM and set in ether->ea prior to
- * loading the station address in the hardware.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, edev->ea, Eaddrlen) == 0)
- memmove(edev->ea, ctlr->ea, Eaddrlen);
-
- ga620init(edev); /* enables interrupts */
-
- /*
- * Linkage to the generic ethernet driver.
- */
- edev->attach = ga620attach;
- edev->transmit = ga620transmit;
- edev->interrupt = ga620interrupt;
- edev->detach = ga620shutdown;
- return 0;
-}
--- a/os/boot/pc/etherga620fw.h
+++ /dev/null
@@ -1,4858 +1,0 @@
-/* Generated by genfw.c */
-#define tigon2FwReleaseMajor 0xc
-#define tigon2FwReleaseMinor 0x4
-#define tigon2FwReleaseFix 0xb
-#define tigon2FwStartAddr 0x00004000
-#define tigon2FwTextAddr 0x00004000
-#define tigon2FwTextLen 0x11bc0
-#define tigon2FwRodataAddr 0x00015bc0
-#define tigon2FwRodataLen 0x10d0
-#define tigon2FwDataAddr 0x00016cc0
-#define tigon2FwDataLen 0x1c0
-#define tigon2FwSbssAddr 0x00016e80
-#define tigon2FwSbssLen 0xcc
-#define tigon2FwBssAddr 0x00016f50
-#define tigon2FwBssLen 0x20c0
-static int tigon2FwText[/*(MAX_TEXT_LEN/4) + 1*/] = {
-0x0,
-0x10000003, 0x0, 0xd, 0xd,
-0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 0x3c100000,
-0x26104000, 0xc0010c0, 0x0, 0xd,
-0x3c1d0001, 0x8fbd6d24, 0x3a0f021, 0x3c100000,
-0x26104000, 0xc0017e0, 0x0, 0xd,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x2000008,
-0x0, 0x800172f, 0x3c0a0001, 0x800172f,
-0x3c0a0002, 0x800172f, 0x0, 0x8002cac,
-0x0, 0x8002c4f, 0x0, 0x800172f,
-0x3c0a0004, 0x800328a, 0x0, 0x8001a52,
-0x0, 0x800394d, 0x0, 0x80038f4,
-0x0, 0x800172f, 0x3c0a0006, 0x80039bb,
-0x3c0a0007, 0x800172f, 0x3c0a0008, 0x800172f,
-0x3c0a0009, 0x8003a13, 0x0, 0x8002ea6,
-0x0, 0x800172f, 0x3c0a000b, 0x800172f,
-0x3c0a000c, 0x800172f, 0x3c0a000d, 0x80028fb,
-0x0, 0x8002890, 0x0, 0x800172f,
-0x3c0a000e, 0x800208c, 0x0, 0x8001964,
-0x0, 0x8001a04, 0x0, 0x8003ca6,
-0x0, 0x8003c94, 0x0, 0x800172f,
-0x0, 0x800191a, 0x0, 0x800172f,
-0x0, 0x800172f, 0x3c0a0013, 0x800172f,
-0x3c0a0014, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x27bdffe0,
-0x3c1cc000, 0xafbf001c, 0xafb00018, 0x8f820140,
-0x24030003, 0xaf8300ec, 0x34420004, 0xc002b20,
-0xaf820140, 0x3c0100c0, 0xc001763, 0xac203ffc,
-0x401821, 0x3c020010, 0x3c010001, 0xac236e9c,
-0x10620011, 0x43102b, 0x14400002, 0x3c020020,
-0x3c020008, 0x1062000c, 0x24050100, 0x3c060001,
-0x8cc66e9c, 0x3c040001, 0x24845c74, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020020,
-0x3c010001, 0xac226e9c, 0x24020008, 0x3c010001,
-0xac226eb4, 0x2402001f, 0x3c010001, 0xac226ec4,
-0x24020016, 0x3c010001, 0xac226e98, 0x3c05fffe,
-0x34a56f08, 0x3c020001, 0x8c426e9c, 0x3c030002,
-0x24639010, 0x3c040001, 0x8c846cc4, 0x431023,
-0x14800002, 0x458021, 0x2610fa38, 0x2402f000,
-0x2028024, 0xc001785, 0x2002021, 0x2022823,
-0x3c040020, 0x821823, 0x651823, 0x247bb000,
-0x3c03fffe, 0x3463bf08, 0x363b821, 0x3c0600bf,
-0x34c6f000, 0x3c070001, 0x8ce76cc0, 0x3c0300bf,
-0x3463e000, 0x852023, 0x3c010001, 0xac246ea8,
-0x822023, 0x3c010001, 0xac256e90, 0x52842,
-0x3c010001, 0xac226e84, 0x27620ffc, 0x3c010001,
-0xac226d20, 0x27621ffc, 0xdb3023, 0x7b1823,
-0x3c010001, 0xac246e88, 0x3c010001, 0xac256eac,
-0x3c010001, 0xac226d24, 0xaf860150, 0x10e00011,
-0xaf830250, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021,
-0xc001749, 0x0, 0x3c020001, 0x8c426cd0,
-0x3c030001, 0x8c636cd4, 0x2442fe00, 0x24630200,
-0x3c010001, 0xac226cd0, 0x3c010001, 0x10000004,
-0xac236cd4, 0x3c1d0001, 0x8fbd6d20, 0x3a0f021,
-0x3c020001, 0x8c426cc4, 0x1040000d, 0x26fafa38,
-0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4,
-0x3c1a0001, 0x8f5a6cd4, 0x2442fa38, 0x246305c8,
-0x3c010001, 0xac226cd0, 0x3c010001, 0xac236cd4,
-0x3c020001, 0x8c426cc8, 0x14400003, 0x0,
-0x3c010001, 0xac206cd0, 0xc001151, 0x0,
-0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020,
-0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4,
-0x27bdff98, 0xafb00048, 0x3c100001, 0x8e1066b8,
-0xafb20050, 0x3c120000, 0x26524100, 0xafbf0060,
-0xafbe005c, 0xafb50058, 0xafb30054, 0xafb1004c,
-0xafa20034, 0xafa30030, 0xafa00010, 0xafa00014,
-0x8f860040, 0x3c040001, 0x24845c80, 0x24050200,
-0x3c010001, 0xac326e80, 0xc002b3b, 0x2003821,
-0x8f830040, 0x3c02f000, 0x621824, 0x3c026000,
-0x1062000b, 0xa3a0003f, 0x240e0001, 0x3c040001,
-0x24845c88, 0xa3ae003f, 0xafa00010, 0xafa00014,
-0x8f860040, 0x24050300, 0xc002b3b, 0x2003821,
-0x8f820240, 0x3c030001, 0x431025, 0xaf820240,
-0xaf800048, 0x8f820048, 0x14400005, 0x0,
-0xaf800048, 0x8f820048, 0x10400004, 0x0,
-0xaf800048, 0x10000003, 0x2e02021, 0xaf80004c,
-0x2e02021, 0x3c050001, 0xc002ba8, 0x34a540f8,
-0x3402021, 0xc002ba8, 0x240505c8, 0x3c020001,
-0x8c426ea8, 0x3c0d0001, 0x8dad6e88, 0x3c030001,
-0x8c636e84, 0x3c080001, 0x8d086e90, 0x3c090001,
-0x8d296eac, 0x3c0a0001, 0x8d4a6eb4, 0x3c0b0001,
-0x8d6b6ec4, 0x3c0c0001, 0x8d8c6e98, 0x3c040001,
-0x24845c94, 0x24050400, 0xaf42013c, 0x8f42013c,
-0x24060001, 0x24070001, 0xaf400000, 0xaf4d0138,
-0xaf430144, 0xaf480148, 0xaf49014c, 0xaf4a0150,
-0xaf4b0154, 0xaf4c0158, 0x2442ff80, 0xaf420140,
-0x24020001, 0xafa20010, 0xc002b3b, 0xafa00014,
-0x8f420138, 0xafa20010, 0x8f42013c, 0xafa20014,
-0x8f460144, 0x8f470148, 0x3c040001, 0x24845ca0,
-0xc002b3b, 0x24050500, 0xafb70010, 0xafba0014,
-0x8f46014c, 0x8f470150, 0x3c040001, 0x24845cac,
-0xc002b3b, 0x24050600, 0x3c020001, 0x8c426e9c,
-0x3603821, 0x3c060002, 0x24c69010, 0x2448ffff,
-0x1061824, 0xe81024, 0x43102b, 0x10400006,
-0x24050900, 0x3c040001, 0x24845cb8, 0xafa80010,
-0xc002b3b, 0xafa00014, 0x8f82000c, 0xafa20010,
-0x8f82003c, 0xafa20014, 0x8f860000, 0x8f870004,
-0x3c040001, 0x24845cc4, 0xc002b3b, 0x24051000,
-0x8c020220, 0x8c030224, 0x8c060218, 0x8c07021c,
-0x3c040001, 0x24845ccc, 0x24051100, 0xafa20010,
-0xc002b3b, 0xafa30014, 0xaf800054, 0xaf80011c,
-0x8c020218, 0x30420002, 0x10400009, 0x0,
-0x8c020220, 0x3c030002, 0x34630004, 0x431025,
-0xaf42000c, 0x8c02021c, 0x10000008, 0x34420004,
-0x8c020220, 0x3c030002, 0x34630006, 0x431025,
-0xaf42000c, 0x8c02021c, 0x34420006, 0xaf420014,
-0x8c020218, 0x30420010, 0x1040000a, 0x0,
-0x8c02021c, 0x34420004, 0xaf420010, 0x8c020220,
-0x3c03000a, 0x34630004, 0x431025, 0x10000009,
-0xaf420008, 0x8c020220, 0x3c03000a, 0x34630006,
-0x431025, 0xaf420008, 0x8c02021c, 0x34420006,
-0xaf420010, 0x24020001, 0xaf8200a0, 0xaf8200b0,
-0x8f830054, 0x8f820054, 0xaf8000d0, 0xaf8000c0,
-0x10000002, 0x24630064, 0x8f820054, 0x621023,
-0x2c420065, 0x1440fffc, 0x0, 0x8c040208,
-0x8c05020c, 0x26e20028, 0xaee20020, 0x24020490,
-0xaee20010, 0xaee40008, 0xaee5000c, 0x26e40008,
-0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094,
-0x8c820018, 0xaf8200b4, 0x9482000a, 0xaf82009c,
-0x8f420014, 0xaf8200b0, 0x8f8200b0, 0x30420004,
-0x1440fffd, 0x0, 0x8f8200b0, 0x3c03ef00,
-0x431024, 0x10400021, 0x0, 0x8f8200b4,
-0xafa20010, 0x8f820090, 0x8f830094, 0x3c040001,
-0x24845cd4, 0xafa30014, 0x8f8600b0, 0x8f87009c,
-0x3c050001, 0xc002b3b, 0x34a5200d, 0x3c040001,
-0x24845ce0, 0x240203c0, 0xafa20010, 0xafa00014,
-0x8f860144, 0x3c070001, 0x24e75ce8, 0xc002b3b,
-0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c,
-0x8f820220, 0x34420004, 0xaf820220, 0x8f820140,
-0x3c030001, 0x431025, 0xaf820140, 0x96e20472,
-0x96e60452, 0x96e70462, 0xafa20010, 0x96e20482,
-0x3c040001, 0x24845d14, 0x24051200, 0xc002b3b,
-0xafa20014, 0x96f00452, 0x32020001, 0x10400002,
-0xb021, 0x24160001, 0x32020002, 0x54400001,
-0x36d60002, 0x32020008, 0x54400001, 0x36d60004,
-0x32020010, 0x54400001, 0x36d60008, 0x32020020,
-0x54400001, 0x36d60010, 0x32020040, 0x54400001,
-0x36d60020, 0x32020080, 0x54400001, 0x36d60040,
-0x96e60482, 0x30c20200, 0x54400001, 0x36d64000,
-0x96e30472, 0x30620200, 0x10400003, 0x30620100,
-0x10000003, 0x36d62000, 0x54400001, 0x36d61000,
-0x96f00462, 0x32c24000, 0x14400004, 0x3207009b,
-0x30c2009b, 0x14e20007, 0x240e0001, 0x32c22000,
-0x1440000d, 0x32020001, 0x3062009b, 0x10e20009,
-0x240e0001, 0x3c040001, 0x24845d20, 0x24051300,
-0x2003821, 0xa3ae003f, 0xafa30010, 0xc002b3b,
-0xafa00014, 0x32020001, 0x54400001, 0x36d60080,
-0x32020002, 0x54400001, 0x36d60100, 0x32020008,
-0x54400001, 0x36d60200, 0x32020010, 0x54400001,
-0x36d60400, 0x32020080, 0x54400001, 0x36d60800,
-0x8c020218, 0x30420200, 0x10400002, 0x3c020008,
-0x2c2b025, 0x8c020218, 0x30420800, 0x10400002,
-0x3c020080, 0x2c2b025, 0x8c020218, 0x30420400,
-0x10400002, 0x3c020100, 0x2c2b025, 0x8c020218,
-0x30420100, 0x10400002, 0x3c020200, 0x2c2b025,
-0x8c020218, 0x30420080, 0x10400002, 0x3c020400,
-0x2c2b025, 0x8c020218, 0x30422000, 0x10400002,
-0x3c020010, 0x2c2b025, 0x8c020218, 0x30424000,
-0x10400002, 0x3c020020, 0x2c2b025, 0x8c020218,
-0x30421000, 0x10400002, 0x3c020040, 0x2c2b025,
-0x8ee20498, 0x8ee3049c, 0xaf420160, 0xaf430164,
-0x8ee204a0, 0x8ee304a4, 0xaf420168, 0xaf43016c,
-0x8ee204a8, 0x8ee304ac, 0xaf420170, 0xaf430174,
-0x8ee20428, 0x8ee3042c, 0xaf420178, 0xaf43017c,
-0x8ee20448, 0x8ee3044c, 0xaf420180, 0xaf430184,
-0x8ee20458, 0x8ee3045c, 0xaf420188, 0xaf43018c,
-0x8ee20468, 0x8ee3046c, 0xaf420190, 0xaf430194,
-0x8ee20478, 0x8ee3047c, 0xaf420198, 0xaf43019c,
-0x8ee20488, 0x8ee3048c, 0xaf4201a0, 0xaf4301a4,
-0x8ee204b0, 0x8ee304b4, 0x24040080, 0xaf4201a8,
-0xaf4301ac, 0xc002ba8, 0x24050080, 0x8c02025c,
-0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200,
-0x24060008, 0xc002bbf, 0xaf4201f8, 0x3c043b9a,
-0x3484ca00, 0x3821, 0x24020006, 0x24030002,
-0xaf4201f4, 0x240203e8, 0xaf430204, 0xaf430200,
-0xaf4401fc, 0xaf420294, 0x24020001, 0xaf430290,
-0xaf42029c, 0x3c030001, 0x671821, 0x90636cd8,
-0x3471021, 0x24e70001, 0xa043022c, 0x2ce2000f,
-0x1440fff8, 0x3471821, 0x24e70001, 0x3c080001,
-0x350840f8, 0x8f820040, 0x3c040001, 0x24845d2c,
-0x24051400, 0x21702, 0x24420030, 0xa062022c,
-0x3471021, 0xa040022c, 0x8c070218, 0x2c03021,
-0x240205c8, 0xafa20010, 0xc002b3b, 0xafa80014,
-0x3c040001, 0x24845d38, 0x3c050000, 0x24a55c80,
-0x24060010, 0x27b10030, 0x2203821, 0x27b30034,
-0xc0017a3, 0xafb30010, 0x3c030001, 0x8c636cc8,
-0x1060000a, 0x408021, 0x8fa30030, 0x2405ff00,
-0x8fa20034, 0x246400ff, 0x852024, 0x831823,
-0x431023, 0xafa20034, 0xafa40030, 0x3c040001,
-0x24845d44, 0x3c050000, 0x24a54100, 0x24060108,
-0x2203821, 0xc0017a3, 0xafb30010, 0x409021,
-0x32c20003, 0x3c010001, 0xac326e80, 0x10400045,
-0x2203821, 0x8f820050, 0x3c030010, 0x431024,
-0x10400016, 0x0, 0x8c020218, 0x30420040,
-0x1040000f, 0x24020001, 0x8f820050, 0x8c030218,
-0x240e0001, 0x3c040001, 0x24845d50, 0xa3ae003f,
-0xafa20010, 0xafa30014, 0x8f870040, 0x24051500,
-0xc002b3b, 0x2c03021, 0x10000004, 0x0,
-0x3c010001, 0x370821, 0xa02240f4, 0x3c040001,
-0x24845d5c, 0x3c050001, 0x24a55b40, 0x3c060001,
-0x24c65bac, 0xc53023, 0x8f420010, 0x27b30030,
-0x2603821, 0x27b10034, 0x34420a00, 0xaf420010,
-0xc0017a3, 0xafb10010, 0x3c040001, 0x24845d70,
-0x3c050001, 0x24a5b714, 0x3c060001, 0x24c6ba90,
-0xc53023, 0x2603821, 0xaf420108, 0xc0017a3,
-0xafb10010, 0x3c040001, 0x24845d8c, 0x3c050001,
-0x24a5be58, 0x3c060001, 0x24c6c900, 0xc53023,
-0x2603821, 0x3c010001, 0xac226ef4, 0xc0017a3,
-0xafb10010, 0x3c040001, 0x24845da4, 0x10000024,
-0x24051600, 0x3c040001, 0x24845dac, 0x3c050001,
-0x24a5a10c, 0x3c060001, 0x24c6a238, 0xc53023,
-0xc0017a3, 0xafb30010, 0x3c040001, 0x24845dbc,
-0x3c050001, 0x24a5b2b0, 0x3c060001, 0x24c6b70c,
-0xc53023, 0x2203821, 0xaf420108, 0xc0017a3,
-0xafb30010, 0x3c040001, 0x24845dd0, 0x3c050001,
-0x24a5ba98, 0x3c060001, 0x24c6be50, 0xc53023,
-0x2203821, 0x3c010001, 0xac226ef4, 0xc0017a3,
-0xafb30010, 0x3c040001, 0x24845de4, 0x24051650,
-0x2c03021, 0x3821, 0x3c010001, 0xac226ef8,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x32c20020,
-0x10400021, 0x27a70030, 0x3c040001, 0x24845df0,
-0x3c050001, 0x24a5b13c, 0x3c060001, 0x24c6b2a8,
-0xc53023, 0x24022000, 0xaf42001c, 0x27a20034,
-0xc0017a3, 0xafa20010, 0x21900, 0x31982,
-0x3c040800, 0x641825, 0xae430028, 0x24030010,
-0xaf43003c, 0x96e30450, 0xaf430040, 0x8f430040,
-0x3c040001, 0x24845e04, 0xafa00014, 0xafa30010,
-0x8f47001c, 0x24051660, 0x3c010001, 0xac226ef0,
-0x10000025, 0x32c60020, 0x8ee20448, 0x8ee3044c,
-0xaf43001c, 0x8f42001c, 0x2442e000, 0x2c422001,
-0x1440000a, 0x240e0001, 0x3c040001, 0x24845e10,
-0xa3ae003f, 0xafa00010, 0xafa00014, 0x8f46001c,
-0x24051700, 0xc002b3b, 0x3821, 0x3c020000,
-0x24425cbc, 0x21100, 0x21182, 0x3c030800,
-0x431025, 0xae420028, 0x24020008, 0xaf42003c,
-0x96e20450, 0xaf420040, 0x8f420040, 0x3c040001,
-0x24845e1c, 0xafa00014, 0xafa20010, 0x8f47001c,
-0x24051800, 0x32c60020, 0xc002b3b, 0x0,
-0x3c050fff, 0x3c030001, 0x8c636ef4, 0x34a5ffff,
-0x2403021, 0x3c020001, 0x8c426ef8, 0x3c040800,
-0x651824, 0x31882, 0x641825, 0x451024,
-0x21082, 0x441025, 0xacc20080, 0x32c20180,
-0x10400056, 0xacc30020, 0x8f82005c, 0x3c030080,
-0x431024, 0x1040000d, 0x0, 0x8f820050,
-0xafa20010, 0x8f82005c, 0x240e0001, 0x3c040001,
-0x24845e28, 0xa3ae003f, 0xafa20014, 0x8f870040,
-0x24051900, 0xc002b3b, 0x2c03021, 0x8f820050,
-0x3c030010, 0x431024, 0x10400016, 0x0,
-0x8c020218, 0x30420040, 0x1040000f, 0x24020001,
-0x8f820050, 0x8c030218, 0x240e0001, 0x3c040001,
-0x24845d50, 0xa3ae003f, 0xafa20010, 0xafa30014,
-0x8f870040, 0x24052000, 0xc002b3b, 0x2c03021,
-0x10000004, 0x0, 0x3c010001, 0x370821,
-0xa02240f4, 0x3c040001, 0x24845e34, 0x3c050001,
-0x24a55ac0, 0x3c060001, 0x24c65b38, 0xc53023,
-0x8f420008, 0x27b30030, 0x2603821, 0x27b10034,
-0x34420e00, 0xaf420008, 0xc0017a3, 0xafb10010,
-0x3c040001, 0x24845e4c, 0x3c050001, 0x24a5d8b4,
-0x3c060001, 0x24c6e3c8, 0xc53023, 0x2603821,
-0xaf42010c, 0xc0017a3, 0xafb10010, 0x3c040001,
-0x24845e64, 0x3c050001, 0x24a5e9ac, 0x3c060001,
-0x24c6f0f0, 0xc53023, 0x2603821, 0x3c010001,
-0xac226f04, 0xc0017a3, 0xafb10010, 0x3c040001,
-0x24845e7c, 0x10000027, 0x24052100, 0x3c040001,
-0x24845e84, 0x3c050001, 0x24a59fc8, 0x3c060001,
-0x24c6a104, 0xc53023, 0x27b10030, 0x2203821,
-0x27b30034, 0xc0017a3, 0xafb30010, 0x3c040001,
-0x24845e94, 0x3c050001, 0x24a5cad4, 0x3c060001,
-0x24c6d8ac, 0xc53023, 0x2203821, 0xaf42010c,
-0xc0017a3, 0xafb30010, 0x3c040001, 0x24845ea4,
-0x3c050001, 0x24a5e84c, 0x3c060001, 0x24c6e9a4,
-0xc53023, 0x2203821, 0x3c010001, 0xac226f04,
-0xc0017a3, 0xafb30010, 0x3c040001, 0x24845eb8,
-0x24052150, 0x2c03021, 0x3821, 0x3c010001,
-0xac226f10, 0xafa00010, 0xc002b3b, 0xafa00014,
-0x3c110fff, 0x3c030001, 0x8c636f04, 0x3631ffff,
-0x2409821, 0x3c020001, 0x8c426f10, 0x3c0e0800,
-0x711824, 0x31882, 0x6e1825, 0x511024,
-0x21082, 0x4e1025, 0xae630038, 0xae620078,
-0x8c020218, 0x30420040, 0x14400004, 0x24020001,
-0x3c010001, 0x370821, 0xa02240f4, 0x3c040001,
-0x24845ec4, 0x3c050001, 0x24a5e3d0, 0x3c060001,
-0x24c6e52c, 0xc53023, 0x27be0030, 0x3c03821,
-0x27b50034, 0xc0017a3, 0xafb50010, 0x3c010001,
-0xac226efc, 0x511024, 0x21082, 0x3c0e0800,
-0x4e1025, 0xae620050, 0x32c22000, 0x10400006,
-0x3c03821, 0x3c020000, 0x24425cbc, 0x2221024,
-0x1000000f, 0x21082, 0x3c040001, 0x24845ed8,
-0x3c050001, 0x24a5e534, 0x3c060001, 0x24c6e6e4,
-0xc53023, 0xc0017a3, 0xafb50010, 0x3c010001,
-0xac226f14, 0x511024, 0x21082, 0x3c0e0800,
-0x4e1025, 0xae620048, 0x32c24000, 0x10400005,
-0x27a70030, 0x3c020000, 0x24425cbc, 0x1000000e,
-0x21100, 0x3c040001, 0x24845ef0, 0x3c050001,
-0x24a5e6ec, 0x3c060001, 0x24c6e844, 0xc53023,
-0x27a20034, 0xc0017a3, 0xafa20010, 0x3c010001,
-0xac226f08, 0x21100, 0x21182, 0x3c030800,
-0x431025, 0xae420060, 0x3c040001, 0x24845f08,
-0x3c050001, 0x24a58230, 0x3c060001, 0x24c68650,
-0xc53023, 0x27b10030, 0x2203821, 0x27b30034,
-0xc0017a3, 0xafb30010, 0x3c0e0fff, 0x35ceffff,
-0x3c040001, 0x24845f14, 0x3c050000, 0x24a56468,
-0x3c060000, 0x24c66588, 0xc53023, 0x2203821,
-0x240f021, 0x3c010001, 0xac226edc, 0x4e1024,
-0x21082, 0x3c150800, 0x551025, 0xafae0044,
-0xafc200b8, 0xc0017a3, 0xafb30010, 0x3c040001,
-0x24845f20, 0x3c050000, 0x24a56590, 0x3c060000,
-0x24c66808, 0x8fae0044, 0xc53023, 0x2203821,
-0x3c010001, 0xac226ed0, 0x4e1024, 0x21082,
-0x551025, 0xafc200e8, 0xc0017a3, 0xafb30010,
-0x3c040001, 0x24845f38, 0x3c050000, 0x24a56810,
-0x3c060000, 0x24c66940, 0x8fae0044, 0xc53023,
-0x2203821, 0x3c010001, 0xac226ec8, 0x4e1024,
-0x21082, 0x551025, 0xafc200c0, 0xc0017a3,
-0xafb30010, 0x3c040001, 0x24845f50, 0x3c050001,
-0x24a5fad0, 0x3c060001, 0x24c6fba8, 0x8fae0044,
-0xc53023, 0x2203821, 0x3c010001, 0xac226ed4,
-0x4e1024, 0x21082, 0x551025, 0xafc200c8,
-0xc0017a3, 0xafb30010, 0x3c040001, 0x24845f5c,
-0x3c050001, 0x24a5c93c, 0x3c060001, 0x24c6ca20,
-0xc53023, 0x2203821, 0xaf420110, 0xc0017a3,
-0xafb30010, 0x3c040001, 0x24845f6c, 0x3c050001,
-0x24a5c910, 0x3c060001, 0x24c6c934, 0xc53023,
-0x2203821, 0xaf420124, 0xc0017a3, 0xafb30010,
-0x3c040001, 0x24845f7c, 0x3c050001, 0x24a55a80,
-0x3c060001, 0x24c65aac, 0xc53023, 0x2203821,
-0xaf420120, 0xaf420114, 0xc0017a3, 0xafb30010,
-0x3c040001, 0x24845f88, 0x3c050001, 0x24a5f298,
-0x3c060001, 0x24c6f6b4, 0xc53023, 0x2203821,
-0xaf420118, 0xc0017a3, 0xafb30010, 0x8fae0044,
-0x3c010001, 0xac226f18, 0x4e1024, 0x21082,
-0x551025, 0xc003fc3, 0xafc200d0, 0xc003c40,
-0x0, 0xc0027a8, 0x0, 0xac000228,
-0xac00022c, 0x96e20450, 0x2442ffff, 0xaf420038,
-0x96e20460, 0xaf420080, 0x32c24000, 0x14400003,
-0x0, 0x96e20480, 0xaf420084, 0x96e70490,
-0x50e00001, 0x24070800, 0x24e2ffff, 0xaf420088,
-0xaf42007c, 0x24020800, 0x10e2000f, 0x32c24000,
-0x10400003, 0x24020400, 0x10e2000b, 0x0,
-0x240e0001, 0x3c040001, 0x24845f98, 0xa3ae003f,
-0x96e60490, 0x24052170, 0x2c03821, 0xafa00010,
-0xc002b3b, 0xafa00014, 0x8f430138, 0x8f440138,
-0x24020001, 0xa34205c2, 0xaf430094, 0xaf440098,
-0xafa00010, 0xafa00014, 0x8f460080, 0x8f470084,
-0x3c040001, 0x24845fa4, 0xc002b3b, 0x24052200,
-0xc0024a4, 0x3c110800, 0x3c1433d8, 0x3694cb58,
-0x3c020800, 0x34420080, 0x3c040001, 0x24845fb0,
-0x3c050000, 0x24a55d00, 0x3c060000, 0x24c65d1c,
-0xc53023, 0x27a70030, 0xaf820060, 0x2402ffff,
-0xaf820064, 0x27a20034, 0xc0017a3, 0xafa20010,
-0x3c010001, 0xac226eb8, 0x21100, 0x21182,
-0x511025, 0xc0018fc, 0xae420000, 0x8f820240,
-0x3c030001, 0x431025, 0xaf820240, 0x3c020000,
-0x24424034, 0xaf820244, 0xaf800240, 0x8f820060,
-0x511024, 0x14400005, 0x3c030800, 0x8f820060,
-0x431024, 0x1040fffd, 0x0, 0xc003c4d,
-0x8821, 0x3c020100, 0xafa20020, 0x8f530018,
-0x240200ff, 0x56620001, 0x26710001, 0x8c020228,
-0x1622000e, 0x1330c0, 0x8f42033c, 0x24420001,
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
-0x24845c24, 0x3c050009, 0xafa00014, 0xafa20010,
-0x8fa60020, 0x1000003f, 0x34a50100, 0xd71021,
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
-0xc01821, 0x8f440178, 0x8f45017c, 0x1021,
-0x24070004, 0xafa70010, 0xafb10014, 0x8f48000c,
-0x24c604c0, 0x2e63021, 0xafa80018, 0x8f48010c,
-0x24070008, 0xa32821, 0xa3482b, 0x822021,
-0x100f809, 0x892021, 0x1440000b, 0x24070008,
-0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24845c2c, 0x3c050009, 0xafa20014, 0x8fa60020,
-0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164,
-0x8f43000c, 0xaf510018, 0x8f860120, 0x24020010,
-0xafa20010, 0xafb10014, 0xafa30018, 0x8f42010c,
-0x40f809, 0x24c6001c, 0x14400010, 0x0,
-0x8f420340, 0x24420001, 0xaf420340, 0x8f420340,
-0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24845c34, 0x3c050009, 0xafa20014, 0x8fa60020,
-0x34a50300, 0xc002b3b, 0x2603821, 0x8f4202e4,
-0x24420001, 0xaf4202e4, 0x8f4202e4, 0x93a2003f,
-0x10400069, 0x3c020700, 0x34423000, 0xafa20028,
-0x8f530018, 0x240200ff, 0x12620002, 0x8821,
-0x26710001, 0x8c020228, 0x1622000e, 0x1330c0,
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
-0x8c020228, 0x3c040001, 0x24845c24, 0x3c050009,
-0xafa00014, 0xafa20010, 0x8fa60028, 0x1000003f,
-0x34a50100, 0xd71021, 0x8fa30028, 0x8fa4002c,
-0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
-0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
-0xafb10014, 0x8f48000c, 0x24c604c0, 0x2e63021,
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24845c2c, 0x3c050009,
-0xafa20014, 0x8fa60028, 0x1000001c, 0x34a50200,
-0x8f440160, 0x8f450164, 0x8f43000c, 0xaf510018,
-0x8f860120, 0x24020010, 0xafa20010, 0xafb10014,
-0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400010, 0x0, 0x8f420340, 0x24420001,
-0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24845c34, 0x3c050009,
-0xafa20014, 0x8fa60028, 0x34a50300, 0xc002b3b,
-0x2603821, 0x8f4202f0, 0x24420001, 0xaf4202f0,
-0x8f4202f0, 0x3c040001, 0x24845fc0, 0xafa00010,
-0xafa00014, 0x8fa60028, 0x24052300, 0xc002b3b,
-0x3821, 0x10000004, 0x0, 0x8c020264,
-0x10400005, 0x0, 0x8f8200a0, 0x30420004,
-0x1440fffa, 0x0, 0x8f820044, 0x34420004,
-0xaf820044, 0x8f420308, 0x24420001, 0xaf420308,
-0x8f420308, 0x8f8200d8, 0x8f8300d4, 0x431023,
-0x2442ff80, 0xaf420090, 0x8f420090, 0x2842ff81,
-0x10400006, 0x24020001, 0x8f420090, 0x8f430144,
-0x431021, 0xaf420090, 0x24020001, 0xaf42008c,
-0x32c20008, 0x10400006, 0x0, 0x8f820214,
-0x3c038100, 0x3042ffff, 0x431025, 0xaf820214,
-0x3c030001, 0x8c636d94, 0x30620002, 0x10400009,
-0x30620001, 0x3c040001, 0x24845fcc, 0x3c050000,
-0x24a56d50, 0x3c060000, 0x24c671c8, 0x10000012,
-0xc53023, 0x10400009, 0x0, 0x3c040001,
-0x24845fdc, 0x3c050000, 0x24a571d0, 0x3c060000,
-0x24c67678, 0x10000008, 0xc53023, 0x3c040001,
-0x24845fec, 0x3c050000, 0x24a56948, 0x3c060000,
-0x24c66d48, 0xc53023, 0x27a70030, 0x27a20034,
-0xc0017a3, 0xafa20010, 0x3c010001, 0xac226ecc,
-0x3c020001, 0x8c426ecc, 0x3c030800, 0x21100,
-0x21182, 0x431025, 0xae420040, 0x8f8200a0,
-0xafa20010, 0x8f8200b0, 0xafa20014, 0x8f86005c,
-0x8f87011c, 0x3c040001, 0x24845ffc, 0x3c010001,
-0xac366ea4, 0x3c010001, 0xac206e94, 0x3c010001,
-0xac3c6e8c, 0x3c010001, 0xac3b6ebc, 0x3c010001,
-0xac376ec0, 0x3c010001, 0xac3a6ea0, 0xc002b3b,
-0x24052400, 0x8f820200, 0xafa20010, 0x8f820220,
-0xafa20014, 0x8f860044, 0x8f870050, 0x3c040001,
-0x24846008, 0xc002b3b, 0x24052500, 0x8f830060,
-0x74100b, 0x242000a, 0x200f821, 0x0,
-0xd, 0x8fbf0060, 0x8fbe005c, 0x8fb50058,
-0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048,
-0x3e00008, 0x27bd0068, 0x27bdffe0, 0x3c040001,
-0x24846014, 0x24052600, 0x3021, 0x3821,
-0xafbf0018, 0xafa00010, 0xc002b3b, 0xafa00014,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008,
-0x0, 0x3e00008, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x3e00008, 0x0, 0x3e00008, 0x0,
-0x27bdfde0, 0x27a50018, 0x3c04dead, 0x3484beef,
-0xafbf0218, 0x8f820150, 0x3c03001f, 0x3463ffff,
-0xafa40018, 0xa22823, 0xa32824, 0x8ca20000,
-0x1044000a, 0x0, 0xafa50010, 0x8ca20000,
-0xafa20014, 0x8f860150, 0x8f870250, 0x3c040001,
-0x2484601c, 0xc002b3b, 0x24052700, 0x8fbf0218,
-0x3e00008, 0x27bd0220, 0x27bdffe0, 0x3c06abba,
-0x34c6babe, 0xafb00018, 0x3c100004, 0x3c07007f,
-0x34e7ffff, 0xafbf001c, 0x102840, 0x8e040000,
-0x8ca30000, 0xaca00000, 0xae060000, 0x8ca20000,
-0xaca30000, 0x10460005, 0xae040000, 0xa08021,
-0xf0102b, 0x1040fff5, 0x102840, 0x3c040001,
-0x24846028, 0x24052800, 0x2003021, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x2001021,
-0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020,
-0x8c020224, 0x3047003f, 0x10e00010, 0x803021,
-0x2821, 0x24030020, 0xe31024, 0x10400002,
-0x63042, 0xa62821, 0x31842, 0x1460fffb,
-0xe31024, 0x2402f000, 0xa22824, 0x3402ffff,
-0x45102b, 0x14400003, 0x3c020001, 0x10000008,
-0x3c020001, 0x3442ffff, 0x851823, 0x43102b,
-0x14400003, 0xa01021, 0x3c02fffe, 0x821021,
-0x3e00008, 0x0, 0x27bdffd0, 0xafb50028,
-0x8fb50040, 0xafb20020, 0xa09021, 0xafb1001c,
-0x24c60003, 0xafbf002c, 0xafb30024, 0xafb00018,
-0x8ea20000, 0x2403fffc, 0xc38024, 0x50102b,
-0x1440001b, 0xe08821, 0x8e330000, 0xafb00010,
-0x8ea20000, 0xafa20014, 0x8e270000, 0x24053000,
-0xc002b3b, 0x2403021, 0x8e230000, 0x702021,
-0x64102b, 0x10400007, 0x2402821, 0x8ca20000,
-0xac620000, 0x24630004, 0x64102b, 0x1440fffb,
-0x24a50004, 0x8ea20000, 0x501023, 0xaea20000,
-0x8e220000, 0x501021, 0x1000000b, 0xae220000,
-0x2402002d, 0xa0820000, 0xafb00010, 0x8ea20000,
-0x2409821, 0xafa20014, 0x8e270000, 0x24053100,
-0xc002b3b, 0x2603021, 0x2601021, 0x8fbf002c,
-0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c,
-0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffe8,
-0x3c1cc000, 0x3c05fffe, 0x3c030001, 0x8c636e84,
-0x3c040001, 0x8c846e90, 0x34a5bf08, 0x24021ffc,
-0x3c010001, 0xac226cd0, 0x3c0200c0, 0x3c010001,
-0xac226cd4, 0x3c020020, 0xafbf0010, 0x3c0100c0,
-0xac201ffc, 0x431023, 0x441023, 0x245bb000,
-0x365b821, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021,
-0x3c0400c0, 0x34840200, 0x3c1a00c0, 0x3c0300c0,
-0x346307c8, 0x24021dfc, 0x3c010001, 0xac226cd0,
-0x24021834, 0x3c010001, 0xac246cd4, 0x3c010001,
-0xac226cd0, 0x3c010001, 0xac236cd4, 0xc00180d,
-0x375a0200, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffc8, 0x3c040001, 0x24846034, 0x24053200,
-0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4,
-0x3021, 0x3603821, 0xafbf0030, 0xafb3002c,
-0xafb20028, 0xafb10024, 0xafb00020, 0xafa2001c,
-0xafa30018, 0xafb70010, 0xc002b3b, 0xafba0014,
-0xc001916, 0x0, 0x8f820240, 0x34420004,
-0xaf820240, 0x24020001, 0xaf420000, 0x3c020001,
-0x571021, 0x904240f4, 0x10400092, 0x2403fffc,
-0x3c100001, 0x2610ac73, 0x3c120001, 0x2652a84c,
-0x2121023, 0x438024, 0x8fa3001c, 0x3c040001,
-0x24846040, 0x70102b, 0x1440001a, 0x27b30018,
-0x8fb10018, 0x24053000, 0x2403021, 0xafb00010,
-0xafa30014, 0xc002b3b, 0x2203821, 0x8fa30018,
-0x702021, 0x64102b, 0x10400007, 0x2403021,
-0x8cc20000, 0xac620000, 0x24630004, 0x64102b,
-0x1440fffb, 0x24c60004, 0x8fa2001c, 0x501023,
-0xafa2001c, 0x8e620000, 0x501021, 0x1000000a,
-0xae620000, 0x2408821, 0x24053100, 0xafb00010,
-0xafa30014, 0x8fa70018, 0x2203021, 0x2402002d,
-0xc002b3b, 0xa0820000, 0x24070020, 0x8fa3001c,
-0x3c040001, 0x2484605c, 0x24120020, 0x3c010001,
-0xac316eb0, 0x2c620020, 0x1440001d, 0x27b10018,
-0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f50,
-0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821,
-0x8fa30018, 0x3c040001, 0x24846f50, 0x24650020,
-0x65102b, 0x10400007, 0x0, 0x8c820000,
-0xac620000, 0x24630004, 0x65102b, 0x1440fffb,
-0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c,
-0x8e220000, 0x521021, 0x1000000b, 0xae220000,
-0x3c100001, 0x26106f50, 0x24053100, 0xafa70010,
-0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d,
-0xc002b3b, 0xa0820000, 0x24070020, 0x3c040001,
-0x24846070, 0x8fa3001c, 0x24120020, 0x3c010001,
-0xac306ee4, 0x2c620020, 0x1440001d, 0x27b10018,
-0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f70,
-0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821,
-0x8fa30018, 0x3c040001, 0x24846f70, 0x24650020,
-0x65102b, 0x10400007, 0x0, 0x8c820000,
-0xac620000, 0x24630004, 0x65102b, 0x1440fffb,
-0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c,
-0x8e220000, 0x521021, 0x1000000b, 0xae220000,
-0x3c100001, 0x26106f70, 0x24053100, 0xafa70010,
-0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d,
-0xc002b3b, 0xa0820000, 0x3c010001, 0x10000031,
-0xac306ee0, 0x3c100001, 0x2610821f, 0x3c120001,
-0x2652809c, 0x2121023, 0x438024, 0x8fa3001c,
-0x3c040001, 0x24846084, 0x70102b, 0x1440001a,
-0x27b30018, 0x8fb10018, 0x24053000, 0x2403021,
-0xafb00010, 0xafa30014, 0xc002b3b, 0x2203821,
-0x8fa30018, 0x702021, 0x64102b, 0x10400007,
-0x2403021, 0x8cc20000, 0xac620000, 0x24630004,
-0x64102b, 0x1440fffb, 0x24c60004, 0x8fa2001c,
-0x501023, 0xafa2001c, 0x8e620000, 0x501021,
-0x1000000a, 0xae620000, 0x2408821, 0x24053100,
-0xafb00010, 0xafa30014, 0x8fa70018, 0x2203021,
-0x2402002d, 0xc002b3b, 0xa0820000, 0x3c010001,
-0xac316eb0, 0x3c030001, 0x8c636eb0, 0x24020400,
-0x60f809, 0xaf820070, 0x8fbf0030, 0x8fb3002c,
-0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008,
-0x27bd0038, 0x0, 0x0, 0x8f820040,
-0x3c03f000, 0x431024, 0x3c036000, 0x14430006,
-0x0, 0x8f820050, 0x2403ff80, 0x431024,
-0x34420055, 0xaf820050, 0x8f820054, 0x244203e8,
-0xaf820058, 0x240201f4, 0xaf4200e0, 0x24020004,
-0xaf4200e8, 0x24020002, 0xaf4001b0, 0xaf4000e4,
-0xaf4200dc, 0xaf4000d8, 0xaf4000d4, 0x3e00008,
-0xaf4000d0, 0x8f820054, 0x24420005, 0x3e00008,
-0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054,
-0x244203e8, 0xaf820058, 0x3c020800, 0x2c21024,
-0x10400004, 0x3c02f7ff, 0x3442ffff, 0x2c2b024,
-0x36940040, 0x3c020001, 0x8c426da8, 0x10400017,
-0x3c020200, 0x3c030001, 0x8c636f1c, 0x10600016,
-0x282a025, 0x3c020001, 0x8c426e44, 0x14400012,
-0x3c020200, 0x3c020001, 0x8c426d94, 0x30420003,
-0x1440000d, 0x3c020200, 0x8f830224, 0x3c020002,
-0x8c428fec, 0x10620008, 0x3c020200, 0xc003daf,
-0x0, 0x10000004, 0x3c020200, 0xc004196,
-0x0, 0x3c020200, 0x2c21024, 0x10400003,
-0x0, 0xc001f4b, 0x0, 0x8f4200d8,
-0x8f4300dc, 0x24420001, 0xaf4200d8, 0x43102b,
-0x14400003, 0x0, 0xaf4000d8, 0x36940080,
-0x8c030238, 0x1060000c, 0x0, 0x8f4201b0,
-0x244203e8, 0xaf4201b0, 0x43102b, 0x14400006,
-0x0, 0x934205c5, 0x14400003, 0x0,
-0xc001da0, 0x0, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x3e00008, 0x0, 0x27bdffd8,
-0xafbf0020, 0x8f43002c, 0x8f420038, 0x10620059,
-0x0, 0x3c020001, 0x571021, 0x904240f0,
-0x10400026, 0x24070008, 0x8f440170, 0x8f450174,
-0x8f48000c, 0x8f860120, 0x24020020, 0xafa20010,
-0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
-0x24c6001c, 0x14400011, 0x24020001, 0x3c010001,
-0x370821, 0xa02240f0, 0x8f820124, 0xafa20010,
-0x8f820128, 0x3c040001, 0x24846128, 0xafa20014,
-0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b,
-0x34a50900, 0x1000005c, 0x0, 0x8f420300,
-0x24420001, 0xaf420300, 0x8f420300, 0x8f42002c,
-0xa34005c1, 0x10000027, 0xaf420038, 0x8f440170,
-0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
-0x24020080, 0xafa20010, 0xafa30014, 0xafa80018,
-0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
-0x24020001, 0x3c010001, 0x370821, 0xa02240f1,
-0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
-0x24846134, 0xafa20014, 0x8f46002c, 0x8f870120,
-0x3c050009, 0xc002b3b, 0x34a51100, 0x10000036,
-0x0, 0x8f420300, 0x8f43002c, 0x24420001,
-0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1,
-0xaf430038, 0x3c010001, 0x370821, 0xa02040f1,
-0x3c010001, 0x370821, 0xa02040f0, 0x10000026,
-0xaf400034, 0x934205c1, 0x1040001d, 0x0,
-0xa34005c1, 0x8f820040, 0x30420001, 0x14400008,
-0x2021, 0x8c030104, 0x24020001, 0x50620005,
-0x24040001, 0x8c020264, 0x10400003, 0x801021,
-0x24040001, 0x801021, 0x10400006, 0x0,
-0x8f42030c, 0x24420001, 0xaf42030c, 0x10000008,
-0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044,
-0x8f420308, 0x24420001, 0xaf420308, 0x8f420308,
-0x3c010001, 0x370821, 0xa02040f0, 0x3c010001,
-0x370821, 0xa02040f1, 0x8f420000, 0x10400007,
-0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
-0x0, 0x10000005, 0x0, 0xaf800048,
-0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
-0x3c03ff7f, 0x3463ffff, 0x431024, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x10000002,
-0xaf80004c, 0xaf800048, 0x8fbf0020, 0x3e00008,
-0x27bd0028, 0x3e00008, 0x0, 0x27bdffd8,
-0xafbf0020, 0x8f430044, 0x8f42007c, 0x10620029,
-0x24070008, 0x8f440168, 0x8f45016c, 0x8f48000c,
-0x8f860120, 0x24020040, 0xafa20010, 0xafa30014,
-0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400011, 0x24020001, 0x3c010001, 0x370821,
-0xa02240f2, 0x8f820124, 0xafa20010, 0x8f820128,
-0x3c040001, 0x2484613c, 0xafa20014, 0x8f460044,
-0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51300,
-0x1000000f, 0x0, 0x8f420304, 0x24420001,
-0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c,
-0x3c010001, 0x370821, 0xa02040f2, 0x10000004,
-0xaf400078, 0x3c010001, 0x370821, 0xa02040f2,
-0x8f420000, 0x10400007, 0x0, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x3c03feff, 0x3463ffff,
-0x431024, 0xaf820060, 0x8f420000, 0x10400003,
-0x0, 0x10000002, 0xaf80004c, 0xaf800048,
-0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008,
-0x0, 0x3c020001, 0x8c426da8, 0x27bdffa8,
-0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044,
-0xafb20040, 0xafb1003c, 0xafb00038, 0x104000d5,
-0x8f900044, 0x8f4200d0, 0x24430001, 0x2842000b,
-0x144000e4, 0xaf4300d0, 0x8f420004, 0x30420002,
-0x1440009c, 0xaf4000d0, 0x8f420004, 0x3c030001,
-0x8c636d98, 0x34420002, 0xaf420004, 0x24020001,
-0x14620003, 0x3c020600, 0x10000002, 0x34423000,
-0x34421000, 0xafa20020, 0x8f4a0018, 0xafaa0034,
-0x27aa0020, 0xafaa002c, 0x8faa0034, 0x240200ff,
-0x11420002, 0x1821, 0x25430001, 0x8c020228,
-0x609821, 0x1662000e, 0x3c050009, 0x8f42033c,
-0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228,
-0x8fa70034, 0x3c040001, 0x2484610c, 0xafa00014,
-0xafa20010, 0x8fa60020, 0x10000070, 0x34a50500,
-0x8faa0034, 0xa38c0, 0xf71021, 0x8fa30020,
-0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054,
-0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9,
-0x1040001b, 0xa821, 0xe09021, 0x265e04c0,
-0x8f440178, 0x8f45017c, 0x2401821, 0x240a0004,
-0xafaa0010, 0xafb30014, 0x8f48000c, 0x1021,
-0x2fe3021, 0xafa80018, 0x8f48010c, 0x24070008,
-0xa32821, 0xa3482b, 0x822021, 0x100f809,
-0x892021, 0x54400006, 0x24150001, 0x8f820054,
-0x2221023, 0x2c4203e9, 0x1440ffe9, 0x0,
-0x32a200ff, 0x54400018, 0xaf530018, 0x8f420378,
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
-0x8faa002c, 0x8fa70034, 0xafa20010, 0x8f820124,
-0x3c040001, 0x24846118, 0xafa20014, 0x8d460000,
-0x3c050009, 0x10000035, 0x34a50600, 0x8f420308,
-0x24150001, 0x24420001, 0xaf420308, 0x8f420308,
-0x1000001e, 0x32a200ff, 0x8f830054, 0x8f820054,
-0x247103e8, 0x2221023, 0x2c4203e9, 0x10400016,
-0xa821, 0x3c1e0020, 0x24120010, 0x8f42000c,
-0x8f440160, 0x8f450164, 0x8f860120, 0xafb20010,
-0xafb30014, 0x5e1025, 0xafa20018, 0x8f42010c,
-0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3,
-0x0, 0x8f820054, 0x2221023, 0x2c4203e9,
-0x1440ffee, 0x0, 0x32a200ff, 0x14400011,
-0x3c050009, 0x8f420378, 0x24420001, 0xaf420378,
-0x8f420378, 0x8f820120, 0x8faa002c, 0x8fa70034,
-0xafa20010, 0x8f820124, 0x3c040001, 0x24846120,
-0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b,
-0x0, 0x8f4202ec, 0x24420001, 0xaf4202ec,
-0x8f4202ec, 0x8f420004, 0x30420001, 0x50400029,
-0x36100040, 0x3c020400, 0x2c21024, 0x10400013,
-0x2404ffdf, 0x8f420250, 0x8f430254, 0x8f4401b4,
-0x14640006, 0x36100040, 0x8f420270, 0x8f430274,
-0x8f4401b8, 0x10640007, 0x2402ffdf, 0x8f420250,
-0x8f430254, 0x8f440270, 0x8f450274, 0x10000012,
-0x3a100020, 0x1000002b, 0x2028024, 0x8f420250,
-0x8f430254, 0x8f4501b4, 0x14650006, 0x2048024,
-0x8f420270, 0x8f430274, 0x8f4401b8, 0x50640021,
-0x36100040, 0x8f420250, 0x8f430254, 0x8f440270,
-0x8f450274, 0x3a100040, 0xaf4301b4, 0x10000019,
-0xaf4501b8, 0x8f4200d4, 0x24430001, 0x10000011,
-0x28420033, 0x8f420004, 0x30420001, 0x10400009,
-0x3c020400, 0x2c21024, 0x10400004, 0x2402ffdf,
-0x2028024, 0x1000000b, 0x36100040, 0x10000009,
-0x36100060, 0x8f4200d4, 0x36100040, 0x24430001,
-0x284201f5, 0x14400003, 0xaf4300d4, 0xaf4000d4,
-0x3a100020, 0xaf900044, 0x2402ff7f, 0x282a024,
-0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044,
-0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008,
-0x27bd0058, 0x3e00008, 0x0, 0x3c020001,
-0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
-0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
-0x104000c7, 0xafb00030, 0x8f4200d0, 0x24430001,
-0x2842000b, 0x144000da, 0xaf4300d0, 0x8f420004,
-0x30420002, 0x14400097, 0xaf4000d0, 0x8f420004,
-0x3c030001, 0x8c636d98, 0x34420002, 0xaf420004,
-0x24020001, 0x14620003, 0x3c020600, 0x10000002,
-0x34423000, 0x34421000, 0xafa20020, 0x1821,
-0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
-0xafaa002c, 0x27c30001, 0x8c020228, 0x609021,
-0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
-0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010,
-0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021,
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
-0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
-0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
-0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
-0x24070008, 0xa32821, 0xa3482b, 0x822021,
-0x100f809, 0x892021, 0x54400006, 0x24130001,
-0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
-0x0, 0x326200ff, 0x54400017, 0xaf520018,
-0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
-0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124,
-0x3c040001, 0x24846118, 0x3c050009, 0xafa20014,
-0x8d460000, 0x10000035, 0x34a50600, 0x8f420308,
-0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
-0x1000001e, 0x326200ff, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x10400016,
-0x9821, 0x3c150020, 0x24110010, 0x8f42000c,
-0x8f440160, 0x8f450164, 0x8f860120, 0xafb10010,
-0xafb20014, 0x551025, 0xafa20018, 0x8f42010c,
-0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3,
-0x0, 0x8f820054, 0x2021023, 0x2c4203e9,
-0x1440ffee, 0x0, 0x326200ff, 0x14400011,
-0x0, 0x8f420378, 0x24420001, 0xaf420378,
-0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24846120, 0x3c050009,
-0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b,
-0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec,
-0x8f4202ec, 0x8f420004, 0x30420001, 0x10400018,
-0x24040001, 0x8f420250, 0x8f430254, 0x8f4501b4,
-0x3c010001, 0x14650006, 0xa0246cf1, 0x8f420270,
-0x8f430274, 0x8f4401b8, 0x10640021, 0x0,
-0x8f420250, 0x8f430254, 0x3c040001, 0x90846cf0,
-0x8f460270, 0x8f470274, 0x38840001, 0xaf4301b4,
-0xaf4701b8, 0x3c010001, 0x10000025, 0xa0246cf0,
-0x8f4200d4, 0x3c010001, 0xa0206cf0, 0x24430001,
-0x28420033, 0x1440001e, 0xaf4300d4, 0x3c020001,
-0x90426cf1, 0xaf4000d4, 0x10000017, 0x38420001,
-0x8f420004, 0x30420001, 0x10400008, 0x0,
-0xc00565a, 0x2021, 0x3c010001, 0xa0206cf1,
-0x3c010001, 0x1000000e, 0xa0206cf0, 0x8f4200d4,
-0x3c010001, 0xa0206cf0, 0x24430001, 0x284201f5,
-0x14400007, 0xaf4300d4, 0x3c020001, 0x90426cf1,
-0xaf4000d4, 0x421026, 0x3c010001, 0xa0226cf1,
-0x3c030001, 0x8c636d98, 0x24020002, 0x1462000c,
-0x3c030002, 0x3c030001, 0x90636cf1, 0x24020001,
-0x5462001f, 0x2021, 0x3c020001, 0x90426cf0,
-0x1443001b, 0x24040005, 0x10000019, 0x24040006,
-0x3c020002, 0x8c428ff4, 0x431024, 0x1040000b,
-0x24020001, 0x3c030001, 0x90636cf1, 0x54620010,
-0x2021, 0x3c020001, 0x90426cf0, 0x1443000c,
-0x24040003, 0x1000000a, 0x24040004, 0x3c030001,
-0x90636cf1, 0x14620006, 0x2021, 0x3c020001,
-0x90426cf0, 0x24040001, 0x50440001, 0x24040002,
-0xc00565a, 0x0, 0x2402ff7f, 0x282a024,
-0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
-0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
-0x27bd0050, 0x3e00008, 0x0, 0x3c020001,
-0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
-0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
-0x104000de, 0xafb00030, 0x8f4200d0, 0x3c040001,
-0x8c846d98, 0x24430001, 0x2842000b, 0xaf4400e8,
-0x144000fe, 0xaf4300d0, 0x8f420004, 0x30420002,
-0x14400095, 0xaf4000d0, 0x8f420004, 0x34420002,
-0xaf420004, 0x24020001, 0x14820003, 0x3c020600,
-0x10000002, 0x34423000, 0x34421000, 0xafa20020,
-0x1821, 0x8f5e0018, 0x27aa0020, 0x240200ff,
-0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228,
-0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c,
-0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228,
-0x3c040001, 0x2484610c, 0x3c050009, 0xafa00014,
-0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500,
-0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0,
-0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8,
-0x2021023, 0x2c4203e9, 0x1040001b, 0x9821,
-0xe08821, 0x263504c0, 0x8f440178, 0x8f45017c,
-0x2201821, 0x240a0004, 0xafaa0010, 0xafb20014,
-0x8f48000c, 0x1021, 0x2f53021, 0xafa80018,
-0x8f48010c, 0x24070008, 0xa32821, 0xa3482b,
-0x822021, 0x100f809, 0x892021, 0x54400006,
-0x24130001, 0x8f820054, 0x2021023, 0x2c4203e9,
-0x1440ffe9, 0x0, 0x326200ff, 0x54400017,
-0xaf520018, 0x8f420378, 0x24420001, 0xaf420378,
-0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24846118, 0x3c050009,
-0xafa20014, 0x8d460000, 0x10000035, 0x34a50600,
-0x8f420308, 0x24130001, 0x24420001, 0xaf420308,
-0x8f420308, 0x1000001e, 0x326200ff, 0x8f830054,
-0x8f820054, 0x247003e8, 0x2021023, 0x2c4203e9,
-0x10400016, 0x9821, 0x3c150020, 0x24110010,
-0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120,
-0xafb10010, 0xafb20014, 0x551025, 0xafa20018,
-0x8f42010c, 0x24070008, 0x40f809, 0x24c6001c,
-0x1440ffe3, 0x0, 0x8f820054, 0x2021023,
-0x2c4203e9, 0x1440ffee, 0x0, 0x326200ff,
-0x14400011, 0x0, 0x8f420378, 0x24420001,
-0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
-0xafa20010, 0x8f820124, 0x3c040001, 0x24846120,
-0x3c050009, 0xafa20014, 0x8d460000, 0x34a50700,
-0xc002b3b, 0x3c03821, 0x8f4202ec, 0x24420001,
-0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001,
-0x10400033, 0x3c020400, 0x2c21024, 0x10400017,
-0x0, 0x934205c0, 0x8f440250, 0x8f450254,
-0x8f4301b4, 0x34420020, 0x14a30006, 0xa34205c0,
-0x8f420270, 0x8f430274, 0x8f4401b8, 0x10640008,
-0x0, 0x8f420250, 0x8f430254, 0x934405c0,
-0x8f460270, 0x8f470274, 0x10000016, 0x38840040,
-0x934205c0, 0x10000048, 0x304200bf, 0x934205c0,
-0x8f440250, 0x8f450254, 0x8f4301b4, 0x304200bf,
-0x14a30006, 0xa34205c0, 0x8f420270, 0x8f430274,
-0x8f4401b8, 0x1064000b, 0x0, 0x8f420250,
-0x8f430254, 0x934405c0, 0x8f460270, 0x8f470274,
-0x38840020, 0xaf4301b4, 0xaf4701b8, 0x10000033,
-0xa34405c0, 0x934205c0, 0x1000002f, 0x34420020,
-0x934205c0, 0x8f4300d4, 0x34420020, 0xa34205c0,
-0x24620001, 0x10000023, 0x28630033, 0x8f4200e4,
-0x8f4300e0, 0x24420001, 0xaf4200e4, 0x43102a,
-0x14400006, 0x24030001, 0x8f4200e8, 0x14430002,
-0xaf4000e4, 0x24030004, 0xaf4300e8, 0x8f420004,
-0x30420001, 0x1040000d, 0x3c020400, 0x2c21024,
-0x10400007, 0x0, 0x934205c0, 0x34420040,
-0xa34205c0, 0x934205c0, 0x1000000f, 0x304200df,
-0x934205c0, 0x1000000c, 0x34420060, 0x934205c0,
-0x8f4300d4, 0x34420020, 0xa34205c0, 0x24620001,
-0x286300fb, 0x14600005, 0xaf4200d4, 0x934205c0,
-0xaf4000d4, 0x38420040, 0xa34205c0, 0x934205c0,
-0x8f4300e8, 0x3042007f, 0xa34205c0, 0x24020001,
-0x14620005, 0x0, 0x934405c0, 0x42102,
-0x10000003, 0x348400f0, 0x934405c0, 0x3484000f,
-0xc005640, 0x0, 0x2402ff7f, 0x282a024,
-0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
-0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
-0x27bd0050, 0x3e00008, 0x0, 0x27bdffb0,
-0x274401c0, 0x26e30028, 0x24650400, 0x65102b,
-0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c,
-0xafb20038, 0xafb10034, 0x10400007, 0xafb00030,
-0x8c820000, 0xac620000, 0x24630004, 0x65102b,
-0x1440fffb, 0x24840004, 0x8c020080, 0xaee20044,
-0x8c0200c0, 0xaee20040, 0x8c020084, 0xaee20030,
-0x8c020084, 0xaee2023c, 0x8c020088, 0xaee20240,
-0x8c02008c, 0xaee20244, 0x8c020090, 0xaee20248,
-0x8c020094, 0xaee2024c, 0x8c020098, 0xaee20250,
-0x8c02009c, 0xaee20254, 0x8c0200a0, 0xaee20258,
-0x8c0200a4, 0xaee2025c, 0x8c0200a8, 0xaee20260,
-0x8c0200ac, 0xaee20264, 0x8c0200b0, 0xaee20268,
-0x8c0200b4, 0xaee2026c, 0x8c0200b8, 0xaee20270,
-0x8c0200bc, 0x24040001, 0xaee20274, 0xaee00034,
-0x41080, 0x571021, 0x8ee30034, 0x8c42023c,
-0x24840001, 0x621821, 0x2c82000f, 0xaee30034,
-0x1440fff8, 0x41080, 0x8c0200cc, 0xaee20048,
-0x8c0200d0, 0xaee2004c, 0x8c0200e0, 0xaee201f8,
-0x8c0200e4, 0xaee201fc, 0x8c0200e8, 0xaee20200,
-0x8c0200ec, 0xaee20204, 0x8c0200f0, 0xaee20208,
-0x8ee400c0, 0x8ee500c4, 0x8c0200fc, 0x45102b,
-0x1040000b, 0x0, 0x8ee200c0, 0x8ee300c4,
-0x24040001, 0x24050000, 0x651821, 0x65302b,
-0x441021, 0x461021, 0xaee200c0, 0xaee300c4,
-0x8c0200fc, 0x8ee400c0, 0x8ee500c4, 0x2408ffff,
-0x24090000, 0x401821, 0x1021, 0x882024,
-0xa92824, 0x822025, 0xa32825, 0xaee400c0,
-0xaee500c4, 0x8ee400d0, 0x8ee500d4, 0x8c0200f4,
-0x45102b, 0x1040000b, 0x0, 0x8ee200d0,
-0x8ee300d4, 0x24040001, 0x24050000, 0x651821,
-0x65302b, 0x441021, 0x461021, 0xaee200d0,
-0xaee300d4, 0x8c0200f4, 0x8ee400d0, 0x8ee500d4,
-0x401821, 0x1021, 0x882024, 0xa92824,
-0x822025, 0xa32825, 0xaee400d0, 0xaee500d4,
-0x8ee400c8, 0x8ee500cc, 0x8c0200f8, 0x45102b,
-0x1040000b, 0x0, 0x8ee200c8, 0x8ee300cc,
-0x24040001, 0x24050000, 0x651821, 0x65302b,
-0x441021, 0x461021, 0xaee200c8, 0xaee300cc,
-0x8c0200f8, 0x8ee400c8, 0x8ee500cc, 0x401821,
-0x1021, 0x882024, 0xa92824, 0x822025,
-0xa32825, 0x24020008, 0xaee400c8, 0xaee500cc,
-0xafa20010, 0xafa00014, 0x8f42000c, 0x8c040208,
-0x8c05020c, 0xafa20018, 0x8f42010c, 0x26e60028,
-0x40f809, 0x24070400, 0x104000f0, 0x3c020400,
-0xafa20020, 0x934205c6, 0x10400089, 0x1821,
-0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
-0xafaa002c, 0x27c30001, 0x8c020228, 0x609021,
-0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
-0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010,
-0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
-0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
-0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
-0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
-0x24070008, 0xa32821, 0xa3482b, 0x822021,
-0x100f809, 0x892021, 0x54400006, 0x24130001,
-0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
-0x0, 0x326200ff, 0x54400017, 0xaf520018,
-0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
-0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124,
-0x3c040001, 0x24846118, 0x3c050009, 0xafa20014,
-0x8d460000, 0x10000033, 0x34a50600, 0x8f420308,
-0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
-0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
-0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
-0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
-0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
-0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
-0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
-0x326200ff, 0x54400012, 0x24020001, 0x8f420378,
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
-0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24846120, 0x3c050009, 0xafa20014, 0x8d460000,
-0x34a50700, 0xc002b3b, 0x3c03821, 0x1021,
-0x1440005b, 0x24020001, 0x10000065, 0x0,
-0x8f510018, 0x240200ff, 0x12220002, 0x8021,
-0x26300001, 0x8c020228, 0x1602000e, 0x1130c0,
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
-0x8c020228, 0x3c040001, 0x248460f4, 0x3c050009,
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f,
-0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024,
-0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
-0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
-0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021,
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x248460fc, 0x3c050009,
-0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200,
-0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018,
-0x8f860120, 0x24020010, 0xafa20010, 0xafb00014,
-0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x54400011, 0x24020001, 0x8f420340, 0x24420001,
-0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24846104, 0x3c050009,
-0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b,
-0x2203821, 0x1021, 0x1040000d, 0x24020001,
-0x8f4202e8, 0xa34005c6, 0xaf4001b0, 0x24420001,
-0xaf4202e8, 0x8f4202e8, 0x8ee20150, 0x24420001,
-0xaee20150, 0x10000003, 0x8ee20150, 0x24020001,
-0xa34205c6, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
-0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
-0x3e00008, 0x27bd0050, 0x27bdffd8, 0xafbf0020,
-0x8f8200b0, 0x30420004, 0x10400068, 0x0,
-0x8f430128, 0x8f820104, 0x14620005, 0x0,
-0x8f430130, 0x8f8200b4, 0x10620006, 0x0,
-0x8f820104, 0xaf420128, 0x8f8200b4, 0x1000005b,
-0xaf420130, 0x8f8200b0, 0x3c030080, 0x431024,
-0x1040000d, 0x0, 0x8f82011c, 0x34420002,
-0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024,
-0xaf8200b0, 0x8f82011c, 0x2403fffd, 0x431024,
-0x1000004a, 0xaf82011c, 0x8f430128, 0x8f820104,
-0x14620005, 0x0, 0x8f430130, 0x8f8200b4,
-0x10620010, 0x0, 0x8f820104, 0xaf420128,
-0x8f8200b4, 0x8f430128, 0xaf420130, 0xafa30010,
-0x8f420130, 0x3c040001, 0x24846144, 0xafa20014,
-0x8f86011c, 0x8f8700b0, 0x3c050005, 0x10000031,
-0x34a50900, 0x8f420128, 0xafa20010, 0x8f420130,
-0x3c040001, 0x24846150, 0xafa20014, 0x8f86011c,
-0x8f8700b0, 0x3c050005, 0xc002b3b, 0x34a51000,
-0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104,
-0x8f8200b0, 0x34420001, 0xaf8200b0, 0x24020008,
-0xaf830104, 0xafa20010, 0xafa00014, 0x8f42000c,
-0x8c040208, 0x8c05020c, 0xafa20018, 0x8f42010c,
-0x26e60028, 0x40f809, 0x24070400, 0x8f82011c,
-0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc,
-0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f420128,
-0xafa20010, 0x8f420130, 0x3c040001, 0x2484615c,
-0xafa20014, 0x8f86011c, 0x8f8700b0, 0x3c050005,
-0x34a51100, 0xc002b3b, 0x0, 0x8f8200a0,
-0x30420004, 0x10400069, 0x0, 0x8f43012c,
-0x8f820124, 0x14620005, 0x0, 0x8f430134,
-0x8f8200a4, 0x10620006, 0x0, 0x8f820124,
-0xaf42012c, 0x8f8200a4, 0x1000005c, 0xaf420134,
-0x8f8200a0, 0x3c030080, 0x431024, 0x1040000d,
-0x0, 0x8f82011c, 0x34420002, 0xaf82011c,
-0x8f8200a0, 0x2403fffb, 0x431024, 0xaf8200a0,
-0x8f82011c, 0x2403fffd, 0x431024, 0x1000004b,
-0xaf82011c, 0x8f43012c, 0x8f820124, 0x14620005,
-0x0, 0x8f430134, 0x8f8200a4, 0x10620010,
-0x0, 0x8f820124, 0xaf42012c, 0x8f8200a4,
-0x8f43012c, 0xaf420134, 0xafa30010, 0x8f420134,
-0x3c040001, 0x24846168, 0xafa20014, 0x8f86011c,
-0x8f8700a0, 0x3c050005, 0x10000032, 0x34a51200,
-0x8f42012c, 0xafa20010, 0x8f420134, 0x3c040001,
-0x24846174, 0xafa20014, 0x8f86011c, 0x8f8700a0,
-0x3c050005, 0xc002b3b, 0x34a51300, 0x8f82011c,
-0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0,
-0x34420001, 0xaf8200a0, 0x24020080, 0xaf830124,
-0xafa20010, 0xafa00014, 0x8f420014, 0x8c040208,
-0x8c05020c, 0xafa20018, 0x8f420108, 0x3c060001,
-0x24c66ed8, 0x40f809, 0x24070004, 0x8f82011c,
-0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc,
-0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f42012c,
-0xafa20010, 0x8f420134, 0x3c040001, 0x24846180,
-0xafa20014, 0x8f86011c, 0x8f8700a0, 0x3c050005,
-0x34a51400, 0xc002b3b, 0x0, 0x8fbf0020,
-0x3e00008, 0x27bd0028, 0x3c081000, 0x24070001,
-0x3c060080, 0x3c050100, 0x8f820070, 0x481024,
-0x1040fffd, 0x0, 0x8f820054, 0x24420005,
-0xaf820078, 0x8c040234, 0x10800016, 0x1821,
-0x3c020001, 0x571021, 0x8c4240e8, 0x24420005,
-0x3c010001, 0x370821, 0xac2240e8, 0x3c020001,
-0x571021, 0x8c4240e8, 0x44102b, 0x14400009,
-0x0, 0x3c030080, 0x3c010001, 0x370821,
-0xac2040e8, 0x3c010001, 0x370821, 0x1000000b,
-0xa02740f0, 0x3c020001, 0x571021, 0x904240f0,
-0x54400006, 0x661825, 0x3c020001, 0x571021,
-0x904240f1, 0x54400001, 0x661825, 0x8c040230,
-0x10800013, 0x0, 0x3c020001, 0x571021,
-0x8c4240ec, 0x24420005, 0x3c010001, 0x370821,
-0xac2240ec, 0x3c020001, 0x571021, 0x8c4240ec,
-0x44102b, 0x14400006, 0x0, 0x3c010001,
-0x370821, 0xac2040ec, 0x10000006, 0x651825,
-0x3c020001, 0x571021, 0x904240f2, 0x54400001,
-0x651825, 0x1060ffbc, 0x0, 0x8f420000,
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x431025, 0xaf820060, 0x8f420000,
-0x10400003, 0x0, 0x1000ffa7, 0xaf80004c,
-0x1000ffa5, 0xaf800048, 0x3e00008, 0x0,
-0x0, 0x0, 0x0, 0x27bdffe0,
-0xafbf0018, 0x8f860064, 0x30c20004, 0x10400025,
-0x24040004, 0x8c020114, 0xaf420020, 0xaf840064,
-0x8f4202fc, 0x24420001, 0xaf4202fc, 0x8f4202fc,
-0x8f820064, 0x30420004, 0x14400005, 0x0,
-0x8c030114, 0x8f420020, 0x1462fff2, 0x0,
-0x8f420000, 0x10400007, 0x8f43003c, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x431025, 0xaf820060,
-0x8f420000, 0x10400073, 0x0, 0x1000006f,
-0x0, 0x30c20008, 0x10400020, 0x24040008,
-0x8c02011c, 0xaf420048, 0xaf840064, 0x8f4202a8,
-0x24420001, 0xaf4202a8, 0x8f4202a8, 0x8f820064,
-0x30420008, 0x14400005, 0x0, 0x8c03011c,
-0x8f420048, 0x1462fff2, 0x0, 0x8f420000,
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x1000ffd9, 0x34420200, 0x30c20020,
-0x10400023, 0x24040020, 0x8c02012c, 0xaf420068,
-0xaf840064, 0x8f4202d8, 0x24420001, 0xaf4202d8,
-0x8f4202d8, 0x8f820064, 0x30420020, 0x14400005,
-0x32c24000, 0x8c03012c, 0x8f420068, 0x1462fff2,
-0x32c24000, 0x14400002, 0x3c020001, 0x2c2b025,
-0x8f420000, 0x10400007, 0x0, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x1000ffb4, 0x34420800,
-0x30c20010, 0x10400029, 0x24040010, 0x8c020124,
-0xaf420058, 0xaf840064, 0x8f4202d4, 0x24420001,
-0xaf4202d4, 0x8f4202d4, 0x8f820064, 0x30420010,
-0x14400005, 0x32c22000, 0x8c030124, 0x8f420058,
-0x1462fff2, 0x32c22000, 0x50400001, 0x36d68000,
-0x8f420000, 0x10400007, 0x0, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x34420100, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x1000006c,
-0xaf80004c, 0x1000006a, 0xaf800048, 0x30c20001,
-0x10400004, 0x24020001, 0xaf820064, 0x10000064,
-0x0, 0x30c20002, 0x1440000b, 0x3c050003,
-0x3c040001, 0x24846244, 0x34a50500, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x2402ffc0,
-0x10000057, 0xaf820064, 0x8c05022c, 0x8c02010c,
-0x10a20048, 0x51080, 0x8c460300, 0x24a20001,
-0x3045003f, 0x24020003, 0xac05022c, 0x61e02,
-0x10620005, 0x24020010, 0x1062001d, 0x30c20fff,
-0x10000039, 0x0, 0x8f4302a8, 0x8f440000,
-0x30c20fff, 0xaf420048, 0x24630001, 0xaf4302a8,
-0x10800007, 0x8f4202a8, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x34420200, 0xaf820060, 0x8f420000,
-0x1040001f, 0x0, 0x1000001b, 0x0,
-0xaf420058, 0x32c22000, 0x50400001, 0x36d68000,
-0x8f4202d4, 0x8f430000, 0x24420001, 0xaf4202d4,
-0x10600007, 0x8f4202d4, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x34420100, 0xaf820060, 0x8f420000,
-0x10400003, 0x0, 0x10000006, 0xaf80004c,
-0x10000004, 0xaf800048, 0xc002196, 0xc02021,
-0x402821, 0x8c02010c, 0x14a20002, 0x24020002,
-0xaf820064, 0x8f820064, 0x30420002, 0x14400004,
-0x0, 0x8c02010c, 0x14a2ffac, 0x0,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008,
-0x0, 0x27bdffa0, 0xafb00040, 0x808021,
-0x101602, 0x2442ffff, 0x304300ff, 0x2c620013,
-0xafbf0058, 0xafbe0054, 0xafb50050, 0xafb3004c,
-0xafb20048, 0xafb10044, 0x104001f3, 0xafa50034,
-0x31080, 0x3c010001, 0x220821, 0x8c226288,
-0x400008, 0x0, 0x101302, 0x30440fff,
-0x24020001, 0x10820005, 0x24020002, 0x1082000c,
-0x2402fffe, 0x10000024, 0x3c050003, 0x8f430004,
-0x3c020001, 0x8c426f04, 0xaf440200, 0xaf440204,
-0x3c040001, 0x8c846e80, 0x10000009, 0x34630001,
-0x8f430004, 0xaf440200, 0xaf440204, 0x3c040001,
-0x8c846e80, 0x621824, 0x3c020001, 0x2442ca28,
-0x21100, 0x21182, 0xaf430004, 0x3c030800,
-0x431025, 0xac820038, 0x8f840054, 0x41442,
-0x41c82, 0x431021, 0x41cc2, 0x431023,
-0x41d02, 0x431021, 0x41d42, 0x431023,
-0x10000009, 0xaf420208, 0x3c040001, 0x24846250,
-0x34a51000, 0x2003021, 0x3821, 0xafa00010,
-0xc002b3b, 0xafa00014, 0x8f4202a0, 0x24420001,
-0xaf4202a0, 0x1000021f, 0x8f4202a0, 0x27b00028,
-0x2002021, 0x24050210, 0xc002bbf, 0x24060008,
-0xc002518, 0x2002021, 0x10000216, 0x0,
-0x8faa0034, 0x27a40028, 0xa1880, 0x25420001,
-0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034,
-0x21080, 0x8c430300, 0x25420001, 0x3042003f,
-0xafa20034, 0xac02022c, 0xafa50028, 0xc002518,
-0xafa3002c, 0x10000203, 0x0, 0x27b00028,
-0x2002021, 0x24050210, 0xc002bbf, 0x24060008,
-0xc002657, 0x2002021, 0x100001fa, 0x0,
-0x8faa0034, 0x27a40028, 0xa1880, 0x25420001,
-0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034,
-0x21080, 0x8c430300, 0x25420001, 0x3042003f,
-0xafa20034, 0xac02022c, 0xafa50028, 0xc002657,
-0xafa3002c, 0x100001e7, 0x0, 0x101302,
-0x30430fff, 0x24020001, 0x10620005, 0x24020002,
-0x1062001e, 0x3c020002, 0x10000033, 0x3c050003,
-0x3c030002, 0x2c31024, 0x54400037, 0x2c3b025,
-0x8f820228, 0x3c010001, 0x370821, 0xac2238d8,
-0x8f82022c, 0x3c010001, 0x370821, 0xac2238dc,
-0x8f820230, 0x3c010001, 0x370821, 0xac2238e0,
-0x8f820234, 0x3c010001, 0x370821, 0xac2238e4,
-0x2402ffff, 0xaf820228, 0xaf82022c, 0xaf820230,
-0xaf820234, 0x10000020, 0x2c3b025, 0x2c21024,
-0x10400012, 0x3c02fffd, 0x3c020001, 0x571021,
-0x8c4238d8, 0xaf820228, 0x3c020001, 0x571021,
-0x8c4238dc, 0xaf82022c, 0x3c020001, 0x571021,
-0x8c4238e0, 0xaf820230, 0x3c020001, 0x571021,
-0x8c4238e4, 0xaf820234, 0x3c02fffd, 0x3442ffff,
-0x10000009, 0x2c2b024, 0x3c040001, 0x2484625c,
-0x34a51100, 0x2003021, 0x3821, 0xafa00010,
-0xc002b3b, 0xafa00014, 0x8f4202cc, 0x24420001,
-0xaf4202cc, 0x1000019f, 0x8f4202cc, 0x101302,
-0x30450fff, 0x24020001, 0x10a20005, 0x24020002,
-0x10a2000d, 0x3c0408ff, 0x10000014, 0x3c050003,
-0x3c0208ff, 0x3442ffff, 0x8f830220, 0x3c040004,
-0x2c4b025, 0x621824, 0x34630008, 0xaf830220,
-0x10000012, 0xaf450298, 0x3484fff7, 0x3c03fffb,
-0x8f820220, 0x3463ffff, 0x2c3b024, 0x441024,
-0xaf820220, 0x10000009, 0xaf450298, 0x3c040001,
-0x24846268, 0x34a51200, 0x2003021, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202bc,
-0x24420001, 0xaf4202bc, 0x10000176, 0x8f4202bc,
-0x27840208, 0x24050200, 0xc002bbf, 0x24060008,
-0x27440224, 0x24050200, 0xc002bbf, 0x24060008,
-0x8f4202c4, 0x24420001, 0xaf4202c4, 0x10000169,
-0x8f4202c4, 0x101302, 0x30430fff, 0x24020001,
-0x10620011, 0x28620002, 0x50400005, 0x24020002,
-0x10600007, 0x0, 0x10000017, 0x0,
-0x1062000f, 0x0, 0x10000013, 0x0,
-0x8c060248, 0x2021, 0xc005104, 0x24050004,
-0x10000007, 0x0, 0x8c060248, 0x2021,
-0xc005104, 0x24050004, 0x10000010, 0x0,
-0x8c06024c, 0x2021, 0xc005104, 0x24050001,
-0x1000000a, 0x0, 0x3c040001, 0x24846274,
-0x3c050003, 0x34a51300, 0x2003021, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202c0,
-0x24420001, 0xaf4202c0, 0x1000013a, 0x8f4202c0,
-0xc002426, 0x0, 0x10000136, 0x0,
-0x24020001, 0xa34205c5, 0x24100100, 0x8f4401a8,
-0x8f4501ac, 0xafb00010, 0xafa00014, 0x8f420014,
-0xafa20018, 0x8f420108, 0x26e60028, 0x40f809,
-0x24070400, 0x1040fff5, 0x0, 0x10000125,
-0x0, 0x3c03ffff, 0x34637fff, 0x8f420368,
-0x8f440360, 0x2c3b024, 0x1821, 0xaf400058,
-0xaf40005c, 0xaf400060, 0xaf400064, 0x441023,
-0xaf420368, 0x3c020900, 0xaf400360, 0xafa20020,
-0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
-0xafaa003c, 0x27c30001, 0x8c020228, 0x609021,
-0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
-0x2484620c, 0x3c050009, 0xafa00014, 0xafa20010,
-0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
-0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
-0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
-0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
-0x24070008, 0xa32821, 0xa3482b, 0x822021,
-0x100f809, 0x892021, 0x54400006, 0x24130001,
-0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
-0x0, 0x326200ff, 0x54400017, 0xaf520018,
-0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
-0x8f820120, 0x8faa003c, 0xafa20010, 0x8f820124,
-0x3c040001, 0x24846218, 0x3c050009, 0xafa20014,
-0x8d460000, 0x10000033, 0x34a50600, 0x8f420308,
-0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
-0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
-0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
-0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
-0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
-0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
-0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
-0x326200ff, 0x14400011, 0x0, 0x8f420378,
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
-0x8faa003c, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24846220, 0x3c050009, 0xafa20014, 0x8d460000,
-0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b0,
-0x24420001, 0xaf4202b0, 0x8f4202b0, 0x8f4202f8,
-0x24420001, 0xaf4202f8, 0x1000008a, 0x8f4202f8,
-0x8c02025c, 0x27440224, 0xaf4201f0, 0x8c020260,
-0x24050200, 0x24060008, 0xc002bbf, 0xaf4201f8,
-0x8f820220, 0x30420008, 0x14400002, 0x24020001,
-0x24020002, 0xaf420298, 0x8f4202ac, 0x24420001,
-0xaf4202ac, 0x10000077, 0x8f4202ac, 0x3c0200ff,
-0x3442ffff, 0x2021824, 0x32c20180, 0x14400006,
-0x3402fffb, 0x43102b, 0x14400003, 0x0,
-0x1000006c, 0xaf4300bc, 0x3c040001, 0x24846280,
-0x3c050003, 0x34a51500, 0x2003021, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020700,
-0x34421000, 0x101e02, 0x621825, 0xafa30020,
-0x8f510018, 0x240200ff, 0x12220002, 0x8021,
-0x26300001, 0x8c020228, 0x1602000e, 0x1130c0,
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
-0x8c020228, 0x3c040001, 0x248461f4, 0x3c050009,
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f,
-0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024,
-0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
-0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
-0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021,
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x248461fc, 0x3c050009,
-0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200,
-0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018,
-0x8f860120, 0x24020010, 0xafa20010, 0xafb00014,
-0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400010, 0x0, 0x8f420340, 0x24420001,
-0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24846204, 0x3c050009,
-0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b,
-0x2203821, 0x8f4202e0, 0x24420001, 0xaf4202e0,
-0x8f4202e0, 0x8f4202f0, 0x24420001, 0xaf4202f0,
-0x8f4202f0, 0x8fa20034, 0x8fbf0058, 0x8fbe0054,
-0x8fb50050, 0x8fb3004c, 0x8fb20048, 0x8fb10044,
-0x8fb00040, 0x3e00008, 0x27bd0060, 0x27bdfff8,
-0x2408ffff, 0x10a00014, 0x4821, 0x3c0aedb8,
-0x354a8320, 0x90870000, 0x24840001, 0x3021,
-0x1071026, 0x30420001, 0x10400002, 0x81842,
-0x6a1826, 0x604021, 0x24c60001, 0x2cc20008,
-0x1440fff7, 0x73842, 0x25290001, 0x125102b,
-0x1440fff0, 0x0, 0x1001021, 0x3e00008,
-0x27bd0008, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
-0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
-0xafb00030, 0x8f870220, 0xafa70024, 0x8f870200,
-0xafa7002c, 0x8f820220, 0x3c0308ff, 0x3463ffff,
-0x431024, 0x34420004, 0xaf820220, 0x8f820200,
-0x3c03c0ff, 0x3463ffff, 0x431024, 0x34420004,
-0xaf820200, 0x8f530358, 0x8f55035c, 0x8f5e0360,
-0x8f470364, 0xafa70014, 0x8f470368, 0xafa7001c,
-0x8f4202d0, 0x274401c0, 0x24420001, 0xaf4202d0,
-0x8f5002d0, 0x8f510204, 0x8f520200, 0xc002ba8,
-0x24050400, 0xaf530358, 0xaf55035c, 0xaf5e0360,
-0x8fa70014, 0xaf470364, 0x8fa7001c, 0xaf470368,
-0xaf5002d0, 0xaf510204, 0xaf520200, 0x8c02025c,
-0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200,
-0x24060008, 0xaf4201f8, 0x24020006, 0xc002bbf,
-0xaf4201f4, 0x3c023b9a, 0x3442ca00, 0xaf4201fc,
-0x240203e8, 0x24040002, 0x24030001, 0xaf420294,
-0xaf440290, 0xaf43029c, 0x8f820220, 0x30420008,
-0x10400004, 0x0, 0xaf430298, 0x10000003,
-0x3021, 0xaf440298, 0x3021, 0x3c030001,
-0x661821, 0x90636d00, 0x3461021, 0x24c60001,
-0xa043022c, 0x2cc2000f, 0x1440fff8, 0x3461821,
-0x24c60001, 0x8f820040, 0x24040080, 0x24050080,
-0x21702, 0x24420030, 0xa062022c, 0x3461021,
-0xc002ba8, 0xa040022c, 0x8fa70024, 0x30e20004,
-0x14400006, 0x0, 0x8f820220, 0x3c0308ff,
-0x3463fffb, 0x431024, 0xaf820220, 0x8fa7002c,
-0x30e20004, 0x14400006, 0x0, 0x8f820200,
-0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200,
-0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
-0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
-0x27bd0050, 0x0, 0x0, 0xaf400104,
-0x24040001, 0x410c0, 0x2e21821, 0x24820001,
-0x3c010001, 0x230821, 0xa42234d0, 0x402021,
-0x2c820080, 0x1440fff8, 0x410c0, 0x24020001,
-0x3c010001, 0x370821, 0xa42038d0, 0xaf420100,
-0xaf800228, 0xaf80022c, 0xaf800230, 0xaf800234,
-0x3e00008, 0x0, 0x27bdffe8, 0xafbf0014,
-0xafb00010, 0x8f420104, 0x28420005, 0x10400026,
-0x808021, 0x3c020001, 0x8f430104, 0x344230d0,
-0x2e22021, 0x318c0, 0x621821, 0x2e31821,
-0x83102b, 0x10400015, 0x1021, 0x96070000,
-0x24840006, 0x24660006, 0x9482fffc, 0x14470009,
-0x2821, 0x9483fffe, 0x96020002, 0x14620006,
-0xa01021, 0x94820000, 0x96030004, 0x431026,
-0x2c450001, 0xa01021, 0x14400009, 0x24840008,
-0x86102b, 0x1440fff0, 0x1021, 0x304200ff,
-0x14400030, 0x24020001, 0x1000002e, 0x1021,
-0x1000fffa, 0x24020001, 0x2002021, 0xc00240c,
-0x24050006, 0x3042007f, 0x218c0, 0x2e31021,
-0x3c010001, 0x220821, 0x942230d0, 0x1040fff2,
-0x2e31021, 0x3c060001, 0xc23021, 0x94c630d0,
-0x10c0ffed, 0x3c080001, 0x350834d2, 0x96070000,
-0x610c0, 0x572021, 0x882021, 0x94820000,
-0x14470009, 0x2821, 0x94830002, 0x96020002,
-0x14620006, 0xa01021, 0x94820004, 0x96030004,
-0x431026, 0x2c450001, 0xa01021, 0x14400007,
-0x610c0, 0x2e21021, 0x3c060001, 0xc23021,
-0x94c634d0, 0x14c0ffeb, 0x610c0, 0x10c0ffd2,
-0x24020001, 0x8fbf0014, 0x8fb00010, 0x3e00008,
-0x27bd0018, 0x3e00008, 0x0, 0x27bdffb0,
-0x801021, 0xafb00030, 0x24500002, 0x2002021,
-0x24050006, 0xafb10034, 0x408821, 0xafbf0048,
-0xafbe0044, 0xafb50040, 0xafb3003c, 0xc00240c,
-0xafb20038, 0x3047007f, 0x710c0, 0x2e21021,
-0x3c050001, 0xa22821, 0x94a530d0, 0x50a0001c,
-0xa03021, 0x3c090001, 0x352934d2, 0x96280002,
-0x510c0, 0x572021, 0x892021, 0x94820000,
-0x14480009, 0x3021, 0x94830002, 0x96020002,
-0x14620006, 0xc01021, 0x94820004, 0x96030004,
-0x431026, 0x2c460001, 0xc01021, 0x14400007,
-0x510c0, 0x2e21021, 0x3c050001, 0xa22821,
-0x94a534d0, 0x14a0ffeb, 0x510c0, 0xa03021,
-0x10c00014, 0x610c0, 0x571821, 0x3c010001,
-0x230821, 0x8c2334d0, 0x571021, 0xafa30010,
-0x3c010001, 0x220821, 0x8c2234d4, 0x3c040001,
-0x24846394, 0xafa20014, 0x8e260000, 0x8e270004,
-0x3c050004, 0xc002b3b, 0x34a50400, 0x10000063,
-0x3c020800, 0x8f450100, 0x10a00006, 0x510c0,
-0x2e21021, 0x3c010001, 0x220821, 0x942234d0,
-0xaf420100, 0xa03021, 0x14c00011, 0x628c0,
-0x710c0, 0x2e21021, 0xafa70010, 0x3c010001,
-0x220821, 0x942230d0, 0x3c040001, 0x248463a0,
-0xafa20014, 0x8e260000, 0x8e270004, 0x3c050004,
-0xc002b3b, 0x34a50500, 0x10000048, 0x3c020800,
-0xb71821, 0x3c020001, 0x96040000, 0x344234d2,
-0x621821, 0xa4640000, 0x8e020002, 0x720c0,
-0xac620002, 0x2e41021, 0x3c030001, 0x621821,
-0x946330d0, 0x2e51021, 0x3c010001, 0x220821,
-0xa42334d0, 0x2e41021, 0x3c010001, 0x220821,
-0xa42630d0, 0x8f420104, 0x24420001, 0x28420080,
-0x1040000f, 0x3c020002, 0x8f420104, 0x3c040001,
-0x348430d2, 0x96030000, 0x210c0, 0x571021,
-0x441021, 0xa4430000, 0x8e030002, 0xac430002,
-0x8f420104, 0x24420001, 0xaf420104, 0x3c020002,
-0x2c21024, 0x10400011, 0x72142, 0x3c030001,
-0x346338d8, 0x24020003, 0x441023, 0x21080,
-0x572021, 0x832021, 0x571021, 0x431021,
-0x30e5001f, 0x8c430000, 0x24020001, 0xa21004,
-0x621825, 0x1000000c, 0xac830000, 0x24020003,
-0x441023, 0x21080, 0x5c2821, 0x5c1021,
-0x30e4001f, 0x8c430228, 0x24020001, 0x821004,
-0x621825, 0xaca30228, 0x3c020800, 0x34421000,
-0x1821, 0xafa20020, 0x8f5e0018, 0x27aa0020,
-0x240200ff, 0x13c20002, 0xafaa002c, 0x27c30001,
-0x8c020228, 0x609021, 0x1642000e, 0x1e38c0,
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
-0x8c020228, 0x3c040001, 0x2484635c, 0x3c050009,
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b,
-0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024,
-0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b,
-0x9821, 0xe08821, 0x263504c0, 0x8f440178,
-0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010,
-0xafb20014, 0x8f48000c, 0x1021, 0x2f53021,
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x54400006, 0x24130001, 0x8f820054, 0x2021023,
-0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff,
-0x54400017, 0xaf520018, 0x8f420378, 0x24420001,
-0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
-0xafa20010, 0x8f820124, 0x3c040001, 0x24846368,
-0x3c050009, 0xafa20014, 0x8d460000, 0x10000033,
-0x34a50600, 0x8f420308, 0x24130001, 0x24420001,
-0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff,
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x10400014, 0x9821, 0x24110010,
-0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120,
-0xafb10010, 0xafb20014, 0xafa20018, 0x8f42010c,
-0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe5,
-0x0, 0x8f820054, 0x2021023, 0x2c4203e9,
-0x1440ffef, 0x0, 0x326200ff, 0x14400011,
-0x0, 0x8f420378, 0x24420001, 0xaf420378,
-0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24846370, 0x3c050009,
-0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b,
-0x3c03821, 0x8f4202b4, 0x24420001, 0xaf4202b4,
-0x8f4202b4, 0x8f4202f4, 0x24420001, 0xaf4202f4,
-0x8f4202f4, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
-0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
-0x3e00008, 0x27bd0050, 0x27bdffa0, 0x801021,
-0xafb00040, 0x24500002, 0x2002021, 0x24050006,
-0xafb10044, 0x408821, 0xafbf0058, 0xafbe0054,
-0xafb50050, 0xafb3004c, 0xc00240c, 0xafb20048,
-0x3048007f, 0x810c0, 0x2e21021, 0x3c060001,
-0xc23021, 0x94c630d0, 0x10c0001c, 0x3821,
-0x3c0a0001, 0x354a34d2, 0x96290002, 0x610c0,
-0x572021, 0x8a2021, 0x94820000, 0x14490009,
-0x2821, 0x94830002, 0x96020002, 0x14620006,
-0xa01021, 0x94820004, 0x96030004, 0x431026,
-0x2c450001, 0xa01021, 0x14400008, 0x610c0,
-0xc03821, 0x2e21021, 0x3c060001, 0xc23021,
-0x94c634d0, 0x14c0ffea, 0x610c0, 0x14c00011,
-0xafa70028, 0x810c0, 0x2e21021, 0xafa80010,
-0x3c010001, 0x220821, 0x942230d0, 0x3c040001,
-0x248463ac, 0xafa20014, 0x8e260000, 0x8e270004,
-0x3c050004, 0xc002b3b, 0x34a50900, 0x10000075,
-0x3c020800, 0x10e0000c, 0x610c0, 0x2e21021,
-0x3c030001, 0x621821, 0x946334d0, 0x710c0,
-0x2e21021, 0x3c010001, 0x220821, 0xa42334d0,
-0x1000000b, 0x3c040001, 0x2e21021, 0x3c030001,
-0x621821, 0x946334d0, 0x810c0, 0x2e21021,
-0x3c010001, 0x220821, 0xa42330d0, 0x3c040001,
-0x348430d0, 0x8f430100, 0x610c0, 0x2e21021,
-0x3c010001, 0x220821, 0xa42334d0, 0x8f420104,
-0x2e43821, 0x2821, 0x18400029, 0xaf460100,
-0x24e60006, 0x94c3fffc, 0x96020000, 0x14620009,
-0x2021, 0x94c3fffe, 0x96020002, 0x14620006,
-0x801021, 0x94c20000, 0x96030004, 0x431026,
-0x2c440001, 0x801021, 0x50400014, 0x24a50001,
-0x8f420104, 0x2442ffff, 0xa2102a, 0x1040000b,
-0x24e40004, 0x94820006, 0x8c830008, 0xa482fffe,
-0xac830000, 0x8f420104, 0x24a50001, 0x2442ffff,
-0xa2102a, 0x1440fff7, 0x24840008, 0x8f420104,
-0x2442ffff, 0x10000006, 0xaf420104, 0x8f420104,
-0x24c60008, 0xa2102a, 0x1440ffda, 0x24e70008,
-0x810c0, 0x2e21021, 0x3c010001, 0x220821,
-0x942230d0, 0x14400023, 0x3c020800, 0x3c020002,
-0x2c21024, 0x10400012, 0x82142, 0x3c030001,
-0x346338d8, 0x24020003, 0x441023, 0x21080,
-0x572021, 0x832021, 0x571021, 0x431021,
-0x3105001f, 0x24030001, 0x8c420000, 0xa31804,
-0x31827, 0x431024, 0x1000000d, 0xac820000,
-0x24020003, 0x441023, 0x21080, 0x5c2821,
-0x5c1021, 0x3104001f, 0x24030001, 0x8c420228,
-0x831804, 0x31827, 0x431024, 0xaca20228,
-0x3c020800, 0x34422000, 0x1821, 0xafa20020,
-0x8f5e0018, 0x27ab0020, 0x240200ff, 0x13c20002,
-0xafab0034, 0x27c30001, 0x8c020228, 0x609021,
-0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
-0x2484635c, 0x3c050009, 0xafa00014, 0xafa20010,
-0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
-0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
-0x240b0004, 0xafab0010, 0xafb20014, 0x8f48000c,
-0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
-0x24070008, 0xa32821, 0xa3482b, 0x822021,
-0x100f809, 0x892021, 0x54400006, 0x24130001,
-0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
-0x0, 0x326200ff, 0x54400017, 0xaf520018,
-0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
-0x8f820120, 0x8fab0034, 0xafa20010, 0x8f820124,
-0x3c040001, 0x24846368, 0x3c050009, 0xafa20014,
-0x8d660000, 0x10000033, 0x34a50600, 0x8f420308,
-0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
-0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
-0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
-0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
-0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
-0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
-0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
-0x326200ff, 0x14400011, 0x0, 0x8f420378,
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
-0x8fab0034, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24846370, 0x3c050009, 0xafa20014, 0x8d660000,
-0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b8,
-0x24420001, 0xaf4202b8, 0x8f4202b8, 0x8f4202f4,
-0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8fbf0058,
-0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048,
-0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060,
-0x0, 0x0, 0x0, 0x27bdffe0,
-0x27644000, 0xafbf0018, 0xc002ba8, 0x24051000,
-0x3c030001, 0x34632cc0, 0x3c040001, 0x34842ec8,
-0x24020020, 0xaf82011c, 0x2e31021, 0xaf800100,
-0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114,
-0xaf800118, 0xaf800120, 0xaf800124, 0xaf800128,
-0xaf800130, 0xaf800134, 0xaf800138, 0xaf4200ec,
-0x2e31021, 0xaf4200f0, 0x2e41021, 0xaf4200f4,
-0x2e41021, 0xaf4200f8, 0x3c020001, 0x571021,
-0x904240f4, 0x1440001c, 0x3c050001, 0x8f82011c,
-0x3c040001, 0x24846470, 0x3c050001, 0x34420001,
-0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c,
-0x34a50100, 0xc002b3b, 0x3821, 0x8c020218,
-0x30420040, 0x10400014, 0x0, 0x8f82011c,
-0x3c040001, 0x2484647c, 0x3c050001, 0x34420004,
-0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c,
-0x10000007, 0x34a50200, 0x3c040001, 0x24846484,
-0xafa00010, 0xafa00014, 0x8f86011c, 0x34a50300,
-0xc002b3b, 0x3821, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x8fa90010, 0x8f83012c, 0x8faa0014,
-0x8fab0018, 0x1060000a, 0x27624fe0, 0x14620002,
-0x24680020, 0x27684800, 0x8f820128, 0x11020004,
-0x0, 0x8f820124, 0x15020007, 0x0,
-0x8f430334, 0x1021, 0x24630001, 0xaf430334,
-0x10000039, 0x8f430334, 0xac640000, 0xac650004,
-0xac660008, 0xa467000e, 0xac690018, 0xac6a001c,
-0xac6b0010, 0xac620014, 0xaf880120, 0x8f4200fc,
-0x8f4400f4, 0x2442ffff, 0xaf4200fc, 0x8c820000,
-0x10490005, 0x3042ff8f, 0x10400019, 0x3122ff8f,
-0x10400018, 0x3c020001, 0x8c830004, 0x2c620010,
-0x10400013, 0x3c020001, 0x24630001, 0xac830004,
-0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004,
-0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021,
-0x14440015, 0x24020001, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x1000000f, 0x24020001,
-0x3c020001, 0x344230c8, 0x2e21021, 0x54820004,
-0x24820008, 0x3c020001, 0x34422ec8, 0x2e21021,
-0x402021, 0x24020001, 0xaf4400f4, 0xac890000,
-0xac820004, 0x24020001, 0x3e00008, 0x0,
-0x3e00008, 0x0, 0x8fa90010, 0x8f83010c,
-0x8faa0014, 0x8fab0018, 0x1060000a, 0x276247e0,
-0x14620002, 0x24680020, 0x27684000, 0x8f820108,
-0x11020004, 0x0, 0x8f820104, 0x15020007,
-0x0, 0x8f430338, 0x1021, 0x24630001,
-0xaf430338, 0x10000035, 0x8f430338, 0xac640000,
-0xac650004, 0xac660008, 0xa467000e, 0xac690018,
-0xac6a001c, 0xac6b0010, 0xac620014, 0xaf880100,
-0x8f4400ec, 0x8c820000, 0x30420006, 0x10400019,
-0x31220006, 0x10400018, 0x3c020001, 0x8c830004,
-0x2c620010, 0x10400013, 0x3c020001, 0x24630001,
-0xac830004, 0x8f4300f0, 0x34422ec0, 0x2e21021,
-0x54620004, 0x24620008, 0x3c020001, 0x34422cc0,
-0x2e21021, 0x14440015, 0x24020001, 0x8f820108,
-0x24420020, 0xaf820108, 0x8f820108, 0x1000000f,
-0x24020001, 0x3c020001, 0x34422ec0, 0x2e21021,
-0x54820004, 0x24820008, 0x3c020001, 0x34422cc0,
-0x2e21021, 0x402021, 0x24020001, 0xaf4400ec,
-0xac890000, 0xac820004, 0x24020001, 0x3e00008,
-0x0, 0x3e00008, 0x0, 0x27bdffd8,
-0x3c040001, 0x2484648c, 0x3c050001, 0xafbf0024,
-0xafb20020, 0xafb1001c, 0xafb00018, 0x8f900104,
-0x8f9100b0, 0x8f92011c, 0x34a52500, 0x8f820100,
-0x2403021, 0x2203821, 0xafa20010, 0xc002b3b,
-0xafb00014, 0x8e020008, 0xafa20010, 0x8e02000c,
-0x3c040001, 0x24846498, 0xafa20014, 0x8e060000,
-0x8e070004, 0x3c050001, 0xc002b3b, 0x34a52510,
-0x8e020018, 0xafa20010, 0x8e02001c, 0x3c040001,
-0x248464a4, 0xafa20014, 0x8e060010, 0x8e070014,
-0x3c050001, 0xc002b3b, 0x34a52520, 0x3c027f00,
-0x2221024, 0x3c030800, 0x54430016, 0x3c030200,
-0x8f82009c, 0x3042ffff, 0x14400012, 0x3c030200,
-0x3c040001, 0x248464b0, 0x3c050002, 0x34a5f030,
-0x3021, 0x3821, 0x36420002, 0xaf82011c,
-0x36220001, 0xaf8200b0, 0xaf900104, 0xaf92011c,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x10000024,
-0x0, 0x2c31024, 0x1040000d, 0x2231024,
-0x1040000b, 0x36420002, 0xaf82011c, 0x36220001,
-0xaf8200b0, 0xaf900104, 0xaf92011c, 0x8f420330,
-0x24420001, 0xaf420330, 0x10000015, 0x8f420330,
-0x3c040001, 0x248464b8, 0x240202a9, 0xafa20010,
-0xafa00014, 0x8f860144, 0x3c070001, 0x24e764c0,
-0xc002b3b, 0x3405dead, 0x8f82011c, 0x34420002,
-0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220,
-0x8f820140, 0x3c030001, 0x431025, 0xaf820140,
-0x8fbf0024, 0x8fb20020, 0x8fb1001c, 0x8fb00018,
-0x3e00008, 0x27bd0028, 0x27bdffd8, 0x3c040001,
-0x248464e8, 0x3c050001, 0xafbf0024, 0xafb20020,
-0xafb1001c, 0xafb00018, 0x8f900124, 0x8f9100a0,
-0x8f92011c, 0x34a52600, 0x8f820120, 0x2403021,
-0x2203821, 0xafa20010, 0xc002b3b, 0xafb00014,
-0x8e020008, 0xafa20010, 0x8e02000c, 0x3c040001,
-0x248464f4, 0xafa20014, 0x8e060000, 0x8e070004,
-0x3c050001, 0xc002b3b, 0x34a52610, 0x8e020018,
-0xafa20010, 0x8e02001c, 0x3c040001, 0x24846500,
-0xafa20014, 0x8e060010, 0x8e070014, 0x3c050001,
-0xc002b3b, 0x34a52620, 0x3c027f00, 0x2221024,
-0x3c030800, 0x54430016, 0x3c030200, 0x8f8200ac,
-0x3042ffff, 0x14400012, 0x3c030200, 0x3c040001,
-0x2484650c, 0x3c050001, 0x34a5f030, 0x3021,
-0x3821, 0x36420002, 0xaf82011c, 0x36220001,
-0xaf8200a0, 0xaf900124, 0xaf92011c, 0xafa00010,
-0xc002b3b, 0xafa00014, 0x10000024, 0x0,
-0x2c31024, 0x1040000d, 0x2231024, 0x1040000b,
-0x36420002, 0xaf82011c, 0x36220001, 0xaf8200a0,
-0xaf900124, 0xaf92011c, 0x8f42032c, 0x24420001,
-0xaf42032c, 0x10000015, 0x8f42032c, 0x3c040001,
-0x248464b8, 0x240202e2, 0xafa20010, 0xafa00014,
-0x8f860144, 0x3c070001, 0x24e764c0, 0xc002b3b,
-0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c,
-0x8f820220, 0x34420004, 0xaf820220, 0x8f820140,
-0x3c030001, 0x431025, 0xaf820140, 0x8fbf0024,
-0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
-0x27bd0028, 0x6021, 0x5021, 0x3021,
-0x2821, 0x6821, 0x4821, 0x7821,
-0x7021, 0x8f880124, 0x8f870104, 0x1580002e,
-0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120,
-0x10460029, 0x0, 0x3c040001, 0x8c846ee4,
-0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004,
-0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e,
-0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014,
-0x10000012, 0x24c60020, 0x10400017, 0x0,
-0x3c040001, 0x8c846ee4, 0x8d020000, 0x8d030004,
-0xac820000, 0xac830004, 0x8d020008, 0xac820008,
-0x9502000e, 0xa482000e, 0x8d020010, 0x25060020,
-0xac820010, 0x8d020014, 0x240c0001, 0xc01821,
-0xac820014, 0x27624fe0, 0x43102b, 0x54400001,
-0x27634800, 0x603021, 0x1540002f, 0x31620100,
-0x11200014, 0x31628000, 0x8f820100, 0x1045002a,
-0x31620100, 0x3c040001, 0x8c846ee0, 0x8ca20000,
-0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008,
-0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010,
-0x240a0001, 0xac820010, 0x8ca20014, 0x10000012,
-0x24a50020, 0x10400018, 0x31620100, 0x3c040001,
-0x8c846ee0, 0x8ce20000, 0x8ce30004, 0xac820000,
-0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e,
-0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010,
-0x8ce20014, 0x240a0001, 0xa01821, 0xac820014,
-0x276247e0, 0x43102b, 0x54400001, 0x27634000,
-0x602821, 0x31620100, 0x5440001d, 0x31621000,
-0x11a00009, 0x31a20800, 0x10400004, 0x25020020,
-0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124,
-0x8f880124, 0x6821, 0x11800011, 0x31621000,
-0x3c040001, 0x8c846ee4, 0x8c820000, 0x8c830004,
-0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4,
-0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021,
-0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000,
-0x1440ff82, 0x0, 0x1120000f, 0x31220800,
-0x10400004, 0x3c020002, 0x8f8200b8, 0xa5c20000,
-0x3c020002, 0x1221024, 0x10400004, 0x24e20020,
-0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104,
-0x8f870104, 0x4821, 0x1140ff70, 0x0,
-0x3c040001, 0x8c846ee0, 0x8c820000, 0x8c830004,
-0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4,
-0x9482000e, 0xaf82009c, 0x8c820010, 0x5021,
-0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014,
-0x3e00008, 0x0, 0x6021, 0x5821,
-0x3021, 0x2821, 0x6821, 0x5021,
-0x7821, 0x7021, 0x8f880124, 0x8f870104,
-0x3c180100, 0x1580002e, 0x8f89011c, 0x11a00014,
-0x31220800, 0x8f820120, 0x10460029, 0x0,
-0x3c040001, 0x8c846ee4, 0x8cc20000, 0x8cc30004,
-0xac820000, 0xac830004, 0x8cc20008, 0xac820008,
-0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001,
-0xac820010, 0x8cc20014, 0x10000012, 0x24c60020,
-0x10400017, 0x0, 0x3c040001, 0x8c846ee4,
-0x8d020000, 0x8d030004, 0xac820000, 0xac830004,
-0x8d020008, 0xac820008, 0x9502000e, 0xa482000e,
-0x8d020010, 0x25060020, 0xac820010, 0x8d020014,
-0x240c0001, 0xc01821, 0xac820014, 0x27624fe0,
-0x43102b, 0x54400001, 0x27634800, 0x603021,
-0x1560002f, 0x31220100, 0x11400014, 0x31228000,
-0x8f820100, 0x1045002a, 0x31220100, 0x3c040001,
-0x8c846ee0, 0x8ca20000, 0x8ca30004, 0xac820000,
-0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e,
-0xa482000e, 0x8ca20010, 0x240b0001, 0xac820010,
-0x8ca20014, 0x10000012, 0x24a50020, 0x10400018,
-0x31220100, 0x3c040001, 0x8c846ee0, 0x8ce20000,
-0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008,
-0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010,
-0x24e50020, 0xac820010, 0x8ce20014, 0x240b0001,
-0xa01821, 0xac820014, 0x276247e0, 0x43102b,
-0x54400001, 0x27634000, 0x602821, 0x31220100,
-0x5440001d, 0x31221000, 0x11a00009, 0x31a20800,
-0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000,
-0x25020020, 0xaf820124, 0x8f880124, 0x6821,
-0x11800011, 0x31221000, 0x3c040001, 0x8c846ee4,
-0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084,
-0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac,
-0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010,
-0x8c8f0014, 0x31221000, 0x14400022, 0x0,
-0x1140000f, 0x31420800, 0x10400004, 0x3c020002,
-0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1421024,
-0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4,
-0x24e20020, 0xaf820104, 0x8f870104, 0x5021,
-0x11600010, 0x0, 0x3c040001, 0x8c846ee0,
-0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094,
-0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c,
-0x8c820010, 0x5821, 0xaf8200b0, 0x8c8a0010,
-0x8c8e0014, 0x8f820070, 0x3c031000, 0x431024,
-0x1040ff5c, 0x0, 0x8f820054, 0x24420005,
-0xaf820078, 0x8c040234, 0x10800016, 0x1821,
-0x3c020001, 0x571021, 0x8c4240e8, 0x24420005,
-0x3c010001, 0x370821, 0xac2240e8, 0x3c020001,
-0x571021, 0x8c4240e8, 0x44102b, 0x14400009,
-0x24020001, 0x3c030080, 0x3c010001, 0x370821,
-0xac2040e8, 0x3c010001, 0x370821, 0x1000000c,
-0xa02240f0, 0x3c020001, 0x571021, 0x904240f0,
-0x14400006, 0x3c020080, 0x3c020001, 0x571021,
-0x904240f1, 0x10400002, 0x3c020080, 0x621825,
-0x8c040230, 0x10800013, 0x0, 0x3c020001,
-0x571021, 0x8c4240ec, 0x24420005, 0x3c010001,
-0x370821, 0xac2240ec, 0x3c020001, 0x571021,
-0x8c4240ec, 0x44102b, 0x14400006, 0x0,
-0x3c010001, 0x370821, 0xac2040ec, 0x10000006,
-0x781825, 0x3c020001, 0x571021, 0x904240f2,
-0x54400001, 0x781825, 0x1060ff1a, 0x0,
-0x8f420000, 0x10400007, 0x0, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x431025, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x1000ff05,
-0xaf80004c, 0x1000ff03, 0xaf800048, 0x3e00008,
-0x0, 0x0, 0x0, 0x3c020001,
-0x8c426d28, 0x27bdffe8, 0xafbf0014, 0x14400012,
-0xafb00010, 0x3c100001, 0x26106f90, 0x2002021,
-0xc002ba8, 0x24052000, 0x26021fe0, 0x3c010001,
-0xac226eec, 0x3c010001, 0xac226ee8, 0xac020250,
-0x24022000, 0xac100254, 0xac020258, 0x24020001,
-0x3c010001, 0xac226d28, 0x8fbf0014, 0x8fb00010,
-0x3e00008, 0x27bd0018, 0x3c090001, 0x8d296eec,
-0x8c820000, 0x8fa30010, 0x8fa80014, 0xad220000,
-0x8c820004, 0xad250008, 0xad220004, 0x8f820054,
-0xad260010, 0xad270014, 0xad230018, 0xad28001c,
-0xad22000c, 0x2529ffe0, 0x3c020001, 0x24426f90,
-0x122102b, 0x10400003, 0x0, 0x3c090001,
-0x8d296ee8, 0x3c020001, 0x8c426d10, 0xad220000,
-0x3c020001, 0x8c426d10, 0x3c010001, 0xac296eec,
-0xad220004, 0xac090250, 0x3e00008, 0x0,
-0x27bdffd0, 0xafb00010, 0x3c100001, 0x8e106eec,
-0x3c020001, 0x8c426d10, 0xafb10014, 0x808821,
-0xafbe0024, 0x8fbe0040, 0x8fa40048, 0xafb20018,
-0xa09021, 0xafbf0028, 0xafb50020, 0xafb3001c,
-0xae020000, 0x3c020001, 0x8c426d10, 0xc09821,
-0xe0a821, 0x10800006, 0xae020004, 0x26050008,
-0xc002bb3, 0x24060018, 0x10000005, 0x2610ffe0,
-0x26040008, 0xc002ba8, 0x24050018, 0x2610ffe0,
-0x3c030001, 0x24636f90, 0x203102b, 0x10400003,
-0x0, 0x3c100001, 0x8e106ee8, 0x8e220000,
-0xae020000, 0x8e220004, 0xae120008, 0xae020004,
-0x8f820054, 0xae130010, 0xae150014, 0xae1e0018,
-0x8fa80044, 0xae08001c, 0xae02000c, 0x2610ffe0,
-0x203102b, 0x10400003, 0x0, 0x3c100001,
-0x8e106ee8, 0x3c020001, 0x8c426d10, 0xae020000,
-0x3c020001, 0x8c426d10, 0x3c010001, 0xac306eec,
-0xae020004, 0xac100250, 0x8fbf0028, 0x8fbe0024,
-0x8fb50020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0030, 0x851821,
-0x83102b, 0x10400006, 0x0, 0xac800000,
-0x24840004, 0x83102b, 0x5440fffd, 0xac800000,
-0x3e00008, 0x0, 0xa61821, 0xa3102b,
-0x10400007, 0x0, 0x8c820000, 0xaca20000,
-0x24a50004, 0xa3102b, 0x1440fffb, 0x24840004,
-0x3e00008, 0x0, 0x861821, 0x83102b,
-0x10400007, 0x0, 0x8ca20000, 0xac820000,
-0x24840004, 0x83102b, 0x1440fffb, 0x24a50004,
-0x3e00008, 0x0, 0x63080, 0x861821,
-0x83102b, 0x10400006, 0x0, 0xac850000,
-0x24840004, 0x83102b, 0x5440fffd, 0xac850000,
-0x3e00008, 0x0, 0x0, 0x26e50028,
-0xa03021, 0x274301c0, 0x8f4d0358, 0x8f47035c,
-0x8f480360, 0x8f490364, 0x8f4a0368, 0x8f4b0204,
-0x8f4c0200, 0x24640400, 0x64102b, 0x10400008,
-0x3c0208ff, 0x8cc20000, 0xac620000, 0x24630004,
-0x64102b, 0x1440fffb, 0x24c60004, 0x3c0208ff,
-0x3442ffff, 0x3c03c0ff, 0xaf4d0358, 0xaf47035c,
-0xaf480360, 0xaf490364, 0xaf4a0368, 0xaf4b0204,
-0xaf4c0200, 0x8f840220, 0x3463ffff, 0x8f860200,
-0x821024, 0x34420004, 0xc31824, 0x34630004,
-0xaf820220, 0xaf830200, 0x8ca20214, 0xac020084,
-0x8ca20218, 0xac020088, 0x8ca2021c, 0xac02008c,
-0x8ca20220, 0xac020090, 0x8ca20224, 0xac020094,
-0x8ca20228, 0xac020098, 0x8ca2022c, 0xac02009c,
-0x8ca20230, 0xac0200a0, 0x8ca20234, 0xac0200a4,
-0x8ca20238, 0xac0200a8, 0x8ca2023c, 0xac0200ac,
-0x8ca20240, 0xac0200b0, 0x8ca20244, 0xac0200b4,
-0x8ca20248, 0xac0200b8, 0x8ca2024c, 0xac0200bc,
-0x8ca2001c, 0xac020080, 0x8ca20018, 0xac0200c0,
-0x8ca20020, 0xac0200cc, 0x8ca20024, 0xac0200d0,
-0x8ca201d0, 0xac0200e0, 0x8ca201d4, 0xac0200e4,
-0x8ca201d8, 0xac0200e8, 0x8ca201dc, 0xac0200ec,
-0x8ca201e0, 0xac0200f0, 0x8ca20098, 0x8ca3009c,
-0xac0300fc, 0x8ca200a8, 0x8ca300ac, 0xac0300f4,
-0x8ca200a0, 0x8ca300a4, 0x30840004, 0xac0300f8,
-0x14800007, 0x30c20004, 0x8f820220, 0x3c0308ff,
-0x3463fffb, 0x431024, 0xaf820220, 0x30c20004,
-0x14400006, 0x0, 0x8f820200, 0x3c03c0ff,
-0x3463fffb, 0x431024, 0xaf820200, 0x8f4202dc,
-0xa34005c5, 0x24420001, 0xaf4202dc, 0x8f4202dc,
-0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
-0xafb00020, 0x8f430024, 0x8f420020, 0x10620038,
-0x0, 0x8f430020, 0x8f420024, 0x622023,
-0x4810003, 0x0, 0x8f420040, 0x822021,
-0x8f430030, 0x8f420024, 0x43102b, 0x14400005,
-0x0, 0x8f430040, 0x8f420024, 0x10000005,
-0x621023, 0x8f420030, 0x8f430024, 0x431023,
-0x2442ffff, 0x406021, 0x8c102a, 0x54400001,
-0x806021, 0x8f4a0024, 0x8f490040, 0x8f480024,
-0x8f440180, 0x8f450184, 0x8f460024, 0x8f4b001c,
-0x24070001, 0xafa70010, 0x84100, 0x1001821,
-0x14c5021, 0x2529ffff, 0x1498024, 0xafb00014,
-0x8f470014, 0x1021, 0x63100, 0xafa70018,
-0xa32821, 0xa3382b, 0x822021, 0x872021,
-0x8f420108, 0x1663021, 0x40f809, 0xc3900,
-0x54400001, 0xaf500024, 0x8f430024, 0x8f420020,
-0x14620018, 0x0, 0x8f420000, 0x10400007,
-0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
-0x0, 0x10000005, 0x0, 0xaf800048,
-0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
-0x2403ffef, 0x431024, 0xaf820060, 0x8f420000,
-0x10400003, 0x0, 0x10000002, 0xaf80004c,
-0xaf800048, 0x8fbf0024, 0x8fb00020, 0x3e00008,
-0x27bd0028, 0x3e00008, 0x0, 0x27bdffc0,
-0x32c20020, 0xafbf0038, 0xafb30034, 0xafb20030,
-0xafb1002c, 0x10400004, 0xafb00028, 0x8f530028,
-0x10000002, 0x0, 0x8f530020, 0x8f420030,
-0x105300eb, 0x21100, 0x8f43001c, 0x628021,
-0x8e040000, 0x8e050004, 0x96120008, 0x8f420090,
-0x9611000a, 0x3246ffff, 0x46102a, 0x10400017,
-0x0, 0x8f8200d8, 0x8f430098, 0x431023,
-0x2442dcbe, 0xaf420090, 0x8f420090, 0x2842dcbf,
-0x10400005, 0x0, 0x8f420090, 0x8f430144,
-0x431021, 0xaf420090, 0x8f420090, 0x46102a,
-0x10400006, 0x0, 0x8f420348, 0x24420001,
-0xaf420348, 0x100000e1, 0x8f420348, 0x8f8200fc,
-0x14400006, 0x0, 0x8f420344, 0x24420001,
-0xaf420344, 0x100000d9, 0x8f420344, 0x934205c2,
-0x1040000b, 0x32c20008, 0x10400008, 0x32220200,
-0x10400006, 0x3c034000, 0x9602000e, 0xaf4300ac,
-0x21400, 0x10000002, 0xaf4200b0, 0xaf4000ac,
-0x32220004, 0x1040007f, 0x32220800, 0x10400003,
-0x3247ffff, 0x10000002, 0x24020020, 0x24020004,
-0xafa20010, 0x8f420030, 0xafa20014, 0x8f420010,
-0x3c030002, 0x431025, 0xafa20018, 0x8f460098,
-0x8f420108, 0x40f809, 0x0, 0x104000b7,
-0x0, 0x8f42009c, 0x8f430094, 0x2421021,
-0xaf42009c, 0xae03000c, 0x8f4200ac, 0x10400008,
-0x3c034000, 0x8f420094, 0x431025, 0xafa20020,
-0x8f42009c, 0x8f4300b0, 0x10000004, 0x431025,
-0x8f420094, 0xafa20020, 0x8f42009c, 0xafa20024,
-0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000,
-0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c,
-0x8f440270, 0x8f450274, 0x401821, 0x1021,
-0xa32821, 0xa3302b, 0x822021, 0x862021,
-0x32230060, 0x24020040, 0xaf440270, 0xaf450274,
-0x10620017, 0x2c620041, 0x10400005, 0x24020020,
-0x10620008, 0x24020001, 0x10000026, 0x0,
-0x24020060, 0x10620019, 0x24020001, 0x10000021,
-0x0, 0x8f420278, 0x8f43027c, 0x24630001,
-0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
-0x8f420278, 0x8f43027c, 0x10000016, 0x24020001,
-0x8f420280, 0x8f430284, 0x24630001, 0x2c640001,
-0x441021, 0xaf420280, 0xaf430284, 0x8f420280,
-0x8f430284, 0x1000000b, 0x24020001, 0x8f420288,
-0x8f43028c, 0x24630001, 0x2c640001, 0x441021,
-0xaf420288, 0xaf43028c, 0x8f420288, 0x8f43028c,
-0x24020001, 0xa34205c2, 0x8f420098, 0x3244ffff,
-0x2406fff8, 0x8f45013c, 0x441021, 0x24420007,
-0x461024, 0x24840007, 0xaf420094, 0x8f420090,
-0x8f430094, 0x862024, 0x441023, 0x65182b,
-0x14600005, 0xaf420090, 0x8f420094, 0x8f430144,
-0x431023, 0xaf420094, 0x8f420094, 0x10000023,
-0xaf40009c, 0x3247ffff, 0x50e00022, 0x32c20020,
-0x14400002, 0x24020010, 0x24020002, 0xafa20010,
-0x8f420030, 0xafa20014, 0x8f420010, 0xafa20018,
-0x8f460098, 0x8f420108, 0x40f809, 0x0,
-0x1040003a, 0x3245ffff, 0x8f420098, 0x8f430090,
-0x8f46013c, 0x451021, 0xaf420098, 0x8f42009c,
-0x8f440098, 0xa34005c2, 0x651823, 0xaf430090,
-0x451021, 0x86202b, 0x14800005, 0xaf42009c,
-0x8f420098, 0x8f430144, 0x431023, 0xaf420098,
-0x32c20020, 0x10400005, 0x0, 0x8f420358,
-0x2442ffff, 0xaf420358, 0x8f420358, 0x8f420030,
-0x8f430040, 0x24420001, 0x2463ffff, 0x431024,
-0xaf420030, 0x8f420030, 0x14530018, 0x0,
-0x8f420000, 0x10400007, 0x0, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x2403fff7, 0x431024,
-0xaf820060, 0x8f420000, 0x10400003, 0x0,
-0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0038,
-0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028,
-0x3e00008, 0x27bd0040, 0x3e00008, 0x0,
-0x27bdffd0, 0x32c20020, 0xafbf002c, 0xafb20028,
-0xafb10024, 0x10400004, 0xafb00020, 0x8f520028,
-0x10000002, 0x0, 0x8f520020, 0x8f420030,
-0x105200b5, 0x21100, 0x8f43001c, 0x628021,
-0x8e040000, 0x8e050004, 0x96110008, 0x8f420090,
-0x9607000a, 0x3226ffff, 0x46102a, 0x10400017,
-0x0, 0x8f8200d8, 0x8f430098, 0x431023,
-0x2442dc46, 0xaf420090, 0x8f420090, 0x2842dc47,
-0x10400005, 0x0, 0x8f420090, 0x8f430144,
-0x431021, 0xaf420090, 0x8f420090, 0x46102a,
-0x10400006, 0x0, 0x8f420348, 0x24420001,
-0xaf420348, 0x100000ab, 0x8f420348, 0x8f8600fc,
-0x10c0000c, 0x0, 0x8f8200f4, 0x2403fff8,
-0x431024, 0x461023, 0x218c3, 0x58600001,
-0x24630100, 0x8f42008c, 0x43102b, 0x14400006,
-0x712c2, 0x8f420344, 0x24420001, 0xaf420344,
-0x10000098, 0x8f420344, 0x934305c2, 0x1060000f,
-0x30460001, 0x8f420010, 0x34480400, 0x32c20008,
-0x10400008, 0x30e20200, 0x10400006, 0x3c034000,
-0x9602000e, 0xaf4300ac, 0x21400, 0x10000004,
-0xaf4200b0, 0x10000002, 0xaf4000ac, 0x8f480010,
-0x30e20004, 0x10400045, 0x3227ffff, 0x8f4900ac,
-0x11200005, 0x30c200ff, 0x14400006, 0x24020040,
-0x10000004, 0x24020008, 0x14400002, 0x24020020,
-0x24020004, 0xafa20010, 0x8f430030, 0x11200004,
-0xafa30014, 0x8f4200b0, 0x621025, 0xafa20014,
-0x3c020002, 0x1021025, 0xafa20018, 0x8f460098,
-0x8f420108, 0x40f809, 0x0, 0x10400069,
-0x3224ffff, 0x8f42008c, 0x8f430094, 0x24420001,
-0xaf42008c, 0x24020001, 0xae03000c, 0xa34205c2,
-0x8f420098, 0x2406fff8, 0x8f45013c, 0x441021,
-0x24420007, 0x461024, 0x24840007, 0xaf420094,
-0x8f420090, 0x8f430094, 0x862024, 0x441023,
-0x65182b, 0x14600005, 0xaf420090, 0x8f420094,
-0x8f430144, 0x431023, 0xaf420094, 0x8f430094,
-0x8f420140, 0x43102b, 0x10400009, 0x0,
-0x8f43013c, 0x8f440094, 0x8f420090, 0x8f450138,
-0x641823, 0x431023, 0xaf420090, 0xaf450094,
-0x8f420094, 0x1000001f, 0xaf420098, 0x10e0001d,
-0x30c200ff, 0x14400002, 0x24020010, 0x24020002,
-0xafa20010, 0x8f420030, 0xafa80018, 0xafa20014,
-0x8f460098, 0x8f420108, 0x40f809, 0x0,
-0x10400030, 0x3225ffff, 0x8f420098, 0x8f44013c,
-0x451021, 0xaf420098, 0x8f420090, 0x8f430098,
-0xa34005c2, 0x451023, 0x64182b, 0x14600005,
-0xaf420090, 0x8f420098, 0x8f430144, 0x431023,
-0xaf420098, 0x8f420030, 0x8f430040, 0x24420001,
-0x2463ffff, 0x431024, 0xaf420030, 0x8f420030,
-0x14520018, 0x0, 0x8f420000, 0x10400007,
-0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
-0x0, 0x10000005, 0x0, 0xaf800048,
-0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
-0x2403fff7, 0x431024, 0xaf820060, 0x8f420000,
-0x10400003, 0x0, 0x10000002, 0xaf80004c,
-0xaf800048, 0x8fbf002c, 0x8fb20028, 0x8fb10024,
-0x8fb00020, 0x3e00008, 0x27bd0030, 0x3e00008,
-0x0, 0x27bdffd8, 0x3c020001, 0x34422ec0,
-0xafbf0020, 0x8f4300f0, 0x8f840108, 0x2e21021,
-0x54620004, 0x24620008, 0x3c020001, 0x34422cc0,
-0x2e21021, 0x401821, 0xaf4300f0, 0xac600000,
-0x8f4200ec, 0x8c660004, 0x14620004, 0x3c020001,
-0x24820020, 0x1000000f, 0xaf820108, 0x8f4300f0,
-0x34422ec0, 0x2e21021, 0x54620004, 0x24620008,
-0x3c020001, 0x34422cc0, 0x2e21021, 0x401821,
-0x8c620004, 0x21140, 0x821021, 0xaf820108,
-0xac600000, 0x8c850018, 0x30a20036, 0x1040006c,
-0x30a20001, 0x8c82001c, 0x8f430040, 0x8f440034,
-0x24420001, 0x2463ffff, 0x431024, 0x862021,
-0xaf42002c, 0x30a20030, 0x14400006, 0xaf440034,
-0x8f420034, 0x8c03023c, 0x43102b, 0x144000b4,
-0x0, 0x32c20010, 0x10400028, 0x24070008,
-0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c,
-0x8f860120, 0x24020080, 0xafa20010, 0xafa30014,
-0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400011, 0x24020001, 0x3c010001, 0x370821,
-0xa02240f1, 0x8f820124, 0xafa20010, 0x8f820128,
-0x3c040001, 0x248467c4, 0xafa20014, 0x8f46002c,
-0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51100,
-0x10000036, 0x0, 0x8f420300, 0x8f43002c,
-0x24420001, 0xaf420300, 0x8f420300, 0x24020001,
-0xa34205c1, 0x10000026, 0xaf430038, 0x8f440170,
-0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
-0x24020020, 0xafa20010, 0xafa30014, 0xafa80018,
-0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
-0x24020001, 0x3c010001, 0x370821, 0xa02240f0,
-0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
-0x248467b8, 0xafa20014, 0x8f46002c, 0x8f870120,
-0x3c050009, 0xc002b3b, 0x34a50900, 0x1000000f,
-0x0, 0x8f420300, 0x24420001, 0xaf420300,
-0x8f420300, 0x8f42002c, 0xa34005c1, 0xaf420038,
-0x3c010001, 0x370821, 0xa02040f1, 0x3c010001,
-0x370821, 0xa02040f0, 0xaf400034, 0x8f420314,
-0x24420001, 0xaf420314, 0x10000059, 0x8f420314,
-0x10400022, 0x30a27000, 0x8c85001c, 0x8f420028,
-0xa22023, 0x4810003, 0x0, 0x8f420040,
-0x822021, 0x8f420358, 0x8f430000, 0xaf450028,
-0x441021, 0x10600007, 0xaf420358, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x34420008, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x10000038,
-0xaf80004c, 0x10000036, 0xaf800048, 0x1040002f,
-0x30a21000, 0x1040000c, 0x30a24000, 0x8c83001c,
-0x8f420050, 0x622023, 0x4820001, 0x24840200,
-0x8f42035c, 0x441021, 0xaf42035c, 0x8f420368,
-0x1000001a, 0xaf430050, 0x1040000c, 0x32c28000,
-0x8c83001c, 0x8f420070, 0x622023, 0x4820001,
-0x24840400, 0x8f420364, 0x441021, 0xaf420364,
-0x8f420368, 0x1000000d, 0xaf430070, 0x1040000e,
-0x3c020800, 0x8c83001c, 0x8f420060, 0x622023,
-0x4820001, 0x24840100, 0x8f420360, 0x441021,
-0xaf420360, 0x8f420368, 0xaf430060, 0x441021,
-0xaf420368, 0x3c020800, 0x2c21024, 0x50400008,
-0x36940040, 0x10000006, 0x0, 0x30a20100,
-0x10400003, 0x0, 0xc002bd8, 0x0,
-0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008,
-0x0, 0x27bdffa8, 0xafbf0050, 0xafbe004c,
-0xafb50048, 0xafb30044, 0xafb20040, 0xafb1003c,
-0xafb00038, 0x8f910108, 0x26220020, 0xaf820108,
-0x8e320018, 0xa821, 0x32420024, 0x104001ba,
-0xf021, 0x8e26001c, 0x8f43001c, 0x61100,
-0x621821, 0x8c70000c, 0x9604000c, 0x962d0016,
-0x9473000a, 0x2c8305dd, 0x38828870, 0x2c420001,
-0x621825, 0x10600015, 0x2821, 0x32c20040,
-0x10400015, 0x24020800, 0x96030014, 0x14620012,
-0x3402aaaa, 0x9603000e, 0x14620007, 0x2021,
-0x96030010, 0x24020300, 0x14620004, 0x801021,
-0x96020012, 0x2c440001, 0x801021, 0x54400006,
-0x24050016, 0x10000004, 0x0, 0x24020800,
-0x50820001, 0x2405000e, 0x934205c3, 0x14400008,
-0x5821, 0x240b0001, 0x32620180, 0xaf4500a8,
-0xaf5000a0, 0x10400002, 0xaf4600a4, 0xa34b05c3,
-0x10a00085, 0x2054021, 0x91020000, 0x3821,
-0x3042000f, 0x25080, 0x32c20002, 0x10400012,
-0x10a1821, 0x32620002, 0x10400010, 0x32c20001,
-0x1002021, 0x94820000, 0x24840002, 0xe23821,
-0x83102b, 0x1440fffb, 0x30e2ffff, 0x71c02,
-0x623821, 0x71c02, 0x30e2ffff, 0x623821,
-0x71027, 0xa502000a, 0x32c20001, 0x1040006a,
-0x32620001, 0x10400068, 0x0, 0x8f4200a8,
-0x10400065, 0x0, 0x8f4200a0, 0x8f4300a8,
-0x431021, 0x904c0009, 0x318900ff, 0x39230006,
-0x3182b, 0x39220011, 0x2102b, 0x621824,
-0x1060000c, 0x3c050006, 0x8f4200a4, 0x3c040001,
-0x248467d4, 0xafa20010, 0x8f4200a0, 0x34a54600,
-0x1203821, 0xc002b3b, 0xafa20014, 0x1000004e,
-0x0, 0x32c20004, 0x14400013, 0x2821,
-0x316200ff, 0x14400004, 0x0, 0x95020002,
-0x1000000d, 0x4a2823, 0x9505000c, 0x9502000e,
-0x95030010, 0xa22821, 0xa32821, 0x95030012,
-0x91040009, 0x95020002, 0xa32821, 0xa42821,
-0x4a1023, 0xa22821, 0x2002021, 0x94820000,
-0x24840002, 0xe23821, 0x88102b, 0x1440fffb,
-0x71c02, 0x30e2ffff, 0x623821, 0x71c02,
-0x30e2ffff, 0x623821, 0x1a52821, 0x51c02,
-0x30a2ffff, 0x622821, 0x51c02, 0x30a2ffff,
-0x622821, 0xa72823, 0x51402, 0xa22821,
-0x30a5ffff, 0x50a00001, 0x3405ffff, 0x316200ff,
-0x14400008, 0x318300ff, 0x8f4300a0, 0x8f4200a8,
-0x624021, 0x91020000, 0x3042000f, 0x25080,
-0x318300ff, 0x24020006, 0x14620003, 0x10a1021,
-0x10000002, 0x24440010, 0x24440006, 0x316200ff,
-0x14400006, 0x0, 0x94820000, 0xa22821,
-0x51c02, 0x30a2ffff, 0x622821, 0x934205c3,
-0x10400003, 0x32620100, 0x50400003, 0xa4850000,
-0x52827, 0xa4850000, 0x9622000e, 0x8f43009c,
-0x621821, 0x32a200ff, 0x10400007, 0xaf43009c,
-0x3c024000, 0x2021025, 0xafa20020, 0x8f42009c,
-0x10000003, 0x5e1025, 0xafb00020, 0x8f42009c,
-0xafa20024, 0x32620080, 0x10400010, 0x32620100,
-0x8f4200b4, 0x24430001, 0x210c0, 0x571021,
-0xaf4300b4, 0x8fa30020, 0x8fa40024, 0x3c010001,
-0x220821, 0xac2338e8, 0x3c010001, 0x220821,
-0xac2438ec, 0x100000a5, 0x32c20020, 0x10400064,
-0x0, 0x8f4200b4, 0x24430001, 0x210c0,
-0x571021, 0xaf4300b4, 0x8fa30020, 0x8fa40024,
-0x3c010001, 0x220821, 0xac2338e8, 0x3c010001,
-0x220821, 0xac2438ec, 0x8f4200b4, 0x10400051,
-0x3821, 0x3c090001, 0x352938e8, 0x3c08001f,
-0x3508ffff, 0x240bffff, 0x340affff, 0x710c0,
-0x571021, 0x491021, 0x8c430000, 0x8c440004,
-0xafa30028, 0xafa4002c, 0x8f8200fc, 0x8fa30028,
-0x8fa4002c, 0xac430000, 0xac440004, 0x24420008,
-0xaf8200f0, 0x8f42008c, 0x2442ffff, 0xaf42008c,
-0x97a2002e, 0x8f440270, 0x8f450274, 0x401821,
-0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaf440270, 0xaf450274, 0x8fa20028,
-0x481024, 0x90430000, 0x30630001, 0x1460000b,
-0x402021, 0x8f420278, 0x8f43027c, 0x24630001,
-0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
-0x8f420278, 0x1000001a, 0x8f43027c, 0x8c820000,
-0x144b000e, 0x0, 0x94820004, 0x144a000b,
-0x0, 0x8f420288, 0x8f43028c, 0x24630001,
-0x2c640001, 0x441021, 0xaf420288, 0xaf43028c,
-0x8f420288, 0x1000000a, 0x8f43028c, 0x8f420280,
-0x8f430284, 0x24630001, 0x2c640001, 0x441021,
-0xaf420280, 0xaf430284, 0x8f420280, 0x8f430284,
-0x8f4200b4, 0x24e70001, 0xe2102b, 0x1440ffb8,
-0x710c0, 0xa34005c3, 0x1000003f, 0xaf4000b4,
-0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000,
-0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c,
-0x8f46008c, 0x8f440270, 0x8f450274, 0x401821,
-0x1021, 0x24c6ffff, 0xaf46008c, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0xaf440270,
-0xaf450274, 0x92020000, 0x30420001, 0x1440000c,
-0x2402ffff, 0x8f420278, 0x8f43027c, 0x24630001,
-0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
-0x8f420278, 0x8f43027c, 0x1000001c, 0x32c20020,
-0x8e030000, 0x1462000f, 0x3402ffff, 0x96030004,
-0x1462000c, 0x0, 0x8f420288, 0x8f43028c,
-0x24630001, 0x2c640001, 0x441021, 0xaf420288,
-0xaf43028c, 0x8f420288, 0x8f43028c, 0x1000000b,
-0x32c20020, 0x8f420280, 0x8f430284, 0x24630001,
-0x2c640001, 0x441021, 0xaf420280, 0xaf430284,
-0x8f420280, 0x8f430284, 0x32c20020, 0x10400005,
-0xaf40009c, 0x8f420358, 0x2442ffff, 0xaf420358,
-0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001,
-0x2463ffff, 0x431024, 0xaf42002c, 0x32420060,
-0x14400008, 0x32c20010, 0x8f420034, 0x24420001,
-0xaf420034, 0x8c03023c, 0x43102b, 0x14400102,
-0x32c20010, 0x10400018, 0x24070008, 0x8f440170,
-0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
-0x24020080, 0xafa20010, 0xafa30014, 0xafa80018,
-0x8f42010c, 0x40f809, 0x24c6001c, 0x10400047,
-0x24020001, 0x8f420300, 0x8f43002c, 0x24420001,
-0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1,
-0x1000007c, 0xaf430038, 0x8f440170, 0x8f450174,
-0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020,
-0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c,
-0x40f809, 0x24c6001c, 0x10400057, 0x24020001,
-0x10000065, 0x0, 0x32420012, 0x10400075,
-0x32420001, 0x9622000e, 0x8f43009c, 0x621821,
-0x32c20020, 0x10400005, 0xaf43009c, 0x8f420358,
-0x2442ffff, 0xaf420358, 0x8f420358, 0x8e22001c,
-0x8f430040, 0x24420001, 0x2463ffff, 0x431024,
-0xaf42002c, 0x32420010, 0x14400008, 0x32c20010,
-0x8f420034, 0x24420001, 0xaf420034, 0x8c03023c,
-0x43102b, 0x144000bc, 0x32c20010, 0x10400028,
-0x24070008, 0x8f440170, 0x8f450174, 0x8f43002c,
-0x8f48000c, 0x8f860120, 0x24020080, 0xafa20010,
-0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
-0x24c6001c, 0x14400011, 0x24020001, 0x3c010001,
-0x370821, 0xa02240f1, 0x8f820124, 0xafa20010,
-0x8f820128, 0x3c040001, 0x248467c4, 0xafa20014,
-0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b,
-0x34a51100, 0x10000036, 0x0, 0x8f420300,
-0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300,
-0x24020001, 0xa34205c1, 0x10000026, 0xaf430038,
-0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c,
-0x8f860120, 0x24020020, 0xafa20010, 0xafa30014,
-0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400011, 0x24020001, 0x3c010001, 0x370821,
-0xa02240f0, 0x8f820124, 0xafa20010, 0x8f820128,
-0x3c040001, 0x248467b8, 0xafa20014, 0x8f46002c,
-0x8f870120, 0x3c050009, 0xc002b3b, 0x34a50900,
-0x1000000f, 0x0, 0x8f420300, 0x24420001,
-0xaf420300, 0x8f420300, 0x8f42002c, 0xa34005c1,
-0xaf420038, 0x3c010001, 0x370821, 0xa02040f1,
-0x3c010001, 0x370821, 0xa02040f0, 0xaf400034,
-0x8f420314, 0x24420001, 0xaf420314, 0x10000062,
-0x8f420314, 0x10400022, 0x32427000, 0x8e25001c,
-0x8f420028, 0xa22023, 0x4810003, 0x0,
-0x8f420040, 0x822021, 0x8f420358, 0x8f430000,
-0xaf450028, 0x441021, 0x10600007, 0xaf420358,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x34420008,
-0xaf820060, 0x8f420000, 0x10400003, 0x0,
-0x10000041, 0xaf80004c, 0x1000003f, 0xaf800048,
-0x1040002f, 0x32421000, 0x1040000c, 0x32424000,
-0x8e23001c, 0x8f420050, 0x622023, 0x4820001,
-0x24840200, 0x8f42035c, 0x441021, 0xaf42035c,
-0x8f420368, 0x1000001a, 0xaf430050, 0x1040000c,
-0x32c28000, 0x8e23001c, 0x8f420070, 0x622023,
-0x4820001, 0x24840400, 0x8f420364, 0x441021,
-0xaf420364, 0x8f420368, 0x1000000d, 0xaf430070,
-0x1040000e, 0x3c020800, 0x8e23001c, 0x8f420060,
-0x622023, 0x4820001, 0x24840100, 0x8f420360,
-0x441021, 0xaf420360, 0x8f420368, 0xaf430060,
-0x441021, 0xaf420368, 0x3c020800, 0x2c21024,
-0x50400011, 0x36940040, 0x1000000f, 0x0,
-0x32420048, 0x10400007, 0x24150001, 0x8e22001c,
-0x3c03ffff, 0x43f024, 0x3042ffff, 0x1000fd75,
-0xae22001c, 0x32420100, 0x10400003, 0x0,
-0xc002bd8, 0x0, 0x8fbf0050, 0x8fbe004c,
-0x8fb50048, 0x8fb30044, 0x8fb20040, 0x8fb1003c,
-0x8fb00038, 0x3e00008, 0x27bd0058, 0x3e00008,
-0x0, 0x0, 0x0, 0x8f8300e4,
-0x8f8200e0, 0x2404fff8, 0x441024, 0x621026,
-0x2102b, 0x21023, 0x3e00008, 0x621024,
-0x3e00008, 0x0, 0x27bdffe0, 0xafbf001c,
-0xafb00018, 0x8f8600c4, 0x8f8400e0, 0x8f8500e4,
-0x2402fff8, 0x821824, 0x10a30009, 0x27623ff8,
-0x14a20002, 0x24a20008, 0x27623000, 0x408021,
-0x16030005, 0x30820004, 0x10400004, 0xc02021,
-0x10000022, 0x1021, 0x8e040000, 0x8f42011c,
-0x14a20003, 0x0, 0x8f420120, 0xaf420114,
-0x8ca30000, 0x8f420148, 0x831823, 0x43102b,
-0x10400003, 0x0, 0x8f420148, 0x621821,
-0x94a20006, 0x24420050, 0x62102b, 0x1440000f,
-0xa01021, 0xafa40010, 0xafa30014, 0x8ca60000,
-0x8ca70004, 0x3c040001, 0xc002b3b, 0x24846894,
-0x8f42020c, 0x24420001, 0xaf42020c, 0x8f42020c,
-0x1021, 0xaf9000e8, 0xaf9000e4, 0x8fbf001c,
-0x8fb00018, 0x3e00008, 0x27bd0020, 0x3e00008,
-0x0, 0x8f8400e0, 0x8f8800c4, 0x8f8300e8,
-0x2402fff8, 0x823824, 0xe32023, 0x2c821000,
-0x50400001, 0x24841000, 0x420c2, 0x801821,
-0x8f440258, 0x8f45025c, 0x1021, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0xaf440258,
-0xaf45025c, 0x8f8300c8, 0x8f420148, 0x1032023,
-0x82102b, 0x14400004, 0x801821, 0x8f420148,
-0x822021, 0x801821, 0x8f440250, 0x8f450254,
-0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaf440250, 0xaf450254, 0xaf8800c8,
-0xaf8700e4, 0xaf8700e8, 0x3e00008, 0x0,
-0x27bdff30, 0x240a0001, 0xafbf00c8, 0xafbe00c4,
-0xafb500c0, 0xafb300bc, 0xafb200b8, 0xafb100b4,
-0xafb000b0, 0xa3a00097, 0xafa00044, 0xafaa005c,
-0x934205c4, 0xa7a0008e, 0x1040000a, 0xa7a00086,
-0x8f4b00c4, 0xafab0064, 0x8f4a00c0, 0xafaa006c,
-0x8f4b00cc, 0xafab0074, 0x8f4a00c8, 0x10000129,
-0xafaa007c, 0x8f420114, 0x40f809, 0x0,
-0x403021, 0x10c0034f, 0x0, 0x8cc20000,
-0x8cc30004, 0xafa20020, 0xafa30024, 0x8fab0024,
-0x8faa0020, 0x3162ffff, 0x2442fffc, 0xafa2006c,
-0x3c020006, 0x2c21024, 0xafab007c, 0x14400015,
-0xafaa0064, 0x91420000, 0x30420001, 0x10400011,
-0x2402ffff, 0x8d430000, 0x14620004, 0x3402ffff,
-0x95430004, 0x1062000b, 0x0, 0xc0024bb,
-0x8fa40064, 0x304200ff, 0x14400006, 0x0,
-0x8f420118, 0x40f809, 0x0, 0x1000032d,
-0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
-0x431024, 0x3c03ffff, 0x431824, 0x14600003,
-0xafa20024, 0x10000040, 0x1821, 0x3c020080,
-0x621024, 0x10400007, 0x0, 0x8f42038c,
-0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036,
-0x24030001, 0x8f420210, 0x24420001, 0xaf420210,
-0x8f420210, 0x3c020001, 0x621024, 0x10400006,
-0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4,
-0x8f4201c4, 0x3c020002, 0x621024, 0x10400006,
-0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c,
-0x8f42037c, 0x3c020004, 0x621024, 0x10400006,
-0x3c020008, 0x8f420380, 0x24420001, 0xaf420380,
-0x8f420380, 0x3c020008, 0x621024, 0x10400006,
-0x3c020010, 0x8f420384, 0x24420001, 0xaf420384,
-0x8f420384, 0x3c020010, 0x621024, 0x10400006,
-0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0,
-0x8f4201c0, 0x3c020020, 0x621024, 0x10400006,
-0x24030001, 0x8f420388, 0x24420001, 0xaf420388,
-0x8f420388, 0x24030001, 0x8c020260, 0x8fab006c,
-0x4b102b, 0x10400014, 0x307000ff, 0x8f4201e8,
-0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8faa007c,
-0x8f8200e0, 0x354a0100, 0xafaa007c, 0xafa20010,
-0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0,
-0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007,
-0xc002b3b, 0x34a50800, 0x12000010, 0x3c020080,
-0x2c21024, 0x1440000e, 0x32c20400, 0x8fab007c,
-0x3c020080, 0x34420100, 0x1621024, 0x10400005,
-0x0, 0x8f42020c, 0x24420001, 0xaf42020c,
-0x8f42020c, 0x100002b0, 0x8fa3006c, 0x32c20400,
-0x10400015, 0x34028100, 0x8faa0064, 0x9543000c,
-0x14620012, 0x3c020100, 0x240b0200, 0xa7ab008e,
-0x9542000e, 0x8d430008, 0x8d440004, 0x8d450000,
-0x8faa006c, 0x8fab0064, 0x254afffc, 0xafaa006c,
-0xa7a20086, 0xad63000c, 0xad640008, 0xad650004,
-0x256b0004, 0xafab0064, 0x3c020100, 0x2c21024,
-0x10400004, 0x0, 0x8faa006c, 0x254a0004,
-0xafaa006c, 0x8f4200bc, 0x5040000a, 0xafa00074,
-0x8fab006c, 0x4b102b, 0x50400006, 0xafa00074,
-0x8f4200bc, 0x1621023, 0xafa20074, 0x8f4a00bc,
-0xafaa006c, 0x8f420080, 0x8fab006c, 0x4b102b,
-0x10400056, 0x32c28000, 0x1040005e, 0x240a0003,
-0x32c21000, 0x1040005b, 0xafaa005c, 0x10000058,
-0x240b0004, 0x8f420350, 0x2403ffbf, 0x283a024,
-0x24420001, 0xaf420350, 0x1000024f, 0x8f420350,
-0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128,
-0x3c040001, 0x248468d0, 0x26620001, 0xafa20014,
-0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007,
-0xc002b3b, 0x34a52250, 0x1000023f, 0x0,
-0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128,
-0x3c040001, 0x248468d0, 0x24020002, 0xafa20014,
-0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007,
-0xc002b3b, 0x34a52450, 0x1000022f, 0x0,
-0x8ea20000, 0x8ea30004, 0x3c040001, 0x248468e8,
-0xafb00010, 0xafbe0014, 0x8ea70018, 0x34a52800,
-0xc002b3b, 0x603021, 0x10000223, 0x0,
-0xa6b1000a, 0x8f820124, 0x3c040001, 0x248468f0,
-0xafbe0014, 0xafa20010, 0x8f460044, 0x8f870120,
-0x3c050007, 0xc002b3b, 0x34a53000, 0x10000216,
-0x0, 0xa6b1000a, 0xa6b2000e, 0x8f820124,
-0x3c040001, 0x248468fc, 0xafbe0014, 0xafa20010,
-0x8f460044, 0x8f870120, 0x3c050007, 0xc002b3b,
-0x34a53200, 0x10000208, 0x0, 0x8f420084,
-0x8faa006c, 0x4a102b, 0x14400007, 0x3c020001,
-0x2c21024, 0x10400004, 0x0, 0x240b0002,
-0xafab005c, 0x8faa006c, 0x1140021b, 0x27ab0020,
-0xafab00a4, 0x3c0a001f, 0x354affff, 0xafaa009c,
-0x8fab005c, 0x240a0001, 0x556a0021, 0x240a0002,
-0x8f430054, 0x8f420050, 0x1062000b, 0x274b0054,
-0x8f5e0054, 0x3403ecc0, 0xafab004c, 0x27c20001,
-0x304201ff, 0xafa20054, 0x1e1140, 0x431021,
-0x1000006b, 0x2e2a821, 0x8f420044, 0x8faa006c,
-0x3c040001, 0x248468ac, 0xafaa0014, 0xafa20010,
-0x8f460054, 0x8f470050, 0x3c050007, 0xc002b3b,
-0x34a51300, 0x8f430350, 0x2402ffbf, 0x282a024,
-0x24630001, 0xaf430350, 0x100001d3, 0x8f420350,
-0x156a001d, 0x0, 0x8f430074, 0x8f420070,
-0x1062000a, 0x274b0074, 0x8f5e0074, 0xafab004c,
-0x27c20001, 0x304203ff, 0xafa20054, 0x1e1140,
-0x24426cc0, 0x1000004a, 0x2e2a821, 0x8f420044,
-0x8faa006c, 0x3c040001, 0x248468b8, 0x3c050007,
-0xafaa0014, 0xafa20010, 0x8f460074, 0x8f470070,
-0x34a51500, 0x240b0001, 0xc002b3b, 0xafab005c,
-0x1000ffc3, 0x0, 0x8f430064, 0x8f420060,
-0x1062001a, 0x274a0064, 0x8f5e0064, 0x8fab005c,
-0xafaa004c, 0x27c20001, 0x304200ff, 0xafa20054,
-0x24020004, 0x1562000e, 0x1e1140, 0x1e1180,
-0x24420cc0, 0x2e21021, 0xafa20044, 0x9442002a,
-0x8faa0044, 0x8fab006c, 0x4b102b, 0x10400024,
-0x25550020, 0x240a0001, 0x10000021, 0xa3aa0097,
-0x24424cc0, 0x1000001e, 0x2e2a821, 0x8f420044,
-0x8fab006c, 0x3c040001, 0x248468c4, 0xafab0014,
-0xafa20010, 0x8f460064, 0x8f470060, 0x3c050007,
-0xc002b3b, 0x34a51800, 0x3c020008, 0x2c21024,
-0x1440ff34, 0x0, 0x8f420370, 0x240a0001,
-0xafaa005c, 0x24420001, 0xaf420370, 0x1000ff90,
-0x8f420370, 0x27a30036, 0x131040, 0x621821,
-0x94620000, 0x441021, 0x10000020, 0xa4620000,
-0x8fab0064, 0xaeab0018, 0x93a20097, 0x10400072,
-0x9821, 0x8faa0044, 0x8fa4006c, 0x8fa300a4,
-0x25420020, 0xafa20028, 0x25420008, 0xafa20030,
-0x25420010, 0xafaa002c, 0xafa20034, 0x9542002a,
-0xa7a20038, 0x95420018, 0xa7a2003a, 0x9542001a,
-0xa7a2003c, 0x9542001c, 0xa7a2003e, 0x94620018,
-0x24630002, 0x822023, 0x1880ffde, 0x26730001,
-0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc,
-0x26650001, 0xa2102a, 0x1440002b, 0x24030001,
-0x8f83012c, 0x10600023, 0x0, 0x8f820124,
-0x431023, 0x22143, 0x58800001, 0x24840040,
-0x8f820128, 0x431023, 0x21943, 0x58600001,
-0x24630040, 0x64102a, 0x54400001, 0x602021,
-0xaf4400fc, 0x8f4200fc, 0xa2102a, 0x10400011,
-0x24030001, 0x10000015, 0x306200ff, 0x8fab0064,
-0x96070018, 0xafab0010, 0x8e220008, 0x3c040001,
-0x248468dc, 0x8c430004, 0x8c420000, 0x34a52400,
-0x2403021, 0xc002b3b, 0xafa30014, 0x1000002b,
-0x0, 0x8f420334, 0x1821, 0x24420001,
-0xaf420334, 0x8f420334, 0x306200ff, 0x5040fedc,
-0x3c020800, 0x12600021, 0x9021, 0x8fb100a4,
-0x2208021, 0x8e220008, 0x96070018, 0x8fa60064,
-0x8c440000, 0x8c450004, 0x240a0001, 0xafaa0010,
-0xafbe0014, 0x8f420008, 0xafa20018, 0x8f42010c,
-0x40f809, 0x0, 0x1040ffd8, 0x3c050007,
-0x96020018, 0x8fab0064, 0x8faa009c, 0x1625821,
-0x14b102b, 0x10400004, 0xafab0064, 0x8f420148,
-0x1625823, 0xafab0064, 0x26100002, 0x26520001,
-0x253102b, 0x1440ffe3, 0x26310004, 0x8fb0006c,
-0x10000036, 0x97b10038, 0x8f4200fc, 0x24050002,
-0xa2102a, 0x1440001b, 0x24030001, 0x8f83012c,
-0x10600013, 0x0, 0x8f820124, 0x431023,
-0x22143, 0x58800001, 0x24840040, 0x8f820128,
-0x431023, 0x21943, 0x58600001, 0x24630040,
-0x64102a, 0x54400001, 0x602021, 0xaf4400fc,
-0x8f4200fc, 0xa2102a, 0x14400006, 0x24030001,
-0x8f420334, 0x1821, 0x24420001, 0xaf420334,
-0x8f420334, 0x306200ff, 0x1040fea5, 0x3c020800,
-0x96b1000a, 0x8fb0006c, 0x3223ffff, 0x70102b,
-0x54400001, 0x608021, 0x8ea40000, 0x8ea50004,
-0x240b0001, 0xafab0010, 0xafbe0014, 0x8f420008,
-0x8fa60064, 0xafa20018, 0x8f42010c, 0x40f809,
-0x2003821, 0x1040fea2, 0x3c050007, 0x96a3000e,
-0x97aa008e, 0x11400007, 0x609021, 0x934205c4,
-0x14400004, 0x0, 0x97ab0086, 0x6a1825,
-0xa6ab0016, 0x8faa007c, 0x3c02ffff, 0x1421024,
-0x10400003, 0xa1402, 0x34630400, 0xa6a20014,
-0x8fab006c, 0x560b0072, 0xa6a3000e, 0x34620004,
-0xa6a2000e, 0x8faa0074, 0x16a1021, 0xa6a2000a,
-0x8f430044, 0x8f4401a0, 0x8f4501a4, 0x34028000,
-0xafa20010, 0x8f420044, 0x2a03021, 0x24070020,
-0xafa20014, 0x8f42000c, 0x31940, 0x604821,
-0xafa20018, 0x8f42010c, 0x4021, 0xa92821,
-0xa9182b, 0x882021, 0x40f809, 0x832021,
-0x5040fe7f, 0xa6b2000e, 0x8f420368, 0xafa0006c,
-0xa34005c4, 0x2442ffff, 0xaf420368, 0x8fab005c,
-0x240a0001, 0x8f420368, 0x156a0006, 0x240a0002,
-0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c,
-0x8f42035c, 0x156a0006, 0x0, 0x8f420364,
-0x2442ffff, 0xaf420364, 0x10000005, 0x8f420364,
-0x8f420360, 0x2442ffff, 0xaf420360, 0x8f420360,
-0x8faa0054, 0x8fab004c, 0xad6a0000, 0x8f420044,
-0x8f440088, 0x8f430078, 0x24420001, 0x441024,
-0x24630001, 0xaf420044, 0xaf430078, 0x8c020240,
-0x62182b, 0x14600075, 0x24070008, 0x8f440168,
-0x8f45016c, 0x8f430044, 0x8f48000c, 0x8f860120,
-0x24020040, 0xafa20010, 0xafa30014, 0xafa80018,
-0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
-0x240b0001, 0x3c010001, 0x370821, 0xa02b40f2,
-0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
-0x2484688c, 0xafa20014, 0x8f460044, 0x8f870120,
-0x3c050009, 0xc002b3b, 0x34a51300, 0x1000000b,
-0x0, 0x8f420304, 0x24420001, 0xaf420304,
-0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001,
-0x370821, 0xa02040f2, 0xaf400078, 0x8f420318,
-0x24420001, 0xaf420318, 0x10000048, 0x8f420318,
-0xa6b0000a, 0x8f430044, 0x8f4401a0, 0x8f4501a4,
-0x34028000, 0xafa20010, 0x8f420044, 0x2a03021,
-0x24070020, 0xafa20014, 0x8f42000c, 0x31940,
-0x604821, 0xafa20018, 0x8f42010c, 0x4021,
-0xa92821, 0xa9182b, 0x882021, 0x40f809,
-0x832021, 0x1040fe1f, 0x240a0001, 0xa34a05c4,
-0x8fab006c, 0x8faa0064, 0x1705823, 0xafab006c,
-0x8fab009c, 0x1505021, 0x16a102b, 0x10400004,
-0xafaa0064, 0x8f420148, 0x1425023, 0xafaa0064,
-0x8f420368, 0x2442ffff, 0xaf420368, 0x8faa005c,
-0x240b0001, 0x8f420368, 0x154b0006, 0x240b0002,
-0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c,
-0x8f42035c, 0x114b0006, 0x0, 0x8f420360,
-0x2442ffff, 0xaf420360, 0x10000005, 0x8f420360,
-0x8f420364, 0x2442ffff, 0xaf420364, 0x8f420364,
-0x8fab0054, 0x8faa004c, 0xad4b0000, 0x8f420044,
-0x8f440088, 0x8f430078, 0x24420001, 0x441024,
-0x24630001, 0xaf420044, 0xaf430078, 0x8faa006c,
-0x1540fe0b, 0x0, 0x8fab006c, 0x1160001e,
-0x0, 0x934205c4, 0x10400009, 0x0,
-0x8faa0064, 0xaf4a00c4, 0xaf4b00c0, 0x8fab007c,
-0xaf4b00c8, 0x8faa0074, 0x1000000e, 0xaf4a00cc,
-0x97ab008e, 0x1160000b, 0x34038100, 0x8fa20020,
-0x8c46000c, 0xa443000c, 0x97aa0086, 0x8c440004,
-0x8c450008, 0xa44a000e, 0xac440000, 0xac450004,
-0xac460008, 0x8f42034c, 0x24420001, 0xaf42034c,
-0x10000010, 0x8f42034c, 0x8fab007c, 0x3164ffff,
-0x2484fffc, 0x801821, 0x8f440250, 0x8f450254,
-0x8f460118, 0x1021, 0xa32821, 0xa3382b,
-0x822021, 0x872021, 0xaf440250, 0xc0f809,
-0xaf450254, 0x8fbf00c8, 0x8fbe00c4, 0x8fb500c0,
-0x8fb300bc, 0x8fb200b8, 0x8fb100b4, 0x8fb000b0,
-0x3e00008, 0x27bd00d0, 0x3e00008, 0x0,
-0x27bdff38, 0x240b0001, 0xafbf00c0, 0xafbe00bc,
-0xafb500b8, 0xafb300b4, 0xafb200b0, 0xafb100ac,
-0xafb000a8, 0xa3a00087, 0xafa00044, 0xafab005c,
-0x934205c4, 0xa7a00076, 0x10400007, 0xa7a0007e,
-0x8f4c00c0, 0xafac0064, 0x8f4b00c8, 0x8f5e00c4,
-0x10000130, 0xafab006c, 0x8f420114, 0x40f809,
-0x0, 0x403021, 0x10c002a1, 0x0,
-0x8cc20000, 0x8cc30004, 0xafa20020, 0xafa30024,
-0x8fac0024, 0x8fbe0020, 0x3182ffff, 0x2442fffc,
-0xafa20064, 0x3c020006, 0x2c21024, 0x14400015,
-0xafac006c, 0x93c20000, 0x30420001, 0x10400011,
-0x2402ffff, 0x8fc30000, 0x14620004, 0x3402ffff,
-0x97c30004, 0x1062000b, 0x0, 0xc0024bb,
-0x3c02021, 0x304200ff, 0x14400006, 0x0,
-0x8f420118, 0x40f809, 0x0, 0x10000280,
-0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
-0x431024, 0x3c03ffff, 0x431824, 0x14600003,
-0xafa20024, 0x10000040, 0x8021, 0x3c020080,
-0x621024, 0x10400007, 0x0, 0x8f42038c,
-0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036,
-0x24100001, 0x8f420210, 0x24420001, 0xaf420210,
-0x8f420210, 0x3c020001, 0x621024, 0x10400006,
-0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4,
-0x8f4201c4, 0x3c020002, 0x621024, 0x10400006,
-0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c,
-0x8f42037c, 0x3c020004, 0x621024, 0x10400006,
-0x3c020008, 0x8f420380, 0x24420001, 0xaf420380,
-0x8f420380, 0x3c020008, 0x621024, 0x10400006,
-0x3c020010, 0x8f420384, 0x24420001, 0xaf420384,
-0x8f420384, 0x3c020010, 0x621024, 0x10400006,
-0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0,
-0x8f4201c0, 0x3c020020, 0x621024, 0x10400006,
-0x24100001, 0x8f420388, 0x24420001, 0xaf420388,
-0x8f420388, 0x24100001, 0x8c020260, 0x8fab0064,
-0x4b102b, 0x10400015, 0x320200ff, 0x8f4201e8,
-0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8fac006c,
-0x8f8200e0, 0x358c0100, 0xafac006c, 0xafa20010,
-0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0,
-0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007,
-0xc002b3b, 0x34a53600, 0x320200ff, 0x10400010,
-0x3c020080, 0x2c21024, 0x1440000e, 0x32c20400,
-0x8fab006c, 0x3c020080, 0x34420100, 0x1621024,
-0x10400005, 0x0, 0x8f42020c, 0x24420001,
-0xaf42020c, 0x8f42020c, 0x10000202, 0x8fa30064,
-0x32c20400, 0x10400012, 0x34028100, 0x97c3000c,
-0x1462000f, 0x0, 0x240c0200, 0xa7ac0076,
-0x97c2000e, 0x8fc30008, 0x8fc40004, 0x8fab0064,
-0x8fc50000, 0x256bfffc, 0xafab0064, 0xa7a2007e,
-0xafc3000c, 0xafc40008, 0xafc50004, 0x27de0004,
-0x8fa70064, 0x320200ff, 0x14400034, 0x3c020100,
-0x97c4000c, 0x2c8305dd, 0x38828870, 0x2c420001,
-0x621825, 0x10600015, 0x2821, 0x32c20800,
-0x10400015, 0x24020800, 0x97c30014, 0x14620012,
-0x3402aaaa, 0x97c3000e, 0x14620007, 0x2021,
-0x97c30010, 0x24020300, 0x14620004, 0x801021,
-0x97c20012, 0x2c440001, 0x801021, 0x54400006,
-0x24050016, 0x10000004, 0x0, 0x24020800,
-0x50820001, 0x2405000e, 0x10a00013, 0x3c52021,
-0x24830009, 0x3c02001f, 0x3442ffff, 0x43102b,
-0x10400003, 0x0, 0x8f420148, 0x621823,
-0x90620000, 0x38430006, 0x2c630001, 0x38420011,
-0x2c420001, 0x621825, 0x10600004, 0x3c020100,
-0x94820002, 0x453821, 0x3c020100, 0x2c21024,
-0x5040000e, 0xafa70064, 0x8fac0064, 0x10ec0008,
-0x3c050007, 0x3c040001, 0x24846908, 0x8fa60064,
-0x34a54000, 0xafa00010, 0xc002b3b, 0xafa00014,
-0x8fab0064, 0x256b0004, 0xafab0064, 0x8f420080,
-0x8fac0064, 0x4c102b, 0x1040002c, 0x32c28000,
-0x10400034, 0x240b0003, 0x32c21000, 0x10400031,
-0xafab005c, 0x1000002e, 0x240c0004, 0x8f420350,
-0x2403ffbf, 0x283a024, 0x24420001, 0xaf420350,
-0x10000173, 0x8f420350, 0x3c020800, 0x2c2b025,
-0x2402ffbf, 0x282a024, 0x8f830128, 0x3c040001,
-0x248468d0, 0x26620001, 0xafa20014, 0xafa30010,
-0x8f860120, 0x8f870124, 0x3c050007, 0xc002b3b,
-0x34a55300, 0x10000162, 0x0, 0x8ea20000,
-0x8ea30004, 0x3c040001, 0x248468e8, 0xafb00010,
-0xafb10014, 0x8ea70018, 0x34a55900, 0xc002b3b,
-0x603021, 0x10000156, 0x0, 0x8f420084,
-0x8fab0064, 0x4b102b, 0x14400007, 0x3c020001,
-0x2c21024, 0x10400004, 0x0, 0x240c0002,
-0xafac005c, 0x8fab0064, 0x11600166, 0x27ac0020,
-0xafac008c, 0x8fab005c, 0x240c0001, 0x556c0021,
-0x240c0002, 0x8f430054, 0x8f420050, 0x1062000b,
-0x274b0054, 0x8f510054, 0x3403ecc0, 0xafab004c,
-0x26220001, 0x304201ff, 0xafa20054, 0x111140,
-0x431021, 0x1000006b, 0x2e2a821, 0x8f420044,
-0x8fac0064, 0x3c040001, 0x248468ac, 0xafac0014,
-0xafa20010, 0x8f460054, 0x8f470050, 0x3c050007,
-0xc002b3b, 0x34a54300, 0x8f430350, 0x2402ffbf,
-0x282a024, 0x24630001, 0xaf430350, 0x10000124,
-0x8f420350, 0x156c001d, 0x0, 0x8f430074,
-0x8f420070, 0x1062000a, 0x274b0074, 0x8f510074,
-0xafab004c, 0x26220001, 0x304203ff, 0xafa20054,
-0x111140, 0x24426cc0, 0x1000004a, 0x2e2a821,
-0x8f420044, 0x8fac0064, 0x3c040001, 0x248468b8,
-0x3c050007, 0xafac0014, 0xafa20010, 0x8f460074,
-0x8f470070, 0x34a54500, 0x240b0001, 0xc002b3b,
-0xafab005c, 0x1000ffc3, 0x0, 0x8f430064,
-0x8f420060, 0x1062001a, 0x274c0064, 0x8f510064,
-0x8fab005c, 0xafac004c, 0x26220001, 0x304200ff,
-0xafa20054, 0x24020004, 0x1562000e, 0x111140,
-0x111180, 0x24420cc0, 0x2e21021, 0xafa20044,
-0x9442002a, 0x8fac0044, 0x8fab0064, 0x4b102b,
-0x10400024, 0x25950020, 0x240c0001, 0x10000021,
-0xa3ac0087, 0x24424cc0, 0x1000001e, 0x2e2a821,
-0x8f420044, 0x8fab0064, 0x3c040001, 0x248468c4,
-0xafab0014, 0xafa20010, 0x8f460064, 0x8f470060,
-0x3c050007, 0xc002b3b, 0x34a54800, 0x3c020008,
-0x2c21024, 0x1440ff61, 0x0, 0x8f420370,
-0x240c0001, 0xafac005c, 0x24420001, 0xaf420370,
-0x1000ff90, 0x8f420370, 0x27a30036, 0x131040,
-0x621821, 0x94620000, 0x441021, 0x1000001f,
-0xa4620000, 0xaebe0018, 0x93a20087, 0x10400084,
-0x9821, 0x8fab0044, 0x8fa40064, 0x8fa3008c,
-0x25620020, 0xafa20028, 0x25620008, 0xafa20030,
-0x25620010, 0xafab002c, 0xafa20034, 0x9562002a,
-0xa7a20038, 0x95620018, 0xa7a2003a, 0x9562001a,
-0xa7a2003c, 0x9562001c, 0xa7a2003e, 0x94620018,
-0x24630002, 0x822023, 0x1880ffdf, 0x26730001,
-0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc,
-0x262102a, 0x14400030, 0x24030001, 0x8f83012c,
-0x10600028, 0x0, 0x8f820124, 0x431023,
-0x22143, 0x58800001, 0x24840040, 0x8f820128,
-0x431023, 0x21943, 0x58600001, 0x24630040,
-0x64102a, 0x54400001, 0x602021, 0xaf4400fc,
-0x8f4200fc, 0x262102a, 0x10400016, 0x24030001,
-0x1000001a, 0x306200ff, 0x8fac008c, 0x101040,
-0x4c1021, 0x94470018, 0x101080, 0x4c1021,
-0xafbe0010, 0x8c420008, 0x3c040001, 0x248468dc,
-0x3c050007, 0x8c430004, 0x8c420000, 0x34a55500,
-0x2003021, 0xc002b3b, 0xafa30014, 0x10000039,
-0x0, 0x8f420334, 0x1821, 0x24420001,
-0xaf420334, 0x8f420334, 0x306200ff, 0x1040ff06,
-0x8021, 0x8f430008, 0x2402fbff, 0x1260002d,
-0x625024, 0x3c0b4000, 0x22b4025, 0x8fb1008c,
-0x2669ffff, 0x2209021, 0x8e420008, 0x96270018,
-0x8c440000, 0x8c450004, 0x56090004, 0x240b0001,
-0x240c0002, 0x10000002, 0xafac0010, 0xafab0010,
-0x16000004, 0xafa80014, 0x8f420008, 0x10000002,
-0xafa20018, 0xafaa0018, 0x8f42010c, 0x3c03021,
-0xafa80098, 0xafa9009c, 0x40f809, 0xafaa00a0,
-0x8fa80098, 0x8fa9009c, 0x8faa00a0, 0x1040ffc2,
-0x3c02001f, 0x96230018, 0x3442ffff, 0x3c3f021,
-0x5e102b, 0x10400003, 0x26310002, 0x8f420148,
-0x3c2f023, 0x26100001, 0x213102b, 0x1440ffda,
-0x26520004, 0x8fb00064, 0x1000001a, 0x0,
-0x96a3000a, 0x8fb00064, 0x70102b, 0x54400001,
-0x608021, 0x8ea40000, 0x8ea50004, 0x8fab005c,
-0x240c0002, 0xafac0010, 0x934305c4, 0xb1700,
-0x10600003, 0x2223025, 0x3c020800, 0xc23025,
-0xafa60014, 0x8f420008, 0xafa20018, 0x8f42010c,
-0x3c03021, 0x40f809, 0x2003821, 0x1040fecb,
-0x3c050007, 0x97ac0076, 0x11800007, 0x96a3000e,
-0x934205c4, 0x14400004, 0x0, 0x97ab007e,
-0x6c1825, 0xa6ab0016, 0x8fac006c, 0x3c02ffff,
-0x1821024, 0x10400003, 0xc1402, 0x34630400,
-0xa6a20014, 0xa6b0000a, 0x8fab0064, 0x560b0006,
-0x3d0f021, 0x34620004, 0xafa00064, 0xa6a2000e,
-0x1000000d, 0xa34005c4, 0x8fac0064, 0x3c02001f,
-0x3442ffff, 0x5e102b, 0x1906023, 0xafac0064,
-0xa6a3000e, 0x240b0001, 0x10400003, 0xa34b05c4,
-0x8f420148, 0x3c2f023, 0x8fab0054, 0x8fac004c,
-0xad8b0000, 0x8fac0064, 0x1580feba, 0x0,
-0x8fab0064, 0x1160001b, 0x0, 0x934205c4,
-0x10400006, 0x0, 0xaf5e00c4, 0xaf4b00c0,
-0x8fac006c, 0x1000000e, 0xaf4c00c8, 0x97ab0076,
-0x1160000b, 0x34038100, 0x8fa20020, 0x8c46000c,
-0xa443000c, 0x97ac007e, 0x8c440004, 0x8c450008,
-0xa44c000e, 0xac440000, 0xac450004, 0xac460008,
-0x8f42034c, 0x24420001, 0xaf42034c, 0x10000010,
-0x8f42034c, 0x8fab006c, 0x3164ffff, 0x2484fffc,
-0x801821, 0x8f440250, 0x8f450254, 0x8f460118,
-0x1021, 0xa32821, 0xa3382b, 0x822021,
-0x872021, 0xaf440250, 0xc0f809, 0xaf450254,
-0x8fbf00c0, 0x8fbe00bc, 0x8fb500b8, 0x8fb300b4,
-0x8fb200b0, 0x8fb100ac, 0x8fb000a8, 0x3e00008,
-0x27bd00c8, 0x3e00008, 0x0, 0x27bdffd8,
-0xafbf0024, 0xafb00020, 0x8f43004c, 0x8f420048,
-0x10620034, 0x0, 0x8f430048, 0x8f42004c,
-0x622023, 0x4820001, 0x24840200, 0x8f430054,
-0x8f42004c, 0x43102b, 0x14400004, 0x24020200,
-0x8f43004c, 0x10000005, 0x431023, 0x8f420054,
-0x8f43004c, 0x431023, 0x2442ffff, 0x405021,
-0x8a102a, 0x54400001, 0x805021, 0x8f49004c,
-0x8f48004c, 0x8f440188, 0x8f45018c, 0x8f46004c,
-0x24071000, 0xafa70010, 0x84140, 0x1001821,
-0x12a4821, 0x313001ff, 0xafb00014, 0x8f470014,
-0x1021, 0x63140, 0xafa70018, 0xa32821,
-0xa3382b, 0x822021, 0x872021, 0x3402ecc0,
-0xc23021, 0x8f420108, 0x2e63021, 0x40f809,
-0xa3940, 0x54400001, 0xaf50004c, 0x8f43004c,
-0x8f420048, 0x14620018, 0x0, 0x8f420000,
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x2403fdff, 0x431024, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x10000002,
-0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb00020,
-0x3e00008, 0x27bd0028, 0x3e00008, 0x0,
-0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f43005c,
-0x8f420058, 0x10620049, 0x0, 0x8f430058,
-0x8f42005c, 0x622023, 0x4820001, 0x24840100,
-0x8f430064, 0x8f42005c, 0x43102b, 0x14400004,
-0x24020100, 0x8f43005c, 0x10000005, 0x431023,
-0x8f420064, 0x8f43005c, 0x431023, 0x2442ffff,
-0x403821, 0x87102a, 0x54400001, 0x803821,
-0x8f42005c, 0x471021, 0x305000ff, 0x32c21000,
-0x10400015, 0x24082000, 0x8f49005c, 0x8f440190,
-0x8f450194, 0x8f46005c, 0x73980, 0xafa80010,
-0xafb00014, 0x8f480014, 0x94980, 0x1201821,
-0x1021, 0xa32821, 0xa3482b, 0x822021,
-0x892021, 0x63180, 0xafa80018, 0x8f420108,
-0x10000014, 0x24c60cc0, 0x8f49005c, 0x8f440190,
-0x8f450194, 0x8f46005c, 0x73940, 0xafa80010,
-0xafb00014, 0x8f480014, 0x94940, 0x1201821,
-0x1021, 0xa32821, 0xa3482b, 0x822021,
-0x892021, 0x63140, 0xafa80018, 0x8f420108,
-0x24c64cc0, 0x40f809, 0x2e63021, 0x54400001,
-0xaf50005c, 0x8f43005c, 0x8f420058, 0x14620018,
-0x0, 0x8f420000, 0x10400007, 0x0,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x2403feff,
-0x431024, 0xaf820060, 0x8f420000, 0x10400003,
-0x0, 0x10000002, 0xaf80004c, 0xaf800048,
-0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028,
-0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
-0xafb00020, 0x8f43006c, 0x8f420068, 0x10620033,
-0x0, 0x8f430068, 0x8f42006c, 0x622023,
-0x4820001, 0x24840400, 0x8f430074, 0x8f42006c,
-0x43102b, 0x14400004, 0x24020400, 0x8f43006c,
-0x10000005, 0x431023, 0x8f420074, 0x8f43006c,
-0x431023, 0x2442ffff, 0x405021, 0x8a102a,
-0x54400001, 0x805021, 0x8f49006c, 0x8f48006c,
-0x8f440198, 0x8f45019c, 0x8f46006c, 0x24074000,
-0xafa70010, 0x84140, 0x1001821, 0x12a4821,
-0x313003ff, 0xafb00014, 0x8f470014, 0x1021,
-0x63140, 0x24c66cc0, 0xafa70018, 0xa32821,
-0xa3382b, 0x822021, 0x872021, 0x8f420108,
-0x2e63021, 0x40f809, 0xa3940, 0x54400001,
-0xaf50006c, 0x8f43006c, 0x8f420068, 0x14620018,
-0x0, 0x8f420000, 0x10400007, 0x0,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x2403f7ff,
-0x431024, 0xaf820060, 0x8f420000, 0x10400003,
-0x0, 0x10000002, 0xaf80004c, 0xaf800048,
-0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028,
-0x3e00008, 0x0, 0x8f4200fc, 0x3c030001,
-0x8f4400f8, 0x346330c8, 0x24420001, 0xaf4200fc,
-0x8f850128, 0x2e31021, 0x54820004, 0x24820008,
-0x3c020001, 0x34422ec8, 0x2e21021, 0x401821,
-0xaf4300f8, 0xac600000, 0x8f4200f4, 0x14620004,
-0x3c020001, 0x24a20020, 0x1000000f, 0xaf820128,
-0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004,
-0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021,
-0x401821, 0x8c620004, 0x21140, 0xa21021,
-0xaf820128, 0xac600000, 0x8ca30018, 0x30620070,
-0x1040002d, 0x30620020, 0x10400004, 0x3c020010,
-0x2c21024, 0x1040000d, 0x0, 0x30620040,
-0x10400004, 0x3c020020, 0x2c21024, 0x10400007,
-0x0, 0x30620010, 0x1040001f, 0x3c020040,
-0x2c21024, 0x1440001c, 0x0, 0x8f820040,
-0x30420001, 0x14400008, 0x2021, 0x8c030104,
-0x24020001, 0x50620005, 0x24040001, 0x8c020264,
-0x10400003, 0x801021, 0x24040001, 0x801021,
-0x10400006, 0x0, 0x8f42030c, 0x24420001,
-0xaf42030c, 0x10000008, 0x8f42030c, 0x8f820044,
-0x34420004, 0xaf820044, 0x8f420308, 0x24420001,
-0xaf420308, 0x8f420308, 0x3e00008, 0x0,
-0x3e00008, 0x0, 0x27bdff98, 0xafbf0060,
-0xafbe005c, 0xafb50058, 0xafb30054, 0xafb20050,
-0xafb1004c, 0xafb00048, 0x8f4200fc, 0x24420001,
-0xaf4200fc, 0x8f880128, 0x25020020, 0xaf820128,
-0x8d030018, 0x30620070, 0x1040002e, 0x30620020,
-0x10400004, 0x3c020010, 0x2c21024, 0x1040000d,
-0x0, 0x30620040, 0x10400004, 0x3c020020,
-0x2c21024, 0x10400007, 0x0, 0x30620010,
-0x104001a9, 0x3c020040, 0x2c21024, 0x144001a6,
-0x0, 0x8f820040, 0x30420001, 0x14400008,
-0x2021, 0x8c030104, 0x24020001, 0x50620005,
-0x24040001, 0x8c020264, 0x10400003, 0x801021,
-0x24040001, 0x801021, 0x10400006, 0x0,
-0x8f42030c, 0x24420001, 0xaf42030c, 0x10000192,
-0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044,
-0x8f420308, 0x24420001, 0xaf420308, 0x1000018a,
-0x8f420308, 0x30620002, 0x1040014b, 0x3c020800,
-0x8d1e001c, 0x1e5702, 0xafaa0034, 0x950a0016,
-0x3c22024, 0xafaa0024, 0x8faa0034, 0x24020001,
-0x15420006, 0x33deffff, 0x1e1140, 0x3403ecc0,
-0x431021, 0x10000010, 0x2e2a821, 0x24020002,
-0x15420005, 0x24020003, 0x1e1140, 0x24426cc0,
-0x10000009, 0x2e2a821, 0x15420005, 0x1e1180,
-0x1e1140, 0x24424cc0, 0x10000003, 0x2e2a821,
-0x571021, 0x24550ce0, 0x96a2000e, 0x304afffc,
-0x30420400, 0x10400003, 0xafaa002c, 0x100000e1,
-0x8821, 0x10800004, 0x8821, 0x97b10026,
-0x100000dd, 0xa6b10012, 0x8eb30018, 0x966a000c,
-0xa7aa003e, 0x97a5003e, 0x2ca305dd, 0x38a28870,
-0x2c420001, 0x621825, 0x10600015, 0x2021,
-0x32c20800, 0x10400015, 0x24020800, 0x96630014,
-0x14620012, 0x3402aaaa, 0x9663000e, 0x14620007,
-0x2821, 0x96630010, 0x24020300, 0x14620004,
-0xa01021, 0x96620012, 0x2c450001, 0xa01021,
-0x54400006, 0x24040016, 0x10000004, 0x0,
-0x24020800, 0x50a20001, 0x2404000e, 0x108000b9,
-0x2649021, 0x92420000, 0x3042000f, 0x28080,
-0x32c20100, 0x10400020, 0x2501821, 0x3c020020,
-0x43102b, 0x1440000e, 0x2402021, 0x2821,
-0x94820000, 0x24840002, 0xa22821, 0x83102b,
-0x1440fffb, 0x30a2ffff, 0x51c02, 0x622821,
-0x51c02, 0x30a2ffff, 0x10000009, 0x622821,
-0x8f470148, 0x8f420110, 0x102842, 0x3c060020,
-0x40f809, 0xafa80040, 0x3045ffff, 0x8fa80040,
-0x50a00001, 0x3405ffff, 0x8faa002c, 0x354a0002,
-0x10000002, 0xafaa002c, 0x2821, 0x32c20080,
-0x10400090, 0xa6a50010, 0x26430009, 0x3c02001f,
-0x3442ffff, 0x43102b, 0x10400003, 0x0,
-0x8f420148, 0x621823, 0x90660000, 0x30c200ff,
-0x38430006, 0x2c630001, 0x38420011, 0x2c420001,
-0x621825, 0x1060007f, 0x24020800, 0x8821,
-0x97a3003e, 0x1462000f, 0x2602021, 0x96710000,
-0x96620002, 0x96630004, 0x96640006, 0x2228821,
-0x2238821, 0x2248821, 0x96620008, 0x9663000a,
-0x9664000c, 0x2228821, 0x2238821, 0x10000007,
-0x2248821, 0x94820000, 0x24840002, 0x2228821,
-0x92102b, 0x1440fffb, 0x0, 0x111c02,
-0x3222ffff, 0x628821, 0x111c02, 0x3222ffff,
-0x628821, 0x32c20200, 0x10400003, 0x26440006,
-0x1000003e, 0x8021, 0x3c05001f, 0x34a5ffff,
-0xa4102b, 0x10400003, 0x0, 0x8f420148,
-0x822023, 0x94820000, 0x30421fff, 0x10400004,
-0x2644000c, 0x96420002, 0x10000030, 0x508023,
-0x96420002, 0x26430014, 0x508023, 0x3c020020,
-0x43102b, 0x1440000a, 0xd08021, 0x9642000c,
-0x2028021, 0x9642000e, 0x96430010, 0x96440012,
-0x2028021, 0x2038021, 0x10000020, 0x2048021,
-0xa4102b, 0x10400003, 0x0, 0x8f420148,
-0x822023, 0x94820000, 0x24840002, 0x2028021,
-0xa4102b, 0x10400003, 0x0, 0x8f420148,
-0x822023, 0x94820000, 0x24840002, 0x2028021,
-0xa4102b, 0x10400003, 0x0, 0x8f420148,
-0x822023, 0x94820000, 0x24840002, 0x2028021,
-0xa4102b, 0x10400003, 0x0, 0x8f420148,
-0x822023, 0x94820000, 0x2028021, 0x3c020100,
-0x2c21024, 0x1040000e, 0x0, 0x8faa002c,
-0x31420004, 0x1040000a, 0x0, 0x9504000e,
-0x2642021, 0xc003eec, 0x2484fffc, 0x3042ffff,
-0x2228821, 0x111c02, 0x3222ffff, 0x628821,
-0x8faa0024, 0x1518823, 0x111402, 0x2228821,
-0x2308821, 0x111402, 0x2228821, 0x3231ffff,
-0x52200001, 0x3411ffff, 0x8faa002c, 0x354a0001,
-0xafaa002c, 0xa6b10012, 0x97aa002e, 0xa6aa000e,
-0x8faa002c, 0x31420004, 0x10400002, 0x24091000,
-0x34098000, 0x8f480044, 0x8f4401a0, 0x8f4501a4,
-0xafa90010, 0x8f490044, 0x84140, 0x1001821,
-0xafa90014, 0x8f48000c, 0x2a03021, 0x24070020,
-0xafa80018, 0x8f48010c, 0x1021, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x1440000b, 0x0, 0x8f820128, 0x3c040001,
-0x24846914, 0xafbe0014, 0xafa20010, 0x8f860124,
-0x8f870120, 0x3c050007, 0xc002b3b, 0x34a59920,
-0x8f420368, 0x2442ffff, 0xaf420368, 0x8f420044,
-0x8f430088, 0x24420001, 0x431024, 0xaf420044,
-0x8faa0034, 0x8f440368, 0x24020001, 0x15420006,
-0x24020002, 0x8f42035c, 0x2442ffff, 0xaf42035c,
-0x10000049, 0x8f42035c, 0x15420006, 0x0,
-0x8f420364, 0x2442ffff, 0xaf420364, 0x10000042,
-0x8f420364, 0x8f420360, 0x2442ffff, 0xaf420360,
-0x1000003d, 0x8f420360, 0x30621000, 0x10400005,
-0x30628000, 0x8f420078, 0x24420001, 0x10000036,
-0xaf420078, 0x10400034, 0x0, 0x8f420078,
-0x24420001, 0xaf420078, 0x8c030240, 0x43102b,
-0x1440002d, 0x24070008, 0x8f440168, 0x8f45016c,
-0x8f430044, 0x8f48000c, 0x8f860120, 0x24020040,
-0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c,
-0x40f809, 0x24c6001c, 0x14400011, 0x24020001,
-0x3c010001, 0x370821, 0xa02240f2, 0x8f820124,
-0xafa20010, 0x8f820128, 0x3c040001, 0x2484688c,
-0xafa20014, 0x8f460044, 0x8f870120, 0x3c050009,
-0xc002b3b, 0x34a51300, 0x1000000b, 0x0,
-0x8f420304, 0x24420001, 0xaf420304, 0x8f420304,
-0x8f420044, 0xaf42007c, 0x3c010001, 0x370821,
-0xa02040f2, 0xaf400078, 0x8f420318, 0x24420001,
-0xaf420318, 0x8f420318, 0x8fbf0060, 0x8fbe005c,
-0x8fb50058, 0x8fb30054, 0x8fb20050, 0x8fb1004c,
-0x8fb00048, 0x3e00008, 0x27bd0068, 0x3e00008,
-0x0, 0x0, 0x0, 0x8f42013c,
-0xaf8200c0, 0x8f42013c, 0xaf8200c4, 0x8f42013c,
-0xaf8200c8, 0x8f420138, 0xaf8200d0, 0x8f420138,
-0xaf8200d4, 0x8f420138, 0x3e00008, 0xaf8200d8,
-0x27bdffe0, 0x27840208, 0x24050200, 0xafbf0018,
-0xc002bbf, 0x24060008, 0x8c020204, 0xc004012,
-0xaf820210, 0x3c020001, 0x8c426d94, 0x30420002,
-0x1040000e, 0x2021, 0x8c060248, 0x24020002,
-0x3c010001, 0xac226d98, 0xc005104, 0x24050002,
-0x2021, 0x8c060248, 0x24020001, 0x3c010001,
-0xac226d98, 0x10000011, 0x24050001, 0x8c060248,
-0x24020004, 0x3c010001, 0xac226d98, 0xc005104,
-0x24050004, 0x3c020001, 0x8c426d94, 0x30420001,
-0x10400008, 0x24020001, 0x3c010001, 0xac226d98,
-0x2021, 0x24050001, 0x3c06601b, 0xc005104,
-0x0, 0x3c040001, 0x248469d0, 0x8f420150,
-0x8f430154, 0x3c050008, 0x8f460158, 0x21640,
-0x31940, 0x34630403, 0x431025, 0x633c0,
-0x461025, 0xaf82021c, 0xafa00010, 0xafa00014,
-0x8f86021c, 0x34a50200, 0xc002b3b, 0x3821,
-0x3c010001, 0xac206d90, 0x3c010001, 0xac206da8,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0,
-0x3c050008, 0x34a50300, 0xafbf0018, 0xafa00010,
-0xafa00014, 0x8f860200, 0x3c040001, 0x248469dc,
-0xc002b3b, 0x3821, 0x8f420410, 0x24420001,
-0xaf420410, 0x8f420410, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb1001c,
-0xafb00018, 0x8f4203a4, 0x24420001, 0xaf4203a4,
-0x8f4203a4, 0x8f900220, 0x8f8200e0, 0xafa20010,
-0x8f8200e4, 0xafa20014, 0x8f8600c4, 0x8f8700c8,
-0x3c040001, 0x248469e8, 0xc002b3b, 0x2002821,
-0x3c044000, 0x2041024, 0x504000b4, 0x3c040100,
-0x8f4203bc, 0x24420001, 0xaf4203bc, 0x8f4203bc,
-0x8f8700c4, 0x8f8300c8, 0x8f420148, 0x671823,
-0x43102b, 0x10400003, 0x0, 0x8f420148,
-0x621821, 0x10600005, 0x0, 0x8f42014c,
-0x43102b, 0x1040000b, 0x0, 0x8f8200e0,
-0x8f430124, 0xaf42011c, 0xaf430114, 0x8f820220,
-0x3c0308ff, 0x3463fffb, 0x431024, 0x100000ce,
-0x441025, 0x8f820220, 0x3c0308ff, 0x3463ffff,
-0x431024, 0x34420004, 0xaf820220, 0x8f8200e0,
-0x8f430124, 0xaf42011c, 0xaf430114, 0x8f8600c8,
-0x8f840120, 0x8f830124, 0x10000005, 0x2821,
-0x14620002, 0x24620020, 0x27624800, 0x401821,
-0x1064000c, 0x30a200ff, 0x8c620018, 0x30420003,
-0x1040fff7, 0x27624fe0, 0x8f4203d0, 0x24050001,
-0x24420001, 0xaf4203d0, 0x8f4203d0, 0x8c660008,
-0x30a200ff, 0x14400058, 0x0, 0x934205c4,
-0x14400055, 0x0, 0x8f8700c4, 0x8f8800e0,
-0x8f8400e4, 0x2402fff8, 0x1024024, 0x1041023,
-0x218c3, 0x4620001, 0x24630200, 0x10600005,
-0x24020001, 0x10620009, 0x0, 0x1000001f,
-0x0, 0x8f4203c0, 0xe03021, 0x24420001,
-0xaf4203c0, 0x10000040, 0x8f4203c0, 0x8f4203c4,
-0x24420001, 0xaf4203c4, 0x8c860000, 0x8f420148,
-0x8f4303c4, 0xe61823, 0x43102b, 0x10400004,
-0x2c62233f, 0x8f420148, 0x621821, 0x2c62233f,
-0x14400031, 0x0, 0x8f42020c, 0x24420001,
-0xaf42020c, 0x8f42020c, 0xe03021, 0x24820008,
-0xaf8200e4, 0x10000028, 0xaf8200e8, 0x8f4203c8,
-0x24420001, 0xaf4203c8, 0x8f4203c8, 0x8c850000,
-0x8f420148, 0xa71823, 0x43102b, 0x10400003,
-0x0, 0x8f420148, 0x621821, 0x8f42014c,
-0x43102b, 0x5440000a, 0xa03021, 0x8f42020c,
-0x24420001, 0xaf42020c, 0x8f42020c, 0x24820008,
-0xaf8200e4, 0x8f8400e4, 0x1488ffec, 0xaf8400e8,
-0x1488000d, 0x27623000, 0x14820002, 0x2482fff8,
-0x27623ff8, 0x94430006, 0x3c02001f, 0x3442ffff,
-0xc33021, 0x46102b, 0x10400003, 0x0,
-0x8f420148, 0xc23023, 0xaf8600c8, 0x8f8300c4,
-0x8f420148, 0xc31823, 0x43102b, 0x10400003,
-0x0, 0x8f420148, 0x621821, 0x10600005,
-0x0, 0x8f42014c, 0x43102b, 0x50400008,
-0x3c02fdff, 0x8f820220, 0x3c0308ff, 0x3463fffb,
-0x431024, 0x3c034000, 0x1000003f, 0x431025,
-0x8f4303cc, 0x3442ffff, 0x282a024, 0x24630001,
-0xaf4303cc, 0x10000039, 0x8f4203cc, 0x2041024,
-0x1040000e, 0x3c110200, 0x8f4203a8, 0x24420001,
-0xaf4203a8, 0x8f4203a8, 0x8f820220, 0x3c0308ff,
-0x3463ffff, 0x431024, 0x441025, 0xc003daf,
-0xaf820220, 0x10000029, 0x0, 0x2111024,
-0x50400008, 0x3c110400, 0x8f4203ac, 0x24420001,
-0xaf4203ac, 0xc003daf, 0x8f4203ac, 0x10000019,
-0x0, 0x2111024, 0x1040001c, 0x0,
-0x8f830224, 0x24021402, 0x14620009, 0x3c050008,
-0x3c040001, 0x248469f4, 0xafa00010, 0xafa00014,
-0x8f860224, 0x34a50500, 0xc002b3b, 0x3821,
-0x8f4203b0, 0x24420001, 0xaf4203b0, 0x8f4203b0,
-0x8f820220, 0x2002021, 0x34420002, 0xc004e9c,
-0xaf820220, 0x8f820220, 0x3c0308ff, 0x3463ffff,
-0x431024, 0x511025, 0xaf820220, 0x8fbf0020,
-0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028,
-0x3e00008, 0x0, 0x3c020001, 0x8c426da8,
-0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040,
-0xafb3003c, 0xafb20038, 0xafb10034, 0x1040000f,
-0xafb00030, 0x3c040001, 0x24846a00, 0x3c050008,
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50600,
-0x24020001, 0x3c010001, 0xac206da8, 0x3c010001,
-0xac226d9c, 0xc002b3b, 0x3821, 0x3c037fff,
-0x8c020268, 0x3463ffff, 0x3c04fdff, 0x431024,
-0xac020268, 0x8f420004, 0x3484ffff, 0x30420002,
-0x10400092, 0x284a024, 0x3c040600, 0x34842000,
-0x8f420004, 0x2821, 0x2403fffd, 0x431024,
-0xaf420004, 0xafa40020, 0x8f5e0018, 0x27aa0020,
-0x240200ff, 0x13c20002, 0xafaa002c, 0x27c50001,
-0x8c020228, 0xa09021, 0x1642000e, 0x1e38c0,
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
-0x8c020228, 0x3c040001, 0x24846998, 0x3c050009,
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d,
-0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024,
-0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b,
-0x9821, 0xe08821, 0x263504c0, 0x8f440178,
-0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010,
-0xafb20014, 0x8f48000c, 0x1021, 0x2f53021,
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x54400006, 0x24130001, 0x8f820054, 0x2021023,
-0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff,
-0x54400017, 0xaf520018, 0x8f420378, 0x24420001,
-0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
-0xafa20010, 0x8f820124, 0x3c040001, 0x248469a4,
-0x3c050009, 0xafa20014, 0x8d460000, 0x10000035,
-0x34a50600, 0x8f420308, 0x24130001, 0x24420001,
-0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff,
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x10400016, 0x9821, 0x3c150020,
-0x24110010, 0x8f42000c, 0x8f440160, 0x8f450164,
-0x8f860120, 0xafb10010, 0xafb20014, 0x551025,
-0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
-0x24c6001c, 0x1440ffe3, 0x0, 0x8f820054,
-0x2021023, 0x2c4203e9, 0x1440ffee, 0x0,
-0x326200ff, 0x14400011, 0x0, 0x8f420378,
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
-0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001,
-0x248469ac, 0x3c050009, 0xafa20014, 0x8d460000,
-0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202ec,
-0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8fbf0048,
-0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038,
-0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050,
-0x3c020001, 0x8c426da8, 0x27bdffe0, 0x1440000d,
-0xafbf0018, 0x3c040001, 0x24846a0c, 0x3c050008,
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50700,
-0x24020001, 0x3c010001, 0xac226da8, 0xc002b3b,
-0x3821, 0x3c020004, 0x2c21024, 0x10400007,
-0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff,
-0x431024, 0x34420008, 0xaf820220, 0x3c050001,
-0x8ca56d98, 0x24020001, 0x14a20007, 0x2021,
-0xc00529b, 0x24050001, 0xac02026c, 0x8c03026c,
-0x10000006, 0x3c020007, 0xc00529b, 0x2021,
-0xac020268, 0x8c030268, 0x3c020007, 0x621824,
-0x3c020002, 0x5062000d, 0x3c0205f5, 0x43102b,
-0x14400006, 0x3c020004, 0x3c020001, 0x10620009,
-0x3c020098, 0x1000000b, 0x0, 0x14620009,
-0x3c023b9a, 0x10000004, 0x3442ca00, 0x10000002,
-0x3442e100, 0x34429680, 0xaf4201fc, 0x8f4201fc,
-0xaee20064, 0x8fbf0018, 0x3e00008, 0x27bd0020,
-0x0, 0x0, 0x0, 0x86102b,
-0x50400001, 0x872023, 0xc41023, 0x24843,
-0x125102b, 0x1040001b, 0x91040, 0x824021,
-0x88102b, 0x10400007, 0x1821, 0x94820000,
-0x24840002, 0x621821, 0x88102b, 0x1440fffb,
-0x0, 0x602021, 0xc73023, 0xa91023,
-0x21040, 0xc22821, 0xc5102b, 0x10400007,
-0x1821, 0x94c20000, 0x24c60002, 0x621821,
-0xc5102b, 0x1440fffb, 0x0, 0x1000000d,
-0x832021, 0x51040, 0x822821, 0x85102b,
-0x10400007, 0x1821, 0x94820000, 0x24840002,
-0x621821, 0x85102b, 0x1440fffb, 0x0,
-0x602021, 0x41c02, 0x3082ffff, 0x622021,
-0x41c02, 0x3082ffff, 0x622021, 0x3e00008,
-0x3082ffff, 0x3e00008, 0x0, 0x802821,
-0x30a20001, 0x1040002b, 0x3c03001f, 0x3463ffff,
-0x24a20004, 0x62102b, 0x54400007, 0x65102b,
-0x90a20001, 0x90a40003, 0x90a30000, 0x90a50002,
-0x1000002a, 0x441021, 0x10400003, 0x0,
-0x8f420148, 0xa22823, 0x90a40000, 0x24a50001,
-0x65102b, 0x10400003, 0x0, 0x8f420148,
-0xa22823, 0x90a20000, 0x24a50001, 0x21200,
-0x822021, 0x65102b, 0x10400003, 0x0,
-0x8f420148, 0xa22823, 0x90a20000, 0x24a50001,
-0x822021, 0x65102b, 0x10400003, 0x0,
-0x8f420148, 0xa22823, 0x90a20000, 0x1000002d,
-0x21200, 0x3463ffff, 0x24a20004, 0x62102b,
-0x5440000a, 0x65102b, 0x90a20000, 0x90a40002,
-0x90a30001, 0x90a50003, 0x441021, 0x21200,
-0x651821, 0x10000020, 0x432021, 0x10400003,
-0x0, 0x8f420148, 0xa22823, 0x90a20000,
-0x24a50001, 0x22200, 0x65102b, 0x10400003,
-0x0, 0x8f420148, 0xa22823, 0x90a20000,
-0x24a50001, 0x822021, 0x65102b, 0x10400003,
-0x0, 0x8f420148, 0xa22823, 0x90a20000,
-0x24a50001, 0x21200, 0x822021, 0x65102b,
-0x10400003, 0x0, 0x8f420148, 0xa22823,
-0x90a20000, 0x822021, 0x41c02, 0x3082ffff,
-0x622021, 0x41c02, 0x3082ffff, 0x622021,
-0x3e00008, 0x3082ffff, 0x0, 0x8f820220,
-0x34420002, 0xaf820220, 0x3c020002, 0x8c428ff8,
-0x30424000, 0x10400054, 0x24040001, 0x8f820200,
-0x24067fff, 0x8f830200, 0x30450002, 0x2402fffd,
-0x621824, 0xaf830200, 0xaf840204, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x8f820224, 0x1444004d, 0x42040, 0xc4102b,
-0x1040fff1, 0x0, 0x8f820200, 0x451025,
-0xaf820200, 0x8f820220, 0x34428000, 0xaf820220,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
-0x0, 0x8f820220, 0x3c030004, 0x431024,
-0x1440000f, 0x0, 0x8f820220, 0x3c03ffff,
-0x34637fff, 0x431024, 0xaf820220, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x8f820220, 0x3c030004, 0x431024, 0x1440000d,
-0x0, 0x8f820220, 0x34428000, 0xaf820220,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
-0x0, 0x8f820220, 0x3c030004, 0x431024,
-0x1040001b, 0x1021, 0x8f830220, 0x24020001,
-0x10000015, 0x3c04f700, 0x8f820220, 0x3c04f700,
-0x441025, 0xaf820220, 0x8f820220, 0x2403fffd,
-0x431024, 0xaf820220, 0x8f820220, 0x3c030300,
-0x431024, 0x14400003, 0x0, 0x10000008,
-0x1021, 0x8f820220, 0x34420002, 0xaf820220,
-0x8f830220, 0x24020001, 0x641825, 0xaf830220,
-0x3e00008, 0x0, 0x2021, 0x3c050100,
-0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220,
-0x27625000, 0xaf8200c0, 0x27625000, 0xaf8200c4,
-0x27625000, 0xaf8200c8, 0x27625000, 0xaf8200d0,
-0x27625000, 0xaf8200d4, 0x27625000, 0xaf8200d8,
-0x27623000, 0xaf8200e0, 0x27623000, 0xaf8200e4,
-0x27623000, 0xaf8200e8, 0x27622800, 0xaf8200f0,
-0x27622800, 0xaf8200f4, 0x27622800, 0xaf8200f8,
-0x418c0, 0x24840001, 0x3631021, 0xac453004,
-0x3631021, 0xac403000, 0x28820200, 0x1440fff9,
-0x418c0, 0x2021, 0x418c0, 0x24840001,
-0x3631021, 0xac402804, 0x3631021, 0xac402800,
-0x28820100, 0x1440fff9, 0x418c0, 0xaf80023c,
-0x24030080, 0x24040100, 0xac600000, 0x24630004,
-0x64102b, 0x5440fffd, 0xac600000, 0x8f830040,
-0x3c02f000, 0x621824, 0x3c025000, 0x1062000c,
-0x43102b, 0x14400006, 0x3c026000, 0x3c024000,
-0x10620008, 0x24020800, 0x10000008, 0x0,
-0x10620004, 0x24020800, 0x10000004, 0x0,
-0x24020700, 0x3c010001, 0xac226dac, 0x3e00008,
-0x0, 0x3c020001, 0x8c426dbc, 0x27bdffd0,
-0xafbf002c, 0xafb20028, 0xafb10024, 0xafb00020,
-0x3c010001, 0x10400005, 0xac206d94, 0xc004d9e,
-0x0, 0x3c010001, 0xac206dbc, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
-0x621023, 0x2c420065, 0x1440fffc, 0x0,
-0xc004db9, 0x0, 0x24040001, 0x2821,
-0x27a60018, 0x34028000, 0xc0045be, 0xa7a20018,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
-0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
-0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
-0x24040001, 0x3c060001, 0x24c66f24, 0xc00457c,
-0x24050002, 0x8f830054, 0x8f820054, 0x10000002,
-0x24630064, 0x8f820054, 0x621023, 0x2c420065,
-0x1440fffc, 0x24040001, 0x24050003, 0x3c100001,
-0x26106f26, 0xc00457c, 0x2003021, 0x97a60018,
-0x3c070001, 0x94e76f24, 0x3c040001, 0x24846ae0,
-0xafa00014, 0x96020000, 0x3c05000d, 0x34a50100,
-0xc002b3b, 0xafa20010, 0x97a20018, 0x1040004d,
-0x24036040, 0x96020000, 0x3042fff0, 0x1443000c,
-0x24020020, 0x3c030001, 0x94636f24, 0x1462000b,
-0x24027830, 0x24020003, 0x3c010001, 0xac226d94,
-0x24020005, 0x3c010001, 0x1000003f, 0xac226f34,
-0x3c030001, 0x94636f24, 0x24027830, 0x1462000c,
-0x24030010, 0x3c020001, 0x94426f26, 0x3042fff0,
-0x14430007, 0x24020003, 0x3c010001, 0xac226d94,
-0x24020006, 0x3c010001, 0x1000002f, 0xac226f34,
-0x3c020001, 0x8c426d94, 0x3c030001, 0x94636f24,
-0x34420001, 0x3c010001, 0xac226d94, 0x24020015,
-0x1462000b, 0x0, 0x3c020001, 0x94426f26,
-0x3042fff0, 0x3843f420, 0x2c630001, 0x3842f430,
-0x2c420001, 0x621825, 0x1460001b, 0x24020003,
-0x3c030001, 0x94636f24, 0x24027810, 0x14620016,
-0x24020002, 0x3c020001, 0x94426f26, 0x3042fff0,
-0x14400011, 0x24020002, 0x1000000f, 0x24020004,
-0x3c020001, 0x8c426d94, 0x34420008, 0x3c010001,
-0xac226d94, 0x1000005e, 0x24020004, 0x3c020001,
-0x8c426d94, 0x34420004, 0x3c010001, 0x100000af,
-0xac226d94, 0x24020001, 0x3c010001, 0xac226f40,
-0x3c020001, 0x8c426d94, 0x30420002, 0x144000b2,
-0x3c09fff0, 0x24020e00, 0xaf820238, 0x8f840054,
-0x8f820054, 0x24030008, 0x3c010001, 0xac236d98,
-0x10000002, 0x248401f4, 0x8f820054, 0x821023,
-0x2c4201f5, 0x1440fffc, 0x3c0200c8, 0x344201fb,
-0xaf820238, 0x8f830054, 0x8f820054, 0x10000002,
-0x246301f4, 0x8f820054, 0x621023, 0x2c4201f5,
-0x1440fffc, 0x8021, 0x24120001, 0x24110009,
-0xc004482, 0x0, 0x3c010001, 0xac326db4,
-0xc004547, 0x0, 0x3c020001, 0x8c426db4,
-0x1451fffb, 0x3c0200c8, 0x344201f6, 0xaf820238,
-0x8f830054, 0x8f820054, 0x10000002, 0x2463000a,
-0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc,
-0x0, 0x8f820220, 0x24040001, 0x34420002,
-0xaf820220, 0x8f830200, 0x24057fff, 0x2402fffd,
-0x621824, 0xaf830200, 0xaf840204, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x8f820224, 0x14440005, 0x34028000, 0x42040,
-0xa4102b, 0x1040fff0, 0x34028000, 0x1082ffa0,
-0x26100001, 0x2e020014, 0x1440ffcd, 0x24020004,
-0x3c010001, 0xac226d98, 0x8021, 0x24120009,
-0x3c11ffff, 0x36313f7f, 0xc004482, 0x0,
-0x24020001, 0x3c010001, 0xac226db4, 0xc004547,
-0x0, 0x3c020001, 0x8c426db4, 0x1452fffb,
-0x0, 0x8f820044, 0x511024, 0x34425080,
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x2463000a, 0x8f820054, 0x621023, 0x2c42000b,
-0x1440fffc, 0x0, 0x8f820044, 0x511024,
-0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054,
-0x10000002, 0x2463000a, 0x8f820054, 0x621023,
-0x2c42000b, 0x1440fffc, 0x0, 0x8f820220,
-0x3c03f700, 0x431025, 0xaf820220, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
-0x621023, 0x2c420065, 0x1440fffc, 0x0,
-0x8f820220, 0x24040001, 0x34420002, 0xaf820220,
-0x8f830200, 0x24057fff, 0x2402fffd, 0x621824,
-0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054,
-0x10000002, 0x24630001, 0x8f820054, 0x621023,
-0x2c420002, 0x1440fffc, 0x0, 0x8f820224,
-0x14440005, 0x34028000, 0x42040, 0xa4102b,
-0x1040fff0, 0x34028000, 0x1082ff50, 0x26100001,
-0x2e020064, 0x1440ffb0, 0x0, 0x3c020001,
-0x8c426d94, 0x30420004, 0x14400007, 0x3c09fff0,
-0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024,
-0xaf820044, 0x3c09fff0, 0x3529bdc0, 0x3c060001,
-0x8cc66d94, 0x3c040001, 0x24846ae0, 0x24020001,
-0x3c010001, 0xac226d9c, 0x8f820054, 0x3c070001,
-0x8ce76f40, 0x3c030001, 0x94636f24, 0x3c080001,
-0x95086f26, 0x3c05000d, 0x34a50100, 0x3c010001,
-0xac206d98, 0x491021, 0x3c010001, 0xac226f30,
-0xafa30010, 0xc002b3b, 0xafa80014, 0x8fbf002c,
-0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008,
-0x27bd0030, 0x27bdffe8, 0x3c050001, 0x8ca56d98,
-0x24060004, 0x24020001, 0x14a20014, 0xafbf0010,
-0x3c020002, 0x8c428ffc, 0x30428000, 0x10400005,
-0x3c04000f, 0x3c030001, 0x8c636f40, 0x10000005,
-0x34844240, 0x3c040004, 0x3c030001, 0x8c636f40,
-0x348493e0, 0x24020005, 0x14620016, 0x0,
-0x3c04003d, 0x10000013, 0x34840900, 0x3c020002,
-0x8c428ff8, 0x30428000, 0x10400005, 0x3c04001e,
-0x3c030001, 0x8c636f40, 0x10000005, 0x34848480,
-0x3c04000f, 0x3c030001, 0x8c636f40, 0x34844240,
-0x24020005, 0x14620003, 0x0, 0x3c04007a,
-0x34841200, 0x3c020001, 0x8c426f30, 0x8f830054,
-0x441021, 0x431023, 0x44102b, 0x1440004c,
-0x0, 0x3c020001, 0x8c426da0, 0x14400048,
-0x0, 0x3c010001, 0x10c00025, 0xac206db0,
-0x3c090001, 0x8d296d94, 0x24070001, 0x3c044000,
-0x3c080002, 0x25088ffc, 0x250afffc, 0x52842,
-0x14a00002, 0x24c6ffff, 0x24050008, 0xa91024,
-0x10400010, 0x0, 0x14a70008, 0x0,
-0x8d020000, 0x441024, 0x1040000a, 0x0,
-0x3c010001, 0x10000007, 0xac256db0, 0x8d420000,
-0x441024, 0x10400003, 0x0, 0x3c010001,
-0xac276db0, 0x3c020001, 0x8c426db0, 0x6182b,
-0x2c420001, 0x431024, 0x5440ffe5, 0x52842,
-0x8f820054, 0x3c030001, 0x8c636db0, 0x3c010001,
-0xac226f30, 0x1060003b, 0x24020005, 0x3c030001,
-0x8c636f40, 0x3c010001, 0xac256d98, 0x14620012,
-0x24020001, 0x3c020002, 0x8c428ff8, 0x3c032000,
-0x34635000, 0x431024, 0x14400006, 0x24020001,
-0x3c010001, 0xac206f1c, 0x3c010001, 0xac226d98,
-0x24020001, 0x3c010001, 0xac226e24, 0x3c010001,
-0xac226da4, 0x24020001, 0x3c010001, 0xac226d9c,
-0x3c020001, 0x8c426db0, 0x1040001e, 0x0,
-0x3c020001, 0x8c426d9c, 0x10400008, 0x24020001,
-0x3c010001, 0xac206d9c, 0xaee204b8, 0x3c010001,
-0xac206e1c, 0x3c010001, 0xac226dd4, 0x8ee304b8,
-0x24020008, 0x10620005, 0x24020001, 0xc004239,
-0x0, 0x1000000b, 0x0, 0x3c030001,
-0x8c636d98, 0x10620007, 0x2402000e, 0x3c030002,
-0x8c638f90, 0x10620003, 0x0, 0xc004e9c,
-0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffe0, 0x3c03fdff, 0x3c040001, 0x8c846d98,
-0x3c020001, 0x8c426dc0, 0x3463ffff, 0x283a024,
-0x14820006, 0xafbf0018, 0x8ee304b8, 0x3c020001,
-0x8c426dc4, 0x10620006, 0x0, 0x8ee204b8,
-0x3c010001, 0xac246dc0, 0x3c010001, 0xac226dc4,
-0x3c030001, 0x8c636d98, 0x24020002, 0x1062019c,
-0x2c620003, 0x10400005, 0x24020001, 0x1062000a,
-0x0, 0x10000226, 0x0, 0x24020004,
-0x106200b6, 0x24020008, 0x1062010a, 0x24020001,
-0x1000021f, 0x0, 0x8ee204b8, 0x2443ffff,
-0x2c620008, 0x1040021c, 0x31080, 0x3c010001,
-0x220821, 0x8c226af8, 0x400008, 0x0,
-0x3c030001, 0x8c636f40, 0x24020005, 0x14620010,
-0x0, 0x3c020001, 0x8c426da4, 0x10400008,
-0x24020003, 0xc004482, 0x0, 0x24020002,
-0xaee204b8, 0x3c010001, 0x10000002, 0xac206da4,
-0xaee204b8, 0x3c010001, 0x10000203, 0xac206d30,
-0xc004482, 0x0, 0x3c020001, 0x8c426da4,
-0x3c010001, 0xac206d30, 0x1440017a, 0x24020002,
-0x1000019d, 0x24020007, 0x3c030001, 0x8c636f40,
-0x24020005, 0x14620003, 0x24020001, 0x3c010001,
-0xac226dd0, 0xc0045ff, 0x0, 0x3c030001,
-0x8c636dd0, 0x10000174, 0x24020011, 0x3c050001,
-0x8ca56d98, 0x3c060002, 0x8cc68ffc, 0xc005104,
-0x2021, 0x24020005, 0x3c010001, 0xac206da4,
-0x100001e1, 0xaee204b8, 0x3c040001, 0x24846aec,
-0x3c05000f, 0x34a50100, 0x3021, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x100001d6,
-0x0, 0x8f820220, 0x3c030004, 0x431024,
-0x14400175, 0x24020007, 0x8f830054, 0x3c020001,
-0x8c426f28, 0x2463d8f0, 0x431023, 0x2c422710,
-0x14400003, 0x24020001, 0x3c010001, 0xac226d9c,
-0x3c020002, 0x8c428ffc, 0x30425000, 0x104001c2,
-0x0, 0x8f820220, 0x30428000, 0x1040017d,
-0x0, 0x10000175, 0x0, 0x3c050001,
-0x8ca56d98, 0xc00529b, 0x2021, 0xc00551b,
-0x2021, 0x3c030002, 0x8c638ff4, 0x46101b0,
-0x24020001, 0x3c020008, 0x621024, 0x10400006,
-0x0, 0x8f820214, 0x3c03ffff, 0x431024,
-0x10000005, 0x3442251f, 0x8f820214, 0x3c03ffff,
-0x431024, 0x3442241f, 0xaf820214, 0x8f820220,
-0x3c030200, 0x34420002, 0xaf820220, 0x24020008,
-0xaee204b8, 0x8f820220, 0x283a025, 0x3c030004,
-0x431024, 0x14400016, 0x0, 0x3c020002,
-0x8c428ffc, 0x30425000, 0x1040000d, 0x0,
-0x8f820220, 0x30428000, 0x10400006, 0x0,
-0x8f820220, 0x3c03ffff, 0x34637fff, 0x10000003,
-0x431024, 0x8f820220, 0x34428000, 0xaf820220,
-0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
-0x3c030001, 0x8c636f40, 0x24020005, 0x1462000a,
-0x0, 0x3c020001, 0x94426f26, 0x24429fbc,
-0x2c420004, 0x10400004, 0x24040018, 0x24050002,
-0xc004ddb, 0x24060020, 0xc003e6d, 0x0,
-0x3c010001, 0x10000170, 0xac206e20, 0x8ee204b8,
-0x2443ffff, 0x2c620008, 0x1040016b, 0x31080,
-0x3c010001, 0x220821, 0x8c226b18, 0x400008,
-0x0, 0xc004547, 0x0, 0x3c030001,
-0x8c636db4, 0x100000e8, 0x24020009, 0x3c020002,
-0x8c428ff8, 0x30424000, 0x10400004, 0x0,
-0x8f820044, 0x10000006, 0x3442f080, 0x8f820044,
-0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080,
-0xaf820044, 0x8f830054, 0x100000ea, 0x24020004,
-0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0,
-0x431023, 0x2c422710, 0x14400147, 0x24020005,
-0x100000d8, 0x0, 0x8f820220, 0x3c03f700,
-0x431025, 0xaf820220, 0xaf800204, 0x3c010002,
-0x100000d6, 0xac208fe0, 0x8f830054, 0x3c020001,
-0x8c426f28, 0x2463fff6, 0x431023, 0x2c42000a,
-0x14400135, 0x24020007, 0x100000d7, 0x0,
-0xc003f50, 0x0, 0x1040012d, 0x24020001,
-0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c846f1c,
-0x431024, 0x3442251f, 0xaf820214, 0x24020008,
-0x10800005, 0xaee204b8, 0x3c020001, 0x8c426e44,
-0x10400064, 0x24020001, 0x8f820220, 0x3c030008,
-0x431024, 0x1040006a, 0x3c020200, 0x10000078,
-0x0, 0x8ee204b8, 0x2443ffff, 0x2c620007,
-0x10400115, 0x31080, 0x3c010001, 0x220821,
-0x8c226b38, 0x400008, 0x0, 0xc003daf,
-0x0, 0x3c010001, 0xac206d9c, 0xaf800204,
-0x3c010002, 0xc004482, 0xac208fe0, 0x24020001,
-0x3c010001, 0xac226db4, 0x24020002, 0x10000102,
-0xaee204b8, 0xc004547, 0x0, 0x3c030001,
-0x8c636db4, 0x10000084, 0x24020009, 0x3c020002,
-0x8c428ff8, 0x30424000, 0x10400003, 0x3c0200c8,
-0x10000002, 0x344201f6, 0x344201fe, 0xaf820238,
-0x8f830054, 0x1000008b, 0x24020004, 0x8f830054,
-0x3c020001, 0x8c426f28, 0x2463d8f0, 0x431023,
-0x2c422710, 0x144000e8, 0x24020005, 0x10000079,
-0x0, 0x8f820220, 0x3c03f700, 0x431025,
-0xaf820220, 0xaf800204, 0x3c010002, 0x10000077,
-0xac208fe0, 0x8f830054, 0x3c020001, 0x8c426f28,
-0x2463fff6, 0x431023, 0x2c42000a, 0x144000d6,
-0x24020007, 0x10000078, 0x0, 0xc003f50,
-0x0, 0x104000ce, 0x24020001, 0x8f820214,
-0x3c03ffff, 0x3c040001, 0x8c846f1c, 0x431024,
-0x3442251f, 0xaf820214, 0x24020008, 0x1080000f,
-0xaee204b8, 0x3c020001, 0x8c426e44, 0x1440000b,
-0x0, 0x8f820220, 0x34420002, 0xaf820220,
-0x24020001, 0x3c010002, 0xac228f90, 0xc004e9c,
-0x8f840220, 0x10000016, 0x0, 0x8f820220,
-0x3c030008, 0x431024, 0x14400011, 0x3c020200,
-0x282a025, 0x2402000e, 0x3c010002, 0xac228f90,
-0xc00551b, 0x2021, 0x8f820220, 0x34420002,
-0xc003e6d, 0xaf820220, 0x3c050001, 0x8ca56d98,
-0xc00529b, 0x2021, 0x100000a3, 0x0,
-0x3c020001, 0x8c426e44, 0x1040009f, 0x0,
-0x3c020001, 0x8c426e40, 0x2442ffff, 0x3c010001,
-0xac226e40, 0x14400098, 0x24020002, 0x3c010001,
-0xac206e44, 0x3c010001, 0x10000093, 0xac226e40,
-0x8ee204b8, 0x2443ffff, 0x2c620007, 0x1040008e,
-0x31080, 0x3c010001, 0x220821, 0x8c226b58,
-0x400008, 0x0, 0x3c020001, 0x8c426da4,
-0x10400018, 0x24020005, 0xc004482, 0x0,
-0x24020002, 0xaee204b8, 0x3c010001, 0x1000007e,
-0xac206da4, 0xc004963, 0x0, 0x3c030001,
-0x8c636dd4, 0x24020006, 0x14620077, 0x24020003,
-0x10000075, 0xaee204b8, 0x3c050001, 0x8ca56d98,
-0x3c060002, 0x8cc68ff8, 0xc005104, 0x2021,
-0x24020005, 0x1000006c, 0xaee204b8, 0x8f820220,
-0x3c03f700, 0x431025, 0xaf820220, 0x8f830054,
-0x24020006, 0xaee204b8, 0x3c010001, 0x10000062,
-0xac236f28, 0x8f820220, 0x3c030004, 0x431024,
-0x10400003, 0x24020007, 0x1000005b, 0xaee204b8,
-0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0,
-0x431023, 0x2c422710, 0x14400003, 0x24020001,
-0x3c010001, 0xac226d9c, 0x3c020002, 0x8c428ff8,
-0x30425000, 0x1040004c, 0x0, 0x8f820220,
-0x30428000, 0x10400007, 0x0, 0x8f820220,
-0x3c03ffff, 0x34637fff, 0x431024, 0x10000042,
-0xaf820220, 0x8f820220, 0x34428000, 0x1000003e,
-0xaf820220, 0x3c050001, 0x8ca56d98, 0xc00529b,
-0x2021, 0xc00551b, 0x2021, 0x3c020002,
-0x8c428ff0, 0x4410032, 0x24020001, 0x8f820214,
-0x3c03ffff, 0x431024, 0x3442251f, 0xaf820214,
-0x24020008, 0xaee204b8, 0x8f820220, 0x34420002,
-0xaf820220, 0x8f820220, 0x3c030004, 0x431024,
-0x14400016, 0x0, 0x3c020002, 0x8c428ff8,
-0x30425000, 0x1040000d, 0x0, 0x8f820220,
-0x30428000, 0x10400006, 0x0, 0x8f820220,
-0x3c03ffff, 0x34637fff, 0x10000003, 0x431024,
-0x8f820220, 0x34428000, 0xaf820220, 0x8f820220,
-0x3c03f700, 0x431025, 0xaf820220, 0x3c020001,
-0x94426f26, 0x24429fbc, 0x2c420004, 0x10400004,
-0x24040018, 0x24050002, 0xc004ddb, 0x24060020,
-0xc003e6d, 0x0, 0x10000003, 0x0,
-0x3c010001, 0xac226d9c, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220,
-0x34420004, 0xaf820220, 0x8f820200, 0x3c050001,
-0x8ca56d98, 0x34420004, 0xaf820200, 0x24020002,
-0x10a2004b, 0x2ca20003, 0x10400005, 0x24020001,
-0x10a2000a, 0x0, 0x100000b1, 0x0,
-0x24020004, 0x10a20072, 0x24020008, 0x10a20085,
-0x3c02f0ff, 0x100000aa, 0x0, 0x8f830050,
-0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c846f40,
-0x621824, 0x3c020700, 0x621825, 0x24020e00,
-0x2484fffb, 0x2c840002, 0xaf830050, 0xaf850200,
-0xaf850220, 0x14800006, 0xaf820238, 0x8f820044,
-0x3c03ffff, 0x34633f7f, 0x431024, 0xaf820044,
-0x3c030001, 0x8c636f40, 0x24020005, 0x14620004,
-0x0, 0x8f820044, 0x34425000, 0xaf820044,
-0x3c020001, 0x8c426d88, 0x3c030001, 0x8c636f40,
-0x34420022, 0x2463fffc, 0x2c630002, 0x1460000c,
-0xaf820200, 0x3c020001, 0x8c426dac, 0x3c030001,
-0x8c636d90, 0x3c040001, 0x8c846d8c, 0x34428000,
-0x621825, 0x641825, 0x1000000a, 0x34620002,
-0x3c020001, 0x8c426d90, 0x3c030001, 0x8c636dac,
-0x3c040001, 0x8c846d8c, 0x431025, 0x441025,
-0x34420002, 0xaf820220, 0x1000002f, 0x24020001,
-0x24020e01, 0xaf820238, 0x8f830050, 0x3c02f0ff,
-0x3442ffff, 0x3c040001, 0x8c846f1c, 0x621824,
-0x3c020d00, 0x621825, 0x24020001, 0xaf830050,
-0xaf820200, 0xaf820220, 0x10800005, 0x3c033f00,
-0x3c020001, 0x8c426d80, 0x10000004, 0x34630070,
-0x3c020001, 0x8c426d80, 0x34630072, 0x431025,
-0xaf820200, 0x3c030001, 0x8c636d84, 0x3c02f700,
-0x621825, 0x3c020001, 0x8c426d90, 0x3c040001,
-0x8c846dac, 0x3c050001, 0x8ca56f40, 0x431025,
-0x441025, 0xaf820220, 0x24020005, 0x14a20006,
-0x24020001, 0x8f820044, 0x2403afff, 0x431024,
-0xaf820044, 0x24020001, 0x1000003d, 0xaf820238,
-0x8f830050, 0x3c02f0ff, 0x3442ffff, 0x3c040001,
-0x8c846f1c, 0x621824, 0x3c020a00, 0x621825,
-0x24020001, 0xaf830050, 0xaf820200, 0x1080001e,
-0xaf820220, 0x3c020001, 0x8c426e44, 0x1440001a,
-0x3c033f00, 0x3c020001, 0x8c426d80, 0x1000001a,
-0x346300e0, 0x8f830050, 0x3c040001, 0x8c846f1c,
-0x3442ffff, 0x621824, 0x1080000f, 0xaf830050,
-0x3c020001, 0x8c426e44, 0x1440000b, 0x3c043f00,
-0x3c030001, 0x8c636d80, 0x348400e0, 0x24020001,
-0xaf820200, 0xaf820220, 0x641825, 0xaf830200,
-0x10000008, 0x3c05f700, 0x3c020001, 0x8c426d80,
-0x3c033f00, 0x346300e2, 0x431025, 0xaf820200,
-0x3c05f700, 0x34a58000, 0x3c030001, 0x8c636d84,
-0x3c020001, 0x8c426d90, 0x3c040001, 0x8c846dac,
-0x651825, 0x431025, 0x441025, 0xaf820220,
-0x3e00008, 0x0, 0x3c030001, 0x8c636db4,
-0x3c020001, 0x8c426db8, 0x10620003, 0x24020002,
-0x3c010001, 0xac236db8, 0x1062001d, 0x2c620003,
-0x10400025, 0x24020001, 0x14620023, 0x24020004,
-0x3c030001, 0x8c636d98, 0x10620006, 0x24020008,
-0x1462000c, 0x3c0200c8, 0x344201fb, 0x10000009,
-0xaf820238, 0x24020e01, 0xaf820238, 0x8f820044,
-0x3c03ffff, 0x34633f7f, 0x431024, 0x34420080,
-0xaf820044, 0x8f830054, 0x24020002, 0x3c010001,
-0xac226db4, 0x3c010001, 0x1000000b, 0xac236f2c,
-0x8f830054, 0x3c020001, 0x8c426f2c, 0x2463d8f0,
-0x431023, 0x2c422710, 0x14400003, 0x24020009,
-0x3c010001, 0xac226db4, 0x3e00008, 0x0,
-0x0, 0x0, 0x0, 0x27bdffd8,
-0xafb20018, 0x809021, 0xafb3001c, 0xa09821,
-0xafb10014, 0xc08821, 0xafb00010, 0x8021,
-0xafbf0020, 0xa6200000, 0xc004d78, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x24100010, 0x2501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x2501024, 0x24100010, 0x2701024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x2701024, 0xc004db9, 0x34108000,
-0xc004db9, 0x0, 0xc004d58, 0x0,
-0x50400005, 0x108042, 0x96220000, 0x501025,
-0xa6220000, 0x108042, 0x1600fff7, 0x0,
-0xc004db9, 0x0, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821,
-0xafb20018, 0xa09021, 0xafb3001c, 0xc09821,
-0xafb00010, 0x8021, 0xafbf0020, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0x24100010, 0x2301024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x2301024, 0x24100010, 0x2501024,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x2501024, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x34108000,
-0x96620000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
-0x0, 0xc004db9, 0x0, 0x8fbf0020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0028, 0x3c040001, 0x8c846dd0,
-0x3c020001, 0x8c426e18, 0x27bdffd8, 0xafbf0020,
-0xafb1001c, 0x10820003, 0xafb00018, 0x3c010001,
-0xac246e18, 0x3c030001, 0x8c636f40, 0x24020005,
-0x14620005, 0x2483ffff, 0xc004963, 0x0,
-0x1000034c, 0x0, 0x2c620013, 0x10400349,
-0x31080, 0x3c010001, 0x220821, 0x8c226b80,
-0x400008, 0x0, 0xc004db9, 0x8021,
-0x34028000, 0xa7a20010, 0x27b10010, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0xc004d78,
-0x2021, 0x108042, 0x1600fffc, 0x0,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x1000030e, 0x24020002, 0x27b10010, 0xa7a00010,
-0x8021, 0xc004d78, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
-0x2021, 0xc004d78, 0x24040001, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x24100010,
-0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020001,
-0x24100010, 0xc004d78, 0x2021, 0x108042,
-0x1600fffc, 0x0, 0xc004db9, 0x34108000,
-0xc004db9, 0x0, 0xc004d58, 0x0,
-0x50400005, 0x108042, 0x96220000, 0x501025,
-0xa6220000, 0x108042, 0x1600fff7, 0x0,
-0xc004db9, 0x0, 0x97a20010, 0x30428000,
-0x144002dc, 0x24020003, 0x100002d8, 0x0,
-0x24021200, 0xa7a20010, 0x27b10010, 0x8021,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0xc004d78, 0x2021, 0x108042, 0x1600fffc,
-0x0, 0xc004d78, 0x24040001, 0xc004d78,
-0x2021, 0x34108000, 0x96220000, 0x501024,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fff8, 0x0, 0xc004db9,
-0x0, 0x8f830054, 0x10000296, 0x24020004,
-0x8f830054, 0x3c020001, 0x8c426f3c, 0x2463ff9c,
-0x431023, 0x2c420064, 0x1440029e, 0x24020002,
-0x3c030001, 0x8c636f40, 0x10620297, 0x2c620003,
-0x14400296, 0x24020011, 0x24020003, 0x10620005,
-0x24020004, 0x10620291, 0x2402000f, 0x1000028f,
-0x24020011, 0x1000028d, 0x24020005, 0x24020014,
-0xa7a20010, 0x27b10010, 0x8021, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x32020012,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020012, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x34108000,
-0x96220000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
-0x0, 0xc004db9, 0x0, 0x8f830054,
-0x10000248, 0x24020006, 0x8f830054, 0x3c020001,
-0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064,
-0x14400250, 0x24020007, 0x1000024c, 0x0,
-0x24020006, 0xa7a20010, 0x27b10010, 0x8021,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020013, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020013,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x8f830054, 0x10000207, 0x24020008, 0x8f830054,
-0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
-0x2c420064, 0x1440020f, 0x24020009, 0x1000020b,
-0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x8021,
-0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x8f830054, 0x10000193, 0x2402000a, 0x8f830054,
-0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
-0x2c420064, 0x1440019b, 0x2402000b, 0x10000197,
-0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020017, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020017,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x8021,
-0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020017, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020017,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x8f830054, 0x1000011f, 0x2402000c, 0x8f830054,
-0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
-0x2c420064, 0x14400127, 0x24020012, 0x10000123,
-0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020014, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020014,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x8021,
-0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020014, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020014,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x8f830054, 0x100000ab, 0x24020013, 0x8f830054,
-0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
-0x2c420064, 0x144000b3, 0x2402000d, 0x100000af,
-0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x8021,
-0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x8f830054, 0x10000037, 0x2402000e, 0x24020840,
-0xa7a20010, 0x27b10010, 0x8021, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x32020013,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020013, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x34108000,
-0x96220000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
-0x0, 0xc004db9, 0x0, 0x8f830054,
-0x24020010, 0x3c010001, 0xac226dd0, 0x3c010001,
-0x1000000c, 0xac236f3c, 0x8f830054, 0x3c020001,
-0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064,
-0x14400004, 0x0, 0x24020011, 0x3c010001,
-0xac226dd0, 0x8fbf0020, 0x8fb1001c, 0x8fb00018,
-0x3e00008, 0x27bd0028, 0x3c030001, 0x8c636d98,
-0x27bdffc8, 0x24020002, 0xafbf0034, 0xafb20030,
-0xafb1002c, 0x14620004, 0xafb00028, 0x3c120002,
-0x10000003, 0x8e528ff8, 0x3c120002, 0x8e528ffc,
-0x3c030001, 0x8c636dd4, 0x3c020001, 0x8c426e1c,
-0x50620004, 0x2463ffff, 0x3c010001, 0xac236e1c,
-0x2463ffff, 0x2c620006, 0x10400377, 0x31080,
-0x3c010001, 0x220821, 0x8c226bd8, 0x400008,
-0x0, 0x2021, 0x2821, 0xc004ddb,
-0x34068000, 0x24040010, 0x24050002, 0x24060002,
-0x24020002, 0xc004ddb, 0xa7a20018, 0x24020002,
-0x3c010001, 0x10000364, 0xac226dd4, 0x27b10018,
-0xa7a00018, 0x8021, 0xc004d78, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x24100010, 0x32020001, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x32020001, 0x24100010, 0xc004d78, 0x2021,
-0x108042, 0x1600fffc, 0x0, 0xc004db9,
-0x34108000, 0xc004db9, 0x0, 0xc004d58,
-0x0, 0x50400005, 0x108042, 0x96220000,
-0x501025, 0xa6220000, 0x108042, 0x1600fff7,
-0x0, 0xc004db9, 0x0, 0x97a20018,
-0x30428000, 0x14400004, 0x24020003, 0x3c010001,
-0xac226dd4, 0x24020003, 0x3c010001, 0x1000032a,
-0xac226dd4, 0x24040010, 0x24050002, 0x24060002,
-0x24020002, 0xc004ddb, 0xa7a20018, 0x3c030001,
-0x8c636e20, 0x24020001, 0x146201e1, 0x8021,
-0x27b10018, 0xa7a00018, 0xc004d78, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x24100010, 0x32020001, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x32020001, 0x24100010, 0x32020018, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020018, 0xc004db9, 0x34108000,
-0xc004db9, 0x0, 0xc004d58, 0x0,
-0x50400005, 0x108042, 0x96220000, 0x501025,
-0xa6220000, 0x108042, 0x1600fff7, 0x0,
-0xc004db9, 0x8021, 0x27b10018, 0xa7a00018,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x8021,
-0x24040018, 0x2821, 0xc004ddb, 0x24060404,
-0xa7a0001a, 0xc004d78, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
-0x2021, 0xc004d78, 0x24040001, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x24100010,
-0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020001,
-0x24100010, 0x32020018, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x32020018, 0xc004db9, 0x34108000, 0xc004db9,
-0x0, 0xc004d58, 0x0, 0x50400005,
-0x108042, 0x97a2001a, 0x501025, 0xa7a2001a,
-0x108042, 0x1600fff7, 0x0, 0xc004db9,
-0x8021, 0xa7a0001a, 0xc004d78, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x24100010, 0x32020001, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x32020001, 0x24100010, 0x32020018, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020018, 0xc004db9, 0x34108000,
-0xc004db9, 0x0, 0xc004d58, 0x0,
-0x50400005, 0x108042, 0x97a2001a, 0x501025,
-0xa7a2001a, 0x108042, 0x1600fff7, 0x0,
-0xc004db9, 0x8021, 0xa7a0001c, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x24040001, 0xc004d78,
-0x2021, 0x24100010, 0xc004d78, 0x2021,
-0x108042, 0x1600fffc, 0x0, 0x24100010,
-0x3202001e, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x3202001e,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x97a2001c, 0x501025, 0xa7a2001c, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x8021,
-0xa7a0001c, 0xc004d78, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
-0x2021, 0xc004d78, 0x24040001, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x24100010,
-0xc004d78, 0x2021, 0x108042, 0x1600fffc,
-0x0, 0x24100010, 0x3202001e, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x3202001e, 0xc004db9, 0x34108000,
-0xc004db9, 0x0, 0xc004d58, 0x0,
-0x50400005, 0x108042, 0x97a2001c, 0x501025,
-0xa7a2001c, 0x108042, 0x1600fff7, 0x0,
-0xc004db9, 0x8021, 0x24020002, 0xa7a2001e,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0xc004d78,
-0x2021, 0x108042, 0x1600fffc, 0x0,
-0x24100010, 0x3202001e, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x3202001e, 0xc004d78, 0x24040001, 0xc004d78,
-0x2021, 0x34108000, 0x97a2001e, 0x501024,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fff8, 0x0, 0xc004db9,
-0x8021, 0xa7a00020, 0xc004d78, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x24100010, 0xc004d78, 0x2021, 0x108042,
-0x1600fffc, 0x0, 0x24100010, 0x3202001e,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x3202001e, 0xc004db9,
-0x34108000, 0xc004db9, 0x0, 0xc004d58,
-0x0, 0x50400005, 0x108042, 0x97a20020,
-0x501025, 0xa7a20020, 0x108042, 0x1600fff7,
-0x0, 0xc004db9, 0x8021, 0xa7a00020,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0x24100010, 0xc004d78,
-0x2021, 0x108042, 0x1600fffc, 0x0,
-0x24100010, 0x3202001e, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x3202001e, 0xc004db9, 0x34108000, 0xc004db9,
-0x0, 0xc004d58, 0x0, 0x50400005,
-0x108042, 0x97a20020, 0x501025, 0xa7a20020,
-0x108042, 0x1600fff7, 0x0, 0xc004db9,
-0x8021, 0xa7a00022, 0xc004d78, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0x24100010, 0xc004d78, 0x2021, 0x108042,
-0x1600fffc, 0x0, 0x24100010, 0xc004d78,
-0x2021, 0x108042, 0x1600fffc, 0x0,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x97a20022, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x24040018, 0x24050002, 0xc004ddb, 0x24060004,
-0x3c100001, 0x8e106e24, 0x24020001, 0x1602011d,
-0x0, 0x3c020001, 0x94426f26, 0x3c010001,
-0xac206e24, 0x24429fbc, 0x2c420004, 0x1040000c,
-0x24040009, 0x24050001, 0xc004ddb, 0x24060400,
-0x24040018, 0x24050001, 0xc004ddb, 0x24060020,
-0x24040018, 0x24050001, 0xc004ddb, 0x24062000,
-0x3c024000, 0x2421024, 0x10400123, 0x3c022000,
-0x2421024, 0x10400004, 0x0, 0x3c010001,
-0x10000003, 0xac306f1c, 0x3c010001, 0xac206f1c,
-0x3c030001, 0x8c636f34, 0x24020005, 0x146200f9,
-0x0, 0x3c020001, 0x8c426f1c, 0x10400067,
-0x3c020004, 0x2421024, 0x10400011, 0xa7a00018,
-0x3c020008, 0x2421024, 0x10400002, 0x24020200,
-0xa7a20018, 0x3c020010, 0x2421024, 0x10400004,
-0x0, 0x97a20018, 0x34420100, 0xa7a20018,
-0x97a60018, 0x24040009, 0x10000004, 0x2821,
-0x24040009, 0x2821, 0x3021, 0xc004ddb,
-0x0, 0x24020001, 0xa7a2001a, 0x3c020008,
-0x2421024, 0x1040000c, 0x3c020002, 0x2421024,
-0x10400002, 0x24020101, 0xa7a2001a, 0x3c020001,
-0x2421024, 0x10400005, 0x3c020010, 0x97a2001a,
-0x34420040, 0xa7a2001a, 0x3c020010, 0x2421024,
-0x1040000e, 0x3c020002, 0x2421024, 0x10400005,
-0x3c020001, 0x97a2001a, 0x34420080, 0xa7a2001a,
-0x3c020001, 0x2421024, 0x10400005, 0x3c0300a0,
-0x97a2001a, 0x34420020, 0xa7a2001a, 0x3c0300a0,
-0x2431024, 0x54430004, 0x3c020020, 0x97a2001a,
-0x1000000c, 0x34420400, 0x2421024, 0x50400004,
-0x3c020080, 0x97a2001a, 0x10000006, 0x34420800,
-0x2421024, 0x10400004, 0x0, 0x97a2001a,
-0x34420c00, 0xa7a2001a, 0x97a6001a, 0x24040004,
-0xc004ddb, 0x2821, 0x3c020004, 0x2421024,
-0x10400004, 0xa7a0001c, 0x32425000, 0x14400004,
-0x0, 0x32424000, 0x10400005, 0x2021,
-0xc004cf9, 0x2402021, 0x10000096, 0x0,
-0x97a6001c, 0x2821, 0x34c61200, 0xc004ddb,
-0xa7a6001c, 0x1000008f, 0x0, 0x2421024,
-0x10400004, 0xa7a00018, 0x32425000, 0x14400004,
-0x0, 0x32424000, 0x10400005, 0x3c020010,
-0xc004cf9, 0x2402021, 0x10000019, 0xa7a0001a,
-0x2421024, 0x10400004, 0x0, 0x97a20018,
-0x10000004, 0xa7a20018, 0x97a20018, 0x34420100,
-0xa7a20018, 0x3c020001, 0x2421024, 0x10400004,
-0x0, 0x97a20018, 0x10000004, 0xa7a20018,
-0x97a20018, 0x34422000, 0xa7a20018, 0x97a60018,
-0x2021, 0xc004ddb, 0x2821, 0xa7a0001a,
-0x8021, 0xc004d78, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
-0x2021, 0xc004d78, 0x24040001, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x24100010,
-0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020001,
-0x24100010, 0xc004d78, 0x2021, 0x108042,
-0x1600fffc, 0x0, 0xc004db9, 0x34108000,
-0xc004db9, 0x0, 0xc004d58, 0x0,
-0x50400005, 0x108042, 0x97a2001a, 0x501025,
-0xa7a2001a, 0x108042, 0x1600fff7, 0x0,
-0xc004db9, 0x8021, 0xa7a0001a, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x24040001, 0xc004d78,
-0x2021, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0xc004d78,
-0x2021, 0x108042, 0x1600fffc, 0x0,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x97a2001a, 0x501025, 0xa7a2001a, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x0,
-0x3c040001, 0x24846bcc, 0x97a60018, 0x97a7001a,
-0x3c020001, 0x8c426d98, 0x3c030001, 0x8c636f1c,
-0x3c05000d, 0x34a50205, 0xafa20010, 0xc002b3b,
-0xafa30014, 0x8f830054, 0x24020004, 0x3c010001,
-0xac226dd4, 0x3c010001, 0x10000017, 0xac236f38,
-0x8f830054, 0x3c020001, 0x8c426f38, 0x2463ff9c,
-0x431023, 0x2c420064, 0x1440000f, 0x0,
-0x8f820220, 0x24030005, 0x3c010001, 0xac236dd4,
-0x3c03f700, 0x431025, 0x10000007, 0xaf820220,
-0x24020006, 0x3c010001, 0xac226dd4, 0x24020011,
-0x3c010001, 0xac226dd0, 0x8fbf0034, 0x8fb20030,
-0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0038,
-0x27bdffd8, 0xafb00018, 0x808021, 0xafb1001c,
-0x8821, 0x32024000, 0x10400013, 0xafbf0020,
-0x3c020010, 0x2021024, 0x2c420001, 0x21023,
-0x30434100, 0x3c020001, 0x2021024, 0x14400006,
-0x34714000, 0x3c020002, 0x2021024, 0x14400002,
-0x34716000, 0x34714040, 0x2021, 0x2821,
-0x10000036, 0x2203021, 0x32021000, 0x10400035,
-0x2021, 0x2821, 0xc004ddb, 0x24060040,
-0x24040018, 0x2821, 0xc004ddb, 0x24060c00,
-0x24040017, 0x2821, 0xc004ddb, 0x24060400,
-0x24040016, 0x2821, 0xc004ddb, 0x24060006,
-0x24040017, 0x2821, 0xc004ddb, 0x24062500,
-0x24040016, 0x2821, 0xc004ddb, 0x24060006,
-0x24040017, 0x2821, 0xc004ddb, 0x24064600,
-0x24040016, 0x2821, 0xc004ddb, 0x24060006,
-0x24040017, 0x2821, 0xc004ddb, 0x24066700,
-0x24040016, 0x2821, 0xc004ddb, 0x24060006,
-0x2404001f, 0x2821, 0xc004ddb, 0x24060010,
-0x24040009, 0x2821, 0xc004ddb, 0x24061500,
-0x24040009, 0x2821, 0x24061d00, 0xc004ddb,
-0x0, 0x3c040001, 0x24846bf0, 0x3c05000e,
-0x34a50100, 0x2003021, 0x2203821, 0xafa00010,
-0xc002b3b, 0xafa00014, 0x8fbf0020, 0x8fb1001c,
-0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044,
-0x8f820044, 0x3c030001, 0x431025, 0x3c030008,
-0xaf820044, 0x8f840054, 0x8f820054, 0xa32824,
-0x10000002, 0x24840001, 0x8f820054, 0x821023,
-0x2c420002, 0x1440fffc, 0x0, 0x8f820044,
-0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
-0x0, 0x3e00008, 0xa01021, 0x8f830044,
-0x3c02fff0, 0x3442ffff, 0x42480, 0x621824,
-0x3c020002, 0x822025, 0x641825, 0xaf830044,
-0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024,
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820044, 0x3c030001,
-0x431025, 0xaf820044, 0x8f830054, 0x8f820054,
-0x10000002, 0x24630001, 0x8f820054, 0x621023,
-0x2c420002, 0x1440fffc, 0x0, 0x3e00008,
-0x0, 0x8f820044, 0x2403ff7f, 0x431024,
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820044, 0x34420080,
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x3e00008, 0x0,
-0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024,
-0xaf820044, 0x8f820044, 0x3c030001, 0x431025,
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe,
-0x3463ffff, 0x431024, 0xaf820044, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x3e00008, 0x0, 0x27bdffc8, 0xafb30024,
-0x809821, 0xafbe002c, 0xa0f021, 0xafb20020,
-0xc09021, 0x33c2ffff, 0xafbf0030, 0xafb50028,
-0xafb1001c, 0xafb00018, 0x14400034, 0xa7b20010,
-0x3271ffff, 0x27b20010, 0x8021, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x2301024,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x2301024, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x34108000,
-0x96420000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x12000075,
-0x0, 0x1000fff6, 0x0, 0x3275ffff,
-0x27b10010, 0xa7a00010, 0x8021, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x24040001, 0xc004d78,
-0x2021, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x2b01024,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x2b01024, 0xc004db9,
-0x34108000, 0xc004db9, 0x0, 0xc004d58,
-0x0, 0x50400005, 0x108042, 0x96220000,
-0x501025, 0xa6220000, 0x108042, 0x1600fff7,
-0x0, 0xc004db9, 0x0, 0x33c5ffff,
-0x24020001, 0x54a20004, 0x24020002, 0x97a20010,
-0x10000006, 0x521025, 0x14a20006, 0x3271ffff,
-0x97a20010, 0x121827, 0x431024, 0xa7a20010,
-0x3271ffff, 0x27b20010, 0x8021, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x2301024,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x2301024, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x34108000,
-0x96420000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
-0x0, 0xc004db9, 0x0, 0x8fbf0030,
-0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb20020,
-0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038,
-0x0, 0x0, 0x0, 0x27bdffe8,
-0xafbf0010, 0x8ee304b8, 0x24020008, 0x146201e0,
-0x0, 0x3c020001, 0x8c426f1c, 0x14400005,
-0x0, 0xc003daf, 0x8f840224, 0x100001d8,
-0x0, 0x8f820220, 0x3c030008, 0x431024,
-0x10400026, 0x24020001, 0x8f840224, 0x8f820220,
-0x3c030400, 0x431024, 0x10400006, 0x0,
-0x3c010002, 0xac208fa0, 0x3c010002, 0x1000000b,
-0xac208fc0, 0x3c030002, 0x24638fa0, 0x8c620000,
-0x24420001, 0xac620000, 0x2c420002, 0x14400003,
-0x24020001, 0x3c010002, 0xac228fc0, 0x3c020002,
-0x8c428fc0, 0x10400006, 0x30820040, 0x10400004,
-0x24020001, 0x3c010002, 0x10000003, 0xac228fc4,
-0x3c010002, 0xac208fc4, 0x3c010002, 0xac248f9c,
-0x3c010002, 0x1000000b, 0xac208fd0, 0x3c010002,
-0xac228fd0, 0x3c010002, 0xac208fc0, 0x3c010002,
-0xac208fa0, 0x3c010002, 0xac208fc4, 0x3c010002,
-0xac208f9c, 0x3c030002, 0x8c638f90, 0x3c020002,
-0x8c428f94, 0x50620004, 0x2463ffff, 0x3c010002,
-0xac238f94, 0x2463ffff, 0x2c62000e, 0x10400194,
-0x31080, 0x3c010001, 0x220821, 0x8c226c00,
-0x400008, 0x0, 0x24020002, 0x3c010002,
-0xac208fc0, 0x3c010002, 0xac208fa0, 0x3c010002,
-0xac208f9c, 0x3c010002, 0xac208fc4, 0x3c010002,
-0xac208fb8, 0x3c010002, 0xac208fb0, 0xaf800224,
-0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fd0,
-0x1440004f, 0x3c02fdff, 0x3442ffff, 0xc003daf,
-0x282a024, 0xaf800204, 0x8f820200, 0x2403fffd,
-0x431024, 0xaf820200, 0x3c010002, 0xac208fe0,
-0x8f830054, 0x3c020002, 0x8c428fb8, 0x24040001,
-0x3c010002, 0xac248fcc, 0x24420001, 0x3c010002,
-0xac228fb8, 0x2c420004, 0x3c010002, 0xac238fb4,
-0x14400006, 0x24020003, 0x3c010001, 0xac246d9c,
-0x3c010002, 0x1000015e, 0xac208fb8, 0x3c010002,
-0x1000015b, 0xac228f90, 0x8f830054, 0x3c020002,
-0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710,
-0x14400003, 0x24020004, 0x3c010002, 0xac228f90,
-0x3c020002, 0x8c428fd0, 0x14400021, 0x3c02fdff,
-0x3442ffff, 0x1000014a, 0x282a024, 0x3c040001,
-0x8c846f20, 0x3c010002, 0xc005084, 0xac208fa8,
-0x3c020002, 0x8c428fdc, 0xaf820204, 0x3c020002,
-0x8c428fd0, 0x14400012, 0x3c03fdff, 0x8f820204,
-0x3463ffff, 0x30420030, 0x1440012f, 0x283a024,
-0x3c030002, 0x8c638fdc, 0x24020005, 0x3c010002,
-0xac228f90, 0x3c010002, 0x10000131, 0xac238fe0,
-0x3c020002, 0x8c428fd0, 0x10400010, 0x3c02fdff,
-0x3c020001, 0x8c426e3c, 0x24420001, 0x3c010001,
-0xac226e3c, 0x2c420002, 0x14400125, 0x24020001,
-0x3c010001, 0xac226e44, 0x3c010001, 0xac206e3c,
-0x3c010001, 0x1000011e, 0xac226d9c, 0x3c030002,
-0x8c638fc0, 0x3442ffff, 0x10600119, 0x282a024,
-0x3c020002, 0x8c428f9c, 0x10400115, 0x0,
-0x3c010002, 0xac228fc8, 0x24020003, 0x3c010002,
-0xac228fa0, 0x100000b8, 0x24020006, 0x3c010002,
-0xac208fa8, 0x8f820204, 0x34420040, 0xaf820204,
-0x3c020002, 0x8c428fe0, 0x24030007, 0x3c010002,
-0xac238f90, 0x34420040, 0x3c010002, 0xac228fe0,
-0x3c020002, 0x8c428fc0, 0x10400005, 0x0,
-0x3c020002, 0x8c428f9c, 0x104000f0, 0x24020002,
-0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21,
-0x104000ea, 0x24020002, 0x3c020002, 0x8c428fc4,
-0x104000ef, 0x2404ffbf, 0x3c020002, 0x8c428f9c,
-0x3c030002, 0x8c638fc8, 0x441024, 0x641824,
-0x10430004, 0x24020001, 0x3c010002, 0x100000e4,
-0xac228f90, 0x24020003, 0xaca20000, 0x24020008,
-0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fcc,
-0x1040000c, 0x24020001, 0x3c040002, 0xc005091,
-0x8c848f9c, 0x3c020002, 0x8c428fe8, 0x14400005,
-0x24020001, 0x3c020002, 0x8c428fe4, 0x10400006,
-0x24020001, 0x3c010001, 0xac226d9c, 0x3c010002,
-0x100000cb, 0xac208fb8, 0x3c020002, 0x8c428fb0,
-0x3c030002, 0x8c638f9c, 0x2c420001, 0x210c0,
-0x30630008, 0x3c010002, 0xac228fb0, 0x3c010002,
-0xac238fac, 0x8f830054, 0x24020009, 0x3c010002,
-0xac228f90, 0x3c010002, 0x100000b9, 0xac238fb4,
-0x8f830054, 0x3c020002, 0x8c428fb4, 0x2463d8f0,
-0x431023, 0x2c422710, 0x1440009f, 0x0,
-0x3c020002, 0x8c428fc0, 0x10400005, 0x0,
-0x3c020002, 0x8c428f9c, 0x104000a0, 0x24020002,
-0x3c030002, 0x24638fa0, 0x8c620000, 0x2c424e21,
-0x1040009a, 0x24020002, 0x3c020002, 0x8c428fcc,
-0x1040000e, 0x0, 0x3c020002, 0x8c428f9c,
-0x3c010002, 0xac208fcc, 0x30420080, 0x1040002f,
-0x2402000c, 0x8f820204, 0x30420080, 0x1440000c,
-0x24020003, 0x10000029, 0x2402000c, 0x3c020002,
-0x8c428f9c, 0x30420080, 0x14400005, 0x24020003,
-0x8f820204, 0x30420080, 0x1040001f, 0x24020003,
-0xac620000, 0x2402000a, 0x3c010002, 0xac228f90,
-0x3c040002, 0x24848fd8, 0x8c820000, 0x3c030002,
-0x8c638fb0, 0x431025, 0xaf820204, 0x8c830000,
-0x3c040002, 0x8c848fb0, 0x2402000b, 0x3c010002,
-0xac228f90, 0x641825, 0x3c010002, 0xac238fe0,
-0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21,
-0x10400066, 0x24020002, 0x3c020002, 0x8c428fd0,
-0x10400005, 0x0, 0x2402000c, 0x3c010002,
-0x10000067, 0xac228f90, 0x3c020002, 0x8c428fc0,
-0x10400063, 0x0, 0x3c040002, 0x8c848f9c,
-0x10800055, 0x30820008, 0x3c030002, 0x8c638fac,
-0x1062005b, 0x24020003, 0x3c010002, 0xac248fc8,
-0xaca20000, 0x24020006, 0x3c010002, 0x10000054,
-0xac228f90, 0x8f820200, 0x34420002, 0xaf820200,
-0x8f830054, 0x2402000d, 0x3c010002, 0xac228f90,
-0x3c010002, 0xac238fb4, 0x8f830054, 0x3c020002,
-0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710,
-0x14400031, 0x0, 0x3c020002, 0x8c428fd0,
-0x10400020, 0x2402000e, 0x3c030002, 0x8c638fe4,
-0x3c010002, 0x14600015, 0xac228f90, 0xc003e6d,
-0x0, 0x3c050001, 0x8ca56d98, 0xc00529b,
-0x2021, 0x3c030001, 0x8c636d98, 0x24020004,
-0x14620005, 0x2403fffb, 0x3c020001, 0x8c426d94,
-0x10000003, 0x2403fff7, 0x3c020001, 0x8c426d94,
-0x431024, 0x3c010001, 0xac226d94, 0x8f830224,
-0x3c020200, 0x3c010002, 0xac238fec, 0x10000020,
-0x282a025, 0x3c020002, 0x8c428fc0, 0x10400005,
-0x0, 0x3c020002, 0x8c428f9c, 0x1040000f,
-0x24020002, 0x3c020002, 0x8c428fa0, 0x2c424e21,
-0x1040000a, 0x24020002, 0x3c020002, 0x8c428fc0,
-0x1040000f, 0x0, 0x3c020002, 0x8c428f9c,
-0x1440000b, 0x0, 0x24020002, 0x3c010002,
-0x10000007, 0xac228f90, 0x3c020002, 0x8c428fc0,
-0x10400003, 0x0, 0xc003daf, 0x0,
-0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
-0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030002,
-0x24638fe8, 0x8c620000, 0x10400005, 0x34422000,
-0x3c010002, 0xac228fdc, 0x10000003, 0xac600000,
-0x3c010002, 0xac248fdc, 0x3e00008, 0x0,
-0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010002,
-0xac228fe4, 0x14400067, 0x3c02ffff, 0x34421f0e,
-0x821024, 0x14400061, 0x24020030, 0x30822000,
-0x1040005d, 0x30838000, 0x31a02, 0x30820001,
-0x21200, 0x3c040001, 0x8c846f20, 0x621825,
-0x331c2, 0x3c030001, 0x24636e48, 0x30828000,
-0x21202, 0x30840001, 0x42200, 0x441025,
-0x239c2, 0x61080, 0x431021, 0x471021,
-0x90430000, 0x24020001, 0x10620025, 0x0,
-0x10600007, 0x24020002, 0x10620013, 0x24020003,
-0x1062002c, 0x3c05000f, 0x10000037, 0x0,
-0x8f820200, 0x2403feff, 0x431024, 0xaf820200,
-0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024,
-0xaf820220, 0x3c010002, 0xac209004, 0x3c010002,
-0x10000034, 0xac20900c, 0x8f820200, 0x34420100,
-0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff,
-0x431024, 0xaf820220, 0x24020100, 0x3c010002,
-0xac229004, 0x3c010002, 0x10000026, 0xac20900c,
-0x8f820200, 0x2403feff, 0x431024, 0xaf820200,
-0x8f820220, 0x3c030001, 0x431025, 0xaf820220,
-0x3c010002, 0xac209004, 0x3c010002, 0x10000019,
-0xac23900c, 0x8f820200, 0x34420100, 0xaf820200,
-0x8f820220, 0x3c030001, 0x431025, 0xaf820220,
-0x24020100, 0x3c010002, 0xac229004, 0x3c010002,
-0x1000000c, 0xac23900c, 0x34a5ffff, 0x3c040001,
-0x24846c38, 0xafa30010, 0xc002b3b, 0xafa00014,
-0x10000004, 0x0, 0x24020030, 0x3c010002,
-0xac228fe8, 0x8fbf0018, 0x3e00008, 0x27bd0020,
-0x0, 0x0, 0x0, 0x27bdffc8,
-0xafb20028, 0x809021, 0xafb3002c, 0xa09821,
-0xafb00020, 0xc08021, 0x3c040001, 0x24846c50,
-0x3c050009, 0x3c020001, 0x8c426d98, 0x34a59001,
-0x2403021, 0x2603821, 0xafbf0030, 0xafb10024,
-0xa7a0001a, 0xafb00014, 0xc002b3b, 0xafa20010,
-0x24020002, 0x12620083, 0x2e620003, 0x10400005,
-0x24020001, 0x1262000a, 0x0, 0x10000173,
-0x0, 0x24020004, 0x126200f8, 0x24020008,
-0x126200f7, 0x3c02ffec, 0x1000016c, 0x0,
-0x3c020001, 0x8c426d94, 0x30420002, 0x14400004,
-0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024,
-0x3c010002, 0x310821, 0xac308ffc, 0x3c024000,
-0x2021024, 0x1040004e, 0x1023c2, 0x30840030,
-0x101382, 0x3042001c, 0x3c030001, 0x24636dd8,
-0x431021, 0x823821, 0x3c020020, 0x2021024,
-0x10400006, 0x24020100, 0x3c010002, 0x310821,
-0xac229000, 0x10000005, 0x3c020080, 0x3c010002,
-0x310821, 0xac209000, 0x3c020080, 0x2021024,
-0x10400006, 0x121940, 0x3c020001, 0x3c010002,
-0x230821, 0x10000005, 0xac229008, 0x121140,
-0x3c010002, 0x220821, 0xac209008, 0x94e40000,
-0x3c030001, 0x8c636f40, 0x24020005, 0x10620010,
-0xa7a40018, 0x32024000, 0x10400002, 0x34824000,
-0xa7a20018, 0x24040001, 0x94e20002, 0x24050004,
-0x24e60002, 0x34420001, 0xc0045be, 0xa4e20002,
-0x24040001, 0x2821, 0xc0045be, 0x27a60018,
-0x3c020001, 0x8c426d98, 0x24110001, 0x3c010001,
-0xac316da4, 0x14530004, 0x32028000, 0xc003daf,
-0x0, 0x32028000, 0x1040011c, 0x0,
-0xc003daf, 0x0, 0x3c030001, 0x8c636f40,
-0x24020005, 0x10620115, 0x24020002, 0x3c010001,
-0xac316d9c, 0x3c010001, 0x10000110, 0xac226d98,
-0x24040001, 0x24050004, 0x27b0001a, 0xc0045be,
-0x2003021, 0x24040001, 0x2821, 0xc0045be,
-0x2003021, 0x3c020002, 0x511021, 0x8c428ff4,
-0x3c040001, 0x8c846d98, 0x3c03bfff, 0x3463ffff,
-0x3c010001, 0xac336da4, 0x431024, 0x3c010002,
-0x310821, 0x109300f7, 0xac228ff4, 0x100000f7,
-0x0, 0x3c022000, 0x2021024, 0x10400005,
-0x24020001, 0x3c010001, 0xac226f1c, 0x10000004,
-0x128940, 0x3c010001, 0xac206f1c, 0x128940,
-0x3c010002, 0x310821, 0xac308ff8, 0x3c024000,
-0x2021024, 0x14400014, 0x0, 0x3c020001,
-0x8c426f1c, 0x10400006, 0x24040004, 0x24050001,
-0xc004ddb, 0x24062000, 0x24020001, 0xaee204b8,
-0x3c020002, 0x511021, 0x8c428ff0, 0x3c03bfff,
-0x3463ffff, 0x431024, 0x3c010002, 0x310821,
-0x100000d0, 0xac228ff0, 0x3c020001, 0x8c426f1c,
-0x10400028, 0x3c0300a0, 0x2031024, 0x5443000d,
-0x3c020020, 0x3c020001, 0x8c426f20, 0x24030100,
-0x3c010002, 0x310821, 0xac239004, 0x3c030001,
-0x3c010002, 0x310821, 0xac23900c, 0x10000015,
-0x34420400, 0x2021024, 0x10400008, 0x24030100,
-0x3c020001, 0x8c426f20, 0x3c010002, 0x310821,
-0xac239004, 0x1000000b, 0x34420800, 0x3c020080,
-0x2021024, 0x1040002e, 0x3c030001, 0x3c020001,
-0x8c426f20, 0x3c010002, 0x310821, 0xac23900c,
-0x34420c00, 0x3c010001, 0xac226f20, 0x10000025,
-0x24040001, 0x3c020020, 0x2021024, 0x10400006,
-0x24020100, 0x3c010002, 0x310821, 0xac229004,
-0x10000005, 0x3c020080, 0x3c010002, 0x310821,
-0xac209004, 0x3c020080, 0x2021024, 0x10400007,
-0x121940, 0x3c020001, 0x3c010002, 0x230821,
-0xac22900c, 0x10000006, 0x24040001, 0x121140,
-0x3c010002, 0x220821, 0xac20900c, 0x24040001,
-0x2821, 0x27b0001e, 0xc00457c, 0x2003021,
-0x24040001, 0x2821, 0xc00457c, 0x2003021,
-0x24040001, 0x24050001, 0x27b0001c, 0xc00457c,
-0x2003021, 0x24040001, 0x24050001, 0xc00457c,
-0x2003021, 0x10000077, 0x0, 0x3c02ffec,
-0x3442ffff, 0x2028024, 0x3c020008, 0x2028025,
-0x121140, 0x3c010002, 0x220821, 0xac308ff8,
-0x3c022000, 0x2021024, 0x10400009, 0x0,
-0x3c020001, 0x8c426e44, 0x14400005, 0x24020001,
-0x3c010001, 0xac226f1c, 0x10000004, 0x3c024000,
-0x3c010001, 0xac206f1c, 0x3c024000, 0x2021024,
-0x1440001d, 0x24020e01, 0x3c030001, 0x8c636f1c,
-0xaf820238, 0x3c010001, 0xac206db0, 0x10600005,
-0x24022020, 0x3c010001, 0xac226f20, 0x24020001,
-0xaee204b8, 0x3c04bfff, 0x121940, 0x3c020002,
-0x431021, 0x8c428ff0, 0x3c050001, 0x8ca56d98,
-0x3484ffff, 0x441024, 0x3c010002, 0x230821,
-0xac228ff0, 0x24020001, 0x10a20044, 0x0,
-0x10000040, 0x0, 0x3c020001, 0x8c426f1c,
-0x1040001c, 0x24022000, 0x3c010001, 0xac226f20,
-0x3c0300a0, 0x2031024, 0x14430005, 0x121140,
-0x3402a000, 0x3c010001, 0x1000002d, 0xac226f20,
-0x3c030002, 0x621821, 0x8c638ff8, 0x3c020020,
-0x621024, 0x10400004, 0x24022001, 0x3c010001,
-0x10000023, 0xac226f20, 0x3c020080, 0x621024,
-0x1040001f, 0x3402a001, 0x3c010001, 0x1000001c,
-0xac226f20, 0x3c020020, 0x2021024, 0x10400007,
-0x121940, 0x24020100, 0x3c010002, 0x230821,
-0xac229004, 0x10000006, 0x3c020080, 0x121140,
-0x3c010002, 0x220821, 0xac209004, 0x3c020080,
-0x2021024, 0x10400006, 0x121940, 0x3c020001,
-0x3c010002, 0x230821, 0x10000005, 0xac22900c,
-0x121140, 0x3c010002, 0x220821, 0xac20900c,
-0x3c030001, 0x8c636d98, 0x24020001, 0x10620003,
-0x0, 0xc003daf, 0x0, 0x8fbf0030,
-0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
-0x3e00008, 0x27bd0038, 0x27bdffb0, 0xafb3003c,
-0x9821, 0xafb50040, 0xa821, 0xafb10034,
-0x8821, 0x24020002, 0xafbf0048, 0xafbe0044,
-0xafb20038, 0xafb00030, 0xafa4002c, 0xa7a0001a,
-0xa7a00018, 0xa7a00020, 0xa7a0001e, 0xa7a00022,
-0x10a20130, 0xa7a0001c, 0x2ca20003, 0x10400005,
-0x24020001, 0x10a2000a, 0x3c024000, 0x1000025d,
-0x2201021, 0x24020004, 0x10a2020a, 0x24020008,
-0x10a20208, 0x2201021, 0x10000256, 0x0,
-0x8fa8002c, 0x88140, 0x3c030002, 0x701821,
-0x8c638ffc, 0x621024, 0x14400009, 0x24040001,
-0x3c027fff, 0x3442ffff, 0x628824, 0x3c010002,
-0x300821, 0xac318ff4, 0x10000246, 0x2201021,
-0x24050001, 0xc00457c, 0x27a60018, 0x24040001,
-0x24050001, 0xc00457c, 0x27a60018, 0x97a20018,
-0x30420004, 0x104000d9, 0x3c114000, 0x3c020001,
-0x8c426f40, 0x2443ffff, 0x2c620006, 0x104000d9,
-0x31080, 0x3c010001, 0x220821, 0x8c226c68,
-0x400008, 0x0, 0x24040001, 0x24050011,
-0x27b0001a, 0xc00457c, 0x2003021, 0x24040001,
-0x24050011, 0xc00457c, 0x2003021, 0x97a3001a,
-0x30624000, 0x10400002, 0x3c150010, 0x3c150008,
-0x30628000, 0x104000aa, 0x3c130001, 0x100000a8,
-0x3c130002, 0x24040001, 0x24050014, 0x27b0001a,
-0xc00457c, 0x2003021, 0x24040001, 0x24050014,
-0xc00457c, 0x2003021, 0x97a3001a, 0x30621000,
-0x10400002, 0x3c150010, 0x3c150008, 0x30620800,
-0x10400097, 0x3c130001, 0x10000095, 0x3c130002,
-0x24040001, 0x24050019, 0x27b0001c, 0xc00457c,
-0x2003021, 0x24040001, 0x24050019, 0xc00457c,
-0x2003021, 0x97a2001c, 0x30430700, 0x24020400,
-0x10620027, 0x28620401, 0x1040000e, 0x24020200,
-0x1062001f, 0x28620201, 0x10400005, 0x24020100,
-0x5062001e, 0x3c130001, 0x1000001e, 0x24040001,
-0x24020300, 0x50620019, 0x3c130002, 0x10000019,
-0x24040001, 0x24020600, 0x1062000d, 0x28620601,
-0x10400005, 0x24020500, 0x5062000b, 0x3c130002,
-0x10000010, 0x24040001, 0x24020700, 0x1462000d,
-0x24040001, 0x3c130004, 0x1000000a, 0x3c150008,
-0x10000006, 0x3c130004, 0x10000005, 0x3c150008,
-0x3c130001, 0x10000002, 0x3c150008, 0x3c150010,
-0x24040001, 0x24050018, 0x27b0001e, 0xc00457c,
-0x2003021, 0x24040001, 0x24050018, 0xc00457c,
-0x2003021, 0x8fa8002c, 0x97a7001e, 0x81140,
-0x3c060002, 0xc23021, 0x8cc68ff4, 0x97a20022,
-0x3c100001, 0x26106c5c, 0x2002021, 0xafa20010,
-0x97a2001c, 0x3c05000c, 0x34a50303, 0xc002b3b,
-0xafa20014, 0x3c020004, 0x16620010, 0x3c020001,
-0x8f840054, 0x24030001, 0x24020002, 0x3c010001,
-0xac236d9c, 0x3c010001, 0xac226d98, 0x3c010001,
-0xac236da4, 0x3c010001, 0xac236e24, 0x3c010001,
-0xac246f30, 0x1000004f, 0x2b38825, 0x16620039,
-0x3c028000, 0x3c020001, 0x8c426e20, 0x1440001e,
-0x24040018, 0x2021, 0x2821, 0xc004ddb,
-0x34068000, 0x8f830054, 0x8f820054, 0x2b38825,
-0x10000002, 0x24630032, 0x8f820054, 0x621023,
-0x2c420033, 0x1440fffc, 0x0, 0x8f830054,
-0x24020001, 0x3c010001, 0xac226e20, 0x3c010001,
-0xac226d9c, 0x3c010001, 0xac226d98, 0x3c010001,
-0xac226da4, 0x3c010001, 0xac226e24, 0x3c010001,
-0x1000002c, 0xac236f30, 0x2821, 0xc004ddb,
-0x24060404, 0x2021, 0x2405001e, 0x27a60018,
-0x24020002, 0xc0045be, 0xa7a20018, 0x2021,
-0x2821, 0x27a60018, 0xc0045be, 0xa7a00018,
-0x24040018, 0x24050002, 0xc004ddb, 0x24060004,
-0x3c028000, 0x2221025, 0x2b31825, 0x10000015,
-0x438825, 0x2221025, 0x2751825, 0x438825,
-0x2002021, 0x97a6001c, 0x3c070001, 0x8ce76d98,
-0x3c05000c, 0x34a50326, 0xafb30010, 0xc002b3b,
-0xafb10014, 0x10000007, 0x0, 0x3c110002,
-0x2308821, 0x8e318ffc, 0x3c027fff, 0x3442ffff,
-0x2228824, 0x3c020001, 0x8c426da8, 0x1040001e,
-0x0, 0x3c020001, 0x8c426f1c, 0x10400002,
-0x3c022000, 0x2228825, 0x8fa8002c, 0x81140,
-0x3c010002, 0x220821, 0x8c229000, 0x10400003,
-0x3c020020, 0x10000005, 0x2228825, 0x3c02ffdf,
-0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140,
-0x3c010002, 0x220821, 0x8c229008, 0x10400003,
-0x3c020080, 0x10000004, 0x2228825, 0x3c02ff7f,
-0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140,
-0x3c010002, 0x220821, 0xac318ff4, 0x10000135,
-0x2201021, 0x8fa8002c, 0x8f140, 0x3c030002,
-0x7e1821, 0x8c638ff8, 0x3c024000, 0x621024,
-0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff,
-0x628824, 0x3c010002, 0x3e0821, 0xac318ff0,
-0x10000124, 0x2201021, 0x2821, 0xc00457c,
-0x27a60018, 0x24040001, 0x2821, 0xc00457c,
-0x27a60018, 0x24040001, 0x24050001, 0x27b20020,
-0xc00457c, 0x2403021, 0x24040001, 0x24050001,
-0xc00457c, 0x2403021, 0x24040001, 0x24050004,
-0x27b1001e, 0xc00457c, 0x2203021, 0x24040001,
-0x24050004, 0xc00457c, 0x2203021, 0x24040001,
-0x24050005, 0x27b00022, 0xc00457c, 0x2003021,
-0x24040001, 0x24050005, 0xc00457c, 0x2003021,
-0x24040001, 0x24050010, 0xc00457c, 0x27a60018,
-0x24040001, 0x24050010, 0xc00457c, 0x27a60018,
-0x24040001, 0x2405000a, 0xc00457c, 0x2403021,
-0x24040001, 0x2405000a, 0xc00457c, 0x2403021,
-0x24040001, 0x24050018, 0xc00457c, 0x2203021,
-0x24040001, 0x24050018, 0xc00457c, 0x2203021,
-0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
-0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
-0x97a20018, 0x30420004, 0x10400066, 0x3c114000,
-0x3c030001, 0x8c636f34, 0x24020005, 0x14620067,
-0x24040001, 0x24050019, 0x27b0001c, 0xc00457c,
-0x2003021, 0x24040001, 0x24050019, 0xc00457c,
-0x2003021, 0x97a2001c, 0x30430700, 0x24020400,
-0x10620027, 0x28620401, 0x1040000e, 0x24020200,
-0x1062001f, 0x28620201, 0x10400005, 0x24020100,
-0x5062001e, 0x3c130001, 0x1000001e, 0x3c020004,
-0x24020300, 0x50620019, 0x3c130002, 0x10000019,
-0x3c020004, 0x24020600, 0x1062000d, 0x28620601,
-0x10400005, 0x24020500, 0x5062000b, 0x3c130002,
-0x10000010, 0x3c020004, 0x24020700, 0x1462000d,
-0x3c020004, 0x3c130004, 0x1000000a, 0x3c150008,
-0x10000006, 0x3c130004, 0x10000005, 0x3c150008,
-0x3c130001, 0x10000002, 0x3c150008, 0x3c150010,
-0x3c020004, 0x12620017, 0x3c028000, 0x8f820054,
-0x24100001, 0x3c010001, 0xac306d9c, 0x3c010001,
-0xac306d98, 0x3c010001, 0xac306da4, 0x3c010001,
-0xac306e24, 0x3c010001, 0xac226f30, 0x3c020001,
-0x16620022, 0x2758825, 0x2021, 0x2821,
-0xc004ddb, 0x34068000, 0x3c010001, 0x1000001b,
-0xac306e20, 0x2221025, 0x2b31825, 0x438825,
-0x97a6001c, 0x3c020001, 0x8c426f1c, 0x3c070001,
-0x8ce76d98, 0x3c040001, 0x24846c5c, 0xafa20010,
-0x97a2001e, 0x3c05000c, 0x34a50323, 0x3c010001,
-0xac206e20, 0xc002b3b, 0xafa20014, 0x10000007,
-0x0, 0x3c110002, 0x23e8821, 0x8e318ff0,
-0x3c027fff, 0x3442ffff, 0x2228824, 0x3c020001,
-0x8c426da8, 0x10400069, 0x0, 0x3c020001,
-0x8c426f1c, 0x10400002, 0x3c022000, 0x2228825,
-0x8fa8002c, 0x81140, 0x3c010002, 0x220821,
-0x8c229004, 0x10400003, 0x3c020020, 0x10000005,
-0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824,
-0x8fa8002c, 0x81140, 0x3c010002, 0x220821,
-0x8c22900c, 0x10400003, 0x3c020080, 0x1000004f,
-0x2228825, 0x3c02ff7f, 0x3442ffff, 0x1000004b,
-0x2228824, 0x8fa8002c, 0x82940, 0x3c030002,
-0x651821, 0x8c638ff8, 0x3c024000, 0x621024,
-0x14400008, 0x3c027fff, 0x3442ffff, 0x628824,
-0x3c010002, 0x250821, 0xac318ff0, 0x10000041,
-0x2201021, 0x3c020001, 0x8c426da8, 0x10400034,
-0x3c11c00c, 0x3c020001, 0x8c426e44, 0x3c04c00c,
-0x34842000, 0x3c030001, 0x8c636f1c, 0x2102b,
-0x21023, 0x441024, 0x10600003, 0x518825,
-0x3c022000, 0x2228825, 0x3c020002, 0x451021,
-0x8c429004, 0x10400003, 0x3c020020, 0x10000004,
-0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824,
-0x8fa8002c, 0x81140, 0x3c010002, 0x220821,
-0x8c22900c, 0x10400003, 0x3c020080, 0x10000004,
-0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824,
-0x3c020001, 0x8c426e30, 0x10400002, 0x3c020800,
-0x2228825, 0x3c020001, 0x8c426e34, 0x10400002,
-0x3c020400, 0x2228825, 0x3c020001, 0x8c426e38,
-0x10400006, 0x3c020100, 0x10000004, 0x2228825,
-0x3c027fff, 0x3442ffff, 0x628824, 0x8fa8002c,
-0x81140, 0x3c010002, 0x220821, 0xac318ff0,
-0x2201021, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
-0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
-0x3e00008, 0x27bd0050, 0x27bdffd0, 0xafb20028,
-0x809021, 0xafbf002c, 0xafb10024, 0xafb00020,
-0x8f840200, 0x3c100001, 0x8e106d98, 0x8f860220,
-0x24020002, 0x1202005c, 0x2e020003, 0x10400005,
-0x24020001, 0x1202000a, 0x121940, 0x1000010c,
-0x0, 0x24020004, 0x120200bf, 0x24020008,
-0x120200be, 0x128940, 0x10000105, 0x0,
-0x3c050002, 0xa32821, 0x8ca58ffc, 0x3c100002,
-0x2038021, 0x8e108ff4, 0x3c024000, 0xa21024,
-0x10400038, 0x3c020008, 0x2021024, 0x10400020,
-0x34840002, 0x3c020002, 0x431021, 0x8c429000,
-0x10400005, 0x34840020, 0x34840100, 0x3c020020,
-0x10000006, 0x2028025, 0x2402feff, 0x822024,
-0x3c02ffdf, 0x3442ffff, 0x2028024, 0x121140,
-0x3c010002, 0x220821, 0x8c229008, 0x10400005,
-0x3c020001, 0xc23025, 0x3c020080, 0x10000016,
-0x2028025, 0x3c02fffe, 0x3442ffff, 0xc23024,
-0x3c02ff7f, 0x3442ffff, 0x1000000f, 0x2028024,
-0x2402fedf, 0x822024, 0x3c02fffe, 0x3442ffff,
-0xc23024, 0x3c02ff5f, 0x3442ffff, 0x2028024,
-0x3c010002, 0x230821, 0xac209000, 0x3c010002,
-0x230821, 0xac209008, 0xaf840200, 0xaf860220,
-0x8f820220, 0x34420002, 0xaf820220, 0x1000000a,
-0x121140, 0x3c02bfff, 0x3442ffff, 0x8f830200,
-0x2028024, 0x2402fffd, 0x621824, 0xc003daf,
-0xaf830200, 0x121140, 0x3c010002, 0x220821,
-0x100000b7, 0xac308ff4, 0x3c020001, 0x8c426f1c,
-0x10400069, 0x24050004, 0x24040001, 0xc00457c,
-0x27a60018, 0x24040001, 0x24050005, 0xc00457c,
-0x27a6001a, 0x97a30018, 0x97a2001a, 0x3c040001,
-0x24846e48, 0x30630c00, 0x31a82, 0x30420c00,
-0x21282, 0xa7a2001a, 0x21080, 0x441021,
-0x431021, 0xa7a30018, 0x90480000, 0x24020001,
-0x3103ffff, 0x10620029, 0x28620002, 0x10400005,
-0x0, 0x10600009, 0x0, 0x1000003d,
-0x0, 0x10700013, 0x24020003, 0x1062002c,
-0x0, 0x10000037, 0x0, 0x8f820200,
-0x2403feff, 0x431024, 0xaf820200, 0x8f820220,
-0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220,
-0x3c010002, 0xac209004, 0x3c010002, 0x10000032,
-0xac20900c, 0x8f820200, 0x34420100, 0xaf820200,
-0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024,
-0xaf820220, 0x24020100, 0x3c010002, 0xac229004,
-0x3c010002, 0x10000024, 0xac20900c, 0x8f820200,
-0x2403feff, 0x431024, 0xaf820200, 0x8f820220,
-0x3c030001, 0x431025, 0xaf820220, 0x3c010002,
-0xac209004, 0x3c010002, 0x10000017, 0xac23900c,
-0x8f820200, 0x34420100, 0xaf820200, 0x8f820220,
-0x3c030001, 0x431025, 0xaf820220, 0x24020100,
-0x3c010002, 0xac229004, 0x3c010002, 0x1000000a,
-0xac23900c, 0x3c040001, 0x24846c80, 0x97a6001a,
-0x97a70018, 0x3c050001, 0x34a5ffff, 0xafa80010,
-0xc002b3b, 0xafa00014, 0x8f820200, 0x34420002,
-0x1000004b, 0xaf820200, 0x128940, 0x3c050002,
-0xb12821, 0x8ca58ff8, 0x3c100002, 0x2118021,
-0x8e108ff0, 0x3c024000, 0xa21024, 0x14400010,
-0x0, 0x3c020001, 0x8c426f1c, 0x14400005,
-0x3c02bfff, 0x8f820200, 0x34420002, 0xaf820200,
-0x3c02bfff, 0x3442ffff, 0xc003daf, 0x2028024,
-0x3c010002, 0x310821, 0x10000031, 0xac308ff0,
-0x3c020001, 0x8c426f1c, 0x10400005, 0x3c020020,
-0x3c020001, 0x8c426e44, 0x10400025, 0x3c020020,
-0xa21024, 0x10400007, 0x34840020, 0x24020100,
-0x3c010002, 0x310821, 0xac229004, 0x10000006,
-0x34840100, 0x3c010002, 0x310821, 0xac209004,
-0x2402feff, 0x822024, 0x3c020080, 0xa21024,
-0x10400007, 0x121940, 0x3c020001, 0x3c010002,
-0x230821, 0xac22900c, 0x10000008, 0xc23025,
-0x121140, 0x3c010002, 0x220821, 0xac20900c,
-0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200,
-0xaf860220, 0x8f820220, 0x34420002, 0xaf820220,
-0x121140, 0x3c010002, 0x220821, 0xac308ff0,
-0x8fbf002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
-0x3e00008, 0x27bd0030, 0x0, 0x1821,
-0x308400ff, 0x2405ffdf, 0x2406ffbf, 0x641007,
-0x30420001, 0x10400004, 0x0, 0x8f820044,
-0x10000003, 0x34420040, 0x8f820044, 0x461024,
-0xaf820044, 0x8f820044, 0x34420020, 0xaf820044,
-0x8f820044, 0x451024, 0xaf820044, 0x24630001,
-0x28620008, 0x5440ffee, 0x641007, 0x3e00008,
-0x0, 0x2c820008, 0x1040001b, 0x0,
-0x2405ffdf, 0x2406ffbf, 0x41880, 0x3c020001,
-0x24426e60, 0x621821, 0x24640004, 0x90620000,
-0x10400004, 0x0, 0x8f820044, 0x10000003,
-0x34420040, 0x8f820044, 0x461024, 0xaf820044,
-0x8f820044, 0x34420020, 0xaf820044, 0x8f820044,
-0x451024, 0xaf820044, 0x24630001, 0x64102b,
-0x1440ffee, 0x0, 0x3e00008, 0x0,
-0x0, 0x0, 0x0, 0x8f8400c4,
-0x8f8600e0, 0x8f8700e4, 0x2402fff8, 0xc22824,
-0x10e5001a, 0x27623ff8, 0x14e20002, 0x24e80008,
-0x27683000, 0x55050004, 0x8d0a0000, 0x30c20004,
-0x14400012, 0x805021, 0x8ce90000, 0x8f42013c,
-0x1494823, 0x49182b, 0x94eb0006, 0x10600002,
-0x25630050, 0x494821, 0x123182b, 0x50400003,
-0x8f4201fc, 0x3e00008, 0xe01021, 0xaf8800e8,
-0x24420001, 0xaf4201fc, 0xaf8800e4, 0x3e00008,
-0x1021, 0x3e00008, 0x0, 0x8f8300e4,
-0x27623ff8, 0x10620004, 0x24620008, 0xaf8200e8,
-0x3e00008, 0xaf8200e4, 0x27623000, 0xaf8200e8,
-0x3e00008, 0xaf8200e4, 0x3e00008, 0x0,
-0x0, 0x0, 0x0, 0x8f880120,
-0x27624fe0, 0x8f830128, 0x15020002, 0x25090020,
-0x27694800, 0x11230012, 0x8fa20010, 0xad040000,
-0xad050004, 0xad060008, 0xa507000e, 0x8fa30014,
-0xad020018, 0x8fa20018, 0xad03001c, 0x25030016,
-0xad020010, 0xad030014, 0xaf890120, 0x8f4300fc,
-0x24020001, 0x2463ffff, 0x3e00008, 0xaf4300fc,
-0x8f430324, 0x1021, 0x24630001, 0x3e00008,
-0xaf430324, 0x3e00008, 0x0, 0x8f880100,
-0x276247e0, 0x8f830108, 0x15020002, 0x25090020,
-0x27694000, 0x1123000f, 0x8fa20010, 0xad040000,
-0xad050004, 0xad060008, 0xa507000e, 0x8fa30014,
-0xad020018, 0x8fa20018, 0xad03001c, 0x25030016,
-0xad020010, 0xad030014, 0xaf890100, 0x3e00008,
-0x24020001, 0x8f430328, 0x1021, 0x24630001,
-0x3e00008, 0xaf430328, 0x3e00008, 0x0,
-0x0, 0x0, 0x0, 0x0 };
-static int tigon2FwRodata[/*(MAX_RODATA_LEN/4) + 1*/] = {
-0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f6677, 0x6d61696e, 0x2e632c76, 0x20312e31,
-0x2e322e34, 0x35203139, 0x39392f30, 0x312f3234,
-0x2030303a, 0x31303a35, 0x35207368, 0x75616e67,
-0x20457870, 0x20240000, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x6261644d, 0x656d537a,
-0x0, 0x68775665, 0x72000000, 0x62616448,
-0x77566572, 0x0, 0x2a2a4441, 0x574e5f41,
-0x0, 0x74785278, 0x4266537a, 0x0,
-0x62664174, 0x6e4d726b, 0x0, 0x7265645a,
-0x6f6e6531, 0x0, 0x70636943, 0x6f6e6600,
-0x67656e43, 0x6f6e6600, 0x2a646d61, 0x5244666c,
-0x0, 0x2a50414e, 0x49432a00, 0x2e2e2f2e,
-0x2e2f2e2e, 0x2f2e2e2f, 0x2e2e2f73, 0x72632f6e,
-0x69632f66, 0x77322f63, 0x6f6d6d6f, 0x6e2f6677,
-0x6d61696e, 0x2e630000, 0x72636246, 0x6c616773,
-0x0, 0x62616452, 0x78526362, 0x0,
-0x676c6f62, 0x466c6773, 0x0, 0x2b5f6469,
-0x73705f6c, 0x6f6f7000, 0x2b65765f, 0x68616e64,
-0x6c657200, 0x63616e74, 0x31446d61, 0x0,
-0x2b715f64, 0x6d615f74, 0x6f5f6e69, 0x635f636b,
-0x73756d00, 0x2b685f73, 0x656e645f, 0x64617461,
-0x5f726561, 0x64795f63, 0x6b73756d, 0x0,
-0x2b685f64, 0x6d615f72, 0x645f6173, 0x73697374,
-0x5f636b73, 0x756d0000, 0x74436b73, 0x6d4f6e00,
-0x2b715f64, 0x6d615f74, 0x6f5f6e69, 0x63000000,
-0x2b685f73, 0x656e645f, 0x64617461, 0x5f726561,
-0x64790000, 0x2b685f64, 0x6d615f72, 0x645f6173,
-0x73697374, 0x0, 0x74436b73, 0x6d4f6666,
-0x0, 0x2b685f73, 0x656e645f, 0x62645f72,
-0x65616479, 0x0, 0x68737453, 0x52696e67,
-0x0, 0x62616453, 0x52696e67, 0x0,
-0x6e696353, 0x52696e67, 0x0, 0x77446d61,
-0x416c6c41, 0x0, 0x2b715f64, 0x6d615f74,
-0x6f5f686f, 0x73745f63, 0x6b73756d, 0x0,
-0x2b685f6d, 0x61635f72, 0x785f636f, 0x6d705f63,
-0x6b73756d, 0x0, 0x2b685f64, 0x6d615f77,
-0x725f6173, 0x73697374, 0x5f636b73, 0x756d0000,
-0x72436b73, 0x6d4f6e00, 0x2b715f64, 0x6d615f74,
-0x6f5f686f, 0x73740000, 0x2b685f6d, 0x61635f72,
-0x785f636f, 0x6d700000, 0x2b685f64, 0x6d615f77,
-0x725f6173, 0x73697374, 0x0, 0x72436b73,
-0x6d4f6666, 0x0, 0x2b685f72, 0x6563765f,
-0x62645f72, 0x65616479, 0x0, 0x2b685f72,
-0x6563765f, 0x6a756d62, 0x6f5f6264, 0x5f726561,
-0x64790000, 0x2b685f72, 0x6563765f, 0x6d696e69,
-0x5f62645f, 0x72656164, 0x79000000, 0x2b6d685f,
-0x636f6d6d, 0x616e6400, 0x2b685f74, 0x696d6572,
-0x0, 0x2b685f64, 0x6f5f7570, 0x64617465,
-0x5f74785f, 0x636f6e73, 0x0, 0x2b685f64,
-0x6f5f7570, 0x64617465, 0x5f72785f, 0x70726f64,
-0x0, 0x2b636b73, 0x756d3136, 0x0,
-0x2b706565, 0x6b5f6d61, 0x635f7278, 0x5f776100,
-0x2b706565, 0x6b5f6d61, 0x635f7278, 0x0,
-0x2b646571, 0x5f6d6163, 0x5f727800, 0x2b685f6d,
-0x61635f72, 0x785f6174, 0x746e0000, 0x62616452,
-0x6574537a, 0x0, 0x72784264, 0x4266537a,
-0x0, 0x2b6e756c, 0x6c5f6861, 0x6e646c65,
-0x72000000, 0x66774f70, 0x4661696c, 0x0,
-0x2b685f75, 0x70646174, 0x655f6c65, 0x64340000,
-0x2b685f75, 0x70646174, 0x655f6c65, 0x64360000,
-0x2b685f75, 0x70646174, 0x655f6c65, 0x64320000,
-0x696e7453, 0x74617465, 0x0, 0x2a2a696e,
-0x69744370, 0x0, 0x23736372, 0x65616d00,
-0x69537461, 0x636b4572, 0x0, 0x70726f62,
-0x654d656d, 0x0, 0x2a2a4441, 0x574e5f42,
-0x0, 0x2b73775f, 0x646d615f, 0x61737369,
-0x73745f70, 0x6c75735f, 0x74696d65, 0x72000000,
-0x2b267072, 0x656c6f61, 0x645f7772, 0x5f646573,
-0x63720000, 0x2b267072, 0x656c6f61, 0x645f7264,
-0x5f646573, 0x63720000, 0x2b685f68, 0x665f7469,
-0x6d657200, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f7469, 0x6d65722e, 0x632c7620, 0x312e312e,
-0x322e3335, 0x20313939, 0x392f3031, 0x2f323720,
-0x31393a30, 0x393a3530, 0x20686179, 0x65732045,
-0x78702024, 0x0, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x542d446d, 0x61526432,
-0x0, 0x542d446d, 0x61526431, 0x0,
-0x542d446d, 0x61526442, 0x0, 0x542d446d,
-0x61577232, 0x0, 0x542d446d, 0x61577231,
-0x0, 0x542d446d, 0x61577242, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f636f, 0x6d6d616e, 0x642e632c, 0x7620312e,
-0x312e322e, 0x32382031, 0x3939392f, 0x30312f32,
-0x30203139, 0x3a34393a, 0x34392073, 0x6875616e,
-0x67204578, 0x70202400, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x3f48636d, 0x644d6278,
-0x0, 0x3f636d64, 0x48737453, 0x0,
-0x3f636d64, 0x4d634d64, 0x0, 0x3f636d64,
-0x50726f6d, 0x0, 0x3f636d64, 0x4c696e6b,
-0x0, 0x3f636d64, 0x45727200, 0x86ac,
-0x8e5c, 0x8e5c, 0x8de4, 0x8b78,
-0x8e30, 0x8e5c, 0x8790, 0x8800,
-0x8990, 0x8a68, 0x8a34, 0x8e5c,
-0x8870, 0x8b24, 0x8e5c, 0x8b34,
-0x87b4, 0x8824, 0x0, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f6d63, 0x6173742e, 0x632c7620, 0x312e312e,
-0x322e3820, 0x31393938, 0x2f31322f, 0x30382030,
-0x323a3336, 0x3a333620, 0x73687561, 0x6e672045,
-0x78702024, 0x0, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x6164644d, 0x63447570,
-0x0, 0x6164644d, 0x6346756c, 0x0,
-0x64656c4d, 0x634e6f45, 0x0, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f646d, 0x612e632c, 0x7620312e, 0x312e322e,
-0x32342031, 0x3939382f, 0x31322f32, 0x31203030,
-0x3a33333a, 0x30392073, 0x6875616e, 0x67204578,
-0x70202400, 0x65767452, 0x6e674600, 0x51657674,
-0x46000000, 0x51657674, 0x505f4600, 0x4d657674,
-0x526e6746, 0x0, 0x4d516576, 0x74460000,
-0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46,
-0x0, 0x5173436f, 0x6e734600, 0x51725072,
-0x6f644600, 0x7377446d, 0x614f6666, 0x0,
-0x31446d61, 0x4f6e0000, 0x7377446d, 0x614f6e00,
-0x2372446d, 0x6141544e, 0x0, 0x72446d61,
-0x41544e30, 0x0, 0x72446d61, 0x41544e31,
-0x0, 0x72446d61, 0x34476200, 0x2a50414e,
-0x49432a00, 0x2e2e2f2e, 0x2e2f2e2e, 0x2f2e2e2f,
-0x2e2e2f73, 0x72632f6e, 0x69632f66, 0x77322f63,
-0x6f6d6d6f, 0x6e2f646d, 0x612e6300, 0x2377446d,
-0x6141544e, 0x0, 0x77446d61, 0x41544e30,
-0x0, 0x77446d61, 0x41544e31, 0x0,
-0x77446d61, 0x34476200, 0x0, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f7472, 0x6163652e, 0x632c7620, 0x312e312e,
-0x322e3520, 0x31393938, 0x2f30392f, 0x33302031,
-0x383a3530, 0x3a323820, 0x73687561, 0x6e672045,
-0x78702024, 0x0, 0x0, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f6461, 0x74612e63, 0x2c762031, 0x2e312e32,
-0x2e313220, 0x31393939, 0x2f30312f, 0x32302031,
-0x393a3439, 0x3a353120, 0x73687561, 0x6e672045,
-0x78702024, 0x0, 0x46575f56, 0x45525349,
-0x4f4e3a20, 0x23312046, 0x72692041, 0x70722037,
-0x2031373a, 0x35373a35, 0x32205044, 0x54203230,
-0x30300000, 0x46575f43, 0x4f4d5049, 0x4c455f54,
-0x494d453a, 0x2031373a, 0x35373a35, 0x32000000,
-0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064,
-0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049,
-0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465,
-0x0, 0x46575f43, 0x4f4d5049, 0x4c455f44,
-0x4f4d4149, 0x4e3a2065, 0x6e672e61, 0x6374656f,
-0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049,
-0x4c45523a, 0x20676363, 0x20766572, 0x73696f6e,
-0x20322e37, 0x2e320000, 0x0, 0x12041100,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f6d65, 0x6d2e632c, 0x7620312e, 0x312e322e,
-0x35203139, 0x39382f30, 0x392f3330, 0x2031383a,
-0x35303a30, 0x38207368, 0x75616e67, 0x20457870,
-0x20240000, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f7365, 0x6e642e63, 0x2c762031, 0x2e312e32,
-0x2e343420, 0x31393938, 0x2f31322f, 0x32312030,
-0x303a3333, 0x3a313820, 0x73687561, 0x6e672045,
-0x78702024, 0x0, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x69736e74, 0x54637055,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f7265, 0x63762e63, 0x2c762031, 0x2e312e32,
-0x2e353320, 0x31393939, 0x2f30312f, 0x31362030,
-0x323a3535, 0x3a343320, 0x73687561, 0x6e672045,
-0x78702024, 0x0, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x724d6163, 0x43686b30,
-0x0, 0x72784672, 0x6d324c67, 0x0,
-0x72784e6f, 0x53744264, 0x0, 0x72784e6f,
-0x4d694264, 0x0, 0x72784e6f, 0x4a6d4264,
-0x0, 0x7278436b, 0x446d6146, 0x0,
-0x72785144, 0x6d457846, 0x0, 0x72785144,
-0x6d614600, 0x72785144, 0x4c426446, 0x0,
-0x72785144, 0x6d426446, 0x0, 0x72784372,
-0x63506164, 0x0, 0x72536d51, 0x446d6146,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f6d61, 0x632e632c, 0x7620312e, 0x312e322e,
-0x32322031, 0x3939382f, 0x31322f30, 0x38203032,
-0x3a33363a, 0x33302073, 0x6875616e, 0x67204578,
-0x70202400, 0x65767452, 0x6e674600, 0x51657674,
-0x46000000, 0x51657674, 0x505f4600, 0x4d657674,
-0x526e6746, 0x0, 0x4d516576, 0x74460000,
-0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46,
-0x0, 0x5173436f, 0x6e734600, 0x51725072,
-0x6f644600, 0x6d616354, 0x68726573, 0x0,
-0x23744d61, 0x6341544e, 0x0, 0x23724d61,
-0x6341544e, 0x0, 0x72656d41, 0x73737274,
-0x0, 0x6c696e6b, 0x444f574e, 0x0,
-0x6c696e6b, 0x55500000, 0x0, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f636b, 0x73756d2e, 0x632c7620, 0x312e312e,
-0x322e3920, 0x31393939, 0x2f30312f, 0x31342030,
-0x303a3033, 0x3a343820, 0x73687561, 0x6e672045,
-0x78702024, 0x0, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x0, 0x0,
-0x0, 0x50726f62, 0x65506879, 0x0,
-0x6c6e6b41, 0x53535254, 0x0, 0x109a4,
-0x10a1c, 0x10a50, 0x10a7c, 0x11050,
-0x10aa8, 0x10b10, 0x111fc, 0x10dc0,
-0x10c68, 0x10c80, 0x10cc4, 0x10cec,
-0x10d0c, 0x10d34, 0x111fc, 0x10dc0,
-0x10df8, 0x10e10, 0x10e40, 0x10e68,
-0x10e88, 0x10eb0, 0x0, 0x10fdc,
-0x11008, 0x1102c, 0x111fc, 0x11050,
-0x11078, 0x11108, 0x0, 0x0,
-0x0, 0x1186c, 0x1193c, 0x11a14,
-0x11ae4, 0x11b40, 0x11c1c, 0x11c44,
-0x11d20, 0x11d48, 0x11ef0, 0x11f18,
-0x120c0, 0x122b8, 0x1254c, 0x12460,
-0x1254c, 0x12578, 0x120e8, 0x12290,
-0x7273745f, 0x676d6969, 0x0, 0x12608,
-0x12640, 0x12728, 0x13374, 0x133b4,
-0x133cc, 0x7365746c, 0x6f6f7000, 0x0,
-0x0, 0x13bbc, 0x13bfc, 0x13c8c,
-0x13cd0, 0x13d34, 0x13dc0, 0x13df4,
-0x13e7c, 0x13f14, 0x13fe4, 0x14024,
-0x140a8, 0x140cc, 0x141dc, 0x646f4261,
-0x73655067, 0x0, 0x0, 0x0,
-0x0, 0x73746d61, 0x634c4e4b, 0x0,
-0x6765746d, 0x636c6e6b, 0x0, 0x14ed8,
-0x14ed8, 0x14b8c, 0x14bd8, 0x14c24,
-0x14ed8, 0x7365746d, 0x61636163, 0x74000000,
-0x0, 0x0 };
-static int tigon2FwData[/*(MAX_DATA_LEN/4) + 1*/] = {
-0x1,
-0x1, 0x1, 0xc001fc, 0x3ffc,
-0xc00000, 0x416c7465, 0x6f6e2041, 0x63654e49,
-0x43205600, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x416c7465,
-0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242,
-0x0, 0x0, 0x0, 0x1ffffc,
-0x1fff7c, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x60cf00,
-0x60, 0xcf000000, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x3, 0x0,
-0x1, 0x0, 0x0, 0x0,
-0x1, 0x0, 0x1, 0x0,
-0x0, 0x0, 0x0, 0x1,
-0x1, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x1000000, 0x21000000,
-0x12000140, 0x0, 0x0, 0x20000000,
-0x120000a0, 0x0, 0x12000060, 0x12000180,
-0x120001e0, 0x0, 0x0, 0x0,
-0x1, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x2,
-0x0, 0x0, 0x30001, 0x1,
-0x30201, 0x0, 0x0, 0x1010101,
-0x1010100, 0x10100, 0x1010001, 0x10001,
-0x1000101, 0x101, 0x0, 0x0 };
--- a/os/boot/pc/etherif.h
+++ /dev/null
@@ -1,47 +1,0 @@
-typedef struct RingBuf {
- uchar owner;
- uchar unused;
- ushort len;
- uchar pkt[sizeof(Etherpkt)];
-} RingBuf;
-
-enum {
- Host = 0, /* buffer owned by host */
- Interface = 1, /* buffer owned by card */
-
- Nrb = 32, /* default number of receive buffers */
- Ntb = 8, /* default number of transmit buffers */
-};
-
-typedef struct Ether Ether;
-struct Ether {
- ISAConf; /* hardware info */
- int ctlrno;
- int state; /* 0: unfound, 1: found, 2: attaching */
- int tbdf;
-
- void (*attach)(Ether*); /* filled in by reset routine */
- void (*transmit)(Ether*);
- void (*interrupt)(Ureg*, void*);
- void (*detach)(Ether*);
- void *ctlr;
-
- ushort nrb; /* number of software receive buffers */
- ushort ntb; /* number of software transmit buffers */
- RingBuf *rb; /* software receive buffers */
- RingBuf *tb; /* software transmit buffers */
-
- ushort rh; /* first receive buffer belonging to host */
- ushort ri; /* first receive buffer belonging to card */
-
- ushort th; /* first transmit buffer belonging to host */
- ushort ti; /* first transmit buffer belonging to card */
- int tbusy; /* transmitter is busy */
- int mbps; /* zero means link down */
-};
-
-extern void etherrloop(Ether*, Etherpkt*, long);
-extern void addethercard(char*, int(*)(Ether*));
-
-#define NEXT(x, l) (((x)+1)%(l))
-#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
--- a/os/boot/pc/etherigbe.c
+++ /dev/null
@@ -1,1741 +1,0 @@
-/*
- * bootstrap driver for
- * Intel RS-82543GC Gigabit Ethernet PCI Controllers
- * as found on the Intel PRO/1000[FT] Server Adapter.
- * The older non-[FT] cards use the 82542 (LSI L2A1157) chip; no attempt
- * is made to handle the older chip although it should be possible.
- *
- * updated just enough to cope with the
- * Intel 8254[0347]NN Gigabit Ethernet Controller
- * as found on the Intel PRO/1000 series of adapters:
- * 82540EM Intel PRO/1000 MT
- * 82543GC Intel PRO/1000 T
- * 82544EI Intel PRO/1000 XT
- * 82547EI built-in
- *
- * The datasheet is not very clear about running on a big-endian system
- * and this driver assumes little-endian throughout.
- * To do:
- * GMII/MII
- * check recovery from receive no buffers condition
- * automatic ett adjustment
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ethermii.h"
-
-enum {
- Debug = 0, /* mostly for X60 debugging */
-};
-enum {
- i82542 = (0x1000<<16)|0x8086,
- i82543gc = (0x1004<<16)|0x8086,
- i82544ei = (0x1008<<16)|0x8086,
- i82540em = (0x100E<<16)|0x8086,
- i82546eb = (0x1010<<16)|0x8086,
- i82547ei = (0x1019<<16)|0x8086,
- i82540eplp = (0x101E<<16)|0x8086,
- i82547gi = (0x1075<<16)|0x8086,
- i82541gi = (0x1076<<16)|0x8086,
- i82541gi2 = (0x1077<<16)|0x8086,
- i82546gb = (0x1079<<16)|0x8086,
- i82541pi = (0x107c<<16)|0x8086,
-};
-
-/* compatibility with cpu kernels */
-#define iallocb allocb
-#ifndef CACHELINESZ
-#define CACHELINESZ 32 /* pentium & later */
-#endif
-
-/* from pci.c */
-enum
-{ /* command register (pcidev->pcr) */
- IOen = (1<<0),
- MEMen = (1<<1),
- MASen = (1<<2),
- MemWrInv = (1<<4),
- PErrEn = (1<<6),
- SErrEn = (1<<8),
-};
-enum {
- Ctrl = 0x00000000, /* Device Control */
- Status = 0x00000008, /* Device Status */
- Eecd = 0x00000010, /* EEPROM/Flash Control/Data */
- Ctrlext = 0x00000018, /* Extended Device Control */
- Mdic = 0x00000020, /* MDI Control */
- Fcal = 0x00000028, /* Flow Control Address Low */
- Fcah = 0x0000002C, /* Flow Control Address High */
- Fct = 0x00000030, /* Flow Control Type */
- Icr = 0x000000C0, /* Interrupt Cause Read */
- Ics = 0x000000C8, /* Interrupt Cause Set */
- Ims = 0x000000D0, /* Interrupt Mask Set/Read */
- Imc = 0x000000D8, /* Interrupt mask Clear */
- Rctl = 0x00000100, /* Receive Control */
- Fcttv = 0x00000170, /* Flow Control Transmit Timer Value */
- Txcw = 0x00000178, /* Transmit Configuration Word */
- Tctl = 0x00000400, /* Transmit Control */
- Tipg = 0x00000410, /* Transmit IPG */
- Tbt = 0x00000448, /* Transmit Burst Timer */
- Ait = 0x00000458, /* Adaptive IFS Throttle */
- Fcrtl = 0x00002160, /* Flow Control RX Threshold Low */
- Fcrth = 0x00002168, /* Flow Control Rx Threshold High */
- Rdbal = 0x00002800, /* Rdesc Base Address Low */
- Rdbah = 0x00002804, /* Rdesc Base Address High */
- Rdlen = 0x00002808, /* Receive Descriptor Length */
- Rdh = 0x00002810, /* Receive Descriptor Head */
- Rdt = 0x00002818, /* Receive Descriptor Tail */
- Rdtr = 0x00002820, /* Receive Descriptor Timer Ring */
- Rxdctl = 0x00002828, /* Receive Descriptor Control */
- Radv = 0x0000282C, /* Receive Interrupt Absolute Delay Timer */
- Txdmac = 0x00003000, /* Transfer DMA Control */
- Ett = 0x00003008, /* Early Transmit Control */
- Tdbal = 0x00003800, /* Tdesc Base Address Low */
- Tdbah = 0x00003804, /* Tdesc Base Address High */
- Tdlen = 0x00003808, /* Transmit Descriptor Length */
- Tdh = 0x00003810, /* Transmit Descriptor Head */
- Tdt = 0x00003818, /* Transmit Descriptor Tail */
- Tidv = 0x00003820, /* Transmit Interrupt Delay Value */
- Txdctl = 0x00003828, /* Transmit Descriptor Control */
- Tadv = 0x0000382C, /* Transmit Interrupt Absolute Delay Timer */
-
- Statistics = 0x00004000, /* Start of Statistics Area */
- Gorcl = 0x88/4, /* Good Octets Received Count */
- Gotcl = 0x90/4, /* Good Octets Transmitted Count */
- Torl = 0xC0/4, /* Total Octets Received */
- Totl = 0xC8/4, /* Total Octets Transmitted */
- Nstatistics = 64,
-
- Rxcsum = 0x00005000, /* Receive Checksum Control */
- Mta = 0x00005200, /* Multicast Table Array */
- Ral = 0x00005400, /* Receive Address Low */
- Rah = 0x00005404, /* Receive Address High */
- Manc = 0x00005820, /* Management Control */
-};
-
-enum { /* Ctrl */
- Bem = 0x00000002, /* Big Endian Mode */
- Prior = 0x00000004, /* Priority on the PCI bus */
- Lrst = 0x00000008, /* Link Reset */
- Asde = 0x00000020, /* Auto-Speed Detection Enable */
- Slu = 0x00000040, /* Set Link Up */
- Ilos = 0x00000080, /* Invert Loss of Signal (LOS) */
- SspeedMASK = 0x00000300, /* Speed Selection */
- SspeedSHIFT = 8,
- Sspeed10 = 0x00000000, /* 10Mb/s */
- Sspeed100 = 0x00000100, /* 100Mb/s */
- Sspeed1000 = 0x00000200, /* 1000Mb/s */
- Frcspd = 0x00000800, /* Force Speed */
- Frcdplx = 0x00001000, /* Force Duplex */
- SwdpinsloMASK = 0x003C0000, /* Software Defined Pins - lo nibble */
- SwdpinsloSHIFT = 18,
- SwdpioloMASK = 0x03C00000, /* Software Defined Pins - I or O */
- SwdpioloSHIFT = 22,
- Devrst = 0x04000000, /* Device Reset */
- Rfce = 0x08000000, /* Receive Flow Control Enable */
- Tfce = 0x10000000, /* Transmit Flow Control Enable */
- Vme = 0x40000000, /* VLAN Mode Enable */
-};
-
-/*
- * can't find Tckok nor Rbcok in any Intel docs,
- * but even 82543gc docs define Lanid.
- */
-enum { /* Status */
- Lu = 0x00000002, /* Link Up */
- Lanid = 0x0000000C, /* mask for Lan ID. (function id) */
-// Tckok = 0x00000004, /* Transmit clock is running */
-// Rbcok = 0x00000008, /* Receive clock is running */
- Txoff = 0x00000010, /* Transmission Paused */
- Tbimode = 0x00000020, /* TBI Mode Indication */
- SpeedMASK = 0x000000C0,
- Speed10 = 0x00000000, /* 10Mb/s */
- Speed100 = 0x00000040, /* 100Mb/s */
- Speed1000 = 0x00000080, /* 1000Mb/s */
- Mtxckok = 0x00000400, /* MTX clock is running */
- Pci66 = 0x00000800, /* PCI Bus speed indication */
- Bus64 = 0x00001000, /* PCI Bus width indication */
-};
-
-enum { /* Ctrl and Status */
- Fd = 0x00000001, /* Full-Duplex */
- AsdvMASK = 0x00000300,
- Asdv10 = 0x00000000, /* 10Mb/s */
- Asdv100 = 0x00000100, /* 100Mb/s */
- Asdv1000 = 0x00000200, /* 1000Mb/s */
-};
-
-enum { /* Eecd */
- Sk = 0x00000001, /* Clock input to the EEPROM */
- Cs = 0x00000002, /* Chip Select */
- Di = 0x00000004, /* Data Input to the EEPROM */
- Do = 0x00000008, /* Data Output from the EEPROM */
- Areq = 0x00000040, /* EEPROM Access Request */
- Agnt = 0x00000080, /* EEPROM Access Grant */
- Eepresent = 0x00000100, /* EEPROM Present */
- Eesz256 = 0x00000200, /* EEPROM is 256 words not 64 */
- Eeszaddr = 0x00000400, /* EEPROM size for 8254[17] */
- Spi = 0x00002000, /* EEPROM is SPI not Microwire */
-};
-
-enum { /* Ctrlext */
- Gpien = 0x0000000F, /* General Purpose Interrupt Enables */
- SwdpinshiMASK = 0x000000F0, /* Software Defined Pins - hi nibble */
- SwdpinshiSHIFT = 4,
- SwdpiohiMASK = 0x00000F00, /* Software Defined Pins - I or O */
- SwdpiohiSHIFT = 8,
- Asdchk = 0x00001000, /* ASD Check */
- Eerst = 0x00002000, /* EEPROM Reset */
- Ips = 0x00004000, /* Invert Power State */
- Spdbyps = 0x00008000, /* Speed Select Bypass */
-};
-
-enum { /* EEPROM content offsets */
- Ea = 0x00, /* Ethernet Address */
- Cf = 0x03, /* Compatibility Field */
- Pba = 0x08, /* Printed Board Assembly number */
- Icw1 = 0x0A, /* Initialization Control Word 1 */
- Sid = 0x0B, /* Subsystem ID */
- Svid = 0x0C, /* Subsystem Vendor ID */
- Did = 0x0D, /* Device ID */
- Vid = 0x0E, /* Vendor ID */
- Icw2 = 0x0F, /* Initialization Control Word 2 */
-};
-
-enum { /* Mdic */
- MDIdMASK = 0x0000FFFF, /* Data */
- MDIdSHIFT = 0,
- MDIrMASK = 0x001F0000, /* PHY Register Address */
- MDIrSHIFT = 16,
- MDIpMASK = 0x03E00000, /* PHY Address */
- MDIpSHIFT = 21,
- MDIwop = 0x04000000, /* Write Operation */
- MDIrop = 0x08000000, /* Read Operation */
- MDIready = 0x10000000, /* End of Transaction */
- MDIie = 0x20000000, /* Interrupt Enable */
- MDIe = 0x40000000, /* Error */
-};
-
-enum { /* Icr, Ics, Ims, Imc */
- Txdw = 0x00000001, /* Transmit Descriptor Written Back */
- Txqe = 0x00000002, /* Transmit Queue Empty */
- Lsc = 0x00000004, /* Link Status Change */
- Rxseq = 0x00000008, /* Receive Sequence Error */
- Rxdmt0 = 0x00000010, /* Rdesc Minimum Threshold Reached */
- Rxo = 0x00000040, /* Receiver Overrun */
- Rxt0 = 0x00000080, /* Receiver Timer Interrupt */
- Mdac = 0x00000200, /* MDIO Access Completed */
- Rxcfg = 0x00000400, /* Receiving /C/ ordered sets */
- Gpi0 = 0x00000800, /* General Purpose Interrupts */
- Gpi1 = 0x00001000,
- Gpi2 = 0x00002000,
- Gpi3 = 0x00004000,
-};
-
-/*
- * The Mdic register isn't implemented on the 82543GC,
- * the software defined pins are used instead.
- * These definitions work for the Intel PRO/1000 T Server Adapter.
- * The direction pin bits are read from the EEPROM.
- */
-enum {
- Mdd = ((1<<2)<<SwdpinsloSHIFT), /* data */
- Mddo = ((1<<2)<<SwdpioloSHIFT), /* pin direction */
- Mdc = ((1<<3)<<SwdpinsloSHIFT), /* clock */
- Mdco = ((1<<3)<<SwdpioloSHIFT), /* pin direction */
- Mdr = ((1<<0)<<SwdpinshiSHIFT), /* reset */
- Mdro = ((1<<0)<<SwdpiohiSHIFT), /* pin direction */
-};
-
-enum { /* Txcw */
- TxcwFd = 0x00000020, /* Full Duplex */
- TxcwHd = 0x00000040, /* Half Duplex */
- TxcwPauseMASK = 0x00000180, /* Pause */
- TxcwPauseSHIFT = 7,
- TxcwPs = (1<<TxcwPauseSHIFT), /* Pause Supported */
- TxcwAs = (2<<TxcwPauseSHIFT), /* Asymmetric FC desired */
- TxcwRfiMASK = 0x00003000, /* Remote Fault Indication */
- TxcwRfiSHIFT = 12,
- TxcwNpr = 0x00008000, /* Next Page Request */
- TxcwConfig = 0x40000000, /* Transmit COnfig Control */
- TxcwAne = 0x80000000, /* Auto-Negotiation Enable */
-};
-
-enum { /* Rctl */
- Rrst = 0x00000001, /* Receiver Software Reset */
- Ren = 0x00000002, /* Receiver Enable */
- Sbp = 0x00000004, /* Store Bad Packets */
- Upe = 0x00000008, /* Unicast Promiscuous Enable */
- Mpe = 0x00000010, /* Multicast Promiscuous Enable */
- Lpe = 0x00000020, /* Long Packet Reception Enable */
- LbmMASK = 0x000000C0, /* Loopback Mode */
- LbmOFF = 0x00000000, /* No Loopback */
- LbmTBI = 0x00000040, /* TBI Loopback */
- LbmMII = 0x00000080, /* GMII/MII Loopback */
- LbmXCVR = 0x000000C0, /* Transceiver Loopback */
- RdtmsMASK = 0x00000300, /* Rdesc Minimum Threshold Size */
- RdtmsHALF = 0x00000000, /* Threshold is 1/2 Rdlen */
- RdtmsQUARTER = 0x00000100, /* Threshold is 1/4 Rdlen */
- RdtmsEIGHTH = 0x00000200, /* Threshold is 1/8 Rdlen */
- MoMASK = 0x00003000, /* Multicast Offset */
- Bam = 0x00008000, /* Broadcast Accept Mode */
- BsizeMASK = 0x00030000, /* Receive Buffer Size */
- Bsize2048 = 0x00000000,
- Bsize1024 = 0x00010000,
- Bsize512 = 0x00020000,
- Bsize256 = 0x00030000,
- Vfe = 0x00040000, /* VLAN Filter Enable */
- Cfien = 0x00080000, /* Canonical Form Indicator Enable */
- Cfi = 0x00100000, /* Canonical Form Indicator value */
- Dpf = 0x00400000, /* Discard Pause Frames */
- Pmcf = 0x00800000, /* Pass MAC Control Frames */
- Bsex = 0x02000000, /* Buffer Size Extension */
- Secrc = 0x04000000, /* Strip CRC from incoming packet */
-};
-
-enum { /* Tctl */
- Trst = 0x00000001, /* Transmitter Software Reset */
- Ten = 0x00000002, /* Transmit Enable */
- Psp = 0x00000008, /* Pad Short Packets */
- CtMASK = 0x00000FF0, /* Collision Threshold */
- CtSHIFT = 4,
- ColdMASK = 0x003FF000, /* Collision Distance */
- ColdSHIFT = 12,
- Swxoff = 0x00400000, /* Sofware XOFF Transmission */
- Pbe = 0x00800000, /* Packet Burst Enable */
- Rtlc = 0x01000000, /* Re-transmit on Late Collision */
- Nrtu = 0x02000000, /* No Re-transmit on Underrrun */
-};
-
-enum { /* [RT]xdctl */
- PthreshMASK = 0x0000003F, /* Prefetch Threshold */
- PthreshSHIFT = 0,
- HthreshMASK = 0x00003F00, /* Host Threshold */
- HthreshSHIFT = 8,
- WthreshMASK = 0x003F0000, /* Writebacj Threshold */
- WthreshSHIFT = 16,
- Gran = 0x01000000, /* Granularity */
-};
-
-enum { /* Rxcsum */
- PcssMASK = 0x000000FF, /* Packet Checksum Start */
- PcssSHIFT = 0,
- Ipofl = 0x00000100, /* IP Checksum Off-load Enable */
- Tuofl = 0x00000200, /* TCP/UDP Checksum Off-load Enable */
-};
-
-enum { /* Manc */
- Arpen = 0x00002000, /* Enable ARP Request Filtering */
-};
-
-typedef struct Rdesc { /* Receive Descriptor */
- uint addr[2];
- ushort length;
- ushort checksum;
- uchar status;
- uchar errors;
- ushort special;
-} Rdesc;
-
-enum { /* Rdesc status */
- Rdd = 0x01, /* Descriptor Done */
- Reop = 0x02, /* End of Packet */
- Ixsm = 0x04, /* Ignore Checksum Indication */
- Vp = 0x08, /* Packet is 802.1Q (matched VET) */
- Tcpcs = 0x20, /* TCP Checksum Calculated on Packet */
- Ipcs = 0x40, /* IP Checksum Calculated on Packet */
- Pif = 0x80, /* Passed in-exact filter */
-};
-
-enum { /* Rdesc errors */
- Ce = 0x01, /* CRC Error or Alignment Error */
- Se = 0x02, /* Symbol Error */
- Seq = 0x04, /* Sequence Error */
- Cxe = 0x10, /* Carrier Extension Error */
- Tcpe = 0x20, /* TCP/UDP Checksum Error */
- Ipe = 0x40, /* IP Checksum Error */
- Rxe = 0x80, /* RX Data Error */
-};
-
-typedef struct Tdesc { /* Legacy+Normal Transmit Descriptor */
- uint addr[2];
- uint control; /* varies with descriptor type */
- uint status; /* varies with descriptor type */
-} Tdesc;
-
-enum { /* Tdesc control */
- LenMASK = 0x000FFFFF, /* Data/Packet Length Field */
- LenSHIFT = 0,
- DtypeCD = 0x00000000, /* Data Type 'Context Descriptor' */
- DtypeDD = 0x00100000, /* Data Type 'Data Descriptor' */
- PtypeTCP = 0x01000000, /* TCP/UDP Packet Type (CD) */
- Teop = 0x01000000, /* End of Packet (DD) */
- PtypeIP = 0x02000000, /* IP Packet Type (CD) */
- Ifcs = 0x02000000, /* Insert FCS (DD) */
- Tse = 0x04000000, /* TCP Segmentation Enable */
- Rs = 0x08000000, /* Report Status */
- Rps = 0x10000000, /* Report Status Sent */
- Dext = 0x20000000, /* Descriptor Extension */
- Vle = 0x40000000, /* VLAN Packet Enable */
- Ide = 0x80000000, /* Interrupt Delay Enable */
-};
-
-enum { /* Tdesc status */
- Tdd = 0x00000001, /* Descriptor Done */
- Ec = 0x00000002, /* Excess Collisions */
- Lc = 0x00000004, /* Late Collision */
- Tu = 0x00000008, /* Transmit Underrun */
- CssMASK = 0x0000FF00, /* Checksum Start Field */
- CssSHIFT = 8,
-};
-
-enum {
- Nrdesc = 32, /* multiple of 8 */
- Ntdesc = 8, /* multiple of 8 */
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Ctlr {
- int port;
- Pcidev* pcidev;
- Ctlr* next;
- int active;
- int id;
- int cls;
- ushort eeprom[0x40];
-
- int* nic;
- Lock imlock;
- int im; /* interrupt mask */
-
- Mii* mii;
-
- Lock slock;
- uint statistics[Nstatistics];
-
- uchar ra[Eaddrlen]; /* receive address */
- ulong mta[128]; /* multicast table array */
-
- Rdesc* rdba; /* receive descriptor base address */
- Block** rb; /* receive buffers */
- int rdh; /* receive descriptor head */
- int rdt; /* receive descriptor tail */
-
- Tdesc* tdba; /* transmit descriptor base address */
- Lock tdlock;
- Block** tb; /* transmit buffers */
- int tdh; /* transmit descriptor head */
- int tdt; /* transmit descriptor tail */
- int ett; /* early transmit threshold */
-
- int txcw;
- int fcrtl;
- int fcrth;
-
- /* bootstrap goo */
- Block* bqhead; /* transmission queue */
- Block* bqtail;
-} Ctlr;
-
-static Ctlr* ctlrhead;
-static Ctlr* ctlrtail;
-
-#define csr32r(c, r) (*((c)->nic+((r)/4)))
-#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
-
-static void
-igbeim(Ctlr* ctlr, int im)
-{
- ilock(&ctlr->imlock);
- ctlr->im |= im;
- csr32w(ctlr, Ims, ctlr->im);
- iunlock(&ctlr->imlock);
-}
-
-static void
-igbeattach(Ether* edev)
-{
- int ctl;
- Ctlr *ctlr;
-
- /*
- * To do here:
- * one-time stuff;
- * start off a kproc for link status change:
- * adjust queue length depending on speed;
- * flow control.
- * more needed here...
- */
- ctlr = edev->ctlr;
- igbeim(ctlr, 0);
- ctl = csr32r(ctlr, Rctl)|Ren;
- csr32w(ctlr, Rctl, ctl);
- ctl = csr32r(ctlr, Tctl)|Ten;
- csr32w(ctlr, Tctl, ctl);
-}
-
-static char* statistics[Nstatistics] = {
- "CRC Error",
- "Alignment Error",
- "Symbol Error",
- "RX Error",
- "Missed Packets",
- "Single Collision",
- "Excessive Collisions",
- "Multiple Collision",
- "Late Collisions",
- nil,
- "Collision",
- "Transmit Underrun",
- "Defer",
- "Transmit - No CRS",
- "Sequence Error",
- "Carrier Extension Error",
- "Receive Error Length",
- nil,
- "XON Received",
- "XON Transmitted",
- "XOFF Received",
- "XOFF Transmitted",
- "FC Received Unsupported",
- "Packets Received (64 Bytes)",
- "Packets Received (65-127 Bytes)",
- "Packets Received (128-255 Bytes)",
- "Packets Received (256-511 Bytes)",
- "Packets Received (512-1023 Bytes)",
- "Packets Received (1024-1522 Bytes)",
- "Good Packets Received",
- "Broadcast Packets Received",
- "Multicast Packets Received",
- "Good Packets Transmitted",
- nil,
- "Good Octets Received",
- nil,
- "Good Octets Transmitted",
- nil,
- nil,
- nil,
- "Receive No Buffers",
- "Receive Undersize",
- "Receive Fragment",
- "Receive Oversize",
- "Receive Jabber",
- nil,
- nil,
- nil,
- "Total Octets Received",
- nil,
- "Total Octets Transmitted",
- nil,
- "Total Packets Received",
- "Total Packets Transmitted",
- "Packets Transmitted (64 Bytes)",
- "Packets Transmitted (65-127 Bytes)",
- "Packets Transmitted (128-255 Bytes)",
- "Packets Transmitted (256-511 Bytes)",
- "Packets Transmitted (512-1023 Bytes)",
- "Packets Transmitted (1024-1522 Bytes)",
- "Multicast Packets Transmitted",
- "Broadcast Packets Transmitted",
- "TCP Segmentation Context Transmitted",
- "TCP Segmentation Context Fail",
-};
-
-static void
-txstart(Ether *edev)
-{
- int tdh, tdt, len, olen;
- Ctlr *ctlr = edev->ctlr;
- Block *bp;
- Tdesc *tdesc;
-
- /*
- * Try to fill the ring back up, moving buffers from the transmit q.
- */
- tdh = PREV(ctlr->tdh, Ntdesc);
- for(tdt = ctlr->tdt; tdt != tdh; tdt = NEXT(tdt, Ntdesc)){
- /* pull off the head of the transmission queue */
- if((bp = ctlr->bqhead) == nil) /* was qget(edev->oq) */
- break;
- ctlr->bqhead = bp->next;
- if (ctlr->bqtail == bp)
- ctlr->bqtail = nil;
- len = olen = BLEN(bp);
-
- /*
- * if packet is too short, make it longer rather than relying
- * on ethernet interface to pad it and complain so the caller
- * will get fixed. I don't think Psp is working right, or it's
- * getting cleared.
- */
- if (len < ETHERMINTU) {
- if (bp->rp + ETHERMINTU <= bp->lim)
- bp->wp = bp->rp + ETHERMINTU;
- else
- bp->wp = bp->lim;
- len = BLEN(bp);
- print("txstart: extended short pkt %d -> %d bytes\n",
- olen, len);
- }
-
- /* set up a descriptor for it */
- tdesc = &ctlr->tdba[tdt];
- tdesc->addr[0] = PCIWADDR(bp->rp);
- tdesc->addr[1] = 0;
- tdesc->control = /* Ide| */ Rs|Dext|Ifcs|Teop|DtypeDD|len;
- tdesc->status = 0;
-
- ctlr->tb[tdt] = bp;
- }
- ctlr->tdt = tdt;
- csr32w(ctlr, Tdt, tdt);
- igbeim(ctlr, Txdw);
-}
-
-static Block *
-fromringbuf(Ether *ether)
-{
- RingBuf *tb = ðer->tb[ether->ti];
- Block *bp = allocb(tb->len);
-
- memmove(bp->wp, tb->pkt, tb->len);
- memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
- bp->wp += tb->len;
- return bp;
-}
-
-static void
-igbetransmit(Ether* edev)
-{
- Block *bp;
- Ctlr *ctlr;
- Tdesc *tdesc;
- RingBuf *tb;
- int tdh;
-
- /*
- * For now there are no smarts here. Tuning comes later.
- */
- ctlr = edev->ctlr;
- ilock(&ctlr->tdlock);
-
- /*
- * Free any completed packets
- * - try to get the soft tdh to catch the tdt;
- * - if the packet had an underrun bump the threshold
- * - the Tu bit doesn't seem to ever be set, perhaps
- * because Rs mode is used?
- */
- tdh = ctlr->tdh;
- for(;;){
- tdesc = &ctlr->tdba[tdh];
- if(!(tdesc->status & Tdd))
- break;
- if(tdesc->status & Tu){
- ctlr->ett++;
- csr32w(ctlr, Ett, ctlr->ett);
- }
- tdesc->status = 0;
- if(ctlr->tb[tdh] != nil){
- freeb(ctlr->tb[tdh]);
- ctlr->tb[tdh] = nil;
- }
- tdh = NEXT(tdh, Ntdesc);
- }
- ctlr->tdh = tdh;
-
- /* copy packets from the software RingBuf to the transmission q */
- /* from boot ether83815.c */
- while((tb = &edev->tb[edev->ti])->owner == Interface){
- bp = fromringbuf(edev);
-
- /* put the buffer on the transmit queue */
- if(ctlr->bqhead)
- ctlr->bqtail->next = bp;
- else
- ctlr->bqhead = bp;
- ctlr->bqtail = bp;
-
- txstart(edev); /* kick transmitter */
- tb->owner = Host; /* give descriptor back */
-
- edev->ti = NEXT(edev->ti, edev->ntb);
- }
-
- iunlock(&ctlr->tdlock);
-}
-
-static void
-igbereplenish(Ctlr* ctlr)
-{
- int rdt;
- Block *bp;
- Rdesc *rdesc;
-
- rdt = ctlr->rdt;
- while(NEXT(rdt, Nrdesc) != ctlr->rdh){
- rdesc = &ctlr->rdba[rdt];
- if(ctlr->rb[rdt] != nil){
- /* nothing to do */
- }
- else if((bp = iallocb(2048)) != nil){
- ctlr->rb[rdt] = bp;
- rdesc->addr[0] = PCIWADDR(bp->rp);
- rdesc->addr[1] = 0;
- }
- else
- break;
- rdesc->status = 0;
-
- rdt = NEXT(rdt, Nrdesc);
- }
- ctlr->rdt = rdt;
- csr32w(ctlr, Rdt, rdt);
-}
-
-static void
-toringbuf(Ether *ether, Block *bp)
-{
- RingBuf *rb = ðer->rb[ether->ri];
-
- if (rb->owner == Interface) {
- rb->len = BLEN(bp);
- memmove(rb->pkt, bp->rp, rb->len);
- rb->owner = Host;
- ether->ri = NEXT(ether->ri, ether->nrb);
- }
- /* else no one is expecting packets from the network */
-}
-
-static void
-igbeinterrupt(Ureg*, void* arg)
-{
- Block *bp;
- Ctlr *ctlr;
- Ether *edev;
- Rdesc *rdesc;
- int icr, im, rdh, txdw = 0;
-
- edev = arg;
- ctlr = edev->ctlr;
-
- ilock(&ctlr->imlock);
- csr32w(ctlr, Imc, ~0);
- im = ctlr->im;
-
- for(icr = csr32r(ctlr, Icr); icr & ctlr->im; icr = csr32r(ctlr, Icr)){
- /*
- * Link status changed.
- */
- if(icr & (Rxseq|Lsc)){
- /*
- * should be more here...
- */
- }
-
- /*
- * Process any received packets.
- */
- rdh = ctlr->rdh;
- for(;;){
- rdesc = &ctlr->rdba[rdh];
- if(!(rdesc->status & Rdd))
- break;
- if ((rdesc->status & Reop) && rdesc->errors == 0) {
- bp = ctlr->rb[rdh];
- ctlr->rb[rdh] = nil;
- /*
- * it appears that the original 82543 needed
- * to have the Ethernet CRC excluded, but that
- * the newer chips do not?
- */
- bp->wp += rdesc->length /* -4 */;
- toringbuf(edev, bp);
- freeb(bp);
- } else if ((rdesc->status & Reop) && rdesc->errors)
- print("igbe: input packet error 0x%ux\n",
- rdesc->errors);
- rdesc->status = 0;
- rdh = NEXT(rdh, Nrdesc);
- }
- ctlr->rdh = rdh;
-
- if(icr & Rxdmt0)
- igbereplenish(ctlr);
- if(icr & Txdw){
- im &= ~Txdw;
- txdw++;
- }
- }
-
- ctlr->im = im;
- csr32w(ctlr, Ims, im);
- iunlock(&ctlr->imlock);
-
- if(txdw)
- igbetransmit(edev);
-}
-
-static int
-igbeinit(Ether* edev)
-{
- int csr, i, r, ctrl;
- MiiPhy *phy;
- Ctlr *ctlr;
-
- ctlr = edev->ctlr;
-
- /*
- * Set up the receive addresses.
- * There are 16 addresses. The first should be the MAC address.
- * The others are cleared and not marked valid (MS bit of Rah).
- */
- csr = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
- csr32w(ctlr, Ral, csr);
- csr = 0x80000000|(edev->ea[5]<<8)|edev->ea[4];
- csr32w(ctlr, Rah, csr);
- for(i = 1; i < 16; i++){
- csr32w(ctlr, Ral+i*8, 0);
- csr32w(ctlr, Rah+i*8, 0);
- }
-
- /*
- * Clear the Multicast Table Array.
- * It's a 4096 bit vector accessed as 128 32-bit registers.
- */
- for(i = 0; i < 128; i++)
- csr32w(ctlr, Mta+i*4, 0);
-
- /*
- * Receive initialisation.
- * Mostly defaults from the datasheet, will
- * need some tuning for performance:
- * Rctl descriptor mimimum threshold size
- * discard pause frames
- * strip CRC
- * Rdtr interrupt delay
- * Rxdctl all the thresholds
- */
- csr32w(ctlr, Rctl, 0);
-
- /*
- * Allocate the descriptor ring and load its
- * address and length into the NIC.
- */
- ctlr->rdba = xspanalloc(Nrdesc*sizeof(Rdesc), 128 /* was 16 */, 0);
- csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
- csr32w(ctlr, Rdbah, 0);
- csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc));
-
- /*
- * Initialise the ring head and tail pointers and
- * populate the ring with Blocks.
- * The datasheet says the tail pointer is set to beyond the last
- * descriptor hardware can process, which implies the initial
- * condition is Rdh == Rdt. However, experience shows Rdt must
- * always be 'behind' Rdh; the replenish routine ensures this.
- */
- ctlr->rdh = 0;
- csr32w(ctlr, Rdh, ctlr->rdh);
- ctlr->rdt = 0;
- csr32w(ctlr, Rdt, ctlr->rdt);
- ctlr->rb = malloc(sizeof(Block*)*Nrdesc);
- igbereplenish(ctlr);
-
- /*
- * Set up Rctl but don't enable receiver (yet).
- */
- csr32w(ctlr, Rdtr, 0);
- switch(ctlr->id){
- case i82540em:
- case i82540eplp:
- case i82541gi:
- case i82541gi2:
- case i82541pi:
- case i82546gb:
- case i82546eb:
- case i82547gi:
- csr32w(ctlr, Radv, 64);
- break;
- }
- csr32w(ctlr, Rxdctl, (8<<WthreshSHIFT)|(8<<HthreshSHIFT)|4);
- /*
- * Enable checksum offload.
- */
- csr32w(ctlr, Rxcsum, Tuofl|Ipofl|(ETHERHDRSIZE<<PcssSHIFT));
-
- csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF);
- igbeim(ctlr, Rxt0|Rxo|Rxdmt0|Rxseq);
-
- /*
- * Transmit initialisation.
- * Mostly defaults from the datasheet, will
- * need some tuning for performance. The normal mode will
- * be full-duplex and things to tune for half-duplex are
- * Tctl re-transmit on late collision
- * Tipg all IPG times
- * Tbt burst timer
- * Ait adaptive IFS throttle
- * and in general
- * Txdmac packet prefetching
- * Ett transmit early threshold
- * Tidv interrupt delay value
- * Txdctl all the thresholds
- */
- csr32w(ctlr, Tctl, (0x0F<<CtSHIFT)|Psp|(66<<ColdSHIFT)); /* Fd */
- switch(ctlr->id){
- default:
- r = 6;
- break;
- case i82543gc:
- case i82544ei:
- case i82547ei:
- case i82540em:
- case i82540eplp:
- case i82541gi:
- case i82541gi2:
- case i82541pi:
- case i82546gb:
- case i82546eb:
- case i82547gi:
- r = 8;
- break;
- }
- csr32w(ctlr, Tipg, (6<<20)|(8<<10)|r);
- csr32w(ctlr, Ait, 0);
- csr32w(ctlr, Txdmac, 0);
- csr32w(ctlr, Tidv, 128);
-
- /*
- * Allocate the descriptor ring and load its
- * address and length into the NIC.
- */
- ctlr->tdba = xspanalloc(Ntdesc*sizeof(Tdesc), 128 /* was 16 */, 0);
- csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
- csr32w(ctlr, Tdbah, 0);
- csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc));
-
- /*
- * Initialise the ring head and tail pointers.
- */
- ctlr->tdh = 0;
- csr32w(ctlr, Tdh, ctlr->tdh);
- ctlr->tdt = 0;
- csr32w(ctlr, Tdt, ctlr->tdt);
- ctlr->tb = malloc(sizeof(Block*)*Ntdesc);
-// ctlr->im |= Txqe|Txdw;
-
- r = (4<<WthreshSHIFT)|(4<<HthreshSHIFT)|(8<<PthreshSHIFT);
- switch(ctlr->id){
- default:
- break;
- case i82540em:
- case i82540eplp:
- case i82547gi:
- case i82541pi:
- case i82546gb:
- case i82546eb:
- case i82541gi:
- case i82541gi2:
- r = csr32r(ctlr, Txdctl);
- r &= ~WthreshMASK;
- r |= Gran|(4<<WthreshSHIFT);
-
- csr32w(ctlr, Tadv, 64);
- break;
- }
- csr32w(ctlr, Txdctl, r);
-
- r = csr32r(ctlr, Tctl);
- r |= Ten;
- csr32w(ctlr, Tctl, r);
-
- if(ctlr->mii == nil || ctlr->mii->curphy == nil) {
- print("igbe: no mii (yet)\n");
- return 0;
- }
- /* wait for the link to come up */
- if (miistatus(ctlr->mii) < 0)
- return -1;
- print("igbe: phy: ");
- phy = ctlr->mii->curphy;
- if (phy->fd)
- print("full duplex");
- else
- print("half duplex");
- print(", %d Mb/s\n", phy->speed);
-
- /*
- * Flow control.
- */
- ctrl = csr32r(ctlr, Ctrl);
- if(phy->rfc)
- ctrl |= Rfce;
- if(phy->tfc)
- ctrl |= Tfce;
- csr32w(ctlr, Ctrl, ctrl);
-
- return 0;
-}
-
-static int
-i82543mdior(Ctlr* ctlr, int n)
-{
- int ctrl, data, i, r;
-
- /*
- * Read n bits from the Management Data I/O Interface.
- */
- ctrl = csr32r(ctlr, Ctrl);
- r = (ctrl & ~Mddo)|Mdco;
- data = 0;
- for(i = n-1; i >= 0; i--){
- if(csr32r(ctlr, Ctrl) & Mdd)
- data |= (1<<i);
- csr32w(ctlr, Ctrl, Mdc|r);
- csr32w(ctlr, Ctrl, r);
- }
- csr32w(ctlr, Ctrl, ctrl);
-
- return data;
-}
-
-static int
-i82543mdiow(Ctlr* ctlr, int bits, int n)
-{
- int ctrl, i, r;
-
- /*
- * Write n bits to the Management Data I/O Interface.
- */
- ctrl = csr32r(ctlr, Ctrl);
- r = Mdco|Mddo|ctrl;
- for(i = n-1; i >= 0; i--){
- if(bits & (1<<i))
- r |= Mdd;
- else
- r &= ~Mdd;
- csr32w(ctlr, Ctrl, Mdc|r);
- csr32w(ctlr, Ctrl, r);
- }
- csr32w(ctlr, Ctrl, ctrl);
-
- return 0;
-}
-
-static int
-i82543miimir(Mii* mii, int pa, int ra)
-{
- int data;
- Ctlr *ctlr;
-
- ctlr = mii->ctlr;
-
- /*
- * MII Management Interface Read.
- *
- * Preamble;
- * ST+OP+PHYAD+REGAD;
- * TA + 16 data bits.
- */
- i82543mdiow(ctlr, 0xFFFFFFFF, 32);
- i82543mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
- data = i82543mdior(ctlr, 18);
-
- if(data & 0x10000)
- return -1;
-
- return data & 0xFFFF;
-}
-
-static int
-i82543miimiw(Mii* mii, int pa, int ra, int data)
-{
- Ctlr *ctlr;
-
- ctlr = mii->ctlr;
-
- /*
- * MII Management Interface Write.
- *
- * Preamble;
- * ST+OP+PHYAD+REGAD+TA + 16 data bits;
- * Z.
- */
- i82543mdiow(ctlr, 0xFFFFFFFF, 32);
- data &= 0xFFFF;
- data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
- i82543mdiow(ctlr, data, 32);
-
- return 0;
-}
-
-static int
-igbemiimir(Mii* mii, int pa, int ra)
-{
- Ctlr *ctlr;
- int mdic, timo;
-
- ctlr = mii->ctlr;
-
- csr32w(ctlr, Mdic, MDIrop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT));
- mdic = 0;
- for(timo = 64; timo; timo--){
- mdic = csr32r(ctlr, Mdic);
- if(mdic & (MDIe|MDIready))
- break;
- microdelay(1);
- }
-
- if((mdic & (MDIe|MDIready)) == MDIready)
- return mdic & 0xFFFF;
- return -1;
-}
-
-static int
-igbemiimiw(Mii* mii, int pa, int ra, int data)
-{
- Ctlr *ctlr;
- int mdic, timo;
-
- ctlr = mii->ctlr;
-
- data &= MDIdMASK;
- csr32w(ctlr, Mdic, MDIwop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT)|data);
- mdic = 0;
- for(timo = 64; timo; timo--){
- mdic = csr32r(ctlr, Mdic);
- if(mdic & (MDIe|MDIready))
- break;
- microdelay(1);
- }
- if((mdic & (MDIe|MDIready)) == MDIready)
- return 0;
- return -1;
-}
-
-static int
-igbemii(Ctlr* ctlr)
-{
- MiiPhy *phy = (MiiPhy *)1;
- int ctrl, p, r;
-
- USED(phy);
- r = csr32r(ctlr, Status);
- if(r & Tbimode)
- return -1;
- if((ctlr->mii = malloc(sizeof(Mii))) == nil)
- return -1;
- ctlr->mii->ctlr = ctlr;
-
- ctrl = csr32r(ctlr, Ctrl);
- ctrl |= Slu;
-
- switch(ctlr->id){
- case i82543gc:
- ctrl |= Frcdplx|Frcspd;
- csr32w(ctlr, Ctrl, ctrl);
-
- /*
- * The reset pin direction (Mdro) should already
- * be set from the EEPROM load.
- * If it's not set this configuration is unexpected
- * so bail.
- */
- r = csr32r(ctlr, Ctrlext);
- if(!(r & Mdro))
- return -1;
- csr32w(ctlr, Ctrlext, r);
- delay(20);
- r = csr32r(ctlr, Ctrlext);
- r &= ~Mdr;
- csr32w(ctlr, Ctrlext, r);
- delay(20);
- r = csr32r(ctlr, Ctrlext);
- r |= Mdr;
- csr32w(ctlr, Ctrlext, r);
- delay(20);
-
- ctlr->mii->mir = i82543miimir;
- ctlr->mii->miw = i82543miimiw;
- break;
- case i82544ei:
- case i82547ei:
- case i82540em:
- case i82540eplp:
- case i82547gi:
- case i82541gi:
- case i82541gi2:
- case i82541pi:
- case i82546gb:
- case i82546eb:
- ctrl &= ~(Frcdplx|Frcspd);
- csr32w(ctlr, Ctrl, ctrl);
- ctlr->mii->mir = igbemiimir;
- ctlr->mii->miw = igbemiimiw;
- break;
- default:
- free(ctlr->mii);
- ctlr->mii = nil;
- return -1;
- }
-
- if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
- if (0)
- print("phy trouble: phy = 0x%lux\n", (ulong)phy);
- free(ctlr->mii);
- ctlr->mii = nil;
- return -1;
- }
- if (Debug)
- print("oui %X phyno %d\n", phy->oui, phy->phyno);
- else
- USED(phy);
-
- /*
- * 8254X-specific PHY registers not in 802.3:
- * 0x10 PHY specific control
- * 0x14 extended PHY specific control
- * Set appropriate values then reset the PHY to have
- * changes noted.
- */
- switch(ctlr->id){
- case i82547gi:
- case i82541gi:
- case i82541gi2:
- case i82541pi:
- case i82546gb:
- case i82546eb:
- break;
- default:
- r = miimir(ctlr->mii, 16);
- r |= 0x0800; /* assert CRS on Tx */
- r |= 0x0060; /* auto-crossover all speeds */
- r |= 0x0002; /* polarity reversal enabled */
- miimiw(ctlr->mii, 16, r);
-
- r = miimir(ctlr->mii, 20);
- r |= 0x0070; /* +25MHz clock */
- r &= ~0x0F00;
- r |= 0x0100; /* 1x downshift */
- miimiw(ctlr->mii, 20, r);
-
- miireset(ctlr->mii);
- break;
- }
- p = 0;
- if(ctlr->txcw & TxcwPs)
- p |= AnaP;
- if(ctlr->txcw & TxcwAs)
- p |= AnaAP;
- miiane(ctlr->mii, ~0, p, ~0);
-
- return 0;
-}
-
-static int
-at93c46io(Ctlr* ctlr, char* op, int data)
-{
- char *lp, *p;
- int i, loop, eecd, r;
-
- eecd = csr32r(ctlr, Eecd);
-
- r = 0;
- loop = -1;
- lp = nil;
- for(p = op; *p != '\0'; p++){
- switch(*p){
- default:
- return -1;
- case ' ':
- continue;
- case ':': /* start of loop */
- loop = strtol(p+1, &lp, 0)-1;
- lp--;
- if(p == lp)
- loop = 7;
- p = lp;
- continue;
- case ';': /* end of loop */
- if(lp == nil)
- return -1;
- loop--;
- if(loop >= 0)
- p = lp;
- else
- lp = nil;
- continue;
- case 'C': /* assert clock */
- eecd |= Sk;
- break;
- case 'c': /* deassert clock */
- eecd &= ~Sk;
- break;
- case 'D': /* next bit in 'data' byte */
- if(loop < 0)
- return -1;
- if(data & (1<<loop))
- eecd |= Di;
- else
- eecd &= ~Di;
- break;
- case 'O': /* collect data output */
- i = (csr32r(ctlr, Eecd) & Do) != 0;
- if(loop >= 0)
- r |= (i<<loop);
- else
- r = i;
- continue;
- case 'I': /* assert data input */
- eecd |= Di;
- break;
- case 'i': /* deassert data input */
- eecd &= ~Di;
- break;
- case 'S': /* enable chip select */
- eecd |= Cs;
- break;
- case 's': /* disable chip select */
- eecd &= ~Cs;
- break;
- }
- csr32w(ctlr, Eecd, eecd);
- microdelay(50);
- }
- if(loop >= 0)
- return -1;
- return r;
-}
-
-static int
-at93c46r(Ctlr* ctlr)
-{
- ushort sum;
- char rop[20];
- int addr, areq, bits, data, eecd, i;
-
- eecd = csr32r(ctlr, Eecd);
- if(eecd & Spi){
- print("igbe: SPI EEPROM access not implemented\n");
- return 0;
- }
- if(eecd & (Eeszaddr|Eesz256))
- bits = 8;
- else
- bits = 6;
- sum = 0;
-
- switch(ctlr->id){
- default:
- areq = 0;
- break;
- case i82540em:
- case i82540eplp:
- case i82541gi:
- case i82541gi2:
- case i82541pi:
- case i82547gi:
- case i82546gb:
- case i82546eb:
- areq = 1;
- csr32w(ctlr, Eecd, eecd|Areq);
- for(i = 0; i < 1000; i++){
- if((eecd = csr32r(ctlr, Eecd)) & Agnt)
- break;
- microdelay(5);
- }
- if(!(eecd & Agnt)){
- print("igbe: not granted EEPROM access\n");
- goto release;
- }
- break;
- }
- snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
-
- for(addr = 0; addr < 0x40; addr++){
- /*
- * Read a word at address 'addr' from the Atmel AT93C46
- * 3-Wire Serial EEPROM or compatible. The EEPROM access is
- * controlled by 4 bits in Eecd. See the AT93C46 datasheet
- * for protocol details.
- */
- if(at93c46io(ctlr, rop, (0x06<<bits)|addr) != 0){
- print("igbe: can't set EEPROM address 0x%2.2X\n", addr);
- goto release;
- }
- data = at93c46io(ctlr, ":16COc;", 0);
- at93c46io(ctlr, "sic", 0);
- ctlr->eeprom[addr] = data;
- sum += data;
- if (Debug) {
- if(addr && ((addr & 0x07) == 0))
- print("\n");
- print(" %4.4ux", data);
- }
- }
- if (Debug)
- print("\n");
-release:
- if(areq)
- csr32w(ctlr, Eecd, eecd & ~Areq);
- return sum;
-}
-
-static void
-detach(Ctlr *ctlr)
-{
- int r;
-
- /*
- * Perform a device reset to get the chip back to the
- * power-on state, followed by an EEPROM reset to read
- * the defaults for some internal registers.
- */
- csr32w(ctlr, Imc, ~0);
- csr32w(ctlr, Rctl, 0);
- csr32w(ctlr, Tctl, 0);
-
- delay(20);
-
- csr32w(ctlr, Ctrl, Devrst);
- /* apparently needed on multi-GHz processors to avoid infinite loops */
- delay(1);
- while(csr32r(ctlr, Ctrl) & Devrst)
- ;
-
- csr32w(ctlr, Ctrlext, Eerst | csr32r(ctlr, Ctrlext));
- delay(1);
- while(csr32r(ctlr, Ctrlext) & Eerst)
- ;
-
- switch(ctlr->id){
- default:
- break;
- case i82540em:
- case i82540eplp:
- case i82541gi:
- case i82541gi2:
- case i82541pi:
- case i82547gi:
- case i82546gb:
- case i82546eb:
- r = csr32r(ctlr, Manc);
- r &= ~Arpen;
- csr32w(ctlr, Manc, r);
- break;
- }
-
- csr32w(ctlr, Imc, ~0);
- delay(1);
- while(csr32r(ctlr, Icr))
- ;
-}
-
-static void
-igbedetach(Ether *edev)
-{
- detach(edev->ctlr);
-}
-
-static void
-igbeshutdown(Ether* ether)
-{
-print("igbeshutdown\n");
- igbedetach(ether);
-}
-
-static int
-igbereset(Ctlr* ctlr)
-{
- int ctrl, i, pause, r, swdpio, txcw;
-
- detach(ctlr);
-
- /*
- * Read the EEPROM, validate the checksum
- * then get the device back to a power-on state.
- */
- r = at93c46r(ctlr);
- /* zero return means no SPI EEPROM access */
- if (r != 0 && r != 0xBABA){
- print("igbe: bad EEPROM checksum - 0x%4.4uX\n", r);
- return -1;
- }
-
- /*
- * Snarf and set up the receive addresses.
- * There are 16 addresses. The first should be the MAC address.
- * The others are cleared and not marked valid (MS bit of Rah).
- */
- if ((ctlr->id == i82546gb || ctlr->id == i82546eb) &&
- BUSFNO(ctlr->pcidev->tbdf) == 1)
- ctlr->eeprom[Ea+2] += 0x100; /* second interface */
- for(i = Ea; i < Eaddrlen/2; i++){
- ctlr->ra[2*i] = ctlr->eeprom[i];
- ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
- }
- /* lan id seems to vary on 82543gc; don't use it */
- if (ctlr->id != i82543gc) {
- r = (csr32r(ctlr, Status) & Lanid) >> 2;
- ctlr->ra[5] += r; /* ea ctlr[1] = ea ctlr[0]+1 */
- }
- r = (ctlr->ra[3]<<24)|(ctlr->ra[2]<<16)|(ctlr->ra[1]<<8)|ctlr->ra[0];
- csr32w(ctlr, Ral, r);
- r = 0x80000000|(ctlr->ra[5]<<8)|ctlr->ra[4];
- csr32w(ctlr, Rah, r);
- for(i = 1; i < 16; i++){
- csr32w(ctlr, Ral+i*8, 0);
- csr32w(ctlr, Rah+i*8, 0);
- }
-
- /*
- * Clear the Multicast Table Array.
- * It's a 4096 bit vector accessed as 128 32-bit registers.
- */
- memset(ctlr->mta, 0, sizeof(ctlr->mta));
- for(i = 0; i < 128; i++)
- csr32w(ctlr, Mta+i*4, 0);
-
- /*
- * Just in case the Eerst didn't load the defaults
- * (doesn't appear to fully on the 8243GC), do it manually.
- */
- if (ctlr->id == i82543gc) {
- txcw = csr32r(ctlr, Txcw);
- txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);
- ctrl = csr32r(ctlr, Ctrl);
- ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);
-
- if(ctlr->eeprom[Icw1] & 0x0400){
- ctrl |= Fd;
- txcw |= TxcwFd;
- }
- if(ctlr->eeprom[Icw1] & 0x0200)
- ctrl |= Lrst;
- if(ctlr->eeprom[Icw1] & 0x0010)
- ctrl |= Ilos;
- if(ctlr->eeprom[Icw1] & 0x0800)
- ctrl |= Frcspd;
- swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;
- ctrl |= swdpio<<SwdpioloSHIFT;
- csr32w(ctlr, Ctrl, ctrl);
-
- ctrl = csr32r(ctlr, Ctrlext);
- ctrl &= ~(Ips|SwdpiohiMASK);
- swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;
- if(ctlr->eeprom[Icw1] & 0x1000)
- ctrl |= Ips;
- ctrl |= swdpio<<SwdpiohiSHIFT;
- csr32w(ctlr, Ctrlext, ctrl);
-
- if(ctlr->eeprom[Icw2] & 0x0800)
- txcw |= TxcwAne;
- pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;
- txcw |= pause<<TxcwPauseSHIFT;
- switch(pause){
- default:
- ctlr->fcrtl = 0x00002000;
- ctlr->fcrth = 0x00004000;
- txcw |= TxcwAs|TxcwPs;
- break;
- case 0:
- ctlr->fcrtl = 0x00002000;
- ctlr->fcrth = 0x00004000;
- break;
- case 2:
- ctlr->fcrtl = 0;
- ctlr->fcrth = 0;
- txcw |= TxcwAs;
- break;
- }
- ctlr->txcw = txcw;
- csr32w(ctlr, Txcw, txcw);
- }
- /*
- * Flow control - values from the datasheet.
- */
- csr32w(ctlr, Fcal, 0x00C28001);
- csr32w(ctlr, Fcah, 0x00000100);
- csr32w(ctlr, Fct, 0x00008808);
- csr32w(ctlr, Fcttv, 0x00000100);
-
- csr32w(ctlr, Fcrtl, ctlr->fcrtl);
- csr32w(ctlr, Fcrth, ctlr->fcrth);
-
- ilock(&ctlr->imlock);
- csr32w(ctlr, Imc, ~0);
- ctlr->im = 0; /* was = Lsc, which hangs some controllers */
- csr32w(ctlr, Ims, ctlr->im);
- iunlock(&ctlr->imlock);
-
- if(!(csr32r(ctlr, Status) & Tbimode) && igbemii(ctlr) < 0) {
- print("igbe: igbemii failed\n");
- return -1;
- }
-
- return 0;
-}
-
-static void
-igbepci(void)
-{
- int port, cls;
- Pcidev *p;
- Ctlr *ctlr;
- static int first = 1;
-
- if (first)
- first = 0;
- else
- return;
-
- p = nil;
- while(p = pcimatch(p, 0, 0)){
- if(p->ccrb != 0x02 || p->ccru != 0)
- continue;
-
- switch((p->did<<16)|p->vid){
- case i82542:
- default:
- continue;
-
- case (0x1001<<16)|0x8086: /* Intel PRO/1000 F */
- break;
- case i82543gc:
- case i82544ei:
- case i82547ei:
- case i82540em:
- case i82540eplp:
- case i82547gi:
- case i82541gi:
- case i82541gi2:
- case i82541pi:
- case i82546gb:
- case i82546eb:
- break;
- }
-
- /* the 82547EI is on the CSA bus, whatever that is */
- port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
- if(port == 0){
- print("igbe: can't map %d @ 0x%8.8luX\n",
- p->mem[0].size, p->mem[0].bar);
- continue;
- }
-
- /*
- * from etherga620.c:
- * If PCI Write-and-Invalidate is enabled set the max write DMA
- * value to the host cache-line size (32 on Pentium or later).
- */
- if(p->pcr & MemWrInv){
- cls = pcicfgr8(p, PciCLS) * 4;
- if(cls != CACHELINESZ)
- pcicfgw8(p, PciCLS, CACHELINESZ/4);
- }
-
- cls = pcicfgr8(p, PciCLS);
- switch(cls){
- default:
- print("igbe: unexpected CLS - %d bytes\n",
- cls*sizeof(long));
- break;
- case 0x00:
- case 0xFF:
- /* alphapc 164lx returns 0 */
- print("igbe: unusable PciCLS: %d, using %d longs\n",
- cls, CACHELINESZ/sizeof(long));
- cls = CACHELINESZ/sizeof(long);
- pcicfgw8(p, PciCLS, cls);
- break;
- case 0x08:
- case 0x10:
- break;
- }
-
- ctlr = malloc(sizeof(Ctlr));
- ctlr->port = port;
- ctlr->pcidev = p;
- ctlr->id = (p->did<<16)|p->vid;
- ctlr->cls = cls*4;
- ctlr->nic = KADDR(ctlr->port);
- if (Debug)
- print("status0 %8.8uX\n", csr32r(ctlr, Status));
- if(igbereset(ctlr)){
- free(ctlr);
- continue;
- }
- if (Debug)
- print("status1 %8.8uX\n", csr32r(ctlr, Status));
- pcisetbme(p);
-
- if(ctlrhead != nil)
- ctlrtail->next = ctlr;
- else
- ctlrhead = ctlr;
- ctlrtail = ctlr;
- }
-}
-
-int
-igbepnp(Ether* edev)
-{
- int i;
- Ctlr *ctlr;
- uchar ea[Eaddrlen];
-
- if(ctlrhead == nil)
- igbepci();
-
- /*
- * Any adapter matches if no edev->port is supplied,
- * otherwise the ports must match.
- */
- for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
- if(ctlr->active)
- continue;
- if(edev->port == 0 || edev->port == ctlr->port){
- ctlr->active = 1;
- break;
- }
- }
- if(ctlr == nil)
- return -1;
-
- edev->ctlr = ctlr;
- edev->port = ctlr->port;
- edev->irq = ctlr->pcidev->intl;
- edev->tbdf = ctlr->pcidev->tbdf;
-// edev->mbps = 1000;
-
- /*
- * Check if the adapter's station address is to be overridden.
- * If not, read it from the EEPROM and set in ether->ea prior to
- * loading the station address in the hardware.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, edev->ea, Eaddrlen) == 0){
- for(i = 0; i < Eaddrlen/2; i++){
- edev->ea[2*i] = ctlr->eeprom[i];
- edev->ea[2*i+1] = ctlr->eeprom[i]>>8;
- }
- }
- igbeinit(edev);
-
- /*
- * Linkage to the generic ethernet driver.
- */
- edev->attach = igbeattach;
- edev->transmit = igbetransmit;
- edev->interrupt = igbeinterrupt;
- edev->detach = igbedetach;
-
- return 0;
-}
--- a/os/boot/pc/ethermii.c
+++ /dev/null
@@ -1,224 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-#include "ethermii.h"
-
-int
-mii(Mii* mii, int mask)
-{
- MiiPhy *miiphy;
- int bit, phyno, r, rmask;
-
- /*
- * Probe through mii for PHYs in mask;
- * return the mask of those found in the current probe.
- * If the PHY has not already been probed, update
- * the Mii information.
- */
- rmask = 0;
- for(phyno = 0; phyno < NMiiPhy; phyno++){
- bit = 1<<phyno;
- if(!(mask & bit))
- continue;
- if(mii->mask & bit){
- rmask |= bit;
- continue;
- }
- if(mii->mir(mii, phyno, Bmsr) == -1)
- continue;
- if((miiphy = malloc(sizeof(MiiPhy))) == nil)
- continue;
-
- miiphy->mii = mii;
- r = mii->mir(mii, phyno, Phyidr1);
- miiphy->oui = (r & 0x3FFF)<<6;
- r = mii->mir(mii, phyno, Phyidr2);
- miiphy->oui |= r>>10;
- miiphy->phyno = phyno;
-
- miiphy->anar = ~0;
- miiphy->fc = ~0;
- miiphy->mscr = ~0;
-
- mii->phy[phyno] = miiphy;
- if(mii->curphy == nil)
- mii->curphy = miiphy;
- mii->mask |= bit;
- mii->nphy++;
-
- rmask |= bit;
- }
- return rmask;
-}
-
-int
-miimir(Mii* mii, int r)
-{
- if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
- return -1;
- return mii->mir(mii, mii->curphy->phyno, r);
-}
-
-int
-miimiw(Mii* mii, int r, int data)
-{
- if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
- return -1;
- return mii->miw(mii, mii->curphy->phyno, r, data);
-}
-
-int
-miireset(Mii* mii)
-{
- int bmcr;
-
- if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
- return -1;
- bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
- bmcr |= BmcrR;
- mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
- microdelay(1);
-
- return 0;
-}
-
-int
-miiane(Mii* mii, int a, int p, int e)
-{
- int anar, bmsr, mscr, r, phyno;
-
- if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
- return -1;
- phyno = mii->curphy->phyno;
-
- bmsr = mii->mir(mii, phyno, Bmsr);
- if(!(bmsr & BmsrAna))
- return -1;
-
- if(a != ~0)
- anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
- else if(mii->curphy->anar != ~0)
- anar = mii->curphy->anar;
- else{
- anar = mii->mir(mii, phyno, Anar);
- anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
- if(bmsr & Bmsr10THD)
- anar |= Ana10HD;
- if(bmsr & Bmsr10TFD)
- anar |= Ana10FD;
- if(bmsr & Bmsr100TXHD)
- anar |= AnaTXHD;
- if(bmsr & Bmsr100TXFD)
- anar |= AnaTXFD;
- }
- mii->curphy->anar = anar;
-
- if(p != ~0)
- anar |= (AnaAP|AnaP) & p;
- else if(mii->curphy->fc != ~0)
- anar |= mii->curphy->fc;
- mii->curphy->fc = (AnaAP|AnaP) & anar;
-
- if(bmsr & BmsrEs){
- mscr = mii->mir(mii, phyno, Mscr);
- mscr &= ~(Mscr1000TFD|Mscr1000THD);
- if(e != ~0)
- mscr |= (Mscr1000TFD|Mscr1000THD) & e;
- else if(mii->curphy->mscr != ~0)
- mscr = mii->curphy->mscr;
- else{
- r = mii->mir(mii, phyno, Esr);
- if(r & Esr1000THD)
- mscr |= Mscr1000THD;
- if(r & Esr1000TFD)
- mscr |= Mscr1000TFD;
- }
- mii->curphy->mscr = mscr;
- mii->miw(mii, phyno, Mscr, mscr);
- }
- mii->miw(mii, phyno, Anar, anar);
-
- r = mii->mir(mii, phyno, Bmcr);
- if(!(r & BmcrR)){
- r |= BmcrAne|BmcrRan;
- mii->miw(mii, phyno, Bmcr, r);
- }
-
- return 0;
-}
-
-int
-miistatus(Mii* mii)
-{
- MiiPhy *phy;
- int anlpar, bmsr, p, r, phyno;
-
- if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
- return -1;
- phy = mii->curphy;
- phyno = phy->phyno;
-
- /*
- * Check Auto-Negotiation is complete and link is up.
- * (Read status twice as the Ls bit is sticky).
- */
- bmsr = mii->mir(mii, phyno, Bmsr);
- if(!(bmsr & (BmsrAnc|BmsrAna)))
- return -1;
-
- bmsr = mii->mir(mii, phyno, Bmsr);
- if(!(bmsr & BmsrLs)){
- phy->link = 0;
- return -1;
- }
-
- phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
- if(phy->mscr){
- r = mii->mir(mii, phyno, Mssr);
- if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
- phy->speed = 1000;
- phy->fd = 1;
- }
- else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
- phy->speed = 1000;
- }
-
- anlpar = mii->mir(mii, phyno, Anlpar);
- if(phy->speed == 0){
- r = phy->anar & anlpar;
- if(r & AnaTXFD){
- phy->speed = 100;
- phy->fd = 1;
- }
- else if(r & AnaTXHD)
- phy->speed = 100;
- else if(r & Ana10FD){
- phy->speed = 10;
- phy->fd = 1;
- }
- else if(r & Ana10HD)
- phy->speed = 10;
- }
- if(phy->speed == 0)
- return -1;
-
- if(phy->fd){
- p = phy->fc;
- r = anlpar & (AnaAP|AnaP);
- if(p == AnaAP && r == (AnaAP|AnaP))
- phy->tfc = 1;
- else if(p == (AnaAP|AnaP) && r == AnaAP)
- phy->rfc = 1;
- else if((p & AnaP) && (r & AnaP))
- phy->rfc = phy->tfc = 1;
- }
-
- phy->link = 1;
-
- return 0;
-}
--- a/os/boot/pc/ethermii.h
+++ /dev/null
@@ -1,116 +1,0 @@
-typedef struct Mii Mii;
-typedef struct MiiPhy MiiPhy;
-
-enum { /* registers */
- Bmcr = 0x00, /* Basic Mode Control */
- Bmsr = 0x01, /* Basic Mode Status */
- Phyidr1 = 0x02, /* PHY Identifier #1 */
- Phyidr2 = 0x03, /* PHY Identifier #2 */
- Anar = 0x04, /* Auto-Negotiation Advertisement */
- Anlpar = 0x05, /* AN Link Partner Ability */
- Aner = 0x06, /* AN Expansion */
- Annptr = 0x07, /* AN Next Page TX */
- Annprr = 0x08, /* AN Next Page RX */
- Mscr = 0x09, /* MASTER-SLAVE Control */
- Mssr = 0x0A, /* MASTER-SLAVE Status */
- Esr = 0x0F, /* Extended Status */
-
- NMiiPhyr = 32,
- NMiiPhy = 32,
-};
-
-enum { /* Bmcr */
- BmcrSs1 = 0x0040, /* Speed Select[1] */
- BmcrCte = 0x0080, /* Collision Test Enable */
- BmcrDm = 0x0100, /* Duplex Mode */
- BmcrRan = 0x0200, /* Restart Auto-Negotiation */
- BmcrI = 0x0400, /* Isolate */
- BmcrPd = 0x0800, /* Power Down */
- BmcrAne = 0x1000, /* Auto-Negotiation Enable */
- BmcrSs0 = 0x2000, /* Speed Select[0] */
- BmcrLe = 0x4000, /* Loopback Enable */
- BmcrR = 0x8000, /* Reset */
-};
-
-enum { /* Bmsr */
- BmsrEc = 0x0001, /* Extended Capability */
- BmsrJd = 0x0002, /* Jabber Detect */
- BmsrLs = 0x0004, /* Link Status */
- BmsrAna = 0x0008, /* Auto-Negotiation Ability */
- BmsrRf = 0x0010, /* Remote Fault */
- BmsrAnc = 0x0020, /* Auto-Negotiation Complete */
- BmsrPs = 0x0040, /* Preamble Suppression Capable */
- BmsrEs = 0x0100, /* Extended Status */
- Bmsr100T2HD = 0x0200, /* 100BASE-T2 HD Capable */
- Bmsr100T2FD = 0x0400, /* 100BASE-T2 FD Capable */
- Bmsr10THD = 0x0800, /* 100BASE-T HD Capable */
- Bmsr10TFD = 0x1000, /* 10BASE-T FD Capable */
- Bmsr100TXHD = 0x2000, /* 100BASE-TX HD Capable */
- Bmsr100TXFD = 0x4000, /* 100BASE-TX FD Capable */
- Bmsr100T4 = 0x8000, /* 100BASE-T4 Capable */
-};
-
-enum { /* Anar/Anlpar */
- Ana10HD = 0x0020, /* Advertise 10BASE-T */
- Ana10FD = 0x0040, /* Advertise 10BASE-T FD */
- AnaTXHD = 0x0080, /* Advertise 100BASE-TX */
- AnaTXFD = 0x0100, /* Advertise 100BASE-TX FD */
- AnaT4 = 0x0200, /* Advertise 100BASE-T4 */
- AnaP = 0x0400, /* Pause */
- AnaAP = 0x0800, /* Asymmetrical Pause */
- AnaRf = 0x2000, /* Remote Fault */
- AnaAck = 0x4000, /* Acknowledge */
- AnaNp = 0x8000, /* Next Page Indication */
-};
-
-enum { /* Mscr */
- Mscr1000THD = 0x0100, /* Advertise 1000BASE-T HD */
- Mscr1000TFD = 0x0200, /* Advertise 1000BASE-T FD */
-};
-
-enum { /* Mssr */
- Mssr1000THD = 0x0400, /* Link Partner 1000BASE-T HD able */
- Mssr1000TFD = 0x0800, /* Link Partner 1000BASE-T FD able */
-};
-
-enum { /* Esr */
- Esr1000THD = 0x1000, /* 1000BASE-T HD Capable */
- Esr1000TFD = 0x2000, /* 1000BASE-T FD Capable */
- Esr1000XHD = 0x4000, /* 1000BASE-X HD Capable */
- Esr1000XFD = 0x8000, /* 1000BASE-X FD Capable */
-};
-
-typedef struct Mii {
- Lock;
- int nphy;
- int mask;
- MiiPhy* phy[NMiiPhy];
- MiiPhy* curphy;
-
- void* ctlr;
- int (*mir)(Mii*, int, int);
- int (*miw)(Mii*, int, int, int);
-} Mii;
-
-typedef struct MiiPhy {
- Mii* mii;
- int oui;
- int phyno;
-
- int anar;
- int fc;
- int mscr;
-
- int link;
- int speed;
- int fd;
- int rfc;
- int tfc;
-};
-
-extern int mii(Mii*, int);
-extern int miiane(Mii*, int, int, int);
-extern int miimir(Mii*, int);
-extern int miimiw(Mii*, int, int);
-extern int miireset(Mii*);
-extern int miistatus(Mii*);
--- a/os/boot/pc/etherrhine.c
+++ /dev/null
@@ -1,657 +1,0 @@
-/*
- Via Rhine driver, written for VT6102.
- Uses the ethermii to control PHY.
-
- Currently always copies on both, tx and rx.
- rx side could be copy-free, and tx-side might be made
- (almost) copy-free by using (possibly) two descriptors (if it allows
- arbitrary tx lengths, which it should..): first for alignment and
- second for rest of the frame. Rx-part should be worth doing.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-typedef struct QLock { int r; } QLock;
-#define qlock(i) while(0)
-#define qunlock(i) while(0)
-#define iprint print
-
-#include "etherif.h"
-#include "ethermii.h"
-
-enum {
- Ntxd = 4,
- Nrxd = 4,
- Nwait = 50,
- BIGSTR = 8192,
-};
-
-typedef struct Desc Desc;
-typedef struct Ctlr Ctlr;
-
-struct Desc {
- ulong stat;
- ulong size;
- ulong addr;
- ulong next;
- char *buf;
- ulong pad[3];
-};
-
-struct Ctlr {
- Pcidev *pci;
- int attached;
- int txused;
- int txhead;
- int txtail;
- int rxtail;
- ulong port;
-
- Mii mii;
-
- Desc *txd; /* wants to be aligned on 16-byte boundary */
- Desc *rxd;
-
- QLock attachlck;
- Lock tlock;
-};
-
-#define ior8(c, r) (inb((c)->port+(r)))
-#define iow8(c, r, b) (outb((c)->port+(r), (int)(b)))
-#define ior16(c, r) (ins((c)->port+(r)))
-#define ior32(c, r) (inl((c)->port+(r)))
-#define iow16(c, r, w) (outs((c)->port+(r), (ushort)(w)))
-#define iow32(c, r, l) (outl((c)->port+(r), (ulong)(l)))
-
-/* names used everywhere else */
-#define csr8r ior8
-#define csr8w iow8
-#define csr16r ior16
-#define csr16w iow16
-#define csr32r ior32
-#define csr32w iow32
-
-enum Regs {
- Eaddr = 0x0,
- Rcr = 0x6,
- Tcr = 0x7,
- Cr = 0x8,
- Isr = 0xc,
- Imr = 0xe,
- McastAddr = 0x10,
- RxdAddr = 0x18,
- TxdAddr = 0x1C,
- Bcr0 = 0x6E, /* Bus Control */
- Bcr1 = 0x6F,
- RhineMiiPhy = 0x6C,
- RhineMiiSr = 0x6D,
- RhineMiiCr = 0x70,
- RhineMiiAddr = 0x71,
- RhineMiiData = 0x72,
- Eecsr = 0x74,
- ConfigB = 0x79,
- ConfigD = 0x7B,
- MiscCr = 0x80,
- HwSticky = 0x83,
- MiscIsr = 0x84,
- MiscImr = 0x86,
- WolCrSet = 0xA0,
- WolCfgSet = 0xA1,
- WolCgSet = 0xA3,
- WolCrClr = 0xA4,
- PwrCfgClr = 0xA5,
- WolCgClr = 0xA7,
-};
-
-enum { /* Rcr */
- Sep = 0x01, /* Accept Error Packets */
- Ar = 0x02, /* Accept Small Packets */
- Am = 0x04, /* Accept Multicast */
- Ab = 0x08, /* Accept Broadcast */
- RxBcast = Ab,
- Prom = 0x10, /* Accept Physical Address Packets */
- RxProm = Prom,
- RrftMASK = 0xE0, /* Receive FIFO Threshold */
- RrftSHIFT = 5,
- Rrft64 = 0<<RrftSHIFT,
- Rrft32 = 1<<RrftSHIFT,
- Rrft128 = 2<<RrftSHIFT,
- Rrft256 = 3<<RrftSHIFT,
- Rrft512 = 4<<RrftSHIFT,
- Rrft768 = 5<<RrftSHIFT,
- Rrft1024 = 6<<RrftSHIFT,
- RrftSAF = 7<<RrftSHIFT,
-};
-
-enum { /* Tcr */
- Lb0 = 0x02, /* Loopback Mode */
- Lb1 = 0x04,
- Ofset = 0x08, /* Back-off Priority Selection */
- RtsfMASK = 0xE0, /* Transmit FIFO Threshold */
- RtsfSHIFT = 5,
- Rtsf128 = 0<<RtsfSHIFT,
- Rtsf256 = 1<<RtsfSHIFT,
- Rtsf512 = 2<<RtsfSHIFT,
- Rtsf1024 = 3<<RtsfSHIFT,
- RtsfSAF = 7<<RtsfSHIFT,
-};
-
-enum Crbits {
- Init = 1<<0,
- Start = 1<<1,
- Stop = 1<<2,
- RxOn = 1<<3,
- TxOn = 1<<4,
- Tdmd = 1<<5,
- Rdmd = 1<<6,
- EarlyRx = 1<<8,
- Reserved0 = 1<<9,
- FullDuplex = 1<<10,
- NoAutoPoll = 1<<11,
- Reserved1 = 1<<12,
- Tdmd1 = 1<<13,
- Rdmd1 = 1<<14,
- Reset = 1<<15,
-};
-
-enum Isrbits {
- RxOk = 1<<0,
- TxOk = 1<<1,
- RxErr = 1<<2,
- TxErr = 1<<3,
- TxBufUdf = 1<<4,
- RxBufLinkErr = 1<<5,
- BusErr = 1<<6,
- CrcOvf = 1<<7,
- EarlyRxInt = 1<<8,
- TxFifoUdf = 1<<9,
- RxFifoOvf = 1<<10,
- TxPktRace = 1<<11,
- NoRxbuf = 1<<12,
- TxCollision = 1<<13,
- PortCh = 1<<14,
- GPInt = 1<<15,
-};
-
-enum { /* Bcr0 */
- DmaMASK = 0x07, /* DMA Length */
- DmaSHIFT = 0,
- Dma32 = 0<<DmaSHIFT,
- Dma64 = 1<<DmaSHIFT,
- Dma128 = 2<<DmaSHIFT,
- Dma256 = 3<<DmaSHIFT,
- Dma512 = 4<<DmaSHIFT,
- Dma1024 = 5<<DmaSHIFT,
- DmaSAF = 7<<DmaSHIFT,
- CrftMASK = 0x38, /* Rx FIFO Threshold */
- CrftSHIFT = 3,
- Crft64 = 1<<CrftSHIFT,
- Crft128 = 2<<CrftSHIFT,
- Crft256 = 3<<CrftSHIFT,
- Crft512 = 4<<CrftSHIFT,
- Crft1024 = 5<<CrftSHIFT,
- CrftSAF = 7<<CrftSHIFT,
- Extled = 0x40, /* Extra LED Support Control */
- Med2 = 0x80, /* Medium Select Control */
-};
-
-enum { /* Bcr1 */
- PotMASK = 0x07, /* Polling Timer Interval */
- PotSHIFT = 0,
- CtftMASK = 0x38, /* Tx FIFO Threshold */
- CtftSHIFT = 3,
- Ctft64 = 1<<CtftSHIFT,
- Ctft128 = 2<<CtftSHIFT,
- Ctft256 = 3<<CtftSHIFT,
- Ctft512 = 4<<CtftSHIFT,
- Ctft1024 = 5<<CtftSHIFT,
- CtftSAF = 7<<CtftSHIFT,
-};
-
-
-enum Eecsrbits {
- EeAutoLoad = 1<<5,
-};
-
-enum Descbits {
- OwnNic = 1<<31, /* stat */
- TxAbort = 1<<8, /* stat */
- TxError = 1<<15, /* stat */
- RxChainbuf = 1<<10, /* stat */
- RxChainStart = 1<<9, /* stat */
- RxChainEnd = 1<<8, /* stat */
- Chainbuf = 1<<15, /* size rx & tx*/
- TxDisableCrc = 1<<16, /* size */
- TxChainStart = 1<<21, /* size */
- TxChainEnd = 1<<22, /* size */
- TxInt = 1<<23, /* size */
-};
-
-enum RhineMiiCrbits {
- Mdc = 1<<0,
- Mdi = 1<<1,
- Mdo = 1<<2,
- Mdout = 1<<3,
- Mdpm = 1<<4,
- Wcmd = 1<<5,
- Rcmd = 1<<6,
- Mauto = 1<<7,
-};
-
-static void
-attach(Ether *edev)
-{
- Ctlr *ctlr;
- Desc *txd, *rxd, *td, *rd;
- Mii *mi;
- MiiPhy *phy;
- int i, s;
-
- ctlr = edev->ctlr;
- qlock(&ctlr->attachlck);
- if (ctlr->attached == 0) {
- txd = ctlr->txd;
- rxd = ctlr->rxd;
- for (i = 0; i < Ntxd; ++i) {
- td = &txd[i];
- td->next = PCIWADDR(&txd[(i+1) % Ntxd]);
- td->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0);
- td->addr = PCIWADDR(td->buf);
- td->size = 0;
- coherence();
- td->stat = 0;
- }
- for (i = 0; i < Nrxd; ++i) {
- rd = &rxd[i];
- rd->next = PCIWADDR(&rxd[(i+1) % Nrxd]);
- rd->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0);
- rd->addr = PCIWADDR(rd->buf);
- rd->size = sizeof(Etherpkt)+4;
- coherence();
- rd->stat = OwnNic;
- }
-
- ctlr->txhead = ctlr->txtail = ctlr->rxtail = 0;
- mi = &ctlr->mii;
- miistatus(mi);
- phy = mi->curphy;
- s = splhi();
- iow32(ctlr, TxdAddr, PCIWADDR(&txd[0]));
- iow32(ctlr, RxdAddr, PCIWADDR(&rxd[0]));
- iow16(ctlr, Cr, (phy->fd? FullDuplex: 0) | NoAutoPoll | TxOn |
- RxOn | Start | Rdmd);
- iow16(ctlr, Isr, 0xFFFF);
- iow16(ctlr, Imr, 0xFFFF);
- iow8(ctlr, MiscIsr, 0xFF);
- iow8(ctlr, MiscImr, ~(3<<5));
- splx(s);
- ctlr->attached = 1;
- }
- qunlock(&ctlr->attachlck);
-}
-
-static void
-txstart(Ether *edev)
-{
- Ctlr *ctlr;
- Desc *txd, *td;
- int i, txused, n;
- RingBuf *tb;
-
- ctlr = edev->ctlr;
- txd = ctlr->txd;
- i = ctlr->txhead;
- n = 0;
- for (txused = ctlr->txused; txused < Ntxd; txused++) {
- tb = &edev->tb[edev->ti];
- if(tb->owner != Interface)
- break;
-
- td = &txd[i];
- memmove(td->buf, tb->pkt, tb->len);
- /* could reduce number of intrs here */
- td->size = tb->len | TxChainStart | TxChainEnd | TxInt;
- coherence();
- td->stat = OwnNic;
- i = (i + 1) % Ntxd;
- n++;
-
- tb->owner = Host;
- edev->ti = NEXT(edev->ti, edev->ntb);
- }
- if (n)
- iow16(ctlr, Cr, ior16(ctlr, Cr) | Tdmd);
-
- ctlr->txhead = i;
- ctlr->txused = txused;
-}
-
-static void
-transmit(Ether *edev)
-{
- Ctlr *ctlr;
-
- ctlr = edev->ctlr;
- ilock(&ctlr->tlock);
- txstart(edev);
- iunlock(&ctlr->tlock);
-}
-
-static void
-txcomplete(Ether *edev)
-{
- Ctlr *ctlr;
- Desc *txd, *td;
- int i, txused;
- ulong stat;
-
- ctlr = edev->ctlr;
- txd = ctlr->txd;
- i = ctlr->txtail;
- for (txused = ctlr->txused; txused > 0; txused--) {
- td = &txd[i];
- stat = td->stat;
- if (stat & OwnNic)
- break;
- i = (i + 1) % Ntxd;
- }
- ctlr->txused = txused;
- ctlr->txtail = i;
-
- if (txused <= Ntxd/2)
- txstart(edev);
-}
-
-static void
-interrupt(Ureg *, void *arg)
-{
- Ether *edev;
- Ctlr *ctlr;
- RingBuf *rb;
- ushort isr, misr;
- ulong stat;
- Desc *rxd, *rd;
- int i, n, size;
-
- edev = (Ether*)arg;
- ctlr = edev->ctlr;
- iow16(ctlr, Imr, 0);
- isr = ior16(ctlr, Isr);
- iow16(ctlr, Isr, 0xFFFF);
- /* don't care about used defined intrs */
- misr = ior16(ctlr, MiscIsr) & ~(3<<5);
-
- if (isr & RxOk) {
- rxd = ctlr->rxd;
- i = ctlr->rxtail;
-
- n = 0;
- while ((rxd[i].stat & OwnNic) == 0) {
- rd = &rxd[i];
- stat = rd->stat;
- if (stat & 0xFF)
- iprint("rx: %lux\n", stat & 0xFF);
- size = ((rd->stat>>16) & (2048-1)) - 4;
-
- rb = &edev->rb[edev->ri];
- if(rb->owner == Interface){
- rb->owner = Host;
- rb->len = size;
- memmove(rb->pkt, rd->buf, size);
- edev->ri = NEXT(edev->ri, edev->nrb);
- }
-
- rd->size = sizeof(Etherpkt)+4;
- coherence();
- rd->stat = OwnNic;
- i = (i + 1) % Nrxd;
- n++;
- }
- if (n)
- iow16(ctlr, Cr, ior16(ctlr, Cr) | Rdmd);
- ctlr->rxtail = i;
- isr &= ~RxOk;
- }
- if (isr & TxOk) {
- txcomplete(edev);
- isr &= ~TxOk;
- }
- if (isr | misr)
- iprint("etherrhine: unhandled irq(s). isr:%x misr:%x\n",
- isr, misr);
- iow16(ctlr, Imr, 0xFFFF);
-}
-
-static int
-miiread(Mii *mii, int phy, int reg)
-{
- Ctlr *ctlr;
- int n;
-
- ctlr = mii->ctlr;
-
- n = Nwait;
- while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd))
- microdelay(1);
- if (n == Nwait)
- iprint("etherrhine: miiread: timeout\n");
-
- iow8(ctlr, RhineMiiCr, 0);
- iow8(ctlr, RhineMiiPhy, phy);
- iow8(ctlr, RhineMiiAddr, reg);
- iow8(ctlr, RhineMiiCr, Rcmd);
-
- n = Nwait;
- while (n-- && ior8(ctlr, RhineMiiCr) & Rcmd)
- microdelay(1);
- if (n == Nwait)
- iprint("etherrhine: miiread: timeout\n");
-
- return ior16(ctlr, RhineMiiData);
-}
-
-static int
-miiwrite(Mii *mii, int phy, int reg, int data)
-{
- int n;
- Ctlr *ctlr;
-
- ctlr = mii->ctlr;
-
- n = Nwait;
- while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd))
- microdelay(1);
- if (n == Nwait)
- iprint("etherrhine: miiwrite: timeout\n");
-
- iow8(ctlr, RhineMiiCr, 0);
- iow8(ctlr, RhineMiiPhy, phy);
- iow8(ctlr, RhineMiiAddr, reg);
- iow16(ctlr, RhineMiiData, data);
- iow8(ctlr, RhineMiiCr, Wcmd);
-
- n = Nwait;
- while (n-- && ior8(ctlr, RhineMiiCr) & Wcmd)
- microdelay(1);
- if (n == Nwait)
- iprint("etherrhine: miiwrite: timeout\n");
-
- return 0;
-}
-
-static void
-reset(Ctlr* ctlr)
-{
- int r, timeo;
-
- /*
- * Soft reset the controller.
- */
- csr16w(ctlr, Cr, Stop);
- csr16w(ctlr, Cr, Stop|Reset);
- for(timeo = 0; timeo < 10000; timeo++){
- if(!(csr16r(ctlr, Cr) & Reset))
- break;
- microdelay(1);
- }
- if(timeo >= 1000)
- return;
-
- /*
- * Load the MAC address into the PAR[01]
- * registers.
- */
- r = csr8r(ctlr, Eecsr);
- csr8w(ctlr, Eecsr, EeAutoLoad|r);
- for(timeo = 0; timeo < 100; timeo++){
- if(!(csr8r(ctlr, Cr) & EeAutoLoad))
- break;
- microdelay(1);
- }
- if(timeo >= 100)
- return;
-
- /*
- * Configure DMA and Rx/Tx thresholds.
- * If the Rx/Tx threshold bits in Bcr[01] are 0 then
- * the thresholds are determined by Rcr/Tcr.
- */
- r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK);
- csr8w(ctlr, Bcr0, r|Crft64|Dma64);
- r = csr8r(ctlr, Bcr1) & ~CtftMASK;
- csr8w(ctlr, Bcr1, r|Ctft64);
-
- r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep);
- csr8w(ctlr, Rcr, r|Ab|Am);
-
- r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0);
- csr8w(ctlr, Tcr, r);
-}
-
-static void
-detach(Ether* edev)
-{
- reset(edev->ctlr);
-}
-
-static void
-init(Ether *edev)
-{
- Ctlr *ctlr;
- int i;
-
- ctlr = edev->ctlr;
- ilock(&ctlr->tlock);
-
- pcisetbme(ctlr->pci);
- reset(ctlr);
-
- iow8(ctlr, Eecsr, ior8(ctlr, Eecsr) | EeAutoLoad);
- for (i = 0; i < Nwait; ++i) {
- if ((ior8(ctlr, Eecsr) & EeAutoLoad) == 0)
- break;
- delay(5);
- }
- if (i >= Nwait)
- iprint("etherrhine: eeprom autoload timeout\n");
-
- for (i = 0; i < Eaddrlen; ++i)
- edev->ea[i] = ior8(ctlr, Eaddr + i);
-
- ctlr->mii.mir = miiread;
- ctlr->mii.miw = miiwrite;
- ctlr->mii.ctlr = ctlr;
-
- if(mii(&ctlr->mii, ~0) == 0 || ctlr->mii.curphy == nil){
- iunlock(&ctlr->tlock);
- iprint("etherrhine: init mii failure\n");
- return;
- }
- for (i = 0; i < NMiiPhy; ++i)
- if (ctlr->mii.phy[i])
- if (ctlr->mii.phy[i]->oui != 0xFFFFF)
- ctlr->mii.curphy = ctlr->mii.phy[i];
- miistatus(&ctlr->mii);
-
- iow16(ctlr, Imr, 0);
- iow16(ctlr, Cr, ior16(ctlr, Cr) | Stop);
-
- iunlock(&ctlr->tlock);
-}
-
-static Pcidev *
-rhinematch(ulong)
-{
- static int nrhines = 0;
- int nfound = 0;
- Pcidev *p = nil;
-
- while(p = pcimatch(p, 0x1106, 0)){
- if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
- continue;
- switch((p->did<<16)|p->vid){
- default:
- continue;
- case (0x3053<<16)|0x1106: /* Rhine III vt6105m (Soekris) */
- case (0x3065<<16)|0x1106: /* Rhine II */
- case (0x3106<<16)|0x1106: /* Rhine III */
- if (++nfound > nrhines) {
- nrhines++;
- return p;
- }
- break;
- }
- }
- return p;
-}
-
-int
-rhinepnp(Ether *edev)
-{
- Pcidev *p;
- Ctlr *ctlr;
- ulong port;
-
- if (edev->attach)
- return 0;
- p = rhinematch(edev->port);
- if (p == nil)
- return -1;
-
- port = p->mem[0].bar & ~1;
-
- if ((ctlr = malloc(sizeof(Ctlr))) == nil) {
- print("etherrhine: couldn't allocate memory for ctlr\n");
- return -1;
- }
- memset(ctlr, 0, sizeof(Ctlr));
- ctlr->txd = xspanalloc(sizeof(Desc) * Ntxd, 16, 0);
- ctlr->rxd = xspanalloc(sizeof(Desc) * Nrxd, 16, 0);
-
- ctlr->pci = p;
- ctlr->port = port;
-
- edev->ctlr = ctlr;
- edev->port = ctlr->port;
- edev->irq = p->intl;
- edev->tbdf = p->tbdf;
-
- init(edev);
-
- edev->attach = attach;
- edev->transmit = transmit;
- edev->interrupt = interrupt;
- edev->detach = detach;
-
- return 0;
-}
-
-int
-vt6102pnp(Ether *edev)
-{
- return rhinepnp(edev);
-}
--- a/os/boot/pc/fns.h
+++ /dev/null
@@ -1,175 +1,0 @@
-void aamloop(int);
-void addconf(char*, ...);
-Alarm* alarm(int, void (*)(Alarm*), void*);
-void alarminit(void);
-Block* allocb(int);
-void apminit(void);
-int biosboot(int dev, char *file, Boot *b);
-void* biosgetfspart(int i, char *name, int chatty);
-void biosinitdev(int i, char *name);
-int biosinit(void);
-void biosprintbootdevs(int dev);
-void biosprintdevs(int i);
-int bootpboot(int, char*, Boot*);
-int bootpass(Boot*, void*, int);
-void cancel(Alarm*);
-int cdinit(void);
-void check(char*);
-void cgascreenputs(char*, int);
-int cistrcmp(char*, char*);
-int cistrncmp(char*, char*, int);
-void changeconf(char*, ...);
-void checkalarms(void);
-void clockinit(void);
-#define coherence() mb386()
-void consdrain(void);
-void consinit(char*, char*);
-void consputs(char*, int);
-void delay(int);
-uchar* etheraddr(int);
-int etherinit(void);
-void etherinitdev(int, char*);
-void etherprintdevs(int);
-int etherrxflush(int);
-int etherrxpkt(int, Etherpkt*, int);
-int ethertxpkt(int, Etherpkt*, int, int);
-#define evenaddr(x) /* 386 doesn't care */
-int floppyboot(int, char*, Boot*);
-int floppyinit(void);
-void floppyinitdev(int, char*);
-void floppyprintdevs(int);
-void* floppygetfspart(int, char*, int);
-void freeb(Block*);
-char* getconf(char*);
-ulong getcr0(void);
-ulong getcr2(void);
-ulong getcr3(void);
-ulong getcr4(void);
-int getfields(char*, char**, int, char);
-int getstr(char*, char*, int, char*, int);
-int gunzip(uchar*, int, uchar*, int);
-void i8042a20(void);
-void i8042init(void);
-void i8042reset(void);
-void* ialloc(ulong, int);
-void idle(void);
-void ilock(Lock*);
-int inb(int);
-ushort ins(int);
-ulong inl(int);
-void insb(int, void*, int);
-void inss(int, void*, int);
-void insl(int, void*, int);
-#define ioalloc(addr, len, align, name) (addr)
-#define iofree(addr)
-void iunlock(Lock*);
-int isaconfig(char*, int, ISAConf*);
-void kbdinit(void);
-void kbdchar(int);
-void machinit(void);
-void mb386(void);
-void meminit(ulong);
-void microdelay(int);
-void mmuinit(void);
-#define nelem(x) (sizeof(x)/sizeof(x[0]))
-char* nextelem(char*, char*);
-uchar nvramread(int);
-void outb(int, int);
-void outs(int, ushort);
-void outl(int, ulong);
-void outsb(int, void*, int);
-void outss(int, void*, int);
-void outsl(int, void*, int);
-void panic(char*, ...);
-ulong pcibarsize(Pcidev*, int);
-int pcicfgr8(Pcidev*, int);
-int pcicfgr16(Pcidev*, int);
-int pcicfgr32(Pcidev*, int);
-void pcicfgw8(Pcidev*, int, int);
-void pcicfgw16(Pcidev*, int, int);
-void pcicfgw32(Pcidev*, int, int);
-void pciclrbme(Pcidev*);
-void pciclrioe(Pcidev*);
-void pciclrmwi(Pcidev*);
-int pcigetpms(Pcidev*);
-void pcihinv(Pcidev*);
-Pcidev* pcimatch(Pcidev*, int, int);
-uchar pciintl(Pcidev *);
-uchar pciipin(Pcidev *, uchar);
-void pcireset(void);
-void pcisetbme(Pcidev*);
-void pcisetioe(Pcidev*);
-void pcisetmwi(Pcidev*);
-int pcisetpms(Pcidev*, int);
-void pcmcisread(PCMslot*);
-int pcmcistuple(int, int, int, void*, int);
-PCMmap* pcmmap(int, ulong, int, int);
-int pcmspecial(char*, ISAConf*);
-void pcmspecialclose(int);
-void pcmunmap(int, PCMmap*);
-void ptcheck(char*);
-void putcr3(ulong);
-void putidt(Segdesc*, int);
-void* pxegetfspart(int, char*, int);
-void qinit(IOQ*);
-void readlsconf(void);
-void sdaddconf(int);
-int sdboot(int, char*, Boot*);
-void sdcheck(char*);
-void* sdgetfspart(int, char*, int);
-int sdinit(void);
-void sdinitdev(int, char*);
-void sdprintdevs(int);
-int sdsetpart(int, char*);
-void setvec(int, void (*)(Ureg*, void*), void*);
-int splhi(void);
-int spllo(void);
-void splx(int);
-void trapinit(void);
-void trapdisable(void);
-void trapenable(void);
-void uartdrain(void);
-void uartspecial(int, void (*)(int), int (*)(void), int);
-void uartputs(IOQ*, char*, int);
-ulong umbmalloc(ulong, int, int);
-void umbfree(ulong, int);
-ulong umbrwmalloc(ulong, int, int);
-void upafree(ulong, int);
-ulong upamalloc(ulong, int, int);
-void warp86(char*, ulong);
-void warp9(ulong);
-int x86cpuid(int*, int*);
-void* xspanalloc(ulong, int, ulong);
-
-#define malloc(n) ialloc(n, 0)
-#define mallocz(n, c) ialloc(n, 0)
-#define free(v) while(0)
-
-#define GSHORT(p) (((p)[1]<<8)|(p)[0])
-#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))
-#define GLSHORT(p) (((p)[0]<<8)|(p)[1])
-#define GLLONG(p) (((ulong)GLSHORT(p)<<16)|GLSHORT(p+2))
-#define PLLONG(p,v) (p)[3]=(v);(p)[2]=(v)>>8;(p)[1]=(v)>>16;(p)[0]=(v)>>24
-
-#define KADDR(a) ((void*)((ulong)(a)|KZERO))
-#define PADDR(a) ((ulong)(a)&~0xF0000000)
-
-#define HOWMANY(x, y) (((x)+((y)-1))/(y))
-#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
-
-
-#define xalloc(n) ialloc(n, 0)
-#define xfree(v) while(0)
-#define lock(l) if(l){/* nothing to do */;}else{/* nothing to do */;}
-#define unlock(l) if(l){/* nothing to do */;}else{/* nothing to do */;}
-
-int dmacount(int);
-int dmadone(int);
-void dmaend(int);
-void dmainit(int);
-long dmasetup(int, void*, long, int);
-
-extern int (*_pcmspecial)(char *, ISAConf *);
-extern void (*_pcmspecialclose)(int);
-extern void devi82365link(void);
-extern void devpccardlink(void);
--- a/os/boot/pc/fs.c
+++ /dev/null
@@ -1,94 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "fs.h"
-
-/*
- * grab next element from a path, return the pointer to unprocessed portion of
- * path.
- */
-char *
-nextelem(char *path, char *elem)
-{
- int i;
-
- while(*path == '/')
- path++;
- if(*path==0 || *path==' ')
- return 0;
- for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
- if(i==NAMELEN){
- print("name component too long\n");
- return 0;
- }
- *elem++ = *path++;
- }
- *elem = '\0';
- return path;
-}
-
-int
-fswalk(Fs *fs, char *path, File *f)
-{
- char element[NAMELEN];
-
- *f = fs->root;
- if(BADPTR(fs->walk))
- panic("fswalk bad pointer fs->walk");
-
- f->path = path;
- while(path = nextelem(path, element)){
- switch(fs->walk(f, element)){
- case -1:
- return -1;
- case 0:
- return 0;
- }
- }
- return 1;
-}
-
-/*
- * boot
- */
-int
-fsboot(Fs *fs, char *path, Boot *b)
-{
- File file;
- long n;
- static char buf[8192];
-
- switch(fswalk(fs, path, &file)){
- case -1:
- print("error walking to %s\n", path);
- return -1;
- case 0:
- print("%s not found\n", path);
- return -1;
- case 1:
- print("found %s\n", path);
- break;
- }
-
- while((n = fsread(&file, buf, sizeof buf)) > 0) {
- if(bootpass(b, buf, n) != MORE)
- break;
- }
-
- bootpass(b, nil, 0); /* tries boot */
- return -1;
-}
-
-int
-fsread(File *file, void *a, long n)
-{
- if(BADPTR(file->fs))
- panic("bad pointer file->fs in fsread");
- if(BADPTR(file->fs->read))
- panic("bad pointer file->fs->read in fsread");
- return file->fs->read(file, a, n);
-}
--- a/os/boot/pc/fs.h
+++ /dev/null
@@ -1,36 +1,0 @@
-typedef struct File File;
-typedef struct Fs Fs;
-
-#include "dosfs.h"
-#include "kfs.h"
-
-struct File{
- union{
- Dosfile dos;
- Kfsfile kfs;
- int walked;
- };
- Fs *fs;
- char *path;
-};
-
-struct Fs{
- union {
- Dos dos;
- Kfs kfs;
- };
- int dev; /* device id */
- long (*diskread)(Fs*, void*, long); /* disk read routine */
- vlong (*diskseek)(Fs*, vlong); /* disk seek routine */
- long (*read)(File*, void*, long);
- int (*walk)(File*, char*);
- File root;
-};
-
-extern int chatty;
-extern int dotini(Fs*);
-extern int fswalk(Fs*, char*, File*);
-extern int fsread(File*, void*, long);
-extern int fsboot(Fs*, char*, Boot*);
-
-#define BADPTR(x) ((ulong)x < 0x80000000)
--- a/os/boot/pc/getcallerpc.c
+++ /dev/null
@@ -1,8 +1,0 @@
-#include "u.h"
-#include "lib.h"
-
-ulong
-getcallerpc(void *x)
-{
- return (((ulong*)(x))[-1]);
-}
--- a/os/boot/pc/ilock.c
+++ /dev/null
@@ -1,24 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-void
-ilock(Lock *lk)
-{
- if(lk->locked != 0)
- panic("ilock");
- lk->spl = splhi();
- lk->locked = 1;
-}
-
-void
-iunlock(Lock *lk)
-{
- if(lk->locked != 1)
- panic("iunlock");
- lk->locked = 0;
- splx(lk->spl);
-}
--- a/os/boot/pc/inflate.c
+++ /dev/null
@@ -1,199 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include <flate.h>
-
-typedef struct Biobuf Biobuf;
-
-struct Biobuf
-{
- uchar *bp;
- uchar *p;
- uchar *ep;
-};
-
-static int header(Biobuf*);
-static int trailer(Biobuf*, Biobuf*);
-static int getc(void*);
-static ulong offset(Biobuf*);
-static int crcwrite(void *out, void *buf, int n);
-static ulong get4(Biobuf *b);
-static ulong Boffset(Biobuf *bp);
-
-/* GZIP flags */
-enum {
- Ftext= (1<<0),
- Fhcrc= (1<<1),
- Fextra= (1<<2),
- Fname= (1<<3),
- Fcomment= (1<<4),
-
- GZCRCPOLY = 0xedb88320UL,
-};
-
-static ulong *crctab;
-static ulong crc;
-
-extern void diff(char*); //XXX
-int
-gunzip(uchar *out, int outn, uchar *in, int inn)
-{
- Biobuf bin, bout;
- int err;
-
- crc = 0;
- crctab = mkcrctab(GZCRCPOLY);
- err = inflateinit();
- if(err != FlateOk)
- print("inflateinit failed: %s\n", flateerr(err));
-
- bin.bp = bin.p = in;
- bin.ep = in+inn;
- bout.bp = bout.p = out;
- bout.ep = out+outn;
-
- err = header(&bin);
- if(err != FlateOk)
- return err;
-
- err = inflate(&bout, crcwrite, &bin, getc);
- if(err != FlateOk)
- print("inflate failed: %s\n", flateerr(err));
-
- err = trailer(&bout, &bin);
- if(err != FlateOk)
- return err;
-
- return Boffset(&bout);
-}
-
-static int
-header(Biobuf *bin)
-{
- int i, flag;
-
- if(getc(bin) != 0x1f || getc(bin) != 0x8b){
- print("bad magic\n");
- return FlateCorrupted;
- }
- if(getc(bin) != 8){
- print("unknown compression type\n");
- return FlateCorrupted;
- }
-
- flag = getc(bin);
-
- /* mod time */
- get4(bin);
-
- /* extra flags */
- getc(bin);
-
- /* OS type */
- getc(bin);
-
- if(flag & Fextra)
- for(i=getc(bin); i>0; i--)
- getc(bin);
-
- /* name */
- if(flag&Fname)
- while(getc(bin) != 0)
- ;
-
- /* comment */
- if(flag&Fcomment)
- while(getc(bin) != 0)
- ;
-
- /* crc16 */
- if(flag&Fhcrc) {
- getc(bin);
- getc(bin);
- }
-
- return FlateOk;
-}
-
-static int
-trailer(Biobuf *bout, Biobuf *bin)
-{
- /* crc32 */
- if(crc != get4(bin)){
- print("crc mismatch\n");
- return FlateCorrupted;
- }
-
- /* length */
- if(get4(bin) != Boffset(bout)){
- print("bad output len\n");
- return FlateCorrupted;
- }
- return FlateOk;
-}
-
-static ulong
-get4(Biobuf *b)
-{
- ulong v;
- int i, c;
-
- v = 0;
- for(i = 0; i < 4; i++){
- c = getc(b);
- v |= c << (i * 8);
- }
- return v;
-}
-
-static int
-getc(void *in)
-{
- Biobuf *bp = in;
-
-// if((bp->p - bp->bp) % 10000 == 0)
-// print(".");
- if(bp->p >= bp->ep)
- return -1;
- return *bp->p++;
-}
-
-static ulong
-Boffset(Biobuf *bp)
-{
- return bp->p - bp->bp;
-}
-
-static int
-crcwrite(void *out, void *buf, int n)
-{
- Biobuf *bp;
- int nn;
-
- crc = blockcrc(crctab, crc, buf, n);
- bp = out;
- nn = n;
- if(nn > bp->ep-bp->p)
- nn = bp->ep-bp->p;
- if(nn > 0)
- memmove(bp->p, buf, nn);
- bp->p += n;
- return n;
-}
-
-#undef malloc
-#undef free
-
-void *
-malloc(ulong n)
-{
- return ialloc(n, 8);
-}
-
-void
-free(void *)
-{
-}
--- a/os/boot/pc/io.h
+++ /dev/null
@@ -1,317 +1,0 @@
-/*
- * programmable interrupt vectors (for the 8259's)
- */
-enum
-{
- Bptvec= 3, /* breakpoints */
- Mathemuvec= 7, /* math coprocessor emulation interrupt */
- Mathovervec= 9, /* math coprocessor overrun interrupt */
- Matherr1vec= 16, /* math coprocessor error interrupt */
- Faultvec= 14, /* page fault */
-
- Syscallvec= 64,
-
- VectorPIC = 24, /* external [A]PIC interrupts */
- VectorCLOCK = VectorPIC+0,
- VectorKBD = VectorPIC+1,
- VectorUART1 = VectorPIC+3,
- VectorUART0 = VectorPIC+4,
- VectorPCMCIA = VectorPIC+5,
- VectorFLOPPY = VectorPIC+6,
- VectorLPT = VectorPIC+7,
- VectorIRQ7 = VectorPIC+7,
- VectorAUX = VectorPIC+12, /* PS/2 port */
- VectorIRQ13 = VectorPIC+13, /* coprocessor on x386 */
- VectorATA0 = VectorPIC+14,
- VectorATA1 = VectorPIC+15,
- MaxVectorPIC = VectorPIC+15,
-};
-
-enum {
- BusCBUS = 0, /* Corollary CBUS */
- BusCBUSII, /* Corollary CBUS II */
- BusEISA, /* Extended ISA */
- BusFUTURE, /* IEEE Futurebus */
- BusINTERN, /* Internal bus */
- BusISA, /* Industry Standard Architecture */
- BusMBI, /* Multibus I */
- BusMBII, /* Multibus II */
- BusMCA, /* Micro Channel Architecture */
- BusMPI, /* MPI */
- BusMPSA, /* MPSA */
- BusNUBUS, /* Apple Macintosh NuBus */
- BusPCI, /* Peripheral Component Interconnect */
- BusPCMCIA, /* PC Memory Card International Association */
- BusTC, /* DEC TurboChannel */
- BusVL, /* VESA Local bus */
- BusVME, /* VMEbus */
- BusXPRESS, /* Express System Bus */
-};
-
-#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
-#define BUSFNO(tbdf) (((tbdf)>>8)&0x07)
-#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F)
-#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF)
-#define BUSTYPE(tbdf) ((tbdf)>>24)
-#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00)
-#define BUSUNKNOWN (-1)
-
-enum {
- MaxEISA = 16,
- CfgEISA = 0xC80,
-};
-
-/*
- * PCI support code.
- */
-enum { /* type 0 and type 1 pre-defined header */
- PciVID = 0x00, /* vendor ID */
- PciDID = 0x02, /* device ID */
- PciPCR = 0x04, /* command */
- PciPSR = 0x06, /* status */
- PciRID = 0x08, /* revision ID */
- PciCCRp = 0x09, /* programming interface class code */
- PciCCRu = 0x0A, /* sub-class code */
- PciCCRb = 0x0B, /* base class code */
- PciCLS = 0x0C, /* cache line size */
- PciLTR = 0x0D, /* latency timer */
- PciHDT = 0x0E, /* header type */
- PciBST = 0x0F, /* BIST */
-
- PciBAR0 = 0x10, /* base address */
- PciBAR1 = 0x14,
-
- PciINTL = 0x3C, /* interrupt line */
- PciINTP = 0x3D, /* interrupt pin */
-};
-
-/* ccrb (base class code) values; controller types */
-enum {
- Pcibcpci1 = 0, /* pci 1.0; no class codes defined */
- Pcibcstore = 1, /* mass storage */
- Pcibcnet = 2, /* network */
- Pcibcdisp = 3, /* display */
- Pcibcmmedia = 4, /* multimedia */
- Pcibcmem = 5, /* memory */
- Pcibcbridge = 6, /* bridge */
- Pcibccomm = 7, /* simple comms (e.g., serial) */
- Pcibcbasesys = 8, /* base system */
- Pcibcinput = 9, /* input */
- Pcibcdock = 0xa, /* docking stations */
- Pcibcproc = 0xb, /* processors */
- Pcibcserial = 0xc, /* serial bus (e.g., USB) */
- Pcibcwireless = 0xd, /* wireless */
- Pcibcintell = 0xe, /* intelligent i/o */
- Pcibcsatcom = 0xf, /* satellite comms */
- Pcibccrypto = 0x10, /* encryption/decryption */
- Pcibcdacq = 0x11, /* data acquisition & signal proc. */
-};
-
-/* ccru (sub-class code) values; common cases only */
-enum {
- /* mass storage */
- Pciscscsi = 0, /* SCSI */
- Pciscide = 1, /* IDE (ATA) */
-
- /* network */
- Pciscether = 0, /* Ethernet */
-
- /* display */
- Pciscvga = 0, /* VGA */
- Pciscxga = 1, /* XGA */
- Pcisc3d = 2, /* 3D */
-
- /* bridges */
- Pcischostpci = 0, /* host/pci */
- Pciscpcicpci = 1, /* pci/pci */
-
- /* simple comms */
- Pciscserial = 0, /* 16450, etc. */
- Pciscmultiser = 1, /* multiport serial */
-
- /* serial bus */
- Pciscusb = 3, /* USB */
-};
-
-enum { /* type 0 pre-defined header */
- PciBAR2 = 0x18,
- PciBAR3 = 0x1C,
- PciBAR4 = 0x20,
- PciBAR5 = 0x24,
- PciCIS = 0x28, /* cardbus CIS pointer */
- PciSVID = 0x2C, /* subsystem vendor ID */
- PciSID = 0x2E, /* cardbus CIS pointer */
- PciEBAR0 = 0x30, /* expansion ROM base address */
- PciMGNT = 0x3E, /* burst period length */
- PciMLT = 0x3F, /* maximum latency between bursts */
-};
-
-enum { /* type 1 pre-defined header */
- PciPBN = 0x18, /* primary bus number */
- PciSBN = 0x19, /* secondary bus number */
- PciUBN = 0x1A, /* subordinate bus number */
- PciSLTR = 0x1B, /* secondary latency timer */
- PciIBR = 0x1C, /* I/O base */
- PciILR = 0x1D, /* I/O limit */
- PciSPSR = 0x1E, /* secondary status */
- PciMBR = 0x20, /* memory base */
- PciMLR = 0x22, /* memory limit */
- PciPMBR = 0x24, /* prefetchable memory base */
- PciPMLR = 0x26, /* prefetchable memory limit */
- PciPUBR = 0x28, /* prefetchable base upper 32 bits */
- PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
- PciIUBR = 0x30, /* I/O base upper 16 bits */
- PciIULR = 0x32, /* I/O limit upper 16 bits */
- PciEBAR1 = 0x28, /* expansion ROM base address */
- PciBCR = 0x3E, /* bridge control register */
-};
-
-enum { /* type 2 pre-defined header */
- PciCBExCA = 0x10,
- PciCBSPSR = 0x16,
- PciCBPBN = 0x18, /* primary bus number */
- PciCBSBN = 0x19, /* secondary bus number */
- PciCBUBN = 0x1A, /* subordinate bus number */
- PciCBSLTR = 0x1B, /* secondary latency timer */
- PciCBMBR0 = 0x1C,
- PciCBMLR0 = 0x20,
- PciCBMBR1 = 0x24,
- PciCBMLR1 = 0x28,
- PciCBIBR0 = 0x2C, /* I/O base */
- PciCBILR0 = 0x30, /* I/O limit */
- PciCBIBR1 = 0x34, /* I/O base */
- PciCBILR1 = 0x38, /* I/O limit */
- PciCBBCTL = 0x3E, /* Bridge control */
- PciCBSVID = 0x40, /* subsystem vendor ID */
- PciCBSID = 0x42, /* subsystem ID */
- PciCBLMBAR = 0x44, /* legacy mode base address */
-};
-
-typedef struct Pcisiz Pcisiz;
-struct Pcisiz
-{
- Pcidev* dev;
- int siz;
- int bar;
-};
-
-typedef struct Pcidev Pcidev;
-typedef struct Pcidev {
- int tbdf; /* type+bus+device+function */
- ushort vid; /* vendor ID */
- ushort did; /* device ID */
-
- ushort pcr;
-
- uchar rid;
- uchar ccrp;
- uchar ccru;
- uchar ccrb;
- uchar cls;
- uchar ltr;
-
- struct {
- ulong bar; /* base address */
- int size;
- } mem[6];
-
- struct {
- ulong bar;
- int size;
- } rom;
- uchar intl; /* interrupt line */
-
- Pcidev* list;
- Pcidev* link; /* next device on this bno */
-
- Pcidev* bridge; /* down a bus */
- struct {
- ulong bar;
- int size;
- } ioa, mema;
-
- int pmrb; /* power management register block */
-};
-
-#define PCIWINDOW 0
-#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)
-#define ISAWINDOW 0
-#define ISAWADDR(va) (PADDR(va)+ISAWINDOW)
-
-/*
- * PCMCIA support code.
- */
-typedef struct PCMslot PCMslot;
-typedef struct PCMconftab PCMconftab;
-
-/*
- * Map between ISA memory space and PCMCIA card memory space.
- */
-struct PCMmap {
- ulong ca; /* card address */
- ulong cea; /* card end address */
- ulong isa; /* ISA address */
- int len; /* length of the ISA area */
- int attr; /* attribute memory */
- int ref;
-};
-
-/* configuration table entry */
-struct PCMconftab
-{
- int index;
- ushort irqs; /* legal irqs */
- uchar irqtype;
- uchar bit16; /* true for 16 bit access */
- struct {
- ulong start;
- ulong len;
- } io[16];
- int nio;
- uchar vpp1;
- uchar vpp2;
- uchar memwait;
- ulong maxwait;
- ulong readywait;
- ulong otherwait;
-};
-
-/* a card slot */
-struct PCMslot
-{
- Lock;
- int ref;
-
- void *cp; /* controller for this slot */
- long memlen; /* memory length */
- uchar base; /* index register base */
- uchar slotno; /* slot number */
-
- /* status */
- uchar special; /* in use for a special device */
- uchar already; /* already inited */
- uchar occupied;
- uchar battery;
- uchar wrprot;
- uchar powered;
- uchar configed;
- uchar enabled;
- uchar busy;
-
- /* cis info */
- ulong msec; /* time of last slotinfo call */
- char verstr[512]; /* version string */
- int ncfg; /* number of configurations */
- struct {
- ushort cpresent; /* config registers present */
- ulong caddr; /* relative address of config registers */
- } cfg[8];
- int nctab; /* number of config table entries */
- PCMconftab ctab[8];
- PCMconftab *def; /* default conftab */
-
- /* memory maps */
- Lock mlock; /* lock down the maps */
- int time;
- PCMmap mmap[4]; /* maps, last is always for the kernel */
-};
--- a/os/boot/pc/ip.h
+++ /dev/null
@@ -1,100 +1,0 @@
-typedef struct Udphdr Udphdr;
-struct Udphdr
-{
- uchar d[6]; /* Ethernet destination */
- uchar s[6]; /* Ethernet source */
- uchar type[2]; /* Ethernet packet type */
-
- uchar vihl; /* Version and header length */
- uchar tos; /* Type of service */
- uchar length[2]; /* packet length */
- uchar id[2]; /* Identification */
- uchar frag[2]; /* Fragment information */
-
- /* Udp pseudo ip really starts here */
- uchar ttl;
- uchar udpproto; /* Protocol */
- uchar udpplen[2]; /* Header plus data length */
- uchar udpsrc[4]; /* Ip source */
- uchar udpdst[4]; /* Ip destination */
- uchar udpsport[2]; /* Source port */
- uchar udpdport[2]; /* Destination port */
- uchar udplen[2]; /* data length */
- uchar udpcksum[2]; /* Checksum */
-};
-
-typedef struct Etherhdr Etherhdr;
-struct Etherhdr
-{
- uchar d[6];
- uchar s[6];
- uchar type[2];
-
- /* Now we have the ip fields */
- uchar vihl; /* Version and header length */
- uchar tos; /* Type of service */
- uchar length[2]; /* packet length */
- uchar id[2]; /* Identification */
- uchar frag[2]; /* Fragment information */
- uchar ttl; /* Time to live */
- uchar proto; /* Protocol */
- uchar cksum[2]; /* Header checksum */
- uchar src[4]; /* Ip source */
- uchar dst[4]; /* Ip destination */
-};
-
-enum
-{
- IP_VER = 0x40,
- IP_HLEN = 0x05,
- UDP_EHSIZE = 22,
- UDP_PHDRSIZE = 12,
- UDP_HDRSIZE = 20,
- ETHER_HDR = 14,
- IP_UDPPROTO = 17,
- ET_IP = 0x800,
- Bcastip = 0xffffffff,
- BPportsrc = 68,
- BPportdst = 67,
- TFTPport = 69,
- Timeout = 5000, /* milliseconds */
- Bootrequest = 1,
- Bootreply = 2,
- Tftp_READ = 1,
- Tftp_WRITE = 2,
- Tftp_DATA = 3,
- Tftp_ACK = 4,
- Tftp_ERROR = 5,
- Segsize = 512,
- TFTPSZ = Segsize+10,
-};
-
-typedef struct Bootp Bootp;
-struct Bootp
-{
- uchar op; /* opcode */
- uchar htype; /* hardware type */
- uchar hlen; /* hardware address len */
- uchar hops; /* hops */
- uchar xid[4]; /* a random number */
- uchar secs[2]; /* elapsed since client started booting */
- uchar pad[2];
- uchar ciaddr[4]; /* client IP address (client tells server) */
- uchar yiaddr[4]; /* client IP address (server tells client) */
- uchar siaddr[4]; /* server IP address */
- uchar giaddr[4]; /* gateway IP address */
- uchar chaddr[16]; /* client hardware address */
- char sname[64]; /* server host name (optional) */
- char file[128]; /* boot file name */
- char vend[128]; /* vendor-specific goo */
-};
-
-typedef struct Netaddr Netaddr;
-struct Netaddr
-{
- ulong ip;
- ushort port;
- char ea[Eaddrlen];
-};
-
-extern int eipfmt(Fmt*);
--- a/os/boot/pc/kbd.c
+++ /dev/null
@@ -1,489 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-enum {
- Data= 0x60, /* data port */
-
- Status= 0x64, /* status port */
- Inready= 0x01, /* input character ready */
- Outbusy= 0x02, /* output busy */
- Sysflag= 0x04, /* system flag */
- Cmddata= 0x08, /* cmd==0, data==1 */
- Inhibit= 0x10, /* keyboard/mouse inhibited */
- Minready= 0x20, /* mouse character ready */
- Rtimeout= 0x40, /* general timeout */
- Parity= 0x80,
-
- Cmd= 0x64, /* command port (write only) */
-
- Spec= 0x80,
-
- PF= Spec|0x20, /* num pad function key */
- View= Spec|0x00, /* view (shift window up) */
- KF= Spec|0x40, /* function key */
- Shift= Spec|0x60,
- Break= Spec|0x61,
- Ctrl= Spec|0x62,
- Latin= Spec|0x63,
- Caps= Spec|0x64,
- Num= Spec|0x65,
- No= Spec|0x7F, /* no mapping */
-
- Home= KF|13,
- Up= KF|14,
- Pgup= KF|15,
- Print= KF|16,
- Left= View,
- Right= View,
- End= '\r',
- Down= View,
- Pgdown= View,
- Ins= KF|20,
- Del= 0x7F,
-};
-
-uchar kbtab[] =
-{
-[0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
-[0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
-[0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
-[0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
-[0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
-[0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
-[0x30] 'b', 'n', 'm', ',', '.', '/', Shift, No,
-[0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
-[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
-[0x48] No, No, No, No, No, No, No, No,
-[0x50] No, No, No, No, No, No, No, KF|11,
-[0x58] KF|12, No, No, No, No, No, No, No,
-};
-
-uchar kbtabshift[] =
-{
-[0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
-[0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
-[0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
-[0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
-[0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
-[0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
-[0x30] 'B', 'N', 'M', '<', '>', '?', Shift, No,
-[0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
-[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
-[0x48] No, No, No, No, No, No, No, No,
-[0x50] No, No, No, No, No, No, No, KF|11,
-[0x58] KF|12, No, No, No, No, No, No, No,
-};
-
-uchar kbtabesc1[] =
-{
-[0x00] No, No, No, No, No, No, No, No,
-[0x08] No, No, No, No, No, No, No, No,
-[0x10] No, No, No, No, No, No, No, No,
-[0x18] No, No, No, No, No, Ctrl, No, No,
-[0x20] No, No, No, No, No, No, No, No,
-[0x28] No, No, No, No, No, No, No, No,
-[0x30] No, No, No, No, No, No, No, Print,
-[0x38] Latin, No, No, No, No, No, No, No,
-[0x40] No, No, No, No, No, No, Break, Home,
-[0x48] Up, Pgup, No, Down, No, Right, No, End,
-[0x50] Left, Pgdown, Ins, Del, No, No, No, No,
-[0x58] No, No, No, No, No, No, No, No,
-};
-
-struct latin
-{
- uchar l;
- char c[2];
-}latintab[] = {
- L'¡', "!!", /* spanish initial ! */
- L'¢', "c|", /* cent */
- L'¢', "c$", /* cent */
- L'£', "l$", /* pound sterling */
- L'¤', "g$", /* general currency */
- L'¥', "y$", /* yen */
- L'¥', "j$", /* yen */
- L'¦', "||", /* broken vertical bar */
- L'§', "SS", /* section symbol */
- L'¨', "\"\"", /* dieresis */
- L'©', "cr", /* copyright */
- L'©', "cO", /* copyright */
- L'ª', "sa", /* super a, feminine ordinal */
- L'«', "<<", /* left angle quotation */
- L'¬', "no", /* not sign, hooked overbar */
- L'', "--", /* soft hyphen */
- L'®', "rg", /* registered trademark */
- L'¯', "__", /* macron */
- L'°', "s0", /* degree (sup o) */
- L'±', "+-", /* plus-minus */
- L'²', "s2", /* sup 2 */
- L'³', "s3", /* sup 3 */
- L'´', "''", /* grave accent */
- L'µ', "mu", /* mu */
- L'¶', "pg", /* paragraph (pilcrow) */
- L'·', "..", /* centered . */
- L'¸', ",,", /* cedilla */
- L'¹', "s1", /* sup 1 */
- L'º', "so", /* sup o */
- L'»', ">>", /* right angle quotation */
- L'¼', "14", /* 1/4 */
- L'½', "12", /* 1/2 */
- L'¾', "34", /* 3/4 */
- L'¿', "??", /* spanish initial ? */
- L'À', "A`", /* A grave */
- L'Á', "A'", /* A acute */
- L'Â', "A^", /* A circumflex */
- L'Ã', "A~", /* A tilde */
- L'Ä', "A\"", /* A dieresis */
- L'Ä', "A:", /* A dieresis */
- L'Å', "Ao", /* A circle */
- L'Å', "AO", /* A circle */
- L'Æ', "Ae", /* AE ligature */
- L'Æ', "AE", /* AE ligature */
- L'Ç', "C,", /* C cedilla */
- L'È', "E`", /* E grave */
- L'É', "E'", /* E acute */
- L'Ê', "E^", /* E circumflex */
- L'Ë', "E\"", /* E dieresis */
- L'Ë', "E:", /* E dieresis */
- L'Ì', "I`", /* I grave */
- L'Í', "I'", /* I acute */
- L'Î', "I^", /* I circumflex */
- L'Ï', "I\"", /* I dieresis */
- L'Ï', "I:", /* I dieresis */
- L'Ð', "D-", /* Eth */
- L'Ñ', "N~", /* N tilde */
- L'Ò', "O`", /* O grave */
- L'Ó', "O'", /* O acute */
- L'Ô', "O^", /* O circumflex */
- L'Õ', "O~", /* O tilde */
- L'Ö', "O\"", /* O dieresis */
- L'Ö', "O:", /* O dieresis */
- L'Ö', "OE", /* O dieresis */
- L'Ö', "Oe", /* O dieresis */
- L'×', "xx", /* times sign */
- L'Ø', "O/", /* O slash */
- L'Ù', "U`", /* U grave */
- L'Ú', "U'", /* U acute */
- L'Û', "U^", /* U circumflex */
- L'Ü', "U\"", /* U dieresis */
- L'Ü', "U:", /* U dieresis */
- L'Ü', "UE", /* U dieresis */
- L'Ü', "Ue", /* U dieresis */
- L'Ý', "Y'", /* Y acute */
- L'Þ', "P|", /* Thorn */
- L'Þ', "Th", /* Thorn */
- L'Þ', "TH", /* Thorn */
- L'ß', "ss", /* sharp s */
- L'à', "a`", /* a grave */
- L'á', "a'", /* a acute */
- L'â', "a^", /* a circumflex */
- L'ã', "a~", /* a tilde */
- L'ä', "a\"", /* a dieresis */
- L'ä', "a:", /* a dieresis */
- L'å', "ao", /* a circle */
- L'æ', "ae", /* ae ligature */
- L'ç', "c,", /* c cedilla */
- L'è', "e`", /* e grave */
- L'é', "e'", /* e acute */
- L'ê', "e^", /* e circumflex */
- L'ë', "e\"", /* e dieresis */
- L'ë', "e:", /* e dieresis */
- L'ì', "i`", /* i grave */
- L'í', "i'", /* i acute */
- L'î', "i^", /* i circumflex */
- L'ï', "i\"", /* i dieresis */
- L'ï', "i:", /* i dieresis */
- L'ð', "d-", /* eth */
- L'ñ', "n~", /* n tilde */
- L'ò', "o`", /* o grave */
- L'ó', "o'", /* o acute */
- L'ô', "o^", /* o circumflex */
- L'õ', "o~", /* o tilde */
- L'ö', "o\"", /* o dieresis */
- L'ö', "o:", /* o dieresis */
- L'ö', "oe", /* o dieresis */
- L'÷', "-:", /* divide sign */
- L'ø', "o/", /* o slash */
- L'ù', "u`", /* u grave */
- L'ú', "u'", /* u acute */
- L'û', "u^", /* u circumflex */
- L'ü', "u\"", /* u dieresis */
- L'ü', "u:", /* u dieresis */
- L'ü', "ue", /* u dieresis */
- L'ý', "y'", /* y acute */
- L'þ', "th", /* thorn */
- L'þ', "p|", /* thorn */
- L'ÿ', "y\"", /* y dieresis */
- L'ÿ', "y:", /* y dieresis */
- 0, 0,
-};
-
-enum
-{
- /* controller command byte */
- Cscs1= (1<<6), /* scan code set 1 */
- Cmousedis= (1<<5), /* mouse disable */
- Ckbddis= (1<<4), /* kbd disable */
- Csf= (1<<2), /* system flag */
- Cmouseint= (1<<1), /* mouse interrupt enable */
- Ckbdint= (1<<0), /* kbd interrupt enable */
-};
-
-static uchar ccc;
-
-int
-latin1(int k1, int k2)
-{
- struct latin *l;
-
- for(l=latintab; l->l; l++)
- if(k1==l->c[0] && k2==l->c[1])
- return l->l;
- return 0;
-}
-
-/*
- * wait for output no longer busy
- */
-static int
-outready(void)
-{
- int tries;
-
- for(tries = 0; (inb(Status) & Outbusy); tries++){
- if(tries > 500)
- return -1;
- delay(2);
- }
- return 0;
-}
-
-/*
- * wait for input
- */
-static int
-inready(void)
-{
- int tries;
-
- for(tries = 0; !(inb(Status) & Inready); tries++){
- if(tries > 500)
- return -1;
- delay(2);
- }
- return 0;
-}
-
-/*
- * ask 8042 to enable the use of address bit 20
- */
-void
-i8042a20(void)
-{
- outready();
- outb(Cmd, 0xD1);
- outready();
- outb(Data, 0xDF);
- outready();
-}
-
-/*
- * ask 8042 to reset the machine
- */
-void
-i8042reset(void)
-{
- int i, x;
-#ifdef notdef
- ushort *s = (ushort*)(KZERO|0x472);
-
- *s = 0x1234; /* BIOS warm-boot flag */
-#endif /* notdef */
-
- outready();
- outb(Cmd, 0xFE); /* pulse reset line (means resend on AT&T machines) */
- outready();
-
- /*
- * Pulse it by hand (old somewhat reliable)
- */
- x = 0xDF;
- for(i = 0; i < 5; i++){
- x ^= 1;
- outready();
- outb(Cmd, 0xD1);
- outready();
- outb(Data, x); /* toggle reset */
- delay(100);
- }
-}
-
-/*
- * keyboard interrupt
- */
-static void
-i8042intr(Ureg*, void*)
-{
- int s, c;
- static int esc1, esc2;
- static int alt, caps, ctl, num, shift;
- static int lstate, k1, k2;
- int keyup;
-
- /*
- * get status
- */
- s = inb(Status);
- if(!(s&Inready))
- return;
-
- /*
- * get the character
- */
- c = inb(Data);
-
- /*
- * if it's the aux port...
- */
- if(s & Minready)
- return;
-
- /*
- * e0's is the first of a 2 character sequence
- */
- if(c == 0xe0){
- esc1 = 1;
- return;
- } else if(c == 0xe1){
- esc2 = 2;
- return;
- }
-
- keyup = c&0x80;
- c &= 0x7f;
- if(c > sizeof kbtab){
- c |= keyup;
- if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */
- print("unknown key %ux\n", c);
- return;
- }
-
- if(esc1){
- c = kbtabesc1[c];
- esc1 = 0;
- } else if(esc2){
- esc2--;
- return;
- } else if(shift)
- c = kbtabshift[c];
- else
- c = kbtab[c];
-
- if(caps && c<='z' && c>='a')
- c += 'A' - 'a';
-
- /*
- * keyup only important for shifts
- */
- if(keyup){
- switch(c){
- case Latin:
- alt = 0;
- break;
- case Shift:
- shift = 0;
- break;
- case Ctrl:
- ctl = 0;
- break;
- }
- return;
- }
-
- /*
- * normal character
- */
- if(!(c & Spec)){
- if(ctl){
- if(alt && c == Del)
- warp86("\nCtrl-Alt-Del\n", 0);
- c &= 0x1f;
- }
- switch(lstate){
- case 1:
- k1 = c;
- lstate = 2;
- return;
- case 2:
- k2 = c;
- lstate = 0;
- c = latin1(k1, k2);
- if(c == 0){
- kbdchar(k1);
- c = k2;
- }
- /* fall through */
- default:
- break;
- }
- } else {
- switch(c){
- case Caps:
- caps ^= 1;
- return;
- case Num:
- num ^= 1;
- return;
- case Shift:
- shift = 1;
- return;
- case Latin:
- alt = 1;
- lstate = 1;
- return;
- case Ctrl:
- ctl = 1;
- return;
- }
- }
- kbdchar(c);
-}
-
-static char *initfailed = "kbd init failed\n";
-
-void
-i8042init(void)
-{
- int c;
-
- /* wait for a quiescent controller */
- while((c = inb(Status)) & (Outbusy | Inready))
- if(c & Inready)
- inb(Data);
-
- /* get current controller command byte */
- outb(Cmd, 0x20);
- if(inready() < 0){
- print("kbdinit: can't read ccc\n");
- ccc = 0;
- } else
- ccc = inb(Data);
-
- /* enable kbd xfers and interrupts */
- ccc &= ~Ckbddis;
- ccc |= Csf | Ckbdint | Cscs1;
- if(outready() < 0)
- print(initfailed);
- outb(Cmd, 0x60);
- if(outready() < 0)
- print(initfailed);
- outb(Data, ccc);
- if(outready() < 0)
- print(initfailed);
-
- setvec(VectorKBD, i8042intr, 0);
-}
--- a/os/boot/pc/kfs.h
+++ /dev/null
@@ -1,57 +1,0 @@
-typedef struct Qid9p1 Qid9p1;
-typedef struct Dentry Dentry;
-typedef struct Kfsfile Kfsfile;
-typedef struct Kfs Kfs;
-
-/* DONT TOUCH, this is the disk structure */
-struct Qid9p1
-{
- long path;
- long version;
-};
-
-//#define NAMELEN 28 /* size of names */
-#define NDBLOCK 6 /* number of direct blocks in Dentry */
-
-/* DONT TOUCH, this is the disk structure */
-struct Dentry
-{
- char name[NAMELEN];
- short uid;
- short gid;
- ushort mode;
-/*
- #define DALLOC 0x8000
- #define DDIR 0x4000
- #define DAPND 0x2000
- #define DLOCK 0x1000
- #define DREAD 0x4
- #define DWRITE 0x2
- #define DEXEC 0x1
-*/
- Qid9p1 qid;
- long size;
- long dblock[NDBLOCK];
- long iblock;
- long diblock;
- long atime;
- long mtime;
-};
-
-struct Kfsfile
-{
- Dentry;
- long off;
-};
-
-struct Kfs
-{
- int RBUFSIZE;
- int BUFSIZE;
- int DIRPERBUF;
- int INDPERBUF;
- int INDPERBUF2;
-};
-
-extern int kfsinit(Fs*);
-
--- a/os/boot/pc/kfsboot.c
+++ /dev/null
@@ -1,256 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "fs.h"
-
-typedef struct Tag Tag;
-
-/*
- * tags on block
- */
-enum
-{
- Tnone = 0,
- Tsuper, /* the super block */
- Tdir, /* directory contents */
- Tind1, /* points to blocks */
- Tind2, /* points to Tind1 */
- Tfile, /* file contents */
- Tfree, /* in free list */
- Tbuck, /* cache fs bucket */
- Tvirgo, /* fake worm virgin bits */
- Tcache, /* cw cache things */
- MAXTAG
-};
-
-#define QPDIR 0x80000000L
-#define QPNONE 0
-#define QPROOT 1
-#define QPSUPER 2
-
-/* DONT TOUCH, this is the disk structure */
-struct Tag
-{
- short pad;
- short tag;
- long path;
-};
-
-static int thisblock = -1;
-static Fs *thisfs;
-static uchar *block;
-
-/*
- * we end up reading 2x or 3x the number of blocks we need to read.
- * this is okay because we need to read so few. if it wasn't okay, we could
- * have getblock return a pointer to a block, and keep a cache of the last
- * three read blocks. that would get us down to the minimum.
- * but this is fine.
- */
-static int
-getblock(Fs *fs, ulong n)
-{
- if(!block)
- block = malloc(16384);
-
- if(thisblock == n && thisfs == fs)
- return 0;
- thisblock = -1;
- if(fs->diskseek(fs, (vlong)n*fs->kfs.RBUFSIZE) < 0)
- return -1;
- if(fs->diskread(fs, block, fs->kfs.RBUFSIZE) != fs->kfs.RBUFSIZE)
- return -1;
- thisblock = n;
- thisfs = fs;
-
- return 1;
-}
-
-static int
-checktag(Fs *fs, uchar *block, int tag, long qpath)
-{
- Tag *t;
-
- t = (Tag*)(block+fs->kfs.BUFSIZE);
- if(t->tag != tag)
- return -1;
- if(qpath != QPNONE && (qpath&~QPDIR) != t->path)
- return -1;
- return 1;
-}
-
-static int
-getblocktag(Fs *fs, ulong n, int tag, long qpath)
-{
- if(getblock(fs, n) < 0 || checktag(fs, block, tag, qpath) < 0)
- return -1;
- return 1;
-}
-
-static int
-readinfo(Fs *fs)
-{
- fs->kfs.RBUFSIZE = 512;
- if(getblock(fs, 0) < 0)
- return -1;
-
- if(memcmp(block+256, "kfs wren device\n", 16) != 0)
- return -1;
-
- fs->kfs.RBUFSIZE = atoi((char*)block+256+16);
- if(!fs->kfs.RBUFSIZE || (fs->kfs.RBUFSIZE&(fs->kfs.RBUFSIZE-1)))
- return -1;
-
- fs->kfs.BUFSIZE = fs->kfs.RBUFSIZE - sizeof(Tag);
- fs->kfs.DIRPERBUF = fs->kfs.BUFSIZE / sizeof(Dentry);
- fs->kfs.INDPERBUF = fs->kfs.BUFSIZE / sizeof(long);
- fs->kfs.INDPERBUF2 = fs->kfs.INDPERBUF * fs->kfs.INDPERBUF;
-
- return 1;
-}
-
-static int
-readroot(Fs *fs, Dentry *d)
-{
- Dentry *d2;
-
- if(getblocktag(fs, 2, Tdir, QPROOT) < 0)
- return -1;
- d2 = (Dentry*)block;
- if(strcmp(d2->name, "/") != 0)
- return -1;
- *d = *(Dentry*)block;
- return 1;
-}
-
-static long
-indfetch(Fs *fs, long addr, long off, int tag, long path)
-{
- if(getblocktag(fs, addr, tag, path) < 0)
- return -1;
- return ((long*)block)[off];
-}
-
-static long
-rel2abs(Fs *fs, Dentry *d, long a)
-{
- long addr;
-
- if(a < NDBLOCK)
- return d->dblock[a];
- a -= NDBLOCK;
- if(a < fs->kfs.INDPERBUF){
- if(d->iblock == 0)
- return 0;
- addr = indfetch(fs, d->iblock, a, Tind1, d->qid.path);
- if(addr == 0)
- print("rel2abs indfetch 0 %s %ld\n", d->name, a);
- return addr;
- }
- a -= fs->kfs.INDPERBUF;
- if(a < fs->kfs.INDPERBUF2){
- if(d->diblock == 0)
- return 0;
- addr = indfetch(fs, d->diblock, a/fs->kfs.INDPERBUF, Tind2, d->qid.path);
- if(addr == 0){
- print("rel2abs indfetch 0 %s %ld\n", d->name, a/fs->kfs.INDPERBUF);
- return 0;
- }
- addr = indfetch(fs, addr, a%fs->kfs.INDPERBUF, Tind1, d->qid.path);
- return addr;
- }
- print("rel2abs trip ind %s %ld\n", d->name, a);
- return -1;
-}
-
-static int
-readdentry(Fs *fs, Dentry *d, int n, Dentry *e)
-{
- long addr, m;
-
- m = n/fs->kfs.DIRPERBUF;
- if((addr = rel2abs(fs, d, m)) <= 0)
- return addr;
- if(getblocktag(fs, addr, Tdir, d->qid.path) < 0)
- return -1;
- *e = *(Dentry*)(block+(n%fs->kfs.DIRPERBUF)*sizeof(Dentry));
- return 1;
-}
-
-static int
-getdatablock(Fs *fs, Dentry *d, long a)
-{
- long addr;
-
- if((addr = rel2abs(fs, d, a)) == 0)
- return -1;
- return getblocktag(fs, addr, Tfile, QPNONE);
-}
-
-static int
-walk(Fs *fs, Dentry *d, char *name, Dentry *e)
-{
- int i, n;
- Dentry x;
-
- for(i=0;; i++){
- if((n=readdentry(fs, d, i, &x)) <= 0)
- return n;
- if(strcmp(x.name, name) == 0){
- *e = x;
- return 1;
- }
- }
-}
-
-static long
-kfsread(File *f, void *va, long len)
-{
- uchar *a;
- long tot, off, o, n;
- Fs *fs;
-
- a = va;
- fs = f->fs;
- off = f->kfs.off;
- tot = 0;
- while(tot < len){
- if(getdatablock(fs, &f->kfs, off/fs->kfs.BUFSIZE) < 0)
- return -1;
- o = off%fs->kfs.BUFSIZE;
- n = fs->kfs.BUFSIZE - o;
- if(n > len-tot)
- n = len-tot;
- memmove(a+tot, block+o, n);
- off += n;
- tot += n;
- }
- f->kfs.off = off;
- return tot;
-}
-
-static int
-kfswalk(File *f, char *name)
-{
- int n;
-
- n = walk(f->fs, &f->kfs, name, &f->kfs);
- if(n < 0)
- return -1;
- f->kfs.off = 0;
- return 1;
-}
-
-int
-kfsinit(Fs *fs)
-{
- if(readinfo(fs) < 0 || readroot(fs, &fs->root.kfs) < 0)
- return -1;
-
- fs->root.fs = fs;
- fs->read = kfsread;
- fs->walk = kfswalk;
- return 0;
-}
--- a/os/boot/pc/l.s
+++ /dev/null
@@ -1,1084 +1,0 @@
-#include "x16.h"
-#include "mem.h"
-
-#define WRMSR BYTE $0x0F; BYTE $0x30 /* WRMSR, argument in AX/DX (lo/hi) */
-#define RDTSC BYTE $0x0F; BYTE $0x31 /* RDTSC, result in AX/DX (lo/hi) */
-#define RDMSR BYTE $0x0F; BYTE $0x32 /* RDMSR, result in AX/DX (lo/hi) */
-
-#ifdef PXE
-#define PDB 0x90000 /* temporary page tables (24KB) */
-#else
-#define PDB 0x08000
-#endif PXE
-
-#define NoScreenBlank 1
-/*#define ResetDiscs 1*/
-
-TEXT origin(SB), $0
- /*
- * This part of l.s is used only in the boot kernel.
- * It assumes that we are in real address mode, i.e.,
- * that we look like an 8086.
- *
- * Make sure the segments are reasonable.
- * If we were started directly from the BIOS
- * (i.e. no MS-DOS) then DS may not be
- * right.
- */
- MOVW CS, AX
- MOVW AX, DS
-
-#ifdef NoScreenBlank
- /*
- * Get the current video mode. If it isn't mode 3,
- * set text mode 3.
- * Well, no. Windows95 won't co-operate here so we have
- * to explicitly set mode 3.
- */
- XORL AX, AX
- MOVB $0x0F, AH
- INT $0x10 /* get current video mode in AL */
- CMPB AL, $03
- JEQ sayhello
-#endif /* NoScreenBlank */
- XORL AX, AX
- MOVB $0x03, AL
- INT $0x10 /* set video mode in AL */
-
-sayhello:
- LWI(hello(SB), rSI)
- CALL16(biosputs(SB))
-
-#ifdef ResetDiscs
- XORL AX, AX /* reset disc system */
- XORL DX, DX
- MOVB $0x80, DL
- INT $0x13
-#endif /* ResetDiscs */
-
-#ifdef DOTCOM
-/*
- * relocate everything to a half meg and jump there
- * - looks weird because it is being assembled by a 32 bit
- * assembler for a 16 bit world
- *
- * only b.com does this - not 9load
- */
- MOVL $0,BX
- INCL BX
- SHLL $15,BX
- MOVL BX,CX
- MOVW BX,ES
- MOVL $0,SI
- MOVL SI,DI
- CLD
- REP
- MOVSL
-
- /*
- * Jump to the copied image;
- * fix up the DS for the new location.
- */
- FARJUMP16(0x8000, _start8000(SB))
-
-TEXT _start8000(SB), $0
- MFSR(rCS, rAX) /* fix up DS, ES (0x8000) */
- MTSR(rAX, rDS)
- MTSR(rAX, rES)
-
- /*
- * If we are already in protected mode, have to get back
- * to real mode before trying any privileged operations
- * (like going into protected mode...).
- * Try to reset with a restart vector.
- */
- MFCR(rCR0, rAX) /* are we in protected mode? */
- ANDI(0x0001, rAX)
- JEQ _real
-
- CLR(rBX)
- MTSR(rBX, rES)
-
- LWI(0x0467, rBX) /* reset entry point */
- LWI(_start8000(SB), rAX) /* offset within segment */
- BYTE $0x26
- BYTE $0x89
- BYTE $0x07 /* MOVW AX, ES:[BX] */
- LBI(0x69, rBL)
- MFSR(rCS, rAX) /* segment */
- BYTE $0x26
- BYTE $0x89
- BYTE $0x07 /* MOVW AX, ES:[BX] */
-
- CLR(rDX)
- OUTPORTB(0x70, 0x8F)
- OUTPORTB(0x71, 0x0A)
-
- FARJUMP16(0xFFFF, 0x0000) /* reset */
-#endif /* DOTCOM */
-
-_real:
-
-/*
- * do things that need to be done in real mode.
- * the results get written to CONFADDR (0x1200)
- * in a series of <4-byte-magic-number><block-of-data>
- * the data length is dependent on the magic number.
- *
- * this gets parsed by conf.c:/^readlsconf
- *
- * N.B. CALL16 kills rDI, so we can't call anything.
- */
- LWI(0x0000, rAX)
- MTSR(rAX, rES)
- LWI(0x1200, rDI)
-
-/*
- * turn off interrupts
- */
- CLI
-
-/*
- * detect APM1.2 bios support
- */
- /* save DI */
- SW(rDI, rock(SB))
-
- /* disconnect anyone else */
- LWI(0x5304, rAX)
- LWI(0x0000, rBX)
- INT $0x15
-
- /* connect */
- CLC
- LWI(0x5303, rAX)
- LWI(0x0000, rBX)
- INT $0x15
- CLI /* apm put interrupts back? */
-
- JC noapm
-
- OPSIZE; PUSHR(rSI)
- OPSIZE; PUSHR(rBX)
- PUSHR(rDI)
- PUSHR(rDX)
- PUSHR(rCX)
- PUSHR(rAX)
-
- /* put DI, ES back */
- LW(rock(SB), rDI)
- LWI(0x0000, rAX)
- MTSR(rAX, rES)
-
- /*
- * write APM data. first four bytes are APM\0.
- */
- LWI(0x5041, rAX)
- STOSW
-
- LWI(0x004d, rAX)
- STOSW
-
- LWI(8, rCX)
-apmmove:
- POPR(rAX)
- STOSW
- LOOP apmmove
-
-noapm:
-
-/*
- * end of real mode hacks: write terminator, put ES back.
- */
- LWI(0x0000, rAX)
- STOSW
- STOSW
-
- MFSR(rCS, rAX) /* fix up ES (0x8000) */
- MTSR(rAX, rES)
-
-/*
- * goto protected mode
- */
-/* MOVL tgdtptr(SB),GDTR /**/
- BYTE $0x0f
- BYTE $0x01
- BYTE $0x16
- WORD $tgdtptr(SB)
-
- LWI(1, rAX)
- /* MOV AX,MSW */
- BYTE $0x0F; BYTE $0x01; BYTE $0xF0
-
-/*
- * clear prefetch queue (weird code to avoid optimizations)
- */
- /* JMP .+2 */
- BYTE $0xEB
- BYTE $0x00
-
-/*
- * set all segs
- */
-/* MOVW $SELECTOR(1, SELGDT, 0),AX /**/
- BYTE $0xc7
- BYTE $0xc0
- WORD $SELECTOR(1, SELGDT, 0)
- MOVW AX,DS
- MOVW AX,SS
- MOVW AX,ES
- MOVW AX,FS
- MOVW AX,GS
-
-/* JMPFAR SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
- BYTE $0x66
- BYTE $0xEA
- LONG $mode32bit-KZERO(SB)
- WORD $SELECTOR(2, SELGDT, 0)
-
-TEXT mode32bit(SB),$0
- /*
- * make a bottom level page table page that maps the first
- * 16 meg of physical memory
- */
- MOVL $PDB, DI /* clear 6 pages for the tables etc. */
- XORL AX, AX
- MOVL $(6*BY2PG), CX
- SHRL $2, CX
-
- CLD
- REP; STOSL
-
- MOVL $PDB, AX /* phys addr of temporary page table */
- MOVL $(4*1024),CX /* pte's per page */
- MOVL $((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
-setpte:
- MOVL BX,-4(AX)(CX*4)
- SUBL $(1<<PGSHIFT),BX
- LOOP setpte
-
- /*
- * make a top level page table page that maps the first
- * 16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
- */
- MOVL AX,BX
- ADDL $(4*BY2PG),AX
- ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX
- MOVL BX,0(AX)
- MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
- ADDL $BY2PG,BX
- MOVL BX,4(AX)
- MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
- ADDL $BY2PG,BX
- MOVL BX,8(AX)
- MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
- ADDL $BY2PG,BX
- MOVL BX,12(AX)
- MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
-
- /*
- * point processor to top level page & turn on paging
- *
- * this produces the apparently harmless "VMX|F(125):468 Dis 0x0:0x0"
- * message in the VMware log.
- */
- MOVL AX,CR3
- MOVL CR0,AX
- ORL $0X80000000,AX
- MOVL AX,CR0
-
- /*
- * use a jump to an absolute location to get the PC into
- * KZERO.
- */
- LEAL tokzero(SB),AX
- JMP* AX
-
-/*
- * When we load 9load from DOS, the bootstrap jumps
- * to the instruction right after `JUMP', which gets
- * us into kzero.
- *
- * The name prevents it from being optimized away.
- */
-TEXT jumplabel(SB), $0
- BYTE $'J'; BYTE $'U'; BYTE $'M'; BYTE $'P'
-
- LEAL tokzero(SB),AX
- JMP* AX
-
-TEXT tokzero(SB),$0
- /*
- * Clear BSS
- */
- LEAL edata(SB),SI
- MOVL SI,DI
- ADDL $4,DI
- MOVL $0,AX
- MOVL AX,(SI)
- LEAL end(SB),CX
- SUBL DI,CX
- SHRL $2,CX
- CLD
- REP
- MOVSL
-
- /*
- * stack and mach
- */
- MOVL $mach0(SB),SP
- MOVL SP,m(SB)
- MOVL $0,0(SP)
- ADDL $(MACHSIZE-4),SP /* start stack above machine struct */
-
- CALL main(SB)
-
-loop:
- JMP loop
-
-GLOBL mach0+0(SB), $MACHSIZE
-GLOBL m(SB), $4
-
-/*
- * gdt to get us to 32-bit/segmented/unpaged mode
- */
-TEXT tgdt(SB),$0
-
- /* null descriptor */
- LONG $0
- LONG $0
-
- /* data segment descriptor for 4 gigabytes (PL 0) */
- LONG $(0xFFFF)
- LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
-
- /* exec segment descriptor for 4 gigabytes (PL 0) */
- LONG $(0xFFFF)
- LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
-
- /* exec segment descriptor for 4 gigabytes (PL 0) 16-bit */
- LONG $(0xFFFF)
- LONG $(SEGG|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
-
-/*
- * pointer to initial gdt
- */
-TEXT tgdtptr(SB),$0
- WORD $(4*8)
- LONG $tgdt-KZERO(SB)
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT biosputs(SB), $0
- PUSHA
- CLR(rBX)
-_BIOSputs:
- LODSB
- ORB(rAL, rAL)
- JEQ _BIOSputsret
-
- LBI(0x0E, rAH)
- BIOSCALL(0x10)
- JMP _BIOSputs
-
-_BIOSputsret:
- POPA
- RET
-
-/*
- * input a byte
- */
-TEXT inb(SB),$0
-
- MOVL p+0(FP),DX
- XORL AX,AX
- INB
- RET
-
-/*
- * input a short from a port
- */
-TEXT ins(SB), $0
-
- MOVL p+0(FP), DX
- XORL AX, AX
- OPSIZE; INL
- RET
-
-/*
- * input a long from a port
- */
-TEXT inl(SB), $0
-
- MOVL p+0(FP), DX
- XORL AX, AX
- INL
- RET
-
-/*
- * output a byte
- */
-TEXT outb(SB),$0
-
- MOVL p+0(FP),DX
- MOVL b+4(FP),AX
- OUTB
- RET
-
-/*
- * output a short to a port
- */
-TEXT outs(SB), $0
- MOVL p+0(FP), DX
- MOVL s+4(FP), AX
- OPSIZE; OUTL
- RET
-
-/*
- * output a long to a port
- */
-TEXT outl(SB), $0
- MOVL p+0(FP), DX
- MOVL s+4(FP), AX
- OUTL
- RET
-
-/*
- * input a string of bytes from a port
- */
-TEXT insb(SB),$0
-
- MOVL p+0(FP),DX
- MOVL a+4(FP),DI
- MOVL c+8(FP),CX
- CLD; REP; INSB
- RET
-
-/*
- * input a string of shorts from a port
- */
-TEXT inss(SB),$0
- MOVL p+0(FP),DX
- MOVL a+4(FP),DI
- MOVL c+8(FP),CX
- CLD
- REP; OPSIZE; INSL
- RET
-
-/*
- * output a string of bytes to a port
- */
-TEXT outsb(SB),$0
-
- MOVL p+0(FP),DX
- MOVL a+4(FP),SI
- MOVL c+8(FP),CX
- CLD; REP; OUTSB
- RET
-
-/*
- * output a string of shorts to a port
- */
-TEXT outss(SB),$0
- MOVL p+0(FP),DX
- MOVL a+4(FP),SI
- MOVL c+8(FP),CX
- CLD
- REP; OPSIZE; OUTSL
- RET
-
-/*
- * input a string of longs from a port
- */
-TEXT insl(SB),$0
-
- MOVL p+0(FP),DX
- MOVL a+4(FP),DI
- MOVL c+8(FP),CX
- CLD; REP; INSL
- RET
-
-/*
- * output a string of longs to a port
- */
-TEXT outsl(SB),$0
-
- MOVL p+0(FP),DX
- MOVL a+4(FP),SI
- MOVL c+8(FP),CX
- CLD; REP; OUTSL
- RET
-
-/*
- * routines to load/read various system registers
- */
-GLOBL idtptr(SB),$6
-TEXT putidt(SB),$0 /* interrupt descriptor table */
- MOVL t+0(FP),AX
- MOVL AX,idtptr+2(SB)
- MOVL l+4(FP),AX
- MOVW AX,idtptr(SB)
- MOVL idtptr(SB),IDTR
- RET
-
-TEXT putcr3(SB),$0 /* top level page table pointer */
- MOVL t+0(FP),AX
- MOVL AX,CR3
- RET
-
-TEXT getcr0(SB),$0 /* coprocessor bits */
- MOVL CR0,AX
- RET
-
-TEXT getcr2(SB),$0 /* fault address */
- MOVL CR2,AX
- RET
-
-TEXT getcr3(SB),$0 /* page directory base */
- MOVL CR3,AX
- RET
-
-TEXT getcr4(SB), $0 /* CR4 - extensions */
- MOVL CR4, AX
- RET
-
-TEXT _cycles(SB), $0 /* time stamp counter */
- RDTSC
- MOVL vlong+0(FP), CX /* &vlong */
- MOVL AX, 0(CX) /* lo */
- MOVL DX, 4(CX) /* hi */
- RET
-
-TEXT rdmsr(SB), $0 /* model-specific register */
- MOVL index+0(FP), CX
- RDMSR
- MOVL vlong+4(FP), CX /* &vlong */
- MOVL AX, 0(CX) /* lo */
- MOVL DX, 4(CX) /* hi */
- RET
-
-TEXT wrmsr(SB), $0
- MOVL index+0(FP), CX
- MOVL lo+4(FP), AX
- MOVL hi+8(FP), DX
- WRMSR
- RET
-
-TEXT mb386(SB), $0
- POPL AX /* return PC */
- PUSHFL
- PUSHL CS
- PUSHL AX
- IRETL
-
-/*
- * special traps
- */
-TEXT intr0(SB),$0
- PUSHL $0
- PUSHL $0
- JMP intrcommon
-TEXT intr1(SB),$0
- PUSHL $0
- PUSHL $1
- JMP intrcommon
-TEXT intr2(SB),$0
- PUSHL $0
- PUSHL $2
- JMP intrcommon
-TEXT intr3(SB),$0
- PUSHL $0
- PUSHL $3
- JMP intrcommon
-TEXT intr4(SB),$0
- PUSHL $0
- PUSHL $4
- JMP intrcommon
-TEXT intr5(SB),$0
- PUSHL $0
- PUSHL $5
- JMP intrcommon
-TEXT intr6(SB),$0
- PUSHL $0
- PUSHL $6
- JMP intrcommon
-TEXT intr7(SB),$0
- PUSHL $0
- PUSHL $7
- JMP intrcommon
-TEXT intr8(SB),$0
- PUSHL $8
- JMP intrcommon
-TEXT intr9(SB),$0
- PUSHL $0
- PUSHL $9
- JMP intrcommon
-TEXT intr10(SB),$0
- PUSHL $10
- JMP intrcommon
-TEXT intr11(SB),$0
- PUSHL $11
- JMP intrcommon
-TEXT intr12(SB),$0
- PUSHL $12
- JMP intrcommon
-TEXT intr13(SB),$0
- PUSHL $13
- JMP intrcommon
-TEXT intr14(SB),$0
- PUSHL $14
- JMP intrcommon
-TEXT intr15(SB),$0
- PUSHL $0
- PUSHL $15
- JMP intrcommon
-TEXT intr16(SB),$0
- PUSHL $0
- PUSHL $16
- JMP intrcommon
-TEXT intr24(SB),$0
- PUSHL $0
- PUSHL $24
- JMP intrcommon
-TEXT intr25(SB),$0
- PUSHL $0
- PUSHL $25
- JMP intrcommon
-TEXT intr26(SB),$0
- PUSHL $0
- PUSHL $26
- JMP intrcommon
-TEXT intr27(SB),$0
- PUSHL $0
- PUSHL $27
- JMP intrcommon
-TEXT intr28(SB),$0
- PUSHL $0
- PUSHL $28
- JMP intrcommon
-TEXT intr29(SB),$0
- PUSHL $0
- PUSHL $29
- JMP intrcommon
-TEXT intr30(SB),$0
- PUSHL $0
- PUSHL $30
- JMP intrcommon
-TEXT intr31(SB),$0
- PUSHL $0
- PUSHL $31
- JMP intrcommon
-TEXT intr32(SB),$0
- PUSHL $0
- PUSHL $32
- JMP intrcommon
-TEXT intr33(SB),$0
- PUSHL $0
- PUSHL $33
- JMP intrcommon
-TEXT intr34(SB),$0
- PUSHL $0
- PUSHL $34
- JMP intrcommon
-TEXT intr35(SB),$0
- PUSHL $0
- PUSHL $35
- JMP intrcommon
-TEXT intr36(SB),$0
- PUSHL $0
- PUSHL $36
- JMP intrcommon
-TEXT intr37(SB),$0
- PUSHL $0
- PUSHL $37
- JMP intrcommon
-TEXT intr38(SB),$0
- PUSHL $0
- PUSHL $38
- JMP intrcommon
-TEXT intr39(SB),$0
- PUSHL $0
- PUSHL $39
- JMP intrcommon
-TEXT intr64(SB),$0
- PUSHL $0
- PUSHL $64
- JMP intrcommon
-TEXT intrbad(SB),$0
- PUSHL $0
- PUSHL $0x1ff
- JMP intrcommon
-
-intrcommon:
- PUSHL DS
- PUSHL ES
- PUSHL FS
- PUSHL GS
- PUSHAL
- MOVL $(KDSEL),AX
- MOVW AX,DS
- MOVW AX,ES
- LEAL 0(SP),AX
- PUSHL AX
- CALL trap(SB)
- POPL AX
- POPAL
- POPL GS
- POPL FS
- POPL ES
- POPL DS
- ADDL $8,SP /* error code and trap type */
- IRETL
-
-
-/*
- * interrupt level is interrupts on or off
- */
-TEXT spllo(SB),$0
- PUSHFL
- POPL AX
- STI
- RET
-
-TEXT splhi(SB),$0
- PUSHFL
- POPL AX
- CLI
- RET
-
-TEXT splx(SB),$0
- MOVL s+0(FP),AX
- PUSHL AX
- POPFL
- RET
-
-/*
- * do nothing whatsoever till interrupt happens
- */
-TEXT idle(SB),$0
- HLT
- RET
-
-/*
- * Try to determine the CPU type which requires fiddling with EFLAGS.
- * If the Id bit can be toggled then the CPUID instruciton can be used
- * to determine CPU identity and features. First have to check if it's
- * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
- * toggled then it's an older 486 of some kind.
- *
- * cpuid(id[], &ax, &dx);
- */
-#define CPUID BYTE $0x0F; BYTE $0xA2 /* CPUID, argument in AX */
-TEXT cpuid(SB), $0
- MOVL $0x240000, AX
- PUSHL AX
- POPFL /* set Id|Ac */
-
- PUSHFL
- POPL BX /* retrieve value */
-
- MOVL $0, AX
- PUSHL AX
- POPFL /* clear Id|Ac, EFLAGS initialised */
-
- PUSHFL
- POPL AX /* retrieve value */
- XORL BX, AX
- TESTL $0x040000, AX /* Ac */
- JZ _cpu386 /* can't set this bit on 386 */
- TESTL $0x200000, AX /* Id */
- JZ _cpu486 /* can't toggle this bit on some 486 */
-
- MOVL $0, AX
- CPUID
- MOVL id+0(FP), BP
- MOVL BX, 0(BP) /* "Genu" "Auth" "Cyri" */
- MOVL DX, 4(BP) /* "ineI" "enti" "xIns" */
- MOVL CX, 8(BP) /* "ntel" "cAMD" "tead" */
-
- MOVL $1, AX
- CPUID
- JMP _cpuid
-
-_cpu486:
- MOVL $0x400, AX
- MOVL $0, DX
- JMP _cpuid
-
-_cpu386:
- MOVL $0x300, AX
- MOVL $0, DX
-
-_cpuid:
- MOVL ax+4(FP), BP
- MOVL AX, 0(BP)
- MOVL dx+8(FP), BP
- MOVL DX, 0(BP)
- RET
-
-
-/*
- * basic timing loop to determine CPU frequency
- */
-TEXT aamloop(SB),$0
-
- MOVL c+0(FP),CX
-aaml1:
- AAM
- LOOP aaml1
- RET
-
-TEXT hello(SB), $0
- BYTE $'P'; BYTE $'l'; BYTE $'a'; BYTE $'n';
- BYTE $' '; BYTE $'9'; BYTE $' '; BYTE $'f';
- BYTE $'r'; BYTE $'o'; BYTE $'m'; BYTE $' ';
- BYTE $'B'; BYTE $'e'; BYTE $'l'; BYTE $'l';
- BYTE $' '; BYTE $'L'; BYTE $'a'; BYTE $'b';
- BYTE $'s';
-#ifdef PXE
- BYTE $' '; BYTE $'b'; BYTE $'y'; BYTE $' ';
- BYTE $'P'; BYTE $'X'; BYTE $'E';
-#endif
- BYTE $'\r';
- BYTE $'\n';
- BYTE $'\z';
-
-TEXT rock(SB), $0
- BYTE $0; BYTE $0; BYTE $0; BYTE $0;
-
-GLOBL pxe(SB), $4
-#ifdef PXE
-DATA pxe+0(SB)/4, $1
-#else
-DATA pxe+0(SB)/4, $0
-#endif /* PXE */
-
-/*
- * Save registers.
- */
-TEXT saveregs(SB), $0
- /* appease 8l */
- SUBL $32, SP
- POPL AX
- POPL AX
- POPL AX
- POPL AX
- POPL AX
- POPL AX
- POPL AX
- POPL AX
-
- PUSHL AX
- PUSHL BX
- PUSHL CX
- PUSHL DX
- PUSHL BP
- PUSHL DI
- PUSHL SI
- PUSHFL
-
- XCHGL 32(SP), AX /* swap return PC and saved flags */
- XCHGL 0(SP), AX
- XCHGL 32(SP), AX
- RET
-
-TEXT restoreregs(SB), $0
- /* appease 8l */
- PUSHL AX
- PUSHL AX
- PUSHL AX
- PUSHL AX
- PUSHL AX
- PUSHL AX
- PUSHL AX
- PUSHL AX
- ADDL $32, SP
-
- XCHGL 32(SP), AX /* swap return PC and saved flags */
- XCHGL 0(SP), AX
- XCHGL 32(SP), AX
-
- POPFL
- POPL SI
- POPL DI
- POPL BP
- POPL DX
- POPL CX
- POPL BX
- POPL AX
- RET
-
-/*
- * Assumed to be in protected mode at time of call.
- * Switch to real mode, execute an interrupt, and
- * then switch back to protected mode.
- *
- * Assumes:
- *
- * - no device interrupts are going to come in
- * - 0-16MB is identity mapped in page tables
- * - can use code segment 0x1000 in real mode
- * to get at l.s code
- */
-TEXT realmodeidtptr(SB), $0
- WORD $(4*256-1)
- LONG $0
-
-TEXT realmode0(SB), $0
- CALL saveregs(SB)
-
- /* switch to low code address */
- LEAL physcode-KZERO(SB), AX
- JMP *AX
-
-TEXT physcode(SB), $0
-
- /* switch to low stack */
- MOVL SP, AX
- MOVL $0x7C00, SP
- PUSHL AX
-
- /* load IDT with real-mode version; GDT already fine */
- MOVL realmodeidtptr(SB), IDTR
-
- /* edit INT $0x00 instruction below */
- MOVL realmodeintr(SB), AX
- MOVB AX, realmodeintrinst+1(SB)
-
- /* disable paging */
- MOVL CR0, AX
- ANDL $0x7FFFFFFF, AX
- MOVL AX, CR0
- /* JMP .+2 to clear prefetch queue*/
- BYTE $0xEB; BYTE $0x00
-
- /* jump to 16-bit code segment */
-/* JMPFAR SELECTOR(3, SELGDT, 0):$again16bit(SB) /**/
- BYTE $0xEA
- LONG $again16bit-KZERO(SB)
- WORD $SELECTOR(3, SELGDT, 0)
-
-TEXT again16bit(SB), $0
- /*
- * Now in 16-bit compatibility mode.
- * These are 32-bit instructions being interpreted
- * as 16-bit instructions. I'm being lazy and
- * not using the macros because I know when
- * the 16- and 32-bit instructions look the same
- * or close enough.
- */
-
- /* disable protected mode and jump to real mode cs */
- OPSIZE; MOVL CR0, AX
- OPSIZE; XORL BX, BX
- OPSIZE; INCL BX
- OPSIZE; XORL BX, AX
- OPSIZE; MOVL AX, CR0
-
- /* JMPFAR 0x1000:now16real */
- BYTE $0xEA
- WORD $now16real-KZERO(SB)
- WORD $0x1000
-
-TEXT now16real(SB), $0
- /* copy the registers for the bios call */
- LWI(0x1000, rAX)
- MOVW AX,SS
- LWI(realmoderegs(SB), rBP)
-
- /* offsets are in Ureg */
- LXW(44, xBP, rAX)
- MOVW AX, DS
- LXW(40, xBP, rAX)
- MOVW AX, ES
-
- OPSIZE; LXW(0, xBP, rDI)
- OPSIZE; LXW(4, xBP, rSI)
- OPSIZE; LXW(16, xBP, rBX)
- OPSIZE; LXW(20, xBP, rDX)
- OPSIZE; LXW(24, xBP, rCX)
- OPSIZE; LXW(28, xBP, rAX)
-
- CLC
-
-TEXT realmodeintrinst(SB), $0
- INT $0x00
-
-
- /* save the registers after the call */
-
- LWI(0x7bfc, rSP)
- OPSIZE; PUSHFL
- OPSIZE; PUSHL AX
-
- LWI(0x1000, rAX)
- MOVW AX,SS
- LWI(realmoderegs(SB), rBP)
-
- OPSIZE; SXW(rDI, 0, xBP)
- OPSIZE; SXW(rSI, 4, xBP)
- OPSIZE; SXW(rBX, 16, xBP)
- OPSIZE; SXW(rDX, 20, xBP)
- OPSIZE; SXW(rCX, 24, xBP)
- OPSIZE; POPL AX
- OPSIZE; SXW(rAX, 28, xBP)
-
- MOVW DS, AX
- OPSIZE; SXW(rAX, 44, xBP)
- MOVW ES, AX
- OPSIZE; SXW(rAX, 40, xBP)
-
- OPSIZE; POPL AX
- OPSIZE; SXW(rAX, 64, xBP) /* flags */
-
- /* re-enter protected mode and jump to 32-bit code */
- OPSIZE; MOVL $1, AX
- OPSIZE; MOVL AX, CR0
-
-/* JMPFAR SELECTOR(2, SELGDT, 0):$again32bit(SB) /**/
- OPSIZE
- BYTE $0xEA
- LONG $again32bit-KZERO(SB)
- WORD $SELECTOR(2, SELGDT, 0)
-
-TEXT again32bit(SB), $0
- MOVW $SELECTOR(1, SELGDT, 0),AX
- MOVW AX,DS
- MOVW AX,SS
- MOVW AX,ES
- MOVW AX,FS
- MOVW AX,GS
-
- /* enable paging and jump to kzero-address code */
- MOVL CR0, AX
- ORL $0x80000000, AX
- MOVL AX, CR0
- LEAL again32kzero(SB), AX
- JMP* AX
-
-TEXT again32kzero(SB), $0
- /* breathe a sigh of relief - back in 32-bit protected mode */
-
- /* switch to old stack */
- PUSHL AX /* match popl below for 8l */
- MOVL $0x7BFC, SP
- POPL SP
-
- /* restore idt */
- MOVL idtptr(SB),IDTR
-
- CALL restoreregs(SB)
- RET
-
-TEXT realmoderegs(SB), $0
- LONG $0; LONG $0; LONG $0; LONG $0
- LONG $0; LONG $0; LONG $0; LONG $0
- LONG $0; LONG $0; LONG $0; LONG $0
- LONG $0; LONG $0; LONG $0; LONG $0
- LONG $0; LONG $0; LONG $0; LONG $0
-
-TEXT realmodeintr(SB), $0
- LONG $0
-
--- a/os/boot/pc/lib.h
+++ /dev/null
@@ -1,106 +1,0 @@
-#define offsetof(s, m) (ulong)(&(((s*)0)->m))
-
-/*
- * functions (possibly) linked in, complete, from libc.
- */
-
-/*
- * mem routines
- */
-extern void* memccpy(void*, void*, int, ulong);
-extern void* memset(void*, int, ulong);
-extern int memcmp(void*, void*, ulong);
-extern void* memmove(void*, void*, ulong);
-extern void* memchr(void*, int, ulong);
-
-/*
- * string routines
- */
-extern char* strcat(char*, char*);
-extern char* strchr(char*, int);
-extern int strcmp(char*, char*);
-extern char* strcpy(char*, char*);
-extern char* strncat(char*, char*, long);
-extern char* strncpy(char*, char*, long);
-extern int strncmp(char*, char*, long);
-extern long strlen(char*);
-extern char* strrchr(char*, char);
-extern char* strstr(char*, char*);
-
-
-/*
- * print routines
- */
-typedef struct Fmt Fmt;
-typedef int (*Fmts)(Fmt*);
-struct Fmt{
- uchar runes; /* output buffer is runes or chars? */
- void *start; /* of buffer */
- void *to; /* current place in the buffer */
- void *stop; /* end of the buffer; overwritten if flush fails */
- int (*flush)(Fmt *); /* called when to == stop */
- void *farg; /* to make flush a closure */
- int nfmt; /* num chars formatted so far */
- va_list args; /* args passed to dofmt */
- int r; /* % format Rune */
- int width;
- int prec;
- ulong flags;
-};
-extern int print(char*, ...);
-extern char* vseprint(char*, char*, char*, va_list);
-extern int sprint(char*, char*, ...);
-extern int snprint(char*, int, char*, ...);
-extern int fmtinstall(int, int (*)(Fmt*));
-
-#pragma varargck argpos addconf 1
-#pragma varargck argpos fmtprint 2
-#pragma varargck argpos print 1
-#pragma varargck argpos seprint 3
-#pragma varargck argpos snprint 3
-#pragma varargck argpos sprint 2
-#pragma varargck type "H" void*
-
-#pragma varargck type "lld" vlong
-#pragma varargck type "llx" vlong
-#pragma varargck type "lld" uvlong
-#pragma varargck type "llx" uvlong
-#pragma varargck type "ld" long
-#pragma varargck type "lx" long
-#pragma varargck type "ld" ulong
-#pragma varargck type "lx" ulong
-#pragma varargck type "d" int
-#pragma varargck type "x" int
-#pragma varargck type "c" int
-#pragma varargck type "C" int
-#pragma varargck type "d" uint
-#pragma varargck type "x" uint
-#pragma varargck type "c" uint
-#pragma varargck type "C" uint
-#pragma varargck type "f" double
-#pragma varargck type "e" double
-#pragma varargck type "g" double
-#pragma varargck type "s" char*
-#pragma varargck type "q" char*
-#pragma varargck type "S" Rune*
-#pragma varargck type "Q" Rune*
-#pragma varargck type "r" void
-#pragma varargck type "%" void
-#pragma varargck type "|" int
-#pragma varargck type "p" void*
-#pragma varargck type "lux" void*
-#pragma varargck type "E" uchar*
-
-#define PRINTSIZE 256
-
-/*
- * one-of-a-kind
- */
-extern int atoi(char*);
-extern uintptr getcallerpc(void*);
-extern long strtol(char*, char**, int);
-extern ulong strtoul(char*, char**, int);
-extern uvlong strtoull(char*, char**, int);
-extern long end;
-
-#define NAMELEN 28
--- a/os/boot/pc/load.c
+++ /dev/null
@@ -1,627 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "sd.h"
-#include "fs.h"
-
-#ifndef VERBOSE
-#define VERBOSE 0
-#endif
-
-/*
- * "cache" must be in this list so that 9load will pass the definition of
- * the cache partition into the kernel so that the disk named by the `cfs'
- * variable in plan9.ini can be seen in all circumstances before termrc
- * sets up all the disk partitions. In particular, if it's on an odd-ball
- * disk like sd10 rather than sdC0, this is needed.
- */
-static char *diskparts[] = {
- "dos", "9fat", "fs", "data", "cdboot", "cache", 0
-};
-static char *etherparts[] = { "*", 0 };
-
-static char *diskinis[] = {
- "plan9/plan9.ini",
- "plan9.ini",
- 0
-};
-static char *etherinis[] = {
- "/cfg/pxe/%E",
- 0
-};
-
-/* ordering: devbios must be called before devsd calls sdbios */
-Type types[] = {
- { Tfloppy,
- Fini|Ffs,
- floppyinit, floppyinitdev,
- floppygetfspart, 0, floppyboot,
- floppyprintdevs,
- diskparts,
- diskinis,
- },
- { Tether,
- Fini|Fbootp,
- etherinit, etherinitdev,
- pxegetfspart, 0, bootpboot,
- etherprintdevs,
- etherparts,
- etherinis,
- },
- { Tbios,
- Fini|Ffs,
- biosinit, biosinitdev,
- biosgetfspart, nil, biosboot,
- biosprintdevs,
- diskparts,
- diskinis,
- },
- { Tcd,
- Fini|Ffs,
- cdinit, sdinitdev,
- sdgetfspart, sdaddconf, sdboot,
- sdprintdevs,
- diskparts,
- diskinis,
- },
- { Tsd,
- Fini|Ffs,
- sdinit, sdinitdev,
- sdgetfspart, sdaddconf, sdboot,
- sdprintdevs,
- diskparts,
- diskinis,
- },
- { Tnil,
- 0,
- nil, nil, nil, nil, nil, nil,
- nil,
- nil,
- 0,
- nil,
- },
-};
-
-static char *typenm[] = {
- [Tnil] "nil",
- [Tfloppy] "floppy",
- [Tsd] "sd",
- [Tether] "ether",
- [Tcd] "cd",
- [Tbios] "bios",
-};
-
-static char *
-typename(int type)
-{
- if (type < 0 || type >= nelem(typenm) || typenm[type] == nil)
- return "**gok**";
- return typenm[type];
-}
-
-extern SDifc sdataifc;
-extern SDifc sdiahciifc;
-extern SDifc sdaoeifc;
-extern SDifc sdbiosifc;
-
-#ifdef NOSCSI
-
-SDifc* sdifc[] = {
- &sdataifc,
- &sdiahciifc,
- &sdbiosifc,
- &sdaoeifc,
- nil,
-};
-
-#else
-
-extern SDifc sdmylexifc;
-extern SDifc sd53c8xxifc;
-
-SDifc* sdifc[] = {
- &sdataifc,
- &sdiahciifc,
- &sdmylexifc,
- &sd53c8xxifc,
- &sdbiosifc,
- &sdaoeifc,
- nil,
-};
-
-#endif NOSCSI
-
-typedef struct Mode Mode;
-
-enum {
- Maxdev = 7,
- Dany = -1,
- Nmedia = 16,
- Nini = 10,
-};
-
-enum { /* mode */
- Mauto = 0x00,
- Mlocal = 0x01,
- Manual = 0x02,
- NMode = 0x03,
-};
-
-typedef struct Medium Medium;
-struct Medium {
- Type* type;
- int flag;
- int dev;
- char name[NAMELEN];
-
- Fs *inifs;
- char *part;
- char *ini;
-
- Medium* next;
-};
-
-typedef struct Mode {
- char* name;
- int mode;
-} Mode;
-
-static Medium media[Nmedia];
-static Medium *curmedium = media;
-
-static Mode modes[NMode+1] = {
- [Mauto] { "auto", Mauto, },
- [Mlocal] { "local", Mlocal, },
- [Manual] { "manual", Manual, },
-};
-
-char **ini;
-
-int scsi0port;
-char *defaultpartition;
-int iniread;
-
-int debugload;
-
-static Medium*
-parse(char *line, char **file)
-{
- char *p;
- Type *tp;
- Medium *mp;
-
- if(p = strchr(line, '!')) {
- *p++ = 0;
- *file = p;
- } else
- *file = "";
-
- for(tp = types; tp->type != Tnil; tp++)
- for(mp = tp->media; mp; mp = mp->next)
- if(strcmp(mp->name, line) == 0)
- return mp;
- if(p)
- *--p = '!';
- return nil;
-}
-
-static int
-boot(Medium *mp, char *file)
-{
- Type *tp;
- Medium *xmp;
- static int didaddconf;
- Boot b;
-
- memset(&b, 0, sizeof b);
- b.state = INITKERNEL;
-
- if(didaddconf == 0) {
- didaddconf = 1;
- for(tp = types; tp->type != Tnil; tp++)
- if(tp->addconf)
- for(xmp = tp->media; xmp; xmp = xmp->next)
- (*tp->addconf)(xmp->dev);
- }
-
- sprint(BOOTLINE, "%s!%s", mp->name, file);
- print("booting %s!%s\n", mp->name, file);
- return (*mp->type->boot)(mp->dev, file, &b);
-}
-
-static Medium*
-allocm(Type *tp)
-{
- Medium **l;
-
- if(curmedium >= &media[Nmedia])
- return 0;
-
- for(l = &tp->media; *l; l = &(*l)->next)
- ;
- *l = curmedium++;
- return *l;
-}
-
-Medium*
-probe(int type, int flag, int dev)
-{
- Type *tp;
- int i;
- Medium *mp;
- File f;
- Fs *fs;
- char **partp;
-
- for(tp = types; tp->type != Tnil; tp++){
- if(type != Tany && type != tp->type)
- continue;
-
- if(flag != Fnone){
- for(mp = tp->media; mp; mp = mp->next){
- if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
- return mp;
- }
- }
- if (debugload)
- print("probing %s...", typename(tp->type));
- if((tp->flag & Fprobe) == 0){
- tp->flag |= Fprobe;
- tp->mask = (*tp->init)();
- }
-
- for(i = 0; tp->mask; i++){
- if((tp->mask & (1<<i)) == 0)
- continue;
- tp->mask &= ~(1<<i);
-
- if((mp = allocm(tp)) == 0)
- continue;
-
- mp->dev = i;
- mp->flag = tp->flag;
- mp->type = tp;
- (*tp->initdev)(i, mp->name);
-
- if(mp->flag & Fini){
- mp->flag &= ~Fini;
- for(partp = tp->parts; *partp; partp++){
- if((fs = (*tp->getfspart)(i, *partp, 0)) == nil)
- continue;
-
- for(ini = tp->inis; *ini; ini++){
- if(fswalk(fs, *ini, &f) > 0){
- mp->inifs = fs;
- mp->part = *partp;
- mp->ini = f.path;
- mp->flag |= Fini;
- goto Break2;
- }
- }
- }
- }
- Break2:
- if((flag & mp->flag) && (dev == Dany || dev == i))
- return mp;
- }
- }
-
- return 0;
-}
-
-void
-main(void)
-{
- Medium *mp;
- int flag, i, mode, tried;
- char def[2*NAMELEN], line[80], *p, *file;
- Type *tp;
-
- i8042a20();
- memset(m, 0, sizeof(Mach));
- trapinit();
- clockinit();
- alarminit();
- meminit(0);
- spllo();
- consinit("0", "9600");
- kbdinit();
- if((ulong)&end > (KZERO|(640*1024)))
- panic("i'm too big\n");
-
- readlsconf();
- print("initial probe, to find plan9.ini...");
- /* find and read plan9.ini, setting configuration variables */
- for(tp = types; tp->type != Tnil; tp++){
- /* skip bios until we have read plan9.ini */
- if(!pxe && tp->type == Tether || tp->type == Tbios)
- continue;
- if (VERBOSE)
- print("probing %s...", typename(tp->type));
- if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
- print("using %s!%s!%s\n", mp->name, mp->part, mp->ini);
- iniread = !dotini(mp->inifs);
- break;
- }
- }
- print("\n");
- apminit();
-
- debugload = getconf("*debugload") != nil;
- if((p = getconf("console")) != nil)
- consinit(p, getconf("baud"));
-
- devpccardlink();
- devi82365link();
-
- /*
- * Even after we find the ini file, we keep probing disks,
- * because we have to collect the partition tables and
- * have boot devices for parse.
- */
- probe(Tany, Fnone, Dany);
- if (debugload)
- print("end disk probe\n");
- tried = 0;
- mode = Mauto;
-
- p = getconf("bootfile");
-
- if(p != 0) {
- mode = Manual;
- for(i = 0; i < NMode; i++){
- if(strcmp(p, modes[i].name) == 0){
- mode = modes[i].mode;
- goto done;
- }
- }
- if((mp = parse(p, &file)) == nil) {
- print("Unknown boot device: %s\n", p);
- goto done;
- }
- tried = boot(mp, file);
- }
-done:
- if(tried == 0 && mode != Manual){
- flag = Fany;
- if(mode == Mlocal)
- flag &= ~Fbootp;
- if((mp = probe(Tany, flag, Dany)) && mp->type->type != Tfloppy)
- boot(mp, "");
- if (debugload)
- print("end auto probe\n");
- }
-
- def[0] = 0;
- probe(Tany, Fnone, Dany);
- if (debugload)
- print("end final probe\n");
- if(p = getconf("bootdef"))
- strcpy(def, p);
-
- flag = 0;
- for(tp = types; tp->type != Tnil; tp++){
- for(mp = tp->media; mp; mp = mp->next){
- if(flag == 0){
- flag = 1;
- print("Boot devices:");
- }
- (*tp->printdevs)(mp->dev);
- }
- }
- if(flag)
- print("\n");
-
- for(;;){
- if(getstr("boot from", line, sizeof(line), def, (mode != Manual)*15) >= 0)
- if(mp = parse(line, &file))
- boot(mp, file);
- def[0] = 0;
- }
-}
-
-int
-getfields(char *lp, char **fields, int n, char sep)
-{
- int i;
-
- for(i = 0; lp && *lp && i < n; i++){
- while(*lp == sep)
- *lp++ = 0;
- if(*lp == 0)
- break;
- fields[i] = lp;
- while(*lp && *lp != sep){
- if(*lp == '\\' && *(lp+1) == '\n')
- *lp++ = ' ';
- lp++;
- }
- }
- return i;
-}
-
-int
-cistrcmp(char *a, char *b)
-{
- int ac, bc;
-
- for(;;){
- ac = *a++;
- bc = *b++;
-
- if(ac >= 'A' && ac <= 'Z')
- ac = 'a' + (ac - 'A');
- if(bc >= 'A' && bc <= 'Z')
- bc = 'a' + (bc - 'A');
- ac -= bc;
- if(ac)
- return ac;
- if(bc == 0)
- break;
- }
- return 0;
-}
-
-int
-cistrncmp(char *a, char *b, int n)
-{
- unsigned ac, bc;
-
- while(n > 0){
- ac = *a++;
- bc = *b++;
- n--;
-
- if(ac >= 'A' && ac <= 'Z')
- ac = 'a' + (ac - 'A');
- if(bc >= 'A' && bc <= 'Z')
- bc = 'a' + (bc - 'A');
-
- ac -= bc;
- if(ac)
- return ac;
- if(bc == 0)
- break;
- }
-
- return 0;
-}
-
-#define PSTART ( 8*1024*1024)
-#define PEND (16*1024*1024)
-
-ulong palloc = PSTART;
-
-void*
-ialloc(ulong n, int align)
-{
- ulong p;
- int a;
-
- p = palloc;
- if(align <= 0)
- align = 4;
- if(a = n % align)
- n += align - a;
- if(a = p % align)
- p += align - a;
-
-
- palloc = p+n;
- if(palloc > PEND)
- panic("ialloc(%lud, %d) called from %#p\n",
- n, align, getcallerpc(&n));
- return memset((void*)(p|KZERO), 0, n);
-}
-
-void*
-xspanalloc(ulong size, int align, ulong span)
-{
- ulong a, v;
-
- if((palloc + (size+align+span)) > PEND)
- panic("xspanalloc(%lud, %d, 0x%lux) called from %#p\n",
- size, align, span, getcallerpc(&size));
-
- a = (ulong)ialloc(size+align+span, 0);
-
- if(span > 2)
- v = (a + span) & ~(span-1);
- else
- v = a;
-
- if(align > 1)
- v = (v + align) & ~(align-1);
-
- return (void*)v;
-}
-
-static Block *allocbp;
-
-Block*
-allocb(int size)
-{
- Block *bp, **lbp;
- ulong addr;
-
- lbp = &allocbp;
- for(bp = *lbp; bp; bp = bp->next){
- if((bp->lim - bp->base) >= size){
- *lbp = bp->next;
- break;
- }
- lbp = &bp->next;
- }
- if(bp == 0){
- if((palloc + (sizeof(Block)+size+64)) > PEND)
- panic("allocb(%d) called from %#p\n",
- size, getcallerpc(&size));
- bp = ialloc(sizeof(Block)+size+64, 0);
- addr = (ulong)bp;
- addr = ROUNDUP(addr + sizeof(Block), 8);
- bp->base = (uchar*)addr;
- bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
- }
-
- if(bp->flag)
- panic("allocb reuse\n");
-
- bp->rp = bp->base;
- bp->wp = bp->rp;
- bp->next = 0;
- bp->flag = 1;
-
- return bp;
-}
-
-void
-freeb(Block* bp)
-{
- bp->next = allocbp;
- allocbp = bp;
-
- bp->flag = 0;
-}
-
-enum {
- Paddr= 0x70, /* address port */
- Pdata= 0x71, /* data port */
-};
-
-uchar
-nvramread(int offset)
-{
- outb(Paddr, offset);
- return inb(Pdata);
-}
-
-void (*etherdetach)(void);
-void (*floppydetach)(void);
-void (*sddetach)(void);
-
-void
-warp9(ulong entry)
-{
- if(etherdetach)
- etherdetach();
- if(floppydetach)
- floppydetach();
- if(sddetach)
- sddetach();
- consdrain();
-
- splhi();
- trapdisable();
-
- /*
- * This is where to push things on the stack to
- * boot *BSD systems, e.g.
- (*(void(*)(void*, void*, void*, void*, ulong, ulong))(PADDR(entry)))(0, 0, 0, 0, 8196, 640);
- * will enable NetBSD boot (the real memory size needs to
- * go in the 5th argument).
- */
- (*(void(*)(void))(PADDR(entry)))();
-}
--- a/os/boot/pc/mbr.s
+++ /dev/null
@@ -1,259 +1,0 @@
-/*
- * Hard disc boot block. Loaded at 0x7C00, relocates to 0x0600:
- * 8a mbr.s; 8l -o mbr -l -H3 -T0x0600 mbr.8
- */
-#include "x16.h"
-#include "mem.h"
-
-/*#define FLOPPY 1 /* test on a floppy */
-#define TRACE(C) PUSHA;\
- CLR(rBX);\
- MOVB $C, AL;\
- LBI(0x0E, rAH);\
- BIOSCALL(0x10);\
- POPA
-
-/*
- * We keep data on the stack, indexed by BP.
- */
-#define Xdap 0x00 /* disc address packet */
-#define Xtable 0x10 /* partition table entry */
-#define Xdrive 0x12 /* starting disc */
-#define Xtotal 0x14 /* sum of allocated data above */
-
-/*
- * Start: loaded at 0000:7C00, relocate to 0000:0600.
- * Boot drive is in rDL.
- */
-TEXT _start(SB), $0
- CLI
- CLR(rAX)
- MTSR(rAX, rSS) /* 0000 -> rSS */
- LWI((0x7C00-Xtotal), rSP) /* 7Bxx -> rSP */
- MW(rSP, rBP) /* set the indexed-data pointer */
-
- MTSR(rAX, rDS) /* 0000 -> rDS, source segment */
- LWI(0x7C00, rSI) /* 7C00 -> rSI, source offset */
- MTSR(rAX, rES) /* 0000 -> rES, destination segment */
- LWI(0x600, rDI) /* 0600 -> rDI, destination offset */
- LWI(0x100, rCX) /* 0100 -> rCX, loop count (words) */
-
- CLD
- REP; MOVSL /* MOV DS:[(E)SI] -> ES:[(E)DI] */
-
- FARJUMP16(0x0000, _start0600(SB))
-
-TEXT _start0600(SB), $0
-#ifdef FLOPPY
- LBI(0x80, rDL)
-#else
- CLRB(rAL) /* some systems pass 0 */
- CMPBR(rAL, rDL)
- JNE _save
- LBI(0x80, rDL)
-#endif /* FLOPPY */
-_save:
- SXB(rDL, Xdrive, xBP) /* save disc */
-
- LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
- CALL16(BIOSputs(SB))
-
- LWI(_start+0x01BE(SB), rSI) /* address of partition table */
- LWI(0x04, rCX) /* 4 entries in table */
- LBI(0x80, rAH) /* active entry value */
- CLRB(rAL) /* inactive entry value */
-
-_activeloop0:
- LXB(0x00, xSI, rBL) /* get active entry from table */
- CMPBR(rBL, rAH) /* is this an active entry? */
- JEQ _active
-
- CMPBR(rBL, rAL) /* if not active it should be 0 */
- JNE _invalidMBR
-
- ADDI(0x10, rSI) /* next table entry */
- DEC(rCX)
- JNE _activeloop0
-
- LWI(noentry(SB), rSI)
- CALL16(buggery(SB))
-
-_active:
- MW(rSI, rDI) /* save table address */
-
-_activeloop1:
- ADDI(0x10, rSI) /* next table entry */
- DEC(rCX)
- JEQ _readsector
-
- LXB(0x00, xSI, rBL) /* get active entry from table */
- CMPBR(rBL, rAH) /* is this an active entry? */
- JNE _activeloop1 /* should only be one active */
-
-_invalidMBR:
- LWI(invalidMBR(SB), rSI)
- CALL16(buggery(SB))
-
-_readsector:
- LBI(0x41, rAH) /* check extensions present */
- LWI(0x55AA, rBX)
- LXB(Xdrive, xBP, rDL) /* drive */
- BIOSCALL(0x13) /* CF set on failure */
- JCS _readsector2
- CMPI(0xAA55, rBX)
- JNE _readsector2
- ANDI(0x0001, rCX)
- JEQ _readsector2
-
-_readsector42:
- SBPBI(0x10, Xdap+0) /* packet size */
- SBPBI(0x00, Xdap+1) /* reserved */
- SBPBI(0x01, Xdap+2) /* number of blocks to transfer */
- SBPBI(0x00, Xdap+3) /* reserved */
- SBPWI(0x7C00, Xdap+4) /* transfer buffer :offset */
- SBPWI(0x0000, Xdap+6) /* transfer buffer seg: */
- LXW(0x08, xDI, rAX) /* LBA (64-bits) */
- SBPW(rAX, Xdap+8)
- LXW(0x0A, xDI, rAX)
- SBPW(rAX, Xdap+10)
- SBPWI(0x0000, Xdap+12)
- SBPWI(0x0000, Xdap+14)
-
- MW(rBP, rSI) /* disk address packet */
- LBI(0x42, rAH) /* extended read */
- BIOSCALL(0x13) /* CF set on failure */
- JCC _readsectorok
-
- LWI(ioerror(SB), rSI)
- CALL16(buggery(SB))
-
-/*
- * Read a sector from a disc using the traditional BIOS call.
- * For BIOSCALL(0x13/AH=0x02):
- * rAH 0x02
- * rAL number of sectors to read (1)
- * rCH low 8 bits of cylinder
- * rCL high 2 bits of cylinder (7-6), sector (5-0)
- * rDH head
- * rDL drive
- * rES:rBX buffer address
- */
-_readsector2:
- LXB(0x01, xDI, rDH) /* head */
- LXW(0x02, xDI, rCX) /* save active cylinder/sector */
-
- LWI(0x0201, rAX) /* read one sector */
- LXB(Xdrive, xBP, rDL) /* drive */
- LWI(0x7C00, rBX) /* buffer address (rES already OK) */
- BIOSCALL(0x13) /* CF set on failure */
- JCC _readsectorok
-
- LWI(ioerror(SB), rSI)
- CALL16(buggery(SB))
-
-_readsectorok:
- LWI(0x7C00, rBX) /* buffer address (rES already OK) */
- LXW(0x1FE, xBX, rAX)
- CMPI(0xAA55, rAX)
- JNE _bbnotok
-
- /*
- * Jump to the loaded PBS.
- * rDL and rSI should still contain the drive
- * and partition table pointer respectively.
- */
- MW(rDI, rSI)
- FARJUMP16(0x0000, 0x7C00)
-
-_bbnotok:
- LWI(invalidPBS(SB), rSI)
-
-TEXT buggery(SB), $0
- CALL16(BIOSputs(SB))
- LWI(reboot(SB), rSI)
- CALL16(BIOSputs(SB))
-
-_wait:
- CLR(rAX) /* wait for any key */
- BIOSCALL(0x16)
-
-_reset:
- CLR(rBX) /* set ES segment for BIOS area */
- MTSR(rBX, rES)
-
- LWI(0x0472, rBX) /* warm-start code address */
- LWI(0x1234, rAX) /* warm-start code */
- POKEW /* MOVW AX, ES:[BX] */
-
- FARJUMP16(0xFFFF, 0x0000) /* reset */
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT BIOSputs(SB), $0
- PUSHA
- CLR(rBX)
-_BIOSputs:
- LODSB
- ORB(rAL, rAL)
- JEQ _BIOSputsret
-
- LBI(0x0E, rAH)
- BIOSCALL(0x10)
- JMP _BIOSputs
-
-_BIOSputsret:
- POPA
- RET
-
-/* "No active entry in MBR" */
-TEXT noentry(SB), $0
- BYTE $'N'; BYTE $'o'; BYTE $' '; BYTE $'a';
- BYTE $'c'; BYTE $'t'; BYTE $'i'; BYTE $'v';
- BYTE $'e'; BYTE $' '; BYTE $'e'; BYTE $'n';
- BYTE $'t'; BYTE $'r'; BYTE $'y'; BYTE $' ';
- BYTE $'i'; BYTE $'n'; BYTE $' '; BYTE $'M';
- BYTE $'B'; BYTE $'R';
- BYTE $'\z';
-
-/* "Invalid MBR" */
-TEXT invalidMBR(SB), $0
- BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
- BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
- BYTE $'M'; BYTE $'B'; BYTE $'R';
- BYTE $'\z';
-
-/* "I/O error" */
-TEXT ioerror(SB), $0
- BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
- BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
- BYTE $'r';
- BYTE $'\z';
-
-/* "Invalid PBS" */
-TEXT invalidPBS(SB), $0
- BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
- BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
- BYTE $'P'; BYTE $'B'; BYTE $'S';
- BYTE $'\z';
-
-/* "\r\nPress almost any key to reboot..." */
-TEXT reboot(SB), $0
- BYTE $'\r';BYTE $'\n';
- BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
- BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $'l';
- BYTE $'m'; BYTE $'o'; BYTE $'s'; BYTE $'t';
- BYTE $' '; BYTE $'a'; BYTE $'n'; BYTE $'y';
- BYTE $' '; BYTE $'k'; BYTE $'e'; BYTE $'y';
- BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
- BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
- BYTE $'o'; BYTE $'t'; BYTE $'.'; BYTE $'.';
- BYTE $'.';
- BYTE $'\z';
-
-/* "MBR..." */
-TEXT confidence(SB), $0
- BYTE $'M'; BYTE $'B'; BYTE $'R'; BYTE $'.';
- BYTE $'.'; BYTE $'.';
- BYTE $'\z';
--- a/os/boot/pc/mem.h
+++ /dev/null
@@ -1,114 +1,0 @@
-/*
- * Memory and machine-specific definitions. Used in C and assembler.
- */
-
-/*
- * Sizes
- */
-#define BI2BY 8 /* bits per byte */
-#define BI2WD 32 /* bits per word */
-#define BY2WD 4 /* bytes per word */
-#define BY2PG 4096 /* bytes per page */
-#define WD2PG (BY2PG/BY2WD) /* words per page */
-#define PGSHIFT 12 /* log(BY2PG) */
-#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
-
-#define MAXMACH 1 /* max # cpus system can run */
-
-/*
- * Time
- */
-#define HZ (100) /* clock frequency */
-#define MS2HZ (1000/HZ) /* millisec per clock tick */
-#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
-#define TK2MS(x) ((x)*(1000/HZ))
-#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
-
-/*
- * Fundamental addresses
- */
-#define IDTADDR 0x80000800 /* idt */
-#define APBOOTSTRAP 0x80001000 /* AP bootstrap code */
-#define CONFADDR 0x80001200 /* info passed from boot loader */
-#define CPU0PDB 0x80002000 /* bootstrap processor PDB */
-#define CPU0PTE 0x80003000 /* bootstrap processor PTE's for 0-4MB */
-#define MACHADDR 0x80004000 /* as seen by current processor */
-#define CPU0MACH 0x80005000 /* Mach for bootstrap processor */
-#define BIOSXCHG 0x80006000 /* To exchange data with the BIOS */
-#define MACHSIZE (BY2PG*8) /* stack size */
-
-/*
- * Address spaces
- *
- * Kernel is at 2GB-4GB
- */
-#define KZERO 0x80000000 /* base of kernel address space */
-#define KTZERO KZERO /* first address in kernel text */
-#define ROMBIOS (KZERO|0xF0000)
-
-/*
- * known 80386 segments (in GDT) and their selectors
- */
-#define NULLSEG 0 /* null segment */
-#define KDSEG 1 /* kernel data/stack */
-#define KESEG 2 /* kernel executable */
-#define UDSEG 3 /* user data/stack */
-#define UESEG 4 /* user executable */
-#define SYSGATE 5 /* system call gate */
-#define TSSSEG 6 /* task segment */
-
-#define SELGDT (0<<3) /* selector is in gdt */
-#define SELLDT (1<<3) /* selector is in ldt */
-
-#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p))
-
-#define NULLSEL SELECTOR(NULLSEG, SELGDT, 0)
-#define KESEL SELECTOR(KESEG, SELGDT, 0)
-#define KDSEL SELECTOR(KDSEG, SELGDT, 0)
-#define UESEL SELECTOR(UESEG, SELGDT, 3)
-#define UDSEL SELECTOR(UDSEG, SELGDT, 3)
-#define TSSSEL SELECTOR(TSSSEG, SELGDT, 0)
-
-/*
- * fields in segment descriptors
- */
-#define SEGDATA (0x10<<8) /* data/stack segment */
-#define SEGEXEC (0x18<<8) /* executable segment */
-#define SEGTSS (0x9<<8) /* TSS segment */
-#define SEGCG (0x0C<<8) /* call gate */
-#define SEGIG (0x0E<<8) /* interrupt gate */
-#define SEGTG (0x0F<<8) /* task gate */
-#define SEGTYPE (0x1F<<8)
-
-#define SEGP (1<<15) /* segment present */
-#define SEGPL(x) ((x)<<13) /* priority level */
-#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */
-#define SEGG (1<<23) /* granularity 1==4k (for other) */
-#define SEGE (1<<10) /* expand down */
-#define SEGW (1<<9) /* writable (for data/stack) */
-#define SEGR (1<<9) /* readable (for code) */
-#define SEGD (1<<22) /* default 1==32bit (for code) */
-
-/*
- * virtual MMU
- */
-#define PTEMAPMEM (1024*1024) /* ??? */
-#define SEGMAPSIZE 16 /* ??? */
-#define PTEPERTAB (PTEMAPMEM/BY2PG) /* ??? */
-#define PPN(x) ((x)&~(BY2PG-1))
-
-/*
- * physical MMU
- */
-#define PTEVALID (1<<0)
-#define PTEUNCACHED 0 /* everything is uncached */
-#define PTEWRITE (1<<1)
-#define PTERONLY (0<<1)
-#define PTEKERNEL (0<<2)
-#define PTEUSER (1<<2)
-#define PTESIZE (1<<7)
-
-/*
- * flag register bits that we care about
- */
-#define IFLAG 0x200
--- a/os/boot/pc/memory.c
+++ /dev/null
@@ -1,504 +1,0 @@
-/*
- * Size memory and create the kernel page-tables on the fly while doing so.
- * Called from main(), this code should only be run by the bootstrap processor.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#define MEMDEBUG 0
-
-#define PDX(va) ((((ulong)(va))>>22) & 0x03FF)
-#define PTX(va) ((((ulong)(va))>>12) & 0x03FF)
-
-enum {
- MemUPA = 0, /* unbacked physical address */
- MemRAM = 1, /* physical memory */
- MemUMB = 2, /* upper memory block (<16MB) */
- NMemType = 3,
-
- KB = 1024,
-
- MemMinMB = 4, /* minimum physical memory (<=4MB) */
- MemMaxMB = 768, /* maximum physical memory to check */
-
- NMemBase = 10,
-};
-
-typedef struct {
- int size;
- ulong addr;
-} Map;
-
-typedef struct {
- char* name;
- Map* map;
- Map* mapend;
-
- Lock;
-} RMap;
-
-static Map mapupa[8];
-static RMap rmapupa = {
- "unallocated unbacked physical memory",
- mapupa,
- &mapupa[7],
-};
-
-static Map xmapupa[8];
-static RMap xrmapupa = {
- "unbacked physical memory",
- xmapupa,
- &xmapupa[7],
-};
-
-static Map mapram[8];
-static RMap rmapram = {
- "physical memory",
- mapram,
- &mapram[7],
-};
-
-static Map mapumb[64];
-static RMap rmapumb = {
- "upper memory block",
- mapumb,
- &mapumb[63],
-};
-
-static Map mapumbrw[8];
-static RMap rmapumbrw = {
- "UMB device memory",
- mapumbrw,
- &mapumbrw[7],
-};
-
-void
-memdebug(void)
-{
- Map *mp;
- ulong maxpa, maxpa1, maxpa2;
-
- if(MEMDEBUG == 0)
- return;
-
- maxpa = (nvramread(0x18)<<8)|nvramread(0x17);
- maxpa1 = (nvramread(0x31)<<8)|nvramread(0x30);
- maxpa2 = (nvramread(0x16)<<8)|nvramread(0x15);
- print("maxpa = %luX -> %luX, maxpa1 = %luX maxpa2 = %luX\n",
- maxpa, MB+maxpa*KB, maxpa1, maxpa2);
-
- for(mp = rmapram.map; mp->size; mp++)
- print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
- for(mp = rmapumb.map; mp->size; mp++)
- print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
- for(mp = rmapumbrw.map; mp->size; mp++)
- print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
- for(mp = rmapupa.map; mp->size; mp++)
- print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
-}
-
-void
-mapfree(RMap* rmap, ulong addr, ulong size)
-{
- Map *mp;
- ulong t;
-
- if(size == 0)
- return;
-
- lock(rmap);
- for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
- ;
-
- if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
- (mp-1)->size += size;
- if(addr+size == mp->addr){
- (mp-1)->size += mp->size;
- while(mp->size){
- mp++;
- (mp-1)->addr = mp->addr;
- (mp-1)->size = mp->size;
- }
- }
- }
- else{
- if(addr+size == mp->addr && mp->size){
- mp->addr -= size;
- mp->size += size;
- }
- else do{
- if(mp >= rmap->mapend){
- print("mapfree: %s: losing 0x%luX, %lud\n",
- rmap->name, addr, size);
- break;
- }
- t = mp->addr;
- mp->addr = addr;
- addr = t;
- t = mp->size;
- mp->size = size;
- mp++;
- }while(size = t);
- }
- unlock(rmap);
-}
-
-ulong
-mapalloc(RMap* rmap, ulong addr, int size, int align)
-{
- Map *mp;
- ulong maddr, oaddr;
-
- lock(rmap);
- for(mp = rmap->map; mp->size; mp++){
- maddr = mp->addr;
-
- if(addr){
- /*
- * A specific address range has been given:
- * if the current map entry is greater then
- * the address is not in the map;
- * if the current map entry does not overlap
- * the beginning of the requested range then
- * continue on to the next map entry;
- * if the current map entry does not entirely
- * contain the requested range then the range
- * is not in the map.
- */
- if(maddr > addr)
- break;
- if(mp->size < addr - maddr) /* maddr+mp->size < addr, but no overflow */
- continue;
- if(addr - maddr > mp->size - size) /* addr+size > maddr+mp->size, but no overflow */
- break;
- maddr = addr;
- }
-
- if(align > 0)
- maddr = ((maddr+align-1)/align)*align;
- if(mp->addr+mp->size-maddr < size)
- continue;
-
- oaddr = mp->addr;
- mp->addr = maddr+size;
- mp->size -= maddr-oaddr+size;
- if(mp->size == 0){
- do{
- mp++;
- (mp-1)->addr = mp->addr;
- }while((mp-1)->size = mp->size);
- }
-
- unlock(rmap);
- if(oaddr != maddr)
- mapfree(rmap, oaddr, maddr-oaddr);
-
- return maddr;
- }
- unlock(rmap);
-
- return 0;
-}
-
-static void
-umbscan(void)
-{
- uchar *p;
-
- /*
- * Scan the Upper Memory Blocks (0xA0000->0xF0000) for pieces
- * which aren't used; they can be used later for devices which
- * want to allocate some virtual address space.
- * Check for two things:
- * 1) device BIOS ROM. This should start with a two-byte header
- * of 0x55 0xAA, followed by a byte giving the size of the ROM
- * in 512-byte chunks. These ROM's must start on a 2KB boundary.
- * 2) device memory. This is read-write.
- * There are some assumptions: there's VGA memory at 0xA0000 and
- * the VGA BIOS ROM is at 0xC0000. Also, if there's no ROM signature
- * at 0xE0000 then the whole 64KB up to 0xF0000 is theoretically up
- * for grabs; check anyway.
- */
- p = KADDR(0xD0000); /*RSC: changed from 0xC0000 */
- while(p < (uchar*)KADDR(0xE0000)){
- if (p[0] == 0x55 && p[1] == 0xAA) {
- /* Skip p[2] chunks of 512 bytes. Test for 0x55 AA before
- poking obtrusively, or else the Thinkpad X20 dies when
- setting up the cardbus (PB) */
- p += p[2] * 512;
- continue;
- }
-
- p[0] = 0xCC;
- p[2*KB-1] = 0xCC;
- if(p[0] != 0xCC || p[2*KB-1] != 0xCC){
- p[0] = 0x55;
- p[1] = 0xAA;
- p[2] = 4;
- if(p[0] == 0x55 && p[1] == 0xAA){
- p += p[2]*512;
- continue;
- }
- if(p[0] == 0xFF && p[1] == 0xFF)
- mapfree(&rmapumb, PADDR(p), 2*KB);
- }
- else
- mapfree(&rmapumbrw, PADDR(p), 2*KB);
- p += 2*KB;
- }
-
- p = KADDR(0xE0000);
- if(p[0] != 0x55 || p[1] != 0xAA){
- p[0] = 0xCC;
- p[64*KB-1] = 0xCC;
- if(p[0] != 0xCC && p[64*KB-1] != 0xCC)
- mapfree(&rmapumb, PADDR(p), 64*KB);
- }
-}
-
-
-void
-meminit(ulong)
-{
- /* A hack to initialize unbacked physical memory. It's assumed PCI space is assigned by
- the BIOS in the 0xF0000000 range and 9load never needs more than 0x2000... to run. These
- values leave ample space for memory allocations for uninitialized PCI cards (e.g. cardbus
- cards). (pb) */
- ulong maxmem = 0x40000000;
-
- umbscan();
- mapfree(&rmapupa, maxmem, 0x00000000-maxmem);
- if(MEMDEBUG)
- memdebug();
-}
-
-ulong
-umbmalloc(ulong addr, int size, int align)
-{
- ulong a;
-
- if(a = mapalloc(&rmapumb, addr, size, align))
- return (ulong)KADDR(a);
-
- return 0;
-}
-
-void
-umbfree(ulong addr, int size)
-{
- mapfree(&rmapumb, PADDR(addr), size);
-}
-
-ulong
-umbrwmalloc(ulong addr, int size, int align)
-{
- ulong a;
- uchar *p;
-
- if(a = mapalloc(&rmapumbrw, addr, size, align))
- return(ulong)KADDR(a);
-
- /*
- * Perhaps the memory wasn't visible before
- * the interface is initialised, so try again.
- */
- if((a = umbmalloc(addr, size, align)) == 0)
- return 0;
- p = (uchar*)a;
- p[0] = 0xCC;
- p[size-1] = 0xCC;
- if(p[0] == 0xCC && p[size-1] == 0xCC)
- return a;
- umbfree(a, size);
-
- return 0;
-}
-
-void
-umbrwfree(ulong addr, int size)
-{
- mapfree(&rmapumbrw, PADDR(addr), size);
-}
-
-ulong*
-mmuwalk(ulong* pdb, ulong va, int level, int create)
-{
- ulong pa, *table;
-
- /*
- * Walk the page-table pointed to by pdb and return a pointer
- * to the entry for virtual address va at the requested level.
- * If the entry is invalid and create isn't requested then bail
- * out early. Otherwise, for the 2nd level walk, allocate a new
- * page-table page and register it in the 1st level.
- */
- table = &pdb[PDX(va)];
- if(!(*table & PTEVALID) && create == 0)
- return 0;
-
- switch(level){
-
- default:
- return 0;
-
- case 1:
- return table;
-
- case 2:
- if(*table & PTESIZE)
- panic("mmuwalk2: va 0x%ux entry 0x%ux\n", va, *table);
- if(!(*table & PTEVALID)){
- pa = PADDR(ialloc(BY2PG, BY2PG));
- *table = pa|PTEWRITE|PTEVALID;
- }
- table = KADDR(PPN(*table));
-
- return &table[PTX(va)];
- }
-}
-
-static Lock mmukmaplock;
-
-ulong
-mmukmap(ulong pa, ulong va, int size)
-{
- ulong pae, *table, *pdb, pgsz, *pte, x;
- int pse, sync;
- extern int cpuidax, cpuiddx;
-
- pdb = KADDR(getcr3());
- if((cpuiddx & 0x08) && (getcr4() & 0x10))
- pse = 1;
- else
- pse = 0;
- sync = 0;
-
- pa = PPN(pa);
- if(va == 0)
- va = (ulong)KADDR(pa);
- else
- va = PPN(va);
-
- pae = pa + size;
- lock(&mmukmaplock);
- while(pa < pae){
- table = &pdb[PDX(va)];
- /*
- * Possibly already mapped.
- */
- if(*table & PTEVALID){
- if(*table & PTESIZE){
- /*
- * Big page. Does it fit within?
- * If it does, adjust pgsz so the correct end can be
- * returned and get out.
- * If not, adjust pgsz up to the next 4MB boundary
- * and continue.
- */
- x = PPN(*table);
- if(x != pa)
- panic("mmukmap1: pa 0x%ux entry 0x%ux\n",
- pa, *table);
- x += 4*MB;
- if(pae <= x){
- pa = pae;
- break;
- }
- pgsz = x - pa;
- pa += pgsz;
- va += pgsz;
-
- continue;
- }
- else{
- /*
- * Little page. Walk to the entry.
- * If the entry is valid, set pgsz and continue.
- * If not, make it so, set pgsz, sync and continue.
- */
- pte = mmuwalk(pdb, va, 2, 0);
- if(pte && *pte & PTEVALID){
- x = PPN(*pte);
- if(x != pa)
- panic("mmukmap2: pa 0x%ux entry 0x%ux\n",
- pa, *pte);
- pgsz = BY2PG;
- pa += pgsz;
- va += pgsz;
- sync++;
-
- continue;
- }
- }
- }
-
- /*
- * Not mapped. Check if it can be mapped using a big page -
- * starts on a 4MB boundary, size >= 4MB and processor can do it.
- * If not a big page, walk the walk, talk the talk.
- * Sync is set.
- */
- if(pse && (pa % (4*MB)) == 0 && (pae >= pa+4*MB)){
- *table = pa|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID;
- pgsz = 4*MB;
- }
- else{
- pte = mmuwalk(pdb, va, 2, 1);
- *pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID;
- pgsz = BY2PG;
- }
- pa += pgsz;
- va += pgsz;
- sync++;
- }
- unlock(&mmukmaplock);
-
- /*
- * If something was added
- * then need to sync up.
- */
- if(sync)
- putcr3(PADDR(pdb));
-
- return pa;
-}
-
-ulong
-upamalloc(ulong addr, int size, int align)
-{
- ulong ae, a;
-
- USED(align);
-
- if((a = mapalloc(&rmapupa, addr, size, align)) == 0){
- memdebug();
- return 0;
- }
-
- /*
- * This is a travesty, but they all are.
- */
- ae = mmukmap(a, 0, size);
-
- /*
- * Should check here that it was all delivered
- * and put it back and barf if not.
- */
- USED(ae);
-
- /*
- * Be very careful this returns a PHYSICAL address.
- */
- return a;
-}
-
-void
-upafree(ulong pa, int size)
-{
- USED(pa, size);
-}
-
--- a/os/boot/pc/mkfile
+++ /dev/null
@@ -1,250 +1,0 @@
-<../../../mkconfig
-objtype=386
-SYSTARG=$OSTARG
-OBJTYPE=386
-BIN=$ROOT/Inferno/$OBJTYPE
-LIBDIR=$ROOT/Inferno/$OBJTYPE/lib
-LIBDIRS=../libflate $ROOT/libkern
-LIBS=\
- libflate\
- libkern\
-
-LIBFILES=${LIBS:%=$LIBDIR/%.a}
-<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
-
-BIN=$ROOT/Inferno/$OBJTYPE
-
-TARG=\
- 9load\
- 9pxeload\
- 9loadlite\
- 9loaddebug\
- 9loadlitedebug\
- ld.com\
- mbr\
- pbs\
- pbslba\
-
-CORE=\
- alarm.$O\
- cga.$O\
- clock.$O\
- console.$O\
- dosboot.$O\
- devfloppy.$O\
- dma.$O\
- fs.$O\
- ilock.$O\
- kbd.$O\
- kfsboot.$O\
- print.$O\
- queue.$O\
- trap.$O\
- getcallerpc.$O\
-
-LOAD=\
- 8250.$O\
- apm.$O\
- boot.$O\
- cis.$O\
- conf.$O\
- devbios.$O\
- devi82365.$O\
- devpccard.$O\
- devsd.$O\
- inflate.$O\
- load.$O\
- memory.$O\
- part.$O\
- pci.$O\
- sdata.$O\
- sdmylex.$O\
- sd53c8xx.$O\
- sdiahci.$O\
- sdscsi.$O\
- sdaoe.$O\
- sdbios.$O\
-
-ETHER=\
- bootp.$O\
- eipfmt.$O\
- ether.$O\
- ether2114x.$O\
- ether2000.$O\
- ether589.$O\
- ether79c970.$O\
- ether8003.$O\
- ether8139.$O\
- ether8169.$O\
- ether82563.$O\
- ether82557.$O\
- ether83815.$O\
- ether8390.$O\
- etherec2t.$O\
- etherelnk3.$O\
- etherga620.$O\
- etherigbe.$O\
- ethermii.$O\
- etherrhine.$O\
- etherdp83820.$O\
-
-BCOM=\
- bcom.$O\
- bootld.$O\
- devsd.$O\
- memory.$O\
- part.$O\
- pci.$O\
- sdata.$O\
- sdscsi.$O\
-
-HFILES=\
- lib.h\
- mem.h\
- dat.h\
- fns.h\
- io.h\
- aoe.h\
-
-CFLAGS=-FVTw -I. -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include
-
-all:V: $TARG
-
-9load: l.$O $CORE $LOAD $ETHER $LIBFILES
- $LD -o $target -H3 -T0x80010000 -l $prereq
- ls -l $target
-
-9pxeload: l.$O $CORE $LOAD $ETHER $LIBFILES
- $LD -o $target -H3 -T0x80007C00 -l $prereq
- ls -l $target
-
-9loaddebug: l.$O $CORE $LOAD $ETHER $LIBFILES
- $LD -o $target -T0x80010000 -l $prereq
- ls -l $target
- # acid $target
- # map({"text", 0x80010000, 0x80090000, 0x00000020})
-
-9loadlite: l.$O $CORE $LOAD noether.$O $LIBFILES
- $LD -o $target -H3 -T0x80010000 -l $prereq
- ls -l $target
-
-9loadlitedebug: l.$O $CORE $LOAD noether.$O $LIBFILES
- $LD -o $target -T0x80010000 -l $prereq
- ls -l $target
- # acid $target
- # map({"text", 0x80010000, 0x80090000, 0x00000020})
-
-ld.com: ld.$O $CORE $BCOM $LIBFILES
- $LD -o $target -H3 -T0x80080100 -l $prereq
- ls -l $target
-
-lddebug: ld.$O $CORE $BCOM $LIBFILES
- $LD -o $target -T0x80080100 -l $prereq
- ls -l $target
- # acid $target
- # map({"text", 0x80080100, 0x800B0000, 0x00000020})
-
-ld.$O: l.s
- $AS -DDOTCOM -o $target l.s
-
-lpxe.$O: l.s
- $AS -DPXE -o $target l.s
-
-%.$O: %.s
- $AS $stem.s
-
-%.$O: %.c
- $CC $CFLAGS $stem.c
-
-%.$O: $HFILES
-
-l.$O pbs.$O pbslba.$O mbr.$O: x16.h
-
-clock.$O floppy.$O trap.$O: ureg.h
-bcom.$O conf.$O devfloppy.$O devsd.$O dosboot.$O fs.$O \
- kfsboot.$O load.$O part.$O: dosfs.h fs.h kfs.h
-ether.$O etherelnk3.$O: etherif.h
-devsd.$O part.$O sdata.$O sdscsi.$O: sd.h
-bootp.$O: ip.h
-
-mbr: mbr.$O
- $LD -o $target -H3 -T0x0600 -l $prereq
- ls -l $target
-
-pbs&: pbs%.$O
- $LD -o $target -H3 -T0x7C00 -l $prereq
- ls -l $target
-
-pbs&.debug: pbs%.$O
- $LD -o $target -T0x7C00 -l $prereq
- ls -l $target
- # acid $target
- # map({"text", 0x7C00, 0x7E00, 0x00000020})
-
-# added to cause libflate to be made automatically:
-
-$ROOT/Inferno/$OBJTYPE/lib/lib%.a:Q: all-$SHELLTYPE
- #
-
-rc-lib%.a nt-lib%.a:VQ:
- echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
- @{builtin cd $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
-
-sh-lib%.a:VQ:
- echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
- (cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
-
-clean:
- rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG 9loaddebug lddebug
-
-install:V:
- for (i in $TARG)
- mk $MKFLAGS $i.install
-
-%.install:V: $BIN/%
-
-$BIN/%: %
- cp $stem $BIN/$stem
-
-UPDATE=\
- mkfile\
- ${CORE:%.$O=%.c}\
- ${LOAD:%.$O=%.c}\
- ${BCOM:%.$O=%.c}\
- ${ETHER:%.$O=%.c}\
- $HFILES\
- l.s\
- noether.c\
- pbs.s\
- pbslba.s\
- mbr.s\
- x16.h\
- ureg.h\
- dosfs.h\
- fs.h\
- kfs.h\
- etherif.h\
- sd.h\
- ip.h\
- devfloppy.h\
- ${TARG:%=/386/%}\
-
-update:V:
- update $UPDATEFLAGS $UPDATE
-
-
-%-sh:QV:
- for i in $LIBDIRS
- do
- echo "(cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem)"
- (cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem)
- done
-
-%-rc %-nt:QV:
- for (i in $LIBDIRS)
- {
- echo '@{cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem}'
- @{cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem}
- }
-
-nuke:V: clean nuke-$SHELLTYPE
--- a/os/boot/pc/noether.c
+++ /dev/null
@@ -1,46 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-int
-etherinit(void)
-{
- return -1;
-}
-
-void
-etherinitdev(int, char*)
-{
-}
-
-void
-etherprintdevs(int)
-{
-}
-
-int
-etherrxpkt(int, Etherpkt*, int)
-{
- return -1;
-}
-
-int
-ethertxpkt(int, Etherpkt*, int, int)
-{
- return -1;
-}
-
-int
-bootpboot(int, char*, Boot*)
-{
- return -1;
-}
-
-void*
-pxegetfspart(int, char*, int)
-{
- return nil;
-}
--- a/os/boot/pc/part.c
+++ /dev/null
@@ -1,344 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-#include "sd.h"
-#include "fs.h"
-
-enum {
- Npart = 32
-};
-
-uchar *mbrbuf, *partbuf;
-int nbuf;
-#define trace 0
-
-int
-tsdbio(SDunit *unit, SDpart *part, void *a, vlong off, int mbr)
-{
- uchar *b;
-
- if(sdbio(unit, part, a, unit->secsize, off) != unit->secsize){
- if(trace)
- print("%s: read %lud at %lld failed\n", unit->name,
- unit->secsize, (vlong)part->start*unit->secsize+off);
- return -1;
- }
- b = a;
- if(mbr && (b[0x1FE] != 0x55 || b[0x1FF] != 0xAA)){
- if(trace)
- print("%s: bad magic %.2ux %.2ux at %lld\n",
- unit->name, b[0x1FE], b[0x1FF],
- (vlong)part->start*unit->secsize+off);
- return -1;
- }
- return 0;
-}
-
-/*
- * read partition table. The partition table is just ascii strings.
- */
-#define MAGIC "plan9 partitions"
-static void
-oldp9part(SDunit *unit)
-{
- SDpart *pp;
- char *field[3], *line[Npart+1];
- ulong n, start, end;
- int i;
-
- /*
- * We have some partitions already.
- */
- pp = &unit->part[unit->npart];
-
- /*
- * We prefer partition tables on the second to last sector,
- * but some old disks use the last sector instead.
- */
- strcpy(pp->name, "partition");
- pp->start = unit->sectors - 2;
- pp->end = unit->sectors - 1;
-
- if(tsdbio(unit, pp, partbuf, 0, 0) < 0)
- return;
-
- if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0) {
- /* not found on 2nd last sector; look on last sector */
- pp->start++;
- pp->end++;
- if(tsdbio(unit, pp, partbuf, 0, 0) < 0)
- return;
- if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0)
- return;
- print("%s: using old plan9 partition table on last sector\n", unit->name);
- }else
- print("%s: using old plan9 partition table on 2nd-to-last sector\n", unit->name);
-
- /* we found a partition table, so add a partition partition */
- unit->npart++;
- partbuf[unit->secsize-1] = '\0';
-
- /*
- * parse partition table
- */
- n = getfields((char*)partbuf, line, Npart+1, '\n');
- if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
- for(i = 1; i < n && unit->npart < SDnpart; i++){
- if(getfields(line[i], field, 3, ' ') != 3)
- break;
- start = strtoull(field[1], 0, 0);
- end = strtoull(field[2], 0, 0);
- if(start >= end || end > unit->sectors)
- break;
- sdaddpart(unit, field[0], start, end);
- }
- }
-}
-
-static void
-p9part(SDunit *unit, char *name)
-{
- SDpart *p;
- char *field[4], *line[Npart+1];
- uvlong start, end;
- int i, n;
-
- p = sdfindpart(unit, name);
- if(p == nil)
- return;
-
- if(tsdbio(unit, p, partbuf, unit->secsize, 0) < 0)
- return;
- partbuf[unit->secsize-1] = '\0';
-
- if(strncmp((char*)partbuf, "part ", 5) != 0)
- return;
-
- n = getfields((char*)partbuf, line, Npart+1, '\n');
- if(n == 0)
- return;
- for(i = 0; i < n && unit->npart < SDnpart; i++){
- if(strncmp(line[i], "part ", 5) != 0)
- break;
- if(getfields(line[i], field, 4, ' ') != 4)
- break;
- start = strtoull(field[2], 0, 0);
- end = strtoull(field[3], 0, 0);
- if(start >= end || end > unit->sectors)
- break;
- sdaddpart(unit, field[1], p->start+start, p->start+end);
- }
-}
-
-int
-isdos(int t)
-{
- return t==FAT12 || t==FAT16 || t==FATHUGE || t==FAT32 || t==FAT32X;
-}
-
-int
-isextend(int t)
-{
- return t==EXTEND || t==EXTHUGE || t==LEXTEND;
-}
-
-/*
- * Fetch the first dos and all plan9 partitions out of the MBR partition table.
- * We return -1 if we did not find a plan9 partition.
- */
-static int
-mbrpart(SDunit *unit)
-{
- Dospart *dp;
- ulong taboffset, start, end;
- ulong firstxpart, nxtxpart;
- int havedos, i, nplan9;
- char name[10];
-
- taboffset = 0;
- dp = (Dospart*)&mbrbuf[0x1BE];
- if(1) {
- /* get the MBR (allowing for DMDDO) */
- if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0)
- return -1;
- for(i=0; i<4; i++)
- if(dp[i].type == DMDDO) {
- if(trace)
- print("DMDDO partition found\n");
- taboffset = 63;
- if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0)
- return -1;
- i = -1; /* start over */
- }
- }
-
- /*
- * Read the partitions, first from the MBR and then
- * from successive extended partition tables.
- */
- nplan9 = 0;
- havedos = 0;
- firstxpart = 0;
- for(;;) {
- if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0)
- return -1;
- if(trace) {
- if(firstxpart)
- print("%s ext %lud ", unit->name, taboffset);
- else
- print("%s mbr ", unit->name);
- }
- nxtxpart = 0;
- for(i=0; i<4; i++) {
- if(trace)
- print("dp %d...", dp[i].type);
- start = taboffset+GLONG(dp[i].start);
- end = start+GLONG(dp[i].len);
-
- if(dp[i].type == PLAN9) {
- if(nplan9 == 0)
- strcpy(name, "plan9");
- else
- sprint(name, "plan9.%d", nplan9);
- sdaddpart(unit, name, start, end);
- p9part(unit, name);
- nplan9++;
- }
-
- /*
- * We used to take the active partition (and then the first
- * when none are active). We have to take the first here,
- * so that the partition we call ``dos'' agrees with the
- * partition disk/fdisk calls ``dos''.
- */
- if(havedos==0 && isdos(dp[i].type)){
- havedos = 1;
- sdaddpart(unit, "dos", start, end);
- }
-
- /* nxtxpart is relative to firstxpart (or 0), not taboffset */
- if(isextend(dp[i].type)){
- nxtxpart = start-taboffset+firstxpart;
- if(trace)
- print("link %lud...", nxtxpart);
- }
- }
- if(trace)
- print("\n");
-
- if(!nxtxpart)
- break;
- if(!firstxpart)
- firstxpart = nxtxpart;
- taboffset = nxtxpart;
- }
- return nplan9 ? 0 : -1;
-}
-
-/*
- * To facilitate booting from CDs, we create a partition for
- * the boot floppy image embedded in a bootable CD.
- */
-static int
-part9660(SDunit *unit)
-{
- uchar buf[2048];
- ulong a, n;
- uchar *p;
-
- if(unit->secsize != 2048)
- return -1;
-
- if(sdbio(unit, &unit->part[0], buf, 2048, 17*2048) < 0)
- return -1;
-
- if(buf[0] || strcmp((char*)buf+1, "CD001\x01EL TORITO SPECIFICATION") != 0)
- return -1;
-
-
- p = buf+0x47;
- a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
-
- if(sdbio(unit, &unit->part[0], buf, 2048, a*2048) < 0)
- return -1;
-
- if(memcmp(buf, "\x01\x00\x00\x00", 4) != 0
- || memcmp(buf+30, "\x55\xAA", 2) != 0
- || buf[0x20] != 0x88)
- return -1;
-
- p = buf+0x28;
- a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
-
- switch(buf[0x21]){
- case 0x01:
- n = 1200*1024;
- break;
- case 0x02:
- n = 1440*1024;
- break;
- case 0x03:
- n = 2880*1024;
- break;
- default:
- return -1;
- }
- n /= 2048;
-
- print("found partition %s!cdboot; %lud+%lud\n", unit->name, a, n);
- sdaddpart(unit, "cdboot", a, a+n);
- return 0;
-}
-
-enum {
- NEW = 1<<0,
- OLD = 1<<1
-};
-
-void
-partition(SDunit *unit)
-{
- int type;
- char *p;
-
- if(unit->part == 0)
- return;
-
- if(part9660(unit) == 0)
- return;
-
- p = getconf("partition");
- if(p == nil)
- p = defaultpartition;
-
- if(p != nil && strncmp(p, "new", 3) == 0)
- type = NEW;
- else if(p != nil && strncmp(p, "old", 3) == 0)
- type = OLD;
- else
- type = NEW|OLD;
-
- if(nbuf < unit->secsize) {
- free(mbrbuf);
- free(partbuf);
- mbrbuf = malloc(unit->secsize);
- partbuf = malloc(unit->secsize);
- if(mbrbuf==nil || partbuf==nil) {
- free(mbrbuf);
- free(partbuf);
- partbuf = mbrbuf = nil;
- nbuf = 0;
- return;
- }
- nbuf = unit->secsize;
- }
-
- if((type & NEW) && mbrpart(unit) >= 0){
- /* nothing to do */;
- }
- else if(type & OLD)
- oldp9part(unit);
-}
--- a/os/boot/pc/pbs.s
+++ /dev/null
@@ -1,372 +1,0 @@
-/*
- * FAT Partition Boot Sector. Loaded at 0x7C00:
- * 8a pbs.s; 8l -o pbs -l -H3 -T0x7C00 pbs.8
- * Will load the target at LOADSEG*16+LOADOFF, so the target
- * should be probably be loaded with LOADOFF added to the
- * -Taddress.
- * If LOADSEG is a multiple of 64KB and LOADOFF is 0 then
- * targets larger than 64KB can be loaded.
- *
- * This code uses the traditional INT13 BIOS interface and can
- * therefore only access the first 8.4GB of the disc.
- *
- * It relies on the _volid field in the FAT header containing
- * the LBA of the root directory.
- */
-#include "x16.h"
-#include "mem.h"
-
-#define LOADSEG (0x10000/16) /* where to load code (64KB) */
-#define LOADOFF 0
-#define DIROFF 0x0200 /* where to read the root directory */
-
-/*
- * FAT directory entry.
- */
-#define Dname 0x00
-#define Dext 0x08
-#define Dattr 0x0B
-#define Dtime 0x16
-#define Ddate 0x18
-#define Dstart 0x1A
-#define Dlengthlo 0x1C
-#define Dlengthhi 0x1E
-
-#define Dirsz 0x20
-
-/*
- * Data is kept on the stack, indexed by rBP.
- */
-#define Xdap 0x00 /* disc address packet */
-#define Xrootsz 0x10 /* file data area */
-#define Xdrive 0x12 /* boot drive, passed by BIOS or MBR */
-#define Xtotal 0x14 /* sum of allocated data above */
-
-TEXT _magic(SB), $0
- BYTE $0xEB; BYTE $0x3C; /* jmp .+ 0x3C (_start0x3E) */
- BYTE $0x90 /* nop */
-TEXT _version(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _sectsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _clustsize(SB), $0
- BYTE $0x00
-TEXT _nresrv(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nfats(SB), $0
- BYTE $0x00
-TEXT _rootsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _volsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _mediadesc(SB), $0
- BYTE $0x00
-TEXT _fatsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _trksize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nheads(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nhiddenlo(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nhiddenhi(SB), $0
- BYTE $0x00; BYTE $0x00;
-TEXT _bigvolsize(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _driveno(SB), $0
- BYTE $0x00
-TEXT _reserved0(SB), $0
- BYTE $0x00
-TEXT _bootsig(SB), $0
- BYTE $0x00
-TEXT _volid(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _label(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
- BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _type(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-
-_start0x3E:
- CLI
- CLR(rAX)
- MTSR(rAX, rSS) /* 0000 -> rSS */
- MTSR(rAX, rDS) /* 0000 -> rDS, source segment */
- MTSR(rAX, rES)
- LWI(_magic-Xtotal(SB), rSP)
- MW(rSP, rBP) /* set the indexed-data pointer */
-
- SBPB(rDL, Xdrive) /* save the boot drive */
-
- /* booting from a CD starts us at 7C0:0. Move to 0:7C00 */
- PUSHR(rAX)
- LWI(_nxt(SB), rAX)
- PUSHR(rAX)
- BYTE $0xCB /* FAR RET */
-
-TEXT _nxt(SB), $0
- STI
-
- LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
- CALL16(BIOSputs(SB))
-
- CALL16(dreset(SB))
-
-_jmp00:
- LW(_volid(SB), rAX) /* Xrootlo */
- LW(_volid+2(SB), rDX) /* Xroothi */
-
- LWI(_magic+DIROFF(SB), rBX)
- CALL16(BIOSread(SB)) /* read the root directory */
-
- LWI((512/Dirsz), rBX)
-
- LWI(_magic+DIROFF(SB), rDI) /* compare first directory entry */
-
-_cmp00:
- PUSHR(rDI) /* save for later if it matches */
- LWI(bootfile(SB), rSI)
- LWI(Dattr, rCX)
- REP
- CMPSB
- POPR(rDI)
- JEQ _jmp02
-
- DEC(rBX)
- JEQ _jmp01
-
- ADDI(Dirsz, rDI)
- JMP _cmp00
-_jmp01:
- CALL16(buggery(SB))
-
-_jmp02:
- CLR(rBX) /* a handy value */
- LW(_rootsize(SB), rAX) /* calculate and save Xrootsz */
- LWI(Dirsz, rCX)
- MUL(rCX)
- LW(_sectsize(SB), rCX)
- PUSHR(rCX)
- DEC(rCX)
- ADD(rCX, rAX)
- ADC(rBX, rDX)
- POPR(rCX) /* _sectsize(SB) */
- DIV(rCX)
- PUSHR(rAX) /* Xrootsz */
-
- /*
- * rDI points to the matching directory entry.
- */
- LXW(Dstart, xDI, rAX) /* starting sector address */
- DEC(rAX) /* that's just the way it is */
- DEC(rAX)
- LB(_clustsize(SB), rCL)
- CLRB(rCH)
- MUL(rCX)
- LW(_volid(SB), rCX) /* Xrootlo */
- ADD(rCX, rAX)
- LW(_volid+2(SB), rCX) /* Xroothi */
- ADC(rCX, rDX)
- POPR(rCX) /* Xrootsz */
- ADD(rCX, rAX)
- ADC(rBX, rDX)
-
- PUSHR(rAX) /* calculate how many sectors to read */
- PUSHR(rDX)
- LXW(Dlengthlo, xDI, rAX)
- LXW(Dlengthhi, xDI, rDX)
- LW(_sectsize(SB), rCX)
- PUSHR(rCX)
- DEC(rCX)
- ADD(rCX, rAX)
- ADC(rBX, rDX)
- POPR(rCX) /* _sectsize(SB) */
- DIV(rCX)
- MW(rAX, rCX)
- POPR(rDX)
- POPR(rAX)
-
- LWI(LOADSEG, rBX) /* address to load into (seg+offset) */
- MTSR(rBX, rES) /* seg */
- LWI(LOADOFF, rBX) /* offset */
-
-_readboot:
- CALL16(BIOSread(SB)) /* read the sector */
-
- LW(_sectsize(SB), rDI) /* bump addresses/counts */
- ADD(rDI, rBX)
- JCC _incsecno
-
- MFSR(rES, rDI) /* next 64KB segment */
- ADDI(0x1000, rDI)
- MTSR(rDI, rES)
-
-_incsecno:
- CLR(rDI)
- INC(rAX)
- ADC(rDI, rDX)
- LOOP _readboot
-
- LWI(LOADSEG, rDI) /* set rDS for loaded code */
- MTSR(rDI, rDS)
- FARJUMP16(LOADSEG, LOADOFF) /* no deposit, no return */
-
-TEXT buggery(SB), $0
- LWI(error(SB), rSI)
- CALL16(BIOSputs(SB))
-
-_wait:
- CLR(rAX) /* wait for almost any key */
- BIOSCALL(0x16)
-
-_reset:
- CLR(rBX) /* set ES segment for BIOS area */
- MTSR(rBX, rES)
-
- LWI(0x0472, rBX) /* warm-start code address */
- LWI(0x1234, rAX) /* warm-start code */
- POKEW /* MOVW AX, ES:[BX] */
-
- FARJUMP16(0xFFFF, 0x0000) /* reset */
-
-/*
- * Read a sector from a disc. On entry:
- * rDX:rAX sector number
- * rES:rBX buffer address
- * For BIOSCALL(0x13):
- * rAH 0x02
- * rAL number of sectors to read (1)
- * rCH low 8 bits of cylinder
- * rCL high 2 bits of cylinder (7-6), sector (5-0)
- * rDH head
- * rDL drive
- * rES:rBX buffer address
- */
-TEXT BIOSread(SB), $0
- LWI(5, rDI) /* retry count (ATAPI ZIPs suck) */
-_retry:
- PUSHA /* may be trashed by BIOSCALL */
- PUSHR(rBX)
-
- LW(_trksize(SB), rBX)
- LW(_nheads(SB), rDI)
- IMUL(rDI, rBX)
- OR(rBX, rBX)
- JZ _ioerror
-
-_okay:
- DIV(rBX) /* cylinder -> rAX, track,sector -> rDX */
-
- MW(rAX, rCX) /* save cylinder */
- ROLI(0x08, rCX) /* swap rC[HL] */
- SHLBI(0x06, rCL) /* move high bits up */
-
- MW(rDX, rAX)
- CLR(rDX)
- LW(_trksize(SB), rBX)
-
- DIV(rBX) /* head -> rAX, sector -> rDX */
-
- INC(rDX) /* sector numbers are 1-based */
- ANDI(0x003F, rDX) /* should not be necessary */
- OR(rDX, rCX)
-
- MW(rAX, rDX)
- SHLI(0x08, rDX) /* form head */
- LBPB(Xdrive, rDL) /* form drive */
-
- POPR(rBX)
- LWI(0x0201, rAX) /* form command and sectors */
- BIOSCALL(0x13) /* CF set on failure */
- JCC _BIOSreadret
-
- POPA
- DEC(rDI) /* too many retries? */
- JEQ _ioerror
-
- CALL16(dreset(SB))
- JMP _retry
-
-_ioerror:
- LWI(ioerror(SB), rSI)
- CALL16(BIOSputs(SB))
- JMP _wait
-
-_BIOSreadret:
- POPA
- RET
-
-TEXT dreset(SB), $0
- PUSHA
- CLR(rAX) /* rAH == 0 == reset disc system */
- LBPB(Xdrive, rDL)
- BIOSCALL(0x13)
- ORB(rAH, rAH) /* status (0 == success) */
- POPA
- JNE _ioerror
- RET
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT BIOSputs(SB), $0
- PUSHA
- CLR(rBX)
-_BIOSputs:
- LODSB
- ORB(rAL, rAL)
- JEQ _BIOSputsret
-
- LBI(0x0E, rAH)
- BIOSCALL(0x10)
- JMP _BIOSputs
-
-_BIOSputsret:
- POPA
- RET
-
-/* "Bad format or I/O error\r\nPress almost any key to reboot..."*/
-TEXT error(SB), $0
- BYTE $'B'; BYTE $'a'; BYTE $'d'; BYTE $' ';
- BYTE $'f'; BYTE $'o'; BYTE $'r'; BYTE $'m';
- BYTE $'a'; BYTE $'t'; BYTE $' '; BYTE $'o';
- BYTE $'r'; BYTE $' ';
-/* "I/O error\r\nPress almost any key to reboot..." */
-TEXT ioerror(SB), $0
- BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
- BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
- BYTE $'r'; BYTE $'\r';BYTE $'\n';
- BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
- BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $' ';
- BYTE $'k'; BYTE $'e'; BYTE $'y';
- BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
- BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
- BYTE $'o'; BYTE $'t';
- BYTE $'.'; BYTE $'.'; BYTE $'.';
- BYTE $'\z';
-
-#ifdef USEBCOM
-/* "B COM" */
-TEXT bootfile(SB), $0
- BYTE $'B'; BYTE $' '; BYTE $' '; BYTE $' ';
- BYTE $' '; BYTE $' '; BYTE $' '; BYTE $' ';
- BYTE $'C'; BYTE $'O'; BYTE $'M';
- BYTE $'\z';
-#else
-/* "9LOAD " */
-TEXT bootfile(SB), $0
- BYTE $'9'; BYTE $'L'; BYTE $'O'; BYTE $'A';
- BYTE $'D'; BYTE $' '; BYTE $' '; BYTE $' ';
- BYTE $' '; BYTE $' '; BYTE $' ';
- BYTE $'\z';
-#endif /* USEBCOM */
-
-/* "PBS..." */
-TEXT confidence(SB), $0
- BYTE $'P'; BYTE $'B'; BYTE $'S'; BYTE $'1';
- BYTE $'.'; BYTE $'.'; BYTE $'.';
- BYTE $'\z';
binary files a/os/boot/pc/pbsdisk /dev/null differ
--- a/os/boot/pc/pbsdisk.s
+++ /dev/null
@@ -1,344 +1,0 @@
-/*
- * Debugging boot sector. Reads the first directory
- * sector from disk and displays it.
- *
- * It relies on the _volid field in the FAT header containing
- * the LBA of the root directory.
- */
-#include "x16.h"
-
-#define DIROFF 0x00200 /* where to read the root directory (offset) */
-#define LOADSEG (0x10000/16) /* where to load code (64KB) */
-#define LOADOFF 0
-
-/*
- * FAT directory entry.
- */
-#define Dname 0x00
-#define Dext 0x08
-#define Dattr 0x0B
-#define Dtime 0x16
-#define Ddate 0x18
-#define Dstart 0x1A
-#define Dlengthlo 0x1C
-#define Dlengthhi 0x1E
-
-#define Dirsz 0x20
-
-/*
- * We keep data on the stack, indexed by rBP.
- */
-#define Xdrive 0x00 /* boot drive, passed by BIOS in rDL */
-#define Xrootlo 0x02 /* offset of root directory */
-#define Xroothi 0x04
-#define Xrootsz 0x06 /* file data area */
-#define Xtotal 0x08 /* sum of allocated data above */
-#define Xdap 0x00 /* disc address packet */
-
-TEXT _magic(SB), $0
- BYTE $0xEB; BYTE $0x3C; /* jmp .+ 0x3C (_start0x3E) */
- BYTE $0x90 /* nop */
-TEXT _version(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _sectsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _clustsize(SB), $0
- BYTE $0x00
-TEXT _nresrv(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nfats(SB), $0
- BYTE $0x00
-TEXT _rootsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _volsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _mediadesc(SB), $0
- BYTE $0x00
-TEXT _fatsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _trksize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nheads(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nhiddenlo(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nhiddenhi(SB), $0
- BYTE $0x00; BYTE $0x00;
-TEXT _bigvolsize(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _driveno(SB), $0
- BYTE $0x00
-TEXT _reserved0(SB), $0
- BYTE $0x00
-TEXT _bootsig(SB), $0
- BYTE $0x00
-TEXT _volid(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _label(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
- BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _type(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-
-_start0x3E:
- CLI
- CLR(rAX)
- MTSR(rAX, rSS) /* 0000 -> rSS */
- MTSR(rAX, rDS) /* 0000 -> rDS, source segment */
- MTSR(rAX, rES)
- LWI(_magic-Xtotal(SB), rSP)
- MW(rSP, rBP) /* set the indexed-data pointer */
- SBPB(rDL, Xdrive) /* save the boot drive */
-
- /* VMware starts us at 7C0:0. Move to 0:7C00 */
- PUSHR(rAX)
- LWI(_nxt(SB), rAX)
- PUSHR(rAX)
- BYTE $0xCB /* FAR RET */
-
-TEXT _nxt(SB), $0
- STI
- LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
- CALL16(BIOSputs(SB))
-
- CALL16(dreset(SB))
-
-_jmp00:
- LW(_volid(SB), rAX) /* Xrootlo */
- LW(_volid+2(SB), rDX) /* Xroothi */
-
- LWI(_magic+DIROFF(SB), rBX)
- CALL16(BIOSread(SB)) /* read the root directory */
-
- CALL16(printnl(SB))
- LWI(_magic+DIROFF(SB), rBX)
- LWI((512/2), rCX)
- CALL16(printbuf(SB))
-
-xloop:
- JMP xloop
-
-
-TEXT buggery(SB), $0
- LWI(error(SB), rSI)
- CALL16(BIOSputs(SB))
-
-TEXT quietbuggery(SB), $0
-xbuggery:
- JMP xbuggery
-
-/*
- * Read a sector from a disc. On entry:
- * rDX:rAX sector number
- * rES:rBX buffer address
- * For BIOSCALL(0x13):
- * rAH 0x02
- * rAL number of sectors to read (1)
- * rCH low 8 bits of cylinder
- * rCL high 2 bits of cylinder (7-6), sector (5-0)
- * rDH head
- * rDL drive
- * rES:rBX buffer address
- */
-TEXT BIOSread(SB), $0
- LWI(5, rDI) /* retry count (ATAPI ZIPs suck) */
-_retry:
- PUSHA /* may be trashed by BIOSCALL */
- PUSHR(rBX)
-
- LW(_trksize(SB), rBX)
- LW(_nheads(SB), rDI)
- IMUL(rDI, rBX)
- OR(rBX, rBX)
- JZ _ioerror
-
-_okay:
- DIV(rBX) /* cylinder -> rAX, track,sector -> rDX */
-
- MW(rAX, rCX) /* save cylinder */
- ROLI(0x08, rCX) /* swap rC[HL] */
- SHLBI(0x06, rCL) /* move high bits up */
-
- MW(rDX, rAX)
- CLR(rDX)
- LW(_trksize(SB), rBX)
-
- DIV(rBX) /* head -> rAX, sector -> rDX */
-
- INC(rDX) /* sector numbers are 1-based */
- ANDI(0x003F, rDX) /* should not be necessary */
- OR(rDX, rCX)
-
- MW(rAX, rDX)
- SHLI(0x08, rDX) /* form head */
- LBPB(Xdrive, rDL) /* form drive */
-
- POPR(rBX)
- LWI(0x0201, rAX) /* form command and sectors */
- BIOSCALL(0x13) /* CF set on failure */
- JCC _BIOSreadret
-
- POPA
- DEC(rDI) /* too many retries? */
- JEQ _ioerror
-
- CALL16(dreset(SB))
- JMP _retry
-
-_ioerror:
- LWI(ioerror(SB), rSI)
- CALL16(BIOSputs(SB))
- JMP xbuggery
-
-_BIOSreadret:
- POPA
- RET
-
-TEXT dreset(SB), $0
- PUSHA
- CLR(rAX) /* rAH == 0 == reset disc system */
- LBPB(Xdrive, rDL)
- BIOSCALL(0x13)
- ORB(rAH, rAH) /* status (0 == success) */
- POPA
- JNE _ioerror
- RET
-
-TEXT printsharp(SB), $0
- LWI(sharp(SB), rSI)
-_doprint:
- CALL16(BIOSputs(SB))
- RET
-
-TEXT printspace(SB), $0
- LWI(space(SB), rSI)
- JMP _doprint
-
-TEXT printnl(SB), $0
- LWI(nl(SB), rSI)
- JMP _doprint
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT BIOSputs(SB), $0
- PUSHA
- CLR(rBX)
-_BIOSputs:
- LODSB
- ORB(rAL, rAL)
- JEQ _BIOSputsret
-
- LBI(0x0E, rAH)
- BIOSCALL(0x10)
- JMP _BIOSputs
-
-_BIOSputsret:
- POPA
- RET
-
-/*
- * Output a register to the display.
- */
-TEXT printAX(SB), $0
- PUSHW(rAX)
- PUSHW(rBX)
- PUSHW(rCX)
- PUSHW(rDI)
-
- LWI(4, rCX)
- LWI(numbuf+4(SB), rSI)
-
-_nextchar:
- DEC(rSI)
- MW(rAX, rBX)
- ANDI(0x000F, rBX)
- ADDI(0x30, rBX) /* 0x30 = '0' */
- CMPI(0x39, rBX) /* 0x39 = '9' */
- JLE _dowrite
- ADDI(0x07, rBX) /* 0x07 = 'A'-(1+'9')*/
-
-_dowrite:
- SXB(rBL, 0, xSI)
- SHRI(4, rAX)
-
- DEC(rCX)
- JNE _nextchar
-
- LWI(numbuf(SB), rSI)
- CALL16(BIOSputs(SB))
-
- POPW(rDI)
- POPW(rCX)
- POPW(rBX)
- POPW(rAX)
-
- CALL16(printspace(SB))
- RET
-
-TEXT printDXAX(SB), $0
- PUSHW(rAX)
- MW(rDX, rAX)
- CALL16(printAX(SB))
- POPW(rAX)
- CALL16(printAX(SB))
- RET
-
-TEXT printBX(SB), $0
- PUSHW(rAX)
- MW(rBX, rAX)
- CALL16(printAX(SB))
- POPW(rAX)
- RET
-
-/*
- * Output some number of words to the display
- * rDS:rDI - buffer
- * rCX: number of words
- */
-TEXT printbuf(SB), $0
- PUSHW(rAX)
- PUSHW(rBX)
- PUSHW(rCX)
-
-_nextword:
- LXW(0, xBX, rAX)
- CALL16(printAX(SB))
- INC(rBX)
- INC(rBX)
- DEC(rCX)
- JNE _nextword
-
- POPW(rCX)
- POPW(rBX)
- POPW(rAX)
- RET
-
-TEXT error(SB), $0
- BYTE $'E';
-
-TEXT ioerror(SB), $0
- BYTE $'I';
-
-TEXT nl(SB), $0
- BYTE $'\r';
- BYTE $'\n';
- BYTE $'\z';
-
-TEXT numbuf(SB), $0
- BYTE $'X'; BYTE $'X'; BYTE $'X'; BYTE $'X';
- BYTE $'\z';
-
-TEXT space(SB), $0
- BYTE $' ';
- BYTE $'\z';
-
-TEXT sharp(SB), $0
- BYTE $'#'; BYTE $'\z';
-
-TEXT confidence(SB), $0
- BYTE $'P'; BYTE $'\z'
binary files a/os/boot/pc/pbsdisklba /dev/null differ
--- a/os/boot/pc/pbsdisklba.s
+++ /dev/null
@@ -1,327 +1,0 @@
-/*
- * Debugging boot sector. Reads the first directory
- * sector from disk and displays it.
- *
- * It relies on the _volid field in the FAT header containing
- * the LBA of the root directory.
- */
-#include "x16.h"
-
-#define DIROFF 0x00200 /* where to read the root directory (offset) */
-#define LOADSEG (0x10000/16) /* where to load code (64KB) */
-#define LOADOFF 0
-
-/*
- * FAT directory entry.
- */
-#define Dname 0x00
-#define Dext 0x08
-#define Dattr 0x0B
-#define Dtime 0x16
-#define Ddate 0x18
-#define Dstart 0x1A
-#define Dlengthlo 0x1C
-#define Dlengthhi 0x1E
-
-#define Dirsz 0x20
-
-/*
- * We keep data on the stack, indexed by rBP.
- */
-#define Xdrive 0x00 /* boot drive, passed by BIOS in rDL */
-#define Xrootlo 0x02 /* offset of root directory */
-#define Xroothi 0x04
-#define Xrootsz 0x06 /* file data area */
-#define Xtotal 0x08 /* sum of allocated data above */
-#define Xdap 0x00 /* disc address packet */
-
-TEXT _magic(SB), $0
- BYTE $0xEB; BYTE $0x3C; /* jmp .+ 0x3C (_start0x3E) */
- BYTE $0x90 /* nop */
-TEXT _version(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _sectsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _clustsize(SB), $0
- BYTE $0x00
-TEXT _nresrv(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nfats(SB), $0
- BYTE $0x00
-TEXT _rootsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _volsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _mediadesc(SB), $0
- BYTE $0x00
-TEXT _fatsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _trksize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nheads(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nhiddenlo(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nhiddenhi(SB), $0
- BYTE $0x00; BYTE $0x00;
-TEXT _bigvolsize(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _driveno(SB), $0
- BYTE $0x00
-TEXT _reserved0(SB), $0
- BYTE $0x00
-TEXT _bootsig(SB), $0
- BYTE $0x00
-TEXT _volid(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _label(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
- BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _type(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-
-_start0x3E:
- CLI
- CLR(rAX)
- MTSR(rAX, rSS) /* 0000 -> rSS */
- MTSR(rAX, rDS) /* 0000 -> rDS, source segment */
- MTSR(rAX, rES)
- LWI(_magic-Xtotal(SB), rSP)
- MW(rSP, rBP) /* set the indexed-data pointer */
-
- SBPB(rDL, Xdrive) /* save the boot drive */
-
- STI
-
- LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
- CALL(BIOSputs(SB))
-
- LBI(0x41, rAH) /* check extensions present */
- LWI(0x55AA, rBX)
- LXB(Xdrive, xBP, rDL) /* drive */
- SYSCALL(0x13) /* CF set on failure */
- JCS _jmp01
- CMPI(0xAA55, rBX)
- JNE _jmp01
- ANDI(0x0001, rCX)
- JEQ _jmp01
-
- /* rCX contains 0x0001 */
- SBPWI(0x0010, Xdap+0) /* reserved + packet size */
- SBPW(rCX, Xdap+2) /* reserved + # of blocks to transfer */
-
- DEC(rCX)
- SBPW(rCX, Xdap+12)
- SBPW(rCX, Xdap+14)
-
-/* BIOSread will do this CALL(dreset(SB)) */
-
-_jmp00:
- LW(_volid(SB), rAX) /* Xrootlo */
- LW(_volid+2(SB), rDX) /* Xroothi */
-
- LWI(_magic+DIROFF(SB), rBX)
- CALL(BIOSread(SB)) /* read the root directory */
-
- CALL(printnl(SB))
- LWI(_magic+DIROFF(SB), rBX)
- LWI((512/2), rCX)
- CALL(printbuf(SB))
-
-xloop:
- JMP xloop
-
-
-_jmp01:
-
-TEXT buggery(SB), $0
- LWI(error(SB), rSI)
- CALL(BIOSputs(SB))
-
-xbuggery:
- JMP xbuggery
-
-/*
- * Read a sector from a disc. On entry:
- * rDX:rAX sector number
- * rES:rBX buffer address
- */
-TEXT BIOSread(SB), $0
- LWI(5, rDI) /* retry count (ATAPI ZIPs suck) */
-_retry:
- PUSHA /* may be trashed by SYSCALL */
-
- SBPW(rBX, Xdap+4) /* transfer buffer :offset */
- MFSR(rES, rDI) /* transfer buffer seg: */
- SBPW(rDI, Xdap+6)
- SBPW(rAX, Xdap+8) /* LBA (64-bits) */
- SBPW(rDX, Xdap+10)
-
- MW(rBP, rSI) /* disk address packet */
- LBI(0x42, rAH) /* extended read */
- LBPB(Xdrive, rDL) /* form drive */
- SYSCALL(0x13) /* CF set on failure */
- JCC _BIOSreadret
-
- POPA
- DEC(rDI) /* too many retries? */
- JEQ _ioerror
-
- CALL(dreset(SB))
- JMP _retry
-
-_ioerror:
- LWI(ioerror(SB), rSI)
- CALL(BIOSputs(SB))
- JMP xbuggery
-
-_BIOSreadret:
- POPA
- RET
-
-TEXT dreset(SB), $0
- PUSHA
- CLR(rAX) /* rAH == 0 == reset disc system */
- LBPB(Xdrive, rDL)
- SYSCALL(0x13)
- ORB(rAH, rAH) /* status (0 == success) */
- POPA
- JNE _ioerror
- RET
-
-
-TEXT printsharp(SB), $0
- LWI(sharp(SB), rSI)
-_doprint:
- CALL(BIOSputs(SB))
- RET
-
-TEXT printspace(SB), $0
- LWI(space(SB), rSI)
- JMP _doprint
-
-TEXT printnl(SB), $0
- LWI(nl(SB), rSI)
- JMP _doprint
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT BIOSputs(SB), $0
- PUSHA
- CLR(rBX)
-_BIOSputs:
- LODSB
- ORB(rAL, rAL)
- JEQ _BIOSputsret
-
- LBI(0x0E, rAH)
- SYSCALL(0x10)
- JMP _BIOSputs
-
-_BIOSputsret:
- POPA
- RET
-
-/*
- * Output a register to the display.
- */
-TEXT printAX(SB), $0
- PUSHW(rAX)
- PUSHW(rBX)
- PUSHW(rCX)
- PUSHW(rDI)
-
- LWI(4, rCX)
- LWI(numbuf+4(SB), rSI)
-
-_nextchar:
- DEC(rSI)
- MW(rAX, rBX)
- ANDI(0x000F, rBX)
- ADDI(0x30, rBX) /* 0x30 = '0' */
- CMPI(0x39, rBX) /* 0x39 = '9' */
- JLE _dowrite
- ADDI(0x07, rBX) /* 0x07 = 'A'-(1+'9')*/
-
-_dowrite:
- SXB(rBL, 0, xSI)
- SHRI(4, rAX)
-
- DEC(rCX)
- JNE _nextchar
-
- LWI(numbuf(SB), rSI)
- CALL(BIOSputs(SB))
-
- POPW(rDI)
- POPW(rCX)
- POPW(rBX)
- POPW(rAX)
-
- CALL(printspace(SB))
- RET
-
-TEXT printDXAX(SB), $0
- PUSHW(rAX)
- MW(rDX, rAX)
- CALL(printAX(SB))
- POPW(rAX)
- CALL(printAX(SB))
- RET
-
-TEXT printBX(SB), $0
- PUSHW(rAX)
- MW(rBX, rAX)
- CALL(printAX(SB))
- POPW(rAX)
- RET
-
-/*
- * Output some number of words to the display
- * rDS:rDI - buffer
- * rCX: number of words
- */
-TEXT printbuf(SB), $0
- PUSHW(rAX)
- PUSHW(rBX)
- PUSHW(rCX)
-
-_nextword:
- LXW(0, xBX, rAX)
- CALL(printAX(SB))
- INC(rBX)
- INC(rBX)
- DEC(rCX)
- JNE _nextword
-
- POPW(rCX)
- POPW(rBX)
- POPW(rAX)
- RET
-
-TEXT error(SB), $0
- BYTE $'E';
-
-TEXT ioerror(SB), $0
- BYTE $'I';
-
-TEXT nl(SB), $0
- BYTE $'\r';
- BYTE $'\n';
- BYTE $'\z';
-
-TEXT numbuf(SB), $0
- BYTE $'X'; BYTE $'X'; BYTE $'X'; BYTE $'X';
- BYTE $'\z';
-
-TEXT space(SB), $0
- BYTE $' ';
- BYTE $'\z';
-
-TEXT sharp(SB), $0
- BYTE $'#'; BYTE $'\z';
--- a/os/boot/pc/pbslba.s
+++ /dev/null
@@ -1,363 +1,0 @@
-/*
- * FAT Partition Boot Sector. Loaded at 0x7C00:
- * 8a pbslba.s; 8l -o pbslba -l -H3 -T0x7C00 pbslba.8
- * Will load the target at LOADSEG*16+LOADOFF, so the target
- * should be probably be loaded with LOADOFF added to the
- * -Taddress.
- * If LOADSEG is a multiple of 64KB and LOADOFF is 0 then
- * targets larger than 64KB can be loaded.
- *
- * This code is uses Enhanced BIOS Services for Disc Drives and
- * can be used with discs up to 137GB in capacity.
- *
- * It relies on the _volid field in the FAT header containing
- * the LBA of the root directory.
- */
-#include "x16.h"
-#include "mem.h"
-
-#define LOADSEG (0x10000/16) /* where to load code (64KB) */
-#define LOADOFF 0
-#define DIROFF 0x0200 /* where to read the root directory */
-
-/*
- * FAT directory entry.
- */
-#define Dname 0x00
-#define Dnamesz 0x0B
-#define Dext 0x08
-#define Dattr 0x0B
-#define Dtime 0x16
-#define Ddate 0x18
-#define Dstart 0x1A
-#define Dlengthlo 0x1C
-#define Dlengthhi 0x1E
-
-#define Dirsz 0x20
-
-/*
- * Data is kept on the stack, indexed by rBP.
- */
-#define Xdap 0x00 /* disc address packet */
-#define Xrootsz 0x10 /* file data area */
-#define Xdrive 0x12 /* boot drive, passed by BIOS or MBR */
-#define Xtotal 0x14 /* sum of allocated data above */
-
-TEXT _magic(SB), $0
- BYTE $0xEB; BYTE $0x3C; /* jmp .+ 0x3C (_start0x3E) */
- BYTE $0x90 /* nop */
-TEXT _version(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _sectsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _clustsize(SB), $0
- BYTE $0x00
-TEXT _nresrv(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nfats(SB), $0
- BYTE $0x00
-TEXT _rootsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _volsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _mediadesc(SB), $0
- BYTE $0x00
-TEXT _fatsize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _trksize(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nheads(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nhiddenlo(SB), $0
- BYTE $0x00; BYTE $0x00
-TEXT _nhiddenhi(SB), $0
- BYTE $0x00; BYTE $0x00;
-TEXT _bigvolsize(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _driveno(SB), $0
- BYTE $0x00
-TEXT _reserved0(SB), $0
- BYTE $0x00
-TEXT _bootsig(SB), $0
- BYTE $0x00
-TEXT _volid(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-TEXT _label(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
- BYTE $0x00; BYTE $0x00; BYTE $0x00
-TEXT _type(SB), $0
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
- BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
-
-_start0x3E:
- CLI
- CLR(rAX)
- MTSR(rAX, rSS) /* 0000 -> rSS */
- MTSR(rAX, rDS) /* 0000 -> rDS, source segment */
- MTSR(rAX, rES)
- LWI(_magic-Xtotal(SB), rSP)
- MW(rSP, rBP) /* set the indexed-data pointer */
-
- SBPB(rDL, Xdrive) /* save the boot drive */
-
- /* booting from a CD starts us at 7C0:0. Move to 0:7C00 */
- PUSHR(rAX)
- LWI(_nxt(SB), rAX)
- PUSHR(rAX)
- BYTE $0xCB /* FAR RET */
-
-TEXT _nxt(SB), $0
- STI
-
- LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
- CALL16(BIOSputs(SB))
-
- LBI(0x41, rAH) /* check extensions present */
- LWI(0x55AA, rBX)
- LXB(Xdrive, xBP, rDL) /* drive */
- BIOSCALL(0x13) /* CF set on failure */
- JCS _jmp01
- CMPI(0xAA55, rBX)
- JNE _jmp01
- ANDI(0x0001, rCX)
- JEQ _jmp01
-
- /* rCX contains 0x0001 */
- SBPWI(0x0010, Xdap+0) /* reserved + packet size */
- SBPW(rCX, Xdap+2) /* reserved + # of blocks to transfer */
-
- DEC(rCX)
- SBPW(rCX, Xdap+12)
- SBPW(rCX, Xdap+14)
-
- CALL16(dreset(SB))
-
-_jmp00:
- LW(_volid(SB), rAX) /* Xrootlo */
- LW(_volid+2(SB), rDX) /* Xroothi */
-
- LWI(_magic+DIROFF(SB), rBX)
- CALL16(BIOSread(SB)) /* read the root directory */
-
- LWI((512/Dirsz), rBX)
-
- LWI(_magic+DIROFF(SB), rDI) /* compare first directory entry */
-
-_cmp00:
- PUSHR(rDI) /* save for later if it matches */
- LWI(bootfile(SB), rSI)
- LWI(Dnamesz, rCX)
- REP
- CMPSB
- POPR(rDI)
- JEQ _jmp02
-
- DEC(rBX)
- JEQ _jmp01
-
- ADDI(Dirsz, rDI)
- JMP _cmp00
-_jmp01:
- CALL16(buggery(SB))
-
-_jmp02:
- CLR(rBX) /* a handy value */
- LW(_rootsize(SB), rAX) /* calculate and save Xrootsz */
- LWI(Dirsz, rCX)
- MUL(rCX)
- LW(_sectsize(SB), rCX)
- PUSHR(rCX)
- DEC(rCX)
- ADD(rCX, rAX)
- ADC(rBX, rDX)
- POPR(rCX) /* _sectsize(SB) */
- DIV(rCX)
- PUSHR(rAX) /* Xrootsz */
-
- /*
- * rDI points to the matching directory entry.
- */
- LXW(Dstart, xDI, rAX) /* starting sector address */
- DEC(rAX) /* that's just the way it is */
- DEC(rAX)
- LB(_clustsize(SB), rCL)
- CLRB(rCH)
- MUL(rCX)
- LW(_volid(SB), rCX) /* Xrootlo */
- ADD(rCX, rAX)
- LW(_volid+2(SB), rCX) /* Xroothi */
- ADC(rCX, rDX)
- POPR(rCX) /* Xrootsz */
- ADD(rCX, rAX)
- ADC(rBX, rDX)
-
- PUSHR(rAX) /* calculate how many sectors to read */
- PUSHR(rDX)
- LXW(Dlengthlo, xDI, rAX)
- LXW(Dlengthhi, xDI, rDX)
- LW(_sectsize(SB), rCX)
- PUSHR(rCX)
- DEC(rCX)
- ADD(rCX, rAX)
- ADC(rBX, rDX)
- POPR(rCX) /* _sectsize(SB) */
- DIV(rCX)
- MW(rAX, rCX)
- POPR(rDX)
- POPR(rAX)
-
- LWI(LOADSEG, rBX) /* address to load into (seg+offset) */
- MTSR(rBX, rES) /* seg */
- LWI(LOADOFF, rBX) /* offset */
-
-_readboot:
- CALL16(BIOSread(SB)) /* read the sector */
-
- LW(_sectsize(SB), rDI) /* bump addresses/counts */
- ADD(rDI, rBX)
- JCC _incsecno
-
- MFSR(rES, rDI) /* next 64KB segment */
- ADDI(0x1000, rDI)
- MTSR(rDI, rES)
-
-_incsecno:
- CLR(rDI)
- INC(rAX)
- ADC(rDI, rDX)
- LOOP _readboot
-
- LWI(LOADSEG, rDI) /* set rDS for loaded code */
- MTSR(rDI, rDS)
- FARJUMP16(LOADSEG, LOADOFF) /* no deposit, no return */
-
-TEXT buggery(SB), $0
- LWI(error(SB), rSI)
- CALL16(BIOSputs(SB))
-
-_wait:
- CLR(rAX) /* wait for almost any key */
- BIOSCALL(0x16)
-
-_reset:
- CLR(rBX) /* set ES segment for BIOS area */
- MTSR(rBX, rES)
-
- LWI(0x0472, rBX) /* warm-start code address */
- LWI(0x1234, rAX) /* warm-start code */
- POKEW /* MOVW AX, ES:[BX] */
-
- FARJUMP16(0xFFFF, 0x0000) /* reset */
-
-
-/*
- * Read a sector from a disc. On entry:
- * rDX:rAX sector number
- * rES:rBX buffer address
- */
-TEXT BIOSread(SB), $0
- LWI(5, rDI) /* retry count (ATAPI ZIPs suck) */
-_retry:
- PUSHA /* may be trashed by BIOSCALL */
-
- SBPW(rBX, Xdap+4) /* transfer buffer :offset */
- MFSR(rES, rDI) /* transfer buffer seg: */
- SBPW(rDI, Xdap+6)
- SBPW(rAX, Xdap+8) /* LBA (64-bits) */
- SBPW(rDX, Xdap+10)
-
- MW(rBP, rSI) /* disk address packet */
- LBI(0x42, rAH) /* extended read */
- LBPB(Xdrive, rDL) /* form drive */
- BIOSCALL(0x13) /* CF set on failure */
- JCC _BIOSreadret
-
- POPA
- DEC(rDI) /* too many retries? */
- JEQ _ioerror
-
- CALL16(dreset(SB))
- JMP _retry
-
-_ioerror:
- LWI(ioerror(SB), rSI)
- CALL16(BIOSputs(SB))
- JMP _wait
-
-_BIOSreadret:
- POPA
- RET
-
-TEXT dreset(SB), $0
- PUSHA
- CLR(rAX) /* rAH == 0 == reset disc system */
- LBPB(Xdrive, rDL)
- BIOSCALL(0x13)
- ORB(rAH, rAH) /* status (0 == success) */
- POPA
- JNE _ioerror
- RET
-
-/*
- * Output a string to the display.
- * String argument is in rSI.
- */
-TEXT BIOSputs(SB), $0
- PUSHA
- CLR(rBX)
-_BIOSputs:
- LODSB
- ORB(rAL, rAL)
- JEQ _BIOSputsret
-
- LBI(0x0E, rAH)
- BIOSCALL(0x10)
- JMP _BIOSputs
-
-_BIOSputsret:
- POPA
- RET
-
-/* "Bad format or I/O error\r\nPress almost any key to reboot..." */
-TEXT error(SB), $0
- BYTE $'B'; BYTE $'a'; BYTE $'d'; BYTE $' ';
- BYTE $'f'; BYTE $'o'; BYTE $'r'; BYTE $'m';
- BYTE $'a'; BYTE $'t'; BYTE $' '; BYTE $'o';
- BYTE $'r'; BYTE $' ';
-/* "I/O error\r\nPress almost any key to reboot..." */
-TEXT ioerror(SB), $0
- BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
- BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
- BYTE $'r'; BYTE $'\r';BYTE $'\n';
- BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
- BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $' ';
- BYTE $'k'; BYTE $'e'; BYTE $'y';
- BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
- BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
- BYTE $'o'; BYTE $'t';
- BYTE $'.'; BYTE $'.'; BYTE $'.';
- BYTE $'\z';
-
-#ifdef USEBCOM
-/* "B COM" */
-TEXT bootfile(SB), $0
- BYTE $'B'; BYTE $' '; BYTE $' '; BYTE $' ';
- BYTE $' '; BYTE $' '; BYTE $' '; BYTE $' ';
- BYTE $'C'; BYTE $'O'; BYTE $'M';
- BYTE $'\z';
-#else
-/* "9LOAD " */
-TEXT bootfile(SB), $0
- BYTE $'9'; BYTE $'L'; BYTE $'O'; BYTE $'A';
- BYTE $'D'; BYTE $' '; BYTE $' '; BYTE $' ';
- BYTE $' '; BYTE $' '; BYTE $' ';
- BYTE $'\z';
-#endif /* USEBCOM */
-
-/* "PBS..." */
-TEXT confidence(SB), $0
- BYTE $'P'; BYTE $'B'; BYTE $'S'; BYTE $'2';
- BYTE $'.'; BYTE $'.'; BYTE $'.';
- BYTE $'\z';
--- a/os/boot/pc/pci.c
+++ /dev/null
@@ -1,1002 +1,0 @@
-/*
- * PCI support code.
- * To do:
- * initialise bridge mappings if the PCI BIOS didn't.
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "error.h"
-
-enum { /* configuration mechanism #1 */
- PciADDR = 0xCF8, /* CONFIG_ADDRESS */
- PciDATA = 0xCFC, /* CONFIG_DATA */
-
- /* configuration mechanism #2 */
- PciCSE = 0xCF8, /* configuration space enable */
- PciFORWARD = 0xCFA, /* which bus */
-
- MaxFNO = 7,
- MaxUBN = 255,
-};
-
-enum
-{ /* command register */
- IOen = (1<<0),
- MEMen = (1<<1),
- MASen = (1<<2),
- MemWrInv = (1<<4),
- PErrEn = (1<<6),
- SErrEn = (1<<8),
-};
-
-static Lock pcicfglock;
-static Lock pcicfginitlock;
-static int pcicfgmode = -1;
-static int pcimaxbno = 7;
-static int pcimaxdno;
-static Pcidev* pciroot;
-static Pcidev* pcilist;
-static Pcidev* pcitail;
-
-static int pcicfgrw32(int, int, int, int);
-static int pcicfgrw8(int, int, int, int);
-
-ulong
-pcibarsize(Pcidev *p, int rno)
-{
- ulong v, size;
-
- v = pcicfgrw32(p->tbdf, rno, 0, 1);
- pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
- size = pcicfgrw32(p->tbdf, rno, 0, 1);
- if(v & 1)
- size |= 0xFFFF0000;
- pcicfgrw32(p->tbdf, rno, v, 0);
-
- return -(size & ~0x0F);
-}
-
-int
-pciscan(int bno, Pcidev** list)
-{
- Pcidev *p, *head, *tail;
- int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
-
- maxubn = bno;
- head = nil;
- tail = nil;
- for(dno = 0; dno <= pcimaxdno; dno++){
- maxfno = 0;
- for(fno = 0; fno <= maxfno; fno++){
- /*
- * For this possible device, form the
- * bus+device+function triplet needed to address it
- * and try to read the vendor and device ID.
- * If successful, allocate a device struct and
- * start to fill it in with some useful information
- * from the device's configuration space.
- */
- tbdf = MKBUS(BusPCI, bno, dno, fno);
- l = pcicfgrw32(tbdf, PciVID, 0, 1);
- if(l == 0xFFFFFFFF || l == 0)
- continue;
- p = malloc(sizeof(*p));
- p->tbdf = tbdf;
- p->vid = l;
- p->did = l>>16;
-
- if(pcilist != nil)
- pcitail->list = p;
- else
- pcilist = p;
- pcitail = p;
-
- p->rid = pcicfgr8(p, PciRID);
- p->ccrp = pcicfgr8(p, PciCCRp);
- p->ccru = pcicfgr8(p, PciCCRu);
- p->ccrb = pcicfgr8(p, PciCCRb);
- p->pcr = pcicfgr32(p, PciPCR);
-
- p->intl = pcicfgr8(p, PciINTL);
-
- /*
- * If the device is a multi-function device adjust the
- * loop count so all possible functions are checked.
- */
- hdt = pcicfgr8(p, PciHDT);
- if(hdt & 0x80)
- maxfno = MaxFNO;
-
- /*
- * If appropriate, read the base address registers
- * and work out the sizes.
- */
- switch(p->ccrb){
-
- case 0x01: /* mass storage controller */
- case 0x02: /* network controller */
- case 0x03: /* display controller */
- case 0x04: /* multimedia device */
- case 0x07: /* simple comm. controllers */
- case 0x08: /* base system peripherals */
- case 0x09: /* input devices */
- case 0x0A: /* docking stations */
- case 0x0B: /* processors */
- case 0x0C: /* serial bus controllers */
- if((hdt & 0x7F) != 0)
- break;
- rno = PciBAR0 - 4;
- for(i = 0; i < nelem(p->mem); i++){
- rno += 4;
- p->mem[i].bar = pcicfgr32(p, rno);
- p->mem[i].size = pcibarsize(p, rno);
- }
- break;
-
- case 0x00:
- case 0x05: /* memory controller */
- case 0x06: /* bridge device */
- default:
- break;
- }
-
- if(head != nil)
- tail->link = p;
- else
- head = p;
- tail = p;
- }
- }
-
- *list = head;
- for(p = head; p != nil; p = p->link){
- /*
- * Find PCI-PCI and PCI-Cardbus bridges
- * and recursively descend the tree.
- */
- if(p->ccrb != 0x06 || p->ccru != 0x04)
- continue;
-
- /*
- * If the secondary or subordinate bus number is not
- * initialised try to do what the PCI BIOS should have
- * done and fill in the numbers as the tree is descended.
- * On the way down the subordinate bus number is set to
- * the maximum as it's not known how many buses are behind
- * this one; the final value is set on the way back up.
- */
- ubn = pcicfgr8(p, PciUBN);
- sbn = pcicfgr8(p, PciSBN);
-
- if(sbn == 0 || ubn == 0){
- sbn = maxubn+1;
- /*
- * Make sure memory, I/O and master enables are
- * off, set the primary, secondary and subordinate
- * bus numbers and clear the secondary status before
- * attempting to scan the secondary bus.
- *
- * Initialisation of the bridge should be done here.
- */
- pcicfgw32(p, PciPCR, 0xFFFF0000);
- l = (MaxUBN<<16)|(sbn<<8)|bno;
- pcicfgw32(p, PciPBN, l);
- pcicfgw16(p, PciSPSR, 0xFFFF);
- maxubn = pciscan(sbn, &p->bridge);
- l = (maxubn<<16)|(sbn<<8)|bno;
-
- pcicfgw32(p, PciPBN, l);
- }
- else{
- /*
- * You can't go back.
- * This shouldn't be possible, but the
- * Iwill DK8-HTX seems to have subordinate
- * bus numbers which get smaller on the
- * way down. Need to look more closely at
- * this.
- */
- if(ubn > maxubn)
- maxubn = ubn;
- pciscan(sbn, &p->bridge);
- }
- }
-
- return maxubn;
-}
-
-static uchar
-null_link(Pcidev *, uchar )
-{
- return 0;
-}
-
-static void
-null_init(Pcidev *, uchar , uchar )
-{
-}
-
-static uchar
-pIIx_link(Pcidev *router, uchar link)
-{
- uchar pirq;
-
- /* link should be 0x60, 0x61, 0x62, 0x63 */
- pirq = pcicfgr8(router, link);
- return (pirq < 16)? pirq: 0;
-}
-
-static void
-pIIx_init(Pcidev *router, uchar link, uchar irq)
-{
- pcicfgw8(router, link, irq);
-}
-
-static uchar
-via_link(Pcidev *router, uchar link)
-{
- uchar pirq;
-
- /* link should be 1, 2, 3, 5 */
- pirq = (link < 6)? pcicfgr8(router, 0x55 + (link>>1)): 0;
-
- return (link & 1)? (pirq >> 4): (pirq & 15);
-}
-
-static void
-via_init(Pcidev *router, uchar link, uchar irq)
-{
- uchar pirq;
-
- pirq = pcicfgr8(router, 0x55 + (link >> 1));
- pirq &= (link & 1)? 0x0f: 0xf0;
- pirq |= (link & 1)? (irq << 4): (irq & 15);
- pcicfgw8(router, 0x55 + (link>>1), pirq);
-}
-
-static uchar
-opti_link(Pcidev *router, uchar link)
-{
- uchar pirq = 0;
-
- /* link should be 0x02, 0x12, 0x22, 0x32 */
- if ((link & 0xcf) == 0x02)
- pirq = pcicfgr8(router, 0xb8 + (link >> 5));
- return (link & 0x10)? (pirq >> 4): (pirq & 15);
-}
-
-static void
-opti_init(Pcidev *router, uchar link, uchar irq)
-{
- uchar pirq;
-
- pirq = pcicfgr8(router, 0xb8 + (link >> 5));
- pirq &= (link & 0x10)? 0x0f : 0xf0;
- pirq |= (link & 0x10)? (irq << 4): (irq & 15);
- pcicfgw8(router, 0xb8 + (link >> 5), pirq);
-}
-
-static uchar
-ali_link(Pcidev *router, uchar link)
-{
- /* No, you're not dreaming */
- static const uchar map[] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
- uchar pirq;
-
- /* link should be 0x01..0x08 */
- pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
- return (link & 1)? map[pirq&15]: map[pirq>>4];
-}
-
-static void
-ali_init(Pcidev *router, uchar link, uchar irq)
-{
- /* Inverse of map in ali_link */
- static const uchar map[] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
- uchar pirq;
-
- pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
- pirq &= (link & 1)? 0x0f: 0xf0;
- pirq |= (link & 1)? (map[irq] << 4): (map[irq] & 15);
- pcicfgw8(router, 0x48 + ((link-1)>>1), pirq);
-}
-
-static uchar
-cyrix_link(Pcidev *router, uchar link)
-{
- uchar pirq;
-
- /* link should be 1, 2, 3, 4 */
- pirq = pcicfgr8(router, 0x5c + ((link-1)>>1));
- return ((link & 1)? pirq >> 4: pirq & 15);
-}
-
-static void
-cyrix_init(Pcidev *router, uchar link, uchar irq)
-{
- uchar pirq;
-
- pirq = pcicfgr8(router, 0x5c + (link>>1));
- pirq &= (link & 1)? 0x0f: 0xf0;
- pirq |= (link & 1)? (irq << 4): (irq & 15);
- pcicfgw8(router, 0x5c + (link>>1), pirq);
-}
-
-typedef struct {
- ushort sb_vid, sb_did;
- uchar (*sb_translate)(Pcidev *, uchar);
- void (*sb_initialize)(Pcidev *, uchar, uchar);
-} bridge_t;
-
-static bridge_t southbridges[] = {
- { 0x8086, 0x122e, pIIx_link, pIIx_init }, // Intel 82371FB
- { 0x8086, 0x1234, pIIx_link, pIIx_init }, // Intel 82371MX
- { 0x8086, 0x7000, pIIx_link, pIIx_init }, // Intel 82371SB
- { 0x8086, 0x7110, pIIx_link, pIIx_init }, // Intel 82371AB
- { 0x8086, 0x7198, pIIx_link, pIIx_init }, // Intel 82443MX (fn 1)
- { 0x8086, 0x2410, pIIx_link, pIIx_init }, // Intel 82801AA
- { 0x8086, 0x2420, pIIx_link, pIIx_init }, // Intel 82801AB
- { 0x8086, 0x2440, pIIx_link, pIIx_init }, // Intel 82801BA
- { 0x8086, 0x244c, pIIx_link, pIIx_init }, // Intel 82801BAM
- { 0x8086, 0x2480, pIIx_link, pIIx_init }, // Intel 82801CA
- { 0x8086, 0x248c, pIIx_link, pIIx_init }, // Intel 82801CAM
- { 0x8086, 0x24c0, pIIx_link, pIIx_init }, // Intel 82801DBL
- { 0x8086, 0x24cc, pIIx_link, pIIx_init }, // Intel 82801DBM
- { 0x8086, 0x24d0, pIIx_link, pIIx_init }, // Intel 82801EB
- { 0x8086, 0x2640, pIIx_link, pIIx_init }, // Intel 82801FB
- { 0x8086, 0x27b8, pIIx_link, pIIx_init }, // Intel 82801GB
- { 0x8086, 0x27b9, pIIx_link, pIIx_init }, // Intel 82801GBM
- { 0x1106, 0x0586, via_link, via_init }, // Viatech 82C586
- { 0x1106, 0x0596, via_link, via_init }, // Viatech 82C596
- { 0x1106, 0x0686, via_link, via_init }, // Viatech 82C686
- { 0x1106, 0x3227, via_link, via_init }, // Viatech VT8237
- { 0x1045, 0xc700, opti_link, opti_init }, // Opti 82C700
- { 0x10b9, 0x1533, ali_link, ali_init }, // Al M1533
- { 0x1039, 0x0008, pIIx_link, pIIx_init }, // SI 503
- { 0x1039, 0x0496, pIIx_link, pIIx_init }, // SI 496
- { 0x1078, 0x0100, cyrix_link, cyrix_init }, // Cyrix 5530 Legacy
-
- { 0x1002, 0x4377, nil, nil }, // ATI Radeon Xpress 200M
- { 0x1002, 0x4372, nil, nil }, // ATI SB400
- { 0x1022, 0x746B, nil, nil }, // AMD 8111
- { 0x10DE, 0x00D1, nil, nil }, // NVIDIA nForce 3
- { 0x10DE, 0x00E0, nil, nil }, // NVIDIA nForce 3 250 Series
- { 0x1166, 0x0200, nil, nil }, // ServerWorks ServerSet III LE
-};
-
-typedef struct {
- uchar e_bus; // Pci bus number
- uchar e_dev; // Pci device number
- uchar e_maps[12]; // Avoid structs! Link and mask.
- uchar e_slot; // Add-in/built-in slot
- uchar e_reserved;
-} slot_t;
-
-typedef struct {
- uchar rt_signature[4]; // Routing table signature
- uchar rt_version[2]; // Version number
- uchar rt_size[2]; // Total table size
- uchar rt_bus; // Interrupt router bus number
- uchar rt_devfn; // Router's devfunc
- uchar rt_pciirqs[2]; // Exclusive PCI irqs
- uchar rt_compat[4]; // Compatible PCI interrupt router
- uchar rt_miniport[4]; // Miniport data
- uchar rt_reserved[11];
- uchar rt_checksum;
-} router_t;
-
-static ushort pciirqs; // Exclusive PCI irqs
-static bridge_t *southbridge; // Which southbridge to use.
-
-static void
-pcirouting(void)
-{
- uchar *p, pin, irq;
- ulong tbdf, vdid;
- ushort vid, did;
- router_t *r;
- slot_t *e;
- int size, i, fn;
- Pcidev *sbpci, *pci;
-
- // Peek in the BIOS
- for (p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16)
- if (p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R')
- break;
-
- if (p >= (uchar *)KADDR(0xfffff))
- return;
-
- r = (router_t *)p;
-
- // print("PCI interrupt routing table version %d.%d at %.6uX\n",
- // r->rt_version[0], r->rt_version[1], (ulong)r & 0xfffff);
-
- tbdf = (BusPCI << 24)|(r->rt_bus << 16)|(r->rt_devfn << 8);
- vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
- vid = vdid;
- did = vdid >> 16;
-
- for (i = 0; i != nelem(southbridges); i++)
- if (vid == southbridges[i].sb_vid && did == southbridges[i].sb_did)
- break;
-
- if (i == nelem(southbridges)) {
- print("pcirouting: South bridge %.4uX, %.4uX not found\n", vid, did);
- return;
- }
- southbridge = &southbridges[i];
-
- if ((sbpci = pcimatch(nil, vid, did)) == nil) {
- print("pcirouting: Cannot match south bridge %.4uX, %.4uX\n",
- vid, did);
- return;
- }
-
- pciirqs = (r->rt_pciirqs[1] << 8)|r->rt_pciirqs[0];
-
- size = (r->rt_size[1] << 8)|r->rt_size[0];
- for (e = (slot_t *)&r[1]; (uchar *)e < p + size; e++) {
- // print("%.2uX/%.2uX %.2uX: ", e->e_bus, e->e_dev, e->e_slot);
- // for (i = 0; i != 4; i++) {
- // uchar *m = &e->e_maps[i * 3];
- // print("[%d] %.2uX %.4uX ",
- // i, m[0], (m[2] << 8)|m[1]);
- // }
- // print("\n");
-
- for (fn = 0; fn != 8; fn++) {
- uchar *m;
-
- // Retrieve the did and vid through the devfn before
- // obtaining the Pcidev structure.
- tbdf = (BusPCI << 24)|(e->e_bus << 16)|((e->e_dev | fn) << 8);
- vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
- if (vdid == 0xFFFFFFFF || vdid == 0)
- continue;
-
- vid = vdid;
- did = vdid >> 16;
-
- pci = nil;
- while ((pci = pcimatch(pci, vid, did)) != nil) {
-
- if (pci->intl != 0 && pci->intl != 0xFF)
- continue;
-
- pin = pcicfgr8(pci, PciINTP);
- if (pin == 0 || pin == 0xff)
- continue;
-
- m = &e->e_maps[(pin - 1) * 3];
- irq = southbridge->sb_translate(sbpci, m[0]);
- if (irq) {
- print("pcirouting: %.4uX/%.4uX at pin %d irq %d\n",
- vid, did, pin, irq);
- pcicfgw8(pci, PciINTL, irq);
- pci->intl = irq;
- }
- }
- }
- }
-}
-
-static void
-pcicfginit(void)
-{
- char *p;
- int bno, n;
- Pcidev **list;
-
- lock(&pcicfginitlock);
- if(pcicfgmode != -1)
- goto out;
-
- /*
- * Try to determine which PCI configuration mode is implemented.
- * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
- * a DWORD at 0xCF8 and another at 0xCFC and will pass through
- * any non-DWORD accesses as normal I/O cycles. There shouldn't be
- * a device behind these addresses so if Mode1 accesses fail try
- * for Mode2 (Mode2 is deprecated).
- */
-
- /*
- * Bits [30:24] of PciADDR must be 0,
- * according to the spec.
- */
- n = inl(PciADDR);
- if(!(n & 0x7FF00000)){
- outl(PciADDR, 0x80000000);
- outb(PciADDR+3, 0);
- if(inl(PciADDR) & 0x80000000){
- pcicfgmode = 1;
- pcimaxdno = 31;
- }
- }
- outl(PciADDR, n);
-
- if(pcicfgmode < 0){
- /*
- * The 'key' part of PciCSE should be 0.
- */
- n = inb(PciCSE);
- if(!(n & 0xF0)){
- outb(PciCSE, 0x0E);
- if(inb(PciCSE) == 0x0E){
- pcicfgmode = 2;
- pcimaxdno = 15;
- }
- }
- outb(PciCSE, n);
- }
-
- if(pcicfgmode < 0)
- goto out;
-
-
- if(p = getconf("*pcimaxbno"))
- pcimaxbno = strtoul(p, 0, 0);
- if(p = getconf("*pcimaxdno"))
- pcimaxdno = strtoul(p, 0, 0);
-
- list = &pciroot;
- for(bno = 0; bno <= pcimaxbno; bno++) {
- bno = pciscan(bno, list);
- while(*list)
- list = &(*list)->link;
- }
-
- pcirouting();
-
-out:
- unlock(&pcicfginitlock);
-
- if(getconf("*pcihinv"))
- pcihinv(nil);
-}
-
-
-static int
-pcicfgrw8(int tbdf, int rno, int data, int read)
-{
- int o, type, x;
-
- if(pcicfgmode == -1)
- pcicfginit();
-
- if(BUSBNO(tbdf))
- type = 0x01;
- else
- type = 0x00;
- x = -1;
- if(BUSDNO(tbdf) > pcimaxdno)
- return x;
-
- lock(&pcicfglock);
- switch(pcicfgmode){
-
- case 1:
- o = rno & 0x03;
- rno &= ~0x03;
- outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
- if(read)
- x = inb(PciDATA+o);
- else
- outb(PciDATA+o, data);
- outl(PciADDR, 0);
- break;
-
- case 2:
- outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
- outb(PciFORWARD, BUSBNO(tbdf));
- if(read)
- x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
- else
- outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
- outb(PciCSE, 0);
- break;
- }
- unlock(&pcicfglock);
-
- return x;
-}
-
-int
-pcicfgr8(Pcidev* pcidev, int rno)
-{
- return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
-}
-
-void
-pcicfgw8(Pcidev* pcidev, int rno, int data)
-{
- pcicfgrw8(pcidev->tbdf, rno, data, 0);
-}
-
-static int
-pcicfgrw16(int tbdf, int rno, int data, int read)
-{
- int o, type, x;
-
- if(pcicfgmode == -1)
- pcicfginit();
-
- if(BUSBNO(tbdf))
- type = 0x01;
- else
- type = 0x00;
- x = -1;
- if(BUSDNO(tbdf) > pcimaxdno)
- return x;
-
- lock(&pcicfglock);
- switch(pcicfgmode){
-
- case 1:
- o = rno & 0x02;
- rno &= ~0x03;
- outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
- if(read)
- x = ins(PciDATA+o);
- else
- outs(PciDATA+o, data);
- outl(PciADDR, 0);
- break;
-
- case 2:
- outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
- outb(PciFORWARD, BUSBNO(tbdf));
- if(read)
- x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
- else
- outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
- outb(PciCSE, 0);
- break;
- }
- unlock(&pcicfglock);
-
- return x;
-}
-
-int
-pcicfgr16(Pcidev* pcidev, int rno)
-{
- return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
-}
-
-void
-pcicfgw16(Pcidev* pcidev, int rno, int data)
-{
- pcicfgrw16(pcidev->tbdf, rno, data, 0);
-}
-
-static int
-pcicfgrw32(int tbdf, int rno, int data, int read)
-{
- int type, x;
-
- if(pcicfgmode == -1)
- pcicfginit();
-
- if(BUSBNO(tbdf))
- type = 0x01;
- else
- type = 0x00;
- x = -1;
- if(BUSDNO(tbdf) > pcimaxdno)
- return x;
-
- lock(&pcicfglock);
- switch(pcicfgmode){
-
- case 1:
- rno &= ~0x03;
- outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
- if(read)
- x = inl(PciDATA);
- else
- outl(PciDATA, data);
- outl(PciADDR, 0);
- break;
-
- case 2:
- outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
- outb(PciFORWARD, BUSBNO(tbdf));
- if(read)
- x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
- else
- outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
- outb(PciCSE, 0);
- break;
- }
- unlock(&pcicfglock);
-
- return x;
-}
-
-int
-pcicfgr32(Pcidev* pcidev, int rno)
-{
- return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
-}
-
-void
-pcicfgw32(Pcidev* pcidev, int rno, int data)
-{
- pcicfgrw32(pcidev->tbdf, rno, data, 0);
-}
-
-Pcidev*
-pcimatch(Pcidev* prev, int vid, int did)
-{
- if(pcicfgmode == -1)
- pcicfginit();
-
- if(prev == nil)
- prev = pcilist;
- else
- prev = prev->list;
-
- while(prev != nil) {
- if((vid == 0 || prev->vid == vid)
- && (did == 0 || prev->did == did))
- break;
- prev = prev->list;
- }
- return prev;
-}
-
-uchar
-pciipin(Pcidev *pci, uchar pin)
-{
- if (pci == nil)
- pci = pcilist;
-
- while (pci) {
- uchar intl;
-
- if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
- return pci->intl;
-
- if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
- return intl;
-
- pci = pci->list;
- }
- return 0;
-}
-
-static ushort
-pciimask(Pcidev *pci)
-{
- ushort imask;
-
- imask = 0;
- while (pci) {
- if (pcicfgr8(pci, PciINTP) && pci->intl < 16)
- imask |= 1 << pci->intl;
-
- if (pci->bridge)
- imask |= pciimask(pci->bridge);
-
- pci = pci->list;
- }
- return imask;
-}
-
-uchar
-pciintl(Pcidev *pci)
-{
- ushort imask;
- int i;
-
- if (pci == nil)
- pci = pcilist;
-
- imask = pciimask(pci) | 1;
- for (i = 0; i != 16; i++)
- if ((imask & (1 << i)) == 0)
- return i;
- return 0;
-}
-
-void
-pcihinv(Pcidev* p)
-{
- int i;
- Pcidev *t;
-
- if(pcicfgmode == -1)
- pcicfginit();
-
- if(p == nil) {
- p = pciroot;
- print("bus dev type vid did intl memory\n");
- }
- for(t = p; t != nil; t = t->link) {
- print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ",
- BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
- t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
-
- for(i = 0; i < nelem(p->mem); i++) {
- if(t->mem[i].size == 0)
- continue;
- print("%d:%.8lux %d ", i,
- t->mem[i].bar, t->mem[i].size);
- }
- print("\n");
- }
- while(p != nil) {
- if(p->bridge != nil)
- pcihinv(p->bridge);
- p = p->link;
- }
-}
-
-void
-pcireset(void)
-{
- Pcidev *p;
- int pcr;
-
- if(pcicfgmode == -1)
- pcicfginit();
-
- for(p = pcilist; p != nil; p = p->list){
- pcr = pcicfgr16(p, PciPSR);
- pcicfgw16(p, PciPSR, pcr & ~0x04);
- }
-}
-
-void
-pcisetioe(Pcidev* p)
-{
- p->pcr |= IOen;
- pcicfgw16(p, PciPCR, p->pcr);
-}
-
-void
-pciclrioe(Pcidev* p)
-{
- p->pcr &= ~IOen;
- pcicfgw16(p, PciPCR, p->pcr);
-}
-
-void
-pcisetbme(Pcidev* p)
-{
- p->pcr |= MASen;
- pcicfgw16(p, PciPCR, p->pcr);
-}
-
-void
-pciclrbme(Pcidev* p)
-{
- p->pcr &= ~MASen;
- pcicfgw16(p, PciPCR, p->pcr);
-}
-
-void
-pcisetmwi(Pcidev* p)
-{
- p->pcr |= MemWrInv;
- pcicfgw16(p, PciPCR, p->pcr);
-}
-
-void
-pciclrmwi(Pcidev* p)
-{
- p->pcr &= ~MemWrInv;
- pcicfgw16(p, PciPCR, p->pcr);
-}
-
-static int
-pcigetpmrb(Pcidev* p)
-{
- int ptr;
-
- if(p->pmrb != 0)
- return p->pmrb;
- p->pmrb = -1;
-
- /*
- * If there are no extended capabilities implemented,
- * (bit 4 in the status register) assume there's no standard
- * power management method.
- * Find the capabilities pointer based on PCI header type.
- */
- if(!(pcicfgr16(p, PciPSR) & 0x0010))
- return -1;
- switch(pcicfgr8(p, PciHDT)){
- default:
- return -1;
- case 0: /* all other */
- case 1: /* PCI to PCI bridge */
- ptr = 0x34;
- break;
- case 2: /* CardBus bridge */
- ptr = 0x14;
- break;
- }
- ptr = pcicfgr32(p, ptr);
-
- while(ptr != 0){
- /*
- * Check for validity.
- * Can't be in standard header and must be double
- * word aligned.
- */
- if(ptr < 0x40 || (ptr & ~0xFC))
- return -1;
- if(pcicfgr8(p, ptr) == 0x01){
- p->pmrb = ptr;
- return ptr;
- }
-
- ptr = pcicfgr8(p, ptr+1);
- }
-
- return -1;
-}
-
-int
-pcigetpms(Pcidev* p)
-{
- int pmcsr, ptr;
-
- if((ptr = pcigetpmrb(p)) == -1)
- return -1;
-
- /*
- * Power Management Register Block:
- * offset 0: Capability ID
- * 1: next item pointer
- * 2: capabilities
- * 4: control/status
- * 6: bridge support extensions
- * 7: data
- */
- pmcsr = pcicfgr16(p, ptr+4);
-
- return pmcsr & 0x0003;
-}
-
-int
-pcisetpms(Pcidev* p, int state)
-{
- int ostate, pmc, pmcsr, ptr;
-
- if((ptr = pcigetpmrb(p)) == -1)
- return -1;
-
- pmc = pcicfgr16(p, ptr+2);
- pmcsr = pcicfgr16(p, ptr+4);
- ostate = pmcsr & 0x0003;
- pmcsr &= ~0x0003;
-
- switch(state){
- default:
- return -1;
- case 0:
- break;
- case 1:
- if(!(pmc & 0x0200))
- return -1;
- break;
- case 2:
- if(!(pmc & 0x0400))
- return -1;
- break;
- case 3:
- break;
- }
- pmcsr |= state;
- pcicfgw16(p, ptr+4, pmcsr);
-
- return ostate;
-}
--- a/os/boot/pc/print.c
+++ /dev/null
@@ -1,31 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-static Lock fmtl;
-
-void
-_fmtlock(void)
-{
- lock(&fmtl);
-}
-
-void
-_fmtunlock(void)
-{
- unlock(&fmtl);
-}
-
-int
-_efgfmt(Fmt*)
-{
- return -1;
-}
-
-int
-errfmt(Fmt*)
-{
- return -1;
-}
--- a/os/boot/pc/queue.c
+++ /dev/null
@@ -1,44 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-int
-qgetc(IOQ *q)
-{
- int c;
-
- if(q->in == q->out)
- return -1;
- c = *q->out;
- if(q->out == q->buf+sizeof(q->buf)-1)
- q->out = q->buf;
- else
- q->out++;
- return c;
-}
-
-static int
-qputc(IOQ *q, int c)
-{
- uchar *nextin;
- if(q->in >= &q->buf[sizeof(q->buf)-1])
- nextin = q->buf;
- else
- nextin = q->in+1;
- if(nextin == q->out)
- return -1;
- *q->in = c;
- q->in = nextin;
- return 0;
-}
-
-void
-qinit(IOQ *q)
-{
- q->in = q->out = q->buf;
- q->getc = qgetc;
- q->putc = qputc;
-}
--- a/os/boot/pc/sd.h
+++ /dev/null
@@ -1,126 +1,0 @@
-/*
- * Storage Device.
- */
-typedef struct SDev SDev;
-typedef struct SDifc SDifc;
-typedef struct SDpart SDpart;
-typedef struct SDreq SDreq;
-typedef struct SDunit SDunit;
-
-typedef struct SDpart {
- uvlong start;
- uvlong end;
- char name[NAMELEN];
- char user[NAMELEN];
- ulong perm;
- int valid;
- void *crud;
-} SDpart;
-
-typedef struct SDunit {
- SDev* dev;
- int subno;
- uchar inquiry[256]; /* format follows SCSI spec */
- char name[NAMELEN];
-// Rendez rendez;
-
-// QLock ctl;
- uvlong sectors;
- ulong secsize;
- SDpart* part;
- int npart; /* of valid partitions */
- int changed;
-
-// QLock raw;
- int state;
- ulong pid;
- SDreq* req;
-} SDunit;
-
-typedef struct SDev {
- SDifc* ifc; /* pnp/legacy */
- void *ctlr;
- int idno;
- int index; /* into unit space */
- int nunit;
- SDev* next;
-
-// QLock; /* enable/disable */
- int enabled;
-} SDev;
-
-typedef struct SDifc {
- char* name;
-
- SDev* (*pnp)(void);
- SDev* (*legacy)(int, int);
- SDev* (*id)(SDev*);
- int (*enable)(SDev*);
- int (*disable)(SDev*);
-
- int (*verify)(SDunit*);
- int (*online)(SDunit*);
- int (*rio)(SDreq*);
- int (*rctl)(SDunit*, char*, int);
- int (*wctl)(SDunit*, void*);
-
- long (*bio)(SDunit*, int, int, void*, long, long);
-} SDifc;
-
-typedef struct SDreq {
- SDunit* unit;
- int lun;
- int write;
- uchar cmd[16];
- int clen;
- void* data;
- int dlen;
-
- int flags;
-
- int status;
- long rlen;
- uchar sense[256];
-} SDreq;
-
-enum {
- SDnosense = 0x00000001,
- SDvalidsense = 0x00010000,
-};
-
-enum {
- SDmalloc = -4,
- SDeio = -3,
- SDtimeout = -2,
- SDnostatus = -1,
-
- SDok = 0,
-
- SDcheck = 0x02, /* check condition */
- SDbusy = 0x08, /* busy */
-
- SDmaxio = 2048*1024,
- SDnpart = 16,
-};
-
-/* sdscsi.c */
-extern int scsiverify(SDunit*);
-extern int scsionline(SDunit*);
-extern long scsibio(SDunit*, int, int, void*, long, long);
-extern SDev* scsiid(SDev*, SDifc*);
-
-#define IrqATA0 14
-#define IrqATA1 15
-#define qlock(i) while(0)
-#define qunlock(i) while(0)
-
-#define putstrn consputs
-
-void sleep(void*, int(*)(void*), void*);
-void tsleep(void*, int(*)(void*), void*, int);
-#define wakeup(x) while(0)
-extern long sdbio(SDunit *unit, SDpart *pp, void *a, long len, vlong off);
-void partition(SDunit*);
-SDpart* sdfindpart(SDunit*, char*);
-void sdaddpart(SDunit*, char*, uvlong, uvlong);
-void* sdmalloc(void*, ulong);
--- a/os/boot/pc/sd53c8xx.c
+++ /dev/null
@@ -1,2124 +1,0 @@
-/*
- * NCR 53c8xx driver for Plan 9
- * Nigel Roles (ngr@cotswold.demon.co.uk)
- *
- * 08/07/99 Ultra2 fixed. Brazil #ifdefs added. Fixed script error 6 diagnostics.
- *
- * 09/06/99 Enhancements to support 895 and 896 correctly. Attempt at Ultra 2 negotiation,
- * though no device to test with yet.
- * Variant now contains the number of valid chip registers to assist
- * dumpncrregs()
- *
- * 06/10/98 Various bug fixes and Brazil compiler inspired changes from jmk
- *
- * 05/10/98 Small fix to handle command length being greater than expected by device
- *
- * 04/08/98 Added missing locks to interrupt handler. Marked places where
- * multiple controller extensions could go
- *
- * 18/05/97 Fixed overestimate in size of local SCRIPT RAM
- *
- * 17/05/97 Bug fix to return status
- *
- * 06/10/96 Enhanced list of chip IDs. 875 revision 1 has no clock doubler, so assume it
- * is shipped with 80MHz crystal. Use bit 3 of the GPREG to recognise differential
- * boards. This is Symbios specific, but since they are about the only suppliers of
- * differential cards.
- *
- * 23/9/96 Wide and Ultra supported. 825A and 860 added to variants. Dual compiling
- * version for fileserver and cpu. 80MHz default clock for 860
- *
- * 5/8/96 Waits for an Inquiry message before initiating synchronous negotiation
- * in case capabilities byte [7] indicates device does not support it. Devices
- * which do target initiated negotiation will typically get in first; a few
- * bugs in handling this have been fixed
- *
- * 3/8/96 Added differential support (put scsi0=diff in plan9.ini)
- * Split exec() into exec() and io(). Exec() is small, and Io() does not
- * use any Plan 9 specific data structures, so alternate exec() functions
- * may be done for other environments, such as the fileserver
- *
- * GENERAL
- *
- * Works on 810 and 875
- * Should work on 815, 825, 810A, 825A, 860A
- * Uses local RAM, large FIFO, prefetch, burst opcode fetch, and 16 byte synch. offset
- * where applicable
- * Supports multi-target, wide, Ultra
- * Differential mode can be enabled by putting scsi0=diff in plan9.ini
- * NO SUPPORT FOR tagged queuing (yet)
- *
- * Known problems
- */
-
-#define MAXTARGET 16 /* can be 8 or 16 */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "error.h"
-
-#include "sd.h"
-extern SDifc sd53c8xxifc;
-
-#define waserror() (0)
-#define poperror()
-typedef struct QLock{ int r; } QLock;
-typedef struct Rendez{ int r; } Rendez;
-#define intrenable(irq, f, c, tbdf, name) setvec(VectorPIC+(irq), f, c);
-
-/**********************************/
-/* Portable configuration macros */
-/**********************************/
-
-//#define BOOTDEBUG
-//#define ASYNC_ONLY
-//#define INTERNAL_SCLK
-//#define ALWAYS_DO_WDTR
-#define WMR_DEBUG
-
-/**********************************/
-/* CPU specific macros */
-/**********************************/
-
-#ifdef BOOTDEBUG
-
-#define KPRINT oprint
-#define IPRINT intrprint
-#define DEBUG(n) 0
-#define IFLUSH() iflush()
-
-#else
-
-#define KPRINT if(0)print
-#define IPRINT if(0)print
-#define DEBUG(n) (0)
-#define IFLUSH()
-
-#endif /* BOOTDEBUG */
-
-/*******************************/
-/* General */
-/*******************************/
-
-#ifndef DMASEG
-#define DMASEG(x) PADDR(x)
-#define legetl(x) (*(ulong*)(x))
-#define lesetl(x,v) (*(ulong*)(x) = (v))
-#define swabl(a,b,c)
-#else
-#endif /*DMASEG */
-#define DMASEG_TO_KADDR(x) KADDR(PADDR(x))
-#define KPTR(x) ((x) == 0 ? 0 : DMASEG_TO_KADDR(x))
-
-#define MEGA 1000000L
-#ifdef INTERNAL_SCLK
-#define SCLK (33 * MEGA)
-#else
-#define SCLK (40 * MEGA)
-#endif /* INTERNAL_SCLK */
-#define ULTRA_NOCLOCKDOUBLE_SCLK (80 * MEGA)
-
-#define MAXSYNCSCSIRATE (5 * MEGA)
-#define MAXFASTSYNCSCSIRATE (10 * MEGA)
-#define MAXULTRASYNCSCSIRATE (20 * MEGA)
-#define MAXULTRA2SYNCSCSIRATE (40 * MEGA)
-#define MAXASYNCCORERATE (25 * MEGA)
-#define MAXSYNCCORERATE (25 * MEGA)
-#define MAXFASTSYNCCORERATE (50 * MEGA)
-#define MAXULTRASYNCCORERATE (80 * MEGA)
-#define MAXULTRA2SYNCCORERATE (160 * MEGA)
-
-
-#define X_MSG 1
-#define X_MSG_SDTR 1
-#define X_MSG_WDTR 3
-
-struct na_patch {
- unsigned lwoff;
- unsigned char type;
-};
-
-typedef struct Ncr {
- uchar scntl0; /* 00 */
- uchar scntl1;
- uchar scntl2;
- uchar scntl3;
-
- uchar scid; /* 04 */
- uchar sxfer;
- uchar sdid;
- uchar gpreg;
-
- uchar sfbr; /* 08 */
- uchar socl;
- uchar ssid;
- uchar sbcl;
-
- uchar dstat; /* 0c */
- uchar sstat0;
- uchar sstat1;
- uchar sstat2;
-
- uchar dsa[4]; /* 10 */
-
- uchar istat; /* 14 */
- uchar istatpad[3];
-
- uchar ctest0; /* 18 */
- uchar ctest1;
- uchar ctest2;
- uchar ctest3;
-
- uchar temp[4]; /* 1c */
-
- uchar dfifo; /* 20 */
- uchar ctest4;
- uchar ctest5;
- uchar ctest6;
-
- uchar dbc[3]; /* 24 */
- uchar dcmd; /* 27 */
-
- uchar dnad[4]; /* 28 */
- uchar dsp[4]; /* 2c */
- uchar dsps[4]; /* 30 */
-
- uchar scratcha[4]; /* 34 */
-
- uchar dmode; /* 38 */
- uchar dien;
- uchar dwt;
- uchar dcntl;
-
- uchar adder[4]; /* 3c */
-
- uchar sien0; /* 40 */
- uchar sien1;
- uchar sist0;
- uchar sist1;
-
- uchar slpar; /* 44 */
- uchar slparpad0;
- uchar macntl;
- uchar gpcntl;
-
- uchar stime0; /* 48 */
- uchar stime1;
- uchar respid;
- uchar respidpad0;
-
- uchar stest0; /* 4c */
- uchar stest1;
- uchar stest2;
- uchar stest3;
-
- uchar sidl; /* 50 */
- uchar sidlpad[3];
-
- uchar sodl; /* 54 */
- uchar sodlpad[3];
-
- uchar sbdl; /* 58 */
- uchar sbdlpad[3];
-
- uchar scratchb[4]; /* 5c */
-} Ncr;
-
-typedef struct Movedata {
- uchar dbc[4];
- uchar pa[4];
-} Movedata;
-
-typedef enum NegoState {
- NeitherDone, WideInit, WideResponse, WideDone,
- SyncInit, SyncResponse, BothDone
-} NegoState;
-
-typedef enum State {
- Allocated, Queued, Active, Done
-} State;
-
-typedef struct Dsa {
- union {
- uchar state[4];
- struct {
- uchar stateb;
- uchar result;
- uchar dmablks;
- uchar flag; /* setbyte(state,3,...) */
- };
- };
-
- union {
- ulong dmancr; /* For block transfer: NCR order (little-endian) */
- uchar dmaaddr[4];
- };
-
- uchar target; /* Target */
- uchar pad0[3];
-
- uchar lun; /* Logical Unit Number */
- uchar pad1[3];
-
- uchar scntl3;
- uchar sxfer;
- uchar pad2[2];
-
- uchar next[4]; /* chaining for SCRIPT (NCR byte order) */
- struct Dsa *freechain; /* chaining for freelist */
- Rendez;
- uchar scsi_id_buf[4];
- Movedata msg_out_buf;
- Movedata cmd_buf;
- Movedata data_buf;
- Movedata status_buf;
- uchar msg_out[10]; /* enough to include SDTR */
- uchar status;
- int p9status;
- uchar parityerror;
-} Dsa;
-
-typedef enum Feature {
- BigFifo = 1, /* 536 byte fifo */
- BurstOpCodeFetch = 2, /* burst fetch opcodes */
- Prefetch = 4, /* prefetch 8 longwords */
- LocalRAM = 8, /* 4K longwords of local RAM */
- Differential = 16, /* Differential support */
- Wide = 32, /* Wide capable */
- Ultra = 64, /* Ultra capable */
- ClockDouble = 128, /* Has clock doubler */
- ClockQuad = 256, /* Has clock quadrupler (same as Ultra2) */
- Ultra2 = 256,
-} Feature;
-
-typedef enum Burst {
- Burst2 = 0,
- Burst4 = 1,
- Burst8 = 2,
- Burst16 = 3,
- Burst32 = 4,
- Burst64 = 5,
- Burst128 = 6
-} Burst;
-
-typedef struct Variant {
- ushort did;
- uchar maxrid; /* maximum allowed revision ID */
- char *name;
- Burst burst; /* codings for max burst */
- uchar maxsyncoff; /* max synchronous offset */
- uchar registers; /* number of 32 bit registers */
- unsigned feature;
-} Variant;
-
-static unsigned char cf2[] = { 6, 2, 3, 4, 6, 8, 12, 16 };
-#define NULTRA2SCF (sizeof(cf2)/sizeof(cf2[0]))
-#define NULTRASCF (NULTRA2SCF - 2)
-#define NSCF (NULTRASCF - 1)
-
-typedef struct Controller {
- Lock;
- struct {
- uchar scntl3;
- uchar stest2;
- } bios;
- uchar synctab[NULTRA2SCF - 1][8];/* table of legal tpfs */
- NegoState s[MAXTARGET];
- uchar scntl3[MAXTARGET];
- uchar sxfer[MAXTARGET];
- uchar cap[MAXTARGET]; /* capabilities byte from Identify */
- ushort capvalid; /* bit per target for validity of cap[] */
- ushort wide; /* bit per target set if wide negotiated */
- ulong sclk; /* clock speed of controller */
- uchar clockmult; /* set by synctabinit */
- uchar ccf; /* CCF bits */
- uchar tpf; /* best tpf value for this controller */
- uchar feature; /* requested features */
- int running; /* is the script processor running? */
- int ssm; /* single step mode */
- Ncr *n; /* pointer to registers */
- Variant *v; /* pointer to variant type */
- ulong *script; /* where the real script is */
- ulong scriptpa; /* where the real script is */
- Pcidev* pcidev;
- SDev* sdev;
-
- struct {
- Lock;
- uchar head[4]; /* head of free list (NCR byte order) */
- Dsa *tail;
- Dsa *freechain;
- } dsalist;
-
- QLock q[MAXTARGET]; /* queues for each target */
-} Controller;
-
-static Controller controller;
-
-/* ISTAT */
-enum { Abrt = 0x80, Srst = 0x40, Sigp = 0x20, Sem = 0x10, Con = 0x08, Intf = 0x04, Sip = 0x02, Dip = 0x01 };
-
-/* DSTAT */
-enum { Dfe = 0x80, Mdpe = 0x40, Bf = 0x20, Abrted = 0x10, Ssi = 0x08, Sir = 0x04, Iid = 0x01 };
-
-/* SSTAT */
-enum { DataOut, DataIn, Cmd, Status, ReservedOut, ReservedIn, MessageOut, MessageIn };
-
-static void setmovedata(Movedata*, ulong, ulong);
-static void advancedata(Movedata*, long);
-static int bios_set_differential(Controller *c);
-
-static char *phase[] = {
- "data out", "data in", "command", "status",
- "reserved out", "reserved in", "message out", "message in"
-};
-
-#ifdef BOOTDEBUG
-#define DEBUGSIZE 10240
-char debugbuf[DEBUGSIZE];
-char *debuglast;
-
-static void
-intrprint(char *format, ...)
-{
- if (debuglast == 0)
- debuglast = debugbuf;
- debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
-}
-
-static void
-iflush()
-{
- int s;
- char *endp;
- s = splhi();
- if (debuglast == 0)
- debuglast = debugbuf;
- if (debuglast == debugbuf) {
- splx(s);
- return;
- }
- endp = debuglast;
- splx(s);
- screenputs(debugbuf, endp - debugbuf);
- s = splhi();
- memmove(debugbuf, endp, debuglast - endp);
- debuglast -= endp - debugbuf;
- splx(s);
-}
-
-static void
-oprint(char *format, ...)
-{
- int s;
-
- iflush();
- s = splhi();
- if (debuglast == 0)
- debuglast = debugbuf;
- debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
- splx(s);
- iflush();
-}
-#endif
-
-#include "sd53c8xx.i"
-
-static Dsa *
-dsaalloc(Controller *c, int target, int lun)
-{
- Dsa *d;
-
- ilock(&c->dsalist);
- if ((d = c->dsalist.freechain) == 0) {
- d = xalloc(sizeof(*d));
- if (DEBUG(1))
- KPRINT("sd53c8xx: %d/%d: allocated new dsa %lux\n", target, lun, d);
- lesetl(d->next, 0);
- lesetl(d->state, A_STATE_ALLOCATED);
- if (legetl(c->dsalist.head) == 0)
- lesetl(c->dsalist.head, DMASEG(d)); /* ATOMIC?!? */
- else
- lesetl(c->dsalist.tail->next, DMASEG(d)); /* ATOMIC?!? */
- c->dsalist.tail = d;
- }
- else {
- if (DEBUG(1))
- KPRINT("sd53c8xx: %d/%d: reused dsa %lux\n", target, lun, d);
- c->dsalist.freechain = d->freechain;
- lesetl(d->state, A_STATE_ALLOCATED);
- }
- iunlock(&c->dsalist);
- d->target = target;
- d->lun = lun;
- return d;
-}
-
-static void
-dsafree(Controller *c, Dsa *d)
-{
- ilock(&c->dsalist);
- d->freechain = c->dsalist.freechain;
- c->dsalist.freechain = d;
- lesetl(d->state, A_STATE_FREE);
- iunlock(&c->dsalist);
-}
-
-static Dsa *
-dsafind(Controller *c, uchar target, uchar lun, uchar state)
-{
- Dsa *d;
- for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) {
- if (d->target != 0xff && d->target != target)
- continue;
- if (lun != 0xff && d->lun != lun)
- continue;
- if (state != 0xff && d->stateb != state)
- continue;
- break;
- }
- return d;
-}
-
-static void
-dumpncrregs(Controller *c, int intr)
-{
- int i;
- Ncr *n = c->n;
- int depth = c->v->registers / 4;
-
- KPRINT("sa = %.8lux\n", c->scriptpa);
- for (i = 0; i < depth; i++) {
- int j;
- for (j = 0; j < 4; j++) {
- int k = j * depth + i;
- uchar *p;
-
- /* display little-endian to make 32-bit values readable */
- p = (uchar*)n+k*4;
- if (intr)
- IPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
- else
- KPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
- USED(p);
- }
- if (intr)
- IPRINT("\n");
- else
- KPRINT("\n");
- }
-}
-
-static int
-chooserate(Controller *c, int tpf, int *scfp, int *xferpp)
-{
- /* find lowest entry >= tpf */
- int besttpf = 1000;
- int bestscfi = 0;
- int bestxferp = 0;
- int scf, xferp;
- int maxscf;
-
- if (c->v->feature & Ultra2)
- maxscf = NULTRA2SCF;
- else if (c->v->feature & Ultra)
- maxscf = NULTRASCF;
- else
- maxscf = NSCF;
-
- /*
- * search large clock factors first since this should
- * result in more reliable transfers
- */
- for (scf = maxscf; scf >= 1; scf--) {
- for (xferp = 0; xferp < 8; xferp++) {
- unsigned char v = c->synctab[scf - 1][xferp];
- if (v == 0)
- continue;
- if (v >= tpf && v < besttpf) {
- besttpf = v;
- bestscfi = scf;
- bestxferp = xferp;
- }
- }
- }
- if (besttpf == 1000)
- return 0;
- if (scfp)
- *scfp = bestscfi;
- if (xferpp)
- *xferpp = bestxferp;
- return besttpf;
-}
-
-static void
-synctabinit(Controller *c)
-{
- int scf;
- unsigned long scsilimit;
- int xferp;
- unsigned long cr, sr;
- int tpf;
- int fast;
- int maxscf;
-
- if (c->v->feature & Ultra2)
- maxscf = NULTRA2SCF;
- else if (c->v->feature & Ultra)
- maxscf = NULTRASCF;
- else
- maxscf = NSCF;
-
- /*
- * for chips with no clock doubler, but Ultra capable (e.g. 860, or interestingly the
- * first spin of the 875), assume 80MHz
- * otherwise use the internal (33 Mhz) or external (40MHz) default
- */
-
- if ((c->v->feature & Ultra) != 0 && (c->v->feature & (ClockDouble | ClockQuad)) == 0)
- c->sclk = ULTRA_NOCLOCKDOUBLE_SCLK;
- else
- c->sclk = SCLK;
-
- /*
- * otherwise, if the chip is Ultra capable, but has a slow(ish) clock,
- * invoke the doubler
- */
-
- if (SCLK <= 40000000) {
- if (c->v->feature & ClockDouble) {
- c->sclk *= 2;
- c->clockmult = 1;
- }
- else if (c->v->feature & ClockQuad) {
- c->sclk *= 4;
- c->clockmult = 1;
- }
- else
- c->clockmult = 0;
- }
- else
- c->clockmult = 0;
-
- /* derive CCF from sclk */
- /* woebetide anyone with SCLK < 16.7 or > 80MHz */
- if (c->sclk <= 25 * MEGA)
- c->ccf = 1;
- else if (c->sclk <= 3750000)
- c->ccf = 2;
- else if (c->sclk <= 50 * MEGA)
- c->ccf = 3;
- else if (c->sclk <= 75 * MEGA)
- c->ccf = 4;
- else if ((c->v->feature & ClockDouble) && c->sclk <= 80 * MEGA)
- c->ccf = 5;
- else if ((c->v->feature & ClockQuad) && c->sclk <= 120 * MEGA)
- c->ccf = 6;
- else if ((c->v->feature & ClockQuad) && c->sclk <= 160 * MEGA)
- c->ccf = 7;
-
- for (scf = 1; scf < maxscf; scf++) {
- /* check for legal core rate */
- /* round up so we run slower for safety */
- cr = (c->sclk * 2 + cf2[scf] - 1) / cf2[scf];
- if (cr <= MAXSYNCCORERATE) {
- scsilimit = MAXSYNCSCSIRATE;
- fast = 0;
- }
- else if (cr <= MAXFASTSYNCCORERATE) {
- scsilimit = MAXFASTSYNCSCSIRATE;
- fast = 1;
- }
- else if ((c->v->feature & Ultra) && cr <= MAXULTRASYNCCORERATE) {
- scsilimit = MAXULTRASYNCSCSIRATE;
- fast = 2;
- }
- else if ((c->v->feature & Ultra2) && cr <= MAXULTRA2SYNCCORERATE) {
- scsilimit = MAXULTRA2SYNCSCSIRATE;
- fast = 3;
- }
- else
- continue;
- for (xferp = 11; xferp >= 4; xferp--) {
- int ok;
- int tp;
- /* calculate scsi rate - round up again */
- /* start from sclk for accuracy */
- int totaldivide = xferp * cf2[scf];
- sr = (c->sclk * 2 + totaldivide - 1) / totaldivide;
- if (sr > scsilimit)
- break;
- /*
- * now work out transfer period
- * round down now so that period is pessimistic
- */
- tp = (MEGA * 1000) / sr;
- /*
- * bounds check it
- */
- if (tp < 25 || tp > 255 * 4)
- continue;
- /*
- * spot stupid special case for Ultra or Ultra2
- * while working out factor
- */
- if (tp == 25)
- tpf = 10;
- else if (tp == 50)
- tpf = 12;
- else if (tp < 52)
- continue;
- else
- tpf = tp / 4;
- /*
- * now check tpf looks sensible
- * given core rate
- */
- switch (fast) {
- case 0:
- /* scf must be ccf for SCSI 1 */
- ok = tpf >= 50 && scf == c->ccf;
- break;
- case 1:
- ok = tpf >= 25 && tpf < 50;
- break;
- case 2:
- /*
- * must use xferp of 4, or 5 at a pinch
- * for an Ultra transfer
- */
- ok = xferp <= 5 && tpf >= 12 && tpf < 25;
- break;
- case 3:
- ok = xferp == 4 && (tpf == 10 || tpf == 11);
- break;
- default:
- ok = 0;
- }
- if (!ok)
- continue;
- c->synctab[scf - 1][xferp - 4] = tpf;
- }
- }
-
-#ifndef NO_ULTRA2
- if (c->v->feature & Ultra2)
- tpf = 10;
- else
-#endif
- if (c->v->feature & Ultra)
- tpf = 12;
- else
- tpf = 25;
- for (; tpf < 256; tpf++) {
- if (chooserate(c, tpf, &scf, &xferp) == tpf) {
- unsigned tp = tpf == 10 ? 25 : (tpf == 12 ? 50 : tpf * 4);
- unsigned long khz = (MEGA + tp - 1) / (tp);
- KPRINT("sd53c8xx: tpf=%d scf=%d.%.1d xferp=%d mhz=%ld.%.3ld\n",
- tpf, cf2[scf] / 2, (cf2[scf] & 1) ? 5 : 0,
- xferp + 4, khz / 1000, khz % 1000);
- USED(khz);
- if (c->tpf == 0)
- c->tpf = tpf; /* note lowest value for controller */
- }
- }
-}
-
-static void
-synctodsa(Dsa *dsa, Controller *c)
-{
-/*
- KPRINT("synctodsa(dsa=%lux, target=%d, scntl3=%.2lx sxfer=%.2x)\n",
- dsa, dsa->target, c->scntl3[dsa->target], c->sxfer[dsa->target]);
-*/
- dsa->scntl3 = c->scntl3[dsa->target];
- dsa->sxfer = c->sxfer[dsa->target];
-}
-
-static void
-setsync(Dsa *dsa, Controller *c, int target, uchar ultra, uchar scf, uchar xferp, uchar reqack)
-{
- c->scntl3[target] =
- (c->scntl3[target] & 0x08) | (((scf << 4) | c->ccf | (ultra << 7)) & ~0x08);
- c->sxfer[target] = (xferp << 5) | reqack;
- c->s[target] = BothDone;
- if (dsa) {
- synctodsa(dsa, c);
- c->n->scntl3 = c->scntl3[target];
- c->n->sxfer = c->sxfer[target];
- }
-}
-
-static void
-setasync(Dsa *dsa, Controller *c, int target)
-{
- setsync(dsa, c, target, 0, c->ccf, 0, 0);
-}
-
-static void
-setwide(Dsa *dsa, Controller *c, int target, uchar wide)
-{
- c->scntl3[target] = wide ? (1 << 3) : 0;
- setasync(dsa, c, target);
- c->s[target] = WideDone;
-}
-
-static int
-buildsdtrmsg(uchar *buf, uchar tpf, uchar offset)
-{
- *buf++ = X_MSG;
- *buf++ = 3;
- *buf++ = X_MSG_SDTR;
- *buf++ = tpf;
- *buf = offset;
- return 5;
-}
-
-static int
-buildwdtrmsg(uchar *buf, uchar expo)
-{
- *buf++ = X_MSG;
- *buf++ = 2;
- *buf++ = X_MSG_WDTR;
- *buf = expo;
- return 4;
-}
-
-static void
-start(Controller *c, long entry)
-{
- ulong p;
-
- if (c->running)
- panic("sd53c8xx: start called while running");
- c->running = 1;
- p = c->scriptpa + entry;
- lesetl(c->n->dsp, p);
- if (c->ssm)
- c->n->dcntl |= 0x4; /* start DMA in SSI mode */
-}
-
-static void
-ncrcontinue(Controller *c)
-{
- if (c->running)
- panic("sd53c8xx: ncrcontinue called while running");
- /* set the start DMA bit to continue execution */
- c->running = 1;
- c->n->dcntl |= 0x4;
-}
-
-static void
-softreset(Controller *c)
-{
- Ncr *n = c->n;
-
- n->istat = Srst; /* software reset */
- n->istat = 0;
- /* general initialisation */
- n->scid = (1 << 6) | 7; /* respond to reselect, ID 7 */
- n->respid = 1 << 7; /* response ID = 7 */
-
-#ifdef INTERNAL_SCLK
- n->stest1 = 0x80; /* disable external scsi clock */
-#else
- n->stest1 = 0x00;
-#endif
-
- n->stime0 = 0xdd; /* about 0.5 second timeout on each device */
- n->scntl0 |= 0x8; /* Enable parity checking */
-
- /* continued setup */
- n->sien0 = 0x8f;
- n->sien1 = 0x04;
- n->dien = 0x7d;
- n->stest3 = 0x80; /* TolerANT enable */
- c->running = 0;
-
- if (c->v->feature & BigFifo)
- n->ctest5 = (1 << 5);
- n->dmode = c->v->burst << 6; /* set burst length bits */
- if (c->v->burst & 4)
- n->ctest5 |= (1 << 2); /* including overflow into ctest5 bit 2 */
- if (c->v->feature & Prefetch)
- n->dcntl |= (1 << 5); /* prefetch enable */
- else if (c->v->feature & BurstOpCodeFetch)
- n->dmode |= (1 << 1); /* burst opcode fetch */
- if (c->v->feature & Differential) {
- /* chip capable */
- if ((c->feature & Differential) || bios_set_differential(c)) {
- /* user enabled, or some evidence bios set differential */
- if (n->sstat2 & (1 << 2))
- print("sd53c8xx: can't go differential; wrong cable\n");
- else {
- n->stest2 = (1 << 5);
- print("sd53c8xx: differential mode set\n");
- }
- }
- }
- if (c->clockmult) {
- n->stest1 |= (1 << 3); /* power up doubler */
- delay(2);
- n->stest3 |= (1 << 5); /* stop clock */
- n->stest1 |= (1 << 2); /* enable doubler */
- n->stest3 &= ~(1 << 5); /* start clock */
- /* pray */
- }
-}
-
-static void
-msgsm(Dsa *dsa, Controller *c, int msg, int *cont, int *wakeme)
-{
- uchar histpf, hisreqack;
- int tpf;
- int scf, xferp;
- int len;
-
- Ncr *n = c->n;
-
- switch (c->s[dsa->target]) {
- case SyncInit:
- switch (msg) {
- case A_SIR_MSG_SDTR:
- /* reply to my SDTR */
- histpf = n->scratcha[2];
- hisreqack = n->scratcha[3];
- KPRINT("sd53c8xx: %d: SDTN response %d %d\n",
- dsa->target, histpf, hisreqack);
-
- if (hisreqack == 0)
- setasync(dsa, c, dsa->target);
- else {
- /* hisreqack should be <= c->v->maxsyncoff */
- tpf = chooserate(c, histpf, &scf, &xferp);
- KPRINT("sd53c8xx: %d: SDTN: using %d %d\n",
- dsa->target, tpf, hisreqack);
- setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
- }
- *cont = -2;
- return;
- case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
- /* target ignored ATN for message after IDENTIFY - not SCSI-II */
- KPRINT("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
- KPRINT("sd53c8xx: %d: SDTN: async\n", dsa->target);
- setasync(dsa, c, dsa->target);
- *cont = E_to_decisions;
- return;
- case A_SIR_MSG_REJECT:
- /* rejection of my SDTR */
- KPRINT("sd53c8xx: %d: SDTN: rejected SDTR\n", dsa->target);
- //async:
- KPRINT("sd53c8xx: %d: SDTN: async\n", dsa->target);
- setasync(dsa, c, dsa->target);
- *cont = -2;
- return;
- }
- break;
- case WideInit:
- switch (msg) {
- case A_SIR_MSG_WDTR:
- /* reply to my WDTR */
- KPRINT("sd53c8xx: %d: WDTN: response %d\n",
- dsa->target, n->scratcha[2]);
- setwide(dsa, c, dsa->target, n->scratcha[2]);
- *cont = -2;
- return;
- case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
- /* target ignored ATN for message after IDENTIFY - not SCSI-II */
- KPRINT("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
- setwide(dsa, c, dsa->target, 0);
- *cont = E_to_decisions;
- return;
- case A_SIR_MSG_REJECT:
- /* rejection of my SDTR */
- KPRINT("sd53c8xx: %d: WDTN: rejected WDTR\n", dsa->target);
- setwide(dsa, c, dsa->target, 0);
- *cont = -2;
- return;
- }
- break;
-
- case NeitherDone:
- case WideDone:
- case BothDone:
- switch (msg) {
- case A_SIR_MSG_WDTR: {
- uchar hiswide, mywide;
- hiswide = n->scratcha[2];
- mywide = (c->v->feature & Wide) != 0;
- KPRINT("sd53c8xx: %d: WDTN: target init %d\n",
- dsa->target, hiswide);
- if (hiswide < mywide)
- mywide = hiswide;
- KPRINT("sd53c8xx: %d: WDTN: responding %d\n",
- dsa->target, mywide);
- setwide(dsa, c, dsa->target, mywide);
- len = buildwdtrmsg(dsa->msg_out, mywide);
- setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
- *cont = E_response;
- c->s[dsa->target] = WideResponse;
- return;
- }
- case A_SIR_MSG_SDTR:
-#ifdef ASYNC_ONLY
- *cont = E_reject;
- return;
-#else
- /* target decides to renegotiate */
- histpf = n->scratcha[2];
- hisreqack = n->scratcha[3];
- KPRINT("sd53c8xx: %d: SDTN: target init %d %d\n",
- dsa->target, histpf, hisreqack);
- if (hisreqack == 0) {
- /* he wants asynchronous */
- setasync(dsa, c, dsa->target);
- tpf = 0;
- }
- else {
- /* he wants synchronous */
- tpf = chooserate(c, histpf, &scf, &xferp);
- if (hisreqack > c->v->maxsyncoff)
- hisreqack = c->v->maxsyncoff;
- KPRINT("sd53c8xx: %d: using %d %d\n",
- dsa->target, tpf, hisreqack);
- setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
- }
- /* build my SDTR message */
- len = buildsdtrmsg(dsa->msg_out, tpf, hisreqack);
- setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
- *cont = E_response;
- c->s[dsa->target] = SyncResponse;
- return;
-#endif
- }
- break;
- case WideResponse:
- switch (msg) {
- case A_SIR_EV_RESPONSE_OK:
- c->s[dsa->target] = WideDone;
- KPRINT("sd53c8xx: %d: WDTN: response accepted\n", dsa->target);
- *cont = -2;
- return;
- case A_SIR_MSG_REJECT:
- setwide(dsa, c, dsa->target, 0);
- KPRINT("sd53c8xx: %d: WDTN: response REJECTed\n", dsa->target);
- *cont = -2;
- return;
- }
- break;
- case SyncResponse:
- switch (msg) {
- case A_SIR_EV_RESPONSE_OK:
- c->s[dsa->target] = BothDone;
- KPRINT("sd53c8xx: %d: SDTN: response accepted (%s)\n",
- dsa->target, phase[n->sstat1 & 7]);
- *cont = -2;
- return; /* chf */
- case A_SIR_MSG_REJECT:
- setasync(dsa, c, dsa->target);
- KPRINT("sd53c8xx: %d: SDTN: response REJECTed\n", dsa->target);
- *cont = -2;
- return;
- }
- break;
- }
- KPRINT("sd53c8xx: %d: msgsm: state %d msg %d\n",
- dsa->target, c->s[dsa->target], msg);
- *wakeme = 1;
- return;
-}
-
-static void
-calcblockdma(Dsa *d, ulong base, ulong count)
-{
- ulong blocks;
- if (DEBUG(3))
- blocks = 0;
- else {
- blocks = count / A_BSIZE;
- if (blocks > 255)
- blocks = 255;
- }
- d->dmablks = blocks;
- d->dmaaddr[0] = base;
- d->dmaaddr[1] = base >> 8;
- d->dmaaddr[2] = base >> 16;
- d->dmaaddr[3] = base >> 24;
- setmovedata(&d->data_buf, base + blocks * A_BSIZE, count - blocks * A_BSIZE);
- if (legetl(d->data_buf.dbc) == 0)
- d->flag = 1;
-}
-
-static ulong
-read_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa)
-{
- ulong dbc;
- uchar dfifo = n->dfifo;
- int inchip;
-
- dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
- if (n->ctest5 & (1 << 5))
- inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
- else
- inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
- if (inchip) {
- IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: DMA FIFO = %d\n",
- dsa->target, dsa->lun, inchip);
- }
- if (n->sxfer & 0xf) {
- /* SCSI FIFO */
- uchar fifo = n->sstat1 >> 4;
- if (c->v->maxsyncoff > 8)
- fifo |= (n->sstat2 & (1 << 4));
- if (fifo) {
- inchip += fifo;
- IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SCSI FIFO = %d\n",
- dsa->target, dsa->lun, fifo);
- }
- }
- else {
- if (n->sstat0 & (1 << 7)) {
- inchip++;
- IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL full\n",
- dsa->target, dsa->lun);
- }
- if (n->sstat2 & (1 << 7)) {
- inchip++;
- IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL msb full\n",
- dsa->target, dsa->lun);
- }
- }
- USED(inchip);
- return dbc;
-}
-
-static ulong
-write_mismatch_recover(Ncr *n, Dsa *dsa)
-{
- ulong dbc;
- uchar dfifo = n->dfifo;
- int inchip;
-
- dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
- USED(dsa);
- if (n->ctest5 & (1 << 5))
- inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
- else
- inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
-#ifdef WMR_DEBUG
- if (inchip) {
- IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: DMA FIFO = %d\n",
- dsa->target, dsa->lun, inchip);
- }
-#endif
- if (n->sstat0 & (1 << 5)) {
- inchip++;
-#ifdef WMR_DEBUG
- IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun);
-#endif
- }
- if (n->sstat2 & (1 << 5)) {
- inchip++;
-#ifdef WMR_DEBUG
- IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun);
-#endif
- }
- if (n->sxfer & 0xf) {
- /* synchronous SODR */
- if (n->sstat0 & (1 << 6)) {
- inchip++;
-#ifdef WMR_DEBUG
- IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR full\n",
- dsa->target, dsa->lun);
-#endif
- }
- if (n->sstat2 & (1 << 6)) {
- inchip++;
-#ifdef WMR_DEBUG
- IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR msb full\n",
- dsa->target, dsa->lun);
-#endif
- }
- }
- /* clear the dma fifo */
- n->ctest3 |= (1 << 2);
- /* wait till done */
- while ((n->dstat & Dfe) == 0)
- ;
- return dbc + inchip;
-}
-
-static void
-interrupt(Ureg *ur, void *a)
-{
- uchar istat;
- ushort sist;
- uchar dstat;
- int wakeme = 0;
- int cont = -1;
- Dsa *dsa;
- Controller *c = a;
- Ncr *n = c->n;
-
- USED(ur);
- if (DEBUG(1))
- IPRINT("sd53c8xx: int\n");
- ilock(c);
- istat = n->istat;
- if (istat & Intf) {
- Dsa *d;
- int wokesomething = 0;
- if (DEBUG(1))
- IPRINT("sd53c8xx: Intfly\n");
- n->istat = Intf;
- /* search for structures in A_STATE_DONE */
- for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) {
- if (d->stateb == A_STATE_DONE) {
- d->p9status = d->status;
- if (DEBUG(1))
- IPRINT("sd53c8xx: waking up dsa %lux\n", d);
- wakeup(d);
- wokesomething = 1;
- }
- }
- if (!wokesomething)
- IPRINT("sd53c8xx: nothing to wake up\n");
- }
-
- if ((istat & (Sip | Dip)) == 0) {
- if (DEBUG(1))
- IPRINT("sd53c8xx: int end %x\n", istat);
- iunlock(c);
- return;
- }
-
- sist = (n->sist1<<8)|n->sist0; /* BUG? can two-byte read be inconsistent? */
- dstat = n->dstat;
- dsa = (Dsa *)DMASEG_TO_KADDR(legetl(n->dsa));
- c->running = 0;
- if (istat & Sip) {
- if (DEBUG(1))
- IPRINT("sist = %.4x\n", sist);
- if (sist & 0x80) {
- ulong addr;
- ulong sa;
- ulong dbc;
- ulong tbc;
- int dmablks;
- ulong dmaaddr;
-
- addr = legetl(n->dsp);
- sa = addr - c->scriptpa;
- if (DEBUG(1) || DEBUG(2))
- IPRINT("sd53c8xx: %d/%d: Phase Mismatch sa=%.8lux\n",
- dsa->target, dsa->lun, sa);
- /*
- * now recover
- */
- if (sa == E_data_in_mismatch) {
- dbc = read_mismatch_recover(c, n, dsa);
- tbc = legetl(dsa->data_buf.dbc) - dbc;
- advancedata(&dsa->data_buf, tbc);
- if (DEBUG(1) || DEBUG(2))
- IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n",
- dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
- cont = E_to_decisions;
- }
- else if (sa == E_data_in_block_mismatch) {
- dbc = read_mismatch_recover(c, n, dsa);
- tbc = A_BSIZE - dbc;
- /* recover current state from registers */
- dmablks = n->scratcha[2];
- dmaaddr = legetl(n->scratchb);
- /* we have got to dmaaddr + tbc */
- /* we have dmablks * A_BSIZE - tbc + residue left to do */
- /* so remaining transfer is */
- IPRINT("in_block_mismatch: dmaaddr = 0x%lux tbc=%lud dmablks=%d\n",
- dmaaddr, tbc, dmablks);
- calcblockdma(dsa, dmaaddr + tbc,
- dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
- /* copy changes into scratch registers */
- IPRINT("recalc: dmablks %d dmaaddr 0x%lx pa 0x%lx dbc %ld\n",
- dsa->dmablks, legetl(dsa->dmaaddr),
- legetl(dsa->data_buf.pa), legetl(dsa->data_buf.dbc));
- n->scratcha[2] = dsa->dmablks;
- lesetl(n->scratchb, dsa->dmancr);
- cont = E_data_block_mismatch_recover;
- }
- else if (sa == E_data_out_mismatch) {
- dbc = write_mismatch_recover(n, dsa);
- tbc = legetl(dsa->data_buf.dbc) - dbc;
- advancedata(&dsa->data_buf, tbc);
- if (DEBUG(1) || DEBUG(2))
- IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n",
- dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
- cont = E_to_decisions;
- }
- else if (sa == E_data_out_block_mismatch) {
- dbc = write_mismatch_recover(n, dsa);
- tbc = legetl(dsa->data_buf.dbc) - dbc;
- /* recover current state from registers */
- dmablks = n->scratcha[2];
- dmaaddr = legetl(n->scratchb);
- /* we have got to dmaaddr + tbc */
- /* we have dmablks blocks - tbc + residue left to do */
- /* so remaining transfer is */
- IPRINT("out_block_mismatch: dmaaddr = %lux tbc=%lud dmablks=%d\n",
- dmaaddr, tbc, dmablks);
- calcblockdma(dsa, dmaaddr + tbc,
- dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
- /* copy changes into scratch registers */
- n->scratcha[2] = dsa->dmablks;
- lesetl(n->scratchb, dsa->dmancr);
- cont = E_data_block_mismatch_recover;
- }
- else if (sa == E_id_out_mismatch) {
- /*
- * target switched phases while attention held during
- * message out. The possibilities are:
- * 1. It didn't like the last message. This is indicated
- * by the new phase being message_in. Use script to recover
- *
- * 2. It's not SCSI-II compliant. The new phase will be other
- * than message_in. We should also indicate that the device
- * is asynchronous, if it's the SDTR that got ignored
- *
- * For now, if the phase switch is not to message_in, and
- * and it happens after IDENTIFY and before SDTR, we
- * notify the negotiation state machine.
- */
- ulong lim = legetl(dsa->msg_out_buf.dbc);
- uchar p = n->sstat1 & 7;
- dbc = write_mismatch_recover(n, dsa);
- tbc = lim - dbc;
- IPRINT("sd53c8xx: %d/%d: msg_out_mismatch: %lud/%lud sent, phase %s\n",
- dsa->target, dsa->lun, tbc, lim, phase[p]);
- if (p != MessageIn && tbc == 1) {
- msgsm(dsa, c, A_SIR_EV_PHASE_SWITCH_AFTER_ID, &cont, &wakeme);
- }
- else
- cont = E_id_out_mismatch_recover;
- }
- else if (sa == E_cmd_out_mismatch) {
- /*
- * probably the command count is longer than the device wants ...
- */
- ulong lim = legetl(dsa->cmd_buf.dbc);
- uchar p = n->sstat1 & 7;
- dbc = write_mismatch_recover(n, dsa);
- tbc = lim - dbc;
- IPRINT("sd53c8xx: %d/%d: cmd_out_mismatch: %lud/%lud sent, phase %s\n",
- dsa->target, dsa->lun, tbc, lim, phase[p]);
- USED(p, tbc);
- cont = E_to_decisions;
- }
- else {
- IPRINT("sd53c8xx: %d/%d: ma sa=%.8lux wanted=%s got=%s\n",
- dsa->target, dsa->lun, sa,
- phase[n->dcmd & 7],
- phase[n->sstat1 & 7]);
- dumpncrregs(c, 1);
- dsa->p9status = SDeio; /* chf */
- wakeme = 1;
- }
- }
- /*else*/ if (sist & 0x400) {
- if (DEBUG(0))
- IPRINT("sd53c8xx: %d/%d Sto\n", dsa->target, dsa->lun);
- dsa->p9status = SDtimeout;
- dsa->stateb = A_STATE_DONE;
- softreset(c);
- cont = E_issue_check;
- wakeme = 1;
- }
- if (sist & 0x1) {
- IPRINT("sd53c8xx: %d/%d: parity error\n", dsa->target, dsa->lun);
- dsa->parityerror = 1;
- }
- if (sist & 0x4) {
- IPRINT("sd53c8xx: %d/%d: unexpected disconnect\n",
- dsa->target, dsa->lun);
- dumpncrregs(c, 1);
- //wakeme = 1;
- dsa->p9status = SDeio;
- }
- }
- if (istat & Dip) {
- if (DEBUG(1))
- IPRINT("dstat = %.2x\n", dstat);
- /*else*/ if (dstat & Ssi) {
- ulong *p = DMASEG_TO_KADDR(legetl(n->dsp));
- ulong w = (uchar *)p - (uchar *)c->script;
- IPRINT("[%lux]", w);
- USED(w);
- cont = -2; /* restart */
- }
- if (dstat & Sir) {
- switch (legetl(n->dsps)) {
- case A_SIR_MSG_IO_COMPLETE:
- dsa->p9status = dsa->status;
- wakeme = 1;
- break;
- case A_SIR_MSG_SDTR:
- case A_SIR_MSG_WDTR:
- case A_SIR_MSG_REJECT:
- case A_SIR_EV_RESPONSE_OK:
- msgsm(dsa, c, legetl(n->dsps), &cont, &wakeme);
- break;
- case A_SIR_MSG_IGNORE_WIDE_RESIDUE:
- /* back up one in the data transfer */
- IPRINT("sd53c8xx: %d/%d: ignore wide residue %d, WSR = %d\n",
- dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1);
- if (dsa->dmablks == 0 && dsa->flag)
- IPRINT("sd53c8xx: %d/%d: transfer over; residue ignored\n",
- dsa->target, dsa->lun);
- else
- calcblockdma(dsa, legetl(dsa->dmaaddr) - 1,
- dsa->dmablks * A_BSIZE + legetl(dsa->data_buf.dbc) + 1);
- cont = -2;
- break;
- case A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT:
- IPRINT("sd53c8xx: %d: not msg_in after reselect (%s)",
- n->ssid & 7, phase[n->sstat1 & 7]);
- dsa = dsafind(c, n->ssid & 7, -1, A_STATE_DISCONNECTED);
- dumpncrregs(c, 1);
- wakeme = 1;
- break;
- case A_SIR_NOTIFY_MSG_IN:
- IPRINT("sd53c8xx: %d/%d: msg_in %d\n",
- dsa->target, dsa->lun, n->sfbr);
- cont = -2;
- break;
- case A_SIR_NOTIFY_DISC:
- IPRINT("sd53c8xx: %d/%d: disconnect:", dsa->target, dsa->lun);
- goto dsadump;
- case A_SIR_NOTIFY_STATUS:
- IPRINT("sd53c8xx: %d/%d: status\n", dsa->target, dsa->lun);
- cont = -2;
- break;
- case A_SIR_NOTIFY_COMMAND:
- IPRINT("sd53c8xx: %d/%d: commands\n", dsa->target, dsa->lun);
- cont = -2;
- break;
- case A_SIR_NOTIFY_DATA_IN:
- IPRINT("sd53c8xx: %d/%d: data in a %lx b %lx\n",
- dsa->target, dsa->lun, legetl(n->scratcha), legetl(n->scratchb));
- cont = -2;
- break;
- case A_SIR_NOTIFY_BLOCK_DATA_IN:
- IPRINT("sd53c8xx: %d/%d: block data in: a2 %x b %lx\n",
- dsa->target, dsa->lun, n->scratcha[2], legetl(n->scratchb));
- cont = -2;
- break;
- case A_SIR_NOTIFY_DATA_OUT:
- IPRINT("sd53c8xx: %d/%d: data out\n", dsa->target, dsa->lun);
- cont = -2;
- break;
- case A_SIR_NOTIFY_DUMP:
- IPRINT("sd53c8xx: %d/%d: dump\n", dsa->target, dsa->lun);
- dumpncrregs(c, 1);
- cont = -2;
- break;
- case A_SIR_NOTIFY_DUMP2:
- IPRINT("sd53c8xx: %d/%d: dump2:", dsa->target, dsa->lun);
- IPRINT(" sa %lux", legetl(n->dsp) - c->scriptpa);
- IPRINT(" dsa %lux", legetl(n->dsa));
- IPRINT(" sfbr %ux", n->sfbr);
- IPRINT(" a %lux", n->scratcha);
- IPRINT(" b %lux", legetl(n->scratchb));
- IPRINT(" ssid %ux", n->ssid);
- IPRINT("\n");
- cont = -2;
- break;
- case A_SIR_NOTIFY_WAIT_RESELECT:
- IPRINT("sd53c8xx: wait reselect\n");
- cont = -2;
- break;
- case A_SIR_NOTIFY_RESELECT:
- IPRINT("sd53c8xx: reselect: ssid %.2x sfbr %.2x at %ld\n",
- n->ssid, n->sfbr, TK2MS(m->ticks));
- cont = -2;
- break;
- case A_SIR_NOTIFY_ISSUE:
- IPRINT("sd53c8xx: %d/%d: issue:", dsa->target, dsa->lun);
- dsadump:
- IPRINT(" tgt=%d", dsa->target);
- IPRINT(" time=%ld", TK2MS(m->ticks));
- IPRINT("\n");
- cont = -2;
- break;
- case A_SIR_NOTIFY_ISSUE_CHECK:
- IPRINT("sd53c8xx: issue check\n");
- cont = -2;
- break;
- case A_SIR_NOTIFY_SIGP:
- IPRINT("sd53c8xx: responded to SIGP\n");
- cont = -2;
- break;
- case A_SIR_NOTIFY_DUMP_NEXT_CODE: {
- ulong *dsp = DMASEG_TO_KADDR(legetl(n->dsp));
- int x;
- IPRINT("sd53c8xx: code at %lux", dsp - c->script);
- for (x = 0; x < 6; x++)
- IPRINT(" %.8lux", dsp[x]);
- IPRINT("\n");
- USED(dsp);
- cont = -2;
- break;
- }
- case A_SIR_NOTIFY_WSR:
- IPRINT("sd53c8xx: %d/%d: WSR set\n", dsa->target, dsa->lun);
- cont = -2;
- break;
- case A_SIR_NOTIFY_LOAD_SYNC:
- IPRINT("sd53c8xx: %d/%d: scntl=%.2x sxfer=%.2x\n",
- dsa->target, dsa->lun, n->scntl3, n->sxfer);
- cont = -2;
- break;
- case A_SIR_NOTIFY_RESELECTED_ON_SELECT:
- IPRINT("sd53c8xx: %d/%d: reselected during select\n",
- dsa->target, dsa->lun);
- cont = -2;
- break;
- default:
- IPRINT("sd53c8xx: %d/%d: script error %ld\n",
- dsa->target, dsa->lun, legetl(n->dsps));
- dumpncrregs(c, 1);
- wakeme = 1;
- }
- }
- /*else*/ if (dstat & Iid) {
- ulong addr = legetl(n->dsp);
- ulong dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
- IPRINT("sd53c8xx: %d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n",
- dsa->target, dsa->lun,
- addr, addr - c->scriptpa, dbc);
- addr = (ulong)DMASEG_TO_KADDR(addr);
- IPRINT("%.8lux %.8lux %.8lux\n",
- *(ulong *)(addr - 12), *(ulong *)(addr - 8), *(ulong *)(addr - 4));
- USED(addr, dbc);
- dsa->p9status = SDeio;
- wakeme = 1;
- }
- /*else*/ if (dstat & Bf) {
- IPRINT("sd53c8xx: %d/%d: Bus Fault\n", dsa->target, dsa->lun);
- dumpncrregs(c, 1);
- dsa->p9status = SDeio;
- wakeme = 1;
- }
- }
- if (cont == -2)
- ncrcontinue(c);
- else if (cont >= 0)
- start(c, cont);
- if (wakeme){
- if(dsa->p9status == SDnostatus)
- dsa->p9status = SDeio;
- wakeup(dsa);
- }
- iunlock(c);
- if (DEBUG(1)) {
- IPRINT("sd53c8xx: int end 1\n");
- }
-}
-
-static int
-done(void *arg)
-{
- return ((Dsa *)arg)->p9status != SDnostatus;
-}
-
-static void
-setmovedata(Movedata *d, ulong pa, ulong bc)
-{
- d->pa[0] = pa;
- d->pa[1] = pa>>8;
- d->pa[2] = pa>>16;
- d->pa[3] = pa>>24;
- d->dbc[0] = bc;
- d->dbc[1] = bc>>8;
- d->dbc[2] = bc>>16;
- d->dbc[3] = bc>>24;
-}
-
-static void
-advancedata(Movedata *d, long v)
-{
- lesetl(d->pa, legetl(d->pa) + v);
- lesetl(d->dbc, legetl(d->dbc) - v);
-}
-
-static void
-dumpwritedata(uchar *data, int datalen)
-{
- int i;
- uchar *bp;
- if (!DEBUG(0)){
- USED(data, datalen);
- return;
- }
-
- if (datalen) {
- KPRINT("sd53c8xx:write:");
- for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++)
- KPRINT("%.2ux", *bp);
- if (i < datalen) {
- KPRINT("...");
- }
- KPRINT("\n");
- }
-}
-
-static void
-dumpreaddata(uchar *data, int datalen)
-{
- int i;
- uchar *bp;
- if (!DEBUG(0)){
- USED(data, datalen);
- return;
- }
-
- if (datalen) {
- KPRINT("sd53c8xx:read:");
- for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++)
- KPRINT("%.2ux", *bp);
- if (i < datalen) {
- KPRINT("...");
- }
- KPRINT("\n");
- }
-}
-
-static void
-busreset(Controller *c)
-{
- int x, ntarget;
-
- /* bus reset */
- c->n->scntl1 |= (1 << 3);
- delay(500);
- c->n->scntl1 &= ~(1 << 3);
- if(!(c->v->feature & Wide))
- ntarget = 8;
- else
- ntarget = MAXTARGET;
- for (x = 0; x < ntarget; x++) {
- setwide(0, c, x, 0);
-#ifndef ASYNC_ONLY
- c->s[x] = NeitherDone;
-#endif
- }
- c->capvalid = 0;
-}
-
-static void
-reset(Controller *c)
-{
- /* should wakeup all pending tasks */
- softreset(c);
- busreset(c);
-}
-
-static int
-symrio(SDreq* r)
-{
- Dsa *d;
- uchar *bp;
- Controller *c;
- uchar target_expo, my_expo;
- int bc, check, status, target;
-
- if((target = r->unit->subno) == 0x07)
- return r->status = SDtimeout; /* assign */
- c = r->unit->dev->ctlr;
-
- check = 0;
- d = dsaalloc(c, target, r->lun);
-
- qlock(&c->q[target]); /* obtain access to target */
-docheck:
- /* load the transfer control stuff */
- d->scsi_id_buf[0] = 0;
- d->scsi_id_buf[1] = c->sxfer[target];
- d->scsi_id_buf[2] = target;
- d->scsi_id_buf[3] = c->scntl3[target];
- synctodsa(d, c);
-
- bc = 0;
-
- d->msg_out[bc] = 0x80 | r->lun;
-
-#ifndef NO_DISCONNECT
- d->msg_out[bc] |= (1 << 6);
-#endif
- bc++;
-
- /* work out what to do about negotiation */
- switch (c->s[target]) {
- default:
- KPRINT("sd53c8xx: %d: strange nego state %d\n", target, c->s[target]);
- c->s[target] = NeitherDone;
- /* fall through */
- case NeitherDone:
- if ((c->capvalid & (1 << target)) == 0)
- break;
- target_expo = (c->cap[target] >> 5) & 3;
- my_expo = (c->v->feature & Wide) != 0;
- if (target_expo < my_expo)
- my_expo = target_expo;
-#ifdef ALWAYS_DO_WDTR
- bc += buildwdtrmsg(d->msg_out + bc, my_expo);
- KPRINT("sd53c8xx: %d: WDTN: initiating expo %d\n", target, my_expo);
- c->s[target] = WideInit;
- break;
-#else
- if (my_expo) {
- bc += buildwdtrmsg(d->msg_out + bc, (c->v->feature & Wide) ? 1 : 0);
- KPRINT("sd53c8xx: %d: WDTN: initiating expo %d\n", target, my_expo);
- c->s[target] = WideInit;
- break;
- }
- KPRINT("sd53c8xx: %d: WDTN: narrow\n", target);
- /* fall through */
-#endif
- case WideDone:
- if (c->cap[target] & (1 << 4)) {
- KPRINT("sd53c8xx: %d: SDTN: initiating %d %d\n", target, c->tpf, c->v->maxsyncoff);
- bc += buildsdtrmsg(d->msg_out + bc, c->tpf, c->v->maxsyncoff);
- c->s[target] = SyncInit;
- break;
- }
- KPRINT("sd53c8xx: %d: SDTN: async only\n", target);
- c->s[target] = BothDone;
- break;
-
- case BothDone:
- break;
- }
-
- setmovedata(&d->msg_out_buf, DMASEG(d->msg_out), bc);
- setmovedata(&d->cmd_buf, DMASEG(r->cmd), r->clen);
- calcblockdma(d, DMASEG(r->data), r->dlen);
-
- if (DEBUG(0)) {
- KPRINT("sd53c8xx: %d/%d: exec: ", target, r->lun);
- for (bp = r->cmd; bp < &r->cmd[r->clen]; bp++)
- KPRINT("%.2ux", *bp);
- KPRINT("\n");
- if (!r->write)
- KPRINT("sd53c8xx: %d/%d: exec: limit=(%d)%ld\n",
- target, r->lun, d->dmablks, legetl(d->data_buf.dbc));
- else
- dumpwritedata(r->data, r->dlen);
- }
-
- setmovedata(&d->status_buf, DMASEG(&d->status), 1);
-
- d->p9status = SDnostatus;
- d->parityerror = 0;
-
- d->stateb = A_STATE_ISSUE; /* start operation */
-
- ilock(c);
- if (c->ssm)
- c->n->dcntl |= 0x10; /* SSI */
- if (c->running) {
- c->n->istat |= Sigp;
- }
- else {
- start(c, E_issue_check);
- }
- iunlock(c);
-
- while(waserror())
- ;
- tsleep(d, done, d, 30 * 1000);
- poperror();
-
- if (!done(d)) {
- KPRINT("sd53c8xx: %d/%d: exec: Timed out\n", target, r->lun);
- dumpncrregs(c, 0);
- dsafree(c, d);
- reset(c);
- qunlock(&c->q[target]);
- r->status = SDtimeout;
- return r->status = SDtimeout; /* assign */
- }
-
- if((status = d->p9status) == SDeio)
- c->s[target] = NeitherDone;
- if (d->parityerror) {
- status = SDeio;
- }
-
- /*
- * adjust datalen
- */
- r->rlen = r->dlen;
- if (d->dmablks > 0)
- r->rlen -= d->dmablks * A_BSIZE;
- else if (d->flag == 0)
- r->rlen -= legetl(d->data_buf.dbc);
- if(!r->write)
- dumpreaddata(r->data, r->rlen);
- if (DEBUG(0))
- KPRINT("53c8xx: %d/%d: exec: p9status=%d status %d rlen %ld\n",
- target, r->lun, d->p9status, status, r->rlen);
- /*
- * spot the identify
- */
- if ((c->capvalid & (1 << target)) == 0
- && (status == SDok || status == SDcheck)
- && r->cmd[0] == 0x12 && r->dlen >= 8) {
- c->capvalid |= 1 << target;
- bp = r->data;
- c->cap[target] = bp[7];
- KPRINT("sd53c8xx: %d: capabilities %.2x\n", target, bp[7]);
- }
- if(!check && status == SDcheck && !(r->flags & SDnosense)){
- check = 1;
- r->write = 0;
- memset(r->cmd, 0, sizeof(r->cmd));
- r->cmd[0] = 0x03;
- r->cmd[1] = r->lun<<5;
- r->cmd[4] = sizeof(r->sense)-1;
- r->clen = 6;
- r->data = r->sense;
- r->dlen = sizeof(r->sense)-1;
- /*
- * Clear out the microcode state
- * so the Dsa can be re-used.
- */
- lesetl(d->state, A_STATE_ALLOCATED);
- goto docheck;
- }
- qunlock(&c->q[target]);
- dsafree(c, d);
-
- if(status == SDok && check){
- status = SDcheck;
- r->flags |= SDvalidsense;
- }
- KPRINT("sd53c8xx: %d: r flags %8.8uX status %d rlen %ld\n",
- target, r->flags, status, r->rlen);
- return r->status = status;
-}
-
-static void
-cribbios(Controller *c)
-{
- c->bios.scntl3 = c->n->scntl3;
- c->bios.stest2 = c->n->stest2;
- print("sd53c8xx: bios scntl3(%.2x) stest2(%.2x)\n", c->bios.scntl3, c->bios.stest2);
-}
-
-static int
-bios_set_differential(Controller *c)
-{
- /* Concept lifted from FreeBSD - thanks Gerard */
- /* basically, if clock conversion factors are set, then there is
- * evidence the bios had a go at the chip, and if so, it would
- * have set the differential enable bit in stest2
- */
- return (c->bios.scntl3 & 7) != 0 && (c->bios.stest2 & 0x20) != 0;
-}
-
-#define NCR_VID 0x1000
-#define NCR_810_DID 0x0001
-#define NCR_820_DID 0x0002 /* don't know enough about this one to support it */
-#define NCR_825_DID 0x0003
-#define NCR_815_DID 0x0004
-#define SYM_810AP_DID 0x0005
-#define SYM_860_DID 0x0006
-#define SYM_896_DID 0x000b
-#define SYM_895_DID 0x000c
-#define SYM_885_DID 0x000d /* ditto */
-#define SYM_875_DID 0x000f /* ditto */
-#define SYM_1010_DID 0x0020
-#define SYM_1011_DID 0x0021
-#define SYM_875J_DID 0x008f
-
-static Variant variant[] = {
-{ NCR_810_DID, 0x0f, "NCR53C810", Burst16, 8, 24, 0 },
-{ NCR_810_DID, 0x1f, "SYM53C810ALV", Burst16, 8, 24, Prefetch },
-{ NCR_810_DID, 0xff, "SYM53C810A", Burst16, 8, 24, Prefetch },
-{ SYM_810AP_DID, 0xff, "SYM53C810AP", Burst16, 8, 24, Prefetch },
-{ NCR_815_DID, 0xff, "NCR53C815", Burst16, 8, 24, BurstOpCodeFetch },
-{ NCR_825_DID, 0x0f, "NCR53C825", Burst16, 8, 24, Wide|BurstOpCodeFetch|Differential },
-{ NCR_825_DID, 0xff, "SYM53C825A", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide },
-{ SYM_860_DID, 0x0f, "SYM53C860", Burst16, 8, 24, Prefetch|Ultra },
-{ SYM_860_DID, 0xff, "SYM53C860LV", Burst16, 8, 24, Prefetch|Ultra },
-{ SYM_875_DID, 0x01, "SYM53C875r1", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra },
-{ SYM_875_DID, 0xff, "SYM53C875", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
-{ SYM_875J_DID, 0xff, "SYM53C875j", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
-{ SYM_885_DID, 0xff, "SYM53C885", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|ClockDouble },
-{ SYM_895_DID, 0xff, "SYM53C895", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
-{ SYM_896_DID, 0xff, "SYM53C896", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
-{ SYM_1010_DID, 0xff, "SYM53C1010", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
-{ SYM_1011_DID, 0xff, "SYM53C1010", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
-};
-
-
-static int
-xfunc(Controller *c, enum na_external x, unsigned long *v)
-{
- switch (x) {
- default:
- print("xfunc: can't find external %d\n", x);
- return 0;
- case X_scsi_id_buf:
- *v = offsetof(Dsa, scsi_id_buf[0]);
- break;
- case X_msg_out_buf:
- *v = offsetof(Dsa, msg_out_buf);
- break;
- case X_cmd_buf:
- *v = offsetof(Dsa, cmd_buf);
- break;
- case X_data_buf:
- *v = offsetof(Dsa, data_buf);
- break;
- case X_status_buf:
- *v = offsetof(Dsa, status_buf);
- break;
- case X_dsa_head:
- *v = DMASEG(&c->dsalist.head[0]);
- break;
- }
- return 1;
-}
-
-static int
-na_fixup(Controller *c, ulong pa_reg,
- struct na_patch *patch, int patches,
- int (*externval)(Controller*, int, ulong*))
-{
- int p;
- int v;
- ulong *script, pa_script;
- unsigned long lw, lv;
-
- script = c->script;
- pa_script = c->scriptpa;
- for (p = 0; p < patches; p++) {
- switch (patch[p].type) {
- case 1:
- /* script relative */
- script[patch[p].lwoff] += pa_script;
- break;
- case 2:
- /* register i/o relative */
- script[patch[p].lwoff] += pa_reg;
- break;
- case 3:
- /* data external */
- lw = script[patch[p].lwoff];
- v = (lw >> 8) & 0xff;
- if (!(*externval)(c, v, &lv))
- return 0;
- v = lv & 0xff;
- script[patch[p].lwoff] = (lw & 0xffff00ffL) | (v << 8);
- break;
- case 4:
- /* 32 bit external */
- lw = script[patch[p].lwoff];
- if (!(*externval)(c, lw, &lv))
- return 0;
- script[patch[p].lwoff] = lv;
- break;
- case 5:
- /* 24 bit external */
- lw = script[patch[p].lwoff];
- if (!(*externval)(c, lw & 0xffffff, &lv))
- return 0;
- script[patch[p].lwoff] = (lw & 0xff000000L) | (lv & 0xffffffL);
- break;
- }
- }
- return 1;
-}
-
-static SDev*
-sympnp(void)
-{
- int ba;
- Pcidev *p;
- Variant *v;
- void *scriptma;
- Controller *ctlr;
- SDev *sdev, *head, *tail;
- ulong regpa, *script, scriptpa;
-
- p = nil;
- head = tail = nil;
- while(p = pcimatch(p, NCR_VID, 0)){
- for(v = variant; v < &variant[nelem(variant)]; v++){
- if(p->did == v->did && p->rid <= v->maxrid)
- break;
- }
- if(v >= &variant[nelem(variant)])
- continue;
- print("sd53c8xx: %s rev. 0x%2.2x intr=%d command=%4.4uX\n",
- v->name, p->rid, p->intl, p->pcr);
-
- regpa = p->mem[1].bar;
- ba = 2;
- if(regpa & 0x04){
- if(p->mem[2].bar)
- continue;
- ba++;
- }
- regpa = upamalloc(regpa & ~0x0F, p->mem[1].size, 0);
- if(regpa == 0)
- continue;
-
- script = nil;
- scriptpa = 0;
- scriptma = nil;
- if((v->feature & LocalRAM) && sizeof(na_script) <= 4096){
- scriptpa = p->mem[ba].bar;
- if((scriptpa & 0x04) && p->mem[ba+1].bar){
- upafree(regpa, p->mem[1].size);
- continue;
- }
- scriptpa = upamalloc(scriptpa & ~0x0F,
- p->mem[ba].size, 0);
- if(scriptpa)
- script = KADDR(scriptpa);
- }
- if(scriptpa == 0){
- /*
- * Either the map failed, or this chip does not have
- * local RAM. It will need a copy of the microcode.
- */
- scriptma = malloc(sizeof(na_script));
- if(scriptma == nil){
- upafree(regpa, p->mem[1].size);
- continue;
- }
- scriptpa = DMASEG(scriptma);
- script = scriptma;
- }
-
- ctlr = malloc(sizeof(Controller));
- sdev = malloc(sizeof(SDev));
- if(ctlr == nil || sdev == nil){
-buggery:
- if(ctlr)
- free(ctlr);
- if(sdev)
- free(sdev);
- if(scriptma)
- free(scriptma);
- else
- upafree(scriptpa, p->mem[ba].size);
- upafree(regpa, p->mem[1].size);
- continue;
- }
-
- ctlr->n = KADDR(regpa);
- ctlr->v = v;
- ctlr->script = script;
- memmove(ctlr->script, na_script, sizeof(na_script));
- ctlr->scriptpa = scriptpa;
- if(!na_fixup(ctlr, regpa, na_patches, NA_PATCHES, xfunc)){
- print("script fixup failed\n");
- goto buggery;
- }
- swabl(ctlr->script, ctlr->script, sizeof(na_script));
-
- ctlr->dsalist.freechain = 0;
- lesetl(ctlr->dsalist.head, 0);
-
- ctlr->pcidev = p;
-
- sdev->ifc = &sd53c8xxifc;
- sdev->ctlr = ctlr;
- if(!(v->feature & Wide))
- sdev->nunit = 8;
- else
- sdev->nunit = MAXTARGET;
- ctlr->sdev = sdev;
-
- if(head != nil)
- tail->next = sdev;
- else
- head = sdev;
- tail = sdev;
- }
-
- return head;
-}
-
-static SDev*
-symid(SDev* sdev)
-{
- return scsiid(sdev, &sd53c8xxifc);
-}
-
-static int
-symenable(SDev* sdev)
-{
- Pcidev *pcidev;
- Controller *ctlr;
- //char name[NAMELEN];
-
- ctlr = sdev->ctlr;
- pcidev = ctlr->pcidev;
-
- pcisetbme(pcidev);
- //snprint(name, NAMELEN, "%s (%s)", sdev->name, sdev->ifc->name);
- intrenable(pcidev->intl, interrupt, ctlr, pcidev->tbdf, name);
-
- ilock(ctlr);
- synctabinit(ctlr);
- cribbios(ctlr);
- reset(ctlr);
- iunlock(ctlr);
-
- return 1;
-}
-
-static int
-symdisable(SDev* sdev)
-{
- Ncr *n;
- Controller *ctlr;
-
- ctlr = sdev->ctlr;
- n = ctlr->n;
-
- n->istat = Srst; /* software reset */
- microdelay(1);
- n->istat = 0;
-
- n->scntl1 |= (1 << 3); /* bus reset */
- delay(500);
- n->scntl1 &= ~(1 << 3);
-
- return 1;
-}
-
-SDifc sd53c8xxifc = {
- "53c8xx", /* name */
-
- sympnp, /* pnp */
- nil, /* legacy */
- symid, /* id */
- symenable, /* enable */
- symdisable, /* disable */
-
- scsiverify, /* verify */
- scsionline, /* online */
- symrio, /* rio */
- nil, /* rctl */
- nil, /* wctl */
-
- scsibio, /* bio */
-};
--- a/os/boot/pc/sd53c8xx.i
+++ /dev/null
@@ -1,769 +1,0 @@
-unsigned long na_script[] = {
- /* extern scsi_id_buf */
- /* extern msg_out_buf */
- /* extern cmd_buf */
- /* extern data_buf */
- /* extern status_buf */
- /* extern msgin_buf */
- /* extern dsa_0 */
- /* extern dsa_1 */
- /* extern dsa_head */
- /* SIR_MSG_IO_COMPLETE = 0 */
- /* error_not_cmd_complete = 1 */
- /* error_disconnected = 2 */
- /* error_reselected = 3 */
- /* error_unexpected_phase = 4 */
- /* error_weird_message = 5 */
- /* SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT = 6 */
- /* error_not_identify_after_reselect = 7 */
- /* error_too_much_data = 8 */
- /* error_too_little_data = 9 */
- /* SIR_MSG_REJECT = 10 */
- /* SIR_MSG_SDTR = 11 */
- /* SIR_EV_RESPONSE_OK = 12 */
- /* error_sigp_set = 13 */
- /* SIR_EV_PHASE_SWITCH_AFTER_ID = 14 */
- /* SIR_MSG_WDTR = 15 */
- /* SIR_MSG_IGNORE_WIDE_RESIDUE = 16 */
- /* SIR_NOTIFY_DISC = 100 */
- /* SIR_NOTIFY_RESELECT = 101 */
- /* SIR_NOTIFY_MSG_IN = 102 */
- /* SIR_NOTIFY_STATUS = 103 */
- /* SIR_NOTIFY_DUMP = 104 */
- /* SIR_NOTIFY_DUMP2 = 105 */
- /* SIR_NOTIFY_SIGP = 106 */
- /* SIR_NOTIFY_ISSUE = 107 */
- /* SIR_NOTIFY_WAIT_RESELECT = 108 */
- /* SIR_NOTIFY_ISSUE_CHECK = 109 */
- /* SIR_NOTIFY_DUMP_NEXT_CODE = 110 */
- /* SIR_NOTIFY_COMMAND = 111 */
- /* SIR_NOTIFY_DATA_IN = 112 */
- /* SIR_NOTIFY_DATA_OUT = 113 */
- /* SIR_NOTIFY_BLOCK_DATA_IN = 114 */
- /* SIR_NOTIFY_WSR = 115 */
- /* SIR_NOTIFY_LOAD_SYNC = 116 */
- /* SIR_NOTIFY_RESELECTED_ON_SELECT = 117 */
- /* STATE_FREE = 0 */
- /* STATE_ALLOCATED = 1 */
- /* STATE_ISSUE = 2 */
- /* STATE_DISCONNECTED = 3 */
- /* STATE_DONE = 4 */
- /* RESULT_OK = 0 */
- /* MSG_IDENTIFY = 0x80 */
- /* MSG_DISCONNECT = 0x04 */
- /* MSG_SAVE_DATA_POINTER = 0x02 */
- /* MSG_RESTORE_POINTERS = 0x03 */
- /* MSG_IGNORE_WIDE_RESIDUE = 0x23 */
- /* X_MSG = 0x01 */
- /* X_MSG_SDTR = 0x01 */
- /* X_MSG_WDTR = 0x03 */
- /* MSG_REJECT = 0x07 */
- /* BSIZE = 512 */
-/* 0000 */ 0x80880000L, /* jump wait_for_reselection */
-/* 0004 */ 0x00000514L,
-/* 0008 */ 0x88880000L, /* call load_sync */
-/* 000c */ 0x0000074cL,
-/* 0010 */ 0x60000200L, /* clear target */
-/* 0014 */ 0x00000000L,
-/* 0018 */ 0x47000000L, /* select atn from scsi_id_buf, reselected_on_select */
-/* 001c */ 0x000004ecL,
-/* 0020 */ 0x878b0000L, /* jump start1, when msg_in */
-/* 0024 */ 0x00000000L,
-/* 0028 */ 0x1e000000L, /* move from msg_out_buf, when msg_out */
-/* 002c */ 0x00000001L,
-/* 0030 */ 0x868b0000L, /* jump start1, when msg_out */
-/* 0034 */ 0x00fffff0L,
-/* 0038 */ 0x82830000L, /* jump to_decisions, when not cmd */
-/* 003c */ 0x000005f0L,
-/* 0040 */ 0x60000008L, /* clear atn */
-/* 0044 */ 0x00000000L,
-/* 0048 */ 0x1a000000L, /* move from cmd_buf, when cmd */
-/* 004c */ 0x00000002L,
-/* 0050 */ 0x81830000L, /* jump to_decisions, when not data_in */
-/* 0054 */ 0x000005d8L,
-/* 0058 */ 0xc0000004L, /* move memory 4, state, scratcha */
-/* 005c */ 0x00000678L,
-/* 0060 */ 0x00000034L,
-/* 0064 */ 0xc0000004L, /* move memory 4, dmaaddr, scratchb */
-/* 0068 */ 0x0000067cL,
-/* 006c */ 0x0000005cL,
-/* 0070 */ 0x72360000L, /* move scratcha2 to sfbr */
-/* 0074 */ 0x00000000L,
-/* 0078 */ 0x808c0000L, /* jump data_in_normal, if 0 */
-/* 007c */ 0x00000078L,
-/* 0080 */ 0x29000200L, /* move BSIZE, ptr dmaaddr, when data_in */
-/* 0084 */ 0x0000067cL,
-/* 0088 */ 0x7e5d0200L, /* move scratchb1 + BSIZE / 256 to scratchb1 */
-/* 008c */ 0x00000000L,
-/* 0090 */ 0x7f5e0000L, /* move scratchb2 + 0 to scratchb2 with carry */
-/* 0094 */ 0x00000000L,
-/* 0098 */ 0x7f5f0000L, /* move scratchb3 + 0 to scratchb3 with carry */
-/* 009c */ 0x00000000L,
-/* 00a0 */ 0x7e36ff00L, /* move scratcha2 + 255 to scratcha2 */
-/* 00a4 */ 0x00000000L,
-/* 00a8 */ 0xc0000004L, /* move memory 4, scratchb, dmaaddr */
-/* 00ac */ 0x0000005cL,
-/* 00b0 */ 0x0000067cL,
-/* 00b4 */ 0x818b0000L, /* jump data_in_block_loop, when data_in */
-/* 00b8 */ 0x00ffffb4L,
-/* 00bc */ 0xc0000004L, /* move memory 4, scratcha, state */
-/* 00c0 */ 0x00000034L,
-/* 00c4 */ 0x00000678L,
-/* 00c8 */ 0x88880000L, /* call save_state */
-/* 00cc */ 0x000005e0L,
-/* 00d0 */ 0x80880000L, /* jump to_decisions */
-/* 00d4 */ 0x00000558L,
-/* 00d8 */ 0xc0000004L, /* move memory 4, scratchb, dmaaddr */
-/* 00dc */ 0x0000005cL,
-/* 00e0 */ 0x0000067cL,
-/* 00e4 */ 0xc0000004L, /* move memory 4, scratcha, state */
-/* 00e8 */ 0x00000034L,
-/* 00ec */ 0x00000678L,
-/* 00f0 */ 0x80880000L, /* jump to_decisions */
-/* 00f4 */ 0x00000538L,
-/* 00f8 */ 0x72370000L, /* move scratcha3 to sfbr */
-/* 00fc */ 0x00000000L,
-/* 0100 */ 0x98040000L, /* int error_too_much_data, if not 0 */
-/* 0104 */ 0x00000008L,
-/* 0108 */ 0x19000000L, /* move from data_buf, when data_in */
-/* 010c */ 0x00000003L,
-/* 0110 */ 0x78370100L, /* move 1 to scratcha3 */
-/* 0114 */ 0x00000000L,
-/* 0118 */ 0xc0000004L, /* move memory 4, scratcha, state */
-/* 011c */ 0x00000034L,
-/* 0120 */ 0x00000678L,
-/* 0124 */ 0x88880000L, /* call save_state */
-/* 0128 */ 0x00000584L,
-/* 012c */ 0x80880000L, /* jump post_data_to_decisions */
-/* 0130 */ 0x0000052cL,
-/* 0134 */ 0xc0000004L, /* move memory 4, state, scratcha */
-/* 0138 */ 0x00000678L,
-/* 013c */ 0x00000034L,
-/* 0140 */ 0xc0000004L, /* move memory 4, dmaaddr, scratchb */
-/* 0144 */ 0x0000067cL,
-/* 0148 */ 0x0000005cL,
-/* 014c */ 0x72360000L, /* move scratcha2 to sfbr */
-/* 0150 */ 0x00000000L,
-/* 0154 */ 0x808c0000L, /* jump data_out_normal, if 0 */
-/* 0158 */ 0x0000005cL,
-/* 015c */ 0xc0000004L, /* move memory 4, dmaaddr, scratchb */
-/* 0160 */ 0x0000067cL,
-/* 0164 */ 0x0000005cL,
-/* 0168 */ 0x28000200L, /* move BSIZE, ptr dmaaddr, when data_out */
-/* 016c */ 0x0000067cL,
-/* 0170 */ 0x7e5d0200L, /* move scratchb1 + BSIZE / 256 to scratchb1 */
-/* 0174 */ 0x00000000L,
-/* 0178 */ 0x7f5e0000L, /* move scratchb2 + 0 to scratchb2 with carry */
-/* 017c */ 0x00000000L,
-/* 0180 */ 0x7f5f0000L, /* move scratchb3 + 0 to scratchb3 with carry */
-/* 0184 */ 0x00000000L,
-/* 0188 */ 0x7e36ff00L, /* move scratcha2 + 255 to scratcha2 */
-/* 018c */ 0x00000000L,
-/* 0190 */ 0xc0000004L, /* move memory 4, scratchb, dmaaddr */
-/* 0194 */ 0x0000005cL,
-/* 0198 */ 0x0000067cL,
-/* 019c */ 0x808b0000L, /* jump data_out_block_loop, when data_out */
-/* 01a0 */ 0x00ffffa8L,
-/* 01a4 */ 0xc0000004L, /* move memory 4, scratcha, state */
-/* 01a8 */ 0x00000034L,
-/* 01ac */ 0x00000678L,
-/* 01b0 */ 0x80880000L, /* jump to_decisions */
-/* 01b4 */ 0x00000478L,
-/* 01b8 */ 0x72370000L, /* move scratcha3 to sfbr */
-/* 01bc */ 0x00000000L,
-/* 01c0 */ 0x98040000L, /* int error_too_little_data, if not 0 */
-/* 01c4 */ 0x00000009L,
-/* 01c8 */ 0x18000000L, /* move from data_buf, when data_out */
-/* 01cc */ 0x00000003L,
-/* 01d0 */ 0x78370100L, /* move 1 to scratcha3 */
-/* 01d4 */ 0x00000000L,
-/* 01d8 */ 0xc0000004L, /* move memory 4, scratcha, state */
-/* 01dc */ 0x00000034L,
-/* 01e0 */ 0x00000678L,
-/* 01e4 */ 0x88880000L, /* call save_state */
-/* 01e8 */ 0x000004c4L,
-/* 01ec */ 0x80880000L, /* jump post_data_to_decisions */
-/* 01f0 */ 0x0000046cL,
-/* 01f4 */ 0x1b000000L, /* move from status_buf, when status */
-/* 01f8 */ 0x00000004L,
-/* 01fc */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
-/* 0200 */ 0x00000004L,
-/* 0204 */ 0x0f000001L, /* move 1, scratcha, when msg_in */
-/* 0208 */ 0x00000034L,
-/* 020c */ 0x808c0007L, /* jump rejected, if MSG_REJECT */
-/* 0210 */ 0x00000088L,
-/* 0214 */ 0x808c0004L, /* jump disconnected, if MSG_DISCONNECT */
-/* 0218 */ 0x00000298L,
-/* 021c */ 0x808c0002L, /* jump msg_in_skip, if MSG_SAVE_DATA_POINTER */
-/* 0220 */ 0x00000090L,
-/* 0224 */ 0x808c0003L, /* jump msg_in_skip, if MSG_RESTORE_POINTERS */
-/* 0228 */ 0x00000088L,
-/* 022c */ 0x808c0023L, /* jump ignore_wide, if MSG_IGNORE_WIDE_RESIDUE */
-/* 0230 */ 0x000001f0L,
-/* 0234 */ 0x808c0001L, /* jump extended, if X_MSG */
-/* 0238 */ 0x00000088L,
-/* 023c */ 0x98040000L, /* int error_not_cmd_complete, if not 0 */
-/* 0240 */ 0x00000001L,
-/* 0244 */ 0x7c027e00L, /* move scntl2&0x7e to scntl2 */
-/* 0248 */ 0x00000000L,
-/* 024c */ 0x60000040L, /* clear ack */
-/* 0250 */ 0x00000000L,
-/* 0254 */ 0x48000000L, /* wait disconnect */
-/* 0258 */ 0x00000000L,
-/* 025c */ 0xc0000004L, /* move memory 4, state, scratcha */
-/* 0260 */ 0x00000678L,
-/* 0264 */ 0x00000034L,
-/* 0268 */ 0x78340400L, /* move STATE_DONE to scratcha0 */
-/* 026c */ 0x00000000L,
-/* 0270 */ 0x78350000L, /* move RESULT_OK to scratcha1 */
-/* 0274 */ 0x00000000L,
-/* 0278 */ 0xc0000004L, /* move memory 4, scratcha, state */
-/* 027c */ 0x00000034L,
-/* 0280 */ 0x00000678L,
-/* 0284 */ 0x88880000L, /* call save_state */
-/* 0288 */ 0x00000424L,
-/* 028c */ 0x98180000L, /* intfly 0 */
-/* 0290 */ 0x00000000L,
-/* 0294 */ 0x80880000L, /* jump issue_check */
-/* 0298 */ 0x0000043cL,
-/* 029c */ 0x98080000L, /* int SIR_MSG_REJECT */
-/* 02a0 */ 0x0000000aL,
-/* 02a4 */ 0x60000040L, /* clear ack */
-/* 02a8 */ 0x00000000L,
-/* 02ac */ 0x80880000L, /* jump to_decisions */
-/* 02b0 */ 0x0000037cL,
-/* 02b4 */ 0x60000040L, /* clear ack */
-/* 02b8 */ 0x00000000L,
-/* 02bc */ 0x80880000L, /* jump to_decisions */
-/* 02c0 */ 0x0000036cL,
-/* 02c4 */ 0x60000040L, /* clear ack */
-/* 02c8 */ 0x00000000L,
-/* 02cc */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
-/* 02d0 */ 0x00000004L,
-/* 02d4 */ 0x0f000001L, /* move 1, scratcha1, when msg_in */
-/* 02d8 */ 0x00000035L,
-/* 02dc */ 0x808c0003L, /* jump ext_3, if 3 */
-/* 02e0 */ 0x00000030L,
-/* 02e4 */ 0x808c0002L, /* jump ext_2, if 2 */
-/* 02e8 */ 0x00000098L,
-/* 02ec */ 0x98040001L, /* int error_weird_message, if not 1 */
-/* 02f0 */ 0x00000005L,
-/* 02f4 */ 0x60000040L, /* clear ack */
-/* 02f8 */ 0x00000000L,
-/* 02fc */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
-/* 0300 */ 0x00000004L,
-/* 0304 */ 0x0f000001L, /* move 1, scratcha1, when msg_in */
-/* 0308 */ 0x00000035L,
-/* 030c */ 0x80880000L, /* jump ext_done */
-/* 0310 */ 0x000000c8L,
-/* 0314 */ 0x60000040L, /* ext_3: clear ack */
-/* 0318 */ 0x00000000L,
-/* 031c */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
-/* 0320 */ 0x00000004L,
-/* 0324 */ 0x0f000001L, /* move 1, scratcha1, when msg_in */
-/* 0328 */ 0x00000035L,
-/* 032c */ 0x60000040L, /* clear ack */
-/* 0330 */ 0x00000000L,
-/* 0334 */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
-/* 0338 */ 0x00000004L,
-/* 033c */ 0x0f000001L, /* move 1, scratcha2, when msg_in */
-/* 0340 */ 0x00000036L,
-/* 0344 */ 0x60000040L, /* clear ack */
-/* 0348 */ 0x00000000L,
-/* 034c */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
-/* 0350 */ 0x00000004L,
-/* 0354 */ 0x0f000001L, /* move 1, scratcha3, when msg_in */
-/* 0358 */ 0x00000037L,
-/* 035c */ 0x72350000L, /* move scratcha1 to sfbr */
-/* 0360 */ 0x00000000L,
-/* 0364 */ 0x80840001L, /* jump ext_done, if not X_MSG_SDTR */
-/* 0368 */ 0x00000070L,
-/* 036c */ 0x98080000L, /* sdtr: int SIR_MSG_SDTR */
-/* 0370 */ 0x0000000bL,
-/* 0374 */ 0x60000040L, /* clear ack */
-/* 0378 */ 0x00000000L,
-/* 037c */ 0x80880000L, /* jump to_decisions */
-/* 0380 */ 0x000002acL,
-/* 0384 */ 0x60000040L, /* ext_2: clear ack */
-/* 0388 */ 0x00000000L,
-/* 038c */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
-/* 0390 */ 0x00000004L,
-/* 0394 */ 0x0f000001L, /* move 1, scratcha1, when msg_in */
-/* 0398 */ 0x00000035L,
-/* 039c */ 0x60000040L, /* clear ack */
-/* 03a0 */ 0x00000000L,
-/* 03a4 */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
-/* 03a8 */ 0x00000004L,
-/* 03ac */ 0x0f000001L, /* move 1, scratcha2, when msg_in */
-/* 03b0 */ 0x00000036L,
-/* 03b4 */ 0x72350000L, /* move scratcha1 to sfbr */
-/* 03b8 */ 0x00000000L,
-/* 03bc */ 0x80840003L, /* jump ext_done, if not X_MSG_WDTR */
-/* 03c0 */ 0x00000018L,
-/* 03c4 */ 0x98080000L, /* wdtr: int SIR_MSG_WDTR */
-/* 03c8 */ 0x0000000fL,
-/* 03cc */ 0x60000040L, /* clear ack */
-/* 03d0 */ 0x00000000L,
-/* 03d4 */ 0x80880000L, /* jump to_decisions */
-/* 03d8 */ 0x00000254L,
-/* 03dc */ 0x58000008L, /* set atn */
-/* 03e0 */ 0x00000000L,
-/* 03e4 */ 0x60000040L, /* clear ack */
-/* 03e8 */ 0x00000000L,
-/* 03ec */ 0x78340700L, /* move MSG_REJECT to scratcha */
-/* 03f0 */ 0x00000000L,
-/* 03f4 */ 0x9e030000L, /* int error_unexpected_phase, when not msg_out */
-/* 03f8 */ 0x00000004L,
-/* 03fc */ 0x60000008L, /* clear atn */
-/* 0400 */ 0x00000000L,
-/* 0404 */ 0x0e000001L, /* move 1, scratcha, when msg_out */
-/* 0408 */ 0x00000034L,
-/* 040c */ 0x60000040L, /* clear ack */
-/* 0410 */ 0x00000000L,
-/* 0414 */ 0x868b0000L, /* jump reject, when msg_out */
-/* 0418 */ 0x00ffffc0L,
-/* 041c */ 0x80880000L, /* jump to_decisions */
-/* 0420 */ 0x0000020cL,
-/* 0424 */ 0x60000040L, /* clear ack */
-/* 0428 */ 0x00000000L,
-/* 042c */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
-/* 0430 */ 0x00000004L,
-/* 0434 */ 0x0f000001L, /* move 1, scratcha1, when msg_in */
-/* 0438 */ 0x00000035L,
-/* 043c */ 0x98080000L, /* int SIR_MSG_IGNORE_WIDE_RESIDUE */
-/* 0440 */ 0x00000010L,
-/* 0444 */ 0x60000040L, /* clear ack */
-/* 0448 */ 0x00000000L,
-/* 044c */ 0x80880000L, /* jump to_decisions */
-/* 0450 */ 0x000001dcL,
-/* 0454 */ 0x58000008L, /* set atn */
-/* 0458 */ 0x00000000L,
-/* 045c */ 0x60000040L, /* clear ack */
-/* 0460 */ 0x00000000L,
-/* 0464 */ 0x9e030000L, /* int error_unexpected_phase, when not msg_out */
-/* 0468 */ 0x00000004L,
-/* 046c */ 0x1e000000L, /* move from msg_out_buf, when msg_out */
-/* 0470 */ 0x00000001L,
-/* 0474 */ 0x868b0000L, /* jump response_repeat, when msg_out */
-/* 0478 */ 0x00fffff0L,
-/* 047c */ 0x878b0000L, /* jump response_msg_in, when msg_in */
-/* 0480 */ 0x00000010L,
-/* 0484 */ 0x98080000L, /* int SIR_EV_RESPONSE_OK */
-/* 0488 */ 0x0000000cL,
-/* 048c */ 0x80880000L, /* jump to_decisions */
-/* 0490 */ 0x0000019cL,
-/* 0494 */ 0x0f000001L, /* move 1, scratcha, when msg_in */
-/* 0498 */ 0x00000034L,
-/* 049c */ 0x808c0007L, /* jump rejected, if MSG_REJECT */
-/* 04a0 */ 0x00fffdf8L,
-/* 04a4 */ 0x98080000L, /* int SIR_EV_RESPONSE_OK */
-/* 04a8 */ 0x0000000cL,
-/* 04ac */ 0x80880000L, /* jump msg_in_not_reject */
-/* 04b0 */ 0x00fffd60L,
-/* 04b4 */ 0x7c027e00L, /* move scntl2&0x7e to scntl2 */
-/* 04b8 */ 0x00000000L,
-/* 04bc */ 0x60000040L, /* clear ack */
-/* 04c0 */ 0x00000000L,
-/* 04c4 */ 0x48000000L, /* wait disconnect */
-/* 04c8 */ 0x00000000L,
-/* 04cc */ 0xc0000004L, /* move memory 4, state, scratcha */
-/* 04d0 */ 0x00000678L,
-/* 04d4 */ 0x00000034L,
-/* 04d8 */ 0x78340300L, /* move STATE_DISCONNECTED to scratcha0 */
-/* 04dc */ 0x00000000L,
-/* 04e0 */ 0xc0000004L, /* move memory 4, scratcha, state */
-/* 04e4 */ 0x00000034L,
-/* 04e8 */ 0x00000678L,
-/* 04ec */ 0x88880000L, /* call save_state */
-/* 04f0 */ 0x000001bcL,
-/* 04f4 */ 0x74020100L, /* move scntl2&0x01 to sfbr */
-/* 04f8 */ 0x00000000L,
-/* 04fc */ 0x98040000L, /* int SIR_NOTIFY_WSR, if not 0 */
-/* 0500 */ 0x00000073L,
-/* 0504 */ 0x80880000L, /* jump issue_check */
-/* 0508 */ 0x000001ccL,
-/* 050c */ 0x98080000L, /* int SIR_NOTIFY_RESELECTED_ON_SELECT */
-/* 0510 */ 0x00000075L,
-/* 0514 */ 0x80880000L, /* jump reselected */
-/* 0518 */ 0x00000008L,
-/* 051c */ 0x54000000L, /* wait reselect sigp_set */
-/* 0520 */ 0x000001acL,
-/* 0524 */ 0x60000200L, /* clear target */
-/* 0528 */ 0x00000000L,
-/* 052c */ 0x9f030000L, /* int SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT, when not msg_in */
-/* 0530 */ 0x00000006L,
-/* 0534 */ 0x0f000001L, /* move 1, scratchb, when msg_in */
-/* 0538 */ 0x0000005cL,
-/* 053c */ 0x98041f80L, /* int error_not_identify_after_reselect, if not MSG_IDENTIFY and mask 0x1f */
-/* 0540 */ 0x00000007L,
-/* 0544 */ 0xc0000004L, /* move memory 4, dsa_head, dsa */
-/* 0548 */ 0x00000008L,
-/* 054c */ 0x00000010L,
-/* 0550 */ 0x72100000L, /* move dsa0 to sfbr */
-/* 0554 */ 0x00000000L,
-/* 0558 */ 0x80840000L, /* jump find_dsa_1, if not 0 */
-/* 055c */ 0x00000030L,
-/* 0560 */ 0x72110000L, /* move dsa1 to sfbr */
-/* 0564 */ 0x00000000L,
-/* 0568 */ 0x80840000L, /* jump find_dsa_1, if not 0 */
-/* 056c */ 0x00000020L,
-/* 0570 */ 0x72120000L, /* move dsa2 to sfbr */
-/* 0574 */ 0x00000000L,
-/* 0578 */ 0x80840000L, /* jump find_dsa_1, if not 0 */
-/* 057c */ 0x00000010L,
-/* 0580 */ 0x72130000L, /* move dsa3 to sfbr */
-/* 0584 */ 0x00000000L,
-/* 0588 */ 0x980c0000L, /* int error_reselected, if 0 */
-/* 058c */ 0x00000003L,
-/* 0590 */ 0x88880000L, /* call load_state */
-/* 0594 */ 0x000000f8L,
-/* 0598 */ 0xc0000004L, /* move memory 4, state, scratcha */
-/* 059c */ 0x00000678L,
-/* 05a0 */ 0x00000034L,
-/* 05a4 */ 0x72340000L, /* move scratcha0 to sfbr */
-/* 05a8 */ 0x00000000L,
-/* 05ac */ 0x80840003L, /* jump find_dsa_next, if not STATE_DISCONNECTED */
-/* 05b0 */ 0x00000038L,
-/* 05b4 */ 0x740a0f00L, /* move ssid & 15 to sfbr */
-/* 05b8 */ 0x00000000L,
-/* 05bc */ 0xc0000001L, /* move memory 1, targ, find_dsa_smc1 */
-/* 05c0 */ 0x00000680L,
-/* 05c4 */ 0x000005c8L,
-/* 05c8 */ 0x808400ffL, /* jump find_dsa_next, if not 255 */
-/* 05cc */ 0x0000001cL,
-/* 05d0 */ 0xc0000001L, /* move memory 1, lun, find_dsa_smc2 */
-/* 05d4 */ 0x00000684L,
-/* 05d8 */ 0x000005e4L,
-/* 05dc */ 0x725c0000L, /* move scratchb0 to sfbr */
-/* 05e0 */ 0x00000000L,
-/* 05e4 */ 0x808cf8ffL, /* jump reload_sync, if 255 and mask ~7 */
-/* 05e8 */ 0x00000034L,
-/* 05ec */ 0xc0000004L, /* move memory 4, next, dsa */
-/* 05f0 */ 0x0000068cL,
-/* 05f4 */ 0x00000010L,
-/* 05f8 */ 0x80880000L, /* jump find_dsa_loop */
-/* 05fc */ 0x00ffff50L,
-/* 0600 */ 0x60000008L, /* clear atn */
-/* 0604 */ 0x00000000L,
-/* 0608 */ 0x878b0000L, /* jump msg_in_phase, when msg_in */
-/* 060c */ 0x00fffbf4L,
-/* 0610 */ 0x98080000L, /* int SIR_MSG_REJECT */
-/* 0614 */ 0x0000000aL,
-/* 0618 */ 0x80880000L, /* jump to_decisions */
-/* 061c */ 0x00000010L,
-/* 0620 */ 0x88880000L, /* call load_sync */
-/* 0624 */ 0x00000134L,
-/* 0628 */ 0x60000040L, /* clear ack */
-/* 062c */ 0x00000000L,
-/* 0630 */ 0x818b0000L, /* jump data_in_phase, when data_in */
-/* 0634 */ 0x00fffa20L,
-/* 0638 */ 0x828a0000L, /* jump cmd_phase, if cmd */
-/* 063c */ 0x00fffa00L,
-/* 0640 */ 0x808a0000L, /* jump data_out_phase, if data_out */
-/* 0644 */ 0x00fffaecL,
-/* 0648 */ 0x838a0000L, /* jump status_phase, if status */
-/* 064c */ 0x00fffba4L,
-/* 0650 */ 0x878a0000L, /* jump msg_in_phase, if msg_in */
-/* 0654 */ 0x00fffbacL,
-/* 0658 */ 0x98080000L, /* int error_unexpected_phase */
-/* 065c */ 0x00000004L,
-/* 0660 */ 0x838b0000L, /* jump status_phase, when status */
-/* 0664 */ 0x00fffb8cL,
-/* 0668 */ 0x878a0000L, /* jump msg_in_phase, if msg_in */
-/* 066c */ 0x00fffb94L,
-/* 0670 */ 0x98080000L, /* int error_unexpected_phase */
-/* 0674 */ 0x00000004L,
-/* 0678 */ 0x00000000L, /* state: defw 0 */
-/* 067c */ 0x00000000L, /* dmaaddr: defw 0 */
-/* 0680 */ 0x00000000L, /* targ: defw 0 */
-/* 0684 */ 0x00000000L, /* lun: defw 0 */
-/* 0688 */ 0x00000000L, /* sync: defw 0 */
-/* 068c */ 0x00000000L, /* next: defw 0 */
- /* dsa_load_len = dsa_load_end - dsa_copy */
- /* dsa_save_len = dsa_save_end - dsa_copy */
-/* 0690 */ 0xc0000004L, /* move memory 4, dsa, load_state_smc0 + 4 */
-/* 0694 */ 0x00000010L,
-/* 0698 */ 0x000006a0L,
-/* 069c */ 0xc0000018L, /* move memory dsa_load_len, 0, dsa_copy */
-/* 06a0 */ 0x00000000L,
-/* 06a4 */ 0x00000678L,
-/* 06a8 */ 0x90080000L, /* return */
-/* 06ac */ 0x00000000L,
-/* 06b0 */ 0xc0000004L, /* move memory 4, dsa, save_state_smc0 + 8 */
-/* 06b4 */ 0x00000010L,
-/* 06b8 */ 0x000006c4L,
-/* 06bc */ 0xc0000008L, /* move memory dsa_save_len, dsa_copy, 0 */
-/* 06c0 */ 0x00000678L,
-/* 06c4 */ 0x00000000L,
-/* 06c8 */ 0x90080000L, /* return */
-/* 06cc */ 0x00000000L,
-/* 06d0 */ 0x721a0000L, /* move ctest2 to sfbr */
-/* 06d4 */ 0x00000000L,
-/* 06d8 */ 0xc0000004L, /* move memory 4, dsa_head, dsa */
-/* 06dc */ 0x00000008L,
-/* 06e0 */ 0x00000010L,
-/* 06e4 */ 0x72100000L, /* move dsa0 to sfbr */
-/* 06e8 */ 0x00000000L,
-/* 06ec */ 0x80840000L, /* jump issue_check_1, if not 0 */
-/* 06f0 */ 0x00000030L,
-/* 06f4 */ 0x72110000L, /* move dsa1 to sfbr */
-/* 06f8 */ 0x00000000L,
-/* 06fc */ 0x80840000L, /* jump issue_check_1, if not 0 */
-/* 0700 */ 0x00000020L,
-/* 0704 */ 0x72120000L, /* move dsa2 to sfbr */
-/* 0708 */ 0x00000000L,
-/* 070c */ 0x80840000L, /* jump issue_check_1, if not 0 */
-/* 0710 */ 0x00000010L,
-/* 0714 */ 0x72130000L, /* move dsa3 to sfbr */
-/* 0718 */ 0x00000000L,
-/* 071c */ 0x808c0000L, /* jump wait_for_reselection, if 0 */
-/* 0720 */ 0x00fffdf8L,
-/* 0724 */ 0x88880000L, /* call load_state */
-/* 0728 */ 0x00ffff64L,
-/* 072c */ 0xc0000004L, /* move memory 4, state, scratcha */
-/* 0730 */ 0x00000678L,
-/* 0734 */ 0x00000034L,
-/* 0738 */ 0x72340000L, /* move scratcha0 to sfbr */
-/* 073c */ 0x00000000L,
-/* 0740 */ 0x808c0002L, /* jump start, if STATE_ISSUE */
-/* 0744 */ 0x00fff8c0L,
-/* 0748 */ 0xc0000004L, /* move memory 4, next, dsa */
-/* 074c */ 0x0000068cL,
-/* 0750 */ 0x00000010L,
-/* 0754 */ 0x80880000L, /* jump issue_check_loop */
-/* 0758 */ 0x00ffff88L,
-/* 075c */ 0xc0000004L, /* move memory 4, sync, scratcha */
-/* 0760 */ 0x00000688L,
-/* 0764 */ 0x00000034L,
-/* 0768 */ 0x72340000L, /* move scratcha0 to sfbr */
-/* 076c */ 0x00000000L,
-/* 0770 */ 0x6a030000L, /* move sfbr to scntl3 */
-/* 0774 */ 0x00000000L,
-/* 0778 */ 0x72350000L, /* move scratcha1 to sfbr */
-/* 077c */ 0x00000000L,
-/* 0780 */ 0x6a050000L, /* move sfbr to sxfer */
-/* 0784 */ 0x00000000L,
-/* 0788 */ 0x90080000L, /* return */
-/* 078c */ 0x00000000L,
-};
-
-#define NA_SCRIPT_SIZE 484
-
-struct na_patch na_patches[] = {
- { 0x0006, 5 }, /* 00000018 */
- { 0x000b, 4 }, /* 0000002c */
- { 0x0013, 4 }, /* 0000004c */
- { 0x0017, 1 }, /* 0000005c */
- { 0x0018, 2 }, /* 00000060 */
- { 0x001a, 1 }, /* 00000068 */
- { 0x001b, 2 }, /* 0000006c */
- { 0x0021, 1 }, /* 00000084 */
- { 0x002b, 2 }, /* 000000ac */
- { 0x002c, 1 }, /* 000000b0 */
- { 0x0030, 2 }, /* 000000c0 */
- { 0x0031, 1 }, /* 000000c4 */
- { 0x0037, 2 }, /* 000000dc */
- { 0x0038, 1 }, /* 000000e0 */
- { 0x003a, 2 }, /* 000000e8 */
- { 0x003b, 1 }, /* 000000ec */
- { 0x0043, 4 }, /* 0000010c */
- { 0x0047, 2 }, /* 0000011c */
- { 0x0048, 1 }, /* 00000120 */
- { 0x004e, 1 }, /* 00000138 */
- { 0x004f, 2 }, /* 0000013c */
- { 0x0051, 1 }, /* 00000144 */
- { 0x0052, 2 }, /* 00000148 */
- { 0x0058, 1 }, /* 00000160 */
- { 0x0059, 2 }, /* 00000164 */
- { 0x005b, 1 }, /* 0000016c */
- { 0x0065, 2 }, /* 00000194 */
- { 0x0066, 1 }, /* 00000198 */
- { 0x006a, 2 }, /* 000001a8 */
- { 0x006b, 1 }, /* 000001ac */
- { 0x0073, 4 }, /* 000001cc */
- { 0x0077, 2 }, /* 000001dc */
- { 0x0078, 1 }, /* 000001e0 */
- { 0x007e, 4 }, /* 000001f8 */
- { 0x0082, 2 }, /* 00000208 */
- { 0x0098, 1 }, /* 00000260 */
- { 0x0099, 2 }, /* 00000264 */
- { 0x009f, 2 }, /* 0000027c */
- { 0x00a0, 1 }, /* 00000280 */
- { 0x00b6, 2 }, /* 000002d8 */
- { 0x00c2, 2 }, /* 00000308 */
- { 0x00ca, 2 }, /* 00000328 */
- { 0x00d0, 2 }, /* 00000340 */
- { 0x00d6, 2 }, /* 00000358 */
- { 0x00e6, 2 }, /* 00000398 */
- { 0x00ec, 2 }, /* 000003b0 */
- { 0x0102, 2 }, /* 00000408 */
- { 0x010e, 2 }, /* 00000438 */
- { 0x011c, 4 }, /* 00000470 */
- { 0x0126, 2 }, /* 00000498 */
- { 0x0134, 1 }, /* 000004d0 */
- { 0x0135, 2 }, /* 000004d4 */
- { 0x0139, 2 }, /* 000004e4 */
- { 0x013a, 1 }, /* 000004e8 */
- { 0x014e, 2 }, /* 00000538 */
- { 0x0152, 4 }, /* 00000548 */
- { 0x0153, 2 }, /* 0000054c */
- { 0x0167, 1 }, /* 0000059c */
- { 0x0168, 2 }, /* 000005a0 */
- { 0x0170, 1 }, /* 000005c0 */
- { 0x0171, 1 }, /* 000005c4 */
- { 0x0175, 1 }, /* 000005d4 */
- { 0x0176, 1 }, /* 000005d8 */
- { 0x017c, 1 }, /* 000005f0 */
- { 0x017d, 2 }, /* 000005f4 */
- { 0x01a5, 2 }, /* 00000694 */
- { 0x01a6, 1 }, /* 00000698 */
- { 0x01a9, 1 }, /* 000006a4 */
- { 0x01ad, 2 }, /* 000006b4 */
- { 0x01ae, 1 }, /* 000006b8 */
- { 0x01b0, 1 }, /* 000006c0 */
- { 0x01b7, 4 }, /* 000006dc */
- { 0x01b8, 2 }, /* 000006e0 */
- { 0x01cc, 1 }, /* 00000730 */
- { 0x01cd, 2 }, /* 00000734 */
- { 0x01d3, 1 }, /* 0000074c */
- { 0x01d4, 2 }, /* 00000750 */
- { 0x01d8, 1 }, /* 00000760 */
- { 0x01d9, 2 }, /* 00000764 */
-};
-#define NA_PATCHES 79
-
-enum na_external {
- X_scsi_id_buf,
- X_msg_out_buf,
- X_cmd_buf,
- X_data_buf,
- X_status_buf,
- X_msgin_buf,
- X_dsa_0,
- X_dsa_1,
- X_dsa_head,
-};
-
-enum {
- E_issue_check_next = 1864,
- E_issue_check_1 = 1828,
- E_issue_check_loop = 1764,
- E_save_state_smc0 = 1724,
- E_load_state_smc0 = 1692,
- E_dsa_load_end = 1680,
- E_sync = 1672,
- E_dsa_save_end = 1664,
- E_dsa_copy = 1656,
- E_id_out_mismatch_recover = 1536,
- E_next = 1676,
- E_reload_sync = 1568,
- E_find_dsa_smc2 = 1508,
- E_lun = 1668,
- E_find_dsa_smc1 = 1480,
- E_targ = 1664,
- E_find_dsa_next = 1516,
- E_load_state = 1680,
- E_find_dsa_1 = 1424,
- E_find_dsa_loop = 1360,
- E_find_dsa = 1348,
- E_sigp_set = 1744,
- E_reselected = 1316,
- E_wsr_check = 1268,
- E_response_msg_in = 1172,
- E_response_repeat = 1132,
- E_response = 1108,
- E_reject = 988,
- E_wdtr = 964,
- E_sdtr = 876,
- E_ext_done = 988,
- E_ext_1 = 756,
- E_ext_2 = 900,
- E_ext_3 = 788,
- E_issue_check = 1752,
- E_extended = 708,
- E_ignore_wide = 1060,
- E_msg_in_skip = 692,
- E_disconnected = 1204,
- E_msg_in_not_reject = 532,
- E_rejected = 668,
- E_msg_in_phase = 516,
- E_status_phase = 500,
- E_data_out_mismatch = 464,
- E_data_out_block_mismatch = 368,
- E_data_out_normal = 440,
- E_data_out_block_loop = 332,
- E_data_out_phase = 308,
- E_post_data_to_decisions = 1632,
- E_data_in_mismatch = 272,
- E_data_block_mismatch_recover = 216,
- E_save_state = 1712,
- E_data_in_block_mismatch = 136,
- E_data_in_normal = 248,
- E_data_in_block_loop = 112,
- E_dmaaddr = 1660,
- E_state = 1656,
- E_data_in_phase = 88,
- E_cmd_out_mismatch = 80,
- E_cmd_phase = 64,
- E_to_decisions = 1584,
- E_id_out_mismatch = 48,
- E_start1 = 40,
- E_reselected_on_select = 1292,
- E_load_sync = 1884,
- E_start = 8,
- E_wait_for_reselection = 1308,
- E_idle = 0,
-};
-#define A_dsa_save_len 8
-#define A_dsa_load_len 24
-#define A_BSIZE 512
-#define A_MSG_REJECT 7
-#define A_X_MSG_WDTR 3
-#define A_X_MSG_SDTR 1
-#define A_X_MSG 1
-#define A_MSG_IGNORE_WIDE_RESIDUE 35
-#define A_MSG_RESTORE_POINTERS 3
-#define A_MSG_SAVE_DATA_POINTER 2
-#define A_MSG_DISCONNECT 4
-#define A_MSG_IDENTIFY 128
-#define A_RESULT_OK 0
-#define A_STATE_DONE 4
-#define A_STATE_DISCONNECTED 3
-#define A_STATE_ISSUE 2
-#define A_STATE_ALLOCATED 1
-#define A_STATE_FREE 0
-#define A_SIR_NOTIFY_RESELECTED_ON_SELECT 117
-#define A_SIR_NOTIFY_LOAD_SYNC 116
-#define A_SIR_NOTIFY_WSR 115
-#define A_SIR_NOTIFY_BLOCK_DATA_IN 114
-#define A_SIR_NOTIFY_DATA_OUT 113
-#define A_SIR_NOTIFY_DATA_IN 112
-#define A_SIR_NOTIFY_COMMAND 111
-#define A_SIR_NOTIFY_DUMP_NEXT_CODE 110
-#define A_SIR_NOTIFY_ISSUE_CHECK 109
-#define A_SIR_NOTIFY_WAIT_RESELECT 108
-#define A_SIR_NOTIFY_ISSUE 107
-#define A_SIR_NOTIFY_SIGP 106
-#define A_SIR_NOTIFY_DUMP2 105
-#define A_SIR_NOTIFY_DUMP 104
-#define A_SIR_NOTIFY_STATUS 103
-#define A_SIR_NOTIFY_MSG_IN 102
-#define A_SIR_NOTIFY_RESELECT 101
-#define A_SIR_NOTIFY_DISC 100
-#define A_SIR_MSG_IGNORE_WIDE_RESIDUE 16
-#define A_SIR_MSG_WDTR 15
-#define A_SIR_EV_PHASE_SWITCH_AFTER_ID 14
-#define A_error_sigp_set 13
-#define A_SIR_EV_RESPONSE_OK 12
-#define A_SIR_MSG_SDTR 11
-#define A_SIR_MSG_REJECT 10
-#define A_error_too_little_data 9
-#define A_error_too_much_data 8
-#define A_error_not_identify_after_reselect 7
-#define A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT 6
-#define A_error_weird_message 5
-#define A_error_unexpected_phase 4
-#define A_error_reselected 3
-#define A_error_disconnected 2
-#define A_error_not_cmd_complete 1
-#define A_SIR_MSG_IO_COMPLETE 0
--- a/os/boot/pc/sdaoe.c
+++ /dev/null
@@ -1,733 +1,0 @@
-/*
- * aoe sd bootstrap driver, copyright © 2007 coraid
- */
-
-#include "u.h"
-#include "mem.h"
-#include "lib.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "sd.h"
-#include "aoe.h"
-
-
-enum {
- Nctlr = 4,
-};
-
-enum {
- /* sync with ahci.h */
- Dllba = 1<<0,
- Dsmart = 1<<1,
- Dpower = 1<<2,
- Dnop = 1<<3,
- Datapi = 1<<4,
- Datapi16= 1<<5,
-};
-
-enum {
- Tfree = -1,
- Tmgmt,
-};
-
-typedef struct Ctlr Ctlr;
-struct Ctlr{
- Ctlr *next;
- SDunit *unit;
-
- int ctlrno;
- int major;
- int minor;
- uchar ea[Eaddrlen];
- ushort lasttag;
-
- ulong vers;
- uchar mediachange;
- uchar flag;
- uchar smart;
- uchar smartrs;
- uchar feat;
-
- uvlong sectors;
- char serial[20+1];
- char firmware[8+1];
- char model[40+1];
- char ident[0x100];
-};
-
-static Ctlr *head;
-static Ctlr *tail;
-
-static int aoeether[10];
-
-SDifc sdaoeifc;
-
-static void
-hnputs(uchar *p, ushort i)
-{
- p[0] = i >> 8;
- p[1] = i;
-}
-
-static void
-hnputl(uchar *p, ulong i)
-{
- p[0] = i >> 24;
- p[1] = i >> 16;
- p[2] = i >> 8;
- p[3] = i;
-}
-
-static ushort
-nhgets(uchar *p)
-{
- return *p<<8 | p[1];
-}
-
-static ulong
-nhgetl(uchar *p)
-{
- return p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
-}
-
-static int
-newtag(Ctlr *d)
-{
- int t;
-
- for(;;){
- t = ++d->lasttag << 16;
- t |= m->ticks & 0xffff;
- switch(t) {
- case Tfree:
- case Tmgmt:
- break;
- default:
- return t;
- }
- }
-}
-
-static int
-hset(Ctlr *d, Aoehdr *h, int cmd)
-{
- int tag;
-
- memmove(h->dst, d->ea, Eaddrlen);
- hnputs(h->type, Aoetype);
- h->verflag = Aoever << 4;
- hnputs(h->major, d->major);
- h->minor = d->minor;
- h->cmd = cmd;
- hnputl(h->tag, tag = newtag(d));
- return tag;
-}
-
-static void
-idmove(char *p, ushort *a, int n)
-{
- int i;
- char *op, *e;
-
- op = p;
- for(i = 0; i < n / 2; i++){
- *p++ = a[i] >> 8;
- *p++ = a[i];
- }
- *p = 0;
- while(p > op && *--p == ' ')
- *p = 0;
- e = p;
- p = op;
- while(*p == ' ')
- p++;
- memmove(op, p, n - (e - p));
-}
-
-static ushort
-gbit16(void *a)
-{
- uchar *i;
-
- i = a;
- return i[1]<<8 | i[0];
-}
-
-static ulong
-gbit32(void *a)
-{
- uchar *i;
- ulong j;
-
- i = a;
- j = i[3] << 24;
- j |= i[2] << 16;
- j |= i[1] << 8;
- j |= i[0];
- return j;
-}
-
-static uvlong
-gbit64(void *a)
-{
- uchar *i;
-
- i = a;
- return (uvlong)gbit32(i+4) << 32 | gbit32(a);
-}
-
-static int
-ataidentify(Ctlr *c, ushort *id)
-{
- vlong s;
- int i;
-
- i = gbit16(id+83) | gbit16(id+86);
- if(i & (1 << 10)){
- c->feat |= Dllba;
- s = gbit64(id+100);
- }else
- s = gbit32(id+60);
-
- idmove(c->serial, id+10, 20);
- idmove(c->firmware, id+23, 8);
- idmove(c->model, id+27, 40);
-
-print("aoe discovers %d.%d: %s %s\n", c->major, c->minor, c->model, c->serial);
-
- c->sectors = s;
- c->mediachange = 1;
- return 0;
-}
-
-static void
-identifydump(Aoeata *a)
-{
- print("%E %E type=%.4ux verflag=%x error=%x %d.%d cmd=%d tag=%.8lux\n",
- a->dst, a->src, nhgets(a->type), a->verflag, a->error,
- nhgets(a->major), a->minor, a->cmd, nhgetl(a->tag));
- print(" aflag=%x errfeat=%ux scnt=%d cmdstat=%ux, lba=%d? res=%.4ux\n",
- a->aflag, a->errfeat, a->scnt, a->cmdstat, 0, nhgets(a->res));
-}
-
-static int
-idpkt(Ctlr *c, Aoeata *a)
-{
- memset(a, 0, sizeof *a);
- a->cmdstat = Cid;
- a->scnt = 1;
- a->lba[3] = 0xa0;
- return hset(c, a, ACata);
-}
-
-static int
-chktag(int *out, int nout, int tag)
-{
- int j;
-
- for(j = 0; j <= nout; j++)
- if(out[j] == tag)
- return 0;
-print("wrong tag\n");
- for(j = 0; j <= nout; j++)
- print("%.8ux != %.8ux\n", out[j], tag);
- return -1;
-}
-
-/*
- * ignore the tag for identify. better than ignoring
- * a response to the wrong identify request
- */
-static int
-identify(Ctlr *c)
-{
- int tag[5], i, n;
- Aoeata *a;
- Etherpkt p;
-
- memset(&p, 0, sizeof p);
- a = (Aoeata*)&p;
- i = 0;
- do {
- if(i == 5){
- print("aoe: identify timeout\n");
- return -1;
- }
- tag[i] = idpkt(c, a);
- ethertxpkt(c->ctlrno, &p, sizeof *a, 0);
- memset(&p, 0, sizeof p);
-next:
- n = etherrxpkt(c->ctlrno, &p, 125);
- if(n == 0){
- i++;
- continue;
- }
- if(nhgets(a->type) != Aoetype)
- goto next;
- if(nhgets(a->major) != c->major || a->minor != c->minor){
- print("wrong device %d.%d want %d.%d; %d\n",
- nhgets(a->major), a->minor,
- c->major, c->minor, n);
- goto next;
- }
- if(chktag(tag, i, nhgetl(a->tag)) == -1)
- goto next;
- if(a->cmdstat & 0xa9){
- print("aoe: ata error on identify: %2ux\n", a->cmdstat);
- return -1;
- }
- } while (a->scnt != 1);
-
- c->feat = 0;
- ataidentify(c, (ushort*)(a+1));
- return 0;
-}
-
-static Ctlr*
-ctlrlookup(int major, int minor)
-{
- Ctlr *c;
-
- for(c = head; c; c = c->next)
- if(c->major == major && c->minor == minor)
- break;
- return c;
-}
-
-static Ctlr*
-newctlr(Etherpkt *p)
-{
- int major, minor;
- Aoeqc *q;
- Ctlr *c;
-
- q = (Aoeqc*)p;
- if(nhgets(q->type) != Aoetype)
- return 0;
- major = nhgets(q->major);
- minor = q->minor;
-
- if(major == 0xffff || minor == 0xff)
- return 0;
-
- if(ctlrlookup(major, minor)){
- print("duplicate shelf.slot\n");
- return 0;
- }
-
- if((c = malloc(sizeof *c)) == 0)
- return 0;
- c->major = major;
- c->minor = minor;
- memmove(c->ea, q->src, Eaddrlen);
-
- if(head != 0)
- tail->next = c;
- else
- head = c;
- tail = c;
- return c;
-}
-
-static void
-discover(int major, int minor)
-{
- int i;
- Aoehdr *h;
- Etherpkt p;
-
- for(i = 0; i < nelem(aoeether); i++){
- if(aoeether[i] == 0)
- continue;
- memset(&p, 0, ETHERMINTU);
- h = (Aoehdr*)&p;
- memset(h->dst, 0xff, sizeof h->dst);
- hnputs(h->type, Aoetype);
- h->verflag = Aoever << 4;
- hnputs(h->major, major);
- h->minor = minor;
- h->cmd = ACconfig;
- ethertxpkt(i, &p, ETHERMINTU, 0);
- }
-}
-
-static int
-rxany(Etherpkt *p, int t)
-{
- int i, n;
-
- for(i = 0; i < nelem(aoeether); i++){
- if(aoeether[i] == 0)
- continue;
- while ((n = etherrxpkt(i, p, t)) != 0)
- if(nhgets(p->type) == Aoetype)
- return n;
- }
- return 0;
-}
-
-static int
-aoeprobe(int major, int minor, SDev *s)
-{
- Ctlr *ctlr;
- Etherpkt p;
- int n, i;
-
- for(i = 0;; i += 200){
- if(i > 8000)
- return -1;
- discover(major, minor);
-again:
- n = rxany(&p, 100);
- if(n > 0 && (ctlr = newctlr(&p)))
- break;
- if(n > 0)
- goto again;
- }
-
- s->ctlr = ctlr;
- s->ifc = &sdaoeifc;
- s->nunit = 1;
- return 0;
-}
-
-static char *probef[32];
-static int nprobe;
-
-int
-pnpprobeid(char *s)
-{
- int id;
-
- if(strlen(s) < 2)
- return 0;
- id = 'e';
- if(s[1] == '!')
- id = s[0];
- return id;
-}
-
-int
-tokenize(char *s, char **args, int maxargs)
-{
- int nargs;
-
- for(nargs = 0; nargs < maxargs; nargs++){
- while(*s != '\0' && strchr("\t\n ", *s) != nil)
- s++;
- if(*s == '\0')
- break;
- args[nargs] = s;
- while(*s != '\0' && strchr("\t\n ", *s) == nil)
- s++;
- if(*s != '\0')
- *s++ = 0;
- }
- return nargs;
-}
-
-int
-aoepnp0(void)
-{
- int i;
- char *p, c;
-
- if((p = getconf("aoeif")) == nil)
- return 0;
-print("aoeif = %s\n", p);
- nprobe = tokenize(p, probef, nelem(probef));
- for(i = 0; i < nprobe; i++){
- if(strncmp(probef[i], "ether", 5) != 0)
- continue;
- c = probef[i][5];
- if(c > '9' || c < '0')
- continue;
- aoeether[c - '0'] = 1;
- }
-
- if((p = getconf("aoedev")) == nil)
- return 0;
- return nprobe = tokenize(p, probef, nelem(probef));
-}
-
-int
-probeshelf(char *s, int *shelf, int *slot)
-{
- int a, b;
- char *r;
-
- for(r = s + strlen(s) - 1; r > s; r--)
- if((*r < '0' || *r > '9') && *r != '.'){
- r++;
- break;
- }
- a = strtoul(r, &r, 10);
- if(*r++ != '.')
- return -1;
- b = strtoul(r, 0, 10);
-
- *shelf = a;
- *slot = b;
-print(" shelf=%d.%d\n", a, b);
- return 0;
-}
-
-Ctlr*
-pnpprobe(SDev *sd)
-{
- int shelf, slot;
- char *p;
- static int i;
-
- if(i >= nprobe)
- return 0;
- p = probef[i++];
- if(strlen(p) < 2)
- return 0;
- if(p[1] == '!'){
- sd->idno = p[0];
- p += 2;
- }
- if(probeshelf(p, &shelf, &slot) == -1 ||
- aoeprobe(shelf, slot, sd) == -1 ||
- identify(sd->ctlr) == -1)
- return 0;
- return sd->ctlr;
-}
-
-/*
- * we may need to pretend we found something
- */
-
-SDev*
-aoepnp(void)
-{
- int n, i, id;
- char *p;
- SDev *h, *t, *s;
-
- p = getconf("aoeif");
- if (p)
- print("aoepnp: aoeif=%s\n", p);
-
- if((n = aoepnp0()) == 0)
- n = 2;
- t = h = 0;
- for(i = 0; i < n; i++){
- id = 'e';
- s = malloc(sizeof *s);
- if(s == 0)
- break;
- s->ctlr = 0;
- s->idno = id;
- s->ifc = &sdaoeifc;
- s->nunit = 1;
- pnpprobe(s);
-
- if(h)
- t->next = s;
- else
- h = s;
- t = s;
- }
- return h;
-}
-
-static int
-aoeverify(SDunit *u)
-{
- Ctlr *c;
- SDev *s;
-
- s = u->dev;
- c = s->ctlr;
- if(c == 0){
- aoepnp0();
- if((s->ctlr = c = pnpprobe(s)) == nil)
- return 0;
- }
- c->mediachange = 1;
- return 1;
-}
-
-static int
-aoeonline(SDunit *u)
-{
- int r;
- Ctlr *c;
-
- c = u->dev->ctlr;
- if(c->mediachange){
- r = 2;
- c->mediachange = 0;
- u->sectors = c->sectors;
- u->secsize = 512;
- } else
- r = 1;
- return r;
-}
-
-static int
-rio(Ctlr *c, Aoeata *a, int n, int scnt)
-{
- int i, tag, cmd;
-
- for(i = 0; i < 5; i++){
- tag = hset(c, a, ACata);
- cmd = a->cmdstat;
- ethertxpkt(c->ctlrno, (Etherpkt*)a, n, 0);
- memset(a, 0, sizeof *a);
-again:
- n = etherrxpkt(c->ctlrno, (Etherpkt*)a, 125);
- if(n == 0)
- continue;
- if(nhgets(a->type) != Aoetype || nhgetl(a->tag) != tag ||
- nhgets(a->major) != c->major || a->minor != c->minor)
- goto again;
- if(a->cmdstat & 0xa9){
- print("aoe: ata rio error: %2ux\n", a->cmdstat);
- return 0;
- }
- switch(cmd){
- case Crd:
- case Crdext:
- if(n - sizeof *a < scnt * 512){
- print("aoe: runt expect %d got %d\n",
- scnt*512 + sizeof *a, n);
- return 0;
- }
- return n - sizeof *a;
- case Cwr:
- case Cwrext:
- return scnt * 512;
- default:
-print("unknown cmd %ux\n", cmd);
- break;
- }
- }
- print("aoe: rio timeout\n");
- return 0;
-}
-
-static void
-putlba(Aoeata *a, vlong lba)
-{
- uchar *c;
-
- c = a->lba;
- c[0] = lba;
- c[1] = lba >> 8;
- c[2] = lba >> 16;
- c[3] = lba >> 24;
- c[4] = lba >> 32;
- c[5] = lba >> 40;
-}
-
-/*
- * you'll need to loop if you want to read more than 2 sectors. for now
- * i'm cheeting and not bothering with a loop.
- */
-static uchar pktbuf[1024 + sizeof(Aoeata)];
-
-static int
-aoebuild(Ctlr *c, uchar *cmd, char *data, vlong lba, int scnt)
-{
- int n;
- Aoeata *a;
-
- memset(pktbuf, 0, sizeof pktbuf);
- a = (Aoeata*)pktbuf;
- hset(c, a, ACata);
- putlba(a, lba);
-
- a->cmdstat = 0x20;
- if(c->flag & Dllba){
- a->aflag |= AAFext;
- a->cmdstat |= 4;
- }else{
- a->lba[3] &= 0xf;
- a->lba[3] |= 0xe0; /* LBA bit+obsolete 0xa0 */
- }
-
- n = scnt;
- if(n > 2)
- n = 2;
- a->scnt = n;
-
- switch(*cmd){
- case 0x2a:
- a->aflag |= AAFwrite;
- a->cmdstat |= 10;
- memmove(a+1, data, n*512);
- n = sizeof *a + n*512;
- break;
- case 0x28:
- n = sizeof *a;
- break;
- default:
- print("aoe: bad cmd 0x%.2ux\n", cmd[0]);
- return -1;
- }
- return n;
-}
-
-static int
-aoerio(SDreq *r)
-{
- int size, nsec, n;
- vlong lba;
- char *data;
- uchar *cmd;
- Aoeata *a;
- Ctlr *c;
- SDunit *unit;
-
- unit = r->unit;
- c = unit->dev->ctlr;
- if(r->data == nil)
- return SDok;
- cmd = r->cmd;
-
- lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5]; /* sic. */
- nsec = cmd[7]<<8 | cmd[8];
- a = (Aoeata*)pktbuf;
- data = r->data;
- r->rlen = 0;
-
- for(; nsec > 0; nsec -= n){
-// print("aoebuild(%2x, %p, %lld, %d)\n", *cmd, data, lba, nsec);
- size = aoebuild(c, cmd, data, lba, nsec);
- if(size < 0){
- r->status = SDcheck;
- return SDcheck;
- }
- n = a->scnt;
- r->rlen += rio(c, a, size, n);
- if(*cmd == 0x28)
- memmove(r->data, a + 1, n * 512);
- data += n * 512;
- lba += n;
- }
-
- r->status = SDok;
- return SDok;
-}
-
-SDifc sdaoeifc = {
- "aoe",
-
- aoepnp,
- nil, /* legacy */
- nil, /* id */
- nil, /* enable */
- nil, /* disable */
-
- aoeverify,
- aoeonline,
- aoerio,
- nil,
- nil,
-
- scsibio,
-};
--- a/os/boot/pc/sdata.c
+++ /dev/null
@@ -1,1652 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "error.h"
-
-#include "sd.h"
-
-extern SDifc sdataifc;
-
-enum {
- DbgCONFIG = 0x0001, /* detected drive config info */
- DbgIDENTIFY = 0x0002, /* detected drive identify info */
- DbgSTATE = 0x0004, /* dump state on panic */
- DbgPROBE = 0x0008, /* trace device probing */
- DbgDEBUG = 0x0080, /* the current problem... */
- DbgINL = 0x0100, /* That Inil20+ message we hate */
- Dbg48BIT = 0x0200, /* 48-bit LBA */
- DbgBsy = 0x0400, /* interrupt but Bsy (shared IRQ) */
-};
-#define DEBUG (DbgDEBUG|DbgCONFIG)
-
-enum { /* I/O ports */
- Data = 0,
- Error = 1, /* (read) */
- Features = 1, /* (write) */
- Count = 2, /* sector count<7-0>, sector count<15-8> */
- Ir = 2, /* interrupt reason (PACKET) */
- Sector = 3, /* sector number */
- Lbalo = 3, /* LBA<7-0>, LBA<31-24> */
- Cyllo = 4, /* cylinder low */
- Bytelo = 4, /* byte count low (PACKET) */
- Lbamid = 4, /* LBA<15-8>, LBA<39-32> */
- Cylhi = 5, /* cylinder high */
- Bytehi = 5, /* byte count hi (PACKET) */
- Lbahi = 5, /* LBA<23-16>, LBA<47-40> */
- Dh = 6, /* Device/Head, LBA<32-14> */
- Status = 7, /* (read) */
- Command = 7, /* (write) */
-
- As = 2, /* Alternate Status (read) */
- Dc = 2, /* Device Control (write) */
-};
-
-enum { /* Error */
- Med = 0x01, /* Media error */
- Ili = 0x01, /* command set specific (PACKET) */
- Nm = 0x02, /* No Media */
- Eom = 0x02, /* command set specific (PACKET) */
- Abrt = 0x04, /* Aborted command */
- Mcr = 0x08, /* Media Change Request */
- Idnf = 0x10, /* no user-accessible address */
- Mc = 0x20, /* Media Change */
- Unc = 0x40, /* Uncorrectable data error */
- Wp = 0x40, /* Write Protect */
- Icrc = 0x80, /* Interface CRC error */
-};
-
-enum { /* Features */
- Dma = 0x01, /* data transfer via DMA (PACKET) */
- Ovl = 0x02, /* command overlapped (PACKET) */
-};
-
-enum { /* Interrupt Reason */
- Cd = 0x01, /* Command/Data */
- Io = 0x02, /* I/O direction */
- Rel = 0x04, /* Bus Release */
-};
-
-enum { /* Device/Head */
- Dev0 = 0xA0, /* Master */
- Dev1 = 0xB0, /* Slave */
- Lba = 0x40, /* LBA mode */
-};
-
-enum { /* Status, Alternate Status */
- Err = 0x01, /* Error */
- Chk = 0x01, /* Check error (PACKET) */
- Drq = 0x08, /* Data Request */
- Dsc = 0x10, /* Device Seek Complete */
- Serv = 0x10, /* Service */
- Df = 0x20, /* Device Fault */
- Dmrd = 0x20, /* DMA ready (PACKET) */
- Drdy = 0x40, /* Device Ready */
- Bsy = 0x80, /* Busy */
-};
-
-enum { /* Command */
- Cnop = 0x00, /* NOP */
- Cdr = 0x08, /* Device Reset */
- Crs = 0x20, /* Read Sectors */
- Crs48 = 0x24, /* Read Sectors Ext */
- Crd48 = 0x25, /* Read w/ DMA Ext */
- Crdq48 = 0x26, /* Read w/ DMA Queued Ext */
- Crsm48 = 0x29, /* Read Multiple Ext */
- Cws = 0x30, /* Write Sectors */
- Cws48 = 0x34, /* Write Sectors Ext */
- Cwd48 = 0x35, /* Write w/ DMA Ext */
- Cwdq48 = 0x36, /* Write w/ DMA Queued Ext */
- Cwsm48 = 0x39, /* Write Multiple Ext */
- Cedd = 0x90, /* Execute Device Diagnostics */
- Cpkt = 0xA0, /* Packet */
- Cidpkt = 0xA1, /* Identify Packet Device */
- Crsm = 0xC4, /* Read Multiple */
- Cwsm = 0xC5, /* Write Multiple */
- Csm = 0xC6, /* Set Multiple */
- Crdq = 0xC7, /* Read DMA queued */
- Crd = 0xC8, /* Read DMA */
- Cwd = 0xCA, /* Write DMA */
- Cwdq = 0xCC, /* Write DMA queued */
- Cstandby = 0xE2, /* Standby */
- Cid = 0xEC, /* Identify Device */
- Csf = 0xEF, /* Set Features */
-};
-
-enum { /* Device Control */
- Nien = 0x02, /* (not) Interrupt Enable */
- Srst = 0x04, /* Software Reset */
-};
-
-enum { /* PCI Configuration Registers */
- Bmiba = 0x20, /* Bus Master Interface Base Address */
- Idetim = 0x40, /* IE Timing */
- Sidetim = 0x44, /* Slave IE Timing */
- Udmactl = 0x48, /* Ultra DMA/33 Control */
- Udmatim = 0x4A, /* Ultra DMA/33 Timing */
-};
-
-enum { /* Bus Master IDE I/O Ports */
- Bmicx = 0, /* Command */
- Bmisx = 2, /* Status */
- Bmidtpx = 4, /* Descriptor Table Pointer */
-};
-
-enum { /* Bmicx */
- Ssbm = 0x01, /* Start/Stop Bus Master */
- Rwcon = 0x08, /* Read/Write Control */
-};
-
-enum { /* Bmisx */
- Bmidea = 0x01, /* Bus Master IDE Active */
- Idedmae = 0x02, /* IDE DMA Error (R/WC) */
- Ideints = 0x04, /* IDE Interrupt Status (R/WC) */
- Dma0cap = 0x20, /* Drive 0 DMA Capable */
- Dma1cap = 0x40, /* Drive 0 DMA Capable */
-};
-enum { /* Physical Region Descriptor */
- PrdEOT = 0x80000000, /* Bus Master IDE Active */
-};
-
-enum { /* offsets into the identify info. */
- Iconfig = 0, /* general configuration */
- Ilcyl = 1, /* logical cylinders */
- Ilhead = 3, /* logical heads */
- Ilsec = 6, /* logical sectors per logical track */
- Iserial = 10, /* serial number */
- Ifirmware = 23, /* firmware revision */
- Imodel = 27, /* model number */
- Imaxrwm = 47, /* max. read/write multiple sectors */
- Icapabilities = 49, /* capabilities */
- Istandby = 50, /* device specific standby timer */
- Ipiomode = 51, /* PIO data transfer mode number */
- Ivalid = 53,
- Iccyl = 54, /* cylinders if (valid&0x01) */
- Ichead = 55, /* heads if (valid&0x01) */
- Icsec = 56, /* sectors if (valid&0x01) */
- Iccap = 57, /* capacity if (valid&0x01) */
- Irwm = 59, /* read/write multiple */
- Ilba = 60, /* LBA size */
- Imwdma = 63, /* multiword DMA mode */
- Iapiomode = 64, /* advanced PIO modes supported */
- Iminmwdma = 65, /* min. multiword DMA cycle time */
- Irecmwdma = 66, /* rec. multiword DMA cycle time */
- Iminpio = 67, /* min. PIO cycle w/o flow control */
- Iminiordy = 68, /* min. PIO cycle with IORDY */
- Ipcktbr = 71, /* time from PACKET to bus release */
- Iserbsy = 72, /* time from SERVICE to !Bsy */
- Iqdepth = 75, /* max. queue depth */
- Imajor = 80, /* major version number */
- Iminor = 81, /* minor version number */
- Icsfs = 82, /* command set/feature supported */
- Icsfe = 85, /* command set/feature enabled */
- Iudma = 88, /* ultra DMA mode */
- Ierase = 89, /* time for security erase */
- Ieerase = 90, /* time for enhanced security erase */
- Ipower = 91, /* current advanced power management */
- Ilba48 = 100, /* 48-bit LBA size (64 bits in 100-103) */
- Irmsn = 127, /* removable status notification */
- Isecstat = 128, /* security status */
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Drive Drive;
-
-typedef struct Prd {
- ulong pa; /* Physical Base Address */
- int count;
-} Prd;
-
-enum {
- Nprd = SDmaxio/(64*1024)+2,
-};
-
-typedef struct Ctlr {
- int cmdport;
- int ctlport;
- int irq;
- int tbdf;
-
- Pcidev* pcidev;
- void (*ienable)(Ctlr*);
- SDev* sdev;
-
- Drive* drive[2];
-
- Prd* prdt; /* physical region descriptor table */
-
-// QLock; /* current command */
- Drive* curdrive;
- int command; /* last command issued (debugging) */
-// Rendez;
- int done;
-
- Lock; /* register access */
-} Ctlr;
-
-typedef struct Drive {
- Ctlr* ctlr;
-
- int dev;
- ushort info[256];
- int c; /* cylinder */
- int h; /* head */
- int s; /* sector */
- vlong sectors; /* total */
- int secsize; /* sector size */
-
-// int dma; /* DMA R/W possible */
-// int dmactl;
-// int rwm; /* read/write multiple possible */
-// int rwmctl;
-
- int pkt; /* PACKET device, length of pktcmd */
- uchar pktcmd[16];
-// int pktdma; /* this PACKET command using dma */
-
- uchar sense[18];
- uchar inquiry[48];
-
-// QLock; /* drive access */
- int command; /* current command */
- int write;
- uchar* data;
- int dlen;
- uchar* limit;
- int count; /* sectors */
- int block; /* R/W bytes per block */
- int status;
- int error;
- int flags; /* internal flags */
-} Drive;
-
-enum { /* internal flags */
- Lba48 = 0x1, /* LBA48 mode */
- Lba48always = 0x2, /* ... */
-};
-
-static void
-pc87415ienable(Ctlr* ctlr)
-{
- Pcidev *p;
- int x;
-
- p = ctlr->pcidev;
- if(p == nil)
- return;
-
- x = pcicfgr32(p, 0x40);
- if(ctlr->cmdport == p->mem[0].bar)
- x &= ~0x00000100;
- else
- x &= ~0x00000200;
- pcicfgw32(p, 0x40, x);
-}
-
-static int
-atadebug(int cmdport, int ctlport, char* fmt, ...)
-{
- int i, n;
- va_list arg;
- char buf[PRINTSIZE];
-
- if(!(DEBUG & DbgPROBE)){
- USED(cmdport, ctlport, fmt);
- return 0;
- }
-
- va_start(arg, fmt);
- n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
- va_end(arg);
-
- if(cmdport){
- if(buf[n-1] == '\n')
- n--;
- n += snprint(buf+n, PRINTSIZE-n, " ataregs 0x%uX:",
- cmdport);
- for(i = Features; i < Command; i++)
- n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",
- inb(cmdport+i));
- if(ctlport)
- n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",
- inb(ctlport+As));
- n += snprint(buf+n, PRINTSIZE-n, "\n");
- }
- putstrn(buf, n);
-
- return n;
-}
-
-static int
-ataready(int cmdport, int ctlport, int dev, int reset, int ready, int micro)
-{
- int as;
-
- atadebug(cmdport, ctlport, "ataready: dev %uX reset %uX ready %uX",
- dev, reset, ready);
-
- for(;;){
- /*
- * Wait for the controller to become not busy and
- * possibly for a status bit to become true (usually
- * Drdy). Must change to the appropriate device
- * register set if necessary before testing for ready.
- * Always run through the loop at least once so it
- * can be used as a test for !Bsy.
- */
- as = inb(ctlport+As);
- if(as & reset){
- /* nothing to do */;
- }
- else if(dev){
- outb(cmdport+Dh, dev);
- dev = 0;
- }
- else if(ready == 0 || (as & ready)){
- atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);
- return as;
- }
-
- if(micro-- <= 0){
- atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);
- break;
- }
- microdelay(1);
- }
- atadebug(cmdport, ctlport, "ataready: timeout");
-
- return -1;
-}
-
-static int
-atacsfenabled(Drive* drive, vlong csf)
-{
- int cmdset, i, x;
-
- for(i = 0; i < 3; i++){
- x = (csf>>(16*i)) & 0xFFFF;
- if(x == 0)
- continue;
- cmdset = drive->info[Icsfe+i];
- if(cmdset == 0 || cmdset == 0xFFFF)
- return 0;
- return cmdset & x;
- }
-
- return 0;
-}
-
-/*
-static int
-atasf(int cmdport, int ctlport, int dev, uchar* command)
-{
- int as, i;
-
- if(ataready(cmdport, ctlport, dev, Bsy|Drq, Drdy, 108*1000) < 0)
- return -1;
-
- for(i = Features; i < Dh; i++)
- outb(cmdport+i, command[i]);
- outb(cmdport+Command, Csf);
- microdelay(100);
- as = ataready(cmdport, ctlport, 0, Bsy, Drdy|Df|Err, 109*1000);
- if(as < 0 || (as & (Df|Err)))
- return -1;
- return 0;
-}
- */
-
-static int
-ataidentify(int cmdport, int ctlport, int dev, int pkt, void* info)
-{
- int as, command, drdy;
-
- if(pkt){
- command = Cidpkt;
- drdy = 0;
- }
- else{
- command = Cid;
- drdy = Drdy;
- }
- as = ataready(cmdport, ctlport, dev, Bsy|Drq, drdy, 103*1000);
- if(as < 0)
- return as;
- outb(cmdport+Command, command);
- microdelay(1);
-
- as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 400*1000);
- if(as < 0)
- return -1;
- if(as & Err)
- return as;
-
- memset(info, 0, 512);
- inss(cmdport+Data, info, 256);
- inb(cmdport+Status);
-
- if(DEBUG & DbgIDENTIFY){
- int i;
- ushort *sp;
-
- sp = (ushort*)info;
- for(i = 0; i < 256; i++){
- if(i && (i%16) == 0)
- print("\n");
- print(" %4.4uX ", *sp);
- sp++;
- }
- print("\n");
- }
-
- return 0;
-}
-
-static Drive*
-atadrive(int cmdport, int ctlport, int dev)
-{
- Drive *drive;
- int as, i, pkt;
- uchar buf[512], *p;
- ushort iconfig, *sp;
-
- atadebug(0, 0, "identify: port 0x%uX dev 0x%2.2uX\n", cmdport, dev);
- pkt = 1;
-retry:
- as = ataidentify(cmdport, ctlport, dev, pkt, buf);
- if(as < 0)
- return nil;
- if(as & Err){
- if(pkt == 0)
- return nil;
- pkt = 0;
- goto retry;
- }
-
- if((drive = malloc(sizeof(Drive))) == nil)
- return nil;
- drive->dev = dev;
- memmove(drive->info, buf, sizeof(drive->info));
- drive->sense[0] = 0x70;
- drive->sense[7] = sizeof(drive->sense)-7;
-
- drive->inquiry[2] = 2;
- drive->inquiry[3] = 2;
- drive->inquiry[4] = sizeof(drive->inquiry)-4;
- p = &drive->inquiry[8];
- sp = &drive->info[Imodel];
- for(i = 0; i < 20; i++){
- *p++ = *sp>>8;
- *p++ = *sp++;
- }
-
- drive->secsize = 512;
-
- /*
- * Beware the CompactFlash Association feature set.
- * Now, why this value in Iconfig just walks all over the bit
- * definitions used in the other parts of the ATA/ATAPI standards
- * is a mystery and a sign of true stupidity on someone's part.
- * Anyway, the standard says if this value is 0x848A then it's
- * CompactFlash and it's NOT a packet device.
- */
- iconfig = drive->info[Iconfig];
- if(iconfig != 0x848A && (iconfig & 0xC000) == 0x8000){
- if(iconfig & 0x01)
- drive->pkt = 16;
- else
- drive->pkt = 12;
- }
- else{
- if(drive->info[Ivalid] & 0x0001){
- drive->c = drive->info[Iccyl];
- drive->h = drive->info[Ichead];
- drive->s = drive->info[Icsec];
- }
- else{
- drive->c = drive->info[Ilcyl];
- drive->h = drive->info[Ilhead];
- drive->s = drive->info[Ilsec];
- }
- if(drive->info[Icapabilities] & 0x0200){
- if(drive->info[Icsfs+1] & 0x0400){
- drive->sectors = drive->info[Ilba48]
- |(drive->info[Ilba48+1]<<16)
- |((vlong)drive->info[Ilba48+2]<<32);
- drive->flags |= Lba48;
- }
- else{
- drive->sectors = (drive->info[Ilba+1]<<16)
- |drive->info[Ilba];
- }
- drive->dev |= Lba;
- }
- else
- drive->sectors = drive->c*drive->h*drive->s;
- // atarwmmode(drive, cmdport, ctlport, dev);
- }
-// atadmamode(drive);
-
- if(DEBUG & DbgCONFIG){
- print("dev %2.2uX port %uX config %4.4uX capabilities %4.4uX",
- dev, cmdport, iconfig, drive->info[Icapabilities]);
- print(" mwdma %4.4uX", drive->info[Imwdma]);
- if(drive->info[Ivalid] & 0x04)
- print(" udma %4.4uX", drive->info[Iudma]);
-// print(" dma %8.8uX rwm %ud", drive->dma, drive->rwm);
- if(drive->flags&Lba48)
- print("\tLLBA sectors %lld", drive->sectors);
- print("\n");
- }
-
- return drive;
-}
-
-static void
-atasrst(int ctlport)
-{
- /*
- * Srst is a big stick and may cause problems if further
- * commands are tried before the drives become ready again.
- * Also, there will be problems here if overlapped commands
- * are ever supported.
- */
- microdelay(5);
- outb(ctlport+Dc, Srst);
- microdelay(5);
- outb(ctlport+Dc, 0);
- microdelay(2*1000);
-}
-
-static SDev*
-ataprobe(int cmdport, int ctlport, int irq)
-{
- Ctlr* ctlr;
- SDev *sdev;
- Drive *drive;
- int dev, error, rhi, rlo;
-
-// if(ioalloc(cmdport, 8, 0, "atacmd") < 0)
-// return nil;
-// if(ioalloc(ctlport+As, 1, 0, "atactl") < 0){
-// iofree(cmdport);
-// return nil;
-// }
-
- /*
- * Try to detect a floating bus.
- * Bsy should be cleared. If not, see if the cylinder registers
- * are read/write capable.
- * If the master fails, try the slave to catch slave-only
- * configurations.
- * There's no need to restore the tested registers as they will
- * be reset on any detected drives by the Cedd command.
- * All this indicates is that there is at least one drive on the
- * controller; when the non-existent drive is selected in a
- * single-drive configuration the registers of the existing drive
- * are often seen, only command execution fails.
- */
- dev = Dev0;
- if(inb(ctlport+As) & Bsy){
- outb(cmdport+Dh, dev);
- microdelay(1);
-trydev1:
- atadebug(cmdport, ctlport, "ataprobe bsy");
- outb(cmdport+Cyllo, 0xAA);
- outb(cmdport+Cylhi, 0x55);
- outb(cmdport+Sector, 0xFF);
- rlo = inb(cmdport+Cyllo);
- rhi = inb(cmdport+Cylhi);
- if(rlo != 0xAA && (rlo == 0xFF || rhi != 0x55)){
- if(dev == Dev1){
-release:
- // iofree(cmdport);
- // iofree(ctlport+As);
- return nil;
- }
- dev = Dev1;
- if(ataready(cmdport, ctlport, dev, Bsy, 0, 20*1000) < 0)
- goto trydev1;
- }
- }
-
- /*
- * Disable interrupts on any detected controllers.
- */
- outb(ctlport+Dc, Nien);
-tryedd1:
- if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 105*1000) < 0){
- /*
- * There's something there, but it didn't come up clean,
- * so try hitting it with a big stick. The timing here is
- * wrong but this is a last-ditch effort and it sometimes
- * gets some marginal hardware back online.
- */
- atasrst(ctlport);
- if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 106*1000) < 0)
- goto release;
- }
-
- /*
- * Can only get here if controller is not busy.
- * If there are drives Bsy will be set within 400nS,
- * must wait 2mS before testing Status.
- * Wait for the command to complete (6 seconds max).
- */
- outb(cmdport+Command, Cedd);
- delay(2);
- if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 6*1000*1000) < 0)
- goto release;
-
- /*
- * If bit 0 of the error register is set then the selected drive
- * exists. This is enough to detect single-drive configurations.
- * However, if the master exists there is no way short of executing
- * a command to determine if a slave is present.
- * It appears possible to get here testing Dev0 although it doesn't
- * exist and the EDD won't take, so try again with Dev1.
- */
- error = inb(cmdport+Error);
- atadebug(cmdport, ctlport, "ataprobe: dev %uX", dev);
- if((error & ~0x80) != 0x01){
- if(dev == Dev1)
- goto release;
- dev = Dev1;
- goto tryedd1;
- }
-
- /*
- * At least one drive is known to exist, try to
- * identify it. If that fails, don't bother checking
- * any further.
- * If the one drive found is Dev0 and the EDD command
- * didn't indicate Dev1 doesn't exist, check for it.
- */
- if((drive = atadrive(cmdport, ctlport, dev)) == nil)
- goto release;
- if((ctlr = malloc(sizeof(Ctlr))) == nil){
- free(drive);
- goto release;
- }
- if((sdev = malloc(sizeof(SDev))) == nil){
- free(ctlr);
- free(drive);
- goto release;
- }
- drive->ctlr = ctlr;
- if(dev == Dev0){
- ctlr->drive[0] = drive;
- if(!(error & 0x80)){
- /*
- * Always leave Dh pointing to a valid drive,
- * otherwise a subsequent call to ataready on
- * this controller may try to test a bogus Status.
- * Ataprobe is the only place possibly invalid
- * drives should be selected.
- */
- drive = atadrive(cmdport, ctlport, Dev1);
- if(drive != nil){
- drive->ctlr = ctlr;
- ctlr->drive[1] = drive;
- }
- else{
- outb(cmdport+Dh, Dev0);
- microdelay(1);
- }
- }
- }
- else
- ctlr->drive[1] = drive;
-
- ctlr->cmdport = cmdport;
- ctlr->ctlport = ctlport;
- ctlr->irq = irq;
- ctlr->tbdf = BUSUNKNOWN;
- ctlr->command = Cedd; /* debugging */
-
- sdev->ifc = &sdataifc;
- sdev->ctlr = ctlr;
- sdev->nunit = 2;
- ctlr->sdev = sdev;
-
- return sdev;
-}
-
-static int
-atasetsense(Drive* drive, int status, int key, int asc, int ascq)
-{
- drive->sense[2] = key;
- drive->sense[12] = asc;
- drive->sense[13] = ascq;
-
- return status;
-}
-
-static int
-atamodesense(Drive* drive, uchar* cmd)
-{
- int len;
-
- /*
- * Fake a vendor-specific request with page code 0,
- * return the drive info.
- */
- if((cmd[2] & 0x3F) != 0 && (cmd[2] & 0x3F) != 0x3F)
- return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
- len = (cmd[7]<<8)|cmd[8];
- if(len == 0)
- return SDok;
- if(len < 8+sizeof(drive->info))
- return atasetsense(drive, SDcheck, 0x05, 0x1A, 0);
- if(drive->data == nil || drive->dlen < len)
- return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
- memset(drive->data, 0, 8);
- drive->data[0] = sizeof(drive->info)>>8;
- drive->data[1] = sizeof(drive->info);
- memmove(drive->data+8, drive->info, sizeof(drive->info));
- drive->data += 8+sizeof(drive->info);
-
- return SDok;
-}
-
-static void
-atanop(Drive* drive, int subcommand)
-{
- Ctlr* ctlr;
- int as, cmdport, ctlport, timeo;
-
- /*
- * Attempt to abort a command by using NOP.
- * In response, the drive is supposed to set Abrt
- * in the Error register, set (Drdy|Err) in Status
- * and clear Bsy when done. However, some drives
- * (e.g. ATAPI Zip) just go Bsy then clear Status
- * when done, hence the timeout loop only on Bsy
- * and the forced setting of drive->error.
- */
- ctlr = drive->ctlr;
- cmdport = ctlr->cmdport;
- outb(cmdport+Features, subcommand);
- outb(cmdport+Dh, drive->dev);
- ctlr->command = Cnop; /* debugging */
- outb(cmdport+Command, Cnop);
-
- microdelay(1);
- ctlport = ctlr->ctlport;
- for(timeo = 0; timeo < 1000; timeo++){
- as = inb(ctlport+As);
- if(!(as & Bsy))
- break;
- microdelay(1);
- }
- drive->error |= Abrt;
-}
-
-static void
-ataabort(Drive* drive, int dolock)
-{
- /*
- * If NOP is available (packet commands) use it otherwise
- * must try a software reset.
- */
- if(dolock)
- ilock(drive->ctlr);
- if(atacsfenabled(drive, 0x0000000000004000LL))
- atanop(drive, 0);
- else{
- atasrst(drive->ctlr->ctlport);
- drive->error |= Abrt;
- }
- if(dolock)
- iunlock(drive->ctlr);
-}
-
-static int
-atapktiodone(void* arg)
-{
- return ((Ctlr*)arg)->done;
-}
-
-static void
-atapktinterrupt(Drive* drive)
-{
- Ctlr* ctlr;
- int cmdport, len;
-
- ctlr = drive->ctlr;
- cmdport = ctlr->cmdport;
- switch(inb(cmdport+Ir) & (/*Rel|*/Io|Cd)){
- case Cd:
- outss(cmdport+Data, drive->pktcmd, drive->pkt/2);
- break;
-
- case 0:
- len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
- if(drive->data+len > drive->limit){
- atanop(drive, 0);
- break;
- }
- outss(cmdport+Data, drive->data, len/2);
- drive->data += len;
- break;
-
- case Io:
- len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
- if(drive->data+len > drive->limit){
- atanop(drive, 0);
- break;
- }
- inss(cmdport+Data, drive->data, len/2);
- drive->data += len;
- break;
-
- case Io|Cd:
- // if(drive->pktdma)
- // atadmainterrupt(drive, drive->dlen);
- // else
- ctlr->done = 1;
- break;
- }
-}
-
-static int
-atapktio(Drive* drive, uchar* cmd, int clen)
-{
- Ctlr *ctlr;
- int as, cmdport, ctlport, len, r;
-
- if(cmd[0] == 0x5A && (cmd[2] & 0x3F) == 0)
- return atamodesense(drive, cmd);
-
- r = SDok;
-
- drive->command = Cpkt;
- memmove(drive->pktcmd, cmd, clen);
- memset(drive->pktcmd+clen, 0, drive->pkt-clen);
- drive->limit = drive->data+drive->dlen;
-
- ctlr = drive->ctlr;
- cmdport = ctlr->cmdport;
- ctlport = ctlr->ctlport;
-
- qlock(ctlr);
-
- as = ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 107*1000);
- if(as < 0 || (as&Chk)){
- qunlock(ctlr);
- return -1;
- }
-
- ilock(ctlr);
-// if(drive->dlen && drive->dmactl && !atadmasetup(drive, drive->dlen))
-// drive->pktdma = Dma;
-// else
-// drive->pktdma = 0;
-
- outb(cmdport+Features, 0/*drive->pktdma*/);
- outb(cmdport+Count, 0);
- outb(cmdport+Sector, 0);
- len = 16*drive->secsize;
- outb(cmdport+Bytelo, len);
- outb(cmdport+Bytehi, len>>8);
- outb(cmdport+Dh, drive->dev);
- ctlr->done = 0;
- ctlr->curdrive = drive;
- ctlr->command = Cpkt; /* debugging */
-// if(drive->pktdma)
-// atadmastart(ctlr, drive->write);
- outb(cmdport+Command, Cpkt);
-
- if((drive->info[Iconfig] & 0x0060) != 0x0020){
- microdelay(1);
- as = ataready(cmdport, ctlport, 0, Bsy, Drq|Chk, 4*1000);
- if(as < 0 || (as & (Bsy|Chk))){
- drive->status = as<0 ? 0 : as;
- ctlr->curdrive = nil;
- ctlr->done = 1;
- r = SDtimeout;
- }else
- atapktinterrupt(drive);
- }
- iunlock(ctlr);
-
- sleep(ctlr, atapktiodone, ctlr);
-
- qunlock(ctlr);
-
- if(drive->status & Chk)
- r = SDcheck;
-
- return r;
-}
-
-static int
-atageniodone(void* arg)
-{
- return ((Ctlr*)arg)->done;
-}
-
-static uchar cmd48[256] = {
- [Crs] Crs48,
- [Crd] Crd48,
- [Crdq] Crdq48,
- [Crsm] Crsm48,
- [Cws] Cws48,
- [Cwd] Cwd48,
- [Cwdq] Cwdq48,
- [Cwsm] Cwsm48,
-};
-
-static int
-atageniostart(Drive* drive, vlong lba)
-{
- Ctlr *ctlr;
- uchar cmd;
- int as, c, cmdport, ctlport, h, len, s, use48;
-
- use48 = 0;
- if((drive->flags&Lba48always) || (lba>>28) || drive->count > 256){
- if(!(drive->flags & Lba48))
- return -1;
- use48 = 1;
- c = h = s = 0;
- }else if(drive->dev & Lba){
- c = (lba>>8) & 0xFFFF;
- h = (lba>>24) & 0x0F;
- s = lba & 0xFF;
- }
- else{
- c = lba/(drive->s*drive->h);
- h = ((lba/drive->s) % drive->h);
- s = (lba % drive->s) + 1;
- }
-
- ctlr = drive->ctlr;
- cmdport = ctlr->cmdport;
- ctlport = ctlr->ctlport;
- if(ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 101*1000) < 0)
- return -1;
-
- ilock(ctlr);
-
- drive->block = drive->secsize;
- if(drive->write)
- drive->command = Cws;
- else
- drive->command = Crs;
-
- drive->limit = drive->data + drive->count*drive->secsize;
- cmd = drive->command;
- if(use48){
- outb(cmdport+Count, (drive->count>>8) & 0xFF);
- outb(cmdport+Count, drive->count & 0XFF);
- outb(cmdport+Lbalo, (lba>>24) & 0xFF);
- outb(cmdport+Lbalo, lba & 0xFF);
- outb(cmdport+Lbamid, (lba>>32) & 0xFF);
- outb(cmdport+Lbamid, (lba>>8) & 0xFF);
- outb(cmdport+Lbahi, (lba>>40) & 0xFF);
- outb(cmdport+Lbahi, (lba>>16) & 0xFF);
- outb(cmdport+Dh, drive->dev|Lba);
- cmd = cmd48[cmd];
-
- if(DEBUG & Dbg48BIT)
- print("using 48-bit commands\n");
- }else{
- outb(cmdport+Count, drive->count);
- outb(cmdport+Sector, s);
- outb(cmdport+Cyllo, c);
- outb(cmdport+Cylhi, c>>8);
- outb(cmdport+Dh, drive->dev|h);
- }
- ctlr->done = 0;
- ctlr->curdrive = drive;
- ctlr->command = drive->command; /* debugging */
- outb(cmdport+Command, cmd);
-
- switch(drive->command){
- case Cws:
- case Cwsm:
- microdelay(1);
- as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 1000);
- if(as < 0 || (as & Err)){
- iunlock(ctlr);
- return -1;
- }
- len = drive->block;
- if(drive->data+len > drive->limit)
- len = drive->limit-drive->data;
- outss(cmdport+Data, drive->data, len/2);
- break;
-
- case Crd:
- case Cwd:
- // atadmastart(ctlr, drive->write);
- break;
- }
- iunlock(ctlr);
-
- return 0;
-}
-
-static int
-atagenioretry(Drive* drive)
-{
- return atasetsense(drive, SDcheck, 4, 8, drive->error);
-}
-
-static int
-atagenio(Drive* drive, uchar* cmd, int)
-{
- uchar *p;
- Ctlr *ctlr;
- int count, max;
- vlong lba, len;
-
- /*
- * Map SCSI commands into ATA commands for discs.
- * Fail any command with a LUN except INQUIRY which
- * will return 'logical unit not supported'.
- */
- if((cmd[1]>>5) && cmd[0] != 0x12)
- return atasetsense(drive, SDcheck, 0x05, 0x25, 0);
-
- switch(cmd[0]){
- default:
- return atasetsense(drive, SDcheck, 0x05, 0x20, 0);
-
- case 0x00: /* test unit ready */
- return SDok;
-
- case 0x03: /* request sense */
- if(cmd[4] < sizeof(drive->sense))
- len = cmd[4];
- else
- len = sizeof(drive->sense);
- if(drive->data && drive->dlen >= len){
- memmove(drive->data, drive->sense, len);
- drive->data += len;
- }
- return SDok;
-
- case 0x12: /* inquiry */
- if(cmd[4] < sizeof(drive->inquiry))
- len = cmd[4];
- else
- len = sizeof(drive->inquiry);
- if(drive->data && drive->dlen >= len){
- memmove(drive->data, drive->inquiry, len);
- drive->data += len;
- }
- return SDok;
-
- case 0x1B: /* start/stop unit */
- /*
- * NOP for now, can use the power management feature
- * set later.
- */
- return SDok;
-
- case 0x25: /* read capacity */
- if((cmd[1] & 0x01) || cmd[2] || cmd[3])
- return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
- if(drive->data == nil || drive->dlen < 8)
- return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
- /*
- * Read capacity returns the LBA of the last sector.
- */
- len = drive->sectors-1;
- p = drive->data;
- *p++ = len>>24;
- *p++ = len>>16;
- *p++ = len>>8;
- *p++ = len;
- len = drive->secsize;
- *p++ = len>>24;
- *p++ = len>>16;
- *p++ = len>>8;
- *p = len;
- drive->data += 8;
- return SDok;
-
- case 0x9E: /* long read capacity */
- if((cmd[1] & 0x01) || cmd[2] || cmd[3])
- return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
- if(drive->data == nil || drive->dlen < 8)
- return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
- /*
- * Read capacity returns the LBA of the last sector.
- */
- len = drive->sectors-1;
- p = drive->data;
- *p++ = len>>56;
- *p++ = len>>48;
- *p++ = len>>40;
- *p++ = len>>32;
- *p++ = len>>24;
- *p++ = len>>16;
- *p++ = len>>8;
- *p++ = len;
- len = drive->secsize;
- *p++ = len>>24;
- *p++ = len>>16;
- *p++ = len>>8;
- *p = len;
- drive->data += 8;
- return SDok;
-
- case 0x28: /* read */
- case 0x2A: /* write */
- break;
-
- case 0x5A:
- return atamodesense(drive, cmd);
- }
-
- ctlr = drive->ctlr;
- lba = (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5];
- count = (cmd[7]<<8)|cmd[8];
- if(drive->data == nil)
- return SDok;
- if(drive->dlen < count*drive->secsize)
- count = drive->dlen/drive->secsize;
- qlock(ctlr);
- while(count){
- max = (drive->flags&Lba48) ? 65536 : 256;
- if(count > max)
- drive->count = max;
- else
- drive->count = count;
- if(atageniostart(drive, lba)){
- ilock(ctlr);
- atanop(drive, 0);
- iunlock(ctlr);
- qunlock(ctlr);
- return atagenioretry(drive);
- }
-
- tsleep(ctlr, atageniodone, ctlr, 10*1000);
- if(!ctlr->done){
- /*
- * What should the above timeout be? In
- * standby and sleep modes it could take as
- * long as 30 seconds for a drive to respond.
- * Very hard to get out of this cleanly.
- */
- // atadumpstate(drive, cmd, lba, count);
- ataabort(drive, 1);
- return atagenioretry(drive);
- }
-
- if(drive->status & Err){
- qunlock(ctlr);
- return atasetsense(drive, SDcheck, 4, 8, drive->error);
- }
- count -= drive->count;
- lba += drive->count;
- }
- qunlock(ctlr);
-
- return SDok;
-}
-
-static int
-atario(SDreq* r)
-{
- Ctlr *ctlr;
- Drive *drive;
- SDunit *unit;
- uchar cmd10[10], *cmdp, *p;
- int clen, reqstatus, status;
-
- unit = r->unit;
- if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil){
- r->status = SDtimeout;
- return SDtimeout;
- }
- drive = ctlr->drive[unit->subno];
-
- /*
- * Most SCSI commands can be passed unchanged except for
- * the padding on the end. The few which require munging
- * are not used internally. Mode select/sense(6) could be
- * converted to the 10-byte form but it's not worth the
- * effort. Read/write(6) are easy.
- */
- switch(r->cmd[0]){
- case 0x08: /* read */
- case 0x0A: /* write */
- cmdp = cmd10;
- memset(cmdp, 0, sizeof(cmd10));
- cmdp[0] = r->cmd[0]|0x20;
- cmdp[1] = r->cmd[1] & 0xE0;
- cmdp[5] = r->cmd[3];
- cmdp[4] = r->cmd[2];
- cmdp[3] = r->cmd[1] & 0x0F;
- cmdp[8] = r->cmd[4];
- clen = sizeof(cmd10);
- break;
-
- default:
- cmdp = r->cmd;
- clen = r->clen;
- break;
- }
-
- qlock(drive);
- drive->write = r->write;
- drive->data = r->data;
- drive->dlen = r->dlen;
-
- drive->status = 0;
- drive->error = 0;
- if(drive->pkt)
- status = atapktio(drive, cmdp, clen);
- else
- status = atagenio(drive, cmdp, clen);
- if(status == SDok){
- atasetsense(drive, SDok, 0, 0, 0);
- if(drive->data){
- p = r->data;
- r->rlen = drive->data - p;
- }
- else
- r->rlen = 0;
- }
- else if(status == SDcheck && !(r->flags & SDnosense)){
- drive->write = 0;
- memset(cmd10, 0, sizeof(cmd10));
- cmd10[0] = 0x03;
- cmd10[1] = r->lun<<5;
- cmd10[4] = sizeof(r->sense)-1;
- drive->data = r->sense;
- drive->dlen = sizeof(r->sense)-1;
- drive->status = 0;
- drive->error = 0;
- if(drive->pkt)
- reqstatus = atapktio(drive, cmd10, 6);
- else
- reqstatus = atagenio(drive, cmd10, 6);
- if(reqstatus == SDok){
- r->flags |= SDvalidsense;
- atasetsense(drive, SDok, 0, 0, 0);
- }
- }
- qunlock(drive);
- r->status = status;
- if(status != SDok)
- return status;
-
- /*
- * Fix up any results.
- * Many ATAPI CD-ROMs ignore the LUN field completely and
- * return valid INQUIRY data. Patch the response to indicate
- * 'logical unit not supported' if the LUN is non-zero.
- */
- switch(cmdp[0]){
- case 0x12: /* inquiry */
- if((p = r->data) == nil)
- break;
- if((cmdp[1]>>5) && (!drive->pkt || (p[0] & 0x1F) == 0x05))
- p[0] = 0x7F;
- /*FALLTHROUGH*/
- default:
- break;
- }
-
- return SDok;
-}
-
-static void
-atainterrupt(Ureg*, void* arg)
-{
- Ctlr *ctlr;
- Drive *drive;
- int cmdport, len, status;
-
- ctlr = arg;
-
- ilock(ctlr);
- if(inb(ctlr->ctlport+As) & Bsy){
- iunlock(ctlr);
- if(DEBUG & DbgBsy)
- print("IBsy+");
- return;
- }
- cmdport = ctlr->cmdport;
- status = inb(cmdport+Status);
- if((drive = ctlr->curdrive) == nil){
- iunlock(ctlr);
- if((DEBUG & DbgINL) && ctlr->command != Cedd)
- print("Inil%2.2uX+", ctlr->command);
- return;
- }
-
- if(status & Err)
- drive->error = inb(cmdport+Error);
- else switch(drive->command){
- default:
- drive->error = Abrt;
- break;
-
- case Crs:
- case Crsm:
- if(!(status & Drq)){
- drive->error = Abrt;
- break;
- }
- len = drive->block;
- if(drive->data+len > drive->limit)
- len = drive->limit-drive->data;
- inss(cmdport+Data, drive->data, len/2);
- drive->data += len;
- if(drive->data >= drive->limit)
- ctlr->done = 1;
- break;
-
- case Cws:
- case Cwsm:
- len = drive->block;
- if(drive->data+len > drive->limit)
- len = drive->limit-drive->data;
- drive->data += len;
- if(drive->data >= drive->limit){
- ctlr->done = 1;
- break;
- }
- if(!(status & Drq)){
- drive->error = Abrt;
- break;
- }
- len = drive->block;
- if(drive->data+len > drive->limit)
- len = drive->limit-drive->data;
- outss(cmdport+Data, drive->data, len/2);
- break;
-
- case Cpkt:
- atapktinterrupt(drive);
- break;
-
- case Crd:
- case Cwd:
- // atadmainterrupt(drive, drive->count*drive->secsize);
- break;
- }
- iunlock(ctlr);
-
- if(drive->error){
- status |= Err;
- ctlr->done = 1;
- }
-
- if(ctlr->done){
- ctlr->curdrive = nil;
- drive->status = status;
- wakeup(ctlr);
- }
-}
-
-static SDev*
-atapnp(void)
-{
- Ctlr *ctlr;
- Pcidev *p;
- int channel, ispc87415, pi, r;
- SDev *legacy[2], *sdev, *head, *tail;
-
- legacy[0] = legacy[1] = head = tail = nil;
- if(sdev = ataprobe(0x1F0, 0x3F4, IrqATA0)){
- head = tail = sdev;
- legacy[0] = sdev;
- }
- if(sdev = ataprobe(0x170, 0x374, IrqATA1)){
- if(head != nil)
- tail->next = sdev;
- else
- head = sdev;
- tail = sdev;
- legacy[1] = sdev;
- }
-
- p = nil;
- while(p = pcimatch(p, 0, 0)){
- /*
- * Look for devices with the correct class and sub-class
- * code and known device and vendor ID; add native-mode
- * channels to the list to be probed, save info for the
- * compatibility mode channels.
- * Note that the legacy devices should not be considered
- * PCI devices by the interrupt controller.
- * For both native and legacy, save info for busmastering
- * if capable.
- * Promise Ultra ATA/66 (PDC20262) appears to
- * 1) give a sub-class of 'other mass storage controller'
- * instead of 'IDE controller', regardless of whether it's
- * the only controller or not;
- * 2) put 0 in the programming interface byte (probably
- * as a consequence of 1) above).
- * Sub-class code 0x04 is 'RAID controller', e.g. VIA VT8237.
- */
- if(p->ccrb != 0x01)
- continue;
- if(p->ccru != 0x01 && p->ccru != 0x04 && p->ccru != 0x80)
- continue;
- pi = p->ccrp;
- ispc87415 = 0;
-
- switch((p->did<<16)|p->vid){
- default:
- continue;
-
- case (0x0002<<16)|0x100B: /* NS PC87415 */
- /*
- * Disable interrupts on both channels until
- * after they are probed for drives.
- * This must be called before interrupts are
- * enabled because the IRQ may be shared.
- */
- ispc87415 = 1;
- pcicfgw32(p, 0x40, 0x00000300);
- break;
- case (0x1000<<16)|0x1042: /* PC-Tech RZ1000 */
- /*
- * Turn off prefetch. Overkill, but cheap.
- */
- r = pcicfgr32(p, 0x40);
- r &= ~0x2000;
- pcicfgw32(p, 0x40, r);
- break;
- case (0x4D38<<16)|0x105A: /* Promise PDC20262 */
- case (0x4D30<<16)|0x105A: /* Promise PDC202xx */
- case (0x4D68<<16)|0x105A: /* Promise PDC20268 */
- case (0x4D69<<16)|0x105A: /* Promise Ultra/133 TX2 */
- case (0x3373<<16)|0x105A: /* Promise 20378 RAID */
- case (0x3149<<16)|0x1106: /* VIA VT8237 SATA/RAID */
- case (0x4379<<16)|0x1002: /* ATI 4379 SATA*/
- case (0x3112<<16)|0x1095: /* SiL 3112 SATA (DMA busted?) */
- case (0x3114<<16)|0x1095: /* SiL 3114 SATA/RAID */
- pi = 0x85;
- break;
- case (0x0004<<16)|0x1103: /* HighPoint HPT-370 */
- pi = 0x85;
- /*
- * Turn off fast interrupt prediction.
- */
- if((r = pcicfgr8(p, 0x51)) & 0x80)
- pcicfgw8(p, 0x51, r & ~0x80);
- if((r = pcicfgr8(p, 0x55)) & 0x80)
- pcicfgw8(p, 0x55, r & ~0x80);
- break;
- case (0x0640<<16)|0x1095: /* CMD 640B */
- /*
- * Bugfix code here...
- */
- break;
- case (0x7441<<16)|0x1022: /* AMD 768 */
- /*
- * Set:
- * 0x41 prefetch, postwrite;
- * 0x43 FIFO configuration 1/2 and 1/2;
- * 0x44 status register read retry;
- * 0x46 DMA read and end of sector flush.
- */
- r = pcicfgr8(p, 0x41);
- pcicfgw8(p, 0x41, r|0xF0);
- r = pcicfgr8(p, 0x43);
- pcicfgw8(p, 0x43, (r & 0x90)|0x2A);
- r = pcicfgr8(p, 0x44);
- pcicfgw8(p, 0x44, r|0x08);
- r = pcicfgr8(p, 0x46);
- pcicfgw8(p, 0x46, (r & 0x0C)|0xF0);
- /*FALLTHROUGH*/
- case (0x7469<<16)|0x1022: /* AMD 3111 */
- /*
- * This can probably be lumped in with the 768 above.
- */
- /*FALLTHROUGH*/
- case (0x209A<<16)|0x1022: /* AMD CS5536 */
- case (0x01BC<<16)|0x10DE: /* nVidia nForce1 */
- case (0x0065<<16)|0x10DE: /* nVidia nForce2 */
- case (0x0085<<16)|0x10DE: /* nVidia nForce2 MCP */
- case (0x00D5<<16)|0x10DE: /* nVidia nForce3 */
- case (0x00E5<<16)|0x10DE: /* nVidia nForce3 Pro */
- case (0x0035<<16)|0x10DE: /* nVidia nForce3 MCP */
- case (0x0053<<16)|0x10DE: /* nVidia nForce4 */
- case (0x0054<<16)|0x10DE: /* nVidia nForce4 SATA */
- case (0x0055<<16)|0x10DE: /* nVidia nForce4 SATA */
- /*
- * Ditto, although it may have a different base
- * address for the registers (0x50?).
- */
- break;
- case (0x0646<<16)|0x1095: /* CMD 646 */
- case (0x0571<<16)|0x1106: /* VIA 82C686 */
- case (0x0211<<16)|0x1166: /* ServerWorks IB6566 */
- case (0x1230<<16)|0x8086: /* 82371FB (PIIX) */
- case (0x7010<<16)|0x8086: /* 82371SB (PIIX3) */
- case (0x7111<<16)|0x8086: /* 82371[AE]B (PIIX4[E]) */
- case (0x2411<<16)|0x8086: /* 82801AA (ICH) */
- case (0x2421<<16)|0x8086: /* 82801AB (ICH0) */
- case (0x244A<<16)|0x8086: /* 82801BA (ICH2, Mobile) */
- case (0x244B<<16)|0x8086: /* 82801BA (ICH2, High-End) */
- case (0x248A<<16)|0x8086: /* 82801CA (ICH3, Mobile) */
- case (0x248B<<16)|0x8086: /* 82801CA (ICH3, High-End) */
- case (0x24CA<<16)|0x8086: /* 82801DBM (ICH4, Mobile) */
- case (0x24CB<<16)|0x8086: /* 82801DB (ICH4, High-End) */
- case (0x24DB<<16)|0x8086: /* 82801EB (ICH5) */
- case (0x266F<<16)|0x8086: /* 82801FB (ICH6) */
- case (0x27C4<<16)|0x8086: /* 82801GBM SATA (ICH7) */
- case (0x27C5<<16)|0x8086: /* 82801GBM SATA AHCI (ICH7) */
- break;
- }
-
- for(channel = 0; channel < 2; channel++){
- if(pi & (1<<(2*channel))){
- sdev = ataprobe(p->mem[0+2*channel].bar & ~0x01,
- p->mem[1+2*channel].bar & ~0x01,
- p->intl);
- if(sdev == nil)
- continue;
-
- ctlr = sdev->ctlr;
- if(ispc87415)
- ctlr->ienable = pc87415ienable;
-
- if(head != nil)
- tail->next = sdev;
- else
- head = sdev;
- tail = sdev;
- ctlr->tbdf = p->tbdf;
- }
- else if((sdev = legacy[channel]) == nil)
- continue;
- else
- ctlr = sdev->ctlr;
-
- ctlr->pcidev = p;
- }
- }
-
- return head;
-}
-
-static SDev*
-atalegacy(int port, int irq)
-{
- return ataprobe(port, port+0x204, irq);
-}
-
-static SDev*
-ataid(SDev* sdev)
-{
- int i;
- Ctlr *ctlr;
-
- /*
- * Legacy controllers are always 'C' and 'D' and if
- * they exist and have drives will be first in the list.
- * If there are no active legacy controllers, native
- * controllers start at 'C'.
- */
- if(sdev == nil)
- return nil;
- ctlr = sdev->ctlr;
- if(ctlr->cmdport == 0x1F0 || ctlr->cmdport == 0x170)
- i = 2;
- else
- i = 0;
- while(sdev){
- if(sdev->ifc == &sdataifc){
- ctlr = sdev->ctlr;
- if(ctlr->cmdport == 0x1F0)
- sdev->idno = 'C';
- else if(ctlr->cmdport == 0x170)
- sdev->idno = 'D';
- else{
- sdev->idno = 'C'+i;
- i++;
- }
- // snprint(sdev->name, NAMELEN, "sd%c", sdev->idno);
- }
- sdev = sdev->next;
- }
-
- return nil;
-}
-
-static int
-ataenable(SDev* sdev)
-{
- Ctlr *ctlr;
-
- ctlr = sdev->ctlr;
-
- setvec(ctlr->irq+VectorPIC, atainterrupt, ctlr);
- outb(ctlr->ctlport+Dc, 0);
- if(ctlr->ienable)
- ctlr->ienable(ctlr);
-
- return 1;
-}
-
-SDifc sdataifc = {
- "ata", /* name */
-
- atapnp, /* pnp */
- atalegacy, /* legacy */
- ataid, /* id */
- ataenable, /* enable */
- nil, /* disable */
-
- scsiverify, /* verify */
- scsionline, /* online */
- atario, /* rio */
- nil, /* rctl */
- nil, /* wctl */
-
- scsibio, /* bio */
-};
--- a/os/boot/pc/sdbios.c
+++ /dev/null
@@ -1,165 +1,0 @@
-/*
- * boot driver for BIOS devices with partitions
- * devbios must be called first
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "error.h"
-
-#include "sd.h"
-#include "fs.h"
-
-long biosread(Fs *, void *, long);
-vlong biosseek(Fs *fs, vlong off);
-
-extern SDifc sdbiosifc;
-extern int onlybios0, biosinited;
-
-int
-biosverify(SDunit* )
-{
- if (onlybios0 || !biosinited)
- return 0;
- return 1;
-}
-
-int
-biosonline(SDunit* unit)
-{
- if (onlybios0 || !biosinited || !unit)
- return 0;
- unit->sectors = 1UL << 30; /* a bunch */
- unit->secsize = 512; /* conventional */
- return 1;
-}
-
-static int
-biosrio(SDreq* r)
-{
- int nb;
- long got;
- vlong len, off;
- uchar *p;
- Fs fs; /* just for fs->dev, which is zero */
-
- if (onlybios0 || !biosinited)
- return SDeio;
- /*
- * Most SCSI commands can be passed unchanged except for
- * the padding on the end. The few which require munging
- * are not used internally. Mode select/sense(6) could be
- * converted to the 10-byte form but it's not worth the
- * effort. Read/write(6) are easy.
- */
- r->rlen = 0;
- r->status = SDok;
- switch(r->cmd[0]){
- case 0x08: /* read */
- case 0x28: /* read */
- if (r->cmd[0] == 0x08)
- panic("biosrio: 0x08 read op\n");
- off = r->cmd[2]<<24 | r->cmd[3]<<16 | r->cmd[4]<<8 | r->cmd[5];
- nb = r->cmd[7]<<8 | r->cmd[8]; /* often 4 */
- USED(nb); /* is nb*512 == r->dlen? */
- memset(&fs, 0, sizeof fs);
- biosseek(&fs, off*512);
- got = biosread(&fs, r->data, r->dlen);
- if (got < 0)
- r->status = SDeio;
- else
- r->rlen = got;
- break;
- case 0x0A: /* write */
- case 0x2A: /* write */
- r->status = SDeio; /* boot programs don't write */
- break;
- case 0x25: /* read capacity */
- /*
- * Read capacity returns the LBA of the last sector.
- */
- len = r->unit->sectors - 1;
- p = r->data;
- *p++ = len>>24;
- *p++ = len>>16;
- *p++ = len>>8;
- *p++ = len;
- len = r->unit->secsize;
- *p++ = len>>24;
- *p++ = len>>16;
- *p++ = len>>8;
- *p = len;
- r->data = (char *)r->data + 8;
- return SDok;
- case 0x9E: /* long read capacity */
- /*
- * Read capacity returns the LBA of the last sector.
- */
- len = r->unit->sectors - 1;
- p = r->data;
- *p++ = len>>56;
- *p++ = len>>48;
- *p++ = len>>40;
- *p++ = len>>32;
- *p++ = len>>24;
- *p++ = len>>16;
- *p++ = len>>8;
- *p++ = len;
- len = r->unit->secsize;
- *p++ = len>>24;
- *p++ = len>>16;
- *p++ = len>>8;
- *p = len;
- r->data = (char *)r->data + 8;
- return SDok;
- /* ignore others */
- }
- return r->status;
-}
-
-SDev*
-biosid(SDev* sdev)
-{
- for (; sdev; sdev = sdev->next)
- if (sdev->ifc == &sdbiosifc)
- sdev->idno = 'B';
- return sdev;
-}
-
-static SDev*
-biospnp(void)
-{
- SDev *sdev;
-
- /* 9pxeload can't use bios int 13 calls; they wedge the machine */
- if (pxe || getconf("*nobiosload") != nil || onlybios0 || !biosinited)
- return nil;
- if((sdev = malloc(sizeof(SDev))) != nil) {
- sdev->ifc = &sdbiosifc;
- sdev->index = -1;
- sdev->nunit = 1;
- }
- return sdev;
-}
-
-SDifc sdbiosifc = {
- "bios", /* name */
-
- biospnp, /* pnp */
- nil, /* legacy */
- biosid, /* id */
- nil, /* enable */
- nil, /* disable */
-
- biosverify, /* verify */
- biosonline, /* online */
- biosrio, /* rio */
- nil, /* rctl */
- nil, /* wctl */
-
- scsibio, /* bio */
-};
--- a/os/boot/pc/sdiahci.c
+++ /dev/null
@@ -1,1668 +1,0 @@
-/*
- * intel/amd ahci (advanced host controller interface) sata controller
- * bootstrap driver
- * copyright © 2007, 2008 coraid, inc.
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "error.h"
-#include "sd.h"
-#include "ahci.h"
-
-#define dprint if(debug==0){}else print
-#define idprint if(prid==0){}else print
-#define aprint if(datapi==0){}else print
-
-enum {
- NCtlr = 2,
- NCtlrdrv= 8,
- NDrive = NCtlr*NCtlrdrv,
-
- Read = 0,
- Write
-};
-
-/* pci space configurtion */
-enum {
- Pmap = 0x90,
- Ppcs = 0x91,
- Prev = 0xa8,
-};
-
-enum {
- Tesb,
- Tich,
- Tsb600,
-};
-
-#define Intel(x) ((x) == Tesb || (x) == Tich)
-
-static char *tname[] = {
- "63xxesb",
- "ich",
- "sb600",
-};
-
-enum {
- Dnull,
- Dmissing,
- Dnew,
- Dready,
- Derror,
- Dreset,
- Doffline,
- Dportreset,
- Dlast
-};
-
-static char *diskstates[Dlast] = {
- "null",
- "missing",
- "new",
- "ready",
- "error",
- "reset",
- "offline",
- "portreset",
-};
-
-extern SDifc sdiahciifc;
-typedef struct Ctlr Ctlr;
-
-enum {
- DMautoneg,
- DMsatai,
- DMsataii,
-};
-
-static char *modename[] = {
- "auto",
- "satai",
- "sataii",
-};
-
-typedef struct {
- Lock;
-
- Ctlr *ctlr;
- SDunit *unit;
- char name[10];
- Aport *port;
- Aportm portm;
- Aportc portc; /* redundant ptr to port and portm. */
-
- uchar mediachange;
- uchar state;
- uchar smartrs;
-
- uvlong sectors;
- ulong intick;
- int wait;
- uchar mode; /* DMautoneg, satai or sataii. */
- uchar active;
-
- char serial[20+1];
- char firmware[8+1];
- char model[40+1];
-
- ushort info[0x200];
-
- int driveno; /* ctlr*NCtlrdrv + unit */
- int portno; /* ctlr port # != drive # when not all ports enabled. */
-} Drive;
-
-struct Ctlr {
- Lock;
-
- int type;
- int enabled;
- SDev *sdev;
- Pcidev *pci;
-
- uchar *mmio;
- ulong *lmmio;
- Ahba *hba;
-
- Drive rawdrive[NCtlrdrv];
- Drive* drive[NCtlrdrv];
- int ndrive;
-};
-
-static Ctlr iactlr[NCtlr];
-static SDev sdevs[NCtlr];
-static int niactlr;
-
-static int prid = 0;
-static int datapi = 0;
-
-static char stab[] = {
-[0] 'i', 'm',
-[8] 't', 'c', 'p', 'e',
-[16] 'N', 'I', 'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
-};
-
-static void
-serrstr(ulong r, char *s, char *e)
-{
- int i;
-
- e -= 3;
- for(i = 0; i < nelem(stab) && s < e; i++)
- if((r & (1<<i)) && stab[i]){
- *s++ = stab[i];
- if(SerrBad & (1<<i))
- *s++ = '*';
- }
- *s = 0;
-}
-
-static char ntab[] = "0123456789abcdef";
-
-static void
-preg(uchar *reg, int n)
-{
- int i;
- char buf[25*3+1], *e;
-
- e = buf;
- for(i = 0; i < n; i++){
- *e++ = ntab[reg[i] >> 4];
- *e++ = ntab[reg[i] & 0xf];
- *e++ = ' ';
- }
- *e++ = '\n';
- *e = 0;
- dprint(buf);
-}
-
-static void
-dreg(char *s, Aport *p)
-{
- dprint("%stask=%lux; cmd=%lux; ci=%lux; is=%lux\n",
- s, p->task, p->cmd, p->ci, p->isr);
-}
-
-static void
-esleep(int ms)
-{
- delay(ms);
-}
-
-typedef struct {
- Aport *p;
- int i;
-} Asleep;
-
-static int
-ahciclear(void *v)
-{
- Asleep *s;
-
- s = v;
- return (s->p->ci & s->i) == 0;
-}
-
-static void
-aesleep(Aportm *, Asleep *a, int ms)
-{
- ulong start;
-
- start = m->ticks;
- while((a->p->ci & a->i) != 0)
- if(TK2MS(m->ticks-start) >= ms)
- break;
-}
-
-static int
-ahciwait(Aportc *c, int ms)
-{
- Aport *p;
- Asleep as;
-
- p = c->p;
- p->ci = 1;
- as.p = p;
- as.i = 1;
- aesleep(c->m, &as, ms);
- if((p->task & 1) == 0 && p->ci == 0)
- return 0;
- dreg("ahciwait timeout ", c->p);
- return -1;
-}
-
-static int
-setfeatures(Aportc *pc, uchar f)
-{
- uchar *c;
- Actab *t;
- Alist *l;
-
- t = pc->m->ctab;
- c = t->cfis;
-
- memset(c, 0, 0x20);
- c[0] = 0x27;
- c[1] = 0x80;
- c[2] = 0xef;
- c[3] = f;
- c[7] = 0xa0; /* obsolete device bits */
-
- l = pc->m->list;
- l->flags = Lwrite|0x5;
- l->len = 0;
- l->ctab = PCIWADDR(t);
- l->ctabhi = 0;
-
- return ahciwait(pc, 3*1000);
-}
-
-static int
-setudmamode(Aportc *pc, uchar f)
-{
- uchar *c;
- Actab *t;
- Alist *l;
-
- t = pc->m->ctab;
- c = t->cfis;
-
- memset(c, 0, 0x20);
- c[0] = 0x27;
- c[1] = 0x80;
- c[2] = 0xef;
- c[3] = 3; /* set transfer mode */
- c[7] = 0xa0; /* obsolete device bits */
- c[12] = 0x40 | f; /* sector count */
-
- l = pc->m->list;
- l->flags = Lwrite | 0x5;
- l->len = 0;
- l->ctab = PCIWADDR(t);
- l->ctabhi = 0;
-
- return ahciwait(pc, 3*1000);
-}
-
-static void
-asleep(int ms)
-{
- delay(ms);
-}
-
-static int
-ahciportreset(Aportc *c)
-{
- ulong *cmd, i;
- Aport *p;
-
- p = c->p;
- cmd = &p->cmd;
- *cmd &= ~(Afre|Ast);
- for(i = 0; i < 500; i += 25){
- if((*cmd & Acr) == 0)
- break;
- asleep(25);
- }
- p->sctl = 1 | (p->sctl & ~7);
- delay(1);
- p->sctl &= ~7;
- return 0;
-}
-
-static ushort
-gbit16(void *a)
-{
- uchar *i;
-
- i = a;
- return i[1]<<8 | i[0];
-}
-
-static ulong
-gbit32(void *a)
-{
- ulong j;
- uchar *i;
-
- i = a;
- j = i[3] << 24;
- j |= i[2] << 16;
- j |= i[1] << 8;
- j |= i[0];
- return j;
-}
-
-static uvlong
-gbit64(void *a)
-{
- uchar *i;
-
- i = a;
- return (uvlong) gbit32(i+4)<<32 | gbit32(a);
-}
-
-static int
-ahciidentify0(Aportc *pc, void *id, int atapi)
-{
- uchar *c;
- Actab *t;
- Alist *l;
- Aprdt *p;
- static uchar tab[] = { 0xec, 0xa1 };
-
- t = pc->m->ctab;
- c = t->cfis;
-
- memset(c, 0, 0x20);
- c[0] = 0x27;
- c[1] = 0x80;
- c[2] = tab[atapi];
- c[7] = 0xa0; /* obsolete device bits */
-
- l = pc->m->list;
- l->flags = 1<<16 | 0x5;
- l->len = 0;
- l->ctab = PCIWADDR(t);
- l->ctabhi = 0;
-
- memset(id, 0, 0x100);
- p = &t->prdt;
- p->dba = PCIWADDR(id);
- p->dbahi = 0;
- p->count = 1<<31 | (0x200-2) | 1;
-
- return ahciwait(pc, 3*1000);
-}
-
-static vlong
-ahciidentify(Aportc *pc, ushort *id)
-{
- int i, sig;
- vlong s;
- Aportm *m;
-
- m = pc->m;
- m->feat = 0;
- m->smart = 0;
- i = 0;
- sig = pc->p->sig >> 16;
- if(sig == 0xeb14){
- m->feat |= Datapi;
- i = 1;
- }
- if(ahciidentify0(pc, id, i) == -1)
- return -1;
-
- i = gbit16(id+83) | gbit16(id+86);
- if(i & (1<<10)){
- m->feat |= Dllba;
- s = gbit64(id+100);
- }else
- s = gbit32(id+60);
-
- if(m->feat & Datapi){
- i = gbit16(id+0);
- if(i & 1)
- m->feat |= Datapi16;
- }
-
- i = gbit16(id+83);
- if((i>>14) != 1)
- return s;
- if(i & (1<<3))
- m->feat |= Dpower;
- i = gbit16(id+82);
- if(i & 1)
- m->feat |= Dsmart;
- if(i & (1<<14))
- m->feat |= Dnop;
- return s;
-}
-
-static int
-ahciquiet(Aport *a)
-{
- ulong *p, i;
-
- p = &a->cmd;
- *p &= ~Ast;
- for(i = 0; i < 500; i += 50){
- if((*p & Acr) == 0)
- goto stop;
- asleep(50);
- }
- return -1;
-stop:
- if((a->task & (ASdrq|ASbsy)) == 0){
- *p |= Ast;
- return 0;
- }
-
- *p |= Aclo;
- for(i = 0; i < 500; i += 50){
- if((*p & Aclo) == 0)
- goto stop1;
- asleep(50);
- }
- return -1;
-stop1:
- /* extra check */
- dprint("clo clear %lx\n", a->task);
- if(a->task & ASbsy)
- return -1;
- *p |= Ast;
- return 0;
-}
-
-static int
-ahciidle(Aport *port)
-{
- ulong *p, i, r;
-
- p = &port->cmd;
- if((*p & Arun) == 0)
- return 0;
- *p &= ~Ast;
- r = 0;
- for(i = 0; i < 500; i += 25){
- if((*p & Acr) == 0)
- goto stop;
- asleep(25);
- }
- r = -1;
-stop:
- if((*p & Afre) == 0)
- return r;
- *p &= ~Afre;
- for(i = 0; i < 500; i += 25){
- if((*p & Afre) == 0)
- return 0;
- asleep(25);
- }
- return -1;
-}
-
-/*
- * §6.2.2.1 first part; comreset handled by reset disk.
- * - remainder is handled by configdisk.
- * - ahcirecover is a quick recovery from a failed command.
- */
-int
-ahciswreset(Aportc *pc)
-{
- int i;
-
- i = ahciidle(pc->p);
- pc->p->cmd |= Afre;
- if(i == -1)
- return -1;
- if(pc->p->task & (ASdrq|ASbsy))
- return -1;
- return 0;
-}
-
-int
-ahcirecover(Aportc *pc)
-{
- ahciswreset(pc);
- pc->p->cmd |= Ast;
- if(setudmamode(pc, 5) == -1)
- return -1;
- return 0;
-}
-
-static void*
-malign(int size, int align)
-{
- void *v;
-
- v = xspanalloc(size, align, 0);
- memset(v, 0, size);
- return v;
-}
-
-static void
-setupfis(Afis *f)
-{
- f->base = malign(0x100, 0x100);
- f->d = f->base + 0;
- f->p = f->base + 0x20;
- f->r = f->base + 0x40;
- f->u = f->base + 0x60;
- f->devicebits = (ulong*)(f->base + 0x58);
-}
-
-static void
-ahciwakeup(Aport *p)
-{
- ushort s;
-
- s = p->sstatus;
- if((s & 0x700) != 0x600)
- return;
- if((s & 7) != 1){
- print("ahci: slumbering drive unwakeable %ux\n", s);
- return;
- }
- p->sctl = 3*Aipm | 0*Aspd | Adet;
- delay(1);
- p->sctl &= ~7;
-// iprint("ahci: wake %ux -> %ux\n", s, p->sstatus);
-}
-
-static int
-ahciconfigdrive(Ahba *h, Aportc *c, int mode)
-{
- Aportm *m;
- Aport *p;
-
- p = c->p;
- m = c->m;
-
- if(m->list == 0){
- setupfis(&m->fis);
- m->list = malign(sizeof *m->list, 1024);
- m->ctab = malign(sizeof *m->ctab, 128);
- }
-
- if(p->sstatus & 3 && h->cap & Hsss){
- dprint("configdrive: spinning up ... [%lux]\n", p->sstatus);
- p->cmd |= Apod|Asud;
- asleep(1400);
- }
-
- p->serror = SerrAll;
-
- p->list = PCIWADDR(m->list);
- p->listhi = 0;
- p->fis = PCIWADDR(m->fis.base);
- p->fishi = 0;
- p->cmd |= Afre | Ast;
-
- if((p->sstatus & 0x707) == 0x601) /* drive coming up in slumbering? */
- ahciwakeup(p);
-
- /* disable power managment sequence from book. */
- p->sctl = (3*Aipm) | (mode*Aspd) | (0*Adet);
- p->cmd &= ~Aalpe;
-
- p->ie = IEM;
-
- return 0;
-}
-
-static int
-ahcienable(Ahba *h)
-{
- h->ghc |= Hie;
- return 0;
-}
-
-static int
-ahcidisable(Ahba *h)
-{
- h->ghc &= ~Hie;
- return 0;
-}
-
-static int
-countbits(ulong u)
-{
- int i, n;
-
- n = 0;
- for(i = 0; i < 32; i++)
- if(u & (1<<i))
- n++;
- return n;
-}
-
-static int
-ahciconf(Ctlr *c)
-{
- ulong u;
- Ahba *h;
- static int count;
-
- h = c->hba = (Ahba*)c->mmio;
- u = h->cap;
-
- if((u & Hsam) == 0)
- h->ghc |= Hae;
-
- print("ahci%d port %#p: hba sss %ld; ncs %ld; coal %ld; mports %ld; "
- "led %ld; clo %ld; ems %ld;\n", count++, h,
- (u>>27) & 1, (u>>8) & 0x1f, (u>>7) & 1, u & 0x1f, (u>>25) & 1,
- (u>>24) & 1, (u>>6) & 1);
- return countbits(h->pi);
-}
-
-static int
-ahcihbareset(Ahba *h)
-{
- int wait;
-
- h->ghc |= 1;
- for(wait = 0; wait < 1000; wait += 100){
- if(h->ghc == 0)
- return 0;
- delay(100);
- }
- return -1;
-}
-
-static void
-idmove(char *p, ushort *a, int n)
-{
- int i;
- char *op, *e;
-
- op = p;
- for(i = 0; i < n/2; i++){
- *p++ = a[i] >> 8;
- *p++ = a[i];
- }
- *p = 0;
- while(p > op && *--p == ' ')
- *p = 0;
- e = p;
- for (p = op; *p == ' '; p++)
- ;
- memmove(op, p, n - (e - p));
-}
-
-static int
-identify(Drive *d)
-{
- ushort *id;
- vlong osectors, s;
- uchar oserial[21];
- SDunit *u;
-
- id = d->info;
- s = ahciidentify(&d->portc, id);
- if(s == -1){
- d->state = Derror;
- return -1;
- }
- osectors = d->sectors;
- memmove(oserial, d->serial, sizeof d->serial);
-
- d->sectors = s;
- d->smartrs = 0;
-
- idmove(d->serial, id+10, 20);
- idmove(d->firmware, id+23, 8);
- idmove(d->model, id+27, 40);
-
- u = d->unit;
- memset(u->inquiry, 0, sizeof u->inquiry);
- u->inquiry[2] = 2;
- u->inquiry[3] = 2;
- u->inquiry[4] = sizeof u->inquiry - 4;
- memmove(u->inquiry+8, d->model, 40);
-
- if((osectors == 0 || osectors != s) &&
- memcmp(oserial, d->serial, sizeof oserial) != 0){
- d->mediachange = 1;
- u->sectors = 0;
- }
-
- return 0;
-}
-
-static void
-clearci(Aport *p)
-{
- if((p->cmd & Ast) == 0)
- return;
- p->cmd &= ~Ast;
- p->cmd |= Ast;
-}
-
-static void
-updatedrive(Drive *d)
-{
- ulong cause, serr, s0, pr, ewake;
- char *name;
- Aport *p;
- static ulong last;
-
- pr = 1;
- ewake = 0;
- p = d->port;
- cause = p->isr;
- serr = p->serror;
- p->isr = cause;
- name = "??";
- if(d->unit && d->unit->name)
- name = d->unit->name;
-
- if(p->ci == 0){
- d->portm.flag |= Fdone;
- pr = 0;
- }else if(cause & Adps)
- pr = 0;
- if(cause&Ifatal){
- ewake = 1;
- dprint("Fatal\n");
- }
- if(cause & Adhrs){
- if(p->task & (32|1)){
- dprint("Adhrs cause = %lux; serr = %lux; task=%lux\n",
- cause, serr, p->task);
- d->portm.flag |= Ferror;
- ewake = 1;
- }
- pr = 0;
- }
-
- if(pr)
- dprint("%s: upd %lux ta %lux\n", name, cause, p->task);
- if(cause & (Aprcs|Aifs)){
- s0 = d->state;
- switch(p->sstatus & 7){
- case 0:
- d->state = Dmissing;
- break;
- case 1:
- if((p->sstatus & 0x700) == 0x600)
- d->state = Dnew;
- else
- d->state = Derror;
- break;
- case 3:
- /* power mgnt crap for surprise removal */
- p->ie |= Aprcs | Apcs; /* is this required? */
- d->state = Dreset;
- break;
- case 4:
- d->state = Doffline;
- break;
- }
- dprint("%s: %s → %s [Apcrs] %lux\n", name, diskstates[s0],
- diskstates[d->state], p->sstatus);
- if(s0 == Dready && d->state != Dready)
- idprint("%s: pulled\n", name);
- if(d->state != Dready)
- d->portm.flag |= Ferror;
- ewake = 1;
- }
- p->serror = serr;
- if(ewake)
- clearci(p);
- last = cause;
-}
-
-static void
-pstatus(Drive *d, ulong s)
-{
- /*
- * bogus code because the first interrupt is currently dropped.
- * likely my fault. serror may be cleared at the wrong time.
- */
- switch(s){
- case 0:
- d->state = Dmissing;
- break;
- case 2: /* should this be missing? need testcase. */
- dprint("pstatus 2\n");
- case 3:
- d->wait = 0;
- d->state = Dnew;
- break;
- case 4:
- d->state = Doffline;
- break;
- case 6:
- d->state = Dnew;
- break;
- }
-}
-
-static int
-configdrive(Drive *d)
-{
- if(ahciconfigdrive(d->ctlr->hba, &d->portc, d->mode) == -1)
- return -1;
- ilock(d);
- pstatus(d, d->port->sstatus & 7);
- iunlock(d);
- return 0;
-}
-
-static void
-resetdisk(Drive *d)
-{
- uint state, det, stat;
- Aport *p;
-
- p = d->port;
- det = p->sctl & 7;
- stat = p->sstatus & 7;
- state = (p->cmd>>28) & 0xf;
- dprint("resetdisk: icc %ux det %d sdet %d\n", state, det, stat);
- if(stat != 3){
- ilock(d);
- d->state = Dportreset;
- iunlock(d);
- return;
- }
- ilock(d);
- state = d->state;
- if(d->state != Dready || d->state != Dnew)
- d->portm.flag |= Ferror;
- clearci(p); /* satisfy sleep condition. */
- iunlock(d);
-
- qlock(&d->portm);
-
- if(p->cmd & Ast && ahciswreset(&d->portc) == -1){
- ilock(d);
- d->state = Dportreset; /* get a bigger stick. */
- iunlock(d);
- } else {
- ilock(d);
- d->state = Dmissing;
- iunlock(d);
-
- configdrive(d);
- }
- dprint("resetdisk: %s → %s\n", diskstates[state], diskstates[d->state]);
- qunlock(&d->portm);
-}
-
-static int
-newdrive(Drive *d)
-{
- char *name, *s;
- Aportc *c;
- Aportm *m;
-
- c = &d->portc;
- m = &d->portm;
-
- name = d->unit->name;
- if(name == 0)
- name = "??";
-
- if(d->port->task == 0x80)
- return -1;
- qlock(c->m);
- if(setudmamode(c, 5) == -1){
- dprint("%s: can't set udma mode\n", name);
- goto lose;
- }
- if(identify(d) == -1){
- dprint("%s: identify failure\n", name);
- goto lose;
- }
- if(m->feat & Dpower && setfeatures(c, 0x85) == -1){
- m->feat &= ~Dpower;
- if(ahcirecover(c) == -1) {
- dprint("%s: ahcirecover failed\n", name);
- goto lose;
- }
- }
-
- ilock(d);
- d->state = Dready;
- iunlock(d);
-
- qunlock(c->m);
-
- s = "";
- if(m->feat & Dllba)
- s = "L";
- idprint("%s: %sLBA %lld sectors\n", d->unit->name, s, d->sectors);
- idprint(" %s %s %s %s\n", d->model, d->firmware, d->serial,
- d->mediachange? "[mediachange]": "");
-
- return 0;
-
-lose:
- qunlock(&d->portm);
- return -1;
-}
-
-enum {
- Nms = 256,
- Mphywait = 2*1024/Nms - 1,
- Midwait = 16*1024/Nms - 1,
- Mcomrwait = 64*1024/Nms - 1,
-};
-
-static void
-westerndigitalhung(Drive *d)
-{
- if((d->portm.feat & Datapi) == 0 && d->active &&
- TK2MS(m->ticks - d->intick) > 5000){
- dprint("%s: drive hung; resetting [%lux] ci=%lx\n",
- d->unit->name, d->port->task, d->port->ci);
- d->state = Dreset;
- }
-}
-
-static ushort olds[NCtlr*NCtlrdrv];
-
-static int
-doportreset(Drive *d)
-{
- int i;
-
- i = -1;
- qlock(&d->portm);
- if(ahciportreset(&d->portc) == -1)
- dprint("ahciportreset fails\n");
- else
- i = 0;
- qunlock(&d->portm);
- dprint("portreset → %s [task %lux]\n", diskstates[d->state],
- d->port->task);
- return i;
-}
-
-static void
-checkdrive(Drive *d, int i)
-{
- ushort s;
- char *name;
-
- ilock(d);
- name = d->unit->name;
- s = d->port->sstatus;
- if(s != olds[i]){
- dprint("%s: status: %#ux -> %#ux: %s\n", name, olds[i],
- s, diskstates[d->state]);
- olds[i] = s;
- d->wait = 0;
- }
- westerndigitalhung(d);
- switch(d->state){
- case Dnull:
- break;
- case Dmissing:
- case Dnew:
- switch(s & 0x107){
- case 1:
- ahciwakeup(d->port);
- case 0:
- break;
- default:
- dprint("%s: unknown status %04ux\n", name, s);
- case 0x100:
- if(++d->wait&Mphywait)
- break;
-reset:
- if(++d->mode > DMsataii)
- d->mode = 0;
- if(d->mode == DMsatai){ /* we tried everything */
- d->state = Dportreset;
- goto portreset;
- }
- dprint("%s: reset; new mode %s\n", name,
- modename[d->mode]);
- iunlock(d);
- resetdisk(d);
- ilock(d);
- break;
- case 0x103:
- if((++d->wait&Midwait) == 0){
- dprint("%s: slow reset %#ux task=%#lux; %d\n",
- name, s, d->port->task, d->wait);
- goto reset;
- }
- s = d->port->task&0xff;
- if(s == 0x7f || ((d->port->sig>>16) != 0xeb14 &&
- (s & ~0x17) != (1<<6)))
- break;
- iunlock(d);
- newdrive(d);
- ilock(d);
- break;
- }
- break;
- case Doffline:
- if(d->wait++ & Mcomrwait)
- break;
- case Derror:
- case Dreset:
- dprint("%s: reset [%s]: mode %d; status %#ux\n",
- name, diskstates[d->state], d->mode, s);
- iunlock(d);
- resetdisk(d);
- ilock(d);
- break;
- case Dportreset:
-portreset:
- if(d->wait++ & 0xff && (s & 0x100) == 0)
- break;
- dprint("%s: portreset [%s]: mode %d; status %04ux\n",
- name, diskstates[d->state], d->mode, s);
- d->portm.flag |= Ferror;
- clearci(d->port);
- if((s & 7) == 0){
- d->state = Dmissing;
- break;
- }
- iunlock(d);
- doportreset(d);
- ilock(d);
- break;
- }
- iunlock(d);
-}
-
-static void
-iainterrupt(Ureg*, void *a)
-{
- int i;
- ulong cause, m;
- Ctlr *c;
- Drive *d;
-
- c = a;
- ilock(c);
- /* check drive here! */
- cause = c->hba->isr;
- for(i = 0; i < c->ndrive; i++){
- m = 1 << i;
- if((cause & m) == 0)
- continue;
- d = c->rawdrive + i;
- ilock(d);
- if(d->port->isr && c->hba->pi & m)
- updatedrive(d);
- c->hba->isr = m;
- iunlock(d);
- }
- iunlock(c);
-}
-
-static int
-iaverify(SDunit *u)
-{
- int i;
- Ctlr *c;
- Drive *d;
-
- c = u->dev->ctlr;
- d = c->drive[u->subno];
- ilock(c);
- ilock(d);
- d->unit = u;
- iunlock(d);
- iunlock(c);
- for(i = 0; i < 10; i++){
- checkdrive(d, d->driveno);
- switch(d->state){
- case Dmissing:
- if(i < 4 || d->port->sstatus & 0x733)
- break;
- /* fall through */
- case Dnull:
- case Dready:
- case Doffline:
- print("sdiahci: drive %d in state %s after %d resets\n",
- d->driveno, diskstates[d->state], i);
- return 1;
- }
- delay(100);
- }
- print("sdiahci: drive %d won't come up; in state %s after %d resets\n",
- d->driveno, diskstates[d->state], i);
- return 1;
-}
-
-static int
-iaenable(SDev *s)
-{
- Ctlr *c;
-
- c = s->ctlr;
- ilock(c);
- if(!c->enabled) {
- if(c->ndrive == 0)
- panic("iaenable: zero s->ctlr->ndrive");
- pcisetbme(c->pci);
- setvec(c->pci->intl+VectorPIC, iainterrupt, c);
- /* supposed to squelch leftover interrupts here. */
- ahcienable(c->hba);
- c->enabled = 1;
- }
- iunlock(c);
- return 1;
-}
-
-static int
-iadisable(SDev *s)
-{
- Ctlr *c;
-
- c = s->ctlr;
- ilock(c);
- ahcidisable(c->hba);
-// intrdisable(c->irq, iainterrupt, c, c->tbdf, name);
- c->enabled = 0;
- iunlock(c);
- return 1;
-}
-
-static int
-iaonline(SDunit *unit)
-{
- int r;
- Ctlr *c;
- Drive *d;
-
- c = unit->dev->ctlr;
- d = c->drive[unit->subno];
- r = 0;
-
- if(d->portm.feat & Datapi && d->mediachange){
- r = scsionline(unit);
- if(r > 0)
- d->mediachange = 0;
- return r;
- }
-
- ilock(d);
- if(d->mediachange){
- r = 2;
- d->mediachange = 0;
- /* devsd resets this after online is called; why? */
- unit->sectors = d->sectors;
- unit->secsize = 512;
- } else if(d->state == Dready)
- r = 1;
- iunlock(d);
- return r;
-}
-
-/* returns locked list! */
-static Alist*
-ahcibuild(Aportm *m, uchar *cmd, void *data, int n, vlong lba)
-{
- uchar *c, acmd, dir, llba;
- Alist *l;
- Actab *t;
- Aprdt *p;
- static uchar tab[2][2] = { 0xc8, 0x25, 0xca, 0x35 };
-
- dir = *cmd != 0x28;
- llba = m->feat & Dllba? 1: 0;
- acmd = tab[dir][llba];
- qlock(m);
- l = m->list;
- t = m->ctab;
- c = t->cfis;
-
- c[0] = 0x27;
- c[1] = 0x80;
- c[2] = acmd;
- c[3] = 0;
-
- c[4] = lba; /* sector lba low 7:0 */
- c[5] = lba >> 8; /* cylinder low lba mid 15:8 */
- c[6] = lba >> 16; /* cylinder hi lba hi 23:16 */
- c[7] = 0xa0 | 0x40; /* obsolete device bits + lba */
- if(llba == 0)
- c[7] |= (lba>>24) & 7;
-
- c[8] = lba >> 24; /* sector (exp) lba 31:24 */
- c[9] = lba >> 32; /* cylinder low (exp) lba 39:32 */
- c[10] = lba >> 48; /* cylinder hi (exp) lba 48:40 */
- c[11] = 0; /* features (exp); */
-
- c[12] = n; /* sector count */
- c[13] = n >> 8; /* sector count (exp) */
- c[14] = 0; /* r */
- c[15] = 0; /* control */
-
- *(ulong*)(c+16) = 0;
-
- l->flags = 1<<16 | Lpref | 0x5; /* Lpref ?? */
- if(dir == Write)
- l->flags |= Lwrite;
- l->len = 0;
- l->ctab = PCIWADDR(t);
- l->ctabhi = 0;
-
- p = &t->prdt;
- p->dba = PCIWADDR(data);
- p->dbahi = 0;
- p->count = 1<<31 | (512*n - 2) | 1;
-
- return l;
-}
-
-static Alist*
-ahcibuildpkt(Aportm *m, SDreq *r, void *data, int n)
-{
- int fill, len;
- uchar *c;
- Actab *t;
- Alist *l;
- Aprdt *p;
-
- qlock(m);
- l = m->list;
- t = m->ctab;
- c = t->cfis;
-
- fill = m->feat & Datapi16? 16: 12;
- if((len = r->clen) > fill)
- len = fill;
- memmove(t->atapi, r->cmd, len);
- memset(t->atapi + len, 0, fill - len);
-
- c[0] = 0x27;
- c[1] = 0x80;
- c[2] = 0xa0;
- if(n != 0)
- c[3] = 1; /* dma */
- else
- c[3] = 0; /* features (exp); */
-
- c[4] = 0; /* sector lba low 7:0 */
- c[5] = n; /* cylinder low lba mid 15:8 */
- c[6] = n >> 8; /* cylinder hi lba hi 23:16 */
- c[7] = 0xa0; /* obsolete device bits */
-
- *(ulong*)(c+8) = 0;
- *(ulong*)(c+12) = 0;
- *(ulong*)(c+16) = 0;
-
- l->flags = 1<<16 | Lpref | Latapi | 0x5;
- if(r->write != 0 && data)
- l->flags |= Lwrite;
- l->len = 0;
- l->ctab = PCIWADDR(t);
- l->ctabhi = 0;
-
- if(data == 0)
- return l;
-
- p = &t->prdt;
- p->dba = PCIWADDR(data);
- p->dbahi = 0;
- p->count = 1<<31 | (n - 2) | 1;
-
- return l;
-}
-
-static int
-waitready(Drive *d)
-{
- ulong s, t, i;
-
- for(i = 0; i < 120; i++){
- ilock(d);
- s = d->port->sstatus;
- t = d->port->task;
- iunlock(d);
- if((s & 0x100) == 0)
- return -1;
- if(d->state == Dready && (s & 7) == 3)
- return 0;
- if((i + 1) % 30 == 0)
- print("%s: waitready: [%s] task=%lux sstat=%lux\n",
- d->unit->name, diskstates[d->state], t, s);
- esleep(1000);
- }
- print("%s: not responding; offline\n", d->unit->name);
- ilock(d);
- d->state = Doffline;
- iunlock(d);
- return -1;
-}
-
-static int
-iariopkt(SDreq *r, Drive *d)
-{
- int n, count, try, max, flag, task;
- char *name;
- uchar *cmd, *data;
- Aport *p;
- Asleep as;
-
- cmd = r->cmd;
- name = d->unit->name;
- p = d->port;
-
- aprint("%02ux %02ux %c %d %p\n", cmd[0], cmd[2], "rw"[r->write],
- r->dlen, r->data);
-// if(cmd[0] == 0x5a && (cmd[2] & 0x3f) == 0x3f)
-// return sdmodesense(r, cmd, d->info, sizeof d->info);
- r->rlen = 0;
- count = r->dlen;
- max = 65536;
-
- try = 0;
-retry:
- if(waitready(d) == -1)
- return SDeio;
- data = r->data;
- n = count;
- if(n > max)
- n = max;
- d->active++;
- ahcibuildpkt(&d->portm, r, data, n);
- ilock(d);
- d->portm.flag = 0;
- iunlock(d);
- p->ci = 1;
-
- as.p = p;
- as.i = 1;
- d->intick = m->ticks;
-
- while(ahciclear(&as) == 0)
- ;
-
- ilock(d);
- flag = d->portm.flag;
- task = d->port->task;
- iunlock(d);
-
- if(task & (Efatal<<8) || task & (ASbsy|ASdrq) && d->state == Dready){
- d->port->ci = 0; /* @? */
- ahcirecover(&d->portc);
- task = d->port->task;
- }
- d->active--;
- qunlock(&d->portm);
- if(flag == 0){
- if(++try == 10){
- print("%s: bad disk\n", name);
- r->status = SDcheck;
- return SDcheck;
- }
- print("%s: retry\n", name);
- esleep(1000);
- goto retry;
- }
- if(flag & Ferror){
- if((task & Eidnf) == 0)
- print("%s: i/o error %ux\n", name, task);
- r->status = SDcheck;
- return SDcheck;
- }
-
- data += n;
-
- r->rlen = data - (uchar*)r->data;
- r->status = SDok;
- return SDok;
-}
-
-static int
-iario(SDreq *r)
-{
- int n, count, max, flag, task;
- vlong lba;
- char *name;
- uchar *cmd, *data;
- Aport *p;
- Asleep as;
- Ctlr *c;
- Drive *d;
- SDunit *unit;
-
- unit = r->unit;
- c = unit->dev->ctlr;
- d = c->drive[unit->subno];
- if(d->portm.feat & Datapi)
- return iariopkt(r, d);
- cmd = r->cmd;
- name = d->unit->name;
- p = d->port;
-
-// if((i = sdfakescsi(r, d->info, sizeof d->info)) != SDnostatus){
-// r->status = i;
-// return i;
-// }
-
- if(*cmd != 0x28 && *cmd != 0x2a){
- print("%s: bad cmd 0x%.2ux\n", name, cmd[0]);
- r->status = SDcheck;
- return SDcheck;
- }
-
- lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];
- count = cmd[7]<<8 | cmd[8];
- if(r->data == nil)
- return SDok;
- if(r->dlen < count * unit->secsize)
- count = r->dlen / unit->secsize;
- max = 128;
-
- if(waitready(d) == -1)
- return SDeio;
- data = r->data;
- while(count > 0){
- n = count;
- if(n > max)
- n = max;
- d->active++;
- ahcibuild(&d->portm, cmd, data, n, lba);
- ilock(d);
- d->portm.flag = 0;
- iunlock(d);
- p->ci = 1;
-
- as.p = p;
- as.i = 1;
- d->intick = m->ticks;
-
- while(ahciclear(&as) == 0)
- ;
-
- ilock(d);
- flag = d->portm.flag;
- task = d->port->task;
- iunlock(d);
-
- if(task & (Efatal<<8) ||
- task & (ASbsy|ASdrq) && d->state == Dready){
- d->port->ci = 0; /* @? */
- ahcirecover(&d->portc);
- task = d->port->task;
- }
- d->active--;
- qunlock(&d->portm);
- if(flag == 0 || flag & Ferror){
- print("%s: i/o error %ux @%lld\n", name, task, lba);
- r->status = SDeio;
- return SDeio;
- }
-
- count -= n;
- lba += n;
- data += n * unit->secsize;
- }
- r->rlen = data - (uchar*)r->data;
- r->status = SDok;
- return SDok;
-}
-
-/*
- * configure drives 0-5 as ahci sata (c.f. errata)
- */
-static int
-iaahcimode(Pcidev *p)
-{
- dprint("iaahcimode %ux %ux %ux\n", pcicfgr8(p, 0x91),
- pcicfgr8(p, 92), pcicfgr8(p, 93));
- pcicfgw16(p, 0x92, pcicfgr32(p, 0x92) | 0xf); /* ports 0-3 */
-// pcicfgw8(p, 0x93, pcicfgr32(p, 9x93) | 3); /* ports 4-5 */
- return 0;
-}
-
-static void
-iasetupahci(Ctlr *c)
-{
- /* disable cmd block decoding. */
- pcicfgw16(c->pci, 0x40, pcicfgr16(c->pci, 0x40) & ~(1<<15));
- pcicfgw16(c->pci, 0x42, pcicfgr16(c->pci, 0x42) & ~(1<<15));
-
- c->lmmio[0x4/4] |= 1 << 31; /* enable ahci mode (ghc register) */
- c->lmmio[0xc/4] = (1<<6) - 1; /* five ports (supposedly ro pi reg) */
-
- /* enable ahci mode; from ich9 datasheet */
- pcicfgw8(c->pci, 0x90, 1<<6 | 1<<5);
-}
-
-static SDev*
-iapnp(void)
-{
- int i, n, nunit, type;
- ulong io;
- Ctlr *c;
- Drive *d;
- Pcidev *p;
- SDev *head, *tail, *s;
- static int done;
-
- if (done || getconf("*noahciload") != nil)
- return nil;
- done = 1;
- p = nil;
- head = tail = nil;
-loop:
- while((p = pcimatch(p, 0, 0)) != nil){
- if(p->vid == 0x8086 && (p->did & 0xfffc) == 0x2680)
- type = Tesb;
- else if(p->vid == 0x8086 && p->did == 0x27c5)
- type = Tich; /* 82801g[bh]m; compat mode fails */
- else if(p->vid == 0x8086 && (p->did & 0xfeff) == 0x2829)
- type = Tich; /* ich8 */
- else if(p->vid == 0x8086 && (p->did & 0xfffe) == 0x2922)
- type = Tich; /* ich8 */
- else if(p->vid == 0x1002 && p->did == 0x4380)
- type = Tsb600;
- else
- continue;
- if(niactlr == NCtlr){
- print("iapnp: %s: too many controllers\n", tname[type]);
- break;
- }
- c = iactlr + niactlr;
- s = sdevs + niactlr;
- memset(c, 0, sizeof *c);
- memset(s, 0, sizeof *s);
- c->pci = p;
- c->type = type;
- io = p->mem[Abar].bar & ~0xf;
- io = upamalloc(io, p->mem[Abar].size, 0);
- if(io == 0){
- print("%s: address %#lux in use, did %#ux\n",
- tname[c->type], io, p->did);
- continue;
- }
- /* ugly hack: get this in compatibility mode; see memory.c:271 */
- if(io == 0x40000000) {
- print("%s: did %#ux is in non-sata mode. bar %#lux\n",
- tname[c->type], p->did, p->mem[Abar].bar);
- continue;
- }
- c->mmio = KADDR(io);
- c->lmmio = (ulong*)c->mmio;
- if(Intel(c->type) && p->did != 0x2681)
- iasetupahci(c);
- nunit = ahciconf(c);
-// ahcihbareset((Ahba*)c->mmio);
- if(Intel(c->type) && iaahcimode(p) == -1)
- break;
- if(nunit < 1){
-// vunmap(c->mmio, p->mem[Abar].size);
- continue;
- }
- niactlr++;
- i = (c->hba->cap>>21) & 1;
- print("%s: sata-%s with %d ports\n", tname[c->type],
- "I\0II"+i*2, nunit);
- s->ifc = &sdiahciifc;
- s->ctlr = c;
- s->nunit = nunit;
- s->idno = 'E';
- c->sdev = s;
- c->ndrive = nunit;
-
- /* map the drives -- they don't all need to be enabled. */
- memset(c->rawdrive, 0, sizeof c->rawdrive);
- n = 0;
- for(i = 0; i < NCtlrdrv; i++) {
- d = c->rawdrive+i;
- d->portno = i;
- d->driveno = -1;
- d->sectors = 0;
- d->ctlr = c;
- if((c->hba->pi & (1<<i)) == 0)
- continue;
-// d->state = Dnew;
- d->port = (Aport*)(c->mmio + 0x80*i + 0x100);
- d->portc.p = d->port;
- d->portc.m = &d->portm;
- d->driveno = n++;
- c->drive[d->driveno] = d;
- }
- for(i = 0; i < n; i++)
- if(ahciidle(c->drive[i]->port) == -1){
- print("%s: port %d wedged; abort\n",
- tname[c->type], i);
- goto loop;
- }
- for(i = 0; i < n; i++){
- c->drive[i]->mode = DMsatai;
- configdrive(c->drive[i]);
- }
-
- if(head)
- tail->next = s;
- else
- head = s;
- tail = s;
- }
- return head;
-}
-
-static SDev*
-iaid(SDev* sdev)
-{
- int i;
- Ctlr *c;
-
- for(; sdev; sdev = sdev->next){
- if(sdev->ifc != &sdiahciifc)
- continue;
- c = sdev->ctlr;
- for(i = 0; i < NCtlr; i++)
- if(c == iactlr + i)
- sdev->idno = 'E' + i;
- }
- return nil;
-}
-
-SDifc sdiahciifc = {
- "iahci",
-
- iapnp,
- nil, /* legacy */
- iaid,
- iaenable,
- iadisable,
-
- iaverify,
- iaonline,
- iario,
- nil,
- nil,
-
- scsibio,
-};
--- a/os/boot/pc/sdmylex.c
+++ /dev/null
@@ -1,1292 +1,0 @@
-/*
- * Mylex MultiMaster (Buslogic BT-*) SCSI Host Adapter
- * in both 24-bit and 32-bit mode.
- * 24-bit mode works for Adaptec AHA-154xx series too.
- *
- * To do:
- * allocate more Ccb's as needed, up to NMbox-1;
- * add nmbox and nccb to Ctlr struct for the above;
- * 64-bit LUN/explicit wide support necessary?
- *
- */
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "error.h"
-
-#include "sd.h"
-
-#define waserror() (0)
-#define poperror()
-typedef struct QLock{ int r; } QLock;
-typedef struct Rendez{ int r; } Rendez;
-#define intrenable(irq, f, c, tbdf, name) setvec(VectorPIC+(irq), f, c);\
- USED(tbdf);
-
-#define K2BPA(va, tbdf) PADDR(va)
-#define BPA2K(pa, tbdf) KADDR(pa)
-
-extern SDifc sdmylexifc;
-
-enum { /* registers */
- Rcontrol = 0x00, /* WO: control register */
- Rstatus = 0x00, /* RO: status register */
- Rcpr = 0x01, /* WO: command/parameter register */
- Rdatain = 0x01, /* RO: data-in register */
- Rinterrupt = 0x02, /* RO: interrupt register */
-};
-
-enum { /* Rcontrol */
- Rsbus = 0x10, /* SCSI Bus Reset */
- Rint = 0x20, /* Interrupt Reset */
- Rsoft = 0x40, /* Soft Reset */
- Rhard = 0x80, /* Hard Reset */
-};
-
-enum { /* Rstatus */
- Cmdinv = 0x01, /* Command Invalid */
- Dirrdy = 0x04, /* Data In Register Ready */
- Cprbsy = 0x08, /* Command/Parameter Register Busy */
- Hardy = 0x10, /* Host Adapter Ready */
- Inreq = 0x20, /* Initialisation Required */
- Dfail = 0x40, /* Diagnostic Failure */
- Dact = 0x80, /* Diagnostic Active */
-};
-
-enum { /* Rcpr */
- Cinitialise = 0x01, /* Initialise Mailbox */
- Cstart = 0x02, /* Start Mailbox Command */
- Cinquiry = 0x04, /* Adapter Inquiry */
- Ceombri = 0x05, /* Enable OMBR Interrupt */
- Cinquire = 0x0B, /* Inquire Configuration */
- Cextbios = 0x28, /* AHA-1542: extended BIOS info. */
- Cmbienable = 0x29, /* AHA-1542: Mailbox interface enable */
- Ciem = 0x81, /* Initialise Extended Mailbox */
- Ciesi = 0x8D, /* Inquire Extended Setup Information */
- Cerrm = 0x8F, /* Enable strict round-robin mode */
- Cwide = 0x96, /* Wide CCB */
-};
-
-enum { /* Rinterrupt */
- Imbl = 0x01, /* Incoming Mailbox Loaded */
- Mbor = 0x02, /* Mailbox Out Ready */
- Cmdc = 0x04, /* Command Complete */
- Rsts = 0x08, /* SCSI Reset State */
- Intv = 0x80, /* Interrupt Valid */
-};
-
-typedef struct {
- uchar code; /* action/completion code */
- uchar ccb[3]; /* CCB pointer (MSB, ..., LSB) */
-} Mbox24;
-
-typedef struct {
- uchar ccb[4]; /* CCB pointer (LSB, ..., MSB) */
- uchar btstat; /* BT-7[45]7[SD] status */
- uchar sdstat; /* SCSI device status */
- uchar pad;
- uchar code; /* action/completion code */
-} Mbox32;
-
-enum { /* mailbox commands */
- Mbfree = 0x00, /* Mailbox not in use */
-
- Mbostart = 0x01, /* Start a mailbox command */
- Mboabort = 0x02, /* Abort a mailbox command */
-
- Mbiok = 0x01, /* CCB completed without error */
- Mbiabort = 0x02, /* CCB aborted at request of host */
- Mbinx = 0x03, /* Aborted CCB not found */
- Mbierror = 0x04, /* CCB completed with error */
-};
-
-typedef struct Ccb24 Ccb24;
-typedef struct Ccb32 Ccb32;
-typedef union Ccb Ccb;
-
-typedef struct Ccb24 {
- uchar opcode; /* Operation code */
- uchar datadir; /* Data direction control */
- uchar cdblen; /* Length of CDB */
- uchar senselen; /* Length of sense area */
- uchar datalen[3]; /* Data length (MSB, ..., LSB) */
- uchar dataptr[3]; /* Data pointer (MSB, ..., LSB) */
- uchar linkptr[3]; /* Link pointer (MSB, ..., LSB) */
- uchar linkid; /* command linking identifier */
- uchar btstat; /* BT-* adapter status */
- uchar sdstat; /* SCSI device status */
- uchar reserved[2]; /* */
- uchar cs[12+0xFF]; /* Command descriptor block + Sense */
-
- void* data; /* buffer if address > 24-bits */
-
- Rendez;
- int done; /* command completed */
-
- Ccb* ccb; /* link on free list */
-} Ccb24;
-
-
-typedef struct Ccb32 {
- uchar opcode; /* Operation code */
- uchar datadir; /* Data direction control */
- uchar cdblen; /* Length of CDB */
- uchar senselen; /* Length of sense area */
- uchar datalen[4]; /* Data length (LSB, ..., MSB) */
- uchar dataptr[4]; /* Data pointer (LSB, ..., MSB) */
- uchar reserved[2];
- uchar btstat; /* BT-* adapter status */
- uchar sdstat; /* SCSI device status */
- uchar targetid; /* Target ID */
- uchar luntag; /* LUN & tag */
- uchar cdb[12]; /* Command descriptor block */
- uchar ccbctl; /* CCB control */
- uchar linkid; /* command linking identifier */
- uchar linkptr[4]; /* Link pointer (LSB, ..., MSB) */
- uchar senseptr[4]; /* Sense pointer (LSB, ..., MSB) */
- uchar sense[0xFF]; /* Sense bytes */
-
- Rendez;
- int done; /* command completed */
-
- Ccb* ccb; /* link on free list */
-} Ccb32;
-
-typedef union Ccb {
- Ccb24;
- Ccb32;
-} Ccb;
-
-enum { /* opcode */
- OInitiator = 0x00, /* initiator CCB */
- Ordl = 0x03, /* initiator CCB with
- * residual data length returned
- */
-};
-
-enum { /* datadir */
- CCBdatain = 0x08, /* inbound, length is checked */
- CCBdataout = 0x10, /* outbound, length is checked */
-};
-
-enum { /* btstat */
- Eok = 0x00, /* normal completion with no errors */
-};
-
-enum { /* luntag */
- TagEnable = 0x20, /* Tag enable */
- SQTag = 0x00, /* Simple Queue Tag */
- HQTag = 0x40, /* Head of Queue Tag */
- OQTag = 0x80, /* Ordered Queue Tag */
-};
-
-enum { /* CCB control */
- NoDisc = 0x08, /* No disconnect */
- NoUnd = 0x10, /* No underrrun error report */
- NoData = 0x20, /* No data transfer */
- NoStat = 0x40, /* No CCB status if zero */
- NoIntr = 0x80, /* No Interrupts */
-};
-
-typedef struct {
- int port; /* I/O port */
- int id; /* adapter SCSI id */
- int bus; /* 24 or 32 -bit */
- int irq;
- int wide;
- Pcidev* pcidev;
- SDev* sdev;
- int spurious;
-
- Lock issuelock;
-
- Lock ccblock;
- QLock ccbq;
- Rendez ccbr;
-
- Lock mboxlock;
- void* mb; /* mailbox out + mailbox in */
- int mbox; /* current mailbox out index into mb */
- int mbix; /* current mailbox in index into mb */
-
- Lock cachelock;
- Ccb* ccb; /* list of free Ccb's */
- Ccb** cache; /* last completed Ccb */
-} Ctlr;
-
-/*
- * The number of mailboxes should be a multiple of 8 (4 for Mbox32)
- * to ensure the boundary between the out and in mailboxes doesn't
- * straddle a cache-line boundary.
- * The number of Ccb's should be less than the number of mailboxes to
- * ensure no queueing is necessary on mailbox allocation.
- */
-enum {
- NMbox = 8*8, /* number of Mbox's */
- NCcb = NMbox-1, /* number of Ccb's */
-};
-
-#define PADDR24(a, n) ((PADDR(a)+(n)) <= (1<<24))
-
-static void
-ccbfree(Ctlr* ctlr, Ccb* ccb)
-{
- lock(&ctlr->ccblock);
- if(ctlr->bus == 24)
- ((Ccb24*)ccb)->ccb = ctlr->ccb;
- else
- ((Ccb32*)ccb)->ccb = ctlr->ccb;
- if(ctlr->ccb == nil)
- wakeup(&ctlr->ccbr);
- ctlr->ccb = ccb;
- unlock(&ctlr->ccblock);
-}
-
-static int
-ccbavailable(void* a)
-{
- return ((Ctlr*)a)->ccb != nil;
-}
-
-static Ccb*
-ccballoc(Ctlr* ctlr)
-{
- Ccb *ccb;
-
- for(;;){
- lock(&ctlr->ccblock);
- if((ccb = ctlr->ccb) != nil){
- if(ctlr->bus == 24)
- ctlr->ccb = ((Ccb24*)ccb)->ccb;
- else
- ctlr->ccb = ((Ccb32*)ccb)->ccb;
- unlock(&ctlr->ccblock);
- break;
- }
-
- unlock(&ctlr->ccblock);
- qlock(&ctlr->ccbq);
- if(waserror()){
- qunlock(&ctlr->ccbq);
- continue;
- }
- sleep(&ctlr->ccbr, ccbavailable, ctlr);
- qunlock(&ctlr->ccbq);
- poperror();
- }
-
- return ccb;
-}
-
-static int
-done24(void* arg)
-{
- return ((Ccb24*)arg)->done;
-}
-
-static int
-mylex24rio(SDreq* r)
-{
- ulong p;
- Ctlr *ctlr;
- Ccb24 *ccb;
- Mbox24 *mb;
- uchar *data, lun, *sense;
- int d, n, btstat, sdstat, target;
-
- ctlr = r->unit->dev->ctlr;
- target = r->unit->subno;
- lun = (r->cmd[1]>>5) & 0x07;
-
- /*
- * Ctlr->cache holds the last completed Ccb for this target if it
- * returned 'check condition'.
- * If this command is a request-sense and there is valid sense data
- * from the last completed Ccb, return it immediately.
- */
- lock(&ctlr->cachelock);
- if((ccb = ctlr->cache[target]) != nil){
- ctlr->cache[target] = nil;
- if(r->cmd[0] == 0x03
- && ccb->sdstat == SDcheck && lun == ((ccb->cs[1]>>5) & 0x07)){
- unlock(&ctlr->cachelock);
- if(r->dlen){
- sense = &ccb->cs[ccb->cdblen];
- n = 8+sense[7];
- if(n > r->dlen)
- n = r->dlen;
- memmove(r->data, sense, n);
- r->rlen = n;
- }
- ccbfree(ctlr, (Ccb*)ccb);
- return SDok;
- }
- }
- unlock(&ctlr->cachelock);
- if(ccb == nil)
- ccb = ccballoc(ctlr);
-
- /*
- * Check if the transfer is to memory above the 24-bit limit the
- * controller can address. If it is, try to allocate a temporary
- * buffer as a staging area.
- */
- n = r->dlen;
- if(n && !PADDR24(r->data, n)){
- data = mallocz(n, 0);
- if(data == nil || !PADDR24(data, n)){
- if(data != nil){
- free(data);
- ccb->data = nil;
- }
- ccbfree(ctlr, (Ccb*)ccb);
- return SDmalloc;
- }
- if(r->write)
- memmove(data, r->data, n);
- ccb->data = r->data;
- }
- else
- data = r->data;
-
- /*
- * Fill in the ccb.
- */
- ccb->opcode = Ordl;
-
- ccb->datadir = (target<<5)|lun;
- if(n == 0)
- ccb->datadir |= CCBdataout|CCBdatain;
- else if(!r->write)
- ccb->datadir |= CCBdatain;
- else
- ccb->datadir |= CCBdataout;
-
- ccb->cdblen = r->clen;
- ccb->senselen = 0xFF;
-
- ccb->datalen[0] = n>>16;
- ccb->datalen[1] = n>>8;
- ccb->datalen[2] = n;
- p = PADDR(data);
- ccb->dataptr[0] = p>>16;
- ccb->dataptr[1] = p>>8;
- ccb->dataptr[2] = p;
-
- ccb->linkptr[0] = ccb->linkptr[1] = ccb->linkptr[2] = 0;
- ccb->linkid = 0;
- ccb->btstat = ccb->sdstat = 0;
- ccb->reserved[0] = ccb->reserved[1] = 0;
-
- memmove(ccb->cs, r->cmd, r->clen);
-
- /*
- * There's one more mbox than there there is
- * ccb so there is always one free.
- */
- lock(&ctlr->mboxlock);
- mb = ctlr->mb;
- mb += ctlr->mbox;
- p = PADDR(ccb);
- mb->ccb[0] = p>>16;
- mb->ccb[1] = p>>8;
- mb->ccb[2] = p;
- mb->code = Mbostart;
- ctlr->mbox++;
- if(ctlr->mbox >= NMbox)
- ctlr->mbox = 0;
-
- /*
- * This command does not require Hardy
- * and doesn't generate a Cmdc interrupt.
- */
- ccb->done = 0;
- outb(ctlr->port+Rcpr, Cstart);
- unlock(&ctlr->mboxlock);
-
- /*
- * Wait for the request to complete and return the status.
- * Since the buffer is not reference counted cannot return
- * until the DMA is done writing into the buffer so the caller
- * cannot free the buffer prematurely.
- */
- while(waserror())
- ;
- tsleep(ccb, done24, ccb, 30*1000);
- poperror();
-
- if(!done24(ccb)){
- print("%s: %d/%d: sd24rio timeout\n",
- "sdmylex"/*ctlr->sdev->name*/, target, r->lun);
- if(ccb->data != nil){
- free(data);
- ccb->data = nil;
- }
- ccbfree(ctlr, (Ccb*)ccb);
-
- return SDtimeout;
- }
-
- /*
- * Save the status and patch up the number of
- * bytes actually transferred.
- * There's a firmware bug on some 956C controllers
- * which causes the return count from a successful
- * READ CAPACITY not be updated, so fix it here.
- */
- sdstat = ccb->sdstat;
- btstat = ccb->btstat;
-
- d = ccb->datalen[0]<<16;
- d |= ccb->datalen[1]<<8;
- d |= ccb->datalen[2];
- if(ccb->cs[0] == 0x25 && sdstat == SDok)
- d = 0;
- n -= d;
- r->rlen = n;
-
- /*
- * Tidy things up if a staging area was used for the data,
- */
- if(ccb->data != nil){
- if(sdstat == SDok && btstat == 0 && !r->write)
- memmove(ccb->data, data, n);
- free(data);
- ccb->data = nil;
- }
-
- /*
- * If there was a check-condition, save the
- * ccb for a possible request-sense command.
- */
- if(sdstat == SDcheck){
- if(r->flags & SDnosense){
- lock(&ctlr->cachelock);
- if(ctlr->cache[target])
- ccbfree(ctlr, ctlr->cache[target]);
- ctlr->cache[target] = (Ccb*)ccb;
- unlock(&ctlr->cachelock);
- return SDcheck;
- }
- sense = &ccb->cs[ccb->cdblen];
- n = 8+sense[7];
- if(n > sizeof(r->sense)-1)
- n = sizeof(r->sense)-1;
- memmove(r->sense, sense, n);
- r->flags |= SDvalidsense;
- }
- ccbfree(ctlr, (Ccb*)ccb);
-
- if(btstat){
- if(btstat == 0x11)
- return SDtimeout;
- return SDeio;
- }
- return sdstat;
-}
-
-static void
-mylex24interrupt(Ureg*, void* arg)
-{
- ulong pa;
- Ctlr *ctlr;
- Ccb24 *ccb;
- Mbox24 *mb, *mbox;
- int port, rinterrupt, rstatus;
-
- ctlr = arg;
- port = ctlr->port;
-
- /*
- * Save and clear the interrupt(s). The only
- * interrupts expected are Cmdc, which is ignored,
- * and Imbl which means something completed.
- * There's one spurious interrupt left over from
- * initialisation, ignore it.
- */
- rinterrupt = inb(port+Rinterrupt);
- rstatus = inb(port+Rstatus);
- outb(port+Rcontrol, Rint);
- if((rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
- print("%s: interrupt 0x%2.2ux\n",
- "sdmylex"/*ctlr->sdev->name*/, rinterrupt);
- if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
- print("%s: command invalid\n", "sdmylex"/*ctlr->sdev->name*/);
-
- /*
- * Look for something in the mail.
- * If there is, save the status, free the mailbox
- * and wakeup whoever.
- */
- mb = ctlr->mb;
- for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
- pa = (mbox->ccb[0]<<16)|(mbox->ccb[1]<<8)|mbox->ccb[2];
- ccb = BPA2K(pa, BUSUNKNOWN);
- mbox->code = 0;
- ccb->done = 1;
- wakeup(ccb);
-
- ctlr->mbix++;
- if(ctlr->mbix >= NMbox+NMbox)
- ctlr->mbix = NMbox;
- }
-}
-
-static int
-done32(void* arg)
-{
- return ((Ccb32*)arg)->done;
-}
-
-static int
-mylex32rio(SDreq* r)
-{
- ulong p;
- uchar lun;
- Ctlr *ctlr;
- Ccb32 *ccb;
- Mbox32 *mb;
- int d, n, btstat, sdstat, target;
-
- ctlr = r->unit->dev->ctlr;
- target = r->unit->subno;
- lun = (r->cmd[1]>>5) & 0x07;
-
- /*
- * Ctlr->cache holds the last completed Ccb for this target if it
- * returned 'check condition'.
- * If this command is a request-sense and there is valid sense data
- * from the last completed Ccb, return it immediately.
- */
- lock(&ctlr->cachelock);
- if((ccb = ctlr->cache[target]) != nil){
- ctlr->cache[target] = nil;
- if(r->cmd[0] == 0x03
- && ccb->sdstat == SDcheck && lun == (ccb->luntag & 0x07)){
- unlock(&ctlr->cachelock);
- if(r->dlen){
- n = 8+ccb->sense[7];
- if(n > r->dlen)
- n = r->dlen;
- memmove(r->data, ccb->sense, n);
- r->rlen = n;
- }
- ccbfree(ctlr, (Ccb*)ccb);
- return SDok;
- }
- }
- unlock(&ctlr->cachelock);
- if(ccb == nil)
- ccb = ccballoc(ctlr);
-
- /*
- * Fill in the ccb.
- */
- ccb->opcode = Ordl;
-
- n = r->dlen;
- if(n == 0)
- ccb->datadir = CCBdataout|CCBdatain;
- else if(!r->write)
- ccb->datadir = CCBdatain;
- else
- ccb->datadir = CCBdataout;
-
- ccb->cdblen = r->clen;
-
- ccb->datalen[0] = n;
- ccb->datalen[1] = n>>8;
- ccb->datalen[2] = n>>16;
- ccb->datalen[3] = n>>24;
- p = PADDR(r->data);
- ccb->dataptr[0] = p;
- ccb->dataptr[1] = p>>8;
- ccb->dataptr[2] = p>>16;
- ccb->dataptr[3] = p>>24;
-
- ccb->targetid = target;
- ccb->luntag = lun;
- if(r->unit->inquiry[7] & 0x02)
- ccb->luntag |= SQTag|TagEnable;
- memmove(ccb->cdb, r->cmd, r->clen);
- ccb->btstat = ccb->sdstat = 0;
- ccb->ccbctl = 0;
-
- /*
- * There's one more mbox than there there is
- * ccb so there is always one free.
- */
- lock(&ctlr->mboxlock);
- mb = ctlr->mb;
- mb += ctlr->mbox;
- p = PADDR(ccb);
- mb->ccb[0] = p;
- mb->ccb[1] = p>>8;
- mb->ccb[2] = p>>16;
- mb->ccb[3] = p>>24;
- mb->code = Mbostart;
- ctlr->mbox++;
- if(ctlr->mbox >= NMbox)
- ctlr->mbox = 0;
-
- /*
- * This command does not require Hardy
- * and doesn't generate a Cmdc interrupt.
- */
- ccb->done = 0;
- outb(ctlr->port+Rcpr, Cstart);
- unlock(&ctlr->mboxlock);
-
- /*
- * Wait for the request to complete and return the status.
- * Since the buffer is not reference counted cannot return
- * until the DMA is done writing into the buffer so the caller
- * cannot free the buffer prematurely.
- */
- while(waserror())
- ;
- tsleep(ccb, done32, ccb, 30*1000);
- poperror();
-
- if(!done32(ccb)){
- print("%s: %d/%d: sd32rio timeout\n",
- "sdmylex"/*ctlr->sdev->name*/, target, r->lun);
- ccbfree(ctlr, (Ccb*)ccb);
-
- return SDtimeout;
- }
-
- /*
- * Save the status and patch up the number of
- * bytes actually transferred.
- * There's a firmware bug on some 956C controllers
- * which causes the return count from a successful
- * READ CAPACITY not to be updated, so fix it here.
- */
- sdstat = ccb->sdstat;
- btstat = ccb->btstat;
-
- d = ccb->datalen[0];
- d |= (ccb->datalen[1]<<8);
- d |= (ccb->datalen[2]<<16);
- d |= (ccb->datalen[3]<<24);
- if(ccb->cdb[0] == 0x25 && sdstat == SDok)
- d = 0;
- n -= d;
- r->rlen = n;
-
- /*
- * If there was a check-condition, save the
- * ccb for a possible request-sense command.
- */
- if(sdstat == SDcheck){
- if(r->flags & SDnosense){
- lock(&ctlr->cachelock);
- if(ctlr->cache[target])
- ccbfree(ctlr, ctlr->cache[target]);
- ctlr->cache[target] = (Ccb*)ccb;
- unlock(&ctlr->cachelock);
- return SDcheck;
- }
- n = 8+ccb->sense[7];
- if(n > sizeof(r->sense)-1)
- n = sizeof(r->sense)-1;
- memmove(r->sense, ccb->sense, n);
- r->flags |= SDvalidsense;
- }
- ccbfree(ctlr, (Ccb*)ccb);
-
- if(btstat){
- if(btstat == 0x11)
- return SDtimeout;
- return SDeio;
- }
- return sdstat;
-}
-
-static void
-mylex32interrupt(Ureg*, void* arg)
-{
- ulong pa;
- Ctlr *ctlr;
- Ccb32 *ccb;
- Mbox32 *mb, *mbox;
- int port, rinterrupt, rstatus;
-
- ctlr = arg;
- port = ctlr->port;
-
- /*
- * Save and clear the interrupt(s). The only
- * interrupts expected are Cmdc, which is ignored,
- * and Imbl which means something completed.
- * There's one spurious interrupt left over from
- * initialisation, ignore it.
- */
- rinterrupt = inb(port+Rinterrupt);
- rstatus = inb(port+Rstatus);
- outb(port+Rcontrol, Rint);
- if((rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
- print("%s: interrupt 0x%2.2ux\n",
- "sdmylex"/*ctlr->sdev->name*/, rinterrupt);
- if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
- print("%s: command invalid\n", "sdmylex"/*ctlr->sdev->name*/);
-
- /*
- * Look for something in the mail.
- * If there is, free the mailbox and wakeup whoever.
- */
- mb = ctlr->mb;
- for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
- pa = (mbox->ccb[3]<<24)
- |(mbox->ccb[2]<<16)
- |(mbox->ccb[1]<<8)
- |mbox->ccb[0];
- if(ctlr->pcidev)
- ccb = BPA2K(pa, ctlr->pcidev->tbdf);
- else
- ccb = BPA2K(pa, BUSUNKNOWN);
- mbox->code = 0;
- ccb->done = 1;
- wakeup(ccb);
-
- ctlr->mbix++;
- if(ctlr->mbix >= NMbox+NMbox)
- ctlr->mbix = NMbox;
- }
-}
-
-static int
-mylexrio(SDreq* r)
-{
- int subno;
- Ctlr *ctlr;
-
- subno = r->unit->subno;
- ctlr = r->unit->dev->ctlr;
- if(subno == ctlr->id || (!ctlr->wide && subno >= 8))
- r->status = SDtimeout;
- else if(ctlr->bus == 24)
- r->status = mylex24rio(r);
- else
- r->status = mylex32rio(r);
- return r->status;
-}
-
-/*
- * Issue a command to a controller. The command and its length is
- * contained in cmd and cmdlen. If any data is to be
- * returned, datalen should be non-zero, and the returned data
- * will be placed in data.
- * If Cmdc is set, bail out, the invalid command will be handled
- * when the interrupt is processed.
- */
-static void
-issueio(int port, uchar* cmd, int cmdlen, uchar* data, int datalen)
-{
- int len;
-
- if(cmd[0] != Cstart && cmd[0] != Ceombri){
- while(!(inb(port+Rstatus) & Hardy))
- ;
- }
- outb(port+Rcpr, cmd[0]);
-
- len = 1;
- while(len < cmdlen){
- if(!(inb(port+Rstatus) & Cprbsy)){
- outb(port+Rcpr, cmd[len]);
- len++;
- }
- if(inb(port+Rinterrupt) & Cmdc)
- return;
- }
-
- if(datalen){
- len = 0;
- while(len < datalen){
- if(inb(port+Rstatus) & Dirrdy){
- data[len] = inb(port+Rdatain);
- len++;
- }
- if(inb(port+Rinterrupt) & Cmdc)
- return;
- }
- }
-}
-
-/*
- * Issue a command to a controller, wait for it to complete then
- * try to reset the interrupt. Should only be called at initialisation.
- */
-static int
-issue(Ctlr* ctlr, uchar* cmd, int cmdlen, uchar* data, int datalen)
-{
- int port;
- uchar rinterrupt, rstatus;
- static Lock mylexissuelock;
-
- port = ctlr->port;
-
- ilock(&ctlr->issuelock);
- issueio(port, cmd, cmdlen, data, datalen);
-
- while(!((rinterrupt = inb(port+Rinterrupt)) & Cmdc))
- ;
-
- rstatus = inb(port+Rstatus);
- outb(port+Rcontrol, Rint);
- iunlock(&ctlr->issuelock);
-
- if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
- return 0;
- return 1;
-}
-
-static SDev*
-mylexprobe(int port, int irq)
-{
- SDev *sdev;
- Ctlr *ctlr;
- uchar cmd[6], data[256];
- int clen, dlen, timeo;
-
- if(ioalloc(port, 0x3, 0, "mylex") < 0)
- return nil;
- ctlr = nil;
-
- /*
- * Attempt to hard-reset the board and reset
- * the SCSI bus. If the board state doesn't settle to
- * idle with mailbox initialisation required, either
- * it isn't a compatible board or it's broken.
- * If the controller has SCAM set this can take a while.
- */
- if(getconf("*noscsireset") != nil)
- outb(port+Rcontrol, Rhard);
- else
- outb(port+Rcontrol, Rhard|Rsbus);
- for(timeo = 0; timeo < 100; timeo++){
- if(inb(port+Rstatus) == (Inreq|Hardy))
- break;
- delay(100);
- }
- if(inb(port+Rstatus) != (Inreq|Hardy)){
-buggery:
- if(ctlr != nil)
- free(ctlr);
- iofree(port);
- return nil;
- }
-
- if((ctlr = malloc(sizeof(Ctlr))) == nil)
- goto buggery;
- ctlr->port = port;
- ctlr->irq = irq;
- ctlr->bus = 24;
- ctlr->wide = 0;
-
- /*
- * Try to determine if this is a 32-bit MultiMaster controller
- * by attempting to obtain the extended inquiry information;
- * this command is not implemented on Adaptec 154xx
- * controllers. If successful, the first byte of the returned
- * data is the host adapter bus type, 'E' for 32-bit EISA,
- * PCI and VLB buses.
- */
- cmd[0] = Ciesi;
- cmd[1] = 14;
- clen = 2;
- dlen = 256;
- if(issue(ctlr, cmd, clen, data, dlen)){
- if(data[0] == 'E')
- ctlr->bus = 32;
- ctlr->wide = data[0x0D] & 0x01;
- }
- else{
- /*
- * Inconceivable though it may seem, a hard controller reset
- * is necessary here to clear out the command queue. Every
- * board seems to lock-up in a different way if you give an
- * invalid command and then try to clear out the
- * command/parameter and/or data-in register.
- * Soft reset doesn't do the job either. Fortunately no
- * serious initialisation has been done yet so there's nothing
- * to tidy up.
- */
- outb(port+Rcontrol, Rhard);
- for(timeo = 0; timeo < 100; timeo++){
- if(inb(port+Rstatus) == (Inreq|Hardy))
- break;
- delay(100);
- }
- if(inb(port+Rstatus) != (Inreq|Hardy))
- goto buggery;
- }
-
- /*
- * If the BIOS is enabled on the AHA-1542C/CF and BIOS options for
- * support of drives > 1Gb, dynamic scanning of the SCSI bus or more
- * than 2 drives under DOS 5.0 are enabled, the BIOS disables
- * accepting Cmbinit to protect against running with drivers which
- * don't support those options. In order to unlock the interface it
- * is necessary to read a lock-code using Cextbios and write it back
- * using Cmbienable; the lock-code is non-zero.
- */
- cmd[0] = Cinquiry;
- clen = 1;
- dlen = 4;
- if(issue(ctlr, cmd, clen, data, dlen) == 0)
- goto buggery;
- if(data[0] >= 0x43){
- cmd[0] = Cextbios;
- clen = 1;
- dlen = 2;
- if(issue(ctlr, cmd, clen, data, dlen) == 0)
- goto buggery;
-
- /*
- * Lock-code returned in data[1]. If it's non-zero write
- * it back along with bit 0 of byte 0 cleared to enable
- * mailbox initialisation.
- */
- if(data[1]){
- cmd[0] = Cmbienable;
- cmd[1] = 0;
- cmd[2] = data[1];
- clen = 3;
- if(issue(ctlr, cmd, clen, 0, 0) == 0)
- goto buggery;
- }
- }
-
- /*
- * Get the id, DMA and IRQ info from the board. This will
- * cause an interrupt which will hopefully not cause any
- * trouble because the interrupt number isn't known yet.
- * This is necessary as the DMA won't be set up if the
- * board has the BIOS disabled.
- *
- * If the IRQ is already known, this must be a 32-bit PCI
- * or EISA card, in which case the returned DMA and IRQ can
- * be ignored.
- */
- cmd[0] = Cinquire;
- clen = 1;
- dlen = 3;
- if(issue(ctlr, cmd, clen, data, dlen) == 0)
- goto buggery;
-
- ctlr->id = data[2] & 0x07;
- if(ctlr->irq < 0){
- switch(data[0]){ /* DMA Arbitration Priority */
- case 0x80: /* Channel 7 */
- outb(0xD6, 0xC3);
- outb(0xD4, 0x03);
- break;
- case 0x40: /* Channel 6 */
- outb(0xD6, 0xC2);
- outb(0xD4, 0x02);
- break;
- case 0x20: /* Channel 5 */
- outb(0xD6, 0xC1);
- outb(0xD4, 0x01);
- break;
- case 0x01: /* Channel 0 */
- outb(0x0B, 0xC0);
- outb(0x0A, 0x00);
- break;
- default:
- if(ctlr->bus == 24)
- goto buggery;
- break;
- }
-
- switch(data[1]){ /* Interrupt Channel */
- case 0x40:
- ctlr->irq = 15;
- break;
- case 0x20:
- ctlr->irq = 14;
- break;
- case 0x08:
- ctlr->irq = 12;
- break;
- case 0x04:
- ctlr->irq = 11;
- break;
- case 0x02:
- ctlr->irq = 10;
- break;
- case 0x01:
- ctlr->irq = 9;
- break;
- default:
- goto buggery;
- }
- }
-
- if((sdev = malloc(sizeof(SDev))) == nil)
- goto buggery;
- sdev->ifc = &sdmylexifc;
- sdev->ctlr = ctlr;
- ctlr->sdev = sdev;
- if(!ctlr->wide)
- sdev->nunit = 8;
- else
- sdev->nunit = 16;
-
- return sdev;
-}
-
-static int mylexport[8] = {
- 0x330, 0x334, 0x230, 0x234, 0x130, 0x134, 0x000, 0x000,
-};
-
-static SDev*
-mylexpnp(void)
-{
- Pcidev *p;
- Ctlr *ctlr;
- ISAConf isa;
- int cfg, ctlrno, i, x;
- SDev *sdev, *head, *tail;
-
- p = nil;
- head = tail = nil;
- while(p = pcimatch(p, 0x104B, 0)){
- if((sdev = mylexprobe(p->mem[0].bar & ~0x01, p->intl)) == nil)
- continue;
-
- ctlr = sdev->ctlr;
- ctlr->pcidev = p;
-
- if(head != nil)
- tail->next = sdev;
- else
- head = sdev;
- tail = sdev;
- }
-
- if(strncmp(KADDR(0xFFFD9), "EISA", 4) == 0){
- for(cfg = 0x1000; cfg < MaxEISA*0x1000; cfg += 0x1000){
- x = 0;
- for(i = 0; i < 4; i++)
- x |= inb(cfg+CfgEISA+i)<<(i*8);
- if(x != 0x0142B30A && x != 0x0242B30A)
- continue;
-
- x = inb(cfg+0xC8C);
- if((sdev = mylexprobe(mylexport[x & 0x07], -1)) == nil)
- continue;
-
- if(head != nil)
- tail->next = sdev;
- else
- head = sdev;
- tail = sdev;
- }
- }
-
- for(ctlrno = 0; ctlrno < 4; ctlrno++){
- memset(&isa, 0, sizeof(isa));
- if(!isaconfig("scsi", ctlrno, &isa))
- continue;
- if(strcmp(isa.type, "aha1542"))
- continue;
- if((sdev = mylexprobe(isa.port, -1)) == nil)
- continue;
-
- if(head != nil)
- tail->next = sdev;
- else
- head = sdev;
- tail = sdev;
- }
-
- return head;
-}
-
-static SDev*
-mylexid(SDev* sdev)
-{
- return scsiid(sdev, &sdmylexifc);
-}
-
-static int
-mylex24enable(Ctlr* ctlr)
-{
- ulong p;
- Ccb24 *ccb, *ccbp;
- uchar cmd[6], *v;
- int len;
-
- len = (sizeof(Mbox24)*NMbox*2)+(sizeof(Ccb24)*NCcb);
- v = xspanalloc(len, 32, 0);
-
- if(!PADDR24(ctlr, sizeof(Ctlr)) || !PADDR24(v, len))
- return 0;
-
- ctlr->mb = v;
- v += sizeof(Mbox24)*NMbox*2;
-
- ccb = (Ccb24*)v;
- for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
- ccbp->ccb = ctlr->ccb;
- ctlr->ccb = (Ccb*)ccbp;
- }
-
- /*
- * Initialise the software controller and
- * set the board scanning the mailboxes.
- */
- ctlr->mbix = NMbox;
-
- cmd[0] = Cinitialise;
- cmd[1] = NMbox;
- p = K2BPA(ctlr->mb, BUSUNKNOWN);
- cmd[2] = p>>16;
- cmd[3] = p>>8;
- cmd[4] = p;
-
- return issue(ctlr, cmd, 5, 0, 0);
-}
-
-static int
-mylex32enable(Ctlr* ctlr)
-{
- ulong p;
- Ccb32 *ccb, *ccbp;
- uchar cmd[6], *v;
-
- v = xspanalloc((sizeof(Mbox32)*NMbox*2)+(sizeof(Ccb32)*NCcb), 32, 0);
-
- ctlr->mb = v;
- v += sizeof(Mbox32)*NMbox*2;
-
- ccb = (Ccb32*)v;
- for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
- /*
- * Fill in some stuff that doesn't change.
- */
- ccbp->senselen = sizeof(ccbp->sense);
- p = PADDR(ccbp->sense);
- ccbp->senseptr[0] = p;
- ccbp->senseptr[1] = p>>8;
- ccbp->senseptr[2] = p>>16;
- ccbp->senseptr[3] = p>>24;
-
- ccbp->ccb = ctlr->ccb;
- ctlr->ccb = (Ccb*)ccbp;
- }
-
- /*
- * Attempt wide mode setup.
- */
- if(ctlr->wide){
- cmd[0] = Cwide;
- cmd[1] = 1;
- if(!issue(ctlr, cmd, 2, 0, 0))
- ctlr->wide = 0;
- }
-
- /*
- * Initialise the software controller and
- * set the board scanning the mailboxes.
- */
- ctlr->mbix = NMbox;
-
- cmd[0] = Ciem;
- cmd[1] = NMbox;
- if(ctlr->pcidev)
- p = K2BPA(ctlr->mb, ctlr->tbdf);
- else
- p = K2BPA(ctlr->mb, BUSUNKNOWN);
- cmd[2] = p;
- cmd[3] = p>>8;
- cmd[4] = p>>16;
- cmd[5] = p>>24;
-
- return issue(ctlr, cmd, 6, 0, 0);
-}
-
-static int
-mylexenable(SDev* sdev)
-{
- int tbdf;
- Ctlr *ctlr;
- void (*interrupt)(Ureg*, void*);
- char name[NAMELEN];
-
- ctlr = sdev->ctlr;
- if(ctlr->cache == nil){
- if((ctlr->cache = malloc(sdev->nunit*sizeof(Ccb*))) == nil)
- return 0;
- }
-
- tbdf = BUSUNKNOWN;
- if(ctlr->bus == 32){
- if(ctlr->pcidev){
- tbdf = ctlr->pcidev->tbdf;
- pcisetbme(ctlr->pcidev);
- }
- if(!mylex32enable(ctlr))
- return 0;
- interrupt = mylex32interrupt;
- }
- else if(mylex24enable(ctlr))
- interrupt = mylex24interrupt;
- else
- return 0;
-
- snprint(name, NAMELEN, "sd%c (%s)", sdev->idno, sdev->ifc->name);
- intrenable(ctlr->irq, interrupt, ctlr, tbdf, name);
-
- return 1;
-}
-
-static int
-mylexdisable(SDev* sdev)
-{
- Ctlr *ctlr;
- int port, timeo;
-
- ctlr = sdev->ctlr;
- port = ctlr->port;
-
- if(getconf("*noscsireset") != nil)
- outb(port+Rcontrol, Rhard);
- else
- outb(port+Rcontrol, Rhard|Rsbus);
- for(timeo = 0; timeo < 100; timeo++){
- if(inb(port+Rstatus) == (Inreq|Hardy))
- break;
- delay(100);
- }
- if(inb(port+Rstatus) != (Inreq|Hardy))
- return 0;
-
- return 1;
-}
-
-SDifc sdmylexifc = {
- "mylex", /* name */
-
- mylexpnp, /* pnp */
- nil, /* legacy */
- mylexid, /* id */
- mylexenable, /* enable */
- mylexdisable, /* disable */
-
- scsiverify, /* verify */
- scsionline, /* online */
- mylexrio, /* rio */
- nil, /* rctl */
- nil, /* wctl */
-
- scsibio, /* bio */
-};
--- a/os/boot/pc/sdscsi.c
+++ /dev/null
@@ -1,376 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "error.h"
-
-#include "sd.h"
-
-static int
-scsitest(SDreq* r)
-{
- r->write = 0;
- memset(r->cmd, 0, sizeof(r->cmd));
- r->cmd[1] = r->lun<<5;
- r->clen = 6;
- r->data = nil;
- r->dlen = 0;
- r->flags = 0;
-
- r->status = ~0;
-
-// cgascreenputs("A", 1);
- return r->unit->dev->ifc->rio(r);
-}
-
-int
-scsiverify(SDunit* unit)
-{
- static SDreq *r;
- int i, status;
- static uchar *inquiry;
-
- if((r = sdmalloc(r, sizeof(SDreq))) == nil)
- return 0;
-
- if((inquiry = sdmalloc(inquiry, sizeof(unit->inquiry))) == nil)
- return 0;
-
- r->unit = unit;
- r->lun = 0; /* ??? */
-
- memset(unit->inquiry, 0, sizeof(unit->inquiry));
- r->write = 0;
- r->cmd[0] = 0x12;
- r->cmd[1] = r->lun<<5;
- r->cmd[4] = sizeof(unit->inquiry)-1;
- r->clen = 6;
- r->data = inquiry;
- r->dlen = sizeof(unit->inquiry)-1;
- r->flags = 0;
-
- r->status = ~0;
-// cgascreenputs("B", 1);
- if(unit->dev->ifc->rio(r) != SDok){
- return 0;
- }
- memmove(unit->inquiry, inquiry, r->dlen);
-
- SET(status);
- for(i = 0; i < 3; i++){
- while((status = scsitest(r)) == SDbusy)
- ;
- if(status == SDok || status != SDcheck)
- break;
- if(!(r->flags & SDvalidsense))
- break;
- if((r->sense[2] & 0x0F) != 0x02)
- continue;
-
- /*
- * Unit is 'not ready'.
- * If it is in the process of becoming ready or needs
- * an initialising command, set status so it will be spun-up
- * below.
- * If there's no medium, that's OK too, but don't
- * try to spin it up.
- */
- if(r->sense[12] == 0x04){
- if(r->sense[13] == 0x02 || r->sense[13] == 0x01){
- status = SDok;
- break;
- }
- }
- if(r->sense[12] == 0x3A)
- break;
- }
-
- if(status == SDok){
- /*
- * Try to ensure a direct-access device is spinning.
- * Ignore the result.
- */
- if((unit->inquiry[0] & 0x1F) == 0){
- memset(r->cmd, 0, sizeof(r->cmd));
- r->write = 0;
- r->cmd[0] = 0x1B;
- r->cmd[1] = r->lun<<5;
- r->cmd[4] = 1;
- r->clen = 6;
- r->data = nil;
- r->dlen = 0;
- r->flags = 0;
-
- r->status = ~0;
- unit->dev->ifc->rio(r);
- }
- return 1;
- }
- return 0;
-}
-
-int
-return0(void*)
-{
- return 0;
-}
-
-static int
-scsirio(SDreq* r)
-{
- /*
- * Perform an I/O request, returning
- * -1 failure
- * 0 ok
- * 2 retry
- * The contents of r may be altered so the
- * caller should re-initialise if necesary.
- */
- r->status = ~0;
-// cgascreenputs("C", 1);
- switch(r->unit->dev->ifc->rio(r)){
- default:
- break;
- case SDcheck:
- if(!(r->flags & SDvalidsense))
- return -1;
- switch(r->sense[2] & 0x0F){
- case 0x00: /* no sense */
- case 0x01: /* recovered error */
- return 2;
- case 0x06: /* check condition */
- /*
- * 0x28 - not ready to ready transition,
- * medium may have changed.
- * 0x29 - power on or some type of reset.
- */
- if(r->sense[12] == 0x28 && r->sense[13] == 0)
- return 2;
- if(r->sense[12] == 0x29)
- return 2;
- break;
- case 0x02: /* not ready */
- /*
- * If no medium present, bail out.
- * If unit is becoming ready, rather than not
- * not ready, wait a little then poke it again. */
- if(r->sense[12] == 0x3A)
- return -1;
- if(r->sense[12] != 0x04 || r->sense[13] != 0x01)
- return -1;
-
- tsleep(nil, return0, 0, 500);
- scsitest(r);
- return 2;
- default:
- break;
- }
- break;
- case SDok:
- return 0;
- }
- return -1;
-}
-
-int
-scsionline(SDunit* unit)
-{
- int ok;
- static SDreq *r;
- static uchar *p;
-
- if((r = sdmalloc(r, sizeof(SDreq))) == nil)
- return 0;
-
- if((p = sdmalloc(p, 8)) == nil)
- return 0;
-
- ok = 0;
-
- r->unit = unit;
- r->lun = 0; /* ??? */
- for(;;){
- /*
- * Read-capacity is mandatory for DA, WORM, CD-ROM and
- * MO. It may return 'not ready' if type DA is not
- * spun up, type MO or type CD-ROM are not loaded or just
- * plain slow getting their act together after a reset.
- */
- r->write = 0;
- memset(r->cmd, 0, sizeof(r->cmd));
- r->cmd[0] = 0x25;
- r->cmd[1] = r->lun<<5;
- r->clen = 10;
- r->data = p;
- r->dlen = 8;
- r->flags = 0;
-
- r->status = ~0;
-// cgascreenputs("F", 1);
- switch(scsirio(r)){
- default:
- break;
- case 0:
- unit->sectors = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
- /*
- * Read-capacity returns the LBA of the last sector,
- * therefore the number of sectors must be incremented.
- */
- unit->sectors++;
- unit->secsize = (p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7];
- ok = 1;
- break;
- case 2:
- continue;
- }
- break;
- }
-
- return ok;
-}
-
-int
-scsiexec(SDunit* unit, int write, uchar* cmd, int clen, void* data, int* dlen)
-{
- static SDreq *r;
- int status;
-
- if((r = sdmalloc(r, sizeof(SDreq))) == nil)
- return SDmalloc;
-
- r->unit = unit;
- r->lun = cmd[1]>>5; /* ??? */
- r->write = write;
- memmove(r->cmd, cmd, clen);
- r->clen = clen;
- r->data = data;
- if(dlen)
- r->dlen = *dlen;
- r->flags = 0;
-
- r->status = ~0;
-
- /*
- * Call the device-specific I/O routine.
- * There should be no calls to 'error()' below this
- * which percolate back up.
- */
-// cgascreenputs("D", 1);
- switch(status = unit->dev->ifc->rio(r)){
- case SDok:
- if(dlen)
- *dlen = r->rlen;
- /*FALLTHROUGH*/
- case SDcheck:
- /*FALLTHROUGH*/
- default:
- /*
- * It's more complicated than this. There are conditions
- * which are 'ok' but for which the returned status code
- * is not 'SDok'.
- * Also, not all conditions require a reqsense, might
- * need to do a reqsense here and make it available to the
- * caller somehow.
- *
- * Mañana.
- */
- break;
- }
-
- return status;
-}
-
-long
-scsibio(SDunit* unit, int lun, int write, void* data, long nb, long bno)
-{
- static SDreq *r;
- long rlen;
-
- if((r = sdmalloc(r, sizeof(SDreq))) == nil)
- return SDmalloc;
-
- r->unit = unit;
- r->lun = lun;
-again:
- r->write = write;
- if(write == 0)
- r->cmd[0] = 0x28;
- else
- r->cmd[0] = 0x2A;
- r->cmd[1] = (lun<<5);
- r->cmd[2] = bno>>24;
- r->cmd[3] = bno>>16;
- r->cmd[4] = bno>>8;
- r->cmd[5] = bno;
- r->cmd[6] = 0;
- r->cmd[7] = nb>>8;
- r->cmd[8] = nb;
- r->cmd[9] = 0;
- r->clen = 10;
- r->data = data;
- r->dlen = nb*unit->secsize;
- r->flags = 0;
-
- r->status = ~0;
-// cgascreenputs("E", 1);
- switch(scsirio(r)){
- default:
- rlen = -1;
- break;
- case 0:
- rlen = r->rlen;
- break;
- case 2:
- rlen = -1;
- if(!(r->flags & SDvalidsense))
- break;
- switch(r->sense[2] & 0x0F){
- default:
- break;
- case 0x06: /* check condition */
- /*
- * Check for a removeable media change.
- * If so, mark it and zap the geometry info
- * to force an online request.
- */
- if(r->sense[12] != 0x28 || r->sense[13] != 0)
- break;
- if(unit->inquiry[1] & 0x80){
- unit->sectors = 0;
- }
- break;
- case 0x02: /* not ready */
- /*
- * If unit is becoming ready,
- * rather than not not ready, try again.
- */
- if(r->sense[12] == 0x04 && r->sense[13] == 0x01)
- goto again;
- break;
- }
- break;
- }
-
- return rlen;
-}
-
-SDev*
-scsiid(SDev* sdev, SDifc* ifc)
-{
- static char idno[16] = "0123456789abcdef";
- static char *p = idno;
-
- while(sdev){
- if(sdev->ifc == ifc){
- sdev->idno = *p++;
- if(p >= &idno[sizeof(idno)])
- break;
- }
- sdev = sdev->next;
- }
-
- return nil;
-}
--- a/os/boot/pc/trap.c
+++ /dev/null
@@ -1,332 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-
-void intr0(void), intr1(void), intr2(void), intr3(void);
-void intr4(void), intr5(void), intr6(void), intr7(void);
-void intr8(void), intr9(void), intr10(void), intr11(void);
-void intr12(void), intr13(void), intr14(void), intr15(void);
-void intr16(void);
-void intr24(void), intr25(void), intr26(void), intr27(void);
-void intr28(void), intr29(void), intr30(void), intr31(void);
-void intr32(void), intr33(void), intr34(void), intr35(void);
-void intr36(void), intr37(void), intr38(void), intr39(void);
-void intr64(void);
-void intrbad(void);
-
-/*
- * 8259 interrupt controllers
- */
-enum
-{
- Int0ctl= 0x20, /* control port (ICW1, OCW2, OCW3) */
- Int0aux= 0x21, /* everything else (ICW2, ICW3, ICW4, OCW1) */
- Int1ctl= 0xA0, /* control port */
- Int1aux= 0xA1, /* everything else (ICW2, ICW3, ICW4, OCW1) */
-
- Icw1= 0x10, /* select bit in ctl register */
- Ocw2= 0x00,
- Ocw3= 0x08,
-
- EOI= 0x20, /* non-specific end of interrupt */
-
- Elcr1= 0x4D0, /* Edge/Level Triggered Register */
- Elcr2= 0x4D1,
-};
-
-int int0mask = 0xff; /* interrupts enabled for first 8259 */
-int int1mask = 0xff; /* interrupts enabled for second 8259 */
-int i8259elcr; /* mask of level-triggered interrupts */
-
-/*
- * trap/interrupt gates
- */
-Segdesc ilt[256];
-
-enum
-{
- Maxhandler= 32, /* max number of interrupt handlers */
-};
-
-typedef struct Handler Handler;
-struct Handler
-{
- void (*r)(Ureg*, void*);
- void *arg;
- Handler *next;
-};
-
-struct
-{
- Handler *ivec[256];
- Handler h[Maxhandler];
- int nextfree;
-} halloc;
-
-void
-sethvec(int v, void (*r)(void), int type, int pri)
-{
- ilt[v].d0 = ((ulong)r)&0xFFFF|(KESEL<<16);
- ilt[v].d1 = ((ulong)r)&0xFFFF0000|SEGP|SEGPL(pri)|type;
-}
-
-void
-setvec(int v, void (*r)(Ureg*, void*), void *arg)
-{
- Handler *h;
-
- if(halloc.nextfree >= Maxhandler)
- panic("out of interrupt handlers");
- h = &halloc.h[halloc.nextfree++];
- h->next = halloc.ivec[v];
- h->r = r;
- h->arg = arg;
- halloc.ivec[v] = h;
-
- /*
- * enable corresponding interrupt in 8259
- */
- if((v&~0x7) == VectorPIC){
- int0mask &= ~(1<<(v&7));
- outb(Int0aux, int0mask);
- } else if((v&~0x7) == VectorPIC+8){
- int1mask &= ~(1<<(v&7));
- outb(Int1aux, int1mask);
- }
-}
-
-void
-trapdisable(void)
-{
- outb(Int0aux, 0xFF);
- outb(Int1aux, 0xFF);
-}
-
-void
-trapenable(void)
-{
- outb(Int0aux, int0mask);
- outb(Int1aux, int1mask);
-}
-
-
-/*
- * set up the interrupt/trap gates
- */
-void
-trapinit(void)
-{
- int i, x;
-
- /*
- * set all interrupts to panics
- */
- for(i = 0; i < 256; i++)
- sethvec(i, intrbad, SEGTG, 0);
-
- /*
- * 80386 processor (and coprocessor) traps
- */
- sethvec(0, intr0, SEGTG, 0);
- sethvec(1, intr1, SEGTG, 0);
- sethvec(2, intr2, SEGTG, 0);
- sethvec(3, intr3, SEGTG, 0);
- sethvec(4, intr4, SEGTG, 0);
- sethvec(5, intr5, SEGTG, 0);
- sethvec(6, intr6, SEGTG, 0);
- sethvec(7, intr7, SEGTG, 0);
- sethvec(8, intr8, SEGTG, 0);
- sethvec(9, intr9, SEGTG, 0);
- sethvec(10, intr10, SEGTG, 0);
- sethvec(11, intr11, SEGTG, 0);
- sethvec(12, intr12, SEGTG, 0);
- sethvec(13, intr13, SEGTG, 0);
- sethvec(14, intr14, SEGTG, 0);
- sethvec(15, intr15, SEGTG, 0);
- sethvec(16, intr16, SEGTG, 0);
-
- /*
- * device interrupts
- */
- sethvec(24, intr24, SEGIG, 0);
- sethvec(25, intr25, SEGIG, 0);
- sethvec(26, intr26, SEGIG, 0);
- sethvec(27, intr27, SEGIG, 0);
- sethvec(28, intr28, SEGIG, 0);
- sethvec(29, intr29, SEGIG, 0);
- sethvec(30, intr30, SEGIG, 0);
- sethvec(31, intr31, SEGIG, 0);
- sethvec(32, intr32, SEGIG, 0);
- sethvec(33, intr33, SEGIG, 0);
- sethvec(34, intr34, SEGIG, 0);
- sethvec(35, intr35, SEGIG, 0);
- sethvec(36, intr36, SEGIG, 0);
- sethvec(37, intr37, SEGIG, 0);
- sethvec(38, intr38, SEGIG, 0);
- sethvec(39, intr39, SEGIG, 0);
-
- /*
- * tell the hardware where the table is (and how long)
- */
- putidt(ilt, sizeof(ilt)-1);
-
- /*
- * Set up the first 8259 interrupt processor.
- * Make 8259 interrupts start at CPU vector VectorPIC.
- * Set the 8259 as master with edge triggered
- * input with fully nested interrupts.
- */
- outb(Int0ctl, Icw1|0x01); /* ICW1 - edge triggered, master,
- ICW4 will be sent */
- outb(Int0aux, VectorPIC); /* ICW2 - interrupt vector offset */
- outb(Int0aux, 0x04); /* ICW3 - have slave on level 2 */
- outb(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */
-
- /*
- * Set up the second 8259 interrupt processor.
- * Make 8259 interrupts start at CPU vector VectorPIC+8.
- * Set the 8259 as master with edge triggered
- * input with fully nested interrupts.
- */
- outb(Int1ctl, Icw1|0x01); /* ICW1 - edge triggered, master,
- ICW4 will be sent */
- outb(Int1aux, VectorPIC+8); /* ICW2 - interrupt vector offset */
- outb(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */
- outb(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */
- outb(Int1aux, int1mask);
-
- /*
- * pass #2 8259 interrupts to #1
- */
- int0mask &= ~0x04;
- outb(Int0aux, int0mask);
-
- /*
- * Set Ocw3 to return the ISR when ctl read.
- */
- outb(Int0ctl, Ocw3|0x03);
- outb(Int1ctl, Ocw3|0x03);
-
- /*
- * Check for Edge/Level register.
- * This check may not work for all chipsets.
- * First try a non-intrusive test - the bits for
- * IRQs 13, 8, 2, 1 and 0 must be edge (0). If
- * that's OK try a R/W test.
- */
- x = (inb(Elcr2)<<8)|inb(Elcr1);
- if(!(x & 0x2107)){
- outb(Elcr1, 0);
- if(inb(Elcr1) == 0){
- outb(Elcr1, 0x20);
- if(inb(Elcr1) == 0x20)
- i8259elcr = x;
- outb(Elcr1, x & 0xFF);
- print("ELCR: %4.4uX\n", i8259elcr);
- }
- }
-}
-
-/*
- * dump registers
- */
-static void
-dumpregs(Ureg *ur)
-{
- print("FLAGS=%lux TRAP=%lux ECODE=%lux PC=%lux\n",
- ur->flags, ur->trap, ur->ecode, ur->pc);
- print(" AX %8.8lux BX %8.8lux CX %8.8lux DX %8.8lux\n",
- ur->ax, ur->bx, ur->cx, ur->dx);
- print(" SI %8.8lux DI %8.8lux BP %8.8lux\n",
- ur->si, ur->di, ur->bp);
- print(" CS %4.4lux DS %4.4lux ES %4.4lux FS %4.4lux GS %4.4lux\n",
- ur->cs & 0xFF, ur->ds & 0xFFFF, ur->es & 0xFFFF, ur->fs & 0xFFFF, ur->gs & 0xFFFF);
- print(" CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux\n",
- getcr0(), getcr2(), getcr3());
-}
-
-/*
- * All traps
- */
-void
-trap(Ureg *ur)
-{
- int v;
- int c;
- Handler *h;
- ushort isr;
-
- v = ur->trap;
- /*
- * tell the 8259 that we're done with the
- * highest level interrupt (interrupts are still
- * off at this point)
- */
- c = v&~0x7;
- isr = 0;
- if(c==VectorPIC || c==VectorPIC+8){
- isr = inb(Int0ctl);
- outb(Int0ctl, EOI);
- if(c == VectorPIC+8){
- isr |= inb(Int1ctl)<<8;
- outb(Int1ctl, EOI);
- }
- }
-
- if(v>=256 || (h = halloc.ivec[v]) == 0){
- if(v >= VectorPIC && v < VectorPIC+16){
- v -= VectorPIC;
- /*
- * Check for a default IRQ7. This can happen when
- * the IRQ input goes away before the acknowledge.
- * In this case, a 'default IRQ7' is generated, but
- * the corresponding bit in the ISR isn't set.
- * In fact, just ignore all such interrupts.
- */
- if(isr & (1<<v))
- print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
- return;
- }
-
- switch(v){
-
- case 0x02: /* NMI */
- print("NMI: nmisc=0x%2.2ux, nmiertc=0x%2.2ux, nmiesc=0x%2.2ux\n",
- inb(0x61), inb(0x70), inb(0x461));
- return;
-
- default:
- dumpregs(ur);
- panic("exception/interrupt %d", v);
- return;
- }
- }
-
- /*
- * call the trap routines
- */
- do {
- (*h->r)(ur, h->arg);
- h = h->next;
- } while(h);
-}
-
-extern void realmode0(void); /* in l.s */
-
-extern int realmodeintr;
-extern Ureg realmoderegs;
-
-void
-realmode(int intr, Ureg *ureg)
-{
- realmoderegs = *ureg;
- realmodeintr = intr;
- trapdisable();
- realmode0();
- trapenable();
- *ureg = realmoderegs;
-}
--- a/os/boot/pc/ureg.h
+++ /dev/null
@@ -1,27 +1,0 @@
-typedef struct Ureg Ureg;
-
-struct Ureg
-{
- ulong di; /* general registers */
- ulong si; /* ... */
- ulong bp; /* ... */
- ulong nsp;
- ulong bx; /* ... */
- ulong dx; /* ... */
- ulong cx; /* ... */
- ulong ax; /* ... */
- ulong gs; /* data segments */
- ulong fs; /* ... */
- ulong es; /* ... */
- ulong ds; /* ... */
- ulong trap; /* trap type */
- ulong ecode; /* error code (or zero) */
- ulong pc; /* pc */
- ulong cs; /* old context */
- ulong flags; /* old flags */
- union {
- ulong usp;
- ulong sp;
- };
- ulong ss; /* old stack segment */
-};
--- a/os/boot/pc/x16.h
+++ /dev/null
@@ -1,159 +1,0 @@
-/*
- * Can't write 16-bit code for 8a without getting into
- * lots of bother, so define some simple commands and
- * output the code directly.
- *
- * N.B. CALL16(x) kills DI, so don't expect it to be
- * saved across calls.
- */
-#define rAX 0 /* rX */
-#define rCX 1
-#define rDX 2
-#define rBX 3
-#define rSP 4 /* SP */
-#define rBP 5 /* BP */
-#define rSI 6 /* SI */
-#define rDI 7 /* DI */
-
-#define rAL 0 /* rL */
-#define rCL 1
-#define rDL 2
-#define rBL 3
-#define rAH 4 /* rH */
-#define rCH 5
-#define rDH 6
-#define rBH 7
-
-#define rES 0 /* rS */
-#define rCS 1
-#define rSS 2
-#define rDS 3
-#define rFS 4
-#define rGS 5
-
-#define xSI 4 /* rI (index) */
-#define xDI 5
-#define xBP 6
-#define xBX 7
-
-#define rCR0 0 /* rC */
-#define rCR2 2
-#define rCR3 3
-#define rCR4 4
-
-#define OP(o, m, ro, rm) BYTE $o; /* op + modr/m byte */ \
- BYTE $(((m)<<6)|((ro)<<3)|(rm))
-#define OPrm(o, r, m) OP(o, 0x00, r, 0x06); /* general r <-> m */ \
- WORD $m;
-#define OPrr(o, r0, r1) OP(o, 0x03, r0, r1); /* general r -> r */
-
-#define LW(m, rX) OPrm(0x8B, rX, m) /* m -> rX */
-#define LXW(x, rI, r) OP(0x8B, 0x02, r, rI); /* x(rI) -> r */ \
- WORD $x
-#define LBPW(x, r) OP(0x8B, 0x02, r, xBP); /* x(rBP) -> r */ \
- WORD $x
-#define LB(m, rB) OPrm(0x8A, rB, m) /* m -> r[HL] */
-#define LXB(x, rI, r) OP(0x8A, 0x01, r, rI); /* x(rI) -> r */ \
- BYTE $x
-#define LBPB(x, r) OP(0x8A, 0x01, r, xBP); /* x(rBP) -> r */ \
- BYTE $x
-#define SW(rX, m) OPrm(0x89, rX, m) /* rX -> m */
-#define SXW(r, x, rI) OP(0x89, 0x02, r, rI); /* r -> x(rI) */ \
- WORD $x
-#define SBPW(r, x) OP(0x89, 0x02, r, xBP); /* r -> x(rBP) */ \
- WORD $(x)
-#define SBPWI(i, x) OP(0xC7, 0x01, 0, xBP); /* i -> x(rBP) */ \
- BYTE $(x); WORD $(i)
-#define STB(rB, m) OPrm(0x88, rB, m) /* rB -> m */
-#define SXB(r, x, rI) OP(0x88, 0x01, r, rI); /* rB -> x(rI) */ \
- BYTE $x
-#define SBPB(r, x) OP(0x88, 0x01, r, xBP); /* r -> x(rBP) */ \
- BYTE $x
-#define SBPBI(i, x) OP(0xC6, 0x01, 0, xBP); /* i -> x(rBP) */ \
- BYTE $(x); BYTE $(i)
-#define LWI(i, rX) BYTE $(0xB8+rX); /* i -> rX */ \
- WORD $i;
-#define LBI(i, rB) BYTE $(0xB0+rB); /* i -> r[HL] */ \
- BYTE $i
-
-#define MW(r0, r1) OPrr(0x89, r0, r1) /* r0 -> r1 */
-#define MFSR(rS, rX) OPrr(0x8C, rS, rX) /* rS -> rX */
-#define MTSR(rX, rS) OPrr(0x8E, rS, rX) /* rX -> rS */
-#define MFCR(rC, rX) BYTE $0x0F; /* rC -> rX */ \
- OP(0x20, 0x03, rC, rX)
-#define MTCR(rX, rC) BYTE $0x0F; /* rX -> rC */ \
- OP(0x22, 0x03, rC, rX)
-
-#define ADC(r0, r1) OPrr(0x11, r0, r1) /* r0 + r1 -> r1 */
-#define ADD(r0, r1) OPrr(0x01, r0, r1) /* r0 + r1 -> r1 */
-#define ADDI(i, r) OP(0x81, 0x03, 0x00, r);/* i+r -> r */ \
- WORD $i;
-#define AND(r0, r1) OPrr(0x21, r0, r1) /* r0&r1 -> r1 */
-#define ANDI(i, r) OP(0x81, 0x03, 0x04, r);/* i&r -> r */ \
- WORD $i;
-#define CLR(r) OPrr(0x31, r, r) /* r^r -> r */
-#define CLRB(r) OPrr(0x30, r, r) /* r^r -> r */
-#define CMP(r0, r1) OPrr(0x39, r0, r1) /* r1-r0 -> flags */
-#define CMPI(i, r) OP(0x81, 0x03, 0x07, r);/* r-i -> flags */ \
- WORD $i;
-#define CMPBR(r0, r1) OPrr(0x38, r0, r1) /* r1-r0 -> flags */
-#define DEC(r) BYTE $(0x48|r) /* r-1 -> r */
-#define DIV(r) OPrr(0xF7, 0x06, r) /* rDX:rAX/r -> rAX, rDX:rAX%r -> rDX */
-#define INC(r) BYTE $(0x40|r) /* r+1 -> r */
-#define MUL(r) OPrr(0xF7, 0x04, r) /* r*rAX -> rDX:rAX */
-#define IMUL(r0, r1) BYTE $0x0F; /* r0*r1 -> r1 */ \
- OPrr(0xAF, r1, r0) /* (signed) */
-#define OR(r0, r1) OPrr(0x09, r0, r1) /* r0|r1 -> r1 */
-#define ORB(r0, r1) OPrr(0x08, r0, r1) /* r0|r1 -> r1 */
-#define ORI(i, r) OP(0x81, 0x03, 0x01, r);/* i|r -> r */ \
- WORD $i;
-#define ROLI(i, r) OPrr(0xC1, 0x00, r); /* r<<>>i -> r */ \
- BYTE $i;
-#define SHLI(i, r) OPrr(0xC1, 0x04, r); /* r<<i -> r */ \
- BYTE $i;
-#define SHLBI(i, r) OPrr(0xC0, 0x04, r); /* r<<i -> r */ \
- BYTE $i;
-#define SHRI(i, r) OPrr(0xC1, 0x05, r); /* r>>i -> r */ \
- BYTE $i;
-#define SHRBI(i, r) OPrr(0xC0, 0x05, r); /* r>>i -> r */ \
- BYTE $i;
-#define SUB(r0, r1) OPrr(0x29, r0, r1) /* r1-r0 -> r1 */
-#define SUBI(i, r) OP(0x81, 0x03, 0x05, r);/* r-i -> r */ \
- WORD $i;
-
-#define STOSW STOSL
-
-#define CALL16(f) LWI(f, rDI); /* &f -> rDI */ \
- BYTE $0xFF; /* (*rDI) */ \
- BYTE $0xD7;
-#define FARJUMP16(s, o) BYTE $0xEA; /* jump to ptr16:16 */ \
- WORD $o; WORD $s
-#define FARJUMP32(s, o) BYTE $0x66; /* jump to ptr32:16 */ \
- BYTE $0xEA; LONG $o; WORD $s
-#define DELAY BYTE $0xEB; /* jmp .+2 */ \
- BYTE $0x00
-#define BIOSCALL(b) INT $b /* INT $b */
-
-#define PEEKW BYTE $0x26; /* MOVW rES:[rBX], rAX */ \
- BYTE $0x8B; BYTE $0x07
-#define POKEW BYTE $0x26; /* MOVW rAX, rES:[rBX] */ \
- BYTE $0x89; BYTE $0x07
-#define OUTPORTB(p, d) LBI(d, rAL); /* d -> I/O port p */ \
- BYTE $0xE6; \
- BYTE $p; DELAY
-#define PUSHA BYTE $0x60
-#define PUSHR(r) BYTE $(0x50|r) /* r -> (--rSP) */
-#define PUSHS(rS) BYTE $(0x06|((rS)<<3)) /* rS -> (--rSP) */
-#define PUSHI(i) BYTE $0x68; WORD $i; /* i -> --(rSP) */
-#define POPA BYTE $0x61
-#define POPR(r) BYTE $(0x58|r) /* (rSP++) -> r */
-#define POPS(rS) BYTE $(0x07|((rS)<<3)) /* (rSP++) -> r */
-#define NOP BYTE $0x90 /* nop */
-
-#define LGDT(gdtptr) BYTE $0x0F; /* LGDT */ \
- BYTE $0x01; BYTE $0x16; \
- WORD $gdtptr
-
-/* operand size switch. */
-#define OPSIZE BYTE $0x66
-
--- a/os/boot/puma/8250.c
+++ /dev/null
@@ -1,312 +1,0 @@
-#include "boot.h"
-
-/*
- * INS8250 uart
- */
-enum
-{
- /*
- * register numbers
- */
- Data= 0, /* xmit/rcv buffer */
- Iena= 1, /* interrupt enable */
- Ircv= (1<<0), /* for char rcv'd */
- Ixmt= (1<<1), /* for xmit buffer empty */
- Irstat=(1<<2), /* for change in rcv'er status */
- Imstat=(1<<3), /* for change in modem status */
- Istat= 2, /* interrupt flag (read) */
- Tctl= 2, /* test control (write) */
- Format= 3, /* byte format */
- Bits8= (3<<0), /* 8 bits/byte */
- Stop2= (1<<2), /* 2 stop bits */
- Pena= (1<<3), /* generate parity */
- Peven= (1<<4), /* even parity */
- Pforce=(1<<5), /* force parity */
- Break= (1<<6), /* generate a break */
- Dra= (1<<7), /* address the divisor */
- Mctl= 4, /* modem control */
- Dtr= (1<<0), /* data terminal ready */
- Rts= (1<<1), /* request to send */
- Ri= (1<<2), /* ring */
- Inton= (1<<3), /* turn on interrupts */
- Loop= (1<<4), /* loop back */
- Lstat= 5, /* line status */
- Inready=(1<<0), /* receive buffer full */
- Oerror=(1<<1), /* receiver overrun */
- Perror=(1<<2), /* receiver parity error */
- Ferror=(1<<3), /* rcv framing error */
- Outready=(1<<5), /* output buffer empty */
- Mstat= 6, /* modem status */
- Ctsc= (1<<0), /* clear to send changed */
- Dsrc= (1<<1), /* data set ready changed */
- Rire= (1<<2), /* rising edge of ring indicator */
- Dcdc= (1<<3), /* data carrier detect changed */
- Cts= (1<<4), /* complement of clear to send line */
- Dsr= (1<<5), /* complement of data set ready line */
- Ring= (1<<6), /* complement of ring indicator line */
- Dcd= (1<<7), /* complement of data carrier detect line */
- Scratch=7, /* scratchpad */
- Dlsb= 0, /* divisor lsb */
- Dmsb= 1, /* divisor msb */
-
- Serial= 0,
- Modem= 1,
-};
-
-typedef struct Uart Uart;
-struct Uart
-{
- int port;
- int setup;
- uchar sticky[8]; /* sticky write register values */
- uchar txbusy;
-
- Queue *iq;
- Queue *oq;
- void (*rx)(Queue *, int);
-
- ulong frame;
- ulong overrun;
-};
-
-Uart uart[1];
-
-static void uartkick(void*);
-
-
-#define UartFREQ 1843200
-
-#define uartwrreg(u,r,v) outb((u)->port + r, (u)->sticky[r] | (v))
-#define uartrdreg(u,r) inb((u)->port + r)
-
-/*
- * set the baud rate by calculating and setting the baudrate
- * generator constant. This will work with fairly non-standard
- * baud rates.
- */
-static void
-uartsetbaud(Uart *up, int rate)
-{
- ulong brconst;
-
- brconst = (UartFREQ+8*rate-1)/(16*rate);
-
- uartwrreg(up, Format, Dra);
- outb(up->port+Dmsb, (brconst>>8) & 0xff);
- outb(up->port+Dlsb, brconst & 0xff);
- uartwrreg(up, Format, 0);
-}
-
-/*
- * toggle DTR
- */
-static void
-uartdtr(Uart *up, int n)
-{
- if(n)
- up->sticky[Mctl] |= Dtr;
- else
- up->sticky[Mctl] &= ~Dtr;
- uartwrreg(up, Mctl, 0);
-}
-
-/*
- * toggle RTS
- */
-static void
-uartrts(Uart *up, int n)
-{
- if(n)
- up->sticky[Mctl] |= Rts;
- else
- up->sticky[Mctl] &= ~Rts;
- uartwrreg(up, Mctl, 0);
-}
-
-static void
-uartintr(Ureg*, void *arg)
-{
- Uart *up;
- int ch;
- int s, l, loops;
-
- up = arg;
- for(loops = 0; loops < 1024; loops++){
- s = uartrdreg(up, Istat);
- switch(s){
- case 6: /* receiver line status */
- l = uartrdreg(up, Lstat);
- if(l & Ferror)
- up->frame++;
- if(l & Oerror)
- up->overrun++;
- break;
-
- case 4: /* received data available */
- case 12:
- ch = inb(up->port+Data);
- if(up->iq)
- if(up->rx)
- (*up->rx)(up->iq, ch);
- else
- qbputc(up->iq, ch);
- break;
-
- case 2: /* transmitter empty */
- ch = -1;
- if(up->oq)
- ch = qbgetc(up->oq);
- if(ch != -1)
- outb(up->port+Data, ch);
- else
- up->txbusy = 0;
- break;
-
- case 0: /* modem status */
- uartrdreg(up, Mstat);
- break;
-
- default:
- if(s&1)
- return;
- print("weird modem interrupt #%2.2ux\n", s);
- break;
- }
- }
- panic("uartintr: 0x%2.2ux\n", uartrdreg(up, Istat));
-}
-
-/*
- * turn on a port's interrupts. set DTR and RTS
- */
-static void
-uartenable(Uart *up)
-{
- /*
- * turn on interrupts
- */
- up->sticky[Iena] = 0;
- if(up->oq)
- up->sticky[Iena] |= Ixmt;
- if(up->iq)
- up->sticky[Iena] |= Ircv|Irstat;
- uartwrreg(up, Iena, 0);
-
- /*
- * turn on DTR and RTS
- */
- uartdtr(up, 1);
- uartrts(up, 1);
-}
-
-void
-uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue *, int))
-{
- Uart *up = &uart[0];
-
- if(up->setup)
- return;
- up->setup = 1;
-
- *iq = up->iq = qopen(4*1024, 0, 0, 0);
- *oq = up->oq = qopen(16*1024, 0, uartkick, up);
- switch(port){
-
- case 0:
- up->port = 0x3F8;
- setvec(V_COM1, uartintr, up);
- break;
-
- case 1:
- up->port = 0x2F8;
- setvec(V_COM2, uartintr, up);
- break;
-
- default:
- return;
- }
-
- /*
- * set rate to 9600 baud.
- * 8 bits/character.
- * 1 stop bit.
- * interrupts enabled.
- */
- uartsetbaud(up, 9600);
- up->sticky[Format] = Bits8;
- uartwrreg(up, Format, 0);
- up->sticky[Mctl] |= Inton;
- uartwrreg(up, Mctl, 0x0);
-
- up->rx = rx;
- uartenable(up);
- if(baud)
- uartsetbaud(up, baud);
-}
-
-static void
-uartputc(int c)
-{
- Uart *up = &uart[0];
- int i;
-
- for(i = 0; i < 100; i++){
- if(uartrdreg(up, Lstat) & Outready)
- break;
- delay(1);
- }
- outb(up->port+Data, c);
-}
-
-void
-uartputs(char *s, int n)
-{
- Uart *up = &uart[0];
- Block *b;
- int nl;
- char *p;
-
- nl = 0;
- for(p = s; p < s+n; p++)
- if(*p == '\n')
- nl++;
- b = iallocb(n+nl);
- while(n--){
- if(*s == '\n')
- *b->wp++ = '\r';
- *b->wp++ = *s++;
- }
- qbwrite(up->oq, b);
-}
-
-/*
- * (re)start output
- */
-static void
-uartkick(void *arg)
-{
- Uart *up = arg;
- int x, n, c;
-
- x = splhi();
- while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1) {
- n = 0;
- while((uartrdreg(up, Lstat) & Outready) == 0){
- if(++n > 100000){
- print("stuck serial line\n");
- break;
- }
- }
- outb(up->port + Data, c);
- }
- splx(x);
-}
-
-void
-uartwait(void)
-{
- Uart *up = &uart[0];
-
- while(up->txbusy)
- ;
-}
--- a/os/boot/puma/alarm.c
+++ /dev/null
@@ -1,123 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#define MAXALARM 10
-
-Alarm alarmtab[MAXALARM];
-
-/*
- * Insert new into list after where
- */
-void
-insert(List **head, List *where, List *new)
-{
- if(where == 0){
- new->next = *head;
- *head = new;
- }else{
- new->next = where->next;
- where->next = new;
- }
-
-}
-
-/*
- * Delete old from list. where->next is known to be old.
- */
-void
-delete(List **head, List *where, List *old)
-{
- if(where == 0){
- *head = old->next;
- return;
- }
- where->next = old->next;
-}
-
-Alarm*
-newalarm(void)
-{
- int i;
- Alarm *a;
-
- for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
- if(a->busy==0 && a->f==0){
- a->f = 0;
- a->arg = 0;
- a->busy = 1;
- return a;
- }
- panic("newalarm");
- return 0; /* not reached */
-}
-
-Alarm*
-alarm(int ms, void (*f)(Alarm*), void *arg)
-{
- Alarm *a, *w, *pw;
- ulong s;
-
- if(ms < 0)
- ms = 0;
- s = splhi();
- a = newalarm();
- a->dt = MS2TK(ms);
- a->f = f;
- a->arg = arg;
- pw = 0;
- for(w=m->alarm; w; pw=w, w=w->next){
- if(w->dt <= a->dt){
- a->dt -= w->dt;
- continue;
- }
- w->dt -= a->dt;
- break;
- }
- insert(&m->alarm, pw, a);
- splx(s);
- return a;
-}
-
-void
-cancel(Alarm *a)
-{
- a->f = 0;
-}
-
-void
-alarminit(void)
-{
-}
-
-#define NA 10 /* alarms per clock tick */
-void
-checkalarms(void)
-{
- int i, n, s;
- Alarm *a;
- void (*f)(void*);
- Alarm *alist[NA];
-
- s = splhi();
- a = m->alarm;
- if(a){
- for(n=0; a && a->dt<=0 && n<NA; n++){
- alist[n] = a;
- delete(&m->alarm, 0, a);
- a = m->alarm;
- }
- if(a)
- a->dt--;
-
- for(i = 0; i < n; i++){
- f = alist[i]->f; /* avoid race with cancel */
- if(f)
- (*f)(alist[i]);
- alist[i]->busy = 0;
- }
- }
- splx(s);
-}
--- a/os/boot/puma/armv4.h
+++ /dev/null
@@ -1,99 +1,0 @@
-/*
- * PSR
- */
-#define PsrMusr 0x10 /* mode */
-#define PsrMfiq 0x11
-#define PsrMirq 0x12
-#define PsrMsvc 0x13
-#define PsrMabt 0x17
-#define PsrMund 0x1B
-#define PsrMsys 0x1F
-#define PsrMask 0x1F
-
-#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
-#define PsrDirq 0x00000080 /* disable IRQ interrupts */
-
-#define PsrV 0x10000000 /* overflow */
-#define PsrC 0x20000000 /* carry/borrow/extend */
-#define PsrZ 0x40000000 /* zero */
-#define PsrN 0x80000000 /* negative/less than */
-
-/*
- * Internal MMU coprocessor registers
- */
-#define CpCPUID 0 /* R: */
-#define CpControl 1 /* R: */
-#define CpTTB 2 /* W: translation table base */
-#define CpDAC 3 /* W: domain access control */
-#define CpFSR 5 /* R: fault status */
-#define CpTLBflush 5 /* W: */
-#define CpFAR 6 /* R: fault address */
-#define CpTLBpurge 6 /* W: */
-#define CpCacheCtl 7 /* W: */
-
-#define CpDebug 14 /* R/W: debug registers */
-/*
- * Coprocessors
- */
-#define CpMMU 15
-
-/*
- * Internal MMU coprocessor registers
- */
-#define CpCmmu 0x00000001 /* M: MMU enable */
-#define CpCalign 0x00000002 /* A: alignment fault enable */
-#define CpCDcache 0x00000004 /* C: instruction/data cache on */
-#define CpCwb 0x00000008 /* W: write buffer turned on */
-#define CpCi32 0x00000010 /* P: 32-bit programme space */
-#define CpCd32 0x00000020 /* D: 32-bit data space */
-#define CpCbe 0x00000080 /* B: big-endian operation */
-#define CpCsystem 0x00000100 /* S: system permission */
-#define CpCrom 0x00000200 /* R: ROM permission */
-#define CpCIcache 0x00001000 /* C: Instruction Cache on */
-
-/*
- * Debug support internal registers
- */
-#define CpDBAR 0
-#define CpDBVR 1
-#define CpDBMR 2
-#define CpDBCR 3
-#define CpIBCR 8
-/*
- * MMU
- */
-/*
- * Small pages:
- * L1: 12-bit index -> 4096 descriptors -> 16Kb
- * L2: 8-bit index -> 256 descriptors -> 1Kb
- * Each L2 descriptor has access permissions for 4 1Kb sub-pages.
- *
- * TTB + L1Tx gives address of L1 descriptor
- * L1 descriptor gives PTBA
- * PTBA + L2Tx gives address of L2 descriptor
- * L2 descriptor gives PBA
- */
-#define MmuTTB(pa) ((pa) & ~0x3FFF) /* translation table base */
-#define MmuL1x(pa) (((pa)>>20) & 0xFFF) /* L1 table index */
-#define MmuPTBA(pa) ((pa) & ~0x3FF) /* page table base address */
-#define MmuL2x(pa) (((pa)>>12) & 0xFF) /* L2 table index */
-#define MmuPBA(pa) ((pa) & ~0xFFF) /* page base address */
-#define MmuSBA(pa) ((pa) & ~0xFFFFF) /* section base address */
-
-#define MmuL1page 0x011 /* descriptor is for L2 pages */
-#define MmuL1section 0x012 /* descriptor is for section */
-
-#define MmuL2invalid 0x000
-#define MmuL2large 0x001 /* large */
-#define MmuL2small 0x002 /* small */
-#define MmuWB 0x004 /* data goes through write buffer */
-#define MmuIDC 0x008 /* data placed in cache */
-
-#define MmuDAC(d) (((d) & 0xF)<<5) /* L1 domain */
-#define MmuAP(i, v) ((v)<<(((i)*2)+4)) /* access permissions */
-#define MmuL1AP(v) MmuAP(3, (v))
-#define MmuL2AP(v) MmuAP(3, (v))|MmuAP(2, (v))|MmuAP(1, (v))|MmuAP(0, (v))
-#define MmuAPsro 0 /* supervisor rw */
-#define MmuAPsrw 1 /* supervisor rw */
-#define MmuAPuro 2 /* supervisor rw + user ro */
-#define MmuAPurw 3 /* supervisor rw + user rw */
--- a/os/boot/puma/boot.h
+++ /dev/null
@@ -1,12 +1,0 @@
-#include <u.h>
-#include "lib.h"
-
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-
-#include "armv4.h"
-#include "puma.h"
-
--- a/os/boot/puma/bootp.c
+++ /dev/null
@@ -1,502 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ip.h"
-
-uchar broadcast[Eaddrlen] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static ushort tftpport = 5000;
-static int Id = 1;
-static Netaddr myaddr;
-static Netaddr server;
-
-typedef struct {
- uchar header[4];
- uchar data[Segsize];
-} Tftp;
-static Tftp tftpb;
-
-static void
-hnputs(uchar *ptr, ushort val)
-{
- ptr[0] = val>>8;
- ptr[1] = val;
-}
-
-static void
-hnputl(uchar *ptr, ulong val)
-{
- ptr[0] = val>>24;
- ptr[1] = val>>16;
- ptr[2] = val>>8;
- ptr[3] = val;
-}
-
-static ulong
-nhgetl(uchar *ptr)
-{
- return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
-}
-
-static ushort
-nhgets(uchar *ptr)
-{
- return ((ptr[0]<<8) | ptr[1]);
-}
-
-static short endian = 1;
-static char* aendian = (char*)&endian;
-#define LITTLE *aendian
-
-static ushort
-ptcl_csum(void *a, int len)
-{
- uchar *addr;
- ulong t1, t2;
- ulong losum, hisum, mdsum, x;
-
- addr = a;
- losum = 0;
- hisum = 0;
- mdsum = 0;
-
- x = 0;
- if((ulong)addr & 1) {
- if(len) {
- hisum += addr[0];
- len--;
- addr++;
- }
- x = 1;
- }
- while(len >= 16) {
- t1 = *(ushort*)(addr+0);
- t2 = *(ushort*)(addr+2); mdsum += t1;
- t1 = *(ushort*)(addr+4); mdsum += t2;
- t2 = *(ushort*)(addr+6); mdsum += t1;
- t1 = *(ushort*)(addr+8); mdsum += t2;
- t2 = *(ushort*)(addr+10); mdsum += t1;
- t1 = *(ushort*)(addr+12); mdsum += t2;
- t2 = *(ushort*)(addr+14); mdsum += t1;
- mdsum += t2;
- len -= 16;
- addr += 16;
- }
- while(len >= 2) {
- mdsum += *(ushort*)addr;
- len -= 2;
- addr += 2;
- }
- if(x) {
- if(len)
- losum += addr[0];
- if(LITTLE)
- losum += mdsum;
- else
- hisum += mdsum;
- } else {
- if(len)
- hisum += addr[0];
- if(LITTLE)
- hisum += mdsum;
- else
- losum += mdsum;
- }
-
- losum += hisum >> 8;
- losum += (hisum & 0xff) << 8;
- while(hisum = losum>>16)
- losum = hisum + (losum & 0xffff);
-
- return ~losum;
-}
-
-static ushort
-ip_csum(uchar *addr)
-{
- int len;
- ulong sum = 0;
-
- len = (addr[0]&0xf)<<2;
-
- while(len > 0) {
- sum += addr[0]<<8 | addr[1] ;
- len -= 2;
- addr += 2;
- }
-
- sum = (sum & 0xffff) + (sum >> 16);
- sum = (sum & 0xffff) + (sum >> 16);
- return (sum^0xffff);
-}
-
-static void
-udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
-{
- Udphdr *uh;
- Etherhdr *ip;
- Etherpkt pkt;
- int len, ptcllen;
-
-
- uh = (Udphdr*)&pkt;
-
- memset(uh, 0, sizeof(Etherpkt));
- memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
-
- /*
- * UDP portion
- */
- ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
- uh->ttl = 0;
- uh->udpproto = IP_UDPPROTO;
- uh->frag[0] = 0;
- uh->frag[1] = 0;
- hnputs(uh->udpplen, ptcllen);
- hnputl(uh->udpsrc, myaddr.ip);
- hnputs(uh->udpsport, myaddr.port);
- hnputl(uh->udpdst, a->ip);
- hnputs(uh->udpdport, a->port);
- hnputs(uh->udplen, ptcllen);
- uh->udpcksum[0] = 0;
- uh->udpcksum[1] = 0;
- dlen = (dlen+1)&~1;
- hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
-
- /*
- * IP portion
- */
- ip = (Etherhdr*)&pkt;
- len = sizeof(Udphdr)+dlen;
- ip->vihl = IP_VER|IP_HLEN;
- ip->tos = 0;
- ip->ttl = 255;
- hnputs(ip->length, len-ETHER_HDR);
- hnputs(ip->id, Id++);
- ip->frag[0] = 0;
- ip->frag[1] = 0;
- ip->cksum[0] = 0;
- ip->cksum[1] = 0;
- hnputs(ip->cksum, ip_csum(&ip->vihl));
-
- /*
- * Ethernet MAC portion
- */
- hnputs(ip->type, ET_IP);
- memmove(ip->d, a->ea, sizeof(ip->d));
-
- ethertxpkt(ctlrno, &pkt, len, Timeout);
-}
-
-static void
-nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
-{
- int n;
- char buf[128];
-
- buf[0] = 0;
- buf[1] = Tftp_ERROR;
- buf[2] = 0;
- buf[3] = code;
- strcpy(buf+4, msg);
- n = strlen(msg) + 4 + 1;
- udpsend(ctlrno, a, buf, n);
- if(report)
- print("\ntftp: error(%d): %s\n", code, msg);
-}
-
-static int
-udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
-{
- int n, len;
- ushort csm;
- Udphdr *h;
- ulong addr, timo;
- Etherpkt pkt;
- static int rxactive;
-
- if(rxactive == 0)
- timo = 1000;
- else
- timo = Timeout;
- timo += TK2MS(m->ticks);
- while(timo > TK2MS(m->ticks)){
- n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
-
- if(n <= 0)
- continue;
-
- h = (Udphdr*)&pkt;
- if(nhgets(h->type) != ET_IP)
- continue;
-
- if(ip_csum(&h->vihl)) {
- print("ip chksum error\n");
- continue;
- }
- if(h->vihl != (IP_VER|IP_HLEN)) {
- print("ip bad vers/hlen\n");
- continue;
- }
-
- if(h->udpproto != IP_UDPPROTO)
- continue;
-
- h->ttl = 0;
- len = nhgets(h->udplen);
- hnputs(h->udpplen, len);
-
- if(nhgets(h->udpcksum)) {
- csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
- if(csm != 0) {
- print("udp chksum error csum #%4lux len %d\n", csm, n);
- break;
- }
- }
-
- if(a->port != 0 && nhgets(h->udpsport) != a->port)
- continue;
-
- addr = nhgetl(h->udpsrc);
- if(a->ip != Bcastip && addr != a->ip)
- continue;
-
- len -= UDP_HDRSIZE-UDP_PHDRSIZE;
- if(len > dlen) {
- print("udp: packet too big\n");
- continue;
- }
-
- memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
- a->ip = addr;
- a->port = nhgets(h->udpsport);
- memmove(a->ea, pkt.s, sizeof(a->ea));
-
- rxactive = 1;
- return len;
- }
-
- return 0;
-}
-
-static int tftpblockno;
-
-static int
-tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
-{
- int i, len, rlen, oport;
- char buf[Segsize+2];
-
- buf[0] = 0;
- buf[1] = Tftp_READ;
- len = sprint(buf+2, "%s", name) + 2;
- len += sprint(buf+len+1, "octet") + 2;
-
- oport = a->port;
- for(i = 0; i < 5; i++){
- a->port = oport;
- udpsend(ctlrno, a, buf, len);
- a->port = 0;
- if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
- continue;
-
- switch((tftp->header[0]<<8)|tftp->header[1]){
-
- case Tftp_ERROR:
- print("tftpopen: error (%d): %s\n",
- (tftp->header[2]<<8)|tftp->header[3], tftp->data);
- return -1;
-
- case Tftp_DATA:
- tftpblockno = 1;
- len = (tftp->header[2]<<8)|tftp->header[3];
- if(len != tftpblockno){
- print("tftpopen: block error: %d\n", len);
- nak(ctlrno, a, 1, "block error", 0);
- return -1;
- }
- return rlen-sizeof(tftp->header);
- }
- }
-
- print("tftpopen: failed to connect to server\n");
- return -1;
-}
-
-static int
-tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
-{
- int blockno, len, retry;
- uchar buf[4];
-
- buf[0] = 0;
- buf[1] = Tftp_ACK;
- buf[2] = tftpblockno>>8;
- buf[3] = tftpblockno;
- tftpblockno++;
-
- dlen += sizeof(tftp->header);
-
- retry = 0;
-buggery:
- udpsend(ctlrno, a, buf, sizeof(buf));
-
- if((len = udprecv(ctlrno, a, tftp, dlen)) != dlen){
- print("tftpread: %d != %d\n", len, dlen);
- nak(ctlrno, a, 2, "short read", 0);
- if(retry++ < 5)
- goto buggery;
- return -1;
- }
-
- blockno = (tftp->header[2]<<8)|tftp->header[3];
- if(blockno != tftpblockno){
- print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
-
- if(blockno == tftpblockno-1 && retry++ < 5)
- goto buggery;
- nak(ctlrno, a, 1, "block error", 0);
-
- return -1;
- }
-
- return len-sizeof(tftp->header);
-}
-
-int
-bootp(int ctlrno, char *file)
-{
- Bootp req, rep;
- int i, dlen, segsize, text, data, bss, total;
- uchar *ea, *addr, *p;
- ulong entry;
- Exec *exec;
- char name[128], *filename, *sysname;
-
- if((ea = etheraddr(ctlrno)) == 0){
- print("invalid ctlrno %d\n", ctlrno);
- return -1;
- }
-
- filename = 0;
- sysname = 0;
- if(file && *file){
- strcpy(name, file);
- if(filename = strchr(name, ':')){
- if(filename != name && *(filename-1) != '\\'){
- sysname = name;
- *filename++ = 0;
- }
- }
- else
- filename = name;
- }
-
-
- memset(&req, 0, sizeof(req));
- req.op = Bootrequest;
- req.htype = 1; /* ethernet */
- req.hlen = Eaddrlen; /* ethernet */
- memmove(req.chaddr, ea, Eaddrlen);
-
- myaddr.ip = 0;
- myaddr.port = BPportsrc;
- memmove(myaddr.ea, ea, Eaddrlen);
-
- for(i = 0; i < 10; i++) {
- server.ip = Bcastip;
- server.port = BPportdst;
- memmove(server.ea, broadcast, sizeof(server.ea));
- udpsend(ctlrno, &server, &req, sizeof(req));
- if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
- continue;
- if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
- continue;
- if(rep.htype != 1 || rep.hlen != Eaddrlen)
- continue;
- if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
- break;
- }
- if(i >= 10) {
- print("bootp timed out\n");
- return -1;
- }
-
- if(filename == 0 || *filename == 0)
- filename = rep.file;
-
- if(rep.sname[0] != '\0')
- print("%s ", rep.sname);
- print("(%d.%d.%d.%d!%d): %s\n",
- rep.siaddr[0],
- rep.siaddr[1],
- rep.siaddr[2],
- rep.siaddr[3],
- server.port,
- filename);
-
- myaddr.ip = nhgetl(rep.yiaddr);
- myaddr.port = tftpport++;
- server.ip = nhgetl(rep.siaddr);
- server.port = TFTPport;
-
- if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
- return -1;
-
- exec = (Exec*)(tftpb.data);
- if(dlen < sizeof(Exec) || GLLONG(exec->magic) != E_MAGIC){
- nak(ctlrno, &server, 0, "bad magic number", 1);
- return -1;
- }
- text = GLLONG(exec->text);
- data = GLLONG(exec->data);
- bss = GLLONG(exec->bss);
- total = text+data+bss;
- entry = GLLONG(exec->entry);
-print("load@%8.8lux: ", PADDR(entry));
- print("%d", text);
-
- addr = (uchar*)PADDR(entry);
- p = tftpb.data+sizeof(Exec);
- dlen -= sizeof(Exec);
- segsize = text;
- for(;;){
- if(dlen == 0){
- if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
- return -1;
- p = tftpb.data;
- }
- if(segsize <= dlen)
- i = segsize;
- else
- i = dlen;
- memmove(addr, p, i);
-
- addr += i;
- p += i;
- segsize -= i;
- dlen -= i;
-
- if(segsize <= 0){
- if(data == 0)
- break;
- print("+%d", data);
- segsize = data;
- data = 0;
- addr = (uchar*)PGROUND((ulong)addr);
- }
- }
- nak(ctlrno, &server, 3, "ok", 0); /* tftpclose */
- print("+%d=%d\n", bss, total);
- print("entry: 0x%lux\n", entry);
-
- (*(void(*)(void))(PADDR(entry)))();
-
- return 0;
-}
--- a/os/boot/puma/cga.c
+++ /dev/null
@@ -1,92 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "io.h"
-#include "fns.h"
-
-enum {
- Width = 160,
- Height = 25,
-
- Attr = 7, /* white on black */
-};
-
-#define CGASCREENBASE ((uchar*)KADDR(0xB8000))
-
-static int pos;
-static int screeninitdone;
-
-static uchar
-cgaregr(int index)
-{
- outb(0x3D4, index);
- return inb(0x3D4+1) & 0xFF;
-}
-
-static void
-cgaregw(int index, int data)
-{
- outb(0x3D4, index);
- outb(0x3D4+1, data);
-}
-
-static void
-movecursor(void)
-{
- cgaregw(0x0E, (pos/2>>8) & 0xFF);
- cgaregw(0x0F, pos/2 & 0xFF);
- CGASCREENBASE[pos+1] = Attr;
-}
-
-static void
-cgascreenputc(int c)
-{
- int i;
-
- if(c == '\n'){
- pos = pos/Width;
- pos = (pos+1)*Width;
- }
- else if(c == '\t'){
- i = 8 - ((pos/2)&7);
- while(i-->0)
- cgascreenputc(' ');
- }
- else if(c == '\b'){
- if(pos >= 2)
- pos -= 2;
- cgascreenputc(' ');
- pos -= 2;
- }
- else{
- CGASCREENBASE[pos++] = c;
- CGASCREENBASE[pos++] = Attr;
- }
- if(pos >= Width*Height){
- memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
- memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
- pos = Width*(Height-1);
- }
- movecursor();
-}
-
-void
-screeninit(void)
-{
- if(screeninitdone == 0){
- pos = cgaregr(0x0E)<<8;
- pos |= cgaregr(0x0F);
- pos *= 2;
- screeninitdone = 1;
- }
-}
-
-void
-cgascreenputs(char* s, int n)
-{
- if(screeninitdone == 0)
- screeninit();
- while(n-- > 0)
- cgascreenputc(*s++);
-}
--- a/os/boot/puma/clock.c
+++ /dev/null
@@ -1,154 +1,0 @@
-#include "boot.h"
-
- /*
- * Control Word Read/Write Counter (mode 0) LSB, MSB
- */
-#define PIT_RW_COUNTER0 0x30
-#define PIT_RW_COUNTER1 0x70
-#define PIT_RW_COUNTER2 0xB0
-#define PIT_COUNTERLATCH0 0x00
-#define PIT_COUNTERLATCH1 0x40
-#define PIT_COUNTERLATCH2 0x80
-
-#define PIT_MODE_0 0 /* Interrupt on Terminal Count */
-#define PIT_MODE_1 2 /* Hardware Retriggeable One-shot */
-#define PIT_MODE_2 4 /* Rate Generator */
-#define PIT_MODE_3 6 /* Square Wave Mode */
-#define PIT_MODE_4 8 /* Software Triggered Mode */
-#define PIT_MODE_5 10 /* Hardware Triggered Mode (Retriggeable) */
-
-/*
- * Harris 82C54 Programmable Interval Timer
- * On the Puma board the PIT is memory mapped
- * starting at 0xf2000000 and with each of the 8-bit
- * registers addressed on a consecutive 4-byte boundary.
- */
-#undef inb
-#undef outb
-#define inb(port) ((*(uchar *)(port))&0xff)
-#define outb(port, data) (*(uchar *)(port) = (data))
-enum
-{
- Cnt0= 0xf2000000, /* counter locations */
- Cnt1= 0xf2000004, /* ... */
- Cnt2= 0xf2000008, /* ... */
- Ctlw= 0xf200000c, /* control word register*/
-
- /* commands */
- Latch0= 0x00, /* latch counter 0's value */
- Load0= 0x30, /* load counter 0 with 2 bytes */
- Latch1= 0x40, /* latch counter 1's value */
- Load1= 0x70, /* load counter 1 with 2 bytes */
-
- /* modes */
- Square= 0x06, /* periodic square wave */
- RateGen= 0x04, /* rate generator */
-
- Freq= 3686400, /* Real clock frequency */
-};
-
-static int cpufreq = 233000000;
-static int aalcycles = 14;
-
-static void
-clockintr(Ureg*, void*)
-{
- m->ticks++;
- checkalarms();
-}
-
-/*
- * delay for l milliseconds more or less. delayloop is set by
- * clockinit() to match the actual CPU speed.
- */
-void
-delay(int l)
-{
- l *= m->delayloop;
- if(l <= 0)
- l = 1;
- aamloop(l);
-}
-
-void
-microdelay(int l)
-{
- l *= m->delayloop;
- l /= 1000;
- if(l <= 0)
- l = 1;
- aamloop(l);
-}
-
-void
-clockinit(void)
-{
- int x, y; /* change in counter */
- int loops, incr;
-
- /*
- * set vector for clock interrupts
- */
- setvec(V_TIMER0, clockintr, 0);
-
- /*
- * set clock for 1/HZ seconds
- */
- outb(Ctlw, Load0|Square);
- outb(Cnt0, (Freq/HZ)); /* low byte */
- outb(Cnt0, (Freq/HZ)>>8); /* high byte */
-
- /* find biggest loop that doesn't wrap */
- incr = 16000000/(aalcycles*HZ*2);
- x = 2000;
- for(loops = incr; loops < 64*1024; loops += incr) {
- /*
- * measure time for the loop
- * TEXT aamloop(SB), $-4
- * _aamloop:
- * MOVW R0, R0
- * MOVW R0, R0
- * MOVW R0, R0
- * SUB $1, R0
- * CMP $0, R0
- * BNE _aamloop
- * RET
- *
- * the time for the loop should be independent of external
- * cache and memory system since it fits in the execution
- * prefetch buffer.
- *
- */
- outb(Ctlw, Latch0);
- x = inb(Cnt0);
- x |= inb(Cnt0)<<8;
- aamloop(loops);
- outb(Ctlw, Latch0);
- y = inb(Cnt0);
- y |= inb(Cnt0)<<8;
- x -= y;
-
- if(x < 0)
- x += Freq/HZ;
-
- if(x > Freq/(3*HZ))
- break;
- }
-
- /*
- * counter goes at twice the frequency, once per transition,
- * i.e., twice per square wave
- */
- x >>= 1;
-
- /*
- * figure out clock frequency and a loop multiplier for delay().
- */
- cpufreq = loops*((aalcycles*Freq)/x);
- m->delayloop = (cpufreq/1000)/aalcycles; /* AAMLOOPs for 1 ms */
-
- /*
- * add in possible .2% error and convert to MHz
- */
- m->speed = (cpufreq + cpufreq/500)/1000000;
-}
--- a/os/boot/puma/conf.c
+++ /dev/null
@@ -1,181 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "dosfs.h"
-
-static char *confname[MAXCONF];
-static char *confval[MAXCONF];
-static int nconf;
-
-static char* defplan9ini =
- "ether0=type=CS8900\r\n"
- "vgasize=640x480x8\r\n"
- "kernelpercent=40\r\n"
- "console=1\r\nbaud=9600\r\n"
-;
-
-extern char **ini;
-
-char*
-getconf(char *name)
-{
- int i;
-
- for(i = 0; i < nconf; i++)
- if(strcmp(confname[i], name) == 0)
- return confval[i];
- return 0;
-}
-
-/*
- * read configuration file
- */
-int
-plan9ini(Dos *dos, char *val)
-{
- Dosfile rc;
- int i, n;
- char *cp, *p, *q, *line[MAXCONF];
-
- cp = BOOTARGS;
- if(dos) {
- if(dosstat(dos, *ini, &rc) <= 0)
- return -1;
-
- *cp = 0;
- n = dosread(&rc, cp, BOOTARGSLEN-1);
- if(n <= 0)
- return -1;
- cp[n] = 0;
- } else if(val != nil){
- if(memchr(val, 0, BOOTARGSLEN-1) == nil)
- return -1;
- print("Using flash configuration\n");
- strcpy(cp, val);
- n = strlen(cp);
- }else{
- print("Using default configuration\n");
- strcpy(cp, defplan9ini);
- n = strlen(cp);
- }
-
- /*
- * Make a working copy.
- * We could change this to pass the parsed strings
- * to the booted programme instead of the raw
- * string, then it only gets done once.
- */
- memmove(cp+BOOTARGSLEN, cp, n+1);
- cp += BOOTARGSLEN;
-
- /*
- * Strip out '\r', change '\t' -> ' '.
- */
- p = cp;
- for(q = cp; *q; q++){
- if(*q == '\r')
- continue;
- if(*q == '\t')
- *q = ' ';
- *p++ = *q;
- }
- *p = 0;
- n = getcfields(cp, line, MAXCONF, "\n");
- for(i = 0; i < n; i++){
- cp = strchr(line[i], '=');
- if(cp == 0)
- continue;
- *cp++ = 0;
- if(cp - line[i] >= NAMELEN+1)
- *(line[i]+NAMELEN-1) = 0;
- confname[nconf] = line[i];
- confval[nconf] = cp;
- nconf++;
- }
- return 0;
-}
-
-static int
-parseether(uchar *to, char *from)
-{
- char nip[4];
- char *p;
- int i;
-
- p = from;
- while(*p == ' ')
- ++p;
- for(i = 0; i < 6; i++){
- if(*p == 0)
- return -1;
- nip[0] = *p++;
- if(*p == 0)
- return -1;
- nip[1] = *p++;
- nip[2] = 0;
- to[i] = strtoul(nip, 0, 16);
- if(*p == ':')
- p++;
- }
- return 0;
-}
-
-int
-isaconfig(char *class, int ctlrno, ISAConf *isa)
-{
- char cc[NAMELEN], *p, *q, *r;
- int n;
-
- sprint(cc, "%s%d", class, ctlrno);
- for(n = 0; n < nconf; n++){
- if(strncmp(confname[n], cc, NAMELEN))
- continue;
- isa->nopt = 0;
- p = confval[n];
- while(*p){
- while(*p == ' ' || *p == '\t')
- p++;
- if(*p == '\0')
- break;
- if(strncmp(p, "type=", 5) == 0){
- p += 5;
- for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
- if(*p == '\0' || *p == ' ' || *p == '\t')
- break;
- *q = *p++;
- }
- *q = '\0';
- }
- else if(strncmp(p, "port=", 5) == 0)
- isa->port = strtoul(p+5, &p, 0);
- else if(strncmp(p, "irq=", 4) == 0)
- isa->irq = strtoul(p+4, &p, 0);
- else if(strncmp(p, "mem=", 4) == 0)
- isa->mem = strtoul(p+4, &p, 0);
- else if(strncmp(p, "size=", 5) == 0)
- isa->size = strtoul(p+5, &p, 0);
- else if(strncmp(p, "ea=", 3) == 0){
- if(parseether(isa->ea, p+3) == -1)
- memset(isa->ea, 0, 6);
- }
- else if(isa->nopt < NISAOPT){
- r = isa->opt[isa->nopt];
- while(*p && *p != ' ' && *p != '\t'){
- *r++ = *p++;
- if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
- break;
- }
- *r = '\0';
- isa->nopt++;
- }
- while(*p && *p != ' ' && *p != '\t')
- p++;
- }
- return 1;
- }
- return 0;
-}
--- a/os/boot/puma/console.c
+++ /dev/null
@@ -1,181 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-static Queue* consiq;
-static Queue* consoq;
-
-void
-bothputs(char *s, int n)
-{
- uartputs(s, n);
-// cgascreenputs(s, n);
-}
-
-static void (*consputs)(char*, int) = 0;
-
-void
-consinit(void)
-{
- char *p;
- int baud, port;
- static int cgadone;
-
- if((p = getconf("console")) == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
- consiq = qopen(4*1024, 0, 0, 0);
- consoq = qopen(8*1024, 0, 0, 0);
- consputs = uartputs;
- if(!cgadone) {
- cgadone = 1;
- //screeninit();
- //kbdinit();
- port = 1;
- baud = 9600;
- uartspecial(port, baud, &consiq, &consoq, kbdchar);
- }
- return;
- }
- if(0 || strstr(p, "lcd") == 0)
- consputs = bothputs;
- else
- consputs = uartputs;
-
- port = strtoul(p, 0, 0);
- baud = 0;
- if(p = getconf("baud"))
- baud = strtoul(p, 0, 0);
- if(baud == 0)
- baud = 9600;
- uartspecial(port, baud, &consiq, &consoq, kbdchar);
-}
-
-void
-kbdchar(Queue *q, int c)
-{
- c &= 0x7F;
- if(c == 0x10)
- panic("^p");
- if(q == 0) {
- if(consiq != 0)
- qbputc(consiq, c);
- } else
- qbputc(q, c);
-}
-
-static int
-getline(char *buf, int size, int dotimeout)
-{
- int c, i=0;
- ulong start;
- char echo;
-
- for (;;) {
- start = m->ticks;
- do{
- if(dotimeout && ((m->ticks - start) > 5*HZ))
- return -2;
- c = qbgetc(consiq);
- }while(c == -1);
- if(c == '\r')
- c = '\n'; /* turn carriage return into newline */
- if(c == '\177')
- c = '\010'; /* turn delete into backspace */
- if(c == '\025')
- echo = '\n'; /* echo ^U as a newline */
- else
- echo = c;
- (*consputs)(&echo, 1);
-
- if(c == '\010'){
- if(i > 0)
- i--; /* bs deletes last character */
- continue;
- }
- /* a newline ends a line */
- if (c == '\n')
- break;
- /* ^U wipes out the line */
- if (c =='\025')
- return -1;
- if(i == size)
- return size;
- buf[i++] = c;
- }
- buf[i] = 0;
- return i;
-}
-
-int
-getstr(char *prompt, char *buf, int size, char *def)
-{
- int len, isdefault;
-
- buf[0] = 0;
- isdefault = (def && *def);
- for (;;) {
- if(isdefault)
- print("%s[default==%s]: ", prompt, def);
- else
- print("%s: ", prompt);
- len = getline(buf, size, isdefault);
- switch(len){
- case -1:
- /* ^U typed */
- continue;
- case -2:
- /* timeout, use default */
- (*consputs)("\n", 1);
- len = 0;
- break;
- default:
- break;
- }
- if(len >= size){
- print("line too long\n");
- continue;
- }
- break;
- }
- if(len == 0 && isdefault)
- strcpy(buf, def);
- return 0;
-}
-
-int
-sprint(char *s, char *fmt, ...)
-{
- return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
-}
-
-int
-print(char *fmt, ...)
-{
- char buf[PRINTSIZE];
- int n;
-
- if(consputs == 0)
- return 0;
- n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
- (*consputs)(buf, n);
- return n;
-}
-
-void
-panic(char *fmt, ...)
-{
- char buf[PRINTSIZE];
- int n;
-
- if(consputs){
- (*consputs)("panic: ", 7);
- n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
- (*consputs)(buf, n);
- (*consputs)("\n", 1);
- }
- spllo();
- for(;;)
- idle();
-}
--- a/os/boot/puma/dat.h
+++ /dev/null
@@ -1,205 +1,0 @@
-typedef struct Block Block;
-typedef struct Queue Queue;
-
-typedef struct List {
- void *next;
-} List;
-
-typedef struct {
- int fake;
- int pri;
-} Lock;
-#define lock(x)
-#define unlock(x)
-
-typedef struct Alarm {
- List;
- int busy;
- long dt;
- void (*f)(void*);
- void *arg;
-} Alarm;
-
-enum {
- Eaddrlen = 6,
- ETHERMINTU = 60, /* minimum transmit size */
- ETHERMAXTU = 1514, /* maximum transmit size */
- ETHERHDRSIZE = 14, /* size of an ethernet header */
-
- MaxEther = 2,
-};
-
-typedef struct {
- uchar d[Eaddrlen];
- uchar s[Eaddrlen];
- uchar type[2];
- uchar data[1500];
- uchar crc[4];
-} Etherpkt;
-
-extern uchar broadcast[Eaddrlen];
-
-enum {
- Npart = 20+2, /* 8 sub partitions, disk, and partition */
- Maxxfer = 16*1024, /* maximum transfer size/cmd */
-};
-
-typedef struct {
- ulong start;
- ulong end;
- char name[NAMELEN+1];
-} Partition;
-
-typedef struct {
- int online;
- int npart; /* number of real partitions */
- Partition p[Npart];
- ulong offset;
- Partition *current; /* current partition */
-
- ulong cap; /* total bytes */
- int bytes; /* bytes/sector */
- int sectors; /* sectors/track */
- int heads; /* heads/cyl */
- long cyl; /* cylinders/drive */
-
- char lba; /* true if drive has logical block addressing */
- char multi; /* non-zero if drive does multiple block xfers */
-} Disc;
-
-enum {
- ScsiTestunit = 0x00,
- ScsiExtsens = 0x03,
- ScsiInquiry = 0x12,
- ScsiModesense = 0x1a,
- ScsiStartunit = 0x1B,
- ScsiStopunit = 0x1B,
- ScsiGetcap = 0x25,
- ScsiRead = 0x08,
- ScsiWrite = 0x0a,
- ScsiExtread = 0x28,
- ScsiExtwrite = 0x2a,
-
- /* data direction */
- ScsiIn = 1,
- ScsiOut = 0,
-};
-
-typedef struct Scsibuf Scsibuf;
-typedef struct Scsibuf {
- void* virt;
- void* phys;
- Scsibuf* next;
-};
-
-typedef struct Scsidata {
- uchar* base;
- uchar* lim;
- uchar* ptr;
-} Scsidata;
-
-typedef struct Ureg Ureg;
-
-typedef struct Scsi {
- ulong pid;
- ushort target;
- ushort lun;
- ushort rflag;
- ushort status;
- Scsidata cmd;
- Scsidata data;
- Scsibuf* b;
- uchar* save;
- uchar cmdblk[16];
-} Scsi;
-
-typedef struct Segdesc {
- ulong d0;
- ulong d1;
-} Segdesc;
-
-typedef struct Mach {
- ulong ticks; /* of the clock since boot time */
- ulong delayloop;
- int speed; /* general system clock in MHz */
- int oscclk; /* oscillator frequency in MHz */
- void* alarm; /* alarms bound to this clock */
-} Mach;
-
-extern Mach *m;
-
-#define E_MAGIC ((((4*20)+0)*20)+7)
-
-typedef struct Exec Exec;
-struct Exec
-{
- uchar magic[4]; /* magic number */
- uchar text[4]; /* size of text segment */
- uchar data[4]; /* size of initialized data */
- uchar bss[4]; /* size of uninitialized data */
- uchar syms[4]; /* size of symbol table */
- uchar entry[4]; /* entry point */
- uchar spsz[4]; /* size of sp/pc offset table */
- uchar pcsz[4]; /* size of pc/line number table */
-};
-
-/*
- * bootline passed by boot program
- */
-#define BOOTLINE ((char *)0x18000-150)
-
-/*
- * Where we leave configuration info.
- */
-#define BOOTARGS ((char*)(0x18000))
-#define BOOTARGSLEN 1024
-#define MAXCONF 32
-
-/*
- * a parsed plan9.ini line
- */
-#define ISAOPTLEN 16
-#define NISAOPT 8
-
-typedef struct ISAConf {
- char type[NAMELEN];
- ulong port;
- ulong irq;
- ulong mem;
- ulong size;
- uchar ea[6];
-
- int nopt;
- char opt[NISAOPT][ISAOPTLEN];
-} ISAConf;
-
-typedef struct {
- int size;
- ulong addr;
-} Map;
-
-typedef struct {
- char* name;
- Map* map;
- Map* mapend;
-
- Lock;
-} RMap;
-
-typedef struct PCIcfg PCIcfg;
-
-extern uchar* vgamem;
-
-struct Block {
- uchar *rp;
- uchar *wp;
- uchar *lim;
- uchar *data;
- Block* next;
- ulong magic;
-};
-#define BLEN(b) ((b)->wp-(b)->rp)
-
-typedef struct QLock {
- int dummy;
-} QLock;
--- a/os/boot/puma/div.s
+++ /dev/null
@@ -1,122 +1,0 @@
-/*
- * Div/Mod taken from the Inferno 2.0 ebsit code
- */
-
-Q = 0
-N = 1
-D = 2
-CC = 3
-TMP = 11
-
-TEXT save<>(SB), 1, $0
- MOVW R(Q), 0(FP)
- MOVW R(N), 4(FP)
- MOVW R(D), 8(FP)
- MOVW R(CC), 12(FP)
-
- MOVW R(TMP), R(Q) /* numerator */
- MOVW 20(FP), R(D) /* denominator */
- CMP $0, R(D)
- BNE s1
- MOVW -1(R(D)), R(TMP) /* divide by zero fault */
-s1: RET
-
-TEXT rest<>(SB), 1, $0
- MOVW 0(FP), R(Q)
- MOVW 4(FP), R(N)
- MOVW 8(FP), R(D)
- MOVW 12(FP), R(CC)
-/*
- * return to caller
- * of rest<>
- */
- MOVW 0(R13), R14
- ADD $20, R13
- B (R14)
-
-TEXT div<>(SB), 1, $0
- MOVW $32, R(CC)
-/*
- * skip zeros 8-at-a-time
- */
-e1:
- AND.S $(0xff<<24),R(Q), R(N)
- BNE e2
- SLL $8, R(Q)
- SUB.S $8, R(CC)
- BNE e1
- RET
-e2:
- MOVW $0, R(N)
-
-loop:
-/*
- * shift R(N||Q) left one
- */
- SLL $1, R(N)
- CMP $0, R(Q)
- ORR.LT $1, R(N)
- SLL $1, R(Q)
-
-/*
- * compare numerator to denominator
- * if less, subtract and set quotent bit
- */
- CMP R(D), R(N)
- ORR.HS $1, R(Q)
- SUB.HS R(D), R(N)
- SUB.S $1, R(CC)
- BNE loop
- RET
-
-TEXT _div(SB), 1, $16
- BL save<>(SB)
- CMP $0, R(Q)
- BGE d1
- RSB $0, R(Q), R(Q)
- CMP $0, R(D)
- BGE d2
- RSB $0, R(D), R(D)
-d0:
- BL div<>(SB) /* none/both neg */
- MOVW R(Q), R(TMP)
- B out
-d1:
- CMP $0, R(D)
- BGE d0
- RSB $0, R(D), R(D)
-d2:
- BL div<>(SB) /* one neg */
- RSB $0, R(Q), R(TMP)
- B out
-
-TEXT _mod(SB), 1, $16
- BL save<>(SB)
- CMP $0, R(D)
- RSB.LT $0, R(D), R(D)
- CMP $0, R(Q)
- BGE m1
- RSB $0, R(Q), R(Q)
- BL div<>(SB) /* neg numerator */
- RSB $0, R(N), R(TMP)
- B out
-m1:
- BL div<>(SB) /* pos numerator */
- MOVW R(N), R(TMP)
- B out
-
-TEXT _divu(SB), 1, $16
- BL save<>(SB)
- BL div<>(SB)
- MOVW R(Q), R(TMP)
- B out
-
-TEXT _modu(SB), 1, $16
- BL save<>(SB)
- BL div<>(SB)
- MOVW R(N), R(TMP)
- B out
-
-out:
- BL rest<>(SB)
- B out
--- a/os/boot/puma/donprint.c
+++ /dev/null
@@ -1,332 +1,0 @@
-#include "u.h"
-#include "lib.h"
-
-#define PTR sizeof(char*)
-#define SHORT sizeof(int)
-#define INT sizeof(int)
-#define LONG sizeof(long)
-#define IDIGIT 30
-#define MAXCON 30
-
-#define FLONG (1<<0)
-#define FSHORT (1<<1)
-#define FUNSIGN (1<<2)
-
-typedef struct Op Op;
-struct Op
-{
- char *p;
- char *ep;
- void *argp;
- int f1;
- int f2;
- int f3;
-};
-
-static int noconv(Op*);
-static int cconv(Op*);
-static int dconv(Op*);
-static int hconv(Op*);
-static int lconv(Op*);
-static int oconv(Op*);
-static int sconv(Op*);
-static int uconv(Op*);
-static int xconv(Op*);
-static int Xconv(Op*);
-static int percent(Op*);
-
-static
-int (*fmtconv[MAXCON])(Op*) =
-{
- noconv,
- cconv, dconv, hconv, lconv,
- oconv, sconv, uconv, xconv,
- Xconv, percent,
-};
-static
-char fmtindex[128] =
-{
- ['c'] 1,
- ['d'] 2,
- ['h'] 3,
- ['l'] 4,
- ['o'] 5,
- ['s'] 6,
- ['u'] 7,
- ['x'] 8,
- ['X'] 9,
- ['%'] 10,
-};
-
-static int convcount = { 11 };
-static int ucase;
-
-static void
-PUT(Op *o, int c)
-{
- static int pos;
- int opos;
-
- if(c == '\t'){
- opos = pos;
- pos = (opos+8) & ~7;
- while(opos++ < pos && o->p < o->ep)
- *o->p++ = ' ';
- return;
- }
- if(o->p < o->ep){
- *o->p++ = c;
- pos++;
- }
- if(c == '\n')
- pos = 0;
-}
-
-int
-fmtinstall(char c, int (*f)(Op*))
-{
-
- c &= 0177;
- if(fmtindex[c] == 0) {
- if(convcount >= MAXCON)
- return 1;
- fmtindex[c] = convcount++;
- }
- fmtconv[fmtindex[c]] = f;
- return 0;
-}
-
-char*
-donprint(char *p, char *ep, char *fmt, void *argp)
-{
- int sf1, c;
- Op o;
-
- o.p = p;
- o.ep = ep;
- o.argp = argp;
-
-loop:
- c = *fmt++;
- if(c != '%') {
- if(c == 0) {
- if(o.p < o.ep)
- *o.p = 0;
- return o.p;
- }
- PUT(&o, c);
- goto loop;
- }
- o.f1 = 0;
- o.f2 = -1;
- o.f3 = 0;
- c = *fmt++;
- sf1 = 0;
- if(c == '-') {
- sf1 = 1;
- c = *fmt++;
- }
- while(c >= '0' && c <= '9') {
- o.f1 = o.f1*10 + c-'0';
- c = *fmt++;
- }
- if(sf1)
- o.f1 = -o.f1;
- if(c != '.')
- goto l1;
- c = *fmt++;
- while(c >= '0' && c <= '9') {
- if(o.f2 < 0)
- o.f2 = 0;
- o.f2 = o.f2*10 + c-'0';
- c = *fmt++;
- }
-l1:
- if(c == 0)
- fmt--;
- c = (*fmtconv[fmtindex[c&0177]])(&o);
- if(c < 0) {
- o.f3 |= -c;
- c = *fmt++;
- goto l1;
- }
- o.argp = (char*)o.argp + c;
- goto loop;
-}
-
-void
-strconv(char *o, Op *op, int f1, int f2)
-{
- int n, c;
- char *p;
-
- n = strlen(o);
- if(f1 >= 0)
- while(n < f1) {
- PUT(op, ' ');
- n++;
- }
- for(p=o; c = *p++;)
- if(f2 != 0) {
- PUT(op, c);
- f2--;
- }
- if(f1 < 0) {
- f1 = -f1;
- while(n < f1) {
- PUT(op, ' ');
- n++;
- }
- }
-}
-
-int
-numbconv(Op *op, int base)
-{
- char b[IDIGIT];
- int i, f, n, r;
- long v;
- short h;
-
- f = 0;
- switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
- case FLONG:
- v = *(long*)op->argp;
- r = LONG;
- break;
-
- case FUNSIGN|FLONG:
- v = *(ulong*)op->argp;
- r = LONG;
- break;
-
- case FSHORT:
- h = *(int*)op->argp;
- v = h;
- r = SHORT;
- break;
-
- case FUNSIGN|FSHORT:
- h = *(int*)op->argp;
- v = (ushort)h;
- r = SHORT;
- break;
-
- default:
- v = *(int*)op->argp;
- r = INT;
- break;
-
- case FUNSIGN:
- v = *(unsigned*)op->argp;
- r = INT;
- break;
- }
- if(!(op->f3 & FUNSIGN) && v < 0) {
- v = -v;
- f = 1;
- }
- b[IDIGIT-1] = 0;
- for(i = IDIGIT-2;; i--) {
- n = (ulong)v % base;
- n += '0';
- if(n > '9'){
- n += 'a' - ('9'+1);
- if(ucase)
- n += 'A'-'a';
- }
- b[i] = n;
- if(i < 2)
- break;
- v = (ulong)v / base;
- if(op->f2 >= 0 && i >= IDIGIT-op->f2)
- continue;
- if(v <= 0)
- break;
- }
- if(f)
- b[--i] = '-';
- strconv(b+i, op, op->f1, -1);
- return r;
-}
-
-static int
-noconv(Op *op)
-{
-
- strconv("***", op, 0, -1);
- return 0;
-}
-
-static int
-cconv(Op *op)
-{
- char b[2];
-
- b[0] = *(int*)op->argp;
- b[1] = 0;
- strconv(b, op, op->f1, -1);
- return INT;
-}
-
-static int
-dconv(Op *op)
-{
- return numbconv(op, 10);
-}
-
-static int
-hconv(Op*)
-{
- return -FSHORT;
-}
-
-static int
-lconv(Op*)
-{
- return -FLONG;
-}
-
-static int
-oconv(Op *op)
-{
- return numbconv(op, 8);
-}
-
-static int
-sconv(Op *op)
-{
- strconv(*(char**)op->argp, op, op->f1, op->f2);
- return PTR;
-}
-
-static int
-uconv(Op*)
-{
- return -FUNSIGN;
-}
-
-static int
-xconv(Op *op)
-{
- return numbconv(op, 16);
-}
-
-static int
-Xconv(Op *op)
-{
- int r;
-
- ucase = 1;
- r = numbconv(op, 16);
- ucase = 0;
- return r;
-}
-
-static int
-percent(Op *op)
-{
-
- PUT(op, '%');
- return 0;
-}
--- a/os/boot/puma/dosboot.c
+++ /dev/null
@@ -1,614 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "dosfs.h"
-
-extern char *premature;
-
-/*
- * predeclared
- */
-static void bootdump(Dosboot*);
-static void setname(Dosfile*, char*);
-long dosreadseg(Dosfile*, long, long);
-
-/*
- * debugging
- */
-#define chatty 1
-#define chat if(chatty)print
-
-/*
- * block io buffers
- */
-enum
-{
- Nbio= 16,
-};
-typedef struct Clustbuf Clustbuf;
-struct Clustbuf
-{
- int age;
- long sector;
- uchar *iobuf;
- Dos *dos;
- int size;
-};
-Clustbuf bio[Nbio];
-
-/*
- * get an io block from an io buffer
- */
-Clustbuf*
-getclust(Dos *dos, long sector)
-{
- Clustbuf *p, *oldest;
- int size;
-
- chat("getclust @ %d\n", sector);
-
- /*
- * if we have it, just return it
- */
- for(p = bio; p < &bio[Nbio]; p++){
- if(sector == p->sector && dos == p->dos){
- p->age = m->ticks;
- chat("getclust %d in cache\n", sector);
- return p;
- }
- }
-
- /*
- * otherwise, reuse the oldest entry
- */
- oldest = bio;
- for(p = &bio[1]; p < &bio[Nbio]; p++){
- if(p->age <= oldest->age)
- oldest = p;
- }
- p = oldest;
-
- /*
- * make sure the buffer is big enough
- */
- size = dos->clustsize*dos->sectsize;
- if(p->iobuf==0 || p->size < size)
- p->iobuf = ialloc(size, 0);
- p->size = size;
-
- /*
- * read in the cluster
- */
- chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
- if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
- chat("can't seek block\n");
- return 0;
- }
- if((*dos->read)(dos->dev, p->iobuf, size) != size){
- chat("can't read block\n");
- return 0;
- }
-
- p->age = m->ticks;
- p->dos = dos;
- p->sector = sector;
- chat("getclust %d read\n", sector);
- return p;
-}
-
-/*
- * walk the fat one level ( n is a current cluster number ).
- * return the new cluster number or -1 if no more.
- */
-static long
-fatwalk(Dos *dos, int n)
-{
- ulong k, sect;
- Clustbuf *p;
- int o;
-
- chat("fatwalk %d\n", n);
-
- if(n < 2 || n >= dos->fatclusters)
- return -1;
-
- switch(dos->fatbits){
- case 12:
- k = (3*n)/2; break;
- case 16:
- k = 2*n; break;
- default:
- return -1;
- }
- if(k >= dos->fatsize*dos->sectsize)
- panic("getfat");
-
- sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
- o = k%(dos->sectsize*dos->clustsize);
- p = getclust(dos, sect);
- k = p->iobuf[o++];
- if(o >= dos->sectsize*dos->clustsize){
- p = getclust(dos, sect+dos->clustsize);
- o = 0;
- }
- k |= p->iobuf[o]<<8;
- if(dos->fatbits == 12){
- if(n&1)
- k >>= 4;
- else
- k &= 0xfff;
- if(k >= 0xff8)
- k |= 0xf000;
- }
- k = k < 0xfff8 ? k : -1;
- chat("fatwalk %d -> %d\n", n, k);
- return k;
-}
-
-/*
- * map a file's logical cluster address to a physical sector address
- */
-static long
-fileaddr(Dosfile *fp, long ltarget)
-{
- Dos *dos = fp->dos;
- long l;
- long p;
-
- chat("fileaddr %8.8s %d\n", fp->name, ltarget);
- /*
- * root directory is contiguous and easy
- */
- if(fp->pstart == 0){
- if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
- return -1;
- l = dos->rootaddr + ltarget*dos->clustsize;
- chat("fileaddr %d -> %d\n", ltarget, l);
- return l;
- }
-
- /*
- * anything else requires a walk through the fat
- */
- if(ltarget >= fp->lcurrent && fp->pcurrent){
- /* start at the currrent point */
- l = fp->lcurrent;
- p = fp->pcurrent;
- } else {
- /* go back to the beginning */
- l = 0;
- p = fp->pstart;
- }
- while(l != ltarget){
- /* walk the fat */
- p = fatwalk(dos, p);
- if(p < 0)
- return -1;
- l++;
- }
- fp->lcurrent = l;
- fp->pcurrent = p;
-
- /*
- * clusters start at 2 instead of 0 (why? - presotto)
- */
- l = dos->dataaddr + (p-2)*dos->clustsize;
- chat("fileaddr %d -> %d\n", ltarget, l);
- return l;
-}
-
-/*
- * read from a dos file
- */
-long
-dosread(Dosfile *fp, void *a, long n)
-{
- long addr;
- long rv;
- int i;
- int off;
- Clustbuf *p;
- uchar *from, *to;
-
- if((fp->attr & DDIR) == 0){
- if(fp->offset >= fp->length)
- return 0;
- if(fp->offset+n > fp->length)
- n = fp->length - fp->offset;
- }
-
- to = a;
- for(rv = 0; rv < n; rv+=i){
- /*
- * read the cluster
- */
- addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
- if(addr < 0)
- return -1;
- p = getclust(fp->dos, addr);
- if(p == 0)
- return -1;
-
- /*
- * copy the bytes we need
- */
- off = fp->offset % fp->dos->clustbytes;
- from = &p->iobuf[off];
- i = n - rv;
- if(i > fp->dos->clustbytes - off)
- i = fp->dos->clustbytes - off;
- memmove(to, from, i);
- to += i;
- fp->offset += i;
- }
-
- return rv;
-}
-
-/*
- * walk a directory returns
- * -1 if something went wrong
- * 0 if not found
- * 1 if found
- */
-int
-doswalk(Dosfile *file, char *name)
-{
- Dosdir d;
- long n;
-
- if((file->attr & DDIR) == 0){
- chat("walking non-directory!\n");
- return -1;
- }
-
- setname(file, name);
-
- file->offset = 0; /* start at the beginning */
- while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
- chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
- if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
- continue;
- if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
- continue;
- if(d.attr & DVLABEL){
- chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
- continue;
- }
- file->attr = d.attr;
- file->pstart = GSHORT(d.start);
- file->length = GLONG(d.length);
- file->pcurrent = 0;
- file->lcurrent = 0;
- file->offset = 0;
- return 1;
- }
- return n >= 0 ? 0 : -1;
-}
-
-
-/*
- * instructions that boot blocks can start with
- */
-#define JMPSHORT 0xeb
-#define JMPNEAR 0xe9
-
-/*
- * read dos file system properties
- */
-int
-dosinit(Dos *dos, int start, int ishard)
-{
- Dosboot *b;
- int i;
- Clustbuf *p;
- Dospart *dp;
- ulong mbroffset, offset;
-
- /* defaults till we know better */
- dos->start = start;
- dos->sectsize = 512;
- dos->clustsize = 1;
- mbroffset = 0;
-
-dmddo:
- /* get first sector */
- p = getclust(dos, mbroffset);
- if(p == 0){
- chat("can't read boot block\n");
- return -1;
- }
-
- /*
- * If it's a hard disc then look for an MBR and pick either an
- * active partition or the FAT with the lowest starting LBA.
- * Things are tricky because we could be pointing to, amongst others:
- * 1) a floppy BPB;
- * 2) a hard disc MBR;
- * 3) a hard disc extended partition table;
- * 4) a logical drive on a hard disc;
- * 5) a disc-manager boot block.
- * They all have the same magic at the end of the block.
- */
- if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
- chat("not DOS\n");
- return -1;
- }
- p->dos = 0;
- b = (Dosboot *)p->iobuf;
- if(ishard && b->mediadesc != 0xF8){
- dp = (Dospart*)&p->iobuf[0x1BE];
- offset = 0xFFFFFFFF;
- for(i = 0; i < 4; i++, dp++){
- if(dp->type == DMDDO){
- mbroffset = 63;
- goto dmddo;
- }
- if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
- continue;
- if(dp->flag & 0x80){
- offset = GLONG(dp->start);
- break;
- }
- if(GLONG(dp->start) < offset)
- offset = GLONG(dp->start);
- }
- if(i != 4 || offset != 0xFFFFFFFF){
- dos->start = mbroffset+offset;
- p = getclust(dos, 0);
- if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
- return -1;
- }
- p->dos = 0;
- }
-
- b = (Dosboot *)p->iobuf;
- if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
- chat("no dos file system\n");
- return -1;
- }
-
- if(chatty)
- bootdump(b);
-
- /*
- * determine the systems' wondersous properties
- */
- dos->sectsize = GSHORT(b->sectsize);
- dos->clustsize = b->clustsize;
- dos->clustbytes = dos->sectsize*dos->clustsize;
- dos->nresrv = GSHORT(b->nresrv);
- dos->nfats = b->nfats;
- dos->rootsize = GSHORT(b->rootsize);
- dos->volsize = GSHORT(b->volsize);
- if(dos->volsize == 0)
- dos->volsize = GLONG(b->bigvolsize);
- dos->mediadesc = b->mediadesc;
- dos->fatsize = GSHORT(b->fatsize);
- dos->fataddr = dos->nresrv;
- dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
- i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
- i = i/dos->sectsize;
- dos->dataaddr = dos->rootaddr + i;
- dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
- if(dos->fatclusters < 4087)
- dos->fatbits = 12;
- else
- dos->fatbits = 16;
- dos->freeptr = 2;
-
- /*
- * set up the root
- */
- dos->root.dos = dos;
- dos->root.pstart = 0;
- dos->root.pcurrent = dos->root.lcurrent = 0;
- dos->root.offset = 0;
- dos->root.attr = DDIR;
- dos->root.length = dos->rootsize*sizeof(Dosdir);
-
- return 0;
-}
-
-static void
-bootdump(Dosboot *b)
-{
- if(chatty == 0)
- return;
- print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
- b->magic[0], b->magic[1], b->magic[2]);
- print("version: \"%8.8s\"\n", b->version);
- print("sectsize: %d\n", GSHORT(b->sectsize));
- print("allocsize: %d\n", b->clustsize);
- print("nresrv: %d\n", GSHORT(b->nresrv));
- print("nfats: %d\n", b->nfats);
- print("rootsize: %d\n", GSHORT(b->rootsize));
- print("volsize: %d\n", GSHORT(b->volsize));
- print("mediadesc: 0x%2.2x\n", b->mediadesc);
- print("fatsize: %d\n", GSHORT(b->fatsize));
- print("trksize: %d\n", GSHORT(b->trksize));
- print("nheads: %d\n", GSHORT(b->nheads));
- print("nhidden: %d\n", GLONG(b->nhidden));
- print("bigvolsize: %d\n", GLONG(b->bigvolsize));
- print("driveno: %d\n", b->driveno);
- print("reserved0: 0x%2.2x\n", b->reserved0);
- print("bootsig: 0x%2.2x\n", b->bootsig);
- print("volid: 0x%8.8x\n", GLONG(b->volid));
- print("label: \"%11.11s\"\n", b->label);
-}
-
-/*
- * grab next element from a path, return the pointer to unprocessed portion of
- * path.
- */
-static char *
-nextelem(char *path, char *elem)
-{
- int i;
-
- while(*path == '/')
- path++;
- if(*path==0 || *path==' ')
- return 0;
- for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
- if(i==28){
- print("name component too long\n");
- return 0;
- }
- *elem++ = *path++;
- }
- *elem = '\0';
- return path;
-}
-
-int
-dosstat(Dos *dos, char *path, Dosfile *f)
-{
- char element[NAMELEN];
-
- *f = dos->root;
- while(path = nextelem(path, element)){
- switch(doswalk(f, element)){
- case -1:
- return -1;
- case 0:
- return 0;
- }
- }
- return 1;
-}
-
-/*
- * boot
- */
-int
-dosboot(Dos *dos, char *path)
-{
- Dosfile file;
- long n;
- long addr;
- Exec *ep;
- void (*b)(void);
-
- switch(dosstat(dos, path, &file)){
-
- case -1:
- print("error walking to %s\n", path);
- return -1;
- case 0:
- print("%s not found\n", path);
- return -1;
- case 1:
- print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
- file.ext, file.attr, file.pstart, file.length);
- break;
- }
-
- /*
- * read header
- */
- ep = (Exec*)ialloc(sizeof(Exec), 0);
- n = sizeof(Exec);
- if(dosreadseg(&file, n, (ulong) ep) != n){
- print(premature);
- return -1;
- }
- if(GLLONG(ep->magic) != E_MAGIC){
- print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
- return -1;
- }
-
- /*
- * read text
- */
- addr = PADDR(GLLONG(ep->entry));
- n = GLLONG(ep->text);
- print("+%d", n);
- if(dosreadseg(&file, n, addr) != n){
- print(premature);
- return -1;
- }
-
- /*
- * read data (starts at first page after kernel)
- */
- addr = PGROUND(addr+n);
- n = GLLONG(ep->data);
- print("+%d", n);
- if(dosreadseg(&file, n, addr) != n){
- print(premature);
- return -1;
- }
-
- /*
- * bss and entry point
- */
- print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
-
- /*
- * Go to new code. It's up to the program to get its PC relocated to
- * the right place.
- */
- b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
- (*b)();
- return 0;
-}
-
-/*
- * read in a segment
- */
-long
-dosreadseg(Dosfile *fp, long len, long addr)
-{
- char *a;
- long n, sofar;
-
- a = (char *)addr;
- for(sofar = 0; sofar < len; sofar += n){
- n = 8*1024;
- if(len - sofar < n)
- n = len - sofar;
- n = dosread(fp, a + sofar, n);
- if(n <= 0)
- break;
- print(".");
- }
- return sofar;
-}
-
-/*
- * set up a dos file name
- */
-static void
-setname(Dosfile *fp, char *from)
-{
- char *to;
-
- to = fp->name;
- for(; *from && to-fp->name < 8; from++, to++){
- if(*from == '.'){
- from++;
- break;
- }
- if(*from >= 'a' && *from <= 'z')
- *to = *from + 'A' - 'a';
- else
- *to = *from;
- }
- while(to - fp->name < 8)
- *to++ = ' ';
-
- to = fp->ext;
- for(; *from && to-fp->ext < 3; from++, to++){
- if(*from >= 'a' && *from <= 'z')
- *to = *from + 'A' - 'a';
- else
- *to = *from;
- }
- while(to-fp->ext < 3)
- *to++ = ' ';
-
- chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
-}
--- a/os/boot/puma/dosfs.h
+++ /dev/null
@@ -1,110 +1,0 @@
-typedef struct Dosboot Dosboot;
-typedef struct Dos Dos;
-typedef struct Dosdir Dosdir;
-typedef struct Dosfile Dosfile;
-typedef struct Dospart Dospart;
-
-struct Dospart
-{
- uchar flag; /* active flag */
- uchar shead; /* starting head */
- uchar scs[2]; /* starting cylinder/sector */
- uchar type; /* partition type */
- uchar ehead; /* ending head */
- uchar ecs[2]; /* ending cylinder/sector */
- uchar start[4]; /* starting sector */
- uchar len[4]; /* length in sectors */
-};
-
-#define FAT12 0x01
-#define FAT16 0x04
-#define FATHUGE 0x06
-#define DMDDO 0x54
-
-struct Dosboot{
- uchar magic[3];
- uchar version[8];
- uchar sectsize[2];
- uchar clustsize;
- uchar nresrv[2];
- uchar nfats;
- uchar rootsize[2];
- uchar volsize[2];
- uchar mediadesc;
- uchar fatsize[2];
- uchar trksize[2];
- uchar nheads[2];
- uchar nhidden[4];
- uchar bigvolsize[4];
- uchar driveno;
- uchar reserved0;
- uchar bootsig;
- uchar volid[4];
- uchar label[11];
- uchar reserved1[8];
-};
-
-struct Dosfile{
- Dos *dos; /* owning dos file system */
- char name[8];
- char ext[3];
- uchar attr;
- long length;
- long pstart; /* physical start cluster address */
- long pcurrent; /* physical current cluster address */
- long lcurrent; /* logical current cluster address */
- long offset;
-};
-
-struct Dos{
- int dev; /* device id */
- long (*read)(int, void*, long); /* read routine */
- long (*seek)(int, long); /* seek routine */
-
- int start; /* start of file system */
- int sectsize; /* in bytes */
- int clustsize; /* in sectors */
- int clustbytes; /* in bytes */
- int nresrv; /* sectors */
- int nfats; /* usually 2 */
- int rootsize; /* number of entries */
- int volsize; /* in sectors */
- int mediadesc;
- int fatsize; /* in sectors */
- int fatclusters;
- int fatbits; /* 12 or 16 */
- long fataddr; /* sector number */
- long rootaddr;
- long dataaddr;
- long freeptr;
-
- Dosfile root;
-};
-
-struct Dosdir{
- uchar name[8];
- uchar ext[3];
- uchar attr;
- uchar reserved[10];
- uchar time[2];
- uchar date[2];
- uchar start[2];
- uchar length[4];
-};
-
-#define DRONLY 0x01
-#define DHIDDEN 0x02
-#define DSYSTEM 0x04
-#define DVLABEL 0x08
-#define DDIR 0x10
-#define DARCH 0x20
-
-extern int chatty;
-
-extern int dosboot(Dos*, char*);
-extern int dosinit(Dos*, int, int);
-extern long dosread(Dosfile*, void*, long);
-extern int dosstat(Dos*, char*, Dosfile*);
-extern int doswalk(Dosfile*, char*);
-
-extern int plan9ini(Dos*, char*);
--- a/os/boot/puma/ebsit.trap.c
+++ /dev/null
@@ -1,206 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "ebsit.h"
-#include "dat.h"
-#include "fns.h"
-
-#include "ureg.h"
-
-int inpanic;
-
-#define CSR ((ushort *) 0x2000000)
-
-
-typedef struct Irqctlr {
- uint addr;
- uint enabled;
- struct {
- void (*r)(Ureg*, void*);
- void *a;
- } h[16];
-} Irqctlr;
-
-static Irqctlr irqctlr;
-
-void
-csrset( int bit )
-{
-static ushort *csr_val = 0x8c;
-
- *csr_val ^= (1 << bit);
- putcsr(*csr_val);
-}
-
-void
-intrinit( void )
-{
-int offset;
-ulong op;
-
-
- irqctlr.addr = 1;
- irqctlr.enabled = 0;
-
- /* Reset Exception */
- offset = ((((ulong) _vsvccall) - 0x0)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0x0) = op;
-
- /* Undefined Instruction Exception */
- offset = ((((ulong) _vundcall) - 0x4)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0x4) = op;
-
- /* SWI Exception */
- offset = ((((ulong) _vsvccall) - 0x8)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0x8) = op;
-
- /* Prefetch Abort Exception */
- offset = ((((ulong) _vpabcall) - 0xc)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0xc) = op;
-
- /* Data Abort Exception */
- offset = ((((ulong) _vdabcall) - 0x10)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0x10) = op;
-
- /* IRQ Exception */
- offset = ((((ulong) _virqcall) - 0x18)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0x18) = op;
-
-
-}
-
-void
-intrenable(uint addr, int bit, void (*r)(Ureg*, void*), void* a)
-{
- int i;
- USED(addr);
- for(i = 0; i < 16; i++)
- {
- if((bit & (1<<i)) == 0)
- continue;
- irqctlr.h[i].r = r;
- irqctlr.h[i].a = a;
- irqctlr.enabled |= (1<<i);
- if (i < 7)
- csrset(i);
- }
- return;
-}
-
-int lucifer; /* Global to store the last CSR (eric) */
-
-static void
-interrupt(Ureg* ureg)
-{
- int i, mask;
-
- mask = *CSR;
- lucifer = mask; /* eric */
- if(irqctlr.enabled == 0){
-
- return;
- }
- for(i = 0; i < 16; i++)
- {
-
- if((irqctlr.enabled & (1<<i)) == 0)
- continue;
- if(( mask & (1 << i)) == 0)
- continue;
- if (!irqctlr.h[i].r)
- continue;
- (irqctlr.h[i].r)(ureg, irqctlr.h[i].a);
- mask &= ~(1 << i);
- }
-
- if ((mask) && (mask < 0x90)) /* ignore non-maskable interrupts */
- {
- print("unknown or unhandled interrupt\n");
- panic("unknown or unhandled interrupt: mask=%ux",mask);
- }
-
-}
-
-static void
-dumpregs(Ureg* ureg)
-{
- print("PSR %8.8uX type %2.2uX PC %8.8uX LINK %8.8uX\n",
- ureg->psr, ureg->type, ureg->pc, ureg->link);
- print("R14 %8.8uX R13 %8.8uX R12 %8.8uX R11 %8.8uX R10 %8.8uX\n",
- ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
- print("R9 %8.8uX R8 %8.8uX R7 %8.8uX R6 %8.8uX R5 %8.8uX\n",
- ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
- print("R4 %8.8uX R3 %8.8uX R2 %8.8uX R1 %8.8uX R0 %8.8uX\n",
- ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
- print("Last Interrupt's CSR: %8.8uX\n",lucifer);
- print("CPSR %8.8uX SPSR %8.8uX\n", cpsrr(), spsrr());
-}
-
-void
-dumpstack(void)
-{
-}
-
-void
-exception(Ureg* ureg)
-{
- static Ureg old_ureg;
- uint far =0;
- uint fsr =0;
-
- static lasttype = 0;
-
- LOWBAT;
-
- USED(far, fsr);
-
- lasttype = ureg->type;
-
- /*
- * All interrupts/exceptions should be resumed at ureg->pc-4,
- * except for Data Abort which resumes at ureg->pc-8.
- */
-
- if(ureg->type == (PsrMabt+1))
- ureg->pc -= 8;
- else
- ureg->pc -= 4;
-
- switch(ureg->type){
-
- case PsrMfiq: /* (Fast) */
- print("Fast\n");
- print("We should never be here\n");
- while(1);
-
- case PsrMirq: /* Interrupt Request */
- interrupt(ureg);
- break;
-
- case PsrMund: /* Undefined instruction */
- print("Undefined instruction\n");
- case PsrMsvc: /* Jump through 0, SWI or reserved trap */
- print("SWI/SVC trap\n");
- case PsrMabt: /* Prefetch abort */
- print("Prefetch Abort\n");
- case PsrMabt+1: /* Data abort */
- print("Data Abort\n");
-
-
- default:
- dumpregs(ureg);
- /* panic("exception %uX\n", ureg->type); */
- break;
- }
-
- LOWBAT; /* Low bat off after interrupt */
-
- splhi();
-
-}
--- a/os/boot/puma/ether.c
+++ /dev/null
@@ -1,156 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ether.h"
-
-static Ctlr ether[MaxEther];
-
-static struct {
- char *type;
- int (*reset)(Ctlr*);
-} cards[] = {
- { "CS8900", cs8900reset, },
- { 0, }
-};
-
-int
-etherinit(void)
-{
- Ctlr *ctlr;
- int ctlrno, i, mask, n;
-
- mask = 0;
- for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
- ctlr = ðer[ctlrno];
- memset(ctlr, 0, sizeof(Ctlr));
- if(isaconfig("ether", ctlrno, &ctlr->card) == 0)
- continue;
- for(n = 0; cards[n].type; n++){
- if(strcmp(cards[n].type, ctlr->card.type))
- continue;
- ctlr->ctlrno = ctlrno;
- if((*cards[n].reset)(ctlr))
- break;
-
- ctlr->iq = qopen(16*1024, 1, 0, 0);
- ctlr->oq = qopen(16*1024, 1, 0, 0);
-
- ctlr->present = 1;
- mask |= 1<<ctlrno;
-
- print("ether%d: %s: port 0x%luX irq %d",
- ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
- if(ctlr->card.mem)
- print(" addr 0x%luX", ctlr->card.mem & ~KZERO);
- if(ctlr->card.size)
- print(" size 0x%luX", ctlr->card.size);
- print(":");
- for(i = 0; i < sizeof(ctlr->card.ea); i++)
- print(" %2.2uX", ctlr->card.ea[i]);
- print("\n"); uartwait();
- setvec(ctlr->card.irq, ctlr->card.intr, ctlr);
- break;
- }
- }
-
- return mask;
-}
-
-static Ctlr*
-attach(int ctlrno)
-{
- Ctlr *ctlr;
-
- if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
- return 0;
-
- ctlr = ðer[ctlrno];
- if(ctlr->present == 1){
- ctlr->present = 2;
- (*ctlr->card.attach)(ctlr);
- }
-
- return ctlr;
-}
-
-uchar*
-etheraddr(int ctlrno)
-{
- Ctlr *ctlr;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- return ctlr->card.ea;
-}
-
-int
-etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
-{
- int n;
- Ctlr *ctlr;
- Block *b;
- ulong start;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- start = m->ticks;
- while((b = qget(ctlr->iq)) == 0){
- if(TK2MS(m->ticks - start) >= timo){
- /*
- print("ether%d: rx timeout\n", ctlrno);
- */
- return 0;
- }
- //delay(1);
- }
-
- n = BLEN(b);
- memmove(pkt, b->rp, n);
- freeb(b);
-
- return n;
-}
-
-int
-etheriq(Ctlr *ctlr, Block *b, int freebp)
-{
- if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0){
- if(freebp)
- freeb(b);
- return 0;
- }
- qbwrite(ctlr->iq, b);
- return 1;
-}
-
-int
-ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
-{
- Ctlr *ctlr;
- Block *b;
- int s;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- if(qlen(ctlr->oq) > 16*1024){
- print("ether%d: tx queue full\n", ctlrno);
- return 0;
- }
- b = iallocb(sizeof(Etherpkt));
- memmove(b->wp, pkt, len);
- memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
- b->wp += len;
- qbwrite(ctlr->oq, b);
- s = splhi();
- (*ctlr->card.transmit)(ctlr);
- splx(s);
-
- return 1;
-}
--- a/os/boot/puma/ether.h
+++ /dev/null
@@ -1,82 +1,0 @@
-/*
- * All the goo for PC ethernet cards.
- */
-typedef struct Card Card;
-typedef struct RingBuf RingBuf;
-typedef struct Type Type;
-typedef struct Ctlr Ctlr;
-
-/*
- * Hardware interface.
- */
-struct Card {
- ISAConf;
-
- int (*reset)(Ctlr*);
- void (*attach)(Ctlr*);
-
- void *(*read)(Ctlr*, void*, ulong, ulong);
- void *(*write)(Ctlr*, ulong, void*, ulong);
-
- void (*receive)(Ctlr*);
- void (*transmit)(Ctlr*);
- void (*intr)(Ureg*, Ctlr*);
- void (*overflow)(Ctlr*);
-
- uchar bit16; /* true if a 16 bit interface */
- uchar ram; /* true if card has shared memory */
-
- ulong dp8390; /* I/O address of 8390 (if any) */
- ulong data; /* I/O data port if no shared memory */
- uchar nxtpkt; /* software bndry */
- uchar tstart; /* 8390 ring addresses */
- uchar pstart;
- uchar pstop;
-
- uchar dummyrr; /* do dummy remote read */
-};
-
-/*
- * Software ring buffer.
- */
-struct RingBuf {
- uchar owner;
- uchar busy; /* unused */
- ushort len;
- uchar pkt[sizeof(Etherpkt)];
-};
-
-enum {
- Host = 0, /* buffer owned by host */
- Interface = 1, /* buffer owned by card */
-
- Nrb = 16, /* default number of receive buffers */
- Ntb = 2, /* default number of transmit buffers */
-};
-
-/*
- * Software controller.
- */
-struct Ctlr {
- Card card; /* hardware info */
- int ctlrno;
- int present;
-
- Queue* iq;
- Queue* oq;
-
- int inpackets;
- int outpackets;
- int crcs; /* input crc errors */
- int oerrs; /* output errors */
- int frames; /* framing errors */
- int overflows; /* packet overflows */
- int buffs; /* buffering errors */
-};
-
-#define NEXT(x, l) (((x)+1)%(l))
-#define HOWMANY(x, y) (((x)+((y)-1))/(y))
-#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
-
-extern int cs8900reset(Ctlr*);
-extern int etheriq(Ctlr*, Block*, int);
--- a/os/boot/puma/ether8900.c
+++ /dev/null
@@ -1,555 +1,0 @@
-/*
- * Crystal CS8900 ethernet controller
- * Specifically for the Teralogic Puma architecture
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ether.h"
-#include "puma.h"
-
-/*
- * On the Puma board the CS8900 can be addressed from either
- * ISA I/O space or ISA memory space at the following locations.
- * The cs8900 address pins are shifted by 1 relative to the CPU.
- */
-enum {
- IsaIOBase = 0xf0000000,
- IsaMemBase = 0xe0000000,
-
- IOBase = 0x300,
- MemBase = 0xc0000,
-};
-
-/* I/O accesses */
-#define out16(port, val) (*((ushort *)IsaIOBase + IOBase + (port)) = (val))
-#define in16(port) *((ushort *)IsaIOBase + IOBase + (port))
-#define in8(port) *((uchar *)IsaIOBase + ((IOBase+(port))<<1))
-#define regIOw(reg, val) do {out16(PpPtr, (reg)|0x3000); out16(PpData, val);} while(0)
-#define regIOr(reg) (out16(PpPtr, (reg)|0x3000), in16(PpData))
-#define regIOr1(reg) (out16(PpPtr, (reg)|0x3000), in16(PpData1))
-
-/* Memory accesses */
-#define regw(reg, val) *((ushort *)IsaMemBase + MemBase + (reg)) = (val)
-#define regr(reg) *((ushort *)IsaMemBase + MemBase + (reg))
-
-/* Puma frame copying */
-#define copyout(src, len) { \
- int _len = (len); \
- ushort *_src = (ushort *)(src); \
- ushort *_dst = (ushort *)IsaMemBase + MemBase + TxFrame; \
- while(_len > 0) { \
- *_dst++ = *_src++; \
- _dst++; \
- _len -= 2; \
- } \
- }
-#define copyoutIO(src, len) { \
- int _len = (len); \
- ushort *_src = (ushort *)(src); \
- while(_len > 0) { \
- out16(RxTxData, *_src); \
- _src++; \
- _len -= 2; \
- } \
- }
-#define copyin(dst, len) { \
- int _len = (len), _len2 = (len)&~1; \
- ushort *_src = (ushort *)IsaMemBase + MemBase + RxFrame; \
- ushort *_dst = (ushort *)(dst); \
- while(_len2 > 0) { \
- *_dst++ = *_src++; \
- _src++; \
- _len2 -= 2; \
- } \
- if(_len&1) \
- *(uchar*)_dst = (*_src)&0xff; \
- }
-#define copyinIO(dst, len) { \
- int _i, _len = (len), _len2 = (len)&~1; \
- ushort *_dst = (ushort *)(dst); \
- _i = in16(RxTxData); USED(_i); /* RxStatus */ \
- _i = in16(RxTxData); USED(_i); /* RxLen */ \
- while(_len2 > 0) { \
- *_dst++ = in16(RxTxData); \
- _len2 -= 2; \
- } \
- if(_len&1) \
- *(uchar*)_dst = (in16(RxTxData))&0xff; \
- }
-
-
-
-enum { /* I/O Mode Register Offsets */
- RxTxData = 0x00, /* receive/transmit data - port 0 */
- TxCmdIO = 0x04, /* transmit command */
- TxLenIO = 0x06, /* transmit length */
- IsqIO = 0x08, /* Interrupt status queue */
- PpPtr = 0x0a, /* packet page pointer */
- PpData = 0x0c, /* packet page data */
- PpData1 = 0x0e, /* packet page data - port 1*/
-};
-
-enum { /* Memory Mode Register Offsets */
- /* Bus Interface Registers */
- Ern = 0x0000, /* EISA registration numberion */
- Pic = 0x0002, /* Product identification code */
- Iob = 0x0020, /* I/O base address */
- Intr = 0x0022, /* interrupt number */
- Mba = 0x002c, /* memory base address */
-
- Ecr = 0x0040, /* EEPROM command register */
- Edw = 0x0042, /* EEPROM data word */
- Rbc = 0x0050, /* receive frame byte counter */
-
- /* Status and Control Registers */
- RxCfg = 0x0102,
- RxCtl = 0x0104,
- TxCfg = 0x0106,
- BufCfg = 0x010a,
- LineCtl = 0x0112,
- SelfCtl = 0x0114,
- BusCtl = 0x0116,
- TestCtl = 0x0118,
- Isq = 0x0120,
- RxEvent = 0x0124,
- TxEvent = 0x0128,
- BufEvent = 0x012c,
- RxMISS = 0x0130,
- TxCol = 0x0132,
- LineSt = 0x0134,
- SelfSt = 0x0136,
- BusSt = 0x0138,
- Tdr = 0x013c,
-
- /* Initiate Transmit Registers */
- TxCmd = 0x0144, /* transmit command */
- TxLen = 0x0146, /* transmit length */
-
- /* Address Filter Registers */
- IndAddr = 0x0158, /* individual address registers */
-
- /* Frame Location */
- RxStatus = 0x0400, /* receive status */
- RxLen = 0x0402, /* receive length */
- RxFrame = 0x0404, /* receive frame location */
- TxFrame = 0x0a00, /* transmit frame location */
-};
-
-enum { /* Ecr */
- Addr = 0x00ff, /* EEPROM word address (field) */
- Opcode = 0x0300, /* command opcode (field) */
-};
-
-enum { /* Isq */
- Regnum = 0x003f, /* register number held by Isq (field) */
- IsqRxEvent = 0x04,
- IsqTxEvent = 0x08,
- IsqBufEvent = 0x0c,
- IsqRxMiss = 0x10,
- IsqTxCol = 0x12,
- RegContent = 0xffc0, /* register data contents (field) */
-};
-
-enum { /* RxCfg */
- Skip_1 = 0x0040,
- StreamE = 0x0080,
- RxOKiE = 0x0100,
- RxDMAonly = 0x0200,
- AutoRxDMAE = 0x0400,
- BufferCRC = 0x0800,
- CRCerroriE = 0x1000,
- RuntiE = 0x2000,
- ExtradataiE = 0x4000,
-};
-
-enum { /* RxEvent */
- IAHash = 0x0040,
- Dribblebits = 0x0080,
- RxOK = 0x0100,
- Hashed = 0x0200,
- IndividualAdr = 0x0400,
- Broadcast = 0x0800,
- CRCerror = 0x1000,
- Runt = 0x2000,
- Extradata = 0x4000,
-};
-
-enum { /* RxCtl */
- IAHashA = 0x0040,
- PromiscuousA = 0x0080,
- RxOKA = 0x0100,
- MulticastA = 0x0200,
- IndividualA = 0x0400,
- BroadcastA = 0x0800,
- CRCerrorA = 0x1000,
- RuntA = 0x2000,
- ExtradataA = 0x4000,
-};
-
-enum { /* TxCfg */
- LossofCRSiE = 0x0040,
- SQEerroriE = 0x0080,
- TxOKiE = 0x0100,
- OutofWindowiE = 0x0200,
- JabberiE = 0x0400,
- AnycolliE = 0x0800,
- Coll16iE = 0x8000,
-};
-
-enum { /* TxEvent */
- LossofCRS = 0x0040,
- SQEerror = 0x0080,
- TxOK = 0x0100,
- OutofWindow = 0x0200,
- Jabber = 0x0400,
- NTxCols = 0x7800, /* number of Tx collisions (field) */
- coll16 = 0x8000,
-};
-
-enum { /* BufCfg */
- SWintX = 0x0040,
- RxDMAiE = 0x0080,
- Rdy4TxiE = 0x0100,
- TxUnderruniE = 0x0200,
- RxMissiE = 0x0400,
- Rx128iE = 0x0800,
- TxColOvfiE = 0x1000,
- MissOvfloiE = 0x2000,
- RxDestiE = 0x8000,
-};
-
-enum { /* BufEvent */
- SWint = 0x0040,
- RxDMAFrame = 0x0080,
- Rdy4Tx = 0x0100,
- TxUnderrun = 0x0200,
- RxMiss = 0x0400,
- Rx128 = 0x0800,
- RxDest = 0x8000,
-};
-
-enum { /* RxMiss */
- MissCount = 0xffc0,
-};
-
-enum { /* TxCol */
- ColCount = 0xffc0,
-};
-
-enum { /* LineCtl */
- SerRxOn = 0x0040,
- SerTxOn = 0x0080,
- Iface = 0x0300, /* (field) 01 - AUI, 00 - 10BASE-T, 10 - Auto select */
- ModBackoffE = 0x0800,
- PolarityDis = 0x1000,
- DefDis = 0x2000,
- LoRxSquelch = 0x4000,
-};
-
-enum { /* LineSt */
- LinkOK = 0x0080,
- AUI = 0x0100,
- TenBT = 0x0200,
- PolarityOK = 0x1000,
- CRS = 0x4000,
-};
-
-enum { /* SelfCtl */
- RESET = 0x0040,
- SWSuspend = 0x0100,
- HWSleepE = 0x0200,
- HWStandbyE = 0x0400,
-};
-
-enum { /* SelfSt */
- INITD = 0x0080,
- SIBUSY = 0x0100,
- EepromPresent = 0x0200,
- EepromOK = 0x0400,
- ElPresent = 0x0800,
- EeSize = 0x1000,
-};
-
-enum { /* BusCtl */
- ResetRxDMA = 0x0040,
- UseSA = 0x0200,
- MemoryE = 0x0400,
- DMABurst = 0x0800,
- EnableIRQ = 0x8000,
-};
-
-enum { /* BusST */
- TxBidErr = 0x0080,
- Rdy4TxNOW = 0x0100,
-};
-
-enum { /* TestCtl */
- FDX = 0x4000, /* full duplex */
-};
-
-enum { /* TxCmd */
- TxStart = 0x00c0, /* bytes before transmit starts (field) */
- TxSt5 = 0x0000, /* start after 5 bytes */
- TxSt381 = 0x0040, /* start after 381 bytes */
- TxSt1021 = 0x0080, /* start after 1021 bytes */
- TxStAll = 0x00c0, /* start after the entire frame is in the cs8900 */
- Force = 0x0100,
- Onecoll = 0x0200,
- InhibitCRC = 0x1000,
- TxPadDis = 0x2000,
-};
-
-static Queue *pendingTx[MaxEther];
-
-static void
-attach(Ctlr *ctlr)
-{
- int reg;
-
- USED(ctlr);
- /* enable transmit and receive */
- reg = regr(BusCtl);
- regw(BusCtl, reg|EnableIRQ);
- reg = regr(LineCtl);
- regw(LineCtl, reg|SerRxOn|SerTxOn);
-}
-
-static char pbuf[200];
-int
-sprintx(void *f, char *to, int count)
-{
- int i, printable;
- char *start = to;
- uchar *from = f;
-
- if(count < 0) {
- print("BAD DATA COUNT %d\n", count);
- return 0;
- }
- printable = 1;
- if(count > 40)
- count = 40;
- for(i=0; i<count && printable; i++)
- if((from[i]<32 && from[i] !='\n' && from[i] !='\r' && from[i] !='\b' && from[i] !='\t') || from[i]>127)
- printable = 0;
- *to++ = '\'';
- if(printable){
- memmove(to, from, count);
- to += count;
- }else{
- for(i=0; i<count; i++){
- if(i>0 && i%4==0)
- *to++ = ' ';
- sprint(to, "%2.2ux", from[i]);
- to += 2;
- }
- }
- *to++ = '\'';
- *to = 0;
- return to - start;
-}
-
-static void
-transmit(Ctlr *ctlr)
-{
- int len, status;
- Block *b;
-
- for(;;){
- /* is TxCmd pending ? - check */
- if(qlen(pendingTx[ctlr->ctlrno]) > 0)
- break;
- b = qget(ctlr->oq);
- if(b == 0)
- break;
- len = BLEN(b);
- regw(TxCmd, TxSt381);
- regw(TxLen, len);
- status = regr(BusSt);
- if((status & Rdy4TxNOW) == 0) {
- qbwrite(pendingTx[ctlr->ctlrno], b);
- break;
- }
- /*
- * Copy the packet to the transmit buffer.
- */
- copyout(b->rp, len);
- freeb(b);
- }
-}
-
-static void
-interrupt(Ureg*, Ctlr *ctlr)
-{
- int len, events, status;
- Block *b;
- Queue *q;
-
- while((events = regr(Isq)) != 0) {
- status = events&RegContent;
-
- switch(events&Regnum) {
-
- case IsqBufEvent:
- if(status&Rdy4Tx) {
- if(qlen(pendingTx[ctlr->ctlrno]) > 0)
- q = pendingTx[ctlr->ctlrno];
- else
- q = ctlr->oq;
- b = qget(q);
- if(b == 0)
- break;
- len = BLEN(b);
- copyout(b->rp, len);
- freeb(b);
- } else
- if(status&TxUnderrun) {
- print("TxUnderrun\n");
- } else
- if(status&RxMiss) {
- print("RxMiss\n");
- } else {
- print("IsqBufEvent status = %ux\n", status);
- }
- break;
-
- case IsqRxEvent:
- if(status&RxOK) {
- len = regr(RxLen);
- if((b = iallocb(len)) != 0) {
- copyin(b->wp, len);
- b->wp += len;
- etheriq(ctlr, b, 1);
- }
- } else {
- print("IsqRxEvent status = %ux\n", status);
- }
- break;
-
- case IsqTxEvent:
- if(status&TxOK) {
- if(qlen(pendingTx[ctlr->ctlrno]) > 0)
- q = pendingTx[ctlr->ctlrno];
- else
- q = ctlr->oq;
- b = qget(q);
- if(b == 0)
- break;
- len = BLEN(b);
- regw(TxCmd, TxSt381);
- regw(TxLen, len);
-if((regr(BusSt) & Rdy4TxNOW) == 0) {
- print("IsqTxEvent and Rdy4TxNow == 0\n");
-}
- copyout(b->rp, len);
- freeb(b);
- } else {
- print("IsqTxEvent status = %ux\n", status);
- }
- break;
- case IsqRxMiss:
- break;
- case IsqTxCol:
- break;
- }
- }
-}
-
-int
-cs8900reset(Ctlr* ctlr)
-{
- int i, reg;
- uchar ea[Eaddrlen];
-
- ctlr->card.irq = V_ETHERNET;
- pendingTx[ctlr->ctlrno] = qopen(16*1024, 1, 0, 0);
-
- /*
- * If the Ethernet address is not set in the plan9.ini file
- * a) try reading from the Puma board ROM. The ether address is found in
- * bytes 4-9 of the ROM. The Teralogic Organizational Unique Id (OUI)
- * is in bytes 4-6 and should be 00 10 8a.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0) {
- uchar *rom = (uchar *)EPROM_BASE;
- if(rom[4] != 0x00 || rom[5] != 0x10 || rom[6] != 0x8a)
- panic("no ether address");
- memmove(ea, &rom[4], Eaddrlen);
- }
- memmove(ctlr->card.ea, ea, Eaddrlen);
-
- /*
- * Identify the chip by reading the Pic register.
- * The EISA registration number is in the low word
- * and the product identification code in the high code.
- * The ERN for Crystal Semiconductor is 0x630e.
- * Bits 0-7 and 13-15 of the Pic should be zero for a CS8900.
- */
- if(regIOr(Ern) != 0x630e || (regIOr(Pic) & 0xe0ff) != 0)
- panic("no cs8900 found");
-
- /*
- * Reset the chip and ensure 16-bit mode operation
- */
- regIOw(SelfCtl, RESET);
- delay(10);
- i=in8(PpPtr); USED(i);
- i=in8(PpPtr+1); USED(i);
- i=in8(PpPtr); USED(i);
- i=in8(PpPtr+1); USED(i);
-
- /*
- * Wait for initialisation and EEPROM reads to complete
- */
- i=0;
- for(;;) {
- short st = regIOr(SelfSt);
- if((st&SIBUSY) == 0 && st&INITD)
- break;
- if(i++ > 1000000)
- panic("cs8900: initialisation failed");
- }
-
- /*
- * Enable memory mode operation.
- */
- regIOw(Mba, MemBase & 0xffff);
- regIOw(Mba+2, MemBase >> 16);
- regIOw(BusCtl, MemoryE|UseSA);
-
- /*
- * Enable 10BASE-T half duplex, transmit in interrupt mode
- */
- reg = regr(LineCtl);
- regw(LineCtl, reg&~Iface);
- reg = regr(TestCtl);
- regw(TestCtl, reg&~FDX);
- regw(BufCfg, Rdy4TxiE|TxUnderruniE|RxMissiE);
- regw(TxCfg, TxOKiE|JabberiE|Coll16iE);
- regw(RxCfg, RxOKiE);
- regw(RxCtl, RxOKA|IndividualA|BroadcastA);
-
- for(i=0; i<Eaddrlen; i+=2)
- regw(IndAddr+i, ea[i] | (ea[i+1] << 8));
-
- /* Puma IRQ tied to INTRQ0 */
- regw(Intr, 0);
-
- ctlr->card.reset = cs8900reset;
- ctlr->card.port = 0x300;
- ctlr->card.attach = attach;
- ctlr->card.transmit = transmit;
- ctlr->card.intr = interrupt;
-
- print("Ether reset...\n");uartwait();
-
- return 0;
-}
-
--- a/os/boot/puma/flash.c
+++ /dev/null
@@ -1,226 +1,0 @@
-#include "boot.h"
-
-typedef struct Flashdev Flashdev;
-struct Flashdev {
- uchar* base;
- int size;
- uchar* exec;
- char* type;
- char* config;
- int conflen;
-};
-
-enum {
- FLASHSEG = 256*1024,
- CONFIGLIM = FLASHSEG,
- BOOTOFF = FLASHSEG,
- BOOTLEN = 3*FLASHSEG, /* third segment might be filsys */
- /* rest of flash is free */
-};
-
-static Flashdev flash;
-
-/*
- * configuration data is written between the bootstrap and
- * the end of region 0. the region ends with allocation descriptors
- * of the following form:
- *
- * byte order is big endian
- *
- * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
- */
-typedef struct Flalloc Flalloc;
-struct Flalloc {
- ulong check; /* checksum of data, or ~0 */
- ulong base; /* base of region; ~0 if unallocated, 0 if deleted */
- uchar len[3];
- uchar tag; /* see below */
- uchar sig[4];
-};
-
-enum {
- /* tags */
- Tdead= 0,
- Tboot= 0x01, /* space reserved for boot */
- Tconf= 0x02, /* configuration data */
- Tnone= 0xFF,
-
- Noval= ~0,
-};
-
-static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
-static char conftag[] = "#plan9.ini\n";
-
-static ulong
-checksum(uchar* p, int n)
-{
- ulong s;
-
- for(s=0; --n >= 0;)
- s += *p++;
- return s;
-}
-
-static int
-validptr(Flalloc *ap, uchar *p)
-{
- return p > (uchar*)end && p < (uchar*)ap;
-}
-
-static int
-flashcheck(Flalloc *ap, char **val, int *len)
-{
- uchar *base;
- int n;
-
- if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
- return 0;
- base = flash.base+ap->base;
- if(!validptr(ap, base))
- return 0;
- n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
- if(n == 0xFFFFFF)
- n = 0;
- if(n < 0)
- return 0;
- if(n > 0 && !validptr(ap, base+n-1))
- return 0;
- if(ap->check != Noval && checksum(base, n) != ap->check){
- print("flash: bad checksum\n");
- return 0;
- }
- *val = (char*)base;
- *len = n;
- return 1;
-}
-
-int
-flashinit(void)
-{
- int f, n, len;
- char *type, *val;
- Flalloc *ap;
-
- flash.base = 0;
- flash.exec = 0;
- flash.type = 0;
- /* TODO - check for presence and type */
-/*
- * if((m->iomem->memc[0].base & 1) == 0){
- * print("flash: flash not present or not enabled\n");
- * return 0;
- * }
- * f = (m->bcsr[2]>>28)&0xF;
- */
-f = 0;
- switch(f){
- default:
- print("flash boot: unknown or no flash\n");
- return 0;
- case 4: n=8; type = "SM732x8"; break;
- case 5: n=4; type = "SM732x8"; break;
- case 6: n=8; type = "AMD29F0x0"; break;
- case 7: n=4; type = "AMD29F0x0"; break;
- case 8: n=2; type = "AMD29F0x0"; break;
- }
- flash.type = type;
- flash.size = n*1024*1024;
- flash.base = KADDR(FLASH_BASE);
- flash.exec = flash.base + BOOTOFF;
- flash.config = nil;
- flash.conflen = 0;
-
- for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
- if(1)
- print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
- if(ap->tag == Tconf &&
- flashcheck(ap, &val, &len) &&
- len >= sizeof(conftag)-1 &&
- memcmp(val, conftag, sizeof(conftag)-1) == 0){
- flash.config = val;
- flash.conflen = len;
- print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
- }
- }
- if(flash.config){
- print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
- flash.config = nil; /* not that daring yet */
- }else
- print("flash: no config\n");
- if(issqueezed(flash.exec) == E_MAGIC){
- print("flash: squeezed StrongARM kernel installed\n");
- return 1<<0;
- }
- if(GLLONG(flash.exec) == E_MAGIC){
- print("flash: unsqueezed stringARM kernel installed\n");
- return 1<<0;
- }
- flash.exec = 0;
- print("flash: no StrongARM kernel in Flash\n");
- return 0;
-}
-
-char*
-flashconfig(int)
-{
- return flash.config;
-}
-
-int
-flashbootable(int)
-{
- return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == E_MAGIC);
-}
-
-int
-flashboot(int)
-{
- ulong entry, addr;
- void (*b)(void);
- Exec *ep;
- Block in;
- long n;
- uchar *p;
-
- if(flash.exec == 0)
- return -1;
- p = flash.exec;
- if(GLLONG(p) == E_MAGIC){
- /* unsqueezed: copy data and perhaps text, then jump to it */
- ep = (Exec*)p;
- entry = PADDR(GLLONG(ep->entry));
- p += sizeof(Exec);
- addr = entry;
- n = GLLONG(ep->text);
- if(addr != (ulong)p){
- memmove((void*)addr, p, n);
- print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
- }
- p += n;
- if(entry >= FLASH_BASE)
- addr = 3*BY2PG; /* kernel text is in Flash, data in RAM */
- else
- addr = PGROUND(addr+n);
- n = GLLONG(ep->data);
- memmove((void*)addr, p, n);
- print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
- }else{
- in.data = p;
- in.rp = in.data;
- in.lim = p+BOOTLEN;
- in.wp = in.lim;
- n = unsqueezef(&in, &entry);
- if(n < 0)
- return -1;
- }
- print("entry=0x%lux\n", entry);
- uartwait();
- /* scc2stop(); */
- /*
- * Go to new code. It's up to the program to get its PC relocated to
- * the right place.
- */
- b = (void (*)(void))KADDR(PADDR(entry));
- (*b)();
- return -1;
-}
--- a/os/boot/puma/fns.h
+++ /dev/null
@@ -1,111 +1,0 @@
-void aamloop(int);
-Alarm* alarm(int, void (*)(Alarm*), void*);
-void alarminit(void);
-int bootp(int, char*);
-void cancel(Alarm*);
-void checkalarms(void);
-void clockinit(void);
-void consinit(void);
-void delay(int);
-uchar* etheraddr(int);
-int etherinit(void);
-int etherrxpkt(int, Etherpkt*, int);
-int ethertxpkt(int, Etherpkt*, int, int);
-int flashboot(int);
-int flashbootable(int);
-char* flashconfig(int);
-int flashinit(void);
-char* getconf(char*);
-int getcfields(char*, char**, int, char*);
-int getstr(char*, char*, int, char*);
-int hardinit(void);
-long hardread(int, void*, long);
-long hardseek(int, long);
-long hardwrite(int, void*, long);
-void* ialloc(ulong, int);
-void idle(void);
-int isaconfig(char*, int, ISAConf*);
-int isgzipped(uchar*);
-int issqueezed(uchar*);
-void kbdinit(void);
-void kbdchar(Queue*, int);
-void machinit(void);
-void meminit(void);
-void microdelay(int);
-void mmuinit(void);
-uchar nvramread(int);
-void outb(int, int);
-void outs(int, ushort);
-void outl(int, ulong);
-void outsb(int, void*, int);
-void outss(int, void*, int);
-void outsl(int, void*, int);
-void panic(char*, ...);
-int optionsw(void);
-int plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
-Partition* setflashpart(int, char*);
-Partition* sethardpart(int, char*);
-Partition* setscsipart(int, char*);
-void setvec(int, void (*)(Ureg*, void*), void*);
-void screeninit(void);
-void screenputs(char*, int);
-void setr13(int, void*);
-int splhi(void);
-int spllo(void);
-void splx(int);
-void trapinit(void);
-void uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
-void uartputs(char*, int);
-void uartwait(void);
-long unsqueezef(Block*, ulong*);
-
-#define GSHORT(p) (((p)[1]<<8)|(p)[0])
-#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))
-#define GLSHORT(p) (((p)[0]<<8)|(p)[1])
-#define GLLONG(p) ((GLSHORT(p)<<16)|GLSHORT(p+2))
-
-#define KADDR(a) ((void*)((ulong)(a)|KZERO))
-#define PADDR(a) ((ulong)(a)&~KZERO)
-
-
-void mapinit(RMap*, Map*, int);
-void mapfree(RMap*, ulong, int);
-ulong mapalloc(RMap*, ulong, int, int);
-
-/* IBM bit field order */
-#define IBFEXT(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1))))
-#define IBIT(b) ((ulong)1<<(31-(b)))
-
-#define SIBIT(n) ((ushort)1<<(15-(n)))
-
-void* malloc(ulong);
-void free(void*);
-
-extern Block* iallocb(int);
-extern void freeb(Block*);
-extern Queue* qopen(int, int, void (*)(void*), void*);
-extern Block* qget(Queue*);
-extern void qbwrite(Queue*, Block*);
-extern long qlen(Queue*);
-#define qpass qbwrite
-extern void qbputc(Queue*, int);
-extern int qbgetc(Queue*);
-
-int sio_inb(int);
-void sio_outb(int, int);
-void led(int);
-
-extern void _virqcall(void);
-extern void _vfiqcall(void);
-extern void _vundcall(void);
-extern void _vsvccall(void);
-extern void _vpabcall(void);
-extern void _vdabcall(void);
-
-void flushIcache(void);
-void writeBackDC(void);
-void flushDcache(void);
-void flushIcache(void);
-void drainWBuffer(void);
-
-void pumainit(void);
--- a/os/boot/puma/hard.c
+++ /dev/null
@@ -1,773 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#define DPRINT if(0)print
-
-typedef struct Drive Drive;
-typedef struct Ident Ident;
-typedef struct Controller Controller;
-
-enum
-{
- /* ports */
- Pbase0= 0x1F0, /* primary */
- Pbase1= 0x170, /* secondary */
- Pbase2= 0x1E8, /* tertiary */
- Pbase3= 0x168, /* quaternary */
- Pdata= 0, /* data port (16 bits) */
- Perror= 1, /* error port (read) */
- Pprecomp= 1, /* buffer mode port (write) */
- Pcount= 2, /* sector count port */
- Psector= 3, /* sector number port */
- Pcyllsb= 4, /* least significant byte cylinder # */
- Pcylmsb= 5, /* most significant byte cylinder # */
- Pdh= 6, /* drive/head port */
- DHmagic= 0xA0,
- DHslave= 0x10,
- Pstatus= 7, /* status port (read) */
- Sbusy= (1<<7),
- Sready= (1<<6),
- Sdrq= (1<<3),
- Serr= (1<<0),
- Pcmd= 7, /* cmd port (write) */
-
- /* commands */
- Crecal= 0x10,
- Cread= 0x20,
- Cwrite= 0x30,
- Cident= 0xEC,
- Cident2= 0xFF, /* pseudo command for post Cident interrupt */
- Csetbuf= 0xEF,
-
- /* file types */
- Qdir= 0,
-
- Timeout= 5, /* seconds to wait for things to complete */
-
- NCtlr= 4,
- NDrive= NCtlr*2,
-};
-
-/*
- * ident sector from drive. this is from ANSI X3.221-1994
- */
-struct Ident
-{
- ushort config; /* general configuration info */
- ushort cyls; /* # of cylinders (default) */
- ushort reserved0;
- ushort heads; /* # of heads (default) */
- ushort b2t; /* unformatted bytes/track */
- ushort b2s; /* unformated bytes/sector */
- ushort s2t; /* sectors/track (default) */
- ushort reserved1[3];
-/* 10 */
- ushort serial[10]; /* serial number */
- ushort type; /* buffer type */
- ushort bsize; /* buffer size/512 */
- ushort ecc; /* ecc bytes returned by read long */
- ushort firm[4]; /* firmware revision */
- ushort model[20]; /* model number */
-/* 47 */
- ushort s2i; /* number of sectors/interrupt */
- ushort dwtf; /* double word transfer flag */
- ushort capabilities;
- ushort reserved2;
- ushort piomode;
- ushort dmamode;
- ushort cvalid; /* (cvald&1) if next 4 words are valid */
- ushort ccyls; /* current # cylinders */
- ushort cheads; /* current # heads */
- ushort cs2t; /* current sectors/track */
- ushort ccap[2]; /* current capacity in sectors */
- ushort cs2i; /* current number of sectors/interrupt */
-/* 60 */
- ushort lbasecs[2]; /* # LBA user addressable sectors */
- ushort dmasingle;
- ushort dmadouble;
-/* 64 */
- ushort reserved3[64];
- ushort vendor[32]; /* vendor specific */
- ushort reserved4[96];
-};
-
-/*
- * a hard drive
- */
-struct Drive
-{
- Controller *cp;
- uchar driveno;
- uchar dh;
-
- Disc;
-};
-
-/*
- * a controller for 2 drives
- */
-struct Controller
-{
- int pbase; /* base port */
- uchar ctlrno;
-
- /*
- * current operation
- */
- int cmd; /* current command */
- char *buf; /* xfer buffer */
- int tcyl; /* target cylinder */
- int thead; /* target head */
- int tsec; /* target sector */
- int tbyte; /* target byte */
- int nsecs; /* length of transfer (sectors) */
- int sofar; /* bytes transferred so far */
- int status;
- int error;
- Drive *dp; /* drive being accessed */
-};
-
-static int atactlrmask;
-static Controller *atactlr[NCtlr];
-static int atadrivemask;
-static Drive *atadrive[NDrive];
-static int pbase[NCtlr] = {
- Pbase0, Pbase1, Pbase2, Pbase3,
-};
-
-static void hardintr(Ureg*, void*);
-static long hardxfer(Drive*, Partition*, int, ulong, long);
-static int hardident(Drive*);
-static void hardsetbuf(Drive*, int);
-static void hardpart(Drive*);
-static int hardparams(Drive*);
-static void hardrecal(Drive*);
-static int hardprobe(Drive*, int, int, int);
-
-static void
-atactlrprobe(int ctlrno, int irq)
-{
- Controller *ctlr;
- Drive *drive;
- int driveno, port;
-
- if(atactlrmask & (1<<ctlrno))
- return;
- atactlrmask |= 1<<ctlrno;
-
- port = pbase[ctlrno];
- outb(port+Pdh, DHmagic);
- delay(1);
- if((inb(port+Pdh) & 0xFF) != DHmagic){
- DPRINT("ata%d: DHmagic not ok\n", ctlrno);
- return;
- }
- DPRINT("ata%d: DHmagic ok\n", ctlrno);
-
- atactlr[ctlrno] = ialloc(sizeof(Controller), 0);
- ctlr = atactlr[ctlrno];
- ctlr->pbase = port;
- ctlr->ctlrno = ctlrno;
- ctlr->buf = ialloc(Maxxfer, 0);
- inb(ctlr->pbase+Pstatus);
- setvec(irq, hardintr, ctlr);
-
- driveno = ctlrno*2;
- atadrive[driveno] = ialloc(sizeof(Drive), 0);
- drive = atadrive[driveno];
- drive->cp = ctlr;
- drive->driveno = driveno;
- drive->dh = DHmagic;
-
- driveno++;
- atadrive[driveno] = ialloc(sizeof(Drive), 0);
- drive = atadrive[driveno];
- drive->cp = ctlr;
- drive->driveno = driveno;
- drive->dh = DHmagic|DHslave;
-}
-
-static Drive*
-atadriveprobe(int driveno)
-{
- Drive *drive;
- int ctlrno;
- ISAConf isa;
-
- ctlrno = driveno/2;
- if(atactlr[ctlrno] == 0){
- if(atactlrmask & (1<<ctlrno))
- return 0;
- memset(&isa, 0, sizeof(ISAConf));
- if(isaconfig("ata", ctlrno, &isa) == 0)
- return 0;
- if(ctlrno && isa.irq)
- atactlrprobe(ctlrno, Int0vec+isa.irq);
- if(atactlr[ctlrno] == 0)
- return 0;
- }
-
- drive = atadrive[driveno];
- if(drive->online == 0){
- if(atadrivemask & (1<<driveno))
- return 0;
- atadrivemask |= 1<<driveno;
- if(hardparams(drive))
- return 0;
- if(drive->lba)
- print("hd%d: LBA %d sectors, %ud bytes\n",
- drive->driveno, drive->sectors, drive->cap);
- else
- print("hd%d: CHS %d/%d/%d %d bytes\n",
- drive->driveno, drive->cyl, drive->heads,
- drive->sectors, drive->cap);
- drive->online = 1;
- hardpart(drive);
- hardsetbuf(drive, 1);
- }
-
- return drive;
-}
-
-int
-hardinit(void)
-{
- atactlrprobe(0, ATAvec0);
- return 0xFF;
-}
-
-long
-hardseek(int driveno, long offset)
-{
- Drive *drive;
-
- if((drive = atadriveprobe(driveno)) == 0)
- return -1;
- drive->offset = offset;
- return offset;
-}
-
-/*
- * did an interrupt happen?
- */
-static void
-hardwait(Controller *cp)
-{
- ulong start;
- int x;
-
- x = spllo();
- for(start = m->ticks; TK2SEC(m->ticks - start) < Timeout && cp->cmd;)
- if(cp->cmd == Cident2 && TK2SEC(m->ticks - start) >= 1)
- break;
- if(TK2SEC(m->ticks - start) >= Timeout){
- DPRINT("hardwait timed out %ux\n", inb(cp->pbase+Pstatus));
- hardintr(0, cp);
- }
- splx(x);
-}
-
-Partition*
-sethardpart(int driveno, char *p)
-{
- Partition *pp;
- Drive *dp;
-
- if((dp = atadriveprobe(driveno)) == 0)
- return 0;
-
- for(pp = dp->p; pp < &dp->p[dp->npart]; pp++)
- if(strcmp(pp->name, p) == 0){
- dp->current = pp;
- return pp;
- }
- return 0;
-}
-
-long
-hardread(int driveno, void *a, long n)
-{
- Drive *dp;
- long rv, i;
- int skip;
- uchar *aa = a;
- Partition *pp;
- Controller *cp;
-
- if((dp = atadriveprobe(driveno)) == 0)
- return 0;
-
- pp = dp->current;
- if(pp == 0)
- return -1;
- cp = dp->cp;
-
- skip = dp->offset % dp->bytes;
- for(rv = 0; rv < n; rv += i){
- i = hardxfer(dp, pp, Cread, dp->offset+rv-skip, n-rv+skip);
- if(i == 0)
- break;
- if(i < 0)
- return -1;
- i -= skip;
- if(i > n - rv)
- i = n - rv;
- memmove(aa+rv, cp->buf + skip, i);
- skip = 0;
- }
- dp->offset += rv;
-
- return rv;
-}
-
-/*
- * wait for the controller to be ready to accept a command
- */
-static int
-cmdreadywait(Drive *drive)
-{
- ulong end;
- uchar dh, status;
- Controller *ctlr;
-
- ctlr = drive->cp;
- end = m->ticks+MS2TK(10)+1;
- dh = (inb(ctlr->pbase+Pdh) & DHslave)^(drive->dh & DHslave);
-
- status = 0;
- while(m->ticks < end){
- status = inb(ctlr->pbase+Pstatus);
- if(status & Sbusy)
- continue;
- if(dh){
- outb(ctlr->pbase+Pdh, drive->dh);
- dh = 0;
- continue;
- }
- if(status & Sready)
- return 0;
- }
- USED(status);
-
- DPRINT("hd%d: cmdreadywait failed %uX\n", drive->driveno, status);
- outb(ctlr->pbase+Pdh, DHmagic);
- return -1;
-}
-
-/*
- * transfer a number of sectors. hardintr will perform all the iterative
- * parts.
- */
-static long
-hardxfer(Drive *dp, Partition *pp, int cmd, ulong start, long len)
-{
- Controller *cp;
- long lsec;
-
- if(dp->online == 0){
- DPRINT("disk not on line\n");
- return -1;
- }
-
- if(cmd == Cwrite)
- return -1;
-
- /*
- * cut transfer size down to disk buffer size
- */
- start = start / dp->bytes;
- if(len > Maxxfer)
- len = Maxxfer;
- len = (len + dp->bytes - 1) / dp->bytes;
-
- /*
- * calculate physical address
- */
- cp = dp->cp;
- lsec = start + pp->start;
- if(lsec >= pp->end){
- DPRINT("read past end of partition\n");
- return 0;
- }
- if(dp->lba){
- cp->tsec = lsec & 0xff;
- cp->tcyl = (lsec>>8) & 0xffff;
- cp->thead = (lsec>>24) & 0xf;
- } else {
- cp->tcyl = lsec/(dp->sectors*dp->heads);
- cp->tsec = (lsec % dp->sectors) + 1;
- cp->thead = (lsec/dp->sectors) % dp->heads;
- }
-
- /*
- * can't xfer past end of disk
- */
- if(lsec+len > pp->end)
- len = pp->end - lsec;
- cp->nsecs = len;
-
- if(cmdreadywait(dp) < 0)
- return -1;
-
- /*
- * start the transfer
- */
- cp->cmd = cmd;
- cp->dp = dp;
- cp->sofar = 0;
- cp->status = 0;
- DPRINT("xfer:\ttcyl %d, tsec %d, thead %d\n", cp->tcyl, cp->tsec, cp->thead);
- DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
- outb(cp->pbase+Pcount, cp->nsecs);
- outb(cp->pbase+Psector, cp->tsec);
- outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | cp->thead);
- outb(cp->pbase+Pcyllsb, cp->tcyl);
- outb(cp->pbase+Pcylmsb, cp->tcyl>>8);
- outb(cp->pbase+Pcmd, cmd);
-
- hardwait(cp);
-
- if(cp->status & Serr){
- DPRINT("hd%d err: status %lux, err %lux\n",
- dp->driveno, cp->status, cp->error);
- DPRINT("\ttcyl %d, tsec %d, thead %d\n",
- cp->tcyl, cp->tsec, cp->thead);
- DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
- return -1;
- }
-
- return cp->nsecs*dp->bytes;
-}
-
-/*
- * set read ahead mode (1 == on, 0 == off)
- */
-static void
-hardsetbuf(Drive *dp, int on)
-{
- Controller *cp = dp->cp;
-
- if(cmdreadywait(dp) < 0)
- return;
-
- cp->cmd = Csetbuf;
- /* BUG: precomp varies by hard drive...this is safari-specific? */
- outb(cp->pbase+Pprecomp, on ? 0xAA : 0x55);
- outb(cp->pbase+Pdh, dp->dh);
- outb(cp->pbase+Pcmd, Csetbuf);
-
- hardwait(cp);
-}
-
-static int
-isatapi(Drive *drive)
-{
- Controller *cp;
-
- cp = drive->cp;
- outb(cp->pbase+Pdh, drive->dh);
- microdelay(1);
- if(inb(cp->pbase+Pstatus))
- return 0;
- if(inb(cp->pbase+Pcylmsb) != 0xEB || inb(cp->pbase+Pcyllsb) != 0x14)
- return 0;
- return 1;
-}
-
-/*
- * get parameters from the drive
- */
-static int
-hardident(Drive *dp)
-{
- Controller *cp;
- Ident *ip;
-
- dp->bytes = 512;
- cp = dp->cp;
-
- if(isatapi(dp) || cmdreadywait(dp) < 0)
- return -1;
-
- cp->nsecs = 1;
- cp->sofar = 0;
- cp->cmd = Cident;
- cp->dp = dp;
- outb(cp->pbase+Pdh, dp->dh);
- outb(cp->pbase+Pcmd, Cident);
-
- hardwait(cp);
-
- if(cp->status & Serr)
- return -1;
-
- hardwait(cp);
-
- ip = (Ident*)cp->buf;
- DPRINT("LBA%d: %lud\n",
- ip->capabilities & (1<<9) == 1, (ip->lbasecs[0]) | (ip->lbasecs[1]<<16));
- DPRINT("DEF: %ud/%ud/%ud\nMAP %ud/%ud/%ud\n",
- ip->cyls, ip->heads, ip->s2t,
- ip->ccyls, ip->cheads, ip->cs2t);
- if(ip->capabilities & (1<<9)){
- dp->lba = 1;
- dp->sectors = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16);
- dp->cap = dp->bytes * dp->sectors;
-/*print("\nata%d model %s with %d lba sectors\n", dp->driveno, id, dp->sectors);/**/
- } else {
- dp->lba = 0;
-
- /* use default (unformatted) settings */
- dp->cyl = ip->cyls;
- dp->heads = ip->heads;
- dp->sectors = ip->s2t;
-/*print("\nata%d model %s with default %d cyl %d head %d sec\n", dp->driveno,
- id, dp->cyl, dp->heads, dp->sectors);/**/
-
- if(ip->cvalid&(1<<0)){
- /* use current settings */
- dp->cyl = ip->ccyls;
- dp->heads = ip->cheads;
- dp->sectors = ip->cs2t;
-/*print("\tchanged to %d cyl %d head %d sec\n", dp->cyl, dp->heads, dp->sectors);/**/
- }
- dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
- }
-
- return 0;
-}
-
-/*
- * probe the given sector to see if it exists
- */
-static int
-hardprobe(Drive *dp, int cyl, int sec, int head)
-{
- Controller *cp;
-
- cp = dp->cp;
- if(cmdreadywait(dp) < 0)
- return -1;
-
- /*
- * start the transfer
- */
- cp->cmd = Cread;
- cp->dp = dp;
- cp->sofar = 0;
- cp->nsecs = 1;
- cp->status = 0;
- outb(cp->pbase+Pcount, 1);
- outb(cp->pbase+Psector, sec+1);
- outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | head);
- outb(cp->pbase+Pcyllsb, cyl);
- outb(cp->pbase+Pcylmsb, cyl>>8);
- outb(cp->pbase+Pcmd, Cread);
-
- hardwait(cp);
-
- if(cp->status & Serr)
- return -1;
-
- return 0;
-}
-
-/*
- * figure out the drive parameters
- */
-static int
-hardparams(Drive *dp)
-{
- int i, hi, lo;
-
- /*
- * first try the easy way, ask the drive and make sure it
- * isn't lying.
- */
- dp->bytes = 512;
- if(hardident(dp) < 0)
- return -1;
- if(dp->lba){
- i = dp->sectors - 1;
- if(hardprobe(dp, (i>>8)&0xffff, (i&0xff)-1, (i>>24)&0xf) == 0)
- return 0;
- } else {
- if(hardprobe(dp, dp->cyl-1, dp->sectors-1, dp->heads-1) == 0)
- return 0;
- }
-
- DPRINT("hardparam: cyl %d sectors %d heads %d\n", dp->cyl, dp->sectors, dp->heads);
- /*
- * the drive lied, determine parameters by seeing which ones
- * work to read sectors.
- */
- dp->lba = 0;
- for(i = 0; i < 16; i++)
- if(hardprobe(dp, 0, 0, i) < 0)
- break;
- dp->heads = i;
- for(i = 0; i < 64; i++)
- if(hardprobe(dp, 0, i, 0) < 0)
- break;
- dp->sectors = i;
- for(i = 512; ; i += 512)
- if(hardprobe(dp, i, dp->sectors-1, dp->heads-1) < 0)
- break;
- lo = i - 512;
- hi = i;
- for(; hi-lo > 1;){
- i = lo + (hi - lo)/2;
- if(hardprobe(dp, i, dp->sectors-1, dp->heads-1) < 0)
- hi = i;
- else
- lo = i;
- }
- dp->cyl = lo + 1;
- dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
-
- if(dp->cyl == 0 || dp->heads == 0 || dp->sectors == 0 || dp->cap == 0)
- return -1;
-
- return 0;
-}
-
-/*
- * read partition table. The partition table is just ascii strings.
- */
-#define MAGIC "plan9 partitions"
-static void
-hardpart(Drive *dp)
-{
- Partition *pp;
- Controller *cp;
- char *field[3], *line[Npart+1], *p, buf[NAMELEN];
- ulong n;
- int i;
-
- cp = dp->cp;
-
- /*
- * we always have a partition for the whole disk
- * and one for the partition table
- */
- pp = &dp->p[0];
- strcpy(pp->name, "disk");
- pp->start = 0;
- pp->end = dp->cap / dp->bytes;
- pp++;
- strcpy(pp->name, "partition");
- pp->start = dp->p[0].end - 1;
- pp->end = dp->p[0].end;
- dp->npart = 2;
-
- /*
- * Check if the partitions are described in plan9.ini.
- * If not, read the disc.
- */
- sprint(buf, "hd%dpartition", dp->driveno);
- if((p = getconf(buf)) == 0){
- /*
- * read last sector from disk, null terminate. This used
- * to be the sector we used for the partition tables.
- * However, this sector is special on some PC's so we've
- * started to use the second last sector as the partition
- * table instead. To avoid reconfiguring all our old systems
- * we first look to see if there is a valid partition
- * table in the last sector. If so, we use it. Otherwise
- * we switch to the second last.
- */
- hardxfer(dp, pp, Cread, 0, dp->bytes);
- cp->buf[dp->bytes-1] = 0;
- n = getcfields(cp->buf, line, Npart+1, "\n");
- if(n == 0 || strncmp(line[0], MAGIC, sizeof(MAGIC)-1)){
- dp->p[0].end--;
- dp->p[1].start--;
- dp->p[1].end--;
- hardxfer(dp, pp, Cread, 0, dp->bytes);
- cp->buf[dp->bytes-1] = 0;
- n = getcfields(cp->buf, line, Npart+1, "\n");
- }
- }
- else{
- strcpy(cp->buf, p);
- n = getcfields(cp->buf, line, Npart+1, "\n");
- }
-
- /*
- * parse partition table.
- */
- if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
- for(i = 1; i < n; i++){
- pp++;
- if(getcfields(line[i], field, 3, " ") != 3)
- break;
- strncpy(pp->name, field[0], NAMELEN);
- pp->start = strtoul(field[1], 0, 0);
- pp->end = strtoul(field[2], 0, 0);
- if(pp->start > pp->end || pp->start >= dp->p[0].end)
- break;
- dp->npart++;
- }
- }
- return;
-}
-
-/*
- * we get an interrupt for every sector transferred
- */
-static void
-hardintr(Ureg*, void *arg)
-{
- Controller *cp;
- Drive *dp;
- long loop;
-
- cp = arg;
- dp = cp->dp;
-
- loop = 0;
- while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy)
- if(++loop > 100000){
- print("hardintr 0x%lux\n", cp->status);
- break;
- }
- switch(cp->cmd){
- case Cread:
- case Cident:
- if(cp->status & Serr){
- cp->cmd = 0;
- cp->error = inb(cp->pbase+Perror);
- return;
- }
- loop = 0;
- while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
- if(++loop > 100000){
- print("hardintr 2 cmd %ux status %ux",
- cp->cmd, inb(cp->pbase+Pstatus));
- cp->cmd = 0;
- return;
- }
- inss(cp->pbase+Pdata, &cp->buf[cp->sofar*dp->bytes],
- dp->bytes/2);
- cp->sofar++;
- if(cp->sofar >= cp->nsecs){
- if(cp->cmd == Cident && (cp->status & Sready) == 0)
- cp->cmd = Cident2; /* sometimes we get a second intr */
- else
- cp->cmd = 0;
- inb(cp->pbase+Pstatus);
- }
- break;
- case Csetbuf:
- case Cident2:
- cp->cmd = 0;
- break;
- default:
- cp->cmd = 0;
- break;
- }
-}
--- a/os/boot/puma/io.h
+++ /dev/null
@@ -1,3 +1,0 @@
-#define inb(port) sio_inb(port)
-#define outb(port, data) sio_outb(port, data)
-
--- a/os/boot/puma/ip.h
+++ /dev/null
@@ -1,98 +1,0 @@
-typedef struct Udphdr Udphdr;
-struct Udphdr
-{
- uchar d[6]; /* Ethernet destination */
- uchar s[6]; /* Ethernet source */
- uchar type[2]; /* Ethernet packet type */
-
- uchar vihl; /* Version and header length */
- uchar tos; /* Type of service */
- uchar length[2]; /* packet length */
- uchar id[2]; /* Identification */
- uchar frag[2]; /* Fragment information */
-
- /* Udp pseudo ip really starts here */
- uchar ttl;
- uchar udpproto; /* Protocol */
- uchar udpplen[2]; /* Header plus data length */
- uchar udpsrc[4]; /* Ip source */
- uchar udpdst[4]; /* Ip destination */
- uchar udpsport[2]; /* Source port */
- uchar udpdport[2]; /* Destination port */
- uchar udplen[2]; /* data length */
- uchar udpcksum[2]; /* Checksum */
-};
-
-typedef struct Etherhdr Etherhdr;
-struct Etherhdr
-{
- uchar d[6];
- uchar s[6];
- uchar type[2];
-
- /* Now we have the ip fields */
- uchar vihl; /* Version and header length */
- uchar tos; /* Type of service */
- uchar length[2]; /* packet length */
- uchar id[2]; /* Identification */
- uchar frag[2]; /* Fragment information */
- uchar ttl; /* Time to live */
- uchar proto; /* Protocol */
- uchar cksum[2]; /* Header checksum */
- uchar src[4]; /* Ip source */
- uchar dst[4]; /* Ip destination */
-};
-
-enum
-{
- IP_VER = 0x40,
- IP_HLEN = 0x05,
- UDP_EHSIZE = 22,
- UDP_PHDRSIZE = 12,
- UDP_HDRSIZE = 20,
- ETHER_HDR = 14,
- IP_UDPPROTO = 17,
- ET_IP = 0x800,
- Bcastip = 0xffffffff,
- BPportsrc = 68,
- BPportdst = 67,
- TFTPport = 69,
- Timeout = 5000, /* milliseconds */
- Bootrequest = 1,
- Bootreply = 2,
- Tftp_READ = 1,
- Tftp_WRITE = 2,
- Tftp_DATA = 3,
- Tftp_ACK = 4,
- Tftp_ERROR = 5,
- Segsize = 512,
- TFTPSZ = Segsize+10,
-};
-
-typedef struct Bootp Bootp;
-struct Bootp
-{
- uchar op; /* opcode */
- uchar htype; /* hardware type */
- uchar hlen; /* hardware address len */
- uchar hops; /* hops */
- uchar xid[4]; /* a random number */
- uchar secs[2]; /* elapsed snce client started booting */
- uchar pad[2];
- uchar ciaddr[4]; /* client IP address (client tells server) */
- uchar yiaddr[4]; /* client IP address (server tells client) */
- uchar siaddr[4]; /* server IP address */
- uchar giaddr[4]; /* gateway IP address */
- uchar chaddr[16]; /* client hardware address */
- char sname[64]; /* server host name (optional) */
- char file[128]; /* boot file name */
- char vend[128]; /* vendor-specific goo */
-};
-
-typedef struct Netaddr Netaddr;
-struct Netaddr
-{
- ulong ip;
- ushort port;
- char ea[Eaddrlen];
-};
--- a/os/boot/puma/kbd.c
+++ /dev/null
@@ -1,482 +1,0 @@
-#include "boot.h"
-
-
-enum {
- Data= 0x60, /* data port */
-
- Status= 0x64, /* status port */
- Inready= 0x01, /* input character ready */
- Outbusy= 0x02, /* output busy */
- Sysflag= 0x04, /* system flag */
- Cmddata= 0x08, /* cmd==0, data==1 */
- Inhibit= 0x10, /* keyboard/mouse inhibited */
- Minready= 0x20, /* mouse character ready */
- Rtimeout= 0x40, /* general timeout */
- Parity= 0x80,
-
- Cmd= 0x64, /* command port (write only) */
-
- Spec= 0x80,
-
- PF= Spec|0x20, /* num pad function key */
- View= Spec|0x00, /* view (shift window up) */
- KF= Spec|0x40, /* function key */
- Shift= Spec|0x60,
- Break= Spec|0x61,
- Ctrl= Spec|0x62,
- Latin= Spec|0x63,
- Caps= Spec|0x64,
- Num= Spec|0x65,
- No= Spec|0x7F, /* no mapping */
-
- Home= KF|13,
- Up= KF|14,
- Pgup= KF|15,
- Print= KF|16,
- Left= View,
- Right= View,
- End= '\r',
- Down= View,
- Pgdown= View,
- Ins= KF|20,
- Del= 0x7F,
-};
-
-uchar kbtab[] =
-{
-[0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
-[0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
-[0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
-[0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
-[0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
-[0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
-[0x30] 'b', 'n', 'm', ',', '.', '/', Shift, No,
-[0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
-[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
-[0x48] No, No, No, No, No, No, No, No,
-[0x50] No, No, No, No, No, No, No, KF|11,
-[0x58] KF|12, No, No, No, No, No, No, No,
-};
-
-uchar kbtabshift[] =
-{
-[0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
-[0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
-[0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
-[0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
-[0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
-[0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
-[0x30] 'B', 'N', 'M', '<', '>', '?', Shift, No,
-[0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
-[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
-[0x48] No, No, No, No, No, No, No, No,
-[0x50] No, No, No, No, No, No, No, KF|11,
-[0x58] KF|12, No, No, No, No, No, No, No,
-};
-
-uchar kbtabesc1[] =
-{
-[0x00] No, No, No, No, No, No, No, No,
-[0x08] No, No, No, No, No, No, No, No,
-[0x10] No, No, No, No, No, No, No, No,
-[0x18] No, No, No, No, No, Ctrl, No, No,
-[0x20] No, No, No, No, No, No, No, No,
-[0x28] No, No, No, No, No, No, No, No,
-[0x30] No, No, No, No, No, No, No, Print,
-[0x38] Latin, No, No, No, No, No, No, No,
-[0x40] No, No, No, No, No, No, Break, Home,
-[0x48] Up, Pgup, No, Down, No, Right, No, End,
-[0x50] Left, Pgdown, Ins, Del, No, No, No, No,
-[0x58] No, No, No, No, No, No, No, No,
-};
-
-struct latin
-{
- uchar l;
- char c[2];
-}latintab[] = {
- L'¡', "!!", /* spanish initial ! */
- L'¢', "c|", /* cent */
- L'¢', "c$", /* cent */
- L'£', "l$", /* pound sterling */
- L'¤', "g$", /* general currency */
- L'¥', "y$", /* yen */
- L'¥', "j$", /* yen */
- L'¦', "||", /* broken vertical bar */
- L'§', "SS", /* section symbol */
- L'¨', "\"\"", /* dieresis */
- L'©', "cr", /* copyright */
- L'©', "cO", /* copyright */
- L'ª', "sa", /* super a, feminine ordinal */
- L'«', "<<", /* left angle quotation */
- L'¬', "no", /* not sign, hooked overbar */
- L'', "--", /* soft hyphen */
- L'®', "rg", /* registered trademark */
- L'¯', "__", /* macron */
- L'°', "s0", /* degree (sup o) */
- L'±', "+-", /* plus-minus */
- L'²', "s2", /* sup 2 */
- L'³', "s3", /* sup 3 */
- L'´', "''", /* grave accent */
- L'µ', "mu", /* mu */
- L'¶', "pg", /* paragraph (pilcrow) */
- L'·', "..", /* centered . */
- L'¸', ",,", /* cedilla */
- L'¹', "s1", /* sup 1 */
- L'º', "so", /* sup o */
- L'»', ">>", /* right angle quotation */
- L'¼', "14", /* 1/4 */
- L'½', "12", /* 1/2 */
- L'¾', "34", /* 3/4 */
- L'¿', "??", /* spanish initial ? */
- L'À', "A`", /* A grave */
- L'Á', "A'", /* A acute */
- L'Â', "A^", /* A circumflex */
- L'Ã', "A~", /* A tilde */
- L'Ä', "A\"", /* A dieresis */
- L'Ä', "A:", /* A dieresis */
- L'Å', "Ao", /* A circle */
- L'Å', "AO", /* A circle */
- L'Æ', "Ae", /* AE ligature */
- L'Æ', "AE", /* AE ligature */
- L'Ç', "C,", /* C cedilla */
- L'È', "E`", /* E grave */
- L'É', "E'", /* E acute */
- L'Ê', "E^", /* E circumflex */
- L'Ë', "E\"", /* E dieresis */
- L'Ë', "E:", /* E dieresis */
- L'Ì', "I`", /* I grave */
- L'Í', "I'", /* I acute */
- L'Î', "I^", /* I circumflex */
- L'Ï', "I\"", /* I dieresis */
- L'Ï', "I:", /* I dieresis */
- L'Ð', "D-", /* Eth */
- L'Ñ', "N~", /* N tilde */
- L'Ò', "O`", /* O grave */
- L'Ó', "O'", /* O acute */
- L'Ô', "O^", /* O circumflex */
- L'Õ', "O~", /* O tilde */
- L'Ö', "O\"", /* O dieresis */
- L'Ö', "O:", /* O dieresis */
- L'Ö', "OE", /* O dieresis */
- L'Ö', "Oe", /* O dieresis */
- L'×', "xx", /* times sign */
- L'Ø', "O/", /* O slash */
- L'Ù', "U`", /* U grave */
- L'Ú', "U'", /* U acute */
- L'Û', "U^", /* U circumflex */
- L'Ü', "U\"", /* U dieresis */
- L'Ü', "U:", /* U dieresis */
- L'Ü', "UE", /* U dieresis */
- L'Ü', "Ue", /* U dieresis */
- L'Ý', "Y'", /* Y acute */
- L'Þ', "P|", /* Thorn */
- L'Þ', "Th", /* Thorn */
- L'Þ', "TH", /* Thorn */
- L'ß', "ss", /* sharp s */
- L'à', "a`", /* a grave */
- L'á', "a'", /* a acute */
- L'â', "a^", /* a circumflex */
- L'ã', "a~", /* a tilde */
- L'ä', "a\"", /* a dieresis */
- L'ä', "a:", /* a dieresis */
- L'å', "ao", /* a circle */
- L'æ', "ae", /* ae ligature */
- L'ç', "c,", /* c cedilla */
- L'è', "e`", /* e grave */
- L'é', "e'", /* e acute */
- L'ê', "e^", /* e circumflex */
- L'ë', "e\"", /* e dieresis */
- L'ë', "e:", /* e dieresis */
- L'ì', "i`", /* i grave */
- L'í', "i'", /* i acute */
- L'î', "i^", /* i circumflex */
- L'ï', "i\"", /* i dieresis */
- L'ï', "i:", /* i dieresis */
- L'ð', "d-", /* eth */
- L'ñ', "n~", /* n tilde */
- L'ò', "o`", /* o grave */
- L'ó', "o'", /* o acute */
- L'ô', "o^", /* o circumflex */
- L'õ', "o~", /* o tilde */
- L'ö', "o\"", /* o dieresis */
- L'ö', "o:", /* o dieresis */
- L'ö', "oe", /* o dieresis */
- L'÷', "-:", /* divide sign */
- L'ø', "o/", /* o slash */
- L'ù', "u`", /* u grave */
- L'ú', "u'", /* u acute */
- L'û', "u^", /* u circumflex */
- L'ü', "u\"", /* u dieresis */
- L'ü', "u:", /* u dieresis */
- L'ü', "ue", /* u dieresis */
- L'ý', "y'", /* y acute */
- L'þ', "th", /* thorn */
- L'þ', "p|", /* thorn */
- L'ÿ', "y\"", /* y dieresis */
- L'ÿ', "y:", /* y dieresis */
- 0, 0,
-};
-
-enum
-{
- /* controller command byte */
- Cscs1= (1<<6), /* scan code set 1 */
- Cmousedis= (1<<5), /* mouse disable */
- Ckbddis= (1<<4), /* kbd disable */
- Csf= (1<<2), /* system flag */
- Cmouseint= (1<<1), /* mouse interrupt enable */
- Ckbdint= (1<<0), /* kbd interrupt enable */
-};
-
-static uchar ccc;
-
-int
-latin1(int k1, int k2)
-{
- struct latin *l;
-
- for(l=latintab; l->l; l++)
- if(k1==l->c[0] && k2==l->c[1])
- return l->l;
- return 0;
-}
-
-/*
- * wait for output no longer busy
- */
-static int
-outready(void)
-{
- int tries;
-
- for(tries = 0; (inb(Status) & Outbusy); tries++){
- if(tries > 500)
- return -1;
- delay(2);
- }
- return 0;
-}
-
-/*
- * wait for input
- */
-static int
-inready(void)
-{
- int tries;
-
- for(tries = 0; !(inb(Status) & Inready); tries++){
- if(tries > 500)
- return -1;
- delay(2);
- }
- return 0;
-}
-
-/*
- * ask 8042 to enable the use of address bit 20
- */
-void
-i8042a20(void)
-{
- outready();
- outb(Cmd, 0xD1);
- outready();
- outb(Data, 0xDF);
- outready();
-}
-
-/*
- * ask 8042 to reset the machine
- */
-void
-i8042reset(void)
-{
- ushort *s = (ushort*)(KZERO|0x472);
- int i, x;
-
- *s = 0x1234; /* BIOS warm-boot flag */
-
- outready();
- outb(Cmd, 0xFE); /* pulse reset line (means resend on AT&T machines) */
- outready();
-
- /*
- * Pulse it by hand (old somewhat reliable)
- */
- x = 0xDF;
- for(i = 0; i < 5; i++){
- x ^= 1;
- outready();
- outb(Cmd, 0xD1);
- outready();
- outb(Data, x); /* toggle reset */
- delay(100);
- }
-}
-
-/*
- * keyboard interrupt
- */
-int
-kbdintr0(void)
-{
- int s, c;
- static int esc1, esc2;
- static int shift;
- static int caps;
- static int ctl;
- static int num;
- static int lstate, k1, k2;
- int keyup;
-
- /*
- * get status
- */
- s = inb(Status);
- if(!(s&Inready))
- return -1;
-
- /*
- * get the character
- */
- c = inb(Data);
-
- /*
- * e0's is the first of a 2 character sequence
- */
- if(c == 0xe0){
- esc1 = 1;
- return 0;
- } else if(c == 0xe1){
- esc2 = 2;
- return 0;
- }
-
- keyup = c&0x80;
- c &= 0x7f;
- if(c > sizeof kbtab){
- print("unknown key %ux\n", c|keyup);
- kbdchar(0, k1);
- return 0;
- }
-
- if(esc1){
- c = kbtabesc1[c];
- esc1 = 0;
- kbdchar(0, c);
- return 0;
- } else if(esc2){
- esc2--;
- return 0;
- } else if(shift)
- c = kbtabshift[c];
- else
- c = kbtab[c];
-
- if(caps && c<='z' && c>='a')
- c += 'A' - 'a';
-
- /*
- * keyup only important for shifts
- */
- if(keyup){
- switch(c){
- case Shift:
- shift = 0;
- break;
- case Ctrl:
- ctl = 0;
- break;
- }
- return 0;
- }
-
- /*
- * normal character
- */
- if(!(c & Spec)){
- if(ctl)
- c &= 0x1f;
- switch(lstate){
- case 1:
- k1 = c;
- lstate = 2;
- return 0;
- case 2:
- k2 = c;
- lstate = 0;
- c = latin1(k1, k2);
- if(c == 0){
- kbdchar(0, k1);
- c = k2;
- }
- /* fall through */
- default:
- break;
- }
- } else {
- switch(c){
- case Caps:
- caps ^= 1;
- return 0;
- case Num:
- num ^= 1;
- return 0;
- case Shift:
- shift = 1;
- return 0;
- case Latin:
- lstate = 1;
- return 0;
- case Ctrl:
- ctl = 1;
- return 0;
- }
- }
- kbdchar(0, c);
- return 0;
-}
-
-static void
-kbdintr(Ureg*, void*)
-{
- while(kbdintr0() == 0)
- ;
-}
-
-static char *initfailed = "kbd init failed\n";
-
-void
-kbdinit(void)
-{
- int c;
-
- /* wait for a quiescent controller */
- while((c = inb(Status)) & (Outbusy | Inready))
- if(c & Inready)
- inb(Data);
-
- /* get current controller command byte */
- outb(Cmd, 0x20);
- if(inready() < 0){
- print("kbdinit: can't read ccc\n");
- ccc = 0;
- } else
- ccc = inb(Data);
-
- /* enable kbd xfers and interrupts */
- ccc &= ~Ckbddis;
- ccc |= Csf | Ckbdint | Cscs1;
- if(outready() < 0)
- print(initfailed);
- outb(Cmd, 0x60);
- if(outready() < 0)
- print(initfailed);
- outb(Data, ccc);
- if(outready() < 0)
- print(initfailed);
-
- setvec(V_KEYBOARD, kbdintr, 0);
-}
--- a/os/boot/puma/l.s
+++ /dev/null
@@ -1,427 +1,0 @@
-/*
- * File: l.s
- * Purpose:
- * Puma Board StrongARM 110 Architecture Specific Assembly
- *
- */
-
-#include "mem.h"
-#include "armv4.h"
-#include "puma.h"
-
-#define DRAMWAIT 100000 /* 3.125μsec per iteration */
-#define TL750R(r) (TL750_BASE+(r)*4)
-
-#define BOOTBASE 0x00200000
-
-TEXT _main(SB),1,$-4
- MOVW R15, R7 /* save PC on entry */
-
-/*
- * initialise DRAM controller on the TL750 (SDRAM mode)
- */
- MOVW $DRAMWAIT, R0 /* wait 312 ms after reset before touching DRAM */
-dram1:
- SUB.S $1, R0
- BNE dram1
-
- MOVW $TL750R(0x103), R0 /* DMC_DELAY */
- MOVW $0x03333333, R1 /* DRAM timing parameters */
- MOVW R1, (R0)
-
- MOVW $TL750R(0x101), R0 /* DMC_SDRAM */
- MOVW $0x03133011, R1 /* SDRAM parameters for Puma */
- MOVW R1, (R0)
-
- MOVW $DRAMWAIT, R0 /* wait 312 ms for initialisation */
-dram2:
- SUB.S $1, R0
- BNE dram2
-
- MOVW $setR12(SB),R12
-
-/*
- * copy bootstrap to final location in DRAM
- */
- MOVW R7, baddr(SB)
- MOVW $(BOOTBASE+8), R0
- CMP R0, R7
- BEQ inplace
- MOVW $((128*1024)/4), R6
-copyboot:
- MOVW.P 4(R7), R5
- MOVW.P R5, 4(R0)
- SUB.S $1, R6
- BNE copyboot
- MOVW $bootrel(SB), R7
- MOVW R7, R15
-
-TEXT bootrel(SB), $-4
-
-/*
- * set C environment and invoke main
- */
-inplace:
- MOVW $mach0(SB),R13
- MOVW R13,m(SB)
- ADD $(MACHSIZE-12),R13
-
- /* disable MMU activity */
- BL mmuctlregr(SB)
- BIC $(CpCmmu|CpCDcache|CpCwb|CpCIcache), R0
- BL mmuctlregw(SB)
-
- BL main(SB)
-loop:
- B loop
-
-TEXT idle(SB),$0
- RET
-
-/*
- * basic timing loop to determine CPU frequency
- */
-TEXT aamloop(SB), $-4 /* 3 */
-_aamloop:
- MOVW R0, R0 /* 1 */
- MOVW R0, R0 /* 1 */
- MOVW R0, R0 /* 1 */
- SUB $1, R0 /* 1 */
- CMP $0, R0 /* 1 */
- BNE _aamloop /* 3 */
- RET /* 3 */
-
-/*
- * Function: setr13( mode, pointer )
- * Purpose:
- * Sets the stack pointer for a particular mode
- */
-
-TEXT setr13(SB), $-4
- MOVW 4(FP), R1
-
- MOVW CPSR, R2
- BIC $PsrMask, R2, R3
- ORR R0, R3
- MOVW R3, CPSR
-
- MOVW R13, R0
- MOVW R1, R13
-
- MOVW R2, CPSR
-
- RET
-
-/*
- * Function: _vundcall
- * Purpose:
- * Undefined Instruction Trap Handler
- *
- */
-
-TEXT _vundcall(SB), $-4
-_vund:
- MOVM.DB [R0-R3], (R13)
- MOVW $PsrMund, R0
- B _vswitch
-
-/*
- * Function: _vsvccall
- * Purpose:
- * Reset or SWI Handler
- *
- */
-
-TEXT _vsvccall(SB), $-4
-_vsvc:
- SUB $12, R13
- MOVW R14, 8(R13)
- MOVW CPSR, R14
- MOVW R14, 4(R13)
- MOVW $PsrMsvc, R14
- MOVW R14, (R13)
- B _vsaveu
-
-/*
- * Function: _pabcall
- * Purpose:
- * Prefetch Abort Trap Handler
- *
- */
-
-TEXT _vpabcall(SB), $-4
-_vpab:
- MOVM.DB [R0-R3], (R13)
- MOVW $PsrMabt, R0
- B _vswitch
-
-/*
- * Function: _vdabcall
- * Purpose:
- * Data Abort Trap Handler
- *
- */
-
-TEXT _vdabcall(SB), $-4
-_vdab:
- MOVM.DB [R0-R3], (R13)
- MOVW $(PsrMabt+1), R0
- B _vswitch
-
-/*
- * Function: _virqcall
- * Purpose:
- * IRQ Trap Handler
- *
- */
-
-TEXT _virqcall(SB), $-4 /* IRQ */
-_virq:
- MOVM.DB [R0-R3], (R13)
- MOVW $PsrMirq, R0
- B _vswitch
-
-/*
- * Function: _vfiqcall
- * Purpose:
- * FIQ Trap Handler
- *
- */
-
-TEXT _vfiqcall(SB), $-4 /* FIQ */
-_vfiq:
- MOVM.DB [R0-R3], (R13)
- MOVW $PsrMfiq, R0
- /* FALLTHROUGH */
-
-_vswitch: /* switch to svc mode */
- MOVW SPSR, R1
- MOVW R14, R2
- MOVW R13, R3
-
- MOVW CPSR, R14
- BIC $PsrMask, R14
- ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
- MOVW R14, CPSR
-
- MOVM.DB.W [R0-R2], (R13)
- MOVM.DB (R3), [R0-R3]
-
-_vsaveu: /* Save Registers */
- SUB $4, R13 /* save link */
- MOVW R14, (R13) /* MOVW.W R14,4(R13)*/
-
- SUB $8, R13
-
- MOVW R13, R14 /* ur->sp */
- ADD $(6*4), R14
- MOVW R14, 0(R13)
-
- MOVW 8(SP), R14 /* ur->link */
- MOVW R14, 4(SP)
-
- MOVM.DB.W [R0-R12], (R13)
- MOVW R0, R0 /* gratuitous noop */
-
- MOVW $setR12(SB), R12 /* static base (SB) */
- MOVW R13, R0 /* argument is ureg */
- SUB $8, R13 /* space for arg+lnk*/
- BL trap(SB)
-
-
-_vrfe: /* Restore Regs */
- MOVW CPSR, R0 /* splhi on return */
- ORR $(PsrDirq|PsrDfiq), R0, R1
- MOVW R1, CPSR
- ADD $(8+4*15), R13 /* [r0-R14]+argument+link */
- MOVW (R13), R14 /* restore link */
- MOVW 8(R13), R0
- MOVW R0, SPSR
- MOVM.DB.S (R13), [R0-R14] /* restore user registers */
- MOVW R0, R0 /* gratuitous nop */
- ADD $12, R13 /* skip saved link+type+SPSR*/
- RFE /* MOVM.IA.S.W (R13), [R15] */
-
-
-/*
- * Function: splhi
- * Purpose:
- * Disable Interrupts
- * Returns:
- * Previous interrupt state
- */
-
-TEXT splhi(SB), $-4
- MOVW CPSR, R0
- ORR $(PsrDirq|PsrDfiq), R0, R1
- MOVW R1, CPSR
- RET
-
-/*
- * Function: spllo
- * Purpose:
- * Enable Interrupts
- * Returns:
- * Previous interrupt state
- */
-
-TEXT spllo(SB), $-4
- MOVW CPSR, R0
- BIC $(PsrDirq), R0, R1
- MOVW R1, CPSR
- RET
-
-/*
- * Function: splx(level)
- * Purpose:
- * Restore interrupt level
- */
-
-TEXT splx(SB), $-4
- MOVW R0, R1
- MOVW CPSR, R0
- MOVW R1, CPSR
- RET
-
-/*
- * Function: islo
- * Purpose:
- * Check if interrupts are enabled
- *
- */
-
-TEXT islo(SB), $-4
- MOVW CPSR, R0
- AND $(PsrDirq), R0
- EOR $(PsrDirq), R0
- RET
-
-/*
- * Function: cpsrr
- * Purpose:
- * Returns current program status register
- *
- */
-
-TEXT cpsrr(SB), $-4
- MOVW CPSR, R0
- RET
-
-/*
- * Function: spsrr
- * Purpose:
- * Returns saved program status register
- *
- */
-
-TEXT spsrr(SB), $-4
- MOVW SPSR, R0
- RET
-
-/*
- * MMU Operations
- */
-TEXT mmuctlregr(SB), $-4
- MRC CpMMU, 0, R0, C(CpControl), C(0)
- RET
-
-TEXT mmuctlregw(SB), $-4
- MCR CpMMU, 0, R0, C(CpControl), C(0)
- MOVW R0, R0
- MOVW R0, R0
- RET
-
-/*
- * Cache Routines
- */
-
-/*
- * Function: flushIcache
- * Purpose:
- * Flushes the *WHOLE* instruction cache
- */
-
-TEXT flushIcache(SB), $-4
- MCR CpMMU, 0, R0, C(CpCacheCtl), C(5), 0
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- RET
-
-
-
-/*
- * Function: flushDentry
- * Purpose:
- * Flushes an entry of the data cache
- */
-
-TEXT flushDentry(SB), $-4
- MCR CpMMU, 0, R0, C(CpCacheCtl), C(6), 1
- RET
-
-/*
- * Function: drainWBuffer
- * Purpose:
- * Drains the Write Buffer
- */
-
-TEXT drainWBuffer(SB), $-4
- MCR CpMMU, 0, R0, C(CpCacheCtl), C(10), 4
- RET
-
-/*
- * Function: writeBackDC
- * Purpose:
- * Drains the dcache prior to flush
- */
-
-TEXT writeBackDC(SB), $-4
- MOVW $0xE0000000, R0
- MOVW $8192, R1
- ADD R0, R1
-
-wbflush:
- MOVW (R0), R2
- ADD $32, R0
- CMP R1,R0
- BNE wbflush
- RET
-
-/*
- * Function: flushDcache(SB)
- * Purpose:
- * Flush the dcache
- */
-
-TEXT flushDcache(SB), $-4
- MCR CpMMU, 0, R0, C(CpCacheCtl), C(6), 0
- RET
-
-/*
- * Function: writeBackBDC(SB)
- * Purpose:
- * Write back the Baby D-Cache
- */
-
-TEXT writeBackBDC(SB), $-4
- MOVW $0xE4000000, R0
- MOVW $0x200, R1
- ADD R0, R1
-
-wbbflush:
- MOVW (R0), R2
- ADD $32, R0
- CMP R1,R0
- BNE wbbflush
- MCR CpMMU, 0, R0, C(CpCacheCtl), C(10), 4
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- MOVW R0,R0
- RET
-
-GLOBL mach0+0(SB), $MACHSIZE
-GLOBL m(SB), $4
-GLOBL baddr(SB), $4
--- a/os/boot/puma/lib.h
+++ /dev/null
@@ -1,107 +1,0 @@
-/*
- * functions (possibly) linked in, complete, from libc.
- */
-
-/*
- * mem routines
- */
-extern void* memccpy(void*, void*, int, long);
-extern void* memset(void*, int, long);
-extern int memcmp(void*, void*, long);
-extern void* memmove(void*, void*, long);
-extern void* memchr(void*, int, long);
-
-/*
- * string routines
- */
-extern char* strcat(char*, char*);
-extern char* strchr(char*, char);
-extern int strcmp(char*, char*);
-extern char* strcpy(char*, char*);
-extern char* strncat(char*, char*, long);
-extern char* strncpy(char*, char*, long);
-extern int strncmp(char*, char*, long);
-extern long strlen(char*);
-extern char* strrchr(char*, char);
-extern char* strstr(char*, char*);
-
-/*
- * print routines
- * Fconv isn't used but is defined to satisfy prototypes in libg.h
- * that are never called.
- */
-typedef struct Fconv Fconv;
-
-extern char* donprint(char*, char*, char*, void*);
-extern int sprint(char*, char*, ...);
-extern int print(char*, ...);
-
-#define PRINTSIZE 256
-
-/*
- * one-of-a-kind
- */
-extern int atoi(char*);
-extern long strtol(char*, char**, int);
-extern ulong strtoul(char*, char**, int);
-extern char end[];
-extern char edata[];
-
-/*
- * Syscall data structures
- */
-
-#define MORDER 0x0003 /* mask for bits defining order of mounting */
-#define MREPL 0x0000 /* mount replaces object */
-#define MBEFORE 0x0001 /* mount goes before others in union directory */
-#define MAFTER 0x0002 /* mount goes after others in union directory */
-#define MCREATE 0x0004 /* permit creation in mounted directory */
-#define MMASK 0x0007 /* all bits on */
-
-#define OREAD 0 /* open for read */
-#define OWRITE 1 /* write */
-#define ORDWR 2 /* read and write */
-#define OEXEC 3 /* execute, == read but check execute permission */
-#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
-#define OCEXEC 32 /* or'ed in, close on exec */
-#define ORCLOSE 64 /* or'ed in, remove on close */
-
-#define NCONT 0 /* continue after note */
-#define NDFLT 1 /* terminate after note */
-
-typedef struct Qid Qid;
-typedef struct Dir Dir;
-typedef struct Waitmsg Waitmsg;
-
-#define ERRLEN 64
-#define DIRLEN 116
-#define NAMELEN 28
-
-struct Qid
-{
- ulong path;
- ulong vers;
-};
-
-struct Dir
-{
- char name[NAMELEN];
- char uid[NAMELEN];
- char gid[NAMELEN];
- Qid qid;
- ulong mode;
- long atime;
- long mtime;
- ulong length;
- short type;
- short dev;
-};
-
-struct Waitmsg
-{
- int pid; /* of loved one */
- int status; /* unused; a placeholder */
- ulong time[3]; /* of loved one */
- char msg[ERRLEN];
-};
-#define nelem(x) (sizeof(x)/sizeof((x)[0]))
--- a/os/boot/puma/main.c
+++ /dev/null
@@ -1,552 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "dosfs.h"
-
-typedef struct Type Type;
-typedef struct Medium Medium;
-typedef struct Mode Mode;
-
-enum {
- Dany = -1,
- Nmedia = 16,
-
- /* DS1 switch options */
- Sflashfs = 1<<0, /* take local fs from flash */
- Snotflash = 1<<1, /* don't boot from flash */
-};
-
-enum { /* type */
- Tflash,
- Tether,
- Thard,
-
- Tany = -1,
-};
-
-enum { /* flag and name */
- Fnone = 0x00,
-
- Fdos = 0x01,
- Ndos = 0x00,
- Fboot = 0x02,
- Nboot = 0x01,
- Fbootp = 0x04,
- Nbootp = 0x02,
- Fflash = 0x08,
- NName = 0x03,
-
- Fany = Fbootp|Fboot|Fdos|Fflash,
-
- Fini = 0x10,
- Fprobe = 0x80,
-};
-
-enum { /* mode */
- Mauto = 0x00,
- Mlocal = 0x01,
- Manual = 0x02,
- NMode = 0x03,
-};
-
-typedef struct Type {
- int type;
- char *cname;
- int flag;
- int (*init)(void);
- long (*read)(int, void*, long);
- long (*seek)(int, long);
- Partition* (*setpart)(int, char*);
- char* name[NName];
-
- int mask;
- Medium* media;
-} Type;
-
-typedef struct Medium {
- Type* type;
- int flag;
- Partition* partition;
- Dos;
-
- Medium* next;
-} Medium;
-
-typedef struct Mode {
- char* name;
- int mode;
-} Mode;
-
-static Type types[] = {
- { Tflash, "flash",
- Fflash,
- flashinit, 0, 0, 0,
- { 0, "F", 0, }
- },
- { Tether, "ether",
- Fbootp,
- etherinit, 0, 0, 0,
- { 0, 0, "e", },
- },
- { Thard, "ata",
- Fini|Fboot|Fdos,
- 0, 0, 0, 0, /* not used now, will be later with PCMCIA */
- { "hd", "h", 0, },
- },
- {-1},
-};
-
-static Medium media[Nmedia];
-static Medium *curmedium = media;
-
-static Mode modes[NMode+1] = {
- [Mauto] { "auto", Mauto, },
- [Mlocal] { "local", Mlocal, },
- [Manual] { "manual", Manual, },
-};
-
-static char *inis[] = {
- "inferno/inferno.ini",
- "inferno.ini",
- "plan9/plan9.ini",
- "plan9.ini",
- 0,
-};
-char **ini;
-void printversion(void);
-
-static int
-parse(char *line, int *type, int *flag, int *dev, char *file)
-{
- Type *tp;
- char buf[2*NAMELEN], *v[4], *p;
- int i;
-
- strcpy(buf, line);
- switch(getcfields(buf, v, 4, "!")){
-
- case 3:
- break;
-
- case 2:
- v[2] = "";
- break;
-
- default:
- return 0;
- }
-
- *flag = 0;
- for(tp = types; tp->cname; tp++){
- for(i = 0; i < NName; i++){
-
- if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
- continue;
- *type = tp->type;
- *flag |= 1<<i;
-
- if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
- return 0;
-
- strcpy(file, v[2]);
-
- return 1;
- }
- }
-
- return 0;
-
-}
-
-static int
-boot(Medium *mp, int flag, char *file)
-{
- Dosfile df;
- char ixdos[128], *p;
-
- if(flag & Fbootp){
- sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
- return bootp(mp->dev, file);
- }
-
- if(flag & Fflash){
- if(mp->flag & Fflash && flashbootable(0))
- flashboot(mp->dev);
- }
-
- if(flag & Fboot){
-
- if(mp->flag & Fini){
- (*mp->type->setpart)(mp->dev, "disk");
- plan9ini(mp, nil);
- }
- if(file == 0 || *file == 0)
- file = mp->partition->name;
- (*mp->type->setpart)(mp->dev, file);
- sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
- return plan9boot(mp->dev, mp->seek, mp->read);
- }
-
- if(flag & Fdos){
- if(mp->type->setpart)
- (*mp->type->setpart)(mp->dev, "disk");
- if(mp->flag & Fini)
- plan9ini(mp, nil);
- if(file == 0 || *file == 0){
- strcpy(ixdos, *ini);
- if(p = strrchr(ixdos, '/'))
- p++;
- else
- p = ixdos;
- strcpy(p, "infernopuma");
- if(dosstat(mp, ixdos, &df) <= 0)
- return -1;
- }
- else
- strcpy(ixdos, file);
- sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
- return dosboot(mp, ixdos);
- }
-
- return -1;
-}
-
-static Medium*
-allocm(Type *tp)
-{
- Medium **l;
-
- if(curmedium >= &media[Nmedia])
- return 0;
-
- for(l = &tp->media; *l; l = &(*l)->next)
- ;
- *l = curmedium++;
- return *l;
-}
-
-Medium*
-probe(int type, int flag, int dev)
-{
- Type *tp;
- int dombr, i, start;
- Medium *mp;
- Dosfile df;
- Partition *pp;
-
- for(tp = types; tp->cname; tp++){
- if(type != Tany && type != tp->type || tp->init == 0)
- continue;
-
- if(flag != Fnone){
- for(mp = tp->media; mp; mp = mp->next){
- if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
- return mp;
- }
- }
- if((tp->flag & Fprobe) == 0){
- tp->flag |= Fprobe;
- tp->mask = (*tp->init)();
- }
-
- for(i = 0; tp->mask; i++){
- if((tp->mask & (1<<i)) == 0)
- continue;
- tp->mask &= ~(1<<i);
-
- if((mp = allocm(tp)) == 0)
- continue;
-
- mp->dev = i;
- mp->flag = tp->flag;
- mp->seek = tp->seek;
- mp->read = tp->read;
- mp->type = tp;
-
- if(mp->flag & Fboot){
- if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
- mp->flag &= ~Fboot;
- if((mp->flag & Fflash) == 0)
- (*tp->setpart)(i, "disk");
- }
-
- if(mp->flag & Fdos){
- start = 0;
- dombr = 1;
- if(mp->type->setpart){
- if(pp = (*mp->type->setpart)(i, "dos")){
- if(start = pp->start)
- dombr = 0;
- }
- (*tp->setpart)(i, "disk");
- }
- if(dosinit(mp, start, dombr) < 0)
- mp->flag &= ~(Fini|Fdos);
- else
- print("dos init failed\n");
- }
-
- if(mp->flag & Fini){
- mp->flag &= ~Fini;
- for(ini = inis; *ini; ini++){
- if(dosstat(mp, *ini, &df) <= 0)
- continue;
- mp->flag |= Fini;
- break;
- }
- }
-
- if((flag & mp->flag) && (dev == Dany || dev == i))
- return mp;
- }
- }
-
- return 0;
-}
-
-static void
-pause(void)
-{
- long d;
- for(d=0; d<10000000; d++)
- ;
- USED(d);
-}
-
-static void
-flash(int n)
-{
- int i;
-
- if(n <= 0)
- return;
- for(i=0; i<n-1; i++) {
- led(1);
- pause();
- led(0);
- pause();
- }
- led(1);
- pause();pause();pause();
- led(0);
- pause();pause();pause();
-}
-
-void
-main(void)
-{
- Medium *mp;
- int dev, flag, i, mode, tried, type, options;
- char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
- Type *tp;
-
- memset(edata, 0, end-edata ); /* clear the BSS */
- pumainit();
-
- machinit();
- meminit();
- trapinit();
- consinit(); /* screen and keyboard initially */
-// screeninit();
- alarminit();
- clockinit();
- printversion();
-
- spllo();
- options = optionsw();
-
-
- mp = 0;
- for(tp = types; tp->cname; tp++){
- if(tp->type == Tether)
- continue;
- if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
- plan9ini(mp, nil);
- break;
- }
- }
-
- if(mp == 0 || (mp->flag & Fini) == 0)
- plan9ini(nil, flashconfig(0));
-
- //consinit(); /* establish new console location */
-
- if((options & Snotflash) == 0 && flashbootable(0)){
- print("Flash boot\n");
- flashboot(0);
- }
-
- tried = 0;
- mode = Mauto;
- p = getconf("bootfile");
- flag = 0;
-
- if(p != 0) {
- mode = Manual;
- for(i = 0; i < NMode; i++){
- if(strcmp(p, modes[i].name) == 0){
- mode = modes[i].mode;
- goto done;
- }
- }
- if(parse(p, &type, &flag, &dev, file) == 0) {
- print("Bad bootfile syntax: %s\n", p);
- goto done;
- }
- mp = probe(type, flag, dev);
- if(mp == 0) {
- print("Cannot access device: %s\n", p);
- goto done;
- }
- tried = boot(mp, flag, file);
- }
-done:
- if(tried == 0 && mode != Manual){
- flag = Fany;
- if(mode == Mlocal)
- flag &= ~Fbootp;
- if(options & Snotflash)
- flag &= ~Fflash;
- if((mp = probe(Tany, flag, Dany)) != 0)
- boot(mp, flag & mp->flag, 0);
- }
-
- def[0] = 0;
- probe(Tany, Fnone, Dany);
-
- flag = 0;
- for(tp = types; tp->cname; tp++){
- for(mp = tp->media; mp; mp = mp->next){
- if(flag == 0){
- flag = 1;
- print("Boot devices:");
- }
-
- if(mp->flag & Fbootp)
- print(" %s!%d", mp->type->name[Nbootp], mp->dev);
- if(mp->flag & Fdos)
- print(" %s!%d", mp->type->name[Ndos], mp->dev);
- if(mp->flag & Fflash || mp->flag & Fboot)
- print(" %s!%d", mp->type->name[Nboot], mp->dev);
- }
- }
- if(flag)
- print("\n");
-
- for(;;){
- if(getstr("boot from", line, sizeof(line), def) >= 0){
- if(parse(line, &type, &flag, &dev, file)){
- if(mp = probe(type, flag, dev))
- boot(mp, flag, file);
- }
- }
- def[0] = 0;
- }
-}
-
-void
-machinit(void)
-{
- memset(m, 0, sizeof(*m));
- m->delayloop = 20000;
-}
-
-void
-printversion(void)
-{
- print("StrongARM SA-110 ");
- print("%d MHz system\n", m->speed);
- print("\n");
-{extern long baddr; print("%8.8lux\n", baddr);}
-}
-
-int
-optionsw()
-{
- return 0;
-}
-
-int
-getcfields(char* lp, char** fields, int n, char* sep)
-{
- int i;
-
- for(i = 0; lp && *lp && i < n; i++){
- while(*lp && strchr(sep, *lp) != 0)
- *lp++ = 0;
- if(*lp == 0)
- break;
- fields[i] = lp;
- while(*lp && strchr(sep, *lp) == 0){
- if(*lp == '\\' && *(lp+1) == '\n')
- *lp++ = ' ';
- lp++;
- }
- }
-
- return i;
-}
-
-static Map memv[512];
-static RMap rammap = {"physical memory"};
-
-void
-meminit(void)
-{
- ulong e;
-
- mapinit(&rammap, memv, sizeof(memv));
- e = PADDR(end);
- mapfree(&rammap, e, 4*1024*1024-e);
-}
-
-void*
-ialloc(ulong n, int align)
-{
- ulong a;
- int s;
-
- if(align <= 0)
- align = 4;
- s = splhi();
- a = mapalloc(&rammap, 0, n, align);
- splx(s);
- if(a == 0)
- panic("ialloc");
- return memset(KADDR(a), 0, n);
-}
-
-void*
-malloc(ulong n)
-{
- ulong *p;
-
- n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
- p = ialloc(n, sizeof(int));
- *p++ = 0xcafebeef;
- *p++ = n;
- return p;
-}
-
-void
-free(ulong *p)
-{
- int s;
-
- if(p){
- if(*(p -= 2) != 0xcafebeef)
- panic("free");
- s = splhi();
- mapfree(&rammap, (ulong)p, p[1]);
- splx(s);
- }
-}
-
-void
-sched(void)
-{
-}
--- a/os/boot/puma/mem.h
+++ /dev/null
@@ -1,38 +1,0 @@
-/*
- * Memory and machine-specific definitions. Used in C and assembler.
- */
-
-/*
- * Sizes
- */
-#define BI2BY 8 /* bits per byte */
-#define BI2WD 32 /* bits per word */
-#define BY2WD 4 /* bytes per word */
-#define BY2PG 4096 /* bytes per page */
-#define WD2PG (BY2PG/BY2WD) /* words per page */
-#define PGSHIFT 12 /* log(BY2PG) */
-#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
-
-#define MAXMACH 1 /* max # cpus system can run */
-
-/*
- * Time
- */
-#define HZ (20) /* clock frequency */
-#define MS2HZ (1000/HZ) /* millisec per clock tick */
-#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
-#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
-#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
-
-/*
- * Fundamental addresses
- */
-
-/*
- * Address spaces
- *
- * Kernel is at 0x00008000
- */
-#define KZERO 0x00000000 /* base of kernel address space */
-#define KTZERO KZERO /* first address in kernel text */
-#define MACHSIZE 4096
--- a/os/boot/puma/mkfile
+++ /dev/null
@@ -1,71 +1,0 @@
-<../../../mkconfig
-
-SYSTARG=Inferno
-OBJTYPE=arm
-<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE #set vars based on target system
-
-TARGET=${O}boot
-OBJ=\
- l.$O\
- div.$O\
- 8250.$O\
- alarm.$O\
- bootp.$O\
- clock.$O\
- console.$O\
- conf.$O\
- dosboot.$O\
- donprint.$O\
- ether.$O\
- ether8900.$O\
- flash.$O\
- kbd.$O\
- main.$O\
- plan9boot.$O\
- puma.$O\
- qio.$O\
- rmap.$O\
- trap.$O\
- zqs.$O
-
-HFILES=\
- lib.h\
- mem.h\
- dat.h\
- fns.h\
- io.h\
- boot.h\
- armv4.h\
- puma.h\
-
-CFLAGS=-w -I.
-LFLAGS=-H1 -R4 -T0x00200000 -E_main #-a
-#LFLAGS=-H1 -R4 -T0x00008080 -E_main #-a
-#LFLAGS = -H1 -R4 -T0xa00000c0 -E_main #-a
-
-all:V: $TARGET
-
-$TARGET: $OBJ
- $LD -o $target $LFLAGS -l $prereq -lc
- ls -l $target
-
-installall:V: install
-install:V: bb $TARGET
- cp $TARGET /arm
-
-%.$O: %.s
- $AS $stem.s
-
-%.$O: %.c
- $CC $CFLAGS $stem.c
-
-%.$O: $HFILES
-
-clock.$O floppy.$O trap.$O: ureg.h
-conf.$O dosboot.$O main.$O: dosfs.h
-ether.$O ether2000.$O ether509.$O ether8003.$O ether8390.$O: ether.h
-bootp.$O: ip.h
-
-clean:
- rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARGET
-
--- a/os/boot/puma/outb.c
+++ /dev/null
@@ -1,20 +1,0 @@
-typedef unsigned short ushort;
-typedef unsigned char uchar;
-
-enum {
- IsaIOBase = 0xf0000000,
- IsaMemBase = 0xe0000000,
-
- IOBase = 0x300,
- MemBase = 0xc0000,
-
- TxFrame = 0x0a00,
-};
-
-#define regw(reg, val) *((ushort *)IsaMemBase + MemBase + (reg)) = (val)
-
-void
-main(void)
-{
- regw(TxFrame, 0x1234);
-}
--- a/os/boot/puma/plan9boot.c
+++ /dev/null
@@ -1,93 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-char *premature = "premature EOF\n";
-
-/*
- * read in a segment
- */
-static long
-readseg(int dev, long (*read)(int, void*, long), long len, long addr)
-{
- char *a;
- long n, sofar;
-
- a = (char *)addr;
- for(sofar = 0; sofar < len; sofar += n){
- n = 8*1024;
- if(len - sofar < n)
- n = len - sofar;
- n = (*read)(dev, a + sofar, n);
- if(n <= 0)
- break;
- print(".");
- }
- return sofar;
-}
-
-/*
- * boot
- */
-int
-plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
-{
- long n;
- long addr;
- void (*b)(void);
- Exec *ep;
-
- if((*seek)(dev, 0) < 0)
- return -1;
-
- /*
- * read header
- */
- ep = (Exec *) ialloc(sizeof(Exec), 0);
- n = sizeof(Exec);
- if(readseg(dev, read, n, (ulong) ep) != n){
- print(premature);
- return -1;
- }
- if(GLLONG(ep->magic) != E_MAGIC){
- print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
- return -1;
- }
-
- /*
- * read text
- */
- addr = PADDR(GLLONG(ep->entry));
- n = GLLONG(ep->text);
- print("%d", n);
- if(readseg(dev, read, n, addr) != n){
- print(premature);
- return -1;
- }
-
- /*
- * read data (starts at first page after kernel)
- */
- addr = PGROUND(addr+n);
- n = GLLONG(ep->data);
- print("+%d", n);
- if(readseg(dev, read, n, addr) != n){
- print(premature);
- return -1;
- }
-
- /*
- * bss and entry point
- */
- print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry)); uartwait();
-
- /*
- * Go to new code. It's up to the program to get its PC relocated to
- * the right place.
- */
- b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
- (*b)();
- return 0;
-}
--- a/os/boot/puma/puma.c
+++ /dev/null
@@ -1,123 +1,0 @@
-#include "boot.h"
-
-//#define GPIO1_PORT 0x0078
-//#define GPIO2_PORT 0x0079
-
-#define GPIO2_N_LED1_DIAG 0x10 /* diagnostic led mask */
-
-#define HARI2_N_LED1 0x01
-#define HARI2_N_LED2 0x02
-#define HARI2_N_LED3 0x04
-#define HARI2_N_LED4 0x08
-
-/*
- * National Semiconductor PC87306 Super I/O
- */
-enum {
- Index= 0x398, /* sio configuration index register */
- Data= 0x399, /* sio configuration data register */
-};
-
-
-// byte flip table for Puma SuperIO port permuted as 76543210 -> 01234567
-unsigned char
-byteflip[] = {
- 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
- 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
- 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
- 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
- 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
- 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
- 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
- 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
- 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
- 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
- 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
- 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
- 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
- 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
- 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
- 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
-};
-
-int
-sio_inb(int port)
-{
- unsigned char b = *(uchar *)IOBADDR(port);
-// b = byteflip[b];
- return b&0xff;
-}
-
-void
-sio_outb(int port, int data)
-{
-// data = byteflip[data];
- *(uchar *)IOBADDR(port) = data;
-}
-
-static void
-siocfg(int r, int v, int rsv)
-{
- sio_outb(Index, r);
- if(rsv)
- v = (sio_inb(Data)&rsv) | (v&~rsv);
- sio_outb(Data, v);
- sio_outb(Data, v); /* ``write data twice'' */
-}
-
-void
-sioinit(void)
-{
- /* determine which byte flip is required ... */
-
- siocfg(SIO_CONFIG_FAR, FAR_LPT_LPTA | FAR_UART1_COM1 | FAR_UART2_COM2, 0);
- siocfg(SIO_CONFIG_FER, FER_LPT_ENABLE | FER_UART1_ENABLE | FER_UART2_ENABLE | FER_IDE_ENABLE, 0);
- siocfg(SIO_CONFIG_KRR, KRR_KBC_ENABLE | KRR_KBC_MUST_BE_1 | KRR_RTC_ENABLE, 0x50);
- siocfg(SIO_CONFIG_SCF0,SCF0_GPIO_PORT1_ENABLE | SCF0_GPIO_PORT2_ENABLE, 0xC0);
-
- /* force UART interrupt pins low, not tristate by setting ienable in MCR (!) */
- sio_outb(COM1_PORT+UART_MCR, sio_inb(COM1_PORT+UART_MCR)|(1<<3));
- sio_outb(COM2_PORT+UART_MCR, sio_inb(COM2_PORT+UART_MCR)|(1<<3));
-}
-
-void
-led(int on)
-{
- int gpio, hari, hbits;
- int s;
-
- s = splhi();
-
- gpio = sio_inb(GPIO2_PORT);
- if (on)
- gpio &= ~GPIO2_N_LED1_DIAG;
- else
- gpio |= GPIO2_N_LED1_DIAG;
- sio_outb(GPIO2_PORT, gpio);
-
- hari = HARI2_INIT;
- hbits = HARI2_N_LED1|HARI2_N_LED2|HARI2_N_LED3|HARI2_N_LED4;
- if (on)
- hari &= ~hbits;
- else
- hari |= hbits;
- *(uchar *)HARI2 = hari;
-
-
- splx(s);
-
-}
-
-void
-pumainit(void)
-{
- /*
- * Initialise HARI2 for:
- * a) Leds off
- * b) No Timer2 aborts
- * c) Ethernet on IRQ
- */
- *(uchar *)HARI2 = HARI2_INIT|HARI2_N_LED1|HARI2_N_LED2|HARI2_N_LED3|HARI2_N_LED4;
- sioinit();
-}
-
--- a/os/boot/puma/puma.h
+++ /dev/null
@@ -1,435 +1,0 @@
-/*
- * Teralogic TL750 - Puma Evaluation Board
- */
-
-/*
- * Puma addresses
- */
-#define EPROM_BASE 0x80000000 /* EPROM */
-#define FLASH_BASE 0xa0000000 /* Flash */
-#define TL750_BASE 0xc0000000 /* TL750 registers */
-#define ISAMEM_BASE 0xe0000000 /* ISA memory space */
-#define ISAIO_BASE 0xf0000000 /* ISA I/O space */
-
-#define ISAIO_SHIFT 2
-#define IOBADDR(io_port) (ISAIO_BASE + (io_port << ISAIO_SHIFT))
-
-/* Hardware address register for interrupts (HARI) */
-#define HARI1 0xE2000000 /* Interrupt status on read, User interrupt on write */
-#define HARI2 0xE3000000 /* More interrupt status on read, LEDs on write */
-#define HARI1_FIQ_MASK 0x92 /* FIQ indicator bits in HARI1, others are IRQ */
-#define HARI2_INIT 0x20 /* No timer2 aborts, Ethernet on IRQ */
-
-
-
-/*
- * Interrupt Vectors
- * corresponding to the HARIx_xxx_IRQ/FIQ bits above.
- *
- * HARI1 interrupts
- */
-#define V_LPT 0 /* Parallel port interrupt */
-#define V_NM0 1 /* MPEG Decode Interrupt */
-#define V_NM1 2 /* MPEG Decode Interrupt */
-#define V_COM2 3 /* Serial Port 2 Interrupt */
-#define V_COM1 4 /* Serial Port 1 Interrupt */
-#define V_MOUSE 5 /* Mouse Interrupt */
-#define V_KEYBOARD 6 /* Keyboard Interrupt */
-#define V_ETHERNET 7 /* Ethernet Interrupt */
-/*
- * HARI2 interrupts
- */
-#define V_TIMER0 8 /* 82C54 Timer 0 Interrupt */
-#define V_TIMER1 9 /* 82C54 Timer 1 Interrupt */
-#define V_TIMER2 10 /* 82C54 Timer 2 Interrupt */
-#define V_SOFTWARE 11 /* Software Interrupt */
-#define V_IDE 12 /* IDE Hard Drive Interrupt */
-#define V_SMARTCARD 13 /* Smart Card Interrupt */
-#define V_TL750 14 /* TL750 Interrupt */
- /* Nothing in vector 15 for now */
-#define V_MAXNUM 15
-
-/*
- * Definitions for National Semiconductor PC87306 SuperIO configuration
- */
-#define SIO_CONFIG_INDEX 0x398 /* SuperIO configuration index register */
-#define SIO_CONFIG_DATA 0x399 /* SuperIO configuration data register */
-
-#define SIO_CONFIG_RESET_VAL 0x88 /* Value read from first read of sio_config_index reg after reset */
-/*
- * PC87306 Configuration Registers (The value listed is the configuration space
- * index.)
- */
-#define SIO_CONFIG_FER 0x00 /* Function Enable Register */
-
-#define FER_LPT_ENABLE 0x01 /* Enable Parallel Port */
-#define FER_UART1_ENABLE 0x02 /* Enable Serial Port 1 */
-#define FER_UART2_ENABLE 0x04 /* Enable Serial Port 2 */
-#define FER_FDC_ENABLE 0x08 /* Enable Floppy Controller */
-#define FER_FDC_4DRIVE_ENCODING 0x10 /* Select Floppy 4 Drive Encoding */
-#define FER_FDC_ADDR_ENABLE 0x20 /* Select Floppy Secondary Address */
- /* 0: [0x3F0..0x3F7] */
- /* 1: [0x370..0x377] */
-#define FER_IDE_ENABLE 0x40 /* Enable IDE Controller */
-#define FER_IDE_ADDR_SELECT 0x80 /* Select IDE Secondary Address */
- /* 0: [0x1F0..0x1F7,0x3F6,0x3F7] */
- /* 1: [0x170..0x177,0x376,0x377] */
-
-#define SIO_CONFIG_FAR 0x01 /* Function Address Register */
-
-#define FAR_LPT_ADDR_MASK 0x03 /* Select LPT Address */
- /* If (PNP0[4] == 0) then: */
- /* 0: LPTB [0x378..0x37F] IRQ5/7 */
- /* 1: LPTA [0x3BC..0x3BE] IRQ7 */
- /* 2: LPTC [0x278..0x27F] IRQ5 */
- /* 3: Reserved */
- /* Else ignored. */
-#define FAR_LPT_LPTB 0 /* 0: LPTB 0x378 irq5/7 */
-#define FAR_LPT_LPTA 1 /* 1: LPTA 0x3BC irq 7 */
-#define FAR_LPT_LPTC 2 /* 2: LPTC 0x278 irq5 */
-
-#define FAR_UART1_ADDR_MASK 0x0C /* Select Serial Port 1 Address */
- /* 0: COM1 [0x3F8..0x3FF] */
- /* 1: COM2 [0x2F8..0x2FF] */
- /* 2: COM3 (See FAR[7:6]) */
- /* 3: COM4 (See FAR[7:6]) */
-#define FAR_UART1_COM1 0x00
-#define FAR_UART2_ADDR_MASK 0x30 /* Select Serial Port 2 Address */
- /* 0: COM1 [0x3F8..0x3FF] */
- /* 1: COM2 [0x2F8..0x2FF] */
- /* 2: COM3 (See FAR[7:6]) */
- /* 3: COM4 (See FAR[7:6]) */
-#define FAR_UART2_COM2 0x10
-#define FAR_EXTENDED_UART_ADDR_SELECT 0xC0 /* Extended Address Selects */
- /* COM3@IRQ4, COM4@IRQ3 */
- /* 0: COM3@0x3E8, COM4@0x2E8 */
- /* 1: COM3@0x338, COM4@0x238 */
- /* 2: COM3@0x2E8, COM4@0x2E0 */
- /* 3: COM3@0x220, COM4@0x228 */
-
-#define SIO_CONFIG_PTR 0x02 /* Power & Test Register */
-
-#define PTR_POWER_DOWN 0x01 /* Power down all enabled functions */
-#define PTR_LPT_IRQ_SELECT 0x08 /* Select LPT IRQ if (FAR[1:0] == 0) */
- /* 0: IRQ5 */
- /* 1: IRQ7 */
-#define PTR_UART1_TEST_MODE 0x10 /* Set serial port 1 test mode */
-#define PTR_UART2_TEST_MODE 0x20 /* Set serial port 2 test mode */
-#define PTR_LOCK_CONFIGURATION 0x40 /* Prevent all further config writes */
- /* Only a RESET will reenable writes */
-#define PTR_LPT_EXTENDED_MODE_SELECT 0x80 /* Select Mode if not EPP/ECP */
- /* 0: Compatible Mode */
- /* 1: Extended Mode */
-
-#define SIO_CONFIG_FCR 0x03 /* Function Control Register */
- /* WARNING: The FCR register must be written */
- /* using read-modify-write! */
-#define FCR_TDR_MODE_SELECT 0x01 /* ? (floppy/tape) */
-#define FCR_IDE_DMA_ENABLE 0x02 /* Enable IDE DMA mode */
-#define FCR_EPP_ZERO_WAIT_STATE 0x40 /* Enable EPP zero wait state */
-
-#define SIO_CONFIG_PCR 0x04 /* Printer Control Register */
-
-#define PCR_EPP_ENABLE 0x01 /* Enable parallel port EPP mode */
-#define PCR_EPP_VERSION_SELECT 0x02 /* Select version of EPP mode */
- /* 0: Version 1.7 */
- /* 1: Version 1.9 (IEEE 1284) */
-#define PCR_ECP_ENABLE 0x04 /* Enable parallel port ECP mode */
-#define PCR_ECP_POWER_DOWN_CLOCK_ENABLE 0x08 /* Enable clock in power-down state */
- /* 0: Freeze ECP clock */
- /* 1: Run ECP clock */
-#define PCR_ECP_INT_POLARITY_CONTROL 0x20 /* Interrupt polarity control */
- /* 0: Level high or negative pulse */
- /* 1: Level low or positive pulse */
-#define PCR_ECP_INT_IO_CONTROL 0x40 /* Interrupt I/O control */
- /* WARNING: Slightly safer to choose */
- /* open drain if you don't know the */
- /* exact requirements of the circuit */
- /* 0: Totem-pole output */
- /* 1: Open drain output */
-#define PCR_RTC_RAM_WRITE_DISABLE 0x80 /* Disable writes to RTC RAM */
- /* 0: Enable writes */
- /* 1: Disable writes */
-
-#define SIO_CONFIG_KRR 0x05 /* Keyboard & RTC Control Register */
- /* WARNING: The KRR register must be written */
- /* with a 1 in bit 2, else the KBC will not */
- /* work! */
-#define KRR_KBC_ENABLE 0x01 /* Enable keyboard controller */
-#define KRR_KBC_SPEED_CONTROL 0x02 /* Select clock divisor if !KRR[7] */
- /* 0: Divide by 3 */
- /* 1: Divide by 2 */
-#define KRR_KBC_MUST_BE_1 0x04 /* Reserved: This bit must be 1! */
-#define KRR_RTC_ENABLE 0x08 /* Enable real time clock */
-#define KRR_RTC_RAMSEL 0x20 /* Select RTC RAM bank */
-#define KRR_KBC_CLOCK_SOURCE_SELECT 0x80 /* Select clock source */
- /* 0: Use X1 clock source */
- /* 1: Use SYSCLK clock source */
-
-#define SIO_CONFIG_PMC 0x06 /* Power Management Control Register */
-
-#define PMC_IDE_TRISTATE_CONTROL 0x01 /* ? (power management) */
-#define PMC_FDC_TRISTATE_CONTROL 0x02 /* ? (power management) */
-#define PMC_UART1_TRISTATE_CONTROL 0x04 /* ? (power management) */
-#define PMC_SELECTIVE_LOCK 0x20 /* ? (power management) */
-#define PMC_LPT_TRISTATE_CONTROL 0x40 /* ? (power management) */
-
-#define SIO_CONFIG_TUP 0x07 /* Tape, UARTS & Parallel Port Register */
-
-#define TUP_EPP_TIMEOUT_INT_ENABLE 0x04 /* Enable EPP timeout interrupts */
-
-#define SIO_CONFIG_SID 0x08 /* Super I/O Identification Register */
-
-#define SID_ID_MASK 0xF8 /* Super I/O ID field */
-#define SID_ID_PC87306 0x70 /* PC87306 ID value */
-
-#define SIO_CONFIG_ASC 0x09 /* Advanced Super I/O Config Register */
- /* WARNING: The ASC register must be written */
- /* with a 0 in bit 3! */
- /* WARNING: The ASC register resets to 1 in */
- /* bit 7 (PC/AT mode)! */
-#define ASC_VLD_MASK 0x03 /* ? (floppy/tape) */
-#define ASC_ENHANCED_TDR_SUPPORT 0x04 /* ? (floppy/tape) */
-#define ASC_MUST_BE_0 0x08 /* Reserved: Must be 0 */
-#define ASC_ECP_CNFGA 0x20 /* ? */
-#define ASC_DENSEL_POLARITY_BIT 0x40 /* ? (floppy/tape) */
-#define ASC_SYSTEM_OPERATION_MODE 0x80 /* Select system operation mode */
- /* 0: PS/2 mode */
- /* 1: PC/AT mode */
-
-#define SIO_CONFIG_CS0LA 0x0A /* Chip Select 0 Low Address Register */
-
-#define SIO_CONFIG_CS0CF 0x0B /* Chip Select 0 Configuration Register */
- /* WARNING: The CS0CF register must be */
- /* written with a 1 in bit 7! */
-#define CS0CF_CS0_DECODE 0x08 /* Select CS0 decode sensitivity */
- /* 0: Decode full 16-bit address */
- /* 1: Decode only bits 15 thru 12 */
-#define CS0CF_CS0_WRITE_ENABLE 0x10 /* Enable CS0 on write cycles */
-#define CS0CF_CS0_READ_ENABLE 0x20 /* Enable CS0 on read cycles */
-#define CS0CF_CS0_MUST_BE_1 0x80 /* Reserved: Must be 1 */
-
-#define SIO_CONFIG_CS1LA 0x0C /* Chip Select 1 Low Address Register */
-
-#define SIO_CONFIG_CS1CF 0x0D /* Chip Select 1 Configuration Register */
-
-#define CS1CF_CS1_DECODE 0x08 /* Select CS1 decode sensitivity */
- /* 0: Decode full 16-bit address */
- /* 1: Decode only bits 15 thru 12 */
-#define CS1CF_CS1_WRITE_ENABLE 0x10 /* Enable CS1 on write cycles */
-#define CS1CF_CS1_READ_ENABLE 0x20 /* Enable CS1 on read cycles */
-
-#define SIO_CONFIG_IRC 0x0E /* Infrared Configuration Register */
-
-#define IRC_UART2_INTERFACE_MODE 0x01 /* Select UART2 interface mode */
- /* 0: Normal (modem) mode */
- /* 1: IR mode */
-#define IRC_IR_FULL_DUPLEX 0x02 /* Select IR duplex mode */
- /* 0: Full duplex mode */
- /* 1: Half duplex mode */
-#define IRC_ENCODED_IR_TRANSMITTER_DRIVE 0x10 /* IR transmitter drive control */
- /* 0: IRTX active for 1.6usec */
- /* 1: IRTX active for 3/16 baud */
-#define IRC_ENCODED_IR_MODE 0x20 /* IR encode mode */
- /* 0: Encoded mode */
- /* 1: Non-encoded mode */
-
-#define SIO_CONFIG_GPBA 0x0F /* GP I/O Port Base Address Config Register */
-
-#define SIO_CONFIG_CS0HA 0x10 /* Chip Select 0 High Address Register */
-
-#define SIO_CONFIG_CS1HA 0x11 /* Chip Select 1 High Address Register */
-
-#define SIO_CONFIG_SCF0 0x12 /* Super I/O Configuration Register 0 */
-
-#define SCF0_RTC_RAM_LOCK 0x01 /* Lock (1) will prevent all further */
- /* accesses to RTC RAM. Only RESET */
- /* return this bit to a 0. */
-#define SCF0_IRQ1_12_LATCH_ENABLE 0x02 /* Enable IRQ1/IRQ12 latching */
-#define SCF0_IRQ12_TRISTATE 0x04 /* IRQ12 tri-state control */
- /* 0: Use quasi-bidirectional buffer */
- /* 1: Tri-state IRQ12 */
-#define SCF0_UART2_TRISTATE 0x08 /* Force UART2/IR outputs to */
- /* tri-state when disabled */
-#define SCF0_GPIO_PORT1_ENABLE 0x10 /* Enable GPIO port 1 */
-#define SCF0_GPIO_PORT2_ENABLE 0x20 /* Enable GPIO port 2 */
-
-#define SIO_CONFIG_SCF1 0x18 /* Super I/O Configuration Register 1 */
-
-#define SCF1_REPORTED_ECP_DMA 0x06 /* Reported ECP DMA number */
- /* 0: Jumpered 8-bit DMA */
- /* 1: DMA channel 1 */
- /* 2: DMA channel 2 */
- /* 3: DMA channel 3 */
-#define SCF1_SELECTED_ECP_DMA 0x08 /* Selected ECP DMA pins */
- /* 0: PDRQ0 & PDACK0 */
- /* 1: PDRQ1 & PDACK1 */
-#define SCF1_SCRATCH_BITS 0xC0 /* ? */
-
-#define SIO_CONFIG_LPTBA 0x19 /* LPT Base Address */
-
-#define SIO_CONFIG_PNP0 0x1B /* Plug & Play Configuration Register 0 */
-
-#define PNP0_LPT_INT_SELECT_CONTROL 0x10 /* LPT IRQ select control */
- /* 0: IRQ selected by FAR[1:0] */
- /* 1: IRQ selected by PNP0[5] */
-#define PNP0_LPT_INT_MAPPING 0x20 /* LPT IRQ mapping */
- /* 0: IRQ5 */
- /* 1: IRQ7 */
-#define PNP0_LPTA_BASE_ADDR_SELECT 0x40 /* LPTA base address */
- /* 0: Always 0x3BC */
- /* 1: Selected by LPTBA[7:0] */
-
-#define SIO_CONFIG_PNP1 0x1C /* Plug & Play Configuration Register 1 */
-
-#define PNP1_UARTS_INT_SELECT_CONTROL 0x01 /* UART interrupt select control */
- /* 0: Use FAR[3:2] & FAR[5:4] */
- /* 1: Use PNP1[2] & PNP1[6] */
-#define PNP1_UART1_INT_MAPPING 0x04 /* UART1 interrupt mapping */
- /* 0: IRQ3 */
- /* 1: IRQ4 */
-#define PNP1_UART2_INT_MAPPING 0x40 /* UART2 interrupt mapping */
- /* 0: IRQ3 */
- /* 1: IRQ4 */
-/*---------------------------------------------------------------------------*/
-
-/*
- * Definitions for the SuperIO UART.
- */
-#define COM1_PORT 0x3f8
-#define COM2_PORT 0x2f8
-
-/*
- * Register offsets.
- */
-#define UART_RX 0 /* Receive port, read only */
-#define UART_TX 0 /* transmit port, write only */
-#define UART_IER 1 /* Interrupt enable, read/write */
-#define UART_IIR 2 /* Interrupt id, read only */
-#define UART_FIFO_CONTROL 2 /* FIFO control, write only */
-#define UART_LCR 3 /* Line control register */
-#define UART_MCR 4 /* Modem control register */
-#define UART_LSR 5 /* Line Status register */
-#define UART_MSR 6 /* Modem Status register */
-
-/* with the DLAB bit set, the first two registers contain the baud rate */
-#define UART_DLLSB 0
-#define UART_DLMSB 1
-
-/*
- * Line control register
- */
-#define LCR_DB 3 /* Data bits in transmission (0 = 5, 1 = 6, 2 = 7, 3 = 8) */
-#define LCR_SB 4 /* Stop bit */
-#define LCR_PE 8 /* Parity enable */
-#define LCR_EP 16 /* Even parity */
-#define LCR_SP 32 /* Stick parity */
-#define LCR_BC 64 /* break control */
-#define LCR_DLAB 128 /* Divisor latch access bit */
-
-
-/*
- * Modem Control register
- */
-#define MCR_DTR 1 /* Data Terminal Ready */
-#define MCR_RTS 2 /* Request To Send */
-#define MCR_OUT1 4 /* Out1 (not used) */
-#define MCR_IRQ_ENABLE 8 /* Enable IRQ */
-#define MCR_LOOP 16 /* Loopback mode */
-
-/*
- * Line status bits.
- */
-#define LSR_DR 0x01 /* Data ready */
-#define LSR_OE 0x02 /* Overrun error */
-#define LSR_PE 0x04 /* Parity error */
-#define LSR_FE 0x08 /* Framing error */
-#define LSR_BI 0x10 /* Break interrupt */
-#define LSR_THRE 0x20 /* Transmitter holding register empty */
-#define LSR_TEMT 0x40 /* Transmitter empty */
-#define LSR_FFE 0x80 /* Receiver FIFO error */
-
-#define LSR_ERROR (LSR_OE | LSR_PE | LSR_FE)
-
-/*
- * Interrupt Identification register (IIR)
- */
-#define IIR_IP 1 /* No Interrupt pending */
-#define IIR_RECEIVE_LINE_STATUS 6 /* Overrun, Parity, Framing erros, Break */
-#define IIR_RDA 4 /* Receive data available */
-#define IIR_FIFO_FLAG 8 /* FIFO flag */
-#define IIR_FIFO_TIMEOUT (IIR_RDA+IIR_FIFO_FLAG) /* Got data some time ago, but FIFO time out */
-#define IIR_THRE 2 /* Transmitter holding register empty. */
-#define IIR_MS 0 /* CTS, DSR, RING, DCD changed */
-#define IIR_HPIP 6 /* Highest priority interrupt pending */
-
-/*
- * Interrupt enable register (IER)
- */
-#define IER_RDA 1 /* Received data available */
-#define IER_THRE 2 /* Transmitter holding register empty */
-#define IER_RLS 4 /* Receiver line status */
-#define IER_MS 8 /* Modem status */
-
-/*
- * PC87306 Parallel I/O Port
- */
-#define LPT1_PORT 0x03BC
-
-/*
- * PC87306 General Purpose I/O Ports
- */
-#define GPIO1_PORT 0x0078
-#define GPIO2_PORT 0x0079
-
-/*
- * PC87306 IDE Port
- */
-#define IDE_PORT_1 0x01F0
-#define IDE_PORT_2 0x03F6
-#define IDE_PORT_3 0x03F7
-
-/*
- * PC87306 Floppy Port
- */
-#define FDC_PORT 0x03F0
-
-/*
- * PC87306 Real Time Clock/battery backed up RAM port
- */
-#define RTC_INDEX_PORT 0x0070
-#define RTC_DATA_PORT 0x0071
-
-/*
- * Offsets in RTC memory (RAMSEL = 0)
- */
-#define RTC_SECONDS 0
-#define RTC_SECONDS_ALARM 1
-#define RTC_MINUTES 2
-#define RTC_MINUTES_ALARM 3
-#define RTC_HOURS 4
-#define RTC_HOURS_ALARM 5
-#define RTC_DAY_OF_WEEK 6
-#define RTC_DAY_OF_MONTH 7
-#define RTC_MONTH 8
-#define RTC_YEAR 9
-#define RTC_CONTROL_A 0xA
-#define RTC_CONTROL_B 0xB
-#define RTC_CONTROL_C 0xC
-#define RTC_CONTROL_D 0xD
-
-#define RTC_NVRAM0_START 0xE
-#define RTC_NVRAM0_SIZE 114
-#define RTC_NVRAM1_START 0
-#define RTC_NVRAM1_SIZE 128
-#define RTC_NVRAM_SIZE (RTC_NVRAM0_SIZE+RTC_NVRAM1_SIZE)
-
-#define RTC_PWNVRAM_START 0x38 /* Start of protected NVRAM */
-#define RTC_PWNVRAM_SIZE 8 /* Size of protected NVRAM */
-
-
-/*
- * PC87306 Keyboard controller ports
- */
-#define KEYBD_DATA_PORT 0x0060
-#define KEYBD_CTRL_PORT 0x0064
--- a/os/boot/puma/qio.c
+++ /dev/null
@@ -1,128 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-struct Queue {
- Block* first;
- Block* last;
- void (*kick)(void*);
- void* arg;
- long len;
-};
-
-Block *
-iallocb(int n)
-{
- Block *b;
-
- b = (Block*)malloc(sizeof(Block)+n);
- b->data = (uchar*)b + sizeof(Block);
- b->rp = b->wp = b->data;
- b->lim = b->data + n;
- b->next = 0;
- b->magic = 0xcafebee0;
- return b;
-}
-
-void
-freeb(Block *b)
-{
- if(b){
- if(b->magic != 0xcafebee0)
- panic("freeb");
- b->magic = 0;
- b->next = (Block*)0xdeadbabe;
- free(b);
- }
-}
-
-Queue *
-qopen(int limit, int msg, void (*kick)(void*), void *arg)
-{
- Queue *q;
-
- USED(limit, msg);
- q = (Queue*)malloc(sizeof(Queue));
- q->first = q->last = 0;
- q->kick = kick;
- q->arg = arg;
- q->len = 0;
- return q;
-}
-
-Block *
-qget(Queue *q)
-{
- int s;
- Block *b;
-
- s = splhi();
- if((b = q->first) != 0){
- q->first = b->next;
- b->next = 0;
- q->len -= BLEN(b);
- if(q->len < 0)
- panic("qget");
- }
- splx(s);
- return b;
-}
-
-void
-qbwrite(Queue *q, Block *b)
-{
- int s;
-
- s = splhi();
- b->next = 0;
- if(q->first == 0)
- q->first = b;
- else
- q->last->next = b;
- q->last = b;
- q->len += BLEN(b);
- splx(s);
- if(q->kick)
- q->kick(q->arg);
-}
-
-long
-qlen(Queue *q)
-{
- return q->len;
-}
-
-int
-qbgetc(Queue *q)
-{
- Block *b;
- int s, c;
-
- c = -1;
- s = splhi();
- while(c < 0 && (b = q->first) != nil){
- if(b->rp < b->wp){
- c = *b->rp++;
- q->len--;
- }
- if(b->rp >= b->wp){
- q->first = b->next;
- b->next = nil;
- }
- }
- splx(s);
- return c;
-}
-
-void
-qbputc(Queue *q, int c)
-{
- Block *b;
-
- b = iallocb(1);
- *b->wp++ = c;
- qbwrite(q, b);
-}
--- a/os/boot/puma/rmap.c
+++ /dev/null
@@ -1,104 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-void
-mapinit(RMap *rmap, Map *map, int size)
-{
- lock(rmap);
- rmap->map = map;
- rmap->mapend = map+(size/sizeof(Map));
- unlock(rmap);
-}
-
-void
-mapfree(RMap* rmap, ulong addr, int size)
-{
- Map *mp;
- ulong t;
-
- if(size <= 0)
- return;
-
- lock(rmap);
- for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
- ;
-
- if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
- (mp-1)->size += size;
- if(addr+size == mp->addr){
- (mp-1)->size += mp->size;
- while(mp->size){
- mp++;
- (mp-1)->addr = mp->addr;
- (mp-1)->size = mp->size;
- }
- }
- }
- else{
- if(addr+size == mp->addr && mp->size){
- mp->addr -= size;
- mp->size += size;
- }
- else do{
- if(mp >= rmap->mapend){
- print("mapfree: %s: losing 0x%uX, %d\n",
- rmap->name, addr, size);
- break;
- }
- t = mp->addr;
- mp->addr = addr;
- addr = t;
- t = mp->size;
- mp->size = size;
- mp++;
- }while(size = t);
- }
- unlock(rmap);
-}
-
-ulong
-mapalloc(RMap* rmap, ulong addr, int size, int align)
-{
- Map *mp;
- ulong maddr, oaddr;
-
- lock(rmap);
- for(mp = rmap->map; mp->size; mp++){
- maddr = mp->addr;
-
- if(addr){
- if(maddr > addr)
- continue;
- if(addr+size > maddr+mp->size)
- break;
- maddr = addr;
- }
-
- if(align > 0)
- maddr = ((maddr+align-1)/align)*align;
- if(mp->addr+mp->size-maddr < size)
- continue;
-
- oaddr = mp->addr;
- mp->addr = maddr+size;
- mp->size -= maddr-oaddr+size;
- if(mp->size == 0){
- do{
- mp++;
- (mp-1)->addr = mp->addr;
- }while((mp-1)->size = mp->size);
- }
-
- unlock(rmap);
- if(oaddr != maddr)
- mapfree(rmap, oaddr, maddr-oaddr);
-
- return maddr;
- }
- unlock(rmap);
-
- return 0;
-}
--- a/os/boot/puma/squeeze.h
+++ /dev/null
@@ -1,34 +1,0 @@
-
-/*
- * squeezed file format:
- * Sqhdr
- * original Exec header
- * two Squeeze tables
- * squeezed segment
- * unsqueezed segment, if any
- */
-#define SQMAGIC (ulong)0xFEEF0F1E
-
-typedef struct Sqhdr Sqhdr;
-struct Sqhdr {
- uchar magic[4]; /* SQMAGIC */
- uchar text[4]; /* squeezed length of text (excluding tables) */
- uchar data[4]; /* squeezed length of data (excluding tables) */
- uchar asis[4]; /* length of unsqueezed segment */
- uchar toptxt[4]; /* value for 0 encoding in text */
- uchar topdat[4]; /* value for 0 encoding in data */
- uchar sum[4]; /* simple checksum of unsqueezed data */
- uchar flags[4];
-};
-#define SQHDRLEN (8*4)
-
-/*
- * certain power instruction types are rearranged by sqz
- * so as to move the variable part of the instruction word to the
- * low order bits. note that the mapping is its own inverse.
- */
-#define QREMAP(X)\
- switch((X)>>26){\
- case 19: case 31: case 59: case 63:\
- (X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
- }
--- a/os/boot/puma/sum.c
+++ /dev/null
@@ -1,13 +1,0 @@
-int
-sum(int a, int b, int c)
-{
- return a+b+c;
-}
-
-void
-main(void)
-{
- int s;
-
- s = sum(1, 2, 3);
-}
--- a/os/boot/puma/trap.c
+++ /dev/null
@@ -1,190 +1,0 @@
-#include "boot.h"
-
-typedef struct IrqEntry {
- void (*r)(Ureg*, void*);
- void *a;
-} IrqEntry;
-
-IrqEntry Irq[V_MAXNUM+1];
-
-static void dumpstk(ulong *);
-void dumpregs(Ureg* ureg);
-
-void
-setvec(int v, void (*f)(Ureg*, void*), void* a)
-{
- if(v < 0 || v >= V_MAXNUM)
- panic("setvec: interrupt source %d out of range\n", v);
- Irq[v].r = f;
- Irq[v].a = a;
-}
-
-ulong irqstack[64];
-ulong fiqstack[64];
-ulong abtstack[64];
-ulong undstack[64];
-
-static void
-safeintr(Ureg*, void *a)
-{
- int v = (int)a;
-// print("spurious interrupt %d\n", v);
- USED(v);
-}
-
-void
-trapinit(void)
-{
- int offset;
- ulong op;
- int v;
- int s;
-
- s = splhi();
-
- /* set up stacks for various exceptions */
- setr13(PsrMirq, irqstack+nelem(irqstack)-1);
- setr13(PsrMfiq, fiqstack+nelem(fiqstack)-1);
- setr13(PsrMabt, abtstack+nelem(abtstack)-1);
- setr13(PsrMund, undstack+nelem(undstack)-1);
-
- for(v = 0; v <= V_MAXNUM; v++) {
- Irq[v].r = safeintr;
- Irq[v].a = (void *)v;
- }
-
- /* Reset Exception */
- offset = ((((ulong) _vsvccall) - 0x0)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0x0) = op;
-
- /* Undefined Instruction Exception */
- offset = ((((ulong) _vundcall) - 0x4)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0x4) = op;
-
- /* SWI Exception */
- offset = ((((ulong) _vsvccall) - 0x8)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0x8) = op;
-
- /* Prefetch Abort Exception */
- offset = ((((ulong) _vpabcall) - 0xc)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0xc) = op;
-
- /* Data Abort Exception */
- offset = ((((ulong) _vdabcall) - 0x10)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0x10) = op;
-
- /* IRQ Exception */
- offset = ((((ulong) _virqcall) - 0x18)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0x18) = op;
-
- /* FIQ Exception */
- offset = ((((ulong) _vfiqcall) - 0x1c)-8) >> 2;
- op = ( 0xea << 24 ) | offset;
- *((ulong *) 0x1c) = op;
-
-
- flushIcache();
- writeBackDC();
- flushDcache();
- flushIcache();
- drainWBuffer();
-
- splx(s);
-}
-
-/*
- * trap is called splhi().
- */
-
-void
-trap(Ureg* ureg)
-{
- ushort mask;
- IrqEntry *ip;
-
- /*
- * All interrupts/exceptions should be resumed at ureg->pc-4,
- * except for Data Abort which resumes at ureg->pc-8.
- */
- ureg->pc -= 4;
-
- switch(ureg->type) {
- case PsrMirq: /* Interrupt Request */
- mask = *(uchar*)HARI1 | ((*(uchar*)HARI2) << 8);
- ip = Irq;
- while (mask != 0) {
- if(mask&1)
- ip->r(ureg, ip->a);
- ip++;
- mask >>= 1;
- }
- break;
-
- case PsrMfiq: /* FIQ */
- mask = *(uchar*)HARI1 & HARI1_FIQ_MASK;
- ip = Irq;
- while (mask != 0) {
- if(mask&1)
- ip->r(ureg, ip->a);
- ip++;
- mask >>= 1;
- }
- break;
-
- case PsrMund: /* Undefined instruction */
- dumpregs(ureg);
- panic("Undefined Instruction Exception\n");
- break;
-
- case PsrMsvc: /* Jump through 0 or SWI */
- dumpregs(ureg);
- panic("SVC/SWI Exception\n");
- break;
-
- case PsrMabt: /* Prefetch abort */
- ureg->pc -= 4;
- /* FALLTHROUGH */
-
- case PsrMabt+1: { /* Data abort */
- uint far =0;
- uint fsr =0;
-
- USED(far,fsr);
- fsr = 0; /*mmuregr(CpFSR);*/
- far = 0; /*mmuregr(CpFAR); */
- if (ureg->type == PsrMabt)
- print("Prefetch Abort/");
- print("Data Abort\n");
-
- print("Data Abort: FSR %8.8uX FAR %8.8uX\n", fsr, far);
- /* FALLTHROUGH */
- }
- default:
- dumpregs(ureg);
- panic("exception %uX\n", ureg->type);
- break;
- }
-
- splhi();
-}
-
-void
-dumpregs(Ureg* ureg)
-{
- print("PSR %8.8uX type %2.2uX PC %8.8uX LINK %8.8uX\n",
- ureg->psr, ureg->type, ureg->pc, ureg->link);
- print("R14 %8.8uX R13 %8.8uX R12 %8.8uX R11 %8.8uX R10 %8.8uX\n",
- ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
- print("R9 %8.8uX R8 %8.8uX R7 %8.8uX R6 %8.8uX R5 %8.8uX\n",
- ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
- print("R4 %8.8uX R3 %8.8uX R2 %8.8uX R1 %8.8uX R0 %8.8uX\n",
- ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
- print("Stack is at: %8.8uX\n", ureg);
-/* print("CPSR %8.8uX SPSR %8.8uX\n", cpsrr(), spsrr());*/
-}
--- a/os/boot/puma/ureg.h
+++ /dev/null
@@ -1,22 +1,0 @@
-typedef struct Ureg {
- uint r0;
- uint r1;
- uint r2;
- uint r3;
- uint r4;
- uint r5;
- uint r6;
- uint r7;
- uint r8;
- uint r9;
- uint r10;
- uint r11;
- uint r12;
- uint r13;
- uint r14;
- uint link;
- uint type;
- uint psr;
-// uint sp;
- uint pc;
-} Ureg;
--- a/os/boot/puma/zqs.c
+++ /dev/null
@@ -1,216 +1,0 @@
-#include "boot.h"
-#include "squeeze.h"
-
-#define EXECHDRLEN (8*4)
-
-typedef struct Squeeze Squeeze;
-struct Squeeze {
- int n;
- ulong tab[7*256];
-};
-
-#define GET4(p) (((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
-
-/*
- * for speed of unsqueezing from Flash, certain checks are
- * not done inside the loop (as they would be in the unsqueeze program zqs),
- * but instead the checksum is expected to catch corrupted files.
- * in fact the Squeeze array bounds can't be exceeded in practice
- * because the tables are always full for a squeezed kernel.
- */
-enum {
- QFLAG = 1, /* invert powerpc-specific code transformation */
- CHECK = 0, /* check precise bounds in Squeeze array (otherwise checksum detects error) */
-};
-
-static ulong chksum;
-static int rdtab(Block*, Squeeze*, int);
-static ulong* unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
-static uchar* unsqzseg(uchar*, Block*, long, long, char*);
-static Alarm* unsqzal;
-
-int
-issqueezed(uchar *b)
-{
- return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
-}
-
-static void
-unsqzdot(void*)
-{
- unsqzal = alarm(500, unsqzdot, nil);
- print(".");
-}
-
-long
-unsqueezef(Block *b, ulong *entryp)
-{
- uchar *loada, *wp;
- ulong toptxt, topdat, oldsum;
- long asis, nst, nsd;
- Sqhdr *sqh;
- Exec *ex;
-
- if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
- return -1;
- sqh = (Sqhdr*)b->rp;
- if(GET4(sqh->magic) != SQMAGIC)
- return -1;
- chksum = 0;
- toptxt = GET4(sqh->toptxt);
- topdat = GET4(sqh->topdat);
- oldsum = GET4(sqh->sum);
- asis = GET4(sqh->asis);
- nst = GET4(sqh->text);
- nsd = GET4(sqh->data);
- b->rp += SQHDRLEN;
- ex = (Exec*)b->rp;
- if(GET4(ex->magic) != E_MAGIC){
- print("zqs: not StrongARM executable\n");
- return -1;
- }
- *entryp = GET4(ex->entry);
- b->rp += EXECHDRLEN;
- loada = KADDR(PADDR(*entryp));
- wp = unsqzseg(loada, b, nst, toptxt, "text");
- if(wp == nil){
- print("zqs: format error\n");
- return -1;
- }
- if(nsd){
- wp = (uchar*)PGROUND((ulong)wp);
- wp = unsqzseg(wp, b, nsd, topdat, "data");
- if(wp == nil){
- print("zqs: format error\n");
- return -1;
- }
- }
- if(asis){
- memmove(wp, b->rp, asis);
- wp += asis;
- b->rp += asis;
- }
- if(chksum != oldsum){
- print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
- return -1;
- }
- return wp-loada;
-}
-
-static uchar *
-unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
-{
- static Squeeze sq3, sq4;
-
- print("unpack %s %8.8lux %lud:", what, wp, ns);
- if(ns == 0)
- return wp;
- if(rdtab(b, &sq3, 0) < 0)
- return nil;
- if(rdtab(b, &sq4, 8) < 0)
- return nil;
- if(BLEN(b) < ns){
- print(" **size error\n");
- return nil;
- }
- unsqzal = alarm(500, unsqzdot, nil);
- wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
- cancel(unsqzal);
- unsqzal = nil;
- print("\n");
- if(wp == nil){
- print("zqs: corrupt squeezed data stream\n");
- return nil;
- }
- b->rp += ns;
- return wp;
-}
-
-static ulong*
-unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
-{
- ulong nx, csum;
- int code, n;
-
- if(QFLAG){
- QREMAP(top); /* adjust top just once, outside the loop */
- }
- csum = chksum;
- while(rp < ep){
- /* no function calls within this loop for speed */
- code = *rp;
- rp++;
- n = 0;
- nx = code>>4;
- do{
- if(nx == 0){
- nx = top;
- }else{
- if(nx==1){
- nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
- rp += 4;
- }else if(nx <= 8){ /* 2 to 8 */
- nx = ((nx-2)<<8) | rp[0];
- if(CHECK && nx >= sq4->n)
- return nil; /* corrupted file */
- nx = sq4->tab[nx] | rp[1];
- rp += 2;
- }else{ /* 9 to 15 */
- nx = ((nx-9)<<8) | rp[0];
- if(CHECK && nx >= sq3->n)
- return nil; /* corrupted file */
- nx = sq3->tab[nx];
- rp++;
- }
- if(rp > ep)
- return nil; /* corrupted file */
- if(QFLAG){
- QREMAP(nx);
- }
- }
- *wp = nx;
- wp++;
- csum += nx;
- nx = code & 0xF;
- }while(++n == 1);
- }
- chksum = csum;
- return wp;
-}
-
-static int
-rdtab(Block *b, Squeeze *sq, int shift)
-{
- uchar *p, *ep;
- ulong v, w;
- int i;
-
- if(BLEN(b) < 2)
- return -1;
- i = (b->rp[0]<<8) | b->rp[1];
- if(1)
- print(" T%d", i);
- b->rp += 2;
- if((i -= 2) > 0){
- if(BLEN(b) < i)
- return -1;
- }
- sq->n = 0;
- p = b->rp;
- ep = b->rp+i;
- b->rp += i;
- v = 0;
- while(p < ep){
- w = 0;
- do{
- if(p >= ep)
- return -1;
- w = (w<<7) | (*p & 0x7F);
- }while(*p++ & 0x80);
- v += w;
- if(0)
- print("%d %8.8lux %8.8lux\n", sq->n, v, w);
- sq->tab[sq->n++] = v<<shift;
- }
- return 0;
-}
--- a/os/boot/rpcg/NOTICE
+++ /dev/null
@@ -1,3 +1,0 @@
-Inferno® Copyright © 1996-1999 Lucent Technologies Inc. All rights reserved.
-PowerPC support Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk). All rights reserved.
-MPC8xx Inferno PowerPC port Copyright © 1998-2003 Vita Nuova Holdings Limited. All rights reserved.
--- a/os/boot/rpcg/alarm.c
+++ /dev/null
@@ -1,123 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#define MAXALARM 10
-
-Alarm alarmtab[MAXALARM];
-
-/*
- * Insert new into list after where
- */
-void
-insert(List **head, List *where, List *new)
-{
- if(where == 0){
- new->next = *head;
- *head = new;
- }else{
- new->next = where->next;
- where->next = new;
- }
-
-}
-
-/*
- * Delete old from list. where->next is known to be old.
- */
-void
-delete(List **head, List *where, List *old)
-{
- if(where == 0){
- *head = old->next;
- return;
- }
- where->next = old->next;
-}
-
-Alarm*
-newalarm(void)
-{
- int i;
- Alarm *a;
-
- for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
- if(a->busy==0 && a->f==0){
- a->f = 0;
- a->arg = 0;
- a->busy = 1;
- return a;
- }
- panic("newalarm");
- return 0; /* not reached */
-}
-
-Alarm*
-alarm(int ms, void (*f)(Alarm*), void *arg)
-{
- Alarm *a, *w, *pw;
- ulong s;
-
- if(ms < 0)
- ms = 0;
- s = splhi();
- a = newalarm();
- a->dt = MS2TK(ms);
- a->f = f;
- a->arg = arg;
- pw = 0;
- for(w=m->alarm; w; pw=w, w=w->next){
- if(w->dt <= a->dt){
- a->dt -= w->dt;
- continue;
- }
- w->dt -= a->dt;
- break;
- }
- insert(&m->alarm, pw, a);
- splx(s);
- return a;
-}
-
-void
-cancel(Alarm *a)
-{
- a->f = 0;
-}
-
-void
-alarminit(void)
-{
-}
-
-#define NA 10 /* alarms per clock tick */
-void
-checkalarms(void)
-{
- int i, n, s;
- Alarm *a;
- void (*f)(Alarm*);
- Alarm *alist[NA];
-
- s = splhi();
- a = m->alarm;
- if(a){
- for(n=0; a && a->dt<=0 && n<NA; n++){
- alist[n] = a;
- delete(&m->alarm, 0, a);
- a = m->alarm;
- }
- if(a)
- a->dt--;
-
- for(i = 0; i < n; i++){
- f = alist[i]->f; /* avoid race with cancel */
- if(f)
- (*f)(alist[i]);
- alist[i]->busy = 0;
- }
- }
- splx(s);
-}
--- a/os/boot/rpcg/all.h
+++ /dev/null
@@ -1,6 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "dat.h"
-#include "fns.h"
-#include "mem.h"
-#include "io.h"
--- a/os/boot/rpcg/archrpcg.c
+++ /dev/null
@@ -1,279 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "archrpcg.h"
-#include "etherif.h"
-
-/*
- * board-specific support for the RPCG RXLite
- */
-
-enum {
- SYSMHZ = 66, /* target frequency */
-
- /* sccr */
- RTSEL = IBIT(8), /* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
- RTDIV = IBIT(7), /* =0, divide by 4; =1, divide by 512 */
- CRQEN = IBIT(9), /* =1, switch to high frequency when CPM active */
- PRQEN = IBIT(10), /* =1, switch to high frequency when interrupt pending */
-
- /* plprcr */
- CSRC = IBIT(21), /* =0, clock is DFNH; =1, clock is DFNL */
-};
-
-static char flashsig[] = "RPXsignature=1.0\nNAME=qbrpcg\nSTART=FFC20100\nVERSION=1.1\n";
-static char* geteeprom(char*);
-
-/*
- * called early in main.c, after machinit:
- * using board and architecture specific registers, initialise
- * 8xx registers that need it and complete initialisation of the Mach structure.
- */
-void
-archinit(void)
-{
- IMM *io;
- int mf, t;
- ulong v;
-
- v = getimmr() & 0xFFFF;
- switch(v>>8){
- case 0x00: t = 0x86000; break;
- case 0x20: t = 0x82300; break;
- case 0x21: t = 0x823a0; break;
- default: t = 0; break;
- }
- m->cputype = t;
- m->bcsr = KADDR(BCSRMEM);
- io = m->iomem;
- m->clockgen = 8*MHz;
- mf = (io->plprcr >> 20)+1; /* use timing set by bootstrap */
- m->cpuhz = m->clockgen*mf;
- m->bcsr[0] = DisableColTest | DisableFullDplx | DisableUSB | HighSpdUSB | LedOff; /* first write enables bcsr regs */
-return;
- io->plprcrk = KEEP_ALIVE_KEY;
- io->plprcr &= ~CSRC; /* general system clock is DFNH */
-/* io->mptpr = 0x0800; /* memory prescaler = 8 for refresh */
- /* use memory refresh time set by RPXLite monitor */
- io->plprcrk = ~KEEP_ALIVE_KEY;
-}
-
-void
-cpuidprint(void)
-{
- int t, v;
-
- print("Inferno bootstrap\n");
- print("PVR: ");
- t = getpvr()>>16;
- switch(t){
- case 0x01: print("MPC601"); break;
- case 0x03: print("MPC603"); break;
- case 0x04: print("MPC604"); break;
- case 0x06: print("MPC603e"); break;
- case 0x07: print("MPC603e-v7"); break;
- case 0x50: print("MPC8xx"); break;
- default: print("PowerPC version #%x", t); break;
- }
- print(", revision #%lux\n", getpvr()&0xffff);
- print("IMMR: ");
- v = getimmr() & 0xFFFF;
- switch(v>>8){
- case 0x00: print("MPC860/821"); break;
- case 0x20: print("MPC823"); break;
- case 0x21: print("MPC823A"); break;
- default: print("Type #%lux", v>>8); break;
- }
- print(", mask #%lux\n", v&0xFF);
- print("options: #%lux\n", archoptionsw());
- print("bcsr: %8.8lux\n", m->bcsr[0]);
- print("PLPRCR=%8.8lux SCCR=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
- print("%lud MHz system\n", m->cpuhz/MHz);
- print("\n");
-//print("%s\n", geteeprom("EA"));
-print("BR0=%8.8lux OR0=%8.8lux\n", m->iomem->memc[0].base, m->iomem->memc[0].option);
-print("MPTPR=%8.8lux\n", m->iomem->mptpr);
-}
-
-static char* defplan9ini[2] = {
- /* 860/821 */
- "ether0=type=SCC port=1 ea=0010ec000051\r\n"
- "vgasize=640x480x8\r\n"
- "kernelpercent=40\r\n"
- "console=0\r\nbaud=9600\r\n",
-
- /* 823 */
- "ether0=type=SCC port=2 ea=0010ec000051\r\n"
- "vgasize=640x480x8\r\n"
- "kernelpercent=40\r\n"
- "console=0\r\nbaud=9600\r\n",
-};
-
-char *
-archconfig(void)
-{
- print("Using default configuration\n");
- return defplan9ini[MPCMODEL(m->cputype) == 0x823];
-}
-
-/*
- * provide value for #r/switch (devrtc.c)
- */
-int
-archoptionsw(void)
-{
- return (m->bcsr[0]&DipSwitchMask)>>4;
-}
-
-/*
- * invoked by clock.c:/^clockintr
- */
-static void
-twinkle(void)
-{
- if(m->ticks%MS2TK(1000) == 0)
- m->bcsr[0] ^= LedOff;
-}
-
-void (*archclocktick)(void) = twinkle;
-
-/*
- * for flash.c:/^flashreset
- * retrieve flash type, virtual base and length and return 0;
- * return -1 on error (no flash)
- */
-int
-archflashreset(char *type, void **addr, long *length)
-{
- if((m->iomem->memc[BOOTCS].base & 1) == 0)
- return -1; /* shouldn't happen */
- strcpy(type, "AMD29F0x0");
- *addr = KADDR(FLASHMEM);
- *length = 4*1024*1024;
- return 0;
-}
-
-int
-archether(int ctlrno, Card *ether)
-{
- char *ea;
-
- if(ctlrno > 0)
- return -1;
- strcpy(ether->type, "SCC");
- ether->port = 2;
- ea = geteeprom("EA");
- if(ea != nil)
- parseether(ether->ea, ea);
- return 1;
-}
-
-/*
- * enable the clocks for the given SCC ether and reveal them to the caller.
- * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
- */
-int
-archetherenable(int cpmid, int *rcs, int *tcs)
-{
- IMM *io;
-
- switch(cpmid){
- default:
- /* no other SCCs are wired for ether on RPXLite*/
- return -1;
-
- case SCC2ID:
- io = ioplock();
- m->bcsr[0] |= EnableEnet;
- io->papar |= SIBIT(6)|SIBIT(4); /* enable CLK2 and CLK4 */
- io->padir &= ~(SIBIT(6)|SIBIT(4));
- *rcs = CLK4;
- *tcs = CLK2;
- iopunlock();
- break;
- }
- return 0;
-}
-
-void
-archetherdisable(int id)
-{
- USED(id);
- m->bcsr[0] &= ~EnableEnet;
-}
-
-/*
- * do anything extra required to enable the UART on the given CPM port
- */
-void
-archenableuart(int id, int irda)
-{
- USED(id, irda);
-}
-
-/*
- * do anything extra required to disable the UART on the given CPM port
- */
-void
-archdisableuart(int id)
-{
- USED(id);
-}
-
-/*
- * enable/disable the LCD panel's backlight
- */
-void
-archbacklight(int on)
-{
- USED(on);
-}
-
-static char*
-geteeprom(char *s)
-{
- static int init;
- static char res[64];
- static uchar eeprom[257];
- uchar *l, *p;
- int i, j;
-
- if(!init){
- i2csetup();
- if(i2crecv(0xa8|1|(0<<8), eeprom, 128) < 0 ||
- i2crecv(0xa8|1|(128<<8), eeprom+128, 128) < 0){
- print("i2c failed\n");
- return nil;
- }
- if(0){
- print("eeprom:\n");
- for(i=0; i<16; i++){for(j=0; j<16; j++)print(" %2.2ux[%c]", eeprom[i*16+j], eeprom[i*16+j]); print("\n");}
- }
- eeprom[256] = 0xFF;
- init = 1;
- }
- for(l = eeprom; *l != 0xFF && *l != '\n';){
- p = l;
- while(*l != '\n' && *l != 0xFF && *l != '=')
- l++;
- if(*l == '='){
- if(l-p == strlen(s) && strncmp(s, (char*)p, strlen(s)) == 0){
- p = l+1;
- while(*l != '\n' && *l != 0xFF)
- l++;
- memmove(res, p, l-p);
- res[l-p] = 0;
- return res;
- }
- }
- while(*l != '\n' && *l != 0xFF)
- l++;
- if(*l == '\n')
- l++;
- }
- return nil;
-}
--- a/os/boot/rpcg/archrpcg.h
+++ /dev/null
@@ -1,48 +1,0 @@
-/*
- * values for RPXLite AW
- */
-enum {
- /* CS assignment */
- BOOTCS = 0,
- DRAM1 = 1,
- /* CS2 is routed to expansion header */
- BCSRCS = 3,
- NVRAMCS = 4,
- /* CS5 is routed to expansion header */
- PCMCIA0CS = 6, /* select even bytes */
- PCMCIA1CS = 7, /* select odd bytes */
-};
-
-/*
- * BCSR bits (there are 4 8-bit registers that we access as ulong)
- */
-enum {
- EnableEnet = IBIT(0),
- EnableXcrLB= IBIT(1),
- DisableColTest= IBIT(2),
- DisableFullDplx=IBIT(3),
- LedOff= IBIT(4),
- DisableUSB= IBIT(5),
- HighSpdUSB= IBIT(6),
- EnableUSBPwr= IBIT(7),
- /* 8,9,10 unused */
- PCCVCCMask= IBIT(12)|IBIT(13),
- PCCVPPMask= IBIT(14)|IBIT(15),
- PCCVCC0V= 0,
- PCCVCC5V= IBIT(13),
- PCCVCC3V= IBIT(12),
- PCCVPP0V= 0,
- PCCVPP5V= IBIT(14),
- PCCVPP12V= IBIT(15),
- PCCVPPHiZ= IBIT(14)|IBIT(15),
- /* 16-23 NYI */
- DipSwitchMask= IBIT(24)|IBIT(25)|IBIT(26)|IBIT(27),
- DipSwitch0= IBIT(24),
- DipSwitch1= IBIT(25),
- DipSwitch2= IBIT(26),
- DipSwitch3= IBIT(27),
- /* bit 28 RESERVED */
- FlashComplete= IBIT(29),
- NVRAMBattGood= IBIT(30),
- RTCBattGood= IBIT(31),
-};
--- a/os/boot/rpcg/boot.h
+++ /dev/null
@@ -1,8 +1,0 @@
-#include <u.h>
-#include "lib.h"
-
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
--- a/os/boot/rpcg/bootp.c
+++ /dev/null
@@ -1,509 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ip.h"
-
-#define XPADDR(a) ((ulong)(a) & ~KSEGM)
-
-enum {
- CHECKSUM = 1, /* set zero if trouble booting from Linux */
-};
-
-uchar broadcast[Eaddrlen] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static ushort tftpport = 5000;
-static int Id = 1;
-static Netaddr myaddr;
-static Netaddr server;
-
-typedef struct {
- uchar header[4];
- uchar data[Segsize];
-} Tftp;
-static Tftp tftpb;
-
-static void
-hnputs(uchar *ptr, ushort val)
-{
- ptr[0] = val>>8;
- ptr[1] = val;
-}
-
-static void
-hnputl(uchar *ptr, ulong val)
-{
- ptr[0] = val>>24;
- ptr[1] = val>>16;
- ptr[2] = val>>8;
- ptr[3] = val;
-}
-
-static ulong
-nhgetl(uchar *ptr)
-{
- return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
-}
-
-static ushort
-nhgets(uchar *ptr)
-{
- return ((ptr[0]<<8) | ptr[1]);
-}
-
-static short endian = 1;
-static char* aendian = (char*)&endian;
-#define LITTLE *aendian
-
-static ushort
-ptcl_csum(void *a, int len)
-{
- uchar *addr;
- ulong t1, t2;
- ulong losum, hisum, mdsum, x;
-
- addr = a;
- losum = 0;
- hisum = 0;
- mdsum = 0;
-
- x = 0;
- if((ulong)addr & 1) {
- if(len) {
- hisum += addr[0];
- len--;
- addr++;
- }
- x = 1;
- }
- while(len >= 16) {
- t1 = *(ushort*)(addr+0);
- t2 = *(ushort*)(addr+2); mdsum += t1;
- t1 = *(ushort*)(addr+4); mdsum += t2;
- t2 = *(ushort*)(addr+6); mdsum += t1;
- t1 = *(ushort*)(addr+8); mdsum += t2;
- t2 = *(ushort*)(addr+10); mdsum += t1;
- t1 = *(ushort*)(addr+12); mdsum += t2;
- t2 = *(ushort*)(addr+14); mdsum += t1;
- mdsum += t2;
- len -= 16;
- addr += 16;
- }
- while(len >= 2) {
- mdsum += *(ushort*)addr;
- len -= 2;
- addr += 2;
- }
- if(x) {
- if(len)
- losum += addr[0];
- if(LITTLE)
- losum += mdsum;
- else
- hisum += mdsum;
- } else {
- if(len)
- hisum += addr[0];
- if(LITTLE)
- hisum += mdsum;
- else
- losum += mdsum;
- }
-
- losum += hisum >> 8;
- losum += (hisum & 0xff) << 8;
- while(hisum = losum>>16)
- losum = hisum + (losum & 0xffff);
-
- return ~losum;
-}
-
-static ushort
-ip_csum(uchar *addr)
-{
- int len;
- ulong sum = 0;
-
- len = (addr[0]&0xf)<<2;
-
- while(len > 0) {
- sum += addr[0]<<8 | addr[1] ;
- len -= 2;
- addr += 2;
- }
-
- sum = (sum & 0xffff) + (sum >> 16);
- sum = (sum & 0xffff) + (sum >> 16);
- return (sum^0xffff);
-}
-
-static void
-udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
-{
- Udphdr *uh;
- Etherhdr *ip;
- static Etherpkt pkt;
- int len, ptcllen;
-
-
- uh = (Udphdr*)&pkt;
-
- memset(uh, 0, sizeof(Etherpkt));
- memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
-
- /*
- * UDP portion
- */
- ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
- uh->ttl = 0;
- uh->udpproto = IP_UDPPROTO;
- uh->frag[0] = 0;
- uh->frag[1] = 0;
- hnputs(uh->udpplen, ptcllen);
- hnputl(uh->udpsrc, myaddr.ip);
- hnputs(uh->udpsport, myaddr.port);
- hnputl(uh->udpdst, a->ip);
- hnputs(uh->udpdport, a->port);
- hnputs(uh->udplen, ptcllen);
- uh->udpcksum[0] = 0;
- uh->udpcksum[1] = 0;
- /*dlen = (dlen+1)&~1; */
- hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
-
- /*
- * IP portion
- */
- ip = (Etherhdr*)&pkt;
- len = sizeof(Udphdr)+dlen;
- ip->vihl = IP_VER|IP_HLEN;
- ip->tos = 0;
- ip->ttl = 255;
- hnputs(ip->length, len-ETHER_HDR);
- hnputs(ip->id, Id++);
- ip->frag[0] = 0;
- ip->frag[1] = 0;
- ip->cksum[0] = 0;
- ip->cksum[1] = 0;
- hnputs(ip->cksum, ip_csum(&ip->vihl));
-
- /*
- * Ethernet MAC portion
- */
- hnputs(ip->type, ET_IP);
- memmove(ip->d, a->ea, sizeof(ip->d));
-
- ethertxpkt(ctlrno, &pkt, len, Timeout);
-}
-
-static void
-nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
-{
- int n;
- char buf[128];
-
- buf[0] = 0;
- buf[1] = Tftp_ERROR;
- buf[2] = 0;
- buf[3] = code;
- strcpy(buf+4, msg);
- n = strlen(msg) + 4 + 1;
- udpsend(ctlrno, a, buf, n);
- if(report)
- print("\ntftp: error(%d): %s\n", code, msg);
-}
-
-static int
-udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
-{
- int n, len;
- ushort csm;
- Udphdr *h;
- ulong addr, timo;
- static Etherpkt pkt;
- static int rxactive;
-
- if(rxactive == 0)
- timo = 1000;
- else
- timo = Timeout;
- timo += TK2MS(m->ticks);
- while(timo > TK2MS(m->ticks)){
- n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
- if(n <= 0)
- continue;
-
- h = (Udphdr*)&pkt;
- if(nhgets(h->type) != ET_IP)
- continue;
-
- if(ip_csum(&h->vihl)) {
- print("ip chksum error\n");
- continue;
- }
- if(h->vihl != (IP_VER|IP_HLEN)) {
- print("ip bad vers/hlen\n");
- continue;
- }
-
- if(h->udpproto != IP_UDPPROTO)
- continue;
-
- h->ttl = 0;
- len = nhgets(h->udplen);
- hnputs(h->udpplen, len);
-
- if(CHECKSUM && nhgets(h->udpcksum)) {
- csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
- if(csm != 0) {
- print("udp chksum error csum #%4lux len %d\n", csm, n);
- break;
- }
- }
-
- if(a->port != 0 && nhgets(h->udpsport) != a->port)
- continue;
-
- addr = nhgetl(h->udpsrc);
- if(a->ip != Bcastip && addr != a->ip)
- continue;
-
- len -= UDP_HDRSIZE-UDP_PHDRSIZE;
- if(len > dlen) {
- print("udp: packet too big\n");
- continue;
- }
-
- memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
- a->ip = addr;
- a->port = nhgets(h->udpsport);
- memmove(a->ea, pkt.s, sizeof(a->ea));
-
- rxactive = 1;
- return len;
- }
-
- return 0;
-}
-
-static int tftpblockno;
-
-static int
-tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
-{
- int i, len, rlen, oport;
- char buf[Segsize+2];
-
- buf[0] = 0;
- buf[1] = Tftp_READ;
- len = sprint(buf+2, "%s", name) + 2;
- len += sprint(buf+len+1, "octet") + 2;
-
- oport = a->port;
- for(i = 0; i < 5; i++){
- a->port = oport;
- udpsend(ctlrno, a, buf, len);
- a->port = 0;
- if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
- continue;
-
- switch((tftp->header[0]<<8)|tftp->header[1]){
-
- case Tftp_ERROR:
- print("tftpopen: error (%d): %s\n",
- (tftp->header[2]<<8)|tftp->header[3], tftp->data);
- return -1;
-
- case Tftp_DATA:
- tftpblockno = 1;
- len = (tftp->header[2]<<8)|tftp->header[3];
- if(len != tftpblockno){
- print("tftpopen: block error: %d\n", len);
- nak(ctlrno, a, 1, "block error", 0);
- return -1;
- }
- return rlen-sizeof(tftp->header);
- }
- }
-
- print("tftpopen: failed to connect to server\n");
- return -1;
-}
-
-static int
-tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
-{
- int blockno, len, retry;
- uchar buf[4];
-
- buf[0] = 0;
- buf[1] = Tftp_ACK;
- buf[2] = tftpblockno>>8;
- buf[3] = tftpblockno;
- tftpblockno++;
-
- dlen += sizeof(tftp->header);
-
- retry = 0;
-buggery:
- udpsend(ctlrno, a, buf, sizeof(buf));
-
- if((len = udprecv(ctlrno, a, tftp, dlen)) < dlen){
- print("tftpread: %d != %d\n", len, dlen);
- nak(ctlrno, a, 2, "short read", 0);
- if(retry++ < 5)
- goto buggery;
- return -1;
- }
-
- blockno = (tftp->header[2]<<8)|tftp->header[3];
- if(blockno != tftpblockno){
- print("?");
-
- if(blockno == tftpblockno-1 && retry++ < 8)
- goto buggery;
- print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
- nak(ctlrno, a, 1, "block error", 0);
-
- return -1;
- }
-
- return len-sizeof(tftp->header);
-}
-
-int
-bootp(int ctlrno, char *file)
-{
- Bootp req, rep;
- int i, dlen, segsize, text, data, bss, total;
- uchar *ea, *addr, *p;
- ulong entry;
- Exec *exec;
- char name[128], *filename, *sysname;
-
- if((ea = etheraddr(ctlrno)) == 0){
- print("invalid ctlrno %d\n", ctlrno);
- return -1;
- }
-
- filename = 0;
- sysname = 0;
- if(file && *file){
- strcpy(name, file);
- if(filename = strchr(name, ':')){
- if(filename != name && *(filename-1) != '\\'){
- sysname = name;
- *filename++ = 0;
- }
- }
- else
- filename = name;
- }
-
-
- memset(&req, 0, sizeof(req));
- req.op = Bootrequest;
- req.htype = 1; /* ethernet */
- req.hlen = Eaddrlen; /* ethernet */
- memmove(req.chaddr, ea, Eaddrlen);
-
- myaddr.ip = 0;
- myaddr.port = BPportsrc;
- memmove(myaddr.ea, ea, Eaddrlen);
-
- for(i = 0; i < 10; i++) {
- server.ip = Bcastip;
- server.port = BPportdst;
- memmove(server.ea, broadcast, sizeof(server.ea));
- udpsend(ctlrno, &server, &req, sizeof(req));
- if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
- continue;
- if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
- continue;
- if(rep.htype != 1 || rep.hlen != Eaddrlen)
- continue;
- if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
- break;
- }
- if(i >= 10) {
- print("bootp timed out\n");
- return -1;
- }
-
- if(filename == 0 || *filename == 0)
- filename = rep.file;
-
- if(rep.sname[0] != '\0')
- print("%s ", rep.sname);
- print("(%d.%d.%d.%d!%d): %s\n",
- rep.siaddr[0],
- rep.siaddr[1],
- rep.siaddr[2],
- rep.siaddr[3],
- server.port,
- filename);uartwait();
-
- myaddr.ip = nhgetl(rep.yiaddr);
- myaddr.port = tftpport++;
- server.ip = nhgetl(rep.siaddr);
- server.port = TFTPport;
-
- if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
- return -1;
- exec = (Exec*)(tftpb.data);
- if(dlen < sizeof(Exec) || GLLONG(exec->magic) != Q_MAGIC){
- nak(ctlrno, &server, 0, "bad magic number", 1);
- return -1;
- }
- text = GLLONG(exec->text);
- data = GLLONG(exec->data);
- bss = GLLONG(exec->bss);
- total = text+data+bss;
- entry = GLLONG(exec->entry);
-print("load@%8.8lux: ", XPADDR(entry));uartwait();
- print("%d", text);
-
- addr = (uchar*)XPADDR(entry);
- p = tftpb.data+sizeof(Exec);
- dlen -= sizeof(Exec);
- segsize = text;
- for(;;){
- if(dlen == 0){
- if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
- return -1;
- p = tftpb.data;
- }
- if(segsize <= dlen)
- i = segsize;
- else
- i = dlen;
- memmove(addr, p, i);
-
- addr += i;
- p += i;
- segsize -= i;
- dlen -= i;
-
- if(segsize <= 0){
- if(data == 0)
- break;
- print("+%d", data);
- segsize = data;
- data = 0;
- addr = (uchar*)PGROUND((ulong)addr);
- }
- }
- nak(ctlrno, &server, 3, "ok", 0); /* tftpclose */
- print("+%d=%d\n", bss, total);
- print("entry: 0x%lux\n", entry);
- uartwait();
- scc2stop();
- splhi();
- (*(void(*)(void))(XPADDR(entry)))();
-
- return 0;
-}
--- a/os/boot/rpcg/clock.c
+++ /dev/null
@@ -1,71 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-
-enum {
- Timebase = 4, /* system clock cycles per time base cycle */
-};
-
-void (*archclocktick)(void); /* set by arch*.c when desired */
-
-static ulong clkreload;
-
-void
-delay(int l)
-{
- ulong i, j;
-
- j = m->delayloop;
- while(l-- > 0)
- for(i=0; i < j; i++)
- ;
-}
-
-void
-microdelay(int l)
-{
- ulong i;
-
- l *= m->delayloop;
- l /= 1000;
- if(l <= 0)
- l = 1;
- for(i = 0; i < l; i++)
- ;
-}
-
-void
-clockintr(Ureg*, void*)
-{
- putdec(clkreload);
- m->ticks++;
- checkalarms();
- if(archclocktick != nil)
- archclocktick();
-}
-
-void
-clockinit(void)
-{
- long x;
-
- m->delayloop = m->cpuhz/1000; /* initial estimate */
- do {
- x = gettbl();
- delay(10);
- x = gettbl() - x;
- } while(x < 0);
-
- /*
- * fix count
- */
- m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase);
- if(m->delayloop == 0)
- m->delayloop = 1;
- clkreload = (m->clockgen/Timebase)/HZ-1;
- putdec(clkreload);
-}
--- a/os/boot/rpcg/conf.c
+++ /dev/null
@@ -1,173 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "dosfs.h"
-
-static char *confname[MAXCONF];
-static char *confval[MAXCONF];
-static int nconf;
-
-extern char **ini;
-
-char*
-getconf(char *name)
-{
- int i;
-
- for(i = 0; i < nconf; i++)
- if(strcmp(confname[i], name) == 0)
- return confval[i];
- return 0;
-}
-
-/*
- * read configuration file
- */
-int
-plan9ini(Dos *dos, char *val)
-{
- Dosfile rc;
- int i, n;
- char *cp, *p, *q, *line[MAXCONF];
-
- cp = BOOTARGS;
- if(dos) {
- if(dosstat(dos, *ini, &rc) <= 0)
- return -1;
-
- *cp = 0;
- n = dosread(&rc, cp, BOOTARGSLEN-1);
- if(n <= 0)
- return -1;
- cp[n] = 0;
- } else if(val != nil){
- if(memchr(val, 0, BOOTARGSLEN-1) == nil)
- return -1;
- print("Using flash configuration\n");
- strcpy(cp, val);
- n = strlen(cp);
- }else{
- strcpy(cp, archconfig());
- n = strlen(cp);
- }
-
- /*
- * Make a working copy.
- * We could change this to pass the parsed strings
- * to the booted programme instead of the raw
- * string, then it only gets done once.
- */
- memmove(cp+BOOTARGSLEN, cp, n+1);
- cp += BOOTARGSLEN;
-
- /*
- * Strip out '\r', change '\t' -> ' '.
- */
- p = cp;
- for(q = cp; *q; q++){
- if(*q == '\r')
- continue;
- if(*q == '\t')
- *q = ' ';
- *p++ = *q;
- }
- *p = 0;
- n = getcfields(cp, line, MAXCONF, "\n");
- for(i = 0; i < n; i++){
- cp = strchr(line[i], '=');
- if(cp == 0)
- continue;
- *cp++ = 0;
- if(cp - line[i] >= NAMELEN+1)
- *(line[i]+NAMELEN-1) = 0;
- confname[nconf] = line[i];
- confval[nconf] = cp;
- nconf++;
- }
- return 0;
-}
-
-int
-parseether(uchar *to, char *from)
-{
- char nip[4];
- char *p;
- int i;
-
- p = from;
- while(*p == ' ')
- ++p;
- for(i = 0; i < 6; i++){
- if(*p == 0)
- return -1;
- nip[0] = *p++;
- if(*p == 0)
- return -1;
- nip[1] = *p++;
- nip[2] = 0;
- to[i] = strtoul(nip, 0, 16);
- if(*p == ':')
- p++;
- }
- return 0;
-}
-
-int
-isaconfig(char *class, int ctlrno, ISAConf *isa)
-{
- char cc[NAMELEN], *p, *q, *r;
- int n;
-
- sprint(cc, "%s%d", class, ctlrno);
- for(n = 0; n < nconf; n++){
- if(strncmp(confname[n], cc, NAMELEN))
- continue;
- isa->nopt = 0;
- p = confval[n];
- while(*p){
- while(*p == ' ' || *p == '\t')
- p++;
- if(*p == '\0')
- break;
- if(strncmp(p, "type=", 5) == 0){
- p += 5;
- for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
- if(*p == '\0' || *p == ' ' || *p == '\t')
- break;
- *q = *p++;
- }
- *q = '\0';
- }
- else if(strncmp(p, "port=", 5) == 0)
- isa->port = strtoul(p+5, &p, 0);
- else if(strncmp(p, "irq=", 4) == 0)
- isa->irq = strtoul(p+4, &p, 0);
- else if(strncmp(p, "mem=", 4) == 0)
- isa->mem = strtoul(p+4, &p, 0);
- else if(strncmp(p, "size=", 5) == 0)
- isa->size = strtoul(p+5, &p, 0);
- else if(strncmp(p, "ea=", 3) == 0){
- if(parseether(isa->ea, p+3) == -1)
- memset(isa->ea, 0, 6);
- }
- else if(isa->nopt < NISAOPT){
- r = isa->opt[isa->nopt];
- while(*p && *p != ' ' && *p != '\t'){
- *r++ = *p++;
- if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
- break;
- }
- *r = '\0';
- isa->nopt++;
- }
- while(*p && *p != ' ' && *p != '\t')
- p++;
- }
- return 1;
- }
- return 0;
-}
--- a/os/boot/rpcg/console.c
+++ /dev/null
@@ -1,173 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-static Queue* consiq;
-static Queue* consoq;
-
-void
-bothputs(char *s, int n)
-{
- uartputs(s, n);
- screenputs(s, n);
-}
-
-static void (*consputs)(char*, int) = bothputs; /* or screenputs */
-
-void
-consinit(void)
-{
- char *p;
- int baud, port;
- static int cgadone;
-
- p = getconf("console");
- if(0)
- if(p == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
- consiq = qopen(4*1024, 0, 0, 0);
- consoq = qopen(8*1024, 0, 0, 0);
- consputs = screenputs;
- return;
- }
- if(p!=0 && strstr(p, "lcd") == 0)
- consputs = bothputs;
- else
- consputs = uartputs;
-//consputs = screenputs;
- port = 0;
- if(p)
- port = strtoul(p, 0, 0);
- baud = 0;
- if(p = getconf("baud"))
- baud = strtoul(p, 0, 0);
- if(baud == 0)
- baud = 9600;
- uartspecial(port, baud, &consiq, &consoq, kbdchar);
-}
-
-void
-kbdchar(Queue *q, int c)
-{
- c &= 0x7F;
- if(c == 0x10)
- panic("^p");
- qbputc(q, c);
-}
-
-static int
-getline(char *buf, int size, int dotimeout)
-{
- int c, i=0;
- ulong start;
- char echo;
-
- for (;;) {
- start = m->ticks;
- do{
- if(dotimeout && ((m->ticks - start) > 5*HZ))
- return -2;
- c = qbgetc(consiq);
- }while(c == -1);
- if(c == '\r')
- c = '\n'; /* turn carriage return into newline */
- if(c == '\177')
- c = '\010'; /* turn delete into backspace */
- if(c == '\025')
- echo = '\n'; /* echo ^U as a newline */
- else
- echo = c;
- (*consputs)(&echo, 1);
-
- if(c == '\010'){
- if(i > 0)
- i--; /* bs deletes last character */
- continue;
- }
- /* a newline ends a line */
- if (c == '\n')
- break;
- /* ^U wipes out the line */
- if (c =='\025')
- return -1;
- if(i == size)
- return size;
- buf[i++] = c;
- }
- buf[i] = 0;
- return i;
-}
-
-int
-getstr(char *prompt, char *buf, int size, char *def)
-{
- int len, isdefault;
-
- buf[0] = 0;
- isdefault = (def && *def);
- for (;;) {
- if(isdefault)
- print("%s[default==%s]: ", prompt, def);
- else
- print("%s: ", prompt);
- len = getline(buf, size, isdefault);
- switch(len){
- case -1:
- /* ^U typed */
- continue;
- case -2:
- /* timeout, use default */
- (*consputs)("\n", 1);
- len = 0;
- break;
- default:
- break;
- }
- if(len >= size){
- print("line too long\n");
- continue;
- }
- break;
- }
- if(len == 0 && isdefault)
- strcpy(buf, def);
- return 0;
-}
-
-int
-sprint(char *s, char *fmt, ...)
-{
- return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
-}
-
-int
-print(char *fmt, ...)
-{
- char buf[PRINTSIZE];
- int n;
-
- if(consputs == 0)
- return 0;
- n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
- (*consputs)(buf, n);
- return n;
-}
-
-void
-panic(char *fmt, ...)
-{
- char buf[PRINTSIZE];
- int n;
-
- if(consputs){
- (*consputs)("panic: ", 7);
- n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
- (*consputs)(buf, n);
- (*consputs)("\n", 1);
- }
- spllo();
- for(;;)
- idle();
-}
--- a/os/boot/rpcg/cpm.c
+++ /dev/null
@@ -1,162 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-enum {
- BDSIZE= 1024, /* TO DO: check this */
-};
-
-static Map bdmapv[BDSIZE/sizeof(BD)];
-static RMap bdmap = {"buffer descriptors"};
-
-void
-cpminit(void)
-{
- IMM *io;
-
- io = m->iomem;
- io->sdcr = 1;
- io->lccr &= ~1; /* disable LCD */
- io->pcint = 0; /* disable all port C interrupts */
- io->pcso = 0;
- io->pcdir =0;
- io->pcpar = 0;
- io->pcdat = 0;
- io->papar = 0;
- io->padir = 0;
- io->paodr = 0;
- io->padat = 0;
- io->pbpar = 0;
- io->pbdir = 0;
- io->pbodr = 0;
- io->pbdat = 0;
- eieio();
-
- for(io->cpcr = 0x8001; io->cpcr & 1;) /* reset all CPM channels */
- eieio();
-
- mapinit(&bdmap, bdmapv, sizeof(bdmapv));
- mapfree(&bdmap, DPBASE, BDSIZE);
-}
-
-void
-cpmop(int op, int cno, int param)
-{
- IMM *io;
- int s;
-
- s = splhi();
- io = m->iomem;
- eieio();
- while(io->cpcr & 1)
- eieio();
- io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1;
- eieio();
- while(io->cpcr & 1)
- eieio();
- splx(s);
-}
-
-/*
- * connect SCCx clocks in NSMI mode (x=1 for USB)
- */
-void
-sccnmsi(int x, int rcs, int tcs)
-{
- IMM *io;
- ulong v;
- int sh;
-
- sh = (x-1)*8; /* each SCCx field in sicr is 8 bits */
- v = (((rcs&7)<<3) | (tcs&7)) << sh;
- io = ioplock();
- io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
- iopunlock();
-}
-
-void
-scc2stop(void)
-{
- SCC *scc;
-
- scc = IOREGS(0xA20, SCC);
- if(scc->gsmrl & (3<<4)){
- cpmop(GracefulStopTx, SCC2ID, 0);
- cpmop(CloseRxBD, SCC2ID, 0);
- delay(1);
- scc->gsmrl &= ~(3<<4); /* disable current use */
- archetherdisable(SCC2ID);
- }
-}
-
-BD *
-bdalloc(int n)
-{
- ulong a;
-
- a = mapalloc(&bdmap, 0, n*sizeof(BD), 0);
- if(a == 0)
- panic("bdalloc");
- return KADDR(a);
-}
-
-void
-bdfree(BD *b, int n)
-{
- if(b){
- eieio();
- mapfree(&bdmap, PADDR(b), n*sizeof(BD));
- }
-}
-
-/*
- * initialise receive and transmit buffer rings.
- */
-int
-ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
-{
- int i, x;
-
- /* the ring entries must be aligned on sizeof(BD) boundaries */
- r->nrdre = nrdre;
- if(r->rdr == nil)
- r->rdr = bdalloc(nrdre);
- /* the buffer size must align with cache lines since the cache doesn't snoop */
- bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1);
- if(r->rrb == nil)
- r->rrb = malloc(nrdre*bufsize);
- if(r->rdr == nil || r->rrb == nil)
- return -1;
- dcflush(r->rrb, nrdre*bufsize);
- x = PADDR(r->rrb);
- for(i = 0; i < nrdre; i++){
- r->rdr[i].length = 0;
- r->rdr[i].addr = x;
- r->rdr[i].status = BDEmpty|BDInt;
- x += bufsize;
- }
- r->rdr[i-1].status |= BDWrap;
- r->rdrx = 0;
-
- r->ntdre = ntdre;
- if(r->tdr == nil)
- r->tdr = bdalloc(ntdre);
- if(r->txb == nil)
- r->txb = malloc(ntdre*sizeof(Block*));
- if(r->tdr == nil || r->txb == nil)
- return -1;
- for(i = 0; i < ntdre; i++){
- r->txb[i] = nil;
- r->tdr[i].addr = 0;
- r->tdr[i].length = 0;
- r->tdr[i].status = 0;
- }
- r->tdr[i-1].status |= BDWrap;
- r->tdrh = 0;
- r->tdri = 0;
- r->ntq = 0;
- return 0;
-}
--- a/os/boot/rpcg/crc32.c
+++ /dev/null
@@ -1,42 +1,0 @@
-#include "boot.h"
-
-/*
- * from Rob Warnock
- */
-static ulong crc32tab[256]; /* initialised on first call to crc32 */
-
-enum {
- CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
-};
-
-/*
- * Build auxiliary table for parallel byte-at-a-time CRC-32.
- */
-static void
-initcrc32(void)
-{
- int i, j;
- ulong c;
-
- for(i = 0; i < 256; i++) {
- for(c = i << 24, j = 8; j > 0; j--)
- if(c & (1<<31))
- c = (c<<1) ^ CRC32POLY;
- else
- c <<= 1;
- crc32tab[i] = c;
- }
-}
-
-ulong
-crc32(void *buf, int n, ulong crc)
-{
- uchar *p;
-
- if(crc32tab[1] == 0)
- initcrc32();
- crc = ~crc;
- for(p = buf; --n >= 0;)
- crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
- return ~crc;
-}
--- a/os/boot/rpcg/dat.h
+++ /dev/null
@@ -1,217 +1,0 @@
-typedef struct Alarm Alarm;
-typedef struct Block Block;
-typedef struct IMM IMM;
-typedef struct Queue Queue;
-
-typedef struct List {
- void *next;
-} List;
-
-typedef struct {
- int fake;
- int pri;
-} Lock;
-#define lock(x)
-#define unlock(x)
-
-struct Alarm {
- List;
- int busy;
- long dt;
- void (*f)(Alarm*);
- void *arg;
-};
-
-enum {
- Eaddrlen = 6,
- ETHERMINTU = 60, /* minimum transmit size */
- ETHERMAXTU = 1514, /* maximum transmit size */
- ETHERHDRSIZE = 14, /* size of an ethernet header */
-
- MaxEther = 4,
-};
-
-typedef struct {
- uchar d[Eaddrlen];
- uchar s[Eaddrlen];
- uchar type[2];
- uchar data[1500];
- uchar crc[4];
-} Etherpkt;
-
-extern uchar broadcast[Eaddrlen];
-
-enum {
- Npart = 20+2, /* 8 sub partitions, disk, and partition */
- Maxxfer = 16*1024, /* maximum transfer size/cmd */
-};
-
-typedef struct {
- ulong start;
- ulong end;
- char name[NAMELEN+1];
-} Partition;
-
-typedef struct {
- int online;
- int npart; /* number of real partitions */
- Partition p[Npart];
- ulong offset;
- Partition *current; /* current partition */
-
- ulong cap; /* total bytes */
- int bytes; /* bytes/sector */
- int sectors; /* sectors/track */
- int heads; /* heads/cyl */
- long cyl; /* cylinders/drive */
-
- char lba; /* true if drive has logical block addressing */
- char multi; /* non-zero if drive does multiple block xfers */
-} Disc;
-
-enum {
- ScsiTestunit = 0x00,
- ScsiExtsens = 0x03,
- ScsiInquiry = 0x12,
- ScsiModesense = 0x1a,
- ScsiStartunit = 0x1B,
- ScsiStopunit = 0x1B,
- ScsiGetcap = 0x25,
- ScsiRead = 0x08,
- ScsiWrite = 0x0a,
- ScsiExtread = 0x28,
- ScsiExtwrite = 0x2a,
-
- /* data direction */
- ScsiIn = 1,
- ScsiOut = 0,
-};
-
-typedef struct Scsibuf Scsibuf;
-typedef struct Scsibuf {
- void* virt;
- void* phys;
- Scsibuf* next;
-};
-
-typedef struct Scsidata {
- uchar* base;
- uchar* lim;
- uchar* ptr;
-} Scsidata;
-
-typedef struct Ureg Ureg;
-
-typedef struct Scsi {
- ulong pid;
- ushort target;
- ushort lun;
- ushort rflag;
- ushort status;
- Scsidata cmd;
- Scsidata data;
- Scsibuf* b;
- uchar* save;
- uchar cmdblk[16];
-} Scsi;
-
-typedef struct Segdesc {
- ulong d0;
- ulong d1;
-} Segdesc;
-
-typedef struct Mach {
- ulong ticks; /* of the clock since boot time */
- ulong delayloop;
- long cpuhz; /* general system clock (cycles) */
- long clockgen; /* clock generator frequency (cycles) */
- ulong cpupvr; /* cpu type in processor version register */
- ulong cputype; /* cpu variant in BCD (eg, 0x823xx) */
- void* alarm; /* alarms bound to this clock */
- ulong* bcsr;
- IMM* iomem;
-} Mach;
-
-/* Mach.cputype */
-#define MPCREV(x) ((x) & 0xFF)
-#define MPCMODEL(x) (((x)>>8) & 0xFFF)
-#define MPCFAMILY(x) (((x)>>24) & 0x0F)
-
-
-extern Mach *m;
-
-#define Q_MAGIC ((((4*21)+0)*21)+7)
-
-typedef struct Exec Exec;
-struct Exec
-{
- uchar magic[4]; /* magic number */
- uchar text[4]; /* size of text segment */
- uchar data[4]; /* size of initialized data */
- uchar bss[4]; /* size of uninitialized data */
- uchar syms[4]; /* size of symbol table */
- uchar entry[4]; /* entry point */
- uchar spsz[4]; /* size of sp/pc offset table */
- uchar pcsz[4]; /* size of pc/line number table */
-};
-
-/*
- * bootline passed by boot program
- */
-#define BOOTLINE ((char *)0x200000-150)
-
-/*
- * Where we leave configuration info.
- */
-#define BOOTARGS ((char*)(0x200000))
-#define BOOTARGSLEN 1024
-#define MAXCONF 32
-
-/*
- * a parsed plan9.ini line
- */
-#define ISAOPTLEN 16
-#define NISAOPT 8
-
-typedef struct ISAConf {
- char type[NAMELEN];
- ulong port;
- ulong irq;
- ulong mem;
- ulong size;
- uchar ea[6];
-
- int nopt;
- char opt[NISAOPT][ISAOPTLEN];
-} ISAConf;
-
-typedef struct {
- int size;
- ulong addr;
-} Map;
-
-typedef struct {
- char* name;
- Map* map;
- Map* mapend;
-
- Lock;
-} RMap;
-
-typedef struct PCIcfg PCIcfg;
-
-extern uchar* vgamem;
-
-struct Block {
- uchar *rp;
- uchar *wp;
- uchar *lim;
- uchar *data;
- Block* next;
- ulong magic;
-};
-#define BLEN(b) ((b)->wp-(b)->rp)
-
-typedef struct QLock {
- int dummy;
-} QLock;
--- a/os/boot/rpcg/defont0.c
+++ /dev/null
@@ -1,216 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <libg.h>
-#include <gnot.h>
-
-
-
-static ulong bits0[] = {
- 0x907070f0, 0xf0f07000, 0xf0888888, 0xf8707070, 0xe0e0e0e0, 0xe09070f0, 0x70f870f0, 0xf870f088,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000e0,
- 0xd0808080, 0x80808800, 0x8888c888, 0x80888888, 0x90909090, 0x90d08080, 0x80808080, 0x80888888,
- 0x00000000, 0x08000000, 0x0c300000, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000003c, 0xc03c0000,
- 0x00006000, 0x06001e00, 0x60181860, 0x78000000, 0x00000000, 0x00000000, 0x0000001c, 0x18380090,
- 0xb06060e0, 0xe0e0f800, 0xf088a888, 0x80808080, 0x90909090, 0x90b060e0, 0x808060e0, 0x80808888,
- 0x00182428, 0x3e707018, 0x18180000, 0x00000006, 0x3c183c3c, 0x1c3e3c7e, 0x3c3c0000, 0x0200403c,
- 0x3c187c1e, 0x787e7e1e, 0x663c7c66, 0x6066623c, 0x7c3c7c3c, 0x7e6266c2, 0x66667e30, 0xc00c1000,
- 0x08006000, 0x06003000, 0x60181860, 0x18000000, 0x00000000, 0x10000000, 0x00000030, 0x180c0090,
- 0x90101080, 0x80808818, 0x88f8a888, 0xe0807070, 0xe0e0e0e0, 0xe0901080, 0x70e01080, 0xe098f088,
- 0x00182428, 0x6adad818, 0x18181000, 0x0000000c, 0x66386666, 0x2c3e667e, 0x66660000, 0x06006066,
- 0x42186632, 0x6c606032, 0x66181864, 0x60667224, 0x66246666, 0x186262da, 0x62620630, 0x600c3800,
- 0x10006000, 0x06003000, 0x60000060, 0x18000000, 0x00000000, 0x30000000, 0x00000030, 0x180c00e0,
- 0x00e0e0f0, 0xf0f00018, 0x88889850, 0x80880808, 0x201c1c1c, 0x1c00e0f0, 0x0080e0f0, 0x80888888,
- 0x00182428, 0x68dad808, 0x300c5418, 0x0000000c, 0x66580606, 0x2c206002, 0x66661818, 0x0cfe3006,
- 0x9e2c6660, 0x66606060, 0x6618186c, 0x60667266, 0x66666660, 0x186262da, 0x36660c30, 0x600c2800,
- 0x103c6c3c, 0x3e3c7e3e, 0x6c787866, 0x18d46c3c, 0x6c3e763c, 0x7e6666c2, 0x66667e18, 0x18180000,
- 0x44180000, 0x18241c24, 0xf0888820, 0x8070f0f0, 0x20202020, 0x201c243e, 0x1cf8241c, 0x80708870,
- 0x0018247c, 0x78745008, 0x300c3818, 0x00000018, 0x66180606, 0x4c206006, 0x76661818, 0x18fe180c,
- 0xb62c6660, 0x66606060, 0x66181868, 0x607e5a66, 0x66666470, 0x186266da, 0x34340c30, 0x300c6c00,
- 0x18667666, 0x66663066, 0x76181864, 0x18fe7666, 0x76663666, 0x306662da, 0x62620608, 0x1810323c,
- 0x44247c7c, 0x24342042, 0x00000000, 0x00000000, 0x20202020, 0x20222408, 0x22002420, 0x00000000,
- 0x00180028, 0x3c287610, 0x300cee7e, 0x00fe0018, 0x66180c18, 0x4c3c7c0c, 0x3c3e0000, 0x30000c18,
- 0xb62c7c60, 0x667c7c6e, 0x7e181878, 0x605a5a66, 0x6466783c, 0x186234da, 0x18341830, 0x300c4400,
- 0x18066660, 0x66663066, 0x66181868, 0x18d66666, 0x66663860, 0x306662da, 0x34620c30, 0x180c5a20,
- 0x44241010, 0x242c2042, 0x0e3e103e, 0x3e3c1c3e, 0x3c1c1c1c, 0x1c3e1c08, 0x3e222418, 0x0e0e0e0e,
- 0x0008007c, 0x1e5cdc00, 0x300c387e, 0x00fe0030, 0x66181806, 0x7e066618, 0x6e060000, 0x18001818,
- 0xb67e6660, 0x66606066, 0x6618186c, 0x605a4e66, 0x78666c0e, 0x1862346c, 0x2c183030, 0x180c4400,
- 0x003e6660, 0x667e3066, 0x66181878, 0x18d66666, 0x6666303c, 0x306634da, 0x18341808, 0x18104c38,
- 0x3c181010, 0x18241c42, 0x11081008, 0x20222208, 0x00000000, 0x00220408, 0x22361804, 0x11111111,
- 0x00000028, 0x16b6cc00, 0x300c5418, 0x00000030, 0x66183006, 0x7e066618, 0x66060000, 0x0cfe3000,
- 0x9a466660, 0x66606066, 0x6618186c, 0x605a4e66, 0x60666606, 0x1862346c, 0x6c183030, 0x180c0000,
- 0x00666660, 0x66603066, 0x6618186c, 0x18d66666, 0x66663006, 0x3066346c, 0x2c343018, 0x18180020,
- 0x00091010, 0x000e0942, 0x10081008, 0x20222208, 0x0f06060f, 0x0a09041e, 0x002a0e38, 0x10101010,
- 0x00180028, 0x56b6cc00, 0x300c1018, 0x18001860, 0x66187e66, 0x0c666630, 0x66661818, 0x06fe6018,
- 0x40466632, 0x6c606036, 0x66181866, 0x605a4624, 0x60246666, 0x1834186c, 0x46186030, 0x0c0c0000,
- 0x006e6666, 0x6e66306e, 0x66181866, 0x18d66666, 0x666e3066, 0x306e186c, 0x46186030, 0x180c003c,
- 0x08090909, 0x1f110aff, 0x0e081008, 0x382c2208, 0x08020901, 0x0a0a0911, 0x09220907, 0x0e0e0e0e,
- 0x00180028, 0x7c1c7600, 0x18180000, 0x18001860, 0x3c7e7e3c, 0x0c3c3c30, 0x3c3c1818, 0x02004018,
- 0x3e467c1e, 0x787e601e, 0x663c1866, 0x7e42463c, 0x603c663c, 0x1818186c, 0x66187e30, 0x0c0c0000,
- 0x00367c3c, 0x363c7c36, 0x667e1866, 0x7ed6663c, 0x7c367c3c, 0x1e36186c, 0x66187e30, 0x180c0008,
- 0x080f0606, 0x04110c18, 0x01081008, 0x20222208, 0x0e020203, 0x0a0c0d1e, 0x0d220e08, 0x01010101,
- 0x00000000, 0x10000000, 0x18180000, 0x080000c0, 0x00000000, 0x00000000, 0x00000008, 0x00000000,
- 0x00000000, 0x00000000, 0x00001800, 0x00000000, 0x000c0000, 0x00000000, 0x00000030, 0x060c00fe,
- 0x00000000, 0x00000006, 0x00001800, 0x00000000, 0x60060000, 0x00000000, 0x0010001c, 0x18380008,
- 0x08090606, 0x040e0a18, 0x11081f08, 0x20221c3e, 0x08020401, 0x0f0a0b11, 0x0b220908, 0x11111111,
- 0x00000000, 0x00000000, 0x0c300000, 0x080000c0, 0x00000000, 0x00000000, 0x00000008, 0x00000000,
- 0x00000000, 0x00000000, 0x00007000, 0x00000000, 0x00060000, 0x00000000, 0x0000003c, 0x063c0000,
- 0x00000000, 0x00000066, 0x00001800, 0x00000000, 0x60060000, 0x00000000, 0x00300000, 0x00000008,
- 0x0f090909, 0x04030900, 0x0e000000, 0x00000000, 0x0f0f0f0f, 0x0209091e, 0x09000f07, 0x0e0e0e0e,
- 0x00000000, 0x00000000, 0x00000000, 0x10000000, 0x00000000, 0x00000000, 0x00000010, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x0000003c, 0x00007000, 0x00000000, 0x60060000, 0x00000000, 0x00600000, 0x0000000f,
-
-};
-
-static GBitmap strike0 = {
- bits0,
- 0,
- 32,
- 0,
- {0, 0, 1024, 14},
- {0, 0, 1024, 14},
-};
-
-static Fontchar info0[] = {
- { 0, 0, 14, 0, 8 },
- { 8, 0, 14, 0, 8 },
- { 16, 0, 14, 0, 8 },
- { 24, 0, 14, 0, 8 },
- { 32, 0, 14, 0, 8 },
- { 40, 0, 14, 0, 8 },
- { 48, 0, 14, 0, 8 },
- { 56, 0, 14, 0, 8 },
- { 64, 0, 14, 0, 8 },
- { 72, 0, 14, 0, 8 },
- { 80, 0, 14, 0, 8 },
- { 88, 0, 14, 0, 8 },
- { 96, 0, 14, 0, 8 },
- { 104, 0, 14, 0, 8 },
- { 112, 0, 14, 0, 8 },
- { 120, 0, 14, 0, 8 },
- { 128, 0, 14, 0, 8 },
- { 136, 0, 14, 0, 8 },
- { 144, 0, 14, 0, 8 },
- { 152, 0, 14, 0, 8 },
- { 160, 0, 14, 0, 8 },
- { 168, 0, 14, 0, 8 },
- { 176, 0, 14, 0, 8 },
- { 184, 0, 14, 0, 8 },
- { 192, 0, 14, 0, 8 },
- { 200, 0, 14, 0, 8 },
- { 208, 0, 14, 0, 8 },
- { 216, 0, 14, 0, 8 },
- { 224, 0, 14, 0, 8 },
- { 232, 0, 14, 0, 8 },
- { 240, 0, 14, 0, 8 },
- { 248, 0, 14, 0, 8 },
- { 256, 0, 0, 0, 8 },
- { 264, 2, 11, 0, 8 },
- { 272, 2, 6, 0, 8 },
- { 280, 2, 11, 0, 8 },
- { 288, 1, 12, 0, 8 },
- { 296, 2, 11, 0, 8 },
- { 304, 2, 11, 0, 8 },
- { 312, 2, 7, 0, 8 },
- { 320, 1, 13, 0, 8 },
- { 328, 1, 13, 0, 8 },
- { 336, 3, 10, 0, 8 },
- { 344, 4, 10, 0, 8 },
- { 352, 9, 14, 0, 8 },
- { 360, 6, 8, 0, 8 },
- { 368, 9, 11, 0, 8 },
- { 376, 1, 13, 0, 8 },
- { 384, 2, 11, 0, 8 },
- { 392, 2, 11, 0, 8 },
- { 400, 2, 11, 0, 8 },
- { 408, 2, 11, 0, 8 },
- { 416, 2, 11, 0, 8 },
- { 424, 2, 11, 0, 8 },
- { 432, 2, 11, 0, 8 },
- { 440, 2, 11, 0, 8 },
- { 448, 2, 11, 0, 8 },
- { 456, 2, 11, 0, 8 },
- { 464, 4, 11, 0, 8 },
- { 472, 4, 14, 0, 8 },
- { 480, 2, 11, 0, 8 },
- { 488, 4, 10, 0, 8 },
- { 496, 2, 11, 0, 8 },
- { 504, 2, 11, 0, 8 },
- { 512, 2, 11, 0, 8 },
- { 520, 2, 11, 0, 8 },
- { 528, 2, 11, 0, 8 },
- { 536, 2, 11, 0, 8 },
- { 544, 2, 11, 0, 8 },
- { 552, 2, 11, 0, 8 },
- { 560, 2, 11, 0, 8 },
- { 568, 2, 11, 0, 8 },
- { 576, 2, 11, 0, 8 },
- { 584, 2, 11, 0, 8 },
- { 592, 2, 13, 0, 8 },
- { 600, 2, 11, 0, 8 },
- { 608, 2, 11, 0, 8 },
- { 616, 2, 11, 0, 8 },
- { 624, 2, 11, 0, 8 },
- { 632, 2, 11, 0, 8 },
- { 640, 2, 11, 0, 8 },
- { 648, 2, 13, 0, 8 },
- { 656, 2, 11, 0, 8 },
- { 664, 2, 11, 0, 8 },
- { 672, 2, 11, 0, 8 },
- { 680, 2, 11, 0, 8 },
- { 688, 2, 11, 0, 8 },
- { 696, 2, 11, 0, 8 },
- { 704, 2, 11, 0, 8 },
- { 712, 2, 11, 0, 8 },
- { 720, 2, 11, 0, 8 },
- { 728, 1, 13, 0, 8 },
- { 736, 1, 13, 0, 8 },
- { 744, 1, 13, 0, 8 },
- { 752, 2, 8, 0, 8 },
- { 760, 11, 12, 0, 8 },
- { 768, 2, 7, 0, 8 },
- { 776, 4, 11, 0, 8 },
- { 784, 1, 11, 0, 8 },
- { 792, 4, 11, 0, 8 },
- { 800, 1, 11, 0, 8 },
- { 808, 4, 11, 0, 8 },
- { 816, 1, 11, 0, 8 },
- { 824, 4, 14, 0, 8 },
- { 832, 1, 11, 0, 8 },
- { 840, 1, 11, 0, 8 },
- { 848, 1, 14, 0, 8 },
- { 856, 1, 11, 0, 8 },
- { 864, 1, 11, 0, 8 },
- { 872, 4, 11, 0, 8 },
- { 880, 4, 11, 0, 8 },
- { 888, 4, 11, 0, 8 },
- { 896, 4, 14, 0, 8 },
- { 904, 4, 14, 0, 8 },
- { 912, 4, 11, 0, 8 },
- { 920, 4, 11, 0, 8 },
- { 928, 2, 11, 0, 8 },
- { 936, 4, 11, 0, 8 },
- { 944, 4, 11, 0, 8 },
- { 952, 4, 11, 0, 8 },
- { 960, 4, 11, 0, 8 },
- { 968, 4, 14, 0, 8 },
- { 976, 4, 11, 0, 8 },
- { 984, 1, 12, 0, 8 },
- { 992, 1, 12, 0, 8 },
- { 1000, 1, 12, 0, 8 },
- { 1008, 5, 8, 0, 8 },
- { 1016, 0, 14, 0, 8 },
- { 1024, 0, 14, 0, 8 },
- { 0, 0, 0, 0, 0 }
-};
-
-GSubfont defont0 = {
- 129,
- 14,
- 2,
- info0,
- &strike0,
-};
--- a/os/boot/rpcg/devether.c
+++ /dev/null
@@ -1,157 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-static Ctlr ether[MaxEther];
-
-static struct {
- char *type;
- int (*reset)(Ctlr*);
-} cards[] = {
- { "SCC", sccethreset, },
- { "SCC2", sccethreset, },
- { 0, }
-};
-
-int
-etherinit(void)
-{
- Ctlr *ctlr;
- int ctlrno, i, mask, n;
-
- mask = 0;
- for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
- ctlr = ðer[ctlrno];
- memset(ctlr, 0, sizeof(Ctlr));
- if(archether(ctlrno, &ctlr->card) <= 0)
- continue;
- for(n = 0; cards[n].type; n++){
- if(strcmp(cards[n].type, ctlr->card.type))
- continue;
- ctlr->ctlrno = ctlrno;
- if((*cards[n].reset)(ctlr))
- break;
-
- ctlr->iq = qopen(16*1024, 1, 0, 0);
- ctlr->oq = qopen(16*1024, 1, 0, 0);
-
- ctlr->present = 1;
- mask |= 1<<ctlrno;
-
- print("ether%d: %s: port 0x%luX irq %d",
- ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
- if(ctlr->card.mem)
- print(" addr 0x%luX", PADDR(ctlr->card.mem));
- if(ctlr->card.size)
- print(" size 0x%luX", ctlr->card.size);
- print(":");
- for(i = 0; i < sizeof(ctlr->card.ea); i++)
- print(" %2.2uX", ctlr->card.ea[i]);
- print("\n"); uartwait();
- setvec(VectorPIC + ctlr->card.irq, ctlr->card.intr, ctlr);
- break;
- }
- }
-
- return mask;
-}
-
-static Ctlr*
-attach(int ctlrno)
-{
- Ctlr *ctlr;
-
- if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
- return 0;
-
- ctlr = ðer[ctlrno];
- if(ctlr->present == 1){
- ctlr->present = 2;
- (*ctlr->card.attach)(ctlr);
- }
-
- return ctlr;
-}
-
-uchar*
-etheraddr(int ctlrno)
-{
- Ctlr *ctlr;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- return ctlr->card.ea;
-}
-
-int
-etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
-{
- int n;
- Ctlr *ctlr;
- Block *b;
- ulong start;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- start = m->ticks;
- while((b = qget(ctlr->iq)) == 0){
- if(TK2MS(m->ticks - start) >= timo){
- /*
- print("ether%d: rx timeout\n", ctlrno);
- */
- return 0;
- }
- }
-
- n = BLEN(b);
- memmove(pkt, b->rp, n);
- freeb(b);
-
- return n;
-}
-
-int
-etheriq(Ctlr *ctlr, Block *b, int freebp)
-{
- if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0 &&
- memcmp(((Etherpkt*)b->rp)->d, broadcast, Eaddrlen) != 0){
- if(freebp)
- freeb(b);
- return 0;
- }
- qbwrite(ctlr->iq, b);
- return 1;
-}
-
-int
-ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
-{
- Ctlr *ctlr;
- Block *b;
- int s;
-
- if((ctlr = attach(ctlrno)) == 0)
- return 0;
-
- if(qlen(ctlr->oq) > 16*1024){
- print("ether%d: tx queue full\n", ctlrno);
- return 0;
- }
- b = iallocb(sizeof(Etherpkt));
- memmove(b->wp, pkt, len);
- memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
- b->wp += len;
- qbwrite(ctlr->oq, b);
- s = splhi();
- (*ctlr->card.transmit)(ctlr);
- splx(s);
-
- return 1;
-}
--- a/os/boot/rpcg/devuart.c
+++ /dev/null
@@ -1,230 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-/*
- * SMC1 in UART mode
- */
-
-typedef struct Uartsmc Uartsmc;
-struct Uartsmc {
- IOCparam;
- ushort maxidl;
- ushort idlc;
- ushort brkln;
- ushort brkec;
- ushort brkcr;
- ushort rmask;
-};
-
-typedef struct Uart Uart;
-struct Uart
-{
- int port;
- int setup;
- uchar txbusy;
-
- Queue* iq;
- Queue* oq;
- void (*rx)(Queue*, int);
- void (*boot)(uchar*, int);
-
- ulong frame;
- ulong overrun;
- uchar rxbuf[128];
- char txbuf[16];
- BD* rxb;
- BD* txb;
-};
-
-Uart uart[1];
-int predawn = 1;
-
-static void uartintr(Ureg*, void*);
-static void uartkick(void*);
-
-static int
-baudgen(int baud)
-{
- int d;
-
- d = ((m->cpuhz/baud)+8)>>4;
- if(d >= (1<<12))
- return ((d+15)>>3)|1;
- return d<<1;
-}
-
-static void
-smcsetup(Uart *up, int baud)
-{
- IMM *io;
- Uartsmc *p;
- BD *bd;
- SMC *smc;
-
- archenableuart(SMC1ID, 0);
- io = m->iomem;
- io->pbpar |= IBIT(24)|IBIT(25); /* enable SMC1 TX/RX */
- io->pbdir &= ~(IBIT(24)|IBIT(25));
- io->brgc1 = baudgen(baud) | BaudEnable;
- io->simode &= ~0xF000; /* SMC1 to NMSI mode, Tx/Rx clocks are BRG1 */
-
- bd = bdalloc(1);
- p = (Uartsmc*)KADDR(SMC1P);
- p->rbase = (ushort)bd;
- up->rxb = bd;
- bd->status = BDEmpty|BDWrap|BDInt;
- bd->length = 0;
- bd->addr = PADDR(up->rxbuf);
- bd = bdalloc(1);
- p->tbase = (ushort)bd;
- up->txb = bd;
- bd->status = BDWrap|BDInt;
- bd->length = 0;
- bd->addr = PADDR(up->txbuf);
-
- cpmop(InitRxTx, SMC1ID, 0);
-
- /* protocol parameters */
- p->rfcr = 0x18;
- p->tfcr = 0x18;
- p->mrblr = 1;
- p->maxidl = 1;
- p->brkln = 0;
- p->brkec = 0;
- p->brkcr = 1;
- smc = IOREGS(0xA80, SMC);
- smc->smce = 0xff; /* clear events */
- smc->smcm = 0x17; /* enable all possible interrupts */
- setvec(VectorCPIC+4, uartintr, up);
- smc->smcmr = 0x4820; /* 8-bit mode, no parity, 1 stop bit, UART mode, ... */
- smc->smcmr |= 3; /* enable rx/tx */
-}
-
-static void
-uartintr(Ureg*, void *arg)
-{
- Uart *up;
- int ch, i;
- BD *bd;
- SMC *smc;
- Block *b;
-
- up = arg;
- smc = IOREGS(0xA80, SMC);
- smc->smce = 0xff; /* clear all events */
- if((bd = up->rxb) != nil && (bd->status & BDEmpty) == 0){
- if(up->iq != nil && bd->length > 0){
- if(up->boot != nil){
- up->boot(up->rxbuf, bd->length);
- }else if(up->rx != nil){
- for(i=0; i<bd->length; i++){
- ch = up->rxbuf[i];
- up->rx(up->iq, ch);
- }
- }else{
- b = iallocb(bd->length);
- memmove(b->wp, up->rxbuf, bd->length);
- b->wp += bd->length;
- qbwrite(up->iq, b);
- }
- }
- bd->status |= BDEmpty|BDInt;
- } else if((bd = up->txb) != nil && (bd->status & BDReady) == 0){
- ch = -1;
- if(up->oq)
- ch = qbgetc(up->oq);
- if(ch != -1){
- up->txbuf[0] = ch;
- bd->length = 1;
- bd->status |= BDReady;
- }else
- up->txbusy = 0;
- }
- /* TO DO: modem status, errors, etc */
-}
-
-static void
-uartkick(void *arg)
-{
- Uart *up = arg;
- int s, c, i;
-
- s = splhi();
- while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1){
- if(predawn){
- while(up->txb->status & BDReady)
- ;
- } else {
- for(i = 0; i < 100; i++){
- if((up->txb->status & BDReady) == 0)
- break;
- delay(1);
- }
- }
- up->txbuf[0] = c;
- up->txb->length = 1;
- up->txb->status |= BDReady;
- up->txbusy = !predawn;
- }
- splx(s);
-}
-
-void
-uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue*,int))
-{
- Uart *up = &uart[0];
-
- if(up->setup)
- return;
- up->setup = 1;
-
- *iq = up->iq = qopen(4*1024, 0, 0, 0);
- *oq = up->oq = qopen(16*1024, 0, uartkick, up);
- up->rx = rx;
- USED(port);
- up->port = SMC1ID;
- if(baud == 0)
- baud = 9600;
- smcsetup(up, baud);
- /* if using SCCn's UART, would also set DTR and RTS, but SMC doesn't use them */
-}
-
-void
-uartsetboot(void (*f)(uchar*, int))
-{
- uart[0].boot = f;
-}
-
-void
-uartputs(char *s, int n)
-{
- Uart *up = &uart[0];
- Block *b;
- int nl;
- char *p;
-
- nl = 0;
- for(p = s; p < s+n; p++)
- if(*p == '\n')
- nl++;
- b = iallocb(n+nl);
- while(n--){
- if(*s == '\n')
- *b->wp++ = '\r';
- *b->wp++ = *s++;
- }
- qbwrite(up->oq, b);
-}
-
-void
-uartwait(void)
-{
- Uart *up = &uart[0];
-
- while(up->txbusy)
- ;
-}
--- a/os/boot/rpcg/dload.c
+++ /dev/null
@@ -1,103 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-static char *kernelfile = "/power/ipaq";
-ulong crc32(void *buf, int n, ulong crc);
-
-void
-main(int argc, char **argv)
-{
- int ifd, n;
- char buf[64], reply[1];
- int i, execsize;
- Fhdr f;
- ulong csum;
-
- ARGBEGIN{
- }ARGEND
- ifd = open(kernelfile, OREAD);
- if(ifd < 0){
- fprint(2, "dload: can't open %s: %r\n", kernelfile);
- exits("open");
- }
- i = 0;
- if(crackhdr(ifd, &f) == 0){
- fprint(2, "dload: not an executable file: %r\n");
- exits("format");
- }
- if(f.magic != Q_MAGIC){
- fprint(2, "dload: not a powerpc executable\n");
- exits("format");
- }
- execsize = f.txtsz + f.datsz + f.txtoff;
- seek(ifd, 0, 0);
- csum = ~0;
- while(execsize > 0 && (n = read(ifd, buf, sizeof(buf))) > 0){
- if(n > execsize)
- n = execsize;
- for(;;){
- if(write(1, buf, sizeof(buf)) != sizeof(buf)){ /* always writes full buffer */
- fprint(2, "dload: write error: %r\n");
- exits("write");
- }
- if(read(0, reply, 1) != 1){
- fprint(2, "dload: bad reply\n");
- exits("read");
- }
- if(reply[0] != 'n')
- break;
- fprint(2, "!");
- }
- if(reply[0] != 'y'){
- fprint(2, "dload: bad ack: %c\n", reply[0]);
- exits("reply");
- }
- if(++i%10 == 0)
- fprint(2, ".");
- execsize -= n;
- }
- exits(0);
-}
-
-/*
- * from Rob Warnock
- */
-static ulong crc32tab[256]; /* initialised on first call to crc32 */
-
-enum {
- CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
-};
-
-/*
- * Build auxiliary table for parallel byte-at-a-time CRC-32.
- */
-static void
-initcrc32(void)
-{
- int i, j;
- ulong c;
-
- for(i = 0; i < 256; i++) {
- for(c = i << 24, j = 8; j > 0; j--)
- if(c & (1<<31))
- c = (c<<1) ^ CRC32POLY;
- else
- c <<= 1;
- crc32tab[i] = c;
- }
-}
-
-ulong
-crc32(void *buf, int n, ulong crc)
-{
- uchar *p;
-
- if(crc32tab[1] == 0)
- initcrc32();
- crc = ~crc;
- for(p = buf; --n >= 0;)
- crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
- return ~crc;
-}
--- a/os/boot/rpcg/donprint.c
+++ /dev/null
@@ -1,332 +1,0 @@
-#include "u.h"
-#include "lib.h"
-
-#define PTR sizeof(char*)
-#define SHORT sizeof(int)
-#define INT sizeof(int)
-#define LONG sizeof(long)
-#define IDIGIT 30
-#define MAXCON 30
-
-#define FLONG (1<<0)
-#define FSHORT (1<<1)
-#define FUNSIGN (1<<2)
-
-typedef struct Op Op;
-struct Op
-{
- char *p;
- char *ep;
- void *argp;
- int f1;
- int f2;
- int f3;
-};
-
-static int noconv(Op*);
-static int cconv(Op*);
-static int dconv(Op*);
-static int hconv(Op*);
-static int lconv(Op*);
-static int oconv(Op*);
-static int sconv(Op*);
-static int uconv(Op*);
-static int xconv(Op*);
-static int Xconv(Op*);
-static int percent(Op*);
-
-static
-int (*fmtconv[MAXCON])(Op*) =
-{
- noconv,
- cconv, dconv, hconv, lconv,
- oconv, sconv, uconv, xconv,
- Xconv, percent,
-};
-static
-char fmtindex[128] =
-{
- ['c'] 1,
- ['d'] 2,
- ['h'] 3,
- ['l'] 4,
- ['o'] 5,
- ['s'] 6,
- ['u'] 7,
- ['x'] 8,
- ['X'] 9,
- ['%'] 10,
-};
-
-static int convcount = { 11 };
-static int ucase;
-
-static void
-PUT(Op *o, int c)
-{
- static int pos;
- int opos;
-
- if(c == '\t'){
- opos = pos;
- pos = (opos+8) & ~7;
- while(opos++ < pos && o->p < o->ep)
- *o->p++ = ' ';
- return;
- }
- if(o->p < o->ep){
- *o->p++ = c;
- pos++;
- }
- if(c == '\n')
- pos = 0;
-}
-
-int
-fmtinstall(char c, int (*f)(Op*))
-{
-
- c &= 0177;
- if(fmtindex[c] == 0) {
- if(convcount >= MAXCON)
- return 1;
- fmtindex[c] = convcount++;
- }
- fmtconv[fmtindex[c]] = f;
- return 0;
-}
-
-char*
-donprint(char *p, char *ep, char *fmt, void *argp)
-{
- int sf1, c;
- Op o;
-
- o.p = p;
- o.ep = ep;
- o.argp = argp;
-
-loop:
- c = *fmt++;
- if(c != '%') {
- if(c == 0) {
- if(o.p < o.ep)
- *o.p = 0;
- return o.p;
- }
- PUT(&o, c);
- goto loop;
- }
- o.f1 = 0;
- o.f2 = -1;
- o.f3 = 0;
- c = *fmt++;
- sf1 = 0;
- if(c == '-') {
- sf1 = 1;
- c = *fmt++;
- }
- while(c >= '0' && c <= '9') {
- o.f1 = o.f1*10 + c-'0';
- c = *fmt++;
- }
- if(sf1)
- o.f1 = -o.f1;
- if(c != '.')
- goto l1;
- c = *fmt++;
- while(c >= '0' && c <= '9') {
- if(o.f2 < 0)
- o.f2 = 0;
- o.f2 = o.f2*10 + c-'0';
- c = *fmt++;
- }
-l1:
- if(c == 0)
- fmt--;
- c = (*fmtconv[fmtindex[c&0177]])(&o);
- if(c < 0) {
- o.f3 |= -c;
- c = *fmt++;
- goto l1;
- }
- o.argp = (char*)o.argp + c;
- goto loop;
-}
-
-void
-strconv(char *o, Op *op, int f1, int f2)
-{
- int n, c;
- char *p;
-
- n = strlen(o);
- if(f1 >= 0)
- while(n < f1) {
- PUT(op, ' ');
- n++;
- }
- for(p=o; c = *p++;)
- if(f2 != 0) {
- PUT(op, c);
- f2--;
- }
- if(f1 < 0) {
- f1 = -f1;
- while(n < f1) {
- PUT(op, ' ');
- n++;
- }
- }
-}
-
-int
-numbconv(Op *op, int base)
-{
- char b[IDIGIT];
- int i, f, n, r;
- long v;
- short h;
-
- f = 0;
- switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
- case FLONG:
- v = *(long*)op->argp;
- r = LONG;
- break;
-
- case FUNSIGN|FLONG:
- v = *(ulong*)op->argp;
- r = LONG;
- break;
-
- case FSHORT:
- h = *(int*)op->argp;
- v = h;
- r = SHORT;
- break;
-
- case FUNSIGN|FSHORT:
- h = *(int*)op->argp;
- v = (ushort)h;
- r = SHORT;
- break;
-
- default:
- v = *(int*)op->argp;
- r = INT;
- break;
-
- case FUNSIGN:
- v = *(unsigned*)op->argp;
- r = INT;
- break;
- }
- if(!(op->f3 & FUNSIGN) && v < 0) {
- v = -v;
- f = 1;
- }
- b[IDIGIT-1] = 0;
- for(i = IDIGIT-2;; i--) {
- n = (ulong)v % base;
- n += '0';
- if(n > '9'){
- n += 'a' - ('9'+1);
- if(ucase)
- n += 'A'-'a';
- }
- b[i] = n;
- if(i < 2)
- break;
- v = (ulong)v / base;
- if(op->f2 >= 0 && i >= IDIGIT-op->f2)
- continue;
- if(v <= 0)
- break;
- }
- if(f)
- b[--i] = '-';
- strconv(b+i, op, op->f1, -1);
- return r;
-}
-
-static int
-noconv(Op *op)
-{
-
- strconv("***", op, 0, -1);
- return 0;
-}
-
-static int
-cconv(Op *op)
-{
- char b[2];
-
- b[0] = *(int*)op->argp;
- b[1] = 0;
- strconv(b, op, op->f1, -1);
- return INT;
-}
-
-static int
-dconv(Op *op)
-{
- return numbconv(op, 10);
-}
-
-static int
-hconv(Op*)
-{
- return -FSHORT;
-}
-
-static int
-lconv(Op*)
-{
- return -FLONG;
-}
-
-static int
-oconv(Op *op)
-{
- return numbconv(op, 8);
-}
-
-static int
-sconv(Op *op)
-{
- strconv(*(char**)op->argp, op, op->f1, op->f2);
- return PTR;
-}
-
-static int
-uconv(Op*)
-{
- return -FUNSIGN;
-}
-
-static int
-xconv(Op *op)
-{
- return numbconv(op, 16);
-}
-
-static int
-Xconv(Op *op)
-{
- int r;
-
- ucase = 1;
- r = numbconv(op, 16);
- ucase = 0;
- return r;
-}
-
-static int
-percent(Op *op)
-{
-
- PUT(op, '%');
- return 0;
-}
--- a/os/boot/rpcg/dosboot.c
+++ /dev/null
@@ -1,614 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "dosfs.h"
-
-extern char *premature;
-
-/*
- * predeclared
- */
-static void bootdump(Dosboot*);
-static void setname(Dosfile*, char*);
-long dosreadseg(Dosfile*, long, long);
-
-/*
- * debugging
- */
-#define chatty 1
-#define chat if(chatty)print
-
-/*
- * block io buffers
- */
-enum
-{
- Nbio= 16,
-};
-typedef struct Clustbuf Clustbuf;
-struct Clustbuf
-{
- int age;
- long sector;
- uchar *iobuf;
- Dos *dos;
- int size;
-};
-Clustbuf bio[Nbio];
-
-/*
- * get an io block from an io buffer
- */
-Clustbuf*
-getclust(Dos *dos, long sector)
-{
- Clustbuf *p, *oldest;
- int size;
-
- chat("getclust @ %d\n", sector);
-
- /*
- * if we have it, just return it
- */
- for(p = bio; p < &bio[Nbio]; p++){
- if(sector == p->sector && dos == p->dos){
- p->age = m->ticks;
- chat("getclust %d in cache\n", sector);
- return p;
- }
- }
-
- /*
- * otherwise, reuse the oldest entry
- */
- oldest = bio;
- for(p = &bio[1]; p < &bio[Nbio]; p++){
- if(p->age <= oldest->age)
- oldest = p;
- }
- p = oldest;
-
- /*
- * make sure the buffer is big enough
- */
- size = dos->clustsize*dos->sectsize;
- if(p->iobuf==0 || p->size < size)
- p->iobuf = ialloc(size, 0);
- p->size = size;
-
- /*
- * read in the cluster
- */
- chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
- if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
- chat("can't seek block\n");
- return 0;
- }
- if((*dos->read)(dos->dev, p->iobuf, size) != size){
- chat("can't read block\n");
- return 0;
- }
-
- p->age = m->ticks;
- p->dos = dos;
- p->sector = sector;
- chat("getclust %d read\n", sector);
- return p;
-}
-
-/*
- * walk the fat one level ( n is a current cluster number ).
- * return the new cluster number or -1 if no more.
- */
-static long
-fatwalk(Dos *dos, int n)
-{
- ulong k, sect;
- Clustbuf *p;
- int o;
-
- chat("fatwalk %d\n", n);
-
- if(n < 2 || n >= dos->fatclusters)
- return -1;
-
- switch(dos->fatbits){
- case 12:
- k = (3*n)/2; break;
- case 16:
- k = 2*n; break;
- default:
- return -1;
- }
- if(k >= dos->fatsize*dos->sectsize)
- panic("getfat");
-
- sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
- o = k%(dos->sectsize*dos->clustsize);
- p = getclust(dos, sect);
- k = p->iobuf[o++];
- if(o >= dos->sectsize*dos->clustsize){
- p = getclust(dos, sect+dos->clustsize);
- o = 0;
- }
- k |= p->iobuf[o]<<8;
- if(dos->fatbits == 12){
- if(n&1)
- k >>= 4;
- else
- k &= 0xfff;
- if(k >= 0xff8)
- k |= 0xf000;
- }
- k = k < 0xfff8 ? k : -1;
- chat("fatwalk %d -> %d\n", n, k);
- return k;
-}
-
-/*
- * map a file's logical cluster address to a physical sector address
- */
-static long
-fileaddr(Dosfile *fp, long ltarget)
-{
- Dos *dos = fp->dos;
- long l;
- long p;
-
- chat("fileaddr %8.8s %d\n", fp->name, ltarget);
- /*
- * root directory is contiguous and easy
- */
- if(fp->pstart == 0){
- if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
- return -1;
- l = dos->rootaddr + ltarget*dos->clustsize;
- chat("fileaddr %d -> %d\n", ltarget, l);
- return l;
- }
-
- /*
- * anything else requires a walk through the fat
- */
- if(ltarget >= fp->lcurrent && fp->pcurrent){
- /* start at the currrent point */
- l = fp->lcurrent;
- p = fp->pcurrent;
- } else {
- /* go back to the beginning */
- l = 0;
- p = fp->pstart;
- }
- while(l != ltarget){
- /* walk the fat */
- p = fatwalk(dos, p);
- if(p < 0)
- return -1;
- l++;
- }
- fp->lcurrent = l;
- fp->pcurrent = p;
-
- /*
- * clusters start at 2 instead of 0 (why? - presotto)
- */
- l = dos->dataaddr + (p-2)*dos->clustsize;
- chat("fileaddr %d -> %d\n", ltarget, l);
- return l;
-}
-
-/*
- * read from a dos file
- */
-long
-dosread(Dosfile *fp, void *a, long n)
-{
- long addr;
- long rv;
- int i;
- int off;
- Clustbuf *p;
- uchar *from, *to;
-
- if((fp->attr & DDIR) == 0){
- if(fp->offset >= fp->length)
- return 0;
- if(fp->offset+n > fp->length)
- n = fp->length - fp->offset;
- }
-
- to = a;
- for(rv = 0; rv < n; rv+=i){
- /*
- * read the cluster
- */
- addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
- if(addr < 0)
- return -1;
- p = getclust(fp->dos, addr);
- if(p == 0)
- return -1;
-
- /*
- * copy the bytes we need
- */
- off = fp->offset % fp->dos->clustbytes;
- from = &p->iobuf[off];
- i = n - rv;
- if(i > fp->dos->clustbytes - off)
- i = fp->dos->clustbytes - off;
- memmove(to, from, i);
- to += i;
- fp->offset += i;
- }
-
- return rv;
-}
-
-/*
- * walk a directory returns
- * -1 if something went wrong
- * 0 if not found
- * 1 if found
- */
-int
-doswalk(Dosfile *file, char *name)
-{
- Dosdir d;
- long n;
-
- if((file->attr & DDIR) == 0){
- chat("walking non-directory!\n");
- return -1;
- }
-
- setname(file, name);
-
- file->offset = 0; /* start at the beginning */
- while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
- chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
- if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
- continue;
- if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
- continue;
- if(d.attr & DVLABEL){
- chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
- continue;
- }
- file->attr = d.attr;
- file->pstart = GSHORT(d.start);
- file->length = GLONG(d.length);
- file->pcurrent = 0;
- file->lcurrent = 0;
- file->offset = 0;
- return 1;
- }
- return n >= 0 ? 0 : -1;
-}
-
-
-/*
- * instructions that boot blocks can start with
- */
-#define JMPSHORT 0xeb
-#define JMPNEAR 0xe9
-
-/*
- * read dos file system properties
- */
-int
-dosinit(Dos *dos, int start, int ishard)
-{
- Dosboot *b;
- int i;
- Clustbuf *p;
- Dospart *dp;
- ulong mbroffset, offset;
-
- /* defaults till we know better */
- dos->start = start;
- dos->sectsize = 512;
- dos->clustsize = 1;
- mbroffset = 0;
-
-dmddo:
- /* get first sector */
- p = getclust(dos, mbroffset);
- if(p == 0){
- chat("can't read boot block\n");
- return -1;
- }
-
- /*
- * If it's a hard disc then look for an MBR and pick either an
- * active partition or the FAT with the lowest starting LBA.
- * Things are tricky because we could be pointing to, amongst others:
- * 1) a floppy BPB;
- * 2) a hard disc MBR;
- * 3) a hard disc extended partition table;
- * 4) a logical drive on a hard disc;
- * 5) a disc-manager boot block.
- * They all have the same magic at the end of the block.
- */
- if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
- chat("not DOS\n");
- return -1;
- }
- p->dos = 0;
- b = (Dosboot *)p->iobuf;
- if(ishard && b->mediadesc != 0xF8){
- dp = (Dospart*)&p->iobuf[0x1BE];
- offset = 0xFFFFFFFF;
- for(i = 0; i < 4; i++, dp++){
- if(dp->type == DMDDO){
- mbroffset = 63;
- goto dmddo;
- }
- if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
- continue;
- if(dp->flag & 0x80){
- offset = GLONG(dp->start);
- break;
- }
- if(GLONG(dp->start) < offset)
- offset = GLONG(dp->start);
- }
- if(i != 4 || offset != 0xFFFFFFFF){
- dos->start = mbroffset+offset;
- p = getclust(dos, 0);
- if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
- return -1;
- }
- p->dos = 0;
- }
-
- b = (Dosboot *)p->iobuf;
- if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
- chat("no dos file system\n");
- return -1;
- }
-
- if(chatty)
- bootdump(b);
-
- /*
- * determine the systems' wondersous properties
- */
- dos->sectsize = GSHORT(b->sectsize);
- dos->clustsize = b->clustsize;
- dos->clustbytes = dos->sectsize*dos->clustsize;
- dos->nresrv = GSHORT(b->nresrv);
- dos->nfats = b->nfats;
- dos->rootsize = GSHORT(b->rootsize);
- dos->volsize = GSHORT(b->volsize);
- if(dos->volsize == 0)
- dos->volsize = GLONG(b->bigvolsize);
- dos->mediadesc = b->mediadesc;
- dos->fatsize = GSHORT(b->fatsize);
- dos->fataddr = dos->nresrv;
- dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
- i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
- i = i/dos->sectsize;
- dos->dataaddr = dos->rootaddr + i;
- dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
- if(dos->fatclusters < 4087)
- dos->fatbits = 12;
- else
- dos->fatbits = 16;
- dos->freeptr = 2;
-
- /*
- * set up the root
- */
- dos->root.dos = dos;
- dos->root.pstart = 0;
- dos->root.pcurrent = dos->root.lcurrent = 0;
- dos->root.offset = 0;
- dos->root.attr = DDIR;
- dos->root.length = dos->rootsize*sizeof(Dosdir);
-
- return 0;
-}
-
-static void
-bootdump(Dosboot *b)
-{
- if(chatty == 0)
- return;
- print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
- b->magic[0], b->magic[1], b->magic[2]);
- print("version: \"%8.8s\"\n", b->version);
- print("sectsize: %d\n", GSHORT(b->sectsize));
- print("allocsize: %d\n", b->clustsize);
- print("nresrv: %d\n", GSHORT(b->nresrv));
- print("nfats: %d\n", b->nfats);
- print("rootsize: %d\n", GSHORT(b->rootsize));
- print("volsize: %d\n", GSHORT(b->volsize));
- print("mediadesc: 0x%2.2x\n", b->mediadesc);
- print("fatsize: %d\n", GSHORT(b->fatsize));
- print("trksize: %d\n", GSHORT(b->trksize));
- print("nheads: %d\n", GSHORT(b->nheads));
- print("nhidden: %d\n", GLONG(b->nhidden));
- print("bigvolsize: %d\n", GLONG(b->bigvolsize));
- print("driveno: %d\n", b->driveno);
- print("reserved0: 0x%2.2x\n", b->reserved0);
- print("bootsig: 0x%2.2x\n", b->bootsig);
- print("volid: 0x%8.8x\n", GLONG(b->volid));
- print("label: \"%11.11s\"\n", b->label);
-}
-
-/*
- * grab next element from a path, return the pointer to unprocessed portion of
- * path.
- */
-static char *
-nextelem(char *path, char *elem)
-{
- int i;
-
- while(*path == '/')
- path++;
- if(*path==0 || *path==' ')
- return 0;
- for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
- if(i==28){
- print("name component too long\n");
- return 0;
- }
- *elem++ = *path++;
- }
- *elem = '\0';
- return path;
-}
-
-int
-dosstat(Dos *dos, char *path, Dosfile *f)
-{
- char element[NAMELEN];
-
- *f = dos->root;
- while(path = nextelem(path, element)){
- switch(doswalk(f, element)){
- case -1:
- return -1;
- case 0:
- return 0;
- }
- }
- return 1;
-}
-
-/*
- * boot
- */
-int
-dosboot(Dos *dos, char *path)
-{
- Dosfile file;
- long n;
- long addr;
- Exec *ep;
- void (*b)(void);
-
- switch(dosstat(dos, path, &file)){
-
- case -1:
- print("error walking to %s\n", path);
- return -1;
- case 0:
- print("%s not found\n", path);
- return -1;
- case 1:
- print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
- file.ext, file.attr, file.pstart, file.length);
- break;
- }
-
- /*
- * read header
- */
- ep = (Exec*)ialloc(sizeof(Exec), 0);
- n = sizeof(Exec);
- if(dosreadseg(&file, n, (ulong) ep) != n){
- print(premature);
- return -1;
- }
- if(GLLONG(ep->magic) != Q_MAGIC){
- print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
- return -1;
- }
-
- /*
- * read text
- */
- addr = PADDR(GLLONG(ep->entry));
- n = GLLONG(ep->text);
- print("+%d", n);
- if(dosreadseg(&file, n, addr) != n){
- print(premature);
- return -1;
- }
-
- /*
- * read data (starts at first page after kernel)
- */
- addr = PGROUND(addr+n);
- n = GLLONG(ep->data);
- print("+%d", n);
- if(dosreadseg(&file, n, addr) != n){
- print(premature);
- return -1;
- }
-
- /*
- * bss and entry point
- */
- print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
-
- /*
- * Go to new code. It's up to the program to get its PC relocated to
- * the right place.
- */
- b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
- (*b)();
- return 0;
-}
-
-/*
- * read in a segment
- */
-long
-dosreadseg(Dosfile *fp, long len, long addr)
-{
- char *a;
- long n, sofar;
-
- a = (char *)addr;
- for(sofar = 0; sofar < len; sofar += n){
- n = 8*1024;
- if(len - sofar < n)
- n = len - sofar;
- n = dosread(fp, a + sofar, n);
- if(n <= 0)
- break;
- print(".");
- }
- return sofar;
-}
-
-/*
- * set up a dos file name
- */
-static void
-setname(Dosfile *fp, char *from)
-{
- char *to;
-
- to = fp->name;
- for(; *from && to-fp->name < 8; from++, to++){
- if(*from == '.'){
- from++;
- break;
- }
- if(*from >= 'a' && *from <= 'z')
- *to = *from + 'A' - 'a';
- else
- *to = *from;
- }
- while(to - fp->name < 8)
- *to++ = ' ';
-
- to = fp->ext;
- for(; *from && to-fp->ext < 3; from++, to++){
- if(*from >= 'a' && *from <= 'z')
- *to = *from + 'A' - 'a';
- else
- *to = *from;
- }
- while(to-fp->ext < 3)
- *to++ = ' ';
-
- chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
-}
--- a/os/boot/rpcg/dosfs.h
+++ /dev/null
@@ -1,110 +1,0 @@
-typedef struct Dosboot Dosboot;
-typedef struct Dos Dos;
-typedef struct Dosdir Dosdir;
-typedef struct Dosfile Dosfile;
-typedef struct Dospart Dospart;
-
-struct Dospart
-{
- uchar flag; /* active flag */
- uchar shead; /* starting head */
- uchar scs[2]; /* starting cylinder/sector */
- uchar type; /* partition type */
- uchar ehead; /* ending head */
- uchar ecs[2]; /* ending cylinder/sector */
- uchar start[4]; /* starting sector */
- uchar len[4]; /* length in sectors */
-};
-
-#define FAT12 0x01
-#define FAT16 0x04
-#define FATHUGE 0x06
-#define DMDDO 0x54
-
-struct Dosboot{
- uchar magic[3];
- uchar version[8];
- uchar sectsize[2];
- uchar clustsize;
- uchar nresrv[2];
- uchar nfats;
- uchar rootsize[2];
- uchar volsize[2];
- uchar mediadesc;
- uchar fatsize[2];
- uchar trksize[2];
- uchar nheads[2];
- uchar nhidden[4];
- uchar bigvolsize[4];
- uchar driveno;
- uchar reserved0;
- uchar bootsig;
- uchar volid[4];
- uchar label[11];
- uchar reserved1[8];
-};
-
-struct Dosfile{
- Dos *dos; /* owning dos file system */
- char name[8];
- char ext[3];
- uchar attr;
- long length;
- long pstart; /* physical start cluster address */
- long pcurrent; /* physical current cluster address */
- long lcurrent; /* logical current cluster address */
- long offset;
-};
-
-struct Dos{
- int dev; /* device id */
- long (*read)(int, void*, long); /* read routine */
- long (*seek)(int, long); /* seek routine */
-
- int start; /* start of file system */
- int sectsize; /* in bytes */
- int clustsize; /* in sectors */
- int clustbytes; /* in bytes */
- int nresrv; /* sectors */
- int nfats; /* usually 2 */
- int rootsize; /* number of entries */
- int volsize; /* in sectors */
- int mediadesc;
- int fatsize; /* in sectors */
- int fatclusters;
- int fatbits; /* 12 or 16 */
- long fataddr; /* sector number */
- long rootaddr;
- long dataaddr;
- long freeptr;
-
- Dosfile root;
-};
-
-struct Dosdir{
- uchar name[8];
- uchar ext[3];
- uchar attr;
- uchar reserved[10];
- uchar time[2];
- uchar date[2];
- uchar start[2];
- uchar length[4];
-};
-
-#define DRONLY 0x01
-#define DHIDDEN 0x02
-#define DSYSTEM 0x04
-#define DVLABEL 0x08
-#define DDIR 0x10
-#define DARCH 0x20
-
-extern int chatty;
-
-extern int dosboot(Dos*, char*);
-extern int dosinit(Dos*, int, int);
-extern long dosread(Dosfile*, void*, long);
-extern int dosstat(Dos*, char*, Dosfile*);
-extern int doswalk(Dosfile*, char*);
-
-extern int plan9ini(Dos*, char*);
--- a/os/boot/rpcg/etherif.h
+++ /dev/null
@@ -1,59 +1,0 @@
-/*
- * All the goo for PC ethernet cards.
- */
-typedef struct Card Card;
-typedef struct Type Type;
-typedef struct Ctlr Ctlr;
-
-/*
- * Hardware interface.
- */
-struct Card {
- ISAConf;
-
- int (*reset)(Ctlr*);
- void (*attach)(Ctlr*);
-
- void *(*read)(Ctlr*, void*, ulong, ulong);
- void *(*write)(Ctlr*, ulong, void*, ulong);
-
- void (*receive)(Ctlr*);
- void (*transmit)(Ctlr*);
- void (*intr)(Ureg*, void*);
- void (*overflow)(Ctlr*);
-
- uchar bit16; /* true if a 16 bit interface */
- uchar ram; /* true if card has shared memory */
-
- ulong dp8390; /* I/O address of 8390 (if any) */
- ulong data; /* I/O data port if no shared memory */
- uchar nxtpkt; /* software bndry */
- uchar tstart; /* 8390 ring addresses */
- uchar pstart;
- uchar pstop;
-
- uchar dummyrr; /* do dummy remote read */
-};
-
-/*
- * Software controller.
- */
-struct Ctlr {
- Card card; /* hardware info */
- int ctlrno;
- int present;
-
- Queue* iq;
- Queue* oq;
-
- int inpackets;
- int outpackets;
- int crcs; /* input crc errors */
- int oerrs; /* output errors */
- int frames; /* framing errors */
- int overflows; /* packet overflows */
- int buffs; /* buffering errors */
-};
-
-extern int sccethreset(Ctlr*);
-extern int etheriq(Ctlr*, Block*, int);
--- a/os/boot/rpcg/etherscc.c
+++ /dev/null
@@ -1,411 +1,0 @@
-/*
- * SCCn ethernet
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "etherif.h"
-
-enum {
- Nrdre = 32, /* receive descriptor ring entries */
- Ntdre = 4, /* transmit descriptor ring entries */
-
- Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
- Bufsize = (Rbsize+7)&~7, /* aligned */
-};
-
-enum {
- /* ether-specific Rx BD bits */
- RxMiss= 1<<8,
- RxeLG= 1<<5,
- RxeNO= 1<<4,
- RxeSH= 1<<3,
- RxeCR= 1<<2,
- RxeOV= 1<<1,
- RxeCL= 1<<0,
- RxError= (RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL), /* various error flags */
-
- /* ether-specific Tx BD bits */
- TxPad= 1<<14, /* pad short frames */
- TxTC= 1<<10, /* transmit CRC */
- TxeDEF= 1<<9,
- TxeHB= 1<<8,
- TxeLC= 1<<7,
- TxeRL= 1<<6,
- TxeUN= 1<<1,
- TxeCSL= 1<<0,
-
- /* scce */
- RXB= 1<<0,
- TXB= 1<<1,
- BSY= 1<<2,
- RXF= 1<<3,
- TXE= 1<<4,
-
- /* gsmrl */
- ENR= 1<<5,
- ENT= 1<<4,
-
- /* port A */
- RXD1= SIBIT(15),
- TXD1= SIBIT(14),
-
- /* port B */
- RTS1= IBIT(19),
-
- /* port C */
- CTS1= SIBIT(11),
- CD1= SIBIT(10),
-};
-
-typedef struct Etherparam Etherparam;
-struct Etherparam {
- SCCparam;
- ulong c_pres; /* preset CRC */
- ulong c_mask; /* constant mask for CRC */
- ulong crcec; /* CRC error counter */
- ulong alec; /* alighnment error counter */
- ulong disfc; /* discard frame counter */
- ushort pads; /* short frame PAD characters */
- ushort ret_lim; /* retry limit threshold */
- ushort ret_cnt; /* retry limit counter */
- ushort mflr; /* maximum frame length reg */
- ushort minflr; /* minimum frame length reg */
- ushort maxd1; /* maximum DMA1 length reg */
- ushort maxd2; /* maximum DMA2 length reg */
- ushort maxd; /* rx max DMA */
- ushort dma_cnt; /* rx dma counter */
- ushort max_b; /* max bd byte count */
- ushort gaddr[4]; /* group address filter */
- ulong tbuf0_data0; /* save area 0 - current frm */
- ulong tbuf0_data1; /* save area 1 - current frm */
- ulong tbuf0_rba0;
- ulong tbuf0_crc;
- ushort tbuf0_bcnt;
- ushort paddr[3]; /* physical address LSB to MSB increasing */
- ushort p_per; /* persistence */
- ushort rfbd_ptr; /* rx first bd pointer */
- ushort tfbd_ptr; /* tx first bd pointer */
- ushort tlbd_ptr; /* tx last bd pointer */
- ulong tbuf1_data0; /* save area 0 - next frame */
- ulong tbuf1_data1; /* save area 1 - next frame */
- ulong tbuf1_rba0;
- ulong tbuf1_crc;
- ushort tbuf1_bcnt;
- ushort tx_len; /* tx frame length counter */
- ushort iaddr[4]; /* individual address filter*/
- ushort boff_cnt; /* back-off counter */
- ushort taddr[3]; /* temp address */
-};
-
-typedef struct {
- SCC* scc;
- int port;
- int cpm;
-
- BD* rdr; /* receive descriptor ring */
- void* rrb; /* receive ring buffers */
- int rdrx; /* index into rdr */
-
- BD* tdr; /* transmit descriptor ring */
- void* trb; /* transmit ring buffers */
- int tdrx; /* index into tdr */
-} Mot;
-static Mot mot[MaxEther];
-
-static int sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID};
-static int sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P};
-static int sccreg[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60};
-static int sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B};
-
-static void
-attach(Ctlr *ctlr)
-{
- mot[ctlr->ctlrno].scc->gsmrl |= ENR|ENT;
- eieio();
-}
-
-static void
-transmit(Ctlr *ctlr)
-{
- int len;
- Mot *motp;
- Block *b;
- BD *tdre;
-
- motp = &mot[ctlr->ctlrno];
- while(((tdre = &motp->tdr[motp->tdrx])->status & BDReady) == 0){
- b = qget(ctlr->oq);
- if(b == 0)
- break;
-
- /*
- * Copy the packet to the transmit buffer.
- */
- len = BLEN(b);
- memmove(KADDR(tdre->addr), b->rp, len);
-
- /*
- * Give ownership of the descriptor to the chip, increment the
- * software ring descriptor pointer and tell the chip to poll.
- */
- tdre->length = len;
- eieio();
- tdre->status = (tdre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
- eieio();
- motp->scc->todr = 1<<15; /* transmit now */
- eieio();
- motp->tdrx = NEXT(motp->tdrx, Ntdre);
-
- freeb(b);
-
- }
-}
-
-static void
-interrupt(Ureg*, void *ap)
-{
- int len, events, status;
- Mot *motp;
- BD *rdre;
- Block *b;
- Ctlr *ctlr;
-
- ctlr = ap;
- motp = &mot[ctlr->ctlrno];
-
- /*
- * Acknowledge all interrupts and whine about those that shouldn't
- * happen.
- */
- events = motp->scc->scce;
- eieio();
- motp->scc->scce = events;
- eieio();
- if(events & (TXE|BSY|RXB))
- print("ETHER.SCC#%d: scce = 0x%uX\n", ctlr->ctlrno, events);
- //print(" %ux|", events);
- /*
- * Receiver interrupt: run round the descriptor ring logging
- * errors and passing valid receive data up to the higher levels
- * until we encounter a descriptor still owned by the chip.
- */
- if(events & (RXF|RXB) || 1){
- rdre = &motp->rdr[motp->rdrx];
- while(((status = rdre->status) & BDEmpty) == 0){
- if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
- //if(status & RxBuff)
- // ctlr->buffs++;
- if(status & (1<<2))
- ctlr->crcs++;
- if(status & (1<<1))
- ctlr->overflows++;
- //print("eth rx: %ux\n", status);
- if(status & RxError)
- print("~");
- else if((status & BDLast) == 0)
- print("@");
- }
- else{
- /*
- * We have a packet. Read it into the next
- * free ring buffer, if any.
- */
- len = rdre->length-4;
- if((b = iallocb(len)) != 0){
- memmove(b->wp, KADDR(rdre->addr), len);
- b->wp += len;
- etheriq(ctlr, b, 1);
- }
- }
-
- /*
- * Finished with this descriptor, reinitialise it,
- * give it back to the chip, then on to the next...
- */
- rdre->length = 0;
- rdre->status = (rdre->status & BDWrap) | BDEmpty | BDInt;
- eieio();
-
- motp->rdrx = NEXT(motp->rdrx, Nrdre);
- rdre = &motp->rdr[motp->rdrx];
- }
- }
-
- /*
- * Transmitter interrupt: handle anything queued for a free descriptor.
- */
- if(events & TXB)
- transmit(ctlr);
- if(events & TXE)
- cpmop(RestartTx, motp->cpm, 0);
-}
-
-static void
-ringinit(Mot* motp)
-{
- int i, x;
-
- /*
- * Initialise the receive and transmit buffer rings. The ring
- * entries must be aligned on 16-byte boundaries.
- */
- if(motp->rdr == 0)
- motp->rdr = bdalloc(Nrdre);
- if(motp->rrb == 0)
- motp->rrb = ialloc(Nrdre*Bufsize, 0);
- x = PADDR(motp->rrb);
- for(i = 0; i < Nrdre; i++){
- motp->rdr[i].length = 0;
- motp->rdr[i].addr = x;
- motp->rdr[i].status = BDEmpty|BDInt;
- x += Bufsize;
- }
- motp->rdr[i-1].status |= BDWrap;
- motp->rdrx = 0;
-
- if(motp->tdr == 0)
- motp->tdr = bdalloc(Ntdre);
- if(motp->trb == 0)
- motp->trb = ialloc(Ntdre*Bufsize, 0);
- x = PADDR(motp->trb);
- for(i = 0; i < Ntdre; i++){
- motp->tdr[i].addr = x;
- motp->tdr[i].length = 0;
- motp->tdr[i].status = TxPad|BDInt|BDLast|TxTC;
- x += Bufsize;
- }
- motp->tdr[i-1].status |= BDWrap;
- motp->tdrx = 0;
-}
-
-/*
- * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence,
- * except that it sets the right bits for the MPC823ADS board when SCC2 is used,
- * and those for the 860/821 development board for SCC1.
- */
-static void
-sccsetup(Mot *ctlr, SCC *scc, uchar *ea)
-{
- int i, rcs, tcs, w;
- Etherparam *p;
- IMM *io;
-
-
- i = 2*(ctlr->port-1);
- io = ioplock();
- w = (TXD1|RXD1)<<i; /* TXDn and RXDn in port A */
- io->papar |= w; /* enable TXDn and RXDn pins */
- io->padir &= ~w;
- io->paodr &= ~w; /* not open drain */
-
- w = (CD1|CTS1)<<i; /* CLSN and RENA: CDn and CTSn in port C */
- io->pcpar &= ~w; /* enable CLSN (CTSn) and RENA (CDn) */
- io->pcdir &= ~w;
- io->pcso |= w;
- iopunlock();
-
- /* clocks and transceiver control: details depend on the board's wiring */
- archetherenable(ctlr->cpm, &rcs, &tcs);
-
- sccnmsi(ctlr->port, rcs, tcs); /* connect the clocks */
-
- p = (Etherparam*)KADDR(sccparam[ctlr->port]);
- memset(p, 0, sizeof(*p));
- p->rfcr = 0x18;
- p->tfcr = 0x18;
- p->mrblr = Bufsize;
- p->rbase = PADDR(ctlr->rdr);
- p->tbase = PADDR(ctlr->tdr);
-
- cpmop(InitRxTx, ctlr->cpm, 0);
-
- p->c_pres = ~0;
- p->c_mask = 0xDEBB20E3;
- p->crcec = 0;
- p->alec = 0;
- p->disfc = 0;
- p->pads = 0x8888;
- p->ret_lim = 0xF;
- p->mflr = Rbsize;
- p->minflr = ETHERMINTU+4;
- p->maxd1 = Bufsize;
- p->maxd2 = Bufsize;
- p->p_per = 0; /* only moderate aggression */
-
- for(i=0; i<Eaddrlen; i+=2)
- p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i]; /* it's not the obvious byte order */
-
- scc->psmr = (2<<10)|(5<<1); /* 32-bit CRC, ignore 22 bits before SFD */
- scc->dsr = 0xd555;
- scc->gsmrh = 0; /* normal operation */
- scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC; /* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */
- eieio();
- scc->scce = ~0; /* clear all events */
- eieio();
- scc->sccm = TXE | RXF | TXB; /* enable interrupts */
- eieio();
-
- io = ioplock();
- w = RTS1<<(ctlr->port-1); /* enable TENA pin (RTSn) */
- io->pbpar |= w;
- io->pbdir |= w;
- iopunlock();
-
- /* gsmrl enable is deferred until attach */
-}
-
-/*
- * Prepare the SCCx ethernet for booting.
- */
-int
-sccethreset(Ctlr* ctlr)
-{
- uchar ea[Eaddrlen];
- Mot *motp;
- SCC *scc;
- char line[50], def[50];
-
- /*
- * Since there's no EPROM, insist that the configuration entry
- * (see conf.c and flash.c) holds the Ethernet address.
- */
- memset(ea, 0, Eaddrlen);
- if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0){
- print("no preset Ether address\n");
- for(;;){
- strcpy(def, "00108bf12900"); /* valid MAC address to be used only for initial configuration */
- if(getstr("ether MAC address", line, sizeof(line), def) < 0)
- return -1;
- if(parseether(ctlr->card.ea, line) >= 0 || ctlr->card.ea[0] == 0xFF)
- break;
- print("invalid MAC address\n");
- }
- }
-
- scc = IOREGS(sccreg[ctlr->card.port], SCC);
- ctlr->card.irq = VectorCPIC+sccirq[ctlr->card.port];
-
- motp = &mot[ctlr->ctlrno];
- motp->scc = scc;
- motp->port = ctlr->card.port;
- motp->cpm = sccid[ctlr->card.port];
-
- ringinit(motp);
-
- sccsetup(motp, scc, ctlr->card.ea);
-
- /* enable is deferred until attach */
-
- ctlr->card.reset = sccethreset;
- ctlr->card.attach = attach;
- ctlr->card.transmit = transmit;
- ctlr->card.intr = interrupt;
-
- return 0;
-}
--- a/os/boot/rpcg/fblt.c
+++ /dev/null
@@ -1,531 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <libg.h>
-#include <gnot.h>
-
-/*
- * bitblt operates a 'word' at a time.
- * WBITS is the number of bits in a word
- * LWBITS=log2(WBITS),
- * W2L is the number of words in a long
- * WMASK has bits set for the low order word of a long
- * WType is a pointer to a word
- */
-#ifndef WBITS
-#define WBITS 32
-#define LWBITS 5
-#define W2L 1
-#define WMASK ~0UL
-typedef ulong *WType;
-#endif
-
-#define DEBUG
-
-#ifdef TEST
-/*
- * globals used for testing
- */
-int FORCEFORW;
-int FORCEBAKW;
-GBitmap *curdm, *cursm;
-Point curpt;
-Rectangle curr;
-Fcode curf;
-void *mem;
-#endif
-
-static void
-gbitexplode(ulong sw, ulong *buf, int sdep, int x)
-{
- int j, o, q, n, nw, inc, qinc;
- ulong s, dw, pix;
-
- inc = 1 << sdep;
- pix = (1 << inc) - 1;
- nw = 1 << x;
- n = 32 >> x;
- qinc = (nw << sdep) - inc;
- for(o = 32 - n; o >= 0; o -= n){
- dw = 0;
- s = sw >> o;
- q = 0;
- for(j = 0; j < n; j += inc){
- dw |= (s & (pix << j)) << q;
- q += qinc;
- }
- for(j = 0; j < x; j++)
- dw |= dw << (inc << j);
- *buf++ = dw;
- }
-}
-
-/*
-void
-main(void)
-{
- ulong buf[128];
-
- gbitexplode(0x7777, buf, 0, 3);
- exits(0);
-}
-*/
-
-void
-gbitblt(GBitmap *dm, Point pt, GBitmap *sm, Rectangle r, Fcode fcode)
-{
- int width; /* width in bits of dst */
- int wwidth; /* floor width in words */
- int height; /* height in pixels minus 1 */
- int sdep; /* src ldepth */
- int ddep; /* dst ldepth */
- int deltadep; /* diff between ldepths */
- int sspan; /* words between scanlines in src */
- int dspan; /* words between scanlines in dst */
- int soff; /* bit offset of src start point */
- int sdest; /* bit offset of src start point that matches doff when expanded */
- int doff; /* bit offset of dst start point */
- int delta; /* amount to shift src by */
- int sign; /* of delta */
- ulong *saddr;
- ulong *daddr;
- ulong *s;
- ulong *d;
- ulong mask;
- ulong tmp; /* temp storage source word */
- ulong sw; /* source word constructed */
- ulong dw; /* dest word fetched */
- ulong lmask; /* affected pixels in leftmost dst word */
- ulong rmask; /* affected pixels in rightmost dst word */
- int i;
- int j;
- ulong buf[32]; /* for expanding a source */
- ulong *p; /* pointer into buf */
- int spare; /* number of words already converted */
-
-
-#ifdef TEST
- curdm = dm;
- cursm = sm;
- curpt = pt;
- curr = r;
- curf = fcode;
-#endif
-
- gbitbltclip(&dm);
-
- width = r.max.x - r.min.x;
- if(width <= 0)
- return;
- height = r.max.y - r.min.y - 1;
- if(height < 0)
- return;
-
- ddep = dm->ldepth;
- pt.x <<= ddep;
- width <<= ddep;
-
- sdep = sm->ldepth;
- r.min.x <<= sdep;
- r.max.x <<= sdep;
-
- dspan = dm->width * W2L;
- sspan = sm->width * W2L;
-
- daddr = (ulong*)((WType)dm->base
- + dm->zero*W2L + pt.y*dspan
- + (pt.x >> LWBITS));
- saddr = (ulong*)((WType)sm->base
- + sm->zero*W2L + r.min.y*sspan
- + (r.min.x >> LWBITS));
-
- doff = pt.x & (WBITS - 1);
- lmask = WMASK >> doff;
- rmask = (WMASK << (WBITS - ((doff+width) & (WBITS-1))))&WMASK;
- if(!rmask)
- rmask = WMASK;
- soff = r.min.x & (WBITS-1);
- wwidth = ((pt.x+width-1)>>LWBITS) - (pt.x>>LWBITS);
-
- if(sm == dm){
-#ifdef TEST
- if(!FORCEBAKW &&
- (FORCEFORW || sm != dm || saddr > daddr ||
- (saddr == daddr && soff > doff)))
- ;
- else{
- daddr += height * dspan;
- saddr += height * sspan;
- sspan -= 2 * W2L * sm->width;
- dspan -= 2 * W2L * dm->width;
- }
-#else
- if(r.min.y < pt.y){ /* bottom to top */
- daddr += height * dspan;
- saddr += height * sspan;
- sspan -= 2 * W2L * sm->width;
- dspan -= 2 * W2L * dm->width;
- }else if(r.min.y == pt.y && r.min.x < pt.x)
- abort()/*goto right*/;
-#endif
- }
- if(wwidth == 0) /* collapse masks for narrow cases */
- lmask &= rmask;
- fcode &= F;
-
- deltadep = ddep - sdep;
- sdest = doff >> deltadep;
- delta = soff - sdest;
- sign = 0;
- if(delta < 0){
- sign = 1;
- delta = -delta;
- }
-
- p = 0;
- for(j = 0; j <= height; j++){
- d = daddr;
- s = saddr;
- mask = lmask;
- tmp = 0;
- if(!sign)
- tmp = *s++;
- spare = 0;
- for(i = wwidth; i >= 0; i--){
- if(spare)
- sw = *p++;
- else{
- if(sign){
- sw = tmp << (WBITS-delta);
- tmp = *s++;
- sw |= tmp >> delta;
- }else{
- sw = tmp << delta;
- tmp = *s++;
- if(delta)
- sw |= tmp >> (WBITS-delta);
- }
- spare = 1 << deltadep;
- if(deltadep >= 1){
- gbitexplode(sw, buf, sdep, deltadep);
- p = buf;
- sw = *p++;
- }
- }
-
- dw = *d;
- switch(fcode){ /* ltor bit aligned */
- case Zero: *d = dw & ~mask; break;
- case DnorS: *d = dw ^ ((~sw | dw) & mask); break;
- case DandnotS: *d = dw ^ ((sw & dw) & mask); break;
- case notS: *d = dw ^ ((~sw ^ dw) & mask); break;
- case notDandS: *d = dw ^ ((sw | dw) & mask); break;
- case notD: *d = dw ^ mask; break;
- case DxorS: *d = dw ^ (sw & mask); break;
- case DnandS: *d = dw ^ ((sw | ~dw) & mask); break;
- case DandS: *d = dw ^ ((~sw & dw) & mask); break;
- case DxnorS: *d = dw ^ (~sw & mask); break;
- case D: break;
- case DornotS: *d = dw | (~sw & mask); break;
- case S: *d = dw ^ ((sw ^ dw) & mask); break;
- case notDorS: *d = dw ^ (~(sw & dw) & mask); break;
- case DorS: *d = dw | (sw & mask); break;
- case F: *d = dw | mask; break;
- }
- d++;
-
- mask = WMASK;
- if(i == 1)
- mask = rmask;
- spare--;
- }
- saddr += sspan;
- daddr += dspan;
- }
-}
-
-#ifdef TEST
-void prprog(void);
-GBitmap *bb1, *bb2;
-ulong *src, *dst, *xdst, *xans;
-int swds, dwds;
-long ticks;
-int timeit;
-
-long
-func(int f, long s, int sld, long d, int dld)
-{
- long a;
- int sh, i, db, sb;
-
- db = 1 << dld;
- sb = 1 << sld;
- sh = db - sb;
- if(sh > 0) {
- a = s;
- for(i = sb; i<db; i += sb){
- a <<= sb;
- s |= a;
- }
- } else if(sh < 0)
- s >>= -sh;
-
- switch(f){
- case Zero: d = 0; break;
- case DnorS: d = ~(d|s); break;
- case DandnotS: d = d & ~s; break;
- case notS: d = ~s; break;
- case notDandS: d = ~d & s; break;
- case notD: d = ~d; break;
- case DxorS: d = d ^ s; break;
- case DnandS: d = ~(d&s); break;
- case DandS: d = d & s; break;
- case DxnorS: d = ~(d^s); break;
- case S: d = s; break;
- case DornotS: d = d | ~s; break;
- case D: d = d; break;
- case notDorS: d = ~d | s; break;
- case DorS: d = d | s; break;
- case F: d = ~0; break;
- }
-
- d &= ((1<<db)-1);
- return d;
-}
-
-void
-run(int fr, int to, int w, int op)
-{
- int i, j, f, t, fy, ty;
- extern long *_clock;
-
- fr += bb2->r.min.x;
- to += bb1->r.min.x;
- fy = bb2->r.min.y + 1;
- ty = bb1->r.min.y + 1;
- if(timeit) {
- memcpy(dst, xdst, dwds * sizeof(long));
- ticks -= *_clock;
- gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
- ticks += *_clock;
- return;
- }
- f = fr;
- t = to;
- memcpy(dst, xdst, dwds * sizeof(long));
- for(i=0; i<w; i++) {
- gbitblt(bb1, Pt(t,ty), bb2, Rect(f,fy,f+1,fy+1), op);
- gbitblt(bb1, Pt(t,ty+1), bb2, Rect(f,fy+1,f+1,fy+2), op);
- f++;
- t++;
- }
- memcpy(xans, dst, dwds * sizeof(long));
-
- memcpy(dst, xdst, dwds * sizeof(long));
- gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
-
- if(memcmp(xans, dst, dwds * sizeof(long))) {
- /*
- * print src and dst row offset, width in bits, and forw/back
- * then print for each of the four rows: the source (s),
- * the dest (d), the good value of the answer (g),
- * and the actual bad value of the answer (b)
- */
- print("fr=%d to=%d w=%d fb=%d%d\n",
- fr, to, w, FORCEFORW, FORCEBAKW);
- print("dst bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
- bb1->base, bb1->zero, bb1->width, bb1->ldepth,
- bb1->r.min.x, bb1->r.min.y, bb1->r.max.x, bb1->r.max.y);
- print("src bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
- bb2->base, bb2->zero, bb2->width, bb2->ldepth,
- bb2->r.min.x, bb2->r.min.y, bb2->r.max.x, bb2->r.max.y);
- for(j=0; 7*j < dwds; j++) {
- print("\ns");
- for(i=0; i<7 && 7*j+i < dwds; i++)
- print(" %.8lux", src[7*j + i]);
- print("\nd");
- for(i=0; i<7 && 7*j+i < dwds; i++)
- print(" %.8lux", xdst[7*j + i]);
- print("\ng");
- for(i=0; i<7 && 7*j+i < dwds; i++)
- print(" %.8lux", xans[7*j + i]);
- print("\nb");
- for(i=0; i<7 && 7*j+i < dwds; i++)
- print(" %.8lux", dst[7*j + i]);
- print("\n");
- }
- prprog();
- }
-}
-
-void
-prprog(void)
-{
- exits(0);
-}
-
-int
-main(int argc, char *argv[])
-{
- int f, t, w, i, sld, dld, op, iters, simple;
- ulong s, d, spix, dpix, apix, fpix, m, *ps, *pd;
- Point sorg, dorg;
- GBitmap *bs, *bd;
- long seed;
- char *ct;
-
- sld = 0;
- dld = 0;
- timeit = 0;
- iters = 200;
- simple = 0;
- ARGBEGIN {
- case 'i':
- iters = atoi(ARGF());
- break;
- case 's':
- simple = 1;
- break;
- case 't':
- timeit = 1;
- ct = ARGF();
- if(ct)
- iters = atoi(ct);
- break;
- } ARGEND
- if(argc > 0)
- sld = atoi(argv[0]);
- if(argc > 1)
- dld = atoi(argv[1]);
- if(!timeit && !simple) {
- seed = time(0);
- print("seed %lux\n", seed); srand(seed); /**/
- }
-
- print("sld %d dld %d\n", sld, dld);
- op = 1;
-
- /* bitmaps for 1-bit tests */
- bd = gballoc(Rect(0,0,32,1), dld);
- bs = gballoc(Rect(0,0,32,1), sld);
- for(i=0; i<bs->width; i++)
- bs->base[i] = lrand();
-
- /* bitmaps for rect tests */
- if(simple) {
- dorg = Pt(0,0);
- sorg = Pt(0,0);
- } else {
- dorg = Pt(nrand(63)-31,nrand(63)-31);
- sorg = Pt(nrand(63)-31,nrand(63)-31);
- }
- bb1 = gballoc(Rpt(dorg,add(dorg,Pt(200,4))), dld);
- bb2 = gballoc(Rpt(sorg,add(sorg,Pt(200,4))), sld);
- dwds = bb1->width * Dy(bb1->r);
- swds = bb2->width * Dy(bb2->r);
- dst = bb1->base;
- src = bb2->base;
- xdst = malloc(dwds * sizeof(long));
- xans = malloc(dwds * sizeof(long));
- for(i=0; i<swds; i++)
- src[i] = lrand();
- for(i=0; i<dwds; i++)
- xdst[i] = lrand();
-
-loop:
- print("Op %d\n", op);
- if(!timeit) {
- print("one pixel\n");
- ps = bs->base;
- pd = bd->base;
- FORCEFORW = 1;
- FORCEBAKW = 0;
- for(i=0; i<1000; i++, FORCEFORW = !FORCEFORW, FORCEBAKW = !FORCEBAKW) {
- f = nrand(32 >> sld);
- t = nrand(32 >> dld);
- s = lrand();
- d = lrand();
- ps[0] = s;
- pd[0] = d;
-#ifdef T386
- spix = (byterev(s) >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
- dpix = (byterev(d) >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
-#else
- spix = (s >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
- dpix = (d >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
-#endif
-#ifdef T386
- apix = byterev(func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld)));
-#else
- apix = func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld));
-#endif
- gbitblt(bd, Pt(t,0), bs, Rect(f,0,f+1,1), op);
- if(ps[0] != s) {
- print("bb src %.8lux %.8lux %d %d\n", ps[0], s, f, t);
- exits("error");
- }
- m = ((1 << (1<<dld)) - 1) << (32 - ((t+1)<<dld));
-#ifdef T386
- m = byterev(m);
-#endif
- if((pd[0] & ~m) != (d & ~m)) {
- print("bb dst1 %.8lux %.8lux\n",
- s, d);
- print("bb %.8lux %.8lux %d %d\n",
- ps[0], pd[0], f, t);
- prprog();
- exits("error");
- }
- if((pd[0] & m) != apix) {
- spix <<= 32 - ((f+1)<<sld);
- dpix <<= 32 - ((t+1)<<dld);
-#ifdef T386
- spix = byterev(spix);
- dpix = byterev(dpix);
-#endif
- print("bb dst2 %.8lux %.8lux\n",
- s, d);
- print("bb %.8lux %.8lux %d %d\n",
- ps[0], pd[0], f, t);
- print("bb %.8lux %.8lux %.8lux %.8lux\n",
- spix, dpix, apix, pd[0] & m);
- prprog();
- exits("error");
- }
- }
- }
-
- print("for\n");
- FORCEFORW = 1;
- FORCEBAKW = 0;
-
- for(i=0; i<iters; i++) {
- f = nrand(64);
- t = nrand(64);
- w = nrand(130);
- run(f, t, w, op);
- }
-
- if(sld == dld) {
- print("bak\n");
- FORCEFORW = 0;
- FORCEBAKW = 1;
-
- for(i=0; i<iters; i++) {
- f = nrand(64);
- t = nrand(64);
- w = nrand(130);
- run(f, t, w, op);
- }
- }
-
- if(op < F) {
- op++;
- goto loop;
- }
- if(timeit)
- print("time: %d ticks\n", ticks);
- exits(0);
-}
-
-
-#endif
--- a/os/boot/rpcg/flash.c
+++ /dev/null
@@ -1,212 +1,0 @@
-#include "boot.h"
-
-typedef struct Flashdev Flashdev;
-struct Flashdev {
- uchar* base;
- int size;
- uchar* exec;
- char* config;
- int conflen;
-};
-
-enum {
- FLASHSEG = 256*1024,
- CONFIGLIM = FLASHSEG,
- BOOTOFF = FLASHSEG,
- BOOTLEN = 3*FLASHSEG, /* third segment might be filsys */
- /* rest of flash is free */
-};
-
-static Flashdev flash;
-
-/*
- * configuration data is written between the bootstrap and
- * the end of region 0. the region ends with allocation descriptors
- * of the following form:
- *
- * byte order is big endian
- *
- * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
- */
-typedef struct Flalloc Flalloc;
-struct Flalloc {
- ulong check; /* checksum of data, or ~0 */
- ulong base; /* base of region; ~0 if unallocated, 0 if deleted */
- uchar len[3];
- uchar tag; /* see below */
- uchar sig[4];
-};
-
-enum {
- /* tags */
- Tdead= 0,
- Tboot= 0x01, /* space reserved for boot */
- Tconf= 0x02, /* configuration data */
- Tnone= 0xFF,
-
- Noval= ~0,
-};
-
-static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
-static char conftag[] = "#plan9.ini\n";
-
-static ulong
-checksum(uchar* p, int n)
-{
- ulong s;
-
- for(s=0; --n >= 0;)
- s += *p++;
- return s;
-}
-
-static int
-validptr(Flalloc *ap, uchar *p)
-{
- return p > (uchar*)&end && p < (uchar*)ap;
-}
-
-static int
-flashcheck(Flalloc *ap, char **val, int *len)
-{
- uchar *base;
- int n;
-
- if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
- return 0;
- base = flash.base+ap->base;
- if(!validptr(ap, base))
- return 0;
- n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
- if(n == 0xFFFFFF)
- n = 0;
- if(n < 0)
- return 0;
- if(n > 0 && !validptr(ap, base+n-1))
- return 0;
- if(ap->check != Noval && checksum(base, n) != ap->check){
- print("flash: bad checksum\n");
- return 0;
- }
- *val = (char*)base;
- *len = n;
- return 1;
-}
-
-int
-flashinit(void)
-{
- int len;
- char *val;
- Flalloc *ap;
- void *addr;
- long mbytes;
- char type[20];
-
- flash.base = 0;
- flash.exec = 0;
- flash.size = 0;
- if(archflashreset(type, &addr, &mbytes) < 0){
- print("flash: flash not present or not enabled\n"); /* shouldn't happen */
- return 0;
- }
- flash.size = mbytes;
- flash.base = addr;
- flash.exec = flash.base + BOOTOFF;
- flash.config = nil;
- flash.conflen = 0;
-
- for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
- if(0)
- print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
- if(ap->tag == Tconf &&
- flashcheck(ap, &val, &len) &&
- len >= sizeof(conftag)-1 &&
- memcmp(val, conftag, sizeof(conftag)-1) == 0){
- flash.config = val;
- flash.conflen = len;
- if(0)
- print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
- }
- }
- if(flash.config == nil)
- print("flash: no config\n");
- else
- print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
- if(issqueezed(flash.exec) == Q_MAGIC){
- print("flash: squeezed powerpc kernel installed\n");
- return 1<<0;
- }
- if(GLLONG(flash.exec) == Q_MAGIC){
- print("flash: unsqueezed powerpc kernel installed\n");
- return 1<<0;
- }
- flash.exec = 0;
- print("flash: no powerpc kernel in Flash\n");
- return 0;
-}
-
-char*
-flashconfig(int)
-{
- return flash.config;
-}
-
-int
-flashbootable(int)
-{
- return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == Q_MAGIC);
-}
-
-int
-flashboot(int)
-{
- ulong entry, addr;
- void (*b)(void);
- Exec *ep;
- Block in;
- long n;
- uchar *p;
-
- if(flash.exec == 0)
- return -1;
- p = flash.exec;
- if(GLLONG(p) == Q_MAGIC){
- /* unsqueezed: copy data and perhaps text, then jump to it */
- ep = (Exec*)p;
- entry = PADDR(GLLONG(ep->entry));
- p += sizeof(Exec);
- addr = entry;
- n = GLLONG(ep->text);
- if(addr != (ulong)p){
- memmove((void*)addr, p, n);
- print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
- }
- p += n;
- if(entry >= FLASHMEM)
- addr = 3*BY2PG; /* kernel text is in Flash, data in RAM */
- else
- addr = PGROUND(addr+n);
- n = GLLONG(ep->data);
- memmove((void*)addr, p, n);
- print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
- }else{
- in.data = p;
- in.rp = in.data;
- in.lim = p+BOOTLEN;
- in.wp = in.lim;
- n = unsqueezef(&in, &entry);
- if(n < 0)
- return -1;
- }
- print("entry=0x%lux\n", entry);
- uartwait();
- scc2stop();
- /*
- * Go to new code. It's up to the program to get its PC relocated to
- * the right place.
- */
- b = (void (*)(void))KADDR(PADDR(entry));
- (*b)();
- return -1;
-}
--- a/os/boot/rpcg/fns.h
+++ /dev/null
@@ -1,118 +1,0 @@
-Alarm* alarm(int, void (*)(Alarm*), void*);
-void alarminit(void);
-void archbacklight(int);
-char* archconfig(void);
-void archdisableuart(int);
-void archenableuart(int, int);
-void archenableusb(int);
-void archetherdisable(int);
-int archetherenable(int, int*, int*);
-int archflashreset(char*, void**, long*);
-void archinit(void);
-int archoptionsw(void);
-int bootp(int, char*);
-void cancel(Alarm*);
-void checkalarms(void);
-void clockinit(void);
-void clockintr(Ureg*, void*);
-void consinit(void);
-void cpminit(void);
-void cpuidprint(void);
-#define dcflush(a,b)
-void delay(int);
-void eieio(void);
-uchar* etheraddr(int);
-int etherinit(void);
-int etherrxpkt(int, Etherpkt*, int);
-int ethertxpkt(int, Etherpkt*, int, int);
-void exception(void);
-int flashboot(int);
-int flashbootable(int);
-char* flashconfig(int);
-int flashinit(void);
-void free(void*);
-void freeb(Block*);
-int getcfields(char*, char**, int, char*);
-char* getconf(char*);
-ulong getdec(void);
-ulong gethid0(void);
-ulong getimmr(void);
-ulong getmsr(void);
-ulong getpvr(void);
-int getstr(char*, char*, int, char*);
-ulong gettbl(void);
-ulong gettbu(void);
-int hardinit(void);
-long hardread(int, void*, long);
-long hardseek(int, long);
-long hardwrite(int, void*, long);
-long i2crecv(int, void*, long);
-long i2csend(int, void*, long);
-void i2csetup(void);
-void* ialloc(ulong, int);
-Block* iallocb(int);
-void idle(void);
-int isaconfig(char*, int, ISAConf*);
-int issqueezed(uchar*);
-void kbdchar(Queue*, int);
-void kbdinit(void);
-void kbdreset(void);
-void machinit(void);
-void* malloc(ulong);
-ulong mapalloc(RMap*, ulong, int, int);
-void mapfree(RMap*, ulong, int);
-void mapinit(RMap*, Map*, int);
-void meminit(void);
-void microdelay(int);
-void mmuinit(void);
-int optionsw(void);
-void panic(char*, ...);
-int parseether(uchar*, char*);
-int plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
-void putdec(ulong);
-void puthid0(ulong);
-void putmsr(ulong);
-int qbgetc(Queue*);
-void qbputc(Queue*, int);
-void qbwrite(Queue*, Block*);
-Block* qget(Queue*);
-long qlen(Queue*);
-Queue* qopen(int, int, void (*)(void*), void*);
-#define qpass qbwrite
-void scc2stop(void);
-void sccnmsi(int, int, int);
-void sched(void);
-void screeninit(void);
-void screenputs(char*, int);
-void sdraminit(ulong);
-Partition* sethardpart(int, char*);
-Partition* setscsipart(int, char*);
-void setvec(int, void (*)(Ureg*, void*), void*);
-int splhi(void);
-int spllo(void);
-void splx(int);
-void trapinit(void);
-void uartputs(char*, int);
-void uartsetboot(void (*f)(uchar*, int));
-void uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
-void uartwait(void);
-long unsqueezef(Block*, ulong*);
-
-#define GSHORT(p) (((p)[1]<<8)|(p)[0])
-#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))
-#define GLSHORT(p) (((p)[0]<<8)|(p)[1])
-#define GLLONG(p) ((GLSHORT(p)<<16)|GLSHORT(p+2))
-
-#define KADDR(a) ((void*)((ulong)(a)|KZERO))
-#define PADDR(a) ((((ulong)(a)&KSEGM)!=KSEG0)?(ulong)(a):((ulong)(a)&~KZERO))
-
-/* IBM bit field order */
-#define IBIT(b) ((ulong)1<<(31-(b)))
-#define SIBIT(n) ((ushort)1<<(15-(n)))
-
-#define IOREGS(x, T) ((T*)((char*)m->iomem+(x)))
-
-int uartinit(void);
-Partition* setuartpart(int, char*);
-long uartread(int, void*, long);
-long uartseek(int, long);
--- a/os/boot/rpcg/g.mx
+++ /dev/null
@@ -1,1987 +1,0 @@
-S0030000FC
-S325000100007C6000A63C800000608480427C632078606310007C0004AC7C6001247C0004AC52
-S325000100204C00012C7C908AA63C800A007C908BA64C00012C3C800C007C908BA64C00012C0A
-S325000100403C8004007C908BA64C00012C7C0004AC7C988AA63C800A007C988BA64C00012C2F
-S325000100603C800C007C988BA64C00012C3C8004007C988BA64C00012C388000077C9E23A6D3
-S325000100807CBE9AA63C80FA207C9E9BA63860FF88906400043C6001016063244090640000DE
-S325000100A0380000003C40001460427FF83C40001460427FF83C60FFC26063D7103882800866
-S325000100C07C0418004182002C38A2A1F87CA4285038A500037CA516707CA903A63884FFFC7B
-S325000100E03863FFFC84A3000494A400044200FFF83C60FFC2606302007C6803A64E80002026
-S325000101003862A1F8388227107C8320514081001C7C8416707C8903A63863FFFC3800000065
-S32500010120940300044200FFFC3822A3C89022801438210FF8380000004800AA01480086F587
-S32500010140480000003D00FA40806800003CA008007C63287890680000480000007C6000A6CC
-S325000101604E8000207C0004AC7C6001247C0004AC4C00012C4E8000207C0006AC4E800020AE
-S325000101804E8000207C6000A6606480007C0004AC7C8001247C0004AC4C00012C4E800020C4
-S325000101A07C6000A65464045E7C0004AC7C8001247C0004AC4C00012C4E8000207C8000A61A
-S325000101C0506404207C0004AC7C8001247C0004AC4C00012C4E8000207C6C42E64E80002062
-S325000101E07C7F42A64E8000207C7E9AA64E8000207C7602A64E8000207C7603A64E800020EE
-S325000102003821FF58BC4100303C40001460427FF87C9142A69081002C7CB042A690A10028B2
-S325000102207CC902A690C100247C8102A6908100207CB342A690A1001C7CD242A690C100187C
-S325000102407C9A02A6908100107CBB02A690A1000C90010008386100087C60092D3800000018
-S325000102604E800020B8410030800100287C1043A6800100247C0903A6800100207C0103A6A8
-S325000102808001001C7C0FF120800100187C1243A6800100107C1A03A68001000C7C1B03A671
-S325000102A08021002C4E8000207C3143A67C0000267C1343A67C0802A64BFFFF4938000000D6
-S325000102C04800AC294BFFFFA17C1242A67C0803A67C1042A64C00012C4C0000647FE802A6C1
-S325000102E097E1FFE84BFFFF05812280147064FFFF5484C23F418200802C0400204182006CA6
-S325000103002C040021418200587C0A0378914900143D00FA409109001C814900203CC0007AEE
-S3250001032060C6120090C9000C80EA028454E7653E394700018089000C7C8451D6908900086D
-S3250001034080E9001C3CC03E0090C7000083E100007FE803A6382100184E8000203D40000828
-S32500010360614A23A04BFFFFA83D400008614A23004BFFFF9C3D400008614A60004BFFFF9076
-S325000103807FE802A697E1FFE038629EC0480035D538629ED3480035CD4BFFFE49546A843E40
-S325000103A02C0A0006418101B4418201A42C0A0001418201902C0A00034182017C2C0A0004DD
-S325000103C04182016838629F0891410008480035954BFFFE117066FFFF90C1001038629F1CDA
-S325000103E081010010910100084800357938629F2E480035714BFFFDF5706AFFFF9141001881
-S325000104007D464671418201182C060020418201042C060021418200F038629F4F7D4846705C
-S32500010420910100084800353D38629F5A80810018708400FF90810008480035294800019D1D
-S325000104409061001038629F6880810010908100084800351138629F7880E2801480E7001C11
-S3250001046080E7000090E10008480034F98142801438629F87808A002080840284908100083C
-S3250001048080CA002080C6028090C1000C480034D538629FA481028014810800083D20000F84
-S325000104A0612942407D084BD691010008480034B538629FB5480034AD8142801438629FB75A
-S325000104C080AA002080A5010090A1000880EA002080E7010490E1000C4800348938629FD0EB
-S325000104E08082801480840020A084017A908100084800347183E100007FE803A638210020A9
-S325000105004E80002038629F47480034594BFFFF1C38629F404800344D4BFFFF1038629F3523
-S32500010520480034414BFFFF0438629EE7480034354BFFFEA038629EE0480034294BFFFE9459
-S3250001054038629ED94800341D4BFFFE8838629EEE480034114BFFFE7C2C0A00074182001C87
-S325000105602C0A0050418200084BFFFE5C38629F01480033F14BFFFE5C38629EF6480033E5A7
-S325000105804BFFFE507FE802A697E1FFF03862A0A7480033D180628014806300145463C23EF5
-S325000105A070630FFF2C03082340820028386000015463103A388283C07C6322148063000080
-S325000105C083E100007FE803A6382100104E8000207C0303784BFFFFDC806280148063001CB5
-S325000105E080630000706300F05463E13E4E8000208102801480C8000038E000327FE63B96AB
-S325000106007FFF39D67CDF30514082001480E8001C80C700006CC6080090C700004E8000204A
-S325000106207FE802A697E1FFF080A2801480A5002080A5010070A50001408200183860FFFF96
-S3250001064083E100007FE803A6382100104E80002038E2A0C490E100084800CDA18081001802
-S325000106603CC0FFC090C4000080E1001C3C800040908700007C03037883E100007FE803A666
-S32500010680382100104E8000207FE802A697E1FFE87C030000408100183860FFFF83E100003C
-S325000106A07FE803A6382100184E800020806100203882A0CE908100084800CD4180C10020CB
-S325000106C0390000029106001C3862A0D2480000CD7C671B787C030000418200148061002037
-S325000106E03863002C90E10008480029053860000183E100007FE803A6382100184E800020D1
-S325000107003821FFF0814280142C030004418200103860FFFF382100104E800020812A002075
-S32500010720810A001C80E8000064E7800090E80000A0E9095260E70A00B0E90952A0E9095055
-S3250001074070E7F5FFB0E9095080A1001838E0000790E500008101001C38A0000590A80000D5
-S325000107607C030378382100104E80002080A2801480A5001C808500003FE07FFF63FFFFFF28
-S325000107807FE42039908500004E8000204E8000204E8000204E8000207FE802A697E1FFD073
-S325000107A09061003480C284247C0600004082006048008929386000A93882C3A89081000806
-S325000107C038C0008090C1000C48008F4D7C0300004180019C3C600000606380A93882C3A88F
-S325000107E0388400809081000838C0008090C1000C48008F257C0300004180017438E000FF00
-S3250001080098E2C4A839000001910284243922C3A888C900002C0600FF4182001088E90000EA
-S325000108202C07000A408200187C03037883E100007FE803A6382100304E80002091210028DB
-S3250001084088A900002C05000A4182001088C900002C0600FF408201009121002C88C90000DE
-S325000108602C06003D40820050806100344800CB5D8121002C810100287C8848507C041800BF
-S3250001088040820034806100344800CB41906100188061003480A1002890A1000880E10018D9
-S325000108A090E1000C4800CAAD8121002C7C03000041820038888900002C04000A418200108F
-S325000108C088A900002C0500FF40820018888900002C04000A4082FF3C392900014BFFFF34AE
-S325000108E0392900014BFFFFD039490001890900002C08000A41820010888900002C0400FF0F
-S325000109004082004C38628048914100089121002C914100287CCA485090C1000C4800C64520
-S3250001092038E2804880A1002C7CE53A14810100287CE83850980700003862804883E10000D7
-S325000109407FE803A6382100304E800020392900014BFFFF9C88E900002C07003D4082000816
-S325000109604BFFFEF8392900014BFFFED83862A0D548002FF17C03037883E100007FE803A6C8
-S32500010980382100304E8000203821FFF080A2801480A500087CA51BD638A500087CA5267000
-S325000109A02C051000418000183865000F7C631E7060630001382100104E80002054A3083CA7
-S325000109C0382100104E8000207FE802A697E1FFD89061002C38600009900100084BFFFDB10C
-S325000109E0810280148128002080A90ABC60A500C090A90ABC9121002480A90AB83FE0FFFF7F
-S32500010A0063FFFF3F7FE5283990A90AB8806100304BFFFF798121002464680001910909F076
-S32500010A2080A90AE03FE0FFFF63FF0FFF7FE5283990A90AE038600001480032B18141002C75
-S32500010A407C691B783CA0FA2060A53E8090A10020B0650000906A00B43C8000006084B000FA
-S32500010A60B0830000B0030002390A00247508E0003CA020007C0828004182011038EA002401
-S32500010A8090E9000438600001480032618141002C7C691B7881010020B0680002906A00B88A
-S32500010AA038C03000B0C30000B003000238AA00A474A5E0003CE020007C053800418200B8F0
-S32500010AC0388A00A4908900047C03037839000009910100089001000C48003085812100205A
-S32500010AE038E0001898E9000438A0001898A9000539000001B109000638C00001B0C9002870
-S32500010B00B009002CB009002E39000001B1090030808280148084002039240A8038C000FF46
-S32500010B2098C9000691210018388000179889000A386000143CA0FFC260A50C9C90A1000854
-S32500010B4080E1002C90E1000C4800A1298121001838E04820B0E90002A0A9000260A500034A
-S32500010B60B0A9000283E100007FE803A6382100284E800020388A00A43FE0FFFF63FFFFFF4D
-S32500010B807FE420394BFFFF4038EA00243FE0FFFF63FFFFFF7FE738394BFFFEE87FE802A630
-S32500010BA097E1FFD08121003880A2801480A5002038A50A8038E000FF98E50006810900B4D3
-S32500010BC0910100207C0800004182001480810020A0840000708480004182009C816900B847
-S32500010BE07C0B00004182001491610020A08B0000708480004182001483E100007FE803A694
-S32500010C00382100304E8000203940FFFF80C900107C0600004182001C9121002C806900104E
-S32500010C2048009409816100208121002C7C6A1B782C0AFFFF4182002C994900A438C00001DD
-S32500010C40B0CB0002A08B000060848000B08B000083E100007FE803A6382100304E8000205B
-S32500010C609809000883E100007FE803A6382100304E80002080A9000C7C050000418200144C
-S32500010C8080810020A08400027C0400404181002481010020A0A8000060A59000B0A8000089
-S32500010CA083E100007FE803A6382100304E80002080A900187C0500004182002438690024D4
-S32500010CC080A10020A0A5000290A1000880E900187CE803A64E8000214BFFFFB89121002CF0
-S32500010CE080C900147C060000418200487C0A037881010020A10800027C0A40404080FF945C
-S32500010D00914100247CCA4A1488C600248069000C90C1000880E900147CE803A64E800021F9
-S32500010D208121002C80A10024394500014BFFFFC480610020A0630002480090E9906100183D
-S32500010D408063000480C1002C38C6002490C1000880810020A08400029081000C4800C2054A
-S32500010D608121001881010020A1080002808900047D044214910900048061002C8063000CE7
-S32500010D80912100084800920D4BFFFF087FE802A697E1FFE09061001C4BFFF4098121001CE2
-S32500010DA090610018888900087C0400004082001C80690010480092758121001C90610014A1
-S32500010DC02C03FFFF4082001C806100184BFFF3F183E100007FE803A6382100204E800020FF
-S32500010DE080C280B47C06000041820064810900B8A108000071088000418200084BFFFFF0E5
-S32500010E0080C1001498C900A480C900B838A00001B0A6000280C900B8A0A6000060A5800073
-S32500010E20B0A600007D284B7880A280B47C0500004082001038A0000198A800084BFFFF6872
-S32500010E407C05037898A800084BFFFF5C7C0A0378914100102C0A00644080FFA880C900B8BD
-S32500010E60A0C6000070C68000408200084BFFFF943860000148001C098121001C80C1001093
-S32500010E80394600014BFFFFCC7FE802A697E1FFE0906100243902C4B080A800047C050000DF
-S32500010EA04182001483E100007FE803A6382100204E8000209101001C38C0000190C8000476
-S32500010EC038601000900100089001000C90010010480090098121001C9069000C8101002C3A
-S32500010EE09068000038604000900100083CE0FFC260E70E8C90E1000C9121001048008FDDD1
-S32500010F00814100288121001C9069001080C100309066000080A1003490A90014388000094F
-S32500010F20908900007C0A000040820008394025807D234B78914100084BFFFA9183E10000AD
-S32500010F407FE803A6382100204E8000209062C4C84E8000207FE802A697E1FFD88181003017
-S32500010F607C6D1B7838C2C4B090C100247C0B03787C6A1B7891A1002C7D0D62147C0A40402C
-S32500010F804080002C88AA00007CA507742C05000A40820008396B0001394A000191A1002C04
-S32500010FA07D0D62147C0A40404180FFDC7C6C5A1448008E71818100308141002C7C6B1B7851
-S32500010FC07D856378398CFFFF7C0500004182005488AA00007CA507742C05000A40820018EF
-S32500010FE080CB000439060001910B00043900000D99060000808B000438C4000190CB00046B
-S325000110007D465378394A000188C6000098C400007D856378398CFFFF7C0500004082FFB477
-S3250001102080610024806300109161000848008F6583E100007FE803A6382100284E80002098
-S325000110403821FFF03902C4B088E800087C070000418200084BFFFFF4382100104E80002038
-S325000110607FE802A697E1FFE0812100289061002438A2C5707C0900004081001490A1001C6E
-S32500011080808500007C0400004082001483E100007FE803A6382100204E8000207D234B78B0
-S325000110A048008D819061001880630004808100249081000880E1002890E1000C4800BEA5F4
-S325000110C08121001880E10028808900047CE43A1490E900048061001C8063000091210008F4
-S325000110E048008EB183E100007FE803A6382100204E800020386000014E8000207FE802A6F1
-S3250001110097E1FFF08061001838A2819890A100084800C3517C0300004182001C8061001889
-S325000111203882819D908100084800C3397C03000040820038900281F83CC0002090C281FC04
-S32500011140386281F83863000838E281A290E100084800C2A9386281F883E100007FE803A6E2
-S32500011160382100104E8000207C03037883E100007FE803A6382100104E8000207FE802A63D
-S3250001118097E1FFE88082C5707C0400004082001C3C600001900100089001000C90010010E0
-S325000111A048008D399062C5708102C5747C080000418200108062C57448008CC19002C57465
-S325000111C0386281A74800279D3C60FFC2606311604BFFFD7D38C0FFFF90C2C5789002C57C8D
-S325000111E09002C5C09002C5C47C03037883E100007FE803A6382100184E8000207FE802A6DA
-S3250001120097E1FFD08181003890610034810100349101001C3942C57080E2801480E70000B0
-S3250001122090E1002C918100387C0C000040810140812A000491410028900A00047C0900006A
-S32500011240408200A0900A0054806A000048008CC981810038814100287C691B787C03000095
-S325000112604082008080C2801480C600008101002C7CC8305054C5083C7CC62A1454C6183850
-S3250001128054A5482C7CC6285038E000327CC63B9628063A984180FFB480EA005438E7000171
-S325000112A090EA00542C07000341800020386281C1480026B17C03037883E100007FE803A6D9
-S325000112C0382100304E800020386281D039000001910100084BFFFC81814100284BFFFF6C6B
-S325000112E080A9000480C900007D4628507C0A6000408100087D8A63788061001C91210020D6
-S3250001130080E9000090E10008914100249141000C4800BC5181610024814100288121002009
-S32500011320808900007CE45A1490E9000080E9000080C900047C073040418000507D234B7839
-S3250001134048008B39816100248141002880E100387D8B385080E1001C7CA75A1490A1001C06
-S32500011360918100387C0C00004181FEC88061001C80E100347C67185083E100007FE803A6BB
-S32500011380382100304E800020912A00044BFFFFC07FE802A697E1FFE0808100289081001C4B
-S325000113A08122C5C07C0900004081005880E1002C7C093800408100088121002C8102C5C077
-S325000113C07CC9405090C2C5C08061001C38E2C57038E7001090E10008912100189121000CDE
-S325000113E04800BB81812100188081001C7CE44A1490E1001C8081002C7CE9205090E1002CA1
-S3250001140080E1002C7C070000408100C83862815038A0004090A100084BFFFDE58141002C56
-S325000114207C691B782C030040408000187C03037883E100007FE803A6382100204E80002011
-S325000114407C035000408100307C8A48509082C5C03862C5703863001038A281507CA55214E4
-S3250001146090A1000880A2C5C090A1000C4800BAF58121002C8061001C38C2815090C1000862
-S32500011480912100189121000C4800BAD9812100188101002C7CC9405090C1002C8101001C8A
-S325000114A07CC84A1490C1001C80C2C57C38C6000190C2C57C386281D2388000019081000842
-S325000114C04BFFFA9580E1002C7C0700004181FF408061001C810100287C68185083E10000C4
-S325000114E07FE803A6382100204E8000203821FFE87C0B03782C0B0100408000545569C00E54
-S32500011500394000087C0A00004081002875248000418200445526083C3FE004C163FF1DB7DB
-S325000115207FE93278394AFFFF7C0A00004181FFE05567103A38A2DC307CE72A1491270000A5
-S32500011540396B00012C0B01004180FFB4382100184E8000205529083C4BFFFFCC7FE802A6EE
-S3250001156097E1FFF081410018906100148082DC347C0400004082000C4BFFFF758141001826
-S3250001158080C1001C3FE0FFFF63FFFFFF7FE8327881210014394AFFFF7C0A00004180003C9F
-S325000115A05505463E7D264B783929000188C600007CA5327854A5103A38C2DC307CA53214B4
-S325000115C080A500005507402E7CE82A78394AFFFF7C0A00004080FFCC3FE0FFFF63FFFFFF00
-S325000115E07FE3427883E100007FE803A6382100104E800020816100088121000C7C0B0000DE
-S32500011600408200148083000090890000912300004E80002080AB000090A90000912B00000F
-S325000116204E800020814100088121000C7C0A00004082001080890000908300004E800020DB
-S3250001164080C9000090CA00004E8000207FE802A697E1FFE87C09037838E2ED382C09000A06
-S325000116604080002C80C700047C0600004082001080A7000C7C0500004182003039290001CE
-S3250001168038E700142C09000A4180FFDC386282D8480023597C03037883E100007FE803A60F
-S325000116A0382100184E8000209007000C9007001038A0000190A700047CE33B7883E10000F0
-S325000116C07FE803A6382100184E8000207FE802A697E1FFD89061002C7C03000040800008D2
-S325000116E09001002C4BFFEABD906100184BFFFF61818280147C6A1B7880C1002C54C5083CA8
-S325000117007CC62A1454C620367CC62A1438E003E87CC63B9690C3000880A1003090A3000C51
-S3250001172080810034908300107C0B0378812C00187C0900004182003480A90008808A0008C4
-S325000117407C0520004181005480A90008808A00087CA5205090AA00087D2B4B7881290000A0
-S325000117607C0900004082FFD4386C001891610008914100249141000C4BFFFE7D8061001800
-S325000117804BFFEA3D8061002483E100007FE803A6382100284E800020808A00088109000845
-S325000117A07C844050908900084BFFFFC09003000C4E8000204E8000207FE802A697E1FFA8BF
-S325000117C04BFFE9E1814280149061004C812A00187C090000418200A47C0B03787C09000024
-S325000117E04182001080E900087C070000408100A47C0900004182001080E9000838E7FFFFD0
-S3250001180090E900087C090378916100507C095800408000685527103A3901001C7CE7421424
-S3250001182080E7000080E7000C7C07000041820028912100545523103A38C1001C7C63321457
-S32500011840806300007CE803A64E80002181610050812100545525103A3881001C7CA522148A
-S3250001186080A500009005000439290001916100507C0958004180FFA08061004C4BFFE94120
-S3250001188083E100007FE803A6382100584E8000202C0B000A418000084BFFFF589161005041
-S325000118A05568103A38C1001C7D08321491280000386A0018900100089121000C4BFFFD69C0
-S325000118C081428014812A001880E10050396700014BFFFF0CA121000A5527043E54E7C23E7B
-S325000118E098E300005526043E98C300014E800020814100085544463E988300005546843E00
-S3250001190098C300015548C23E99030002994300034E8000207C671B78886300005463C00E76
-S32500011920888700015484801E7C63237888A7000254A5402E7C632B7888C700037C633378AA
-S325000119404E8000207C671B78886300005463402E88A700017C632B784E8000203821FFD83C
-S325000119608222809C814100307C691B787C0F03787C0C03787C0B03787C100378706500014E
-S32500011980418200207C0A000041820014888900007D8C2214394AFFFF392900013A00000191
-S325000119A02C0A001041800054A0E90000A08900027D6B3A14A0C900047DAB2214A109000660
-S325000119C07DCD3214A0A900087DCE4214A0E9000A7DCE2A14A089000C7DCE3A14A0C9000E1D
-S325000119E07DAE22147D6D3214394AFFF0392900102C0A00104080FFB42C0A00024180001C9D
-S32500011A00A0C900007D6B3214394AFFFE392900022C0A00024080FFEC7C10000041820070A2
-S32500011A207C0A00004182000C88A900007DEF2A14889100007C8407747C0400004182004850
-S32500011A407DEF5A145588C23E7D2F4214718800FF5508402E7D2942145528843F41820014F0
-S32500011A607127FFFF7D283A145528843F4082FFF43FE0FFFF63FFFFFF7FE34A7838210028BF
-S32500011A804E8000207D8C5A144BFFFFBC7C0A00004182000C88A900007D8C2A1488910000EF
-S32500011AA07C8407747C0400004182000C7D8C5A144BFFFF947DEF5A144BFFFF8C3821FFF00A
-S32500011AC07C691B787C0B037888E3000070E7000F54EA103A7C0A00004081002888C900006C
-S32500011AE054C6402E890900017CC643787D6B3214394AFFFE392900027C0A00004181FFE08E
-S32500011B007168FFFF5566843E7D0832147104FFFF5507843E7C843A146883FFFF382100106E
-S32500011B204E8000207FE802A697E1FFD0906100343862B7C89061002C9001000838E005F059
-S32500011B4090E1000C4800B1E98061002C3863002A80A1003C90A10008810100409101000C57
-S32500011B604800B4018121002C80C1004039460008980900163900001199090017980900141C
-S32500011B80980900153869001891410020914100084BFFFD458061002C3863001A8102822090
-S32500011BA0910100084BFFFD4D8061002C38630022A0E2822490E100084BFFFD1D8061002C14
-S32500011BC03863001E8101003881080000910100084BFFFD218061002C3863002480810038FB
-S32500011BE0A0840004908100084BFFFCED8061002C3863002680E1002090E100084BFFFCD983
-S32500011C008121002C98090028980900293869001680E1004038E7001490E100084BFFFD41D0
-S32500011C205464043E908100188061002C3863002881010018910100084BFFFC9D3922B7C8B9
-S32500011C40810100403948002C390000459909000E9809000F390000FF990900169121002866
-S32500011C60386900109141002438AAFFF290A100084BFFFC6580610028386300128082801CAB
-S32500011C8038E4000190E2801C908100084BFFFC49812100289809001498090015980900187C
-S32500011CA0980900193869000E4BFFFE155468043E91010018806100283863001880810018DA
-S32500011CC0908100084BFFFC11806100283863000C39000800910100084BFFFBFD80610028B7
-S32500011CE080C1003838C6000690C10008388000069081000C4800B26D8061003438E2B7C817
-S32500011D0090E10008808100249081000C38E0138890E100104800471583E100007FE803A6B5
-S32500011D20382100304E8000207FE802A697E1FF60906100A49801001C38A0000598A1001DC2
-S32500011D409801001E80C100AC98C1001F3861001C3863000480C100B090C100084800B69D27
-S32500011D60806100B04800B66538830005806100A4810100A89101000838C1001C90C1000CED
-S32500011D80908100104BFFFDA180C100B47C0600004182001C38629C48810100AC9101000897
-S32500011DA080C100B090C1000C48001BB983E100007FE803A6382100A04E8000207FE802A648
-S32500011DC097E1FFD09061003480A281F47C0500004082029C392003E880828014808400003A
-S32500011DE05485083C7C842A145484183854A5482C7C84285038C000327C8433967C89221446
-S32500011E009081001880A2801480A5000054A6083C7CA5321454A5183854C6482C7CA530509A
-S32500011E2038E000327CA53B96810100187C082840408102288061003438E2BDB890E10008D1
-S32500011E4080828014808400005486083C7C8432145484183854C6482C7C84305038E00032FD
-S32500011E607C843B96810100187C8440509081000C480044319061002C7C0300004181000820
-S32500011E804BFFFF843882BDB8908100203864000C4BFFFAB55466043E2C060800418200086C
-S32500011EA04BFFFF64806100203863000E4BFFFC11812100207C0300004182001038629C5EC5
-S32500011EC048001AA14BFFFF4088E9000E2C0700454182001038629C6F48001A894BFFFF28A4
-S32500011EE0890900172C080011418200084BFFFF1898090016386900264BFFFA4D5466043EB6
-S32500011F00806100203863001890C1002890C100084BFFF9C580610020386300284BFFFA29FB
-S32500011F207C030000408200F480A10038A0A500047C050000418200208061002038630022A1
-S32500011F404BFFFA0581010038A10800047C0340004082FEB4806100203863001A4BFFF9B9E5
-S32500011F60814100389061001C80AA00003880FFFF7C0520004182001080AA00007C0328002E
-S32500011F804082FE8480C100283926FFF880C100407C0930004081001038629CA6480019C52E
-S32500011FA04BFFFE648061003C808100203884002A90810008912100289121000C4800AFA5FD
-S32500011FC080A1003880E1001C90E5000080610020386300224BFFF97181210038B069000446
-S32500011FE03869000638A2BDB838A5000690A1000838E0000690E1000C4800AF693880000114
-S32500012000908281F48061002883E100007FE803A6382100304E80002080610020386300168C
-S32500012020808100283884000C908100084BFFF9315469043E5528043E7C0800004182FEEC2C
-S3250001204038629C815527043E90E1000880E1002C90E1000C4800190D7C03037883E10000B5
-S325000120607FE803A6382100304E800020392013884BFFFD687FE802A697E1FDC89061023CB4
-S325000120809801002638E0000198E10027386100263863000238829CBB9081000880C10244B4
-S325000120A090C1000C48001879390300023861002638630001910102307C681A1438829CBE60
-S325000120C090810008480018598161024038A3000280C102307CA62A1490A10230A08B0004C1
-S325000120E0908102287C090378912102342C0900054080007081010228B10B00048061023CC1
-S325000121009161000838E1002690E1000C80810230908100104BFFFA1181210240B0090004B8
-S325000121208061023C9121000880A1024890A1000C39000204910100104BFFFC858161024047
-S32500012140812102482C0300044080003480C1023439260001912102342C0900054180FF9814
-S3250001216038629D05480017FD3860FFFF83E100007FE803A6382102384E8000208889000024
-S325000121805484402E88C900017C8433782C040003418200482C040005418200084BFFFFB0BE
-S325000121A038629CC488C9000254C6402E890900037CC6437890C1000838A9000490A1000C36
-S325000121C0480017A13860FFFF83E100007FE803A6382102384E8000203960000188890002C0
-S325000121E05484402E88C900037C843378916283E87C0458004182004838629CDE9081000825
-S32500012200480017618061023C80C1024090C10008388000019081000C38C29CF990C1001036
-S32500012220900100144BFFFB053860FFFF83E100007FE803A6382102384E8000203863FFFC87
-S3250001224083E100007FE803A6382102384E8000207FE802A697E1FFD0812283E890610034F9
-S325000122609801002038800004988100217D25467098A100229921002338A9000190A283E899
-S32500012280810100403908000491010040900100248061003480E1003890E1000838A1002089
-S325000122A090A1000C38E0000490E100104BFFF8798061003480E1003890E1000880A1003CFE
-S325000122C090A1000C81010040910100104BFFFAF1816100408141003C7C691B787C035800B2
-S325000122E04080006438629D2C912100089161000C480016718061003480C1003890C10008E2
-S32500012300388000029081000C38C29D4090C10010900100144BFFFA158101002438C8000102
-S3250001232090C100242C080005408000084BFFFF643860FFFF83E100007FE803A638210030E0
-S325000123404E800020890A00025508402E88AA00037D082B789101002C808283E87C082000FC
-S325000123604182007C38629D4B480015F9814283E88121002C38CAFFFF7C09300040820018B4
-S3250001238080A1002439050001910100242C0500084180FF0038629D4D912100089141000CE7
-S325000123A0480015C18061003480E1003890E1000838A0000190A1000C38E29D7590E100100E
-S325000123C0900100144BFFF9653860FFFF83E100007FE803A6382100304E8000203863FFFC92
-S325000123E083E100007FE803A6382100304E8000207FE802A697E1FC48906103BC48003E6981
-S32500012400814103C0906100C07C0300004082002838629D8180A103BC90A1000848001545A3
-S325000124203860FFFF83E100007FE803A6382103B84E8000209001002C900100287C0A00008D
-S325000124404182001488AA00007CA507747C050000408205C03861024C9001000838A0016C03
-S3250001246090A1000C4800A8C938E0000198E1024C390000019901024D388000069881024E35
-S325000124803861024C3863001C80A100C090A10008390000069101000C4800AAC990028220B1
-S325000124A038A00044B0A28224386282203863000680C100C090C10008388000069081000CEF
-S325000124C04800AAA1900100DC808100DC2C04000A4080009038C0FFFF90C2823838E0004331
-S325000124E0B0E2823C3862823838630006390283689101000838A0000690A1000C4800AA655E
-S32500012500806103BC390282389101000838A1024C90A1000C38E0016C90E100104BFFF609D2
-S32500012520806103BC38C2823890C10008390100E09101000C38A0016C90A100104BFFF881E6
-S325000125407C0300004181045C80C100DC38C6000190C100DC808100DC2C04000A4180FF783B
-S3250001256080C100DC2C06000A4180002038629D94480013F13860FFFF83E100007FE803A6F9
-S32500012580382103B84E8000208101002C7C0800004182040080A1002C88A500007CA5077423
-S325000125A07C050000418203EC8901010C7D0807747C0800004182001838629DA538E100E016
-S325000125C038E7002C90E100084800139938629DA9888100F490810008888100F59081000C2B
-S325000125E0888100F690810010888100F790810014A082823C908100188081002C9081001C2C
-S32500012600480013614BFFEA3D386100E0386300104BFFF30590628220A08283A438E4000126
-S32500012620B0E283A4B0828224386100E0386300144BFFF2E59062823838E00045B0E2823C60
-S32500012640806103BC38C2823890C100088121002C9121000C38C2C5C890C100104BFFFA19F5
-S325000126607C030000408000183860FFFF83E100007FE803A6382103B84E8000203882C5C8A9
-S3250001268039440004906100D82C030020418002CC890A00005508402E88CA00017D0833782A
-S325000126A05508801E88EA000254E7402E888A00037CE723787D083B782C0806EB4082029C2B
-S325000126C088EA000454E7402E88AA00057CE72B7854E7801E88CA000654C6402E890A000744
-S325000126E07CC643787CED337888AA000854A5402E890A00097CA5437854A5801E888A000AF6
-S325000127005484402E88CA000B7C8433787CAC2378890A000C5508402E88CA000D7D083378A8
-S325000127205508801E88EA000E54E7402E888A000F7CE723787D083B78910100C8918100CCDF
-S325000127407CC8621491A100D07CC66A1490C100C488AA001454A5402E890A00157CA54378B0
-S3250001276054A5801E888A00165484402E88CA00177C8433787CA5237838629DD090A100B491
-S325000127803FE01FFF63FFFFFF7FE8283991010008480011D14BFFE8AD38629DDF80C100D003
-S325000127A090C10008480011BD808100B43FE01FFF63FFFFFF7FE42039908100BC38E2C5C821
-S325000127C039A70024808100D83944FFE0816100D0916100D47C0A000040820050806103BC09
-S325000127E0388282389081000838E2C5C890E1000C39000200910100104BFFFA59816100D4F1
-S325000128007C6A1B787C030000408000183860FFFF83E100007FE803A6382103B84E800020D5
-S3250001282038C2C5C839A60004914100D87C0B5000418100087D6A5B78806100BC91A100B89B
-S3250001284091A10008914100DC9141000C4800A715818100CC814100DC80A100BC7D05521476
-S32500012860910100BC80A100B87DA5521491A100B880A100D47D6A285080A100D87D4A28502C
-S32500012880914100D8916100D47C0B00004181FF487C0C000040820088806103BC38C282380B
-S325000128A090C10008390000039101000C38A29DE690A10010900100144BFFF47138629DE9CC
-S325000128C080E100C890E1000880A100C490A1000C4800109138629DF1810100B4910100084C
-S325000128E0480010814BFFE75D4800137D4BFFD8B580C100B43FE01FFF63FFFFFF7FE630395B
-S325000129007CC803A64E8000217C03037883E100007FE803A6382103B84E80002038629DE24B
-S32500012920918100084800103D81A100B8814100D8816100CC916100D4900100CC80E100BC7F
-S3250001294038E70FFF3FE0FFFF63FFF0007FE7383990E100BC4BFFFE80806103BC38C28238B4
-S3250001296090C100089001000C39029DBF9101001038A0000190A100144BFFF3B13860FFFF7F
-S3250001298083E100007FE803A6382103B84E80002038C100E038C6006C90C1002C4BFFFC0CA8
-S325000129A03861024C3863001C390100E03908001C9101000838A0000690A1000C4800AB0D46
-S325000129C0814100287C030000418200084BFFFB7C88E100E12C0700014082FB7088C100E225
-S325000129E02C0600064082FB647C0A00004182FB747D435378388100E03884002C908100089A
-S32500012A004800AA617C0300004182FB584BFFFB3C38610030914100084800A9E13861003008
-S32500012A203880003A908100084800A2E17C0300004182004038E100309061002C7C0338001A
-S32500012A404182FA1488A3FFFF7CA507742C05005C408200084BFFFA0038C1003090C100289C
-S32500012A6038C3000190C1002C980300004BFFF9E8390100309101002C4BFFF9DC3821FFF081
-S32500012A807C691B7880A28014814500047D254B783929FFFF7C050000408100187C0703781A
-S32500012AA07C0750404080FFE838E700014BFFFFF4382100104E8000203821FFF08102801442
-S32500012AC0810800047D0341D638A003E87D482BD741810008394000017C0903787C095040E8
-S32500012AE040800010392900017C0950404180FFF8382100104E8000207FE802A697E1FFF002
-S32500012B00806280284BFFD6F580A2801480E5000038E7000190E500004BFFECA18102823053
-S32500012B207C0800004182000C7D0803A64E80002183E100007FE803A6382100104E80002053
-S32500012B407FE802A697E1FFB88142801480CA000838E003E87CC63BD690CA00044BFFD67D36
-S32500012B60906100443860000A4BFFFF154BFFD66D808100447CE4185090E100447C07000047
-S32500012B80408000084BFFFFD83861002881028014810800049101000848009D69386100203F
-S32500012BA0810280148108000C5504103A7D0822145508083C38A003E87D082BD69101000880
-S32500012BC048009D253861003039010008392100288089000080A900049088000090A80004CD
-S32500012BE038A1001038C10020810600008126000491050000912500044800A0DD38610028C4
-S32500012C00810100445508103A9101000848009CD93861003838C10008390100308128000004
-S32500012C208088000491260000908600043881001038A1002880C500008105000490C40000C3
-S32500012C40910400044800935939010004392100388089000080A900049088000090A8000446
-S32500012C6048009DD581428014906A0004810A00047C0800004082000C38800001908A000486
-S32500012C8080AA000C38C000047CA533D638E000327CA53BD63865FFFF906280284BFFD55DA4
-S32500012CA083E100007FE803A6382100484E8000207FE802A697E1FFE89061001C7C0903788F
-S32500012CC080A282347C09280040800060912100145523103A38C226107C6332148063000088
-S32500012CE08101001C910100084800A779812100147C030000408200245523103A38822690E0
-S32500012D007C6322148063000083E100007FE803A6382100184E8000203929000180A28234A6
-S32500012D207C0928004180FFA87C03037883E100007FE803A6382100184E8000207FE802A69B
-S32500012D4097E1FF28816100E03CE0002090E100A87C0300004182021080E280A080E7000079
-S32500012D6090E1000838E100B490E1000C48002AA9814100A87C030000418100183860FFFF15
-S32500012D8083E100007FE803A6382100D84E800020980A0000386100B49141000838A003FFF6
-S32500012DA090A1000C48001FA57C6A1B787C030000418100183860FFFF83E100007FE803A6E7
-S32500012DC0382100D84E80002080A100A87CA51A1498050000806100A838630400810100A8C6
-S32500012DE09101000838CA000190C1000C4800A175808100A8396404007D6A5B787D6C5B78B4
-S32500012E00888A00007C8407747C04000041820028890A00007D0807742C08000D4082011804
-S32500012E20394A0001888A00007C8407747C0400004082FFE0980B00007D83637838E10020A2
-S32500012E4090E10008388000209081000C38C2886B90C1001048005EF1906100AC7C0A03787A
-S32500012E60808100AC7C0A200040800044914100B05543103A38A100207C632A148063000097
-S32500012E8038E0003D90E1000848009E8181828234814100B07C03000040820028394A0001DE
-S32500012EA0808100AC7C0A20004180FFC47C03037883E100007FE803A6382100D84E800020A7
-S32500012EC039630001980300005547103A390100207CE7421480E700007CE758502C07001DF8
-S32500012EE0418000185546103A38A100207CC62A1480C600009806001B5587103A38A226105F
-S32500012F007CE72A145546103A38A100207CC62A1480C6000090C700005588103A38C2269037
-S32500012F207D08321491680000388C0001908282344BFFFF6C888A00007C8407742C040009BE
-S32500012F404082000C38E0002098EA00007D685B78396B0001892A00007D29077499280000F0
-S32500012F604BFFFEC07C0B00004182005C7D635B7890010008388003FF9081000C4800A5BDCF
-S32500012F807C030000408200183860FFFF83E100007FE803A6382100D84E8000203862885036
-S32500012FA0480009C1806100A880E100E090E100084800A449806100A84800A4117C6A1B7881
-S32500012FC04BFFFE144BFFD5C190610018806100A880C1001890C100084800A421806100A8D4
-S32500012FE04800A3E97C6A1B784BFFFDEC7FE802A697E1FFD89061002C8121003088A90000CC
-S325000130007CA507742C050020408200183929000188A900007CA507742C0500204182FFF0AF
-S325000130207C0A03789141001C2C0A0006408000C0888900007C8407747C04000040820018F8
-S325000130403860FFFF83E100007FE803A6382100284E8000203889000188A900007CA5077461
-S3250001306098A10024890400007D0807747C080000408200183860FFFF83E100007FE803A6F7
-S32500013080382100284E8000203904000191010020888400007C840774988100259801002646
-S325000130A03861002490010008388000109081000C48009EB58141001C812100208101002CE5
-S325000130C07D08521498680000890900007D0807742C08003A4082000839290001394A00014D
-S325000130E09141001C2C0A00064180FF487C03037883E100007FE803A6382100284E800020BA
-S325000131007FE802A697E1FFB87C691B783861002C3902886D910100089121000C81010050D3
-S3250001312091010010480007F97C09037880C282347C093000408000489121001C5523103A59
-S3250001314038E226107C633A14806300003881002C9081000838C0001C90C1000C4800A1F5BB
-S325000131608121001C7C030000418200283929000180C282347C0930004180FFC07C03037896
-S3250001318083E100007FE803A6382100484E80002081010054900800345525103A388226904F
-S325000131A07CA5221480A5000090A1002880E1002888E700007CE707747C07000041820040D7
-S325000131C080C1002888C600007CC607742C0600204182035080E1002888E700007CE7077436
-S325000131E02C0700094182033C80C1002888C600007CC607747C060000408200183860000121
-S3250001320083E100007FE803A6382100484E80002080610028388288729081000838C00005D1
-S3250001322090C1000C4800A12D814100547C030000408200D48101002839080005910100283F
-S325000132407D49537838CA001B7C0930404080002C80A1002888A500007CA507747C05000045
-S325000132604182001880C1002888C600007CC607742C0600204082005C9809000080810028BE
-S32500013280888400007C8407747C0400004182FF2081010028890800007D0807742C080020AF
-S325000132A0408200084BFFFF0880810028888400007C8407742C040009408200084BFFFEF001
-S325000132C080A1002838A5000190A100284BFFFFB080E1002888E700007CE707742C0700095C
-S325000132E04182FF9880A10028388500019081002888A500007CA5077498A9000039290001C0
-S325000133004BFFFF448061002838E2887890E10008388000059081000C4800A0397C03000003
-S3250001332040820028806100283863000539010028910100089001000C48009C2D80A10054D4
-S325000133409065001C4BFFFF388061002838A2887E90A1000838E0000490E1000C48009FF53D
-S325000133607C03000040820028806100283863000438C1002890C100089001000C48009BE952
-S3250001338081010054906800204BFFFEF480610028390288839101000838A0000490A1000CFA
-S325000133A048009FB17C03000040820028806100283863000438810028908100089001000CC6
-S325000133C048009BA580C10054906600244BFFFEB08061002838C2888890C10008390000050D
-S325000133E09101000C48009F6D7C03000040820028806100283863000538E1002890E1000808
-S325000134009001000C48009B6180810054906400284BFFFE6C806100283882888E90810008AD
-S3250001342038C0000390C1000C48009F29812100547C0300004082003C3869002C80A1002894
-S3250001344038A5000390A100084BFFFBA52C03FFFF4082FE2C806100543863002C90010008B4
-S32500013460388000069081000C480098C54BFFFE1080C900342C0600084080FE0480A9003497
-S3250001348054A520367CA54A143945003881010028890800007D0807747C0800004182001807
-S325000134A080E1002888E700007CE707742C07002040820018980A000080C9003438C60001E4
-S325000134C090C900344BFFFDB881010028890800007D0807742C080009408200084BFFFFD8F6
-S325000134E07D445378394A000180A10028390500019101002888A500007CA5077498A400006E
-S325000135007CE9505081090034550820367CE8385038E7FFC82C07000F4180FF744BFFFF9805
-S325000135208101002839080001910100284BFFFC947FE802A697E1FFF09061001480C1001830
-S3250001354090C100084BFFDA118061001480A1001890A100084800729183E100007FE803A6B0
-S32500013560382100104E8000207FE802A697E1FFD0386295484BFFF73D7C691B787C090000A5
-S32500013580418200247D234B789121002C38A2955B90A1000848009C7D8121002C7C0300004B
-S325000135A04182009C3C80FFC260841054908282F4900100247C090000418200187D234B78E0
-S325000135C0900100089001000C4800999D90610024900100283862955F4BFFF6D981210028F1
-S325000135E07C03000041820014900100089001000C480099757C691B787C090000408200081B
-S32500013600392025808061002491210008388281909081000C38C281D890C100103D00FFC24C
-S325000136206108374C910100144BFFD86183E100007FE803A6382100304E8000203CE0FFC2A6
-S3250001364060E7363090E282F44BFFFF687FE802A697E1FFF09061001480C1001870C8007F92
-S32500013660910100182C08001040820010386295644800037981010018806100149101000803
-S3250001368048006A4D83E100007FE803A6382100104E8000207FE802A697E1FFE090610024DE
-S325000136A09001001880C2801480C6000090C100148101002C7C0800004182001C80A2801412
-S325000136C080A5000080C100147CA62850280500FA4181010480628190480069517C691B7874
-S325000136E02C03FFFF408200084BFFFFC82C03000D408200083920000A2C09007F40820008D4
-S32500013700392000089121001C2C090015408200C03900000A99010013386100133880000152
-S325000137209081000880C282F47CC803A64E80002181810024816100288141001C812100180D
-S325000137402C0A0008408200187C0900004081FF5838E9FFFF90E100184BFFFF4C2C0A000A30
-S32500013760408200207CEC4A14980700007D234B7883E100007FE803A6382100204E800020BD
-S325000137802C0A0015408200183860FFFF83E100007FE803A6382100204E8000207C095800AF
-S325000137A0408200187D635B7883E100007FE803A6382100204E8000203909000191010018AD
-S325000137C07C8C4A14994400004BFFFEDC992100134BFFFF483860FFFE83E100007FE803A614
-S325000137E0382100204E8000207FE802A697E1FFE090610024808100289804000080E100308A
-S325000138007C0700004182001880810030888400007C8407747C040000408200FC7C06037850
-S3250001382090C10018808100187C040000418200683862956780C1002490C1000880810030CF
-S325000138409081000C4800011D8061002880E1002C90E1000880C1001890C1000C4BFFFE3998
-S325000138607C691B782C03FFFE4182008C2C03FFFF4182FFB48101002C7C0940004180002C4B
-S3250001388038629580480000DD808100187C0400004082FFA03862957980E1002490E10008AD
-S325000138A0480000C14BFFFFA47C0900004082001080E100187C070000408200187C030378E4
-S325000138C083E100007FE803A6382100204E8000208061002880A1003090A1000848009B1D73
-S325000138E07C03037883E100007FE803A6382100204E8000203862957E38800001908100086D
-S3250001390080C282F47CC803A64E8000217C0903784BFFFF6438C000014BFFFF087FE802A606
-S3250001392097E1FFE89061001C38C3010090C10008808100209081000C38E1002038E7000425
-S3250001394090E10010480007F18081001C7C64185083E100007FE803A6382100184E80002067
-S325000139607FE802A697E1FEE09061012480E282F47C070000408200187C03037883E1000032
-S325000139807FE803A6382101204E8000203861002038C1002038C6010090C1000881010124D7
-S325000139A09101000C38C1012438C6000490C1001048000785390100207C881850386100208E
-S325000139C09081001C90810008810282F47D0803A64E8000218061001C83E100007FE803A613
-S325000139E0382101204E8000207FE802A697E1FEE0812282F4906101247C0900004182007408
-S32500013A003862958F38800007908100087D2803A64E8000213861002038A1002038A501003C
-S32500013A2090A1000880E1012490E1000C38A1012438A5000490A10010480006FD38E100209F
-S32500013A407D071850386100209101000880E282F47CE803A64E8000213862959738800001CD
-S32500013A609081000880C282F47CC803A64E8000214BFFC7154BFFC70D4BFFFFFC7FE802A6FA
-S32500013A8097E1FFE0808280148124002038C0000190C90030808908403FE0FFFF63FFFFFE1E
-S32500013AA07FE4203990890840B0090968B0090964B0090960B0090962B0090966B009095210
-S32500013AC0B0090950B0090954B009095690090ABC90090AB8B0090AC29121001C90090AC42B
-S32500013AE04BFFC6998101001C3CA0000060A58001B0A809C080C1001CA0C609C070C6000132
-S32500013B00418200184BFFC67580C1001CA0C609C070C600014082FFF0386281E038E2B3C83A
-S32500013B2090E10008388004009081000C480065E9386281E03CC0FA2060C6240090C10008E2
-S32500013B40390004009101000C480065F183E100007FE803A6382100204E8000207FE802A6FB
-S32500013B6097E1FFE89061001C4BFFC639906100108102801481080020910100144BFFC5FD16
-S32500013B8081010014A10809C071080001418200184BFFC5E981010014A10809C07108000147
-S32500013BA04082FFF08081001C5484402E80A1002054A520367C842B7880C1002454C6083CF4
-S32500013BC07C8433786084000180A10014B08509C04BFFC5A980E10014A0E709C070E7000146
-S32500013BE0418200184BFFC59580E10014A0E709C070E700014082FFF0806100104BFFC5C1B0
-S32500013C0083E100007FE803A6382100184E8000203821FFE85465183838A5FFF8810100200B
-S32500013C20710800075508183880E1002470E700077D083B787D0B283080E280148127002097
-S32500013C4080E90AEC390000FF7D0828307D0840F87CE740387CE75B7890E90AEC382100183B
-S32500013C604E8000207FE802A697E1FFE080E2801480E7002039270A209121001C80E90000AB
-S32500013C8070E70030418200543860000538C0000490C100089001000C4BFFFEC53860000744
-S32500013CA039000004910100089001000C4BFFFEB1386000014BFFEDC980A1001C80E5000055
-S32500013CC03FE0FFFF63FFFFCF7FE7383990E50000386000044BFFCA9983E100007FE803A687
-S32500013CE0382100204E8000207FE802A697E1FFE07C681B78386281E0900100085507183839
-S32500013D0090E1000C90010010480065997C681B789061001C7C030000408200103862833B0B
-S32500013D204BFFFCC98101001C7D03437883E100007FE803A6382100204E8000207FE802A6AA
-S32500013D4097E1FFE89061001C7C030000418200384BFFC4298121001C386281E07528E00009
-S32500013D603CA020007C0828004182002C7D274B7890E1000880810020548418389081000C5F
-S32500013D80480063B983E100007FE803A6382100184E8000203FE0FFFF63FFFFFF7FE7483981
-S32500013DA04BFFFFD07FE802A697E1FFE83E0000006210900081E1002481C100207C6A1B78D4
-S32500013DC091C3000C9061001C80E300007C070000408200247DC373784BFFFF113E000000E0
-S32500013DE06210900081E1002481C100208141001C906A000080C1002838C6000F3FE0FFFF67
-S32500013E0063FFFFF07FED3039808A00047C0400004082002C91A100287C6E69D64800518558
-S32500013E203E0000006210900081E1002481C1002081A100288141001C906A000480CA0000E3
-S32500013E407C060000418201A880AA00047C0500004182019C80AA000474A5E0003CC020001B
-S32500013E607C05300041820174808A00047C8C23787C0B03787C0B700040800044556418389B
-S32500013E8080EA00007C843A14B004000255661838808A00007CC622149186000455651838FB
-S32500013EA0810A00007CA54214B20500007D8C6A14396B00017C0B70004180FFC4556818388E
-S32500013EC080CA00007D083214A0A8FFF860A52000B0A8FFF8900A000891EA0020808A0010BC
-S32500013EE07C040000408200187DE37B784BFFFDFD81E100248141001C906A0010810A0014BD
-S32500013F007C0800004082001855E3103A4800509581E100248141001C906A001480EA0010A1
-S32500013F207C070000418200A080CA00147C060000418200947C0B03787C0B7800408000504C
-S32500013F405567103A80AA00147CE72A14900700005564183880EA00107C843A149004000475
-S32500013F6055661838808A00107CC62214B00600025568183880CA00107D083214B0080000FB
-S32500013F80396B00017C0B78004180FFB855651838810A00107CA54214A0E5FFF860E72000FF
-S32500013FA0B0E5FFF8900A0018900A001C900A00247C03037883E100007FE803A63821001869
-S32500013FC04E8000203860FFFF83E100007FE803A6382100184E800020808A00043FE0FFFF58
-S32500013FE063FFFFFF7FE420394BFFFE843860FFFF83E100007FE803A6382100184E80002069
-S325000140003821FFF0818282D0816100187C6A1B782C0B00094082005C7D8B6378388C00087C
-S325000140203FE0FFFF63FFFFF87FEC20397D675B78396B0001918282D07C07600040800014C7
-S32500014040808A0000810A00047C0440404180000C382100104E80002080EA000039270001D1
-S32500014060912A000038800020988700004BFFFFC080A30000808300047C0520404080001C97
-S325000140808103000039280001912300009968000038AC000190A282D02C0B000A408200080A
-S325000140A0900282D0382100104E800020814283E07C6907747D26077470C6007F7CC90774A5
-S325000140C07D24077438C285A87C843214888400007C8407747C0400004082002C2C0A001E07
-S325000140E04180000C386000014E8000207D26077438E285A87CC63A14390A0001910283E036
-S32500014100994600007D250774390285A87CA5421488A500007CA5077454A5103A38C284D063
-S325000141207CA5321480E1000890E500007C0303784E8000207FE802A697E1FFC890610018F4
-S3250001414080E1004090E1001C80810048908100208141004438EA000190E10044894A0000FF
-S325000141607D4A07742C0A0025418200487C0A00004082003080A1001880E1001C7C05384069
-S325000141804080000C80810018980400008061001883E100007FE803A6382100384E800020AB
-S325000141A038610018914100084BFFFE594BFFFFA49001002438A0FFFF90A100289001002C3E
-S325000141C03967000191610044894700007D4A07747C0C03782C0A002D4082001C39800001F1
-S325000141E07D6A5B78396B000191610044894A00007D4A07742C0A00304180000C2C0A00396C
-S325000142004081010C7C0C00004182001080A100247D050050910100242C0A002E41820084F6
-S325000142207C0A00004082000C38CBFFFF90C100443861001838A285A87146007F7CA5321438
-S3250001424088A500007CA5077454A5103A38C284D07CA5321480A500007CA803A64E800021B5
-S325000142607C0300004080002C7CA300508081002C7C852B7890A1002C81410044396A000185
-S3250001428091610044894A00007D4A07744BFFFF9480E100207CE71A1490E100204BFFFEB450
-S325000142A07D6A5B78396B000191610044894A00007D4A07742C0A00304180FF682C0A003950
-S325000142C0408100084BFFFF5C808100287C040000408000089001002880C1002854C5103A73
-S325000142E07CC62A1454C6083C7CC6521438C6FFD090C100287D6A5B78396B00019161004456
-S32500014300894A00007D4A07744BFFFFAC810100245507103A7D083A145508083C7D085214E1
-S325000143203908FFD0910100247D6A5B78396B000191610044894A00007D4A07744BFFFEB806
-S325000143407FE802A697E1FFE0906100244800907D7C6A1B789061001C80E1002C7C070000F0
-S325000143604180003C9141001C80C1002C7C0A30004080002C80610028388000209081000842
-S325000143804BFFFC8180C1001C394600019141001C80C1002C7C0A30004180FFDC81610024BF
-S325000143A07D665B78396B00019161001488C600007CC607747C0600004182003480E1003080
-S325000143C07C0700004182FFDC8061002890C100084BFFFC31816100148141001C8101003056
-S325000143E03908FFFF910100304BFFFFB880C1002C7C0600004080004880A1002C7D0500509E
-S325000144009101002C9141001C80A1002C7C0A28004080002C80610028390000209101000806
-S325000144204BFFFBE180A1001C394500019141001C80A1002C7C0A28004180FFDC83E10000AA
-S325000144407FE803A6382100204E8000207FE802A697E1FFA881C282E881A100607C6C1B7806
-S325000144607C0F037880C3001470C600072C0600044181015C418201442C060001418201281F
-S325000144802C0600024182010080AC00088145000038E0000490E1002880CC001470C60004D4
-S325000144A04082000C7C0A0000418000D0980100573960001C7FEA6B967FFF69D67CFF505029
-S325000144C0392700302C09003940810014392900277C0E0000418200083929FFE038C1003AB0
-S325000144E07CC65A14992600002C0B0002408000547C0F0000418200183881003A396BFFFFFE
-S325000145007C845A1438A0002D98A400003861003A7C635A149181000880EC000C90E1000CB6
-S3250001452038E0FFFF90E100104BFFFE198061002883E100007FE803A6382100584E80002060
-S325000145407D4A6B96810C00107C0800004180001880EC00103900001E7CE740507C0B38000D
-S32500014560408000107C0A0000418100084BFFFF84396BFFFF4BFFFF407D4A005039E00001EB
-S325000145804BFFFF2C80AC000880A500007CA907347D2407347C8A2378388000049081002874
-S325000145A04BFFFEF8808C00088144000038C0000490C100284BFFFEE4810C000881480000DC
-S325000145C038A0000490A100284BFFFED02C060005418200302C060006418200084BFFFEAC66
-S325000145E080AC000880A500007CA907345524043E7C8A237838800004908100284BFFFE9CC6
-S3250001460080E300088147000038800004908100284BFFFE887FE802A697E1FFE87C671B78B7
-S32500014620386280B890E100089001000C3880FFFF908100104BFFFD0D7C03037883E1000002
-S325000146407FE803A6382100184E8000207FE802A697E1FFE07C681B7880E3000880E7000035
-S3250001466098E1001E9801001F3861001E910100088088000C9081000C3880FFFF908100108B
-S325000146804BFFFCC13860000483E100007FE803A6382100204E8000207FE802A697E1FFF01F
-S325000146A03900000A910100084BFFFDA583E100007FE803A6382100104E8000203860FFFECA
-S325000146C04E8000203860FFFF4E8000207FE802A697E1FFF038E0000890E100084BFFFD719A
-S325000146E083E100007FE803A6382100104E8000207FE802A697E1FFE87C671B788063000819
-S325000147008063000090E100088107000C9101000C81070010910100104BFFFC2938600004BF
-S3250001472083E100007FE803A6382100184E8000203860FFFC4E8000207FE802A697E1FFF0A8
-S3250001474038A0001090A100084BFFFD0583E100007FE803A6382100104E8000207FE802A60B
-S3250001476097E1FFE839000001910282E838C0001090C100084BFFFCD9900282E883E10000BC
-S325000147807FE803A6382100184E8000207FE802A697E1FFF038E0002590E100084BFFF865D0
-S325000147A07C03037883E100007FE803A6382100104E8000207FE802A697E1FFD89061002CB2
-S325000147C03862889880A1003090A100084BFFF19581A100308181002C3942A1F83902A1F856
-S325000147E0390801407C0A40404080003080CA00047C0D30004082001080EA000C7C0C38002B
-S32500014800418201B4394A00143902A1F8390801407C0A40404180FFD83962A1F838C2A1F8C7
-S325000148203946001438C2A1F838C601407C0A30404080002C808A0000810B00007C044000D4
-S32500014840418100087D4B5378394A001438C2A1F838C601407C0A30404180FFDC7D6A5B783F
-S3250001486080CC001480EC00107D6639D69141002480CA00087C0600004182011480AA001087
-S325000148807C055800418001089161001C916A0010386288BD80AC000C7CAD2A14810C00103A
-S325000148A07CA541D690A100084BFFF0B98141002C806A000080EA000C812100307CE93A14BA
-S325000148C080AA00107CE729D690E1000880AA00087CA803A64E8000218141002C7C03000061
-S325000148E040800020386288CF4BFFF0797C03037883E100007FE803A6382100284E80002050
-S32500014900806A00008101002481080008910100088101001C9101000C80CA00047CC803A65E
-S325000149204E800021816100308141002480A1001C7C03280041820020386288E14BFFF02560
-S325000149407C03037883E100007FE803A6382100284E8000208082801480840000908A0000BF
-S3250001496080C1002C90CA000C916A0004386288F3916100084BFFEFED8061002483E10000C0
-S325000149807FE803A6382100284E8000207D635B789161001C90010008480045818161001C2B
-S325000149A08141002481A100308181002C906A00084BFFFED89141002480A2801480A5000097
-S325000149C090AA0000386288A791A100084BFFEF958061002483E100007FE803A638210028CB
-S325000149E04E8000207FE802A697E1FFD89061002C3862890580E1003090E100084BFFEF6577
-S32500014A00816100308141002C2C0B0002418001AC80EA00347C0B3800408001A0810A003867
-S32500014A202C08000C418201802C080010418200183860FFFF83E100007FE803A63821002841
-S32500014A404E800020556B083C810A0030812A00107D0849D6916100247C0B40404180001451
-S32500014A60386289114BFFEF85816100248141002C808A001080EA00147C8439D67C8B2396E2
-S32500014A80810A00147C8441D680EA003C7C843A1480EA0010810A00147CE741D67FEB3B9697
-S32500014AA07FFF39D67CFF585090E100187D43537890810020908100084BFFFCFD8181002C70
-S32500014AC07C6A1B7880C3000881010018396800017CC6421488C6000090C1002480CC001018
-S32500014AE080EC00147CC639D67C0B3000418000287D836378808C001480A100207C852214CB
-S32500014B00908100084BFFFCB18181002C7C6A1B787C0B0378810A00087D085A1489080000BE
-S32500014B205508402E808100247C8A437880EC00382C07000C4082002080C1003070C6000150
-S32500014B404182005C554AE13E280A0FF841800008614AF0003CE0000060E7FFF87C0A38407C
-S32500014B60408000347D4453783862891880A1003090A10008908100249081000C4BFFEDE57B
-S32500014B808061002483E100007FE803A6382100284E8000203880FFFF4BFFFFD0714A0FFF8E
-S32500014BA04BFFFFA85567083C7D0B3A14392000027D684BD64BFFFE943860FFFF83E10000F0
-S32500014BC07FE803A6382100284E8000207FE802A697E1FFD87C691B7881030000910100243F
-S32500014BE03862892A9121002C390900049101000880C1003090C1000C4BFFED6981A1002CE7
-S32500014C008181003081610024808D00147C04000040820070810B00107D0C41D680CB0014E7
-S32500014C207D0831D680AB002454A528347C082800418000183860FFFF83E100007FE803A6AE
-S32500014C40382100284E800020808B004080AB00147CAC29D67C842A143862893D9181000875
-S32500014C60908100209081000C4BFFECF98061002083E100007FE803A6382100284E800020CC
-S32500014C80808D001C7C0C20004180001080AD00187C050000408200A87C0A0378812D001478
-S32500014CA0914100207C0A6000418200507D635B78912100084BFFFD3181A1002C818100309D
-S32500014CC0816100247C691B787C030000408000183860FFFF83E100007FE803A6382100286D
-S32500014CE04E80002080C1002039460001914100207C0A60004082FFB8914D001C912D0018BD
-S32500014D0038E9FFFE80CB00147CE731D680AB00447CE53A14386289509181000890E1002069
-S32500014D2090E1000C4BFFEC3D8061002083E100007FE803A6382100284E800020814D001CAE
-S32500014D40812D00184BFFFF5C7FE802A697E1FFC87C6A1B788903000F7108001040820050E4
-S32500014D60808A0020810A00107C044000418000187C03037883E100007FE803A638210038CF
-S32500014D804E80002080EA0020810100447CE74214808A00107C07200040810014810A0010E8
-S32500014DA0812A00207D09405091010044810100409101001C7C0B03789161003080E10044FC
-S32500014DC07C0B38004080010C7D43537880CA00209141003C80EA000080E700187CC63BD601
-S32500014DE090C100084BFFFDE97C6A1B787C030000408000183860FFFF83E100007FE803A649
-S32500014E00382100384E8000208061003C80630000914100084BFFF9A18181003C7C03000091
-S32500014E20408200183860FFFF83E100007FE803A6382100384E80002080CC002080EC000030
-S32500014E4080E700187FE63BD67FFF39D67D5F3050810300087DA8521480C1004480810030A0
-S32500014E607D64305080EC000080E700187CEA38507C0B380040810010810C00008108001833
-S32500014E807D6A40508061001C91A100089161002C9161000C480080CD8161002C8141003CA0
-S32500014EA080E1001C7CA75A1490A1001C808A00207CE45A1490EA002080E100307D675A141B
-S32500014EC09161003080E100447C0B38004180FEFC7D635B7883E100007FE803A638210038D2
-S32500014EE04E8000207FE802A697E1FFC08883000F7084001040820020386289634BFFEA6558
-S32500014F003860FFFF83E100007FE803A6382100404E8000209061004480C1004890C10008E2
-S32500014F2048000EA981210044900900207D234B78388100209081000838E0002090E1000CC2
-S32500014F404BFFFE092C030020408201103862897B388100209081000838C1002038C6000828
-S32500014F6090C1000C4BFFE9FD806100443863000438A1002090A1000838E0000890E1000C0A
-S32500014F8048008549812100447C030000418200084BFFFF9C3869000C38C1002038C6000813
-S32500014FA090C10008390000039101000C4800851D812100447C030000418200084BFFFF70E4
-S32500014FC088A1002B70A500084182002838628995388100209081000838C1002038C60008A5
-S32500014FE090C1000C4BFFE97D812100444BFFFF4088A1002B98A9000F88E1003B54E7402E3D
-S325000150008901003A7CE7437890E900148881003F5484402E88A1003E7C842B785484801E0C
-S3250001502088A1003D54A5402E88C1003C7CA533787C842B7890890010900900189009001C19
-S32500015040900900203860000183E100007FE803A6382100404E8000207C03000041800018A4
-S325000150607C03037883E100007FE803A6382100404E8000203860FFFF83E100007FE803A62A
-S32500015080382100404E8000207FE802A697E1FFD07C6D1B7880E1003890E3000C38C002009E
-S325000150A090C3001038800001908300147C0903787DA36B7891A100349121001C91210008B5
-S325000150C04BFFF6F581A100347C6A1B787C03000040820020386289AD4BFFE8893860FFFF43
-S325000150E083E100007FE803A6382100304E80002081030008890801FE2C08005540820380D4
-S3250001510080C3000888C601FF2C0600AA408203709003000C8123000880C1003C7C06000094
-S3250001512041820010890900152C0800F8408201E8812A000888A900002C0500E9418200381E
-S3250001514088C900002C0600EB4082001088E900022C07009041820020386289CD4BFFE805C8
-S325000151603860FFFF83E100007FE803A6382100304E8000207D234B789121002C4800031DFE
-S325000151808141002C81210034888A000C5484402E88CA000B7C8433789089001088EA000D30
-S325000151A090E900148089001080A900147C8429D69089001888CA000F54C6402E890A000E4B
-S325000151C07CC6437890C9001C888A00109089002088CA001254C6402E890A00117CC643786E
-S325000151E090C9002488EA001454E7402E888A00137CE7237890E90028810900287C08000002
-S325000152004082003088EA002354E7402E88AA00227CE72B7854E7801E88CA002154C6402E29
-S32500015220890A00207CC643787CE7337890E90028888A00159089002C88CA001754C6402EAB
-S32500015240890A00167CC6437890C900308089001C9089003C8089002080A900307C8429D61D
-S3250001526080A9003C7C8522149089004080C9002454C6283480E900107CC63A143946FFFFC9
-S3250001528080C900107D4A33D680C900407CC6521490C900448089002880A900447C85205001
-S325000152A080A900147C842BD6388400029089003480C900342C060FF74080005038E0000CB5
-S325000152C090E9003839000002910900489129004C9009006090090068900900649009006CF7
-S325000152E038A0001098A9005B81090024550828349109005C7C03037883E100007FE803A658
-S32500015300382100304E80002038A0001090A900384BFFFFB4808A0008392401BE3980FFFFD4
-S325000153207C0B03782C0B000440800064890900042C0800544082000C3920003F4BFFFD74C6
-S3250001534088A900042C0500014182001088C900042C0600044082011889090000710800801B
-S32500015360418200A88889000B5484402E88E9000A7C843B785484801E890900095508402E4F
-S3250001538088A900087D082B787C8C43782C0B0004408200183900FFFF7C0C40004082000C00
-S325000153A0900A000C4BFFFD8C80C1001C7CC6621490CD000C7DA36B78900100084BFFF3F91D
-S325000153C07C6A1B787C0300004182001480E3000888E701FE2C070055418200183860FFFF25
-S325000153E083E100007FE803A6382100304E80002080A3000888A501FF2C0500AA4082FFE0E7
-S32500015400900A000C4BFFFD2C88E9000B54E7402E88A9000A7CE72B7854E7801E88C90009D3
-S3250001542054C6402E890900087CC643787CE733787C0760404080002C88C9000B54C6402E45
-S325000154408889000A7CC6237854C6801E88A9000954A5402E88E900087CA53B787CCC2B78BC
-S32500015460396B0001392900104BFFFEBC88E900042C0700064082FFEC4BFFFEE0386289C4A0
-S325000154804BFFE4E13860FFFF83E100007FE803A6382100304E8000207FE802A697E1FFE807
-S325000154A07C691B78386289E1888900009081000888C9000190C1000C9121001C890900022E
-S325000154C0910100104BFFE49D38628A0180A1001C38A5000390A100084BFFE4898121001C68
-S325000154E038628A138909000C5508402E88A9000B7D082B78910100084BFFE46938628A212B
-S3250001550080E1001C88E7000D90E100084BFFE4558121001C38628A308889000F5484402E17
-S3250001552088C9000E7C843378908100084BFFE43538628A3C8101001C8908001091010008A5
-S325000155404BFFE4218121001C38628A4788A9001254A5402E88E900117CA53B7890A1000893
-S325000155604BFFE4018121001C38628A55888900145484402E88C900137C843378908100082B
-S325000155804BFFE3E138628A628101001C89080015910100084BFFE3CD8121001C38628A7640
-S325000155A088A9001754A5402E88E900167CA53B7890A100084BFFE3AD8121001C38628A8362
-S325000155C0888900195484402E88C900187C843378908100084BFFE38D8121001C38628A90FB
-S325000155E08909001B5508402E88A9001A7D082B78910100084BFFE36D8121001C38628A9C07
-S3250001560088E9001F54E7402E88A9001E7CE72B7854E7801E88C9001D54C6402E8909001C78
-S325000156207CC643787CE7337890E100084BFFE3358121001C38628AA988A9002354A5402E37
-S32500015640890900227CA5437854A5801E888900215484402E88C900207C8433787CA52378CC
-S3250001566090A100084BFFE2FD38628AB98101001C89080024910100084BFFE2E938628AC6F8
-S3250001568080A1001C88A5002590A100084BFFE2D538628ADA80E1001C88E7002690E10008B1
-S325000156A04BFFE2C18121001C38628AEC8889002A5484402E88E900297C843B785484801EE4
-S325000156C0890900285508402E88A900277D082B787C844378908100084BFFE28938628AFC15
-S325000156E080E1001C38E7002B90E100084BFFE27583E100007FE803A6382100184E800020EF
-S325000157007FE802A697E1FFE8816100207C691B7888C900007CC607742C06002F4082001851
-S325000157203929000188C900007CC607742C06002F4182FFF088A900007CA507747C05000090
-S32500015740418200C088C900007CC607742C060020418200B07C0A037888A900007CA507741E
-S325000157607C0500004182001488C900007CC607742C06002F4082001C980B00007D234B7877
-S3250001578083E100007FE803A6382100184E80002088E900007CE707742C0700204082001CAF
-S325000157A0980B00007D234B7883E100007FE803A6382100184E8000202C0A001C40820020D5
-S325000157C038628B0E4BFFE19D7C03037883E100007FE803A6382100184E8000207D655B7845
-S325000157E0396B00017D264B783929000188C600007CC6077498C50000394A00014BFFFF5CA3
-S325000158007C03037883E100007FE803A6382100184E8000207FE802A697E1FFD080E1003CC1
-S325000158207C641B7838C0000380A4004C8104005090A7000080A400549107000490A7000824
-S3250001584038C6FFFF3884000C38E7000C7C0600004181FFD88061003838A1001490A10008F8
-S325000158604BFFFEA1906100387C030000418200508061003C38A1001490A100084BFFF66991
-S325000158802C03FFFF418200247C030000418200084BFFFFC47C03037883E100007FE803A628
-S325000158A0382100304E8000203860FFFF83E100007FE803A6382100304E8000203860000150
-S325000158C083E100007FE803A6382100304E8000207FE802A697E1FFA880E1006090E100086E
-S325000158E038C1003490C1000C4BFFFF2D814100602C03FFFF418204207C030000418203F82E
-S325000159002C030001418203B43860002090010008480036097C6B1B7838A0002038610034BF
-S3250001592090A1003090A10008916100289161000C4800040581410028810100307C03400002
-S3250001594041820020806282CC4BFFE0193860FFFF83E100007FE803A6382100584E80002041
-S3250001596088CA000054C6402E888A00017CC6237854C6801E88AA000254A5402E88EA00038E
-S325000159807CA53B787CC62B782C0606EB4182004C38628B7C890A00005508402E88CA0001C3
-S325000159A07D0833785508801E88EA000254E7402E888A00037CE723787D083B7891010008B3
-S325000159C04BFFDFA13860FFFF83E100007FE803A6382100584E80002088EA001454E7402E1E
-S325000159E088AA00157CE72B7854E7801E890A00165508402E892A00177D084B787CE74378D6
-S32500015A0074E7E0003C8020007C0720004182027488CA001454C6402E88EA00157CC63B7822
-S32500015A2054C6801E890A00165508402E88AA00177D082B787CC6437890C1002C890A0004B1
-S32500015A405508402E88CA00057D0833785508801E88EA000654E7402E888A00077CE72378BA
-S32500015A607D083B7838628BA791010030910100084BFFDEF13861003480A1003090A100084F
-S32500015A808101002C9101000C480002AD81610030814100287C03580041820020806282CCD6
-S32500015AA04BFFDEC13860FFFF83E100007FE803A6382100584E80002080E1002C7C8B3A146B
-S32500015AC038840FFF3FE0FFFF63FFF0007FE420399081002C88AA000854A5402E890A000950
-S32500015AE07CA5437854A5801E888A000A5484402E88CA000B7C8433787CA5237838628BAB36
-S32500015B0090A1003090A100084BFFDE593861003480E1003090E1000880A1002C90A1000C02
-S32500015B204800021581410028810100307C03400041820020806282CC4BFFDE293860FFFFAA
-S32500015B4083E100007FE803A6382100584E80002038628BAF88CA000C54C6402E888A000D52
-S32500015B607CC6237854C6801E88AA000E54A5402E88EA000F7CA53B787CC62B7890C100084F
-S32500015B80888A00145484402E88EA00157C843B785484801E890A00165508402E88AA001725
-S32500015BA07D082B787C8443789081000C4BFFDDB581410028890A00145508402E88CA00153F
-S32500015BC07D0833785508801E892A00165529402E888A00177D2923787D084B787508E000CF
-S32500015BE03CA020007C0828004182004888EA001454E7402E890A00157CE7437854E7801E1D
-S32500015C00888A00165484402E88CA00177C8433787CE723787CE803A64E8000217C03037807
-S32500015C2083E100007FE803A6382100584E80002088EA001454E7402E888A00157CE72378F6
-S32500015C4054E7801E88AA001654A5402E890A00177CA543787CE72B783FE0FFFF63FFFFFFAC
-S32500015C607FE738397CE803A64E8000217C03037883E100007FE803A6382100584E8000203D
-S32500015C8088CA001454C6402E890A00157CC6437854C6801E888A00165484402E88EA0017BB
-S32500015CA07C843B787CC623783FE0FFFF63FFFFFF7FE630394BFFFD8438628B4A38A10034BB
-S32500015CC038A5000490A1000838E1003438E7000C90E1000C888100439081001080810048F8
-S32500015CE09081001480E1004490E100184BFFDC754BFFFC1838628B3C914100084BFFDC658B
-S32500015D003860FFFF83E100007FE803A6382100584E80002038628B27914100084BFFDC4542
-S32500015D203860FFFF83E100007FE803A6382100584E8000207FE802A697E1FFD88161003043
-S32500015D409061002C80E1003490E100247C0A03787C0A580040800044392020007C8A5850EB
-S32500015D607C044800408000087D2A58508061002C808100249141001C7C845214908100089E
-S32500015D809121000C4BFFEFC58141001C906100207C030000418100187D43537883E1000009
-S32500015DA07FE803A6382100284E80002038628BC44BFFDBB1816100308081002080C1001C0E
-S32500015DC07D4622144BFFFF8C7FE802A697E1FFE0812100287C6B1B783943000488E9000053
-S32500015DE07CE707747C070000418200147CCB505038C6FFFC2C060008418001047CAB5050BD
-S32500015E0038A5FFFC2C050008408000247D455378394A000138C0002098C500007CAB505039
-S32500015E2038A5FFFC2C0500084180FFE4394B000C88A900007CA507747C05000041820014F1
-S32500015E407C8B50503884FFF42C0400034180005C7C8B50503884FFF42C0400034080002428
-S32500015E607D445378394A000138A0002098A400007C8B50503884FFF42C0400034180FFE4AA
-S32500015E8038628BC638AB000490A10008390B000C9101000C4BFFDACD83E100007FE803A69D
-S32500015EA0382100204E800020888900007C8407742C0400614180001488A900007CA50774B5
-S32500015EC02C05007A4081001C888900007C840774988A000039290001394A00014BFFFF5401
-S32500015EE0890900007D0807743908FFE0990A000039290001394A00014BFFFF3888C900008D
-S32500015F007CC607742C06002E4082000C392900014BFFFEEC88A900007CA507742C05006199
-S32500015F204180001488C900007CC607742C06007A4081001C88A900007CA5077498AA0000DF
-S32500015F4039290001394A00014BFFFE94888900007C8407743884FFE0988A000039290001CB
-S32500015F60394A00014BFFFE787FE802A697E1FFC8900100287C0A03782C0A00044080006074
-S32500015F8091410030554818387C8A4214548428347C88205038A2D7D07C642A149061003443
-S32500015FA09001000838E0011890E1000C48006D818061003080C1003490C100084BFFA6CDC1
-S32500015FC0816100347C0300004181002880810030394400012C0A00044180FFA880610028E1
-S32500015FE083E100007FE803A6382100384E8000207C0A03785547183838C282807CE7321415
-S3250001600080E700007C0700004182FFC4914100245543183838E282807C633A1480630000FF
-S32500016020916100084800743D81610034814100247C0300004182000C394A00014BFFFFB897
-S3250001604080810030908B00EC7D635B785548183838E282807D083A14810800047D0803A6B7
-S325000160604E8000217C030000418200084BFFFF603860400038A0000190A100089001000CB0
-S325000160809001001048003E5580E10034906700F43860400038C0000190C100089001000C36
-S325000160A09001001048003E3581410034906A00F839000001910A00F03880000180C10030A6
-S325000160C07C843030810100287D0423789081002838629A1180CA00EC90C100089141000CA8
-S325000160E0808A001C90810010808A0020908100144BFFD87181410034808A00247C040000CC
-S325000161004182002C38629A31808A00247484E0003D2020007C04480041820098810A0024CF
-S32500016120910100084BFFD83D8141003480CA00287C0600004182001438629A3E80AA0028DA
-S3250001614090A100084BFFD81D38629A4B4BFFD8157C0A03782C0A00064080003038629A4D5C
-S325000161609141002C80C100347CAA321488A5002C90A100084BFFD7ED80A1002C39450001CD
-S325000161802C0A00064180FFD838629A554BFFD7D54BFFAEB181410034806A0020810A00D0A1
-S325000161A0910100089141000C48004AC94BFFFE20810A00243FE0FFFF63FFFFFF7FE8403991
-S325000161C04BFFFF607FE802A697E1FFE82C03000440800080546618387CA3321454A528346A
-S325000161E07CA6285038C2D7D07CA5321480A500F07C0500004182005C546718387D033A1468
-S32500016200550828347D0740503922D7D07D484A1480AA00F02C0500014082002438C0000259
-S3250001622090CA00F07D43537891410014810A00BC7D0803A64E800021814100147D435378D7
-S3250001624083E100007FE803A6382100184E8000207C03037883E100007FE803A63821001885
-S325000162604E8000207FE802A697E1FFE84BFFFF597C030000408200187C03037883E1000062
-S325000162807FE803A6382100184E8000203863002C83E100007FE803A6382100184E800020EE
-S325000162A07FE802A697E1FFD84BFFFF1D906100207C030000408200187C03037883E100004B
-S325000162C07FE803A6382100284E80002080828014808400009081001880610020806300F49D
-S325000162E048003C357C6A1B787C0300004082005080A2801480A5000080E100187CA72850E5
-S3250001630054A4083C7CA5221454A518385484482C7CA5205038C000327CA5339680C1003434
-S325000163207C0530404180FFB47C03037883E100007FE803A6382100284E800020810300048C
-S32500016340812300007D094050806100309141001C808A000090810008910100249101000C06
-S3250001636048006C018061001C48003B118061002483E100007FE803A6382100284E800020E8
-S325000163807FE802A697E1FFE87C691B7880610020806300009121001C3889002C9081000858
-S325000163A038E0000690E1000C48007121812100207C03000041820028806900003902836826
-S325000163C09101000838A0000690A1000C480070FD812100207C030000408200288061001C24
-S325000163E0806300F49121000848003BA93860000183E100007FE803A6382100184E8000206D
-S3250001640080E100247C0700004182000C7D234B7848003A697C03037883E100007FE803A6E2
-S32500016420382100184E8000207FE802A697E1FFD89061002C4BFFFD917C030000408200184A
-S325000164407C03037883E100007FE803A6382100284E80002090610024806300F848003BC520
-S325000164602C0340004081002838629A5780A1002C90A100084BFFD4ED7C03037883E1000043
-S325000164807FE803A6382100284E800020386005F0480039919061002080630004810100302D
-S325000164A09101000880C1003490C1000C48006AB580610020806300043863000680E10024F4
-S325000164C038E7002C90E1000838A0000690A1000C48006A91812100208081003480C900044F
-S325000164E07C8622149089000480610024806300F89121000848003A9D4BFF9CA98121002432
-S325000165009061001C7D234B78810900CC7D0803A64E8000218061001C4BFF9CA53860000170
-S3250001652083E100007FE803A6382100284E8000207FE802A697E1FFF880A300EC54A7183899
-S325000165407CA53A1454A5103A3902A3387CA5421480A5000080C5000060C6003090C50000E0
-S325000165604BFF9C1983E100007FE803A6382100084E8000207FE802A697E1FFD89061002CD7
-S325000165808081002C808400EC548518387C842A145484103A38C2A3387D24321481090020E8
-S325000165A0550818389121002080C900187D08321491010018A1080000710880004082001CFF
-S325000165C08061002C806300F84800394D7C691B787C0300004082001483E100007FE803A6BD
-S325000165E0382100284E80002080A3000480C300007CA6285080610018806300049121001C73
-S32500016600810900009101000890A1002490A1000C4800695180C1001881010024B106000203
-S325000166204BFF9B5981210018A0A9000070A5200060A5DC00B0A900004BFF9B41808100205C
-S32500016640808400003D00000061088000B104000C4BFF9B298121002080C9002038C6000110
-S3250001666038E000047FE63BD67FFF39D67CDF305090C900208061001C480038018121002060
-S325000166804BFFFF1C7FE802A697E1FFC8808100409081001C80C400EC54C718387CC63A14A7
-S325000166A054C6103A3902A3387CC6421490C1002880A60000A0A5001090A100304BFF9ABDCB
-S325000166C0808100288084000081010030B10400104BFF9AA98181001C8141002881010030C8
-S325000166E0710800154182002438629BD880AC00EC90A1000880A1003090A1000C4BFFD265B1
-S325000167008181001C8141002881010030710800094082000480AA001454A5183880CA000C93
-S325000167207D65321491610024A0AB00007CA92B7870A58000408201247128003F408200C427
-S3250001674071250C002C050C00408200B8A0AB00023865FFFC90610034480036C98161002482
-S325000167607C0300004182004C9061002080630004808B000490810008808100349081000C12
-S32500016780480067E1812100208081003480C900047C862214908900048061001C9121000812
-S325000167A0390000019101000C4BFFFBD981610024B00B0002A08B0000708420006084900066
-S325000167C0B08B00004BFF99B58181001C8141002880AA001438A5000138C000207FE533D636
-S325000167E07FFF31D67CBF285090AA001480EA001454E71838810A000C7D6742144BFFFF28C1
-S32500016800712700044182001080CC010438C6000190CC01047124000241820010810C011049
-S3250001682039080001910C01107126003F4182001438629BF44BFFD12D816100244BFFFF7480
-S32500016840712808004082FF6C38629BF64BFFD115816100244BFFFF5C80E1003070E7000273
-S32500016860418200107D8363784BFFFD0D8141002880A1003070A50010418200183860000636
-S3250001688080EA000890E100089001000C4BFFD2D183E100007FE803A6382100384E80002089
-S325000168A07FE802A697E1FFE03DA0000061AD90007C6A1B78906100248103000C7C0800004E
-S325000168C04082001C386000204BFFD4213DA0000061AD900081410024906A000C80CA00101B
-S325000168E07C060000408200243C6000006063BE0090010008480026253DA0000061AD900065
-S3250001690081410024906A001080AA001074A5E0003CC020007C0530004182015C808A001046
-S325000169207C8C23787C0B03782C0B0020408000445567183880AA000C7CE72A14B0070002B4
-S325000169405564183880EA000C7C843A14918400045568183880CA000C7D083214B1A80000C3
-S32500016960398C05F0396B00012C0B00204180FFC45564183880EA000C7C843A14A0C4FFF8AE
-S3250001698060C62000B0C4FFF8900A001480CA00187C06000040820014386000044BFFD34DD1
-S325000169A081410024906A0018808A001C7C04000040820018386017C0900100084800255D86
-S325000169C081410024906A001C810A001C7508E0003D2020007C0848004182008880EA001C96
-S325000169E07CEC3B787C0B03782C0B00044080004855651838810A00187CA5421491850004F2
-S32500016A005564183880EA00187C843A14B004000255661838808A00187CC6221439005C00A6
-S32500016A20B1060000398C05F0396B00012C0B00044180FFC05567183880AA00187CE72A148F
-S32500016A40A087FFF860842000B087FFF8900A002083E100007FE803A6382100204E8000204A
-S32500016A6080EA001C3FE0FFFF63FFFFFF7FE738394BFFFF70808A00103FE0FFFF63FFFFFFE5
-S32500016A807FE420394BFFFE9C7FE802A697E1FFD080A3000454A5083C3985FFFE80A2801424
-S32500016AA08145002038A000037CAB6030A0CA09527CC75B78B0EA09527D6658F8A0AA0950B1
-S32500016AC07CA63038B0CA09507D6558F8A08A09547C852838B0AA095438E000307CEB603042
-S32500016AE07D6458F8A10A09627D042038B08A09627D6858F8A0EA09607CE84038B10A0960A2
-S32500016B00A0CA09647CC75B78B0EA0964906100348063000838E1002890E1000838810024D3
-S32500016B209081000C4BFF9BDD8061003480630004808100289081000880E1002490E1000C2F
-S32500016B404BFFD0D180A1003480A5000454A5103A38C283A87CA53214806500009061001C04
-S32500016B609001000838A000A490A1000C480061C13D8020008161001C8141003438800018B1
-S32500016B80988B000438E0001898EB000538A005F0B0AB0006810A000C7508E0007C08600009
-S32500016BA04182018480CA000CB0CB000080AA001874A5E0007C05600041820158810A0018DA
-S32500016BC0B10B00027C03037880AA000890A100089001000C4BFFCF8981A100388181003CB4
-S32500016BE08161001C38E0FFFF90EB00303CA0DEBB60A520E390AB0034900B0038900B003C39
-S32500016C00900B00403C80000060848888B08B004438E0000FB0EB004638A005EEB0AB004AEB
-S32500016C2039000040B10B004C38C005F0B0CB004E388005F0B08B0050B00B00787C0A0378AA
-S32500016C402C0A00064080003C7CEA621488E7000154E7402E7D0C5214890800007CE7437862
-S32500016C60392000027D0A4BD65508083C7D085850B0E80076394A00022C0A00064180FFCCE1
-S32500016C803900080AB10D00083CC0000060C6D555B0CD000E900D00043CC0108860C6000C9E
-S32500016CA090CD00004BFF94D580E100383C8000006084FFFFB08700104BFF94C180A1003847
-S32500016CC038E0001AB0E500144BFF94B1810280148168002081010034810800043908FFFFA1
-S32500016CE0392010007D284030808B0ABC7C87437890EB0ABC80CB0AB87CC44378908B0AB85A
-S32500016D0083E100007FE803A6382100304E800020810A00183FE0FFFF63FFFFFF7FE8403981
-S32500016D204BFFFEA080CA000C3FE0FFFF63FFFFFF7FE630394BFFFE747FE802A697E1FF7011
-S32500016D40906100943861008A9001000838A0000690A1000C48005FD93861008A8101009417
-S32500016D603908002C9101000838C0000690C1000C48006759812100947C030000408200909B
-S32500016D8038629BF84BFFCBDD3861001C39029C11910100084800666538629C1E38C1004EE8
-S32500016DA090C10008390000329101000C38C1001C90C100104BFFCA357C0300004080001854
-S32500016DC03860FFFF83E100007FE803A6382100904E800020806100943863002C3881004E88
-S32500016DE0908100084BFFC209812100947C0300004080001C88C9002C2C0600FF418200104C
-S32500016E0038629C304BFFCB5D4BFFFF8080E9001C54E7103A388280887CE7221480E70000FE
-S32500016E2080C2801480C600207D663A1480C9001C54C6103A38E280307CC63A1480C6000075
-S32500016E4038C6001090C9002080E900EC54E818387CE7421454E7103A3882A3387C672214D7
-S32500016E60916100809163000080E9001C90E3000480E9001C54E7103A390283107CE7421418
-S32500016E8080E7000090E30008906100844BFFFA158061008480A1008090A1000881010094E6
-S32500016EA03908002C9101000C4BFFFBE1812100943D00FFC261086E38910900B83CE0FFC228
-S32500016EC060E7663090E900BC3CC0FFC260C6667490C900CC3CA0FFC260A5678490A900D021
-S32500016EE07C03037883E100007FE803A6382100904E8000203821FFD08161003C82810038C5
-S32500016F00824100407C751B7838A000017CAE583038A000017CA570303A65FFFF38A0000148
-S32500016F207CAA903038A000207CAF96307D4558307E2E2850388000207DAF20507C0D000010
-S32500016F40418000787C0A03787EB06C307C0C03787C0B03787C0B7800408000247E665830D2
-S32500016F607E0630387CC660307D4A33787D8C8A147D6B72147C0B78004180FFE47C0B037820
-S32500016F807C0B90004080001C7DC758307D4738307D4A3B78396B00017C0B90004180FFEC1D
-S32500016FA07E88A3783A940004914800007DAF68507C0D00004080FF90382100304E800020CB
-S32500016FC07FE802A697E1FEF89061010C3861010C480006498141011880C101248081011C93
-S32500016FE07CC430514181001483E100007FE803A6382101084E8000208081012880E1012083
-S325000170007C8720503884FFFF908100FC80A100FC7C0500004080001483E100007FE803A649
-S32500017020382101084E80002080E1010C81A7000C808101107C87683090E1011091A100F402
-S325000170407CCB6830836A000C8081011C7C87D83090E1011C936100F8808101247C87D8307D
-S3250001706090E1012480E1010C83470008832A000880E10114934100E87CE7D1D680A1010C14
-S3250001708080A500047CE72A14808101107C842E707CE43A1454E7103A80C1010C80C60000A8
-S325000170A07EE7321492E100CC80C10120932100EC7CC6C9D6808A00047CC622148101011CD7
-S325000170C07D082E707CC8321454C6103A80AA00007EC62A1492C100D080A1011070AC001F5C
-S325000170E03900FFFF7D086430910100B0918100DC7D0C5A147108001F38A000207D08285085
-S3250001710038C0FFFF7CC840303FE0FFFF63FFFFFF7FE84039910100AC810100AC7C08000071
-S325000171204082000C38A0FFFF90A100AC80C1011C70C6001F90C100E4810101107C8B4214EF
-S325000171403884FFFF7C842E7080A101107CA52E707C8520509081010080A1010C7C0A280080
-S325000171604082005880E10120808101147C0720004080046080C100FC7CC6D1D654C6103A05
-S325000171807EF73214808100FC7C84C9D65484103A7ED6221480EA000854E7083C7F27C85036
-S325000171A0932100EC8081010C808400085484083C7F44D050934100E8808101007C040000D1
-S325000171C04082001480C100AC810100B07D06303890C100B080C1012C70C6000F90C1012C96
-S325000171E07E9B68507D85A63080C100E47E6530507C1803787C1300004080000C3B000001B1
-S325000172007E7300507C1003787C15037892A100A480A100FC7C152800418100F892E100CC6D
-S325000172207EECBB7892E100C492C100D07ECFB37881A100B091A100C07C0E03787C1800007B
-S32500017240408200107DE57B7839EF000481C500007C12037882210100922100A87C110000F9
-S325000172604180008C7C1200004182027C7E0783783A10000481670000814C00008101012CB9
-S325000172802C08000841810194418201702C08000441810110418200F87C080000418200D83B
-S325000172A02C080001418200B02C080002418200942C0800034182006C398C0004918100C48D
-S325000172C039A0FFFF91A100C02C1100014082000C81A100AC91A100C03A52FFFF3A31FFFF1F
-S325000172E0922100A87C1100004080FF7C5727103A7ED63A145747103A7EF73A143AB500015F
-S3250001730092A100A480A100FC7C1528004081FF1083E100007FE803A6382101084E80002025
-S325000173203FE0FFFF63FFFFFF7FE65A787CC652787CC668387D46327890CC00004BFFFF7C16
-S325000173407D6750387CE768387D473A7890EC00004BFFFF683FE0FFFF63FFFFFF7FE85A785E
-S325000173607D0853787D0868387D484278910C00004BFFFF483FE0FFFF63FFFFFF7FE56A7821
-S325000173807D45283890AC00004BFFFF307D6553787CA568387D452A7890AC00004BFFFF1C9C
-S325000173A02C080005418200482C080006418200302C080007418200084BFFFF003FE0FFFFE9
-S325000173C063FFFFFF7FE852787D6843787D0868387D484278910C00004BFFFEE07D67683888
-S325000173E07D473A7890EC00004BFFFED07D446A78908C00004BFFFEC43FE0FFFF63FFFFFF34
-S325000174007FE75A787CE750387CE768387D473A7890EC00004BFFFEA42C08000C41810070EF
-S32500017420418200582C080009418200342C08000A4182FE882C08000B418200084BFFFE7CA1
-S325000174403FE0FFFF63FFFFFF7FE75A787CE768387D473B7890EC00004BFFFE603FE0FFFFB5
-S3250001746063FFFFFF7FE65A787CC668387D46327890CC00004BFFFE447D6852787D08683863
-S325000174807D484278910C00004BFFFE302C08000D418200342C08000E4182001C2C08000FB5
-S325000174A0418200084BFFFE147D476B7890EC00004BFFFE087D6668387D46337890CC0000DE
-S325000174C04BFFFDF87D6750383FE0FFFF63FFFFFF7FE73A787CE768387D473A7890EC000070
-S325000174E04BFFFDD8930100D47C180000418200AC38E000207CF338507DC738307DE57B78CB
-S3250001750039EF000491E100C881C5000091C100BC926100D87DC89C307CEB437838E0000193
-S325000175207CF2A0309241001C2C1400014180FD4C7D635B7838A1002490A100089361000CE3
-S32500017540928100F0928100104BFFF9AD836100F8834100E8832100EC830100D482E100CC6F
-S3250001756082C100D082A100A4828100F0826100D88241001C822100A881E100C881C100BC2A
-S3250001758081A100C0818100C4390100243A080004816800004BFFFCE47DCB98307DE77B781E
-S325000175A039EF000491E100C881C7000091C100BC926100D87C1300004182FF6438E0002050
-S325000175C07CF338507DC73C307D6B3B784BFFFF5080C10120810101147C0640004082FBDC75
-S325000175E080A1011C80E101107C053800418000084BFFFBC84800600181A100F4836100F8AA
-S32500017600834100E8832100EC818100DC82E100CC82C100D04BFFFBA43821FFE87C691B7866
-S3250001762080E30018810300107D68385080E3001C810300147D48385080E3000480C30000B9
-S3250001764080C600207C0730004080003080E9000080E70020808900047CE43850810900109B
-S325000176607CC83A1490C9001080A900047D053A14910900047D6758508109000880E90000E6
-S3250001768080E700247C08380040800030810900008108002480A900087D0540508089001415
-S325000176A07CE4421490E9001480C900087C864214908900087D485050808900047C845A14D6
-S325000176C080C9000080C600287C0430004081002480E900047CEB3A1480A9000080A50028BF
-S325000176E07CE53850810900187CE7405090E9001880C900087CC65214810900008108002C3C
-S325000177007C06400040810024808900087C8A221480E9000080E7002C7C87205080A9001CBA
-S325000177207C8428509089001C8109001080E9000C80E700207C0838004080002C8109000CC1
-S325000177408108002080A900107D054050808900047CE4421490E9000480C900107C8642143D
-S3250001776090890010808900148109000C810800247C0440004080002C8089000C8084002490
-S3250001778080C900147C86205080A900087D0522149109000880E900147CA7221490A9001465
-S325000177A080A900188089000C808400287C0520004081001080E9000C80E7002890E9001839
-S325000177C08089001C8109000C8108002C7C0440004081001080C9000C80C6002C90C9001C65
-S325000177E0382100184E8000203821FFF0814100187C691B787C070378394AFFFF7C0A000084
-S32500017800418000207D244B7839290001888400007CE72214394AFFFF7C0A00004080FFE866
-S325000178207CE33B78382100104E80002081210008390227107C0940404081000C7C0918400D
-S325000178404180000C7C0303784E800020386000014E8000207FE802A697E1FFE080C3000438
-S3250001786038A0FFFF7C0628004182001480C300043CA000047C062840418000187C030378C6
-S3250001788083E100007FE803A6382100204E80002088C3000B2C0600FF4182FFE480E3000472
-S325000178A0810282F87D683A14906100249161001C916100084BFFFF79816100247C0300002D
-S325000178C0408200187C03037883E100007FE803A6382100204E80002088AB000854A5402E50
-S325000178E0890B00097CA5437854A5402E888B000A7CAA23783D0000FF6108FFFF7C0A40005A
-S32500017900408200087C0A03787C0A0000408000187C03037883E100007FE803A63821002050
-S325000179204E8000207C0A0000408100307D635B78914100188121001C7CAA4A1438A5FFFF21
-S3250001794090A100084BFFFEE981610024814100187C0300004182007C80CB000038A0FFFFF7
-S325000179607C062800418200288061001C91410018914100084BFFFE758141001880E100248E
-S3250001798080E700007C0338004082002C80A1002880E1001C90E500008081002C9144000097
-S325000179A03860000183E100007FE803A6382100204E80002038628CD04BFFBFA97C030378AA
-S325000179C083E100007FE803A6382100204E8000207C03037883E100007FE803A638210020DE
-S325000179E04E8000207FE802A697E1FFB8900282F890028300900282FC386100203881003879
-S32500017A009081000838C1003490C1000C4BFF8C157C0300004080002038628CE54BFFBF4519
-S32500017A207C03037883E100007FE803A6382100484E80002081010034910282FC80A1003822
-S32500017A4090A282F880E282F83CE7000490E28300900283049002830880A282F83FE0000387
-S32500017A6063FFFFF07D3F2A149121003C3869000C390282F09101000838A0000490A1000CB9
-S32500017A8048005A497C030000408200A080E1003C88E7000B2C070002408200248061003CC4
-S32500017AA038A1004090A1000838E1004490E1000C4BFFFDA57C030000408200108101003C98
-S32500017AC03928FFF04BFFFFA4808100442C04000B408000108101003C3928FFF04BFFFF8C2F
-S32500017AE080610040390280C09101000838A0000B90A1000C480059D57C0300004182001061
-S32500017B008101003C3928FFF04BFFFF6080E1004090E2830480810044908283088101003C6D
-S32500017B203928FFF04BFFFF4480A283047C050000408200B438628D504BFFBE2980628300B4
-S32500017B404800356D2C0306EB4082002038628D804BFFBE113860000183E100007FE803A665
-S32500017B60382100484E80002081028300890800005508402E80C2830088C600017D083378C9
-S32500017B805508801E80E2830088E7000254E7402E80828300888400037CE723787D083B781A
-S32500017BA02C0806EB4082002038628DAA4BFFBDB53860000183E100007FE803A6382100487C
-S32500017BC04E8000209002830038628DD64BFFBD957C03037883E100007FE803A638210048F3
-S32500017BE04E80002038628D6280E2830490E1000880A2830890A1000C81028304910100100F
-S32500017C004BFFBD614BFFFF38806283044E8000207FE802A697E1FFF080C283007C06000060
-S32500017C204182006880628300480034857C0300004082004480A2830088A5000054A5402EEE
-S32500017C4081028300890800017CA5437854A5801E80828300888400025484402E80C2830074
-S32500017C6088C600037C8433787CA523782C0506EB408200183860000183E100007FE803A63C
-S32500017C80382100104E8000207C03037883E100007FE803A6382100104E8000207FE802A6B2
-S32500017CA097E1FFB080E283007C070000408200183860FFFF83E100007FE803A638210050A1
-S32500017CC04E8000208142830088CA000054C6402E888A00017CC6237854C6801E88AA0002B3
-S32500017CE054A5402E88EA00037CA53B787CC62B782C0606EB408202387D49537888CA0014D2
-S32500017D0054C6402E888A00157CC6237854C6801E88EA001654E7402E890A00177CE743781F
-S32500017D207CC63B7874C6E0003D0020007C064000418201C488A9001454A5402E88C9001574
-S32500017D407CA5337854A5801E88E9001654E7402E888900177CE723787CA53B7890A1004C12
-S32500017D60398A00208161004C88E9000454E7402E88A900057CE72B7854E7801E88C9000661
-S32500017D8054C6402E91210040890900077CC643787CEA33787C0B6000418200507D635B780E
-S32500017DA0916100489181002091810008914100249141000C480051AD38628DF980C1004873
-S32500017DC090C10008808100209081000C80E1002490E100104BFFBB8D818100208161004821
-S32500017DE081410024812100407D8C521480A1004C3CE0FFC07C053840418000E439403000B6
-S32500017E0088A9000854A5402E890900097CA5437854A5801E8889000A5484402E88C9000BF0
-S32500017E207C8433787CA523787D43537891410048918100209181000890A1002490A1000C51
-S32500017E404800512138628E1980A1004890A10008810100209101000C80C1002490C1001078
-S32500017E604BFFBB0138628E398081004C908100084BFFBAF14BFF91CD4BFFBDED8101004CCF
-S32500017E807508E0003CA020007C0828004182002480E1004C7CE803A64E8000213860FFFFB0
-S32500017EA083E100007FE803A6382100504E80002080E1004C3FE0FFFF63FFFFFF7FE73839AF
-S32500017EC07CE803A64E8000213860FFFF83E100007FE803A6382100504E8000207C8A5A148A
-S32500017EE038840FFF3FE0FFFF63FFF0007FEA20394BFFFF1088AA001454A5402E88EA0015F3
-S32500017F007CA53B7854A5801E890A00165508402E88CA00177D0833787CA543783FE0FFFFE9
-S32500017F2063FFFFFF7FE528394BFFFE349141003480C1003490C100283D0A000C9101003090
-S32500017F4080C1003090C1002C386100283881004C90810008480032057C0300004080FF0888
-S32500017F603860FFFF83E100007FE803A6382100504E8000207FE802A697E1FF907C691B78CB
-S32500017F803861003491210008480054713861003438C1002490C10008390000049101000C28
-S32500017FA038C29AD590C1001048000D9D2C030002418201482C030003418200187C030378BA
-S32500017FC083E100007FE803A6382100704E8000208101007C9008000039429E0080AA000492
-S32500017FE07C050000418201007C0903782C090003408000E45524103A7C8452148084001C10
-S325000180007C040000418200C4806100249121001C5528103A9141006C7D0852148108001CEA
-S32500018020910100084800543D8141006C8121001C7C0300004082009480C10078810A0000C1
-S32500018040910600008101007C38A000017CA54830808800007C852B7890A800008061002825
-S3250001806038A1002090A100089001000C48004EF981010080906800007C030000408200144C
-S3250001808080A1002080E100287C053800418200288061008480A1002C90A100084800535D88
-S325000180A03860000183E100007FE803A6382100704E8000207C03037883E100007FE803A687
-S325000180C0382100704E800020392900012C0900034180FF24394A003080AA00047C05000001
-S325000180E04082FF087C03037883E100007FE803A6382100704E80002039029AD79101002C21
-S325000181004BFFFED07FE802A697E1FF30906100D47C0303784BFF8E39814100D8812100D4AA
-S3250001812071440004418200503C60001F6063FF6A38C29AD890C10008810900008108002489
-S325000181409101000C80A9000C90A100104BFFB7D1806100D48063000C810100DC9101000896
-S325000181604BFFA29183E100007FE803A6382100D04E800020714600084182002881090004B8
-S32500018180710800084182001C7C0303784BFFFA85814100D8812100D47C03000040820274EE
-S325000181A071460002418200FC8109000471080010418200348069000C38A29ADE90A10008B2
-S325000181C080E9000080E700187CE803A64E800021806100D43863000C900100084BFFAB6169
-S325000181E0812100D4808100DC7C040000418200A480C100DC88C600007CC607747C06000094
-S32500018200418200908069000C80A100DC90A1000881090000810800187D0803A64E80002191
-S32500018220812100D43C60001F6063FF6A38829AE39081000880C9000080C6002090C1000C7E
-S325000182408109000C91010010810100DC910100144BFFB6CD812100D48069000C80A9001466
-S3250001826090A1000880A9001090A1000C480017A5906100247C0303784BFF8CD58061002485
-S3250001828083E100007FE803A6382100D04E80002080E9000838E7000890E100DC4BFFFF68B6
-S325000182A0714700014182015880890000808400187C040000418200248069000C39029AECA0
-S325000182C09101000880A9000080A500187CA803A64E800021812100D480C9000470C60010D2
-S325000182E0418200103869000C900100084BFFAA5180C100DC7C06000041820084810100DCD5
-S32500018300890800007D0807747C080000418200703861002C810100DC91010008480050DDDC
-S325000183203C60001F6063FF6A38C29AF690C10008810100D4810800008108001C9101000C4A
-S3250001834080A100D480A5000C90A1001038A1002C90A100144BFFB5C9806100D43863000C41
-S325000183603901002C910100084BFFD56983E100007FE803A6382100D04E8000203861002C1E
-S32500018380808280A080840000908100084800506D3861002C38C0002F90C1000848004F3D79
-S325000183A07C03000041820050392300017D234B7838A29AF190A1000848005041806100D438
-S325000183C03863000C3881002C9081000838C100AC90C1000C4BFFD4417C0300004181FF440C
-S325000183E03860FFFF83E100007FE803A6382100D04E8000203921002C4BFFFFB43860FFFF3C
-S3250001840083E100007FE803A6382100D04E8000208069000C4BFFF889814100D8812100D4FA
-S325000184204BFFFD803821FFF08142801838C2E53838C608007C0A3040418000107C030378ED
-S32500018440382100104E8000203923002C80E900007C0700004182001880E900003927007C2A
-S3250001846080E900007C0700004082FFF038EA008090E2801891490000806900003821001080
-S325000184804E8000207FE802A697E1FFA89061005C39629E00810B00047C080000418200302C
-S325000184A080E1005C2C07FFFF41820038808B00008101005C7C08200041820028396B003080
-S325000184C0810B00047C0800004082FFD87C03037883E100007FE803A6382100584E800020DB
-S325000184E080AB000C7C0500004182FFD4808100607C0400004182005C814B002C7C0A0000A9
-S3250001850041820050810A0004812100607D2840394182003480A100642C05FFFF4182001410
-S3250001852080EA000C80C100647C063800408200187D43537883E100007FE803A638210058D5
-S325000185404E800020814A007C7C0A00004082FFB8808B0008708400804082002880AB00083C
-S3250001856060A5008090AB000891610054808B000C7C8803A64E80002181610054906B0028DA
-S325000185807C0D0378808B00287C0400004182FF30810B0028392000017D2968307D084839D9
-S325000185A04082000C39AD00014BFFFFDC3880000191A1004C7C8468307C8420F8810B00283F
-S325000185C07D042038908B00287D635B78916100544BFFFE5581A1004C816100547C6A1B78C5
-S325000185E07C0300004082000C39AD00014BFFFF9891A3000C80CB000890C30004810B0014D5
-S325000186009103001480AB001090A300109163000090610044808300047084000241820078CC
-S325000186207DA36B7838C29AFF90C10008812B00187D2803A64E80002181A1004C816100549F
-S3250001864081410044906A00087C0300004082001880EA00043FE0FFFF63FFFFFD7FE73839F2
-S3250001866090EA000480AA000470A50018408200287DA36B7838A29B0490A1000880EB0018F8
-S325000186807CE803A64E80002181A1004C816100548141004480CA000470C60001418200B82D
-S325000186A09001004838A0000190A1005080CA000080C600187C0600004182005C7DA36B7834
-S325000186C038A29B0990A10008810A0000810800187D0803A64E8000217C0300004182001839
-S325000186E080830000908100487C04000041820008900100508061004C38C29B0D90C10008C3
-S3250001870081010054810800187D0803A64E80002181410044386A000C8081004890810008A8
-S32500018720810100509101000C4BFFC96181A1004C81610054814100447C030000408000DC89
-S3250001874080EA00043FE0FFFF63FFFFEE7FE7383990EA000480AA000470A50010418200705D
-S3250001876080CA00043FE0FFFF63FFFFEF7FE6303990CA0004398282B8918280A0808C0000D7
-S325000187807C04000041820048386A000C80AC000090A1000838A1002090A1000C4BFFD0796B
-S325000187A081A1004C81610054814100447C0300004181005880C280A039860004918280A017
-S325000187C0808C00007C0400004082FFC080EA0004810100607D0738394182FDCC808100644F
-S325000187E02C04FFFF4182001080C100647C0668004082FDB47D43537883E100007FE803A670
-S32500018800382100584E800020808A000460840010908A00044BFFFFB838629B124BFFB1450A
-S3250001882081A1004C81610054814100444BFFFF287FE802A697E1FEF8480004C14BFF7AA127
-S32500018840480006654BFFB2394800254D4BFFAD1D4BFF7B314BFF8F614BFFA2E938629B23FE
-S325000188604BFFB101900280B44BFF791D38629B2C4BFFB0F14BFF7D657C6A1B7838629B32F7
-S32500018880914100E8914100084BFFB0D97C0B037839429E0080CA00047C060000418200209C
-S325000188A080AA00002C050002408203FC394A003080CA00047C0600004082FFE87C0B0000E0
-S325000188C0418203C480CB000470C60010418203B880A100E870A50002408200147C03037804
-S325000188E04BFFF3317C03000040820388900100F0900100F438629B4C4BFFA3B990610024F5
-S32500018900900100FC80A100247C0500004182005838E0000290E100F47C0A03782C0A000329
-S32500018920408002BC80610024914100F855451838388283487CA5221480A5000090A10008BF
-S3250001894048004B21814100F87C030000408202845547183838C283487CE7321480E7000416
-S3250001896090E100F4808100F07C0400004082001080C100F42C060002408201D4980100B0FF
-S325000189803860FFFF9001000838C0FFFF90C1000C4BFFFAF5900100FC39029E0091010020FD
-S325000189A081010020810800047C080000418200D480E100208147002C914101047C0A000094
-S325000189C0418200A4808100FC7C0400004082001838C0000190C100FC38629B884BFFAF8551
-S325000189E08141010480EA000470E700044182002438629B9680CA000080C6002490C1000821
-S32500018A00810A000C9101000C4BFFAF5981410104810A0004710800014182002438629B9D3F
-S32500018A2080EA000080E7001C90E10008808A000C9081000C4BFFAF2D81410104808A00049B
-S32500018A4070840018408200E4810A000471080002408200D8814A007C914101047C0A000015
-S32500018A604082FF6480A1002038A5003090A1002081010020810800047C0800004082FF3483
-S32500018A80808100FC7C0400004182000C38629BAB4BFFAED138629BAD38E1002890E100083E
-S32500018AA0388000509081000C38E100B090E100104BFFAD397C0300004180006838610028A7
-S32500018AC0388100EC9081000838C100FC90C1000C392101009121001038A1007890A10014CC
-S32500018AE04BFFF4957C03000041820038806100EC80A100FC90A10008810101009101000CDE
-S32500018B004BFFF9857C03000041820018810100FC9101000838C1007890C1000C4BFFF5E91E
-S32500018B20980100B04BFFFF7038629BA480EA000080E7002090E10008808A000C9081000CB6
-S32500018B404BFFAE21814101044BFFFF0C3900001F910100FC808100F42C04000140820018F3
-S32500018B6080C100FC3FE0FFFF63FFFFFB7FE6303990C100FC808100E8708400024182001863
-S32500018B8080C100FC3FE0FFFF63FFFFF77FE6303990C100FC3860FFFF80C100FC90C10008D5
-S32500018BA038A0FFFF90A1000C4BFFF8DD7C0300004182FDCC81030004812100FC7D2840382E
-S32500018BC0910100089001000C4BFFF53D4BFFFDB0394A00012C0A00034180FD4C8061002418
-S32500018BE038C100EC90C10008390100FC9101000C38A1010090A1001038E1007890E100142B
-S32500018C004BFFF3757C0300004082001838629B5580810024908100084BFFAD494BFFFD48AB
-S32500018C20806100EC808100FC90810008810101009101000C4BFFF8517C030000408200183D
-S32500018C4038629B6E81010024910100084BFFAD154BFFFD14810100FC9101000838E100781A
-S32500018C6090E1000C4BFFF4A1906100F04BFFFCF838629B404BFFACED7C0303784BFFF021C5
-S32500018C804BFFFC6C7C0303784BFFEF81906100187C03037880E1001890E100084BFFA0A1E7
-S32500018CA04BFFFC3091410020806A000038A0001090A1000838C0FFFF90C1000C4BFFF7C9DD
-S32500018CC0814100207C6B1B787C0300004182FBE0808B000470840010408200084BFFFBD022
-S32500018CE091610104386B000C900100084BFFA051816101044BFFFBC87FE802A697E1FFE891
-S32500018D008062801490010008388000249081000C4800401D80C2801439004E209106000487
-S32500018D204BFF74C180E28014906700103CA0FA2090A7002083E100007FE803A6382100187E
-S32500018D404E8000207FE802A697E1FFE87C691B78900100147C0900004182001488E90000C6
-S32500018D607CE707747C070000408200188061001483E100007FE803A6382100184E800020E9
-S32500018D8080C10014810100247C064000418000188061001483E100007FE803A6382100185C
-S32500018DA04E80002088A900007CA507747C05000041820028806100289121001C88C900005D
-S32500018DC07CC6077490C1000848003F418121001C7C030000408200C0890900007D0807745D
-S32500018DE07C080000408200188061001483E100007FE803A6382100184E8000208081001431
-S32500018E005484103A80E100207C843A149124000088C900007CC607747C060000418200282A
-S32500018E20806100289121001C88E900007CE7077490E1000848003ED58121001C7C030000F4
-S32500018E404182001480E1001438E7000190E100144BFFFF04888900007C8407742C04005CB5
-S32500018E604082001488A900017CA507742C05000A4182000C392900014BFFFF987D264B7893
-S32500018E803929000138E0002098E60000392900014BFFFF807D284B7839290001980800001B
-S32500018EA04BFFFF047FE802A697E1FFE03862813838C2C7D090C10008390010009101000CD4
-S32500018EC04800125538C2271074C6E0003CE020007C0638004182003038A227103862813844
-S32500018EE090A100083CE000407CE5385090E1000C4800124983E100007FE803A638210020E0
-S32500018F004E80002038A227103FE0FFFF63FFFFFF7FE528394BFFFFC87FE802A697E1FFD89A
-S32500018F209061002C810100307C0800004181000C38A0000490A100304BFF72699061002096
-S32500018F4038628138900100088081002C9081000C80E1003090E10010480013499061002409
-S32500018F60806100204BFF725980E100247C0700004082000C38629BC74BFFAA718061002498
-S32500018F809001000880A1002C90A1000C48003DA183E100007FE803A6382100284E8000209E
-S32500018FA07FE802A697E1FFE8388300033FE0FFFF63FFFFFC7FE42039386400089061001C97
-S32500018FC038800004908100084BFFFF5138A300043D00CAFE6108BEEF9103000038650004EC
-S32500018FE08121001C9125000083E100007FE803A6382100184E8000207FE802A697E1FFE0BD
-S325000190007C0300004182005038C3FFF890C1001880C600003CE0CAFE60E7BEEF7C06380084
-S325000190204182000C38629BCE4BFFA9C14BFF7175812100189061001C38628138912100089F
-S32500019040810900049101000C480010F18061001C4BFF716D83E100007FE803A63821002082
-S325000190604E8000204E8000207FE802A697E1FFF0808283809081000C390000FF9904001090
-S325000190804BFF70F98081000C88C4000060C6000198C400004BFF70E58081000C38C000177F
-S325000190A098C400144BFF70D583E100007FE803A6382100104E8000203821FFF080E2838032
-S325000190C09807001489070000710800FE99070000382100104E8000207FE802A697E1FFC092
-S325000190E038C2837090C100308106000C7C0800004182001483E100007FE803A63821004000
-S325000191004E800020386283C84BFFA8598141003038800001908A000C3CA0FA2060A50860F6
-S3250001912090A1003890AA00103CA0FA2060A53C8090AA00144BFFFF858121003080A9002C7B
-S325000191407C050000408200283860008438A0000290A100084BFFFDC5812100309069002C6B
-S3250001916080E9002C38E7008490E9002880E900307C0700004082001C3860008438E00002DF
-S3250001918090E100084BFFFD95812100309069003080E900187C0700004082004838600001D1
-S325000191A04BFFAB49812100309069001880C9003074C6E0003CE020007C06380041820248F1
-S325000191C080A9003080E9001890A7000480E90018B007000280C9001838A02000B0A600008A
-S325000191E080C9001C7C06000040820048386000024BFFAAF9812100309069001C80A9002CB4
-S3250001920074A5E0003CC020007C053000418201E48089002C80C9001C9086000480C9001CC0
-S32500019220B006000280A9001C38802800B085000080A280148145002080EA0AB860E70030D6
-S3250001924090EA0AB8A0EA0AC260E70030B0EA0AC280EA0ABC60E7003090EA0ABC81490014D3
-S3250001926080E9001874E7E0003CC020007C0730004182016C80A90018B0AA00008089001C6C
-S325000192807484E0003D0020007C0440004182013C80E9001CB0EA000238C0001898CA00043B
-S325000192A038800018988A000538E00084B0EA0006900A0008900A000CA08A0000B08A0010B8
-S325000192C0B00A0012900A0018A0AA0002B0AA0020900A001CB00A00224BFF6EA181E2801461
-S325000192E03DC0000161CE86A08181003838C0000198CC000C980C0000980C00047DCD7378F0
-S3250001930080EF00087CE773D6388000027CE723D63A07FFFD7C0B03787C0B80004080008087
-S32500019320394000037C0A000041800068808F000838AA00027C842E305567083C38E700067D
-S325000193407C843BD67D247051408000087D2900507C096800408000307D2D4B78996C00087E
-S3250001936088AC00003FE0FFFF63FFFFF97FE52839390000037D0A40505508083C7CA54378A6
-S3250001938098AC0000394AFFFF7C0A00004080FFA0396B00017C0B80004180FF883860002070
-S325000193A03CC0FFC260C6951890C10008390283709101000C480018BD83E100007FE803A660
-S325000193C0382100404E80002080E9001C3FE0FFFF63FFFFFF7FE738394BFFFEBC80A90018E1
-S325000193E03FE0FFFF63FFFFFF7FE528394BFFFE8C8089002C3FE0FFFF63FFFFFF7FE42039E2
-S325000194004BFFFE1480A900303FE0FFFF63FFFFFF7FE528394BFFFDB07FE802A697E1FFE0F1
-S3250001942080A1002890A10018812500109121001488E9001090E1001C4BFF6D418141001837
-S325000194408121001C80810014992400107126001441820034386283D6912100084BFFA50522
-S325000194608121001880C900207C060000418200089009002083E100007FE803A638210020CF
-S325000194804E8000207127000241820018808A00202C0400034082000C38A0000190AA002004
-S325000194A0712600014182FFD0810A00202C0800044082FFC438800001908A002083E10000BC
-S325000194C07FE803A6382100204E800020806300202C0300024080000C386000014E80002087
-S325000194E07C0303784E8000207FE802A697E1FFE89061001C80C1001C900600249001001446
-S325000195008061001C4BFFFFC97C0300004082007480A280B47C0500004182FFE880E100148A
-S3250001952038E7000190E100142C0700644081002C80C1001C39000001910600208081001C90
-S3250001954038C0000190C4002483E100007FE803A6382100184E800020386000014BFF952127
-S325000195607C03037880E1001C90E100084BFFFEAD8061001C4BFFFF597C0300004182FF948B
-S3250001958083E100007FE803A6382100184E8000207FE802A697E1FFD88181003439628370CF
-S325000195A02C0C0080408100183860FFFF83E100007FE803A6382100284E8000203940000120
-S325000195C080CB002C3FE0FFFF63FFFFFE7FE5183998A60000706500014182001480EB002C5A
-S325000195E07C66467098C70001394A000191610024806B002C914100207C63521480A1003033
-S3250001960090A100089181000C48003959812100243900000391090020808900183D000000F8
-S325000196206108B000B104000080A9002C74A5E0003CC020007C053000418200C88089002C7A
-S3250001964080C9001C9086000480C9001C80A10034808100207CA52214B0A600028109001C54
-S325000196603CE0000060E7B800B0E800004BFFF9FD810100248108001038E0008198E8000C8C
-S325000196804BFF6AF9806100244BFFFE614BFFFA2D81610024814B0020808B001CA0840000BA
-S325000196A0708880004082000C70850007418200183860FFFF83E100007FE803A638210028FB
-S325000196C04E8000202C0A0001418200183860FFFF83E100007FE803A6382100284E8000200A
-S325000196E0808B00247C0400004082FFC88061003483E100007FE803A6382100284E80002033
-S325000197008089002C3FE0FFFF63FFFFFF7FE420394BFFFF307FE802A697E1FFD081E1003C67
-S325000197203DC020007C6C1B78394283702C0F0080408100183860FFFF83E100007FE803A67E
-S32500019740382100304E800020808A002C6068000199040000706800014182002480AA0028DD
-S325000197603FE0FFFF63FFFFFE7FE4603998850000808A00287D8846709904000138A00004E6
-S3250001978090AA002080EA003074E7E0007C077000418201D080CA0030810A001890C8000493
-S325000197A0810A00183CE0000060E7B000B0E800007C0D0378816A001CB00B0008718500018F
-S325000197C04182002C810A00287508E0007C0870004182017C80EA002890EB00043880000284
-S325000197E0B08B0002396B000839A0040080AA002C74A5E0007C0570004182013C9141002C5E
-S32500019800808A002C908B000438CF0001B0CB000261A8A800B10B000091A100207C0D00001F
-S325000198204182001480AA001C3C80000060848000B08500004BFFF83580A1002C80A50010B6
-S32500019840388000819885000C4BFF69318061002C4BFFFC994BFFF86581C1003C8141002CBC
-S3250001986081AA0020816A001CA16B000080A100207C0500004182001080EA001CA0E70008D9
-S325000198807D6B3B78818A0018A18C00027C0C7000408100087DCC7378716800074082000C31
-S325000198A071658000418200183860FFFF83E100007FE803A6382100304E8000202C0D0001B5
-S325000198C0418200183860FFFF83E100007FE803A6382100304E800020808A0018A0840000DF
-S325000198E070848000418200183860FFFF83E100007FE803A6382100304E80002080EA002403
-S325000199007C0700004082FFA48061003880EA003090E10008918100189181000C4800364521
-S325000199208061001883E100007FE803A6382100304E8000209141002C808A002C3FE0FFFFEB
-S3250001994063FFFFFF7FE420394BFFFEBC80EA00283FE0FFFF63FFFFFF7FE738394BFFFE7C36
-S3250001996080CA00303FE0FFFF63FFFFFF7FE630394BFFFE287FE802A697E1FFD88161003437
-S325000199809061002C80A1003890A100247C0A03787C0A58004080004C392020007CEA585083
-S325000199A07C074800408000087D2A58508061002C80E100249141001C7CE7521490E10008FC
-S325000199C09121000C80C100307CC803A64E8000218141001C906100207C030000418100182D
-S325000199E07D43537883E100007FE803A6382100284E800020386285574BFF9F698161003414
-S32500019A0080E100208081001C7D443A144BFFFF847FE802A697E1FFD09061003490010008B1
-S32500019A2080A100387CA803A64E8000217C030000408000183860FFFF83E100007FE803A6A9
-S32500019A40382100304E80002038600020900100084BFFF4C97C6B1B783880002080610034C9
-S32500019A6080E1003C90E100089081002C9081000C91610020916100104BFFFEFD8141002034
-S32500019A8080C1002C7C03300041820020806282CC4BFF9ED13860FFFF83E100007FE803A6CD
-S32500019AA0382100304E800020888A00005484402E88EA00017C843B785484801E890A00029F
-S32500019AC05508402E88AA00037D082B787C8443782C0406EB4182004C3862855988CA0000A2
-S32500019AE054C6402E888A00017CC6237854C6801E88AA000254A5402E88EA00037CA53B784B
-S32500019B007CC62B7890C100084BFF9E593860FFFF83E100007FE803A6382100304E8000203E
-S32500019B2088AA001454A5402E890A00157CA5437854A5801E88CA001654C6402E88EA0017DD
-S32500019B407CC63B787CA5337874A5E0003CE020007C05380041820294888A00145484402E8A
-S32500019B6088AA00157C842B785484801E88CA001654C6402E890A00177CC643787C8433783C
-S32500019B809081002888CA000454C6402E888A00057CC6237854C6801E88AA000654A5402E5C
-S32500019BA088EA00077CA53B787CC62B783862858490C1002C90C100084BFF9DA9806100344E
-S32500019BC08081003C908100088101002C9101000C80A1002890A100104BFFFD9D8161002C60
-S32500019BE0814100207C03580041820020806282CC4BFF9D713860FFFF83E100007FE803A630
-S32500019C00382100304E800020808100287CCB221438C60FFF3FE0FFFF63FFF0007FEB3039D2
-S32500019C2088EA000854E7402E88AA00097CE72B7854E7801E88CA000A54C6402E890A000B5E
-S32500019C407CC643787CE733783862858790E1002C90E10008916100289161000C4BFF9D0532
-S32500019C60806100348101003C9101000880E1002C90E1000C80810028908100104BFFFCF9DD
-S32500019C808141002080E1002C7C03380041820020806282CC4BFF9CCD3860FFFF83E10000D7
-S32500019CA07FE803A6382100304E8000203862859388AA000C54A5402E890A000D7CA5437843
-S32500019CC054A5801E888A000E5484402E88CA000F7C8433787CA5237890A10008890A0014D8
-S32500019CE05508402E88CA00157D0833785508801E88EA001654E7402E888A00177CE72378A8
-S32500019D007D083B789101000C4BFF9C594BFF73354BFF9F554BFF648D8141002088EA001454
-S32500019D2054E7402E88AA00157CE72B7854E7801E890A00165508402E892A00177D084B78C7
-S32500019D407CE7437874E7E0003C8020007C0720004182004888CA001454C6402E88EA0015A4
-S32500019D607CC63B7854C6801E890A00165508402E88AA00177D082B787CC643787CC803A660
-S32500019D804E8000217C03037883E100007FE803A6382100304E80002088CA001454C6402EFA
-S32500019DA0890A00157CC6437854C6801E888A00165484402E88EA00177C843B787CC62378B8
-S32500019DC03FE0FFFF63FFFFFF7FE630397CC803A64E8000217C03037883E100007FE803A6E7
-S32500019DE0382100304E800020888A00145484402E88CA00157C8433785484801E88EA001669
-S32500019E0054E7402E88AA00177CE72B787C843B783FE0FFFF63FFFFFF7FE420394BFFFD64AC
-S32500019E207FE802A697E1FFE89061001C386300184BFFF17138A3001890A3000C8103000C7F
-S32500019E40910300049103000080C3000C80E1001C7CC63A1490C30008900300103D00CAFE70
-S32500019E606108BEE09103001483E100007FE803A6382100184E8000207FE802A697E1FFF0E3
-S32500019E807C691B787C0300004182004090610014810300143CE0CAFE60E7BEE07C0838009F
-S32500019EA041820010386281284BFF9B4181210014900900143CE0DEAD60E7BABE90E900100D
-S32500019EC07D234B784BFFF13583E100007FE803A6382100104E8000207FE802A697E1FFE86F
-S32500019EE0386000144BFFF0BD900300049003000080A1002490A30008808100289083000CC6
-S32500019F009003001083E100007FE803A6382100184E8000207FE802A697E1FFE89061001C49
-S32500019F204BFF62818141001C90610014812A0000912100107C0900004182003C80A90010E0
-S32500019F4090AA00009009001080E90004810900007CE83850810A00107CE7405090EA00101C
-S32500019F6080CA00107C0600004080000C3862812E4BFF9A79806100144BFF624580610010B5
-S32500019F8083E100007FE803A6382100184E8000207FE802A697E1FFE89061001C4BFF6205BB
-S32500019FA08141001C812100207C6B1B789009001080EA00007C0700004082005C912A000011
-S32500019FC0912A000480A9000480C900007CA6285080CA00107CA62A1490AA00107D635B78F4
-S32500019FE04BFF61DD8121001C80A900087C050000418200148069000C80E900087CE803A618
-S3250001A0004E80002183E100007FE803A6382100184E80002080AA0004912500104BFFFFA496
-S3250001A020806300104E8000207FE802A697E1FFE09061002438C0FFFF90C100144BFF616552
-S3250001A04081610014814100247C6C1B78916100147C0B000040800010812A00007C09000015
-S3250001A060408200207D8363784BFF61558061001483E100007FE803A6382100204E8000204C
-S3250001A08080E9000080C900047C073040408000208169000038EB000190E90000896B0000B5
-S3250001A0A0808A00103884FFFF908A001080E9000080C900047C0730404180FF9480E9001025
-S3250001A0C090EA0000900900104BFFFF847FE802A697E1FFE89061001C386000014BFFFD45E9
-S3250001A0E07C681B788083000438C4000190C3000480C1002098C400008061001C9101000833
-S3250001A1004BFFFE9183E100007FE803A6382100184E800020812100089123000480C1000CDD
-S3250001A12038A000087CC62BD654C618387CC64A1490C300084E8000207FE802A697E1FFD844
-S3250001A14081810034816100307C6E1B787C0C00004181001483E100007FE803A638210028E0
-S3250001A1604E8000208143000480AA00047C0558404181001080CA00007C0600004082011C5E
-S3250001A18080AE00047C0A28404081001C38CAFFFC80C6000080EAFFF87CC63A147C065800AD
-S3250001A1A0418200A47D0B6214812A00047C0848004082001080EA00007C07000040820060D7
-S3250001A1C0808E00087C0A20404180002C3862829880AE000090A100089161000C9181001054
-S3250001A1E04BFF978183E100007FE803A6382100284E80002081AA0004916A00047DAB6B78DA
-S3250001A20081AA0000918A0000394A00087DAC6B787C0D00004182FFD04BFFFFA880AA000420
-S3250001A2207D0C2850910A000480EA00007CA7621490AA000083E100007FE803A63821002845
-S3250001A2404E80002080CAFFF87C866214908AFFF87C8B621480AA00047C0428004082FF88A3
-S3250001A26080AA0000808AFFF87CA42A1490AAFFF880EA00007C0700004182FF6C394A000877
-S3250001A280388AFFFC80CA000490C40000810A0000910AFFF84BFFFFDC394A00084BFFFECC77
-S3250001A2A07FE802A697E1FFD881E1003081C1003481A100387C701B7881630004810B0000E4
-S3250001A2C07C08000041820028818B00047C0F00004182005C7C0C784040810028396B000879
-S3250001A2E0810B00007C0800004082FFE07C03037883E100007FE803A6382100284E800020C9
-S3250001A3007D0F7214812B00007D2C4A147C084840408100187C03037883E100007FE803A61E
-S3250001A320382100284E8000207DEC7B787C0D0000408100147C8D62143884FFFF7C846B96B3
-S3250001A3407D8469D680CB000080EB00047CC63A147CCC30507C067040408000084BFFFF80E1
-S3250001A36081AB00047CEC721490EB00047D0C72147D0D4050812B00007D084850910B0000AB
-S3250001A38080CB00007C06000040820028396B000838CBFFFC810B00049106000080AB000003
-S3250001A3A090ABFFF87C050000418200084BFFFFE07C0D6000418200207E03837891A100086D
-S3250001A3C0918100207CCD605090C1000C4BFFFD6D818100207D83637883E100007FE803A6C9
-S3250001A3E0382100284E8000207FE802A697E1FFB8388002809081003438A001E090A1003808
-S3250001A40038C0000390C1003C90010040386100344800042180E100407C07000040820014A8
-S3250001A42083E100007FE803A6382100484E800020388000039082825480A1004090A2824812
-S3250001A44038E000A090E28250900282589002825C3900028091028260388001E0908282645C
-S3250001A46038A2824838C2824880E600108106001490E5002091050024810600188086001C4C
-S3250001A480910500289085002C7C0303783880FFFF9081000838C0FFFF90C1000C3900FFFF63
-S3250001A4A09101001048000641386000FF900100089001000C900100104800062D3862824817
-S3250001A4C038A1000890A1002C80E1002C900700008081002C9004000438C2824890C1001029
-S3250001A4E0390100143882824880A4001080C4001490A8000090C8000480C4001880E4001C87
-S3250001A50090C8000890E8000C900100244BFFCAB538E0000890E280A8900280AC8102800C4B
-S3250001A52089080105910280B083E100007FE803A6382100484E8000207FE802A697E1FFB879
-S3250001A5407C691B7880C282487C0600004082001483E100007FE803A6382100484E80002015
-S3250001A5609061004C2C030008418202302C030009418201D02C03000A4182010480A282609A
-S3250001A580810280B07CA8285080C280A87C062800418000103860000A4BFFFFA18121004C06
-S3250001A5A07129007F408100C8A8E280087C093800408000BC5528183880C2800C7D28321421
-S3250001A5C03881003C38A280A880C5000080E5000490C4000090E400043862824838E100087E
-S3250001A5E090E100348081003488C900047CC607748101003C7CC8321490C4000080C1003457
-S3250001A600810100409106000480A2801090A10010390100149101003080A10030A8E90000F1
-S3250001A62090E50000808100309004000480C1003091210044A90900089106000880A10030C4
-S3250001A64088E2800A7CE7077490E5000C38E0000C90E100244BFFC96D808100448884000511
-S3250001A66080C1003C7C843214908280A883E100007FE803A6382100484E8000203900000892
-S3250001A680910280A88882800A7C840774810280AC7C882214908280AC88C2800A7CC6077431
-S3250001A6A080E282647CC63850810280AC7C0830004081000C80A2825C90A280AC386282488F
-S3250001A6C038E1000890E10034808100349004000080C10034810280AC9106000438A2824881
-S3250001A6E090A1001038E1001490E10030808100309004000080C10030810280AC91060004C4
-S3250001A70080A1003080E2826090E500088081003088C2800A7CC6077454C6083C80E280AC72
-S3250001A7207CC63A1490C4000C900100244BFFC89583E100007FE803A6382100484E800020C3
-S3250001A740808280A83884FFF880A280B07C842BD67084000738C000087C84305080E280B0B5
-S3250001A7607C8439D680A280A87C852214908280A880E280A8808282607C0720004180FEF048
-S3250001A7803860000A4BFFFDB583E100007FE803A6382100484E80002080C280B038C6000899
-S3250001A7A0810280A87C0830004180FEC480A280B080E280A87CA5385090A280A83860002019
-S3250001A7C04BFFFD7980A280B080E280A87CA5385090A280A883E100007FE803A638210048BE
-S3250001A7E04E8000207FE802A697E1FFF07C691B788101001838C8FFFF90C100187C080000F1
-S3250001A8004081002038E9000190E10014886900007C6307744BFFFD25812100144BFFFFD41F
-S3250001A82083E100007FE803A6382100104E8000207FE802A697E1FFD87C6A1B7880E2801479
-S3250001A84080E7002090E10024388001E09083000438E0028090E3000038A0000390A3000802
-S3250001A860806300009141002C80EA00047C6339D638A0001090A100084BFFE6A13DA0017D47
-S3250001A88061AD78408181002C81610024906C000C80AC000080CC00047CA531D690AC0010BF
-S3250001A8A0808B00303FE0FFFF63FFFFBF7FE42039908B0030810C000C7508E0003D2020009F
-S3250001A8C07C0848004182020C80EC000C90EB085080EC0000810C00047CE741D654E7183887
-S3250001A8E038E7007F390000807CE743D654E7881C60E70D6690EB084038A000037C050000C6
-S3250001A900418200142C050002418201A02C050003418201687C0A03782C0A00104080001C3F
-S3250001A9205546083C7CC65A14B1460E00394A00012C0A00104180FFEC808C0004548458289E
-S3250001A9403FE0100063FF00217FE42378908B084880CC000054C6502A3FE0010063FF00E48F
-S3250001A9607FE6337890CB084480C28014818600087D4C6BD67CCC53D67C0668004081000806
-S3250001A980394A00019141001C2C0A00104180000C38E0001090E1001CB00B097638E01FFF06
-S3250001A9A0B0EB0972A0AB097270A5FDFFB0AB097238A01FFFB0AB0970810B0ABC61085001F7
-S3250001A9C0910B0ABC810B0AB861085001910B0AB8A10B0AC27108AFFEB10B0AC24BFF579D44
-S3250001A9E080C100243D0055CC6108AA33910603804BFF578981410024808A02803FE0FFFF74
-S3250001AA0063FFFFE07FE4203938A281108101001C7CA5421488A500007C842B78908A028046
-S3250001AA204BFF575980A100243CE0AA3360E755CC90E503804BFF57458102825091028250D7
-S3250001AA4080A1002438E0000798E508584BFF572D8101002480A8084060A5000190A8084044
-S3250001AA60386000014BFF5D3183E100007FE803A6382100284E8000207C0A03782C0A010043
-S3250001AA804080FEB85544402E554520367C842B787C8453785545083C7CA55A14B0850E0024
-S3250001AAA0394A00014BFFFFD87C0A03782C0A00104080FE885546402E554720367CC63B786D
-S3250001AAC07CC65378B0CB0E00394A00014BFFFFE080EC000C3FE0FFFF63FFFFFF7FE7383960
-S3250001AAE04BFFFDEC80810008548B273E80E1000C54EA273E80A1001054A9273E3FE0FFFF0F
-S3250001AB0063FFFFFF7FE81A78710800FF5508083C80C2801480C600207D0832145565402E8D
-S3250001AB20554620367CA533787CA54B78B0A80E00386000014E8000203821FFE83D4055CCA2
-S3250001AB40614AAA333D20FA209149030038C000C3B0C902009149032038E000C1B0E902204B
-S3250001AB603CA0AA3360A555CC90A903209149034038C00082B0C90240382100184E800020E2
-S3250001AB807FE802A697E1FFE081410028906100247145000341820010386287E44BFF8E4D93
-S3250001ABA081410028812100243CC07C1060C643A690C900003C807C08608402A69089000405
-S3250001ABC03CE07C1260E743A690E900087544E0003CC020007C043000418200887D485378D3
-S3250001ABE07D0A437855053E7F4182000C2C05007F408200303FE003FF63FFFFFC7FE5503919
-S3250001AC003FE0480063FF00037FE52B7890A9000C83E100007FE803A6382100204E8000203A
-S3250001AC205544843E64843C009089000C7144FFFF64846000908900103C807C08608403A678
-S3250001AC40908900143CE04E8060E7002190E9001883E100007FE803A6382100204E80002002
-S3250001AC603FE0FFFF63FFFFFF7FE850394BFFFF747FE802A697E1FFE89061001C8082E53011
-S3250001AC802C0400304180000C386287EC4BFF8D5D80C1001C7D4602148082E53039040001B4
-S3250001ACA09102E5305484203638A2E03038A502007D642A145547103A38C2E0307CE7321436
-S3250001ACC080E7000090EB000881010020910B000080E1002490EB00045544103A38E2E03034
-S3250001ACE07C843A149164000080A28014816500202C0A00104180003038EAFFF070E7001F90
-S3250001AD0038C000017CC7383080CB09487CC73B7890EB094883E100007FE803A63821001845
-S3250001AD204E8000202C0A000841800038714800075508083C38E0001F7D08385039200001E8
-S3250001AD407D284030808B00147C884378910B001483E100007FE803A6382100184E80002076
-S3250001AD605544083C608400013900001F7C84405038A000017CA4203080AB00147CA42378DF
-S3250001AD80908B001483E100007FE803A6382100184E8000207FE802A697E1FFE03D4055CCA6
-S3250001ADA0614AAA33810280148128002080A900043FE0FFFF63FFFFF37FE5283990A9000484
-S3250001ADC09009001438E0FFFF90E900189009094038E0FFFF90E90944900909483CE000E173
-S3250001ADE060E79F0090E9094080A9094060A5008090A909409149030039000001B109020058
-S3250001AE0080C9001464C6004090C900149149030C4BFF53693860FFFF4BFF53E17C090378F4
-S3250001AE202C0930004080002C7D234B789121001C3D00FFC2610803A8910100084BFFFD4551
-S3250001AE4080E1001C392701002C0930004180FFDC83E100007FE803A6382100204E80002031
-S3250001AE607FE802A697E1FFD87C6A1B787C0903782C09002840800064386288065526103A86
-S3250001AE8038A284307CC62A1480C6000090C10008810A00009101000C912100245528103A38
-S3250001AEA038E284307D083A1481080004910100109141002080AA000490A100144BFF8AA5DD
-S3250001AEC0810100243928000280C10020394600082C0900284180FFA483E100007FE803A645
-S3250001AEE0382100284E8000207FE802A697E1FFE87C6A1B789061001C80C3000054C9C23E88
-S3250001AF002C090005418200802C0900094182005C38C0000190C280B47C0900004180003C4F
-S3250001AF202C09001540800034386288345524103A390295A07C8442148084000090810008D0
-S3250001AF404BFF8A218061001C4BFFFF19386288424BFF8A11480000003862881B912100080E
-S3250001AF604BFF8A014BFFFFE07D435378900100084BFF7B8983E100007FE803A63821001875
-S3250001AF804E8000204800001583E100007FE803A6382100184E8000207FE802A697E1FFD82E
-S3250001AFA09061002C810280148168002091610018890B001C550CF0BE7D8A0E7091810024C9
-S3250001AFC071880001418200E02C0A00044082002438800001B08B09304BFF51A1818100241E
-S3250001AFE081610018A0AB093054A5AAFE39450010914100205545103A3882E0307CA52214A6
-S3250001B000814500007C0A00004082000848000000808A000C7C0400004182002038A0001F5B
-S3250001B0207CAC285038C000017CC5283080CB00107CC52B7890AB00108061002C80EA0004D2
-S3250001B04090E100089141001C80EA00007CE803A64E80002180C1001C814600087C0A00006A
-S3250001B060418200084BFFFFD480C100202C060010418000248101001880A1002038A5FFF0B2
-S3250001B080392000017D2528308088094C7C852B7890A8094C83E100007FE803A638210028D2
-S3250001B0A04E800020394A00084BFFFF487C691B7888A3000054A5402E888300017CA52378AD
-S3250001B0C054A5402E88C300027CA5337854A5402E88C300037CA533783CE0FEEF60E70F1EEB
-S3250001B0E07C05380040820030886300205463402E88C900217C6333785463402E88E90022BA
-S3250001B1007C633B785463402E890900237C6343784E8000207C0303784E8000207FE802A63D
-S3250001B12097E1FFE8386001F43CA0FFC260A5B21C90A100089001000C4BFF65959062822CF2
-S3250001B14038628BE04BFF881D83E100007FE803A6382100184E8000207FE802A697E1FFB8E3
-S3250001B160818100507C6B1B788083000480A300007C8520502C040040408000183860FFFF83
-S3250001B18083E100007FE803A6382100484E80002081430000890A00005508402E88EA000110
-S3250001B1A07D083B785508402E892A00027D084B785508402E888A00037D0823783CA0FEEFBF
-S3250001B1C060A50F1E7C082800418200183860FFFF83E100007FE803A6382100484E80002016
-S3250001B1E0900282EC88CA001054C6402E88AA00117CC62B7854C6402E88EA00127CC63B7835
-S3250001B20054C6402E88EA00137CCE3B78888A00145484402E890A00157C8443785484402E08
-S3250001B22088AA00167C842B785484402E88AA00177C842B789081003888EA001854E7402E6E
-S3250001B24088CA00197CE7337854E7402E890A001A7CE7437854E7402E890A001B7CE7437885
-S3250001B26090E1003488AA000C54A5402E888A000D7CA5237854A5402E88CA000E7CA533780F
-S3250001B28054A5402E88CA000F7CA5337890A10030890A00045508402E88EA00057D083B78A1
-S3250001B2A05508402E892A00067D084B785508402E888A00077D0D237888CA000854C6402ED0
-S3250001B2C088AA00097CC62B7854C6402E88EA000A7CC63B7854C6402E88EA000B7CC63B7854
-S3250001B2E090C1002880C3000038C6002090C3000081430000888A00005484402E890A00016A
-S3250001B3007C8443785484402E88AA00027C842B785484402E88AA00037C842B782C0406EB0F
-S3250001B3204182002038628BE24BFF86393860FFFF83E100007FE803A6382100484E8000207A
-S3250001B34088CA001454C6402E88AA00157CC62B7854C6402E88EA00167CC63B7854C6402E3F
-S3250001B36088EA00177CC63B7890CC000081030000390800209103000080EC000074E7E000CC
-S3250001B3803D0020007C0740004182015480CC00007CC3337890C100449161004C916100086B
-S3250001B3A091A1000C91C1001038A28BFF90A1001448000141816100287C6A1B787C030000B1
-S3250001B3C04082002038628C044BFF85993860FFFF83E100007FE803A6382100484E80002059
-S3250001B3E07C0B00004182005C38EA0FFF3FE0FFFF63FFF0007FE3383980E1004C90E1000808
-S3250001B4009161000C810100389101001038C28C1790C10014480000DD7C6A1B787C030000AC
-S3250001B4204082002038628C1C4BFF85393860FFFF83E100007FE803A6382100484E80002040
-S3250001B44080C100307C060000418200407D435378914100408081004C8084000090810008E8
-S3250001B460808100309081000C48001AF981610030808100407D445A1480E1004C80C70000A6
-S3250001B4807C865A1490870000808282EC80C100347C0430004182003038628C2F810282EC50
-S3250001B4A09101000880C1003490C1000C4BFF84B53860FFFF83E100007FE803A638210048EB
-S3250001B4C04E80002080C100447C66505083E100007FE803A6382100484E80002080CC000021
-S3250001B4E03FE0FFFF63FFFFFF7FE630394BFFFEA47FE802A697E1FFE07C6A1B7838628C67A2
-S3250001B5008081003490810008914100249141000C80A1002C90A100104BFF84498101002CAF
-S3250001B5207C080000408200188061002483E100007FE803A6382100204E80002080610028BD
-S3250001B5403902EE00910100089001000C480003257C030000408000187C03037883E100005F
-S3250001B5607FE803A6382100204E8000208061002838E20A0890E10008388000089081000CC2
-S3250001B580480002F1814100287C030000408000187C03037883E100007FE803A63821002041
-S3250001B5A04E80002080CA000480EA00007CC7305080A1002C7C0628004080002038628C7F9F
-S3250001B5C04BFF83A17C03037883E100007FE803A6382100204E800020386001F43D00FFC296
-S3250001B5E06108B21C910100089001000C4BFF60E1814100289062822C80610024810A000031
-S3250001B60091010008810A00008121002C7D084A149101000C38E2EE0090E1001039020A08D9
-S3250001B6209101001480A1003090A100184800006D906100248062822C4BFF61759002822C09
-S3250001B64038628C8E4BFF831D814100247C0A00004082002038628C904BFF83097C03037871
-S3250001B66083E100007FE803A6382100204E80002080E100288081002C80C700007C862214B3
-S3250001B680908700007D43537883E100007FE803A6382100204E8000203821FFE8820100243F
-S3250001B6A081610030812100207C6C1B78556536BE2C050013418201942C05001F4182018C4A
-S3250001B6C02C05003B418201842C05003F4182017C81A282EC7C0980404080016088890000F7
-S3250001B6E07C8F2378392900017C0E03787C8A26707C0A00004082002C7D6A5B78914C00008E
-S3250001B700398C00047DAD521471EA000F39CE00012C0E00014082FFC07C0A00004182FFDC77
-S3250001B7202C0A00014082009488E9000354E7402E88C900027CE7337854E7402E89090001BB
-S3250001B7407CE7437854E7402E890900007CEA4378392900047C098040408100107C030378F2
-S3250001B760382100184E800020554736BE2C070013418200202C07001F418200182C07003B0F
-S3250001B780418200102C07003F418200084BFFFF703FE0FC0063FFF8017FE8503955478BFE4E
-S3250001B7A070E707FE7D083B78714407FE548478207D0A23784BFFFF48280A000841810044D1
-S3250001B7C038AAFFFE54A5402E890900007CA5437854A5103A80C1002C7CA5321480A500046E
-S3250001B7E0890900017CAA4378392900027C0980404081FF787C030378382100184E80002094
-S3250001B800390AFFF75508402E88C900007D0833785508103A80E100287D083A1481480004CC
-S3250001B820392900017C0980404081FF407C030378382100184E80002091A282EC7D83637884
-S3250001B840382100184E8000203FE0FC0063FFF8017FE6583955658BFE70A507FE7CC62B78D4
-S3250001B860716707FE54E778207CCB3B784BFFFE647FE802A697E1FFD08083000480A30000EB
-S3250001B8807C8520502C040002408000183860FFFF83E100007FE803A6382100304E800020A5
-S3250001B8A081030000890800005508402E9061003480E3000088E700017D083B7838628CB398
-S3250001B8C09101001C910100084BFF809981C100388161003480CB000038C6000290CB000080
-S3250001B8E08081001C39A4FFFE7C0D00004081002C810B0004812B00007D0940507C08680096
-S3250001B900408000183860FFFF83E100007FE803A6382100304E800020900E0000814B00005D
-S3250001B92080CB00007D866A14810B00007CC86A1490CB00007C0D03787C0A60404080009011
-S3250001B9407C0B03787C0A6040418000183860FFFF83E100007FE803A6382100304E8000205E
-S3250001B9605568383088CA000070C6007F7D0B33787D455378394A000188A5000070A500808E
-S3250001B980418200207C0A60404180FFD83860FFFF83E100007FE803A6382100304E8000207E
-S3250001B9A07DAD5A14808E000038A4000190AE00005484103A7C84721480E1003C7DA53830F0
-S3250001B9C090A400047C0A60404180FF787C03037883E100007FE803A6382100304E800020E5
-S3250001B9E03821FFF07C6B1B7880A1001C810100247D45421480C10018808100207D26221430
-S3250001BA008081001C7C0A20404080000839290001914B0004912B0000382100104E800020FE
-S3250001BA203821FFF07C6B1B788101001C80C100247D4640508081001880E100207D27205039
-S3250001BA4080E1001C7C0A3840408100083929FFFF914B0004912B0000382100104E80002048
-S3250001BA603821FFD8CA2100307C6E1B78DA210020810100203FE0000F63FFFFFF7FE84039CC
-S3250001BA80650C001081A10024810100205508653E710807FF38C004337D2830507C0B037861
-S3250001BAA07C0A03787C090000418000B02C090020408000847C090000408200607DAB6B783D
-S3250001BAC07D8A637880A1002074A580007C050000418200207C0B0000418200287C040378D2
-S3250001BAE07D6B20503FE0FFFF63FFFFFF7FEA5278914E0000916E0004382100284E800020E6
-S3250001BB007C0703787D4A3850914E0000916E0004382100284E8000207DA54C3038C00020CA
-S3250001BB207CC930507D8630307CAB33787D8A4C304BFFFF942C0900204082000C7D8B63789E
-S3250001BB404BFFFF842C0900404080FF7C38C9FFE07D8B34304BFFFF707C0703787D29385030
-S3250001BB602C09000A418100207DAB48307D85483038C000207CC930507DA634307CAA33784E
-S3250001BB804BFFFF44FC80881ED8828020814280244BFFFF347FE802A697E1FFE8C061002062
-S3250001BBA0D86100084BFFFEBD83E100007FE803A6382100184E8000203D20433080E1000430
-S3250001BBC074E780007C0700004182009C808100087C0400004182007C7C0603788101000852
-S3250001BBE07CC8305090C1000880C100043FE0FFFF63FFFFFF7FE6327890C1000480E1000496
-S3250001BC00912280206CE6800090C28024C8228020FC21D828C8828428FC01013280A100080C
-S3250001BC20912280206CA4800090828024C8628020FC63D828FC03E0004080000CC8428428DA
-S3250001BC40FC63102AFC00182AFC1C00284E8000207C04037880C100047C8620509081000411
-S3250001BC604BFFFF9C80A10004912280206CA4800090828024C8628020FC63D828C84284283B
-S3250001BC80FC0300B281010008912280206D07800090E28024C8228020FC21D828FC01E00081
-S3250001BCA04080000CC8428428FC21102AFC00082A4E8000207FE802A697E1FFF038C1000415
-S3250001BCC038E10014810700008087000491060000908600044BFFFEE5FC00001883E1000047
-S3250001BCE07FE803A6382100104E8000203821FFD83DA080008241003C822100408161002C59
-S3250001BD008181003081210034814100387C0A00004082000C7C090000418200F47C0B68405B
-S3250001BD20418000E07C0F03787C0E03787C096840418000147C096800408200307C0A784031
-S3250001BD40408000285525083C55480FFE7CA94378554A083C39CE00017C0968404180FFE8EC
-S3250001BD607C0968004182FFD87C0F03787C0D03787C0E00004180006455E4083C55A70FFEF6
-S3250001BD807C8F3B7855AD083C7C0B4840418100147C0B4800408200287C0C50404180002001
-S3250001BDA07D9063787D8A60507C0C804040810008396BFFFF7D69585061AD00015547F87E7B
-S3250001BDC05525F8007CEA2B785529F87E39CEFFFF7C0E00004080FFA47C1200004182000C9E
-S3250001BDE091B2000491F200007C1100004182000C9191000491710000382100284E8000207F
-S3250001BE007D6D5B787D8F63784BFFFF207D8C53964BFFFF0C7FE802A697E1FFE07C691B78E9
-S3250001BE2080E100287C07000040820010808100307C0400004182005438E1000439010028D6
-S3250001BE408088000080A800049087000090A7000438A1000C38C1003080E600008106000456
-S3250001BE6090E5000091050004912100147C06037890C100184BFFFE7983E100007FE803A64B
-S3250001BE80382100204E8000207C0803789109000080C1002C80A100347CC62B9690C9000479
-S3250001BEA083E100007FE803A6382100204E8000207FE802A697E1FFE07C691B788101002818
-S3250001BEC07C0800004082001080A100307C05000041820054390100043881002880A40000D9
-S3250001BEE080C4000490A8000090C8000438C1000C38E10030810700008087000491060000E7
-S3250001BF00908600047C04037890810014912100184BFFFDDD83E100007FE803A63821002005
-S3250001BF204E8000207C0403789089000080E1002C80C100347FE733967FFF31D67CFF38503F
-S3250001BF4090E9000483E100007FE803A6382100204E800020808300047C0400004082001821
-S3250001BF6080A300007C0603787CA5305090A300004E800020808300047C0503787C8428505D
-S3250001BF8090830004810300003FE0FFFF63FFFFFF7FE84278910300004E8000207FE802A6D0
-S3250001BFA097E1FFD07C691B78906100348081003C7C84FE7080C100387C06200040820018F6
-S3250001BFC0810100447D08FE7080A100407C054000418200AC80E1003854E70FFE90E1002C92
-S3250001BFE07C07000041820010386100384BFFFF698121003480E1004054E70FFE90E1002809
-S3250001C0007C07000041820010386100404BFFFF498121003438E100043901003880880000EB
-S3250001C02080A800049087000090A7000438A1000C38C1004080E600008106000490E50000F7
-S3250001C04091050004912100147C06037890C100184BFFFC9D80E1002C808100287C072000D7
-S3250001C0604182000C806100344BFFFEED83E100007FE803A6382100304E8000208081003C78
-S3250001C080810100447C8443D69089000480E900047CE7FE7090E9000083E100007FE803A672
-S3250001C0A0382100304E8000207FE802A697E1FFD07C6A1B78906100348101003C7D08FE705D
-S3250001C0C080A100387C0540004082001880E100447CE7FE70808100407C043800418200A48F
-S3250001C0E080C1003854C60FFE90C1002C7C06000041820010386100384BFFFE5D814100345B
-S3250001C10080C1004054C60FFE7C06000041820010386100404BFFFE418141003438C10004C6
-S3250001C12038E10038810700008087000491060000908600043881000C38A1004080C5000040
-S3250001C14080E5000490C4000090E400047C07037890E10014914100184BFFFB9580C1002CEF
-S3250001C1607C0600004182000C806100344BFFFDE983E100007FE803A6382100304E80002037
-S3250001C1808101003C80E100447FE83BD67FFF39D67D1F4050910A000480CA00047CC6FE7067
-S3250001C1A090CA000083E100007FE803A6382100304E8000203821FFF081610020814100180F
-S3250001C1C02C0B0020418000387D46FE7090C300002C0B0040418000147D48FE70910300046D
-S3250001C1E0382100104E800020390BFFE07D48463091030004382100104E8000207C0B00000D
-S3250001C200418100189143000080E1001C90E30004382100104E8000207D465E3090C300007A
-S3250001C22038E000207CEB38507D47383080A1001C7CA55C307CE72B7890E3000438210010D4
-S3250001C2404E8000203821FFF081410020816100182C0A0020418000387C05037890A3000047
-S3250001C2602C0A0040418000147C05037890A30004382100104E800020390AFFE07D68443067
-S3250001C28091030004382100104E8000207C0A0000418100189163000080E1001C90E3000460
-S3250001C2A0382100104E8000207D66543090C3000038E000207CEA38507D67383080A1001CB7
-S3250001C2C07CA554307CE72B7890E30004382100104E8000203821FFF0814100208161001CB6
-S3250001C2E02C0A0020418000387C05037890A300042C0A0040418000147C05037890A300003B
-S3250001C300382100104E800020390AFFE07D68403091030000382100104E8000207C0A0000D7
-S3250001C320418100189163000480E1001890E30000382100104E8000207D66503090C3000427
-S3250001C34038E000207CEA38507D673C3080A100187CA550307CE72B7890E3000038210010A4
-S3250001C3604E80002080C1000880A100107CC6283890C300008081000C810100147C8440383E
-S3250001C380908300044E8000208101000880E100107D083B789103000080C1000C80A1001448
-S3250001C3A07CC62B7890C300044E80002080A10008812100107CA54A7890A300008101000CCD
-S3250001C3C080E100147D083A78910300044E8000208121000880E9000090E300008089000491
-S3250001C3E09083000480C9000438C6000190C90004808900047C0400004082001080A90000EE
-S3250001C40038A5000190A900004E8000208121000880C9000090C300008109000491030004A4
-S3250001C420810900047C08000040820010808900003884FFFF90890000808900043884FFFF6E
-S3250001C440908900044E800020812100087C6A1B7880A9000438A5000190A9000481090004D1
-S3250001C4607C0800004082001080890000388400019089000080890000908A000080C9000410
-S3250001C48090CA00044E800020812100087C6A1B7880E900047C0700004082001081090000DA
-S3250001C4A03908FFFF91090000810900043908FFFF9109000481090000910A000080A90004DF
-S3250001C4C090AA00044E8000207FE802A697E1FFD0814100388121003C90610034390100207C
-S3250001C4E08083000080A300049088000090A8000480A100402C0500064181029C4182023CBE
-S3250001C5002C05000341810164418201002C050001418200942C05000241820030480010D915
-S3250001C5208101003438A1002080C5000080E5000490C8000090E8000483E100007FE803A64F
-S3250001C540382100304E80002088AA000090A1002C7C07037890E1002838610020390100083C
-S3250001C5603881002880A4000080C4000490A8000090C8000438C1001038E1004481070000E5
-S3250001C5808087000491060000908600047D2803A64E80002180C100388101002499060000DD
-S3250001C5A04BFFFF8088AA00007CA5077490A1002C80E1002C54E70FFE90E100283861002059
-S3250001C5C038A1000838C1002880E600008106000490E500009105000439010010388100440B
-S3250001C5E080A4000080C4000490A8000090C800047D2803A64E8000218101003880A10024F8
-S3250001C60098A800004BFFFF1CA90A00009101002C80A1002C54A50FFE90A100283861002098
-S3250001C620390100083881002880A4000080C4000490A8000090C8000438C1001038E100446A
-S3250001C640810700008087000491060000908600047D2803A64E80002180C100388101002433
-S3250001C660B10600004BFFFEBC2C050004418200702C050005418200084BFFFEA4808A000099
-S3250001C6809081002C8081002C54840FFE908100283861002038E100083901002880880000C7
-S3250001C6A080A800049087000090A7000438A1001038C1004480E600008106000490E5000069
-S3250001C6C0910500047D2803A64E80002180A1003880E1002490E500004BFFFE48A10A0000EE
-S3250001C6E09101002C7C05037890A100283861002038C1000838E10028810700008087000492
-S3250001C70091060000908600043881001038A1004480C5000080E5000490C4000090E4000401
-S3250001C7207D2803A64E8000218081003880C10024B0C400004BFFFDEC808A00009081002C29
-S3250001C7407C040378908100283861002038A1000838C1002880E600008106000490E500007D
-S3250001C76091050004390100103881004480A4000080C4000490A8000090C800047D2803A683
-S3250001C7804E8000218101003880A1002490A800004BFFFD902C050007418200DC2C05000885
-S3250001C7A0418200D42C0500094182006C2C05000A418200084BFFFD6880CA000090C1002CF6
-S3250001C7C07C06037890C100283861002038E10008390100288088000080A800049087000055
-S3250001C7E090A7000438A1001038C1004480E600008106000490E50000910500047D2803A683
-S3250001C8004E80002180A1003880E1002490E500004BFFFD1080CA000090C1002C80C1002C44
-S3250001C82054C60FFE90C10028386100203881000838A1002880C5000080E5000490C40000D4
-S3250001C84090E4000438E10010390100448088000080A800049087000090A700047D2803A6DE
-S3250001C8604E80002180E1003880810024908700004BFFFCB0386100203881000880AA000053
-S3250001C88080CA000490A4000090C4000438C1001038E1004481070000808700049106000027
-S3250001C8A0908600047D2803A64E80002180C10038390100208088000080A8000490860000FD
-S3250001C8C090A600044BFFFC5C3821FFF081010018910300047C06037890C300003821001042
-S3250001C8E04E8000203821FFF081010018910300047D06FE7090C30000382100104E8000202E
-S3250001C9003821FFF080A1001890A300047C08037891030000382100104E8000203821FFF026
-S3250001C92080A1001890A300047CA8FE7091030000382100104E8000203821FFF080E1001842
-S3250001C94090E300047C05037890A30000382100104E8000203821FFF080E1001854E7801E39
-S3250001C9607CE88670910300047D06FE7090C30000382100104E8000203821FFF080A10018A2
-S3250001C98070A5FFFF90A300047C04037890830000382100104E8000203821FFF080C1001840
-S3250001C9A054C6C00E7CC7C67090E300047CE5FE7090A30000382100104E8000203821FFF0F7
-S3250001C9C080810018708400FF908300047C08037891030000382100104E8000203821FFF0FB
-S3250001C9E080810018708400FF5483C00E7C63C670382100104E80002080610008706300FF58
-S3250001CA004E8000203821FFF0808100187084FFFF5483801E7C638670382100104E8000202D
-S3250001CA20806100087063FFFF4E800020806100084E800020806100084E80002080610008B0
-S3250001CA404E800020806100084E800020810100087C0800004082001880A100047C0500007C
-S3250001CA604082000C7C0303784E800020386000014E80002080E10008808100107C07200055
-S3250001CA804082001480C100048101000C7C0640004182000C7C0303784E80002038600001D4
-S3250001CAA04E80002080A1000880E100107C0538004082001C8081000480C1000C7C0430004E
-S3250001CAC04082000C7C0303784E800020386000014E8000208101000480A1000C7C082800B3
-S3250001CAE04180002480E100048081000C7C0720004082001C80C10008810100107C0640407A
-S3250001CB004080000C386000014E8000207C0303784E80002080A1000480E1000C7C05380088
-S3250001CB20418000248081000480C1000C7C0430004082001C8101000880A100107C08284082
-S3250001CB404181000C386000014E8000207C0303784E80002080E100048081000C7C0720007C
-S3250001CB604181002480C100048101000C7C0640004082001C80A1000880E100107C053840C2
-S3250001CB804081000C386000014E8000207C0303784E8000208081000480C1000C7C04300050
-S3250001CBA0418100248101000480A1000C7C0828004082001C80E10008808100107C072040EE
-S3250001CBC04180000C386000014E8000207C0303784E80002080C100048101000C7C0640403D
-S3250001CBE04180002480A1000480E1000C7C0538004082001C8081000880C100107C043040D6
-S3250001CC004080000C386000014E8000207C0303784E8000208101000480A1000C7C08284033
-S3250001CC204180002480E100048081000C7C0720004082001C80C10008810100107C06404038
-S3250001CC404181000C386000014E8000207C0303784E80002080A1000480E1000C7C05384005
-S3250001CC60418100248081000480C1000C7C0430004082001C8101000880A100107C08284040
-S3250001CC804081000C386000014E8000207C0303784E80002080E100048081000C7C072040FC
-S3250001CCA04181002480C100048101000C7C0640004082001C80A1000880E100107C05384081
-S3250001CCC04180000C386000014E8000207C0303784E8000208121000C814100088081001484
-S3250001CCE080A100107CC921D67CE920167D0451D67CE742147D0549D67CE7421490C3000413
-S3250001CD0090E300004E8000208881000B3863FFFF8CC300017C062000418200107C060000B7
-S3250001CD204082FFF07C0303784E800020906100048081000C7C0400004081007C80A100086B
-S3250001CD4054A5063E50A5442E50A5801E7CA62B787CA72B787CA82B782C04001040810050F2
-S3250001CD607069000741820018212900087D2103A67CA01D2A7C634A147C8920507C892671A7
-S3250001CD804081002C7D2903A690A300003943000890C3000490EA0000386A0008910A00047F
-S3250001CDA04200FFE85484073F4182000C7C8103A67CA01D2A806100044E8000209061000485
-S3250001CDC08121000C7C6A1B787C090000418200A841800184816100082C0900104081008C73
-S3250001CDE07DAB4A147D8A4A147C0A5840418100CC7D67527870E7000340820084714700038C
-S3250001CE004182002020E700047D2748507CE103A67E005C2A7D6B3A147E00552A7D4A3A148F
-S3250001CE207D2E2671408100447DC903A6396BFFFC394AFFFC860B0004960A0004862B0004AA
-S3250001CE40962A0004860B0004960A0004862B0004962A00044200FFE05529073F4182001895
-S3250001CE60396B0004394A00047D2103A67E005C2A7E00552A806100044E8000207D2E26711F
-S3250001CE80408100247DC903A67E0B84AA396B00107E0A85AA394A00104200FFF05529073F0D
-S3250001CEA04182FFD47D2103A67E005C2A7E00552A806100044E8000202C090004418000843C
-S3250001CEC07DA7627870E700034082007871A70003418200188E0DFFFF9E0CFFFF3929FFFF22
-S3250001CEE071A700034082FFF07D2E2671408100347DC903A6860DFFFC960CFFFC862DFFFC60
-S3250001CF00962CFFFC860DFFFC960CFFFC862DFFFC962CFFFC4200FFE05529073F4182FF58B8
-S3250001CF207D2E16714081001C7DC903A6860DFFFC960CFFFC4200FFF8552907BF4182FF384A
-S3250001CF407C0D58404081FF308E0DFFFF9E0CFFFF4BFFFFF090000000806100044E800020DC
-S3250001CF604BFFFE5C3821FFD08281003881C1003C7C731B787C6B1B787C1203787C0D03781C
-S3250001CF807C1003787C0F0378888B00007C8407742C04000C41810268418202502C04000939
-S3250001CFA0418202482C04000A418202402C04000B4182023888CB00007CC607742C06002D77
-S3250001CFC04182020888EB00007CE707742C07002B418201F87C0E00004082001888AB00007B
-S3250001CFE07CA507742C050030418201B039C0000A2C0E0002418000782C0E002441810070B1
-S3250001D0002C0E00104082001488EB00007CE707742C070030418200F07C0D037838A0FFFFA8
-S3250001D0207E25739688CB00007CC607747CCA33787DCC73782C0600304180000C2C0A00396A
-S3250001D040408100BC2C0A00614180000C2C0A007A408100A42C0A00414180000C2C0A005AFF
-S3250001D0604081008C7C0C7000418000547C100000408200087E6B9B787C14000041820008A2
-S3250001D080917400007C0F0000418200103860FFFF382100304E8000207C12000041820014B4
-S3250001D0A07C0303787C6D1850382100304E8000207DA36B78382100304E8000207C0D8840DC
-S3250001D0C04081000839E000017CAD71D67D4562147C0A68404080000839E000017D4D537819
-S3250001D0E0396B00013A1000014BFFFF3C398AFFC94BFFFF74398AFFA94BFFFF6C398AFFD0BA
-S3250001D1004BFFFF64890B00017D0807742C08007841820018888B00017C8407742C04005828
-S3250001D120418200084BFFFEF488AB00027CA507742C0500304180001C88CB00027CC60774C0
-S3250001D1402C0600394181000C396B00024BFFFECC88EB00027CE707742C0700614180001419
-S3250001D160890B00027D0807742C0800664081FFDC888B00027C8407742C0400414180FE9C80
-S3250001D18088AB00027CA507742C0500464181FE8C396B00024BFFFE8439C00008890B0001EC
-S3250001D1A07D0807742C08007841820018888B00017C8407742C040058418200084BFFFE3483
-S3250001D1C039C000104BFFFE2C7D685B78396B0001890800007D0807742C08002D4082FDF8C5
-S3250001D1E03A4000014BFFFDF0396B0001888B00007C8407742C04000C4081FDA02C04000D6C
-S3250001D2004182FFE82C0400204182FFE04BFFFDA87FE802A697E1FFD8814100309061002C0F
-S3250001D22088AA00007CA5077490A100207C0500004082001483E100007FE803A6382100287C
-S3250001D2404E8000207D435378480001819061001C8061002C80A1002090A100084BFFFAADFF
-S3250001D2607C691B787C0900004182005C7D234B789121002480810030908100088101001C6A
-S3250001D2809101000C480000CD812100247C030000408200187D234B7883E100007FE803A6DE
-S3250001D2A0382100284E8000203869000180C1002090C100084BFFFA557C691B787C09000006
-S3250001D2C04082FFAC7C03037883E100007FE803A6382100284E8000207FE802A697E1FFE88F
-S3250001D2E07C691B7880A100207C050000408200247D234B787C080378910100084BFFFA0DBA
-S3250001D30083E100007FE803A6382100184E8000207C040378908100147D234B78810100200E
-S3250001D320910100084BFFF9E57C0300004182001039230001906100144BFFFFE08061001452
-S3250001D34083E100007FE803A6382100184E8000203821FFF081A100188141001C7C6C1B7818
-S3250001D3607C0A0000408100587D896378398C0001892900007D2907747DAB6B7839AD00019B
-S3250001D380896B00007D6B0774394AFFFF7C095800418200247C095840408100103860000163
-S3250001D3A0382100104E8000203860FFFF382100104E8000207C0900004082FFA87C0303783A
-S3250001D3C0382100104E8000207FE802A697E1FFF0906100147C07037890E100084BFFF92D8D
-S3250001D3E0810100147C68185083E100007FE803A6382100104E8000207FE802A697E1FFE013
-S3250001D400814100287C691B789061001C7D234B789121002491410028914100087C0803788A
-S3250001D4209101000C3900271091010010480001617C0300004082001880A100243925271058
-S3250001D44081010028394827104BFFFFC48061001C83E100007FE803A6382100204E8000207E
-S3250001D4603821FFF0818100187C6B1B787D695B78396B0001892900007D2907747D8A6378B6
-S3250001D480398C0001894A00007D4A07747C095000418200247C09504040810010386000016F
-S3250001D4A0382100104E8000203860FFFF382100104E8000207C0900004082FFB47C0303782D
-S3250001D4C0382100104E8000203821FFE8812100247C6D1B78818100207C0900404081005074
-S3250001D4E07DAB6B7839AD0001896B00007D8A6378398C0001894A00007C0B50004182002406
-S3250001D5007C0B50404081001038600001382100184E8000203860FFFF382100184E8000202F
-S3250001D5203929FFFF7C0900404181FFB87C030378382100184E8000203821FFF08121001CE7
-S3250001D5407C6A1B7880E1001870EB00FF7C090040408100307D475378394A000188E7000040
-S3250001D5607C07580040820010386AFFFF382100104E8000203929FFFF7C0900404181FFD842
-S3250001D5807C030378382100104E8000203821FFF0812100207C6A1B78816100188081001C99
-S3250001D5A0708C00FF7C090040408100407D465378394A00017D645B78396B0001888400002C
-S3250001D5C0988600005484063E7C046000408200107D435378382100104E8000203929FFFF16
-S3250001D5E07C0900404181FFC87C030378382100104E8000207C040378808400007C04000006
-S3150001D600418200084BFFFFF04E8000200000000021
-S3250001D61000810E02001415F0001403E80000000000146530000000010000000000000000A0
-S3250001D6300000000000000000FFFFFFFF0000001E0000001D0000001C0000001B0000000065
-S3250001D6500000000000000000000000000000000000000000000000000000000000000000B3
-S3250001D670000000000000000000000000000000000000000000000000000000000000000093
-S3250001D690FFFFFFFF00000A0000000A2000000A4000000A6000140104000000000000000076
-S3250001D6B0000000000000000000000000000000012A2A2A000000000023706C616E392E6936
-S3250001D6D06E690A00000000005250587369676E61747572653D312E300A4E414D453D71627F
-S3250001D6F0727063670A53544152543D46464332303130300A56455253494F4E3D312E310AC9
-S3250001D710000000000001000000000401080205030C06060909070710100000000000000082
-S3250001D7306672656562007167657400000000000000141BAF0000000000000000000000003F
-S3250001D7500000000000000000000000000000000000000000000000000000000000000000B2
-S3250001D770000000000000000000000000000000000000000000000000000000000000000092
-S3250001D79000000000000000000000000000000000626F6F74006469736B00626F6F740075EA
-S3250001D7B06172743A207374617274207472616E736D697373696F6E0A00756172743A2074A5
-S3250001D7D0696D656F75740A006E007900000000000000000000000000001403200000000077
-S3250001D7F0000000000000000000000000000000000000000000000000000000000000000012
-S3250001D8100000000000000000000000000000000000000000000000000000000000000000F1
-S3250001D8300000000000000000FFC206F000000000000000000000000000000000000000001A
-S3250001D8500000000000000000000000000000000000000000000000000000000000000000B1
-S3250001D87000000000000000000000000000000000000000000000000000141A00FFC26E38FC
-S3250001D89000141A04FFC26E3800000000000000006D6170667265653A2025733A206C6F735E
-S3250001D8B0696E672030782575582C2025640A000000141A9300141AA700141AB300141AC312
-S3250001D8D0000000000014054000000000000000006E6577616C61726D000000000000000081
-S3250001D8F00000000000000000F1A55A1FFFC2363000000000000000000000000000000000DB
-S3250001D9100000000000000000FFFFFFFF0000000000000004000000080000000C00000000DC
-S3250001D9306275666665722064657363726970746F7273006264616C6C6F63000000000000B3
-S3250001D95000141A810000000000141A860000000100141A8C00000002000000000000000090
-S3250001D970FFFFFFFFFFFF000000000000000000000000000000000000000000000000000096
-S3250001D9900000000000000000000000000000000000000000000000000000000013880000D5
-S3250001D9B0FFFFFFFFFA203C00FA203D00FA203E00FA203F000000000000141FD70014203B7D
-S3250001D9D06932632073657475702E2E2E0A004932432325780A0000000000000B00000000BA
-S3250001D9F0000000000000000000140E4000000000000000200000000000000000000000008E
-S3250001DA10000004000000000E0000000000000000000004000000000E0000000000000000CB
-S3250001DA3041F0000000000000001407460014074C0014075100140754001407580014075B12
-S3250001DA500014075E0014076200140766001407690014076C0014076F001407720014077586
-S3250001DA70001407780014077B0014077E0014078100140784001407880014078C001407909D
-S3250001DA9000140794001407980014079C001407A0001407A4001407A8001407AC001407B087
-S3250001DAB0001407B4001407B8001407BC001407C0001407C4001407C8001407CC001407D067
-S3250001DAD0001407D4001407D8FFC24714FFC2474CFFC24798FFC247BCFFC247C4FFC247CCD9
-S3250001DAF0FFC247F0FFC24830FFC24838FFC2485CFFC2488C000000000000000000000000A3
-S3250001DB100000000000000000000000000000000000000000000000000000000000000000EE
-S3250001DB300000000000000000000000000000000000000000000000000000000000000000CE
-S3250001DB507072656D617475726520454F460A002E00626164206D61676963203078256C7591
-S3250001DB7078206E6F74206120706C616E20392065786563757461626C65210A002564002BDF
-S3250001DB9025644025382E386C7578002B25640A7374617274206174203078256C75780A0058
-S3250001DBB000000000000000000000000000000000000000000000000000000000000000004E
-S3250001DBD000000000000A000000000000000000000000000000000000000000000000000024
-S3250001DBF0000000000000000000000000000000000000000000000000090000000000000005
-S3250001DC100000000102000000030000000400000500000006000700000800000000000000C9
-S3250001DC30726573657276656420300073797374656D207265736574006D616368696E652040
-S3250001DC50636865636B00646174612061636365737300696E737472756374696F6E206163DD
-S3250001DC70636573730065787465726E616C20696E7465727275707400616C69676E6D656E24
-S3250001DC90740070726F6772616D20657863657074696F6E00666C6F6174696E672D706F6949
-S3250001DCB06E7420756E617661696C61626C650064656372656D656E74657200726573657218
-S3250001DCD0766564204100726573657276656420420073797374656D2063616C6C0074726123
-S3250001DCF06365207472617000666C6F6174696E6720706F696E742061737369737400726542
-S3250001DD10736572766564204600736F66747761726520656D756C6174696F6E0049544C4279
-S3250001DD30206D6973730044544C42206D6973730049544C42206572726F720044544C422033
-S3250001DD506572726F72004341555345005352523100504300474F4B004C52004352005845A5
-S3250001DD7052004354520052300052310052320052330052340052350052360052370052389B
-S3250001DD900052390052313000523131005231320052313300523134005231350052313600E7
-S3250001DDB052313700523138005231390052323000523231005232320052323300523234008D
-S3250001DDD0523235005232360052323700523238005232390052333000523331007365746866
-S3250001DDF0766563006F7574206F6620696E746572727570742068616E646C6572730025736B
-S3250001DE1009252E386C757809257309252E386C75780A00657863657074696F6E2F696E741D
-S3250001DE30657272757074202325780A00657863657074696F6E2025730A005E5020746F20DD
-S3250001DE5072657365740A00005573696E6720666C61736820636F6E66696775726174696F20
-S3250001DE706E0A000A002573256400747970653D00706F72743D006972713D006D656D3D00E2
-S3250001DE9073697A653D0065613D00000000000000676574636C75737420402025640A00678B
-S3250001DEB06574636C75737420256420696E2063616368650A00676574636C75737420616439
-S3250001DED064722025640A0063616E2774207365656B20626C6F636B0A0063616E2774207279
-S3250001DEF065616420626C6F636B0A00676574636C75737420256420726561640A0066617497
-S3250001DF1077616C6B2025640A006765746661740066617477616C6B202564202D3E20256446
-S3250001DF300A0066696C65616464722025382E38732025640A0066696C656164647220256498
-S3250001DF50202D3E2025640A0066696C6561646472202564202D3E2025640A0077616C6B6932
-S3250001DF706E67206E6F6E2D6469726563746F7279210A00636F6D706172696E6720746F203A
-S3250001DF9025382E38732E25332E33730A0025382E38732E25332E33732069732061204C4116
-S3250001DFB042454C0A0063616E2774207265616420626F6F7420626C6F636B0A006E6F74206A
-S3250001DFD0444F530A006E6F20646F732066696C652073797374656D0A006D616769633A200D
-S3250001DFF0307825322E327820307825322E327820307825322E32780A0076657273696F6E35
-S3250001E0103A202225382E3873220A007365637473697A653A2025640A00616C6C6F637369CD
-S3250001E0307A653A2025640A006E72657372763A2025640A006E666174733A2025640A0072F5
-S3250001E0506F6F7473697A653A2025640A00766F6C73697A653A2025640A006D656469616452
-S3250001E0706573633A20307825322E32780A0066617473697A653A2025640A0074726B736903
-S3250001E0907A653A2025640A006E68656164733A2025640A006E68696464656E3A2025640A76
-S3250001E0B000626967766F6C73697A653A2025640A0064726976656E6F3A2025640A00726563
-S3250001E0D0736572766564303A20307825322E32780A00626F6F747369673A20307825322EB7
-S3250001E0F032780A00766F6C69643A20307825382E38780A006C6162656C3A20222531312EBF
-S3250001E110313173220A006E616D6520636F6D706F6E656E7420746F6F206C6F6E670A0065A2
-S3250001E13072726F722077616C6B696E6720746F2025730A002573206E6F7420666F756E64EC
-S3250001E1500A00666F756E642025382E38732E25332E3373206174747220307825757820738A
-S3250001E17074617274203078256C7578206C656E2025640A00626164206D6167696320307865
-S3250001E190256C7578206E6F74206120706C616E20392065786563757461626C65210A002B3C
-S3250001E1B02564002B2564002B25640A7374617274206174203078256C75780A002E006E61DD
-S3250001E1D06D652069732025382E38732025332E33730A0000000000002E007A71733A206E5A
-S3250001E1F06F7420706F77657250432065786563757461626C650A0074657874007A71733A9C
-S3250001E21020666F726D6174206572726F720A0064617461007A71733A20666F726D617420EF
-S3250001E2306572726F720A000A73717565657A6564206B65726E656C3A20636865636B737542
-S3250001E2506D206572726F723A2025382E386C7578206E6565642025382E386C75780A007503
-S3250001E2706E7061636B2025732025382E386C757820256C75643A00202A2A73697A6520650E
-S3250001E29072726F720A000A007A71733A20636F72727570742073717565657A65642064615C
-S3250001E2B074612073747265616D0A00205425640025642025382E386C75782025382E386CAB
-S3250001E2D075780A0000000000666C6173683A2062616420636865636B73756D0A00666C61F1
-S3250001E2F073683A20666C617368206E6F742070726573656E74206F72206E6F7420656E616C
-S3250001E310626C65640A00636F6E66202325382E386C75783A20232578202325362E366C7543
-S3250001E330780A00666C6173683A20666F756E6420636F6E6669672025382E386C75782825A1
-S3250001E35064293A0A25730A00666C6173683A206E6F20636F6E6669670A00666C6173682020
-S3250001E370636F6E6669672025382E386C7578282564293A0A25730A00666C6173683A207339
-S3250001E390717565657A656420706F7765727063206B65726E656C20696E7374616C6C6564D2
-S3250001E3B00A00666C6173683A20756E73717565657A656420706F7765727063206B65726E9B
-S3250001E3D0656C20696E7374616C6C65640A00666C6173683A206E6F20706F776572706320E6
-S3250001E3F06B65726E656C20696E20466C6173680A00746578743A2025382E386C7578203CDF
-S3250001E4102D2025382E386C7578205B256C645D0A00646174613A2025382E386C7578203C39
-S3250001E4302D2025382E386C7578205B256C645D0A00656E7472793D3078256C75780A0000E6
-S3250001E450907070F0F0F07000F0888888F8707070E0E0E0E0E09070F070F870F0F870F0882D
-S3250001E470000000000000000000000000000000000000000000000000000000000000000085
-S3250001E490000000000000000000000000000000000000000000000000000000000000000065
-S3250001E4B000000000000000000000000000000000000000000000000000000000000000E065
-S3250001E4D0D0808080808088008888C888808888889090909090D0808080808080808888881D
-S3250001E4F000000000080000000C3000000000000600000000000000000000000000000000BB
-S3250001E5100000000000000000000000000000000000000000000000000000003CC03C0000AC
-S3250001E5300000600006001E00601818607800000000000000000000000000001C18380090DC
-S3250001E550B06060E0E0E0F800F088A888808080809090909090B060E0808060E080808888E4
-S3250001E570001824283E70701818180000000000063C183C3C1C3E3C7E3C3C00000200403CDE
-S3250001E5903C187C1E787E7E1E663C7C666066623C7C3C7C3C7E6266C266667E30C00C10002E
-S3250001E5B008006000060030006018186018000000000000001000000000000030180C0090AA
-S3250001E5D0901010808080881888F8A888E0807070E0E0E0E0E090108070E01080E098F08814
-S3250001E5F0001824286ADAD818181810000000000C663866662C3E667E6666000006006066D0
-S3250001E610421866326C606032661818646066722466246666186262DA62620630600C380093
-S3250001E63010006000060030006000006018000000000000003000000000000030180C00E0E1
-S3250001E65000E0E0F0F0F000188888985080880808201C1C1C1C00E0F00080E0F08088888823
-S3250001E6700018242868DAD808300C54180000000C665806062C206002666618180CFE300695
-S3250001E6909E2C6660666060606618186C6066726666666660186262DA36660C30600C2800F9
-S3250001E6B0103C6C3C3E3C7E3E6C78786618D46C3C6C3E763C7E6666C266667E1818180000C9
-S3250001E6D04418000018241C24F08888208070F0F020202020201C243E1CF8241C8070887001
-S3250001E6F00018247C78745008300C381800000018661806064C2060067666181818FE180CC1
-S3250001E710B62C66606660606066181868607E5A6666666470186266DA34340C30300C6C0072
-S3250001E73018667666666630667618186418FE766676663666306662DA626206081810323C58
-S3250001E75044247C7C2434204200000000000000002020202020222408220024200000000034
-S3250001E770001800283C287610300CEE7E00FE001866180C184C3C7C0C3C3E000030000C181A
-S3250001E790B62C7C60667C7C6E7E181878605A5A666466783C186234DA18341830300C44001E
-S3250001E7B018066660666630666618186818D6666666663860306662DA34620C30180C5A209E
-S3250001E7D044241010242C20420E3E103E3E3C1C3E3C1C1C1C1C3E1C083E2224180E0E0E0E98
-S3250001E7F00008007C1E5CDC00300C387E00FE0030661818067E0666186E06000018001818AE
-S3250001E810B67E6660666060666618186C605A4E6678666C0E1862346C2C183030180C44006D
-S3250001E830003E6660667E30666618187818D666666666303C306634DA1834180818104C3887
-S3250001E8503C18101018241C4211081008202222080000000000220408223618041111111110
-S3250001E8700000002816B6CC00300C541800000030661830067E066618660600000CFE30008D
-S3250001E8909A466660666060666618186C605A4E66606666061862346C6C183030180C00006B
-S3250001E8B000666660666030666618186C18D66666666630063066346C2C34301818180020CD
-S3250001E8D000091010000E094210081008202222080F06060F0A09041E002A0E3810101010F4
-S3250001E8F00018002856B6CC00300C10181800186066187E660C6666306666181806FE601813
-S3250001E910404666326C60603666181866605A4624602466661834186C461860300C0C00001A
-S3250001E930006E66666E66306E6618186618D66666666E3066306E186C46186030180C003C84
-S3250001E950080909091F110AFF0E081008382C2208080209010A0A0911092209070E0E0E0ED3
-S3250001E970001800287C1C760018180000180018603C7E7E3C0C3C3C303C3C18180200401848
-S3250001E9903E467C1E787E601E663C18667E42463C603C663C1818186C66187E300C0C000036
-S3250001E9B000367C3C363C7C36667E18667ED6663C7C367C3C1E36186C66187E30180C00083C
-S3250001E9D0080F060604110C1801081008202222080E0202030A0C0D1E0D220E080101010198
-S3250001E9F0000000001000000018180000080000C000000000000000000000000800000000F0
-S3250001EA1000000000000000000000180000000000000C00000000000000000030060C00FE7B
-S3250001EA300000000000000006000018000000000060060000000000000010001C18380008B7
-S3250001EA5008090606040E0A1811081F0820221C3E080204010F0A0B110B22090811111111AC
-S3250001EA7000000000000000000C300000080000C00000000000000000000000080000000073
-S3250001EA900000000000000000000070000000000000060000000000000000003C063C00006B
-S3250001EAB0000000000000006600001800000000006006000000000000003000000000000823
-S3250001EAD00F090909040309000E000000000000000F0F0F0F0209091E09000F070E0E0E0E12
-S3250001EAF00000000000000000000000001000000000000000000000000000001000000000DF
-S3250001EB100000000000000000000000000000000000000000000000000000000000000000DE
-S3250001EB30000000000000003C00007000000000006006000000000000006000000000000F3D
-S3250001EB50636F6E736F6C65006C63640073637265656E006C63640062617564005E70002536
-S3250001EB70735B64656661756C743D3D25735D3A200025733A20000A006C696E6520746F6FEC
-S3250001EB90206C6F6E670A0070616E69633A20000A0000000000000000001406200014062B96
-S3250001EBB000140638001406460014065200140665001406780014068200140694001406AFFC
-S3250001EBD0001406BB001406C6001406D1001406DD001406E8001406FE001407090014071C12
-S3250001EBF000140726001407300014073B000000000000000E000800000008000E00080000E8
-S3250001EC100010000E000800000018000E000800000020000E000800000028000E0008000015
-S3250001EC300030000E000800000038000E000800000040000E000800000048000E0008000075
-S3250001EC500050000E000800000058000E000800000060000E000800000068000E00080000D5
-S3250001EC700070000E000800000078000E000800000080000E000800000088000E0008000035
-S3250001EC900090000E000800000098000E0008000000A0000E0008000000A8000E0008000095
-S3250001ECB000B0000E0008000000B8000E0008000000C0000E0008000000C8000E00080000F5
-S3250001ECD000D0000E0008000000D8000E0008000000E0000E0008000000E8000E0008000055
-S3250001ECF000F0000E0008000000F8000E0008000001000000000800000108020B00080000C2
-S3250001ED1001100206000800000118020B000800000120010C000800000128020B0008000019
-S3250001ED300130020B0008000001380207000800000140010D000800000148010D0008000076
-S3250001ED500150030A000800000158040A000800000160090E000800000168060800080000C8
-S3250001ED700170090B000800000178010D000800000180020B000800000188020B000800002C
-S3250001ED900190020B000800000198020B0008000001A0020B0008000001A8020B0008000094
-S3250001EDB001B0020B0008000001B8020B0008000001C0020B0008000001C8020B00080000F4
-S3250001EDD001D0040B0008000001D8040E0008000001E0020B0008000001E8040A000800004C
-S3250001EDF001F0020B0008000001F8020B000800000200020B000800000208020B00080000B2
-S3250001EE100210020B000800000218020B000800000220020B000800000228020B000800000F
-S3250001EE300230020B000800000238020B000800000240020B000800000248020B000800006F
-S3250001EE500250020D000800000258020B000800000260020B000800000268020B00080000CD
-S3250001EE700270020B000800000278020B000800000280020B000800000288020D000800002D
-S3250001EE900290020B000800000298020B0008000002A0020B0008000002A8020B000800008F
-S3250001EEB002B0020B0008000002B8020B0008000002C0020B0008000002C8020B00080000EF
-S3250001EED002D0020B0008000002D8010D0008000002E0010D0008000002E8010D000800004C
-S3250001EEF002F002080008000002F80B0C0008000003000207000800000308040B00080000A8
-S3250001EF100310010B000800000318040B000800000320010B000800000328040B0008000008
-S3250001EF300330010B000800000338040E000800000340010B000800000348010B0008000068
-S3250001EF500350010E000800000358010B000800000360010B000800000368040B00080000C8
-S3250001EF700370040B000800000378040B000800000380040E000800000388040E000800001C
-S3250001EF900390040B000800000398040B0008000003A0020B0008000003A8040B0008000084
-S3250001EFB003B0040B0008000003B8040B0008000003C0040B0008000003C8040E00080000DF
-S3250001EFD003D0040B0008000003D8010C0008000003E0010C0008000003E8010C0008000048
-S3250001EFF003F005080008000003F8000E000800000400000E000800000000000000000000C7
-S3250001F010534343005343433200657468657225643A2025733A20706F7274203078256C7575
-S3250001F0305820697271202564002061646472203078256C7558002073697A65203078256C37
-S3250001F0507558003A002025322E327558000A00657468657225643A207478207175657565B8
-S3250001F0702066756C6C0A0000666C6173680046006574686572006500617461006864006861
-S3250001F090006175746F006C6F63616C006D616E75616C00696E6665726E6F2F696E666572E3
-S3250001F0B06E6F2E696E6900696E6665726E6F2E696E6900706C616E392F706C616E392E6901
-S3250001F0D06E6900706C616E392E696E69002100002573212564006469736B002573212564A0
-S3250001F0F0212573006469736B00696D706300257321256421257300626F6F74006469736B92
-S3250001F11000646F73006469736B00646F7320696E6974206661696C65640A00707265646132
-S3250001F130776E0A006461776E0A006F7074696F6E733D232575780A00466C61736820626FAE
-S3250001F1506F740A00626F6F7466696C650042616420626F6F7466696C652073796E74617815
-S3250001F1703A2025730A0043616E6E6F7420616363657373206465766963653A2025730A00FB
-S3250001F190426F6F7420646576696365733A00202573212564002025732125640020257321EA
-S3250001F1B02564000A00626F6F742066726F6D00706879736963616C206D656D6F727900699E
-S3250001F1D0616C6C6F63006672656500000000000045544845522E5343432325643A20736310
-S3250001F1F06365203D2030782575580A007E0040006E6F207072657365742045746865722089
-S3250001F210616464726573730A00303031303862663132393030006574686572204D41432001
-S3250001F2306164647265737300696E76616C6964204D414320616464726573730A00000000E9
-S3250001F2500A746674703A206572726F72282564293A2025730A0069702063686B73756D20D1
-S3250001F2706572726F720A0069702062616420766572732F686C656E0A007564702063686BC4
-S3250001F29073756D206572726F72206373756D202325346C7578206C656E2025640A00756400
-S3250001F2B0703A207061636B657420746F6F206269670A002573006F637465740074667470B2
-S3250001F2D06F70656E3A206572726F7220282564293A2025730A00746674706F70656E3A2021
-S3250001F2F0626C6F636B206572726F723A2025640A00626C6F636B206572726F720074667412
-S3250001F310706F70656E3A206661696C656420746F20636F6E6E65637420746F207365727605
-S3250001F33065720A0074667470726561643A20256420213D2025640A0073686F727420726540
-S3250001F3506164003F0074667470726561643A20626C6F636B206572726F723A2025642C205A
-S3250001F37065787065637465642025640A00626C6F636B206572726F7200696E76616C696435
-S3250001F3902063746C726E6F2025640A00626F6F74702074696D6564206F75740A0025732060
-S3250001F3B0002825642E25642E25642E2564212564293A2025730A00626164206D6167696349
-S3250001F3D0206E756D626572006C6F61644025382E386C75783A20002564002B2564006F6B00
-S3250001F3F0002B25643D25640A00656E7472793A203078256C75780A000000000000141A6820
-S3250001F41000000008FFC27AE40000000000000000000000000000000000141A6E0000000012
-S3250001F43000000000000000000000000200141A7000000004FFC26068000000000000000088
-S3250001F45000000000000000000000000000141A7600000000000000000000000300141A7848
-S3250001F470000000130000000000000000000000000000000000141A7C00141A7F000000000B
-S3250001F4900000000000000000FFFFFFFF000000000000000000000000000000000000000059
-S3250001F4B0000000000000000000000000000000000000000000000000496E6665726E6F2044
-S3250001F4D0626F6F7473747261700A005056523A20004D5043363031004D5043363033004D9E
-S3250001F4F05043363034004D504336303365004D5043363033652D7637004D5043387878002A
-S3250001F510506F77657250432076657273696F6E20232578002C207265766973696F6E202330
-S3250001F530256C75780A00494D4D523A20004D50433836302F383231004D5043383233004D8B
-S3250001F55050433832334100547970652023256C7578002C206D61736B2023256C75780A00FD
-S3250001F5706F7074696F6E733A2023256C75780A00626373723A2025382E386C75780A0050E9
-S3250001F5904C505243523D25382E386C757820534343523D25382E386C75780A00256C756460
-S3250001F5B0204D487A2073797374656D0A000A004252303D25382E386C7578204F52303D25BC
-S3250001F5D0382E386C75780A004D505450523D25382E386C75780A006574686572303D7479AB
-S3250001F5F070653D53434320706F72743D312065613D3030313065633030303035310D0A7657
-S3250001F610676173697A653D3634307834383078380D0A6B65726E656C70657263656E743DEF
-S3250001F63034300D0A636F6E736F6C653D300D0A626175643D393630300D0A006574686572EA
-S3250001F650303D747970653D53434320706F72743D322065613D303031306563303030303559
-S3250001F670310D0A76676173697A653D3634307834383078380D0A6B65726E656C7065726355
-S3250001F690656E743D34300D0A636F6E736F6C653D300D0A626175643D393630300D0A0055C9
-S3250001F6B073696E672064656661756C7420636F6E66696775726174696F6E0A00414D4432D7
-S3250001F6D039463078300053434300454100693263206661696C65640A00656570726F6D3A0E
-S3250001F6F00A002025322E3275785B25635D000A00CFFFCC240FFFCC040CAFCC0403AFCC082E
-S3250001F7103FBFCC27FFFFCC25FFFFCC25FFFFCC25CFFFCC240FFFCC040CAFCC8403AFCC8867
-S3250001F7303FBFCC27FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC2538
-S3250001F750FFFFCC25FFFFCC25FFFFCC25FFFFCC25CFFFCC240FFFCC040CFFCC0403FFCC0091
-S3250001F7703FFFCC27FFFFCC25FFFFCC25FFFFCC25CFFFCC240FFFCC040CFFCC8403FFCC842B
-S3250001F7900CFFCC0033FFCC27FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25BC
-S3250001F7B0FFFFCC25FFFFCC25FFFFCC25FFFFCC25C0FFCC2403FFCC240FFFCC240FFFCC24D9
-S3250001F7D03FFFCC27FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC2558
-S3150001F7F0FFFFCC25FFFFCC25FFFFCC25FFFFCC2546
-S700000100FE
--- a/os/boot/rpcg/gbitbltclip.c
+++ /dev/null
@@ -1,52 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <libg.h>
-#include <gnot.h>
-
-void
-gbitbltclip(void *vp)
-{
- int dx, dy;
- int i;
- struct{
- GBitmap *dm;
- Point p;
- GBitmap *sm;
- Rectangle r;
- Fcode f;
- }*bp;
-
- bp = vp;
- dx = Dx(bp->r);
- dy = Dy(bp->r);
- if(bp->p.x < bp->dm->clipr.min.x){
- i = bp->dm->clipr.min.x-bp->p.x;
- bp->r.min.x += i;
- bp->p.x += i;
- dx -= i;
- }
- if(bp->p.y < bp->dm->clipr.min.y){
- i = bp->dm->clipr.min.y-bp->p.y;
- bp->r.min.y += i;
- bp->p.y += i;
- dy -= i;
- }
- if(bp->p.x+dx > bp->dm->clipr.max.x)
- bp->r.max.x -= bp->p.x+dx-bp->dm->clipr.max.x;
- if(bp->p.y+dy > bp->dm->clipr.max.y)
- bp->r.max.y -= bp->p.y+dy-bp->dm->clipr.max.y;
- if(bp->r.min.x < bp->sm->clipr.min.x){
- i = bp->sm->clipr.min.x-bp->r.min.x;
- bp->p.x += i;
- bp->r.min.x += i;
- }
- if(bp->r.min.y < bp->sm->clipr.min.y){
- i = bp->sm->clipr.min.y-bp->r.min.y;
- bp->p.y += i;
- bp->r.min.y += i;
- }
- if(bp->r.max.x > bp->sm->clipr.max.x)
- bp->r.max.x = bp->sm->clipr.max.x;
- if(bp->r.max.y > bp->sm->clipr.max.y)
- bp->r.max.y = bp->sm->clipr.max.y;
-}
--- a/os/boot/rpcg/gnot.h
+++ /dev/null
@@ -1,71 +1,0 @@
-
-extern void *bbmalloc(int);
-extern void bbfree(void *, int);
-extern int bbonstack(void);
-extern void bbexec(void(*)(void), int, int);
-
-/*
- * Graphics types
- */
-
-typedef struct GBitmap GBitmap;
-typedef struct GFont GFont;
-typedef struct GSubfont GSubfont;
-typedef struct GCacheinfo GCacheinfo;
-
-struct GBitmap
-{
- ulong *base; /* pointer to start of data */
- long zero; /* base+zero=&word containing (0,0) */
- ulong width; /* width in 32 bit words of total data area */
- int ldepth; /* log base 2 of number of bits per pixel */
- Rectangle r; /* rectangle in data area, local coords */
- Rectangle clipr; /* clipping region */
- GBitmap *cache; /* zero; distinguishes bitmap from layer */
-};
-
-
-/*
- * GFont etc. are not used in the library, only in devbit.c.
- * GSubfont is only barely used.
- */
-struct GSubfont
-{
- short n; /* number of chars in font */
- char height; /* height of bitmap */
- char ascent; /* top of bitmap to baseline */
- Fontchar *info; /* n+1 character descriptors */
- GBitmap *bits; /* where the characters are */
-};
-struct GCacheinfo
-{
- ulong xright; /* right edge of bits */
- Fontchar;
-};
-
-struct GFont
-{
- uchar height; /* max height of bitmap, interline spacing */
- char ascent; /* top of bitmap to baseline */
- char width; /* widest so far; used in caching only */
- char ldepth; /* of images */
- short id; /* of font */
- int ncache; /* number of entries in cache */
- GCacheinfo *cache; /* cached characters */
- GBitmap *b; /* cached images */
-};
-
-extern ulong *gaddr(GBitmap*, Point);
-extern uchar *gbaddr(GBitmap*, Point);
-extern void gbitblt(GBitmap*, Point, GBitmap*, Rectangle, Fcode);
-extern void gbitbltclip(void*);
-extern void gtexture(GBitmap*, Rectangle, GBitmap*, Fcode);
-extern Point gsubfstrsize(GSubfont*, char*);
-extern int gsubfstrwidth(GSubfont*, char*);
-extern Point gsubfstring(GBitmap*, Point, GSubfont*, char*, Fcode);
-extern Point gbitbltstring(GBitmap*, Point, GSubfont*, char*, Fcode);
-extern void gsegment(GBitmap*, Point, Point, int, Fcode);
-extern void gpoint(GBitmap*, Point, int, Fcode);
-extern void gflushcpucache(void);
-extern GBitmap* gballoc(Rectangle, int);
-extern void gbfree(GBitmap*);
--- a/os/boot/rpcg/i2c.c
+++ /dev/null
@@ -1,360 +1,0 @@
-#include "boot.h"
-
-/*
- * basic read/write interface to mpc8xx I2C bus (master mode)
- */
-
-typedef struct I2C I2C;
-
-struct I2C {
- uchar i2mod;
- uchar rsv12a[3];
- uchar i2add;
- uchar rsv12b[3];
- uchar i2brg;
- uchar rsv12c[3];
- uchar i2com;
- uchar rsv12d[3];
- uchar i2cer;
- uchar rsv12e[3];
- uchar i2cmr;
-};
-
-enum {
- /* i2c-specific BD flags */
- RxeOV= 1<<1, /* overrun */
- TxS= 1<<10, /* transmit start condition */
- TxeNAK= 1<<2, /* last transmitted byte not acknowledged */
- TxeUN= 1<<1, /* underflow */
- TxeCL= 1<<0, /* collision */
- TxERR= (TxeNAK|TxeUN|TxeCL),
-
- /* i2cmod */
- REVD= 1<<5, /* =1, LSB first */
- GCD= 1<<4, /* =1, general call address disabled */
- FLT= 1<<3, /* =0, not filtered; =1, filtered */
- PDIV= 3<<1, /* predivisor field */
- EN= 1<<0, /* enable */
-
- /* i2com */
- STR= 1<<7, /* start transmit */
- I2CM= 1<<0, /* master */
- I2CS= 0<<0, /* slave */
-
- /* i2cer */
- TXE = 1<<4,
- BSY = 1<<2,
- TXB = 1<<1,
- RXB = 1<<0,
-
- /* port B bits */
- I2CSDA = IBIT(27),
- I2CSCL = IBIT(26),
-
- Rbit = 1<<0, /* bit in address byte denoting read */
-
- /* maximum I2C I/O (can change) */
- MaxIO= 128,
- Bufsize = MaxIO+4, /* extra space for address/clock bytes and alignment */
- Freq = 100000,
- I2CTimeout = 250, /* msec */
-};
-
-/* data cache needn't be flushed if buffers allocated in uncached INTMEM */
-#define DCFLUSH(a,n)
-
-/*
- * I2C software structures
- */
-
-struct Ctlr {
- Lock;
- QLock io;
- int init;
- I2C* i2c;
- IOCparam* sp;
-
- BD* rd;
- BD* td;
- int phase;
- int timeout;
- char* addr;
- char* txbuf;
- char* rxbuf;
-};
-typedef struct Ctlr Ctlr;
-
-static Ctlr i2ctlr[1];
-extern int predawn;
-
-static void interrupt(Ureg*, void*);
-
-static void
-enable(void)
-{
- I2C *i2c;
-
- i2c = i2ctlr->i2c;
- i2c->i2cer = ~0; /* clear events */
- eieio();
- i2c->i2mod |= EN;
- eieio();
- i2c->i2cmr = TXE|BSY|TXB|RXB; /* enable all interrupts */
- eieio();
-}
-
-static void
-disable(void)
-{
- I2C *i2c;
-
- i2c = i2ctlr->i2c;
- i2c->i2cmr = 0; /* mask all interrupts */
- i2c->i2mod &= ~EN;
-}
-
-/*
- * called by the reset routine of any driver using the I2C
- */
-void
-i2csetup(void)
-{
- IMM *io;
- I2C *i2c;
- IOCparam *sp;
- Ctlr *ctlr;
- long f, e, emin;
- int p, d, dmax;
-
- ctlr = i2ctlr;
- if(ctlr->init)
- return;
- print("i2c setup...\n");
- ctlr->init = 1;
- i2c = KADDR(INTMEM+0x860);
- ctlr->i2c = i2c;
- sp = KADDR(INTMEM+0x3c80);
- ctlr->sp = sp;
- disable();
-
- if(ctlr->txbuf == nil){
- ctlr->txbuf = ialloc(Bufsize, 2);
- ctlr->addr = ctlr->txbuf+Bufsize;
- }
- if(ctlr->rxbuf == nil)
- ctlr->rxbuf = ialloc(Bufsize, 2);
- if(ctlr->rd == nil){
- ctlr->rd = bdalloc(1);
- ctlr->rd->addr = PADDR(ctlr->rxbuf);
- ctlr->rd->length = 0;
- ctlr->rd->status = BDWrap;
- }
- if(ctlr->td == nil){
- ctlr->td = bdalloc(2);
- ctlr->td->addr = PADDR(ctlr->txbuf);
- ctlr->td->length = 0;
- ctlr->td->status = BDWrap|BDLast;
- }
-
- /* select port pins */
- io = ioplock();
- io->pbdir |= I2CSDA | I2CSCL;
- io->pbodr |= I2CSDA | I2CSCL;
- io->pbpar |= I2CSDA | I2CSCL;
- iopunlock();
-
- /* explicitly initialise parameters, because InitRxTx can't be used (see i2c/spi relocation errata) */
- sp = ctlr->sp;
- sp->rbase = PADDR(ctlr->rd);
- sp->tbase = PADDR(ctlr->td);
- sp->rfcr = 0x18;
- sp->tfcr = 0x18;
- sp->mrblr = Bufsize;
- sp->rstate = 0;
- sp->rptr = 0;
- sp->rbptr = sp->rbase;
- sp->rcnt = 0;
- sp->tstate = 0;
- sp->tbptr = sp->tbase;
- sp->tptr = 0;
- sp->tcnt = 0;
- eieio();
-
- i2c->i2com = I2CM;
- i2c->i2mod = 0; /* normal mode */
- i2c->i2add = 0;
-
- emin = Freq;
- dmax = (m->cpuhz/Freq)/2-3;
- for(d=0; d < dmax; d++){
- for(p=3; p>=0; p--){
- f = (m->cpuhz>>(p+2))/(2*(d+3));
- e = Freq - f;
- if(e < 0)
- e = -e;
- if(e < emin){
- emin = e;
- i2c->i2brg = d;
- i2c->i2mod = (i2c->i2mod&~PDIV)|((3-p)<<1); /* set PDIV */
- }
- }
- }
- //print("i2brg=%d i2mod=#%2.2ux\n", i2c->i2brg, i2c->i2mod);
- setvec(VectorCPIC+0x10, interrupt, i2ctlr);
-}
-
-enum {
- Idling,
- Done,
- Busy,
- Sending,
- Recving,
-};
-
-static void
-interrupt(Ureg*, void *arg)
-{
- int events;
- Ctlr *ctlr;
- I2C *i2c;
-
- ctlr = arg;
- i2c = ctlr->i2c;
- events = i2c->i2cer;
- eieio();
- i2c->i2cer = events;
- if(events & (BSY|TXE)){
- print("I2C#%x\n", events);
- if(ctlr->phase != Idling){
- ctlr->phase = Idling;
- }
- }else{
- if(events & TXB){
- //print("i2c: xmt %d %4.4ux %4.4ux\n", ctlr->phase, ctlr->td->status, ctlr->td[1].status);
- if(ctlr->phase == Sending){
- ctlr->phase = Done;
- }
- }
- if(events & RXB){
- //print("i2c: rcv %d %4.4ux %d\n", ctlr->phase, ctlr->rd->status, ctlr->rd->length);
- if(ctlr->phase == Recving){
- ctlr->phase = Done;
- }
- }
- }
-}
-
-static int
-done(void *a)
-{
- return ((Ctlr*)a)->phase < Busy;
-}
-
-static void
-i2cwait(Ctlr *ctlr)
-{
- int i;
-
- ctlr->timeout = 0;
- i = 0;
- while(!done(ctlr)){
- if(predawn){
- if(++i > 100){
- ctlr->phase = Done;
- ctlr->timeout = 1;
- return;
- }
- delay(1);
- interrupt(nil, ctlr);
- }
- }
-}
-
-long
-i2csend(int addr, void *buf, long n)
-{
- Ctlr *ctlr;
- int i, p, s;
-
- ctlr = i2ctlr;
- if(n > MaxIO)
- return -1;
- i = 1;
- ctlr->txbuf[0] = addr & ~1;
- if(addr & 1){
- ctlr->txbuf[1] = addr>>8;
- i++;
- }
- memmove(ctlr->txbuf+i, buf, n);
- DCFLUSH(ctlr->txbuf, Bufsize);
- ctlr->phase = Sending;
- ctlr->rd->status = BDEmpty|BDWrap|BDInt;
- ctlr->td->addr = PADDR(ctlr->txbuf);
- ctlr->td->length = n+i;
- ctlr->td->status = BDReady|BDWrap|BDLast|BDInt;
- enable();
- ctlr->i2c->i2com = STR|I2CM;
- eieio();
- i2cwait(ctlr);
- disable();
- p = ctlr->phase;
- s = ctlr->td->status;
- if(s & BDReady || s & TxERR || p != Done || ctlr->timeout)
- return -1;
- return n;
-}
-
-long
-i2crecv(int addr, void *buf, long n)
-{
- Ctlr *ctlr;
- int p, s, flag;
- BD *td;
- long nr;
-
- ctlr = i2ctlr;
- if(n > MaxIO)
- return -1;
- ctlr->txbuf[0] = addr|Rbit;
- if(addr & 1){ /* special select sequence */
- ctlr->addr[0] = addr &~ 1;
- ctlr->addr[1] = addr>>8;
- }
- DCFLUSH(ctlr->txbuf, Bufsize);
- DCFLUSH(ctlr->rxbuf, Bufsize);
- ctlr->phase = Recving;
- ctlr->rd->addr = PADDR(ctlr->rxbuf);
- ctlr->rd->status = BDEmpty|BDWrap|BDInt;
- flag = 0;
- td = ctlr->td;
- td[1].status = 0;
- if(addr & 1){
- /* special select sequence */
- td->addr = PADDR(ctlr->addr);
- td->length = 2;
- /* td->status made BDReady below */
- td++;
- flag = TxS;
- }
- td->addr = PADDR(ctlr->txbuf);
- td->length = n+1;
- td->status = BDReady|BDWrap|BDLast | flag; /* not BDInt: leave that to receive */
- if(flag)
- ctlr->td->status = BDReady;
- enable();
- ctlr->i2c->i2com = STR|I2CM;
- eieio();
- i2cwait(ctlr);
- disable();
- p = ctlr->phase;
- s = ctlr->td->status;
- if(flag)
- s |= ctlr->td[1].status;
- nr = ctlr->rd->length;
- if(nr > n)
- nr = n; /* shouldn't happen */
- if(s & TxERR || s & BDReady || p != Done || ctlr->rd->status & BDEmpty || ctlr->timeout)
- return -1;
- memmove(buf, ctlr->rxbuf, nr);
- return nr;
-}
--- a/os/boot/rpcg/initfads.c
+++ /dev/null
@@ -1,187 +1,0 @@
-/*
- * Called from l.s in EPROM to set up a minimal working environment.
- * Since there is no DRAM yet, and therefore no stack, no function
- * calls may be made from sysinit0, and values can't be stored,
- * except to INTMEM. Global values are accessed by offset from SB,
- * which has been set by l.s to point into EPROM.
- *
- * This is FADS-specific in CS assignment and access of the FADS BCSR
- * to discover memory size and speed.
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "archfads.h"
-
-#define MB (1024*1024)
-
-enum {
- UPMSIZE = 64, /* memory controller instruction RAM */
- SPEED = 50, /* maximum memory clock in MHz */
- SDRAMSIZE = 4*MB,
-
- /* mcr */
- WriteRAM = 0<<30,
- ReadRAM = 1<<30,
- ExecRAM = 2<<30,
-
- SelUPMA = 0<<23,
- SelUPMB = 1<<23,
-
- Once = 1<<8,
-};
-
-/*
- * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
- */
-static ulong upma50[UPMSIZE] = {
- 0x8FFFEC24, 0xFFFEC04, 0xCFFEC04, 0xFFEC04,
- 0xFFEC00, 0x37FFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x8FFFEC24, 0xFFFEC04, 0x8FFEC04, 0xFFEC0C,
- 0x3FFEC00, 0xFFEC44, 0xFFCC08, 0xCFFCC44,
- 0xFFEC0C, 0x3FFEC00, 0xFFEC44, 0xFFCC00,
- 0x3FFFC847, 0x3FFFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x11BFCC47,
- 0xC0FFCC84, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x3AFCC4C,
- 0xCAFCC00, 0x3AFCC4C, 0xCAFCC00, 0x3AFCC4C,
- 0xCAFCC00, 0x33BFCC4F, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xC0FFCC84, 0xFFCC04, 0x7FFCC04, 0x3FFFCC06,
- 0xFFFFCC85, 0xFFFFCC05, 0xFFFFCC05, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x33FFCC07, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-};
-
-/*
- * the FADS manual table 3-7 suggests the following for 60ns EDO DRAMs at 20MHz
- */
-static ulong upma20[UPMSIZE] = {
- 0x8FFFCC04, 0x08FFCC00, 0x33FFCC47, ~0, ~0, ~0, ~0, ~0,
- [0x08] 0x8FFFCC04, 0x08FFCC08, 0x08FFCC08, 0x08FFCC08, 0x08FFCC00, 0x3FFFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x18] 0x8FEFCC00, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x20] 0x8FEFCC00, 0x09AFCC48, 0x09AFCC48, 0x08AFCC48, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x30] 0x80FFCC84, 0x17FFCC04, 0xFFFFCC86, 0xFFFFCC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x3C] 0x33FFCC07, ~0, ~0, ~0,
-};
-
-void
-sysinit0(int inrom)
-{
- ulong *upm, *bcsr;
- IMM *io;
- int i, mb;
-
- io = (IMM*)INTMEM; /* running before maps, no KADDR */
-
- /* system interface unit initialisation, FADS manual table 3-2, except as noted */
- io->siumcr = 0x01012440;
- io->sypcr = 0xFFFFFF88;
- io->tbscrk = KEEP_ALIVE_KEY;
- io->tbscr = 0xC3; /* time base enabled */
- io->rtcsck = KEEP_ALIVE_KEY;
- io->rtcsc = 0xC1; /* don't FRZ, real-time clock enabled */
- io->rtcsck = ~KEEP_ALIVE_KEY;
- io->piscrk = KEEP_ALIVE_KEY;
- io->piscr = 0x82;
-
- io->memc[BCSRCS].option = 0xFFFF8110; /* 32k block, all types access, CS early negate, 1 ws */
- io->memc[BCSRCS].base = BCSRMEM | 1; /* base, 32-bit port, no parity, GPCM */
-
- io->memc[BOOTCS].base = FLASHMEM | 1;
- io->memc[BOOTCS].option = 0xFF800D54;
-
- if(!inrom)
- return; /* can't initialise DRAM controller from DRAM */
-
- bcsr = (ulong*)BCSRMEM;
-// bcsr[1] &= ~DisableDRAM;
- /* could check DRAM speed here; assume 60ns */
- switch((bcsr[2]>>23)&3){
- default: return; /* can't happen; for the compiler */
- case 0: mb = 4; break;
- case 1: mb = 32; break;
- case 2: mb = 16; break;
- case 3: mb = 8; break;
- }
-
- upm = upma50;
- for(i=0; i<UPMSIZE; i++){
- io->mdr = upm[i];
- io->mcr = WriteRAM | SelUPMA | i;
- }
- io->mptpr = 0x0400;
- if(SPEED >= 32)
- io->mamr = (0x9C<<24) | 0xA21114; /* 50MHz BRGCLK; FADS manual says 0xC0, mpc8bug sets 0x9C */
- else if(SPEED >= 20)
- io->mamr = (0x60<<24) | 0xA21114; /* 25MHz BRGCLK */
- else
- io->mamr = (0x40<<24) | 0xA21114; /* 16.67MHz BRGCLK */
- io->memc[DRAM1].option = ~((mb<<20)-1)|0x0800; /* address mask, SAM=1 */
- io->memc[DRAM1].base = 0 | 0x81; /* base at 0, 32-bit port size, no parity, UPMA */
-}
-
-/*
- * the FADS manual table 3-9's suggestion for MB811171622A-100 32+MHz-50MHz
- */
-static ulong upmb50[UPMSIZE] = {
- [0x00] 0x1F07FC04, 0xEEAEFC04, 0x11ADFC04, 0xEFBBBC00, 0x1FF77C47,
- [0x05] 0x1FF77C34, 0xEFEABC34, 0x1FB57C35,
- [0x08] 0x1F07FC04, 0xEEAEFC04, 0x10ADFC04, 0xF0AFFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x18] 0x1F27FC04, 0xEEAEBC00, 0x01B93C04, 0x1FF77C47, ~0, ~0, ~0, ~0,
- [0x20] 0x1F07FC04, 0xEEAEBC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x30] 0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC07, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x3C] 0x7FFFFC07, ~0, ~0, ~0,
-};
-
-/*
- * the FADS manual table 3-8's suggestion for MB811171622A-100 up to 32MHz
- */
-static ulong upmb32[UPMSIZE] = {
- [0x00] 0x126CC04, 0xFB98C00, 0x1FF74C45, ~0, ~0,
- [0x05] 0x1FE77C34, 0xEFAABC34, 0x1FA57C35,
- [0x08] 0x0026FC04, 0x10ADFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x18] 0x0E26BC04, 0x01B93C00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0,
- [0x20] 0x0E26BC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x30] 0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
- [0x3C] 0x7FFFFC07, ~0, ~0, ~0,
-};
-
-/*
- * optionally called by archfads.c:/^archinit to initialise access to SDRAM
- */
-void
-sdraminit(ulong base)
-{
- ulong *upm;
- IMM *io;
- int i;
-
- io = (IMM*)INTMEM; /* running before maps, no KADDR */
- if(SPEED > 32)
- upm = upmb50;
- else
- upm = upmb32;
- for(i=0; i<UPMSIZE; i++){
- io->mdr = upm[i];
- io->mcr = WriteRAM | SelUPMB | i;
- }
- io->memc[SDRAM].option = ~(SDRAMSIZE-1)|0x0A00; /* address mask, SAM=1, G5LS=1 */
- io->memc[SDRAM].base = base | 0xC1;
- if(SPEED > 32){
- io->mbmr = 0xD0802114; /* 50MHz BRGCLK */
- io->mar = 0x88;
- }else{
- io->mbmr = 0x80802114; /* 32MHz BRGCLK */
- io->mar = 0x48;
- }
- io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 5; /* run MRS command in locations 5-8 of UPMB */
- io->mbmr = (io->mbmr & ~0xF) | 8;
- io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 0x30; /* run refresh sequence */
- io->mbmr = (io->mbmr & ~0xF) | 4; /* 4-beat refresh bursts */
-}
--- a/os/boot/rpcg/initpaq.c
+++ /dev/null
@@ -1,101 +1,0 @@
-/*
- * Called from l.s in EPROM to set up a minimal working environment.
- * Since there is no DRAM yet, and therefore no stack, no function
- * calls may be made from sysinit0, and values can't be stored,
- * except to INTMEM. Global values are accessed by offset from SB,
- * which has been set by l.s to point into EPROM.
- *
- * This is PowerPAQ-specific:
- * - assumes 8mbytes
- * - powerpaq CS assignment
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "archpaq.h"
-
-#define MB (1024*1024)
-
-enum {
- DRAMSIZE = 8*MB,
- FLASHSIZE = 8*MB,
-
- UPMSIZE = 64, /* memory controller instruction RAM */
- SPEED = 50, /* maximum memory clock in MHz */
-
- /* mcr */
- WriteRAM = 0<<30,
- ReadRAM = 1<<30,
- ExecRAM = 2<<30,
-
- SelUPMA = 0<<23,
- SelUPMB = 1<<23,
-
- Once = 1<<8,
-};
-
-/*
- * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
- */
-static ulong upmb50[UPMSIZE] = {
- 0x8FFFEC24, 0xFFFEC04, 0xCFFEC04, 0xFFEC04,
- 0xFFEC00, 0x37FFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x8FFFEC24, 0xFFFEC04, 0x8FFEC04, 0xFFEC0C,
- 0x3FFEC00, 0xFFEC44, 0xFFCC08, 0xCFFCC44,
- 0xFFEC0C, 0x3FFEC00, 0xFFEC44, 0xFFCC00,
- 0x3FFFC847, 0x3FFFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x11BFCC47,
- 0xC0FFCC84, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x3AFCC4C,
- 0xCAFCC00, 0x3AFCC4C, 0xCAFCC00, 0x3AFCC4C,
- 0xCAFCC00, 0x33BFCC4F, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0xC0FFCC84, 0xFFCC04, 0x7FFCC04, 0x3FFFCC06,
- 0xFFFFCC85, 0xFFFFCC05, 0xFFFFCC05, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
- 0x33FFCC07, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-};
-
-void
-sysinit0(int inrom)
-{
- ulong *upm;
- IMM *io;
- int i;
-
- io = (IMM*)INTMEM; /* running before maps, no KADDR */
-
- /* system interface unit initialisation, FADS manual table 3-2, except as noted */
- io->siumcr = 0x01012440;
- io->sypcr = 0xFFFFFF88;
- io->tbscrk = KEEP_ALIVE_KEY;
- io->tbscr = 0xC3; /* time base enabled */
- io->rtcsck = KEEP_ALIVE_KEY;
- io->rtcsc = 0xC1; /* don't FRZ, real-time clock enabled */
- io->rtcsck = ~KEEP_ALIVE_KEY;
- io->piscrk = KEEP_ALIVE_KEY;
- io->piscr = 0x82;
-
- io->memc[BOOTCS].base = FLASHMEM | 1;
- io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(2<<4); /* mask, BIH, 2 wait states */
-
- if(!inrom)
- return; /* can't initialise DRAM controller from DRAM */
-
- /* could check DRAM speed here; assume 60ns */
- /* could probe DRAM for size here; assume DRAMSIZE */
- io->mptpr = 0x400; /* powerpaq flash has 0x1000 */
- io->mbmr = (0xC0<<24) | 0xA21114; /* 50MHz BRGCLK */
- upm = upmb50;
- for(i=0; i<UPMSIZE; i++){
- io->mdr = upm[i];
- io->mcr = WriteRAM | SelUPMB | i;
- }
- io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0800; /* address mask, SAM=1 */
- io->memc[DRAM1].base = 0 | 0xC1; /* base at 0, 32-bit port size, no parity, UPMB */
-}
--- a/os/boot/rpcg/initrpcg.c
+++ /dev/null
@@ -1,91 +1,0 @@
-
-/*
- * Called from l.s in EPROM to set up a minimal working environment.
- * Since there is no DRAM yet, and therefore no stack, no function
- * calls may be made from sysinit, and values can't be stored,
- * except to INTMEM. Global values are accessed by offset from SB,
- * which has been set by l.s to point into EPROM.
- */
-
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "archrpcg.h"
-
-#define MB (1024*1024)
-
-enum {
- UPMSIZE = 64, /* memory controller instruction RAM */
- DRAMSIZE = 16*MB,
- FLASHSIZE = 4*MB,
-
- WriteRAM = 0<<30,
- ReadRAM = 1<<30,
- ExecRAM = 2<<30,
-
- SelUPMA = 0<<23,
- SelUPMB = 1<<23,
-};
-/* RPCG values for RPXLite AW */
-static ulong upma50[UPMSIZE] = {
- 0xCFFFCC24, 0x0FFFCC04, 0x0CAFCC04, 0x03AFCC08,
- 0x3FBFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xCFFFCC24, 0x0FFFCC04, 0x0CAFCC84, 0x03AFCC88,
- 0x3FBFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC04, 0x03FFCC00,
- 0x3FFFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC84, 0x03FFCC84,
- 0x0CFFCC00, 0x33FFCC27, 0xFFFFCC25, 0xFFFFCC25,
- 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xC0FFCC24, 0x03FFCC24, 0x0FFFCC24, 0x0FFFCC24,
- 0x3FFFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
- 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
-};
-
-void
-sysinit0(int inrom)
-{
- ulong *upm;
- IMM *io;
- int i;
-
- io = (IMM*)INTMEM; /* running before maps, no KADDR */
-// io->siumcr = 0x01012440;
-// io->sypcr = 0xFFFFFF88;
- io->tbscrk = KEEP_ALIVE_KEY;
- io->tbscr = 0xC3;
- io->rtcsck = KEEP_ALIVE_KEY;
- io->rtcsc = 0xC1;
- io->rtcsck = ~KEEP_ALIVE_KEY;
- io->piscrk = KEEP_ALIVE_KEY;
- io->piscr = 0x82;
-return;
- io->memc[BCSRCS].option = 0xFFFF8910; /* 32k block, all types access, CSNT, CS early negate, burst inhibit, 1 ws */
- io->memc[BCSRCS].base = BCSRMEM | 1; /* base, 32-bit port, no parity, GPCM */
-
-// io->memc[BOOTCS].base = FLASHMEM | 0x801; /* base, 16 bit port */
-// io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(4<<4); /* mask, BIH, 4 wait states */
-
- if(1||!inrom)
- return; /* can't initialise DRAM controller from DRAM */
-
- /* TO DO: could check DRAM size and speed now */
-
- upm = upma50;
- for(i=0; i<nelem(upma50); i++){
- io->mdr = upm[i];
- io->mcr = WriteRAM | SelUPMA | i;
- }
- io->mptpr = 0x0800; /* divide by 8 */
- io->mamr = (0x58<<24) | 0xA01430; /* 40MHz BRGCLK */
- io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0E00; /* address mask, SAM=1, G5LA/S=3 */
- io->memc[DRAM1].base = 0 | 0x81; /* base at 0, 32-bit port size, no parity, UPMA */
-}
--- a/os/boot/rpcg/io.h
+++ /dev/null
@@ -1,463 +1,0 @@
-enum
-{
- /* software interrupt vectors (SIU and CPM) */
- VectorPIC= 0, /* level 0 to level 7, assigned by software */
- CPIClevel= 4,
- VectorIRQ= VectorPIC+8, /* IRQ0 to IRQ7 */
- VectorCPIC= VectorIRQ+8, /* 32 CPM interrupts: 0 (error) to 0x1F (PC15) */
-};
-
-enum
-{
- BUSUNKNOWN = 0,
-};
-
-/*
- * Buffer Descriptors and IO Rings
- */
-
-typedef struct BD BD;
-struct BD {
- ushort status;
- ushort length;
- ulong addr;
-};
-
-BD* bdalloc(int);
-void bdfree(BD*, int);
-
-enum {
- /* Rx BDs, bits common to all protocols */
- BDEmpty= 1<<15,
- BDWrap= 1<<13,
- BDInt= 1<<12,
- BDLast= 1<<11,
- BDFirst= 1<<10,
-
- /* Tx BDs */
- BDReady= 1<<15,
- /* BDWrap, BDInt, BDLast */
-};
-
-typedef struct Ring Ring;
-struct Ring {
- BD* rdr; /* receive descriptor ring */
- void* rrb; /* receive ring buffers */
- int rdrx; /* index into rdr */
- int nrdre; /* length of rdr */
-
- BD* tdr; /* transmit descriptor ring */
- Block** txb; /* corresponding transmit ring buffers */
- int tdrh; /* host index into tdr */
- int tdri; /* interface index into tdr */
- int ntdre; /* length of tdr */
- int ntq; /* pending transmit requests */
-};
-
-#define NEXT(x, l) (((x)+1)%(l))
-#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
-#define HOWMANY(x, y) (((x)+((y)-1))/(y))
-#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
-
-int ioringinit(Ring*, int, int, int);
-
-/*
- * CPM
- */
-enum {
- /* commands */
- InitRxTx = 0,
- InitRx = 1,
- InitTx = 2,
- EnterHunt= 3,
- StopTx= 4,
- GracefulStopTx = 5,
- InitIDMA = 5,
- RestartTx = 6,
- CloseRxBD = 7,
- SetGroupAddr = 8,
- SetTimer = 8,
- GCITimeout = 9,
- GCIAbort = 10,
- StopIDMA = 11,
- StartDSP = 12,
- ArmIDMA = 13,
- InitDSP = 13,
- USBCmd = 15,
-
- /* channel IDs */
- SCC1ID= 0,
- USBID= 0,
- I2CID= 1,
- IDMA1ID= 1,
- SCC2ID= 4,
- SPIID= 5,
- IDMA2ID= 5,
- TIMERID= 5,
- SCC3ID= 8,
- SMC1ID= 9,
- DSP1ID=9,
- SCC4ID= 12,
- SMC2ID= 13,
- DSP2ID= 13,
-
- BaudEnable = 1<<16,
-
- /* sicr */
- CLK1 = 4, /* SCC1,2 */
- CLK2 = 5,
- CLK3 = 6,
- CLK4 = 7,
- CLK5 = CLK1, /* SCC3,4 */
- CLK6 = CLK2,
- CLK7 = CLK3,
- CLK8 = CLK4,
-};
-
-void cpmop(int, int, int);
-#define ioplock() (m->iomem)
-#define iopunlock()
-
-/*
- * the structures below follow hardware/firmware layouts in the 8xx manuals:
- * mind the data types, offsets and alignment
- */
-
-/*
- * basic IO controller parameters (SMC and SCC)
- */
-typedef struct IOCparam IOCparam;
-struct IOCparam {
- ushort rbase;
- ushort tbase;
- uchar rfcr;
- uchar tfcr;
- ushort mrblr;
- ulong rstate;
- ulong rptr;
- ushort rbptr;
- ushort rcnt;
- ulong rtmp;
- ulong tstate;
- ulong tptr;
- ushort tbptr;
- ushort tcnt;
- ulong ttmp;
-};
-
-typedef struct SCCparam SCCparam;
-struct SCCparam {
- IOCparam;
- ulong rcrc;
- ulong tcrc;
-};
-
-typedef struct SCC SCC;
-struct SCC {
- ulong gsmrl;
- ulong gsmrh;
- ushort psmr;
- uchar rsvscc0[2];
- ushort todr;
- ushort dsr;
- ushort scce;
- uchar rsvscc1[2];
- ushort sccm;
- uchar rsvscc3;
- uchar sccs;
- ushort irmode;
- ushort irsip;
-};
-
-typedef struct SMC SMC;
-struct SMC {
- uchar pad1[2];
- ushort smcmr;
- uchar pad2[2];
- uchar smce;
- uchar pad3[3];
- uchar smcm;
- uchar pad4[5];
-};
-
-typedef struct SPI SPI;
-struct SPI {
- ushort spmode;
- uchar res1[4];
- uchar spie;
- uchar res2[3];
- uchar spim;
- uchar res3[2];
- uchar spcom;
- uchar res4[10];
-};
-
-typedef struct USB USB;
-struct USB { /* 823 only */
- uchar usmod;
- uchar usadr;
- uchar uscom;
- uchar rsvu1;
- ushort usep[4];
- uchar rsvu2[4];
- ushort usber;
- uchar rsvu3[2];
- ushort usbmr;
- uchar rsvu4;
- uchar usbs;
- uchar rsvu5[8];
-};
-
-typedef struct IMM IMM;
-struct IMM {
- struct { /* general SIU */
- ulong siumcr;
- ulong sypcr;
- uchar rsv0[0xE-0x8];
- ushort swsr;
- ulong sipend;
- ulong simask;
- ulong siel;
- uchar sivec;
- uchar padv[3];
- ulong tesr;
- uchar rsv1[0x30-0x24];
- ulong sdcr;
- uchar rsv2[0x80-0x34];
- };
- struct { /* PCMCIA */
- struct {
- ulong base;
- ulong option;
- } pcmr[8];
- uchar rsv3[0xe0-0xc0];
- ulong pgcra;
- ulong pgcrb;
- ulong pscr;
- uchar rsv4[0xf0-0xec];
- ulong pipr;
- uchar rsv5[4];
- ulong per;
- uchar rsv6[4];
- };
- struct { /* MEMC */
- struct {
- ulong base;
- ulong option;
- } memc[8];
- uchar rsv7a[0x24];
- ulong mar;
- ulong mcr;
- uchar rsv7b[4];
- ulong mamr;
- ulong mbmr;
- ushort mstat;
- ushort mptpr;
- ulong mdr;
- uchar rsv7c[0x80];
- };
- struct { /* system integration timers */
- ushort tbscr;
- uchar rsv8a[2];
- ulong tbrefu;
- ulong tbrefl;
- uchar rsv8b[0x14];
- ushort rtcsc;
- uchar rsv8c[2];
- ulong rtc;
- ulong rtsec;
- ulong rtcal;
- uchar rsv8d[0x10];
- ushort piscr;
- ushort rsv8e;
- ulong pitc;
- ulong pitr;
- uchar rsv8f[0x34];
- };
- struct { /* 280: clocks and resets */
- ulong sccr;
- ulong plprcr;
- ulong rsr;
- uchar rsv9[0x300-0x28c];
- };
- struct { /* 300: system integration timers keys */
- ulong tbscrk;
- ulong tbrefuk;
- ulong tbreflk;
- ulong tbk;
- uchar rsv10a[0x10];
- ulong rtcsck;
- ulong rtck;
- ulong rtseck;
- ulong rtcalk;
- uchar rsv10b[0x10];
- ulong piscrk;
- ulong pitck;
- uchar rsv10c[0x38];
- };
- struct { /* 380: clocks and resets keys */
- ulong sccrk;
- ulong plprcrk;
- ulong rsrk;
- uchar rsv11[0x800-0x38C];
- };
- struct { /* 800: video controller */
- ushort vccr;
- ushort pad11a;
- uchar vsr;
- uchar pad11b;
- uchar vcmr;
- uchar pad11c;
- ulong vbcb;
- ulong pad11d;
- ulong vfcr0;
- ulong vfaa0;
- ulong vfba0;
- ulong vfcr1;
- ulong vfaa1;
- ulong vfba1;
- uchar rsv11a[0x840-0x828];
- };
- struct { /* 840: LCD */
- ulong lccr;
- ulong lchcr;
- ulong lcvcr;
- ulong rsv11b;
- ulong lcfaa;
- ulong lcfba;
- uchar lcsr;
- uchar rsv11c[0x860-0x859];
- };
- struct { /* 860: I2C */
- uchar i2mod;
- uchar rsv12a[3];
- uchar i2add;
- uchar rsv12b[3];
- uchar i2brg;
- uchar rsv12c[3];
- uchar i2com;
- uchar rsv12d[3];
- uchar i2cer;
- uchar rsv12e[3];
- uchar i2cmr;
- uchar rsv12[0x900-0x875];
- };
- struct { /* 900: DMA */
- uchar rsv13[4];
- ulong sdar;
- uchar sdsr;
- uchar pad1[3];
- uchar sdmr;
- uchar pad2[3];
- uchar idsr1;
- uchar pad3[3];
- uchar idmr1;
- uchar pad4[3];
- uchar idsr2;
- uchar pad5[3];
- uchar idmr2;
- uchar pad6[0x930-0x91D];
- };
- struct { /* CPM interrupt control */
- ushort civr;
- uchar pad7[0x940-0x932];
- ulong cicr;
- ulong cipr;
- ulong cimr;
- ulong cisr;
- };
- struct { /* input/output port */
- ushort padir;
- ushort papar;
- ushort paodr;
- ushort padat;
- uchar pad8[8];
- ushort pcdir;
- ushort pcpar;
- ushort pcso;
- ushort pcdat;
- ushort pcint;
- uchar pad9[6];
- ushort pddir;
- ushort pdpar;
- ushort rsv14a;
- ushort pddat;
- uchar rsv14[0x980-0x978];
- };
- struct { /* CPM timers */
- ushort tgcr;
- uchar rsv15a[0x990-0x982];
- ushort tmr1;
- ushort tmr2;
- ushort trr1;
- ushort trr2;
- ushort tcr1;
- ushort tcr2;
- ushort tcn1;
- ushort tcn2;
- ushort tmr3;
- ushort tmr4;
- ushort trr3;
- ushort trr4;
- ushort tcr3;
- ushort tcr4;
- ushort tcn3;
- ushort tcn4;
- ushort ter1;
- ushort ter2;
- ushort ter3;
- ushort ter4;
- uchar rsv15[0x9C0-0x9B8];
- };
- struct { /* CPM */
- ushort cpcr;
- uchar res0[2];
- ushort rccr;
- uchar res1;
- uchar rmds;
- uchar res2a[4];
- ushort rctr1;
- ushort rctr2;
- ushort rctr3;
- ushort rctr4;
- uchar res2[2];
- ushort rter;
- uchar res3[2];
- ushort rtmr;
- uchar rsv16[0x9F0-0x9DC];
- };
- union { /* BRG */
- struct {
- ulong brgc1;
- ulong brgc2;
- ulong brgc3;
- ulong brgc4;
- };
- ulong brgc[4];
- };
- uchar skip0[0xAB2-0xA00]; /* USB, SCC, SMC, SPI: address using cpmdev(CP...)->regs */
- struct { /* PIP */
- ushort pipc; /* not 823 */
- ushort ptpr; /* not 823 */
- ulong pbdir;
- ulong pbpar;
- uchar pad10[2];
- ushort pbodr;
- ulong pbdat;
- uchar pad11[0xAE0-0xAC8];
- };
- struct { /* SI */
- ulong simode;
- uchar sigmr;
- uchar pad12;
- uchar sistr;
- uchar sicmr;
- uchar pad13[4];
- ulong sicr;
- ulong sirp;
- uchar pad14[0xB00-0xAF4];
- };
- ulong vcram[64];
- ushort siram[256];
- ushort lcdmap[256];
-};
--- a/os/boot/rpcg/ip.h
+++ /dev/null
@@ -1,98 +1,0 @@
-typedef struct Udphdr Udphdr;
-struct Udphdr
-{
- uchar d[6]; /* Ethernet destination */
- uchar s[6]; /* Ethernet source */
- uchar type[2]; /* Ethernet packet type */
-
- uchar vihl; /* Version and header length */
- uchar tos; /* Type of service */
- uchar length[2]; /* packet length */
- uchar id[2]; /* Identification */
- uchar frag[2]; /* Fragment information */
-
- /* Udp pseudo ip really starts here */
- uchar ttl;
- uchar udpproto; /* Protocol */
- uchar udpplen[2]; /* Header plus data length */
- uchar udpsrc[4]; /* Ip source */
- uchar udpdst[4]; /* Ip destination */
- uchar udpsport[2]; /* Source port */
- uchar udpdport[2]; /* Destination port */
- uchar udplen[2]; /* data length */
- uchar udpcksum[2]; /* Checksum */
-};
-
-typedef struct Etherhdr Etherhdr;
-struct Etherhdr
-{
- uchar d[6];
- uchar s[6];
- uchar type[2];
-
- /* Now we have the ip fields */
- uchar vihl; /* Version and header length */
- uchar tos; /* Type of service */
- uchar length[2]; /* packet length */
- uchar id[2]; /* Identification */
- uchar frag[2]; /* Fragment information */
- uchar ttl; /* Time to live */
- uchar proto; /* Protocol */
- uchar cksum[2]; /* Header checksum */
- uchar src[4]; /* Ip source */
- uchar dst[4]; /* Ip destination */
-};
-
-enum
-{
- IP_VER = 0x40,
- IP_HLEN = 0x05,
- UDP_EHSIZE = 22,
- UDP_PHDRSIZE = 12,
- UDP_HDRSIZE = 20,
- ETHER_HDR = 14,
- IP_UDPPROTO = 17,
- ET_IP = 0x800,
- Bcastip = 0xffffffff,
- BPportsrc = 68,
- BPportdst = 67,
- TFTPport = 69,
- Timeout = 5000, /* milliseconds */
- Bootrequest = 1,
- Bootreply = 2,
- Tftp_READ = 1,
- Tftp_WRITE = 2,
- Tftp_DATA = 3,
- Tftp_ACK = 4,
- Tftp_ERROR = 5,
- Segsize = 512,
- TFTPSZ = Segsize+10,
-};
-
-typedef struct Bootp Bootp;
-struct Bootp
-{
- uchar op; /* opcode */
- uchar htype; /* hardware type */
- uchar hlen; /* hardware address len */
- uchar hops; /* hops */
- uchar xid[4]; /* a random number */
- uchar secs[2]; /* elapsed snce client started booting */
- uchar pad[2];
- uchar ciaddr[4]; /* client IP address (client tells server) */
- uchar yiaddr[4]; /* client IP address (server tells client) */
- uchar siaddr[4]; /* server IP address */
- uchar giaddr[4]; /* gateway IP address */
- uchar chaddr[16]; /* client hardware address */
- char sname[64]; /* server host name (optional) */
- char file[128]; /* boot file name */
- char vend[128]; /* vendor-specific goo */
-};
-
-typedef struct Netaddr Netaddr;
-struct Netaddr
-{
- ulong ip;
- ushort port;
- char ea[Eaddrlen];
-};
--- a/os/boot/rpcg/l.s
+++ /dev/null
@@ -1,388 +1,0 @@
-#include "mem.h"
-
-/* special instruction definitions */
-#define BDNE BC 0,2,
-#define BDNZ BC 16,0,
-#define NOOP OR R0,R0,R0
-
-/*
- * common ppc special purpose registers
- */
-#define DSISR 18
-#define DAR 19 /* Data Address Register */
-#define DEC 22 /* Decrementer */
-#define SRR0 26 /* Saved Registers (exception) */
-#define SRR1 27
-#define SPRG0 272 /* Supervisor Private Registers */
-#define SPRG1 273
-#define SPRG2 274
-#define SPRG3 275
-#define TBRU 269 /* Time base Upper/Lower (Reading) */
-#define TBRL 268
-#define TBWU 285 /* Time base Upper/Lower (Writing) */
-#define TBWL 284
-#define PVR 287 /* Processor Version */
-
-/*
- * mpc82x-specific special purpose registers of interest here
- */
-#define EIE 80
-#define EID 81
-#define NRI 82
-#define IMMR 638
-#define IC_CST 560
-#define IC_ADR 561
-#define IC_DAT 562
-#define DC_CST 568
-#define DC_ADR 569
-#define DC_DAT 570
-#define MI_CTR 784
-#define MI_AP 786
-#define MI_EPN 787
-#define MI_TWC 789
-#define MI_RPN 790
-#define MI_DBCAM 816
-#define MI_DBRAM0 817
-#define MI_DBRAM1 818
-#define MD_CTR 792
-#define M_CASID 793
-#define MD_AP 794
-#define MD_EPN 795
-#define M_TWB 796
-#define MD_TWC 797
-#define MD_RPN 798
-#define M_TW 799
-#define MD_DBCAM 824
-#define MD_DBRAM0 825
-#define MD_DBRAM1 826
-
-/* as on 603e, apparently mtmsr needs help in some chip revisions */
-#define WAITMSR SYNC; ISYNC
-
-/* use of SPRG registers in save/restore */
-#define SAVER0 SPRG0
-#define SAVER1 SPRG1
-#define SAVELR SPRG2
-#define SAVECR SPRG3
-
-#define UREGSIZE ((8+32)*4)
-#define UREGSPACE (UREGSIZE+8) /* allow for arg to trap, and align */
-
-/*
- * This code is loaded by the ROM loader at location 0x3000,
- * or lives in flash memory at FLASHMEM+0x100
- * Move it to high memory so that it can load the kernel at 0x0000.
- */
-
-#define LOADCODEBASE 0x3000 /* when downloaded in S records */
-#define FLASHCODEBASE (FLASHMEM+0x20000+0x100) /* when in flash */
-
- TEXT start(SB), $-4
- MOVW MSR, R3
- MOVW $(EE|IP|RI), R4
- ANDN R4, R3
- OR $ME, R3
- SYNC
- MOVW R3, MSR /* turn off interrupts but enable traps */
- WAITMSR
-
-/*
- * reset the caches and disable them for now
- */
- MOVW SPR(IC_CST), R4 /* read and clear */
- MOVW $(5<<25), R4
- MOVW R4, SPR(IC_CST) /* unlock all */
- ISYNC
- MOVW $(6<<25), R4
- MOVW R4, SPR(IC_CST) /* invalidate all */
- ISYNC
- MOVW $(2<<25), R4
- MOVW R4, SPR(IC_CST) /* disable i-cache */
- ISYNC
-
- SYNC
- MOVW SPR(DC_CST), R4 /* read and clear */
- MOVW $(10<<24), R4
- MOVW R4, SPR(DC_CST) /* unlock all */
- ISYNC
- MOVW $(12<<24), R4
- MOVW R4, SPR(DC_CST) /* invalidate all */
- ISYNC
- MOVW $(4<<24), R4
- MOVW R4, SPR(DC_CST) /* disable i-cache */
- ISYNC
-
- MOVW $7, R4
- MOVW R4, SPR(158) /* cancel `show cycle' for normal instruction execution */
-
-/*
- * set other system configuration values
- */
- MOVW SPR(IMMR), R5 /* save initial space pointer */
- MOVW $INTMEM, R4
- MOVW R4, SPR(IMMR) /* set internal memory base */
- MOVW $0xFFFFFF88, R3
- MOVW R3, 4(R4) /* disable watchdog in sypcr */
- MOVW $0x01012440, R3
- MOVW R3, 0(R4) /* siumcr */
-
-/*
- * system initialisation (init and map DRAM)
- */
- MOVW $0, R0
- MOVW $setSB(SB), R2
-#ifndef confrpcg
- MOVW $(0xF000<<16), R3
-/*MOVW R0, R3*/
- ANDCC R5, R3 /* initial space is high? */
- BEQ notrom
- MOVW $FLASHCODEBASE, R5 /* where $start(SB) actually is now */
- MOVW $start(SB), R4 /* logical start address */
- SUB R4, R5, R6 /* text relocation value */
- MOVW $etext(SB), R7
- SUB R4, R7
- ADD R5, R7 /* data address in ROM */
- MOVW $bdata(SB), R8
- SUB R8, R2
- ADD R7, R2 /* relocate SB: SB' = romdata+(SB-bdata) */
- MOVW $sysinit0(SB), R4
- ADD R6, R4 /* relocate sysinit0's address */
- MOVW R4, CTR
- MOVW $inmem(SB), R4
- ADD R6, R4
- MOVW R4, LR /* and the return address */
- BR (CTR) /* call sysinit0 */
- TEXT inmem(SB), $-4
- MOVW $FLASHCODEBASE, R3
- BR cpu0
-notrom:
- MOVW $start(SB), R6
- SUB R6, R2
- ADD $LOADCODEBASE, R2
- BL sysinit0(SB)
- MOVW $LOADCODEBASE, R3
-#endif
-
-/*
- * cpu 0
- * relocate bootstrap to our link addresses for text and data
- * set new PC
- */
-cpu0:
- MOVW $setSB(SB), R2 /* set correct static base register */
-#ifndef confrpcg
- MOVW $start(SB), R4
- MOVW $etext(SB), R5
- SUB R4, R5
- CMP R4, R3 /* already there? */
- BNE copytext
- ADD R5, R3 /* start of data image */
-#else
- MOVW $etext(SB), R3
-#endif
- BR copydata
-
-copytext:
- ADD $3, R5
- SRAW $2, R5
- MOVW R5, CTR
- SUB $4, R4
- SUB $4, R3
-copyt: /* copy text */
- MOVWU 4(R3), R5
- MOVWU R5, 4(R4)
- BDNZ copyt
- ADD $4, R3
-
-copydata:
- /* copy data */
- MOVW $bdata(SB), R4
- CMP R4, R3 /* already there? */
- BEQ loadkpc
- MOVW $edata(SB), R5
- SUB R4, R5
- ADD $3, R5
- SRAW $2, R5
- MOVW R5, CTR
- SUB $4, R4
- SUB $4, R3
-copyd:
- MOVWU 4(R3), R5
- MOVWU R5, 4(R4)
- BDNZ copyd
-#endif
-
- /* load correct PC */
-loadkpc:
- MOVW $start1(SB), R3
- MOVW R3, LR
- BR (LR)
-TEXT start1(SB), $-4
- MOVW $edata(SB), R3
- MOVW $end(SB), R4
- SUBCC R3, R4
- BLE skipz
- SRAW $2, R4
- MOVW R4, CTR
- SUB $4, R3
- MOVW $0, R0
-zero:
- MOVWU R0, 4(R3)
- BDNZ zero
-skipz:
- MOVW $mach0(SB), R1
- MOVW R1, m(SB)
- ADD $(MACHSIZE-8), R1
- MOVW $0, R0
-
- BL sysinit0(SB)
-
- BL main(SB)
- BR 0(PC)
-
-TEXT ledx(SB), $0
-
- MOVW $BCSRMEM, R8
- MOVW 0(R8), R3
- MOVW $(0x0800<<16), R5
- ANDN R5, R3, R3
- MOVW R3, 0(R8)
- BR 0(PC)
-
-TEXT getmsr(SB), $0
- MOVW MSR, R3
- RETURN
-
-TEXT putmsr(SB), $0
- SYNC
- MOVW R3, MSR
- WAITMSR
- RETURN
-
-TEXT eieio(SB), $0
- EIEIO
- RETURN
-
-TEXT idle(SB), $0
- RETURN
-
-TEXT spllo(SB), $0
- MOVW MSR, R3
- OR $EE, R3, R4
- SYNC
- MOVW R4, MSR
- WAITMSR
- RETURN
-
-TEXT splhi(SB), $0
- MOVW MSR, R3
- RLWNM $0, R3, $~EE, R4
- SYNC
- MOVW R4, MSR
- WAITMSR
- RETURN
-
-TEXT splx(SB), $0
- MOVW MSR, R4
- RLWMI $0, R3, $EE, R4
- SYNC
- MOVW R4, MSR
- WAITMSR
- RETURN
-
-TEXT gettbl(SB), $0
-/* MOVW SPR(TBRL), R3 */
- WORD $0x7c6c42e6 /* mftbl on 8xx series */
- RETURN
-
-TEXT getpvr(SB), $0
- MOVW SPR(PVR), R3
- RETURN
-
-TEXT getimmr(SB), $0
- MOVW SPR(IMMR), R3
- RETURN
-
-TEXT getdec(SB), $0
- MOVW SPR(DEC), R3
- RETURN
-
-TEXT putdec(SB), $0
- MOVW R3, SPR(DEC)
- RETURN
-
-/*
- * save state in Ureg on kernel stack.
- * enter with R0 giving the PC from the call to `exception' from the vector.
- * on return, SB (R2) has been set, and R3 has the Ureg*
- */
-TEXT saveureg(SB), $-4
- SUB $UREGSPACE, R1
- MOVMW R2, 48(R1) /* r2:r31 */
- MOVW $setSB(SB), R2
- MOVW SPR(SAVER1), R4
- MOVW R4, 44(R1)
- MOVW SPR(SAVER0), R5
- MOVW R5, 40(R1)
- MOVW CTR, R6
- MOVW R6, 36(R1)
- MOVW XER, R4
- MOVW R4, 32(R1)
- MOVW SPR(SAVECR), R5 /* CR */
- MOVW R5, 28(R1)
- MOVW SPR(SAVELR), R6 /* LR */
- MOVW R6, 24(R1)
- /* pad at 20(R1) */
- MOVW SPR(SRR0), R4
- MOVW R4, 16(R1) /* old PC */
- MOVW SPR(SRR1), R5
- MOVW R5, 12(R1)
- MOVW R0, 8(R1) /* cause/vector, encoded in LR from vector */
- ADD $8, R1, R3 /* Ureg* */
- STWCCC R3, (R1) /* break any pending reservations */
- MOVW $0, R0 /* R0ISZERO */
- BR (LR)
-
-/*
- * restore state from Ureg
- * SB (R2) is unusable on return
- */
-TEXT restoreureg(SB), $-4
- MOVMW 48(R1), R2 /* r2:r31 */
- /* defer R1 */
- MOVW 40(R1), R0
- MOVW R0, SPR(SAVER0)
- MOVW 36(R1), R0
- MOVW R0, CTR
- MOVW 32(R1), R0
- MOVW R0, XER
- MOVW 28(R1), R0
- MOVW R0, CR /* CR */
- MOVW 24(R1), R0
- MOVW R0, SPR(SAVELR) /* LR */
- /* pad, skip */
- MOVW 16(R1), R0
- MOVW R0, SPR(SRR0) /* old PC */
- MOVW 12(R1), R0
- MOVW R0, SPR(SRR1) /* old MSR */
- /* cause, skip */
- MOVW 44(R1), R1 /* old SP */
- BR (LR)
-
-TEXT exception(SB), $-4
- MOVW R1, SPR(SAVER1)
- MOVW CR, R0
- MOVW R0, SPR(SAVECR)
- MOVW LR, R0
- BL saveureg(SB)
- MOVW $0, R0
- BL trap(SB)
- BL restoreureg(SB)
- MOVW SPR(SAVELR), R0
- MOVW R0, LR
- MOVW SPR(SAVER0), R0
- ISYNC
- RFI
-
-GLOBL mach0+0(SB), $MACHSIZE
-GLOBL m(SB), $4
--- a/os/boot/rpcg/lib.h
+++ /dev/null
@@ -1,106 +1,0 @@
-/*
- * functions (possibly) linked in, complete, from libc.
- */
-
-/*
- * mem routines
- */
-extern void* memccpy(void*, void*, int, long);
-extern void* memset(void*, int, long);
-extern int memcmp(void*, void*, long);
-extern void* memmove(void*, void*, long);
-extern void* memchr(void*, int, long);
-
-/*
- * string routines
- */
-extern char* strcat(char*, char*);
-extern char* strchr(char*, char);
-extern int strcmp(char*, char*);
-extern char* strcpy(char*, char*);
-extern char* strncat(char*, char*, long);
-extern char* strncpy(char*, char*, long);
-extern int strncmp(char*, char*, long);
-extern long strlen(char*);
-extern char* strrchr(char*, char);
-extern char* strstr(char*, char*);
-
-/*
- * print routines
- * Fconv isn't used but is defined to satisfy prototypes in libg.h
- * that are never called.
- */
-typedef struct Fconv Fconv;
-
-extern char* donprint(char*, char*, char*, void*);
-extern int sprint(char*, char*, ...);
-extern int print(char*, ...);
-
-#define PRINTSIZE 256
-
-/*
- * one-of-a-kind
- */
-extern int atoi(char*);
-extern long strtol(char*, char**, int);
-extern ulong strtoul(char*, char**, int);
-extern long end;
-
-/*
- * Syscall data structures
- */
-
-#define MORDER 0x0003 /* mask for bits defining order of mounting */
-#define MREPL 0x0000 /* mount replaces object */
-#define MBEFORE 0x0001 /* mount goes before others in union directory */
-#define MAFTER 0x0002 /* mount goes after others in union directory */
-#define MCREATE 0x0004 /* permit creation in mounted directory */
-#define MMASK 0x0007 /* all bits on */
-
-#define OREAD 0 /* open for read */
-#define OWRITE 1 /* write */
-#define ORDWR 2 /* read and write */
-#define OEXEC 3 /* execute, == read but check execute permission */
-#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
-#define OCEXEC 32 /* or'ed in, close on exec */
-#define ORCLOSE 64 /* or'ed in, remove on close */
-
-#define NCONT 0 /* continue after note */
-#define NDFLT 1 /* terminate after note */
-
-typedef struct Qid Qid;
-typedef struct Dir Dir;
-typedef struct Waitmsg Waitmsg;
-
-#define ERRLEN 64
-#define DIRLEN 116
-#define NAMELEN 28
-
-struct Qid
-{
- ulong path;
- ulong vers;
-};
-
-struct Dir
-{
- char name[NAMELEN];
- char uid[NAMELEN];
- char gid[NAMELEN];
- Qid qid;
- ulong mode;
- long atime;
- long mtime;
- vlong length;
- short type;
- short dev;
-};
-
-struct Waitmsg
-{
- int pid; /* of loved one */
- int status; /* unused; a placeholder */
- ulong time[3]; /* of loved one */
- char msg[ERRLEN];
-};
-#define nelem(x) (sizeof(x)/sizeof((x)[0]))
--- a/os/boot/rpcg/libg.h
+++ /dev/null
@@ -1,418 +1,0 @@
-#pragma src "/sys/src/libg"
-#pragma lib "libg.a"
-
-enum /* constants for I/O to devgraphics */
-{
- Tilehdr = 40,
- Tilesize = 8000
-};
-
-/*
- * you may think it's a blit, but it's gnot
- */
-enum
-{
- EMAXMSG = 128+8192, /* size of 9p header+data */
-};
-
-/*
- * Types
- */
-
-typedef struct Bitmap Bitmap;
-typedef struct Display Display;
-typedef struct Point Point;
-typedef struct Rectangle Rectangle;
-typedef struct Cursor Cursor;
-typedef struct Mouse Mouse;
-typedef struct Menu Menu;
-typedef struct Font Font;
-typedef struct Fontchar Fontchar;
-typedef struct Subfont Subfont;
-typedef struct Cachefont Cachefont;
-typedef struct Cacheinfo Cacheinfo;
-typedef struct Cachesubf Cachesubf;
-typedef struct Event Event;
-typedef struct Slave Slave;
-typedef struct Ebuf Ebuf;
-typedef struct RGB RGB;
-typedef struct Linedesc Linedesc;
-typedef struct DRefret DRefret;
-
-struct DRefret
-{
- int n; /* number of bytes */
- int dy; /* number of lines */
- uchar *dp; /* pointer to data */
-};
-
-struct Point
-{
- int x;
- int y;
-};
-
-struct Rectangle
-{
- Point min;
- Point max;
-};
-
-typedef DRefret DRefresh(Display*, int, Rectangle, uchar*, uchar*, int);
-
-struct Bitmap
-{
- Rectangle r; /* rectangle in data area, local coords */
- Rectangle clipr; /* clipping region */
- int ldepth; /* log base 2 of number of bits per pixel */
- ulong *base; /* pointer to start of data */
- int zero; /* base+zero=&word containing (0,0) */
- ulong width; /* width in words of total data area */
- Display *display; /* if present */
-};
-
-struct Display
-{
- uchar *data; /* transfer buffer */
- Rectangle r;
- int ldepth;
- Rectangle bb; /* bounding box of changes */
- int waste; /* unused part of bb */
- Rectangle bound; /* memory for boundin/boundout */
- Bitmap *image; /* owner */
- int id;
- int fd;
- int ctlfd;
- int local;
- int bytewidth;
- void *drdata1; /* storage for drefresh() */
- void *drdata2; /* storage for drefresh() */
- DRefresh *drefresh;
-};
-
-
-struct Mouse
-{
- int buttons; /* bit array: LMR=124 */
- Point xy;
- ulong msec;
-};
-
-struct Cursor
-{
- Point offset;
- uchar clr[2*16];
- uchar set[2*16];
-};
-
-struct Menu
-{
- char **item;
- char *(*gen)(int);
- int lasthit;
-};
-
-struct Linedesc
-{
- int x0;
- int y0;
- char xmajor;
- char slopeneg;
- long dminor;
- long dmajor;
-};
-
-/*
- * Subfonts
- *
- * given char c, Subfont *f, Fontchar *i, and Point p, one says
- * i = f->info+c;
- * bitblt(b, Pt(p.x+i->left,p.y+i->top),
- * bitmap, Rect(i->x,i->top,(i+1)->x,i->bottom),
- * fc);
- * p.x += i->width;
- * where bitmap b is the repository of the images.
- *
- */
-
-struct Fontchar
-{
- short x; /* left edge of bits */
- uchar top; /* first non-zero scan-line */
- uchar bottom; /* last non-zero scan-line + 1 */
- char left; /* offset of baseline */
- uchar width; /* width of baseline */
-};
-
-struct Subfont
-{
- short n; /* number of chars in font */
- uchar height; /* height of bitmap */
- char ascent; /* top of bitmap to baseline */
- Fontchar *info; /* n+1 character descriptors */
- Bitmap *bits; /* of font */
-};
-
-enum
-{
- /* starting values */
- LOG2NFCACHE = 6,
- NFCACHE = (1<<LOG2NFCACHE), /* #chars cached */
- NFLOOK = 5, /* #chars to scan in cache */
- NFSUBF = 2, /* #subfonts to cache */
- /* max value */
- MAXFCACHE = 2048+NFLOOK, /* generous upper limit */
- MAXSUBF = 50, /* generous upper limit */
- /* deltas */
- DSUBF = 4,
- /* expiry ages */
- SUBFAGE = 10000,
- CACHEAGE = 10000,
-};
-
-struct Cachefont
-{
- Rune min; /* lowest rune value to be taken from subfont */
- Rune max; /* highest rune value+1 to be taken from subfont */
- int offset; /* position in subfont of character at min */
- int abs; /* name has been made absolute */
- char *name;
-};
-
-struct Cacheinfo
-{
- Rune value; /* value of character at this slot in cache */
- ushort age;
- ulong xright; /* right edge of bits */
- Fontchar;
-};
-
-struct Cachesubf
-{
- ulong age; /* for replacement */
- Cachefont *cf; /* font info that owns us */
- Subfont *f; /* attached subfont */
-};
-
-struct Font
-{
- char *name;
- short height; /* max height of bitmap, interline spacing */
- short ascent; /* top of bitmap to baseline */
- int maxldepth; /* over all loaded subfonts */
- short width; /* widest so far; used in caching only */
- short ldepth; /* of images */
- short nsub; /* number of subfonts */
- ulong age; /* increasing counter; used for LRU */
- int ncache; /* size of cache */
- int nsubf; /* size of subfont list */
- Cacheinfo *cache;
- Cachesubf *subf;
- Cachefont **sub; /* as read from file */
- Bitmap *cacheimage;
-};
-
-struct Event
-{
- int kbdc;
- Mouse mouse;
- int n; /* number of characters in mesage */
- uchar data[EMAXMSG]; /* message from an arbitrary file descriptor */
-};
-
-struct Slave{
- int pid;
- Ebuf *head; /* queue of messages for this descriptor */
- Ebuf *tail;
-};
-
-struct Ebuf{
- Ebuf *next;
- int n; /* number of bytes in buf */
- uchar buf[EMAXMSG];
-};
-
-struct RGB
-{
- ulong red;
- ulong green;
- ulong blue;
-};
-
-/*
- * Codes for bitblt etc.
- *
- * D
- * 0 1
- * ---------
- * 0 | 1 | 2 |
- * S |---|---|
- * 1 | 4 | 8 |
- * ---------
- *
- * Usually used as D|S; DorS is so tracebacks are readable.
- */
-typedef
-enum Fcode
-{
- Zero = 0x0,
- DnorS = 0x1,
- DandnotS = 0x2,
- notS = 0x3,
- notDandS = 0x4,
- notD = 0x5,
- DxorS = 0x6,
- DnandS = 0x7,
- DandS = 0x8,
- DxnorS = 0x9,
- D = 0xA,
- DornotS = 0xB,
- S = 0xC,
- notDorS = 0xD,
- DorS = 0xE,
- F = 0xF,
-} Fcode;
-
-/*
- * Miscellany
- */
-
-extern Point add(Point, Point), sub(Point, Point);
-extern Point mul(Point, int), div(Point, int);
-extern Rectangle rsubp(Rectangle, Point), raddp(Rectangle, Point), inset(Rectangle, int);
-extern Rectangle rmul(Rectangle, int), rdiv(Rectangle, int);
-extern Rectangle rshift(Rectangle, int), rcanon(Rectangle);
-extern Bitmap* balloc(Rectangle, int);
-extern Bitmap* ballocnomem(Rectangle, int);
-extern Bitmap* brealloc(Bitmap*, Rectangle, int);
-extern Bitmap* breallocnomem(Bitmap*, Rectangle, int);
-extern int bbytewidth(Bitmap*, int*, int*);
-extern void bfree(Bitmap*);
-extern void bfreemem(Bitmap*);
-extern int rectclip(Rectangle*, Rectangle);
-extern void binit(void(*)(char*), char*, char*);
-extern void binit1(void(*)(char*), char*, char*, int);
-extern void bclose(void);
-extern void berror(char*);
-extern void bitblt(Bitmap*, Point, Bitmap*, Rectangle, Fcode);
-extern int bitbltclip(void*);
-extern Font* rdfontfile(char*, int);
-extern void ffree(Font*);
-extern void fminldepth(Font*);
-extern Font* mkfont(Subfont*, Rune);
-extern Subfont* subfalloc(int, int, int, Fontchar*, Bitmap*);
-extern void subffree(Subfont*);
-extern int cachechars(Font*, char**, ushort*, int, int*);
-extern Point string(Bitmap*, Point, Font*, char*, Fcode);
-extern Point subfstring(Bitmap*, Point, Subfont*, char*, Fcode);
-extern void segment(Bitmap*, Point, Point, int, Fcode);
-extern void point(Bitmap*, Point, int, Fcode);
-extern void arc(Bitmap*, Point, Point, Point, int, Fcode);
-extern void circle(Bitmap*, Point, int, int, Fcode);
-extern void disc(Bitmap*, Point, int, int, Fcode);
-extern void ellipse(Bitmap*, Point, int, int, int, Fcode);
-extern long strwidth(Font*, char*);
-extern void agefont(Font*);
-extern int loadchar(Font*, Rune, Cacheinfo*, int, int);
-extern Point strsize(Font*, char*);
-extern long charwidth(Font*, Rune);
-extern void texture(Bitmap*, Rectangle, Bitmap*, Fcode);
-extern void wrbitmap(Bitmap*, int, int, uchar*);
-extern void rdbitmap(Bitmap*, int, int, uchar*);
-extern void wrbitmapfile(int, Bitmap*);
-extern Bitmap* rdbitmapfile(int);
-extern void wrsubfontfile(int, Subfont*);
-extern void wrcolmap(Bitmap*, RGB*);
-extern void rdcolmap(Bitmap*, RGB*);
-extern Subfont* rdsubfontfile(int, Bitmap*);
-extern void _unpackinfo(Fontchar*, uchar*, int);
-
-extern int ptinrect(Point, Rectangle), rectinrect(Rectangle, Rectangle);
-extern int rectXrect(Rectangle, Rectangle);
-extern int eqpt(Point, Point), eqrect(Rectangle, Rectangle);
-extern void border(Bitmap*, Rectangle, int, Fcode);
-extern void cursorswitch(Cursor*);
-extern void cursorset(Point);
-extern Rectangle bscreenrect(Rectangle*);
-extern void bflush(void);
-extern void bexit(void);
-extern int _clipline(Rectangle, Point*, Point*, Linedesc*);
-extern int clipline(Rectangle, Point*, Point*);
-extern int clipr(Bitmap*, Rectangle);
-
-extern void einit(ulong);
-extern ulong estart(ulong, int, int);
-extern ulong etimer(ulong, int);
-extern ulong event(Event*);
-extern ulong eread(ulong, Event*);
-extern Ebuf* ebread(Slave*);
-extern Mouse emouse(void);
-extern int ekbd(void);
-extern int ecanread(ulong);
-extern int ecanmouse(void);
-extern int ecankbd(void);
-extern void ereshaped(Rectangle); /* supplied by user */
-extern int menuhit(int, Mouse*, Menu*);
-extern Rectangle getrect(int, Mouse*);
-extern ulong rgbpix(Bitmap*, RGB);
-extern int _gminor(long, Linedesc*);
-
-enum{
- Emouse = 1,
- Ekeyboard = 2,
-};
-
-enum
-{
- MAXSLAVE = 32,
-};
-
-#define Pt(x, y) ((Point){(x), (y)})
-#define Rect(x1, y1, x2, y2) ((Rectangle){Pt(x1, y1), Pt(x2, y2)})
-#define Rpt(p1, p2) ((Rectangle){(p1), (p2)})
-
-
-#define Dx(r) ((r).max.x-(r).min.x)
-#define Dy(r) ((r).max.y-(r).min.y)
-
-extern Bitmap screen;
-extern Font *font;
-extern uchar _btmp[8192];
-
-extern int _mousefd;
-extern int _cursorfd;
-
-#define BGSHORT(p) (((p)[0]<<0) | ((p)[1]<<8))
-#define BG32INT(p) ((s32int)((BGSHORT(p)<<0) | (BGSHORT(p+2)<<16)))
-#define BPSHORT(p, v) ((p)[0]=(v), (p)[1]=((v)>>8))
-#define BP32INT(p, v) (BPSHORT(p, ((s32int)v)), BPSHORT(p+2, ((s32int)v)>>16))
-
-ulong *wordaddr(Bitmap*, Point);
-uchar *byteaddr(Bitmap*, Point);
-int dfree(Display*);
-int dwritectl(Display*, char*, int);
-int dreadctl(Display*, char*, int);
-int dinfo(Display*, int, int*, Rectangle*);
-void* dinit(Display*, Bitmap*, int, int);
-int ddelete(Display*);
-void dfreemem(Display*);
-int dreadctl(Display*, char*, int);
-int dwritectl(Display*, char*, int);
-void dbound(Display*, Rectangle);
-void bload(Bitmap*, Rectangle, uchar*);
-ulong bunload(Bitmap*, Rectangle, uchar*);
-void drefresh(Display*, Rectangle);
-Display *dopen(char*, int, DRefresh*);
-Bitmap* dbitmap(Display*, DRefresh*, int);
-void dclose(Display*);
-void dflush(Display*);
-void _bltinit(void);
-Bitmap* battach(Bitmap*, int, int);
-int readmouse(Mouse*);
-int atomouse(Mouse*, char*, int);
-
-/*
- * Refresh functions
- */
-DRefresh drtexture;
-DRefresh drbackstore;
--- a/os/boot/rpcg/main.c
+++ /dev/null
@@ -1,527 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "dosfs.h"
-
-typedef struct Type Type;
-typedef struct Medium Medium;
-typedef struct Mode Mode;
-
-enum {
- Dany = -1,
- Nmedia = 16,
-
- /* DS1 switch options */
- Sflashfs = 1<<0, /* take local fs from flash */
- Snotflash = 1<<1, /* don't boot from flash */
-};
-
-enum { /* type */
- Tflash,
- Tuart,
- Tether,
- Thard,
-
- Tany = -1,
-};
-
-enum { /* flag and name */
- Fnone = 0x00,
-
- Fdos = 0x01,
- Ndos = 0x00,
- Fboot = 0x02,
- Nboot = 0x01,
- Fbootp = 0x04,
- Nbootp = 0x02,
- Fflash = 0x08,
- Fuart = 0x10,
- NName = 0x03,
-
- Fany = Fbootp|Fboot|Fdos|Fflash|Fuart,
-
- Fini = 0x10,
- Fprobe = 0x80,
-};
-
-enum { /* mode */
- Mauto = 0x00,
- Mlocal = 0x01,
- Manual = 0x02,
- NMode = 0x03,
-};
-
-typedef struct Type {
- int type;
- char *cname;
- int flag;
- int (*init)(void);
- long (*read)(int, void*, long);
- long (*seek)(int, long);
- Partition* (*setpart)(int, char*);
- char* name[NName];
-
- int mask;
- Medium* media;
-} Type;
-
-typedef struct Medium {
- Type* type;
- int flag;
- Partition* partition;
- Dos;
-
- Medium* next;
-} Medium;
-
-typedef struct Mode {
- char* name;
- int mode;
-} Mode;
-
-static Type types[] = {
- { Tflash, "flash",
- Fflash,
- flashinit, 0, 0, 0,
- { 0, "F", 0, }
- },
-/*
- { Tuart, "uart",
- Fuart|Fboot,
- uartinit, uartread, uartseek, setuartpart,
- { 0, "u", 0, }
- },
-*/
- { Tether, "ether",
- Fbootp,
- etherinit, 0, 0, 0,
- { 0, 0, "e", },
- },
- { Thard, "ata",
- Fini|Fboot|Fdos,
- 0, 0, 0, 0, /* not used now, will be later with PCMCIA */
- { "hd", "h", 0, },
- },
- {-1},
-};
-
-static Medium media[Nmedia];
-static Medium *curmedium = media;
-
-static Mode modes[NMode+1] = {
- [Mauto] { "auto", Mauto, },
- [Mlocal] { "local", Mlocal, },
- [Manual] { "manual", Manual, },
-};
-
-static char *inis[] = {
- "inferno/inferno.ini",
- "inferno.ini",
- "plan9/plan9.ini",
- "plan9.ini",
- 0,
-};
-char **ini;
-int predawn;
-
-static int
-parse(char *line, int *type, int *flag, int *dev, char *file)
-{
- Type *tp;
- char buf[2*NAMELEN], *v[4], *p;
- int i;
-
- strcpy(buf, line);
- switch(getcfields(buf, v, 4, "!")){
-
- case 3:
- break;
-
- case 2:
- v[2] = "";
- break;
-
- default:
- return 0;
- }
-
- *flag = 0;
- for(tp = types; tp->cname; tp++){
- for(i = 0; i < NName; i++){
-
- if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
- continue;
- *type = tp->type;
- *flag |= 1<<i;
-
- if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
- return 0;
-
- strcpy(file, v[2]);
-
- return 1;
- }
- }
-
- return 0;
-
-}
-
-static int
-boot(Medium *mp, int flag, char *file)
-{
- Dosfile df;
- char ixdos[128], *p;
- int r;
-
- uartsetboot(0);
- if(flag & Fbootp){
- sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
- return bootp(mp->dev, file);
- }
-
- if(flag & Fflash){
- if(mp->flag & Fflash && flashbootable(0))
- flashboot(mp->dev);
- }
-
- if(flag & Fboot){
-
- if(mp->flag & Fini){
- (*mp->type->setpart)(mp->dev, "disk");
- plan9ini(mp, nil);
- }
- if(file == 0 || *file == 0)
- file = mp->partition->name;
- (*mp->type->setpart)(mp->dev, file);
- sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
- r = plan9boot(mp->dev, mp->seek, mp->read);
- uartsetboot(0);
- return r;
- }
-
- if(flag & Fdos){
- if(mp->type->setpart)
- (*mp->type->setpart)(mp->dev, "disk");
- if(mp->flag & Fini)
- plan9ini(mp, nil);
- if(file == 0 || *file == 0){
- strcpy(ixdos, *ini);
- if(p = strrchr(ixdos, '/'))
- p++;
- else
- p = ixdos;
- strcpy(p, "impc");
- if(dosstat(mp, ixdos, &df) <= 0)
- return -1;
- }
- else
- strcpy(ixdos, file);
- sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
- return dosboot(mp, ixdos);
- }
-
- return -1;
-}
-
-static Medium*
-allocm(Type *tp)
-{
- Medium **l;
-
- if(curmedium >= &media[Nmedia])
- return 0;
-
- for(l = &tp->media; *l; l = &(*l)->next)
- ;
- *l = curmedium++;
- return *l;
-}
-
-Medium*
-probe(int type, int flag, int dev)
-{
- Type *tp;
- int dombr, i, start;
- Medium *mp;
- Dosfile df;
- Partition *pp;
-
- for(tp = types; tp->cname; tp++){
- if(type != Tany && type != tp->type || tp->init == 0)
- continue;
-
- if(flag != Fnone){
- for(mp = tp->media; mp; mp = mp->next){
- if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
- return mp;
- }
- }
- if((tp->flag & Fprobe) == 0){
- tp->flag |= Fprobe;
- tp->mask = (*tp->init)();
- }
-
- for(i = 0; tp->mask; i++){
- if((tp->mask & (1<<i)) == 0)
- continue;
- tp->mask &= ~(1<<i);
-
- if((mp = allocm(tp)) == 0)
- continue;
-
- mp->dev = i;
- mp->flag = tp->flag;
- mp->seek = tp->seek;
- mp->read = tp->read;
- mp->type = tp;
-
- if(mp->flag & Fboot){
- if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
- mp->flag &= ~Fboot;
- if((mp->flag & (Fflash|Fuart)) == 0)
- (*tp->setpart)(i, "disk");
- }
-
- if(mp->flag & Fdos){
- start = 0;
- dombr = 1;
- if(mp->type->setpart){
- if(pp = (*mp->type->setpart)(i, "dos")){
- if(start = pp->start)
- dombr = 0;
- }
- (*tp->setpart)(i, "disk");
- }
- if(dosinit(mp, start, dombr) < 0)
- mp->flag &= ~(Fini|Fdos);
- else
- print("dos init failed\n");
- }
-
- if(mp->flag & Fini){
- mp->flag &= ~Fini;
- for(ini = inis; *ini; ini++){
- if(dosstat(mp, *ini, &df) <= 0)
- continue;
- mp->flag |= Fini;
- break;
- }
- }
-
- if((flag & mp->flag) && (dev == Dany || dev == i))
- return mp;
- }
- }
-
- return 0;
-}
-
-void
-main(void)
-{
- Medium *mp;
- int dev, flag, i, mode, tried, type, options;
- char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
- Type *tp;
-
- machinit();
- archinit();
- meminit();
- cpminit();
- trapinit();
- consinit(); /* screen and keyboard initially */
-/* screeninit(); */
- cpuidprint();
- alarminit();
- clockinit();
-print("predawn\n");
- predawn = 0;
- spllo();
-print("dawn\n");
- options = archoptionsw();
-print("options=#%ux\n", options);
-
- mp = 0;
- for(tp = types; tp->cname; tp++){
- if(tp->type == Tether)
- continue;
- if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
- plan9ini(mp, nil);
- break;
- }
- }
-
- if(mp == 0 || (mp->flag & Fini) == 0)
- plan9ini(nil, flashconfig(0));
-
- //consinit(); /* establish new console location */
-
- if((options & Snotflash) == 0 && flashbootable(0)){
- print("Flash boot\n");
- flashboot(0);
- }
-
- tried = 0;
- mode = Mauto;
- p = getconf("bootfile");
- flag = 0;
-
- if(p != 0) {
- mode = Manual;
- for(i = 0; i < NMode; i++){
- if(strcmp(p, modes[i].name) == 0){
- mode = modes[i].mode;
- goto done;
- }
- }
- if(parse(p, &type, &flag, &dev, file) == 0) {
- print("Bad bootfile syntax: %s\n", p);
- goto done;
- }
- mp = probe(type, flag, dev);
- if(mp == 0) {
- print("Cannot access device: %s\n", p);
- goto done;
- }
- tried = boot(mp, flag, file);
- }
-done:
- if(tried == 0 && mode != Manual){
- flag = Fany;
- if(mode == Mlocal)
- flag &= ~Fbootp;
- if(options & Snotflash)
- flag &= ~Fflash;
- if((mp = probe(Tany, flag, Dany)) != 0)
- boot(mp, flag & mp->flag, 0);
- }
-
- def[0] = 0;
- probe(Tany, Fnone, Dany);
-
- flag = 0;
- for(tp = types; tp->cname; tp++){
- for(mp = tp->media; mp; mp = mp->next){
- if(flag == 0){
- flag = 1;
- print("Boot devices:");
- }
-
- if(mp->flag & Fbootp)
- print(" %s!%d", mp->type->name[Nbootp], mp->dev);
- if(mp->flag & Fdos)
- print(" %s!%d", mp->type->name[Ndos], mp->dev);
- if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot)
- print(" %s!%d", mp->type->name[Nboot], mp->dev);
- }
- }
- if(flag)
- print("\n");
-
- for(;;){
- if(getstr("boot from", line, sizeof(line), def) >= 0){
- if(parse(line, &type, &flag, &dev, file)){
- if(mp = probe(type, flag, dev))
- boot(mp, flag, file);
- }
- }
- def[0] = 0;
- }
-}
-
-void
-machinit(void)
-{
- memset(m, 0, sizeof(*m));
- m->delayloop = 20000;
- m->cpupvr = getpvr();
- m->iomem = KADDR(INTMEM);
-}
-
-int
-getcfields(char* lp, char** fields, int n, char* sep)
-{
- int i;
-
- for(i = 0; lp && *lp && i < n; i++){
- while(*lp && strchr(sep, *lp) != 0)
- *lp++ = 0;
- if(*lp == 0)
- break;
- fields[i] = lp;
- while(*lp && strchr(sep, *lp) == 0){
- if(*lp == '\\' && *(lp+1) == '\n')
- *lp++ = ' ';
- lp++;
- }
- }
-
- return i;
-}
-
-static Map memv[512];
-static RMap rammap = {"physical memory"};
-
-void
-meminit(void)
-{
- ulong e;
-
- mapinit(&rammap, memv, sizeof(memv));
- e = PADDR(&end);
- mapfree(&rammap, e, 4*1024*1024-e); /* fixed 4Mbytes is plenty for bootstrap */
-}
-
-void*
-ialloc(ulong n, int align)
-{
- ulong a;
- int s;
-
- if(align <= 0)
- align = 4;
- s = splhi();
- a = mapalloc(&rammap, 0, n, align);
- splx(s);
- if(a == 0)
- panic("ialloc");
- return memset(KADDR(a), 0, n);
-}
-
-void*
-malloc(ulong n)
-{
- ulong *p;
-
- n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
- p = ialloc(n, sizeof(int));
- *p++ = 0xcafebeef;
- *p++ = n;
- return p;
-}
-
-void
-free(void *ap)
-{
- int s;
- ulong *p;
-
- p = ap;
- if(p){
- if(*(p -= 2) != 0xcafebeef)
- panic("free");
- s = splhi();
- mapfree(&rammap, (ulong)p, p[1]);
- splx(s);
- }
-}
-
-void
-sched(void)
-{
-}
--- a/os/boot/rpcg/mem.h
+++ /dev/null
@@ -1,94 +1,0 @@
-/*
- * Memory and machine-specific definitions. Used in C and assembler.
- */
-
-/*
- * Sizes
- */
-#define BI2BY 8 /* bits per byte */
-#define BI2WD 32 /* bits per word */
-#define BY2WD 4 /* bytes per word */
-#define BY2PG 4096 /* bytes per page */
-#define WD2PG (BY2PG/BY2WD) /* words per page */
-#define PGSHIFT 12 /* log(BY2PG) */
-#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
-
-#define MAXMACH 1 /* max # cpus system can run */
-#define CACHELINELOG 4
-#define CACHELINESZ (1<<CACHELINELOG)
-
-/*
- * Time
- */
-#define HZ (50) /* clock frequency */
-#define MS2HZ (1000/HZ) /* millisec per clock tick */
-#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
-#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
-#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
-#define MHz 1000000
-
-/*
- * Fundamental values
- */
-
-#define KZERO 0 /* bootstrap runs in real mode */
-#define MACHSIZE 4096
-
-/*
- * physical MMU
- */
-#define KSEG0 0x20000000
-#define KSEGM 0xE0000000 /* mask to check which seg */
-
-/*
- * MSR bits
- */
-
-#define POW 0x40000 /* enable power mgmt */
-#define TGPR 0x20000 /* GPR0-3 remapped; 603/603e specific */
-#define ILE 0x10000 /* interrupts little endian */
-#define EE 0x08000 /* enable external/decrementer interrupts */
-#define PR 0x04000 /* =1, user mode */
-#define FPE 0x02000 /* enable floating point */
-#define ME 0x01000 /* enable machine check exceptions */
-#define FE0 0x00800
-#define SE 0x00400 /* single-step trace */
-#define BE 0x00200 /* branch trace */
-#define FE1 0x00100
-#define IP 0x00040 /* =0, vector to nnnnn; =1, vector to FFFnnnnn */
-#define IR 0x00020 /* enable instruction address translation */
-#define DR 0x00010 /* enable data address translation */
-#define RI 0x00002 /* exception is recoverable */
-#define LE 0x00001 /* little endian mode */
-
-#define KMSR (ME|FE0|FE1|FPE)
-#define UMSR (KMSR|PR|EE|IR|DR)
-
-/*
- * MPC82x addresses
- */
-#define BCSRMEM 0xFA400000
-#define FLASHMEM 0xFFC00000
-#define INTMEM 0xFA200000
-
-#define DPRAM (INTMEM+0x2000)
-#define DPLEN1 0x400
-#define DPLEN2 0x200
-#define DPLEN3 0x100
-#define DPBASE (DPRAM+DPLEN1)
-
-#define SCC1P (INTMEM+0x3C00)
-#define I2CP (INTMEM+0x3C80)
-#define MISCP (INTMEM+0x3CB0)
-#define IDMA1P (INTMEM+0x3CC0)
-#define SCC2P (INTMEM+0x3D00)
-#define SCC3P (INTMEM+0x3E00)
-#define SCC4P (INTMEM+0x3F00)
-#define SPIP (INTMEM+0x3D80)
-#define TIMERP (INTMEM+0x3DB0)
-#define SMC1P (INTMEM+0x3E80)
-#define DSP1P (INTMEM+0x3EC0)
-#define SMC2P (INTMEM+0x3F80)
-#define DSP2P (INTMEM+0x3FC0)
-
-#define KEEP_ALIVE_KEY 0x55ccaa33 /* clock and rtc register key */
--- a/os/boot/rpcg/mkfile
+++ /dev/null
@@ -1,120 +1,0 @@
-objtype=power
-OBJTYPE=power # always
-<../../../mkconfig
-SYSTARG=$OSTARG # always
-<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
-INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin #path of directory where kernel is installed
-CONF=rpcg # selects board dependent code
-TARG=qb$CONF
-OFILES=\
- l.$O\
- arch$CONF.$O\
- devuart.$O\
- uartboot.$O\
- alarm.$O\
- bootp.$O\
- clock.$O\
- conf.$O\
- console.$O\
- cpm.$O\
- defont0.$O\
- donprint.$O\
- dosboot.$O\
- devether.$O\
- etherscc.$O\
- fblt.$O\
- gbitbltclip.$O\
- flash.$O\
- main.$O\
- i2c.$O\
- plan9boot.$O\
- qio.$O\
- rmap.$O\
- screen.$O\
- init$CONF.$O\
- trap.$O\
- zqs.$O\
-
-HFILES=\
- boot.h\
- dat.h\
- fns.h\
- io.h\
- lib.h\
- mem.h\
- squeeze.h\
- gnot.h\
- arch$CONF.h\
-
-LIBS=\
- kern\
-
-LIBDIRS=$LIBS
-LIBNAMES=${LIBS:%=lib%.a}
-LIBFILES=${LIBS:%=$ROOT/$TARGMODEL/$OBJTYPE/lib/lib%.a}
-
-#all:NV: $TARG k.mx f.mx
-all:NV: $TARG
-install:V: $INSTALLDIR/$TARG
-installall:V: $INSTALLDIR/$TARG
-
-$INSTALLDIR/%: %
- rm -f $INSTALLDIR/$stem && cp $stem $INSTALLDIR/$stem
-
-$TARG: $OFILES $LIBNAMES
- $LD -o $target -l -T0x140000 -R4 $OFILES $LIBFILES
- ls -l $target
-
-qbrom$CONF: $OFILES $LIBNAMES
- $LD -o $target -l -T0xFFC20100 -R0 -D0x140000 $OFILES $LIBFILES
-
-k.mx: $TARG
- ms2 -S 0x100 -a 0x140000 -3 -p 4 $TARG >$target
-
-f.mx: qbrom$CONF
- ms2 -S 0x100 -a 0xFFC20100 -3 -p 4 $prereq >$target
-
-g.mx: qbrom$CONF
- ms2 -S 0x100 -a 0x10000 -3 -p 4 $prereq >$target
-
-%.$O: %.s
- $AS -Dconf$CONF $stem.s
-
-%.$O: %.c
- $CC $CFLAGS $stem.c
-
-%.$O: $HFILES
-
-lib%.a:V: $SHELLTYPE-lib%.a
-
-rc-lib%.a nt-lib%.a:VQ:
- echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
- @{builtin cd $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
-
-sh-lib%.a:VQ:
- echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
- (cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
-
-clock.$O floppy.$O trap.$O: ureg.h
-conf.$O dosboot.$O main.$O: dosfs.h
-ether.$O etherscc.$O: etherif.h
-bootp.$O: ip.h
-
-clean:V:
- rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG qboot k.mx f.mx romboot
-
-nuke-sh:QV:
- for i in $LIBDIRS
- do
- echo "(cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke)"
- (cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke)
- done
-
-nuke-rc nuke-nt:QV:
- for (i in $LIBDIRS)
- {
- echo '@{cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke}'
- @{cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke}
- }
-
-nuke:V: clean nuke-$SHELLTYPE
--- a/os/boot/rpcg/ms2.c
+++ /dev/null
@@ -1,179 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <mach.h>
-
-void record(uchar*, int);
-void usage(void);
-void dosegment(long, int);
-void trailer(ulong);
-
-enum
-{
- Recordsize = 32,
-};
-
-int dsegonly;
-int supressend;
-int binary;
-int addr4;
-ulong addr;
-ulong psize = 4096;
-ulong startaddr = 0x030000;
-Biobuf stdout;
-Biobuf bio;
-
-void
-main(int argc, char **argv)
-{
- Dir dir;
- Fhdr f;
- int fd;
-
- ARGBEGIN{
- case 'd':
- dsegonly++;
- break;
- case 's':
- supressend++;
- break;
- case 'a':
- addr = strtoul(ARGF(), 0, 0);
- break;
- case 'p':
- psize = strtoul(ARGF(), 0, 0);
- break;
- case 'b':
- binary++;
- break;
- case 'S':
- startaddr = strtoul(ARGF(), 0, 0);
- break;
- case '4':
- addr4++;
- break;
- default:
- usage();
- }ARGEND
-
- if(argc != 1)
- usage();
-
- Binit(&stdout, 1, OWRITE);
-
- fd = open(argv[0], OREAD);
- if(fd < 0) {
- fprint(2, "ms2: open %s: %r\n", argv[0]);
- exits("open");
- }
-
- if(binary) {
- if(dirfstat(fd, &dir) < 0) {
- fprint(2, "ms2: stat failed %r");
- exits("dirfstat");
- }
- Binit(&bio, fd, OREAD);
- dosegment(0, dir.length);
- if(supressend == 0)
- trailer(startaddr);
- Bterm(&stdout);
- Bterm(&bio);
- exits(0);
- }
-
- if(crackhdr(fd, &f) == 0){
- fprint(2, "ms2: bad magic: %r\n");
- exits("magic");
- }
- seek(fd, 0, 0);
-
- Binit(&bio, fd, OREAD);
-
- if(dsegonly)
- dosegment(f.datoff, f.datsz);
- else {
- dosegment(f.txtoff, f.txtsz);
- addr = (addr+(psize-1))&~(psize-1);
- dosegment(f.datoff, f.datsz);
- }
-
- if(supressend == 0)
- trailer(startaddr);
-
- Bterm(&stdout);
- Bterm(&bio);
- exits(0);
-}
-
-void
-dosegment(long foff, int len)
-{
- int l, n;
- uchar buf[2*Recordsize];
-
- Bseek(&bio, foff, 0);
- for(;;) {
- l = len;
- if(l > Recordsize)
- l = Recordsize;
- n = Bread(&bio, buf, l);
- if(n == 0)
- break;
- if(n < 0) {
- fprint(2, "ms2: read error: %r\n");
- exits("read");
- }
- record(buf, l);
- len -= l;
- }
-}
-
-void
-record(uchar *s, int l)
-{
- int i;
- ulong cksum;
-
- if(addr4 || addr & (0xFF<<24)){
- Bprint(&stdout, "S3%.2X%.8luX", l+5, addr);
- cksum = l+5;
- cksum += (addr>>24)&0xff;
- }else{
- Bprint(&stdout, "S2%.2X%.6X", l+4, addr);
- cksum = l+4;
- }
- cksum += addr&0xff;
- cksum += (addr>>8)&0xff;
- cksum += (addr>>16)&0xff;
-
- for(i = 0; i < l; i++) {
- cksum += *s;
- Bprint(&stdout, "%.2X", *s++);
- }
- Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
- addr += l;
-}
-
-void
-trailer(ulong a)
-{
- ulong cksum;
-
- cksum = 0;
- if(addr4 || a & (0xFF<<24)){
- Bprint(&stdout, "S7%.8luX", a);
- cksum += (a>>24)&0xff;
- }else
- Bprint(&stdout, "S9%.6X", a);
- cksum += a&0xff;
- cksum += (a>>8)&0xff;
- cksum += (a>>16)&0xff;
- Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
-}
-
-void
-usage(void)
-{
- fprint(2, "usage: ms2 [-ds] [-a address] [-p pagesize] ?.out\n");
- exits("usage");
-}
--- a/os/boot/rpcg/plan9boot.c
+++ /dev/null
@@ -1,96 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-char *premature = "premature EOF\n";
-
-/*
- * read in a segment
- */
-static long
-readseg(int dev, long (*read)(int, void*, long), long len, long addr)
-{
- char *a;
- long n, sofar;
-
- a = (char *)addr;
- for(sofar = 0; sofar < len; sofar += n){
- n = 8*1024;
- if(len - sofar < n)
- n = len - sofar;
- n = (*read)(dev, a + sofar, n);
- if(n <= 0)
- break;
- print(".");
- }
- return sofar;
-}
-
-/*
- * boot
- */
-int
-plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
-{
- long n;
- long addr;
- void (*b)(void);
- Exec *ep;
-
- if((*seek)(dev, 0) < 0)
- return -1;
-
- /*
- * read header
- */
- ep = (Exec *) ialloc(sizeof(Exec), 0);
- n = sizeof(Exec);
- if(readseg(dev, read, n, (long) ep) != n){
- print(premature);
- return -1;
- }
- if(GLLONG(ep->magic) != Q_MAGIC){
- print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
- return -1;
- }
-
- /*
- * read text
- */
- addr = PADDR(GLLONG(ep->entry));
- n = GLLONG(ep->text);
- print("%d", n);
- if(readseg(dev, read, n, addr) != n){
- print(premature);
- return -1;
- }
-
- /*
- * read data (starts at first page after kernel)
- */
- addr = PGROUND(addr+n);
- n = GLLONG(ep->data);
- print("+%d@%8.8lux", n, addr);
- if(readseg(dev, read, n, addr) != n){
- print(premature);
- return -1;
- }
-
- /*
- * bss and entry point
- */
- print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
- uartwait();
- scc2stop();
- splhi();
-
- /*
- * Go to new code. It's up to the program to get its PC relocated to
- * the right place.
- */
- b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
- (*b)();
- return 0;
-}
binary files a/os/boot/rpcg/qbromrpcg /dev/null differ
--- a/os/boot/rpcg/qio.c
+++ /dev/null
@@ -1,128 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-struct Queue {
- Block* first;
- Block* last;
- void (*kick)(void*);
- void* arg;
- long len;
-};
-
-Block *
-iallocb(int n)
-{
- Block *b;
-
- b = (Block*)malloc(sizeof(Block)+n);
- b->data = (uchar*)b + sizeof(Block);
- b->rp = b->wp = b->data;
- b->lim = b->data + n;
- b->next = 0;
- b->magic = 0xcafebee0;
- return b;
-}
-
-void
-freeb(Block *b)
-{
- if(b){
- if(b->magic != 0xcafebee0)
- panic("freeb");
- b->magic = 0;
- b->next = (Block*)0xdeadbabe;
- free(b);
- }
-}
-
-Queue *
-qopen(int limit, int msg, void (*kick)(void*), void *arg)
-{
- Queue *q;
-
- USED(limit, msg);
- q = (Queue*)malloc(sizeof(Queue));
- q->first = q->last = 0;
- q->kick = kick;
- q->arg = arg;
- q->len = 0;
- return q;
-}
-
-Block *
-qget(Queue *q)
-{
- int s;
- Block *b;
-
- s = splhi();
- if((b = q->first) != 0){
- q->first = b->next;
- b->next = 0;
- q->len -= BLEN(b);
- if(q->len < 0)
- panic("qget");
- }
- splx(s);
- return b;
-}
-
-void
-qbwrite(Queue *q, Block *b)
-{
- int s;
-
- s = splhi();
- b->next = 0;
- if(q->first == 0)
- q->first = b;
- else
- q->last->next = b;
- q->last = b;
- q->len += BLEN(b);
- splx(s);
- if(q->kick)
- q->kick(q->arg);
-}
-
-long
-qlen(Queue *q)
-{
- return q->len;
-}
-
-int
-qbgetc(Queue *q)
-{
- Block *b;
- int s, c;
-
- c = -1;
- s = splhi();
- while(c < 0 && (b = q->first) != nil){
- if(b->rp < b->wp){
- c = *b->rp++;
- q->len--;
- }
- if(b->rp >= b->wp){
- q->first = b->next;
- b->next = nil;
- }
- }
- splx(s);
- return c;
-}
-
-void
-qbputc(Queue *q, int c)
-{
- Block *b;
-
- b = iallocb(1);
- *b->wp++ = c;
- qbwrite(q, b);
-}
--- a/os/boot/rpcg/rmap.c
+++ /dev/null
@@ -1,104 +1,0 @@
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-void
-mapinit(RMap *rmap, Map *map, int size)
-{
- lock(rmap);
- rmap->map = map;
- rmap->mapend = map+(size/sizeof(Map));
- unlock(rmap);
-}
-
-void
-mapfree(RMap* rmap, ulong addr, int size)
-{
- Map *mp;
- ulong t;
-
- if(size <= 0)
- return;
-
- lock(rmap);
- for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
- ;
-
- if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
- (mp-1)->size += size;
- if(addr+size == mp->addr){
- (mp-1)->size += mp->size;
- while(mp->size){
- mp++;
- (mp-1)->addr = mp->addr;
- (mp-1)->size = mp->size;
- }
- }
- }
- else{
- if(addr+size == mp->addr && mp->size){
- mp->addr -= size;
- mp->size += size;
- }
- else do{
- if(mp >= rmap->mapend){
- print("mapfree: %s: losing 0x%uX, %d\n",
- rmap->name, addr, size);
- break;
- }
- t = mp->addr;
- mp->addr = addr;
- addr = t;
- t = mp->size;
- mp->size = size;
- mp++;
- }while(size = t);
- }
- unlock(rmap);
-}
-
-ulong
-mapalloc(RMap* rmap, ulong addr, int size, int align)
-{
- Map *mp;
- ulong maddr, oaddr;
-
- lock(rmap);
- for(mp = rmap->map; mp->size; mp++){
- maddr = mp->addr;
-
- if(addr){
- if(maddr > addr)
- continue;
- if(addr+size > maddr+mp->size)
- break;
- maddr = addr;
- }
-
- if(align > 0)
- maddr = ((maddr+align-1)/align)*align;
- if(mp->addr+mp->size-maddr < size)
- continue;
-
- oaddr = mp->addr;
- mp->addr = maddr+size;
- mp->size -= maddr-oaddr+size;
- if(mp->size == 0){
- do{
- mp++;
- (mp-1)->addr = mp->addr;
- }while((mp-1)->size = mp->size);
- }
-
- unlock(rmap);
- if(oaddr != maddr)
- mapfree(rmap, oaddr, maddr-oaddr);
-
- return maddr;
- }
- unlock(rmap);
-
- return 0;
-}
--- a/os/boot/rpcg/screen.c
+++ /dev/null
@@ -1,242 +1,0 @@
-#include "all.h"
-#include <libg.h>
-#include <gnot.h>
-
-enum {
- Colldepth = 3,
- Colmaxx = 640,
- Colmaxxvis = 640,
- Colmaxy = 480,
-};
-
-#define MINX 8
-
-extern GSubfont defont0;
-
-struct{
- Point pos;
- int bwid;
-}out;
-
-typedef struct Mode Mode;
-struct Mode {
- int x;
- int y;
- int d;
- char* aperture;
- int apsize;
-};
-
-GBitmap gscreen;
-Point gchar(GBitmap*, Point, GFont*, int, Fcode);
-int setcolor(ulong, ulong, ulong, ulong);
-static void lcdinit(Mode*);
-
-void
-screeninit(void)
-{
- Mode m;
-
- m.x = Colmaxx;
- m.y = Colmaxy;
- m.d = Colldepth;
- m.aperture = 0;
- lcdinit(&m);
- if(m.aperture == 0)
- return;
- gscreen.ldepth = 3;
- gscreen.base = (ulong*)m.aperture;
- gscreen.width = Colmaxx/BY2WD;
- gscreen.r = Rect(0, 0, Colmaxxvis, Colmaxy);
- gscreen.clipr = gscreen.r;
- /*
- * For now, just use a fixed colormap:
- * 0 == white and 255 == black
- */
- setcolor(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
- setcolor(255, 0x00000000, 0x00000000, 0x00000000);
-
- gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, Zero);
- out.pos.x = MINX;
- out.pos.y = 0;
- out.bwid = defont0.info[' '].width;
-}
-
-void
-screenputc(int c)
-{
- Fontchar *i;
- Point p;
-
- if(gscreen.base == nil)
- return;
- switch(c){
- case '\n':
- out.pos.x = MINX;
- out.pos.y += defont0.height;
- if(out.pos.y > gscreen.r.max.y-defont0.height)
- out.pos.y = gscreen.r.min.y;
- gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
- Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height),
- Zero);
- break;
- case '\t':
- out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
- if(out.pos.x >= gscreen.r.max.x)
- screenputc('\n');
- break;
- case '\b':
- if(out.pos.x >= out.bwid+MINX){
- out.pos.x -= out.bwid;
- screenputc(' ');
- out.pos.x -= out.bwid;
- }
- break;
- default:
- if(out.pos.x >= gscreen.r.max.x-out.bwid)
- screenputc('\n');
- c &= 0x7f;
- if(c <= 0 || c >= defont0.n)
- break;
- i = defont0.info + c;
- p = out.pos;
- gbitblt(&gscreen, Pt(p.x+i->left, p.y), defont0.bits,
- Rect(i[0].x, 0, i[1].x, defont0.height),
- S);
- out.pos.x = p.x + i->width;
- break;
- }
-}
-
-void
-screenputs(char *s, int n)
-{
- while(n-- > 0)
- screenputc(*s++);
-}
-
-/*
- * See section 5.2.1 (page 5-6) of the MPC823 manual
- */
-static uchar lcdclock[17] = { /* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */
- 0, 0, (1<<2), 1,
- (2<<2), 2, (1<<2)|1, 3,
- (3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1,
- (2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2),
- (4<<2)
-};
-
-/*
- * support for the Sharp LQ64D341 TFT colour display
- */
-
-enum {
- COLS = 640,
- ROWS = 480,
- LDEPTH = 3, /* screen depth */
- LCDFREQ = 25000000,
-
- /* lccr */
- ClockLow = 1<<11,
- OELow = 1<<10,
- HsyncLow = 1<<9,
- VsyncLow = 1<<8,
- DataLow = 1<<7,
- Passive8 = 1<<4,
- DualScan = 1<<3,
- IsColour = 1<<2,
- IsTFT = 1<<1,
- Enable = 1<<0,
-
- /* lchcr */
- BigEndian = 1<<24,
- AT7 = 7<<21, /* access type */
-
- /* sdcr */
- LAM = 1<<6, /* ``LCD aggressive mode'' */
-};
-
-/*
- * TO DO: most of the data could come from a table
- */
-static void
-lcdinit(Mode *mode)
-{
- IMM *io;
- int i, d;
- long hz;
-
- io = m->iomem;
- mode->y = ROWS;
- mode->x = COLS;
- mode->d = LDEPTH;
- mode->aperture = ialloc(mode->x*mode->y, 16);
- mode->apsize = mode->x*mode->y;
-
- io->sdcr &= ~LAM; /* MPC823 errata: turn off LAM before disabling controller */
- io->lcfaa = PADDR(mode->aperture);
- io->lccr = (((mode->x*mode->y*(1<<LDEPTH)+127)/128) << 17) | (LDEPTH << 5) | IsColour | IsTFT | OELow | VsyncLow | ClockLow;
-
- switch(LDEPTH){
- default:
- case 0:
- /* monochrome/greyscale identity map */
- for(i=0; i<16; i++)
- io->lcdmap[i] = i;
- break;
- case 2:
- /* 4-bit grey scale map */
- for(i=0; i<16; i++)
- io->lcdmap[0] = (i<<8)|(i<<4)|i;
- break;
- case 3:
- /* 8-bit linear map */
- for(i=0; i<256; i++)
- io->lcdmap[i] = (i<<8)|(i<<4)|i;
- break;
- }
-
- io->lcvcr = (mode->y << 11) | (1<<28) | 33; /* 2 line vsync pulse, 34 line wait between frames */
- io->lchcr = (mode->x<<10) | BigEndian | 228; /* clock cycles between lines */
-
- hz = m->cpuhz;
- d = hz/LCDFREQ;
- if(hz/d > LCDFREQ)
- d++;
- if(d >= 16)
- d = 16;
-
- /*
- * enable LCD outputs
- */
- io->pddat = 0;
- io->pdpar = 0x1fff;
-io->pdpar &= ~SIBIT(6); /* 823 bug fix? */
- io->pddir = 0x1fff;
- io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17);
- io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17);
- io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17));
-
- eieio();
- io->sccrk = KEEP_ALIVE_KEY;
- eieio();
- io->sccr = (io->sccr & ~0x1F) | lcdclock[d];
- eieio();
- io->sccrk = ~KEEP_ALIVE_KEY;
- eieio();
- gscreen.width = gscreen.width; /* access external memory before enabling (mpc823 errata) */
- io->lcsr = 7; /* clear status */
- eieio();
- io->lccr |= Enable;
- archbacklight(1);
-}
-
-int
-setcolor(ulong p, ulong r, ulong g, ulong b)
-{
- r >>= 28;
- g >>= 28;
- b >>= 28;
- m->iomem->lcdmap[~p&0xFF] = (r<<8) | (g<<4) | b; /* TO DO: it's a function of the ldepth */
- return 1;
-}
binary files a/os/boot/rpcg/sload /dev/null differ
--- a/os/boot/rpcg/sload.c
+++ /dev/null
@@ -1,71 +1,0 @@
-/*
- * send S records to rpcg
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-static int dbg;
-static char buf[2048];
-static int run=1;
-static void stuffbym(char*, int, int);
-static void getdot(void);
-
-void
-main(int argc, char **argv)
-{
- int n;
- char *l;
- Biobuf *f;
- static int p;
-
- ARGBEGIN{
- case 'd': dbg++; break;
- case 'n': run=0; break;
- }ARGEND
-
- f = Bopen(*argv? *argv: "k.mx", OREAD);
- if(f == 0) {
- fprint(2, "sload: cannot open k.mx: %r\n");
- exits("sload");
- }
- getdot();
- while((l = Brdline(f, '\n')) != 0) {
- l[Blinelen(f)-1] = '\r';
- stuffbym(l, Blinelen(f), 16);
- getdot();
- if(++p % 25 == 0)
- write(2, ".", 1);
- }
- exits(0);
-}
-
-static void
-stuffbym(char *l, int n, int m)
-{
- int nr, ns;
-
- while(n > 0) {
- ns = n;
- if(ns > m)
- ns = m;
- write(1, l, ns);
- l += ns;
- n -= ns;
- }
-}
-
-static void
-getdot(void)
-{
- char c;
-
- for(;;){
- if(read(0, &c, 1) != 1)
- exits("bang");
- write(2, &c, 1);
- if(c == '.')
- break;
- }
-}
--- a/os/boot/rpcg/squeeze.h
+++ /dev/null
@@ -1,34 +1,0 @@
-
-/*
- * squeezed file format:
- * Sqhdr
- * original Exec header
- * two Squeeze tables
- * squeezed segment
- * unsqueezed segment, if any
- */
-#define SQMAGIC (ulong)0xFEEF0F1E
-
-typedef struct Sqhdr Sqhdr;
-struct Sqhdr {
- uchar magic[4]; /* SQMAGIC */
- uchar text[4]; /* squeezed length of text (excluding tables) */
- uchar data[4]; /* squeezed length of data (excluding tables) */
- uchar asis[4]; /* length of unsqueezed segment */
- uchar toptxt[4]; /* value for 0 encoding in text */
- uchar topdat[4]; /* value for 0 encoding in data */
- uchar sum[4]; /* simple checksum of unsqueezed data */
- uchar flags[4];
-};
-#define SQHDRLEN (8*4)
-
-/*
- * certain power instruction types are rearranged by sqz
- * so as to move the variable part of the instruction word to the
- * low order bits. note that the mapping is its own inverse.
- */
-#define QREMAP(X)\
- switch((X)>>26){\
- case 19: case 31: case 59: case 63:\
- (X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
- }
--- a/os/boot/rpcg/trap.c
+++ /dev/null
@@ -1,233 +1,0 @@
-#include "boot.h"
-
-enum
-{
- Maxhandler= 32+16, /* max number of interrupt handlers */
-};
-
-typedef struct Handler Handler;
-struct Handler
-{
- void (*r)(Ureg*, void*);
- void *arg;
- Handler *next;
- int edge;
-};
-
-struct
-{
- Handler *ivec[128];
- Handler h[Maxhandler];
- int free;
-} halloc;
-
-char *excname[] = {
- "reserved 0",
- "system reset",
- "machine check",
- "data access",
- "instruction access",
- "external interrupt",
- "alignment",
- "program exception",
- "floating-point unavailable",
- "decrementer",
- "reserved A",
- "reserved B",
- "system call",
- "trace trap",
- "floating point assist",
- "reserved F",
- "software emulation",
- "ITLB miss",
- "DTLB miss",
- "ITLB error",
- "DTLB error",
-};
-
-char *regname[]={
- "CAUSE", "SRR1",
- "PC", "GOK",
- "LR", "CR",
- "XER", "CTR",
- "R0", "R1",
- "R2", "R3",
- "R4", "R5",
- "R6", "R7",
- "R8", "R9",
- "R10", "R11",
- "R12", "R13",
- "R14", "R15",
- "R16", "R17",
- "R18", "R19",
- "R20", "R21",
- "R22", "R23",
- "R24", "R25",
- "R26", "R27",
- "R28", "R29",
- "R30", "R31",
-};
-
-static void intr(Ureg*);
-
-void
-sethvec(int v, void (*r)(void))
-{
- ulong *vp, pa, o;
-
- if((ulong)r & 3)
- panic("sethvec");
- vp = (ulong*)KADDR(v);
- vp[0] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */
- vp[1] = 0x7c0802a6; /* MOVW LR, R0 */
- vp[2] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */
- pa = PADDR(r);
- o = pa >> 25;
- if(o != 0 && o != 0x7F){
- /* a branch too far: running from ROM */
- vp[3] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
- vp[4] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
- vp[5] = 0x7c0803a6; /* MOVW R0, LR */
- vp[6] = 0x4e800021; /* BL (LR) */
- }else
- vp[3] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
-}
-
-#define LEV(n) (((n)<<1)|1)
-#define IRQ(n) (((n)<<1)|0)
-
-void
-setvec(int v, void (*r)(Ureg*, void*), void *arg)
-{
- Handler *h;
- IMM *io;
-
- if(halloc.free >= Maxhandler)
- panic("out of interrupt handlers");
- v -= VectorPIC;
- h = &halloc.h[halloc.free++];
- h->next = halloc.ivec[v];
- h->r = r;
- h->arg = arg;
- halloc.ivec[v] = h;
-
- /*
- * enable corresponding interrupt in SIU/CPM
- */
-
- io = m->iomem;
- if(v >= VectorCPIC){
- v -= VectorCPIC;
- io->cimr |= 1<<(v&0x1F);
- }
- else if(v >= VectorIRQ)
- io->simask |= 1<<(31-IRQ(v&7));
- else
- io->simask |= 1<<(31-LEV(v));
-}
-
-void
-trapinit(void)
-{
- int i;
- IMM *io;
-
- io = m->iomem;
- io->sypcr &= ~(3<<2); /* disable watchdog (821/823) */
- io->simask = 0; /* mask all */
- io->siel = ~0; /* edge sensitive, wake on all */
- io->cicr = 0; /* disable CPM interrupts */
- io->cipr = ~0; /* clear all interrupts */
- io->cimr = 0; /* mask all events */
- io->cicr = (0xE1<<16)|(CPIClevel<<13)|(0x1F<<8);
- io->cicr |= 1 << 7; /* enable */
- io->tbscrk = KEEP_ALIVE_KEY;
- io->tbscr = 1; /* TBE */
- io->simask |= 1<<(31-LEV(CPIClevel)); /* CPM's level */
- io->tbk = KEEP_ALIVE_KEY;
- eieio();
- putdec(~0);
-
- /*
- * set all exceptions to trap
- */
- for(i = 0x0; i < 0x3000; i += 0x100)
- sethvec(i, exception);
-}
-
-void
-dumpregs(Ureg *ur)
-{
- int i;
- ulong *l;
- l = &ur->cause;
- for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
- print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
-}
-
-void
-trap(Ureg *ur)
-{
- int c;
-
- c = ur->cause >> 8;
- switch(c){
- default:
- {extern int predawn; predawn = 1;}
- if(c < 0 || c >= nelem(excname))
- print("exception/interrupt #%x\n", c);
- else
- print("exception %s\n", excname[c]);
- dumpregs(ur);
- /* spllo(); */
- print("^P to reset\n");
- for(;;)
- ;
-
- case 0x09: /* decrementer */
- clockintr(ur, 0);
- return;
-
- case 0x05: /* external interrupt */
- intr(ur);
- break;
- }
-}
-
-static void
-intr(Ureg *ur)
-{
- int b, v;
- Handler *h;
- IMM *io;
-
- io = m->iomem;
- b = io->sivec>>2;
- v = b>>1;
- if(b & 1) {
- if(v == CPIClevel){
- io->civr = 1;
- eieio();
- v = VectorCPIC+(io->civr>>11);
- }
- }else
- v += VectorIRQ;
- h = halloc.ivec[v];
- if(h == nil){
- for(;;)
- ;
- //print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
- return;
- }
- if(h->edge)
- io->sipend |= 1<<(31-b);
- /*
- * call the interrupt handlers
- */
- do {
- (*h->r)(ur, h->arg);
- h = h->next;
- } while(h != nil);
- if(v >= VectorCPIC)
- io->cisr |= 1<<(v-VectorCPIC);
-}
--- a/os/boot/rpcg/uartboot.c
+++ /dev/null
@@ -1,189 +1,0 @@
-#include "boot.h"
-
-/*
- * this doesn't yet use the crc
- */
-
-typedef struct Uboot Uboot;
-struct Uboot {
- Queue* iq;
- Block* partial;
- ulong csum;
- long bno;
- uchar buf[64];
- int nleft;
- int ntimeout;
-};
-
-static Uboot uboot;
-ulong crc32(void *buf, int n, ulong crc);
-
-static void
-uartbrecv(uchar *p, int n)
-{
- Uboot *ub;
- Block *b;
-
- ub = &uboot;
- if(n > 0 && ub->iq != nil){
- b = iallocb(n);
- memmove(b->wp, p, n);
- b->wp += n;
- qbwrite(ub->iq, b);
- }
-}
-
-int
-uartinit(void)
-{
- return 1<<0;
-}
-
-Partition*
-setuartpart(int, char *s)
-{
- static Partition pp[1];
-
- if(strcmp(s, "boot") != 0 && strcmp(s, "disk") != 0)
- return 0;
- pp[0].start = 0;
- pp[0].end = 2*1024*1024;
- strcpy(pp[0].name, "boot");
- return pp;
-}
-
-long
-uartseek(int, long)
-{
- /* start the boot */
- if(uboot.iq == nil)
- uboot.iq = qopen(64*1024, 0, 0, 0);
- if(uboot.partial){
- freeb(uboot.partial);
- uboot.partial = 0;
- }
- print("uart: start transmission\n");
- uartsetboot(uartbrecv);
- uboot.csum = ~0;
- uboot.bno = 0;
- uboot.nleft = 0;
- uboot.ntimeout = 0;
- return 0;
-}
-
-static long
-uartreadn(void *buf, int nb)
-{
- ulong start;
- Uboot *ub;
- int l;
- Block *b;
- uchar *p;
-
- p = buf;
- ub = &uboot;
- start = m->ticks;
- while(nb > 0){
- b = ub->partial;
- ub->partial = nil;
- if(b == nil){
- ub->ntimeout = 0;
- while((b = qget(ub->iq)) == 0){
- if(TK2MS(m->ticks - start) >= 15*1000){
- if(++ub->ntimeout >= 3){
- print("uart: timeout\n");
- return 0;
- }
- uartputs("n", 1);
- }
- }
- }
- l = BLEN(b);
- if(l > nb)
- l = nb;
- memmove(p, b->rp, l);
- b->rp += l;
- if(b->rp >= b->wp)
- freeb(b);
- else
- ub->partial = b;
- nb -= l;
- p += l;
- }
- return p-(uchar*)buf;
-}
-
-long
-uartread(int, void *buf, long n)
-{
- uchar *p;
- int l;
- static uchar lbuf[64];
-
- p = buf;
- if((l = uboot.nleft) > 0){
- if(l > n)
- l = n;
- uboot.nleft -= l;
- memmove(p, uboot.buf, l);
- p += l;
- n -= l;
- }
- while(n > 0){
- l = uartreadn(lbuf, sizeof(lbuf));
- if(l < sizeof(lbuf))
- return 0;
- if(l > n){
- uboot.nleft = l-n;
- memmove(uboot.buf, lbuf+n, uboot.nleft);
- l = n;
- }
- memmove(p, lbuf, l);
- n -= l;
- p += l;
- uboot.bno++;
- uartputs("y", 1);
- }
- return p-(uchar*)buf;
-}
-
-/*
- * from Rob Warnock
- */
-static ulong crc32tab[256]; /* initialised on first call to crc32 */
-
-enum {
- CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
-};
-
-/*
- * Build auxiliary table for parallel byte-at-a-time CRC-32.
- */
-static void
-initcrc32(void)
-{
- int i, j;
- ulong c;
-
- for(i = 0; i < 256; i++) {
- for(c = i << 24, j = 8; j > 0; j--)
- if(c & (1<<31))
- c = (c<<1) ^ CRC32POLY;
- else
- c <<= 1;
- crc32tab[i] = c;
- }
-}
-
-ulong
-crc32(void *buf, int n, ulong crc)
-{
- uchar *p;
-
- if(crc32tab[1] == 0)
- initcrc32();
- crc = ~crc;
- for(p = buf; --n >= 0;)
- crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
- return ~crc;
-}
--- a/os/boot/rpcg/ureg.h
+++ /dev/null
@@ -1,43 +1,0 @@
-struct Ureg
-{
- ulong cause;
- union { ulong srr1; ulong status;};
- ulong pc; /* SRR0 */
- ulong pad;
- ulong lr;
- ulong cr;
- ulong xer;
- ulong ctr;
- ulong r0;
- union{ ulong r1; ulong sp; ulong usp; };
- ulong r2;
- ulong r3;
- ulong r4;
- ulong r5;
- ulong r6;
- ulong r7;
- ulong r8;
- ulong r9;
- ulong r10;
- ulong r11;
- ulong r12;
- ulong r13;
- ulong r14;
- ulong r15;
- ulong r16;
- ulong r17;
- ulong r18;
- ulong r19;
- ulong r20;
- ulong r21;
- ulong r22;
- ulong r23;
- ulong r24;
- ulong r25;
- ulong r26;
- ulong r27;
- ulong r28;
- ulong r29;
- ulong r30;
- ulong r31;
-};
--- a/os/boot/rpcg/zqs.c
+++ /dev/null
@@ -1,234 +1,0 @@
-#include "boot.h"
-#include "squeeze.h"
-
-/*
- * for details of `unsqueeze' see:
- *
- * %A Mark Taunton
- * %T Compressed Executables: An Exercise in Thinking Small
- * %P 385-404
- * %I USENIX
- * %B USENIX Conference Proceedings
- * %D Summer 1991
- * %C Nashville, TN
- *
- * several of the unimplemented improvements described in the paper
- * have been implemented here
- *
- * there is a further transformation on the powerpc (QFLAG!=0) to shuffle bits
- * in certain instructions so as to push the fixed bits to the top of the word.
- */
-
-#define EXECHDRLEN (8*4)
-
-typedef struct Squeeze Squeeze;
-struct Squeeze {
- int n;
- ulong tab[7*256];
-};
-
-#define GET4(p) (((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
-
-/*
- * for speed of unsqueezing from Flash, certain checks are
- * not done inside the loop (as they would be in the unsqueeze program zqs),
- * but instead the checksum is expected to catch corrupted files.
- * in fact the Squeeze array bounds can't be exceeded in practice
- * because the tables are always full for a squeezed kernel.
- */
-enum {
- QFLAG = 1, /* invert powerpc-specific code transformation */
- CHECK = 0, /* check precise bounds in Squeeze array (otherwise checksum detects error) */
-};
-
-static ulong chksum;
-static int rdtab(Block*, Squeeze*, int);
-static ulong* unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
-static uchar* unsqzseg(uchar*, Block*, long, long, char*);
-static Alarm* unsqzal;
-
-int
-issqueezed(uchar *b)
-{
- return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
-}
-
-static void
-unsqzdot(Alarm*)
-{
- unsqzal = alarm(500, unsqzdot, nil);
- print(".");
-}
-
-long
-unsqueezef(Block *b, ulong *entryp)
-{
- uchar *loada, *wp;
- ulong toptxt, topdat, oldsum;
- long asis, nst, nsd;
- Sqhdr *sqh;
- Exec *ex;
-
- if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
- return -1;
- sqh = (Sqhdr*)b->rp;
- if(GET4(sqh->magic) != SQMAGIC)
- return -1;
- chksum = 0;
- toptxt = GET4(sqh->toptxt);
- topdat = GET4(sqh->topdat);
- oldsum = GET4(sqh->sum);
- asis = GET4(sqh->asis);
- nst = GET4(sqh->text);
- nsd = GET4(sqh->data);
- b->rp += SQHDRLEN;
- ex = (Exec*)b->rp;
- if(GET4(ex->magic) != Q_MAGIC){
- print("zqs: not powerPC executable\n");
- return -1;
- }
- *entryp = GET4(ex->entry);
- b->rp += EXECHDRLEN;
- loada = KADDR(PADDR(*entryp));
- wp = unsqzseg(loada, b, nst, toptxt, "text");
- if(wp == nil){
- print("zqs: format error\n");
- return -1;
- }
- if(nsd){
- wp = (uchar*)PGROUND((ulong)wp);
- wp = unsqzseg(wp, b, nsd, topdat, "data");
- if(wp == nil){
- print("zqs: format error\n");
- return -1;
- }
- }
- if(asis){
- memmove(wp, b->rp, asis);
- wp += asis;
- b->rp += asis;
- }
- if(chksum != oldsum){
- print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
- return -1;
- }
- return wp-loada;
-}
-
-static uchar *
-unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
-{
- static Squeeze sq3, sq4;
-
- print("unpack %s %8.8lux %lud:", what, wp, ns);
- if(ns == 0)
- return wp;
- if(rdtab(b, &sq3, 0) < 0)
- return nil;
- if(rdtab(b, &sq4, 8) < 0)
- return nil;
- if(BLEN(b) < ns){
- print(" **size error\n");
- return nil;
- }
- unsqzal = alarm(500, unsqzdot, nil);
- wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
- cancel(unsqzal);
- unsqzal = nil;
- print("\n");
- if(wp == nil){
- print("zqs: corrupt squeezed data stream\n");
- return nil;
- }
- b->rp += ns;
- return wp;
-}
-
-static ulong*
-unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
-{
- ulong nx, csum;
- int code, n;
-
- if(QFLAG){
- QREMAP(top); /* adjust top just once, outside the loop */
- }
- csum = chksum;
- while(rp < ep){
- /* no function calls within this loop for speed */
- code = *rp;
- rp++;
- n = 0;
- nx = code>>4;
- do{
- if(nx == 0){
- nx = top;
- }else{
- if(nx==1){
- nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
- rp += 4;
- }else if(nx <= 8){ /* 2 to 8 */
- nx = ((nx-2)<<8) | rp[0];
- if(CHECK && nx >= sq4->n)
- return nil; /* corrupted file */
- nx = sq4->tab[nx] | rp[1];
- rp += 2;
- }else{ /* 9 to 15 */
- nx = ((nx-9)<<8) | rp[0];
- if(CHECK && nx >= sq3->n)
- return nil; /* corrupted file */
- nx = sq3->tab[nx];
- rp++;
- }
- if(rp > ep)
- return nil; /* corrupted file */
- if(QFLAG){
- QREMAP(nx);
- }
- }
- *wp = nx;
- wp++;
- csum += nx;
- nx = code & 0xF;
- }while(++n == 1);
- }
- chksum = csum;
- return wp;
-}
-
-static int
-rdtab(Block *b, Squeeze *sq, int shift)
-{
- uchar *p, *ep;
- ulong v, w;
- int i;
-
- if(BLEN(b) < 2)
- return -1;
- i = (b->rp[0]<<8) | b->rp[1];
- if(1)
- print(" T%d", i);
- b->rp += 2;
- if((i -= 2) > 0){
- if(BLEN(b) < i)
- return -1;
- }
- sq->n = 0;
- p = b->rp;
- ep = b->rp+i;
- b->rp += i;
- v = 0;
- while(p < ep){
- w = 0;
- do{
- if(p >= ep)
- return -1;
- w = (w<<7) | (*p & 0x7F);
- }while(*p++ & 0x80);
- v += w;
- if(0)
- print("%d %8.8lux %8.8lux\n", sq->n, v, w);
- sq->tab[sq->n++] = v<<shift;
- }
- return 0;
-}
--- /dev/null
+++ b/os/boot.original/README
@@ -1,0 +1,33 @@
+Often the devices we use now come with some
+form of bootstrap (often annoyingly complicated,
+which gets in the way). Older boards were sometimes
+bare, and we had to provide something (often annoyingly
+complicated...). On the PC it's currently helpful to
+have something that can boot from disc or ether;
+since it's a thankless task to write such a thing, we
+use Plan 9's, and thank its authors.
+
+The current scheme on newer devices is to have a simple
+program that can put a stripped-down Inferno kernel into
+flash, and use that to boot from other devices (including over the net)
+as required during development.
+
+There are two distinct models for bootstrap in this directory.
+
+ Model I
+
+Each member of the first model is represented by a self-contained directory.
+They are derived from various ages of Plan 9's /sys/src/boot/pc.
+
+arm1110 arm a prefix to a gzip'd kernel to decompress it (runs after basic bootloader)
+pc 386 pc-specific bootstrap essentially identical to current Plan 9
+ and covered by the Lucent Public License; it uses
+libflate - zlib-style inflate/deflate library
+mpc power PowerPC bootstrap for FADS board derived from an older version
+ of Plan 9 but covered by our Inferno licence (because it came with Inferno)
+puma arm SA110 bootstrap for Teralogics Puma, also covered by the Inferno licence
+
+ Model II
+omap purpose-built bootstrap for the OMAP processor
+
+Not all of these are being distributed.
--- /dev/null
+++ b/os/boot.original/arm1110/Mk
@@ -1,0 +1,8 @@
+#!/bin/rc
+rfork ne
+ROOT=/usr/inferno
+fn cd
+NPROC=3
+path=(/usr/inferno/Plan9/$cputype/bin $path)
+#bind /usr/inferno/mkconfig.dist /usr/inferno/mkconfig
+exec mk $*
--- /dev/null
+++ b/os/boot.original/arm1110/dat.h
@@ -1,0 +1,1 @@
+/* deliberately empty */
--- /dev/null
+++ b/os/boot.original/arm1110/donprint.c
@@ -1,0 +1,332 @@
+#include "u.h"
+#include "lib.h"
+
+#define PTR sizeof(char*)
+#define SHORT sizeof(int)
+#define INT sizeof(int)
+#define LONG sizeof(long)
+#define IDIGIT 30
+#define MAXCON 30
+
+#define FLONG (1<<0)
+#define FSHORT (1<<1)
+#define FUNSIGN (1<<2)
+
+typedef struct Op Op;
+struct Op
+{
+ char *p;
+ char *ep;
+ void *argp;
+ int f1;
+ int f2;
+ int f3;
+};
+
+static int noconv(Op*);
+static int cconv(Op*);
+static int dconv(Op*);
+static int hconv(Op*);
+static int lconv(Op*);
+static int oconv(Op*);
+static int sconv(Op*);
+static int uconv(Op*);
+static int xconv(Op*);
+static int Xconv(Op*);
+static int percent(Op*);
+
+static
+int (*fmtconv[MAXCON])(Op*) =
+{
+ noconv,
+ cconv, dconv, hconv, lconv,
+ oconv, sconv, uconv, xconv,
+ Xconv, percent,
+};
+static
+char fmtindex[128] =
+{
+ ['c'] 1,
+ ['d'] 2,
+ ['h'] 3,
+ ['l'] 4,
+ ['o'] 5,
+ ['s'] 6,
+ ['u'] 7,
+ ['x'] 8,
+ ['X'] 9,
+ ['%'] 10,
+};
+
+static int convcount = { 11 };
+static int ucase;
+
+static void
+PUT(Op *o, int c)
+{
+ static int pos;
+ int opos;
+
+ if(c == '\t'){
+ opos = pos;
+ pos = (opos+8) & ~7;
+ while(opos++ < pos && o->p < o->ep)
+ *o->p++ = ' ';
+ return;
+ }
+ if(o->p < o->ep){
+ *o->p++ = c;
+ pos++;
+ }
+ if(c == '\n')
+ pos = 0;
+}
+
+int
+fmtinstall(char c, int (*f)(Op*))
+{
+
+ c &= 0177;
+ if(fmtindex[c] == 0) {
+ if(convcount >= MAXCON)
+ return 1;
+ fmtindex[c] = convcount++;
+ }
+ fmtconv[fmtindex[c]] = f;
+ return 0;
+}
+
+char*
+donprint(char *p, char *ep, char *fmt, void *argp)
+{
+ int sf1, c;
+ Op o;
+
+ o.p = p;
+ o.ep = ep;
+ o.argp = argp;
+
+loop:
+ c = *fmt++;
+ if(c != '%') {
+ if(c == 0) {
+ if(o.p < o.ep)
+ *o.p = 0;
+ return o.p;
+ }
+ PUT(&o, c);
+ goto loop;
+ }
+ o.f1 = 0;
+ o.f2 = -1;
+ o.f3 = 0;
+ c = *fmt++;
+ sf1 = 0;
+ if(c == '-') {
+ sf1 = 1;
+ c = *fmt++;
+ }
+ while(c >= '0' && c <= '9') {
+ o.f1 = o.f1*10 + c-'0';
+ c = *fmt++;
+ }
+ if(sf1)
+ o.f1 = -o.f1;
+ if(c != '.')
+ goto l1;
+ c = *fmt++;
+ while(c >= '0' && c <= '9') {
+ if(o.f2 < 0)
+ o.f2 = 0;
+ o.f2 = o.f2*10 + c-'0';
+ c = *fmt++;
+ }
+l1:
+ if(c == 0)
+ fmt--;
+ c = (*fmtconv[fmtindex[c&0177]])(&o);
+ if(c < 0) {
+ o.f3 |= -c;
+ c = *fmt++;
+ goto l1;
+ }
+ o.argp = (char*)o.argp + c;
+ goto loop;
+}
+
+void
+strconv(char *o, Op *op, int f1, int f2)
+{
+ int n, c;
+ char *p;
+
+ n = strlen(o);
+ if(f1 >= 0)
+ while(n < f1) {
+ PUT(op, ' ');
+ n++;
+ }
+ for(p=o; c = *p++;)
+ if(f2 != 0) {
+ PUT(op, c);
+ f2--;
+ }
+ if(f1 < 0) {
+ f1 = -f1;
+ while(n < f1) {
+ PUT(op, ' ');
+ n++;
+ }
+ }
+}
+
+int
+numbconv(Op *op, int base)
+{
+ char b[IDIGIT];
+ int i, f, n, r;
+ long v;
+ short h;
+
+ f = 0;
+ switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
+ case FLONG:
+ v = *(long*)op->argp;
+ r = LONG;
+ break;
+
+ case FUNSIGN|FLONG:
+ v = *(ulong*)op->argp;
+ r = LONG;
+ break;
+
+ case FSHORT:
+ h = *(int*)op->argp;
+ v = h;
+ r = SHORT;
+ break;
+
+ case FUNSIGN|FSHORT:
+ h = *(int*)op->argp;
+ v = (ushort)h;
+ r = SHORT;
+ break;
+
+ default:
+ v = *(int*)op->argp;
+ r = INT;
+ break;
+
+ case FUNSIGN:
+ v = *(unsigned*)op->argp;
+ r = INT;
+ break;
+ }
+ if(!(op->f3 & FUNSIGN) && v < 0) {
+ v = -v;
+ f = 1;
+ }
+ b[IDIGIT-1] = 0;
+ for(i = IDIGIT-2;; i--) {
+ n = (ulong)v % base;
+ n += '0';
+ if(n > '9'){
+ n += 'a' - ('9'+1);
+ if(ucase)
+ n += 'A'-'a';
+ }
+ b[i] = n;
+ if(i < 2)
+ break;
+ v = (ulong)v / base;
+ if(op->f2 >= 0 && i >= IDIGIT-op->f2)
+ continue;
+ if(v <= 0)
+ break;
+ }
+ if(f)
+ b[--i] = '-';
+ strconv(b+i, op, op->f1, -1);
+ return r;
+}
+
+static int
+noconv(Op *op)
+{
+
+ strconv("***", op, 0, -1);
+ return 0;
+}
+
+static int
+cconv(Op *op)
+{
+ char b[2];
+
+ b[0] = *(int*)op->argp;
+ b[1] = 0;
+ strconv(b, op, op->f1, -1);
+ return INT;
+}
+
+static int
+dconv(Op *op)
+{
+ return numbconv(op, 10);
+}
+
+static int
+hconv(Op*)
+{
+ return -FSHORT;
+}
+
+static int
+lconv(Op*)
+{
+ return -FLONG;
+}
+
+static int
+oconv(Op *op)
+{
+ return numbconv(op, 8);
+}
+
+static int
+sconv(Op *op)
+{
+ strconv(*(char**)op->argp, op, op->f1, op->f2);
+ return PTR;
+}
+
+static int
+uconv(Op*)
+{
+ return -FUNSIGN;
+}
+
+static int
+xconv(Op *op)
+{
+ return numbconv(op, 16);
+}
+
+static int
+Xconv(Op *op)
+{
+ int r;
+
+ ucase = 1;
+ r = numbconv(op, 16);
+ ucase = 0;
+ return r;
+}
+
+static int
+percent(Op *op)
+{
+
+ PUT(op, '%');
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/arm1110/fns.h
@@ -1,0 +1,7 @@
+/*
+ * functions defined locally
+ */
+extern int gunzip(uchar *out, int outn, uchar *in, int inn);
+extern void delay(int ms);
+extern void serialputs(char *str, int n);
+extern void draincache(void);
--- /dev/null
+++ b/os/boot.original/arm1110/il.s
@@ -1,0 +1,99 @@
+#include "mem.h"
+/*
+ * Entered here from Compaq's bootldr. First relocate to
+ * the location we're linked for and then copy back the
+ * decompressed kernel.
+ *
+ * All
+ */
+TEXT _start(SB), $-4
+ MOVW $setR12(SB), R12 /* load the SB */
+ MOVW $1, R0 /* dance to make 5l think that the magic */
+ MOVW $1, R1 /* numbers in WORDs below are being used */
+ CMP.S R0, R1 /* and to align them to where bootldr wants */
+ BEQ _start2
+ WORD $0x016f2818 /* magic number to say we are a kernel */
+ WORD $0xc0008000 /* entry point address */
+ WORD $0 /* size?, or end of data? */
+
+_start2:
+
+ /* SVC mode, interrupts disabled */
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
+ MOVW R1, CPSR
+
+ /* disable the MMU */
+ MOVW $0x130, R1
+ MCR CpMMU, 0, R1, C(CpControl), C(0x0)
+
+ /* enable caches */
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ ORR $(CpCdcache|CpCicache|CpCwb), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+
+ /* flush caches */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+ /* drain prefetch */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+
+ /* drain write buffer */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+
+ /* relocate to where we expect to be */
+ MOVW $(FLATESIZE),R3
+ MOVW $0xC0008000,R1
+ MOVW $0xC0200000,R2
+ ADD R1,R3
+_relloop:
+ MOVW (R1),R0
+ MOVW R0,(R2)
+ ADD $4,R1
+ ADD $4,R2
+ CMP.S R1,R3
+ BNE _relloop
+
+ MOVW $(MACHADDR+BY2PG), R13 /* stack */
+ SUB $4, R13 /* link */
+
+ /* jump to where we've been relocated */
+ MOVW $_relocated(SB),R15
+
+TEXT _relocated(SB),$-4
+ BL main(SB)
+ BL exit(SB)
+ /* we shouldn't get here */
+_mainloop:
+ B _mainloop
+ BL _div(SB) /* hack to get _div etc loaded */
+
+TEXT mypc(SB),$-4
+ MOVW R14,R0
+ RET
+
+TEXT draincache(SB),$-4
+ /* write back any dirty data */
+ MOVW $0xe0000000,R0
+ ADD $(8*1024),R0,R1
+_cfloop:
+ MOVW.P 32(R0),R2
+ CMP.S R0,R1
+ BNE _cfloop
+
+ /* drain write buffer and invalidate i&d cache contents */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+
+ /* drain prefetch */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+
+ /* disable caches */
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ BIC $(CpCdcache|CpCicache|CpCwb), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
--- /dev/null
+++ b/os/boot.original/arm1110/imain.c
@@ -1,0 +1,48 @@
+#include "u.h"
+#include "lib.h"
+#include "fns.h"
+#include "dat.h"
+#include "mem.h"
+
+void
+main(void)
+{
+ void (*f)(void);
+ ulong *kernel;
+
+ print("inflating kernel\n");
+
+ kernel = (ulong*)(0xc0200000+20*1024);
+ if(gunzip((uchar*)0xc0008000, 2*1024*1024, (uchar*)kernel, FLATESIZE) > 0){
+ f = (void (*)(void))0xc0008010;
+ draincache();
+ } else {
+ print("inflation failed\n");
+ f = nil;
+ }
+ (*f)();
+}
+
+void
+exit(void)
+{
+
+ void (*f)(void);
+
+ delay(1000);
+
+ print("it's a wonderful day to die\n");
+ f = nil;
+ (*f)();
+}
+
+void
+delay(int ms)
+{
+ int i;
+
+ while(ms-- > 0){
+ for(i = 0; i < 1000; i++)
+ ;
+ }
+}
--- /dev/null
+++ b/os/boot.original/arm1110/inflate.c
@@ -1,0 +1,208 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include <flate.h>
+
+typedef struct Biobuf Biobuf;
+
+struct Biobuf
+{
+ uchar *bp;
+ uchar *p;
+ uchar *ep;
+};
+
+static int header(Biobuf*);
+static int trailer(Biobuf*, Biobuf*);
+static int getc(void*);
+static ulong offset(Biobuf*);
+static int crcwrite(void *out, void *buf, int n);
+static ulong get4(Biobuf *b);
+static ulong Boffset(Biobuf *bp);
+
+/* GZIP flags */
+enum {
+ Ftext= (1<<0),
+ Fhcrc= (1<<1),
+ Fextra= (1<<2),
+ Fname= (1<<3),
+ Fcomment= (1<<4),
+
+ GZCRCPOLY = 0xedb88320UL,
+};
+
+static ulong *crctab;
+static ulong crc;
+
+int
+gunzip(uchar *out, int outn, uchar *in, int inn)
+{
+ Biobuf bin, bout;
+ int err;
+
+ crc = 0;
+ crctab = mkcrctab(GZCRCPOLY);
+ err = inflateinit();
+ if(err != FlateOk)
+ print("inflateinit failed: %s\n", flateerr(err));
+
+ bin.bp = bin.p = in;
+ bin.ep = in+inn;
+ bout.bp = bout.p = out;
+ bout.ep = out+outn;
+
+ err = header(&bin);
+ if(err != FlateOk)
+ return err;
+
+ err = inflate(&bout, crcwrite, &bin, getc);
+ if(err != FlateOk)
+ print("inflate failed: %s\n", flateerr(err));
+
+ err = trailer(&bout, &bin);
+ if(err != FlateOk)
+ return err;
+
+ return Boffset(&bout);
+}
+
+static int
+header(Biobuf *bin)
+{
+ int i, flag;
+
+ if(getc(bin) != 0x1f || getc(bin) != 0x8b){
+ print("bad magic\n");
+ return FlateCorrupted;
+ }
+ if(getc(bin) != 8){
+ print("unknown compression type\n");
+ return FlateCorrupted;
+ }
+
+ flag = getc(bin);
+
+ /* mod time */
+ get4(bin);
+
+ /* extra flags */
+ getc(bin);
+
+ /* OS type */
+ getc(bin);
+
+ if(flag & Fextra)
+ for(i=getc(bin); i>0; i--)
+ getc(bin);
+
+ /* name */
+ if(flag&Fname)
+ while(getc(bin) != 0)
+ ;
+
+ /* comment */
+ if(flag&Fcomment)
+ while(getc(bin) != 0)
+ ;
+
+ /* crc16 */
+ if(flag&Fhcrc) {
+ getc(bin);
+ getc(bin);
+ }
+
+ return FlateOk;
+}
+
+static int
+trailer(Biobuf *bout, Biobuf *bin)
+{
+ /* crc32 */
+ ulong x;
+
+ x = get4(bin);
+ if(crc != x){
+ print("crc mismatch %lux %lux\n", crc, x);
+ return FlateCorrupted;
+ }
+
+ /* length */
+ if(get4(bin) != Boffset(bout)){
+ print("bad output len\n");
+ return FlateCorrupted;
+ }
+ return FlateOk;
+}
+
+static ulong
+get4(Biobuf *b)
+{
+ ulong v;
+ int i, c;
+
+ v = 0;
+ for(i = 0; i < 4; i++){
+ c = getc(b);
+ v |= c << (i * 8);
+ }
+ return v;
+}
+
+static int
+getc(void *in)
+{
+ Biobuf *bp = in;
+
+ if((bp->p - bp->bp) % 10000 == 0)
+ print(".");
+ if(bp->p >= bp->ep)
+ return -1;
+ return *bp->p++;
+}
+
+static ulong
+Boffset(Biobuf *bp)
+{
+ return bp->p - bp->bp;
+}
+
+static int
+crcwrite(void *out, void *buf, int n)
+{
+ Biobuf *bp;
+
+ crc = blockcrc(crctab, crc, buf, n);
+ bp = out;
+ if(n > bp->ep-bp->p)
+ n = bp->ep-bp->p;
+ memmove(bp->p, buf, n);
+ bp->p += n;
+ return n;
+}
+
+#undef malloc
+#undef free
+
+static ulong ibrkp = ~0;
+
+void *
+malloc(ulong n)
+{
+ ulong rv;
+
+ if(ibrkp == ~0)
+ ibrkp = ((ulong)end)+1024*1024;
+ n = (n+3)>>2;
+ n <<= 2;
+ rv = ibrkp;
+ ibrkp += n;
+ return (void*)rv;
+}
+
+void
+free(void *)
+{
+}
--- /dev/null
+++ b/os/boot.original/arm1110/io.h
@@ -1,0 +1,261 @@
+/*
+ * Definitions for IO devices. Used only in C.
+ */
+
+enum
+{
+ /* hardware counter frequency */
+ ClockFreq= 3686400,
+};
+
+/*
+ * IRQ's defined by SA1100
+ */
+enum
+{
+ IRQgpio0= 0,
+ IRQgpio1= 1,
+ IRQgpio2= 2,
+ IRQgpio3= 3,
+ IRQgpio4= 4,
+ IRQgpio5= 5,
+ IRQgpio6= 6,
+ IRQgpio7= 7,
+ IRQgpio8= 8,
+ IRQgpio9= 9,
+ IRQgpio10= 10,
+ IRQgpiohi= 11,
+ IRQlcd= 12,
+ IRQudc= 13,
+ IRQuart1b= 15,
+ IRQuart2= 16,
+ IRQuart3= 17,
+ IRQmcp= 18,
+ IRQssp= 19,
+ IRQdma0= 20,
+ IRQdma1= 21,
+ IRQdma2= 22,
+ IRQdma3= 23,
+ IRQdma4= 24,
+ IRQdma5= 25,
+ IRQtimer0= 26,
+ IRQtimer1= 27,
+ IRQtimer2= 28,
+ IRQtimer3= 29,
+ IRQsecond= 30,
+ IRQrtc= 31,
+};
+
+/*
+ * GPIO lines (signal names from compaq document). _i indicates input
+ * and _o output.
+ */
+enum
+{
+ GPIO_PWR_ON_i= 1<<0, /* power button */
+ GPIO_UP_IRQ_i= 1<<1, /* microcontroller interrupts */
+ GPIO_LDD8_o= 1<<2, /* LCD data 8-15 */
+ GPIO_LDD9_o= 1<<3,
+ GPIO_LDD10_o= 1<<4,
+ GPIO_LDD11_o= 1<<5,
+ GPIO_LDD12_o= 1<<6,
+ GPIO_LDD13_o= 1<<7,
+ GPIO_LDD14_o= 1<<8,
+ GPIO_LDD15_o= 1<<9,
+ GPIO_CARD_IND1_i= 1<<10, /* card inserted in PCMCIA socket 1 */
+ GPIO_CARD_IRQ1_i= 1<<11, /* PCMCIA socket 1 interrupt */
+ GPIO_CLK_SET0_o= 1<<12, /* clock selects for audio codec */
+ GPIO_CLK_SET1_o= 1<<13,
+ GPIO_L3_SDA_io= 1<<14, /* UDA1341 interface */
+ GPIO_L3_MODE_o= 1<<15,
+ GPIO_L3_SCLK_o= 1<<16,
+ GPIO_CARD_IND0_i= 1<<17, /* card inserted in PCMCIA socket 0 */
+ GPIO_KEY_ACT_i= 1<<18, /* hot key from cradle */
+ GPIO_SYS_CLK_i= 1<<19, /* clock from codec */
+ GPIO_BAT_FAULT_i= 1<<20, /* battery fault */
+ GPIO_CARD_IRQ0_i= 1<<21, /* PCMCIA socket 0 interrupt */
+ GPIO_LOCK_i= 1<<22, /* expansion pack lock/unlock */
+ GPIO_COM_DCD_i= 1<<23, /* DCD from UART3 */
+ GPIO_OPT_IRQ_i= 1<<24, /* expansion pack IRQ */
+ GPIO_COM_CTS_i= 1<<25, /* CTS from UART3 */
+ GPIO_COM_RTS_o= 1<<26, /* RTS to UART3 */
+ GPIO_OPT_IND_i= 1<<27, /* expansion pack inserted */
+
+/* Peripheral Unit GPIO pin assignments: alternate functions */
+ GPIO_SSP_TXD_o= 1<<10, /* SSP Transmit Data */
+ GPIO_SSP_RXD_i= 1<<11, /* SSP Receive Data */
+ GPIO_SSP_SCLK_o= 1<<12, /* SSP Sample CLocK */
+ GPIO_SSP_SFRM_o= 1<<13, /* SSP Sample FRaMe */
+ /* ser. port 1: */
+ GPIO_UART_TXD_o= 1<<14, /* UART Transmit Data */
+ GPIO_UART_RXD_i= 1<<15, /* UART Receive Data */
+ GPIO_SDLC_SCLK_io= 1<<16, /* SDLC Sample CLocK (I/O) */
+ GPIO_SDLC_AAF_o= 1<<17, /* SDLC Abort After Frame */
+ GPIO_UART_SCLK1_i= 1<<18, /* UART Sample CLocK 1 */
+ /* ser. port 4: */
+ GPIO_SSP_CLK_i= 1<<19, /* SSP external CLocK */
+ /* ser. port 3: */
+ GPIO_UART_SCLK3_i= 1<<20, /* UART Sample CLocK 3 */
+ /* ser. port 4: */
+ GPIO_MCP_CLK_i= 1<<21, /* MCP CLocK */
+ /* test controller: */
+ GPIO_TIC_ACK_o= 1<<21, /* TIC ACKnowledge */
+ GPIO_MBGNT_o= 1<<21, /* Memory Bus GraNT */
+ GPIO_TREQA_i= 1<<22, /* TIC REQuest A */
+ GPIO_MBREQ_i= 1<<22, /* Memory Bus REQuest */
+ GPIO_TREQB_i= 1<<23, /* TIC REQuest B */
+ GPIO_1Hz_o= 1<<25, /* 1 Hz clock */
+ GPIO_RCLK_o= 1<<26, /* internal (R) CLocK (O, fcpu/2) */
+ GPIO_32_768kHz_o= 1<<27, /* 32.768 kHz clock (O, RTC) */
+};
+
+/*
+ * types of interrupts
+ */
+enum
+{
+ GPIOrising,
+ GPIOfalling,
+ GPIOboth,
+ IRQ,
+};
+
+/* hardware registers */
+typedef struct Uartregs Uartregs;
+struct Uartregs
+{
+ ulong ctl[4];
+ ulong dummya;
+ ulong data;
+ ulong dummyb;
+ ulong status[2];
+};
+Uartregs *uart3regs;
+
+/* general purpose I/O lines control registers */
+typedef struct GPIOregs GPIOregs;
+struct GPIOregs
+{
+ ulong level; /* 1 == high */
+ ulong direction; /* 1 == output */
+ ulong set; /* a 1 sets the bit, 0 leaves it alone */
+ ulong clear; /* a 1 clears the bit, 0 leaves it alone */
+ ulong rising; /* rising edge detect enable */
+ ulong falling; /* falling edge detect enable */
+ ulong edgestatus; /* writing a 1 bit clears */
+ ulong altfunc; /* turn on alternate function for any set bits */
+};
+
+extern GPIOregs *gpioregs;
+
+/* extra general purpose I/O bits, output only */
+enum
+{
+ EGPIO_prog_flash= 1<<0,
+ EGPIO_pcmcia_reset= 1<<1,
+ EGPIO_exppack_reset= 1<<2,
+ EGPIO_codec_reset= 1<<3,
+ EGPIO_exp_nvram_power= 1<<4,
+ EGPIO_exp_full_power= 1<<5,
+ EGPIO_lcd_3v= 1<<6,
+ EGPIO_rs232_power= 1<<7,
+ EGPIO_lcd_ic_power= 1<<8,
+ EGPIO_ir_power= 1<<9,
+ EGPIO_audio_power= 1<<10,
+ EGPIO_audio_ic_power= 1<<11,
+ EGPIO_audio_mute= 1<<12,
+ EGPIO_fir= 1<<13, /* not set is sir */
+ EGPIO_lcd_5v= 1<<14,
+ EGPIO_lcd_9v= 1<<15,
+};
+extern ulong *egpioreg;
+
+/* Peripheral pin controller registers */
+typedef struct PPCregs PPCregs;
+struct PPCregs {
+ ulong direction;
+ ulong state;
+ ulong assignment;
+ ulong sleepdir;
+ ulong flags;
+};
+extern PPCregs *ppcregs;
+
+/* Synchronous Serial Port controller registers */
+typedef struct SSPregs SSPregs;
+struct SSPregs {
+ ulong control0;
+ ulong control1;
+ ulong dummy0;
+ ulong data;
+ ulong dummy1;
+ ulong status;
+};
+extern SSPregs *sspregs;
+
+/* Multimedia Communications Port controller registers */
+typedef struct MCPregs MCPregs;
+struct MCPregs {
+ ulong control0;
+ ulong reserved0;
+ ulong data0;
+ ulong data1;
+ ulong data2;
+ ulong reserved1;
+ ulong status;
+ ulong reserved[11];
+ ulong control1;
+};
+extern MCPregs *mcpregs;
+
+/*
+ * memory configuration
+ */
+enum
+{
+ /* bit shifts for pcmcia access time counters */
+ MECR_io0= 0,
+ MECR_attr0= 5,
+ MECR_mem0= 10,
+ MECR_fast0= 11,
+ MECR_io1= MECR_io0+16,
+ MECR_attr1= MECR_attr0+16,
+ MECR_mem1= MECR_mem0+16,
+ MECR_fast1= MECR_fast0+16,
+};
+
+typedef struct MemConfRegs MemConfRegs;
+struct MemConfRegs
+{
+ ulong mdcnfg; /* dram */
+ ulong mdcas00; /* dram banks 0/1 */
+ ulong mdcas01;
+ ulong mdcas02;
+ ulong msc0; /* static */
+ ulong msc1;
+ ulong mecr; /* pcmcia */
+ ulong mdrefr; /* dram refresh */
+ ulong mdcas20; /* dram banks 2/3 */
+ ulong mdcas21;
+ ulong mdcas22;
+ ulong msc2; /* static */
+ ulong smcnfg; /* SMROM config */
+};
+extern MemConfRegs *memconfregs;
+
+/*
+ * power management
+ */
+typedef struct PowerRegs PowerRegs;
+struct PowerRegs
+{
+ ulong pmcr; /* Power manager control register */
+ ulong pssr; /* Power manager sleep status register */
+ ulong pspr; /* Power manager scratch pad register */
+ ulong pwer; /* Power manager wakeup enable register */
+ ulong pcfr; /* Power manager general configuration register */
+ ulong ppcr; /* Power manager PPL configuration register */
+ ulong pgsr; /* Power manager GPIO sleep state register */
+ ulong posr; /* Power manager oscillator status register */
+};
+extern PowerRegs *powerregs;
--- /dev/null
+++ b/os/boot.original/arm1110/l.s
@@ -1,0 +1,454 @@
+#include "mem.h"
+
+/*
+ * Entered here from Compaq's bootldr with MMU disabled.
+ */
+TEXT _start(SB), $-4
+ MOVW $setR12(SB), R12 /* load the SB */
+_main:
+ /* SVC mode, interrupts disabled */
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
+ MOVW R1, CPSR
+
+ /* disable the MMU */
+ MOVW $0x130, R1
+ MCR CpMMU, 0, R1, C(CpControl), C(0x0)
+
+ /* flush caches */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+ /* drain prefetch */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+
+ /* drain write buffer */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+
+ MOVW $(MACHADDR+BY2PG), R13 /* stack */
+ SUB $4, R13 /* link */
+ BL main(SB)
+ BL exit(SB)
+ /* we shouldn't get here */
+_mainloop:
+ B _mainloop
+ BL _div(SB) /* hack to get _div etc loaded */
+
+/* flush tlb's */
+TEXT mmuinvalidate(SB), $-4
+ MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
+ RET
+
+/* flush tlb's */
+TEXT mmuinvalidateaddr(SB), $-4
+ MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1
+ RET
+
+/* write back and invalidate i and d caches */
+TEXT cacheflush(SB), $-4
+ /* write back any dirty data */
+ MOVW $0xe0000000,R0
+ ADD $(8*1024),R0,R1
+_cfloop:
+ MOVW.P 32(R0),R2
+ CMP.S R0,R1
+ BNE _cfloop
+
+ /* drain write buffer and invalidate i&d cache contents */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+
+ /* drain prefetch */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ RET
+
+/* write back d cache */
+TEXT cachewb(SB), $-4
+ /* write back any dirty data */
+_cachewb:
+ MOVW $0xe0000000,R0
+ ADD $(8*1024),R0,R1
+_cwbloop:
+ MOVW.P 32(R0),R2
+ CMP.S R0,R1
+ BNE _cwbloop
+
+ /* drain write buffer */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ RET
+
+/* write back a single cache line */
+TEXT cachewbaddr(SB), $-4
+ BIC $31,R0
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
+ B _wbflush
+
+/* write back a region of cache lines */
+TEXT cachewbregion(SB), $-4
+ MOVW 4(FP),R1
+ CMP.S $(4*1024),R1
+ BGT _cachewb
+ ADD R0,R1
+ BIC $31,R0
+_cwbrloop:
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
+ ADD $32,R0
+ CMP.S R0,R1
+ BGT _cwbrloop
+ B _wbflush
+
+/* invalidate the dcache */
+TEXT dcacheinvalidate(SB), $-4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x6)
+ RET
+
+/* invalidate the icache */
+TEXT icacheinvalidate(SB), $-4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x9)
+ RET
+
+/* drain write buffer */
+TEXT wbflush(SB), $-4
+_wbflush:
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ RET
+
+/* return cpu id */
+TEXT getcpuid(SB), $-4
+ MRC CpMMU, 0, R0, C(CpCPUID), C(0x0)
+ RET
+
+/* return fault status */
+TEXT getfsr(SB), $-4
+ MRC CpMMU, 0, R0, C(CpFSR), C(0x0)
+ RET
+
+/* return fault address */
+TEXT getfar(SB), $-4
+ MRC CpMMU, 0, R0, C(CpFAR), C(0x0)
+ RET
+
+/* return fault address */
+TEXT putfar(SB), $-4
+ MRC CpMMU, 0, R0, C(CpFAR), C(0x0)
+ RET
+
+/* set the translation table base */
+TEXT putttb(SB), $-4
+ MCR CpMMU, 0, R0, C(CpTTB), C(0x0)
+ RET
+
+/*
+ * enable mmu, i and d caches
+ */
+TEXT mmuenable(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ ORR $(CpCmmuena|CpCdcache|CpCicache|CpCwb), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
+
+TEXT mmudisable(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ BIC $(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCvivec), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
+
+/*
+ * use exception vectors at 0xffff0000
+ */
+TEXT mappedIvecEnable(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ ORR $(CpCvivec), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
+TEXT mappedIvecDisable(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ BIC $(CpCvivec), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
+
+/* set the translation table base */
+TEXT putdac(SB), $-4
+ MCR CpMMU, 0, R0, C(CpDAC), C(0x0)
+ RET
+
+/* set address translation pid */
+TEXT putpid(SB), $-4
+ MCR CpMMU, 0, R0, C(CpPID), C(0x0)
+ RET
+
+/*
+ * set the stack value for the mode passed in R0
+ */
+TEXT setr13(SB), $-4
+ MOVW 4(FP), R1
+
+ MOVW CPSR, R2
+ BIC $PsrMask, R2, R3
+ ORR R0, R3
+ MOVW R3, CPSR
+
+ MOVW R13, R0
+ MOVW R1, R13
+
+ MOVW R2, CPSR
+ RET
+
+/*
+ * exception vectors, copied by trapinit() to somewhere useful
+ */
+
+TEXT vectors(SB), $-4
+ MOVW 0x18(R15), R15 /* reset */
+ MOVW 0x18(R15), R15 /* undefined */
+ MOVW 0x18(R15), R15 /* SWI */
+ MOVW 0x18(R15), R15 /* prefetch abort */
+ MOVW 0x18(R15), R15 /* data abort */
+ MOVW 0x18(R15), R15 /* reserved */
+ MOVW 0x18(R15), R15 /* IRQ */
+ MOVW 0x18(R15), R15 /* FIQ */
+
+TEXT vtable(SB), $-4
+ WORD $_vsvc(SB) /* reset, in svc mode already */
+ WORD $_vund(SB) /* undefined, switch to svc mode */
+ WORD $_vsvc(SB) /* swi, in svc mode already */
+ WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */
+ WORD $_vdabt(SB) /* data abort, switch to svc mode */
+ WORD $_vsvc(SB) /* reserved */
+ WORD $_virq(SB) /* IRQ, switch to svc mode */
+ WORD $_vfiq(SB) /* FIQ, switch to svc mode */
+
+TEXT _vrst(SB), $-4
+ BL resettrap(SB)
+
+TEXT _vsvc(SB), $-4 /* SWI */
+ MOVW.W R14, -4(R13) /* ureg->pc = interupted PC */
+ MOVW SPSR, R14 /* ureg->psr = SPSR */
+ MOVW.W R14, -4(R13) /* ... */
+ MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */
+ MOVW.W R14, -4(R13) /* ... */
+ MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $8, R13 /* space for argument+link */
+
+ BL syscall(SB)
+
+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT _vund(SB), $-4 /* undefined */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMund, R0
+ B _vswitch
+
+TEXT _vpabt(SB), $-4 /* prefetch abort */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMabt, R0 /* r0 = type */
+ B _vswitch
+
+TEXT _vdabt(SB), $-4 /* prefetch abort */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $(PsrMabt+1), R0 /* r0 = type */
+ B _vswitch
+
+TEXT _virq(SB), $-4 /* IRQ */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMirq, R0 /* r0 = type */
+ B _vswitch
+
+ /*
+ * come here with type in R0 and R13 pointing above saved [r0-r4]
+ * and type in r0. we'll switch to SVC mode and then call trap.
+ */
+_vswitch:
+ MOVW SPSR, R1 /* save SPSR for ureg */
+ MOVW R14, R2 /* save interrupted pc for ureg */
+ MOVW R13, R3 /* save pointer to where the original [R0-R3] are */
+
+ /* switch to svc mode */
+ MOVW CPSR, R14
+ BIC $PsrMask, R14
+ ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
+ MOVW R14, CPSR
+
+ /* interupted code kernel or user? */
+ AND.S $0xf, R1, R4
+ BEQ _userexcep
+
+ /* here for trap from SVC mode */
+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
+ MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
+ MOVM.DB.W [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $8, R13 /* space for argument+link (for debugger) */
+ MOVW $0xdeaddead,R11 /* marker */
+
+ BL trap(SB)
+
+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+ /* here for trap from USER mode */
+_userexcep:
+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
+ MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
+ MOVM.DB.W.S [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $8, R13 /* space for argument+link (for debugger) */
+
+ BL trap(SB)
+
+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT _vfiq(SB), $-4 /* FIQ */
+ RFE /* FIQ is special, ignore it for now */
+
+/*
+ * This is the first jump from kernel to user mode.
+ * Fake a return from interrupt.
+ *
+ * Enter with R0 containing the user stack pointer.
+ * UTZERO + 0x20 is always the entry point.
+ *
+ */
+TEXT touser(SB),$-4
+ /* store the user stack pointer into the USR_r13 */
+ MOVM.DB.W [R0], (R13)
+ MOVM.S.IA.W (R13),[R13]
+
+ /* set up a PSR for user level */
+ MOVW $(PsrMusr), R0
+ MOVW R0,SPSR
+
+ /* save the PC on the stack */
+ MOVW $(UTZERO+0x20), R0
+ MOVM.DB.W [R0],(R13)
+
+ /* return from interrupt */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+/*
+ * here to jump to a newly forked process
+ */
+TEXT forkret(SB),$-4
+ ADD $(4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT splhi(SB), $-4
+ /* save caller pc in Mach */
+ MOVW $(MACHADDR+0x04),R2
+ MOVW R14,0(R2)
+ /* turn off interrupts */
+ MOVW CPSR, R0
+ ORR $(PsrDfiq|PsrDirq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+TEXT spllo(SB), $-4
+ MOVW CPSR, R0
+ BIC $(PsrDfiq|PsrDirq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+TEXT splx(SB), $-4
+ /* save caller pc in Mach */
+ MOVW $(MACHADDR+0x04),R2
+ MOVW R14,0(R2)
+ /* reset interrupt level */
+ MOVW R0, R1
+ MOVW CPSR, R0
+ MOVW R1, CPSR
+ RET
+
+TEXT splxpc(SB), $-4 /* for iunlock */
+ MOVW R0, R1
+ MOVW CPSR, R0
+ MOVW R1, CPSR
+ RET
+
+TEXT spldone(SB), $0
+ RET
+
+TEXT islo(SB), $-4
+ MOVW CPSR, R0
+ AND $(PsrDfiq|PsrDirq), R0
+ EOR $(PsrDfiq|PsrDirq), R0
+ RET
+
+TEXT cpsrr(SB), $-4
+ MOVW CPSR, R0
+ RET
+
+TEXT spsrr(SB), $-4
+ MOVW SPSR, R0
+ RET
+
+TEXT getcallerpc(SB), $-4
+ MOVW 0(R13), R0
+ RET
+
+TEXT tas(SB), $-4
+ MOVW R0, R1
+ MOVW $0xDEADDEAD, R2
+ SWPW R2, (R1), R0
+ RET
+
+TEXT setlabel(SB), $-4
+ MOVW R13, 0(R0) /* sp */
+ MOVW R14, 4(R0) /* pc */
+ MOVW $0, R0
+ RET
+
+TEXT gotolabel(SB), $-4
+ MOVW 0(R0), R13 /* sp */
+ MOVW 4(R0), R14 /* pc */
+ MOVW $1, R0
+ RET
+
+
+/* The first MCR instruction of this function needs to be on a cache-line
+ * boundary; to make this happen, it will be copied (in trap.c).
+ *
+ * Doze puts the machine into idle mode. Any interrupt will get it out
+ * at the next instruction (the RET, to be precise).
+ */
+TEXT _doze(SB), $-4
+ MOVW $UCDRAMZERO, R1
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MCR CpPWR, 0, R0, C(CpTest), C(0x2), 2
+ MOVW (R1), R0
+ MCR CpPWR, 0, R0, C(CpTest), C(0x8), 2
+ RET
--- /dev/null
+++ b/os/boot.original/arm1110/lib.h
@@ -1,0 +1,143 @@
+/*
+ * functions (possibly) linked in, complete, from libc.
+ */
+
+/*
+ * mem routines
+ */
+extern void *memccpy(void*, void*, int, long);
+extern void *memset(void*, int, long);
+extern int memcmp(void*, void*, long);
+extern void *memmove(void*, void*, long);
+extern void *memchr(void*, int, long);
+
+/*
+ * string routines
+ */
+extern char *strcat(char*, char*);
+extern char *strchr(char*, char);
+extern char *strrchr(char*, char);
+extern int strcmp(char*, char*);
+extern char *strcpy(char*, char*);
+extern char *strncat(char*, char*, long);
+extern char *strncpy(char*, char*, long);
+extern int strncmp(char*, char*, long);
+extern long strlen(char*);
+extern char* strstr(char*, char*);
+extern int atoi(char*);
+
+enum
+{
+ UTFmax = 3, /* maximum bytes per rune */
+ Runesync = 0x80, /* cannot represent part of a UTF sequence */
+ Runeself = 0x80, /* rune and UTF sequences are the same (<) */
+ Runeerror = 0x80, /* decoding error in UTF */
+};
+
+/*
+ * rune routines
+ */
+extern int runetochar(char*, Rune*);
+extern int chartorune(Rune*, char*);
+extern char* utfrune(char*, long);
+extern int utflen(char*);
+extern int runelen(long);
+
+extern int abs(int);
+
+/*
+ * print routines
+ */
+typedef struct Cconv Fconv;
+extern char* donprint(char*, char*, char*, void*);
+extern int sprint(char*, char*, ...);
+extern char* seprint(char*, char*, char*, ...);
+extern int snprint(char*, int, char*, ...);
+extern int print(char*, ...);
+
+/*
+ * one-of-a-kind
+ */
+extern char* cleanname(char*);
+extern ulong getcallerpc(void*);
+extern long strtol(char*, char**, int);
+extern ulong strtoul(char*, char**, int);
+extern vlong strtoll(char*, char**, int);
+extern uvlong strtoull(char*, char**, int);
+extern char etext[];
+extern char edata[];
+extern char end[];
+extern int getfields(char*, char**, int, int, char*);
+
+/*
+ * Syscall data structures
+ */
+#define MORDER 0x0003 /* mask for bits defining order of mounting */
+#define MREPL 0x0000 /* mount replaces object */
+#define MBEFORE 0x0001 /* mount goes before others in union directory */
+#define MAFTER 0x0002 /* mount goes after others in union directory */
+#define MCREATE 0x0004 /* permit creation in mounted directory */
+#define MCACHE 0x0010 /* cache some data */
+#define MMASK 0x001F /* all bits on */
+
+#define OREAD 0 /* open for read */
+#define OWRITE 1 /* write */
+#define ORDWR 2 /* read and write */
+#define OEXEC 3 /* execute, == read but check execute permission */
+#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
+#define OCEXEC 32 /* or'ed in, close on exec */
+#define ORCLOSE 64 /* or'ed in, remove on close */
+
+#define NCONT 0 /* continue after note */
+#define NDFLT 1 /* terminate after note */
+#define NSAVE 2 /* clear note but hold state */
+#define NRSTR 3 /* restore saved state */
+
+typedef struct Qid Qid;
+typedef struct Dir Dir;
+typedef struct Waitmsg Waitmsg;
+
+#define ERRLEN 64
+#define DIRLEN 116
+#define NAMELEN 28
+
+struct Qid
+{
+ ulong path;
+ ulong vers;
+};
+
+struct Dir
+{
+ char name[NAMELEN];
+ char uid[NAMELEN];
+ char gid[NAMELEN];
+ Qid qid;
+ ulong mode;
+ long atime;
+ long mtime;
+ vlong length;
+ short type;
+ short dev;
+};
+
+struct Waitmsg
+{
+ char pid[12]; /* of loved one */
+ char time[3*12]; /* of loved one and descendants */
+ char msg[ERRLEN];
+};
+
+/*
+ * locks
+ */
+typedef
+struct Lock {
+ int val;
+} Lock;
+
+extern int _tas(int*);
+
+extern void lock(Lock*);
+extern void unlock(Lock*);
+extern int canlock(Lock*);
--- /dev/null
+++ b/os/boot.original/arm1110/map
@@ -1,0 +1,10 @@
+defn acidmap()
+{
+ local dfoffset;
+
+ dfoffset = map()[1][3];
+ map({"text", _start, etext, 0x20});
+ map({"data", etext+1, edata, dfoffset});
+ print("Set map for plan 9 kernel image\n");
+ print("btext ", _start, " etext ", etext, "\n");
+}
--- /dev/null
+++ b/os/boot.original/arm1110/mem.h
@@ -1,0 +1,215 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#define BY2V 8 /* bytes per double word */
+#define BY2PG 4096 /* bytes per page */
+#define WD2PG (BY2PG/BY2WD) /* words per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
+#define PGROUND(s) ROUND(s, BY2PG)
+#define BLOCKALIGN 8
+
+#define MAXMACH 1 /* max # cpus system can run */
+
+/*
+ * Time
+ */
+#define HZ (20) /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
+#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
+
+/*
+ * Virtual addresses:
+ *
+ * We direct map all discovered DRAM and the area twixt 0xe0000000 and
+ * 0xe8000000 used to provide zeros for cache flushing.
+ *
+ * Flash is mapped to 0xb0000000 and special registers are mapped
+ * on demand to areas starting at 0xa0000000.
+ *
+ * The direct mapping is convenient but not necessary. It means
+ * that we don't have to turn on the MMU till well into the
+ * kernel. This can be changed by providing a mapping in l.s
+ * before calling main.
+ */
+#define UZERO 0 /* base of user address space */
+#define UTZERO (UZERO+BY2PG) /* first address in user text */
+#define KZERO 0xC0000000 /* base of kernel address space */
+#define KTZERO 0xC0008000 /* first address in kernel text */
+#define EMEMZERO 0x90000000 /* 256 meg for add on memory */
+#define EMEMTOP 0xA0000000 /* ... */
+#define REGZERO 0xA0000000 /* 128 meg for mapspecial regs */
+#define REGTOP 0xA8000000 /* ... */
+#define FLASHZERO 0xB0000000 /* 128 meg for flash */
+#define FLASHTOP 0xB8000000 /* ... */
+#define DRAMZERO 0xC0000000 /* 128 meg for dram */
+#define DRAMTOP 0xC8000000 /* ... */
+#define UCDRAMZERO 0xC8000000 /* 128 meg for dram (uncached/unbuffered) */
+#define UCDRAMTOP 0xD0000000 /* ... */
+#define NULLZERO 0xE0000000 /* 128 meg for cache flush zeroes */
+#define NULLTOP 0xE8000000 /* ... */
+#define USTKTOP 0x2000000 /* byte just beyond user stack */
+#define USTKSIZE (8*1024*1024) /* size of user stack */
+#define TSTKTOP (USTKTOP-USTKSIZE) /* end of new stack in sysexec */
+#define TSTKSIZ 100
+#define MACHADDR (KZERO+0x00001000)
+#define EVECTORS 0xFFFF0000 /* virt base of exception vectors */
+
+#define KSTACK (16*1024) /* Size of kernel stack */
+
+#define FLATESIZE (700*1024) /* maximum size of compressed image */
+
+/*
+ * Offsets into flash
+ */
+#define Flash_bootldr (FLASHZERO+0x0) /* boot loader */
+#define Flash_kernel (FLASHZERO+0x10000) /* boot kernel */
+#define Flash_tar (FLASHZERO+0x100000) /* tar file containing fs.sac */
+
+/*
+ * virtual MMU
+ */
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 1984
+#define SSEGMAPSIZE 16
+#define PPN(x) ((x)&~(BY2PG-1))
+
+/*
+ * SA1110 definitions
+ */
+
+/*
+ * memory physical addresses
+ */
+#define PHYSFLASH0 0x00000000
+#define PHYSDRAM0 0xC0000000
+#define PHYSNULL0 0xE0000000
+
+/*
+ * peripheral control module physical addresses
+ */
+#define USBREGS 0x80000000 /* serial port 0 - USB */
+#define UART1REGS 0x80010000 /* serial port 1 - UART */
+#define GPCLKREGS 0x80020060 /* serial port 1 - general purpose clock */
+#define UART2REGS 0x80030000 /* serial port 2 - low speed IR */
+#define HSSPREGS 0x80040060 /* serial port 2 - high speed IR */
+#define UART3REGS 0x80050000 /* serial port 3 - RS232 UART */
+#define MCPREGS 0x80060000 /* serial port 4 - multimedia comm port */
+#define SSPREGS 0x80070060 /* serial port 4 - synchronous serial port */
+#define OSTIMERREGS 0x90000000 /* operating system timer registers */
+#define POWERREGS 0x90020000 /* power management */
+#define GPIOREGS 0x90040000 /* 28 general purpose IO pins */
+#define INTRREGS 0x90050000 /* interrupt registers */
+#define PPCREGS 0x90060000 /* peripheral pin controller */
+#define MEMCONFREGS 0xA0000000 /* memory configuration */
+#define LCDREGS 0xB0100000 /* display */
+
+/*
+ * PCMCIA addresses
+ */
+#define PHYSPCM0REGS 0x20000000
+#define PYHSPCM0ATTR 0x28000000
+#define PYHSPCM0MEM 0x2C000000
+#define PHYSPCM1REGS 0x30000000
+#define PYHSPCM1ATTR 0x38000000
+#define PYHSPCM1MEM 0x3C000000
+
+/*
+ * Program Status Registers
+ */
+#define PsrMusr 0x00000010 /* mode */
+#define PsrMfiq 0x00000011
+#define PsrMirq 0x00000012
+#define PsrMsvc 0x00000013
+#define PsrMabt 0x00000017
+#define PsrMund 0x0000001B
+#define PsrMask 0x0000001F
+
+#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
+#define PsrDirq 0x00000080 /* disable IRQ interrupts */
+
+#define PsrV 0x10000000 /* overflow */
+#define PsrC 0x20000000 /* carry/borrow/extend */
+#define PsrZ 0x40000000 /* zero */
+#define PsrN 0x80000000 /* negative/less than */
+
+/*
+ * Coprocessors
+ */
+#define CpMMU 15
+#define CpPWR 15
+
+/*
+ * Internal MMU coprocessor registers
+ */
+#define CpCPUID 0 /* R: */
+#define CpControl 1 /* R: */
+#define CpTTB 2 /* RW: translation table base */
+#define CpDAC 3 /* RW: domain access control */
+#define CpFSR 5 /* RW: fault status */
+#define CpFAR 6 /* RW: fault address */
+#define CpCacheFlush 7 /* W: cache flushing, wb draining*/
+#define CpTLBFlush 8 /* W: TLB flushing */
+#define CpRBFlush 9 /* W: Read Buffer ops */
+#define CpPID 13 /* RW: PID for virtual mapping */
+#define CpBpt 14 /* W: Breakpoint register */
+#define CpTest 15 /* W: Test, Clock and Idle Control */
+
+/*
+ * CpControl
+ */
+#define CpCmmuena 0x00000001 /* M: MMU enable */
+#define CpCalign 0x00000002 /* A: alignment fault enable */
+#define CpCdcache 0x00000004 /* C: data cache on */
+#define CpCwb 0x00000008 /* W: write buffer turned on */
+#define CpCi32 0x00000010 /* P: 32-bit program space */
+#define CpCd32 0x00000020 /* D: 32-bit data space */
+#define CpCbe 0x00000080 /* B: big-endian operation */
+#define CpCsystem 0x00000100 /* S: system permission */
+#define CpCrom 0x00000200 /* R: ROM permission */
+#define CpCicache 0x00001000 /* I: instruction cache on */
+#define CpCvivec 0x00002000 /* X: virtual interrupt vector adjust */
+
+/*
+ * fault codes
+ */
+#define FCterm 0x2 /* terminal */
+#define FCvec 0x0 /* vector */
+#define FCalignf 0x1 /* unaligned full word data access */
+#define FCalignh 0x3 /* unaligned half word data access */
+#define FCl1abort 0xc /* level 1 external abort on translation */
+#define FCl2abort 0xe /* level 2 external abort on translation */
+#define FCtransSec 0x5 /* section translation */
+#define FCtransPage 0x7 /* page translation */
+#define FCdomainSec 0x9 /* section domain */
+#define FCdomainPage 0x11 /* page domain */
+#define FCpermSec 0x9 /* section permissions */
+#define FCpermPage 0x11 /* page permissions */
+#define FCabortLFSec 0x4 /* external abort on linefetch for section */
+#define FCabortLFPage 0x6 /* external abort on linefetch for page */
+#define FCabortNLFSec 0x8 /* external abort on non-linefetch for section */
+#define FCabortNLFPage 0xa /* external abort on non-linefetch for page */
+
+/*
+ * PTE bits used by fault.h. mmu.c translates them to real values.
+ */
+#define PTEVALID (1<<0)
+#define PTERONLY 0 /* this is implied by the absence of PTEWRITE */
+#define PTEWRITE (1<<1)
+#define PTEUNCACHED (1<<2)
+#define PTEKERNEL (1<<3) /* no user access */
+
+/*
+ * H3650 specific definitions
+ */
+#define EGPIOREGS 0x49000000 /* Additional GPIO register */
--- /dev/null
+++ b/os/boot.original/arm1110/mkfile
@@ -1,0 +1,86 @@
+<../../../mkconfig
+objtype=arm
+SYSTARG=$OSTARG
+OBJTYPE=arm
+BIN=$ROOT/Inferno/$OBJTYPE
+LIBDIR=$ROOT/Inferno/$OBJTYPE/lib
+LIBDIRS=../libflate $ROOT/libkern
+LIBS=\
+ libflate\
+ libkern\
+
+LIBFILES=${LIBS:%=$LIBDIR/%.a}
+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
+
+BIN=$ROOT/Inferno/$OBJTYPE
+
+TARG=\
+ inflate\
+
+INFLATE=\
+ il.$O\
+ imain.$O\
+
+CORE=\
+ uart.$O\
+ inflate.$O\
+ donprint.$O\
+ print.$O\
+
+HFILES=\
+ mem.h\
+
+CFLAGS=-FVw -I. -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include
+
+all:V: $TARG
+
+install:V: $BIN/$TARG
+
+$BIN/%: %
+ cp $stem $BIN/$stem
+
+inflate: $INFLATE $CORE $LIBFILES
+ $LD -o s$target -R4 -T0xC0200010 -l $prereq
+ $LD -o _$target -H5 -R4 -T0xC0200010 -l $prereq
+ dd -conv sync -ibs 20k -if _$target -of $target
+
+%.$O: %.s
+ $AS $stem.s
+
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+
+%.$O: $HFILES
+
+clean:
+ rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG _$TARG s$TARG
+
+
+# added to cause libflate to be made automatically:
+
+$ROOT/Inferno/$OBJTYPE/lib/lib%.a:Q: all-$SHELLTYPE
+ #
+
+rc-lib%.a nt-lib%.a:VQ:
+ echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
+ @{builtin cd $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
+
+sh-lib%.a:VQ:
+ echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
+ (cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
+
+%-sh:QV:
+ for i in $LIBDIRS
+ do
+ echo "(cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem)"
+ (cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem)
+ done
+
+%-rc %-nt:QV:
+ for (i in $LIBDIRS)
+ {
+ echo '@{cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem}'
+ @{cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem}
+ }
+
+nuke:V: clean nuke-$SHELLTYPE
--- /dev/null
+++ b/os/boot.original/arm1110/print.c
@@ -1,0 +1,56 @@
+#include "u.h"
+#include "lib.h"
+#include "fns.h"
+#include "dat.h"
+
+
+#define SIZE 1024
+
+int
+print(char *fmt, ...)
+{
+ char buf[SIZE], *out;
+ va_list arg;
+
+ va_start(arg, fmt);
+ out = donprint(buf, buf+SIZE, fmt, arg);
+ va_end(arg);
+ serialputs(buf, out-buf);
+ return out-buf;
+}
+
+int
+sprint(char *buf, char *fmt, ...)
+{
+ char *out;
+ va_list arg;
+
+ va_start(arg, fmt);
+ out = donprint(buf, buf+SIZE, fmt, arg);
+ va_end(arg);
+ return out-buf;
+}
+
+int
+snprint(char *buf, int len, char *fmt, ...)
+{
+ char *out;
+ va_list arg;
+
+ va_start(arg, fmt);
+ out = donprint(buf, buf+len, fmt, arg);
+ va_end(arg);
+ return out-buf;
+}
+
+char*
+seprint(char *buf, char *e, char *fmt, ...)
+{
+ char *out;
+ va_list arg;
+
+ va_start(arg, fmt);
+ out = donprint(buf, e, fmt, arg);
+ va_end(arg);
+ return out;
+}
--- /dev/null
+++ b/os/boot.original/arm1110/uart.c
@@ -1,0 +1,69 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum
+{
+ /* ctl[0] bits */
+ Parity= 1<<0,
+ Even= 1<<1,
+ Stop2= 1<<2,
+ Bits8= 1<<3,
+ SCE= 1<<4, /* synchronous clock enable */
+ RCE= 1<<5, /* rx on falling edge of clock */
+ TCE= 1<<6, /* tx on falling edge of clock */
+
+ /* ctl[3] bits */
+ Rena= 1<<0, /* receiver enable */
+ Tena= 1<<1, /* transmitter enable */
+ Break= 1<<2, /* force TXD3 low */
+ Rintena= 1<<3, /* enable receive interrupt */
+ Tintena= 1<<4, /* enable transmitter interrupt */
+ Loopback= 1<<5, /* loop back data */
+
+ /* data bits */
+ DEparity= 1<<8, /* parity error */
+ DEframe= 1<<9, /* framing error */
+ DEoverrun= 1<<10, /* overrun error */
+
+ /* status[0] bits */
+ Tint= 1<<0, /* transmit fifo half full interrupt */
+ Rint0= 1<<1, /* receiver fifo 1/3-2/3 full */
+ Rint1= 1<<2, /* receiver fifo not empty and receiver idle */
+ Breakstart= 1<<3,
+ Breakend= 1<<4,
+ Fifoerror= 1<<5, /* fifo error */
+
+ /* status[1] bits */
+ Tbusy= 1<<0, /* transmitting */
+ Rnotempty= 1<<1, /* receive fifo not empty */
+ Tnotfull= 1<<2, /* transmit fifo not full */
+ ParityError= 1<<3,
+ FrameError= 1<<4,
+ Overrun= 1<<5,
+};
+
+Uartregs *uart3regs = UART3REGS;
+
+
+/*
+ * for iprint, just write it
+ */
+void
+serialputs(char *str, int n)
+{
+ Uartregs *ur;
+
+ ur = uart3regs;
+ while(n-- > 0){
+ /* wait for output ready */
+ while((ur->status[1] & Tnotfull) == 0)
+ ;
+ ur->data = *str++;
+ }
+ while((ur->status[1] & Tbusy))
+ ;
+}
--- /dev/null
+++ b/os/boot.original/libflate/LICENCE
@@ -1,0 +1,237 @@
+Lucent Public License Version 1.02
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
+PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+ a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
+ Program, and
+ b. in the case of each Contributor,
+
+ i. changes to the Program, and
+ ii. additions to the Program;
+
+ where such changes and/or additions to the Program were added to the
+ Program by such Contributor itself or anyone acting on such
+ Contributor's behalf, and the Contributor explicitly consents, in
+ accordance with Section 3C, to characterization of the changes and/or
+ additions as Contributions.
+
+"Contributor" means LUCENT and any other entity that has Contributed a
+Contribution to the Program.
+
+"Distributor" means a Recipient that distributes the Program,
+modifications to the Program, or any part thereof.
+
+"Licensed Patents" mean patent claims licensable by a Contributor
+which are necessarily infringed by the use or sale of its Contribution
+alone or when combined with the Program.
+
+"Original Program" means the original version of the software
+accompanying this Agreement as released by LUCENT, including source
+code, object code and documentation, if any.
+
+"Program" means the Original Program and Contributions or any part
+thereof
+
+"Recipient" means anyone who receives the Program under this
+Agreement, including all Contributors.
+
+2. GRANT OF RIGHTS
+
+ a. Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free copyright
+ license to reproduce, prepare derivative works of, publicly display,
+ publicly perform, distribute and sublicense the Contribution of such
+ Contributor, if any, and such derivative works, in source code and
+ object code form.
+
+ b. Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free patent
+ license under Licensed Patents to make, use, sell, offer to sell,
+ import and otherwise transfer the Contribution of such Contributor, if
+ any, in source code and object code form. The patent license granted
+ by a Contributor shall also apply to the combination of the
+ Contribution of that Contributor and the Program if, at the time the
+ Contribution is added by the Contributor, such addition of the
+ Contribution causes such combination to be covered by the Licensed
+ Patents. The patent license granted by a Contributor shall not apply
+ to (i) any other combinations which include the Contribution, nor to
+ (ii) Contributions of other Contributors. No hardware per se is
+ licensed hereunder.
+
+ c. Recipient understands that although each Contributor grants the
+ licenses to its Contributions set forth herein, no assurances are
+ provided by any Contributor that the Program does not infringe the
+ patent or other intellectual property rights of any other entity. Each
+ Contributor disclaims any liability to Recipient for claims brought by
+ any other entity based on infringement of intellectual property rights
+ or otherwise. As a condition to exercising the rights and licenses
+ granted hereunder, each Recipient hereby assumes sole responsibility
+ to secure any other intellectual property rights needed, if any. For
+ example, if a third party patent license is required to allow
+ Recipient to distribute the Program, it is Recipient's responsibility
+ to acquire that license before distributing the Program.
+
+ d. Each Contributor represents that to its knowledge it has sufficient
+ copyright rights in its Contribution, if any, to grant the copyright
+ license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A. Distributor may choose to distribute the Program in any form under
+this Agreement or under its own license agreement, provided that:
+
+ a. it complies with the terms and conditions of this Agreement;
+
+ b. if the Program is distributed in source code or other tangible
+ form, a copy of this Agreement or Distributor's own license agreement
+ is included with each copy of the Program; and
+
+ c. if distributed under Distributor's own license agreement, such
+ license agreement:
+
+ i. effectively disclaims on behalf of all Contributors all warranties
+ and conditions, express and implied, including warranties or
+ conditions of title and non-infringement, and implied warranties or
+ conditions of merchantability and fitness for a particular purpose;
+ ii. effectively excludes on behalf of all Contributors all liability
+ for damages, including direct, indirect, special, incidental and
+ consequential damages, such as lost profits; and
+ iii. states that any provisions which differ from this Agreement are
+ offered by that Contributor alone and not by any other party.
+
+B. Each Distributor must include the following in a conspicuous
+ location in the Program:
+
+ Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
+ Reserved.
+
+C. In addition, each Contributor must identify itself as the
+originator of its Contribution in a manner that reasonably allows
+subsequent Recipients to identify the originator of the Contribution.
+Also, each Contributor must agree that the additions and/or changes
+are intended to be a Contribution. Once a Contribution is contributed,
+it may not thereafter be revoked.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use
+of the Program, the Distributor who includes the Program in a
+commercial product offering should do so in a manner which does not
+create potential liability for Contributors. Therefore, if a
+Distributor includes the Program in a commercial product offering,
+such Distributor ("Commercial Distributor") hereby agrees to defend
+and indemnify every Contributor ("Indemnified Contributor") against
+any losses, damages and costs (collectively"Losses") arising from
+claims, lawsuits and other legal actions brought by a third party
+against the Indemnified Contributor to the extent caused by the acts
+or omissions of such Commercial Distributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement.
+In order to qualify, an Indemnified Contributor must: a) promptly
+notify the Commercial Distributor in writing of such claim, and b)
+allow the Commercial Distributor to control, and cooperate with the
+Commercial Distributor in, the defense and any related settlement
+negotiations. The Indemnified Contributor may participate in any such
+claim at its own expense.
+
+For example, a Distributor might include the Program in a commercial
+product offering, Product X. That Distributor is then a Commercial
+Distributor. If that Commercial Distributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Distributor's responsibility
+alone. Under this section, the Commercial Distributor would have to
+defend claims against the Contributors related to those performance
+claims and warranties, and if a court requires any Contributor to pay
+any damages as a result, the Commercial Distributor must pay those
+damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement, including but not limited to
+the risks and costs of program errors, compliance with applicable
+laws, damage to or loss of data, programs or equipment, and
+unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
+ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. EXPORT CONTROL
+
+Recipient agrees that Recipient alone is responsible for compliance
+with the United States export administration regulations (and the
+export control laws and regulation of any other countries).
+
+8. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further
+action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against a Contributor with
+respect to a patent applicable to software (including a cross-claim or
+counterclaim in a lawsuit), then any patent licenses granted by that
+Contributor to such Recipient under this Agreement shall terminate as
+of the date such litigation is filed. In addition, if Recipient
+institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program
+itself (excluding combinations of the Program with other software or
+hardware) infringes such Recipient's patent(s), then such Recipient's
+rights granted under Section 2(b) shall terminate as of the date such
+litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of
+time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use
+and distribution of the Program as soon as reasonably practicable.
+However, Recipient's obligations under this Agreement and any licenses
+granted by Recipient relating to the Program shall continue and
+survive.
+
+LUCENT may publish new versions (including revisions) of this
+Agreement from time to time. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new
+version of the Agreement is published, Contributor may elect to
+distribute the Program (including its Contributions) under the new
+version. No one other than LUCENT has the right to modify this
+Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
+Recipient receives no rights or licenses to the intellectual property
+of any Contributor under this Agreement, whether expressly, by
+implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No
+party to this Agreement will bring a legal action under this Agreement
+more than one year after the cause of action arose. Each party waives
+its rights to a jury trial in any resulting litigation.
+
--- /dev/null
+++ b/os/boot.original/libflate/NOTICE
@@ -1,0 +1,8 @@
+Copyright © 2002 Lucent Technologies Inc.
+All Rights Reserved
+
+This software was originally developed for Plan 9.
+It is provided under the terms of the Lucent Public License, Version 1.02.
+
+Trivial modifications have been made to make it compile for Inferno.
+ Vita Nuova Holdings Limited.
--- /dev/null
+++ b/os/boot.original/libflate/adler.c
@@ -1,0 +1,71 @@
+#include "lib9.h"
+#include <flate.h>
+
+enum
+{
+ ADLERITERS = 5552, /* max iters before can overflow 32 bits */
+ ADLERBASE = 65521 /* largest prime smaller than 65536 */
+};
+
+ulong
+adler32(ulong adler, void *vbuf, int n)
+{
+ ulong s1, s2;
+ uchar *buf, *ebuf;
+ int m;
+
+ buf = vbuf;
+ s1 = adler & 0xffff;
+ s2 = (adler >> 16) & 0xffff;
+ for(; n >= 16; n -= m){
+ m = n;
+ if(m > ADLERITERS)
+ m = ADLERITERS;
+ m &= ~15;
+ for(ebuf = buf + m; buf < ebuf; buf += 16){
+ s1 += buf[0];
+ s2 += s1;
+ s1 += buf[1];
+ s2 += s1;
+ s1 += buf[2];
+ s2 += s1;
+ s1 += buf[3];
+ s2 += s1;
+ s1 += buf[4];
+ s2 += s1;
+ s1 += buf[5];
+ s2 += s1;
+ s1 += buf[6];
+ s2 += s1;
+ s1 += buf[7];
+ s2 += s1;
+ s1 += buf[8];
+ s2 += s1;
+ s1 += buf[9];
+ s2 += s1;
+ s1 += buf[10];
+ s2 += s1;
+ s1 += buf[11];
+ s2 += s1;
+ s1 += buf[12];
+ s2 += s1;
+ s1 += buf[13];
+ s2 += s1;
+ s1 += buf[14];
+ s2 += s1;
+ s1 += buf[15];
+ s2 += s1;
+ }
+ s1 %= ADLERBASE;
+ s2 %= ADLERBASE;
+ }
+ if(n){
+ for(ebuf = buf + n; buf < ebuf; buf++){
+ s1 += buf[0];
+ s2 += s1;
+ }
+ s1 %= ADLERBASE;
+ s2 %= ADLERBASE;
+ }
+ return (s2 << 16) + s1;
+}
--- /dev/null
+++ b/os/boot.original/libflate/crc.c
@@ -1,0 +1,39 @@
+#include "lib9.h"
+#include <flate.h>
+
+ulong*
+mkcrctab(ulong poly)
+{
+ ulong *crctab;
+ ulong crc;
+ int i, j;
+
+ crctab = malloc(256 * sizeof(ulong));
+ if(crctab == nil)
+ return nil;
+
+ for(i = 0; i < 256; i++){
+ crc = i;
+ for(j = 0; j < 8; j++){
+ if(crc & 1)
+ crc = (crc >> 1) ^ poly;
+ else
+ crc >>= 1;
+ }
+ crctab[i] = crc;
+ }
+ return crctab;
+}
+
+ulong
+blockcrc(ulong *crctab, ulong crc, void *vbuf, int n)
+{
+ uchar *buf, *ebuf;
+
+ crc ^= 0xffffffff;
+ buf = vbuf;
+ ebuf = buf + n;
+ while(buf < ebuf)
+ crc = crctab[(crc & 0xff) ^ *buf++] ^ (crc >> 8);
+ return crc ^ 0xffffffff;
+}
--- /dev/null
+++ b/os/boot.original/libflate/deflate.c
@@ -1,0 +1,1358 @@
+#include "lib9.h"
+#include <flate.h>
+
+typedef struct Chain Chain;
+typedef struct Chains Chains;
+typedef struct Dyncode Dyncode;
+typedef struct Huff Huff;
+typedef struct LZblock LZblock;
+typedef struct LZstate LZstate;
+
+enum
+{
+ /*
+ * deflate format paramaters
+ */
+ DeflateUnc = 0, /* uncompressed block */
+ DeflateFix = 1, /* fixed huffman codes */
+ DeflateDyn = 2, /* dynamic huffman codes */
+
+ DeflateEob = 256, /* end of block code in lit/len book */
+ DeflateMaxBlock = 64*1024-1, /* maximum size of uncompressed block */
+
+ DeflateMaxExp = 10, /* maximum expansion for a block */
+
+ LenStart = 257, /* start of length codes in litlen */
+ Nlitlen = 288, /* number of litlen codes */
+ Noff = 30, /* number of offset codes */
+ Nclen = 19, /* number of codelen codes */
+
+ MaxOff = 32*1024,
+ MinMatch = 3, /* shortest match possible */
+ MaxMatch = 258, /* longest match possible */
+
+ /*
+ * huffman code paramaters
+ */
+ MaxLeaf = Nlitlen,
+ MaxHuffBits = 16, /* max bits in a huffman code */
+ ChainMem = 2 * (MaxHuffBits - 1) * MaxHuffBits,
+
+ /*
+ * coding of the lz parse
+ */
+ LenFlag = 1 << 3,
+ LenShift = 4, /* leaves enough space for MinMatchMaxOff */
+ MaxLitRun = LenFlag - 1,
+
+ /*
+ * internal lz paramaters
+ */
+ DeflateOut = 4096, /* output buffer size */
+ BlockSize = 8192, /* attempted input read quanta */
+ DeflateBlock = DeflateMaxBlock & ~(BlockSize - 1),
+ MinMatchMaxOff = 4096, /* max profitable offset for small match;
+ * assumes 8 bits for len, 5+10 for offset
+ * DONT CHANGE WITHOUT CHANGING LZPARSE CONSTANTS
+ */
+ HistSlop = 512, /* must be at lead MaxMatch */
+ HistBlock = 64*1024,
+ HistSize = HistBlock + HistSlop,
+
+ HashLog = 13,
+ HashSize = 1<<HashLog,
+
+ MaxOffCode = 256, /* biggest offset looked up in direct table */
+
+ EstLitBits = 8,
+ EstLenBits = 4,
+ EstOffBits = 5,
+};
+
+/*
+ * knuth vol. 3 multiplicative hashing
+ * each byte x chosen according to rules
+ * 1/4 < x < 3/10, 1/3 x < < 3/7, 4/7 < x < 2/3, 7/10 < x < 3/4
+ * with reasonable spread between the bytes & their complements
+ *
+ * the 3 byte value appears to be as almost good as the 4 byte value,
+ * and might be faster on some machines
+ */
+/*
+#define hashit(c) (((ulong)(c) * 0x6b43a9) >> (24 - HashLog))
+*/
+#define hashit(c) ((((ulong)(c) & 0xffffff) * 0x6b43a9b5) >> (32 - HashLog))
+
+/*
+ * lempel-ziv style compression state
+ */
+struct LZstate
+{
+ uchar hist[HistSize];
+ ulong pos; /* current location in history buffer */
+ ulong avail; /* data available after pos */
+ int eof;
+ ushort hash[HashSize]; /* hash chains */
+ ushort nexts[MaxOff];
+ int now; /* pos in hash chains */
+ int dot; /* dawn of time in history */
+ int prevlen; /* lazy matching state */
+ int prevoff;
+ int maxcheck; /* compressor tuning */
+
+ uchar obuf[DeflateOut];
+ uchar *out; /* current position in the output buffer */
+ uchar *eout;
+ ulong bits; /* bit shift register */
+ int nbits;
+ int rbad; /* got an error reading the buffer */
+ int wbad; /* got an error writing the buffer */
+ int (*w)(void*, void*, int);
+ void *wr;
+
+ ulong totr; /* total input size */
+ ulong totw; /* total output size */
+ int debug;
+};
+
+struct LZblock
+{
+ ushort parse[DeflateMaxBlock / 2 + 1];
+ int lastv; /* value being constucted for parse */
+ ulong litlencount[Nlitlen];
+ ulong offcount[Noff];
+ ushort *eparse; /* limit for parse table */
+ int bytes; /* consumed from the input */
+ int excost; /* cost of encoding extra len & off bits */
+};
+
+/*
+ * huffman code table
+ */
+struct Huff
+{
+ short bits; /* length of the code */
+ ushort encode; /* the code */
+};
+
+/*
+ * encoding of dynamic huffman trees
+ */
+struct Dyncode
+{
+ int nlit;
+ int noff;
+ int nclen;
+ int ncode;
+ Huff codetab[Nclen];
+ uchar codes[Nlitlen+Noff];
+ uchar codeaux[Nlitlen+Noff];
+};
+
+static int deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int));
+static int lzcomp(LZstate*, LZblock*, uchar*, ushort*, int finish);
+static void wrblock(LZstate*, int, ushort*, ushort*, Huff*, Huff*);
+static int bitcost(Huff*, ulong*, int);
+static int huffcodes(Dyncode*, Huff*, Huff*);
+static void wrdyncode(LZstate*, Dyncode*);
+static void lzput(LZstate*, ulong bits, int nbits);
+static void lzflushbits(LZstate*);
+static void lzflush(LZstate *lz);
+static void lzwrite(LZstate *lz, void *buf, int n);
+
+static int hufftabinit(Huff*, int, ulong*, int);
+static int mkgzprecode(Huff*, ulong *, int, int);
+
+static int mkprecode(Huff*, ulong *, int, int, ulong*);
+static void nextchain(Chains*, int);
+static void leafsort(ulong*, ushort*, int, int);
+
+/* conversion from len to code word */
+static int lencode[MaxMatch];
+
+/*
+ * conversion from off to code word
+ * off <= MaxOffCode ? offcode[off] : bigoffcode[off >> 7]
+*/
+static int offcode[MaxOffCode];
+static int bigoffcode[256];
+
+/* litlen code words LenStart-285 extra bits */
+static int litlenbase[Nlitlen-LenStart];
+static int litlenextra[Nlitlen-LenStart] =
+{
+/* 257 */ 0, 0, 0,
+/* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
+/* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
+/* 280 */ 4, 5, 5, 5, 5, 0, 0, 0
+};
+
+/* offset code word extra bits */
+static int offbase[Noff];
+static int offextra[] =
+{
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
+ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
+ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
+ 0, 0,
+};
+
+/* order code lengths */
+static int clenorder[Nclen] =
+{
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+};
+
+/* static huffman tables */
+static Huff litlentab[Nlitlen];
+static Huff offtab[Noff];
+static Huff hofftab[Noff];
+
+/* bit reversal for brain dead endian swap in huffman codes */
+static uchar revtab[256];
+static ulong nlits;
+static ulong nmatches;
+
+int
+deflateinit(void)
+{
+ ulong bitcount[MaxHuffBits];
+ int i, j, ci, n;
+
+ /* byte reverse table */
+ for(i=0; i<256; i++)
+ for(j=0; j<8; j++)
+ if(i & (1<<j))
+ revtab[i] |= 0x80 >> j;
+
+ /* static Litlen bit lengths */
+ for(i=0; i<144; i++)
+ litlentab[i].bits = 8;
+ for(i=144; i<256; i++)
+ litlentab[i].bits = 9;
+ for(i=256; i<280; i++)
+ litlentab[i].bits = 7;
+ for(i=280; i<Nlitlen; i++)
+ litlentab[i].bits = 8;
+
+ memset(bitcount, 0, sizeof(bitcount));
+ bitcount[8] += 144 - 0;
+ bitcount[9] += 256 - 144;
+ bitcount[7] += 280 - 256;
+ bitcount[8] += Nlitlen - 280;
+
+ if(!hufftabinit(litlentab, Nlitlen, bitcount, 9))
+ return FlateInternal;
+
+ /* static offset bit lengths */
+ for(i = 0; i < Noff; i++)
+ offtab[i].bits = 5;
+
+ memset(bitcount, 0, sizeof(bitcount));
+ bitcount[5] = Noff;
+
+ if(!hufftabinit(offtab, Noff, bitcount, 5))
+ return FlateInternal;
+
+ bitcount[0] = 0;
+ bitcount[1] = 0;
+ if(!mkgzprecode(hofftab, bitcount, 2, MaxHuffBits))
+ return FlateInternal;
+
+ /* conversion tables for lens & offs to codes */
+ ci = 0;
+ for(i = LenStart; i < 286; i++){
+ n = ci + (1 << litlenextra[i - LenStart]);
+ litlenbase[i - LenStart] = ci;
+ for(; ci < n; ci++)
+ lencode[ci] = i;
+ }
+ /* patch up special case for len MaxMatch */
+ lencode[MaxMatch-MinMatch] = 285;
+ litlenbase[285-LenStart] = MaxMatch-MinMatch;
+
+ ci = 0;
+ for(i = 0; i < 16; i++){
+ n = ci + (1 << offextra[i]);
+ offbase[i] = ci;
+ for(; ci < n; ci++)
+ offcode[ci] = i;
+ }
+
+ ci = ci >> 7;
+ for(; i < 30; i++){
+ n = ci + (1 << (offextra[i] - 7));
+ offbase[i] = ci << 7;
+ for(; ci < n; ci++)
+ bigoffcode[ci] = i;
+ }
+ return FlateOk;
+}
+
+static void
+deflatereset(LZstate *lz, int level, int debug)
+{
+ memset(lz->nexts, 0, sizeof lz->nexts);
+ memset(lz->hash, 0, sizeof lz->hash);
+ lz->totr = 0;
+ lz->totw = 0;
+ lz->pos = 0;
+ lz->avail = 0;
+ lz->out = lz->obuf;
+ lz->eout = &lz->obuf[DeflateOut];
+ lz->prevlen = MinMatch - 1;
+ lz->prevoff = 0;
+ lz->now = MaxOff + 1;
+ lz->dot = lz->now;
+ lz->bits = 0;
+ lz->nbits = 0;
+ lz->maxcheck = (1 << level);
+ lz->maxcheck -= lz->maxcheck >> 2;
+ if(lz->maxcheck < 2)
+ lz->maxcheck = 2;
+ else if(lz->maxcheck > 1024)
+ lz->maxcheck = 1024;
+
+ lz->debug = debug;
+}
+
+int
+deflate(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
+{
+ LZstate *lz;
+ LZblock *lzb;
+ int ok;
+
+ lz = malloc(sizeof *lz + sizeof *lzb);
+ if(lz == nil)
+ return FlateNoMem;
+ lzb = (LZblock*)&lz[1];
+
+ deflatereset(lz, level, debug);
+ lz->w = w;
+ lz->wr = wr;
+ lz->wbad = 0;
+ lz->rbad = 0;
+ lz->eof = 0;
+ ok = FlateOk;
+ while(!lz->eof || lz->avail){
+ ok = deflateb(lz, lzb, rr, r);
+ if(ok != FlateOk)
+ break;
+ }
+ if(ok == FlateOk && lz->rbad)
+ ok = FlateInputFail;
+ if(ok == FlateOk && lz->wbad)
+ ok = FlateOutputFail;
+ free(lz);
+ return ok;
+}
+
+static int
+deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int))
+{
+ Dyncode dyncode, hdyncode;
+ Huff dlitlentab[Nlitlen], dofftab[Noff], hlitlentab[Nlitlen];
+ ulong litcount[Nlitlen];
+ long nunc, ndyn, nfix, nhuff;
+ uchar *slop, *hslop;
+ ulong ep;
+ int i, n, m, mm, nslop;
+
+ memset(lzb->litlencount, 0, sizeof lzb->litlencount);
+ memset(lzb->offcount, 0, sizeof lzb->offcount);
+ lzb->litlencount[DeflateEob]++;
+
+ lzb->bytes = 0;
+ lzb->eparse = lzb->parse;
+ lzb->lastv = 0;
+ lzb->excost = 0;
+
+ slop = &lz->hist[lz->pos];
+ n = lz->avail;
+ while(n < DeflateBlock && (!lz->eof || lz->avail)){
+ /*
+ * fill the buffer as much as possible,
+ * while leaving room for MaxOff history behind lz->pos,
+ * and not reading more than we can handle.
+ *
+ * make sure we read at least HistSlop bytes.
+ */
+ if(!lz->eof){
+ ep = lz->pos + lz->avail;
+ if(ep >= HistBlock)
+ ep -= HistBlock;
+ m = HistBlock - MaxOff - lz->avail;
+ if(m > HistBlock - n)
+ m = HistBlock - n;
+ if(m > (HistBlock + HistSlop) - ep)
+ m = (HistBlock + HistSlop) - ep;
+ if(m & ~(BlockSize - 1))
+ m &= ~(BlockSize - 1);
+
+ /*
+ * be nice to the caller: stop reads that are too small.
+ * can only get here when we've already filled the buffer some
+ */
+ if(m < HistSlop){
+ if(!m || !lzb->bytes)
+ return FlateInternal;
+ break;
+ }
+
+ mm = (*r)(rr, &lz->hist[ep], m);
+ if(mm > 0){
+ /*
+ * wrap data to end if we're read it from the beginning
+ * this way, we don't have to wrap searches.
+ *
+ * wrap reads past the end to the beginning.
+ * this way, we can guarantee minimum size reads.
+ */
+ if(ep < HistSlop)
+ memmove(&lz->hist[ep + HistBlock], &lz->hist[ep], HistSlop - ep);
+ else if(ep + mm > HistBlock)
+ memmove(&lz->hist[0], &lz->hist[HistBlock], ep + mm - HistBlock);
+
+ lz->totr += mm;
+ n += mm;
+ lz->avail += mm;
+ }else{
+ if(mm < 0)
+ lz->rbad = 1;
+ lz->eof = 1;
+ }
+ }
+ ep = lz->pos + lz->avail;
+ if(ep > HistSize)
+ ep = HistSize;
+ if(lzb->bytes + ep - lz->pos > DeflateMaxBlock)
+ ep = lz->pos + DeflateMaxBlock - lzb->bytes;
+ m = lzcomp(lz, lzb, &lz->hist[ep], lzb->eparse, lz->eof);
+ lzb->bytes += m;
+ lz->pos = (lz->pos + m) & (HistBlock - 1);
+ lz->avail -= m;
+ }
+ if(lzb->lastv)
+ *lzb->eparse++ = lzb->lastv;
+ if(lzb->eparse > lzb->parse + nelem(lzb->parse))
+ return FlateInternal;
+ nunc = lzb->bytes;
+
+ if(!mkgzprecode(dlitlentab, lzb->litlencount, Nlitlen, MaxHuffBits)
+ || !mkgzprecode(dofftab, lzb->offcount, Noff, MaxHuffBits))
+ return FlateInternal;
+
+ ndyn = huffcodes(&dyncode, dlitlentab, dofftab);
+ if(ndyn < 0)
+ return FlateInternal;
+ ndyn += bitcost(dlitlentab, lzb->litlencount, Nlitlen)
+ + bitcost(dofftab, lzb->offcount, Noff)
+ + lzb->excost;
+
+ memset(litcount, 0, sizeof litcount);
+
+ nslop = nunc;
+ if(nslop > &lz->hist[HistSize] - slop)
+ nslop = &lz->hist[HistSize] - slop;
+
+ for(i = 0; i < nslop; i++)
+ litcount[slop[i]]++;
+ hslop = &lz->hist[HistSlop - nslop];
+ for(; i < nunc; i++)
+ litcount[hslop[i]]++;
+ litcount[DeflateEob]++;
+
+ if(!mkgzprecode(hlitlentab, litcount, Nlitlen, MaxHuffBits))
+ return FlateInternal;
+ nhuff = huffcodes(&hdyncode, hlitlentab, hofftab);
+ if(nhuff < 0)
+ return FlateInternal;
+ nhuff += bitcost(hlitlentab, litcount, Nlitlen);
+
+ nfix = bitcost(litlentab, lzb->litlencount, Nlitlen)
+ + bitcost(offtab, lzb->offcount, Noff)
+ + lzb->excost;
+
+ lzput(lz, lz->eof && !lz->avail, 1);
+
+ if(lz->debug){
+ fprint(2, "block: bytes=%lud entries=%ld extra bits=%d\n\tuncompressed=%lud fixed=%lud dynamic=%lud huffman=%lud\n",
+ nunc, lzb->eparse - lzb->parse, lzb->excost, (nunc + 4) * 8, nfix, ndyn, nhuff);
+ fprint(2, "\tnlit=%lud matches=%lud eof=%d\n", nlits, nmatches, lz->eof && !lz->avail);
+ }
+
+ if((nunc + 4) * 8 < ndyn && (nunc + 4) * 8 < nfix && (nunc + 4) * 8 < nhuff){
+ lzput(lz, DeflateUnc, 2);
+ lzflushbits(lz);
+
+ lzput(lz, nunc & 0xff, 8);
+ lzput(lz, (nunc >> 8) & 0xff, 8);
+ lzput(lz, ~nunc & 0xff, 8);
+ lzput(lz, (~nunc >> 8) & 0xff, 8);
+ lzflush(lz);
+
+ lzwrite(lz, slop, nslop);
+ lzwrite(lz, &lz->hist[HistSlop], nunc - nslop);
+ }else if(ndyn < nfix && ndyn < nhuff){
+ lzput(lz, DeflateDyn, 2);
+
+ wrdyncode(lz, &dyncode);
+ wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, dlitlentab, dofftab);
+ lzput(lz, dlitlentab[DeflateEob].encode, dlitlentab[DeflateEob].bits);
+ }else if(nhuff < nfix){
+ lzput(lz, DeflateDyn, 2);
+
+ wrdyncode(lz, &hdyncode);
+
+ m = 0;
+ for(i = nunc; i > MaxLitRun; i -= MaxLitRun)
+ lzb->parse[m++] = MaxLitRun;
+ lzb->parse[m++] = i;
+
+ wrblock(lz, slop - lz->hist, lzb->parse, lzb->parse + m, hlitlentab, hofftab);
+ lzput(lz, hlitlentab[DeflateEob].encode, hlitlentab[DeflateEob].bits);
+ }else{
+ lzput(lz, DeflateFix, 2);
+
+ wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, litlentab, offtab);
+ lzput(lz, litlentab[DeflateEob].encode, litlentab[DeflateEob].bits);
+ }
+
+ if(lz->eof && !lz->avail){
+ lzflushbits(lz);
+ lzflush(lz);
+ }
+ return FlateOk;
+}
+
+static void
+lzwrite(LZstate *lz, void *buf, int n)
+{
+ int nw;
+
+ if(n && lz->w){
+ nw = (*lz->w)(lz->wr, buf, n);
+ if(nw != n){
+ lz->w = nil;
+ lz->wbad = 1;
+ }else
+ lz->totw += n;
+ }
+}
+
+static void
+lzflush(LZstate *lz)
+{
+ lzwrite(lz, lz->obuf, lz->out - lz->obuf);
+ lz->out = lz->obuf;
+}
+
+static void
+lzput(LZstate *lz, ulong bits, int nbits)
+{
+ bits = (bits << lz->nbits) | lz->bits;
+ for(nbits += lz->nbits; nbits >= 8; nbits -= 8){
+ *lz->out++ = bits;
+ if(lz->out == lz->eout)
+ lzflush(lz);
+ bits >>= 8;
+ }
+ lz->bits = bits;
+ lz->nbits = nbits;
+}
+
+static void
+lzflushbits(LZstate *lz)
+{
+ if(lz->nbits)
+ lzput(lz, 0, 8 - (lz->nbits & 7));
+}
+
+/*
+ * write out a block of n samples,
+ * given lz encoding and counts for huffman tables
+ */
+static void
+wrblock(LZstate *out, int litoff, ushort *soff, ushort *eoff, Huff *litlentab, Huff *offtab)
+{
+ ushort *off;
+ int i, run, offset, lit, len, c;
+
+ if(out->debug > 2){
+ for(off = soff; off < eoff; ){
+ offset = *off++;
+ run = offset & MaxLitRun;
+ if(run){
+ for(i = 0; i < run; i++){
+ lit = out->hist[litoff & (HistBlock - 1)];
+ litoff++;
+ fprint(2, "\tlit %.2ux %c\n", lit, lit);
+ }
+ if(!(offset & LenFlag))
+ continue;
+ len = offset >> LenShift;
+ offset = *off++;
+ }else if(offset & LenFlag){
+ len = offset >> LenShift;
+ offset = *off++;
+ }else{
+ len = 0;
+ offset >>= LenShift;
+ }
+ litoff += len + MinMatch;
+ fprint(2, "\t<%d, %d>\n", offset + 1, len + MinMatch);
+ }
+ }
+
+ for(off = soff; off < eoff; ){
+ offset = *off++;
+ run = offset & MaxLitRun;
+ if(run){
+ for(i = 0; i < run; i++){
+ lit = out->hist[litoff & (HistBlock - 1)];
+ litoff++;
+ lzput(out, litlentab[lit].encode, litlentab[lit].bits);
+ }
+ if(!(offset & LenFlag))
+ continue;
+ len = offset >> LenShift;
+ offset = *off++;
+ }else if(offset & LenFlag){
+ len = offset >> LenShift;
+ offset = *off++;
+ }else{
+ len = 0;
+ offset >>= LenShift;
+ }
+ litoff += len + MinMatch;
+ c = lencode[len];
+ lzput(out, litlentab[c].encode, litlentab[c].bits);
+ c -= LenStart;
+ if(litlenextra[c])
+ lzput(out, len - litlenbase[c], litlenextra[c]);
+
+ if(offset < MaxOffCode)
+ c = offcode[offset];
+ else
+ c = bigoffcode[offset >> 7];
+ lzput(out, offtab[c].encode, offtab[c].bits);
+ if(offextra[c])
+ lzput(out, offset - offbase[c], offextra[c]);
+ }
+}
+
+/*
+ * look for the longest, closest string which matches
+ * the next prefix. the clever part here is looking for
+ * a string 1 longer than the previous best match.
+ *
+ * follows the recommendation of limiting number of chains
+ * which are checked. this appears to be the best heuristic.
+ */
+static int
+lzmatch(int now, int then, uchar *p, uchar *es, ushort *nexts, uchar *hist, int runlen, int check, int *m)
+{
+ uchar *s, *t;
+ int ml, off, last;
+
+ ml = check;
+ if(runlen >= 8)
+ check >>= 2;
+ *m = 0;
+ if(p + runlen >= es)
+ return runlen;
+ last = 0;
+ for(; check-- > 0; then = nexts[then & (MaxOff-1)]){
+ off = (ushort)(now - then);
+ if(off <= last || off > MaxOff)
+ break;
+ s = p + runlen;
+ t = hist + (((p - hist) - off) & (HistBlock-1));
+ t += runlen;
+ for(; s >= p; s--){
+ if(*s != *t)
+ goto matchloop;
+ t--;
+ }
+
+ /*
+ * we have a new best match.
+ * extend it to it's maximum length
+ */
+ t += runlen + 2;
+ s += runlen + 2;
+ for(; s < es; s++){
+ if(*s != *t)
+ break;
+ t++;
+ }
+ runlen = s - p;
+ *m = off - 1;
+ if(s == es || runlen > ml)
+ break;
+matchloop:;
+ last = off;
+ }
+ return runlen;
+}
+
+static int
+lzcomp(LZstate *lz, LZblock *lzb, uchar *ep, ushort *parse, int finish)
+{
+ ulong cont, excost, *litlencount, *offcount;
+ uchar *p, *q, *s, *es;
+ ushort *nexts, *hash;
+ int v, i, h, runlen, n, now, then, m, prevlen, prevoff, maxdefer;
+
+ litlencount = lzb->litlencount;
+ offcount = lzb->offcount;
+ nexts = lz->nexts;
+ hash = lz->hash;
+ now = lz->now;
+
+ p = &lz->hist[lz->pos];
+ if(lz->prevlen != MinMatch - 1)
+ p++;
+
+ /*
+ * hash in the links for any hanging link positions,
+ * and calculate the hash for the current position.
+ */
+ n = MinMatch;
+ if(n > ep - p)
+ n = ep - p;
+ cont = 0;
+ for(i = 0; i < n - 1; i++){
+ m = now - ((MinMatch-1) - i);
+ if(m < lz->dot)
+ continue;
+ s = lz->hist + (((p - lz->hist) - (now - m)) & (HistBlock-1));
+
+ cont = (s[0] << 16) | (s[1] << 8) | s[2];
+ h = hashit(cont);
+ prevoff = 0;
+ for(then = hash[h]; ; then = nexts[then & (MaxOff-1)]){
+ v = (ushort)(now - then);
+ if(v <= prevoff || v >= (MinMatch-1) - i)
+ break;
+ prevoff = v;
+ }
+ if(then == (ushort)m)
+ continue;
+ nexts[m & (MaxOff-1)] = hash[h];
+ hash[h] = m;
+ }
+ for(i = 0; i < n; i++)
+ cont = (cont << 8) | p[i];
+
+ /*
+ * now must point to the index in the nexts array
+ * corresponding to p's position in the history
+ */
+ prevlen = lz->prevlen;
+ prevoff = lz->prevoff;
+ maxdefer = lz->maxcheck >> 2;
+ excost = 0;
+ v = lzb->lastv;
+ for(;;){
+ es = p + MaxMatch;
+ if(es > ep){
+ if(!finish || p >= ep)
+ break;
+ es = ep;
+ }
+
+ h = hashit(cont);
+ runlen = lzmatch(now, hash[h], p, es, nexts, lz->hist, prevlen, lz->maxcheck, &m);
+
+ /*
+ * back out of small matches too far in the past
+ */
+ if(runlen == MinMatch && m >= MinMatchMaxOff){
+ runlen = MinMatch - 1;
+ m = 0;
+ }
+
+ /*
+ * record the encoding and increment counts for huffman trees
+ * if we get a match, defer selecting it until we check for
+ * a longer match at the next position.
+ */
+ if(prevlen >= runlen && prevlen != MinMatch - 1){
+ /*
+ * old match at least as good; use that one
+ */
+ n = prevlen - MinMatch;
+ if(v || n){
+ *parse++ = v | LenFlag | (n << LenShift);
+ *parse++ = prevoff;
+ }else
+ *parse++ = prevoff << LenShift;
+ v = 0;
+
+ n = lencode[n];
+ litlencount[n]++;
+ excost += litlenextra[n - LenStart];
+
+ if(prevoff < MaxOffCode)
+ n = offcode[prevoff];
+ else
+ n = bigoffcode[prevoff >> 7];
+ offcount[n]++;
+ excost += offextra[n];
+
+ runlen = prevlen - 1;
+ prevlen = MinMatch - 1;
+ nmatches++;
+ }else if(runlen == MinMatch - 1){
+ /*
+ * no match; just put out the literal
+ */
+ if(++v == MaxLitRun){
+ *parse++ = v;
+ v = 0;
+ }
+ litlencount[*p]++;
+ nlits++;
+ runlen = 1;
+ }else{
+ if(prevlen != MinMatch - 1){
+ /*
+ * longer match now. output previous literal,
+ * update current match, and try again
+ */
+ if(++v == MaxLitRun){
+ *parse++ = v;
+ v = 0;
+ }
+ litlencount[p[-1]]++;
+ nlits++;
+ }
+
+ prevoff = m;
+
+ if(runlen < maxdefer){
+ prevlen = runlen;
+ runlen = 1;
+ }else{
+ n = runlen - MinMatch;
+ if(v || n){
+ *parse++ = v | LenFlag | (n << LenShift);
+ *parse++ = prevoff;
+ }else
+ *parse++ = prevoff << LenShift;
+ v = 0;
+
+ n = lencode[n];
+ litlencount[n]++;
+ excost += litlenextra[n - LenStart];
+
+ if(prevoff < MaxOffCode)
+ n = offcode[prevoff];
+ else
+ n = bigoffcode[prevoff >> 7];
+ offcount[n]++;
+ excost += offextra[n];
+
+ prevlen = MinMatch - 1;
+ nmatches++;
+ }
+ }
+
+ /*
+ * update the hash for the newly matched data
+ * this is constructed so the link for the old
+ * match in this position must be at the end of a chain,
+ * and will expire when this match is added, ie it will
+ * never be examined by the match loop.
+ * add to the hash chain only if we have the real hash data.
+ */
+ for(q = p + runlen; p != q; p++){
+ if(p + MinMatch <= ep){
+ h = hashit(cont);
+ nexts[now & (MaxOff-1)] = hash[h];
+ hash[h] = now;
+ if(p + MinMatch < ep)
+ cont = (cont << 8) | p[MinMatch];
+ }
+ now++;
+ }
+ }
+
+ /*
+ * we can just store away the lazy state and
+ * pick it up next time. the last block will have finish set
+ * so we won't have any pending matches
+ * however, we need to correct for how much we've encoded
+ */
+ if(prevlen != MinMatch - 1)
+ p--;
+
+ lzb->excost += excost;
+ lzb->eparse = parse;
+ lzb->lastv = v;
+
+ lz->now = now;
+ lz->prevlen = prevlen;
+ lz->prevoff = prevoff;
+
+ return p - &lz->hist[lz->pos];
+}
+
+/*
+ * make up the dynamic code tables, and return the number of bits
+ * needed to transmit them.
+ */
+static int
+huffcodes(Dyncode *dc, Huff *littab, Huff *offtab)
+{
+ Huff *codetab;
+ uchar *codes, *codeaux;
+ ulong codecount[Nclen], excost;
+ int i, n, m, v, c, nlit, noff, ncode, nclen;
+
+ codetab = dc->codetab;
+ codes = dc->codes;
+ codeaux = dc->codeaux;
+
+ /*
+ * trim the sizes of the tables
+ */
+ for(nlit = Nlitlen; nlit > 257 && littab[nlit-1].bits == 0; nlit--)
+ ;
+ for(noff = Noff; noff > 1 && offtab[noff-1].bits == 0; noff--)
+ ;
+
+ /*
+ * make the code-length code
+ */
+ for(i = 0; i < nlit; i++)
+ codes[i] = littab[i].bits;
+ for(i = 0; i < noff; i++)
+ codes[i + nlit] = offtab[i].bits;
+
+ /*
+ * run-length compress the code-length code
+ */
+ excost = 0;
+ c = 0;
+ ncode = nlit+noff;
+ for(i = 0; i < ncode; ){
+ n = i + 1;
+ v = codes[i];
+ while(n < ncode && v == codes[n])
+ n++;
+ n -= i;
+ i += n;
+ if(v == 0){
+ while(n >= 11){
+ m = n;
+ if(m > 138)
+ m = 138;
+ codes[c] = 18;
+ codeaux[c++] = m - 11;
+ n -= m;
+ excost += 7;
+ }
+ if(n >= 3){
+ codes[c] = 17;
+ codeaux[c++] = n - 3;
+ n = 0;
+ excost += 3;
+ }
+ }
+ while(n--){
+ codes[c++] = v;
+ while(n >= 3){
+ m = n;
+ if(m > 6)
+ m = 6;
+ codes[c] = 16;
+ codeaux[c++] = m - 3;
+ n -= m;
+ excost += 3;
+ }
+ }
+ }
+
+ memset(codecount, 0, sizeof codecount);
+ for(i = 0; i < c; i++)
+ codecount[codes[i]]++;
+ if(!mkgzprecode(codetab, codecount, Nclen, 8))
+ return -1;
+
+ for(nclen = Nclen; nclen > 4 && codetab[clenorder[nclen-1]].bits == 0; nclen--)
+ ;
+
+ dc->nlit = nlit;
+ dc->noff = noff;
+ dc->nclen = nclen;
+ dc->ncode = c;
+
+ return 5 + 5 + 4 + nclen * 3 + bitcost(codetab, codecount, Nclen) + excost;
+}
+
+static void
+wrdyncode(LZstate *out, Dyncode *dc)
+{
+ Huff *codetab;
+ uchar *codes, *codeaux;
+ int i, v, c;
+
+ /*
+ * write out header, then code length code lengths,
+ * and code lengths
+ */
+ lzput(out, dc->nlit-257, 5);
+ lzput(out, dc->noff-1, 5);
+ lzput(out, dc->nclen-4, 4);
+
+ codetab = dc->codetab;
+ for(i = 0; i < dc->nclen; i++)
+ lzput(out, codetab[clenorder[i]].bits, 3);
+
+ codes = dc->codes;
+ codeaux = dc->codeaux;
+ c = dc->ncode;
+ for(i = 0; i < c; i++){
+ v = codes[i];
+ lzput(out, codetab[v].encode, codetab[v].bits);
+ if(v >= 16){
+ if(v == 16)
+ lzput(out, codeaux[i], 2);
+ else if(v == 17)
+ lzput(out, codeaux[i], 3);
+ else /* v == 18 */
+ lzput(out, codeaux[i], 7);
+ }
+ }
+}
+
+static int
+bitcost(Huff *tab, ulong *count, int n)
+{
+ ulong tot;
+ int i;
+
+ tot = 0;
+ for(i = 0; i < n; i++)
+ tot += count[i] * tab[i].bits;
+ return tot;
+}
+
+static int
+mkgzprecode(Huff *tab, ulong *count, int n, int maxbits)
+{
+ ulong bitcount[MaxHuffBits];
+ int i, nbits;
+
+ nbits = mkprecode(tab, count, n, maxbits, bitcount);
+ for(i = 0; i < n; i++){
+ if(tab[i].bits == -1)
+ tab[i].bits = 0;
+ else if(tab[i].bits == 0){
+ if(nbits != 0 || bitcount[0] != 1)
+ return 0;
+ bitcount[1] = 1;
+ bitcount[0] = 0;
+ nbits = 1;
+ tab[i].bits = 1;
+ }
+ }
+ if(bitcount[0] != 0)
+ return 0;
+ return hufftabinit(tab, n, bitcount, nbits);
+}
+
+static int
+hufftabinit(Huff *tab, int n, ulong *bitcount, int nbits)
+{
+ ulong code, nc[MaxHuffBits];
+ int i, bits;
+
+ code = 0;
+ for(bits = 1; bits <= nbits; bits++){
+ code = (code + bitcount[bits-1]) << 1;
+ nc[bits] = code;
+ }
+
+ for(i = 0; i < n; i++){
+ bits = tab[i].bits;
+ if(bits){
+ code = nc[bits]++ << (16 - bits);
+ if(code & ~0xffff)
+ return 0;
+ tab[i].encode = revtab[code >> 8] | (revtab[code & 0xff] << 8);
+ }
+ }
+ return 1;
+}
+
+
+/*
+ * this should be in a library
+ */
+struct Chain
+{
+ ulong count; /* occurances of everything in the chain */
+ ushort leaf; /* leaves to the left of chain, or leaf value */
+ char col; /* ref count for collecting unused chains */
+ char gen; /* need to generate chains for next lower level */
+ Chain *up; /* Chain up in the lists */
+};
+
+struct Chains
+{
+ Chain *lists[(MaxHuffBits - 1) * 2];
+ ulong leafcount[MaxLeaf]; /* sorted list of leaf counts */
+ ushort leafmap[MaxLeaf]; /* map to actual leaf number */
+ int nleaf; /* number of leaves */
+ Chain chains[ChainMem];
+ Chain *echains;
+ Chain *free;
+ char col;
+ int nlists;
+};
+
+/*
+ * fast, low space overhead algorithm for max depth huffman type codes
+ *
+ * J. Katajainen, A. Moffat and A. Turpin, "A fast and space-economical
+ * algorithm for length-limited coding," Proc. Intl. Symp. on Algorithms
+ * and Computation, Cairns, Australia, Dec. 1995, Lecture Notes in Computer
+ * Science, Vol 1004, J. Staples, P. Eades, N. Katoh, and A. Moffat, eds.,
+ * pp 12-21, Springer Verlag, New York, 1995.
+ */
+static int
+mkprecode(Huff *tab, ulong *count, int n, int maxbits, ulong *bitcount)
+{
+ Chains cs;
+ Chain *c;
+ int i, m, em, bits;
+
+ /*
+ * set up the sorted list of leaves
+ */
+ m = 0;
+ for(i = 0; i < n; i++){
+ tab[i].bits = -1;
+ tab[i].encode = 0;
+ if(count[i] != 0){
+ cs.leafcount[m] = count[i];
+ cs.leafmap[m] = i;
+ m++;
+ }
+ }
+ if(m < 2){
+ if(m != 0){
+ tab[cs.leafmap[0]].bits = 0;
+ bitcount[0] = 1;
+ }else
+ bitcount[0] = 0;
+ return 0;
+ }
+ cs.nleaf = m;
+ leafsort(cs.leafcount, cs.leafmap, 0, m);
+
+ for(i = 0; i < m; i++)
+ cs.leafcount[i] = count[cs.leafmap[i]];
+
+ /*
+ * set up free list
+ */
+ cs.free = &cs.chains[2];
+ cs.echains = &cs.chains[ChainMem];
+ cs.col = 1;
+
+ /*
+ * initialize chains for each list
+ */
+ c = &cs.chains[0];
+ c->count = cs.leafcount[0];
+ c->leaf = 1;
+ c->col = cs.col;
+ c->up = nil;
+ c->gen = 0;
+ cs.chains[1] = cs.chains[0];
+ cs.chains[1].leaf = 2;
+ cs.chains[1].count = cs.leafcount[1];
+ for(i = 0; i < maxbits-1; i++){
+ cs.lists[i * 2] = &cs.chains[0];
+ cs.lists[i * 2 + 1] = &cs.chains[1];
+ }
+
+ cs.nlists = 2 * (maxbits - 1);
+ m = 2 * m - 2;
+ for(i = 2; i < m; i++)
+ nextchain(&cs, cs.nlists - 2);
+
+ bits = 0;
+ bitcount[0] = cs.nleaf;
+ for(c = cs.lists[cs.nlists - 1]; c != nil; c = c->up){
+ m = c->leaf;
+ bitcount[bits++] -= m;
+ bitcount[bits] = m;
+ }
+ m = 0;
+ for(i = bits; i >= 0; i--)
+ for(em = m + bitcount[i]; m < em; m++)
+ tab[cs.leafmap[m]].bits = i;
+
+ return bits;
+}
+
+/*
+ * calculate the next chain on the list
+ * we can always toss out the old chain
+ */
+static void
+nextchain(Chains *cs, int list)
+{
+ Chain *c, *oc;
+ int i, nleaf, sumc;
+
+ oc = cs->lists[list + 1];
+ cs->lists[list] = oc;
+ if(oc == nil)
+ return;
+
+ /*
+ * make sure we have all chains needed to make sumc
+ * note it is possible to generate only one of these,
+ * use twice that value for sumc, and then generate
+ * the second if that preliminary sumc would be chosen.
+ * however, this appears to be slower on current tests
+ */
+ if(oc->gen){
+ nextchain(cs, list - 2);
+ nextchain(cs, list - 2);
+ oc->gen = 0;
+ }
+
+ /*
+ * pick up the chain we're going to add;
+ * collect unused chains no free ones are left
+ */
+ for(c = cs->free; ; c++){
+ if(c >= cs->echains){
+ cs->col++;
+ for(i = 0; i < cs->nlists; i++)
+ for(c = cs->lists[i]; c != nil; c = c->up)
+ c->col = cs->col;
+ c = cs->chains;
+ }
+ if(c->col != cs->col)
+ break;
+ }
+
+ /*
+ * pick the cheapest of
+ * 1) the next package from the previous list
+ * 2) the next leaf
+ */
+ nleaf = oc->leaf;
+ sumc = 0;
+ if(list > 0 && cs->lists[list-1] != nil)
+ sumc = cs->lists[list-2]->count + cs->lists[list-1]->count;
+ if(sumc != 0 && (nleaf >= cs->nleaf || cs->leafcount[nleaf] > sumc)){
+ c->count = sumc;
+ c->leaf = oc->leaf;
+ c->up = cs->lists[list-1];
+ c->gen = 1;
+ }else if(nleaf >= cs->nleaf){
+ cs->lists[list + 1] = nil;
+ return;
+ }else{
+ c->leaf = nleaf + 1;
+ c->count = cs->leafcount[nleaf];
+ c->up = oc->up;
+ c->gen = 0;
+ }
+ cs->free = c + 1;
+
+ cs->lists[list + 1] = c;
+ c->col = cs->col;
+}
+
+static int
+pivot(ulong *c, int a, int n)
+{
+ int j, pi, pj, pk;
+
+ j = n/6;
+ pi = a + j; /* 1/6 */
+ j += j;
+ pj = pi + j; /* 1/2 */
+ pk = pj + j; /* 5/6 */
+ if(c[pi] < c[pj]){
+ if(c[pi] < c[pk]){
+ if(c[pj] < c[pk])
+ return pj;
+ return pk;
+ }
+ return pi;
+ }
+ if(c[pj] < c[pk]){
+ if(c[pi] < c[pk])
+ return pi;
+ return pk;
+ }
+ return pj;
+}
+
+static void
+leafsort(ulong *leafcount, ushort *leafmap, int a, int n)
+{
+ ulong t;
+ int j, pi, pj, pn;
+
+ while(n > 1){
+ if(n > 10){
+ pi = pivot(leafcount, a, n);
+ }else
+ pi = a + (n>>1);
+
+ t = leafcount[pi];
+ leafcount[pi] = leafcount[a];
+ leafcount[a] = t;
+ t = leafmap[pi];
+ leafmap[pi] = leafmap[a];
+ leafmap[a] = t;
+ pi = a;
+ pn = a + n;
+ pj = pn;
+ for(;;){
+ do
+ pi++;
+ while(pi < pn && (leafcount[pi] < leafcount[a] || leafcount[pi] == leafcount[a] && leafmap[pi] > leafmap[a]));
+ do
+ pj--;
+ while(pj > a && (leafcount[pj] > leafcount[a] || leafcount[pj] == leafcount[a] && leafmap[pj] < leafmap[a]));
+ if(pj < pi)
+ break;
+ t = leafcount[pi];
+ leafcount[pi] = leafcount[pj];
+ leafcount[pj] = t;
+ t = leafmap[pi];
+ leafmap[pi] = leafmap[pj];
+ leafmap[pj] = t;
+ }
+ t = leafcount[a];
+ leafcount[a] = leafcount[pj];
+ leafcount[pj] = t;
+ t = leafmap[a];
+ leafmap[a] = leafmap[pj];
+ leafmap[pj] = t;
+ j = pj - a;
+
+ n = n-j-1;
+ if(j >= n){
+ leafsort(leafcount, leafmap, a, j);
+ a += j+1;
+ }else{
+ leafsort(leafcount, leafmap, a + (j+1), n);
+ n = j;
+ }
+ }
+}
--- /dev/null
+++ b/os/boot.original/libflate/deflateblock.c
@@ -1,0 +1,55 @@
+#include "lib9.h"
+#include <flate.h>
+
+typedef struct Block Block;
+
+struct Block
+{
+ uchar *pos;
+ uchar *limit;
+};
+
+static int
+blread(void *vb, void *buf, int n)
+{
+ Block *b;
+
+ b = vb;
+ if(n > b->limit - b->pos)
+ n = b->limit - b->pos;
+ memmove(buf, b->pos, n);
+ b->pos += n;
+ return n;
+}
+
+static int
+blwrite(void *vb, void *buf, int n)
+{
+ Block *b;
+
+ b = vb;
+
+ if(n > b->limit - b->pos)
+ n = b->limit - b->pos;
+ memmove(b->pos, buf, n);
+ b->pos += n;
+ return n;
+}
+
+int
+deflateblock(uchar *dst, int dsize, uchar *src, int ssize, int level, int debug)
+{
+ Block bd, bs;
+ int ok;
+
+ bs.pos = src;
+ bs.limit = src + ssize;
+
+ bd.pos = dst;
+ bd.limit = dst + dsize;
+
+ ok = deflate(&bd, blwrite, &bs, blread, level, debug);
+ if(ok != FlateOk)
+ return ok;
+ return bd.pos - dst;
+}
--- /dev/null
+++ b/os/boot.original/libflate/deflatezlib.c
@@ -1,0 +1,59 @@
+#include "lib9.h"
+#include <flate.h>
+#include "zlib.h"
+
+typedef struct ZRead ZRead;
+
+struct ZRead
+{
+ ulong adler;
+ void *rr;
+ int (*r)(void*, void*, int);
+};
+
+static int
+zlread(void *vzr, void *buf, int n)
+{
+ ZRead *zr;
+
+ zr = vzr;
+ n = (*zr->r)(zr->rr, buf, n);
+ if(n <= 0)
+ return n;
+ zr->adler = adler32(zr->adler, buf, n);
+ return n;
+}
+
+int
+deflatezlib(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
+{
+ ZRead zr;
+ uchar buf[4];
+ int ok;
+
+ buf[0] = ZlibDeflate | ZlibWin32k;
+
+ /* bogus zlib encoding of compression level */
+ buf[1] = ((level > 2) + (level > 5) + (level > 8)) << 6;
+
+ /* header check field */
+ buf[1] |= 31 - ((buf[0] << 8) | buf[1]) % 31;
+ if((*w)(wr, buf, 2) != 2)
+ return FlateOutputFail;
+
+ zr.rr = rr;
+ zr.r = r;
+ zr.adler = 1;
+ ok = deflate(wr, w, &zr, zlread, level, debug);
+ if(ok != FlateOk)
+ return ok;
+
+ buf[0] = zr.adler >> 24;
+ buf[1] = zr.adler >> 16;
+ buf[2] = zr.adler >> 8;
+ buf[3] = zr.adler;
+ if((*w)(wr, buf, 4) != 4)
+ return FlateOutputFail;
+
+ return FlateOk;
+}
--- /dev/null
+++ b/os/boot.original/libflate/deflatezlibblock.c
@@ -1,0 +1,33 @@
+#include "lib9.h"
+#include <flate.h>
+#include "zlib.h"
+
+int
+deflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize, int level, int debug)
+{
+ ulong adler;
+ int n;
+
+ if(dsize < 6)
+ return FlateOutputFail;
+
+ n = deflateblock(dst + 2, dsize - 6, src, ssize, level, debug);
+ if(n < 0)
+ return n;
+
+ dst[0] = ZlibDeflate | ZlibWin32k;
+
+ /* bogus zlib encoding of compression level */
+ dst[1] = ((level > 2) + (level > 5) + (level > 8)) << 6;
+
+ /* header check field */
+ dst[1] |= 31 - ((dst[0] << 8) | dst[1]) % 31;
+
+ adler = adler32(1, src, ssize);
+ dst[n + 2] = adler >> 24;
+ dst[n + 3] = adler >> 16;
+ dst[n + 4] = adler >> 8;
+ dst[n + 5] = adler;
+
+ return n + 6;
+}
--- /dev/null
+++ b/os/boot.original/libflate/flateerr.c
@@ -1,0 +1,22 @@
+#include "lib9.h"
+#include <flate.h>
+
+char *
+flateerr(int err)
+{
+ switch(err){
+ case FlateOk:
+ return "no error";
+ case FlateNoMem:
+ return "out of memory";
+ case FlateInputFail:
+ return "input error";
+ case FlateOutputFail:
+ return "output error";
+ case FlateCorrupted:
+ return "corrupted data";
+ case FlateInternal:
+ return "internal error";
+ }
+ return "unknown error";
+}
--- /dev/null
+++ b/os/boot.original/libflate/inflate.c
@@ -1,0 +1,692 @@
+#include "lib9.h"
+#include <flate.h>
+
+enum {
+ HistorySize= 32*1024,
+ BufSize= 4*1024,
+ MaxHuffBits= 17, /* maximum bits in a encoded code */
+ Nlitlen= 288, /* number of litlen codes */
+ Noff= 32, /* number of offset codes */
+ Nclen= 19, /* number of codelen codes */
+ LenShift= 10, /* code = len<<LenShift|code */
+ LitlenBits= 7, /* number of bits in litlen decode table */
+ OffBits= 6, /* number of bits in offset decode table */
+ ClenBits= 6, /* number of bits in code len decode table */
+ MaxFlatBits= LitlenBits,
+ MaxLeaf= Nlitlen
+};
+
+typedef struct Input Input;
+typedef struct History History;
+typedef struct Huff Huff;
+
+struct Input
+{
+ int error; /* first error encountered, or FlateOk */
+ void *wr;
+ int (*w)(void*, void*, int);
+ void *getr;
+ int (*get)(void*);
+ ulong sreg;
+ int nbits;
+};
+
+struct History
+{
+ uchar his[HistorySize];
+ uchar *cp; /* current pointer in history */
+ int full; /* his has been filled up at least once */
+};
+
+struct Huff
+{
+ int maxbits; /* max bits for any code */
+ int minbits; /* min bits to get before looking in flat */
+ int flatmask; /* bits used in "flat" fast decoding table */
+ ulong flat[1<<MaxFlatBits];
+ ulong maxcode[MaxHuffBits];
+ ulong last[MaxHuffBits];
+ ulong decode[MaxLeaf];
+};
+
+/* litlen code words 257-285 extra bits */
+static int litlenextra[Nlitlen-257] =
+{
+/* 257 */ 0, 0, 0,
+/* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
+/* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
+/* 280 */ 4, 5, 5, 5, 5, 0, 0, 0
+};
+
+static int litlenbase[Nlitlen-257];
+
+/* offset code word extra bits */
+static int offextra[Noff] =
+{
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
+ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
+ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
+ 0, 0,
+};
+static int offbase[Noff];
+
+/* order code lengths */
+static int clenorder[Nclen] =
+{
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+};
+
+/* for static huffman tables */
+static Huff litlentab;
+static Huff offtab;
+static uchar revtab[256];
+
+static int uncblock(Input *in, History*);
+static int fixedblock(Input *in, History*);
+static int dynamicblock(Input *in, History*);
+static int sregfill(Input *in, int n);
+static int sregunget(Input *in);
+static int decode(Input*, History*, Huff*, Huff*);
+static int hufftab(Huff*, char*, int, int);
+static int hdecsym(Input *in, Huff *h, int b);
+
+int
+inflateinit(void)
+{
+ char *len;
+ int i, j, base;
+
+ /* byte reverse table */
+ for(i=0; i<256; i++)
+ for(j=0; j<8; j++)
+ if(i & (1<<j))
+ revtab[i] |= 0x80 >> j;
+
+ for(i=257,base=3; i<Nlitlen; i++) {
+ litlenbase[i-257] = base;
+ base += 1<<litlenextra[i-257];
+ }
+ /* strange table entry in spec... */
+ litlenbase[285-257]--;
+
+ for(i=0,base=1; i<Noff; i++) {
+ offbase[i] = base;
+ base += 1<<offextra[i];
+ }
+
+ len = malloc(MaxLeaf);
+ if(len == nil)
+ return FlateNoMem;
+
+ /* static Litlen bit lengths */
+ for(i=0; i<144; i++)
+ len[i] = 8;
+ for(i=144; i<256; i++)
+ len[i] = 9;
+ for(i=256; i<280; i++)
+ len[i] = 7;
+ for(i=280; i<Nlitlen; i++)
+ len[i] = 8;
+
+ if(!hufftab(&litlentab, len, Nlitlen, MaxFlatBits))
+ return FlateInternal;
+
+ /* static Offset bit lengths */
+ for(i=0; i<Noff; i++)
+ len[i] = 5;
+
+ if(!hufftab(&offtab, len, Noff, MaxFlatBits))
+ return FlateInternal;
+ free(len);
+
+ return FlateOk;
+}
+
+int
+inflate(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
+{
+ History *his;
+ Input in;
+ int final, type;
+
+ his = malloc(sizeof(History));
+ if(his == nil)
+ return FlateNoMem;
+ his->cp = his->his;
+ his->full = 0;
+ in.getr = getr;
+ in.get = get;
+ in.wr = wr;
+ in.w = w;
+ in.nbits = 0;
+ in.sreg = 0;
+ in.error = FlateOk;
+
+ do {
+ if(!sregfill(&in, 3))
+ goto bad;
+ final = in.sreg & 0x1;
+ type = (in.sreg>>1) & 0x3;
+ in.sreg >>= 3;
+ in.nbits -= 3;
+ switch(type) {
+ default:
+ in.error = FlateCorrupted;
+ goto bad;
+ case 0:
+ /* uncompressed */
+ if(!uncblock(&in, his))
+ goto bad;
+ break;
+ case 1:
+ /* fixed huffman */
+ if(!fixedblock(&in, his))
+ goto bad;
+ break;
+ case 2:
+ /* dynamic huffman */
+ if(!dynamicblock(&in, his))
+ goto bad;
+ break;
+ }
+ } while(!final);
+
+ if(his->cp != his->his && (*w)(wr, his->his, his->cp - his->his) != his->cp - his->his) {
+ in.error = FlateOutputFail;
+ goto bad;
+ }
+
+ if(!sregunget(&in))
+ goto bad;
+
+ free(his);
+ if(in.error != FlateOk)
+ return FlateInternal;
+ return FlateOk;
+
+bad:
+ free(his);
+ if(in.error == FlateOk)
+ return FlateInternal;
+ return in.error;
+}
+
+static int
+uncblock(Input *in, History *his)
+{
+ int len, nlen, c;
+ uchar *hs, *hp, *he;
+
+ if(!sregunget(in))
+ return 0;
+ len = (*in->get)(in->getr);
+ len |= (*in->get)(in->getr)<<8;
+ nlen = (*in->get)(in->getr);
+ nlen |= (*in->get)(in->getr)<<8;
+ if(len != (~nlen&0xffff)) {
+ in->error = FlateCorrupted;
+ return 0;
+ }
+
+ hp = his->cp;
+ hs = his->his;
+ he = hs + HistorySize;
+
+ while(len > 0) {
+ c = (*in->get)(in->getr);
+ if(c < 0)
+ return 0;
+ *hp++ = c;
+ if(hp == he) {
+ his->full = 1;
+ if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
+ in->error = FlateOutputFail;
+ return 0;
+ }
+ hp = hs;
+ }
+ len--;
+ }
+
+ his->cp = hp;
+
+ return 1;
+}
+
+static int
+fixedblock(Input *in, History *his)
+{
+ return decode(in, his, &litlentab, &offtab);
+}
+
+static int
+dynamicblock(Input *in, History *his)
+{
+ Huff *lentab, *offtab;
+ char *len;
+ int i, j, n, c, nlit, ndist, nclen, res, nb;
+
+ if(!sregfill(in, 14))
+ return 0;
+ nlit = (in->sreg&0x1f) + 257;
+ ndist = ((in->sreg>>5) & 0x1f) + 1;
+ nclen = ((in->sreg>>10) & 0xf) + 4;
+ in->sreg >>= 14;
+ in->nbits -= 14;
+
+ if(nlit > Nlitlen || ndist > Noff || nlit < 257) {
+ in->error = FlateCorrupted;
+ return 0;
+ }
+
+ /* huff table header */
+ len = malloc(Nlitlen+Noff);
+ lentab = malloc(sizeof(Huff));
+ offtab = malloc(sizeof(Huff));
+ if(len == nil || lentab == nil || offtab == nil){
+ in->error = FlateNoMem;
+ goto bad;
+ }
+ for(i=0; i < Nclen; i++)
+ len[i] = 0;
+ for(i=0; i<nclen; i++) {
+ if(!sregfill(in, 3))
+ goto bad;
+ len[clenorder[i]] = in->sreg & 0x7;
+ in->sreg >>= 3;
+ in->nbits -= 3;
+ }
+
+ if(!hufftab(lentab, len, Nclen, ClenBits)){
+ in->error = FlateCorrupted;
+ goto bad;
+ }
+
+ n = nlit+ndist;
+ for(i=0; i<n;) {
+ nb = lentab->minbits;
+ for(;;){
+ if(in->nbits<nb && !sregfill(in, nb))
+ goto bad;
+ c = lentab->flat[in->sreg & lentab->flatmask];
+ nb = c & 0xff;
+ if(nb > in->nbits){
+ if(nb != 0xff)
+ continue;
+ c = hdecsym(in, lentab, c);
+ if(c < 0)
+ goto bad;
+ }else{
+ c >>= 8;
+ in->sreg >>= nb;
+ in->nbits -= nb;
+ }
+ break;
+ }
+
+ if(c < 16) {
+ j = 1;
+ } else if(c == 16) {
+ if(in->nbits<2 && !sregfill(in, 2))
+ goto bad;
+ j = (in->sreg&0x3)+3;
+ in->sreg >>= 2;
+ in->nbits -= 2;
+ if(i == 0) {
+ in->error = FlateCorrupted;
+ goto bad;
+ }
+ c = len[i-1];
+ } else if(c == 17) {
+ if(in->nbits<3 && !sregfill(in, 3))
+ goto bad;
+ j = (in->sreg&0x7)+3;
+ in->sreg >>= 3;
+ in->nbits -= 3;
+ c = 0;
+ } else if(c == 18) {
+ if(in->nbits<7 && !sregfill(in, 7))
+ goto bad;
+ j = (in->sreg&0x7f)+11;
+ in->sreg >>= 7;
+ in->nbits -= 7;
+ c = 0;
+ } else {
+ in->error = FlateCorrupted;
+ goto bad;
+ }
+
+ if(i+j > n) {
+ in->error = FlateCorrupted;
+ goto bad;
+ }
+
+ while(j) {
+ len[i] = c;
+ i++;
+ j--;
+ }
+ }
+
+ if(!hufftab(lentab, len, nlit, LitlenBits)
+ || !hufftab(offtab, &len[nlit], ndist, OffBits)){
+ in->error = FlateCorrupted;
+ goto bad;
+ }
+
+ res = decode(in, his, lentab, offtab);
+
+ free(len);
+ free(lentab);
+ free(offtab);
+
+ return res;
+
+bad:
+ free(len);
+ free(lentab);
+ free(offtab);
+ return 0;
+}
+
+static int
+decode(Input *in, History *his, Huff *litlentab, Huff *offtab)
+{
+ int len, off;
+ uchar *hs, *hp, *hq, *he;
+ int c;
+ int nb;
+
+ hs = his->his;
+ he = hs + HistorySize;
+ hp = his->cp;
+
+ for(;;) {
+ nb = litlentab->minbits;
+ for(;;){
+ if(in->nbits<nb && !sregfill(in, nb))
+ return 0;
+ c = litlentab->flat[in->sreg & litlentab->flatmask];
+ nb = c & 0xff;
+ if(nb > in->nbits){
+ if(nb != 0xff)
+ continue;
+ c = hdecsym(in, litlentab, c);
+ if(c < 0)
+ return 0;
+ }else{
+ c >>= 8;
+ in->sreg >>= nb;
+ in->nbits -= nb;
+ }
+ break;
+ }
+
+ if(c < 256) {
+ /* literal */
+ *hp++ = c;
+ if(hp == he) {
+ his->full = 1;
+ if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
+ in->error = FlateOutputFail;
+ return 0;
+ }
+ hp = hs;
+ }
+ continue;
+ }
+
+ if(c == 256)
+ break;
+
+ if(c > 285) {
+ in->error = FlateCorrupted;
+ return 0;
+ }
+
+ c -= 257;
+ nb = litlenextra[c];
+ if(in->nbits < nb && !sregfill(in, nb))
+ return 0;
+ len = litlenbase[c] + (in->sreg & ((1<<nb)-1));
+ in->sreg >>= nb;
+ in->nbits -= nb;
+
+ /* get offset */
+ nb = offtab->minbits;
+ for(;;){
+ if(in->nbits<nb && !sregfill(in, nb))
+ return 0;
+ c = offtab->flat[in->sreg & offtab->flatmask];
+ nb = c & 0xff;
+ if(nb > in->nbits){
+ if(nb != 0xff)
+ continue;
+ c = hdecsym(in, offtab, c);
+ if(c < 0)
+ return 0;
+ }else{
+ c >>= 8;
+ in->sreg >>= nb;
+ in->nbits -= nb;
+ }
+ break;
+ }
+
+ if(c > 29) {
+ in->error = FlateCorrupted;
+ return 0;
+ }
+
+ nb = offextra[c];
+ if(in->nbits < nb && !sregfill(in, nb))
+ return 0;
+
+ off = offbase[c] + (in->sreg & ((1<<nb)-1));
+ in->sreg >>= nb;
+ in->nbits -= nb;
+
+ hq = hp - off;
+ if(hq < hs) {
+ if(!his->full) {
+ in->error = FlateCorrupted;
+ return 0;
+ }
+ hq += HistorySize;
+ }
+
+ /* slow but correct */
+ while(len) {
+ *hp = *hq;
+ hq++;
+ hp++;
+ if(hq >= he)
+ hq = hs;
+ if(hp == he) {
+ his->full = 1;
+ if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
+ in->error = FlateOutputFail;
+ return 0;
+ }
+ hp = hs;
+ }
+ len--;
+ }
+
+ }
+
+ his->cp = hp;
+
+ return 1;
+}
+
+static int
+revcode(int c, int b)
+{
+ /* shift encode up so it starts on bit 15 then reverse */
+ c <<= (16-b);
+ c = revtab[c>>8] | (revtab[c&0xff]<<8);
+ return c;
+}
+
+/*
+ * construct the huffman decoding arrays and a fast lookup table.
+ * the fast lookup is a table indexed by the next flatbits bits,
+ * which returns the symbol matched and the number of bits consumed,
+ * or the minimum number of bits needed and 0xff if more than flatbits
+ * bits are needed.
+ *
+ * flatbits can be longer than the smallest huffman code,
+ * because shorter codes are assigned smaller lexical prefixes.
+ * this means assuming zeros for the next few bits will give a
+ * conservative answer, in the sense that it will either give the
+ * correct answer, or return the minimum number of bits which
+ * are needed for an answer.
+ */
+static int
+hufftab(Huff *h, char *hb, int maxleaf, int flatbits)
+{
+ ulong bitcount[MaxHuffBits];
+ ulong c, fc, ec, mincode, code, nc[MaxHuffBits];
+ int i, b, minbits, maxbits;
+
+ for(i = 0; i < MaxHuffBits; i++)
+ bitcount[i] = 0;
+ maxbits = -1;
+ minbits = MaxHuffBits + 1;
+ for(i=0; i < maxleaf; i++){
+ b = hb[i];
+ if(b){
+ bitcount[b]++;
+ if(b < minbits)
+ minbits = b;
+ if(b > maxbits)
+ maxbits = b;
+ }
+ }
+
+ h->maxbits = maxbits;
+ if(maxbits <= 0){
+ h->maxbits = 0;
+ h->minbits = 0;
+ h->flatmask = 0;
+ return 1;
+ }
+ code = 0;
+ c = 0;
+ for(b = 0; b <= maxbits; b++){
+ h->last[b] = c;
+ c += bitcount[b];
+ mincode = code << 1;
+ nc[b] = mincode;
+ code = mincode + bitcount[b];
+ if(code > (1 << b))
+ return 0;
+ h->maxcode[b] = code - 1;
+ h->last[b] += code - 1;
+ }
+
+ if(flatbits > maxbits)
+ flatbits = maxbits;
+ h->flatmask = (1 << flatbits) - 1;
+ if(minbits > flatbits)
+ minbits = flatbits;
+ h->minbits = minbits;
+
+ b = 1 << flatbits;
+ for(i = 0; i < b; i++)
+ h->flat[i] = ~0;
+
+ /*
+ * initialize the flat table to include the minimum possible
+ * bit length for each code prefix
+ */
+ for(b = maxbits; b > flatbits; b--){
+ code = h->maxcode[b];
+ if(code == -1)
+ break;
+ mincode = code + 1 - bitcount[b];
+ mincode >>= b - flatbits;
+ code >>= b - flatbits;
+ for(; mincode <= code; mincode++)
+ h->flat[revcode(mincode, flatbits)] = (b << 8) | 0xff;
+ }
+
+ for(i = 0; i < maxleaf; i++){
+ b = hb[i];
+ if(b <= 0)
+ continue;
+ c = nc[b]++;
+ if(b <= flatbits){
+ code = (i << 8) | b;
+ ec = (c + 1) << (flatbits - b);
+ if(ec > (1<<flatbits))
+ return 0; /* this is actually an internal error */
+ for(fc = c << (flatbits - b); fc < ec; fc++)
+ h->flat[revcode(fc, flatbits)] = code;
+ }
+ if(b > minbits){
+ c = h->last[b] - c;
+ if(c >= maxleaf)
+ return 0;
+ h->decode[c] = i;
+ }
+ }
+ return 1;
+}
+
+static int
+hdecsym(Input *in, Huff *h, int nb)
+{
+ long c;
+
+ if((nb & 0xff) == 0xff)
+ nb = nb >> 8;
+ else
+ nb = nb & 0xff;
+ for(; nb <= h->maxbits; nb++){
+ if(in->nbits<nb && !sregfill(in, nb))
+ return -1;
+ c = revtab[in->sreg&0xff]<<8;
+ c |= revtab[(in->sreg>>8)&0xff];
+ c >>= (16-nb);
+ if(c <= h->maxcode[nb]){
+ in->sreg >>= nb;
+ in->nbits -= nb;
+ return h->decode[h->last[nb] - c];
+ }
+ }
+ in->error = FlateCorrupted;
+ return -1;
+}
+
+static int
+sregfill(Input *in, int n)
+{
+ int c;
+
+ while(n > in->nbits) {
+ c = (*in->get)(in->getr);
+ if(c < 0){
+ in->error = FlateInputFail;
+ return 0;
+ }
+ in->sreg |= c<<in->nbits;
+ in->nbits += 8;
+ }
+ return 1;
+}
+
+static int
+sregunget(Input *in)
+{
+ if(in->nbits >= 8) {
+ in->error = FlateInternal;
+ return 0;
+ }
+
+ /* throw other bits on the floor */
+ in->nbits = 0;
+ in->sreg = 0;
+ return 1;
+}
--- /dev/null
+++ b/os/boot.original/libflate/inflateblock.c
@@ -1,0 +1,53 @@
+#include "lib9.h"
+#include <flate.h>
+
+typedef struct Block Block;
+
+struct Block
+{
+ uchar *pos;
+ uchar *limit;
+};
+
+static int
+blgetc(void *vb)
+{
+ Block *b;
+
+ b = vb;
+ if(b->pos >= b->limit)
+ return -1;
+ return *b->pos++;
+}
+
+static int
+blwrite(void *vb, void *buf, int n)
+{
+ Block *b;
+
+ b = vb;
+
+ if(n > b->limit - b->pos)
+ n = b->limit - b->pos;
+ memmove(b->pos, buf, n);
+ b->pos += n;
+ return n;
+}
+
+int
+inflateblock(uchar *dst, int dsize, uchar *src, int ssize)
+{
+ Block bd, bs;
+ int ok;
+
+ bs.pos = src;
+ bs.limit = src + ssize;
+
+ bd.pos = dst;
+ bd.limit = dst + dsize;
+
+ ok = inflate(&bd, blwrite, &bs, blgetc);
+ if(ok != FlateOk)
+ return ok;
+ return bd.pos - dst;
+}
--- /dev/null
+++ b/os/boot.original/libflate/inflatezlib.c
@@ -1,0 +1,65 @@
+#include "lib9.h"
+#include <flate.h>
+#include "zlib.h"
+
+typedef struct ZWrite ZWrite;
+
+struct ZWrite
+{
+ ulong adler;
+ void *wr;
+ int (*w)(void*, void*, int);
+};
+
+static int
+zlwrite(void *vzw, void *buf, int n)
+{
+ ZWrite *zw;
+
+ zw = vzw;
+ zw->adler = adler32(zw->adler, buf, n);
+ n = (*zw->w)(zw->wr, buf, n);
+ if(n <= 0)
+ return n;
+ return n;
+}
+
+int
+inflatezlib(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
+{
+ ZWrite zw;
+ ulong v;
+ int c, i;
+
+ c = (*get)(getr);
+ if(c < 0)
+ return FlateInputFail;
+ i = (*get)(getr);
+ if(i < 0)
+ return FlateInputFail;
+
+ if(((c << 8) | i) % 31)
+ return FlateCorrupted;
+ if((c & ZlibMeth) != ZlibDeflate
+ || (c & ZlibCInfo) > ZlibWin32k)
+ return FlateCorrupted;
+
+ zw.wr = wr;
+ zw.w = w;
+ zw.adler = 1;
+ i = inflate(&zw, zlwrite, getr, get);
+ if(i != FlateOk)
+ return i;
+
+ v = 0;
+ for(i = 0; i < 4; i++){
+ c = (*get)(getr);
+ if(c < 0)
+ return FlateInputFail;
+ v = (v << 8) | c;
+ }
+ if(zw.adler != v)
+ return FlateCorrupted;
+
+ return FlateOk;
+}
--- /dev/null
+++ b/os/boot.original/libflate/inflatezlibblock.c
@@ -1,0 +1,67 @@
+#include "lib9.h"
+#include <flate.h>
+#include "zlib.h"
+
+typedef struct Block Block;
+
+struct Block
+{
+ uchar *pos;
+ uchar *limit;
+};
+
+static int
+blgetc(void *vb)
+{
+ Block *b;
+
+ b = vb;
+ if(b->pos >= b->limit)
+ return -1;
+ return *b->pos++;
+}
+
+static int
+blwrite(void *vb, void *buf, int n)
+{
+ Block *b;
+
+ b = vb;
+
+ if(n > b->limit - b->pos)
+ n = b->limit - b->pos;
+ memmove(b->pos, buf, n);
+ b->pos += n;
+ return n;
+}
+
+int
+inflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize)
+{
+ Block bd, bs;
+ int ok;
+
+ if(ssize < 6)
+ return FlateInputFail;
+
+ if(((src[0] << 8) | src[1]) % 31)
+ return FlateCorrupted;
+ if((src[0] & ZlibMeth) != ZlibDeflate
+ || (src[0] & ZlibCInfo) > ZlibWin32k)
+ return FlateCorrupted;
+
+ bs.pos = src + 2;
+ bs.limit = src + ssize - 6;
+
+ bd.pos = dst;
+ bd.limit = dst + dsize;
+
+ ok = inflate(&bd, blwrite, &bs, blgetc);
+ if(ok != FlateOk)
+ return ok;
+
+ if(adler32(1, dst, bs.pos - dst) != ((bs.pos[0] << 24) | (bs.pos[1] << 16) | (bs.pos[2] << 8) | bs.pos[3]))
+ return FlateCorrupted;
+
+ return bd.pos - dst;
+}
--- /dev/null
+++ b/os/boot.original/libflate/mkfile
@@ -1,0 +1,21 @@
+<../../../mkconfig
+
+LIB=libflate.a
+OFILES=\
+ deflate.$O\
+ deflatezlib.$O\
+ deflateblock.$O\
+ deflatezlibblock.$O\
+ inflate.$O\
+ inflatezlib.$O\
+ inflateblock.$O\
+ inflatezlibblock.$O\
+ flateerr.$O\
+ crc.$O\
+ adler.$O\
+
+HFILES=\
+ $ROOT/include/flate.h\
+ zlib.h\
+
+<$ROOT/mkfiles/mksyslib-$SHELLTYPE
--- /dev/null
+++ b/os/boot.original/libflate/zlib.h
@@ -1,0 +1,11 @@
+/*
+ * zlib header fields
+ */
+enum
+{
+ ZlibMeth = 0x0f, /* mask of compression methods */
+ ZlibDeflate = 0x08,
+
+ ZlibCInfo = 0xf0, /* mask of compression aux. info */
+ ZlibWin32k = 0x70, /* 32k history window */
+};
--- /dev/null
+++ b/os/boot.original/mpc/NOTICE
@@ -1,0 +1,3 @@
+Inferno® Copyright © 1996-1999 Lucent Technologies Inc. All rights reserved.
+PowerPC support Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk). All rights reserved.
+MPC8xx Inferno PowerPC port Copyright © 1998-2003 Vita Nuova Holdings Limited. All rights reserved.
--- /dev/null
+++ b/os/boot.original/mpc/alarm.c
@@ -1,0 +1,123 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#define MAXALARM 10
+
+Alarm alarmtab[MAXALARM];
+
+/*
+ * Insert new into list after where
+ */
+void
+insert(List **head, List *where, List *new)
+{
+ if(where == 0){
+ new->next = *head;
+ *head = new;
+ }else{
+ new->next = where->next;
+ where->next = new;
+ }
+
+}
+
+/*
+ * Delete old from list. where->next is known to be old.
+ */
+void
+delete(List **head, List *where, List *old)
+{
+ if(where == 0){
+ *head = old->next;
+ return;
+ }
+ where->next = old->next;
+}
+
+Alarm*
+newalarm(void)
+{
+ int i;
+ Alarm *a;
+
+ for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
+ if(a->busy==0 && a->f==0){
+ a->f = 0;
+ a->arg = 0;
+ a->busy = 1;
+ return a;
+ }
+ panic("newalarm");
+ return 0; /* not reached */
+}
+
+Alarm*
+alarm(int ms, void (*f)(Alarm*), void *arg)
+{
+ Alarm *a, *w, *pw;
+ ulong s;
+
+ if(ms < 0)
+ ms = 0;
+ s = splhi();
+ a = newalarm();
+ a->dt = MS2TK(ms);
+ a->f = f;
+ a->arg = arg;
+ pw = 0;
+ for(w=m->alarm; w; pw=w, w=w->next){
+ if(w->dt <= a->dt){
+ a->dt -= w->dt;
+ continue;
+ }
+ w->dt -= a->dt;
+ break;
+ }
+ insert(&m->alarm, pw, a);
+ splx(s);
+ return a;
+}
+
+void
+cancel(Alarm *a)
+{
+ a->f = 0;
+}
+
+void
+alarminit(void)
+{
+}
+
+#define NA 10 /* alarms per clock tick */
+void
+checkalarms(void)
+{
+ int i, n, s;
+ Alarm *a;
+ void (*f)(Alarm*);
+ Alarm *alist[NA];
+
+ s = splhi();
+ a = m->alarm;
+ if(a){
+ for(n=0; a && a->dt<=0 && n<NA; n++){
+ alist[n] = a;
+ delete(&m->alarm, 0, a);
+ a = m->alarm;
+ }
+ if(a)
+ a->dt--;
+
+ for(i = 0; i < n; i++){
+ f = alist[i]->f; /* avoid race with cancel */
+ if(f)
+ (*f)(alist[i]);
+ alist[i]->busy = 0;
+ }
+ }
+ splx(s);
+}
--- /dev/null
+++ b/os/boot.original/mpc/all.h
@@ -1,0 +1,6 @@
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "mem.h"
+#include "io.h"
--- /dev/null
+++ b/os/boot.original/mpc/archfads.c
@@ -1,0 +1,355 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "archfads.h"
+
+/*
+ * board-specific support for the 8xxFADS (including 860/21 development system)
+ */
+
+enum {
+ USESDRAM = 0, /* set to 1 if kernel is to use SDRAM as well as DRAM */
+
+ /* sccr */
+ RTSEL = IBIT(8), /* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
+ RTDIV = IBIT(7), /* =0, divide by 4; =1, divide by 512 */
+ CRQEN = IBIT(9), /* =1, switch to high frequency when CPM active */
+ PRQEN = IBIT(10), /* =1, switch to high frequency when interrupt pending */
+
+ /* plprcr */
+ CSRC = IBIT(21), /* =0, clock is DFNH; =1, clock is DFNL */
+};
+
+/*
+ * called early in main.c, after machinit:
+ * using board and architecture specific registers, initialise
+ * 8xx registers that need it and complete initialisation of the Mach structure.
+ */
+void
+archinit(void)
+{
+ IMM *io;
+ int mf, isfads, sysmhz, t;
+ ulong v;
+
+ v = getimmr() & 0xFFFF;
+ isfads = 0; /* assume it's the 860/821 board */
+ sysmhz = 40;
+ switch(v>>8){
+ case 0x00: t = 0x86000; break;
+ case 0x20: t = 0x82300; isfads = 1; break;
+ case 0x21: t = 0x823a0; isfads = 1; break;
+ default: t = 0; break;
+ }
+ m->cputype = t;
+ m->bcsr = KADDR(BCSRMEM);
+ m->bcsr[1] |= DisableRS232a | DisableIR | DisableEther | DisablePCMCIA | DisableRS232b;
+ m->bcsr[1] &= ~(DisableDRAM|DisableFlash);
+ if(isfads){
+ sysmhz = 50;
+ m->bcsr[1] &= ~EnableSDRAM;
+ m->bcsr[4] &= ~(EnableVideoClock|EnableVideoPort);
+ m->bcsr[4] |= DisableVideoLamp;
+ }
+ io = m->iomem;
+ if(1 || io->sccr & IBIT(7)){ /* RTDIV=1 */
+ /* oscillator frequency can't be determined independently: check a switch */
+ if((m->bcsr[2]>>19)&(1<<2))
+ m->clockgen = 5*MHz;
+ else
+ m->clockgen = 4*MHz;
+ } else
+ m->clockgen = 32768;
+ mf = (sysmhz*MHz)/m->clockgen;
+ m->cpuhz = m->clockgen*mf;
+ io->plprcrk = KEEP_ALIVE_KEY;
+ io->plprcr &= ~IBIT(21); /* general system clock is DFNH */
+ io->plprcr = (io->plprcr & ((1<<20)-1)) | ((mf-1)<<20);
+ io->mptpr = 0x0400; /* memory prescaler = 16 for refresh */
+ io->plprcrk = ~KEEP_ALIVE_KEY;
+ if(isfads){
+ m->bcsr[1] |= EnableSDRAM;
+ sdraminit(SDRAMMEM);
+ if(!USESDRAM)
+ m->bcsr[1] &= ~EnableSDRAM; /* tells kernel not to map it */
+ }
+}
+
+static void
+archidprint(void)
+{
+ int f, i;
+ ulong v;
+
+ /* 8xx and FADS specific */
+ print("IMMR: ");
+ v = getimmr() & 0xFFFF;
+ switch(v>>8){
+ case 0x00: print("MPC860/821"); break;
+ case 0x20: print("MPC823"); break;
+ case 0x21: print("MPC823A"); break;
+ default: print("Type #%lux", v>>8); break;
+ }
+ print(", mask #%lux\n", v&0xFF);
+ v = m->bcsr[3]>>16;
+ print("MPC8xxFADS rev %lud, DB: ", ((v>>4)&8)|((v>>1)&4)|(v&3));
+ f = (v>>8)&0x3F;
+ switch(f){
+ default: print("ID#%x", f); break;
+ case 0x00: print("MPC860/821"); break;
+ case 0x01: print("MPC813"); break;
+ case 0x02: print("MPC821"); break;
+ case 0x03: print("MPC823"); break;
+ case 0x20: print("MPC801"); break;
+ case 0x21: print("MPC850"); break;
+ case 0x22: print("MPC860"); break;
+ case 0x23: print("MPC860SAR"); break;
+ case 0x24: print("MPC860T"); break;
+ }
+ print("ADS, rev #%lux\n", (m->bcsr[2]>>16)&7);
+ for(i=0; i<=4; i++)
+ print("BCSR%d: %8.8lux\n", i, m->bcsr[i]);
+ v = m->bcsr[2];
+ f = (v>>28)&0xF;
+ switch(f){
+ default: print("Unknown"); break;
+ case 4: print("SM732A2000/SM73228 - 8M SIMM"); break;
+ case 5: print("SM732A1000A/SM73218 - 4M SIMM"); break;
+ case 6: print("MCM29080 - 8M SIMM"); break;
+ case 7: print("MCM29040 - 4M SIMM"); break;
+ case 8: print("MCM29020 - 2M SIMM"); break;
+ }
+ switch((m->bcsr[3]>>20)&7){
+ default: i = 0; break;
+ case 1: i = 150; break;
+ case 2: i = 120; break;
+ case 3: i = 90; break;
+ }
+ print(" flash, %dns\n", i);
+ f = (v>>23)&0xF;
+ switch(f&3){
+ case 0: i = 4; break;
+ case 1: i = 32; break;
+ case 2: i = 16; break;
+ case 3: i = 8; break;
+ }
+ print("%dM SIMM, ", i);
+ switch(f>>2){
+ default: i = 0; break;
+ case 2: i = 70; break;
+ case 3: i = 60; break;
+ }
+ print("%dns\n", i);
+ print("options: #%lux\n", (m->bcsr[2]>>19)&0xF);
+ print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
+}
+
+void
+cpuidprint(void)
+{
+ int t;
+
+ print("PVR: ");
+ t = getpvr()>>16;
+ switch(t){
+ case 0x01: print("MPC601"); break;
+ case 0x03: print("MPC603"); break;
+ case 0x04: print("MPC604"); break;
+ case 0x06: print("MPC603e"); break;
+ case 0x07: print("MPC603e-v7"); break;
+ case 0x50: print("MPC8xx"); break;
+ default: print("PowerPC version #%x", t); break;
+ }
+ print(", revision #%lux\n", getpvr()&0xffff);
+ archidprint();
+ print("%lud MHz system\n", m->cpuhz/MHz);
+ print("\n");
+}
+
+static char* defplan9ini[2] = {
+ /* 860/821 */
+ "ether0=type=SCC port=1 ea=00108bf12900\r\n"
+ "vgasize=640x480x8\r\n"
+ "kernelpercent=40\r\n"
+ "console=0 lcd\r\nbaud=9600\r\n",
+
+ /* 823 */
+ "ether0=type=SCC port=2 ea=00108bf12900\r\n"
+ "vgasize=640x480x8\r\n"
+ "kernelpercent=40\r\n"
+ "console=0 lcd\r\nbaud=9600\r\n",
+};
+
+char *
+archconfig(void)
+{
+ print("Using default configuration\n");
+ return defplan9ini[MPCMODEL(m->cputype) == 0x823];
+}
+
+/*
+ * provide value for #r/switch (devrtc.c)
+ */
+int
+archoptionsw(void)
+{
+ return (m->bcsr[2]>>19)&0xF; /* value of switch DS1 */
+}
+
+/*
+ * invoked by clock.c:/^clockintr
+ */
+static void
+twinkle(void)
+{
+ if(m->ticks%MS2TK(1000) == 0)
+ m->bcsr[4] ^= DisableLamp;
+}
+
+void (*archclocktick)(void) = twinkle;
+
+/*
+ * for flash.c:/^flashreset
+ * retrieve flash type, virtual base and length and return 0;
+ * return -1 on error (no flash)
+ */
+int
+archflashreset(char *type, void **addr, long *length)
+{
+ char *t;
+ int mbyte;
+
+ if((m->iomem->memc[0].base & 1) == 0)
+ return -1; /* shouldn't happen */
+ switch((m->bcsr[2]>>28)&0xF){
+ default: return -1; /* unknown or not there */
+ case 4: mbyte=8; t = "SM732x8"; break;
+ case 5: mbyte=4; t = "SM732x8"; break;
+ case 6: mbyte=8; t = "AMD29F0x0"; break;
+ case 7: mbyte=4; t = "AMD29F0x0"; break;
+ case 8: mbyte=2; t = "AMD29F0x0"; break;
+ }
+ strcpy(type, t);
+ *addr = KADDR(FLASHMEM);
+ *length = mbyte*1024*1024;
+ return 0;
+}
+
+/*
+ * enable the clocks for the given SCC ether and reveal them to the caller.
+ * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
+ */
+int
+archetherenable(int cpmid, int *rcs, int *tcs)
+{
+ IMM *io;
+
+ switch(cpmid){
+ default:
+ /* no other SCCs are wired on the FADS board */
+ return -1;
+
+ case SCC2ID: /* assume 8xxFADS board with 823DABS */
+ io = ioplock();
+ m->bcsr[1] |= DisableIR|DisableRS232b;
+ m->bcsr[1] &= ~DisableEther;
+ io->papar |= SIBIT(6)|SIBIT(5); /* enable CLK2 and CLK3 */
+ io->padir &= ~(SIBIT(6)|SIBIT(5));
+
+ /* ETHLOOP etc set in BCSR elsewhere */
+ *rcs = CLK2;
+ *tcs = CLK3;
+ iopunlock();
+ break;
+
+ case SCC1ID: /* assume 860/21 development board */
+ io = ioplock();
+ m->bcsr[1] |= DisableIR|DisableRS232b; /* TO DO: might not be shared with RS232b */
+ m->bcsr[1] &= ~DisableEther;
+ io->papar |= SIBIT(6)|SIBIT(7); /* enable CLK2 and CLK1 */
+ io->padir &= ~(SIBIT(6)|SIBIT(7));
+
+ /* settings peculiar to 860/821 development board */
+ io->pcpar &= ~(SIBIT(4)|SIBIT(5)|SIBIT(6)); /* ETHLOOP, TPFULDL~, TPSQEL~ */
+ io->pcdir |= SIBIT(4)|SIBIT(5)|SIBIT(6);
+ io->pcdat &= ~SIBIT(4);
+ io->pcdat |= SIBIT(5)|SIBIT(6);
+ *rcs = CLK2;
+ *tcs = CLK1;
+ iopunlock();
+ break;
+ }
+ return 0;
+}
+
+void
+archetherdisable(int id)
+{
+ USED(id);
+ m->bcsr[1] |= DisableEther|DisableIR|DisableRS232b;
+}
+
+/*
+ * do anything extra required to enable the UART on the given CPM port
+ */
+void
+archenableuart(int id, int irda)
+{
+ switch(id){
+ case SMC1ID:
+ m->bcsr[1] &= ~DisableRS232a;
+ break;
+ case SCC2ID:
+ m->bcsr[1] |= DisableEther|DisableIR|DisableRS232b;
+ if(irda)
+ m->bcsr[1] &= ~DisableIR;
+ else
+ m->bcsr[1] &= ~DisableRS232b;
+ break;
+ default:
+ /* nothing special */
+ break;
+ }
+}
+
+/*
+ * do anything extra required to disable the UART on the given CPM port
+ */
+void
+archdisableuart(int id)
+{
+ switch(id){
+ case SMC1ID:
+ m->bcsr[1] |= DisableRS232a;
+ break;
+ case SCC2ID:
+ m->bcsr[1] |= DisableIR|DisableRS232b;
+ break;
+ default:
+ /* nothing special */
+ break;
+ }
+}
+
+/*
+ * enable/disable the LCD panel's backlight via
+ * York touch panel interface (does no harm without it)
+ */
+void
+archbacklight(int on)
+{
+ IMM *io;
+
+ delay(2);
+ io = ioplock();
+ io->papar &= ~SIBIT(4);
+ io->padir |= SIBIT(4);
+ if(on)
+ io->padat |= SIBIT(4);
+ else
+ io->padat &= ~SIBIT(4);
+ iopunlock();
+}
--- /dev/null
+++ b/os/boot.original/mpc/archfads.h
@@ -1,0 +1,42 @@
+
+enum {
+ /* BCSR1 bits */
+ DisableFlash= IBIT(0),
+ DisableDRAM= IBIT(1),
+ DisableEther= IBIT(2),
+ DisableIR= IBIT(3),
+ DisableRS232a= IBIT(7),
+ DisablePCMCIA= IBIT(8),
+ PCCVCCMask= IBIT(9)|IBIT(15),
+ PCCVPPMask= IBIT(10)|IBIT(11),
+ DisableRS232b= IBIT(13),
+ EnableSDRAM= IBIT(14),
+
+ PCCVCC0V= IBIT(15)|IBIT(9),
+ PCCVCC5V= IBIT(9), /* active low */
+ PCCVCC3V= IBIT(15), /* active low */
+ PCCVPP0V= IBIT(10)|IBIT(11), /* active low */
+ PCCVPP5V= IBIT(10), /* active low */
+ PCCVPP12V= IBIT(11), /* active low */
+ PCCVPPHiZ= IBIT(10)|IBIT(11),
+
+ /* BCSR4 bits */
+ DisableTPDuplex= IBIT(1),
+ DisableLamp= IBIT(3),
+ DisableUSB= IBIT(4),
+ USBFullSpeed= IBIT(5),
+ DisableUSBVcc= IBIT(6),
+ DisableVideoLamp= IBIT(8),
+ EnableVideoClock= IBIT(9),
+ EnableVideoPort= IBIT(10),
+ DisableModem= IBIT(11),
+};
+
+enum {
+ /* memory controller CS assignment on FADS boards */
+ BOOTCS = 0,
+ BCSRCS = 1,
+ DRAM1 = 2,
+ DRAM2 = 3,
+ SDRAM = 4,
+};
--- /dev/null
+++ b/os/boot.original/mpc/archpaq.c
@@ -1,0 +1,240 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "archpaq.h"
+
+/*
+ * board-specific support for the 82x PowerPAQ
+ */
+
+enum {
+ SYSMHZ = 50, /* desired system clock in MHz */
+
+ /* sccr */
+ RTSEL = IBIT(8), /* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
+ RTDIV = IBIT(7), /* =0, divide by 4; =1, divide by 512 */
+ CRQEN = IBIT(9), /* =1, switch to high frequency when CPM active */
+ PRQEN = IBIT(10), /* =1, switch to high frequency when interrupt pending */
+
+ /* plprcr */
+ CSRC = IBIT(21), /* =0, clock is DFNH; =1, clock is DFNL */
+};
+
+/*
+ * called early in main.c, after machinit:
+ * using board and architecture specific registers, initialise
+ * 8xx registers that need it and complete initialisation of the Mach structure.
+ */
+void
+archinit(void)
+{
+ IMM *io;
+ int mf, t;
+
+ switch((getimmr()>>8)&0xFF){
+ case 0x00: t = 0x86000; break; /* also 821 */
+ case 0x20: t = 0x82300; break;
+ case 0x21: t = 0x823a0; break;
+ default: t = 0; break;
+ }
+ m->cputype = t;
+ m->bcsr = nil; /* there isn't one */
+ m->clockgen = 32*1024; /* crystal frequency */
+ io = m->iomem;
+ io->sccrk = KEEP_ALIVE_KEY;
+ io->sccr &= ~RTDIV; /* divide 32k by 4 */
+ io->sccr |= RTSEL;
+ io->sccrk = ~KEEP_ALIVE_KEY;
+ mf = (SYSMHZ*MHz)/m->clockgen;
+ m->cpuhz = m->clockgen*mf;
+ io->plprcrk = KEEP_ALIVE_KEY;
+ io->plprcr &= ~IBIT(21); /* general system clock is DFNH */
+ io->plprcr = (io->plprcr & ((1<<20)-1)) | ((mf-1)<<20);
+ io->mptpr = 0x0400; /* memory prescaler = 16 for refresh */
+ io->plprcrk = ~KEEP_ALIVE_KEY;
+}
+
+void
+cpuidprint(void)
+{
+ int t, v;
+
+ print("PVR: ");
+ t = getpvr()>>16;
+ switch(t){
+ case 0x01: print("MPC601"); break;
+ case 0x03: print("MPC603"); break;
+ case 0x04: print("MPC604"); break;
+ case 0x06: print("MPC603e"); break;
+ case 0x07: print("MPC603e-v7"); break;
+ case 0x50: print("MPC8xx"); break;
+ default: print("PowerPC version #%x", t); break;
+ }
+ print(", revision #%lux\n", getpvr()&0xffff);
+ print("IMMR: ");
+ v = getimmr() & 0xFFFF;
+ switch(v>>8){
+ case 0x00: print("MPC860/821"); break;
+ case 0x20: print("MPC823"); break;
+ case 0x21: print("MPC823A"); break;
+ default: print("Type #%lux", v>>8); break;
+ }
+ print(", mask #%lux\n", v&0xFF);
+ print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
+ print("%lud MHz system\n", m->cpuhz/MHz);
+ print("\n");
+}
+
+static char* defplan9ini[2] = {
+ /* 860/821 */
+ "ether0=type=SCC port=1 ea=00108bf12900\r\n"
+ "vgasize=640x480x8\r\n"
+ "kernelpercent=40\r\n"
+ "console=0 lcd\r\nbaud=19200\r\n",
+
+ /* 823 */
+ "ether0=type=SCC port=2 ea=00108bf12900\r\n"
+ "vgasize=640x480x8\r\n"
+ "kernelpercent=40\r\n"
+ "console=0 lcd\r\nbaud=19200\r\n",
+};
+
+char *
+archconfig(void)
+{
+ print("Using default configuration\n");
+ return defplan9ini[MPCMODEL(m->cputype) == 0x823];
+}
+
+/*
+ * provide value for #r/switch (devrtc.c)
+ */
+int
+archoptionsw(void)
+{
+ return 0;
+}
+
+/*
+ * invoked by clock.c:/^clockintr
+ */
+static void
+twinkle(void)
+{
+ /* no easy-to-use LED on PAQ (they use i2c) */
+}
+
+void (*archclocktick)(void) = twinkle;
+
+/*
+ * for flash.c:/^flashinit
+ * retrieve flash type, virtual base and length and return 0;
+ * return -1 on error (no flash)
+ */
+int
+archflashreset(char *type, void **addr, long *length)
+{
+ strcpy(type, "AMD29F0x0");
+ *addr = KADDR(FLASHMEM);
+ *length = 8*1024*1024; /* 8mbytes on some models */
+ return 0;
+}
+
+/*
+ * enable the clocks for the given SCC ether and reveal them to the caller.
+ * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
+ */
+int
+archetherenable(int cpmid, int *rcs, int *tcs)
+{
+ USED(cpmid, rcs, tcs);
+ return -1; /* there isn't an ether on the PAQs */
+}
+
+void
+archetherdisable(int id)
+{
+ USED(id);
+}
+
+/*
+ * do anything extra required to enable the UART on the given CPM port
+ */
+void
+archenableuart(int id, int irda)
+{
+ IMM *io;
+
+ USED(irda);
+ switch(id){
+ case SMC1ID:
+ io = ioplock();
+ io->pbodr &= ~0xc0;
+ io->pbdat |= 0xc0;
+ io->pcdat |= 0x400;
+ io->pcpar &= ~0x400;
+ io->pcdir |= 0x400;
+ io->pcdat &= ~0x400; /* enable SMC RS232 buffer */
+ iopunlock();
+ break;
+ case SCC2ID:
+ /* TO DO */
+ break;
+ default:
+ /* nothing special */
+ break;
+ }
+}
+
+/*
+ * do anything extra required to disable the UART on the given CPM port
+ */
+void
+archdisableuart(int id)
+{
+ switch(id){
+ case SMC1ID:
+ /* TO DO */
+ break;
+ case SCC2ID:
+ /* TO DO */
+ break;
+ default:
+ /* nothing special */
+ break;
+ }
+}
+
+/*
+ * enable/disable the LCD panel's backlight via i2c
+ */
+void
+archbacklight(int on)
+{
+ uchar msg;
+ IMM *io;
+
+ i2csetup();
+ msg = ~7;
+ i2csend(LEDRegI2C, &msg, 1);
+ io = ioplock();
+ io->pbpar &= ~EnableLCD;
+ io->pbodr &= ~EnableLCD;
+ io->pbdir |= EnableLCD;
+ if(on)
+ io->pbdat |= EnableLCD;
+ else
+ io->pbdat &= ~EnableLCD;
+ iopunlock();
+ if(on){
+ msg = ~(DisablePanelVCC5|DisableTFT);
+ i2csend(PanelI2C, &msg, 1);
+ }else{
+ msg = ~0;
+ i2csend(PanelI2C, &msg, 1);
+ }
+}
--- /dev/null
+++ b/os/boot.original/mpc/archpaq.h
@@ -1,0 +1,29 @@
+enum {
+ /* memory controller CS assignment on PowerPAQ */
+ BOOTCS = 0,
+ DRAM1 = 1, /* UPMB */
+ DRAM2 = 2, /* UPMB */
+ /* CS3 also connected to DRAM */
+ /* CS4 128mbyte 8-bit gpcm, trlx, 15 wait; it's DAC */
+ /* CS5 is external*/
+};
+
+enum {
+ /* I2C addresses */
+ PanelI2C = 0x21<<1,
+ /* the control bits are active low enables, or high disables */
+ DisableVGA = ~0xFD, /* disable VGA signals */
+ DisableTFT = ~0xFB, /* disable TFT panel signals */
+ DisableSPIBus = ~0xF7, /* disable SPI/I2C to panel */
+ DisablePanelVCC5 = ~0xEF, /* disable +5V to panel(s) */
+ DisablePanelVCC3 = ~0xDF, /* disable +3.3V to panel(s) */
+ DisableMonoPanel = ~0xBF, /* disable mono panel signals */
+ DisableSPISelect = ~0x7F, /* disable SPI chip select to LVDS panel */
+ ContrastI2C = 0x2E<<1,
+ LEDRegI2C = 0x20<<1,
+ DisableGreenLED = ~0xFE,
+ DisableYellowLED = ~0xFD,
+ DisableRedLED = ~0xFB,
+
+ EnableLCD = IBIT(23), /* LCD enable bit in i/o port B */
+};
--- /dev/null
+++ b/os/boot.original/mpc/boot.h
@@ -1,0 +1,8 @@
+#include <u.h>
+#include "lib.h"
+
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
--- /dev/null
+++ b/os/boot.original/mpc/bootp.c
@@ -1,0 +1,507 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ip.h"
+
+enum {
+ CHECKSUM = 1, /* set zero if trouble booting from Linux */
+};
+
+uchar broadcast[Eaddrlen] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static ushort tftpport = 5000;
+static int Id = 1;
+static Netaddr myaddr;
+static Netaddr server;
+
+typedef struct {
+ uchar header[4];
+ uchar data[Segsize];
+} Tftp;
+static Tftp tftpb;
+
+static void
+hnputs(uchar *ptr, ushort val)
+{
+ ptr[0] = val>>8;
+ ptr[1] = val;
+}
+
+static void
+hnputl(uchar *ptr, ulong val)
+{
+ ptr[0] = val>>24;
+ ptr[1] = val>>16;
+ ptr[2] = val>>8;
+ ptr[3] = val;
+}
+
+static ulong
+nhgetl(uchar *ptr)
+{
+ return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+}
+
+static ushort
+nhgets(uchar *ptr)
+{
+ return ((ptr[0]<<8) | ptr[1]);
+}
+
+static short endian = 1;
+static char* aendian = (char*)&endian;
+#define LITTLE *aendian
+
+static ushort
+ptcl_csum(void *a, int len)
+{
+ uchar *addr;
+ ulong t1, t2;
+ ulong losum, hisum, mdsum, x;
+
+ addr = a;
+ losum = 0;
+ hisum = 0;
+ mdsum = 0;
+
+ x = 0;
+ if((ulong)addr & 1) {
+ if(len) {
+ hisum += addr[0];
+ len--;
+ addr++;
+ }
+ x = 1;
+ }
+ while(len >= 16) {
+ t1 = *(ushort*)(addr+0);
+ t2 = *(ushort*)(addr+2); mdsum += t1;
+ t1 = *(ushort*)(addr+4); mdsum += t2;
+ t2 = *(ushort*)(addr+6); mdsum += t1;
+ t1 = *(ushort*)(addr+8); mdsum += t2;
+ t2 = *(ushort*)(addr+10); mdsum += t1;
+ t1 = *(ushort*)(addr+12); mdsum += t2;
+ t2 = *(ushort*)(addr+14); mdsum += t1;
+ mdsum += t2;
+ len -= 16;
+ addr += 16;
+ }
+ while(len >= 2) {
+ mdsum += *(ushort*)addr;
+ len -= 2;
+ addr += 2;
+ }
+ if(x) {
+ if(len)
+ losum += addr[0];
+ if(LITTLE)
+ losum += mdsum;
+ else
+ hisum += mdsum;
+ } else {
+ if(len)
+ hisum += addr[0];
+ if(LITTLE)
+ hisum += mdsum;
+ else
+ losum += mdsum;
+ }
+
+ losum += hisum >> 8;
+ losum += (hisum & 0xff) << 8;
+ while(hisum = losum>>16)
+ losum = hisum + (losum & 0xffff);
+
+ return ~losum;
+}
+
+static ushort
+ip_csum(uchar *addr)
+{
+ int len;
+ ulong sum = 0;
+
+ len = (addr[0]&0xf)<<2;
+
+ while(len > 0) {
+ sum += addr[0]<<8 | addr[1] ;
+ len -= 2;
+ addr += 2;
+ }
+
+ sum = (sum & 0xffff) + (sum >> 16);
+ sum = (sum & 0xffff) + (sum >> 16);
+ return (sum^0xffff);
+}
+
+static void
+udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+ Udphdr *uh;
+ Etherhdr *ip;
+ static Etherpkt pkt;
+ int len, ptcllen;
+
+
+ uh = (Udphdr*)&pkt;
+
+ memset(uh, 0, sizeof(Etherpkt));
+ memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
+
+ /*
+ * UDP portion
+ */
+ ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
+ uh->ttl = 0;
+ uh->udpproto = IP_UDPPROTO;
+ uh->frag[0] = 0;
+ uh->frag[1] = 0;
+ hnputs(uh->udpplen, ptcllen);
+ hnputl(uh->udpsrc, myaddr.ip);
+ hnputs(uh->udpsport, myaddr.port);
+ hnputl(uh->udpdst, a->ip);
+ hnputs(uh->udpdport, a->port);
+ hnputs(uh->udplen, ptcllen);
+ uh->udpcksum[0] = 0;
+ uh->udpcksum[1] = 0;
+ /*dlen = (dlen+1)&~1; */
+ hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
+
+ /*
+ * IP portion
+ */
+ ip = (Etherhdr*)&pkt;
+ len = sizeof(Udphdr)+dlen;
+ ip->vihl = IP_VER|IP_HLEN;
+ ip->tos = 0;
+ ip->ttl = 255;
+ hnputs(ip->length, len-ETHER_HDR);
+ hnputs(ip->id, Id++);
+ ip->frag[0] = 0;
+ ip->frag[1] = 0;
+ ip->cksum[0] = 0;
+ ip->cksum[1] = 0;
+ hnputs(ip->cksum, ip_csum(&ip->vihl));
+
+ /*
+ * Ethernet MAC portion
+ */
+ hnputs(ip->type, ET_IP);
+ memmove(ip->d, a->ea, sizeof(ip->d));
+
+ ethertxpkt(ctlrno, &pkt, len, Timeout);
+}
+
+static void
+nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
+{
+ int n;
+ char buf[128];
+
+ buf[0] = 0;
+ buf[1] = Tftp_ERROR;
+ buf[2] = 0;
+ buf[3] = code;
+ strcpy(buf+4, msg);
+ n = strlen(msg) + 4 + 1;
+ udpsend(ctlrno, a, buf, n);
+ if(report)
+ print("\ntftp: error(%d): %s\n", code, msg);
+}
+
+static int
+udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+ int n, len;
+ ushort csm;
+ Udphdr *h;
+ ulong addr, timo;
+ static Etherpkt pkt;
+ static int rxactive;
+
+ if(rxactive == 0)
+ timo = 1000;
+ else
+ timo = Timeout;
+ timo += TK2MS(m->ticks);
+ while(timo > TK2MS(m->ticks)){
+ n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
+ if(n <= 0)
+ continue;
+
+ h = (Udphdr*)&pkt;
+ if(nhgets(h->type) != ET_IP)
+ continue;
+
+ if(ip_csum(&h->vihl)) {
+ print("ip chksum error\n");
+ continue;
+ }
+ if(h->vihl != (IP_VER|IP_HLEN)) {
+ print("ip bad vers/hlen\n");
+ continue;
+ }
+
+ if(h->udpproto != IP_UDPPROTO)
+ continue;
+
+ h->ttl = 0;
+ len = nhgets(h->udplen);
+ hnputs(h->udpplen, len);
+
+ if(CHECKSUM && nhgets(h->udpcksum)) {
+ csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
+ if(csm != 0) {
+ print("udp chksum error csum #%4lux len %d\n", csm, n);
+ break;
+ }
+ }
+
+ if(a->port != 0 && nhgets(h->udpsport) != a->port)
+ continue;
+
+ addr = nhgetl(h->udpsrc);
+ if(a->ip != Bcastip && addr != a->ip)
+ continue;
+
+ len -= UDP_HDRSIZE-UDP_PHDRSIZE;
+ if(len > dlen) {
+ print("udp: packet too big\n");
+ continue;
+ }
+
+ memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
+ a->ip = addr;
+ a->port = nhgets(h->udpsport);
+ memmove(a->ea, pkt.s, sizeof(a->ea));
+
+ rxactive = 1;
+ return len;
+ }
+
+ return 0;
+}
+
+static int tftpblockno;
+
+static int
+tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
+{
+ int i, len, rlen, oport;
+ char buf[Segsize+2];
+
+ buf[0] = 0;
+ buf[1] = Tftp_READ;
+ len = sprint(buf+2, "%s", name) + 2;
+ len += sprint(buf+len+1, "octet") + 2;
+
+ oport = a->port;
+ for(i = 0; i < 5; i++){
+ a->port = oport;
+ udpsend(ctlrno, a, buf, len);
+ a->port = 0;
+ if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
+ continue;
+
+ switch((tftp->header[0]<<8)|tftp->header[1]){
+
+ case Tftp_ERROR:
+ print("tftpopen: error (%d): %s\n",
+ (tftp->header[2]<<8)|tftp->header[3], tftp->data);
+ return -1;
+
+ case Tftp_DATA:
+ tftpblockno = 1;
+ len = (tftp->header[2]<<8)|tftp->header[3];
+ if(len != tftpblockno){
+ print("tftpopen: block error: %d\n", len);
+ nak(ctlrno, a, 1, "block error", 0);
+ return -1;
+ }
+ return rlen-sizeof(tftp->header);
+ }
+ }
+
+ print("tftpopen: failed to connect to server\n");
+ return -1;
+}
+
+static int
+tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
+{
+ int blockno, len, retry;
+ uchar buf[4];
+
+ buf[0] = 0;
+ buf[1] = Tftp_ACK;
+ buf[2] = tftpblockno>>8;
+ buf[3] = tftpblockno;
+ tftpblockno++;
+
+ dlen += sizeof(tftp->header);
+
+ retry = 0;
+buggery:
+ udpsend(ctlrno, a, buf, sizeof(buf));
+
+ if((len = udprecv(ctlrno, a, tftp, dlen)) < dlen){
+ print("tftpread: %d != %d\n", len, dlen);
+ nak(ctlrno, a, 2, "short read", 0);
+ if(retry++ < 5)
+ goto buggery;
+ return -1;
+ }
+
+ blockno = (tftp->header[2]<<8)|tftp->header[3];
+ if(blockno != tftpblockno){
+ print("?");
+
+ if(blockno == tftpblockno-1 && retry++ < 8)
+ goto buggery;
+ print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
+ nak(ctlrno, a, 1, "block error", 0);
+
+ return -1;
+ }
+
+ return len-sizeof(tftp->header);
+}
+
+int
+bootp(int ctlrno, char *file)
+{
+ Bootp req, rep;
+ int i, dlen, segsize, text, data, bss, total;
+ uchar *ea, *addr, *p;
+ ulong entry;
+ Exec *exec;
+ char name[128], *filename, *sysname;
+
+ if((ea = etheraddr(ctlrno)) == 0){
+ print("invalid ctlrno %d\n", ctlrno);
+ return -1;
+ }
+
+ filename = 0;
+ sysname = 0;
+ if(file && *file){
+ strcpy(name, file);
+ if(filename = strchr(name, ':')){
+ if(filename != name && *(filename-1) != '\\'){
+ sysname = name;
+ *filename++ = 0;
+ }
+ }
+ else
+ filename = name;
+ }
+
+
+ memset(&req, 0, sizeof(req));
+ req.op = Bootrequest;
+ req.htype = 1; /* ethernet */
+ req.hlen = Eaddrlen; /* ethernet */
+ memmove(req.chaddr, ea, Eaddrlen);
+
+ myaddr.ip = 0;
+ myaddr.port = BPportsrc;
+ memmove(myaddr.ea, ea, Eaddrlen);
+
+ for(i = 0; i < 10; i++) {
+ server.ip = Bcastip;
+ server.port = BPportdst;
+ memmove(server.ea, broadcast, sizeof(server.ea));
+ udpsend(ctlrno, &server, &req, sizeof(req));
+ if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
+ continue;
+ if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
+ continue;
+ if(rep.htype != 1 || rep.hlen != Eaddrlen)
+ continue;
+ if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
+ break;
+ }
+ if(i >= 10) {
+ print("bootp timed out\n");
+ return -1;
+ }
+
+ if(filename == 0 || *filename == 0)
+ filename = rep.file;
+
+ if(rep.sname[0] != '\0')
+ print("%s ", rep.sname);
+ print("(%d.%d.%d.%d!%d): %s\n",
+ rep.siaddr[0],
+ rep.siaddr[1],
+ rep.siaddr[2],
+ rep.siaddr[3],
+ server.port,
+ filename);uartwait();
+
+ myaddr.ip = nhgetl(rep.yiaddr);
+ myaddr.port = tftpport++;
+ server.ip = nhgetl(rep.siaddr);
+ server.port = TFTPport;
+
+ if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
+ return -1;
+ exec = (Exec*)(tftpb.data);
+ if(dlen < sizeof(Exec) || GLLONG(exec->magic) != Q_MAGIC){
+ nak(ctlrno, &server, 0, "bad magic number", 1);
+ return -1;
+ }
+ text = GLLONG(exec->text);
+ data = GLLONG(exec->data);
+ bss = GLLONG(exec->bss);
+ total = text+data+bss;
+ entry = GLLONG(exec->entry);
+print("load@%8.8lux: ", PADDR(entry));uartwait();
+ print("%d", text);
+
+ addr = (uchar*)PADDR(entry);
+ p = tftpb.data+sizeof(Exec);
+ dlen -= sizeof(Exec);
+ segsize = text;
+ for(;;){
+ if(dlen == 0){
+ if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
+ return -1;
+ p = tftpb.data;
+ }
+ if(segsize <= dlen)
+ i = segsize;
+ else
+ i = dlen;
+ memmove(addr, p, i);
+
+ addr += i;
+ p += i;
+ segsize -= i;
+ dlen -= i;
+
+ if(segsize <= 0){
+ if(data == 0)
+ break;
+ print("+%d", data);
+ segsize = data;
+ data = 0;
+ addr = (uchar*)PGROUND((ulong)addr);
+ }
+ }
+ nak(ctlrno, &server, 3, "ok", 0); /* tftpclose */
+ print("+%d=%d\n", bss, total);
+ print("entry: 0x%lux\n", entry);
+ uartwait();
+ scc2stop();
+ splhi();
+ (*(void(*)(void))(PADDR(entry)))();
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/clock.c
@@ -1,0 +1,71 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+enum {
+ Timebase = 4, /* system clock cycles per time base cycle */
+};
+
+void (*archclocktick)(void); /* set by arch*.c when desired */
+
+static ulong clkreload;
+
+void
+delay(int l)
+{
+ ulong i, j;
+
+ j = m->delayloop;
+ while(l-- > 0)
+ for(i=0; i < j; i++)
+ ;
+}
+
+void
+microdelay(int l)
+{
+ ulong i;
+
+ l *= m->delayloop;
+ l /= 1000;
+ if(l <= 0)
+ l = 1;
+ for(i = 0; i < l; i++)
+ ;
+}
+
+void
+clockintr(Ureg*, void*)
+{
+ putdec(clkreload);
+ m->ticks++;
+ checkalarms();
+ if(archclocktick != nil)
+ archclocktick();
+}
+
+void
+clockinit(void)
+{
+ long x;
+
+ m->delayloop = m->cpuhz/1000; /* initial estimate */
+ do {
+ x = gettbl();
+ delay(10);
+ x = gettbl() - x;
+ } while(x < 0);
+
+ /*
+ * fix count
+ */
+ m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase);
+ if(m->delayloop == 0)
+ m->delayloop = 1;
+ clkreload = (m->clockgen/Timebase)/HZ-1;
+ putdec(clkreload);
+}
--- /dev/null
+++ b/os/boot.original/mpc/conf.c
@@ -1,0 +1,173 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "dosfs.h"
+
+static char *confname[MAXCONF];
+static char *confval[MAXCONF];
+static int nconf;
+
+extern char **ini;
+
+char*
+getconf(char *name)
+{
+ int i;
+
+ for(i = 0; i < nconf; i++)
+ if(strcmp(confname[i], name) == 0)
+ return confval[i];
+ return 0;
+}
+
+/*
+ * read configuration file
+ */
+int
+plan9ini(Dos *dos, char *val)
+{
+ Dosfile rc;
+ int i, n;
+ char *cp, *p, *q, *line[MAXCONF];
+
+ cp = BOOTARGS;
+ if(dos) {
+ if(dosstat(dos, *ini, &rc) <= 0)
+ return -1;
+
+ *cp = 0;
+ n = dosread(&rc, cp, BOOTARGSLEN-1);
+ if(n <= 0)
+ return -1;
+ cp[n] = 0;
+ } else if(val != nil){
+ if(memchr(val, 0, BOOTARGSLEN-1) == nil)
+ return -1;
+ print("Using flash configuration\n");
+ strcpy(cp, val);
+ n = strlen(cp);
+ }else{
+ strcpy(cp, archconfig());
+ n = strlen(cp);
+ }
+
+ /*
+ * Make a working copy.
+ * We could change this to pass the parsed strings
+ * to the booted programme instead of the raw
+ * string, then it only gets done once.
+ */
+ memmove(cp+BOOTARGSLEN, cp, n+1);
+ cp += BOOTARGSLEN;
+
+ /*
+ * Strip out '\r', change '\t' -> ' '.
+ */
+ p = cp;
+ for(q = cp; *q; q++){
+ if(*q == '\r')
+ continue;
+ if(*q == '\t')
+ *q = ' ';
+ *p++ = *q;
+ }
+ *p = 0;
+ n = getcfields(cp, line, MAXCONF, "\n");
+ for(i = 0; i < n; i++){
+ cp = strchr(line[i], '=');
+ if(cp == 0)
+ continue;
+ *cp++ = 0;
+ if(cp - line[i] >= NAMELEN+1)
+ *(line[i]+NAMELEN-1) = 0;
+ confname[nconf] = line[i];
+ confval[nconf] = cp;
+ nconf++;
+ }
+ return 0;
+}
+
+int
+parseether(uchar *to, char *from)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ while(*p == ' ')
+ ++p;
+ for(i = 0; i < 6; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ char cc[NAMELEN], *p, *q, *r;
+ int n;
+
+ sprint(cc, "%s%d", class, ctlrno);
+ for(n = 0; n < nconf; n++){
+ if(strncmp(confname[n], cc, NAMELEN))
+ continue;
+ isa->nopt = 0;
+ p = confval[n];
+ while(*p){
+ while(*p == ' ' || *p == '\t')
+ p++;
+ if(*p == '\0')
+ break;
+ if(strncmp(p, "type=", 5) == 0){
+ p += 5;
+ for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
+ if(*p == '\0' || *p == ' ' || *p == '\t')
+ break;
+ *q = *p++;
+ }
+ *q = '\0';
+ }
+ else if(strncmp(p, "port=", 5) == 0)
+ isa->port = strtoul(p+5, &p, 0);
+ else if(strncmp(p, "irq=", 4) == 0)
+ isa->irq = strtoul(p+4, &p, 0);
+ else if(strncmp(p, "mem=", 4) == 0)
+ isa->mem = strtoul(p+4, &p, 0);
+ else if(strncmp(p, "size=", 5) == 0)
+ isa->size = strtoul(p+5, &p, 0);
+ else if(strncmp(p, "ea=", 3) == 0){
+ if(parseether(isa->ea, p+3) == -1)
+ memset(isa->ea, 0, 6);
+ }
+ else if(isa->nopt < NISAOPT){
+ r = isa->opt[isa->nopt];
+ while(*p && *p != ' ' && *p != '\t'){
+ *r++ = *p++;
+ if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
+ break;
+ }
+ *r = '\0';
+ isa->nopt++;
+ }
+ while(*p && *p != ' ' && *p != '\t')
+ p++;
+ }
+ return 1;
+ }
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/console.c
@@ -1,0 +1,173 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+static Queue* consiq;
+static Queue* consoq;
+
+void
+bothputs(char *s, int n)
+{
+ uartputs(s, n);
+ screenputs(s, n);
+}
+
+static void (*consputs)(char*, int) = bothputs; /* or screenputs */
+
+void
+consinit(void)
+{
+ char *p;
+ int baud, port;
+ static int cgadone;
+
+ p = getconf("console");
+ if(0)
+ if(p == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
+ consiq = qopen(4*1024, 0, 0, 0);
+ consoq = qopen(8*1024, 0, 0, 0);
+ consputs = screenputs;
+ return;
+ }
+ if(p!=0 && strstr(p, "lcd") == 0)
+ consputs = bothputs;
+ else
+ consputs = uartputs;
+//consputs = screenputs;
+ port = 0;
+ if(p)
+ port = strtoul(p, 0, 0);
+ baud = 0;
+ if(p = getconf("baud"))
+ baud = strtoul(p, 0, 0);
+ if(baud == 0)
+ baud = 9600;
+ uartspecial(port, baud, &consiq, &consoq, kbdchar);
+}
+
+void
+kbdchar(Queue *q, int c)
+{
+ c &= 0x7F;
+ if(c == 0x10)
+ panic("^p");
+ qbputc(q, c);
+}
+
+static int
+getline(char *buf, int size, int dotimeout)
+{
+ int c, i=0;
+ ulong start;
+ char echo;
+
+ for (;;) {
+ start = m->ticks;
+ do{
+ if(dotimeout && ((m->ticks - start) > 5*HZ))
+ return -2;
+ c = qbgetc(consiq);
+ }while(c == -1);
+ if(c == '\r')
+ c = '\n'; /* turn carriage return into newline */
+ if(c == '\177')
+ c = '\010'; /* turn delete into backspace */
+ if(c == '\025')
+ echo = '\n'; /* echo ^U as a newline */
+ else
+ echo = c;
+ (*consputs)(&echo, 1);
+
+ if(c == '\010'){
+ if(i > 0)
+ i--; /* bs deletes last character */
+ continue;
+ }
+ /* a newline ends a line */
+ if (c == '\n')
+ break;
+ /* ^U wipes out the line */
+ if (c =='\025')
+ return -1;
+ if(i == size)
+ return size;
+ buf[i++] = c;
+ }
+ buf[i] = 0;
+ return i;
+}
+
+int
+getstr(char *prompt, char *buf, int size, char *def)
+{
+ int len, isdefault;
+
+ buf[0] = 0;
+ isdefault = (def && *def);
+ for (;;) {
+ if(isdefault)
+ print("%s[default==%s]: ", prompt, def);
+ else
+ print("%s: ", prompt);
+ len = getline(buf, size, isdefault);
+ switch(len){
+ case -1:
+ /* ^U typed */
+ continue;
+ case -2:
+ /* timeout, use default */
+ (*consputs)("\n", 1);
+ len = 0;
+ break;
+ default:
+ break;
+ }
+ if(len >= size){
+ print("line too long\n");
+ continue;
+ }
+ break;
+ }
+ if(len == 0 && isdefault)
+ strcpy(buf, def);
+ return 0;
+}
+
+int
+sprint(char *s, char *fmt, ...)
+{
+ return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
+}
+
+int
+print(char *fmt, ...)
+{
+ char buf[PRINTSIZE];
+ int n;
+
+ if(consputs == 0)
+ return 0;
+ n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+ (*consputs)(buf, n);
+ return n;
+}
+
+void
+panic(char *fmt, ...)
+{
+ char buf[PRINTSIZE];
+ int n;
+
+ if(consputs){
+ (*consputs)("panic: ", 7);
+ n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+ (*consputs)(buf, n);
+ (*consputs)("\n", 1);
+ }
+ spllo();
+ for(;;)
+ idle();
+}
--- /dev/null
+++ b/os/boot.original/mpc/cpm.c
@@ -1,0 +1,162 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum {
+ BDSIZE= 1024, /* TO DO: check this */
+};
+
+static Map bdmapv[BDSIZE/sizeof(BD)];
+static RMap bdmap = {"buffer descriptors"};
+
+void
+cpminit(void)
+{
+ IMM *io;
+
+ io = m->iomem;
+ io->sdcr = 1;
+ io->lccr &= ~1; /* disable LCD */
+ io->pcint = 0; /* disable all port C interrupts */
+ io->pcso = 0;
+ io->pcdir =0;
+ io->pcpar = 0;
+ io->pcdat = 0;
+ io->papar = 0;
+ io->padir = 0;
+ io->paodr = 0;
+ io->padat = 0;
+ io->pbpar = 0;
+ io->pbdir = 0;
+ io->pbodr = 0;
+ io->pbdat = 0;
+ eieio();
+
+ for(io->cpcr = 0x8001; io->cpcr & 1;) /* reset all CPM channels */
+ eieio();
+
+ mapinit(&bdmap, bdmapv, sizeof(bdmapv));
+ mapfree(&bdmap, DPBASE, BDSIZE);
+}
+
+void
+cpmop(int op, int cno, int param)
+{
+ IMM *io;
+ int s;
+
+ s = splhi();
+ io = m->iomem;
+ eieio();
+ while(io->cpcr & 1)
+ eieio();
+ io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1;
+ eieio();
+ while(io->cpcr & 1)
+ eieio();
+ splx(s);
+}
+
+/*
+ * connect SCCx clocks in NSMI mode (x=1 for USB)
+ */
+void
+sccnmsi(int x, int rcs, int tcs)
+{
+ IMM *io;
+ ulong v;
+ int sh;
+
+ sh = (x-1)*8; /* each SCCx field in sicr is 8 bits */
+ v = (((rcs&7)<<3) | (tcs&7)) << sh;
+ io = ioplock();
+ io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
+ iopunlock();
+}
+
+void
+scc2stop(void)
+{
+ SCC *scc;
+
+ scc = IOREGS(0xA20, SCC);
+ if(scc->gsmrl & (3<<4)){
+ cpmop(GracefulStopTx, SCC2ID, 0);
+ cpmop(CloseRxBD, SCC2ID, 0);
+ delay(1);
+ scc->gsmrl &= ~(3<<4); /* disable current use */
+ archetherdisable(SCC2ID);
+ }
+}
+
+BD *
+bdalloc(int n)
+{
+ ulong a;
+
+ a = mapalloc(&bdmap, 0, n*sizeof(BD), 0);
+ if(a == 0)
+ panic("bdalloc");
+ return KADDR(a);
+}
+
+void
+bdfree(BD *b, int n)
+{
+ if(b){
+ eieio();
+ mapfree(&bdmap, PADDR(b), n*sizeof(BD));
+ }
+}
+
+/*
+ * initialise receive and transmit buffer rings.
+ */
+int
+ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
+{
+ int i, x;
+
+ /* the ring entries must be aligned on sizeof(BD) boundaries */
+ r->nrdre = nrdre;
+ if(r->rdr == nil)
+ r->rdr = bdalloc(nrdre);
+ /* the buffer size must align with cache lines since the cache doesn't snoop */
+ bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1);
+ if(r->rrb == nil)
+ r->rrb = malloc(nrdre*bufsize);
+ if(r->rdr == nil || r->rrb == nil)
+ return -1;
+ dcflush(r->rrb, nrdre*bufsize);
+ x = PADDR(r->rrb);
+ for(i = 0; i < nrdre; i++){
+ r->rdr[i].length = 0;
+ r->rdr[i].addr = x;
+ r->rdr[i].status = BDEmpty|BDInt;
+ x += bufsize;
+ }
+ r->rdr[i-1].status |= BDWrap;
+ r->rdrx = 0;
+
+ r->ntdre = ntdre;
+ if(r->tdr == nil)
+ r->tdr = bdalloc(ntdre);
+ if(r->txb == nil)
+ r->txb = malloc(ntdre*sizeof(Block*));
+ if(r->tdr == nil || r->txb == nil)
+ return -1;
+ for(i = 0; i < ntdre; i++){
+ r->txb[i] = nil;
+ r->tdr[i].addr = 0;
+ r->tdr[i].length = 0;
+ r->tdr[i].status = 0;
+ }
+ r->tdr[i-1].status |= BDWrap;
+ r->tdrh = 0;
+ r->tdri = 0;
+ r->ntq = 0;
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/crc32.c
@@ -1,0 +1,42 @@
+#include "boot.h"
+
+/*
+ * from Rob Warnock
+ */
+static ulong crc32tab[256]; /* initialised on first call to crc32 */
+
+enum {
+ CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+ int i, j;
+ ulong c;
+
+ for(i = 0; i < 256; i++) {
+ for(c = i << 24, j = 8; j > 0; j--)
+ if(c & (1<<31))
+ c = (c<<1) ^ CRC32POLY;
+ else
+ c <<= 1;
+ crc32tab[i] = c;
+ }
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+ uchar *p;
+
+ if(crc32tab[1] == 0)
+ initcrc32();
+ crc = ~crc;
+ for(p = buf; --n >= 0;)
+ crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+ return ~crc;
+}
--- /dev/null
+++ b/os/boot.original/mpc/dat.h
@@ -1,0 +1,217 @@
+typedef struct Alarm Alarm;
+typedef struct Block Block;
+typedef struct IMM IMM;
+typedef struct Queue Queue;
+
+typedef struct List {
+ void *next;
+} List;
+
+typedef struct {
+ int fake;
+ int pri;
+} Lock;
+#define lock(x)
+#define unlock(x)
+
+struct Alarm {
+ List;
+ int busy;
+ long dt;
+ void (*f)(Alarm*);
+ void *arg;
+};
+
+enum {
+ Eaddrlen = 6,
+ ETHERMINTU = 60, /* minimum transmit size */
+ ETHERMAXTU = 1514, /* maximum transmit size */
+ ETHERHDRSIZE = 14, /* size of an ethernet header */
+
+ MaxEther = 4,
+};
+
+typedef struct {
+ uchar d[Eaddrlen];
+ uchar s[Eaddrlen];
+ uchar type[2];
+ uchar data[1500];
+ uchar crc[4];
+} Etherpkt;
+
+extern uchar broadcast[Eaddrlen];
+
+enum {
+ Npart = 20+2, /* 8 sub partitions, disk, and partition */
+ Maxxfer = 16*1024, /* maximum transfer size/cmd */
+};
+
+typedef struct {
+ ulong start;
+ ulong end;
+ char name[NAMELEN+1];
+} Partition;
+
+typedef struct {
+ int online;
+ int npart; /* number of real partitions */
+ Partition p[Npart];
+ ulong offset;
+ Partition *current; /* current partition */
+
+ ulong cap; /* total bytes */
+ int bytes; /* bytes/sector */
+ int sectors; /* sectors/track */
+ int heads; /* heads/cyl */
+ long cyl; /* cylinders/drive */
+
+ char lba; /* true if drive has logical block addressing */
+ char multi; /* non-zero if drive does multiple block xfers */
+} Disc;
+
+enum {
+ ScsiTestunit = 0x00,
+ ScsiExtsens = 0x03,
+ ScsiInquiry = 0x12,
+ ScsiModesense = 0x1a,
+ ScsiStartunit = 0x1B,
+ ScsiStopunit = 0x1B,
+ ScsiGetcap = 0x25,
+ ScsiRead = 0x08,
+ ScsiWrite = 0x0a,
+ ScsiExtread = 0x28,
+ ScsiExtwrite = 0x2a,
+
+ /* data direction */
+ ScsiIn = 1,
+ ScsiOut = 0,
+};
+
+typedef struct Scsibuf Scsibuf;
+typedef struct Scsibuf {
+ void* virt;
+ void* phys;
+ Scsibuf* next;
+};
+
+typedef struct Scsidata {
+ uchar* base;
+ uchar* lim;
+ uchar* ptr;
+} Scsidata;
+
+typedef struct Ureg Ureg;
+
+typedef struct Scsi {
+ ulong pid;
+ ushort target;
+ ushort lun;
+ ushort rflag;
+ ushort status;
+ Scsidata cmd;
+ Scsidata data;
+ Scsibuf* b;
+ uchar* save;
+ uchar cmdblk[16];
+} Scsi;
+
+typedef struct Segdesc {
+ ulong d0;
+ ulong d1;
+} Segdesc;
+
+typedef struct Mach {
+ ulong ticks; /* of the clock since boot time */
+ ulong delayloop;
+ long cpuhz; /* general system clock (cycles) */
+ long clockgen; /* clock generator frequency (cycles) */
+ ulong cpupvr; /* cpu type in processor version register */
+ ulong cputype; /* cpu variant in BCD (eg, 0x823xx) */
+ void* alarm; /* alarms bound to this clock */
+ ulong* bcsr;
+ IMM* iomem;
+} Mach;
+
+/* Mach.cputype */
+#define MPCREV(x) ((x) & 0xFF)
+#define MPCMODEL(x) (((x)>>8) & 0xFFF)
+#define MPCFAMILY(x) (((x)>>24) & 0x0F)
+
+
+extern Mach *m;
+
+#define Q_MAGIC ((((4*21)+0)*21)+7)
+
+typedef struct Exec Exec;
+struct Exec
+{
+ uchar magic[4]; /* magic number */
+ uchar text[4]; /* size of text segment */
+ uchar data[4]; /* size of initialized data */
+ uchar bss[4]; /* size of uninitialized data */
+ uchar syms[4]; /* size of symbol table */
+ uchar entry[4]; /* entry point */
+ uchar spsz[4]; /* size of sp/pc offset table */
+ uchar pcsz[4]; /* size of pc/line number table */
+};
+
+/*
+ * bootline passed by boot program
+ */
+#define BOOTLINE ((char *)0x200000-150)
+
+/*
+ * Where we leave configuration info.
+ */
+#define BOOTARGS ((char*)(0x200000))
+#define BOOTARGSLEN 1024
+#define MAXCONF 32
+
+/*
+ * a parsed plan9.ini line
+ */
+#define ISAOPTLEN 16
+#define NISAOPT 8
+
+typedef struct ISAConf {
+ char type[NAMELEN];
+ ulong port;
+ ulong irq;
+ ulong mem;
+ ulong size;
+ uchar ea[6];
+
+ int nopt;
+ char opt[NISAOPT][ISAOPTLEN];
+} ISAConf;
+
+typedef struct {
+ int size;
+ ulong addr;
+} Map;
+
+typedef struct {
+ char* name;
+ Map* map;
+ Map* mapend;
+
+ Lock;
+} RMap;
+
+typedef struct PCIcfg PCIcfg;
+
+extern uchar* vgamem;
+
+struct Block {
+ uchar *rp;
+ uchar *wp;
+ uchar *lim;
+ uchar *data;
+ Block* next;
+ ulong magic;
+};
+#define BLEN(b) ((b)->wp-(b)->rp)
+
+typedef struct QLock {
+ int dummy;
+} QLock;
--- /dev/null
+++ b/os/boot.original/mpc/defont0.c
@@ -1,0 +1,216 @@
+#include <u.h>
+#include <libc.h>
+#include <libg.h>
+#include <gnot.h>
+
+
+
+static ulong bits0[] = {
+ 0x907070f0, 0xf0f07000, 0xf0888888, 0xf8707070, 0xe0e0e0e0, 0xe09070f0, 0x70f870f0, 0xf870f088,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000e0,
+ 0xd0808080, 0x80808800, 0x8888c888, 0x80888888, 0x90909090, 0x90d08080, 0x80808080, 0x80888888,
+ 0x00000000, 0x08000000, 0x0c300000, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000003c, 0xc03c0000,
+ 0x00006000, 0x06001e00, 0x60181860, 0x78000000, 0x00000000, 0x00000000, 0x0000001c, 0x18380090,
+ 0xb06060e0, 0xe0e0f800, 0xf088a888, 0x80808080, 0x90909090, 0x90b060e0, 0x808060e0, 0x80808888,
+ 0x00182428, 0x3e707018, 0x18180000, 0x00000006, 0x3c183c3c, 0x1c3e3c7e, 0x3c3c0000, 0x0200403c,
+ 0x3c187c1e, 0x787e7e1e, 0x663c7c66, 0x6066623c, 0x7c3c7c3c, 0x7e6266c2, 0x66667e30, 0xc00c1000,
+ 0x08006000, 0x06003000, 0x60181860, 0x18000000, 0x00000000, 0x10000000, 0x00000030, 0x180c0090,
+ 0x90101080, 0x80808818, 0x88f8a888, 0xe0807070, 0xe0e0e0e0, 0xe0901080, 0x70e01080, 0xe098f088,
+ 0x00182428, 0x6adad818, 0x18181000, 0x0000000c, 0x66386666, 0x2c3e667e, 0x66660000, 0x06006066,
+ 0x42186632, 0x6c606032, 0x66181864, 0x60667224, 0x66246666, 0x186262da, 0x62620630, 0x600c3800,
+ 0x10006000, 0x06003000, 0x60000060, 0x18000000, 0x00000000, 0x30000000, 0x00000030, 0x180c00e0,
+ 0x00e0e0f0, 0xf0f00018, 0x88889850, 0x80880808, 0x201c1c1c, 0x1c00e0f0, 0x0080e0f0, 0x80888888,
+ 0x00182428, 0x68dad808, 0x300c5418, 0x0000000c, 0x66580606, 0x2c206002, 0x66661818, 0x0cfe3006,
+ 0x9e2c6660, 0x66606060, 0x6618186c, 0x60667266, 0x66666660, 0x186262da, 0x36660c30, 0x600c2800,
+ 0x103c6c3c, 0x3e3c7e3e, 0x6c787866, 0x18d46c3c, 0x6c3e763c, 0x7e6666c2, 0x66667e18, 0x18180000,
+ 0x44180000, 0x18241c24, 0xf0888820, 0x8070f0f0, 0x20202020, 0x201c243e, 0x1cf8241c, 0x80708870,
+ 0x0018247c, 0x78745008, 0x300c3818, 0x00000018, 0x66180606, 0x4c206006, 0x76661818, 0x18fe180c,
+ 0xb62c6660, 0x66606060, 0x66181868, 0x607e5a66, 0x66666470, 0x186266da, 0x34340c30, 0x300c6c00,
+ 0x18667666, 0x66663066, 0x76181864, 0x18fe7666, 0x76663666, 0x306662da, 0x62620608, 0x1810323c,
+ 0x44247c7c, 0x24342042, 0x00000000, 0x00000000, 0x20202020, 0x20222408, 0x22002420, 0x00000000,
+ 0x00180028, 0x3c287610, 0x300cee7e, 0x00fe0018, 0x66180c18, 0x4c3c7c0c, 0x3c3e0000, 0x30000c18,
+ 0xb62c7c60, 0x667c7c6e, 0x7e181878, 0x605a5a66, 0x6466783c, 0x186234da, 0x18341830, 0x300c4400,
+ 0x18066660, 0x66663066, 0x66181868, 0x18d66666, 0x66663860, 0x306662da, 0x34620c30, 0x180c5a20,
+ 0x44241010, 0x242c2042, 0x0e3e103e, 0x3e3c1c3e, 0x3c1c1c1c, 0x1c3e1c08, 0x3e222418, 0x0e0e0e0e,
+ 0x0008007c, 0x1e5cdc00, 0x300c387e, 0x00fe0030, 0x66181806, 0x7e066618, 0x6e060000, 0x18001818,
+ 0xb67e6660, 0x66606066, 0x6618186c, 0x605a4e66, 0x78666c0e, 0x1862346c, 0x2c183030, 0x180c4400,
+ 0x003e6660, 0x667e3066, 0x66181878, 0x18d66666, 0x6666303c, 0x306634da, 0x18341808, 0x18104c38,
+ 0x3c181010, 0x18241c42, 0x11081008, 0x20222208, 0x00000000, 0x00220408, 0x22361804, 0x11111111,
+ 0x00000028, 0x16b6cc00, 0x300c5418, 0x00000030, 0x66183006, 0x7e066618, 0x66060000, 0x0cfe3000,
+ 0x9a466660, 0x66606066, 0x6618186c, 0x605a4e66, 0x60666606, 0x1862346c, 0x6c183030, 0x180c0000,
+ 0x00666660, 0x66603066, 0x6618186c, 0x18d66666, 0x66663006, 0x3066346c, 0x2c343018, 0x18180020,
+ 0x00091010, 0x000e0942, 0x10081008, 0x20222208, 0x0f06060f, 0x0a09041e, 0x002a0e38, 0x10101010,
+ 0x00180028, 0x56b6cc00, 0x300c1018, 0x18001860, 0x66187e66, 0x0c666630, 0x66661818, 0x06fe6018,
+ 0x40466632, 0x6c606036, 0x66181866, 0x605a4624, 0x60246666, 0x1834186c, 0x46186030, 0x0c0c0000,
+ 0x006e6666, 0x6e66306e, 0x66181866, 0x18d66666, 0x666e3066, 0x306e186c, 0x46186030, 0x180c003c,
+ 0x08090909, 0x1f110aff, 0x0e081008, 0x382c2208, 0x08020901, 0x0a0a0911, 0x09220907, 0x0e0e0e0e,
+ 0x00180028, 0x7c1c7600, 0x18180000, 0x18001860, 0x3c7e7e3c, 0x0c3c3c30, 0x3c3c1818, 0x02004018,
+ 0x3e467c1e, 0x787e601e, 0x663c1866, 0x7e42463c, 0x603c663c, 0x1818186c, 0x66187e30, 0x0c0c0000,
+ 0x00367c3c, 0x363c7c36, 0x667e1866, 0x7ed6663c, 0x7c367c3c, 0x1e36186c, 0x66187e30, 0x180c0008,
+ 0x080f0606, 0x04110c18, 0x01081008, 0x20222208, 0x0e020203, 0x0a0c0d1e, 0x0d220e08, 0x01010101,
+ 0x00000000, 0x10000000, 0x18180000, 0x080000c0, 0x00000000, 0x00000000, 0x00000008, 0x00000000,
+ 0x00000000, 0x00000000, 0x00001800, 0x00000000, 0x000c0000, 0x00000000, 0x00000030, 0x060c00fe,
+ 0x00000000, 0x00000006, 0x00001800, 0x00000000, 0x60060000, 0x00000000, 0x0010001c, 0x18380008,
+ 0x08090606, 0x040e0a18, 0x11081f08, 0x20221c3e, 0x08020401, 0x0f0a0b11, 0x0b220908, 0x11111111,
+ 0x00000000, 0x00000000, 0x0c300000, 0x080000c0, 0x00000000, 0x00000000, 0x00000008, 0x00000000,
+ 0x00000000, 0x00000000, 0x00007000, 0x00000000, 0x00060000, 0x00000000, 0x0000003c, 0x063c0000,
+ 0x00000000, 0x00000066, 0x00001800, 0x00000000, 0x60060000, 0x00000000, 0x00300000, 0x00000008,
+ 0x0f090909, 0x04030900, 0x0e000000, 0x00000000, 0x0f0f0f0f, 0x0209091e, 0x09000f07, 0x0e0e0e0e,
+ 0x00000000, 0x00000000, 0x00000000, 0x10000000, 0x00000000, 0x00000000, 0x00000010, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x0000003c, 0x00007000, 0x00000000, 0x60060000, 0x00000000, 0x00600000, 0x0000000f,
+
+};
+
+static GBitmap strike0 = {
+ bits0,
+ 0,
+ 32,
+ 0,
+ {0, 0, 1024, 14},
+ {0, 0, 1024, 14},
+};
+
+static Fontchar info0[] = {
+ { 0, 0, 14, 0, 8 },
+ { 8, 0, 14, 0, 8 },
+ { 16, 0, 14, 0, 8 },
+ { 24, 0, 14, 0, 8 },
+ { 32, 0, 14, 0, 8 },
+ { 40, 0, 14, 0, 8 },
+ { 48, 0, 14, 0, 8 },
+ { 56, 0, 14, 0, 8 },
+ { 64, 0, 14, 0, 8 },
+ { 72, 0, 14, 0, 8 },
+ { 80, 0, 14, 0, 8 },
+ { 88, 0, 14, 0, 8 },
+ { 96, 0, 14, 0, 8 },
+ { 104, 0, 14, 0, 8 },
+ { 112, 0, 14, 0, 8 },
+ { 120, 0, 14, 0, 8 },
+ { 128, 0, 14, 0, 8 },
+ { 136, 0, 14, 0, 8 },
+ { 144, 0, 14, 0, 8 },
+ { 152, 0, 14, 0, 8 },
+ { 160, 0, 14, 0, 8 },
+ { 168, 0, 14, 0, 8 },
+ { 176, 0, 14, 0, 8 },
+ { 184, 0, 14, 0, 8 },
+ { 192, 0, 14, 0, 8 },
+ { 200, 0, 14, 0, 8 },
+ { 208, 0, 14, 0, 8 },
+ { 216, 0, 14, 0, 8 },
+ { 224, 0, 14, 0, 8 },
+ { 232, 0, 14, 0, 8 },
+ { 240, 0, 14, 0, 8 },
+ { 248, 0, 14, 0, 8 },
+ { 256, 0, 0, 0, 8 },
+ { 264, 2, 11, 0, 8 },
+ { 272, 2, 6, 0, 8 },
+ { 280, 2, 11, 0, 8 },
+ { 288, 1, 12, 0, 8 },
+ { 296, 2, 11, 0, 8 },
+ { 304, 2, 11, 0, 8 },
+ { 312, 2, 7, 0, 8 },
+ { 320, 1, 13, 0, 8 },
+ { 328, 1, 13, 0, 8 },
+ { 336, 3, 10, 0, 8 },
+ { 344, 4, 10, 0, 8 },
+ { 352, 9, 14, 0, 8 },
+ { 360, 6, 8, 0, 8 },
+ { 368, 9, 11, 0, 8 },
+ { 376, 1, 13, 0, 8 },
+ { 384, 2, 11, 0, 8 },
+ { 392, 2, 11, 0, 8 },
+ { 400, 2, 11, 0, 8 },
+ { 408, 2, 11, 0, 8 },
+ { 416, 2, 11, 0, 8 },
+ { 424, 2, 11, 0, 8 },
+ { 432, 2, 11, 0, 8 },
+ { 440, 2, 11, 0, 8 },
+ { 448, 2, 11, 0, 8 },
+ { 456, 2, 11, 0, 8 },
+ { 464, 4, 11, 0, 8 },
+ { 472, 4, 14, 0, 8 },
+ { 480, 2, 11, 0, 8 },
+ { 488, 4, 10, 0, 8 },
+ { 496, 2, 11, 0, 8 },
+ { 504, 2, 11, 0, 8 },
+ { 512, 2, 11, 0, 8 },
+ { 520, 2, 11, 0, 8 },
+ { 528, 2, 11, 0, 8 },
+ { 536, 2, 11, 0, 8 },
+ { 544, 2, 11, 0, 8 },
+ { 552, 2, 11, 0, 8 },
+ { 560, 2, 11, 0, 8 },
+ { 568, 2, 11, 0, 8 },
+ { 576, 2, 11, 0, 8 },
+ { 584, 2, 11, 0, 8 },
+ { 592, 2, 13, 0, 8 },
+ { 600, 2, 11, 0, 8 },
+ { 608, 2, 11, 0, 8 },
+ { 616, 2, 11, 0, 8 },
+ { 624, 2, 11, 0, 8 },
+ { 632, 2, 11, 0, 8 },
+ { 640, 2, 11, 0, 8 },
+ { 648, 2, 13, 0, 8 },
+ { 656, 2, 11, 0, 8 },
+ { 664, 2, 11, 0, 8 },
+ { 672, 2, 11, 0, 8 },
+ { 680, 2, 11, 0, 8 },
+ { 688, 2, 11, 0, 8 },
+ { 696, 2, 11, 0, 8 },
+ { 704, 2, 11, 0, 8 },
+ { 712, 2, 11, 0, 8 },
+ { 720, 2, 11, 0, 8 },
+ { 728, 1, 13, 0, 8 },
+ { 736, 1, 13, 0, 8 },
+ { 744, 1, 13, 0, 8 },
+ { 752, 2, 8, 0, 8 },
+ { 760, 11, 12, 0, 8 },
+ { 768, 2, 7, 0, 8 },
+ { 776, 4, 11, 0, 8 },
+ { 784, 1, 11, 0, 8 },
+ { 792, 4, 11, 0, 8 },
+ { 800, 1, 11, 0, 8 },
+ { 808, 4, 11, 0, 8 },
+ { 816, 1, 11, 0, 8 },
+ { 824, 4, 14, 0, 8 },
+ { 832, 1, 11, 0, 8 },
+ { 840, 1, 11, 0, 8 },
+ { 848, 1, 14, 0, 8 },
+ { 856, 1, 11, 0, 8 },
+ { 864, 1, 11, 0, 8 },
+ { 872, 4, 11, 0, 8 },
+ { 880, 4, 11, 0, 8 },
+ { 888, 4, 11, 0, 8 },
+ { 896, 4, 14, 0, 8 },
+ { 904, 4, 14, 0, 8 },
+ { 912, 4, 11, 0, 8 },
+ { 920, 4, 11, 0, 8 },
+ { 928, 2, 11, 0, 8 },
+ { 936, 4, 11, 0, 8 },
+ { 944, 4, 11, 0, 8 },
+ { 952, 4, 11, 0, 8 },
+ { 960, 4, 11, 0, 8 },
+ { 968, 4, 14, 0, 8 },
+ { 976, 4, 11, 0, 8 },
+ { 984, 1, 12, 0, 8 },
+ { 992, 1, 12, 0, 8 },
+ { 1000, 1, 12, 0, 8 },
+ { 1008, 5, 8, 0, 8 },
+ { 1016, 0, 14, 0, 8 },
+ { 1024, 0, 14, 0, 8 },
+ { 0, 0, 0, 0, 0 }
+};
+
+GSubfont defont0 = {
+ 129,
+ 14,
+ 2,
+ info0,
+ &strike0,
+};
--- /dev/null
+++ b/os/boot.original/mpc/devether.c
@@ -1,0 +1,157 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+static Ctlr ether[MaxEther];
+
+static struct {
+ char *type;
+ int (*reset)(Ctlr*);
+} cards[] = {
+ { "SCC", sccethreset, },
+ { "SCC2", sccethreset, },
+ { 0, }
+};
+
+int
+etherinit(void)
+{
+ Ctlr *ctlr;
+ int ctlrno, i, mask, n;
+
+ mask = 0;
+ for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+ ctlr = ðer[ctlrno];
+ memset(ctlr, 0, sizeof(Ctlr));
+ if(isaconfig("ether", ctlrno, &ctlr->card) == 0)
+ continue;
+ for(n = 0; cards[n].type; n++){
+ if(strcmp(cards[n].type, ctlr->card.type))
+ continue;
+ ctlr->ctlrno = ctlrno;
+ if((*cards[n].reset)(ctlr))
+ break;
+
+ ctlr->iq = qopen(16*1024, 1, 0, 0);
+ ctlr->oq = qopen(16*1024, 1, 0, 0);
+
+ ctlr->present = 1;
+ mask |= 1<<ctlrno;
+
+ print("ether%d: %s: port 0x%luX irq %d",
+ ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
+ if(ctlr->card.mem)
+ print(" addr 0x%luX", PADDR(ctlr->card.mem));
+ if(ctlr->card.size)
+ print(" size 0x%luX", ctlr->card.size);
+ print(":");
+ for(i = 0; i < sizeof(ctlr->card.ea); i++)
+ print(" %2.2uX", ctlr->card.ea[i]);
+ print("\n"); uartwait();
+ setvec(VectorPIC + ctlr->card.irq, ctlr->card.intr, ctlr);
+ break;
+ }
+ }
+
+ return mask;
+}
+
+static Ctlr*
+attach(int ctlrno)
+{
+ Ctlr *ctlr;
+
+ if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
+ return 0;
+
+ ctlr = ðer[ctlrno];
+ if(ctlr->present == 1){
+ ctlr->present = 2;
+ (*ctlr->card.attach)(ctlr);
+ }
+
+ return ctlr;
+}
+
+uchar*
+etheraddr(int ctlrno)
+{
+ Ctlr *ctlr;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ return ctlr->card.ea;
+}
+
+int
+etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
+{
+ int n;
+ Ctlr *ctlr;
+ Block *b;
+ ulong start;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ start = m->ticks;
+ while((b = qget(ctlr->iq)) == 0){
+ if(TK2MS(m->ticks - start) >= timo){
+ /*
+ print("ether%d: rx timeout\n", ctlrno);
+ */
+ return 0;
+ }
+ }
+
+ n = BLEN(b);
+ memmove(pkt, b->rp, n);
+ freeb(b);
+
+ return n;
+}
+
+int
+etheriq(Ctlr *ctlr, Block *b, int freebp)
+{
+ if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0 &&
+ memcmp(((Etherpkt*)b->rp)->d, broadcast, Eaddrlen) != 0){
+ if(freebp)
+ freeb(b);
+ return 0;
+ }
+ qbwrite(ctlr->iq, b);
+ return 1;
+}
+
+int
+ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
+{
+ Ctlr *ctlr;
+ Block *b;
+ int s;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ if(qlen(ctlr->oq) > 16*1024){
+ print("ether%d: tx queue full\n", ctlrno);
+ return 0;
+ }
+ b = iallocb(sizeof(Etherpkt));
+ memmove(b->wp, pkt, len);
+ memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
+ b->wp += len;
+ qbwrite(ctlr->oq, b);
+ s = splhi();
+ (*ctlr->card.transmit)(ctlr);
+ splx(s);
+
+ return 1;
+}
--- /dev/null
+++ b/os/boot.original/mpc/devuart.c
@@ -1,0 +1,230 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ * SMC1 in UART mode
+ */
+
+typedef struct Uartsmc Uartsmc;
+struct Uartsmc {
+ IOCparam;
+ ushort maxidl;
+ ushort idlc;
+ ushort brkln;
+ ushort brkec;
+ ushort brkcr;
+ ushort rmask;
+};
+
+typedef struct Uart Uart;
+struct Uart
+{
+ int port;
+ int setup;
+ uchar txbusy;
+
+ Queue* iq;
+ Queue* oq;
+ void (*rx)(Queue*, int);
+ void (*boot)(uchar*, int);
+
+ ulong frame;
+ ulong overrun;
+ uchar rxbuf[128];
+ char txbuf[16];
+ BD* rxb;
+ BD* txb;
+};
+
+Uart uart[1];
+int predawn = 1;
+
+static void uartintr(Ureg*, void*);
+static void uartkick(void*);
+
+static int
+baudgen(int baud)
+{
+ int d;
+
+ d = ((m->cpuhz/baud)+8)>>4;
+ if(d >= (1<<12))
+ return ((d+15)>>3)|1;
+ return d<<1;
+}
+
+static void
+smcsetup(Uart *up, int baud)
+{
+ IMM *io;
+ Uartsmc *p;
+ BD *bd;
+ SMC *smc;
+
+ archenableuart(SMC1ID, 0);
+ io = m->iomem;
+ io->pbpar |= IBIT(24)|IBIT(25); /* enable SMC1 TX/RX */
+ io->pbdir &= ~(IBIT(24)|IBIT(25));
+ io->brgc1 = baudgen(baud) | BaudEnable;
+ io->simode &= ~0xF000; /* SMC1 to NMSI mode, Tx/Rx clocks are BRG1 */
+
+ bd = bdalloc(1);
+ p = (Uartsmc*)KADDR(SMC1P);
+ p->rbase = (ushort)bd;
+ up->rxb = bd;
+ bd->status = BDEmpty|BDWrap|BDInt;
+ bd->length = 0;
+ bd->addr = PADDR(up->rxbuf);
+ bd = bdalloc(1);
+ p->tbase = (ushort)bd;
+ up->txb = bd;
+ bd->status = BDWrap|BDInt;
+ bd->length = 0;
+ bd->addr = PADDR(up->txbuf);
+
+ cpmop(InitRxTx, SMC1ID, 0);
+
+ /* protocol parameters */
+ p->rfcr = 0x18;
+ p->tfcr = 0x18;
+ p->mrblr = 1;
+ p->maxidl = 1;
+ p->brkln = 0;
+ p->brkec = 0;
+ p->brkcr = 1;
+ smc = IOREGS(0xA80, SMC);
+ smc->smce = 0xff; /* clear events */
+ smc->smcm = 0x17; /* enable all possible interrupts */
+ setvec(VectorCPIC+4, uartintr, up);
+ smc->smcmr = 0x4820; /* 8-bit mode, no parity, 1 stop bit, UART mode, ... */
+ smc->smcmr |= 3; /* enable rx/tx */
+}
+
+static void
+uartintr(Ureg*, void *arg)
+{
+ Uart *up;
+ int ch, i;
+ BD *bd;
+ SMC *smc;
+ Block *b;
+
+ up = arg;
+ smc = IOREGS(0xA80, SMC);
+ smc->smce = 0xff; /* clear all events */
+ if((bd = up->rxb) != nil && (bd->status & BDEmpty) == 0){
+ if(up->iq != nil && bd->length > 0){
+ if(up->boot != nil){
+ up->boot(up->rxbuf, bd->length);
+ }else if(up->rx != nil){
+ for(i=0; i<bd->length; i++){
+ ch = up->rxbuf[i];
+ up->rx(up->iq, ch);
+ }
+ }else{
+ b = iallocb(bd->length);
+ memmove(b->wp, up->rxbuf, bd->length);
+ b->wp += bd->length;
+ qbwrite(up->iq, b);
+ }
+ }
+ bd->status |= BDEmpty|BDInt;
+ } else if((bd = up->txb) != nil && (bd->status & BDReady) == 0){
+ ch = -1;
+ if(up->oq)
+ ch = qbgetc(up->oq);
+ if(ch != -1){
+ up->txbuf[0] = ch;
+ bd->length = 1;
+ bd->status |= BDReady;
+ }else
+ up->txbusy = 0;
+ }
+ /* TO DO: modem status, errors, etc */
+}
+
+static void
+uartkick(void *arg)
+{
+ Uart *up = arg;
+ int s, c, i;
+
+ s = splhi();
+ while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1){
+ if(predawn){
+ while(up->txb->status & BDReady)
+ ;
+ } else {
+ for(i = 0; i < 100; i++){
+ if((up->txb->status & BDReady) == 0)
+ break;
+ delay(1);
+ }
+ }
+ up->txbuf[0] = c;
+ up->txb->length = 1;
+ up->txb->status |= BDReady;
+ up->txbusy = !predawn;
+ }
+ splx(s);
+}
+
+void
+uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue*,int))
+{
+ Uart *up = &uart[0];
+
+ if(up->setup)
+ return;
+ up->setup = 1;
+
+ *iq = up->iq = qopen(4*1024, 0, 0, 0);
+ *oq = up->oq = qopen(16*1024, 0, uartkick, up);
+ up->rx = rx;
+ USED(port);
+ up->port = SMC1ID;
+ if(baud == 0)
+ baud = 9600;
+ smcsetup(up, baud);
+ /* if using SCCn's UART, would also set DTR and RTS, but SMC doesn't use them */
+}
+
+void
+uartsetboot(void (*f)(uchar*, int))
+{
+ uart[0].boot = f;
+}
+
+void
+uartputs(char *s, int n)
+{
+ Uart *up = &uart[0];
+ Block *b;
+ int nl;
+ char *p;
+
+ nl = 0;
+ for(p = s; p < s+n; p++)
+ if(*p == '\n')
+ nl++;
+ b = iallocb(n+nl);
+ while(n--){
+ if(*s == '\n')
+ *b->wp++ = '\r';
+ *b->wp++ = *s++;
+ }
+ qbwrite(up->oq, b);
+}
+
+void
+uartwait(void)
+{
+ Uart *up = &uart[0];
+
+ while(up->txbusy)
+ ;
+}
--- /dev/null
+++ b/os/boot.original/mpc/dload.c
@@ -1,0 +1,103 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+static char *kernelfile = "/power/ipaq";
+ulong crc32(void *buf, int n, ulong crc);
+
+void
+main(int argc, char **argv)
+{
+ int ifd, n;
+ char buf[64], reply[1];
+ int i, execsize;
+ Fhdr f;
+ ulong csum;
+
+ ARGBEGIN{
+ }ARGEND
+ ifd = open(kernelfile, OREAD);
+ if(ifd < 0){
+ fprint(2, "dload: can't open %s: %r\n", kernelfile);
+ exits("open");
+ }
+ i = 0;
+ if(crackhdr(ifd, &f) == 0){
+ fprint(2, "dload: not an executable file: %r\n");
+ exits("format");
+ }
+ if(f.magic != Q_MAGIC){
+ fprint(2, "dload: not a powerpc executable\n");
+ exits("format");
+ }
+ execsize = f.txtsz + f.datsz + f.txtoff;
+ seek(ifd, 0, 0);
+ csum = ~0;
+ while(execsize > 0 && (n = read(ifd, buf, sizeof(buf))) > 0){
+ if(n > execsize)
+ n = execsize;
+ for(;;){
+ if(write(1, buf, sizeof(buf)) != sizeof(buf)){ /* always writes full buffer */
+ fprint(2, "dload: write error: %r\n");
+ exits("write");
+ }
+ if(read(0, reply, 1) != 1){
+ fprint(2, "dload: bad reply\n");
+ exits("read");
+ }
+ if(reply[0] != 'n')
+ break;
+ fprint(2, "!");
+ }
+ if(reply[0] != 'y'){
+ fprint(2, "dload: bad ack: %c\n", reply[0]);
+ exits("reply");
+ }
+ if(++i%10 == 0)
+ fprint(2, ".");
+ execsize -= n;
+ }
+ exits(0);
+}
+
+/*
+ * from Rob Warnock
+ */
+static ulong crc32tab[256]; /* initialised on first call to crc32 */
+
+enum {
+ CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+ int i, j;
+ ulong c;
+
+ for(i = 0; i < 256; i++) {
+ for(c = i << 24, j = 8; j > 0; j--)
+ if(c & (1<<31))
+ c = (c<<1) ^ CRC32POLY;
+ else
+ c <<= 1;
+ crc32tab[i] = c;
+ }
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+ uchar *p;
+
+ if(crc32tab[1] == 0)
+ initcrc32();
+ crc = ~crc;
+ for(p = buf; --n >= 0;)
+ crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+ return ~crc;
+}
--- /dev/null
+++ b/os/boot.original/mpc/donprint.c
@@ -1,0 +1,332 @@
+#include "u.h"
+#include "lib.h"
+
+#define PTR sizeof(char*)
+#define SHORT sizeof(int)
+#define INT sizeof(int)
+#define LONG sizeof(long)
+#define IDIGIT 30
+#define MAXCON 30
+
+#define FLONG (1<<0)
+#define FSHORT (1<<1)
+#define FUNSIGN (1<<2)
+
+typedef struct Op Op;
+struct Op
+{
+ char *p;
+ char *ep;
+ void *argp;
+ int f1;
+ int f2;
+ int f3;
+};
+
+static int noconv(Op*);
+static int cconv(Op*);
+static int dconv(Op*);
+static int hconv(Op*);
+static int lconv(Op*);
+static int oconv(Op*);
+static int sconv(Op*);
+static int uconv(Op*);
+static int xconv(Op*);
+static int Xconv(Op*);
+static int percent(Op*);
+
+static
+int (*fmtconv[MAXCON])(Op*) =
+{
+ noconv,
+ cconv, dconv, hconv, lconv,
+ oconv, sconv, uconv, xconv,
+ Xconv, percent,
+};
+static
+char fmtindex[128] =
+{
+ ['c'] 1,
+ ['d'] 2,
+ ['h'] 3,
+ ['l'] 4,
+ ['o'] 5,
+ ['s'] 6,
+ ['u'] 7,
+ ['x'] 8,
+ ['X'] 9,
+ ['%'] 10,
+};
+
+static int convcount = { 11 };
+static int ucase;
+
+static void
+PUT(Op *o, int c)
+{
+ static int pos;
+ int opos;
+
+ if(c == '\t'){
+ opos = pos;
+ pos = (opos+8) & ~7;
+ while(opos++ < pos && o->p < o->ep)
+ *o->p++ = ' ';
+ return;
+ }
+ if(o->p < o->ep){
+ *o->p++ = c;
+ pos++;
+ }
+ if(c == '\n')
+ pos = 0;
+}
+
+int
+fmtinstall(char c, int (*f)(Op*))
+{
+
+ c &= 0177;
+ if(fmtindex[c] == 0) {
+ if(convcount >= MAXCON)
+ return 1;
+ fmtindex[c] = convcount++;
+ }
+ fmtconv[fmtindex[c]] = f;
+ return 0;
+}
+
+char*
+donprint(char *p, char *ep, char *fmt, void *argp)
+{
+ int sf1, c;
+ Op o;
+
+ o.p = p;
+ o.ep = ep;
+ o.argp = argp;
+
+loop:
+ c = *fmt++;
+ if(c != '%') {
+ if(c == 0) {
+ if(o.p < o.ep)
+ *o.p = 0;
+ return o.p;
+ }
+ PUT(&o, c);
+ goto loop;
+ }
+ o.f1 = 0;
+ o.f2 = -1;
+ o.f3 = 0;
+ c = *fmt++;
+ sf1 = 0;
+ if(c == '-') {
+ sf1 = 1;
+ c = *fmt++;
+ }
+ while(c >= '0' && c <= '9') {
+ o.f1 = o.f1*10 + c-'0';
+ c = *fmt++;
+ }
+ if(sf1)
+ o.f1 = -o.f1;
+ if(c != '.')
+ goto l1;
+ c = *fmt++;
+ while(c >= '0' && c <= '9') {
+ if(o.f2 < 0)
+ o.f2 = 0;
+ o.f2 = o.f2*10 + c-'0';
+ c = *fmt++;
+ }
+l1:
+ if(c == 0)
+ fmt--;
+ c = (*fmtconv[fmtindex[c&0177]])(&o);
+ if(c < 0) {
+ o.f3 |= -c;
+ c = *fmt++;
+ goto l1;
+ }
+ o.argp = (char*)o.argp + c;
+ goto loop;
+}
+
+void
+strconv(char *o, Op *op, int f1, int f2)
+{
+ int n, c;
+ char *p;
+
+ n = strlen(o);
+ if(f1 >= 0)
+ while(n < f1) {
+ PUT(op, ' ');
+ n++;
+ }
+ for(p=o; c = *p++;)
+ if(f2 != 0) {
+ PUT(op, c);
+ f2--;
+ }
+ if(f1 < 0) {
+ f1 = -f1;
+ while(n < f1) {
+ PUT(op, ' ');
+ n++;
+ }
+ }
+}
+
+int
+numbconv(Op *op, int base)
+{
+ char b[IDIGIT];
+ int i, f, n, r;
+ long v;
+ short h;
+
+ f = 0;
+ switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
+ case FLONG:
+ v = *(long*)op->argp;
+ r = LONG;
+ break;
+
+ case FUNSIGN|FLONG:
+ v = *(ulong*)op->argp;
+ r = LONG;
+ break;
+
+ case FSHORT:
+ h = *(int*)op->argp;
+ v = h;
+ r = SHORT;
+ break;
+
+ case FUNSIGN|FSHORT:
+ h = *(int*)op->argp;
+ v = (ushort)h;
+ r = SHORT;
+ break;
+
+ default:
+ v = *(int*)op->argp;
+ r = INT;
+ break;
+
+ case FUNSIGN:
+ v = *(unsigned*)op->argp;
+ r = INT;
+ break;
+ }
+ if(!(op->f3 & FUNSIGN) && v < 0) {
+ v = -v;
+ f = 1;
+ }
+ b[IDIGIT-1] = 0;
+ for(i = IDIGIT-2;; i--) {
+ n = (ulong)v % base;
+ n += '0';
+ if(n > '9'){
+ n += 'a' - ('9'+1);
+ if(ucase)
+ n += 'A'-'a';
+ }
+ b[i] = n;
+ if(i < 2)
+ break;
+ v = (ulong)v / base;
+ if(op->f2 >= 0 && i >= IDIGIT-op->f2)
+ continue;
+ if(v <= 0)
+ break;
+ }
+ if(f)
+ b[--i] = '-';
+ strconv(b+i, op, op->f1, -1);
+ return r;
+}
+
+static int
+noconv(Op *op)
+{
+
+ strconv("***", op, 0, -1);
+ return 0;
+}
+
+static int
+cconv(Op *op)
+{
+ char b[2];
+
+ b[0] = *(int*)op->argp;
+ b[1] = 0;
+ strconv(b, op, op->f1, -1);
+ return INT;
+}
+
+static int
+dconv(Op *op)
+{
+ return numbconv(op, 10);
+}
+
+static int
+hconv(Op*)
+{
+ return -FSHORT;
+}
+
+static int
+lconv(Op*)
+{
+ return -FLONG;
+}
+
+static int
+oconv(Op *op)
+{
+ return numbconv(op, 8);
+}
+
+static int
+sconv(Op *op)
+{
+ strconv(*(char**)op->argp, op, op->f1, op->f2);
+ return PTR;
+}
+
+static int
+uconv(Op*)
+{
+ return -FUNSIGN;
+}
+
+static int
+xconv(Op *op)
+{
+ return numbconv(op, 16);
+}
+
+static int
+Xconv(Op *op)
+{
+ int r;
+
+ ucase = 1;
+ r = numbconv(op, 16);
+ ucase = 0;
+ return r;
+}
+
+static int
+percent(Op *op)
+{
+
+ PUT(op, '%');
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/dosboot.c
@@ -1,0 +1,614 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "dosfs.h"
+
+extern char *premature;
+
+/*
+ * predeclared
+ */
+static void bootdump(Dosboot*);
+static void setname(Dosfile*, char*);
+long dosreadseg(Dosfile*, long, long);
+
+/*
+ * debugging
+ */
+#define chatty 1
+#define chat if(chatty)print
+
+/*
+ * block io buffers
+ */
+enum
+{
+ Nbio= 16,
+};
+typedef struct Clustbuf Clustbuf;
+struct Clustbuf
+{
+ int age;
+ long sector;
+ uchar *iobuf;
+ Dos *dos;
+ int size;
+};
+Clustbuf bio[Nbio];
+
+/*
+ * get an io block from an io buffer
+ */
+Clustbuf*
+getclust(Dos *dos, long sector)
+{
+ Clustbuf *p, *oldest;
+ int size;
+
+ chat("getclust @ %d\n", sector);
+
+ /*
+ * if we have it, just return it
+ */
+ for(p = bio; p < &bio[Nbio]; p++){
+ if(sector == p->sector && dos == p->dos){
+ p->age = m->ticks;
+ chat("getclust %d in cache\n", sector);
+ return p;
+ }
+ }
+
+ /*
+ * otherwise, reuse the oldest entry
+ */
+ oldest = bio;
+ for(p = &bio[1]; p < &bio[Nbio]; p++){
+ if(p->age <= oldest->age)
+ oldest = p;
+ }
+ p = oldest;
+
+ /*
+ * make sure the buffer is big enough
+ */
+ size = dos->clustsize*dos->sectsize;
+ if(p->iobuf==0 || p->size < size)
+ p->iobuf = ialloc(size, 0);
+ p->size = size;
+
+ /*
+ * read in the cluster
+ */
+ chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
+ if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
+ chat("can't seek block\n");
+ return 0;
+ }
+ if((*dos->read)(dos->dev, p->iobuf, size) != size){
+ chat("can't read block\n");
+ return 0;
+ }
+
+ p->age = m->ticks;
+ p->dos = dos;
+ p->sector = sector;
+ chat("getclust %d read\n", sector);
+ return p;
+}
+
+/*
+ * walk the fat one level ( n is a current cluster number ).
+ * return the new cluster number or -1 if no more.
+ */
+static long
+fatwalk(Dos *dos, int n)
+{
+ ulong k, sect;
+ Clustbuf *p;
+ int o;
+
+ chat("fatwalk %d\n", n);
+
+ if(n < 2 || n >= dos->fatclusters)
+ return -1;
+
+ switch(dos->fatbits){
+ case 12:
+ k = (3*n)/2; break;
+ case 16:
+ k = 2*n; break;
+ default:
+ return -1;
+ }
+ if(k >= dos->fatsize*dos->sectsize)
+ panic("getfat");
+
+ sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
+ o = k%(dos->sectsize*dos->clustsize);
+ p = getclust(dos, sect);
+ k = p->iobuf[o++];
+ if(o >= dos->sectsize*dos->clustsize){
+ p = getclust(dos, sect+dos->clustsize);
+ o = 0;
+ }
+ k |= p->iobuf[o]<<8;
+ if(dos->fatbits == 12){
+ if(n&1)
+ k >>= 4;
+ else
+ k &= 0xfff;
+ if(k >= 0xff8)
+ k |= 0xf000;
+ }
+ k = k < 0xfff8 ? k : -1;
+ chat("fatwalk %d -> %d\n", n, k);
+ return k;
+}
+
+/*
+ * map a file's logical cluster address to a physical sector address
+ */
+static long
+fileaddr(Dosfile *fp, long ltarget)
+{
+ Dos *dos = fp->dos;
+ long l;
+ long p;
+
+ chat("fileaddr %8.8s %d\n", fp->name, ltarget);
+ /*
+ * root directory is contiguous and easy
+ */
+ if(fp->pstart == 0){
+ if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
+ return -1;
+ l = dos->rootaddr + ltarget*dos->clustsize;
+ chat("fileaddr %d -> %d\n", ltarget, l);
+ return l;
+ }
+
+ /*
+ * anything else requires a walk through the fat
+ */
+ if(ltarget >= fp->lcurrent && fp->pcurrent){
+ /* start at the currrent point */
+ l = fp->lcurrent;
+ p = fp->pcurrent;
+ } else {
+ /* go back to the beginning */
+ l = 0;
+ p = fp->pstart;
+ }
+ while(l != ltarget){
+ /* walk the fat */
+ p = fatwalk(dos, p);
+ if(p < 0)
+ return -1;
+ l++;
+ }
+ fp->lcurrent = l;
+ fp->pcurrent = p;
+
+ /*
+ * clusters start at 2 instead of 0 (why? - presotto)
+ */
+ l = dos->dataaddr + (p-2)*dos->clustsize;
+ chat("fileaddr %d -> %d\n", ltarget, l);
+ return l;
+}
+
+/*
+ * read from a dos file
+ */
+long
+dosread(Dosfile *fp, void *a, long n)
+{
+ long addr;
+ long rv;
+ int i;
+ int off;
+ Clustbuf *p;
+ uchar *from, *to;
+
+ if((fp->attr & DDIR) == 0){
+ if(fp->offset >= fp->length)
+ return 0;
+ if(fp->offset+n > fp->length)
+ n = fp->length - fp->offset;
+ }
+
+ to = a;
+ for(rv = 0; rv < n; rv+=i){
+ /*
+ * read the cluster
+ */
+ addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
+ if(addr < 0)
+ return -1;
+ p = getclust(fp->dos, addr);
+ if(p == 0)
+ return -1;
+
+ /*
+ * copy the bytes we need
+ */
+ off = fp->offset % fp->dos->clustbytes;
+ from = &p->iobuf[off];
+ i = n - rv;
+ if(i > fp->dos->clustbytes - off)
+ i = fp->dos->clustbytes - off;
+ memmove(to, from, i);
+ to += i;
+ fp->offset += i;
+ }
+
+ return rv;
+}
+
+/*
+ * walk a directory returns
+ * -1 if something went wrong
+ * 0 if not found
+ * 1 if found
+ */
+int
+doswalk(Dosfile *file, char *name)
+{
+ Dosdir d;
+ long n;
+
+ if((file->attr & DDIR) == 0){
+ chat("walking non-directory!\n");
+ return -1;
+ }
+
+ setname(file, name);
+
+ file->offset = 0; /* start at the beginning */
+ while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
+ chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
+ if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
+ continue;
+ if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
+ continue;
+ if(d.attr & DVLABEL){
+ chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
+ continue;
+ }
+ file->attr = d.attr;
+ file->pstart = GSHORT(d.start);
+ file->length = GLONG(d.length);
+ file->pcurrent = 0;
+ file->lcurrent = 0;
+ file->offset = 0;
+ return 1;
+ }
+ return n >= 0 ? 0 : -1;
+}
+
+
+/*
+ * instructions that boot blocks can start with
+ */
+#define JMPSHORT 0xeb
+#define JMPNEAR 0xe9
+
+/*
+ * read dos file system properties
+ */
+int
+dosinit(Dos *dos, int start, int ishard)
+{
+ Dosboot *b;
+ int i;
+ Clustbuf *p;
+ Dospart *dp;
+ ulong mbroffset, offset;
+
+ /* defaults till we know better */
+ dos->start = start;
+ dos->sectsize = 512;
+ dos->clustsize = 1;
+ mbroffset = 0;
+
+dmddo:
+ /* get first sector */
+ p = getclust(dos, mbroffset);
+ if(p == 0){
+ chat("can't read boot block\n");
+ return -1;
+ }
+
+ /*
+ * If it's a hard disc then look for an MBR and pick either an
+ * active partition or the FAT with the lowest starting LBA.
+ * Things are tricky because we could be pointing to, amongst others:
+ * 1) a floppy BPB;
+ * 2) a hard disc MBR;
+ * 3) a hard disc extended partition table;
+ * 4) a logical drive on a hard disc;
+ * 5) a disc-manager boot block.
+ * They all have the same magic at the end of the block.
+ */
+ if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
+ chat("not DOS\n");
+ return -1;
+ }
+ p->dos = 0;
+ b = (Dosboot *)p->iobuf;
+ if(ishard && b->mediadesc != 0xF8){
+ dp = (Dospart*)&p->iobuf[0x1BE];
+ offset = 0xFFFFFFFF;
+ for(i = 0; i < 4; i++, dp++){
+ if(dp->type == DMDDO){
+ mbroffset = 63;
+ goto dmddo;
+ }
+ if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
+ continue;
+ if(dp->flag & 0x80){
+ offset = GLONG(dp->start);
+ break;
+ }
+ if(GLONG(dp->start) < offset)
+ offset = GLONG(dp->start);
+ }
+ if(i != 4 || offset != 0xFFFFFFFF){
+ dos->start = mbroffset+offset;
+ p = getclust(dos, 0);
+ if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
+ return -1;
+ }
+ p->dos = 0;
+ }
+
+ b = (Dosboot *)p->iobuf;
+ if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
+ chat("no dos file system\n");
+ return -1;
+ }
+
+ if(chatty)
+ bootdump(b);
+
+ /*
+ * determine the systems' wondersous properties
+ */
+ dos->sectsize = GSHORT(b->sectsize);
+ dos->clustsize = b->clustsize;
+ dos->clustbytes = dos->sectsize*dos->clustsize;
+ dos->nresrv = GSHORT(b->nresrv);
+ dos->nfats = b->nfats;
+ dos->rootsize = GSHORT(b->rootsize);
+ dos->volsize = GSHORT(b->volsize);
+ if(dos->volsize == 0)
+ dos->volsize = GLONG(b->bigvolsize);
+ dos->mediadesc = b->mediadesc;
+ dos->fatsize = GSHORT(b->fatsize);
+ dos->fataddr = dos->nresrv;
+ dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
+ i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
+ i = i/dos->sectsize;
+ dos->dataaddr = dos->rootaddr + i;
+ dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
+ if(dos->fatclusters < 4087)
+ dos->fatbits = 12;
+ else
+ dos->fatbits = 16;
+ dos->freeptr = 2;
+
+ /*
+ * set up the root
+ */
+ dos->root.dos = dos;
+ dos->root.pstart = 0;
+ dos->root.pcurrent = dos->root.lcurrent = 0;
+ dos->root.offset = 0;
+ dos->root.attr = DDIR;
+ dos->root.length = dos->rootsize*sizeof(Dosdir);
+
+ return 0;
+}
+
+static void
+bootdump(Dosboot *b)
+{
+ if(chatty == 0)
+ return;
+ print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
+ b->magic[0], b->magic[1], b->magic[2]);
+ print("version: \"%8.8s\"\n", b->version);
+ print("sectsize: %d\n", GSHORT(b->sectsize));
+ print("allocsize: %d\n", b->clustsize);
+ print("nresrv: %d\n", GSHORT(b->nresrv));
+ print("nfats: %d\n", b->nfats);
+ print("rootsize: %d\n", GSHORT(b->rootsize));
+ print("volsize: %d\n", GSHORT(b->volsize));
+ print("mediadesc: 0x%2.2x\n", b->mediadesc);
+ print("fatsize: %d\n", GSHORT(b->fatsize));
+ print("trksize: %d\n", GSHORT(b->trksize));
+ print("nheads: %d\n", GSHORT(b->nheads));
+ print("nhidden: %d\n", GLONG(b->nhidden));
+ print("bigvolsize: %d\n", GLONG(b->bigvolsize));
+ print("driveno: %d\n", b->driveno);
+ print("reserved0: 0x%2.2x\n", b->reserved0);
+ print("bootsig: 0x%2.2x\n", b->bootsig);
+ print("volid: 0x%8.8x\n", GLONG(b->volid));
+ print("label: \"%11.11s\"\n", b->label);
+}
+
+/*
+ * grab next element from a path, return the pointer to unprocessed portion of
+ * path.
+ */
+static char *
+nextelem(char *path, char *elem)
+{
+ int i;
+
+ while(*path == '/')
+ path++;
+ if(*path==0 || *path==' ')
+ return 0;
+ for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
+ if(i==28){
+ print("name component too long\n");
+ return 0;
+ }
+ *elem++ = *path++;
+ }
+ *elem = '\0';
+ return path;
+}
+
+int
+dosstat(Dos *dos, char *path, Dosfile *f)
+{
+ char element[NAMELEN];
+
+ *f = dos->root;
+ while(path = nextelem(path, element)){
+ switch(doswalk(f, element)){
+ case -1:
+ return -1;
+ case 0:
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * boot
+ */
+int
+dosboot(Dos *dos, char *path)
+{
+ Dosfile file;
+ long n;
+ long addr;
+ Exec *ep;
+ void (*b)(void);
+
+ switch(dosstat(dos, path, &file)){
+
+ case -1:
+ print("error walking to %s\n", path);
+ return -1;
+ case 0:
+ print("%s not found\n", path);
+ return -1;
+ case 1:
+ print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
+ file.ext, file.attr, file.pstart, file.length);
+ break;
+ }
+
+ /*
+ * read header
+ */
+ ep = (Exec*)ialloc(sizeof(Exec), 0);
+ n = sizeof(Exec);
+ if(dosreadseg(&file, n, (ulong) ep) != n){
+ print(premature);
+ return -1;
+ }
+ if(GLLONG(ep->magic) != Q_MAGIC){
+ print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+ return -1;
+ }
+
+ /*
+ * read text
+ */
+ addr = PADDR(GLLONG(ep->entry));
+ n = GLLONG(ep->text);
+ print("+%d", n);
+ if(dosreadseg(&file, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * read data (starts at first page after kernel)
+ */
+ addr = PGROUND(addr+n);
+ n = GLLONG(ep->data);
+ print("+%d", n);
+ if(dosreadseg(&file, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * bss and entry point
+ */
+ print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
+
+ /*
+ * Go to new code. It's up to the program to get its PC relocated to
+ * the right place.
+ */
+ b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+ (*b)();
+ return 0;
+}
+
+/*
+ * read in a segment
+ */
+long
+dosreadseg(Dosfile *fp, long len, long addr)
+{
+ char *a;
+ long n, sofar;
+
+ a = (char *)addr;
+ for(sofar = 0; sofar < len; sofar += n){
+ n = 8*1024;
+ if(len - sofar < n)
+ n = len - sofar;
+ n = dosread(fp, a + sofar, n);
+ if(n <= 0)
+ break;
+ print(".");
+ }
+ return sofar;
+}
+
+/*
+ * set up a dos file name
+ */
+static void
+setname(Dosfile *fp, char *from)
+{
+ char *to;
+
+ to = fp->name;
+ for(; *from && to-fp->name < 8; from++, to++){
+ if(*from == '.'){
+ from++;
+ break;
+ }
+ if(*from >= 'a' && *from <= 'z')
+ *to = *from + 'A' - 'a';
+ else
+ *to = *from;
+ }
+ while(to - fp->name < 8)
+ *to++ = ' ';
+
+ to = fp->ext;
+ for(; *from && to-fp->ext < 3; from++, to++){
+ if(*from >= 'a' && *from <= 'z')
+ *to = *from + 'A' - 'a';
+ else
+ *to = *from;
+ }
+ while(to-fp->ext < 3)
+ *to++ = ' ';
+
+ chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
+}
--- /dev/null
+++ b/os/boot.original/mpc/dosfs.h
@@ -1,0 +1,110 @@
+typedef struct Dosboot Dosboot;
+typedef struct Dos Dos;
+typedef struct Dosdir Dosdir;
+typedef struct Dosfile Dosfile;
+typedef struct Dospart Dospart;
+
+struct Dospart
+{
+ uchar flag; /* active flag */
+ uchar shead; /* starting head */
+ uchar scs[2]; /* starting cylinder/sector */
+ uchar type; /* partition type */
+ uchar ehead; /* ending head */
+ uchar ecs[2]; /* ending cylinder/sector */
+ uchar start[4]; /* starting sector */
+ uchar len[4]; /* length in sectors */
+};
+
+#define FAT12 0x01
+#define FAT16 0x04
+#define FATHUGE 0x06
+#define DMDDO 0x54
+
+struct Dosboot{
+ uchar magic[3];
+ uchar version[8];
+ uchar sectsize[2];
+ uchar clustsize;
+ uchar nresrv[2];
+ uchar nfats;
+ uchar rootsize[2];
+ uchar volsize[2];
+ uchar mediadesc;
+ uchar fatsize[2];
+ uchar trksize[2];
+ uchar nheads[2];
+ uchar nhidden[4];
+ uchar bigvolsize[4];
+ uchar driveno;
+ uchar reserved0;
+ uchar bootsig;
+ uchar volid[4];
+ uchar label[11];
+ uchar reserved1[8];
+};
+
+struct Dosfile{
+ Dos *dos; /* owning dos file system */
+ char name[8];
+ char ext[3];
+ uchar attr;
+ long length;
+ long pstart; /* physical start cluster address */
+ long pcurrent; /* physical current cluster address */
+ long lcurrent; /* logical current cluster address */
+ long offset;
+};
+
+struct Dos{
+ int dev; /* device id */
+ long (*read)(int, void*, long); /* read routine */
+ long (*seek)(int, long); /* seek routine */
+
+ int start; /* start of file system */
+ int sectsize; /* in bytes */
+ int clustsize; /* in sectors */
+ int clustbytes; /* in bytes */
+ int nresrv; /* sectors */
+ int nfats; /* usually 2 */
+ int rootsize; /* number of entries */
+ int volsize; /* in sectors */
+ int mediadesc;
+ int fatsize; /* in sectors */
+ int fatclusters;
+ int fatbits; /* 12 or 16 */
+ long fataddr; /* sector number */
+ long rootaddr;
+ long dataaddr;
+ long freeptr;
+
+ Dosfile root;
+};
+
+struct Dosdir{
+ uchar name[8];
+ uchar ext[3];
+ uchar attr;
+ uchar reserved[10];
+ uchar time[2];
+ uchar date[2];
+ uchar start[2];
+ uchar length[4];
+};
+
+#define DRONLY 0x01
+#define DHIDDEN 0x02
+#define DSYSTEM 0x04
+#define DVLABEL 0x08
+#define DDIR 0x10
+#define DARCH 0x20
+
+extern int chatty;
+
+extern int dosboot(Dos*, char*);
+extern int dosinit(Dos*, int, int);
+extern long dosread(Dosfile*, void*, long);
+extern int dosstat(Dos*, char*, Dosfile*);
+extern int doswalk(Dosfile*, char*);
+
+extern int plan9ini(Dos*, char*);
--- /dev/null
+++ b/os/boot.original/mpc/etherif.h
@@ -1,0 +1,59 @@
+/*
+ * All the goo for PC ethernet cards.
+ */
+typedef struct Card Card;
+typedef struct Type Type;
+typedef struct Ctlr Ctlr;
+
+/*
+ * Hardware interface.
+ */
+struct Card {
+ ISAConf;
+
+ int (*reset)(Ctlr*);
+ void (*attach)(Ctlr*);
+
+ void *(*read)(Ctlr*, void*, ulong, ulong);
+ void *(*write)(Ctlr*, ulong, void*, ulong);
+
+ void (*receive)(Ctlr*);
+ void (*transmit)(Ctlr*);
+ void (*intr)(Ureg*, void*);
+ void (*overflow)(Ctlr*);
+
+ uchar bit16; /* true if a 16 bit interface */
+ uchar ram; /* true if card has shared memory */
+
+ ulong dp8390; /* I/O address of 8390 (if any) */
+ ulong data; /* I/O data port if no shared memory */
+ uchar nxtpkt; /* software bndry */
+ uchar tstart; /* 8390 ring addresses */
+ uchar pstart;
+ uchar pstop;
+
+ uchar dummyrr; /* do dummy remote read */
+};
+
+/*
+ * Software controller.
+ */
+struct Ctlr {
+ Card card; /* hardware info */
+ int ctlrno;
+ int present;
+
+ Queue* iq;
+ Queue* oq;
+
+ int inpackets;
+ int outpackets;
+ int crcs; /* input crc errors */
+ int oerrs; /* output errors */
+ int frames; /* framing errors */
+ int overflows; /* packet overflows */
+ int buffs; /* buffering errors */
+};
+
+extern int sccethreset(Ctlr*);
+extern int etheriq(Ctlr*, Block*, int);
--- /dev/null
+++ b/os/boot.original/mpc/etherscc.c
@@ -1,0 +1,411 @@
+/*
+ * SCCn ethernet
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+enum {
+ Nrdre = 32, /* receive descriptor ring entries */
+ Ntdre = 4, /* transmit descriptor ring entries */
+
+ Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
+ Bufsize = (Rbsize+7)&~7, /* aligned */
+};
+
+enum {
+ /* ether-specific Rx BD bits */
+ RxMiss= 1<<8,
+ RxeLG= 1<<5,
+ RxeNO= 1<<4,
+ RxeSH= 1<<3,
+ RxeCR= 1<<2,
+ RxeOV= 1<<1,
+ RxeCL= 1<<0,
+ RxError= (RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL), /* various error flags */
+
+ /* ether-specific Tx BD bits */
+ TxPad= 1<<14, /* pad short frames */
+ TxTC= 1<<10, /* transmit CRC */
+ TxeDEF= 1<<9,
+ TxeHB= 1<<8,
+ TxeLC= 1<<7,
+ TxeRL= 1<<6,
+ TxeUN= 1<<1,
+ TxeCSL= 1<<0,
+
+ /* scce */
+ RXB= 1<<0,
+ TXB= 1<<1,
+ BSY= 1<<2,
+ RXF= 1<<3,
+ TXE= 1<<4,
+
+ /* gsmrl */
+ ENR= 1<<5,
+ ENT= 1<<4,
+
+ /* port A */
+ RXD1= SIBIT(15),
+ TXD1= SIBIT(14),
+
+ /* port B */
+ RTS1= IBIT(19),
+
+ /* port C */
+ CTS1= SIBIT(11),
+ CD1= SIBIT(10),
+};
+
+typedef struct Etherparam Etherparam;
+struct Etherparam {
+ SCCparam;
+ ulong c_pres; /* preset CRC */
+ ulong c_mask; /* constant mask for CRC */
+ ulong crcec; /* CRC error counter */
+ ulong alec; /* alighnment error counter */
+ ulong disfc; /* discard frame counter */
+ ushort pads; /* short frame PAD characters */
+ ushort ret_lim; /* retry limit threshold */
+ ushort ret_cnt; /* retry limit counter */
+ ushort mflr; /* maximum frame length reg */
+ ushort minflr; /* minimum frame length reg */
+ ushort maxd1; /* maximum DMA1 length reg */
+ ushort maxd2; /* maximum DMA2 length reg */
+ ushort maxd; /* rx max DMA */
+ ushort dma_cnt; /* rx dma counter */
+ ushort max_b; /* max bd byte count */
+ ushort gaddr[4]; /* group address filter */
+ ulong tbuf0_data0; /* save area 0 - current frm */
+ ulong tbuf0_data1; /* save area 1 - current frm */
+ ulong tbuf0_rba0;
+ ulong tbuf0_crc;
+ ushort tbuf0_bcnt;
+ ushort paddr[3]; /* physical address LSB to MSB increasing */
+ ushort p_per; /* persistence */
+ ushort rfbd_ptr; /* rx first bd pointer */
+ ushort tfbd_ptr; /* tx first bd pointer */
+ ushort tlbd_ptr; /* tx last bd pointer */
+ ulong tbuf1_data0; /* save area 0 - next frame */
+ ulong tbuf1_data1; /* save area 1 - next frame */
+ ulong tbuf1_rba0;
+ ulong tbuf1_crc;
+ ushort tbuf1_bcnt;
+ ushort tx_len; /* tx frame length counter */
+ ushort iaddr[4]; /* individual address filter*/
+ ushort boff_cnt; /* back-off counter */
+ ushort taddr[3]; /* temp address */
+};
+
+typedef struct {
+ SCC* scc;
+ int port;
+ int cpm;
+
+ BD* rdr; /* receive descriptor ring */
+ void* rrb; /* receive ring buffers */
+ int rdrx; /* index into rdr */
+
+ BD* tdr; /* transmit descriptor ring */
+ void* trb; /* transmit ring buffers */
+ int tdrx; /* index into tdr */
+} Mot;
+static Mot mot[MaxEther];
+
+static int sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID};
+static int sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P};
+static int sccreg[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60};
+static int sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B};
+
+static void
+attach(Ctlr *ctlr)
+{
+ mot[ctlr->ctlrno].scc->gsmrl |= ENR|ENT;
+ eieio();
+}
+
+static void
+transmit(Ctlr *ctlr)
+{
+ int len;
+ Mot *motp;
+ Block *b;
+ BD *tdre;
+
+ motp = &mot[ctlr->ctlrno];
+ while(((tdre = &motp->tdr[motp->tdrx])->status & BDReady) == 0){
+ b = qget(ctlr->oq);
+ if(b == 0)
+ break;
+
+ /*
+ * Copy the packet to the transmit buffer.
+ */
+ len = BLEN(b);
+ memmove(KADDR(tdre->addr), b->rp, len);
+
+ /*
+ * Give ownership of the descriptor to the chip, increment the
+ * software ring descriptor pointer and tell the chip to poll.
+ */
+ tdre->length = len;
+ eieio();
+ tdre->status = (tdre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
+ eieio();
+ motp->scc->todr = 1<<15; /* transmit now */
+ eieio();
+ motp->tdrx = NEXT(motp->tdrx, Ntdre);
+
+ freeb(b);
+
+ }
+}
+
+static void
+interrupt(Ureg*, void *ap)
+{
+ int len, events, status;
+ Mot *motp;
+ BD *rdre;
+ Block *b;
+ Ctlr *ctlr;
+
+ ctlr = ap;
+ motp = &mot[ctlr->ctlrno];
+
+ /*
+ * Acknowledge all interrupts and whine about those that shouldn't
+ * happen.
+ */
+ events = motp->scc->scce;
+ eieio();
+ motp->scc->scce = events;
+ eieio();
+ if(events & (TXE|BSY|RXB))
+ print("ETHER.SCC#%d: scce = 0x%uX\n", ctlr->ctlrno, events);
+ //print(" %ux|", events);
+ /*
+ * Receiver interrupt: run round the descriptor ring logging
+ * errors and passing valid receive data up to the higher levels
+ * until we encounter a descriptor still owned by the chip.
+ */
+ if(events & (RXF|RXB) || 1){
+ rdre = &motp->rdr[motp->rdrx];
+ while(((status = rdre->status) & BDEmpty) == 0){
+ if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
+ //if(status & RxBuff)
+ // ctlr->buffs++;
+ if(status & (1<<2))
+ ctlr->crcs++;
+ if(status & (1<<1))
+ ctlr->overflows++;
+ //print("eth rx: %ux\n", status);
+ if(status & RxError)
+ print("~");
+ else if((status & BDLast) == 0)
+ print("@");
+ }
+ else{
+ /*
+ * We have a packet. Read it into the next
+ * free ring buffer, if any.
+ */
+ len = rdre->length-4;
+ if((b = iallocb(len)) != 0){
+ memmove(b->wp, KADDR(rdre->addr), len);
+ b->wp += len;
+ etheriq(ctlr, b, 1);
+ }
+ }
+
+ /*
+ * Finished with this descriptor, reinitialise it,
+ * give it back to the chip, then on to the next...
+ */
+ rdre->length = 0;
+ rdre->status = (rdre->status & BDWrap) | BDEmpty | BDInt;
+ eieio();
+
+ motp->rdrx = NEXT(motp->rdrx, Nrdre);
+ rdre = &motp->rdr[motp->rdrx];
+ }
+ }
+
+ /*
+ * Transmitter interrupt: handle anything queued for a free descriptor.
+ */
+ if(events & TXB)
+ transmit(ctlr);
+ if(events & TXE)
+ cpmop(RestartTx, motp->cpm, 0);
+}
+
+static void
+ringinit(Mot* motp)
+{
+ int i, x;
+
+ /*
+ * Initialise the receive and transmit buffer rings. The ring
+ * entries must be aligned on 16-byte boundaries.
+ */
+ if(motp->rdr == 0)
+ motp->rdr = bdalloc(Nrdre);
+ if(motp->rrb == 0)
+ motp->rrb = ialloc(Nrdre*Bufsize, 0);
+ x = PADDR(motp->rrb);
+ for(i = 0; i < Nrdre; i++){
+ motp->rdr[i].length = 0;
+ motp->rdr[i].addr = x;
+ motp->rdr[i].status = BDEmpty|BDInt;
+ x += Bufsize;
+ }
+ motp->rdr[i-1].status |= BDWrap;
+ motp->rdrx = 0;
+
+ if(motp->tdr == 0)
+ motp->tdr = bdalloc(Ntdre);
+ if(motp->trb == 0)
+ motp->trb = ialloc(Ntdre*Bufsize, 0);
+ x = PADDR(motp->trb);
+ for(i = 0; i < Ntdre; i++){
+ motp->tdr[i].addr = x;
+ motp->tdr[i].length = 0;
+ motp->tdr[i].status = TxPad|BDInt|BDLast|TxTC;
+ x += Bufsize;
+ }
+ motp->tdr[i-1].status |= BDWrap;
+ motp->tdrx = 0;
+}
+
+/*
+ * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence,
+ * except that it sets the right bits for the MPC823ADS board when SCC2 is used,
+ * and those for the 860/821 development board for SCC1.
+ */
+static void
+sccsetup(Mot *ctlr, SCC *scc, uchar *ea)
+{
+ int i, rcs, tcs, w;
+ Etherparam *p;
+ IMM *io;
+
+
+ i = 2*(ctlr->port-1);
+ io = ioplock();
+ w = (TXD1|RXD1)<<i; /* TXDn and RXDn in port A */
+ io->papar |= w; /* enable TXDn and RXDn pins */
+ io->padir &= ~w;
+ io->paodr &= ~w; /* not open drain */
+
+ w = (CD1|CTS1)<<i; /* CLSN and RENA: CDn and CTSn in port C */
+ io->pcpar &= ~w; /* enable CLSN (CTSn) and RENA (CDn) */
+ io->pcdir &= ~w;
+ io->pcso |= w;
+ iopunlock();
+
+ /* clocks and transceiver control: details depend on the board's wiring */
+ archetherenable(ctlr->cpm, &rcs, &tcs);
+
+ sccnmsi(ctlr->port, rcs, tcs); /* connect the clocks */
+
+ p = (Etherparam*)KADDR(sccparam[ctlr->port]);
+ memset(p, 0, sizeof(*p));
+ p->rfcr = 0x18;
+ p->tfcr = 0x18;
+ p->mrblr = Bufsize;
+ p->rbase = PADDR(ctlr->rdr);
+ p->tbase = PADDR(ctlr->tdr);
+
+ cpmop(InitRxTx, ctlr->cpm, 0);
+
+ p->c_pres = ~0;
+ p->c_mask = 0xDEBB20E3;
+ p->crcec = 0;
+ p->alec = 0;
+ p->disfc = 0;
+ p->pads = 0x8888;
+ p->ret_lim = 0xF;
+ p->mflr = Rbsize;
+ p->minflr = ETHERMINTU+4;
+ p->maxd1 = Bufsize;
+ p->maxd2 = Bufsize;
+ p->p_per = 0; /* only moderate aggression */
+
+ for(i=0; i<Eaddrlen; i+=2)
+ p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i]; /* it's not the obvious byte order */
+
+ scc->psmr = (2<<10)|(5<<1); /* 32-bit CRC, ignore 22 bits before SFD */
+ scc->dsr = 0xd555;
+ scc->gsmrh = 0; /* normal operation */
+ scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC; /* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */
+ eieio();
+ scc->scce = ~0; /* clear all events */
+ eieio();
+ scc->sccm = TXE | RXF | TXB; /* enable interrupts */
+ eieio();
+
+ io = ioplock();
+ w = RTS1<<(ctlr->port-1); /* enable TENA pin (RTSn) */
+ io->pbpar |= w;
+ io->pbdir |= w;
+ iopunlock();
+
+ /* gsmrl enable is deferred until attach */
+}
+
+/*
+ * Prepare the SCCx ethernet for booting.
+ */
+int
+sccethreset(Ctlr* ctlr)
+{
+ uchar ea[Eaddrlen];
+ Mot *motp;
+ SCC *scc;
+ char line[50], def[50];
+
+ /*
+ * Since there's no EPROM, insist that the configuration entry
+ * (see conf.c and flash.c) holds the Ethernet address.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0){
+ print("no preset Ether address\n");
+ for(;;){
+ strcpy(def, "00108bf12900"); /* valid MAC address to be used only for initial configuration */
+ if(getstr("ether MAC address", line, sizeof(line), def) < 0)
+ return -1;
+ if(parseether(ctlr->card.ea, line) >= 0 || ctlr->card.ea[0] == 0xFF)
+ break;
+ print("invalid MAC address\n");
+ }
+ }
+
+ scc = IOREGS(sccreg[ctlr->card.port], SCC);
+ ctlr->card.irq = VectorCPIC+sccirq[ctlr->card.port];
+
+ motp = &mot[ctlr->ctlrno];
+ motp->scc = scc;
+ motp->port = ctlr->card.port;
+ motp->cpm = sccid[ctlr->card.port];
+
+ ringinit(motp);
+
+ sccsetup(motp, scc, ctlr->card.ea);
+
+ /* enable is deferred until attach */
+
+ ctlr->card.reset = sccethreset;
+ ctlr->card.attach = attach;
+ ctlr->card.transmit = transmit;
+ ctlr->card.intr = interrupt;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/fblt.c
@@ -1,0 +1,531 @@
+#include <u.h>
+#include <libc.h>
+#include <libg.h>
+#include <gnot.h>
+
+/*
+ * bitblt operates a 'word' at a time.
+ * WBITS is the number of bits in a word
+ * LWBITS=log2(WBITS),
+ * W2L is the number of words in a long
+ * WMASK has bits set for the low order word of a long
+ * WType is a pointer to a word
+ */
+#ifndef WBITS
+#define WBITS 32
+#define LWBITS 5
+#define W2L 1
+#define WMASK ~0UL
+typedef ulong *WType;
+#endif
+
+#define DEBUG
+
+#ifdef TEST
+/*
+ * globals used for testing
+ */
+int FORCEFORW;
+int FORCEBAKW;
+GBitmap *curdm, *cursm;
+Point curpt;
+Rectangle curr;
+Fcode curf;
+void *mem;
+#endif
+
+static void
+gbitexplode(ulong sw, ulong *buf, int sdep, int x)
+{
+ int j, o, q, n, nw, inc, qinc;
+ ulong s, dw, pix;
+
+ inc = 1 << sdep;
+ pix = (1 << inc) - 1;
+ nw = 1 << x;
+ n = 32 >> x;
+ qinc = (nw << sdep) - inc;
+ for(o = 32 - n; o >= 0; o -= n){
+ dw = 0;
+ s = sw >> o;
+ q = 0;
+ for(j = 0; j < n; j += inc){
+ dw |= (s & (pix << j)) << q;
+ q += qinc;
+ }
+ for(j = 0; j < x; j++)
+ dw |= dw << (inc << j);
+ *buf++ = dw;
+ }
+}
+
+/*
+void
+main(void)
+{
+ ulong buf[128];
+
+ gbitexplode(0x7777, buf, 0, 3);
+ exits(0);
+}
+*/
+
+void
+gbitblt(GBitmap *dm, Point pt, GBitmap *sm, Rectangle r, Fcode fcode)
+{
+ int width; /* width in bits of dst */
+ int wwidth; /* floor width in words */
+ int height; /* height in pixels minus 1 */
+ int sdep; /* src ldepth */
+ int ddep; /* dst ldepth */
+ int deltadep; /* diff between ldepths */
+ int sspan; /* words between scanlines in src */
+ int dspan; /* words between scanlines in dst */
+ int soff; /* bit offset of src start point */
+ int sdest; /* bit offset of src start point that matches doff when expanded */
+ int doff; /* bit offset of dst start point */
+ int delta; /* amount to shift src by */
+ int sign; /* of delta */
+ ulong *saddr;
+ ulong *daddr;
+ ulong *s;
+ ulong *d;
+ ulong mask;
+ ulong tmp; /* temp storage source word */
+ ulong sw; /* source word constructed */
+ ulong dw; /* dest word fetched */
+ ulong lmask; /* affected pixels in leftmost dst word */
+ ulong rmask; /* affected pixels in rightmost dst word */
+ int i;
+ int j;
+ ulong buf[32]; /* for expanding a source */
+ ulong *p; /* pointer into buf */
+ int spare; /* number of words already converted */
+
+
+#ifdef TEST
+ curdm = dm;
+ cursm = sm;
+ curpt = pt;
+ curr = r;
+ curf = fcode;
+#endif
+
+ gbitbltclip(&dm);
+
+ width = r.max.x - r.min.x;
+ if(width <= 0)
+ return;
+ height = r.max.y - r.min.y - 1;
+ if(height < 0)
+ return;
+
+ ddep = dm->ldepth;
+ pt.x <<= ddep;
+ width <<= ddep;
+
+ sdep = sm->ldepth;
+ r.min.x <<= sdep;
+ r.max.x <<= sdep;
+
+ dspan = dm->width * W2L;
+ sspan = sm->width * W2L;
+
+ daddr = (ulong*)((WType)dm->base
+ + dm->zero*W2L + pt.y*dspan
+ + (pt.x >> LWBITS));
+ saddr = (ulong*)((WType)sm->base
+ + sm->zero*W2L + r.min.y*sspan
+ + (r.min.x >> LWBITS));
+
+ doff = pt.x & (WBITS - 1);
+ lmask = WMASK >> doff;
+ rmask = (WMASK << (WBITS - ((doff+width) & (WBITS-1))))&WMASK;
+ if(!rmask)
+ rmask = WMASK;
+ soff = r.min.x & (WBITS-1);
+ wwidth = ((pt.x+width-1)>>LWBITS) - (pt.x>>LWBITS);
+
+ if(sm == dm){
+#ifdef TEST
+ if(!FORCEBAKW &&
+ (FORCEFORW || sm != dm || saddr > daddr ||
+ (saddr == daddr && soff > doff)))
+ ;
+ else{
+ daddr += height * dspan;
+ saddr += height * sspan;
+ sspan -= 2 * W2L * sm->width;
+ dspan -= 2 * W2L * dm->width;
+ }
+#else
+ if(r.min.y < pt.y){ /* bottom to top */
+ daddr += height * dspan;
+ saddr += height * sspan;
+ sspan -= 2 * W2L * sm->width;
+ dspan -= 2 * W2L * dm->width;
+ }else if(r.min.y == pt.y && r.min.x < pt.x)
+ abort()/*goto right*/;
+#endif
+ }
+ if(wwidth == 0) /* collapse masks for narrow cases */
+ lmask &= rmask;
+ fcode &= F;
+
+ deltadep = ddep - sdep;
+ sdest = doff >> deltadep;
+ delta = soff - sdest;
+ sign = 0;
+ if(delta < 0){
+ sign = 1;
+ delta = -delta;
+ }
+
+ p = 0;
+ for(j = 0; j <= height; j++){
+ d = daddr;
+ s = saddr;
+ mask = lmask;
+ tmp = 0;
+ if(!sign)
+ tmp = *s++;
+ spare = 0;
+ for(i = wwidth; i >= 0; i--){
+ if(spare)
+ sw = *p++;
+ else{
+ if(sign){
+ sw = tmp << (WBITS-delta);
+ tmp = *s++;
+ sw |= tmp >> delta;
+ }else{
+ sw = tmp << delta;
+ tmp = *s++;
+ if(delta)
+ sw |= tmp >> (WBITS-delta);
+ }
+ spare = 1 << deltadep;
+ if(deltadep >= 1){
+ gbitexplode(sw, buf, sdep, deltadep);
+ p = buf;
+ sw = *p++;
+ }
+ }
+
+ dw = *d;
+ switch(fcode){ /* ltor bit aligned */
+ case Zero: *d = dw & ~mask; break;
+ case DnorS: *d = dw ^ ((~sw | dw) & mask); break;
+ case DandnotS: *d = dw ^ ((sw & dw) & mask); break;
+ case notS: *d = dw ^ ((~sw ^ dw) & mask); break;
+ case notDandS: *d = dw ^ ((sw | dw) & mask); break;
+ case notD: *d = dw ^ mask; break;
+ case DxorS: *d = dw ^ (sw & mask); break;
+ case DnandS: *d = dw ^ ((sw | ~dw) & mask); break;
+ case DandS: *d = dw ^ ((~sw & dw) & mask); break;
+ case DxnorS: *d = dw ^ (~sw & mask); break;
+ case D: break;
+ case DornotS: *d = dw | (~sw & mask); break;
+ case S: *d = dw ^ ((sw ^ dw) & mask); break;
+ case notDorS: *d = dw ^ (~(sw & dw) & mask); break;
+ case DorS: *d = dw | (sw & mask); break;
+ case F: *d = dw | mask; break;
+ }
+ d++;
+
+ mask = WMASK;
+ if(i == 1)
+ mask = rmask;
+ spare--;
+ }
+ saddr += sspan;
+ daddr += dspan;
+ }
+}
+
+#ifdef TEST
+void prprog(void);
+GBitmap *bb1, *bb2;
+ulong *src, *dst, *xdst, *xans;
+int swds, dwds;
+long ticks;
+int timeit;
+
+long
+func(int f, long s, int sld, long d, int dld)
+{
+ long a;
+ int sh, i, db, sb;
+
+ db = 1 << dld;
+ sb = 1 << sld;
+ sh = db - sb;
+ if(sh > 0) {
+ a = s;
+ for(i = sb; i<db; i += sb){
+ a <<= sb;
+ s |= a;
+ }
+ } else if(sh < 0)
+ s >>= -sh;
+
+ switch(f){
+ case Zero: d = 0; break;
+ case DnorS: d = ~(d|s); break;
+ case DandnotS: d = d & ~s; break;
+ case notS: d = ~s; break;
+ case notDandS: d = ~d & s; break;
+ case notD: d = ~d; break;
+ case DxorS: d = d ^ s; break;
+ case DnandS: d = ~(d&s); break;
+ case DandS: d = d & s; break;
+ case DxnorS: d = ~(d^s); break;
+ case S: d = s; break;
+ case DornotS: d = d | ~s; break;
+ case D: d = d; break;
+ case notDorS: d = ~d | s; break;
+ case DorS: d = d | s; break;
+ case F: d = ~0; break;
+ }
+
+ d &= ((1<<db)-1);
+ return d;
+}
+
+void
+run(int fr, int to, int w, int op)
+{
+ int i, j, f, t, fy, ty;
+ extern long *_clock;
+
+ fr += bb2->r.min.x;
+ to += bb1->r.min.x;
+ fy = bb2->r.min.y + 1;
+ ty = bb1->r.min.y + 1;
+ if(timeit) {
+ memcpy(dst, xdst, dwds * sizeof(long));
+ ticks -= *_clock;
+ gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
+ ticks += *_clock;
+ return;
+ }
+ f = fr;
+ t = to;
+ memcpy(dst, xdst, dwds * sizeof(long));
+ for(i=0; i<w; i++) {
+ gbitblt(bb1, Pt(t,ty), bb2, Rect(f,fy,f+1,fy+1), op);
+ gbitblt(bb1, Pt(t,ty+1), bb2, Rect(f,fy+1,f+1,fy+2), op);
+ f++;
+ t++;
+ }
+ memcpy(xans, dst, dwds * sizeof(long));
+
+ memcpy(dst, xdst, dwds * sizeof(long));
+ gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
+
+ if(memcmp(xans, dst, dwds * sizeof(long))) {
+ /*
+ * print src and dst row offset, width in bits, and forw/back
+ * then print for each of the four rows: the source (s),
+ * the dest (d), the good value of the answer (g),
+ * and the actual bad value of the answer (b)
+ */
+ print("fr=%d to=%d w=%d fb=%d%d\n",
+ fr, to, w, FORCEFORW, FORCEBAKW);
+ print("dst bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
+ bb1->base, bb1->zero, bb1->width, bb1->ldepth,
+ bb1->r.min.x, bb1->r.min.y, bb1->r.max.x, bb1->r.max.y);
+ print("src bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
+ bb2->base, bb2->zero, bb2->width, bb2->ldepth,
+ bb2->r.min.x, bb2->r.min.y, bb2->r.max.x, bb2->r.max.y);
+ for(j=0; 7*j < dwds; j++) {
+ print("\ns");
+ for(i=0; i<7 && 7*j+i < dwds; i++)
+ print(" %.8lux", src[7*j + i]);
+ print("\nd");
+ for(i=0; i<7 && 7*j+i < dwds; i++)
+ print(" %.8lux", xdst[7*j + i]);
+ print("\ng");
+ for(i=0; i<7 && 7*j+i < dwds; i++)
+ print(" %.8lux", xans[7*j + i]);
+ print("\nb");
+ for(i=0; i<7 && 7*j+i < dwds; i++)
+ print(" %.8lux", dst[7*j + i]);
+ print("\n");
+ }
+ prprog();
+ }
+}
+
+void
+prprog(void)
+{
+ exits(0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int f, t, w, i, sld, dld, op, iters, simple;
+ ulong s, d, spix, dpix, apix, fpix, m, *ps, *pd;
+ Point sorg, dorg;
+ GBitmap *bs, *bd;
+ long seed;
+ char *ct;
+
+ sld = 0;
+ dld = 0;
+ timeit = 0;
+ iters = 200;
+ simple = 0;
+ ARGBEGIN {
+ case 'i':
+ iters = atoi(ARGF());
+ break;
+ case 's':
+ simple = 1;
+ break;
+ case 't':
+ timeit = 1;
+ ct = ARGF();
+ if(ct)
+ iters = atoi(ct);
+ break;
+ } ARGEND
+ if(argc > 0)
+ sld = atoi(argv[0]);
+ if(argc > 1)
+ dld = atoi(argv[1]);
+ if(!timeit && !simple) {
+ seed = time(0);
+ print("seed %lux\n", seed); srand(seed); /**/
+ }
+
+ print("sld %d dld %d\n", sld, dld);
+ op = 1;
+
+ /* bitmaps for 1-bit tests */
+ bd = gballoc(Rect(0,0,32,1), dld);
+ bs = gballoc(Rect(0,0,32,1), sld);
+ for(i=0; i<bs->width; i++)
+ bs->base[i] = lrand();
+
+ /* bitmaps for rect tests */
+ if(simple) {
+ dorg = Pt(0,0);
+ sorg = Pt(0,0);
+ } else {
+ dorg = Pt(nrand(63)-31,nrand(63)-31);
+ sorg = Pt(nrand(63)-31,nrand(63)-31);
+ }
+ bb1 = gballoc(Rpt(dorg,add(dorg,Pt(200,4))), dld);
+ bb2 = gballoc(Rpt(sorg,add(sorg,Pt(200,4))), sld);
+ dwds = bb1->width * Dy(bb1->r);
+ swds = bb2->width * Dy(bb2->r);
+ dst = bb1->base;
+ src = bb2->base;
+ xdst = malloc(dwds * sizeof(long));
+ xans = malloc(dwds * sizeof(long));
+ for(i=0; i<swds; i++)
+ src[i] = lrand();
+ for(i=0; i<dwds; i++)
+ xdst[i] = lrand();
+
+loop:
+ print("Op %d\n", op);
+ if(!timeit) {
+ print("one pixel\n");
+ ps = bs->base;
+ pd = bd->base;
+ FORCEFORW = 1;
+ FORCEBAKW = 0;
+ for(i=0; i<1000; i++, FORCEFORW = !FORCEFORW, FORCEBAKW = !FORCEBAKW) {
+ f = nrand(32 >> sld);
+ t = nrand(32 >> dld);
+ s = lrand();
+ d = lrand();
+ ps[0] = s;
+ pd[0] = d;
+#ifdef T386
+ spix = (byterev(s) >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
+ dpix = (byterev(d) >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
+#else
+ spix = (s >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
+ dpix = (d >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
+#endif
+#ifdef T386
+ apix = byterev(func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld)));
+#else
+ apix = func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld));
+#endif
+ gbitblt(bd, Pt(t,0), bs, Rect(f,0,f+1,1), op);
+ if(ps[0] != s) {
+ print("bb src %.8lux %.8lux %d %d\n", ps[0], s, f, t);
+ exits("error");
+ }
+ m = ((1 << (1<<dld)) - 1) << (32 - ((t+1)<<dld));
+#ifdef T386
+ m = byterev(m);
+#endif
+ if((pd[0] & ~m) != (d & ~m)) {
+ print("bb dst1 %.8lux %.8lux\n",
+ s, d);
+ print("bb %.8lux %.8lux %d %d\n",
+ ps[0], pd[0], f, t);
+ prprog();
+ exits("error");
+ }
+ if((pd[0] & m) != apix) {
+ spix <<= 32 - ((f+1)<<sld);
+ dpix <<= 32 - ((t+1)<<dld);
+#ifdef T386
+ spix = byterev(spix);
+ dpix = byterev(dpix);
+#endif
+ print("bb dst2 %.8lux %.8lux\n",
+ s, d);
+ print("bb %.8lux %.8lux %d %d\n",
+ ps[0], pd[0], f, t);
+ print("bb %.8lux %.8lux %.8lux %.8lux\n",
+ spix, dpix, apix, pd[0] & m);
+ prprog();
+ exits("error");
+ }
+ }
+ }
+
+ print("for\n");
+ FORCEFORW = 1;
+ FORCEBAKW = 0;
+
+ for(i=0; i<iters; i++) {
+ f = nrand(64);
+ t = nrand(64);
+ w = nrand(130);
+ run(f, t, w, op);
+ }
+
+ if(sld == dld) {
+ print("bak\n");
+ FORCEFORW = 0;
+ FORCEBAKW = 1;
+
+ for(i=0; i<iters; i++) {
+ f = nrand(64);
+ t = nrand(64);
+ w = nrand(130);
+ run(f, t, w, op);
+ }
+ }
+
+ if(op < F) {
+ op++;
+ goto loop;
+ }
+ if(timeit)
+ print("time: %d ticks\n", ticks);
+ exits(0);
+}
+
+
+#endif
--- /dev/null
+++ b/os/boot.original/mpc/flash.c
@@ -1,0 +1,212 @@
+#include "boot.h"
+
+typedef struct Flashdev Flashdev;
+struct Flashdev {
+ uchar* base;
+ int size;
+ uchar* exec;
+ char* config;
+ int conflen;
+};
+
+enum {
+ FLASHSEG = 256*1024,
+ CONFIGLIM = FLASHSEG,
+ BOOTOFF = FLASHSEG,
+ BOOTLEN = 3*FLASHSEG, /* third segment might be filsys */
+ /* rest of flash is free */
+};
+
+static Flashdev flash;
+
+/*
+ * configuration data is written between the bootstrap and
+ * the end of region 0. the region ends with allocation descriptors
+ * of the following form:
+ *
+ * byte order is big endian
+ *
+ * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
+ */
+typedef struct Flalloc Flalloc;
+struct Flalloc {
+ ulong check; /* checksum of data, or ~0 */
+ ulong base; /* base of region; ~0 if unallocated, 0 if deleted */
+ uchar len[3];
+ uchar tag; /* see below */
+ uchar sig[4];
+};
+
+enum {
+ /* tags */
+ Tdead= 0,
+ Tboot= 0x01, /* space reserved for boot */
+ Tconf= 0x02, /* configuration data */
+ Tnone= 0xFF,
+
+ Noval= ~0,
+};
+
+static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
+static char conftag[] = "#plan9.ini\n";
+
+static ulong
+checksum(uchar* p, int n)
+{
+ ulong s;
+
+ for(s=0; --n >= 0;)
+ s += *p++;
+ return s;
+}
+
+static int
+validptr(Flalloc *ap, uchar *p)
+{
+ return p > (uchar*)&end && p < (uchar*)ap;
+}
+
+static int
+flashcheck(Flalloc *ap, char **val, int *len)
+{
+ uchar *base;
+ int n;
+
+ if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
+ return 0;
+ base = flash.base+ap->base;
+ if(!validptr(ap, base))
+ return 0;
+ n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
+ if(n == 0xFFFFFF)
+ n = 0;
+ if(n < 0)
+ return 0;
+ if(n > 0 && !validptr(ap, base+n-1))
+ return 0;
+ if(ap->check != Noval && checksum(base, n) != ap->check){
+ print("flash: bad checksum\n");
+ return 0;
+ }
+ *val = (char*)base;
+ *len = n;
+ return 1;
+}
+
+int
+flashinit(void)
+{
+ int len;
+ char *val;
+ Flalloc *ap;
+ void *addr;
+ long mbytes;
+ char type[20];
+
+ flash.base = 0;
+ flash.exec = 0;
+ flash.size = 0;
+ if(archflashreset(type, &addr, &mbytes) < 0){
+ print("flash: flash not present or not enabled\n"); /* shouldn't happen */
+ return 0;
+ }
+ flash.size = mbytes;
+ flash.base = addr;
+ flash.exec = flash.base + BOOTOFF;
+ flash.config = nil;
+ flash.conflen = 0;
+
+ for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
+ if(0)
+ print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
+ if(ap->tag == Tconf &&
+ flashcheck(ap, &val, &len) &&
+ len >= sizeof(conftag)-1 &&
+ memcmp(val, conftag, sizeof(conftag)-1) == 0){
+ flash.config = val;
+ flash.conflen = len;
+ if(0)
+ print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
+ }
+ }
+ if(flash.config == nil)
+ print("flash: no config\n");
+ else
+ print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
+ if(issqueezed(flash.exec) == Q_MAGIC){
+ print("flash: squeezed powerpc kernel installed\n");
+ return 1<<0;
+ }
+ if(GLLONG(flash.exec) == Q_MAGIC){
+ print("flash: unsqueezed powerpc kernel installed\n");
+ return 1<<0;
+ }
+ flash.exec = 0;
+ print("flash: no powerpc kernel in Flash\n");
+ return 0;
+}
+
+char*
+flashconfig(int)
+{
+ return flash.config;
+}
+
+int
+flashbootable(int)
+{
+ return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == Q_MAGIC);
+}
+
+int
+flashboot(int)
+{
+ ulong entry, addr;
+ void (*b)(void);
+ Exec *ep;
+ Block in;
+ long n;
+ uchar *p;
+
+ if(flash.exec == 0)
+ return -1;
+ p = flash.exec;
+ if(GLLONG(p) == Q_MAGIC){
+ /* unsqueezed: copy data and perhaps text, then jump to it */
+ ep = (Exec*)p;
+ entry = PADDR(GLLONG(ep->entry));
+ p += sizeof(Exec);
+ addr = entry;
+ n = GLLONG(ep->text);
+ if(addr != (ulong)p){
+ memmove((void*)addr, p, n);
+ print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
+ }
+ p += n;
+ if(entry >= FLASHMEM)
+ addr = 3*BY2PG; /* kernel text is in Flash, data in RAM */
+ else
+ addr = PGROUND(addr+n);
+ n = GLLONG(ep->data);
+ memmove((void*)addr, p, n);
+ print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
+ }else{
+ in.data = p;
+ in.rp = in.data;
+ in.lim = p+BOOTLEN;
+ in.wp = in.lim;
+ n = unsqueezef(&in, &entry);
+ if(n < 0)
+ return -1;
+ }
+ print("entry=0x%lux\n", entry);
+ uartwait();
+ scc2stop();
+ /*
+ * Go to new code. It's up to the program to get its PC relocated to
+ * the right place.
+ */
+ b = (void (*)(void))KADDR(PADDR(entry));
+ (*b)();
+ return -1;
+}
--- /dev/null
+++ b/os/boot.original/mpc/fns.h
@@ -1,0 +1,117 @@
+Alarm* alarm(int, void (*)(Alarm*), void*);
+void alarminit(void);
+void archbacklight(int);
+char* archconfig(void);
+void archdisableuart(int);
+void archenableuart(int, int);
+void archenableusb(int);
+void archetherdisable(int);
+int archetherenable(int, int*, int*);
+int archflashreset(char*, void**, long*);
+void archinit(void);
+int archoptionsw(void);
+int bootp(int, char*);
+void cancel(Alarm*);
+void checkalarms(void);
+void clockinit(void);
+void clockintr(Ureg*, void*);
+void consinit(void);
+void cpminit(void);
+void cpuidprint(void);
+#define dcflush(a,b)
+void delay(int);
+void eieio(void);
+uchar* etheraddr(int);
+int etherinit(void);
+int etherrxpkt(int, Etherpkt*, int);
+int ethertxpkt(int, Etherpkt*, int, int);
+void exception(void);
+int flashboot(int);
+int flashbootable(int);
+char* flashconfig(int);
+int flashinit(void);
+void free(void*);
+void freeb(Block*);
+int getcfields(char*, char**, int, char*);
+char* getconf(char*);
+ulong getdec(void);
+ulong gethid0(void);
+ulong getimmr(void);
+ulong getmsr(void);
+ulong getpvr(void);
+int getstr(char*, char*, int, char*);
+ulong gettbl(void);
+ulong gettbu(void);
+int hardinit(void);
+long hardread(int, void*, long);
+long hardseek(int, long);
+long hardwrite(int, void*, long);
+long i2csend(int, void*, long);
+void i2csetup(void);
+void* ialloc(ulong, int);
+Block* iallocb(int);
+void idle(void);
+int isaconfig(char*, int, ISAConf*);
+int issqueezed(uchar*);
+void kbdchar(Queue*, int);
+void kbdinit(void);
+void kbdreset(void);
+void machinit(void);
+void* malloc(ulong);
+ulong mapalloc(RMap*, ulong, int, int);
+void mapfree(RMap*, ulong, int);
+void mapinit(RMap*, Map*, int);
+void meminit(void);
+void microdelay(int);
+void mmuinit(void);
+int optionsw(void);
+void panic(char*, ...);
+int parseether(uchar*, char*);
+int plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
+void putdec(ulong);
+void puthid0(ulong);
+void putmsr(ulong);
+int qbgetc(Queue*);
+void qbputc(Queue*, int);
+void qbwrite(Queue*, Block*);
+Block* qget(Queue*);
+long qlen(Queue*);
+Queue* qopen(int, int, void (*)(void*), void*);
+#define qpass qbwrite
+void scc2stop(void);
+void sccnmsi(int, int, int);
+void sched(void);
+void screeninit(void);
+void screenputs(char*, int);
+void sdraminit(ulong);
+Partition* sethardpart(int, char*);
+Partition* setscsipart(int, char*);
+void setvec(int, void (*)(Ureg*, void*), void*);
+int splhi(void);
+int spllo(void);
+void splx(int);
+void trapinit(void);
+void uartputs(char*, int);
+void uartsetboot(void (*f)(uchar*, int));
+void uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
+void uartwait(void);
+long unsqueezef(Block*, ulong*);
+
+#define GSHORT(p) (((p)[1]<<8)|(p)[0])
+#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))
+#define GLSHORT(p) (((p)[0]<<8)|(p)[1])
+#define GLLONG(p) ((GLSHORT(p)<<16)|GLSHORT(p+2))
+
+#define KADDR(a) ((void*)((ulong)(a)|KZERO))
+#define PADDR(a) ((ulong)(a)&~KSEGM)
+
+/* IBM bit field order */
+#define IBIT(b) ((ulong)1<<(31-(b)))
+#define SIBIT(n) ((ushort)1<<(15-(n)))
+
+#define IOREGS(x, T) ((T*)((char*)m->iomem+(x)))
+
+int uartinit(void);
+Partition* setuartpart(int, char*);
+long uartread(int, void*, long);
+long uartseek(int, long);
--- /dev/null
+++ b/os/boot.original/mpc/gbitbltclip.c
@@ -1,0 +1,52 @@
+#include <u.h>
+#include <libc.h>
+#include <libg.h>
+#include <gnot.h>
+
+void
+gbitbltclip(void *vp)
+{
+ int dx, dy;
+ int i;
+ struct{
+ GBitmap *dm;
+ Point p;
+ GBitmap *sm;
+ Rectangle r;
+ Fcode f;
+ }*bp;
+
+ bp = vp;
+ dx = Dx(bp->r);
+ dy = Dy(bp->r);
+ if(bp->p.x < bp->dm->clipr.min.x){
+ i = bp->dm->clipr.min.x-bp->p.x;
+ bp->r.min.x += i;
+ bp->p.x += i;
+ dx -= i;
+ }
+ if(bp->p.y < bp->dm->clipr.min.y){
+ i = bp->dm->clipr.min.y-bp->p.y;
+ bp->r.min.y += i;
+ bp->p.y += i;
+ dy -= i;
+ }
+ if(bp->p.x+dx > bp->dm->clipr.max.x)
+ bp->r.max.x -= bp->p.x+dx-bp->dm->clipr.max.x;
+ if(bp->p.y+dy > bp->dm->clipr.max.y)
+ bp->r.max.y -= bp->p.y+dy-bp->dm->clipr.max.y;
+ if(bp->r.min.x < bp->sm->clipr.min.x){
+ i = bp->sm->clipr.min.x-bp->r.min.x;
+ bp->p.x += i;
+ bp->r.min.x += i;
+ }
+ if(bp->r.min.y < bp->sm->clipr.min.y){
+ i = bp->sm->clipr.min.y-bp->r.min.y;
+ bp->p.y += i;
+ bp->r.min.y += i;
+ }
+ if(bp->r.max.x > bp->sm->clipr.max.x)
+ bp->r.max.x = bp->sm->clipr.max.x;
+ if(bp->r.max.y > bp->sm->clipr.max.y)
+ bp->r.max.y = bp->sm->clipr.max.y;
+}
--- /dev/null
+++ b/os/boot.original/mpc/gnot.h
@@ -1,0 +1,71 @@
+
+extern void *bbmalloc(int);
+extern void bbfree(void *, int);
+extern int bbonstack(void);
+extern void bbexec(void(*)(void), int, int);
+
+/*
+ * Graphics types
+ */
+
+typedef struct GBitmap GBitmap;
+typedef struct GFont GFont;
+typedef struct GSubfont GSubfont;
+typedef struct GCacheinfo GCacheinfo;
+
+struct GBitmap
+{
+ ulong *base; /* pointer to start of data */
+ long zero; /* base+zero=&word containing (0,0) */
+ ulong width; /* width in 32 bit words of total data area */
+ int ldepth; /* log base 2 of number of bits per pixel */
+ Rectangle r; /* rectangle in data area, local coords */
+ Rectangle clipr; /* clipping region */
+ GBitmap *cache; /* zero; distinguishes bitmap from layer */
+};
+
+
+/*
+ * GFont etc. are not used in the library, only in devbit.c.
+ * GSubfont is only barely used.
+ */
+struct GSubfont
+{
+ short n; /* number of chars in font */
+ char height; /* height of bitmap */
+ char ascent; /* top of bitmap to baseline */
+ Fontchar *info; /* n+1 character descriptors */
+ GBitmap *bits; /* where the characters are */
+};
+struct GCacheinfo
+{
+ ulong xright; /* right edge of bits */
+ Fontchar;
+};
+
+struct GFont
+{
+ uchar height; /* max height of bitmap, interline spacing */
+ char ascent; /* top of bitmap to baseline */
+ char width; /* widest so far; used in caching only */
+ char ldepth; /* of images */
+ short id; /* of font */
+ int ncache; /* number of entries in cache */
+ GCacheinfo *cache; /* cached characters */
+ GBitmap *b; /* cached images */
+};
+
+extern ulong *gaddr(GBitmap*, Point);
+extern uchar *gbaddr(GBitmap*, Point);
+extern void gbitblt(GBitmap*, Point, GBitmap*, Rectangle, Fcode);
+extern void gbitbltclip(void*);
+extern void gtexture(GBitmap*, Rectangle, GBitmap*, Fcode);
+extern Point gsubfstrsize(GSubfont*, char*);
+extern int gsubfstrwidth(GSubfont*, char*);
+extern Point gsubfstring(GBitmap*, Point, GSubfont*, char*, Fcode);
+extern Point gbitbltstring(GBitmap*, Point, GSubfont*, char*, Fcode);
+extern void gsegment(GBitmap*, Point, Point, int, Fcode);
+extern void gpoint(GBitmap*, Point, int, Fcode);
+extern void gflushcpucache(void);
+extern GBitmap* gballoc(Rectangle, int);
+extern void gbfree(GBitmap*);
--- /dev/null
+++ b/os/boot.original/mpc/i2c.c
@@ -1,0 +1,351 @@
+#include "boot.h"
+
+/*
+ * basic read/write interface to mpc8xx I2C bus (master mode)
+ */
+
+typedef struct I2C I2C;
+
+struct I2C {
+ uchar i2mod;
+ uchar rsv12a[3];
+ uchar i2add;
+ uchar rsv12b[3];
+ uchar i2brg;
+ uchar rsv12c[3];
+ uchar i2com;
+ uchar rsv12d[3];
+ uchar i2cer;
+ uchar rsv12e[3];
+ uchar i2cmr;
+};
+
+enum {
+ /* i2c-specific BD flags */
+ RxeOV= 1<<1, /* overrun */
+ TxS= 1<<10, /* transmit start condition */
+ TxeNAK= 1<<2, /* last transmitted byte not acknowledged */
+ TxeUN= 1<<1, /* underflow */
+ TxeCL= 1<<0, /* collision */
+ TxERR= (TxeNAK|TxeUN|TxeCL),
+
+ /* i2cmod */
+ REVD= 1<<5, /* =1, LSB first */
+ GCD= 1<<4, /* =1, general call address disabled */
+ FLT= 1<<3, /* =0, not filtered; =1, filtered */
+ PDIV= 3<<1, /* predivisor field */
+ EN= 1<<0, /* enable */
+
+ /* i2com */
+ STR= 1<<7, /* start transmit */
+ I2CM= 1<<0, /* master */
+ I2CS= 0<<0, /* slave */
+
+ /* i2cer */
+ TXE = 1<<4,
+ BSY = 1<<2,
+ TXB = 1<<1,
+ RXB = 1<<0,
+
+ /* port B bits */
+ I2CSDA = IBIT(27),
+ I2CSCL = IBIT(26),
+
+ Rbit = 1<<0, /* bit in address byte denoting read */
+
+ /* maximum I2C I/O (can change) */
+ Bufsize = 64,
+ Tbuflen= Bufsize+4, /* extra address bytes and alignment */
+ Freq = 100000,
+ I2CTimeout = 250, /* msec */
+};
+
+/* data cache needn't be flushed if buffers allocated in uncached INTMEM */
+#define DCFLUSH(a,n)
+
+/*
+ * I2C software structures
+ */
+
+struct Ctlr {
+ Lock;
+ QLock io;
+ int init;
+ I2C* i2c;
+ IOCparam* sp;
+
+ BD* rd;
+ BD* td;
+ int phase;
+ char* addr;
+ char* txbuf;
+ char* rxbuf;
+};
+typedef struct Ctlr Ctlr;
+
+static Ctlr i2ctlr[1];
+extern int predawn;
+
+static void interrupt(Ureg*, void*);
+
+static void
+enable(void)
+{
+ I2C *i2c;
+
+ i2c = i2ctlr->i2c;
+ i2c->i2cer = ~0; /* clear events */
+ eieio();
+ i2c->i2mod |= EN;
+ eieio();
+ i2c->i2cmr = TXE|BSY|TXB|RXB; /* enable all interrupts */
+ eieio();
+}
+
+static void
+disable(void)
+{
+ I2C *i2c;
+
+ i2c = i2ctlr->i2c;
+ i2c->i2cmr = 0; /* mask all interrupts */
+ i2c->i2mod &= ~EN;
+}
+
+/*
+ * called by the reset routine of any driver using the I2C
+ */
+void
+i2csetup(void)
+{
+ IMM *io;
+ I2C *i2c;
+ IOCparam *sp;
+ Ctlr *ctlr;
+ long f, e, emin;
+ int p, d, dmax;
+
+ ctlr = i2ctlr;
+ if(ctlr->init)
+ return;
+ print("i2c setup...\n");
+ ctlr->init = 1;
+ i2c = KADDR(INTMEM+0x860);
+ ctlr->i2c = i2c;
+ sp = KADDR(INTMEM+0x3c80);
+ ctlr->sp = sp;
+ disable();
+
+ if(ctlr->txbuf == nil){
+ ctlr->txbuf = ialloc(Tbuflen, 2);
+ ctlr->addr = ctlr->txbuf+Bufsize;
+ }
+ if(ctlr->rxbuf == nil)
+ ctlr->rxbuf = ialloc(Bufsize, 2);
+ if(ctlr->rd == nil){
+ ctlr->rd = bdalloc(1);
+ ctlr->rd->addr = PADDR(ctlr->rxbuf);
+ ctlr->rd->length = 0;
+ ctlr->rd->status = BDWrap;
+ }
+ if(ctlr->td == nil){
+ ctlr->td = bdalloc(2);
+ ctlr->td->addr = PADDR(ctlr->txbuf);
+ ctlr->td->length = 0;
+ ctlr->td->status = BDWrap|BDLast;
+ }
+
+ /* select port pins */
+ io = ioplock();
+ io->pbdir |= I2CSDA | I2CSCL;
+ io->pbodr |= I2CSDA | I2CSCL;
+ io->pbpar |= I2CSDA | I2CSCL;
+ iopunlock();
+
+ /* explicitly initialise parameters, because InitRxTx can't be used (see i2c/spi relocation errata) */
+ sp = ctlr->sp;
+ sp->rbase = PADDR(ctlr->rd);
+ sp->tbase = PADDR(ctlr->td);
+ sp->rfcr = 0x18;
+ sp->tfcr = 0x18;
+ sp->mrblr = Bufsize;
+ sp->rstate = 0;
+ sp->rptr = 0;
+ sp->rbptr = sp->rbase;
+ sp->rcnt = 0;
+ sp->tstate = 0;
+ sp->tbptr = sp->tbase;
+ sp->tptr = 0;
+ sp->tcnt = 0;
+ eieio();
+
+ i2c->i2com = I2CM;
+ i2c->i2mod = 0; /* normal mode */
+ i2c->i2add = 0;
+
+ emin = Freq;
+ dmax = (m->cpuhz/Freq)/2-3;
+ for(d=0; d < dmax; d++){
+ for(p=3; p>=0; p--){
+ f = (m->cpuhz>>(p+2))/(2*(d+3));
+ e = Freq - f;
+ if(e < 0)
+ e = -e;
+ if(e < emin){
+ emin = e;
+ i2c->i2brg = d;
+ i2c->i2mod = (i2c->i2mod&~PDIV)|((3-p)<<1); /* set PDIV */
+ }
+ }
+ }
+ //print("i2brg=%d i2mod=#%2.2ux\n", i2c->i2brg, i2c->i2mod);
+ setvec(VectorCPIC+0x10, interrupt, i2ctlr);
+}
+
+enum {
+ Idling,
+ Done,
+ Busy,
+ Sending,
+ Recving,
+};
+
+static void
+interrupt(Ureg*, void *arg)
+{
+ int events;
+ Ctlr *ctlr;
+ I2C *i2c;
+
+ ctlr = arg;
+ i2c = ctlr->i2c;
+ events = i2c->i2cer;
+ eieio();
+ i2c->i2cer = events;
+ if(events & (BSY|TXE)){
+ //print("I2C#%x\n", events);
+ if(ctlr->phase != Idling){
+ ctlr->phase = Idling;
+ }
+ }else{
+ if(events & TXB){
+ //print("i2c: xmt %d %4.4ux %4.4ux\n", ctlr->phase, ctlr->td->status, ctlr->td[1].status);
+ if(ctlr->phase == Sending){
+ ctlr->phase = Done;
+ }
+ }
+ if(events & RXB){
+ //print("i2c: rcv %d %4.4ux %d\n", ctlr->phase, ctlr->rd->status, ctlr->rd->length);
+ if(ctlr->phase == Recving){
+ ctlr->phase = Done;
+ }
+ }
+ }
+}
+
+static int
+done(void *a)
+{
+ return ((Ctlr*)a)->phase < Busy;
+}
+
+static void
+i2cwait(Ctlr *ctlr)
+{
+ /* TO DO: timeout */
+ while(!done(ctlr)){
+ if(predawn)
+ interrupt(nil, ctlr);
+ }
+}
+
+long
+i2csend(int addr, void *buf, long n)
+{
+ Ctlr *ctlr;
+ int i, p, s;
+
+ ctlr = i2ctlr;
+ if(n > Bufsize)
+ return -1;
+ i = 1;
+ ctlr->txbuf[0] = addr & ~1;
+ if(addr & 1){
+ ctlr->txbuf[1] = addr>>8;
+ i++;
+ }
+ memmove(ctlr->txbuf+i, buf, n);
+ DCFLUSH(ctlr->txbuf, Tbuflen);
+ ctlr->phase = Sending;
+ ctlr->rd->status = BDEmpty|BDWrap|BDInt;
+ ctlr->td->addr = PADDR(ctlr->txbuf);
+ ctlr->td->length = n+i;
+ ctlr->td->status = BDReady|BDWrap|BDLast|BDInt;
+ enable();
+ ctlr->i2c->i2com = STR|I2CM;
+ eieio();
+ i2cwait(ctlr);
+ disable();
+ p = ctlr->phase;
+ s = ctlr->td->status;
+ if(s & BDReady || s & TxERR || p != Done)
+ return -1;
+ return n;
+}
+
+long
+i2crecv(int addr, void *buf, long n)
+{
+ Ctlr *ctlr;
+ int p, s, flag;
+ BD *td;
+ long nr;
+
+ ctlr = i2ctlr;
+ if(n > Bufsize)
+ return -1;
+ ctlr->txbuf[0] = addr|Rbit;
+ if(addr & 1){ /* special select sequence */
+ ctlr->addr[0] = addr &~ 1;
+ ctlr->addr[1] = addr>>8;
+ }
+ DCFLUSH(ctlr->txbuf, Tbuflen);
+ DCFLUSH(ctlr->rxbuf, Bufsize);
+ ctlr->phase = Recving;
+ ctlr->rd->addr = PADDR(ctlr->rxbuf);
+ ctlr->rd->status = BDEmpty|BDWrap|BDInt;
+ flag = 0;
+ td = ctlr->td;
+ td[1].status = 0;
+ if(addr & 1){
+ /* special select sequence */
+ td->addr = PADDR(ctlr->addr);
+ td->length = 2;
+ /* td->status made BDReady below */
+ td++;
+ flag = TxS;
+ }
+ td->addr = PADDR(ctlr->txbuf);
+ td->length = n+1;
+ td->status = BDReady|BDWrap|BDLast | flag; /* not BDInt: leave that to receive */
+ if(flag)
+ ctlr->td->status = BDReady;
+ enable();
+ ctlr->i2c->i2com = STR|I2CM;
+ eieio();
+ i2cwait(ctlr);
+ disable();
+ p = ctlr->phase;
+ s = ctlr->td->status;
+ if(flag)
+ s |= ctlr->td[1].status;
+ nr = ctlr->rd->length;
+ if(nr > n)
+ nr = n; /* shouldn't happen */
+ if(s & TxERR || s & BDReady || ctlr->rd->status & BDEmpty)
+ return -1;
+ if(p != Done)
+ return -1;
+ memmove(buf, ctlr->rxbuf, nr);
+ return nr;
+}
--- /dev/null
+++ b/os/boot.original/mpc/initfads.c
@@ -1,0 +1,187 @@
+/*
+ * Called from l.s in EPROM to set up a minimal working environment.
+ * Since there is no DRAM yet, and therefore no stack, no function
+ * calls may be made from sysinit0, and values can't be stored,
+ * except to INTMEM. Global values are accessed by offset from SB,
+ * which has been set by l.s to point into EPROM.
+ *
+ * This is FADS-specific in CS assignment and access of the FADS BCSR
+ * to discover memory size and speed.
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "archfads.h"
+
+#define MB (1024*1024)
+
+enum {
+ UPMSIZE = 64, /* memory controller instruction RAM */
+ SPEED = 50, /* maximum memory clock in MHz */
+ SDRAMSIZE = 4*MB,
+
+ /* mcr */
+ WriteRAM = 0<<30,
+ ReadRAM = 1<<30,
+ ExecRAM = 2<<30,
+
+ SelUPMA = 0<<23,
+ SelUPMB = 1<<23,
+
+ Once = 1<<8,
+};
+
+/*
+ * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
+ */
+static ulong upma50[UPMSIZE] = {
+ 0x8FFFEC24, 0xFFFEC04, 0xCFFEC04, 0xFFEC04,
+ 0xFFEC00, 0x37FFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x8FFFEC24, 0xFFFEC04, 0x8FFEC04, 0xFFEC0C,
+ 0x3FFEC00, 0xFFEC44, 0xFFCC08, 0xCFFCC44,
+ 0xFFEC0C, 0x3FFEC00, 0xFFEC44, 0xFFCC00,
+ 0x3FFFC847, 0x3FFFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x11BFCC47,
+ 0xC0FFCC84, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x3AFCC4C,
+ 0xCAFCC00, 0x3AFCC4C, 0xCAFCC00, 0x3AFCC4C,
+ 0xCAFCC00, 0x33BFCC4F, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xC0FFCC84, 0xFFCC04, 0x7FFCC04, 0x3FFFCC06,
+ 0xFFFFCC85, 0xFFFFCC05, 0xFFFFCC05, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x33FFCC07, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+};
+
+/*
+ * the FADS manual table 3-7 suggests the following for 60ns EDO DRAMs at 20MHz
+ */
+static ulong upma20[UPMSIZE] = {
+ 0x8FFFCC04, 0x08FFCC00, 0x33FFCC47, ~0, ~0, ~0, ~0, ~0,
+ [0x08] 0x8FFFCC04, 0x08FFCC08, 0x08FFCC08, 0x08FFCC08, 0x08FFCC00, 0x3FFFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x18] 0x8FEFCC00, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x20] 0x8FEFCC00, 0x09AFCC48, 0x09AFCC48, 0x08AFCC48, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x30] 0x80FFCC84, 0x17FFCC04, 0xFFFFCC86, 0xFFFFCC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x3C] 0x33FFCC07, ~0, ~0, ~0,
+};
+
+void
+sysinit0(int inrom)
+{
+ ulong *upm, *bcsr;
+ IMM *io;
+ int i, mb;
+
+ io = (IMM*)INTMEM; /* running before maps, no KADDR */
+
+ /* system interface unit initialisation, FADS manual table 3-2, except as noted */
+ io->siumcr = 0x01012440;
+ io->sypcr = 0xFFFFFF88;
+ io->tbscrk = KEEP_ALIVE_KEY;
+ io->tbscr = 0xC3; /* time base enabled */
+ io->rtcsck = KEEP_ALIVE_KEY;
+ io->rtcsc = 0xC1; /* don't FRZ, real-time clock enabled */
+ io->rtcsck = ~KEEP_ALIVE_KEY;
+ io->piscrk = KEEP_ALIVE_KEY;
+ io->piscr = 0x82;
+
+ io->memc[BCSRCS].option = 0xFFFF8110; /* 32k block, all types access, CS early negate, 1 ws */
+ io->memc[BCSRCS].base = BCSRMEM | 1; /* base, 32-bit port, no parity, GPCM */
+
+ io->memc[BOOTCS].base = FLASHMEM | 1;
+ io->memc[BOOTCS].option = 0xFF800D54;
+
+ if(!inrom)
+ return; /* can't initialise DRAM controller from DRAM */
+
+ bcsr = (ulong*)BCSRMEM;
+// bcsr[1] &= ~DisableDRAM;
+ /* could check DRAM speed here; assume 60ns */
+ switch((bcsr[2]>>23)&3){
+ default: return; /* can't happen; for the compiler */
+ case 0: mb = 4; break;
+ case 1: mb = 32; break;
+ case 2: mb = 16; break;
+ case 3: mb = 8; break;
+ }
+
+ upm = upma50;
+ for(i=0; i<UPMSIZE; i++){
+ io->mdr = upm[i];
+ io->mcr = WriteRAM | SelUPMA | i;
+ }
+ io->mptpr = 0x0400;
+ if(SPEED >= 32)
+ io->mamr = (0x9C<<24) | 0xA21114; /* 50MHz BRGCLK; FADS manual says 0xC0, mpc8bug sets 0x9C */
+ else if(SPEED >= 20)
+ io->mamr = (0x60<<24) | 0xA21114; /* 25MHz BRGCLK */
+ else
+ io->mamr = (0x40<<24) | 0xA21114; /* 16.67MHz BRGCLK */
+ io->memc[DRAM1].option = ~((mb<<20)-1)|0x0800; /* address mask, SAM=1 */
+ io->memc[DRAM1].base = 0 | 0x81; /* base at 0, 32-bit port size, no parity, UPMA */
+}
+
+/*
+ * the FADS manual table 3-9's suggestion for MB811171622A-100 32+MHz-50MHz
+ */
+static ulong upmb50[UPMSIZE] = {
+ [0x00] 0x1F07FC04, 0xEEAEFC04, 0x11ADFC04, 0xEFBBBC00, 0x1FF77C47,
+ [0x05] 0x1FF77C34, 0xEFEABC34, 0x1FB57C35,
+ [0x08] 0x1F07FC04, 0xEEAEFC04, 0x10ADFC04, 0xF0AFFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x18] 0x1F27FC04, 0xEEAEBC00, 0x01B93C04, 0x1FF77C47, ~0, ~0, ~0, ~0,
+ [0x20] 0x1F07FC04, 0xEEAEBC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x30] 0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC07, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x3C] 0x7FFFFC07, ~0, ~0, ~0,
+};
+
+/*
+ * the FADS manual table 3-8's suggestion for MB811171622A-100 up to 32MHz
+ */
+static ulong upmb32[UPMSIZE] = {
+ [0x00] 0x126CC04, 0xFB98C00, 0x1FF74C45, ~0, ~0,
+ [0x05] 0x1FE77C34, 0xEFAABC34, 0x1FA57C35,
+ [0x08] 0x0026FC04, 0x10ADFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x18] 0x0E26BC04, 0x01B93C00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0,
+ [0x20] 0x0E26BC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x30] 0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x3C] 0x7FFFFC07, ~0, ~0, ~0,
+};
+
+/*
+ * optionally called by archfads.c:/^archinit to initialise access to SDRAM
+ */
+void
+sdraminit(ulong base)
+{
+ ulong *upm;
+ IMM *io;
+ int i;
+
+ io = (IMM*)INTMEM; /* running before maps, no KADDR */
+ if(SPEED > 32)
+ upm = upmb50;
+ else
+ upm = upmb32;
+ for(i=0; i<UPMSIZE; i++){
+ io->mdr = upm[i];
+ io->mcr = WriteRAM | SelUPMB | i;
+ }
+ io->memc[SDRAM].option = ~(SDRAMSIZE-1)|0x0A00; /* address mask, SAM=1, G5LS=1 */
+ io->memc[SDRAM].base = base | 0xC1;
+ if(SPEED > 32){
+ io->mbmr = 0xD0802114; /* 50MHz BRGCLK */
+ io->mar = 0x88;
+ }else{
+ io->mbmr = 0x80802114; /* 32MHz BRGCLK */
+ io->mar = 0x48;
+ }
+ io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 5; /* run MRS command in locations 5-8 of UPMB */
+ io->mbmr = (io->mbmr & ~0xF) | 8;
+ io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 0x30; /* run refresh sequence */
+ io->mbmr = (io->mbmr & ~0xF) | 4; /* 4-beat refresh bursts */
+}
--- /dev/null
+++ b/os/boot.original/mpc/initpaq.c
@@ -1,0 +1,101 @@
+/*
+ * Called from l.s in EPROM to set up a minimal working environment.
+ * Since there is no DRAM yet, and therefore no stack, no function
+ * calls may be made from sysinit0, and values can't be stored,
+ * except to INTMEM. Global values are accessed by offset from SB,
+ * which has been set by l.s to point into EPROM.
+ *
+ * This is PowerPAQ-specific:
+ * - assumes 8mbytes
+ * - powerpaq CS assignment
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "archpaq.h"
+
+#define MB (1024*1024)
+
+enum {
+ DRAMSIZE = 8*MB,
+ FLASHSIZE = 8*MB,
+
+ UPMSIZE = 64, /* memory controller instruction RAM */
+ SPEED = 50, /* maximum memory clock in MHz */
+
+ /* mcr */
+ WriteRAM = 0<<30,
+ ReadRAM = 1<<30,
+ ExecRAM = 2<<30,
+
+ SelUPMA = 0<<23,
+ SelUPMB = 1<<23,
+
+ Once = 1<<8,
+};
+
+/*
+ * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
+ */
+static ulong upmb50[UPMSIZE] = {
+ 0x8FFFEC24, 0xFFFEC04, 0xCFFEC04, 0xFFEC04,
+ 0xFFEC00, 0x37FFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x8FFFEC24, 0xFFFEC04, 0x8FFEC04, 0xFFEC0C,
+ 0x3FFEC00, 0xFFEC44, 0xFFCC08, 0xCFFCC44,
+ 0xFFEC0C, 0x3FFEC00, 0xFFEC44, 0xFFCC00,
+ 0x3FFFC847, 0x3FFFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x11BFCC47,
+ 0xC0FFCC84, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x3AFCC4C,
+ 0xCAFCC00, 0x3AFCC4C, 0xCAFCC00, 0x3AFCC4C,
+ 0xCAFCC00, 0x33BFCC4F, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xC0FFCC84, 0xFFCC04, 0x7FFCC04, 0x3FFFCC06,
+ 0xFFFFCC85, 0xFFFFCC05, 0xFFFFCC05, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x33FFCC07, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+};
+
+void
+sysinit0(int inrom)
+{
+ ulong *upm;
+ IMM *io;
+ int i;
+
+ io = (IMM*)INTMEM; /* running before maps, no KADDR */
+
+ /* system interface unit initialisation, FADS manual table 3-2, except as noted */
+ io->siumcr = 0x01012440;
+ io->sypcr = 0xFFFFFF88;
+ io->tbscrk = KEEP_ALIVE_KEY;
+ io->tbscr = 0xC3; /* time base enabled */
+ io->rtcsck = KEEP_ALIVE_KEY;
+ io->rtcsc = 0xC1; /* don't FRZ, real-time clock enabled */
+ io->rtcsck = ~KEEP_ALIVE_KEY;
+ io->piscrk = KEEP_ALIVE_KEY;
+ io->piscr = 0x82;
+
+ io->memc[BOOTCS].base = FLASHMEM | 1;
+ io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(2<<4); /* mask, BIH, 2 wait states */
+
+ if(!inrom)
+ return; /* can't initialise DRAM controller from DRAM */
+
+ /* could check DRAM speed here; assume 60ns */
+ /* could probe DRAM for size here; assume DRAMSIZE */
+ io->mptpr = 0x400; /* powerpaq flash has 0x1000 */
+ io->mbmr = (0xC0<<24) | 0xA21114; /* 50MHz BRGCLK */
+ upm = upmb50;
+ for(i=0; i<UPMSIZE; i++){
+ io->mdr = upm[i];
+ io->mcr = WriteRAM | SelUPMB | i;
+ }
+ io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0800; /* address mask, SAM=1 */
+ io->memc[DRAM1].base = 0 | 0xC1; /* base at 0, 32-bit port size, no parity, UPMB */
+}
--- /dev/null
+++ b/os/boot.original/mpc/initrpcg.c
@@ -1,0 +1,91 @@
+
+/*
+ * Called from l.s in EPROM to set up a minimal working environment.
+ * Since there is no DRAM yet, and therefore no stack, no function
+ * calls may be made from sysinit, and values can't be stored,
+ * except to INTMEM. Global values are accessed by offset from SB,
+ * which has been set by l.s to point into EPROM.
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "archrpcg.h"
+
+#define MB (1024*1024)
+
+enum {
+ UPMSIZE = 64, /* memory controller instruction RAM */
+ DRAMSIZE = 16*MB,
+ FLASHSIZE = 4*MB,
+
+ WriteRAM = 0<<30,
+ ReadRAM = 1<<30,
+ ExecRAM = 2<<30,
+
+ SelUPMA = 0<<23,
+ SelUPMB = 1<<23,
+};
+/* RPCG values for RPXLite AW */
+static ulong upma50[UPMSIZE] = {
+ 0xCFFFCC24, 0x0FFFCC04, 0x0CAFCC04, 0x03AFCC08,
+ 0x3FBFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xCFFFCC24, 0x0FFFCC04, 0x0CAFCC84, 0x03AFCC88,
+ 0x3FBFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC04, 0x03FFCC00,
+ 0x3FFFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC84, 0x03FFCC84,
+ 0x0CFFCC00, 0x33FFCC27, 0xFFFFCC25, 0xFFFFCC25,
+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xC0FFCC24, 0x03FFCC24, 0x0FFFCC24, 0x0FFFCC24,
+ 0x3FFFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+};
+
+void
+sysinit0(int inrom)
+{
+ ulong *upm;
+ IMM *io;
+ int i;
+
+ io = (IMM*)INTMEM; /* running before maps, no KADDR */
+ io->siumcr = 0x01012440;
+ io->sypcr = 0xFFFFFF88;
+ io->tbscrk = KEEP_ALIVE_KEY;
+ io->tbscr = 0xC3;
+ io->rtcsck = KEEP_ALIVE_KEY;
+ io->rtcsc = 0xC1;
+ io->rtcsck = ~KEEP_ALIVE_KEY;
+ io->piscrk = KEEP_ALIVE_KEY;
+ io->piscr = 0x82;
+return;
+ io->memc[BCSRCS].option = 0xFFFF8910; /* 32k block, all types access, CSNT, CS early negate, burst inhibit, 1 ws */
+ io->memc[BCSRCS].base = BCSRMEM | 1; /* base, 32-bit port, no parity, GPCM */
+
+ io->memc[BOOTCS].base = FLASHMEM | 0x801; /* base, 16 bit port */
+ io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(4<<4); /* mask, BIH, 4 wait states */
+
+ if(1||!inrom)
+ return; /* can't initialise DRAM controller from DRAM */
+
+ /* TO DO: could check DRAM size and speed now */
+
+ upm = upma50;
+ for(i=0; i<nelem(upma50); i++){
+ io->mdr = upm[i];
+ io->mcr = WriteRAM | SelUPMA | i;
+ }
+ io->mptpr = 0x0800; /* divide by 8 */
+ io->mamr = (0x58<<24) | 0xA01430; /* 40MHz BRGCLK */
+ io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0E00; /* address mask, SAM=1, G5LA/S=3 */
+ io->memc[DRAM1].base = 0 | 0x81; /* base at 0, 32-bit port size, no parity, UPMA */
+}
--- /dev/null
+++ b/os/boot.original/mpc/io.h
@@ -1,0 +1,463 @@
+enum
+{
+ /* software interrupt vectors (SIU and CPM) */
+ VectorPIC= 0, /* level 0 to level 7, assigned by software */
+ CPIClevel= 4,
+ VectorIRQ= VectorPIC+8, /* IRQ0 to IRQ7 */
+ VectorCPIC= VectorIRQ+8, /* 32 CPM interrupts: 0 (error) to 0x1F (PC15) */
+};
+
+enum
+{
+ BUSUNKNOWN = 0,
+};
+
+/*
+ * Buffer Descriptors and IO Rings
+ */
+
+typedef struct BD BD;
+struct BD {
+ ushort status;
+ ushort length;
+ ulong addr;
+};
+
+BD* bdalloc(int);
+void bdfree(BD*, int);
+
+enum {
+ /* Rx BDs, bits common to all protocols */
+ BDEmpty= 1<<15,
+ BDWrap= 1<<13,
+ BDInt= 1<<12,
+ BDLast= 1<<11,
+ BDFirst= 1<<10,
+
+ /* Tx BDs */
+ BDReady= 1<<15,
+ /* BDWrap, BDInt, BDLast */
+};
+
+typedef struct Ring Ring;
+struct Ring {
+ BD* rdr; /* receive descriptor ring */
+ void* rrb; /* receive ring buffers */
+ int rdrx; /* index into rdr */
+ int nrdre; /* length of rdr */
+
+ BD* tdr; /* transmit descriptor ring */
+ Block** txb; /* corresponding transmit ring buffers */
+ int tdrh; /* host index into tdr */
+ int tdri; /* interface index into tdr */
+ int ntdre; /* length of tdr */
+ int ntq; /* pending transmit requests */
+};
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
+
+int ioringinit(Ring*, int, int, int);
+
+/*
+ * CPM
+ */
+enum {
+ /* commands */
+ InitRxTx = 0,
+ InitRx = 1,
+ InitTx = 2,
+ EnterHunt= 3,
+ StopTx= 4,
+ GracefulStopTx = 5,
+ InitIDMA = 5,
+ RestartTx = 6,
+ CloseRxBD = 7,
+ SetGroupAddr = 8,
+ SetTimer = 8,
+ GCITimeout = 9,
+ GCIAbort = 10,
+ StopIDMA = 11,
+ StartDSP = 12,
+ ArmIDMA = 13,
+ InitDSP = 13,
+ USBCmd = 15,
+
+ /* channel IDs */
+ SCC1ID= 0,
+ USBID= 0,
+ I2CID= 1,
+ IDMA1ID= 1,
+ SCC2ID= 4,
+ SPIID= 5,
+ IDMA2ID= 5,
+ TIMERID= 5,
+ SCC3ID= 8,
+ SMC1ID= 9,
+ DSP1ID=9,
+ SCC4ID= 12,
+ SMC2ID= 13,
+ DSP2ID= 13,
+
+ BaudEnable = 1<<16,
+
+ /* sicr */
+ CLK1 = 4, /* SCC1,2 */
+ CLK2 = 5,
+ CLK3 = 6,
+ CLK4 = 7,
+ CLK5 = CLK1, /* SCC3,4 */
+ CLK6 = CLK2,
+ CLK7 = CLK3,
+ CLK8 = CLK4,
+};
+
+void cpmop(int, int, int);
+#define ioplock() (m->iomem)
+#define iopunlock()
+
+/*
+ * the structures below follow hardware/firmware layouts in the 8xx manuals:
+ * mind the data types, offsets and alignment
+ */
+
+/*
+ * basic IO controller parameters (SMC and SCC)
+ */
+typedef struct IOCparam IOCparam;
+struct IOCparam {
+ ushort rbase;
+ ushort tbase;
+ uchar rfcr;
+ uchar tfcr;
+ ushort mrblr;
+ ulong rstate;
+ ulong rptr;
+ ushort rbptr;
+ ushort rcnt;
+ ulong rtmp;
+ ulong tstate;
+ ulong tptr;
+ ushort tbptr;
+ ushort tcnt;
+ ulong ttmp;
+};
+
+typedef struct SCCparam SCCparam;
+struct SCCparam {
+ IOCparam;
+ ulong rcrc;
+ ulong tcrc;
+};
+
+typedef struct SCC SCC;
+struct SCC {
+ ulong gsmrl;
+ ulong gsmrh;
+ ushort psmr;
+ uchar rsvscc0[2];
+ ushort todr;
+ ushort dsr;
+ ushort scce;
+ uchar rsvscc1[2];
+ ushort sccm;
+ uchar rsvscc3;
+ uchar sccs;
+ ushort irmode;
+ ushort irsip;
+};
+
+typedef struct SMC SMC;
+struct SMC {
+ uchar pad1[2];
+ ushort smcmr;
+ uchar pad2[2];
+ uchar smce;
+ uchar pad3[3];
+ uchar smcm;
+ uchar pad4[5];
+};
+
+typedef struct SPI SPI;
+struct SPI {
+ ushort spmode;
+ uchar res1[4];
+ uchar spie;
+ uchar res2[3];
+ uchar spim;
+ uchar res3[2];
+ uchar spcom;
+ uchar res4[10];
+};
+
+typedef struct USB USB;
+struct USB { /* 823 only */
+ uchar usmod;
+ uchar usadr;
+ uchar uscom;
+ uchar rsvu1;
+ ushort usep[4];
+ uchar rsvu2[4];
+ ushort usber;
+ uchar rsvu3[2];
+ ushort usbmr;
+ uchar rsvu4;
+ uchar usbs;
+ uchar rsvu5[8];
+};
+
+typedef struct IMM IMM;
+struct IMM {
+ struct { /* general SIU */
+ ulong siumcr;
+ ulong sypcr;
+ uchar rsv0[0xE-0x8];
+ ushort swsr;
+ ulong sipend;
+ ulong simask;
+ ulong siel;
+ uchar sivec;
+ uchar padv[3];
+ ulong tesr;
+ uchar rsv1[0x30-0x24];
+ ulong sdcr;
+ uchar rsv2[0x80-0x34];
+ };
+ struct { /* PCMCIA */
+ struct {
+ ulong base;
+ ulong option;
+ } pcmr[8];
+ uchar rsv3[0xe0-0xc0];
+ ulong pgcra;
+ ulong pgcrb;
+ ulong pscr;
+ uchar rsv4[0xf0-0xec];
+ ulong pipr;
+ uchar rsv5[4];
+ ulong per;
+ uchar rsv6[4];
+ };
+ struct { /* MEMC */
+ struct {
+ ulong base;
+ ulong option;
+ } memc[8];
+ uchar rsv7a[0x24];
+ ulong mar;
+ ulong mcr;
+ uchar rsv7b[4];
+ ulong mamr;
+ ulong mbmr;
+ ushort mstat;
+ ushort mptpr;
+ ulong mdr;
+ uchar rsv7c[0x80];
+ };
+ struct { /* system integration timers */
+ ushort tbscr;
+ uchar rsv8a[2];
+ ulong tbrefu;
+ ulong tbrefl;
+ uchar rsv8b[0x14];
+ ushort rtcsc;
+ uchar rsv8c[2];
+ ulong rtc;
+ ulong rtsec;
+ ulong rtcal;
+ uchar rsv8d[0x10];
+ ushort piscr;
+ ushort rsv8e;
+ ulong pitc;
+ ulong pitr;
+ uchar rsv8f[0x34];
+ };
+ struct { /* 280: clocks and resets */
+ ulong sccr;
+ ulong plprcr;
+ ulong rsr;
+ uchar rsv9[0x300-0x28c];
+ };
+ struct { /* 300: system integration timers keys */
+ ulong tbscrk;
+ ulong tbrefuk;
+ ulong tbreflk;
+ ulong tbk;
+ uchar rsv10a[0x10];
+ ulong rtcsck;
+ ulong rtck;
+ ulong rtseck;
+ ulong rtcalk;
+ uchar rsv10b[0x10];
+ ulong piscrk;
+ ulong pitck;
+ uchar rsv10c[0x38];
+ };
+ struct { /* 380: clocks and resets keys */
+ ulong sccrk;
+ ulong plprcrk;
+ ulong rsrk;
+ uchar rsv11[0x800-0x38C];
+ };
+ struct { /* 800: video controller */
+ ushort vccr;
+ ushort pad11a;
+ uchar vsr;
+ uchar pad11b;
+ uchar vcmr;
+ uchar pad11c;
+ ulong vbcb;
+ ulong pad11d;
+ ulong vfcr0;
+ ulong vfaa0;
+ ulong vfba0;
+ ulong vfcr1;
+ ulong vfaa1;
+ ulong vfba1;
+ uchar rsv11a[0x840-0x828];
+ };
+ struct { /* 840: LCD */
+ ulong lccr;
+ ulong lchcr;
+ ulong lcvcr;
+ ulong rsv11b;
+ ulong lcfaa;
+ ulong lcfba;
+ uchar lcsr;
+ uchar rsv11c[0x860-0x859];
+ };
+ struct { /* 860: I2C */
+ uchar i2mod;
+ uchar rsv12a[3];
+ uchar i2add;
+ uchar rsv12b[3];
+ uchar i2brg;
+ uchar rsv12c[3];
+ uchar i2com;
+ uchar rsv12d[3];
+ uchar i2cer;
+ uchar rsv12e[3];
+ uchar i2cmr;
+ uchar rsv12[0x900-0x875];
+ };
+ struct { /* 900: DMA */
+ uchar rsv13[4];
+ ulong sdar;
+ uchar sdsr;
+ uchar pad1[3];
+ uchar sdmr;
+ uchar pad2[3];
+ uchar idsr1;
+ uchar pad3[3];
+ uchar idmr1;
+ uchar pad4[3];
+ uchar idsr2;
+ uchar pad5[3];
+ uchar idmr2;
+ uchar pad6[0x930-0x91D];
+ };
+ struct { /* CPM interrupt control */
+ ushort civr;
+ uchar pad7[0x940-0x932];
+ ulong cicr;
+ ulong cipr;
+ ulong cimr;
+ ulong cisr;
+ };
+ struct { /* input/output port */
+ ushort padir;
+ ushort papar;
+ ushort paodr;
+ ushort padat;
+ uchar pad8[8];
+ ushort pcdir;
+ ushort pcpar;
+ ushort pcso;
+ ushort pcdat;
+ ushort pcint;
+ uchar pad9[6];
+ ushort pddir;
+ ushort pdpar;
+ ushort rsv14a;
+ ushort pddat;
+ uchar rsv14[0x980-0x978];
+ };
+ struct { /* CPM timers */
+ ushort tgcr;
+ uchar rsv15a[0x990-0x982];
+ ushort tmr1;
+ ushort tmr2;
+ ushort trr1;
+ ushort trr2;
+ ushort tcr1;
+ ushort tcr2;
+ ushort tcn1;
+ ushort tcn2;
+ ushort tmr3;
+ ushort tmr4;
+ ushort trr3;
+ ushort trr4;
+ ushort tcr3;
+ ushort tcr4;
+ ushort tcn3;
+ ushort tcn4;
+ ushort ter1;
+ ushort ter2;
+ ushort ter3;
+ ushort ter4;
+ uchar rsv15[0x9C0-0x9B8];
+ };
+ struct { /* CPM */
+ ushort cpcr;
+ uchar res0[2];
+ ushort rccr;
+ uchar res1;
+ uchar rmds;
+ uchar res2a[4];
+ ushort rctr1;
+ ushort rctr2;
+ ushort rctr3;
+ ushort rctr4;
+ uchar res2[2];
+ ushort rter;
+ uchar res3[2];
+ ushort rtmr;
+ uchar rsv16[0x9F0-0x9DC];
+ };
+ union { /* BRG */
+ struct {
+ ulong brgc1;
+ ulong brgc2;
+ ulong brgc3;
+ ulong brgc4;
+ };
+ ulong brgc[4];
+ };
+ uchar skip0[0xAB2-0xA00]; /* USB, SCC, SMC, SPI: address using cpmdev(CP...)->regs */
+ struct { /* PIP */
+ ushort pipc; /* not 823 */
+ ushort ptpr; /* not 823 */
+ ulong pbdir;
+ ulong pbpar;
+ uchar pad10[2];
+ ushort pbodr;
+ ulong pbdat;
+ uchar pad11[0xAE0-0xAC8];
+ };
+ struct { /* SI */
+ ulong simode;
+ uchar sigmr;
+ uchar pad12;
+ uchar sistr;
+ uchar sicmr;
+ uchar pad13[4];
+ ulong sicr;
+ ulong sirp;
+ uchar pad14[0xB00-0xAF4];
+ };
+ ulong vcram[64];
+ ushort siram[256];
+ ushort lcdmap[256];
+};
--- /dev/null
+++ b/os/boot.original/mpc/ip.h
@@ -1,0 +1,98 @@
+typedef struct Udphdr Udphdr;
+struct Udphdr
+{
+ uchar d[6]; /* Ethernet destination */
+ uchar s[6]; /* Ethernet source */
+ uchar type[2]; /* Ethernet packet type */
+
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+
+ /* Udp pseudo ip really starts here */
+ uchar ttl;
+ uchar udpproto; /* Protocol */
+ uchar udpplen[2]; /* Header plus data length */
+ uchar udpsrc[4]; /* Ip source */
+ uchar udpdst[4]; /* Ip destination */
+ uchar udpsport[2]; /* Source port */
+ uchar udpdport[2]; /* Destination port */
+ uchar udplen[2]; /* data length */
+ uchar udpcksum[2]; /* Checksum */
+};
+
+typedef struct Etherhdr Etherhdr;
+struct Etherhdr
+{
+ uchar d[6];
+ uchar s[6];
+ uchar type[2];
+
+ /* Now we have the ip fields */
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+ uchar ttl; /* Time to live */
+ uchar proto; /* Protocol */
+ uchar cksum[2]; /* Header checksum */
+ uchar src[4]; /* Ip source */
+ uchar dst[4]; /* Ip destination */
+};
+
+enum
+{
+ IP_VER = 0x40,
+ IP_HLEN = 0x05,
+ UDP_EHSIZE = 22,
+ UDP_PHDRSIZE = 12,
+ UDP_HDRSIZE = 20,
+ ETHER_HDR = 14,
+ IP_UDPPROTO = 17,
+ ET_IP = 0x800,
+ Bcastip = 0xffffffff,
+ BPportsrc = 68,
+ BPportdst = 67,
+ TFTPport = 69,
+ Timeout = 5000, /* milliseconds */
+ Bootrequest = 1,
+ Bootreply = 2,
+ Tftp_READ = 1,
+ Tftp_WRITE = 2,
+ Tftp_DATA = 3,
+ Tftp_ACK = 4,
+ Tftp_ERROR = 5,
+ Segsize = 512,
+ TFTPSZ = Segsize+10,
+};
+
+typedef struct Bootp Bootp;
+struct Bootp
+{
+ uchar op; /* opcode */
+ uchar htype; /* hardware type */
+ uchar hlen; /* hardware address len */
+ uchar hops; /* hops */
+ uchar xid[4]; /* a random number */
+ uchar secs[2]; /* elapsed snce client started booting */
+ uchar pad[2];
+ uchar ciaddr[4]; /* client IP address (client tells server) */
+ uchar yiaddr[4]; /* client IP address (server tells client) */
+ uchar siaddr[4]; /* server IP address */
+ uchar giaddr[4]; /* gateway IP address */
+ uchar chaddr[16]; /* client hardware address */
+ char sname[64]; /* server host name (optional) */
+ char file[128]; /* boot file name */
+ char vend[128]; /* vendor-specific goo */
+};
+
+typedef struct Netaddr Netaddr;
+struct Netaddr
+{
+ ulong ip;
+ ushort port;
+ char ea[Eaddrlen];
+};
--- /dev/null
+++ b/os/boot.original/mpc/l.s
@@ -1,0 +1,370 @@
+#include "mem.h"
+
+/* special instruction definitions */
+#define BDNE BC 0,2,
+#define BDNZ BC 16,0,
+#define NOOP OR R0,R0,R0
+
+/*
+ * common ppc special purpose registers
+ */
+#define DSISR 18
+#define DAR 19 /* Data Address Register */
+#define DEC 22 /* Decrementer */
+#define SRR0 26 /* Saved Registers (exception) */
+#define SRR1 27
+#define SPRG0 272 /* Supervisor Private Registers */
+#define SPRG1 273
+#define SPRG2 274
+#define SPRG3 275
+#define TBRU 269 /* Time base Upper/Lower (Reading) */
+#define TBRL 268
+#define TBWU 285 /* Time base Upper/Lower (Writing) */
+#define TBWL 284
+#define PVR 287 /* Processor Version */
+
+/*
+ * mpc82x-specific special purpose registers of interest here
+ */
+#define EIE 80
+#define EID 81
+#define NRI 82
+#define IMMR 638
+#define IC_CST 560
+#define IC_ADR 561
+#define IC_DAT 562
+#define DC_CST 568
+#define DC_ADR 569
+#define DC_DAT 570
+#define MI_CTR 784
+#define MI_AP 786
+#define MI_EPN 787
+#define MI_TWC 789
+#define MI_RPN 790
+#define MI_DBCAM 816
+#define MI_DBRAM0 817
+#define MI_DBRAM1 818
+#define MD_CTR 792
+#define M_CASID 793
+#define MD_AP 794
+#define MD_EPN 795
+#define M_TWB 796
+#define MD_TWC 797
+#define MD_RPN 798
+#define M_TW 799
+#define MD_DBCAM 824
+#define MD_DBRAM0 825
+#define MD_DBRAM1 826
+
+/* as on 603e, apparently mtmsr needs help in some chip revisions */
+#define WAITMSR SYNC; ISYNC
+
+/* use of SPRG registers in save/restore */
+#define SAVER0 SPRG0
+#define SAVER1 SPRG1
+#define SAVELR SPRG2
+#define SAVECR SPRG3
+
+#define UREGSIZE ((8+32)*4)
+#define UREGSPACE (UREGSIZE+8) /* allow for arg to trap, and align */
+
+/*
+ * This code is loaded by the ROM loader at location 0x3000,
+ * or lives in flash memory at 0x2800100.
+ * Move it to high memory so that it can load the kernel at 0x0000.
+ */
+
+#define LOADCODEBASE 0x3000 /* when downloaded in S records */
+#define FLASHCODEBASE (FLASHMEM+0x100) /* when in flash */
+
+ TEXT start(SB), $-4
+ MOVW MSR, R3
+ MOVW $(EE|IP|RI), R4
+ ANDN R4, R3
+ OR $ME, R3
+ SYNC
+ MOVW R3, MSR /* turn off interrupts but enable traps */
+ WAITMSR
+
+/*
+ * reset the caches and disable them for now
+ */
+ MOVW SPR(IC_CST), R4 /* read and clear */
+ MOVW $(5<<25), R4
+ MOVW R4, SPR(IC_CST) /* unlock all */
+ ISYNC
+ MOVW $(6<<25), R4
+ MOVW R4, SPR(IC_CST) /* invalidate all */
+ ISYNC
+ MOVW $(2<<25), R4
+ MOVW R4, SPR(IC_CST) /* disable i-cache */
+ ISYNC
+
+ SYNC
+ MOVW SPR(DC_CST), R4 /* read and clear */
+ MOVW $(10<<24), R4
+ MOVW R4, SPR(DC_CST) /* unlock all */
+ ISYNC
+ MOVW $(12<<24), R4
+ MOVW R4, SPR(DC_CST) /* invalidate all */
+ ISYNC
+ MOVW $(4<<24), R4
+ MOVW R4, SPR(DC_CST) /* disable i-cache */
+ ISYNC
+
+ MOVW $7, R4
+ANDN R4, R4, R4
+ MOVW R4, SPR(158) /* cancel `show cycle' for normal instruction execution */
+
+/*
+ * set other system configuration values
+ */
+ MOVW SPR(IMMR), R5 /* save initial space pointer */
+ MOVW $INTMEM, R4
+ MOVW R4, SPR(IMMR) /* set internal memory base */
+ MOVW $0xFFFFFF88, R3
+ MOVW R3, 4(R4) /* disable watchdog in sypcr */
+ MOVW $0x01012440, R3
+ MOVW R3, 0(R4) /* siumcr */
+
+/*
+ * system initialisation (init and map DRAM)
+ */
+ MOVW $0, R0
+ MOVW $setSB(SB), R2
+ MOVW $(0xF000<<16), R3
+/*MOVW R0, R3*/
+ ANDCC R5, R3 /* initial space is high? */
+ BEQ notrom
+ MOVW $FLASHCODEBASE, R5 /* where $start(SB) actually is now */
+ MOVW $start(SB), R4 /* logical start address */
+ SUB R4, R5, R6 /* text relocation value */
+ MOVW $etext(SB), R7
+ SUB R4, R7
+ ADD R5, R7 /* data address in ROM */
+ MOVW $bdata(SB), R8
+ SUB R8, R2
+ ADD R7, R2 /* relocate SB: SB' = romdata+(SB-bdata) */
+ MOVW $sysinit0(SB), R4
+ ADD R6, R4 /* relocate sysinit0's address */
+ MOVW R4, CTR
+ MOVW $inmem(SB), R4
+ ADD R6, R4
+ MOVW R4, LR /* and the return address */
+ BR (CTR) /* call sysinit0 */
+ TEXT inmem(SB), $-4
+ MOVW $FLASHCODEBASE, R3
+ BR cpu0
+notrom:
+ MOVW $start(SB), R6
+ SUB R6, R2
+ ADD $LOADCODEBASE, R2
+ BL sysinit0(SB)
+ MOVW $LOADCODEBASE, R3
+
+/*
+ * cpu 0
+ * relocate bootstrap to our link addresses for text and data
+ * set new PC
+ */
+cpu0:
+ MOVW $setSB(SB), R2 /* set correct static base register */
+ MOVW $start(SB), R4
+ MOVW $etext(SB), R5
+ SUB R4, R5
+ CMP R4, R3 /* already there? */
+ BNE copytext
+ ADD R5, R3 /* start of data image */
+ BR copydata
+
+copytext:
+ ADD $3, R5
+ SRAW $2, R5
+ MOVW R5, CTR
+ SUB $4, R4
+ SUB $4, R3
+copyt: /* copy text */
+ MOVWU 4(R3), R5
+ MOVWU R5, 4(R4)
+ BDNZ copyt
+ ADD $4, R3
+
+copydata:
+ /* copy data */
+ MOVW $bdata(SB), R4
+ CMP R4, R3 /* already there? */
+ BEQ loadkpc
+ MOVW $edata(SB), R5
+ SUB R4, R5
+ ADD $3, R5
+ SRAW $2, R5
+ MOVW R5, CTR
+ SUB $4, R4
+ SUB $4, R3
+copyd:
+ MOVWU 4(R3), R5
+ MOVWU R5, 4(R4)
+ BDNZ copyd
+
+ /* load correct PC */
+loadkpc:
+ MOVW $start1(SB), R3
+ MOVW R3, LR
+ BR (LR)
+TEXT start1(SB), $-4
+ MOVW $edata(SB), R3
+ MOVW $end(SB), R4
+ SUBCC R3, R4
+ BLE skipz
+ SRAW $2, R4
+ MOVW R4, CTR
+ SUB $4, R3
+ MOVW $0, R0
+zero:
+ MOVWU R0, 4(R3)
+ BDNZ zero
+skipz:
+ MOVW $mach0(SB), R1
+ MOVW R1, m(SB)
+ ADD $(MACHSIZE-8), R1
+ MOVW $0, R0
+ BL main(SB)
+ BR 0(PC)
+
+TEXT getmsr(SB), $0
+ MOVW MSR, R3
+ RETURN
+
+TEXT putmsr(SB), $0
+ SYNC
+ MOVW R3, MSR
+ WAITMSR
+ RETURN
+
+TEXT eieio(SB), $0
+ EIEIO
+ RETURN
+
+TEXT idle(SB), $0
+ RETURN
+
+TEXT spllo(SB), $0
+ MOVW MSR, R3
+ OR $EE, R3, R4
+ SYNC
+ MOVW R4, MSR
+ WAITMSR
+ RETURN
+
+TEXT splhi(SB), $0
+ MOVW MSR, R3
+ RLWNM $0, R3, $~EE, R4
+ SYNC
+ MOVW R4, MSR
+ WAITMSR
+ RETURN
+
+TEXT splx(SB), $0
+ MOVW MSR, R4
+ RLWMI $0, R3, $EE, R4
+ SYNC
+ MOVW R4, MSR
+ WAITMSR
+ RETURN
+
+TEXT gettbl(SB), $0
+/* MOVW SPR(TBRL), R3 */
+ WORD $0x7c6c42e6 /* mftbl on 8xx series */
+ RETURN
+
+TEXT getpvr(SB), $0
+ MOVW SPR(PVR), R3
+ RETURN
+
+TEXT getimmr(SB), $0
+ MOVW SPR(IMMR), R3
+ RETURN
+
+TEXT getdec(SB), $0
+ MOVW SPR(DEC), R3
+ RETURN
+
+TEXT putdec(SB), $0
+ MOVW R3, SPR(DEC)
+ RETURN
+
+/*
+ * save state in Ureg on kernel stack.
+ * enter with R0 giving the PC from the call to `exception' from the vector.
+ * on return, SB (R2) has been set, and R3 has the Ureg*
+ */
+TEXT saveureg(SB), $-4
+ SUB $UREGSPACE, R1
+ MOVMW R2, 48(R1) /* r2:r31 */
+ MOVW $setSB(SB), R2
+ MOVW SPR(SAVER1), R4
+ MOVW R4, 44(R1)
+ MOVW SPR(SAVER0), R5
+ MOVW R5, 40(R1)
+ MOVW CTR, R6
+ MOVW R6, 36(R1)
+ MOVW XER, R4
+ MOVW R4, 32(R1)
+ MOVW SPR(SAVECR), R5 /* CR */
+ MOVW R5, 28(R1)
+ MOVW SPR(SAVELR), R6 /* LR */
+ MOVW R6, 24(R1)
+ /* pad at 20(R1) */
+ MOVW SPR(SRR0), R4
+ MOVW R4, 16(R1) /* old PC */
+ MOVW SPR(SRR1), R5
+ MOVW R5, 12(R1)
+ MOVW R0, 8(R1) /* cause/vector, encoded in LR from vector */
+ ADD $8, R1, R3 /* Ureg* */
+ STWCCC R3, (R1) /* break any pending reservations */
+ MOVW $0, R0 /* R0ISZERO */
+ BR (LR)
+
+/*
+ * restore state from Ureg
+ * SB (R2) is unusable on return
+ */
+TEXT restoreureg(SB), $-4
+ MOVMW 48(R1), R2 /* r2:r31 */
+ /* defer R1 */
+ MOVW 40(R1), R0
+ MOVW R0, SPR(SAVER0)
+ MOVW 36(R1), R0
+ MOVW R0, CTR
+ MOVW 32(R1), R0
+ MOVW R0, XER
+ MOVW 28(R1), R0
+ MOVW R0, CR /* CR */
+ MOVW 24(R1), R0
+ MOVW R0, SPR(SAVELR) /* LR */
+ /* pad, skip */
+ MOVW 16(R1), R0
+ MOVW R0, SPR(SRR0) /* old PC */
+ MOVW 12(R1), R0
+ MOVW R0, SPR(SRR1) /* old MSR */
+ /* cause, skip */
+ MOVW 44(R1), R1 /* old SP */
+ BR (LR)
+
+TEXT exception(SB), $-4
+ MOVW R1, SPR(SAVER1)
+ MOVW CR, R0
+ MOVW R0, SPR(SAVECR)
+ MOVW LR, R0
+ BL saveureg(SB)
+ MOVW $0, R0
+ BL trap(SB)
+ BL restoreureg(SB)
+ MOVW SPR(SAVELR), R0
+ MOVW R0, LR
+ MOVW SPR(SAVER0), R0
+ ISYNC
+ RFI
+
+GLOBL mach0+0(SB), $MACHSIZE
+GLOBL m(SB), $4
--- /dev/null
+++ b/os/boot.original/mpc/lib.h
@@ -1,0 +1,106 @@
+/*
+ * functions (possibly) linked in, complete, from libc.
+ */
+
+/*
+ * mem routines
+ */
+extern void* memccpy(void*, void*, int, long);
+extern void* memset(void*, int, long);
+extern int memcmp(void*, void*, long);
+extern void* memmove(void*, void*, long);
+extern void* memchr(void*, int, long);
+
+/*
+ * string routines
+ */
+extern char* strcat(char*, char*);
+extern char* strchr(char*, char);
+extern int strcmp(char*, char*);
+extern char* strcpy(char*, char*);
+extern char* strncat(char*, char*, long);
+extern char* strncpy(char*, char*, long);
+extern int strncmp(char*, char*, long);
+extern long strlen(char*);
+extern char* strrchr(char*, char);
+extern char* strstr(char*, char*);
+
+/*
+ * print routines
+ * Fconv isn't used but is defined to satisfy prototypes in libg.h
+ * that are never called.
+ */
+typedef struct Fconv Fconv;
+
+extern char* donprint(char*, char*, char*, void*);
+extern int sprint(char*, char*, ...);
+extern int print(char*, ...);
+
+#define PRINTSIZE 256
+
+/*
+ * one-of-a-kind
+ */
+extern int atoi(char*);
+extern long strtol(char*, char**, int);
+extern ulong strtoul(char*, char**, int);
+extern long end;
+
+/*
+ * Syscall data structures
+ */
+
+#define MORDER 0x0003 /* mask for bits defining order of mounting */
+#define MREPL 0x0000 /* mount replaces object */
+#define MBEFORE 0x0001 /* mount goes before others in union directory */
+#define MAFTER 0x0002 /* mount goes after others in union directory */
+#define MCREATE 0x0004 /* permit creation in mounted directory */
+#define MMASK 0x0007 /* all bits on */
+
+#define OREAD 0 /* open for read */
+#define OWRITE 1 /* write */
+#define ORDWR 2 /* read and write */
+#define OEXEC 3 /* execute, == read but check execute permission */
+#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
+#define OCEXEC 32 /* or'ed in, close on exec */
+#define ORCLOSE 64 /* or'ed in, remove on close */
+
+#define NCONT 0 /* continue after note */
+#define NDFLT 1 /* terminate after note */
+
+typedef struct Qid Qid;
+typedef struct Dir Dir;
+typedef struct Waitmsg Waitmsg;
+
+#define ERRLEN 64
+#define DIRLEN 116
+#define NAMELEN 28
+
+struct Qid
+{
+ ulong path;
+ ulong vers;
+};
+
+struct Dir
+{
+ char name[NAMELEN];
+ char uid[NAMELEN];
+ char gid[NAMELEN];
+ Qid qid;
+ ulong mode;
+ long atime;
+ long mtime;
+ vlong length;
+ short type;
+ short dev;
+};
+
+struct Waitmsg
+{
+ int pid; /* of loved one */
+ int status; /* unused; a placeholder */
+ ulong time[3]; /* of loved one */
+ char msg[ERRLEN];
+};
+#define nelem(x) (sizeof(x)/sizeof((x)[0]))
--- /dev/null
+++ b/os/boot.original/mpc/main.c
@@ -1,0 +1,524 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "dosfs.h"
+
+typedef struct Type Type;
+typedef struct Medium Medium;
+typedef struct Mode Mode;
+
+enum {
+ Dany = -1,
+ Nmedia = 16,
+
+ /* DS1 switch options */
+ Sflashfs = 1<<0, /* take local fs from flash */
+ Snotflash = 1<<1, /* don't boot from flash */
+};
+
+enum { /* type */
+ Tflash,
+ Tuart,
+ Tether,
+ Thard,
+
+ Tany = -1,
+};
+
+enum { /* flag and name */
+ Fnone = 0x00,
+
+ Fdos = 0x01,
+ Ndos = 0x00,
+ Fboot = 0x02,
+ Nboot = 0x01,
+ Fbootp = 0x04,
+ Nbootp = 0x02,
+ Fflash = 0x08,
+ Fuart = 0x10,
+ NName = 0x03,
+
+ Fany = Fbootp|Fboot|Fdos|Fflash|Fuart,
+
+ Fini = 0x10,
+ Fprobe = 0x80,
+};
+
+enum { /* mode */
+ Mauto = 0x00,
+ Mlocal = 0x01,
+ Manual = 0x02,
+ NMode = 0x03,
+};
+
+typedef struct Type {
+ int type;
+ char *cname;
+ int flag;
+ int (*init)(void);
+ long (*read)(int, void*, long);
+ long (*seek)(int, long);
+ Partition* (*setpart)(int, char*);
+ char* name[NName];
+
+ int mask;
+ Medium* media;
+} Type;
+
+typedef struct Medium {
+ Type* type;
+ int flag;
+ Partition* partition;
+ Dos;
+
+ Medium* next;
+} Medium;
+
+typedef struct Mode {
+ char* name;
+ int mode;
+} Mode;
+
+static Type types[] = {
+ { Tflash, "flash",
+ Fflash,
+ flashinit, 0, 0, 0,
+ { 0, "F", 0, }
+ },
+/*
+ { Tuart, "uart",
+ Fuart|Fboot,
+ uartinit, uartread, uartseek, setuartpart,
+ { 0, "u", 0, }
+ },
+*/
+ { Tether, "ether",
+ Fbootp,
+ etherinit, 0, 0, 0,
+ { 0, 0, "e", },
+ },
+ { Thard, "ata",
+ Fini|Fboot|Fdos,
+ 0, 0, 0, 0, /* not used now, will be later with PCMCIA */
+ { "hd", "h", 0, },
+ },
+ {-1},
+};
+
+static Medium media[Nmedia];
+static Medium *curmedium = media;
+
+static Mode modes[NMode+1] = {
+ [Mauto] { "auto", Mauto, },
+ [Mlocal] { "local", Mlocal, },
+ [Manual] { "manual", Manual, },
+};
+
+static char *inis[] = {
+ "inferno/inferno.ini",
+ "inferno.ini",
+ "plan9/plan9.ini",
+ "plan9.ini",
+ 0,
+};
+char **ini;
+int predawn;
+
+static int
+parse(char *line, int *type, int *flag, int *dev, char *file)
+{
+ Type *tp;
+ char buf[2*NAMELEN], *v[4], *p;
+ int i;
+
+ strcpy(buf, line);
+ switch(getcfields(buf, v, 4, "!")){
+
+ case 3:
+ break;
+
+ case 2:
+ v[2] = "";
+ break;
+
+ default:
+ return 0;
+ }
+
+ *flag = 0;
+ for(tp = types; tp->cname; tp++){
+ for(i = 0; i < NName; i++){
+
+ if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
+ continue;
+ *type = tp->type;
+ *flag |= 1<<i;
+
+ if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
+ return 0;
+
+ strcpy(file, v[2]);
+
+ return 1;
+ }
+ }
+
+ return 0;
+
+}
+
+static int
+boot(Medium *mp, int flag, char *file)
+{
+ Dosfile df;
+ char ixdos[128], *p;
+ int r;
+
+ uartsetboot(0);
+ if(flag & Fbootp){
+ sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
+ return bootp(mp->dev, file);
+ }
+
+ if(flag & Fflash){
+ if(mp->flag & Fflash && flashbootable(0))
+ flashboot(mp->dev);
+ }
+
+ if(flag & Fboot){
+
+ if(mp->flag & Fini){
+ (*mp->type->setpart)(mp->dev, "disk");
+ plan9ini(mp, nil);
+ }
+ if(file == 0 || *file == 0)
+ file = mp->partition->name;
+ (*mp->type->setpart)(mp->dev, file);
+ sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
+ r = plan9boot(mp->dev, mp->seek, mp->read);
+ uartsetboot(0);
+ return r;
+ }
+
+ if(flag & Fdos){
+ if(mp->type->setpart)
+ (*mp->type->setpart)(mp->dev, "disk");
+ if(mp->flag & Fini)
+ plan9ini(mp, nil);
+ if(file == 0 || *file == 0){
+ strcpy(ixdos, *ini);
+ if(p = strrchr(ixdos, '/'))
+ p++;
+ else
+ p = ixdos;
+ strcpy(p, "impc");
+ if(dosstat(mp, ixdos, &df) <= 0)
+ return -1;
+ }
+ else
+ strcpy(ixdos, file);
+ sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
+ return dosboot(mp, ixdos);
+ }
+
+ return -1;
+}
+
+static Medium*
+allocm(Type *tp)
+{
+ Medium **l;
+
+ if(curmedium >= &media[Nmedia])
+ return 0;
+
+ for(l = &tp->media; *l; l = &(*l)->next)
+ ;
+ *l = curmedium++;
+ return *l;
+}
+
+Medium*
+probe(int type, int flag, int dev)
+{
+ Type *tp;
+ int dombr, i, start;
+ Medium *mp;
+ Dosfile df;
+ Partition *pp;
+
+ for(tp = types; tp->cname; tp++){
+ if(type != Tany && type != tp->type || tp->init == 0)
+ continue;
+
+ if(flag != Fnone){
+ for(mp = tp->media; mp; mp = mp->next){
+ if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
+ return mp;
+ }
+ }
+ if((tp->flag & Fprobe) == 0){
+ tp->flag |= Fprobe;
+ tp->mask = (*tp->init)();
+ }
+
+ for(i = 0; tp->mask; i++){
+ if((tp->mask & (1<<i)) == 0)
+ continue;
+ tp->mask &= ~(1<<i);
+
+ if((mp = allocm(tp)) == 0)
+ continue;
+
+ mp->dev = i;
+ mp->flag = tp->flag;
+ mp->seek = tp->seek;
+ mp->read = tp->read;
+ mp->type = tp;
+
+ if(mp->flag & Fboot){
+ if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
+ mp->flag &= ~Fboot;
+ if((mp->flag & (Fflash|Fuart)) == 0)
+ (*tp->setpart)(i, "disk");
+ }
+
+ if(mp->flag & Fdos){
+ start = 0;
+ dombr = 1;
+ if(mp->type->setpart){
+ if(pp = (*mp->type->setpart)(i, "dos")){
+ if(start = pp->start)
+ dombr = 0;
+ }
+ (*tp->setpart)(i, "disk");
+ }
+ if(dosinit(mp, start, dombr) < 0)
+ mp->flag &= ~(Fini|Fdos);
+ else
+ print("dos init failed\n");
+ }
+
+ if(mp->flag & Fini){
+ mp->flag &= ~Fini;
+ for(ini = inis; *ini; ini++){
+ if(dosstat(mp, *ini, &df) <= 0)
+ continue;
+ mp->flag |= Fini;
+ break;
+ }
+ }
+
+ if((flag & mp->flag) && (dev == Dany || dev == i))
+ return mp;
+ }
+ }
+
+ return 0;
+}
+
+void
+main(void)
+{
+ Medium *mp;
+ int dev, flag, i, mode, tried, type, options;
+ char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
+ Type *tp;
+
+ machinit();
+ archinit();
+ meminit();
+ cpminit();
+ trapinit();
+ consinit(); /* screen and keyboard initially */
+ screeninit();
+ cpuidprint();
+ alarminit();
+ clockinit();
+ predawn = 0;
+ spllo();
+ options = archoptionsw();
+
+ mp = 0;
+ for(tp = types; tp->cname; tp++){
+ if(tp->type == Tether)
+ continue;
+ if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
+ plan9ini(mp, nil);
+ break;
+ }
+ }
+
+ if(mp == 0 || (mp->flag & Fini) == 0)
+ plan9ini(nil, flashconfig(0));
+
+ //consinit(); /* establish new console location */
+
+ if((options & Snotflash) == 0 && flashbootable(0)){
+ print("Flash boot\n");
+ flashboot(0);
+ }
+
+ tried = 0;
+ mode = Mauto;
+ p = getconf("bootfile");
+ flag = 0;
+
+ if(p != 0) {
+ mode = Manual;
+ for(i = 0; i < NMode; i++){
+ if(strcmp(p, modes[i].name) == 0){
+ mode = modes[i].mode;
+ goto done;
+ }
+ }
+ if(parse(p, &type, &flag, &dev, file) == 0) {
+ print("Bad bootfile syntax: %s\n", p);
+ goto done;
+ }
+ mp = probe(type, flag, dev);
+ if(mp == 0) {
+ print("Cannot access device: %s\n", p);
+ goto done;
+ }
+ tried = boot(mp, flag, file);
+ }
+done:
+ if(tried == 0 && mode != Manual){
+ flag = Fany;
+ if(mode == Mlocal)
+ flag &= ~Fbootp;
+ if(options & Snotflash)
+ flag &= ~Fflash;
+ if((mp = probe(Tany, flag, Dany)) != 0)
+ boot(mp, flag & mp->flag, 0);
+ }
+
+ def[0] = 0;
+ probe(Tany, Fnone, Dany);
+
+ flag = 0;
+ for(tp = types; tp->cname; tp++){
+ for(mp = tp->media; mp; mp = mp->next){
+ if(flag == 0){
+ flag = 1;
+ print("Boot devices:");
+ }
+
+ if(mp->flag & Fbootp)
+ print(" %s!%d", mp->type->name[Nbootp], mp->dev);
+ if(mp->flag & Fdos)
+ print(" %s!%d", mp->type->name[Ndos], mp->dev);
+ if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot)
+ print(" %s!%d", mp->type->name[Nboot], mp->dev);
+ }
+ }
+ if(flag)
+ print("\n");
+
+ for(;;){
+ if(getstr("boot from", line, sizeof(line), def) >= 0){
+ if(parse(line, &type, &flag, &dev, file)){
+ if(mp = probe(type, flag, dev))
+ boot(mp, flag, file);
+ }
+ }
+ def[0] = 0;
+ }
+}
+
+void
+machinit(void)
+{
+ memset(m, 0, sizeof(*m));
+ m->delayloop = 20000;
+ m->cpupvr = getpvr();
+ m->iomem = KADDR(INTMEM);
+}
+
+int
+getcfields(char* lp, char** fields, int n, char* sep)
+{
+ int i;
+
+ for(i = 0; lp && *lp && i < n; i++){
+ while(*lp && strchr(sep, *lp) != 0)
+ *lp++ = 0;
+ if(*lp == 0)
+ break;
+ fields[i] = lp;
+ while(*lp && strchr(sep, *lp) == 0){
+ if(*lp == '\\' && *(lp+1) == '\n')
+ *lp++ = ' ';
+ lp++;
+ }
+ }
+
+ return i;
+}
+
+static Map memv[512];
+static RMap rammap = {"physical memory"};
+
+void
+meminit(void)
+{
+ ulong e;
+
+ mapinit(&rammap, memv, sizeof(memv));
+ e = PADDR(&end);
+ mapfree(&rammap, e, 4*1024*1024-e); /* fixed 4Mbytes is plenty for bootstrap */
+}
+
+void*
+ialloc(ulong n, int align)
+{
+ ulong a;
+ int s;
+
+ if(align <= 0)
+ align = 4;
+ s = splhi();
+ a = mapalloc(&rammap, 0, n, align);
+ splx(s);
+ if(a == 0)
+ panic("ialloc");
+ return memset(KADDR(a), 0, n);
+}
+
+void*
+malloc(ulong n)
+{
+ ulong *p;
+
+ n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
+ p = ialloc(n, sizeof(int));
+ *p++ = 0xcafebeef;
+ *p++ = n;
+ return p;
+}
+
+void
+free(void *ap)
+{
+ int s;
+ ulong *p;
+
+ p = ap;
+ if(p){
+ if(*(p -= 2) != 0xcafebeef)
+ panic("free");
+ s = splhi();
+ mapfree(&rammap, (ulong)p, p[1]);
+ splx(s);
+ }
+}
+
+void
+sched(void)
+{
+}
--- /dev/null
+++ b/os/boot.original/mpc/mem.h
@@ -1,0 +1,95 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#define BY2PG 4096 /* bytes per page */
+#define WD2PG (BY2PG/BY2WD) /* words per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
+
+#define MAXMACH 1 /* max # cpus system can run */
+#define CACHELINELOG 4
+#define CACHELINESZ (1<<CACHELINELOG)
+
+/*
+ * Time
+ */
+#define HZ (50) /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
+#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
+#define MHz 1000000
+
+/*
+ * Fundamental values
+ */
+
+#define KZERO 0 /* bootstrap runs in real mode */
+#define MACHSIZE 4096
+
+/*
+ * physical MMU
+ */
+#define KSEG0 0x20000000
+#define KSEGM 0xE0000000 /* mask to check which seg */
+
+/*
+ * MSR bits
+ */
+
+#define POW 0x40000 /* enable power mgmt */
+#define TGPR 0x20000 /* GPR0-3 remapped; 603/603e specific */
+#define ILE 0x10000 /* interrupts little endian */
+#define EE 0x08000 /* enable external/decrementer interrupts */
+#define PR 0x04000 /* =1, user mode */
+#define FPE 0x02000 /* enable floating point */
+#define ME 0x01000 /* enable machine check exceptions */
+#define FE0 0x00800
+#define SE 0x00400 /* single-step trace */
+#define BE 0x00200 /* branch trace */
+#define FE1 0x00100
+#define IP 0x00040 /* =0, vector to nnnnn; =1, vector to FFFnnnnn */
+#define IR 0x00020 /* enable instruction address translation */
+#define DR 0x00010 /* enable data address translation */
+#define RI 0x00002 /* exception is recoverable */
+#define LE 0x00001 /* little endian mode */
+
+#define KMSR (ME|FE0|FE1|FPE)
+#define UMSR (KMSR|PR|EE|IR|DR)
+
+/*
+ * MPC82x addresses; mpc8bug is happy with these
+ */
+#define BCSRMEM 0x02100000
+#define INTMEM 0x02200000
+#define FLASHMEM 0x02800000
+#define SDRAMMEM 0x03000000
+
+#define DPRAM (INTMEM+0x2000)
+#define DPLEN1 0x400
+#define DPLEN2 0x200
+#define DPLEN3 0x100
+#define DPBASE (DPRAM+DPLEN1)
+
+#define SCC1P (INTMEM+0x3C00)
+#define I2CP (INTMEM+0x3C80)
+#define MISCP (INTMEM+0x3CB0)
+#define IDMA1P (INTMEM+0x3CC0)
+#define SCC2P (INTMEM+0x3D00)
+#define SCC3P (INTMEM+0x3E00)
+#define SCC4P (INTMEM+0x3F00)
+#define SPIP (INTMEM+0x3D80)
+#define TIMERP (INTMEM+0x3DB0)
+#define SMC1P (INTMEM+0x3E80)
+#define DSP1P (INTMEM+0x3EC0)
+#define SMC2P (INTMEM+0x3F80)
+#define DSP2P (INTMEM+0x3FC0)
+
+#define KEEP_ALIVE_KEY 0x55ccaa33 /* clock and rtc register key */
--- /dev/null
+++ b/os/boot.original/mpc/mkfile
@@ -1,0 +1,116 @@
+objtype=power
+OBJTYPE=power # always
+<../../../mkconfig
+SYSTARG=$OSTARG # always
+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
+INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin #path of directory where kernel is installed
+ARCH=fads # selects board dependent code
+TARG=qb$ARCH
+OFILES=\
+ l.$O\
+ arch$ARCH.$O\
+ devuart.$O\
+ uartboot.$O\
+ alarm.$O\
+ bootp.$O\
+ clock.$O\
+ conf.$O\
+ console.$O\
+ cpm.$O\
+ defont0.$O\
+ donprint.$O\
+ dosboot.$O\
+ devether.$O\
+ etherscc.$O\
+ fblt.$O\
+ gbitbltclip.$O\
+ flash.$O\
+ main.$O\
+ plan9boot.$O\
+ qio.$O\
+ rmap.$O\
+ screen.$O\
+ init$ARCH.$O\
+ trap.$O\
+ zqs.$O\
+
+HFILES=\
+ boot.h\
+ dat.h\
+ fns.h\
+ io.h\
+ lib.h\
+ mem.h\
+ squeeze.h\
+ gnot.h\
+ arch$ARCH.h\
+
+LIBS=\
+ kern\
+
+LIBDIRS=$LIBS
+LIBNAMES=${LIBS:%=lib%.a}
+LIBFILES=${LIBS:%=$ROOT/$TARGMODEL/$OBJTYPE/lib/lib%.a}
+
+#all:NV: $TARG k.mx f.mx
+all:NV: $TARG
+install:V: $INSTALLDIR/$TARG
+installall:V: $INSTALLDIR/$TARG
+
+$INSTALLDIR/%: %
+ rm -f $INSTALLDIR/$stem && cp $stem $INSTALLDIR/$stem
+
+$TARG: $OFILES $LIBNAMES
+ $LD -o $target -l -T0x140000 -R4 $OFILES $LIBFILES
+ ls -l $target
+
+qbrom$ARCH: $OFILES $LIBNAMES
+ $LD -o $target -l -T0x02800100 -R0 -D0x140000 $OFILES $LIBFILES
+
+k.mx: $TARG
+ ms2 -S 0x100 -a 0x100 -p 4 $TARG >k.mx
+
+f.mx: qbrom$ARCH
+ ms2 -S 0x100 -a 0x2800100 -p 4 $prereq >f.mx
+
+%.$O: %.s
+ $AS $stem.s
+
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+
+%.$O: $HFILES
+
+lib%.a:V: $SHELLTYPE-lib%.a
+
+rc-lib%.a nt-lib%.a:VQ:
+ echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
+ @{builtin cd $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
+
+sh-lib%.a:VQ:
+ echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
+ (cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
+
+clock.$O floppy.$O trap.$O: ureg.h
+conf.$O dosboot.$O main.$O: dosfs.h
+ether.$O etherscc.$O: etherif.h
+bootp.$O: ip.h
+
+clean:V:
+ rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG qboot k.mx f.mx romboot
+
+nuke-sh:QV:
+ for i in $LIBDIRS
+ do
+ echo "(cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke)"
+ (cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke)
+ done
+
+nuke-rc nuke-nt:QV:
+ for (i in $LIBDIRS)
+ {
+ echo '@{cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke}'
+ @{cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke}
+ }
+
+nuke:V: clean nuke-$SHELLTYPE
--- /dev/null
+++ b/os/boot.original/mpc/ms2.c
@@ -1,0 +1,179 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+void record(uchar*, int);
+void usage(void);
+void dosegment(long, int);
+void trailer(ulong);
+
+enum
+{
+ Recordsize = 32,
+};
+
+int dsegonly;
+int supressend;
+int binary;
+int addr4;
+ulong addr;
+ulong psize = 4096;
+ulong startaddr = 0x030000;
+Biobuf stdout;
+Biobuf bio;
+
+void
+main(int argc, char **argv)
+{
+ Dir dir;
+ Fhdr f;
+ int fd;
+
+ ARGBEGIN{
+ case 'd':
+ dsegonly++;
+ break;
+ case 's':
+ supressend++;
+ break;
+ case 'a':
+ addr = strtoul(ARGF(), 0, 0);
+ break;
+ case 'p':
+ psize = strtoul(ARGF(), 0, 0);
+ break;
+ case 'b':
+ binary++;
+ break;
+ case 'S':
+ startaddr = strtoul(ARGF(), 0, 0);
+ break;
+ case '4':
+ addr4++;
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if(argc != 1)
+ usage();
+
+ Binit(&stdout, 1, OWRITE);
+
+ fd = open(argv[0], OREAD);
+ if(fd < 0) {
+ fprint(2, "ms2: open %s: %r\n", argv[0]);
+ exits("open");
+ }
+
+ if(binary) {
+ if(dirfstat(fd, &dir) < 0) {
+ fprint(2, "ms2: stat failed %r");
+ exits("dirfstat");
+ }
+ Binit(&bio, fd, OREAD);
+ dosegment(0, dir.length);
+ if(supressend == 0)
+ trailer(startaddr);
+ Bterm(&stdout);
+ Bterm(&bio);
+ exits(0);
+ }
+
+ if(crackhdr(fd, &f) == 0){
+ fprint(2, "ms2: bad magic: %r\n");
+ exits("magic");
+ }
+ seek(fd, 0, 0);
+
+ Binit(&bio, fd, OREAD);
+
+ if(dsegonly)
+ dosegment(f.datoff, f.datsz);
+ else {
+ dosegment(f.txtoff, f.txtsz);
+ addr = (addr+(psize-1))&~(psize-1);
+ dosegment(f.datoff, f.datsz);
+ }
+
+ if(supressend == 0)
+ trailer(startaddr);
+
+ Bterm(&stdout);
+ Bterm(&bio);
+ exits(0);
+}
+
+void
+dosegment(long foff, int len)
+{
+ int l, n;
+ uchar buf[2*Recordsize];
+
+ Bseek(&bio, foff, 0);
+ for(;;) {
+ l = len;
+ if(l > Recordsize)
+ l = Recordsize;
+ n = Bread(&bio, buf, l);
+ if(n == 0)
+ break;
+ if(n < 0) {
+ fprint(2, "ms2: read error: %r\n");
+ exits("read");
+ }
+ record(buf, l);
+ len -= l;
+ }
+}
+
+void
+record(uchar *s, int l)
+{
+ int i;
+ ulong cksum;
+
+ if(addr4 || addr & (0xFF<<24)){
+ Bprint(&stdout, "S3%.2X%.8luX", l+5, addr);
+ cksum = l+5;
+ cksum += (addr>>24)&0xff;
+ }else{
+ Bprint(&stdout, "S2%.2X%.6X", l+4, addr);
+ cksum = l+4;
+ }
+ cksum += addr&0xff;
+ cksum += (addr>>8)&0xff;
+ cksum += (addr>>16)&0xff;
+
+ for(i = 0; i < l; i++) {
+ cksum += *s;
+ Bprint(&stdout, "%.2X", *s++);
+ }
+ Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
+ addr += l;
+}
+
+void
+trailer(ulong a)
+{
+ ulong cksum;
+
+ cksum = 0;
+ if(addr4 || a & (0xFF<<24)){
+ Bprint(&stdout, "S7%.8luX", a);
+ cksum += (a>>24)&0xff;
+ }else
+ Bprint(&stdout, "S9%.6X", a);
+ cksum += a&0xff;
+ cksum += (a>>8)&0xff;
+ cksum += (a>>16)&0xff;
+ Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: ms2 [-ds] [-a address] [-p pagesize] ?.out\n");
+ exits("usage");
+}
--- /dev/null
+++ b/os/boot.original/mpc/plan9boot.c
@@ -1,0 +1,96 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+char *premature = "premature EOF\n";
+
+/*
+ * read in a segment
+ */
+static long
+readseg(int dev, long (*read)(int, void*, long), long len, long addr)
+{
+ char *a;
+ long n, sofar;
+
+ a = (char *)addr;
+ for(sofar = 0; sofar < len; sofar += n){
+ n = 8*1024;
+ if(len - sofar < n)
+ n = len - sofar;
+ n = (*read)(dev, a + sofar, n);
+ if(n <= 0)
+ break;
+ print(".");
+ }
+ return sofar;
+}
+
+/*
+ * boot
+ */
+int
+plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
+{
+ long n;
+ long addr;
+ void (*b)(void);
+ Exec *ep;
+
+ if((*seek)(dev, 0) < 0)
+ return -1;
+
+ /*
+ * read header
+ */
+ ep = (Exec *) ialloc(sizeof(Exec), 0);
+ n = sizeof(Exec);
+ if(readseg(dev, read, n, (long) ep) != n){
+ print(premature);
+ return -1;
+ }
+ if(GLLONG(ep->magic) != Q_MAGIC){
+ print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+ return -1;
+ }
+
+ /*
+ * read text
+ */
+ addr = PADDR(GLLONG(ep->entry));
+ n = GLLONG(ep->text);
+ print("%d", n);
+ if(readseg(dev, read, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * read data (starts at first page after kernel)
+ */
+ addr = PGROUND(addr+n);
+ n = GLLONG(ep->data);
+ print("+%d@%8.8lux", n, addr);
+ if(readseg(dev, read, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * bss and entry point
+ */
+ print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
+ uartwait();
+ scc2stop();
+ splhi();
+
+ /*
+ * Go to new code. It's up to the program to get its PC relocated to
+ * the right place.
+ */
+ b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+ (*b)();
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/qio.c
@@ -1,0 +1,128 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+struct Queue {
+ Block* first;
+ Block* last;
+ void (*kick)(void*);
+ void* arg;
+ long len;
+};
+
+Block *
+iallocb(int n)
+{
+ Block *b;
+
+ b = (Block*)malloc(sizeof(Block)+n);
+ b->data = (uchar*)b + sizeof(Block);
+ b->rp = b->wp = b->data;
+ b->lim = b->data + n;
+ b->next = 0;
+ b->magic = 0xcafebee0;
+ return b;
+}
+
+void
+freeb(Block *b)
+{
+ if(b){
+ if(b->magic != 0xcafebee0)
+ panic("freeb");
+ b->magic = 0;
+ b->next = (Block*)0xdeadbabe;
+ free(b);
+ }
+}
+
+Queue *
+qopen(int limit, int msg, void (*kick)(void*), void *arg)
+{
+ Queue *q;
+
+ USED(limit, msg);
+ q = (Queue*)malloc(sizeof(Queue));
+ q->first = q->last = 0;
+ q->kick = kick;
+ q->arg = arg;
+ q->len = 0;
+ return q;
+}
+
+Block *
+qget(Queue *q)
+{
+ int s;
+ Block *b;
+
+ s = splhi();
+ if((b = q->first) != 0){
+ q->first = b->next;
+ b->next = 0;
+ q->len -= BLEN(b);
+ if(q->len < 0)
+ panic("qget");
+ }
+ splx(s);
+ return b;
+}
+
+void
+qbwrite(Queue *q, Block *b)
+{
+ int s;
+
+ s = splhi();
+ b->next = 0;
+ if(q->first == 0)
+ q->first = b;
+ else
+ q->last->next = b;
+ q->last = b;
+ q->len += BLEN(b);
+ splx(s);
+ if(q->kick)
+ q->kick(q->arg);
+}
+
+long
+qlen(Queue *q)
+{
+ return q->len;
+}
+
+int
+qbgetc(Queue *q)
+{
+ Block *b;
+ int s, c;
+
+ c = -1;
+ s = splhi();
+ while(c < 0 && (b = q->first) != nil){
+ if(b->rp < b->wp){
+ c = *b->rp++;
+ q->len--;
+ }
+ if(b->rp >= b->wp){
+ q->first = b->next;
+ b->next = nil;
+ }
+ }
+ splx(s);
+ return c;
+}
+
+void
+qbputc(Queue *q, int c)
+{
+ Block *b;
+
+ b = iallocb(1);
+ *b->wp++ = c;
+ qbwrite(q, b);
+}
--- /dev/null
+++ b/os/boot.original/mpc/rmap.c
@@ -1,0 +1,104 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+void
+mapinit(RMap *rmap, Map *map, int size)
+{
+ lock(rmap);
+ rmap->map = map;
+ rmap->mapend = map+(size/sizeof(Map));
+ unlock(rmap);
+}
+
+void
+mapfree(RMap* rmap, ulong addr, int size)
+{
+ Map *mp;
+ ulong t;
+
+ if(size <= 0)
+ return;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
+ ;
+
+ if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
+ (mp-1)->size += size;
+ if(addr+size == mp->addr){
+ (mp-1)->size += mp->size;
+ while(mp->size){
+ mp++;
+ (mp-1)->addr = mp->addr;
+ (mp-1)->size = mp->size;
+ }
+ }
+ }
+ else{
+ if(addr+size == mp->addr && mp->size){
+ mp->addr -= size;
+ mp->size += size;
+ }
+ else do{
+ if(mp >= rmap->mapend){
+ print("mapfree: %s: losing 0x%uX, %d\n",
+ rmap->name, addr, size);
+ break;
+ }
+ t = mp->addr;
+ mp->addr = addr;
+ addr = t;
+ t = mp->size;
+ mp->size = size;
+ mp++;
+ }while(size = t);
+ }
+ unlock(rmap);
+}
+
+ulong
+mapalloc(RMap* rmap, ulong addr, int size, int align)
+{
+ Map *mp;
+ ulong maddr, oaddr;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->size; mp++){
+ maddr = mp->addr;
+
+ if(addr){
+ if(maddr > addr)
+ continue;
+ if(addr+size > maddr+mp->size)
+ break;
+ maddr = addr;
+ }
+
+ if(align > 0)
+ maddr = ((maddr+align-1)/align)*align;
+ if(mp->addr+mp->size-maddr < size)
+ continue;
+
+ oaddr = mp->addr;
+ mp->addr = maddr+size;
+ mp->size -= maddr-oaddr+size;
+ if(mp->size == 0){
+ do{
+ mp++;
+ (mp-1)->addr = mp->addr;
+ }while((mp-1)->size = mp->size);
+ }
+
+ unlock(rmap);
+ if(oaddr != maddr)
+ mapfree(rmap, oaddr, maddr-oaddr);
+
+ return maddr;
+ }
+ unlock(rmap);
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/mpc/screen.c
@@ -1,0 +1,242 @@
+#include "all.h"
+#include <libg.h>
+#include <gnot.h>
+
+enum {
+ Colldepth = 3,
+ Colmaxx = 640,
+ Colmaxxvis = 640,
+ Colmaxy = 480,
+};
+
+#define MINX 8
+
+extern GSubfont defont0;
+
+struct{
+ Point pos;
+ int bwid;
+}out;
+
+typedef struct Mode Mode;
+struct Mode {
+ int x;
+ int y;
+ int d;
+ char* aperture;
+ int apsize;
+};
+
+GBitmap gscreen;
+Point gchar(GBitmap*, Point, GFont*, int, Fcode);
+int setcolor(ulong, ulong, ulong, ulong);
+static void lcdinit(Mode*);
+
+void
+screeninit(void)
+{
+ Mode m;
+
+ m.x = Colmaxx;
+ m.y = Colmaxy;
+ m.d = Colldepth;
+ m.aperture = 0;
+ lcdinit(&m);
+ if(m.aperture == 0)
+ return;
+ gscreen.ldepth = 3;
+ gscreen.base = (ulong*)m.aperture;
+ gscreen.width = Colmaxx/BY2WD;
+ gscreen.r = Rect(0, 0, Colmaxxvis, Colmaxy);
+ gscreen.clipr = gscreen.r;
+ /*
+ * For now, just use a fixed colormap:
+ * 0 == white and 255 == black
+ */
+ setcolor(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+ setcolor(255, 0x00000000, 0x00000000, 0x00000000);
+
+ gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, Zero);
+ out.pos.x = MINX;
+ out.pos.y = 0;
+ out.bwid = defont0.info[' '].width;
+}
+
+void
+screenputc(int c)
+{
+ Fontchar *i;
+ Point p;
+
+ if(gscreen.base == nil)
+ return;
+ switch(c){
+ case '\n':
+ out.pos.x = MINX;
+ out.pos.y += defont0.height;
+ if(out.pos.y > gscreen.r.max.y-defont0.height)
+ out.pos.y = gscreen.r.min.y;
+ gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
+ Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height),
+ Zero);
+ break;
+ case '\t':
+ out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
+ if(out.pos.x >= gscreen.r.max.x)
+ screenputc('\n');
+ break;
+ case '\b':
+ if(out.pos.x >= out.bwid+MINX){
+ out.pos.x -= out.bwid;
+ screenputc(' ');
+ out.pos.x -= out.bwid;
+ }
+ break;
+ default:
+ if(out.pos.x >= gscreen.r.max.x-out.bwid)
+ screenputc('\n');
+ c &= 0x7f;
+ if(c <= 0 || c >= defont0.n)
+ break;
+ i = defont0.info + c;
+ p = out.pos;
+ gbitblt(&gscreen, Pt(p.x+i->left, p.y), defont0.bits,
+ Rect(i[0].x, 0, i[1].x, defont0.height),
+ S);
+ out.pos.x = p.x + i->width;
+ break;
+ }
+}
+
+void
+screenputs(char *s, int n)
+{
+ while(n-- > 0)
+ screenputc(*s++);
+}
+
+/*
+ * See section 5.2.1 (page 5-6) of the MPC823 manual
+ */
+static uchar lcdclock[17] = { /* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */
+ 0, 0, (1<<2), 1,
+ (2<<2), 2, (1<<2)|1, 3,
+ (3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1,
+ (2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2),
+ (4<<2)
+};
+
+/*
+ * support for the Sharp LQ64D341 TFT colour display
+ */
+
+enum {
+ COLS = 640,
+ ROWS = 480,
+ LDEPTH = 3, /* screen depth */
+ LCDFREQ = 25000000,
+
+ /* lccr */
+ ClockLow = 1<<11,
+ OELow = 1<<10,
+ HsyncLow = 1<<9,
+ VsyncLow = 1<<8,
+ DataLow = 1<<7,
+ Passive8 = 1<<4,
+ DualScan = 1<<3,
+ IsColour = 1<<2,
+ IsTFT = 1<<1,
+ Enable = 1<<0,
+
+ /* lchcr */
+ BigEndian = 1<<24,
+ AT7 = 7<<21, /* access type */
+
+ /* sdcr */
+ LAM = 1<<6, /* ``LCD aggressive mode'' */
+};
+
+/*
+ * TO DO: most of the data could come from a table
+ */
+static void
+lcdinit(Mode *mode)
+{
+ IMM *io;
+ int i, d;
+ long hz;
+
+ io = m->iomem;
+ mode->y = ROWS;
+ mode->x = COLS;
+ mode->d = LDEPTH;
+ mode->aperture = ialloc(mode->x*mode->y, 16);
+ mode->apsize = mode->x*mode->y;
+
+ io->sdcr &= ~LAM; /* MPC823 errata: turn off LAM before disabling controller */
+ io->lcfaa = PADDR(mode->aperture);
+ io->lccr = (((mode->x*mode->y*(1<<LDEPTH)+127)/128) << 17) | (LDEPTH << 5) | IsColour | IsTFT | OELow | VsyncLow | ClockLow;
+
+ switch(LDEPTH){
+ default:
+ case 0:
+ /* monochrome/greyscale identity map */
+ for(i=0; i<16; i++)
+ io->lcdmap[i] = i;
+ break;
+ case 2:
+ /* 4-bit grey scale map */
+ for(i=0; i<16; i++)
+ io->lcdmap[0] = (i<<8)|(i<<4)|i;
+ break;
+ case 3:
+ /* 8-bit linear map */
+ for(i=0; i<256; i++)
+ io->lcdmap[i] = (i<<8)|(i<<4)|i;
+ break;
+ }
+
+ io->lcvcr = (mode->y << 11) | (1<<28) | 33; /* 2 line vsync pulse, 34 line wait between frames */
+ io->lchcr = (mode->x<<10) | BigEndian | 228; /* clock cycles between lines */
+
+ hz = m->cpuhz;
+ d = hz/LCDFREQ;
+ if(hz/d > LCDFREQ)
+ d++;
+ if(d >= 16)
+ d = 16;
+
+ /*
+ * enable LCD outputs
+ */
+ io->pddat = 0;
+ io->pdpar = 0x1fff;
+io->pdpar &= ~SIBIT(6); /* 823 bug fix? */
+ io->pddir = 0x1fff;
+ io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17);
+ io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17);
+ io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17));
+
+ eieio();
+ io->sccrk = KEEP_ALIVE_KEY;
+ eieio();
+ io->sccr = (io->sccr & ~0x1F) | lcdclock[d];
+ eieio();
+ io->sccrk = ~KEEP_ALIVE_KEY;
+ eieio();
+ gscreen.width = gscreen.width; /* access external memory before enabling (mpc823 errata) */
+ io->lcsr = 7; /* clear status */
+ eieio();
+ io->lccr |= Enable;
+ archbacklight(1);
+}
+
+int
+setcolor(ulong p, ulong r, ulong g, ulong b)
+{
+ r >>= 28;
+ g >>= 28;
+ b >>= 28;
+ m->iomem->lcdmap[~p&0xFF] = (r<<8) | (g<<4) | b; /* TO DO: it's a function of the ldepth */
+ return 1;
+}
--- /dev/null
+++ b/os/boot.original/mpc/sload.c
@@ -1,0 +1,71 @@
+/*
+ * send S records to rpcg
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+static int dbg;
+static char buf[2048];
+static int run=1;
+static void stuffbym(char*, int, int);
+static void getdot(void);
+
+void
+main(int argc, char **argv)
+{
+ int n;
+ char *l;
+ Biobuf *f;
+ static int p;
+
+ ARGBEGIN{
+ case 'd': dbg++; break;
+ case 'n': run=0; break;
+ }ARGEND
+
+ f = Bopen(*argv? *argv: "k.mx", OREAD);
+ if(f == 0) {
+ fprint(2, "sload: cannot open k.mx: %r\n");
+ exits("sload");
+ }
+ getdot();
+ while((l = Brdline(f, '\n')) != 0) {
+ l[Blinelen(f)-1] = '\r';
+ stuffbym(l, Blinelen(f), 16);
+ getdot();
+ if(++p % 25 == 0)
+ write(2, ".", 1);
+ }
+ exits(0);
+}
+
+static void
+stuffbym(char *l, int n, int m)
+{
+ int nr, ns;
+
+ while(n > 0) {
+ ns = n;
+ if(ns > m)
+ ns = m;
+ write(1, l, ns);
+ l += ns;
+ n -= ns;
+ }
+}
+
+static void
+getdot(void)
+{
+ char c;
+
+ for(;;){
+ if(read(0, &c, 1) != 1)
+ exits("bang");
+ write(2, &c, 1);
+ if(c == '.')
+ break;
+ }
+}
--- /dev/null
+++ b/os/boot.original/mpc/squeeze.h
@@ -1,0 +1,34 @@
+
+/*
+ * squeezed file format:
+ * Sqhdr
+ * original Exec header
+ * two Squeeze tables
+ * squeezed segment
+ * unsqueezed segment, if any
+ */
+#define SQMAGIC (ulong)0xFEEF0F1E
+
+typedef struct Sqhdr Sqhdr;
+struct Sqhdr {
+ uchar magic[4]; /* SQMAGIC */
+ uchar text[4]; /* squeezed length of text (excluding tables) */
+ uchar data[4]; /* squeezed length of data (excluding tables) */
+ uchar asis[4]; /* length of unsqueezed segment */
+ uchar toptxt[4]; /* value for 0 encoding in text */
+ uchar topdat[4]; /* value for 0 encoding in data */
+ uchar sum[4]; /* simple checksum of unsqueezed data */
+ uchar flags[4];
+};
+#define SQHDRLEN (8*4)
+
+/*
+ * certain power instruction types are rearranged by sqz
+ * so as to move the variable part of the instruction word to the
+ * low order bits. note that the mapping is its own inverse.
+ */
+#define QREMAP(X)\
+ switch((X)>>26){\
+ case 19: case 31: case 59: case 63:\
+ (X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
+ }
--- /dev/null
+++ b/os/boot.original/mpc/trap.c
@@ -1,0 +1,233 @@
+#include "boot.h"
+
+enum
+{
+ Maxhandler= 32+16, /* max number of interrupt handlers */
+};
+
+typedef struct Handler Handler;
+struct Handler
+{
+ void (*r)(Ureg*, void*);
+ void *arg;
+ Handler *next;
+ int edge;
+};
+
+struct
+{
+ Handler *ivec[128];
+ Handler h[Maxhandler];
+ int free;
+} halloc;
+
+char *excname[] = {
+ "reserved 0",
+ "system reset",
+ "machine check",
+ "data access",
+ "instruction access",
+ "external interrupt",
+ "alignment",
+ "program exception",
+ "floating-point unavailable",
+ "decrementer",
+ "reserved A",
+ "reserved B",
+ "system call",
+ "trace trap",
+ "floating point assist",
+ "reserved F",
+ "software emulation",
+ "ITLB miss",
+ "DTLB miss",
+ "ITLB error",
+ "DTLB error",
+};
+
+char *regname[]={
+ "CAUSE", "SRR1",
+ "PC", "GOK",
+ "LR", "CR",
+ "XER", "CTR",
+ "R0", "R1",
+ "R2", "R3",
+ "R4", "R5",
+ "R6", "R7",
+ "R8", "R9",
+ "R10", "R11",
+ "R12", "R13",
+ "R14", "R15",
+ "R16", "R17",
+ "R18", "R19",
+ "R20", "R21",
+ "R22", "R23",
+ "R24", "R25",
+ "R26", "R27",
+ "R28", "R29",
+ "R30", "R31",
+};
+
+static void intr(Ureg*);
+
+void
+sethvec(int v, void (*r)(void))
+{
+ ulong *vp, pa, o;
+
+ if((ulong)r & 3)
+ panic("sethvec");
+ vp = (ulong*)KADDR(v);
+ vp[0] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */
+ vp[1] = 0x7c0802a6; /* MOVW LR, R0 */
+ vp[2] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */
+ pa = PADDR(r);
+ o = pa >> 25;
+ if(o != 0 && o != 0x7F){
+ /* a branch too far: running from ROM */
+ vp[3] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
+ vp[4] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
+ vp[5] = 0x7c0803a6; /* MOVW R0, LR */
+ vp[6] = 0x4e800021; /* BL (LR) */
+ }else
+ vp[3] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
+}
+
+#define LEV(n) (((n)<<1)|1)
+#define IRQ(n) (((n)<<1)|0)
+
+void
+setvec(int v, void (*r)(Ureg*, void*), void *arg)
+{
+ Handler *h;
+ IMM *io;
+
+ if(halloc.free >= Maxhandler)
+ panic("out of interrupt handlers");
+ v -= VectorPIC;
+ h = &halloc.h[halloc.free++];
+ h->next = halloc.ivec[v];
+ h->r = r;
+ h->arg = arg;
+ halloc.ivec[v] = h;
+
+ /*
+ * enable corresponding interrupt in SIU/CPM
+ */
+
+ io = m->iomem;
+ if(v >= VectorCPIC){
+ v -= VectorCPIC;
+ io->cimr |= 1<<(v&0x1F);
+ }
+ else if(v >= VectorIRQ)
+ io->simask |= 1<<(31-IRQ(v&7));
+ else
+ io->simask |= 1<<(31-LEV(v));
+}
+
+void
+trapinit(void)
+{
+ int i;
+ IMM *io;
+
+ io = m->iomem;
+ io->sypcr &= ~(3<<2); /* disable watchdog (821/823) */
+ io->simask = 0; /* mask all */
+ io->siel = ~0; /* edge sensitive, wake on all */
+ io->cicr = 0; /* disable CPM interrupts */
+ io->cipr = ~0; /* clear all interrupts */
+ io->cimr = 0; /* mask all events */
+ io->cicr = (0xE1<<16)|(CPIClevel<<13)|(0x1F<<8);
+ io->cicr |= 1 << 7; /* enable */
+ io->tbscrk = KEEP_ALIVE_KEY;
+ io->tbscr = 1; /* TBE */
+ io->simask |= 1<<(31-LEV(CPIClevel)); /* CPM's level */
+ io->tbk = KEEP_ALIVE_KEY;
+ eieio();
+ putdec(~0);
+
+ /*
+ * set all exceptions to trap
+ */
+ for(i = 0x0; i < 0x3000; i += 0x100)
+ sethvec(i, exception);
+}
+
+void
+dumpregs(Ureg *ur)
+{
+ int i;
+ ulong *l;
+ l = &ur->cause;
+ for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
+ print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
+}
+
+void
+trap(Ureg *ur)
+{
+ int c;
+
+ c = ur->cause >> 8;
+ switch(c){
+ default:
+ {extern int predawn; predawn = 1;}
+ if(c < 0 || c >= nelem(excname))
+ print("exception/interrupt #%x\n", c);
+ else
+ print("exception %s\n", excname[c]);
+ dumpregs(ur);
+ /* spllo(); */
+ print("^P to reset\n");
+ for(;;)
+ ;
+
+ case 0x09: /* decrementer */
+ clockintr(ur, 0);
+ return;
+
+ case 0x05: /* external interrupt */
+ intr(ur);
+ break;
+ }
+}
+
+static void
+intr(Ureg *ur)
+{
+ int b, v;
+ Handler *h;
+ IMM *io;
+
+ io = m->iomem;
+ b = io->sivec>>2;
+ v = b>>1;
+ if(b & 1) {
+ if(v == CPIClevel){
+ io->civr = 1;
+ eieio();
+ v = VectorCPIC+(io->civr>>11);
+ }
+ }else
+ v += VectorIRQ;
+ h = halloc.ivec[v];
+ if(h == nil){
+ for(;;)
+ ;
+ //print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
+ return;
+ }
+ if(h->edge)
+ io->sipend |= 1<<(31-b);
+ /*
+ * call the interrupt handlers
+ */
+ do {
+ (*h->r)(ur, h->arg);
+ h = h->next;
+ } while(h != nil);
+ if(v >= VectorCPIC)
+ io->cisr |= 1<<(v-VectorCPIC);
+}
--- /dev/null
+++ b/os/boot.original/mpc/uartboot.c
@@ -1,0 +1,189 @@
+#include "boot.h"
+
+/*
+ * this doesn't yet use the crc
+ */
+
+typedef struct Uboot Uboot;
+struct Uboot {
+ Queue* iq;
+ Block* partial;
+ ulong csum;
+ long bno;
+ uchar buf[64];
+ int nleft;
+ int ntimeout;
+};
+
+static Uboot uboot;
+ulong crc32(void *buf, int n, ulong crc);
+
+static void
+uartbrecv(uchar *p, int n)
+{
+ Uboot *ub;
+ Block *b;
+
+ ub = &uboot;
+ if(n > 0 && ub->iq != nil){
+ b = iallocb(n);
+ memmove(b->wp, p, n);
+ b->wp += n;
+ qbwrite(ub->iq, b);
+ }
+}
+
+int
+uartinit(void)
+{
+ return 1<<0;
+}
+
+Partition*
+setuartpart(int, char *s)
+{
+ static Partition pp[1];
+
+ if(strcmp(s, "boot") != 0 && strcmp(s, "disk") != 0)
+ return 0;
+ pp[0].start = 0;
+ pp[0].end = 2*1024*1024;
+ strcpy(pp[0].name, "boot");
+ return pp;
+}
+
+long
+uartseek(int, long)
+{
+ /* start the boot */
+ if(uboot.iq == nil)
+ uboot.iq = qopen(64*1024, 0, 0, 0);
+ if(uboot.partial){
+ freeb(uboot.partial);
+ uboot.partial = 0;
+ }
+ print("uart: start transmission\n");
+ uartsetboot(uartbrecv);
+ uboot.csum = ~0;
+ uboot.bno = 0;
+ uboot.nleft = 0;
+ uboot.ntimeout = 0;
+ return 0;
+}
+
+static long
+uartreadn(void *buf, int nb)
+{
+ ulong start;
+ Uboot *ub;
+ int l;
+ Block *b;
+ uchar *p;
+
+ p = buf;
+ ub = &uboot;
+ start = m->ticks;
+ while(nb > 0){
+ b = ub->partial;
+ ub->partial = nil;
+ if(b == nil){
+ ub->ntimeout = 0;
+ while((b = qget(ub->iq)) == 0){
+ if(TK2MS(m->ticks - start) >= 15*1000){
+ if(++ub->ntimeout >= 3){
+ print("uart: timeout\n");
+ return 0;
+ }
+ uartputs("n", 1);
+ }
+ }
+ }
+ l = BLEN(b);
+ if(l > nb)
+ l = nb;
+ memmove(p, b->rp, l);
+ b->rp += l;
+ if(b->rp >= b->wp)
+ freeb(b);
+ else
+ ub->partial = b;
+ nb -= l;
+ p += l;
+ }
+ return p-(uchar*)buf;
+}
+
+long
+uartread(int, void *buf, long n)
+{
+ uchar *p;
+ int l;
+ static uchar lbuf[64];
+
+ p = buf;
+ if((l = uboot.nleft) > 0){
+ if(l > n)
+ l = n;
+ uboot.nleft -= l;
+ memmove(p, uboot.buf, l);
+ p += l;
+ n -= l;
+ }
+ while(n > 0){
+ l = uartreadn(lbuf, sizeof(lbuf));
+ if(l < sizeof(lbuf))
+ return 0;
+ if(l > n){
+ uboot.nleft = l-n;
+ memmove(uboot.buf, lbuf+n, uboot.nleft);
+ l = n;
+ }
+ memmove(p, lbuf, l);
+ n -= l;
+ p += l;
+ uboot.bno++;
+ uartputs("y", 1);
+ }
+ return p-(uchar*)buf;
+}
+
+/*
+ * from Rob Warnock
+ */
+static ulong crc32tab[256]; /* initialised on first call to crc32 */
+
+enum {
+ CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+ int i, j;
+ ulong c;
+
+ for(i = 0; i < 256; i++) {
+ for(c = i << 24, j = 8; j > 0; j--)
+ if(c & (1<<31))
+ c = (c<<1) ^ CRC32POLY;
+ else
+ c <<= 1;
+ crc32tab[i] = c;
+ }
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+ uchar *p;
+
+ if(crc32tab[1] == 0)
+ initcrc32();
+ crc = ~crc;
+ for(p = buf; --n >= 0;)
+ crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+ return ~crc;
+}
--- /dev/null
+++ b/os/boot.original/mpc/ureg.h
@@ -1,0 +1,43 @@
+struct Ureg
+{
+ ulong cause;
+ union { ulong srr1; ulong status;};
+ ulong pc; /* SRR0 */
+ ulong pad;
+ ulong lr;
+ ulong cr;
+ ulong xer;
+ ulong ctr;
+ ulong r0;
+ union{ ulong r1; ulong sp; ulong usp; };
+ ulong r2;
+ ulong r3;
+ ulong r4;
+ ulong r5;
+ ulong r6;
+ ulong r7;
+ ulong r8;
+ ulong r9;
+ ulong r10;
+ ulong r11;
+ ulong r12;
+ ulong r13;
+ ulong r14;
+ ulong r15;
+ ulong r16;
+ ulong r17;
+ ulong r18;
+ ulong r19;
+ ulong r20;
+ ulong r21;
+ ulong r22;
+ ulong r23;
+ ulong r24;
+ ulong r25;
+ ulong r26;
+ ulong r27;
+ ulong r28;
+ ulong r29;
+ ulong r30;
+ ulong r31;
+};
--- /dev/null
+++ b/os/boot.original/mpc/zqs.c
@@ -1,0 +1,234 @@
+#include "boot.h"
+#include "squeeze.h"
+
+/*
+ * for details of `unsqueeze' see:
+ *
+ * %A Mark Taunton
+ * %T Compressed Executables: An Exercise in Thinking Small
+ * %P 385-404
+ * %I USENIX
+ * %B USENIX Conference Proceedings
+ * %D Summer 1991
+ * %C Nashville, TN
+ *
+ * several of the unimplemented improvements described in the paper
+ * have been implemented here
+ *
+ * there is a further transformation on the powerpc (QFLAG!=0) to shuffle bits
+ * in certain instructions so as to push the fixed bits to the top of the word.
+ */
+
+#define EXECHDRLEN (8*4)
+
+typedef struct Squeeze Squeeze;
+struct Squeeze {
+ int n;
+ ulong tab[7*256];
+};
+
+#define GET4(p) (((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
+
+/*
+ * for speed of unsqueezing from Flash, certain checks are
+ * not done inside the loop (as they would be in the unsqueeze program zqs),
+ * but instead the checksum is expected to catch corrupted files.
+ * in fact the Squeeze array bounds can't be exceeded in practice
+ * because the tables are always full for a squeezed kernel.
+ */
+enum {
+ QFLAG = 1, /* invert powerpc-specific code transformation */
+ CHECK = 0, /* check precise bounds in Squeeze array (otherwise checksum detects error) */
+};
+
+static ulong chksum;
+static int rdtab(Block*, Squeeze*, int);
+static ulong* unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
+static uchar* unsqzseg(uchar*, Block*, long, long, char*);
+static Alarm* unsqzal;
+
+int
+issqueezed(uchar *b)
+{
+ return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
+}
+
+static void
+unsqzdot(Alarm*)
+{
+ unsqzal = alarm(500, unsqzdot, nil);
+ print(".");
+}
+
+long
+unsqueezef(Block *b, ulong *entryp)
+{
+ uchar *loada, *wp;
+ ulong toptxt, topdat, oldsum;
+ long asis, nst, nsd;
+ Sqhdr *sqh;
+ Exec *ex;
+
+ if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
+ return -1;
+ sqh = (Sqhdr*)b->rp;
+ if(GET4(sqh->magic) != SQMAGIC)
+ return -1;
+ chksum = 0;
+ toptxt = GET4(sqh->toptxt);
+ topdat = GET4(sqh->topdat);
+ oldsum = GET4(sqh->sum);
+ asis = GET4(sqh->asis);
+ nst = GET4(sqh->text);
+ nsd = GET4(sqh->data);
+ b->rp += SQHDRLEN;
+ ex = (Exec*)b->rp;
+ if(GET4(ex->magic) != Q_MAGIC){
+ print("zqs: not powerPC executable\n");
+ return -1;
+ }
+ *entryp = GET4(ex->entry);
+ b->rp += EXECHDRLEN;
+ loada = KADDR(PADDR(*entryp));
+ wp = unsqzseg(loada, b, nst, toptxt, "text");
+ if(wp == nil){
+ print("zqs: format error\n");
+ return -1;
+ }
+ if(nsd){
+ wp = (uchar*)PGROUND((ulong)wp);
+ wp = unsqzseg(wp, b, nsd, topdat, "data");
+ if(wp == nil){
+ print("zqs: format error\n");
+ return -1;
+ }
+ }
+ if(asis){
+ memmove(wp, b->rp, asis);
+ wp += asis;
+ b->rp += asis;
+ }
+ if(chksum != oldsum){
+ print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
+ return -1;
+ }
+ return wp-loada;
+}
+
+static uchar *
+unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
+{
+ static Squeeze sq3, sq4;
+
+ print("unpack %s %8.8lux %lud:", what, wp, ns);
+ if(ns == 0)
+ return wp;
+ if(rdtab(b, &sq3, 0) < 0)
+ return nil;
+ if(rdtab(b, &sq4, 8) < 0)
+ return nil;
+ if(BLEN(b) < ns){
+ print(" **size error\n");
+ return nil;
+ }
+ unsqzal = alarm(500, unsqzdot, nil);
+ wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
+ cancel(unsqzal);
+ unsqzal = nil;
+ print("\n");
+ if(wp == nil){
+ print("zqs: corrupt squeezed data stream\n");
+ return nil;
+ }
+ b->rp += ns;
+ return wp;
+}
+
+static ulong*
+unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
+{
+ ulong nx, csum;
+ int code, n;
+
+ if(QFLAG){
+ QREMAP(top); /* adjust top just once, outside the loop */
+ }
+ csum = chksum;
+ while(rp < ep){
+ /* no function calls within this loop for speed */
+ code = *rp;
+ rp++;
+ n = 0;
+ nx = code>>4;
+ do{
+ if(nx == 0){
+ nx = top;
+ }else{
+ if(nx==1){
+ nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
+ rp += 4;
+ }else if(nx <= 8){ /* 2 to 8 */
+ nx = ((nx-2)<<8) | rp[0];
+ if(CHECK && nx >= sq4->n)
+ return nil; /* corrupted file */
+ nx = sq4->tab[nx] | rp[1];
+ rp += 2;
+ }else{ /* 9 to 15 */
+ nx = ((nx-9)<<8) | rp[0];
+ if(CHECK && nx >= sq3->n)
+ return nil; /* corrupted file */
+ nx = sq3->tab[nx];
+ rp++;
+ }
+ if(rp > ep)
+ return nil; /* corrupted file */
+ if(QFLAG){
+ QREMAP(nx);
+ }
+ }
+ *wp = nx;
+ wp++;
+ csum += nx;
+ nx = code & 0xF;
+ }while(++n == 1);
+ }
+ chksum = csum;
+ return wp;
+}
+
+static int
+rdtab(Block *b, Squeeze *sq, int shift)
+{
+ uchar *p, *ep;
+ ulong v, w;
+ int i;
+
+ if(BLEN(b) < 2)
+ return -1;
+ i = (b->rp[0]<<8) | b->rp[1];
+ if(1)
+ print(" T%d", i);
+ b->rp += 2;
+ if((i -= 2) > 0){
+ if(BLEN(b) < i)
+ return -1;
+ }
+ sq->n = 0;
+ p = b->rp;
+ ep = b->rp+i;
+ b->rp += i;
+ v = 0;
+ while(p < ep){
+ w = 0;
+ do{
+ if(p >= ep)
+ return -1;
+ w = (w<<7) | (*p & 0x7F);
+ }while(*p++ & 0x80);
+ v += w;
+ if(0)
+ print("%d %8.8lux %8.8lux\n", sq->n, v, w);
+ sq->tab[sq->n++] = v<<shift;
+ }
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/8250.c
@@ -1,0 +1,308 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ * INS8250 uart
+ */
+enum
+{
+ /*
+ * register numbers
+ */
+ Data= 0, /* xmit/rcv buffer */
+ Iena= 1, /* interrupt enable */
+ Ircv= (1<<0), /* for char rcv'd */
+ Ixmt= (1<<1), /* for xmit buffer empty */
+ Irstat=(1<<2), /* for change in rcv'er status */
+ Imstat=(1<<3), /* for change in modem status */
+ Istat= 2, /* interrupt flag (read) */
+ Tctl= 2, /* test control (write) */
+ Format= 3, /* byte format */
+ Bits8= (3<<0), /* 8 bits/byte */
+ Stop2= (1<<2), /* 2 stop bits */
+ Pena= (1<<3), /* generate parity */
+ Peven= (1<<4), /* even parity */
+ Pforce=(1<<5), /* force parity */
+ Break= (1<<6), /* generate a break */
+ Dra= (1<<7), /* address the divisor */
+ Mctl= 4, /* modem control */
+ Dtr= (1<<0), /* data terminal ready */
+ Rts= (1<<1), /* request to send */
+ Ri= (1<<2), /* ring */
+ Inton= (1<<3), /* turn on interrupts */
+ Loop= (1<<4), /* loop back */
+ Lstat= 5, /* line status */
+ Inready=(1<<0), /* receive buffer full */
+ Oerror=(1<<1), /* receiver overrun */
+ Perror=(1<<2), /* receiver parity error */
+ Ferror=(1<<3), /* rcv framing error */
+ Outready=(1<<5), /* output buffer empty */
+ Mstat= 6, /* modem status */
+ Ctsc= (1<<0), /* clear to send changed */
+ Dsrc= (1<<1), /* data set ready changed */
+ Rire= (1<<2), /* rising edge of ring indicator */
+ Dcdc= (1<<3), /* data carrier detect changed */
+ Cts= (1<<4), /* complement of clear to send line */
+ Dsr= (1<<5), /* complement of data set ready line */
+ Ring= (1<<6), /* complement of ring indicator line */
+ Dcd= (1<<7), /* complement of data carrier detect line */
+ Scratch=7, /* scratchpad */
+ Dlsb= 0, /* divisor lsb */
+ Dmsb= 1, /* divisor msb */
+
+ Serial= 0,
+ Modem= 1,
+};
+
+typedef struct Uart Uart;
+struct Uart
+{
+ int port;
+ uchar sticky[8]; /* sticky write register values */
+ uchar txbusy;
+
+ void (*rx)(int); /* routine to take a received character */
+ int (*tx)(void); /* routine to get a character to transmit */
+
+ ulong frame;
+ ulong overrun;
+};
+
+static Uart com[2];
+static Uart* uart;
+
+#define UartFREQ 1843200
+
+#define uartwrreg(u,r,v) outb((u)->port + r, (u)->sticky[r] | (v))
+#define uartrdreg(u,r) inb((u)->port + r)
+
+/*
+ * set the baud rate by calculating and setting the baudrate
+ * generator constant. This will work with fairly non-standard
+ * baud rates.
+ */
+static void
+uartsetbaud(Uart *up, int rate)
+{
+ ulong brconst;
+
+ brconst = (UartFREQ+8*rate-1)/(16*rate);
+
+ uartwrreg(up, Format, Dra);
+ outb(up->port+Dmsb, (brconst>>8) & 0xff);
+ outb(up->port+Dlsb, brconst & 0xff);
+ uartwrreg(up, Format, 0);
+}
+
+/*
+ * toggle DTR
+ */
+static void
+uartdtr(Uart *up, int n)
+{
+ if(n)
+ up->sticky[Mctl] |= Dtr;
+ else
+ up->sticky[Mctl] &= ~Dtr;
+ uartwrreg(up, Mctl, 0);
+}
+
+/*
+ * toggle RTS
+ */
+static void
+uartrts(Uart *up, int n)
+{
+ if(n)
+ up->sticky[Mctl] |= Rts;
+ else
+ up->sticky[Mctl] &= ~Rts;
+ uartwrreg(up, Mctl, 0);
+}
+
+static void
+uartintr(Ureg*, void *arg)
+{
+ Uart *up;
+ int ch;
+ int s, l, loops;
+
+ up = arg;
+ for(loops = 0; loops < 1024; loops++){
+ s = uartrdreg(up, Istat);
+ switch(s & 0x3F){
+ case 6: /* receiver line status */
+ l = uartrdreg(up, Lstat);
+ if(l & Ferror)
+ up->frame++;
+ if(l & Oerror)
+ up->overrun++;
+ break;
+
+ case 4: /* received data available */
+ case 12:
+ ch = inb(up->port+Data);
+ if(up->rx)
+ (*up->rx)(ch);
+ break;
+
+ case 2: /* transmitter empty */
+ ch = -1;
+ if(up->tx)
+ ch = (*up->tx)();
+ if(ch != -1)
+ outb(up->port+Data, ch);
+ else
+ up->txbusy = 0;
+ break;
+
+ case 0: /* modem status */
+ uartrdreg(up, Mstat);
+ break;
+
+ default:
+ if(s&1)
+ return;
+ print("weird modem interrupt #%2.2ux\n", s);
+ break;
+ }
+ }
+ panic("uartintr: 0x%2.2ux\n", uartrdreg(up, Istat));
+}
+
+/*
+ * turn on a port's interrupts. set DTR and RTS
+ */
+static void
+uartenable(Uart *up)
+{
+ /*
+ * turn on interrupts
+ */
+ up->sticky[Iena] = 0;
+ if(up->tx)
+ up->sticky[Iena] |= Ixmt;
+ if(up->rx)
+ up->sticky[Iena] |= Ircv|Irstat;
+ uartwrreg(up, Iena, 0);
+
+ /*
+ * turn on DTR and RTS
+ */
+ uartdtr(up, 1);
+ uartrts(up, 1);
+}
+
+static void
+uartdisable(Uart* up)
+{
+ /*
+ * Disable interrupts.
+ */
+ up->sticky[Iena] = 0;
+ uartwrreg(up, Iena, 0);
+ uartdtr(up, 0);
+ uartrts(up, 0);
+}
+
+void
+uartspecial(int port, void (*rx)(int), int (*tx)(void), int baud)
+{
+ Uart *up;
+ int vector;
+
+ switch(port){
+ case 0:
+ port = 0x3F8;
+ vector = VectorUART0;
+ up = &com[0];
+ break;
+ case 1:
+ port = 0x2F8;
+ vector = VectorUART1;
+ up = &com[1];
+ break;
+ default:
+ return;
+ }
+
+ if(uart != nil && uart != up)
+ uartdisable(uart);
+ uart = up;
+
+ if(up->port == 0){
+ up->port = port;
+ setvec(vector, uartintr, up);
+ }
+
+ /*
+ * set rate to 9600 baud.
+ * 8 bits/character.
+ * 1 stop bit.
+ * interrupts enabled.
+ */
+ uartsetbaud(up, 9600);
+ up->sticky[Format] = Bits8;
+ uartwrreg(up, Format, 0);
+ up->sticky[Mctl] |= Inton;
+ uartwrreg(up, Mctl, 0x0);
+
+ up->rx = rx;
+ up->tx = tx;
+ uartenable(up);
+ if(baud)
+ uartsetbaud(up, baud);
+}
+
+void
+uartputc(int c)
+{
+ int i;
+ Uart *up;
+
+ if((up = uart) == nil)
+ return;
+ for(i = 0; i < 100; i++){
+ if(uartrdreg(up, Lstat) & Outready)
+ break;
+ delay(1);
+ }
+ outb(up->port+Data, c);
+}
+
+void
+uartputs(IOQ *q, char *s, int n)
+{
+ Uart *up;
+ int c, x;
+
+ if((up = uart) == nil)
+ return;
+ while(n--){
+ if(*s == '\n')
+ q->putc(q, '\r');
+ q->putc(q, *s++);
+ }
+ x = splhi();
+ if(up->txbusy == 0 && (c = q->getc(q)) != -1){
+ uartputc(c & 0xFF);
+ up->txbusy = 1;
+ }
+ splx(x);
+}
+
+void
+uartdrain(void)
+{
+ Uart *up;
+ int timeo;
+
+ if((up = uart) == nil)
+ return;
+ for(timeo = 0; timeo < 10000 && up->txbusy; timeo++)
+ delay(1);
+}
--- /dev/null
+++ b/os/boot.original/pc/LICENCE
@@ -1,0 +1,237 @@
+Lucent Public License Version 1.02
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
+PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+ a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
+ Program, and
+ b. in the case of each Contributor,
+
+ i. changes to the Program, and
+ ii. additions to the Program;
+
+ where such changes and/or additions to the Program were added to the
+ Program by such Contributor itself or anyone acting on such
+ Contributor's behalf, and the Contributor explicitly consents, in
+ accordance with Section 3C, to characterization of the changes and/or
+ additions as Contributions.
+
+"Contributor" means LUCENT and any other entity that has Contributed a
+Contribution to the Program.
+
+"Distributor" means a Recipient that distributes the Program,
+modifications to the Program, or any part thereof.
+
+"Licensed Patents" mean patent claims licensable by a Contributor
+which are necessarily infringed by the use or sale of its Contribution
+alone or when combined with the Program.
+
+"Original Program" means the original version of the software
+accompanying this Agreement as released by LUCENT, including source
+code, object code and documentation, if any.
+
+"Program" means the Original Program and Contributions or any part
+thereof
+
+"Recipient" means anyone who receives the Program under this
+Agreement, including all Contributors.
+
+2. GRANT OF RIGHTS
+
+ a. Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free copyright
+ license to reproduce, prepare derivative works of, publicly display,
+ publicly perform, distribute and sublicense the Contribution of such
+ Contributor, if any, and such derivative works, in source code and
+ object code form.
+
+ b. Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free patent
+ license under Licensed Patents to make, use, sell, offer to sell,
+ import and otherwise transfer the Contribution of such Contributor, if
+ any, in source code and object code form. The patent license granted
+ by a Contributor shall also apply to the combination of the
+ Contribution of that Contributor and the Program if, at the time the
+ Contribution is added by the Contributor, such addition of the
+ Contribution causes such combination to be covered by the Licensed
+ Patents. The patent license granted by a Contributor shall not apply
+ to (i) any other combinations which include the Contribution, nor to
+ (ii) Contributions of other Contributors. No hardware per se is
+ licensed hereunder.
+
+ c. Recipient understands that although each Contributor grants the
+ licenses to its Contributions set forth herein, no assurances are
+ provided by any Contributor that the Program does not infringe the
+ patent or other intellectual property rights of any other entity. Each
+ Contributor disclaims any liability to Recipient for claims brought by
+ any other entity based on infringement of intellectual property rights
+ or otherwise. As a condition to exercising the rights and licenses
+ granted hereunder, each Recipient hereby assumes sole responsibility
+ to secure any other intellectual property rights needed, if any. For
+ example, if a third party patent license is required to allow
+ Recipient to distribute the Program, it is Recipient's responsibility
+ to acquire that license before distributing the Program.
+
+ d. Each Contributor represents that to its knowledge it has sufficient
+ copyright rights in its Contribution, if any, to grant the copyright
+ license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A. Distributor may choose to distribute the Program in any form under
+this Agreement or under its own license agreement, provided that:
+
+ a. it complies with the terms and conditions of this Agreement;
+
+ b. if the Program is distributed in source code or other tangible
+ form, a copy of this Agreement or Distributor's own license agreement
+ is included with each copy of the Program; and
+
+ c. if distributed under Distributor's own license agreement, such
+ license agreement:
+
+ i. effectively disclaims on behalf of all Contributors all warranties
+ and conditions, express and implied, including warranties or
+ conditions of title and non-infringement, and implied warranties or
+ conditions of merchantability and fitness for a particular purpose;
+ ii. effectively excludes on behalf of all Contributors all liability
+ for damages, including direct, indirect, special, incidental and
+ consequential damages, such as lost profits; and
+ iii. states that any provisions which differ from this Agreement are
+ offered by that Contributor alone and not by any other party.
+
+B. Each Distributor must include the following in a conspicuous
+ location in the Program:
+
+ Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
+ Reserved.
+
+C. In addition, each Contributor must identify itself as the
+originator of its Contribution in a manner that reasonably allows
+subsequent Recipients to identify the originator of the Contribution.
+Also, each Contributor must agree that the additions and/or changes
+are intended to be a Contribution. Once a Contribution is contributed,
+it may not thereafter be revoked.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use
+of the Program, the Distributor who includes the Program in a
+commercial product offering should do so in a manner which does not
+create potential liability for Contributors. Therefore, if a
+Distributor includes the Program in a commercial product offering,
+such Distributor ("Commercial Distributor") hereby agrees to defend
+and indemnify every Contributor ("Indemnified Contributor") against
+any losses, damages and costs (collectively"Losses") arising from
+claims, lawsuits and other legal actions brought by a third party
+against the Indemnified Contributor to the extent caused by the acts
+or omissions of such Commercial Distributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement.
+In order to qualify, an Indemnified Contributor must: a) promptly
+notify the Commercial Distributor in writing of such claim, and b)
+allow the Commercial Distributor to control, and cooperate with the
+Commercial Distributor in, the defense and any related settlement
+negotiations. The Indemnified Contributor may participate in any such
+claim at its own expense.
+
+For example, a Distributor might include the Program in a commercial
+product offering, Product X. That Distributor is then a Commercial
+Distributor. If that Commercial Distributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Distributor's responsibility
+alone. Under this section, the Commercial Distributor would have to
+defend claims against the Contributors related to those performance
+claims and warranties, and if a court requires any Contributor to pay
+any damages as a result, the Commercial Distributor must pay those
+damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement, including but not limited to
+the risks and costs of program errors, compliance with applicable
+laws, damage to or loss of data, programs or equipment, and
+unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
+ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. EXPORT CONTROL
+
+Recipient agrees that Recipient alone is responsible for compliance
+with the United States export administration regulations (and the
+export control laws and regulation of any other countries).
+
+8. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further
+action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against a Contributor with
+respect to a patent applicable to software (including a cross-claim or
+counterclaim in a lawsuit), then any patent licenses granted by that
+Contributor to such Recipient under this Agreement shall terminate as
+of the date such litigation is filed. In addition, if Recipient
+institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program
+itself (excluding combinations of the Program with other software or
+hardware) infringes such Recipient's patent(s), then such Recipient's
+rights granted under Section 2(b) shall terminate as of the date such
+litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of
+time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use
+and distribution of the Program as soon as reasonably practicable.
+However, Recipient's obligations under this Agreement and any licenses
+granted by Recipient relating to the Program shall continue and
+survive.
+
+LUCENT may publish new versions (including revisions) of this
+Agreement from time to time. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new
+version of the Agreement is published, Contributor may elect to
+distribute the Program (including its Contributions) under the new
+version. No one other than LUCENT has the right to modify this
+Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
+Recipient receives no rights or licenses to the intellectual property
+of any Contributor under this Agreement, whether expressly, by
+implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No
+party to this Agreement will bring a legal action under this Agreement
+more than one year after the cause of action arose. Each party waives
+its rights to a jury trial in any resulting litigation.
+
--- /dev/null
+++ b/os/boot.original/pc/NOTICE
@@ -1,0 +1,4 @@
+Copyright © 1995-2007 Lucent Technologies Inc. and others. All rights reserved.
+Revisions for use with Inferno © 2003-2007 Vita Nuova Holdings Limited.
+
+This software is provided under the terms of the Lucent Public License, Version 1.02.
--- /dev/null
+++ b/os/boot.original/pc/ahci.h
@@ -1,0 +1,275 @@
+/*
+ * advanced host controller interface (sata)
+ * © 2007 coraid, inc
+ */
+
+/* ata errors */
+enum {
+ Emed = 1<<0, /* media error */
+ Enm = 1<<1, /* no media */
+ Eabrt = 1<<2, /* abort */
+ Emcr = 1<<3, /* media change request */
+ Eidnf = 1<<4, /* no user-accessible address */
+ Emc = 1<<5, /* media change */
+ Eunc = 1<<6, /* data error */
+ Ewp = 1<<6, /* write protect */
+ Eicrc = 1<<7, /* interface crc error */
+
+ Efatal = Eidnf|Eicrc, /* must sw reset */
+};
+
+/* ata status */
+enum {
+ ASerr = 1<<0, /* error */
+ ASdrq = 1<<3, /* request */
+ ASdf = 1<<5, /* fault */
+ ASdrdy = 1<<6, /* ready */
+ ASbsy = 1<<7, /* busy */
+
+ ASobs = 1<<1|1<<2|1<<4,
+};
+
+/* pci configuration */
+enum {
+ Abar = 5,
+};
+
+/*
+ * ahci memory configuration
+ *
+ * 0000-0023 generic host control
+ * 0024-009f reserved
+ * 00a0-00ff vendor specific.
+ * 0100-017f port 0
+ * ...
+ * 1080-1100 port 31
+ */
+
+/* cap bits: supported features */
+enum {
+ Hs64a = 1<<31, /* 64-bit addressing */
+ Hsncq = 1<<30, /* ncq */
+ Hssntf = 1<<29, /* snotification reg. */
+ Hsmps = 1<<28, /* mech pres switch */
+ Hsss = 1<<27, /* staggered spinup */
+ Hsalp = 1<<26, /* aggressive link pm */
+ Hsal = 1<<25, /* activity led */
+ Hsclo = 1<<24, /* command-list override */
+ Hiss = 1<<20, /* for interface speed */
+// Hsnzo = 1<<19,
+ Hsam = 1<<18, /* ahci-mode only */
+ Hspm = 1<<17, /* port multiplier */
+// Hfbss = 1<<16,
+ Hpmb = 1<<15, /* multiple-block pio */
+ Hssc = 1<<14, /* slumber state */
+ Hpsc = 1<<13, /* partial-slumber state */
+ Hncs = 1<<8, /* n command slots */
+ Hcccs = 1<<7, /* coal */
+ Hems = 1<<6, /* enclosure mgmt. */
+ Hsxs = 1<<5, /* external sata */
+ Hnp = 1<<0, /* n ports */
+};
+
+/* ghc bits */
+enum {
+ Hae = 1<<31, /* enable ahci */
+ Hie = 1<<1, /* " interrupts */
+ Hhr = 1<<0, /* hba reset */
+};
+
+typedef struct {
+ ulong cap;
+ ulong ghc;
+ ulong isr;
+ ulong pi; /* ports implemented */
+ ulong ver;
+ ulong ccc; /* coaleasing control */
+ ulong cccports;
+ ulong emloc;
+ ulong emctl;
+} Ahba;
+
+enum {
+ Acpds = 1<<31, /* cold port detect status */
+ Atfes = 1<<30, /* task file error status */
+ Ahbfs = 1<<29, /* hba fatal */
+ Ahbds = 1<<28, /* hba error (parity error) */
+ Aifs = 1<<27, /* interface fatal §6.1.2 */
+ Ainfs = 1<<26, /* interface error (recovered) */
+ Aofs = 1<<24, /* too many bytes from disk */
+ Aipms = 1<<23, /* incorrect prt mul status */
+ Aprcs = 1<<22, /* PhyRdy change status Pxserr.diag.n */
+ Adpms = 1<<7, /* mechanical presence status */
+ Apcs = 1<<6, /* port connect diag.x */
+ Adps = 1<<5, /* descriptor processed */
+ Aufs = 1<<4, /* unknown fis diag.f */
+ Asdbs = 1<<3, /* set device bits fis received w/ i bit set */
+ Adss = 1<<2, /* dma setup */
+ Apio = 1<<1, /* pio setup fis */
+ Adhrs = 1<<0, /* device to host register fis */
+
+ IEM = Acpds|Atfes|Ahbds|Ahbfs|Ahbds|Aifs|Ainfs|Aprcs|Apcs|Adps|
+ Aufs|Asdbs|Adss|Adhrs,
+ Ifatal = Atfes|Ahbfs|Ahbds|Aifs,
+};
+
+/* serror bits */
+enum {
+ SerrX = 1<<26, /* exchanged */
+ SerrF = 1<<25, /* unknown fis */
+ SerrT = 1<<24, /* transition error */
+ SerrS = 1<<23, /* link sequence */
+ SerrH = 1<<22, /* handshake */
+ SerrC = 1<<21, /* crc */
+ SerrD = 1<<20, /* not used by ahci */
+ SerrB = 1<<19, /* 10-tp-8 decode */
+ SerrW = 1<<18, /* comm wake */
+ SerrI = 1<<17, /* phy internal */
+ SerrN = 1<<16, /* phyrdy change */
+
+ ErrE = 1<<11, /* internal */
+ ErrP = 1<<10, /* ata protocol violation */
+ ErrC = 1<<9, /* communication */
+ ErrT = 1<<8, /* transient */
+ ErrM = 1<<1, /* recoverd comm */
+ ErrI = 1<<0, /* recovered data integrety */
+
+ ErrAll = ErrE|ErrP|ErrC|ErrT|ErrM|ErrI,
+ SerrAll = SerrX|SerrF|SerrT|SerrS|SerrH|SerrC|SerrD|SerrB|SerrW|
+ SerrI|SerrN|ErrAll,
+ SerrBad = 0x7f<<19,
+};
+
+/* cmd register bits */
+enum {
+ Aicc = 1<<28, /* interface communcations control. 4 bits */
+ Aasp = 1<<27, /* agressive slumber & partial sleep */
+ Aalpe = 1<<26, /* agressive link pm enable */
+ Adlae = 1<<25, /* drive led on atapi */
+ Aatapi = 1<<24, /* device is atapi */
+ Aesp = 1<<21, /* external sata port */
+ Acpd = 1<<20, /* cold presence detect */
+ Ampsp = 1<<19, /* mechanical pres. */
+ Ahpcp = 1<<18, /* hot plug capable */
+ Apma = 1<<17, /* pm attached */
+ Acps = 1<<16, /* cold presence state */
+ Acr = 1<<15, /* cmdlist running */
+ Afr = 1<<14, /* fis running */
+ Ampss = 1<<13, /* mechanical presence switch state */
+ Accs = 1<<8, /* current command slot 12:08 */
+ Afre = 1<<4, /* fis enable receive */
+ Aclo = 1<<3, /* command list override */
+ Apod = 1<<2, /* power on dev (requires cold-pres. detect) */
+ Asud = 1<<1, /* spin-up device; requires ss capability */
+ Ast = 1<<0, /* start */
+
+ Arun = Ast|Acr|Afre|Afr,
+};
+
+/* ctl register bits */
+enum {
+ Aipm = 1<<8, /* interface power mgmt. 3=off */
+ Aspd = 1<<4,
+ Adet = 1<<0, /* device detection */
+};
+
+#define sstatus scr0
+#define sctl scr2
+#define serror scr1
+#define sactive scr3
+
+typedef struct {
+ ulong list; /* PxCLB must be 1kb aligned. */
+ ulong listhi;
+ ulong fis; /* 256-byte aligned */
+ ulong fishi;
+ ulong isr;
+ ulong ie; /* interrupt enable */
+ ulong cmd;
+ ulong res1;
+ ulong task;
+ ulong sig;
+ ulong scr0;
+ ulong scr2;
+ ulong scr1;
+ ulong scr3;
+ ulong ci; /* command issue */
+ ulong ntf;
+ uchar res2[8];
+ ulong vendor;
+} Aport;
+
+/* in host's memory; not memory mapped */
+typedef struct {
+ uchar *base;
+ uchar *d;
+ uchar *p;
+ uchar *r;
+ uchar *u;
+ ulong *devicebits;
+} Afis;
+
+enum {
+ Lprdtl = 1<<16, /* physical region descriptor table len */
+ Lpmp = 1<<12, /* port multiplier port */
+ Lclear = 1<<10, /* clear busy on R_OK */
+ Lbist = 1<<9,
+ Lreset = 1<<8,
+ Lpref = 1<<7, /* prefetchable */
+ Lwrite = 1<<6,
+ Latapi = 1<<5,
+ Lcfl = 1<<0, /* command fis length in double words */
+};
+
+/* in hosts memory; memory mapped */
+typedef struct {
+ ulong flags;
+ ulong len;
+ ulong ctab;
+ ulong ctabhi;
+ uchar reserved[16];
+} Alist;
+
+typedef struct {
+ ulong dba;
+ ulong dbahi;
+ ulong pad;
+ ulong count;
+} Aprdt;
+
+typedef struct {
+ uchar cfis[0x40];
+ uchar atapi[0x10];
+ uchar pad[0x30];
+ Aprdt prdt;
+} Actab;
+
+enum {
+ Ferror = 1,
+ Fdone = 2,
+};
+
+enum {
+ Dllba = 1,
+ Dsmart = 1<<1,
+ Dpower = 1<<2,
+ Dnop = 1<<3,
+ Datapi = 1<<4,
+ Datapi16= 1<<5,
+};
+
+typedef struct {
+// QLock;
+// Rendez;
+ uchar flag;
+ uchar feat;
+ uchar smart;
+ Afis fis;
+ Alist *list;
+ Actab *ctab;
+} Aportm;
+
+typedef struct {
+ Aport *p;
+ Aportm *m;
+} Aportc;
--- /dev/null
+++ b/os/boot.original/pc/alarm.c
@@ -1,0 +1,123 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#define MAXALARM 10
+
+Alarm alarmtab[MAXALARM];
+
+/*
+ * Insert new into list after where
+ */
+void
+insert(List **head, List *where, List *new)
+{
+ if(where == 0){
+ new->next = *head;
+ *head = new;
+ }else{
+ new->next = where->next;
+ where->next = new;
+ }
+
+}
+
+/*
+ * Delete old from list. where->next is known to be old.
+ */
+void
+delete(List **head, List *where, List *old)
+{
+ if(where == 0){
+ *head = old->next;
+ return;
+ }
+ where->next = old->next;
+}
+
+Alarm*
+newalarm(void)
+{
+ int i;
+ Alarm *a;
+
+ for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
+ if(a->busy==0 && a->f==0){
+ a->f = 0;
+ a->arg = 0;
+ a->busy = 1;
+ return a;
+ }
+ panic("newalarm");
+ return 0; /* not reached */
+}
+
+Alarm*
+alarm(int ms, void (*f)(Alarm*), void *arg)
+{
+ Alarm *a, *w, *pw;
+ ulong s;
+
+ if(ms < 0)
+ ms = 0;
+ s = splhi();
+ a = newalarm();
+ a->dt = MS2TK(ms);
+ a->f = f;
+ a->arg = arg;
+ pw = 0;
+ for(w=m->alarm; w; pw=w, w=w->next){
+ if(w->dt <= a->dt){
+ a->dt -= w->dt;
+ continue;
+ }
+ w->dt -= a->dt;
+ break;
+ }
+ insert(&m->alarm, pw, a);
+ splx(s);
+ return a;
+}
+
+void
+cancel(Alarm *a)
+{
+ a->f = 0;
+}
+
+void
+alarminit(void)
+{
+}
+
+#define NA 10 /* alarms per clock tick */
+void
+checkalarms(void)
+{
+ int i, n, s;
+ Alarm *a;
+ void (*f)(Alarm*);
+ Alarm *alist[NA];
+
+ s = splhi();
+ a = m->alarm;
+ if(a){
+ for(n=0; a && a->dt<=0 && n<NA; n++){
+ alist[n] = a;
+ delete(&m->alarm, 0, a);
+ a = m->alarm;
+ }
+ if(a)
+ a->dt--;
+
+ for(i = 0; i < n; i++){
+ f = alist[i]->f; /* avoid race with cancel */
+ if(f)
+ (*f)(alist[i]);
+ alist[i]->busy = 0;
+ }
+ }
+ splx(s);
+}
--- /dev/null
+++ b/os/boot.original/pc/aoe.h
@@ -1,0 +1,76 @@
+/*
+ * ATA-over-Ethernet
+ */
+enum {
+ ACata,
+ ACconfig,
+};
+
+enum {
+ AQCread,
+ AQCtest,
+ AQCprefix,
+ AQCset,
+ AQCfset,
+};
+
+enum {
+ AEcmd = 1,
+ AEarg,
+ AEdev,
+ AEcfg,
+ AEver,
+};
+
+enum {
+ Aoetype = 0x88a2,
+ Aoever = 1,
+
+ AFerr = 1<<2,
+ AFrsp = 1<<3,
+
+ AAFwrite= 1,
+ AAFext = 1<<6,
+};
+
+enum {
+ Crd = 0x20,
+ Crdext = 0x24,
+ Cwr = 0x30,
+ Cwrext = 0x34,
+ Cid = 0xec,
+};
+
+typedef struct {
+ uchar dst[Eaddrlen];
+ uchar src[Eaddrlen];
+ uchar type[2];
+ uchar verflag;
+ uchar error;
+ uchar major[2];
+ uchar minor;
+ uchar cmd;
+ uchar tag[4];
+} Aoehdr;
+
+typedef struct {
+ Aoehdr;
+ uchar aflag;
+ uchar errfeat;
+ uchar scnt;
+ uchar cmdstat;
+ uchar lba[6];
+ uchar res[2];
+} Aoeata;
+
+typedef struct {
+ Aoehdr;
+ uchar bufcnt[2];
+ uchar fwver[2];
+ uchar scnt;
+ uchar verccmd;
+ uchar cslen[2];
+} Aoeqc;
+
+extern char Echange[];
+extern char Enotup[];
--- /dev/null
+++ b/os/boot.original/pc/apm.c
@@ -1,0 +1,16 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+Apminfo apm;
+
+void
+apminit(void)
+{
+ if(getconf("apm0") && apm.haveinfo)
+ changeconf("apm0=ax=%x ebx=%x cx=%x dx=%x di=%x esi=%x\n",
+ apm.ax, apm.ebx, apm.cx, apm.dx, apm.di, apm.esi);
+}
--- /dev/null
+++ b/os/boot.original/pc/bcom.c
@@ -1,0 +1,463 @@
+/*
+ * ld - DOS boot loader of Plan 9
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "fs.h"
+
+Type types[] = {
+ { Tfloppy,
+ Fini|Ffs,
+ floppyinit, floppyinitdev,
+ floppygetfspart, 0, floppyboot,
+ },
+ { Tsd,
+ Fini|Ffs,
+ sdinit, sdinitdev,
+ sdgetfspart, sdaddconf, sdboot,
+ },
+ { Tnil,
+ 0,
+ 0, 0,
+ 0, 0, 0,
+ },
+};
+
+#include "sd.h"
+
+extern SDifc sdataifc;
+extern SDifc sdmylexifc;
+extern SDifc sd53c8xxifc;
+SDifc* sdifc[] = {
+ &sdataifc,
+// &sdmylexifc,
+// &sd53c8xxifc,
+ nil,
+};
+
+typedef struct Mode Mode;
+
+enum {
+ Maxdev = 7,
+ Dany = -1,
+ Nmedia = 16,
+ Nini = 10,
+};
+
+enum { /* mode */
+ Mauto = 0x00,
+ Mlocal = 0x01,
+ Manual = 0x02,
+ NMode = 0x03,
+};
+
+typedef struct Medium Medium;
+struct Medium {
+ Type* type;
+ int flag;
+ int dev;
+ char name[NAMELEN];
+ Fs* inifs;
+
+ Medium* next;
+};
+
+typedef struct Mode {
+ char* name;
+ int mode;
+} Mode;
+
+static Medium media[Nmedia];
+static Medium *curmedium = media;
+
+static Mode modes[NMode+1] = {
+ [Mauto] { "auto", Mauto, },
+ [Mlocal] { "local", Mlocal, },
+ [Manual] { "manual", Manual, },
+};
+
+char *defaultpartition = "new";
+
+static Medium*
+parse(char *line, char **file)
+{
+ char *p;
+ Type *tp;
+ Medium *mp;
+
+ if(p = strchr(line, '!')) {
+ *p++ = 0;
+ *file = p;
+ } else
+ *file = "";
+
+ for(tp = types; tp->type != Tnil; tp++)
+ for(mp = tp->media; mp; mp = mp->next)
+ if(strcmp(mp->name, line) == 0)
+ return mp;
+ return nil;
+}
+
+static int
+boot(Medium *mp, char *file)
+{
+ static Boot b;
+
+ memset(&b, 0, sizeof b);
+ b.state = INIT9LOAD;
+
+// sprint(BOOTLINE, "%s!%s", mp->name, file);
+ return (*mp->type->boot)(mp->dev, file, &b);
+}
+
+static Medium*
+allocm(Type *tp)
+{
+ Medium **l;
+
+ if(curmedium >= &media[Nmedia])
+ return 0;
+
+ for(l = &tp->media; *l; l = &(*l)->next)
+ ;
+ *l = curmedium++;
+ return *l;
+}
+
+char *parts[] = { "dos", "9fat", "fs", 0 };
+
+Medium*
+probe(int type, int flag, int dev)
+{
+ Type *tp;
+ int i;
+ Medium *mp;
+
+ for(tp = types; tp->type != Tnil; tp++){
+ if(type != Tany && type != tp->type)
+ continue;
+
+ if(flag != Fnone){
+ for(mp = tp->media; mp; mp = mp->next){
+ if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
+ return mp;
+ }
+ }
+
+ if((tp->flag & Fprobe) == 0){
+ tp->flag |= Fprobe;
+ tp->mask = (*tp->init)();
+ }
+
+ for(i = 0; tp->mask; i++){
+ if((tp->mask & (1<<i)) == 0)
+ continue;
+ tp->mask &= ~(1<<i);
+
+ if((mp = allocm(tp)) == 0)
+ continue;
+
+ mp->dev = i;
+ mp->flag = tp->flag;
+ mp->type = tp;
+ (*tp->initdev)(i, mp->name);
+
+ if((flag & mp->flag) && (dev == Dany || dev == i))
+ return mp;
+ }
+ }
+
+ return 0;
+}
+
+extern int loopconst;
+void
+main(void)
+{
+ Medium *mp;
+ int flag;
+ char def[2*NAMELEN], line[80], *p, *file;
+ Type *tp;
+
+ i8042a20();
+ memset(m, 0, sizeof(Mach));
+ trapinit();
+ clockinit();
+ alarminit();
+ spllo();
+
+ kbdinit();
+
+ if((ulong)&end > (KZERO|(640*1024)))
+ panic("i'm too big");
+
+ /*
+ * If there were any arguments, MS-DOS leaves a character
+ * count followed by the arguments in the runtime header.
+ * Step over the leading space.
+ */
+ p = (char*)0x80080080;
+ if(p[0]){
+ p[p[0]+1] = 0;
+ p += 2;
+ }
+ else
+ p = 0;
+
+ /*
+ * Advance command line to first option, if any
+ */
+ if(p) {
+ while(*p==' ' || *p=='\t')
+ p++;
+ if(*p == 0)
+ p = nil;
+ }
+
+ /*
+ * Probe everything, to collect device names.
+ */
+ probe(Tany, Fnone, Dany);
+
+ if(p != 0) {
+ if((mp = parse(p, &file)) == nil) {
+ print("bad loadfile syntax: %s\n", p);
+ goto done;
+ }
+ boot(mp, file);
+ }
+
+done:
+ flag = 0;
+ for(tp = types; tp->type != Tnil; tp++){
+ for(mp = tp->media; mp; mp = mp->next){
+ if(flag == 0){
+ flag = 1;
+ print("Load devices:");
+ }
+ print(" %s", mp->name);
+ }
+ }
+ if(flag)
+ print("\n");
+
+ for(;;){
+ if(getstr("load from", line, sizeof(line), nil, 0) >= 0)
+ if(mp = parse(line, &file))
+ boot(mp, file);
+ def[0] = 0;
+ }
+}
+
+int
+getfields(char *lp, char **fields, int n, char sep)
+{
+ int i;
+
+ for(i = 0; lp && *lp && i < n; i++){
+ while(*lp == sep)
+ *lp++ = 0;
+ if(*lp == 0)
+ break;
+ fields[i] = lp;
+ while(*lp && *lp != sep){
+ if(*lp == '\\' && *(lp+1) == '\n')
+ *lp++ = ' ';
+ lp++;
+ }
+ }
+ return i;
+}
+
+int
+cistrcmp(char *a, char *b)
+{
+ int ac, bc;
+
+ for(;;){
+ ac = *a++;
+ bc = *b++;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+ return 0;
+}
+
+int
+cistrncmp(char *a, char *b, int n)
+{
+ unsigned ac, bc;
+
+ while(n > 0){
+ ac = *a++;
+ bc = *b++;
+ n--;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+
+ return 0;
+}
+
+void*
+ialloc(ulong n, int align)
+{
+
+ static ulong palloc;
+ ulong p;
+ int a;
+
+ if(palloc == 0)
+ palloc = 3*1024*1024;
+
+ p = palloc;
+ if(align <= 0)
+ align = 4;
+ if(a = n % align)
+ n += align - a;
+ if(a = p % align)
+ p += align - a;
+
+ palloc = p+n;
+
+ return memset((void*)(p|KZERO), 0, n);
+}
+
+void*
+xspanalloc(ulong size, int align, ulong span)
+{
+ ulong a, v;
+
+ a = (ulong)ialloc(size+align+span, 0);
+
+ if(span > 2)
+ v = (a + span) & ~(span-1);
+ else
+ v = a;
+
+ if(align > 1)
+ v = (v + align) & ~(align-1);
+
+ return (void*)v;
+}
+
+static Block *allocbp;
+
+Block*
+allocb(int size)
+{
+ Block *bp, **lbp;
+ ulong addr;
+
+ lbp = &allocbp;
+ for(bp = *lbp; bp; bp = bp->next){
+ if((bp->lim - bp->base) >= size){
+ *lbp = bp->next;
+ break;
+ }
+ lbp = &bp->next;
+ }
+ if(bp == 0){
+ bp = ialloc(sizeof(Block)+size+64, 0);
+ addr = (ulong)bp;
+ addr = ROUNDUP(addr + sizeof(Block), 8);
+ bp->base = (uchar*)addr;
+ bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
+ }
+
+ if(bp->flag)
+ panic("allocb reuse\n");
+
+ bp->rp = bp->base;
+ bp->wp = bp->rp;
+ bp->next = 0;
+ bp->flag = 1;
+
+ return bp;
+}
+
+void
+freeb(Block* bp)
+{
+ bp->next = allocbp;
+ allocbp = bp;
+
+ bp->flag = 0;
+}
+
+enum {
+ Paddr= 0x70, /* address port */
+ Pdata= 0x71, /* data port */
+};
+
+uchar
+nvramread(int offset)
+{
+ outb(Paddr, offset);
+ return inb(Pdata);
+}
+
+void (*etherdetach)(void);
+void (*floppydetach)(void);
+void (*sddetach)(void);
+
+void
+warp9(ulong entry)
+{
+ if(etherdetach)
+ etherdetach();
+ consdrain();
+ (*(void(*)(void))(PADDR(entry)))();
+}
+
+char*
+getconf(char*)
+{
+ return nil;
+}
+
+void
+addconf(char*, ...)
+{
+}
+
+void
+uartspecial(int, void(*)(int), int(*)(void), int)
+{
+}
+
+void
+uartputs(IOQ*, char*, int)
+{
+}
+
+void
+uartputc(int)
+{}
+
+void
+uartdrain(void)
+{
+}
--- /dev/null
+++ b/os/boot.original/pc/boot.c
@@ -1,0 +1,451 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "../../../utils/libmach/elf.h"
+
+static uchar elfident[7] = {
+ '\177', 'E', 'L', 'F', '\1', '\1', '\1'
+};
+static Ehdr ehdr, rehdr;
+static Phdr *phdr;
+static int curphdr;
+static ulong curoff;
+static ulong elftotal;
+static long (*swal)(long);
+static ushort (*swab)(ushort);
+
+/*
+ * big-endian short
+ */
+ushort
+beswab(ushort s)
+{
+ uchar *p;
+
+ p = (uchar*)&s;
+ return (p[0]<<8) | p[1];
+}
+
+/*
+ * big-endian long
+ */
+long
+beswal(long l)
+{
+ uchar *p;
+
+ p = (uchar*)&l;
+ return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
+}
+
+/*
+ * little-endian short
+ */
+ushort
+leswab(ushort s)
+{
+ uchar *p;
+
+ p = (uchar*)&s;
+ return (p[1]<<8) | p[0];
+}
+
+/*
+ * little-endian long
+ */
+long
+leswal(long l)
+{
+ uchar *p;
+
+ p = (uchar*)&l;
+ return (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
+}
+
+/*
+ * Convert header to canonical form
+ */
+static void
+hswal(long *lp, int n, long (*swap) (long))
+{
+ while (n--) {
+ *lp = (*swap) (*lp);
+ lp++;
+ }
+}
+
+static int
+readehdr(Boot *b)
+{
+ int i;
+
+ /* bitswap the header according to the DATA format */
+ if(ehdr.ident[CLASS] != ELFCLASS32) {
+ print("bad ELF class - not 32 bit\n");
+ return 0;
+ }
+ if(ehdr.ident[DATA] == ELFDATA2LSB) {
+ swab = leswab;
+ swal = leswal;
+ } else if(ehdr.ident[DATA] == ELFDATA2MSB) {
+ swab = beswab;
+ swal = beswal;
+ } else {
+ print("bad ELF encoding - not big or little endian\n");
+ return 0;
+ }
+ memmove(&rehdr, &ehdr, sizeof(Ehdr));
+
+ ehdr.type = swab(ehdr.type);
+ ehdr.machine = swab(ehdr.machine);
+ ehdr.version = swal(ehdr.version);
+ ehdr.elfentry = swal(ehdr.elfentry);
+ ehdr.phoff = swal(ehdr.phoff);
+ ehdr.shoff = swal(ehdr.shoff);
+ ehdr.flags = swal(ehdr.flags);
+ ehdr.ehsize = swab(ehdr.ehsize);
+ ehdr.phentsize = swab(ehdr.phentsize);
+ ehdr.phnum = swab(ehdr.phnum);
+ ehdr.shentsize = swab(ehdr.shentsize);
+ ehdr.shnum = swab(ehdr.shnum);
+ ehdr.shstrndx = swab(ehdr.shstrndx);
+ if(ehdr.type != EXEC || ehdr.version != CURRENT)
+ return 0;
+ if(ehdr.phentsize != sizeof(Phdr))
+ return 0;
+
+ if(debug)
+ print("readehdr OK entry 0x%lux\n", ehdr.elfentry);
+
+ curoff = sizeof(Ehdr);
+ i = ehdr.phoff+ehdr.phentsize*ehdr.phnum - curoff;
+ b->state = READPHDR;
+ b->bp = (char*)malloc(i);
+ b->wp = b->bp;
+ b->ep = b->wp + i;
+ phdr = (Phdr*)(b->bp + ehdr.phoff-sizeof(Ehdr));
+ if(debug)
+ print("phdr...");
+
+ return 1;
+}
+
+static int
+nextphdr(Boot *b)
+{
+ Phdr *php;
+ ulong entry, offset;
+ char *paddr;
+
+ if(debug)
+ print("readedata %d\n", curphdr);
+
+ for(; curphdr < ehdr.phnum; curphdr++){
+ php = phdr+curphdr;
+ if(php->type != LOAD)
+ continue;
+ offset = php->offset;
+ paddr = (char*)PADDR(php->paddr);
+ if(offset < curoff){
+ /*
+ * Can't (be bothered to) rewind the
+ * input, it might be from tftp. If we
+ * did then we could boot FreeBSD kernels
+ * too maybe.
+ */
+ return 0;
+ }
+ if(php->offset > curoff){
+ b->state = READEPAD;
+ b->bp = (char*)malloc(offset - curoff);
+ b->wp = b->bp;
+ b->ep = b->wp + offset - curoff;
+ if(debug)
+ print("nextphdr %lud...\n", offset - curoff);
+ return 1;
+ }
+ b->state = READEDATA;
+ b->bp = paddr;
+ b->wp = b->bp;
+ b->ep = b->wp+php->filesz;
+ print("%ud+", php->filesz);
+ elftotal += php->filesz;
+ if(debug)
+ print("nextphdr %ud@0x%p\n", php->filesz, paddr);
+
+ return 1;
+ }
+
+ if(curphdr != 0){
+ print("=%lud\n", elftotal);
+ b->state = TRYBOOT;
+ entry = ehdr.elfentry & ~0xF0000000;
+ PLLONG(b->exec.entry, entry);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+readepad(Boot *b)
+{
+ Phdr *php;
+
+ php = phdr+curphdr;
+ if(debug)
+ print("readepad %d\n", curphdr);
+ curoff = php->offset;
+
+ return nextphdr(b);
+}
+
+static int
+readedata(Boot *b)
+{
+ Phdr *php;
+
+ php = phdr+curphdr;
+ if(debug)
+ print("readedata %d\n", curphdr);
+ if(php->filesz < php->memsz){
+ print("%lud", php->memsz-php->filesz);
+ elftotal += php->memsz-php->filesz;
+ memset((char*)(PADDR(php->paddr)+php->filesz), 0, php->memsz-php->filesz);
+ }
+ curoff = php->offset+php->filesz;
+ curphdr++;
+
+ return nextphdr(b);
+}
+
+static int
+readphdr(Boot *b)
+{
+ Phdr *php;
+
+ php = phdr;
+ hswal((long*)php, ehdr.phentsize*ehdr.phnum/sizeof(long), swal);
+ if(debug)
+ print("phdr curoff %lud vaddr 0x%lux paddr 0x%lux\n",
+ curoff, php->vaddr, php->paddr);
+
+ curoff = ehdr.phoff+ehdr.phentsize*ehdr.phnum;
+ curphdr = 0;
+
+ return nextphdr(b);
+}
+
+static int
+addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
+{
+ int n;
+
+ n = edbuf - *dbuf;
+ if(n <= 0)
+ return 0;
+ if(n > esbuf - *sbuf)
+ n = esbuf - *sbuf;
+ if(n <= 0)
+ return -1;
+
+ memmove(*dbuf, *sbuf, n);
+ *sbuf += n;
+ *dbuf += n;
+ return edbuf - *dbuf;
+}
+
+int
+bootpass(Boot *b, void *vbuf, int nbuf)
+{
+ char *buf, *ebuf;
+ Exec *ep;
+ ulong entry, data, text, bss;
+
+ if(b->state == FAILED)
+ return FAIL;
+
+ if(nbuf == 0)
+ goto Endofinput;
+
+ buf = vbuf;
+ ebuf = buf+nbuf;
+ while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
+ switch(b->state) {
+ case INITKERNEL:
+ b->state = READEXEC;
+ b->bp = (char*)&b->exec;
+ b->wp = b->bp;
+ b->ep = b->bp+sizeof(Exec);
+ break;
+ case READEXEC:
+ ep = &b->exec;
+ if(GLLONG(ep->magic) == I_MAGIC) {
+ b->state = READ9TEXT;
+ b->bp = (char*)PADDR(GLLONG(ep->entry));
+ b->wp = b->bp;
+ b->ep = b->wp+GLLONG(ep->text);
+ print("%lud", GLLONG(ep->text));
+ break;
+ }
+
+ /* check for gzipped kernel */
+ if(b->bp[0] == 0x1F && (uchar)b->bp[1] == 0x8B && b->bp[2] == 0x08) {
+ b->state = READGZIP;
+ b->bp = (char*)malloc(1440*1024);
+ b->wp = b->bp;
+ b->ep = b->wp + 1440*1024;
+ memmove(b->bp, &b->exec, sizeof(Exec));
+ b->wp += sizeof(Exec);
+ print("gz...");
+ break;
+ }
+
+ /*
+ * Check for ELF.
+ */
+ if(memcmp(b->bp, elfident, 4) == 0){
+ b->state = READEHDR;
+ b->bp = (char*)&ehdr;
+ b->wp = b->bp;
+ b->ep = b->wp + sizeof(Ehdr);
+ memmove(b->bp, &b->exec, sizeof(Exec));
+ b->wp += sizeof(Exec);
+ print("elf...");
+ break;
+ }
+
+ print("bad kernel format\n");
+ b->state = FAILED;
+ return FAIL;
+
+ case READ9TEXT:
+ ep = &b->exec;
+ b->state = READ9DATA;
+ b->bp = (char*)PGROUND(PADDR(GLLONG(ep->entry))+GLLONG(ep->text));
+ b->wp = b->bp;
+ b->ep = b->wp + GLLONG(ep->data);
+ print("+%ld", GLLONG(ep->data));
+ break;
+
+ case READ9DATA:
+ ep = &b->exec;
+ bss = GLLONG(ep->bss);
+ print("+%ld=%ld\n",
+ bss, GLLONG(ep->text)+GLLONG(ep->data)+bss);
+ b->state = TRYBOOT;
+ return ENOUGH;
+
+ case READEHDR:
+ if(!readehdr(b)){
+ print("readehdr failed\n");
+ b->state = FAILED;
+ return FAIL;
+ }
+ break;
+
+ case READPHDR:
+ if(!readphdr(b)){
+ b->state = FAILED;
+ return FAIL;
+ }
+ break;
+
+ case READEPAD:
+ if(!readepad(b)){
+ b->state = FAILED;
+ return FAIL;
+ }
+ break;
+
+ case READEDATA:
+ if(!readedata(b)){
+ b->state = FAILED;
+ return FAIL;
+ }
+ if(b->state == TRYBOOT)
+ return ENOUGH;
+ break;
+
+ case TRYBOOT:
+ case READGZIP:
+ return ENOUGH;
+
+ case READ9LOAD:
+ case INIT9LOAD:
+ panic("9load");
+
+ default:
+ panic("bootstate");
+ }
+ }
+ return MORE;
+
+
+Endofinput:
+ /* end of input */
+ switch(b->state) {
+ case INITKERNEL:
+ case READEXEC:
+ case READ9TEXT:
+ case READ9DATA:
+ case READEHDR:
+ case READPHDR:
+ case READEPAD:
+ case READEDATA:
+ print("premature EOF\n");
+ b->state = FAILED;
+ return FAIL;
+
+ case TRYBOOT:
+ entry = GLLONG(b->exec.entry);
+ print("entry: 0x%lux\n", entry);
+ warp9(PADDR(entry));
+ b->state = FAILED;
+ return FAIL;
+
+ case READGZIP:
+ ep = &b->exec;
+ if(b->bp[0] != 0x1F || (uchar)b->bp[1] != 0x8B || b->bp[2] != 0x08)
+ print("lost magic\n");
+
+ print("%ld => ", b->wp - b->bp);
+ if(gunzip((uchar*)ep, sizeof(*ep), (uchar*)b->bp, b->wp - b->bp) < sizeof(*ep)) {
+ print("badly compressed kernel\n");
+ return FAIL;
+ }
+
+ entry = GLLONG(ep->entry);
+ text = GLLONG(ep->text);
+ data = GLLONG(ep->data);
+ bss = GLLONG(ep->bss);
+ print("%lud+%lud+%lud=%lud\n", text, data, bss, text+data+bss);
+
+ if(gunzip((uchar*)PADDR(entry)-sizeof(Exec), sizeof(Exec)+text+data,
+ (uchar*)b->bp, b->wp-b->bp) < sizeof(Exec)+text+data) {
+ print("error uncompressing kernel\n");
+ return FAIL;
+ }
+
+ /* relocate data to start at page boundary */
+ memmove((void*)PGROUND(PADDR(entry+text)), (void*)(PADDR(entry+text)), data);
+
+ print("entry: %lux\n", entry);
+ warp9(PADDR(entry));
+ b->state = FAILED;
+ return FAIL;
+
+ case INIT9LOAD:
+ case READ9LOAD:
+ panic("end 9load");
+
+ default:
+ panic("bootdone");
+ }
+ b->state = FAILED;
+ return FAIL;
+}
--- /dev/null
+++ b/os/boot.original/pc/bootld.c
@@ -1,0 +1,108 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+static int
+addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
+{
+ int n;
+
+ n = edbuf - *dbuf;
+ if(n <= 0)
+ return 0;
+ if(n > esbuf - *sbuf)
+ n = esbuf - *sbuf;
+ if(n <= 0)
+ return -1;
+
+ memmove(*dbuf, *sbuf, n);
+ *sbuf += n;
+ *dbuf += n;
+ return edbuf - *dbuf;
+}
+
+extern void origin(void);
+
+int
+bootpass(Boot *b, void *vbuf, int nbuf)
+{
+ char *buf, *ebuf, *p, *q;
+ ulong size;
+
+ if(b->state == FAILED)
+ return FAIL;
+
+ if(nbuf == 0)
+ goto Endofinput;
+
+ buf = vbuf;
+ ebuf = buf+nbuf;
+ while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
+ switch(b->state) {
+ case INIT9LOAD:
+ b->state = READ9LOAD;
+ b->bp = (char*)0x10000;
+ b->wp = b->bp;
+ b->ep = b->bp + 256*1024;
+ break;
+
+ case READ9LOAD:
+ return ENOUGH;
+
+ default:
+ panic("bootstate");
+ }
+ }
+ return MORE;
+
+
+Endofinput:
+ /* end of input */
+ print("\n");
+ switch(b->state) {
+ case INIT9LOAD:
+ print("premature EOF\n");
+ b->state = FAILED;
+ return FAIL;
+
+ case READ9LOAD:
+ size = b->wp - b->bp;
+ if(memcmp(b->bp, origin, 16) != 0) {
+ print("beginning of file does not look right\n");
+ b->state = FAILED;
+ return FAIL;
+ }
+ if(size < 32*1024 || size > 256*1024) {
+ print("got %lud byte loader; not likely\n", size);
+ b->state = FAILED;
+ return FAIL;
+ }
+
+ p = b->bp;
+ q = b->wp;
+ if(q - p > 10000) /* don't search much past l.s */
+ q = p+10000;
+
+ /*
+ * The string `JUMP' appears right before
+ * tokzero, which is where we want to jump.
+ */
+ for(; p<q; p++) {
+ if(strncmp(p, "JUMP", 4) == 0) {
+ p += 4;
+ warp9((ulong)p);
+ }
+ }
+ print("could not find jump destination\n");
+ b->state = FAILED;
+ return FAIL;
+
+ default:
+ panic("bootdone");
+ }
+ b->state = FAILED;
+ return FAIL;
+}
--- /dev/null
+++ b/os/boot.original/pc/bootp.c
@@ -1,0 +1,659 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ip.h"
+
+extern int debugload;
+
+uchar broadcast[Eaddrlen] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static ushort tftpport = 5000;
+static int Id = 1;
+static Netaddr myaddr;
+static Netaddr server;
+
+typedef struct {
+ uchar header[4];
+ uchar data[Segsize];
+} Tftp;
+static Tftp tftpb;
+
+static void
+hnputs(uchar *ptr, ushort val)
+{
+ ptr[0] = val>>8;
+ ptr[1] = val;
+}
+
+static void
+hnputl(uchar *ptr, ulong val)
+{
+ ptr[0] = val>>24;
+ ptr[1] = val>>16;
+ ptr[2] = val>>8;
+ ptr[3] = val;
+}
+
+static ulong
+nhgetl(uchar *ptr)
+{
+ return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+}
+
+static ushort
+nhgets(uchar *ptr)
+{
+ return ((ptr[0]<<8) | ptr[1]);
+}
+
+static short endian = 1;
+static char* aendian = (char*)&endian;
+#define LITTLE *aendian
+
+static ushort
+ptcl_csum(void *a, int len)
+{
+ uchar *addr;
+ ulong t1, t2;
+ ulong losum, hisum, mdsum, x;
+
+ addr = a;
+ losum = 0;
+ hisum = 0;
+ mdsum = 0;
+
+ x = 0;
+ if((ulong)addr & 1) {
+ if(len) {
+ hisum += addr[0];
+ len--;
+ addr++;
+ }
+ x = 1;
+ }
+ while(len >= 16) {
+ t1 = *(ushort*)(addr+0);
+ t2 = *(ushort*)(addr+2); mdsum += t1;
+ t1 = *(ushort*)(addr+4); mdsum += t2;
+ t2 = *(ushort*)(addr+6); mdsum += t1;
+ t1 = *(ushort*)(addr+8); mdsum += t2;
+ t2 = *(ushort*)(addr+10); mdsum += t1;
+ t1 = *(ushort*)(addr+12); mdsum += t2;
+ t2 = *(ushort*)(addr+14); mdsum += t1;
+ mdsum += t2;
+ len -= 16;
+ addr += 16;
+ }
+ while(len >= 2) {
+ mdsum += *(ushort*)addr;
+ len -= 2;
+ addr += 2;
+ }
+ if(x) {
+ if(len)
+ losum += addr[0];
+ if(LITTLE)
+ losum += mdsum;
+ else
+ hisum += mdsum;
+ } else {
+ if(len)
+ hisum += addr[0];
+ if(LITTLE)
+ hisum += mdsum;
+ else
+ losum += mdsum;
+ }
+
+ losum += hisum >> 8;
+ losum += (hisum & 0xff) << 8;
+ while(hisum = losum>>16)
+ losum = hisum + (losum & 0xffff);
+
+ return ~losum;
+}
+
+static ushort
+ip_csum(uchar *addr)
+{
+ int len;
+ ulong sum = 0;
+
+ len = (addr[0]&0xf)<<2;
+
+ while(len > 0) {
+ sum += addr[0]<<8 | addr[1] ;
+ len -= 2;
+ addr += 2;
+ }
+
+ sum = (sum & 0xffff) + (sum >> 16);
+ sum = (sum & 0xffff) + (sum >> 16);
+ return (sum^0xffff);
+}
+
+enum {
+ /* this is only true of IPv4, but we're not doing v6 yet */
+ Min_udp_payload = ETHERMINTU - ETHERHDRSIZE - UDP_HDRSIZE,
+};
+
+static void
+udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+ char payload[ETHERMAXTU];
+ Udphdr *uh;
+ Etherhdr *ip;
+ Etherpkt pkt;
+ int len, ptcllen;
+
+ /*
+ * if packet is too short, make it longer rather than relying
+ * on ethernet interface or lower layers to pad it.
+ */
+ if (dlen < Min_udp_payload) {
+ memmove(payload, data, dlen);
+ data = payload;
+ dlen = Min_udp_payload;
+ }
+
+ uh = (Udphdr*)&pkt;
+
+ memset(uh, 0, sizeof(Etherpkt));
+ memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
+
+ /*
+ * UDP portion
+ */
+ ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
+ uh->ttl = 0;
+ uh->udpproto = IP_UDPPROTO;
+ uh->frag[0] = 0;
+ uh->frag[1] = 0;
+ hnputs(uh->udpplen, ptcllen);
+ hnputl(uh->udpsrc, myaddr.ip);
+ hnputs(uh->udpsport, myaddr.port);
+ hnputl(uh->udpdst, a->ip);
+ hnputs(uh->udpdport, a->port);
+ hnputs(uh->udplen, ptcllen);
+ uh->udpcksum[0] = 0;
+ uh->udpcksum[1] = 0;
+ dlen = (dlen+1)&~1;
+ hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
+
+ /*
+ * IP portion
+ */
+ ip = (Etherhdr*)&pkt;
+ len = UDP_EHSIZE+UDP_HDRSIZE+dlen; /* non-descriptive names */
+ ip->vihl = IP_VER|IP_HLEN;
+ ip->tos = 0;
+ ip->ttl = 255;
+ hnputs(ip->length, len-ETHER_HDR);
+ hnputs(ip->id, Id++);
+ ip->frag[0] = 0;
+ ip->frag[1] = 0;
+ ip->cksum[0] = 0;
+ ip->cksum[1] = 0;
+ hnputs(ip->cksum, ip_csum(&ip->vihl));
+
+ /*
+ * Ethernet MAC portion
+ */
+ hnputs(ip->type, ET_IP);
+ memmove(ip->d, a->ea, sizeof(ip->d));
+
+if(debug) {
+ print("udpsend ");
+}
+ ethertxpkt(ctlrno, &pkt, len, Timeout);
+}
+
+static void
+nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
+{
+ int n;
+ char buf[128];
+
+ buf[0] = 0;
+ buf[1] = Tftp_ERROR;
+ buf[2] = 0;
+ buf[3] = code;
+ strcpy(buf+4, msg);
+ n = strlen(msg) + 4 + 1;
+ udpsend(ctlrno, a, buf, n);
+ if(report)
+ print("\ntftp: error(%d): %s\n", code, msg);
+}
+
+static int
+udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+ int n, len;
+ ushort csm;
+ Udphdr *h;
+ ulong addr, timo;
+ Etherpkt pkt;
+ static int rxactive;
+
+ if(rxactive == 0)
+ timo = 1000;
+ else
+ timo = Timeout;
+ timo += TK2MS(m->ticks);
+ while(timo > TK2MS(m->ticks)){
+ n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
+ if(n <= 0)
+ continue;
+
+ h = (Udphdr*)&pkt;
+ if(debug)
+ print("udprecv %E to %E...\n", h->s, h->d);
+
+ if(nhgets(h->type) != ET_IP) {
+ if(debug)
+ print("not ip...");
+ continue;
+ }
+
+ if(ip_csum(&h->vihl)) {
+ print("ip chksum error\n");
+ continue;
+ }
+ if(h->vihl != (IP_VER|IP_HLEN)) {
+ print("ip bad vers/hlen\n");
+ continue;
+ }
+
+ if(h->udpproto != IP_UDPPROTO) {
+ if(debug)
+ print("not udp (%d)...", h->udpproto);
+ continue;
+ }
+
+ if(debug)
+ print("okay udp...");
+
+ h->ttl = 0;
+ len = nhgets(h->udplen);
+ hnputs(h->udpplen, len);
+
+ if(nhgets(h->udpcksum)) {
+ csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
+ if(csm != 0) {
+ print("udp chksum error csum #%4ux len %d\n",
+ csm, n);
+ break;
+ }
+ }
+
+ if(a->port != 0 && nhgets(h->udpsport) != a->port) {
+ if(debug)
+ print("udpport %ux not %ux\n",
+ nhgets(h->udpsport), a->port);
+ continue;
+ }
+
+ addr = nhgetl(h->udpsrc);
+ if(a->ip != Bcastip && a->ip != addr) {
+ if(debug)
+ print("bad ip %lux not %lux\n", addr, a->ip);
+ continue;
+ }
+
+ len -= UDP_HDRSIZE-UDP_PHDRSIZE;
+ if(len > dlen) {
+ print("udp: packet too big: %d > %d; from addr %E\n",
+ len, dlen, h->udpsrc);
+ continue;
+ }
+
+ memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
+ a->ip = addr;
+ a->port = nhgets(h->udpsport);
+ memmove(a->ea, pkt.s, sizeof(a->ea));
+
+ rxactive = 1;
+ return len;
+ }
+
+ return 0;
+}
+
+static int tftpblockno;
+
+/*
+ * format of a request packet, from the RFC:
+ *
+ 2 bytes string 1 byte string 1 byte
+ ------------------------------------------------
+ | Opcode | Filename | 0 | Mode | 0 |
+ ------------------------------------------------
+ */
+static int
+tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
+{
+ int i, len, rlen, oport;
+ char buf[Segsize+2];
+
+ buf[0] = 0;
+ buf[1] = Tftp_READ;
+ len = 2 + sprint(buf+2, "%s", name) + 1;
+ len += sprint(buf+len, "octet") + 1;
+
+ oport = a->port;
+ for(i = 0; i < 5; i++){
+ a->port = oport;
+ udpsend(ctlrno, a, buf, len);
+ a->port = 0;
+ if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
+ continue;
+
+ switch((tftp->header[0]<<8)|tftp->header[1]){
+
+ case Tftp_ERROR:
+ print("tftpopen: error (%d): %s\n",
+ (tftp->header[2]<<8)|tftp->header[3], (char*)tftp->data);
+ return -1;
+
+ case Tftp_DATA:
+ tftpblockno = 1;
+ len = (tftp->header[2]<<8)|tftp->header[3];
+ if(len != tftpblockno){
+ print("tftpopen: block error: %d\n", len);
+ nak(ctlrno, a, 1, "block error", 0);
+ return -1;
+ }
+ rlen -= sizeof(tftp->header);
+ if(rlen < Segsize){
+ /* ACK now, in case we don't later */
+ buf[0] = 0;
+ buf[1] = Tftp_ACK;
+ buf[2] = tftpblockno>>8;
+ buf[3] = tftpblockno;
+ udpsend(ctlrno, a, buf, sizeof(tftp->header));
+ }
+ return rlen;
+ }
+ }
+
+ print("tftpopen: failed to connect to server\n");
+ return -1;
+}
+
+static int
+tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
+{
+ uchar buf[4];
+ int try, blockno, len;
+
+ dlen += sizeof(tftp->header);
+
+ for(try = 0; try < 10; try++) {
+ buf[0] = 0;
+ buf[1] = Tftp_ACK;
+ buf[2] = tftpblockno>>8;
+ buf[3] = tftpblockno;
+
+ udpsend(ctlrno, a, buf, sizeof(buf));
+ len = udprecv(ctlrno, a, tftp, dlen);
+ if(len <= sizeof(tftp->header)){
+ if(debug)
+ print("tftpread: too short %d <= %d\n",
+ len, sizeof(tftp->header));
+ continue;
+ }
+ blockno = (tftp->header[2]<<8)|tftp->header[3];
+ if(blockno <= tftpblockno){
+ if(debug)
+ print("tftpread: blkno %d <= %d\n",
+ blockno, tftpblockno);
+ continue;
+ }
+
+ if(blockno == tftpblockno+1) {
+ tftpblockno++;
+ if(len < dlen) { /* last packet; send final ack */
+ tftpblockno++;
+ buf[0] = 0;
+ buf[1] = Tftp_ACK;
+ buf[2] = tftpblockno>>8;
+ buf[3] = tftpblockno;
+ udpsend(ctlrno, a, buf, sizeof(buf));
+ }
+ return len-sizeof(tftp->header);
+ }
+ print("tftpread: block error: %d, expected %d\n",
+ blockno, tftpblockno+1);
+ }
+
+ return -1;
+}
+
+static int
+bootpopen(int ctlrno, char *file, Bootp *rep, int dotftpopen)
+{
+ Bootp req;
+ int i, n;
+ uchar *ea;
+ char name[128], *filename, *sysname;
+
+ if (debugload)
+ print("bootpopen: ether%d!%s...", ctlrno, file);
+ if((ea = etheraddr(ctlrno)) == 0){
+ print("invalid ctlrno %d\n", ctlrno);
+ return -1;
+ }
+
+ filename = 0;
+ sysname = 0;
+ if(file && *file){
+ strcpy(name, file);
+ if(filename = strchr(name, '!')){
+ sysname = name;
+ *filename++ = 0;
+ }
+ else
+ filename = name;
+ }
+
+ memset(&req, 0, sizeof(req));
+ req.op = Bootrequest;
+ req.htype = 1; /* ethernet */
+ req.hlen = Eaddrlen; /* ethernet */
+ memmove(req.chaddr, ea, Eaddrlen);
+ if(filename != nil)
+ strncpy(req.file, filename, sizeof(req.file));
+ if(sysname != nil)
+ strncpy(req.sname, sysname, sizeof(req.sname));
+
+ myaddr.ip = 0;
+ myaddr.port = BPportsrc;
+ memmove(myaddr.ea, ea, Eaddrlen);
+
+ etherrxflush(ctlrno);
+ for(i = 0; i < 10; i++) {
+ server.ip = Bcastip;
+ server.port = BPportdst;
+ memmove(server.ea, broadcast, sizeof(server.ea));
+ udpsend(ctlrno, &server, &req, sizeof(req));
+ if(udprecv(ctlrno, &server, rep, sizeof(*rep)) <= 0)
+ continue;
+ if(memcmp(req.chaddr, rep->chaddr, Eaddrlen))
+ continue;
+ if(rep->htype != 1 || rep->hlen != Eaddrlen)
+ continue;
+ if(sysname == 0 || strcmp(sysname, rep->sname) == 0)
+ break;
+ }
+ if(i >= 10) {
+ print("bootp timed out\n");
+ return -1;
+ }
+
+ if(!dotftpopen)
+ return 0;
+
+ if(filename == 0 || *filename == 0){
+ if(strcmp(rep->file, "/386/9pxeload") == 0)
+ return -1;
+ filename = rep->file;
+ }
+
+ if(rep->sname[0] != '\0')
+ print("%s ", rep->sname);
+ print("(%d.%d.%d.%d!%d): %s\n",
+ rep->siaddr[0],
+ rep->siaddr[1],
+ rep->siaddr[2],
+ rep->siaddr[3],
+ server.port,
+ filename);
+
+ myaddr.ip = nhgetl(rep->yiaddr);
+ myaddr.port = tftpport++;
+ server.ip = nhgetl(rep->siaddr);
+ server.port = TFTPport;
+
+ if((n = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
+ return -1;
+
+ return n;
+}
+
+int
+bootpboot(int ctlrno, char *file, Boot *b)
+{
+ int n;
+ Bootp rep;
+
+ if((n = bootpopen(ctlrno, file, &rep, 1)) < 0)
+ return -1;
+
+ while(bootpass(b, tftpb.data, n) == MORE){
+ n = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data));
+ if(n < sizeof(tftpb.data))
+ break;
+ }
+
+ if(0 < n && n < sizeof(tftpb.data)) /* got to end of file */
+ bootpass(b, tftpb.data, n);
+ else
+ nak(ctlrno, &server, 3, "ok", 0); /* tftpclose to abort transfer */
+ bootpass(b, nil, 0); /* boot if possible */
+ return -1;
+}
+
+#include "fs.h"
+
+#define INIPATHLEN 64
+
+static struct {
+ Fs fs;
+ char ini[INIPATHLEN];
+} pxether[MaxEther];
+
+static vlong
+pxediskseek(Fs*, vlong)
+{
+ return -1LL;
+}
+
+static long
+pxediskread(Fs*, void*, long)
+{
+ return -1;
+}
+
+static long
+pxeread(File* f, void* va, long len)
+{
+ int n;
+ Bootp rep;
+ char *p, *v;
+
+ if((n = bootpopen(f->fs->dev, pxether[f->fs->dev].ini, &rep, 1)) < 0)
+ return -1;
+
+ p = v = va;
+ while(n > 0) {
+ if((p-v)+n > len)
+ n = len - (p-v);
+ memmove(p, tftpb.data, n);
+ p += n;
+ if(n != Segsize)
+ break;
+ if((n = tftpread(f->fs->dev, &server, &tftpb, sizeof(tftpb.data))) < 0)
+ return -1;
+ }
+ return p-v;
+}
+
+static int
+pxewalk(File* f, char* name)
+{
+ Bootp rep;
+ char *ini;
+
+ switch(f->walked){
+ default:
+ return -1;
+ case 0:
+ if(strcmp(name, "cfg") == 0){
+ f->walked = 1;
+ return 1;
+ }
+ break;
+ case 1:
+ if(strcmp(name, "pxe") == 0){
+ f->walked = 2;
+ return 1;
+ }
+ break;
+ case 2:
+ if(strcmp(name, "%E") != 0)
+ break;
+ f->walked = 3;
+
+ if(bootpopen(f->fs->dev, nil, &rep, 0) < 0)
+ return 0;
+
+ ini = pxether[f->fs->dev].ini;
+ /* use our mac address instead of relying on a bootp answer */
+ snprint(ini, INIPATHLEN, "/cfg/pxe/%E", (uchar *)myaddr.ea);
+ f->path = ini;
+
+ return 1;
+ }
+ return 0;
+}
+
+void*
+pxegetfspart(int ctlrno, char* part, int)
+{
+ if(!pxe)
+ return nil;
+ if(strcmp(part, "*") != 0)
+ return nil;
+ if(ctlrno >= MaxEther)
+ return nil;
+ if(iniread && getconf("*pxeini") != nil)
+ return nil;
+
+ pxether[ctlrno].fs.dev = ctlrno;
+ pxether[ctlrno].fs.diskread = pxediskread;
+ pxether[ctlrno].fs.diskseek = pxediskseek;
+
+ pxether[ctlrno].fs.read = pxeread;
+ pxether[ctlrno].fs.walk = pxewalk;
+
+ pxether[ctlrno].fs.root.fs = &pxether[ctlrno].fs;
+ pxether[ctlrno].fs.root.walked = 0;
+
+ return &pxether[ctlrno].fs;
+}
--- /dev/null
+++ b/os/boot.original/pc/cga.c
@@ -1,0 +1,91 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+enum {
+ Width = 160,
+ Height = 25,
+
+ Attr = 7, /* white on black */
+};
+
+#define CGASCREENBASE ((uchar*)KADDR(0xB8000))
+
+static int pos;
+static int screeninitdone;
+
+static uchar
+cgaregr(int index)
+{
+ outb(0x3D4, index);
+ return inb(0x3D4+1) & 0xFF;
+}
+
+static void
+cgaregw(int index, int data)
+{
+ outb(0x3D4, index);
+ outb(0x3D4+1, data);
+}
+
+static void
+movecursor(void)
+{
+ cgaregw(0x0E, (pos/2>>8) & 0xFF);
+ cgaregw(0x0F, pos/2 & 0xFF);
+ CGASCREENBASE[pos+1] = Attr;
+}
+
+static void
+cgascreenputc(int c)
+{
+ int i;
+
+ if(c == '\n'){
+ pos = pos/Width;
+ pos = (pos+1)*Width;
+ }
+ else if(c == '\t'){
+ i = 8 - ((pos/2)&7);
+ while(i-->0)
+ cgascreenputc(' ');
+ }
+ else if(c == '\b'){
+ if(pos >= 2)
+ pos -= 2;
+ cgascreenputc(' ');
+ pos -= 2;
+ }
+ else{
+ CGASCREENBASE[pos++] = c;
+ CGASCREENBASE[pos++] = Attr;
+ }
+ if(pos >= Width*Height){
+ memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
+ memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
+ pos = Width*(Height-1);
+ }
+ movecursor();
+}
+
+static void
+screeninit(void)
+{
+ if(screeninitdone == 0){
+ pos = cgaregr(0x0E)<<8;
+ pos |= cgaregr(0x0F);
+ pos *= 2;
+ screeninitdone = 1;
+ }
+}
+
+void
+cgascreenputs(char* s, int n)
+{
+ if(screeninitdone == 0)
+ screeninit();
+ while(n-- > 0)
+ cgascreenputc(*s++);
+}
--- /dev/null
+++ b/os/boot.original/pc/cis.c
@@ -1,0 +1,539 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "io.h"
+
+enum{
+ Linktarget = 0x13,
+};
+
+/*
+ * read and crack the card information structure enough to set
+ * important parameters like power
+ */
+/* cis memory walking */
+typedef struct Cisdat {
+ uchar *cisbase;
+ int cispos;
+ int cisskip;
+ int cislen;
+} Cisdat;
+
+static void tcfig(PCMslot*, Cisdat*, int);
+static void tentry(PCMslot*, Cisdat*, int);
+static void tvers1(PCMslot*, Cisdat*, int);
+static void tlonglnkmfc(PCMslot*, Cisdat*, int);
+
+static int
+readc(Cisdat *cis, uchar *x)
+{
+ if(cis->cispos >= cis->cislen)
+ return 0;
+ *x = cis->cisbase[cis->cisskip*cis->cispos];
+ cis->cispos++;
+ return 1;
+}
+
+static int
+xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
+{
+ PCMmap *m;
+ Cisdat cis;
+ int i, l;
+ uchar *p;
+ uchar type, link, n, c;
+ int this, subtype;
+
+ m = pcmmap(slotno, 0, 0, attr);
+ if(m == 0)
+ return -1;
+
+ cis.cisbase = KADDR(m->isa);
+ cis.cispos = 0;
+ cis.cisskip = attr ? 2 : 1;
+ cis.cislen = m->len;
+
+ /* loop through all the tuples */
+ for(i = 0; i < 1000; i++){
+ this = cis.cispos;
+ if(readc(&cis, &type) != 1)
+ break;
+ if(type == 0xFF)
+ break;
+ if(readc(&cis, &link) != 1)
+ break;
+ if(link == 0xFF)
+ break;
+
+ n = link;
+ if(link > 1 && subtuple != -1){
+ if(readc(&cis, &c) != 1)
+ break;
+ subtype = c;
+ n--;
+ }else
+ subtype = -1;
+
+ if(type == tuple && subtype == subtuple){
+ p = v;
+ for(l=0; l<nv && l<n; l++)
+ if(readc(&cis, p++) != 1)
+ break;
+ pcmunmap(slotno, m);
+ return nv;
+ }
+ cis.cispos = this + (2+link);
+ }
+ pcmunmap(slotno, m);
+ return -1;
+}
+
+int
+pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
+{
+ int n;
+
+ /* try attribute space, then memory */
+ if((n = xcistuple(slotno, tuple, subtuple, v, nv, 1)) >= 0)
+ return n;
+ return xcistuple(slotno, tuple, subtuple, v, nv, 0);
+}
+
+void
+pcmcisread(PCMslot *pp)
+{
+ int this;
+ Cisdat cis;
+ PCMmap *m;
+ uchar type, link;
+
+ memset(pp->ctab, 0, sizeof(pp->ctab));
+ pp->ncfg = 0;
+ memset(pp->cfg, 0, sizeof(pp->cfg));
+ pp->configed = 0;
+ pp->nctab = 0;
+ pp->verstr[0] = 0;
+
+ /*
+ * Read all tuples in attribute space.
+ */
+ m = pcmmap(pp->slotno, 0, 0, 1);
+ if(m == 0)
+ return;
+
+ cis.cisbase = KADDR(m->isa);
+ cis.cispos = 0;
+ cis.cisskip = 2;
+ cis.cislen = m->len;
+
+ /* loop through all the tuples */
+ for(;;){
+ this = cis.cispos;
+ if(readc(&cis, &type) != 1)
+ break;
+ if(type == 0xFF)
+ break;
+ if(readc(&cis, &link) != 1)
+ break;
+
+ switch(type){
+ default:
+ break;
+ case 6:
+ tlonglnkmfc(pp, &cis, type);
+ break;
+ case 0x15:
+ tvers1(pp, &cis, type);
+ break;
+ case 0x1A:
+ tcfig(pp, &cis, type);
+ break;
+ case 0x1B:
+ tentry(pp, &cis, type);
+ break;
+ }
+
+ if(link == 0xFF)
+ break;
+ cis.cispos = this + (2+link);
+ }
+ pcmunmap(pp->slotno, m);
+}
+
+static ulong
+getlong(Cisdat *cis, int size)
+{
+ uchar c;
+ int i;
+ ulong x;
+
+ x = 0;
+ for(i = 0; i < size; i++){
+ if(readc(cis, &c) != 1)
+ break;
+ x |= c<<(i*8);
+ }
+ return x;
+}
+
+static void
+tcfig(PCMslot *pp, Cisdat *cis, int )
+{
+ uchar size, rasize, rmsize;
+ uchar last;
+
+ if(readc(cis, &size) != 1)
+ return;
+ rasize = (size&0x3) + 1;
+ rmsize = ((size>>2)&0xf) + 1;
+ if(readc(cis, &last) != 1)
+ return;
+
+ if(pp->ncfg >= 8){
+ print("tcfig: too many configuration registers\n");
+ return;
+ }
+
+ pp->cfg[pp->ncfg].caddr = getlong(cis, rasize);
+ pp->cfg[pp->ncfg].cpresent = getlong(cis, rmsize);
+ pp->ncfg++;
+}
+
+static ulong vexp[8] =
+{
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
+};
+static ulong vmant[16] =
+{
+ 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
+};
+
+static ulong
+microvolt(Cisdat *cis)
+{
+ uchar c;
+ ulong microvolts;
+ ulong exp;
+
+ if(readc(cis, &c) != 1)
+ return 0;
+ exp = vexp[c&0x7];
+ microvolts = vmant[(c>>3)&0xf]*exp;
+ while(c & 0x80){
+ if(readc(cis, &c) != 1)
+ return 0;
+ switch(c){
+ case 0x7d:
+ break; /* high impedence when sleeping */
+ case 0x7e:
+ case 0x7f:
+ microvolts = 0; /* no connection */
+ break;
+ default:
+ exp /= 10;
+ microvolts += exp*(c&0x7f);
+ }
+ }
+ return microvolts;
+}
+
+static ulong
+nanoamps(Cisdat *cis)
+{
+ uchar c;
+ ulong nanoamps;
+
+ if(readc(cis, &c) != 1)
+ return 0;
+ nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
+ while(c & 0x80){
+ if(readc(cis, &c) != 1)
+ return 0;
+ if(c == 0x7d || c == 0x7e || c == 0x7f)
+ nanoamps = 0;
+ }
+ return nanoamps;
+}
+
+/*
+ * only nominal voltage (feature 1) is important for config,
+ * other features must read card to stay in sync.
+ */
+static ulong
+power(Cisdat *cis)
+{
+ uchar feature;
+ ulong mv;
+
+ mv = 0;
+ if(readc(cis, &feature) != 1)
+ return 0;
+ if(feature & 1)
+ mv = microvolt(cis);
+ if(feature & 2)
+ microvolt(cis);
+ if(feature & 4)
+ microvolt(cis);
+ if(feature & 8)
+ nanoamps(cis);
+ if(feature & 0x10)
+ nanoamps(cis);
+ if(feature & 0x20)
+ nanoamps(cis);
+ if(feature & 0x40)
+ nanoamps(cis);
+ return mv/1000000;
+}
+
+static ulong mantissa[16] =
+{ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };
+
+static ulong exponent[8] =
+{ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };
+
+static ulong
+ttiming(Cisdat *cis, int scale)
+{
+ uchar unscaled;
+ ulong nanosecs;
+
+ if(readc(cis, &unscaled) != 1)
+ return 0;
+ nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
+ nanosecs = nanosecs * vexp[scale];
+ return nanosecs;
+}
+
+static void
+timing(Cisdat *cis, PCMconftab *ct)
+{
+ uchar c, i;
+
+ if(readc(cis, &c) != 1)
+ return;
+ i = c&0x3;
+ if(i != 3)
+ ct->maxwait = ttiming(cis, i); /* max wait */
+ i = (c>>2)&0x7;
+ if(i != 7)
+ ct->readywait = ttiming(cis, i); /* max ready/busy wait */
+ i = (c>>5)&0x7;
+ if(i != 7)
+ ct->otherwait = ttiming(cis, i); /* reserved wait */
+}
+
+static void
+iospaces(Cisdat *cis, PCMconftab *ct)
+{
+ uchar c;
+ int i, nio;
+
+ ct->nio = 0;
+ if(readc(cis, &c) != 1)
+ return;
+
+ ct->bit16 = ((c>>5)&3) >= 2;
+ if(!(c & 0x80)){
+ ct->io[0].start = 0;
+ ct->io[0].len = 1<<(c&0x1f);
+ ct->nio = 1;
+ return;
+ }
+
+ if(readc(cis, &c) != 1)
+ return;
+
+ /*
+ * For each of the range descriptions read the
+ * start address and the length (value is length-1).
+ */
+ nio = (c&0xf)+1;
+ for(i = 0; i < nio; i++){
+ ct->io[i].start = getlong(cis, (c>>4)&0x3);
+ ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
+ }
+ ct->nio = nio;
+}
+
+static void
+irq(Cisdat *cis, PCMconftab *ct)
+{
+ uchar c;
+
+ if(readc(cis, &c) != 1)
+ return;
+ ct->irqtype = c & 0xe0;
+ if(c & 0x10)
+ ct->irqs = getlong(cis, 2);
+ else
+ ct->irqs = 1<<(c&0xf);
+ ct->irqs &= 0xDEB8; /* levels available to card */
+}
+
+static void
+memspace(Cisdat *cis, int asize, int lsize, int host)
+{
+ ulong haddress, address, len;
+
+ len = getlong(cis, lsize)*256;
+ address = getlong(cis, asize)*256;
+ USED(len, address);
+ if(host){
+ haddress = getlong(cis, asize)*256;
+ USED(haddress);
+ }
+}
+
+static void
+tentry(PCMslot *pp, Cisdat *cis, int )
+{
+ uchar c, i, feature;
+ PCMconftab *ct;
+
+ if(pp->nctab >= nelem(pp->ctab))
+ return;
+ if(readc(cis, &c) != 1)
+ return;
+ ct = &pp->ctab[pp->nctab++];
+
+ /* copy from last default config */
+ if(pp->def)
+ *ct = *pp->def;
+
+ ct->index = c & 0x3f;
+
+ /* is this the new default? */
+ if(c & 0x40)
+ pp->def = ct;
+
+ /* memory wait specified? */
+ if(c & 0x80){
+ if(readc(cis, &i) != 1)
+ return;
+ if(i&0x80)
+ ct->memwait = 1;
+ }
+
+ if(readc(cis, &feature) != 1)
+ return;
+ switch(feature&0x3){
+ case 1:
+ ct->vpp1 = ct->vpp2 = power(cis);
+ break;
+ case 2:
+ power(cis);
+ ct->vpp1 = ct->vpp2 = power(cis);
+ break;
+ case 3:
+ power(cis);
+ ct->vpp1 = power(cis);
+ ct->vpp2 = power(cis);
+ break;
+ default:
+ break;
+ }
+ if(feature&0x4)
+ timing(cis, ct);
+ if(feature&0x8)
+ iospaces(cis, ct);
+ if(feature&0x10)
+ irq(cis, ct);
+ switch((feature>>5)&0x3){
+ case 1:
+ memspace(cis, 0, 2, 0);
+ break;
+ case 2:
+ memspace(cis, 2, 2, 0);
+ break;
+ case 3:
+ if(readc(cis, &c) != 1)
+ return;
+ for(i = 0; i <= (c&0x7); i++)
+ memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
+ break;
+ }
+ pp->configed++;
+}
+
+static void
+tvers1(PCMslot *pp, Cisdat *cis, int )
+{
+ uchar c, major, minor, last;
+ int i;
+
+ if(readc(cis, &major) != 1)
+ return;
+ if(readc(cis, &minor) != 1)
+ return;
+ last = 0;
+ for(i = 0; i < sizeof(pp->verstr)-1; i++){
+ if(readc(cis, &c) != 1)
+ return;
+ if(c == 0)
+ c = ';';
+ if(c == '\n')
+ c = ';';
+ if(c == 0xff)
+ break;
+ if(c == ';' && last == ';')
+ continue;
+ pp->verstr[i] = c;
+ last = c;
+ }
+ pp->verstr[i] = 0;
+}
+
+static void
+tlonglnkmfc(PCMslot *pp, Cisdat *cis, int)
+{
+ int i, npos, opos;
+ uchar nfn, space, expect, type, this, link;
+
+ readc(cis, &nfn);
+ for(i = 0; i < nfn; i++){
+ readc(cis, &space);
+ npos = getlong(cis, 4);
+ opos = cis->cispos;
+ cis->cispos = npos;
+ expect = Linktarget;
+
+ while(1){
+ this = cis->cispos;
+ if(readc(cis, &type) != 1)
+ break;
+ if(type == 0xFF)
+ break;
+ if(readc(cis, &link) != 1)
+ break;
+
+ if(expect && expect != type){
+ print("tlonglnkmfc: expected %X found %X\n",
+ expect, type);
+ break;
+ }
+ expect = 0;
+
+ switch(type){
+ default:
+ break;
+ case 0x15:
+ tvers1(pp, cis, type);
+ break;
+ case 0x1A:
+ tcfig(pp, cis, type);
+ break;
+ case 0x1B:
+ tentry(pp, cis, type);
+ break;
+ }
+
+ if(link == 0xFF)
+ break;
+ cis->cispos = this + (2+link);
+ }
+ cis->cispos = opos;
+ }
+}
--- /dev/null
+++ b/os/boot.original/pc/clock.c
@@ -1,0 +1,309 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+/*
+ * 8253 timer
+ */
+enum
+{
+ T0cntr= 0x40, /* counter ports */
+ T1cntr= 0x41, /* ... */
+ T2cntr= 0x42, /* ... */
+ Tmode= 0x43, /* mode port */
+
+ /* commands */
+ Latch0= 0x00, /* latch counter 0's value */
+ Load0= 0x30, /* load counter 0 with 2 bytes */
+
+ /* modes */
+ Square= 0x36, /* perioic square wave */
+
+ Freq= 1193182, /* Real clock frequency */
+};
+
+static uvlong cpuhz = 66000000;
+static int cpumhz = 66;
+static int loopconst = 100;
+int cpuidax, cpuiddx;
+int havetsc;
+
+extern void _cycles(uvlong*); /* in l.s */
+extern void wrmsr(int, vlong);
+
+static void
+clockintr(Ureg*, void*)
+{
+ m->ticks++;
+ checkalarms();
+}
+
+#define STEPPING(x) ((x)&0xf)
+#define X86MODEL(x) (((x)>>4)&0xf)
+#define X86FAMILY(x) (((x)>>8)&0xf)
+
+enum
+{
+ /* flags */
+ CpuidFPU = 0x001, /* on-chip floating point unit */
+ CpuidMCE = 0x080, /* machine check exception */
+ CpuidCX8 = 0x100, /* CMPXCHG8B instruction */
+};
+
+typedef struct
+{
+ int family;
+ int model;
+ int aalcycles;
+ char *name;
+} X86type;
+
+X86type x86intel[] =
+{
+ { 4, 0, 22, "486DX", }, /* known chips */
+ { 4, 1, 22, "486DX50", },
+ { 4, 2, 22, "486SX", },
+ { 4, 3, 22, "486DX2", },
+ { 4, 4, 22, "486SL", },
+ { 4, 5, 22, "486SX2", },
+ { 4, 7, 22, "DX2WB", }, /* P24D */
+ { 4, 8, 22, "DX4", }, /* P24C */
+ { 4, 9, 22, "DX4WB", }, /* P24CT */
+ { 5, 0, 23, "P5", },
+ { 5, 1, 23, "P5", },
+ { 5, 2, 23, "P54C", },
+ { 5, 3, 23, "P24T", },
+ { 5, 4, 23, "P55C MMX", },
+ { 5, 7, 23, "P54C VRT", },
+ { 6, 1, 16, "PentiumPro", },/* trial and error */
+ { 6, 3, 16, "PentiumII", },
+ { 6, 5, 16, "PentiumII/Xeon", },
+ { 6, 6, 16, "Celeron", },
+ { 6, 7, 16, "PentiumIII/Xeon", },
+ { 6, 8, 16, "PentiumIII/Xeon", },
+ { 6, 0xB, 16, "PentiumIII/Xeon", },
+ { 0xF, 1, 16, "P4", }, /* P4 */
+ { 0xF, 2, 16, "PentiumIV/Xeon", },
+
+ { 3, -1, 32, "386", }, /* family defaults */
+ { 4, -1, 22, "486", },
+ { 5, -1, 23, "P5", },
+ { 6, -1, 16, "P6", },
+ { 0xF, -1, 16, "P4", }, /* P4 */
+
+ { -1, -1, 16, "unknown", }, /* total default */
+};
+
+
+/*
+ * The AMD processors all implement the CPUID instruction.
+ * The later ones also return the processor name via functions
+ * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX
+ * and DX:
+ * K5 "AMD-K5(tm) Processor"
+ * K6 "AMD-K6tm w/ multimedia extensions"
+ * K6 3D "AMD-K6(tm) 3D processor"
+ * K6 3D+ ?
+ */
+static X86type x86amd[] =
+{
+ { 5, 0, 23, "AMD-K5", }, /* guesswork */
+ { 5, 1, 23, "AMD-K5", }, /* guesswork */
+ { 5, 2, 23, "AMD-K5", }, /* guesswork */
+ { 5, 3, 23, "AMD-K5", }, /* guesswork */
+ { 5, 4, 23, "AMD Geode GX1", }, /* guesswork */
+ { 5, 5, 23, "AMD Geode GX2", }, /* guesswork */
+ { 5, 6, 11, "AMD-K6", }, /* trial and error */
+ { 5, 7, 11, "AMD-K6", }, /* trial and error */
+ { 5, 8, 11, "AMD-K6-2", }, /* trial and error */
+ { 5, 9, 11, "AMD-K6-III", },/* trial and error */
+ { 5, 0xa, 23, "AMD Geode LX", }, /* guesswork */
+
+ { 6, 1, 11, "AMD-Athlon", },/* trial and error */
+ { 6, 2, 11, "AMD-Athlon", },/* trial and error */
+
+ { 4, -1, 22, "Am486", }, /* guesswork */
+ { 5, -1, 23, "AMD-K5/K6", }, /* guesswork */
+ { 6, -1, 11, "AMD-Athlon", },/* guesswork */
+ { 0xF, -1, 11, "AMD64", }, /* guesswork */
+
+ { -1, -1, 11, "unknown", }, /* total default */
+};
+
+static X86type *cputype;
+
+
+void
+delay(int millisecs)
+{
+ millisecs *= loopconst;
+ if(millisecs <= 0)
+ millisecs = 1;
+ aamloop(millisecs);
+}
+
+void
+microdelay(int microsecs)
+{
+ microsecs *= loopconst;
+ microsecs /= 1000;
+ if(microsecs <= 0)
+ microsecs = 1;
+ aamloop(microsecs);
+}
+
+extern void cpuid(char*, int*, int*);
+
+X86type*
+cpuidentify(void)
+{
+ int family, model;
+ X86type *t;
+ char cpuidid[16];
+ int cpuidax, cpuiddx;
+
+ cpuid(cpuidid, &cpuidax, &cpuiddx);
+ if(strncmp(cpuidid, "AuthenticAMD", 12) == 0 ||
+ strncmp(cpuidid, "Geode by NSC", 12) == 0)
+ t = x86amd;
+ else
+ t = x86intel;
+ family = X86FAMILY(cpuidax);
+ model = X86MODEL(cpuidax);
+ if (0)
+ print("cpuidentify: cpuidax 0x%ux cpuiddx 0x%ux\n",
+ cpuidax, cpuiddx);
+ while(t->name){
+ if((t->family == family && t->model == model)
+ || (t->family == family && t->model == -1)
+ || (t->family == -1))
+ break;
+ t++;
+ }
+ if(t->name == nil)
+ panic("cpuidentify");
+
+ if(cpuiddx & 0x10){
+ havetsc = 1;
+ if(cpuiddx & 0x20)
+ wrmsr(0x10, 0);
+ }
+
+ return t;
+}
+
+void
+clockinit(void)
+{
+ uvlong a, b, cpufreq;
+ int loops, incr, x, y;
+ X86type *t;
+
+ /*
+ * set vector for clock interrupts
+ */
+ setvec(VectorCLOCK, clockintr, 0);
+
+ t = cpuidentify();
+
+ /*
+ * set clock for 1/HZ seconds
+ */
+ outb(Tmode, Load0|Square);
+ outb(T0cntr, (Freq/HZ)); /* low byte */
+ outb(T0cntr, (Freq/HZ)>>8); /* high byte */
+
+ /*
+ * Introduce a little delay to make sure the count is
+ * latched and the timer is counting down; with a fast
+ * enough processor this may not be the case.
+ * The i8254 (which this probably is) has a read-back
+ * command which can be used to make sure the counting
+ * register has been written into the counting element.
+ */
+ x = (Freq/HZ);
+ for(loops = 0; loops < 100000 && x >= (Freq/HZ); loops++){
+ outb(Tmode, Latch0);
+ x = inb(T0cntr);
+ x |= inb(T0cntr)<<8;
+ }
+
+ /* find biggest loop that doesn't wrap */
+ incr = 16000000/(t->aalcycles*HZ*2);
+ x = 2000;
+ for(loops = incr; loops < 64*1024; loops += incr) {
+
+ /*
+ * measure time for the loop
+ *
+ * MOVL loops,CX
+ * aaml1: AAM
+ * LOOP aaml1
+ *
+ * the time for the loop should be independent of external
+ * cache and memory system since it fits in the execution
+ * prefetch buffer.
+ *
+ */
+ outb(Tmode, Latch0);
+ if(havetsc)
+ _cycles(&a);
+ x = inb(T0cntr);
+ x |= inb(T0cntr)<<8;
+ aamloop(loops);
+ outb(Tmode, Latch0);
+ if(havetsc)
+ _cycles(&b);
+ y = inb(T0cntr);
+ y |= inb(T0cntr)<<8;
+ x -= y;
+
+ if(x < 0)
+ x += Freq/HZ;
+
+ if(x > Freq/(3*HZ))
+ break;
+ }
+
+ /*
+ * figure out clock frequency and a loop multiplier for delay().
+ * counter goes at twice the frequency, once per transition,
+ * i.e., twice per square wave
+ */
+ cpufreq = (vlong)loops*((t->aalcycles*2*Freq)/x);
+ loopconst = (cpufreq/1000)/t->aalcycles; /* AAM+LOOP's for 1 ms */
+
+ if(havetsc){
+ /* counter goes up by 2*Freq */
+ b = (b-a)<<1;
+ b *= Freq;
+ b /= x;
+
+ /*
+ * round to the nearest megahz
+ */
+ cpumhz = (b+500000)/1000000L;
+ cpuhz = b;
+ }
+ else{
+ /*
+ * add in possible .5% error and convert to MHz
+ */
+ cpumhz = (cpufreq + cpufreq/200)/1000000;
+ cpuhz = cpufreq;
+ }
+
+ if(debug){
+ int timeo;
+
+ print("%dMHz %s loop %d\n", cpumhz, t->name, loopconst);
+ print("tick...");
+ for(timeo = 0; timeo < 10; timeo++)
+ delay(1000);
+ print("tock...\n");
+ }
+}
--- /dev/null
+++ b/os/boot.original/pc/conf.c
@@ -1,0 +1,537 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "fs.h"
+
+/*
+ * Where configuration info is left for the loaded programme.
+ * This will turn into a structure as more is done by the boot loader
+ * (e.g. why parse the .ini file twice?).
+ * There are 3584 bytes available at CONFADDR.
+ *
+ * The low-level boot routines in l.s leave data for us at CONFADDR,
+ * which we pick up before reading the plan9.ini file.
+ */
+#define BOOTLINELEN 64
+#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
+#define BOOTARGSLEN (3584-0x200-BOOTLINELEN)
+#define MAXCONF 100
+
+static char *confname[MAXCONF];
+static char *confval[MAXCONF];
+static int nconf;
+
+extern char **ini;
+
+typedef struct {
+ char* name;
+ int start;
+ int end;
+} Mblock;
+
+typedef struct {
+ char* tag;
+ Mblock* mb;
+} Mitem;
+
+static Mblock mblock[MAXCONF];
+static int nmblock;
+static Mitem mitem[MAXCONF];
+static int nmitem;
+static char* mdefault;
+static char mdefaultbuf[10];
+static int mtimeout;
+
+static char*
+comma(char* line, char** residue)
+{
+ char *q, *r;
+
+ if((q = strchr(line, ',')) != nil){
+ *q++ = 0;
+ if(*q == ' ')
+ q++;
+ }
+ *residue = q;
+
+ if((r = strchr(line, ' ')) != nil)
+ *r = 0;
+
+ if(*line == ' ')
+ line++;
+ return line;
+}
+
+static Mblock*
+findblock(char* name, char** residue)
+{
+ int i;
+ char *p;
+
+ p = comma(name, residue);
+ for(i = 0; i < nmblock; i++){
+ if(strcmp(p, mblock[i].name) == 0)
+ return &mblock[i];
+ }
+ return nil;
+}
+
+static Mitem*
+finditem(char* name, char** residue)
+{
+ int i;
+ char *p;
+
+ p = comma(name, residue);
+ for(i = 0; i < nmitem; i++){
+ if(strcmp(p, mitem[i].mb->name) == 0)
+ return &mitem[i];
+ }
+ return nil;
+}
+
+static void
+parsemenu(char* str, char* scratch, int len)
+{
+ Mitem *mi;
+ Mblock *mb, *menu;
+ char buf[20], *p, *q, *line[MAXCONF];
+ int i, inblock, n, show;
+
+ inblock = 0;
+ menu = nil;
+ memmove(scratch, str, len);
+ n = getfields(scratch, line, MAXCONF, '\n');
+ if(n >= MAXCONF)
+ print("warning: possibly too many lines in plan9.ini\n");
+ for(i = 0; i < n; i++){
+ p = line[i];
+ if(inblock && *p == '['){
+ mblock[nmblock].end = i;
+ if(strcmp(mblock[nmblock].name, "menu") == 0)
+ menu = &mblock[nmblock];
+ nmblock++;
+ inblock = 0;
+ }
+ if(*p == '['){
+ if(nmblock == 0 && i != 0){
+ mblock[nmblock].name = "common";
+ mblock[nmblock].start = 0;
+ mblock[nmblock].end = i;
+ nmblock++;
+ }
+ q = strchr(p+1, ']');
+ if(q == nil || *(q+1) != 0){
+ print("malformed menu block header - %s\n", p);
+ return;
+ }
+ *q = 0;
+ mblock[nmblock].name = p+1;
+ mblock[nmblock].start = i+1;
+ inblock = 1;
+ }
+ }
+
+ if(inblock){
+ mblock[nmblock].end = i;
+ nmblock++;
+ }
+ if(menu == nil)
+ return;
+ if(nmblock < 2){
+ print("incomplete menu specification\n");
+ return;
+ }
+
+ for(i = menu->start; i < menu->end; i++){
+ p = line[i];
+ if(cistrncmp(p, "menuitem=", 9) == 0){
+ p += 9;
+ if((mb = findblock(p, &q)) == nil){
+ print("no block for menuitem %s\n", p);
+ return;
+ }
+ if(q != nil)
+ mitem[nmitem].tag = q;
+ else
+ mitem[nmitem].tag = mb->name;
+ mitem[nmitem].mb = mb;
+ nmitem++;
+ }
+ else if(cistrncmp(p, "menudefault=", 12) == 0){
+ p += 12;
+ if((mi = finditem(p, &q)) == nil){
+ print("no item for menudefault %s\n", p);
+ return;
+ }
+ if(q != nil)
+ mtimeout = strtol(q, 0, 0);
+ sprint(mdefaultbuf, "%ld", mi-mitem+1);
+ mdefault = mdefaultbuf;
+ }
+ else if(cistrncmp(p, "menuconsole=", 12) == 0){
+ p += 12;
+ p = comma(p, &q);
+ consinit(p, q);
+ }
+ else{
+ print("invalid line in [menu] block - %s\n", p);
+ return;
+ }
+ }
+
+again:
+ print("\nPlan 9 Startup Menu:\n====================\n");
+ for(i = 0; i < nmitem; i++)
+ print(" %d. %s\n", i+1, mitem[i].tag);
+ for(;;){
+ getstr("Selection", buf, sizeof(buf), mdefault, mtimeout);
+ mtimeout = 0;
+ i = strtol(buf, &p, 0)-1;
+ if(i < 0 || i >= nmitem)
+ goto again;
+ switch(*p){
+ case 'p':
+ case 'P':
+ show = 1;
+ print("\n");
+ break;
+ case 0:
+ show = 0;
+ break;
+ default:
+ continue;
+
+ }
+ mi = &mitem[i];
+
+ p = str;
+ p += sprint(p, "menuitem=%s\n", mi->mb->name);
+ for(i = 0; i < nmblock; i++){
+ mb = &mblock[i];
+ if(mi->mb != mb && cistrcmp(mb->name, "common") != 0)
+ continue;
+ for(n = mb->start; n < mb->end; n++)
+ p += sprint(p, "%s\n", line[n]);
+ }
+
+ if(show){
+ for(q = str; q < p; q += i){
+ if((i = print(q)) <= 0)
+ break;
+ }
+ goto again;
+ }
+ break;
+ }
+ print("\n");
+}
+
+/*
+static void
+msleep(int msec)
+{
+ ulong start;
+
+ for(start = m->ticks; TK2MS(m->ticks - start) < msec; )
+ ;
+}
+*/
+
+void
+readlsconf(void)
+{
+ uchar *p;
+
+ p = (uchar*)CONFADDR;
+ for(;;) {
+ if(strcmp((char*)p, "APM") == 0){
+ apm.haveinfo = 1;
+ apm.ax = *(ushort*)(p+4);
+ apm.cx = *(ushort*)(p+6);
+ apm.dx = *(ushort*)(p+8);
+ apm.di = *(ushort*)(p+10);
+ apm.ebx = *(ulong*)(p+12);
+ apm.esi = *(ulong*)(p+16);
+ print("apm ax=%x cx=%x dx=%x di=%x ebx=%x esi=%x\n",
+ apm.ax, apm.cx, apm.dx, apm.di, apm.ebx, apm.esi);
+ p += 20;
+ continue;
+ }
+ break;
+ }
+}
+
+char*
+getconf(char *name)
+{
+ int i, n, nmatch;
+ char buf[20];
+
+ nmatch = 0;
+ for(i = 0; i < nconf; i++)
+ if(cistrcmp(confname[i], name) == 0)
+ nmatch++;
+
+ switch(nmatch) {
+ default:
+ print("\n");
+ nmatch = 0;
+ for(i = 0; i < nconf; i++)
+ if(cistrcmp(confname[i], name) == 0)
+ print("%d. %s\n", ++nmatch, confval[i]);
+ print("%d. none of the above\n", ++nmatch);
+ do {
+ getstr(name, buf, sizeof(buf), nil, 0);
+ n = atoi(buf);
+ } while(n < 1 || n > nmatch);
+
+ for(i = 0; i < nconf; i++)
+ if(cistrcmp(confname[i], name) == 0)
+ if(--n == 0)
+ return confval[i];
+ break;
+
+ case 1:
+ for(i = 0; i < nconf; i++)
+ if(cistrcmp(confname[i], name) == 0)
+ return confval[i];
+ break;
+
+ case 0:
+ break;
+ }
+ return nil;
+}
+
+void
+addconf(char *fmt, ...)
+{
+ va_list arg;
+
+ va_start(arg, fmt);
+ vseprint(BOOTARGS+strlen(BOOTARGS), BOOTARGS+BOOTARGSLEN, fmt, arg);
+ va_end(arg);
+}
+
+void
+changeconf(char *fmt, ...)
+{
+ va_list arg;
+ char *p, *q, pref[20], buf[128];
+
+ va_start(arg, fmt);
+ vseprint(buf, buf+sizeof buf, fmt, arg);
+ va_end(arg);
+ strncpy(pref+1, buf, 19);
+ pref[19] = '\0';
+ if(p = strchr(pref, '='))
+ *(p+1) = '\0';
+ else
+ print("warning: did not change %s in plan9.ini\n", buf);
+
+ /* find old line by looking for \nwhat= */
+ pref[0] = '\n';
+ if(strncmp(BOOTARGS, pref+1, strlen(pref+1)) == 0)
+ p = BOOTARGS;
+ else if(p = strstr(BOOTARGS, pref))
+ p++;
+ else
+ p = nil;
+
+ /* move rest of args up, deleting what= line. */
+ if(p != nil && (q = strchr(p, '\n')) != nil)
+ memmove(p, q+1, strlen(q+1)+1);
+
+ /* add replacement to end */
+ addconf("%s", buf);
+}
+
+/*
+ * read configuration file
+ */
+static char inibuf[BOOTARGSLEN];
+static char id[8] = "ZORT 0\r\n";
+
+int
+dotini(Fs *fs)
+{
+ File rc;
+ int blankline, i, incomment, inspace, n;
+ char *cp, *p, *q, *line[MAXCONF];
+
+ if(fswalk(fs, *ini, &rc) <= 0)
+ return -1;
+
+ cp = inibuf;
+ *cp = 0;
+ n = fsread(&rc, cp, BOOTARGSLEN-1);
+ if(n <= 0)
+ return -1;
+
+ cp[n] = 0;
+
+ /*
+ * Strip out '\r', change '\t' -> ' '.
+ * Change runs of spaces into single spaces.
+ * Strip out trailing spaces, blank lines.
+ *
+ * We do this before we make the copy so that if we
+ * need to change the copy, it is already fairly clean.
+ * The main need is in the case when plan9.ini has been
+ * padded with lots of trailing spaces, as is the case
+ * for those created during a distribution install.
+ */
+ p = cp;
+ blankline = 1;
+ incomment = inspace = 0;
+ for(q = cp; *q; q++){
+ if(*q == '\r')
+ continue;
+ if(*q == '\t')
+ *q = ' ';
+ if(*q == ' '){
+ inspace = 1;
+ continue;
+ }
+ if(*q == '\n'){
+ if(!blankline){
+ if(!incomment)
+ *p++ = '\n';
+ blankline = 1;
+ }
+ incomment = inspace = 0;
+ continue;
+ }
+ if(inspace){
+ if(!blankline && !incomment)
+ *p++ = ' ';
+ inspace = 0;
+ }
+ if(blankline && *q == '#')
+ incomment = 1;
+ blankline = 0;
+ if(!incomment)
+ *p++ = *q;
+ }
+ if(p > cp && p[-1] != '\n')
+ *p++ = '\n';
+ *p++ = 0;
+ n = p-cp;
+
+ parsemenu(cp, BOOTARGS, n);
+
+ /*
+ * Keep a copy.
+ * We could change this to pass the parsed strings
+ * to the booted programme instead of the raw
+ * string, then it only gets done once.
+ */
+ if(strncmp(cp, id, sizeof(id))){
+ memmove(BOOTARGS, id, sizeof(id));
+ if(n+1+sizeof(id) >= BOOTARGSLEN)
+ n -= sizeof(id);
+ memmove(BOOTARGS+sizeof(id), cp, n+1);
+ }
+ else
+ memmove(BOOTARGS, cp, n+1);
+
+ n = getfields(cp, line, MAXCONF, '\n');
+ for(i = 0; i < n; i++){
+ cp = strchr(line[i], '=');
+ if(cp == 0)
+ continue;
+ *cp++ = 0;
+ if(cp - line[i] >= NAMELEN+1)
+ *(line[i]+NAMELEN-1) = 0;
+ confname[nconf] = line[i];
+ confval[nconf] = cp;
+ nconf++;
+ }
+ return 0;
+}
+
+static int
+parseether(uchar *to, char *from)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ while(*p == ' ')
+ ++p;
+ for(i = 0; i < 6; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ char cc[NAMELEN], *p, *q, *r;
+ int n;
+
+ sprint(cc, "%s%d", class, ctlrno);
+ for(n = 0; n < nconf; n++){
+ if(cistrncmp(confname[n], cc, NAMELEN))
+ continue;
+ isa->nopt = 0;
+ p = confval[n];
+ while(*p){
+ while(*p == ' ' || *p == '\t')
+ p++;
+ if(*p == '\0')
+ break;
+ if(cistrncmp(p, "type=", 5) == 0){
+ p += 5;
+ for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
+ if(*p == '\0' || *p == ' ' || *p == '\t')
+ break;
+ *q = *p++;
+ }
+ *q = '\0';
+ }
+ else if(cistrncmp(p, "port=", 5) == 0)
+ isa->port = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "irq=", 4) == 0)
+ isa->irq = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "mem=", 4) == 0)
+ isa->mem = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "size=", 5) == 0)
+ isa->size = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "ea=", 3) == 0){
+ if(parseether(isa->ea, p+3) == -1)
+ memset(isa->ea, 0, 6);
+ }
+ else if(isa->nopt < NISAOPT){
+ r = isa->opt[isa->nopt];
+ while(*p && *p != ' ' && *p != '\t'){
+ *r++ = *p++;
+ if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
+ break;
+ }
+ *r = '\0';
+ isa->nopt++;
+ }
+ while(*p && *p != ' ' && *p != '\t')
+ p++;
+ }
+ return 1;
+ }
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/console.c
@@ -1,0 +1,236 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+IOQ consiq;
+IOQ consoq;
+
+static int useuart;
+
+int debug = 0;
+
+void
+kbdchar(int c)
+{
+ c &= 0x7F;
+ if(c == 0x10)
+ warp86("\n^P\n", 0);
+ if(c == 0x12)
+ debug = !debug;
+ consiq.putc(&consiq, c);
+}
+
+static int
+consputc(void)
+{
+ return consoq.getc(&consoq);
+}
+
+void
+kbdinit(void)
+{
+ i8042init();
+ qinit(&consiq);
+}
+
+void
+consinit(char* name, char* speed)
+{
+ int baud, port;
+
+ if(name == nil || cistrcmp(name, "cga") == 0)
+ return;
+ port = strtoul(name, 0, 0);
+ if(port < 0 || port > 1)
+ return;
+ if(speed == nil || (baud = strtoul(speed, 0, 0)) == 0)
+ baud = 9600;
+
+ qinit(&consoq);
+
+ uartspecial(port, kbdchar, consputc, baud);
+ useuart = 1;
+ uartputs(&consoq, "\n", 1);
+}
+
+void
+consdrain(void)
+{
+ if(useuart)
+ uartdrain();
+}
+
+void
+consputs(char* s, int n)
+{
+ cgascreenputs(s, n);
+ if(useuart)
+ uartputs(&consoq, s, n);
+}
+
+void
+warp86(char* s, ulong)
+{
+ if(s != nil)
+ print(s);
+ spllo();
+ consdrain();
+
+ i8042reset();
+ print("Takes a licking and keeps on ticking...\n");
+ for(;;)
+ idle();
+}
+
+static int
+getline(char *buf, int size, int timeout)
+{
+ int c, i=0;
+ ulong start;
+ char echo;
+
+ for (;;) {
+ start = m->ticks;
+ do{
+ /* timeout seconds to first char */
+ if(timeout && ((m->ticks - start) > timeout*HZ))
+ return -2;
+ c = consiq.getc(&consiq);
+ }while(c == -1);
+ timeout = 0;
+
+ if(c == '\r')
+ c = '\n'; /* turn carriage return into newline */
+ if(c == '\177')
+ c = '\010'; /* turn delete into backspace */
+ if(c == '\025')
+ echo = '\n'; /* echo ^U as a newline */
+ else
+ echo = c;
+ consputs(&echo, 1);
+
+ if(c == '\010'){
+ if(i > 0)
+ i--; /* bs deletes last character */
+ continue;
+ }
+ /* a newline ends a line */
+ if (c == '\n')
+ break;
+ /* ^U wipes out the line */
+ if (c =='\025')
+ return -1;
+ if(i == size)
+ return size;
+ buf[i++] = c;
+ }
+ buf[i] = 0;
+ return i;
+}
+
+int
+getstr(char *prompt, char *buf, int size, char *def, int timeout)
+{
+ int len, isdefault;
+ char pbuf[PRINTSIZE];
+
+ buf[0] = 0;
+ isdefault = (def && *def);
+ if(isdefault == 0){
+ timeout = 0;
+ sprint(pbuf, "%s: ", prompt);
+ }
+ else if(timeout)
+ sprint(pbuf, "%s[default==%s (%ds timeout)]: ", prompt, def, timeout);
+ else
+ sprint(pbuf, "%s[default==%s]: ", prompt, def);
+ for (;;) {
+ print(pbuf);
+ len = getline(buf, size, timeout);
+ switch(len){
+ case 0:
+ /* RETURN */
+ if(isdefault)
+ break;
+ continue;
+ case -1:
+ /* ^U typed */
+ continue;
+ case -2:
+ /* timeout, use default */
+ consputs("\n", 1);
+ len = 0;
+ break;
+ default:
+ break;
+ }
+ if(len >= size){
+ print("line too long\n");
+ continue;
+ }
+ break;
+ }
+ if(len == 0 && isdefault)
+ strcpy(buf, def);
+ return 0;
+}
+
+int
+print(char *fmt, ...)
+{
+ int n;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+ consputs(buf, n);
+
+ return n;
+}
+
+int
+sprint(char *s, char *fmt, ...)
+{
+ int n;
+ va_list arg;
+
+ va_start(arg, fmt);
+ n = vseprint(s, s+PRINTSIZE, fmt, arg) - s;
+ va_end(arg);
+
+ return n;
+}
+
+void
+panic(char *fmt, ...)
+{
+ int n;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ strcpy(buf, "panic: ");
+ va_start(arg, fmt);
+ n = vseprint(buf+7, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+ buf[n] = '\n';
+ consputs(buf, n+1);
+
+//floppymemwrite();
+//splhi(); for(;;);
+ if(etherdetach)
+ etherdetach();
+ if(sddetach)
+ sddetach();
+
+ consputs("\nPress almost any key to reset...", 32);
+ spllo();
+ while(consiq.getc(&consiq) == -1)
+ ;
+
+ warp86(nil, 0);
+}
--- /dev/null
+++ b/os/boot.original/pc/dat.h
@@ -1,0 +1,215 @@
+typedef struct List {
+ void *next;
+} List;
+
+typedef struct Alarm Alarm;
+typedef struct Alarm {
+ List;
+ int busy;
+ long dt;
+ void (*f)(Alarm*);
+ void *arg;
+} Alarm;
+
+typedef struct Apminfo {
+ int haveinfo;
+ int ax;
+ int cx;
+ int dx;
+ int di;
+ int ebx;
+ int esi;
+} Apminfo;
+
+typedef struct Block Block;
+struct Block {
+ Block* next;
+ uchar* rp; /* first unconsumed byte */
+ uchar* wp; /* first empty byte */
+ uchar* lim; /* 1 past the end of the buffer */
+ uchar* base; /* start of the buffer */
+ ulong flag;
+};
+#define BLEN(s) ((s)->wp - (s)->rp)
+
+typedef struct IOQ IOQ;
+typedef struct IOQ {
+ uchar buf[4096];
+ uchar *in;
+ uchar *out;
+ int state;
+ int (*getc)(IOQ*);
+ int (*putc)(IOQ*, int);
+ void *ptr;
+};
+
+enum {
+ Eaddrlen = 6,
+ /* next two exclude 4-byte ether CRC */
+ ETHERMINTU = 60, /* minimum transmit size */
+ ETHERMAXTU = 1514, /* maximum transmit size */
+ ETHERHDRSIZE = 14, /* size of an ethernet header */
+
+ MaxEther = 6,
+};
+
+typedef struct {
+ uchar d[Eaddrlen];
+ uchar s[Eaddrlen];
+ uchar type[2];
+ uchar data[1500];
+ uchar crc[4];
+} Etherpkt;
+
+extern uchar broadcast[Eaddrlen];
+
+typedef struct Ureg Ureg;
+#pragma incomplete Ureg
+
+typedef struct Segdesc {
+ ulong d0;
+ ulong d1;
+} Segdesc;
+
+typedef struct Mach {
+ ulong ticks; /* of the clock since boot time */
+ void *alarm; /* alarms bound to this clock */
+} Mach;
+
+extern Mach *m;
+
+#define I_MAGIC ((((4*11)+0)*11)+7)
+
+typedef struct Exec Exec;
+struct Exec
+{
+ uchar magic[4]; /* magic number */
+ uchar text[4]; /* size of text segment */
+ uchar data[4]; /* size of initialized data */
+ uchar bss[4]; /* size of uninitialized data */
+ uchar syms[4]; /* size of symbol table */
+ uchar entry[4]; /* entry point */
+ uchar spsz[4]; /* size of sp/pc offset table */
+ uchar pcsz[4]; /* size of pc/line number table */
+};
+
+/*
+ * a parsed .ini line
+ */
+#define ISAOPTLEN 32
+#define NISAOPT 8
+
+typedef struct ISAConf {
+ char type[NAMELEN];
+ ulong port;
+ ulong irq;
+ ulong mem;
+ ulong size;
+ uchar ea[6];
+
+ int nopt;
+ char opt[NISAOPT][ISAOPTLEN];
+} ISAConf;
+
+typedef struct Pcidev Pcidev;
+typedef struct PCMmap PCMmap;
+typedef struct PCMslot PCMslot;
+
+#define BOOTLINE ((char*)CONFADDR)
+
+enum {
+ MB = (1024*1024),
+};
+#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1))
+
+
+typedef struct Type Type;
+typedef struct Medium Medium;
+typedef struct Boot Boot;
+
+enum { /* type */
+ Tnil = 0x00,
+
+ Tfloppy = 0x01,
+ Tsd = 0x02,
+ Tether = 0x03,
+ Tcd = 0x04,
+ Tbios = 0x05,
+
+ Tany = -1,
+};
+
+enum { /* name and flag */
+ Fnone = 0x00,
+
+ Nfs = 0x00,
+ Ffs = (1<<Nfs),
+ Nboot = 0x01,
+ Fboot = (1<<Nboot),
+ Nbootp = 0x02,
+ Fbootp = (1<<Nbootp),
+ NName = 3,
+
+ Fany = Fbootp|Fboot|Ffs,
+
+ Fini = 0x10,
+ Fprobe = 0x80,
+};
+
+typedef struct Type {
+ int type;
+ int flag;
+ int (*init)(void);
+ void (*initdev)(int, char*);
+ void* (*getfspart)(int, char*, int); /* actually returns Dos* */
+ void (*addconf)(int);
+ int (*boot)(int, char*, Boot*);
+ void (*printdevs)(int);
+ char** parts;
+ char** inis;
+ int mask;
+ Medium* media;
+} Type;
+
+extern void (*etherdetach)(void);
+extern void (*floppydetach)(void);
+extern void (*sddetach)(void);
+
+typedef struct Lock { /* for ilock, iunlock */
+ int locked;
+ int spl;
+} Lock;
+
+enum { /* returned by bootpass */
+ MORE, ENOUGH, FAIL
+};
+enum {
+ INITKERNEL,
+ READEXEC,
+ READ9TEXT,
+ READ9DATA,
+ READGZIP,
+ READEHDR,
+ READPHDR,
+ READEPAD,
+ READEDATA,
+ TRYBOOT,
+ INIT9LOAD,
+ READ9LOAD,
+ FAILED
+};
+
+struct Boot {
+ int state;
+
+ Exec exec;
+ char *bp; /* base ptr */
+ char *wp; /* write ptr */
+ char *ep; /* end ptr */
+};
+
+extern int debug;
+extern Apminfo apm;
+extern char *defaultpartition;
+extern int iniread;
+extern int pxe;
--- /dev/null
+++ b/os/boot.original/pc/devbios.c
@@ -1,0 +1,428 @@
+/*
+ * boot driver for BIOS devices
+ */
+#include <u.h>
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "fs.h"
+
+typedef uvlong Devbytes, Devsects;
+
+typedef struct Biosdrive Biosdrive; /* 1 drive -> ndevs */
+typedef struct Biosdev Biosdev;
+
+enum {
+ Debug = 0,
+ Maxdevs = 4,
+
+ CF = 1,
+ Flopid = 0, /* first floppy */
+ Baseid = 0x80, /* first disk */
+
+ /* bios calls: int 13 disk services */
+ Biosinit = 0, /* initialise disk & floppy ctlrs */
+ Biosdrvsts,
+ Bioschsrdsects,
+ Biosdrvparam = 8,
+ Biosctlrinit,
+ Biosreset = 0xd, /* reset disk */
+ Biosdrvrdy = 0x10,
+ Biosdrvtype = 0x15,
+ Biosckext = 0x41,
+ Biosrdsect,
+ Biosedrvparam = 0x48,
+
+ /* disk types */
+ Typenone = 0,
+ Typedisk = 3,
+};
+
+struct Biosdrive {
+ int ndevs;
+};
+struct Biosdev {
+ Devbytes size;
+ Devbytes offset;
+ uchar id; /* drive number; e.g., 0x80 */
+ char type;
+ ushort sectsz;
+};
+
+typedef struct Extread {
+ uchar size;
+ uchar unused1;
+ uchar nsects;
+ uchar unused2;
+ ulong addr; /* segment:offset */
+ uvlong stsect; /* starting sector */
+} Extread;
+typedef struct Edrvparam {
+ /* from edd 1.1 spec */
+ ushort size; /* max. buffer size */
+ ushort flags;
+ ulong physcyls;
+ ulong physheads;
+ ulong phystracksects;
+ uvlong physsects;
+ ushort sectsz;
+ void *dpte; /* ~0ull: invalid */
+
+ /* remainder from edd 3.0 spec */
+ ushort key; /* 0xbedd if present */
+ uchar dpilen;
+ uchar unused1;
+ ushort unused2;
+ char bustype[4]; /* "PCI" or "ISA" */
+ char ifctype[8]; /* "ATA", "ATAPI", "SCSI", "USB", "1394", "FIBRE" */
+ uvlong ifcpath;
+ uvlong devpath;
+ uchar unused3;
+ uchar dpicksum;
+} Edrvparam;
+
+void realmode(int intr, Ureg *ureg); /* from trap.c */
+
+int onlybios0;
+int biosinited;
+
+static Biosdev bdev[Maxdevs];
+static Biosdrive bdrive;
+static Ureg regs;
+
+static int dreset(uchar drive);
+static Devbytes extgetsize(Biosdev *);
+static Devsects getsize(uchar drive, char *type);
+static int islba(uchar drive);
+
+static int
+biosdiskcall(Ureg *rp, uchar op, ulong bx, ulong dx, ulong si)
+{
+ memset(rp, 0, sizeof *rp);
+ rp->ax = op << 8;
+ rp->bx = bx;
+ rp->dx = dx; /* often drive id */
+ rp->si = si;
+ /* pass command in *rp, get results from there */
+ realmode(0x13, rp);
+ if (rp->flags & CF) {
+// print("biosdiskcall: int 13 op 0x%ux drive 0x%lux failed, "
+// "ah error code 0x%ux\n", op, dx, (uchar)(rp->ax >> 8));
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Find out what the bios knows about devices.
+ * our boot device could be usb; ghod only knows where it will appear.
+ */
+int
+biosinit(void)
+{
+ int devid, lba, mask, lastbit;
+ Devbytes size;
+ char type;
+ Biosdev *bdp;
+ static int beenhere;
+
+ mask = lastbit = 0;
+ if (beenhere)
+ return mask;
+ beenhere = 1;
+ /* 9pxeload can't use bios int 13 calls; they wedge the machine */
+ if (pxe || getconf("*nobiosload") != nil || onlybios0 || !biosinited)
+ return mask;
+ for (devid = 0; devid < (1 << 8) && bdrive.ndevs < Maxdevs; devid++) {
+ lba = islba(devid);
+ if(!lba /* || devid != Baseid && dreset(devid) < 0 */ )
+ continue;
+ type = Typedisk; /* HACK */
+ if (getsize(devid, &type) == 0) { /* no device, end of range */
+ devid &= ~0xf;
+ devid += 0x10;
+ devid--;
+ continue;
+ }
+ lastbit = 1 << bdrive.ndevs;
+ mask |= lastbit;
+ bdp = &bdev[bdrive.ndevs];
+ bdp->id = devid;
+ bdp->type = type;
+ size = extgetsize(bdp);
+ bdp->size = size;
+ print("bios%d: drive 0x%ux: %llud bytes, type %d\n",
+ bdrive.ndevs, devid, size, type);
+ bdrive.ndevs++;
+ }
+ /*
+ * bioses seem to only be able to read from drive number 0x80
+ * and certainly can't read from the highest drive number when we
+ * call them, even if there is only one. attempting to read from
+ * the last drive number yields a hung machine or a two-minute pause.
+ */
+ if (bdrive.ndevs > 0) {
+ if (bdrive.ndevs == 1) {
+ print("biosinit: sorry, only one bios drive; "
+ "can't read last one\n");
+ onlybios0 = 1;
+ } else
+ biosinited = 1;
+ bdrive.ndevs--; /* omit last drive number; it can't be read */
+ mask &= ~lastbit;
+ }
+ return mask;
+}
+
+void
+biosinitdev(int i, char *name)
+{
+ if(i >= bdrive.ndevs)
+ panic("biosinitdev");
+ sprint(name, "bios%d", i);
+}
+
+void
+biosprintdevs(int i)
+{
+ if(i >= bdrive.ndevs){
+ print("got a print for %d, only got %d\n", i, bdrive.ndevs);
+ panic("biosprintdevs");
+ }
+ print(" bios%d", i);
+}
+
+int
+biosboot(int dev, char *file, Boot *b)
+{
+ Fs *fs;
+
+ if(strncmp(file, "dos!", 4) == 0)
+ file += 4;
+ if(strchr(file, '!') != nil || strcmp(file, "") == 0) {
+ print("syntax is bios0!file\n");
+ return -1;
+ }
+
+ fs = biosgetfspart(dev, "9fat", 1);
+ if(fs == nil)
+ return -1;
+ return fsboot(fs, file, b);
+}
+
+/* read n bytes at sector offset into a from drive id */
+long
+sectread(Biosdev *bdp, void *a, long n, Devsects offset)
+{
+ uchar *biosparam, *cp;
+ Extread *erp;
+
+ if(n < 0 || n > bdp->sectsz)
+ return -1;
+ if(Debug)
+ memset((uchar *)BIOSXCHG, 'r', bdp->sectsz); /* preclean the buffer. */
+
+ biosdiskcall(®s, Biosdrvrdy, 0, bdp->id, 0);
+
+ /* space for a BIG sector, just in case... */
+ biosparam = (uchar *)BIOSXCHG + 2*1024;
+
+ /* read into BIOSXCHG */
+ erp = (Extread *)biosparam;
+ memset(erp, 0, sizeof *erp);
+ erp->size = sizeof *erp;
+ erp->nsects = 1;
+ erp->addr = PADDR(BIOSXCHG);
+ erp->stsect = offset;
+ if (biosdiskcall(®s, Biosrdsect, 0, bdp->id, PADDR(erp)) < 0) {
+ print("sectread: bios failed to read %ld @ sector %lld of 0x%ux\n",
+ n, offset, bdp->id);
+ return -1;
+ }
+
+ /* copy into caller's buffer */
+ memmove(a, (char *)BIOSXCHG, n);
+ if(Debug){
+ cp = (uchar *)BIOSXCHG;
+ print("-%ux %ux %ux %ux--%16.16s-\n",
+ cp[0], cp[1], cp[2], cp[3], (char *)cp + 480);
+ }
+ return n;
+}
+
+/* not tested yet. */
+static int
+dreset(uchar drive)
+{
+if (0) {
+print("devbios: resetting disk controllers...");
+ biosdiskcall(®s, Biosinit, 0, drive, 0);
+print("\n");
+}
+ return regs.ax? -1: 0; /* ax!=0 on error */
+}
+
+static int
+islba(uchar drive)
+{
+ if (biosdiskcall(®s, Biosckext, 0x55aa, drive, 0) < 0)
+ return 0;
+ if(regs.bx != 0xaa55){
+ print("islba: buggy bios\n");
+ return 0;
+ }
+ if (Debug)
+ print("islba: drive 0x%ux extensions version %d.%d cx 0x%lux\n",
+ drive, (uchar)(regs.ax >> 8),
+ (uchar)regs.ax, regs.cx); /* cx: 4=edd, 1=use dap */
+ return regs.cx & 1; /* dap bit */
+}
+
+/*
+ * works so so... some floppies are 0x80+x when they shouldn't be,
+ * and report lba even if they cannot...
+ */
+static Devsects
+getsize(uchar id, char *typep)
+{
+ int dtype;
+
+ if (biosdiskcall(®s, Biosdrvtype, 0x55aa, id, 0) < 0)
+ return 0;
+
+ dtype = (ushort)regs.ax >> 8;
+ if(dtype == Typenone){
+ print("no such device 0x%ux of type %d\n", id, dtype);
+ return 0;
+ }
+ if(dtype != Typedisk){
+ print("non-disk device 0x%ux of type %d\n", id, dtype);
+ return 0;
+ }
+ *typep = dtype;
+ return (ushort)regs.cx | regs.dx << 16;
+}
+
+/* extended get size */
+static Devbytes
+extgetsize(Biosdev *bdp)
+{
+ Edrvparam *edp;
+
+ edp = (Edrvparam *)BIOSXCHG;
+ memset(edp, 0, sizeof *edp);
+ edp->size = sizeof *edp;
+ edp->dpilen = 36;
+ if (biosdiskcall(®s, Biosedrvparam, 0, bdp->id, PADDR(edp)) < 0)
+ return 0;
+ if(Debug) {
+ print("extgetsize: drive 0x%ux info flags 0x%ux",
+ bdp->id, edp->flags);
+ if (edp->key == 0xbedd)
+ print(" %s %s", edp->bustype, edp->ifctype);
+ print("\n");
+ }
+ if (edp->sectsz <= 0) {
+ print("extgetsize: drive 0x%ux: non-positive sector size\n",
+ bdp->id);
+ edp->sectsz = 1; /* don't divide by zero */
+ }
+ bdp->sectsz = edp->sectsz;
+ return edp->physsects * edp->sectsz;
+}
+
+long
+biosread(Fs *fs, void *a, long n)
+{
+ int want, got, part;
+ long totnr, stuck;
+ Devbytes offset;
+ Biosdev *bdp;
+
+ if(fs->dev > bdrive.ndevs)
+ return -1;
+ if (n <= 0)
+ return n;
+ bdp = &bdev[fs->dev];
+ offset = bdp->offset;
+ stuck = 0;
+ for (totnr = 0; totnr < n && stuck < 4; totnr += got) {
+ want = bdp->sectsz;
+ if (totnr + want > n)
+ want = n - totnr;
+ if(Debug)
+ print("bios%d, read: %ld @ off %lld, want: %d, id: 0x%ux\n",
+ fs->dev, n, offset, want, bdp->id);
+ part = offset % bdp->sectsz;
+ if (part != 0) { /* back up to start of sector */
+ offset -= part;
+ totnr -= part;
+ if (totnr < 0) {
+ print("biosread: negative count %ld\n", totnr);
+ return -1;
+ }
+ }
+ if ((vlong)offset < 0) {
+ print("biosread: negative offset %lld\n", offset);
+ return -1;
+ }
+ got = sectread(bdp, (char *)a + totnr, want, offset/bdp->sectsz);
+ if(got <= 0){
+// print("biosread: failed to read %ld @ off %lld of 0x%ux, "
+// "want %d got %d\n",
+// n, offset, bdp->id, want, got);
+ return -1;
+ }
+ offset += got;
+ bdp->offset = offset;
+ if (got < bdp->sectsz)
+ stuck++; /* we'll have to re-read this sector */
+ else
+ stuck = 0;
+ }
+ return totnr;
+}
+
+vlong
+biosseek(Fs *fs, vlong off)
+{
+ if (off < 0) {
+ print("biosseek(fs, %lld) is illegal\n", off);
+ return -1;
+ }
+ if(fs->dev > bdrive.ndevs) {
+ print("biosseek: fs->dev %d > bdrive.ndevs %d\n",
+ fs->dev, bdrive.ndevs);
+ return -1;
+ }
+ bdev[fs->dev].offset = off; /* do not know size... (yet) */
+ return off;
+}
+
+void *
+biosgetfspart(int i, char *name, int chatty)
+{
+ static Fs fs;
+
+ if(strcmp(name, "9fat") != 0){
+ if(chatty)
+ print("unknown partition bios%d!%s (use bios%d!9fat)\n",
+ i, name, i);
+ return nil;
+ }
+
+ fs.dev = i;
+ fs.diskread = biosread;
+ fs.diskseek = biosseek;
+
+ if(dosinit(&fs) < 0){
+ if(chatty)
+ print("bios%d!%s does not contain a FAT file system\n",
+ i, name);
+ return nil;
+ }
+ return &fs;
+}
--- /dev/null
+++ b/os/boot.original/pc/devbios.h
@@ -1,0 +1,22 @@
+typedef uvlong Devbytes, Devsects;
+
+typedef struct Biosdrive Biosdrive; /* 1 drive -> ndevs */
+typedef struct Biosdev Biosdev;
+
+struct Biosdrive {
+ int ndevs;
+};
+struct Biosdev {
+ Devbytes size;
+ Devbytes offset;
+ uchar id;
+ char type;
+};
+
+int biosboot(int dev, char *file, Boot *b);
+void* biosgetfspart(int i, char *name, int chatty);
+void biosinitdev(int i, char *name);
+int biosinit(void);
+void biosprintbootdevs(int dev);
+void biosprintdevs(int i);
+long biosread(Fs *fs, void *a, long n);
--- /dev/null
+++ b/os/boot.original/pc/devfloppy.c
@@ -1,0 +1,853 @@
+#include <u.h>
+
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+#include "fs.h"
+#include "devfloppy.h"
+
+
+/* Intel 82077A (8272A compatible) floppy controller */
+
+/* This module expects the following functions to be defined
+ * elsewhere:
+ *
+ * inb()
+ * outb()
+ * floppyexec()
+ * floppyeject()
+ * floppysetup0()
+ * floppysetup1()
+ * dmainit()
+ * dmasetup()
+ * dmaend()
+ *
+ * On DMA systems, floppyexec() should be an empty function;
+ * on non-DMA systems, dmaend() should be an empty function;
+ * dmasetup() may enforce maximum transfer sizes.
+ */
+
+enum {
+ /* file types */
+ Qdir= 0,
+ Qdata= (1<<2),
+ Qctl= (2<<2),
+ Qmask= (3<<2),
+
+ DMAchan= 2, /* floppy dma channel */
+};
+
+#define DPRINT if(0)print
+
+FType floppytype[] =
+{
+ { "3½HD", T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54, 0, },
+ { "3½DD", T1440kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
+ { "3½DD", T720kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },
+ { "5¼HD", T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, },
+ { "5¼DD", T1200kb, 512, 9, 2, 2, 40, 0x2A, 0x50, 1, },
+ { "ATT3B1", T1200kb, 512, 8, 2, 2, 48, 0x2A, 0x50, 1, },
+ { "5¼DD", T360kb, 512, 9, 2, 1, 40, 0x2A, 0x50, 2, },
+};
+
+/*
+ * bytes per sector encoding for the controller.
+ * - index for b2c is is (bytes per sector/128).
+ * - index for c2b is code from b2c
+ */
+static int b2c[] =
+{
+[1] 0,
+[2] 1,
+[4] 2,
+[8] 3,
+};
+static int c2b[] =
+{
+ 128,
+ 256,
+ 512,
+ 1024,
+};
+
+FController fl;
+
+#define MOTORBIT(i) (1<<((i)+4))
+
+/*
+ * predeclared
+ */
+static int cmddone(void*);
+static void floppyformat(FDrive*, char*);
+static void floppykproc(void*);
+static void floppypos(FDrive*,long);
+static int floppyrecal(FDrive*);
+static int floppyresult(void);
+static void floppyrevive(void);
+static vlong pcfloppyseek(FDrive*, vlong);
+static int floppysense(void);
+static void floppywait(int);
+static long floppyxfer(FDrive*, int, void*, long, long);
+
+static void
+fldump(void)
+{
+ DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb),
+ inb(Pdor), inb(Pmsr), inb(Pdir));
+}
+
+static void
+floppyalarm(Alarm* a)
+{
+ FDrive *dp;
+
+ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
+ if((fl.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5)
+ floppyoff(dp);
+ }
+
+ alarm(5*1000, floppyalarm, 0);
+ cancel(a);
+}
+
+/*
+ * set floppy drive to its default type
+ */
+static void
+floppysetdef(FDrive *dp)
+{
+ FType *t;
+
+ for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++)
+ if(dp->dt == t->dt){
+ dp->t = t;
+ break;
+ }
+}
+
+static void
+_floppydetach(void)
+{
+ /*
+ * stop the motors
+ */
+ fl.motor = 0;
+ delay(10);
+ outb(Pdor, fl.motor | Fintena | Fena);
+ delay(10);
+}
+
+int
+floppyinit(void)
+{
+ FDrive *dp;
+ FType *t;
+ ulong maxtsize;
+ int mask;
+
+ dmainit(DMAchan);
+
+ floppysetup0(&fl);
+
+ /*
+ * init dependent parameters
+ */
+ maxtsize = 0;
+ for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
+ t->cap = t->bytes * t->heads * t->sectors * t->tracks;
+ t->bcode = b2c[t->bytes/128];
+ t->tsize = t->bytes * t->sectors;
+ if(maxtsize < t->tsize)
+ maxtsize = t->tsize;
+ }
+
+ fl.selected = fl.d;
+
+ floppydetach = _floppydetach;
+ floppydetach();
+
+ /*
+ * init drives
+ */
+ mask = 0;
+ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
+ dp->dev = dp - fl.d;
+ if(dp->dt == Tnone)
+ continue;
+ mask |= 1<<dp->dev;
+ floppysetdef(dp);
+ dp->cyl = -1; /* because we don't know */
+ dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024);
+ dp->ccyl = -1;
+ dp->vers = 0;
+ dp->maxtries = 5;
+ }
+
+ /*
+ * first operation will recalibrate
+ */
+ fl.confused = 1;
+
+ floppysetup1(&fl);
+
+ /* to turn the motor off when inactive */
+ alarm(5*1000, floppyalarm, 0);
+
+ return mask;
+}
+
+void
+floppyinitdev(int i, char *name)
+{
+ if(i >= fl.ndrive)
+ panic("floppyinitdev");
+ sprint(name, "fd%d", i);
+}
+
+void
+floppyprintdevs(int i)
+{
+ if(i >= fl.ndrive)
+ panic("floppyprintdevs");
+ print(" fd%d", i);
+}
+
+int
+floppyboot(int dev, char *file, Boot *b)
+{
+ Fs *fs;
+
+ if(strncmp(file, "dos!", 4) == 0)
+ file += 4;
+ else if(strchr(file, '!') || strcmp(file, "")==0) {
+ print("syntax is fd0!file\n");
+ return -1;
+ }
+
+ fs = floppygetfspart(dev, "dos", 1);
+ if(fs == nil)
+ return -1;
+
+ return fsboot(fs, file, b);
+}
+
+void
+floppyprintbootdevs(int dev)
+{
+ print(" fd%d", dev);
+}
+
+/*
+ * check if the floppy has been replaced under foot. cause
+ * an error if it has.
+ *
+ * a seek and a read clears the condition. this was determined
+ * experimentally, there has to be a better way.
+ *
+ * if the read fails, cycle through the possible floppy
+ * density till one works or we've cycled through all
+ * possibilities for this drive.
+ */
+static int
+changed(FDrive *dp)
+{
+ FType *start;
+
+ /*
+ * if floppy has changed or first time through
+ */
+ if((inb(Pdir)&Fchange) || dp->vers == 0){
+ DPRINT("changed\n");
+ fldump();
+ dp->vers++;
+ floppysetdef(dp);
+ dp->maxtries = 3;
+ start = dp->t;
+
+ /* flopppyon fails if there's no drive */
+ dp->confused = 1; /* make floppyon recal */
+ if(floppyon(dp) < 0)
+ return -1;
+
+ pcfloppyseek(dp, dp->t->heads*dp->t->tsize);
+
+ while(floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize) <= 0){
+
+ /*
+ * if the xfer attempt doesn't clear the changed bit,
+ * there's no floppy in the drive
+ */
+ if(inb(Pdir)&Fchange)
+ return -1;
+
+ while(++dp->t){
+ if(dp->t == &floppytype[nelem(floppytype)])
+ dp->t = floppytype;
+ if(dp->dt == dp->t->dt)
+ break;
+ }
+
+ /* flopppyon fails if there's no drive */
+ if(floppyon(dp) < 0)
+ return -1;
+
+ DPRINT("changed: trying %s\n", dp->t->name);
+ fldump();
+ if(dp->t == start)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+readtrack(FDrive *dp, int cyl, int head)
+{
+ int i, nn, sofar;
+ ulong pos;
+
+ nn = dp->t->tsize;
+ if(dp->ccyl==cyl && dp->chead==head)
+ return nn;
+ pos = (cyl*dp->t->heads+head) * nn;
+ for(sofar = 0; sofar < nn; sofar += i){
+ dp->ccyl = -1;
+ i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar);
+ if(i <= 0)
+ return -1;
+ }
+ dp->ccyl = cyl;
+ dp->chead = head;
+ return nn;
+}
+
+long
+floppyread(Fs *fs, void *a, long n)
+{
+ FDrive *dp;
+ long rv, offset;
+ int sec, head, cyl;
+ long len;
+ uchar *aa;
+
+ aa = a;
+ dp = &fl.d[fs->dev];
+
+ offset = dp->offset;
+ floppyon(dp);
+ if(changed(dp))
+ return -1;
+
+ for(rv = 0; rv < n; rv += len){
+ /*
+ * all xfers come out of the track cache
+ */
+ dp->len = n - rv;
+ floppypos(dp, offset+rv);
+ cyl = dp->tcyl;
+ head = dp->thead;
+ len = dp->len;
+ sec = dp->tsec;
+ if(readtrack(dp, cyl, head) < 0)
+ break;
+ memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);
+ }
+ dp->offset = offset+rv;
+
+ return rv;
+}
+
+void*
+floppygetfspart(int i, char *name, int chatty)
+{
+ static Fs fs;
+
+ if(strcmp(name, "dos") != 0){
+ if(chatty)
+ print("unknown partition fd%d!%s (use fd%d!dos)\n", i, name, i);
+ return nil;
+ }
+
+ fs.dev = i;
+ fs.diskread = floppyread;
+ fs.diskseek = floppyseek;
+
+ /* sometimes we get spurious errors and doing it again works */
+ if(dosinit(&fs) < 0 && dosinit(&fs) < 0){
+ if(chatty)
+ print("fd%d!%s does not contain a FAT file system\n", i, name);
+ return nil;
+ }
+ return &fs;
+}
+
+static int
+return0(void*)
+{
+ return 0;
+}
+
+static void
+timedsleep(int (*f)(void*), void* arg, int ms)
+{
+ int s;
+ ulong end;
+
+ end = m->ticks + 1 + MS2TK(ms);
+ while(m->ticks < end && !(*f)(arg)){
+ s = spllo();
+ delay(10);
+ splx(s);
+ }
+}
+
+/*
+ * start a floppy drive's motor.
+ */
+static int
+floppyon(FDrive *dp)
+{
+ int alreadyon;
+ int tries;
+
+ if(fl.confused)
+ floppyrevive();
+
+ /* start motor and select drive */
+ dp->lasttouched = m->ticks;
+ alreadyon = fl.motor & MOTORBIT(dp->dev);
+ if(!alreadyon){
+ fl.motor |= MOTORBIT(dp->dev);
+ outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
+ /* wait for drive to spin up */
+ timedsleep(return0, 0, 750);
+
+ /* clear any pending interrupts */
+ floppysense();
+ }
+
+ /* set transfer rate */
+ if(fl.rate != dp->t->rate){
+ fl.rate = dp->t->rate;
+ outb(Pdsr, fl.rate);
+ }
+
+ /* get drive to a known cylinder */
+ if(dp->confused)
+ for(tries = 0; tries < 4; tries++)
+ if(floppyrecal(dp) >= 0)
+ break;
+ dp->lasttouched = m->ticks;
+ fl.selected = dp;
+ if(dp->confused)
+ return -1;
+ return 0;
+}
+
+/*
+ * stop the floppy if it hasn't been used in 5 seconds
+ */
+static void
+floppyoff(FDrive *dp)
+{
+ fl.motor &= ~MOTORBIT(dp->dev);
+ outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
+}
+
+/*
+ * send a command to the floppy
+ */
+static int
+floppycmd(void)
+{
+ int i;
+ int tries;
+
+ fl.nstat = 0;
+ for(i = 0; i < fl.ncmd; i++){
+ for(tries = 0; ; tries++){
+ if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
+ break;
+ if(tries > 1000){
+ DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
+ fldump();
+
+ /* empty fifo, might have been a bad command */
+ floppyresult();
+ return -1;
+ }
+ microdelay(1);
+ }
+ outb(Pfdata, fl.cmd[i]);
+ }
+ return 0;
+}
+
+/*
+ * get a command result from the floppy
+ *
+ * when the controller goes ready waiting for a command
+ * (instead of sending results), we're done
+ *
+ */
+static int
+floppyresult(void)
+{
+ int i, s;
+ int tries;
+
+ /* get the result of the operation */
+ for(i = 0; i < sizeof(fl.stat); i++){
+ /* wait for status byte */
+ for(tries = 0; ; tries++){
+ s = inb(Pmsr)&(Ffrom|Fready);
+ if(s == Fready){
+ fl.nstat = i;
+ return fl.nstat;
+ }
+ if(s == (Ffrom|Fready))
+ break;
+ if(tries > 1000){
+ DPRINT("floppyresult: %d stats\n", i);
+ fldump();
+ fl.confused = 1;
+ return -1;
+ }
+ microdelay(1);
+ }
+ fl.stat[i] = inb(Pfdata);
+ }
+ fl.nstat = sizeof(fl.stat);
+ return fl.nstat;
+}
+
+/*
+ * calculate physical address of a logical byte offset into the disk
+ *
+ * truncate dp->length if it crosses a track boundary
+ */
+static void
+floppypos(FDrive *dp, long off)
+{
+ int lsec;
+ int ltrack;
+ int end;
+
+ lsec = off/dp->t->bytes;
+ ltrack = lsec/dp->t->sectors;
+ dp->tcyl = ltrack/dp->t->heads;
+ dp->tsec = (lsec % dp->t->sectors) + 1;
+ dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
+
+ /*
+ * can't read across track boundaries.
+ * if so, decrement the bytes to be read.
+ */
+ end = (ltrack+1)*dp->t->sectors*dp->t->bytes;
+ if(off+dp->len > end)
+ dp->len = end - off;
+}
+
+/*
+ * get the interrupt cause from the floppy.
+ */
+static int
+floppysense(void)
+{
+ fl.ncmd = 0;
+ fl.cmd[fl.ncmd++] = Fsense;
+ if(floppycmd() < 0)
+ return -1;
+ if(floppyresult() < 2){
+ DPRINT("can't read sense response\n");
+ fldump();
+ fl.confused = 1;
+ return -1;
+ }
+ return 0;
+}
+
+static int
+cmddone(void *a)
+{
+ USED(a);
+ return fl.ncmd == 0;
+}
+
+/*
+ * Wait for a floppy interrupt. If none occurs in 5 seconds, we
+ * may have missed one. This only happens on some portables which
+ * do power management behind our backs. Call the interrupt
+ * routine to try to clear any conditions.
+ */
+static void
+floppywait(int slow)
+{
+ timedsleep(cmddone, 0, slow ? 5000 : 1000);
+ if(!cmddone(0)){
+ floppyintr(0);
+ fl.confused = 1;
+ }
+}
+
+/*
+ * we've lost the floppy position, go to cylinder 0.
+ */
+static int
+floppyrecal(FDrive *dp)
+{
+ dp->ccyl = -1;
+ dp->cyl = -1;
+
+ fl.ncmd = 0;
+ fl.cmd[fl.ncmd++] = Frecal;
+ fl.cmd[fl.ncmd++] = dp->dev;
+ if(floppycmd() < 0)
+ return -1;
+ floppywait(1);
+ if(fl.nstat < 2){
+ DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
+ fl.confused = 1;
+ return -1;
+ }
+ if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
+ DPRINT("recalibrate: failed\n");
+ dp->confused = 1;
+ return -1;
+ }
+ dp->cyl = fl.stat[1];
+ if(dp->cyl != 0){
+ DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl);
+ dp->cyl = -1;
+ dp->confused = 1;
+ return -1;
+ }
+
+ dp->confused = 0;
+ return 0;
+}
+
+/*
+ * if the controller or a specific drive is in a confused state,
+ * reset it and get back to a kown state
+ */
+static void
+floppyrevive(void)
+{
+ FDrive *dp;
+
+ /*
+ * reset the controller if it's confused
+ */
+ if(fl.confused){
+ DPRINT("floppyrevive in\n");
+ fldump();
+
+ /* reset controller and turn all motors off */
+ splhi();
+ fl.ncmd = 1;
+ fl.cmd[0] = 0;
+ outb(Pdor, 0);
+ delay(10);
+ outb(Pdor, Fintena|Fena);
+ delay(10);
+ spllo();
+ fl.motor = 0;
+ fl.confused = 0;
+ floppywait(0);
+
+ /* mark all drives in an unknown state */
+ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)
+ dp->confused = 1;
+
+ /* set rate to a known value */
+ outb(Pdsr, 0);
+ fl.rate = 0;
+
+ DPRINT("floppyrevive out\n");
+ fldump();
+ }
+}
+
+/*
+ * seek to the target cylinder
+ *
+ * interrupt, no results
+ */
+static vlong
+pcfloppyseek(FDrive *dp, vlong off)
+{
+ floppypos(dp, off);
+ if(dp->cyl == dp->tcyl){
+ dp->offset = off;
+ return off;
+ }
+ dp->cyl = -1;
+
+ fl.ncmd = 0;
+ fl.cmd[fl.ncmd++] = Fseek;
+ fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
+ fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
+ if(floppycmd() < 0)
+ return -1;
+ floppywait(1);
+ if(fl.nstat < 2){
+ DPRINT("seek: confused\n");
+ fl.confused = 1;
+ return -1;
+ }
+ if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
+ DPRINT("seek: failed\n");
+ dp->confused = 1;
+ return -1;
+ }
+
+ dp->cyl = dp->tcyl;
+ dp->offset = off;
+ DPRINT("seek to %d succeeded\n", dp->offset);
+
+ return dp->offset;
+}
+
+/*
+ * read or write to floppy. try up to three times.
+ */
+static long
+floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
+{
+ long offset;
+ int tries;
+
+ if(off >= dp->t->cap)
+ return 0;
+ if(off + n > dp->t->cap)
+ n = dp->t->cap - off;
+
+ /* retry on error (until it gets ridiculous) */
+ for(tries = 0; tries < dp->maxtries; tries++){
+
+ dp->len = n;
+ if(pcfloppyseek(dp, off) < 0){
+ DPRINT("xfer: seek failed\n");
+ dp->confused = 1;
+ continue;
+ }
+
+ /*
+ * set up the dma (dp->len may be trimmed)
+ */
+ dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
+ if(dp->len < 0){
+ buggery:
+ dmaend(DMAchan);
+ continue;
+ }
+
+ /*
+ * start operation
+ */
+ fl.ncmd = 0;
+ fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);
+ fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
+ fl.cmd[fl.ncmd++] = dp->tcyl;
+ fl.cmd[fl.ncmd++] = dp->thead;
+ fl.cmd[fl.ncmd++] = dp->tsec;
+ fl.cmd[fl.ncmd++] = dp->t->bcode;
+ fl.cmd[fl.ncmd++] = dp->t->sectors;
+ fl.cmd[fl.ncmd++] = dp->t->gpl;
+ fl.cmd[fl.ncmd++] = 0xFF;
+ if(floppycmd() < 0)
+ goto buggery;
+
+ /*
+ * give bus to DMA, floppyintr() will read result
+ */
+ floppywait(0);
+ dmaend(DMAchan);
+
+ /*
+ * check for errors
+ */
+ if(fl.nstat < 7){
+ DPRINT("xfer: confused\n");
+ fl.confused = 1;
+ continue;
+ }
+ if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
+ DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],
+ fl.stat[1], fl.stat[2]);
+ DPRINT("offset %lud len %ld\n", off, dp->len);
+ if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){
+ DPRINT("DMA overrun: retry\n");
+ } else
+ dp->confused = 1;
+ continue;
+ }
+
+ /*
+ * check for correct cylinder
+ */
+ offset = fl.stat[3] * dp->t->heads + fl.stat[4];
+ offset = offset*dp->t->sectors + fl.stat[5] - 1;
+ offset = offset * c2b[fl.stat[6]];
+ if(offset != off+dp->len){
+ DPRINT("xfer: ends on wrong cyl\n");
+ dp->confused = 1;
+ continue;
+ }
+
+ dp->lasttouched = m->ticks;
+ dp->maxtries = 20;
+ return dp->len;
+ }
+
+ return -1;
+}
+
+/*
+void
+floppymemwrite(void)
+{
+ int i;
+ int n;
+ uchar *a;
+ FDrive *dp;
+
+ dp = &fl.d[0];
+ a = (uchar*)0x80000000;
+ n = 0;
+ while(n < 1440*1024){
+ i = floppyxfer(dp, Fwrite, a+n, n, 1440*1024-n);
+ if(i <= 0)
+ break;
+ n += i;
+ }
+ print("floppymemwrite wrote %d bytes\n", n);
+splhi(); for(;;);
+}
+*/
+
+static void
+floppyintr(Ureg *ur)
+{
+ USED(ur);
+ switch(fl.cmd[0]&~Fmulti){
+ case Fread:
+ case Fwrite:
+ case Fformat:
+ case Fdumpreg:
+ floppyresult();
+ break;
+ case Fseek:
+ case Frecal:
+ default:
+ floppysense(); /* to clear interrupt */
+ break;
+ }
+ fl.ncmd = 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/devfloppy.h
@@ -1,0 +1,196 @@
+typedef struct FController FController;
+typedef struct FDrive FDrive;
+typedef struct FType FType;
+
+static void floppyintr(Ureg*);
+static int floppyon(FDrive*);
+static void floppyoff(FDrive*);
+static void floppysetdef(FDrive*);
+
+/*
+ * a floppy drive
+ */
+struct FDrive
+{
+ FType *t; /* floppy type */
+ int dt; /* drive type */
+ int dev;
+
+ ulong lasttouched; /* time last touched */
+ int cyl; /* current arm position */
+ int confused; /* needs to be recalibrated */
+ int offset; /* current offset */
+ int vers;
+ int maxtries;
+
+ int tcyl; /* target cylinder */
+ int thead; /* target head */
+ int tsec; /* target sector */
+ long len; /* size of xfer */
+
+ uchar *cache; /* track cache */
+ int ccyl;
+ int chead;
+
+// Rendez r; /* waiting here for motor to spin up */
+ void *aux;
+};
+
+/*
+ * controller for 4 floppys
+ */
+struct FController
+{
+// QLock; /* exclusive access to the contoller */
+
+ int ndrive;
+ FDrive *d; /* the floppy drives */
+ FDrive *selected;
+ int rate; /* current rate selected */
+ uchar cmd[14]; /* command */
+ int ncmd; /* # command bytes */
+ uchar stat[14]; /* command status */
+ int nstat; /* # status bytes */
+ int confused; /* controler needs to be reset */
+// Rendez r; /* wait here for command termination */
+ int motor; /* bit mask of spinning disks */
+// Rendez kr; /* for motor watcher */
+};
+
+/*
+ * floppy types (all MFM encoding)
+ */
+struct FType
+{
+ char *name;
+ int dt; /* compatible drive type */
+ int bytes; /* bytes/sector */
+ int sectors; /* sectors/track */
+ int heads; /* number of heads */
+ int steps; /* steps per cylinder */
+ int tracks; /* tracks/disk */
+ int gpl; /* intersector gap length for read/write */
+ int fgpl; /* intersector gap length for format */
+ int rate; /* rate code */
+
+ /*
+ * these depend on previous entries and are set filled in
+ * by floppyinit
+ */
+ int bcode; /* coded version of bytes for the controller */
+ long cap; /* drive capacity in bytes */
+ long tsize; /* track size in bytes */
+};
+/* bits in the registers */
+enum
+{
+ /* status registers a & b */
+ Psra= 0x3f0,
+ Psrb= 0x3f1,
+
+ /* digital output register */
+ Pdor= 0x3f2,
+ Fintena= 0x8, /* enable floppy interrupt */
+ Fena= 0x4, /* 0 == reset controller */
+
+ /* main status register */
+ Pmsr= 0x3f4,
+ Fready= 0x80, /* ready to be touched */
+ Ffrom= 0x40, /* data from controller */
+ Ffloppybusy= 0x10, /* operation not over */
+
+ /* data register */
+ Pfdata= 0x3f5,
+ Frecal= 0x07, /* recalibrate cmd */
+ Fseek= 0x0f, /* seek cmd */
+ Fsense= 0x08, /* sense cmd */
+ Fread= 0x66, /* read cmd */
+ Freadid= 0x4a, /* read track id */
+ Fspec= 0x03, /* set hold times */
+ Fwrite= 0x45, /* write cmd */
+ Fformat= 0x4d, /* format cmd */
+ Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */
+ Fdumpreg= 0x0e, /* dump internal registers */
+
+ /* digital input register */
+ Pdir= 0x3F7, /* disk changed port (read only) */
+ Pdsr= 0x3F7, /* data rate select port (write only) */
+ Fchange= 0x80, /* disk has changed */
+
+ /* status 0 byte */
+ Drivemask= 3<<0,
+ Seekend= 1<<5,
+ Codemask= (3<<6)|(3<<3),
+ Cmdexec= 1<<6,
+
+ /* status 1 byte */
+ Overrun= 0x10,
+};
+
+/*
+ * types of drive (from PC equipment byte)
+ */
+enum
+{
+ Tnone= 0,
+ T360kb= 1,
+ T1200kb= 2,
+ T720kb= 3,
+ T1440kb= 4,
+};
+
+static void
+pcfloppyintr(Ureg *ur, void *a)
+{
+ USED(a);
+
+ floppyintr(ur);
+}
+
+void
+floppysetup0(FController *fl)
+{
+ uchar equip;
+
+ /*
+ * Read nvram for types of floppies 0 & 1.
+ * Always try floppy 0.
+ */
+ equip = nvramread(0x10);
+ fl->ndrive = 1;
+
+ if(equip & 0xf)
+ fl->ndrive++;
+
+ /*
+ * Allocate the drive storage.
+ * There's always one.
+ */
+ fl->d = xalloc(fl->ndrive*sizeof(FDrive));
+ fl->d[0].dt = (equip >> 4) & 0xf;
+ if(fl->d[0].dt == Tnone)
+ fl->d[0].dt = T1440kb;
+
+ if(fl->ndrive == 2)
+ fl->d[1].dt = equip & 0xf;
+}
+
+void
+floppysetup1(FController*)
+{
+// intrenable(VectorFLOPPY, pcfloppyintr, fl, BUSUNKNOWN);
+ setvec(VectorFLOPPY, pcfloppyintr, 0);
+}
+
+
+static vlong pcfloppyseek(FDrive*, vlong);
+FController fl;
+
+vlong
+floppyseek(Fs *fs, vlong off)
+{
+ FDrive *dp;
+
+ dp = &fl.d[fs->dev];
+ return pcfloppyseek(dp, off);
+}
--- /dev/null
+++ b/os/boot.original/pc/devi82365.c
@@ -1,0 +1,742 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "io.h"
+
+/*
+ * Intel 82365SL PCIC controller and compatibles.
+ */
+enum
+{
+ /*
+ * registers indices
+ */
+ Rid= 0x0, /* identification and revision */
+ Ris= 0x1, /* interface status */
+ Rpc= 0x2, /* power control */
+ Foutena= (1<<7), /* output enable */
+ Fautopower= (1<<5), /* automatic power switching */
+ Fcardena= (1<<4), /* PC card enable */
+ Rigc= 0x3, /* interrupt and general control */
+ Fiocard= (1<<5), /* I/O card (vs memory) */
+ Fnotreset= (1<<6), /* reset if not set */
+ FSMIena= (1<<4), /* enable change interrupt on SMI */
+ Rcsc= 0x4, /* card status change */
+ Rcscic= 0x5, /* card status change interrupt config */
+ Fchangeena= (1<<3), /* card changed */
+ Fbwarnena= (1<<1), /* card battery warning */
+ Fbdeadena= (1<<0), /* card battery dead */
+ Rwe= 0x6, /* address window enable */
+ Fmem16= (1<<5), /* use A23-A12 to decode address */
+ Rio= 0x7, /* I/O control */
+ Fwidth16= (1<<0), /* 16 bit data width */
+ Fiocs16= (1<<1), /* IOCS16 determines data width */
+ Fzerows= (1<<2), /* zero wait state */
+ Ftiming= (1<<3), /* timing register to use */
+ Riobtm0lo= 0x8, /* I/O address 0 start low byte */
+ Riobtm0hi= 0x9, /* I/O address 0 start high byte */
+ Riotop0lo= 0xa, /* I/O address 0 stop low byte */
+ Riotop0hi= 0xb, /* I/O address 0 stop high byte */
+ Riobtm1lo= 0xc, /* I/O address 1 start low byte */
+ Riobtm1hi= 0xd, /* I/O address 1 start high byte */
+ Riotop1lo= 0xe, /* I/O address 1 stop low byte */
+ Riotop1hi= 0xf, /* I/O address 1 stop high byte */
+ Rmap= 0x10, /* map 0 */
+
+ /*
+ * CL-PD67xx extension registers
+ */
+ Rmisc1= 0x16, /* misc control 1 */
+ F5Vdetect= (1<<0),
+ Fvcc3V= (1<<1),
+ Fpmint= (1<<2),
+ Fpsirq= (1<<3),
+ Fspeaker= (1<<4),
+ Finpack= (1<<7),
+ Rfifo= 0x17, /* fifo control */
+ Fflush= (1<<7), /* flush fifo */
+ Rmisc2= 0x1E, /* misc control 2 */
+ Flowpow= (1<<1), /* low power mode */
+ Rchipinfo= 0x1F, /* chip information */
+ Ratactl= 0x26, /* ATA control */
+
+ /*
+ * offsets into the system memory address maps
+ */
+ Mbtmlo= 0x0, /* System mem addr mapping start low byte */
+ Mbtmhi= 0x1, /* System mem addr mapping start high byte */
+ F16bit= (1<<7), /* 16-bit wide data path */
+ Mtoplo= 0x2, /* System mem addr mapping stop low byte */
+ Mtophi= 0x3, /* System mem addr mapping stop high byte */
+ Ftimer1= (1<<6), /* timer set 1 */
+ Mofflo= 0x4, /* Card memory offset address low byte */
+ Moffhi= 0x5, /* Card memory offset address high byte */
+ Fregactive= (1<<6), /* attribute memory */
+
+ /*
+ * configuration registers - they start at an offset in attribute
+ * memory found in the CIS.
+ */
+ Rconfig= 0,
+ Creset= (1<<7), /* reset device */
+ Clevel= (1<<6), /* level sensitive interrupt line */
+ Cirq= (1<<2), /* IRQ enable */
+ Cdecode= (1<<1), /* address decode */
+ Cfunc= (1<<0), /* function enable */
+ Riobase0= 5,
+ Riobase1= 6,
+ Riosize= 9,
+};
+
+static int pcmcia_pcmspecial(char *, ISAConf *);
+static void pcmcia_pcmspecialclose(int);
+
+#define MAP(x,o) (Rmap + (x)*0x8 + o)
+
+typedef struct I82365 I82365;
+
+/* a controller */
+enum
+{
+ Ti82365,
+ Tpd6710,
+ Tpd6720,
+ Tvg46x,
+};
+struct I82365
+{
+ int type;
+ int dev;
+ int nslot;
+ int xreg; /* index register address */
+ int dreg; /* data register address */
+ int irq;
+};
+static I82365 *controller[4];
+static int ncontroller;
+static PCMslot *slot;
+static PCMslot *lastslot;
+static nslot;
+
+static void i82365intr(Ureg*, void*);
+static void i82365reset(void);
+static int pcmio(int, ISAConf*);
+
+static void i82365dump(PCMslot*);
+
+void
+devi82365link(void)
+{
+ static int already;
+ char *p;
+
+ if(already)
+ return;
+ already = 1;
+
+ if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0)
+ return;
+
+ if (_pcmspecial)
+ return;
+
+ _pcmspecial = pcmcia_pcmspecial;
+ _pcmspecialclose = pcmcia_pcmspecialclose;
+}
+
+/*
+ * reading and writing card registers
+ */
+static uchar
+rdreg(PCMslot *pp, int index)
+{
+ outb(((I82365*)pp->cp)->xreg, pp->base + index);
+ return inb(((I82365*)pp->cp)->dreg);
+}
+static void
+wrreg(PCMslot *pp, int index, uchar val)
+{
+ outb(((I82365*)pp->cp)->xreg, pp->base + index);
+ outb(((I82365*)pp->cp)->dreg, val);
+}
+
+/*
+ * get info about card
+ */
+static void
+slotinfo(PCMslot *pp)
+{
+ uchar isr;
+
+ isr = rdreg(pp, Ris);
+ pp->occupied = (isr & (3<<2)) == (3<<2);
+ pp->powered = isr & (1<<6);
+ pp->battery = (isr & 3) == 3;
+ pp->wrprot = isr & (1<<4);
+ pp->busy = isr & (1<<5);
+ //pp->msec = TK2MS(MACHP(0)->ticks);
+}
+
+static int
+vcode(int volt)
+{
+ switch(volt){
+ case 5:
+ return 1;
+ case 12:
+ return 2;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * enable the slot card
+ */
+static void
+slotena(PCMslot *pp)
+{
+ if(pp->enabled)
+ return;
+
+ /* power up and unreset, wait's are empirical (???) */
+ wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
+ delay(300);
+ wrreg(pp, Rigc, 0);
+ delay(100);
+ wrreg(pp, Rigc, Fnotreset);
+ delay(500);
+
+ /* get configuration */
+ slotinfo(pp);
+ if(pp->occupied){
+ pcmcisread(pp);
+ pp->enabled = 1;
+ } else
+ wrreg(pp, Rpc, Fautopower);
+}
+
+/*
+ * disable the slot card
+ */
+static void
+slotdis(PCMslot *pp)
+{
+ wrreg(pp, Rpc, 0); /* turn off card power */
+ wrreg(pp, Rwe, 0); /* no windows */
+ pp->enabled = 0;
+}
+
+/*
+ * status change interrupt
+ */
+static void
+i82365intr(Ureg *, void *)
+{
+ uchar csc, was;
+ PCMslot *pp;
+
+ if(slot == 0)
+ return;
+
+ for(pp = slot; pp < lastslot; pp++){
+ csc = rdreg(pp, Rcsc);
+ was = pp->occupied;
+ slotinfo(pp);
+ if(csc & (1<<3) && was != pp->occupied){
+ if(!pp->occupied)
+ slotdis(pp);
+ }
+ }
+}
+
+enum
+{
+ Mshift= 12,
+ Mgran= (1<<Mshift), /* granularity of maps */
+ Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
+};
+
+/*
+ * get a map for pc card region, return corrected len
+ */
+PCMmap*
+pcmmap(int slotno, ulong offset, int len, int attr)
+{
+ PCMslot *pp;
+ uchar we, bit;
+ PCMmap *m, *nm;
+ int i;
+ ulong e;
+
+ pp = slot + slotno;
+ lock(&pp->mlock);
+
+ /* convert offset to granularity */
+ if(len <= 0)
+ len = 1;
+ e = ROUND(offset+len, Mgran);
+ offset &= Mmask;
+ len = e - offset;
+
+ /* look for a map that covers the right area */
+ we = rdreg(pp, Rwe);
+ bit = 1;
+ nm = 0;
+ for(m = pp->mmap; m < &pp->mmap[nelem(pp->mmap)]; m++){
+ if((we & bit))
+ if(m->attr == attr)
+ if(offset >= m->ca && e <= m->cea){
+
+ m->ref++;
+ unlock(&pp->mlock);
+ return m;
+ }
+ bit <<= 1;
+ if(nm == 0 && m->ref == 0)
+ nm = m;
+ }
+ m = nm;
+ if(m == 0){
+ unlock(&pp->mlock);
+ return 0;
+ }
+
+ /* if isa space isn't big enough, free it and get more */
+ if(m->len < len){
+ if(m->isa){
+ umbfree(m->isa, m->len);
+ m->len = 0;
+ }
+ m->isa = PADDR(umbmalloc(0, len, Mgran));
+ if(m->isa == 0){
+ print("pcmmap %d: out of isa space\n", len);
+ unlock(&pp->mlock);
+ return 0;
+ }
+ m->len = len;
+ }
+
+ /* set up new map */
+ m->ca = offset;
+ m->cea = m->ca + m->len;
+ m->attr = attr;
+ i = m-pp->mmap;
+ bit = 1<<i;
+ wrreg(pp, Rwe, we & ~bit); /* disable map before changing it */
+ wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift);
+ wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
+ wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
+ wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
+ offset -= m->isa;
+ offset &= (1<<25)-1;
+ offset >>= Mshift;
+ wrreg(pp, MAP(i, Mofflo), offset);
+ wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
+ wrreg(pp, Rwe, we | bit); /* enable map */
+ m->ref = 1;
+
+ unlock(&pp->mlock);
+ return m;
+}
+
+void
+pcmunmap(int slotno, PCMmap* m)
+{
+ PCMslot *pp;
+
+ pp = slot + slotno;
+ lock(&pp->mlock);
+ m->ref--;
+ unlock(&pp->mlock);
+}
+
+static void
+increfp(PCMslot *pp)
+{
+ lock(pp);
+ if(pp->ref++ == 0)
+ slotena(pp);
+ unlock(pp);
+}
+
+static void
+decrefp(PCMslot *pp)
+{
+ lock(pp);
+ if(pp->ref-- == 1)
+ slotdis(pp);
+ unlock(pp);
+}
+
+/*
+ * look for a card whose version contains 'idstr'
+ */
+static int
+pcmcia_pcmspecial(char *idstr, ISAConf *isa)
+{
+ PCMslot *pp;
+ extern char *strstr(char*, char*);
+ int enabled;
+
+ i82365reset();
+ for(pp = slot; pp < lastslot; pp++){
+ if(pp->special)
+ continue; /* already taken */
+ enabled = 0;
+ /* make sure we don't power on cards when we already know what's
+ * in them. We'll reread every two minutes if necessary
+ */
+ if (pp->verstr[0] == '\0') {
+ increfp(pp);
+ enabled++;
+ }
+
+ if(pp->occupied) {
+ if(strstr(pp->verstr, idstr)){
+ if (!enabled){
+ enabled = 1;
+ increfp(pp);
+ }
+ if(isa == 0 || pcmio(pp->slotno, isa) == 0){
+ pp->special = 1;
+ return pp->slotno;
+ }
+ }
+ } else
+ pp->special = 1;
+ if (enabled)
+ decrefp(pp);
+ }
+ return -1;
+}
+
+static void
+pcmcia_pcmspecialclose(int slotno)
+{
+ PCMslot *pp;
+
+ print("pcmspecialclose called\n");
+ if(slotno >= nslot)
+ panic("pcmspecialclose");
+ pp = slot + slotno;
+ pp->special = 0;
+ decrefp(pp);
+}
+
+static char *chipname[] =
+{
+[Ti82365] "Intel 82365SL",
+[Tpd6710] "Cirrus Logic PD6710",
+[Tpd6720] "Cirrus Logic PD6720",
+[Tvg46x] "Vadem VG-46x",
+};
+
+static I82365*
+i82365probe(int x, int d, int dev)
+{
+ uchar c, id;
+ I82365 *cp;
+ ISAConf isa;
+ int i, nslot;
+
+ outb(x, Rid + (dev<<7));
+ id = inb(d);
+ if((id & 0xf0) != 0x80)
+ return 0; /* not a memory & I/O card */
+ if((id & 0x0f) == 0x00)
+ return 0; /* no revision number, not possible */
+
+ cp = xalloc(sizeof(I82365));
+ cp->xreg = x;
+ cp->dreg = d;
+ cp->dev = dev;
+ cp->type = Ti82365;
+ cp->nslot = 2;
+
+ switch(id){
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ /* could be a cirrus */
+ outb(x, Rchipinfo + (dev<<7));
+ outb(d, 0);
+ c = inb(d);
+ if((c & 0xc0) != 0xc0)
+ break;
+ c = inb(d);
+ if((c & 0xc0) != 0x00)
+ break;
+ if(c & 0x20){
+ cp->type = Tpd6720;
+ } else {
+ cp->type = Tpd6710;
+ cp->nslot = 1;
+ }
+
+ /* low power mode */
+ outb(x, Rmisc2 + (dev<<7));
+ c = inb(d);
+ outb(d, c & ~Flowpow);
+ break;
+ }
+
+ /* if it's not a Cirrus, it could be a Vadem... */
+ if(cp->type == Ti82365){
+ /* unlock the Vadem extended regs */
+ outb(x, 0x0E + (dev<<7));
+ outb(x, 0x37 + (dev<<7));
+
+ /* make the id register show the Vadem id */
+ outb(x, 0x3A + (dev<<7));
+ c = inb(d);
+ outb(d, c|0xC0);
+ outb(x, Rid + (dev<<7));
+ c = inb(d);
+ if(c & 0x08)
+ cp->type = Tvg46x;
+
+ /* go back to Intel compatible id */
+ outb(x, 0x3A + (dev<<7));
+ c = inb(d);
+ outb(d, c & ~0xC0);
+ }
+
+ memset(&isa, 0, sizeof(ISAConf));
+ if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq)
+ cp->irq = isa.irq;
+ else
+ cp->irq = VectorPCMCIA - VectorPIC;
+
+ for(i = 0; i < isa.nopt; i++){
+ if(cistrncmp(isa.opt[i], "nslot=", 6))
+ continue;
+ nslot = strtol(&isa.opt[i][6], nil, 0);
+ if(nslot > 0 && nslot <= 2)
+ cp->nslot = nslot;
+ }
+
+ controller[ncontroller++] = cp;
+ return cp;
+}
+
+static void
+i82365dump(PCMslot *pp)
+{
+ int i;
+
+ for(i = 0; i < 0x40; i++){
+ if((i&0x0F) == 0)
+ print("\n%2.2uX: ", i);
+ if(((i+1) & 0x0F) == 0x08)
+ print(" - ");
+ print("%2.2uX ", rdreg(pp, i));
+ }
+ print("\n");
+}
+
+/*
+ * set up for slot cards
+ */
+static void
+i82365reset(void)
+{
+ static int already;
+ int i, j;
+ I82365 *cp;
+ PCMslot *pp;
+
+ if(already)
+ return;
+ already = 1;
+
+
+ /* look for controllers */
+ i82365probe(0x3E0, 0x3E1, 0);
+ i82365probe(0x3E0, 0x3E1, 1);
+ i82365probe(0x3E2, 0x3E3, 0);
+ i82365probe(0x3E2, 0x3E3, 1);
+
+ for(i = 0; i < ncontroller; i++)
+ nslot += controller[i]->nslot;
+ slot = xalloc(nslot * sizeof(PCMslot));
+
+ lastslot = slot;
+ for(i = 0; i < ncontroller; i++){
+ cp = controller[i];
+ print("#y%d: %d slot %s: port 0x%uX irq %d\n",
+ i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq);
+ for(j = 0; j < cp->nslot; j++){
+ pp = lastslot++;
+ pp->slotno = pp - slot;
+ pp->memlen = 64*MB;
+ pp->base = (cp->dev<<7) | (j<<6);
+ pp->cp = cp;
+ pp->msec = ~0;
+ pp->verstr[0] = 0;
+ slotdis(pp);
+
+ /* interrupt on status change */
+ wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena);
+ rdreg(pp, Rcsc);
+ }
+
+ /* for card management interrupts */
+ setvec(cp->irq+VectorPIC, i82365intr, 0);
+ }
+}
+
+/*
+ * configure the PCMslot for IO. We assume very heavily that we can read
+ * configuration info from the CIS. If not, we won't set up correctly.
+ */
+static int
+pcmio(int slotno, ISAConf *isa)
+{
+ uchar we, x, *p;
+ PCMslot *pp;
+ PCMconftab *ct, *et, *t;
+ PCMmap *m;
+ int i, index, irq;
+ char *cp;
+
+ irq = isa->irq;
+ if(irq == 2)
+ irq = 9;
+
+ if(slotno > nslot)
+ return -1;
+ pp = slot + slotno;
+
+ if(!pp->occupied)
+ return -1;
+
+ et = &pp->ctab[pp->nctab];
+
+ ct = 0;
+ for(i = 0; i < isa->nopt; i++){
+ if(strncmp(isa->opt[i], "index=", 6))
+ continue;
+ index = strtol(&isa->opt[i][6], &cp, 0);
+ if(cp == &isa->opt[i][6] || index >= pp->nctab)
+ return -1;
+ ct = &pp->ctab[index];
+ }
+
+ if(ct == 0){
+
+ /* assume default is right */
+ if(pp->def)
+ ct = pp->def;
+ else
+ ct = pp->ctab;
+
+ /* try for best match */
+ if(ct->nio == 0
+ || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
+ for(t = pp->ctab; t < et; t++)
+ if(t->nio
+ && t->io[0].start == isa->port
+ && ((1<<irq) & t->irqs)){
+ ct = t;
+ break;
+ }
+ }
+ if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
+ for(t = pp->ctab; t < et; t++)
+ if(t->nio && ((1<<irq) & t->irqs)){
+ ct = t;
+ break;
+ }
+ }
+ if(ct->nio == 0){
+ for(t = pp->ctab; t < et; t++)
+ if(t->nio){
+ ct = t;
+ break;
+ }
+ }
+ }
+
+ if(ct == et || ct->nio == 0)
+ return -1;
+ if(isa->port == 0 && ct->io[0].start == 0)
+ return -1;
+
+ /* route interrupts */
+ isa->irq = irq;
+ wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
+
+ /* set power and enable device */
+ x = vcode(ct->vpp1);
+ wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
+
+ /* 16-bit data path */
+ if(ct->bit16)
+ x = Ftiming|Fiocs16|Fwidth16;
+ else
+ x = Ftiming;
+ if(ct->nio == 2 && ct->io[1].start)
+ x |= x<<4;
+ wrreg(pp, Rio, x);
+
+ /*
+ * enable io port map 0
+ * the 'top' register value includes the last valid address
+ */
+ if(isa->port == 0)
+ isa->port = ct->io[0].start;
+ we = rdreg(pp, Rwe);
+ wrreg(pp, Riobtm0lo, isa->port);
+ wrreg(pp, Riobtm0hi, isa->port>>8);
+ i = isa->port+ct->io[0].len-1;
+ wrreg(pp, Riotop0lo, i);
+ wrreg(pp, Riotop0hi, i>>8);
+ we |= 1<<6;
+ if(ct->nio >= 2 && ct->io[1].start){
+ wrreg(pp, Riobtm1lo, ct->io[1].start);
+ wrreg(pp, Riobtm1hi, ct->io[1].start>>8);
+ i = ct->io[1].start+ct->io[1].len-1;
+ wrreg(pp, Riotop1lo, i);
+ wrreg(pp, Riotop1hi, i>>8);
+ we |= 1<<7;
+ }
+ wrreg(pp, Rwe, we);
+
+ /* only touch Rconfig if it is present */
+ m = pcmmap(slotno, pp->cfg[0].caddr + Rconfig, 0x20, 1);
+ p = KADDR(m->isa + pp->cfg[0].caddr - m->ca);
+ if(pp->cfg[0].cpresent & (1<<Rconfig)){
+ /* Reset adapter */
+
+ /* set configuration and interrupt type.
+ * if level is possible on the card, use it.
+ */
+ x = ct->index;
+ if(ct->irqtype & 0x20)
+ x |= Clevel;
+
+ /* enable the device, enable address decode and
+ * irq enable.
+ */
+ x |= Cfunc|Cdecode|Cirq;
+
+ p[0] = x;
+ //delay(5);
+ microdelay(40);
+ }
+
+ if(pp->cfg[0].cpresent & (1<<Riobase0)){
+ /* set up the iobase 0 */
+ p[Riobase0 << 1] = isa->port;
+ p[Riobase1 << 1] = isa->port >> 8;
+ }
+
+ if(pp->cfg[0].cpresent & (1<<Riosize))
+ p[Riosize << 1] = ct->io[0].len;
+ pcmunmap(slotno, m);
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/devpccard.c
@@ -1,0 +1,1606 @@
+/*
+ cardbus and pcmcia (grmph) support.
+*/
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "io.h"
+
+extern int pciscan(int, Pcidev **);
+
+int (*_pcmspecial)(char *, ISAConf *);
+void (*_pcmspecialclose)(int);
+
+int
+pcmspecial(char *idstr, ISAConf *isa)
+{
+ return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1;
+}
+
+void
+pcmspecialclose(int a)
+{
+ if (_pcmspecialclose != nil)
+ _pcmspecialclose(a);
+}
+
+static ulong
+ioreserve(ulong, int size, int align, char *)
+{
+ static ulong isaend = 0x400; /*0xfd00*/
+ ulong ioaddr;
+
+ if (align)
+ isaend = ((isaend + align - 1) / align) * align;
+ ioaddr = isaend;
+ isaend += size;
+ return ioaddr;
+}
+
+#define MAP(x,o) (Rmap + (x)*0x8 + o)
+
+enum {
+ TI_vid = 0x104c,
+ TI_1131_did = 0xAC15,
+ TI_1250_did = 0xAC16,
+ TI_1450_did = 0xAC1B,
+ TI_1251A_did = 0xAC1D,
+ TI_1420_did = 0xAC51,
+
+ Ricoh_vid = 0x1180,
+ Ricoh_475_did = 0x0475,
+ Ricoh_476_did = 0x0476,
+ Ricoh_478_did = 0x0478,
+
+ O2_vid = 0x1217,
+ O2_OZ711M3_did = 0x7134,
+
+ Nslots = 4, /* Maximum number of CardBus slots to use */
+
+ K = 1024,
+ M = K * K,
+
+ LegacyAddr = 0x3e0,
+ NUMEVENTS = 10,
+
+ TI1131xSC = 0x80, // system control
+ TI122X_SC_INTRTIE = 1 << 29,
+ TI12xxIM = 0x8c, //
+ TI1131xCC = 0x91, // card control
+ TI113X_CC_RIENB = 1 << 7,
+ TI113X_CC_ZVENABLE = 1 << 6,
+ TI113X_CC_PCI_IRQ_ENA = 1 << 5,
+ TI113X_CC_PCI_IREQ = 1 << 4,
+ TI113X_CC_PCI_CSC = 1 << 3,
+ TI113X_CC_SPKROUTEN = 1 << 1,
+ TI113X_CC_IFG = 1 << 0,
+ TI1131xDC = 0x92, // device control
+};
+
+typedef struct Variant Variant;
+struct Variant {
+ ushort vid;
+ ushort did;
+ char *name;
+};
+
+static Variant variant[] = {
+{ Ricoh_vid, Ricoh_475_did, "Ricoh 475 PCI/Cardbus bridge", },
+{ Ricoh_vid, Ricoh_476_did, "Ricoh 476 PCI/Cardbus bridge", },
+{ Ricoh_vid, Ricoh_478_did, "Ricoh 478 PCI/Cardbus bridge", },
+{ TI_vid, TI_1131_did, "TI PCI-1131 Cardbus Controller", },
+{ TI_vid, TI_1250_did, "TI PCI-1250 Cardbus Controller", },
+{ TI_vid, TI_1450_did, "TI PCI-1450 Cardbus Controller", },
+{ TI_vid, TI_1251A_did, "TI PCI-1251A Cardbus Controller", },
+{ TI_vid, TI_1420_did, "TI PCI-1420 Cardbus Controller", },
+{ O2_vid, O2_OZ711M3_did, "O2Micro OZ711M3 MemoryCardBus", },
+};
+
+/* Cardbus registers */
+enum {
+ SocketEvent = 0,
+ SE_CCD = 3 << 1,
+ SE_POWER = 1 << 3,
+ SocketMask = 1,
+ SocketState = 2,
+ SS_CCD = 3 << 1,
+ SS_POWER = 1 << 3,
+ SS_PC16 = 1 << 4,
+ SS_CBC = 1 << 5,
+ SS_NOTCARD = 1 << 7,
+ SS_BADVCC = 1 << 9,
+ SS_5V = 1 << 10,
+ SS_3V = 1 << 11,
+ SocketForce = 3,
+ SocketControl = 4,
+ SC_5V = 0x22,
+ SC_3V = 0x33,
+};
+
+enum {
+ PciPCR_IO = 1 << 0,
+ PciPCR_MEM = 1 << 1,
+ PciPCR_Master = 1 << 2,
+
+ PciPMC = 0xa4,
+
+ Nbars = 6,
+ Ncmd = 10,
+ CBIRQ = 9,
+
+ PC16,
+ PC32,
+};
+
+enum {
+ Ti82365,
+ Tpd6710,
+ Tpd6720,
+ Tvg46x,
+};
+
+/*
+ * Intel 82365SL PCIC controller for the PCMCIA or
+ * Cirrus Logic PD6710/PD6720 which is mostly register compatible
+ */
+enum
+{
+ /*
+ * registers indices
+ */
+ Rid= 0x0, /* identification and revision */
+ Ris= 0x1, /* interface status */
+ Rpc= 0x2, /* power control */
+ Foutena= (1<<7), /* output enable */
+ Fautopower= (1<<5), /* automatic power switching */
+ Fcardena= (1<<4), /* PC card enable */
+ Rigc= 0x3, /* interrupt and general control */
+ Fiocard= (1<<5), /* I/O card (vs memory) */
+ Fnotreset= (1<<6), /* reset if not set */
+ FSMIena= (1<<4), /* enable change interrupt on SMI */
+ Rcsc= 0x4, /* card status change */
+ Rcscic= 0x5, /* card status change interrupt config */
+ Fchangeena= (1<<3), /* card changed */
+ Fbwarnena= (1<<1), /* card battery warning */
+ Fbdeadena= (1<<0), /* card battery dead */
+ Rwe= 0x6, /* address window enable */
+ Fmem16= (1<<5), /* use A23-A12 to decode address */
+ Rio= 0x7, /* I/O control */
+ Fwidth16= (1<<0), /* 16 bit data width */
+ Fiocs16= (1<<1), /* IOCS16 determines data width */
+ Fzerows= (1<<2), /* zero wait state */
+ Ftiming= (1<<3), /* timing register to use */
+ Riobtm0lo= 0x8, /* I/O address 0 start low byte */
+ Riobtm0hi= 0x9, /* I/O address 0 start high byte */
+ Riotop0lo= 0xa, /* I/O address 0 stop low byte */
+ Riotop0hi= 0xb, /* I/O address 0 stop high byte */
+ Riobtm1lo= 0xc, /* I/O address 1 start low byte */
+ Riobtm1hi= 0xd, /* I/O address 1 start high byte */
+ Riotop1lo= 0xe, /* I/O address 1 stop low byte */
+ Riotop1hi= 0xf, /* I/O address 1 stop high byte */
+ Rmap= 0x10, /* map 0 */
+
+ /*
+ * CL-PD67xx extension registers
+ */
+ Rmisc1= 0x16, /* misc control 1 */
+ F5Vdetect= (1<<0),
+ Fvcc3V= (1<<1),
+ Fpmint= (1<<2),
+ Fpsirq= (1<<3),
+ Fspeaker= (1<<4),
+ Finpack= (1<<7),
+ Rfifo= 0x17, /* fifo control */
+ Fflush= (1<<7), /* flush fifo */
+ Rmisc2= 0x1E, /* misc control 2 */
+ Flowpow= (1<<1), /* low power mode */
+ Rchipinfo= 0x1F, /* chip information */
+ Ratactl= 0x26, /* ATA control */
+
+ /*
+ * offsets into the system memory address maps
+ */
+ Mbtmlo= 0x0, /* System mem addr mapping start low byte */
+ Mbtmhi= 0x1, /* System mem addr mapping start high byte */
+ F16bit= (1<<7), /* 16-bit wide data path */
+ Mtoplo= 0x2, /* System mem addr mapping stop low byte */
+ Mtophi= 0x3, /* System mem addr mapping stop high byte */
+ Ftimer1= (1<<6), /* timer set 1 */
+ Mofflo= 0x4, /* Card memory offset address low byte */
+ Moffhi= 0x5, /* Card memory offset address high byte */
+ Fregactive= (1<<6), /* attribute memory */
+
+ /*
+ * configuration registers - they start at an offset in attribute
+ * memory found in the CIS.
+ */
+ Rconfig= 0,
+ Creset= (1<<7), /* reset device */
+ Clevel= (1<<6), /* level sensitive interrupt line */
+};
+
+/*
+ * read and crack the card information structure enough to set
+ * important parameters like power
+ */
+/* cis memory walking */
+typedef struct Cisdat Cisdat;
+struct Cisdat {
+ uchar *cisbase;
+ int cispos;
+ int cisskip;
+ int cislen;
+};
+
+typedef struct Pcminfo Pcminfo;
+struct Pcminfo {
+ char verstr[512]; /* Version string */
+ PCMmap mmap[4]; /* maps, last is always for the kernel */
+ ulong conf_addr; /* Config address */
+ uchar conf_present; /* Config register present */
+ int nctab; /* In use configuration tables */
+ PCMconftab ctab[8]; /* Configuration tables */
+ PCMconftab *defctab; /* Default conftab */
+
+ int port; /* Actual port usage */
+ int irq; /* Actual IRQ usage */
+};
+
+typedef struct Cardbus Cardbus;
+struct Cardbus {
+ Lock;
+ Variant *variant; /* Which CardBus chipset */
+ Pcidev *pci; /* The bridge itself */
+ ulong *regs; /* Cardbus registers */
+ int ltype; /* Legacy type */
+ int lindex; /* Legacy port index address */
+ int ldata; /* Legacy port data address */
+ int lbase; /* Base register for this socket */
+
+ int state; /* Current state of card */
+ int type; /* Type of card */
+ Pcminfo linfo; /* PCMCIA slot info */
+
+ int special; /* card is allocated to a driver */
+
+ int refs; /* Number of refs to slot */
+ Lock refslock; /* inc/dev ref lock */
+};
+
+enum {
+ Mshift= 12,
+ Mgran= (1<<Mshift), /* granularity of maps */
+ Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
+};
+
+static Cardbus cbslots[Nslots];
+static int nslots;
+
+static ulong exponent[8] = {
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
+};
+
+static ulong vmant[16] = {
+ 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
+};
+
+static ulong mantissa[16] = {
+ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80,
+};
+
+static void cbint(Ureg *, void *);
+static int powerup(Cardbus *);
+static void configure(Cardbus *);
+static void managecard(Cardbus *);
+static void cardmanager(void *);
+static void eject(Cardbus *);
+static void interrupt(Ureg *, void *);
+static void powerdown(Cardbus *cb);
+static void unconfigure(Cardbus *cb);
+
+static void i82365probe(Cardbus *cb, int lindex, int ldata);
+static void i82365configure(Cardbus *cb);
+static PCMmap *isamap(Cardbus *cb, ulong offset, int len, int attr);
+static void isaunmap(PCMmap* m);
+static uchar rdreg(Cardbus *cb, int index);
+static void wrreg(Cardbus *cb, int index, uchar val);
+static int readc(Cisdat *cis, uchar *x);
+static void tvers1(Cardbus *cb, Cisdat *cis, int );
+static void tcfig(Cardbus *cb, Cisdat *cis, int );
+static void tentry(Cardbus *cb, Cisdat *cis, int );
+static int vcode(int volt);
+static int pccard_pcmspecial(char *idstr, ISAConf *isa);
+static void pccard_pcmspecialclose(int slotno);
+
+enum {
+ CardDetected,
+ CardPowered,
+ CardEjected,
+ CardConfigured,
+};
+
+static char *messages[] = {
+[CardDetected] "CardDetected",
+[CardPowered] "CardPowered",
+[CardEjected] "CardEjected",
+[CardConfigured] "CardConfigured",
+};
+
+enum {
+ SlotEmpty,
+ SlotFull,
+ SlotPowered,
+ SlotConfigured,
+};
+
+static char *states[] = {
+[SlotEmpty] "SlotEmpty",
+[SlotFull] "SlotFull",
+[SlotPowered] "SlotPowered",
+[SlotConfigured] "SlotConfigured",
+};
+
+static void
+engine(Cardbus *cb, int message)
+{
+ // print("engine(%d): %s(%s)\n",
+ // (int)(cb - cbslots), states[cb->state], messages[message]);
+ switch (cb->state) {
+ case SlotEmpty:
+
+ switch (message) {
+ case CardDetected:
+ cb->state = SlotFull;
+ powerup(cb);
+ break;
+ case CardEjected:
+ break;
+ default:
+ //print("#Y%d: Invalid message %s in SlotEmpty state\n",
+ // (int)(cb - cbslots), messages[message]);
+ break;
+ }
+ break;
+
+ case SlotFull:
+
+ switch (message) {
+ case CardPowered:
+ cb->state = SlotPowered;
+ configure(cb);
+ break;
+ case CardEjected:
+ cb->state = SlotEmpty;
+ powerdown(cb);
+ break;
+ default:
+ //print("#Y%d: Invalid message %s in SlotFull state\n",
+ // (int)(cb - cbslots), messages[message]);
+ break;
+ }
+ break;
+
+ case SlotPowered:
+
+ switch (message) {
+ case CardConfigured:
+ cb->state = SlotConfigured;
+ break;
+ case CardEjected:
+ cb->state = SlotEmpty;
+ unconfigure(cb);
+ powerdown(cb);
+ break;
+ default:
+ print("#Y%d: Invalid message %s in SlotPowered state\n",
+ (int)(cb - cbslots), messages[message]);
+ break;
+ }
+ break;
+
+ case SlotConfigured:
+
+ switch (message) {
+ case CardEjected:
+ cb->state = SlotEmpty;
+ unconfigure(cb);
+ powerdown(cb);
+ break;
+ default:
+ //print("#Y%d: Invalid message %s in SlotConfigured state\n",
+ // (int)(cb - cbslots), messages[message]);
+ break;
+ }
+ break;
+ }
+}
+
+void
+devpccardlink(void)
+{
+ static int initialized;
+ Pcidev *pci;
+ int i;
+ char *p;
+
+ if (initialized)
+ return;
+ initialized = 1;
+
+ if((p=getconf("pccard0")) && strncmp(p, "disabled", 8)==0)
+ return;
+
+ if(_pcmspecial)
+ return;
+
+
+ /* Allocate legacy space */
+ if (ioalloc(LegacyAddr, 2, 0, "i82365.0") < 0)
+ print("#Y: WARNING: Cannot allocate legacy ports\n");
+
+ /* Find all CardBus controllers */
+ pci = nil;
+ while ((pci = pcimatch(pci, 0, 0)) != nil) {
+ ulong baddr;
+ uchar pin;
+ Cardbus *cb;
+ int slot;
+
+ if(pci->ccrb != 6 || pci->ccru != 7)
+ continue;
+ for (i = 0; i != nelem(variant); i++)
+ if (pci->vid == variant[i].vid && pci->did == variant[i].did)
+ break;
+ if (i == nelem(variant))
+ continue;
+
+ /* initialize this slot */
+ slot = nslots++;
+ cb = &cbslots[slot];
+
+ cb->pci = pci;
+ cb->variant = &variant[i];
+
+ // Set up PCI bus numbers if needed.
+ if (pcicfgr8(pci, PciSBN) == 0) {
+ static int busbase = 0x20;
+
+ pcicfgw8(pci, PciSBN, busbase);
+ pcicfgw8(pci, PciUBN, busbase + 2);
+ busbase += 3;
+ }
+
+ // Patch up intl if needed.
+ if ((pin = pcicfgr8(pci, PciINTP)) != 0 &&
+ (pci->intl == 0xff || pci->intl == 0)) {
+ pci->intl = pciipin(nil, pin);
+ pcicfgw8(pci, PciINTL, pci->intl);
+
+ if (pci->intl == 0xff || pci->intl == 0)
+ print("#Y%d: No interrupt?\n", (int)(cb - cbslots));
+ }
+
+ // Don't you love standards!
+ if (pci->vid == TI_vid) {
+ if (pci->did <= TI_1131_did) {
+ uchar cc;
+
+ cc = pcicfgr8(pci, TI1131xCC);
+ cc &= ~(TI113X_CC_PCI_IRQ_ENA |
+ TI113X_CC_PCI_IREQ |
+ TI113X_CC_PCI_CSC |
+ TI113X_CC_ZVENABLE);
+ cc |= TI113X_CC_PCI_IRQ_ENA |
+ TI113X_CC_PCI_IREQ |
+ TI113X_CC_SPKROUTEN;
+ pcicfgw8(pci, TI1131xCC, cc);
+
+ // PCI interrupts only
+ pcicfgw8(pci, TI1131xDC,
+ pcicfgr8(pci, TI1131xDC) & ~6);
+
+ // CSC ints to PCI bus.
+ wrreg(cb, Rigc, rdreg(cb, Rigc) | 0x10);
+ }
+ else if (pci->did == TI_1250_did) {
+ print("No support yet for the TI_1250_did, prod pb\n");
+ }
+ else if (pci->did == TI_1420_did) {
+ // Disable Vcc protection
+ pcicfgw32(cb->pci, 0x80,
+ pcicfgr32(cb->pci, 0x80) | (1 << 21));
+ }
+
+ pcicfgw16(cb->pci, PciPMC, pcicfgr16(cb->pci, PciPMC) & ~3);
+ }
+
+ if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {
+ int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
+
+ baddr = upamalloc(baddr, size, size);
+ pcicfgw32(cb->pci, PciBAR0, baddr);
+ cb->regs = (ulong *)KADDR(baddr);
+ }
+ else
+ cb->regs = (ulong *)KADDR(upamalloc(baddr, 4096, 0));
+ cb->state = SlotEmpty;
+
+ /* Don't really know what to do with this... */
+ i82365probe(cb, LegacyAddr, LegacyAddr + 1);
+
+ print("#Y%ld: %s, %.8ulX intl %d\n", cb - cbslots,
+ variant[i].name, baddr, pci->intl);
+ }
+
+ if (nslots == 0)
+ return;
+
+ _pcmspecial = pccard_pcmspecial;
+ _pcmspecialclose = pccard_pcmspecialclose;
+
+ for (i = 0; i != nslots; i++) {
+ Cardbus *cb = &cbslots[i];
+
+ if ((cb->regs[SocketState] & SE_CCD) == 0)
+ engine(cb, CardDetected);
+ }
+
+ delay(500); /* Allow time for power up */
+
+ for (i = 0; i != nslots; i++) {
+ Cardbus *cb = &cbslots[i];
+
+ if (cb->regs[SocketState] & SE_POWER)
+ engine(cb, CardPowered);
+
+ /* Ack and enable interrupts on all events */
+ //cb->regs[SocketEvent] = cb->regs[SocketEvent];
+ //cb->regs[SocketMask] |= 0xF;
+ //wrreg(cb, Rcscic, 0xC);
+ }
+}
+
+static int
+powerup(Cardbus *cb)
+{
+ ulong state;
+ ushort bcr;
+
+ state = cb->regs[SocketState];
+ if (state & SS_PC16) {
+
+ // print("#Y%ld: Probed a PC16 card, powering up card\n", cb - cbslots);
+ cb->type = PC16;
+ memset(&cb->linfo, 0, sizeof(Pcminfo));
+
+ /* power up and unreset, wait's are empirical (???) */
+ wrreg(cb, Rpc, Fautopower|Foutena|Fcardena);
+ delay(300);
+ wrreg(cb, Rigc, 0);
+ delay(100);
+ wrreg(cb, Rigc, Fnotreset);
+ delay(500);
+
+ return 1;
+ }
+
+ if (state & SS_CCD)
+ return 0;
+
+ if (state & SS_NOTCARD) {
+ print("#Y%ld: No card inserted\n", cb - cbslots);
+ return 0;
+ }
+
+ if (state & SS_BADVCC) {
+ print("#Y%ld: Bad VCC request to card, powering down card!\n",
+ cb - cbslots);
+ cb->regs[SocketControl] = 0;
+ return 0;
+ }
+
+ if ((state & SS_3V) == 0 && (state & SS_5V) == 0) {
+ print("#Y%ld: Unsupported voltage, powering down card!\n",
+ cb - cbslots);
+ cb->regs[SocketControl] = 0;
+ return 0;
+ }
+
+ //print("#Y%ld: card %spowered at %d volt\n", cb - cbslots,
+ // (state & SS_POWER)? "": "not ",
+ // (state & SS_3V)? 3: (state & SS_5V)? 5: -1);
+
+ /* Power up the card
+ * and make sure the secondary bus is not in reset.
+ */
+ cb->regs[SocketControl] = (state & SS_5V)? SC_5V: SC_3V;
+ delay(50);
+ bcr = pcicfgr16(cb->pci, PciBCR);
+ bcr &= ~0x40;
+ pcicfgw16(cb->pci, PciBCR, bcr);
+ delay(100);
+
+ cb->type = PC32;
+
+ return 1;
+}
+
+static void
+powerdown(Cardbus *cb)
+{
+ ushort bcr;
+
+ if (cb->type == PC16) {
+
+ wrreg(cb, Rpc, 0); /* turn off card power */
+ wrreg(cb, Rwe, 0); /* no windows */
+
+ cb->type = -1;
+ return;
+ }
+
+ bcr = pcicfgr16(cb->pci, PciBCR);
+ bcr |= 0x40;
+ pcicfgw16(cb->pci, PciBCR, bcr);
+ cb->regs[SocketControl] = 0;
+ cb->type = -1;
+}
+
+static void
+configure(Cardbus *cb)
+{
+ Pcidev *pci;
+ ulong size, bar;
+ int i, ioindex, memindex, r;
+
+ //print("configuring slot %d (%s)\n", (int)(cb - cbslots), states[cb->state]);
+ if (cb->state == SlotConfigured)
+ return;
+ engine(cb, CardConfigured);
+
+ delay(50); /* Emperically established */
+
+ if (cb->type == PC16) {
+ i82365configure(cb);
+ return;
+ }
+
+ /* Scan the CardBus for new PCI devices */
+ pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge);
+ pci = cb->pci->bridge;
+ while (pci) {
+ r = pcicfgr16(pci, PciPCR);
+ r &= ~(PciPCR_IO|PciPCR_MEM);
+ pcicfgw16(pci, PciPCR, r);
+
+ /*
+ * Treat the found device as an ordinary PCI card.
+ * It seems that the CIS is not always present in
+ * CardBus cards.
+ * XXX, need to support multifunction cards
+ */
+ memindex = ioindex = 0;
+ for (i = 0; i != Nbars; i++) {
+
+ if (pci->mem[i].size == 0)
+ continue;
+ if (pci->mem[i].bar & 1) {
+
+ // Allocate I/O space
+ if (ioindex > 1) {
+ print("#Y%ld: WARNING: Can only configure 2 I/O slots\n", cb - cbslots);
+ continue;
+ }
+ bar = ioreserve(-1, pci->mem[i].size, 0, "cardbus");
+ pci->mem[i].bar = bar | 1;
+ pcicfgw32(pci, PciBAR0 + i * sizeof(ulong),
+ pci->mem[i].bar);
+ pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, bar);
+ pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8,
+ bar + pci->mem[i].size - 1);
+ //print("ioindex[%d] %.8uX (%d)\n",
+ // ioindex, bar, pci->mem[i].size);
+ ioindex++;
+ continue;
+ }
+
+ // Allocating memory space
+ if (memindex > 1) {
+ print("#Y%ld: WARNING: Can only configure 2 memory slots\n", cb - cbslots);
+ continue;
+ }
+
+ bar = upamalloc(0, pci->mem[i].size, BY2PG);
+ pci->mem[i].bar = bar | (pci->mem[i].bar & 0x80);
+ pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), pci->mem[i].bar);
+ pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, bar);
+ pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8,
+ bar + pci->mem[i].size - 1);
+
+ if (pci->mem[i].bar & 0x80) {
+ /* Enable prefetch */
+ r = pcicfgr16(cb->pci, PciBCR);
+ r |= 1 << (8 + memindex);
+ pcicfgw16(cb->pci, PciBCR, r);
+ }
+
+ //print("memindex[%d] %.8uX (%d)\n",
+ // memindex, bar, pci->mem[i].size);
+ memindex++;
+ }
+
+ if ((size = pcibarsize(pci, PciEBAR0)) > 0) {
+
+ if (memindex > 1)
+ print("#Y%ld: WARNING: Too many memory spaces, not mapping ROM space\n",
+ cb - cbslots);
+ else {
+ pci->rom.bar = upamalloc(0, size, BY2PG);
+ pci->rom.size = size;
+
+ pcicfgw32(pci, PciEBAR0, pci->rom.bar);
+ pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8,
+ pci->rom.bar);
+ pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8,
+ pci->rom.bar + pci->rom.size - 1);
+ }
+ }
+
+ /* Set the basic PCI registers for the device */
+ pci->pcr = pcicfgr16(pci, PciPCR);
+ pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master;
+ pci->cls = 8;
+ pci->ltr = 64;
+ pcicfgw16(pci, PciPCR, pci->pcr);
+ pcicfgw8(pci, PciCLS, pci->cls);
+ pcicfgw8(pci, PciLTR, pci->ltr);
+
+ if (pcicfgr8(pci, PciINTP)) {
+ pci->intl = pcicfgr8(cb->pci, PciINTL);
+ pcicfgw8(pci, PciINTL, pci->intl);
+
+ /* Route interrupts to INTA#/B# */
+ pcicfgw16(cb->pci, PciBCR,
+ pcicfgr16(cb->pci, PciBCR) & ~(1 << 7));
+ }
+
+ pci = pci->list;
+ }
+}
+
+static void
+unconfigure(Cardbus *cb)
+{
+ Pcidev *pci;
+ int i, ioindex, memindex, r;
+
+ if (cb->type == PC16) {
+ print("#Y%d: Don't know how to unconfigure a PC16 card\n",
+ (int)(cb - cbslots));
+
+ memset(&cb->linfo, 0, sizeof(Pcminfo));
+ return;
+ }
+
+ pci = cb->pci->bridge;
+ if (pci == nil)
+ return; /* Not configured */
+ cb->pci->bridge = nil;
+
+ memindex = ioindex = 0;
+ while (pci) {
+ Pcidev *_pci;
+
+ for (i = 0; i != Nbars; i++) {
+ if (pci->mem[i].size == 0)
+ continue;
+ if (pci->mem[i].bar & 1) {
+ iofree(pci->mem[i].bar & ~1);
+ pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8,
+ (ushort)-1);
+ pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0);
+ ioindex++;
+ continue;
+ }
+
+ upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size);
+ pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
+ pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
+ r = pcicfgr16(cb->pci, PciBCR);
+ r &= ~(1 << (8 + memindex));
+ pcicfgw16(cb->pci, PciBCR, r);
+ memindex++;
+ }
+
+ if (pci->rom.bar && memindex < 2) {
+ upafree(pci->rom.bar & ~0xF, pci->rom.size);
+ pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
+ pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
+ memindex++;
+ }
+
+ _pci = pci->list;
+ free(_pci);
+ pci = _pci;
+ }
+}
+
+static void
+i82365configure(Cardbus *cb)
+{
+ int this;
+ Cisdat cis;
+ PCMmap *m;
+ uchar type, link;
+
+ /*
+ * Read all tuples in attribute space.
+ */
+ m = isamap(cb, 0, 0, 1);
+ if(m == 0)
+ return;
+
+ cis.cisbase = KADDR(m->isa);
+ cis.cispos = 0;
+ cis.cisskip = 2;
+ cis.cislen = m->len;
+
+ /* loop through all the tuples */
+ for(;;){
+ this = cis.cispos;
+ if(readc(&cis, &type) != 1)
+ break;
+ if(type == 0xFF)
+ break;
+ if(readc(&cis, &link) != 1)
+ break;
+
+ switch(type){
+ default:
+ break;
+ case 0x15:
+ tvers1(cb, &cis, type);
+ break;
+ case 0x1A:
+ tcfig(cb, &cis, type);
+ break;
+ case 0x1B:
+ tentry(cb, &cis, type);
+ break;
+ }
+
+ if(link == 0xFF)
+ break;
+ cis.cispos = this + (2+link);
+ }
+ isaunmap(m);
+}
+
+/*
+ * look for a card whose version contains 'idstr'
+ */
+static int
+pccard_pcmspecial(char *idstr, ISAConf *isa)
+{
+ int i, irq;
+ PCMconftab *ct, *et;
+ Pcminfo *pi;
+ Cardbus *cb;
+ uchar x, we, *p;
+
+ cb = nil;
+ for (i = 0; i != nslots; i++) {
+ cb = &cbslots[i];
+
+ lock(cb);
+ if (cb->state == SlotConfigured &&
+ cb->type == PC16 &&
+ !cb->special &&
+ strstr(cb->linfo.verstr, idstr))
+ break;
+ unlock(cb);
+ }
+
+ if (i == nslots) {
+ // print("#Y: %s not found\n", idstr);
+ return -1;
+ }
+
+ pi = &cb->linfo;
+
+ /*
+ * configure the PCMslot for IO. We assume very heavily that we can read
+ * configuration info from the CIS. If not, we won't set up correctly.
+ */
+ irq = isa->irq;
+ if(irq == 2)
+ irq = 9;
+
+ et = &pi->ctab[pi->nctab];
+ ct = nil;
+ for(i = 0; i < isa->nopt; i++){
+ int index;
+ char *cp;
+
+ if(strncmp(isa->opt[i], "index=", 6))
+ continue;
+ index = strtol(&isa->opt[i][6], &cp, 0);
+ if(cp == &isa->opt[i][6] || index >= pi->nctab) {
+ unlock(cb);
+ print("#Y%d: Cannot find index %d in conf table\n",
+ (int)(cb - cbslots), index);
+ return -1;
+ }
+ ct = &pi->ctab[index];
+ }
+
+ if(ct == nil){
+ PCMconftab *t;
+
+ /* assume default is right */
+ if(pi->defctab)
+ ct = pi->defctab;
+ else
+ ct = pi->ctab;
+
+ /* try for best match */
+ if(ct->nio == 0
+ || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
+ for(t = pi->ctab; t < et; t++)
+ if(t->nio
+ && t->io[0].start == isa->port
+ && ((1<<irq) & t->irqs)){
+ ct = t;
+ break;
+ }
+ }
+ if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
+ for(t = pi->ctab; t < et; t++)
+ if(t->nio && ((1<<irq) & t->irqs)){
+ ct = t;
+ break;
+ }
+ }
+ if(ct->nio == 0){
+ for(t = pi->ctab; t < et; t++)
+ if(t->nio){
+ ct = t;
+ break;
+ }
+ }
+ }
+
+ if(ct == et || ct->nio == 0) {
+ unlock(cb);
+ print("#Y%d: No configuration?\n", (int)(cb - cbslots));
+ return -1;
+ }
+ if(isa->port == 0 && ct->io[0].start == 0) {
+ unlock(cb);
+ print("#Y%d: No part or start address\n", (int)(cb - cbslots));
+ return -1;
+ }
+
+ cb->special = 1; /* taken */
+
+ /* route interrupts */
+ isa->irq = irq;
+ wrreg(cb, Rigc, irq | Fnotreset | Fiocard);
+
+ /* set power and enable device */
+ x = vcode(ct->vpp1);
+ wrreg(cb, Rpc, x|Fautopower|Foutena|Fcardena);
+
+ /* 16-bit data path */
+ if(ct->bit16)
+ x = Ftiming|Fiocs16|Fwidth16;
+ else
+ x = Ftiming;
+ if(ct->nio == 2 && ct->io[1].start)
+ x |= x<<4;
+ wrreg(cb, Rio, x);
+
+ /*
+ * enable io port map 0
+ * the 'top' register value includes the last valid address
+ */
+ if(isa->port == 0)
+ isa->port = ct->io[0].start;
+ we = rdreg(cb, Rwe);
+ wrreg(cb, Riobtm0lo, isa->port);
+ wrreg(cb, Riobtm0hi, isa->port>>8);
+ i = isa->port+ct->io[0].len-1;
+ wrreg(cb, Riotop0lo, i);
+ wrreg(cb, Riotop0hi, i>>8);
+ we |= 1<<6;
+ if(ct->nio == 2 && ct->io[1].start){
+ wrreg(cb, Riobtm1lo, ct->io[1].start);
+ wrreg(cb, Riobtm1hi, ct->io[1].start>>8);
+ i = ct->io[1].start+ct->io[1].len-1;
+ wrreg(cb, Riotop1lo, i);
+ wrreg(cb, Riotop1hi, i>>8);
+ we |= 1<<7;
+ }
+ wrreg(cb, Rwe, we);
+
+ /* only touch Rconfig if it is present */
+ if(pi->conf_present & (1<<Rconfig)){
+ PCMmap *m;
+
+ /* Reset adapter */
+ m = isamap(cb, pi->conf_addr + Rconfig, 1, 1);
+ p = KADDR(m->isa + pi->conf_addr + Rconfig - m->ca);
+
+ /* set configuration and interrupt type */
+ x = ct->index;
+ if((ct->irqtype & 0x20)/* && ((ct->irqtype & 0x40)==0 || isa->irq>7)*/)
+ x |= Clevel;
+ *p = x;
+ delay(5);
+
+ isaunmap(m);
+ }
+
+ pi->port = isa->port;
+ pi->irq = isa->irq;
+ unlock(cb);
+
+ print("#Y%d: %s irq %ld, port %lX\n", (int)(cb - cbslots), pi->verstr, isa->irq, isa->port);
+ return (int)(cb - cbslots);
+}
+
+static void
+pccard_pcmspecialclose(int slotno)
+{
+ Cardbus *cb = &cbslots[slotno];
+
+ wrreg(cb, Rwe, 0); /* no windows */
+ cb->special = 0;
+}
+
+static int
+xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
+{
+ PCMmap *m;
+ Cisdat cis;
+ int i, l;
+ uchar *p;
+ uchar type, link, n, c;
+ int this, subtype;
+ Cardbus *cb = &cbslots[slotno];
+
+ m = isamap(cb, 0, 0, attr);
+ if(m == 0)
+ return -1;
+
+ cis.cisbase = KADDR(m->isa);
+ cis.cispos = 0;
+ cis.cisskip = attr ? 2 : 1;
+ cis.cislen = m->len;
+
+ /* loop through all the tuples */
+ for(i = 0; i < 1000; i++){
+ this = cis.cispos;
+ if(readc(&cis, &type) != 1)
+ break;
+ if(type == 0xFF)
+ break;
+ if(readc(&cis, &link) != 1)
+ break;
+ if(link == 0xFF)
+ break;
+
+ n = link;
+ if (link > 1 && subtuple != -1) {
+ if (readc(&cis, &c) != 1)
+ break;
+ subtype = c;
+ n--;
+ } else
+ subtype = -1;
+
+ if(type == tuple && subtype == subtuple) {
+ p = v;
+ for(l=0; l<nv && l<n; l++)
+ if(readc(&cis, p++) != 1)
+ break;
+ isaunmap(m);
+ return nv;
+ }
+ cis.cispos = this + (2+link);
+ }
+ isaunmap(m);
+ return -1;
+}
+
+static PCMmap *
+isamap(Cardbus *cb, ulong offset, int len, int attr)
+{
+ uchar we, bit;
+ PCMmap *m, *nm;
+ Pcminfo *pi;
+ int i;
+ ulong e;
+
+ pi = &cb->linfo;
+
+ /* convert offset to granularity */
+ if(len <= 0)
+ len = 1;
+ e = ROUND(offset+len, Mgran);
+ offset &= Mmask;
+ len = e - offset;
+
+ /* look for a map that covers the right area */
+ we = rdreg(cb, Rwe);
+ bit = 1;
+ nm = 0;
+ for(m = pi->mmap; m < &pi->mmap[nelem(pi->mmap)]; m++){
+ if((we & bit))
+ if(m->attr == attr)
+ if(offset >= m->ca && e <= m->cea){
+
+ m->ref++;
+ return m;
+ }
+ bit <<= 1;
+ if(nm == 0 && m->ref == 0)
+ nm = m;
+ }
+ m = nm;
+ if(m == 0)
+ return 0;
+
+ /* if isa space isn't big enough, free it and get more */
+ if(m->len < len){
+ if(m->isa){
+ umbfree(m->isa, m->len);
+ m->len = 0;
+ }
+ m->isa = PADDR(umbmalloc(0, len, Mgran));
+ if(m->isa == 0){
+ print("isamap: out of isa space\n");
+ return 0;
+ }
+ m->len = len;
+ }
+
+ /* set up new map */
+ m->ca = offset;
+ m->cea = m->ca + m->len;
+ m->attr = attr;
+ i = m - pi->mmap;
+ bit = 1<<i;
+ wrreg(cb, Rwe, we & ~bit); /* disable map before changing it */
+ wrreg(cb, MAP(i, Mbtmlo), m->isa>>Mshift);
+ wrreg(cb, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
+ wrreg(cb, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
+ wrreg(cb, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
+ offset -= m->isa;
+ offset &= (1<<25)-1;
+ offset >>= Mshift;
+ wrreg(cb, MAP(i, Mofflo), offset);
+ wrreg(cb, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
+ wrreg(cb, Rwe, we | bit); /* enable map */
+ m->ref = 1;
+
+ return m;
+}
+
+static void
+isaunmap(PCMmap* m)
+{
+ m->ref--;
+}
+
+/*
+ * reading and writing card registers
+ */
+static uchar
+rdreg(Cardbus *cb, int index)
+{
+ outb(cb->lindex, cb->lbase + index);
+ return inb(cb->ldata);
+}
+
+static void
+wrreg(Cardbus *cb, int index, uchar val)
+{
+ outb(cb->lindex, cb->lbase + index);
+ outb(cb->ldata, val);
+}
+
+static int
+readc(Cisdat *cis, uchar *x)
+{
+ if(cis->cispos >= cis->cislen)
+ return 0;
+ *x = cis->cisbase[cis->cisskip*cis->cispos];
+ cis->cispos++;
+ return 1;
+}
+
+static ulong
+getlong(Cisdat *cis, int size)
+{
+ uchar c;
+ int i;
+ ulong x;
+
+ x = 0;
+ for(i = 0; i < size; i++){
+ if(readc(cis, &c) != 1)
+ break;
+ x |= c<<(i*8);
+ }
+ return x;
+}
+
+static void
+tcfig(Cardbus *cb, Cisdat *cis, int )
+{
+ uchar size, rasize, rmsize;
+ uchar last;
+ Pcminfo *pi;
+
+ if(readc(cis, &size) != 1)
+ return;
+ rasize = (size&0x3) + 1;
+ rmsize = ((size>>2)&0xf) + 1;
+ if(readc(cis, &last) != 1)
+ return;
+
+ pi = &cb->linfo;
+ pi->conf_addr = getlong(cis, rasize);
+ pi->conf_present = getlong(cis, rmsize);
+}
+
+static void
+tvers1(Cardbus *cb, Cisdat *cis, int )
+{
+ uchar c, major, minor, last;
+ int i;
+ Pcminfo *pi;
+
+ pi = &cb->linfo;
+ if(readc(cis, &major) != 1)
+ return;
+ if(readc(cis, &minor) != 1)
+ return;
+ last = 0;
+ for(i = 0; i < sizeof(pi->verstr) - 1; i++){
+ if(readc(cis, &c) != 1)
+ return;
+ if(c == 0)
+ c = ';';
+ if(c == '\n')
+ c = ';';
+ if(c == 0xff)
+ break;
+ if(c == ';' && last == ';')
+ continue;
+ pi->verstr[i] = c;
+ last = c;
+ }
+ pi->verstr[i] = 0;
+}
+
+static ulong
+microvolt(Cisdat *cis)
+{
+ uchar c;
+ ulong microvolts;
+ ulong exp;
+
+ if(readc(cis, &c) != 1)
+ return 0;
+ exp = exponent[c&0x7];
+ microvolts = vmant[(c>>3)&0xf]*exp;
+ while(c & 0x80){
+ if(readc(cis, &c) != 1)
+ return 0;
+ switch(c){
+ case 0x7d:
+ break; /* high impedence when sleeping */
+ case 0x7e:
+ case 0x7f:
+ microvolts = 0; /* no connection */
+ break;
+ default:
+ exp /= 10;
+ microvolts += exp*(c&0x7f);
+ }
+ }
+ return microvolts;
+}
+
+static ulong
+nanoamps(Cisdat *cis)
+{
+ uchar c;
+ ulong nanoamps;
+
+ if(readc(cis, &c) != 1)
+ return 0;
+ nanoamps = exponent[c&0x7]*vmant[(c>>3)&0xf];
+ while(c & 0x80){
+ if(readc(cis, &c) != 1)
+ return 0;
+ if(c == 0x7d || c == 0x7e || c == 0x7f)
+ nanoamps = 0;
+ }
+ return nanoamps;
+}
+
+/*
+ * only nominal voltage (feature 1) is important for config,
+ * other features must read card to stay in sync.
+ */
+static ulong
+power(Cisdat *cis)
+{
+ uchar feature;
+ ulong mv;
+
+ mv = 0;
+ if(readc(cis, &feature) != 1)
+ return 0;
+ if(feature & 1)
+ mv = microvolt(cis);
+ if(feature & 2)
+ microvolt(cis);
+ if(feature & 4)
+ microvolt(cis);
+ if(feature & 8)
+ nanoamps(cis);
+ if(feature & 0x10)
+ nanoamps(cis);
+ if(feature & 0x20)
+ nanoamps(cis);
+ if(feature & 0x40)
+ nanoamps(cis);
+ return mv/1000000;
+}
+
+static ulong
+ttiming(Cisdat *cis, int scale)
+{
+ uchar unscaled;
+ ulong nanosecs;
+
+ if(readc(cis, &unscaled) != 1)
+ return 0;
+ nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
+ nanosecs = nanosecs * exponent[scale];
+ return nanosecs;
+}
+
+static void
+timing(Cisdat *cis, PCMconftab *ct)
+{
+ uchar c, i;
+
+ if(readc(cis, &c) != 1)
+ return;
+ i = c&0x3;
+ if(i != 3)
+ ct->maxwait = ttiming(cis, i); /* max wait */
+ i = (c>>2)&0x7;
+ if(i != 7)
+ ct->readywait = ttiming(cis, i); /* max ready/busy wait */
+ i = (c>>5)&0x7;
+ if(i != 7)
+ ct->otherwait = ttiming(cis, i); /* reserved wait */
+}
+
+static void
+iospaces(Cisdat *cis, PCMconftab *ct)
+{
+ uchar c;
+ int i, nio;
+
+ ct->nio = 0;
+ if(readc(cis, &c) != 1)
+ return;
+
+ ct->bit16 = ((c>>5)&3) >= 2;
+ if(!(c & 0x80)){
+ ct->io[0].start = 0;
+ ct->io[0].len = 1<<(c&0x1f);
+ ct->nio = 1;
+ return;
+ }
+
+ if(readc(cis, &c) != 1)
+ return;
+
+ /*
+ * For each of the range descriptions read the
+ * start address and the length (value is length-1).
+ */
+ nio = (c&0xf)+1;
+ for(i = 0; i < nio; i++){
+ ct->io[i].start = getlong(cis, (c>>4)&0x3);
+ ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
+ }
+ ct->nio = nio;
+}
+
+static void
+irq(Cisdat *cis, PCMconftab *ct)
+{
+ uchar c;
+
+ if(readc(cis, &c) != 1)
+ return;
+ ct->irqtype = c & 0xe0;
+ if(c & 0x10)
+ ct->irqs = getlong(cis, 2);
+ else
+ ct->irqs = 1<<(c&0xf);
+ ct->irqs &= 0xDEB8; /* levels available to card */
+}
+
+static void
+memspace(Cisdat *cis, int asize, int lsize, int host)
+{
+ ulong haddress, address, len;
+
+ len = getlong(cis, lsize)*256;
+ address = getlong(cis, asize)*256;
+ USED(len, address);
+ if(host){
+ haddress = getlong(cis, asize)*256;
+ USED(haddress);
+ }
+}
+
+static void
+tentry(Cardbus *cb, Cisdat *cis, int )
+{
+ uchar c, i, feature;
+ PCMconftab *ct;
+ Pcminfo *pi;
+
+ pi = &cb->linfo;
+ if(pi->nctab >= nelem(pi->ctab))
+ return;
+ if(readc(cis, &c) != 1)
+ return;
+ ct = &pi->ctab[pi->nctab++];
+
+ /* copy from last default config */
+ if(pi->defctab)
+ *ct = *pi->defctab;
+
+ ct->index = c & 0x3f;
+
+ /* is this the new default? */
+ if(c & 0x40)
+ pi->defctab = ct;
+
+ /* memory wait specified? */
+ if(c & 0x80){
+ if(readc(cis, &i) != 1)
+ return;
+ if(i&0x80)
+ ct->memwait = 1;
+ }
+
+ if(readc(cis, &feature) != 1)
+ return;
+ switch(feature&0x3){
+ case 1:
+ ct->vpp1 = ct->vpp2 = power(cis);
+ break;
+ case 2:
+ power(cis);
+ ct->vpp1 = ct->vpp2 = power(cis);
+ break;
+ case 3:
+ power(cis);
+ ct->vpp1 = power(cis);
+ ct->vpp2 = power(cis);
+ break;
+ default:
+ break;
+ }
+ if(feature&0x4)
+ timing(cis, ct);
+ if(feature&0x8)
+ iospaces(cis, ct);
+ if(feature&0x10)
+ irq(cis, ct);
+ switch((feature>>5)&0x3){
+ case 1:
+ memspace(cis, 0, 2, 0);
+ break;
+ case 2:
+ memspace(cis, 2, 2, 0);
+ break;
+ case 3:
+ if(readc(cis, &c) != 1)
+ return;
+ for(i = 0; i <= (c&0x7); i++)
+ memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
+ break;
+ }
+}
+
+static void
+i82365probe(Cardbus *cb, int lindex, int ldata)
+{
+ uchar c, id;
+ int dev = 0; /* According to the Ricoh spec 00->3F _and_ 80->BF seem
+ to be the same socket A (ditto for B). */
+
+ outb(lindex, Rid + (dev<<7));
+ id = inb(ldata);
+ if((id & 0xf0) != 0x80)
+ return; /* not a memory & I/O card */
+ if((id & 0x0f) == 0x00)
+ return; /* no revision number, not possible */
+
+ cb->lindex = lindex;
+ cb->ldata = ldata;
+ cb->ltype = Ti82365;
+ cb->lbase = (int)(cb - cbslots) * 0x40;
+
+ switch(id){
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ /* could be a cirrus */
+ outb(cb->lindex, Rchipinfo + (dev<<7));
+ outb(cb->ldata, 0);
+ c = inb(cb->ldata);
+ if((c & 0xc0) != 0xc0)
+ break;
+ c = inb(cb->ldata);
+ if((c & 0xc0) != 0x00)
+ break;
+ if(c & 0x20){
+ cb->ltype = Tpd6720;
+ } else {
+ cb->ltype = Tpd6710;
+ }
+ break;
+ }
+
+ /* if it's not a Cirrus, it could be a Vadem... */
+ if(cb->ltype == Ti82365){
+ /* unlock the Vadem extended regs */
+ outb(cb->lindex, 0x0E + (dev<<7));
+ outb(cb->lindex, 0x37 + (dev<<7));
+
+ /* make the id register show the Vadem id */
+ outb(cb->lindex, 0x3A + (dev<<7));
+ c = inb(cb->ldata);
+ outb(cb->ldata, c|0xC0);
+ outb(cb->lindex, Rid + (dev<<7));
+ c = inb(cb->ldata);
+ if(c & 0x08)
+ cb->ltype = Tvg46x;
+
+ /* go back to Intel compatible id */
+ outb(cb->lindex, 0x3A + (dev<<7));
+ c = inb(cb->ldata);
+ outb(cb->ldata, c & ~0xC0);
+ }
+}
+
+static int
+vcode(int volt)
+{
+ switch(volt){
+ case 5:
+ return 1;
+ case 12:
+ return 2;
+ default:
+ return 0;
+ }
+}
--- /dev/null
+++ b/os/boot.original/pc/devsd.c
@@ -1,0 +1,631 @@
+/*
+ * Storage Device.
+ */
+#include "u.h"
+#include "mem.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "error.h"
+
+#include "sd.h"
+#include "fs.h"
+
+#define parttrace 0
+
+
+extern SDifc* sdifc[];
+
+static SDev* sdlist;
+static SDunit** sdunit;
+static int sdnunit;
+static int _sdmask;
+static int cdmask;
+static int sdmask;
+
+enum {
+ Rawcmd,
+ Rawdata,
+ Rawstatus,
+};
+
+void
+sdaddpart(SDunit* unit, char* name, uvlong start, uvlong end)
+{
+ SDpart *pp;
+ int i, partno;
+
+ if(parttrace)
+ print("add %d %s %s %lld %lld\n", unit->npart, unit->name, name, start, end);
+ /*
+ * Check name not already used
+ * and look for a free slot.
+ */
+ if(unit->part != nil){
+ partno = -1;
+ for(i = 0; i < SDnpart; i++){
+ pp = &unit->part[i];
+ if(!pp->valid){
+ if(partno == -1)
+ partno = i;
+ break;
+ }
+ if(strcmp(name, pp->name) == 0){
+ if(pp->start == start && pp->end == end){
+ if(parttrace)
+ print("already present\n");
+ return;
+ }
+ }
+ }
+ }else{
+ if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil){
+ if(parttrace)
+ print("malloc failed\n");
+ return;
+ }
+ partno = 0;
+ }
+
+ /*
+ * Check there is a free slot and size and extent are valid.
+ */
+ if(partno == -1 || start > end || end > unit->sectors){
+ print("cannot add %s!%s [%llud,%llud) to disk [0,%llud): %s\n",
+ unit->name, name, start, end, unit->sectors,
+ partno==-1 ? "no free partitions" : "partition boundaries out of range");
+ return;
+ }
+ pp = &unit->part[partno];
+ pp->start = start;
+ pp->end = end;
+ strncpy(pp->name, name, NAMELEN);
+ pp->valid = 1;
+ unit->npart++;
+}
+
+void
+sddelpart(SDunit* unit, char* name)
+{
+ int i;
+ SDpart *pp;
+
+ if(parttrace)
+ print("del %d %s %s\n", unit->npart, unit->name, name);
+ /*
+ * Look for the partition to delete.
+ * Can't delete if someone still has it open.
+ * If it's the last valid partition zap the
+ * whole table.
+ */
+ pp = unit->part;
+ for(i = 0; i < SDnpart; i++){
+ if(strncmp(name, pp->name, NAMELEN) == 0)
+ break;
+ pp++;
+ }
+ if(i >= SDnpart)
+ return;
+ pp->valid = 0;
+
+ unit->npart--;
+ if(unit->npart == 0){
+ free(unit->part);
+ unit->part = nil;
+ }
+}
+
+static int
+sdinitpart(SDunit* unit)
+{
+ unit->sectors = unit->secsize = 0;
+ unit->npart = 0;
+ if(unit->part){
+ free(unit->part);
+ unit->part = nil;
+ }
+
+ if(unit->inquiry[0] & 0xC0)
+ return 0;
+ switch(unit->inquiry[0] & 0x1F){
+ case 0x00: /* DA */
+ case 0x04: /* WORM */
+ case 0x05: /* CD-ROM */
+ case 0x07: /* MO */
+ break;
+ default:
+ return 0;
+ }
+
+ if(unit->dev->ifc->online == nil || unit->dev->ifc->online(unit) == 0)
+ return 0;
+ sdaddpart(unit, "data", 0, unit->sectors);
+ return 1;
+}
+
+static SDunit*
+sdgetunit(SDev* sdev, int subno)
+{
+ int index;
+ SDunit *unit;
+
+ /*
+ * Associate a unit with a given device and sub-unit
+ * number on that device.
+ * The device will be probed if it has not already been
+ * successfully accessed.
+ */
+ qlock(&sdqlock);
+ index = sdev->index+subno;
+ unit = sdunit[index];
+ if(unit == nil){
+ if((unit = malloc(sizeof(SDunit))) == nil){
+ qunlock(&sdqlock);
+ return nil;
+ }
+
+ if(sdev->enabled == 0 && sdev->ifc->enable)
+ sdev->ifc->enable(sdev);
+ sdev->enabled = 1;
+
+ snprint(unit->name, NAMELEN, "sd%c%d", sdev->idno, subno);
+ unit->subno = subno;
+ unit->dev = sdev;
+
+ /*
+ * No need to lock anything here as this is only
+ * called before the unit is made available in the
+ * sdunit[] array.
+ */
+ if(unit->dev->ifc->verify(unit) == 0){
+ qunlock(&sdqlock);
+ free(unit);
+ return nil;
+ }
+ sdunit[index] = unit;
+ }
+ qunlock(&sdqlock);
+
+ return unit;
+}
+
+static SDunit*
+sdindex2unit(int index)
+{
+ SDev *sdev;
+
+ /*
+ * Associate a unit with a given index into the top-level
+ * device directory.
+ * The device will be probed if it has not already been
+ * successfully accessed.
+ */
+ for(sdev = sdlist; sdev != nil; sdev = sdev->next){
+ if(index >= sdev->index && index < sdev->index+sdev->nunit)
+ return sdgetunit(sdev, index-sdev->index);
+ }
+
+ return nil;
+}
+
+static void
+_sddetach(void)
+{
+ SDev *sdev;
+
+ for(sdev = sdlist; sdev != nil; sdev = sdev->next){
+ if(sdev->enabled == 0)
+ continue;
+ if(sdev->ifc->disable)
+ sdev->ifc->disable(sdev);
+ sdev->enabled = 0;
+ }
+}
+
+static void
+sddump(void)
+{
+ SDev *sdev;
+
+ print("sdevs:\n");
+ for(sdev = sdlist; sdev != nil; sdev = sdev->next){
+ print("sdev %c index %d nunit %d: ",
+ sdev->idno, sdev->index, sdev->nunit);
+ print("\n");
+ }
+}
+
+static int
+_sdinit(void)
+{
+ ulong m;
+ int i;
+ SDev *sdev, *tail;
+ SDunit *unit;
+
+ /*
+ * Probe all configured controllers and make a list
+ * of devices found, accumulating a possible maximum number
+ * of units attached and marking each device with an index
+ * into the linear top-level directory array of units.
+ */
+ tail = nil;
+ for(i = 0; sdifc[i] != nil; i++){
+ if((sdev = sdifc[i]->pnp()) == nil)
+ continue;
+ if(sdlist != nil)
+ tail->next = sdev;
+ else
+ sdlist = sdev;
+ for(tail = sdev; tail->next != nil; tail = tail->next){
+ tail->index = sdnunit;
+ sdnunit += tail->nunit;
+ }
+ tail->index = sdnunit;
+ sdnunit += tail->nunit;
+ }
+ /*
+ * Legacy and option code goes here. This will be hard...
+ */
+
+ /*
+ * The maximum number of possible units is known, allocate
+ * placeholders for their datastructures; the units will be
+ * probed and structures allocated when attached.
+ * Allocate controller names for the different types.
+ */
+ if(sdnunit == 0)
+ return 0;
+ if((sdunit = malloc(sdnunit*sizeof(SDunit*))) == nil)
+ return 0;
+ sddetach = _sddetach;
+
+ for(i = 0; sdifc[i] != nil; i++){
+ if(sdifc[i]->id)
+ sdifc[i]->id(sdlist);
+ }
+ if (0)
+ sddump();
+
+ m = 0;
+ cdmask = sdmask = 0;
+ for(i=0; i<sdnunit && i < 32; i++) {
+ unit = sdindex2unit(i);
+ if(unit == nil)
+ continue;
+ sdinitpart(unit);
+ partition(unit);
+ if(unit->npart > 0){ /* BUG */
+ if((unit->inquiry[0] & 0x1F) == 0x05)
+ cdmask |= (1<<i);
+ else
+ sdmask |= (1<<i);
+ m |= (1<<i);
+ }
+ }
+
+//notesdinfo();
+ _sdmask = m;
+ return m;
+}
+
+int
+cdinit(void)
+{
+ if(sdnunit == 0)
+ _sdinit();
+ return cdmask;
+}
+
+int
+sdinit(void)
+{
+ if(sdnunit == 0)
+ _sdinit();
+ return sdmask;
+}
+
+void
+sdinitdev(int i, char *s)
+{
+ SDunit *unit;
+
+ unit = sdindex2unit(i);
+ strcpy(s, unit->name);
+}
+
+void
+sdprintdevs(int i)
+{
+ char *s;
+ SDunit *unit;
+
+ unit = sdindex2unit(i);
+ for(i=0; i<unit->npart; i++){
+ s = unit->part[i].name;
+ if(strncmp(s, "dos", 3) == 0
+ || strncmp(s, "9fat", 4) == 0
+ || strncmp(s, "fs", 2) == 0)
+ print(" %s!%s", unit->name, s);
+ }
+}
+
+SDpart*
+sdfindpart(SDunit *unit, char *name)
+{
+ int i;
+
+ if(parttrace)
+ print("findpart %d %s %s\t\n", unit->npart, unit->name, name);
+ for(i=0; i<unit->npart; i++) {
+ if(parttrace)
+ print("%s...", unit->part[i].name);
+ if(strcmp(unit->part[i].name, name) == 0){
+ if(parttrace)
+ print("\n");
+ return &unit->part[i];
+ }
+ }
+ if(parttrace)
+ print("not found\n");
+ return nil;
+}
+
+typedef struct Scsicrud Scsicrud;
+struct Scsicrud {
+ Fs fs;
+ vlong offset;
+ SDunit *unit;
+ SDpart *part;
+};
+
+long
+sdread(Fs *vcrud, void *v, long n)
+{
+ Scsicrud *crud;
+ long x;
+
+ crud = (Scsicrud*)vcrud;
+ x = sdbio(crud->unit, crud->part, v, n, crud->offset);
+ if(x > 0)
+ crud->offset += x;
+ return x;
+}
+
+vlong
+sdseek(Fs *vcrud, vlong seek)
+{
+ ((Scsicrud*)vcrud)->offset = seek;
+ return seek;
+}
+
+void*
+sdgetfspart(int i, char *s, int chatty)
+{
+ SDunit *unit;
+ SDpart *p;
+ Scsicrud *crud;
+
+ if(cdmask&(1<<i)){
+ if(strcmp(s, "cdboot") != 0)
+ return nil;
+ }else if(sdmask&(1<<i)){
+ if(strcmp(s, "cdboot") == 0)
+ return nil;
+ }
+
+ unit = sdindex2unit(i);
+ if((p = sdfindpart(unit, s)) == nil){
+ if(chatty)
+ print("unknown partition %s!%s\n", unit->name, s);
+ return nil;
+ }
+ if(p->crud == nil) {
+ crud = malloc(sizeof(Scsicrud));
+ crud->fs.dev = i;
+ crud->fs.diskread = sdread;
+ crud->fs.diskseek = sdseek;
+ // crud->start = 0;
+ crud->unit = unit;
+ crud->part = p;
+ if(dosinit(&crud->fs) < 0 && dosinit(&crud->fs) < 0 && kfsinit(&crud->fs) < 0){
+ if(chatty)
+ print("partition %s!%s does not contain a DOS or KFS file system\n",
+ unit->name, s);
+ return nil;
+ }
+ p->crud = crud;
+ }
+ return p->crud;
+}
+
+/*
+ * Leave partitions around for devsd to pick up.
+ * (Needed by boot process; more extensive
+ * partitioning is done by termrc or cpurc).
+ */
+void
+sdaddconf(int i)
+{
+ SDunit *unit;
+ SDpart *pp;
+
+ unit = sdindex2unit(i);
+
+ /*
+ * If there were no partitions (just data and partition), don't bother.
+ */
+ if(unit->npart<= 1 || (unit->npart==2 && strcmp(unit->part[1].name, "partition")==0))
+ return;
+
+ addconf("%spart=", unit->name);
+ for(i=1, pp=&unit->part[i]; i<unit->npart; i++, pp++) /* skip 0, which is "data" */
+ addconf("%s%s %lld %lld", i==1 ? "" : "/", pp->name,
+ pp->start, pp->end);
+ addconf("\n");
+}
+
+int
+sdboot(int dev, char *pname, Boot *b)
+{
+ char *file;
+ Fs *fs;
+
+ if((file = strchr(pname, '!')) == nil) {
+ print("syntax is sdC0!partition!file\n");
+ return -1;
+ }
+ *file++ = '\0';
+
+ fs = sdgetfspart(dev, pname, 1);
+ if(fs == nil)
+ return -1;
+
+ return fsboot(fs, file, b);
+}
+
+long
+sdbio(SDunit *unit, SDpart *pp, void* va, long len, vlong off)
+{
+ long l;
+ ulong bno, max, nb, offset;
+ static uchar *b;
+ char *a;
+ static ulong bsz;
+
+ a = va;
+memset(a, 0xDA, len);
+ qlock(&unit->ctl);
+ if(unit->changed){
+ qunlock(&unit->ctl);
+ return 0;
+ }
+
+ /*
+ * Check the request is within bounds.
+ * Removeable drives are locked throughout the I/O
+ * in case the media changes unexpectedly.
+ * Non-removeable drives are not locked during the I/O
+ * to allow the hardware to optimise if it can; this is
+ * a little fast and loose.
+ * It's assumed that non-removable media parameters
+ * (sectors, secsize) can't change once the drive has
+ * been brought online.
+ */
+ bno = (off/unit->secsize) + pp->start;
+ nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
+ max = SDmaxio/unit->secsize;
+ if(nb > max)
+ nb = max;
+ if(bno+nb > pp->end)
+ nb = pp->end - bno;
+ if(bno >= pp->end || nb == 0){
+ qunlock(&unit->ctl);
+ return 0;
+ }
+ if(!(unit->inquiry[1] & 0x80))
+ qunlock(&unit->ctl);
+
+ if(bsz < nb*unit->secsize){
+ b = malloc(nb*unit->secsize);
+ bsz = nb*unit->secsize;
+ }
+// b = sdmalloc(nb*unit->secsize);
+// if(b == nil)
+// return 0;
+
+ offset = off%unit->secsize;
+ if((l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno)) < 0) {
+// sdfree(b);
+ return 0;
+ }
+
+ if(l < offset)
+ len = 0;
+ else if(len > l - offset)
+ len = l - offset;
+ if(len)
+ memmove(a, b+offset, len);
+// sdfree(b);
+
+ if(unit->inquiry[1] & 0x80)
+ qunlock(&unit->ctl);
+
+ return len;
+}
+
+#ifdef DMA
+long
+sdrio(SDreq *r, void* a, long n)
+{
+ if(n >= SDmaxio || n < 0)
+ return 0;
+
+ r->data = nil;
+ if(n){
+ if((r->data = malloc(n)) == nil)
+ return 0;
+ if(r->write)
+ memmove(r->data, a, n);
+ }
+ r->dlen = n;
+
+ if(r->unit->dev->ifc->rio(r) != SDok){
+// cgascreenputs("1", 1);
+ if(r->data != nil){
+ sdfree(r->data);
+ r->data = nil;
+ }
+ return 0;
+ }
+// cgascreenputs("2", 1);
+
+ if(!r->write && r->rlen > 0)
+ memmove(a, r->data, r->rlen);
+// cgascreenputs("3", 1);
+ if(r->data != nil){
+ sdfree(r->data);
+ r->data = nil;
+ }
+
+// cgascreenputs("4", 1);
+ return r->rlen;
+}
+#endif /* DMA */
+
+void
+sleep(void*, int (*fn)(void*), void *v)
+{
+ int x;
+ x = spllo();
+ while(!fn(v))
+ ;
+ splx(x);
+ return;
+}
+
+void
+tsleep(void*, int (*fn)(void*), void *v, int msec)
+{
+ int x;
+ ulong start;
+
+ x = spllo();
+ for(start = m->ticks; TK2MS(m->ticks - start) < msec
+ && !fn(v); )
+ ;
+ splx(x);
+ return;
+}
+
+void*
+sdmalloc(void *p, ulong sz)
+{
+ if(p != nil) {
+ memset(p, 0, sz);
+ return p;
+ }
+ return malloc(sz);
+}
--- /dev/null
+++ b/os/boot.original/pc/dma.c
@@ -1,0 +1,245 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+typedef struct DMAport DMAport;
+typedef struct DMA DMA;
+typedef struct DMAxfer DMAxfer;
+
+enum
+{
+ /*
+ * the byte registers for DMA0 are all one byte apart
+ */
+ Dma0= 0x00,
+ Dma0status= Dma0+0x8, /* status port */
+ Dma0reset= Dma0+0xD, /* reset port */
+
+ /*
+ * the byte registers for DMA1 are all two bytes apart (why?)
+ */
+ Dma1= 0xC0,
+ Dma1status= Dma1+2*0x8, /* status port */
+ Dma1reset= Dma1+2*0xD, /* reset port */
+};
+
+/*
+ * state of a dma transfer
+ */
+struct DMAxfer
+{
+ ulong bpa; /* bounce buffer physical address */
+ void* bva; /* bounce buffer virtual address */
+ void* va; /* virtual address destination/src */
+ long len; /* bytes to be transferred */
+ int isread;
+};
+
+/*
+ * the dma controllers. the first half of this structure specifies
+ * the I/O ports used by the DMA controllers.
+ */
+struct DMAport
+{
+ uchar addr[4]; /* current address (4 channels) */
+ uchar count[4]; /* current count (4 channels) */
+ uchar page[4]; /* page registers (4 channels) */
+ uchar cmd; /* command status register */
+ uchar req; /* request registers */
+ uchar sbm; /* single bit mask register */
+ uchar mode; /* mode register */
+ uchar cbp; /* clear byte pointer */
+ uchar mc; /* master clear */
+ uchar cmask; /* clear mask register */
+ uchar wam; /* write all mask register bit */
+};
+
+struct DMA
+{
+ DMAport;
+ int shift;
+ Lock;
+ DMAxfer x[4];
+};
+
+DMA dma[2] = {
+ { 0x00, 0x02, 0x04, 0x06,
+ 0x01, 0x03, 0x05, 0x07,
+ 0x87, 0x83, 0x81, 0x82,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0 },
+
+ { 0xc0, 0xc4, 0xc8, 0xcc,
+ 0xc2, 0xc6, 0xca, 0xce,
+ 0x8f, 0x8b, 0x89, 0x8a,
+ 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
+ 1 },
+};
+
+/*
+ * DMA must be in the first 16MB. This gets called early by the
+ * initialisation routines of any devices which require DMA to ensure
+ * the allocated bounce buffers are below the 16MB limit.
+ */
+void
+dmainit(int chan)
+{
+ DMA *dp;
+ DMAxfer *xp;
+ ulong v;
+ static int once;
+
+ if(once == 0){
+// if(ioalloc(0x00, 0x10, 0, "dma") < 0
+// || ioalloc(0x80, 0x10, 0, "dma") < 0
+// || ioalloc(0xd0, 0x10, 0, "dma") < 0)
+// panic("dmainit");
+ outb(dma[0].mc, 0);
+ outb(dma[1].mc, 0);
+ outb(dma[0].cmask, 0);
+ outb(dma[1].cmask, 0);
+ outb(dma[1].mode, 0xC0);
+ once = 1;
+ }
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+ xp = &dp->x[chan];
+ if(xp->bva != nil)
+ return;
+
+ v = (ulong)xalloc(BY2PG+BY2PG);
+ if(v == 0 || PADDR(v) >= 16*MB){
+ print("dmainit: chan %d: 0x%luX out of range\n", chan, v);
+ xfree((void*)v);
+ v = 0;
+ }
+ xp->bva = (void*)ROUND(v, BY2PG);
+ xp->bpa = PADDR(xp->bva);
+ xp->len = 0;
+ xp->isread = 0;
+}
+
+/*
+ * setup a dma transfer. if the destination is not in kernel
+ * memory, allocate a page for the transfer.
+ *
+ * we assume BIOS has set up the command register before we
+ * are booted.
+ *
+ * return the updated transfer length (we can't transfer across 64k
+ * boundaries)
+ */
+long
+dmasetup(int chan, void *va, long len, int isread)
+{
+ DMA *dp;
+ ulong pa;
+ uchar mode;
+ DMAxfer *xp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+ xp = &dp->x[chan];
+
+ /*
+ * if this isn't kernel memory or crossing 64k boundary or above 16 meg
+ * use the allocated low memory page.
+ */
+ pa = PADDR(va);
+ if((((ulong)va)&0xF0000000) != KZERO
+ || (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)
+ || pa > 16*MB) {
+ if(xp->bva == nil)
+ return -1;
+ if(len > BY2PG)
+ len = BY2PG;
+ if(!isread)
+ memmove(xp->bva, va, len);
+ xp->va = va;
+ xp->len = len;
+ xp->isread = isread;
+ pa = xp->bpa;
+ }
+ else
+ xp->len = 0;
+
+ /*
+ * this setup must be atomic
+ */
+ ilock(dp);
+ mode = (isread ? 0x44 : 0x48) | chan;
+ outb(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */
+ outb(dp->page[chan], pa>>16);
+ outb(dp->cbp, 0); /* set count & address to their first byte */
+ outb(dp->addr[chan], pa>>dp->shift); /* set address */
+ outb(dp->addr[chan], pa>>(8+dp->shift));
+ outb(dp->count[chan], (len>>dp->shift)-1); /* set count */
+ outb(dp->count[chan], ((len>>dp->shift)-1)>>8);
+ outb(dp->sbm, chan); /* enable the channel */
+ iunlock(dp);
+
+ return len;
+}
+
+int
+dmadone(int chan)
+{
+ DMA *dp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+
+ return inb(dp->cmd) & (1<<chan);
+}
+
+/*
+ * this must be called after a dma has been completed.
+ *
+ * if a page has been allocated for the dma,
+ * copy the data into the actual destination
+ * and free the page.
+ */
+void
+dmaend(int chan)
+{
+ DMA *dp;
+ DMAxfer *xp;
+
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+
+ /*
+ * disable the channel
+ */
+ ilock(dp);
+ outb(dp->sbm, 4|chan);
+ iunlock(dp);
+
+ xp = &dp->x[chan];
+ if(xp->len == 0 || !xp->isread)
+ return;
+
+ /*
+ * copy out of temporary page
+ */
+ memmove(xp->va, xp->bva, xp->len);
+ xp->len = 0;
+}
+
+/*
+int
+dmacount(int chan)
+{
+ int retval;
+ DMA *dp;
+
+ dp = &dma[(chan>>2)&1];
+ outb(dp->cbp, 0);
+ retval = inb(dp->count[chan]);
+ retval |= inb(dp->count[chan]) << 8;
+ return((retval<<dp->shift)+1);
+}
+ */
--- /dev/null
+++ b/os/boot.original/pc/dosboot.c
@@ -1,0 +1,582 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "fs.h"
+
+struct Dosboot{
+ uchar magic[3];
+ uchar version[8];
+ uchar sectsize[2];
+ uchar clustsize;
+ uchar nresrv[2];
+ uchar nfats;
+ uchar rootsize[2];
+ uchar volsize[2];
+ uchar mediadesc;
+ uchar fatsize[2];
+ uchar trksize[2];
+ uchar nheads[2];
+ uchar nhidden[4];
+ uchar bigvolsize[4];
+/* fat 32 */
+ uchar bigfatsize[4];
+ uchar extflags[2];
+ uchar fsversion[2];
+ uchar rootdirstartclust[4];
+ uchar fsinfosect[2];
+ uchar backupbootsect[2];
+/* ???
+ uchar driveno;
+ uchar reserved0;
+ uchar bootsig;
+ uchar volid[4];
+ uchar label[11];
+ uchar reserved1[8];
+*/
+};
+
+struct Dosdir{
+ uchar name[8];
+ uchar ext[3];
+ uchar attr;
+ uchar lowercase;
+ uchar hundredth;
+ uchar ctime[2];
+ uchar cdate[2];
+ uchar adate[2];
+ uchar highstart[2];
+ uchar mtime[2];
+ uchar mdate[2];
+ uchar start[2];
+ uchar length[4];
+};
+
+#define DOSRONLY 0x01
+#define DOSHIDDEN 0x02
+#define DOSSYSTEM 0x04
+#define DOSVLABEL 0x08
+#define DOSDIR 0x10
+#define DOSARCH 0x20
+
+/*
+ * predeclared
+ */
+static void bootdump(Dosboot*);
+static void setname(Dosfile*, char*);
+
+/*
+ * debugging
+ */
+#define chatty 0
+#define chat if(chatty)print
+
+/*
+ * block io buffers
+ */
+enum
+{
+ Nbio= 16,
+};
+typedef struct Clustbuf Clustbuf;
+struct Clustbuf
+{
+ int age;
+ long sector;
+ uchar *iobuf;
+ Dos *dos;
+ int size;
+};
+Clustbuf bio[Nbio];
+
+/*
+ * get an io block from an io buffer
+ */
+Clustbuf*
+getclust(Dos *dos, long sector)
+{
+ Fs *fs;
+ Clustbuf *p, *oldest;
+ int size;
+
+ chat("getclust @ %ld\n", sector);
+
+ /*
+ * if we have it, just return it
+ */
+ for(p = bio; p < &bio[Nbio]; p++){
+ if(sector == p->sector && dos == p->dos){
+ p->age = m->ticks;
+ chat("getclust %ld in cache\n", sector);
+ return p;
+ }
+ }
+
+ /*
+ * otherwise, reuse the oldest entry
+ */
+ oldest = bio;
+ for(p = &bio[1]; p < &bio[Nbio]; p++){
+ if(p->age <= oldest->age)
+ oldest = p;
+ }
+ p = oldest;
+
+ /*
+ * make sure the buffer is big enough
+ */
+ size = dos->clustsize*dos->sectsize;
+ if(p->iobuf==0 || p->size < size)
+ p->iobuf = ialloc(size, 0);
+ p->size = size;
+
+ /*
+ * read in the cluster
+ */
+ fs = (Fs*)dos;
+ chat("getclust addr %lud %p %p %p\n", (ulong)((sector+dos->start)*(vlong)dos->sectsize),
+ fs, fs->diskseek, fs->diskread);
+ if(fs->diskseek(fs, (sector+dos->start)*(vlong)dos->sectsize) < 0){
+ chat("can't seek block\n");
+ return 0;
+ }
+ if(fs->diskread(fs, p->iobuf, size) != size){
+ chat("can't read block\n");
+ return 0;
+ }
+
+ p->age = m->ticks;
+ p->dos = dos;
+ p->sector = sector;
+ chat("getclust %ld read\n", sector);
+ return p;
+}
+
+/*
+ * walk the fat one level ( n is a current cluster number ).
+ * return the new cluster number or -1 if no more.
+ */
+static long
+fatwalk(Dos *dos, int n)
+{
+ ulong k, sect;
+ Clustbuf *p;
+ int o;
+
+ chat("fatwalk %d\n", n);
+
+ if(n < 2 || n >= dos->fatclusters)
+ return -1;
+
+ switch(dos->fatbits){
+ case 12:
+ k = (3*n)/2; break;
+ case 16:
+ k = 2*n; break;
+ case 32:
+ k = 4*n; break;
+ default:
+ return -1;
+ }
+ if(k >= dos->fatsize*dos->sectsize)
+ panic("getfat");
+
+ sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
+ o = k%(dos->sectsize*dos->clustsize);
+ p = getclust(dos, sect);
+ k = p->iobuf[o++];
+ if(o >= dos->sectsize*dos->clustsize){
+ p = getclust(dos, sect+dos->clustsize);
+ o = 0;
+ }
+ k |= p->iobuf[o++]<<8;
+ if(dos->fatbits == 12){
+ if(n&1)
+ k >>= 4;
+ else
+ k &= 0xfff;
+ if(k >= 0xff8)
+ k = -1;
+ }
+ else if (dos->fatbits == 32){
+ if(o >= dos->sectsize*dos->clustsize){
+ p = getclust(dos, sect+dos->clustsize);
+ o = 0;
+ }
+ k |= p->iobuf[o++]<<16;
+ k |= p->iobuf[o]<<24;
+ if (k >= 0xfffffff8)
+ k = -1;
+ }
+ else
+ k = k < 0xfff8 ? k : -1;
+ chat("fatwalk %d -> %lud\n", n, k);
+ return k;
+}
+
+/*
+ * map a file's logical cluster address to a physical sector address
+ */
+static long
+fileaddr(Dosfile *fp, long ltarget)
+{
+ Dos *dos = fp->dos;
+ long l;
+ long p;
+
+ chat("fileaddr %8.8s %ld\n", fp->name, ltarget);
+ /*
+ * root directory is contiguous and easy (unless FAT32)
+ */
+ if(fp->pstart == 0 && dos->rootsize != 0) {
+ if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
+ return -1;
+ l = dos->rootaddr + ltarget*dos->clustsize;
+ chat("fileaddr %ld -> %ld\n", ltarget, l);
+ return l;
+ }
+
+ /*
+ * anything else requires a walk through the fat
+ */
+ if(ltarget >= fp->lcurrent && fp->pcurrent){
+ /* start at the currrent point */
+ l = fp->lcurrent;
+ p = fp->pcurrent;
+ } else {
+ /* go back to the beginning */
+ l = 0;
+ p = fp->pstart;
+ }
+ while(l != ltarget){
+ /* walk the fat */
+ p = fatwalk(dos, p);
+ if(p < 0)
+ return -1;
+ l++;
+ }
+ fp->lcurrent = l;
+ fp->pcurrent = p;
+
+ /*
+ * clusters start at 2 instead of 0 (why? - presotto)
+ */
+ l = dos->dataaddr + (p-2)*dos->clustsize;
+ chat("fileaddr %ld -> %ld\n", ltarget, l);
+ return l;
+}
+
+/*
+ * read from a dos file
+ */
+long
+dosread(Dosfile *fp, void *a, long n)
+{
+ long addr;
+ long rv;
+ int i;
+ int off;
+ Clustbuf *p;
+ uchar *from, *to;
+
+ if((fp->attr & DOSDIR) == 0){
+ if(fp->offset >= fp->length)
+ return 0;
+ if(fp->offset+n > fp->length)
+ n = fp->length - fp->offset;
+ }
+
+ to = a;
+ for(rv = 0; rv < n; rv+=i){
+ /*
+ * read the cluster
+ */
+ addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
+ if(addr < 0)
+ return -1;
+ p = getclust(fp->dos, addr);
+ if(p == 0)
+ return -1;
+
+ /*
+ * copy the bytes we need
+ */
+ off = fp->offset % fp->dos->clustbytes;
+ from = &p->iobuf[off];
+ i = n - rv;
+ if(i > fp->dos->clustbytes - off)
+ i = fp->dos->clustbytes - off;
+ memmove(to, from, i);
+ to += i;
+ fp->offset += i;
+ }
+
+ return rv;
+}
+
+/*
+ * walk a directory returns
+ * -1 if something went wrong
+ * 0 if not found
+ * 1 if found
+ */
+int
+doswalk(File *f, char *name)
+{
+ Dosdir d;
+ long n;
+ Dosfile *file;
+
+ chat("doswalk %s\n", name);
+
+ file = &f->dos;
+
+ if((file->attr & DOSDIR) == 0){
+ chat("walking non-directory!\n");
+ return -1;
+ }
+
+ setname(file, name);
+
+ file->offset = 0; /* start at the beginning */
+ while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
+ chat("comparing to %8.8s.%3.3s\n", (char*)d.name, (char*)d.ext);
+ if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
+ continue;
+ if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
+ continue;
+ if(d.attr & DOSVLABEL){
+ chat("%8.8s.%3.3s is a LABEL\n", (char*)d.name, (char*)d.ext);
+ continue;
+ }
+ file->attr = d.attr;
+ file->pstart = GSHORT(d.start);
+ if (file->dos->fatbits == 32)
+ file->pstart |= GSHORT(d.highstart) << 16;
+ file->length = GLONG(d.length);
+ file->pcurrent = 0;
+ file->lcurrent = 0;
+ file->offset = 0;
+ return 1;
+ }
+ return n >= 0 ? 0 : -1;
+}
+
+/*
+ * instructions that boot blocks can start with
+ */
+#define JMPSHORT 0xeb
+#define JMPNEAR 0xe9
+
+/*
+ * read in a segment
+ */
+long
+dosreadseg(File *f, void *va, long len)
+{
+ char *a;
+ long n, sofar;
+ Dosfile *fp;
+
+ fp = &f->dos;
+ a = va;
+ for(sofar = 0; sofar < len; sofar += n){
+ n = 8*1024;
+ if(len - sofar < n)
+ n = len - sofar;
+ n = dosread(fp, a + sofar, n);
+ if(n <= 0)
+ break;
+ print(".");
+ }
+ return sofar;
+}
+
+int
+dosinit(Fs *fs)
+{
+ Clustbuf *p;
+ Dosboot *b;
+ int i;
+ Dos *dos;
+ Dosfile *root;
+
+chat("dosinit0 %p %p %p\n", fs, fs->diskseek, fs->diskread);
+
+ dos = &fs->dos;
+ /* defaults till we know better */
+ dos->sectsize = 512;
+ dos->clustsize = 1;
+
+ /* get first sector */
+ p = getclust(dos, 0);
+ if(p == 0){
+ chat("can't read boot block\n");
+ return -1;
+ }
+
+chat("dosinit0a\n");
+
+ p->dos = 0;
+ b = (Dosboot *)p->iobuf;
+ if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
+ chat("no dos file system %x %x %x %x\n",
+ b->magic[0], b->magic[1], b->magic[2], b->magic[3]);
+ return -1;
+ }
+
+ if(chatty)
+ bootdump(b);
+
+ if(b->clustsize == 0) {
+unreasonable:
+ if(chatty){
+ print("unreasonable FAT BPB: ");
+ for(i=0; i<3+8+2+1; i++)
+ print(" %.2ux", p->iobuf[i]);
+ print("\n");
+ }
+ return -1;
+ }
+
+chat("dosinit1\n");
+
+ /*
+ * Determine the systems' wondrous properties.
+ * There are heuristics here, but there's no real way
+ * of knowing if this is a reasonable FAT.
+ */
+ dos->fatbits = 0;
+ dos->sectsize = GSHORT(b->sectsize);
+ if(dos->sectsize & 0xFF)
+ goto unreasonable;
+ dos->clustsize = b->clustsize;
+ dos->clustbytes = dos->sectsize*dos->clustsize;
+ dos->nresrv = GSHORT(b->nresrv);
+ dos->nfats = b->nfats;
+ dos->fatsize = GSHORT(b->fatsize);
+ dos->rootsize = GSHORT(b->rootsize);
+ dos->volsize = GSHORT(b->volsize);
+ if(dos->volsize == 0)
+ dos->volsize = GLONG(b->bigvolsize);
+ dos->mediadesc = b->mediadesc;
+ if(dos->fatsize == 0) {
+ chat("fat32\n");
+ dos->rootsize = 0;
+ dos->fatsize = GLONG(b->bigfatsize);
+ dos->fatbits = 32;
+ }
+ dos->fataddr = dos->nresrv;
+ if (dos->rootsize == 0) {
+ dos->rootaddr = 0;
+ dos->rootclust = GLONG(b->rootdirstartclust);
+ dos->dataaddr = dos->fataddr + dos->nfats*dos->fatsize;
+ } else {
+ dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
+ i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
+ i = i/dos->sectsize;
+ dos->dataaddr = dos->rootaddr + i;
+ }
+ dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
+ if(dos->fatbits != 32) {
+ if(dos->fatclusters < 4087)
+ dos->fatbits = 12;
+ else
+ dos->fatbits = 16;
+ }
+ dos->freeptr = 2;
+
+ if(dos->clustbytes < 512 || dos->clustbytes > 64*1024)
+ goto unreasonable;
+
+chat("dosinit2\n");
+
+ /*
+ * set up the root
+ */
+
+ fs->root.fs = fs;
+ root = &fs->root.dos;
+ root->dos = dos;
+ root->pstart = dos->rootsize == 0 ? dos->rootclust : 0;
+ root->pcurrent = root->lcurrent = 0;
+ root->offset = 0;
+ root->attr = DOSDIR;
+ root->length = dos->rootsize*sizeof(Dosdir);
+
+chat("dosinit3\n");
+
+ fs->read = dosreadseg;
+ fs->walk = doswalk;
+ return 0;
+}
+
+static void
+bootdump(Dosboot *b)
+{
+ if(chatty == 0)
+ return;
+ print("magic: 0x%2.2x 0x%2.2x 0x%2.2x ",
+ b->magic[0], b->magic[1], b->magic[2]);
+ print("version: \"%8.8s\"\n", (char*)b->version);
+ print("sectsize: %d ", GSHORT(b->sectsize));
+ print("allocsize: %d ", b->clustsize);
+ print("nresrv: %d ", GSHORT(b->nresrv));
+ print("nfats: %d\n", b->nfats);
+ print("rootsize: %d ", GSHORT(b->rootsize));
+ print("volsize: %d ", GSHORT(b->volsize));
+ print("mediadesc: 0x%2.2x\n", b->mediadesc);
+ print("fatsize: %d ", GSHORT(b->fatsize));
+ print("trksize: %d ", GSHORT(b->trksize));
+ print("nheads: %d ", GSHORT(b->nheads));
+ print("nhidden: %d ", GLONG(b->nhidden));
+ print("bigvolsize: %d\n", GLONG(b->bigvolsize));
+/*
+ print("driveno: %d\n", b->driveno);
+ print("reserved0: 0x%2.2x\n", b->reserved0);
+ print("bootsig: 0x%2.2x\n", b->bootsig);
+ print("volid: 0x%8.8x\n", GLONG(b->volid));
+ print("label: \"%11.11s\"\n", b->label);
+*/
+}
+
+
+/*
+ * set up a dos file name
+ */
+static void
+setname(Dosfile *fp, char *from)
+{
+ char *to;
+
+ to = fp->name;
+ for(; *from && to-fp->name < 8; from++, to++){
+ if(*from == '.'){
+ from++;
+ break;
+ }
+ if(*from >= 'a' && *from <= 'z')
+ *to = *from + 'A' - 'a';
+ else
+ *to = *from;
+ }
+ while(to - fp->name < 8)
+ *to++ = ' ';
+
+ /* from might be 12345678.123: don't save the '.' in ext */
+ if(*from == '.')
+ from++;
+
+ to = fp->ext;
+ for(; *from && to-fp->ext < 3; from++, to++){
+ if(*from >= 'a' && *from <= 'z')
+ *to = *from + 'A' - 'a';
+ else
+ *to = *from;
+ }
+ while(to-fp->ext < 3)
+ *to++ = ' ';
+
+ chat("name is %8.8s.%3.3s\n", fp->name, fp->ext);
+}
--- /dev/null
+++ b/os/boot.original/pc/dosfs.h
@@ -1,0 +1,62 @@
+typedef struct Dosboot Dosboot;
+typedef struct Dos Dos;
+typedef struct Dosdir Dosdir;
+typedef struct Dosfile Dosfile;
+typedef struct Dospart Dospart;
+
+struct Dospart
+{
+ uchar flag; /* active flag */
+ uchar shead; /* starting head */
+ uchar scs[2]; /* starting cylinder/sector */
+ uchar type; /* partition type */
+ uchar ehead; /* ending head */
+ uchar ecs[2]; /* ending cylinder/sector */
+ uchar start[4]; /* starting sector */
+ uchar len[4]; /* length in sectors */
+};
+
+#define FAT12 0x01
+#define FAT16 0x04
+#define EXTEND 0x05
+#define FATHUGE 0x06
+#define FAT32 0x0b
+#define FAT32X 0x0c
+#define EXTHUGE 0x0f
+#define DMDDO 0x54
+#define PLAN9 0x39
+#define LEXTEND 0x85
+
+struct Dosfile{
+ Dos *dos; /* owning dos file system */
+ char name[8];
+ char ext[3];
+ uchar attr;
+ long length;
+ long pstart; /* physical start cluster address */
+ long pcurrent; /* physical current cluster address */
+ long lcurrent; /* logical current cluster address */
+ long offset;
+};
+
+struct Dos{
+ long start; /* start of file system */
+ int sectsize; /* in bytes */
+ int clustsize; /* in sectors */
+ int clustbytes; /* in bytes */
+ int nresrv; /* sectors */
+ int nfats; /* usually 2 */
+ int rootsize; /* number of entries */
+ int volsize; /* in sectors */
+ int mediadesc;
+ int fatsize; /* in sectors */
+ int fatclusters;
+ int fatbits; /* 12 or 16 */
+ long fataddr; /* sector number */
+ long rootaddr;
+ long rootclust;
+ long dataaddr;
+ long freeptr;
+};
+
+extern int dosinit(Fs*);
--- /dev/null
+++ b/os/boot.original/pc/eipfmt.c
@@ -1,0 +1,145 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "ip.h"
+
+
+enum
+{
+ IPaddrlen= 16,
+ IPv4addrlen= 4,
+ IPv4off= 12,
+ IPllen= 4,
+};
+extern int fmtstrcpy(Fmt*, char*);
+
+
+/*
+ * prefix of all v4 addresses
+ */
+uchar v4prefix[IPaddrlen] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0xff, 0xff,
+ 0, 0, 0, 0
+};
+
+enum
+{
+ Isprefix= 16,
+};
+
+uchar prefixvals[256] =
+{
+[0x00] 0 | Isprefix,
+[0x80] 1 | Isprefix,
+[0xC0] 2 | Isprefix,
+[0xE0] 3 | Isprefix,
+[0xF0] 4 | Isprefix,
+[0xF8] 5 | Isprefix,
+[0xFC] 6 | Isprefix,
+[0xFE] 7 | Isprefix,
+[0xFF] 8 | Isprefix,
+};
+
+void
+hnputl(void *p, uint v)
+{
+ uchar *a;
+
+ a = p;
+ a[0] = v>>24;
+ a[1] = v>>16;
+ a[2] = v>>8;
+ a[3] = v;
+}
+
+int
+eipfmt(Fmt *f)
+{
+ char buf[5*8];
+ static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
+ static char *ifmt = "%d.%d.%d.%d";
+ uchar *p, ip[16];
+ ulong *lp;
+ ushort s;
+ int i, j, n, eln, eli;
+
+ switch(f->r) {
+ case 'E': /* Ethernet address */
+ p = va_arg(f->args, uchar*);
+ snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
+ return fmtstrcpy(f, buf);
+
+ case 'I': /* Ip address */
+ p = va_arg(f->args, uchar*);
+common:
+ if(memcmp(p, v4prefix, 12) == 0){
+ snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]);
+ return fmtstrcpy(f, buf);
+ }
+
+ /* find longest elision */
+ eln = eli = -1;
+ for(i = 0; i < 16; i += 2){
+ for(j = i; j < 16; j += 2)
+ if(p[j] != 0 || p[j+1] != 0)
+ break;
+ if(j > i && j - i > eln){
+ eli = i;
+ eln = j - i;
+ }
+ }
+
+ /* print with possible elision */
+ n = 0;
+ for(i = 0; i < 16; i += 2){
+ if(i == eli){
+ n += sprint(buf+n, "::");
+ i += eln;
+ if(i >= 16)
+ break;
+ } else if(i != 0)
+ n += sprint(buf+n, ":");
+ s = (p[i]<<8) + p[i+1];
+ n += sprint(buf+n, "%ux", s);
+ }
+ return fmtstrcpy(f, buf);
+
+ case 'i': /* v6 address as 4 longs */
+ lp = va_arg(f->args, ulong*);
+ for(i = 0; i < 4; i++)
+ hnputl(ip+4*i, *lp++);
+ p = ip;
+ goto common;
+
+ case 'V': /* v4 ip address */
+ p = va_arg(f->args, uchar*);
+ snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]);
+ return fmtstrcpy(f, buf);
+
+ case 'M': /* ip mask */
+ p = va_arg(f->args, uchar*);
+
+ /* look for a prefix mask */
+ for(i = 0; i < 16; i++)
+ if(p[i] != 0xff)
+ break;
+ if(i < 16){
+ if((prefixvals[p[i]] & Isprefix) == 0)
+ goto common;
+ for(j = i+1; j < 16; j++)
+ if(p[j] != 0)
+ goto common;
+ n = 8*i + (prefixvals[p[i]] & ~Isprefix);
+ } else
+ n = 8*16;
+
+ /* got one, use /xx format */
+ snprint(buf, sizeof buf, "/%d", n);
+ return fmtstrcpy(f, buf);
+ }
+ return fmtstrcpy(f, "(eipfmt)");
+}
--- /dev/null
+++ b/os/boot.original/pc/error.h
@@ -1,0 +1,58 @@
+extern char Enoerror[]; /* no error */
+extern char Emount[]; /* inconsistent mount */
+extern char Eunmount[]; /* not mounted */
+extern char Eunion[]; /* not in union */
+extern char Emountrpc[]; /* mount rpc error */
+extern char Eshutdown[]; /* mounted device shut down */
+extern char Enocreate[]; /* mounted directory forbids creation */
+extern char Enonexist[]; /* file does not exist */
+extern char Eexist[]; /* file already exists */
+extern char Ebadsharp[]; /* unknown device in # filename */
+extern char Enotdir[]; /* not a directory */
+extern char Eisdir[]; /* file is a directory */
+extern char Ebadchar[]; /* bad character in file name */
+extern char Efilename[]; /* file name syntax */
+extern char Eperm[]; /* permission denied */
+extern char Ebadusefd[]; /* inappropriate use of fd */
+extern char Ebadarg[]; /* bad arg in system call */
+extern char Einuse[]; /* device or object already in use */
+extern char Eio[]; /* i/o error */
+extern char Etoobig[]; /* read or write too large */
+extern char Etoosmall[]; /* read or write too small */
+extern char Enetaddr[]; /* bad network address */
+extern char Emsgsize[]; /* message is too big for protocol */
+extern char Enetbusy[]; /* network device is busy or allocated */
+extern char Enoproto[]; /* network protocol not supported */
+extern char Enoport[]; /* network port not available */
+extern char Enoifc[]; /* bad interface or no free interface slots */
+extern char Enolisten[]; /* not announced */
+extern char Ehungup[]; /* write to hungup channel */
+extern char Ebadctl[]; /* bad process or channel control request */
+extern char Enodev[]; /* no free devices */
+extern char Enoenv[]; /* no free environment resources */
+extern char Emuxshutdown[]; /* mux server shut down */
+extern char Emuxbusy[]; /* all mux channels busy */
+extern char Emuxmsg[]; /* bad mux message format or mismatch */
+extern char Eprocdied[]; /* process exited */
+extern char Enochild[]; /* no living children */
+extern char Eioload[]; /* i/o error in demand load */
+extern char Enovmem[]; /* virtual memory allocation failed */
+extern char Ebadld[]; /* illegal line discipline */
+extern char Ebadfd[]; /* fd out of range or not open */
+extern char Eisstream[]; /* seek on a stream */
+extern char Ebadexec[]; /* exec header invalid */
+extern char Etimedout[]; /* connection timed out */
+extern char Econrefused[]; /* connection refused */
+extern char Enetunreach[]; /* network unreachable */
+extern char Eintr[]; /* interrupted */
+extern char Eneedservice[]; /* service required for tcp/udp/il calls */
+extern char Enomem[]; /* kernel allocate failed */
+extern char Enoswap[]; /* swap space full */
+extern char Esfnotcached[]; /* subfont not cached */
+extern char Esoverlap[]; /* segments overlap */
+extern char Emouseset[]; /* mouse type already set */
+extern char Erecover[]; /* failed to recover fd */
+extern char Eshort[]; /* i/o count too small */
+extern char Egreg[]; /* ken scheduled it */
+extern char Ebadspec[]; /* bad attach specifier */
+extern char Enoreg[]; /* process has no saved registers */
--- /dev/null
+++ b/os/boot.original/pc/ether.c
@@ -1,0 +1,291 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ip.h"
+
+#include "etherif.h"
+
+static Ether ether[MaxEther];
+
+extern int ether2114xreset(Ether*);
+extern int elnk3reset(Ether*);
+extern int i82557reset(Ether*);
+extern int igbepnp(Ether *);
+extern int i82563pnp(Ether *);
+extern int elnk3reset(Ether*);
+extern int ether589reset(Ether*);
+extern int ne2000reset(Ether*);
+extern int wd8003reset(Ether*);
+extern int ec2treset(Ether*);
+extern int amd79c970reset(Ether*);
+extern int rtl8139pnp(Ether*);
+extern int rtl8169pnp(Ether*);
+extern int ether83815reset(Ether*);
+extern int rhinepnp(Ether*);
+extern int ga620pnp(Ether*);
+extern int dp83820pnp(Ether*);
+
+struct {
+ char *type;
+ int (*reset)(Ether*);
+ int noprobe;
+} ethercards[] = {
+ { "21140", ether2114xreset, 0, },
+ { "2114x", ether2114xreset, 0, },
+ { "i82557", i82557reset, 0, },
+ { "igbe", igbepnp, 0, },
+ { "i82563",i82563pnp, 0, },
+ { "igbepcie",i82563pnp, 0, },
+ { "elnk3", elnk3reset, 0, },
+ { "3C509", elnk3reset, 0, },
+ { "3C575", elnk3reset, 0, },
+ { "3C589", ether589reset, 1, },
+ { "3C562", ether589reset, 1, },
+ { "589E", ether589reset, 1, },
+ { "NE2000", ne2000reset, 0, },
+ { "WD8003", wd8003reset, 1, },
+ { "EC2T", ec2treset, 0, },
+ { "AMD79C970", amd79c970reset, 0, },
+ { "RTL8139", rtl8139pnp, 0, },
+ { "RTL8169", rtl8169pnp, 0, },
+ { "83815", ether83815reset, 0, },
+ { "rhine", rhinepnp, 0, },
+ { "vt6102", rhinepnp, 0, },
+ { "GA620", ga620pnp, 0, },
+ { "83820", dp83820pnp, 0, },
+ { "dp83820", dp83820pnp, 0, },
+
+ { 0, }
+};
+
+static void xetherdetach(void);
+
+int
+etherinit(void)
+{
+ Ether *ctlr;
+ int ctlrno, i, mask, n, x;
+
+ fmtinstall('E', eipfmt);
+
+ etherdetach = xetherdetach;
+ mask = 0;
+ for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+ ctlr = ðer[ctlrno];
+ memset(ctlr, 0, sizeof(Ether));
+ if(iniread && isaconfig("ether", ctlrno, ctlr) == 0)
+ continue;
+
+ for(n = 0; ethercards[n].type; n++){
+ if(!iniread){
+ if(ethercards[n].noprobe)
+ continue;
+ memset(ctlr, 0, sizeof(Ether));
+ strcpy(ctlr->type, ethercards[n].type);
+ }
+ else if(cistrcmp(ethercards[n].type, ctlr->type))
+ continue;
+ ctlr->ctlrno = ctlrno;
+
+ x = splhi();
+ if((*ethercards[n].reset)(ctlr)){
+ splx(x);
+ if(iniread)
+ break;
+ else
+ continue;
+ }
+
+ ctlr->state = 1; /* card found */
+ mask |= 1<<ctlrno;
+ if(ctlr->irq == 2)
+ ctlr->irq = 9;
+ setvec(VectorPIC + ctlr->irq, ctlr->interrupt, ctlr);
+
+ print("ether#%d: %s: port 0x%luX irq %lud",
+ ctlr->ctlrno, ctlr->type, ctlr->port, ctlr->irq);
+ if(ctlr->mem)
+ print(" addr 0x%luX", ctlr->mem & ~KZERO);
+ if(ctlr->size)
+ print(" size 0x%luX", ctlr->size);
+ print(": %E\n", ctlr->ea);
+
+ if(ctlr->nrb == 0)
+ ctlr->nrb = Nrb;
+ ctlr->rb = ialloc(sizeof(RingBuf)*ctlr->nrb, 0);
+ if(ctlr->ntb == 0)
+ ctlr->ntb = Ntb;
+ ctlr->tb = ialloc(sizeof(RingBuf)*ctlr->ntb, 0);
+
+ ctlr->rh = 0;
+ ctlr->ri = 0;
+ for(i = 0; i < ctlr->nrb; i++)
+ ctlr->rb[i].owner = Interface;
+
+ ctlr->th = 0;
+ ctlr->ti = 0;
+ for(i = 0; i < ctlr->ntb; i++)
+ ctlr->tb[i].owner = Host;
+
+ splx(x);
+ break;
+ }
+ }
+
+ return mask;
+}
+
+void
+etherinitdev(int i, char *s)
+{
+ sprint(s, "ether%d", i);
+}
+
+void
+etherprintdevs(int i)
+{
+ print(" ether%d", i);
+}
+
+static Ether*
+attach(int ctlrno)
+{
+ Ether *ctlr;
+
+ if(ctlrno >= MaxEther || ether[ctlrno].state == 0)
+ return 0;
+
+ ctlr = ðer[ctlrno];
+ if(ctlr->state == 1){ /* card found? */
+ ctlr->state = 2; /* attaching */
+ (*ctlr->attach)(ctlr);
+ }
+
+ return ctlr;
+}
+
+static void
+xetherdetach(void)
+{
+ Ether *ctlr;
+ int ctlrno, x;
+
+ x = splhi();
+ for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+ ctlr = ðer[ctlrno];
+ if(ctlr->detach && ctlr->state != 0) /* found | attaching? */
+ ctlr->detach(ctlr);
+ }
+ splx(x);
+}
+
+uchar*
+etheraddr(int ctlrno)
+{
+ Ether *ctlr;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ return ctlr->ea;
+}
+
+static int
+wait(RingBuf* ring, uchar owner, int timo)
+{
+ ulong start;
+
+ start = m->ticks;
+ while(TK2MS(m->ticks - start) < timo){
+ if(ring->owner != owner)
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+etherrxpkt(int ctlrno, Etherpkt* pkt, int timo)
+{
+ int n;
+ Ether *ctlr;
+ RingBuf *ring;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ ring = &ctlr->rb[ctlr->rh];
+ if(wait(ring, Interface, timo) == 0){
+ if(debug)
+ print("ether%d: rx timeout\n", ctlrno);
+ return 0;
+ }
+
+ n = ring->len;
+ memmove(pkt, ring->pkt, n);
+ ring->owner = Interface;
+ ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
+
+ return n;
+}
+
+int
+etherrxflush(int ctlrno)
+{
+ int n;
+ Ether *ctlr;
+ RingBuf *ring;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ n = 0;
+ for(;;){
+ ring = &ctlr->rb[ctlr->rh];
+ if(wait(ring, Interface, 100) == 0)
+ break;
+
+ ring->owner = Interface;
+ ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
+ n++;
+ }
+
+ return n;
+}
+
+int
+ethertxpkt(int ctlrno, Etherpkt* pkt, int len, int)
+{
+ Ether *ctlr;
+ RingBuf *ring;
+ int s;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ ring = &ctlr->tb[ctlr->th];
+ if(wait(ring, Interface, 1000) == 0){
+ print("ether%d: tx buffer timeout\n", ctlrno);
+ return 0;
+ }
+
+ memmove(pkt->s, ctlr->ea, Eaddrlen);
+ if(debug)
+ print("%E to %E...\n", pkt->s, pkt->d);
+ memmove(ring->pkt, pkt, len);
+ if(len < ETHERMINTU){
+ memset(ring->pkt+len, 0, ETHERMINTU-len);
+ len = ETHERMINTU;
+ }
+ ring->len = len;
+ ring->owner = Interface;
+ ctlr->th = NEXT(ctlr->th, ctlr->ntb);
+ s = splhi();
+ (*ctlr->transmit)(ctlr);
+ splx(s);
+
+ return 1;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether2000.c
@@ -1,0 +1,110 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ether8390.h"
+
+/*
+ * Driver written for the 'Notebook Computer Ethernet LAN Adapter',
+ * a plug-in to the bus-slot on the rear of the Gateway NOMAD 425DXL
+ * laptop. The manual says NE2000 compatible.
+ * The interface appears to be pretty well described in the National
+ * Semiconductor Local Area Network Databook (1992) as one of the
+ * AT evaluation cards.
+ *
+ * The NE2000 is really just a DP8390[12] plus a data port
+ * and a reset port.
+ */
+enum {
+ Data = 0x10, /* offset from I/O base of data port */
+ Reset = 0x1F, /* offset from I/O base of reset port */
+};
+
+int
+ne2000reset(Ether* ether)
+{
+ ushort buf[16];
+ ulong port;
+ Dp8390 *ctlr;
+ int i;
+ uchar ea[Eaddrlen];
+
+ /*
+ * Set up the software configuration.
+ * Use defaults for port, irq, mem and size
+ * if not specified.
+ */
+ if(ether->port == 0)
+ ether->port = 0x300;
+ if(ether->irq == 0)
+ ether->irq = 2;
+ if(ether->mem == 0)
+ ether->mem = 0x4000;
+ if(ether->size == 0)
+ ether->size = 16*1024;
+ port = ether->port;
+
+ ether->ctlr = malloc(sizeof(Dp8390));
+ ctlr = ether->ctlr;
+ ctlr->width = 2;
+ ctlr->ram = 0;
+
+ ctlr->port = port;
+ ctlr->data = port+Data;
+
+ ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz);
+ ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
+ ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz);
+
+ ctlr->dummyrr = 1;
+ for(i = 0; i < ether->nopt; i++){
+ if(strcmp(ether->opt[i], "nodummyrr"))
+ continue;
+ ctlr->dummyrr = 0;
+ break;
+ }
+
+ /*
+ * Reset the board. This is done by doing a read
+ * followed by a write to the Reset address.
+ */
+ buf[0] = inb(port+Reset);
+ delay(2);
+ outb(port+Reset, buf[0]);
+ delay(2);
+
+ /*
+ * Init the (possible) chip, then use the (possible)
+ * chip to read the (possible) PROM for ethernet address
+ * and a marker byte.
+ * Could just look at the DP8390 command register after
+ * initialisation has been tried, but that wouldn't be
+ * enough, there are other ethernet boards which could
+ * match.
+ */
+ dp8390reset(ether);
+ memset(buf, 0, sizeof(buf));
+ dp8390read(ctlr, buf, 0, sizeof(buf));
+ if((buf[0x0E] & 0xFF) != 0x57 || (buf[0x0F] & 0xFF) != 0x57){
+ free(ether->ctlr);
+ return -1;
+ }
+
+ /*
+ * Stupid machine. Shorts were asked for,
+ * shorts were delivered, although the PROM is a byte array.
+ * Set the ethernet address.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+ for(i = 0; i < sizeof(ether->ea); i++)
+ ether->ea[i] = buf[i];
+ }
+ dp8390setea(ether);
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether2114x.c
@@ -1,0 +1,1652 @@
+/*
+ * Digital Semiconductor DECchip 21140 PCI Fast Ethernet LAN Controller
+ * as found on the Digital Fast EtherWORKS PCI 10/100 adapter (DE-500-X).
+ * To do:
+ * thresholds;
+ * ring sizing;
+ * handle more error conditions;
+ * all the rest of it...
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+#define DEBUG (0)
+#define debug if(DEBUG)print
+
+enum {
+ Nrde = 32,
+ Ntde = 4,
+};
+
+#define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4)
+
+enum { /* CRS0 - Bus Mode */
+ Swr = 0x00000001, /* Software Reset */
+ Bar = 0x00000002, /* Bus Arbitration */
+ Dsl = 0x0000007C, /* Descriptor Skip Length (field) */
+ Ble = 0x00000080, /* Big/Little Endian */
+ Pbl = 0x00003F00, /* Programmable Burst Length (field) */
+ Cal = 0x0000C000, /* Cache Alignment (field) */
+ Cal8 = 0x00004000, /* 8 longword boundary alignment */
+ Cal16 = 0x00008000, /* 16 longword boundary alignment */
+ Cal32 = 0x0000C000, /* 32 longword boundary alignment */
+ Tap = 0x000E0000, /* Transmit Automatic Polling (field) */
+ Dbo = 0x00100000, /* Descriptor Byte Ordering Mode */
+ Rml = 0x00200000, /* Read Multiple */
+};
+
+enum { /* CSR[57] - Status and Interrupt Enable */
+ Ti = 0x00000001, /* Transmit Interrupt */
+ Tps = 0x00000002, /* Transmit Process Stopped */
+ Tu = 0x00000004, /* Transmit buffer Unavailable */
+ Tjt = 0x00000008, /* Transmit Jabber Timeout */
+ Unf = 0x00000020, /* transmit UNderFlow */
+ Ri = 0x00000040, /* Receive Interrupt */
+ Ru = 0x00000080, /* Receive buffer Unavailable */
+ Rps = 0x00000100, /* Receive Process Stopped */
+ Rwt = 0x00000200, /* Receive Watchdog Timeout */
+ Eti = 0x00000400, /* Early Transmit Interrupt */
+ Gte = 0x00000800, /* General purpose Timer Expired */
+ Fbe = 0x00002000, /* Fatal Bit Error */
+ Ais = 0x00008000, /* Abnormal Interrupt Summary */
+ Nis = 0x00010000, /* Normal Interrupt Summary */
+ Rs = 0x000E0000, /* Receive process State (field) */
+ Ts = 0x00700000, /* Transmit process State (field) */
+ Eb = 0x03800000, /* Error bits */
+};
+
+enum { /* CSR6 - Operating Mode */
+ Hp = 0x00000001, /* Hash/Perfect receive filtering mode */
+ Sr = 0x00000002, /* Start/stop Receive */
+ Ho = 0x00000004, /* Hash-Only filtering mode */
+ Pb = 0x00000008, /* Pass Bad frames */
+ If = 0x00000010, /* Inverse Filtering */
+ Sb = 0x00000020, /* Start/stop Backoff counter */
+ Pr = 0x00000040, /* Promiscuous Mode */
+ Pm = 0x00000080, /* Pass all Multicast */
+ Fd = 0x00000200, /* Full Duplex mode */
+ Om = 0x00000C00, /* Operating Mode (field) */
+ Fc = 0x00001000, /* Force Collision */
+ St = 0x00002000, /* Start/stop Transmission Command */
+ Tr = 0x0000C000, /* ThReshold control bits (field) */
+ Tr128 = 0x00000000,
+ Tr256 = 0x00004000,
+ Tr512 = 0x00008000,
+ Tr1024 = 0x0000C000,
+ Ca = 0x00020000, /* CApture effect enable */
+ Ps = 0x00040000, /* Port Select */
+ Hbd = 0x00080000, /* HeartBeat Disable */
+ Imm = 0x00100000, /* IMMediate mode */
+ Sf = 0x00200000, /* Store and Forward */
+ Ttm = 0x00400000, /* Transmit Threshold Mode */
+ Pcs = 0x00800000, /* PCS function */
+ Scr = 0x01000000, /* SCRambler mode */
+ Mbo = 0x02000000, /* Must Be One */
+ Ra = 0x40000000, /* Receive All */
+ Sc = 0x80000000, /* Special Capture effect enable */
+
+ TrMODE = Tr512, /* default transmission threshold */
+};
+
+enum { /* CSR9 - ROM and MII Management */
+ Scs = 0x00000001, /* serial ROM chip select */
+ Sclk = 0x00000002, /* serial ROM clock */
+ Sdi = 0x00000004, /* serial ROM data in */
+ Sdo = 0x00000008, /* serial ROM data out */
+ Ss = 0x00000800, /* serial ROM select */
+ Wr = 0x00002000, /* write */
+ Rd = 0x00004000, /* read */
+
+ Mdc = 0x00010000, /* MII management clock */
+ Mdo = 0x00020000, /* MII management write data */
+ Mii = 0x00040000, /* MII management operation mode (W) */
+ Mdi = 0x00080000, /* MII management data in */
+};
+
+enum { /* CSR12 - General-Purpose Port */
+ Gpc = 0x00000100, /* General Purpose Control */
+};
+
+typedef struct Des {
+ int status;
+ int control;
+ ulong addr;
+ void* bp;
+} Des;
+
+enum { /* status */
+ Of = 0x00000001, /* Rx: OverFlow */
+ Ce = 0x00000002, /* Rx: CRC Error */
+ Db = 0x00000004, /* Rx: Dribbling Bit */
+ Re = 0x00000008, /* Rx: Report on MII Error */
+ Rw = 0x00000010, /* Rx: Receive Watchdog */
+ Ft = 0x00000020, /* Rx: Frame Type */
+ Cs = 0x00000040, /* Rx: Collision Seen */
+ Tl = 0x00000080, /* Rx: Frame too Long */
+ Ls = 0x00000100, /* Rx: Last deScriptor */
+ Fs = 0x00000200, /* Rx: First deScriptor */
+ Mf = 0x00000400, /* Rx: Multicast Frame */
+ Rf = 0x00000800, /* Rx: Runt Frame */
+ Dt = 0x00003000, /* Rx: Data Type (field) */
+ De = 0x00004000, /* Rx: Descriptor Error */
+ Fl = 0x3FFF0000, /* Rx: Frame Length (field) */
+ Ff = 0x40000000, /* Rx: Filtering Fail */
+
+ Def = 0x00000001, /* Tx: DEFerred */
+ Uf = 0x00000002, /* Tx: UnderFlow error */
+ Lf = 0x00000004, /* Tx: Link Fail report */
+ Cc = 0x00000078, /* Tx: Collision Count (field) */
+ Hf = 0x00000080, /* Tx: Heartbeat Fail */
+ Ec = 0x00000100, /* Tx: Excessive Collisions */
+ Lc = 0x00000200, /* Tx: Late Collision */
+ Nc = 0x00000400, /* Tx: No Carrier */
+ Lo = 0x00000800, /* Tx: LOss of carrier */
+ To = 0x00004000, /* Tx: Transmission jabber timeOut */
+
+ Es = 0x00008000, /* [RT]x: Error Summary */
+ Own = 0x80000000, /* [RT]x: OWN bit */
+};
+
+enum { /* control */
+ Bs1 = 0x000007FF, /* [RT]x: Buffer 1 Size */
+ Bs2 = 0x003FF800, /* [RT]x: Buffer 2 Size */
+
+ Ch = 0x01000000, /* [RT]x: second address CHained */
+ Er = 0x02000000, /* [RT]x: End of Ring */
+
+ Ft0 = 0x00400000, /* Tx: Filtering Type 0 */
+ Dpd = 0x00800000, /* Tx: Disabled PaDding */
+ Ac = 0x04000000, /* Tx: Add CRC disable */
+ Set = 0x08000000, /* Tx: SETup packet */
+ Ft1 = 0x10000000, /* Tx: Filtering Type 1 */
+ Fseg = 0x20000000, /* Tx: First SEGment */
+ Lseg = 0x40000000, /* Tx: Last SEGment */
+ Ic = 0x80000000, /* Tx: Interrupt on Completion */
+};
+
+enum { /* PHY registers */
+ Bmcr = 0, /* Basic Mode Control */
+ Bmsr = 1, /* Basic Mode Status */
+ Phyidr1 = 2, /* PHY Identifier #1 */
+ Phyidr2 = 3, /* PHY Identifier #2 */
+ Anar = 4, /* Auto-Negotiation Advertisment */
+ Anlpar = 5, /* Auto-Negotiation Link Partner Ability */
+ Aner = 6, /* Auto-Negotiation Expansion */
+};
+
+enum { /* Variants */
+ Tulip0 = (0x0009<<16)|0x1011,
+ Tulip1 = (0x0014<<16)|0x1011,
+ Tulip3 = (0x0019<<16)|0x1011,
+ Pnic = (0x0002<<16)|0x11AD,
+ Pnic2 = (0xC115<<16)|0x11AD,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id; /* (pcidev->did<<16)|pcidev->vid */
+
+ uchar *srom;
+ int sromsz;
+ uchar* sromea; /* MAC address */
+ uchar* leaf;
+ int sct; /* selected connection type */
+ int k; /* info block count */
+ uchar* infoblock[16];
+ int sctk; /* sct block index */
+ int curk; /* current block index */
+ uchar* type5block;
+
+ int phy[32]; /* logical to physical map */
+ int phyreset; /* reset bitmap */
+ int curphyad;
+ int fdx;
+ int ttm;
+
+ uchar fd; /* option */
+ int medium; /* option */
+
+ int csr6; /* CSR6 - operating mode */
+ int mask; /* CSR[57] - interrupt mask */
+ int mbps;
+
+ Des* rdr; /* receive descriptor ring */
+ int nrdr; /* size of rdr */
+ int rdrx; /* index into rdr */
+
+ Des* tdr; /* transmit descriptor ring */
+ int ntdr; /* size of tdr */
+ int tdrh; /* host index into tdr */
+ int tdri; /* interface index into tdr */
+ int ntq; /* descriptors active */
+ Block* setupbp;
+
+ ulong of; /* receive statistics */
+ ulong ce;
+ ulong cs;
+ ulong tl;
+ ulong rf;
+ ulong de;
+
+ ulong uf; /* transmit statistics */
+ ulong ec;
+ ulong lc;
+ ulong nc;
+ ulong lo;
+ ulong to;
+
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr32r(c, r) (inl((c)->port+((r)*8)))
+#define csr32w(c, r, l) (outl((c)->port+((r)*8), (ulong)(l)))
+
+static void
+attach(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ if(!(ctlr->csr6 & Sr)){
+ ctlr->csr6 |= Sr;
+ csr32w(ctlr, 6, ctlr->csr6);
+ }
+}
+
+static void
+transmit(Ether* ether)
+{
+ Ctlr *ctlr;
+ Block *bp;
+ Des *des;
+ int control;
+ RingBuf *tb;
+
+ ctlr = ether->ctlr;
+ while(ctlr->ntq < (ctlr->ntdr-1)){
+ if(ctlr->setupbp){
+ bp = ctlr->setupbp;
+ ctlr->setupbp = 0;
+ control = Ic|Set|BLEN(bp);
+ }
+ else{
+ if(ether->ntb == 0)
+ break;
+ tb = ðer->tb[ether->ti];
+ if(tb->owner != Interface)
+ break;
+ bp = allocb(tb->len);
+ memmove(bp->wp, tb->pkt, tb->len);
+ memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+ bp->wp += tb->len;
+
+ tb->owner = Host;
+ ether->ti = NEXT(ether->ti, ether->ntb);
+
+ control = Ic|Lseg|Fseg|BLEN(bp);
+ }
+
+ ctlr->tdr[PREV(ctlr->tdrh, ctlr->ntdr)].control &= ~Ic;
+ des = &ctlr->tdr[ctlr->tdrh];
+ des->bp = bp;
+ des->addr = PADDR(bp->rp);
+ des->control |= control;
+ ctlr->ntq++;
+ //coherence();
+ des->status = Own;
+ csr32w(ctlr, 1, 0);
+ ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
+ }
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *ether;
+ int len, status;
+ Des *des;
+ RingBuf *ring;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ while((status = csr32r(ctlr, 5)) & (Nis|Ais)){
+ /*
+ * Acknowledge the interrupts and mask-out
+ * the ones that are implicitly handled.
+ */
+ csr32w(ctlr, 5, status);
+ status &= (ctlr->mask & ~(Nis|Ais|Ti));
+
+ /*
+ * Received packets.
+ */
+ if(status & Ri){
+ des = &ctlr->rdr[ctlr->rdrx];
+ while((des->status & Own) == 0){
+ len = ((des->status & Fl)>>16)-4;
+ if(des->status & Es){
+ if(des->status & Of)
+ ctlr->of++;
+ if(des->status & Ce)
+ ctlr->ce++;
+ if(des->status & Cs)
+ ctlr->cs++;
+ if(des->status & Tl)
+ ctlr->tl++;
+ if(des->status & Rf)
+ ctlr->rf++;
+ if(des->status & De)
+ ctlr->de++;
+ }
+ else{
+ ring = ðer->rb[ether->ri];
+ if(ring->owner == Interface){
+ ring->owner = Host;
+ ring->len = len;
+ memmove(ring->pkt, des->bp, len);
+ ether->ri = NEXT(ether->ri, ether->nrb);
+ }
+ }
+
+ des->control &= Er;
+ des->control |= Rbsz;
+ des->status = Own;
+
+ ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
+ des = &ctlr->rdr[ctlr->rdrx];
+ }
+ status &= ~Ri;
+ }
+
+ /*
+ * Check the transmit side:
+ * check for Transmit Underflow and Adjust
+ * the threshold upwards;
+ * free any transmitted buffers and try to
+ * top-up the ring.
+ */
+ if(status & Unf){
+ csr32w(ctlr, 6, ctlr->csr6 & ~St);
+ switch(ctlr->csr6 & Tr){
+ case Tr128:
+ len = Tr256;
+ break;
+ case Tr256:
+ len = Tr512;
+ break;
+ case Tr512:
+ len = Tr1024;
+ break;
+ default:
+ case Tr1024:
+ len = Sf;
+ break;
+ }
+ ctlr->csr6 = (ctlr->csr6 & ~Tr)|len;
+ csr32w(ctlr, 6, ctlr->csr6);
+ csr32w(ctlr, 5, Tps);
+ status &= ~(Unf|Tps);
+ }
+
+ while(ctlr->ntq){
+ des = &ctlr->tdr[ctlr->tdri];
+ if(des->status & Own)
+ break;
+
+ if(des->status & Es){
+ if(des->status & Uf)
+ ctlr->uf++;
+ if(des->status & Ec)
+ ctlr->ec++;
+ if(des->status & Lc)
+ ctlr->lc++;
+ if(des->status & Nc)
+ ctlr->nc++;
+ if(des->status & Lo)
+ ctlr->lo++;
+ if(des->status & To)
+ ctlr->to++;
+ }
+
+ freeb(des->bp);
+ des->control &= Er;
+
+ ctlr->ntq--;
+ ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
+ }
+ transmit(ether);
+
+ /*
+ * Anything left not catered for?
+ */
+ if(status)
+ panic("#l%d: status %8.8uX\n", ether->ctlrno, status);
+ }
+}
+
+static void
+ctlrinit(Ether* ether)
+{
+ Ctlr *ctlr;
+ Des *des;
+ Block *bp;
+ int i;
+ uchar bi[Eaddrlen*2];
+
+ ctlr = ether->ctlr;
+
+ /*
+ * Allocate and initialise the receive ring;
+ * allocate and initialise the transmit ring;
+ * unmask interrupts and start the transmit side;
+ * create and post a setup packet to initialise
+ * the physical ethernet address.
+ */
+ ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des));
+ for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
+ des->bp = malloc(Rbsz);
+ des->status = Own;
+ des->control = Rbsz;
+ des->addr = PADDR(des->bp);
+ }
+ ctlr->rdr[ctlr->nrdr-1].control |= Er;
+ ctlr->rdrx = 0;
+ csr32w(ctlr, 3, PADDR(ctlr->rdr));
+
+ ctlr->tdr = ialloc(ctlr->ntdr*sizeof(Des), 32);
+ ctlr->tdr[ctlr->ntdr-1].control |= Er;
+ ctlr->tdrh = 0;
+ ctlr->tdri = 0;
+ csr32w(ctlr, 4, PADDR(ctlr->tdr));
+
+ /*
+ * Clear any bits in the Status Register (CSR5) as
+ * the PNIC has a different reset value from a true 2114x.
+ */
+ ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti;
+ csr32w(ctlr, 5, ctlr->mask);
+ csr32w(ctlr, 7, ctlr->mask);
+ ctlr->csr6 |= St;
+ csr32w(ctlr, 6, ctlr->csr6);
+
+ for(i = 0; i < Eaddrlen/2; i++){
+ bi[i*4] = ether->ea[i*2];
+ bi[i*4+1] = ether->ea[i*2+1];
+ bi[i*4+2] = ether->ea[i*2+1];
+ bi[i*4+3] = ether->ea[i*2];
+ }
+ bp = allocb(Eaddrlen*2*16);
+ memset(bp->rp, 0xFF, sizeof(bi));
+ for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi))
+ memmove(bp->rp+i, bi, sizeof(bi));
+ bp->wp += sizeof(bi)*16;
+
+ ctlr->setupbp = bp;
+ transmit(ether);
+}
+
+static void
+csr9w(Ctlr* ctlr, int data)
+{
+ csr32w(ctlr, 9, data);
+ microdelay(1);
+}
+
+static int
+miimdi(Ctlr* ctlr, int n)
+{
+ int data, i;
+
+ /*
+ * Read n bits from the MII Management Register.
+ */
+ data = 0;
+ for(i = n-1; i >= 0; i--){
+ if(csr32r(ctlr, 9) & Mdi)
+ data |= (1<<i);
+ csr9w(ctlr, Mii|Mdc);
+ csr9w(ctlr, Mii);
+ }
+ csr9w(ctlr, 0);
+
+ return data;
+}
+
+static void
+miimdo(Ctlr* ctlr, int bits, int n)
+{
+ int i, mdo;
+
+ /*
+ * Write n bits to the MII Management Register.
+ */
+ for(i = n-1; i >= 0; i--){
+ if(bits & (1<<i))
+ mdo = Mdo;
+ else
+ mdo = 0;
+ csr9w(ctlr, mdo);
+ csr9w(ctlr, mdo|Mdc);
+ csr9w(ctlr, mdo);
+ }
+}
+
+static int
+miir(Ctlr* ctlr, int phyad, int regad)
+{
+ int data, i;
+
+ if(ctlr->id == Pnic){
+ i = 1000;
+ csr32w(ctlr, 20, 0x60020000|(phyad<<23)|(regad<<18));
+ do{
+ microdelay(1);
+ data = csr32r(ctlr, 20);
+ }while((data & 0x80000000) && --i);
+
+ if(i == 0)
+ return -1;
+ return data & 0xFFFF;
+ }
+
+ /*
+ * Preamble;
+ * ST+OP+PHYAD+REGAD;
+ * TA + 16 data bits.
+ */
+ miimdo(ctlr, 0xFFFFFFFF, 32);
+ miimdo(ctlr, 0x1800|(phyad<<5)|regad, 14);
+ data = miimdi(ctlr, 18);
+
+ if(data & 0x10000)
+ return -1;
+
+ return data & 0xFFFF;
+}
+
+static void
+miiw(Ctlr* ctlr, int phyad, int regad, int data)
+{
+ /*
+ * Preamble;
+ * ST+OP+PHYAD+REGAD+TA + 16 data bits;
+ * Z.
+ */
+ miimdo(ctlr, 0xFFFFFFFF, 32);
+ data &= 0xFFFF;
+ data |= (0x05<<(5+5+2+16))|(phyad<<(5+2+16))|(regad<<(2+16))|(0x02<<16);
+ miimdo(ctlr, data, 32);
+ csr9w(ctlr, Mdc);
+ csr9w(ctlr, 0);
+}
+
+static int
+sromr(Ctlr* ctlr, int r)
+{
+ int i, op, data, size;
+
+ if(ctlr->id == Pnic){
+ i = 1000;
+ csr32w(ctlr, 19, 0x600|r);
+ do{
+ microdelay(1);
+ data = csr32r(ctlr, 19);
+ }while((data & 0x80000000) && --i);
+
+ if(ctlr->sromsz == 0)
+ ctlr->sromsz = 6;
+
+ return csr32r(ctlr, 9) & 0xFFFF;
+ }
+
+ /*
+ * This sequence for reading a 16-bit register 'r'
+ * in the EEPROM is taken (pretty much) straight from Section
+ * 7.4 of the 21140 Hardware Reference Manual.
+ */
+reread:
+ csr9w(ctlr, Rd|Ss);
+ csr9w(ctlr, Rd|Ss|Scs);
+ csr9w(ctlr, Rd|Ss|Sclk|Scs);
+ csr9w(ctlr, Rd|Ss);
+
+ op = 0x06;
+ for(i = 3-1; i >= 0; i--){
+ data = Rd|Ss|(((op>>i) & 0x01)<<2)|Scs;
+ csr9w(ctlr, data);
+ csr9w(ctlr, data|Sclk);
+ csr9w(ctlr, data);
+ }
+
+ /*
+ * First time through must work out the EEPROM size.
+ * This doesn't seem to work on the 21041 as implemented
+ * in Virtual PC for the Mac, so wire any 21041 to 6,
+ * it's the only 21041 this code will ever likely see.
+ */
+ if((size = ctlr->sromsz) == 0){
+ if(ctlr->id == Tulip1)
+ ctlr->sromsz = size = 6;
+ else
+ size = 8;
+ }
+
+ for(size = size-1; size >= 0; size--){
+ data = Rd|Ss|(((r>>size) & 0x01)<<2)|Scs;
+ csr9w(ctlr, data);
+ csr9w(ctlr, data|Sclk);
+ csr9w(ctlr, data);
+ microdelay(1);
+ if(ctlr->sromsz == 0 && !(csr32r(ctlr, 9) & Sdo))
+ break;
+ }
+
+ data = 0;
+ for(i = 16-1; i >= 0; i--){
+ csr9w(ctlr, Rd|Ss|Sclk|Scs);
+ if(csr32r(ctlr, 9) & Sdo)
+ data |= (1<<i);
+ csr9w(ctlr, Rd|Ss|Scs);
+ }
+
+ csr9w(ctlr, 0);
+
+ if(ctlr->sromsz == 0){
+ ctlr->sromsz = 8-size;
+ goto reread;
+ }
+
+ return data & 0xFFFF;
+}
+
+static void
+softreset(Ctlr* ctlr)
+{
+ /*
+ * Soft-reset the controller and initialise bus mode.
+ * Delay should be >= 50 PCI cycles (2×S @ 25MHz).
+ */
+ csr32w(ctlr, 0, Swr);
+ microdelay(10);
+ csr32w(ctlr, 0, Rml|Cal16);
+ delay(1);
+}
+
+static int
+type5block(Ctlr* ctlr, uchar* block)
+{
+ int csr15, i, len;
+
+ /*
+ * Reset or GPR sequence. Reset should be once only,
+ * before the GPR sequence.
+ * Note 'block' is not a pointer to the block head but
+ * a pointer to the data in the block starting at the
+ * reset length value so type5block can be used for the
+ * sequences contained in type 1 and type 3 blocks.
+ * The SROM docs state the 21140 type 5 block is the
+ * same as that for the 21143, but the two controllers
+ * use different registers and sequence-element lengths
+ * so the 21140 code here is a guess for a real type 5
+ * sequence.
+ */
+ len = *block++;
+ if(ctlr->id != Tulip3){
+ for(i = 0; i < len; i++){
+ csr32w(ctlr, 12, *block);
+ block++;
+ }
+ return len;
+ }
+
+ for(i = 0; i < len; i++){
+ csr15 = *block++<<16;
+ csr15 |= *block++<<24;
+ csr32w(ctlr, 15, csr15);
+ debug("%8.8uX ", csr15);
+ }
+ return 2*len;
+}
+
+static int
+typephylink(Ctlr* ctlr, uchar*)
+{
+ int an, bmcr, bmsr, csr6, x;
+
+ /*
+ * Fail if
+ * auto-negotiataion enabled but not complete;
+ * no valid link established.
+ */
+ bmcr = miir(ctlr, ctlr->curphyad, Bmcr);
+ miir(ctlr, ctlr->curphyad, Bmsr);
+ bmsr = miir(ctlr, ctlr->curphyad, Bmsr);
+ debug("bmcr 0x%2.2uX bmsr 0x%2.2uX\n", bmcr, bmsr);
+ if(((bmcr & 0x1000) && !(bmsr & 0x0020)) || !(bmsr & 0x0004))
+ return 0;
+
+ if(bmcr & 0x1000){
+ an = miir(ctlr, ctlr->curphyad, Anar);
+ an &= miir(ctlr, ctlr->curphyad, Anlpar) & 0x3E0;
+ debug("an 0x%2.uX 0x%2.2uX 0x%2.2uX\n",
+ miir(ctlr, ctlr->curphyad, Anar),
+ miir(ctlr, ctlr->curphyad, Anlpar),
+ an);
+
+ if(an & 0x0100)
+ x = 0x4000;
+ else if(an & 0x0080)
+ x = 0x2000;
+ else if(an & 0x0040)
+ x = 0x1000;
+ else if(an & 0x0020)
+ x = 0x0800;
+ else
+ x = 0;
+ }
+ else if((bmcr & 0x2100) == 0x2100)
+ x = 0x4000;
+ else if(bmcr & 0x2000){
+ /*
+ * If FD capable, force it if necessary.
+ */
+ if((bmsr & 0x4000) && ctlr->fd){
+ miiw(ctlr, ctlr->curphyad, Bmcr, 0x2100);
+ x = 0x4000;
+ }
+ else
+ x = 0x2000;
+ }
+ else if(bmcr & 0x0100)
+ x = 0x1000;
+ else
+ x = 0x0800;
+
+ csr6 = Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
+ if(ctlr->fdx & x)
+ csr6 |= Fd;
+ if(ctlr->ttm & x)
+ csr6 |= Ttm;
+ debug("csr6 0x%8.8uX 0x%8.8uX 0x%8.8luX\n",
+ csr6, ctlr->csr6, csr32r(ctlr, 6));
+ if(csr6 != ctlr->csr6){
+ ctlr->csr6 = csr6;
+ csr32w(ctlr, 6, csr6);
+ }
+
+ return 1;
+}
+
+static int
+typephymode(Ctlr* ctlr, uchar* block, int wait)
+{
+ uchar *p;
+ int len, mc, nway, phyx, timeo;
+
+ if(DEBUG){
+ int i;
+
+ len = (block[0] & ~0x80)+1;
+ for(i = 0; i < len; i++)
+ debug("%2.2uX ", block[i]);
+ debug("\n");
+ }
+
+ if(block[1] == 1)
+ len = 1;
+ else if(block[1] == 3)
+ len = 2;
+ else
+ return -1;
+
+ /*
+ * Snarf the media capabilities, nway advertisment,
+ * FDX and TTM bitmaps.
+ */
+ p = &block[5+len*block[3]+len*block[4+len*block[3]]];
+ mc = *p++;
+ mc |= *p++<<8;
+ nway = *p++;
+ nway |= *p++<<8;
+ ctlr->fdx = *p++;
+ ctlr->fdx |= *p++<<8;
+ ctlr->ttm = *p++;
+ ctlr->ttm |= *p<<8;
+ debug("mc %4.4uX nway %4.4uX fdx %4.4uX ttm %4.4uX\n",
+ mc, nway, ctlr->fdx, ctlr->ttm);
+ USED(mc);
+
+ phyx = block[2];
+ ctlr->curphyad = ctlr->phy[phyx];
+
+ ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
+ //csr32w(ctlr, 6, ctlr->csr6);
+ if(typephylink(ctlr, block))
+ return 0;
+
+ if(!(ctlr->phyreset & (1<<phyx))){
+ debug("reset seq: len %d: ", block[3]);
+ if(ctlr->type5block)
+ type5block(ctlr, &ctlr->type5block[2]);
+ else
+ type5block(ctlr, &block[4+len*block[3]]);
+ debug("\n");
+ ctlr->phyreset |= (1<<phyx);
+ }
+
+ /*
+ * GPR sequence.
+ */
+ debug("gpr seq: len %d: ", block[3]);
+ type5block(ctlr, &block[3]);
+ debug("\n");
+
+ ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb;
+ //csr32w(ctlr, 6, ctlr->csr6);
+ if(typephylink(ctlr, block))
+ return 0;
+
+ /*
+ * Turn off auto-negotiation, set the auto-negotiation
+ * advertisment register then start the auto-negotiation
+ * process again.
+ */
+ miiw(ctlr, ctlr->curphyad, Bmcr, 0);
+ miiw(ctlr, ctlr->curphyad, Anar, nway|1);
+ miiw(ctlr, ctlr->curphyad, Bmcr, 0x1000);
+
+ if(!wait)
+ return 0;
+
+ for(timeo = 0; timeo < 30; timeo++){
+ if(typephylink(ctlr, block))
+ return 0;
+ delay(100);
+ }
+
+ return -1;
+}
+
+static int
+typesymmode(Ctlr *ctlr, uchar *block, int wait)
+{
+ uint gpmode, gpdata, command;
+
+ USED(wait);
+ gpmode = block[3] | ((uint) block[4] << 8);
+ gpdata = block[5] | ((uint) block[6] << 8);
+ command = (block[7] | ((uint) block[8] << 8)) & 0x71;
+ if (command & 0x8000) {
+ print("ether2114x.c: FIXME: handle type 4 mode blocks where cmd.active_invalid != 0\n");
+ return -1;
+ }
+ csr32w(ctlr, 15, gpmode);
+ csr32w(ctlr, 15, gpdata);
+ ctlr->csr6 = (command & 0x71) << 18;
+ csr32w(ctlr, 6, ctlr->csr6);
+ return 0;
+}
+
+static int
+type2mode(Ctlr* ctlr, uchar* block, int)
+{
+ uchar *p;
+ int csr6, csr13, csr14, csr15, gpc, gpd;
+
+ csr6 = Sc|Mbo|Ca|TrMODE|Sb;
+ debug("type2mode: medium 0x%2.2uX\n", block[2]);
+
+ /*
+ * Don't attempt full-duplex
+ * unless explicitly requested.
+ */
+ if((block[2] & 0x3F) == 0x04){ /* 10BASE-TFD */
+ if(!ctlr->fd)
+ return -1;
+ csr6 |= Fd;
+ }
+
+ /*
+ * Operating mode programming values from the datasheet
+ * unless media specific data is explicitly given.
+ */
+ p = &block[3];
+ if(block[2] & 0x40){
+ csr13 = (block[4]<<8)|block[3];
+ csr14 = (block[6]<<8)|block[5];
+ csr15 = (block[8]<<8)|block[7];
+ p += 6;
+ }
+ else switch(block[2] & 0x3F){
+ default:
+ return -1;
+ case 0x00: /* 10BASE-T */
+ csr13 = 0x00000001;
+ csr14 = 0x00007F3F;
+ csr15 = 0x00000008;
+ break;
+ case 0x01: /* 10BASE-2 */
+ csr13 = 0x00000009;
+ csr14 = 0x00000705;
+ csr15 = 0x00000006;
+ break;
+ case 0x02: /* 10BASE-5 (AUI) */
+ csr13 = 0x00000009;
+ csr14 = 0x00000705;
+ csr15 = 0x0000000E;
+ break;
+ case 0x04: /* 10BASE-TFD */
+ csr13 = 0x00000001;
+ csr14 = 0x00007F3D;
+ csr15 = 0x00000008;
+ break;
+ }
+ gpc = *p++<<16;
+ gpc |= *p++<<24;
+ gpd = *p++<<16;
+ gpd |= *p<<24;
+
+ csr32w(ctlr, 13, 0);
+ csr32w(ctlr, 14, csr14);
+ csr32w(ctlr, 15, gpc|csr15);
+ delay(10);
+ csr32w(ctlr, 15, gpd|csr15);
+ csr32w(ctlr, 13, csr13);
+
+ ctlr->csr6 = csr6;
+ csr32w(ctlr, 6, ctlr->csr6);
+
+ debug("type2mode: csr13 %8.8uX csr14 %8.8uX csr15 %8.8uX\n",
+ csr13, csr14, csr15);
+ debug("type2mode: gpc %8.8uX gpd %8.8uX csr6 %8.8uX\n",
+ gpc, gpd, csr6);
+
+ return 0;
+}
+
+static int
+type0link(Ctlr* ctlr, uchar* block)
+{
+ int m, polarity, sense;
+
+ m = (block[3]<<8)|block[2];
+ sense = 1<<((m & 0x000E)>>1);
+ if(m & 0x0080)
+ polarity = sense;
+ else
+ polarity = 0;
+
+ return (csr32r(ctlr, 12) & sense)^polarity;
+}
+
+static int
+type0mode(Ctlr* ctlr, uchar* block, int wait)
+{
+ int csr6, m, timeo;
+
+ csr6 = Sc|Mbo|Hbd|Ca|TrMODE|Sb;
+debug("type0: medium 0x%uX, fd %d: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
+ ctlr->medium, ctlr->fd, block[0], block[1], block[2], block[3]);
+ switch(block[0]){
+ default:
+ break;
+
+ case 0x04: /* 10BASE-TFD */
+ case 0x05: /* 100BASE-TXFD */
+ case 0x08: /* 100BASE-FXFD */
+ /*
+ * Don't attempt full-duplex
+ * unless explicitly requested.
+ */
+ if(!ctlr->fd)
+ return -1;
+ csr6 |= Fd;
+ break;
+ }
+
+ m = (block[3]<<8)|block[2];
+ if(m & 0x0001)
+ csr6 |= Ps;
+ if(m & 0x0010)
+ csr6 |= Ttm;
+ if(m & 0x0020)
+ csr6 |= Pcs;
+ if(m & 0x0040)
+ csr6 |= Scr;
+
+ csr32w(ctlr, 12, block[1]);
+ microdelay(10);
+ csr32w(ctlr, 6, csr6);
+ ctlr->csr6 = csr6;
+
+ if(!wait)
+ return 0;
+
+ for(timeo = 0; timeo < 30; timeo++){
+ if(type0link(ctlr, block))
+ return 0;
+ delay(100);
+ }
+
+ return -1;
+}
+
+static int
+media21041(Ether* ether, int wait)
+{
+ Ctlr* ctlr;
+ uchar *block;
+ int csr6, csr13, csr14, csr15, medium, timeo;
+
+ ctlr = ether->ctlr;
+ block = ctlr->infoblock[ctlr->curk];
+ debug("media21041: block[0] %2.2uX, medium %4.4uX sct %4.4uX\n",
+ block[0], ctlr->medium, ctlr->sct);
+
+ medium = block[0] & 0x3F;
+ if(ctlr->medium >= 0 && medium != ctlr->medium)
+ return 0;
+ if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != medium)
+ return 0;
+
+ csr6 = Sc|Mbo|Ca|TrMODE|Sb;
+ if(block[0] & 0x40){
+ csr13 = (block[2]<<8)|block[1];
+ csr14 = (block[4]<<8)|block[3];
+ csr15 = (block[6]<<8)|block[5];
+ }
+ else switch(medium){
+ default:
+ return -1;
+ case 0x00: /* 10BASE-T */
+ csr13 = 0xEF01;
+ csr14 = 0xFF3F;
+ csr15 = 0x0008;
+ break;
+ case 0x01: /* 10BASE-2 */
+ csr13 = 0xEF09;
+ csr14 = 0xF73D;
+ csr15 = 0x0006;
+ break;
+ case 0x02: /* 10BASE-5 */
+ csr13 = 0xEF09;
+ csr14 = 0xF73D;
+ csr15 = 0x000E;
+ break;
+ case 0x04: /* 10BASE-TFD */
+ csr13 = 0xEF01;
+ csr14 = 0xFF3D;
+ csr15 = 0x0008;
+ break;
+ }
+
+ csr32w(ctlr, 13, 0);
+ csr32w(ctlr, 14, csr14);
+ csr32w(ctlr, 15, csr15);
+ csr32w(ctlr, 13, csr13);
+ delay(10);
+
+ if(medium == 0x04)
+ csr6 |= Fd;
+ ctlr->csr6 = csr6;
+ csr32w(ctlr, 6, ctlr->csr6);
+
+ debug("media21041: csr6 %8.8uX csr13 %4.4uX csr14 %4.4uX csr15 %4.4uX\n",
+ csr6, csr13, csr14, csr15);
+
+ if(!wait)
+ return 0;
+
+ for(timeo = 0; timeo < 30; timeo++){
+ if(!(csr32r(ctlr, 12) & 0x0002)){
+ debug("media21041: ok: csr12 %4.4luX timeo %d\n",
+ csr32r(ctlr, 12), timeo);
+ return 10;
+ }
+ delay(100);
+ }
+ debug("media21041: !ok: csr12 %4.4luX\n", csr32r(ctlr, 12));
+
+ return -1;
+}
+
+static int
+mediaxx(Ether* ether, int wait)
+{
+ Ctlr* ctlr;
+ uchar *block;
+
+ ctlr = ether->ctlr;
+ block = ctlr->infoblock[ctlr->curk];
+ if(block[0] & 0x80){
+ switch(block[1]){
+ default:
+ return -1;
+ case 0:
+ if(ctlr->medium >= 0 && block[2] != ctlr->medium)
+ return 0;
+/* need this test? */ if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[2])
+ return 0;
+ if(type0mode(ctlr, block+2, wait))
+ return 0;
+ break;
+ case 1:
+ if(typephymode(ctlr, block, wait))
+ return 0;
+ break;
+ case 2:
+ debug("type2: medium %d block[2] %d\n",
+ ctlr->medium, block[2]);
+ if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
+ return 0;
+ if(type2mode(ctlr, block, wait))
+ return 0;
+ break;
+ case 3:
+ if(typephymode(ctlr, block, wait))
+ return 0;
+ break;
+ case 4:
+ debug("type4: medium %d block[2] %d\n",
+ ctlr->medium, block[2]);
+ if(ctlr->medium >= 0 && ((block[2] & 0x3F) != ctlr->medium))
+ return 0;
+ if(typesymmode(ctlr, block, wait))
+ return 0;
+ break;
+ }
+ }
+ else{
+ if(ctlr->medium >= 0 && block[0] != ctlr->medium)
+ return 0;
+/* need this test? */if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[0])
+ return 0;
+ if(type0mode(ctlr, block, wait))
+ return 0;
+ }
+
+ if(ctlr->csr6){
+ if(!(ctlr->csr6 & Ps) || (ctlr->csr6 & Ttm))
+ return 10;
+ return 100;
+ }
+
+ return 0;
+}
+
+static int
+media(Ether* ether, int wait)
+{
+ Ctlr* ctlr;
+ int k, mbps;
+
+ ctlr = ether->ctlr;
+ for(k = 0; k < ctlr->k; k++){
+ switch(ctlr->id){
+ default:
+ mbps = mediaxx(ether, wait);
+ break;
+ case Tulip1: /* 21041 */
+ mbps = media21041(ether, wait);
+ break;
+ }
+ if(mbps > 0)
+ return mbps;
+ if(ctlr->curk == 0)
+ ctlr->curk = ctlr->k-1;
+ else
+ ctlr->curk--;
+ }
+
+ return 0;
+}
+
+static char* mediatable[9] = {
+ "10BASE-T", /* TP */
+ "10BASE-2", /* BNC */
+ "10BASE-5", /* AUI */
+ "100BASE-TX",
+ "10BASE-TFD",
+ "100BASE-TXFD",
+ "100BASE-T4",
+ "100BASE-FX",
+ "100BASE-FXFD",
+};
+
+static uchar en1207[] = { /* Accton EN1207-COMBO */
+ 0x00, 0x00, 0xE8, /* [0] vendor ethernet code */
+ 0x00, /* [3] spare */
+
+ 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */
+ 0x1F, /* [6] general purpose control */
+ 2, /* [7] block count */
+
+ 0x00, /* [8] media code (10BASE-TX) */
+ 0x0B, /* [9] general purpose port data */
+ 0x9E, 0x00, /* [10] command (LSB+MSB = 0x009E) */
+
+ 0x03, /* [8] media code (100BASE-TX) */
+ 0x1B, /* [9] general purpose port data */
+ 0x6D, 0x00, /* [10] command (LSB+MSB = 0x006D) */
+
+ /* There is 10BASE-2 as well, but... */
+};
+
+static uchar ana6910fx[] = { /* Adaptec (Cogent) ANA-6910FX */
+ 0x00, 0x00, 0x92, /* [0] vendor ethernet code */
+ 0x00, /* [3] spare */
+
+ 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */
+ 0x3F, /* [6] general purpose control */
+ 1, /* [7] block count */
+
+ 0x07, /* [8] media code (100BASE-FX) */
+ 0x03, /* [9] general purpose port data */
+ 0x2D, 0x00 /* [10] command (LSB+MSB = 0x000D) */
+};
+
+static uchar smc9332[] = { /* SMC 9332 */
+ 0x00, 0x00, 0xC0, /* [0] vendor ethernet code */
+ 0x00, /* [3] spare */
+
+ 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */
+ 0x1F, /* [6] general purpose control */
+ 2, /* [7] block count */
+
+ 0x00, /* [8] media code (10BASE-TX) */
+ 0x00, /* [9] general purpose port data */
+ 0x9E, 0x00, /* [10] command (LSB+MSB = 0x009E) */
+
+ 0x03, /* [8] media code (100BASE-TX) */
+ 0x09, /* [9] general purpose port data */
+ 0x6D, 0x00, /* [10] command (LSB+MSB = 0x006D) */
+};
+
+static uchar* leaf21140[] = {
+ en1207, /* Accton EN1207-COMBO */
+ ana6910fx, /* Adaptec (Cogent) ANA-6910FX */
+ smc9332, /* SMC 9332 */
+ 0,
+};
+
+/*
+ * Copied to ctlr->srom at offset 20.
+ */
+static uchar leafpnic[] = {
+ 0x00, 0x00, 0x00, 0x00, /* MAC address */
+ 0x00, 0x00,
+ 0x00, /* controller 0 device number */
+ 0x1E, 0x00, /* controller 0 info leaf offset */
+ 0x00, /* reserved */
+ 0x00, 0x08, /* selected connection type */
+ 0x00, /* general purpose control */
+ 0x01, /* block count */
+
+ 0x8C, /* format indicator and count */
+ 0x01, /* block type */
+ 0x00, /* PHY number */
+ 0x00, /* GPR sequence length */
+ 0x00, /* reset sequence length */
+ 0x00, 0x78, /* media capabilities */
+ 0xE0, 0x01, /* Nway advertisment */
+ 0x00, 0x50, /* FDX bitmap */
+ 0x00, 0x18, /* TTM bitmap */
+};
+
+static int
+srom(Ctlr* ctlr)
+{
+ int i, k, oui, phy, x;
+ uchar *p;
+
+ /*
+ * This is a partial decoding of the SROM format described in
+ * 'Digital Semiconductor 21X4 Serial ROM Format, Version 4.05,
+ * 2-Mar-98'. Only the 2114[03] are handled, support for other
+ * controllers can be added as needed.
+ */
+ sromr(ctlr, 0);
+ if(ctlr->srom == nil)
+ ctlr->srom = malloc((1<<ctlr->sromsz)*sizeof(ushort));
+ for(i = 0; i < (1<<ctlr->sromsz); i++){
+ x = sromr(ctlr, i);
+ ctlr->srom[2*i] = x;
+ ctlr->srom[2*i+1] = x>>8;
+ }
+
+ if(DEBUG){
+ print("srom:");
+ for(i = 0; i < ((1<<ctlr->sromsz)*sizeof(ushort)); i++){
+ if(i && ((i & 0x0F) == 0))
+ print("\n ");
+ print(" %2.2uX", ctlr->srom[i]);
+ }
+ print("\n");
+ }
+
+ /*
+ * There are 2 SROM layouts:
+ * e.g. Digital EtherWORKS station address at offset 20;
+ * this complies with the 21140A SROM
+ * application note from Digital;
+ * e.g. SMC9332 station address at offset 0 followed by
+ * 2 additional bytes, repeated at offset
+ * 6; the 8 bytes are also repeated in
+ * reverse order at offset 8.
+ * To check which it is, read the SROM and check for the repeating
+ * patterns of the non-compliant cards; if that fails use the one at
+ * offset 20.
+ */
+ ctlr->sromea = ctlr->srom;
+ for(i = 0; i < 8; i++){
+ x = ctlr->srom[i];
+ if(x != ctlr->srom[15-i] || x != ctlr->srom[16+i]){
+ ctlr->sromea = &ctlr->srom[20];
+ break;
+ }
+ }
+
+ /*
+ * Fake up the SROM for the PNIC.
+ * It looks like a 21140 with a PHY.
+ * The MAC address is byte-swapped in the orginal SROM data.
+ */
+ if(ctlr->id == Pnic){
+ memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));
+ for(i = 0; i < Eaddrlen; i += 2){
+ ctlr->srom[20+i] = ctlr->srom[i+1];
+ ctlr->srom[20+i+1] = ctlr->srom[i];
+ }
+ }
+
+ /*
+ * Next, try to find the info leaf in the SROM for media detection.
+ * If it's a non-conforming card try to match the vendor ethernet code
+ * and point p at a fake info leaf with compact 21140 entries.
+ */
+ if(ctlr->sromea == ctlr->srom){
+ p = nil;
+ for(i = 0; leaf21140[i] != nil; i++){
+ if(memcmp(leaf21140[i], ctlr->sromea, 3) == 0){
+ p = &leaf21140[i][4];
+ break;
+ }
+ }
+ if(p == nil)
+ return -1;
+ }
+ else
+ p = &ctlr->srom[(ctlr->srom[28]<<8)|ctlr->srom[27]];
+
+ /*
+ * Set up the info needed for later media detection.
+ * For the 21140, set the general-purpose mask in CSR12.
+ * The info block entries are stored in order of increasing
+ * precedence, so detection will work backwards through the
+ * stored indexes into ctlr->srom.
+ * If an entry is found which matches the selected connection
+ * type, save the index. Otherwise, start at the last entry.
+ * If any MII entries are found (type 1 and 3 blocks), scan
+ * for PHYs.
+ */
+ ctlr->leaf = p;
+ ctlr->sct = *p++;
+ ctlr->sct |= *p++<<8;
+ if(ctlr->id != Tulip3 && ctlr->id != Tulip1){
+ csr32w(ctlr, 12, Gpc|*p++);
+ delay(200);
+ }
+ ctlr->k = *p++;
+ if(ctlr->k >= nelem(ctlr->infoblock))
+ ctlr->k = nelem(ctlr->infoblock)-1;
+ ctlr->sctk = ctlr->k-1;
+ phy = 0;
+ for(k = 0; k < ctlr->k; k++){
+ ctlr->infoblock[k] = p;
+ if(ctlr->id == Tulip1){
+ debug("type21041: 0x%2.2uX\n", p[0]);
+ if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
+ ctlr->sctk = k;
+ if(*p & 0x40)
+ p += 7;
+ else
+ p += 1;
+ }
+ /*
+ * The RAMIX PMC665 has a badly-coded SROM,
+ * hence the test for 21143 and type 3.
+ */
+ else if((*p & 0x80) || (ctlr->id == Tulip3 && *(p+1) == 3)){
+ *p |= 0x80;
+ if(*(p+1) == 1 || *(p+1) == 3)
+ phy = 1;
+ if(*(p+1) == 5)
+ ctlr->type5block = p;
+ p += (*p & ~0x80)+1;
+ }
+ else{
+ debug("type0: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",
+ p[0], p[1], p[2], p[3]);
+ if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))
+ ctlr->sctk = k;
+ p += 4;
+ }
+ }
+ ctlr->curk = ctlr->sctk;
+ debug("sct 0x%uX medium 0x%uX k %d curk %d phy %d\n",
+ ctlr->sct, ctlr->medium, ctlr->k, ctlr->curk, phy);
+
+ if(phy){
+ x = 0;
+ for(k = 0; k < nelem(ctlr->phy); k++){
+ if((oui = miir(ctlr, k, 2)) == -1 || oui == 0)
+ continue;
+ if(DEBUG){
+ oui = (oui & 0x3FF)<<6;
+ oui |= miir(ctlr, k, 3)>>10;
+ miir(ctlr, k, 1);
+ debug("phy%d: index %d oui %uX reg1 %uX\n",
+ x, k, oui, miir(ctlr, k, 1));
+ USED(oui);
+ }
+ ctlr->phy[x] = k;
+ }
+ }
+
+ ctlr->fd = 0;
+ ctlr->medium = -1;
+
+ return 0;
+}
+
+static void
+dec2114xpci(void)
+{
+ Ctlr *ctlr;
+ Pcidev *p;
+ int x;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+
+ case Tulip3: /* 21143 */
+ /*
+ * Exit sleep mode.
+ */
+ x = pcicfgr32(p, 0x40);
+ x &= ~0xC0000000;
+ pcicfgw32(p, 0x40, x);
+ /*FALLTHROUGH*/
+
+ case Pnic: /* PNIC */
+ case Pnic2: /* PNIC-II */
+ case Tulip0: /* 21140 */
+ case Tulip1: /* 21041 */
+ break;
+ }
+
+ /*
+ * bar[0] is the I/O port register address and
+ * bar[1] is the memory-mapped register address.
+ */
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = p->mem[0].bar & ~0x01;
+ ctlr->pcidev = p;
+ ctlr->id = (p->did<<16)|p->vid;
+ debug("2114x: type 0x%8.8uX rev 0x%4.4uX at port 0x%4.4uX\n",
+ ctlr->id, p->rid, ctlr->port);
+
+ /*
+ * Some cards (e.g. ANA-6910FX) seem to need the Ps bit
+ * set or they don't always work right after a hardware
+ * reset.
+ */
+ csr32w(ctlr, 6, Mbo|Ps);
+ softreset(ctlr);
+
+ if(srom(ctlr)){
+ free(ctlr);
+ break;
+ }
+
+ switch(ctlr->id){
+ default:
+ break;
+
+ case Pnic: /* PNIC */
+ /*
+ * Turn off the jabber timer.
+ */
+ csr32w(ctlr, 15, 0x00000001);
+ break;
+ }
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+}
+
+static void
+detach(Ether* ether)
+{
+ softreset(ether->ctlr);
+}
+
+int
+ether2114xreset(Ether* ether)
+{
+ Ctlr *ctlr;
+ int i, x;
+ uchar ea[Eaddrlen];
+ static int scandone;
+
+ if(scandone == 0){
+ dec2114xpci();
+ scandone = 1;
+ }
+
+ /*
+ * Any adapter matches if no ether->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(ether->port == 0 || ether->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ ether->ctlr = ctlr;
+ ether->port = ctlr->port;
+ ether->irq = ctlr->pcidev->intl;
+ ether->tbdf = ctlr->pcidev->tbdf;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in the hardware.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0)
+ memmove(ether->ea, ctlr->sromea, Eaddrlen);
+
+ /*
+ * Look for a medium override in case there's no autonegotiation
+ * (no MII) or the autonegotiation fails.
+ */
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrcmp(ether->opt[i], "FD") == 0){
+ ctlr->fd = 1;
+ continue;
+ }
+ for(x = 0; x < nelem(mediatable); x++){
+ debug("compare <%s> <%s>\n", mediatable[x],
+ ether->opt[i]);
+ if(cistrcmp(mediatable[x], ether->opt[i]))
+ continue;
+ ctlr->medium = x;
+
+ switch(ctlr->medium){
+ default:
+ ctlr->fd = 0;
+ break;
+
+ case 0x04: /* 10BASE-TFD */
+ case 0x05: /* 100BASE-TXFD */
+ case 0x08: /* 100BASE-FXFD */
+ ctlr->fd = 1;
+ break;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Determine media.
+ */
+ ctlr->mbps = media(ether, 1);
+
+ /*
+ * Initialise descriptor rings, ethernet address.
+ */
+ ctlr->nrdr = Nrde;
+ ctlr->ntdr = Ntde;
+ pcisetbme(ctlr->pcidev);
+ ctlrinit(ether);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->detach = detach;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether589.c
@@ -1,0 +1,211 @@
+/*
+ * 3C589 and 3C562.
+ * To do:
+ * check xcvr10Base2 still works (is GlobalReset necessary?).
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "error.h"
+
+#include "etherif.h"
+
+enum { /* all windows */
+ CommandR = 0x000E,
+ IntStatusR = 0x000E,
+};
+
+enum { /* Commands */
+ GlobalReset = 0x0000,
+ SelectRegisterWindow = 0x0001,
+ RxReset = 0x0005,
+ TxReset = 0x000B,
+ AcknowledgeInterrupt = 0x000D,
+};
+
+enum { /* IntStatus bits */
+ commandInProgress = 0x1000,
+};
+
+#define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a))
+#define STATUS(port) ins((port)+IntStatusR)
+
+enum { /* Window 0 - setup */
+ Wsetup = 0x0000,
+ /* registers */
+ ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */
+ ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */
+ ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */
+ AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */
+ ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */
+ EepromCommand = 0x000A,
+ EepromData = 0x000C,
+ /* AddressConfig Bits */
+ autoSelect9 = 0x0080,
+ xcvrMask9 = 0xC000,
+ /* ConfigControl bits */
+ Ena = 0x0001,
+ base10TAvailable9 = 0x0200,
+ coaxAvailable9 = 0x1000,
+ auiAvailable9 = 0x2000,
+ /* EepromCommand bits */
+ EepromReadRegister = 0x0080,
+ EepromBusy = 0x8000,
+};
+
+enum { /* Window 1 - operating set */
+ Wop = 0x0001,
+};
+
+enum { /* Window 3 - FIFO management */
+ Wfifo = 0x0003,
+ /* registers */
+ InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */
+ /* InternalConfig bits */
+ xcvr10BaseT = 0x00000000,
+ xcvr10Base2 = 0x00300000,
+};
+
+enum { /* Window 4 - diagnostic */
+ Wdiagnostic = 0x0004,
+ /* registers */
+ MediaStatus = 0x000A,
+ /* MediaStatus bits */
+ linkBeatDetect = 0x0800,
+};
+
+extern int elnk3reset(Ether*);
+
+static char *tcmpcmcia[] = {
+ "3C589", /* 3COM 589[ABCD] */
+ "3C562", /* 3COM 562 */
+ "589E", /* 3COM Megahertz 589E */
+ nil,
+};
+
+static int
+configASIC(Ether* ether, int port, int xcvr)
+{
+ int x;
+
+ /* set Window 0 configuration registers */
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ outs(port+ConfigControl, Ena);
+
+ /* IRQ must be 3 on 3C589/3C562 */
+ outs(port + ResourceConfig, 0x3F00);
+
+ x = ins(port+AddressConfig) & ~xcvrMask9;
+ x |= (xcvr>>20)<<14;
+ outs(port+AddressConfig, x);
+
+ COMMAND(port, TxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, RxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+
+ return elnk3reset(ether);
+}
+
+int
+ether589reset(Ether* ether)
+{
+ int i, t, slot;
+ char *type;
+ int port;
+ enum { WantAny, Want10BT, Want10B2 };
+ int want;
+ uchar ea[6];
+ char *p;
+
+ if(ether->irq == 0)
+ ether->irq = 10;
+ if(ether->port == 0)
+ ether->port = 0x240;
+ port = ether->port;
+
+// if(ioalloc(port, 0x10, 0, "3C589") < 0)
+// return -1;
+
+ type = nil;
+ slot = -1;
+ for(i = 0; tcmpcmcia[i] != nil; i++){
+ type = tcmpcmcia[i];
+if(debug) print("try %s...", type);
+ if((slot = pcmspecial(type, ether)) >= 0)
+ break;
+ }
+ if(slot < 0){
+if(debug) print("none found\n");
+// iofree(port);
+ return -1;
+ }
+
+ /*
+ * Read Ethernet address from card memory
+ * on 3C562, but only if the user has not
+ * overridden it.
+ */
+ memset(ea, 0, sizeof ea);
+ if(memcmp(ea, ether->ea, 6) == 0 && strcmp(type, "3C562") == 0) {
+ if(debug)
+ print("read 562...");
+ if(pcmcistuple(slot, 0x88, -1, ea, 6) == 6) {
+ for(i = 0; i < 6; i += 2){
+ t = ea[i];
+ ea[i] = ea[i+1];
+ ea[i+1] = t;
+ }
+ memmove(ether->ea, ea, 6);
+ if(debug)
+ print("ea %E", ea);
+ }
+ }
+ /*
+ * Allow user to specify desired media in plan9.ini
+ */
+ want = WantAny;
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrncmp(ether->opt[i], "media=", 6) != 0)
+ continue;
+ p = ether->opt[i]+6;
+ if(cistrcmp(p, "10base2") == 0)
+ want = Want10B2;
+ else if(cistrcmp(p, "10baseT") == 0)
+ want = Want10BT;
+ }
+
+ /* try configuring as a 10BaseT */
+ if(want==WantAny || want==Want10BT){
+ if(configASIC(ether, port, xcvr10BaseT) < 0){
+ pcmspecialclose(slot);
+// iofree(port);
+ return -1;
+ }
+ delay(100);
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ if((ins(port+MediaStatus)&linkBeatDetect) || want==Want10BT){
+ COMMAND(port, SelectRegisterWindow, Wop);
+ print("#l%d: xcvr10BaseT %s\n", ether->ctlrno, type);
+ return 0;
+ }
+ }
+
+ /* try configuring as a 10base2 */
+ if(want==WantAny || want==Want10B2){
+ COMMAND(port, GlobalReset, 0);
+ if(configASIC(ether, port, xcvr10Base2) < 0){
+ pcmspecialclose(slot);
+// iofree(port);
+ return -1;
+ }
+ print("#l%d: xcvr10Base2 %s\n", ether->ctlrno, type);
+ return 0;
+ }
+ return -1; /* not reached */
+}
--- /dev/null
+++ b/os/boot.original/pc/ether79c970.c
@@ -1,0 +1,539 @@
+/*
+ * AMD79C970
+ * PCnet-PCI Single-Chip Ethernet Controller for PCI Local Bus
+ * To do:
+ * finish this rewrite
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+enum {
+ Lognrdre = 6,
+ Nrdre = (1<<Lognrdre),/* receive descriptor ring entries */
+ Logntdre = 4,
+ Ntdre = (1<<Logntdre),/* transmit descriptor ring entries */
+
+ Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
+};
+
+enum { /* DWIO I/O resource map */
+ Aprom = 0x0000, /* physical address */
+ Rdp = 0x0010, /* register data port */
+ Rap = 0x0014, /* register address port */
+ Sreset = 0x0018, /* software reset */
+ Bdp = 0x001C, /* bus configuration register data port */
+};
+
+enum { /* CSR0 */
+ Init = 0x0001, /* begin initialisation */
+ Strt = 0x0002, /* enable chip */
+ Stop = 0x0004, /* disable chip */
+ Tdmd = 0x0008, /* transmit demand */
+ Txon = 0x0010, /* transmitter on */
+ Rxon = 0x0020, /* receiver on */
+ Iena = 0x0040, /* interrupt enable */
+ Intr = 0x0080, /* interrupt flag */
+ Idon = 0x0100, /* initialisation done */
+ Tint = 0x0200, /* transmit interrupt */
+ Rint = 0x0400, /* receive interrupt */
+ Merr = 0x0800, /* memory error */
+ Miss = 0x1000, /* missed frame */
+ Cerr = 0x2000, /* collision */
+ Babl = 0x4000, /* transmitter timeout */
+ Err = 0x8000, /* Babl|Cerr|Miss|Merr */
+};
+
+enum { /* CSR3 */
+ Bswp = 0x0004, /* byte swap */
+ Emba = 0x0008, /* enable modified back-off algorithm */
+ Dxmt2pd = 0x0010, /* disable transmit two part deferral */
+ Lappen = 0x0020, /* look-ahead packet processing enable */
+};
+
+enum { /* CSR4 */
+ ApadXmt = 0x0800, /* auto pad transmit */
+};
+
+enum { /* CSR15 */
+ Prom = 0x8000, /* promiscuous mode */
+};
+
+typedef struct { /* Initialisation Block */
+ ushort mode;
+ uchar rlen; /* upper 4 bits */
+ uchar tlen; /* upper 4 bits */
+ uchar padr[6];
+ uchar res[2];
+ uchar ladr[8];
+ ulong rdra;
+ ulong tdra;
+} Iblock;
+
+typedef struct { /* descriptor ring entry */
+ ulong addr;
+ ulong md1; /* status|bcnt */
+ ulong md2; /* rcc|rpc|mcnt */
+ void* data;
+} Dre;
+
+enum { /* md1 */
+ Enp = 0x01000000, /* end of packet */
+ Stp = 0x02000000, /* start of packet */
+ RxBuff = 0x04000000, /* buffer error */
+ Def = 0x04000000, /* deferred */
+ Crc = 0x08000000, /* CRC error */
+ One = 0x08000000, /* one retry needed */
+ Oflo = 0x10000000, /* overflow error */
+ More = 0x10000000, /* more than one retry needed */
+ Fram = 0x20000000, /* framing error */
+ RxErr = 0x40000000, /* Fram|Oflo|Crc|RxBuff */
+ TxErr = 0x40000000, /* Uflo|Lcol|Lcar|Rtry */
+ Own = 0x80000000,
+};
+
+enum { /* md2 */
+ Rtry = 0x04000000, /* failed after repeated retries */
+ Lcar = 0x08000000, /* loss of carrier */
+ Lcol = 0x10000000, /* late collision */
+ Uflo = 0x40000000, /* underflow error */
+ TxBuff = 0x80000000, /* buffer error */
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ Lock;
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+
+ int init; /* initialisation in progress */
+ Iblock iblock;
+
+ Dre* rdr; /* receive descriptor ring */
+ int rdrx;
+
+ Dre* tdr; /* transmit descriptor ring */
+ int tdrh; /* host index into tdr */
+ int tdri; /* interface index into tdr */
+ int ntq; /* descriptors active */
+
+ ulong rxbuff; /* receive statistics */
+ ulong crc;
+ ulong oflo;
+ ulong fram;
+
+ ulong rtry; /* transmit statistics */
+ ulong lcar;
+ ulong lcol;
+ ulong uflo;
+ ulong txbuff;
+
+ ulong merr; /* bobf is such a whiner */
+ ulong miss;
+ ulong babl;
+
+ int (*ior)(Ctlr*, int);
+ void (*iow)(Ctlr*, int, int);
+};
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+/*
+ * The Rdp, Rap, Sreset, Bdp ports are 32-bit port offset in the enumeration above.
+ * To get to 16-bit offsets, scale down with 0x10 staying the same.
+ */
+static int
+io16r(Ctlr* c, int r)
+{
+ if(r >= Rdp)
+ r = (r-Rdp)/2+Rdp;
+ return ins(c->port+r);
+}
+
+static void
+io16w(Ctlr* c, int r, int v)
+{
+ if(r >= Rdp)
+ r = (r-Rdp)/2+Rdp;
+ outs(c->port+r, v);
+}
+
+static int
+io32r(Ctlr* c, int r)
+{
+ return inl(c->port+r);
+}
+
+static void
+io32w(Ctlr* c, int r, int v)
+{
+ outl(c->port+r, v);
+}
+
+static void
+attach(Ether*)
+{
+}
+
+static void
+detach(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ctlr->iow(ctlr, Rdp, Iena|Stop);
+}
+
+static void
+ringinit(Ctlr* ctlr)
+{
+ Dre *dre;
+
+ /*
+ * Initialise the receive and transmit buffer rings.
+ * The ring entries must be aligned on 16-byte boundaries.
+ *
+ * This routine is protected by ctlr->init.
+ */
+ if(ctlr->rdr == 0){
+ ctlr->rdr = ialloc(Nrdre*sizeof(Dre), 0x10);
+ for(dre = ctlr->rdr; dre < &ctlr->rdr[Nrdre]; dre++){
+ dre->data = malloc(Rbsize);
+ dre->addr = PADDR(dre->data);
+ dre->md2 = 0;
+ dre->md1 = Own|(-Rbsize & 0xFFFF);
+ }
+ }
+ ctlr->rdrx = 0;
+
+ if(ctlr->tdr == 0)
+ ctlr->tdr = ialloc(Ntdre*sizeof(Dre), 0x10);
+ memset(ctlr->tdr, 0, Ntdre*sizeof(Dre));
+ ctlr->tdrh = ctlr->tdri = 0;
+}
+
+static void
+transmit(Ether* ether)
+{
+ Ctlr *ctlr;
+ Block *bp;
+ Dre *dre;
+ RingBuf *tb;
+
+ ctlr = ether->ctlr;
+
+ if(ctlr->init)
+ return;
+
+ while(ctlr->ntq < (Ntdre-1)){
+ tb = ðer->tb[ether->ti];
+ if(tb->owner != Interface)
+ break;
+
+ bp = allocb(tb->len);
+ memmove(bp->wp, tb->pkt, tb->len);
+ memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+ bp->wp += tb->len;
+
+ /*
+ * Give ownership of the descriptor to the chip,
+ * increment the software ring descriptor pointer
+ * and tell the chip to poll.
+ * There's no need to pad to ETHERMINTU
+ * here as ApadXmt is set in CSR4.
+ */
+ dre = &ctlr->tdr[ctlr->tdrh];
+ dre->data = bp;
+ dre->addr = PADDR(bp->rp);
+ dre->md2 = 0;
+ dre->md1 = Own|Stp|Enp|Oflo|(-BLEN(bp) & 0xFFFF);
+ ctlr->ntq++;
+ ctlr->iow(ctlr, Rap, 0);
+ ctlr->iow(ctlr, Rdp, Iena|Tdmd);
+ ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
+
+ tb->owner = Host;
+ ether->ti = NEXT(ether->ti, ether->ntb);
+ }
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *ether;
+ int csr0;
+ Dre *dre;
+ RingBuf *rb;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ /*
+ * Acknowledge all interrupts and whine about those that shouldn't
+ * happen.
+ */
+intrloop:
+ csr0 = ctlr->ior(ctlr, Rdp) & 0xFFFF;
+ ctlr->iow(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena);
+ if(csr0 & Merr)
+ ctlr->merr++;
+ if(csr0 & Miss)
+ ctlr->miss++;
+ if(csr0 & Babl)
+ ctlr->babl++;
+ //if(csr0 & (Babl|Miss|Merr))
+ // print("#l%d: csr0 = 0x%uX\n", ether->ctlrno, csr0);
+ if(!(csr0 & (Rint|Tint)))
+ return;
+
+ /*
+ * Receiver interrupt: run round the descriptor ring logging
+ * errors and passing valid receive data up to the higher levels
+ * until a descriptor is encountered still owned by the chip.
+ */
+ if(csr0 & Rint){
+ dre = &ctlr->rdr[ctlr->rdrx];
+ while(!(dre->md1 & Own)){
+ rb = ðer->rb[ether->ri];
+ if(dre->md1 & RxErr){
+ if(dre->md1 & RxBuff)
+ ctlr->rxbuff++;
+ if(dre->md1 & Crc)
+ ctlr->crc++;
+ if(dre->md1 & Oflo)
+ ctlr->oflo++;
+ if(dre->md1 & Fram)
+ ctlr->fram++;
+ }
+ else if(rb->owner == Interface){
+ rb->owner = Host;
+ rb->len = (dre->md2 & 0x0FFF)-4;
+ memmove(rb->pkt, dre->data, rb->len);
+ ether->ri = NEXT(ether->ri, ether->nrb);
+ }
+
+ /*
+ * Finished with this descriptor, reinitialise it,
+ * give it back to the chip, then on to the next...
+ */
+ dre->md2 = 0;
+ dre->md1 = Own|(-Rbsize & 0xFFFF);
+
+ ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
+ dre = &ctlr->rdr[ctlr->rdrx];
+ }
+ }
+
+ /*
+ * Transmitter interrupt: wakeup anyone waiting for a free descriptor.
+ */
+ if(csr0 & Tint){
+ lock(ctlr);
+ while(ctlr->ntq){
+ dre = &ctlr->tdr[ctlr->tdri];
+ if(dre->md1 & Own)
+ break;
+
+ if(dre->md1 & TxErr){
+ if(dre->md2 & Rtry)
+ ctlr->rtry++;
+ if(dre->md2 & Lcar)
+ ctlr->lcar++;
+ if(dre->md2 & Lcol)
+ ctlr->lcol++;
+ if(dre->md2 & Uflo)
+ ctlr->uflo++;
+ if(dre->md2 & TxBuff)
+ ctlr->txbuff++;
+ }
+
+ freeb(dre->data);
+
+ ctlr->ntq--;
+ ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
+ }
+ transmit(ether);
+ unlock(ctlr);
+ }
+ goto intrloop;
+}
+
+static void
+amd79c970pci(void)
+{
+ Ctlr *ctlr;
+ Pcidev *p;
+
+ p = nil;
+ while(p = pcimatch(p, 0x1022, 0x2000)){
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = p->mem[0].bar & ~0x01;
+ ctlr->pcidev = p;
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+}
+
+int
+amd79c970reset(Ether* ether)
+{
+ int x;
+ uchar ea[Eaddrlen];
+ Ctlr *ctlr;
+
+ if(ctlrhead == nil)
+ amd79c970pci();
+
+ /*
+ * Any adapter matches if no port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(ether->port == 0 || ether->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ /*
+ * Allocate a controller structure and start to initialise it.
+ */
+ ether->ctlr = ctlr;
+ ether->port = ctlr->port;
+ ether->irq = ctlr->pcidev->intl;
+ ether->tbdf = ctlr->pcidev->tbdf;
+ pcisetbme(ctlr->pcidev);
+ ilock(ctlr);
+ ctlr->init = 1;
+
+ io32r(ctlr, Sreset);
+ io16r(ctlr, Sreset);
+
+ if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){
+ ctlr->ior = io16r;
+ ctlr->iow = io16w;
+ }else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){
+ ctlr->ior = io32r;
+ ctlr->iow = io32w;
+ }else{
+ print("#l%d: card doesn't talk right\n", ether->ctlrno);
+ iunlock(ctlr);
+ return -1;
+ }
+
+ ctlr->iow(ctlr, Rap, 88);
+ x = ctlr->ior(ctlr, Rdp);
+ ctlr->iow(ctlr, Rap, 89);
+ x |= ctlr->ior(ctlr, Rdp)<<16;
+
+ switch(x&0xFFFFFFF){
+ case 0x2420003: /* PCnet/PCI 79C970 */
+ case 0x2621003: /* PCnet/PCI II 79C970A */
+ break;
+ default:
+ print("unknown PCnet card version %.7ux\n", x&0xFFFFFFF);
+ iunlock(ctlr);
+ return -1;
+ }
+
+ /*
+ * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access.
+ * Set the auto pad transmit in CSR4.
+ */
+ ctlr->iow(ctlr, Rap, 20);
+ ctlr->iow(ctlr, Bdp, 0x0002);
+
+ ctlr->iow(ctlr, Rap, 4);
+ x = ctlr->ior(ctlr, Rdp) & 0xFFFF;
+ ctlr->iow(ctlr, Rdp, ApadXmt|x);
+
+ ctlr->iow(ctlr, Rap, 0);
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the I/O-space and set in ether->ea prior to
+ * loading the station address in the initialisation block.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(!memcmp(ea, ether->ea, Eaddrlen)){
+ x = ctlr->ior(ctlr, Aprom);
+ ether->ea[0] = x;
+ ether->ea[1] = x>>8;
+ if(ctlr->ior == io16r)
+ x = ctlr->ior(ctlr, Aprom+2);
+ else
+ x >>= 16;
+ ether->ea[2] = x;
+ ether->ea[3] = x>>8;
+ x = ctlr->ior(ctlr, Aprom+4);
+ ether->ea[4] = x;
+ ether->ea[5] = x>>8;
+ }
+
+ /*
+ * Start to fill in the initialisation block
+ * (must be DWORD aligned).
+ */
+ ctlr->iblock.rlen = Lognrdre<<4;
+ ctlr->iblock.tlen = Logntdre<<4;
+ memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr));
+
+ ringinit(ctlr);
+ ctlr->iblock.rdra = PADDR(ctlr->rdr);
+ ctlr->iblock.tdra = PADDR(ctlr->tdr);
+
+ /*
+ * Point the chip at the initialisation block and tell it to go.
+ * Mask the Idon interrupt and poll for completion. Strt and interrupt
+ * enables will be set later when attaching to the network.
+ */
+ x = PADDR(&ctlr->iblock);
+ ctlr->iow(ctlr, Rap, 1);
+ ctlr->iow(ctlr, Rdp, x & 0xFFFF);
+ ctlr->iow(ctlr, Rap, 2);
+ ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF);
+ ctlr->iow(ctlr, Rap, 3);
+ ctlr->iow(ctlr, Rdp, Idon);
+ ctlr->iow(ctlr, Rap, 0);
+ ctlr->iow(ctlr, Rdp, Init);
+
+ while(!(ctlr->ior(ctlr, Rdp) & Idon))
+ ;
+
+ /*
+ * We used to set CSR0 to Idon|Stop here, and then
+ * in attach change it to Iena|Strt. Apparently the simulated
+ * 79C970 in VMware never enables after a write of Idon|Stop,
+ * so we enable the device here now.
+ */
+ ctlr->iow(ctlr, Rdp, Iena|Strt);
+ ctlr->init = 0;
+ iunlock(ctlr);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->detach = detach;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether8003.c
@@ -1,0 +1,258 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ether8390.h"
+
+/*
+ * Western Digital/Standard Microsystems Corporation cards (WD80[01]3).
+ * Also handles 8216 cards (Elite Ultra).
+ * Configuration code based on that provided by SMC a long time ago.
+ */
+enum { /* 83C584 Bus Interface Controller */
+ Msr = 0x00, /* Memory Select Register */
+ Icr = 0x01, /* Interface Configuration Register */
+ Iar = 0x02, /* I/O Address Register */
+ Bio = 0x03, /* BIOS ROM Address Register */
+ Ear = 0x03, /* EEROM Address Register (shared with Bio) */
+ Irr = 0x04, /* Interrupt Request Register */
+ Hcr = 0x04, /* 8216 hardware control */
+ Laar = 0x05, /* LA Address Register */
+ Ijr = 0x06, /* Initialisation Jumpers */
+ Gp2 = 0x07, /* General Purpose Data Register */
+ Lar = 0x08, /* LAN Address Registers */
+ Id = 0x0E, /* Card ID byte */
+ Cksum = 0x0F, /* Checksum */
+};
+
+enum { /* Msr */
+ Rst = 0x80, /* software reset */
+ Menb = 0x40, /* memory enable */
+};
+
+enum { /* Icr */
+ Bit16 = 0x01, /* 16-bit bus */
+ Other = 0x02, /* other register access */
+ Ir2 = 0x04, /* IR2 */
+ Msz = 0x08, /* SRAM size */
+ Rla = 0x10, /* recall LAN address */
+ Rx7 = 0x20, /* recall all but I/O and LAN address */
+ Rio = 0x40, /* recall I/O address from EEROM */
+ Sto = 0x80, /* non-volatile EEROM store */
+};
+
+enum { /* Laar */
+ ZeroWS16 = 0x20, /* zero wait states for 16-bit ops */
+ L16en = 0x40, /* enable 16-bit LAN operation */
+ M16en = 0x80, /* enable 16-bit memory access */
+};
+
+enum { /* Ijr */
+ Ienable = 0x01, /* 8216 interrupt enable */
+};
+
+/*
+ * Mapping from configuration bits to interrupt level.
+ */
+static int irq8003[8] = {
+ 9, 3, 5, 7, 10, 11, 15, 4,
+};
+
+static int irq8216[8] = {
+ 0, 9, 3, 5, 7, 10, 11, 15,
+};
+
+static void
+reset8003(Ether* ether, uchar ea[Eaddrlen], uchar ic[8])
+{
+ Dp8390 *ctlr;
+ ulong port;
+
+ ctlr = ether->ctlr;
+ port = ether->port;
+
+ /*
+ * Check for old, dumb 8003E, which doesn't have an interface
+ * chip. Only Msr exists out of the 1st eight registers, reads
+ * of the others just alias the 2nd eight registers, the LAN
+ * address ROM. Can check Icr, Irr and Laar against the ethernet
+ * address read above and if they match it's an 8003E (or an
+ * 8003EBT, 8003S, 8003SH or 8003WT, doesn't matter), in which
+ * case the default irq gets used.
+ */
+ if(memcmp(&ea[1], &ic[1], 5) == 0){
+ memset(ic, 0, sizeof(ic));
+ ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
+ }
+ else{
+ /*
+ * As a final sanity check for the 8013EBT, which doesn't have
+ * the 83C584 interface chip, but has 2 real registers, write Gp2
+ * and if it reads back the same, it's not an 8013EBT.
+ */
+ outb(port+Gp2, 0xAA);
+ inb(port+Msr); /* wiggle bus */
+ if(inb(port+Gp2) != 0xAA){
+ memset(ic, 0, sizeof(ic));
+ ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
+ }
+ else
+ ether->irq = irq8003[((ic[Irr]>>5) & 0x3)|(ic[Icr] & 0x4)];
+
+ /*
+ * Check if 16-bit card.
+ * If Bit16 is read/write, then it's an 8-bit card.
+ * If Bit16 is set, it's in a 16-bit slot.
+ */
+ outb(port+Icr, ic[Icr]^Bit16);
+ inb(port+Msr); /* wiggle bus */
+ if((inb(port+Icr) & Bit16) == (ic[Icr] & Bit16)){
+ ctlr->width = 2;
+ ic[Icr] &= ~Bit16;
+ }
+ outb(port+Icr, ic[Icr]);
+
+ if(ctlr->width == 2 && (inb(port+Icr) & Bit16) == 0)
+ ctlr->width = 1;
+ }
+
+ ether->mem = (ulong)KADDR((ic[Msr] & 0x3F)<<13);
+ if(ctlr->width == 2)
+ ether->mem |= (ic[Laar] & 0x1F)<<19;
+ else
+ ether->mem |= 0x80000;
+
+ if(ic[Icr] & (1<<3))
+ ether->size = 32*1024;
+ if(ctlr->width == 2)
+ ether->size <<= 1;
+
+ /*
+ * Enable interface RAM, set interface width.
+ */
+ outb(port+Msr, ic[Msr]|Menb);
+ if(ctlr->width == 2)
+ outb(port+Laar, ic[Laar]|L16en|M16en|ZeroWS16);
+}
+
+static void
+reset8216(Ether* ether, uchar[8])
+{
+ uchar hcr, irq, x;
+ ulong addr, port;
+ Dp8390 *ctlr;
+
+ ctlr = ether->ctlr;
+ port = ether->port;
+
+ ctlr->width = 2;
+
+ /*
+ * Switch to the alternate register set and retrieve the memory
+ * and irq information.
+ */
+ hcr = inb(port+Hcr);
+ outb(port+Hcr, 0x80|hcr);
+ addr = inb(port+0x0B) & 0xFF;
+ irq = inb(port+0x0D);
+ outb(port+Hcr, hcr);
+
+ ether->mem = (ulong)KADDR(0xC0000+((((addr>>2) & 0x30)|(addr & 0x0F))<<13));
+ ether->size = 8192*(1<<((addr>>4) & 0x03));
+ ether->irq = irq8216[((irq>>4) & 0x04)|((irq>>2) & 0x03)];
+
+ /*
+ * Enable interface RAM, set interface width, and enable interrupts.
+ */
+ x = inb(port+Msr) & ~Rst;
+ outb(port+Msr, Menb|x);
+ x = inb(port+Laar);
+ outb(port+Laar, M16en|x);
+ outb(port+Ijr, Ienable);
+}
+
+/*
+ * Get configuration parameters, enable memory.
+ * There are opportunities here for buckets of code, try to resist.
+ */
+int
+wd8003reset(Ether* ether)
+{
+ int i;
+ uchar ea[Eaddrlen], ic[8], id, nullea[Eaddrlen], sum;
+ ulong port;
+ Dp8390 *ctlr;
+
+ /*
+ * Set up the software configuration.
+ * Use defaults for port, irq, mem and size if not specified.
+ * Defaults are set for the dumb 8003E which can't be
+ * autoconfigured.
+ */
+ if(ether->port == 0)
+ ether->port = 0x280;
+ if(ether->irq == 0)
+ ether->irq = 3;
+ if(ether->mem == 0)
+ ether->mem = 0xD0000;
+ if(ether->size == 0)
+ ether->size = 8*1024;
+
+ /*
+ * Look for the interface. Read the LAN address ROM
+ * and validate the checksum - the sum of all 8 bytes
+ * should be 0xFF.
+ * At the same time, get the (possible) interface chip
+ * registers, they'll be used later to check for aliasing.
+ */
+ port = ether->port;
+ sum = 0;
+ for(i = 0; i < sizeof(ea); i++){
+ ea[i] = inb(port+Lar+i);
+ sum += ea[i];
+ ic[i] = inb(port+i);
+ }
+ id = inb(port+Id);
+ sum += id;
+ sum += inb(port+Cksum);
+ if(sum != 0xFF)
+ return -1;
+
+ ether->ctlr = malloc(sizeof(Dp8390));
+ ctlr = ether->ctlr;
+ ctlr->ram = 1;
+
+ if((id & 0xFE) == 0x2A)
+ reset8216(ether, ic);
+ else
+ reset8003(ether, ea, ic);
+
+ /*
+ * Set the DP8390 ring addresses.
+ */
+ ctlr->port = port+0x10;
+ ctlr->tstart = 0;
+ ctlr->pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
+ ctlr->pstop = HOWMANY(ether->size, Dp8390BufSz);
+
+ /*
+ * Finally, init the 8390, set the ethernet address
+ * and claim the memory used.
+ */
+ dp8390reset(ether);
+ memset(nullea, 0, Eaddrlen);
+ if(memcmp(nullea, ether->ea, Eaddrlen) == 0){
+ for(i = 0; i < sizeof(ether->ea); i++)
+ ether->ea[i] = ea[i];
+ }
+ dp8390setea(ether);
+
+ if(umbrwmalloc(PADDR(ether->mem), ether->size, 0) == 0)
+ print("ether8003: warning - 0x%luX unavailable", PADDR(ether->mem));
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether8139.c
@@ -1,0 +1,614 @@
+/*
+ * Realtek 8139 (but not the 8129).
+ * Error recovery for the various over/under -flow conditions
+ * may need work.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+enum { /* registers */
+ Idr0 = 0x0000, /* MAC address */
+ Mar0 = 0x0008, /* Multicast address */
+ Tsd0 = 0x0010, /* Transmit Status Descriptor0 */
+ Tsad0 = 0x0020, /* Transmit Start Address Descriptor0 */
+ Rbstart = 0x0030, /* Receive Buffer Start Address */
+ Erbcr = 0x0034, /* Early Receive Byte Count */
+ Ersr = 0x0036, /* Early Receive Status */
+ Cr = 0x0037, /* Command Register */
+ Capr = 0x0038, /* Current Address of Packet Read */
+ Cbr = 0x003A, /* Current Buffer Address */
+ Imr = 0x003C, /* Interrupt Mask */
+ Isr = 0x003E, /* Interrupt Status */
+ Tcr = 0x0040, /* Transmit Configuration */
+ Rcr = 0x0044, /* Receive Configuration */
+ Tctr = 0x0048, /* Timer Count */
+ Mpc = 0x004C, /* Missed Packet Counter */
+ Cr9346 = 0x0050, /* 9346 Command Register */
+ Config0 = 0x0051, /* Configuration Register 0 */
+ Config1 = 0x0052, /* Configuration Register 1 */
+ TimerInt = 0x0054, /* Timer Interrupt */
+ Msr = 0x0058, /* Media Status */
+ Config3 = 0x0059, /* Configuration Register 3 */
+ Config4 = 0x005A, /* Configuration Register 4 */
+ Mulint = 0x005C, /* Multiple Interrupt Select */
+ RerID = 0x005E, /* PCI Revision ID */
+ Tsad = 0x0060, /* Transmit Status of all Descriptors */
+
+ Bmcr = 0x0062, /* Basic Mode Control */
+ Bmsr = 0x0064, /* Basic Mode Status */
+ Anar = 0x0066, /* Auto-Negotiation Advertisment */
+ Anlpar = 0x0068, /* Auto-Negotiation Link Partner */
+ Aner = 0x006A, /* Auto-Negotiation Expansion */
+ Dis = 0x006C, /* Disconnect Counter */
+ Fcsc = 0x006E, /* False Carrier Sense Counter */
+ Nwaytr = 0x0070, /* N-way Test */
+ Rec = 0x0072, /* RX_ER Counter */
+ Cscr = 0x0074, /* CS Configuration */
+ Phy1parm = 0x0078, /* PHY Parameter 1 */
+ Twparm = 0x007C, /* Twister Parameter */
+ Phy2parm = 0x0080, /* PHY Parameter 2 */
+};
+
+enum { /* Cr */
+ Bufe = 0x01, /* Rx Buffer Empty */
+ Te = 0x04, /* Transmitter Enable */
+ Re = 0x08, /* Receiver Enable */
+ Rst = 0x10, /* Software Reset */
+};
+
+enum { /* Imr/Isr */
+ Rok = 0x0001, /* Receive OK */
+ Rer = 0x0002, /* Receive Error */
+ Tok = 0x0004, /* Transmit OK */
+ Ter = 0x0008, /* Transmit Error */
+ Rxovw = 0x0010, /* Receive Buffer Overflow */
+ PunLc = 0x0020, /* Packet Underrun or Link Change */
+ Fovw = 0x0040, /* Receive FIFO Overflow */
+ Clc = 0x2000, /* Cable Length Change */
+ Timer = 0x4000, /* Timer */
+ Serr = 0x8000, /* System Error */
+};
+
+enum { /* Tcr */
+ Clrabt = 0x00000001, /* Clear Abort */
+ TxrrSHIFT = 4, /* Transmit Retry Count */
+ TxrrMASK = 0x000000F0,
+ MtxdmaSHIFT = 8, /* Max. DMA Burst Size */
+ MtxdmaMASK = 0x00000700,
+ Mtxdma2048 = 0x00000700,
+ Acrc = 0x00010000, /* Append CRC (not) */
+ LbkSHIFT = 17, /* Loopback Test */
+ LbkMASK = 0x00060000,
+ IfgSHIFT = 24, /* Interframe Gap */
+ IfgMASK = 0x03000000,
+ HwveridSHIFT = 22, /* Hardware Version ID */
+ HwveridMASK = 0x7CC00000,
+};
+
+enum { /* Rcr */
+ Aap = 0x00000001, /* Accept All Packets */
+ Apm = 0x00000002, /* Accept Physical Match */
+ Am = 0x00000004, /* Accept Multicast */
+ Ab = 0x00000008, /* Accept Broadcast */
+ Ar = 0x00000010, /* Accept Runt */
+ Aer = 0x00000020, /* Accept Error */
+ Sel9356 = 0x00000040, /* 9356 EEPROM used */
+ Wrap = 0x00000080, /* Rx Buffer Wrap Control */
+ MrxdmaSHIFT = 8, /* Max. DMA Burst Size */
+ MrxdmaMASK = 0x00000700,
+ Mrxdmaunlimited = 0x00000700,
+ RblenSHIFT = 11, /* Receive Buffer Length */
+ RblenMASK = 0x00001800,
+ Rblen8K = 0x00000000, /* 8KB+16 */
+ Rblen16K = 0x00000800, /* 16KB+16 */
+ Rblen32K = 0x00001000, /* 32KB+16 */
+ Rblen64K = 0x00001800, /* 64KB+16 */
+ RxfthSHIFT = 13, /* Receive Buffer Length */
+ RxfthMASK = 0x0000E000,
+ Rxfth256 = 0x00008000,
+ Rxfthnone = 0x0000E000,
+ Rer8 = 0x00010000, /* Accept Error Packets > 8 bytes */
+ MulERINT = 0x00020000, /* Multiple Early Interrupt Select */
+ ErxthSHIFT = 24, /* Early Rx Threshold */
+ ErxthMASK = 0x0F000000,
+ Erxthnone = 0x00000000,
+};
+
+enum { /* Received Packet Status */
+ Rcok = 0x0001, /* Receive Completed OK */
+ Fae = 0x0002, /* Frame Alignment Error */
+ Crc = 0x0004, /* CRC Error */
+ Long = 0x0008, /* Long Packet */
+ Runt = 0x0010, /* Runt Packet Received */
+ Ise = 0x0020, /* Invalid Symbol Error */
+ Bar = 0x2000, /* Broadcast Address Received */
+ Pam = 0x4000, /* Physical Address Matched */
+ Mar = 0x8000, /* Multicast Address Received */
+};
+
+enum { /* Media Status Register */
+ Rxpf = 0x01, /* Pause Flag */
+ Txpf = 0x02, /* Pause Flag */
+ Linkb = 0x04, /* Inverse of Link Status */
+ Speed10 = 0x08, /* 10Mbps */
+ Auxstatus = 0x10, /* Aux. Power Present Status */
+ Rxfce = 0x40, /* Receive Flow Control Enable */
+ Txfce = 0x80, /* Transmit Flow Control Enable */
+};
+
+typedef struct { /* Soft Transmit Descriptor */
+ int tsd;
+ int tsad;
+ uchar* data;
+} Td;
+
+enum { /* Tsd0 */
+ SizeSHIFT = 0, /* Descriptor Size */
+ SizeMASK = 0x00001FFF,
+ Own = 0x00002000,
+ Tun = 0x00004000, /* Transmit FIFO Underrun */
+ Tcok = 0x00008000, /* Transmit COmpleted OK */
+ EtxthSHIFT = 16, /* Early Tx Threshold */
+ EtxthMASK = 0x001F0000,
+ NccSHIFT = 24, /* Number of Collisions Count */
+ NccMASK = 0x0F000000,
+ Cdh = 0x10000000, /* CD Heartbeat */
+ Owc = 0x20000000, /* Out of Window Collision */
+ Tabt = 0x40000000, /* Transmit Abort */
+ Crs = 0x80000000, /* Carrier Sense Lost */
+};
+
+enum {
+ Rblen = Rblen64K, /* Receive Buffer Length */
+ Ntd = 4, /* Number of Transmit Descriptors */
+ Tdbsz = ROUNDUP(sizeof(Etherpkt), 4),
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id;
+
+ Lock ilock; /* init */
+ void* alloc; /* base of per-Ctlr allocated data */
+
+ int rcr; /* receive configuration register */
+ uchar* rbstart; /* receive buffer */
+ int rblen; /* receive buffer length */
+ int ierrs; /* receive errors */
+
+ Lock tlock; /* transmit */
+ Td td[Ntd];
+ int ntd; /* descriptors active */
+ int tdh; /* host index into td */
+ int tdi; /* interface index into td */
+ int etxth; /* early transmit threshold */
+ int taligned; /* packet required no alignment */
+ int tunaligned; /* packet required alignment */
+
+ int dis; /* disconnect counter */
+ int fcsc; /* false carrier sense counter */
+ int rec; /* RX_ER counter */
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr8r(c, r) (inb((c)->port+(r)))
+#define csr16r(c, r) (ins((c)->port+(r)))
+#define csr32r(c, r) (inl((c)->port+(r)))
+#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
+#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
+#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
+
+static int
+rtl8139reset(Ctlr* ctlr)
+{
+ /*
+ * Soft reset the controller.
+ */
+ csr8w(ctlr, Cr, Rst);
+ while(csr8r(ctlr, Cr) & Rst)
+ ;
+
+ return 0;
+}
+
+static void
+rtl8139detach(Ether* edev)
+{
+ rtl8139reset(edev->ctlr);
+}
+
+static void
+rtl8139halt(Ctlr* ctlr)
+{
+ csr8w(ctlr, Cr, 0);
+ csr16w(ctlr, Imr, 0);
+ csr16w(ctlr, Isr, ~0);
+}
+
+static void
+rtl8139init(Ether* edev)
+{
+ int i;
+ ulong r;
+ Ctlr *ctlr;
+ uchar *alloc;
+
+ ctlr = edev->ctlr;
+ ilock(&ctlr->ilock);
+
+ rtl8139halt(ctlr);
+
+ /*
+ * MAC Address.
+ */
+ r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
+ csr32w(ctlr, Idr0, r);
+ r = (edev->ea[5]<<8)|edev->ea[4];
+ csr32w(ctlr, Idr0+4, r);
+
+ /*
+ * Receiver
+ */
+ alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 32);
+ ctlr->rbstart = alloc;
+ alloc += ctlr->rblen+16;
+ memset(ctlr->rbstart, 0, ctlr->rblen+16);
+ csr32w(ctlr, Rbstart, PADDR(ctlr->rbstart));
+ ctlr->rcr = Rxfth256|Rblen|Mrxdmaunlimited|Ab|Apm;
+
+ /*
+ * Transmitter.
+ */
+ for(i = 0; i < Ntd; i++){
+ ctlr->td[i].tsd = Tsd0+i*4;
+ ctlr->td[i].tsad = Tsad0+i*4;
+ ctlr->td[i].data = alloc;
+ alloc += Tdbsz;
+ }
+ ctlr->ntd = ctlr->tdh = ctlr->tdi = 0;
+ ctlr->etxth = 128/32;
+
+ /*
+ * Interrupts.
+ */
+ csr32w(ctlr, TimerInt, 0);
+ csr16w(ctlr, Imr, Serr|Timer|Fovw|PunLc|Rxovw|Ter|Tok|Rer|Rok);
+ csr32w(ctlr, Mpc, 0);
+
+ /*
+ * Enable receiver/transmitter.
+ * Need to enable before writing the Rcr or it won't take.
+ */
+ csr8w(ctlr, Cr, Te|Re);
+ csr32w(ctlr, Tcr, Mtxdma2048);
+ csr32w(ctlr, Rcr, ctlr->rcr);
+
+ iunlock(&ctlr->ilock);
+}
+
+static void
+rtl8139attach(Ether* edev)
+{
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ if(ctlr->alloc == nil){
+ ctlr->rblen = 1<<((Rblen>>RblenSHIFT)+13);
+ ctlr->alloc = mallocz(ctlr->rblen+16 + Ntd*Tdbsz + 32, 0);
+ rtl8139init(edev);
+ }
+}
+
+static void
+rtl8139txstart(Ether* edev)
+{
+ Td *td;
+ Ctlr *ctlr;
+ RingBuf *tb;
+
+ ctlr = edev->ctlr;
+ while(ctlr->ntd < Ntd){
+ tb = &edev->tb[edev->ti];
+ if(tb->owner != Interface)
+ break;
+
+ td = &ctlr->td[ctlr->tdh];
+ memmove(td->data, tb->pkt, tb->len);
+ csr32w(ctlr, td->tsad, PADDR(tb->pkt));
+ csr32w(ctlr, td->tsd, (ctlr->etxth<<EtxthSHIFT)|tb->len);
+
+ ctlr->ntd++;
+ ctlr->tdh = NEXT(ctlr->tdh, Ntd);
+ tb->owner = Host;
+ edev->ti = NEXT(edev->ti, edev->ntb);
+ }
+}
+
+static void
+rtl8139transmit(Ether* edev)
+{
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ ilock(&ctlr->tlock);
+ rtl8139txstart(edev);
+ iunlock(&ctlr->tlock);
+}
+
+static void
+rtl8139receive(Ether* edev)
+{
+ Ctlr *ctlr;
+ RingBuf *rb;
+ ushort capr;
+ uchar cr, *p;
+ int l, length, status;
+
+ ctlr = edev->ctlr;
+
+ /*
+ * Capr is where the host is reading from,
+ * Cbr is where the NIC is currently writing.
+ */
+ capr = (csr16r(ctlr, Capr)+16) % ctlr->rblen;
+ while(!(csr8r(ctlr, Cr) & Bufe)){
+ p = ctlr->rbstart+capr;
+
+ /*
+ * Apparently the packet length may be 0xFFF0 if
+ * the NIC is still copying the packet into memory.
+ */
+ length = (*(p+3)<<8)|*(p+2);
+ if(length == 0xFFF0)
+ break;
+ status = (*(p+1)<<8)|*p;
+
+ if(!(status & Rcok)){
+ /*
+ * Reset the receiver.
+ * Also may have to restore the multicast list
+ * here too if it ever gets used.
+ */
+ cr = csr8r(ctlr, Cr);
+ csr8w(ctlr, Cr, cr & ~Re);
+ csr32w(ctlr, Rbstart, PADDR(ctlr->rbstart));
+ csr8w(ctlr, Cr, cr);
+ csr32w(ctlr, Rcr, ctlr->rcr);
+
+ continue;
+ }
+
+ /*
+ * Receive Completed OK.
+ * Very simplistic; there are ways this could be done
+ * without copying, but the juice probably isn't worth
+ * the squeeze.
+ * The packet length includes a 4 byte CRC on the end.
+ */
+ capr = (capr+4) % ctlr->rblen;
+ p = ctlr->rbstart+capr;
+ capr = (capr+length) % ctlr->rblen;
+
+ rb = &edev->rb[edev->ri];
+ l = 0;
+ if(p+length >= ctlr->rbstart+ctlr->rblen){
+ l = ctlr->rbstart+ctlr->rblen - p;
+ if(rb->owner == Interface)
+ memmove(rb->pkt, p, l);
+ length -= l;
+ p = ctlr->rbstart;
+ }
+ if(length > 0 && rb->owner == Interface){
+ memmove(rb->pkt+l, p, length);
+ l += length;
+ }
+ if(rb->owner == Interface){
+ rb->owner = Host;
+ rb->len = l-4;
+ edev->ri = NEXT(edev->ri, edev->nrb);
+ }
+
+ capr = ROUNDUP(capr, 4);
+ csr16w(ctlr, Capr, capr-16);
+ }
+}
+
+static void
+rtl8139interrupt(Ureg*, void* arg)
+{
+ Td *td;
+ Ctlr *ctlr;
+ Ether *edev;
+ int isr, tsd;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ while((isr = csr16r(ctlr, Isr)) != 0){
+ csr16w(ctlr, Isr, isr);
+ if(isr & (Fovw|PunLc|Rxovw|Rer|Rok)){
+ rtl8139receive(edev);
+ if(!(isr & Rok))
+ ctlr->ierrs++;
+ isr &= ~(Fovw|Rxovw|Rer|Rok);
+ }
+
+ if(isr & (Ter|Tok)){
+ ilock(&ctlr->tlock);
+ while(ctlr->ntd){
+ td = &ctlr->td[ctlr->tdi];
+ tsd = csr32r(ctlr, td->tsd);
+ if(!(tsd & (Tabt|Tun|Tcok)))
+ break;
+
+ if(!(tsd & Tcok)){
+ if(tsd & Tun){
+ if(ctlr->etxth < ETHERMAXTU/32)
+ ctlr->etxth++;
+ }
+ }
+
+ ctlr->ntd--;
+ ctlr->tdi = NEXT(ctlr->tdi, Ntd);
+ }
+ rtl8139txstart(edev);
+ iunlock(&ctlr->tlock);
+ isr &= ~(Ter|Tok);
+ }
+
+ if(isr & PunLc)
+ isr &= ~(Clc|PunLc);
+
+ /*
+ * Only Serr|Timer should be left by now.
+ * Should anything be done to tidy up? TimerInt isn't
+ * used so that can be cleared. A PCI bus error is indicated
+ * by Serr, that's pretty serious; is there anyhing to do
+ * other than try to reinitialise the chip?
+ */
+ if((isr & (Serr|Timer)) != 0){
+ print("rtl8139interrupt: imr %4.4uX isr %4.4uX\n",
+ csr16r(ctlr, Imr), isr);
+ if(isr & Timer)
+ csr32w(ctlr, TimerInt, 0);
+ if(isr & Serr)
+ rtl8139init(edev);
+ }
+ }
+}
+
+static Ctlr*
+rtl8139match(Ether* edev, int id)
+{
+ int port;
+ Pcidev *p;
+ Ctlr *ctlr;
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ p = ctlr->pcidev;
+ if(((p->did<<16)|p->vid) != id)
+ continue;
+ port = p->mem[0].bar & ~0x01;
+ if(edev->port != 0 && edev->port != port)
+ continue;
+
+ ctlr->port = port;
+ if(rtl8139reset(ctlr))
+ continue;
+ pcisetbme(p);
+
+ ctlr->active = 1;
+ return ctlr;
+ }
+ return nil;
+}
+
+static struct {
+ char* name;
+ int id;
+} rtl8139pci[] = {
+ { "rtl8139", (0x8139<<16)|0x10EC, }, /* generic */
+ { "smc1211", (0x1211<<16)|0x1113, }, /* SMC EZ-Card */
+ { "dfe-538tx", (0x1300<<16)|0x1186, }, /* D-Link DFE-538TX */
+ { "dfe-560txd", (0x1340<<16)|0x1186, }, /* D-Link DFE-560TXD */
+ { nil },
+};
+
+int
+rtl8139pnp(Ether* edev)
+{
+ int i, id;
+ Pcidev *p;
+ Ctlr *ctlr;
+ uchar ea[Eaddrlen];
+
+ /*
+ * Make a list of all ethernet controllers
+ * if not already done.
+ */
+ if(ctlrhead == nil){
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->pcidev = p;
+ ctlr->id = (p->did<<16)|p->vid;
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+ }
+
+ /*
+ * Is it an RTL8139 under a different name?
+ * Normally a search is made through all the found controllers
+ * for one which matches any of the known vid+did pairs.
+ * If a vid+did pair is specified a search is made for that
+ * specific controller only.
+ */
+ id = 0;
+ for(i = 0; i < edev->nopt; i++){
+ if(cistrncmp(edev->opt[i], "id=", 3) == 0)
+ id = strtol(&edev->opt[i][3], nil, 0);
+ }
+
+ ctlr = nil;
+ if(id != 0)
+ ctlr = rtl8139match(edev, id);
+ else for(i = 0; rtl8139pci[i].name; i++){
+ if((ctlr = rtl8139match(edev, rtl8139pci[i].id)) != nil)
+ break;
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the device and set in edev->ea.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, edev->ea, Eaddrlen) == 0){
+ i = csr32r(ctlr, Idr0);
+ edev->ea[0] = i;
+ edev->ea[1] = i>>8;
+ edev->ea[2] = i>>16;
+ edev->ea[3] = i>>24;
+ i = csr32r(ctlr, Idr0+4);
+ edev->ea[4] = i;
+ edev->ea[5] = i>>8;
+ }
+
+ edev->attach = rtl8139attach;
+ edev->transmit = rtl8139transmit;
+ edev->interrupt = rtl8139interrupt;
+ edev->detach = rtl8139detach;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether8169.c
@@ -1,0 +1,958 @@
+/*
+ * Realtek RTL8110S/8169S.
+ * Mostly there. There are some magic register values used
+ * which are not described in any datasheet or driver but seem
+ * to be necessary.
+ * Why is the Fovf descriptor bit set for every received packet?
+ * Occasionally the hardware indicates an input TCP checksum error
+ * although the higher-level software seems to check the packet OK?
+ * No tuning has been done. Only tested on an RTL8110S, there
+ * are slight differences between the chips in the series so some
+ * tweaks may be needed.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+typedef struct QLock { int r; } QLock;
+#define qlock(i) while(0)
+#define qunlock(i) while(0)
+#define iallocb allocb
+#define iprint print
+#define mallocalign(n, a, o, s) ialloc((n), (a))
+
+#include "etherif.h"
+#include "ethermii.h"
+
+enum { /* registers */
+ Idr0 = 0x00, /* MAC address */
+ Mar0 = 0x08, /* Multicast address */
+ Dtccr = 0x10, /* Dump Tally Counter Command */
+ Tnpds = 0x20, /* Transmit Normal Priority Descriptors */
+ Thpds = 0x28, /* Transmit High Priority Descriptors */
+ Flash = 0x30, /* Flash Memory Read/Write */
+ Erbcr = 0x34, /* Early Receive Byte Count */
+ Ersr = 0x36, /* Early Receive Status */
+ Cr = 0x37, /* Command Register */
+ Tppoll = 0x38, /* Transmit Priority Polling */
+ Imr = 0x3C, /* Interrupt Mask */
+ Isr = 0x3E, /* Interrupt Status */
+ Tcr = 0x40, /* Transmit Configuration */
+ Rcr = 0x44, /* Receive Configuration */
+ Tctr = 0x48, /* Timer Count */
+ Mpc = 0x4C, /* Missed Packet Counter */
+ Cr9346 = 0x50, /* 9346 Command Register */
+ Config0 = 0x51, /* Configuration Register 0 */
+ Config1 = 0x52, /* Configuration Register 1 */
+ Config2 = 0x53, /* Configuration Register 2 */
+ Config3 = 0x54, /* Configuration Register 3 */
+ Config4 = 0x55, /* Configuration Register 4 */
+ Config5 = 0x56, /* Configuration Register 5 */
+ Timerint = 0x58, /* Timer Interrupt */
+ Mulint = 0x5C, /* Multiple Interrupt Select */
+ Phyar = 0x60, /* PHY Access */
+ Tbicsr0 = 0x64, /* TBI Control and Status */
+ Tbianar = 0x68, /* TBI Auto-Negotiation Advertisment */
+ Tbilpar = 0x6A, /* TBI Auto-Negotiation Link Partner */
+ Phystatus = 0x6C, /* PHY Status */
+
+ Rms = 0xDA, /* Receive Packet Maximum Size */
+ Cplusc = 0xE0, /* C+ Command */
+ Rdsar = 0xE4, /* Receive Descriptor Start Address */
+ Mtps = 0xEC, /* Max. Transmit Packet Size */
+};
+
+enum { /* Dtccr */
+ Cmd = 0x00000008, /* Command */
+};
+
+enum { /* Cr */
+ Te = 0x04, /* Transmitter Enable */
+ Re = 0x08, /* Receiver Enable */
+ Rst = 0x10, /* Software Reset */
+};
+
+enum { /* Tppoll */
+ Fswint = 0x01, /* Forced Software Interrupt */
+ Npq = 0x40, /* Normal Priority Queue polling */
+ Hpq = 0x80, /* High Priority Queue polling */
+};
+
+enum { /* Imr/Isr */
+ Rok = 0x0001, /* Receive OK */
+ Rer = 0x0002, /* Receive Error */
+ Tok = 0x0004, /* Transmit OK */
+ Ter = 0x0008, /* Transmit Error */
+ Rdu = 0x0010, /* Receive Descriptor Unavailable */
+ Punlc = 0x0020, /* Packet Underrun or Link Change */
+ Fovw = 0x0040, /* Receive FIFO Overflow */
+ Tdu = 0x0080, /* Transmit Descriptor Unavailable */
+ Swint = 0x0100, /* Software Interrupt */
+ Timeout = 0x4000, /* Timer */
+ Serr = 0x8000, /* System Error */
+};
+
+enum { /* Tcr */
+ MtxdmaSHIFT = 8, /* Max. DMA Burst Size */
+ MtxdmaMASK = 0x00000700,
+ Mtxdmaunlimited = 0x00000700,
+ Acrc = 0x00010000, /* Append CRC (not) */
+ Lbk0 = 0x00020000, /* Loopback Test 0 */
+ Lbk1 = 0x00040000, /* Loopback Test 1 */
+ Ifg2 = 0x00080000, /* Interframe Gap 2 */
+ HwveridSHIFT = 23, /* Hardware Version ID */
+ HwveridMASK = 0x7C800000,
+ Macv01 = 0x00000000, /* RTL8169 */
+ Macv02 = 0x00800000, /* RTL8169S/8110S */
+ Macv03 = 0x04000000, /* RTL8169S/8110S */
+ Macv04 = 0x10000000, /* RTL8169SB/8110SB */
+ Macv05 = 0x18000000, /* RTL8169SC/8110SC */
+ Macv11 = 0x30000000, /* RTL8168B/8111B */
+ Macv12 = 0x38000000, /* RTL8169B/8111B */
+ Macv13 = 0x34000000, /* RTL8101E */
+ Macv14 = 0x30800000, /* RTL8100E */
+ Macv15 = 0x38800000, /* RTL8100E */
+ Ifg0 = 0x01000000, /* Interframe Gap 0 */
+ Ifg1 = 0x02000000, /* Interframe Gap 1 */
+};
+
+enum { /* Rcr */
+ Aap = 0x00000001, /* Accept All Packets */
+ Apm = 0x00000002, /* Accept Physical Match */
+ Am = 0x00000004, /* Accept Multicast */
+ Ab = 0x00000008, /* Accept Broadcast */
+ Ar = 0x00000010, /* Accept Runt */
+ Aer = 0x00000020, /* Accept Error */
+ Sel9356 = 0x00000040, /* 9356 EEPROM used */
+ MrxdmaSHIFT = 8, /* Max. DMA Burst Size */
+ MrxdmaMASK = 0x00000700,
+ Mrxdmaunlimited = 0x00000700,
+ RxfthSHIFT = 13, /* Receive Buffer Length */
+ RxfthMASK = 0x0000E000,
+ Rxfth256 = 0x00008000,
+ Rxfthnone = 0x0000E000,
+ Rer8 = 0x00010000, /* Accept Error Packets > 8 bytes */
+ MulERINT = 0x01000000, /* Multiple Early Interrupt Select */
+};
+
+enum { /* Cr9346 */
+ Eedo = 0x01, /* */
+ Eedi = 0x02, /* */
+ Eesk = 0x04, /* */
+ Eecs = 0x08, /* */
+ Eem0 = 0x40, /* Operating Mode */
+ Eem1 = 0x80,
+};
+
+enum { /* Phyar */
+ DataMASK = 0x0000FFFF, /* 16-bit GMII/MII Register Data */
+ DataSHIFT = 0,
+ RegaddrMASK = 0x001F0000, /* 5-bit GMII/MII Register Address */
+ RegaddrSHIFT = 16,
+ Flag = 0x80000000, /* */
+};
+
+enum { /* Phystatus */
+ Fd = 0x01, /* Full Duplex */
+ Linksts = 0x02, /* Link Status */
+ Speed10 = 0x04, /* */
+ Speed100 = 0x08, /* */
+ Speed1000 = 0x10, /* */
+ Rxflow = 0x20, /* */
+ Txflow = 0x40, /* */
+ Entbi = 0x80, /* */
+};
+
+enum { /* Cplusc */
+ Mulrw = 0x0008, /* PCI Multiple R/W Enable */
+ Dac = 0x0010, /* PCI Dual Address Cycle Enable */
+ Rxchksum = 0x0020, /* Receive Checksum Offload Enable */
+ Rxvlan = 0x0040, /* Receive VLAN De-tagging Enable */
+ Endian = 0x0200, /* Endian Mode */
+};
+
+typedef struct D D; /* Transmit/Receive Descriptor */
+struct D {
+ u32 control;
+ u32 vlan;
+ u32 addrlo;
+ u32 addrhi;
+};
+
+enum { /* Transmit Descriptor control */
+ TxflMASK = 0x0000FFFF, /* Transmit Frame Length */
+ TxflSHIFT = 0,
+ Tcps = 0x00010000, /* TCP Checksum Offload */
+ Udpcs = 0x00020000, /* UDP Checksum Offload */
+ Ipcs = 0x00040000, /* IP Checksum Offload */
+ Lgsen = 0x08000000, /* Large Send */
+};
+
+enum { /* Receive Descriptor control */
+ RxflMASK = 0x00003FFF, /* Receive Frame Length */
+ RxflSHIFT = 0,
+ Tcpf = 0x00004000, /* TCP Checksum Failure */
+ Udpf = 0x00008000, /* UDP Checksum Failure */
+ Ipf = 0x00010000, /* IP Checksum Failure */
+ Pid0 = 0x00020000, /* Protocol ID0 */
+ Pid1 = 0x00040000, /* Protocol ID1 */
+ Crce = 0x00080000, /* CRC Error */
+ Runt = 0x00100000, /* Runt Packet */
+ Res = 0x00200000, /* Receive Error Summary */
+ Rwt = 0x00400000, /* Receive Watchdog Timer Expired */
+ Fovf = 0x00800000, /* FIFO Overflow */
+ Bovf = 0x01000000, /* Buffer Overflow */
+ Bar = 0x02000000, /* Broadcast Address Received */
+ Pam = 0x04000000, /* Physical Address Matched */
+ Mar = 0x08000000, /* Multicast Address Received */
+};
+
+enum { /* General Descriptor control */
+ Ls = 0x10000000, /* Last Segment Descriptor */
+ Fs = 0x20000000, /* First Segment Descriptor */
+ Eor = 0x40000000, /* End of Descriptor Ring */
+ Own = 0x80000000, /* Ownership */
+};
+
+/*
+ */
+enum { /* Ring sizes (<= 1024) */
+ Ntd = 8, /* Transmit Ring */
+ Nrd = 32, /* Receive Ring */
+
+ Mps = ROUNDUP(ETHERMAXTU+4, 128),
+};
+
+typedef struct Dtcc Dtcc;
+struct Dtcc {
+ u64int txok;
+ u64int rxok;
+ u64int txer;
+ u32 rxer;
+ u16int misspkt;
+ u16int fae;
+ u32 tx1col;
+ u32 txmcol;
+ u64int rxokph;
+ u64int rxokbrd;
+ u32 rxokmu;
+ u16int txabt;
+ u16int txundrn;
+};
+
+enum { /* Variants */
+ Rtl8100e = (0x8136<<16)|0x10EC, /* RTL810[01]E ? */
+ Rtl8169c = (0x0116<<16)|0x16EC, /* RTL8169C+ (USR997902) */
+ Rtl8169sc = (0x8167<<16)|0x10EC, /* RTL8169SC */
+ Rtl8168b = (0x8168<<16)|0x10EC, /* RTL8168B */
+ Rtl8169 = (0x8169<<16)|0x10EC, /* RTL8169 */
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+
+ void* nic;
+
+ QLock alock; /* attach */
+ Lock ilock; /* init */
+ int init; /* */
+
+ int pciv; /* */
+ int macv; /* MAC version */
+ int phyv; /* PHY version */
+
+ Mii* mii;
+
+ Lock tlock; /* transmit */
+ D* td; /* descriptor ring */
+ Block** tb; /* transmit buffers */
+ int ntd;
+
+ int tdh; /* head - producer index (host) */
+ int tdt; /* tail - consumer index (NIC) */
+ int ntdfree;
+ int ntq;
+
+ int mtps; /* Max. Transmit Packet Size */
+
+ Lock rlock; /* receive */
+ D* rd; /* descriptor ring */
+ void** rb; /* receive buffers */
+ int nrd;
+
+ int rdh; /* head - producer index (NIC) */
+ int rdt; /* tail - consumer index (host) */
+ int nrdfree;
+
+ int rcr; /* receive configuration register */
+
+ QLock slock; /* statistics */
+ Dtcc* dtcc;
+ uint txdu;
+ uint tcpf;
+ uint udpf;
+ uint ipf;
+ uint fovf;
+ uint ierrs;
+ uint rer;
+ uint rdu;
+ uint punlc;
+ uint fovw;
+} Ctlr;
+
+static Ctlr* rtl8169ctlrhead;
+static Ctlr* rtl8169ctlrtail;
+
+#define csr8r(c, r) (inb((c)->port+(r)))
+#define csr16r(c, r) (ins((c)->port+(r)))
+#define csr32r(c, r) (inl((c)->port+(r)))
+#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
+#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
+#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
+
+static int
+rtl8169miimir(Mii* mii, int pa, int ra)
+{
+ uint r;
+ int timeo;
+ Ctlr *ctlr;
+
+ if(pa != 1)
+ return -1;
+ ctlr = mii->ctlr;
+
+ r = (ra<<16) & RegaddrMASK;
+ csr32w(ctlr, Phyar, r);
+ delay(1);
+ for(timeo = 0; timeo < 2000; timeo++){
+ if((r = csr32r(ctlr, Phyar)) & Flag)
+ break;
+ microdelay(100);
+ }
+ if(!(r & Flag))
+ return -1;
+
+ return (r & DataMASK)>>DataSHIFT;
+}
+
+static int
+rtl8169miimiw(Mii* mii, int pa, int ra, int data)
+{
+ uint r;
+ int timeo;
+ Ctlr *ctlr;
+
+ if(pa != 1)
+ return -1;
+ ctlr = mii->ctlr;
+
+ r = Flag|((ra<<16) & RegaddrMASK)|((data<<DataSHIFT) & DataMASK);
+ csr32w(ctlr, Phyar, r);
+ delay(1);
+ for(timeo = 0; timeo < 2000; timeo++){
+ if(!((r = csr32r(ctlr, Phyar)) & Flag))
+ break;
+ microdelay(100);
+ }
+ if(r & Flag)
+ return -1;
+
+ return 0;
+}
+
+static int
+rtl8169mii(Ctlr* ctlr)
+{
+ MiiPhy *phy;
+
+ /*
+ * Link management.
+ */
+ if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+ return -1;
+ ctlr->mii->mir = rtl8169miimir;
+ ctlr->mii->miw = rtl8169miimiw;
+ ctlr->mii->ctlr = ctlr;
+
+ /*
+ * Get rev number out of Phyidr2 so can config properly.
+ * There's probably more special stuff for Macv0[234] needed here.
+ */
+ ctlr->phyv = rtl8169miimir(ctlr->mii, 1, Phyidr2) & 0x0F;
+ if(ctlr->macv == Macv02){
+ csr8w(ctlr, 0x82, 1); /* magic */
+ rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000); /* magic */
+ }
+
+ if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){
+ free(ctlr->mii);
+ ctlr->mii = nil;
+ return -1;
+ }
+ print("oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
+ phy->oui, phy->phyno, ctlr->macv, ctlr->phyv);
+
+ miiane(ctlr->mii, ~0, ~0, ~0);
+
+ return 0;
+}
+
+static void
+rtl8169halt(Ctlr* ctlr)
+{
+ csr8w(ctlr, Cr, 0);
+ csr16w(ctlr, Imr, 0);
+ csr16w(ctlr, Isr, ~0);
+}
+
+static int
+rtl8169reset(Ctlr* ctlr)
+{
+ u32 r;
+ int timeo;
+
+ /*
+ * Soft reset the controller.
+ */
+ csr8w(ctlr, Cr, Rst);
+ for(r = timeo = 0; timeo < 1000; timeo++){
+ r = csr8r(ctlr, Cr);
+ if(!(r & Rst))
+ break;
+ delay(1);
+ }
+ rtl8169halt(ctlr);
+
+ if(r & Rst)
+ return -1;
+ return 0;
+}
+
+static void
+rtl8169detach(Ether* edev)
+{
+ rtl8169reset(edev->ctlr);
+}
+
+static void
+rtl8169replenish(Ctlr* ctlr)
+{
+ D *d;
+ int rdt;
+ void *bp;
+
+ rdt = ctlr->rdt;
+ while(NEXT(rdt, ctlr->nrd) != ctlr->rdh){
+ d = &ctlr->rd[rdt];
+ if(ctlr->rb[rdt] == nil){
+ /*
+ * simple allocation for now
+ */
+ bp = mallocalign(Mps, 8, 0, 0);
+ ctlr->rb[rdt] = bp;
+ d->addrlo = PCIWADDR(bp);
+ d->addrhi = 0;
+ }
+ coherence();
+ d->control |= Own|Mps;
+ rdt = NEXT(rdt, ctlr->nrd);
+ ctlr->nrdfree++;
+ }
+ ctlr->rdt = rdt;
+}
+
+static int
+rtl8169init(Ether* edev)
+{
+ u32 r;
+ Ctlr *ctlr;
+ u8int cplusc;
+
+ ctlr = edev->ctlr;
+ ilock(&ctlr->ilock);
+
+ rtl8169halt(ctlr);
+
+ /*
+ * MAC Address.
+ * Must put chip into config register write enable mode.
+ */
+ csr8w(ctlr, Cr9346, Eem1|Eem0);
+ r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
+ csr32w(ctlr, Idr0, r);
+ r = (edev->ea[5]<<8)|edev->ea[4];
+ csr32w(ctlr, Idr0+4, r);
+
+ /*
+ * Transmitter.
+ */
+ memset(ctlr->td, 0, sizeof(D)*ctlr->ntd);
+ ctlr->tdh = ctlr->tdt = 0;
+ ctlr->td[ctlr->ntd-1].control = Eor;
+
+ /*
+ * Receiver.
+ * Need to do something here about the multicast filter.
+ */
+ memset(ctlr->rd, 0, sizeof(D)*ctlr->nrd);
+ ctlr->rdh = ctlr->rdt = 0;
+ ctlr->rd[ctlr->nrd-1].control = Eor;
+ rtl8169replenish(ctlr);
+ ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Apm;
+
+ /*
+ * Mtps is in units of 128 except for the RTL8169
+ * where is is 32. If using jumbo frames should be
+ * set to 0x3F.
+ * Setting Mulrw in Cplusc disables the Tx/Rx DMA burst
+ * settings in Tcr/Rcr; the (1<<14) is magic.
+ */
+ ctlr->mtps = HOWMANY(Mps, 128);
+ cplusc = csr16r(ctlr, Cplusc) & ~(1<<14);
+ cplusc |= Rxchksum|Mulrw;
+ switch(ctlr->macv){
+ default:
+ return -1;
+ case Macv01:
+ ctlr->mtps = HOWMANY(Mps, 32);
+ break;
+ case Macv02:
+ case Macv03:
+ cplusc |= (1<<14); /* magic */
+ break;
+ case Macv05:
+ /*
+ * This is interpreted from clearly bogus code
+ * in the manufacturer-supplied driver, it could
+ * be wrong. Untested.
+ */
+ r = csr8r(ctlr, Config2) & 0x07;
+ if(r == 0x01) /* 66MHz PCI */
+ csr32w(ctlr, 0x7C, 0x0007FFFF); /* magic */
+ else
+ csr32w(ctlr, 0x7C, 0x0007FF00); /* magic */
+ pciclrmwi(ctlr->pcidev);
+ break;
+ case Macv13:
+ /*
+ * This is interpreted from clearly bogus code
+ * in the manufacturer-supplied driver, it could
+ * be wrong. Untested.
+ */
+ pcicfgw8(ctlr->pcidev, 0x68, 0x00); /* magic */
+ pcicfgw8(ctlr->pcidev, 0x69, 0x08); /* magic */
+ break;
+ case Macv04:
+ case Macv11:
+ case Macv12:
+ case Macv14:
+ case Macv15:
+ break;
+ }
+
+ /*
+ * Enable receiver/transmitter.
+ * Need to do this first or some of the settings below
+ * won't take.
+ */
+ switch(ctlr->pciv){
+ default:
+ csr8w(ctlr, Cr, Te|Re);
+ csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+ csr32w(ctlr, Rcr, ctlr->rcr);
+ case Rtl8169sc:
+ case Rtl8168b:
+ break;
+ }
+
+ /*
+ * Interrupts.
+ * Disable Tdu|Tok for now, the transmit routine will tidy.
+ * Tdu means the NIC ran out of descriptors to send, so it
+ * doesn't really need to ever be on.
+ */
+ csr32w(ctlr, Timerint, 0);
+ csr16w(ctlr, Imr, Serr|Timeout|Fovw|Punlc|Rdu|Ter|Rer|Rok);
+
+ /*
+ * Clear missed-packet counter;
+ * initial early transmit threshold value;
+ * set the descriptor ring base addresses;
+ * set the maximum receive packet size;
+ * no early-receive interrupts.
+ */
+ csr32w(ctlr, Mpc, 0);
+ csr8w(ctlr, Mtps, ctlr->mtps);
+ csr32w(ctlr, Tnpds+4, 0);
+ csr32w(ctlr, Tnpds, PCIWADDR(ctlr->td));
+ csr32w(ctlr, Rdsar+4, 0);
+ csr32w(ctlr, Rdsar, PCIWADDR(ctlr->rd));
+ csr16w(ctlr, Rms, Mps);
+ r = csr16r(ctlr, Mulint) & 0xF000;
+ csr16w(ctlr, Mulint, r);
+ csr16w(ctlr, Cplusc, cplusc);
+
+ /*
+ * Set configuration.
+ */
+ switch(ctlr->pciv){
+ default:
+ break;
+ case Rtl8169sc:
+ csr16w(ctlr, 0xE2, 0); /* magic */
+ csr8w(ctlr, Cr, Te|Re);
+ csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+ csr32w(ctlr, Rcr, ctlr->rcr);
+ break;
+ case Rtl8168b:
+ case Rtl8169c:
+ csr16w(ctlr, 0xE2, 0); /* magic */
+ csr16w(ctlr, Cplusc, 0x2000); /* magic */
+ csr8w(ctlr, Cr, Te|Re);
+ csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+ csr32w(ctlr, Rcr, ctlr->rcr);
+ csr16w(ctlr, Rms, 0x0800);
+ csr8w(ctlr, Mtps, 0x3F);
+ break;
+ }
+
+ csr8w(ctlr, Cr9346, 0);
+
+ iunlock(&ctlr->ilock);
+
+// rtl8169mii(ctlr);
+
+ return 0;
+}
+
+static void
+rtl8169attach(Ether* edev)
+{
+ int timeo;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ qlock(&ctlr->alock);
+ if(ctlr->init == 0){
+ /*
+ * Handle allocation/init errors here.
+ */
+ ctlr->td = xspanalloc(sizeof(D)*Ntd, 256, 0);
+ ctlr->tb = malloc(Ntd*sizeof(Block*));
+ ctlr->ntd = Ntd;
+ ctlr->rd = xspanalloc(sizeof(D)*Nrd, 256, 0);
+ ctlr->rb = malloc(Nrd*sizeof(Block*));
+ ctlr->nrd = Nrd;
+ ctlr->dtcc = xspanalloc(sizeof(Dtcc), 64, 0);
+ rtl8169init(edev);
+ ctlr->init = 1;
+ }
+ qunlock(&ctlr->alock);
+
+ for(timeo = 0; timeo < 3500; timeo++){
+ if(miistatus(ctlr->mii) == 0)
+ break;
+ delay(10);
+ }
+}
+
+static void
+rtl8169transmit(Ether* edev)
+{
+ D *d;
+ Block *bp;
+ Ctlr *ctlr;
+ int control, x;
+ RingBuf *tb;
+
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->tlock);
+ for(x = ctlr->tdh; ctlr->ntq > 0; x = NEXT(x, ctlr->ntd)){
+ d = &ctlr->td[x];
+ if((control = d->control) & Own)
+ break;
+
+ /*
+ * Check errors and log here.
+ */
+ USED(control);
+
+ /*
+ * Free it up.
+ * Need to clean the descriptor here? Not really.
+ * Simple freeb for now (no chain and freeblist).
+ * Use ntq count for now.
+ */
+ freeb(ctlr->tb[x]);
+ ctlr->tb[x] = nil;
+ d->control &= Eor;
+
+ ctlr->ntq--;
+ }
+ ctlr->tdh = x;
+
+ x = ctlr->tdt;
+ while(ctlr->ntq < (ctlr->ntd-1)){
+ tb = &edev->tb[edev->ti];
+ if(tb->owner != Interface)
+ break;
+
+ bp = allocb(tb->len);
+ memmove(bp->wp, tb->pkt, tb->len);
+ memmove(bp->wp+Eaddrlen, edev->ea, Eaddrlen);
+ bp->wp += tb->len;
+
+ tb->owner = Host;
+ edev->ti = NEXT(edev->ti, edev->ntb);
+
+ d = &ctlr->td[x];
+ d->addrlo = PCIWADDR(bp->rp);
+ d->addrhi = 0;
+ ctlr->tb[x] = bp;
+ coherence();
+ d->control |= Own|Fs|Ls|((BLEN(bp)<<TxflSHIFT) & TxflMASK);
+
+ x = NEXT(x, ctlr->ntd);
+ ctlr->ntq++;
+ }
+ if(x != ctlr->tdt){
+ ctlr->tdt = x;
+ csr8w(ctlr, Tppoll, Npq);
+ }
+ else if(ctlr->ntq >= (ctlr->ntd-1))
+ ctlr->txdu++;
+
+ iunlock(&ctlr->tlock);
+}
+
+static void
+rtl8169receive(Ether* edev)
+{
+ D *d;
+ int len, rdh;
+ Ctlr *ctlr;
+ u32 control;
+ RingBuf *ring;
+
+ ctlr = edev->ctlr;
+
+ rdh = ctlr->rdh;
+ for(;;){
+ d = &ctlr->rd[rdh];
+
+ if(d->control & Own)
+ break;
+
+ control = d->control;
+ if((control & (Fs|Ls|Res)) == (Fs|Ls)){
+ len = ((control & RxflMASK)>>RxflSHIFT) - 4;
+
+ ring = &edev->rb[edev->ri];
+ if(ring->owner == Interface){
+ ring->owner = Host;
+ ring->len = len;
+ memmove(ring->pkt, ctlr->rb[rdh], len);
+ edev->ri = NEXT(edev->ri, edev->nrb);
+ }
+ }
+ else{
+ /*
+ * Error stuff here.
+ print("control %#8.8ux\n", control);
+ */
+ }
+ d->control &= Eor;
+ ctlr->nrdfree--;
+ rdh = NEXT(rdh, ctlr->nrd);
+ }
+ ctlr->rdh = rdh;
+
+ if(ctlr->nrdfree < ctlr->nrd/2)
+ rtl8169replenish(ctlr);
+}
+
+static void
+rtl8169interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *edev;
+ u32 isr;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ while((isr = csr16r(ctlr, Isr)) != 0 && isr != 0xFFFF){
+ csr16w(ctlr, Isr, isr);
+ if(isr & (Fovw|Punlc|Rdu|Rer|Rok)){
+ rtl8169receive(edev);
+ if(!(isr & (Punlc|Rok)))
+ ctlr->ierrs++;
+ if(isr & Rer)
+ ctlr->rer++;
+ if(isr & Rdu)
+ ctlr->rdu++;
+ if(isr & Punlc)
+ ctlr->punlc++;
+ if(isr & Fovw)
+ ctlr->fovw++;
+ isr &= ~(Fovw|Rdu|Rer|Rok);
+ }
+
+ if(isr & (Tdu|Ter|Tok)){
+ rtl8169transmit(edev);
+ isr &= ~(Tdu|Ter|Tok);
+ }
+
+ if(isr & Punlc){
+// rtl8169link(edev);
+ isr &= ~Punlc;
+ }
+
+ /*
+ * Some of the reserved bits get set sometimes...
+ */
+ if(isr & (Serr|Timeout|Tdu|Fovw|Punlc|Rdu|Ter|Tok|Rer|Rok))
+ panic("rtl8169interrupt: imr %#4.4ux isr %#4.4ux\n",
+ csr16r(ctlr, Imr), isr);
+ }
+}
+
+static void
+rtl8169pci(void)
+{
+ Pcidev *p;
+ Ctlr *ctlr;
+ int i, port;
+ u32 bar;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+
+ switch(i = ((p->did<<16)|p->vid)){
+ default:
+ continue;
+ case Rtl8100e: /* RTL810[01]E ? */
+ case Rtl8169c: /* RTL8169C */
+ case Rtl8169sc: /* RTL8169SC */
+ case Rtl8168b: /* RTL8168B */
+ case Rtl8169: /* RTL8169 */
+ break;
+ case (0xC107<<16)|0x1259: /* Corega CG-LAPCIGT */
+ i = Rtl8169;
+ break;
+ }
+
+ bar = p->mem[0].bar;
+ port = bar & ~0x01;
+ if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){
+ print("rtl8169: port %#ux in use\n", port);
+ continue;
+ }
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = port;
+ ctlr->pcidev = p;
+ ctlr->pciv = i;
+
+ if(pcigetpms(p) > 0){
+ pcisetpms(p, 0);
+
+ for(i = 0; i < 6; i++)
+ pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
+ pcicfgw8(p, PciINTL, p->intl);
+ pcicfgw8(p, PciLTR, p->ltr);
+ pcicfgw8(p, PciCLS, p->cls);
+ pcicfgw16(p, PciPCR, p->pcr);
+ }
+
+ if(rtl8169reset(ctlr)){
+ iofree(port);
+ free(ctlr);
+ continue;
+ }
+
+ /*
+ * Extract the chip hardware version,
+ * needed to configure each properly.
+ */
+ ctlr->macv = csr32r(ctlr, Tcr) & HwveridMASK;
+
+ rtl8169mii(ctlr);
+
+ pcisetbme(p);
+
+ if(rtl8169ctlrhead != nil)
+ rtl8169ctlrtail->next = ctlr;
+ else
+ rtl8169ctlrhead = ctlr;
+ rtl8169ctlrtail = ctlr;
+ }
+}
+
+int
+rtl8169pnp(Ether* edev)
+{
+ u32 r;
+ Ctlr *ctlr;
+
+ if(rtl8169ctlrhead == nil)
+ rtl8169pci();
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = rtl8169ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+// edev->mbps = 100;
+
+ /*
+ * Pull the MAC address out of the chip.
+ */
+ r = csr32r(ctlr, Idr0);
+ edev->ea[0] = r;
+ edev->ea[1] = r>>8;
+ edev->ea[2] = r>>16;
+ edev->ea[3] = r>>24;
+ r = csr32r(ctlr, Idr0+4);
+ edev->ea[4] = r;
+ edev->ea[5] = r>>8;
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ edev->attach = rtl8169attach;
+ edev->transmit = rtl8169transmit;
+ edev->interrupt = rtl8169interrupt;
+ edev->detach = rtl8169detach;
+// edev->ifstat = rtl8169ifstat;
+// edev->ctl = nil;
+//
+// edev->arg = edev;
+// edev->promiscuous = rtl8169promiscuous;
+// edev->multicast = rtl8169multicast;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether82557.c
@@ -1,0 +1,882 @@
+/*
+ * Intel 82557 Fast Ethernet PCI Bus LAN Controller
+ * as found on the Intel EtherExpress PRO/100B. This chip is full
+ * of smarts, unfortunately none of them are in the right place.
+ * To do:
+ * the PCI scanning code could be made common to other adapters;
+ * PCI code needs rewritten to handle byte, word, dword accesses
+ * and using the devno as a bus+dev+function triplet.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+enum {
+ Nrfd = 4, /* receive frame area */
+
+ NullPointer = 0xFFFFFFFF, /* 82557 NULL pointer */
+};
+
+enum { /* CSR */
+ Status = 0x00, /* byte or word (word includes Ack) */
+ Ack = 0x01, /* byte */
+ CommandR = 0x02, /* byte or word (word includes Interrupt) */
+ Interrupt = 0x03, /* byte */
+ Pointer = 0x04, /* dword */
+ Port = 0x08, /* dword */
+ Fcr = 0x0C, /* Flash control register */
+ Ecr = 0x0E, /* EEPROM control register */
+ Mcr = 0x10, /* MDI control register */
+};
+
+enum { /* Status */
+ RUidle = 0x0000,
+ RUsuspended = 0x0004,
+ RUnoresources = 0x0008,
+ RUready = 0x0010,
+ RUrbd = 0x0020, /* bit */
+ RUstatus = 0x003F, /* mask */
+
+ CUidle = 0x0000,
+ CUsuspended = 0x0040,
+ CUactive = 0x0080,
+ CUstatus = 0x00C0, /* mask */
+
+ StatSWI = 0x0400, /* SoftWare generated Interrupt */
+ StatMDI = 0x0800, /* MDI r/w done */
+ StatRNR = 0x1000, /* Receive unit Not Ready */
+ StatCNA = 0x2000, /* Command unit Not Active (Active->Idle) */
+ StatFR = 0x4000, /* Finished Receiving */
+ StatCX = 0x8000, /* Command eXecuted */
+ StatTNO = 0x8000, /* Transmit NOT OK */
+};
+
+enum { /* Command (byte) */
+ CUnop = 0x00,
+ CUstart = 0x10,
+ CUresume = 0x20,
+ LoadDCA = 0x40, /* Load Dump Counters Address */
+ DumpSC = 0x50, /* Dump Statistical Counters */
+ LoadCUB = 0x60, /* Load CU Base */
+ ResetSA = 0x70, /* Dump and Reset Statistical Counters */
+
+ RUstart = 0x01,
+ RUresume = 0x02,
+ RUabort = 0x04,
+ LoadHDS = 0x05, /* Load Header Data Size */
+ LoadRUB = 0x06, /* Load RU Base */
+ RBDresume = 0x07, /* Resume frame reception */
+};
+
+enum { /* Interrupt (byte) */
+ InterruptM = 0x01, /* interrupt Mask */
+ InterruptSI = 0x02, /* Software generated Interrupt */
+};
+
+enum { /* Ecr */
+ EEsk = 0x01, /* serial clock */
+ EEcs = 0x02, /* chip select */
+ EEdi = 0x04, /* serial data in */
+ EEdo = 0x08, /* serial data out */
+
+ EEstart = 0x04, /* start bit */
+ EEread = 0x02, /* read opcode */
+};
+
+enum { /* Mcr */
+ MDIread = 0x08000000, /* read opcode */
+ MDIwrite = 0x04000000, /* write opcode */
+ MDIready = 0x10000000, /* ready bit */
+ MDIie = 0x20000000, /* interrupt enable */
+};
+
+typedef struct Rfd {
+ int field;
+ ulong link;
+ ulong rbd;
+ ushort count;
+ ushort size;
+
+ Etherpkt;
+} Rfd;
+
+enum { /* field */
+ RfdCollision = 0x00000001,
+ RfdIA = 0x00000002, /* IA match */
+ RfdRxerr = 0x00000010, /* PHY character error */
+ RfdType = 0x00000020, /* Type frame */
+ RfdRunt = 0x00000080,
+ RfdOverrun = 0x00000100,
+ RfdBuffer = 0x00000200,
+ RfdAlignment = 0x00000400,
+ RfdCRC = 0x00000800,
+
+ RfdOK = 0x00002000, /* frame received OK */
+ RfdC = 0x00008000, /* reception Complete */
+ RfdSF = 0x00080000, /* Simplified or Flexible (1) Rfd */
+ RfdH = 0x00100000, /* Header RFD */
+
+ RfdI = 0x20000000, /* Interrupt after completion */
+ RfdS = 0x40000000, /* Suspend after completion */
+ RfdEL = 0x80000000, /* End of List */
+};
+
+enum { /* count */
+ RfdF = 0x00004000,
+ RfdEOF = 0x00008000,
+};
+
+typedef struct Cb {
+ int command;
+ ulong link;
+ uchar data[24]; /* CbIAS + CbConfigure */
+} Cb;
+
+typedef struct TxCB {
+ int command;
+ ulong link;
+ ulong tbd;
+ ushort count;
+ uchar threshold;
+ uchar number;
+} TxCB;
+
+enum { /* action command */
+ CbOK = 0x00002000, /* DMA completed OK */
+ CbC = 0x00008000, /* execution Complete */
+
+ CbNOP = 0x00000000,
+ CbIAS = 0x00010000, /* Indvidual Address Setup */
+ CbConfigure = 0x00020000,
+ CbMAS = 0x00030000, /* Multicast Address Setup */
+ CbTransmit = 0x00040000,
+ CbDump = 0x00060000,
+ CbDiagnose = 0x00070000,
+ CbCommand = 0x00070000, /* mask */
+
+ CbSF = 0x00080000, /* CbTransmit */
+
+ CbI = 0x20000000, /* Interrupt after completion */
+ CbS = 0x40000000, /* Suspend after completion */
+ CbEL = 0x80000000, /* End of List */
+};
+
+enum { /* CbTransmit count */
+ CbEOF = 0x00008000,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+
+ int eepromsz; /* address size in bits */
+ ushort* eeprom;
+
+ int ctlrno;
+ char* type;
+
+ uchar configdata[24];
+
+ Rfd rfd[Nrfd];
+ int rfdl;
+ int rfdx;
+
+ Block* cbqhead;
+ Block* cbqtail;
+ int cbqbusy;
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+static uchar configdata[24] = {
+ 0x16, /* byte count */
+ 0x44, /* Rx/Tx FIFO limit */
+ 0x00, /* adaptive IFS */
+ 0x00,
+ 0x04, /* Rx DMA maximum byte count */
+ 0x84, /* Tx DMA maximum byte count */
+ 0x33, /* late SCB, CNA interrupts */
+ 0x01, /* discard short Rx frames */
+ 0x00, /* 503/MII */
+
+ 0x00,
+ 0x2E, /* normal operation, NSAI */
+ 0x00, /* linear priority */
+ 0x60, /* inter-frame spacing */
+ 0x00,
+ 0xF2,
+ 0x48, /* promiscuous mode off */
+ 0x00,
+ 0x40,
+ 0xF2, /* transmit padding enable */
+ 0x80, /* full duplex pin enable */
+ 0x3F, /* no Multi IA */
+ 0x05, /* no Multi Cast ALL */
+};
+
+#define csr8r(c, r) (inb((c)->port+(r)))
+#define csr16r(c, r) (ins((c)->port+(r)))
+#define csr32r(c, r) (inl((c)->port+(r)))
+#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
+#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
+#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
+
+static void
+custart(Ctlr* ctlr)
+{
+ if(ctlr->cbqhead == 0){
+ ctlr->cbqbusy = 0;
+ return;
+ }
+ ctlr->cbqbusy = 1;
+
+ csr32w(ctlr, Pointer, PADDR(ctlr->cbqhead->rp));
+ while(csr8r(ctlr, CommandR))
+ ;
+ csr8w(ctlr, CommandR, CUstart);
+}
+
+static void
+action(Ctlr* ctlr, Block* bp)
+{
+ Cb *cb;
+
+ cb = (Cb*)bp->rp;
+ cb->command |= CbEL;
+
+ if(ctlr->cbqhead){
+ ctlr->cbqtail->next = bp;
+ cb = (Cb*)ctlr->cbqtail->rp;
+ cb->link = PADDR(bp->rp);
+ cb->command &= ~CbEL;
+ }
+ else
+ ctlr->cbqhead = bp;
+ ctlr->cbqtail = bp;
+
+ if(ctlr->cbqbusy == 0)
+ custart(ctlr);
+}
+
+static void
+attach(Ether* ether)
+{
+ int status;
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ status = csr16r(ctlr, Status);
+ if((status & RUstatus) == RUidle){
+ csr32w(ctlr, Pointer, PADDR(&ctlr->rfd[ctlr->rfdx]));
+ while(csr8r(ctlr, CommandR))
+ ;
+ csr8w(ctlr, CommandR, RUstart);
+ }
+}
+
+static void
+configure(void* arg, int promiscuous)
+{
+ Ctlr *ctlr;
+ Block *bp;
+ Cb *cb;
+
+ ctlr = ((Ether*)arg)->ctlr;
+
+ bp = allocb(sizeof(Cb));
+ cb = (Cb*)bp->rp;
+ bp->wp += sizeof(Cb);
+
+ cb->command = CbConfigure;
+ cb->link = NullPointer;
+ memmove(cb->data, ctlr->configdata, sizeof(ctlr->configdata));
+ if(promiscuous)
+ cb->data[15] |= 0x01;
+ action(ctlr, bp);
+}
+
+static void
+transmit(Ether* ether)
+{
+ Block *bp;
+ TxCB *txcb;
+ RingBuf *tb;
+
+ for(tb = ðer->tb[ether->ti]; tb->owner == Interface; tb = ðer->tb[ether->ti]){
+ bp = allocb(tb->len+sizeof(TxCB));
+ txcb = (TxCB*)bp->wp;
+ bp->wp += sizeof(TxCB);
+
+ txcb->command = CbTransmit;
+ txcb->link = NullPointer;
+ txcb->tbd = NullPointer;
+ txcb->count = CbEOF|tb->len;
+ txcb->threshold = 2;
+ txcb->number = 0;
+
+ memmove(bp->wp, tb->pkt, tb->len);
+ memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+ bp->wp += tb->len;
+
+ action(ether->ctlr, bp);
+
+ tb->owner = Host;
+ ether->ti = NEXT(ether->ti, ether->ntb);
+ }
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Rfd *rfd;
+ Block *bp;
+ Ctlr *ctlr;
+ Ether *ether;
+ int status;
+ RingBuf *rb;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ for(;;){
+ status = csr16r(ctlr, Status);
+ csr8w(ctlr, Ack, (status>>8) & 0xFF);
+
+ if((status & (StatCX|StatFR|StatCNA|StatRNR)) == 0)
+ return;
+
+ if(status & StatFR){
+ rfd = &ctlr->rfd[ctlr->rfdx];
+ while(rfd->field & RfdC){
+ rb = ðer->rb[ether->ri];
+ if(rb->owner == Interface){
+ rb->owner = Host;
+ rb->len = rfd->count & 0x3FFF;
+ memmove(rb->pkt, rfd->d, rfd->count & 0x3FFF);
+ ether->ri = NEXT(ether->ri, ether->nrb);
+ }
+
+ /*
+ * Reinitialise the frame for reception and bump
+ * the receive frame processing index;
+ * bump the sentinel index, mark the new sentinel
+ * and clear the old sentinel suspend bit;
+ * set bp and rfd for the next receive frame to
+ * process.
+ */
+ rfd->field = 0;
+ rfd->count = 0;
+ ctlr->rfdx = NEXT(ctlr->rfdx, Nrfd);
+
+ rfd = &ctlr->rfd[ctlr->rfdl];
+ ctlr->rfdl = NEXT(ctlr->rfdl, Nrfd);
+ ctlr->rfd[ctlr->rfdl].field |= RfdS;
+ rfd->field &= ~RfdS;
+
+ rfd = &ctlr->rfd[ctlr->rfdx];
+ }
+ status &= ~StatFR;
+ }
+
+ if(status & StatRNR){
+ while(csr8r(ctlr, CommandR))
+ ;
+ csr8w(ctlr, CommandR, RUresume);
+
+ status &= ~StatRNR;
+ }
+
+ if(status & StatCNA){
+ while(bp = ctlr->cbqhead){
+ if((((Cb*)bp->rp)->command & CbC) == 0)
+ break;
+ ctlr->cbqhead = bp->next;
+ freeb(bp);
+ }
+ custart(ctlr);
+
+ status &= ~StatCNA;
+ }
+
+ if(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI))
+ panic("%s#%d: status %uX\n", ctlr->type, ctlr->ctlrno, status);
+ }
+}
+
+static void
+ctlrinit(Ctlr* ctlr)
+{
+ int i;
+ Rfd *rfd;
+ ulong link;
+
+ link = NullPointer;
+ for(i = Nrfd-1; i >= 0; i--){
+ rfd = &ctlr->rfd[i];
+
+ rfd->field = 0;
+ rfd->link = link;
+ link = PADDR(rfd);
+ rfd->rbd = NullPointer;
+ rfd->count = 0;
+ rfd->size = sizeof(Etherpkt);
+ }
+ ctlr->rfd[Nrfd-1].link = PADDR(&ctlr->rfd[0]);
+
+ ctlr->rfdl = 0;
+ ctlr->rfd[0].field |= RfdS;
+ ctlr->rfdx = 2;
+
+ memmove(ctlr->configdata, configdata, sizeof(configdata));
+}
+
+static int
+miir(Ctlr* ctlr, int phyadd, int regadd)
+{
+ int mcr, timo;
+
+ csr32w(ctlr, Mcr, MDIread|(phyadd<<21)|(regadd<<16));
+ mcr = 0;
+ for(timo = 64; timo; timo--){
+ mcr = csr32r(ctlr, Mcr);
+ if(mcr & MDIready)
+ break;
+ microdelay(1);
+ }
+
+ if(mcr & MDIready)
+ return mcr & 0xFFFF;
+
+ return -1;
+}
+
+static int
+miiw(Ctlr* ctlr, int phyadd, int regadd, int data)
+{
+ int mcr, timo;
+
+ csr32w(ctlr, Mcr, MDIwrite|(phyadd<<21)|(regadd<<16)|(data & 0xFFFF));
+ mcr = 0;
+ for(timo = 64; timo; timo--){
+ mcr = csr32r(ctlr, Mcr);
+ if(mcr & MDIready)
+ break;
+ microdelay(1);
+ }
+
+ if(mcr & MDIready)
+ return 0;
+
+ return -1;
+}
+
+static int
+hy93c46r(Ctlr* ctlr, int r)
+{
+ int data, i, op, size;
+
+ /*
+ * Hyundai HY93C46 or equivalent serial EEPROM.
+ * This sequence for reading a 16-bit register 'r'
+ * in the EEPROM is taken straight from Section
+ * 3.3.4.2 of the Intel 82557 User's Guide.
+ */
+reread:
+ csr16w(ctlr, Ecr, EEcs);
+ op = EEstart|EEread;
+ for(i = 2; i >= 0; i--){
+ data = (((op>>i) & 0x01)<<2)|EEcs;
+ csr16w(ctlr, Ecr, data);
+ csr16w(ctlr, Ecr, data|EEsk);
+ microdelay(1);
+ csr16w(ctlr, Ecr, data);
+ microdelay(1);
+ }
+
+ /*
+ * First time through must work out the EEPROM size.
+ */
+ if((size = ctlr->eepromsz) == 0)
+ size = 8;
+
+ for(size = size-1; size >= 0; size--){
+ data = (((r>>size) & 0x01)<<2)|EEcs;
+ csr16w(ctlr, Ecr, data);
+ csr16w(ctlr, Ecr, data|EEsk);
+ delay(1);
+ csr16w(ctlr, Ecr, data);
+ microdelay(1);
+ if(!(csr16r(ctlr, Ecr) & EEdo))
+ break;
+ }
+
+ data = 0;
+ for(i = 15; i >= 0; i--){
+ csr16w(ctlr, Ecr, EEcs|EEsk);
+ microdelay(1);
+ if(csr16r(ctlr, Ecr) & EEdo)
+ data |= (1<<i);
+ csr16w(ctlr, Ecr, EEcs);
+ microdelay(1);
+ }
+
+ csr16w(ctlr, Ecr, 0);
+
+ if(ctlr->eepromsz == 0){
+ ctlr->eepromsz = 8-size;
+ ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
+ goto reread;
+ }
+
+ return data;
+}
+
+static void
+i82557pci(void)
+{
+ Pcidev *p;
+ Ctlr *ctlr;
+
+ p = nil;
+ while(p = pcimatch(p, 0x8086, 0)){
+ switch(p->did){
+ default:
+ continue;
+ case 0x1031: /* Intel 82562EM */
+ case 0x1050: /* Intel 82562EZ */
+ case 0x1039: /* Intel 82801BD PRO/100 VE */
+ case 0x103A: /* Intel 82562 PRO/100 VE */
+ case 0x1064: /* Intel 82562 PRO/100 VE */
+ case 0x2449: /* Intel 82562ET */
+ case 0x1209: /* Intel 82559ER */
+ case 0x1229: /* Intel 8255[789] */
+ case 0x1030: /* Intel 82559 InBusiness 10/100 */
+ break;
+ }
+
+ /*
+ * bar[0] is the memory-mapped register address (4KB),
+ * bar[1] is the I/O port register address (32 bytes) and
+ * bar[2] is for the flash ROM (1MB).
+ */
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = p->mem[1].bar & ~0x01;
+ ctlr->pcidev = p;
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+
+ pcisetbme(p);
+ }
+}
+
+static void
+detach(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+
+ csr32w(ctlr, Port, 0);
+ delay(1);
+
+ while(csr8r(ctlr, CommandR))
+ ;
+}
+
+static int
+scanphy(Ctlr* ctlr)
+{
+ int i, oui, x;
+
+ for(i = 0; i < 32; i++){
+ if((oui = miir(ctlr, i, 2)) == -1 || oui == 0 || oui == 0xFFFF)
+ continue;
+ oui <<= 6;
+ x = miir(ctlr, i, 3);
+ oui |= x>>10;
+ //print("phy%d: oui %uX reg1 %uX\n", i, oui, miir(ctlr, i, 1));
+
+ if(oui == 0xAA00)
+ ctlr->eeprom[6] = 0x07<<8;
+ else if(oui == 0x80017){
+ if(x & 0x01)
+ ctlr->eeprom[6] = 0x0A<<8;
+ else
+ ctlr->eeprom[6] = 0x04<<8;
+ }
+ return i;
+ }
+ return -1;
+}
+
+int
+i82557reset(Ether* ether)
+{
+ int anar, anlpar, bmcr, bmsr, force, i, phyaddr, x;
+ unsigned short sum;
+ Block *bp;
+ uchar ea[Eaddrlen];
+ Ctlr *ctlr;
+ Cb *cb;
+
+
+ if(ctlrhead == nil)
+ i82557pci();
+
+ /*
+ * Any adapter matches if no ether->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(ether->port == 0 || ether->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ /*
+ * Initialise the Ctlr structure.
+ * Perform a software reset after which need to ensure busmastering
+ * is still enabled. The EtherExpress PRO/100B appears to leave
+ * the PCI configuration alone (see the 'To do' list above) so punt
+ * for now.
+ * Load the RUB and CUB registers for linear addressing (0).
+ */
+ ether->ctlr = ctlr;
+ ether->port = ctlr->port;
+ ether->irq = ctlr->pcidev->intl;
+ ether->tbdf = ctlr->pcidev->tbdf;
+ ctlr->ctlrno = ether->ctlrno;
+ ctlr->type = ether->type;
+
+ csr32w(ctlr, Port, 0);
+ delay(1);
+
+ while(csr8r(ctlr, CommandR))
+ ;
+ csr32w(ctlr, Pointer, 0);
+ csr8w(ctlr, CommandR, LoadRUB);
+ while(csr8r(ctlr, CommandR))
+ ;
+ csr8w(ctlr, CommandR, LoadCUB);
+
+ /*
+ * Initialise the action and receive frame areas.
+ */
+ ctlrinit(ctlr);
+
+ /*
+ * Read the EEPROM.
+ * Do a dummy read first to get the size
+ * and allocate ctlr->eeprom.
+ */
+ hy93c46r(ctlr, 0);
+ sum = 0;
+ for(i = 0; i < (1<<ctlr->eepromsz); i++){
+ x = hy93c46r(ctlr, i);
+ ctlr->eeprom[i] = x;
+ sum += x;
+ }
+ if(sum != 0xBABA)
+ print("#l%d: EEPROM checksum - 0x%4.4uX\n", ether->ctlrno, sum);
+
+ /*
+ * Eeprom[6] indicates whether there is a PHY and whether
+ * it's not 10Mb-only, in which case use the given PHY address
+ * to set any PHY specific options and determine the speed.
+ * Unfortunately, sometimes the EEPROM is blank except for
+ * the ether address and checksum; in this case look at the
+ * controller type and if it's am 82558 or 82559 it has an
+ * embedded PHY so scan for that.
+ * If no PHY, assume 82503 (serial) operation.
+ */
+ if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000))
+ phyaddr = ctlr->eeprom[6] & 0x00FF;
+ else
+ switch(ctlr->pcidev->rid){
+ case 0x01: /* 82557 A-step */
+ case 0x02: /* 82557 B-step */
+ case 0x03: /* 82557 C-step */
+ default:
+ phyaddr = -1;
+ break;
+ case 0x04: /* 82558 A-step */
+ case 0x05: /* 82558 B-step */
+ case 0x06: /* 82559 A-step */
+ case 0x07: /* 82559 B-step */
+ case 0x08: /* 82559 C-step */
+ case 0x09: /* 82559ER A-step */
+ phyaddr = scanphy(ctlr);
+ break;
+ }
+ if(phyaddr >= 0){
+ /*
+ * Resolve the highest common ability of the two
+ * link partners. In descending order:
+ * 0x0100 100BASE-TX Full Duplex
+ * 0x0200 100BASE-T4
+ * 0x0080 100BASE-TX
+ * 0x0040 10BASE-T Full Duplex
+ * 0x0020 10BASE-T
+ */
+ anar = miir(ctlr, phyaddr, 0x04);
+ anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;
+ anar &= anlpar;
+ bmcr = 0;
+ if(anar & 0x380)
+ bmcr = 0x2000;
+ if(anar & 0x0140)
+ bmcr |= 0x0100;
+
+ switch((ctlr->eeprom[6]>>8) & 0x001F){
+
+ case 0x04: /* DP83840 */
+ case 0x0A: /* DP83840A */
+ /*
+ * The DP83840[A] requires some tweaking for
+ * reliable operation.
+ * The manual says bit 10 should be unconditionally
+ * set although it supposedly only affects full-duplex
+ * operation (an & 0x0140).
+ */
+ x = miir(ctlr, phyaddr, 0x17) & ~0x0520;
+ x |= 0x0420;
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrcmp(ether->opt[i], "congestioncontrol"))
+ continue;
+ x |= 0x0100;
+ break;
+ }
+ miiw(ctlr, phyaddr, 0x17, x);
+
+ /*
+ * If the link partner can't autonegotiate, determine
+ * the speed from elsewhere.
+ */
+ if(anlpar == 0){
+ miir(ctlr, phyaddr, 0x01);
+ bmsr = miir(ctlr, phyaddr, 0x01);
+ x = miir(ctlr, phyaddr, 0x19);
+ if((bmsr & 0x0004) && !(x & 0x0040))
+ bmcr = 0x2000;
+ }
+ break;
+
+ case 0x07: /* Intel 82555 */
+ /*
+ * Auto-negotiation may fail if the other end is
+ * a DP83840A and the cable is short.
+ */
+ bmsr = miir(ctlr, phyaddr, 0x01);
+ if((miir(ctlr, phyaddr, 0) & 0x1000) && !(bmsr & 0x0020)){
+ miiw(ctlr, phyaddr, 0x1A, 0x2010);
+ x = miir(ctlr, phyaddr, 0);
+ miiw(ctlr, phyaddr, 0, 0x0200|x);
+ for(i = 0; i < 3000; i++){
+ delay(1);
+ if(miir(ctlr, phyaddr, 0x01) & 0x0020)
+ break;
+ }
+ miiw(ctlr, phyaddr, 0x1A, 0x2000);
+
+ anar = miir(ctlr, phyaddr, 0x04);
+ anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;
+ anar &= anlpar;
+ bmcr = 0;
+ if(anar & 0x380)
+ bmcr = 0x2000;
+ if(anar & 0x0140)
+ bmcr |= 0x0100;
+ }
+ break;
+ }
+
+ /*
+ * Force speed and duplex if no auto-negotiation.
+ */
+ if(anlpar == 0){
+ force = 0;
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrcmp(ether->opt[i], "fullduplex") == 0){
+ force = 1;
+ bmcr |= 0x0100;
+ ctlr->configdata[19] |= 0x40;
+ }
+ else if(cistrcmp(ether->opt[i], "speed") == 0){
+ force = 1;
+ x = strtol(ðer->opt[i][6], 0, 0);
+ if(x == 10)
+ bmcr &= ~0x2000;
+ else if(x == 100)
+ bmcr |= 0x2000;
+ else
+ force = 0;
+ }
+ }
+ if(force)
+ miiw(ctlr, phyaddr, 0x00, bmcr);
+ }
+
+ ctlr->configdata[8] = 1;
+ ctlr->configdata[15] &= ~0x80;
+ }
+ else{
+ ctlr->configdata[8] = 0;
+ ctlr->configdata[15] |= 0x80;
+ }
+
+ /*
+ * Load the chip configuration
+ */
+ configure(ether, 0);
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to loading
+ * the station address with the Individual Address Setup command.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+ for(i = 0; i < Eaddrlen/2; i++){
+ x = ctlr->eeprom[i];
+ ether->ea[2*i] = x & 0xFF;
+ ether->ea[2*i+1] = (x>>8) & 0xFF;
+ }
+ }
+
+ bp = allocb(sizeof(Cb));
+ cb = (Cb*)bp->rp;
+ bp->wp += sizeof(Cb);
+
+ cb->command = CbIAS;
+ cb->link = NullPointer;
+ memmove(cb->data, ether->ea, Eaddrlen);
+ action(ctlr, bp);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->detach = detach;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether82563.c
@@ -1,0 +1,977 @@
+/*
+ * bootstrap driver for
+ * Intel 82563, 82571, 82573 Gigabit Ethernet PCI-Express Controllers
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+/* compatibility with cpu kernels */
+#define iallocb allocb
+#ifndef CACHELINESZ
+#define CACHELINESZ 32 /* pentium & later */
+#endif
+
+/* from pci.c */
+enum
+{ /* command register pcidev->pcr */
+ IOen = 1<<0,
+ MEMen = 1<<1,
+ MASen = 1<<2,
+ MemWrInv = 1<<4,
+ PErrEn = 1<<6,
+ SErrEn = 1<<8,
+};
+
+/*
+ * these are in the order they appear in the manual, not numeric order.
+ * It was too hard to find them in the book. Ref 21489, rev 2.6
+ */
+
+enum {
+ /* General */
+
+ Ctrl = 0x00000000, /* Device Control */
+ Status = 0x00000008, /* Device Status */
+ Eec = 0x00000010, /* EEPROM/Flash Control/Data */
+ Eerd = 0x00000014, /* EEPROM Read */
+ Ctrlext = 0x00000018, /* Extended Device Control */
+ Fla = 0x0000001c, /* Flash Access */
+ Mdic = 0x00000020, /* MDI Control */
+ Seresctl = 0x00000024, /* Serdes ana */
+ Fcal = 0x00000028, /* Flow Control Address Low */
+ Fcah = 0x0000002C, /* Flow Control Address High */
+ Fct = 0x00000030, /* Flow Control Type */
+ Kumctrlsta = 0x00000034, /* Kumeran Controll and Status Register */
+ Vet = 0x00000038, /* VLAN EtherType */
+ Fcttv = 0x00000170, /* Flow Control Transmit Timer Value */
+ Txcw = 0x00000178, /* Transmit Configuration Word */
+ Rxcw = 0x00000180, /* Receive Configuration Word */
+ Ledctl = 0x00000E00, /* LED control */
+ Pba = 0x00001000, /* Packet Buffer Allocation */
+
+ /* Interrupt */
+
+ Icr = 0x000000C0, /* Interrupt Cause Read */
+ Ics = 0x000000C8, /* Interrupt Cause Set */
+ Ims = 0x000000D0, /* Interrupt Mask Set/Read */
+ Imc = 0x000000D8, /* Interrupt mask Clear */
+ Iam = 0x000000E0, /* Interrupt acknowledge Auto Mask */
+
+ /* Receive */
+
+ Rctl = 0x00000100, /* Receive Control */
+ Ert = 0x00002008, /* Early Receive Threshold (573[EVL] only) */
+ Fcrtl = 0x00002160, /* Flow Control RX Threshold Low */
+ Fcrth = 0x00002168, /* Flow Control Rx Threshold High */
+ Psrctl = 0x00002170, /* Packet Split Receive Control */
+ Rdbal = 0x00002800, /* Rdesc Base Address Low Queue 0 */
+ Rdbah = 0x00002804, /* Rdesc Base Address High Queue 0 */
+ Rdlen = 0x00002808, /* Receive Descriptor Length Queue 0 */
+ Rdh = 0x00002810, /* Receive Descriptor Head Queue 0 */
+ Rdt = 0x00002818, /* Receive Descriptor Tail Queue 0 */
+ Rdtr = 0x00002820, /* Receive Descriptor Timer Ring */
+ Rxdctl = 0x00002828, /* Receive Descriptor Control */
+ Radv = 0x0000282C, /* Receive Interrupt Absolute Delay Timer */
+ Rdbal1 = 0x00002900, /* Rdesc Base Address Low Queue 1 */
+ Rdbah1 = 0x00002804, /* Rdesc Base Address High Queue 1 */
+ Rdlen1 = 0x00002908, /* Receive Descriptor Length Queue 1 */
+ Rdh1 = 0x00002910, /* Receive Descriptor Head Queue 1 */
+ Rdt1 = 0x00002918, /* Receive Descriptor Tail Queue 1 */
+ Rxdctl1 = 0x00002928, /* Receive Descriptor Control Queue 1 */
+ Rsrpd = 0x00002c00, /* Receive Small Packet Detect */
+ Raid = 0x00002c08, /* Receive ACK interrupt delay */
+ Cpuvec = 0x00002c10, /* CPU Vector */
+ Rxcsum = 0x00005000, /* Receive Checksum Control */
+ Rfctl = 0x00005008, /* Receive Filter Control */
+ Mta = 0x00005200, /* Multicast Table Array */
+ Ral = 0x00005400, /* Receive Address Low */
+ Rah = 0x00005404, /* Receive Address High */
+ Vfta = 0x00005600, /* VLAN Filter Table Array */
+ Mrqc = 0x00005818, /* Multiple Receive Queues Command */
+ Rssim = 0x00005864, /* RSS Interrupt Mask */
+ Rssir = 0x00005868, /* RSS Interrupt Request */
+ Reta = 0x00005c00, /* Redirection Table */
+ Rssrk = 0x00005c80, /* RSS Random Key */
+
+ /* Transmit */
+
+ Tctl = 0x00000400, /* Transmit Control */
+ Tipg = 0x00000410, /* Transmit IPG */
+ Tdbal = 0x00003800, /* Tdesc Base Address Low */
+ Tdbah = 0x00003804, /* Tdesc Base Address High */
+ Tdlen = 0x00003808, /* Transmit Descriptor Length */
+ Tdh = 0x00003810, /* Transmit Descriptor Head */
+ Tdt = 0x00003818, /* Transmit Descriptor Tail */
+ Tidv = 0x00003820, /* Transmit Interrupt Delay Value */
+ Txdctl = 0x00003828, /* Transmit Descriptor Control */
+ Tadv = 0x0000382C, /* Transmit Interrupt Absolute Delay Timer */
+ Tarc0 = 0x00003840, /* Transmit Arbitration Counter Queue 0 */
+ Tdbal1 = 0x00003900, /* Transmit Descriptor Base Low Queue 1 */
+ Tdbah1 = 0x00003904, /* Transmit Descriptor Base High Queue 1 */
+ Tdlen1 = 0x00003908, /* Transmit Descriptor Length Queue 1 */
+ Tdh1 = 0x00003910, /* Transmit Descriptor Head Queue 1 */
+ Tdt1 = 0x00003918, /* Transmit Descriptor Tail Queue 1 */
+ Txdctl1 = 0x00003928, /* Transmit Descriptor Control 1 */
+ Tarc1 = 0x00003940, /* Transmit Arbitration Counter Queue 1 */
+
+ /* Statistics */
+
+ Statistics = 0x00004000, /* Start of Statistics Area */
+ Gorcl = 0x88/4, /* Good Octets Received Count */
+ Gotcl = 0x90/4, /* Good Octets Transmitted Count */
+ Torl = 0xC0/4, /* Total Octets Received */
+ Totl = 0xC8/4, /* Total Octets Transmitted */
+ Nstatistics = 64,
+
+};
+
+enum { /* Ctrl */
+ GIOmd = 1<<2, /* BIO master disable */
+ Lrst = 1<<3, /* link reset */
+ Slu = 1<<6, /* Set Link Up */
+ SspeedMASK = 3<<8, /* Speed Selection */
+ SspeedSHIFT = 8,
+ Sspeed10 = 0x00000000, /* 10Mb/s */
+ Sspeed100 = 0x00000100, /* 100Mb/s */
+ Sspeed1000 = 0x00000200, /* 1000Mb/s */
+ Frcspd = 1<<11, /* Force Speed */
+ Frcdplx = 1<<12, /* Force Duplex */
+ SwdpinsloMASK = 0x003C0000, /* Software Defined Pins - lo nibble */
+ SwdpinsloSHIFT = 18,
+ SwdpioloMASK = 0x03C00000, /* Software Defined Pins - I or O */
+ SwdpioloSHIFT = 22,
+ Devrst = 1<<26, /* Device Reset */
+ Rfce = 1<<27, /* Receive Flow Control Enable */
+ Tfce = 1<<28, /* Transmit Flow Control Enable */
+ Vme = 1<<30, /* VLAN Mode Enable */
+ Phy_rst = 1<<31, /* Phy Reset */
+};
+
+enum { /* Status */
+ Lu = 1<<1, /* Link Up */
+ Lanid = 3<<2, /* mask for Lan ID. */
+ Txoff = 1<<4, /* Transmission Paused */
+ Tbimode = 1<<5, /* TBI Mode Indication */
+ SpeedMASK = 0x000000C0,
+ Speed10 = 0x00000000, /* 10Mb/s */
+ Speed100 = 0x00000040, /* 100Mb/s */
+ Speed1000 = 0x00000080, /* 1000Mb/s */
+ Phyra = 1<<10, /* PHY Reset Asserted */
+ GIOme = 1<<19, /* GIO Master Enable Status */
+};
+
+enum { /* Ctrl and Status */
+ Fd = 0x00000001, /* Full-Duplex */
+ AsdvMASK = 0x00000300,
+ Asdv10 = 0x00000000, /* 10Mb/s */
+ Asdv100 = 0x00000100, /* 100Mb/s */
+ Asdv1000 = 0x00000200, /* 1000Mb/s */
+};
+
+enum { /* Eec */
+ Sk = 1<<0, /* Clock input to the EEPROM */
+ Cs = 1<<1, /* Chip Select */
+ Di = 1<<2, /* Data Input to the EEPROM */
+ Do = 1<<3, /* Data Output from the EEPROM */
+ Areq = 1<<6, /* EEPROM Access Request */
+ Agnt = 1<<7, /* EEPROM Access Grant */
+};
+
+enum { /* Eerd */
+ ee_start = 1<<0, /* Start Read */
+ ee_done = 1<<1, /* Read done */
+ ee_addr = 0xfff8<<2, /* Read address [15:2] */
+ ee_data = 0xffff<<16, /* Read Data; Data returned from eeprom/nvm */
+};
+
+enum { /* Ctrlext */
+ Asdchk = 1<<12, /* ASD Check */
+ Eerst = 1<<13, /* EEPROM Reset */
+ Spdbyps = 1<<15, /* Speed Select Bypass */
+};
+
+enum { /* EEPROM content offsets */
+ Ea = 0x00, /* Ethernet Address */
+ Cf = 0x03, /* Compatibility Field */
+ Icw1 = 0x0A, /* Initialization Control Word 1 */
+ Sid = 0x0B, /* Subsystem ID */
+ Svid = 0x0C, /* Subsystem Vendor ID */
+ Did = 0x0D, /* Device ID */
+ Vid = 0x0E, /* Vendor ID */
+ Icw2 = 0x0F, /* Initialization Control Word 2 */
+};
+
+enum { /* Mdic */
+ MDIdMASK = 0x0000FFFF, /* Data */
+ MDIdSHIFT = 0,
+ MDIrMASK = 0x001F0000, /* PHY Register Address */
+ MDIrSHIFT = 16,
+ MDIpMASK = 0x03E00000, /* PHY Address */
+ MDIpSHIFT = 21,
+ MDIwop = 0x04000000, /* Write Operation */
+ MDIrop = 0x08000000, /* Read Operation */
+ MDIready = 0x10000000, /* End of Transaction */
+ MDIie = 0x20000000, /* Interrupt Enable */
+ MDIe = 0x40000000, /* Error */
+};
+
+enum { /* Icr, Ics, Ims, Imc */
+ Txdw = 0x00000001, /* Transmit Descriptor Written Back */
+ Txqe = 0x00000002, /* Transmit Queue Empty */
+ Lsc = 0x00000004, /* Link Status Change */
+ Rxseq = 0x00000008, /* Receive Sequence Error */
+ Rxdmt0 = 0x00000010, /* Rdesc Minimum Threshold Reached */
+ Rxo = 0x00000040, /* Receiver Overrun */
+ Rxt0 = 0x00000080, /* Receiver Timer Interrupt */
+ Mdac = 0x00000200, /* MDIO Access Completed */
+ Rxcfg = 0x00000400, /* Receiving /C/ ordered sets */
+ Gpi0 = 0x00000800, /* General Purpose Interrupts */
+ Gpi1 = 0x00001000,
+ Gpi2 = 0x00002000,
+ Gpi3 = 0x00004000,
+ Ack = 0x00020000, /* receive ACK frame */
+};
+
+enum { /* Txcw */
+ TxcwFd = 0x00000020, /* Full Duplex */
+ TxcwHd = 0x00000040, /* Half Duplex */
+ TxcwPauseMASK = 0x00000180, /* Pause */
+ TxcwPauseSHIFT = 7,
+ TxcwPs = 1<<TxcwPauseSHIFT, /* Pause Supported */
+ TxcwAs = 2<<TxcwPauseSHIFT, /* Asymmetric FC desired */
+ TxcwRfiMASK = 0x00003000, /* Remote Fault Indication */
+ TxcwRfiSHIFT = 12,
+ TxcwNpr = 0x00008000, /* Next Page Request */
+ TxcwConfig = 0x40000000, /* Transmit COnfig Control */
+ TxcwAne = 0x80000000, /* Auto-Negotiation Enable */
+};
+
+enum { /* Rctl */
+ Rrst = 0x00000001, /* Receiver Software Reset */
+ Ren = 0x00000002, /* Receiver Enable */
+ Sbp = 0x00000004, /* Store Bad Packets */
+ Upe = 0x00000008, /* Unicast Promiscuous Enable */
+ Mpe = 0x00000010, /* Multicast Promiscuous Enable */
+ Lpe = 0x00000020, /* Long Packet Reception Enable */
+ LbmMASK = 0x000000C0, /* Loopback Mode */
+ LbmOFF = 0x00000000, /* No Loopback */
+ LbmTBI = 0x00000040, /* TBI Loopback */
+ LbmMII = 0x00000080, /* GMII/MII Loopback */
+ LbmXCVR = 0x000000C0, /* Transceiver Loopback */
+ RdtmsMASK = 0x00000300, /* Rdesc Minimum Threshold Size */
+ RdtmsHALF = 0x00000000, /* Threshold is 1/2 Rdlen */
+ RdtmsQUARTER = 0x00000100, /* Threshold is 1/4 Rdlen */
+ RdtmsEIGHTH = 0x00000200, /* Threshold is 1/8 Rdlen */
+ MoMASK = 0x00003000, /* Multicast Offset */
+ Bam = 0x00008000, /* Broadcast Accept Mode */
+ BsizeMASK = 0x00030000, /* Receive Buffer Size */
+ Bsize2048 = 0x00000000,
+ Bsize1024 = 0x00010000,
+ Bsize512 = 0x00020000,
+ Bsize256 = 0x00030000,
+ Vfe = 0x00040000, /* VLAN Filter Enable */
+ Cfien = 0x00080000, /* Canonical Form Indicator Enable */
+ Cfi = 0x00100000, /* Canonical Form Indicator value */
+ Dpf = 0x00400000, /* Discard Pause Frames */
+ Pmcf = 0x00800000, /* Pass MAC Control Frames */
+ Bsex = 0x02000000, /* Buffer Size Extension */
+ Secrc = 0x04000000, /* Strip CRC from incoming packet */
+};
+
+enum { /* Tctl */
+ Trst = 0x00000001, /* Transmitter Software Reset */
+ Ten = 0x00000002, /* Transmit Enable */
+ Psp = 0x00000008, /* Pad Short Packets */
+ Mulr = 0x10000000, /* Allow multiple concurrent requests */
+ CtMASK = 0x00000FF0, /* Collision Threshold */
+ CtSHIFT = 4,
+ ColdMASK = 0x003FF000, /* Collision Distance */
+ ColdSHIFT = 12,
+ Swxoff = 0x00400000, /* Sofware XOFF Transmission */
+ Pbe = 0x00800000, /* Packet Burst Enable */
+ Rtlc = 0x01000000, /* Re-transmit on Late Collision */
+ Nrtu = 0x02000000, /* No Re-transmit on Underrrun */
+};
+
+enum { /* [RT]xdctl */
+ PthreshMASK = 0x0000003F, /* Prefetch Threshold */
+ PthreshSHIFT = 0,
+ HthreshMASK = 0x00003F00, /* Host Threshold */
+ HthreshSHIFT = 8,
+ WthreshMASK = 0x003F0000, /* Writebacj Threshold */
+ WthreshSHIFT = 16,
+ Gran = 0x01000000, /* Granularity */
+};
+
+enum { /* Rxcsum */
+ PcssMASK = 0x000000FF, /* Packet Checksum Start */
+ PcssSHIFT = 0,
+ Ipofl = 0x00000100, /* IP Checksum Off-load Enable */
+ Tuofl = 0x00000200, /* TCP/UDP Checksum Off-load Enable */
+};
+
+typedef struct Rdesc { /* Receive Descriptor */
+ uint addr[2];
+ ushort length;
+ ushort checksum;
+ uchar status;
+ uchar errors;
+ ushort special;
+} Rdesc;
+
+enum { /* Rdesc status */
+ Rdd = 0x01, /* Descriptor Done */
+ Reop = 0x02, /* End of Packet */
+ Ixsm = 0x04, /* Ignore Checksum Indication */
+ Vp = 0x08, /* Packet is 802.1Q (matched VET) */
+ Tcpcs = 0x20, /* TCP Checksum Calculated on Packet */
+ Ipcs = 0x40, /* IP Checksum Calculated on Packet */
+ Pif = 0x80, /* Passed in-exact filter */
+};
+
+enum { /* Rdesc errors */
+ Ce = 0x01, /* CRC Error or Alignment Error */
+ Se = 0x02, /* Symbol Error */
+ Seq = 0x04, /* Sequence Error */
+ Cxe = 0x10, /* Carrier Extension Error */
+ Tcpe = 0x20, /* TCP/UDP Checksum Error */
+ Ipe = 0x40, /* IP Checksum Error */
+ Rxe = 0x80, /* RX Data Error */
+};
+
+typedef struct Tdesc { /* Legacy+Normal Transmit Descriptor */
+ uint addr[2];
+ uint control; /* varies with descriptor type */
+ uint status; /* varies with descriptor type */
+} Tdesc;
+
+enum { /* Tdesc control */
+ LenMASK = 0x000FFFFF, /* Data/Packet Length Field */
+ LenSHIFT = 0,
+ DtypeCD = 0x00000000, /* Data Type 'Context Descriptor' */
+ DtypeDD = 0x00100000, /* Data Type 'Data Descriptor' */
+ PtypeTCP = 0x01000000, /* TCP/UDP Packet Type (CD) */
+ Teop = 0x01000000, /* End of Packet (DD) */
+ PtypeIP = 0x02000000, /* IP Packet Type (CD) */
+ Ifcs = 0x02000000, /* Insert FCS (DD) */
+ Tse = 0x04000000, /* TCP Segmentation Enable */
+ Rs = 0x08000000, /* Report Status */
+ Rps = 0x10000000, /* Report Status Sent */
+ Dext = 0x20000000, /* Descriptor Extension */
+ Vle = 0x40000000, /* VLAN Packet Enable */
+ Ide = 0x80000000, /* Interrupt Delay Enable */
+};
+
+enum { /* Tdesc status */
+ Tdd = 0x00000001, /* Descriptor Done */
+ Ec = 0x00000002, /* Excess Collisions */
+ Lc = 0x00000004, /* Late Collision */
+ Tu = 0x00000008, /* Transmit Underrun */
+ CssMASK = 0x0000FF00, /* Checksum Start Field */
+ CssSHIFT = 8,
+};
+
+enum {
+ Nrdesc = 128, /* multiple of 8 */
+ Ntdesc = 128, /* multiple of 8 */
+};
+
+enum {
+ i82563,
+ i82571,
+ i82573,
+};
+
+static char *tname[] = {
+ "i82563",
+ "i82571",
+ "i82573",
+};
+
+#define Type tname[ctlr->type]
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ int port;
+ Pcidev *pcidev;
+ Ctlr *next;
+ int active;
+ int cls;
+ ushort eeprom[0x40];
+ uchar ra[Eaddrlen]; /* receive address */
+ int type;
+
+ int* nic;
+ Lock imlock;
+ int im; /* interrupt mask */
+
+ Lock slock;
+ uint statistics[Nstatistics];
+
+ Rdesc *rdba; /* receive descriptor base address */
+ Block **rb; /* receive buffers */
+ int rdh; /* receive descriptor head */
+ int rdt; /* receive descriptor tail */
+
+ Tdesc *tdba; /* transmit descriptor base address */
+ Lock tdlock;
+ Block **tb; /* transmit buffers */
+ int tdh; /* transmit descriptor head */
+ int tdt; /* transmit descriptor tail */
+
+ int txcw;
+ int fcrtl;
+ int fcrth;
+
+ /* bootstrap goo */
+ Block *bqhead; /* transmission queue */
+ Block *bqtail;
+};
+
+static Ctlr *ctlrhead;
+static Ctlr *ctlrtail;
+
+#define csr32r(c, r) (*((c)->nic+((r)/4)))
+#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
+
+static void
+i82563im(Ctlr* ctlr, int im)
+{
+ ilock(&ctlr->imlock);
+ ctlr->im |= im;
+ csr32w(ctlr, Ims, ctlr->im);
+ iunlock(&ctlr->imlock);
+}
+
+static void
+i82563attach(Ether* edev)
+{
+ int ctl;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ i82563im(ctlr, 0);
+ ctl = csr32r(ctlr, Rctl)|Ren;
+ csr32w(ctlr, Rctl, ctl);
+ ctl = csr32r(ctlr, Tctl)|Ten;
+ csr32w(ctlr, Tctl, ctl);
+}
+
+
+static void
+txstart(Ether *edev)
+{
+ int tdh, tdt;
+ Ctlr *ctlr = edev->ctlr;
+ Block *bp;
+ Tdesc *tdesc;
+
+ /*
+ * Try to fill the ring back up, moving buffers from the transmit q.
+ */
+ tdh = PREV(ctlr->tdh, Ntdesc);
+ for(tdt = ctlr->tdt; tdt != tdh; tdt = NEXT(tdt, Ntdesc)){
+ /* pull off the head of the transmission queue */
+ if((bp = ctlr->bqhead) == nil) /* was qget(edev->oq) */
+ break;
+ ctlr->bqhead = bp->next;
+ if (ctlr->bqtail == bp)
+ ctlr->bqtail = nil;
+
+ /* set up a descriptor for it */
+ tdesc = &ctlr->tdba[tdt];
+ tdesc->addr[0] = PCIWADDR(bp->rp);
+ tdesc->addr[1] = 0;
+ tdesc->control = /* Ide | */ Rs | Ifcs | Teop | BLEN(bp);
+
+ ctlr->tb[tdt] = bp;
+ }
+ ctlr->tdt = tdt;
+ csr32w(ctlr, Tdt, tdt);
+ i82563im(ctlr, Txdw);
+}
+
+static Block *
+fromringbuf(Ether *ether)
+{
+ RingBuf *tb = ðer->tb[ether->ti];
+ Block *bp = allocb(tb->len);
+
+ memmove(bp->wp, tb->pkt, tb->len);
+ memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+ bp->wp += tb->len;
+ return bp;
+}
+
+static void
+i82563transmit(Ether* edev)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ Tdesc *tdesc;
+ RingBuf *tb;
+ int tdh;
+
+ ctlr = edev->ctlr;
+ ilock(&ctlr->tdlock);
+
+ /*
+ * Free any completed packets
+ * - try to get the soft tdh to catch the tdt;
+ * - if the packet had an underrun bump the threshold
+ * - the Tu bit doesn't seem to ever be set, perhaps
+ * because Rs mode is used?
+ */
+ tdh = ctlr->tdh;
+ for(;;){
+ tdesc = &ctlr->tdba[tdh];
+ if(!(tdesc->status & Tdd))
+ break;
+ if(ctlr->tb[tdh] != nil){
+ freeb(ctlr->tb[tdh]);
+ ctlr->tb[tdh] = nil;
+ }
+ tdesc->status = 0;
+ tdh = NEXT(tdh, Ntdesc);
+ }
+ ctlr->tdh = tdh;
+
+ /* copy packets from the software RingBuf to the transmission q */
+ while((tb = &edev->tb[edev->ti])->owner == Interface){
+ bp = fromringbuf(edev);
+// print("#l%d: tx %d %E %E\n", edev->ctlrno, edev->ti, bp->rp,
+// bp->rp+6);
+
+ if(ctlr->bqhead)
+ ctlr->bqtail->next = bp;
+ else
+ ctlr->bqhead = bp;
+ ctlr->bqtail = bp;
+
+ txstart(edev); /* kick transmitter */
+ tb->owner = Host; /* give descriptor back */
+ edev->ti = NEXT(edev->ti, edev->ntb);
+ }
+ iunlock(&ctlr->tdlock);
+}
+
+static void
+i82563replenish(Ctlr* ctlr)
+{
+ int rdt;
+ Block *bp;
+ Rdesc *rdesc;
+
+ rdt = ctlr->rdt;
+ while(NEXT(rdt, Nrdesc) != ctlr->rdh){
+ rdesc = &ctlr->rdba[rdt];
+ if(ctlr->rb[rdt] != nil){
+ /* nothing to do */
+ }
+ else if((bp = iallocb(2048)) != nil){
+ ctlr->rb[rdt] = bp;
+ rdesc->addr[0] = PCIWADDR(bp->rp);
+ rdesc->addr[1] = 0;
+ }
+ else
+ break;
+ rdesc->status = 0;
+
+ rdt = NEXT(rdt, Nrdesc);
+ }
+ ctlr->rdt = rdt;
+ csr32w(ctlr, Rdt, rdt);
+}
+
+static void
+toringbuf(Ether *ether, Block *bp)
+{
+ RingBuf *rb = ðer->rb[ether->ri];
+
+ if (rb->owner == Interface) {
+ rb->len = BLEN(bp);
+ memmove(rb->pkt, bp->rp, rb->len);
+ rb->owner = Host;
+ ether->ri = NEXT(ether->ri, ether->nrb);
+ } else if (debug)
+ print("#l%d: toringbuf: dropping packets @ ri %d\n",
+ ether->ctlrno, ether->ri);
+}
+
+static void
+i82563interrupt(Ureg*, void* arg)
+{
+ int icr, im, rdh, txdw = 0;
+ Block *bp;
+ Ctlr *ctlr;
+ Ether *edev;
+ Rdesc *rdesc;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->imlock);
+ csr32w(ctlr, Imc, ~0);
+ im = ctlr->im;
+
+ for(icr = csr32r(ctlr, Icr); icr & ctlr->im; icr = csr32r(ctlr, Icr)){
+ if(icr & (Rxseq|Lsc)){
+ /* should be more here */
+ }
+
+ rdh = ctlr->rdh;
+ for (;;) {
+ rdesc = &ctlr->rdba[rdh];
+ if(!(rdesc->status & Rdd))
+ break;
+ if ((rdesc->status & Reop) && rdesc->errors == 0) {
+ bp = ctlr->rb[rdh];
+ if(0 && memcmp(bp->rp, broadcast, 6) != 0)
+ print("#l%d: rx %d %E %E %d\n",
+ edev->ctlrno, rdh, bp->rp,
+ bp->rp+6, rdesc->length);
+ ctlr->rb[rdh] = nil;
+ bp->wp += rdesc->length;
+ toringbuf(edev, bp);
+ freeb(bp);
+ } else if (rdesc->status & Reop && rdesc->errors)
+ print("%s: input packet error 0x%ux\n",
+ Type, rdesc->errors);
+ rdesc->status = 0;
+ rdh = NEXT(rdh, Nrdesc);
+ }
+ ctlr->rdh = rdh;
+ if(icr & Rxdmt0)
+ i82563replenish(ctlr);
+ if(icr & Txdw){
+ im &= ~Txdw;
+ txdw++;
+ }
+ }
+ ctlr->im = im;
+ csr32w(ctlr, Ims, im);
+ iunlock(&ctlr->imlock);
+ if(txdw)
+ i82563transmit(edev);
+}
+
+static void
+i82563init(Ether* edev)
+{
+ int csr, i, r;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ csr = edev->ea[3]<<24 | edev->ea[2]<<16 | edev->ea[1]<<8 | edev->ea[0];
+ csr32w(ctlr, Ral, csr);
+ csr = 0x80000000 | edev->ea[5]<<8 | edev->ea[4];
+ csr32w(ctlr, Rah, csr);
+ for (i = 1; i < 16; i++) {
+ csr32w(ctlr, Ral+i*8, 0);
+ csr32w(ctlr, Rah+i*8, 0);
+ }
+ for(i = 0; i < 128; i++)
+ csr32w(ctlr, Mta+i*4, 0);
+ csr32w(ctlr, Rctl, 0);
+ ctlr->rdba = xspanalloc(Nrdesc*sizeof(Rdesc), 256, 0);
+ csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
+ csr32w(ctlr, Rdbah, 0);
+ csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc));
+ ctlr->rdh = 0;
+ csr32w(ctlr, Rdh, ctlr->rdh);
+ ctlr->rdt = 0;
+ csr32w(ctlr, Rdt, ctlr->rdt);
+ ctlr->rb = malloc(sizeof(Block*)*Nrdesc);
+ i82563replenish(ctlr);
+ csr32w(ctlr, Rdtr, 0);
+ csr32w(ctlr, Rctl, Dpf | Bsize2048 | Bam | RdtmsHALF);
+ i82563im(ctlr, Rxt0 | Rxo | Rxdmt0 | Rxseq | Ack);
+
+ csr32w(ctlr, Tctl, 0x0F<<CtSHIFT | Psp | 0x3f<<ColdSHIFT | Mulr);
+ csr32w(ctlr, Tipg, 6<<20 | 8<<10 | 8);
+ csr32w(ctlr, Tidv, 1);
+
+ ctlr->tdba = xspanalloc(Ntdesc*sizeof(Tdesc), 256, 0);
+ memset(ctlr->tdba, 0, Ntdesc*sizeof(Tdesc));
+ csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
+
+ csr32w(ctlr, Tdbah, 0);
+ csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc));
+ ctlr->tdh = 0;
+ csr32w(ctlr, Tdh, ctlr->tdh);
+ ctlr->tdt = 0;
+ csr32w(ctlr, Tdt, ctlr->tdt);
+ ctlr->tb = malloc(sizeof(Block*)*Ntdesc);
+
+// r = 4<<WthreshSHIFT | 4<<HthreshSHIFT | 8<<PthreshSHIFT;
+// csr32w(ctlr, Txdctl, r);
+ csr32w(ctlr, Rxcsum, Tuofl | Ipofl | ETHERHDRSIZE<<PcssSHIFT);
+ r = csr32r(ctlr, Tctl);
+ r |= Ten;
+ csr32w(ctlr, Tctl, r);
+}
+
+
+static ushort
+eeread(Ctlr* ctlr, int adr)
+{
+ csr32w(ctlr, Eerd, ee_start | adr << 2);
+ while ((csr32r(ctlr, Eerd) & ee_done) == 0)
+ ;
+ return csr32r(ctlr, Eerd) >> 16;
+}
+
+static int
+eeload(Ctlr* ctlr)
+{
+ ushort sum;
+ int data, adr;
+
+ sum = 0;
+ for (adr = 0; adr < 0x40; adr++) {
+ data = eeread(ctlr, adr);
+ ctlr->eeprom[adr] = data;
+ sum += data;
+ }
+ return sum;
+}
+
+
+static void
+detach(Ctlr *ctlr)
+{
+ int r;
+
+ csr32w(ctlr, Imc, ~0);
+ csr32w(ctlr, Rctl, 0);
+ csr32w(ctlr, Tctl, 0);
+
+ delay(10);
+
+ r = csr32r(ctlr, Ctrl);
+ csr32w(ctlr, Ctrl, Devrst | r);
+ /* apparently needed on multi-GHz processors to avoid infinite loops */
+ delay(1);
+ while(csr32r(ctlr, Ctrl) & Devrst)
+ ;
+
+ if(1 || ctlr->type != i82563){
+ r = csr32r(ctlr, Ctrl);
+ csr32w(ctlr, Ctrl, Slu | r);
+ }
+
+ csr32w(ctlr, Ctrlext, Eerst | csr32r(ctlr, Ctrlext));
+ delay(1);
+ while(csr32r(ctlr, Ctrlext) & Eerst)
+ ;
+
+ csr32w(ctlr, Imc, ~0);
+ delay(1);
+ while(csr32r(ctlr, Icr))
+ ;
+}
+
+static void
+i82563detach(Ether *edev)
+{
+ detach(edev->ctlr);
+}
+
+static void
+i82563shutdown(Ether* ether)
+{
+ i82563detach(ether);
+}
+
+static int
+i82563reset(Ctlr* ctlr)
+{
+ int i, r;
+
+ detach(ctlr);
+
+ r = eeload(ctlr);
+ if (r != 0 && r != 0xBABA){
+ print("%s: bad EEPROM checksum - 0x%4.4ux\n", Type, r);
+ return -1;
+ }
+
+ for(i = Ea; i < Eaddrlen/2; i++){
+ ctlr->ra[2*i] = ctlr->eeprom[i];
+ ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
+ }
+ r = (csr32r(ctlr, Status) & Lanid) >> 2;
+ ctlr->ra[5] += r; /* ea ctlr[1] = ea ctlr[0]+1 */
+
+ r = ctlr->ra[3]<<24 | ctlr->ra[2]<<16 | ctlr->ra[1]<<8 | ctlr->ra[0];
+ csr32w(ctlr, Ral, r);
+ r = 0x80000000 | ctlr->ra[5]<<8 | ctlr->ra[4];
+ csr32w(ctlr, Rah, r);
+ for(i = 1; i < 16; i++){
+ csr32w(ctlr, Ral+i*8, 0);
+ csr32w(ctlr, Rah+i*8, 0);
+ }
+
+ for(i = 0; i < 128; i++)
+ csr32w(ctlr, Mta+i*4, 0);
+
+ csr32w(ctlr, Fcal, 0x00C28001);
+ csr32w(ctlr, Fcah, 0x00000100);
+ csr32w(ctlr, Fct, 0x00008808);
+ csr32w(ctlr, Fcttv, 0x00000100);
+
+ csr32w(ctlr, Fcrtl, ctlr->fcrtl);
+ csr32w(ctlr, Fcrth, ctlr->fcrth);
+
+ ilock(&ctlr->imlock);
+ csr32w(ctlr, Imc, ~0);
+ ctlr->im = 0; /* was = Lsc, which hangs some controllers */
+ csr32w(ctlr, Ims, ctlr->im);
+ iunlock(&ctlr->imlock);
+
+ return 0;
+}
+
+static void
+i82563pci(void)
+{
+ int port, type, cls;
+ Pcidev *p;
+ Ctlr *ctlr;
+ static int first = 1;
+
+ if (first)
+ first = 0;
+ else
+ return;
+
+ p = nil;
+ while(p = pcimatch(p, 0x8086, 0)){
+ switch(p->did){
+ case 0x1096:
+ case 0x10ba:
+ type = i82563;
+ break;
+ case 0x108b: /* e */
+ case 0x108c: /* e (iamt) */
+ case 0x109a: /* l */
+ type = i82573;
+ break;
+ default:
+ continue;
+ }
+
+ port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
+ if(port == 0){
+ print("%s: can't map %d @ 0x%8.8lux\n", tname[type],
+ p->mem[0].size, p->mem[0].bar);
+ continue;
+ }
+
+ if(p->pcr & MemWrInv){
+ cls = pcicfgr8(p, PciCLS) * 4;
+ if(cls != CACHELINESZ)
+ pcicfgw8(p, PciCLS, CACHELINESZ/4);
+ }
+
+ cls = pcicfgr8(p, PciCLS);
+ switch(cls){
+ default:
+ print("%s: unexpected CLS - %d bytes\n",
+ tname[type], cls*sizeof(long));
+ break;
+ case 0x00:
+ case 0xFF:
+ /* alphapc 164lx returns 0 */
+ print("%s: unusable PciCLS: %d, using %d longs\n",
+ tname[type], cls, CACHELINESZ/sizeof(long));
+ cls = CACHELINESZ/sizeof(long);
+ pcicfgw8(p, PciCLS, cls);
+ break;
+ case 0x08:
+ case 0x10:
+ break;
+ }
+
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = port;
+ ctlr->pcidev = p;
+ ctlr->cls = cls*4;
+ ctlr->type = type;
+ ctlr->nic = KADDR(ctlr->port);
+ if(i82563reset(ctlr)){
+ free(ctlr);
+ continue;
+ }
+ pcisetbme(p);
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+}
+
+static uchar nilea[Eaddrlen];
+
+int
+i82563pnp(Ether* edev)
+{
+ Ctlr *ctlr;
+
+ if(ctlrhead == nil)
+ i82563pci();
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+// edev->mbps = 1000;
+
+ if(memcmp(edev->ea, nilea, Eaddrlen) == 0)
+ memmove(edev->ea, ctlr->ra, Eaddrlen);
+ i82563init(edev);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ edev->attach = i82563attach;
+ edev->transmit = i82563transmit;
+ edev->interrupt = i82563interrupt;
+ edev->detach = i82563detach;
+
+ /*
+ * with the current structure, there is no right place for this.
+ * ideally, we recognize the interface, note it's down and move on.
+ * currently either we can skip the interface or note it is down,
+ * but not both.
+ */
+ if((csr32r(ctlr, Status)&Lu) == 0){
+ print("ether#%d: 82563 (%s): link down\n", edev->ctlrno, Type);
+ return -1;
+ }
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether83815.c
@@ -1,0 +1,820 @@
+/*
+ * National Semiconductor DP83815
+ *
+ * Supports only internal PHY and has been tested on:
+ * Netgear FA311TX (using Netgear DS108 10/100 hub)
+ * To do:
+ * check Ethernet address;
+ * test autonegotiation on 10 Mbit, and 100 Mbit full duplex;
+ * external PHY via MII (should be common code for MII);
+ * thresholds;
+ * ring sizing;
+ * physical link changes/disconnect;
+ * push initialisation back to attach.
+ *
+ * C H Forsyth, forsyth@vitanuova.com, 18th June 2001.
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+#define DEBUG (1)
+#define debug if(DEBUG)print
+
+enum {
+ Nrde = 8,
+ Ntde = 8,
+};
+
+#define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4)
+
+typedef struct Des {
+ ulong next;
+ int cmdsts;
+ ulong addr;
+ Block* bp;
+} Des;
+
+enum { /* cmdsts */
+ Own = 1<<31, /* set by data producer to hand to consumer */
+ More = 1<<30, /* more of packet in next descriptor */
+ Intr = 1<<29, /* interrupt when device is done with it */
+ Supcrc = 1<<28, /* suppress crc on transmit */
+ Inccrc = 1<<28, /* crc included on receive (always) */
+ Ok = 1<<27, /* packet ok */
+ Size = 0xFFF, /* packet size in bytes */
+
+ /* transmit */
+ Txa = 1<<26, /* transmission aborted */
+ Tfu = 1<<25, /* transmit fifo underrun */
+ Crs = 1<<24, /* carrier sense lost */
+ Td = 1<<23, /* transmission deferred */
+ Ed = 1<<22, /* excessive deferral */
+ Owc = 1<<21, /* out of window collision */
+ Ec = 1<<20, /* excessive collisions */
+ /* 19-16 collision count */
+
+ /* receive */
+ Rxa = 1<<26, /* receive aborted (same as Rxo) */
+ Rxo = 1<<25, /* receive overrun */
+ Dest = 3<<23, /* destination class */
+ Drej= 0<<23, /* packet was rejected */
+ Duni= 1<<23, /* unicast */
+ Dmulti= 2<<23, /* multicast */
+ Dbroad= 3<<23, /* broadcast */
+ Long = 1<<22, /* too long packet received */
+ Runt = 1<<21, /* packet less than 64 bytes */
+ Ise = 1<<20, /* invalid symbol */
+ Crce = 1<<19, /* invalid crc */
+ Fae = 1<<18, /* frame alignment error */
+ Lbp = 1<<17, /* loopback packet */
+ Col = 1<<16, /* collision during receive */
+};
+
+enum { /* Variants */
+ Nat83815 = (0x0020<<16)|0x100B,
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id; /* (pcidev->did<<16)|pcidev->vid */
+
+ ushort srom[0xB+1];
+ uchar sromea[Eaddrlen]; /* MAC address */
+
+ uchar fd; /* option or auto negotiation */
+
+ int mbps;
+
+ Lock ilock;
+
+ Des* rdr; /* receive descriptor ring */
+ int nrdr; /* size of rdr */
+ int rdrx; /* index into rdr */
+
+ Lock tlock;
+ Des* tdr; /* transmit descriptor ring */
+ int ntdr; /* size of tdr */
+ int tdrh; /* host index into tdr */
+ int tdri; /* interface index into tdr */
+ int ntq; /* descriptors active */
+ int ntqmax;
+ Block* bqhead; /* transmission queue */
+ Block* bqtail;
+
+ ulong rxa; /* receive statistics */
+ ulong rxo;
+ ulong rlong;
+ ulong runt;
+ ulong ise;
+ ulong crce;
+ ulong fae;
+ ulong lbp;
+ ulong col;
+ ulong rxsovr;
+ ulong rxorn;
+
+ ulong txa; /* transmit statistics */
+ ulong tfu;
+ ulong crs;
+ ulong td;
+ ulong ed;
+ ulong owc;
+ ulong ec;
+ ulong txurn;
+
+ ulong dperr; /* system errors */
+ ulong rmabt;
+ ulong rtabt;
+ ulong sserr;
+ ulong rxsover;
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+enum {
+ /* registers (could memory map) */
+ Rcr= 0x00, /* command register */
+ Rst= 1<<8,
+ Rxr= 1<<5, /* receiver reset */
+ Txr= 1<<4, /* transmitter reset */
+ Rxd= 1<<3, /* receiver disable */
+ Rxe= 1<<2, /* receiver enable */
+ Txd= 1<<1, /* transmitter disable */
+ Txe= 1<<0, /* transmitter enable */
+ Rcfg= 0x04, /* configuration */
+ Lnksts= 1<<31, /* link good */
+ Speed100= 1<<30, /* 100 Mb/s link */
+ Fdup= 1<<29, /* full duplex */
+ Pol= 1<<28, /* polarity reversal (10baseT) */
+ Aneg_dn= 1<<27, /* autonegotiation done */
+ Pint_acen= 1<<17, /* PHY interrupt auto clear enable */
+ Pause_adv= 1<<16, /* advertise pause during auto neg */
+ Paneg_ena= 1<<13, /* auto negotiation enable */
+ Paneg_all= 7<<13, /* auto negotiation enable 10/100 half & full */
+ Ext_phy= 1<<12, /* enable MII for external PHY */
+ Phy_rst= 1<<10, /* reset internal PHY */
+ Phy_dis= 1<<9, /* disable internal PHY (eg, low power) */
+ Req_alg= 1<<7, /* PCI bus request: set means less aggressive */
+ Sb= 1<<6, /* single slot back-off not random */
+ Pow= 1<<5, /* out of window timer selection */
+ Exd= 1<<4, /* disable excessive deferral timer */
+ Pesel= 1<<3, /* parity error algorithm selection */
+ Brom_dis= 1<<2, /* disable boot rom interface */
+ Bem= 1<<0, /* big-endian mode */
+ Rmear= 0x08, /* eeprom access */
+ Mdc= 1<<6, /* MII mangement check */
+ Mddir= 1<<5, /* MII management direction */
+ Mdio= 1<<4, /* MII mangement data */
+ Eesel= 1<<3, /* EEPROM chip select */
+ Eeclk= 1<<2, /* EEPROM clock */
+ Eedo= 1<<1, /* EEPROM data out (from chip) */
+ Eedi= 1<<0, /* EEPROM data in (to chip) */
+ Rptscr= 0x0C, /* pci test control */
+ Risr= 0x10, /* interrupt status */
+ Txrcmp= 1<<25, /* transmit reset complete */
+ Rxrcmp= 1<<24, /* receiver reset complete */
+ Dperr= 1<<23, /* detected parity error */
+ Sserr= 1<<22, /* signalled system error */
+ Rmabt= 1<<21, /* received master abort */
+ Rtabt= 1<<20, /* received target abort */
+ Rxsovr= 1<<16, /* RX status FIFO overrun */
+ Hiberr= 1<<15, /* high bits error set (OR of 25-16) */
+ Phy= 1<<14, /* PHY interrupt */
+ Pme= 1<<13, /* power management event (wake online) */
+ Swi= 1<<12, /* software interrupt */
+ Mib= 1<<11, /* MIB service */
+ Txurn= 1<<10, /* TX underrun */
+ Txidle= 1<<9, /* TX idle */
+ Txerr= 1<<8, /* TX packet error */
+ Txdesc= 1<<7, /* TX descriptor (with Intr bit done) */
+ Txok= 1<<6, /* TX ok */
+ Rxorn= 1<<5, /* RX overrun */
+ Rxidle= 1<<4, /* RX idle */
+ Rxearly= 1<<3, /* RX early threshold */
+ Rxerr= 1<<2, /* RX packet error */
+ Rxdesc= 1<<1, /* RX descriptor (with Intr bit done) */
+ Rxok= 1<<0, /* RX ok */
+ Rimr= 0x14, /* interrupt mask */
+ Rier= 0x18, /* interrupt enable */
+ Ie= 1<<0, /* interrupt enable */
+ Rtxdp= 0x20, /* transmit descriptor pointer */
+ Rtxcfg= 0x24, /* transmit configuration */
+ Csi= 1<<31, /* carrier sense ignore (needed for full duplex) */
+ Hbi= 1<<30, /* heartbeat ignore (needed for full duplex) */
+ Atp= 1<<28, /* automatic padding of runt packets */
+ Mxdma= 7<<20, /* maximum dma transfer field */
+ Mxdma32= 4<<20, /* 4x32-bit words (32 bytes) */
+ Mxdma64= 5<<20, /* 8x32-bit words (64 bytes) */
+ Flth= 0x3F<<8, /* Tx fill threshold, units of 32 bytes (must be > Mxdma) */
+ Drth= 0x3F<<0, /* Tx drain threshold (units of 32 bytes) */
+ Flth128= 4<<8, /* fill at 128 bytes */
+ Drth512= 16<<0, /* drain at 512 bytes */
+ Rrxdp= 0x30, /* receive descriptor pointer */
+ Rrxcfg= 0x34, /* receive configuration */
+ Atx= 1<<28, /* accept transmit packets (needed for full duplex) */
+ Rdrth= 0x1F<<1, /* Rx drain threshold (units of 32 bytes) */
+ Rdrth64= 2<<1, /* drain at 64 bytes */
+ Rccsr= 0x3C, /* CLKRUN control/status */
+ Pmests= 1<<15, /* PME status */
+ Rwcsr= 0x40, /* wake on lan control/status */
+ Rpcr= 0x44, /* pause control/status */
+ Rrfcr= 0x48, /* receive filter/match control */
+ Rfen= 1<<31, /* receive filter enable */
+ Aab= 1<<30, /* accept all broadcast */
+ Aam= 1<<29, /* accept all multicast */
+ Aau= 1<<28, /* accept all unicast */
+ Apm= 1<<27, /* accept on perfect match */
+ Apat= 0xF<<23, /* accept on pattern match */
+ Aarp= 1<<22, /* accept ARP */
+ Mhen= 1<<21, /* multicast hash enable */
+ Uhen= 1<<20, /* unicast hash enable */
+ Ulm= 1<<19, /* U/L bit mask */
+ /* bits 0-9 are rfaddr */
+ Rrfdr= 0x4C, /* receive filter/match data */
+ Rbrar= 0x50, /* boot rom address */
+ Rbrdr= 0x54, /* boot rom data */
+ Rsrr= 0x58, /* silicon revision */
+ Rmibc= 0x5C, /* MIB control */
+ /* 60-78 MIB data */
+
+ /* PHY registers */
+ Rbmcr= 0x80, /* basic mode configuration */
+ Reset= 1<<15,
+ Sel100= 1<<13, /* select 100Mb/sec if no auto neg */
+ Anena= 1<<12, /* auto negotiation enable */
+ Anrestart= 1<<9, /* restart auto negotiation */
+ Selfdx= 1<<8, /* select full duplex if no auto neg */
+ Rbmsr= 0x84, /* basic mode status */
+ Ancomp= 1<<5, /* autonegotiation complete */
+ Rphyidr1= 0x88,
+ Rphyidr2= 0x8C,
+ Ranar= 0x90, /* autonegotiation advertisement */
+ Ranlpar= 0x94, /* autonegotiation link partner ability */
+ Raner= 0x98, /* autonegotiation expansion */
+ Rannptr= 0x9C, /* autonegotiation next page TX */
+ Rphysts= 0xC0, /* PHY status */
+ Rmicr= 0xC4, /* MII control */
+ Inten= 1<<1, /* PHY interrupt enable */
+ Rmisr= 0xC8, /* MII status */
+ Rfcscr= 0xD0, /* false carrier sense counter */
+ Rrecr= 0xD4, /* receive error counter */
+ Rpcsr= 0xD8, /* 100Mb config/status */
+ Rphycr= 0xE4, /* PHY control */
+ Rtbscr= 0xE8, /* 10BaseT status/control */
+};
+
+/*
+ * eeprom addresses
+ * 7 to 9 (16 bit words): mac address, shifted and reversed
+ */
+
+#define csr32r(c, r) (inl((c)->port+(r)))
+#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
+#define csr16r(c, r) (ins((c)->port+(r)))
+#define csr16w(c, r, l) (outs((c)->port+(r), (ulong)(l)))
+
+static void
+dumpcregs(Ctlr *ctlr)
+{
+ int i;
+
+ for(i=0; i<=0x5C; i+=4)
+ print("%2.2ux %8.8lux\n", i, csr32r(ctlr, i));
+}
+
+static void
+attach(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(&ctlr->ilock);
+ if(0)
+ dumpcregs(ctlr);
+ csr32w(ctlr, Rcr, Rxe);
+ iunlock(&ctlr->ilock);
+}
+
+static void
+detach(Ether* ether)
+{
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ csr32w(ctlr, Rcr, 0);
+ delay(1);
+}
+
+static void
+txstart(Ether* ether)
+{
+ Ctlr *ctlr;
+ Block *bp;
+ Des *des;
+ int started;
+
+ ctlr = ether->ctlr;
+ started = 0;
+ while(ctlr->ntq < ctlr->ntdr-1){
+ bp = ctlr->bqhead;
+ if(bp == nil)
+ break;
+ ctlr->bqhead = bp->next;
+ des = &ctlr->tdr[ctlr->tdrh];
+ des->bp = bp;
+ des->addr = PADDR(bp->rp);
+ ctlr->ntq++;
+ coherence();
+ des->cmdsts = Own | BLEN(bp);
+ ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
+ started = 1;
+ }
+ if(started){
+ coherence();
+ csr32w(ctlr, Rcr, Txe); /* prompt */
+ }
+
+ if(ctlr->ntq > ctlr->ntqmax)
+ ctlr->ntqmax = ctlr->ntq;
+}
+
+static void
+transmit(Ether* ether)
+{
+ Ctlr *ctlr;
+ Block *bp;
+ RingBuf *tb;
+
+ ctlr = ether->ctlr;
+ ilock(&ctlr->tlock);
+ while((tb = ðer->tb[ether->ti])->owner == Interface){
+ bp = allocb(tb->len);
+ memmove(bp->wp, tb->pkt, tb->len);
+ memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+ bp->wp += tb->len;
+ if(ctlr->bqhead)
+ ctlr->bqtail->next = bp;
+ else
+ ctlr->bqhead = bp;
+ ctlr->bqtail = bp;
+ txstart(ether);
+ tb->owner = Host;
+ ether->ti = NEXT(ether->ti, ether->ntb);
+ }
+ iunlock(&ctlr->tlock);
+}
+
+static void
+txrxcfg(Ctlr *ctlr, int txdrth)
+{
+ ulong rx, tx;
+
+ rx = csr32r(ctlr, Rrxcfg);
+ tx = csr32r(ctlr, Rtxcfg);
+ if(ctlr->fd){
+ rx |= Atx;
+ tx |= Csi | Hbi;
+ }else{
+ rx &= ~Atx;
+ tx &= ~(Csi | Hbi);
+ }
+ tx &= ~(Mxdma|Drth|Flth);
+ tx |= Mxdma64 | Flth128 | txdrth;
+ csr32w(ctlr, Rtxcfg, tx);
+ rx &= ~(Mxdma|Rdrth);
+ rx |= Mxdma64 | Rdrth64;
+ csr32w(ctlr, Rrxcfg, rx);
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Ether *ether;
+ int status, cmdsts;
+ Des *des;
+ RingBuf *rb;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ while((status = csr32r(ctlr, Risr)) != 0){
+
+ status &= ~(Pme|Mib);
+ status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);
+
+ /*
+ * Received packets.
+ */
+ if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){
+ des = &ctlr->rdr[ctlr->rdrx];
+ while((cmdsts = des->cmdsts) & Own){
+ rb = ðer->rb[ether->ri];
+ if(rb->owner == Interface && (cmdsts&Ok)){
+ rb->len = (cmdsts&Size)-4;
+ memmove(rb->pkt, des->bp->rp, rb->len);
+ rb->owner = Host;
+ ether->ri = NEXT(ether->ri, ether->nrb);
+ }
+
+ des->cmdsts = Rbsz;
+ coherence();
+
+ ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
+ des = &ctlr->rdr[ctlr->rdrx];
+ }
+ status &= ~(Rxdesc|Rxok|Rxerr|Rxearly|Rxorn);
+ }
+
+ /*
+ * Check the transmit side:
+ * check for Transmit Underflow and Adjust
+ * the threshold upwards;
+ * free any transmitted buffers and try to
+ * top-up the ring.
+ */
+ if(status & Txurn){
+ ctlr->txurn++;
+ ilock(&ctlr->ilock);
+ /* change threshold */
+ iunlock(&ctlr->ilock);
+ status &= ~(Txurn);
+ }
+
+ ilock(&ctlr->tlock);
+ while(ctlr->ntq){
+ des = &ctlr->tdr[ctlr->tdri];
+ cmdsts = des->cmdsts;
+ if(cmdsts & Own)
+ break;
+
+ freeb(des->bp);
+ des->bp = nil;
+ des->cmdsts = 0;
+
+ ctlr->ntq--;
+ ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
+ }
+ txstart(ether);
+ iunlock(&ctlr->tlock);
+
+ status &= ~(Txurn|Txidle|Txerr|Txdesc|Txok);
+
+ /*
+ * Anything left not catered for?
+ */
+ if(status)
+ print("#l%d: status %8.8uX\n", ether->ctlrno, status);
+ }
+}
+
+static void
+ctlrinit(Ether* ether)
+{
+ Ctlr *ctlr;
+ Des *des, *last;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * Allocate and initialise the receive ring;
+ * allocate and initialise the transmit ring;
+ * unmask interrupts and start the transmit side
+ */
+ ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des));
+ last = nil;
+ for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
+ des->bp = allocb(Rbsz);
+ des->cmdsts = Rbsz;
+ des->addr = PADDR(des->bp->rp);
+ if(last != nil)
+ last->next = PADDR(des);
+ last = des;
+ }
+ ctlr->rdr[ctlr->nrdr-1].next = PADDR(ctlr->rdr);
+ ctlr->rdrx = 0;
+ csr32w(ctlr, Rrxdp, PADDR(ctlr->rdr));
+
+ ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0);
+ last = nil;
+ for(des = ctlr->tdr; des < &ctlr->tdr[ctlr->ntdr]; des++){
+ des->cmdsts = 0;
+ des->bp = nil;
+ des->addr = ~0;
+ if(last != nil)
+ last->next = PADDR(des);
+ last = des;
+ }
+ ctlr->tdr[ctlr->ntdr-1].next = PADDR(ctlr->tdr);
+ ctlr->tdrh = 0;
+ ctlr->tdri = 0;
+ csr32w(ctlr, Rtxdp, PADDR(ctlr->tdr));
+
+ txrxcfg(ctlr, Drth512);
+
+ csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok); /* Phy|Pme|Mib */
+ csr32r(ctlr, Risr); /* clear status */
+ csr32w(ctlr, Rier, Ie);
+}
+
+static void
+eeclk(Ctlr *ctlr, int clk)
+{
+ csr32w(ctlr, Rmear, Eesel | clk);
+ microdelay(2);
+}
+
+static void
+eeidle(Ctlr *ctlr)
+{
+ int i;
+
+ eeclk(ctlr, 0);
+ eeclk(ctlr, Eeclk);
+ for(i=0; i<25; i++){
+ eeclk(ctlr, 0);
+ eeclk(ctlr, Eeclk);
+ }
+ eeclk(ctlr, 0);
+ csr32w(ctlr, Rmear, 0);
+ microdelay(2);
+}
+
+static int
+eegetw(Ctlr *ctlr, int a)
+{
+ int d, i, w, v;
+
+ eeidle(ctlr);
+ eeclk(ctlr, 0);
+ eeclk(ctlr, Eeclk);
+ d = 0x180 | a;
+ for(i=0x400; i; i>>=1){
+ v = (d & i) ? Eedi : 0;
+ eeclk(ctlr, v);
+ eeclk(ctlr, Eeclk|v);
+ }
+ eeclk(ctlr, 0);
+
+ w = 0;
+ for(i=0x8000; i; i >>= 1){
+ eeclk(ctlr, Eeclk);
+ if(csr32r(ctlr, Rmear) & Eedo)
+ w |= i;
+ microdelay(2);
+ eeclk(ctlr, 0);
+ }
+ eeidle(ctlr);
+ return w;
+}
+
+static void
+softreset(Ctlr* ctlr, int resetphys)
+{
+ int i, w;
+
+ /*
+ * Soft-reset the controller
+ */
+ csr32w(ctlr, Rcr, Rst);
+ for(i=0;; i++){
+ if(i > 100)
+ panic("ns83815: soft reset did not complete");
+ microdelay(250);
+ if((csr32r(ctlr, Rcr) & Rst) == 0)
+ break;
+ delay(1);
+ }
+
+ csr32w(ctlr, Rccsr, Pmests);
+ csr32w(ctlr, Rccsr, 0);
+ csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen);
+
+ if(resetphys){
+ /*
+ * Soft-reset the PHY
+ */
+ csr32w(ctlr, Rbmcr, Reset);
+ for(i=0;; i++){
+ if(i > 100)
+ panic("ns83815: PHY soft reset time out");
+ if((csr32r(ctlr, Rbmcr) & Reset) == 0)
+ break;
+ delay(1);
+ }
+ }
+
+ /*
+ * Initialisation values, in sequence (see 4.4 Recommended Registers Configuration)
+ */
+ csr16w(ctlr, 0xCC, 0x0001); /* PGSEL */
+ csr16w(ctlr, 0xE4, 0x189C); /* PMCCSR */
+ csr16w(ctlr, 0xFC, 0x0000); /* TSTDAT */
+ csr16w(ctlr, 0xF4, 0x5040); /* DSPCFG */
+ csr16w(ctlr, 0xF8, 0x008C); /* SDCFG */
+
+ /*
+ * Auto negotiate
+ */
+ w = csr16r(ctlr, Rbmsr); /* clear latched bits */
+ debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
+ csr16w(ctlr, Rbmcr, Anena);
+ if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){
+ csr16w(ctlr, Rbmcr, Anena|Anrestart);
+ for(i=0;; i++){
+ if(i > 6000){
+ print("ns83815: auto neg timed out\n");
+ break;
+ }
+ if((w = csr16r(ctlr, Rbmsr)) & Ancomp)
+ break;
+ delay(1);
+ }
+ debug("%d ms\n", i);
+ w &= 0xFFFF;
+ debug("bmsr: %4.4ux\n", w);
+ }
+ debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
+ debug("anlpar: %4.4ux\n", csr16r(ctlr, Ranlpar));
+ debug("aner: %4.4ux\n", csr16r(ctlr, Raner));
+ debug("physts: %4.4ux\n", csr16r(ctlr, Rphysts));
+ debug("tbscr: %4.4ux\n", csr16r(ctlr, Rtbscr));
+}
+
+static char* mediatable[9] = {
+ "10BASE-T", /* TP */
+ "10BASE-2", /* BNC */
+ "10BASE-5", /* AUI */
+ "100BASE-TX",
+ "10BASE-TFD",
+ "100BASE-TXFD",
+ "100BASE-T4",
+ "100BASE-FX",
+ "100BASE-FXFD",
+};
+
+static void
+srom(Ctlr* ctlr)
+{
+ int i, j;
+
+ for(i = 0; i < nelem(ctlr->srom); i++)
+ ctlr->srom[i] = eegetw(ctlr, i);
+
+ /*
+ * the MAC address is reversed, straddling word boundaries
+ */
+ memset(ctlr->sromea, 0, sizeof(ctlr->sromea));
+ j = 6*16 + 15;
+ for(i=0; i<48; i++){
+ ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7);
+ j++;
+ }
+}
+
+static void
+scanpci83815(void)
+{
+ Ctlr *ctlr;
+ Pcidev *p;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+
+ case Nat83815:
+ break;
+ }
+
+ /*
+ * bar[0] is the I/O port register address and
+ * bar[1] is the memory-mapped register address.
+ */
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = p->mem[0].bar & ~0x01;
+ ctlr->pcidev = p;
+ ctlr->id = (p->did<<16)|p->vid;
+
+ softreset(ctlr, 0);
+ srom(ctlr);
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+}
+
+int
+ether83815reset(Ether* ether)
+{
+ Ctlr *ctlr;
+ int i, x;
+ uchar ea[Eaddrlen];
+ static int scandone;
+
+ if(scandone == 0){
+ scanpci83815();
+ scandone = 1;
+ }
+
+ /*
+ * Any adapter matches if no ether->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(ether->port == 0 || ether->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ ether->ctlr = ctlr;
+ ether->port = ctlr->port;
+ ether->irq = ctlr->pcidev->intl;
+ ether->tbdf = ctlr->pcidev->tbdf;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in the hardware.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0)
+ memmove(ether->ea, ctlr->sromea, Eaddrlen);
+ for(i=0; i<Eaddrlen; i+=2){
+ x = ether->ea[i] | (ether->ea[i+1]<<8);
+ csr32w(ctlr, Rrfcr, i);
+ csr32w(ctlr, Rrfdr, x);
+ }
+ csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);
+
+ /*
+ * Look for a medium override in case there's no autonegotiation
+ * the autonegotiation fails.
+ */
+
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrcmp(ether->opt[i], "FD") == 0){
+ ctlr->fd = 1;
+ continue;
+ }
+ for(x = 0; x < nelem(mediatable); x++){
+ debug("compare <%s> <%s>\n", mediatable[x],
+ ether->opt[i]);
+ if(cistrcmp(mediatable[x], ether->opt[i]) == 0){
+ switch(x){
+ default:
+ ctlr->fd = 0;
+ break;
+
+ case 0x04: /* 10BASE-TFD */
+ case 0x05: /* 100BASE-TXFD */
+ case 0x08: /* 100BASE-FXFD */
+ ctlr->fd = 1;
+ break;
+ }
+ break;
+ }
+ }
+ }
+
+ /*
+ * Initialise descriptor rings, ethernet address.
+ */
+ ctlr->nrdr = Nrde;
+ ctlr->ntdr = Ntde;
+ pcisetbme(ctlr->pcidev);
+ ctlrinit(ether);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->detach = detach;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether8390.c
@@ -1,0 +1,715 @@
+/*
+ * National Semiconductor DP8390 and clone
+ * Network Interface Controller.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ether8390.h"
+
+enum { /* NIC core registers */
+ Cr = 0x00, /* command register, all pages */
+
+ /* Page 0, read */
+ Clda0 = 0x01, /* current local DMA address 0 */
+ Clda1 = 0x02, /* current local DMA address 1 */
+ Bnry = 0x03, /* boundary pointer (R/W) */
+ Tsr = 0x04, /* transmit status register */
+ Ncr = 0x05, /* number of collisions register */
+ Fifo = 0x06, /* FIFO */
+ Isr = 0x07, /* interrupt status register (R/W) */
+ Crda0 = 0x08, /* current remote DMA address 0 */
+ Crda1 = 0x09, /* current remote DMA address 1 */
+ Rsr = 0x0C, /* receive status register */
+ Cntr0 = 0x0D, /* frame alignment errors */
+ Cntr1 = 0x0E, /* CRC errors */
+ Cntr2 = 0x0F, /* missed packet errors */
+
+ /* Page 0, write */
+ Pstart = 0x01, /* page start register */
+ Pstop = 0x02, /* page stop register */
+ Tpsr = 0x04, /* transmit page start address */
+ Tbcr0 = 0x05, /* transmit byte count register 0 */
+ Tbcr1 = 0x06, /* transmit byte count register 1 */
+ Rsar0 = 0x08, /* remote start address register 0 */
+ Rsar1 = 0x09, /* remote start address register 1 */
+ Rbcr0 = 0x0A, /* remote byte count register 0 */
+ Rbcr1 = 0x0B, /* remote byte count register 1 */
+ Rcr = 0x0C, /* receive configuration register */
+ Tcr = 0x0D, /* transmit configuration register */
+ Dcr = 0x0E, /* data configuration register */
+ Imr = 0x0F, /* interrupt mask */
+
+ /* Page 1, read/write */
+ Par0 = 0x01, /* physical address register 0 */
+ Curr = 0x07, /* current page register */
+ Mar0 = 0x08, /* multicast address register 0 */
+};
+
+enum { /* Cr */
+ Stp = 0x01, /* stop */
+ Sta = 0x02, /* start */
+ Txp = 0x04, /* transmit packet */
+ Rd0 = 0x08, /* remote DMA command */
+ Rd1 = 0x10,
+ Rd2 = 0x20,
+ RdREAD = Rd0, /* remote read */
+ RdWRITE = Rd1, /* remote write */
+ RdSEND = Rd1|Rd0, /* send packet */
+ RdABORT = Rd2, /* abort/complete remote DMA */
+ Ps0 = 0x40, /* page select */
+ Ps1 = 0x80,
+ Page0 = 0x00,
+ Page1 = Ps0,
+ Page2 = Ps1,
+};
+
+enum { /* Isr/Imr */
+ Prx = 0x01, /* packet received */
+ Ptx = 0x02, /* packet transmitted */
+ Rxe = 0x04, /* receive error */
+ Txe = 0x08, /* transmit error */
+ Ovw = 0x10, /* overwrite warning */
+ Cnt = 0x20, /* counter overflow */
+ Rdc = 0x40, /* remote DMA complete */
+ Rst = 0x80, /* reset status */
+};
+
+enum { /* Dcr */
+ Wts = 0x01, /* word transfer select */
+ Bos = 0x02, /* byte order select */
+ Las = 0x04, /* long address select */
+ Ls = 0x08, /* loopback select */
+ Arm = 0x10, /* auto-initialise remote */
+ Ft0 = 0x20, /* FIFO threshold select */
+ Ft1 = 0x40,
+ Ft1WORD = 0x00,
+ Ft2WORD = Ft0,
+ Ft4WORD = Ft1,
+ Ft6WORD = Ft1|Ft0,
+};
+
+enum { /* Tcr */
+ Crc = 0x01, /* inhibit CRC */
+ Lb0 = 0x02, /* encoded loopback control */
+ Lb1 = 0x04,
+ LpbkNORMAL = 0x00, /* normal operation */
+ LpbkNIC = Lb0, /* internal NIC module loopback */
+ LpbkENDEC = Lb1, /* internal ENDEC module loopback */
+ LpbkEXTERNAL = Lb1|Lb0, /* external loopback */
+ Atd = 0x08, /* auto transmit disable */
+ Ofst = 0x10, /* collision offset enable */
+};
+
+enum { /* Tsr */
+ Ptxok = 0x01, /* packet transmitted */
+ Col = 0x04, /* transmit collided */
+ Abt = 0x08, /* tranmit aborted */
+ Crs = 0x10, /* carrier sense lost */
+ Fu = 0x20, /* FIFO underrun */
+ Cdh = 0x40, /* CD heartbeat */
+ Owc = 0x80, /* out of window collision */
+};
+
+enum { /* Rcr */
+ Sep = 0x01, /* save errored packets */
+ Ar = 0x02, /* accept runt packets */
+ Ab = 0x04, /* accept broadcast */
+ Am = 0x08, /* accept multicast */
+ Pro = 0x10, /* promiscuous physical */
+ Mon = 0x20, /* monitor mode */
+};
+
+enum { /* Rsr */
+ Prxok = 0x01, /* packet received intact */
+ Crce = 0x02, /* CRC error */
+ Fae = 0x04, /* frame alignment error */
+ Fo = 0x08, /* FIFO overrun */
+ Mpa = 0x10, /* missed packet */
+ Phy = 0x20, /* physical/multicast address */
+ Dis = 0x40, /* receiver disabled */
+ Dfr = 0x80, /* deferring */
+};
+
+typedef struct {
+ uchar status;
+ uchar next;
+ uchar len0;
+ uchar len1;
+} Hdr;
+
+void
+dp8390getea(Ether* ether, uchar* ea)
+{
+ Dp8390 *ctlr;
+ uchar cr;
+ int i;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * Get the ethernet address from the chip.
+ * Take care to restore the command register
+ * afterwards.
+ */
+ ilock(ctlr);
+ cr = regr(ctlr, Cr) & ~Txp;
+ regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
+ for(i = 0; i < Eaddrlen; i++)
+ ea[i] = regr(ctlr, Par0+i);
+ regw(ctlr, Cr, cr);
+ iunlock(ctlr);
+}
+
+void
+dp8390setea(Ether* ether)
+{
+ int i;
+ uchar cr;
+ Dp8390 *ctlr;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * Set the ethernet address into the chip.
+ * Take care to restore the command register
+ * afterwards. Don't care about multicast
+ * addresses as multicast is never enabled
+ * (currently).
+ */
+ ilock(ctlr);
+ cr = regr(ctlr, Cr) & ~Txp;
+ regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
+ for(i = 0; i < Eaddrlen; i++)
+ regw(ctlr, Par0+i, ether->ea[i]);
+ regw(ctlr, Cr, cr);
+ iunlock(ctlr);
+}
+
+static void*
+_dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len)
+{
+ uchar cr;
+ int timo;
+
+ /*
+ * Read some data at offset 'from' in the card's memory
+ * using the DP8390 remote DMA facility, and place it at
+ * 'to' in main memory, via the I/O data port.
+ */
+ cr = regr(ctlr, Cr) & ~Txp;
+ regw(ctlr, Cr, Page0|RdABORT|Sta);
+ regw(ctlr, Isr, Rdc);
+
+ /*
+ * Set up the remote DMA address and count.
+ */
+ len = ROUNDUP(len, ctlr->width);
+ regw(ctlr, Rbcr0, len & 0xFF);
+ regw(ctlr, Rbcr1, (len>>8) & 0xFF);
+ regw(ctlr, Rsar0, from & 0xFF);
+ regw(ctlr, Rsar1, (from>>8) & 0xFF);
+
+ /*
+ * Start the remote DMA read and suck the data
+ * out of the I/O port.
+ */
+ regw(ctlr, Cr, Page0|RdREAD|Sta);
+ rdread(ctlr, to, len);
+
+ /*
+ * Wait for the remote DMA to complete. The timeout
+ * is necessary because this routine may be called on
+ * a non-existent chip during initialisation and, due
+ * to the miracles of the bus, it's possible to get this
+ * far and still be talking to a slot full of nothing.
+ */
+ for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--)
+ ;
+
+ regw(ctlr, Isr, Rdc);
+ regw(ctlr, Cr, cr);
+
+ return to;
+}
+
+void*
+dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len)
+{
+ void *v;
+
+ ilock(ctlr);
+ v = _dp8390read(ctlr, to, from, len);
+ iunlock(ctlr);
+
+ return v;
+}
+
+static void*
+dp8390write(Dp8390* ctlr, ulong to, void* from, ulong len)
+{
+ ulong crda;
+ uchar cr;
+ int timo, width;
+
+top:
+ /*
+ * Write some data to offset 'to' in the card's memory
+ * using the DP8390 remote DMA facility, reading it at
+ * 'from' in main memory, via the I/O data port.
+ */
+ cr = regr(ctlr, Cr) & ~Txp;
+ regw(ctlr, Cr, Page0|RdABORT|Sta);
+ regw(ctlr, Isr, Rdc);
+
+ len = ROUNDUP(len, ctlr->width);
+
+ /*
+ * Set up the remote DMA address and count.
+ * This is straight from the DP8390[12D] datasheet,
+ * hence the initial set up for read.
+ * Assumption here that the A7000 EtherV card will
+ * never need a dummyrr.
+ */
+ if(ctlr->dummyrr && (ctlr->width == 1 || ctlr->width == 2)){
+ if(ctlr->width == 2)
+ width = 1;
+ else
+ width = 0;
+ crda = to-1-width;
+ regw(ctlr, Rbcr0, (len+1+width) & 0xFF);
+ regw(ctlr, Rbcr1, ((len+1+width)>>8) & 0xFF);
+ regw(ctlr, Rsar0, crda & 0xFF);
+ regw(ctlr, Rsar1, (crda>>8) & 0xFF);
+ regw(ctlr, Cr, Page0|RdREAD|Sta);
+
+ for(timo=0;; timo++){
+ if(timo > 10000){
+ print("ether8390: dummyrr timeout; assuming nodummyrr\n");
+ ctlr->dummyrr = 0;
+ goto top;
+ }
+ crda = regr(ctlr, Crda0);
+ crda |= regr(ctlr, Crda1)<<8;
+ if(crda == to){
+ /*
+ * Start the remote DMA write and make sure
+ * the registers are correct.
+ */
+ regw(ctlr, Cr, Page0|RdWRITE|Sta);
+
+ crda = regr(ctlr, Crda0);
+ crda |= regr(ctlr, Crda1)<<8;
+ if(crda != to)
+ panic("crda write %d to %d\n", crda, to);
+
+ break;
+ }
+ }
+ }
+ else{
+ regw(ctlr, Rsar0, to & 0xFF);
+ regw(ctlr, Rsar1, (to>>8) & 0xFF);
+ regw(ctlr, Rbcr0, len & 0xFF);
+ regw(ctlr, Rbcr1, (len>>8) & 0xFF);
+ regw(ctlr, Cr, Page0|RdWRITE|Sta);
+ }
+
+ /*
+ * Pump the data into the I/O port
+ * then wait for the remote DMA to finish.
+ */
+ rdwrite(ctlr, from, len);
+ for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--)
+ ;
+
+ regw(ctlr, Isr, Rdc);
+ regw(ctlr, Cr, cr);
+
+ return (void*)to;
+}
+
+static void
+ringinit(Dp8390* ctlr)
+{
+ regw(ctlr, Pstart, ctlr->pstart);
+ regw(ctlr, Pstop, ctlr->pstop);
+ regw(ctlr, Bnry, ctlr->pstop-1);
+
+ regw(ctlr, Cr, Page1|RdABORT|Stp);
+ regw(ctlr, Curr, ctlr->pstart);
+ regw(ctlr, Cr, Page0|RdABORT|Stp);
+
+ ctlr->nxtpkt = ctlr->pstart;
+}
+
+static uchar
+getcurr(Dp8390* ctlr)
+{
+ uchar cr, curr;
+
+ cr = regr(ctlr, Cr) & ~Txp;
+ regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
+ curr = regr(ctlr, Curr);
+ regw(ctlr, Cr, cr);
+
+ return curr;
+}
+
+static void
+receive(Ether* ether)
+{
+ Dp8390 *ctlr;
+ uchar curr, *p;
+ Hdr hdr;
+ ulong count, data, len;
+ RingBuf *ring;
+
+ ctlr = ether->ctlr;
+ for(curr = getcurr(ctlr); ctlr->nxtpkt != curr; curr = getcurr(ctlr)){
+ data = ctlr->nxtpkt*Dp8390BufSz;
+ if(ctlr->ram)
+ memmove(&hdr, (void*)(ether->mem+data), sizeof(Hdr));
+ else
+ _dp8390read(ctlr, &hdr, data, sizeof(Hdr));
+
+ /*
+ * Don't believe the upper byte count, work it
+ * out from the software next-page pointer and
+ * the current next-page pointer.
+ */
+ if(hdr.next > ctlr->nxtpkt)
+ len = hdr.next - ctlr->nxtpkt - 1;
+ else
+ len = (ctlr->pstop-ctlr->nxtpkt) + (hdr.next-ctlr->pstart) - 1;
+ if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr)))
+ len--;
+
+ len = ((len<<8)|hdr.len0)-4;
+
+ /*
+ * Chip is badly scrogged, reinitialise the ring.
+ */
+ if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop
+ || len < 60 || len > sizeof(Etherpkt)){
+ print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%lud\n",
+ hdr.status, hdr.next, hdr.len0, hdr.len1, len);
+ regw(ctlr, Cr, Page0|RdABORT|Stp);
+ ringinit(ctlr);
+ regw(ctlr, Cr, Page0|RdABORT|Sta);
+
+ return;
+ }
+
+ /*
+ * If it's a good packet read it in to the software buffer.
+ * If the packet wraps round the hardware ring, read it in
+ * two pieces.
+ */
+ ring = ðer->rb[ether->ri];
+ if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && ring->owner == Interface){
+ p = ring->pkt;
+ ring->len = len;
+ data += sizeof(Hdr);
+
+ if((data+len) >= ctlr->pstop*Dp8390BufSz){
+ count = ctlr->pstop*Dp8390BufSz - data;
+ if(ctlr->ram)
+ memmove(p, (void*)(ether->mem+data), count);
+ else
+ _dp8390read(ctlr, p, data, count);
+ p += count;
+ data = ctlr->pstart*Dp8390BufSz;
+ len -= count;
+ }
+ if(len){
+ if(ctlr->ram)
+ memmove(p, (void*)(ether->mem+data), len);
+ else
+ _dp8390read(ctlr, p, data, len);
+ }
+
+ /*
+ * Copy the packet to whoever wants it.
+ */
+ ring->owner = Host;
+ ether->ri = NEXT(ether->ri, ether->nrb);
+ }
+
+ /*
+ * Finished with this packet, update the
+ * hardware and software ring pointers.
+ */
+ ctlr->nxtpkt = hdr.next;
+
+ hdr.next--;
+ if(hdr.next < ctlr->pstart)
+ hdr.next = ctlr->pstop-1;
+ regw(ctlr, Bnry, hdr.next);
+ }
+}
+
+static void
+txstart(Ether* ether)
+{
+ int len;
+ Dp8390 *ctlr;
+ RingBuf *ring;
+ uchar minpkt[ETHERMINTU], *rp;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * This routine is called both from the top level and from interrupt
+ * level and expects to be called with ctlr already locked.
+ */
+ if(ether->tbusy)
+ return;
+ ring = ðer->tb[ether->ti];
+ if(ring->owner != Interface)
+ return;
+
+ /*
+ * Make sure the packet is of minimum length;
+ * copy it to the card's memory by the appropriate means;
+ * start the transmission.
+ */
+ len = ring->len;
+ rp = ring->pkt;
+ if(len < ETHERMINTU){
+ rp = minpkt;
+ memmove(rp, ring->pkt, len);
+ memset(rp+len, 0, ETHERMINTU-len);
+ len = ETHERMINTU;
+ }
+
+ if(ctlr->ram)
+ memmove((void*)(ether->mem+ctlr->tstart*Dp8390BufSz), rp, len);
+ else
+ dp8390write(ctlr, ctlr->tstart*Dp8390BufSz, rp, len);
+
+ regw(ctlr, Tbcr0, len & 0xFF);
+ regw(ctlr, Tbcr1, (len>>8) & 0xFF);
+ regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);
+
+ ether->tbusy = 1;
+}
+
+static void
+transmit(Ether* ether)
+{
+ Dp8390 *ctlr;
+
+ ctlr = ether->ctlr;
+
+ ilock(ctlr);
+ txstart(ether);
+ iunlock(ctlr);
+}
+
+static void
+overflow(Ether *ether)
+{
+ Dp8390 *ctlr;
+ uchar txp;
+ int resend;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * The following procedure is taken from the DP8390[12D] datasheet,
+ * it seems pretty adamant that this is what has to be done.
+ */
+ txp = regr(ctlr, Cr) & Txp;
+ regw(ctlr, Cr, Page0|RdABORT|Stp);
+ delay(2);
+ regw(ctlr, Rbcr0, 0);
+ regw(ctlr, Rbcr1, 0);
+
+ resend = 0;
+ if(txp && (regr(ctlr, Isr) & (Txe|Ptx)) == 0)
+ resend = 1;
+
+ regw(ctlr, Tcr, LpbkNIC);
+ regw(ctlr, Cr, Page0|RdABORT|Sta);
+ receive(ether);
+ regw(ctlr, Isr, Ovw);
+ regw(ctlr, Tcr, LpbkNORMAL);
+
+ if(resend)
+ regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Ether *ether;
+ Dp8390 *ctlr;
+ RingBuf *ring;
+ uchar isr, r;
+
+ ether = arg;
+ ctlr = ether->ctlr;
+
+ /*
+ * While there is something of interest,
+ * clear all the interrupts and process.
+ */
+ ilock(ctlr);
+ regw(ctlr, Imr, 0x00);
+ while(isr = (regr(ctlr, Isr) & (Cnt|Ovw|Txe|Rxe|Ptx|Prx))){
+ if(isr & Ovw){
+ overflow(ether);
+ regw(ctlr, Isr, Ovw);
+ }
+
+ /*
+ * Packets have been received.
+ * Take a spin round the ring.
+ */
+ if(isr & (Rxe|Prx)){
+ receive(ether);
+ regw(ctlr, Isr, Rxe|Prx);
+ }
+
+ /*
+ * A packet completed transmission, successfully or
+ * not. Start transmission on the next buffered packet,
+ * and wake the output routine.
+ */
+ if(isr & (Txe|Ptx)){
+ r = regr(ctlr, Tsr);
+ if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){
+ print("dp8390: Tsr#%2.2ux|", r);
+ }
+
+ regw(ctlr, Isr, Txe|Ptx);
+
+ ring = ðer->tb[ether->ti];
+ ring->owner = Host;
+ ether->ti = NEXT(ether->ti, ether->ntb);
+ ether->tbusy = 0;
+ txstart(ether);
+ }
+
+ if(isr & Cnt){
+ regr(ctlr, Cntr0);
+ regr(ctlr, Cntr1);
+ regr(ctlr, Cntr2);
+ regw(ctlr, Isr, Cnt);
+ }
+ }
+ regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
+ iunlock(ctlr);
+}
+
+static void
+attach(Ether* ether)
+{
+ Dp8390 *ctlr;
+ uchar r;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * Enable the chip for transmit/receive.
+ * The init routine leaves the chip in monitor
+ * mode. Clear the missed-packet counter, it
+ * increments while in monitor mode.
+ * Sometimes there's an interrupt pending at this
+ * point but there's nothing in the Isr, so
+ * any pending interrupts are cleared and the
+ * mask of acceptable interrupts is enabled here.
+ */
+ r = Ab;
+ ilock(ctlr);
+ regw(ctlr, Isr, 0xFF);
+ regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);
+ regw(ctlr, Rcr, r);
+ r = regr(ctlr, Cntr2);
+ regw(ctlr, Tcr, LpbkNORMAL);
+ iunlock(ctlr);
+ USED(r);
+}
+
+static void
+detach(Ether* ether)
+{
+ int timo;
+ Dp8390 *ctlr;
+
+ /*
+ * Stop the chip. Set the Stp bit and wait for the chip
+ * to finish whatever was on its tiny mind before it sets
+ * the Rst bit.
+ * The timeout is needed because there may not be a real
+ * chip there if this is called when probing for a device
+ * at boot.
+ */
+ ctlr = ether->ctlr;
+ regw(ctlr, Cr, Page0|RdABORT|Stp);
+ regw(ctlr, Rbcr0, 0);
+ regw(ctlr, Rbcr1, 0);
+ for(timo = 10000; (regr(ctlr, Isr) & Rst) == 0 && timo; timo--)
+ ;
+}
+
+int
+dp8390reset(Ether* ether)
+{
+ Dp8390 *ctlr;
+
+ ctlr = ether->ctlr;
+
+ /*
+ * This is the initialisation procedure described
+ * as 'mandatory' in the datasheet, with references
+ * to the 3C503 technical reference manual.
+ */
+ detach(ether);
+ if(ctlr->width != 1)
+ regw(ctlr, Dcr, Ft4WORD|Ls|Wts);
+ else
+ regw(ctlr, Dcr, Ft4WORD|Ls);
+
+ regw(ctlr, Rbcr0, 0);
+ regw(ctlr, Rbcr1, 0);
+
+ regw(ctlr, Tcr, LpbkNIC);
+ regw(ctlr, Rcr, Mon);
+
+ /*
+ * Init the ring hardware and software ring pointers.
+ * Can't initialise ethernet address as it may not be
+ * known yet.
+ */
+ ringinit(ctlr);
+ regw(ctlr, Tpsr, ctlr->tstart);
+
+ /*
+ * Clear any pending interrupts and mask then all off.
+ */
+ regw(ctlr, Isr, 0xFF);
+ regw(ctlr, Imr, 0);
+
+ /*
+ * Leave the chip initialised,
+ * but in monitor mode.
+ */
+ regw(ctlr, Cr, Page0|RdABORT|Sta);
+
+ /*
+ * Set up the software configuration.
+ */
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+ ether->detach = detach;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ether8390.h
@@ -1,0 +1,71 @@
+/*
+ * Ctlr for the boards using the National Semiconductor DP8390
+ * and SMC 83C90 Network Interface Controller.
+ * Common code is in ether8390.c.
+ */
+typedef struct {
+ Lock;
+
+ ulong port; /* I/O address of 8390 */
+ ulong data; /* I/O data port if no shared memory */
+
+ uchar width; /* data transfer width in bytes */
+ uchar ram; /* true if card has shared memory */
+ uchar dummyrr; /* do dummy remote read */
+
+ uchar nxtpkt; /* receive: software bndry */
+ uchar pstart;
+ uchar pstop;
+
+ int txbusy; /* transmit */
+ uchar tstart; /* 8390 ring addresses */
+} Dp8390;
+
+#define Dp8390BufSz 256
+
+extern int dp8390reset(Ether*);
+extern void *dp8390read(Dp8390*, void*, ulong, ulong);
+extern void dp8390getea(Ether*, uchar*);
+extern void dp8390setea(Ether*);
+
+/*
+ * x86-specific code.
+ */
+#define regr(c, r) inb((c)->port+(r))
+#define regw(c, r, v) outb((c)->port+(r), (v))
+
+static void
+rdread(Dp8390* ctlr, void* to, int len)
+{
+ switch(ctlr->width){
+ default:
+ panic("dp8390 rdread: width %d\n", ctlr->width);
+ break;
+
+ case 2:
+ inss(ctlr->data, to, len/2);
+ break;
+
+ case 1:
+ insb(ctlr->data, to, len);
+ break;
+ }
+}
+
+static void
+rdwrite(Dp8390* ctlr, void* from, int len)
+{
+ switch(ctlr->width){
+ default:
+ panic("dp8390 rdwrite: width %d\n", ctlr->width);
+ break;
+
+ case 2:
+ outss(ctlr->data, from, len/2);
+ break;
+
+ case 1:
+ outsb(ctlr->data, from, len);
+ break;
+ }
+}
--- /dev/null
+++ b/os/boot.original/pc/etherdp83820.c
@@ -1,0 +1,1222 @@
+/*
+ * boot driver for
+ * National Semiconductor DP83820
+ * 10/100/1000 Mb/s Ethernet Network Interface Controller
+ * (Gig-NIC).
+ * Driver assumes little-endian and 32-bit host throughout.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+#define iprint print
+#define waserror() (0)
+#define poperror()
+
+enum { /* Registers */
+ Cr = 0x00, /* Command */
+ Cfg = 0x04, /* Configuration and Media Status */
+ Mear = 0x08, /* MII/EEPROM Access */
+ Ptscr = 0x0C, /* PCI Test Control */
+ Isr = 0x10, /* Interrupt Status */
+ Imr = 0x14, /* Interrupt Mask */
+ Ier = 0x18, /* Interrupt Enable */
+ Ihr = 0x1C, /* Interrupt Holdoff */
+ Txdp = 0x20, /* Transmit Descriptor Pointer */
+ Txdphi = 0x24, /* Transmit Descriptor Pointer Hi */
+ Txcfg = 0x28, /* Transmit Configuration */
+ Gpior = 0x2C, /* General Purpose I/O Control */
+ Rxdp = 0x30, /* Receive Descriptor Pointer */
+ Rxdphi = 0x34, /* Receive Descriptor Pointer Hi */
+ Rxcfg = 0x38, /* Receive Configuration */
+ Pqcr = 0x3C, /* Priority Queueing Control */
+ Wcsr = 0x40, /* Wake on LAN Control/Status */
+ Pcr = 0x44, /* Pause Control/Status */
+ Rfcr = 0x48, /* Receive Filter/Match Control */
+ Rfdr = 0x4C, /* Receive Filter/Match Data */
+ Brar = 0x50, /* Boot ROM Address */
+ Brdr = 0x54, /* Boot ROM Data */
+ Srr = 0x58, /* Silicon Revision */
+ Mibc = 0x5C, /* MIB Control */
+ Mibd = 0x60, /* MIB Data */
+ Txdp1 = 0xA0, /* Txdp Priority 1 */
+ Txdp2 = 0xA4, /* Txdp Priority 2 */
+ Txdp3 = 0xA8, /* Txdp Priority 3 */
+ Rxdp1 = 0xB0, /* Rxdp Priority 1 */
+ Rxdp2 = 0xB4, /* Rxdp Priority 2 */
+ Rxdp3 = 0xB8, /* Rxdp Priority 3 */
+ Vrcr = 0xBC, /* VLAN/IP Receive Control */
+ Vtcr = 0xC0, /* VLAN/IP Transmit Control */
+ Vdr = 0xC4, /* VLAN Data */
+ Ccsr = 0xCC, /* Clockrun Control/Status */
+ Tbicr = 0xE0, /* TBI Control */
+ Tbisr = 0xE4, /* TBI Status */
+ Tanar = 0xE8, /* TBI ANAR */
+ Tanlpar = 0xEC, /* TBI ANLPAR */
+ Taner = 0xF0, /* TBI ANER */
+ Tesr = 0xF4, /* TBI ESR */
+};
+
+enum { /* Cr */
+ Txe = 0x00000001, /* Transmit Enable */
+ Txd = 0x00000002, /* Transmit Disable */
+ Rxe = 0x00000004, /* Receiver Enable */
+ Rxd = 0x00000008, /* Receiver Disable */
+ Txr = 0x00000010, /* Transmitter Reset */
+ Rxr = 0x00000020, /* Receiver Reset */
+ Swien = 0x00000080, /* Software Interrupt Enable */
+ Rst = 0x00000100, /* Reset */
+ TxpriSHFT = 9, /* Tx Priority Queue Select */
+ TxpriMASK = 0x00001E00,
+ RxpriSHFT = 13, /* Rx Priority Queue Select */
+ RxpriMASK = 0x0001E000,
+};
+
+enum { /* Configuration and Media Status */
+ Bem = 0x00000001, /* Big Endian Mode */
+ Ext125 = 0x00000002, /* External 125MHz reference Select */
+ Bromdis = 0x00000004, /* Disable Boot ROM interface */
+ Pesel = 0x00000008, /* Parity Error Detection Action */
+ Exd = 0x00000010, /* Excessive Deferral Abort */
+ Pow = 0x00000020, /* Program Out of Window Timer */
+ Sb = 0x00000040, /* Single Back-off */
+ Reqalg = 0x00000080, /* PCI Bus Request Algorithm */
+ Extstsen = 0x00000100, /* Extended Status Enable */
+ Phydis = 0x00000200, /* Disable PHY */
+ Phyrst = 0x00000400, /* Reset PHY */
+ M64addren = 0x00000800, /* Master 64-bit Addressing Enable */
+ Data64en = 0x00001000, /* 64-bit Data Enable */
+ Pci64det = 0x00002000, /* PCI 64-bit Bus Detected */
+ T64addren = 0x00004000, /* Target 64-bit Addressing Enable */
+ Mwidis = 0x00008000, /* MWI Disable */
+ Mrmdis = 0x00010000, /* MRM Disable */
+ Tmrtest = 0x00020000, /* Timer Test Mode */
+ Spdstsien = 0x00040000, /* PHY Spdsts Interrupt Enable */
+ Lnkstsien = 0x00080000, /* PHY Lnksts Interrupt Enable */
+ Dupstsien = 0x00100000, /* PHY Dupsts Interrupt Enable */
+ Mode1000 = 0x00400000, /* 1000Mb/s Mode Control */
+ Tbien = 0x01000000, /* Ten-Bit Interface Enable */
+ Dupsts = 0x10000000, /* Full Duplex Status */
+ Spdsts100 = 0x20000000, /* SPEED100 Input Pin Status */
+ Spdsts1000 = 0x40000000, /* SPEED1000 Input Pin Status */
+ Lnksts = 0x80000000, /* Link Status */
+};
+
+enum { /* MII/EEPROM Access */
+ Eedi = 0x00000001, /* EEPROM Data In */
+ Eedo = 0x00000002, /* EEPROM Data Out */
+ Eeclk = 0x00000004, /* EEPROM Serial Clock */
+ Eesel = 0x00000008, /* EEPROM Chip Select */
+ Mdio = 0x00000010, /* MII Management Data */
+ Mddir = 0x00000020, /* MII Management Direction */
+ Mdc = 0x00000040, /* MII Management Clock */
+};
+
+enum { /* Interrupts */
+ Rxok = 0x00000001, /* Rx OK */
+ Rxdesc = 0x00000002, /* Rx Descriptor */
+ Rxerr = 0x00000004, /* Rx Packet Error */
+ Rxearly = 0x00000008, /* Rx Early Threshold */
+ Rxidle = 0x00000010, /* Rx Idle */
+ Rxorn = 0x00000020, /* Rx Overrun */
+ Txok = 0x00000040, /* Tx Packet OK */
+ Txdesc = 0x00000080, /* Tx Descriptor */
+ Txerr = 0x00000100, /* Tx Packet Error */
+ Txidle = 0x00000200, /* Tx Idle */
+ Txurn = 0x00000400, /* Tx Underrun */
+ Mib = 0x00000800, /* MIB Service */
+ Swi = 0x00001000, /* Software Interrupt */
+ Pme = 0x00002000, /* Power Management Event */
+ Phy = 0x00004000, /* PHY Interrupt */
+ Hibint = 0x00008000, /* High Bits Interrupt Set */
+ Rxsovr = 0x00010000, /* Rx Status FIFO Overrun */
+ Rtabt = 0x00020000, /* Received Target Abort */
+ Rmabt = 0x00040000, /* Received Master Abort */
+ Sserr = 0x00080000, /* Signalled System Error */
+ Dperr = 0x00100000, /* Detected Parity Error */
+ Rxrcmp = 0x00200000, /* Receive Reset Complete */
+ Txrcmp = 0x00400000, /* Transmit Reset Complete */
+ Rxdesc0 = 0x00800000, /* Rx Descriptor for Priority Queue 0 */
+ Rxdesc1 = 0x01000000, /* Rx Descriptor for Priority Queue 1 */
+ Rxdesc2 = 0x02000000, /* Rx Descriptor for Priority Queue 2 */
+ Rxdesc3 = 0x04000000, /* Rx Descriptor for Priority Queue 3 */
+ Txdesc0 = 0x08000000, /* Tx Descriptor for Priority Queue 0 */
+ Txdesc1 = 0x10000000, /* Tx Descriptor for Priority Queue 1 */
+ Txdesc2 = 0x20000000, /* Tx Descriptor for Priority Queue 2 */
+ Txdesc3 = 0x40000000, /* Tx Descriptor for Priority Queue 3 */
+};
+
+enum { /* Interrupt Enable */
+ Ien = 0x00000001, /* Interrupt Enable */
+};
+
+enum { /* Interrupt Holdoff */
+ IhSHFT = 0, /* Interrupt Holdoff */
+ IhMASK = 0x000000FF,
+ Ihctl = 0x00000100, /* Interrupt Holdoff Control */
+};
+
+enum { /* Transmit Configuration */
+ TxdrthSHFT = 0, /* Tx Drain Threshold */
+ TxdrthMASK = 0x000000FF,
+ FlthSHFT = 16, /* Tx Fill Threshold */
+ FlthMASK = 0x0000FF00,
+ Brstdis = 0x00080000, /* 1000Mb/s Burst Disable */
+ MxdmaSHFT = 20, /* Max Size per Tx DMA Burst */
+ MxdmaMASK = 0x00700000,
+ Ecretryen = 0x00800000, /* Excessive Collision Retry Enable */
+ Atp = 0x10000000, /* Automatic Transmit Padding */
+ Mlb = 0x20000000, /* MAC Loopback */
+ Hbi = 0x40000000, /* Heartbeat Ignore */
+ Csi = 0x80000000, /* Carrier Sense Ignore */
+};
+
+enum { /* Receive Configuration */
+ RxdrthSHFT = 1, /* Rx Drain Threshold */
+ RxdrthMASK = 0x0000003E,
+ Airl = 0x04000000, /* Accept In-Range Length Errored */
+ Alp = 0x08000000, /* Accept Long Packets */
+ Rxfd = 0x10000000, /* Receive Full Duplex */
+ Stripcrc = 0x20000000, /* Strip CRC */
+ Arp = 0x40000000, /* Accept Runt Packets */
+ Aep = 0x80000000, /* Accept Errored Packets */
+};
+
+enum { /* Priority Queueing Control */
+ Txpqen = 0x00000001, /* Transmit Priority Queuing Enable */
+ Txfairen = 0x00000002, /* Transmit Fairness Enable */
+ RxpqenSHFT = 2, /* Receive Priority Queue Enable */
+ RxpqenMASK = 0x0000000C,
+};
+
+enum { /* Pause Control/Status */
+ PscntSHFT = 0, /* Pause Counter Value */
+ PscntMASK = 0x0000FFFF,
+ Pstx = 0x00020000, /* Transmit Pause Frame */
+ PsffloSHFT = 18, /* Rx Data FIFO Lo Threshold */
+ PsffloMASK = 0x000C0000,
+ PsffhiSHFT = 20, /* Rx Data FIFO Hi Threshold */
+ PsffhiMASK = 0x00300000,
+ PsstloSHFT = 22, /* Rx Stat FIFO Hi Threshold */
+ PsstloMASK = 0x00C00000,
+ PssthiSHFT = 24, /* Rx Stat FIFO Hi Threshold */
+ PssthiMASK = 0x03000000,
+ Psrcvd = 0x08000000, /* Pause Frame Received */
+ Psact = 0x10000000, /* Pause Active */
+ Psda = 0x20000000, /* Pause on Destination Address */
+ Psmcast = 0x40000000, /* Pause on Multicast */
+ Psen = 0x80000000, /* Pause Enable */
+};
+
+enum { /* Receive Filter/Match Control */
+ RfaddrSHFT = 0, /* Extended Register Address */
+ RfaddrMASK = 0x000003FF,
+ Ulm = 0x00080000, /* U/L bit mask */
+ Uhen = 0x00100000, /* Unicast Hash Enable */
+ Mhen = 0x00200000, /* Multicast Hash Enable */
+ Aarp = 0x00400000, /* Accept ARP Packets */
+ ApatSHFT = 23, /* Accept on Pattern Match */
+ ApatMASK = 0x07800000,
+ Apm = 0x08000000, /* Accept on Perfect Match */
+ Aau = 0x10000000, /* Accept All Unicast */
+ Aam = 0x20000000, /* Accept All Multicast */
+ Aab = 0x40000000, /* Accept All Broadcast */
+ Rfen = 0x80000000, /* Rx Filter Enable */
+};
+
+enum { /* Receive Filter/Match Data */
+ RfdataSHFT = 0, /* Receive Filter Data */
+ RfdataMASK = 0x0000FFFF,
+ BmaskSHFT = 16, /* Byte Mask */
+ BmaskMASK = 0x00030000,
+};
+
+enum { /* MIB Control */
+ Wrn = 0x00000001, /* Warning Test Indicator */
+ Frz = 0x00000002, /* Freeze All Counters */
+ Aclr = 0x00000004, /* Clear All Counters */
+ Mibs = 0x00000008, /* MIB Counter Strobe */
+};
+
+enum { /* MIB Data */
+ Nmibd = 11, /* Number of MIB Data Registers */
+};
+
+enum { /* VLAN/IP Receive Control */
+ Vtden = 0x00000001, /* VLAN Tag Detection Enable */
+ Vtren = 0x00000002, /* VLAN Tag Removal Enable */
+ Dvtf = 0x00000004, /* Discard VLAN Tagged Frames */
+ Dutf = 0x00000008, /* Discard Untagged Frames */
+ Ipen = 0x00000010, /* IP Checksum Enable */
+ Ripe = 0x00000020, /* Reject IP Checksum Errors */
+ Rtcpe = 0x00000040, /* Reject TCP Checksum Errors */
+ Rudpe = 0x00000080, /* Reject UDP Checksum Errors */
+};
+
+enum { /* VLAN/IP Transmit Control */
+ Vgti = 0x00000001, /* VLAN Global Tag Insertion */
+ Vppti = 0x00000002, /* VLAN Per-Packet Tag Insertion */
+ Gchk = 0x00000004, /* Global Checksum Generation */
+ Ppchk = 0x00000008, /* Per-Packet Checksum Generation */
+};
+
+enum { /* VLAN Data */
+ VtypeSHFT = 0, /* VLAN Type Field */
+ VtypeMASK = 0x0000FFFF,
+ VtciSHFT = 16, /* VLAN Tag Control Information */
+ VtciMASK = 0xFFFF0000,
+};
+
+enum { /* Clockrun Control/Status */
+ Clkrunen = 0x00000001, /* CLKRUN Enable */
+ Pmeen = 0x00000100, /* PME Enable */
+ Pmests = 0x00008000, /* PME Status */
+};
+
+typedef struct {
+ u32 link; /* Link to the next descriptor */
+ u32 bufptr; /* pointer to data Buffer */
+ int cmdsts; /* Command/Status */
+ int extsts; /* optional Extended Status */
+
+ Block* bp; /* Block containing bufptr */
+ u32 unused; /* pad to 64-bit */
+} Desc;
+
+enum { /* Common cmdsts bits */
+ SizeMASK = 0x0000FFFF, /* Descriptor Byte Count */
+ SizeSHFT = 0,
+ Ok = 0x08000000, /* Packet OK */
+ Crc = 0x10000000, /* Suppress/Include CRC */
+ Intr = 0x20000000, /* Interrupt on ownership transfer */
+ More = 0x40000000, /* not last descriptor in a packet */
+ Own = 0x80000000, /* Descriptor Ownership */
+};
+
+enum { /* Transmit cmdsts bits */
+ CcntMASK = 0x000F0000, /* Collision Count */
+ CcntSHFT = 16,
+ Ec = 0x00100000, /* Excessive Collisions */
+ Owc = 0x00200000, /* Out of Window Collision */
+ Ed = 0x00400000, /* Excessive Deferral */
+ Td = 0x00800000, /* Transmit Deferred */
+ Crs = 0x01000000, /* Carrier Sense Lost */
+ Tfu = 0x02000000, /* Transmit FIFO Underrun */
+ Txa = 0x04000000, /* Transmit Abort */
+};
+
+enum { /* Receive cmdsts bits */
+ Irl = 0x00010000, /* In-Range Length Error */
+ Lbp = 0x00020000, /* Loopback Packet */
+ Fae = 0x00040000, /* Frame Alignment Error */
+ Crce = 0x00080000, /* CRC Error */
+ Ise = 0x00100000, /* Invalid Symbol Error */
+ Runt = 0x00200000, /* Runt Packet Received */
+ Long = 0x00400000, /* Too Long Packet Received */
+ DestMASK = 0x01800000, /* Destination Class */
+ DestSHFT = 23,
+ Rxo = 0x02000000, /* Receive Overrun */
+ Rxa = 0x04000000, /* Receive Aborted */
+};
+
+enum { /* extsts bits */
+ EvtciMASK = 0x0000FFFF, /* VLAN Tag Control Information */
+ EvtciSHFT = 0,
+ Vpkt = 0x00010000, /* VLAN Packet */
+ Ippkt = 0x00020000, /* IP Packet */
+ Iperr = 0x00040000, /* IP Checksum Error */
+ Tcppkt = 0x00080000, /* TCP Packet */
+ Tcperr = 0x00100000, /* TCP Checksum Error */
+ Udppkt = 0x00200000, /* UDP Packet */
+ Udperr = 0x00400000, /* UDP Checksum Error */
+};
+
+enum {
+ Nrd = 32, /* was 256 */
+ Nrbf = 4*Nrd,
+ Rbsz = ROUNDUP(sizeof(Etherpkt)+8, 8),
+ Ntd = 8, /* was 128 */
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id;
+
+ int eepromsz; /* address size in bits */
+ ushort* eeprom;
+
+ int* nic;
+ int cfg;
+ int imr;
+
+ Lock alock; /* attach */
+ Lock ilock; /* init */
+ void* alloc; /* base of per-Ctlr allocated data */
+
+ Mii* mii;
+
+ Lock rdlock; /* receive */
+ Desc* rd;
+ int nrd;
+ int nrb;
+ int rdx;
+ int rxcfg;
+
+ Lock tlock; /* transmit */
+ Desc* td;
+ int ntd;
+ int tdh;
+ int tdt;
+ int ntq;
+ int txcfg;
+
+ int rxidle;
+
+ uint mibd[Nmibd];
+
+ int ec;
+ int owc;
+ int ed;
+ int crs;
+ int tfu;
+ int txa;
+};
+
+#define csr32r(c, r) (*((c)->nic+((r)/4)))
+#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
+
+static Ctlr* dp83820ctlrhead;
+static Ctlr* dp83820ctlrtail;
+
+static Lock dp83820rblock; /* free receive Blocks */
+static Block* dp83820rbpool;
+
+static char* dp83820mibs[Nmibd] = {
+ "RXErroredPkts",
+ "RXFCSErrors",
+ "RXMsdPktErrors",
+ "RXFAErrors",
+ "RXSymbolErrors",
+ "RXFrameToLong",
+ "RXIRLErrors",
+ "RXBadOpcodes",
+ "RXPauseFrames",
+ "TXPauseFrames",
+ "TXSQEErrors",
+};
+
+static int
+mdior(Ctlr* ctlr, int n)
+{
+ int data, i, mear, r;
+
+ mear = csr32r(ctlr, Mear);
+ r = ~(Mdc|Mddir) & mear;
+ data = 0;
+ for(i = n-1; i >= 0; i--){
+ if(csr32r(ctlr, Mear) & Mdio)
+ data |= (1<<i);
+ csr32w(ctlr, Mear, Mdc|r);
+ csr32w(ctlr, Mear, r);
+ }
+ csr32w(ctlr, Mear, mear);
+
+ return data;
+}
+
+static void
+mdiow(Ctlr* ctlr, int bits, int n)
+{
+ int i, mear, r;
+
+ mear = csr32r(ctlr, Mear);
+ r = Mddir|(~Mdc & mear);
+ for(i = n-1; i >= 0; i--){
+ if(bits & (1<<i))
+ r |= Mdio;
+ else
+ r &= ~Mdio;
+ csr32w(ctlr, Mear, r);
+ csr32w(ctlr, Mear, Mdc|r);
+ }
+ csr32w(ctlr, Mear, mear);
+}
+
+static int
+dp83820miimir(Mii* mii, int pa, int ra)
+{
+ int data;
+ Ctlr *ctlr;
+
+ ctlr = mii->ctlr;
+
+ /*
+ * MII Management Interface Read.
+ *
+ * Preamble;
+ * ST+OP+PA+RA;
+ * LT + 16 data bits.
+ */
+ mdiow(ctlr, 0xFFFFFFFF, 32);
+ mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
+ data = mdior(ctlr, 18);
+
+ if(data & 0x10000)
+ return -1;
+
+ return data & 0xFFFF;
+}
+
+static int
+dp83820miimiw(Mii* mii, int pa, int ra, int data)
+{
+ Ctlr *ctlr;
+
+ ctlr = mii->ctlr;
+
+ /*
+ * MII Management Interface Write.
+ *
+ * Preamble;
+ * ST+OP+PA+RA+LT + 16 data bits;
+ * Z.
+ */
+ mdiow(ctlr, 0xFFFFFFFF, 32);
+ data &= 0xFFFF;
+ data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
+ mdiow(ctlr, data, 32);
+
+ return 0;
+}
+
+static Block *
+dp83820rballoc(Desc* desc)
+{
+ Block *bp;
+
+ if(desc->bp == nil){
+ ilock(&dp83820rblock);
+ if((bp = dp83820rbpool) == nil){
+ iunlock(&dp83820rblock);
+ desc->bp = nil;
+ desc->cmdsts = Own;
+ return nil;
+ }
+ dp83820rbpool = bp->next;
+ bp->next = nil;
+ iunlock(&dp83820rblock);
+
+ desc->bufptr = PCIWADDR(bp->rp);
+ desc->bp = bp;
+ }
+ else{
+ bp = desc->bp;
+ bp->rp = bp->lim - Rbsz;
+ bp->wp = bp->rp;
+ }
+
+ coherence();
+ desc->cmdsts = Intr|Rbsz;
+
+ return bp;
+}
+
+static void
+dp83820rbfree(Block *bp)
+{
+ bp->rp = bp->lim - Rbsz;
+ bp->wp = bp->rp;
+
+ ilock(&dp83820rblock);
+ bp->next = dp83820rbpool;
+ dp83820rbpool = bp;
+ iunlock(&dp83820rblock);
+}
+
+static void
+dp83820halt(Ctlr* ctlr)
+{
+ int i, timeo;
+
+ ilock(&ctlr->ilock);
+ csr32w(ctlr, Imr, 0);
+ csr32w(ctlr, Ier, 0);
+ csr32w(ctlr, Cr, Rxd|Txd);
+ for(timeo = 0; timeo < 1000; timeo++){
+ if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
+ break;
+ microdelay(1);
+ }
+ csr32w(ctlr, Mibc, Frz);
+ iunlock(&ctlr->ilock);
+
+ if(ctlr->rd != nil){
+ for(i = 0; i < ctlr->nrd; i++){
+ if(ctlr->rd[i].bp == nil)
+ continue;
+ freeb(ctlr->rd[i].bp);
+ ctlr->rd[i].bp = nil;
+ }
+ }
+ if(ctlr->td != nil){
+ for(i = 0; i < ctlr->ntd; i++){
+ if(ctlr->td[i].bp == nil)
+ continue;
+ freeb(ctlr->td[i].bp);
+ ctlr->td[i].bp = nil;
+ }
+ }
+}
+
+static void
+dp83820cfg(Ctlr* ctlr)
+{
+ int cfg;
+
+ /*
+ * Don't know how to deal with a TBI yet.
+ */
+ if(ctlr->mii == nil)
+ return;
+
+ /*
+ * The polarity of these bits is at the mercy
+ * of the board designer.
+ * The correct answer for all speed and duplex questions
+ * should be to query the phy.
+ */
+ cfg = csr32r(ctlr, Cfg);
+ if(!(cfg & Dupsts)){
+ ctlr->rxcfg |= Rxfd;
+ ctlr->txcfg |= Csi|Hbi;
+ iprint("83820: full duplex, ");
+ }
+ else{
+ ctlr->rxcfg &= ~Rxfd;
+ ctlr->txcfg &= ~(Csi|Hbi);
+ iprint("83820: half duplex, ");
+ }
+ csr32w(ctlr, Rxcfg, ctlr->rxcfg);
+ csr32w(ctlr, Txcfg, ctlr->txcfg);
+
+ switch(cfg & (Spdsts1000|Spdsts100)){
+ case Spdsts1000: /* 100Mbps */
+ default: /* 10Mbps */
+ ctlr->cfg &= ~Mode1000;
+ if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
+ iprint("100Mb/s\n");
+ else
+ iprint("10Mb/s\n");
+ break;
+ case Spdsts100: /* 1Gbps */
+ ctlr->cfg |= Mode1000;
+ iprint("1Gb/s\n");
+ break;
+ }
+ csr32w(ctlr, Cfg, ctlr->cfg);
+}
+
+static void
+dp83820init(Ether* edev)
+{
+ int i;
+ Ctlr *ctlr;
+ Desc *desc;
+ uchar *alloc;
+
+ ctlr = edev->ctlr;
+
+ dp83820halt(ctlr);
+
+ /*
+ * Receiver
+ */
+ alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
+ ctlr->rd = (Desc*)alloc;
+ alloc += ctlr->nrd*sizeof(Desc);
+ memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
+ ctlr->rdx = 0;
+ for(i = 0; i < ctlr->nrd; i++){
+ desc = &ctlr->rd[i];
+ desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
+ if(dp83820rballoc(desc) == nil)
+ continue;
+ }
+ csr32w(ctlr, Rxdphi, 0);
+ csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
+
+ for(i = 0; i < Eaddrlen; i += 2){
+ csr32w(ctlr, Rfcr, i);
+ csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
+ }
+ csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
+
+ ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
+ ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
+
+ /*
+ * Transmitter.
+ */
+ ctlr->td = (Desc*)alloc;
+ memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
+ ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
+ for(i = 0; i < ctlr->ntd; i++){
+ desc = &ctlr->td[i];
+ desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
+ }
+ csr32w(ctlr, Txdphi, 0);
+ csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
+
+ ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
+ ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
+
+ ilock(&ctlr->ilock);
+
+ dp83820cfg(ctlr);
+
+ csr32w(ctlr, Mibc, Aclr);
+ ctlr->imr |= Mib;
+
+ csr32w(ctlr, Imr, ctlr->imr);
+
+ /* try coalescing adjacent interrupts; use hold-off interval of 100µs */
+ csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
+
+ csr32w(ctlr, Ier, Ien);
+ csr32w(ctlr, Cr, Rxe|Txe);
+
+ iunlock(&ctlr->ilock);
+}
+
+static void
+dp83820attach(Ether* edev)
+{
+ Block *bp;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ lock(&ctlr->alock);
+ if(ctlr->alloc != nil){
+ unlock(&ctlr->alock);
+ return;
+ }
+
+ if(waserror()){
+err:
+ if(ctlr->mii != nil){
+ free(ctlr->mii);
+ ctlr->mii = nil;
+ }
+ if(ctlr->alloc != nil){
+ free(ctlr->alloc);
+ ctlr->alloc = nil;
+ }
+ unlock(&ctlr->alock);
+ return;
+ }
+
+ if(!(ctlr->cfg & Tbien)){
+ if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+ goto err;
+ ctlr->mii->ctlr = ctlr;
+ ctlr->mii->mir = dp83820miimir;
+ ctlr->mii->miw = dp83820miimiw;
+ if(mii(ctlr->mii, ~0) == 0)
+ goto err;
+ ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
+ ctlr->imr |= Phy;
+ }
+
+ ctlr->nrd = Nrd;
+ ctlr->nrb = Nrbf;
+ ctlr->ntd = Ntd;
+ ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
+ if(ctlr->alloc == nil)
+ goto err;
+
+ /*
+ * the Bill Paul bsd drivers claim that receive buffers must be aligned
+ * on 8-byte boundaries.
+ */
+ for(ctlr->nrb = 0; ctlr->nrb < Nrbf; ctlr->nrb++){
+ if((bp = allocb(Rbsz+8-1)) == nil)
+ break;
+ bp->rp += 8 - (uintptr)bp->rp % 8;
+ bp->wp = bp->rp;
+// bp->free = dp83820rbfree; /* TODO: fix */
+ dp83820rbfree(bp);
+ }
+
+ dp83820init(edev);
+
+ unlock(&ctlr->alock);
+ poperror();
+}
+
+/*
+ * free a list of blocks
+ */
+static void
+freeblist(Block *b)
+{
+ Block *next;
+
+ for(; b != 0; b = next){
+ next = b->next;
+ b->next = 0;
+ freeb(b);
+ }
+}
+
+static void
+toringbuf(Ether *ether, Block *bp)
+{
+ RingBuf *rb = ðer->rb[ether->ri];
+
+ if (rb->owner == Interface) {
+ rb->len = BLEN(bp);
+ memmove(rb->pkt, bp->rp, rb->len);
+ rb->owner = Host;
+ ether->ri = NEXT(ether->ri, ether->nrb);
+ }
+ /* else no one is expecting packets from the network */
+}
+
+static Block *
+fromringbuf(Ether *ether)
+{
+ RingBuf *tb = ðer->tb[ether->ti];
+ Block *bp = allocb(tb->len);
+
+ memmove(bp->wp, tb->pkt, tb->len);
+ memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+ bp->wp += tb->len;
+ return bp;
+}
+
+static void
+dp83820transmit(Ether* edev)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ Desc *desc;
+ RingBuf *tb;
+ int cmdsts, r, x;
+
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->tlock);
+
+ bp = nil;
+ for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
+ desc = &ctlr->td[x];
+ if((cmdsts = desc->cmdsts) & Own)
+ break;
+ if(!(cmdsts & Ok)){
+ if(cmdsts & Ec)
+ ctlr->ec++;
+ if(cmdsts & Owc)
+ ctlr->owc++;
+ if(cmdsts & Ed)
+ ctlr->ed++;
+ if(cmdsts & Crs)
+ ctlr->crs++;
+ if(cmdsts & Tfu)
+ ctlr->tfu++;
+ if(cmdsts & Txa)
+ ctlr->txa++;
+ }
+ desc->bp->next = bp;
+ bp = desc->bp;
+ desc->bp = nil;
+
+ ctlr->ntq--;
+ }
+ ctlr->tdh = x;
+ if(bp != nil)
+ freeblist(bp);
+
+ x = ctlr->tdt;
+// tb = &edev->tb[edev->ti];
+ while(ctlr->ntq < ctlr->ntd - 1 /* && tb->owner == Interface */ ){
+ bp = fromringbuf(edev);
+ if (bp == nil)
+ break;
+
+ /* transmit packet from bp */
+ desc = &ctlr->td[x];
+ desc->bufptr = PCIWADDR(bp->rp);
+ desc->bp = bp;
+ ctlr->ntq++;
+ coherence();
+ desc->cmdsts = Own|Intr|BLEN(bp); /* kick transmitter */
+//print("t");
+ tb = &edev->tb[edev->ti];
+ tb->owner = Host; /* give descriptor back */
+ edev->ti = NEXT(edev->ti, edev->ntb);
+
+ x = NEXT(x, ctlr->ntd);
+ }
+ if(x != ctlr->tdt){
+ ctlr->tdt = x;
+ r = csr32r(ctlr, Cr);
+ csr32w(ctlr, Cr, Txe|r);
+ }
+
+ iunlock(&ctlr->tlock);
+}
+
+static void
+dp83820interrupt(Ureg*, void* arg)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ Desc *desc;
+ Ether *edev;
+ int cmdsts, i, isr, r, x;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
+ if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
+ x = ctlr->rdx;
+ desc = &ctlr->rd[x];
+ while((cmdsts = desc->cmdsts) & Own){
+ if((cmdsts & Ok) && desc->bp != nil){
+ /* receive a packet into desc->bp */
+ bp = desc->bp;
+ desc->bp = nil;
+ // bp->rp = desc->bufptr;
+ bp->wp += cmdsts & SizeMASK;
+
+ toringbuf(edev, bp);
+//print("r");
+ }
+ dp83820rballoc(desc);
+
+ x = NEXT(x, ctlr->nrd);
+ desc = &ctlr->rd[x];
+ }
+ ctlr->rdx = x;
+
+ if(isr & Rxidle){
+ r = csr32r(ctlr, Cr);
+ csr32w(ctlr, Cr, Rxe|r);
+ ctlr->rxidle++;
+ }
+
+ isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
+ }
+
+ if(isr & Txurn){
+ x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
+ r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
+ if(x < ((TxdrthMASK)>>TxdrthSHFT)
+ && x < (2048/32 - r)){
+ ctlr->txcfg &= ~TxdrthMASK;
+ x++;
+ ctlr->txcfg |= x<<TxdrthSHFT;
+ csr32w(ctlr, Txcfg, ctlr->txcfg);
+ }
+ }
+
+ if(isr & (Txurn|Txidle|Txdesc|Txok)){
+ dp83820transmit(edev);
+ isr &= ~(Txurn|Txidle|Txdesc|Txok);
+ }
+
+ if(isr & Mib){
+ for(i = 0; i < Nmibd; i++){
+ r = csr32r(ctlr, Mibd+(i*sizeof(int)));
+ ctlr->mibd[i] += r & 0xFFFF;
+ }
+ isr &= ~Mib;
+ }
+
+ if((isr & Phy) && ctlr->mii != nil){
+ ctlr->mii->mir(ctlr->mii, 1, Bmsr);
+ print("phy: cfg %8.8uX bmsr %4.4uX\n",
+ csr32r(ctlr, Cfg),
+ ctlr->mii->mir(ctlr->mii, 1, Bmsr));
+ dp83820cfg(ctlr);
+ isr &= ~Phy;
+ }
+// TODO fix if(isr)
+// TODO fix iprint("dp83820: isr %8.8uX\n", isr);
+ USED(isr);
+ }
+}
+
+static int
+dp83820detach(Ctlr* ctlr)
+{
+ /*
+ * Soft reset the controller.
+ */
+ csr32w(ctlr, Cr, Rst);
+ delay(1);
+ while(csr32r(ctlr, Cr) & Rst)
+ delay(1);
+ return 0;
+}
+
+static void
+dp83820shutdown(Ether* ether)
+{
+print("dp83820shutdown\n");
+ dp83820detach(ether->ctlr);
+}
+
+static int
+atc93c46r(Ctlr* ctlr, int address)
+{
+ int data, i, mear, r, size;
+
+ /*
+ * Analog Technology, Inc. ATC93C46
+ * or equivalent serial EEPROM.
+ */
+ mear = csr32r(ctlr, Mear);
+ mear &= ~(Eesel|Eeclk|Eedo|Eedi);
+ r = Eesel|mear;
+
+reread:
+ csr32w(ctlr, Mear, r);
+ data = 0x06;
+ for(i = 3-1; i >= 0; i--){
+ if(data & (1<<i))
+ r |= Eedi;
+ else
+ r &= ~Eedi;
+ csr32w(ctlr, Mear, r);
+ csr32w(ctlr, Mear, Eeclk|r);
+ microdelay(1);
+ csr32w(ctlr, Mear, r);
+ microdelay(1);
+ }
+
+ /*
+ * First time through must work out the EEPROM size.
+ */
+ if((size = ctlr->eepromsz) == 0)
+ size = 8;
+
+ for(size = size-1; size >= 0; size--){
+ if(address & (1<<size))
+ r |= Eedi;
+ else
+ r &= ~Eedi;
+ csr32w(ctlr, Mear, r);
+ microdelay(1);
+ csr32w(ctlr, Mear, Eeclk|r);
+ microdelay(1);
+ csr32w(ctlr, Mear, r);
+ microdelay(1);
+ if(!(csr32r(ctlr, Mear) & Eedo))
+ break;
+ }
+ r &= ~Eedi;
+
+ data = 0;
+ for(i = 16-1; i >= 0; i--){
+ csr32w(ctlr, Mear, Eeclk|r);
+ microdelay(1);
+ if(csr32r(ctlr, Mear) & Eedo)
+ data |= (1<<i);
+ csr32w(ctlr, Mear, r);
+ microdelay(1);
+ }
+
+ csr32w(ctlr, Mear, mear);
+
+ if(ctlr->eepromsz == 0){
+ ctlr->eepromsz = 8-size;
+ ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
+ goto reread;
+ }
+
+ return data;
+}
+
+static int
+dp83820reset(Ctlr* ctlr)
+{
+ int i, r;
+ unsigned char sum;
+
+ /*
+ * Soft reset the controller;
+ * read the EEPROM to get the initial settings
+ * of the Cfg and Gpior bits which should be cleared by
+ * the reset.
+ */
+ csr32w(ctlr, Cr, Rst);
+ delay(1);
+ while(csr32r(ctlr, Cr) & Rst)
+ delay(1);
+
+ atc93c46r(ctlr, 0);
+ if(ctlr->eeprom == nil) {
+ print("dp83820reset: no eeprom\n");
+ return -1;
+ }
+ sum = 0;
+ for(i = 0; i < 0x0E; i++){
+ r = atc93c46r(ctlr, i);
+ ctlr->eeprom[i] = r;
+ sum += r;
+ sum += r>>8;
+ }
+
+ if(sum != 0){
+ print("dp83820reset: bad EEPROM checksum\n");
+ return -1;
+ }
+
+#ifdef notdef
+ csr32w(ctlr, Gpior, ctlr->eeprom[4]);
+
+ cfg = Extstsen|Exd;
+ r = csr32r(ctlr, Cfg);
+ if(ctlr->eeprom[5] & 0x0001)
+ cfg |= Ext125;
+ if(ctlr->eeprom[5] & 0x0002)
+ cfg |= M64addren;
+ if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
+ cfg |= Data64en;
+ if(ctlr->eeprom[5] & 0x0008)
+ cfg |= T64addren;
+ if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
+ cfg |= Mwidis;
+ if(ctlr->eeprom[5] & 0x0020)
+ cfg |= Mrmdis;
+ if(ctlr->eeprom[5] & 0x0080)
+ cfg |= Mode1000;
+ if(ctlr->eeprom[5] & 0x0200)
+ cfg |= Tbien|Mode1000;
+ /*
+ * What about RO bits we might have destroyed with Rst?
+ * What about Exd, Tmrtest, Extstsen, Pintctl?
+ * Why does it think it has detected a 64-bit bus when
+ * it hasn't?
+ */
+#else
+ //r = csr32r(ctlr, Cfg);
+ //r &= ~(Mode1000|T64addren|Data64en|M64addren);
+ //csr32w(ctlr, Cfg, r);
+ //csr32w(ctlr, Cfg, 0x2000);
+#endif /* notdef */
+ ctlr->cfg = csr32r(ctlr, Cfg);
+print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
+ ctlr->cfg &= ~(T64addren|Data64en|M64addren);
+ csr32w(ctlr, Cfg, ctlr->cfg);
+ csr32w(ctlr, Mibc, Aclr|Frz);
+
+ return 0;
+}
+
+static void
+dp83820pci(void)
+{
+ int port;
+ Pcidev *p;
+ Ctlr *ctlr;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+ case (0x0022<<16)|0x100B: /* DP83820 (Gig-NIC) */
+ break;
+ }
+
+ port = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0);
+ if(port == 0){
+ print("dp83820: can't map %d @ 0x%8.8luX\n",
+ p->mem[1].size, p->mem[1].bar);
+ continue;
+ }
+
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = port;
+ ctlr->pcidev = p;
+ ctlr->id = p->did<<16 | p->vid;
+
+ ctlr->nic = KADDR(ctlr->port);
+ if(dp83820reset(ctlr)){
+ free(ctlr);
+ continue;
+ }
+ pcisetbme(p);
+
+ if(dp83820ctlrhead != nil)
+ dp83820ctlrtail->next = ctlr;
+ else
+ dp83820ctlrhead = ctlr;
+ dp83820ctlrtail = ctlr;
+ }
+}
+
+int
+dp83820pnp(Ether* edev)
+{
+ int i;
+ Ctlr *ctlr;
+ uchar ea[Eaddrlen];
+
+ if(dp83820ctlrhead == nil)
+ dp83820pci();
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in the hardware.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, edev->ea, Eaddrlen) == 0)
+ for(i = 0; i < Eaddrlen/2; i++){
+ edev->ea[2*i] = ctlr->eeprom[0x0C-i];
+ edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
+ }
+
+ edev->attach = dp83820attach;
+ edev->transmit = dp83820transmit;
+ edev->interrupt = dp83820interrupt;
+ edev->detach = dp83820shutdown;
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/etherec2t.c
@@ -1,0 +1,155 @@
+/*
+ * Supposed NE2000 PCMCIA clones, see the comments in ether2000.c
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ether8390.h"
+
+enum {
+ Data = 0x10, /* offset from I/O base of data port */
+ Reset = 0x1F, /* offset from I/O base of reset port */
+};
+
+static char* ec2tpcmcia[] = {
+ "EC2T", /* Linksys Combo PCMCIA EthernetCard */
+ "PCMPC100", /* EtherFast 10/100 PC Card */
+ "EN2216", /* Accton EtherPair-PCMCIA */
+ "FA410TX", /* Netgear FA410TX */
+ "Network Everywhere", /* Linksys NP10T 10BaseT Card */
+ nil,
+};
+
+int
+ec2treset(Ether* ether)
+{
+ ushort buf[16];
+ ulong port;
+ Dp8390 *ctlr;
+ int i, slot;
+ uchar ea[Eaddrlen], sum, x;
+ char *type;
+
+ /*
+ * Set up the software configuration.
+ * Use defaults for port, irq, mem and size
+ * if not specified.
+ * The manual says 16KB memory, the box
+ * says 32KB. The manual seems to be correct.
+ */
+ if(ether->port == 0)
+ ether->port = 0x300;
+ if(ether->irq == 0)
+ ether->irq = 9;
+ if(ether->mem == 0)
+ ether->mem = 0x4000;
+ if(ether->size == 0)
+ ether->size = 16*1024;
+ port = ether->port;
+
+ //if(ioalloc(ether->port, 0x20, 0, "ec2t") < 0)
+ // return -1;
+ slot = -1;
+ type = nil;
+ for(i = 0; ec2tpcmcia[i] != nil; i++){
+ type = ec2tpcmcia[i];
+ if((slot = pcmspecial(type, ether)) >= 0)
+ break;
+ }
+ if(ec2tpcmcia[i] == nil){
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrncmp(ether->opt[i], "id=", 3))
+ continue;
+ type = ðer->opt[i][3];
+ if((slot = pcmspecial(type, ether)) >= 0)
+ break;
+ }
+ }
+ if(slot < 0){
+ // iofree(port);
+ return -1;
+ }
+
+ ether->ctlr = malloc(sizeof(Dp8390));
+ ctlr = ether->ctlr;
+ ctlr->width = 2;
+ ctlr->ram = 0;
+
+ ctlr->port = port;
+ ctlr->data = port+Data;
+
+ ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz);
+ ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
+ ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz);
+
+ ctlr->dummyrr = 0;
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrcmp(ether->opt[i], "nodummyrr") == 0)
+ ctlr->dummyrr = 0;
+ else if(cistrncmp(ether->opt[i], "dummyrr=", 8) == 0)
+ ctlr->dummyrr = strtol(ðer->opt[i][8], nil, 0);
+ }
+
+ /*
+ * Reset the board. This is done by doing a read
+ * followed by a write to the Reset address.
+ */
+ buf[0] = inb(port+Reset);
+ delay(2);
+ outb(port+Reset, buf[0]);
+ delay(2);
+
+ /*
+ * Init the (possible) chip, then use the (possible)
+ * chip to read the (possible) PROM for ethernet address
+ * and a marker byte.
+ * Could just look at the DP8390 command register after
+ * initialisation has been tried, but that wouldn't be
+ * enough, there are other ethernet boards which could
+ * match.
+ */
+ dp8390reset(ether);
+ sum = 0;
+ if(cistrcmp(type, "PCMPC100") == 0 || cistrcmp(type, "FA410TX") == 0){
+ /*
+ * The PCMPC100 has the ethernet address in I/O space.
+ * There's a checksum over 8 bytes which sums to 0xFF.
+ */
+ for(i = 0; i < 8; i++){
+ x = inb(port+0x14+i);
+ sum += x;
+ buf[i] = (x<<8)|x;
+ }
+ }
+ else{
+ memset(buf, 0, sizeof(buf));
+ dp8390read(ctlr, buf, 0, sizeof(buf));
+ if((buf[0x0E] & 0xFF) == 0x57 && (buf[0x0F] & 0xFF) == 0x57)
+ sum = 0xFF;
+ }
+ if(sum != 0xFF){
+ pcmspecialclose(slot);
+ //iofree(ether->port);
+ free(ether->ctlr);
+ return -1;
+ }
+
+ /*
+ * Stupid machine. Shorts were asked for,
+ * shorts were delivered, although the PROM is a byte array.
+ * Set the ethernet address.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+ for(i = 0; i < sizeof(ether->ea); i++)
+ ether->ea[i] = buf[i];
+ }
+ dp8390setea(ether);
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/etherelnk3.c
@@ -1,0 +1,1897 @@
+/*
+ * Etherlink III, Fast EtherLink and Fast EtherLink XL adapters.
+ * To do:
+ * check robustness in the face of errors (e.g. busmaster & rxUnderrun);
+ * RxEarly and busmaster;
+ * autoSelect;
+ * PCI latency timer and master enable;
+ * errata list;
+ * rewrite all initialisation.
+ *
+ * Product ID:
+ * 9150 ISA 3C509[B]
+ * 9050 ISA 3C509[B]-TP
+ * 9450 ISA 3C509[B]-COMBO
+ * 9550 ISA 3C509[B]-TPO
+ *
+ * 9350 EISA 3C579
+ * 9250 EISA 3C579-TP
+ *
+ * 5920 EISA 3C592-[TP|COMBO|TPO]
+ * 5970 EISA 3C597-TX Fast Etherlink 10BASE-T/100BASE-TX
+ * 5971 EISA 3C597-T4 Fast Etherlink 10BASE-T/100BASE-T4
+ * 5972 EISA 3C597-MII Fast Etherlink 10BASE-T/MII
+ *
+ * 5900 PCI 3C590-[TP|COMBO|TPO]
+ * 5950 PCI 3C595-TX Fast Etherlink Shared 10BASE-T/100BASE-TX
+ * 5951 PCI 3C595-T4 Fast Etherlink Shared 10BASE-T/100BASE-T4
+ * 5952 PCI 3C595-MII Fast Etherlink 10BASE-T/MII
+ *
+ * 9000 PCI 3C900-TPO Etherlink III XL PCI 10BASE-T
+ * 9001 PCI 3C900-COMBO Etherlink III XL PCI 10BASE-T/10BASE-2/AUI
+ * 9005 PCI 3C900B-COMBO Etherlink III XL PCI 10BASE-T/10BASE-2/AUI
+ * 9050 PCI 3C905-TX Fast Etherlink XL Shared 10BASE-T/100BASE-TX
+ * 9051 PCI 3C905-T4 Fast Etherlink Shared 10BASE-T/100BASE-T4
+ * 9055 PCI 3C905B-TX Fast Etherlink Shared 10BASE-T/100BASE-TX
+ * 9200 PCI 3C905C-TX Fast Etherlink Shared 10BASE-T/100BASE-TX
+ *
+ * 9058 PCMCIA 3C589[B]-[TP|COMBO]
+ *
+ * 627C MCA 3C529
+ * 627D MCA 3C529-TP
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+#define XCVRDEBUG if(0)print
+
+enum {
+ IDport = 0x0110, /* anywhere between 0x0100 and 0x01F0 */
+};
+
+enum { /* all windows */
+ CommandR = 0x000E,
+ IntStatusR = 0x000E,
+};
+
+enum { /* Commands */
+ GlobalReset = 0x0000,
+ SelectRegisterWindow = 0x0001,
+ EnableDcConverter = 0x0002,
+ RxDisable = 0x0003,
+ RxEnable = 0x0004,
+ RxReset = 0x0005,
+ Stall = 0x0006, /* 3C90x */
+ TxDone = 0x0007,
+ RxDiscard = 0x0008,
+ TxEnable = 0x0009,
+ TxDisable = 0x000A,
+ TxReset = 0x000B,
+ RequestInterrupt = 0x000C,
+ AcknowledgeInterrupt = 0x000D,
+ SetInterruptEnable = 0x000E,
+ SetIndicationEnable = 0x000F, /* SetReadZeroMask */
+ SetRxFilter = 0x0010,
+ SetRxEarlyThresh = 0x0011,
+ SetTxAvailableThresh = 0x0012,
+ SetTxStartThresh = 0x0013,
+ StartDma = 0x0014, /* initiate busmaster operation */
+ StatisticsEnable = 0x0015,
+ StatisticsDisable = 0x0016,
+ DisableDcConverter = 0x0017,
+ SetTxReclaimThresh = 0x0018, /* PIO-only adapters */
+ PowerUp = 0x001B, /* not all adapters */
+ PowerDownFull = 0x001C, /* not all adapters */
+ PowerAuto = 0x001D, /* not all adapters */
+};
+
+enum { /* (Global|Rx|Tx)Reset command bits */
+ tpAuiReset = 0x0001, /* 10BaseT and AUI transceivers */
+ endecReset = 0x0002, /* internal Ethernet encoder/decoder */
+ networkReset = 0x0004, /* network interface logic */
+ fifoReset = 0x0008, /* FIFO control logic */
+ aismReset = 0x0010, /* autoinitialise state-machine logic */
+ hostReset = 0x0020, /* bus interface logic */
+ dmaReset = 0x0040, /* bus master logic */
+ vcoReset = 0x0080, /* on-board 10Mbps VCO */
+ updnReset = 0x0100, /* upload/download (Rx/TX) logic */
+
+ resetMask = 0x01FF,
+};
+
+enum { /* Stall command bits */
+ upStall = 0x0000,
+ upUnStall = 0x0001,
+ dnStall = 0x0002,
+ dnUnStall = 0x0003,
+};
+
+enum { /* SetRxFilter command bits */
+ receiveIndividual = 0x0001, /* match station address */
+ receiveMulticast = 0x0002,
+ receiveBroadcast = 0x0004,
+ receiveAllFrames = 0x0008, /* promiscuous */
+};
+
+enum { /* StartDma command bits */
+ Upload = 0x0000, /* transfer data from adapter to memory */
+ Download = 0x0001, /* transfer data from memory to adapter */
+};
+
+enum { /* IntStatus bits */
+ interruptLatch = 0x0001,
+ hostError = 0x0002, /* Adapter Failure */
+ txComplete = 0x0004,
+ txAvailable = 0x0008,
+ rxComplete = 0x0010,
+ rxEarly = 0x0020,
+ intRequested = 0x0040,
+ updateStats = 0x0080,
+ transferInt = 0x0100, /* Bus Master Transfer Complete */
+ dnComplete = 0x0200,
+ upComplete = 0x0400,
+ busMasterInProgress = 0x0800,
+ commandInProgress = 0x1000,
+
+ interruptMask = 0x07FE,
+};
+
+#define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a))
+#define STATUS(port) ins((port)+IntStatusR)
+
+enum { /* Window 0 - setup */
+ Wsetup = 0x0000,
+ /* registers */
+ ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */
+ ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */
+ ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */
+ AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */
+ ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */
+ EepromCommand = 0x000A,
+ EepromData = 0x000C,
+ /* AddressConfig Bits */
+ autoSelect9 = 0x0080,
+ xcvrMask9 = 0xC000,
+ /* ConfigControl bits */
+ Ena = 0x0001,
+ base10TAvailable9 = 0x0200,
+ coaxAvailable9 = 0x1000,
+ auiAvailable9 = 0x2000,
+ /* EepromCommand bits */
+ _EepromReadRegister = 0x0080,
+ _EepromRead8bRegister = 0x0230,
+ EepromBusy = 0x8000,
+};
+
+static int EepromReadRegister = _EepromReadRegister;
+
+#define EEPROMCMD(port, cmd, a) outs((port)+EepromCommand, (cmd)|(a))
+#define EEPROMBUSY(port) (ins((port)+EepromCommand) & EepromBusy)
+#define EEPROMDATA(port) ins((port)+EepromData)
+
+enum { /* Window 1 - operating set */
+ Wop = 0x0001,
+ /* registers */
+ Fifo = 0x0000,
+ RxError = 0x0004, /* 3C59[0257] only */
+ RxStatus = 0x0008,
+ Timer = 0x000A,
+ TxStatus = 0x000B,
+ TxFree = 0x000C,
+ /* RxError bits */
+ rxOverrun = 0x0001,
+ runtFrame = 0x0002,
+ alignmentError = 0x0004, /* Framing */
+ crcError = 0x0008,
+ oversizedFrame = 0x0010,
+ dribbleBits = 0x0080,
+ /* RxStatus bits */
+ rxBytes = 0x1FFF, /* 3C59[0257] mask */
+ rxBytes9 = 0x07FF, /* 3C5[078]9 mask */
+ rxError9 = 0x3800, /* 3C5[078]9 error mask */
+ rxOverrun9 = 0x0000,
+ oversizedFrame9 = 0x0800,
+ dribbleBits9 = 0x1000,
+ runtFrame9 = 0x1800,
+ alignmentError9 = 0x2000, /* Framing */
+ crcError9 = 0x2800,
+ rxError = 0x4000,
+ rxIncomplete = 0x8000,
+ /* TxStatus Bits */
+ txStatusOverflow = 0x0004,
+ maxCollisions = 0x0008,
+ txUnderrun = 0x0010,
+ txJabber = 0x0020,
+ interruptRequested = 0x0040,
+ txStatusComplete = 0x0080,
+};
+
+enum { /* Window 2 - station address */
+ Wstation = 0x0002,
+
+ ResetOp905B = 0x000C,
+};
+
+enum { /* Window 3 - FIFO management */
+ Wfifo = 0x0003,
+ /* registers */
+ InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */
+ OtherInt = 0x0004, /* 3C59[0257] */
+ RomControl = 0x0006, /* 3C509B, 3C59[27] */
+ MacControl = 0x0006, /* 3C59[0257] */
+ ResetOptions = 0x0008, /* 3C59[0257] */
+ MediaOptions = 0x0008, /* 3C905B */
+ RxFree = 0x000A,
+ /* InternalConfig bits */
+ disableBadSsdDetect = 0x00000100,
+ ramLocation = 0x00000200, /* 0 external, 1 internal */
+ ramPartition5to3 = 0x00000000,
+ ramPartition3to1 = 0x00010000,
+ ramPartition1to1 = 0x00020000,
+ ramPartition3to5 = 0x00030000,
+ ramPartitionMask = 0x00030000,
+ xcvr10BaseT = 0x00000000,
+ xcvrAui = 0x00100000, /* 10BASE5 */
+ xcvr10Base2 = 0x00300000,
+ xcvr100BaseTX = 0x00400000,
+ xcvr100BaseFX = 0x00500000,
+ xcvrMii = 0x00600000,
+ xcvrMask = 0x00700000,
+ autoSelect = 0x01000000,
+ /* MacControl bits */
+ deferExtendEnable = 0x0001,
+ deferTimerSelect = 0x001E, /* mask */
+ fullDuplexEnable = 0x0020,
+ allowLargePackets = 0x0040,
+ extendAfterCollision = 0x0080, /* 3C90xB */
+ flowControlEnable = 0x0100, /* 3C90xB */
+ vltEnable = 0x0200, /* 3C90xB */
+ /* ResetOptions bits */
+ baseT4Available = 0x0001,
+ baseTXAvailable = 0x0002,
+ baseFXAvailable = 0x0004,
+ base10TAvailable = 0x0008,
+ coaxAvailable = 0x0010,
+ auiAvailable = 0x0020,
+ miiConnector = 0x0040,
+};
+
+enum { /* Window 4 - diagnostic */
+ Wdiagnostic = 0x0004,
+ /* registers */
+ VcoDiagnostic = 0x0002,
+ FifoDiagnostic = 0x0004,
+ NetworkDiagnostic = 0x0006,
+ PhysicalMgmt = 0x0008,
+ MediaStatus = 0x000A,
+ BadSSD = 0x000C,
+ UpperBytesOk = 0x000D,
+ /* FifoDiagnostic bits */
+ txOverrun = 0x0400,
+ rxUnderrun = 0x2000,
+ receiving = 0x8000,
+ /* PhysicalMgmt bits */
+ mgmtClk = 0x0001,
+ mgmtData = 0x0002,
+ mgmtDir = 0x0004,
+ cat5LinkTestDefeat = 0x8000,
+ /* MediaStatus bits */
+ dataRate100 = 0x0002,
+ crcStripDisable = 0x0004,
+ enableSqeStats = 0x0008,
+ collisionDetect = 0x0010,
+ carrierSense = 0x0020,
+ jabberGuardEnable = 0x0040,
+ linkBeatEnable = 0x0080,
+ jabberDetect = 0x0200,
+ polarityReversed = 0x0400,
+ linkBeatDetect = 0x0800,
+ txInProg = 0x1000,
+ dcConverterEnabled = 0x4000,
+ auiDisable = 0x8000, /* 10BaseT transceiver selected */
+};
+
+enum { /* Window 5 - internal state */
+ Wstate = 0x0005,
+ /* registers */
+ TxStartThresh = 0x0000,
+ TxAvailableThresh = 0x0002,
+ RxEarlyThresh = 0x0006,
+ RxFilter = 0x0008,
+ InterruptEnable = 0x000A,
+ IndicationEnable = 0x000C,
+};
+
+enum { /* Window 6 - statistics */
+ Wstatistics = 0x0006,
+ /* registers */
+ CarrierLost = 0x0000,
+ SqeErrors = 0x0001,
+ MultipleColls = 0x0002,
+ SingleCollFrames = 0x0003,
+ LateCollisions = 0x0004,
+ RxOverruns = 0x0005,
+ FramesXmittedOk = 0x0006,
+ FramesRcvdOk = 0x0007,
+ FramesDeferred = 0x0008,
+ UpperFramesOk = 0x0009,
+ BytesRcvdOk = 0x000A,
+ BytesXmittedOk = 0x000C,
+};
+
+enum { /* Window 7 - bus master operations */
+ Wmaster = 0x0007,
+ /* registers */
+ MasterAddress = 0x0000,
+ MasterLen = 0x0006,
+ MasterStatus = 0x000C,
+ /* MasterStatus bits */
+ masterAbort = 0x0001,
+ targetAbort = 0x0002,
+ targetRetry = 0x0004,
+ targetDisc = 0x0008,
+ masterDownload = 0x1000,
+ masterUpload = 0x4000,
+ masterInProgress = 0x8000,
+
+ masterMask = 0xD00F,
+};
+
+enum { /* 3C90x extended register set */
+ Timer905 = 0x001A, /* 8-bits */
+ TxStatus905 = 0x001B, /* 8-bits */
+ PktStatus = 0x0020, /* 32-bits */
+ DnListPtr = 0x0024, /* 32-bits, 8-byte aligned */
+ FragAddr = 0x0028, /* 32-bits */
+ FragLen = 0x002C, /* 16-bits */
+ ListOffset = 0x002E, /* 8-bits */
+ TxFreeThresh = 0x002F, /* 8-bits */
+ UpPktStatus = 0x0030, /* 32-bits */
+ FreeTimer = 0x0034, /* 16-bits */
+ UpListPtr = 0x0038, /* 32-bits, 8-byte aligned */
+
+ /* PktStatus bits */
+ fragLast = 0x00000001,
+ dnCmplReq = 0x00000002,
+ dnStalled = 0x00000004,
+ upCompleteX = 0x00000008,
+ dnCompleteX = 0x00000010,
+ upRxEarlyEnable = 0x00000020,
+ armCountdown = 0x00000040,
+ dnInProg = 0x00000080,
+ counterSpeed = 0x00000010, /* 0 3.2uS, 1 320nS */
+ countdownMode = 0x00000020,
+ /* UpPktStatus bits (dpd->control) */
+ upPktLenMask = 0x00001FFF,
+ upStalled = 0x00002000,
+ upError = 0x00004000,
+ upPktComplete = 0x00008000,
+ upOverrun = 0x00010000, /* RxError<<16 */
+ upRuntFrame = 0x00020000,
+ upAlignmentError = 0x00040000,
+ upCRCError = 0x00080000,
+ upOversizedFrame = 0x00100000,
+ upDribbleBits = 0x00800000,
+ upOverflow = 0x01000000,
+
+ dnIndicate = 0x80000000, /* FrameStartHeader (dpd->control) */
+
+ updnLastFrag = 0x80000000, /* (dpd->len) */
+
+ Nup = 32,
+ Ndn = 64,
+};
+
+/*
+ * Up/Dn Packet Descriptors.
+ * The hardware info (np, control, addr, len) must be 8-byte aligned
+ * and this structure size must be a multiple of 8.
+ */
+typedef struct Pd Pd;
+typedef struct Pd {
+ ulong np; /* next pointer */
+ ulong control; /* FSH or UpPktStatus */
+ ulong addr;
+ ulong len;
+
+ Pd* next;
+ void *vaddr;
+} Pd;
+
+typedef struct {
+ Lock wlock; /* window access */
+
+ int attached;
+ int busmaster;
+ Block* rbp; /* receive buffer */
+
+ Block* txbp; /* FIFO -based transmission */
+ int txthreshold;
+ int txbusy;
+
+ int nup; /* full-busmaster -based reception */
+ void* upbase;
+ Pd* upr;
+ Pd* uphead;
+
+ int ndn; /* full-busmaster -based transmission */
+ void* dnbase;
+ Pd* dnr;
+ Pd* dnhead;
+ Pd* dntail;
+ int dnq;
+
+ long interrupts; /* statistics */
+ long timer[2];
+ long stats[BytesRcvdOk+3];
+
+ int upqmax;
+ int upqmaxhw;
+ ulong upinterrupts;
+ ulong upqueued;
+ ulong upstalls;
+ int dnqmax;
+ int dnqmaxhw;
+ ulong dninterrupts;
+ ulong dnqueued;
+
+ int xcvr; /* transceiver type */
+ int rxstatus9; /* old-style RxStatus register */
+ int rxearly; /* RxEarlyThreshold */
+ int ts; /* threshold shift */
+ int upenabled;
+ int dnenabled;
+} Ctlr;
+
+static void
+init905(Ctlr* ctlr)
+{
+ Pd *pd, *prev;
+ uchar *vaddr;
+
+ /*
+ * Create rings for the receive and transmit sides.
+ * Take care with alignment:
+ * make sure ring base is 8-byte aligned;
+ * make sure each entry is 8-byte aligned.
+ */
+ ctlr->upbase = malloc((ctlr->nup+1)*sizeof(Pd));
+ ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8);
+ vaddr = ialloc((ctlr->nup+1)*ROUNDUP(sizeof(Etherpkt)+4, 8), 8);
+
+ prev = ctlr->upr;
+ for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){
+ pd->np = PADDR(&prev->np);
+ pd->control = 0;
+ pd->vaddr = vaddr;
+ pd->addr = PADDR(vaddr);
+ vaddr += ROUNDUP(sizeof(Etherpkt)+4, 8);
+ pd->len = updnLastFrag|sizeof(Etherpkt);
+
+ pd->next = prev;
+ prev = pd;
+ }
+ ctlr->uphead = ctlr->upr;
+
+ ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd));
+ ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8);
+ vaddr = ialloc((ctlr->ndn+1)*ROUNDUP(sizeof(Etherpkt)+4, 8), 8);
+
+ prev = ctlr->dnr;
+ for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){
+ pd->next = prev;
+ pd->vaddr = vaddr;
+ pd->addr = PADDR(vaddr);
+ vaddr += ROUNDUP(sizeof(Etherpkt)+4, 8);
+ prev = pd;
+ }
+ ctlr->dnhead = ctlr->dnr;
+ ctlr->dntail = ctlr->dnr;
+ ctlr->dnq = 0;
+}
+
+static Block*
+rbpalloc(Block* (*f)(int))
+{
+ Block *bp;
+ ulong addr;
+
+ /*
+ * The receive buffers must be on a 32-byte
+ * boundary for EISA busmastering.
+ */
+ if(bp = f(ROUNDUP(sizeof(Etherpkt), 4) + 31)){
+ addr = (ulong)bp->base;
+ addr = ROUNDUP(addr, 32);
+ bp->rp = (uchar*)addr;
+ }
+
+ return bp;
+}
+
+static uchar*
+startdma(Ether* ether, ulong address)
+{
+ int port, status, w;
+ uchar *wp;
+
+ port = ether->port;
+
+ w = (STATUS(port)>>13) & 0x07;
+ COMMAND(port, SelectRegisterWindow, Wmaster);
+
+ wp = KADDR(inl(port+MasterAddress));
+ status = ins(port+MasterStatus);
+ if(status & (masterInProgress|targetAbort|masterAbort))
+ print("#l%d: BM status 0x%uX\n", ether->ctlrno, status);
+ outs(port+MasterStatus, masterMask);
+ outl(port+MasterAddress, address);
+ outs(port+MasterLen, sizeof(Etherpkt));
+ COMMAND(port, StartDma, Upload);
+
+ COMMAND(port, SelectRegisterWindow, w);
+ return wp;
+}
+
+/* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
+static void
+intrack3c575(ulong *cbfns)
+{
+ cbfns[1] = 0x8000;
+}
+
+static void
+attach(Ether* ether)
+{
+ int port, x;
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
+ ilock(&ctlr->wlock);
+ if(ctlr->attached){
+ iunlock(&ctlr->wlock);
+ return;
+ }
+
+ port = ether->port;
+
+ COMMAND(port, SetRxFilter, receiveIndividual|receiveBroadcast);
+ x = interruptMask;
+ if(ctlr->busmaster == 1)
+ x &= ~(rxEarly|rxComplete);
+ else{
+ if(ctlr->dnenabled)
+ x &= ~transferInt;
+ if(ctlr->upenabled)
+ x &= ~(rxEarly|rxComplete);
+ }
+ COMMAND(port, SetIndicationEnable, x);
+ COMMAND(port, SetInterruptEnable, x);
+ COMMAND(port, RxEnable, 0);
+ COMMAND(port, TxEnable, 0);
+
+ if (ether->mem)
+ /* This must be a cardbus card. Acknowledge the interrupt */
+ intrack3c575(KADDR(ether->mem));
+
+ /*
+ * Prime the busmaster channel for receiving directly into a
+ * receive packet buffer if necessary.
+ */
+ if(ctlr->busmaster == 1)
+ startdma(ether, PADDR(ctlr->rbp->rp));
+ else{
+ if(ctlr->upenabled)
+ outl(port+UpListPtr, PADDR(&ctlr->uphead->np));
+ }
+
+ ctlr->attached = 1;
+ iunlock(&ctlr->wlock);
+
+}
+
+static void
+statistics(Ether* ether)
+{
+ int port, i, u, w;
+ Ctlr *ctlr;
+
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ /*
+ * 3C59[27] require a read between a PIO write and
+ * reading a statistics register.
+ */
+ w = (STATUS(port)>>13) & 0x07;
+ COMMAND(port, SelectRegisterWindow, Wstatistics);
+ STATUS(port);
+
+ for(i = 0; i < UpperFramesOk; i++)
+ ctlr->stats[i] += inb(port+i) & 0xFF;
+ u = inb(port+UpperFramesOk) & 0xFF;
+ ctlr->stats[FramesXmittedOk] += (u & 0x30)<<4;
+ ctlr->stats[FramesRcvdOk] += (u & 0x03)<<8;
+ ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF;
+ ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF;
+
+ switch(ctlr->xcvr){
+
+ case xcvrMii:
+ case xcvr100BaseTX:
+ case xcvr100BaseFX:
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ STATUS(port);
+ ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD);
+ break;
+ }
+
+ COMMAND(port, SelectRegisterWindow, w);
+}
+
+static void
+txstart(Ether* ether)
+{
+ int port, len;
+ Ctlr *ctlr;
+ RingBuf *tb;
+
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ /*
+ * Attempt to top-up the transmit FIFO. If there's room simply
+ * stuff in the packet length (unpadded to a dword boundary), the
+ * packet data (padded) and remove the packet from the queue.
+ * If there's no room post an interrupt for when there is.
+ * This routine is called both from the top level and from interrupt
+ * level and expects to be called with ctlr->wlock already locked
+ * and the correct register window (Wop) in place.
+ */
+ for(tb = ðer->tb[ether->ti]; tb->owner == Interface; tb = ðer->tb[ether->ti]){
+ len = ROUNDUP(tb->len, 4);
+ if(len+4 <= ins(port+TxFree)){
+ outl(port+Fifo, tb->len);
+ outsl(port+Fifo, tb->pkt, len/4);
+ tb->owner = Host;
+ ether->ti = NEXT(ether->ti, ether->ntb);
+ }
+ else{
+ if(ctlr->txbusy == 0){
+ ctlr->txbusy = 1;
+ COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts);
+ }
+ break;
+ }
+ }
+}
+
+static void
+txstart905(Ether* ether)
+{
+ Ctlr *ctlr;
+ int port, stalled, timeo;
+ RingBuf *tb;
+ Pd *pd;
+
+ ctlr = ether->ctlr;
+ port = ether->port;
+
+ /*
+ * Free any completed packets.
+ */
+ pd = ctlr->dntail;
+ while(ctlr->dnq){
+ if(PADDR(&pd->np) == inl(port+DnListPtr))
+ break;
+ ctlr->dnq--;
+ pd = pd->next;
+ }
+ ctlr->dntail = pd;
+
+ stalled = 0;
+ while(ctlr->dnq < (ctlr->ndn-1)){
+ tb = ðer->tb[ether->ti];
+ if(tb->owner != Interface)
+ break;
+
+ pd = ctlr->dnhead->next;
+ pd->np = 0;
+ pd->control = dnIndicate|tb->len;
+ memmove(pd->vaddr, tb->pkt, tb->len);
+ pd->len = updnLastFrag|tb->len;
+
+ tb->owner = Host;
+ ether->ti = NEXT(ether->ti, ether->ntb);
+
+ if(stalled == 0 && ctlr->dnq && inl(port+DnListPtr)){
+ COMMAND(port, Stall, dnStall);
+ for(timeo = 100; (STATUS(port) & commandInProgress) && timeo; timeo--)
+ ;
+ if(timeo == 0)
+ print("#l%d: dnstall %d\n", ether->ctlrno, timeo);
+ stalled = 1;
+ }
+
+ coherence();
+ ctlr->dnhead->np = PADDR(&pd->np);
+ ctlr->dnhead->control &= ~dnIndicate;
+ ctlr->dnhead = pd;
+ if(ctlr->dnq == 0)
+ ctlr->dntail = pd;
+ ctlr->dnq++;
+
+ ctlr->dnqueued++;
+ }
+
+ if(ctlr->dnq > ctlr->dnqmax)
+ ctlr->dnqmax = ctlr->dnq;
+
+ /*
+ * If the adapter is not currently processing anything
+ * and there is something on the queue, start it processing.
+ */
+ if(inl(port+DnListPtr) == 0 && ctlr->dnq)
+ outl(port+DnListPtr, PADDR(&ctlr->dnhead->np));
+ if(stalled)
+ COMMAND(port, Stall, dnUnStall);
+}
+
+static void
+transmit(Ether* ether)
+{
+ Ctlr *ctlr;
+ int port, w;
+
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ ilock(&ctlr->wlock);
+ if(ctlr->dnenabled)
+ txstart905(ether);
+ else{
+ w = (STATUS(port)>>13) & 0x07;
+ COMMAND(port, SelectRegisterWindow, Wop);
+ txstart(ether);
+ COMMAND(port, SelectRegisterWindow, w);
+ }
+ iunlock(&ctlr->wlock);
+}
+
+static void
+receive905(Ether* ether)
+{
+ Ctlr *ctlr;
+ int len, port, q;
+ Pd *pd;
+ RingBuf *rb;
+
+ ctlr = ether->ctlr;
+ port = ether->port;
+
+ if(inl(port+UpPktStatus) & upStalled)
+ ctlr->upstalls++;
+ q = 0;
+ for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){
+ if(!(pd->control & upError)){
+ rb = ðer->rb[ether->ri];
+ if (rb->owner == Interface) {
+ len = pd->control & rxBytes;
+ rb->len = len;
+ memmove(rb->pkt, pd->vaddr, len);
+ rb->owner = Host;
+ ether->ri = NEXT(ether->ri, ether->nrb);
+ }
+ }
+
+ pd->control = 0;
+ COMMAND(port, Stall, upUnStall);
+
+ q++;
+ }
+ ctlr->uphead = pd;
+
+ ctlr->upqueued += q;
+ if(q > ctlr->upqmax)
+ ctlr->upqmax = q;
+}
+
+static void
+receive(Ether* ether)
+{
+ int len, port, rxstatus;
+ RingBuf *rb;
+ Ctlr *ctlr;
+
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
+ if(ctlr->busmaster == 1 && (STATUS(port) & busMasterInProgress))
+ break;
+
+ /*
+ * If there was an error, log it and continue.
+ * Unfortunately the 3C5[078]9 has the error info in the status register
+ * and the 3C59[0257] implement a separate RxError register.
+ */
+ if((rxstatus & rxError) == 0){
+ /*
+ * Packet received. Read it into the next free
+ * ring buffer, if any. Must read len bytes padded
+ * to a doubleword, can be picked out 32-bits at
+ * a time. The CRC is already stripped off.
+ */
+ rb = ðer->rb[ether->ri];
+ if(rb->owner == Interface){
+ len = (rxstatus & rxBytes9);
+ rb->len = len;
+ insl(port+Fifo, rb->pkt, HOWMANY(len, 4));
+
+ rb->owner = Host;
+ ether->ri = NEXT(ether->ri, ether->nrb);
+ }else
+if(debug) print("toss...");
+ }
+else
+if(debug) print("error...");
+
+ /*
+ * All done, discard the packet.
+ */
+ COMMAND(port, RxDiscard, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+ }
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Ether *ether;
+ int port, status, s, txstatus, w, x;
+ Ctlr *ctlr;
+
+ ether = arg;
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ ilock(&ctlr->wlock);
+ status = STATUS(port);
+ if(!(status & (interruptMask|interruptLatch))){
+ iunlock(&ctlr->wlock);
+ return;
+ }
+ w = (status>>13) & 0x07;
+ COMMAND(port, SelectRegisterWindow, Wop);
+
+ ctlr->interrupts++;
+ if(ctlr->busmaster == 2)
+ ctlr->timer[0] += inb(port+Timer905) & 0xFF;
+ else
+ ctlr->timer[0] += inb(port+Timer) & 0xFF;
+
+ do{
+ if(status & hostError){
+ /*
+ * Adapter failure, try to find out why, reset if
+ * necessary. What happens if Tx is active and a reset
+ * occurs, need to retransmit? This probably isn't right.
+ */
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+FifoDiagnostic);
+ COMMAND(port, SelectRegisterWindow, Wop);
+ print("#l%d: status 0x%uX, diag 0x%uX\n",
+ ether->ctlrno, status, x);
+
+ if(x & txOverrun){
+ if(ctlr->busmaster == 0)
+ COMMAND(port, TxReset, 0);
+ else
+ COMMAND(port, TxReset, (updnReset|dmaReset));
+ COMMAND(port, TxEnable, 0);
+ }
+
+ if(x & rxUnderrun){
+ /*
+ * This shouldn't happen...
+ * Reset the receiver and restore the filter and RxEarly
+ * threshold before re-enabling.
+ * Need to restart any busmastering?
+ */
+ COMMAND(port, SelectRegisterWindow, Wstate);
+ s = (port+RxFilter) & 0x000F;
+ COMMAND(port, SelectRegisterWindow, Wop);
+ COMMAND(port, RxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, SetRxFilter, s);
+ COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
+ COMMAND(port, RxEnable, 0);
+ }
+
+ status &= ~hostError;
+ }
+
+ if(status & (transferInt|rxComplete)){
+ receive(ether);
+ status &= ~(transferInt|rxComplete);
+ }
+
+ if(status & (upComplete)){
+ COMMAND(port, AcknowledgeInterrupt, upComplete);
+ receive905(ether);
+ status &= ~upComplete;
+ ctlr->upinterrupts++;
+ }
+
+ if(status & txComplete){
+ /*
+ * Pop the TxStatus stack, accumulating errors.
+ * Adjust the TX start threshold if there was an underrun.
+ * If there was a Jabber or Underrun error, reset
+ * the transmitter, taking care not to reset the dma logic
+ * as a busmaster receive may be in progress.
+ * For all conditions enable the transmitter.
+ */
+ if(ctlr->busmaster == 2)
+ txstatus = port+TxStatus905;
+ else
+ txstatus = port+TxStatus;
+ s = 0;
+ do{
+ if(x = inb(txstatus))
+ outb(txstatus, 0);
+ s |= x;
+ }while(STATUS(port) & txComplete);
+
+ if(s & txUnderrun){
+ if(ctlr->dnenabled){
+ while(inl(port+PktStatus) & dnInProg)
+ ;
+ }
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ while(ins(port+MediaStatus) & txInProg)
+ ;
+ COMMAND(port, SelectRegisterWindow, Wop);
+ if(ctlr->txthreshold < ETHERMAXTU)
+ ctlr->txthreshold += ETHERMINTU;
+ }
+
+ /*
+ * According to the manual, maxCollisions does not require
+ * a TxReset, merely a TxEnable. However, evidence points to
+ * it being necessary on the 3C905. The jury is still out.
+ * On busy or badly configured networks maxCollisions can
+ * happen frequently enough for messages to be annoying so
+ * keep quiet about them by popular request.
+ */
+ if(s & (txJabber|txUnderrun|maxCollisions)){
+ if(ctlr->busmaster == 0)
+ COMMAND(port, TxReset, 0);
+ else
+ COMMAND(port, TxReset, (updnReset|dmaReset));
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
+ if(ctlr->busmaster == 2)
+ outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
+ if(ctlr->dnenabled)
+ status |= dnComplete;
+ }
+
+ if(s & ~(txStatusComplete|maxCollisions))
+ print("#l%d: txstatus 0x%uX, threshold %d\n",
+ ether->ctlrno, s, ctlr->txthreshold);
+ COMMAND(port, TxEnable, 0);
+ status &= ~txComplete;
+ status |= txAvailable;
+ }
+
+ if(status & txAvailable){
+ COMMAND(port, AcknowledgeInterrupt, txAvailable);
+ ctlr->txbusy = 0;
+ txstart(ether);
+ status &= ~txAvailable;
+ }
+
+ if(status & dnComplete){
+ COMMAND(port, AcknowledgeInterrupt, dnComplete);
+ txstart905(ether);
+ status &= ~dnComplete;
+ ctlr->dninterrupts++;
+ }
+
+ if(status & updateStats){
+ statistics(ether);
+ status &= ~updateStats;
+ }
+
+ /*
+ * Currently, this shouldn't happen.
+ */
+ if(status & rxEarly){
+ COMMAND(port, AcknowledgeInterrupt, rxEarly);
+ status &= ~rxEarly;
+ }
+
+ /*
+ * Panic if there are any interrupts not dealt with.
+ */
+ if(status & interruptMask)
+ panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
+
+ COMMAND(port, AcknowledgeInterrupt, interruptLatch);
+ if (ether->mem)
+ intrack3c575((ulong *)KADDR(ether->mem));
+
+ }while((status = STATUS(port)) & (interruptMask|interruptLatch));
+
+ if(ctlr->busmaster == 2)
+ ctlr->timer[1] += inb(port+Timer905) & 0xFF;
+ else
+ ctlr->timer[1] += inb(port+Timer) & 0xFF;
+
+ COMMAND(port, SelectRegisterWindow, w);
+ iunlock(&ctlr->wlock);
+}
+
+static void
+txrxreset(int port)
+{
+ COMMAND(port, TxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, RxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+}
+
+typedef struct Adapter {
+ int port;
+ int irq;
+ int tbdf;
+ ulong cbfns;
+} Adapter;
+static Block* adapter;
+
+static void
+tcmadapter(int port, int irq, int tbdf, ulong cbfns)
+{
+ Block *bp;
+ Adapter *ap;
+
+ bp = allocb(sizeof(Adapter));
+ ap = (Adapter*)bp->rp;
+ ap->port = port;
+ ap->irq = irq;
+ ap->tbdf = tbdf;
+ ap->cbfns = cbfns;
+
+ bp->next = adapter;
+ adapter = bp;
+}
+
+/*
+ * Write two 0 bytes to identify the IDport and then reset the
+ * ID sequence. Then send the ID sequence to the card to get
+ * the card into command state.
+ */
+static void
+idseq(void)
+{
+ int i;
+ uchar al;
+ static int reset, untag;
+
+ /*
+ * One time only:
+ * reset any adapters listening
+ */
+ if(reset == 0){
+ outb(IDport, 0);
+ outb(IDport, 0);
+ outb(IDport, 0xC0);
+ delay(20);
+ reset = 1;
+ }
+
+ outb(IDport, 0);
+ outb(IDport, 0);
+ for(al = 0xFF, i = 0; i < 255; i++){
+ outb(IDport, al);
+ if(al & 0x80){
+ al <<= 1;
+ al ^= 0xCF;
+ }
+ else
+ al <<= 1;
+ }
+
+ /*
+ * One time only:
+ * write ID sequence to get the attention of all adapters;
+ * untag all adapters.
+ * If a global reset is done here on all adapters it will confuse
+ * any ISA cards configured for EISA mode.
+ */
+ if(untag == 0){
+ outb(IDport, 0xD0);
+ untag = 1;
+ }
+}
+
+static ulong
+activate(void)
+{
+ int i;
+ ushort x, acr;
+
+ /*
+ * Do the little configuration dance:
+ *
+ * 2. write the ID sequence to get to command state.
+ */
+ idseq();
+
+ /*
+ * 3. Read the Manufacturer ID from the EEPROM.
+ * This is done by writing the IDPort with 0x87 (0x80
+ * is the 'read EEPROM' command, 0x07 is the offset of
+ * the Manufacturer ID field in the EEPROM).
+ * The data comes back 1 bit at a time.
+ * A delay seems necessary between reading the bits.
+ *
+ * If the ID doesn't match, there are no more adapters.
+ */
+ outb(IDport, 0x87);
+ delay(20);
+ for(x = 0, i = 0; i < 16; i++){
+ delay(20);
+ x <<= 1;
+ x |= inb(IDport) & 0x01;
+ }
+ if(x != 0x6D50)
+ return 0;
+
+ /*
+ * 3. Read the Address Configuration from the EEPROM.
+ * The Address Configuration field is at offset 0x08 in the EEPROM).
+ */
+ outb(IDport, 0x88);
+ for(acr = 0, i = 0; i < 16; i++){
+ delay(20);
+ acr <<= 1;
+ acr |= inb(IDport) & 0x01;
+ }
+
+ return (acr & 0x1F)*0x10 + 0x200;
+}
+
+static void
+tcm509isa(void)
+{
+ int irq, port;
+
+ /*
+ * Attempt to activate all adapters. If adapter is set for
+ * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
+ * it fully.
+ */
+ while(port = activate()){
+ /*
+ * 6. Tag the adapter so it won't respond in future.
+ */
+ outb(IDport, 0xD1);
+ if(port == 0x3F0)
+ continue;
+
+ /*
+ * 6. Activate the adapter by writing the Activate command
+ * (0xFF).
+ */
+ outb(IDport, 0xFF);
+ delay(20);
+
+ /*
+ * 8. Can now talk to the adapter's I/O base addresses.
+ * Use the I/O base address from the acr just read.
+ *
+ * Enable the adapter and clear out any lingering status
+ * and interrupts.
+ */
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ outs(port+ConfigControl, Ena);
+
+ txrxreset(port);
+ COMMAND(port, AcknowledgeInterrupt, 0xFF);
+
+ irq = (ins(port+ResourceConfig)>>12) & 0x0F;
+ tcmadapter(port, irq, BUSUNKNOWN, 0);
+ }
+}
+
+static void
+tcm5XXeisa(void)
+{
+ ushort x;
+ int irq, port, slot;
+
+ /*
+ * Check if this is an EISA machine.
+ * If not, nothing to do.
+ */
+ if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4))
+ return;
+
+ /*
+ * Continue through the EISA slots looking for a match on both
+ * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
+ * If an adapter is found, select window 0, enable it and clear
+ * out any lingering status and interrupts.
+ */
+ for(slot = 1; slot < MaxEISA; slot++){
+ port = slot*0x1000;
+ if(ins(port+0xC80+ManufacturerID) != 0x6D50)
+ continue;
+ x = ins(port+0xC80+ProductID);
+ if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900)
+ continue;
+
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ outs(port+ConfigControl, Ena);
+
+ txrxreset(port);
+ COMMAND(port, AcknowledgeInterrupt, 0xFF);
+
+ irq = (ins(port+ResourceConfig)>>12) & 0x0F;
+ tcmadapter(port, irq, BUSUNKNOWN, 0);
+ }
+}
+
+static void
+tcm59Xpci(Ether *ether)
+{
+ Pcidev *p;
+ int irq, port;
+ ulong bar;
+
+ p = nil;
+ while(p = pcimatch(p, 0x10B7, 0)){
+ if (p->did == 0x5157) {
+ EepromReadRegister = _EepromRead8bRegister;
+
+ /* Map the CardBus functions */
+ bar = pcicfgr32(p, PciBAR2);
+ print("ether#%d: CardBus functions at %.8luX\n", ether->ctlrno, bar & ~KZERO);
+ }
+ else
+ bar = 0;
+
+ /*
+ * Not prepared to deal with memory-mapped
+ * devices yet.
+ */
+ if(!(p->mem[0].bar & 0x01))
+ continue;
+ port = p->mem[0].bar & ~0x01;
+ irq = p->intl;
+ COMMAND(port, GlobalReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+
+ tcmadapter(port, irq, p->tbdf, bar);
+ pcisetbme(p);
+ }
+}
+
+static char* tcmpcmcia[] = {
+ "3C589", /* 3COM 589[ABCD] */
+ "3C562", /* 3COM 562 */
+ "589E", /* 3COM Megahertz 589E */
+ nil,
+};
+
+static int
+tcm5XXpcmcia(Ether* ether)
+{
+ int i;
+
+ for(i = 0; tcmpcmcia[i] != nil; i++){
+ if(!cistrcmp(ether->type, tcmpcmcia[i])){
+ /*
+ * No need for an ioalloc here, the 589 reset
+ * code deals with it.
+ if(ioalloc(ether->port, 0x10, 0, "tcm5XXpcmcia") < 0)
+ return 0;
+ */
+ return ether->port;
+ }
+ }
+
+ return 0;
+}
+
+static void
+setxcvr(int port, int xcvr, int is9)
+{
+ int x;
+
+ if(is9){
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ x = ins(port+AddressConfig) & ~xcvrMask9;
+ x |= (xcvr>>20)<<14;
+ outs(port+AddressConfig, x);
+ }
+ else{
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ x = inl(port+InternalConfig) & ~xcvrMask;
+ x |= xcvr;
+ outl(port+InternalConfig, x);
+ }
+
+ txrxreset(port);
+}
+
+static void
+setfullduplex(int port)
+{
+ int x;
+
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ x = ins(port+MacControl);
+ outs(port+MacControl, fullDuplexEnable|x);
+
+ txrxreset(port);
+}
+
+static int
+miimdi(int port, int n)
+{
+ int data, i;
+
+ /*
+ * Read n bits from the MII Management Register.
+ */
+ data = 0;
+ for(i = n-1; i >= 0; i--){
+ if(ins(port) & mgmtData)
+ data |= (1<<i);
+ microdelay(1);
+ outs(port, mgmtClk);
+ microdelay(1);
+ outs(port, 0);
+ microdelay(1);
+ }
+
+ return data;
+}
+
+static void
+miimdo(int port, int bits, int n)
+{
+ int i, mdo;
+
+ /*
+ * Write n bits to the MII Management Register.
+ */
+ for(i = n-1; i >= 0; i--){
+ if(bits & (1<<i))
+ mdo = mgmtDir|mgmtData;
+ else
+ mdo = mgmtDir;
+ outs(port, mdo);
+ microdelay(1);
+ outs(port, mdo|mgmtClk);
+ microdelay(1);
+ outs(port, mdo);
+ microdelay(1);
+ }
+}
+
+static int
+miir(int port, int phyad, int regad)
+{
+ int data, w;
+
+ w = (STATUS(port)>>13) & 0x07;
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ port += PhysicalMgmt;
+
+ /*
+ * Preamble;
+ * ST+OP+PHYAD+REGAD;
+ * TA + 16 data bits.
+ */
+ miimdo(port, 0xFFFFFFFF, 32);
+ miimdo(port, 0x1800|(phyad<<5)|regad, 14);
+ data = miimdi(port, 18);
+
+ port -= PhysicalMgmt;
+ COMMAND(port, SelectRegisterWindow, w);
+
+ if(data & 0x10000)
+ return -1;
+
+ return data & 0xFFFF;
+}
+
+static void
+scanphy(int port)
+{
+ int i, x;
+
+ for(i = 0; i < 32; i++){
+ if((x = miir(port, i, 2)) == -1 || x == 0)
+ continue;
+ x <<= 6;
+ x |= miir(port, i, 3)>>10;
+ XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
+ USED(x);
+ }
+}
+
+#ifdef notdef
+static struct xxx {
+ int available;
+ int next;
+} xxx[8] = {
+ { base10TAvailable, 1, }, /* xcvr10BaseT -> xcvrAui */
+ { auiAvailable, 3, }, /* xcvrAui -> xcvr10Base2 */
+ { 0, -1, },
+ { coaxAvailable, -1, }, /* xcvr10Base2 -> nowhere */
+ { baseTXAvailable, 5, }, /* xcvr100BaseTX-> xcvr100BaseFX */
+ { baseFXAvailable, -1, }, /* xcvr100BaseFX-> nowhere */
+ { miiConnector, -1, }, /* xcvrMii -> nowhere */
+ { 0, -1, },
+};
+#endif /* notdef */
+
+static struct {
+ char *name;
+ int avail;
+ int xcvr;
+} media[] = {
+ "10BaseT", base10TAvailable, xcvr10BaseT,
+ "10Base2", coaxAvailable, xcvr10Base2,
+ "100BaseTX", baseTXAvailable, xcvr100BaseTX,
+ "100BaseFX", baseFXAvailable, xcvr100BaseFX,
+ "aui", auiAvailable, xcvrAui,
+ "mii", miiConnector, xcvrMii
+};
+
+static int
+autoselect(int port, int xcvr, int is9)
+{
+ int media, x;
+ USED(xcvr);
+
+ /*
+ * Pathetic attempt at automatic media selection.
+ * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
+ * cards operational.
+ * It's a bonus if it works for anything else.
+ */
+ if(is9){
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ x = ins(port+ConfigControl);
+ media = 0;
+ if(x & base10TAvailable9)
+ media |= base10TAvailable;
+ if(x & coaxAvailable9)
+ media |= coaxAvailable;
+ if(x & auiAvailable9)
+ media |= auiAvailable;
+ }
+ else{
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ media = ins(port+ResetOptions);
+ }
+ XCVRDEBUG("autoselect: media %uX\n", media);
+
+ if(media & miiConnector)
+ return xcvrMii;
+
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ XCVRDEBUG("autoselect: media status %uX\n", ins(port+MediaStatus));
+
+ if(media & baseTXAvailable){
+ /*
+ * Must have InternalConfig register.
+ */
+ setxcvr(port, xcvr100BaseTX, is9);
+
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
+ outs(port+MediaStatus, linkBeatEnable|x);
+ delay(10);
+
+ if(ins(port+MediaStatus) & linkBeatDetect)
+ return xcvr100BaseTX;
+ outs(port+MediaStatus, x);
+ }
+
+ if(media & base10TAvailable){
+ setxcvr(port, xcvr10BaseT, is9);
+
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~dcConverterEnabled;
+ outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
+ delay(100);
+
+ XCVRDEBUG("autoselect: 10BaseT media status %uX\n", ins(port+MediaStatus));
+ if(ins(port+MediaStatus) & linkBeatDetect)
+ return xcvr10BaseT;
+ outs(port+MediaStatus, x);
+ }
+
+ /*
+ * Botch.
+ */
+ return autoSelect;
+}
+
+static int
+eepromdata(int port, int offset)
+{
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ while(EEPROMBUSY(port))
+ ;
+ EEPROMCMD(port, EepromReadRegister, offset);
+ while(EEPROMBUSY(port))
+ ;
+ return EEPROMDATA(port);
+}
+
+int
+elnk3reset(Ether* ether)
+{
+ int anar, anlpar, phyaddr, phystat, timeo, xcvr;
+ int busmaster, did, i, j, port, rxearly, rxstatus9, x;
+ Block *bp, **bpp;
+ Adapter *ap;
+ uchar ea[Eaddrlen];
+ Ctlr *ctlr;
+ static int scandone;
+ char *p;
+
+ /*
+ * Scan for adapter on PCI, EISA and finally
+ * using the little ISA configuration dance.
+ */
+ if(scandone == 0){
+ tcm59Xpci(ether);
+ tcm5XXeisa();
+ tcm509isa();
+ scandone = 1;
+ }
+
+ /*
+ * Any adapter matches if no ether->port is supplied,
+ * otherwise the ports must match.
+ */
+ port = 0;
+ bpp = &adapter;
+ for(bp = *bpp; bp; bp = bp->next){
+ ap = (Adapter*)bp->rp;
+ if(ether->port == 0 || ether->port == ap->port){
+ port = ap->port;
+ ether->irq = ap->irq;
+ ether->tbdf = ap->tbdf;
+ ether->mem = ap->cbfns; /* Misuse the mem ref for the cardbus functions */
+ *bpp = bp->next;
+ freeb(bp);
+ break;
+ }
+ bpp = &bp->next;
+ }
+ if(port == 0 && (port = tcm5XXpcmcia(ether)) == 0)
+ return -1;
+
+ /*
+ * Read the DeviceID from the EEPROM, it's at offset 0x03,
+ * and do something depending on capabilities.
+ */
+ switch(did = eepromdata(port, 0x03)){
+
+ case 0x5157: /* 3C575 Cyclone */
+ case 0x4500: /* 3C450 HomePNA Tornado */
+ case 0x6056:
+ case 0x7646: /* 3CSOHO100-TX */
+ case 0x9055: /* 3C905B-TX */
+ case 0x9200: /* 3C905C-TX */
+ /*FALLTHROUGH*/
+ case 0x9000: /* 3C900-TPO */
+ case 0x9001: /* 3C900-COMBO */
+ case 0x9005: /* 3C900B-COMBO */
+ case 0x9050: /* 3C905-TX */
+ case 0x9051: /* 3C905-T4 */
+ if(BUSTYPE(ether->tbdf) != BusPCI)
+ goto buggery;
+ busmaster = 2;
+ goto vortex;
+
+ case 0x5900: /* 3C590-[TP|COMBO|TPO] */
+ case 0x5920: /* 3C592-[TP|COMBO|TPO] */
+ case 0x5950: /* 3C595-TX */
+ case 0x5951: /* 3C595-T4 */
+ case 0x5952: /* 3C595-MII */
+ case 0x5970: /* 3C597-TX */
+ case 0x5971: /* 3C597-T4 */
+ case 0x5972: /* 3C597-MII */
+ busmaster = 1;
+ vortex:
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
+ rxearly = 8188;
+ rxstatus9 = 0;
+ break;
+
+ buggery:
+ default:
+ busmaster = 0;
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ x = ins(port+AddressConfig);
+ xcvr = ((x & xcvrMask9)>>14)<<20;
+ if(x & autoSelect9)
+ xcvr |= autoSelect;
+ rxearly = 2044;
+ rxstatus9 = 1;
+ break;
+ }
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in Wstation.
+ * The EEPROM returns 16-bits at a time.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+ for(i = 0; i < Eaddrlen/2; i++){
+ x = eepromdata(port, i);
+ ether->ea[2*i] = x>>8;
+ ether->ea[2*i+1] = x;
+ }
+ }
+
+ COMMAND(port, SelectRegisterWindow, Wstation);
+ for(i = 0; i < Eaddrlen; i++)
+ outb(port+i, ether->ea[i]);
+
+ /*
+ * Enable the transceiver if necessary and determine whether
+ * busmastering can be used. Due to bugs in the first revision
+ * of the 3C59[05], don't use busmastering at 10Mbps.
+ */
+ XCVRDEBUG("reset: xcvr %uX\n", xcvr);
+
+ /*
+ * Allow user to specify desired media in plan9.ini
+ */
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrncmp(ether->opt[i], "media=", 6) != 0)
+ continue;
+ p = ether->opt[i]+6;
+ for(j = 0; j < nelem(media); j++)
+ if(cistrcmp(p, media[j].name) == 0)
+ xcvr = media[j].xcvr;
+ }
+
+ /*
+ * forgive me, but i am weak
+ */
+ switch(did){
+ default:
+ if(xcvr & autoSelect)
+ xcvr = autoselect(port, xcvr, rxstatus9);
+ break;
+ case 0x4500:
+ case 0x5157:
+ case 0x6056:
+ case 0x7646:
+ case 0x9055:
+ case 0x9200:
+ xcvr = xcvrMii;
+ txrxreset(port);
+ XCVRDEBUG("905[BC] reset ops 0x%uX\n", ins(port+ResetOp905B));
+
+ if (did == 0x5157) {
+ ushort reset_opts;
+
+ COMMAND(port, SelectRegisterWindow, Wstation);
+ reset_opts = ins(port + ResetOp905B);
+ reset_opts |= 0x0010; /* Invert LED */
+ outs(port + ResetOp905B, reset_opts);
+ }
+ break;
+ }
+ XCVRDEBUG("autoselect returns: xcvr %uX, did 0x%uX\n", xcvr, did);
+
+ switch(xcvr){
+
+ case xcvrMii:
+ /*
+ * Quick hack.
+ scanphy(port);
+ */
+ phyaddr = (did == 0x5157)? 0: 24;
+ for(i = 0; i < 7; i++)
+ XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
+ XCVRDEBUG("\n");
+
+ for(timeo = 0; timeo < 30; timeo++){
+ phystat = miir(port, phyaddr, 0x01);
+ if(phystat & 0x20)
+ break;
+ XCVRDEBUG(" %2.2uX", phystat);
+ delay(100);
+ }
+ XCVRDEBUG(" %2.2uX", miir(port, phyaddr, 0x01));
+ XCVRDEBUG("\n");
+
+ anar = miir(port, phyaddr, 0x04);
+ anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
+ anar &= anlpar;
+ miir(port, phyaddr, 0x00);
+ XCVRDEBUG("mii an: %uX anlp: %uX r0:%uX r1:%uX\n",
+ anar, anlpar, miir(port, phyaddr, 0x00),
+ miir(port, phyaddr, 0x01));
+ for(i = 0; i < ether->nopt; i++){
+ if(cistrcmp(ether->opt[i], "fullduplex") == 0)
+ anar |= 0x0100;
+ else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
+ anar |= 0x0100;
+ else if(cistrcmp(ether->opt[i], "force100") == 0)
+ anar |= 0x0080;
+ }
+ XCVRDEBUG("mii anar: %uX\n", anar);
+ if(anar & 0x0100){ /* 100BASE-TXFD */
+ setfullduplex(port);
+ }
+ else if(anar & 0x0200){ /* 100BASE-T4 */
+ /* nothing to do */
+ }
+ else if(anar & 0x0080){ /* 100BASE-TX */
+ /* nothing to do */;
+ }
+ else if(anar & 0x0040) /* 10BASE-TFD */
+ setfullduplex(port);
+ else{ /* 10BASE-T */
+ /* nothing to do */;
+ }
+ break;
+
+ case xcvr100BaseTX:
+ case xcvr100BaseFX:
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ x = inl(port+InternalConfig) & ~ramPartitionMask;
+ outl(port+InternalConfig, x|ramPartition1to1);
+
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
+ x |= linkBeatEnable;
+ outs(port+MediaStatus, x);
+ break;
+
+ case xcvr10BaseT:
+ /*
+ * Enable Link Beat and Jabber to start the
+ * transceiver.
+ */
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~dcConverterEnabled;
+ x |= linkBeatEnable|jabberGuardEnable;
+ outs(port+MediaStatus, x);
+
+ if((did & 0xFF00) == 0x5900)
+ busmaster = 0;
+ break;
+
+ case xcvr10Base2:
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
+ outs(port+MediaStatus, x);
+
+ /*
+ * Start the DC-DC converter.
+ * Wait > 800 microseconds.
+ */
+ COMMAND(port, EnableDcConverter, 0);
+ delay(1);
+ break;
+ }
+
+ /*
+ * Wop is the normal operating register set.
+ * The 3C59[0257] adapters allow access to more than one register window
+ * at a time, but there are situations where switching still needs to be
+ * done, so just do it.
+ * Clear out any lingering Tx status.
+ */
+ COMMAND(port, SelectRegisterWindow, Wop);
+ if(busmaster == 2)
+ x = port+TxStatus905;
+ else
+ x = port+TxStatus;
+ while(inb(x))
+ outb(x, 0);
+
+ /*
+ * Allocate a controller structure, clear out the
+ * adapter statistics, clear the statistics logged into ctlr
+ * and enable statistics collection. Xcvr is needed in order
+ * to collect the BadSSD statistics.
+ */
+ ether->ctlr = malloc(sizeof(Ctlr));
+ ctlr = ether->ctlr;
+
+ ilock(&ctlr->wlock);
+ ctlr->xcvr = xcvr;
+ statistics(ether);
+ memset(ctlr->stats, 0, sizeof(ctlr->stats));
+
+ ctlr->busmaster = busmaster;
+ ctlr->xcvr = xcvr;
+ ctlr->rxstatus9 = rxstatus9;
+ ctlr->rxearly = rxearly;
+ if(rxearly >= 2048)
+ ctlr->ts = 2;
+
+ COMMAND(port, StatisticsEnable, 0);
+
+ /*
+ * Allocate any receive buffers.
+ */
+ if (ctlr->busmaster == 2) {
+ ctlr->dnenabled = 1;
+
+ /*
+ * 10MUpldBug.
+ * Disabling is too severe, can use receive busmastering at
+ * 100Mbps OK, but how to tell which rate is actually being used -
+ * the 3c905 always seems to have dataRate100 set?
+ * Believe the bug doesn't apply if upRxEarlyEnable is set
+ * and the threshold is set such that uploads won't start
+ * until the whole packet has been received.
+ */
+ ctlr->upenabled = 1;
+ x = eepromdata(port, 0x0F);
+ if(!(x & 0x01))
+ outl(port+PktStatus, upRxEarlyEnable);
+
+ ctlr->nup = Nup;
+ ctlr->ndn = Ndn;
+ init905(ctlr);
+ outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
+ }
+
+ /*
+ * Set a base TxStartThresh which will be incremented
+ * if any txUnderrun errors occur and ensure no RxEarly
+ * interrupts happen.
+ */
+ ctlr->txthreshold = ETHERMAXTU/2;
+ COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
+ COMMAND(port, SetRxEarlyThresh, rxearly>>ctlr->ts);
+
+ iunlock(&ctlr->wlock);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ ether->port = port;
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/etherelnk3x.c
@@ -1,0 +1,1074 @@
+/*
+ * Etherlink III and Fast EtherLink adapters.
+ * To do:
+ * autoSelect;
+ * busmaster channel;
+ * PCMCIA;
+ * PCI latency timer and master enable;
+ * errata list.
+ *
+ * Product ID:
+ * 9150 ISA 3C509[B]
+ * 9050 ISA 3C509[B]-TP
+ * 9450 ISA 3C509[B]-COMBO
+ * 9550 ISA 3C509[B]-TPO
+ *
+ * 9350 EISA 3C579
+ * 9250 EISA 3C579-TP
+ *
+ * 5920 EISA 3C592-[TP|COMBO|TPO]
+ * 5970 EISA 3C597-TX Fast Etherlink 10BASE-T/100BASE-TX
+ * 5971 EISA 3C597-T4 Fast Etherlink 10BASE-T/100BASE-T4
+ * 5972 EISA 3C597-MII Fast Etherlink 10BASE-T/MII
+ *
+ * 5900 PCI 3C590-[TP|COMBO|TPO]
+ * 5950 PCI 3C595-TX Fast Etherlink Shared 10BASE-T/100BASE-TX
+ * 5951 PCI 3C595-T4 Fast Etherlink Shared 10BASE-T/100BASE-T4
+ * 5952 PCI 3C595-MII Fast Etherlink 10BASE-T/MII
+ *
+ * 9058 PCMCIA 3C589[B]-[TP|COMBO]
+ *
+ * 627C MCA 3C529
+ * 627D MCA 3C529-TP
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+enum {
+ IDport = 0x0110, /* anywhere between 0x0100 and 0x01F0 */
+};
+
+enum { /* all windows */
+ Command = 0x000E,
+ IntStatus = 0x000E,
+};
+
+enum { /* Commands */
+ GlobalReset = 0x0000,
+ SelectRegisterWindow = 0x0001,
+ EnableDcConverter = 0x0002,
+ RxDisable = 0x0003,
+ RxEnable = 0x0004,
+ RxReset = 0x0005,
+ TxDone = 0x0007,
+ RxDiscard = 0x0008,
+ TxEnable = 0x0009,
+ TxDisable = 0x000A,
+ TxReset = 0x000B,
+ RequestInterrupt = 0x000C,
+ AcknowledgeInterrupt = 0x000D,
+ SetInterruptEnable = 0x000E,
+ SetIndicationEnable = 0x000F, /* SetReadZeroMask */
+ SetRxFilter = 0x0010,
+ SetRxEarlyThresh = 0x0011,
+ SetTxAvailableThresh = 0x0012,
+ SetTxStartThresh = 0x0013,
+ StartDma = 0x0014, /* initiate busmaster operation */
+ StatisticsEnable = 0x0015,
+ StatisticsDisable = 0x0016,
+ DisableDcConverter = 0x0017,
+ SetTxReclaimThresh = 0x0018, /* PIO-only adapters */
+ PowerUp = 0x001B, /* not all adapters */
+ PowerDownFull = 0x001C, /* not all adapters */
+ PowerAuto = 0x001D, /* not all adapters */
+};
+
+enum { /* (Global|Rx|Tx)Reset command bits */
+ tpAuiReset = 0x0001, /* 10BaseT and AUI transceivers */
+ endecReset = 0x0002, /* internal Ethernet encoder/decoder */
+ networkReset = 0x0004, /* network interface logic */
+ fifoReset = 0x0008, /* FIFO control logic */
+ aismReset = 0x0010, /* autoinitialise state-machine logic */
+ hostReset = 0x0020, /* bus interface logic */
+ dmaReset = 0x0040, /* bus master logic */
+ vcoReset = 0x0080, /* on-board 10Mbps VCO */
+
+ resetMask = 0x00FF,
+};
+
+enum { /* SetRxFilter command bits */
+ receiveIndividual = 0x0001, /* match station address */
+ receiveMulticast = 0x0002,
+ receiveBroadcast = 0x0004,
+ receiveAllFrames = 0x0008, /* promiscuous */
+};
+
+enum { /* StartDma command bits */
+ Upload = 0x0000, /* transfer data from adapter to memory */
+ Download = 0x0001, /* transfer data from memory to adapter */
+};
+
+enum { /* IntStatus bits */
+ interruptLatch = 0x0001,
+ hostError = 0x0002, /* Adapter Failure */
+ txComplete = 0x0004,
+ txAvailable = 0x0008,
+ rxComplete = 0x0010,
+ rxEarly = 0x0020,
+ intRequested = 0x0040,
+ updateStats = 0x0080,
+ transferInt = 0x0100, /* Bus Master Transfer Complete */
+ busMasterInProgress = 0x0800,
+ commandInProgress = 0x1000,
+
+ interruptMask = 0x01FE,
+};
+
+#define COMMAND(port, cmd, a) outs((port)+Command, ((cmd)<<11)|(a))
+#define STATUS(port) ins((port)+IntStatus)
+
+enum { /* Window 0 - setup */
+ Wsetup = 0x0000,
+ /* registers */
+ ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */
+ ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */
+ ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */
+ AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */
+ ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */
+ EepromCommand = 0x000A,
+ EepromData = 0x000C,
+ /* AddressConfig Bits */
+ autoSelect9 = 0x0080,
+ xcvrMask9 = 0xC000,
+ /* ConfigControl bits */
+ Ena = 0x0001,
+ /* EepromCommand bits */
+ EepromReadRegister = 0x0080,
+ EepromBusy = 0x8000,
+};
+
+#define EEPROMCMD(port, cmd, a) outs((port)+EepromCommand, (cmd)|(a))
+#define EEPROMBUSY(port) (ins((port)+EepromCommand) & EepromBusy)
+#define EEPROMDATA(port) ins((port)+EepromData)
+
+enum { /* Window 1 - operating set */
+ Wop = 0x0001,
+ /* registers */
+ Fifo = 0x0000,
+ RxError = 0x0004, /* 3C59[0257] only */
+ RxStatus = 0x0008,
+ Timer = 0x000A,
+ TxStatus = 0x000B,
+ TxFree = 0x000C,
+ /* RxError bits */
+ rxOverrun = 0x0001,
+ runtFrame = 0x0002,
+ alignmentError = 0x0004, /* Framing */
+ crcError = 0x0008,
+ oversizedFrame = 0x0010,
+ dribbleBits = 0x0080,
+ /* RxStatus bits */
+ rxBytes = 0x1FFF, /* 3C59[0257] mask */
+ rxBytes9 = 0x07FF, /* 3C5[078]9 mask */
+ rxError9 = 0x3800, /* 3C5[078]9 error mask */
+ rxOverrun9 = 0x0000,
+ oversizedFrame9 = 0x0800,
+ dribbleBits9 = 0x1000,
+ runtFrame9 = 0x1800,
+ alignmentError9 = 0x2000, /* Framing */
+ crcError9 = 0x2800,
+ rxError = 0x4000,
+ rxIncomplete = 0x8000,
+ /* TxStatus Bits */
+ txStatusOverflow = 0x0004,
+ maxCollisions = 0x0008,
+ txUnderrun = 0x0010,
+ txJabber = 0x0020,
+ interruptRequested = 0x0040,
+ txStatusComplete = 0x0080,
+};
+
+enum { /* Window 2 - station address */
+ Wstation = 0x0002,
+};
+
+enum { /* Window 3 - FIFO management */
+ Wfifo = 0x0003,
+ /* registers */
+ InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */
+ OtherInt = 0x0004, /* 3C59[0257] */
+ RomControl = 0x0006, /* 3C509B, 3C59[27] */
+ MacControl = 0x0006, /* 3C59[0257] */
+ ResetOptions = 0x0008, /* 3C59[0257] */
+ RxFree = 0x000A,
+ /* InternalConfig bits */
+ disableBadSsdDetect = 0x00000100,
+ ramLocation = 0x00000200, /* 0 external, 1 internal */
+ ramPartition5to3 = 0x00000000,
+ ramPartition3to1 = 0x00010000,
+ ramPartition1to1 = 0x00020000,
+ ramPartition3to5 = 0x00030000,
+ ramPartitionMask = 0x00030000,
+ xcvr10BaseT = 0x00000000,
+ xcvrAui = 0x00100000, /* 10BASE5 */
+ xcvr10Base2 = 0x00300000,
+ xcvr100BaseTX = 0x00400000,
+ xcvr100BaseFX = 0x00500000,
+ xcvrMii = 0x00600000,
+ xcvrMask = 0x00700000,
+ autoSelect = 0x01000000,
+ /* MacControl bits */
+ deferExtendEnable = 0x0001,
+ deferTimerSelect = 0x001E, /* mask */
+ fullDuplexEnable = 0x0020,
+ allowLargePackets = 0x0040,
+ /* ResetOptions bits */
+ baseT4Available = 0x0001,
+ baseTXAvailable = 0x0002,
+ baseFXAvailable = 0x0004,
+ base10TAvailable = 0x0008,
+ coaxAvailable = 0x0010,
+ auiAvailable = 0x0020,
+ miiConnector = 0x0040,
+};
+
+enum { /* Window 4 - diagnostic */
+ Wdiagnostic = 0x0004,
+ /* registers */
+ VcoDiagnostic = 0x0002,
+ FifoDiagnostic = 0x0004,
+ NetworkDiagnostic = 0x0006,
+ PhysicalMgmt = 0x0008,
+ MediaStatus = 0x000A,
+ BadSSD = 0x000C,
+ /* FifoDiagnostic bits */
+ txOverrun = 0x0400,
+ rxUnderrun = 0x2000,
+ receiving = 0x8000,
+ /* MediaStatus bits */
+ dataRate100 = 0x0002,
+ crcStripDisable = 0x0004,
+ enableSqeStats = 0x0008,
+ collisionDetect = 0x0010,
+ carrierSense = 0x0020,
+ jabberGuardEnable = 0x0040,
+ linkBeatEnable = 0x0080,
+ jabberDetect = 0x0200,
+ polarityReversed = 0x0400,
+ linkBeatDetect = 0x0800,
+ txInProg = 0x1000,
+ dcConverterEnabled = 0x4000,
+ auiDisable = 0x8000,
+};
+
+enum { /* Window 5 - internal state */
+ Wstate = 0x0005,
+ /* registers */
+ TxStartThresh = 0x0000,
+ TxAvalableThresh = 0x0002,
+ RxEarlyThresh = 0x0006,
+ RxFilter = 0x0008,
+ InterruptEnable = 0x000A,
+ IndicationEnable = 0x000C,
+};
+
+enum { /* Window 6 - statistics */
+ Wstatistics = 0x0006,
+ /* registers */
+ CarrierLost = 0x0000,
+ SqeErrors = 0x0001,
+ MultipleColls = 0x0002,
+ SingleCollFrames = 0x0003,
+ LateCollisions = 0x0004,
+ RxOverruns = 0x0005,
+ FramesXmittedOk = 0x0006,
+ FramesRcvdOk = 0x0007,
+ FramesDeferred = 0x0008,
+ UpperFramesOk = 0x0009,
+ BytesRcvdOk = 0x000A,
+ BytesXmittedOk = 0x000C,
+};
+
+enum { /* Window 7 - bus master operations */
+ Wmaster = 0x0007,
+ /* registers */
+ MasterAddress = 0x0000,
+ MasterLen = 0x0006,
+ MasterStatus = 0x000C,
+ /* MasterStatus bits */
+ masterAbort = 0x0001,
+ targetAbort = 0x0002,
+ targetRetry = 0x0004,
+ targetDisc = 0x0008,
+ masterDownload = 0x1000,
+ masterUpload = 0x4000,
+ masterInProgress = 0x8000,
+
+ masterMask = 0xD00F,
+};
+
+typedef struct {
+ int txthreshold;
+} Ctlr;
+
+static void
+attach(Ether* ether)
+{
+ int port, x;
+
+ port = ether->port;
+
+ /*
+ * Set the receiver packet filter for this and broadcast addresses,
+ * set the interrupt masks for all interrupts, enable the receiver
+ * and transmitter.
+ */
+ x = receiveBroadcast|receiveIndividual;
+ COMMAND(port, SetRxFilter, x);
+
+ x = interruptMask|interruptLatch;
+ COMMAND(port, SetIndicationEnable, x);
+ COMMAND(port, SetInterruptEnable, x);
+
+ COMMAND(port, RxEnable, 0);
+ COMMAND(port, TxEnable, 0);
+}
+
+static void
+transmit(Ether* ether)
+{
+ int port, len;
+ RingBuf *tb;
+
+ /*
+ * Attempt to top-up the transmit FIFO. If there's room simply
+ * stuff in the packet length (unpadded to a dword boundary), the
+ * packet data (padded) and remove the packet from the queue.
+ * If there's no room post an interrupt for when there is.
+ * This routine is called both from the top level and from interrupt
+ * level.
+ */
+ port = ether->port;
+ for(tb = ðer->tb[ether->ti]; tb->owner == Interface; tb = ðer->tb[ether->ti]){
+ len = ROUNDUP(tb->len, 4);
+ if(len+4 <= ins(port+TxFree)){
+ outl(port+Fifo, tb->len);
+ outsl(port+Fifo, tb->pkt, len/4);
+ tb->owner = Host;
+ ether->ti = NEXT(ether->ti, ether->ntb);
+ }
+ else{
+ COMMAND(port, SetTxAvailableThresh, len);
+ break;
+ }
+ }
+}
+
+static void
+receive(Ether* ether)
+{
+ int len, port, rxstatus;
+ RingBuf *rb;
+
+ port = ether->port;
+
+ while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
+ /*
+ * If there was an error, throw it away and continue.
+ * The 3C5[078]9 has the error info in the status register
+ * and the 3C59[0257] implement a separate RxError register.
+ */
+ if((rxstatus & rxError) == 0){
+ /*
+ * Packet received. Read it into the next free
+ * ring buffer, if any. Must read len bytes padded
+ * to a doubleword, can be picked out 32-bits at
+ * a time. The CRC is already stripped off.
+ */
+ rb = ðer->rb[ether->ri];
+ if(rb->owner == Interface){
+ len = (rxstatus & rxBytes9);
+ rb->len = len;
+ insl(port+Fifo, rb->pkt, HOWMANY(len, 4));
+
+ rb->owner = Host;
+ ether->ri = NEXT(ether->ri, ether->nrb);
+ }
+ }
+
+ /*
+ * All done, discard the packet.
+ */
+ COMMAND(port, RxDiscard, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+ }
+}
+
+static void
+statistics(Ether* ether)
+{
+ int i, port, w;
+
+ port = ether->port;
+ w = (STATUS(port)>>13) & 0x07;
+ COMMAND(port, SelectRegisterWindow, Wop);
+ COMMAND(port, SelectRegisterWindow, Wstatistics);
+
+ for(i = 0; i < 0x0A; i++)
+ inb(port+i);
+ ins(port+BytesRcvdOk);
+ ins(port+BytesXmittedOk);
+
+ COMMAND(port, SelectRegisterWindow, w);
+}
+
+static void
+interrupt(Ureg*, void* arg)
+{
+ Ether *ether;
+ int port, status, txstatus, w, x;
+ Ctlr *ctlr;
+
+ ether = arg;
+ port = ether->port;
+ ctlr = ether->ctlr;
+
+ w = (STATUS(port)>>13) & 0x07;
+ COMMAND(port, SelectRegisterWindow, Wop);
+
+ for(;;){
+ /*
+ * Clear the interrupt latch.
+ * It's possible to receive a packet and for another
+ * to become complete before exiting the interrupt
+ * handler so this must be done first to ensure another
+ * interrupt will occur.
+ */
+ COMMAND(port, AcknowledgeInterrupt, interruptLatch);
+ status = STATUS(port);
+ if((status & interruptMask) == 0)
+ break;
+
+ if(status & hostError){
+ /*
+ * Adapter failure, try to find out why, reset if
+ * necessary. What happens if Tx is active and a reset
+ * occurs, need to retransmit? This probably isn't right.
+ */
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+FifoDiagnostic);
+ COMMAND(port, SelectRegisterWindow, Wop);
+ print("elnk3#%d: status 0x%uX, diag 0x%uX\n",
+ ether->ctlrno, status, x);
+
+ if(x & txOverrun){
+ COMMAND(port, TxReset, 0);
+ COMMAND(port, TxEnable, 0);
+ }
+
+ if(x & rxUnderrun){
+ /*
+ * This shouldn't happen...
+ * Need to restart any busmastering?
+ */
+ COMMAND(port, RxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, RxEnable, 0);
+ }
+
+ status &= ~hostError;
+ }
+
+ if(status & (transferInt|rxComplete)){
+ receive(ether);
+ status &= ~(transferInt|rxComplete);
+ }
+
+ if(status & txComplete){
+ /*
+ * Pop the TxStatus stack, accumulating errors.
+ * Adjust the TX start threshold if there was an underrun.
+ * If there was a Jabber or Underrun error, reset
+ * the transmitter.
+ * For all conditions enable the transmitter.
+ */
+ txstatus = 0;
+ do{
+ if(x = inb(port+TxStatus))
+ outb(port+TxStatus, 0);
+ txstatus |= x;
+ }while(STATUS(port) & txComplete);
+
+ if(txstatus & txUnderrun){
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ while(ins(port+MediaStatus) & txInProg)
+ ;
+ COMMAND(port, SelectRegisterWindow, Wop);
+ if(ctlr->txthreshold < ETHERMAXTU)
+ ctlr->txthreshold += ETHERMINTU;
+ }
+
+ if(txstatus & (txJabber|txUnderrun)){
+ COMMAND(port, TxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, SetTxStartThresh, ctlr->txthreshold);
+ }
+ COMMAND(port, TxEnable, 0);
+ status &= ~txComplete;
+ status |= txAvailable;
+ }
+
+ if(status & txAvailable){
+ COMMAND(port, AcknowledgeInterrupt, txAvailable);
+ transmit(ether);
+ status &= ~txAvailable;
+ }
+
+ if(status & updateStats){
+ statistics(ether);
+ status &= ~updateStats;
+ }
+
+ /*
+ * Panic if there are any interrupts not dealt with.
+ */
+ if(status & interruptMask)
+ panic("elnk3#%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
+ }
+
+ COMMAND(port, SelectRegisterWindow, w);
+}
+
+typedef struct Adapter {
+ int port;
+ int irq;
+ int tbdf;
+} Adapter;
+static Block* adapter;
+
+static void
+tcmadapter(int port, int irq, int tbdf)
+{
+ Block *bp;
+ Adapter *ap;
+
+ bp = allocb(sizeof(Adapter));
+ ap = (Adapter*)bp->rp;
+ ap->port = port;
+ ap->irq = irq;
+ ap->tbdf = tbdf;
+
+ bp->next = adapter;
+ adapter = bp;
+}
+
+/*
+ * Write two 0 bytes to identify the IDport and then reset the
+ * ID sequence. Then send the ID sequence to the card to get
+ * the card into command state.
+ */
+static void
+idseq(void)
+{
+ int i;
+ uchar al;
+ static int reset, untag;
+
+ /*
+ * One time only:
+ * reset any adapters listening
+ */
+ if(reset == 0){
+ outb(IDport, 0);
+ outb(IDport, 0);
+ outb(IDport, 0xC0);
+ delay(20);
+ reset = 1;
+ }
+
+ outb(IDport, 0);
+ outb(IDport, 0);
+ for(al = 0xFF, i = 0; i < 255; i++){
+ outb(IDport, al);
+ if(al & 0x80){
+ al <<= 1;
+ al ^= 0xCF;
+ }
+ else
+ al <<= 1;
+ }
+
+ /*
+ * One time only:
+ * write ID sequence to get the attention of all adapters;
+ * untag all adapters.
+ * If we do a global reset here on all adapters we'll confuse any
+ * ISA cards configured for EISA mode.
+ */
+ if(untag == 0){
+ outb(IDport, 0xD0);
+ untag = 1;
+ }
+}
+
+static ulong
+activate(void)
+{
+ int i;
+ ushort x, acr;
+
+ /*
+ * Do the little configuration dance:
+ *
+ * 2. write the ID sequence to get to command state.
+ */
+ idseq();
+
+ /*
+ * 3. Read the Manufacturer ID from the EEPROM.
+ * This is done by writing the IDPort with 0x87 (0x80
+ * is the 'read EEPROM' command, 0x07 is the offset of
+ * the Manufacturer ID field in the EEPROM).
+ * The data comes back 1 bit at a time.
+ * We seem to need a delay here between reading the bits.
+ *
+ * If the ID doesn't match, there are no more adapters.
+ */
+ outb(IDport, 0x87);
+ delay(20);
+ for(x = 0, i = 0; i < 16; i++){
+ delay(20);
+ x <<= 1;
+ x |= inb(IDport) & 0x01;
+ }
+ if(x != 0x6D50)
+ return 0;
+
+ /*
+ * 3. Read the Address Configuration from the EEPROM.
+ * The Address Configuration field is at offset 0x08 in the EEPROM).
+ */
+ outb(IDport, 0x88);
+ for(acr = 0, i = 0; i < 16; i++){
+ delay(20);
+ acr <<= 1;
+ acr |= inb(IDport) & 0x01;
+ }
+
+ return (acr & 0x1F)*0x10 + 0x200;
+}
+
+#ifdef notjustpcmcia
+static void
+tcm509isa(void)
+{
+ int irq, port;
+
+ /*
+ * Attempt to activate all adapters. If adapter is set for
+ * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
+ * it fully.
+ */
+ while(port = activate()){
+ /*
+ * 6. Tag the adapter so it won't respond in future.
+ */
+ outb(IDport, 0xD1);
+ if(port == 0x3F0)
+ continue;
+
+ /*
+ * 6. Activate the adapter by writing the Activate command
+ * (0xFF).
+ */
+ outb(IDport, 0xFF);
+ delay(20);
+
+ /*
+ * 8. Can now talk to the adapter's I/O base addresses.
+ * Use the I/O base address from the acr just read.
+ *
+ * Enable the adapter and clear out any lingering status
+ * and interrupts.
+ */
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ outs(port+ConfigControl, Ena);
+
+ COMMAND(port, TxReset, 0);
+ COMMAND(port, RxReset, 0);
+ COMMAND(port, AcknowledgeInterrupt, 0xFF);
+
+ irq = (ins(port+ResourceConfig)>>12) & 0x0F;
+ tcmadapter(port, irq, BUSUNKNOWN);
+ }
+}
+
+static void
+tcm5XXeisa(void)
+{
+ ushort x;
+ int irq, port, slot;
+
+ /*
+ * Check if this is an EISA machine.
+ * If not, nothing to do.
+ */
+ if(strncmp((char*)(KZERO|0xFFFD9), "EISA", 4))
+ return;
+
+ /*
+ * Continue through the EISA slots looking for a match on both
+ * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
+ * If an adapter is found, select window 0, enable it and clear
+ * out any lingering status and interrupts.
+ */
+ for(slot = 1; slot < MaxEISA; slot++){
+ port = slot*0x1000;
+ if(ins(port+0xC80+ManufacturerID) != 0x6D50)
+ continue;
+ x = ins(port+0xC80+ProductID);
+ if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900)
+ continue;
+
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ outs(port+ConfigControl, Ena);
+
+ COMMAND(port, TxReset, 0);
+ COMMAND(port, RxReset, 0);
+ COMMAND(port, AcknowledgeInterrupt, 0xFF);
+
+ irq = (ins(port+ResourceConfig)>>12) & 0x0F;
+ tcmadapter(port, irq, BUSUNKNOWN);
+ }
+}
+
+static void
+tcm59Xpci(void)
+{
+ Pcidev *p;
+ int irq, port;
+
+ p = nil;
+ while(p = pcimatch(p, 0x10B7, 0)){
+ port = p->mem[0].bar & ~0x01;
+ irq = p->intl;
+ COMMAND(port, GlobalReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+
+ tcmadapter(port, irq, p->tbdf);
+ }
+}
+#endif /* notjustpcmcia */
+
+static char* tcmpcmcia[] = {
+ "3C589", /* 3COM 589[ABCD] */
+ "3C562", /* 3COM 562 */
+ "589E", /* 3COM Megahertz 589E */
+ nil,
+};
+
+static int
+tcm5XXpcmcia(Ether* ether)
+{
+ int i;
+
+ for(i = 0; tcmpcmcia[i] != nil; i++){
+ if(!cistrcmp(ether->type, tcmpcmcia[i]))
+ return ether->port;
+ }
+
+ return 0;
+}
+
+static int
+autoselect(int port, int rxstatus9)
+{
+ int media, x;
+
+ /*
+ * Pathetic attempt at automatic media selection.
+ * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
+ * cards operational.
+ */
+ media = auiAvailable|coaxAvailable|base10TAvailable;
+ if(rxstatus9 == 0){
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ media = ins(port+ResetOptions);
+ }
+
+ if(media & miiConnector)
+ return xcvrMii;
+
+ if(media & baseTXAvailable){
+ /*
+ * Must have InternalConfig register.
+ */
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ x = inl(port+InternalConfig) & ~xcvrMask;
+ x |= xcvr100BaseTX;
+ outl(port+InternalConfig, x);
+ COMMAND(port, TxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, RxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
+ outs(port+MediaStatus, linkBeatEnable|x);
+ delay(10);
+
+{ int i, v;
+ for(i = 0; i < 10000; i++){
+ v = ins(port+MediaStatus);
+ if(v & linkBeatDetect){
+ print("count %d v %uX\n", i, v);
+ return xcvr100BaseTX;
+ }
+ delay(1);
+ }
+print("count %d v %uX\n", i, ins(port+MediaStatus));
+}
+ if(ins(port+MediaStatus) & linkBeatDetect)
+ return xcvr100BaseTX;
+ outs(port+MediaStatus, x);
+ }
+
+ if(media & base10TAvailable){
+ if(rxstatus9 == 0){
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ x = inl(port+InternalConfig) & ~xcvrMask;
+ x |= xcvr10BaseT;
+ outl(port+InternalConfig, x);
+ }
+ else{
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ x = ins(port+AddressConfig) & ~xcvrMask9;
+ x |= (xcvr10BaseT>>20)<<14;
+ outs(port+AddressConfig, x);
+ }
+ COMMAND(port, TxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+ COMMAND(port, RxReset, 0);
+ while(STATUS(port) & commandInProgress)
+ ;
+
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~dcConverterEnabled;
+ outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
+ delay(10);
+
+ if(ins(port+MediaStatus) & linkBeatDetect)
+ return xcvr10BaseT;
+ outs(port+MediaStatus, x);
+ }
+
+ /*
+ * Botch.
+ */
+ return autoSelect;
+}
+
+static int
+eepromdata(int port, int offset)
+{
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ while(EEPROMBUSY(port))
+ ;
+ EEPROMCMD(port, EepromReadRegister, offset);
+ while(EEPROMBUSY(port))
+ ;
+ return EEPROMDATA(port);
+}
+
+int
+elnk3reset(Ether* ether)
+{
+ int did, i, port, rxstatus9, x, xcvr;
+ Block *bp, **bpp;
+ Adapter *ap;
+ uchar ea[Eaddrlen];
+ Ctlr *ctlr;
+#ifdef notjustpcmcia
+ static int scandone;
+
+ /*
+ * Scan for adapter on PCI, EISA and finally
+ * using the little ISA configuration dance.
+ */
+ if(scandone == 0){
+ tcm59Xpci();
+ tcm5XXeisa();
+ tcm509isa();
+ scandone = 1;
+ }
+#endif /* notjustpcmcia */
+
+ /*
+ * Any adapter matches if no ether->port is supplied,
+ * otherwise the ports must match.
+ */
+ port = 0;
+ bpp = &adapter;
+ for(bp = *bpp; bp; bp = bp->next){
+ ap = (Adapter*)bp->rp;
+ if(ether->port == 0 || ether->port == ap->port){
+ port = ap->port;
+ ether->irq = ap->irq;
+ ether->tbdf = ap->tbdf;
+ *bpp = bp->next;
+ freeb(bp);
+ break;
+ }
+ bpp = &bp->next;
+ }
+ if(port == 0 && (port = tcm5XXpcmcia(ether)) == 0)
+ return -1;
+
+ /*
+ * Read the DeviceID from the EEPROM, it's at offset 0x03,
+ * and do something depending on capabilities.
+ */
+ switch(did = eepromdata(port, 0x03)){
+
+ case 0x9000:
+ case 0x9001:
+ case 0x9050:
+ case 0x9051:
+ if(BUSTYPE(ether->tbdf) != BusPCI)
+ goto buggery;
+ goto vortex;
+
+ case 0x5900:
+ case 0x5920:
+ case 0x5950:
+ case 0x5951:
+ case 0x5952:
+ case 0x5970:
+ case 0x5971:
+ case 0x5972:
+ vortex:
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
+ rxstatus9 = 0;
+ break;
+
+ buggery:
+ default:
+ COMMAND(port, SelectRegisterWindow, Wsetup);
+ x = ins(port+AddressConfig);
+ xcvr = ((x & xcvrMask9)>>14)<<20;
+ if(x & autoSelect9)
+ xcvr |= autoSelect;
+ rxstatus9 = 1;
+ break;
+ }
+ USED(did);
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to loading the
+ * station address in Wstation. The EEPROM returns 16-bits at a time.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ether->ea, Eaddrlen) == 0){
+ for(i = 0; i < Eaddrlen/2; i++){
+ x = eepromdata(port, i);
+ ether->ea[2*i] = x>>8;
+ ether->ea[2*i+1] = x;
+ }
+ }
+
+ COMMAND(port, SelectRegisterWindow, Wstation);
+ for(i = 0; i < Eaddrlen; i++)
+ outb(port+i, ether->ea[i]);
+
+ /*
+ * Enable the transceiver if necessary.
+ */
+ if(xcvr & autoSelect)
+ xcvr = autoselect(port, rxstatus9);
+ switch(xcvr){
+
+ case xcvrMii:
+ break;
+
+ case xcvr100BaseTX:
+ case xcvr100BaseFX:
+ COMMAND(port, SelectRegisterWindow, Wfifo);
+ x = inl(port+InternalConfig) & ~ramPartitionMask;
+ outl(port+InternalConfig, x|ramPartition1to1);
+
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
+ x |= linkBeatEnable;
+ outs(port+MediaStatus, x);
+ break;
+
+ case xcvr10BaseT:
+ /*
+ * Enable Link Beat and Jabber to start the
+ * transceiver.
+ */
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~dcConverterEnabled;
+ x |= linkBeatEnable|jabberGuardEnable;
+ outs(port+MediaStatus, x);
+ break;
+
+ case xcvr10Base2:
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
+ outs(port+MediaStatus, x);
+
+ /*
+ * Start the DC-DC converter.
+ * Wait > 800 microseconds.
+ */
+ COMMAND(port, EnableDcConverter, 0);
+ delay(1);
+ break;
+ }
+
+ /*
+ * Wop is the normal operating register set.
+ * The 3C59[0257] adapters allow access to more than one register window
+ * at a time, but there are situations where switching still needs to be
+ * done, so just do it.
+ * Clear out any lingering Tx status.
+ */
+ COMMAND(port, SelectRegisterWindow, Wop);
+ while(inb(port+TxStatus))
+ outb(port+TxStatus, 0);
+
+ /*
+ * Allocate a controller structure and start
+ * to initialise it.
+ */
+ ether->ctlr = malloc(sizeof(Ctlr));
+ ctlr = ether->ctlr;
+ memset(ctlr, 0, sizeof(Ctlr));
+
+ /*
+ * Set a base TxStartThresh which will be incremented
+ * if any txUnderrun errors occur and ensure no RxEarly
+ * interrupts happen.
+ */
+ ctlr->txthreshold = ETHERMINTU;
+ COMMAND(port, SetTxStartThresh, ETHERMINTU);
+ COMMAND(port, SetRxEarlyThresh, ETHERMAXTU);
+
+ /*
+ * Set up the software configuration.
+ */
+ ether->port = port;
+ ether->attach = attach;
+ ether->transmit = transmit;
+ ether->interrupt = interrupt;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/etherga620.c
@@ -1,0 +1,1147 @@
+/*
+ * bootstrap driver for
+ * Netgear GA620 Gigabit Ethernet Card.
+ * Specific for the Alteon Tigon 2 and Intel Pentium or later.
+ * To Do:
+ * cache alignment for PCI Write-and-Invalidate
+ * mini ring (what size)?
+ * tune coalescing values
+ * statistics formatting
+ * don't update Spi if nothing to send
+ * receive ring alignment
+ * watchdog for link management?
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#define malign(n) xspanalloc((n), 32, 0)
+
+#include "etherif.h"
+#include "etherga620fw.h"
+
+enum {
+ Mhc = 0x0040, /* Miscellaneous Host Control */
+ Mlc = 0x0044, /* Miscellaneous Local Control */
+ Mc = 0x0050, /* Miscellaneous Configuration */
+ Ps = 0x005C, /* PCI State */
+ Wba = 0x0068, /* Window Base Address */
+ Wd = 0x006C, /* Window Data */
+
+ DMAas = 0x011C, /* DMA Assist State */
+
+ CPUAstate = 0x0140, /* CPU A State */
+ CPUApc = 0x0144, /* CPU A Programme Counter */
+
+ CPUBstate = 0x0240, /* CPU B State */
+
+ Hi = 0x0504, /* Host In Interrupt Handler */
+ Cpi = 0x050C, /* Command Producer Index */
+ Spi = 0x0514, /* Send Producer Index */
+ Rspi = 0x051C, /* Receive Standard Producer Index */
+ Rjpi = 0x0524, /* Receive Jumbo Producer Index */
+ Rmpi = 0x052C, /* Receive Mini Producer Index */
+
+ Mac = 0x0600, /* MAC Address */
+ Gip = 0x0608, /* General Information Pointer */
+ Om = 0x0618, /* Operating Mode */
+ DMArc = 0x061C, /* DMA Read Configuration */
+ DMAwc = 0x0620, /* DMA Write Configuration */
+ Tbr = 0x0624, /* Transmit Buffer Ratio */
+ Eci = 0x0628, /* Event Consumer Index */
+ Cci = 0x062C, /* Command Consumer Index */
+
+ Rct = 0x0630, /* Receive Coalesced Ticks */
+ Sct = 0x0634, /* Send Coalesced Ticks */
+ St = 0x0638, /* Stat Ticks */
+ SmcBD = 0x063C, /* Send Max. Coalesced BDs */
+ RmcBD = 0x0640, /* Receive Max. Coalesced BDs */
+ Nt = 0x0644, /* NIC Tracing */
+ Gln = 0x0648, /* Gigabit Link Negotiation */
+ Fln = 0x064C, /* 10/100 Link Negotiation */
+ Ifx = 0x065C, /* Interface Index */
+ IfMTU = 0x0660, /* Interface MTU */
+ Mi = 0x0664, /* Mask Interrupts */
+ Gls = 0x0668, /* Gigabit Link State */
+ Fls = 0x066C, /* 10/100 Link State */
+
+ Cr = 0x0700, /* Command Ring */
+
+ Lmw = 0x0800, /* Local Memory Window */
+};
+
+enum { /* Mhc */
+ Is = 0x00000001, /* Interrupt State */
+ Ci = 0x00000002, /* Clear Interrupt */
+ Hr = 0x00000008, /* Hard Reset */
+ Eebs = 0x00000010, /* Enable Endian Byte Swap */
+ Eews = 0x00000020, /* Enable Endian Word (64-bit) swap */
+ Mpio = 0x00000040, /* Mask PCI Interrupt Output */
+};
+
+enum { /* Mlc */
+ SRAM512 = 0x00000200, /* SRAM Bank Size of 512KB */
+ SRAMmask = 0x00000300,
+ EEclk = 0x00100000, /* Serial EEPROM Clock Output */
+ EEdoe = 0x00200000, /* Serial EEPROM Data Out Enable */
+ EEdo = 0x00400000, /* Serial EEPROM Data Out Value */
+ EEdi = 0x00800000, /* Serial EEPROM Data Input */
+};
+
+enum { /* Mc */
+ SyncSRAM = 0x00100000, /* Set Synchronous SRAM Timing */
+};
+
+enum { /* Ps */
+ PCIwm32 = 0x000000C0, /* Write Max DMA 32 */
+ PCImrm = 0x00020000, /* Use Memory Read Multiple Command */
+ PCI66 = 0x00080000,
+ PCI32 = 0x00100000,
+ PCIrcmd = 0x06000000, /* PCI Read Command */
+ PCIwcmd = 0x70000000, /* PCI Write Command */
+};
+
+enum { /* CPUAstate */
+ CPUrf = 0x00000010, /* ROM Fail */
+ CPUhalt = 0x00010000, /* Halt the internal CPU */
+ CPUhie = 0x00040000, /* HALT instruction executed */
+};
+
+enum { /* Om */
+ BswapBD = 0x00000002, /* Byte Swap Buffer Descriptors */
+ WswapBD = 0x00000004, /* Word Swap Buffer Descriptors */
+ Warn = 0x00000008,
+ BswapDMA = 0x00000010, /* Byte Swap DMA Data */
+ Only1DMA = 0x00000040, /* Only One DMA Active at a time */
+ NoJFrag = 0x00000200, /* Don't Fragment Jumbo Frames */
+ Fatal = 0x40000000,
+};
+
+enum { /* Lmw */
+ Lmwsz = 2*1024, /* Local Memory Window Size */
+
+ /*
+ * legal values are 0x3800 iff Nsr is 128, 0x3000 iff Nsr is 256,
+ * or 0x2000 iff Nsr is 512.
+ */
+ Sr = 0x3800, /* Send Ring (accessed via Lmw) */
+};
+
+enum { /* Link */
+ Lpref = 0x00008000, /* Preferred Link */
+ L10MB = 0x00010000,
+ L100MB = 0x00020000,
+ L1000MB = 0x00040000,
+ Lfd = 0x00080000, /* Full Duplex */
+ Lhd = 0x00100000, /* Half Duplex */
+ Lefc = 0x00200000, /* Emit Flow Control Packets */
+ Lofc = 0x00800000, /* Obey Flow Control Packets */
+ Lean = 0x20000000, /* Enable Autonegotiation/Sensing */
+ Le = 0x40000000, /* Link Enable */
+};
+
+typedef struct Host64 {
+ uint hi;
+ uint lo;
+} Host64;
+
+typedef struct Ere { /* Event Ring Element */
+ int event; /* event<<24 | code<<12 | index */
+ int unused;
+} Ere;
+
+typedef int Cmd; /* cmd<<24 | flags<<12 | index */
+
+typedef struct Rbd { /* Receive Buffer Descriptor */
+ Host64 addr;
+ int indexlen; /* ring-index<<16 | buffer-length */
+ int flags; /* only lower 16-bits */
+ int checksum; /* ip<<16 |tcp/udp */
+ int error; /* only upper 16-bits */
+ int reserved;
+ void* opaque; /* passed to receive return ring */
+} Rbd;
+
+typedef struct Sbd { /* Send Buffer Descriptor */
+ Host64 addr;
+ int lenflags; /* len<<16 |flags */
+ int reserved;
+} Sbd;
+
+enum { /* Buffer Descriptor Flags */
+ Fend = 0x00000004, /* Frame Ends in this Buffer */
+ Frjr = 0x00000010, /* Receive Jumbo Ring Buffer */
+ Funicast = 0x00000020, /* Unicast packet (2-bit field) */
+ Fmulticast = 0x00000040, /* Multicast packet */
+ Fbroadcast = 0x00000060, /* Broadcast packet */
+ Ferror = 0x00000400, /* Frame Has Error */
+ Frmr = 0x00001000, /* Receive Mini Ring Buffer */
+};
+
+enum { /* Buffer Error Flags */
+ Ecrc = 0x00010000, /* bad CRC */
+ Ecollision = 0x00020000, /* collision */
+ Elink = 0x00040000, /* link lost */
+ Ephy = 0x00080000, /* unspecified PHY frame decode error */
+ Eodd = 0x00100000, /* odd number of nibbles */
+ Emac = 0x00200000, /* unspecified MAC abort */
+ Elen64 = 0x00400000, /* short packet */
+ Eresources = 0x00800000, /* MAC out of internal resources */
+ Egiant = 0x01000000, /* packet too big */
+};
+
+typedef struct Rcb { /* Ring Control Block */
+ Host64 addr; /* points to the Rbd ring */
+ int control; /* max_len<<16 |flags */
+ int unused;
+} Rcb;
+
+enum {
+ TcpUdpCksum = 0x0001, /* Perform TCP or UDP checksum */
+ IpCksum = 0x0002, /* Perform IP checksum */
+ NoPseudoHdrCksum= 0x0008, /* Don't include the pseudo header */
+ VlanAssist = 0x0010, /* Enable VLAN tagging */
+ CoalUpdateOnly = 0x0020, /* Coalesce transmit interrupts */
+ HostRing = 0x0040, /* Sr in host memory */
+ SnapCksum = 0x0080, /* Parse + offload 802.3 SNAP frames */
+ UseExtRxBd = 0x0100, /* Extended Rbd for Jumbo frames */
+ RingDisabled = 0x0200, /* Jumbo or Mini RCB only */
+};
+
+typedef struct Gib { /* General Information Block */
+ int statistics[256]; /* Statistics */
+ Rcb ercb; /* Event Ring */
+ Rcb crcb; /* Command Ring */
+ Rcb srcb; /* Send Ring */
+ Rcb rsrcb; /* Receive Standard Ring */
+ Rcb rjrcb; /* Receive Jumbo Ring */
+ Rcb rmrcb; /* Receive Mini Ring */
+ Rcb rrrcb; /* Receive Return Ring */
+ Host64 epp; /* Event Producer */
+ Host64 rrrpp; /* Receive Return Ring Producer */
+ Host64 scp; /* Send Consumer */
+ Host64 rsp; /* Refresh Stats */
+} Gib;
+
+/*
+ * these sizes are all fixed in the card,
+ * except for Nsr, which has only 3 valid sizes.
+ */
+enum { /* Host/NIC Interface ring sizes */
+ Ner = 256, /* event ring */
+ Ncr = 64, /* command ring */
+ Nsr = 128, /* send ring: 128, 256 or 512 */
+ Nrsr = 512, /* receive standard ring */
+ Nrjr = 256, /* receive jumbo ring */
+ Nrmr = 1024, /* receive mini ring, optional */
+ Nrrr = 2048, /* receive return ring */
+};
+
+enum {
+ NrsrHI = 72, /* Fill-level of Rsr (m.b. < Nrsr) */
+ NrsrLO = 54, /* Level at which to top-up ring */
+ NrjrHI = 0, /* Fill-level of Rjr (m.b. < Nrjr) */
+ NrjrLO = 0, /* Level at which to top-up ring */
+ NrmrHI = 0, /* Fill-level of Rmr (m.b. < Nrmr) */
+ NrmrLO = 0, /* Level at which to top-up ring */
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id;
+
+ uchar ea[Eaddrlen];
+
+ int* nic;
+ Gib* gib;
+
+ Ere* er;
+
+ Lock srlock;
+ Sbd* sr;
+ Block** srb;
+ int nsr; /* currently in send ring */
+
+ Rbd* rsr;
+ int nrsr; /* currently in Receive Standard Ring */
+ Rbd* rjr;
+ int nrjr; /* currently in Receive Jumbo Ring */
+ Rbd* rmr;
+ int nrmr; /* currently in Receive Mini Ring */
+ Rbd* rrr;
+ int rrrci; /* Receive Return Ring Consumer Index */
+
+ int epi[2]; /* Event Producer Index */
+ int rrrpi[2]; /* Receive Return Ring Producer Index */
+ int sci[3]; /* Send Consumer Index ([2] is host) */
+
+ int interrupts; /* statistics */
+ int mi;
+ uvlong ticks;
+
+ int coalupdateonly; /* tuning */
+ int hardwarecksum;
+ int rct; /* Receive Coalesce Ticks */
+ int sct; /* Send Coalesce Ticks */
+ int st; /* Stat Ticks */
+ int smcbd; /* Send Max. Coalesced BDs */
+ int rmcbd; /* Receive Max. Coalesced BDs */
+};
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr32r(c, r) (*((c)->nic+((r)/4)))
+#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
+
+static void
+sethost64(Host64* host64, void* addr)
+{
+ uvlong uvl;
+
+ uvl = PCIWADDR(addr);
+ host64->hi = uvl>>32;
+ host64->lo = uvl & 0xFFFFFFFFL;
+}
+
+static void
+ga620command(Ctlr* ctlr, int cmd, int flags, int index)
+{
+ int cpi;
+
+ cpi = csr32r(ctlr, Cpi);
+ csr32w(ctlr, Cr+(cpi*4), cmd<<24 | flags<<12 | index);
+ cpi = NEXT(cpi, Ncr);
+ csr32w(ctlr, Cpi, cpi);
+}
+
+static void
+ga620attach(Ether* )
+{
+}
+
+static void
+waitforlink(Ether *edev)
+{
+ int i;
+
+ if (edev->mbps == 0) {
+ print("#l%d: ga620: waiting for link", edev->ctlrno);
+ /* usually takes about 10 seconds */
+ for (i = 0; i < 20 && edev->mbps == 0; i++) {
+ print(".");
+ delay(1000);
+ }
+ print("\n");
+ if (i == 20 && edev->mbps == 0)
+ edev->mbps = 1; /* buggered */
+ }
+}
+
+static void
+toringbuf(Ether *ether, Block *bp)
+{
+ RingBuf *rb = ðer->rb[ether->ri];
+
+ if (rb->owner == Interface) {
+ rb->len = BLEN(bp);
+ memmove(rb->pkt, bp->rp, rb->len);
+ rb->owner = Host;
+ ether->ri = NEXT(ether->ri, ether->nrb);
+ }
+ /* else no one is expecting packets from the network */
+}
+
+static Block *
+fromringbuf(Ether *ether)
+{
+ RingBuf *tb = ðer->tb[ether->ti];
+ Block *bp = allocb(tb->len);
+
+ if (bp == nil)
+ panic("fromringbuf: nil allocb return");
+ if (bp->wp == nil)
+ panic("fromringbuf: nil bp->wb");
+ memmove(bp->wp, tb->pkt, tb->len);
+ memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+ bp->wp += tb->len;
+ return bp;
+}
+
+static int
+_ga620transmit(Ether* edev)
+{
+ Sbd *sbd;
+ Block *bp;
+ Ctlr *ctlr;
+ RingBuf *tb;
+ int sci, spi, work;
+
+ /*
+ * For now there are no smarts here, just empty the
+ * ring and try to fill it back up. Tuning comes later.
+ */
+ ctlr = edev->ctlr;
+ waitforlink(edev);
+ ilock(&ctlr->srlock);
+
+ /*
+ * Free any completed packets.
+ * Ctlr->sci[0] is where the NIC has got to consuming the ring.
+ * Ctlr->sci[2] is where the host has got to tidying up after the
+ * NIC has done with the packets.
+ */
+ work = 0;
+ for(sci = ctlr->sci[2]; sci != ctlr->sci[0]; sci = NEXT(sci, Nsr)){
+ if(ctlr->srb[sci] == nil)
+ continue;
+ freeb(ctlr->srb[sci]);
+ ctlr->srb[sci] = nil;
+ work++;
+ }
+ ctlr->sci[2] = sci;
+
+ sci = PREV(sci, Nsr);
+
+ tb = &edev->tb[edev->ti];
+ for(spi = csr32r(ctlr, Spi); spi != sci && tb->owner == Interface;
+ spi = NEXT(spi, Nsr)){
+ bp = fromringbuf(edev);
+
+ sbd = &ctlr->sr[spi];
+ sethost64(&sbd->addr, bp->rp);
+ sbd->lenflags = BLEN(bp)<<16 |Fend;
+
+ ctlr->srb[spi] = bp;
+ work++;
+
+ tb->owner = Host;
+ edev->ti = NEXT(edev->ti, edev->ntb);
+ tb = &edev->tb[edev->ti];
+ }
+ csr32w(ctlr, Spi, spi);
+
+ iunlock(&ctlr->srlock);
+
+ return work;
+}
+
+static void
+ga620transmit(Ether* edev)
+{
+ _ga620transmit(edev);
+}
+
+static void
+ga620replenish(Ctlr* ctlr)
+{
+ Rbd *rbd;
+ int rspi;
+ Block *bp;
+
+ rspi = csr32r(ctlr, Rspi);
+ while(ctlr->nrsr < NrsrHI){
+ if((bp = allocb(ETHERMAXTU+4)) == nil)
+ break;
+ rbd = &ctlr->rsr[rspi];
+ sethost64(&rbd->addr, bp->rp);
+ rbd->indexlen = rspi<<16 | (ETHERMAXTU+4);
+ rbd->flags = 0;
+ rbd->opaque = bp;
+
+ rspi = NEXT(rspi, Nrsr);
+ ctlr->nrsr++;
+ }
+ csr32w(ctlr, Rspi, rspi);
+}
+
+static void
+ga620event(Ether *edev, int eci, int epi)
+{
+ unsigned event, code;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ while(eci != epi){
+ event = ctlr->er[eci].event;
+ code = (event >> 12) & ((1<<12)-1);
+ switch(event>>24){
+ case 0x01: /* firmware operational */
+ /* host stack (us) is up. 3rd arg of 2 means down. */
+ ga620command(ctlr, 0x01, 0x01, 0x00);
+ /*
+ * link negotiation: any speed is okay.
+ * 3rd arg of 1 selects gigabit only; 2 10/100 only.
+ */
+ ga620command(ctlr, 0x0B, 0x00, 0x00);
+ print("#l%d: ga620: port %8.8uX: firmware is up\n",
+ edev->ctlrno, ctlr->port);
+ break;
+ case 0x04: /* statistics updated */
+ break;
+ case 0x06: /* link state changed */
+ switch (code) {
+ case 1:
+ edev->mbps = 1000;
+ break;
+ case 2:
+ print("#l%d: link down\n", edev->ctlrno);
+ break;
+ case 3:
+ edev->mbps = 100; /* it's 10 or 100 */
+ break;
+ }
+ if (code != 2)
+ print("#l%d: %dMbps link up\n",
+ edev->ctlrno, edev->mbps);
+ break;
+ case 0x07: /* event error */
+ default:
+ print("#l%d: ga620: er[%d] = %8.8uX\n", edev->ctlrno,
+ eci, event);
+ break;
+ }
+ eci = NEXT(eci, Ner);
+ }
+ csr32w(ctlr, Eci, eci);
+}
+
+static void
+ga620receive(Ether* edev)
+{
+ int len;
+ Rbd *rbd;
+ Block *bp;
+ Ctlr* ctlr;
+
+ ctlr = edev->ctlr;
+ while(ctlr->rrrci != ctlr->rrrpi[0]){
+ rbd = &ctlr->rrr[ctlr->rrrci];
+ /*
+ * Errors are collected in the statistics block so
+ * no need to tally them here, let ifstat do the work.
+ */
+ len = rbd->indexlen & 0xFFFF;
+ if(!(rbd->flags & Ferror) && len != 0){
+ bp = rbd->opaque;
+ bp->wp = bp->rp+len;
+
+ toringbuf(edev, bp);
+ } else
+ freeb(rbd->opaque);
+ rbd->opaque = nil;
+
+ if(rbd->flags & Frjr)
+ ctlr->nrjr--;
+ else if(rbd->flags & Frmr)
+ ctlr->nrmr--;
+ else
+ ctlr->nrsr--;
+
+ ctlr->rrrci = NEXT(ctlr->rrrci, Nrrr);
+ }
+}
+
+static void
+ga620interrupt(Ureg*, void* arg)
+{
+ int csr, ie, work;
+ Ctlr *ctlr;
+ Ether *edev;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ if(!(csr32r(ctlr, Mhc) & Is))
+ return;
+
+ ctlr->interrupts++;
+ csr32w(ctlr, Hi, 1);
+
+ ie = 0;
+ work = 0;
+ while(ie < 2){
+ if(ctlr->rrrci != ctlr->rrrpi[0]){
+ ga620receive(edev);
+ work = 1;
+ }
+
+ if(_ga620transmit(edev) != 0)
+ work = 1;
+
+ csr = csr32r(ctlr, Eci);
+ if(csr != ctlr->epi[0]){
+ ga620event(edev, csr, ctlr->epi[0]);
+ work = 1;
+ }
+
+ if(ctlr->nrsr <= NrsrLO)
+ ga620replenish(ctlr);
+ if(work == 0){
+ if(ie == 0)
+ csr32w(ctlr, Hi, 0);
+ ie++;
+ }
+ work = 0;
+ }
+}
+
+static void
+ga620lmw(Ctlr* ctlr, int addr, int* data, int len)
+{
+ int i, l, lmw, v;
+
+ /*
+ * Write to or clear ('data' == nil) 'len' bytes of the NIC
+ * local memory at address 'addr'.
+ * The destination address and count should be 32-bit aligned.
+ */
+ v = 0;
+ while(len > 0){
+ /*
+ * 1) Set the window. The (Lmwsz-1) bits are ignored
+ * in Wba when accessing through the local memory window;
+ * 2) Find the minimum of how many bytes still to
+ * transfer and how many left in this window;
+ * 3) Create the offset into the local memory window in the
+ * shared memory space then copy (or zero) the data;
+ * 4) Bump the counts.
+ */
+ csr32w(ctlr, Wba, addr);
+
+ l = ROUNDUP(addr+1, Lmwsz) - addr;
+ if(l > len)
+ l = len;
+
+ lmw = Lmw + (addr & (Lmwsz-1));
+ for(i = 0; i < l; i += 4){
+ if(data != nil)
+ v = *data++;
+ csr32w(ctlr, lmw+i, v);
+ }
+
+ len -= l;
+ addr += l;
+ }
+}
+
+static int
+ga620init(Ether* edev)
+{
+ Ctlr *ctlr;
+ Host64 host64;
+ int csr, ea, i, flags;
+
+ ctlr = edev->ctlr;
+
+ /*
+ * Load the MAC address.
+ */
+ ea = edev->ea[0]<<8 | edev->ea[1];
+ csr32w(ctlr, Mac, ea);
+ ea = edev->ea[2]<<24 | edev->ea[3]<<16 | edev->ea[4]<<8 | edev->ea[5];
+ csr32w(ctlr, Mac+4, ea);
+
+ /*
+ * General Information Block.
+ */
+ ctlr->gib = malloc(sizeof(Gib));
+ sethost64(&host64, ctlr->gib);
+ csr32w(ctlr, Gip, host64.hi);
+ csr32w(ctlr, Gip+4, host64.lo);
+
+ /*
+ * Event Ring.
+ * This is located in host memory. Allocate the ring,
+ * tell the NIC where it is and initialise the indices.
+ */
+ ctlr->er = malign(sizeof(Ere)*Ner);
+ sethost64(&ctlr->gib->ercb.addr, ctlr->er);
+ sethost64(&ctlr->gib->epp, ctlr->epi);
+ csr32w(ctlr, Eci, 0);
+
+ /*
+ * Command Ring.
+ * This is located in the General Communications Region
+ * and so the value placed in the Rcb is unused, the NIC
+ * knows where it is. Stick in the value according to
+ * the datasheet anyway.
+ * Initialise the ring and indices.
+ */
+ ctlr->gib->crcb.addr.lo = Cr - 0x400;
+ for(i = 0; i < Ncr*4; i += 4)
+ csr32w(ctlr, Cr+i, 0);
+ csr32w(ctlr, Cpi, 0);
+ csr32w(ctlr, Cci, 0);
+
+ /*
+ * Send Ring.
+ * This ring is either in NIC memory at a fixed location depending
+ * on how big the ring is or it is in host memory. If in NIC
+ * memory it is accessed via the Local Memory Window; with a send
+ * ring size of 128 the window covers the whole ring and then need
+ * only be set once:
+ * ctlr->sr = (uchar*)ctlr->nic+Lmw;
+ * ga620lmw(ctlr, Sr, nil, sizeof(Sbd)*Nsr);
+ * ctlr->gib->srcb.addr.lo = Sr;
+ * There is nowhere in the Sbd to hold the Block* associated
+ * with this entry so an external array must be kept.
+ */
+ ctlr->sr = malign(sizeof(Sbd)*Nsr);
+ sethost64(&ctlr->gib->srcb.addr, ctlr->sr);
+ if(ctlr->hardwarecksum)
+ flags = TcpUdpCksum|NoPseudoHdrCksum|HostRing;
+ else
+ flags = HostRing;
+ if(ctlr->coalupdateonly)
+ flags |= CoalUpdateOnly;
+ ctlr->gib->srcb.control = Nsr<<16 | flags;
+ sethost64(&ctlr->gib->scp, ctlr->sci);
+ csr32w(ctlr, Spi, 0);
+ ctlr->srb = malloc(sizeof(Block*)*Nsr);
+
+ /*
+ * Receive Standard Ring.
+ */
+ ctlr->rsr = malign(sizeof(Rbd)*Nrsr);
+ sethost64(&ctlr->gib->rsrcb.addr, ctlr->rsr);
+ if(ctlr->hardwarecksum)
+ flags = TcpUdpCksum|NoPseudoHdrCksum;
+ else
+ flags = 0;
+ ctlr->gib->rsrcb.control = (ETHERMAXTU+4)<<16 | flags;
+ csr32w(ctlr, Rspi, 0);
+
+ /*
+ * Jumbo and Mini Rings. Unused for now.
+ */
+ ctlr->gib->rjrcb.control = RingDisabled;
+ ctlr->gib->rmrcb.control = RingDisabled;
+
+ /*
+ * Receive Return Ring.
+ * This is located in host memory. Allocate the ring,
+ * tell the NIC where it is and initialise the indices.
+ */
+ ctlr->rrr = malign(sizeof(Rbd)*Nrrr);
+ sethost64(&ctlr->gib->rrrcb.addr, ctlr->rrr);
+ ctlr->gib->rrrcb.control = Nrrr<<16 | 0;
+ sethost64(&ctlr->gib->rrrpp, ctlr->rrrpi);
+ ctlr->rrrci = 0;
+
+ /*
+ * Refresh Stats Pointer.
+ * For now just point it at the existing statistics block.
+ */
+ sethost64(&ctlr->gib->rsp, ctlr->gib->statistics);
+
+ /*
+ * DMA configuration.
+ * Use the recommended values.
+ */
+ csr32w(ctlr, DMArc, 0x80);
+ csr32w(ctlr, DMAwc, 0x80);
+
+ /*
+ * Transmit Buffer Ratio.
+ * Set to 1/3 of available buffer space (units are 1/64ths)
+ * if using Jumbo packets, ~64KB otherwise (assume 1MB on NIC).
+ */
+ if(NrjrHI > 0 || Nsr > 128)
+ csr32w(ctlr, Tbr, 64/3);
+ else
+ csr32w(ctlr, Tbr, 4);
+
+ /*
+ * Tuneable parameters.
+ * These defaults are based on the tuning hints in the Alteon
+ * Host/NIC Software Interface Definition and example software.
+ */
+ ctlr->rct = 1 /*100*/;
+ csr32w(ctlr, Rct, ctlr->rct);
+ ctlr->sct = 0;
+ csr32w(ctlr, Sct, ctlr->sct);
+ ctlr->st = 1000000;
+ csr32w(ctlr, St, ctlr->st);
+ ctlr->smcbd = Nsr/4;
+ csr32w(ctlr, SmcBD, ctlr->smcbd);
+ ctlr->rmcbd = 4 /*6*/;
+ csr32w(ctlr, RmcBD, ctlr->rmcbd);
+
+ /*
+ * Enable DMA Assist Logic.
+ */
+ csr = csr32r(ctlr, DMAas) & ~0x03;
+ csr32w(ctlr, DMAas, csr|0x01);
+
+ /*
+ * Link negotiation.
+ * The bits are set here but the NIC must be given a command
+ * once it is running to set negotiation in motion.
+ */
+ csr32w(ctlr, Gln, Le|Lean|Lofc|Lfd|L1000MB|Lpref);
+ csr32w(ctlr, Fln, Le|Lean|Lhd|Lfd|L100MB|L10MB);
+
+ /*
+ * A unique index for this controller and the maximum packet
+ * length expected.
+ * For now only standard packets are expected.
+ */
+ csr32w(ctlr, Ifx, 1);
+ csr32w(ctlr, IfMTU, ETHERMAXTU+4);
+
+ /*
+ * Enable Interrupts.
+ * There are 3 ways to mask interrupts - a bit in the Mhc (which
+ * is already cleared), the Mi register and the Hi mailbox.
+ * Writing to the Hi mailbox has the side-effect of clearing the
+ * PCI interrupt.
+ */
+ csr32w(ctlr, Mi, 0);
+ csr32w(ctlr, Hi, 0);
+
+ /*
+ * Start the firmware.
+ */
+ csr32w(ctlr, CPUApc, tigon2FwStartAddr);
+ csr = csr32r(ctlr, CPUAstate) & ~CPUhalt;
+ csr32w(ctlr, CPUAstate, csr);
+
+ return 0;
+}
+
+static int
+at24c32io(Ctlr* ctlr, char* op, int data)
+{
+ char *lp, *p;
+ int i, loop, mlc, r;
+
+ mlc = csr32r(ctlr, Mlc);
+
+ r = 0;
+ loop = -1;
+ lp = nil;
+ for(p = op; *p != '\0'; p++){
+ switch(*p){
+ default:
+ return -1;
+ case ' ':
+ continue;
+ case ':': /* start of 8-bit loop */
+ if(lp != nil)
+ return -1;
+ lp = p;
+ loop = 7;
+ continue;
+ case ';': /* end of 8-bit loop */
+ if(lp == nil)
+ return -1;
+ loop--;
+ if(loop >= 0)
+ p = lp;
+ else
+ lp = nil;
+ continue;
+ case 'C': /* assert clock */
+ mlc |= EEclk;
+ break;
+ case 'c': /* deassert clock */
+ mlc &= ~EEclk;
+ break;
+ case 'D': /* next bit in 'data' byte */
+ if(loop < 0)
+ return -1;
+ if(data & (1<<loop))
+ mlc |= EEdo;
+ else
+ mlc &= ~EEdo;
+ break;
+ case 'E': /* enable data output */
+ mlc |= EEdoe;
+ break;
+ case 'e': /* disable data output */
+ mlc &= ~EEdoe;
+ break;
+ case 'I': /* input bit */
+ i = (csr32r(ctlr, Mlc) & EEdi) != 0;
+ if(loop >= 0)
+ r |= (i<<loop);
+ else
+ r = i;
+ continue;
+ case 'O': /* assert data output */
+ mlc |= EEdo;
+ break;
+ case 'o': /* deassert data output */
+ mlc &= ~EEdo;
+ break;
+ }
+ csr32w(ctlr, Mlc, mlc);
+ microdelay(1);
+ }
+ if(loop >= 0)
+ return -1;
+ return r;
+}
+
+static int
+at24c32r(Ctlr* ctlr, int addr)
+{
+ int data;
+
+ /*
+ * Read a byte at address 'addr' from the Atmel AT24C32
+ * Serial EEPROM. The 2-wire EEPROM access is controlled
+ * by 4 bits in Mlc. See the AT24C32 datasheet for
+ * protocol details.
+ */
+ /*
+ * Start condition - a high to low transition of data
+ * with the clock high must precede any other command.
+ */
+ at24c32io(ctlr, "OECoc", 0);
+
+ /*
+ * Perform a random read at 'addr'. A dummy byte
+ * write sequence is performed to clock in the device
+ * and data word addresses (0 and 'addr' respectively).
+ */
+ data = -1;
+ if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA0) != 0)
+ goto stop;
+ if(at24c32io(ctlr, "oE :DCc; oeCIc", addr>>8) != 0)
+ goto stop;
+ if(at24c32io(ctlr, "oE :DCc; oeCIc", addr) != 0)
+ goto stop;
+
+ /*
+ * Now send another start condition followed by a
+ * request to read the device. The EEPROM responds
+ * by clocking out the data.
+ */
+ at24c32io(ctlr, "OECoc", 0);
+ if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA1) != 0)
+ goto stop;
+ data = at24c32io(ctlr, ":CIc;", 0xA1);
+
+stop:
+ /*
+ * Stop condition - a low to high transition of data
+ * with the clock high is a stop condition. After a read
+ * sequence, the stop command will place the EEPROM in
+ * a standby power mode.
+ */
+ at24c32io(ctlr, "oECOc", 0);
+
+ return data;
+}
+
+static int
+ga620detach(Ctlr* ctlr)
+{
+ int timeo;
+
+ /*
+ * Hard reset (don't know which endian so catch both);
+ * enable for little-endian mode;
+ * wait for code to be loaded from serial EEPROM or flash;
+ * make sure CPU A is halted.
+ */
+ csr32w(ctlr, Mhc, Hr<<24 | Hr);
+ csr32w(ctlr, Mhc, (Eews|Ci)<<24 | Eews|Ci);
+
+ microdelay(1);
+ for(timeo = 0; timeo < 500000; timeo++){
+ if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) == CPUhie)
+ break;
+ microdelay(1);
+ }
+ if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) != CPUhie)
+ return -1;
+ csr32w(ctlr, CPUAstate, CPUhalt);
+
+ /*
+ * After reset, CPU B seems to be stuck in 'CPUrf'.
+ * Worry about it later.
+ */
+ csr32w(ctlr, CPUBstate, CPUhalt);
+
+ return 0;
+}
+
+static void
+ga620shutdown(Ether* ether)
+{
+print("ga620shutdown\n");
+ ga620detach(ether->ctlr);
+}
+
+static int
+ga620reset(Ctlr* ctlr)
+{
+ int cls, csr, i, r;
+
+ if(ga620detach(ctlr) < 0)
+ return -1;
+
+ /*
+ * Tigon 2 PCI NICs have 512KB SRAM per bank.
+ * Clear out any lingering serial EEPROM state
+ * bits.
+ */
+ csr = csr32r(ctlr, Mlc) & ~(EEdi|EEdo|EEdoe|EEclk|SRAMmask);
+ csr32w(ctlr, Mlc, SRAM512|csr);
+ csr = csr32r(ctlr, Mc);
+ csr32w(ctlr, Mc, SyncSRAM|csr);
+
+ /*
+ * Initialise PCI State register.
+ * If PCI Write-and-Invalidate is enabled set the max write DMA
+ * value to the host cache-line size (32 on Pentium or later).
+ */
+ csr = csr32r(ctlr, Ps) & (PCI32|PCI66);
+ csr |= PCIwcmd|PCIrcmd|PCImrm;
+ if(ctlr->pcidev->pcr & 0x0010){
+ cls = pcicfgr8(ctlr->pcidev, PciCLS) * 4;
+ if(cls != 32)
+ pcicfgw8(ctlr->pcidev, PciCLS, 32/4);
+ csr |= PCIwm32;
+ }
+ csr32w(ctlr, Ps, csr);
+
+ /*
+ * Operating Mode.
+ */
+ csr32w(ctlr, Om, Fatal|NoJFrag|BswapDMA|WswapBD);
+
+ /*
+ * Snarf the MAC address from the serial EEPROM.
+ */
+ for(i = 0; i < Eaddrlen; i++){
+ if((r = at24c32r(ctlr, 0x8E+i)) == -1)
+ return -1;
+ ctlr->ea[i] = r;
+ }
+
+ /*
+ * Load the firmware.
+ */
+ ga620lmw(ctlr, tigon2FwTextAddr, tigon2FwText, tigon2FwTextLen);
+ ga620lmw(ctlr, tigon2FwRodataAddr, tigon2FwRodata, tigon2FwRodataLen);
+ ga620lmw(ctlr, tigon2FwDataAddr, tigon2FwData, tigon2FwDataLen);
+ ga620lmw(ctlr, tigon2FwSbssAddr, nil, tigon2FwSbssLen);
+ ga620lmw(ctlr, tigon2FwBssAddr, nil, tigon2FwBssLen);
+
+ /*
+ * we will eventually get events telling us that the firmware is
+ * up and that the link is up.
+ */
+ return 0;
+}
+
+static void
+ga620pci(void)
+{
+ int port;
+ Pcidev *p;
+ Ctlr *ctlr;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+
+ switch(p->did<<16 | p->vid){
+ default:
+ continue;
+ case 0x620A<<16 | 0x1385: /* Netgear GA620 fiber */
+ case 0x630A<<16 | 0x1385: /* Netgear GA620T copper */
+ case 0x0001<<16 | 0x12AE: /* Alteon Acenic fiber
+ * and DEC DEGPA-SA */
+ case 0x0002<<16 | 0x12AE: /* Alteon Acenic copper */
+ case 0x0009<<16 | 0x10A9: /* SGI Acenic */
+ break;
+ }
+
+ port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
+ if(port == 0){
+ print("ga620: can't map %d @ 0x%8.8luX\n",
+ p->mem[0].size, p->mem[0].bar);
+ continue;
+ }
+
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = port;
+ ctlr->pcidev = p;
+ ctlr->id = p->did<<16 | p->vid;
+
+ ctlr->nic = KADDR(ctlr->port);
+ if(ga620reset(ctlr)){
+ free(ctlr);
+ continue;
+ }
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+}
+
+int
+ga620pnp(Ether* edev)
+{
+ Ctlr *ctlr;
+ uchar ea[Eaddrlen];
+
+ if(ctlrhead == nil)
+ ga620pci();
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in the hardware.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, edev->ea, Eaddrlen) == 0)
+ memmove(edev->ea, ctlr->ea, Eaddrlen);
+
+ ga620init(edev); /* enables interrupts */
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ edev->attach = ga620attach;
+ edev->transmit = ga620transmit;
+ edev->interrupt = ga620interrupt;
+ edev->detach = ga620shutdown;
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/etherga620fw.h
@@ -1,0 +1,4858 @@
+/* Generated by genfw.c */
+#define tigon2FwReleaseMajor 0xc
+#define tigon2FwReleaseMinor 0x4
+#define tigon2FwReleaseFix 0xb
+#define tigon2FwStartAddr 0x00004000
+#define tigon2FwTextAddr 0x00004000
+#define tigon2FwTextLen 0x11bc0
+#define tigon2FwRodataAddr 0x00015bc0
+#define tigon2FwRodataLen 0x10d0
+#define tigon2FwDataAddr 0x00016cc0
+#define tigon2FwDataLen 0x1c0
+#define tigon2FwSbssAddr 0x00016e80
+#define tigon2FwSbssLen 0xcc
+#define tigon2FwBssAddr 0x00016f50
+#define tigon2FwBssLen 0x20c0
+static int tigon2FwText[/*(MAX_TEXT_LEN/4) + 1*/] = {
+0x0,
+0x10000003, 0x0, 0xd, 0xd,
+0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 0x3c100000,
+0x26104000, 0xc0010c0, 0x0, 0xd,
+0x3c1d0001, 0x8fbd6d24, 0x3a0f021, 0x3c100000,
+0x26104000, 0xc0017e0, 0x0, 0xd,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x2000008,
+0x0, 0x800172f, 0x3c0a0001, 0x800172f,
+0x3c0a0002, 0x800172f, 0x0, 0x8002cac,
+0x0, 0x8002c4f, 0x0, 0x800172f,
+0x3c0a0004, 0x800328a, 0x0, 0x8001a52,
+0x0, 0x800394d, 0x0, 0x80038f4,
+0x0, 0x800172f, 0x3c0a0006, 0x80039bb,
+0x3c0a0007, 0x800172f, 0x3c0a0008, 0x800172f,
+0x3c0a0009, 0x8003a13, 0x0, 0x8002ea6,
+0x0, 0x800172f, 0x3c0a000b, 0x800172f,
+0x3c0a000c, 0x800172f, 0x3c0a000d, 0x80028fb,
+0x0, 0x8002890, 0x0, 0x800172f,
+0x3c0a000e, 0x800208c, 0x0, 0x8001964,
+0x0, 0x8001a04, 0x0, 0x8003ca6,
+0x0, 0x8003c94, 0x0, 0x800172f,
+0x0, 0x800191a, 0x0, 0x800172f,
+0x0, 0x800172f, 0x3c0a0013, 0x800172f,
+0x3c0a0014, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x27bdffe0,
+0x3c1cc000, 0xafbf001c, 0xafb00018, 0x8f820140,
+0x24030003, 0xaf8300ec, 0x34420004, 0xc002b20,
+0xaf820140, 0x3c0100c0, 0xc001763, 0xac203ffc,
+0x401821, 0x3c020010, 0x3c010001, 0xac236e9c,
+0x10620011, 0x43102b, 0x14400002, 0x3c020020,
+0x3c020008, 0x1062000c, 0x24050100, 0x3c060001,
+0x8cc66e9c, 0x3c040001, 0x24845c74, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020020,
+0x3c010001, 0xac226e9c, 0x24020008, 0x3c010001,
+0xac226eb4, 0x2402001f, 0x3c010001, 0xac226ec4,
+0x24020016, 0x3c010001, 0xac226e98, 0x3c05fffe,
+0x34a56f08, 0x3c020001, 0x8c426e9c, 0x3c030002,
+0x24639010, 0x3c040001, 0x8c846cc4, 0x431023,
+0x14800002, 0x458021, 0x2610fa38, 0x2402f000,
+0x2028024, 0xc001785, 0x2002021, 0x2022823,
+0x3c040020, 0x821823, 0x651823, 0x247bb000,
+0x3c03fffe, 0x3463bf08, 0x363b821, 0x3c0600bf,
+0x34c6f000, 0x3c070001, 0x8ce76cc0, 0x3c0300bf,
+0x3463e000, 0x852023, 0x3c010001, 0xac246ea8,
+0x822023, 0x3c010001, 0xac256e90, 0x52842,
+0x3c010001, 0xac226e84, 0x27620ffc, 0x3c010001,
+0xac226d20, 0x27621ffc, 0xdb3023, 0x7b1823,
+0x3c010001, 0xac246e88, 0x3c010001, 0xac256eac,
+0x3c010001, 0xac226d24, 0xaf860150, 0x10e00011,
+0xaf830250, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021,
+0xc001749, 0x0, 0x3c020001, 0x8c426cd0,
+0x3c030001, 0x8c636cd4, 0x2442fe00, 0x24630200,
+0x3c010001, 0xac226cd0, 0x3c010001, 0x10000004,
+0xac236cd4, 0x3c1d0001, 0x8fbd6d20, 0x3a0f021,
+0x3c020001, 0x8c426cc4, 0x1040000d, 0x26fafa38,
+0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4,
+0x3c1a0001, 0x8f5a6cd4, 0x2442fa38, 0x246305c8,
+0x3c010001, 0xac226cd0, 0x3c010001, 0xac236cd4,
+0x3c020001, 0x8c426cc8, 0x14400003, 0x0,
+0x3c010001, 0xac206cd0, 0xc001151, 0x0,
+0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020,
+0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4,
+0x27bdff98, 0xafb00048, 0x3c100001, 0x8e1066b8,
+0xafb20050, 0x3c120000, 0x26524100, 0xafbf0060,
+0xafbe005c, 0xafb50058, 0xafb30054, 0xafb1004c,
+0xafa20034, 0xafa30030, 0xafa00010, 0xafa00014,
+0x8f860040, 0x3c040001, 0x24845c80, 0x24050200,
+0x3c010001, 0xac326e80, 0xc002b3b, 0x2003821,
+0x8f830040, 0x3c02f000, 0x621824, 0x3c026000,
+0x1062000b, 0xa3a0003f, 0x240e0001, 0x3c040001,
+0x24845c88, 0xa3ae003f, 0xafa00010, 0xafa00014,
+0x8f860040, 0x24050300, 0xc002b3b, 0x2003821,
+0x8f820240, 0x3c030001, 0x431025, 0xaf820240,
+0xaf800048, 0x8f820048, 0x14400005, 0x0,
+0xaf800048, 0x8f820048, 0x10400004, 0x0,
+0xaf800048, 0x10000003, 0x2e02021, 0xaf80004c,
+0x2e02021, 0x3c050001, 0xc002ba8, 0x34a540f8,
+0x3402021, 0xc002ba8, 0x240505c8, 0x3c020001,
+0x8c426ea8, 0x3c0d0001, 0x8dad6e88, 0x3c030001,
+0x8c636e84, 0x3c080001, 0x8d086e90, 0x3c090001,
+0x8d296eac, 0x3c0a0001, 0x8d4a6eb4, 0x3c0b0001,
+0x8d6b6ec4, 0x3c0c0001, 0x8d8c6e98, 0x3c040001,
+0x24845c94, 0x24050400, 0xaf42013c, 0x8f42013c,
+0x24060001, 0x24070001, 0xaf400000, 0xaf4d0138,
+0xaf430144, 0xaf480148, 0xaf49014c, 0xaf4a0150,
+0xaf4b0154, 0xaf4c0158, 0x2442ff80, 0xaf420140,
+0x24020001, 0xafa20010, 0xc002b3b, 0xafa00014,
+0x8f420138, 0xafa20010, 0x8f42013c, 0xafa20014,
+0x8f460144, 0x8f470148, 0x3c040001, 0x24845ca0,
+0xc002b3b, 0x24050500, 0xafb70010, 0xafba0014,
+0x8f46014c, 0x8f470150, 0x3c040001, 0x24845cac,
+0xc002b3b, 0x24050600, 0x3c020001, 0x8c426e9c,
+0x3603821, 0x3c060002, 0x24c69010, 0x2448ffff,
+0x1061824, 0xe81024, 0x43102b, 0x10400006,
+0x24050900, 0x3c040001, 0x24845cb8, 0xafa80010,
+0xc002b3b, 0xafa00014, 0x8f82000c, 0xafa20010,
+0x8f82003c, 0xafa20014, 0x8f860000, 0x8f870004,
+0x3c040001, 0x24845cc4, 0xc002b3b, 0x24051000,
+0x8c020220, 0x8c030224, 0x8c060218, 0x8c07021c,
+0x3c040001, 0x24845ccc, 0x24051100, 0xafa20010,
+0xc002b3b, 0xafa30014, 0xaf800054, 0xaf80011c,
+0x8c020218, 0x30420002, 0x10400009, 0x0,
+0x8c020220, 0x3c030002, 0x34630004, 0x431025,
+0xaf42000c, 0x8c02021c, 0x10000008, 0x34420004,
+0x8c020220, 0x3c030002, 0x34630006, 0x431025,
+0xaf42000c, 0x8c02021c, 0x34420006, 0xaf420014,
+0x8c020218, 0x30420010, 0x1040000a, 0x0,
+0x8c02021c, 0x34420004, 0xaf420010, 0x8c020220,
+0x3c03000a, 0x34630004, 0x431025, 0x10000009,
+0xaf420008, 0x8c020220, 0x3c03000a, 0x34630006,
+0x431025, 0xaf420008, 0x8c02021c, 0x34420006,
+0xaf420010, 0x24020001, 0xaf8200a0, 0xaf8200b0,
+0x8f830054, 0x8f820054, 0xaf8000d0, 0xaf8000c0,
+0x10000002, 0x24630064, 0x8f820054, 0x621023,
+0x2c420065, 0x1440fffc, 0x0, 0x8c040208,
+0x8c05020c, 0x26e20028, 0xaee20020, 0x24020490,
+0xaee20010, 0xaee40008, 0xaee5000c, 0x26e40008,
+0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094,
+0x8c820018, 0xaf8200b4, 0x9482000a, 0xaf82009c,
+0x8f420014, 0xaf8200b0, 0x8f8200b0, 0x30420004,
+0x1440fffd, 0x0, 0x8f8200b0, 0x3c03ef00,
+0x431024, 0x10400021, 0x0, 0x8f8200b4,
+0xafa20010, 0x8f820090, 0x8f830094, 0x3c040001,
+0x24845cd4, 0xafa30014, 0x8f8600b0, 0x8f87009c,
+0x3c050001, 0xc002b3b, 0x34a5200d, 0x3c040001,
+0x24845ce0, 0x240203c0, 0xafa20010, 0xafa00014,
+0x8f860144, 0x3c070001, 0x24e75ce8, 0xc002b3b,
+0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c,
+0x8f820220, 0x34420004, 0xaf820220, 0x8f820140,
+0x3c030001, 0x431025, 0xaf820140, 0x96e20472,
+0x96e60452, 0x96e70462, 0xafa20010, 0x96e20482,
+0x3c040001, 0x24845d14, 0x24051200, 0xc002b3b,
+0xafa20014, 0x96f00452, 0x32020001, 0x10400002,
+0xb021, 0x24160001, 0x32020002, 0x54400001,
+0x36d60002, 0x32020008, 0x54400001, 0x36d60004,
+0x32020010, 0x54400001, 0x36d60008, 0x32020020,
+0x54400001, 0x36d60010, 0x32020040, 0x54400001,
+0x36d60020, 0x32020080, 0x54400001, 0x36d60040,
+0x96e60482, 0x30c20200, 0x54400001, 0x36d64000,
+0x96e30472, 0x30620200, 0x10400003, 0x30620100,
+0x10000003, 0x36d62000, 0x54400001, 0x36d61000,
+0x96f00462, 0x32c24000, 0x14400004, 0x3207009b,
+0x30c2009b, 0x14e20007, 0x240e0001, 0x32c22000,
+0x1440000d, 0x32020001, 0x3062009b, 0x10e20009,
+0x240e0001, 0x3c040001, 0x24845d20, 0x24051300,
+0x2003821, 0xa3ae003f, 0xafa30010, 0xc002b3b,
+0xafa00014, 0x32020001, 0x54400001, 0x36d60080,
+0x32020002, 0x54400001, 0x36d60100, 0x32020008,
+0x54400001, 0x36d60200, 0x32020010, 0x54400001,
+0x36d60400, 0x32020080, 0x54400001, 0x36d60800,
+0x8c020218, 0x30420200, 0x10400002, 0x3c020008,
+0x2c2b025, 0x8c020218, 0x30420800, 0x10400002,
+0x3c020080, 0x2c2b025, 0x8c020218, 0x30420400,
+0x10400002, 0x3c020100, 0x2c2b025, 0x8c020218,
+0x30420100, 0x10400002, 0x3c020200, 0x2c2b025,
+0x8c020218, 0x30420080, 0x10400002, 0x3c020400,
+0x2c2b025, 0x8c020218, 0x30422000, 0x10400002,
+0x3c020010, 0x2c2b025, 0x8c020218, 0x30424000,
+0x10400002, 0x3c020020, 0x2c2b025, 0x8c020218,
+0x30421000, 0x10400002, 0x3c020040, 0x2c2b025,
+0x8ee20498, 0x8ee3049c, 0xaf420160, 0xaf430164,
+0x8ee204a0, 0x8ee304a4, 0xaf420168, 0xaf43016c,
+0x8ee204a8, 0x8ee304ac, 0xaf420170, 0xaf430174,
+0x8ee20428, 0x8ee3042c, 0xaf420178, 0xaf43017c,
+0x8ee20448, 0x8ee3044c, 0xaf420180, 0xaf430184,
+0x8ee20458, 0x8ee3045c, 0xaf420188, 0xaf43018c,
+0x8ee20468, 0x8ee3046c, 0xaf420190, 0xaf430194,
+0x8ee20478, 0x8ee3047c, 0xaf420198, 0xaf43019c,
+0x8ee20488, 0x8ee3048c, 0xaf4201a0, 0xaf4301a4,
+0x8ee204b0, 0x8ee304b4, 0x24040080, 0xaf4201a8,
+0xaf4301ac, 0xc002ba8, 0x24050080, 0x8c02025c,
+0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200,
+0x24060008, 0xc002bbf, 0xaf4201f8, 0x3c043b9a,
+0x3484ca00, 0x3821, 0x24020006, 0x24030002,
+0xaf4201f4, 0x240203e8, 0xaf430204, 0xaf430200,
+0xaf4401fc, 0xaf420294, 0x24020001, 0xaf430290,
+0xaf42029c, 0x3c030001, 0x671821, 0x90636cd8,
+0x3471021, 0x24e70001, 0xa043022c, 0x2ce2000f,
+0x1440fff8, 0x3471821, 0x24e70001, 0x3c080001,
+0x350840f8, 0x8f820040, 0x3c040001, 0x24845d2c,
+0x24051400, 0x21702, 0x24420030, 0xa062022c,
+0x3471021, 0xa040022c, 0x8c070218, 0x2c03021,
+0x240205c8, 0xafa20010, 0xc002b3b, 0xafa80014,
+0x3c040001, 0x24845d38, 0x3c050000, 0x24a55c80,
+0x24060010, 0x27b10030, 0x2203821, 0x27b30034,
+0xc0017a3, 0xafb30010, 0x3c030001, 0x8c636cc8,
+0x1060000a, 0x408021, 0x8fa30030, 0x2405ff00,
+0x8fa20034, 0x246400ff, 0x852024, 0x831823,
+0x431023, 0xafa20034, 0xafa40030, 0x3c040001,
+0x24845d44, 0x3c050000, 0x24a54100, 0x24060108,
+0x2203821, 0xc0017a3, 0xafb30010, 0x409021,
+0x32c20003, 0x3c010001, 0xac326e80, 0x10400045,
+0x2203821, 0x8f820050, 0x3c030010, 0x431024,
+0x10400016, 0x0, 0x8c020218, 0x30420040,
+0x1040000f, 0x24020001, 0x8f820050, 0x8c030218,
+0x240e0001, 0x3c040001, 0x24845d50, 0xa3ae003f,
+0xafa20010, 0xafa30014, 0x8f870040, 0x24051500,
+0xc002b3b, 0x2c03021, 0x10000004, 0x0,
+0x3c010001, 0x370821, 0xa02240f4, 0x3c040001,
+0x24845d5c, 0x3c050001, 0x24a55b40, 0x3c060001,
+0x24c65bac, 0xc53023, 0x8f420010, 0x27b30030,
+0x2603821, 0x27b10034, 0x34420a00, 0xaf420010,
+0xc0017a3, 0xafb10010, 0x3c040001, 0x24845d70,
+0x3c050001, 0x24a5b714, 0x3c060001, 0x24c6ba90,
+0xc53023, 0x2603821, 0xaf420108, 0xc0017a3,
+0xafb10010, 0x3c040001, 0x24845d8c, 0x3c050001,
+0x24a5be58, 0x3c060001, 0x24c6c900, 0xc53023,
+0x2603821, 0x3c010001, 0xac226ef4, 0xc0017a3,
+0xafb10010, 0x3c040001, 0x24845da4, 0x10000024,
+0x24051600, 0x3c040001, 0x24845dac, 0x3c050001,
+0x24a5a10c, 0x3c060001, 0x24c6a238, 0xc53023,
+0xc0017a3, 0xafb30010, 0x3c040001, 0x24845dbc,
+0x3c050001, 0x24a5b2b0, 0x3c060001, 0x24c6b70c,
+0xc53023, 0x2203821, 0xaf420108, 0xc0017a3,
+0xafb30010, 0x3c040001, 0x24845dd0, 0x3c050001,
+0x24a5ba98, 0x3c060001, 0x24c6be50, 0xc53023,
+0x2203821, 0x3c010001, 0xac226ef4, 0xc0017a3,
+0xafb30010, 0x3c040001, 0x24845de4, 0x24051650,
+0x2c03021, 0x3821, 0x3c010001, 0xac226ef8,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x32c20020,
+0x10400021, 0x27a70030, 0x3c040001, 0x24845df0,
+0x3c050001, 0x24a5b13c, 0x3c060001, 0x24c6b2a8,
+0xc53023, 0x24022000, 0xaf42001c, 0x27a20034,
+0xc0017a3, 0xafa20010, 0x21900, 0x31982,
+0x3c040800, 0x641825, 0xae430028, 0x24030010,
+0xaf43003c, 0x96e30450, 0xaf430040, 0x8f430040,
+0x3c040001, 0x24845e04, 0xafa00014, 0xafa30010,
+0x8f47001c, 0x24051660, 0x3c010001, 0xac226ef0,
+0x10000025, 0x32c60020, 0x8ee20448, 0x8ee3044c,
+0xaf43001c, 0x8f42001c, 0x2442e000, 0x2c422001,
+0x1440000a, 0x240e0001, 0x3c040001, 0x24845e10,
+0xa3ae003f, 0xafa00010, 0xafa00014, 0x8f46001c,
+0x24051700, 0xc002b3b, 0x3821, 0x3c020000,
+0x24425cbc, 0x21100, 0x21182, 0x3c030800,
+0x431025, 0xae420028, 0x24020008, 0xaf42003c,
+0x96e20450, 0xaf420040, 0x8f420040, 0x3c040001,
+0x24845e1c, 0xafa00014, 0xafa20010, 0x8f47001c,
+0x24051800, 0x32c60020, 0xc002b3b, 0x0,
+0x3c050fff, 0x3c030001, 0x8c636ef4, 0x34a5ffff,
+0x2403021, 0x3c020001, 0x8c426ef8, 0x3c040800,
+0x651824, 0x31882, 0x641825, 0x451024,
+0x21082, 0x441025, 0xacc20080, 0x32c20180,
+0x10400056, 0xacc30020, 0x8f82005c, 0x3c030080,
+0x431024, 0x1040000d, 0x0, 0x8f820050,
+0xafa20010, 0x8f82005c, 0x240e0001, 0x3c040001,
+0x24845e28, 0xa3ae003f, 0xafa20014, 0x8f870040,
+0x24051900, 0xc002b3b, 0x2c03021, 0x8f820050,
+0x3c030010, 0x431024, 0x10400016, 0x0,
+0x8c020218, 0x30420040, 0x1040000f, 0x24020001,
+0x8f820050, 0x8c030218, 0x240e0001, 0x3c040001,
+0x24845d50, 0xa3ae003f, 0xafa20010, 0xafa30014,
+0x8f870040, 0x24052000, 0xc002b3b, 0x2c03021,
+0x10000004, 0x0, 0x3c010001, 0x370821,
+0xa02240f4, 0x3c040001, 0x24845e34, 0x3c050001,
+0x24a55ac0, 0x3c060001, 0x24c65b38, 0xc53023,
+0x8f420008, 0x27b30030, 0x2603821, 0x27b10034,
+0x34420e00, 0xaf420008, 0xc0017a3, 0xafb10010,
+0x3c040001, 0x24845e4c, 0x3c050001, 0x24a5d8b4,
+0x3c060001, 0x24c6e3c8, 0xc53023, 0x2603821,
+0xaf42010c, 0xc0017a3, 0xafb10010, 0x3c040001,
+0x24845e64, 0x3c050001, 0x24a5e9ac, 0x3c060001,
+0x24c6f0f0, 0xc53023, 0x2603821, 0x3c010001,
+0xac226f04, 0xc0017a3, 0xafb10010, 0x3c040001,
+0x24845e7c, 0x10000027, 0x24052100, 0x3c040001,
+0x24845e84, 0x3c050001, 0x24a59fc8, 0x3c060001,
+0x24c6a104, 0xc53023, 0x27b10030, 0x2203821,
+0x27b30034, 0xc0017a3, 0xafb30010, 0x3c040001,
+0x24845e94, 0x3c050001, 0x24a5cad4, 0x3c060001,
+0x24c6d8ac, 0xc53023, 0x2203821, 0xaf42010c,
+0xc0017a3, 0xafb30010, 0x3c040001, 0x24845ea4,
+0x3c050001, 0x24a5e84c, 0x3c060001, 0x24c6e9a4,
+0xc53023, 0x2203821, 0x3c010001, 0xac226f04,
+0xc0017a3, 0xafb30010, 0x3c040001, 0x24845eb8,
+0x24052150, 0x2c03021, 0x3821, 0x3c010001,
+0xac226f10, 0xafa00010, 0xc002b3b, 0xafa00014,
+0x3c110fff, 0x3c030001, 0x8c636f04, 0x3631ffff,
+0x2409821, 0x3c020001, 0x8c426f10, 0x3c0e0800,
+0x711824, 0x31882, 0x6e1825, 0x511024,
+0x21082, 0x4e1025, 0xae630038, 0xae620078,
+0x8c020218, 0x30420040, 0x14400004, 0x24020001,
+0x3c010001, 0x370821, 0xa02240f4, 0x3c040001,
+0x24845ec4, 0x3c050001, 0x24a5e3d0, 0x3c060001,
+0x24c6e52c, 0xc53023, 0x27be0030, 0x3c03821,
+0x27b50034, 0xc0017a3, 0xafb50010, 0x3c010001,
+0xac226efc, 0x511024, 0x21082, 0x3c0e0800,
+0x4e1025, 0xae620050, 0x32c22000, 0x10400006,
+0x3c03821, 0x3c020000, 0x24425cbc, 0x2221024,
+0x1000000f, 0x21082, 0x3c040001, 0x24845ed8,
+0x3c050001, 0x24a5e534, 0x3c060001, 0x24c6e6e4,
+0xc53023, 0xc0017a3, 0xafb50010, 0x3c010001,
+0xac226f14, 0x511024, 0x21082, 0x3c0e0800,
+0x4e1025, 0xae620048, 0x32c24000, 0x10400005,
+0x27a70030, 0x3c020000, 0x24425cbc, 0x1000000e,
+0x21100, 0x3c040001, 0x24845ef0, 0x3c050001,
+0x24a5e6ec, 0x3c060001, 0x24c6e844, 0xc53023,
+0x27a20034, 0xc0017a3, 0xafa20010, 0x3c010001,
+0xac226f08, 0x21100, 0x21182, 0x3c030800,
+0x431025, 0xae420060, 0x3c040001, 0x24845f08,
+0x3c050001, 0x24a58230, 0x3c060001, 0x24c68650,
+0xc53023, 0x27b10030, 0x2203821, 0x27b30034,
+0xc0017a3, 0xafb30010, 0x3c0e0fff, 0x35ceffff,
+0x3c040001, 0x24845f14, 0x3c050000, 0x24a56468,
+0x3c060000, 0x24c66588, 0xc53023, 0x2203821,
+0x240f021, 0x3c010001, 0xac226edc, 0x4e1024,
+0x21082, 0x3c150800, 0x551025, 0xafae0044,
+0xafc200b8, 0xc0017a3, 0xafb30010, 0x3c040001,
+0x24845f20, 0x3c050000, 0x24a56590, 0x3c060000,
+0x24c66808, 0x8fae0044, 0xc53023, 0x2203821,
+0x3c010001, 0xac226ed0, 0x4e1024, 0x21082,
+0x551025, 0xafc200e8, 0xc0017a3, 0xafb30010,
+0x3c040001, 0x24845f38, 0x3c050000, 0x24a56810,
+0x3c060000, 0x24c66940, 0x8fae0044, 0xc53023,
+0x2203821, 0x3c010001, 0xac226ec8, 0x4e1024,
+0x21082, 0x551025, 0xafc200c0, 0xc0017a3,
+0xafb30010, 0x3c040001, 0x24845f50, 0x3c050001,
+0x24a5fad0, 0x3c060001, 0x24c6fba8, 0x8fae0044,
+0xc53023, 0x2203821, 0x3c010001, 0xac226ed4,
+0x4e1024, 0x21082, 0x551025, 0xafc200c8,
+0xc0017a3, 0xafb30010, 0x3c040001, 0x24845f5c,
+0x3c050001, 0x24a5c93c, 0x3c060001, 0x24c6ca20,
+0xc53023, 0x2203821, 0xaf420110, 0xc0017a3,
+0xafb30010, 0x3c040001, 0x24845f6c, 0x3c050001,
+0x24a5c910, 0x3c060001, 0x24c6c934, 0xc53023,
+0x2203821, 0xaf420124, 0xc0017a3, 0xafb30010,
+0x3c040001, 0x24845f7c, 0x3c050001, 0x24a55a80,
+0x3c060001, 0x24c65aac, 0xc53023, 0x2203821,
+0xaf420120, 0xaf420114, 0xc0017a3, 0xafb30010,
+0x3c040001, 0x24845f88, 0x3c050001, 0x24a5f298,
+0x3c060001, 0x24c6f6b4, 0xc53023, 0x2203821,
+0xaf420118, 0xc0017a3, 0xafb30010, 0x8fae0044,
+0x3c010001, 0xac226f18, 0x4e1024, 0x21082,
+0x551025, 0xc003fc3, 0xafc200d0, 0xc003c40,
+0x0, 0xc0027a8, 0x0, 0xac000228,
+0xac00022c, 0x96e20450, 0x2442ffff, 0xaf420038,
+0x96e20460, 0xaf420080, 0x32c24000, 0x14400003,
+0x0, 0x96e20480, 0xaf420084, 0x96e70490,
+0x50e00001, 0x24070800, 0x24e2ffff, 0xaf420088,
+0xaf42007c, 0x24020800, 0x10e2000f, 0x32c24000,
+0x10400003, 0x24020400, 0x10e2000b, 0x0,
+0x240e0001, 0x3c040001, 0x24845f98, 0xa3ae003f,
+0x96e60490, 0x24052170, 0x2c03821, 0xafa00010,
+0xc002b3b, 0xafa00014, 0x8f430138, 0x8f440138,
+0x24020001, 0xa34205c2, 0xaf430094, 0xaf440098,
+0xafa00010, 0xafa00014, 0x8f460080, 0x8f470084,
+0x3c040001, 0x24845fa4, 0xc002b3b, 0x24052200,
+0xc0024a4, 0x3c110800, 0x3c1433d8, 0x3694cb58,
+0x3c020800, 0x34420080, 0x3c040001, 0x24845fb0,
+0x3c050000, 0x24a55d00, 0x3c060000, 0x24c65d1c,
+0xc53023, 0x27a70030, 0xaf820060, 0x2402ffff,
+0xaf820064, 0x27a20034, 0xc0017a3, 0xafa20010,
+0x3c010001, 0xac226eb8, 0x21100, 0x21182,
+0x511025, 0xc0018fc, 0xae420000, 0x8f820240,
+0x3c030001, 0x431025, 0xaf820240, 0x3c020000,
+0x24424034, 0xaf820244, 0xaf800240, 0x8f820060,
+0x511024, 0x14400005, 0x3c030800, 0x8f820060,
+0x431024, 0x1040fffd, 0x0, 0xc003c4d,
+0x8821, 0x3c020100, 0xafa20020, 0x8f530018,
+0x240200ff, 0x56620001, 0x26710001, 0x8c020228,
+0x1622000e, 0x1330c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x24845c24, 0x3c050009, 0xafa00014, 0xafa20010,
+0x8fa60020, 0x1000003f, 0x34a50100, 0xd71021,
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
+0xc01821, 0x8f440178, 0x8f45017c, 0x1021,
+0x24070004, 0xafa70010, 0xafb10014, 0x8f48000c,
+0x24c604c0, 0x2e63021, 0xafa80018, 0x8f48010c,
+0x24070008, 0xa32821, 0xa3482b, 0x822021,
+0x100f809, 0x892021, 0x1440000b, 0x24070008,
+0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001,
+0x24845c2c, 0x3c050009, 0xafa20014, 0x8fa60020,
+0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164,
+0x8f43000c, 0xaf510018, 0x8f860120, 0x24020010,
+0xafa20010, 0xafb10014, 0xafa30018, 0x8f42010c,
+0x40f809, 0x24c6001c, 0x14400010, 0x0,
+0x8f420340, 0x24420001, 0xaf420340, 0x8f420340,
+0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001,
+0x24845c34, 0x3c050009, 0xafa20014, 0x8fa60020,
+0x34a50300, 0xc002b3b, 0x2603821, 0x8f4202e4,
+0x24420001, 0xaf4202e4, 0x8f4202e4, 0x93a2003f,
+0x10400069, 0x3c020700, 0x34423000, 0xafa20028,
+0x8f530018, 0x240200ff, 0x12620002, 0x8821,
+0x26710001, 0x8c020228, 0x1622000e, 0x1330c0,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x24845c24, 0x3c050009,
+0xafa00014, 0xafa20010, 0x8fa60028, 0x1000003f,
+0x34a50100, 0xd71021, 0x8fa30028, 0x8fa4002c,
+0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
+0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
+0xafb10014, 0x8f48000c, 0x24c604c0, 0x2e63021,
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24845c2c, 0x3c050009,
+0xafa20014, 0x8fa60028, 0x1000001c, 0x34a50200,
+0x8f440160, 0x8f450164, 0x8f43000c, 0xaf510018,
+0x8f860120, 0x24020010, 0xafa20010, 0xafb10014,
+0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x14400010, 0x0, 0x8f420340, 0x24420001,
+0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24845c34, 0x3c050009,
+0xafa20014, 0x8fa60028, 0x34a50300, 0xc002b3b,
+0x2603821, 0x8f4202f0, 0x24420001, 0xaf4202f0,
+0x8f4202f0, 0x3c040001, 0x24845fc0, 0xafa00010,
+0xafa00014, 0x8fa60028, 0x24052300, 0xc002b3b,
+0x3821, 0x10000004, 0x0, 0x8c020264,
+0x10400005, 0x0, 0x8f8200a0, 0x30420004,
+0x1440fffa, 0x0, 0x8f820044, 0x34420004,
+0xaf820044, 0x8f420308, 0x24420001, 0xaf420308,
+0x8f420308, 0x8f8200d8, 0x8f8300d4, 0x431023,
+0x2442ff80, 0xaf420090, 0x8f420090, 0x2842ff81,
+0x10400006, 0x24020001, 0x8f420090, 0x8f430144,
+0x431021, 0xaf420090, 0x24020001, 0xaf42008c,
+0x32c20008, 0x10400006, 0x0, 0x8f820214,
+0x3c038100, 0x3042ffff, 0x431025, 0xaf820214,
+0x3c030001, 0x8c636d94, 0x30620002, 0x10400009,
+0x30620001, 0x3c040001, 0x24845fcc, 0x3c050000,
+0x24a56d50, 0x3c060000, 0x24c671c8, 0x10000012,
+0xc53023, 0x10400009, 0x0, 0x3c040001,
+0x24845fdc, 0x3c050000, 0x24a571d0, 0x3c060000,
+0x24c67678, 0x10000008, 0xc53023, 0x3c040001,
+0x24845fec, 0x3c050000, 0x24a56948, 0x3c060000,
+0x24c66d48, 0xc53023, 0x27a70030, 0x27a20034,
+0xc0017a3, 0xafa20010, 0x3c010001, 0xac226ecc,
+0x3c020001, 0x8c426ecc, 0x3c030800, 0x21100,
+0x21182, 0x431025, 0xae420040, 0x8f8200a0,
+0xafa20010, 0x8f8200b0, 0xafa20014, 0x8f86005c,
+0x8f87011c, 0x3c040001, 0x24845ffc, 0x3c010001,
+0xac366ea4, 0x3c010001, 0xac206e94, 0x3c010001,
+0xac3c6e8c, 0x3c010001, 0xac3b6ebc, 0x3c010001,
+0xac376ec0, 0x3c010001, 0xac3a6ea0, 0xc002b3b,
+0x24052400, 0x8f820200, 0xafa20010, 0x8f820220,
+0xafa20014, 0x8f860044, 0x8f870050, 0x3c040001,
+0x24846008, 0xc002b3b, 0x24052500, 0x8f830060,
+0x74100b, 0x242000a, 0x200f821, 0x0,
+0xd, 0x8fbf0060, 0x8fbe005c, 0x8fb50058,
+0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048,
+0x3e00008, 0x27bd0068, 0x27bdffe0, 0x3c040001,
+0x24846014, 0x24052600, 0x3021, 0x3821,
+0xafbf0018, 0xafa00010, 0xc002b3b, 0xafa00014,
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008,
+0x0, 0x3e00008, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x3e00008, 0x0, 0x3e00008, 0x0,
+0x27bdfde0, 0x27a50018, 0x3c04dead, 0x3484beef,
+0xafbf0218, 0x8f820150, 0x3c03001f, 0x3463ffff,
+0xafa40018, 0xa22823, 0xa32824, 0x8ca20000,
+0x1044000a, 0x0, 0xafa50010, 0x8ca20000,
+0xafa20014, 0x8f860150, 0x8f870250, 0x3c040001,
+0x2484601c, 0xc002b3b, 0x24052700, 0x8fbf0218,
+0x3e00008, 0x27bd0220, 0x27bdffe0, 0x3c06abba,
+0x34c6babe, 0xafb00018, 0x3c100004, 0x3c07007f,
+0x34e7ffff, 0xafbf001c, 0x102840, 0x8e040000,
+0x8ca30000, 0xaca00000, 0xae060000, 0x8ca20000,
+0xaca30000, 0x10460005, 0xae040000, 0xa08021,
+0xf0102b, 0x1040fff5, 0x102840, 0x3c040001,
+0x24846028, 0x24052800, 0x2003021, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x2001021,
+0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020,
+0x8c020224, 0x3047003f, 0x10e00010, 0x803021,
+0x2821, 0x24030020, 0xe31024, 0x10400002,
+0x63042, 0xa62821, 0x31842, 0x1460fffb,
+0xe31024, 0x2402f000, 0xa22824, 0x3402ffff,
+0x45102b, 0x14400003, 0x3c020001, 0x10000008,
+0x3c020001, 0x3442ffff, 0x851823, 0x43102b,
+0x14400003, 0xa01021, 0x3c02fffe, 0x821021,
+0x3e00008, 0x0, 0x27bdffd0, 0xafb50028,
+0x8fb50040, 0xafb20020, 0xa09021, 0xafb1001c,
+0x24c60003, 0xafbf002c, 0xafb30024, 0xafb00018,
+0x8ea20000, 0x2403fffc, 0xc38024, 0x50102b,
+0x1440001b, 0xe08821, 0x8e330000, 0xafb00010,
+0x8ea20000, 0xafa20014, 0x8e270000, 0x24053000,
+0xc002b3b, 0x2403021, 0x8e230000, 0x702021,
+0x64102b, 0x10400007, 0x2402821, 0x8ca20000,
+0xac620000, 0x24630004, 0x64102b, 0x1440fffb,
+0x24a50004, 0x8ea20000, 0x501023, 0xaea20000,
+0x8e220000, 0x501021, 0x1000000b, 0xae220000,
+0x2402002d, 0xa0820000, 0xafb00010, 0x8ea20000,
+0x2409821, 0xafa20014, 0x8e270000, 0x24053100,
+0xc002b3b, 0x2603021, 0x2601021, 0x8fbf002c,
+0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c,
+0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffe8,
+0x3c1cc000, 0x3c05fffe, 0x3c030001, 0x8c636e84,
+0x3c040001, 0x8c846e90, 0x34a5bf08, 0x24021ffc,
+0x3c010001, 0xac226cd0, 0x3c0200c0, 0x3c010001,
+0xac226cd4, 0x3c020020, 0xafbf0010, 0x3c0100c0,
+0xac201ffc, 0x431023, 0x441023, 0x245bb000,
+0x365b821, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021,
+0x3c0400c0, 0x34840200, 0x3c1a00c0, 0x3c0300c0,
+0x346307c8, 0x24021dfc, 0x3c010001, 0xac226cd0,
+0x24021834, 0x3c010001, 0xac246cd4, 0x3c010001,
+0xac226cd0, 0x3c010001, 0xac236cd4, 0xc00180d,
+0x375a0200, 0x8fbf0010, 0x3e00008, 0x27bd0018,
+0x27bdffc8, 0x3c040001, 0x24846034, 0x24053200,
+0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4,
+0x3021, 0x3603821, 0xafbf0030, 0xafb3002c,
+0xafb20028, 0xafb10024, 0xafb00020, 0xafa2001c,
+0xafa30018, 0xafb70010, 0xc002b3b, 0xafba0014,
+0xc001916, 0x0, 0x8f820240, 0x34420004,
+0xaf820240, 0x24020001, 0xaf420000, 0x3c020001,
+0x571021, 0x904240f4, 0x10400092, 0x2403fffc,
+0x3c100001, 0x2610ac73, 0x3c120001, 0x2652a84c,
+0x2121023, 0x438024, 0x8fa3001c, 0x3c040001,
+0x24846040, 0x70102b, 0x1440001a, 0x27b30018,
+0x8fb10018, 0x24053000, 0x2403021, 0xafb00010,
+0xafa30014, 0xc002b3b, 0x2203821, 0x8fa30018,
+0x702021, 0x64102b, 0x10400007, 0x2403021,
+0x8cc20000, 0xac620000, 0x24630004, 0x64102b,
+0x1440fffb, 0x24c60004, 0x8fa2001c, 0x501023,
+0xafa2001c, 0x8e620000, 0x501021, 0x1000000a,
+0xae620000, 0x2408821, 0x24053100, 0xafb00010,
+0xafa30014, 0x8fa70018, 0x2203021, 0x2402002d,
+0xc002b3b, 0xa0820000, 0x24070020, 0x8fa3001c,
+0x3c040001, 0x2484605c, 0x24120020, 0x3c010001,
+0xac316eb0, 0x2c620020, 0x1440001d, 0x27b10018,
+0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f50,
+0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821,
+0x8fa30018, 0x3c040001, 0x24846f50, 0x24650020,
+0x65102b, 0x10400007, 0x0, 0x8c820000,
+0xac620000, 0x24630004, 0x65102b, 0x1440fffb,
+0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c,
+0x8e220000, 0x521021, 0x1000000b, 0xae220000,
+0x3c100001, 0x26106f50, 0x24053100, 0xafa70010,
+0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d,
+0xc002b3b, 0xa0820000, 0x24070020, 0x3c040001,
+0x24846070, 0x8fa3001c, 0x24120020, 0x3c010001,
+0xac306ee4, 0x2c620020, 0x1440001d, 0x27b10018,
+0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f70,
+0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821,
+0x8fa30018, 0x3c040001, 0x24846f70, 0x24650020,
+0x65102b, 0x10400007, 0x0, 0x8c820000,
+0xac620000, 0x24630004, 0x65102b, 0x1440fffb,
+0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c,
+0x8e220000, 0x521021, 0x1000000b, 0xae220000,
+0x3c100001, 0x26106f70, 0x24053100, 0xafa70010,
+0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d,
+0xc002b3b, 0xa0820000, 0x3c010001, 0x10000031,
+0xac306ee0, 0x3c100001, 0x2610821f, 0x3c120001,
+0x2652809c, 0x2121023, 0x438024, 0x8fa3001c,
+0x3c040001, 0x24846084, 0x70102b, 0x1440001a,
+0x27b30018, 0x8fb10018, 0x24053000, 0x2403021,
+0xafb00010, 0xafa30014, 0xc002b3b, 0x2203821,
+0x8fa30018, 0x702021, 0x64102b, 0x10400007,
+0x2403021, 0x8cc20000, 0xac620000, 0x24630004,
+0x64102b, 0x1440fffb, 0x24c60004, 0x8fa2001c,
+0x501023, 0xafa2001c, 0x8e620000, 0x501021,
+0x1000000a, 0xae620000, 0x2408821, 0x24053100,
+0xafb00010, 0xafa30014, 0x8fa70018, 0x2203021,
+0x2402002d, 0xc002b3b, 0xa0820000, 0x3c010001,
+0xac316eb0, 0x3c030001, 0x8c636eb0, 0x24020400,
+0x60f809, 0xaf820070, 0x8fbf0030, 0x8fb3002c,
+0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008,
+0x27bd0038, 0x0, 0x0, 0x8f820040,
+0x3c03f000, 0x431024, 0x3c036000, 0x14430006,
+0x0, 0x8f820050, 0x2403ff80, 0x431024,
+0x34420055, 0xaf820050, 0x8f820054, 0x244203e8,
+0xaf820058, 0x240201f4, 0xaf4200e0, 0x24020004,
+0xaf4200e8, 0x24020002, 0xaf4001b0, 0xaf4000e4,
+0xaf4200dc, 0xaf4000d8, 0xaf4000d4, 0x3e00008,
+0xaf4000d0, 0x8f820054, 0x24420005, 0x3e00008,
+0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054,
+0x244203e8, 0xaf820058, 0x3c020800, 0x2c21024,
+0x10400004, 0x3c02f7ff, 0x3442ffff, 0x2c2b024,
+0x36940040, 0x3c020001, 0x8c426da8, 0x10400017,
+0x3c020200, 0x3c030001, 0x8c636f1c, 0x10600016,
+0x282a025, 0x3c020001, 0x8c426e44, 0x14400012,
+0x3c020200, 0x3c020001, 0x8c426d94, 0x30420003,
+0x1440000d, 0x3c020200, 0x8f830224, 0x3c020002,
+0x8c428fec, 0x10620008, 0x3c020200, 0xc003daf,
+0x0, 0x10000004, 0x3c020200, 0xc004196,
+0x0, 0x3c020200, 0x2c21024, 0x10400003,
+0x0, 0xc001f4b, 0x0, 0x8f4200d8,
+0x8f4300dc, 0x24420001, 0xaf4200d8, 0x43102b,
+0x14400003, 0x0, 0xaf4000d8, 0x36940080,
+0x8c030238, 0x1060000c, 0x0, 0x8f4201b0,
+0x244203e8, 0xaf4201b0, 0x43102b, 0x14400006,
+0x0, 0x934205c5, 0x14400003, 0x0,
+0xc001da0, 0x0, 0x8fbf0010, 0x3e00008,
+0x27bd0018, 0x3e00008, 0x0, 0x27bdffd8,
+0xafbf0020, 0x8f43002c, 0x8f420038, 0x10620059,
+0x0, 0x3c020001, 0x571021, 0x904240f0,
+0x10400026, 0x24070008, 0x8f440170, 0x8f450174,
+0x8f48000c, 0x8f860120, 0x24020020, 0xafa20010,
+0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
+0x24c6001c, 0x14400011, 0x24020001, 0x3c010001,
+0x370821, 0xa02240f0, 0x8f820124, 0xafa20010,
+0x8f820128, 0x3c040001, 0x24846128, 0xafa20014,
+0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b,
+0x34a50900, 0x1000005c, 0x0, 0x8f420300,
+0x24420001, 0xaf420300, 0x8f420300, 0x8f42002c,
+0xa34005c1, 0x10000027, 0xaf420038, 0x8f440170,
+0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
+0x24020080, 0xafa20010, 0xafa30014, 0xafa80018,
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
+0x24020001, 0x3c010001, 0x370821, 0xa02240f1,
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
+0x24846134, 0xafa20014, 0x8f46002c, 0x8f870120,
+0x3c050009, 0xc002b3b, 0x34a51100, 0x10000036,
+0x0, 0x8f420300, 0x8f43002c, 0x24420001,
+0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1,
+0xaf430038, 0x3c010001, 0x370821, 0xa02040f1,
+0x3c010001, 0x370821, 0xa02040f0, 0x10000026,
+0xaf400034, 0x934205c1, 0x1040001d, 0x0,
+0xa34005c1, 0x8f820040, 0x30420001, 0x14400008,
+0x2021, 0x8c030104, 0x24020001, 0x50620005,
+0x24040001, 0x8c020264, 0x10400003, 0x801021,
+0x24040001, 0x801021, 0x10400006, 0x0,
+0x8f42030c, 0x24420001, 0xaf42030c, 0x10000008,
+0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044,
+0x8f420308, 0x24420001, 0xaf420308, 0x8f420308,
+0x3c010001, 0x370821, 0xa02040f0, 0x3c010001,
+0x370821, 0xa02040f1, 0x8f420000, 0x10400007,
+0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
+0x0, 0x10000005, 0x0, 0xaf800048,
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
+0x3c03ff7f, 0x3463ffff, 0x431024, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x10000002,
+0xaf80004c, 0xaf800048, 0x8fbf0020, 0x3e00008,
+0x27bd0028, 0x3e00008, 0x0, 0x27bdffd8,
+0xafbf0020, 0x8f430044, 0x8f42007c, 0x10620029,
+0x24070008, 0x8f440168, 0x8f45016c, 0x8f48000c,
+0x8f860120, 0x24020040, 0xafa20010, 0xafa30014,
+0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x14400011, 0x24020001, 0x3c010001, 0x370821,
+0xa02240f2, 0x8f820124, 0xafa20010, 0x8f820128,
+0x3c040001, 0x2484613c, 0xafa20014, 0x8f460044,
+0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51300,
+0x1000000f, 0x0, 0x8f420304, 0x24420001,
+0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c,
+0x3c010001, 0x370821, 0xa02040f2, 0x10000004,
+0xaf400078, 0x3c010001, 0x370821, 0xa02040f2,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x3c03feff, 0x3463ffff,
+0x431024, 0xaf820060, 0x8f420000, 0x10400003,
+0x0, 0x10000002, 0xaf80004c, 0xaf800048,
+0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008,
+0x0, 0x3c020001, 0x8c426da8, 0x27bdffa8,
+0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044,
+0xafb20040, 0xafb1003c, 0xafb00038, 0x104000d5,
+0x8f900044, 0x8f4200d0, 0x24430001, 0x2842000b,
+0x144000e4, 0xaf4300d0, 0x8f420004, 0x30420002,
+0x1440009c, 0xaf4000d0, 0x8f420004, 0x3c030001,
+0x8c636d98, 0x34420002, 0xaf420004, 0x24020001,
+0x14620003, 0x3c020600, 0x10000002, 0x34423000,
+0x34421000, 0xafa20020, 0x8f4a0018, 0xafaa0034,
+0x27aa0020, 0xafaa002c, 0x8faa0034, 0x240200ff,
+0x11420002, 0x1821, 0x25430001, 0x8c020228,
+0x609821, 0x1662000e, 0x3c050009, 0x8f42033c,
+0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228,
+0x8fa70034, 0x3c040001, 0x2484610c, 0xafa00014,
+0xafa20010, 0x8fa60020, 0x10000070, 0x34a50500,
+0x8faa0034, 0xa38c0, 0xf71021, 0x8fa30020,
+0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054,
+0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9,
+0x1040001b, 0xa821, 0xe09021, 0x265e04c0,
+0x8f440178, 0x8f45017c, 0x2401821, 0x240a0004,
+0xafaa0010, 0xafb30014, 0x8f48000c, 0x1021,
+0x2fe3021, 0xafa80018, 0x8f48010c, 0x24070008,
+0xa32821, 0xa3482b, 0x822021, 0x100f809,
+0x892021, 0x54400006, 0x24150001, 0x8f820054,
+0x2221023, 0x2c4203e9, 0x1440ffe9, 0x0,
+0x32a200ff, 0x54400018, 0xaf530018, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
+0x8faa002c, 0x8fa70034, 0xafa20010, 0x8f820124,
+0x3c040001, 0x24846118, 0xafa20014, 0x8d460000,
+0x3c050009, 0x10000035, 0x34a50600, 0x8f420308,
+0x24150001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001e, 0x32a200ff, 0x8f830054, 0x8f820054,
+0x247103e8, 0x2221023, 0x2c4203e9, 0x10400016,
+0xa821, 0x3c1e0020, 0x24120010, 0x8f42000c,
+0x8f440160, 0x8f450164, 0x8f860120, 0xafb20010,
+0xafb30014, 0x5e1025, 0xafa20018, 0x8f42010c,
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3,
+0x0, 0x8f820054, 0x2221023, 0x2c4203e9,
+0x1440ffee, 0x0, 0x32a200ff, 0x14400011,
+0x3c050009, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa002c, 0x8fa70034,
+0xafa20010, 0x8f820124, 0x3c040001, 0x24846120,
+0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b,
+0x0, 0x8f4202ec, 0x24420001, 0xaf4202ec,
+0x8f4202ec, 0x8f420004, 0x30420001, 0x50400029,
+0x36100040, 0x3c020400, 0x2c21024, 0x10400013,
+0x2404ffdf, 0x8f420250, 0x8f430254, 0x8f4401b4,
+0x14640006, 0x36100040, 0x8f420270, 0x8f430274,
+0x8f4401b8, 0x10640007, 0x2402ffdf, 0x8f420250,
+0x8f430254, 0x8f440270, 0x8f450274, 0x10000012,
+0x3a100020, 0x1000002b, 0x2028024, 0x8f420250,
+0x8f430254, 0x8f4501b4, 0x14650006, 0x2048024,
+0x8f420270, 0x8f430274, 0x8f4401b8, 0x50640021,
+0x36100040, 0x8f420250, 0x8f430254, 0x8f440270,
+0x8f450274, 0x3a100040, 0xaf4301b4, 0x10000019,
+0xaf4501b8, 0x8f4200d4, 0x24430001, 0x10000011,
+0x28420033, 0x8f420004, 0x30420001, 0x10400009,
+0x3c020400, 0x2c21024, 0x10400004, 0x2402ffdf,
+0x2028024, 0x1000000b, 0x36100040, 0x10000009,
+0x36100060, 0x8f4200d4, 0x36100040, 0x24430001,
+0x284201f5, 0x14400003, 0xaf4300d4, 0xaf4000d4,
+0x3a100020, 0xaf900044, 0x2402ff7f, 0x282a024,
+0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044,
+0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008,
+0x27bd0058, 0x3e00008, 0x0, 0x3c020001,
+0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
+0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
+0x104000c7, 0xafb00030, 0x8f4200d0, 0x24430001,
+0x2842000b, 0x144000da, 0xaf4300d0, 0x8f420004,
+0x30420002, 0x14400097, 0xaf4000d0, 0x8f420004,
+0x3c030001, 0x8c636d98, 0x34420002, 0xaf420004,
+0x24020001, 0x14620003, 0x3c020600, 0x10000002,
+0x34423000, 0x34421000, 0xafa20020, 0x1821,
+0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
+0xafaa002c, 0x27c30001, 0x8c020228, 0x609021,
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010,
+0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021,
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
+0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
+0x24070008, 0xa32821, 0xa3482b, 0x822021,
+0x100f809, 0x892021, 0x54400006, 0x24130001,
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
+0x0, 0x326200ff, 0x54400017, 0xaf520018,
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
+0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124,
+0x3c040001, 0x24846118, 0x3c050009, 0xafa20014,
+0x8d460000, 0x10000035, 0x34a50600, 0x8f420308,
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001e, 0x326200ff, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400016,
+0x9821, 0x3c150020, 0x24110010, 0x8f42000c,
+0x8f440160, 0x8f450164, 0x8f860120, 0xafb10010,
+0xafb20014, 0x551025, 0xafa20018, 0x8f42010c,
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3,
+0x0, 0x8f820054, 0x2021023, 0x2c4203e9,
+0x1440ffee, 0x0, 0x326200ff, 0x14400011,
+0x0, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24846120, 0x3c050009,
+0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b,
+0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec,
+0x8f4202ec, 0x8f420004, 0x30420001, 0x10400018,
+0x24040001, 0x8f420250, 0x8f430254, 0x8f4501b4,
+0x3c010001, 0x14650006, 0xa0246cf1, 0x8f420270,
+0x8f430274, 0x8f4401b8, 0x10640021, 0x0,
+0x8f420250, 0x8f430254, 0x3c040001, 0x90846cf0,
+0x8f460270, 0x8f470274, 0x38840001, 0xaf4301b4,
+0xaf4701b8, 0x3c010001, 0x10000025, 0xa0246cf0,
+0x8f4200d4, 0x3c010001, 0xa0206cf0, 0x24430001,
+0x28420033, 0x1440001e, 0xaf4300d4, 0x3c020001,
+0x90426cf1, 0xaf4000d4, 0x10000017, 0x38420001,
+0x8f420004, 0x30420001, 0x10400008, 0x0,
+0xc00565a, 0x2021, 0x3c010001, 0xa0206cf1,
+0x3c010001, 0x1000000e, 0xa0206cf0, 0x8f4200d4,
+0x3c010001, 0xa0206cf0, 0x24430001, 0x284201f5,
+0x14400007, 0xaf4300d4, 0x3c020001, 0x90426cf1,
+0xaf4000d4, 0x421026, 0x3c010001, 0xa0226cf1,
+0x3c030001, 0x8c636d98, 0x24020002, 0x1462000c,
+0x3c030002, 0x3c030001, 0x90636cf1, 0x24020001,
+0x5462001f, 0x2021, 0x3c020001, 0x90426cf0,
+0x1443001b, 0x24040005, 0x10000019, 0x24040006,
+0x3c020002, 0x8c428ff4, 0x431024, 0x1040000b,
+0x24020001, 0x3c030001, 0x90636cf1, 0x54620010,
+0x2021, 0x3c020001, 0x90426cf0, 0x1443000c,
+0x24040003, 0x1000000a, 0x24040004, 0x3c030001,
+0x90636cf1, 0x14620006, 0x2021, 0x3c020001,
+0x90426cf0, 0x24040001, 0x50440001, 0x24040002,
+0xc00565a, 0x0, 0x2402ff7f, 0x282a024,
+0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
+0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
+0x27bd0050, 0x3e00008, 0x0, 0x3c020001,
+0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
+0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
+0x104000de, 0xafb00030, 0x8f4200d0, 0x3c040001,
+0x8c846d98, 0x24430001, 0x2842000b, 0xaf4400e8,
+0x144000fe, 0xaf4300d0, 0x8f420004, 0x30420002,
+0x14400095, 0xaf4000d0, 0x8f420004, 0x34420002,
+0xaf420004, 0x24020001, 0x14820003, 0x3c020600,
+0x10000002, 0x34423000, 0x34421000, 0xafa20020,
+0x1821, 0x8f5e0018, 0x27aa0020, 0x240200ff,
+0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228,
+0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c,
+0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228,
+0x3c040001, 0x2484610c, 0x3c050009, 0xafa00014,
+0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500,
+0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0,
+0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8,
+0x2021023, 0x2c4203e9, 0x1040001b, 0x9821,
+0xe08821, 0x263504c0, 0x8f440178, 0x8f45017c,
+0x2201821, 0x240a0004, 0xafaa0010, 0xafb20014,
+0x8f48000c, 0x1021, 0x2f53021, 0xafa80018,
+0x8f48010c, 0x24070008, 0xa32821, 0xa3482b,
+0x822021, 0x100f809, 0x892021, 0x54400006,
+0x24130001, 0x8f820054, 0x2021023, 0x2c4203e9,
+0x1440ffe9, 0x0, 0x326200ff, 0x54400017,
+0xaf520018, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24846118, 0x3c050009,
+0xafa20014, 0x8d460000, 0x10000035, 0x34a50600,
+0x8f420308, 0x24130001, 0x24420001, 0xaf420308,
+0x8f420308, 0x1000001e, 0x326200ff, 0x8f830054,
+0x8f820054, 0x247003e8, 0x2021023, 0x2c4203e9,
+0x10400016, 0x9821, 0x3c150020, 0x24110010,
+0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120,
+0xafb10010, 0xafb20014, 0x551025, 0xafa20018,
+0x8f42010c, 0x24070008, 0x40f809, 0x24c6001c,
+0x1440ffe3, 0x0, 0x8f820054, 0x2021023,
+0x2c4203e9, 0x1440ffee, 0x0, 0x326200ff,
+0x14400011, 0x0, 0x8f420378, 0x24420001,
+0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
+0xafa20010, 0x8f820124, 0x3c040001, 0x24846120,
+0x3c050009, 0xafa20014, 0x8d460000, 0x34a50700,
+0xc002b3b, 0x3c03821, 0x8f4202ec, 0x24420001,
+0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001,
+0x10400033, 0x3c020400, 0x2c21024, 0x10400017,
+0x0, 0x934205c0, 0x8f440250, 0x8f450254,
+0x8f4301b4, 0x34420020, 0x14a30006, 0xa34205c0,
+0x8f420270, 0x8f430274, 0x8f4401b8, 0x10640008,
+0x0, 0x8f420250, 0x8f430254, 0x934405c0,
+0x8f460270, 0x8f470274, 0x10000016, 0x38840040,
+0x934205c0, 0x10000048, 0x304200bf, 0x934205c0,
+0x8f440250, 0x8f450254, 0x8f4301b4, 0x304200bf,
+0x14a30006, 0xa34205c0, 0x8f420270, 0x8f430274,
+0x8f4401b8, 0x1064000b, 0x0, 0x8f420250,
+0x8f430254, 0x934405c0, 0x8f460270, 0x8f470274,
+0x38840020, 0xaf4301b4, 0xaf4701b8, 0x10000033,
+0xa34405c0, 0x934205c0, 0x1000002f, 0x34420020,
+0x934205c0, 0x8f4300d4, 0x34420020, 0xa34205c0,
+0x24620001, 0x10000023, 0x28630033, 0x8f4200e4,
+0x8f4300e0, 0x24420001, 0xaf4200e4, 0x43102a,
+0x14400006, 0x24030001, 0x8f4200e8, 0x14430002,
+0xaf4000e4, 0x24030004, 0xaf4300e8, 0x8f420004,
+0x30420001, 0x1040000d, 0x3c020400, 0x2c21024,
+0x10400007, 0x0, 0x934205c0, 0x34420040,
+0xa34205c0, 0x934205c0, 0x1000000f, 0x304200df,
+0x934205c0, 0x1000000c, 0x34420060, 0x934205c0,
+0x8f4300d4, 0x34420020, 0xa34205c0, 0x24620001,
+0x286300fb, 0x14600005, 0xaf4200d4, 0x934205c0,
+0xaf4000d4, 0x38420040, 0xa34205c0, 0x934205c0,
+0x8f4300e8, 0x3042007f, 0xa34205c0, 0x24020001,
+0x14620005, 0x0, 0x934405c0, 0x42102,
+0x10000003, 0x348400f0, 0x934405c0, 0x3484000f,
+0xc005640, 0x0, 0x2402ff7f, 0x282a024,
+0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
+0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
+0x27bd0050, 0x3e00008, 0x0, 0x27bdffb0,
+0x274401c0, 0x26e30028, 0x24650400, 0x65102b,
+0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c,
+0xafb20038, 0xafb10034, 0x10400007, 0xafb00030,
+0x8c820000, 0xac620000, 0x24630004, 0x65102b,
+0x1440fffb, 0x24840004, 0x8c020080, 0xaee20044,
+0x8c0200c0, 0xaee20040, 0x8c020084, 0xaee20030,
+0x8c020084, 0xaee2023c, 0x8c020088, 0xaee20240,
+0x8c02008c, 0xaee20244, 0x8c020090, 0xaee20248,
+0x8c020094, 0xaee2024c, 0x8c020098, 0xaee20250,
+0x8c02009c, 0xaee20254, 0x8c0200a0, 0xaee20258,
+0x8c0200a4, 0xaee2025c, 0x8c0200a8, 0xaee20260,
+0x8c0200ac, 0xaee20264, 0x8c0200b0, 0xaee20268,
+0x8c0200b4, 0xaee2026c, 0x8c0200b8, 0xaee20270,
+0x8c0200bc, 0x24040001, 0xaee20274, 0xaee00034,
+0x41080, 0x571021, 0x8ee30034, 0x8c42023c,
+0x24840001, 0x621821, 0x2c82000f, 0xaee30034,
+0x1440fff8, 0x41080, 0x8c0200cc, 0xaee20048,
+0x8c0200d0, 0xaee2004c, 0x8c0200e0, 0xaee201f8,
+0x8c0200e4, 0xaee201fc, 0x8c0200e8, 0xaee20200,
+0x8c0200ec, 0xaee20204, 0x8c0200f0, 0xaee20208,
+0x8ee400c0, 0x8ee500c4, 0x8c0200fc, 0x45102b,
+0x1040000b, 0x0, 0x8ee200c0, 0x8ee300c4,
+0x24040001, 0x24050000, 0x651821, 0x65302b,
+0x441021, 0x461021, 0xaee200c0, 0xaee300c4,
+0x8c0200fc, 0x8ee400c0, 0x8ee500c4, 0x2408ffff,
+0x24090000, 0x401821, 0x1021, 0x882024,
+0xa92824, 0x822025, 0xa32825, 0xaee400c0,
+0xaee500c4, 0x8ee400d0, 0x8ee500d4, 0x8c0200f4,
+0x45102b, 0x1040000b, 0x0, 0x8ee200d0,
+0x8ee300d4, 0x24040001, 0x24050000, 0x651821,
+0x65302b, 0x441021, 0x461021, 0xaee200d0,
+0xaee300d4, 0x8c0200f4, 0x8ee400d0, 0x8ee500d4,
+0x401821, 0x1021, 0x882024, 0xa92824,
+0x822025, 0xa32825, 0xaee400d0, 0xaee500d4,
+0x8ee400c8, 0x8ee500cc, 0x8c0200f8, 0x45102b,
+0x1040000b, 0x0, 0x8ee200c8, 0x8ee300cc,
+0x24040001, 0x24050000, 0x651821, 0x65302b,
+0x441021, 0x461021, 0xaee200c8, 0xaee300cc,
+0x8c0200f8, 0x8ee400c8, 0x8ee500cc, 0x401821,
+0x1021, 0x882024, 0xa92824, 0x822025,
+0xa32825, 0x24020008, 0xaee400c8, 0xaee500cc,
+0xafa20010, 0xafa00014, 0x8f42000c, 0x8c040208,
+0x8c05020c, 0xafa20018, 0x8f42010c, 0x26e60028,
+0x40f809, 0x24070400, 0x104000f0, 0x3c020400,
+0xafa20020, 0x934205c6, 0x10400089, 0x1821,
+0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
+0xafaa002c, 0x27c30001, 0x8c020228, 0x609021,
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010,
+0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
+0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
+0x24070008, 0xa32821, 0xa3482b, 0x822021,
+0x100f809, 0x892021, 0x54400006, 0x24130001,
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
+0x0, 0x326200ff, 0x54400017, 0xaf520018,
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
+0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124,
+0x3c040001, 0x24846118, 0x3c050009, 0xafa20014,
+0x8d460000, 0x10000033, 0x34a50600, 0x8f420308,
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
+0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
+0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
+0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
+0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
+0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
+0x326200ff, 0x54400012, 0x24020001, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
+0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001,
+0x24846120, 0x3c050009, 0xafa20014, 0x8d460000,
+0x34a50700, 0xc002b3b, 0x3c03821, 0x1021,
+0x1440005b, 0x24020001, 0x10000065, 0x0,
+0x8f510018, 0x240200ff, 0x12220002, 0x8021,
+0x26300001, 0x8c020228, 0x1602000e, 0x1130c0,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x248460f4, 0x3c050009,
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f,
+0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024,
+0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
+0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
+0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021,
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x248460fc, 0x3c050009,
+0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200,
+0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018,
+0x8f860120, 0x24020010, 0xafa20010, 0xafb00014,
+0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x54400011, 0x24020001, 0x8f420340, 0x24420001,
+0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24846104, 0x3c050009,
+0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b,
+0x2203821, 0x1021, 0x1040000d, 0x24020001,
+0x8f4202e8, 0xa34005c6, 0xaf4001b0, 0x24420001,
+0xaf4202e8, 0x8f4202e8, 0x8ee20150, 0x24420001,
+0xaee20150, 0x10000003, 0x8ee20150, 0x24020001,
+0xa34205c6, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
+0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
+0x3e00008, 0x27bd0050, 0x27bdffd8, 0xafbf0020,
+0x8f8200b0, 0x30420004, 0x10400068, 0x0,
+0x8f430128, 0x8f820104, 0x14620005, 0x0,
+0x8f430130, 0x8f8200b4, 0x10620006, 0x0,
+0x8f820104, 0xaf420128, 0x8f8200b4, 0x1000005b,
+0xaf420130, 0x8f8200b0, 0x3c030080, 0x431024,
+0x1040000d, 0x0, 0x8f82011c, 0x34420002,
+0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024,
+0xaf8200b0, 0x8f82011c, 0x2403fffd, 0x431024,
+0x1000004a, 0xaf82011c, 0x8f430128, 0x8f820104,
+0x14620005, 0x0, 0x8f430130, 0x8f8200b4,
+0x10620010, 0x0, 0x8f820104, 0xaf420128,
+0x8f8200b4, 0x8f430128, 0xaf420130, 0xafa30010,
+0x8f420130, 0x3c040001, 0x24846144, 0xafa20014,
+0x8f86011c, 0x8f8700b0, 0x3c050005, 0x10000031,
+0x34a50900, 0x8f420128, 0xafa20010, 0x8f420130,
+0x3c040001, 0x24846150, 0xafa20014, 0x8f86011c,
+0x8f8700b0, 0x3c050005, 0xc002b3b, 0x34a51000,
+0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104,
+0x8f8200b0, 0x34420001, 0xaf8200b0, 0x24020008,
+0xaf830104, 0xafa20010, 0xafa00014, 0x8f42000c,
+0x8c040208, 0x8c05020c, 0xafa20018, 0x8f42010c,
+0x26e60028, 0x40f809, 0x24070400, 0x8f82011c,
+0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc,
+0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f420128,
+0xafa20010, 0x8f420130, 0x3c040001, 0x2484615c,
+0xafa20014, 0x8f86011c, 0x8f8700b0, 0x3c050005,
+0x34a51100, 0xc002b3b, 0x0, 0x8f8200a0,
+0x30420004, 0x10400069, 0x0, 0x8f43012c,
+0x8f820124, 0x14620005, 0x0, 0x8f430134,
+0x8f8200a4, 0x10620006, 0x0, 0x8f820124,
+0xaf42012c, 0x8f8200a4, 0x1000005c, 0xaf420134,
+0x8f8200a0, 0x3c030080, 0x431024, 0x1040000d,
+0x0, 0x8f82011c, 0x34420002, 0xaf82011c,
+0x8f8200a0, 0x2403fffb, 0x431024, 0xaf8200a0,
+0x8f82011c, 0x2403fffd, 0x431024, 0x1000004b,
+0xaf82011c, 0x8f43012c, 0x8f820124, 0x14620005,
+0x0, 0x8f430134, 0x8f8200a4, 0x10620010,
+0x0, 0x8f820124, 0xaf42012c, 0x8f8200a4,
+0x8f43012c, 0xaf420134, 0xafa30010, 0x8f420134,
+0x3c040001, 0x24846168, 0xafa20014, 0x8f86011c,
+0x8f8700a0, 0x3c050005, 0x10000032, 0x34a51200,
+0x8f42012c, 0xafa20010, 0x8f420134, 0x3c040001,
+0x24846174, 0xafa20014, 0x8f86011c, 0x8f8700a0,
+0x3c050005, 0xc002b3b, 0x34a51300, 0x8f82011c,
+0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0,
+0x34420001, 0xaf8200a0, 0x24020080, 0xaf830124,
+0xafa20010, 0xafa00014, 0x8f420014, 0x8c040208,
+0x8c05020c, 0xafa20018, 0x8f420108, 0x3c060001,
+0x24c66ed8, 0x40f809, 0x24070004, 0x8f82011c,
+0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc,
+0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f42012c,
+0xafa20010, 0x8f420134, 0x3c040001, 0x24846180,
+0xafa20014, 0x8f86011c, 0x8f8700a0, 0x3c050005,
+0x34a51400, 0xc002b3b, 0x0, 0x8fbf0020,
+0x3e00008, 0x27bd0028, 0x3c081000, 0x24070001,
+0x3c060080, 0x3c050100, 0x8f820070, 0x481024,
+0x1040fffd, 0x0, 0x8f820054, 0x24420005,
+0xaf820078, 0x8c040234, 0x10800016, 0x1821,
+0x3c020001, 0x571021, 0x8c4240e8, 0x24420005,
+0x3c010001, 0x370821, 0xac2240e8, 0x3c020001,
+0x571021, 0x8c4240e8, 0x44102b, 0x14400009,
+0x0, 0x3c030080, 0x3c010001, 0x370821,
+0xac2040e8, 0x3c010001, 0x370821, 0x1000000b,
+0xa02740f0, 0x3c020001, 0x571021, 0x904240f0,
+0x54400006, 0x661825, 0x3c020001, 0x571021,
+0x904240f1, 0x54400001, 0x661825, 0x8c040230,
+0x10800013, 0x0, 0x3c020001, 0x571021,
+0x8c4240ec, 0x24420005, 0x3c010001, 0x370821,
+0xac2240ec, 0x3c020001, 0x571021, 0x8c4240ec,
+0x44102b, 0x14400006, 0x0, 0x3c010001,
+0x370821, 0xac2040ec, 0x10000006, 0x651825,
+0x3c020001, 0x571021, 0x904240f2, 0x54400001,
+0x651825, 0x1060ffbc, 0x0, 0x8f420000,
+0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x431025, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x1000ffa7, 0xaf80004c,
+0x1000ffa5, 0xaf800048, 0x3e00008, 0x0,
+0x0, 0x0, 0x0, 0x27bdffe0,
+0xafbf0018, 0x8f860064, 0x30c20004, 0x10400025,
+0x24040004, 0x8c020114, 0xaf420020, 0xaf840064,
+0x8f4202fc, 0x24420001, 0xaf4202fc, 0x8f4202fc,
+0x8f820064, 0x30420004, 0x14400005, 0x0,
+0x8c030114, 0x8f420020, 0x1462fff2, 0x0,
+0x8f420000, 0x10400007, 0x8f43003c, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x431025, 0xaf820060,
+0x8f420000, 0x10400073, 0x0, 0x1000006f,
+0x0, 0x30c20008, 0x10400020, 0x24040008,
+0x8c02011c, 0xaf420048, 0xaf840064, 0x8f4202a8,
+0x24420001, 0xaf4202a8, 0x8f4202a8, 0x8f820064,
+0x30420008, 0x14400005, 0x0, 0x8c03011c,
+0x8f420048, 0x1462fff2, 0x0, 0x8f420000,
+0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x1000ffd9, 0x34420200, 0x30c20020,
+0x10400023, 0x24040020, 0x8c02012c, 0xaf420068,
+0xaf840064, 0x8f4202d8, 0x24420001, 0xaf4202d8,
+0x8f4202d8, 0x8f820064, 0x30420020, 0x14400005,
+0x32c24000, 0x8c03012c, 0x8f420068, 0x1462fff2,
+0x32c24000, 0x14400002, 0x3c020001, 0x2c2b025,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x1000ffb4, 0x34420800,
+0x30c20010, 0x10400029, 0x24040010, 0x8c020124,
+0xaf420058, 0xaf840064, 0x8f4202d4, 0x24420001,
+0xaf4202d4, 0x8f4202d4, 0x8f820064, 0x30420010,
+0x14400005, 0x32c22000, 0x8c030124, 0x8f420058,
+0x1462fff2, 0x32c22000, 0x50400001, 0x36d68000,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x34420100, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x1000006c,
+0xaf80004c, 0x1000006a, 0xaf800048, 0x30c20001,
+0x10400004, 0x24020001, 0xaf820064, 0x10000064,
+0x0, 0x30c20002, 0x1440000b, 0x3c050003,
+0x3c040001, 0x24846244, 0x34a50500, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x2402ffc0,
+0x10000057, 0xaf820064, 0x8c05022c, 0x8c02010c,
+0x10a20048, 0x51080, 0x8c460300, 0x24a20001,
+0x3045003f, 0x24020003, 0xac05022c, 0x61e02,
+0x10620005, 0x24020010, 0x1062001d, 0x30c20fff,
+0x10000039, 0x0, 0x8f4302a8, 0x8f440000,
+0x30c20fff, 0xaf420048, 0x24630001, 0xaf4302a8,
+0x10800007, 0x8f4202a8, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x34420200, 0xaf820060, 0x8f420000,
+0x1040001f, 0x0, 0x1000001b, 0x0,
+0xaf420058, 0x32c22000, 0x50400001, 0x36d68000,
+0x8f4202d4, 0x8f430000, 0x24420001, 0xaf4202d4,
+0x10600007, 0x8f4202d4, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x34420100, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x10000006, 0xaf80004c,
+0x10000004, 0xaf800048, 0xc002196, 0xc02021,
+0x402821, 0x8c02010c, 0x14a20002, 0x24020002,
+0xaf820064, 0x8f820064, 0x30420002, 0x14400004,
+0x0, 0x8c02010c, 0x14a2ffac, 0x0,
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008,
+0x0, 0x27bdffa0, 0xafb00040, 0x808021,
+0x101602, 0x2442ffff, 0x304300ff, 0x2c620013,
+0xafbf0058, 0xafbe0054, 0xafb50050, 0xafb3004c,
+0xafb20048, 0xafb10044, 0x104001f3, 0xafa50034,
+0x31080, 0x3c010001, 0x220821, 0x8c226288,
+0x400008, 0x0, 0x101302, 0x30440fff,
+0x24020001, 0x10820005, 0x24020002, 0x1082000c,
+0x2402fffe, 0x10000024, 0x3c050003, 0x8f430004,
+0x3c020001, 0x8c426f04, 0xaf440200, 0xaf440204,
+0x3c040001, 0x8c846e80, 0x10000009, 0x34630001,
+0x8f430004, 0xaf440200, 0xaf440204, 0x3c040001,
+0x8c846e80, 0x621824, 0x3c020001, 0x2442ca28,
+0x21100, 0x21182, 0xaf430004, 0x3c030800,
+0x431025, 0xac820038, 0x8f840054, 0x41442,
+0x41c82, 0x431021, 0x41cc2, 0x431023,
+0x41d02, 0x431021, 0x41d42, 0x431023,
+0x10000009, 0xaf420208, 0x3c040001, 0x24846250,
+0x34a51000, 0x2003021, 0x3821, 0xafa00010,
+0xc002b3b, 0xafa00014, 0x8f4202a0, 0x24420001,
+0xaf4202a0, 0x1000021f, 0x8f4202a0, 0x27b00028,
+0x2002021, 0x24050210, 0xc002bbf, 0x24060008,
+0xc002518, 0x2002021, 0x10000216, 0x0,
+0x8faa0034, 0x27a40028, 0xa1880, 0x25420001,
+0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034,
+0x21080, 0x8c430300, 0x25420001, 0x3042003f,
+0xafa20034, 0xac02022c, 0xafa50028, 0xc002518,
+0xafa3002c, 0x10000203, 0x0, 0x27b00028,
+0x2002021, 0x24050210, 0xc002bbf, 0x24060008,
+0xc002657, 0x2002021, 0x100001fa, 0x0,
+0x8faa0034, 0x27a40028, 0xa1880, 0x25420001,
+0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034,
+0x21080, 0x8c430300, 0x25420001, 0x3042003f,
+0xafa20034, 0xac02022c, 0xafa50028, 0xc002657,
+0xafa3002c, 0x100001e7, 0x0, 0x101302,
+0x30430fff, 0x24020001, 0x10620005, 0x24020002,
+0x1062001e, 0x3c020002, 0x10000033, 0x3c050003,
+0x3c030002, 0x2c31024, 0x54400037, 0x2c3b025,
+0x8f820228, 0x3c010001, 0x370821, 0xac2238d8,
+0x8f82022c, 0x3c010001, 0x370821, 0xac2238dc,
+0x8f820230, 0x3c010001, 0x370821, 0xac2238e0,
+0x8f820234, 0x3c010001, 0x370821, 0xac2238e4,
+0x2402ffff, 0xaf820228, 0xaf82022c, 0xaf820230,
+0xaf820234, 0x10000020, 0x2c3b025, 0x2c21024,
+0x10400012, 0x3c02fffd, 0x3c020001, 0x571021,
+0x8c4238d8, 0xaf820228, 0x3c020001, 0x571021,
+0x8c4238dc, 0xaf82022c, 0x3c020001, 0x571021,
+0x8c4238e0, 0xaf820230, 0x3c020001, 0x571021,
+0x8c4238e4, 0xaf820234, 0x3c02fffd, 0x3442ffff,
+0x10000009, 0x2c2b024, 0x3c040001, 0x2484625c,
+0x34a51100, 0x2003021, 0x3821, 0xafa00010,
+0xc002b3b, 0xafa00014, 0x8f4202cc, 0x24420001,
+0xaf4202cc, 0x1000019f, 0x8f4202cc, 0x101302,
+0x30450fff, 0x24020001, 0x10a20005, 0x24020002,
+0x10a2000d, 0x3c0408ff, 0x10000014, 0x3c050003,
+0x3c0208ff, 0x3442ffff, 0x8f830220, 0x3c040004,
+0x2c4b025, 0x621824, 0x34630008, 0xaf830220,
+0x10000012, 0xaf450298, 0x3484fff7, 0x3c03fffb,
+0x8f820220, 0x3463ffff, 0x2c3b024, 0x441024,
+0xaf820220, 0x10000009, 0xaf450298, 0x3c040001,
+0x24846268, 0x34a51200, 0x2003021, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202bc,
+0x24420001, 0xaf4202bc, 0x10000176, 0x8f4202bc,
+0x27840208, 0x24050200, 0xc002bbf, 0x24060008,
+0x27440224, 0x24050200, 0xc002bbf, 0x24060008,
+0x8f4202c4, 0x24420001, 0xaf4202c4, 0x10000169,
+0x8f4202c4, 0x101302, 0x30430fff, 0x24020001,
+0x10620011, 0x28620002, 0x50400005, 0x24020002,
+0x10600007, 0x0, 0x10000017, 0x0,
+0x1062000f, 0x0, 0x10000013, 0x0,
+0x8c060248, 0x2021, 0xc005104, 0x24050004,
+0x10000007, 0x0, 0x8c060248, 0x2021,
+0xc005104, 0x24050004, 0x10000010, 0x0,
+0x8c06024c, 0x2021, 0xc005104, 0x24050001,
+0x1000000a, 0x0, 0x3c040001, 0x24846274,
+0x3c050003, 0x34a51300, 0x2003021, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202c0,
+0x24420001, 0xaf4202c0, 0x1000013a, 0x8f4202c0,
+0xc002426, 0x0, 0x10000136, 0x0,
+0x24020001, 0xa34205c5, 0x24100100, 0x8f4401a8,
+0x8f4501ac, 0xafb00010, 0xafa00014, 0x8f420014,
+0xafa20018, 0x8f420108, 0x26e60028, 0x40f809,
+0x24070400, 0x1040fff5, 0x0, 0x10000125,
+0x0, 0x3c03ffff, 0x34637fff, 0x8f420368,
+0x8f440360, 0x2c3b024, 0x1821, 0xaf400058,
+0xaf40005c, 0xaf400060, 0xaf400064, 0x441023,
+0xaf420368, 0x3c020900, 0xaf400360, 0xafa20020,
+0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
+0xafaa003c, 0x27c30001, 0x8c020228, 0x609021,
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x2484620c, 0x3c050009, 0xafa00014, 0xafa20010,
+0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
+0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
+0x24070008, 0xa32821, 0xa3482b, 0x822021,
+0x100f809, 0x892021, 0x54400006, 0x24130001,
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
+0x0, 0x326200ff, 0x54400017, 0xaf520018,
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
+0x8f820120, 0x8faa003c, 0xafa20010, 0x8f820124,
+0x3c040001, 0x24846218, 0x3c050009, 0xafa20014,
+0x8d460000, 0x10000033, 0x34a50600, 0x8f420308,
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
+0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
+0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
+0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
+0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
+0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
+0x326200ff, 0x14400011, 0x0, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
+0x8faa003c, 0xafa20010, 0x8f820124, 0x3c040001,
+0x24846220, 0x3c050009, 0xafa20014, 0x8d460000,
+0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b0,
+0x24420001, 0xaf4202b0, 0x8f4202b0, 0x8f4202f8,
+0x24420001, 0xaf4202f8, 0x1000008a, 0x8f4202f8,
+0x8c02025c, 0x27440224, 0xaf4201f0, 0x8c020260,
+0x24050200, 0x24060008, 0xc002bbf, 0xaf4201f8,
+0x8f820220, 0x30420008, 0x14400002, 0x24020001,
+0x24020002, 0xaf420298, 0x8f4202ac, 0x24420001,
+0xaf4202ac, 0x10000077, 0x8f4202ac, 0x3c0200ff,
+0x3442ffff, 0x2021824, 0x32c20180, 0x14400006,
+0x3402fffb, 0x43102b, 0x14400003, 0x0,
+0x1000006c, 0xaf4300bc, 0x3c040001, 0x24846280,
+0x3c050003, 0x34a51500, 0x2003021, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020700,
+0x34421000, 0x101e02, 0x621825, 0xafa30020,
+0x8f510018, 0x240200ff, 0x12220002, 0x8021,
+0x26300001, 0x8c020228, 0x1602000e, 0x1130c0,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x248461f4, 0x3c050009,
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f,
+0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024,
+0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
+0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
+0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021,
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x248461fc, 0x3c050009,
+0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200,
+0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018,
+0x8f860120, 0x24020010, 0xafa20010, 0xafb00014,
+0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x14400010, 0x0, 0x8f420340, 0x24420001,
+0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24846204, 0x3c050009,
+0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b,
+0x2203821, 0x8f4202e0, 0x24420001, 0xaf4202e0,
+0x8f4202e0, 0x8f4202f0, 0x24420001, 0xaf4202f0,
+0x8f4202f0, 0x8fa20034, 0x8fbf0058, 0x8fbe0054,
+0x8fb50050, 0x8fb3004c, 0x8fb20048, 0x8fb10044,
+0x8fb00040, 0x3e00008, 0x27bd0060, 0x27bdfff8,
+0x2408ffff, 0x10a00014, 0x4821, 0x3c0aedb8,
+0x354a8320, 0x90870000, 0x24840001, 0x3021,
+0x1071026, 0x30420001, 0x10400002, 0x81842,
+0x6a1826, 0x604021, 0x24c60001, 0x2cc20008,
+0x1440fff7, 0x73842, 0x25290001, 0x125102b,
+0x1440fff0, 0x0, 0x1001021, 0x3e00008,
+0x27bd0008, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
+0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
+0xafb00030, 0x8f870220, 0xafa70024, 0x8f870200,
+0xafa7002c, 0x8f820220, 0x3c0308ff, 0x3463ffff,
+0x431024, 0x34420004, 0xaf820220, 0x8f820200,
+0x3c03c0ff, 0x3463ffff, 0x431024, 0x34420004,
+0xaf820200, 0x8f530358, 0x8f55035c, 0x8f5e0360,
+0x8f470364, 0xafa70014, 0x8f470368, 0xafa7001c,
+0x8f4202d0, 0x274401c0, 0x24420001, 0xaf4202d0,
+0x8f5002d0, 0x8f510204, 0x8f520200, 0xc002ba8,
+0x24050400, 0xaf530358, 0xaf55035c, 0xaf5e0360,
+0x8fa70014, 0xaf470364, 0x8fa7001c, 0xaf470368,
+0xaf5002d0, 0xaf510204, 0xaf520200, 0x8c02025c,
+0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200,
+0x24060008, 0xaf4201f8, 0x24020006, 0xc002bbf,
+0xaf4201f4, 0x3c023b9a, 0x3442ca00, 0xaf4201fc,
+0x240203e8, 0x24040002, 0x24030001, 0xaf420294,
+0xaf440290, 0xaf43029c, 0x8f820220, 0x30420008,
+0x10400004, 0x0, 0xaf430298, 0x10000003,
+0x3021, 0xaf440298, 0x3021, 0x3c030001,
+0x661821, 0x90636d00, 0x3461021, 0x24c60001,
+0xa043022c, 0x2cc2000f, 0x1440fff8, 0x3461821,
+0x24c60001, 0x8f820040, 0x24040080, 0x24050080,
+0x21702, 0x24420030, 0xa062022c, 0x3461021,
+0xc002ba8, 0xa040022c, 0x8fa70024, 0x30e20004,
+0x14400006, 0x0, 0x8f820220, 0x3c0308ff,
+0x3463fffb, 0x431024, 0xaf820220, 0x8fa7002c,
+0x30e20004, 0x14400006, 0x0, 0x8f820200,
+0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200,
+0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
+0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
+0x27bd0050, 0x0, 0x0, 0xaf400104,
+0x24040001, 0x410c0, 0x2e21821, 0x24820001,
+0x3c010001, 0x230821, 0xa42234d0, 0x402021,
+0x2c820080, 0x1440fff8, 0x410c0, 0x24020001,
+0x3c010001, 0x370821, 0xa42038d0, 0xaf420100,
+0xaf800228, 0xaf80022c, 0xaf800230, 0xaf800234,
+0x3e00008, 0x0, 0x27bdffe8, 0xafbf0014,
+0xafb00010, 0x8f420104, 0x28420005, 0x10400026,
+0x808021, 0x3c020001, 0x8f430104, 0x344230d0,
+0x2e22021, 0x318c0, 0x621821, 0x2e31821,
+0x83102b, 0x10400015, 0x1021, 0x96070000,
+0x24840006, 0x24660006, 0x9482fffc, 0x14470009,
+0x2821, 0x9483fffe, 0x96020002, 0x14620006,
+0xa01021, 0x94820000, 0x96030004, 0x431026,
+0x2c450001, 0xa01021, 0x14400009, 0x24840008,
+0x86102b, 0x1440fff0, 0x1021, 0x304200ff,
+0x14400030, 0x24020001, 0x1000002e, 0x1021,
+0x1000fffa, 0x24020001, 0x2002021, 0xc00240c,
+0x24050006, 0x3042007f, 0x218c0, 0x2e31021,
+0x3c010001, 0x220821, 0x942230d0, 0x1040fff2,
+0x2e31021, 0x3c060001, 0xc23021, 0x94c630d0,
+0x10c0ffed, 0x3c080001, 0x350834d2, 0x96070000,
+0x610c0, 0x572021, 0x882021, 0x94820000,
+0x14470009, 0x2821, 0x94830002, 0x96020002,
+0x14620006, 0xa01021, 0x94820004, 0x96030004,
+0x431026, 0x2c450001, 0xa01021, 0x14400007,
+0x610c0, 0x2e21021, 0x3c060001, 0xc23021,
+0x94c634d0, 0x14c0ffeb, 0x610c0, 0x10c0ffd2,
+0x24020001, 0x8fbf0014, 0x8fb00010, 0x3e00008,
+0x27bd0018, 0x3e00008, 0x0, 0x27bdffb0,
+0x801021, 0xafb00030, 0x24500002, 0x2002021,
+0x24050006, 0xafb10034, 0x408821, 0xafbf0048,
+0xafbe0044, 0xafb50040, 0xafb3003c, 0xc00240c,
+0xafb20038, 0x3047007f, 0x710c0, 0x2e21021,
+0x3c050001, 0xa22821, 0x94a530d0, 0x50a0001c,
+0xa03021, 0x3c090001, 0x352934d2, 0x96280002,
+0x510c0, 0x572021, 0x892021, 0x94820000,
+0x14480009, 0x3021, 0x94830002, 0x96020002,
+0x14620006, 0xc01021, 0x94820004, 0x96030004,
+0x431026, 0x2c460001, 0xc01021, 0x14400007,
+0x510c0, 0x2e21021, 0x3c050001, 0xa22821,
+0x94a534d0, 0x14a0ffeb, 0x510c0, 0xa03021,
+0x10c00014, 0x610c0, 0x571821, 0x3c010001,
+0x230821, 0x8c2334d0, 0x571021, 0xafa30010,
+0x3c010001, 0x220821, 0x8c2234d4, 0x3c040001,
+0x24846394, 0xafa20014, 0x8e260000, 0x8e270004,
+0x3c050004, 0xc002b3b, 0x34a50400, 0x10000063,
+0x3c020800, 0x8f450100, 0x10a00006, 0x510c0,
+0x2e21021, 0x3c010001, 0x220821, 0x942234d0,
+0xaf420100, 0xa03021, 0x14c00011, 0x628c0,
+0x710c0, 0x2e21021, 0xafa70010, 0x3c010001,
+0x220821, 0x942230d0, 0x3c040001, 0x248463a0,
+0xafa20014, 0x8e260000, 0x8e270004, 0x3c050004,
+0xc002b3b, 0x34a50500, 0x10000048, 0x3c020800,
+0xb71821, 0x3c020001, 0x96040000, 0x344234d2,
+0x621821, 0xa4640000, 0x8e020002, 0x720c0,
+0xac620002, 0x2e41021, 0x3c030001, 0x621821,
+0x946330d0, 0x2e51021, 0x3c010001, 0x220821,
+0xa42334d0, 0x2e41021, 0x3c010001, 0x220821,
+0xa42630d0, 0x8f420104, 0x24420001, 0x28420080,
+0x1040000f, 0x3c020002, 0x8f420104, 0x3c040001,
+0x348430d2, 0x96030000, 0x210c0, 0x571021,
+0x441021, 0xa4430000, 0x8e030002, 0xac430002,
+0x8f420104, 0x24420001, 0xaf420104, 0x3c020002,
+0x2c21024, 0x10400011, 0x72142, 0x3c030001,
+0x346338d8, 0x24020003, 0x441023, 0x21080,
+0x572021, 0x832021, 0x571021, 0x431021,
+0x30e5001f, 0x8c430000, 0x24020001, 0xa21004,
+0x621825, 0x1000000c, 0xac830000, 0x24020003,
+0x441023, 0x21080, 0x5c2821, 0x5c1021,
+0x30e4001f, 0x8c430228, 0x24020001, 0x821004,
+0x621825, 0xaca30228, 0x3c020800, 0x34421000,
+0x1821, 0xafa20020, 0x8f5e0018, 0x27aa0020,
+0x240200ff, 0x13c20002, 0xafaa002c, 0x27c30001,
+0x8c020228, 0x609021, 0x1642000e, 0x1e38c0,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x2484635c, 0x3c050009,
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b,
+0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024,
+0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b,
+0x9821, 0xe08821, 0x263504c0, 0x8f440178,
+0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010,
+0xafb20014, 0x8f48000c, 0x1021, 0x2f53021,
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x54400006, 0x24130001, 0x8f820054, 0x2021023,
+0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff,
+0x54400017, 0xaf520018, 0x8f420378, 0x24420001,
+0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
+0xafa20010, 0x8f820124, 0x3c040001, 0x24846368,
+0x3c050009, 0xafa20014, 0x8d460000, 0x10000033,
+0x34a50600, 0x8f420308, 0x24130001, 0x24420001,
+0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x10400014, 0x9821, 0x24110010,
+0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120,
+0xafb10010, 0xafb20014, 0xafa20018, 0x8f42010c,
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe5,
+0x0, 0x8f820054, 0x2021023, 0x2c4203e9,
+0x1440ffef, 0x0, 0x326200ff, 0x14400011,
+0x0, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24846370, 0x3c050009,
+0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b,
+0x3c03821, 0x8f4202b4, 0x24420001, 0xaf4202b4,
+0x8f4202b4, 0x8f4202f4, 0x24420001, 0xaf4202f4,
+0x8f4202f4, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
+0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
+0x3e00008, 0x27bd0050, 0x27bdffa0, 0x801021,
+0xafb00040, 0x24500002, 0x2002021, 0x24050006,
+0xafb10044, 0x408821, 0xafbf0058, 0xafbe0054,
+0xafb50050, 0xafb3004c, 0xc00240c, 0xafb20048,
+0x3048007f, 0x810c0, 0x2e21021, 0x3c060001,
+0xc23021, 0x94c630d0, 0x10c0001c, 0x3821,
+0x3c0a0001, 0x354a34d2, 0x96290002, 0x610c0,
+0x572021, 0x8a2021, 0x94820000, 0x14490009,
+0x2821, 0x94830002, 0x96020002, 0x14620006,
+0xa01021, 0x94820004, 0x96030004, 0x431026,
+0x2c450001, 0xa01021, 0x14400008, 0x610c0,
+0xc03821, 0x2e21021, 0x3c060001, 0xc23021,
+0x94c634d0, 0x14c0ffea, 0x610c0, 0x14c00011,
+0xafa70028, 0x810c0, 0x2e21021, 0xafa80010,
+0x3c010001, 0x220821, 0x942230d0, 0x3c040001,
+0x248463ac, 0xafa20014, 0x8e260000, 0x8e270004,
+0x3c050004, 0xc002b3b, 0x34a50900, 0x10000075,
+0x3c020800, 0x10e0000c, 0x610c0, 0x2e21021,
+0x3c030001, 0x621821, 0x946334d0, 0x710c0,
+0x2e21021, 0x3c010001, 0x220821, 0xa42334d0,
+0x1000000b, 0x3c040001, 0x2e21021, 0x3c030001,
+0x621821, 0x946334d0, 0x810c0, 0x2e21021,
+0x3c010001, 0x220821, 0xa42330d0, 0x3c040001,
+0x348430d0, 0x8f430100, 0x610c0, 0x2e21021,
+0x3c010001, 0x220821, 0xa42334d0, 0x8f420104,
+0x2e43821, 0x2821, 0x18400029, 0xaf460100,
+0x24e60006, 0x94c3fffc, 0x96020000, 0x14620009,
+0x2021, 0x94c3fffe, 0x96020002, 0x14620006,
+0x801021, 0x94c20000, 0x96030004, 0x431026,
+0x2c440001, 0x801021, 0x50400014, 0x24a50001,
+0x8f420104, 0x2442ffff, 0xa2102a, 0x1040000b,
+0x24e40004, 0x94820006, 0x8c830008, 0xa482fffe,
+0xac830000, 0x8f420104, 0x24a50001, 0x2442ffff,
+0xa2102a, 0x1440fff7, 0x24840008, 0x8f420104,
+0x2442ffff, 0x10000006, 0xaf420104, 0x8f420104,
+0x24c60008, 0xa2102a, 0x1440ffda, 0x24e70008,
+0x810c0, 0x2e21021, 0x3c010001, 0x220821,
+0x942230d0, 0x14400023, 0x3c020800, 0x3c020002,
+0x2c21024, 0x10400012, 0x82142, 0x3c030001,
+0x346338d8, 0x24020003, 0x441023, 0x21080,
+0x572021, 0x832021, 0x571021, 0x431021,
+0x3105001f, 0x24030001, 0x8c420000, 0xa31804,
+0x31827, 0x431024, 0x1000000d, 0xac820000,
+0x24020003, 0x441023, 0x21080, 0x5c2821,
+0x5c1021, 0x3104001f, 0x24030001, 0x8c420228,
+0x831804, 0x31827, 0x431024, 0xaca20228,
+0x3c020800, 0x34422000, 0x1821, 0xafa20020,
+0x8f5e0018, 0x27ab0020, 0x240200ff, 0x13c20002,
+0xafab0034, 0x27c30001, 0x8c020228, 0x609021,
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x2484635c, 0x3c050009, 0xafa00014, 0xafa20010,
+0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
+0x240b0004, 0xafab0010, 0xafb20014, 0x8f48000c,
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
+0x24070008, 0xa32821, 0xa3482b, 0x822021,
+0x100f809, 0x892021, 0x54400006, 0x24130001,
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
+0x0, 0x326200ff, 0x54400017, 0xaf520018,
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
+0x8f820120, 0x8fab0034, 0xafa20010, 0x8f820124,
+0x3c040001, 0x24846368, 0x3c050009, 0xafa20014,
+0x8d660000, 0x10000033, 0x34a50600, 0x8f420308,
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
+0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
+0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
+0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
+0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
+0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
+0x326200ff, 0x14400011, 0x0, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
+0x8fab0034, 0xafa20010, 0x8f820124, 0x3c040001,
+0x24846370, 0x3c050009, 0xafa20014, 0x8d660000,
+0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b8,
+0x24420001, 0xaf4202b8, 0x8f4202b8, 0x8f4202f4,
+0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8fbf0058,
+0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048,
+0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060,
+0x0, 0x0, 0x0, 0x27bdffe0,
+0x27644000, 0xafbf0018, 0xc002ba8, 0x24051000,
+0x3c030001, 0x34632cc0, 0x3c040001, 0x34842ec8,
+0x24020020, 0xaf82011c, 0x2e31021, 0xaf800100,
+0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114,
+0xaf800118, 0xaf800120, 0xaf800124, 0xaf800128,
+0xaf800130, 0xaf800134, 0xaf800138, 0xaf4200ec,
+0x2e31021, 0xaf4200f0, 0x2e41021, 0xaf4200f4,
+0x2e41021, 0xaf4200f8, 0x3c020001, 0x571021,
+0x904240f4, 0x1440001c, 0x3c050001, 0x8f82011c,
+0x3c040001, 0x24846470, 0x3c050001, 0x34420001,
+0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c,
+0x34a50100, 0xc002b3b, 0x3821, 0x8c020218,
+0x30420040, 0x10400014, 0x0, 0x8f82011c,
+0x3c040001, 0x2484647c, 0x3c050001, 0x34420004,
+0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c,
+0x10000007, 0x34a50200, 0x3c040001, 0x24846484,
+0xafa00010, 0xafa00014, 0x8f86011c, 0x34a50300,
+0xc002b3b, 0x3821, 0x8fbf0018, 0x3e00008,
+0x27bd0020, 0x8fa90010, 0x8f83012c, 0x8faa0014,
+0x8fab0018, 0x1060000a, 0x27624fe0, 0x14620002,
+0x24680020, 0x27684800, 0x8f820128, 0x11020004,
+0x0, 0x8f820124, 0x15020007, 0x0,
+0x8f430334, 0x1021, 0x24630001, 0xaf430334,
+0x10000039, 0x8f430334, 0xac640000, 0xac650004,
+0xac660008, 0xa467000e, 0xac690018, 0xac6a001c,
+0xac6b0010, 0xac620014, 0xaf880120, 0x8f4200fc,
+0x8f4400f4, 0x2442ffff, 0xaf4200fc, 0x8c820000,
+0x10490005, 0x3042ff8f, 0x10400019, 0x3122ff8f,
+0x10400018, 0x3c020001, 0x8c830004, 0x2c620010,
+0x10400013, 0x3c020001, 0x24630001, 0xac830004,
+0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004,
+0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021,
+0x14440015, 0x24020001, 0x8f820128, 0x24420020,
+0xaf820128, 0x8f820128, 0x1000000f, 0x24020001,
+0x3c020001, 0x344230c8, 0x2e21021, 0x54820004,
+0x24820008, 0x3c020001, 0x34422ec8, 0x2e21021,
+0x402021, 0x24020001, 0xaf4400f4, 0xac890000,
+0xac820004, 0x24020001, 0x3e00008, 0x0,
+0x3e00008, 0x0, 0x8fa90010, 0x8f83010c,
+0x8faa0014, 0x8fab0018, 0x1060000a, 0x276247e0,
+0x14620002, 0x24680020, 0x27684000, 0x8f820108,
+0x11020004, 0x0, 0x8f820104, 0x15020007,
+0x0, 0x8f430338, 0x1021, 0x24630001,
+0xaf430338, 0x10000035, 0x8f430338, 0xac640000,
+0xac650004, 0xac660008, 0xa467000e, 0xac690018,
+0xac6a001c, 0xac6b0010, 0xac620014, 0xaf880100,
+0x8f4400ec, 0x8c820000, 0x30420006, 0x10400019,
+0x31220006, 0x10400018, 0x3c020001, 0x8c830004,
+0x2c620010, 0x10400013, 0x3c020001, 0x24630001,
+0xac830004, 0x8f4300f0, 0x34422ec0, 0x2e21021,
+0x54620004, 0x24620008, 0x3c020001, 0x34422cc0,
+0x2e21021, 0x14440015, 0x24020001, 0x8f820108,
+0x24420020, 0xaf820108, 0x8f820108, 0x1000000f,
+0x24020001, 0x3c020001, 0x34422ec0, 0x2e21021,
+0x54820004, 0x24820008, 0x3c020001, 0x34422cc0,
+0x2e21021, 0x402021, 0x24020001, 0xaf4400ec,
+0xac890000, 0xac820004, 0x24020001, 0x3e00008,
+0x0, 0x3e00008, 0x0, 0x27bdffd8,
+0x3c040001, 0x2484648c, 0x3c050001, 0xafbf0024,
+0xafb20020, 0xafb1001c, 0xafb00018, 0x8f900104,
+0x8f9100b0, 0x8f92011c, 0x34a52500, 0x8f820100,
+0x2403021, 0x2203821, 0xafa20010, 0xc002b3b,
+0xafb00014, 0x8e020008, 0xafa20010, 0x8e02000c,
+0x3c040001, 0x24846498, 0xafa20014, 0x8e060000,
+0x8e070004, 0x3c050001, 0xc002b3b, 0x34a52510,
+0x8e020018, 0xafa20010, 0x8e02001c, 0x3c040001,
+0x248464a4, 0xafa20014, 0x8e060010, 0x8e070014,
+0x3c050001, 0xc002b3b, 0x34a52520, 0x3c027f00,
+0x2221024, 0x3c030800, 0x54430016, 0x3c030200,
+0x8f82009c, 0x3042ffff, 0x14400012, 0x3c030200,
+0x3c040001, 0x248464b0, 0x3c050002, 0x34a5f030,
+0x3021, 0x3821, 0x36420002, 0xaf82011c,
+0x36220001, 0xaf8200b0, 0xaf900104, 0xaf92011c,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x10000024,
+0x0, 0x2c31024, 0x1040000d, 0x2231024,
+0x1040000b, 0x36420002, 0xaf82011c, 0x36220001,
+0xaf8200b0, 0xaf900104, 0xaf92011c, 0x8f420330,
+0x24420001, 0xaf420330, 0x10000015, 0x8f420330,
+0x3c040001, 0x248464b8, 0x240202a9, 0xafa20010,
+0xafa00014, 0x8f860144, 0x3c070001, 0x24e764c0,
+0xc002b3b, 0x3405dead, 0x8f82011c, 0x34420002,
+0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220,
+0x8f820140, 0x3c030001, 0x431025, 0xaf820140,
+0x8fbf0024, 0x8fb20020, 0x8fb1001c, 0x8fb00018,
+0x3e00008, 0x27bd0028, 0x27bdffd8, 0x3c040001,
+0x248464e8, 0x3c050001, 0xafbf0024, 0xafb20020,
+0xafb1001c, 0xafb00018, 0x8f900124, 0x8f9100a0,
+0x8f92011c, 0x34a52600, 0x8f820120, 0x2403021,
+0x2203821, 0xafa20010, 0xc002b3b, 0xafb00014,
+0x8e020008, 0xafa20010, 0x8e02000c, 0x3c040001,
+0x248464f4, 0xafa20014, 0x8e060000, 0x8e070004,
+0x3c050001, 0xc002b3b, 0x34a52610, 0x8e020018,
+0xafa20010, 0x8e02001c, 0x3c040001, 0x24846500,
+0xafa20014, 0x8e060010, 0x8e070014, 0x3c050001,
+0xc002b3b, 0x34a52620, 0x3c027f00, 0x2221024,
+0x3c030800, 0x54430016, 0x3c030200, 0x8f8200ac,
+0x3042ffff, 0x14400012, 0x3c030200, 0x3c040001,
+0x2484650c, 0x3c050001, 0x34a5f030, 0x3021,
+0x3821, 0x36420002, 0xaf82011c, 0x36220001,
+0xaf8200a0, 0xaf900124, 0xaf92011c, 0xafa00010,
+0xc002b3b, 0xafa00014, 0x10000024, 0x0,
+0x2c31024, 0x1040000d, 0x2231024, 0x1040000b,
+0x36420002, 0xaf82011c, 0x36220001, 0xaf8200a0,
+0xaf900124, 0xaf92011c, 0x8f42032c, 0x24420001,
+0xaf42032c, 0x10000015, 0x8f42032c, 0x3c040001,
+0x248464b8, 0x240202e2, 0xafa20010, 0xafa00014,
+0x8f860144, 0x3c070001, 0x24e764c0, 0xc002b3b,
+0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c,
+0x8f820220, 0x34420004, 0xaf820220, 0x8f820140,
+0x3c030001, 0x431025, 0xaf820140, 0x8fbf0024,
+0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
+0x27bd0028, 0x6021, 0x5021, 0x3021,
+0x2821, 0x6821, 0x4821, 0x7821,
+0x7021, 0x8f880124, 0x8f870104, 0x1580002e,
+0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120,
+0x10460029, 0x0, 0x3c040001, 0x8c846ee4,
+0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004,
+0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e,
+0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014,
+0x10000012, 0x24c60020, 0x10400017, 0x0,
+0x3c040001, 0x8c846ee4, 0x8d020000, 0x8d030004,
+0xac820000, 0xac830004, 0x8d020008, 0xac820008,
+0x9502000e, 0xa482000e, 0x8d020010, 0x25060020,
+0xac820010, 0x8d020014, 0x240c0001, 0xc01821,
+0xac820014, 0x27624fe0, 0x43102b, 0x54400001,
+0x27634800, 0x603021, 0x1540002f, 0x31620100,
+0x11200014, 0x31628000, 0x8f820100, 0x1045002a,
+0x31620100, 0x3c040001, 0x8c846ee0, 0x8ca20000,
+0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008,
+0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010,
+0x240a0001, 0xac820010, 0x8ca20014, 0x10000012,
+0x24a50020, 0x10400018, 0x31620100, 0x3c040001,
+0x8c846ee0, 0x8ce20000, 0x8ce30004, 0xac820000,
+0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e,
+0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010,
+0x8ce20014, 0x240a0001, 0xa01821, 0xac820014,
+0x276247e0, 0x43102b, 0x54400001, 0x27634000,
+0x602821, 0x31620100, 0x5440001d, 0x31621000,
+0x11a00009, 0x31a20800, 0x10400004, 0x25020020,
+0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124,
+0x8f880124, 0x6821, 0x11800011, 0x31621000,
+0x3c040001, 0x8c846ee4, 0x8c820000, 0x8c830004,
+0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4,
+0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021,
+0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000,
+0x1440ff82, 0x0, 0x1120000f, 0x31220800,
+0x10400004, 0x3c020002, 0x8f8200b8, 0xa5c20000,
+0x3c020002, 0x1221024, 0x10400004, 0x24e20020,
+0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104,
+0x8f870104, 0x4821, 0x1140ff70, 0x0,
+0x3c040001, 0x8c846ee0, 0x8c820000, 0x8c830004,
+0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4,
+0x9482000e, 0xaf82009c, 0x8c820010, 0x5021,
+0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014,
+0x3e00008, 0x0, 0x6021, 0x5821,
+0x3021, 0x2821, 0x6821, 0x5021,
+0x7821, 0x7021, 0x8f880124, 0x8f870104,
+0x3c180100, 0x1580002e, 0x8f89011c, 0x11a00014,
+0x31220800, 0x8f820120, 0x10460029, 0x0,
+0x3c040001, 0x8c846ee4, 0x8cc20000, 0x8cc30004,
+0xac820000, 0xac830004, 0x8cc20008, 0xac820008,
+0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001,
+0xac820010, 0x8cc20014, 0x10000012, 0x24c60020,
+0x10400017, 0x0, 0x3c040001, 0x8c846ee4,
+0x8d020000, 0x8d030004, 0xac820000, 0xac830004,
+0x8d020008, 0xac820008, 0x9502000e, 0xa482000e,
+0x8d020010, 0x25060020, 0xac820010, 0x8d020014,
+0x240c0001, 0xc01821, 0xac820014, 0x27624fe0,
+0x43102b, 0x54400001, 0x27634800, 0x603021,
+0x1560002f, 0x31220100, 0x11400014, 0x31228000,
+0x8f820100, 0x1045002a, 0x31220100, 0x3c040001,
+0x8c846ee0, 0x8ca20000, 0x8ca30004, 0xac820000,
+0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e,
+0xa482000e, 0x8ca20010, 0x240b0001, 0xac820010,
+0x8ca20014, 0x10000012, 0x24a50020, 0x10400018,
+0x31220100, 0x3c040001, 0x8c846ee0, 0x8ce20000,
+0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008,
+0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010,
+0x24e50020, 0xac820010, 0x8ce20014, 0x240b0001,
+0xa01821, 0xac820014, 0x276247e0, 0x43102b,
+0x54400001, 0x27634000, 0x602821, 0x31220100,
+0x5440001d, 0x31221000, 0x11a00009, 0x31a20800,
+0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000,
+0x25020020, 0xaf820124, 0x8f880124, 0x6821,
+0x11800011, 0x31221000, 0x3c040001, 0x8c846ee4,
+0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084,
+0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac,
+0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010,
+0x8c8f0014, 0x31221000, 0x14400022, 0x0,
+0x1140000f, 0x31420800, 0x10400004, 0x3c020002,
+0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1421024,
+0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4,
+0x24e20020, 0xaf820104, 0x8f870104, 0x5021,
+0x11600010, 0x0, 0x3c040001, 0x8c846ee0,
+0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094,
+0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c,
+0x8c820010, 0x5821, 0xaf8200b0, 0x8c8a0010,
+0x8c8e0014, 0x8f820070, 0x3c031000, 0x431024,
+0x1040ff5c, 0x0, 0x8f820054, 0x24420005,
+0xaf820078, 0x8c040234, 0x10800016, 0x1821,
+0x3c020001, 0x571021, 0x8c4240e8, 0x24420005,
+0x3c010001, 0x370821, 0xac2240e8, 0x3c020001,
+0x571021, 0x8c4240e8, 0x44102b, 0x14400009,
+0x24020001, 0x3c030080, 0x3c010001, 0x370821,
+0xac2040e8, 0x3c010001, 0x370821, 0x1000000c,
+0xa02240f0, 0x3c020001, 0x571021, 0x904240f0,
+0x14400006, 0x3c020080, 0x3c020001, 0x571021,
+0x904240f1, 0x10400002, 0x3c020080, 0x621825,
+0x8c040230, 0x10800013, 0x0, 0x3c020001,
+0x571021, 0x8c4240ec, 0x24420005, 0x3c010001,
+0x370821, 0xac2240ec, 0x3c020001, 0x571021,
+0x8c4240ec, 0x44102b, 0x14400006, 0x0,
+0x3c010001, 0x370821, 0xac2040ec, 0x10000006,
+0x781825, 0x3c020001, 0x571021, 0x904240f2,
+0x54400001, 0x781825, 0x1060ff1a, 0x0,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x431025, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x1000ff05,
+0xaf80004c, 0x1000ff03, 0xaf800048, 0x3e00008,
+0x0, 0x0, 0x0, 0x3c020001,
+0x8c426d28, 0x27bdffe8, 0xafbf0014, 0x14400012,
+0xafb00010, 0x3c100001, 0x26106f90, 0x2002021,
+0xc002ba8, 0x24052000, 0x26021fe0, 0x3c010001,
+0xac226eec, 0x3c010001, 0xac226ee8, 0xac020250,
+0x24022000, 0xac100254, 0xac020258, 0x24020001,
+0x3c010001, 0xac226d28, 0x8fbf0014, 0x8fb00010,
+0x3e00008, 0x27bd0018, 0x3c090001, 0x8d296eec,
+0x8c820000, 0x8fa30010, 0x8fa80014, 0xad220000,
+0x8c820004, 0xad250008, 0xad220004, 0x8f820054,
+0xad260010, 0xad270014, 0xad230018, 0xad28001c,
+0xad22000c, 0x2529ffe0, 0x3c020001, 0x24426f90,
+0x122102b, 0x10400003, 0x0, 0x3c090001,
+0x8d296ee8, 0x3c020001, 0x8c426d10, 0xad220000,
+0x3c020001, 0x8c426d10, 0x3c010001, 0xac296eec,
+0xad220004, 0xac090250, 0x3e00008, 0x0,
+0x27bdffd0, 0xafb00010, 0x3c100001, 0x8e106eec,
+0x3c020001, 0x8c426d10, 0xafb10014, 0x808821,
+0xafbe0024, 0x8fbe0040, 0x8fa40048, 0xafb20018,
+0xa09021, 0xafbf0028, 0xafb50020, 0xafb3001c,
+0xae020000, 0x3c020001, 0x8c426d10, 0xc09821,
+0xe0a821, 0x10800006, 0xae020004, 0x26050008,
+0xc002bb3, 0x24060018, 0x10000005, 0x2610ffe0,
+0x26040008, 0xc002ba8, 0x24050018, 0x2610ffe0,
+0x3c030001, 0x24636f90, 0x203102b, 0x10400003,
+0x0, 0x3c100001, 0x8e106ee8, 0x8e220000,
+0xae020000, 0x8e220004, 0xae120008, 0xae020004,
+0x8f820054, 0xae130010, 0xae150014, 0xae1e0018,
+0x8fa80044, 0xae08001c, 0xae02000c, 0x2610ffe0,
+0x203102b, 0x10400003, 0x0, 0x3c100001,
+0x8e106ee8, 0x3c020001, 0x8c426d10, 0xae020000,
+0x3c020001, 0x8c426d10, 0x3c010001, 0xac306eec,
+0xae020004, 0xac100250, 0x8fbf0028, 0x8fbe0024,
+0x8fb50020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0030, 0x851821,
+0x83102b, 0x10400006, 0x0, 0xac800000,
+0x24840004, 0x83102b, 0x5440fffd, 0xac800000,
+0x3e00008, 0x0, 0xa61821, 0xa3102b,
+0x10400007, 0x0, 0x8c820000, 0xaca20000,
+0x24a50004, 0xa3102b, 0x1440fffb, 0x24840004,
+0x3e00008, 0x0, 0x861821, 0x83102b,
+0x10400007, 0x0, 0x8ca20000, 0xac820000,
+0x24840004, 0x83102b, 0x1440fffb, 0x24a50004,
+0x3e00008, 0x0, 0x63080, 0x861821,
+0x83102b, 0x10400006, 0x0, 0xac850000,
+0x24840004, 0x83102b, 0x5440fffd, 0xac850000,
+0x3e00008, 0x0, 0x0, 0x26e50028,
+0xa03021, 0x274301c0, 0x8f4d0358, 0x8f47035c,
+0x8f480360, 0x8f490364, 0x8f4a0368, 0x8f4b0204,
+0x8f4c0200, 0x24640400, 0x64102b, 0x10400008,
+0x3c0208ff, 0x8cc20000, 0xac620000, 0x24630004,
+0x64102b, 0x1440fffb, 0x24c60004, 0x3c0208ff,
+0x3442ffff, 0x3c03c0ff, 0xaf4d0358, 0xaf47035c,
+0xaf480360, 0xaf490364, 0xaf4a0368, 0xaf4b0204,
+0xaf4c0200, 0x8f840220, 0x3463ffff, 0x8f860200,
+0x821024, 0x34420004, 0xc31824, 0x34630004,
+0xaf820220, 0xaf830200, 0x8ca20214, 0xac020084,
+0x8ca20218, 0xac020088, 0x8ca2021c, 0xac02008c,
+0x8ca20220, 0xac020090, 0x8ca20224, 0xac020094,
+0x8ca20228, 0xac020098, 0x8ca2022c, 0xac02009c,
+0x8ca20230, 0xac0200a0, 0x8ca20234, 0xac0200a4,
+0x8ca20238, 0xac0200a8, 0x8ca2023c, 0xac0200ac,
+0x8ca20240, 0xac0200b0, 0x8ca20244, 0xac0200b4,
+0x8ca20248, 0xac0200b8, 0x8ca2024c, 0xac0200bc,
+0x8ca2001c, 0xac020080, 0x8ca20018, 0xac0200c0,
+0x8ca20020, 0xac0200cc, 0x8ca20024, 0xac0200d0,
+0x8ca201d0, 0xac0200e0, 0x8ca201d4, 0xac0200e4,
+0x8ca201d8, 0xac0200e8, 0x8ca201dc, 0xac0200ec,
+0x8ca201e0, 0xac0200f0, 0x8ca20098, 0x8ca3009c,
+0xac0300fc, 0x8ca200a8, 0x8ca300ac, 0xac0300f4,
+0x8ca200a0, 0x8ca300a4, 0x30840004, 0xac0300f8,
+0x14800007, 0x30c20004, 0x8f820220, 0x3c0308ff,
+0x3463fffb, 0x431024, 0xaf820220, 0x30c20004,
+0x14400006, 0x0, 0x8f820200, 0x3c03c0ff,
+0x3463fffb, 0x431024, 0xaf820200, 0x8f4202dc,
+0xa34005c5, 0x24420001, 0xaf4202dc, 0x8f4202dc,
+0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
+0xafb00020, 0x8f430024, 0x8f420020, 0x10620038,
+0x0, 0x8f430020, 0x8f420024, 0x622023,
+0x4810003, 0x0, 0x8f420040, 0x822021,
+0x8f430030, 0x8f420024, 0x43102b, 0x14400005,
+0x0, 0x8f430040, 0x8f420024, 0x10000005,
+0x621023, 0x8f420030, 0x8f430024, 0x431023,
+0x2442ffff, 0x406021, 0x8c102a, 0x54400001,
+0x806021, 0x8f4a0024, 0x8f490040, 0x8f480024,
+0x8f440180, 0x8f450184, 0x8f460024, 0x8f4b001c,
+0x24070001, 0xafa70010, 0x84100, 0x1001821,
+0x14c5021, 0x2529ffff, 0x1498024, 0xafb00014,
+0x8f470014, 0x1021, 0x63100, 0xafa70018,
+0xa32821, 0xa3382b, 0x822021, 0x872021,
+0x8f420108, 0x1663021, 0x40f809, 0xc3900,
+0x54400001, 0xaf500024, 0x8f430024, 0x8f420020,
+0x14620018, 0x0, 0x8f420000, 0x10400007,
+0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
+0x0, 0x10000005, 0x0, 0xaf800048,
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
+0x2403ffef, 0x431024, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x10000002, 0xaf80004c,
+0xaf800048, 0x8fbf0024, 0x8fb00020, 0x3e00008,
+0x27bd0028, 0x3e00008, 0x0, 0x27bdffc0,
+0x32c20020, 0xafbf0038, 0xafb30034, 0xafb20030,
+0xafb1002c, 0x10400004, 0xafb00028, 0x8f530028,
+0x10000002, 0x0, 0x8f530020, 0x8f420030,
+0x105300eb, 0x21100, 0x8f43001c, 0x628021,
+0x8e040000, 0x8e050004, 0x96120008, 0x8f420090,
+0x9611000a, 0x3246ffff, 0x46102a, 0x10400017,
+0x0, 0x8f8200d8, 0x8f430098, 0x431023,
+0x2442dcbe, 0xaf420090, 0x8f420090, 0x2842dcbf,
+0x10400005, 0x0, 0x8f420090, 0x8f430144,
+0x431021, 0xaf420090, 0x8f420090, 0x46102a,
+0x10400006, 0x0, 0x8f420348, 0x24420001,
+0xaf420348, 0x100000e1, 0x8f420348, 0x8f8200fc,
+0x14400006, 0x0, 0x8f420344, 0x24420001,
+0xaf420344, 0x100000d9, 0x8f420344, 0x934205c2,
+0x1040000b, 0x32c20008, 0x10400008, 0x32220200,
+0x10400006, 0x3c034000, 0x9602000e, 0xaf4300ac,
+0x21400, 0x10000002, 0xaf4200b0, 0xaf4000ac,
+0x32220004, 0x1040007f, 0x32220800, 0x10400003,
+0x3247ffff, 0x10000002, 0x24020020, 0x24020004,
+0xafa20010, 0x8f420030, 0xafa20014, 0x8f420010,
+0x3c030002, 0x431025, 0xafa20018, 0x8f460098,
+0x8f420108, 0x40f809, 0x0, 0x104000b7,
+0x0, 0x8f42009c, 0x8f430094, 0x2421021,
+0xaf42009c, 0xae03000c, 0x8f4200ac, 0x10400008,
+0x3c034000, 0x8f420094, 0x431025, 0xafa20020,
+0x8f42009c, 0x8f4300b0, 0x10000004, 0x431025,
+0x8f420094, 0xafa20020, 0x8f42009c, 0xafa20024,
+0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000,
+0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c,
+0x8f440270, 0x8f450274, 0x401821, 0x1021,
+0xa32821, 0xa3302b, 0x822021, 0x862021,
+0x32230060, 0x24020040, 0xaf440270, 0xaf450274,
+0x10620017, 0x2c620041, 0x10400005, 0x24020020,
+0x10620008, 0x24020001, 0x10000026, 0x0,
+0x24020060, 0x10620019, 0x24020001, 0x10000021,
+0x0, 0x8f420278, 0x8f43027c, 0x24630001,
+0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
+0x8f420278, 0x8f43027c, 0x10000016, 0x24020001,
+0x8f420280, 0x8f430284, 0x24630001, 0x2c640001,
+0x441021, 0xaf420280, 0xaf430284, 0x8f420280,
+0x8f430284, 0x1000000b, 0x24020001, 0x8f420288,
+0x8f43028c, 0x24630001, 0x2c640001, 0x441021,
+0xaf420288, 0xaf43028c, 0x8f420288, 0x8f43028c,
+0x24020001, 0xa34205c2, 0x8f420098, 0x3244ffff,
+0x2406fff8, 0x8f45013c, 0x441021, 0x24420007,
+0x461024, 0x24840007, 0xaf420094, 0x8f420090,
+0x8f430094, 0x862024, 0x441023, 0x65182b,
+0x14600005, 0xaf420090, 0x8f420094, 0x8f430144,
+0x431023, 0xaf420094, 0x8f420094, 0x10000023,
+0xaf40009c, 0x3247ffff, 0x50e00022, 0x32c20020,
+0x14400002, 0x24020010, 0x24020002, 0xafa20010,
+0x8f420030, 0xafa20014, 0x8f420010, 0xafa20018,
+0x8f460098, 0x8f420108, 0x40f809, 0x0,
+0x1040003a, 0x3245ffff, 0x8f420098, 0x8f430090,
+0x8f46013c, 0x451021, 0xaf420098, 0x8f42009c,
+0x8f440098, 0xa34005c2, 0x651823, 0xaf430090,
+0x451021, 0x86202b, 0x14800005, 0xaf42009c,
+0x8f420098, 0x8f430144, 0x431023, 0xaf420098,
+0x32c20020, 0x10400005, 0x0, 0x8f420358,
+0x2442ffff, 0xaf420358, 0x8f420358, 0x8f420030,
+0x8f430040, 0x24420001, 0x2463ffff, 0x431024,
+0xaf420030, 0x8f420030, 0x14530018, 0x0,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x2403fff7, 0x431024,
+0xaf820060, 0x8f420000, 0x10400003, 0x0,
+0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0038,
+0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028,
+0x3e00008, 0x27bd0040, 0x3e00008, 0x0,
+0x27bdffd0, 0x32c20020, 0xafbf002c, 0xafb20028,
+0xafb10024, 0x10400004, 0xafb00020, 0x8f520028,
+0x10000002, 0x0, 0x8f520020, 0x8f420030,
+0x105200b5, 0x21100, 0x8f43001c, 0x628021,
+0x8e040000, 0x8e050004, 0x96110008, 0x8f420090,
+0x9607000a, 0x3226ffff, 0x46102a, 0x10400017,
+0x0, 0x8f8200d8, 0x8f430098, 0x431023,
+0x2442dc46, 0xaf420090, 0x8f420090, 0x2842dc47,
+0x10400005, 0x0, 0x8f420090, 0x8f430144,
+0x431021, 0xaf420090, 0x8f420090, 0x46102a,
+0x10400006, 0x0, 0x8f420348, 0x24420001,
+0xaf420348, 0x100000ab, 0x8f420348, 0x8f8600fc,
+0x10c0000c, 0x0, 0x8f8200f4, 0x2403fff8,
+0x431024, 0x461023, 0x218c3, 0x58600001,
+0x24630100, 0x8f42008c, 0x43102b, 0x14400006,
+0x712c2, 0x8f420344, 0x24420001, 0xaf420344,
+0x10000098, 0x8f420344, 0x934305c2, 0x1060000f,
+0x30460001, 0x8f420010, 0x34480400, 0x32c20008,
+0x10400008, 0x30e20200, 0x10400006, 0x3c034000,
+0x9602000e, 0xaf4300ac, 0x21400, 0x10000004,
+0xaf4200b0, 0x10000002, 0xaf4000ac, 0x8f480010,
+0x30e20004, 0x10400045, 0x3227ffff, 0x8f4900ac,
+0x11200005, 0x30c200ff, 0x14400006, 0x24020040,
+0x10000004, 0x24020008, 0x14400002, 0x24020020,
+0x24020004, 0xafa20010, 0x8f430030, 0x11200004,
+0xafa30014, 0x8f4200b0, 0x621025, 0xafa20014,
+0x3c020002, 0x1021025, 0xafa20018, 0x8f460098,
+0x8f420108, 0x40f809, 0x0, 0x10400069,
+0x3224ffff, 0x8f42008c, 0x8f430094, 0x24420001,
+0xaf42008c, 0x24020001, 0xae03000c, 0xa34205c2,
+0x8f420098, 0x2406fff8, 0x8f45013c, 0x441021,
+0x24420007, 0x461024, 0x24840007, 0xaf420094,
+0x8f420090, 0x8f430094, 0x862024, 0x441023,
+0x65182b, 0x14600005, 0xaf420090, 0x8f420094,
+0x8f430144, 0x431023, 0xaf420094, 0x8f430094,
+0x8f420140, 0x43102b, 0x10400009, 0x0,
+0x8f43013c, 0x8f440094, 0x8f420090, 0x8f450138,
+0x641823, 0x431023, 0xaf420090, 0xaf450094,
+0x8f420094, 0x1000001f, 0xaf420098, 0x10e0001d,
+0x30c200ff, 0x14400002, 0x24020010, 0x24020002,
+0xafa20010, 0x8f420030, 0xafa80018, 0xafa20014,
+0x8f460098, 0x8f420108, 0x40f809, 0x0,
+0x10400030, 0x3225ffff, 0x8f420098, 0x8f44013c,
+0x451021, 0xaf420098, 0x8f420090, 0x8f430098,
+0xa34005c2, 0x451023, 0x64182b, 0x14600005,
+0xaf420090, 0x8f420098, 0x8f430144, 0x431023,
+0xaf420098, 0x8f420030, 0x8f430040, 0x24420001,
+0x2463ffff, 0x431024, 0xaf420030, 0x8f420030,
+0x14520018, 0x0, 0x8f420000, 0x10400007,
+0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
+0x0, 0x10000005, 0x0, 0xaf800048,
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
+0x2403fff7, 0x431024, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x10000002, 0xaf80004c,
+0xaf800048, 0x8fbf002c, 0x8fb20028, 0x8fb10024,
+0x8fb00020, 0x3e00008, 0x27bd0030, 0x3e00008,
+0x0, 0x27bdffd8, 0x3c020001, 0x34422ec0,
+0xafbf0020, 0x8f4300f0, 0x8f840108, 0x2e21021,
+0x54620004, 0x24620008, 0x3c020001, 0x34422cc0,
+0x2e21021, 0x401821, 0xaf4300f0, 0xac600000,
+0x8f4200ec, 0x8c660004, 0x14620004, 0x3c020001,
+0x24820020, 0x1000000f, 0xaf820108, 0x8f4300f0,
+0x34422ec0, 0x2e21021, 0x54620004, 0x24620008,
+0x3c020001, 0x34422cc0, 0x2e21021, 0x401821,
+0x8c620004, 0x21140, 0x821021, 0xaf820108,
+0xac600000, 0x8c850018, 0x30a20036, 0x1040006c,
+0x30a20001, 0x8c82001c, 0x8f430040, 0x8f440034,
+0x24420001, 0x2463ffff, 0x431024, 0x862021,
+0xaf42002c, 0x30a20030, 0x14400006, 0xaf440034,
+0x8f420034, 0x8c03023c, 0x43102b, 0x144000b4,
+0x0, 0x32c20010, 0x10400028, 0x24070008,
+0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c,
+0x8f860120, 0x24020080, 0xafa20010, 0xafa30014,
+0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x14400011, 0x24020001, 0x3c010001, 0x370821,
+0xa02240f1, 0x8f820124, 0xafa20010, 0x8f820128,
+0x3c040001, 0x248467c4, 0xafa20014, 0x8f46002c,
+0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51100,
+0x10000036, 0x0, 0x8f420300, 0x8f43002c,
+0x24420001, 0xaf420300, 0x8f420300, 0x24020001,
+0xa34205c1, 0x10000026, 0xaf430038, 0x8f440170,
+0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
+0x24020020, 0xafa20010, 0xafa30014, 0xafa80018,
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
+0x24020001, 0x3c010001, 0x370821, 0xa02240f0,
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
+0x248467b8, 0xafa20014, 0x8f46002c, 0x8f870120,
+0x3c050009, 0xc002b3b, 0x34a50900, 0x1000000f,
+0x0, 0x8f420300, 0x24420001, 0xaf420300,
+0x8f420300, 0x8f42002c, 0xa34005c1, 0xaf420038,
+0x3c010001, 0x370821, 0xa02040f1, 0x3c010001,
+0x370821, 0xa02040f0, 0xaf400034, 0x8f420314,
+0x24420001, 0xaf420314, 0x10000059, 0x8f420314,
+0x10400022, 0x30a27000, 0x8c85001c, 0x8f420028,
+0xa22023, 0x4810003, 0x0, 0x8f420040,
+0x822021, 0x8f420358, 0x8f430000, 0xaf450028,
+0x441021, 0x10600007, 0xaf420358, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x34420008, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x10000038,
+0xaf80004c, 0x10000036, 0xaf800048, 0x1040002f,
+0x30a21000, 0x1040000c, 0x30a24000, 0x8c83001c,
+0x8f420050, 0x622023, 0x4820001, 0x24840200,
+0x8f42035c, 0x441021, 0xaf42035c, 0x8f420368,
+0x1000001a, 0xaf430050, 0x1040000c, 0x32c28000,
+0x8c83001c, 0x8f420070, 0x622023, 0x4820001,
+0x24840400, 0x8f420364, 0x441021, 0xaf420364,
+0x8f420368, 0x1000000d, 0xaf430070, 0x1040000e,
+0x3c020800, 0x8c83001c, 0x8f420060, 0x622023,
+0x4820001, 0x24840100, 0x8f420360, 0x441021,
+0xaf420360, 0x8f420368, 0xaf430060, 0x441021,
+0xaf420368, 0x3c020800, 0x2c21024, 0x50400008,
+0x36940040, 0x10000006, 0x0, 0x30a20100,
+0x10400003, 0x0, 0xc002bd8, 0x0,
+0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008,
+0x0, 0x27bdffa8, 0xafbf0050, 0xafbe004c,
+0xafb50048, 0xafb30044, 0xafb20040, 0xafb1003c,
+0xafb00038, 0x8f910108, 0x26220020, 0xaf820108,
+0x8e320018, 0xa821, 0x32420024, 0x104001ba,
+0xf021, 0x8e26001c, 0x8f43001c, 0x61100,
+0x621821, 0x8c70000c, 0x9604000c, 0x962d0016,
+0x9473000a, 0x2c8305dd, 0x38828870, 0x2c420001,
+0x621825, 0x10600015, 0x2821, 0x32c20040,
+0x10400015, 0x24020800, 0x96030014, 0x14620012,
+0x3402aaaa, 0x9603000e, 0x14620007, 0x2021,
+0x96030010, 0x24020300, 0x14620004, 0x801021,
+0x96020012, 0x2c440001, 0x801021, 0x54400006,
+0x24050016, 0x10000004, 0x0, 0x24020800,
+0x50820001, 0x2405000e, 0x934205c3, 0x14400008,
+0x5821, 0x240b0001, 0x32620180, 0xaf4500a8,
+0xaf5000a0, 0x10400002, 0xaf4600a4, 0xa34b05c3,
+0x10a00085, 0x2054021, 0x91020000, 0x3821,
+0x3042000f, 0x25080, 0x32c20002, 0x10400012,
+0x10a1821, 0x32620002, 0x10400010, 0x32c20001,
+0x1002021, 0x94820000, 0x24840002, 0xe23821,
+0x83102b, 0x1440fffb, 0x30e2ffff, 0x71c02,
+0x623821, 0x71c02, 0x30e2ffff, 0x623821,
+0x71027, 0xa502000a, 0x32c20001, 0x1040006a,
+0x32620001, 0x10400068, 0x0, 0x8f4200a8,
+0x10400065, 0x0, 0x8f4200a0, 0x8f4300a8,
+0x431021, 0x904c0009, 0x318900ff, 0x39230006,
+0x3182b, 0x39220011, 0x2102b, 0x621824,
+0x1060000c, 0x3c050006, 0x8f4200a4, 0x3c040001,
+0x248467d4, 0xafa20010, 0x8f4200a0, 0x34a54600,
+0x1203821, 0xc002b3b, 0xafa20014, 0x1000004e,
+0x0, 0x32c20004, 0x14400013, 0x2821,
+0x316200ff, 0x14400004, 0x0, 0x95020002,
+0x1000000d, 0x4a2823, 0x9505000c, 0x9502000e,
+0x95030010, 0xa22821, 0xa32821, 0x95030012,
+0x91040009, 0x95020002, 0xa32821, 0xa42821,
+0x4a1023, 0xa22821, 0x2002021, 0x94820000,
+0x24840002, 0xe23821, 0x88102b, 0x1440fffb,
+0x71c02, 0x30e2ffff, 0x623821, 0x71c02,
+0x30e2ffff, 0x623821, 0x1a52821, 0x51c02,
+0x30a2ffff, 0x622821, 0x51c02, 0x30a2ffff,
+0x622821, 0xa72823, 0x51402, 0xa22821,
+0x30a5ffff, 0x50a00001, 0x3405ffff, 0x316200ff,
+0x14400008, 0x318300ff, 0x8f4300a0, 0x8f4200a8,
+0x624021, 0x91020000, 0x3042000f, 0x25080,
+0x318300ff, 0x24020006, 0x14620003, 0x10a1021,
+0x10000002, 0x24440010, 0x24440006, 0x316200ff,
+0x14400006, 0x0, 0x94820000, 0xa22821,
+0x51c02, 0x30a2ffff, 0x622821, 0x934205c3,
+0x10400003, 0x32620100, 0x50400003, 0xa4850000,
+0x52827, 0xa4850000, 0x9622000e, 0x8f43009c,
+0x621821, 0x32a200ff, 0x10400007, 0xaf43009c,
+0x3c024000, 0x2021025, 0xafa20020, 0x8f42009c,
+0x10000003, 0x5e1025, 0xafb00020, 0x8f42009c,
+0xafa20024, 0x32620080, 0x10400010, 0x32620100,
+0x8f4200b4, 0x24430001, 0x210c0, 0x571021,
+0xaf4300b4, 0x8fa30020, 0x8fa40024, 0x3c010001,
+0x220821, 0xac2338e8, 0x3c010001, 0x220821,
+0xac2438ec, 0x100000a5, 0x32c20020, 0x10400064,
+0x0, 0x8f4200b4, 0x24430001, 0x210c0,
+0x571021, 0xaf4300b4, 0x8fa30020, 0x8fa40024,
+0x3c010001, 0x220821, 0xac2338e8, 0x3c010001,
+0x220821, 0xac2438ec, 0x8f4200b4, 0x10400051,
+0x3821, 0x3c090001, 0x352938e8, 0x3c08001f,
+0x3508ffff, 0x240bffff, 0x340affff, 0x710c0,
+0x571021, 0x491021, 0x8c430000, 0x8c440004,
+0xafa30028, 0xafa4002c, 0x8f8200fc, 0x8fa30028,
+0x8fa4002c, 0xac430000, 0xac440004, 0x24420008,
+0xaf8200f0, 0x8f42008c, 0x2442ffff, 0xaf42008c,
+0x97a2002e, 0x8f440270, 0x8f450274, 0x401821,
+0x1021, 0xa32821, 0xa3302b, 0x822021,
+0x862021, 0xaf440270, 0xaf450274, 0x8fa20028,
+0x481024, 0x90430000, 0x30630001, 0x1460000b,
+0x402021, 0x8f420278, 0x8f43027c, 0x24630001,
+0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
+0x8f420278, 0x1000001a, 0x8f43027c, 0x8c820000,
+0x144b000e, 0x0, 0x94820004, 0x144a000b,
+0x0, 0x8f420288, 0x8f43028c, 0x24630001,
+0x2c640001, 0x441021, 0xaf420288, 0xaf43028c,
+0x8f420288, 0x1000000a, 0x8f43028c, 0x8f420280,
+0x8f430284, 0x24630001, 0x2c640001, 0x441021,
+0xaf420280, 0xaf430284, 0x8f420280, 0x8f430284,
+0x8f4200b4, 0x24e70001, 0xe2102b, 0x1440ffb8,
+0x710c0, 0xa34005c3, 0x1000003f, 0xaf4000b4,
+0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000,
+0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c,
+0x8f46008c, 0x8f440270, 0x8f450274, 0x401821,
+0x1021, 0x24c6ffff, 0xaf46008c, 0xa32821,
+0xa3302b, 0x822021, 0x862021, 0xaf440270,
+0xaf450274, 0x92020000, 0x30420001, 0x1440000c,
+0x2402ffff, 0x8f420278, 0x8f43027c, 0x24630001,
+0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
+0x8f420278, 0x8f43027c, 0x1000001c, 0x32c20020,
+0x8e030000, 0x1462000f, 0x3402ffff, 0x96030004,
+0x1462000c, 0x0, 0x8f420288, 0x8f43028c,
+0x24630001, 0x2c640001, 0x441021, 0xaf420288,
+0xaf43028c, 0x8f420288, 0x8f43028c, 0x1000000b,
+0x32c20020, 0x8f420280, 0x8f430284, 0x24630001,
+0x2c640001, 0x441021, 0xaf420280, 0xaf430284,
+0x8f420280, 0x8f430284, 0x32c20020, 0x10400005,
+0xaf40009c, 0x8f420358, 0x2442ffff, 0xaf420358,
+0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001,
+0x2463ffff, 0x431024, 0xaf42002c, 0x32420060,
+0x14400008, 0x32c20010, 0x8f420034, 0x24420001,
+0xaf420034, 0x8c03023c, 0x43102b, 0x14400102,
+0x32c20010, 0x10400018, 0x24070008, 0x8f440170,
+0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
+0x24020080, 0xafa20010, 0xafa30014, 0xafa80018,
+0x8f42010c, 0x40f809, 0x24c6001c, 0x10400047,
+0x24020001, 0x8f420300, 0x8f43002c, 0x24420001,
+0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1,
+0x1000007c, 0xaf430038, 0x8f440170, 0x8f450174,
+0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020,
+0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c,
+0x40f809, 0x24c6001c, 0x10400057, 0x24020001,
+0x10000065, 0x0, 0x32420012, 0x10400075,
+0x32420001, 0x9622000e, 0x8f43009c, 0x621821,
+0x32c20020, 0x10400005, 0xaf43009c, 0x8f420358,
+0x2442ffff, 0xaf420358, 0x8f420358, 0x8e22001c,
+0x8f430040, 0x24420001, 0x2463ffff, 0x431024,
+0xaf42002c, 0x32420010, 0x14400008, 0x32c20010,
+0x8f420034, 0x24420001, 0xaf420034, 0x8c03023c,
+0x43102b, 0x144000bc, 0x32c20010, 0x10400028,
+0x24070008, 0x8f440170, 0x8f450174, 0x8f43002c,
+0x8f48000c, 0x8f860120, 0x24020080, 0xafa20010,
+0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
+0x24c6001c, 0x14400011, 0x24020001, 0x3c010001,
+0x370821, 0xa02240f1, 0x8f820124, 0xafa20010,
+0x8f820128, 0x3c040001, 0x248467c4, 0xafa20014,
+0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b,
+0x34a51100, 0x10000036, 0x0, 0x8f420300,
+0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300,
+0x24020001, 0xa34205c1, 0x10000026, 0xaf430038,
+0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c,
+0x8f860120, 0x24020020, 0xafa20010, 0xafa30014,
+0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x14400011, 0x24020001, 0x3c010001, 0x370821,
+0xa02240f0, 0x8f820124, 0xafa20010, 0x8f820128,
+0x3c040001, 0x248467b8, 0xafa20014, 0x8f46002c,
+0x8f870120, 0x3c050009, 0xc002b3b, 0x34a50900,
+0x1000000f, 0x0, 0x8f420300, 0x24420001,
+0xaf420300, 0x8f420300, 0x8f42002c, 0xa34005c1,
+0xaf420038, 0x3c010001, 0x370821, 0xa02040f1,
+0x3c010001, 0x370821, 0xa02040f0, 0xaf400034,
+0x8f420314, 0x24420001, 0xaf420314, 0x10000062,
+0x8f420314, 0x10400022, 0x32427000, 0x8e25001c,
+0x8f420028, 0xa22023, 0x4810003, 0x0,
+0x8f420040, 0x822021, 0x8f420358, 0x8f430000,
+0xaf450028, 0x441021, 0x10600007, 0xaf420358,
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
+0x10000005, 0x0, 0xaf800048, 0x8f820048,
+0x1040fffd, 0x0, 0x8f820060, 0x34420008,
+0xaf820060, 0x8f420000, 0x10400003, 0x0,
+0x10000041, 0xaf80004c, 0x1000003f, 0xaf800048,
+0x1040002f, 0x32421000, 0x1040000c, 0x32424000,
+0x8e23001c, 0x8f420050, 0x622023, 0x4820001,
+0x24840200, 0x8f42035c, 0x441021, 0xaf42035c,
+0x8f420368, 0x1000001a, 0xaf430050, 0x1040000c,
+0x32c28000, 0x8e23001c, 0x8f420070, 0x622023,
+0x4820001, 0x24840400, 0x8f420364, 0x441021,
+0xaf420364, 0x8f420368, 0x1000000d, 0xaf430070,
+0x1040000e, 0x3c020800, 0x8e23001c, 0x8f420060,
+0x622023, 0x4820001, 0x24840100, 0x8f420360,
+0x441021, 0xaf420360, 0x8f420368, 0xaf430060,
+0x441021, 0xaf420368, 0x3c020800, 0x2c21024,
+0x50400011, 0x36940040, 0x1000000f, 0x0,
+0x32420048, 0x10400007, 0x24150001, 0x8e22001c,
+0x3c03ffff, 0x43f024, 0x3042ffff, 0x1000fd75,
+0xae22001c, 0x32420100, 0x10400003, 0x0,
+0xc002bd8, 0x0, 0x8fbf0050, 0x8fbe004c,
+0x8fb50048, 0x8fb30044, 0x8fb20040, 0x8fb1003c,
+0x8fb00038, 0x3e00008, 0x27bd0058, 0x3e00008,
+0x0, 0x0, 0x0, 0x8f8300e4,
+0x8f8200e0, 0x2404fff8, 0x441024, 0x621026,
+0x2102b, 0x21023, 0x3e00008, 0x621024,
+0x3e00008, 0x0, 0x27bdffe0, 0xafbf001c,
+0xafb00018, 0x8f8600c4, 0x8f8400e0, 0x8f8500e4,
+0x2402fff8, 0x821824, 0x10a30009, 0x27623ff8,
+0x14a20002, 0x24a20008, 0x27623000, 0x408021,
+0x16030005, 0x30820004, 0x10400004, 0xc02021,
+0x10000022, 0x1021, 0x8e040000, 0x8f42011c,
+0x14a20003, 0x0, 0x8f420120, 0xaf420114,
+0x8ca30000, 0x8f420148, 0x831823, 0x43102b,
+0x10400003, 0x0, 0x8f420148, 0x621821,
+0x94a20006, 0x24420050, 0x62102b, 0x1440000f,
+0xa01021, 0xafa40010, 0xafa30014, 0x8ca60000,
+0x8ca70004, 0x3c040001, 0xc002b3b, 0x24846894,
+0x8f42020c, 0x24420001, 0xaf42020c, 0x8f42020c,
+0x1021, 0xaf9000e8, 0xaf9000e4, 0x8fbf001c,
+0x8fb00018, 0x3e00008, 0x27bd0020, 0x3e00008,
+0x0, 0x8f8400e0, 0x8f8800c4, 0x8f8300e8,
+0x2402fff8, 0x823824, 0xe32023, 0x2c821000,
+0x50400001, 0x24841000, 0x420c2, 0x801821,
+0x8f440258, 0x8f45025c, 0x1021, 0xa32821,
+0xa3302b, 0x822021, 0x862021, 0xaf440258,
+0xaf45025c, 0x8f8300c8, 0x8f420148, 0x1032023,
+0x82102b, 0x14400004, 0x801821, 0x8f420148,
+0x822021, 0x801821, 0x8f440250, 0x8f450254,
+0x1021, 0xa32821, 0xa3302b, 0x822021,
+0x862021, 0xaf440250, 0xaf450254, 0xaf8800c8,
+0xaf8700e4, 0xaf8700e8, 0x3e00008, 0x0,
+0x27bdff30, 0x240a0001, 0xafbf00c8, 0xafbe00c4,
+0xafb500c0, 0xafb300bc, 0xafb200b8, 0xafb100b4,
+0xafb000b0, 0xa3a00097, 0xafa00044, 0xafaa005c,
+0x934205c4, 0xa7a0008e, 0x1040000a, 0xa7a00086,
+0x8f4b00c4, 0xafab0064, 0x8f4a00c0, 0xafaa006c,
+0x8f4b00cc, 0xafab0074, 0x8f4a00c8, 0x10000129,
+0xafaa007c, 0x8f420114, 0x40f809, 0x0,
+0x403021, 0x10c0034f, 0x0, 0x8cc20000,
+0x8cc30004, 0xafa20020, 0xafa30024, 0x8fab0024,
+0x8faa0020, 0x3162ffff, 0x2442fffc, 0xafa2006c,
+0x3c020006, 0x2c21024, 0xafab007c, 0x14400015,
+0xafaa0064, 0x91420000, 0x30420001, 0x10400011,
+0x2402ffff, 0x8d430000, 0x14620004, 0x3402ffff,
+0x95430004, 0x1062000b, 0x0, 0xc0024bb,
+0x8fa40064, 0x304200ff, 0x14400006, 0x0,
+0x8f420118, 0x40f809, 0x0, 0x1000032d,
+0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
+0x431024, 0x3c03ffff, 0x431824, 0x14600003,
+0xafa20024, 0x10000040, 0x1821, 0x3c020080,
+0x621024, 0x10400007, 0x0, 0x8f42038c,
+0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036,
+0x24030001, 0x8f420210, 0x24420001, 0xaf420210,
+0x8f420210, 0x3c020001, 0x621024, 0x10400006,
+0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4,
+0x8f4201c4, 0x3c020002, 0x621024, 0x10400006,
+0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c,
+0x8f42037c, 0x3c020004, 0x621024, 0x10400006,
+0x3c020008, 0x8f420380, 0x24420001, 0xaf420380,
+0x8f420380, 0x3c020008, 0x621024, 0x10400006,
+0x3c020010, 0x8f420384, 0x24420001, 0xaf420384,
+0x8f420384, 0x3c020010, 0x621024, 0x10400006,
+0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0,
+0x8f4201c0, 0x3c020020, 0x621024, 0x10400006,
+0x24030001, 0x8f420388, 0x24420001, 0xaf420388,
+0x8f420388, 0x24030001, 0x8c020260, 0x8fab006c,
+0x4b102b, 0x10400014, 0x307000ff, 0x8f4201e8,
+0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8faa007c,
+0x8f8200e0, 0x354a0100, 0xafaa007c, 0xafa20010,
+0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0,
+0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007,
+0xc002b3b, 0x34a50800, 0x12000010, 0x3c020080,
+0x2c21024, 0x1440000e, 0x32c20400, 0x8fab007c,
+0x3c020080, 0x34420100, 0x1621024, 0x10400005,
+0x0, 0x8f42020c, 0x24420001, 0xaf42020c,
+0x8f42020c, 0x100002b0, 0x8fa3006c, 0x32c20400,
+0x10400015, 0x34028100, 0x8faa0064, 0x9543000c,
+0x14620012, 0x3c020100, 0x240b0200, 0xa7ab008e,
+0x9542000e, 0x8d430008, 0x8d440004, 0x8d450000,
+0x8faa006c, 0x8fab0064, 0x254afffc, 0xafaa006c,
+0xa7a20086, 0xad63000c, 0xad640008, 0xad650004,
+0x256b0004, 0xafab0064, 0x3c020100, 0x2c21024,
+0x10400004, 0x0, 0x8faa006c, 0x254a0004,
+0xafaa006c, 0x8f4200bc, 0x5040000a, 0xafa00074,
+0x8fab006c, 0x4b102b, 0x50400006, 0xafa00074,
+0x8f4200bc, 0x1621023, 0xafa20074, 0x8f4a00bc,
+0xafaa006c, 0x8f420080, 0x8fab006c, 0x4b102b,
+0x10400056, 0x32c28000, 0x1040005e, 0x240a0003,
+0x32c21000, 0x1040005b, 0xafaa005c, 0x10000058,
+0x240b0004, 0x8f420350, 0x2403ffbf, 0x283a024,
+0x24420001, 0xaf420350, 0x1000024f, 0x8f420350,
+0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128,
+0x3c040001, 0x248468d0, 0x26620001, 0xafa20014,
+0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007,
+0xc002b3b, 0x34a52250, 0x1000023f, 0x0,
+0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128,
+0x3c040001, 0x248468d0, 0x24020002, 0xafa20014,
+0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007,
+0xc002b3b, 0x34a52450, 0x1000022f, 0x0,
+0x8ea20000, 0x8ea30004, 0x3c040001, 0x248468e8,
+0xafb00010, 0xafbe0014, 0x8ea70018, 0x34a52800,
+0xc002b3b, 0x603021, 0x10000223, 0x0,
+0xa6b1000a, 0x8f820124, 0x3c040001, 0x248468f0,
+0xafbe0014, 0xafa20010, 0x8f460044, 0x8f870120,
+0x3c050007, 0xc002b3b, 0x34a53000, 0x10000216,
+0x0, 0xa6b1000a, 0xa6b2000e, 0x8f820124,
+0x3c040001, 0x248468fc, 0xafbe0014, 0xafa20010,
+0x8f460044, 0x8f870120, 0x3c050007, 0xc002b3b,
+0x34a53200, 0x10000208, 0x0, 0x8f420084,
+0x8faa006c, 0x4a102b, 0x14400007, 0x3c020001,
+0x2c21024, 0x10400004, 0x0, 0x240b0002,
+0xafab005c, 0x8faa006c, 0x1140021b, 0x27ab0020,
+0xafab00a4, 0x3c0a001f, 0x354affff, 0xafaa009c,
+0x8fab005c, 0x240a0001, 0x556a0021, 0x240a0002,
+0x8f430054, 0x8f420050, 0x1062000b, 0x274b0054,
+0x8f5e0054, 0x3403ecc0, 0xafab004c, 0x27c20001,
+0x304201ff, 0xafa20054, 0x1e1140, 0x431021,
+0x1000006b, 0x2e2a821, 0x8f420044, 0x8faa006c,
+0x3c040001, 0x248468ac, 0xafaa0014, 0xafa20010,
+0x8f460054, 0x8f470050, 0x3c050007, 0xc002b3b,
+0x34a51300, 0x8f430350, 0x2402ffbf, 0x282a024,
+0x24630001, 0xaf430350, 0x100001d3, 0x8f420350,
+0x156a001d, 0x0, 0x8f430074, 0x8f420070,
+0x1062000a, 0x274b0074, 0x8f5e0074, 0xafab004c,
+0x27c20001, 0x304203ff, 0xafa20054, 0x1e1140,
+0x24426cc0, 0x1000004a, 0x2e2a821, 0x8f420044,
+0x8faa006c, 0x3c040001, 0x248468b8, 0x3c050007,
+0xafaa0014, 0xafa20010, 0x8f460074, 0x8f470070,
+0x34a51500, 0x240b0001, 0xc002b3b, 0xafab005c,
+0x1000ffc3, 0x0, 0x8f430064, 0x8f420060,
+0x1062001a, 0x274a0064, 0x8f5e0064, 0x8fab005c,
+0xafaa004c, 0x27c20001, 0x304200ff, 0xafa20054,
+0x24020004, 0x1562000e, 0x1e1140, 0x1e1180,
+0x24420cc0, 0x2e21021, 0xafa20044, 0x9442002a,
+0x8faa0044, 0x8fab006c, 0x4b102b, 0x10400024,
+0x25550020, 0x240a0001, 0x10000021, 0xa3aa0097,
+0x24424cc0, 0x1000001e, 0x2e2a821, 0x8f420044,
+0x8fab006c, 0x3c040001, 0x248468c4, 0xafab0014,
+0xafa20010, 0x8f460064, 0x8f470060, 0x3c050007,
+0xc002b3b, 0x34a51800, 0x3c020008, 0x2c21024,
+0x1440ff34, 0x0, 0x8f420370, 0x240a0001,
+0xafaa005c, 0x24420001, 0xaf420370, 0x1000ff90,
+0x8f420370, 0x27a30036, 0x131040, 0x621821,
+0x94620000, 0x441021, 0x10000020, 0xa4620000,
+0x8fab0064, 0xaeab0018, 0x93a20097, 0x10400072,
+0x9821, 0x8faa0044, 0x8fa4006c, 0x8fa300a4,
+0x25420020, 0xafa20028, 0x25420008, 0xafa20030,
+0x25420010, 0xafaa002c, 0xafa20034, 0x9542002a,
+0xa7a20038, 0x95420018, 0xa7a2003a, 0x9542001a,
+0xa7a2003c, 0x9542001c, 0xa7a2003e, 0x94620018,
+0x24630002, 0x822023, 0x1880ffde, 0x26730001,
+0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc,
+0x26650001, 0xa2102a, 0x1440002b, 0x24030001,
+0x8f83012c, 0x10600023, 0x0, 0x8f820124,
+0x431023, 0x22143, 0x58800001, 0x24840040,
+0x8f820128, 0x431023, 0x21943, 0x58600001,
+0x24630040, 0x64102a, 0x54400001, 0x602021,
+0xaf4400fc, 0x8f4200fc, 0xa2102a, 0x10400011,
+0x24030001, 0x10000015, 0x306200ff, 0x8fab0064,
+0x96070018, 0xafab0010, 0x8e220008, 0x3c040001,
+0x248468dc, 0x8c430004, 0x8c420000, 0x34a52400,
+0x2403021, 0xc002b3b, 0xafa30014, 0x1000002b,
+0x0, 0x8f420334, 0x1821, 0x24420001,
+0xaf420334, 0x8f420334, 0x306200ff, 0x5040fedc,
+0x3c020800, 0x12600021, 0x9021, 0x8fb100a4,
+0x2208021, 0x8e220008, 0x96070018, 0x8fa60064,
+0x8c440000, 0x8c450004, 0x240a0001, 0xafaa0010,
+0xafbe0014, 0x8f420008, 0xafa20018, 0x8f42010c,
+0x40f809, 0x0, 0x1040ffd8, 0x3c050007,
+0x96020018, 0x8fab0064, 0x8faa009c, 0x1625821,
+0x14b102b, 0x10400004, 0xafab0064, 0x8f420148,
+0x1625823, 0xafab0064, 0x26100002, 0x26520001,
+0x253102b, 0x1440ffe3, 0x26310004, 0x8fb0006c,
+0x10000036, 0x97b10038, 0x8f4200fc, 0x24050002,
+0xa2102a, 0x1440001b, 0x24030001, 0x8f83012c,
+0x10600013, 0x0, 0x8f820124, 0x431023,
+0x22143, 0x58800001, 0x24840040, 0x8f820128,
+0x431023, 0x21943, 0x58600001, 0x24630040,
+0x64102a, 0x54400001, 0x602021, 0xaf4400fc,
+0x8f4200fc, 0xa2102a, 0x14400006, 0x24030001,
+0x8f420334, 0x1821, 0x24420001, 0xaf420334,
+0x8f420334, 0x306200ff, 0x1040fea5, 0x3c020800,
+0x96b1000a, 0x8fb0006c, 0x3223ffff, 0x70102b,
+0x54400001, 0x608021, 0x8ea40000, 0x8ea50004,
+0x240b0001, 0xafab0010, 0xafbe0014, 0x8f420008,
+0x8fa60064, 0xafa20018, 0x8f42010c, 0x40f809,
+0x2003821, 0x1040fea2, 0x3c050007, 0x96a3000e,
+0x97aa008e, 0x11400007, 0x609021, 0x934205c4,
+0x14400004, 0x0, 0x97ab0086, 0x6a1825,
+0xa6ab0016, 0x8faa007c, 0x3c02ffff, 0x1421024,
+0x10400003, 0xa1402, 0x34630400, 0xa6a20014,
+0x8fab006c, 0x560b0072, 0xa6a3000e, 0x34620004,
+0xa6a2000e, 0x8faa0074, 0x16a1021, 0xa6a2000a,
+0x8f430044, 0x8f4401a0, 0x8f4501a4, 0x34028000,
+0xafa20010, 0x8f420044, 0x2a03021, 0x24070020,
+0xafa20014, 0x8f42000c, 0x31940, 0x604821,
+0xafa20018, 0x8f42010c, 0x4021, 0xa92821,
+0xa9182b, 0x882021, 0x40f809, 0x832021,
+0x5040fe7f, 0xa6b2000e, 0x8f420368, 0xafa0006c,
+0xa34005c4, 0x2442ffff, 0xaf420368, 0x8fab005c,
+0x240a0001, 0x8f420368, 0x156a0006, 0x240a0002,
+0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c,
+0x8f42035c, 0x156a0006, 0x0, 0x8f420364,
+0x2442ffff, 0xaf420364, 0x10000005, 0x8f420364,
+0x8f420360, 0x2442ffff, 0xaf420360, 0x8f420360,
+0x8faa0054, 0x8fab004c, 0xad6a0000, 0x8f420044,
+0x8f440088, 0x8f430078, 0x24420001, 0x441024,
+0x24630001, 0xaf420044, 0xaf430078, 0x8c020240,
+0x62182b, 0x14600075, 0x24070008, 0x8f440168,
+0x8f45016c, 0x8f430044, 0x8f48000c, 0x8f860120,
+0x24020040, 0xafa20010, 0xafa30014, 0xafa80018,
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
+0x240b0001, 0x3c010001, 0x370821, 0xa02b40f2,
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
+0x2484688c, 0xafa20014, 0x8f460044, 0x8f870120,
+0x3c050009, 0xc002b3b, 0x34a51300, 0x1000000b,
+0x0, 0x8f420304, 0x24420001, 0xaf420304,
+0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001,
+0x370821, 0xa02040f2, 0xaf400078, 0x8f420318,
+0x24420001, 0xaf420318, 0x10000048, 0x8f420318,
+0xa6b0000a, 0x8f430044, 0x8f4401a0, 0x8f4501a4,
+0x34028000, 0xafa20010, 0x8f420044, 0x2a03021,
+0x24070020, 0xafa20014, 0x8f42000c, 0x31940,
+0x604821, 0xafa20018, 0x8f42010c, 0x4021,
+0xa92821, 0xa9182b, 0x882021, 0x40f809,
+0x832021, 0x1040fe1f, 0x240a0001, 0xa34a05c4,
+0x8fab006c, 0x8faa0064, 0x1705823, 0xafab006c,
+0x8fab009c, 0x1505021, 0x16a102b, 0x10400004,
+0xafaa0064, 0x8f420148, 0x1425023, 0xafaa0064,
+0x8f420368, 0x2442ffff, 0xaf420368, 0x8faa005c,
+0x240b0001, 0x8f420368, 0x154b0006, 0x240b0002,
+0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c,
+0x8f42035c, 0x114b0006, 0x0, 0x8f420360,
+0x2442ffff, 0xaf420360, 0x10000005, 0x8f420360,
+0x8f420364, 0x2442ffff, 0xaf420364, 0x8f420364,
+0x8fab0054, 0x8faa004c, 0xad4b0000, 0x8f420044,
+0x8f440088, 0x8f430078, 0x24420001, 0x441024,
+0x24630001, 0xaf420044, 0xaf430078, 0x8faa006c,
+0x1540fe0b, 0x0, 0x8fab006c, 0x1160001e,
+0x0, 0x934205c4, 0x10400009, 0x0,
+0x8faa0064, 0xaf4a00c4, 0xaf4b00c0, 0x8fab007c,
+0xaf4b00c8, 0x8faa0074, 0x1000000e, 0xaf4a00cc,
+0x97ab008e, 0x1160000b, 0x34038100, 0x8fa20020,
+0x8c46000c, 0xa443000c, 0x97aa0086, 0x8c440004,
+0x8c450008, 0xa44a000e, 0xac440000, 0xac450004,
+0xac460008, 0x8f42034c, 0x24420001, 0xaf42034c,
+0x10000010, 0x8f42034c, 0x8fab007c, 0x3164ffff,
+0x2484fffc, 0x801821, 0x8f440250, 0x8f450254,
+0x8f460118, 0x1021, 0xa32821, 0xa3382b,
+0x822021, 0x872021, 0xaf440250, 0xc0f809,
+0xaf450254, 0x8fbf00c8, 0x8fbe00c4, 0x8fb500c0,
+0x8fb300bc, 0x8fb200b8, 0x8fb100b4, 0x8fb000b0,
+0x3e00008, 0x27bd00d0, 0x3e00008, 0x0,
+0x27bdff38, 0x240b0001, 0xafbf00c0, 0xafbe00bc,
+0xafb500b8, 0xafb300b4, 0xafb200b0, 0xafb100ac,
+0xafb000a8, 0xa3a00087, 0xafa00044, 0xafab005c,
+0x934205c4, 0xa7a00076, 0x10400007, 0xa7a0007e,
+0x8f4c00c0, 0xafac0064, 0x8f4b00c8, 0x8f5e00c4,
+0x10000130, 0xafab006c, 0x8f420114, 0x40f809,
+0x0, 0x403021, 0x10c002a1, 0x0,
+0x8cc20000, 0x8cc30004, 0xafa20020, 0xafa30024,
+0x8fac0024, 0x8fbe0020, 0x3182ffff, 0x2442fffc,
+0xafa20064, 0x3c020006, 0x2c21024, 0x14400015,
+0xafac006c, 0x93c20000, 0x30420001, 0x10400011,
+0x2402ffff, 0x8fc30000, 0x14620004, 0x3402ffff,
+0x97c30004, 0x1062000b, 0x0, 0xc0024bb,
+0x3c02021, 0x304200ff, 0x14400006, 0x0,
+0x8f420118, 0x40f809, 0x0, 0x10000280,
+0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
+0x431024, 0x3c03ffff, 0x431824, 0x14600003,
+0xafa20024, 0x10000040, 0x8021, 0x3c020080,
+0x621024, 0x10400007, 0x0, 0x8f42038c,
+0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036,
+0x24100001, 0x8f420210, 0x24420001, 0xaf420210,
+0x8f420210, 0x3c020001, 0x621024, 0x10400006,
+0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4,
+0x8f4201c4, 0x3c020002, 0x621024, 0x10400006,
+0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c,
+0x8f42037c, 0x3c020004, 0x621024, 0x10400006,
+0x3c020008, 0x8f420380, 0x24420001, 0xaf420380,
+0x8f420380, 0x3c020008, 0x621024, 0x10400006,
+0x3c020010, 0x8f420384, 0x24420001, 0xaf420384,
+0x8f420384, 0x3c020010, 0x621024, 0x10400006,
+0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0,
+0x8f4201c0, 0x3c020020, 0x621024, 0x10400006,
+0x24100001, 0x8f420388, 0x24420001, 0xaf420388,
+0x8f420388, 0x24100001, 0x8c020260, 0x8fab0064,
+0x4b102b, 0x10400015, 0x320200ff, 0x8f4201e8,
+0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8fac006c,
+0x8f8200e0, 0x358c0100, 0xafac006c, 0xafa20010,
+0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0,
+0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007,
+0xc002b3b, 0x34a53600, 0x320200ff, 0x10400010,
+0x3c020080, 0x2c21024, 0x1440000e, 0x32c20400,
+0x8fab006c, 0x3c020080, 0x34420100, 0x1621024,
+0x10400005, 0x0, 0x8f42020c, 0x24420001,
+0xaf42020c, 0x8f42020c, 0x10000202, 0x8fa30064,
+0x32c20400, 0x10400012, 0x34028100, 0x97c3000c,
+0x1462000f, 0x0, 0x240c0200, 0xa7ac0076,
+0x97c2000e, 0x8fc30008, 0x8fc40004, 0x8fab0064,
+0x8fc50000, 0x256bfffc, 0xafab0064, 0xa7a2007e,
+0xafc3000c, 0xafc40008, 0xafc50004, 0x27de0004,
+0x8fa70064, 0x320200ff, 0x14400034, 0x3c020100,
+0x97c4000c, 0x2c8305dd, 0x38828870, 0x2c420001,
+0x621825, 0x10600015, 0x2821, 0x32c20800,
+0x10400015, 0x24020800, 0x97c30014, 0x14620012,
+0x3402aaaa, 0x97c3000e, 0x14620007, 0x2021,
+0x97c30010, 0x24020300, 0x14620004, 0x801021,
+0x97c20012, 0x2c440001, 0x801021, 0x54400006,
+0x24050016, 0x10000004, 0x0, 0x24020800,
+0x50820001, 0x2405000e, 0x10a00013, 0x3c52021,
+0x24830009, 0x3c02001f, 0x3442ffff, 0x43102b,
+0x10400003, 0x0, 0x8f420148, 0x621823,
+0x90620000, 0x38430006, 0x2c630001, 0x38420011,
+0x2c420001, 0x621825, 0x10600004, 0x3c020100,
+0x94820002, 0x453821, 0x3c020100, 0x2c21024,
+0x5040000e, 0xafa70064, 0x8fac0064, 0x10ec0008,
+0x3c050007, 0x3c040001, 0x24846908, 0x8fa60064,
+0x34a54000, 0xafa00010, 0xc002b3b, 0xafa00014,
+0x8fab0064, 0x256b0004, 0xafab0064, 0x8f420080,
+0x8fac0064, 0x4c102b, 0x1040002c, 0x32c28000,
+0x10400034, 0x240b0003, 0x32c21000, 0x10400031,
+0xafab005c, 0x1000002e, 0x240c0004, 0x8f420350,
+0x2403ffbf, 0x283a024, 0x24420001, 0xaf420350,
+0x10000173, 0x8f420350, 0x3c020800, 0x2c2b025,
+0x2402ffbf, 0x282a024, 0x8f830128, 0x3c040001,
+0x248468d0, 0x26620001, 0xafa20014, 0xafa30010,
+0x8f860120, 0x8f870124, 0x3c050007, 0xc002b3b,
+0x34a55300, 0x10000162, 0x0, 0x8ea20000,
+0x8ea30004, 0x3c040001, 0x248468e8, 0xafb00010,
+0xafb10014, 0x8ea70018, 0x34a55900, 0xc002b3b,
+0x603021, 0x10000156, 0x0, 0x8f420084,
+0x8fab0064, 0x4b102b, 0x14400007, 0x3c020001,
+0x2c21024, 0x10400004, 0x0, 0x240c0002,
+0xafac005c, 0x8fab0064, 0x11600166, 0x27ac0020,
+0xafac008c, 0x8fab005c, 0x240c0001, 0x556c0021,
+0x240c0002, 0x8f430054, 0x8f420050, 0x1062000b,
+0x274b0054, 0x8f510054, 0x3403ecc0, 0xafab004c,
+0x26220001, 0x304201ff, 0xafa20054, 0x111140,
+0x431021, 0x1000006b, 0x2e2a821, 0x8f420044,
+0x8fac0064, 0x3c040001, 0x248468ac, 0xafac0014,
+0xafa20010, 0x8f460054, 0x8f470050, 0x3c050007,
+0xc002b3b, 0x34a54300, 0x8f430350, 0x2402ffbf,
+0x282a024, 0x24630001, 0xaf430350, 0x10000124,
+0x8f420350, 0x156c001d, 0x0, 0x8f430074,
+0x8f420070, 0x1062000a, 0x274b0074, 0x8f510074,
+0xafab004c, 0x26220001, 0x304203ff, 0xafa20054,
+0x111140, 0x24426cc0, 0x1000004a, 0x2e2a821,
+0x8f420044, 0x8fac0064, 0x3c040001, 0x248468b8,
+0x3c050007, 0xafac0014, 0xafa20010, 0x8f460074,
+0x8f470070, 0x34a54500, 0x240b0001, 0xc002b3b,
+0xafab005c, 0x1000ffc3, 0x0, 0x8f430064,
+0x8f420060, 0x1062001a, 0x274c0064, 0x8f510064,
+0x8fab005c, 0xafac004c, 0x26220001, 0x304200ff,
+0xafa20054, 0x24020004, 0x1562000e, 0x111140,
+0x111180, 0x24420cc0, 0x2e21021, 0xafa20044,
+0x9442002a, 0x8fac0044, 0x8fab0064, 0x4b102b,
+0x10400024, 0x25950020, 0x240c0001, 0x10000021,
+0xa3ac0087, 0x24424cc0, 0x1000001e, 0x2e2a821,
+0x8f420044, 0x8fab0064, 0x3c040001, 0x248468c4,
+0xafab0014, 0xafa20010, 0x8f460064, 0x8f470060,
+0x3c050007, 0xc002b3b, 0x34a54800, 0x3c020008,
+0x2c21024, 0x1440ff61, 0x0, 0x8f420370,
+0x240c0001, 0xafac005c, 0x24420001, 0xaf420370,
+0x1000ff90, 0x8f420370, 0x27a30036, 0x131040,
+0x621821, 0x94620000, 0x441021, 0x1000001f,
+0xa4620000, 0xaebe0018, 0x93a20087, 0x10400084,
+0x9821, 0x8fab0044, 0x8fa40064, 0x8fa3008c,
+0x25620020, 0xafa20028, 0x25620008, 0xafa20030,
+0x25620010, 0xafab002c, 0xafa20034, 0x9562002a,
+0xa7a20038, 0x95620018, 0xa7a2003a, 0x9562001a,
+0xa7a2003c, 0x9562001c, 0xa7a2003e, 0x94620018,
+0x24630002, 0x822023, 0x1880ffdf, 0x26730001,
+0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc,
+0x262102a, 0x14400030, 0x24030001, 0x8f83012c,
+0x10600028, 0x0, 0x8f820124, 0x431023,
+0x22143, 0x58800001, 0x24840040, 0x8f820128,
+0x431023, 0x21943, 0x58600001, 0x24630040,
+0x64102a, 0x54400001, 0x602021, 0xaf4400fc,
+0x8f4200fc, 0x262102a, 0x10400016, 0x24030001,
+0x1000001a, 0x306200ff, 0x8fac008c, 0x101040,
+0x4c1021, 0x94470018, 0x101080, 0x4c1021,
+0xafbe0010, 0x8c420008, 0x3c040001, 0x248468dc,
+0x3c050007, 0x8c430004, 0x8c420000, 0x34a55500,
+0x2003021, 0xc002b3b, 0xafa30014, 0x10000039,
+0x0, 0x8f420334, 0x1821, 0x24420001,
+0xaf420334, 0x8f420334, 0x306200ff, 0x1040ff06,
+0x8021, 0x8f430008, 0x2402fbff, 0x1260002d,
+0x625024, 0x3c0b4000, 0x22b4025, 0x8fb1008c,
+0x2669ffff, 0x2209021, 0x8e420008, 0x96270018,
+0x8c440000, 0x8c450004, 0x56090004, 0x240b0001,
+0x240c0002, 0x10000002, 0xafac0010, 0xafab0010,
+0x16000004, 0xafa80014, 0x8f420008, 0x10000002,
+0xafa20018, 0xafaa0018, 0x8f42010c, 0x3c03021,
+0xafa80098, 0xafa9009c, 0x40f809, 0xafaa00a0,
+0x8fa80098, 0x8fa9009c, 0x8faa00a0, 0x1040ffc2,
+0x3c02001f, 0x96230018, 0x3442ffff, 0x3c3f021,
+0x5e102b, 0x10400003, 0x26310002, 0x8f420148,
+0x3c2f023, 0x26100001, 0x213102b, 0x1440ffda,
+0x26520004, 0x8fb00064, 0x1000001a, 0x0,
+0x96a3000a, 0x8fb00064, 0x70102b, 0x54400001,
+0x608021, 0x8ea40000, 0x8ea50004, 0x8fab005c,
+0x240c0002, 0xafac0010, 0x934305c4, 0xb1700,
+0x10600003, 0x2223025, 0x3c020800, 0xc23025,
+0xafa60014, 0x8f420008, 0xafa20018, 0x8f42010c,
+0x3c03021, 0x40f809, 0x2003821, 0x1040fecb,
+0x3c050007, 0x97ac0076, 0x11800007, 0x96a3000e,
+0x934205c4, 0x14400004, 0x0, 0x97ab007e,
+0x6c1825, 0xa6ab0016, 0x8fac006c, 0x3c02ffff,
+0x1821024, 0x10400003, 0xc1402, 0x34630400,
+0xa6a20014, 0xa6b0000a, 0x8fab0064, 0x560b0006,
+0x3d0f021, 0x34620004, 0xafa00064, 0xa6a2000e,
+0x1000000d, 0xa34005c4, 0x8fac0064, 0x3c02001f,
+0x3442ffff, 0x5e102b, 0x1906023, 0xafac0064,
+0xa6a3000e, 0x240b0001, 0x10400003, 0xa34b05c4,
+0x8f420148, 0x3c2f023, 0x8fab0054, 0x8fac004c,
+0xad8b0000, 0x8fac0064, 0x1580feba, 0x0,
+0x8fab0064, 0x1160001b, 0x0, 0x934205c4,
+0x10400006, 0x0, 0xaf5e00c4, 0xaf4b00c0,
+0x8fac006c, 0x1000000e, 0xaf4c00c8, 0x97ab0076,
+0x1160000b, 0x34038100, 0x8fa20020, 0x8c46000c,
+0xa443000c, 0x97ac007e, 0x8c440004, 0x8c450008,
+0xa44c000e, 0xac440000, 0xac450004, 0xac460008,
+0x8f42034c, 0x24420001, 0xaf42034c, 0x10000010,
+0x8f42034c, 0x8fab006c, 0x3164ffff, 0x2484fffc,
+0x801821, 0x8f440250, 0x8f450254, 0x8f460118,
+0x1021, 0xa32821, 0xa3382b, 0x822021,
+0x872021, 0xaf440250, 0xc0f809, 0xaf450254,
+0x8fbf00c0, 0x8fbe00bc, 0x8fb500b8, 0x8fb300b4,
+0x8fb200b0, 0x8fb100ac, 0x8fb000a8, 0x3e00008,
+0x27bd00c8, 0x3e00008, 0x0, 0x27bdffd8,
+0xafbf0024, 0xafb00020, 0x8f43004c, 0x8f420048,
+0x10620034, 0x0, 0x8f430048, 0x8f42004c,
+0x622023, 0x4820001, 0x24840200, 0x8f430054,
+0x8f42004c, 0x43102b, 0x14400004, 0x24020200,
+0x8f43004c, 0x10000005, 0x431023, 0x8f420054,
+0x8f43004c, 0x431023, 0x2442ffff, 0x405021,
+0x8a102a, 0x54400001, 0x805021, 0x8f49004c,
+0x8f48004c, 0x8f440188, 0x8f45018c, 0x8f46004c,
+0x24071000, 0xafa70010, 0x84140, 0x1001821,
+0x12a4821, 0x313001ff, 0xafb00014, 0x8f470014,
+0x1021, 0x63140, 0xafa70018, 0xa32821,
+0xa3382b, 0x822021, 0x872021, 0x3402ecc0,
+0xc23021, 0x8f420108, 0x2e63021, 0x40f809,
+0xa3940, 0x54400001, 0xaf50004c, 0x8f43004c,
+0x8f420048, 0x14620018, 0x0, 0x8f420000,
+0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x2403fdff, 0x431024, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x10000002,
+0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb00020,
+0x3e00008, 0x27bd0028, 0x3e00008, 0x0,
+0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f43005c,
+0x8f420058, 0x10620049, 0x0, 0x8f430058,
+0x8f42005c, 0x622023, 0x4820001, 0x24840100,
+0x8f430064, 0x8f42005c, 0x43102b, 0x14400004,
+0x24020100, 0x8f43005c, 0x10000005, 0x431023,
+0x8f420064, 0x8f43005c, 0x431023, 0x2442ffff,
+0x403821, 0x87102a, 0x54400001, 0x803821,
+0x8f42005c, 0x471021, 0x305000ff, 0x32c21000,
+0x10400015, 0x24082000, 0x8f49005c, 0x8f440190,
+0x8f450194, 0x8f46005c, 0x73980, 0xafa80010,
+0xafb00014, 0x8f480014, 0x94980, 0x1201821,
+0x1021, 0xa32821, 0xa3482b, 0x822021,
+0x892021, 0x63180, 0xafa80018, 0x8f420108,
+0x10000014, 0x24c60cc0, 0x8f49005c, 0x8f440190,
+0x8f450194, 0x8f46005c, 0x73940, 0xafa80010,
+0xafb00014, 0x8f480014, 0x94940, 0x1201821,
+0x1021, 0xa32821, 0xa3482b, 0x822021,
+0x892021, 0x63140, 0xafa80018, 0x8f420108,
+0x24c64cc0, 0x40f809, 0x2e63021, 0x54400001,
+0xaf50005c, 0x8f43005c, 0x8f420058, 0x14620018,
+0x0, 0x8f420000, 0x10400007, 0x0,
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
+0x10000005, 0x0, 0xaf800048, 0x8f820048,
+0x1040fffd, 0x0, 0x8f820060, 0x2403feff,
+0x431024, 0xaf820060, 0x8f420000, 0x10400003,
+0x0, 0x10000002, 0xaf80004c, 0xaf800048,
+0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028,
+0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
+0xafb00020, 0x8f43006c, 0x8f420068, 0x10620033,
+0x0, 0x8f430068, 0x8f42006c, 0x622023,
+0x4820001, 0x24840400, 0x8f430074, 0x8f42006c,
+0x43102b, 0x14400004, 0x24020400, 0x8f43006c,
+0x10000005, 0x431023, 0x8f420074, 0x8f43006c,
+0x431023, 0x2442ffff, 0x405021, 0x8a102a,
+0x54400001, 0x805021, 0x8f49006c, 0x8f48006c,
+0x8f440198, 0x8f45019c, 0x8f46006c, 0x24074000,
+0xafa70010, 0x84140, 0x1001821, 0x12a4821,
+0x313003ff, 0xafb00014, 0x8f470014, 0x1021,
+0x63140, 0x24c66cc0, 0xafa70018, 0xa32821,
+0xa3382b, 0x822021, 0x872021, 0x8f420108,
+0x2e63021, 0x40f809, 0xa3940, 0x54400001,
+0xaf50006c, 0x8f43006c, 0x8f420068, 0x14620018,
+0x0, 0x8f420000, 0x10400007, 0x0,
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
+0x10000005, 0x0, 0xaf800048, 0x8f820048,
+0x1040fffd, 0x0, 0x8f820060, 0x2403f7ff,
+0x431024, 0xaf820060, 0x8f420000, 0x10400003,
+0x0, 0x10000002, 0xaf80004c, 0xaf800048,
+0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028,
+0x3e00008, 0x0, 0x8f4200fc, 0x3c030001,
+0x8f4400f8, 0x346330c8, 0x24420001, 0xaf4200fc,
+0x8f850128, 0x2e31021, 0x54820004, 0x24820008,
+0x3c020001, 0x34422ec8, 0x2e21021, 0x401821,
+0xaf4300f8, 0xac600000, 0x8f4200f4, 0x14620004,
+0x3c020001, 0x24a20020, 0x1000000f, 0xaf820128,
+0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004,
+0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021,
+0x401821, 0x8c620004, 0x21140, 0xa21021,
+0xaf820128, 0xac600000, 0x8ca30018, 0x30620070,
+0x1040002d, 0x30620020, 0x10400004, 0x3c020010,
+0x2c21024, 0x1040000d, 0x0, 0x30620040,
+0x10400004, 0x3c020020, 0x2c21024, 0x10400007,
+0x0, 0x30620010, 0x1040001f, 0x3c020040,
+0x2c21024, 0x1440001c, 0x0, 0x8f820040,
+0x30420001, 0x14400008, 0x2021, 0x8c030104,
+0x24020001, 0x50620005, 0x24040001, 0x8c020264,
+0x10400003, 0x801021, 0x24040001, 0x801021,
+0x10400006, 0x0, 0x8f42030c, 0x24420001,
+0xaf42030c, 0x10000008, 0x8f42030c, 0x8f820044,
+0x34420004, 0xaf820044, 0x8f420308, 0x24420001,
+0xaf420308, 0x8f420308, 0x3e00008, 0x0,
+0x3e00008, 0x0, 0x27bdff98, 0xafbf0060,
+0xafbe005c, 0xafb50058, 0xafb30054, 0xafb20050,
+0xafb1004c, 0xafb00048, 0x8f4200fc, 0x24420001,
+0xaf4200fc, 0x8f880128, 0x25020020, 0xaf820128,
+0x8d030018, 0x30620070, 0x1040002e, 0x30620020,
+0x10400004, 0x3c020010, 0x2c21024, 0x1040000d,
+0x0, 0x30620040, 0x10400004, 0x3c020020,
+0x2c21024, 0x10400007, 0x0, 0x30620010,
+0x104001a9, 0x3c020040, 0x2c21024, 0x144001a6,
+0x0, 0x8f820040, 0x30420001, 0x14400008,
+0x2021, 0x8c030104, 0x24020001, 0x50620005,
+0x24040001, 0x8c020264, 0x10400003, 0x801021,
+0x24040001, 0x801021, 0x10400006, 0x0,
+0x8f42030c, 0x24420001, 0xaf42030c, 0x10000192,
+0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044,
+0x8f420308, 0x24420001, 0xaf420308, 0x1000018a,
+0x8f420308, 0x30620002, 0x1040014b, 0x3c020800,
+0x8d1e001c, 0x1e5702, 0xafaa0034, 0x950a0016,
+0x3c22024, 0xafaa0024, 0x8faa0034, 0x24020001,
+0x15420006, 0x33deffff, 0x1e1140, 0x3403ecc0,
+0x431021, 0x10000010, 0x2e2a821, 0x24020002,
+0x15420005, 0x24020003, 0x1e1140, 0x24426cc0,
+0x10000009, 0x2e2a821, 0x15420005, 0x1e1180,
+0x1e1140, 0x24424cc0, 0x10000003, 0x2e2a821,
+0x571021, 0x24550ce0, 0x96a2000e, 0x304afffc,
+0x30420400, 0x10400003, 0xafaa002c, 0x100000e1,
+0x8821, 0x10800004, 0x8821, 0x97b10026,
+0x100000dd, 0xa6b10012, 0x8eb30018, 0x966a000c,
+0xa7aa003e, 0x97a5003e, 0x2ca305dd, 0x38a28870,
+0x2c420001, 0x621825, 0x10600015, 0x2021,
+0x32c20800, 0x10400015, 0x24020800, 0x96630014,
+0x14620012, 0x3402aaaa, 0x9663000e, 0x14620007,
+0x2821, 0x96630010, 0x24020300, 0x14620004,
+0xa01021, 0x96620012, 0x2c450001, 0xa01021,
+0x54400006, 0x24040016, 0x10000004, 0x0,
+0x24020800, 0x50a20001, 0x2404000e, 0x108000b9,
+0x2649021, 0x92420000, 0x3042000f, 0x28080,
+0x32c20100, 0x10400020, 0x2501821, 0x3c020020,
+0x43102b, 0x1440000e, 0x2402021, 0x2821,
+0x94820000, 0x24840002, 0xa22821, 0x83102b,
+0x1440fffb, 0x30a2ffff, 0x51c02, 0x622821,
+0x51c02, 0x30a2ffff, 0x10000009, 0x622821,
+0x8f470148, 0x8f420110, 0x102842, 0x3c060020,
+0x40f809, 0xafa80040, 0x3045ffff, 0x8fa80040,
+0x50a00001, 0x3405ffff, 0x8faa002c, 0x354a0002,
+0x10000002, 0xafaa002c, 0x2821, 0x32c20080,
+0x10400090, 0xa6a50010, 0x26430009, 0x3c02001f,
+0x3442ffff, 0x43102b, 0x10400003, 0x0,
+0x8f420148, 0x621823, 0x90660000, 0x30c200ff,
+0x38430006, 0x2c630001, 0x38420011, 0x2c420001,
+0x621825, 0x1060007f, 0x24020800, 0x8821,
+0x97a3003e, 0x1462000f, 0x2602021, 0x96710000,
+0x96620002, 0x96630004, 0x96640006, 0x2228821,
+0x2238821, 0x2248821, 0x96620008, 0x9663000a,
+0x9664000c, 0x2228821, 0x2238821, 0x10000007,
+0x2248821, 0x94820000, 0x24840002, 0x2228821,
+0x92102b, 0x1440fffb, 0x0, 0x111c02,
+0x3222ffff, 0x628821, 0x111c02, 0x3222ffff,
+0x628821, 0x32c20200, 0x10400003, 0x26440006,
+0x1000003e, 0x8021, 0x3c05001f, 0x34a5ffff,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
+0x822023, 0x94820000, 0x30421fff, 0x10400004,
+0x2644000c, 0x96420002, 0x10000030, 0x508023,
+0x96420002, 0x26430014, 0x508023, 0x3c020020,
+0x43102b, 0x1440000a, 0xd08021, 0x9642000c,
+0x2028021, 0x9642000e, 0x96430010, 0x96440012,
+0x2028021, 0x2038021, 0x10000020, 0x2048021,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
+0x822023, 0x94820000, 0x24840002, 0x2028021,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
+0x822023, 0x94820000, 0x24840002, 0x2028021,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
+0x822023, 0x94820000, 0x24840002, 0x2028021,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
+0x822023, 0x94820000, 0x2028021, 0x3c020100,
+0x2c21024, 0x1040000e, 0x0, 0x8faa002c,
+0x31420004, 0x1040000a, 0x0, 0x9504000e,
+0x2642021, 0xc003eec, 0x2484fffc, 0x3042ffff,
+0x2228821, 0x111c02, 0x3222ffff, 0x628821,
+0x8faa0024, 0x1518823, 0x111402, 0x2228821,
+0x2308821, 0x111402, 0x2228821, 0x3231ffff,
+0x52200001, 0x3411ffff, 0x8faa002c, 0x354a0001,
+0xafaa002c, 0xa6b10012, 0x97aa002e, 0xa6aa000e,
+0x8faa002c, 0x31420004, 0x10400002, 0x24091000,
+0x34098000, 0x8f480044, 0x8f4401a0, 0x8f4501a4,
+0xafa90010, 0x8f490044, 0x84140, 0x1001821,
+0xafa90014, 0x8f48000c, 0x2a03021, 0x24070020,
+0xafa80018, 0x8f48010c, 0x1021, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x1440000b, 0x0, 0x8f820128, 0x3c040001,
+0x24846914, 0xafbe0014, 0xafa20010, 0x8f860124,
+0x8f870120, 0x3c050007, 0xc002b3b, 0x34a59920,
+0x8f420368, 0x2442ffff, 0xaf420368, 0x8f420044,
+0x8f430088, 0x24420001, 0x431024, 0xaf420044,
+0x8faa0034, 0x8f440368, 0x24020001, 0x15420006,
+0x24020002, 0x8f42035c, 0x2442ffff, 0xaf42035c,
+0x10000049, 0x8f42035c, 0x15420006, 0x0,
+0x8f420364, 0x2442ffff, 0xaf420364, 0x10000042,
+0x8f420364, 0x8f420360, 0x2442ffff, 0xaf420360,
+0x1000003d, 0x8f420360, 0x30621000, 0x10400005,
+0x30628000, 0x8f420078, 0x24420001, 0x10000036,
+0xaf420078, 0x10400034, 0x0, 0x8f420078,
+0x24420001, 0xaf420078, 0x8c030240, 0x43102b,
+0x1440002d, 0x24070008, 0x8f440168, 0x8f45016c,
+0x8f430044, 0x8f48000c, 0x8f860120, 0x24020040,
+0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c,
+0x40f809, 0x24c6001c, 0x14400011, 0x24020001,
+0x3c010001, 0x370821, 0xa02240f2, 0x8f820124,
+0xafa20010, 0x8f820128, 0x3c040001, 0x2484688c,
+0xafa20014, 0x8f460044, 0x8f870120, 0x3c050009,
+0xc002b3b, 0x34a51300, 0x1000000b, 0x0,
+0x8f420304, 0x24420001, 0xaf420304, 0x8f420304,
+0x8f420044, 0xaf42007c, 0x3c010001, 0x370821,
+0xa02040f2, 0xaf400078, 0x8f420318, 0x24420001,
+0xaf420318, 0x8f420318, 0x8fbf0060, 0x8fbe005c,
+0x8fb50058, 0x8fb30054, 0x8fb20050, 0x8fb1004c,
+0x8fb00048, 0x3e00008, 0x27bd0068, 0x3e00008,
+0x0, 0x0, 0x0, 0x8f42013c,
+0xaf8200c0, 0x8f42013c, 0xaf8200c4, 0x8f42013c,
+0xaf8200c8, 0x8f420138, 0xaf8200d0, 0x8f420138,
+0xaf8200d4, 0x8f420138, 0x3e00008, 0xaf8200d8,
+0x27bdffe0, 0x27840208, 0x24050200, 0xafbf0018,
+0xc002bbf, 0x24060008, 0x8c020204, 0xc004012,
+0xaf820210, 0x3c020001, 0x8c426d94, 0x30420002,
+0x1040000e, 0x2021, 0x8c060248, 0x24020002,
+0x3c010001, 0xac226d98, 0xc005104, 0x24050002,
+0x2021, 0x8c060248, 0x24020001, 0x3c010001,
+0xac226d98, 0x10000011, 0x24050001, 0x8c060248,
+0x24020004, 0x3c010001, 0xac226d98, 0xc005104,
+0x24050004, 0x3c020001, 0x8c426d94, 0x30420001,
+0x10400008, 0x24020001, 0x3c010001, 0xac226d98,
+0x2021, 0x24050001, 0x3c06601b, 0xc005104,
+0x0, 0x3c040001, 0x248469d0, 0x8f420150,
+0x8f430154, 0x3c050008, 0x8f460158, 0x21640,
+0x31940, 0x34630403, 0x431025, 0x633c0,
+0x461025, 0xaf82021c, 0xafa00010, 0xafa00014,
+0x8f86021c, 0x34a50200, 0xc002b3b, 0x3821,
+0x3c010001, 0xac206d90, 0x3c010001, 0xac206da8,
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0,
+0x3c050008, 0x34a50300, 0xafbf0018, 0xafa00010,
+0xafa00014, 0x8f860200, 0x3c040001, 0x248469dc,
+0xc002b3b, 0x3821, 0x8f420410, 0x24420001,
+0xaf420410, 0x8f420410, 0x8fbf0018, 0x3e00008,
+0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb1001c,
+0xafb00018, 0x8f4203a4, 0x24420001, 0xaf4203a4,
+0x8f4203a4, 0x8f900220, 0x8f8200e0, 0xafa20010,
+0x8f8200e4, 0xafa20014, 0x8f8600c4, 0x8f8700c8,
+0x3c040001, 0x248469e8, 0xc002b3b, 0x2002821,
+0x3c044000, 0x2041024, 0x504000b4, 0x3c040100,
+0x8f4203bc, 0x24420001, 0xaf4203bc, 0x8f4203bc,
+0x8f8700c4, 0x8f8300c8, 0x8f420148, 0x671823,
+0x43102b, 0x10400003, 0x0, 0x8f420148,
+0x621821, 0x10600005, 0x0, 0x8f42014c,
+0x43102b, 0x1040000b, 0x0, 0x8f8200e0,
+0x8f430124, 0xaf42011c, 0xaf430114, 0x8f820220,
+0x3c0308ff, 0x3463fffb, 0x431024, 0x100000ce,
+0x441025, 0x8f820220, 0x3c0308ff, 0x3463ffff,
+0x431024, 0x34420004, 0xaf820220, 0x8f8200e0,
+0x8f430124, 0xaf42011c, 0xaf430114, 0x8f8600c8,
+0x8f840120, 0x8f830124, 0x10000005, 0x2821,
+0x14620002, 0x24620020, 0x27624800, 0x401821,
+0x1064000c, 0x30a200ff, 0x8c620018, 0x30420003,
+0x1040fff7, 0x27624fe0, 0x8f4203d0, 0x24050001,
+0x24420001, 0xaf4203d0, 0x8f4203d0, 0x8c660008,
+0x30a200ff, 0x14400058, 0x0, 0x934205c4,
+0x14400055, 0x0, 0x8f8700c4, 0x8f8800e0,
+0x8f8400e4, 0x2402fff8, 0x1024024, 0x1041023,
+0x218c3, 0x4620001, 0x24630200, 0x10600005,
+0x24020001, 0x10620009, 0x0, 0x1000001f,
+0x0, 0x8f4203c0, 0xe03021, 0x24420001,
+0xaf4203c0, 0x10000040, 0x8f4203c0, 0x8f4203c4,
+0x24420001, 0xaf4203c4, 0x8c860000, 0x8f420148,
+0x8f4303c4, 0xe61823, 0x43102b, 0x10400004,
+0x2c62233f, 0x8f420148, 0x621821, 0x2c62233f,
+0x14400031, 0x0, 0x8f42020c, 0x24420001,
+0xaf42020c, 0x8f42020c, 0xe03021, 0x24820008,
+0xaf8200e4, 0x10000028, 0xaf8200e8, 0x8f4203c8,
+0x24420001, 0xaf4203c8, 0x8f4203c8, 0x8c850000,
+0x8f420148, 0xa71823, 0x43102b, 0x10400003,
+0x0, 0x8f420148, 0x621821, 0x8f42014c,
+0x43102b, 0x5440000a, 0xa03021, 0x8f42020c,
+0x24420001, 0xaf42020c, 0x8f42020c, 0x24820008,
+0xaf8200e4, 0x8f8400e4, 0x1488ffec, 0xaf8400e8,
+0x1488000d, 0x27623000, 0x14820002, 0x2482fff8,
+0x27623ff8, 0x94430006, 0x3c02001f, 0x3442ffff,
+0xc33021, 0x46102b, 0x10400003, 0x0,
+0x8f420148, 0xc23023, 0xaf8600c8, 0x8f8300c4,
+0x8f420148, 0xc31823, 0x43102b, 0x10400003,
+0x0, 0x8f420148, 0x621821, 0x10600005,
+0x0, 0x8f42014c, 0x43102b, 0x50400008,
+0x3c02fdff, 0x8f820220, 0x3c0308ff, 0x3463fffb,
+0x431024, 0x3c034000, 0x1000003f, 0x431025,
+0x8f4303cc, 0x3442ffff, 0x282a024, 0x24630001,
+0xaf4303cc, 0x10000039, 0x8f4203cc, 0x2041024,
+0x1040000e, 0x3c110200, 0x8f4203a8, 0x24420001,
+0xaf4203a8, 0x8f4203a8, 0x8f820220, 0x3c0308ff,
+0x3463ffff, 0x431024, 0x441025, 0xc003daf,
+0xaf820220, 0x10000029, 0x0, 0x2111024,
+0x50400008, 0x3c110400, 0x8f4203ac, 0x24420001,
+0xaf4203ac, 0xc003daf, 0x8f4203ac, 0x10000019,
+0x0, 0x2111024, 0x1040001c, 0x0,
+0x8f830224, 0x24021402, 0x14620009, 0x3c050008,
+0x3c040001, 0x248469f4, 0xafa00010, 0xafa00014,
+0x8f860224, 0x34a50500, 0xc002b3b, 0x3821,
+0x8f4203b0, 0x24420001, 0xaf4203b0, 0x8f4203b0,
+0x8f820220, 0x2002021, 0x34420002, 0xc004e9c,
+0xaf820220, 0x8f820220, 0x3c0308ff, 0x3463ffff,
+0x431024, 0x511025, 0xaf820220, 0x8fbf0020,
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028,
+0x3e00008, 0x0, 0x3c020001, 0x8c426da8,
+0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040,
+0xafb3003c, 0xafb20038, 0xafb10034, 0x1040000f,
+0xafb00030, 0x3c040001, 0x24846a00, 0x3c050008,
+0xafa00010, 0xafa00014, 0x8f860220, 0x34a50600,
+0x24020001, 0x3c010001, 0xac206da8, 0x3c010001,
+0xac226d9c, 0xc002b3b, 0x3821, 0x3c037fff,
+0x8c020268, 0x3463ffff, 0x3c04fdff, 0x431024,
+0xac020268, 0x8f420004, 0x3484ffff, 0x30420002,
+0x10400092, 0x284a024, 0x3c040600, 0x34842000,
+0x8f420004, 0x2821, 0x2403fffd, 0x431024,
+0xaf420004, 0xafa40020, 0x8f5e0018, 0x27aa0020,
+0x240200ff, 0x13c20002, 0xafaa002c, 0x27c50001,
+0x8c020228, 0xa09021, 0x1642000e, 0x1e38c0,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x24846998, 0x3c050009,
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d,
+0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024,
+0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b,
+0x9821, 0xe08821, 0x263504c0, 0x8f440178,
+0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010,
+0xafb20014, 0x8f48000c, 0x1021, 0x2f53021,
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x54400006, 0x24130001, 0x8f820054, 0x2021023,
+0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff,
+0x54400017, 0xaf520018, 0x8f420378, 0x24420001,
+0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
+0xafa20010, 0x8f820124, 0x3c040001, 0x248469a4,
+0x3c050009, 0xafa20014, 0x8d460000, 0x10000035,
+0x34a50600, 0x8f420308, 0x24130001, 0x24420001,
+0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x10400016, 0x9821, 0x3c150020,
+0x24110010, 0x8f42000c, 0x8f440160, 0x8f450164,
+0x8f860120, 0xafb10010, 0xafb20014, 0x551025,
+0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
+0x24c6001c, 0x1440ffe3, 0x0, 0x8f820054,
+0x2021023, 0x2c4203e9, 0x1440ffee, 0x0,
+0x326200ff, 0x14400011, 0x0, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
+0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001,
+0x248469ac, 0x3c050009, 0xafa20014, 0x8d460000,
+0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202ec,
+0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8fbf0048,
+0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038,
+0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050,
+0x3c020001, 0x8c426da8, 0x27bdffe0, 0x1440000d,
+0xafbf0018, 0x3c040001, 0x24846a0c, 0x3c050008,
+0xafa00010, 0xafa00014, 0x8f860220, 0x34a50700,
+0x24020001, 0x3c010001, 0xac226da8, 0xc002b3b,
+0x3821, 0x3c020004, 0x2c21024, 0x10400007,
+0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff,
+0x431024, 0x34420008, 0xaf820220, 0x3c050001,
+0x8ca56d98, 0x24020001, 0x14a20007, 0x2021,
+0xc00529b, 0x24050001, 0xac02026c, 0x8c03026c,
+0x10000006, 0x3c020007, 0xc00529b, 0x2021,
+0xac020268, 0x8c030268, 0x3c020007, 0x621824,
+0x3c020002, 0x5062000d, 0x3c0205f5, 0x43102b,
+0x14400006, 0x3c020004, 0x3c020001, 0x10620009,
+0x3c020098, 0x1000000b, 0x0, 0x14620009,
+0x3c023b9a, 0x10000004, 0x3442ca00, 0x10000002,
+0x3442e100, 0x34429680, 0xaf4201fc, 0x8f4201fc,
+0xaee20064, 0x8fbf0018, 0x3e00008, 0x27bd0020,
+0x0, 0x0, 0x0, 0x86102b,
+0x50400001, 0x872023, 0xc41023, 0x24843,
+0x125102b, 0x1040001b, 0x91040, 0x824021,
+0x88102b, 0x10400007, 0x1821, 0x94820000,
+0x24840002, 0x621821, 0x88102b, 0x1440fffb,
+0x0, 0x602021, 0xc73023, 0xa91023,
+0x21040, 0xc22821, 0xc5102b, 0x10400007,
+0x1821, 0x94c20000, 0x24c60002, 0x621821,
+0xc5102b, 0x1440fffb, 0x0, 0x1000000d,
+0x832021, 0x51040, 0x822821, 0x85102b,
+0x10400007, 0x1821, 0x94820000, 0x24840002,
+0x621821, 0x85102b, 0x1440fffb, 0x0,
+0x602021, 0x41c02, 0x3082ffff, 0x622021,
+0x41c02, 0x3082ffff, 0x622021, 0x3e00008,
+0x3082ffff, 0x3e00008, 0x0, 0x802821,
+0x30a20001, 0x1040002b, 0x3c03001f, 0x3463ffff,
+0x24a20004, 0x62102b, 0x54400007, 0x65102b,
+0x90a20001, 0x90a40003, 0x90a30000, 0x90a50002,
+0x1000002a, 0x441021, 0x10400003, 0x0,
+0x8f420148, 0xa22823, 0x90a40000, 0x24a50001,
+0x65102b, 0x10400003, 0x0, 0x8f420148,
+0xa22823, 0x90a20000, 0x24a50001, 0x21200,
+0x822021, 0x65102b, 0x10400003, 0x0,
+0x8f420148, 0xa22823, 0x90a20000, 0x24a50001,
+0x822021, 0x65102b, 0x10400003, 0x0,
+0x8f420148, 0xa22823, 0x90a20000, 0x1000002d,
+0x21200, 0x3463ffff, 0x24a20004, 0x62102b,
+0x5440000a, 0x65102b, 0x90a20000, 0x90a40002,
+0x90a30001, 0x90a50003, 0x441021, 0x21200,
+0x651821, 0x10000020, 0x432021, 0x10400003,
+0x0, 0x8f420148, 0xa22823, 0x90a20000,
+0x24a50001, 0x22200, 0x65102b, 0x10400003,
+0x0, 0x8f420148, 0xa22823, 0x90a20000,
+0x24a50001, 0x822021, 0x65102b, 0x10400003,
+0x0, 0x8f420148, 0xa22823, 0x90a20000,
+0x24a50001, 0x21200, 0x822021, 0x65102b,
+0x10400003, 0x0, 0x8f420148, 0xa22823,
+0x90a20000, 0x822021, 0x41c02, 0x3082ffff,
+0x622021, 0x41c02, 0x3082ffff, 0x622021,
+0x3e00008, 0x3082ffff, 0x0, 0x8f820220,
+0x34420002, 0xaf820220, 0x3c020002, 0x8c428ff8,
+0x30424000, 0x10400054, 0x24040001, 0x8f820200,
+0x24067fff, 0x8f830200, 0x30450002, 0x2402fffd,
+0x621824, 0xaf830200, 0xaf840204, 0x8f830054,
+0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
+0x621023, 0x2c420002, 0x1440fffc, 0x0,
+0x8f820224, 0x1444004d, 0x42040, 0xc4102b,
+0x1040fff1, 0x0, 0x8f820200, 0x451025,
+0xaf820200, 0x8f820220, 0x34428000, 0xaf820220,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x8f820220, 0x3c030004, 0x431024,
+0x1440000f, 0x0, 0x8f820220, 0x3c03ffff,
+0x34637fff, 0x431024, 0xaf820220, 0x8f830054,
+0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
+0x621023, 0x2c420002, 0x1440fffc, 0x0,
+0x8f820220, 0x3c030004, 0x431024, 0x1440000d,
+0x0, 0x8f820220, 0x34428000, 0xaf820220,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x8f820220, 0x3c030004, 0x431024,
+0x1040001b, 0x1021, 0x8f830220, 0x24020001,
+0x10000015, 0x3c04f700, 0x8f820220, 0x3c04f700,
+0x441025, 0xaf820220, 0x8f820220, 0x2403fffd,
+0x431024, 0xaf820220, 0x8f820220, 0x3c030300,
+0x431024, 0x14400003, 0x0, 0x10000008,
+0x1021, 0x8f820220, 0x34420002, 0xaf820220,
+0x8f830220, 0x24020001, 0x641825, 0xaf830220,
+0x3e00008, 0x0, 0x2021, 0x3c050100,
+0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220,
+0x27625000, 0xaf8200c0, 0x27625000, 0xaf8200c4,
+0x27625000, 0xaf8200c8, 0x27625000, 0xaf8200d0,
+0x27625000, 0xaf8200d4, 0x27625000, 0xaf8200d8,
+0x27623000, 0xaf8200e0, 0x27623000, 0xaf8200e4,
+0x27623000, 0xaf8200e8, 0x27622800, 0xaf8200f0,
+0x27622800, 0xaf8200f4, 0x27622800, 0xaf8200f8,
+0x418c0, 0x24840001, 0x3631021, 0xac453004,
+0x3631021, 0xac403000, 0x28820200, 0x1440fff9,
+0x418c0, 0x2021, 0x418c0, 0x24840001,
+0x3631021, 0xac402804, 0x3631021, 0xac402800,
+0x28820100, 0x1440fff9, 0x418c0, 0xaf80023c,
+0x24030080, 0x24040100, 0xac600000, 0x24630004,
+0x64102b, 0x5440fffd, 0xac600000, 0x8f830040,
+0x3c02f000, 0x621824, 0x3c025000, 0x1062000c,
+0x43102b, 0x14400006, 0x3c026000, 0x3c024000,
+0x10620008, 0x24020800, 0x10000008, 0x0,
+0x10620004, 0x24020800, 0x10000004, 0x0,
+0x24020700, 0x3c010001, 0xac226dac, 0x3e00008,
+0x0, 0x3c020001, 0x8c426dbc, 0x27bdffd0,
+0xafbf002c, 0xafb20028, 0xafb10024, 0xafb00020,
+0x3c010001, 0x10400005, 0xac206d94, 0xc004d9e,
+0x0, 0x3c010001, 0xac206dbc, 0x8f830054,
+0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
+0x621023, 0x2c420065, 0x1440fffc, 0x0,
+0xc004db9, 0x0, 0x24040001, 0x2821,
+0x27a60018, 0x34028000, 0xc0045be, 0xa7a20018,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
+0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
+0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
+0x24040001, 0x3c060001, 0x24c66f24, 0xc00457c,
+0x24050002, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630064, 0x8f820054, 0x621023, 0x2c420065,
+0x1440fffc, 0x24040001, 0x24050003, 0x3c100001,
+0x26106f26, 0xc00457c, 0x2003021, 0x97a60018,
+0x3c070001, 0x94e76f24, 0x3c040001, 0x24846ae0,
+0xafa00014, 0x96020000, 0x3c05000d, 0x34a50100,
+0xc002b3b, 0xafa20010, 0x97a20018, 0x1040004d,
+0x24036040, 0x96020000, 0x3042fff0, 0x1443000c,
+0x24020020, 0x3c030001, 0x94636f24, 0x1462000b,
+0x24027830, 0x24020003, 0x3c010001, 0xac226d94,
+0x24020005, 0x3c010001, 0x1000003f, 0xac226f34,
+0x3c030001, 0x94636f24, 0x24027830, 0x1462000c,
+0x24030010, 0x3c020001, 0x94426f26, 0x3042fff0,
+0x14430007, 0x24020003, 0x3c010001, 0xac226d94,
+0x24020006, 0x3c010001, 0x1000002f, 0xac226f34,
+0x3c020001, 0x8c426d94, 0x3c030001, 0x94636f24,
+0x34420001, 0x3c010001, 0xac226d94, 0x24020015,
+0x1462000b, 0x0, 0x3c020001, 0x94426f26,
+0x3042fff0, 0x3843f420, 0x2c630001, 0x3842f430,
+0x2c420001, 0x621825, 0x1460001b, 0x24020003,
+0x3c030001, 0x94636f24, 0x24027810, 0x14620016,
+0x24020002, 0x3c020001, 0x94426f26, 0x3042fff0,
+0x14400011, 0x24020002, 0x1000000f, 0x24020004,
+0x3c020001, 0x8c426d94, 0x34420008, 0x3c010001,
+0xac226d94, 0x1000005e, 0x24020004, 0x3c020001,
+0x8c426d94, 0x34420004, 0x3c010001, 0x100000af,
+0xac226d94, 0x24020001, 0x3c010001, 0xac226f40,
+0x3c020001, 0x8c426d94, 0x30420002, 0x144000b2,
+0x3c09fff0, 0x24020e00, 0xaf820238, 0x8f840054,
+0x8f820054, 0x24030008, 0x3c010001, 0xac236d98,
+0x10000002, 0x248401f4, 0x8f820054, 0x821023,
+0x2c4201f5, 0x1440fffc, 0x3c0200c8, 0x344201fb,
+0xaf820238, 0x8f830054, 0x8f820054, 0x10000002,
+0x246301f4, 0x8f820054, 0x621023, 0x2c4201f5,
+0x1440fffc, 0x8021, 0x24120001, 0x24110009,
+0xc004482, 0x0, 0x3c010001, 0xac326db4,
+0xc004547, 0x0, 0x3c020001, 0x8c426db4,
+0x1451fffb, 0x3c0200c8, 0x344201f6, 0xaf820238,
+0x8f830054, 0x8f820054, 0x10000002, 0x2463000a,
+0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc,
+0x0, 0x8f820220, 0x24040001, 0x34420002,
+0xaf820220, 0x8f830200, 0x24057fff, 0x2402fffd,
+0x621824, 0xaf830200, 0xaf840204, 0x8f830054,
+0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
+0x621023, 0x2c420002, 0x1440fffc, 0x0,
+0x8f820224, 0x14440005, 0x34028000, 0x42040,
+0xa4102b, 0x1040fff0, 0x34028000, 0x1082ffa0,
+0x26100001, 0x2e020014, 0x1440ffcd, 0x24020004,
+0x3c010001, 0xac226d98, 0x8021, 0x24120009,
+0x3c11ffff, 0x36313f7f, 0xc004482, 0x0,
+0x24020001, 0x3c010001, 0xac226db4, 0xc004547,
+0x0, 0x3c020001, 0x8c426db4, 0x1452fffb,
+0x0, 0x8f820044, 0x511024, 0x34425080,
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
+0x2463000a, 0x8f820054, 0x621023, 0x2c42000b,
+0x1440fffc, 0x0, 0x8f820044, 0x511024,
+0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054,
+0x10000002, 0x2463000a, 0x8f820054, 0x621023,
+0x2c42000b, 0x1440fffc, 0x0, 0x8f820220,
+0x3c03f700, 0x431025, 0xaf820220, 0x8f830054,
+0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
+0x621023, 0x2c420065, 0x1440fffc, 0x0,
+0x8f820220, 0x24040001, 0x34420002, 0xaf820220,
+0x8f830200, 0x24057fff, 0x2402fffd, 0x621824,
+0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054,
+0x10000002, 0x24630001, 0x8f820054, 0x621023,
+0x2c420002, 0x1440fffc, 0x0, 0x8f820224,
+0x14440005, 0x34028000, 0x42040, 0xa4102b,
+0x1040fff0, 0x34028000, 0x1082ff50, 0x26100001,
+0x2e020064, 0x1440ffb0, 0x0, 0x3c020001,
+0x8c426d94, 0x30420004, 0x14400007, 0x3c09fff0,
+0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024,
+0xaf820044, 0x3c09fff0, 0x3529bdc0, 0x3c060001,
+0x8cc66d94, 0x3c040001, 0x24846ae0, 0x24020001,
+0x3c010001, 0xac226d9c, 0x8f820054, 0x3c070001,
+0x8ce76f40, 0x3c030001, 0x94636f24, 0x3c080001,
+0x95086f26, 0x3c05000d, 0x34a50100, 0x3c010001,
+0xac206d98, 0x491021, 0x3c010001, 0xac226f30,
+0xafa30010, 0xc002b3b, 0xafa80014, 0x8fbf002c,
+0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008,
+0x27bd0030, 0x27bdffe8, 0x3c050001, 0x8ca56d98,
+0x24060004, 0x24020001, 0x14a20014, 0xafbf0010,
+0x3c020002, 0x8c428ffc, 0x30428000, 0x10400005,
+0x3c04000f, 0x3c030001, 0x8c636f40, 0x10000005,
+0x34844240, 0x3c040004, 0x3c030001, 0x8c636f40,
+0x348493e0, 0x24020005, 0x14620016, 0x0,
+0x3c04003d, 0x10000013, 0x34840900, 0x3c020002,
+0x8c428ff8, 0x30428000, 0x10400005, 0x3c04001e,
+0x3c030001, 0x8c636f40, 0x10000005, 0x34848480,
+0x3c04000f, 0x3c030001, 0x8c636f40, 0x34844240,
+0x24020005, 0x14620003, 0x0, 0x3c04007a,
+0x34841200, 0x3c020001, 0x8c426f30, 0x8f830054,
+0x441021, 0x431023, 0x44102b, 0x1440004c,
+0x0, 0x3c020001, 0x8c426da0, 0x14400048,
+0x0, 0x3c010001, 0x10c00025, 0xac206db0,
+0x3c090001, 0x8d296d94, 0x24070001, 0x3c044000,
+0x3c080002, 0x25088ffc, 0x250afffc, 0x52842,
+0x14a00002, 0x24c6ffff, 0x24050008, 0xa91024,
+0x10400010, 0x0, 0x14a70008, 0x0,
+0x8d020000, 0x441024, 0x1040000a, 0x0,
+0x3c010001, 0x10000007, 0xac256db0, 0x8d420000,
+0x441024, 0x10400003, 0x0, 0x3c010001,
+0xac276db0, 0x3c020001, 0x8c426db0, 0x6182b,
+0x2c420001, 0x431024, 0x5440ffe5, 0x52842,
+0x8f820054, 0x3c030001, 0x8c636db0, 0x3c010001,
+0xac226f30, 0x1060003b, 0x24020005, 0x3c030001,
+0x8c636f40, 0x3c010001, 0xac256d98, 0x14620012,
+0x24020001, 0x3c020002, 0x8c428ff8, 0x3c032000,
+0x34635000, 0x431024, 0x14400006, 0x24020001,
+0x3c010001, 0xac206f1c, 0x3c010001, 0xac226d98,
+0x24020001, 0x3c010001, 0xac226e24, 0x3c010001,
+0xac226da4, 0x24020001, 0x3c010001, 0xac226d9c,
+0x3c020001, 0x8c426db0, 0x1040001e, 0x0,
+0x3c020001, 0x8c426d9c, 0x10400008, 0x24020001,
+0x3c010001, 0xac206d9c, 0xaee204b8, 0x3c010001,
+0xac206e1c, 0x3c010001, 0xac226dd4, 0x8ee304b8,
+0x24020008, 0x10620005, 0x24020001, 0xc004239,
+0x0, 0x1000000b, 0x0, 0x3c030001,
+0x8c636d98, 0x10620007, 0x2402000e, 0x3c030002,
+0x8c638f90, 0x10620003, 0x0, 0xc004e9c,
+0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018,
+0x27bdffe0, 0x3c03fdff, 0x3c040001, 0x8c846d98,
+0x3c020001, 0x8c426dc0, 0x3463ffff, 0x283a024,
+0x14820006, 0xafbf0018, 0x8ee304b8, 0x3c020001,
+0x8c426dc4, 0x10620006, 0x0, 0x8ee204b8,
+0x3c010001, 0xac246dc0, 0x3c010001, 0xac226dc4,
+0x3c030001, 0x8c636d98, 0x24020002, 0x1062019c,
+0x2c620003, 0x10400005, 0x24020001, 0x1062000a,
+0x0, 0x10000226, 0x0, 0x24020004,
+0x106200b6, 0x24020008, 0x1062010a, 0x24020001,
+0x1000021f, 0x0, 0x8ee204b8, 0x2443ffff,
+0x2c620008, 0x1040021c, 0x31080, 0x3c010001,
+0x220821, 0x8c226af8, 0x400008, 0x0,
+0x3c030001, 0x8c636f40, 0x24020005, 0x14620010,
+0x0, 0x3c020001, 0x8c426da4, 0x10400008,
+0x24020003, 0xc004482, 0x0, 0x24020002,
+0xaee204b8, 0x3c010001, 0x10000002, 0xac206da4,
+0xaee204b8, 0x3c010001, 0x10000203, 0xac206d30,
+0xc004482, 0x0, 0x3c020001, 0x8c426da4,
+0x3c010001, 0xac206d30, 0x1440017a, 0x24020002,
+0x1000019d, 0x24020007, 0x3c030001, 0x8c636f40,
+0x24020005, 0x14620003, 0x24020001, 0x3c010001,
+0xac226dd0, 0xc0045ff, 0x0, 0x3c030001,
+0x8c636dd0, 0x10000174, 0x24020011, 0x3c050001,
+0x8ca56d98, 0x3c060002, 0x8cc68ffc, 0xc005104,
+0x2021, 0x24020005, 0x3c010001, 0xac206da4,
+0x100001e1, 0xaee204b8, 0x3c040001, 0x24846aec,
+0x3c05000f, 0x34a50100, 0x3021, 0x3821,
+0xafa00010, 0xc002b3b, 0xafa00014, 0x100001d6,
+0x0, 0x8f820220, 0x3c030004, 0x431024,
+0x14400175, 0x24020007, 0x8f830054, 0x3c020001,
+0x8c426f28, 0x2463d8f0, 0x431023, 0x2c422710,
+0x14400003, 0x24020001, 0x3c010001, 0xac226d9c,
+0x3c020002, 0x8c428ffc, 0x30425000, 0x104001c2,
+0x0, 0x8f820220, 0x30428000, 0x1040017d,
+0x0, 0x10000175, 0x0, 0x3c050001,
+0x8ca56d98, 0xc00529b, 0x2021, 0xc00551b,
+0x2021, 0x3c030002, 0x8c638ff4, 0x46101b0,
+0x24020001, 0x3c020008, 0x621024, 0x10400006,
+0x0, 0x8f820214, 0x3c03ffff, 0x431024,
+0x10000005, 0x3442251f, 0x8f820214, 0x3c03ffff,
+0x431024, 0x3442241f, 0xaf820214, 0x8f820220,
+0x3c030200, 0x34420002, 0xaf820220, 0x24020008,
+0xaee204b8, 0x8f820220, 0x283a025, 0x3c030004,
+0x431024, 0x14400016, 0x0, 0x3c020002,
+0x8c428ffc, 0x30425000, 0x1040000d, 0x0,
+0x8f820220, 0x30428000, 0x10400006, 0x0,
+0x8f820220, 0x3c03ffff, 0x34637fff, 0x10000003,
+0x431024, 0x8f820220, 0x34428000, 0xaf820220,
+0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
+0x3c030001, 0x8c636f40, 0x24020005, 0x1462000a,
+0x0, 0x3c020001, 0x94426f26, 0x24429fbc,
+0x2c420004, 0x10400004, 0x24040018, 0x24050002,
+0xc004ddb, 0x24060020, 0xc003e6d, 0x0,
+0x3c010001, 0x10000170, 0xac206e20, 0x8ee204b8,
+0x2443ffff, 0x2c620008, 0x1040016b, 0x31080,
+0x3c010001, 0x220821, 0x8c226b18, 0x400008,
+0x0, 0xc004547, 0x0, 0x3c030001,
+0x8c636db4, 0x100000e8, 0x24020009, 0x3c020002,
+0x8c428ff8, 0x30424000, 0x10400004, 0x0,
+0x8f820044, 0x10000006, 0x3442f080, 0x8f820044,
+0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080,
+0xaf820044, 0x8f830054, 0x100000ea, 0x24020004,
+0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0,
+0x431023, 0x2c422710, 0x14400147, 0x24020005,
+0x100000d8, 0x0, 0x8f820220, 0x3c03f700,
+0x431025, 0xaf820220, 0xaf800204, 0x3c010002,
+0x100000d6, 0xac208fe0, 0x8f830054, 0x3c020001,
+0x8c426f28, 0x2463fff6, 0x431023, 0x2c42000a,
+0x14400135, 0x24020007, 0x100000d7, 0x0,
+0xc003f50, 0x0, 0x1040012d, 0x24020001,
+0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c846f1c,
+0x431024, 0x3442251f, 0xaf820214, 0x24020008,
+0x10800005, 0xaee204b8, 0x3c020001, 0x8c426e44,
+0x10400064, 0x24020001, 0x8f820220, 0x3c030008,
+0x431024, 0x1040006a, 0x3c020200, 0x10000078,
+0x0, 0x8ee204b8, 0x2443ffff, 0x2c620007,
+0x10400115, 0x31080, 0x3c010001, 0x220821,
+0x8c226b38, 0x400008, 0x0, 0xc003daf,
+0x0, 0x3c010001, 0xac206d9c, 0xaf800204,
+0x3c010002, 0xc004482, 0xac208fe0, 0x24020001,
+0x3c010001, 0xac226db4, 0x24020002, 0x10000102,
+0xaee204b8, 0xc004547, 0x0, 0x3c030001,
+0x8c636db4, 0x10000084, 0x24020009, 0x3c020002,
+0x8c428ff8, 0x30424000, 0x10400003, 0x3c0200c8,
+0x10000002, 0x344201f6, 0x344201fe, 0xaf820238,
+0x8f830054, 0x1000008b, 0x24020004, 0x8f830054,
+0x3c020001, 0x8c426f28, 0x2463d8f0, 0x431023,
+0x2c422710, 0x144000e8, 0x24020005, 0x10000079,
+0x0, 0x8f820220, 0x3c03f700, 0x431025,
+0xaf820220, 0xaf800204, 0x3c010002, 0x10000077,
+0xac208fe0, 0x8f830054, 0x3c020001, 0x8c426f28,
+0x2463fff6, 0x431023, 0x2c42000a, 0x144000d6,
+0x24020007, 0x10000078, 0x0, 0xc003f50,
+0x0, 0x104000ce, 0x24020001, 0x8f820214,
+0x3c03ffff, 0x3c040001, 0x8c846f1c, 0x431024,
+0x3442251f, 0xaf820214, 0x24020008, 0x1080000f,
+0xaee204b8, 0x3c020001, 0x8c426e44, 0x1440000b,
+0x0, 0x8f820220, 0x34420002, 0xaf820220,
+0x24020001, 0x3c010002, 0xac228f90, 0xc004e9c,
+0x8f840220, 0x10000016, 0x0, 0x8f820220,
+0x3c030008, 0x431024, 0x14400011, 0x3c020200,
+0x282a025, 0x2402000e, 0x3c010002, 0xac228f90,
+0xc00551b, 0x2021, 0x8f820220, 0x34420002,
+0xc003e6d, 0xaf820220, 0x3c050001, 0x8ca56d98,
+0xc00529b, 0x2021, 0x100000a3, 0x0,
+0x3c020001, 0x8c426e44, 0x1040009f, 0x0,
+0x3c020001, 0x8c426e40, 0x2442ffff, 0x3c010001,
+0xac226e40, 0x14400098, 0x24020002, 0x3c010001,
+0xac206e44, 0x3c010001, 0x10000093, 0xac226e40,
+0x8ee204b8, 0x2443ffff, 0x2c620007, 0x1040008e,
+0x31080, 0x3c010001, 0x220821, 0x8c226b58,
+0x400008, 0x0, 0x3c020001, 0x8c426da4,
+0x10400018, 0x24020005, 0xc004482, 0x0,
+0x24020002, 0xaee204b8, 0x3c010001, 0x1000007e,
+0xac206da4, 0xc004963, 0x0, 0x3c030001,
+0x8c636dd4, 0x24020006, 0x14620077, 0x24020003,
+0x10000075, 0xaee204b8, 0x3c050001, 0x8ca56d98,
+0x3c060002, 0x8cc68ff8, 0xc005104, 0x2021,
+0x24020005, 0x1000006c, 0xaee204b8, 0x8f820220,
+0x3c03f700, 0x431025, 0xaf820220, 0x8f830054,
+0x24020006, 0xaee204b8, 0x3c010001, 0x10000062,
+0xac236f28, 0x8f820220, 0x3c030004, 0x431024,
+0x10400003, 0x24020007, 0x1000005b, 0xaee204b8,
+0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0,
+0x431023, 0x2c422710, 0x14400003, 0x24020001,
+0x3c010001, 0xac226d9c, 0x3c020002, 0x8c428ff8,
+0x30425000, 0x1040004c, 0x0, 0x8f820220,
+0x30428000, 0x10400007, 0x0, 0x8f820220,
+0x3c03ffff, 0x34637fff, 0x431024, 0x10000042,
+0xaf820220, 0x8f820220, 0x34428000, 0x1000003e,
+0xaf820220, 0x3c050001, 0x8ca56d98, 0xc00529b,
+0x2021, 0xc00551b, 0x2021, 0x3c020002,
+0x8c428ff0, 0x4410032, 0x24020001, 0x8f820214,
+0x3c03ffff, 0x431024, 0x3442251f, 0xaf820214,
+0x24020008, 0xaee204b8, 0x8f820220, 0x34420002,
+0xaf820220, 0x8f820220, 0x3c030004, 0x431024,
+0x14400016, 0x0, 0x3c020002, 0x8c428ff8,
+0x30425000, 0x1040000d, 0x0, 0x8f820220,
+0x30428000, 0x10400006, 0x0, 0x8f820220,
+0x3c03ffff, 0x34637fff, 0x10000003, 0x431024,
+0x8f820220, 0x34428000, 0xaf820220, 0x8f820220,
+0x3c03f700, 0x431025, 0xaf820220, 0x3c020001,
+0x94426f26, 0x24429fbc, 0x2c420004, 0x10400004,
+0x24040018, 0x24050002, 0xc004ddb, 0x24060020,
+0xc003e6d, 0x0, 0x10000003, 0x0,
+0x3c010001, 0xac226d9c, 0x8fbf0018, 0x3e00008,
+0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220,
+0x34420004, 0xaf820220, 0x8f820200, 0x3c050001,
+0x8ca56d98, 0x34420004, 0xaf820200, 0x24020002,
+0x10a2004b, 0x2ca20003, 0x10400005, 0x24020001,
+0x10a2000a, 0x0, 0x100000b1, 0x0,
+0x24020004, 0x10a20072, 0x24020008, 0x10a20085,
+0x3c02f0ff, 0x100000aa, 0x0, 0x8f830050,
+0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c846f40,
+0x621824, 0x3c020700, 0x621825, 0x24020e00,
+0x2484fffb, 0x2c840002, 0xaf830050, 0xaf850200,
+0xaf850220, 0x14800006, 0xaf820238, 0x8f820044,
+0x3c03ffff, 0x34633f7f, 0x431024, 0xaf820044,
+0x3c030001, 0x8c636f40, 0x24020005, 0x14620004,
+0x0, 0x8f820044, 0x34425000, 0xaf820044,
+0x3c020001, 0x8c426d88, 0x3c030001, 0x8c636f40,
+0x34420022, 0x2463fffc, 0x2c630002, 0x1460000c,
+0xaf820200, 0x3c020001, 0x8c426dac, 0x3c030001,
+0x8c636d90, 0x3c040001, 0x8c846d8c, 0x34428000,
+0x621825, 0x641825, 0x1000000a, 0x34620002,
+0x3c020001, 0x8c426d90, 0x3c030001, 0x8c636dac,
+0x3c040001, 0x8c846d8c, 0x431025, 0x441025,
+0x34420002, 0xaf820220, 0x1000002f, 0x24020001,
+0x24020e01, 0xaf820238, 0x8f830050, 0x3c02f0ff,
+0x3442ffff, 0x3c040001, 0x8c846f1c, 0x621824,
+0x3c020d00, 0x621825, 0x24020001, 0xaf830050,
+0xaf820200, 0xaf820220, 0x10800005, 0x3c033f00,
+0x3c020001, 0x8c426d80, 0x10000004, 0x34630070,
+0x3c020001, 0x8c426d80, 0x34630072, 0x431025,
+0xaf820200, 0x3c030001, 0x8c636d84, 0x3c02f700,
+0x621825, 0x3c020001, 0x8c426d90, 0x3c040001,
+0x8c846dac, 0x3c050001, 0x8ca56f40, 0x431025,
+0x441025, 0xaf820220, 0x24020005, 0x14a20006,
+0x24020001, 0x8f820044, 0x2403afff, 0x431024,
+0xaf820044, 0x24020001, 0x1000003d, 0xaf820238,
+0x8f830050, 0x3c02f0ff, 0x3442ffff, 0x3c040001,
+0x8c846f1c, 0x621824, 0x3c020a00, 0x621825,
+0x24020001, 0xaf830050, 0xaf820200, 0x1080001e,
+0xaf820220, 0x3c020001, 0x8c426e44, 0x1440001a,
+0x3c033f00, 0x3c020001, 0x8c426d80, 0x1000001a,
+0x346300e0, 0x8f830050, 0x3c040001, 0x8c846f1c,
+0x3442ffff, 0x621824, 0x1080000f, 0xaf830050,
+0x3c020001, 0x8c426e44, 0x1440000b, 0x3c043f00,
+0x3c030001, 0x8c636d80, 0x348400e0, 0x24020001,
+0xaf820200, 0xaf820220, 0x641825, 0xaf830200,
+0x10000008, 0x3c05f700, 0x3c020001, 0x8c426d80,
+0x3c033f00, 0x346300e2, 0x431025, 0xaf820200,
+0x3c05f700, 0x34a58000, 0x3c030001, 0x8c636d84,
+0x3c020001, 0x8c426d90, 0x3c040001, 0x8c846dac,
+0x651825, 0x431025, 0x441025, 0xaf820220,
+0x3e00008, 0x0, 0x3c030001, 0x8c636db4,
+0x3c020001, 0x8c426db8, 0x10620003, 0x24020002,
+0x3c010001, 0xac236db8, 0x1062001d, 0x2c620003,
+0x10400025, 0x24020001, 0x14620023, 0x24020004,
+0x3c030001, 0x8c636d98, 0x10620006, 0x24020008,
+0x1462000c, 0x3c0200c8, 0x344201fb, 0x10000009,
+0xaf820238, 0x24020e01, 0xaf820238, 0x8f820044,
+0x3c03ffff, 0x34633f7f, 0x431024, 0x34420080,
+0xaf820044, 0x8f830054, 0x24020002, 0x3c010001,
+0xac226db4, 0x3c010001, 0x1000000b, 0xac236f2c,
+0x8f830054, 0x3c020001, 0x8c426f2c, 0x2463d8f0,
+0x431023, 0x2c422710, 0x14400003, 0x24020009,
+0x3c010001, 0xac226db4, 0x3e00008, 0x0,
+0x0, 0x0, 0x0, 0x27bdffd8,
+0xafb20018, 0x809021, 0xafb3001c, 0xa09821,
+0xafb10014, 0xc08821, 0xafb00010, 0x8021,
+0xafbf0020, 0xa6200000, 0xc004d78, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x24100010, 0x2501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x2501024, 0x24100010, 0x2701024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x2701024, 0xc004db9, 0x34108000,
+0xc004db9, 0x0, 0xc004d58, 0x0,
+0x50400005, 0x108042, 0x96220000, 0x501025,
+0xa6220000, 0x108042, 0x1600fff7, 0x0,
+0xc004db9, 0x0, 0x8fbf0020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821,
+0xafb20018, 0xa09021, 0xafb3001c, 0xc09821,
+0xafb00010, 0x8021, 0xafbf0020, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0x24100010, 0x2301024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x2301024, 0x24100010, 0x2501024,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x2501024, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x34108000,
+0x96620000, 0x501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
+0x0, 0xc004db9, 0x0, 0x8fbf0020,
+0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0x3e00008, 0x27bd0028, 0x3c040001, 0x8c846dd0,
+0x3c020001, 0x8c426e18, 0x27bdffd8, 0xafbf0020,
+0xafb1001c, 0x10820003, 0xafb00018, 0x3c010001,
+0xac246e18, 0x3c030001, 0x8c636f40, 0x24020005,
+0x14620005, 0x2483ffff, 0xc004963, 0x0,
+0x1000034c, 0x0, 0x2c620013, 0x10400349,
+0x31080, 0x3c010001, 0x220821, 0x8c226b80,
+0x400008, 0x0, 0xc004db9, 0x8021,
+0x34028000, 0xa7a20010, 0x27b10010, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0xc004d78,
+0x2021, 0x108042, 0x1600fffc, 0x0,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x1000030e, 0x24020002, 0x27b10010, 0xa7a00010,
+0x8021, 0xc004d78, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
+0x2021, 0xc004d78, 0x24040001, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0xc004d78, 0x2021, 0x108042,
+0x1600fffc, 0x0, 0xc004db9, 0x34108000,
+0xc004db9, 0x0, 0xc004d58, 0x0,
+0x50400005, 0x108042, 0x96220000, 0x501025,
+0xa6220000, 0x108042, 0x1600fff7, 0x0,
+0xc004db9, 0x0, 0x97a20010, 0x30428000,
+0x144002dc, 0x24020003, 0x100002d8, 0x0,
+0x24021200, 0xa7a20010, 0x27b10010, 0x8021,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0xc004d78, 0x2021, 0x108042, 0x1600fffc,
+0x0, 0xc004d78, 0x24040001, 0xc004d78,
+0x2021, 0x34108000, 0x96220000, 0x501024,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fff8, 0x0, 0xc004db9,
+0x0, 0x8f830054, 0x10000296, 0x24020004,
+0x8f830054, 0x3c020001, 0x8c426f3c, 0x2463ff9c,
+0x431023, 0x2c420064, 0x1440029e, 0x24020002,
+0x3c030001, 0x8c636f40, 0x10620297, 0x2c620003,
+0x14400296, 0x24020011, 0x24020003, 0x10620005,
+0x24020004, 0x10620291, 0x2402000f, 0x1000028f,
+0x24020011, 0x1000028d, 0x24020005, 0x24020014,
+0xa7a20010, 0x27b10010, 0x8021, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x32020012,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020012, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x34108000,
+0x96220000, 0x501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
+0x0, 0xc004db9, 0x0, 0x8f830054,
+0x10000248, 0x24020006, 0x8f830054, 0x3c020001,
+0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064,
+0x14400250, 0x24020007, 0x1000024c, 0x0,
+0x24020006, 0xa7a20010, 0x27b10010, 0x8021,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020013, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020013,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x8f830054, 0x10000207, 0x24020008, 0x8f830054,
+0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
+0x2c420064, 0x1440020f, 0x24020009, 0x1000020b,
+0x0, 0x27b10010, 0xa7a00010, 0x8021,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020018, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x96220000, 0x501025, 0xa6220000, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x8021,
+0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020018, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x8f830054, 0x10000193, 0x2402000a, 0x8f830054,
+0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
+0x2c420064, 0x1440019b, 0x2402000b, 0x10000197,
+0x0, 0x27b10010, 0xa7a00010, 0x8021,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020017, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020017,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x96220000, 0x501025, 0xa6220000, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x8021,
+0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020017, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020017,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x8f830054, 0x1000011f, 0x2402000c, 0x8f830054,
+0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
+0x2c420064, 0x14400127, 0x24020012, 0x10000123,
+0x0, 0x27b10010, 0xa7a00010, 0x8021,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020014, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020014,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x96220000, 0x501025, 0xa6220000, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x8021,
+0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020014, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020014,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x8f830054, 0x100000ab, 0x24020013, 0x8f830054,
+0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
+0x2c420064, 0x144000b3, 0x2402000d, 0x100000af,
+0x0, 0x27b10010, 0xa7a00010, 0x8021,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020018, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x96220000, 0x501025, 0xa6220000, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x8021,
+0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020018, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x8f830054, 0x10000037, 0x2402000e, 0x24020840,
+0xa7a20010, 0x27b10010, 0x8021, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x32020013,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020013, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x34108000,
+0x96220000, 0x501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
+0x0, 0xc004db9, 0x0, 0x8f830054,
+0x24020010, 0x3c010001, 0xac226dd0, 0x3c010001,
+0x1000000c, 0xac236f3c, 0x8f830054, 0x3c020001,
+0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064,
+0x14400004, 0x0, 0x24020011, 0x3c010001,
+0xac226dd0, 0x8fbf0020, 0x8fb1001c, 0x8fb00018,
+0x3e00008, 0x27bd0028, 0x3c030001, 0x8c636d98,
+0x27bdffc8, 0x24020002, 0xafbf0034, 0xafb20030,
+0xafb1002c, 0x14620004, 0xafb00028, 0x3c120002,
+0x10000003, 0x8e528ff8, 0x3c120002, 0x8e528ffc,
+0x3c030001, 0x8c636dd4, 0x3c020001, 0x8c426e1c,
+0x50620004, 0x2463ffff, 0x3c010001, 0xac236e1c,
+0x2463ffff, 0x2c620006, 0x10400377, 0x31080,
+0x3c010001, 0x220821, 0x8c226bd8, 0x400008,
+0x0, 0x2021, 0x2821, 0xc004ddb,
+0x34068000, 0x24040010, 0x24050002, 0x24060002,
+0x24020002, 0xc004ddb, 0xa7a20018, 0x24020002,
+0x3c010001, 0x10000364, 0xac226dd4, 0x27b10018,
+0xa7a00018, 0x8021, 0xc004d78, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0xc004d78, 0x2021,
+0x108042, 0x1600fffc, 0x0, 0xc004db9,
+0x34108000, 0xc004db9, 0x0, 0xc004d58,
+0x0, 0x50400005, 0x108042, 0x96220000,
+0x501025, 0xa6220000, 0x108042, 0x1600fff7,
+0x0, 0xc004db9, 0x0, 0x97a20018,
+0x30428000, 0x14400004, 0x24020003, 0x3c010001,
+0xac226dd4, 0x24020003, 0x3c010001, 0x1000032a,
+0xac226dd4, 0x24040010, 0x24050002, 0x24060002,
+0x24020002, 0xc004ddb, 0xa7a20018, 0x3c030001,
+0x8c636e20, 0x24020001, 0x146201e1, 0x8021,
+0x27b10018, 0xa7a00018, 0xc004d78, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0x32020018, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020018, 0xc004db9, 0x34108000,
+0xc004db9, 0x0, 0xc004d58, 0x0,
+0x50400005, 0x108042, 0x96220000, 0x501025,
+0xa6220000, 0x108042, 0x1600fff7, 0x0,
+0xc004db9, 0x8021, 0x27b10018, 0xa7a00018,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020018, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x96220000, 0x501025, 0xa6220000, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x8021,
+0x24040018, 0x2821, 0xc004ddb, 0x24060404,
+0xa7a0001a, 0xc004d78, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
+0x2021, 0xc004d78, 0x24040001, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0x32020018, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x32020018, 0xc004db9, 0x34108000, 0xc004db9,
+0x0, 0xc004d58, 0x0, 0x50400005,
+0x108042, 0x97a2001a, 0x501025, 0xa7a2001a,
+0x108042, 0x1600fff7, 0x0, 0xc004db9,
+0x8021, 0xa7a0001a, 0xc004d78, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0x32020018, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020018, 0xc004db9, 0x34108000,
+0xc004db9, 0x0, 0xc004d58, 0x0,
+0x50400005, 0x108042, 0x97a2001a, 0x501025,
+0xa7a2001a, 0x108042, 0x1600fff7, 0x0,
+0xc004db9, 0x8021, 0xa7a0001c, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x24040001, 0xc004d78,
+0x2021, 0x24100010, 0xc004d78, 0x2021,
+0x108042, 0x1600fffc, 0x0, 0x24100010,
+0x3202001e, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x3202001e,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x97a2001c, 0x501025, 0xa7a2001c, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x8021,
+0xa7a0001c, 0xc004d78, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
+0x2021, 0xc004d78, 0x24040001, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x24100010,
+0xc004d78, 0x2021, 0x108042, 0x1600fffc,
+0x0, 0x24100010, 0x3202001e, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x3202001e, 0xc004db9, 0x34108000,
+0xc004db9, 0x0, 0xc004d58, 0x0,
+0x50400005, 0x108042, 0x97a2001c, 0x501025,
+0xa7a2001c, 0x108042, 0x1600fff7, 0x0,
+0xc004db9, 0x8021, 0x24020002, 0xa7a2001e,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0x24100010, 0xc004d78,
+0x2021, 0x108042, 0x1600fffc, 0x0,
+0x24100010, 0x3202001e, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x3202001e, 0xc004d78, 0x24040001, 0xc004d78,
+0x2021, 0x34108000, 0x97a2001e, 0x501024,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fff8, 0x0, 0xc004db9,
+0x8021, 0xa7a00020, 0xc004d78, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x24100010, 0xc004d78, 0x2021, 0x108042,
+0x1600fffc, 0x0, 0x24100010, 0x3202001e,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x3202001e, 0xc004db9,
+0x34108000, 0xc004db9, 0x0, 0xc004d58,
+0x0, 0x50400005, 0x108042, 0x97a20020,
+0x501025, 0xa7a20020, 0x108042, 0x1600fff7,
+0x0, 0xc004db9, 0x8021, 0xa7a00020,
+0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d78, 0x2021,
+0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0x24100010, 0xc004d78,
+0x2021, 0x108042, 0x1600fffc, 0x0,
+0x24100010, 0x3202001e, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
+0x3202001e, 0xc004db9, 0x34108000, 0xc004db9,
+0x0, 0xc004d58, 0x0, 0x50400005,
+0x108042, 0x97a20020, 0x501025, 0xa7a20020,
+0x108042, 0x1600fff7, 0x0, 0xc004db9,
+0x8021, 0xa7a00022, 0xc004d78, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0xc004d78, 0x2021, 0xc004d78, 0x24040001,
+0x24100010, 0xc004d78, 0x2021, 0x108042,
+0x1600fffc, 0x0, 0x24100010, 0xc004d78,
+0x2021, 0x108042, 0x1600fffc, 0x0,
+0xc004d78, 0x24040001, 0xc004d78, 0x2021,
+0x34108000, 0x97a20022, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fff8, 0x0, 0xc004db9, 0x0,
+0x24040018, 0x24050002, 0xc004ddb, 0x24060004,
+0x3c100001, 0x8e106e24, 0x24020001, 0x1602011d,
+0x0, 0x3c020001, 0x94426f26, 0x3c010001,
+0xac206e24, 0x24429fbc, 0x2c420004, 0x1040000c,
+0x24040009, 0x24050001, 0xc004ddb, 0x24060400,
+0x24040018, 0x24050001, 0xc004ddb, 0x24060020,
+0x24040018, 0x24050001, 0xc004ddb, 0x24062000,
+0x3c024000, 0x2421024, 0x10400123, 0x3c022000,
+0x2421024, 0x10400004, 0x0, 0x3c010001,
+0x10000003, 0xac306f1c, 0x3c010001, 0xac206f1c,
+0x3c030001, 0x8c636f34, 0x24020005, 0x146200f9,
+0x0, 0x3c020001, 0x8c426f1c, 0x10400067,
+0x3c020004, 0x2421024, 0x10400011, 0xa7a00018,
+0x3c020008, 0x2421024, 0x10400002, 0x24020200,
+0xa7a20018, 0x3c020010, 0x2421024, 0x10400004,
+0x0, 0x97a20018, 0x34420100, 0xa7a20018,
+0x97a60018, 0x24040009, 0x10000004, 0x2821,
+0x24040009, 0x2821, 0x3021, 0xc004ddb,
+0x0, 0x24020001, 0xa7a2001a, 0x3c020008,
+0x2421024, 0x1040000c, 0x3c020002, 0x2421024,
+0x10400002, 0x24020101, 0xa7a2001a, 0x3c020001,
+0x2421024, 0x10400005, 0x3c020010, 0x97a2001a,
+0x34420040, 0xa7a2001a, 0x3c020010, 0x2421024,
+0x1040000e, 0x3c020002, 0x2421024, 0x10400005,
+0x3c020001, 0x97a2001a, 0x34420080, 0xa7a2001a,
+0x3c020001, 0x2421024, 0x10400005, 0x3c0300a0,
+0x97a2001a, 0x34420020, 0xa7a2001a, 0x3c0300a0,
+0x2431024, 0x54430004, 0x3c020020, 0x97a2001a,
+0x1000000c, 0x34420400, 0x2421024, 0x50400004,
+0x3c020080, 0x97a2001a, 0x10000006, 0x34420800,
+0x2421024, 0x10400004, 0x0, 0x97a2001a,
+0x34420c00, 0xa7a2001a, 0x97a6001a, 0x24040004,
+0xc004ddb, 0x2821, 0x3c020004, 0x2421024,
+0x10400004, 0xa7a0001c, 0x32425000, 0x14400004,
+0x0, 0x32424000, 0x10400005, 0x2021,
+0xc004cf9, 0x2402021, 0x10000096, 0x0,
+0x97a6001c, 0x2821, 0x34c61200, 0xc004ddb,
+0xa7a6001c, 0x1000008f, 0x0, 0x2421024,
+0x10400004, 0xa7a00018, 0x32425000, 0x14400004,
+0x0, 0x32424000, 0x10400005, 0x3c020010,
+0xc004cf9, 0x2402021, 0x10000019, 0xa7a0001a,
+0x2421024, 0x10400004, 0x0, 0x97a20018,
+0x10000004, 0xa7a20018, 0x97a20018, 0x34420100,
+0xa7a20018, 0x3c020001, 0x2421024, 0x10400004,
+0x0, 0x97a20018, 0x10000004, 0xa7a20018,
+0x97a20018, 0x34422000, 0xa7a20018, 0x97a60018,
+0x2021, 0xc004ddb, 0x2821, 0xa7a0001a,
+0x8021, 0xc004d78, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
+0x2021, 0xc004d78, 0x24040001, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001,
+0xc004d78, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0xc004d78, 0x2021, 0x108042,
+0x1600fffc, 0x0, 0xc004db9, 0x34108000,
+0xc004db9, 0x0, 0xc004d58, 0x0,
+0x50400005, 0x108042, 0x97a2001a, 0x501025,
+0xa7a2001a, 0x108042, 0x1600fff7, 0x0,
+0xc004db9, 0x8021, 0xa7a0001a, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x24040001, 0xc004d78,
+0x2021, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0xc004d78,
+0x2021, 0x108042, 0x1600fffc, 0x0,
+0xc004db9, 0x34108000, 0xc004db9, 0x0,
+0xc004d58, 0x0, 0x50400005, 0x108042,
+0x97a2001a, 0x501025, 0xa7a2001a, 0x108042,
+0x1600fff7, 0x0, 0xc004db9, 0x0,
+0x3c040001, 0x24846bcc, 0x97a60018, 0x97a7001a,
+0x3c020001, 0x8c426d98, 0x3c030001, 0x8c636f1c,
+0x3c05000d, 0x34a50205, 0xafa20010, 0xc002b3b,
+0xafa30014, 0x8f830054, 0x24020004, 0x3c010001,
+0xac226dd4, 0x3c010001, 0x10000017, 0xac236f38,
+0x8f830054, 0x3c020001, 0x8c426f38, 0x2463ff9c,
+0x431023, 0x2c420064, 0x1440000f, 0x0,
+0x8f820220, 0x24030005, 0x3c010001, 0xac236dd4,
+0x3c03f700, 0x431025, 0x10000007, 0xaf820220,
+0x24020006, 0x3c010001, 0xac226dd4, 0x24020011,
+0x3c010001, 0xac226dd0, 0x8fbf0034, 0x8fb20030,
+0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0038,
+0x27bdffd8, 0xafb00018, 0x808021, 0xafb1001c,
+0x8821, 0x32024000, 0x10400013, 0xafbf0020,
+0x3c020010, 0x2021024, 0x2c420001, 0x21023,
+0x30434100, 0x3c020001, 0x2021024, 0x14400006,
+0x34714000, 0x3c020002, 0x2021024, 0x14400002,
+0x34716000, 0x34714040, 0x2021, 0x2821,
+0x10000036, 0x2203021, 0x32021000, 0x10400035,
+0x2021, 0x2821, 0xc004ddb, 0x24060040,
+0x24040018, 0x2821, 0xc004ddb, 0x24060c00,
+0x24040017, 0x2821, 0xc004ddb, 0x24060400,
+0x24040016, 0x2821, 0xc004ddb, 0x24060006,
+0x24040017, 0x2821, 0xc004ddb, 0x24062500,
+0x24040016, 0x2821, 0xc004ddb, 0x24060006,
+0x24040017, 0x2821, 0xc004ddb, 0x24064600,
+0x24040016, 0x2821, 0xc004ddb, 0x24060006,
+0x24040017, 0x2821, 0xc004ddb, 0x24066700,
+0x24040016, 0x2821, 0xc004ddb, 0x24060006,
+0x2404001f, 0x2821, 0xc004ddb, 0x24060010,
+0x24040009, 0x2821, 0xc004ddb, 0x24061500,
+0x24040009, 0x2821, 0x24061d00, 0xc004ddb,
+0x0, 0x3c040001, 0x24846bf0, 0x3c05000e,
+0x34a50100, 0x2003021, 0x2203821, 0xafa00010,
+0xc002b3b, 0xafa00014, 0x8fbf0020, 0x8fb1001c,
+0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044,
+0x8f820044, 0x3c030001, 0x431025, 0x3c030008,
+0xaf820044, 0x8f840054, 0x8f820054, 0xa32824,
+0x10000002, 0x24840001, 0x8f820054, 0x821023,
+0x2c420002, 0x1440fffc, 0x0, 0x8f820044,
+0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x3e00008, 0xa01021, 0x8f830044,
+0x3c02fff0, 0x3442ffff, 0x42480, 0x621824,
+0x3c020002, 0x822025, 0x641825, 0xaf830044,
+0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024,
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630001, 0x8f820054, 0x621023, 0x2c420002,
+0x1440fffc, 0x0, 0x8f820044, 0x3c030001,
+0x431025, 0xaf820044, 0x8f830054, 0x8f820054,
+0x10000002, 0x24630001, 0x8f820054, 0x621023,
+0x2c420002, 0x1440fffc, 0x0, 0x3e00008,
+0x0, 0x8f820044, 0x2403ff7f, 0x431024,
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630001, 0x8f820054, 0x621023, 0x2c420002,
+0x1440fffc, 0x0, 0x8f820044, 0x34420080,
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630001, 0x8f820054, 0x621023, 0x2c420002,
+0x1440fffc, 0x0, 0x3e00008, 0x0,
+0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024,
+0xaf820044, 0x8f820044, 0x3c030001, 0x431025,
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630001, 0x8f820054, 0x621023, 0x2c420002,
+0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe,
+0x3463ffff, 0x431024, 0xaf820044, 0x8f830054,
+0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
+0x621023, 0x2c420002, 0x1440fffc, 0x0,
+0x3e00008, 0x0, 0x27bdffc8, 0xafb30024,
+0x809821, 0xafbe002c, 0xa0f021, 0xafb20020,
+0xc09021, 0x33c2ffff, 0xafbf0030, 0xafb50028,
+0xafb1001c, 0xafb00018, 0x14400034, 0xa7b20010,
+0x3271ffff, 0x27b20010, 0x8021, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x2301024,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x2301024, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x34108000,
+0x96420000, 0x501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x12000075,
+0x0, 0x1000fff6, 0x0, 0x3275ffff,
+0x27b10010, 0xa7a00010, 0x8021, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x24040001, 0xc004d78,
+0x2021, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x2b01024,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x2b01024, 0xc004db9,
+0x34108000, 0xc004db9, 0x0, 0xc004d58,
+0x0, 0x50400005, 0x108042, 0x96220000,
+0x501025, 0xa6220000, 0x108042, 0x1600fff7,
+0x0, 0xc004db9, 0x0, 0x33c5ffff,
+0x24020001, 0x54a20004, 0x24020002, 0x97a20010,
+0x10000006, 0x521025, 0x14a20006, 0x3271ffff,
+0x97a20010, 0x121827, 0x431024, 0xa7a20010,
+0x3271ffff, 0x27b20010, 0x8021, 0xc004d78,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0xc004d78,
+0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d78, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x2301024,
+0x10400002, 0x2021, 0x24040001, 0xc004d78,
+0x108042, 0x1600fffa, 0x2301024, 0xc004d78,
+0x24040001, 0xc004d78, 0x2021, 0x34108000,
+0x96420000, 0x501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
+0x0, 0xc004db9, 0x0, 0x8fbf0030,
+0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb20020,
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038,
+0x0, 0x0, 0x0, 0x27bdffe8,
+0xafbf0010, 0x8ee304b8, 0x24020008, 0x146201e0,
+0x0, 0x3c020001, 0x8c426f1c, 0x14400005,
+0x0, 0xc003daf, 0x8f840224, 0x100001d8,
+0x0, 0x8f820220, 0x3c030008, 0x431024,
+0x10400026, 0x24020001, 0x8f840224, 0x8f820220,
+0x3c030400, 0x431024, 0x10400006, 0x0,
+0x3c010002, 0xac208fa0, 0x3c010002, 0x1000000b,
+0xac208fc0, 0x3c030002, 0x24638fa0, 0x8c620000,
+0x24420001, 0xac620000, 0x2c420002, 0x14400003,
+0x24020001, 0x3c010002, 0xac228fc0, 0x3c020002,
+0x8c428fc0, 0x10400006, 0x30820040, 0x10400004,
+0x24020001, 0x3c010002, 0x10000003, 0xac228fc4,
+0x3c010002, 0xac208fc4, 0x3c010002, 0xac248f9c,
+0x3c010002, 0x1000000b, 0xac208fd0, 0x3c010002,
+0xac228fd0, 0x3c010002, 0xac208fc0, 0x3c010002,
+0xac208fa0, 0x3c010002, 0xac208fc4, 0x3c010002,
+0xac208f9c, 0x3c030002, 0x8c638f90, 0x3c020002,
+0x8c428f94, 0x50620004, 0x2463ffff, 0x3c010002,
+0xac238f94, 0x2463ffff, 0x2c62000e, 0x10400194,
+0x31080, 0x3c010001, 0x220821, 0x8c226c00,
+0x400008, 0x0, 0x24020002, 0x3c010002,
+0xac208fc0, 0x3c010002, 0xac208fa0, 0x3c010002,
+0xac208f9c, 0x3c010002, 0xac208fc4, 0x3c010002,
+0xac208fb8, 0x3c010002, 0xac208fb0, 0xaf800224,
+0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fd0,
+0x1440004f, 0x3c02fdff, 0x3442ffff, 0xc003daf,
+0x282a024, 0xaf800204, 0x8f820200, 0x2403fffd,
+0x431024, 0xaf820200, 0x3c010002, 0xac208fe0,
+0x8f830054, 0x3c020002, 0x8c428fb8, 0x24040001,
+0x3c010002, 0xac248fcc, 0x24420001, 0x3c010002,
+0xac228fb8, 0x2c420004, 0x3c010002, 0xac238fb4,
+0x14400006, 0x24020003, 0x3c010001, 0xac246d9c,
+0x3c010002, 0x1000015e, 0xac208fb8, 0x3c010002,
+0x1000015b, 0xac228f90, 0x8f830054, 0x3c020002,
+0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710,
+0x14400003, 0x24020004, 0x3c010002, 0xac228f90,
+0x3c020002, 0x8c428fd0, 0x14400021, 0x3c02fdff,
+0x3442ffff, 0x1000014a, 0x282a024, 0x3c040001,
+0x8c846f20, 0x3c010002, 0xc005084, 0xac208fa8,
+0x3c020002, 0x8c428fdc, 0xaf820204, 0x3c020002,
+0x8c428fd0, 0x14400012, 0x3c03fdff, 0x8f820204,
+0x3463ffff, 0x30420030, 0x1440012f, 0x283a024,
+0x3c030002, 0x8c638fdc, 0x24020005, 0x3c010002,
+0xac228f90, 0x3c010002, 0x10000131, 0xac238fe0,
+0x3c020002, 0x8c428fd0, 0x10400010, 0x3c02fdff,
+0x3c020001, 0x8c426e3c, 0x24420001, 0x3c010001,
+0xac226e3c, 0x2c420002, 0x14400125, 0x24020001,
+0x3c010001, 0xac226e44, 0x3c010001, 0xac206e3c,
+0x3c010001, 0x1000011e, 0xac226d9c, 0x3c030002,
+0x8c638fc0, 0x3442ffff, 0x10600119, 0x282a024,
+0x3c020002, 0x8c428f9c, 0x10400115, 0x0,
+0x3c010002, 0xac228fc8, 0x24020003, 0x3c010002,
+0xac228fa0, 0x100000b8, 0x24020006, 0x3c010002,
+0xac208fa8, 0x8f820204, 0x34420040, 0xaf820204,
+0x3c020002, 0x8c428fe0, 0x24030007, 0x3c010002,
+0xac238f90, 0x34420040, 0x3c010002, 0xac228fe0,
+0x3c020002, 0x8c428fc0, 0x10400005, 0x0,
+0x3c020002, 0x8c428f9c, 0x104000f0, 0x24020002,
+0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21,
+0x104000ea, 0x24020002, 0x3c020002, 0x8c428fc4,
+0x104000ef, 0x2404ffbf, 0x3c020002, 0x8c428f9c,
+0x3c030002, 0x8c638fc8, 0x441024, 0x641824,
+0x10430004, 0x24020001, 0x3c010002, 0x100000e4,
+0xac228f90, 0x24020003, 0xaca20000, 0x24020008,
+0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fcc,
+0x1040000c, 0x24020001, 0x3c040002, 0xc005091,
+0x8c848f9c, 0x3c020002, 0x8c428fe8, 0x14400005,
+0x24020001, 0x3c020002, 0x8c428fe4, 0x10400006,
+0x24020001, 0x3c010001, 0xac226d9c, 0x3c010002,
+0x100000cb, 0xac208fb8, 0x3c020002, 0x8c428fb0,
+0x3c030002, 0x8c638f9c, 0x2c420001, 0x210c0,
+0x30630008, 0x3c010002, 0xac228fb0, 0x3c010002,
+0xac238fac, 0x8f830054, 0x24020009, 0x3c010002,
+0xac228f90, 0x3c010002, 0x100000b9, 0xac238fb4,
+0x8f830054, 0x3c020002, 0x8c428fb4, 0x2463d8f0,
+0x431023, 0x2c422710, 0x1440009f, 0x0,
+0x3c020002, 0x8c428fc0, 0x10400005, 0x0,
+0x3c020002, 0x8c428f9c, 0x104000a0, 0x24020002,
+0x3c030002, 0x24638fa0, 0x8c620000, 0x2c424e21,
+0x1040009a, 0x24020002, 0x3c020002, 0x8c428fcc,
+0x1040000e, 0x0, 0x3c020002, 0x8c428f9c,
+0x3c010002, 0xac208fcc, 0x30420080, 0x1040002f,
+0x2402000c, 0x8f820204, 0x30420080, 0x1440000c,
+0x24020003, 0x10000029, 0x2402000c, 0x3c020002,
+0x8c428f9c, 0x30420080, 0x14400005, 0x24020003,
+0x8f820204, 0x30420080, 0x1040001f, 0x24020003,
+0xac620000, 0x2402000a, 0x3c010002, 0xac228f90,
+0x3c040002, 0x24848fd8, 0x8c820000, 0x3c030002,
+0x8c638fb0, 0x431025, 0xaf820204, 0x8c830000,
+0x3c040002, 0x8c848fb0, 0x2402000b, 0x3c010002,
+0xac228f90, 0x641825, 0x3c010002, 0xac238fe0,
+0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21,
+0x10400066, 0x24020002, 0x3c020002, 0x8c428fd0,
+0x10400005, 0x0, 0x2402000c, 0x3c010002,
+0x10000067, 0xac228f90, 0x3c020002, 0x8c428fc0,
+0x10400063, 0x0, 0x3c040002, 0x8c848f9c,
+0x10800055, 0x30820008, 0x3c030002, 0x8c638fac,
+0x1062005b, 0x24020003, 0x3c010002, 0xac248fc8,
+0xaca20000, 0x24020006, 0x3c010002, 0x10000054,
+0xac228f90, 0x8f820200, 0x34420002, 0xaf820200,
+0x8f830054, 0x2402000d, 0x3c010002, 0xac228f90,
+0x3c010002, 0xac238fb4, 0x8f830054, 0x3c020002,
+0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710,
+0x14400031, 0x0, 0x3c020002, 0x8c428fd0,
+0x10400020, 0x2402000e, 0x3c030002, 0x8c638fe4,
+0x3c010002, 0x14600015, 0xac228f90, 0xc003e6d,
+0x0, 0x3c050001, 0x8ca56d98, 0xc00529b,
+0x2021, 0x3c030001, 0x8c636d98, 0x24020004,
+0x14620005, 0x2403fffb, 0x3c020001, 0x8c426d94,
+0x10000003, 0x2403fff7, 0x3c020001, 0x8c426d94,
+0x431024, 0x3c010001, 0xac226d94, 0x8f830224,
+0x3c020200, 0x3c010002, 0xac238fec, 0x10000020,
+0x282a025, 0x3c020002, 0x8c428fc0, 0x10400005,
+0x0, 0x3c020002, 0x8c428f9c, 0x1040000f,
+0x24020002, 0x3c020002, 0x8c428fa0, 0x2c424e21,
+0x1040000a, 0x24020002, 0x3c020002, 0x8c428fc0,
+0x1040000f, 0x0, 0x3c020002, 0x8c428f9c,
+0x1440000b, 0x0, 0x24020002, 0x3c010002,
+0x10000007, 0xac228f90, 0x3c020002, 0x8c428fc0,
+0x10400003, 0x0, 0xc003daf, 0x0,
+0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
+0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030002,
+0x24638fe8, 0x8c620000, 0x10400005, 0x34422000,
+0x3c010002, 0xac228fdc, 0x10000003, 0xac600000,
+0x3c010002, 0xac248fdc, 0x3e00008, 0x0,
+0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010002,
+0xac228fe4, 0x14400067, 0x3c02ffff, 0x34421f0e,
+0x821024, 0x14400061, 0x24020030, 0x30822000,
+0x1040005d, 0x30838000, 0x31a02, 0x30820001,
+0x21200, 0x3c040001, 0x8c846f20, 0x621825,
+0x331c2, 0x3c030001, 0x24636e48, 0x30828000,
+0x21202, 0x30840001, 0x42200, 0x441025,
+0x239c2, 0x61080, 0x431021, 0x471021,
+0x90430000, 0x24020001, 0x10620025, 0x0,
+0x10600007, 0x24020002, 0x10620013, 0x24020003,
+0x1062002c, 0x3c05000f, 0x10000037, 0x0,
+0x8f820200, 0x2403feff, 0x431024, 0xaf820200,
+0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024,
+0xaf820220, 0x3c010002, 0xac209004, 0x3c010002,
+0x10000034, 0xac20900c, 0x8f820200, 0x34420100,
+0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff,
+0x431024, 0xaf820220, 0x24020100, 0x3c010002,
+0xac229004, 0x3c010002, 0x10000026, 0xac20900c,
+0x8f820200, 0x2403feff, 0x431024, 0xaf820200,
+0x8f820220, 0x3c030001, 0x431025, 0xaf820220,
+0x3c010002, 0xac209004, 0x3c010002, 0x10000019,
+0xac23900c, 0x8f820200, 0x34420100, 0xaf820200,
+0x8f820220, 0x3c030001, 0x431025, 0xaf820220,
+0x24020100, 0x3c010002, 0xac229004, 0x3c010002,
+0x1000000c, 0xac23900c, 0x34a5ffff, 0x3c040001,
+0x24846c38, 0xafa30010, 0xc002b3b, 0xafa00014,
+0x10000004, 0x0, 0x24020030, 0x3c010002,
+0xac228fe8, 0x8fbf0018, 0x3e00008, 0x27bd0020,
+0x0, 0x0, 0x0, 0x27bdffc8,
+0xafb20028, 0x809021, 0xafb3002c, 0xa09821,
+0xafb00020, 0xc08021, 0x3c040001, 0x24846c50,
+0x3c050009, 0x3c020001, 0x8c426d98, 0x34a59001,
+0x2403021, 0x2603821, 0xafbf0030, 0xafb10024,
+0xa7a0001a, 0xafb00014, 0xc002b3b, 0xafa20010,
+0x24020002, 0x12620083, 0x2e620003, 0x10400005,
+0x24020001, 0x1262000a, 0x0, 0x10000173,
+0x0, 0x24020004, 0x126200f8, 0x24020008,
+0x126200f7, 0x3c02ffec, 0x1000016c, 0x0,
+0x3c020001, 0x8c426d94, 0x30420002, 0x14400004,
+0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024,
+0x3c010002, 0x310821, 0xac308ffc, 0x3c024000,
+0x2021024, 0x1040004e, 0x1023c2, 0x30840030,
+0x101382, 0x3042001c, 0x3c030001, 0x24636dd8,
+0x431021, 0x823821, 0x3c020020, 0x2021024,
+0x10400006, 0x24020100, 0x3c010002, 0x310821,
+0xac229000, 0x10000005, 0x3c020080, 0x3c010002,
+0x310821, 0xac209000, 0x3c020080, 0x2021024,
+0x10400006, 0x121940, 0x3c020001, 0x3c010002,
+0x230821, 0x10000005, 0xac229008, 0x121140,
+0x3c010002, 0x220821, 0xac209008, 0x94e40000,
+0x3c030001, 0x8c636f40, 0x24020005, 0x10620010,
+0xa7a40018, 0x32024000, 0x10400002, 0x34824000,
+0xa7a20018, 0x24040001, 0x94e20002, 0x24050004,
+0x24e60002, 0x34420001, 0xc0045be, 0xa4e20002,
+0x24040001, 0x2821, 0xc0045be, 0x27a60018,
+0x3c020001, 0x8c426d98, 0x24110001, 0x3c010001,
+0xac316da4, 0x14530004, 0x32028000, 0xc003daf,
+0x0, 0x32028000, 0x1040011c, 0x0,
+0xc003daf, 0x0, 0x3c030001, 0x8c636f40,
+0x24020005, 0x10620115, 0x24020002, 0x3c010001,
+0xac316d9c, 0x3c010001, 0x10000110, 0xac226d98,
+0x24040001, 0x24050004, 0x27b0001a, 0xc0045be,
+0x2003021, 0x24040001, 0x2821, 0xc0045be,
+0x2003021, 0x3c020002, 0x511021, 0x8c428ff4,
+0x3c040001, 0x8c846d98, 0x3c03bfff, 0x3463ffff,
+0x3c010001, 0xac336da4, 0x431024, 0x3c010002,
+0x310821, 0x109300f7, 0xac228ff4, 0x100000f7,
+0x0, 0x3c022000, 0x2021024, 0x10400005,
+0x24020001, 0x3c010001, 0xac226f1c, 0x10000004,
+0x128940, 0x3c010001, 0xac206f1c, 0x128940,
+0x3c010002, 0x310821, 0xac308ff8, 0x3c024000,
+0x2021024, 0x14400014, 0x0, 0x3c020001,
+0x8c426f1c, 0x10400006, 0x24040004, 0x24050001,
+0xc004ddb, 0x24062000, 0x24020001, 0xaee204b8,
+0x3c020002, 0x511021, 0x8c428ff0, 0x3c03bfff,
+0x3463ffff, 0x431024, 0x3c010002, 0x310821,
+0x100000d0, 0xac228ff0, 0x3c020001, 0x8c426f1c,
+0x10400028, 0x3c0300a0, 0x2031024, 0x5443000d,
+0x3c020020, 0x3c020001, 0x8c426f20, 0x24030100,
+0x3c010002, 0x310821, 0xac239004, 0x3c030001,
+0x3c010002, 0x310821, 0xac23900c, 0x10000015,
+0x34420400, 0x2021024, 0x10400008, 0x24030100,
+0x3c020001, 0x8c426f20, 0x3c010002, 0x310821,
+0xac239004, 0x1000000b, 0x34420800, 0x3c020080,
+0x2021024, 0x1040002e, 0x3c030001, 0x3c020001,
+0x8c426f20, 0x3c010002, 0x310821, 0xac23900c,
+0x34420c00, 0x3c010001, 0xac226f20, 0x10000025,
+0x24040001, 0x3c020020, 0x2021024, 0x10400006,
+0x24020100, 0x3c010002, 0x310821, 0xac229004,
+0x10000005, 0x3c020080, 0x3c010002, 0x310821,
+0xac209004, 0x3c020080, 0x2021024, 0x10400007,
+0x121940, 0x3c020001, 0x3c010002, 0x230821,
+0xac22900c, 0x10000006, 0x24040001, 0x121140,
+0x3c010002, 0x220821, 0xac20900c, 0x24040001,
+0x2821, 0x27b0001e, 0xc00457c, 0x2003021,
+0x24040001, 0x2821, 0xc00457c, 0x2003021,
+0x24040001, 0x24050001, 0x27b0001c, 0xc00457c,
+0x2003021, 0x24040001, 0x24050001, 0xc00457c,
+0x2003021, 0x10000077, 0x0, 0x3c02ffec,
+0x3442ffff, 0x2028024, 0x3c020008, 0x2028025,
+0x121140, 0x3c010002, 0x220821, 0xac308ff8,
+0x3c022000, 0x2021024, 0x10400009, 0x0,
+0x3c020001, 0x8c426e44, 0x14400005, 0x24020001,
+0x3c010001, 0xac226f1c, 0x10000004, 0x3c024000,
+0x3c010001, 0xac206f1c, 0x3c024000, 0x2021024,
+0x1440001d, 0x24020e01, 0x3c030001, 0x8c636f1c,
+0xaf820238, 0x3c010001, 0xac206db0, 0x10600005,
+0x24022020, 0x3c010001, 0xac226f20, 0x24020001,
+0xaee204b8, 0x3c04bfff, 0x121940, 0x3c020002,
+0x431021, 0x8c428ff0, 0x3c050001, 0x8ca56d98,
+0x3484ffff, 0x441024, 0x3c010002, 0x230821,
+0xac228ff0, 0x24020001, 0x10a20044, 0x0,
+0x10000040, 0x0, 0x3c020001, 0x8c426f1c,
+0x1040001c, 0x24022000, 0x3c010001, 0xac226f20,
+0x3c0300a0, 0x2031024, 0x14430005, 0x121140,
+0x3402a000, 0x3c010001, 0x1000002d, 0xac226f20,
+0x3c030002, 0x621821, 0x8c638ff8, 0x3c020020,
+0x621024, 0x10400004, 0x24022001, 0x3c010001,
+0x10000023, 0xac226f20, 0x3c020080, 0x621024,
+0x1040001f, 0x3402a001, 0x3c010001, 0x1000001c,
+0xac226f20, 0x3c020020, 0x2021024, 0x10400007,
+0x121940, 0x24020100, 0x3c010002, 0x230821,
+0xac229004, 0x10000006, 0x3c020080, 0x121140,
+0x3c010002, 0x220821, 0xac209004, 0x3c020080,
+0x2021024, 0x10400006, 0x121940, 0x3c020001,
+0x3c010002, 0x230821, 0x10000005, 0xac22900c,
+0x121140, 0x3c010002, 0x220821, 0xac20900c,
+0x3c030001, 0x8c636d98, 0x24020001, 0x10620003,
+0x0, 0xc003daf, 0x0, 0x8fbf0030,
+0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
+0x3e00008, 0x27bd0038, 0x27bdffb0, 0xafb3003c,
+0x9821, 0xafb50040, 0xa821, 0xafb10034,
+0x8821, 0x24020002, 0xafbf0048, 0xafbe0044,
+0xafb20038, 0xafb00030, 0xafa4002c, 0xa7a0001a,
+0xa7a00018, 0xa7a00020, 0xa7a0001e, 0xa7a00022,
+0x10a20130, 0xa7a0001c, 0x2ca20003, 0x10400005,
+0x24020001, 0x10a2000a, 0x3c024000, 0x1000025d,
+0x2201021, 0x24020004, 0x10a2020a, 0x24020008,
+0x10a20208, 0x2201021, 0x10000256, 0x0,
+0x8fa8002c, 0x88140, 0x3c030002, 0x701821,
+0x8c638ffc, 0x621024, 0x14400009, 0x24040001,
+0x3c027fff, 0x3442ffff, 0x628824, 0x3c010002,
+0x300821, 0xac318ff4, 0x10000246, 0x2201021,
+0x24050001, 0xc00457c, 0x27a60018, 0x24040001,
+0x24050001, 0xc00457c, 0x27a60018, 0x97a20018,
+0x30420004, 0x104000d9, 0x3c114000, 0x3c020001,
+0x8c426f40, 0x2443ffff, 0x2c620006, 0x104000d9,
+0x31080, 0x3c010001, 0x220821, 0x8c226c68,
+0x400008, 0x0, 0x24040001, 0x24050011,
+0x27b0001a, 0xc00457c, 0x2003021, 0x24040001,
+0x24050011, 0xc00457c, 0x2003021, 0x97a3001a,
+0x30624000, 0x10400002, 0x3c150010, 0x3c150008,
+0x30628000, 0x104000aa, 0x3c130001, 0x100000a8,
+0x3c130002, 0x24040001, 0x24050014, 0x27b0001a,
+0xc00457c, 0x2003021, 0x24040001, 0x24050014,
+0xc00457c, 0x2003021, 0x97a3001a, 0x30621000,
+0x10400002, 0x3c150010, 0x3c150008, 0x30620800,
+0x10400097, 0x3c130001, 0x10000095, 0x3c130002,
+0x24040001, 0x24050019, 0x27b0001c, 0xc00457c,
+0x2003021, 0x24040001, 0x24050019, 0xc00457c,
+0x2003021, 0x97a2001c, 0x30430700, 0x24020400,
+0x10620027, 0x28620401, 0x1040000e, 0x24020200,
+0x1062001f, 0x28620201, 0x10400005, 0x24020100,
+0x5062001e, 0x3c130001, 0x1000001e, 0x24040001,
+0x24020300, 0x50620019, 0x3c130002, 0x10000019,
+0x24040001, 0x24020600, 0x1062000d, 0x28620601,
+0x10400005, 0x24020500, 0x5062000b, 0x3c130002,
+0x10000010, 0x24040001, 0x24020700, 0x1462000d,
+0x24040001, 0x3c130004, 0x1000000a, 0x3c150008,
+0x10000006, 0x3c130004, 0x10000005, 0x3c150008,
+0x3c130001, 0x10000002, 0x3c150008, 0x3c150010,
+0x24040001, 0x24050018, 0x27b0001e, 0xc00457c,
+0x2003021, 0x24040001, 0x24050018, 0xc00457c,
+0x2003021, 0x8fa8002c, 0x97a7001e, 0x81140,
+0x3c060002, 0xc23021, 0x8cc68ff4, 0x97a20022,
+0x3c100001, 0x26106c5c, 0x2002021, 0xafa20010,
+0x97a2001c, 0x3c05000c, 0x34a50303, 0xc002b3b,
+0xafa20014, 0x3c020004, 0x16620010, 0x3c020001,
+0x8f840054, 0x24030001, 0x24020002, 0x3c010001,
+0xac236d9c, 0x3c010001, 0xac226d98, 0x3c010001,
+0xac236da4, 0x3c010001, 0xac236e24, 0x3c010001,
+0xac246f30, 0x1000004f, 0x2b38825, 0x16620039,
+0x3c028000, 0x3c020001, 0x8c426e20, 0x1440001e,
+0x24040018, 0x2021, 0x2821, 0xc004ddb,
+0x34068000, 0x8f830054, 0x8f820054, 0x2b38825,
+0x10000002, 0x24630032, 0x8f820054, 0x621023,
+0x2c420033, 0x1440fffc, 0x0, 0x8f830054,
+0x24020001, 0x3c010001, 0xac226e20, 0x3c010001,
+0xac226d9c, 0x3c010001, 0xac226d98, 0x3c010001,
+0xac226da4, 0x3c010001, 0xac226e24, 0x3c010001,
+0x1000002c, 0xac236f30, 0x2821, 0xc004ddb,
+0x24060404, 0x2021, 0x2405001e, 0x27a60018,
+0x24020002, 0xc0045be, 0xa7a20018, 0x2021,
+0x2821, 0x27a60018, 0xc0045be, 0xa7a00018,
+0x24040018, 0x24050002, 0xc004ddb, 0x24060004,
+0x3c028000, 0x2221025, 0x2b31825, 0x10000015,
+0x438825, 0x2221025, 0x2751825, 0x438825,
+0x2002021, 0x97a6001c, 0x3c070001, 0x8ce76d98,
+0x3c05000c, 0x34a50326, 0xafb30010, 0xc002b3b,
+0xafb10014, 0x10000007, 0x0, 0x3c110002,
+0x2308821, 0x8e318ffc, 0x3c027fff, 0x3442ffff,
+0x2228824, 0x3c020001, 0x8c426da8, 0x1040001e,
+0x0, 0x3c020001, 0x8c426f1c, 0x10400002,
+0x3c022000, 0x2228825, 0x8fa8002c, 0x81140,
+0x3c010002, 0x220821, 0x8c229000, 0x10400003,
+0x3c020020, 0x10000005, 0x2228825, 0x3c02ffdf,
+0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140,
+0x3c010002, 0x220821, 0x8c229008, 0x10400003,
+0x3c020080, 0x10000004, 0x2228825, 0x3c02ff7f,
+0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140,
+0x3c010002, 0x220821, 0xac318ff4, 0x10000135,
+0x2201021, 0x8fa8002c, 0x8f140, 0x3c030002,
+0x7e1821, 0x8c638ff8, 0x3c024000, 0x621024,
+0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff,
+0x628824, 0x3c010002, 0x3e0821, 0xac318ff0,
+0x10000124, 0x2201021, 0x2821, 0xc00457c,
+0x27a60018, 0x24040001, 0x2821, 0xc00457c,
+0x27a60018, 0x24040001, 0x24050001, 0x27b20020,
+0xc00457c, 0x2403021, 0x24040001, 0x24050001,
+0xc00457c, 0x2403021, 0x24040001, 0x24050004,
+0x27b1001e, 0xc00457c, 0x2203021, 0x24040001,
+0x24050004, 0xc00457c, 0x2203021, 0x24040001,
+0x24050005, 0x27b00022, 0xc00457c, 0x2003021,
+0x24040001, 0x24050005, 0xc00457c, 0x2003021,
+0x24040001, 0x24050010, 0xc00457c, 0x27a60018,
+0x24040001, 0x24050010, 0xc00457c, 0x27a60018,
+0x24040001, 0x2405000a, 0xc00457c, 0x2403021,
+0x24040001, 0x2405000a, 0xc00457c, 0x2403021,
+0x24040001, 0x24050018, 0xc00457c, 0x2203021,
+0x24040001, 0x24050018, 0xc00457c, 0x2203021,
+0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
+0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
+0x97a20018, 0x30420004, 0x10400066, 0x3c114000,
+0x3c030001, 0x8c636f34, 0x24020005, 0x14620067,
+0x24040001, 0x24050019, 0x27b0001c, 0xc00457c,
+0x2003021, 0x24040001, 0x24050019, 0xc00457c,
+0x2003021, 0x97a2001c, 0x30430700, 0x24020400,
+0x10620027, 0x28620401, 0x1040000e, 0x24020200,
+0x1062001f, 0x28620201, 0x10400005, 0x24020100,
+0x5062001e, 0x3c130001, 0x1000001e, 0x3c020004,
+0x24020300, 0x50620019, 0x3c130002, 0x10000019,
+0x3c020004, 0x24020600, 0x1062000d, 0x28620601,
+0x10400005, 0x24020500, 0x5062000b, 0x3c130002,
+0x10000010, 0x3c020004, 0x24020700, 0x1462000d,
+0x3c020004, 0x3c130004, 0x1000000a, 0x3c150008,
+0x10000006, 0x3c130004, 0x10000005, 0x3c150008,
+0x3c130001, 0x10000002, 0x3c150008, 0x3c150010,
+0x3c020004, 0x12620017, 0x3c028000, 0x8f820054,
+0x24100001, 0x3c010001, 0xac306d9c, 0x3c010001,
+0xac306d98, 0x3c010001, 0xac306da4, 0x3c010001,
+0xac306e24, 0x3c010001, 0xac226f30, 0x3c020001,
+0x16620022, 0x2758825, 0x2021, 0x2821,
+0xc004ddb, 0x34068000, 0x3c010001, 0x1000001b,
+0xac306e20, 0x2221025, 0x2b31825, 0x438825,
+0x97a6001c, 0x3c020001, 0x8c426f1c, 0x3c070001,
+0x8ce76d98, 0x3c040001, 0x24846c5c, 0xafa20010,
+0x97a2001e, 0x3c05000c, 0x34a50323, 0x3c010001,
+0xac206e20, 0xc002b3b, 0xafa20014, 0x10000007,
+0x0, 0x3c110002, 0x23e8821, 0x8e318ff0,
+0x3c027fff, 0x3442ffff, 0x2228824, 0x3c020001,
+0x8c426da8, 0x10400069, 0x0, 0x3c020001,
+0x8c426f1c, 0x10400002, 0x3c022000, 0x2228825,
+0x8fa8002c, 0x81140, 0x3c010002, 0x220821,
+0x8c229004, 0x10400003, 0x3c020020, 0x10000005,
+0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824,
+0x8fa8002c, 0x81140, 0x3c010002, 0x220821,
+0x8c22900c, 0x10400003, 0x3c020080, 0x1000004f,
+0x2228825, 0x3c02ff7f, 0x3442ffff, 0x1000004b,
+0x2228824, 0x8fa8002c, 0x82940, 0x3c030002,
+0x651821, 0x8c638ff8, 0x3c024000, 0x621024,
+0x14400008, 0x3c027fff, 0x3442ffff, 0x628824,
+0x3c010002, 0x250821, 0xac318ff0, 0x10000041,
+0x2201021, 0x3c020001, 0x8c426da8, 0x10400034,
+0x3c11c00c, 0x3c020001, 0x8c426e44, 0x3c04c00c,
+0x34842000, 0x3c030001, 0x8c636f1c, 0x2102b,
+0x21023, 0x441024, 0x10600003, 0x518825,
+0x3c022000, 0x2228825, 0x3c020002, 0x451021,
+0x8c429004, 0x10400003, 0x3c020020, 0x10000004,
+0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824,
+0x8fa8002c, 0x81140, 0x3c010002, 0x220821,
+0x8c22900c, 0x10400003, 0x3c020080, 0x10000004,
+0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824,
+0x3c020001, 0x8c426e30, 0x10400002, 0x3c020800,
+0x2228825, 0x3c020001, 0x8c426e34, 0x10400002,
+0x3c020400, 0x2228825, 0x3c020001, 0x8c426e38,
+0x10400006, 0x3c020100, 0x10000004, 0x2228825,
+0x3c027fff, 0x3442ffff, 0x628824, 0x8fa8002c,
+0x81140, 0x3c010002, 0x220821, 0xac318ff0,
+0x2201021, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
+0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
+0x3e00008, 0x27bd0050, 0x27bdffd0, 0xafb20028,
+0x809021, 0xafbf002c, 0xafb10024, 0xafb00020,
+0x8f840200, 0x3c100001, 0x8e106d98, 0x8f860220,
+0x24020002, 0x1202005c, 0x2e020003, 0x10400005,
+0x24020001, 0x1202000a, 0x121940, 0x1000010c,
+0x0, 0x24020004, 0x120200bf, 0x24020008,
+0x120200be, 0x128940, 0x10000105, 0x0,
+0x3c050002, 0xa32821, 0x8ca58ffc, 0x3c100002,
+0x2038021, 0x8e108ff4, 0x3c024000, 0xa21024,
+0x10400038, 0x3c020008, 0x2021024, 0x10400020,
+0x34840002, 0x3c020002, 0x431021, 0x8c429000,
+0x10400005, 0x34840020, 0x34840100, 0x3c020020,
+0x10000006, 0x2028025, 0x2402feff, 0x822024,
+0x3c02ffdf, 0x3442ffff, 0x2028024, 0x121140,
+0x3c010002, 0x220821, 0x8c229008, 0x10400005,
+0x3c020001, 0xc23025, 0x3c020080, 0x10000016,
+0x2028025, 0x3c02fffe, 0x3442ffff, 0xc23024,
+0x3c02ff7f, 0x3442ffff, 0x1000000f, 0x2028024,
+0x2402fedf, 0x822024, 0x3c02fffe, 0x3442ffff,
+0xc23024, 0x3c02ff5f, 0x3442ffff, 0x2028024,
+0x3c010002, 0x230821, 0xac209000, 0x3c010002,
+0x230821, 0xac209008, 0xaf840200, 0xaf860220,
+0x8f820220, 0x34420002, 0xaf820220, 0x1000000a,
+0x121140, 0x3c02bfff, 0x3442ffff, 0x8f830200,
+0x2028024, 0x2402fffd, 0x621824, 0xc003daf,
+0xaf830200, 0x121140, 0x3c010002, 0x220821,
+0x100000b7, 0xac308ff4, 0x3c020001, 0x8c426f1c,
+0x10400069, 0x24050004, 0x24040001, 0xc00457c,
+0x27a60018, 0x24040001, 0x24050005, 0xc00457c,
+0x27a6001a, 0x97a30018, 0x97a2001a, 0x3c040001,
+0x24846e48, 0x30630c00, 0x31a82, 0x30420c00,
+0x21282, 0xa7a2001a, 0x21080, 0x441021,
+0x431021, 0xa7a30018, 0x90480000, 0x24020001,
+0x3103ffff, 0x10620029, 0x28620002, 0x10400005,
+0x0, 0x10600009, 0x0, 0x1000003d,
+0x0, 0x10700013, 0x24020003, 0x1062002c,
+0x0, 0x10000037, 0x0, 0x8f820200,
+0x2403feff, 0x431024, 0xaf820200, 0x8f820220,
+0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220,
+0x3c010002, 0xac209004, 0x3c010002, 0x10000032,
+0xac20900c, 0x8f820200, 0x34420100, 0xaf820200,
+0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024,
+0xaf820220, 0x24020100, 0x3c010002, 0xac229004,
+0x3c010002, 0x10000024, 0xac20900c, 0x8f820200,
+0x2403feff, 0x431024, 0xaf820200, 0x8f820220,
+0x3c030001, 0x431025, 0xaf820220, 0x3c010002,
+0xac209004, 0x3c010002, 0x10000017, 0xac23900c,
+0x8f820200, 0x34420100, 0xaf820200, 0x8f820220,
+0x3c030001, 0x431025, 0xaf820220, 0x24020100,
+0x3c010002, 0xac229004, 0x3c010002, 0x1000000a,
+0xac23900c, 0x3c040001, 0x24846c80, 0x97a6001a,
+0x97a70018, 0x3c050001, 0x34a5ffff, 0xafa80010,
+0xc002b3b, 0xafa00014, 0x8f820200, 0x34420002,
+0x1000004b, 0xaf820200, 0x128940, 0x3c050002,
+0xb12821, 0x8ca58ff8, 0x3c100002, 0x2118021,
+0x8e108ff0, 0x3c024000, 0xa21024, 0x14400010,
+0x0, 0x3c020001, 0x8c426f1c, 0x14400005,
+0x3c02bfff, 0x8f820200, 0x34420002, 0xaf820200,
+0x3c02bfff, 0x3442ffff, 0xc003daf, 0x2028024,
+0x3c010002, 0x310821, 0x10000031, 0xac308ff0,
+0x3c020001, 0x8c426f1c, 0x10400005, 0x3c020020,
+0x3c020001, 0x8c426e44, 0x10400025, 0x3c020020,
+0xa21024, 0x10400007, 0x34840020, 0x24020100,
+0x3c010002, 0x310821, 0xac229004, 0x10000006,
+0x34840100, 0x3c010002, 0x310821, 0xac209004,
+0x2402feff, 0x822024, 0x3c020080, 0xa21024,
+0x10400007, 0x121940, 0x3c020001, 0x3c010002,
+0x230821, 0xac22900c, 0x10000008, 0xc23025,
+0x121140, 0x3c010002, 0x220821, 0xac20900c,
+0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200,
+0xaf860220, 0x8f820220, 0x34420002, 0xaf820220,
+0x121140, 0x3c010002, 0x220821, 0xac308ff0,
+0x8fbf002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
+0x3e00008, 0x27bd0030, 0x0, 0x1821,
+0x308400ff, 0x2405ffdf, 0x2406ffbf, 0x641007,
+0x30420001, 0x10400004, 0x0, 0x8f820044,
+0x10000003, 0x34420040, 0x8f820044, 0x461024,
+0xaf820044, 0x8f820044, 0x34420020, 0xaf820044,
+0x8f820044, 0x451024, 0xaf820044, 0x24630001,
+0x28620008, 0x5440ffee, 0x641007, 0x3e00008,
+0x0, 0x2c820008, 0x1040001b, 0x0,
+0x2405ffdf, 0x2406ffbf, 0x41880, 0x3c020001,
+0x24426e60, 0x621821, 0x24640004, 0x90620000,
+0x10400004, 0x0, 0x8f820044, 0x10000003,
+0x34420040, 0x8f820044, 0x461024, 0xaf820044,
+0x8f820044, 0x34420020, 0xaf820044, 0x8f820044,
+0x451024, 0xaf820044, 0x24630001, 0x64102b,
+0x1440ffee, 0x0, 0x3e00008, 0x0,
+0x0, 0x0, 0x0, 0x8f8400c4,
+0x8f8600e0, 0x8f8700e4, 0x2402fff8, 0xc22824,
+0x10e5001a, 0x27623ff8, 0x14e20002, 0x24e80008,
+0x27683000, 0x55050004, 0x8d0a0000, 0x30c20004,
+0x14400012, 0x805021, 0x8ce90000, 0x8f42013c,
+0x1494823, 0x49182b, 0x94eb0006, 0x10600002,
+0x25630050, 0x494821, 0x123182b, 0x50400003,
+0x8f4201fc, 0x3e00008, 0xe01021, 0xaf8800e8,
+0x24420001, 0xaf4201fc, 0xaf8800e4, 0x3e00008,
+0x1021, 0x3e00008, 0x0, 0x8f8300e4,
+0x27623ff8, 0x10620004, 0x24620008, 0xaf8200e8,
+0x3e00008, 0xaf8200e4, 0x27623000, 0xaf8200e8,
+0x3e00008, 0xaf8200e4, 0x3e00008, 0x0,
+0x0, 0x0, 0x0, 0x8f880120,
+0x27624fe0, 0x8f830128, 0x15020002, 0x25090020,
+0x27694800, 0x11230012, 0x8fa20010, 0xad040000,
+0xad050004, 0xad060008, 0xa507000e, 0x8fa30014,
+0xad020018, 0x8fa20018, 0xad03001c, 0x25030016,
+0xad020010, 0xad030014, 0xaf890120, 0x8f4300fc,
+0x24020001, 0x2463ffff, 0x3e00008, 0xaf4300fc,
+0x8f430324, 0x1021, 0x24630001, 0x3e00008,
+0xaf430324, 0x3e00008, 0x0, 0x8f880100,
+0x276247e0, 0x8f830108, 0x15020002, 0x25090020,
+0x27694000, 0x1123000f, 0x8fa20010, 0xad040000,
+0xad050004, 0xad060008, 0xa507000e, 0x8fa30014,
+0xad020018, 0x8fa20018, 0xad03001c, 0x25030016,
+0xad020010, 0xad030014, 0xaf890100, 0x3e00008,
+0x24020001, 0x8f430328, 0x1021, 0x24630001,
+0x3e00008, 0xaf430328, 0x3e00008, 0x0,
+0x0, 0x0, 0x0, 0x0 };
+static int tigon2FwRodata[/*(MAX_RODATA_LEN/4) + 1*/] = {
+0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f6677, 0x6d61696e, 0x2e632c76, 0x20312e31,
+0x2e322e34, 0x35203139, 0x39392f30, 0x312f3234,
+0x2030303a, 0x31303a35, 0x35207368, 0x75616e67,
+0x20457870, 0x20240000, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x6261644d, 0x656d537a,
+0x0, 0x68775665, 0x72000000, 0x62616448,
+0x77566572, 0x0, 0x2a2a4441, 0x574e5f41,
+0x0, 0x74785278, 0x4266537a, 0x0,
+0x62664174, 0x6e4d726b, 0x0, 0x7265645a,
+0x6f6e6531, 0x0, 0x70636943, 0x6f6e6600,
+0x67656e43, 0x6f6e6600, 0x2a646d61, 0x5244666c,
+0x0, 0x2a50414e, 0x49432a00, 0x2e2e2f2e,
+0x2e2f2e2e, 0x2f2e2e2f, 0x2e2e2f73, 0x72632f6e,
+0x69632f66, 0x77322f63, 0x6f6d6d6f, 0x6e2f6677,
+0x6d61696e, 0x2e630000, 0x72636246, 0x6c616773,
+0x0, 0x62616452, 0x78526362, 0x0,
+0x676c6f62, 0x466c6773, 0x0, 0x2b5f6469,
+0x73705f6c, 0x6f6f7000, 0x2b65765f, 0x68616e64,
+0x6c657200, 0x63616e74, 0x31446d61, 0x0,
+0x2b715f64, 0x6d615f74, 0x6f5f6e69, 0x635f636b,
+0x73756d00, 0x2b685f73, 0x656e645f, 0x64617461,
+0x5f726561, 0x64795f63, 0x6b73756d, 0x0,
+0x2b685f64, 0x6d615f72, 0x645f6173, 0x73697374,
+0x5f636b73, 0x756d0000, 0x74436b73, 0x6d4f6e00,
+0x2b715f64, 0x6d615f74, 0x6f5f6e69, 0x63000000,
+0x2b685f73, 0x656e645f, 0x64617461, 0x5f726561,
+0x64790000, 0x2b685f64, 0x6d615f72, 0x645f6173,
+0x73697374, 0x0, 0x74436b73, 0x6d4f6666,
+0x0, 0x2b685f73, 0x656e645f, 0x62645f72,
+0x65616479, 0x0, 0x68737453, 0x52696e67,
+0x0, 0x62616453, 0x52696e67, 0x0,
+0x6e696353, 0x52696e67, 0x0, 0x77446d61,
+0x416c6c41, 0x0, 0x2b715f64, 0x6d615f74,
+0x6f5f686f, 0x73745f63, 0x6b73756d, 0x0,
+0x2b685f6d, 0x61635f72, 0x785f636f, 0x6d705f63,
+0x6b73756d, 0x0, 0x2b685f64, 0x6d615f77,
+0x725f6173, 0x73697374, 0x5f636b73, 0x756d0000,
+0x72436b73, 0x6d4f6e00, 0x2b715f64, 0x6d615f74,
+0x6f5f686f, 0x73740000, 0x2b685f6d, 0x61635f72,
+0x785f636f, 0x6d700000, 0x2b685f64, 0x6d615f77,
+0x725f6173, 0x73697374, 0x0, 0x72436b73,
+0x6d4f6666, 0x0, 0x2b685f72, 0x6563765f,
+0x62645f72, 0x65616479, 0x0, 0x2b685f72,
+0x6563765f, 0x6a756d62, 0x6f5f6264, 0x5f726561,
+0x64790000, 0x2b685f72, 0x6563765f, 0x6d696e69,
+0x5f62645f, 0x72656164, 0x79000000, 0x2b6d685f,
+0x636f6d6d, 0x616e6400, 0x2b685f74, 0x696d6572,
+0x0, 0x2b685f64, 0x6f5f7570, 0x64617465,
+0x5f74785f, 0x636f6e73, 0x0, 0x2b685f64,
+0x6f5f7570, 0x64617465, 0x5f72785f, 0x70726f64,
+0x0, 0x2b636b73, 0x756d3136, 0x0,
+0x2b706565, 0x6b5f6d61, 0x635f7278, 0x5f776100,
+0x2b706565, 0x6b5f6d61, 0x635f7278, 0x0,
+0x2b646571, 0x5f6d6163, 0x5f727800, 0x2b685f6d,
+0x61635f72, 0x785f6174, 0x746e0000, 0x62616452,
+0x6574537a, 0x0, 0x72784264, 0x4266537a,
+0x0, 0x2b6e756c, 0x6c5f6861, 0x6e646c65,
+0x72000000, 0x66774f70, 0x4661696c, 0x0,
+0x2b685f75, 0x70646174, 0x655f6c65, 0x64340000,
+0x2b685f75, 0x70646174, 0x655f6c65, 0x64360000,
+0x2b685f75, 0x70646174, 0x655f6c65, 0x64320000,
+0x696e7453, 0x74617465, 0x0, 0x2a2a696e,
+0x69744370, 0x0, 0x23736372, 0x65616d00,
+0x69537461, 0x636b4572, 0x0, 0x70726f62,
+0x654d656d, 0x0, 0x2a2a4441, 0x574e5f42,
+0x0, 0x2b73775f, 0x646d615f, 0x61737369,
+0x73745f70, 0x6c75735f, 0x74696d65, 0x72000000,
+0x2b267072, 0x656c6f61, 0x645f7772, 0x5f646573,
+0x63720000, 0x2b267072, 0x656c6f61, 0x645f7264,
+0x5f646573, 0x63720000, 0x2b685f68, 0x665f7469,
+0x6d657200, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f7469, 0x6d65722e, 0x632c7620, 0x312e312e,
+0x322e3335, 0x20313939, 0x392f3031, 0x2f323720,
+0x31393a30, 0x393a3530, 0x20686179, 0x65732045,
+0x78702024, 0x0, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x542d446d, 0x61526432,
+0x0, 0x542d446d, 0x61526431, 0x0,
+0x542d446d, 0x61526442, 0x0, 0x542d446d,
+0x61577232, 0x0, 0x542d446d, 0x61577231,
+0x0, 0x542d446d, 0x61577242, 0x0,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f636f, 0x6d6d616e, 0x642e632c, 0x7620312e,
+0x312e322e, 0x32382031, 0x3939392f, 0x30312f32,
+0x30203139, 0x3a34393a, 0x34392073, 0x6875616e,
+0x67204578, 0x70202400, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x3f48636d, 0x644d6278,
+0x0, 0x3f636d64, 0x48737453, 0x0,
+0x3f636d64, 0x4d634d64, 0x0, 0x3f636d64,
+0x50726f6d, 0x0, 0x3f636d64, 0x4c696e6b,
+0x0, 0x3f636d64, 0x45727200, 0x86ac,
+0x8e5c, 0x8e5c, 0x8de4, 0x8b78,
+0x8e30, 0x8e5c, 0x8790, 0x8800,
+0x8990, 0x8a68, 0x8a34, 0x8e5c,
+0x8870, 0x8b24, 0x8e5c, 0x8b34,
+0x87b4, 0x8824, 0x0, 0x0,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f6d63, 0x6173742e, 0x632c7620, 0x312e312e,
+0x322e3820, 0x31393938, 0x2f31322f, 0x30382030,
+0x323a3336, 0x3a333620, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x6164644d, 0x63447570,
+0x0, 0x6164644d, 0x6346756c, 0x0,
+0x64656c4d, 0x634e6f45, 0x0, 0x0,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f646d, 0x612e632c, 0x7620312e, 0x312e322e,
+0x32342031, 0x3939382f, 0x31322f32, 0x31203030,
+0x3a33333a, 0x30392073, 0x6875616e, 0x67204578,
+0x70202400, 0x65767452, 0x6e674600, 0x51657674,
+0x46000000, 0x51657674, 0x505f4600, 0x4d657674,
+0x526e6746, 0x0, 0x4d516576, 0x74460000,
+0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46,
+0x0, 0x5173436f, 0x6e734600, 0x51725072,
+0x6f644600, 0x7377446d, 0x614f6666, 0x0,
+0x31446d61, 0x4f6e0000, 0x7377446d, 0x614f6e00,
+0x2372446d, 0x6141544e, 0x0, 0x72446d61,
+0x41544e30, 0x0, 0x72446d61, 0x41544e31,
+0x0, 0x72446d61, 0x34476200, 0x2a50414e,
+0x49432a00, 0x2e2e2f2e, 0x2e2f2e2e, 0x2f2e2e2f,
+0x2e2e2f73, 0x72632f6e, 0x69632f66, 0x77322f63,
+0x6f6d6d6f, 0x6e2f646d, 0x612e6300, 0x2377446d,
+0x6141544e, 0x0, 0x77446d61, 0x41544e30,
+0x0, 0x77446d61, 0x41544e31, 0x0,
+0x77446d61, 0x34476200, 0x0, 0x0,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f7472, 0x6163652e, 0x632c7620, 0x312e312e,
+0x322e3520, 0x31393938, 0x2f30392f, 0x33302031,
+0x383a3530, 0x3a323820, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x0, 0x0,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f6461, 0x74612e63, 0x2c762031, 0x2e312e32,
+0x2e313220, 0x31393939, 0x2f30312f, 0x32302031,
+0x393a3439, 0x3a353120, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x46575f56, 0x45525349,
+0x4f4e3a20, 0x23312046, 0x72692041, 0x70722037,
+0x2031373a, 0x35373a35, 0x32205044, 0x54203230,
+0x30300000, 0x46575f43, 0x4f4d5049, 0x4c455f54,
+0x494d453a, 0x2031373a, 0x35373a35, 0x32000000,
+0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064,
+0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049,
+0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465,
+0x0, 0x46575f43, 0x4f4d5049, 0x4c455f44,
+0x4f4d4149, 0x4e3a2065, 0x6e672e61, 0x6374656f,
+0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049,
+0x4c45523a, 0x20676363, 0x20766572, 0x73696f6e,
+0x20322e37, 0x2e320000, 0x0, 0x12041100,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f6d65, 0x6d2e632c, 0x7620312e, 0x312e322e,
+0x35203139, 0x39382f30, 0x392f3330, 0x2031383a,
+0x35303a30, 0x38207368, 0x75616e67, 0x20457870,
+0x20240000, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f7365, 0x6e642e63, 0x2c762031, 0x2e312e32,
+0x2e343420, 0x31393938, 0x2f31322f, 0x32312030,
+0x303a3333, 0x3a313820, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x69736e74, 0x54637055,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f7265, 0x63762e63, 0x2c762031, 0x2e312e32,
+0x2e353320, 0x31393939, 0x2f30312f, 0x31362030,
+0x323a3535, 0x3a343320, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x724d6163, 0x43686b30,
+0x0, 0x72784672, 0x6d324c67, 0x0,
+0x72784e6f, 0x53744264, 0x0, 0x72784e6f,
+0x4d694264, 0x0, 0x72784e6f, 0x4a6d4264,
+0x0, 0x7278436b, 0x446d6146, 0x0,
+0x72785144, 0x6d457846, 0x0, 0x72785144,
+0x6d614600, 0x72785144, 0x4c426446, 0x0,
+0x72785144, 0x6d426446, 0x0, 0x72784372,
+0x63506164, 0x0, 0x72536d51, 0x446d6146,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f6d61, 0x632e632c, 0x7620312e, 0x312e322e,
+0x32322031, 0x3939382f, 0x31322f30, 0x38203032,
+0x3a33363a, 0x33302073, 0x6875616e, 0x67204578,
+0x70202400, 0x65767452, 0x6e674600, 0x51657674,
+0x46000000, 0x51657674, 0x505f4600, 0x4d657674,
+0x526e6746, 0x0, 0x4d516576, 0x74460000,
+0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46,
+0x0, 0x5173436f, 0x6e734600, 0x51725072,
+0x6f644600, 0x6d616354, 0x68726573, 0x0,
+0x23744d61, 0x6341544e, 0x0, 0x23724d61,
+0x6341544e, 0x0, 0x72656d41, 0x73737274,
+0x0, 0x6c696e6b, 0x444f574e, 0x0,
+0x6c696e6b, 0x55500000, 0x0, 0x0,
+0x0, 0x24486561, 0x6465723a, 0x202f7072,
+0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
+0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
+0x6e2f636b, 0x73756d2e, 0x632c7620, 0x312e312e,
+0x322e3920, 0x31393939, 0x2f30312f, 0x31342030,
+0x303a3033, 0x3a343820, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x65767452, 0x6e674600,
+0x51657674, 0x46000000, 0x51657674, 0x505f4600,
+0x4d657674, 0x526e6746, 0x0, 0x4d516576,
+0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
+0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
+0x51725072, 0x6f644600, 0x0, 0x0,
+0x0, 0x50726f62, 0x65506879, 0x0,
+0x6c6e6b41, 0x53535254, 0x0, 0x109a4,
+0x10a1c, 0x10a50, 0x10a7c, 0x11050,
+0x10aa8, 0x10b10, 0x111fc, 0x10dc0,
+0x10c68, 0x10c80, 0x10cc4, 0x10cec,
+0x10d0c, 0x10d34, 0x111fc, 0x10dc0,
+0x10df8, 0x10e10, 0x10e40, 0x10e68,
+0x10e88, 0x10eb0, 0x0, 0x10fdc,
+0x11008, 0x1102c, 0x111fc, 0x11050,
+0x11078, 0x11108, 0x0, 0x0,
+0x0, 0x1186c, 0x1193c, 0x11a14,
+0x11ae4, 0x11b40, 0x11c1c, 0x11c44,
+0x11d20, 0x11d48, 0x11ef0, 0x11f18,
+0x120c0, 0x122b8, 0x1254c, 0x12460,
+0x1254c, 0x12578, 0x120e8, 0x12290,
+0x7273745f, 0x676d6969, 0x0, 0x12608,
+0x12640, 0x12728, 0x13374, 0x133b4,
+0x133cc, 0x7365746c, 0x6f6f7000, 0x0,
+0x0, 0x13bbc, 0x13bfc, 0x13c8c,
+0x13cd0, 0x13d34, 0x13dc0, 0x13df4,
+0x13e7c, 0x13f14, 0x13fe4, 0x14024,
+0x140a8, 0x140cc, 0x141dc, 0x646f4261,
+0x73655067, 0x0, 0x0, 0x0,
+0x0, 0x73746d61, 0x634c4e4b, 0x0,
+0x6765746d, 0x636c6e6b, 0x0, 0x14ed8,
+0x14ed8, 0x14b8c, 0x14bd8, 0x14c24,
+0x14ed8, 0x7365746d, 0x61636163, 0x74000000,
+0x0, 0x0 };
+static int tigon2FwData[/*(MAX_DATA_LEN/4) + 1*/] = {
+0x1,
+0x1, 0x1, 0xc001fc, 0x3ffc,
+0xc00000, 0x416c7465, 0x6f6e2041, 0x63654e49,
+0x43205600, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x416c7465,
+0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242,
+0x0, 0x0, 0x0, 0x1ffffc,
+0x1fff7c, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x60cf00,
+0x60, 0xcf000000, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x3, 0x0,
+0x1, 0x0, 0x0, 0x0,
+0x1, 0x0, 0x1, 0x0,
+0x0, 0x0, 0x0, 0x1,
+0x1, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x1000000, 0x21000000,
+0x12000140, 0x0, 0x0, 0x20000000,
+0x120000a0, 0x0, 0x12000060, 0x12000180,
+0x120001e0, 0x0, 0x0, 0x0,
+0x1, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x2,
+0x0, 0x0, 0x30001, 0x1,
+0x30201, 0x0, 0x0, 0x1010101,
+0x1010100, 0x10100, 0x1010001, 0x10001,
+0x1000101, 0x101, 0x0, 0x0 };
--- /dev/null
+++ b/os/boot.original/pc/etherif.h
@@ -1,0 +1,47 @@
+typedef struct RingBuf {
+ uchar owner;
+ uchar unused;
+ ushort len;
+ uchar pkt[sizeof(Etherpkt)];
+} RingBuf;
+
+enum {
+ Host = 0, /* buffer owned by host */
+ Interface = 1, /* buffer owned by card */
+
+ Nrb = 32, /* default number of receive buffers */
+ Ntb = 8, /* default number of transmit buffers */
+};
+
+typedef struct Ether Ether;
+struct Ether {
+ ISAConf; /* hardware info */
+ int ctlrno;
+ int state; /* 0: unfound, 1: found, 2: attaching */
+ int tbdf;
+
+ void (*attach)(Ether*); /* filled in by reset routine */
+ void (*transmit)(Ether*);
+ void (*interrupt)(Ureg*, void*);
+ void (*detach)(Ether*);
+ void *ctlr;
+
+ ushort nrb; /* number of software receive buffers */
+ ushort ntb; /* number of software transmit buffers */
+ RingBuf *rb; /* software receive buffers */
+ RingBuf *tb; /* software transmit buffers */
+
+ ushort rh; /* first receive buffer belonging to host */
+ ushort ri; /* first receive buffer belonging to card */
+
+ ushort th; /* first transmit buffer belonging to host */
+ ushort ti; /* first transmit buffer belonging to card */
+ int tbusy; /* transmitter is busy */
+ int mbps; /* zero means link down */
+};
+
+extern void etherrloop(Ether*, Etherpkt*, long);
+extern void addethercard(char*, int(*)(Ether*));
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
--- /dev/null
+++ b/os/boot.original/pc/etherigbe.c
@@ -1,0 +1,1741 @@
+/*
+ * bootstrap driver for
+ * Intel RS-82543GC Gigabit Ethernet PCI Controllers
+ * as found on the Intel PRO/1000[FT] Server Adapter.
+ * The older non-[FT] cards use the 82542 (LSI L2A1157) chip; no attempt
+ * is made to handle the older chip although it should be possible.
+ *
+ * updated just enough to cope with the
+ * Intel 8254[0347]NN Gigabit Ethernet Controller
+ * as found on the Intel PRO/1000 series of adapters:
+ * 82540EM Intel PRO/1000 MT
+ * 82543GC Intel PRO/1000 T
+ * 82544EI Intel PRO/1000 XT
+ * 82547EI built-in
+ *
+ * The datasheet is not very clear about running on a big-endian system
+ * and this driver assumes little-endian throughout.
+ * To do:
+ * GMII/MII
+ * check recovery from receive no buffers condition
+ * automatic ett adjustment
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+enum {
+ Debug = 0, /* mostly for X60 debugging */
+};
+enum {
+ i82542 = (0x1000<<16)|0x8086,
+ i82543gc = (0x1004<<16)|0x8086,
+ i82544ei = (0x1008<<16)|0x8086,
+ i82540em = (0x100E<<16)|0x8086,
+ i82546eb = (0x1010<<16)|0x8086,
+ i82547ei = (0x1019<<16)|0x8086,
+ i82540eplp = (0x101E<<16)|0x8086,
+ i82547gi = (0x1075<<16)|0x8086,
+ i82541gi = (0x1076<<16)|0x8086,
+ i82541gi2 = (0x1077<<16)|0x8086,
+ i82546gb = (0x1079<<16)|0x8086,
+ i82541pi = (0x107c<<16)|0x8086,
+};
+
+/* compatibility with cpu kernels */
+#define iallocb allocb
+#ifndef CACHELINESZ
+#define CACHELINESZ 32 /* pentium & later */
+#endif
+
+/* from pci.c */
+enum
+{ /* command register (pcidev->pcr) */
+ IOen = (1<<0),
+ MEMen = (1<<1),
+ MASen = (1<<2),
+ MemWrInv = (1<<4),
+ PErrEn = (1<<6),
+ SErrEn = (1<<8),
+};
+enum {
+ Ctrl = 0x00000000, /* Device Control */
+ Status = 0x00000008, /* Device Status */
+ Eecd = 0x00000010, /* EEPROM/Flash Control/Data */
+ Ctrlext = 0x00000018, /* Extended Device Control */
+ Mdic = 0x00000020, /* MDI Control */
+ Fcal = 0x00000028, /* Flow Control Address Low */
+ Fcah = 0x0000002C, /* Flow Control Address High */
+ Fct = 0x00000030, /* Flow Control Type */
+ Icr = 0x000000C0, /* Interrupt Cause Read */
+ Ics = 0x000000C8, /* Interrupt Cause Set */
+ Ims = 0x000000D0, /* Interrupt Mask Set/Read */
+ Imc = 0x000000D8, /* Interrupt mask Clear */
+ Rctl = 0x00000100, /* Receive Control */
+ Fcttv = 0x00000170, /* Flow Control Transmit Timer Value */
+ Txcw = 0x00000178, /* Transmit Configuration Word */
+ Tctl = 0x00000400, /* Transmit Control */
+ Tipg = 0x00000410, /* Transmit IPG */
+ Tbt = 0x00000448, /* Transmit Burst Timer */
+ Ait = 0x00000458, /* Adaptive IFS Throttle */
+ Fcrtl = 0x00002160, /* Flow Control RX Threshold Low */
+ Fcrth = 0x00002168, /* Flow Control Rx Threshold High */
+ Rdbal = 0x00002800, /* Rdesc Base Address Low */
+ Rdbah = 0x00002804, /* Rdesc Base Address High */
+ Rdlen = 0x00002808, /* Receive Descriptor Length */
+ Rdh = 0x00002810, /* Receive Descriptor Head */
+ Rdt = 0x00002818, /* Receive Descriptor Tail */
+ Rdtr = 0x00002820, /* Receive Descriptor Timer Ring */
+ Rxdctl = 0x00002828, /* Receive Descriptor Control */
+ Radv = 0x0000282C, /* Receive Interrupt Absolute Delay Timer */
+ Txdmac = 0x00003000, /* Transfer DMA Control */
+ Ett = 0x00003008, /* Early Transmit Control */
+ Tdbal = 0x00003800, /* Tdesc Base Address Low */
+ Tdbah = 0x00003804, /* Tdesc Base Address High */
+ Tdlen = 0x00003808, /* Transmit Descriptor Length */
+ Tdh = 0x00003810, /* Transmit Descriptor Head */
+ Tdt = 0x00003818, /* Transmit Descriptor Tail */
+ Tidv = 0x00003820, /* Transmit Interrupt Delay Value */
+ Txdctl = 0x00003828, /* Transmit Descriptor Control */
+ Tadv = 0x0000382C, /* Transmit Interrupt Absolute Delay Timer */
+
+ Statistics = 0x00004000, /* Start of Statistics Area */
+ Gorcl = 0x88/4, /* Good Octets Received Count */
+ Gotcl = 0x90/4, /* Good Octets Transmitted Count */
+ Torl = 0xC0/4, /* Total Octets Received */
+ Totl = 0xC8/4, /* Total Octets Transmitted */
+ Nstatistics = 64,
+
+ Rxcsum = 0x00005000, /* Receive Checksum Control */
+ Mta = 0x00005200, /* Multicast Table Array */
+ Ral = 0x00005400, /* Receive Address Low */
+ Rah = 0x00005404, /* Receive Address High */
+ Manc = 0x00005820, /* Management Control */
+};
+
+enum { /* Ctrl */
+ Bem = 0x00000002, /* Big Endian Mode */
+ Prior = 0x00000004, /* Priority on the PCI bus */
+ Lrst = 0x00000008, /* Link Reset */
+ Asde = 0x00000020, /* Auto-Speed Detection Enable */
+ Slu = 0x00000040, /* Set Link Up */
+ Ilos = 0x00000080, /* Invert Loss of Signal (LOS) */
+ SspeedMASK = 0x00000300, /* Speed Selection */
+ SspeedSHIFT = 8,
+ Sspeed10 = 0x00000000, /* 10Mb/s */
+ Sspeed100 = 0x00000100, /* 100Mb/s */
+ Sspeed1000 = 0x00000200, /* 1000Mb/s */
+ Frcspd = 0x00000800, /* Force Speed */
+ Frcdplx = 0x00001000, /* Force Duplex */
+ SwdpinsloMASK = 0x003C0000, /* Software Defined Pins - lo nibble */
+ SwdpinsloSHIFT = 18,
+ SwdpioloMASK = 0x03C00000, /* Software Defined Pins - I or O */
+ SwdpioloSHIFT = 22,
+ Devrst = 0x04000000, /* Device Reset */
+ Rfce = 0x08000000, /* Receive Flow Control Enable */
+ Tfce = 0x10000000, /* Transmit Flow Control Enable */
+ Vme = 0x40000000, /* VLAN Mode Enable */
+};
+
+/*
+ * can't find Tckok nor Rbcok in any Intel docs,
+ * but even 82543gc docs define Lanid.
+ */
+enum { /* Status */
+ Lu = 0x00000002, /* Link Up */
+ Lanid = 0x0000000C, /* mask for Lan ID. (function id) */
+// Tckok = 0x00000004, /* Transmit clock is running */
+// Rbcok = 0x00000008, /* Receive clock is running */
+ Txoff = 0x00000010, /* Transmission Paused */
+ Tbimode = 0x00000020, /* TBI Mode Indication */
+ SpeedMASK = 0x000000C0,
+ Speed10 = 0x00000000, /* 10Mb/s */
+ Speed100 = 0x00000040, /* 100Mb/s */
+ Speed1000 = 0x00000080, /* 1000Mb/s */
+ Mtxckok = 0x00000400, /* MTX clock is running */
+ Pci66 = 0x00000800, /* PCI Bus speed indication */
+ Bus64 = 0x00001000, /* PCI Bus width indication */
+};
+
+enum { /* Ctrl and Status */
+ Fd = 0x00000001, /* Full-Duplex */
+ AsdvMASK = 0x00000300,
+ Asdv10 = 0x00000000, /* 10Mb/s */
+ Asdv100 = 0x00000100, /* 100Mb/s */
+ Asdv1000 = 0x00000200, /* 1000Mb/s */
+};
+
+enum { /* Eecd */
+ Sk = 0x00000001, /* Clock input to the EEPROM */
+ Cs = 0x00000002, /* Chip Select */
+ Di = 0x00000004, /* Data Input to the EEPROM */
+ Do = 0x00000008, /* Data Output from the EEPROM */
+ Areq = 0x00000040, /* EEPROM Access Request */
+ Agnt = 0x00000080, /* EEPROM Access Grant */
+ Eepresent = 0x00000100, /* EEPROM Present */
+ Eesz256 = 0x00000200, /* EEPROM is 256 words not 64 */
+ Eeszaddr = 0x00000400, /* EEPROM size for 8254[17] */
+ Spi = 0x00002000, /* EEPROM is SPI not Microwire */
+};
+
+enum { /* Ctrlext */
+ Gpien = 0x0000000F, /* General Purpose Interrupt Enables */
+ SwdpinshiMASK = 0x000000F0, /* Software Defined Pins - hi nibble */
+ SwdpinshiSHIFT = 4,
+ SwdpiohiMASK = 0x00000F00, /* Software Defined Pins - I or O */
+ SwdpiohiSHIFT = 8,
+ Asdchk = 0x00001000, /* ASD Check */
+ Eerst = 0x00002000, /* EEPROM Reset */
+ Ips = 0x00004000, /* Invert Power State */
+ Spdbyps = 0x00008000, /* Speed Select Bypass */
+};
+
+enum { /* EEPROM content offsets */
+ Ea = 0x00, /* Ethernet Address */
+ Cf = 0x03, /* Compatibility Field */
+ Pba = 0x08, /* Printed Board Assembly number */
+ Icw1 = 0x0A, /* Initialization Control Word 1 */
+ Sid = 0x0B, /* Subsystem ID */
+ Svid = 0x0C, /* Subsystem Vendor ID */
+ Did = 0x0D, /* Device ID */
+ Vid = 0x0E, /* Vendor ID */
+ Icw2 = 0x0F, /* Initialization Control Word 2 */
+};
+
+enum { /* Mdic */
+ MDIdMASK = 0x0000FFFF, /* Data */
+ MDIdSHIFT = 0,
+ MDIrMASK = 0x001F0000, /* PHY Register Address */
+ MDIrSHIFT = 16,
+ MDIpMASK = 0x03E00000, /* PHY Address */
+ MDIpSHIFT = 21,
+ MDIwop = 0x04000000, /* Write Operation */
+ MDIrop = 0x08000000, /* Read Operation */
+ MDIready = 0x10000000, /* End of Transaction */
+ MDIie = 0x20000000, /* Interrupt Enable */
+ MDIe = 0x40000000, /* Error */
+};
+
+enum { /* Icr, Ics, Ims, Imc */
+ Txdw = 0x00000001, /* Transmit Descriptor Written Back */
+ Txqe = 0x00000002, /* Transmit Queue Empty */
+ Lsc = 0x00000004, /* Link Status Change */
+ Rxseq = 0x00000008, /* Receive Sequence Error */
+ Rxdmt0 = 0x00000010, /* Rdesc Minimum Threshold Reached */
+ Rxo = 0x00000040, /* Receiver Overrun */
+ Rxt0 = 0x00000080, /* Receiver Timer Interrupt */
+ Mdac = 0x00000200, /* MDIO Access Completed */
+ Rxcfg = 0x00000400, /* Receiving /C/ ordered sets */
+ Gpi0 = 0x00000800, /* General Purpose Interrupts */
+ Gpi1 = 0x00001000,
+ Gpi2 = 0x00002000,
+ Gpi3 = 0x00004000,
+};
+
+/*
+ * The Mdic register isn't implemented on the 82543GC,
+ * the software defined pins are used instead.
+ * These definitions work for the Intel PRO/1000 T Server Adapter.
+ * The direction pin bits are read from the EEPROM.
+ */
+enum {
+ Mdd = ((1<<2)<<SwdpinsloSHIFT), /* data */
+ Mddo = ((1<<2)<<SwdpioloSHIFT), /* pin direction */
+ Mdc = ((1<<3)<<SwdpinsloSHIFT), /* clock */
+ Mdco = ((1<<3)<<SwdpioloSHIFT), /* pin direction */
+ Mdr = ((1<<0)<<SwdpinshiSHIFT), /* reset */
+ Mdro = ((1<<0)<<SwdpiohiSHIFT), /* pin direction */
+};
+
+enum { /* Txcw */
+ TxcwFd = 0x00000020, /* Full Duplex */
+ TxcwHd = 0x00000040, /* Half Duplex */
+ TxcwPauseMASK = 0x00000180, /* Pause */
+ TxcwPauseSHIFT = 7,
+ TxcwPs = (1<<TxcwPauseSHIFT), /* Pause Supported */
+ TxcwAs = (2<<TxcwPauseSHIFT), /* Asymmetric FC desired */
+ TxcwRfiMASK = 0x00003000, /* Remote Fault Indication */
+ TxcwRfiSHIFT = 12,
+ TxcwNpr = 0x00008000, /* Next Page Request */
+ TxcwConfig = 0x40000000, /* Transmit COnfig Control */
+ TxcwAne = 0x80000000, /* Auto-Negotiation Enable */
+};
+
+enum { /* Rctl */
+ Rrst = 0x00000001, /* Receiver Software Reset */
+ Ren = 0x00000002, /* Receiver Enable */
+ Sbp = 0x00000004, /* Store Bad Packets */
+ Upe = 0x00000008, /* Unicast Promiscuous Enable */
+ Mpe = 0x00000010, /* Multicast Promiscuous Enable */
+ Lpe = 0x00000020, /* Long Packet Reception Enable */
+ LbmMASK = 0x000000C0, /* Loopback Mode */
+ LbmOFF = 0x00000000, /* No Loopback */
+ LbmTBI = 0x00000040, /* TBI Loopback */
+ LbmMII = 0x00000080, /* GMII/MII Loopback */
+ LbmXCVR = 0x000000C0, /* Transceiver Loopback */
+ RdtmsMASK = 0x00000300, /* Rdesc Minimum Threshold Size */
+ RdtmsHALF = 0x00000000, /* Threshold is 1/2 Rdlen */
+ RdtmsQUARTER = 0x00000100, /* Threshold is 1/4 Rdlen */
+ RdtmsEIGHTH = 0x00000200, /* Threshold is 1/8 Rdlen */
+ MoMASK = 0x00003000, /* Multicast Offset */
+ Bam = 0x00008000, /* Broadcast Accept Mode */
+ BsizeMASK = 0x00030000, /* Receive Buffer Size */
+ Bsize2048 = 0x00000000,
+ Bsize1024 = 0x00010000,
+ Bsize512 = 0x00020000,
+ Bsize256 = 0x00030000,
+ Vfe = 0x00040000, /* VLAN Filter Enable */
+ Cfien = 0x00080000, /* Canonical Form Indicator Enable */
+ Cfi = 0x00100000, /* Canonical Form Indicator value */
+ Dpf = 0x00400000, /* Discard Pause Frames */
+ Pmcf = 0x00800000, /* Pass MAC Control Frames */
+ Bsex = 0x02000000, /* Buffer Size Extension */
+ Secrc = 0x04000000, /* Strip CRC from incoming packet */
+};
+
+enum { /* Tctl */
+ Trst = 0x00000001, /* Transmitter Software Reset */
+ Ten = 0x00000002, /* Transmit Enable */
+ Psp = 0x00000008, /* Pad Short Packets */
+ CtMASK = 0x00000FF0, /* Collision Threshold */
+ CtSHIFT = 4,
+ ColdMASK = 0x003FF000, /* Collision Distance */
+ ColdSHIFT = 12,
+ Swxoff = 0x00400000, /* Sofware XOFF Transmission */
+ Pbe = 0x00800000, /* Packet Burst Enable */
+ Rtlc = 0x01000000, /* Re-transmit on Late Collision */
+ Nrtu = 0x02000000, /* No Re-transmit on Underrrun */
+};
+
+enum { /* [RT]xdctl */
+ PthreshMASK = 0x0000003F, /* Prefetch Threshold */
+ PthreshSHIFT = 0,
+ HthreshMASK = 0x00003F00, /* Host Threshold */
+ HthreshSHIFT = 8,
+ WthreshMASK = 0x003F0000, /* Writebacj Threshold */
+ WthreshSHIFT = 16,
+ Gran = 0x01000000, /* Granularity */
+};
+
+enum { /* Rxcsum */
+ PcssMASK = 0x000000FF, /* Packet Checksum Start */
+ PcssSHIFT = 0,
+ Ipofl = 0x00000100, /* IP Checksum Off-load Enable */
+ Tuofl = 0x00000200, /* TCP/UDP Checksum Off-load Enable */
+};
+
+enum { /* Manc */
+ Arpen = 0x00002000, /* Enable ARP Request Filtering */
+};
+
+typedef struct Rdesc { /* Receive Descriptor */
+ uint addr[2];
+ ushort length;
+ ushort checksum;
+ uchar status;
+ uchar errors;
+ ushort special;
+} Rdesc;
+
+enum { /* Rdesc status */
+ Rdd = 0x01, /* Descriptor Done */
+ Reop = 0x02, /* End of Packet */
+ Ixsm = 0x04, /* Ignore Checksum Indication */
+ Vp = 0x08, /* Packet is 802.1Q (matched VET) */
+ Tcpcs = 0x20, /* TCP Checksum Calculated on Packet */
+ Ipcs = 0x40, /* IP Checksum Calculated on Packet */
+ Pif = 0x80, /* Passed in-exact filter */
+};
+
+enum { /* Rdesc errors */
+ Ce = 0x01, /* CRC Error or Alignment Error */
+ Se = 0x02, /* Symbol Error */
+ Seq = 0x04, /* Sequence Error */
+ Cxe = 0x10, /* Carrier Extension Error */
+ Tcpe = 0x20, /* TCP/UDP Checksum Error */
+ Ipe = 0x40, /* IP Checksum Error */
+ Rxe = 0x80, /* RX Data Error */
+};
+
+typedef struct Tdesc { /* Legacy+Normal Transmit Descriptor */
+ uint addr[2];
+ uint control; /* varies with descriptor type */
+ uint status; /* varies with descriptor type */
+} Tdesc;
+
+enum { /* Tdesc control */
+ LenMASK = 0x000FFFFF, /* Data/Packet Length Field */
+ LenSHIFT = 0,
+ DtypeCD = 0x00000000, /* Data Type 'Context Descriptor' */
+ DtypeDD = 0x00100000, /* Data Type 'Data Descriptor' */
+ PtypeTCP = 0x01000000, /* TCP/UDP Packet Type (CD) */
+ Teop = 0x01000000, /* End of Packet (DD) */
+ PtypeIP = 0x02000000, /* IP Packet Type (CD) */
+ Ifcs = 0x02000000, /* Insert FCS (DD) */
+ Tse = 0x04000000, /* TCP Segmentation Enable */
+ Rs = 0x08000000, /* Report Status */
+ Rps = 0x10000000, /* Report Status Sent */
+ Dext = 0x20000000, /* Descriptor Extension */
+ Vle = 0x40000000, /* VLAN Packet Enable */
+ Ide = 0x80000000, /* Interrupt Delay Enable */
+};
+
+enum { /* Tdesc status */
+ Tdd = 0x00000001, /* Descriptor Done */
+ Ec = 0x00000002, /* Excess Collisions */
+ Lc = 0x00000004, /* Late Collision */
+ Tu = 0x00000008, /* Transmit Underrun */
+ CssMASK = 0x0000FF00, /* Checksum Start Field */
+ CssSHIFT = 8,
+};
+
+enum {
+ Nrdesc = 32, /* multiple of 8 */
+ Ntdesc = 8, /* multiple of 8 */
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Ctlr {
+ int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+ int id;
+ int cls;
+ ushort eeprom[0x40];
+
+ int* nic;
+ Lock imlock;
+ int im; /* interrupt mask */
+
+ Mii* mii;
+
+ Lock slock;
+ uint statistics[Nstatistics];
+
+ uchar ra[Eaddrlen]; /* receive address */
+ ulong mta[128]; /* multicast table array */
+
+ Rdesc* rdba; /* receive descriptor base address */
+ Block** rb; /* receive buffers */
+ int rdh; /* receive descriptor head */
+ int rdt; /* receive descriptor tail */
+
+ Tdesc* tdba; /* transmit descriptor base address */
+ Lock tdlock;
+ Block** tb; /* transmit buffers */
+ int tdh; /* transmit descriptor head */
+ int tdt; /* transmit descriptor tail */
+ int ett; /* early transmit threshold */
+
+ int txcw;
+ int fcrtl;
+ int fcrth;
+
+ /* bootstrap goo */
+ Block* bqhead; /* transmission queue */
+ Block* bqtail;
+} Ctlr;
+
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
+#define csr32r(c, r) (*((c)->nic+((r)/4)))
+#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
+
+static void
+igbeim(Ctlr* ctlr, int im)
+{
+ ilock(&ctlr->imlock);
+ ctlr->im |= im;
+ csr32w(ctlr, Ims, ctlr->im);
+ iunlock(&ctlr->imlock);
+}
+
+static void
+igbeattach(Ether* edev)
+{
+ int ctl;
+ Ctlr *ctlr;
+
+ /*
+ * To do here:
+ * one-time stuff;
+ * start off a kproc for link status change:
+ * adjust queue length depending on speed;
+ * flow control.
+ * more needed here...
+ */
+ ctlr = edev->ctlr;
+ igbeim(ctlr, 0);
+ ctl = csr32r(ctlr, Rctl)|Ren;
+ csr32w(ctlr, Rctl, ctl);
+ ctl = csr32r(ctlr, Tctl)|Ten;
+ csr32w(ctlr, Tctl, ctl);
+}
+
+static char* statistics[Nstatistics] = {
+ "CRC Error",
+ "Alignment Error",
+ "Symbol Error",
+ "RX Error",
+ "Missed Packets",
+ "Single Collision",
+ "Excessive Collisions",
+ "Multiple Collision",
+ "Late Collisions",
+ nil,
+ "Collision",
+ "Transmit Underrun",
+ "Defer",
+ "Transmit - No CRS",
+ "Sequence Error",
+ "Carrier Extension Error",
+ "Receive Error Length",
+ nil,
+ "XON Received",
+ "XON Transmitted",
+ "XOFF Received",
+ "XOFF Transmitted",
+ "FC Received Unsupported",
+ "Packets Received (64 Bytes)",
+ "Packets Received (65-127 Bytes)",
+ "Packets Received (128-255 Bytes)",
+ "Packets Received (256-511 Bytes)",
+ "Packets Received (512-1023 Bytes)",
+ "Packets Received (1024-1522 Bytes)",
+ "Good Packets Received",
+ "Broadcast Packets Received",
+ "Multicast Packets Received",
+ "Good Packets Transmitted",
+ nil,
+ "Good Octets Received",
+ nil,
+ "Good Octets Transmitted",
+ nil,
+ nil,
+ nil,
+ "Receive No Buffers",
+ "Receive Undersize",
+ "Receive Fragment",
+ "Receive Oversize",
+ "Receive Jabber",
+ nil,
+ nil,
+ nil,
+ "Total Octets Received",
+ nil,
+ "Total Octets Transmitted",
+ nil,
+ "Total Packets Received",
+ "Total Packets Transmitted",
+ "Packets Transmitted (64 Bytes)",
+ "Packets Transmitted (65-127 Bytes)",
+ "Packets Transmitted (128-255 Bytes)",
+ "Packets Transmitted (256-511 Bytes)",
+ "Packets Transmitted (512-1023 Bytes)",
+ "Packets Transmitted (1024-1522 Bytes)",
+ "Multicast Packets Transmitted",
+ "Broadcast Packets Transmitted",
+ "TCP Segmentation Context Transmitted",
+ "TCP Segmentation Context Fail",
+};
+
+static void
+txstart(Ether *edev)
+{
+ int tdh, tdt, len, olen;
+ Ctlr *ctlr = edev->ctlr;
+ Block *bp;
+ Tdesc *tdesc;
+
+ /*
+ * Try to fill the ring back up, moving buffers from the transmit q.
+ */
+ tdh = PREV(ctlr->tdh, Ntdesc);
+ for(tdt = ctlr->tdt; tdt != tdh; tdt = NEXT(tdt, Ntdesc)){
+ /* pull off the head of the transmission queue */
+ if((bp = ctlr->bqhead) == nil) /* was qget(edev->oq) */
+ break;
+ ctlr->bqhead = bp->next;
+ if (ctlr->bqtail == bp)
+ ctlr->bqtail = nil;
+ len = olen = BLEN(bp);
+
+ /*
+ * if packet is too short, make it longer rather than relying
+ * on ethernet interface to pad it and complain so the caller
+ * will get fixed. I don't think Psp is working right, or it's
+ * getting cleared.
+ */
+ if (len < ETHERMINTU) {
+ if (bp->rp + ETHERMINTU <= bp->lim)
+ bp->wp = bp->rp + ETHERMINTU;
+ else
+ bp->wp = bp->lim;
+ len = BLEN(bp);
+ print("txstart: extended short pkt %d -> %d bytes\n",
+ olen, len);
+ }
+
+ /* set up a descriptor for it */
+ tdesc = &ctlr->tdba[tdt];
+ tdesc->addr[0] = PCIWADDR(bp->rp);
+ tdesc->addr[1] = 0;
+ tdesc->control = /* Ide| */ Rs|Dext|Ifcs|Teop|DtypeDD|len;
+ tdesc->status = 0;
+
+ ctlr->tb[tdt] = bp;
+ }
+ ctlr->tdt = tdt;
+ csr32w(ctlr, Tdt, tdt);
+ igbeim(ctlr, Txdw);
+}
+
+static Block *
+fromringbuf(Ether *ether)
+{
+ RingBuf *tb = ðer->tb[ether->ti];
+ Block *bp = allocb(tb->len);
+
+ memmove(bp->wp, tb->pkt, tb->len);
+ memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
+ bp->wp += tb->len;
+ return bp;
+}
+
+static void
+igbetransmit(Ether* edev)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ Tdesc *tdesc;
+ RingBuf *tb;
+ int tdh;
+
+ /*
+ * For now there are no smarts here. Tuning comes later.
+ */
+ ctlr = edev->ctlr;
+ ilock(&ctlr->tdlock);
+
+ /*
+ * Free any completed packets
+ * - try to get the soft tdh to catch the tdt;
+ * - if the packet had an underrun bump the threshold
+ * - the Tu bit doesn't seem to ever be set, perhaps
+ * because Rs mode is used?
+ */
+ tdh = ctlr->tdh;
+ for(;;){
+ tdesc = &ctlr->tdba[tdh];
+ if(!(tdesc->status & Tdd))
+ break;
+ if(tdesc->status & Tu){
+ ctlr->ett++;
+ csr32w(ctlr, Ett, ctlr->ett);
+ }
+ tdesc->status = 0;
+ if(ctlr->tb[tdh] != nil){
+ freeb(ctlr->tb[tdh]);
+ ctlr->tb[tdh] = nil;
+ }
+ tdh = NEXT(tdh, Ntdesc);
+ }
+ ctlr->tdh = tdh;
+
+ /* copy packets from the software RingBuf to the transmission q */
+ /* from boot ether83815.c */
+ while((tb = &edev->tb[edev->ti])->owner == Interface){
+ bp = fromringbuf(edev);
+
+ /* put the buffer on the transmit queue */
+ if(ctlr->bqhead)
+ ctlr->bqtail->next = bp;
+ else
+ ctlr->bqhead = bp;
+ ctlr->bqtail = bp;
+
+ txstart(edev); /* kick transmitter */
+ tb->owner = Host; /* give descriptor back */
+
+ edev->ti = NEXT(edev->ti, edev->ntb);
+ }
+
+ iunlock(&ctlr->tdlock);
+}
+
+static void
+igbereplenish(Ctlr* ctlr)
+{
+ int rdt;
+ Block *bp;
+ Rdesc *rdesc;
+
+ rdt = ctlr->rdt;
+ while(NEXT(rdt, Nrdesc) != ctlr->rdh){
+ rdesc = &ctlr->rdba[rdt];
+ if(ctlr->rb[rdt] != nil){
+ /* nothing to do */
+ }
+ else if((bp = iallocb(2048)) != nil){
+ ctlr->rb[rdt] = bp;
+ rdesc->addr[0] = PCIWADDR(bp->rp);
+ rdesc->addr[1] = 0;
+ }
+ else
+ break;
+ rdesc->status = 0;
+
+ rdt = NEXT(rdt, Nrdesc);
+ }
+ ctlr->rdt = rdt;
+ csr32w(ctlr, Rdt, rdt);
+}
+
+static void
+toringbuf(Ether *ether, Block *bp)
+{
+ RingBuf *rb = ðer->rb[ether->ri];
+
+ if (rb->owner == Interface) {
+ rb->len = BLEN(bp);
+ memmove(rb->pkt, bp->rp, rb->len);
+ rb->owner = Host;
+ ether->ri = NEXT(ether->ri, ether->nrb);
+ }
+ /* else no one is expecting packets from the network */
+}
+
+static void
+igbeinterrupt(Ureg*, void* arg)
+{
+ Block *bp;
+ Ctlr *ctlr;
+ Ether *edev;
+ Rdesc *rdesc;
+ int icr, im, rdh, txdw = 0;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ ilock(&ctlr->imlock);
+ csr32w(ctlr, Imc, ~0);
+ im = ctlr->im;
+
+ for(icr = csr32r(ctlr, Icr); icr & ctlr->im; icr = csr32r(ctlr, Icr)){
+ /*
+ * Link status changed.
+ */
+ if(icr & (Rxseq|Lsc)){
+ /*
+ * should be more here...
+ */
+ }
+
+ /*
+ * Process any received packets.
+ */
+ rdh = ctlr->rdh;
+ for(;;){
+ rdesc = &ctlr->rdba[rdh];
+ if(!(rdesc->status & Rdd))
+ break;
+ if ((rdesc->status & Reop) && rdesc->errors == 0) {
+ bp = ctlr->rb[rdh];
+ ctlr->rb[rdh] = nil;
+ /*
+ * it appears that the original 82543 needed
+ * to have the Ethernet CRC excluded, but that
+ * the newer chips do not?
+ */
+ bp->wp += rdesc->length /* -4 */;
+ toringbuf(edev, bp);
+ freeb(bp);
+ } else if ((rdesc->status & Reop) && rdesc->errors)
+ print("igbe: input packet error 0x%ux\n",
+ rdesc->errors);
+ rdesc->status = 0;
+ rdh = NEXT(rdh, Nrdesc);
+ }
+ ctlr->rdh = rdh;
+
+ if(icr & Rxdmt0)
+ igbereplenish(ctlr);
+ if(icr & Txdw){
+ im &= ~Txdw;
+ txdw++;
+ }
+ }
+
+ ctlr->im = im;
+ csr32w(ctlr, Ims, im);
+ iunlock(&ctlr->imlock);
+
+ if(txdw)
+ igbetransmit(edev);
+}
+
+static int
+igbeinit(Ether* edev)
+{
+ int csr, i, r, ctrl;
+ MiiPhy *phy;
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+
+ /*
+ * Set up the receive addresses.
+ * There are 16 addresses. The first should be the MAC address.
+ * The others are cleared and not marked valid (MS bit of Rah).
+ */
+ csr = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
+ csr32w(ctlr, Ral, csr);
+ csr = 0x80000000|(edev->ea[5]<<8)|edev->ea[4];
+ csr32w(ctlr, Rah, csr);
+ for(i = 1; i < 16; i++){
+ csr32w(ctlr, Ral+i*8, 0);
+ csr32w(ctlr, Rah+i*8, 0);
+ }
+
+ /*
+ * Clear the Multicast Table Array.
+ * It's a 4096 bit vector accessed as 128 32-bit registers.
+ */
+ for(i = 0; i < 128; i++)
+ csr32w(ctlr, Mta+i*4, 0);
+
+ /*
+ * Receive initialisation.
+ * Mostly defaults from the datasheet, will
+ * need some tuning for performance:
+ * Rctl descriptor mimimum threshold size
+ * discard pause frames
+ * strip CRC
+ * Rdtr interrupt delay
+ * Rxdctl all the thresholds
+ */
+ csr32w(ctlr, Rctl, 0);
+
+ /*
+ * Allocate the descriptor ring and load its
+ * address and length into the NIC.
+ */
+ ctlr->rdba = xspanalloc(Nrdesc*sizeof(Rdesc), 128 /* was 16 */, 0);
+ csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
+ csr32w(ctlr, Rdbah, 0);
+ csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc));
+
+ /*
+ * Initialise the ring head and tail pointers and
+ * populate the ring with Blocks.
+ * The datasheet says the tail pointer is set to beyond the last
+ * descriptor hardware can process, which implies the initial
+ * condition is Rdh == Rdt. However, experience shows Rdt must
+ * always be 'behind' Rdh; the replenish routine ensures this.
+ */
+ ctlr->rdh = 0;
+ csr32w(ctlr, Rdh, ctlr->rdh);
+ ctlr->rdt = 0;
+ csr32w(ctlr, Rdt, ctlr->rdt);
+ ctlr->rb = malloc(sizeof(Block*)*Nrdesc);
+ igbereplenish(ctlr);
+
+ /*
+ * Set up Rctl but don't enable receiver (yet).
+ */
+ csr32w(ctlr, Rdtr, 0);
+ switch(ctlr->id){
+ case i82540em:
+ case i82540eplp:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82546gb:
+ case i82546eb:
+ case i82547gi:
+ csr32w(ctlr, Radv, 64);
+ break;
+ }
+ csr32w(ctlr, Rxdctl, (8<<WthreshSHIFT)|(8<<HthreshSHIFT)|4);
+ /*
+ * Enable checksum offload.
+ */
+ csr32w(ctlr, Rxcsum, Tuofl|Ipofl|(ETHERHDRSIZE<<PcssSHIFT));
+
+ csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF);
+ igbeim(ctlr, Rxt0|Rxo|Rxdmt0|Rxseq);
+
+ /*
+ * Transmit initialisation.
+ * Mostly defaults from the datasheet, will
+ * need some tuning for performance. The normal mode will
+ * be full-duplex and things to tune for half-duplex are
+ * Tctl re-transmit on late collision
+ * Tipg all IPG times
+ * Tbt burst timer
+ * Ait adaptive IFS throttle
+ * and in general
+ * Txdmac packet prefetching
+ * Ett transmit early threshold
+ * Tidv interrupt delay value
+ * Txdctl all the thresholds
+ */
+ csr32w(ctlr, Tctl, (0x0F<<CtSHIFT)|Psp|(66<<ColdSHIFT)); /* Fd */
+ switch(ctlr->id){
+ default:
+ r = 6;
+ break;
+ case i82543gc:
+ case i82544ei:
+ case i82547ei:
+ case i82540em:
+ case i82540eplp:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82546gb:
+ case i82546eb:
+ case i82547gi:
+ r = 8;
+ break;
+ }
+ csr32w(ctlr, Tipg, (6<<20)|(8<<10)|r);
+ csr32w(ctlr, Ait, 0);
+ csr32w(ctlr, Txdmac, 0);
+ csr32w(ctlr, Tidv, 128);
+
+ /*
+ * Allocate the descriptor ring and load its
+ * address and length into the NIC.
+ */
+ ctlr->tdba = xspanalloc(Ntdesc*sizeof(Tdesc), 128 /* was 16 */, 0);
+ csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
+ csr32w(ctlr, Tdbah, 0);
+ csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc));
+
+ /*
+ * Initialise the ring head and tail pointers.
+ */
+ ctlr->tdh = 0;
+ csr32w(ctlr, Tdh, ctlr->tdh);
+ ctlr->tdt = 0;
+ csr32w(ctlr, Tdt, ctlr->tdt);
+ ctlr->tb = malloc(sizeof(Block*)*Ntdesc);
+// ctlr->im |= Txqe|Txdw;
+
+ r = (4<<WthreshSHIFT)|(4<<HthreshSHIFT)|(8<<PthreshSHIFT);
+ switch(ctlr->id){
+ default:
+ break;
+ case i82540em:
+ case i82540eplp:
+ case i82547gi:
+ case i82541pi:
+ case i82546gb:
+ case i82546eb:
+ case i82541gi:
+ case i82541gi2:
+ r = csr32r(ctlr, Txdctl);
+ r &= ~WthreshMASK;
+ r |= Gran|(4<<WthreshSHIFT);
+
+ csr32w(ctlr, Tadv, 64);
+ break;
+ }
+ csr32w(ctlr, Txdctl, r);
+
+ r = csr32r(ctlr, Tctl);
+ r |= Ten;
+ csr32w(ctlr, Tctl, r);
+
+ if(ctlr->mii == nil || ctlr->mii->curphy == nil) {
+ print("igbe: no mii (yet)\n");
+ return 0;
+ }
+ /* wait for the link to come up */
+ if (miistatus(ctlr->mii) < 0)
+ return -1;
+ print("igbe: phy: ");
+ phy = ctlr->mii->curphy;
+ if (phy->fd)
+ print("full duplex");
+ else
+ print("half duplex");
+ print(", %d Mb/s\n", phy->speed);
+
+ /*
+ * Flow control.
+ */
+ ctrl = csr32r(ctlr, Ctrl);
+ if(phy->rfc)
+ ctrl |= Rfce;
+ if(phy->tfc)
+ ctrl |= Tfce;
+ csr32w(ctlr, Ctrl, ctrl);
+
+ return 0;
+}
+
+static int
+i82543mdior(Ctlr* ctlr, int n)
+{
+ int ctrl, data, i, r;
+
+ /*
+ * Read n bits from the Management Data I/O Interface.
+ */
+ ctrl = csr32r(ctlr, Ctrl);
+ r = (ctrl & ~Mddo)|Mdco;
+ data = 0;
+ for(i = n-1; i >= 0; i--){
+ if(csr32r(ctlr, Ctrl) & Mdd)
+ data |= (1<<i);
+ csr32w(ctlr, Ctrl, Mdc|r);
+ csr32w(ctlr, Ctrl, r);
+ }
+ csr32w(ctlr, Ctrl, ctrl);
+
+ return data;
+}
+
+static int
+i82543mdiow(Ctlr* ctlr, int bits, int n)
+{
+ int ctrl, i, r;
+
+ /*
+ * Write n bits to the Management Data I/O Interface.
+ */
+ ctrl = csr32r(ctlr, Ctrl);
+ r = Mdco|Mddo|ctrl;
+ for(i = n-1; i >= 0; i--){
+ if(bits & (1<<i))
+ r |= Mdd;
+ else
+ r &= ~Mdd;
+ csr32w(ctlr, Ctrl, Mdc|r);
+ csr32w(ctlr, Ctrl, r);
+ }
+ csr32w(ctlr, Ctrl, ctrl);
+
+ return 0;
+}
+
+static int
+i82543miimir(Mii* mii, int pa, int ra)
+{
+ int data;
+ Ctlr *ctlr;
+
+ ctlr = mii->ctlr;
+
+ /*
+ * MII Management Interface Read.
+ *
+ * Preamble;
+ * ST+OP+PHYAD+REGAD;
+ * TA + 16 data bits.
+ */
+ i82543mdiow(ctlr, 0xFFFFFFFF, 32);
+ i82543mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
+ data = i82543mdior(ctlr, 18);
+
+ if(data & 0x10000)
+ return -1;
+
+ return data & 0xFFFF;
+}
+
+static int
+i82543miimiw(Mii* mii, int pa, int ra, int data)
+{
+ Ctlr *ctlr;
+
+ ctlr = mii->ctlr;
+
+ /*
+ * MII Management Interface Write.
+ *
+ * Preamble;
+ * ST+OP+PHYAD+REGAD+TA + 16 data bits;
+ * Z.
+ */
+ i82543mdiow(ctlr, 0xFFFFFFFF, 32);
+ data &= 0xFFFF;
+ data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
+ i82543mdiow(ctlr, data, 32);
+
+ return 0;
+}
+
+static int
+igbemiimir(Mii* mii, int pa, int ra)
+{
+ Ctlr *ctlr;
+ int mdic, timo;
+
+ ctlr = mii->ctlr;
+
+ csr32w(ctlr, Mdic, MDIrop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT));
+ mdic = 0;
+ for(timo = 64; timo; timo--){
+ mdic = csr32r(ctlr, Mdic);
+ if(mdic & (MDIe|MDIready))
+ break;
+ microdelay(1);
+ }
+
+ if((mdic & (MDIe|MDIready)) == MDIready)
+ return mdic & 0xFFFF;
+ return -1;
+}
+
+static int
+igbemiimiw(Mii* mii, int pa, int ra, int data)
+{
+ Ctlr *ctlr;
+ int mdic, timo;
+
+ ctlr = mii->ctlr;
+
+ data &= MDIdMASK;
+ csr32w(ctlr, Mdic, MDIwop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT)|data);
+ mdic = 0;
+ for(timo = 64; timo; timo--){
+ mdic = csr32r(ctlr, Mdic);
+ if(mdic & (MDIe|MDIready))
+ break;
+ microdelay(1);
+ }
+ if((mdic & (MDIe|MDIready)) == MDIready)
+ return 0;
+ return -1;
+}
+
+static int
+igbemii(Ctlr* ctlr)
+{
+ MiiPhy *phy = (MiiPhy *)1;
+ int ctrl, p, r;
+
+ USED(phy);
+ r = csr32r(ctlr, Status);
+ if(r & Tbimode)
+ return -1;
+ if((ctlr->mii = malloc(sizeof(Mii))) == nil)
+ return -1;
+ ctlr->mii->ctlr = ctlr;
+
+ ctrl = csr32r(ctlr, Ctrl);
+ ctrl |= Slu;
+
+ switch(ctlr->id){
+ case i82543gc:
+ ctrl |= Frcdplx|Frcspd;
+ csr32w(ctlr, Ctrl, ctrl);
+
+ /*
+ * The reset pin direction (Mdro) should already
+ * be set from the EEPROM load.
+ * If it's not set this configuration is unexpected
+ * so bail.
+ */
+ r = csr32r(ctlr, Ctrlext);
+ if(!(r & Mdro))
+ return -1;
+ csr32w(ctlr, Ctrlext, r);
+ delay(20);
+ r = csr32r(ctlr, Ctrlext);
+ r &= ~Mdr;
+ csr32w(ctlr, Ctrlext, r);
+ delay(20);
+ r = csr32r(ctlr, Ctrlext);
+ r |= Mdr;
+ csr32w(ctlr, Ctrlext, r);
+ delay(20);
+
+ ctlr->mii->mir = i82543miimir;
+ ctlr->mii->miw = i82543miimiw;
+ break;
+ case i82544ei:
+ case i82547ei:
+ case i82540em:
+ case i82540eplp:
+ case i82547gi:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82546gb:
+ case i82546eb:
+ ctrl &= ~(Frcdplx|Frcspd);
+ csr32w(ctlr, Ctrl, ctrl);
+ ctlr->mii->mir = igbemiimir;
+ ctlr->mii->miw = igbemiimiw;
+ break;
+ default:
+ free(ctlr->mii);
+ ctlr->mii = nil;
+ return -1;
+ }
+
+ if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
+ if (0)
+ print("phy trouble: phy = 0x%lux\n", (ulong)phy);
+ free(ctlr->mii);
+ ctlr->mii = nil;
+ return -1;
+ }
+ if (Debug)
+ print("oui %X phyno %d\n", phy->oui, phy->phyno);
+ else
+ USED(phy);
+
+ /*
+ * 8254X-specific PHY registers not in 802.3:
+ * 0x10 PHY specific control
+ * 0x14 extended PHY specific control
+ * Set appropriate values then reset the PHY to have
+ * changes noted.
+ */
+ switch(ctlr->id){
+ case i82547gi:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82546gb:
+ case i82546eb:
+ break;
+ default:
+ r = miimir(ctlr->mii, 16);
+ r |= 0x0800; /* assert CRS on Tx */
+ r |= 0x0060; /* auto-crossover all speeds */
+ r |= 0x0002; /* polarity reversal enabled */
+ miimiw(ctlr->mii, 16, r);
+
+ r = miimir(ctlr->mii, 20);
+ r |= 0x0070; /* +25MHz clock */
+ r &= ~0x0F00;
+ r |= 0x0100; /* 1x downshift */
+ miimiw(ctlr->mii, 20, r);
+
+ miireset(ctlr->mii);
+ break;
+ }
+ p = 0;
+ if(ctlr->txcw & TxcwPs)
+ p |= AnaP;
+ if(ctlr->txcw & TxcwAs)
+ p |= AnaAP;
+ miiane(ctlr->mii, ~0, p, ~0);
+
+ return 0;
+}
+
+static int
+at93c46io(Ctlr* ctlr, char* op, int data)
+{
+ char *lp, *p;
+ int i, loop, eecd, r;
+
+ eecd = csr32r(ctlr, Eecd);
+
+ r = 0;
+ loop = -1;
+ lp = nil;
+ for(p = op; *p != '\0'; p++){
+ switch(*p){
+ default:
+ return -1;
+ case ' ':
+ continue;
+ case ':': /* start of loop */
+ loop = strtol(p+1, &lp, 0)-1;
+ lp--;
+ if(p == lp)
+ loop = 7;
+ p = lp;
+ continue;
+ case ';': /* end of loop */
+ if(lp == nil)
+ return -1;
+ loop--;
+ if(loop >= 0)
+ p = lp;
+ else
+ lp = nil;
+ continue;
+ case 'C': /* assert clock */
+ eecd |= Sk;
+ break;
+ case 'c': /* deassert clock */
+ eecd &= ~Sk;
+ break;
+ case 'D': /* next bit in 'data' byte */
+ if(loop < 0)
+ return -1;
+ if(data & (1<<loop))
+ eecd |= Di;
+ else
+ eecd &= ~Di;
+ break;
+ case 'O': /* collect data output */
+ i = (csr32r(ctlr, Eecd) & Do) != 0;
+ if(loop >= 0)
+ r |= (i<<loop);
+ else
+ r = i;
+ continue;
+ case 'I': /* assert data input */
+ eecd |= Di;
+ break;
+ case 'i': /* deassert data input */
+ eecd &= ~Di;
+ break;
+ case 'S': /* enable chip select */
+ eecd |= Cs;
+ break;
+ case 's': /* disable chip select */
+ eecd &= ~Cs;
+ break;
+ }
+ csr32w(ctlr, Eecd, eecd);
+ microdelay(50);
+ }
+ if(loop >= 0)
+ return -1;
+ return r;
+}
+
+static int
+at93c46r(Ctlr* ctlr)
+{
+ ushort sum;
+ char rop[20];
+ int addr, areq, bits, data, eecd, i;
+
+ eecd = csr32r(ctlr, Eecd);
+ if(eecd & Spi){
+ print("igbe: SPI EEPROM access not implemented\n");
+ return 0;
+ }
+ if(eecd & (Eeszaddr|Eesz256))
+ bits = 8;
+ else
+ bits = 6;
+ sum = 0;
+
+ switch(ctlr->id){
+ default:
+ areq = 0;
+ break;
+ case i82540em:
+ case i82540eplp:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82547gi:
+ case i82546gb:
+ case i82546eb:
+ areq = 1;
+ csr32w(ctlr, Eecd, eecd|Areq);
+ for(i = 0; i < 1000; i++){
+ if((eecd = csr32r(ctlr, Eecd)) & Agnt)
+ break;
+ microdelay(5);
+ }
+ if(!(eecd & Agnt)){
+ print("igbe: not granted EEPROM access\n");
+ goto release;
+ }
+ break;
+ }
+ snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
+
+ for(addr = 0; addr < 0x40; addr++){
+ /*
+ * Read a word at address 'addr' from the Atmel AT93C46
+ * 3-Wire Serial EEPROM or compatible. The EEPROM access is
+ * controlled by 4 bits in Eecd. See the AT93C46 datasheet
+ * for protocol details.
+ */
+ if(at93c46io(ctlr, rop, (0x06<<bits)|addr) != 0){
+ print("igbe: can't set EEPROM address 0x%2.2X\n", addr);
+ goto release;
+ }
+ data = at93c46io(ctlr, ":16COc;", 0);
+ at93c46io(ctlr, "sic", 0);
+ ctlr->eeprom[addr] = data;
+ sum += data;
+ if (Debug) {
+ if(addr && ((addr & 0x07) == 0))
+ print("\n");
+ print(" %4.4ux", data);
+ }
+ }
+ if (Debug)
+ print("\n");
+release:
+ if(areq)
+ csr32w(ctlr, Eecd, eecd & ~Areq);
+ return sum;
+}
+
+static void
+detach(Ctlr *ctlr)
+{
+ int r;
+
+ /*
+ * Perform a device reset to get the chip back to the
+ * power-on state, followed by an EEPROM reset to read
+ * the defaults for some internal registers.
+ */
+ csr32w(ctlr, Imc, ~0);
+ csr32w(ctlr, Rctl, 0);
+ csr32w(ctlr, Tctl, 0);
+
+ delay(20);
+
+ csr32w(ctlr, Ctrl, Devrst);
+ /* apparently needed on multi-GHz processors to avoid infinite loops */
+ delay(1);
+ while(csr32r(ctlr, Ctrl) & Devrst)
+ ;
+
+ csr32w(ctlr, Ctrlext, Eerst | csr32r(ctlr, Ctrlext));
+ delay(1);
+ while(csr32r(ctlr, Ctrlext) & Eerst)
+ ;
+
+ switch(ctlr->id){
+ default:
+ break;
+ case i82540em:
+ case i82540eplp:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82547gi:
+ case i82546gb:
+ case i82546eb:
+ r = csr32r(ctlr, Manc);
+ r &= ~Arpen;
+ csr32w(ctlr, Manc, r);
+ break;
+ }
+
+ csr32w(ctlr, Imc, ~0);
+ delay(1);
+ while(csr32r(ctlr, Icr))
+ ;
+}
+
+static void
+igbedetach(Ether *edev)
+{
+ detach(edev->ctlr);
+}
+
+static void
+igbeshutdown(Ether* ether)
+{
+print("igbeshutdown\n");
+ igbedetach(ether);
+}
+
+static int
+igbereset(Ctlr* ctlr)
+{
+ int ctrl, i, pause, r, swdpio, txcw;
+
+ detach(ctlr);
+
+ /*
+ * Read the EEPROM, validate the checksum
+ * then get the device back to a power-on state.
+ */
+ r = at93c46r(ctlr);
+ /* zero return means no SPI EEPROM access */
+ if (r != 0 && r != 0xBABA){
+ print("igbe: bad EEPROM checksum - 0x%4.4uX\n", r);
+ return -1;
+ }
+
+ /*
+ * Snarf and set up the receive addresses.
+ * There are 16 addresses. The first should be the MAC address.
+ * The others are cleared and not marked valid (MS bit of Rah).
+ */
+ if ((ctlr->id == i82546gb || ctlr->id == i82546eb) &&
+ BUSFNO(ctlr->pcidev->tbdf) == 1)
+ ctlr->eeprom[Ea+2] += 0x100; /* second interface */
+ for(i = Ea; i < Eaddrlen/2; i++){
+ ctlr->ra[2*i] = ctlr->eeprom[i];
+ ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
+ }
+ /* lan id seems to vary on 82543gc; don't use it */
+ if (ctlr->id != i82543gc) {
+ r = (csr32r(ctlr, Status) & Lanid) >> 2;
+ ctlr->ra[5] += r; /* ea ctlr[1] = ea ctlr[0]+1 */
+ }
+ r = (ctlr->ra[3]<<24)|(ctlr->ra[2]<<16)|(ctlr->ra[1]<<8)|ctlr->ra[0];
+ csr32w(ctlr, Ral, r);
+ r = 0x80000000|(ctlr->ra[5]<<8)|ctlr->ra[4];
+ csr32w(ctlr, Rah, r);
+ for(i = 1; i < 16; i++){
+ csr32w(ctlr, Ral+i*8, 0);
+ csr32w(ctlr, Rah+i*8, 0);
+ }
+
+ /*
+ * Clear the Multicast Table Array.
+ * It's a 4096 bit vector accessed as 128 32-bit registers.
+ */
+ memset(ctlr->mta, 0, sizeof(ctlr->mta));
+ for(i = 0; i < 128; i++)
+ csr32w(ctlr, Mta+i*4, 0);
+
+ /*
+ * Just in case the Eerst didn't load the defaults
+ * (doesn't appear to fully on the 8243GC), do it manually.
+ */
+ if (ctlr->id == i82543gc) {
+ txcw = csr32r(ctlr, Txcw);
+ txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);
+ ctrl = csr32r(ctlr, Ctrl);
+ ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);
+
+ if(ctlr->eeprom[Icw1] & 0x0400){
+ ctrl |= Fd;
+ txcw |= TxcwFd;
+ }
+ if(ctlr->eeprom[Icw1] & 0x0200)
+ ctrl |= Lrst;
+ if(ctlr->eeprom[Icw1] & 0x0010)
+ ctrl |= Ilos;
+ if(ctlr->eeprom[Icw1] & 0x0800)
+ ctrl |= Frcspd;
+ swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;
+ ctrl |= swdpio<<SwdpioloSHIFT;
+ csr32w(ctlr, Ctrl, ctrl);
+
+ ctrl = csr32r(ctlr, Ctrlext);
+ ctrl &= ~(Ips|SwdpiohiMASK);
+ swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;
+ if(ctlr->eeprom[Icw1] & 0x1000)
+ ctrl |= Ips;
+ ctrl |= swdpio<<SwdpiohiSHIFT;
+ csr32w(ctlr, Ctrlext, ctrl);
+
+ if(ctlr->eeprom[Icw2] & 0x0800)
+ txcw |= TxcwAne;
+ pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;
+ txcw |= pause<<TxcwPauseSHIFT;
+ switch(pause){
+ default:
+ ctlr->fcrtl = 0x00002000;
+ ctlr->fcrth = 0x00004000;
+ txcw |= TxcwAs|TxcwPs;
+ break;
+ case 0:
+ ctlr->fcrtl = 0x00002000;
+ ctlr->fcrth = 0x00004000;
+ break;
+ case 2:
+ ctlr->fcrtl = 0;
+ ctlr->fcrth = 0;
+ txcw |= TxcwAs;
+ break;
+ }
+ ctlr->txcw = txcw;
+ csr32w(ctlr, Txcw, txcw);
+ }
+ /*
+ * Flow control - values from the datasheet.
+ */
+ csr32w(ctlr, Fcal, 0x00C28001);
+ csr32w(ctlr, Fcah, 0x00000100);
+ csr32w(ctlr, Fct, 0x00008808);
+ csr32w(ctlr, Fcttv, 0x00000100);
+
+ csr32w(ctlr, Fcrtl, ctlr->fcrtl);
+ csr32w(ctlr, Fcrth, ctlr->fcrth);
+
+ ilock(&ctlr->imlock);
+ csr32w(ctlr, Imc, ~0);
+ ctlr->im = 0; /* was = Lsc, which hangs some controllers */
+ csr32w(ctlr, Ims, ctlr->im);
+ iunlock(&ctlr->imlock);
+
+ if(!(csr32r(ctlr, Status) & Tbimode) && igbemii(ctlr) < 0) {
+ print("igbe: igbemii failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+igbepci(void)
+{
+ int port, cls;
+ Pcidev *p;
+ Ctlr *ctlr;
+ static int first = 1;
+
+ if (first)
+ first = 0;
+ else
+ return;
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ if(p->ccrb != 0x02 || p->ccru != 0)
+ continue;
+
+ switch((p->did<<16)|p->vid){
+ case i82542:
+ default:
+ continue;
+
+ case (0x1001<<16)|0x8086: /* Intel PRO/1000 F */
+ break;
+ case i82543gc:
+ case i82544ei:
+ case i82547ei:
+ case i82540em:
+ case i82540eplp:
+ case i82547gi:
+ case i82541gi:
+ case i82541gi2:
+ case i82541pi:
+ case i82546gb:
+ case i82546eb:
+ break;
+ }
+
+ /* the 82547EI is on the CSA bus, whatever that is */
+ port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
+ if(port == 0){
+ print("igbe: can't map %d @ 0x%8.8luX\n",
+ p->mem[0].size, p->mem[0].bar);
+ continue;
+ }
+
+ /*
+ * from etherga620.c:
+ * If PCI Write-and-Invalidate is enabled set the max write DMA
+ * value to the host cache-line size (32 on Pentium or later).
+ */
+ if(p->pcr & MemWrInv){
+ cls = pcicfgr8(p, PciCLS) * 4;
+ if(cls != CACHELINESZ)
+ pcicfgw8(p, PciCLS, CACHELINESZ/4);
+ }
+
+ cls = pcicfgr8(p, PciCLS);
+ switch(cls){
+ default:
+ print("igbe: unexpected CLS - %d bytes\n",
+ cls*sizeof(long));
+ break;
+ case 0x00:
+ case 0xFF:
+ /* alphapc 164lx returns 0 */
+ print("igbe: unusable PciCLS: %d, using %d longs\n",
+ cls, CACHELINESZ/sizeof(long));
+ cls = CACHELINESZ/sizeof(long);
+ pcicfgw8(p, PciCLS, cls);
+ break;
+ case 0x08:
+ case 0x10:
+ break;
+ }
+
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = port;
+ ctlr->pcidev = p;
+ ctlr->id = (p->did<<16)|p->vid;
+ ctlr->cls = cls*4;
+ ctlr->nic = KADDR(ctlr->port);
+ if (Debug)
+ print("status0 %8.8uX\n", csr32r(ctlr, Status));
+ if(igbereset(ctlr)){
+ free(ctlr);
+ continue;
+ }
+ if (Debug)
+ print("status1 %8.8uX\n", csr32r(ctlr, Status));
+ pcisetbme(p);
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+ }
+}
+
+int
+igbepnp(Ether* edev)
+{
+ int i;
+ Ctlr *ctlr;
+ uchar ea[Eaddrlen];
+
+ if(ctlrhead == nil)
+ igbepci();
+
+ /*
+ * Any adapter matches if no edev->port is supplied,
+ * otherwise the ports must match.
+ */
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(edev->port == 0 || edev->port == ctlr->port){
+ ctlr->active = 1;
+ break;
+ }
+ }
+ if(ctlr == nil)
+ return -1;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = ctlr->pcidev->intl;
+ edev->tbdf = ctlr->pcidev->tbdf;
+// edev->mbps = 1000;
+
+ /*
+ * Check if the adapter's station address is to be overridden.
+ * If not, read it from the EEPROM and set in ether->ea prior to
+ * loading the station address in the hardware.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, edev->ea, Eaddrlen) == 0){
+ for(i = 0; i < Eaddrlen/2; i++){
+ edev->ea[2*i] = ctlr->eeprom[i];
+ edev->ea[2*i+1] = ctlr->eeprom[i]>>8;
+ }
+ }
+ igbeinit(edev);
+
+ /*
+ * Linkage to the generic ethernet driver.
+ */
+ edev->attach = igbeattach;
+ edev->transmit = igbetransmit;
+ edev->interrupt = igbeinterrupt;
+ edev->detach = igbedetach;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ethermii.c
@@ -1,0 +1,224 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+#include "ethermii.h"
+
+int
+mii(Mii* mii, int mask)
+{
+ MiiPhy *miiphy;
+ int bit, phyno, r, rmask;
+
+ /*
+ * Probe through mii for PHYs in mask;
+ * return the mask of those found in the current probe.
+ * If the PHY has not already been probed, update
+ * the Mii information.
+ */
+ rmask = 0;
+ for(phyno = 0; phyno < NMiiPhy; phyno++){
+ bit = 1<<phyno;
+ if(!(mask & bit))
+ continue;
+ if(mii->mask & bit){
+ rmask |= bit;
+ continue;
+ }
+ if(mii->mir(mii, phyno, Bmsr) == -1)
+ continue;
+ if((miiphy = malloc(sizeof(MiiPhy))) == nil)
+ continue;
+
+ miiphy->mii = mii;
+ r = mii->mir(mii, phyno, Phyidr1);
+ miiphy->oui = (r & 0x3FFF)<<6;
+ r = mii->mir(mii, phyno, Phyidr2);
+ miiphy->oui |= r>>10;
+ miiphy->phyno = phyno;
+
+ miiphy->anar = ~0;
+ miiphy->fc = ~0;
+ miiphy->mscr = ~0;
+
+ mii->phy[phyno] = miiphy;
+ if(mii->curphy == nil)
+ mii->curphy = miiphy;
+ mii->mask |= bit;
+ mii->nphy++;
+
+ rmask |= bit;
+ }
+ return rmask;
+}
+
+int
+miimir(Mii* mii, int r)
+{
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ return mii->mir(mii, mii->curphy->phyno, r);
+}
+
+int
+miimiw(Mii* mii, int r, int data)
+{
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ return mii->miw(mii, mii->curphy->phyno, r, data);
+}
+
+int
+miireset(Mii* mii)
+{
+ int bmcr;
+
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
+ bmcr |= BmcrR;
+ mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
+ microdelay(1);
+
+ return 0;
+}
+
+int
+miiane(Mii* mii, int a, int p, int e)
+{
+ int anar, bmsr, mscr, r, phyno;
+
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ phyno = mii->curphy->phyno;
+
+ bmsr = mii->mir(mii, phyno, Bmsr);
+ if(!(bmsr & BmsrAna))
+ return -1;
+
+ if(a != ~0)
+ anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
+ else if(mii->curphy->anar != ~0)
+ anar = mii->curphy->anar;
+ else{
+ anar = mii->mir(mii, phyno, Anar);
+ anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
+ if(bmsr & Bmsr10THD)
+ anar |= Ana10HD;
+ if(bmsr & Bmsr10TFD)
+ anar |= Ana10FD;
+ if(bmsr & Bmsr100TXHD)
+ anar |= AnaTXHD;
+ if(bmsr & Bmsr100TXFD)
+ anar |= AnaTXFD;
+ }
+ mii->curphy->anar = anar;
+
+ if(p != ~0)
+ anar |= (AnaAP|AnaP) & p;
+ else if(mii->curphy->fc != ~0)
+ anar |= mii->curphy->fc;
+ mii->curphy->fc = (AnaAP|AnaP) & anar;
+
+ if(bmsr & BmsrEs){
+ mscr = mii->mir(mii, phyno, Mscr);
+ mscr &= ~(Mscr1000TFD|Mscr1000THD);
+ if(e != ~0)
+ mscr |= (Mscr1000TFD|Mscr1000THD) & e;
+ else if(mii->curphy->mscr != ~0)
+ mscr = mii->curphy->mscr;
+ else{
+ r = mii->mir(mii, phyno, Esr);
+ if(r & Esr1000THD)
+ mscr |= Mscr1000THD;
+ if(r & Esr1000TFD)
+ mscr |= Mscr1000TFD;
+ }
+ mii->curphy->mscr = mscr;
+ mii->miw(mii, phyno, Mscr, mscr);
+ }
+ mii->miw(mii, phyno, Anar, anar);
+
+ r = mii->mir(mii, phyno, Bmcr);
+ if(!(r & BmcrR)){
+ r |= BmcrAne|BmcrRan;
+ mii->miw(mii, phyno, Bmcr, r);
+ }
+
+ return 0;
+}
+
+int
+miistatus(Mii* mii)
+{
+ MiiPhy *phy;
+ int anlpar, bmsr, p, r, phyno;
+
+ if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+ return -1;
+ phy = mii->curphy;
+ phyno = phy->phyno;
+
+ /*
+ * Check Auto-Negotiation is complete and link is up.
+ * (Read status twice as the Ls bit is sticky).
+ */
+ bmsr = mii->mir(mii, phyno, Bmsr);
+ if(!(bmsr & (BmsrAnc|BmsrAna)))
+ return -1;
+
+ bmsr = mii->mir(mii, phyno, Bmsr);
+ if(!(bmsr & BmsrLs)){
+ phy->link = 0;
+ return -1;
+ }
+
+ phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
+ if(phy->mscr){
+ r = mii->mir(mii, phyno, Mssr);
+ if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
+ phy->speed = 1000;
+ phy->fd = 1;
+ }
+ else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
+ phy->speed = 1000;
+ }
+
+ anlpar = mii->mir(mii, phyno, Anlpar);
+ if(phy->speed == 0){
+ r = phy->anar & anlpar;
+ if(r & AnaTXFD){
+ phy->speed = 100;
+ phy->fd = 1;
+ }
+ else if(r & AnaTXHD)
+ phy->speed = 100;
+ else if(r & Ana10FD){
+ phy->speed = 10;
+ phy->fd = 1;
+ }
+ else if(r & Ana10HD)
+ phy->speed = 10;
+ }
+ if(phy->speed == 0)
+ return -1;
+
+ if(phy->fd){
+ p = phy->fc;
+ r = anlpar & (AnaAP|AnaP);
+ if(p == AnaAP && r == (AnaAP|AnaP))
+ phy->tfc = 1;
+ else if(p == (AnaAP|AnaP) && r == AnaAP)
+ phy->rfc = 1;
+ else if((p & AnaP) && (r & AnaP))
+ phy->rfc = phy->tfc = 1;
+ }
+
+ phy->link = 1;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/ethermii.h
@@ -1,0 +1,116 @@
+typedef struct Mii Mii;
+typedef struct MiiPhy MiiPhy;
+
+enum { /* registers */
+ Bmcr = 0x00, /* Basic Mode Control */
+ Bmsr = 0x01, /* Basic Mode Status */
+ Phyidr1 = 0x02, /* PHY Identifier #1 */
+ Phyidr2 = 0x03, /* PHY Identifier #2 */
+ Anar = 0x04, /* Auto-Negotiation Advertisement */
+ Anlpar = 0x05, /* AN Link Partner Ability */
+ Aner = 0x06, /* AN Expansion */
+ Annptr = 0x07, /* AN Next Page TX */
+ Annprr = 0x08, /* AN Next Page RX */
+ Mscr = 0x09, /* MASTER-SLAVE Control */
+ Mssr = 0x0A, /* MASTER-SLAVE Status */
+ Esr = 0x0F, /* Extended Status */
+
+ NMiiPhyr = 32,
+ NMiiPhy = 32,
+};
+
+enum { /* Bmcr */
+ BmcrSs1 = 0x0040, /* Speed Select[1] */
+ BmcrCte = 0x0080, /* Collision Test Enable */
+ BmcrDm = 0x0100, /* Duplex Mode */
+ BmcrRan = 0x0200, /* Restart Auto-Negotiation */
+ BmcrI = 0x0400, /* Isolate */
+ BmcrPd = 0x0800, /* Power Down */
+ BmcrAne = 0x1000, /* Auto-Negotiation Enable */
+ BmcrSs0 = 0x2000, /* Speed Select[0] */
+ BmcrLe = 0x4000, /* Loopback Enable */
+ BmcrR = 0x8000, /* Reset */
+};
+
+enum { /* Bmsr */
+ BmsrEc = 0x0001, /* Extended Capability */
+ BmsrJd = 0x0002, /* Jabber Detect */
+ BmsrLs = 0x0004, /* Link Status */
+ BmsrAna = 0x0008, /* Auto-Negotiation Ability */
+ BmsrRf = 0x0010, /* Remote Fault */
+ BmsrAnc = 0x0020, /* Auto-Negotiation Complete */
+ BmsrPs = 0x0040, /* Preamble Suppression Capable */
+ BmsrEs = 0x0100, /* Extended Status */
+ Bmsr100T2HD = 0x0200, /* 100BASE-T2 HD Capable */
+ Bmsr100T2FD = 0x0400, /* 100BASE-T2 FD Capable */
+ Bmsr10THD = 0x0800, /* 100BASE-T HD Capable */
+ Bmsr10TFD = 0x1000, /* 10BASE-T FD Capable */
+ Bmsr100TXHD = 0x2000, /* 100BASE-TX HD Capable */
+ Bmsr100TXFD = 0x4000, /* 100BASE-TX FD Capable */
+ Bmsr100T4 = 0x8000, /* 100BASE-T4 Capable */
+};
+
+enum { /* Anar/Anlpar */
+ Ana10HD = 0x0020, /* Advertise 10BASE-T */
+ Ana10FD = 0x0040, /* Advertise 10BASE-T FD */
+ AnaTXHD = 0x0080, /* Advertise 100BASE-TX */
+ AnaTXFD = 0x0100, /* Advertise 100BASE-TX FD */
+ AnaT4 = 0x0200, /* Advertise 100BASE-T4 */
+ AnaP = 0x0400, /* Pause */
+ AnaAP = 0x0800, /* Asymmetrical Pause */
+ AnaRf = 0x2000, /* Remote Fault */
+ AnaAck = 0x4000, /* Acknowledge */
+ AnaNp = 0x8000, /* Next Page Indication */
+};
+
+enum { /* Mscr */
+ Mscr1000THD = 0x0100, /* Advertise 1000BASE-T HD */
+ Mscr1000TFD = 0x0200, /* Advertise 1000BASE-T FD */
+};
+
+enum { /* Mssr */
+ Mssr1000THD = 0x0400, /* Link Partner 1000BASE-T HD able */
+ Mssr1000TFD = 0x0800, /* Link Partner 1000BASE-T FD able */
+};
+
+enum { /* Esr */
+ Esr1000THD = 0x1000, /* 1000BASE-T HD Capable */
+ Esr1000TFD = 0x2000, /* 1000BASE-T FD Capable */
+ Esr1000XHD = 0x4000, /* 1000BASE-X HD Capable */
+ Esr1000XFD = 0x8000, /* 1000BASE-X FD Capable */
+};
+
+typedef struct Mii {
+ Lock;
+ int nphy;
+ int mask;
+ MiiPhy* phy[NMiiPhy];
+ MiiPhy* curphy;
+
+ void* ctlr;
+ int (*mir)(Mii*, int, int);
+ int (*miw)(Mii*, int, int, int);
+} Mii;
+
+typedef struct MiiPhy {
+ Mii* mii;
+ int oui;
+ int phyno;
+
+ int anar;
+ int fc;
+ int mscr;
+
+ int link;
+ int speed;
+ int fd;
+ int rfc;
+ int tfc;
+};
+
+extern int mii(Mii*, int);
+extern int miiane(Mii*, int, int, int);
+extern int miimir(Mii*, int);
+extern int miimiw(Mii*, int, int);
+extern int miireset(Mii*);
+extern int miistatus(Mii*);
--- /dev/null
+++ b/os/boot.original/pc/etherrhine.c
@@ -1,0 +1,657 @@
+/*
+ Via Rhine driver, written for VT6102.
+ Uses the ethermii to control PHY.
+
+ Currently always copies on both, tx and rx.
+ rx side could be copy-free, and tx-side might be made
+ (almost) copy-free by using (possibly) two descriptors (if it allows
+ arbitrary tx lengths, which it should..): first for alignment and
+ second for rest of the frame. Rx-part should be worth doing.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+typedef struct QLock { int r; } QLock;
+#define qlock(i) while(0)
+#define qunlock(i) while(0)
+#define iprint print
+
+#include "etherif.h"
+#include "ethermii.h"
+
+enum {
+ Ntxd = 4,
+ Nrxd = 4,
+ Nwait = 50,
+ BIGSTR = 8192,
+};
+
+typedef struct Desc Desc;
+typedef struct Ctlr Ctlr;
+
+struct Desc {
+ ulong stat;
+ ulong size;
+ ulong addr;
+ ulong next;
+ char *buf;
+ ulong pad[3];
+};
+
+struct Ctlr {
+ Pcidev *pci;
+ int attached;
+ int txused;
+ int txhead;
+ int txtail;
+ int rxtail;
+ ulong port;
+
+ Mii mii;
+
+ Desc *txd; /* wants to be aligned on 16-byte boundary */
+ Desc *rxd;
+
+ QLock attachlck;
+ Lock tlock;
+};
+
+#define ior8(c, r) (inb((c)->port+(r)))
+#define iow8(c, r, b) (outb((c)->port+(r), (int)(b)))
+#define ior16(c, r) (ins((c)->port+(r)))
+#define ior32(c, r) (inl((c)->port+(r)))
+#define iow16(c, r, w) (outs((c)->port+(r), (ushort)(w)))
+#define iow32(c, r, l) (outl((c)->port+(r), (ulong)(l)))
+
+/* names used everywhere else */
+#define csr8r ior8
+#define csr8w iow8
+#define csr16r ior16
+#define csr16w iow16
+#define csr32r ior32
+#define csr32w iow32
+
+enum Regs {
+ Eaddr = 0x0,
+ Rcr = 0x6,
+ Tcr = 0x7,
+ Cr = 0x8,
+ Isr = 0xc,
+ Imr = 0xe,
+ McastAddr = 0x10,
+ RxdAddr = 0x18,
+ TxdAddr = 0x1C,
+ Bcr0 = 0x6E, /* Bus Control */
+ Bcr1 = 0x6F,
+ RhineMiiPhy = 0x6C,
+ RhineMiiSr = 0x6D,
+ RhineMiiCr = 0x70,
+ RhineMiiAddr = 0x71,
+ RhineMiiData = 0x72,
+ Eecsr = 0x74,
+ ConfigB = 0x79,
+ ConfigD = 0x7B,
+ MiscCr = 0x80,
+ HwSticky = 0x83,
+ MiscIsr = 0x84,
+ MiscImr = 0x86,
+ WolCrSet = 0xA0,
+ WolCfgSet = 0xA1,
+ WolCgSet = 0xA3,
+ WolCrClr = 0xA4,
+ PwrCfgClr = 0xA5,
+ WolCgClr = 0xA7,
+};
+
+enum { /* Rcr */
+ Sep = 0x01, /* Accept Error Packets */
+ Ar = 0x02, /* Accept Small Packets */
+ Am = 0x04, /* Accept Multicast */
+ Ab = 0x08, /* Accept Broadcast */
+ RxBcast = Ab,
+ Prom = 0x10, /* Accept Physical Address Packets */
+ RxProm = Prom,
+ RrftMASK = 0xE0, /* Receive FIFO Threshold */
+ RrftSHIFT = 5,
+ Rrft64 = 0<<RrftSHIFT,
+ Rrft32 = 1<<RrftSHIFT,
+ Rrft128 = 2<<RrftSHIFT,
+ Rrft256 = 3<<RrftSHIFT,
+ Rrft512 = 4<<RrftSHIFT,
+ Rrft768 = 5<<RrftSHIFT,
+ Rrft1024 = 6<<RrftSHIFT,
+ RrftSAF = 7<<RrftSHIFT,
+};
+
+enum { /* Tcr */
+ Lb0 = 0x02, /* Loopback Mode */
+ Lb1 = 0x04,
+ Ofset = 0x08, /* Back-off Priority Selection */
+ RtsfMASK = 0xE0, /* Transmit FIFO Threshold */
+ RtsfSHIFT = 5,
+ Rtsf128 = 0<<RtsfSHIFT,
+ Rtsf256 = 1<<RtsfSHIFT,
+ Rtsf512 = 2<<RtsfSHIFT,
+ Rtsf1024 = 3<<RtsfSHIFT,
+ RtsfSAF = 7<<RtsfSHIFT,
+};
+
+enum Crbits {
+ Init = 1<<0,
+ Start = 1<<1,
+ Stop = 1<<2,
+ RxOn = 1<<3,
+ TxOn = 1<<4,
+ Tdmd = 1<<5,
+ Rdmd = 1<<6,
+ EarlyRx = 1<<8,
+ Reserved0 = 1<<9,
+ FullDuplex = 1<<10,
+ NoAutoPoll = 1<<11,
+ Reserved1 = 1<<12,
+ Tdmd1 = 1<<13,
+ Rdmd1 = 1<<14,
+ Reset = 1<<15,
+};
+
+enum Isrbits {
+ RxOk = 1<<0,
+ TxOk = 1<<1,
+ RxErr = 1<<2,
+ TxErr = 1<<3,
+ TxBufUdf = 1<<4,
+ RxBufLinkErr = 1<<5,
+ BusErr = 1<<6,
+ CrcOvf = 1<<7,
+ EarlyRxInt = 1<<8,
+ TxFifoUdf = 1<<9,
+ RxFifoOvf = 1<<10,
+ TxPktRace = 1<<11,
+ NoRxbuf = 1<<12,
+ TxCollision = 1<<13,
+ PortCh = 1<<14,
+ GPInt = 1<<15,
+};
+
+enum { /* Bcr0 */
+ DmaMASK = 0x07, /* DMA Length */
+ DmaSHIFT = 0,
+ Dma32 = 0<<DmaSHIFT,
+ Dma64 = 1<<DmaSHIFT,
+ Dma128 = 2<<DmaSHIFT,
+ Dma256 = 3<<DmaSHIFT,
+ Dma512 = 4<<DmaSHIFT,
+ Dma1024 = 5<<DmaSHIFT,
+ DmaSAF = 7<<DmaSHIFT,
+ CrftMASK = 0x38, /* Rx FIFO Threshold */
+ CrftSHIFT = 3,
+ Crft64 = 1<<CrftSHIFT,
+ Crft128 = 2<<CrftSHIFT,
+ Crft256 = 3<<CrftSHIFT,
+ Crft512 = 4<<CrftSHIFT,
+ Crft1024 = 5<<CrftSHIFT,
+ CrftSAF = 7<<CrftSHIFT,
+ Extled = 0x40, /* Extra LED Support Control */
+ Med2 = 0x80, /* Medium Select Control */
+};
+
+enum { /* Bcr1 */
+ PotMASK = 0x07, /* Polling Timer Interval */
+ PotSHIFT = 0,
+ CtftMASK = 0x38, /* Tx FIFO Threshold */
+ CtftSHIFT = 3,
+ Ctft64 = 1<<CtftSHIFT,
+ Ctft128 = 2<<CtftSHIFT,
+ Ctft256 = 3<<CtftSHIFT,
+ Ctft512 = 4<<CtftSHIFT,
+ Ctft1024 = 5<<CtftSHIFT,
+ CtftSAF = 7<<CtftSHIFT,
+};
+
+
+enum Eecsrbits {
+ EeAutoLoad = 1<<5,
+};
+
+enum Descbits {
+ OwnNic = 1<<31, /* stat */
+ TxAbort = 1<<8, /* stat */
+ TxError = 1<<15, /* stat */
+ RxChainbuf = 1<<10, /* stat */
+ RxChainStart = 1<<9, /* stat */
+ RxChainEnd = 1<<8, /* stat */
+ Chainbuf = 1<<15, /* size rx & tx*/
+ TxDisableCrc = 1<<16, /* size */
+ TxChainStart = 1<<21, /* size */
+ TxChainEnd = 1<<22, /* size */
+ TxInt = 1<<23, /* size */
+};
+
+enum RhineMiiCrbits {
+ Mdc = 1<<0,
+ Mdi = 1<<1,
+ Mdo = 1<<2,
+ Mdout = 1<<3,
+ Mdpm = 1<<4,
+ Wcmd = 1<<5,
+ Rcmd = 1<<6,
+ Mauto = 1<<7,
+};
+
+static void
+attach(Ether *edev)
+{
+ Ctlr *ctlr;
+ Desc *txd, *rxd, *td, *rd;
+ Mii *mi;
+ MiiPhy *phy;
+ int i, s;
+
+ ctlr = edev->ctlr;
+ qlock(&ctlr->attachlck);
+ if (ctlr->attached == 0) {
+ txd = ctlr->txd;
+ rxd = ctlr->rxd;
+ for (i = 0; i < Ntxd; ++i) {
+ td = &txd[i];
+ td->next = PCIWADDR(&txd[(i+1) % Ntxd]);
+ td->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0);
+ td->addr = PCIWADDR(td->buf);
+ td->size = 0;
+ coherence();
+ td->stat = 0;
+ }
+ for (i = 0; i < Nrxd; ++i) {
+ rd = &rxd[i];
+ rd->next = PCIWADDR(&rxd[(i+1) % Nrxd]);
+ rd->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0);
+ rd->addr = PCIWADDR(rd->buf);
+ rd->size = sizeof(Etherpkt)+4;
+ coherence();
+ rd->stat = OwnNic;
+ }
+
+ ctlr->txhead = ctlr->txtail = ctlr->rxtail = 0;
+ mi = &ctlr->mii;
+ miistatus(mi);
+ phy = mi->curphy;
+ s = splhi();
+ iow32(ctlr, TxdAddr, PCIWADDR(&txd[0]));
+ iow32(ctlr, RxdAddr, PCIWADDR(&rxd[0]));
+ iow16(ctlr, Cr, (phy->fd? FullDuplex: 0) | NoAutoPoll | TxOn |
+ RxOn | Start | Rdmd);
+ iow16(ctlr, Isr, 0xFFFF);
+ iow16(ctlr, Imr, 0xFFFF);
+ iow8(ctlr, MiscIsr, 0xFF);
+ iow8(ctlr, MiscImr, ~(3<<5));
+ splx(s);
+ ctlr->attached = 1;
+ }
+ qunlock(&ctlr->attachlck);
+}
+
+static void
+txstart(Ether *edev)
+{
+ Ctlr *ctlr;
+ Desc *txd, *td;
+ int i, txused, n;
+ RingBuf *tb;
+
+ ctlr = edev->ctlr;
+ txd = ctlr->txd;
+ i = ctlr->txhead;
+ n = 0;
+ for (txused = ctlr->txused; txused < Ntxd; txused++) {
+ tb = &edev->tb[edev->ti];
+ if(tb->owner != Interface)
+ break;
+
+ td = &txd[i];
+ memmove(td->buf, tb->pkt, tb->len);
+ /* could reduce number of intrs here */
+ td->size = tb->len | TxChainStart | TxChainEnd | TxInt;
+ coherence();
+ td->stat = OwnNic;
+ i = (i + 1) % Ntxd;
+ n++;
+
+ tb->owner = Host;
+ edev->ti = NEXT(edev->ti, edev->ntb);
+ }
+ if (n)
+ iow16(ctlr, Cr, ior16(ctlr, Cr) | Tdmd);
+
+ ctlr->txhead = i;
+ ctlr->txused = txused;
+}
+
+static void
+transmit(Ether *edev)
+{
+ Ctlr *ctlr;
+
+ ctlr = edev->ctlr;
+ ilock(&ctlr->tlock);
+ txstart(edev);
+ iunlock(&ctlr->tlock);
+}
+
+static void
+txcomplete(Ether *edev)
+{
+ Ctlr *ctlr;
+ Desc *txd, *td;
+ int i, txused;
+ ulong stat;
+
+ ctlr = edev->ctlr;
+ txd = ctlr->txd;
+ i = ctlr->txtail;
+ for (txused = ctlr->txused; txused > 0; txused--) {
+ td = &txd[i];
+ stat = td->stat;
+ if (stat & OwnNic)
+ break;
+ i = (i + 1) % Ntxd;
+ }
+ ctlr->txused = txused;
+ ctlr->txtail = i;
+
+ if (txused <= Ntxd/2)
+ txstart(edev);
+}
+
+static void
+interrupt(Ureg *, void *arg)
+{
+ Ether *edev;
+ Ctlr *ctlr;
+ RingBuf *rb;
+ ushort isr, misr;
+ ulong stat;
+ Desc *rxd, *rd;
+ int i, n, size;
+
+ edev = (Ether*)arg;
+ ctlr = edev->ctlr;
+ iow16(ctlr, Imr, 0);
+ isr = ior16(ctlr, Isr);
+ iow16(ctlr, Isr, 0xFFFF);
+ /* don't care about used defined intrs */
+ misr = ior16(ctlr, MiscIsr) & ~(3<<5);
+
+ if (isr & RxOk) {
+ rxd = ctlr->rxd;
+ i = ctlr->rxtail;
+
+ n = 0;
+ while ((rxd[i].stat & OwnNic) == 0) {
+ rd = &rxd[i];
+ stat = rd->stat;
+ if (stat & 0xFF)
+ iprint("rx: %lux\n", stat & 0xFF);
+ size = ((rd->stat>>16) & (2048-1)) - 4;
+
+ rb = &edev->rb[edev->ri];
+ if(rb->owner == Interface){
+ rb->owner = Host;
+ rb->len = size;
+ memmove(rb->pkt, rd->buf, size);
+ edev->ri = NEXT(edev->ri, edev->nrb);
+ }
+
+ rd->size = sizeof(Etherpkt)+4;
+ coherence();
+ rd->stat = OwnNic;
+ i = (i + 1) % Nrxd;
+ n++;
+ }
+ if (n)
+ iow16(ctlr, Cr, ior16(ctlr, Cr) | Rdmd);
+ ctlr->rxtail = i;
+ isr &= ~RxOk;
+ }
+ if (isr & TxOk) {
+ txcomplete(edev);
+ isr &= ~TxOk;
+ }
+ if (isr | misr)
+ iprint("etherrhine: unhandled irq(s). isr:%x misr:%x\n",
+ isr, misr);
+ iow16(ctlr, Imr, 0xFFFF);
+}
+
+static int
+miiread(Mii *mii, int phy, int reg)
+{
+ Ctlr *ctlr;
+ int n;
+
+ ctlr = mii->ctlr;
+
+ n = Nwait;
+ while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd))
+ microdelay(1);
+ if (n == Nwait)
+ iprint("etherrhine: miiread: timeout\n");
+
+ iow8(ctlr, RhineMiiCr, 0);
+ iow8(ctlr, RhineMiiPhy, phy);
+ iow8(ctlr, RhineMiiAddr, reg);
+ iow8(ctlr, RhineMiiCr, Rcmd);
+
+ n = Nwait;
+ while (n-- && ior8(ctlr, RhineMiiCr) & Rcmd)
+ microdelay(1);
+ if (n == Nwait)
+ iprint("etherrhine: miiread: timeout\n");
+
+ return ior16(ctlr, RhineMiiData);
+}
+
+static int
+miiwrite(Mii *mii, int phy, int reg, int data)
+{
+ int n;
+ Ctlr *ctlr;
+
+ ctlr = mii->ctlr;
+
+ n = Nwait;
+ while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd))
+ microdelay(1);
+ if (n == Nwait)
+ iprint("etherrhine: miiwrite: timeout\n");
+
+ iow8(ctlr, RhineMiiCr, 0);
+ iow8(ctlr, RhineMiiPhy, phy);
+ iow8(ctlr, RhineMiiAddr, reg);
+ iow16(ctlr, RhineMiiData, data);
+ iow8(ctlr, RhineMiiCr, Wcmd);
+
+ n = Nwait;
+ while (n-- && ior8(ctlr, RhineMiiCr) & Wcmd)
+ microdelay(1);
+ if (n == Nwait)
+ iprint("etherrhine: miiwrite: timeout\n");
+
+ return 0;
+}
+
+static void
+reset(Ctlr* ctlr)
+{
+ int r, timeo;
+
+ /*
+ * Soft reset the controller.
+ */
+ csr16w(ctlr, Cr, Stop);
+ csr16w(ctlr, Cr, Stop|Reset);
+ for(timeo = 0; timeo < 10000; timeo++){
+ if(!(csr16r(ctlr, Cr) & Reset))
+ break;
+ microdelay(1);
+ }
+ if(timeo >= 1000)
+ return;
+
+ /*
+ * Load the MAC address into the PAR[01]
+ * registers.
+ */
+ r = csr8r(ctlr, Eecsr);
+ csr8w(ctlr, Eecsr, EeAutoLoad|r);
+ for(timeo = 0; timeo < 100; timeo++){
+ if(!(csr8r(ctlr, Cr) & EeAutoLoad))
+ break;
+ microdelay(1);
+ }
+ if(timeo >= 100)
+ return;
+
+ /*
+ * Configure DMA and Rx/Tx thresholds.
+ * If the Rx/Tx threshold bits in Bcr[01] are 0 then
+ * the thresholds are determined by Rcr/Tcr.
+ */
+ r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK);
+ csr8w(ctlr, Bcr0, r|Crft64|Dma64);
+ r = csr8r(ctlr, Bcr1) & ~CtftMASK;
+ csr8w(ctlr, Bcr1, r|Ctft64);
+
+ r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep);
+ csr8w(ctlr, Rcr, r|Ab|Am);
+
+ r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0);
+ csr8w(ctlr, Tcr, r);
+}
+
+static void
+detach(Ether* edev)
+{
+ reset(edev->ctlr);
+}
+
+static void
+init(Ether *edev)
+{
+ Ctlr *ctlr;
+ int i;
+
+ ctlr = edev->ctlr;
+ ilock(&ctlr->tlock);
+
+ pcisetbme(ctlr->pci);
+ reset(ctlr);
+
+ iow8(ctlr, Eecsr, ior8(ctlr, Eecsr) | EeAutoLoad);
+ for (i = 0; i < Nwait; ++i) {
+ if ((ior8(ctlr, Eecsr) & EeAutoLoad) == 0)
+ break;
+ delay(5);
+ }
+ if (i >= Nwait)
+ iprint("etherrhine: eeprom autoload timeout\n");
+
+ for (i = 0; i < Eaddrlen; ++i)
+ edev->ea[i] = ior8(ctlr, Eaddr + i);
+
+ ctlr->mii.mir = miiread;
+ ctlr->mii.miw = miiwrite;
+ ctlr->mii.ctlr = ctlr;
+
+ if(mii(&ctlr->mii, ~0) == 0 || ctlr->mii.curphy == nil){
+ iunlock(&ctlr->tlock);
+ iprint("etherrhine: init mii failure\n");
+ return;
+ }
+ for (i = 0; i < NMiiPhy; ++i)
+ if (ctlr->mii.phy[i])
+ if (ctlr->mii.phy[i]->oui != 0xFFFFF)
+ ctlr->mii.curphy = ctlr->mii.phy[i];
+ miistatus(&ctlr->mii);
+
+ iow16(ctlr, Imr, 0);
+ iow16(ctlr, Cr, ior16(ctlr, Cr) | Stop);
+
+ iunlock(&ctlr->tlock);
+}
+
+static Pcidev *
+rhinematch(ulong)
+{
+ static int nrhines = 0;
+ int nfound = 0;
+ Pcidev *p = nil;
+
+ while(p = pcimatch(p, 0x1106, 0)){
+ if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
+ continue;
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+ case (0x3053<<16)|0x1106: /* Rhine III vt6105m (Soekris) */
+ case (0x3065<<16)|0x1106: /* Rhine II */
+ case (0x3106<<16)|0x1106: /* Rhine III */
+ if (++nfound > nrhines) {
+ nrhines++;
+ return p;
+ }
+ break;
+ }
+ }
+ return p;
+}
+
+int
+rhinepnp(Ether *edev)
+{
+ Pcidev *p;
+ Ctlr *ctlr;
+ ulong port;
+
+ if (edev->attach)
+ return 0;
+ p = rhinematch(edev->port);
+ if (p == nil)
+ return -1;
+
+ port = p->mem[0].bar & ~1;
+
+ if ((ctlr = malloc(sizeof(Ctlr))) == nil) {
+ print("etherrhine: couldn't allocate memory for ctlr\n");
+ return -1;
+ }
+ memset(ctlr, 0, sizeof(Ctlr));
+ ctlr->txd = xspanalloc(sizeof(Desc) * Ntxd, 16, 0);
+ ctlr->rxd = xspanalloc(sizeof(Desc) * Nrxd, 16, 0);
+
+ ctlr->pci = p;
+ ctlr->port = port;
+
+ edev->ctlr = ctlr;
+ edev->port = ctlr->port;
+ edev->irq = p->intl;
+ edev->tbdf = p->tbdf;
+
+ init(edev);
+
+ edev->attach = attach;
+ edev->transmit = transmit;
+ edev->interrupt = interrupt;
+ edev->detach = detach;
+
+ return 0;
+}
+
+int
+vt6102pnp(Ether *edev)
+{
+ return rhinepnp(edev);
+}
--- /dev/null
+++ b/os/boot.original/pc/fns.h
@@ -1,0 +1,175 @@
+void aamloop(int);
+void addconf(char*, ...);
+Alarm* alarm(int, void (*)(Alarm*), void*);
+void alarminit(void);
+Block* allocb(int);
+void apminit(void);
+int biosboot(int dev, char *file, Boot *b);
+void* biosgetfspart(int i, char *name, int chatty);
+void biosinitdev(int i, char *name);
+int biosinit(void);
+void biosprintbootdevs(int dev);
+void biosprintdevs(int i);
+int bootpboot(int, char*, Boot*);
+int bootpass(Boot*, void*, int);
+void cancel(Alarm*);
+int cdinit(void);
+void check(char*);
+void cgascreenputs(char*, int);
+int cistrcmp(char*, char*);
+int cistrncmp(char*, char*, int);
+void changeconf(char*, ...);
+void checkalarms(void);
+void clockinit(void);
+#define coherence() mb386()
+void consdrain(void);
+void consinit(char*, char*);
+void consputs(char*, int);
+void delay(int);
+uchar* etheraddr(int);
+int etherinit(void);
+void etherinitdev(int, char*);
+void etherprintdevs(int);
+int etherrxflush(int);
+int etherrxpkt(int, Etherpkt*, int);
+int ethertxpkt(int, Etherpkt*, int, int);
+#define evenaddr(x) /* 386 doesn't care */
+int floppyboot(int, char*, Boot*);
+int floppyinit(void);
+void floppyinitdev(int, char*);
+void floppyprintdevs(int);
+void* floppygetfspart(int, char*, int);
+void freeb(Block*);
+char* getconf(char*);
+ulong getcr0(void);
+ulong getcr2(void);
+ulong getcr3(void);
+ulong getcr4(void);
+int getfields(char*, char**, int, char);
+int getstr(char*, char*, int, char*, int);
+int gunzip(uchar*, int, uchar*, int);
+void i8042a20(void);
+void i8042init(void);
+void i8042reset(void);
+void* ialloc(ulong, int);
+void idle(void);
+void ilock(Lock*);
+int inb(int);
+ushort ins(int);
+ulong inl(int);
+void insb(int, void*, int);
+void inss(int, void*, int);
+void insl(int, void*, int);
+#define ioalloc(addr, len, align, name) (addr)
+#define iofree(addr)
+void iunlock(Lock*);
+int isaconfig(char*, int, ISAConf*);
+void kbdinit(void);
+void kbdchar(int);
+void machinit(void);
+void mb386(void);
+void meminit(ulong);
+void microdelay(int);
+void mmuinit(void);
+#define nelem(x) (sizeof(x)/sizeof(x[0]))
+char* nextelem(char*, char*);
+uchar nvramread(int);
+void outb(int, int);
+void outs(int, ushort);
+void outl(int, ulong);
+void outsb(int, void*, int);
+void outss(int, void*, int);
+void outsl(int, void*, int);
+void panic(char*, ...);
+ulong pcibarsize(Pcidev*, int);
+int pcicfgr8(Pcidev*, int);
+int pcicfgr16(Pcidev*, int);
+int pcicfgr32(Pcidev*, int);
+void pcicfgw8(Pcidev*, int, int);
+void pcicfgw16(Pcidev*, int, int);
+void pcicfgw32(Pcidev*, int, int);
+void pciclrbme(Pcidev*);
+void pciclrioe(Pcidev*);
+void pciclrmwi(Pcidev*);
+int pcigetpms(Pcidev*);
+void pcihinv(Pcidev*);
+Pcidev* pcimatch(Pcidev*, int, int);
+uchar pciintl(Pcidev *);
+uchar pciipin(Pcidev *, uchar);
+void pcireset(void);
+void pcisetbme(Pcidev*);
+void pcisetioe(Pcidev*);
+void pcisetmwi(Pcidev*);
+int pcisetpms(Pcidev*, int);
+void pcmcisread(PCMslot*);
+int pcmcistuple(int, int, int, void*, int);
+PCMmap* pcmmap(int, ulong, int, int);
+int pcmspecial(char*, ISAConf*);
+void pcmspecialclose(int);
+void pcmunmap(int, PCMmap*);
+void ptcheck(char*);
+void putcr3(ulong);
+void putidt(Segdesc*, int);
+void* pxegetfspart(int, char*, int);
+void qinit(IOQ*);
+void readlsconf(void);
+void sdaddconf(int);
+int sdboot(int, char*, Boot*);
+void sdcheck(char*);
+void* sdgetfspart(int, char*, int);
+int sdinit(void);
+void sdinitdev(int, char*);
+void sdprintdevs(int);
+int sdsetpart(int, char*);
+void setvec(int, void (*)(Ureg*, void*), void*);
+int splhi(void);
+int spllo(void);
+void splx(int);
+void trapinit(void);
+void trapdisable(void);
+void trapenable(void);
+void uartdrain(void);
+void uartspecial(int, void (*)(int), int (*)(void), int);
+void uartputs(IOQ*, char*, int);
+ulong umbmalloc(ulong, int, int);
+void umbfree(ulong, int);
+ulong umbrwmalloc(ulong, int, int);
+void upafree(ulong, int);
+ulong upamalloc(ulong, int, int);
+void warp86(char*, ulong);
+void warp9(ulong);
+int x86cpuid(int*, int*);
+void* xspanalloc(ulong, int, ulong);
+
+#define malloc(n) ialloc(n, 0)
+#define mallocz(n, c) ialloc(n, 0)
+#define free(v) while(0)
+
+#define GSHORT(p) (((p)[1]<<8)|(p)[0])
+#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))
+#define GLSHORT(p) (((p)[0]<<8)|(p)[1])
+#define GLLONG(p) (((ulong)GLSHORT(p)<<16)|GLSHORT(p+2))
+#define PLLONG(p,v) (p)[3]=(v);(p)[2]=(v)>>8;(p)[1]=(v)>>16;(p)[0]=(v)>>24
+
+#define KADDR(a) ((void*)((ulong)(a)|KZERO))
+#define PADDR(a) ((ulong)(a)&~0xF0000000)
+
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
+
+
+#define xalloc(n) ialloc(n, 0)
+#define xfree(v) while(0)
+#define lock(l) if(l){/* nothing to do */;}else{/* nothing to do */;}
+#define unlock(l) if(l){/* nothing to do */;}else{/* nothing to do */;}
+
+int dmacount(int);
+int dmadone(int);
+void dmaend(int);
+void dmainit(int);
+long dmasetup(int, void*, long, int);
+
+extern int (*_pcmspecial)(char *, ISAConf *);
+extern void (*_pcmspecialclose)(int);
+extern void devi82365link(void);
+extern void devpccardlink(void);
--- /dev/null
+++ b/os/boot.original/pc/fs.c
@@ -1,0 +1,94 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "fs.h"
+
+/*
+ * grab next element from a path, return the pointer to unprocessed portion of
+ * path.
+ */
+char *
+nextelem(char *path, char *elem)
+{
+ int i;
+
+ while(*path == '/')
+ path++;
+ if(*path==0 || *path==' ')
+ return 0;
+ for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
+ if(i==NAMELEN){
+ print("name component too long\n");
+ return 0;
+ }
+ *elem++ = *path++;
+ }
+ *elem = '\0';
+ return path;
+}
+
+int
+fswalk(Fs *fs, char *path, File *f)
+{
+ char element[NAMELEN];
+
+ *f = fs->root;
+ if(BADPTR(fs->walk))
+ panic("fswalk bad pointer fs->walk");
+
+ f->path = path;
+ while(path = nextelem(path, element)){
+ switch(fs->walk(f, element)){
+ case -1:
+ return -1;
+ case 0:
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * boot
+ */
+int
+fsboot(Fs *fs, char *path, Boot *b)
+{
+ File file;
+ long n;
+ static char buf[8192];
+
+ switch(fswalk(fs, path, &file)){
+ case -1:
+ print("error walking to %s\n", path);
+ return -1;
+ case 0:
+ print("%s not found\n", path);
+ return -1;
+ case 1:
+ print("found %s\n", path);
+ break;
+ }
+
+ while((n = fsread(&file, buf, sizeof buf)) > 0) {
+ if(bootpass(b, buf, n) != MORE)
+ break;
+ }
+
+ bootpass(b, nil, 0); /* tries boot */
+ return -1;
+}
+
+int
+fsread(File *file, void *a, long n)
+{
+ if(BADPTR(file->fs))
+ panic("bad pointer file->fs in fsread");
+ if(BADPTR(file->fs->read))
+ panic("bad pointer file->fs->read in fsread");
+ return file->fs->read(file, a, n);
+}
--- /dev/null
+++ b/os/boot.original/pc/fs.h
@@ -1,0 +1,36 @@
+typedef struct File File;
+typedef struct Fs Fs;
+
+#include "dosfs.h"
+#include "kfs.h"
+
+struct File{
+ union{
+ Dosfile dos;
+ Kfsfile kfs;
+ int walked;
+ };
+ Fs *fs;
+ char *path;
+};
+
+struct Fs{
+ union {
+ Dos dos;
+ Kfs kfs;
+ };
+ int dev; /* device id */
+ long (*diskread)(Fs*, void*, long); /* disk read routine */
+ vlong (*diskseek)(Fs*, vlong); /* disk seek routine */
+ long (*read)(File*, void*, long);
+ int (*walk)(File*, char*);
+ File root;
+};
+
+extern int chatty;
+extern int dotini(Fs*);
+extern int fswalk(Fs*, char*, File*);
+extern int fsread(File*, void*, long);
+extern int fsboot(Fs*, char*, Boot*);
+
+#define BADPTR(x) ((ulong)x < 0x80000000)
--- /dev/null
+++ b/os/boot.original/pc/getcallerpc.c
@@ -1,0 +1,8 @@
+#include "u.h"
+#include "lib.h"
+
+ulong
+getcallerpc(void *x)
+{
+ return (((ulong*)(x))[-1]);
+}
--- /dev/null
+++ b/os/boot.original/pc/ilock.c
@@ -1,0 +1,24 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+void
+ilock(Lock *lk)
+{
+ if(lk->locked != 0)
+ panic("ilock");
+ lk->spl = splhi();
+ lk->locked = 1;
+}
+
+void
+iunlock(Lock *lk)
+{
+ if(lk->locked != 1)
+ panic("iunlock");
+ lk->locked = 0;
+ splx(lk->spl);
+}
--- /dev/null
+++ b/os/boot.original/pc/inflate.c
@@ -1,0 +1,199 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include <flate.h>
+
+typedef struct Biobuf Biobuf;
+
+struct Biobuf
+{
+ uchar *bp;
+ uchar *p;
+ uchar *ep;
+};
+
+static int header(Biobuf*);
+static int trailer(Biobuf*, Biobuf*);
+static int getc(void*);
+static ulong offset(Biobuf*);
+static int crcwrite(void *out, void *buf, int n);
+static ulong get4(Biobuf *b);
+static ulong Boffset(Biobuf *bp);
+
+/* GZIP flags */
+enum {
+ Ftext= (1<<0),
+ Fhcrc= (1<<1),
+ Fextra= (1<<2),
+ Fname= (1<<3),
+ Fcomment= (1<<4),
+
+ GZCRCPOLY = 0xedb88320UL,
+};
+
+static ulong *crctab;
+static ulong crc;
+
+extern void diff(char*); //XXX
+int
+gunzip(uchar *out, int outn, uchar *in, int inn)
+{
+ Biobuf bin, bout;
+ int err;
+
+ crc = 0;
+ crctab = mkcrctab(GZCRCPOLY);
+ err = inflateinit();
+ if(err != FlateOk)
+ print("inflateinit failed: %s\n", flateerr(err));
+
+ bin.bp = bin.p = in;
+ bin.ep = in+inn;
+ bout.bp = bout.p = out;
+ bout.ep = out+outn;
+
+ err = header(&bin);
+ if(err != FlateOk)
+ return err;
+
+ err = inflate(&bout, crcwrite, &bin, getc);
+ if(err != FlateOk)
+ print("inflate failed: %s\n", flateerr(err));
+
+ err = trailer(&bout, &bin);
+ if(err != FlateOk)
+ return err;
+
+ return Boffset(&bout);
+}
+
+static int
+header(Biobuf *bin)
+{
+ int i, flag;
+
+ if(getc(bin) != 0x1f || getc(bin) != 0x8b){
+ print("bad magic\n");
+ return FlateCorrupted;
+ }
+ if(getc(bin) != 8){
+ print("unknown compression type\n");
+ return FlateCorrupted;
+ }
+
+ flag = getc(bin);
+
+ /* mod time */
+ get4(bin);
+
+ /* extra flags */
+ getc(bin);
+
+ /* OS type */
+ getc(bin);
+
+ if(flag & Fextra)
+ for(i=getc(bin); i>0; i--)
+ getc(bin);
+
+ /* name */
+ if(flag&Fname)
+ while(getc(bin) != 0)
+ ;
+
+ /* comment */
+ if(flag&Fcomment)
+ while(getc(bin) != 0)
+ ;
+
+ /* crc16 */
+ if(flag&Fhcrc) {
+ getc(bin);
+ getc(bin);
+ }
+
+ return FlateOk;
+}
+
+static int
+trailer(Biobuf *bout, Biobuf *bin)
+{
+ /* crc32 */
+ if(crc != get4(bin)){
+ print("crc mismatch\n");
+ return FlateCorrupted;
+ }
+
+ /* length */
+ if(get4(bin) != Boffset(bout)){
+ print("bad output len\n");
+ return FlateCorrupted;
+ }
+ return FlateOk;
+}
+
+static ulong
+get4(Biobuf *b)
+{
+ ulong v;
+ int i, c;
+
+ v = 0;
+ for(i = 0; i < 4; i++){
+ c = getc(b);
+ v |= c << (i * 8);
+ }
+ return v;
+}
+
+static int
+getc(void *in)
+{
+ Biobuf *bp = in;
+
+// if((bp->p - bp->bp) % 10000 == 0)
+// print(".");
+ if(bp->p >= bp->ep)
+ return -1;
+ return *bp->p++;
+}
+
+static ulong
+Boffset(Biobuf *bp)
+{
+ return bp->p - bp->bp;
+}
+
+static int
+crcwrite(void *out, void *buf, int n)
+{
+ Biobuf *bp;
+ int nn;
+
+ crc = blockcrc(crctab, crc, buf, n);
+ bp = out;
+ nn = n;
+ if(nn > bp->ep-bp->p)
+ nn = bp->ep-bp->p;
+ if(nn > 0)
+ memmove(bp->p, buf, nn);
+ bp->p += n;
+ return n;
+}
+
+#undef malloc
+#undef free
+
+void *
+malloc(ulong n)
+{
+ return ialloc(n, 8);
+}
+
+void
+free(void *)
+{
+}
--- /dev/null
+++ b/os/boot.original/pc/io.h
@@ -1,0 +1,317 @@
+/*
+ * programmable interrupt vectors (for the 8259's)
+ */
+enum
+{
+ Bptvec= 3, /* breakpoints */
+ Mathemuvec= 7, /* math coprocessor emulation interrupt */
+ Mathovervec= 9, /* math coprocessor overrun interrupt */
+ Matherr1vec= 16, /* math coprocessor error interrupt */
+ Faultvec= 14, /* page fault */
+
+ Syscallvec= 64,
+
+ VectorPIC = 24, /* external [A]PIC interrupts */
+ VectorCLOCK = VectorPIC+0,
+ VectorKBD = VectorPIC+1,
+ VectorUART1 = VectorPIC+3,
+ VectorUART0 = VectorPIC+4,
+ VectorPCMCIA = VectorPIC+5,
+ VectorFLOPPY = VectorPIC+6,
+ VectorLPT = VectorPIC+7,
+ VectorIRQ7 = VectorPIC+7,
+ VectorAUX = VectorPIC+12, /* PS/2 port */
+ VectorIRQ13 = VectorPIC+13, /* coprocessor on x386 */
+ VectorATA0 = VectorPIC+14,
+ VectorATA1 = VectorPIC+15,
+ MaxVectorPIC = VectorPIC+15,
+};
+
+enum {
+ BusCBUS = 0, /* Corollary CBUS */
+ BusCBUSII, /* Corollary CBUS II */
+ BusEISA, /* Extended ISA */
+ BusFUTURE, /* IEEE Futurebus */
+ BusINTERN, /* Internal bus */
+ BusISA, /* Industry Standard Architecture */
+ BusMBI, /* Multibus I */
+ BusMBII, /* Multibus II */
+ BusMCA, /* Micro Channel Architecture */
+ BusMPI, /* MPI */
+ BusMPSA, /* MPSA */
+ BusNUBUS, /* Apple Macintosh NuBus */
+ BusPCI, /* Peripheral Component Interconnect */
+ BusPCMCIA, /* PC Memory Card International Association */
+ BusTC, /* DEC TurboChannel */
+ BusVL, /* VESA Local bus */
+ BusVME, /* VMEbus */
+ BusXPRESS, /* Express System Bus */
+};
+
+#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
+#define BUSFNO(tbdf) (((tbdf)>>8)&0x07)
+#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F)
+#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF)
+#define BUSTYPE(tbdf) ((tbdf)>>24)
+#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00)
+#define BUSUNKNOWN (-1)
+
+enum {
+ MaxEISA = 16,
+ CfgEISA = 0xC80,
+};
+
+/*
+ * PCI support code.
+ */
+enum { /* type 0 and type 1 pre-defined header */
+ PciVID = 0x00, /* vendor ID */
+ PciDID = 0x02, /* device ID */
+ PciPCR = 0x04, /* command */
+ PciPSR = 0x06, /* status */
+ PciRID = 0x08, /* revision ID */
+ PciCCRp = 0x09, /* programming interface class code */
+ PciCCRu = 0x0A, /* sub-class code */
+ PciCCRb = 0x0B, /* base class code */
+ PciCLS = 0x0C, /* cache line size */
+ PciLTR = 0x0D, /* latency timer */
+ PciHDT = 0x0E, /* header type */
+ PciBST = 0x0F, /* BIST */
+
+ PciBAR0 = 0x10, /* base address */
+ PciBAR1 = 0x14,
+
+ PciINTL = 0x3C, /* interrupt line */
+ PciINTP = 0x3D, /* interrupt pin */
+};
+
+/* ccrb (base class code) values; controller types */
+enum {
+ Pcibcpci1 = 0, /* pci 1.0; no class codes defined */
+ Pcibcstore = 1, /* mass storage */
+ Pcibcnet = 2, /* network */
+ Pcibcdisp = 3, /* display */
+ Pcibcmmedia = 4, /* multimedia */
+ Pcibcmem = 5, /* memory */
+ Pcibcbridge = 6, /* bridge */
+ Pcibccomm = 7, /* simple comms (e.g., serial) */
+ Pcibcbasesys = 8, /* base system */
+ Pcibcinput = 9, /* input */
+ Pcibcdock = 0xa, /* docking stations */
+ Pcibcproc = 0xb, /* processors */
+ Pcibcserial = 0xc, /* serial bus (e.g., USB) */
+ Pcibcwireless = 0xd, /* wireless */
+ Pcibcintell = 0xe, /* intelligent i/o */
+ Pcibcsatcom = 0xf, /* satellite comms */
+ Pcibccrypto = 0x10, /* encryption/decryption */
+ Pcibcdacq = 0x11, /* data acquisition & signal proc. */
+};
+
+/* ccru (sub-class code) values; common cases only */
+enum {
+ /* mass storage */
+ Pciscscsi = 0, /* SCSI */
+ Pciscide = 1, /* IDE (ATA) */
+
+ /* network */
+ Pciscether = 0, /* Ethernet */
+
+ /* display */
+ Pciscvga = 0, /* VGA */
+ Pciscxga = 1, /* XGA */
+ Pcisc3d = 2, /* 3D */
+
+ /* bridges */
+ Pcischostpci = 0, /* host/pci */
+ Pciscpcicpci = 1, /* pci/pci */
+
+ /* simple comms */
+ Pciscserial = 0, /* 16450, etc. */
+ Pciscmultiser = 1, /* multiport serial */
+
+ /* serial bus */
+ Pciscusb = 3, /* USB */
+};
+
+enum { /* type 0 pre-defined header */
+ PciBAR2 = 0x18,
+ PciBAR3 = 0x1C,
+ PciBAR4 = 0x20,
+ PciBAR5 = 0x24,
+ PciCIS = 0x28, /* cardbus CIS pointer */
+ PciSVID = 0x2C, /* subsystem vendor ID */
+ PciSID = 0x2E, /* cardbus CIS pointer */
+ PciEBAR0 = 0x30, /* expansion ROM base address */
+ PciMGNT = 0x3E, /* burst period length */
+ PciMLT = 0x3F, /* maximum latency between bursts */
+};
+
+enum { /* type 1 pre-defined header */
+ PciPBN = 0x18, /* primary bus number */
+ PciSBN = 0x19, /* secondary bus number */
+ PciUBN = 0x1A, /* subordinate bus number */
+ PciSLTR = 0x1B, /* secondary latency timer */
+ PciIBR = 0x1C, /* I/O base */
+ PciILR = 0x1D, /* I/O limit */
+ PciSPSR = 0x1E, /* secondary status */
+ PciMBR = 0x20, /* memory base */
+ PciMLR = 0x22, /* memory limit */
+ PciPMBR = 0x24, /* prefetchable memory base */
+ PciPMLR = 0x26, /* prefetchable memory limit */
+ PciPUBR = 0x28, /* prefetchable base upper 32 bits */
+ PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
+ PciIUBR = 0x30, /* I/O base upper 16 bits */
+ PciIULR = 0x32, /* I/O limit upper 16 bits */
+ PciEBAR1 = 0x28, /* expansion ROM base address */
+ PciBCR = 0x3E, /* bridge control register */
+};
+
+enum { /* type 2 pre-defined header */
+ PciCBExCA = 0x10,
+ PciCBSPSR = 0x16,
+ PciCBPBN = 0x18, /* primary bus number */
+ PciCBSBN = 0x19, /* secondary bus number */
+ PciCBUBN = 0x1A, /* subordinate bus number */
+ PciCBSLTR = 0x1B, /* secondary latency timer */
+ PciCBMBR0 = 0x1C,
+ PciCBMLR0 = 0x20,
+ PciCBMBR1 = 0x24,
+ PciCBMLR1 = 0x28,
+ PciCBIBR0 = 0x2C, /* I/O base */
+ PciCBILR0 = 0x30, /* I/O limit */
+ PciCBIBR1 = 0x34, /* I/O base */
+ PciCBILR1 = 0x38, /* I/O limit */
+ PciCBBCTL = 0x3E, /* Bridge control */
+ PciCBSVID = 0x40, /* subsystem vendor ID */
+ PciCBSID = 0x42, /* subsystem ID */
+ PciCBLMBAR = 0x44, /* legacy mode base address */
+};
+
+typedef struct Pcisiz Pcisiz;
+struct Pcisiz
+{
+ Pcidev* dev;
+ int siz;
+ int bar;
+};
+
+typedef struct Pcidev Pcidev;
+typedef struct Pcidev {
+ int tbdf; /* type+bus+device+function */
+ ushort vid; /* vendor ID */
+ ushort did; /* device ID */
+
+ ushort pcr;
+
+ uchar rid;
+ uchar ccrp;
+ uchar ccru;
+ uchar ccrb;
+ uchar cls;
+ uchar ltr;
+
+ struct {
+ ulong bar; /* base address */
+ int size;
+ } mem[6];
+
+ struct {
+ ulong bar;
+ int size;
+ } rom;
+ uchar intl; /* interrupt line */
+
+ Pcidev* list;
+ Pcidev* link; /* next device on this bno */
+
+ Pcidev* bridge; /* down a bus */
+ struct {
+ ulong bar;
+ int size;
+ } ioa, mema;
+
+ int pmrb; /* power management register block */
+};
+
+#define PCIWINDOW 0
+#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)
+#define ISAWINDOW 0
+#define ISAWADDR(va) (PADDR(va)+ISAWINDOW)
+
+/*
+ * PCMCIA support code.
+ */
+typedef struct PCMslot PCMslot;
+typedef struct PCMconftab PCMconftab;
+
+/*
+ * Map between ISA memory space and PCMCIA card memory space.
+ */
+struct PCMmap {
+ ulong ca; /* card address */
+ ulong cea; /* card end address */
+ ulong isa; /* ISA address */
+ int len; /* length of the ISA area */
+ int attr; /* attribute memory */
+ int ref;
+};
+
+/* configuration table entry */
+struct PCMconftab
+{
+ int index;
+ ushort irqs; /* legal irqs */
+ uchar irqtype;
+ uchar bit16; /* true for 16 bit access */
+ struct {
+ ulong start;
+ ulong len;
+ } io[16];
+ int nio;
+ uchar vpp1;
+ uchar vpp2;
+ uchar memwait;
+ ulong maxwait;
+ ulong readywait;
+ ulong otherwait;
+};
+
+/* a card slot */
+struct PCMslot
+{
+ Lock;
+ int ref;
+
+ void *cp; /* controller for this slot */
+ long memlen; /* memory length */
+ uchar base; /* index register base */
+ uchar slotno; /* slot number */
+
+ /* status */
+ uchar special; /* in use for a special device */
+ uchar already; /* already inited */
+ uchar occupied;
+ uchar battery;
+ uchar wrprot;
+ uchar powered;
+ uchar configed;
+ uchar enabled;
+ uchar busy;
+
+ /* cis info */
+ ulong msec; /* time of last slotinfo call */
+ char verstr[512]; /* version string */
+ int ncfg; /* number of configurations */
+ struct {
+ ushort cpresent; /* config registers present */
+ ulong caddr; /* relative address of config registers */
+ } cfg[8];
+ int nctab; /* number of config table entries */
+ PCMconftab ctab[8];
+ PCMconftab *def; /* default conftab */
+
+ /* memory maps */
+ Lock mlock; /* lock down the maps */
+ int time;
+ PCMmap mmap[4]; /* maps, last is always for the kernel */
+};
--- /dev/null
+++ b/os/boot.original/pc/ip.h
@@ -1,0 +1,100 @@
+typedef struct Udphdr Udphdr;
+struct Udphdr
+{
+ uchar d[6]; /* Ethernet destination */
+ uchar s[6]; /* Ethernet source */
+ uchar type[2]; /* Ethernet packet type */
+
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+
+ /* Udp pseudo ip really starts here */
+ uchar ttl;
+ uchar udpproto; /* Protocol */
+ uchar udpplen[2]; /* Header plus data length */
+ uchar udpsrc[4]; /* Ip source */
+ uchar udpdst[4]; /* Ip destination */
+ uchar udpsport[2]; /* Source port */
+ uchar udpdport[2]; /* Destination port */
+ uchar udplen[2]; /* data length */
+ uchar udpcksum[2]; /* Checksum */
+};
+
+typedef struct Etherhdr Etherhdr;
+struct Etherhdr
+{
+ uchar d[6];
+ uchar s[6];
+ uchar type[2];
+
+ /* Now we have the ip fields */
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+ uchar ttl; /* Time to live */
+ uchar proto; /* Protocol */
+ uchar cksum[2]; /* Header checksum */
+ uchar src[4]; /* Ip source */
+ uchar dst[4]; /* Ip destination */
+};
+
+enum
+{
+ IP_VER = 0x40,
+ IP_HLEN = 0x05,
+ UDP_EHSIZE = 22,
+ UDP_PHDRSIZE = 12,
+ UDP_HDRSIZE = 20,
+ ETHER_HDR = 14,
+ IP_UDPPROTO = 17,
+ ET_IP = 0x800,
+ Bcastip = 0xffffffff,
+ BPportsrc = 68,
+ BPportdst = 67,
+ TFTPport = 69,
+ Timeout = 5000, /* milliseconds */
+ Bootrequest = 1,
+ Bootreply = 2,
+ Tftp_READ = 1,
+ Tftp_WRITE = 2,
+ Tftp_DATA = 3,
+ Tftp_ACK = 4,
+ Tftp_ERROR = 5,
+ Segsize = 512,
+ TFTPSZ = Segsize+10,
+};
+
+typedef struct Bootp Bootp;
+struct Bootp
+{
+ uchar op; /* opcode */
+ uchar htype; /* hardware type */
+ uchar hlen; /* hardware address len */
+ uchar hops; /* hops */
+ uchar xid[4]; /* a random number */
+ uchar secs[2]; /* elapsed since client started booting */
+ uchar pad[2];
+ uchar ciaddr[4]; /* client IP address (client tells server) */
+ uchar yiaddr[4]; /* client IP address (server tells client) */
+ uchar siaddr[4]; /* server IP address */
+ uchar giaddr[4]; /* gateway IP address */
+ uchar chaddr[16]; /* client hardware address */
+ char sname[64]; /* server host name (optional) */
+ char file[128]; /* boot file name */
+ char vend[128]; /* vendor-specific goo */
+};
+
+typedef struct Netaddr Netaddr;
+struct Netaddr
+{
+ ulong ip;
+ ushort port;
+ char ea[Eaddrlen];
+};
+
+extern int eipfmt(Fmt*);
--- /dev/null
+++ b/os/boot.original/pc/kbd.c
@@ -1,0 +1,489 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum {
+ Data= 0x60, /* data port */
+
+ Status= 0x64, /* status port */
+ Inready= 0x01, /* input character ready */
+ Outbusy= 0x02, /* output busy */
+ Sysflag= 0x04, /* system flag */
+ Cmddata= 0x08, /* cmd==0, data==1 */
+ Inhibit= 0x10, /* keyboard/mouse inhibited */
+ Minready= 0x20, /* mouse character ready */
+ Rtimeout= 0x40, /* general timeout */
+ Parity= 0x80,
+
+ Cmd= 0x64, /* command port (write only) */
+
+ Spec= 0x80,
+
+ PF= Spec|0x20, /* num pad function key */
+ View= Spec|0x00, /* view (shift window up) */
+ KF= Spec|0x40, /* function key */
+ Shift= Spec|0x60,
+ Break= Spec|0x61,
+ Ctrl= Spec|0x62,
+ Latin= Spec|0x63,
+ Caps= Spec|0x64,
+ Num= Spec|0x65,
+ No= Spec|0x7F, /* no mapping */
+
+ Home= KF|13,
+ Up= KF|14,
+ Pgup= KF|15,
+ Print= KF|16,
+ Left= View,
+ Right= View,
+ End= '\r',
+ Down= View,
+ Pgdown= View,
+ Ins= KF|20,
+ Del= 0x7F,
+};
+
+uchar kbtab[] =
+{
+[0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
+[0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
+[0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+[0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
+[0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+[0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
+[0x30] 'b', 'n', 'm', ',', '.', '/', Shift, No,
+[0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
+[0x48] No, No, No, No, No, No, No, No,
+[0x50] No, No, No, No, No, No, No, KF|11,
+[0x58] KF|12, No, No, No, No, No, No, No,
+};
+
+uchar kbtabshift[] =
+{
+[0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
+[0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
+[0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
+[0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
+[0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
+[0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
+[0x30] 'B', 'N', 'M', '<', '>', '?', Shift, No,
+[0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
+[0x48] No, No, No, No, No, No, No, No,
+[0x50] No, No, No, No, No, No, No, KF|11,
+[0x58] KF|12, No, No, No, No, No, No, No,
+};
+
+uchar kbtabesc1[] =
+{
+[0x00] No, No, No, No, No, No, No, No,
+[0x08] No, No, No, No, No, No, No, No,
+[0x10] No, No, No, No, No, No, No, No,
+[0x18] No, No, No, No, No, Ctrl, No, No,
+[0x20] No, No, No, No, No, No, No, No,
+[0x28] No, No, No, No, No, No, No, No,
+[0x30] No, No, No, No, No, No, No, Print,
+[0x38] Latin, No, No, No, No, No, No, No,
+[0x40] No, No, No, No, No, No, Break, Home,
+[0x48] Up, Pgup, No, Down, No, Right, No, End,
+[0x50] Left, Pgdown, Ins, Del, No, No, No, No,
+[0x58] No, No, No, No, No, No, No, No,
+};
+
+struct latin
+{
+ uchar l;
+ char c[2];
+}latintab[] = {
+ L'¡', "!!", /* spanish initial ! */
+ L'¢', "c|", /* cent */
+ L'¢', "c$", /* cent */
+ L'£', "l$", /* pound sterling */
+ L'¤', "g$", /* general currency */
+ L'¥', "y$", /* yen */
+ L'¥', "j$", /* yen */
+ L'¦', "||", /* broken vertical bar */
+ L'§', "SS", /* section symbol */
+ L'¨', "\"\"", /* dieresis */
+ L'©', "cr", /* copyright */
+ L'©', "cO", /* copyright */
+ L'ª', "sa", /* super a, feminine ordinal */
+ L'«', "<<", /* left angle quotation */
+ L'¬', "no", /* not sign, hooked overbar */
+ L'', "--", /* soft hyphen */
+ L'®', "rg", /* registered trademark */
+ L'¯', "__", /* macron */
+ L'°', "s0", /* degree (sup o) */
+ L'±', "+-", /* plus-minus */
+ L'²', "s2", /* sup 2 */
+ L'³', "s3", /* sup 3 */
+ L'´', "''", /* grave accent */
+ L'µ', "mu", /* mu */
+ L'¶', "pg", /* paragraph (pilcrow) */
+ L'·', "..", /* centered . */
+ L'¸', ",,", /* cedilla */
+ L'¹', "s1", /* sup 1 */
+ L'º', "so", /* sup o */
+ L'»', ">>", /* right angle quotation */
+ L'¼', "14", /* 1/4 */
+ L'½', "12", /* 1/2 */
+ L'¾', "34", /* 3/4 */
+ L'¿', "??", /* spanish initial ? */
+ L'À', "A`", /* A grave */
+ L'Á', "A'", /* A acute */
+ L'Â', "A^", /* A circumflex */
+ L'Ã', "A~", /* A tilde */
+ L'Ä', "A\"", /* A dieresis */
+ L'Ä', "A:", /* A dieresis */
+ L'Å', "Ao", /* A circle */
+ L'Å', "AO", /* A circle */
+ L'Æ', "Ae", /* AE ligature */
+ L'Æ', "AE", /* AE ligature */
+ L'Ç', "C,", /* C cedilla */
+ L'È', "E`", /* E grave */
+ L'É', "E'", /* E acute */
+ L'Ê', "E^", /* E circumflex */
+ L'Ë', "E\"", /* E dieresis */
+ L'Ë', "E:", /* E dieresis */
+ L'Ì', "I`", /* I grave */
+ L'Í', "I'", /* I acute */
+ L'Î', "I^", /* I circumflex */
+ L'Ï', "I\"", /* I dieresis */
+ L'Ï', "I:", /* I dieresis */
+ L'Ð', "D-", /* Eth */
+ L'Ñ', "N~", /* N tilde */
+ L'Ò', "O`", /* O grave */
+ L'Ó', "O'", /* O acute */
+ L'Ô', "O^", /* O circumflex */
+ L'Õ', "O~", /* O tilde */
+ L'Ö', "O\"", /* O dieresis */
+ L'Ö', "O:", /* O dieresis */
+ L'Ö', "OE", /* O dieresis */
+ L'Ö', "Oe", /* O dieresis */
+ L'×', "xx", /* times sign */
+ L'Ø', "O/", /* O slash */
+ L'Ù', "U`", /* U grave */
+ L'Ú', "U'", /* U acute */
+ L'Û', "U^", /* U circumflex */
+ L'Ü', "U\"", /* U dieresis */
+ L'Ü', "U:", /* U dieresis */
+ L'Ü', "UE", /* U dieresis */
+ L'Ü', "Ue", /* U dieresis */
+ L'Ý', "Y'", /* Y acute */
+ L'Þ', "P|", /* Thorn */
+ L'Þ', "Th", /* Thorn */
+ L'Þ', "TH", /* Thorn */
+ L'ß', "ss", /* sharp s */
+ L'à', "a`", /* a grave */
+ L'á', "a'", /* a acute */
+ L'â', "a^", /* a circumflex */
+ L'ã', "a~", /* a tilde */
+ L'ä', "a\"", /* a dieresis */
+ L'ä', "a:", /* a dieresis */
+ L'å', "ao", /* a circle */
+ L'æ', "ae", /* ae ligature */
+ L'ç', "c,", /* c cedilla */
+ L'è', "e`", /* e grave */
+ L'é', "e'", /* e acute */
+ L'ê', "e^", /* e circumflex */
+ L'ë', "e\"", /* e dieresis */
+ L'ë', "e:", /* e dieresis */
+ L'ì', "i`", /* i grave */
+ L'í', "i'", /* i acute */
+ L'î', "i^", /* i circumflex */
+ L'ï', "i\"", /* i dieresis */
+ L'ï', "i:", /* i dieresis */
+ L'ð', "d-", /* eth */
+ L'ñ', "n~", /* n tilde */
+ L'ò', "o`", /* o grave */
+ L'ó', "o'", /* o acute */
+ L'ô', "o^", /* o circumflex */
+ L'õ', "o~", /* o tilde */
+ L'ö', "o\"", /* o dieresis */
+ L'ö', "o:", /* o dieresis */
+ L'ö', "oe", /* o dieresis */
+ L'÷', "-:", /* divide sign */
+ L'ø', "o/", /* o slash */
+ L'ù', "u`", /* u grave */
+ L'ú', "u'", /* u acute */
+ L'û', "u^", /* u circumflex */
+ L'ü', "u\"", /* u dieresis */
+ L'ü', "u:", /* u dieresis */
+ L'ü', "ue", /* u dieresis */
+ L'ý', "y'", /* y acute */
+ L'þ', "th", /* thorn */
+ L'þ', "p|", /* thorn */
+ L'ÿ', "y\"", /* y dieresis */
+ L'ÿ', "y:", /* y dieresis */
+ 0, 0,
+};
+
+enum
+{
+ /* controller command byte */
+ Cscs1= (1<<6), /* scan code set 1 */
+ Cmousedis= (1<<5), /* mouse disable */
+ Ckbddis= (1<<4), /* kbd disable */
+ Csf= (1<<2), /* system flag */
+ Cmouseint= (1<<1), /* mouse interrupt enable */
+ Ckbdint= (1<<0), /* kbd interrupt enable */
+};
+
+static uchar ccc;
+
+int
+latin1(int k1, int k2)
+{
+ struct latin *l;
+
+ for(l=latintab; l->l; l++)
+ if(k1==l->c[0] && k2==l->c[1])
+ return l->l;
+ return 0;
+}
+
+/*
+ * wait for output no longer busy
+ */
+static int
+outready(void)
+{
+ int tries;
+
+ for(tries = 0; (inb(Status) & Outbusy); tries++){
+ if(tries > 500)
+ return -1;
+ delay(2);
+ }
+ return 0;
+}
+
+/*
+ * wait for input
+ */
+static int
+inready(void)
+{
+ int tries;
+
+ for(tries = 0; !(inb(Status) & Inready); tries++){
+ if(tries > 500)
+ return -1;
+ delay(2);
+ }
+ return 0;
+}
+
+/*
+ * ask 8042 to enable the use of address bit 20
+ */
+void
+i8042a20(void)
+{
+ outready();
+ outb(Cmd, 0xD1);
+ outready();
+ outb(Data, 0xDF);
+ outready();
+}
+
+/*
+ * ask 8042 to reset the machine
+ */
+void
+i8042reset(void)
+{
+ int i, x;
+#ifdef notdef
+ ushort *s = (ushort*)(KZERO|0x472);
+
+ *s = 0x1234; /* BIOS warm-boot flag */
+#endif /* notdef */
+
+ outready();
+ outb(Cmd, 0xFE); /* pulse reset line (means resend on AT&T machines) */
+ outready();
+
+ /*
+ * Pulse it by hand (old somewhat reliable)
+ */
+ x = 0xDF;
+ for(i = 0; i < 5; i++){
+ x ^= 1;
+ outready();
+ outb(Cmd, 0xD1);
+ outready();
+ outb(Data, x); /* toggle reset */
+ delay(100);
+ }
+}
+
+/*
+ * keyboard interrupt
+ */
+static void
+i8042intr(Ureg*, void*)
+{
+ int s, c;
+ static int esc1, esc2;
+ static int alt, caps, ctl, num, shift;
+ static int lstate, k1, k2;
+ int keyup;
+
+ /*
+ * get status
+ */
+ s = inb(Status);
+ if(!(s&Inready))
+ return;
+
+ /*
+ * get the character
+ */
+ c = inb(Data);
+
+ /*
+ * if it's the aux port...
+ */
+ if(s & Minready)
+ return;
+
+ /*
+ * e0's is the first of a 2 character sequence
+ */
+ if(c == 0xe0){
+ esc1 = 1;
+ return;
+ } else if(c == 0xe1){
+ esc2 = 2;
+ return;
+ }
+
+ keyup = c&0x80;
+ c &= 0x7f;
+ if(c > sizeof kbtab){
+ c |= keyup;
+ if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */
+ print("unknown key %ux\n", c);
+ return;
+ }
+
+ if(esc1){
+ c = kbtabesc1[c];
+ esc1 = 0;
+ } else if(esc2){
+ esc2--;
+ return;
+ } else if(shift)
+ c = kbtabshift[c];
+ else
+ c = kbtab[c];
+
+ if(caps && c<='z' && c>='a')
+ c += 'A' - 'a';
+
+ /*
+ * keyup only important for shifts
+ */
+ if(keyup){
+ switch(c){
+ case Latin:
+ alt = 0;
+ break;
+ case Shift:
+ shift = 0;
+ break;
+ case Ctrl:
+ ctl = 0;
+ break;
+ }
+ return;
+ }
+
+ /*
+ * normal character
+ */
+ if(!(c & Spec)){
+ if(ctl){
+ if(alt && c == Del)
+ warp86("\nCtrl-Alt-Del\n", 0);
+ c &= 0x1f;
+ }
+ switch(lstate){
+ case 1:
+ k1 = c;
+ lstate = 2;
+ return;
+ case 2:
+ k2 = c;
+ lstate = 0;
+ c = latin1(k1, k2);
+ if(c == 0){
+ kbdchar(k1);
+ c = k2;
+ }
+ /* fall through */
+ default:
+ break;
+ }
+ } else {
+ switch(c){
+ case Caps:
+ caps ^= 1;
+ return;
+ case Num:
+ num ^= 1;
+ return;
+ case Shift:
+ shift = 1;
+ return;
+ case Latin:
+ alt = 1;
+ lstate = 1;
+ return;
+ case Ctrl:
+ ctl = 1;
+ return;
+ }
+ }
+ kbdchar(c);
+}
+
+static char *initfailed = "kbd init failed\n";
+
+void
+i8042init(void)
+{
+ int c;
+
+ /* wait for a quiescent controller */
+ while((c = inb(Status)) & (Outbusy | Inready))
+ if(c & Inready)
+ inb(Data);
+
+ /* get current controller command byte */
+ outb(Cmd, 0x20);
+ if(inready() < 0){
+ print("kbdinit: can't read ccc\n");
+ ccc = 0;
+ } else
+ ccc = inb(Data);
+
+ /* enable kbd xfers and interrupts */
+ ccc &= ~Ckbddis;
+ ccc |= Csf | Ckbdint | Cscs1;
+ if(outready() < 0)
+ print(initfailed);
+ outb(Cmd, 0x60);
+ if(outready() < 0)
+ print(initfailed);
+ outb(Data, ccc);
+ if(outready() < 0)
+ print(initfailed);
+
+ setvec(VectorKBD, i8042intr, 0);
+}
--- /dev/null
+++ b/os/boot.original/pc/kfs.h
@@ -1,0 +1,57 @@
+typedef struct Qid9p1 Qid9p1;
+typedef struct Dentry Dentry;
+typedef struct Kfsfile Kfsfile;
+typedef struct Kfs Kfs;
+
+/* DONT TOUCH, this is the disk structure */
+struct Qid9p1
+{
+ long path;
+ long version;
+};
+
+//#define NAMELEN 28 /* size of names */
+#define NDBLOCK 6 /* number of direct blocks in Dentry */
+
+/* DONT TOUCH, this is the disk structure */
+struct Dentry
+{
+ char name[NAMELEN];
+ short uid;
+ short gid;
+ ushort mode;
+/*
+ #define DALLOC 0x8000
+ #define DDIR 0x4000
+ #define DAPND 0x2000
+ #define DLOCK 0x1000
+ #define DREAD 0x4
+ #define DWRITE 0x2
+ #define DEXEC 0x1
+*/
+ Qid9p1 qid;
+ long size;
+ long dblock[NDBLOCK];
+ long iblock;
+ long diblock;
+ long atime;
+ long mtime;
+};
+
+struct Kfsfile
+{
+ Dentry;
+ long off;
+};
+
+struct Kfs
+{
+ int RBUFSIZE;
+ int BUFSIZE;
+ int DIRPERBUF;
+ int INDPERBUF;
+ int INDPERBUF2;
+};
+
+extern int kfsinit(Fs*);
+
--- /dev/null
+++ b/os/boot.original/pc/kfsboot.c
@@ -1,0 +1,256 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "fs.h"
+
+typedef struct Tag Tag;
+
+/*
+ * tags on block
+ */
+enum
+{
+ Tnone = 0,
+ Tsuper, /* the super block */
+ Tdir, /* directory contents */
+ Tind1, /* points to blocks */
+ Tind2, /* points to Tind1 */
+ Tfile, /* file contents */
+ Tfree, /* in free list */
+ Tbuck, /* cache fs bucket */
+ Tvirgo, /* fake worm virgin bits */
+ Tcache, /* cw cache things */
+ MAXTAG
+};
+
+#define QPDIR 0x80000000L
+#define QPNONE 0
+#define QPROOT 1
+#define QPSUPER 2
+
+/* DONT TOUCH, this is the disk structure */
+struct Tag
+{
+ short pad;
+ short tag;
+ long path;
+};
+
+static int thisblock = -1;
+static Fs *thisfs;
+static uchar *block;
+
+/*
+ * we end up reading 2x or 3x the number of blocks we need to read.
+ * this is okay because we need to read so few. if it wasn't okay, we could
+ * have getblock return a pointer to a block, and keep a cache of the last
+ * three read blocks. that would get us down to the minimum.
+ * but this is fine.
+ */
+static int
+getblock(Fs *fs, ulong n)
+{
+ if(!block)
+ block = malloc(16384);
+
+ if(thisblock == n && thisfs == fs)
+ return 0;
+ thisblock = -1;
+ if(fs->diskseek(fs, (vlong)n*fs->kfs.RBUFSIZE) < 0)
+ return -1;
+ if(fs->diskread(fs, block, fs->kfs.RBUFSIZE) != fs->kfs.RBUFSIZE)
+ return -1;
+ thisblock = n;
+ thisfs = fs;
+
+ return 1;
+}
+
+static int
+checktag(Fs *fs, uchar *block, int tag, long qpath)
+{
+ Tag *t;
+
+ t = (Tag*)(block+fs->kfs.BUFSIZE);
+ if(t->tag != tag)
+ return -1;
+ if(qpath != QPNONE && (qpath&~QPDIR) != t->path)
+ return -1;
+ return 1;
+}
+
+static int
+getblocktag(Fs *fs, ulong n, int tag, long qpath)
+{
+ if(getblock(fs, n) < 0 || checktag(fs, block, tag, qpath) < 0)
+ return -1;
+ return 1;
+}
+
+static int
+readinfo(Fs *fs)
+{
+ fs->kfs.RBUFSIZE = 512;
+ if(getblock(fs, 0) < 0)
+ return -1;
+
+ if(memcmp(block+256, "kfs wren device\n", 16) != 0)
+ return -1;
+
+ fs->kfs.RBUFSIZE = atoi((char*)block+256+16);
+ if(!fs->kfs.RBUFSIZE || (fs->kfs.RBUFSIZE&(fs->kfs.RBUFSIZE-1)))
+ return -1;
+
+ fs->kfs.BUFSIZE = fs->kfs.RBUFSIZE - sizeof(Tag);
+ fs->kfs.DIRPERBUF = fs->kfs.BUFSIZE / sizeof(Dentry);
+ fs->kfs.INDPERBUF = fs->kfs.BUFSIZE / sizeof(long);
+ fs->kfs.INDPERBUF2 = fs->kfs.INDPERBUF * fs->kfs.INDPERBUF;
+
+ return 1;
+}
+
+static int
+readroot(Fs *fs, Dentry *d)
+{
+ Dentry *d2;
+
+ if(getblocktag(fs, 2, Tdir, QPROOT) < 0)
+ return -1;
+ d2 = (Dentry*)block;
+ if(strcmp(d2->name, "/") != 0)
+ return -1;
+ *d = *(Dentry*)block;
+ return 1;
+}
+
+static long
+indfetch(Fs *fs, long addr, long off, int tag, long path)
+{
+ if(getblocktag(fs, addr, tag, path) < 0)
+ return -1;
+ return ((long*)block)[off];
+}
+
+static long
+rel2abs(Fs *fs, Dentry *d, long a)
+{
+ long addr;
+
+ if(a < NDBLOCK)
+ return d->dblock[a];
+ a -= NDBLOCK;
+ if(a < fs->kfs.INDPERBUF){
+ if(d->iblock == 0)
+ return 0;
+ addr = indfetch(fs, d->iblock, a, Tind1, d->qid.path);
+ if(addr == 0)
+ print("rel2abs indfetch 0 %s %ld\n", d->name, a);
+ return addr;
+ }
+ a -= fs->kfs.INDPERBUF;
+ if(a < fs->kfs.INDPERBUF2){
+ if(d->diblock == 0)
+ return 0;
+ addr = indfetch(fs, d->diblock, a/fs->kfs.INDPERBUF, Tind2, d->qid.path);
+ if(addr == 0){
+ print("rel2abs indfetch 0 %s %ld\n", d->name, a/fs->kfs.INDPERBUF);
+ return 0;
+ }
+ addr = indfetch(fs, addr, a%fs->kfs.INDPERBUF, Tind1, d->qid.path);
+ return addr;
+ }
+ print("rel2abs trip ind %s %ld\n", d->name, a);
+ return -1;
+}
+
+static int
+readdentry(Fs *fs, Dentry *d, int n, Dentry *e)
+{
+ long addr, m;
+
+ m = n/fs->kfs.DIRPERBUF;
+ if((addr = rel2abs(fs, d, m)) <= 0)
+ return addr;
+ if(getblocktag(fs, addr, Tdir, d->qid.path) < 0)
+ return -1;
+ *e = *(Dentry*)(block+(n%fs->kfs.DIRPERBUF)*sizeof(Dentry));
+ return 1;
+}
+
+static int
+getdatablock(Fs *fs, Dentry *d, long a)
+{
+ long addr;
+
+ if((addr = rel2abs(fs, d, a)) == 0)
+ return -1;
+ return getblocktag(fs, addr, Tfile, QPNONE);
+}
+
+static int
+walk(Fs *fs, Dentry *d, char *name, Dentry *e)
+{
+ int i, n;
+ Dentry x;
+
+ for(i=0;; i++){
+ if((n=readdentry(fs, d, i, &x)) <= 0)
+ return n;
+ if(strcmp(x.name, name) == 0){
+ *e = x;
+ return 1;
+ }
+ }
+}
+
+static long
+kfsread(File *f, void *va, long len)
+{
+ uchar *a;
+ long tot, off, o, n;
+ Fs *fs;
+
+ a = va;
+ fs = f->fs;
+ off = f->kfs.off;
+ tot = 0;
+ while(tot < len){
+ if(getdatablock(fs, &f->kfs, off/fs->kfs.BUFSIZE) < 0)
+ return -1;
+ o = off%fs->kfs.BUFSIZE;
+ n = fs->kfs.BUFSIZE - o;
+ if(n > len-tot)
+ n = len-tot;
+ memmove(a+tot, block+o, n);
+ off += n;
+ tot += n;
+ }
+ f->kfs.off = off;
+ return tot;
+}
+
+static int
+kfswalk(File *f, char *name)
+{
+ int n;
+
+ n = walk(f->fs, &f->kfs, name, &f->kfs);
+ if(n < 0)
+ return -1;
+ f->kfs.off = 0;
+ return 1;
+}
+
+int
+kfsinit(Fs *fs)
+{
+ if(readinfo(fs) < 0 || readroot(fs, &fs->root.kfs) < 0)
+ return -1;
+
+ fs->root.fs = fs;
+ fs->read = kfsread;
+ fs->walk = kfswalk;
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/pc/l.s
@@ -1,0 +1,1084 @@
+#include "x16.h"
+#include "mem.h"
+
+#define WRMSR BYTE $0x0F; BYTE $0x30 /* WRMSR, argument in AX/DX (lo/hi) */
+#define RDTSC BYTE $0x0F; BYTE $0x31 /* RDTSC, result in AX/DX (lo/hi) */
+#define RDMSR BYTE $0x0F; BYTE $0x32 /* RDMSR, result in AX/DX (lo/hi) */
+
+#ifdef PXE
+#define PDB 0x90000 /* temporary page tables (24KB) */
+#else
+#define PDB 0x08000
+#endif PXE
+
+#define NoScreenBlank 1
+/*#define ResetDiscs 1*/
+
+TEXT origin(SB), $0
+ /*
+ * This part of l.s is used only in the boot kernel.
+ * It assumes that we are in real address mode, i.e.,
+ * that we look like an 8086.
+ *
+ * Make sure the segments are reasonable.
+ * If we were started directly from the BIOS
+ * (i.e. no MS-DOS) then DS may not be
+ * right.
+ */
+ MOVW CS, AX
+ MOVW AX, DS
+
+#ifdef NoScreenBlank
+ /*
+ * Get the current video mode. If it isn't mode 3,
+ * set text mode 3.
+ * Well, no. Windows95 won't co-operate here so we have
+ * to explicitly set mode 3.
+ */
+ XORL AX, AX
+ MOVB $0x0F, AH
+ INT $0x10 /* get current video mode in AL */
+ CMPB AL, $03
+ JEQ sayhello
+#endif /* NoScreenBlank */
+ XORL AX, AX
+ MOVB $0x03, AL
+ INT $0x10 /* set video mode in AL */
+
+sayhello:
+ LWI(hello(SB), rSI)
+ CALL16(biosputs(SB))
+
+#ifdef ResetDiscs
+ XORL AX, AX /* reset disc system */
+ XORL DX, DX
+ MOVB $0x80, DL
+ INT $0x13
+#endif /* ResetDiscs */
+
+#ifdef DOTCOM
+/*
+ * relocate everything to a half meg and jump there
+ * - looks weird because it is being assembled by a 32 bit
+ * assembler for a 16 bit world
+ *
+ * only b.com does this - not 9load
+ */
+ MOVL $0,BX
+ INCL BX
+ SHLL $15,BX
+ MOVL BX,CX
+ MOVW BX,ES
+ MOVL $0,SI
+ MOVL SI,DI
+ CLD
+ REP
+ MOVSL
+
+ /*
+ * Jump to the copied image;
+ * fix up the DS for the new location.
+ */
+ FARJUMP16(0x8000, _start8000(SB))
+
+TEXT _start8000(SB), $0
+ MFSR(rCS, rAX) /* fix up DS, ES (0x8000) */
+ MTSR(rAX, rDS)
+ MTSR(rAX, rES)
+
+ /*
+ * If we are already in protected mode, have to get back
+ * to real mode before trying any privileged operations
+ * (like going into protected mode...).
+ * Try to reset with a restart vector.
+ */
+ MFCR(rCR0, rAX) /* are we in protected mode? */
+ ANDI(0x0001, rAX)
+ JEQ _real
+
+ CLR(rBX)
+ MTSR(rBX, rES)
+
+ LWI(0x0467, rBX) /* reset entry point */
+ LWI(_start8000(SB), rAX) /* offset within segment */
+ BYTE $0x26
+ BYTE $0x89
+ BYTE $0x07 /* MOVW AX, ES:[BX] */
+ LBI(0x69, rBL)
+ MFSR(rCS, rAX) /* segment */
+ BYTE $0x26
+ BYTE $0x89
+ BYTE $0x07 /* MOVW AX, ES:[BX] */
+
+ CLR(rDX)
+ OUTPORTB(0x70, 0x8F)
+ OUTPORTB(0x71, 0x0A)
+
+ FARJUMP16(0xFFFF, 0x0000) /* reset */
+#endif /* DOTCOM */
+
+_real:
+
+/*
+ * do things that need to be done in real mode.
+ * the results get written to CONFADDR (0x1200)
+ * in a series of <4-byte-magic-number><block-of-data>
+ * the data length is dependent on the magic number.
+ *
+ * this gets parsed by conf.c:/^readlsconf
+ *
+ * N.B. CALL16 kills rDI, so we can't call anything.
+ */
+ LWI(0x0000, rAX)
+ MTSR(rAX, rES)
+ LWI(0x1200, rDI)
+
+/*
+ * turn off interrupts
+ */
+ CLI
+
+/*
+ * detect APM1.2 bios support
+ */
+ /* save DI */
+ SW(rDI, rock(SB))
+
+ /* disconnect anyone else */
+ LWI(0x5304, rAX)
+ LWI(0x0000, rBX)
+ INT $0x15
+
+ /* connect */
+ CLC
+ LWI(0x5303, rAX)
+ LWI(0x0000, rBX)
+ INT $0x15
+ CLI /* apm put interrupts back? */
+
+ JC noapm
+
+ OPSIZE; PUSHR(rSI)
+ OPSIZE; PUSHR(rBX)
+ PUSHR(rDI)
+ PUSHR(rDX)
+ PUSHR(rCX)
+ PUSHR(rAX)
+
+ /* put DI, ES back */
+ LW(rock(SB), rDI)
+ LWI(0x0000, rAX)
+ MTSR(rAX, rES)
+
+ /*
+ * write APM data. first four bytes are APM\0.
+ */
+ LWI(0x5041, rAX)
+ STOSW
+
+ LWI(0x004d, rAX)
+ STOSW
+
+ LWI(8, rCX)
+apmmove:
+ POPR(rAX)
+ STOSW
+ LOOP apmmove
+
+noapm:
+
+/*
+ * end of real mode hacks: write terminator, put ES back.
+ */
+ LWI(0x0000, rAX)
+ STOSW
+ STOSW
+
+ MFSR(rCS, rAX) /* fix up ES (0x8000) */
+ MTSR(rAX, rES)
+
+/*
+ * goto protected mode
+ */
+/* MOVL tgdtptr(SB),GDTR /**/
+ BYTE $0x0f
+ BYTE $0x01
+ BYTE $0x16
+ WORD $tgdtptr(SB)
+
+ LWI(1, rAX)
+ /* MOV AX,MSW */
+ BYTE $0x0F; BYTE $0x01; BYTE $0xF0
+
+/*
+ * clear prefetch queue (weird code to avoid optimizations)
+ */
+ /* JMP .+2 */
+ BYTE $0xEB
+ BYTE $0x00
+
+/*
+ * set all segs
+ */
+/* MOVW $SELECTOR(1, SELGDT, 0),AX /**/
+ BYTE $0xc7
+ BYTE $0xc0
+ WORD $SELECTOR(1, SELGDT, 0)
+ MOVW AX,DS
+ MOVW AX,SS
+ MOVW AX,ES
+ MOVW AX,FS
+ MOVW AX,GS
+
+/* JMPFAR SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
+ BYTE $0x66
+ BYTE $0xEA
+ LONG $mode32bit-KZERO(SB)
+ WORD $SELECTOR(2, SELGDT, 0)
+
+TEXT mode32bit(SB),$0
+ /*
+ * make a bottom level page table page that maps the first
+ * 16 meg of physical memory
+ */
+ MOVL $PDB, DI /* clear 6 pages for the tables etc. */
+ XORL AX, AX
+ MOVL $(6*BY2PG), CX
+ SHRL $2, CX
+
+ CLD
+ REP; STOSL
+
+ MOVL $PDB, AX /* phys addr of temporary page table */
+ MOVL $(4*1024),CX /* pte's per page */
+ MOVL $((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
+setpte:
+ MOVL BX,-4(AX)(CX*4)
+ SUBL $(1<<PGSHIFT),BX
+ LOOP setpte
+
+ /*
+ * make a top level page table page that maps the first
+ * 16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
+ */
+ MOVL AX,BX
+ ADDL $(4*BY2PG),AX
+ ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX
+ MOVL BX,0(AX)
+ MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
+ ADDL $BY2PG,BX
+ MOVL BX,4(AX)
+ MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
+ ADDL $BY2PG,BX
+ MOVL BX,8(AX)
+ MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
+ ADDL $BY2PG,BX
+ MOVL BX,12(AX)
+ MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
+
+ /*
+ * point processor to top level page & turn on paging
+ *
+ * this produces the apparently harmless "VMX|F(125):468 Dis 0x0:0x0"
+ * message in the VMware log.
+ */
+ MOVL AX,CR3
+ MOVL CR0,AX
+ ORL $0X80000000,AX
+ MOVL AX,CR0
+
+ /*
+ * use a jump to an absolute location to get the PC into
+ * KZERO.
+ */
+ LEAL tokzero(SB),AX
+ JMP* AX
+
+/*
+ * When we load 9load from DOS, the bootstrap jumps
+ * to the instruction right after `JUMP', which gets
+ * us into kzero.
+ *
+ * The name prevents it from being optimized away.
+ */
+TEXT jumplabel(SB), $0
+ BYTE $'J'; BYTE $'U'; BYTE $'M'; BYTE $'P'
+
+ LEAL tokzero(SB),AX
+ JMP* AX
+
+TEXT tokzero(SB),$0
+ /*
+ * Clear BSS
+ */
+ LEAL edata(SB),SI
+ MOVL SI,DI
+ ADDL $4,DI
+ MOVL $0,AX
+ MOVL AX,(SI)
+ LEAL end(SB),CX
+ SUBL DI,CX
+ SHRL $2,CX
+ CLD
+ REP
+ MOVSL
+
+ /*
+ * stack and mach
+ */
+ MOVL $mach0(SB),SP
+ MOVL SP,m(SB)
+ MOVL $0,0(SP)
+ ADDL $(MACHSIZE-4),SP /* start stack above machine struct */
+
+ CALL main(SB)
+
+loop:
+ JMP loop
+
+GLOBL mach0+0(SB), $MACHSIZE
+GLOBL m(SB), $4
+
+/*
+ * gdt to get us to 32-bit/segmented/unpaged mode
+ */
+TEXT tgdt(SB),$0
+
+ /* null descriptor */
+ LONG $0
+ LONG $0
+
+ /* data segment descriptor for 4 gigabytes (PL 0) */
+ LONG $(0xFFFF)
+ LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
+
+ /* exec segment descriptor for 4 gigabytes (PL 0) */
+ LONG $(0xFFFF)
+ LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
+
+ /* exec segment descriptor for 4 gigabytes (PL 0) 16-bit */
+ LONG $(0xFFFF)
+ LONG $(SEGG|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
+
+/*
+ * pointer to initial gdt
+ */
+TEXT tgdtptr(SB),$0
+ WORD $(4*8)
+ LONG $tgdt-KZERO(SB)
+
+/*
+ * Output a string to the display.
+ * String argument is in rSI.
+ */
+TEXT biosputs(SB), $0
+ PUSHA
+ CLR(rBX)
+_BIOSputs:
+ LODSB
+ ORB(rAL, rAL)
+ JEQ _BIOSputsret
+
+ LBI(0x0E, rAH)
+ BIOSCALL(0x10)
+ JMP _BIOSputs
+
+_BIOSputsret:
+ POPA
+ RET
+
+/*
+ * input a byte
+ */
+TEXT inb(SB),$0
+
+ MOVL p+0(FP),DX
+ XORL AX,AX
+ INB
+ RET
+
+/*
+ * input a short from a port
+ */
+TEXT ins(SB), $0
+
+ MOVL p+0(FP), DX
+ XORL AX, AX
+ OPSIZE; INL
+ RET
+
+/*
+ * input a long from a port
+ */
+TEXT inl(SB), $0
+
+ MOVL p+0(FP), DX
+ XORL AX, AX
+ INL
+ RET
+
+/*
+ * output a byte
+ */
+TEXT outb(SB),$0
+
+ MOVL p+0(FP),DX
+ MOVL b+4(FP),AX
+ OUTB
+ RET
+
+/*
+ * output a short to a port
+ */
+TEXT outs(SB), $0
+ MOVL p+0(FP), DX
+ MOVL s+4(FP), AX
+ OPSIZE; OUTL
+ RET
+
+/*
+ * output a long to a port
+ */
+TEXT outl(SB), $0
+ MOVL p+0(FP), DX
+ MOVL s+4(FP), AX
+ OUTL
+ RET
+
+/*
+ * input a string of bytes from a port
+ */
+TEXT insb(SB),$0
+
+ MOVL p+0(FP),DX
+ MOVL a+4(FP),DI
+ MOVL c+8(FP),CX
+ CLD; REP; INSB
+ RET
+
+/*
+ * input a string of shorts from a port
+ */
+TEXT inss(SB),$0
+ MOVL p+0(FP),DX
+ MOVL a+4(FP),DI
+ MOVL c+8(FP),CX
+ CLD
+ REP; OPSIZE; INSL
+ RET
+
+/*
+ * output a string of bytes to a port
+ */
+TEXT outsb(SB),$0
+
+ MOVL p+0(FP),DX
+ MOVL a+4(FP),SI
+ MOVL c+8(FP),CX
+ CLD; REP; OUTSB
+ RET
+
+/*
+ * output a string of shorts to a port
+ */
+TEXT outss(SB),$0
+ MOVL p+0(FP),DX
+ MOVL a+4(FP),SI
+ MOVL c+8(FP),CX
+ CLD
+ REP; OPSIZE; OUTSL
+ RET
+
+/*
+ * input a string of longs from a port
+ */
+TEXT insl(SB),$0
+
+ MOVL p+0(FP),DX
+ MOVL a+4(FP),DI
+ MOVL c+8(FP),CX
+ CLD; REP; INSL
+ RET
+
+/*
+ * output a string of longs to a port
+ */
+TEXT outsl(SB),$0
+
+ MOVL p+0(FP),DX
+ MOVL a+4(FP),SI
+ MOVL c+8(FP),CX
+ CLD; REP; OUTSL
+ RET
+
+/*
+ * routines to load/read various system registers
+ */
+GLOBL idtptr(SB),$6
+TEXT putidt(SB),$0 /* interrupt descriptor table */
+ MOVL t+0(FP),AX
+ MOVL AX,idtptr+2(SB)
+ MOVL l+4(FP),AX
+ MOVW AX,idtptr(SB)
+ MOVL idtptr(SB),IDTR
+ RET
+
+TEXT putcr3(SB),$0 /* top level page table pointer */
+ MOVL t+0(FP),AX
+ MOVL AX,CR3
+ RET
+
+TEXT getcr0(SB),$0 /* coprocessor bits */
+ MOVL CR0,AX
+ RET
+
+TEXT getcr2(SB),$0 /* fault address */
+ MOVL CR2,AX
+ RET
+
+TEXT getcr3(SB),$0 /* page directory base */
+ MOVL CR3,AX
+ RET
+
+TEXT getcr4(SB), $0 /* CR4 - extensions */
+ MOVL CR4, AX
+ RET
+
+TEXT _cycles(SB), $0 /* time stamp counter */
+ RDTSC
+ MOVL vlong+0(FP), CX /* &vlong */
+ MOVL AX, 0(CX) /* lo */
+ MOVL DX, 4(CX) /* hi */
+ RET
+
+TEXT rdmsr(SB), $0 /* model-specific register */
+ MOVL index+0(FP), CX
+ RDMSR
+ MOVL vlong+4(FP), CX /* &vlong */
+ MOVL AX, 0(CX) /* lo */
+ MOVL DX, 4(CX) /* hi */
+ RET
+
+TEXT wrmsr(SB), $0
+ MOVL index+0(FP), CX
+ MOVL lo+4(FP), AX
+ MOVL hi+8(FP), DX
+ WRMSR
+ RET
+
+TEXT mb386(SB), $0
+ POPL AX /* return PC */
+ PUSHFL
+ PUSHL CS
+ PUSHL AX
+ IRETL
+
+/*
+ * special traps
+ */
+TEXT intr0(SB),$0
+ PUSHL $0
+ PUSHL $0
+ JMP intrcommon
+TEXT intr1(SB),$0
+ PUSHL $0
+ PUSHL $1
+ JMP intrcommon
+TEXT intr2(SB),$0
+ PUSHL $0
+ PUSHL $2
+ JMP intrcommon
+TEXT intr3(SB),$0
+ PUSHL $0
+ PUSHL $3
+ JMP intrcommon
+TEXT intr4(SB),$0
+ PUSHL $0
+ PUSHL $4
+ JMP intrcommon
+TEXT intr5(SB),$0
+ PUSHL $0
+ PUSHL $5
+ JMP intrcommon
+TEXT intr6(SB),$0
+ PUSHL $0
+ PUSHL $6
+ JMP intrcommon
+TEXT intr7(SB),$0
+ PUSHL $0
+ PUSHL $7
+ JMP intrcommon
+TEXT intr8(SB),$0
+ PUSHL $8
+ JMP intrcommon
+TEXT intr9(SB),$0
+ PUSHL $0
+ PUSHL $9
+ JMP intrcommon
+TEXT intr10(SB),$0
+ PUSHL $10
+ JMP intrcommon
+TEXT intr11(SB),$0
+ PUSHL $11
+ JMP intrcommon
+TEXT intr12(SB),$0
+ PUSHL $12
+ JMP intrcommon
+TEXT intr13(SB),$0
+ PUSHL $13
+ JMP intrcommon
+TEXT intr14(SB),$0
+ PUSHL $14
+ JMP intrcommon
+TEXT intr15(SB),$0
+ PUSHL $0
+ PUSHL $15
+ JMP intrcommon
+TEXT intr16(SB),$0
+ PUSHL $0
+ PUSHL $16
+ JMP intrcommon
+TEXT intr24(SB),$0
+ PUSHL $0
+ PUSHL $24
+ JMP intrcommon
+TEXT intr25(SB),$0
+ PUSHL $0
+ PUSHL $25
+ JMP intrcommon
+TEXT intr26(SB),$0
+ PUSHL $0
+ PUSHL $26
+ JMP intrcommon
+TEXT intr27(SB),$0
+ PUSHL $0
+ PUSHL $27
+ JMP intrcommon
+TEXT intr28(SB),$0
+ PUSHL $0
+ PUSHL $28
+ JMP intrcommon
+TEXT intr29(SB),$0
+ PUSHL $0
+ PUSHL $29
+ JMP intrcommon
+TEXT intr30(SB),$0
+ PUSHL $0
+ PUSHL $30
+ JMP intrcommon
+TEXT intr31(SB),$0
+ PUSHL $0
+ PUSHL $31
+ JMP intrcommon
+TEXT intr32(SB),$0
+ PUSHL $0
+ PUSHL $32
+ JMP intrcommon
+TEXT intr33(SB),$0
+ PUSHL $0
+ PUSHL $33
+ JMP intrcommon
+TEXT intr34(SB),$0
+ PUSHL $0
+ PUSHL $34
+ JMP intrcommon
+TEXT intr35(SB),$0
+ PUSHL $0
+ PUSHL $35
+ JMP intrcommon
+TEXT intr36(SB),$0
+ PUSHL $0
+ PUSHL $36
+ JMP intrcommon
+TEXT intr37(SB),$0
+ PUSHL $0
+ PUSHL $37
+ JMP intrcommon
+TEXT intr38(SB),$0
+ PUSHL $0
+ PUSHL $38
+ JMP intrcommon
+TEXT intr39(SB),$0
+ PUSHL $0
+ PUSHL $39
+ JMP intrcommon
+TEXT intr64(SB),$0
+ PUSHL $0
+ PUSHL $64
+ JMP intrcommon
+TEXT intrbad(SB),$0
+ PUSHL $0
+ PUSHL $0x1ff
+ JMP intrcommon
+
+intrcommon:
+ PUSHL DS
+ PUSHL ES
+ PUSHL FS
+ PUSHL GS
+ PUSHAL
+ MOVL $(KDSEL),AX
+ MOVW AX,DS
+ MOVW AX,ES
+ LEAL 0(SP),AX
+ PUSHL AX
+ CALL trap(SB)
+ POPL AX
+ POPAL
+ POPL GS
+ POPL FS
+ POPL ES
+ POPL DS
+ ADDL $8,SP /* error code and trap type */
+ IRETL
+
+
+/*
+ * interrupt level is interrupts on or off
+ */
+TEXT spllo(SB),$0
+ PUSHFL
+ POPL AX
+ STI
+ RET
+
+TEXT splhi(SB),$0
+ PUSHFL
+ POPL AX
+ CLI
+ RET
+
+TEXT splx(SB),$0
+ MOVL s+0(FP),AX
+ PUSHL AX
+ POPFL
+ RET
+
+/*
+ * do nothing whatsoever till interrupt happens
+ */
+TEXT idle(SB),$0
+ HLT
+ RET
+
+/*
+ * Try to determine the CPU type which requires fiddling with EFLAGS.
+ * If the Id bit can be toggled then the CPUID instruciton can be used
+ * to determine CPU identity and features. First have to check if it's
+ * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
+ * toggled then it's an older 486 of some kind.
+ *
+ * cpuid(id[], &ax, &dx);
+ */
+#define CPUID BYTE $0x0F; BYTE $0xA2 /* CPUID, argument in AX */
+TEXT cpuid(SB), $0
+ MOVL $0x240000, AX
+ PUSHL AX
+ POPFL /* set Id|Ac */
+
+ PUSHFL
+ POPL BX /* retrieve value */
+
+ MOVL $0, AX
+ PUSHL AX
+ POPFL /* clear Id|Ac, EFLAGS initialised */
+
+ PUSHFL
+ POPL AX /* retrieve value */
+ XORL BX, AX
+ TESTL $0x040000, AX /* Ac */
+ JZ _cpu386 /* can't set this bit on 386 */
+ TESTL $0x200000, AX /* Id */
+ JZ _cpu486 /* can't toggle this bit on some 486 */
+
+ MOVL $0, AX
+ CPUID
+ MOVL id+0(FP), BP
+ MOVL BX, 0(BP) /* "Genu" "Auth" "Cyri" */
+ MOVL DX, 4(BP) /* "ineI" "enti" "xIns" */
+ MOVL CX, 8(BP) /* "ntel" "cAMD" "tead" */
+
+ MOVL $1, AX
+ CPUID
+ JMP _cpuid
+
+_cpu486:
+ MOVL $0x400, AX
+ MOVL $0, DX
+ JMP _cpuid
+
+_cpu386:
+ MOVL $0x300, AX
+ MOVL $0, DX
+
+_cpuid:
+ MOVL ax+4(FP), BP
+ MOVL AX, 0(BP)
+ MOVL dx+8(FP), BP
+ MOVL DX, 0(BP)
+ RET
+
+
+/*
+ * basic timing loop to determine CPU frequency
+ */
+TEXT aamloop(SB),$0
+
+ MOVL c+0(FP),CX
+aaml1:
+ AAM
+ LOOP aaml1
+ RET
+
+TEXT hello(SB), $0
+ BYTE $'P'; BYTE $'l'; BYTE $'a'; BYTE $'n';
+ BYTE $' '; BYTE $'9'; BYTE $' '; BYTE $'f';
+ BYTE $'r'; BYTE $'o'; BYTE $'m'; BYTE $' ';
+ BYTE $'B'; BYTE $'e'; BYTE $'l'; BYTE $'l';
+ BYTE $' '; BYTE $'L'; BYTE $'a'; BYTE $'b';
+ BYTE $'s';
+#ifdef PXE
+ BYTE $' '; BYTE $'b'; BYTE $'y'; BYTE $' ';
+ BYTE $'P'; BYTE $'X'; BYTE $'E';
+#endif
+ BYTE $'\r';
+ BYTE $'\n';
+ BYTE $'\z';
+
+TEXT rock(SB), $0
+ BYTE $0; BYTE $0; BYTE $0; BYTE $0;
+
+GLOBL pxe(SB), $4
+#ifdef PXE
+DATA pxe+0(SB)/4, $1
+#else
+DATA pxe+0(SB)/4, $0
+#endif /* PXE */
+
+/*
+ * Save registers.
+ */
+TEXT saveregs(SB), $0
+ /* appease 8l */
+ SUBL $32, SP
+ POPL AX
+ POPL AX
+ POPL AX
+ POPL AX
+ POPL AX
+ POPL AX
+ POPL AX
+ POPL AX
+
+ PUSHL AX
+ PUSHL BX
+ PUSHL CX
+ PUSHL DX
+ PUSHL BP
+ PUSHL DI
+ PUSHL SI
+ PUSHFL
+
+ XCHGL 32(SP), AX /* swap return PC and saved flags */
+ XCHGL 0(SP), AX
+ XCHGL 32(SP), AX
+ RET
+
+TEXT restoreregs(SB), $0
+ /* appease 8l */
+ PUSHL AX
+ PUSHL AX
+ PUSHL AX
+ PUSHL AX
+ PUSHL AX
+ PUSHL AX
+ PUSHL AX
+ PUSHL AX
+ ADDL $32, SP
+
+ XCHGL 32(SP), AX /* swap return PC and saved flags */
+ XCHGL 0(SP), AX
+ XCHGL 32(SP), AX
+
+ POPFL
+ POPL SI
+ POPL DI
+ POPL BP
+ POPL DX
+ POPL CX
+ POPL BX
+ POPL AX
+ RET
+
+/*
+ * Assumed to be in protected mode at time of call.
+ * Switch to real mode, execute an interrupt, and
+ * then switch back to protected mode.
+ *
+ * Assumes:
+ *
+ * - no device interrupts are going to come in
+ * - 0-16MB is identity mapped in page tables
+ * - can use code segment 0x1000 in real mode
+ * to get at l.s code
+ */
+TEXT realmodeidtptr(SB), $0
+ WORD $(4*256-1)
+ LONG $0
+
+TEXT realmode0(SB), $0
+ CALL saveregs(SB)
+
+ /* switch to low code address */
+ LEAL physcode-KZERO(SB), AX
+ JMP *AX
+
+TEXT physcode(SB), $0
+
+ /* switch to low stack */
+ MOVL SP, AX
+ MOVL $0x7C00, SP
+ PUSHL AX
+
+ /* load IDT with real-mode version; GDT already fine */
+ MOVL realmodeidtptr(SB), IDTR
+
+ /* edit INT $0x00 instruction below */
+ MOVL realmodeintr(SB), AX
+ MOVB AX, realmodeintrinst+1(SB)
+
+ /* disable paging */
+ MOVL CR0, AX
+ ANDL $0x7FFFFFFF, AX
+ MOVL AX, CR0
+ /* JMP .+2 to clear prefetch queue*/
+ BYTE $0xEB; BYTE $0x00
+
+ /* jump to 16-bit code segment */
+/* JMPFAR SELECTOR(3, SELGDT, 0):$again16bit(SB) /**/
+ BYTE $0xEA
+ LONG $again16bit-KZERO(SB)
+ WORD $SELECTOR(3, SELGDT, 0)
+
+TEXT again16bit(SB), $0
+ /*
+ * Now in 16-bit compatibility mode.
+ * These are 32-bit instructions being interpreted
+ * as 16-bit instructions. I'm being lazy and
+ * not using the macros because I know when
+ * the 16- and 32-bit instructions look the same
+ * or close enough.
+ */
+
+ /* disable protected mode and jump to real mode cs */
+ OPSIZE; MOVL CR0, AX
+ OPSIZE; XORL BX, BX
+ OPSIZE; INCL BX
+ OPSIZE; XORL BX, AX
+ OPSIZE; MOVL AX, CR0
+
+ /* JMPFAR 0x1000:now16real */
+ BYTE $0xEA
+ WORD $now16real-KZERO(SB)
+ WORD $0x1000
+
+TEXT now16real(SB), $0
+ /* copy the registers for the bios call */
+ LWI(0x1000, rAX)
+ MOVW AX,SS
+ LWI(realmoderegs(SB), rBP)
+
+ /* offsets are in Ureg */
+ LXW(44, xBP, rAX)
+ MOVW AX, DS
+ LXW(40, xBP, rAX)
+ MOVW AX, ES
+
+ OPSIZE; LXW(0, xBP, rDI)
+ OPSIZE; LXW(4, xBP, rSI)
+ OPSIZE; LXW(16, xBP, rBX)
+ OPSIZE; LXW(20, xBP, rDX)
+ OPSIZE; LXW(24, xBP, rCX)
+ OPSIZE; LXW(28, xBP, rAX)
+
+ CLC
+
+TEXT realmodeintrinst(SB), $0
+ INT $0x00
+
+
+ /* save the registers after the call */
+
+ LWI(0x7bfc, rSP)
+ OPSIZE; PUSHFL
+ OPSIZE; PUSHL AX
+
+ LWI(0x1000, rAX)
+ MOVW AX,SS
+ LWI(realmoderegs(SB), rBP)
+
+ OPSIZE; SXW(rDI, 0, xBP)
+ OPSIZE; SXW(rSI, 4, xBP)
+ OPSIZE; SXW(rBX, 16, xBP)
+ OPSIZE; SXW(rDX, 20, xBP)
+ OPSIZE; SXW(rCX, 24, xBP)
+ OPSIZE; POPL AX
+ OPSIZE; SXW(rAX, 28, xBP)
+
+ MOVW DS, AX
+ OPSIZE; SXW(rAX, 44, xBP)
+ MOVW ES, AX
+ OPSIZE; SXW(rAX, 40, xBP)
+
+ OPSIZE; POPL AX
+ OPSIZE; SXW(rAX, 64, xBP) /* flags */
+
+ /* re-enter protected mode and jump to 32-bit code */
+ OPSIZE; MOVL $1, AX
+ OPSIZE; MOVL AX, CR0
+
+/* JMPFAR SELECTOR(2, SELGDT, 0):$again32bit(SB) /**/
+ OPSIZE
+ BYTE $0xEA
+ LONG $again32bit-KZERO(SB)
+ WORD $SELECTOR(2, SELGDT, 0)
+
+TEXT again32bit(SB), $0
+ MOVW $SELECTOR(1, SELGDT, 0),AX
+ MOVW AX,DS
+ MOVW AX,SS
+ MOVW AX,ES
+ MOVW AX,FS
+ MOVW AX,GS
+
+ /* enable paging and jump to kzero-address code */
+ MOVL CR0, AX
+ ORL $0x80000000, AX
+ MOVL AX, CR0
+ LEAL again32kzero(SB), AX
+ JMP* AX
+
+TEXT again32kzero(SB), $0
+ /* breathe a sigh of relief - back in 32-bit protected mode */
+
+ /* switch to old stack */
+ PUSHL AX /* match popl below for 8l */
+ MOVL $0x7BFC, SP
+ POPL SP
+
+ /* restore idt */
+ MOVL idtptr(SB),IDTR
+
+ CALL restoreregs(SB)
+ RET
+
+TEXT realmoderegs(SB), $0
+ LONG $0; LONG $0; LONG $0; LONG $0
+ LONG $0; LONG $0; LONG $0; LONG $0
+ LONG $0; LONG $0; LONG $0; LONG $0
+ LONG $0; LONG $0; LONG $0; LONG $0
+ LONG $0; LONG $0; LONG $0; LONG $0
+
+TEXT realmodeintr(SB), $0
+ LONG $0
+
--- /dev/null
+++ b/os/boot.original/pc/lib.h
@@ -1,0 +1,106 @@
+#define offsetof(s, m) (ulong)(&(((s*)0)->m))
+
+/*
+ * functions (possibly) linked in, complete, from libc.
+ */
+
+/*
+ * mem routines
+ */
+extern void* memccpy(void*, void*, int, ulong);
+extern void* memset(void*, int, ulong);
+extern int memcmp(void*, void*, ulong);
+extern void* memmove(void*, void*, ulong);
+extern void* memchr(void*, int, ulong);
+
+/*
+ * string routines
+ */
+extern char* strcat(char*, char*);
+extern char* strchr(char*, int);
+extern int strcmp(char*, char*);
+extern char* strcpy(char*, char*);
+extern char* strncat(char*, char*, long);
+extern char* strncpy(char*, char*, long);
+extern int strncmp(char*, char*, long);
+extern long strlen(char*);
+extern char* strrchr(char*, char);
+extern char* strstr(char*, char*);
+
+
+/*
+ * print routines
+ */
+typedef struct Fmt Fmt;
+typedef int (*Fmts)(Fmt*);
+struct Fmt{
+ uchar runes; /* output buffer is runes or chars? */
+ void *start; /* of buffer */
+ void *to; /* current place in the buffer */
+ void *stop; /* end of the buffer; overwritten if flush fails */
+ int (*flush)(Fmt *); /* called when to == stop */
+ void *farg; /* to make flush a closure */
+ int nfmt; /* num chars formatted so far */
+ va_list args; /* args passed to dofmt */
+ int r; /* % format Rune */
+ int width;
+ int prec;
+ ulong flags;
+};
+extern int print(char*, ...);
+extern char* vseprint(char*, char*, char*, va_list);
+extern int sprint(char*, char*, ...);
+extern int snprint(char*, int, char*, ...);
+extern int fmtinstall(int, int (*)(Fmt*));
+
+#pragma varargck argpos addconf 1
+#pragma varargck argpos fmtprint 2
+#pragma varargck argpos print 1
+#pragma varargck argpos seprint 3
+#pragma varargck argpos snprint 3
+#pragma varargck argpos sprint 2
+#pragma varargck type "H" void*
+
+#pragma varargck type "lld" vlong
+#pragma varargck type "llx" vlong
+#pragma varargck type "lld" uvlong
+#pragma varargck type "llx" uvlong
+#pragma varargck type "ld" long
+#pragma varargck type "lx" long
+#pragma varargck type "ld" ulong
+#pragma varargck type "lx" ulong
+#pragma varargck type "d" int
+#pragma varargck type "x" int
+#pragma varargck type "c" int
+#pragma varargck type "C" int
+#pragma varargck type "d" uint
+#pragma varargck type "x" uint
+#pragma varargck type "c" uint
+#pragma varargck type "C" uint
+#pragma varargck type "f" double
+#pragma varargck type "e" double
+#pragma varargck type "g" double
+#pragma varargck type "s" char*
+#pragma varargck type "q" char*
+#pragma varargck type "S" Rune*
+#pragma varargck type "Q" Rune*
+#pragma varargck type "r" void
+#pragma varargck type "%" void
+#pragma varargck type "|" int
+#pragma varargck type "p" void*
+#pragma varargck type "lux" void*
+#pragma varargck type "E" uchar*
+
+#define PRINTSIZE 256
+
+/*
+ * one-of-a-kind
+ */
+extern int atoi(char*);
+extern uintptr getcallerpc(void*);
+extern long strtol(char*, char**, int);
+extern ulong strtoul(char*, char**, int);
+extern uvlong strtoull(char*, char**, int);
+extern long end;
+
+#define NAMELEN 28
--- /dev/null
+++ b/os/boot.original/pc/load.c
@@ -1,0 +1,627 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "sd.h"
+#include "fs.h"
+
+#ifndef VERBOSE
+#define VERBOSE 0
+#endif
+
+/*
+ * "cache" must be in this list so that 9load will pass the definition of
+ * the cache partition into the kernel so that the disk named by the `cfs'
+ * variable in plan9.ini can be seen in all circumstances before termrc
+ * sets up all the disk partitions. In particular, if it's on an odd-ball
+ * disk like sd10 rather than sdC0, this is needed.
+ */
+static char *diskparts[] = {
+ "dos", "9fat", "fs", "data", "cdboot", "cache", 0
+};
+static char *etherparts[] = { "*", 0 };
+
+static char *diskinis[] = {
+ "plan9/plan9.ini",
+ "plan9.ini",
+ 0
+};
+static char *etherinis[] = {
+ "/cfg/pxe/%E",
+ 0
+};
+
+/* ordering: devbios must be called before devsd calls sdbios */
+Type types[] = {
+ { Tfloppy,
+ Fini|Ffs,
+ floppyinit, floppyinitdev,
+ floppygetfspart, 0, floppyboot,
+ floppyprintdevs,
+ diskparts,
+ diskinis,
+ },
+ { Tether,
+ Fini|Fbootp,
+ etherinit, etherinitdev,
+ pxegetfspart, 0, bootpboot,
+ etherprintdevs,
+ etherparts,
+ etherinis,
+ },
+ { Tbios,
+ Fini|Ffs,
+ biosinit, biosinitdev,
+ biosgetfspart, nil, biosboot,
+ biosprintdevs,
+ diskparts,
+ diskinis,
+ },
+ { Tcd,
+ Fini|Ffs,
+ cdinit, sdinitdev,
+ sdgetfspart, sdaddconf, sdboot,
+ sdprintdevs,
+ diskparts,
+ diskinis,
+ },
+ { Tsd,
+ Fini|Ffs,
+ sdinit, sdinitdev,
+ sdgetfspart, sdaddconf, sdboot,
+ sdprintdevs,
+ diskparts,
+ diskinis,
+ },
+ { Tnil,
+ 0,
+ nil, nil, nil, nil, nil, nil,
+ nil,
+ nil,
+ 0,
+ nil,
+ },
+};
+
+static char *typenm[] = {
+ [Tnil] "nil",
+ [Tfloppy] "floppy",
+ [Tsd] "sd",
+ [Tether] "ether",
+ [Tcd] "cd",
+ [Tbios] "bios",
+};
+
+static char *
+typename(int type)
+{
+ if (type < 0 || type >= nelem(typenm) || typenm[type] == nil)
+ return "**gok**";
+ return typenm[type];
+}
+
+extern SDifc sdataifc;
+extern SDifc sdiahciifc;
+extern SDifc sdaoeifc;
+extern SDifc sdbiosifc;
+
+#ifdef NOSCSI
+
+SDifc* sdifc[] = {
+ &sdataifc,
+ &sdiahciifc,
+ &sdbiosifc,
+ &sdaoeifc,
+ nil,
+};
+
+#else
+
+extern SDifc sdmylexifc;
+extern SDifc sd53c8xxifc;
+
+SDifc* sdifc[] = {
+ &sdataifc,
+ &sdiahciifc,
+ &sdmylexifc,
+ &sd53c8xxifc,
+ &sdbiosifc,
+ &sdaoeifc,
+ nil,
+};
+
+#endif NOSCSI
+
+typedef struct Mode Mode;
+
+enum {
+ Maxdev = 7,
+ Dany = -1,
+ Nmedia = 16,
+ Nini = 10,
+};
+
+enum { /* mode */
+ Mauto = 0x00,
+ Mlocal = 0x01,
+ Manual = 0x02,
+ NMode = 0x03,
+};
+
+typedef struct Medium Medium;
+struct Medium {
+ Type* type;
+ int flag;
+ int dev;
+ char name[NAMELEN];
+
+ Fs *inifs;
+ char *part;
+ char *ini;
+
+ Medium* next;
+};
+
+typedef struct Mode {
+ char* name;
+ int mode;
+} Mode;
+
+static Medium media[Nmedia];
+static Medium *curmedium = media;
+
+static Mode modes[NMode+1] = {
+ [Mauto] { "auto", Mauto, },
+ [Mlocal] { "local", Mlocal, },
+ [Manual] { "manual", Manual, },
+};
+
+char **ini;
+
+int scsi0port;
+char *defaultpartition;
+int iniread;
+
+int debugload;
+
+static Medium*
+parse(char *line, char **file)
+{
+ char *p;
+ Type *tp;
+ Medium *mp;
+
+ if(p = strchr(line, '!')) {
+ *p++ = 0;
+ *file = p;
+ } else
+ *file = "";
+
+ for(tp = types; tp->type != Tnil; tp++)
+ for(mp = tp->media; mp; mp = mp->next)
+ if(strcmp(mp->name, line) == 0)
+ return mp;
+ if(p)
+ *--p = '!';
+ return nil;
+}
+
+static int
+boot(Medium *mp, char *file)
+{
+ Type *tp;
+ Medium *xmp;
+ static int didaddconf;
+ Boot b;
+
+ memset(&b, 0, sizeof b);
+ b.state = INITKERNEL;
+
+ if(didaddconf == 0) {
+ didaddconf = 1;
+ for(tp = types; tp->type != Tnil; tp++)
+ if(tp->addconf)
+ for(xmp = tp->media; xmp; xmp = xmp->next)
+ (*tp->addconf)(xmp->dev);
+ }
+
+ sprint(BOOTLINE, "%s!%s", mp->name, file);
+ print("booting %s!%s\n", mp->name, file);
+ return (*mp->type->boot)(mp->dev, file, &b);
+}
+
+static Medium*
+allocm(Type *tp)
+{
+ Medium **l;
+
+ if(curmedium >= &media[Nmedia])
+ return 0;
+
+ for(l = &tp->media; *l; l = &(*l)->next)
+ ;
+ *l = curmedium++;
+ return *l;
+}
+
+Medium*
+probe(int type, int flag, int dev)
+{
+ Type *tp;
+ int i;
+ Medium *mp;
+ File f;
+ Fs *fs;
+ char **partp;
+
+ for(tp = types; tp->type != Tnil; tp++){
+ if(type != Tany && type != tp->type)
+ continue;
+
+ if(flag != Fnone){
+ for(mp = tp->media; mp; mp = mp->next){
+ if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
+ return mp;
+ }
+ }
+ if (debugload)
+ print("probing %s...", typename(tp->type));
+ if((tp->flag & Fprobe) == 0){
+ tp->flag |= Fprobe;
+ tp->mask = (*tp->init)();
+ }
+
+ for(i = 0; tp->mask; i++){
+ if((tp->mask & (1<<i)) == 0)
+ continue;
+ tp->mask &= ~(1<<i);
+
+ if((mp = allocm(tp)) == 0)
+ continue;
+
+ mp->dev = i;
+ mp->flag = tp->flag;
+ mp->type = tp;
+ (*tp->initdev)(i, mp->name);
+
+ if(mp->flag & Fini){
+ mp->flag &= ~Fini;
+ for(partp = tp->parts; *partp; partp++){
+ if((fs = (*tp->getfspart)(i, *partp, 0)) == nil)
+ continue;
+
+ for(ini = tp->inis; *ini; ini++){
+ if(fswalk(fs, *ini, &f) > 0){
+ mp->inifs = fs;
+ mp->part = *partp;
+ mp->ini = f.path;
+ mp->flag |= Fini;
+ goto Break2;
+ }
+ }
+ }
+ }
+ Break2:
+ if((flag & mp->flag) && (dev == Dany || dev == i))
+ return mp;
+ }
+ }
+
+ return 0;
+}
+
+void
+main(void)
+{
+ Medium *mp;
+ int flag, i, mode, tried;
+ char def[2*NAMELEN], line[80], *p, *file;
+ Type *tp;
+
+ i8042a20();
+ memset(m, 0, sizeof(Mach));
+ trapinit();
+ clockinit();
+ alarminit();
+ meminit(0);
+ spllo();
+ consinit("0", "9600");
+ kbdinit();
+ if((ulong)&end > (KZERO|(640*1024)))
+ panic("i'm too big\n");
+
+ readlsconf();
+ print("initial probe, to find plan9.ini...");
+ /* find and read plan9.ini, setting configuration variables */
+ for(tp = types; tp->type != Tnil; tp++){
+ /* skip bios until we have read plan9.ini */
+ if(!pxe && tp->type == Tether || tp->type == Tbios)
+ continue;
+ if (VERBOSE)
+ print("probing %s...", typename(tp->type));
+ if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
+ print("using %s!%s!%s\n", mp->name, mp->part, mp->ini);
+ iniread = !dotini(mp->inifs);
+ break;
+ }
+ }
+ print("\n");
+ apminit();
+
+ debugload = getconf("*debugload") != nil;
+ if((p = getconf("console")) != nil)
+ consinit(p, getconf("baud"));
+
+ devpccardlink();
+ devi82365link();
+
+ /*
+ * Even after we find the ini file, we keep probing disks,
+ * because we have to collect the partition tables and
+ * have boot devices for parse.
+ */
+ probe(Tany, Fnone, Dany);
+ if (debugload)
+ print("end disk probe\n");
+ tried = 0;
+ mode = Mauto;
+
+ p = getconf("bootfile");
+
+ if(p != 0) {
+ mode = Manual;
+ for(i = 0; i < NMode; i++){
+ if(strcmp(p, modes[i].name) == 0){
+ mode = modes[i].mode;
+ goto done;
+ }
+ }
+ if((mp = parse(p, &file)) == nil) {
+ print("Unknown boot device: %s\n", p);
+ goto done;
+ }
+ tried = boot(mp, file);
+ }
+done:
+ if(tried == 0 && mode != Manual){
+ flag = Fany;
+ if(mode == Mlocal)
+ flag &= ~Fbootp;
+ if((mp = probe(Tany, flag, Dany)) && mp->type->type != Tfloppy)
+ boot(mp, "");
+ if (debugload)
+ print("end auto probe\n");
+ }
+
+ def[0] = 0;
+ probe(Tany, Fnone, Dany);
+ if (debugload)
+ print("end final probe\n");
+ if(p = getconf("bootdef"))
+ strcpy(def, p);
+
+ flag = 0;
+ for(tp = types; tp->type != Tnil; tp++){
+ for(mp = tp->media; mp; mp = mp->next){
+ if(flag == 0){
+ flag = 1;
+ print("Boot devices:");
+ }
+ (*tp->printdevs)(mp->dev);
+ }
+ }
+ if(flag)
+ print("\n");
+
+ for(;;){
+ if(getstr("boot from", line, sizeof(line), def, (mode != Manual)*15) >= 0)
+ if(mp = parse(line, &file))
+ boot(mp, file);
+ def[0] = 0;
+ }
+}
+
+int
+getfields(char *lp, char **fields, int n, char sep)
+{
+ int i;
+
+ for(i = 0; lp && *lp && i < n; i++){
+ while(*lp == sep)
+ *lp++ = 0;
+ if(*lp == 0)
+ break;
+ fields[i] = lp;
+ while(*lp && *lp != sep){
+ if(*lp == '\\' && *(lp+1) == '\n')
+ *lp++ = ' ';
+ lp++;
+ }
+ }
+ return i;
+}
+
+int
+cistrcmp(char *a, char *b)
+{
+ int ac, bc;
+
+ for(;;){
+ ac = *a++;
+ bc = *b++;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+ return 0;
+}
+
+int
+cistrncmp(char *a, char *b, int n)
+{
+ unsigned ac, bc;
+
+ while(n > 0){
+ ac = *a++;
+ bc = *b++;
+ n--;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+
+ return 0;
+}
+
+#define PSTART ( 8*1024*1024)
+#define PEND (16*1024*1024)
+
+ulong palloc = PSTART;
+
+void*
+ialloc(ulong n, int align)
+{
+ ulong p;
+ int a;
+
+ p = palloc;
+ if(align <= 0)
+ align = 4;
+ if(a = n % align)
+ n += align - a;
+ if(a = p % align)
+ p += align - a;
+
+
+ palloc = p+n;
+ if(palloc > PEND)
+ panic("ialloc(%lud, %d) called from %#p\n",
+ n, align, getcallerpc(&n));
+ return memset((void*)(p|KZERO), 0, n);
+}
+
+void*
+xspanalloc(ulong size, int align, ulong span)
+{
+ ulong a, v;
+
+ if((palloc + (size+align+span)) > PEND)
+ panic("xspanalloc(%lud, %d, 0x%lux) called from %#p\n",
+ size, align, span, getcallerpc(&size));
+
+ a = (ulong)ialloc(size+align+span, 0);
+
+ if(span > 2)
+ v = (a + span) & ~(span-1);
+ else
+ v = a;
+
+ if(align > 1)
+ v = (v + align) & ~(align-1);
+
+ return (void*)v;
+}
+
+static Block *allocbp;
+
+Block*
+allocb(int size)
+{
+ Block *bp, **lbp;
+ ulong addr;
+
+ lbp = &allocbp;
+ for(bp = *lbp; bp; bp = bp->next){
+ if((bp->lim - bp->base) >= size){
+ *lbp = bp->next;
+ break;
+ }
+ lbp = &bp->next;
+ }
+ if(bp == 0){
+ if((palloc + (sizeof(Block)+size+64)) > PEND)
+ panic("allocb(%d) called from %#p\n",
+ size, getcallerpc(&size));
+ bp = ialloc(sizeof(Block)+size+64, 0);
+ addr = (ulong)bp;
+ addr = ROUNDUP(addr + sizeof(Block), 8);
+ bp->base = (uchar*)addr;
+ bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
+ }
+
+ if(bp->flag)
+ panic("allocb reuse\n");
+
+ bp->rp = bp->base;
+ bp->wp = bp->rp;
+ bp->next = 0;
+ bp->flag = 1;
+
+ return bp;
+}
+
+void
+freeb(Block* bp)
+{
+ bp->next = allocbp;
+ allocbp = bp;
+
+ bp->flag = 0;
+}
+
+enum {
+ Paddr= 0x70, /* address port */
+ Pdata= 0x71, /* data port */
+};
+
+uchar
+nvramread(int offset)
+{
+ outb(Paddr, offset);
+ return inb(Pdata);
+}
+
+void (*etherdetach)(void);
+void (*floppydetach)(void);
+void (*sddetach)(void);
+
+void
+warp9(ulong entry)
+{
+ if(etherdetach)
+ etherdetach();
+ if(floppydetach)
+ floppydetach();
+ if(sddetach)
+ sddetach();
+ consdrain();
+
+ splhi();
+ trapdisable();
+
+ /*
+ * This is where to push things on the stack to
+ * boot *BSD systems, e.g.
+ (*(void(*)(void*, void*, void*, void*, ulong, ulong))(PADDR(entry)))(0, 0, 0, 0, 8196, 640);
+ * will enable NetBSD boot (the real memory size needs to
+ * go in the 5th argument).
+ */
+ (*(void(*)(void))(PADDR(entry)))();
+}
--- /dev/null
+++ b/os/boot.original/pc/mbr.s
@@ -1,0 +1,259 @@
+/*
+ * Hard disc boot block. Loaded at 0x7C00, relocates to 0x0600:
+ * 8a mbr.s; 8l -o mbr -l -H3 -T0x0600 mbr.8
+ */
+#include "x16.h"
+#include "mem.h"
+
+/*#define FLOPPY 1 /* test on a floppy */
+#define TRACE(C) PUSHA;\
+ CLR(rBX);\
+ MOVB $C, AL;\
+ LBI(0x0E, rAH);\
+ BIOSCALL(0x10);\
+ POPA
+
+/*
+ * We keep data on the stack, indexed by BP.
+ */
+#define Xdap 0x00 /* disc address packet */
+#define Xtable 0x10 /* partition table entry */
+#define Xdrive 0x12 /* starting disc */
+#define Xtotal 0x14 /* sum of allocated data above */
+
+/*
+ * Start: loaded at 0000:7C00, relocate to 0000:0600.
+ * Boot drive is in rDL.
+ */
+TEXT _start(SB), $0
+ CLI
+ CLR(rAX)
+ MTSR(rAX, rSS) /* 0000 -> rSS */
+ LWI((0x7C00-Xtotal), rSP) /* 7Bxx -> rSP */
+ MW(rSP, rBP) /* set the indexed-data pointer */
+
+ MTSR(rAX, rDS) /* 0000 -> rDS, source segment */
+ LWI(0x7C00, rSI) /* 7C00 -> rSI, source offset */
+ MTSR(rAX, rES) /* 0000 -> rES, destination segment */
+ LWI(0x600, rDI) /* 0600 -> rDI, destination offset */
+ LWI(0x100, rCX) /* 0100 -> rCX, loop count (words) */
+
+ CLD
+ REP; MOVSL /* MOV DS:[(E)SI] -> ES:[(E)DI] */
+
+ FARJUMP16(0x0000, _start0600(SB))
+
+TEXT _start0600(SB), $0
+#ifdef FLOPPY
+ LBI(0x80, rDL)
+#else
+ CLRB(rAL) /* some systems pass 0 */
+ CMPBR(rAL, rDL)
+ JNE _save
+ LBI(0x80, rDL)
+#endif /* FLOPPY */
+_save:
+ SXB(rDL, Xdrive, xBP) /* save disc */
+
+ LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
+ CALL16(BIOSputs(SB))
+
+ LWI(_start+0x01BE(SB), rSI) /* address of partition table */
+ LWI(0x04, rCX) /* 4 entries in table */
+ LBI(0x80, rAH) /* active entry value */
+ CLRB(rAL) /* inactive entry value */
+
+_activeloop0:
+ LXB(0x00, xSI, rBL) /* get active entry from table */
+ CMPBR(rBL, rAH) /* is this an active entry? */
+ JEQ _active
+
+ CMPBR(rBL, rAL) /* if not active it should be 0 */
+ JNE _invalidMBR
+
+ ADDI(0x10, rSI) /* next table entry */
+ DEC(rCX)
+ JNE _activeloop0
+
+ LWI(noentry(SB), rSI)
+ CALL16(buggery(SB))
+
+_active:
+ MW(rSI, rDI) /* save table address */
+
+_activeloop1:
+ ADDI(0x10, rSI) /* next table entry */
+ DEC(rCX)
+ JEQ _readsector
+
+ LXB(0x00, xSI, rBL) /* get active entry from table */
+ CMPBR(rBL, rAH) /* is this an active entry? */
+ JNE _activeloop1 /* should only be one active */
+
+_invalidMBR:
+ LWI(invalidMBR(SB), rSI)
+ CALL16(buggery(SB))
+
+_readsector:
+ LBI(0x41, rAH) /* check extensions present */
+ LWI(0x55AA, rBX)
+ LXB(Xdrive, xBP, rDL) /* drive */
+ BIOSCALL(0x13) /* CF set on failure */
+ JCS _readsector2
+ CMPI(0xAA55, rBX)
+ JNE _readsector2
+ ANDI(0x0001, rCX)
+ JEQ _readsector2
+
+_readsector42:
+ SBPBI(0x10, Xdap+0) /* packet size */
+ SBPBI(0x00, Xdap+1) /* reserved */
+ SBPBI(0x01, Xdap+2) /* number of blocks to transfer */
+ SBPBI(0x00, Xdap+3) /* reserved */
+ SBPWI(0x7C00, Xdap+4) /* transfer buffer :offset */
+ SBPWI(0x0000, Xdap+6) /* transfer buffer seg: */
+ LXW(0x08, xDI, rAX) /* LBA (64-bits) */
+ SBPW(rAX, Xdap+8)
+ LXW(0x0A, xDI, rAX)
+ SBPW(rAX, Xdap+10)
+ SBPWI(0x0000, Xdap+12)
+ SBPWI(0x0000, Xdap+14)
+
+ MW(rBP, rSI) /* disk address packet */
+ LBI(0x42, rAH) /* extended read */
+ BIOSCALL(0x13) /* CF set on failure */
+ JCC _readsectorok
+
+ LWI(ioerror(SB), rSI)
+ CALL16(buggery(SB))
+
+/*
+ * Read a sector from a disc using the traditional BIOS call.
+ * For BIOSCALL(0x13/AH=0x02):
+ * rAH 0x02
+ * rAL number of sectors to read (1)
+ * rCH low 8 bits of cylinder
+ * rCL high 2 bits of cylinder (7-6), sector (5-0)
+ * rDH head
+ * rDL drive
+ * rES:rBX buffer address
+ */
+_readsector2:
+ LXB(0x01, xDI, rDH) /* head */
+ LXW(0x02, xDI, rCX) /* save active cylinder/sector */
+
+ LWI(0x0201, rAX) /* read one sector */
+ LXB(Xdrive, xBP, rDL) /* drive */
+ LWI(0x7C00, rBX) /* buffer address (rES already OK) */
+ BIOSCALL(0x13) /* CF set on failure */
+ JCC _readsectorok
+
+ LWI(ioerror(SB), rSI)
+ CALL16(buggery(SB))
+
+_readsectorok:
+ LWI(0x7C00, rBX) /* buffer address (rES already OK) */
+ LXW(0x1FE, xBX, rAX)
+ CMPI(0xAA55, rAX)
+ JNE _bbnotok
+
+ /*
+ * Jump to the loaded PBS.
+ * rDL and rSI should still contain the drive
+ * and partition table pointer respectively.
+ */
+ MW(rDI, rSI)
+ FARJUMP16(0x0000, 0x7C00)
+
+_bbnotok:
+ LWI(invalidPBS(SB), rSI)
+
+TEXT buggery(SB), $0
+ CALL16(BIOSputs(SB))
+ LWI(reboot(SB), rSI)
+ CALL16(BIOSputs(SB))
+
+_wait:
+ CLR(rAX) /* wait for any key */
+ BIOSCALL(0x16)
+
+_reset:
+ CLR(rBX) /* set ES segment for BIOS area */
+ MTSR(rBX, rES)
+
+ LWI(0x0472, rBX) /* warm-start code address */
+ LWI(0x1234, rAX) /* warm-start code */
+ POKEW /* MOVW AX, ES:[BX] */
+
+ FARJUMP16(0xFFFF, 0x0000) /* reset */
+
+/*
+ * Output a string to the display.
+ * String argument is in rSI.
+ */
+TEXT BIOSputs(SB), $0
+ PUSHA
+ CLR(rBX)
+_BIOSputs:
+ LODSB
+ ORB(rAL, rAL)
+ JEQ _BIOSputsret
+
+ LBI(0x0E, rAH)
+ BIOSCALL(0x10)
+ JMP _BIOSputs
+
+_BIOSputsret:
+ POPA
+ RET
+
+/* "No active entry in MBR" */
+TEXT noentry(SB), $0
+ BYTE $'N'; BYTE $'o'; BYTE $' '; BYTE $'a';
+ BYTE $'c'; BYTE $'t'; BYTE $'i'; BYTE $'v';
+ BYTE $'e'; BYTE $' '; BYTE $'e'; BYTE $'n';
+ BYTE $'t'; BYTE $'r'; BYTE $'y'; BYTE $' ';
+ BYTE $'i'; BYTE $'n'; BYTE $' '; BYTE $'M';
+ BYTE $'B'; BYTE $'R';
+ BYTE $'\z';
+
+/* "Invalid MBR" */
+TEXT invalidMBR(SB), $0
+ BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
+ BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
+ BYTE $'M'; BYTE $'B'; BYTE $'R';
+ BYTE $'\z';
+
+/* "I/O error" */
+TEXT ioerror(SB), $0
+ BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
+ BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
+ BYTE $'r';
+ BYTE $'\z';
+
+/* "Invalid PBS" */
+TEXT invalidPBS(SB), $0
+ BYTE $'I'; BYTE $'n'; BYTE $'v'; BYTE $'a';
+ BYTE $'l'; BYTE $'i'; BYTE $'d'; BYTE $' ';
+ BYTE $'P'; BYTE $'B'; BYTE $'S';
+ BYTE $'\z';
+
+/* "\r\nPress almost any key to reboot..." */
+TEXT reboot(SB), $0
+ BYTE $'\r';BYTE $'\n';
+ BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
+ BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $'l';
+ BYTE $'m'; BYTE $'o'; BYTE $'s'; BYTE $'t';
+ BYTE $' '; BYTE $'a'; BYTE $'n'; BYTE $'y';
+ BYTE $' '; BYTE $'k'; BYTE $'e'; BYTE $'y';
+ BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
+ BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
+ BYTE $'o'; BYTE $'t'; BYTE $'.'; BYTE $'.';
+ BYTE $'.';
+ BYTE $'\z';
+
+/* "MBR..." */
+TEXT confidence(SB), $0
+ BYTE $'M'; BYTE $'B'; BYTE $'R'; BYTE $'.';
+ BYTE $'.'; BYTE $'.';
+ BYTE $'\z';
--- /dev/null
+++ b/os/boot.original/pc/mem.h
@@ -1,0 +1,114 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#define BY2PG 4096 /* bytes per page */
+#define WD2PG (BY2PG/BY2WD) /* words per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
+
+#define MAXMACH 1 /* max # cpus system can run */
+
+/*
+ * Time
+ */
+#define HZ (100) /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+#define TK2MS(x) ((x)*(1000/HZ))
+#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
+
+/*
+ * Fundamental addresses
+ */
+#define IDTADDR 0x80000800 /* idt */
+#define APBOOTSTRAP 0x80001000 /* AP bootstrap code */
+#define CONFADDR 0x80001200 /* info passed from boot loader */
+#define CPU0PDB 0x80002000 /* bootstrap processor PDB */
+#define CPU0PTE 0x80003000 /* bootstrap processor PTE's for 0-4MB */
+#define MACHADDR 0x80004000 /* as seen by current processor */
+#define CPU0MACH 0x80005000 /* Mach for bootstrap processor */
+#define BIOSXCHG 0x80006000 /* To exchange data with the BIOS */
+#define MACHSIZE (BY2PG*8) /* stack size */
+
+/*
+ * Address spaces
+ *
+ * Kernel is at 2GB-4GB
+ */
+#define KZERO 0x80000000 /* base of kernel address space */
+#define KTZERO KZERO /* first address in kernel text */
+#define ROMBIOS (KZERO|0xF0000)
+
+/*
+ * known 80386 segments (in GDT) and their selectors
+ */
+#define NULLSEG 0 /* null segment */
+#define KDSEG 1 /* kernel data/stack */
+#define KESEG 2 /* kernel executable */
+#define UDSEG 3 /* user data/stack */
+#define UESEG 4 /* user executable */
+#define SYSGATE 5 /* system call gate */
+#define TSSSEG 6 /* task segment */
+
+#define SELGDT (0<<3) /* selector is in gdt */
+#define SELLDT (1<<3) /* selector is in ldt */
+
+#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p))
+
+#define NULLSEL SELECTOR(NULLSEG, SELGDT, 0)
+#define KESEL SELECTOR(KESEG, SELGDT, 0)
+#define KDSEL SELECTOR(KDSEG, SELGDT, 0)
+#define UESEL SELECTOR(UESEG, SELGDT, 3)
+#define UDSEL SELECTOR(UDSEG, SELGDT, 3)
+#define TSSSEL SELECTOR(TSSSEG, SELGDT, 0)
+
+/*
+ * fields in segment descriptors
+ */
+#define SEGDATA (0x10<<8) /* data/stack segment */
+#define SEGEXEC (0x18<<8) /* executable segment */
+#define SEGTSS (0x9<<8) /* TSS segment */
+#define SEGCG (0x0C<<8) /* call gate */
+#define SEGIG (0x0E<<8) /* interrupt gate */
+#define SEGTG (0x0F<<8) /* task gate */
+#define SEGTYPE (0x1F<<8)
+
+#define SEGP (1<<15) /* segment present */
+#define SEGPL(x) ((x)<<13) /* priority level */
+#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */
+#define SEGG (1<<23) /* granularity 1==4k (for other) */
+#define SEGE (1<<10) /* expand down */
+#define SEGW (1<<9) /* writable (for data/stack) */
+#define SEGR (1<<9) /* readable (for code) */
+#define SEGD (1<<22) /* default 1==32bit (for code) */
+
+/*
+ * virtual MMU
+ */
+#define PTEMAPMEM (1024*1024) /* ??? */
+#define SEGMAPSIZE 16 /* ??? */
+#define PTEPERTAB (PTEMAPMEM/BY2PG) /* ??? */
+#define PPN(x) ((x)&~(BY2PG-1))
+
+/*
+ * physical MMU
+ */
+#define PTEVALID (1<<0)
+#define PTEUNCACHED 0 /* everything is uncached */
+#define PTEWRITE (1<<1)
+#define PTERONLY (0<<1)
+#define PTEKERNEL (0<<2)
+#define PTEUSER (1<<2)
+#define PTESIZE (1<<7)
+
+/*
+ * flag register bits that we care about
+ */
+#define IFLAG 0x200
--- /dev/null
+++ b/os/boot.original/pc/memory.c
@@ -1,0 +1,504 @@
+/*
+ * Size memory and create the kernel page-tables on the fly while doing so.
+ * Called from main(), this code should only be run by the bootstrap processor.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#define MEMDEBUG 0
+
+#define PDX(va) ((((ulong)(va))>>22) & 0x03FF)
+#define PTX(va) ((((ulong)(va))>>12) & 0x03FF)
+
+enum {
+ MemUPA = 0, /* unbacked physical address */
+ MemRAM = 1, /* physical memory */
+ MemUMB = 2, /* upper memory block (<16MB) */
+ NMemType = 3,
+
+ KB = 1024,
+
+ MemMinMB = 4, /* minimum physical memory (<=4MB) */
+ MemMaxMB = 768, /* maximum physical memory to check */
+
+ NMemBase = 10,
+};
+
+typedef struct {
+ int size;
+ ulong addr;
+} Map;
+
+typedef struct {
+ char* name;
+ Map* map;
+ Map* mapend;
+
+ Lock;
+} RMap;
+
+static Map mapupa[8];
+static RMap rmapupa = {
+ "unallocated unbacked physical memory",
+ mapupa,
+ &mapupa[7],
+};
+
+static Map xmapupa[8];
+static RMap xrmapupa = {
+ "unbacked physical memory",
+ xmapupa,
+ &xmapupa[7],
+};
+
+static Map mapram[8];
+static RMap rmapram = {
+ "physical memory",
+ mapram,
+ &mapram[7],
+};
+
+static Map mapumb[64];
+static RMap rmapumb = {
+ "upper memory block",
+ mapumb,
+ &mapumb[63],
+};
+
+static Map mapumbrw[8];
+static RMap rmapumbrw = {
+ "UMB device memory",
+ mapumbrw,
+ &mapumbrw[7],
+};
+
+void
+memdebug(void)
+{
+ Map *mp;
+ ulong maxpa, maxpa1, maxpa2;
+
+ if(MEMDEBUG == 0)
+ return;
+
+ maxpa = (nvramread(0x18)<<8)|nvramread(0x17);
+ maxpa1 = (nvramread(0x31)<<8)|nvramread(0x30);
+ maxpa2 = (nvramread(0x16)<<8)|nvramread(0x15);
+ print("maxpa = %luX -> %luX, maxpa1 = %luX maxpa2 = %luX\n",
+ maxpa, MB+maxpa*KB, maxpa1, maxpa2);
+
+ for(mp = rmapram.map; mp->size; mp++)
+ print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
+ for(mp = rmapumb.map; mp->size; mp++)
+ print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
+ for(mp = rmapumbrw.map; mp->size; mp++)
+ print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
+ for(mp = rmapupa.map; mp->size; mp++)
+ print("%8.8luX %8.8luX %8.8luX\n", mp->addr, (ulong)mp->size, mp->addr+mp->size);
+}
+
+void
+mapfree(RMap* rmap, ulong addr, ulong size)
+{
+ Map *mp;
+ ulong t;
+
+ if(size == 0)
+ return;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
+ ;
+
+ if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
+ (mp-1)->size += size;
+ if(addr+size == mp->addr){
+ (mp-1)->size += mp->size;
+ while(mp->size){
+ mp++;
+ (mp-1)->addr = mp->addr;
+ (mp-1)->size = mp->size;
+ }
+ }
+ }
+ else{
+ if(addr+size == mp->addr && mp->size){
+ mp->addr -= size;
+ mp->size += size;
+ }
+ else do{
+ if(mp >= rmap->mapend){
+ print("mapfree: %s: losing 0x%luX, %lud\n",
+ rmap->name, addr, size);
+ break;
+ }
+ t = mp->addr;
+ mp->addr = addr;
+ addr = t;
+ t = mp->size;
+ mp->size = size;
+ mp++;
+ }while(size = t);
+ }
+ unlock(rmap);
+}
+
+ulong
+mapalloc(RMap* rmap, ulong addr, int size, int align)
+{
+ Map *mp;
+ ulong maddr, oaddr;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->size; mp++){
+ maddr = mp->addr;
+
+ if(addr){
+ /*
+ * A specific address range has been given:
+ * if the current map entry is greater then
+ * the address is not in the map;
+ * if the current map entry does not overlap
+ * the beginning of the requested range then
+ * continue on to the next map entry;
+ * if the current map entry does not entirely
+ * contain the requested range then the range
+ * is not in the map.
+ */
+ if(maddr > addr)
+ break;
+ if(mp->size < addr - maddr) /* maddr+mp->size < addr, but no overflow */
+ continue;
+ if(addr - maddr > mp->size - size) /* addr+size > maddr+mp->size, but no overflow */
+ break;
+ maddr = addr;
+ }
+
+ if(align > 0)
+ maddr = ((maddr+align-1)/align)*align;
+ if(mp->addr+mp->size-maddr < size)
+ continue;
+
+ oaddr = mp->addr;
+ mp->addr = maddr+size;
+ mp->size -= maddr-oaddr+size;
+ if(mp->size == 0){
+ do{
+ mp++;
+ (mp-1)->addr = mp->addr;
+ }while((mp-1)->size = mp->size);
+ }
+
+ unlock(rmap);
+ if(oaddr != maddr)
+ mapfree(rmap, oaddr, maddr-oaddr);
+
+ return maddr;
+ }
+ unlock(rmap);
+
+ return 0;
+}
+
+static void
+umbscan(void)
+{
+ uchar *p;
+
+ /*
+ * Scan the Upper Memory Blocks (0xA0000->0xF0000) for pieces
+ * which aren't used; they can be used later for devices which
+ * want to allocate some virtual address space.
+ * Check for two things:
+ * 1) device BIOS ROM. This should start with a two-byte header
+ * of 0x55 0xAA, followed by a byte giving the size of the ROM
+ * in 512-byte chunks. These ROM's must start on a 2KB boundary.
+ * 2) device memory. This is read-write.
+ * There are some assumptions: there's VGA memory at 0xA0000 and
+ * the VGA BIOS ROM is at 0xC0000. Also, if there's no ROM signature
+ * at 0xE0000 then the whole 64KB up to 0xF0000 is theoretically up
+ * for grabs; check anyway.
+ */
+ p = KADDR(0xD0000); /*RSC: changed from 0xC0000 */
+ while(p < (uchar*)KADDR(0xE0000)){
+ if (p[0] == 0x55 && p[1] == 0xAA) {
+ /* Skip p[2] chunks of 512 bytes. Test for 0x55 AA before
+ poking obtrusively, or else the Thinkpad X20 dies when
+ setting up the cardbus (PB) */
+ p += p[2] * 512;
+ continue;
+ }
+
+ p[0] = 0xCC;
+ p[2*KB-1] = 0xCC;
+ if(p[0] != 0xCC || p[2*KB-1] != 0xCC){
+ p[0] = 0x55;
+ p[1] = 0xAA;
+ p[2] = 4;
+ if(p[0] == 0x55 && p[1] == 0xAA){
+ p += p[2]*512;
+ continue;
+ }
+ if(p[0] == 0xFF && p[1] == 0xFF)
+ mapfree(&rmapumb, PADDR(p), 2*KB);
+ }
+ else
+ mapfree(&rmapumbrw, PADDR(p), 2*KB);
+ p += 2*KB;
+ }
+
+ p = KADDR(0xE0000);
+ if(p[0] != 0x55 || p[1] != 0xAA){
+ p[0] = 0xCC;
+ p[64*KB-1] = 0xCC;
+ if(p[0] != 0xCC && p[64*KB-1] != 0xCC)
+ mapfree(&rmapumb, PADDR(p), 64*KB);
+ }
+}
+
+
+void
+meminit(ulong)
+{
+ /* A hack to initialize unbacked physical memory. It's assumed PCI space is assigned by
+ the BIOS in the 0xF0000000 range and 9load never needs more than 0x2000... to run. These
+ values leave ample space for memory allocations for uninitialized PCI cards (e.g. cardbus
+ cards). (pb) */
+ ulong maxmem = 0x40000000;
+
+ umbscan();
+ mapfree(&rmapupa, maxmem, 0x00000000-maxmem);
+ if(MEMDEBUG)
+ memdebug();
+}
+
+ulong
+umbmalloc(ulong addr, int size, int align)
+{
+ ulong a;
+
+ if(a = mapalloc(&rmapumb, addr, size, align))
+ return (ulong)KADDR(a);
+
+ return 0;
+}
+
+void
+umbfree(ulong addr, int size)
+{
+ mapfree(&rmapumb, PADDR(addr), size);
+}
+
+ulong
+umbrwmalloc(ulong addr, int size, int align)
+{
+ ulong a;
+ uchar *p;
+
+ if(a = mapalloc(&rmapumbrw, addr, size, align))
+ return(ulong)KADDR(a);
+
+ /*
+ * Perhaps the memory wasn't visible before
+ * the interface is initialised, so try again.
+ */
+ if((a = umbmalloc(addr, size, align)) == 0)
+ return 0;
+ p = (uchar*)a;
+ p[0] = 0xCC;
+ p[size-1] = 0xCC;
+ if(p[0] == 0xCC && p[size-1] == 0xCC)
+ return a;
+ umbfree(a, size);
+
+ return 0;
+}
+
+void
+umbrwfree(ulong addr, int size)
+{
+ mapfree(&rmapumbrw, PADDR(addr), size);
+}
+
+ulong*
+mmuwalk(ulong* pdb, ulong va, int level, int create)
+{
+ ulong pa, *table;
+
+ /*
+ * Walk the page-table pointed to by pdb and return a pointer
+ * to the entry for virtual address va at the requested level.
+ * If the entry is invalid and create isn't requested then bail
+ * out early. Otherwise, for the 2nd level walk, allocate a new
+ * page-table page and register it in the 1st level.
+ */
+ table = &pdb[PDX(va)];
+ if(!(*table & PTEVALID) && create == 0)
+ return 0;
+
+ switch(level){
+
+ default:
+ return 0;
+
+ case 1:
+ return table;
+
+ case 2:
+ if(*table & PTESIZE)
+ panic("mmuwalk2: va 0x%ux entry 0x%ux\n", va, *table);
+ if(!(*table & PTEVALID)){
+ pa = PADDR(ialloc(BY2PG, BY2PG));
+ *table = pa|PTEWRITE|PTEVALID;
+ }
+ table = KADDR(PPN(*table));
+
+ return &table[PTX(va)];
+ }
+}
+
+static Lock mmukmaplock;
+
+ulong
+mmukmap(ulong pa, ulong va, int size)
+{
+ ulong pae, *table, *pdb, pgsz, *pte, x;
+ int pse, sync;
+ extern int cpuidax, cpuiddx;
+
+ pdb = KADDR(getcr3());
+ if((cpuiddx & 0x08) && (getcr4() & 0x10))
+ pse = 1;
+ else
+ pse = 0;
+ sync = 0;
+
+ pa = PPN(pa);
+ if(va == 0)
+ va = (ulong)KADDR(pa);
+ else
+ va = PPN(va);
+
+ pae = pa + size;
+ lock(&mmukmaplock);
+ while(pa < pae){
+ table = &pdb[PDX(va)];
+ /*
+ * Possibly already mapped.
+ */
+ if(*table & PTEVALID){
+ if(*table & PTESIZE){
+ /*
+ * Big page. Does it fit within?
+ * If it does, adjust pgsz so the correct end can be
+ * returned and get out.
+ * If not, adjust pgsz up to the next 4MB boundary
+ * and continue.
+ */
+ x = PPN(*table);
+ if(x != pa)
+ panic("mmukmap1: pa 0x%ux entry 0x%ux\n",
+ pa, *table);
+ x += 4*MB;
+ if(pae <= x){
+ pa = pae;
+ break;
+ }
+ pgsz = x - pa;
+ pa += pgsz;
+ va += pgsz;
+
+ continue;
+ }
+ else{
+ /*
+ * Little page. Walk to the entry.
+ * If the entry is valid, set pgsz and continue.
+ * If not, make it so, set pgsz, sync and continue.
+ */
+ pte = mmuwalk(pdb, va, 2, 0);
+ if(pte && *pte & PTEVALID){
+ x = PPN(*pte);
+ if(x != pa)
+ panic("mmukmap2: pa 0x%ux entry 0x%ux\n",
+ pa, *pte);
+ pgsz = BY2PG;
+ pa += pgsz;
+ va += pgsz;
+ sync++;
+
+ continue;
+ }
+ }
+ }
+
+ /*
+ * Not mapped. Check if it can be mapped using a big page -
+ * starts on a 4MB boundary, size >= 4MB and processor can do it.
+ * If not a big page, walk the walk, talk the talk.
+ * Sync is set.
+ */
+ if(pse && (pa % (4*MB)) == 0 && (pae >= pa+4*MB)){
+ *table = pa|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID;
+ pgsz = 4*MB;
+ }
+ else{
+ pte = mmuwalk(pdb, va, 2, 1);
+ *pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID;
+ pgsz = BY2PG;
+ }
+ pa += pgsz;
+ va += pgsz;
+ sync++;
+ }
+ unlock(&mmukmaplock);
+
+ /*
+ * If something was added
+ * then need to sync up.
+ */
+ if(sync)
+ putcr3(PADDR(pdb));
+
+ return pa;
+}
+
+ulong
+upamalloc(ulong addr, int size, int align)
+{
+ ulong ae, a;
+
+ USED(align);
+
+ if((a = mapalloc(&rmapupa, addr, size, align)) == 0){
+ memdebug();
+ return 0;
+ }
+
+ /*
+ * This is a travesty, but they all are.
+ */
+ ae = mmukmap(a, 0, size);
+
+ /*
+ * Should check here that it was all delivered
+ * and put it back and barf if not.
+ */
+ USED(ae);
+
+ /*
+ * Be very careful this returns a PHYSICAL address.
+ */
+ return a;
+}
+
+void
+upafree(ulong pa, int size)
+{
+ USED(pa, size);
+}
+
--- /dev/null
+++ b/os/boot.original/pc/mkfile
@@ -1,0 +1,250 @@
+<../../../mkconfig
+objtype=386
+SYSTARG=$OSTARG
+OBJTYPE=386
+BIN=$ROOT/Inferno/$OBJTYPE
+LIBDIR=$ROOT/Inferno/$OBJTYPE/lib
+LIBDIRS=../libflate $ROOT/libkern
+LIBS=\
+ libflate\
+ libkern\
+
+LIBFILES=${LIBS:%=$LIBDIR/%.a}
+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
+
+BIN=$ROOT/Inferno/$OBJTYPE
+
+TARG=\
+ 9load\
+ 9pxeload\
+ 9loadlite\
+ 9loaddebug\
+ 9loadlitedebug\
+ ld.com\
+ mbr\
+ pbs\
+ pbslba\
+
+CORE=\
+ alarm.$O\
+ cga.$O\
+ clock.$O\
+ console.$O\
+ dosboot.$O\
+ devfloppy.$O\
+ dma.$O\
+ fs.$O\
+ ilock.$O\
+ kbd.$O\
+ kfsboot.$O\
+ print.$O\
+ queue.$O\
+ trap.$O\
+ getcallerpc.$O\
+
+LOAD=\
+ 8250.$O\
+ apm.$O\
+ boot.$O\
+ cis.$O\
+ conf.$O\
+ devbios.$O\
+ devi82365.$O\
+ devpccard.$O\
+ devsd.$O\
+ inflate.$O\
+ load.$O\
+ memory.$O\
+ part.$O\
+ pci.$O\
+ sdata.$O\
+ sdmylex.$O\
+ sd53c8xx.$O\
+ sdiahci.$O\
+ sdscsi.$O\
+ sdaoe.$O\
+ sdbios.$O\
+
+ETHER=\
+ bootp.$O\
+ eipfmt.$O\
+ ether.$O\
+ ether2114x.$O\
+ ether2000.$O\
+ ether589.$O\
+ ether79c970.$O\
+ ether8003.$O\
+ ether8139.$O\
+ ether8169.$O\
+ ether82563.$O\
+ ether82557.$O\
+ ether83815.$O\
+ ether8390.$O\
+ etherec2t.$O\
+ etherelnk3.$O\
+ etherga620.$O\
+ etherigbe.$O\
+ ethermii.$O\
+ etherrhine.$O\
+ etherdp83820.$O\
+
+BCOM=\
+ bcom.$O\
+ bootld.$O\
+ devsd.$O\
+ memory.$O\
+ part.$O\
+ pci.$O\
+ sdata.$O\
+ sdscsi.$O\
+
+HFILES=\
+ lib.h\
+ mem.h\
+ dat.h\
+ fns.h\
+ io.h\
+ aoe.h\
+
+CFLAGS=-FVTw -I. -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include
+
+all:V: $TARG
+
+9load: l.$O $CORE $LOAD $ETHER $LIBFILES
+ $LD -o $target -H3 -T0x80010000 -l $prereq
+ ls -l $target
+
+9pxeload: l.$O $CORE $LOAD $ETHER $LIBFILES
+ $LD -o $target -H3 -T0x80007C00 -l $prereq
+ ls -l $target
+
+9loaddebug: l.$O $CORE $LOAD $ETHER $LIBFILES
+ $LD -o $target -T0x80010000 -l $prereq
+ ls -l $target
+ # acid $target
+ # map({"text", 0x80010000, 0x80090000, 0x00000020})
+
+9loadlite: l.$O $CORE $LOAD noether.$O $LIBFILES
+ $LD -o $target -H3 -T0x80010000 -l $prereq
+ ls -l $target
+
+9loadlitedebug: l.$O $CORE $LOAD noether.$O $LIBFILES
+ $LD -o $target -T0x80010000 -l $prereq
+ ls -l $target
+ # acid $target
+ # map({"text", 0x80010000, 0x80090000, 0x00000020})
+
+ld.com: ld.$O $CORE $BCOM $LIBFILES
+ $LD -o $target -H3 -T0x80080100 -l $prereq
+ ls -l $target
+
+lddebug: ld.$O $CORE $BCOM $LIBFILES
+ $LD -o $target -T0x80080100 -l $prereq
+ ls -l $target
+ # acid $target
+ # map({"text", 0x80080100, 0x800B0000, 0x00000020})
+
+ld.$O: l.s
+ $AS -DDOTCOM -o $target l.s
+
+lpxe.$O: l.s
+ $AS -DPXE -o $target l.s
+
+%.$O: %.s
+ $AS $stem.s
+
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+
+%.$O: $HFILES
+
+l.$O pbs.$O pbslba.$O mbr.$O: x16.h
+
+clock.$O floppy.$O trap.$O: ureg.h
+bcom.$O conf.$O devfloppy.$O devsd.$O dosboot.$O fs.$O \
+ kfsboot.$O load.$O part.$O: dosfs.h fs.h kfs.h
+ether.$O etherelnk3.$O: etherif.h
+devsd.$O part.$O sdata.$O sdscsi.$O: sd.h
+bootp.$O: ip.h
+
+mbr: mbr.$O
+ $LD -o $target -H3 -T0x0600 -l $prereq
+ ls -l $target
+
+pbs&: pbs%.$O
+ $LD -o $target -H3 -T0x7C00 -l $prereq
+ ls -l $target
+
+pbs&.debug: pbs%.$O
+ $LD -o $target -T0x7C00 -l $prereq
+ ls -l $target
+ # acid $target
+ # map({"text", 0x7C00, 0x7E00, 0x00000020})
+
+# added to cause libflate to be made automatically:
+
+$ROOT/Inferno/$OBJTYPE/lib/lib%.a:Q: all-$SHELLTYPE
+ #
+
+rc-lib%.a nt-lib%.a:VQ:
+ echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
+ @{builtin cd $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
+
+sh-lib%.a:VQ:
+ echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
+ (cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
+
+clean:
+ rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG 9loaddebug lddebug
+
+install:V:
+ for (i in $TARG)
+ mk $MKFLAGS $i.install
+
+%.install:V: $BIN/%
+
+$BIN/%: %
+ cp $stem $BIN/$stem
+
+UPDATE=\
+ mkfile\
+ ${CORE:%.$O=%.c}\
+ ${LOAD:%.$O=%.c}\
+ ${BCOM:%.$O=%.c}\
+ ${ETHER:%.$O=%.c}\
+ $HFILES\
+ l.s\
+ noether.c\
+ pbs.s\
+ pbslba.s\
+ mbr.s\
+ x16.h\
+ ureg.h\
+ dosfs.h\
+ fs.h\
+ kfs.h\
+ etherif.h\
+ sd.h\
+ ip.h\
+ devfloppy.h\
+ ${TARG:%=/386/%}\
+
+update:V:
+ update $UPDATEFLAGS $UPDATE
+
+
+%-sh:QV:
+ for i in $LIBDIRS
+ do
+ echo "(cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem)"
+ (cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem)
+ done
+
+%-rc %-nt:QV:
+ for (i in $LIBDIRS)
+ {
+ echo '@{cd $i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE $stem}'
+ @{cd $i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE $stem}
+ }
+
+nuke:V: clean nuke-$SHELLTYPE
--- /dev/null
+++ b/os/boot.original/pc/noether.c
@@ -1,0 +1,46 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+int
+etherinit(void)
+{
+ return -1;
+}
+
+void
+etherinitdev(int, char*)
+{
+}
+
+void
+etherprintdevs(int)
+{
+}
+
+int
+etherrxpkt(int, Etherpkt*, int)
+{
+ return -1;
+}
+
+int
+ethertxpkt(int, Etherpkt*, int, int)
+{
+ return -1;
+}
+
+int
+bootpboot(int, char*, Boot*)
+{
+ return -1;
+}
+
+void*
+pxegetfspart(int, char*, int)
+{
+ return nil;
+}
--- /dev/null
+++ b/os/boot.original/pc/part.c
@@ -1,0 +1,344 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include "sd.h"
+#include "fs.h"
+
+enum {
+ Npart = 32
+};
+
+uchar *mbrbuf, *partbuf;
+int nbuf;
+#define trace 0
+
+int
+tsdbio(SDunit *unit, SDpart *part, void *a, vlong off, int mbr)
+{
+ uchar *b;
+
+ if(sdbio(unit, part, a, unit->secsize, off) != unit->secsize){
+ if(trace)
+ print("%s: read %lud at %lld failed\n", unit->name,
+ unit->secsize, (vlong)part->start*unit->secsize+off);
+ return -1;
+ }
+ b = a;
+ if(mbr && (b[0x1FE] != 0x55 || b[0x1FF] != 0xAA)){
+ if(trace)
+ print("%s: bad magic %.2ux %.2ux at %lld\n",
+ unit->name, b[0x1FE], b[0x1FF],
+ (vlong)part->start*unit->secsize+off);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * read partition table. The partition table is just ascii strings.
+ */
+#define MAGIC "plan9 partitions"
+static void
+oldp9part(SDunit *unit)
+{
+ SDpart *pp;
+ char *field[3], *line[Npart+1];
+ ulong n, start, end;
+ int i;
+
+ /*
+ * We have some partitions already.
+ */
+ pp = &unit->part[unit->npart];
+
+ /*
+ * We prefer partition tables on the second to last sector,
+ * but some old disks use the last sector instead.
+ */
+ strcpy(pp->name, "partition");
+ pp->start = unit->sectors - 2;
+ pp->end = unit->sectors - 1;
+
+ if(tsdbio(unit, pp, partbuf, 0, 0) < 0)
+ return;
+
+ if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0) {
+ /* not found on 2nd last sector; look on last sector */
+ pp->start++;
+ pp->end++;
+ if(tsdbio(unit, pp, partbuf, 0, 0) < 0)
+ return;
+ if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0)
+ return;
+ print("%s: using old plan9 partition table on last sector\n", unit->name);
+ }else
+ print("%s: using old plan9 partition table on 2nd-to-last sector\n", unit->name);
+
+ /* we found a partition table, so add a partition partition */
+ unit->npart++;
+ partbuf[unit->secsize-1] = '\0';
+
+ /*
+ * parse partition table
+ */
+ n = getfields((char*)partbuf, line, Npart+1, '\n');
+ if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
+ for(i = 1; i < n && unit->npart < SDnpart; i++){
+ if(getfields(line[i], field, 3, ' ') != 3)
+ break;
+ start = strtoull(field[1], 0, 0);
+ end = strtoull(field[2], 0, 0);
+ if(start >= end || end > unit->sectors)
+ break;
+ sdaddpart(unit, field[0], start, end);
+ }
+ }
+}
+
+static void
+p9part(SDunit *unit, char *name)
+{
+ SDpart *p;
+ char *field[4], *line[Npart+1];
+ uvlong start, end;
+ int i, n;
+
+ p = sdfindpart(unit, name);
+ if(p == nil)
+ return;
+
+ if(tsdbio(unit, p, partbuf, unit->secsize, 0) < 0)
+ return;
+ partbuf[unit->secsize-1] = '\0';
+
+ if(strncmp((char*)partbuf, "part ", 5) != 0)
+ return;
+
+ n = getfields((char*)partbuf, line, Npart+1, '\n');
+ if(n == 0)
+ return;
+ for(i = 0; i < n && unit->npart < SDnpart; i++){
+ if(strncmp(line[i], "part ", 5) != 0)
+ break;
+ if(getfields(line[i], field, 4, ' ') != 4)
+ break;
+ start = strtoull(field[2], 0, 0);
+ end = strtoull(field[3], 0, 0);
+ if(start >= end || end > unit->sectors)
+ break;
+ sdaddpart(unit, field[1], p->start+start, p->start+end);
+ }
+}
+
+int
+isdos(int t)
+{
+ return t==FAT12 || t==FAT16 || t==FATHUGE || t==FAT32 || t==FAT32X;
+}
+
+int
+isextend(int t)
+{
+ return t==EXTEND || t==EXTHUGE || t==LEXTEND;
+}
+
+/*
+ * Fetch the first dos and all plan9 partitions out of the MBR partition table.
+ * We return -1 if we did not find a plan9 partition.
+ */
+static int
+mbrpart(SDunit *unit)
+{
+ Dospart *dp;
+ ulong taboffset, start, end;
+ ulong firstxpart, nxtxpart;
+ int havedos, i, nplan9;
+ char name[10];
+
+ taboffset = 0;
+ dp = (Dospart*)&mbrbuf[0x1BE];
+ if(1) {
+ /* get the MBR (allowing for DMDDO) */
+ if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0)
+ return -1;
+ for(i=0; i<4; i++)
+ if(dp[i].type == DMDDO) {
+ if(trace)
+ print("DMDDO partition found\n");
+ taboffset = 63;
+ if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0)
+ return -1;
+ i = -1; /* start over */
+ }
+ }
+
+ /*
+ * Read the partitions, first from the MBR and then
+ * from successive extended partition tables.
+ */
+ nplan9 = 0;
+ havedos = 0;
+ firstxpart = 0;
+ for(;;) {
+ if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0)
+ return -1;
+ if(trace) {
+ if(firstxpart)
+ print("%s ext %lud ", unit->name, taboffset);
+ else
+ print("%s mbr ", unit->name);
+ }
+ nxtxpart = 0;
+ for(i=0; i<4; i++) {
+ if(trace)
+ print("dp %d...", dp[i].type);
+ start = taboffset+GLONG(dp[i].start);
+ end = start+GLONG(dp[i].len);
+
+ if(dp[i].type == PLAN9) {
+ if(nplan9 == 0)
+ strcpy(name, "plan9");
+ else
+ sprint(name, "plan9.%d", nplan9);
+ sdaddpart(unit, name, start, end);
+ p9part(unit, name);
+ nplan9++;
+ }
+
+ /*
+ * We used to take the active partition (and then the first
+ * when none are active). We have to take the first here,
+ * so that the partition we call ``dos'' agrees with the
+ * partition disk/fdisk calls ``dos''.
+ */
+ if(havedos==0 && isdos(dp[i].type)){
+ havedos = 1;
+ sdaddpart(unit, "dos", start, end);
+ }
+
+ /* nxtxpart is relative to firstxpart (or 0), not taboffset */
+ if(isextend(dp[i].type)){
+ nxtxpart = start-taboffset+firstxpart;
+ if(trace)
+ print("link %lud...", nxtxpart);
+ }
+ }
+ if(trace)
+ print("\n");
+
+ if(!nxtxpart)
+ break;
+ if(!firstxpart)
+ firstxpart = nxtxpart;
+ taboffset = nxtxpart;
+ }
+ return nplan9 ? 0 : -1;
+}
+
+/*
+ * To facilitate booting from CDs, we create a partition for
+ * the boot floppy image embedded in a bootable CD.
+ */
+static int
+part9660(SDunit *unit)
+{
+ uchar buf[2048];
+ ulong a, n;
+ uchar *p;
+
+ if(unit->secsize != 2048)
+ return -1;
+
+ if(sdbio(unit, &unit->part[0], buf, 2048, 17*2048) < 0)
+ return -1;
+
+ if(buf[0] || strcmp((char*)buf+1, "CD001\x01EL TORITO SPECIFICATION") != 0)
+ return -1;
+
+
+ p = buf+0x47;
+ a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
+
+ if(sdbio(unit, &unit->part[0], buf, 2048, a*2048) < 0)
+ return -1;
+
+ if(memcmp(buf, "\x01\x00\x00\x00", 4) != 0
+ || memcmp(buf+30, "\x55\xAA", 2) != 0
+ || buf[0x20] != 0x88)
+ return -1;
+
+ p = buf+0x28;
+ a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
+
+ switch(buf[0x21]){
+ case 0x01:
+ n = 1200*1024;
+ break;
+ case 0x02:
+ n = 1440*1024;
+ break;
+ case 0x03:
+ n = 2880*1024;
+ break;
+ default:
+ return -1;
+ }
+ n /= 2048;
+
+ print("found partition %s!cdboot; %lud+%lud\n", unit->name, a, n);
+ sdaddpart(unit, "cdboot", a, a+n);
+ return 0;
+}
+
+enum {
+ NEW = 1<<0,
+ OLD = 1<<1
+};
+
+void
+partition(SDunit *unit)
+{
+ int type;
+ char *p;
+
+ if(unit->part == 0)
+ return;
+
+ if(part9660(unit) == 0)
+ return;
+
+ p = getconf("partition");
+ if(p == nil)
+ p = defaultpartition;
+
+ if(p != nil && strncmp(p, "new", 3) == 0)
+ type = NEW;
+ else if(p != nil && strncmp(p, "old", 3) == 0)
+ type = OLD;
+ else
+ type = NEW|OLD;
+
+ if(nbuf < unit->secsize) {
+ free(mbrbuf);
+ free(partbuf);
+ mbrbuf = malloc(unit->secsize);
+ partbuf = malloc(unit->secsize);
+ if(mbrbuf==nil || partbuf==nil) {
+ free(mbrbuf);
+ free(partbuf);
+ partbuf = mbrbuf = nil;
+ nbuf = 0;
+ return;
+ }
+ nbuf = unit->secsize;
+ }
+
+ if((type & NEW) && mbrpart(unit) >= 0){
+ /* nothing to do */;
+ }
+ else if(type & OLD)
+ oldp9part(unit);
+}
--- /dev/null
+++ b/os/boot.original/pc/pbs.s
@@ -1,0 +1,372 @@
+/*
+ * FAT Partition Boot Sector. Loaded at 0x7C00:
+ * 8a pbs.s; 8l -o pbs -l -H3 -T0x7C00 pbs.8
+ * Will load the target at LOADSEG*16+LOADOFF, so the target
+ * should be probably be loaded with LOADOFF added to the
+ * -Taddress.
+ * If LOADSEG is a multiple of 64KB and LOADOFF is 0 then
+ * targets larger than 64KB can be loaded.
+ *
+ * This code uses the traditional INT13 BIOS interface and can
+ * therefore only access the first 8.4GB of the disc.
+ *
+ * It relies on the _volid field in the FAT header containing
+ * the LBA of the root directory.
+ */
+#include "x16.h"
+#include "mem.h"
+
+#define LOADSEG (0x10000/16) /* where to load code (64KB) */
+#define LOADOFF 0
+#define DIROFF 0x0200 /* where to read the root directory */
+
+/*
+ * FAT directory entry.
+ */
+#define Dname 0x00
+#define Dext 0x08
+#define Dattr 0x0B
+#define Dtime 0x16
+#define Ddate 0x18
+#define Dstart 0x1A
+#define Dlengthlo 0x1C
+#define Dlengthhi 0x1E
+
+#define Dirsz 0x20
+
+/*
+ * Data is kept on the stack, indexed by rBP.
+ */
+#define Xdap 0x00 /* disc address packet */
+#define Xrootsz 0x10 /* file data area */
+#define Xdrive 0x12 /* boot drive, passed by BIOS or MBR */
+#define Xtotal 0x14 /* sum of allocated data above */
+
+TEXT _magic(SB), $0
+ BYTE $0xEB; BYTE $0x3C; /* jmp .+ 0x3C (_start0x3E) */
+ BYTE $0x90 /* nop */
+TEXT _version(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _sectsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _clustsize(SB), $0
+ BYTE $0x00
+TEXT _nresrv(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nfats(SB), $0
+ BYTE $0x00
+TEXT _rootsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _volsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _mediadesc(SB), $0
+ BYTE $0x00
+TEXT _fatsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _trksize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nheads(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nhiddenlo(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nhiddenhi(SB), $0
+ BYTE $0x00; BYTE $0x00;
+TEXT _bigvolsize(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _driveno(SB), $0
+ BYTE $0x00
+TEXT _reserved0(SB), $0
+ BYTE $0x00
+TEXT _bootsig(SB), $0
+ BYTE $0x00
+TEXT _volid(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _label(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+ BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _type(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+
+_start0x3E:
+ CLI
+ CLR(rAX)
+ MTSR(rAX, rSS) /* 0000 -> rSS */
+ MTSR(rAX, rDS) /* 0000 -> rDS, source segment */
+ MTSR(rAX, rES)
+ LWI(_magic-Xtotal(SB), rSP)
+ MW(rSP, rBP) /* set the indexed-data pointer */
+
+ SBPB(rDL, Xdrive) /* save the boot drive */
+
+ /* booting from a CD starts us at 7C0:0. Move to 0:7C00 */
+ PUSHR(rAX)
+ LWI(_nxt(SB), rAX)
+ PUSHR(rAX)
+ BYTE $0xCB /* FAR RET */
+
+TEXT _nxt(SB), $0
+ STI
+
+ LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
+ CALL16(BIOSputs(SB))
+
+ CALL16(dreset(SB))
+
+_jmp00:
+ LW(_volid(SB), rAX) /* Xrootlo */
+ LW(_volid+2(SB), rDX) /* Xroothi */
+
+ LWI(_magic+DIROFF(SB), rBX)
+ CALL16(BIOSread(SB)) /* read the root directory */
+
+ LWI((512/Dirsz), rBX)
+
+ LWI(_magic+DIROFF(SB), rDI) /* compare first directory entry */
+
+_cmp00:
+ PUSHR(rDI) /* save for later if it matches */
+ LWI(bootfile(SB), rSI)
+ LWI(Dattr, rCX)
+ REP
+ CMPSB
+ POPR(rDI)
+ JEQ _jmp02
+
+ DEC(rBX)
+ JEQ _jmp01
+
+ ADDI(Dirsz, rDI)
+ JMP _cmp00
+_jmp01:
+ CALL16(buggery(SB))
+
+_jmp02:
+ CLR(rBX) /* a handy value */
+ LW(_rootsize(SB), rAX) /* calculate and save Xrootsz */
+ LWI(Dirsz, rCX)
+ MUL(rCX)
+ LW(_sectsize(SB), rCX)
+ PUSHR(rCX)
+ DEC(rCX)
+ ADD(rCX, rAX)
+ ADC(rBX, rDX)
+ POPR(rCX) /* _sectsize(SB) */
+ DIV(rCX)
+ PUSHR(rAX) /* Xrootsz */
+
+ /*
+ * rDI points to the matching directory entry.
+ */
+ LXW(Dstart, xDI, rAX) /* starting sector address */
+ DEC(rAX) /* that's just the way it is */
+ DEC(rAX)
+ LB(_clustsize(SB), rCL)
+ CLRB(rCH)
+ MUL(rCX)
+ LW(_volid(SB), rCX) /* Xrootlo */
+ ADD(rCX, rAX)
+ LW(_volid+2(SB), rCX) /* Xroothi */
+ ADC(rCX, rDX)
+ POPR(rCX) /* Xrootsz */
+ ADD(rCX, rAX)
+ ADC(rBX, rDX)
+
+ PUSHR(rAX) /* calculate how many sectors to read */
+ PUSHR(rDX)
+ LXW(Dlengthlo, xDI, rAX)
+ LXW(Dlengthhi, xDI, rDX)
+ LW(_sectsize(SB), rCX)
+ PUSHR(rCX)
+ DEC(rCX)
+ ADD(rCX, rAX)
+ ADC(rBX, rDX)
+ POPR(rCX) /* _sectsize(SB) */
+ DIV(rCX)
+ MW(rAX, rCX)
+ POPR(rDX)
+ POPR(rAX)
+
+ LWI(LOADSEG, rBX) /* address to load into (seg+offset) */
+ MTSR(rBX, rES) /* seg */
+ LWI(LOADOFF, rBX) /* offset */
+
+_readboot:
+ CALL16(BIOSread(SB)) /* read the sector */
+
+ LW(_sectsize(SB), rDI) /* bump addresses/counts */
+ ADD(rDI, rBX)
+ JCC _incsecno
+
+ MFSR(rES, rDI) /* next 64KB segment */
+ ADDI(0x1000, rDI)
+ MTSR(rDI, rES)
+
+_incsecno:
+ CLR(rDI)
+ INC(rAX)
+ ADC(rDI, rDX)
+ LOOP _readboot
+
+ LWI(LOADSEG, rDI) /* set rDS for loaded code */
+ MTSR(rDI, rDS)
+ FARJUMP16(LOADSEG, LOADOFF) /* no deposit, no return */
+
+TEXT buggery(SB), $0
+ LWI(error(SB), rSI)
+ CALL16(BIOSputs(SB))
+
+_wait:
+ CLR(rAX) /* wait for almost any key */
+ BIOSCALL(0x16)
+
+_reset:
+ CLR(rBX) /* set ES segment for BIOS area */
+ MTSR(rBX, rES)
+
+ LWI(0x0472, rBX) /* warm-start code address */
+ LWI(0x1234, rAX) /* warm-start code */
+ POKEW /* MOVW AX, ES:[BX] */
+
+ FARJUMP16(0xFFFF, 0x0000) /* reset */
+
+/*
+ * Read a sector from a disc. On entry:
+ * rDX:rAX sector number
+ * rES:rBX buffer address
+ * For BIOSCALL(0x13):
+ * rAH 0x02
+ * rAL number of sectors to read (1)
+ * rCH low 8 bits of cylinder
+ * rCL high 2 bits of cylinder (7-6), sector (5-0)
+ * rDH head
+ * rDL drive
+ * rES:rBX buffer address
+ */
+TEXT BIOSread(SB), $0
+ LWI(5, rDI) /* retry count (ATAPI ZIPs suck) */
+_retry:
+ PUSHA /* may be trashed by BIOSCALL */
+ PUSHR(rBX)
+
+ LW(_trksize(SB), rBX)
+ LW(_nheads(SB), rDI)
+ IMUL(rDI, rBX)
+ OR(rBX, rBX)
+ JZ _ioerror
+
+_okay:
+ DIV(rBX) /* cylinder -> rAX, track,sector -> rDX */
+
+ MW(rAX, rCX) /* save cylinder */
+ ROLI(0x08, rCX) /* swap rC[HL] */
+ SHLBI(0x06, rCL) /* move high bits up */
+
+ MW(rDX, rAX)
+ CLR(rDX)
+ LW(_trksize(SB), rBX)
+
+ DIV(rBX) /* head -> rAX, sector -> rDX */
+
+ INC(rDX) /* sector numbers are 1-based */
+ ANDI(0x003F, rDX) /* should not be necessary */
+ OR(rDX, rCX)
+
+ MW(rAX, rDX)
+ SHLI(0x08, rDX) /* form head */
+ LBPB(Xdrive, rDL) /* form drive */
+
+ POPR(rBX)
+ LWI(0x0201, rAX) /* form command and sectors */
+ BIOSCALL(0x13) /* CF set on failure */
+ JCC _BIOSreadret
+
+ POPA
+ DEC(rDI) /* too many retries? */
+ JEQ _ioerror
+
+ CALL16(dreset(SB))
+ JMP _retry
+
+_ioerror:
+ LWI(ioerror(SB), rSI)
+ CALL16(BIOSputs(SB))
+ JMP _wait
+
+_BIOSreadret:
+ POPA
+ RET
+
+TEXT dreset(SB), $0
+ PUSHA
+ CLR(rAX) /* rAH == 0 == reset disc system */
+ LBPB(Xdrive, rDL)
+ BIOSCALL(0x13)
+ ORB(rAH, rAH) /* status (0 == success) */
+ POPA
+ JNE _ioerror
+ RET
+
+/*
+ * Output a string to the display.
+ * String argument is in rSI.
+ */
+TEXT BIOSputs(SB), $0
+ PUSHA
+ CLR(rBX)
+_BIOSputs:
+ LODSB
+ ORB(rAL, rAL)
+ JEQ _BIOSputsret
+
+ LBI(0x0E, rAH)
+ BIOSCALL(0x10)
+ JMP _BIOSputs
+
+_BIOSputsret:
+ POPA
+ RET
+
+/* "Bad format or I/O error\r\nPress almost any key to reboot..."*/
+TEXT error(SB), $0
+ BYTE $'B'; BYTE $'a'; BYTE $'d'; BYTE $' ';
+ BYTE $'f'; BYTE $'o'; BYTE $'r'; BYTE $'m';
+ BYTE $'a'; BYTE $'t'; BYTE $' '; BYTE $'o';
+ BYTE $'r'; BYTE $' ';
+/* "I/O error\r\nPress almost any key to reboot..." */
+TEXT ioerror(SB), $0
+ BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
+ BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
+ BYTE $'r'; BYTE $'\r';BYTE $'\n';
+ BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
+ BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $' ';
+ BYTE $'k'; BYTE $'e'; BYTE $'y';
+ BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
+ BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
+ BYTE $'o'; BYTE $'t';
+ BYTE $'.'; BYTE $'.'; BYTE $'.';
+ BYTE $'\z';
+
+#ifdef USEBCOM
+/* "B COM" */
+TEXT bootfile(SB), $0
+ BYTE $'B'; BYTE $' '; BYTE $' '; BYTE $' ';
+ BYTE $' '; BYTE $' '; BYTE $' '; BYTE $' ';
+ BYTE $'C'; BYTE $'O'; BYTE $'M';
+ BYTE $'\z';
+#else
+/* "9LOAD " */
+TEXT bootfile(SB), $0
+ BYTE $'9'; BYTE $'L'; BYTE $'O'; BYTE $'A';
+ BYTE $'D'; BYTE $' '; BYTE $' '; BYTE $' ';
+ BYTE $' '; BYTE $' '; BYTE $' ';
+ BYTE $'\z';
+#endif /* USEBCOM */
+
+/* "PBS..." */
+TEXT confidence(SB), $0
+ BYTE $'P'; BYTE $'B'; BYTE $'S'; BYTE $'1';
+ BYTE $'.'; BYTE $'.'; BYTE $'.';
+ BYTE $'\z';
binary files /dev/null b/os/boot.original/pc/pbsdisk differ
--- /dev/null
+++ b/os/boot.original/pc/pbsdisk.s
@@ -1,0 +1,344 @@
+/*
+ * Debugging boot sector. Reads the first directory
+ * sector from disk and displays it.
+ *
+ * It relies on the _volid field in the FAT header containing
+ * the LBA of the root directory.
+ */
+#include "x16.h"
+
+#define DIROFF 0x00200 /* where to read the root directory (offset) */
+#define LOADSEG (0x10000/16) /* where to load code (64KB) */
+#define LOADOFF 0
+
+/*
+ * FAT directory entry.
+ */
+#define Dname 0x00
+#define Dext 0x08
+#define Dattr 0x0B
+#define Dtime 0x16
+#define Ddate 0x18
+#define Dstart 0x1A
+#define Dlengthlo 0x1C
+#define Dlengthhi 0x1E
+
+#define Dirsz 0x20
+
+/*
+ * We keep data on the stack, indexed by rBP.
+ */
+#define Xdrive 0x00 /* boot drive, passed by BIOS in rDL */
+#define Xrootlo 0x02 /* offset of root directory */
+#define Xroothi 0x04
+#define Xrootsz 0x06 /* file data area */
+#define Xtotal 0x08 /* sum of allocated data above */
+#define Xdap 0x00 /* disc address packet */
+
+TEXT _magic(SB), $0
+ BYTE $0xEB; BYTE $0x3C; /* jmp .+ 0x3C (_start0x3E) */
+ BYTE $0x90 /* nop */
+TEXT _version(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _sectsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _clustsize(SB), $0
+ BYTE $0x00
+TEXT _nresrv(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nfats(SB), $0
+ BYTE $0x00
+TEXT _rootsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _volsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _mediadesc(SB), $0
+ BYTE $0x00
+TEXT _fatsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _trksize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nheads(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nhiddenlo(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nhiddenhi(SB), $0
+ BYTE $0x00; BYTE $0x00;
+TEXT _bigvolsize(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _driveno(SB), $0
+ BYTE $0x00
+TEXT _reserved0(SB), $0
+ BYTE $0x00
+TEXT _bootsig(SB), $0
+ BYTE $0x00
+TEXT _volid(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _label(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+ BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _type(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+
+_start0x3E:
+ CLI
+ CLR(rAX)
+ MTSR(rAX, rSS) /* 0000 -> rSS */
+ MTSR(rAX, rDS) /* 0000 -> rDS, source segment */
+ MTSR(rAX, rES)
+ LWI(_magic-Xtotal(SB), rSP)
+ MW(rSP, rBP) /* set the indexed-data pointer */
+ SBPB(rDL, Xdrive) /* save the boot drive */
+
+ /* VMware starts us at 7C0:0. Move to 0:7C00 */
+ PUSHR(rAX)
+ LWI(_nxt(SB), rAX)
+ PUSHR(rAX)
+ BYTE $0xCB /* FAR RET */
+
+TEXT _nxt(SB), $0
+ STI
+ LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
+ CALL16(BIOSputs(SB))
+
+ CALL16(dreset(SB))
+
+_jmp00:
+ LW(_volid(SB), rAX) /* Xrootlo */
+ LW(_volid+2(SB), rDX) /* Xroothi */
+
+ LWI(_magic+DIROFF(SB), rBX)
+ CALL16(BIOSread(SB)) /* read the root directory */
+
+ CALL16(printnl(SB))
+ LWI(_magic+DIROFF(SB), rBX)
+ LWI((512/2), rCX)
+ CALL16(printbuf(SB))
+
+xloop:
+ JMP xloop
+
+
+TEXT buggery(SB), $0
+ LWI(error(SB), rSI)
+ CALL16(BIOSputs(SB))
+
+TEXT quietbuggery(SB), $0
+xbuggery:
+ JMP xbuggery
+
+/*
+ * Read a sector from a disc. On entry:
+ * rDX:rAX sector number
+ * rES:rBX buffer address
+ * For BIOSCALL(0x13):
+ * rAH 0x02
+ * rAL number of sectors to read (1)
+ * rCH low 8 bits of cylinder
+ * rCL high 2 bits of cylinder (7-6), sector (5-0)
+ * rDH head
+ * rDL drive
+ * rES:rBX buffer address
+ */
+TEXT BIOSread(SB), $0
+ LWI(5, rDI) /* retry count (ATAPI ZIPs suck) */
+_retry:
+ PUSHA /* may be trashed by BIOSCALL */
+ PUSHR(rBX)
+
+ LW(_trksize(SB), rBX)
+ LW(_nheads(SB), rDI)
+ IMUL(rDI, rBX)
+ OR(rBX, rBX)
+ JZ _ioerror
+
+_okay:
+ DIV(rBX) /* cylinder -> rAX, track,sector -> rDX */
+
+ MW(rAX, rCX) /* save cylinder */
+ ROLI(0x08, rCX) /* swap rC[HL] */
+ SHLBI(0x06, rCL) /* move high bits up */
+
+ MW(rDX, rAX)
+ CLR(rDX)
+ LW(_trksize(SB), rBX)
+
+ DIV(rBX) /* head -> rAX, sector -> rDX */
+
+ INC(rDX) /* sector numbers are 1-based */
+ ANDI(0x003F, rDX) /* should not be necessary */
+ OR(rDX, rCX)
+
+ MW(rAX, rDX)
+ SHLI(0x08, rDX) /* form head */
+ LBPB(Xdrive, rDL) /* form drive */
+
+ POPR(rBX)
+ LWI(0x0201, rAX) /* form command and sectors */
+ BIOSCALL(0x13) /* CF set on failure */
+ JCC _BIOSreadret
+
+ POPA
+ DEC(rDI) /* too many retries? */
+ JEQ _ioerror
+
+ CALL16(dreset(SB))
+ JMP _retry
+
+_ioerror:
+ LWI(ioerror(SB), rSI)
+ CALL16(BIOSputs(SB))
+ JMP xbuggery
+
+_BIOSreadret:
+ POPA
+ RET
+
+TEXT dreset(SB), $0
+ PUSHA
+ CLR(rAX) /* rAH == 0 == reset disc system */
+ LBPB(Xdrive, rDL)
+ BIOSCALL(0x13)
+ ORB(rAH, rAH) /* status (0 == success) */
+ POPA
+ JNE _ioerror
+ RET
+
+TEXT printsharp(SB), $0
+ LWI(sharp(SB), rSI)
+_doprint:
+ CALL16(BIOSputs(SB))
+ RET
+
+TEXT printspace(SB), $0
+ LWI(space(SB), rSI)
+ JMP _doprint
+
+TEXT printnl(SB), $0
+ LWI(nl(SB), rSI)
+ JMP _doprint
+
+/*
+ * Output a string to the display.
+ * String argument is in rSI.
+ */
+TEXT BIOSputs(SB), $0
+ PUSHA
+ CLR(rBX)
+_BIOSputs:
+ LODSB
+ ORB(rAL, rAL)
+ JEQ _BIOSputsret
+
+ LBI(0x0E, rAH)
+ BIOSCALL(0x10)
+ JMP _BIOSputs
+
+_BIOSputsret:
+ POPA
+ RET
+
+/*
+ * Output a register to the display.
+ */
+TEXT printAX(SB), $0
+ PUSHW(rAX)
+ PUSHW(rBX)
+ PUSHW(rCX)
+ PUSHW(rDI)
+
+ LWI(4, rCX)
+ LWI(numbuf+4(SB), rSI)
+
+_nextchar:
+ DEC(rSI)
+ MW(rAX, rBX)
+ ANDI(0x000F, rBX)
+ ADDI(0x30, rBX) /* 0x30 = '0' */
+ CMPI(0x39, rBX) /* 0x39 = '9' */
+ JLE _dowrite
+ ADDI(0x07, rBX) /* 0x07 = 'A'-(1+'9')*/
+
+_dowrite:
+ SXB(rBL, 0, xSI)
+ SHRI(4, rAX)
+
+ DEC(rCX)
+ JNE _nextchar
+
+ LWI(numbuf(SB), rSI)
+ CALL16(BIOSputs(SB))
+
+ POPW(rDI)
+ POPW(rCX)
+ POPW(rBX)
+ POPW(rAX)
+
+ CALL16(printspace(SB))
+ RET
+
+TEXT printDXAX(SB), $0
+ PUSHW(rAX)
+ MW(rDX, rAX)
+ CALL16(printAX(SB))
+ POPW(rAX)
+ CALL16(printAX(SB))
+ RET
+
+TEXT printBX(SB), $0
+ PUSHW(rAX)
+ MW(rBX, rAX)
+ CALL16(printAX(SB))
+ POPW(rAX)
+ RET
+
+/*
+ * Output some number of words to the display
+ * rDS:rDI - buffer
+ * rCX: number of words
+ */
+TEXT printbuf(SB), $0
+ PUSHW(rAX)
+ PUSHW(rBX)
+ PUSHW(rCX)
+
+_nextword:
+ LXW(0, xBX, rAX)
+ CALL16(printAX(SB))
+ INC(rBX)
+ INC(rBX)
+ DEC(rCX)
+ JNE _nextword
+
+ POPW(rCX)
+ POPW(rBX)
+ POPW(rAX)
+ RET
+
+TEXT error(SB), $0
+ BYTE $'E';
+
+TEXT ioerror(SB), $0
+ BYTE $'I';
+
+TEXT nl(SB), $0
+ BYTE $'\r';
+ BYTE $'\n';
+ BYTE $'\z';
+
+TEXT numbuf(SB), $0
+ BYTE $'X'; BYTE $'X'; BYTE $'X'; BYTE $'X';
+ BYTE $'\z';
+
+TEXT space(SB), $0
+ BYTE $' ';
+ BYTE $'\z';
+
+TEXT sharp(SB), $0
+ BYTE $'#'; BYTE $'\z';
+
+TEXT confidence(SB), $0
+ BYTE $'P'; BYTE $'\z'
binary files /dev/null b/os/boot.original/pc/pbsdisklba differ
--- /dev/null
+++ b/os/boot.original/pc/pbsdisklba.s
@@ -1,0 +1,327 @@
+/*
+ * Debugging boot sector. Reads the first directory
+ * sector from disk and displays it.
+ *
+ * It relies on the _volid field in the FAT header containing
+ * the LBA of the root directory.
+ */
+#include "x16.h"
+
+#define DIROFF 0x00200 /* where to read the root directory (offset) */
+#define LOADSEG (0x10000/16) /* where to load code (64KB) */
+#define LOADOFF 0
+
+/*
+ * FAT directory entry.
+ */
+#define Dname 0x00
+#define Dext 0x08
+#define Dattr 0x0B
+#define Dtime 0x16
+#define Ddate 0x18
+#define Dstart 0x1A
+#define Dlengthlo 0x1C
+#define Dlengthhi 0x1E
+
+#define Dirsz 0x20
+
+/*
+ * We keep data on the stack, indexed by rBP.
+ */
+#define Xdrive 0x00 /* boot drive, passed by BIOS in rDL */
+#define Xrootlo 0x02 /* offset of root directory */
+#define Xroothi 0x04
+#define Xrootsz 0x06 /* file data area */
+#define Xtotal 0x08 /* sum of allocated data above */
+#define Xdap 0x00 /* disc address packet */
+
+TEXT _magic(SB), $0
+ BYTE $0xEB; BYTE $0x3C; /* jmp .+ 0x3C (_start0x3E) */
+ BYTE $0x90 /* nop */
+TEXT _version(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _sectsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _clustsize(SB), $0
+ BYTE $0x00
+TEXT _nresrv(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nfats(SB), $0
+ BYTE $0x00
+TEXT _rootsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _volsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _mediadesc(SB), $0
+ BYTE $0x00
+TEXT _fatsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _trksize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nheads(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nhiddenlo(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nhiddenhi(SB), $0
+ BYTE $0x00; BYTE $0x00;
+TEXT _bigvolsize(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _driveno(SB), $0
+ BYTE $0x00
+TEXT _reserved0(SB), $0
+ BYTE $0x00
+TEXT _bootsig(SB), $0
+ BYTE $0x00
+TEXT _volid(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _label(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+ BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _type(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+
+_start0x3E:
+ CLI
+ CLR(rAX)
+ MTSR(rAX, rSS) /* 0000 -> rSS */
+ MTSR(rAX, rDS) /* 0000 -> rDS, source segment */
+ MTSR(rAX, rES)
+ LWI(_magic-Xtotal(SB), rSP)
+ MW(rSP, rBP) /* set the indexed-data pointer */
+
+ SBPB(rDL, Xdrive) /* save the boot drive */
+
+ STI
+
+ LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
+ CALL(BIOSputs(SB))
+
+ LBI(0x41, rAH) /* check extensions present */
+ LWI(0x55AA, rBX)
+ LXB(Xdrive, xBP, rDL) /* drive */
+ SYSCALL(0x13) /* CF set on failure */
+ JCS _jmp01
+ CMPI(0xAA55, rBX)
+ JNE _jmp01
+ ANDI(0x0001, rCX)
+ JEQ _jmp01
+
+ /* rCX contains 0x0001 */
+ SBPWI(0x0010, Xdap+0) /* reserved + packet size */
+ SBPW(rCX, Xdap+2) /* reserved + # of blocks to transfer */
+
+ DEC(rCX)
+ SBPW(rCX, Xdap+12)
+ SBPW(rCX, Xdap+14)
+
+/* BIOSread will do this CALL(dreset(SB)) */
+
+_jmp00:
+ LW(_volid(SB), rAX) /* Xrootlo */
+ LW(_volid+2(SB), rDX) /* Xroothi */
+
+ LWI(_magic+DIROFF(SB), rBX)
+ CALL(BIOSread(SB)) /* read the root directory */
+
+ CALL(printnl(SB))
+ LWI(_magic+DIROFF(SB), rBX)
+ LWI((512/2), rCX)
+ CALL(printbuf(SB))
+
+xloop:
+ JMP xloop
+
+
+_jmp01:
+
+TEXT buggery(SB), $0
+ LWI(error(SB), rSI)
+ CALL(BIOSputs(SB))
+
+xbuggery:
+ JMP xbuggery
+
+/*
+ * Read a sector from a disc. On entry:
+ * rDX:rAX sector number
+ * rES:rBX buffer address
+ */
+TEXT BIOSread(SB), $0
+ LWI(5, rDI) /* retry count (ATAPI ZIPs suck) */
+_retry:
+ PUSHA /* may be trashed by SYSCALL */
+
+ SBPW(rBX, Xdap+4) /* transfer buffer :offset */
+ MFSR(rES, rDI) /* transfer buffer seg: */
+ SBPW(rDI, Xdap+6)
+ SBPW(rAX, Xdap+8) /* LBA (64-bits) */
+ SBPW(rDX, Xdap+10)
+
+ MW(rBP, rSI) /* disk address packet */
+ LBI(0x42, rAH) /* extended read */
+ LBPB(Xdrive, rDL) /* form drive */
+ SYSCALL(0x13) /* CF set on failure */
+ JCC _BIOSreadret
+
+ POPA
+ DEC(rDI) /* too many retries? */
+ JEQ _ioerror
+
+ CALL(dreset(SB))
+ JMP _retry
+
+_ioerror:
+ LWI(ioerror(SB), rSI)
+ CALL(BIOSputs(SB))
+ JMP xbuggery
+
+_BIOSreadret:
+ POPA
+ RET
+
+TEXT dreset(SB), $0
+ PUSHA
+ CLR(rAX) /* rAH == 0 == reset disc system */
+ LBPB(Xdrive, rDL)
+ SYSCALL(0x13)
+ ORB(rAH, rAH) /* status (0 == success) */
+ POPA
+ JNE _ioerror
+ RET
+
+
+TEXT printsharp(SB), $0
+ LWI(sharp(SB), rSI)
+_doprint:
+ CALL(BIOSputs(SB))
+ RET
+
+TEXT printspace(SB), $0
+ LWI(space(SB), rSI)
+ JMP _doprint
+
+TEXT printnl(SB), $0
+ LWI(nl(SB), rSI)
+ JMP _doprint
+
+/*
+ * Output a string to the display.
+ * String argument is in rSI.
+ */
+TEXT BIOSputs(SB), $0
+ PUSHA
+ CLR(rBX)
+_BIOSputs:
+ LODSB
+ ORB(rAL, rAL)
+ JEQ _BIOSputsret
+
+ LBI(0x0E, rAH)
+ SYSCALL(0x10)
+ JMP _BIOSputs
+
+_BIOSputsret:
+ POPA
+ RET
+
+/*
+ * Output a register to the display.
+ */
+TEXT printAX(SB), $0
+ PUSHW(rAX)
+ PUSHW(rBX)
+ PUSHW(rCX)
+ PUSHW(rDI)
+
+ LWI(4, rCX)
+ LWI(numbuf+4(SB), rSI)
+
+_nextchar:
+ DEC(rSI)
+ MW(rAX, rBX)
+ ANDI(0x000F, rBX)
+ ADDI(0x30, rBX) /* 0x30 = '0' */
+ CMPI(0x39, rBX) /* 0x39 = '9' */
+ JLE _dowrite
+ ADDI(0x07, rBX) /* 0x07 = 'A'-(1+'9')*/
+
+_dowrite:
+ SXB(rBL, 0, xSI)
+ SHRI(4, rAX)
+
+ DEC(rCX)
+ JNE _nextchar
+
+ LWI(numbuf(SB), rSI)
+ CALL(BIOSputs(SB))
+
+ POPW(rDI)
+ POPW(rCX)
+ POPW(rBX)
+ POPW(rAX)
+
+ CALL(printspace(SB))
+ RET
+
+TEXT printDXAX(SB), $0
+ PUSHW(rAX)
+ MW(rDX, rAX)
+ CALL(printAX(SB))
+ POPW(rAX)
+ CALL(printAX(SB))
+ RET
+
+TEXT printBX(SB), $0
+ PUSHW(rAX)
+ MW(rBX, rAX)
+ CALL(printAX(SB))
+ POPW(rAX)
+ RET
+
+/*
+ * Output some number of words to the display
+ * rDS:rDI - buffer
+ * rCX: number of words
+ */
+TEXT printbuf(SB), $0
+ PUSHW(rAX)
+ PUSHW(rBX)
+ PUSHW(rCX)
+
+_nextword:
+ LXW(0, xBX, rAX)
+ CALL(printAX(SB))
+ INC(rBX)
+ INC(rBX)
+ DEC(rCX)
+ JNE _nextword
+
+ POPW(rCX)
+ POPW(rBX)
+ POPW(rAX)
+ RET
+
+TEXT error(SB), $0
+ BYTE $'E';
+
+TEXT ioerror(SB), $0
+ BYTE $'I';
+
+TEXT nl(SB), $0
+ BYTE $'\r';
+ BYTE $'\n';
+ BYTE $'\z';
+
+TEXT numbuf(SB), $0
+ BYTE $'X'; BYTE $'X'; BYTE $'X'; BYTE $'X';
+ BYTE $'\z';
+
+TEXT space(SB), $0
+ BYTE $' ';
+ BYTE $'\z';
+
+TEXT sharp(SB), $0
+ BYTE $'#'; BYTE $'\z';
--- /dev/null
+++ b/os/boot.original/pc/pbslba.s
@@ -1,0 +1,363 @@
+/*
+ * FAT Partition Boot Sector. Loaded at 0x7C00:
+ * 8a pbslba.s; 8l -o pbslba -l -H3 -T0x7C00 pbslba.8
+ * Will load the target at LOADSEG*16+LOADOFF, so the target
+ * should be probably be loaded with LOADOFF added to the
+ * -Taddress.
+ * If LOADSEG is a multiple of 64KB and LOADOFF is 0 then
+ * targets larger than 64KB can be loaded.
+ *
+ * This code is uses Enhanced BIOS Services for Disc Drives and
+ * can be used with discs up to 137GB in capacity.
+ *
+ * It relies on the _volid field in the FAT header containing
+ * the LBA of the root directory.
+ */
+#include "x16.h"
+#include "mem.h"
+
+#define LOADSEG (0x10000/16) /* where to load code (64KB) */
+#define LOADOFF 0
+#define DIROFF 0x0200 /* where to read the root directory */
+
+/*
+ * FAT directory entry.
+ */
+#define Dname 0x00
+#define Dnamesz 0x0B
+#define Dext 0x08
+#define Dattr 0x0B
+#define Dtime 0x16
+#define Ddate 0x18
+#define Dstart 0x1A
+#define Dlengthlo 0x1C
+#define Dlengthhi 0x1E
+
+#define Dirsz 0x20
+
+/*
+ * Data is kept on the stack, indexed by rBP.
+ */
+#define Xdap 0x00 /* disc address packet */
+#define Xrootsz 0x10 /* file data area */
+#define Xdrive 0x12 /* boot drive, passed by BIOS or MBR */
+#define Xtotal 0x14 /* sum of allocated data above */
+
+TEXT _magic(SB), $0
+ BYTE $0xEB; BYTE $0x3C; /* jmp .+ 0x3C (_start0x3E) */
+ BYTE $0x90 /* nop */
+TEXT _version(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _sectsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _clustsize(SB), $0
+ BYTE $0x00
+TEXT _nresrv(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nfats(SB), $0
+ BYTE $0x00
+TEXT _rootsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _volsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _mediadesc(SB), $0
+ BYTE $0x00
+TEXT _fatsize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _trksize(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nheads(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nhiddenlo(SB), $0
+ BYTE $0x00; BYTE $0x00
+TEXT _nhiddenhi(SB), $0
+ BYTE $0x00; BYTE $0x00;
+TEXT _bigvolsize(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _driveno(SB), $0
+ BYTE $0x00
+TEXT _reserved0(SB), $0
+ BYTE $0x00
+TEXT _bootsig(SB), $0
+ BYTE $0x00
+TEXT _volid(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+TEXT _label(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
+ BYTE $0x00; BYTE $0x00; BYTE $0x00
+TEXT _type(SB), $0
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+ BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
+
+_start0x3E:
+ CLI
+ CLR(rAX)
+ MTSR(rAX, rSS) /* 0000 -> rSS */
+ MTSR(rAX, rDS) /* 0000 -> rDS, source segment */
+ MTSR(rAX, rES)
+ LWI(_magic-Xtotal(SB), rSP)
+ MW(rSP, rBP) /* set the indexed-data pointer */
+
+ SBPB(rDL, Xdrive) /* save the boot drive */
+
+ /* booting from a CD starts us at 7C0:0. Move to 0:7C00 */
+ PUSHR(rAX)
+ LWI(_nxt(SB), rAX)
+ PUSHR(rAX)
+ BYTE $0xCB /* FAR RET */
+
+TEXT _nxt(SB), $0
+ STI
+
+ LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */
+ CALL16(BIOSputs(SB))
+
+ LBI(0x41, rAH) /* check extensions present */
+ LWI(0x55AA, rBX)
+ LXB(Xdrive, xBP, rDL) /* drive */
+ BIOSCALL(0x13) /* CF set on failure */
+ JCS _jmp01
+ CMPI(0xAA55, rBX)
+ JNE _jmp01
+ ANDI(0x0001, rCX)
+ JEQ _jmp01
+
+ /* rCX contains 0x0001 */
+ SBPWI(0x0010, Xdap+0) /* reserved + packet size */
+ SBPW(rCX, Xdap+2) /* reserved + # of blocks to transfer */
+
+ DEC(rCX)
+ SBPW(rCX, Xdap+12)
+ SBPW(rCX, Xdap+14)
+
+ CALL16(dreset(SB))
+
+_jmp00:
+ LW(_volid(SB), rAX) /* Xrootlo */
+ LW(_volid+2(SB), rDX) /* Xroothi */
+
+ LWI(_magic+DIROFF(SB), rBX)
+ CALL16(BIOSread(SB)) /* read the root directory */
+
+ LWI((512/Dirsz), rBX)
+
+ LWI(_magic+DIROFF(SB), rDI) /* compare first directory entry */
+
+_cmp00:
+ PUSHR(rDI) /* save for later if it matches */
+ LWI(bootfile(SB), rSI)
+ LWI(Dnamesz, rCX)
+ REP
+ CMPSB
+ POPR(rDI)
+ JEQ _jmp02
+
+ DEC(rBX)
+ JEQ _jmp01
+
+ ADDI(Dirsz, rDI)
+ JMP _cmp00
+_jmp01:
+ CALL16(buggery(SB))
+
+_jmp02:
+ CLR(rBX) /* a handy value */
+ LW(_rootsize(SB), rAX) /* calculate and save Xrootsz */
+ LWI(Dirsz, rCX)
+ MUL(rCX)
+ LW(_sectsize(SB), rCX)
+ PUSHR(rCX)
+ DEC(rCX)
+ ADD(rCX, rAX)
+ ADC(rBX, rDX)
+ POPR(rCX) /* _sectsize(SB) */
+ DIV(rCX)
+ PUSHR(rAX) /* Xrootsz */
+
+ /*
+ * rDI points to the matching directory entry.
+ */
+ LXW(Dstart, xDI, rAX) /* starting sector address */
+ DEC(rAX) /* that's just the way it is */
+ DEC(rAX)
+ LB(_clustsize(SB), rCL)
+ CLRB(rCH)
+ MUL(rCX)
+ LW(_volid(SB), rCX) /* Xrootlo */
+ ADD(rCX, rAX)
+ LW(_volid+2(SB), rCX) /* Xroothi */
+ ADC(rCX, rDX)
+ POPR(rCX) /* Xrootsz */
+ ADD(rCX, rAX)
+ ADC(rBX, rDX)
+
+ PUSHR(rAX) /* calculate how many sectors to read */
+ PUSHR(rDX)
+ LXW(Dlengthlo, xDI, rAX)
+ LXW(Dlengthhi, xDI, rDX)
+ LW(_sectsize(SB), rCX)
+ PUSHR(rCX)
+ DEC(rCX)
+ ADD(rCX, rAX)
+ ADC(rBX, rDX)
+ POPR(rCX) /* _sectsize(SB) */
+ DIV(rCX)
+ MW(rAX, rCX)
+ POPR(rDX)
+ POPR(rAX)
+
+ LWI(LOADSEG, rBX) /* address to load into (seg+offset) */
+ MTSR(rBX, rES) /* seg */
+ LWI(LOADOFF, rBX) /* offset */
+
+_readboot:
+ CALL16(BIOSread(SB)) /* read the sector */
+
+ LW(_sectsize(SB), rDI) /* bump addresses/counts */
+ ADD(rDI, rBX)
+ JCC _incsecno
+
+ MFSR(rES, rDI) /* next 64KB segment */
+ ADDI(0x1000, rDI)
+ MTSR(rDI, rES)
+
+_incsecno:
+ CLR(rDI)
+ INC(rAX)
+ ADC(rDI, rDX)
+ LOOP _readboot
+
+ LWI(LOADSEG, rDI) /* set rDS for loaded code */
+ MTSR(rDI, rDS)
+ FARJUMP16(LOADSEG, LOADOFF) /* no deposit, no return */
+
+TEXT buggery(SB), $0
+ LWI(error(SB), rSI)
+ CALL16(BIOSputs(SB))
+
+_wait:
+ CLR(rAX) /* wait for almost any key */
+ BIOSCALL(0x16)
+
+_reset:
+ CLR(rBX) /* set ES segment for BIOS area */
+ MTSR(rBX, rES)
+
+ LWI(0x0472, rBX) /* warm-start code address */
+ LWI(0x1234, rAX) /* warm-start code */
+ POKEW /* MOVW AX, ES:[BX] */
+
+ FARJUMP16(0xFFFF, 0x0000) /* reset */
+
+
+/*
+ * Read a sector from a disc. On entry:
+ * rDX:rAX sector number
+ * rES:rBX buffer address
+ */
+TEXT BIOSread(SB), $0
+ LWI(5, rDI) /* retry count (ATAPI ZIPs suck) */
+_retry:
+ PUSHA /* may be trashed by BIOSCALL */
+
+ SBPW(rBX, Xdap+4) /* transfer buffer :offset */
+ MFSR(rES, rDI) /* transfer buffer seg: */
+ SBPW(rDI, Xdap+6)
+ SBPW(rAX, Xdap+8) /* LBA (64-bits) */
+ SBPW(rDX, Xdap+10)
+
+ MW(rBP, rSI) /* disk address packet */
+ LBI(0x42, rAH) /* extended read */
+ LBPB(Xdrive, rDL) /* form drive */
+ BIOSCALL(0x13) /* CF set on failure */
+ JCC _BIOSreadret
+
+ POPA
+ DEC(rDI) /* too many retries? */
+ JEQ _ioerror
+
+ CALL16(dreset(SB))
+ JMP _retry
+
+_ioerror:
+ LWI(ioerror(SB), rSI)
+ CALL16(BIOSputs(SB))
+ JMP _wait
+
+_BIOSreadret:
+ POPA
+ RET
+
+TEXT dreset(SB), $0
+ PUSHA
+ CLR(rAX) /* rAH == 0 == reset disc system */
+ LBPB(Xdrive, rDL)
+ BIOSCALL(0x13)
+ ORB(rAH, rAH) /* status (0 == success) */
+ POPA
+ JNE _ioerror
+ RET
+
+/*
+ * Output a string to the display.
+ * String argument is in rSI.
+ */
+TEXT BIOSputs(SB), $0
+ PUSHA
+ CLR(rBX)
+_BIOSputs:
+ LODSB
+ ORB(rAL, rAL)
+ JEQ _BIOSputsret
+
+ LBI(0x0E, rAH)
+ BIOSCALL(0x10)
+ JMP _BIOSputs
+
+_BIOSputsret:
+ POPA
+ RET
+
+/* "Bad format or I/O error\r\nPress almost any key to reboot..." */
+TEXT error(SB), $0
+ BYTE $'B'; BYTE $'a'; BYTE $'d'; BYTE $' ';
+ BYTE $'f'; BYTE $'o'; BYTE $'r'; BYTE $'m';
+ BYTE $'a'; BYTE $'t'; BYTE $' '; BYTE $'o';
+ BYTE $'r'; BYTE $' ';
+/* "I/O error\r\nPress almost any key to reboot..." */
+TEXT ioerror(SB), $0
+ BYTE $'I'; BYTE $'/'; BYTE $'O'; BYTE $' ';
+ BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $'o';
+ BYTE $'r'; BYTE $'\r';BYTE $'\n';
+ BYTE $'P'; BYTE $'r'; BYTE $'e'; BYTE $'s';
+ BYTE $'s'; BYTE $' '; BYTE $'a'; BYTE $' ';
+ BYTE $'k'; BYTE $'e'; BYTE $'y';
+ BYTE $' '; BYTE $'t'; BYTE $'o'; BYTE $' ';
+ BYTE $'r'; BYTE $'e'; BYTE $'b'; BYTE $'o';
+ BYTE $'o'; BYTE $'t';
+ BYTE $'.'; BYTE $'.'; BYTE $'.';
+ BYTE $'\z';
+
+#ifdef USEBCOM
+/* "B COM" */
+TEXT bootfile(SB), $0
+ BYTE $'B'; BYTE $' '; BYTE $' '; BYTE $' ';
+ BYTE $' '; BYTE $' '; BYTE $' '; BYTE $' ';
+ BYTE $'C'; BYTE $'O'; BYTE $'M';
+ BYTE $'\z';
+#else
+/* "9LOAD " */
+TEXT bootfile(SB), $0
+ BYTE $'9'; BYTE $'L'; BYTE $'O'; BYTE $'A';
+ BYTE $'D'; BYTE $' '; BYTE $' '; BYTE $' ';
+ BYTE $' '; BYTE $' '; BYTE $' ';
+ BYTE $'\z';
+#endif /* USEBCOM */
+
+/* "PBS..." */
+TEXT confidence(SB), $0
+ BYTE $'P'; BYTE $'B'; BYTE $'S'; BYTE $'2';
+ BYTE $'.'; BYTE $'.'; BYTE $'.';
+ BYTE $'\z';
--- /dev/null
+++ b/os/boot.original/pc/pci.c
@@ -1,0 +1,1002 @@
+/*
+ * PCI support code.
+ * To do:
+ * initialise bridge mappings if the PCI BIOS didn't.
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "error.h"
+
+enum { /* configuration mechanism #1 */
+ PciADDR = 0xCF8, /* CONFIG_ADDRESS */
+ PciDATA = 0xCFC, /* CONFIG_DATA */
+
+ /* configuration mechanism #2 */
+ PciCSE = 0xCF8, /* configuration space enable */
+ PciFORWARD = 0xCFA, /* which bus */
+
+ MaxFNO = 7,
+ MaxUBN = 255,
+};
+
+enum
+{ /* command register */
+ IOen = (1<<0),
+ MEMen = (1<<1),
+ MASen = (1<<2),
+ MemWrInv = (1<<4),
+ PErrEn = (1<<6),
+ SErrEn = (1<<8),
+};
+
+static Lock pcicfglock;
+static Lock pcicfginitlock;
+static int pcicfgmode = -1;
+static int pcimaxbno = 7;
+static int pcimaxdno;
+static Pcidev* pciroot;
+static Pcidev* pcilist;
+static Pcidev* pcitail;
+
+static int pcicfgrw32(int, int, int, int);
+static int pcicfgrw8(int, int, int, int);
+
+ulong
+pcibarsize(Pcidev *p, int rno)
+{
+ ulong v, size;
+
+ v = pcicfgrw32(p->tbdf, rno, 0, 1);
+ pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
+ size = pcicfgrw32(p->tbdf, rno, 0, 1);
+ if(v & 1)
+ size |= 0xFFFF0000;
+ pcicfgrw32(p->tbdf, rno, v, 0);
+
+ return -(size & ~0x0F);
+}
+
+int
+pciscan(int bno, Pcidev** list)
+{
+ Pcidev *p, *head, *tail;
+ int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
+
+ maxubn = bno;
+ head = nil;
+ tail = nil;
+ for(dno = 0; dno <= pcimaxdno; dno++){
+ maxfno = 0;
+ for(fno = 0; fno <= maxfno; fno++){
+ /*
+ * For this possible device, form the
+ * bus+device+function triplet needed to address it
+ * and try to read the vendor and device ID.
+ * If successful, allocate a device struct and
+ * start to fill it in with some useful information
+ * from the device's configuration space.
+ */
+ tbdf = MKBUS(BusPCI, bno, dno, fno);
+ l = pcicfgrw32(tbdf, PciVID, 0, 1);
+ if(l == 0xFFFFFFFF || l == 0)
+ continue;
+ p = malloc(sizeof(*p));
+ p->tbdf = tbdf;
+ p->vid = l;
+ p->did = l>>16;
+
+ if(pcilist != nil)
+ pcitail->list = p;
+ else
+ pcilist = p;
+ pcitail = p;
+
+ p->rid = pcicfgr8(p, PciRID);
+ p->ccrp = pcicfgr8(p, PciCCRp);
+ p->ccru = pcicfgr8(p, PciCCRu);
+ p->ccrb = pcicfgr8(p, PciCCRb);
+ p->pcr = pcicfgr32(p, PciPCR);
+
+ p->intl = pcicfgr8(p, PciINTL);
+
+ /*
+ * If the device is a multi-function device adjust the
+ * loop count so all possible functions are checked.
+ */
+ hdt = pcicfgr8(p, PciHDT);
+ if(hdt & 0x80)
+ maxfno = MaxFNO;
+
+ /*
+ * If appropriate, read the base address registers
+ * and work out the sizes.
+ */
+ switch(p->ccrb){
+
+ case 0x01: /* mass storage controller */
+ case 0x02: /* network controller */
+ case 0x03: /* display controller */
+ case 0x04: /* multimedia device */
+ case 0x07: /* simple comm. controllers */
+ case 0x08: /* base system peripherals */
+ case 0x09: /* input devices */
+ case 0x0A: /* docking stations */
+ case 0x0B: /* processors */
+ case 0x0C: /* serial bus controllers */
+ if((hdt & 0x7F) != 0)
+ break;
+ rno = PciBAR0 - 4;
+ for(i = 0; i < nelem(p->mem); i++){
+ rno += 4;
+ p->mem[i].bar = pcicfgr32(p, rno);
+ p->mem[i].size = pcibarsize(p, rno);
+ }
+ break;
+
+ case 0x00:
+ case 0x05: /* memory controller */
+ case 0x06: /* bridge device */
+ default:
+ break;
+ }
+
+ if(head != nil)
+ tail->link = p;
+ else
+ head = p;
+ tail = p;
+ }
+ }
+
+ *list = head;
+ for(p = head; p != nil; p = p->link){
+ /*
+ * Find PCI-PCI and PCI-Cardbus bridges
+ * and recursively descend the tree.
+ */
+ if(p->ccrb != 0x06 || p->ccru != 0x04)
+ continue;
+
+ /*
+ * If the secondary or subordinate bus number is not
+ * initialised try to do what the PCI BIOS should have
+ * done and fill in the numbers as the tree is descended.
+ * On the way down the subordinate bus number is set to
+ * the maximum as it's not known how many buses are behind
+ * this one; the final value is set on the way back up.
+ */
+ ubn = pcicfgr8(p, PciUBN);
+ sbn = pcicfgr8(p, PciSBN);
+
+ if(sbn == 0 || ubn == 0){
+ sbn = maxubn+1;
+ /*
+ * Make sure memory, I/O and master enables are
+ * off, set the primary, secondary and subordinate
+ * bus numbers and clear the secondary status before
+ * attempting to scan the secondary bus.
+ *
+ * Initialisation of the bridge should be done here.
+ */
+ pcicfgw32(p, PciPCR, 0xFFFF0000);
+ l = (MaxUBN<<16)|(sbn<<8)|bno;
+ pcicfgw32(p, PciPBN, l);
+ pcicfgw16(p, PciSPSR, 0xFFFF);
+ maxubn = pciscan(sbn, &p->bridge);
+ l = (maxubn<<16)|(sbn<<8)|bno;
+
+ pcicfgw32(p, PciPBN, l);
+ }
+ else{
+ /*
+ * You can't go back.
+ * This shouldn't be possible, but the
+ * Iwill DK8-HTX seems to have subordinate
+ * bus numbers which get smaller on the
+ * way down. Need to look more closely at
+ * this.
+ */
+ if(ubn > maxubn)
+ maxubn = ubn;
+ pciscan(sbn, &p->bridge);
+ }
+ }
+
+ return maxubn;
+}
+
+static uchar
+null_link(Pcidev *, uchar )
+{
+ return 0;
+}
+
+static void
+null_init(Pcidev *, uchar , uchar )
+{
+}
+
+static uchar
+pIIx_link(Pcidev *router, uchar link)
+{
+ uchar pirq;
+
+ /* link should be 0x60, 0x61, 0x62, 0x63 */
+ pirq = pcicfgr8(router, link);
+ return (pirq < 16)? pirq: 0;
+}
+
+static void
+pIIx_init(Pcidev *router, uchar link, uchar irq)
+{
+ pcicfgw8(router, link, irq);
+}
+
+static uchar
+via_link(Pcidev *router, uchar link)
+{
+ uchar pirq;
+
+ /* link should be 1, 2, 3, 5 */
+ pirq = (link < 6)? pcicfgr8(router, 0x55 + (link>>1)): 0;
+
+ return (link & 1)? (pirq >> 4): (pirq & 15);
+}
+
+static void
+via_init(Pcidev *router, uchar link, uchar irq)
+{
+ uchar pirq;
+
+ pirq = pcicfgr8(router, 0x55 + (link >> 1));
+ pirq &= (link & 1)? 0x0f: 0xf0;
+ pirq |= (link & 1)? (irq << 4): (irq & 15);
+ pcicfgw8(router, 0x55 + (link>>1), pirq);
+}
+
+static uchar
+opti_link(Pcidev *router, uchar link)
+{
+ uchar pirq = 0;
+
+ /* link should be 0x02, 0x12, 0x22, 0x32 */
+ if ((link & 0xcf) == 0x02)
+ pirq = pcicfgr8(router, 0xb8 + (link >> 5));
+ return (link & 0x10)? (pirq >> 4): (pirq & 15);
+}
+
+static void
+opti_init(Pcidev *router, uchar link, uchar irq)
+{
+ uchar pirq;
+
+ pirq = pcicfgr8(router, 0xb8 + (link >> 5));
+ pirq &= (link & 0x10)? 0x0f : 0xf0;
+ pirq |= (link & 0x10)? (irq << 4): (irq & 15);
+ pcicfgw8(router, 0xb8 + (link >> 5), pirq);
+}
+
+static uchar
+ali_link(Pcidev *router, uchar link)
+{
+ /* No, you're not dreaming */
+ static const uchar map[] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+ uchar pirq;
+
+ /* link should be 0x01..0x08 */
+ pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
+ return (link & 1)? map[pirq&15]: map[pirq>>4];
+}
+
+static void
+ali_init(Pcidev *router, uchar link, uchar irq)
+{
+ /* Inverse of map in ali_link */
+ static const uchar map[] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
+ uchar pirq;
+
+ pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
+ pirq &= (link & 1)? 0x0f: 0xf0;
+ pirq |= (link & 1)? (map[irq] << 4): (map[irq] & 15);
+ pcicfgw8(router, 0x48 + ((link-1)>>1), pirq);
+}
+
+static uchar
+cyrix_link(Pcidev *router, uchar link)
+{
+ uchar pirq;
+
+ /* link should be 1, 2, 3, 4 */
+ pirq = pcicfgr8(router, 0x5c + ((link-1)>>1));
+ return ((link & 1)? pirq >> 4: pirq & 15);
+}
+
+static void
+cyrix_init(Pcidev *router, uchar link, uchar irq)
+{
+ uchar pirq;
+
+ pirq = pcicfgr8(router, 0x5c + (link>>1));
+ pirq &= (link & 1)? 0x0f: 0xf0;
+ pirq |= (link & 1)? (irq << 4): (irq & 15);
+ pcicfgw8(router, 0x5c + (link>>1), pirq);
+}
+
+typedef struct {
+ ushort sb_vid, sb_did;
+ uchar (*sb_translate)(Pcidev *, uchar);
+ void (*sb_initialize)(Pcidev *, uchar, uchar);
+} bridge_t;
+
+static bridge_t southbridges[] = {
+ { 0x8086, 0x122e, pIIx_link, pIIx_init }, // Intel 82371FB
+ { 0x8086, 0x1234, pIIx_link, pIIx_init }, // Intel 82371MX
+ { 0x8086, 0x7000, pIIx_link, pIIx_init }, // Intel 82371SB
+ { 0x8086, 0x7110, pIIx_link, pIIx_init }, // Intel 82371AB
+ { 0x8086, 0x7198, pIIx_link, pIIx_init }, // Intel 82443MX (fn 1)
+ { 0x8086, 0x2410, pIIx_link, pIIx_init }, // Intel 82801AA
+ { 0x8086, 0x2420, pIIx_link, pIIx_init }, // Intel 82801AB
+ { 0x8086, 0x2440, pIIx_link, pIIx_init }, // Intel 82801BA
+ { 0x8086, 0x244c, pIIx_link, pIIx_init }, // Intel 82801BAM
+ { 0x8086, 0x2480, pIIx_link, pIIx_init }, // Intel 82801CA
+ { 0x8086, 0x248c, pIIx_link, pIIx_init }, // Intel 82801CAM
+ { 0x8086, 0x24c0, pIIx_link, pIIx_init }, // Intel 82801DBL
+ { 0x8086, 0x24cc, pIIx_link, pIIx_init }, // Intel 82801DBM
+ { 0x8086, 0x24d0, pIIx_link, pIIx_init }, // Intel 82801EB
+ { 0x8086, 0x2640, pIIx_link, pIIx_init }, // Intel 82801FB
+ { 0x8086, 0x27b8, pIIx_link, pIIx_init }, // Intel 82801GB
+ { 0x8086, 0x27b9, pIIx_link, pIIx_init }, // Intel 82801GBM
+ { 0x1106, 0x0586, via_link, via_init }, // Viatech 82C586
+ { 0x1106, 0x0596, via_link, via_init }, // Viatech 82C596
+ { 0x1106, 0x0686, via_link, via_init }, // Viatech 82C686
+ { 0x1106, 0x3227, via_link, via_init }, // Viatech VT8237
+ { 0x1045, 0xc700, opti_link, opti_init }, // Opti 82C700
+ { 0x10b9, 0x1533, ali_link, ali_init }, // Al M1533
+ { 0x1039, 0x0008, pIIx_link, pIIx_init }, // SI 503
+ { 0x1039, 0x0496, pIIx_link, pIIx_init }, // SI 496
+ { 0x1078, 0x0100, cyrix_link, cyrix_init }, // Cyrix 5530 Legacy
+
+ { 0x1002, 0x4377, nil, nil }, // ATI Radeon Xpress 200M
+ { 0x1002, 0x4372, nil, nil }, // ATI SB400
+ { 0x1022, 0x746B, nil, nil }, // AMD 8111
+ { 0x10DE, 0x00D1, nil, nil }, // NVIDIA nForce 3
+ { 0x10DE, 0x00E0, nil, nil }, // NVIDIA nForce 3 250 Series
+ { 0x1166, 0x0200, nil, nil }, // ServerWorks ServerSet III LE
+};
+
+typedef struct {
+ uchar e_bus; // Pci bus number
+ uchar e_dev; // Pci device number
+ uchar e_maps[12]; // Avoid structs! Link and mask.
+ uchar e_slot; // Add-in/built-in slot
+ uchar e_reserved;
+} slot_t;
+
+typedef struct {
+ uchar rt_signature[4]; // Routing table signature
+ uchar rt_version[2]; // Version number
+ uchar rt_size[2]; // Total table size
+ uchar rt_bus; // Interrupt router bus number
+ uchar rt_devfn; // Router's devfunc
+ uchar rt_pciirqs[2]; // Exclusive PCI irqs
+ uchar rt_compat[4]; // Compatible PCI interrupt router
+ uchar rt_miniport[4]; // Miniport data
+ uchar rt_reserved[11];
+ uchar rt_checksum;
+} router_t;
+
+static ushort pciirqs; // Exclusive PCI irqs
+static bridge_t *southbridge; // Which southbridge to use.
+
+static void
+pcirouting(void)
+{
+ uchar *p, pin, irq;
+ ulong tbdf, vdid;
+ ushort vid, did;
+ router_t *r;
+ slot_t *e;
+ int size, i, fn;
+ Pcidev *sbpci, *pci;
+
+ // Peek in the BIOS
+ for (p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16)
+ if (p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R')
+ break;
+
+ if (p >= (uchar *)KADDR(0xfffff))
+ return;
+
+ r = (router_t *)p;
+
+ // print("PCI interrupt routing table version %d.%d at %.6uX\n",
+ // r->rt_version[0], r->rt_version[1], (ulong)r & 0xfffff);
+
+ tbdf = (BusPCI << 24)|(r->rt_bus << 16)|(r->rt_devfn << 8);
+ vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
+ vid = vdid;
+ did = vdid >> 16;
+
+ for (i = 0; i != nelem(southbridges); i++)
+ if (vid == southbridges[i].sb_vid && did == southbridges[i].sb_did)
+ break;
+
+ if (i == nelem(southbridges)) {
+ print("pcirouting: South bridge %.4uX, %.4uX not found\n", vid, did);
+ return;
+ }
+ southbridge = &southbridges[i];
+
+ if ((sbpci = pcimatch(nil, vid, did)) == nil) {
+ print("pcirouting: Cannot match south bridge %.4uX, %.4uX\n",
+ vid, did);
+ return;
+ }
+
+ pciirqs = (r->rt_pciirqs[1] << 8)|r->rt_pciirqs[0];
+
+ size = (r->rt_size[1] << 8)|r->rt_size[0];
+ for (e = (slot_t *)&r[1]; (uchar *)e < p + size; e++) {
+ // print("%.2uX/%.2uX %.2uX: ", e->e_bus, e->e_dev, e->e_slot);
+ // for (i = 0; i != 4; i++) {
+ // uchar *m = &e->e_maps[i * 3];
+ // print("[%d] %.2uX %.4uX ",
+ // i, m[0], (m[2] << 8)|m[1]);
+ // }
+ // print("\n");
+
+ for (fn = 0; fn != 8; fn++) {
+ uchar *m;
+
+ // Retrieve the did and vid through the devfn before
+ // obtaining the Pcidev structure.
+ tbdf = (BusPCI << 24)|(e->e_bus << 16)|((e->e_dev | fn) << 8);
+ vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
+ if (vdid == 0xFFFFFFFF || vdid == 0)
+ continue;
+
+ vid = vdid;
+ did = vdid >> 16;
+
+ pci = nil;
+ while ((pci = pcimatch(pci, vid, did)) != nil) {
+
+ if (pci->intl != 0 && pci->intl != 0xFF)
+ continue;
+
+ pin = pcicfgr8(pci, PciINTP);
+ if (pin == 0 || pin == 0xff)
+ continue;
+
+ m = &e->e_maps[(pin - 1) * 3];
+ irq = southbridge->sb_translate(sbpci, m[0]);
+ if (irq) {
+ print("pcirouting: %.4uX/%.4uX at pin %d irq %d\n",
+ vid, did, pin, irq);
+ pcicfgw8(pci, PciINTL, irq);
+ pci->intl = irq;
+ }
+ }
+ }
+ }
+}
+
+static void
+pcicfginit(void)
+{
+ char *p;
+ int bno, n;
+ Pcidev **list;
+
+ lock(&pcicfginitlock);
+ if(pcicfgmode != -1)
+ goto out;
+
+ /*
+ * Try to determine which PCI configuration mode is implemented.
+ * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
+ * a DWORD at 0xCF8 and another at 0xCFC and will pass through
+ * any non-DWORD accesses as normal I/O cycles. There shouldn't be
+ * a device behind these addresses so if Mode1 accesses fail try
+ * for Mode2 (Mode2 is deprecated).
+ */
+
+ /*
+ * Bits [30:24] of PciADDR must be 0,
+ * according to the spec.
+ */
+ n = inl(PciADDR);
+ if(!(n & 0x7FF00000)){
+ outl(PciADDR, 0x80000000);
+ outb(PciADDR+3, 0);
+ if(inl(PciADDR) & 0x80000000){
+ pcicfgmode = 1;
+ pcimaxdno = 31;
+ }
+ }
+ outl(PciADDR, n);
+
+ if(pcicfgmode < 0){
+ /*
+ * The 'key' part of PciCSE should be 0.
+ */
+ n = inb(PciCSE);
+ if(!(n & 0xF0)){
+ outb(PciCSE, 0x0E);
+ if(inb(PciCSE) == 0x0E){
+ pcicfgmode = 2;
+ pcimaxdno = 15;
+ }
+ }
+ outb(PciCSE, n);
+ }
+
+ if(pcicfgmode < 0)
+ goto out;
+
+
+ if(p = getconf("*pcimaxbno"))
+ pcimaxbno = strtoul(p, 0, 0);
+ if(p = getconf("*pcimaxdno"))
+ pcimaxdno = strtoul(p, 0, 0);
+
+ list = &pciroot;
+ for(bno = 0; bno <= pcimaxbno; bno++) {
+ bno = pciscan(bno, list);
+ while(*list)
+ list = &(*list)->link;
+ }
+
+ pcirouting();
+
+out:
+ unlock(&pcicfginitlock);
+
+ if(getconf("*pcihinv"))
+ pcihinv(nil);
+}
+
+
+static int
+pcicfgrw8(int tbdf, int rno, int data, int read)
+{
+ int o, type, x;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(BUSBNO(tbdf))
+ type = 0x01;
+ else
+ type = 0x00;
+ x = -1;
+ if(BUSDNO(tbdf) > pcimaxdno)
+ return x;
+
+ lock(&pcicfglock);
+ switch(pcicfgmode){
+
+ case 1:
+ o = rno & 0x03;
+ rno &= ~0x03;
+ outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+ if(read)
+ x = inb(PciDATA+o);
+ else
+ outb(PciDATA+o, data);
+ outl(PciADDR, 0);
+ break;
+
+ case 2:
+ outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
+ outb(PciFORWARD, BUSBNO(tbdf));
+ if(read)
+ x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
+ else
+ outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
+ outb(PciCSE, 0);
+ break;
+ }
+ unlock(&pcicfglock);
+
+ return x;
+}
+
+int
+pcicfgr8(Pcidev* pcidev, int rno)
+{
+ return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw8(Pcidev* pcidev, int rno, int data)
+{
+ pcicfgrw8(pcidev->tbdf, rno, data, 0);
+}
+
+static int
+pcicfgrw16(int tbdf, int rno, int data, int read)
+{
+ int o, type, x;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(BUSBNO(tbdf))
+ type = 0x01;
+ else
+ type = 0x00;
+ x = -1;
+ if(BUSDNO(tbdf) > pcimaxdno)
+ return x;
+
+ lock(&pcicfglock);
+ switch(pcicfgmode){
+
+ case 1:
+ o = rno & 0x02;
+ rno &= ~0x03;
+ outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+ if(read)
+ x = ins(PciDATA+o);
+ else
+ outs(PciDATA+o, data);
+ outl(PciADDR, 0);
+ break;
+
+ case 2:
+ outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
+ outb(PciFORWARD, BUSBNO(tbdf));
+ if(read)
+ x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
+ else
+ outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
+ outb(PciCSE, 0);
+ break;
+ }
+ unlock(&pcicfglock);
+
+ return x;
+}
+
+int
+pcicfgr16(Pcidev* pcidev, int rno)
+{
+ return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw16(Pcidev* pcidev, int rno, int data)
+{
+ pcicfgrw16(pcidev->tbdf, rno, data, 0);
+}
+
+static int
+pcicfgrw32(int tbdf, int rno, int data, int read)
+{
+ int type, x;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(BUSBNO(tbdf))
+ type = 0x01;
+ else
+ type = 0x00;
+ x = -1;
+ if(BUSDNO(tbdf) > pcimaxdno)
+ return x;
+
+ lock(&pcicfglock);
+ switch(pcicfgmode){
+
+ case 1:
+ rno &= ~0x03;
+ outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
+ if(read)
+ x = inl(PciDATA);
+ else
+ outl(PciDATA, data);
+ outl(PciADDR, 0);
+ break;
+
+ case 2:
+ outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
+ outb(PciFORWARD, BUSBNO(tbdf));
+ if(read)
+ x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
+ else
+ outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
+ outb(PciCSE, 0);
+ break;
+ }
+ unlock(&pcicfglock);
+
+ return x;
+}
+
+int
+pcicfgr32(Pcidev* pcidev, int rno)
+{
+ return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
+}
+
+void
+pcicfgw32(Pcidev* pcidev, int rno, int data)
+{
+ pcicfgrw32(pcidev->tbdf, rno, data, 0);
+}
+
+Pcidev*
+pcimatch(Pcidev* prev, int vid, int did)
+{
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(prev == nil)
+ prev = pcilist;
+ else
+ prev = prev->list;
+
+ while(prev != nil) {
+ if((vid == 0 || prev->vid == vid)
+ && (did == 0 || prev->did == did))
+ break;
+ prev = prev->list;
+ }
+ return prev;
+}
+
+uchar
+pciipin(Pcidev *pci, uchar pin)
+{
+ if (pci == nil)
+ pci = pcilist;
+
+ while (pci) {
+ uchar intl;
+
+ if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
+ return pci->intl;
+
+ if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
+ return intl;
+
+ pci = pci->list;
+ }
+ return 0;
+}
+
+static ushort
+pciimask(Pcidev *pci)
+{
+ ushort imask;
+
+ imask = 0;
+ while (pci) {
+ if (pcicfgr8(pci, PciINTP) && pci->intl < 16)
+ imask |= 1 << pci->intl;
+
+ if (pci->bridge)
+ imask |= pciimask(pci->bridge);
+
+ pci = pci->list;
+ }
+ return imask;
+}
+
+uchar
+pciintl(Pcidev *pci)
+{
+ ushort imask;
+ int i;
+
+ if (pci == nil)
+ pci = pcilist;
+
+ imask = pciimask(pci) | 1;
+ for (i = 0; i != 16; i++)
+ if ((imask & (1 << i)) == 0)
+ return i;
+ return 0;
+}
+
+void
+pcihinv(Pcidev* p)
+{
+ int i;
+ Pcidev *t;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ if(p == nil) {
+ p = pciroot;
+ print("bus dev type vid did intl memory\n");
+ }
+ for(t = p; t != nil; t = t->link) {
+ print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ",
+ BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
+ t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
+
+ for(i = 0; i < nelem(p->mem); i++) {
+ if(t->mem[i].size == 0)
+ continue;
+ print("%d:%.8lux %d ", i,
+ t->mem[i].bar, t->mem[i].size);
+ }
+ print("\n");
+ }
+ while(p != nil) {
+ if(p->bridge != nil)
+ pcihinv(p->bridge);
+ p = p->link;
+ }
+}
+
+void
+pcireset(void)
+{
+ Pcidev *p;
+ int pcr;
+
+ if(pcicfgmode == -1)
+ pcicfginit();
+
+ for(p = pcilist; p != nil; p = p->list){
+ pcr = pcicfgr16(p, PciPSR);
+ pcicfgw16(p, PciPSR, pcr & ~0x04);
+ }
+}
+
+void
+pcisetioe(Pcidev* p)
+{
+ p->pcr |= IOen;
+ pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pciclrioe(Pcidev* p)
+{
+ p->pcr &= ~IOen;
+ pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pcisetbme(Pcidev* p)
+{
+ p->pcr |= MASen;
+ pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pciclrbme(Pcidev* p)
+{
+ p->pcr &= ~MASen;
+ pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pcisetmwi(Pcidev* p)
+{
+ p->pcr |= MemWrInv;
+ pcicfgw16(p, PciPCR, p->pcr);
+}
+
+void
+pciclrmwi(Pcidev* p)
+{
+ p->pcr &= ~MemWrInv;
+ pcicfgw16(p, PciPCR, p->pcr);
+}
+
+static int
+pcigetpmrb(Pcidev* p)
+{
+ int ptr;
+
+ if(p->pmrb != 0)
+ return p->pmrb;
+ p->pmrb = -1;
+
+ /*
+ * If there are no extended capabilities implemented,
+ * (bit 4 in the status register) assume there's no standard
+ * power management method.
+ * Find the capabilities pointer based on PCI header type.
+ */
+ if(!(pcicfgr16(p, PciPSR) & 0x0010))
+ return -1;
+ switch(pcicfgr8(p, PciHDT)){
+ default:
+ return -1;
+ case 0: /* all other */
+ case 1: /* PCI to PCI bridge */
+ ptr = 0x34;
+ break;
+ case 2: /* CardBus bridge */
+ ptr = 0x14;
+ break;
+ }
+ ptr = pcicfgr32(p, ptr);
+
+ while(ptr != 0){
+ /*
+ * Check for validity.
+ * Can't be in standard header and must be double
+ * word aligned.
+ */
+ if(ptr < 0x40 || (ptr & ~0xFC))
+ return -1;
+ if(pcicfgr8(p, ptr) == 0x01){
+ p->pmrb = ptr;
+ return ptr;
+ }
+
+ ptr = pcicfgr8(p, ptr+1);
+ }
+
+ return -1;
+}
+
+int
+pcigetpms(Pcidev* p)
+{
+ int pmcsr, ptr;
+
+ if((ptr = pcigetpmrb(p)) == -1)
+ return -1;
+
+ /*
+ * Power Management Register Block:
+ * offset 0: Capability ID
+ * 1: next item pointer
+ * 2: capabilities
+ * 4: control/status
+ * 6: bridge support extensions
+ * 7: data
+ */
+ pmcsr = pcicfgr16(p, ptr+4);
+
+ return pmcsr & 0x0003;
+}
+
+int
+pcisetpms(Pcidev* p, int state)
+{
+ int ostate, pmc, pmcsr, ptr;
+
+ if((ptr = pcigetpmrb(p)) == -1)
+ return -1;
+
+ pmc = pcicfgr16(p, ptr+2);
+ pmcsr = pcicfgr16(p, ptr+4);
+ ostate = pmcsr & 0x0003;
+ pmcsr &= ~0x0003;
+
+ switch(state){
+ default:
+ return -1;
+ case 0:
+ break;
+ case 1:
+ if(!(pmc & 0x0200))
+ return -1;
+ break;
+ case 2:
+ if(!(pmc & 0x0400))
+ return -1;
+ break;
+ case 3:
+ break;
+ }
+ pmcsr |= state;
+ pcicfgw16(p, ptr+4, pmcsr);
+
+ return ostate;
+}
--- /dev/null
+++ b/os/boot.original/pc/print.c
@@ -1,0 +1,31 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+static Lock fmtl;
+
+void
+_fmtlock(void)
+{
+ lock(&fmtl);
+}
+
+void
+_fmtunlock(void)
+{
+ unlock(&fmtl);
+}
+
+int
+_efgfmt(Fmt*)
+{
+ return -1;
+}
+
+int
+errfmt(Fmt*)
+{
+ return -1;
+}
--- /dev/null
+++ b/os/boot.original/pc/queue.c
@@ -1,0 +1,44 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+int
+qgetc(IOQ *q)
+{
+ int c;
+
+ if(q->in == q->out)
+ return -1;
+ c = *q->out;
+ if(q->out == q->buf+sizeof(q->buf)-1)
+ q->out = q->buf;
+ else
+ q->out++;
+ return c;
+}
+
+static int
+qputc(IOQ *q, int c)
+{
+ uchar *nextin;
+ if(q->in >= &q->buf[sizeof(q->buf)-1])
+ nextin = q->buf;
+ else
+ nextin = q->in+1;
+ if(nextin == q->out)
+ return -1;
+ *q->in = c;
+ q->in = nextin;
+ return 0;
+}
+
+void
+qinit(IOQ *q)
+{
+ q->in = q->out = q->buf;
+ q->getc = qgetc;
+ q->putc = qputc;
+}
--- /dev/null
+++ b/os/boot.original/pc/sd.h
@@ -1,0 +1,126 @@
+/*
+ * Storage Device.
+ */
+typedef struct SDev SDev;
+typedef struct SDifc SDifc;
+typedef struct SDpart SDpart;
+typedef struct SDreq SDreq;
+typedef struct SDunit SDunit;
+
+typedef struct SDpart {
+ uvlong start;
+ uvlong end;
+ char name[NAMELEN];
+ char user[NAMELEN];
+ ulong perm;
+ int valid;
+ void *crud;
+} SDpart;
+
+typedef struct SDunit {
+ SDev* dev;
+ int subno;
+ uchar inquiry[256]; /* format follows SCSI spec */
+ char name[NAMELEN];
+// Rendez rendez;
+
+// QLock ctl;
+ uvlong sectors;
+ ulong secsize;
+ SDpart* part;
+ int npart; /* of valid partitions */
+ int changed;
+
+// QLock raw;
+ int state;
+ ulong pid;
+ SDreq* req;
+} SDunit;
+
+typedef struct SDev {
+ SDifc* ifc; /* pnp/legacy */
+ void *ctlr;
+ int idno;
+ int index; /* into unit space */
+ int nunit;
+ SDev* next;
+
+// QLock; /* enable/disable */
+ int enabled;
+} SDev;
+
+typedef struct SDifc {
+ char* name;
+
+ SDev* (*pnp)(void);
+ SDev* (*legacy)(int, int);
+ SDev* (*id)(SDev*);
+ int (*enable)(SDev*);
+ int (*disable)(SDev*);
+
+ int (*verify)(SDunit*);
+ int (*online)(SDunit*);
+ int (*rio)(SDreq*);
+ int (*rctl)(SDunit*, char*, int);
+ int (*wctl)(SDunit*, void*);
+
+ long (*bio)(SDunit*, int, int, void*, long, long);
+} SDifc;
+
+typedef struct SDreq {
+ SDunit* unit;
+ int lun;
+ int write;
+ uchar cmd[16];
+ int clen;
+ void* data;
+ int dlen;
+
+ int flags;
+
+ int status;
+ long rlen;
+ uchar sense[256];
+} SDreq;
+
+enum {
+ SDnosense = 0x00000001,
+ SDvalidsense = 0x00010000,
+};
+
+enum {
+ SDmalloc = -4,
+ SDeio = -3,
+ SDtimeout = -2,
+ SDnostatus = -1,
+
+ SDok = 0,
+
+ SDcheck = 0x02, /* check condition */
+ SDbusy = 0x08, /* busy */
+
+ SDmaxio = 2048*1024,
+ SDnpart = 16,
+};
+
+/* sdscsi.c */
+extern int scsiverify(SDunit*);
+extern int scsionline(SDunit*);
+extern long scsibio(SDunit*, int, int, void*, long, long);
+extern SDev* scsiid(SDev*, SDifc*);
+
+#define IrqATA0 14
+#define IrqATA1 15
+#define qlock(i) while(0)
+#define qunlock(i) while(0)
+
+#define putstrn consputs
+
+void sleep(void*, int(*)(void*), void*);
+void tsleep(void*, int(*)(void*), void*, int);
+#define wakeup(x) while(0)
+extern long sdbio(SDunit *unit, SDpart *pp, void *a, long len, vlong off);
+void partition(SDunit*);
+SDpart* sdfindpart(SDunit*, char*);
+void sdaddpart(SDunit*, char*, uvlong, uvlong);
+void* sdmalloc(void*, ulong);
--- /dev/null
+++ b/os/boot.original/pc/sd53c8xx.c
@@ -1,0 +1,2124 @@
+/*
+ * NCR 53c8xx driver for Plan 9
+ * Nigel Roles (ngr@cotswold.demon.co.uk)
+ *
+ * 08/07/99 Ultra2 fixed. Brazil #ifdefs added. Fixed script error 6 diagnostics.
+ *
+ * 09/06/99 Enhancements to support 895 and 896 correctly. Attempt at Ultra 2 negotiation,
+ * though no device to test with yet.
+ * Variant now contains the number of valid chip registers to assist
+ * dumpncrregs()
+ *
+ * 06/10/98 Various bug fixes and Brazil compiler inspired changes from jmk
+ *
+ * 05/10/98 Small fix to handle command length being greater than expected by device
+ *
+ * 04/08/98 Added missing locks to interrupt handler. Marked places where
+ * multiple controller extensions could go
+ *
+ * 18/05/97 Fixed overestimate in size of local SCRIPT RAM
+ *
+ * 17/05/97 Bug fix to return status
+ *
+ * 06/10/96 Enhanced list of chip IDs. 875 revision 1 has no clock doubler, so assume it
+ * is shipped with 80MHz crystal. Use bit 3 of the GPREG to recognise differential
+ * boards. This is Symbios specific, but since they are about the only suppliers of
+ * differential cards.
+ *
+ * 23/9/96 Wide and Ultra supported. 825A and 860 added to variants. Dual compiling
+ * version for fileserver and cpu. 80MHz default clock for 860
+ *
+ * 5/8/96 Waits for an Inquiry message before initiating synchronous negotiation
+ * in case capabilities byte [7] indicates device does not support it. Devices
+ * which do target initiated negotiation will typically get in first; a few
+ * bugs in handling this have been fixed
+ *
+ * 3/8/96 Added differential support (put scsi0=diff in plan9.ini)
+ * Split exec() into exec() and io(). Exec() is small, and Io() does not
+ * use any Plan 9 specific data structures, so alternate exec() functions
+ * may be done for other environments, such as the fileserver
+ *
+ * GENERAL
+ *
+ * Works on 810 and 875
+ * Should work on 815, 825, 810A, 825A, 860A
+ * Uses local RAM, large FIFO, prefetch, burst opcode fetch, and 16 byte synch. offset
+ * where applicable
+ * Supports multi-target, wide, Ultra
+ * Differential mode can be enabled by putting scsi0=diff in plan9.ini
+ * NO SUPPORT FOR tagged queuing (yet)
+ *
+ * Known problems
+ */
+
+#define MAXTARGET 16 /* can be 8 or 16 */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "error.h"
+
+#include "sd.h"
+extern SDifc sd53c8xxifc;
+
+#define waserror() (0)
+#define poperror()
+typedef struct QLock{ int r; } QLock;
+typedef struct Rendez{ int r; } Rendez;
+#define intrenable(irq, f, c, tbdf, name) setvec(VectorPIC+(irq), f, c);
+
+/**********************************/
+/* Portable configuration macros */
+/**********************************/
+
+//#define BOOTDEBUG
+//#define ASYNC_ONLY
+//#define INTERNAL_SCLK
+//#define ALWAYS_DO_WDTR
+#define WMR_DEBUG
+
+/**********************************/
+/* CPU specific macros */
+/**********************************/
+
+#ifdef BOOTDEBUG
+
+#define KPRINT oprint
+#define IPRINT intrprint
+#define DEBUG(n) 0
+#define IFLUSH() iflush()
+
+#else
+
+#define KPRINT if(0)print
+#define IPRINT if(0)print
+#define DEBUG(n) (0)
+#define IFLUSH()
+
+#endif /* BOOTDEBUG */
+
+/*******************************/
+/* General */
+/*******************************/
+
+#ifndef DMASEG
+#define DMASEG(x) PADDR(x)
+#define legetl(x) (*(ulong*)(x))
+#define lesetl(x,v) (*(ulong*)(x) = (v))
+#define swabl(a,b,c)
+#else
+#endif /*DMASEG */
+#define DMASEG_TO_KADDR(x) KADDR(PADDR(x))
+#define KPTR(x) ((x) == 0 ? 0 : DMASEG_TO_KADDR(x))
+
+#define MEGA 1000000L
+#ifdef INTERNAL_SCLK
+#define SCLK (33 * MEGA)
+#else
+#define SCLK (40 * MEGA)
+#endif /* INTERNAL_SCLK */
+#define ULTRA_NOCLOCKDOUBLE_SCLK (80 * MEGA)
+
+#define MAXSYNCSCSIRATE (5 * MEGA)
+#define MAXFASTSYNCSCSIRATE (10 * MEGA)
+#define MAXULTRASYNCSCSIRATE (20 * MEGA)
+#define MAXULTRA2SYNCSCSIRATE (40 * MEGA)
+#define MAXASYNCCORERATE (25 * MEGA)
+#define MAXSYNCCORERATE (25 * MEGA)
+#define MAXFASTSYNCCORERATE (50 * MEGA)
+#define MAXULTRASYNCCORERATE (80 * MEGA)
+#define MAXULTRA2SYNCCORERATE (160 * MEGA)
+
+
+#define X_MSG 1
+#define X_MSG_SDTR 1
+#define X_MSG_WDTR 3
+
+struct na_patch {
+ unsigned lwoff;
+ unsigned char type;
+};
+
+typedef struct Ncr {
+ uchar scntl0; /* 00 */
+ uchar scntl1;
+ uchar scntl2;
+ uchar scntl3;
+
+ uchar scid; /* 04 */
+ uchar sxfer;
+ uchar sdid;
+ uchar gpreg;
+
+ uchar sfbr; /* 08 */
+ uchar socl;
+ uchar ssid;
+ uchar sbcl;
+
+ uchar dstat; /* 0c */
+ uchar sstat0;
+ uchar sstat1;
+ uchar sstat2;
+
+ uchar dsa[4]; /* 10 */
+
+ uchar istat; /* 14 */
+ uchar istatpad[3];
+
+ uchar ctest0; /* 18 */
+ uchar ctest1;
+ uchar ctest2;
+ uchar ctest3;
+
+ uchar temp[4]; /* 1c */
+
+ uchar dfifo; /* 20 */
+ uchar ctest4;
+ uchar ctest5;
+ uchar ctest6;
+
+ uchar dbc[3]; /* 24 */
+ uchar dcmd; /* 27 */
+
+ uchar dnad[4]; /* 28 */
+ uchar dsp[4]; /* 2c */
+ uchar dsps[4]; /* 30 */
+
+ uchar scratcha[4]; /* 34 */
+
+ uchar dmode; /* 38 */
+ uchar dien;
+ uchar dwt;
+ uchar dcntl;
+
+ uchar adder[4]; /* 3c */
+
+ uchar sien0; /* 40 */
+ uchar sien1;
+ uchar sist0;
+ uchar sist1;
+
+ uchar slpar; /* 44 */
+ uchar slparpad0;
+ uchar macntl;
+ uchar gpcntl;
+
+ uchar stime0; /* 48 */
+ uchar stime1;
+ uchar respid;
+ uchar respidpad0;
+
+ uchar stest0; /* 4c */
+ uchar stest1;
+ uchar stest2;
+ uchar stest3;
+
+ uchar sidl; /* 50 */
+ uchar sidlpad[3];
+
+ uchar sodl; /* 54 */
+ uchar sodlpad[3];
+
+ uchar sbdl; /* 58 */
+ uchar sbdlpad[3];
+
+ uchar scratchb[4]; /* 5c */
+} Ncr;
+
+typedef struct Movedata {
+ uchar dbc[4];
+ uchar pa[4];
+} Movedata;
+
+typedef enum NegoState {
+ NeitherDone, WideInit, WideResponse, WideDone,
+ SyncInit, SyncResponse, BothDone
+} NegoState;
+
+typedef enum State {
+ Allocated, Queued, Active, Done
+} State;
+
+typedef struct Dsa {
+ union {
+ uchar state[4];
+ struct {
+ uchar stateb;
+ uchar result;
+ uchar dmablks;
+ uchar flag; /* setbyte(state,3,...) */
+ };
+ };
+
+ union {
+ ulong dmancr; /* For block transfer: NCR order (little-endian) */
+ uchar dmaaddr[4];
+ };
+
+ uchar target; /* Target */
+ uchar pad0[3];
+
+ uchar lun; /* Logical Unit Number */
+ uchar pad1[3];
+
+ uchar scntl3;
+ uchar sxfer;
+ uchar pad2[2];
+
+ uchar next[4]; /* chaining for SCRIPT (NCR byte order) */
+ struct Dsa *freechain; /* chaining for freelist */
+ Rendez;
+ uchar scsi_id_buf[4];
+ Movedata msg_out_buf;
+ Movedata cmd_buf;
+ Movedata data_buf;
+ Movedata status_buf;
+ uchar msg_out[10]; /* enough to include SDTR */
+ uchar status;
+ int p9status;
+ uchar parityerror;
+} Dsa;
+
+typedef enum Feature {
+ BigFifo = 1, /* 536 byte fifo */
+ BurstOpCodeFetch = 2, /* burst fetch opcodes */
+ Prefetch = 4, /* prefetch 8 longwords */
+ LocalRAM = 8, /* 4K longwords of local RAM */
+ Differential = 16, /* Differential support */
+ Wide = 32, /* Wide capable */
+ Ultra = 64, /* Ultra capable */
+ ClockDouble = 128, /* Has clock doubler */
+ ClockQuad = 256, /* Has clock quadrupler (same as Ultra2) */
+ Ultra2 = 256,
+} Feature;
+
+typedef enum Burst {
+ Burst2 = 0,
+ Burst4 = 1,
+ Burst8 = 2,
+ Burst16 = 3,
+ Burst32 = 4,
+ Burst64 = 5,
+ Burst128 = 6
+} Burst;
+
+typedef struct Variant {
+ ushort did;
+ uchar maxrid; /* maximum allowed revision ID */
+ char *name;
+ Burst burst; /* codings for max burst */
+ uchar maxsyncoff; /* max synchronous offset */
+ uchar registers; /* number of 32 bit registers */
+ unsigned feature;
+} Variant;
+
+static unsigned char cf2[] = { 6, 2, 3, 4, 6, 8, 12, 16 };
+#define NULTRA2SCF (sizeof(cf2)/sizeof(cf2[0]))
+#define NULTRASCF (NULTRA2SCF - 2)
+#define NSCF (NULTRASCF - 1)
+
+typedef struct Controller {
+ Lock;
+ struct {
+ uchar scntl3;
+ uchar stest2;
+ } bios;
+ uchar synctab[NULTRA2SCF - 1][8];/* table of legal tpfs */
+ NegoState s[MAXTARGET];
+ uchar scntl3[MAXTARGET];
+ uchar sxfer[MAXTARGET];
+ uchar cap[MAXTARGET]; /* capabilities byte from Identify */
+ ushort capvalid; /* bit per target for validity of cap[] */
+ ushort wide; /* bit per target set if wide negotiated */
+ ulong sclk; /* clock speed of controller */
+ uchar clockmult; /* set by synctabinit */
+ uchar ccf; /* CCF bits */
+ uchar tpf; /* best tpf value for this controller */
+ uchar feature; /* requested features */
+ int running; /* is the script processor running? */
+ int ssm; /* single step mode */
+ Ncr *n; /* pointer to registers */
+ Variant *v; /* pointer to variant type */
+ ulong *script; /* where the real script is */
+ ulong scriptpa; /* where the real script is */
+ Pcidev* pcidev;
+ SDev* sdev;
+
+ struct {
+ Lock;
+ uchar head[4]; /* head of free list (NCR byte order) */
+ Dsa *tail;
+ Dsa *freechain;
+ } dsalist;
+
+ QLock q[MAXTARGET]; /* queues for each target */
+} Controller;
+
+static Controller controller;
+
+/* ISTAT */
+enum { Abrt = 0x80, Srst = 0x40, Sigp = 0x20, Sem = 0x10, Con = 0x08, Intf = 0x04, Sip = 0x02, Dip = 0x01 };
+
+/* DSTAT */
+enum { Dfe = 0x80, Mdpe = 0x40, Bf = 0x20, Abrted = 0x10, Ssi = 0x08, Sir = 0x04, Iid = 0x01 };
+
+/* SSTAT */
+enum { DataOut, DataIn, Cmd, Status, ReservedOut, ReservedIn, MessageOut, MessageIn };
+
+static void setmovedata(Movedata*, ulong, ulong);
+static void advancedata(Movedata*, long);
+static int bios_set_differential(Controller *c);
+
+static char *phase[] = {
+ "data out", "data in", "command", "status",
+ "reserved out", "reserved in", "message out", "message in"
+};
+
+#ifdef BOOTDEBUG
+#define DEBUGSIZE 10240
+char debugbuf[DEBUGSIZE];
+char *debuglast;
+
+static void
+intrprint(char *format, ...)
+{
+ if (debuglast == 0)
+ debuglast = debugbuf;
+ debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
+}
+
+static void
+iflush()
+{
+ int s;
+ char *endp;
+ s = splhi();
+ if (debuglast == 0)
+ debuglast = debugbuf;
+ if (debuglast == debugbuf) {
+ splx(s);
+ return;
+ }
+ endp = debuglast;
+ splx(s);
+ screenputs(debugbuf, endp - debugbuf);
+ s = splhi();
+ memmove(debugbuf, endp, debuglast - endp);
+ debuglast -= endp - debugbuf;
+ splx(s);
+}
+
+static void
+oprint(char *format, ...)
+{
+ int s;
+
+ iflush();
+ s = splhi();
+ if (debuglast == 0)
+ debuglast = debugbuf;
+ debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));
+ splx(s);
+ iflush();
+}
+#endif
+
+#include "sd53c8xx.i"
+
+static Dsa *
+dsaalloc(Controller *c, int target, int lun)
+{
+ Dsa *d;
+
+ ilock(&c->dsalist);
+ if ((d = c->dsalist.freechain) == 0) {
+ d = xalloc(sizeof(*d));
+ if (DEBUG(1))
+ KPRINT("sd53c8xx: %d/%d: allocated new dsa %lux\n", target, lun, d);
+ lesetl(d->next, 0);
+ lesetl(d->state, A_STATE_ALLOCATED);
+ if (legetl(c->dsalist.head) == 0)
+ lesetl(c->dsalist.head, DMASEG(d)); /* ATOMIC?!? */
+ else
+ lesetl(c->dsalist.tail->next, DMASEG(d)); /* ATOMIC?!? */
+ c->dsalist.tail = d;
+ }
+ else {
+ if (DEBUG(1))
+ KPRINT("sd53c8xx: %d/%d: reused dsa %lux\n", target, lun, d);
+ c->dsalist.freechain = d->freechain;
+ lesetl(d->state, A_STATE_ALLOCATED);
+ }
+ iunlock(&c->dsalist);
+ d->target = target;
+ d->lun = lun;
+ return d;
+}
+
+static void
+dsafree(Controller *c, Dsa *d)
+{
+ ilock(&c->dsalist);
+ d->freechain = c->dsalist.freechain;
+ c->dsalist.freechain = d;
+ lesetl(d->state, A_STATE_FREE);
+ iunlock(&c->dsalist);
+}
+
+static Dsa *
+dsafind(Controller *c, uchar target, uchar lun, uchar state)
+{
+ Dsa *d;
+ for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) {
+ if (d->target != 0xff && d->target != target)
+ continue;
+ if (lun != 0xff && d->lun != lun)
+ continue;
+ if (state != 0xff && d->stateb != state)
+ continue;
+ break;
+ }
+ return d;
+}
+
+static void
+dumpncrregs(Controller *c, int intr)
+{
+ int i;
+ Ncr *n = c->n;
+ int depth = c->v->registers / 4;
+
+ KPRINT("sa = %.8lux\n", c->scriptpa);
+ for (i = 0; i < depth; i++) {
+ int j;
+ for (j = 0; j < 4; j++) {
+ int k = j * depth + i;
+ uchar *p;
+
+ /* display little-endian to make 32-bit values readable */
+ p = (uchar*)n+k*4;
+ if (intr)
+ IPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
+ else
+ KPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);
+ USED(p);
+ }
+ if (intr)
+ IPRINT("\n");
+ else
+ KPRINT("\n");
+ }
+}
+
+static int
+chooserate(Controller *c, int tpf, int *scfp, int *xferpp)
+{
+ /* find lowest entry >= tpf */
+ int besttpf = 1000;
+ int bestscfi = 0;
+ int bestxferp = 0;
+ int scf, xferp;
+ int maxscf;
+
+ if (c->v->feature & Ultra2)
+ maxscf = NULTRA2SCF;
+ else if (c->v->feature & Ultra)
+ maxscf = NULTRASCF;
+ else
+ maxscf = NSCF;
+
+ /*
+ * search large clock factors first since this should
+ * result in more reliable transfers
+ */
+ for (scf = maxscf; scf >= 1; scf--) {
+ for (xferp = 0; xferp < 8; xferp++) {
+ unsigned char v = c->synctab[scf - 1][xferp];
+ if (v == 0)
+ continue;
+ if (v >= tpf && v < besttpf) {
+ besttpf = v;
+ bestscfi = scf;
+ bestxferp = xferp;
+ }
+ }
+ }
+ if (besttpf == 1000)
+ return 0;
+ if (scfp)
+ *scfp = bestscfi;
+ if (xferpp)
+ *xferpp = bestxferp;
+ return besttpf;
+}
+
+static void
+synctabinit(Controller *c)
+{
+ int scf;
+ unsigned long scsilimit;
+ int xferp;
+ unsigned long cr, sr;
+ int tpf;
+ int fast;
+ int maxscf;
+
+ if (c->v->feature & Ultra2)
+ maxscf = NULTRA2SCF;
+ else if (c->v->feature & Ultra)
+ maxscf = NULTRASCF;
+ else
+ maxscf = NSCF;
+
+ /*
+ * for chips with no clock doubler, but Ultra capable (e.g. 860, or interestingly the
+ * first spin of the 875), assume 80MHz
+ * otherwise use the internal (33 Mhz) or external (40MHz) default
+ */
+
+ if ((c->v->feature & Ultra) != 0 && (c->v->feature & (ClockDouble | ClockQuad)) == 0)
+ c->sclk = ULTRA_NOCLOCKDOUBLE_SCLK;
+ else
+ c->sclk = SCLK;
+
+ /*
+ * otherwise, if the chip is Ultra capable, but has a slow(ish) clock,
+ * invoke the doubler
+ */
+
+ if (SCLK <= 40000000) {
+ if (c->v->feature & ClockDouble) {
+ c->sclk *= 2;
+ c->clockmult = 1;
+ }
+ else if (c->v->feature & ClockQuad) {
+ c->sclk *= 4;
+ c->clockmult = 1;
+ }
+ else
+ c->clockmult = 0;
+ }
+ else
+ c->clockmult = 0;
+
+ /* derive CCF from sclk */
+ /* woebetide anyone with SCLK < 16.7 or > 80MHz */
+ if (c->sclk <= 25 * MEGA)
+ c->ccf = 1;
+ else if (c->sclk <= 3750000)
+ c->ccf = 2;
+ else if (c->sclk <= 50 * MEGA)
+ c->ccf = 3;
+ else if (c->sclk <= 75 * MEGA)
+ c->ccf = 4;
+ else if ((c->v->feature & ClockDouble) && c->sclk <= 80 * MEGA)
+ c->ccf = 5;
+ else if ((c->v->feature & ClockQuad) && c->sclk <= 120 * MEGA)
+ c->ccf = 6;
+ else if ((c->v->feature & ClockQuad) && c->sclk <= 160 * MEGA)
+ c->ccf = 7;
+
+ for (scf = 1; scf < maxscf; scf++) {
+ /* check for legal core rate */
+ /* round up so we run slower for safety */
+ cr = (c->sclk * 2 + cf2[scf] - 1) / cf2[scf];
+ if (cr <= MAXSYNCCORERATE) {
+ scsilimit = MAXSYNCSCSIRATE;
+ fast = 0;
+ }
+ else if (cr <= MAXFASTSYNCCORERATE) {
+ scsilimit = MAXFASTSYNCSCSIRATE;
+ fast = 1;
+ }
+ else if ((c->v->feature & Ultra) && cr <= MAXULTRASYNCCORERATE) {
+ scsilimit = MAXULTRASYNCSCSIRATE;
+ fast = 2;
+ }
+ else if ((c->v->feature & Ultra2) && cr <= MAXULTRA2SYNCCORERATE) {
+ scsilimit = MAXULTRA2SYNCSCSIRATE;
+ fast = 3;
+ }
+ else
+ continue;
+ for (xferp = 11; xferp >= 4; xferp--) {
+ int ok;
+ int tp;
+ /* calculate scsi rate - round up again */
+ /* start from sclk for accuracy */
+ int totaldivide = xferp * cf2[scf];
+ sr = (c->sclk * 2 + totaldivide - 1) / totaldivide;
+ if (sr > scsilimit)
+ break;
+ /*
+ * now work out transfer period
+ * round down now so that period is pessimistic
+ */
+ tp = (MEGA * 1000) / sr;
+ /*
+ * bounds check it
+ */
+ if (tp < 25 || tp > 255 * 4)
+ continue;
+ /*
+ * spot stupid special case for Ultra or Ultra2
+ * while working out factor
+ */
+ if (tp == 25)
+ tpf = 10;
+ else if (tp == 50)
+ tpf = 12;
+ else if (tp < 52)
+ continue;
+ else
+ tpf = tp / 4;
+ /*
+ * now check tpf looks sensible
+ * given core rate
+ */
+ switch (fast) {
+ case 0:
+ /* scf must be ccf for SCSI 1 */
+ ok = tpf >= 50 && scf == c->ccf;
+ break;
+ case 1:
+ ok = tpf >= 25 && tpf < 50;
+ break;
+ case 2:
+ /*
+ * must use xferp of 4, or 5 at a pinch
+ * for an Ultra transfer
+ */
+ ok = xferp <= 5 && tpf >= 12 && tpf < 25;
+ break;
+ case 3:
+ ok = xferp == 4 && (tpf == 10 || tpf == 11);
+ break;
+ default:
+ ok = 0;
+ }
+ if (!ok)
+ continue;
+ c->synctab[scf - 1][xferp - 4] = tpf;
+ }
+ }
+
+#ifndef NO_ULTRA2
+ if (c->v->feature & Ultra2)
+ tpf = 10;
+ else
+#endif
+ if (c->v->feature & Ultra)
+ tpf = 12;
+ else
+ tpf = 25;
+ for (; tpf < 256; tpf++) {
+ if (chooserate(c, tpf, &scf, &xferp) == tpf) {
+ unsigned tp = tpf == 10 ? 25 : (tpf == 12 ? 50 : tpf * 4);
+ unsigned long khz = (MEGA + tp - 1) / (tp);
+ KPRINT("sd53c8xx: tpf=%d scf=%d.%.1d xferp=%d mhz=%ld.%.3ld\n",
+ tpf, cf2[scf] / 2, (cf2[scf] & 1) ? 5 : 0,
+ xferp + 4, khz / 1000, khz % 1000);
+ USED(khz);
+ if (c->tpf == 0)
+ c->tpf = tpf; /* note lowest value for controller */
+ }
+ }
+}
+
+static void
+synctodsa(Dsa *dsa, Controller *c)
+{
+/*
+ KPRINT("synctodsa(dsa=%lux, target=%d, scntl3=%.2lx sxfer=%.2x)\n",
+ dsa, dsa->target, c->scntl3[dsa->target], c->sxfer[dsa->target]);
+*/
+ dsa->scntl3 = c->scntl3[dsa->target];
+ dsa->sxfer = c->sxfer[dsa->target];
+}
+
+static void
+setsync(Dsa *dsa, Controller *c, int target, uchar ultra, uchar scf, uchar xferp, uchar reqack)
+{
+ c->scntl3[target] =
+ (c->scntl3[target] & 0x08) | (((scf << 4) | c->ccf | (ultra << 7)) & ~0x08);
+ c->sxfer[target] = (xferp << 5) | reqack;
+ c->s[target] = BothDone;
+ if (dsa) {
+ synctodsa(dsa, c);
+ c->n->scntl3 = c->scntl3[target];
+ c->n->sxfer = c->sxfer[target];
+ }
+}
+
+static void
+setasync(Dsa *dsa, Controller *c, int target)
+{
+ setsync(dsa, c, target, 0, c->ccf, 0, 0);
+}
+
+static void
+setwide(Dsa *dsa, Controller *c, int target, uchar wide)
+{
+ c->scntl3[target] = wide ? (1 << 3) : 0;
+ setasync(dsa, c, target);
+ c->s[target] = WideDone;
+}
+
+static int
+buildsdtrmsg(uchar *buf, uchar tpf, uchar offset)
+{
+ *buf++ = X_MSG;
+ *buf++ = 3;
+ *buf++ = X_MSG_SDTR;
+ *buf++ = tpf;
+ *buf = offset;
+ return 5;
+}
+
+static int
+buildwdtrmsg(uchar *buf, uchar expo)
+{
+ *buf++ = X_MSG;
+ *buf++ = 2;
+ *buf++ = X_MSG_WDTR;
+ *buf = expo;
+ return 4;
+}
+
+static void
+start(Controller *c, long entry)
+{
+ ulong p;
+
+ if (c->running)
+ panic("sd53c8xx: start called while running");
+ c->running = 1;
+ p = c->scriptpa + entry;
+ lesetl(c->n->dsp, p);
+ if (c->ssm)
+ c->n->dcntl |= 0x4; /* start DMA in SSI mode */
+}
+
+static void
+ncrcontinue(Controller *c)
+{
+ if (c->running)
+ panic("sd53c8xx: ncrcontinue called while running");
+ /* set the start DMA bit to continue execution */
+ c->running = 1;
+ c->n->dcntl |= 0x4;
+}
+
+static void
+softreset(Controller *c)
+{
+ Ncr *n = c->n;
+
+ n->istat = Srst; /* software reset */
+ n->istat = 0;
+ /* general initialisation */
+ n->scid = (1 << 6) | 7; /* respond to reselect, ID 7 */
+ n->respid = 1 << 7; /* response ID = 7 */
+
+#ifdef INTERNAL_SCLK
+ n->stest1 = 0x80; /* disable external scsi clock */
+#else
+ n->stest1 = 0x00;
+#endif
+
+ n->stime0 = 0xdd; /* about 0.5 second timeout on each device */
+ n->scntl0 |= 0x8; /* Enable parity checking */
+
+ /* continued setup */
+ n->sien0 = 0x8f;
+ n->sien1 = 0x04;
+ n->dien = 0x7d;
+ n->stest3 = 0x80; /* TolerANT enable */
+ c->running = 0;
+
+ if (c->v->feature & BigFifo)
+ n->ctest5 = (1 << 5);
+ n->dmode = c->v->burst << 6; /* set burst length bits */
+ if (c->v->burst & 4)
+ n->ctest5 |= (1 << 2); /* including overflow into ctest5 bit 2 */
+ if (c->v->feature & Prefetch)
+ n->dcntl |= (1 << 5); /* prefetch enable */
+ else if (c->v->feature & BurstOpCodeFetch)
+ n->dmode |= (1 << 1); /* burst opcode fetch */
+ if (c->v->feature & Differential) {
+ /* chip capable */
+ if ((c->feature & Differential) || bios_set_differential(c)) {
+ /* user enabled, or some evidence bios set differential */
+ if (n->sstat2 & (1 << 2))
+ print("sd53c8xx: can't go differential; wrong cable\n");
+ else {
+ n->stest2 = (1 << 5);
+ print("sd53c8xx: differential mode set\n");
+ }
+ }
+ }
+ if (c->clockmult) {
+ n->stest1 |= (1 << 3); /* power up doubler */
+ delay(2);
+ n->stest3 |= (1 << 5); /* stop clock */
+ n->stest1 |= (1 << 2); /* enable doubler */
+ n->stest3 &= ~(1 << 5); /* start clock */
+ /* pray */
+ }
+}
+
+static void
+msgsm(Dsa *dsa, Controller *c, int msg, int *cont, int *wakeme)
+{
+ uchar histpf, hisreqack;
+ int tpf;
+ int scf, xferp;
+ int len;
+
+ Ncr *n = c->n;
+
+ switch (c->s[dsa->target]) {
+ case SyncInit:
+ switch (msg) {
+ case A_SIR_MSG_SDTR:
+ /* reply to my SDTR */
+ histpf = n->scratcha[2];
+ hisreqack = n->scratcha[3];
+ KPRINT("sd53c8xx: %d: SDTN response %d %d\n",
+ dsa->target, histpf, hisreqack);
+
+ if (hisreqack == 0)
+ setasync(dsa, c, dsa->target);
+ else {
+ /* hisreqack should be <= c->v->maxsyncoff */
+ tpf = chooserate(c, histpf, &scf, &xferp);
+ KPRINT("sd53c8xx: %d: SDTN: using %d %d\n",
+ dsa->target, tpf, hisreqack);
+ setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
+ }
+ *cont = -2;
+ return;
+ case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
+ /* target ignored ATN for message after IDENTIFY - not SCSI-II */
+ KPRINT("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
+ KPRINT("sd53c8xx: %d: SDTN: async\n", dsa->target);
+ setasync(dsa, c, dsa->target);
+ *cont = E_to_decisions;
+ return;
+ case A_SIR_MSG_REJECT:
+ /* rejection of my SDTR */
+ KPRINT("sd53c8xx: %d: SDTN: rejected SDTR\n", dsa->target);
+ //async:
+ KPRINT("sd53c8xx: %d: SDTN: async\n", dsa->target);
+ setasync(dsa, c, dsa->target);
+ *cont = -2;
+ return;
+ }
+ break;
+ case WideInit:
+ switch (msg) {
+ case A_SIR_MSG_WDTR:
+ /* reply to my WDTR */
+ KPRINT("sd53c8xx: %d: WDTN: response %d\n",
+ dsa->target, n->scratcha[2]);
+ setwide(dsa, c, dsa->target, n->scratcha[2]);
+ *cont = -2;
+ return;
+ case A_SIR_EV_PHASE_SWITCH_AFTER_ID:
+ /* target ignored ATN for message after IDENTIFY - not SCSI-II */
+ KPRINT("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target);
+ setwide(dsa, c, dsa->target, 0);
+ *cont = E_to_decisions;
+ return;
+ case A_SIR_MSG_REJECT:
+ /* rejection of my SDTR */
+ KPRINT("sd53c8xx: %d: WDTN: rejected WDTR\n", dsa->target);
+ setwide(dsa, c, dsa->target, 0);
+ *cont = -2;
+ return;
+ }
+ break;
+
+ case NeitherDone:
+ case WideDone:
+ case BothDone:
+ switch (msg) {
+ case A_SIR_MSG_WDTR: {
+ uchar hiswide, mywide;
+ hiswide = n->scratcha[2];
+ mywide = (c->v->feature & Wide) != 0;
+ KPRINT("sd53c8xx: %d: WDTN: target init %d\n",
+ dsa->target, hiswide);
+ if (hiswide < mywide)
+ mywide = hiswide;
+ KPRINT("sd53c8xx: %d: WDTN: responding %d\n",
+ dsa->target, mywide);
+ setwide(dsa, c, dsa->target, mywide);
+ len = buildwdtrmsg(dsa->msg_out, mywide);
+ setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
+ *cont = E_response;
+ c->s[dsa->target] = WideResponse;
+ return;
+ }
+ case A_SIR_MSG_SDTR:
+#ifdef ASYNC_ONLY
+ *cont = E_reject;
+ return;
+#else
+ /* target decides to renegotiate */
+ histpf = n->scratcha[2];
+ hisreqack = n->scratcha[3];
+ KPRINT("sd53c8xx: %d: SDTN: target init %d %d\n",
+ dsa->target, histpf, hisreqack);
+ if (hisreqack == 0) {
+ /* he wants asynchronous */
+ setasync(dsa, c, dsa->target);
+ tpf = 0;
+ }
+ else {
+ /* he wants synchronous */
+ tpf = chooserate(c, histpf, &scf, &xferp);
+ if (hisreqack > c->v->maxsyncoff)
+ hisreqack = c->v->maxsyncoff;
+ KPRINT("sd53c8xx: %d: using %d %d\n",
+ dsa->target, tpf, hisreqack);
+ setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack);
+ }
+ /* build my SDTR message */
+ len = buildsdtrmsg(dsa->msg_out, tpf, hisreqack);
+ setmovedata(&dsa->msg_out_buf, DMASEG(dsa->msg_out), len);
+ *cont = E_response;
+ c->s[dsa->target] = SyncResponse;
+ return;
+#endif
+ }
+ break;
+ case WideResponse:
+ switch (msg) {
+ case A_SIR_EV_RESPONSE_OK:
+ c->s[dsa->target] = WideDone;
+ KPRINT("sd53c8xx: %d: WDTN: response accepted\n", dsa->target);
+ *cont = -2;
+ return;
+ case A_SIR_MSG_REJECT:
+ setwide(dsa, c, dsa->target, 0);
+ KPRINT("sd53c8xx: %d: WDTN: response REJECTed\n", dsa->target);
+ *cont = -2;
+ return;
+ }
+ break;
+ case SyncResponse:
+ switch (msg) {
+ case A_SIR_EV_RESPONSE_OK:
+ c->s[dsa->target] = BothDone;
+ KPRINT("sd53c8xx: %d: SDTN: response accepted (%s)\n",
+ dsa->target, phase[n->sstat1 & 7]);
+ *cont = -2;
+ return; /* chf */
+ case A_SIR_MSG_REJECT:
+ setasync(dsa, c, dsa->target);
+ KPRINT("sd53c8xx: %d: SDTN: response REJECTed\n", dsa->target);
+ *cont = -2;
+ return;
+ }
+ break;
+ }
+ KPRINT("sd53c8xx: %d: msgsm: state %d msg %d\n",
+ dsa->target, c->s[dsa->target], msg);
+ *wakeme = 1;
+ return;
+}
+
+static void
+calcblockdma(Dsa *d, ulong base, ulong count)
+{
+ ulong blocks;
+ if (DEBUG(3))
+ blocks = 0;
+ else {
+ blocks = count / A_BSIZE;
+ if (blocks > 255)
+ blocks = 255;
+ }
+ d->dmablks = blocks;
+ d->dmaaddr[0] = base;
+ d->dmaaddr[1] = base >> 8;
+ d->dmaaddr[2] = base >> 16;
+ d->dmaaddr[3] = base >> 24;
+ setmovedata(&d->data_buf, base + blocks * A_BSIZE, count - blocks * A_BSIZE);
+ if (legetl(d->data_buf.dbc) == 0)
+ d->flag = 1;
+}
+
+static ulong
+read_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa)
+{
+ ulong dbc;
+ uchar dfifo = n->dfifo;
+ int inchip;
+
+ dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
+ if (n->ctest5 & (1 << 5))
+ inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
+ else
+ inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
+ if (inchip) {
+ IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: DMA FIFO = %d\n",
+ dsa->target, dsa->lun, inchip);
+ }
+ if (n->sxfer & 0xf) {
+ /* SCSI FIFO */
+ uchar fifo = n->sstat1 >> 4;
+ if (c->v->maxsyncoff > 8)
+ fifo |= (n->sstat2 & (1 << 4));
+ if (fifo) {
+ inchip += fifo;
+ IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SCSI FIFO = %d\n",
+ dsa->target, dsa->lun, fifo);
+ }
+ }
+ else {
+ if (n->sstat0 & (1 << 7)) {
+ inchip++;
+ IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL full\n",
+ dsa->target, dsa->lun);
+ }
+ if (n->sstat2 & (1 << 7)) {
+ inchip++;
+ IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL msb full\n",
+ dsa->target, dsa->lun);
+ }
+ }
+ USED(inchip);
+ return dbc;
+}
+
+static ulong
+write_mismatch_recover(Ncr *n, Dsa *dsa)
+{
+ ulong dbc;
+ uchar dfifo = n->dfifo;
+ int inchip;
+
+ dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
+ USED(dsa);
+ if (n->ctest5 & (1 << 5))
+ inchip = ((dfifo | ((n->ctest5 & 3) << 8)) - (dbc & 0x3ff)) & 0x3ff;
+ else
+ inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f;
+#ifdef WMR_DEBUG
+ if (inchip) {
+ IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: DMA FIFO = %d\n",
+ dsa->target, dsa->lun, inchip);
+ }
+#endif
+ if (n->sstat0 & (1 << 5)) {
+ inchip++;
+#ifdef WMR_DEBUG
+ IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun);
+#endif
+ }
+ if (n->sstat2 & (1 << 5)) {
+ inchip++;
+#ifdef WMR_DEBUG
+ IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun);
+#endif
+ }
+ if (n->sxfer & 0xf) {
+ /* synchronous SODR */
+ if (n->sstat0 & (1 << 6)) {
+ inchip++;
+#ifdef WMR_DEBUG
+ IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR full\n",
+ dsa->target, dsa->lun);
+#endif
+ }
+ if (n->sstat2 & (1 << 6)) {
+ inchip++;
+#ifdef WMR_DEBUG
+ IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR msb full\n",
+ dsa->target, dsa->lun);
+#endif
+ }
+ }
+ /* clear the dma fifo */
+ n->ctest3 |= (1 << 2);
+ /* wait till done */
+ while ((n->dstat & Dfe) == 0)
+ ;
+ return dbc + inchip;
+}
+
+static void
+interrupt(Ureg *ur, void *a)
+{
+ uchar istat;
+ ushort sist;
+ uchar dstat;
+ int wakeme = 0;
+ int cont = -1;
+ Dsa *dsa;
+ Controller *c = a;
+ Ncr *n = c->n;
+
+ USED(ur);
+ if (DEBUG(1))
+ IPRINT("sd53c8xx: int\n");
+ ilock(c);
+ istat = n->istat;
+ if (istat & Intf) {
+ Dsa *d;
+ int wokesomething = 0;
+ if (DEBUG(1))
+ IPRINT("sd53c8xx: Intfly\n");
+ n->istat = Intf;
+ /* search for structures in A_STATE_DONE */
+ for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) {
+ if (d->stateb == A_STATE_DONE) {
+ d->p9status = d->status;
+ if (DEBUG(1))
+ IPRINT("sd53c8xx: waking up dsa %lux\n", d);
+ wakeup(d);
+ wokesomething = 1;
+ }
+ }
+ if (!wokesomething)
+ IPRINT("sd53c8xx: nothing to wake up\n");
+ }
+
+ if ((istat & (Sip | Dip)) == 0) {
+ if (DEBUG(1))
+ IPRINT("sd53c8xx: int end %x\n", istat);
+ iunlock(c);
+ return;
+ }
+
+ sist = (n->sist1<<8)|n->sist0; /* BUG? can two-byte read be inconsistent? */
+ dstat = n->dstat;
+ dsa = (Dsa *)DMASEG_TO_KADDR(legetl(n->dsa));
+ c->running = 0;
+ if (istat & Sip) {
+ if (DEBUG(1))
+ IPRINT("sist = %.4x\n", sist);
+ if (sist & 0x80) {
+ ulong addr;
+ ulong sa;
+ ulong dbc;
+ ulong tbc;
+ int dmablks;
+ ulong dmaaddr;
+
+ addr = legetl(n->dsp);
+ sa = addr - c->scriptpa;
+ if (DEBUG(1) || DEBUG(2))
+ IPRINT("sd53c8xx: %d/%d: Phase Mismatch sa=%.8lux\n",
+ dsa->target, dsa->lun, sa);
+ /*
+ * now recover
+ */
+ if (sa == E_data_in_mismatch) {
+ dbc = read_mismatch_recover(c, n, dsa);
+ tbc = legetl(dsa->data_buf.dbc) - dbc;
+ advancedata(&dsa->data_buf, tbc);
+ if (DEBUG(1) || DEBUG(2))
+ IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n",
+ dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
+ cont = E_to_decisions;
+ }
+ else if (sa == E_data_in_block_mismatch) {
+ dbc = read_mismatch_recover(c, n, dsa);
+ tbc = A_BSIZE - dbc;
+ /* recover current state from registers */
+ dmablks = n->scratcha[2];
+ dmaaddr = legetl(n->scratchb);
+ /* we have got to dmaaddr + tbc */
+ /* we have dmablks * A_BSIZE - tbc + residue left to do */
+ /* so remaining transfer is */
+ IPRINT("in_block_mismatch: dmaaddr = 0x%lux tbc=%lud dmablks=%d\n",
+ dmaaddr, tbc, dmablks);
+ calcblockdma(dsa, dmaaddr + tbc,
+ dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
+ /* copy changes into scratch registers */
+ IPRINT("recalc: dmablks %d dmaaddr 0x%lx pa 0x%lx dbc %ld\n",
+ dsa->dmablks, legetl(dsa->dmaaddr),
+ legetl(dsa->data_buf.pa), legetl(dsa->data_buf.dbc));
+ n->scratcha[2] = dsa->dmablks;
+ lesetl(n->scratchb, dsa->dmancr);
+ cont = E_data_block_mismatch_recover;
+ }
+ else if (sa == E_data_out_mismatch) {
+ dbc = write_mismatch_recover(n, dsa);
+ tbc = legetl(dsa->data_buf.dbc) - dbc;
+ advancedata(&dsa->data_buf, tbc);
+ if (DEBUG(1) || DEBUG(2))
+ IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n",
+ dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc));
+ cont = E_to_decisions;
+ }
+ else if (sa == E_data_out_block_mismatch) {
+ dbc = write_mismatch_recover(n, dsa);
+ tbc = legetl(dsa->data_buf.dbc) - dbc;
+ /* recover current state from registers */
+ dmablks = n->scratcha[2];
+ dmaaddr = legetl(n->scratchb);
+ /* we have got to dmaaddr + tbc */
+ /* we have dmablks blocks - tbc + residue left to do */
+ /* so remaining transfer is */
+ IPRINT("out_block_mismatch: dmaaddr = %lux tbc=%lud dmablks=%d\n",
+ dmaaddr, tbc, dmablks);
+ calcblockdma(dsa, dmaaddr + tbc,
+ dmablks * A_BSIZE - tbc + legetl(dsa->data_buf.dbc));
+ /* copy changes into scratch registers */
+ n->scratcha[2] = dsa->dmablks;
+ lesetl(n->scratchb, dsa->dmancr);
+ cont = E_data_block_mismatch_recover;
+ }
+ else if (sa == E_id_out_mismatch) {
+ /*
+ * target switched phases while attention held during
+ * message out. The possibilities are:
+ * 1. It didn't like the last message. This is indicated
+ * by the new phase being message_in. Use script to recover
+ *
+ * 2. It's not SCSI-II compliant. The new phase will be other
+ * than message_in. We should also indicate that the device
+ * is asynchronous, if it's the SDTR that got ignored
+ *
+ * For now, if the phase switch is not to message_in, and
+ * and it happens after IDENTIFY and before SDTR, we
+ * notify the negotiation state machine.
+ */
+ ulong lim = legetl(dsa->msg_out_buf.dbc);
+ uchar p = n->sstat1 & 7;
+ dbc = write_mismatch_recover(n, dsa);
+ tbc = lim - dbc;
+ IPRINT("sd53c8xx: %d/%d: msg_out_mismatch: %lud/%lud sent, phase %s\n",
+ dsa->target, dsa->lun, tbc, lim, phase[p]);
+ if (p != MessageIn && tbc == 1) {
+ msgsm(dsa, c, A_SIR_EV_PHASE_SWITCH_AFTER_ID, &cont, &wakeme);
+ }
+ else
+ cont = E_id_out_mismatch_recover;
+ }
+ else if (sa == E_cmd_out_mismatch) {
+ /*
+ * probably the command count is longer than the device wants ...
+ */
+ ulong lim = legetl(dsa->cmd_buf.dbc);
+ uchar p = n->sstat1 & 7;
+ dbc = write_mismatch_recover(n, dsa);
+ tbc = lim - dbc;
+ IPRINT("sd53c8xx: %d/%d: cmd_out_mismatch: %lud/%lud sent, phase %s\n",
+ dsa->target, dsa->lun, tbc, lim, phase[p]);
+ USED(p, tbc);
+ cont = E_to_decisions;
+ }
+ else {
+ IPRINT("sd53c8xx: %d/%d: ma sa=%.8lux wanted=%s got=%s\n",
+ dsa->target, dsa->lun, sa,
+ phase[n->dcmd & 7],
+ phase[n->sstat1 & 7]);
+ dumpncrregs(c, 1);
+ dsa->p9status = SDeio; /* chf */
+ wakeme = 1;
+ }
+ }
+ /*else*/ if (sist & 0x400) {
+ if (DEBUG(0))
+ IPRINT("sd53c8xx: %d/%d Sto\n", dsa->target, dsa->lun);
+ dsa->p9status = SDtimeout;
+ dsa->stateb = A_STATE_DONE;
+ softreset(c);
+ cont = E_issue_check;
+ wakeme = 1;
+ }
+ if (sist & 0x1) {
+ IPRINT("sd53c8xx: %d/%d: parity error\n", dsa->target, dsa->lun);
+ dsa->parityerror = 1;
+ }
+ if (sist & 0x4) {
+ IPRINT("sd53c8xx: %d/%d: unexpected disconnect\n",
+ dsa->target, dsa->lun);
+ dumpncrregs(c, 1);
+ //wakeme = 1;
+ dsa->p9status = SDeio;
+ }
+ }
+ if (istat & Dip) {
+ if (DEBUG(1))
+ IPRINT("dstat = %.2x\n", dstat);
+ /*else*/ if (dstat & Ssi) {
+ ulong *p = DMASEG_TO_KADDR(legetl(n->dsp));
+ ulong w = (uchar *)p - (uchar *)c->script;
+ IPRINT("[%lux]", w);
+ USED(w);
+ cont = -2; /* restart */
+ }
+ if (dstat & Sir) {
+ switch (legetl(n->dsps)) {
+ case A_SIR_MSG_IO_COMPLETE:
+ dsa->p9status = dsa->status;
+ wakeme = 1;
+ break;
+ case A_SIR_MSG_SDTR:
+ case A_SIR_MSG_WDTR:
+ case A_SIR_MSG_REJECT:
+ case A_SIR_EV_RESPONSE_OK:
+ msgsm(dsa, c, legetl(n->dsps), &cont, &wakeme);
+ break;
+ case A_SIR_MSG_IGNORE_WIDE_RESIDUE:
+ /* back up one in the data transfer */
+ IPRINT("sd53c8xx: %d/%d: ignore wide residue %d, WSR = %d\n",
+ dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1);
+ if (dsa->dmablks == 0 && dsa->flag)
+ IPRINT("sd53c8xx: %d/%d: transfer over; residue ignored\n",
+ dsa->target, dsa->lun);
+ else
+ calcblockdma(dsa, legetl(dsa->dmaaddr) - 1,
+ dsa->dmablks * A_BSIZE + legetl(dsa->data_buf.dbc) + 1);
+ cont = -2;
+ break;
+ case A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT:
+ IPRINT("sd53c8xx: %d: not msg_in after reselect (%s)",
+ n->ssid & 7, phase[n->sstat1 & 7]);
+ dsa = dsafind(c, n->ssid & 7, -1, A_STATE_DISCONNECTED);
+ dumpncrregs(c, 1);
+ wakeme = 1;
+ break;
+ case A_SIR_NOTIFY_MSG_IN:
+ IPRINT("sd53c8xx: %d/%d: msg_in %d\n",
+ dsa->target, dsa->lun, n->sfbr);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DISC:
+ IPRINT("sd53c8xx: %d/%d: disconnect:", dsa->target, dsa->lun);
+ goto dsadump;
+ case A_SIR_NOTIFY_STATUS:
+ IPRINT("sd53c8xx: %d/%d: status\n", dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_COMMAND:
+ IPRINT("sd53c8xx: %d/%d: commands\n", dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DATA_IN:
+ IPRINT("sd53c8xx: %d/%d: data in a %lx b %lx\n",
+ dsa->target, dsa->lun, legetl(n->scratcha), legetl(n->scratchb));
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_BLOCK_DATA_IN:
+ IPRINT("sd53c8xx: %d/%d: block data in: a2 %x b %lx\n",
+ dsa->target, dsa->lun, n->scratcha[2], legetl(n->scratchb));
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DATA_OUT:
+ IPRINT("sd53c8xx: %d/%d: data out\n", dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DUMP:
+ IPRINT("sd53c8xx: %d/%d: dump\n", dsa->target, dsa->lun);
+ dumpncrregs(c, 1);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DUMP2:
+ IPRINT("sd53c8xx: %d/%d: dump2:", dsa->target, dsa->lun);
+ IPRINT(" sa %lux", legetl(n->dsp) - c->scriptpa);
+ IPRINT(" dsa %lux", legetl(n->dsa));
+ IPRINT(" sfbr %ux", n->sfbr);
+ IPRINT(" a %lux", n->scratcha);
+ IPRINT(" b %lux", legetl(n->scratchb));
+ IPRINT(" ssid %ux", n->ssid);
+ IPRINT("\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_WAIT_RESELECT:
+ IPRINT("sd53c8xx: wait reselect\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_RESELECT:
+ IPRINT("sd53c8xx: reselect: ssid %.2x sfbr %.2x at %ld\n",
+ n->ssid, n->sfbr, TK2MS(m->ticks));
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_ISSUE:
+ IPRINT("sd53c8xx: %d/%d: issue:", dsa->target, dsa->lun);
+ dsadump:
+ IPRINT(" tgt=%d", dsa->target);
+ IPRINT(" time=%ld", TK2MS(m->ticks));
+ IPRINT("\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_ISSUE_CHECK:
+ IPRINT("sd53c8xx: issue check\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_SIGP:
+ IPRINT("sd53c8xx: responded to SIGP\n");
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_DUMP_NEXT_CODE: {
+ ulong *dsp = DMASEG_TO_KADDR(legetl(n->dsp));
+ int x;
+ IPRINT("sd53c8xx: code at %lux", dsp - c->script);
+ for (x = 0; x < 6; x++)
+ IPRINT(" %.8lux", dsp[x]);
+ IPRINT("\n");
+ USED(dsp);
+ cont = -2;
+ break;
+ }
+ case A_SIR_NOTIFY_WSR:
+ IPRINT("sd53c8xx: %d/%d: WSR set\n", dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_LOAD_SYNC:
+ IPRINT("sd53c8xx: %d/%d: scntl=%.2x sxfer=%.2x\n",
+ dsa->target, dsa->lun, n->scntl3, n->sxfer);
+ cont = -2;
+ break;
+ case A_SIR_NOTIFY_RESELECTED_ON_SELECT:
+ IPRINT("sd53c8xx: %d/%d: reselected during select\n",
+ dsa->target, dsa->lun);
+ cont = -2;
+ break;
+ default:
+ IPRINT("sd53c8xx: %d/%d: script error %ld\n",
+ dsa->target, dsa->lun, legetl(n->dsps));
+ dumpncrregs(c, 1);
+ wakeme = 1;
+ }
+ }
+ /*else*/ if (dstat & Iid) {
+ ulong addr = legetl(n->dsp);
+ ulong dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0];
+ IPRINT("sd53c8xx: %d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n",
+ dsa->target, dsa->lun,
+ addr, addr - c->scriptpa, dbc);
+ addr = (ulong)DMASEG_TO_KADDR(addr);
+ IPRINT("%.8lux %.8lux %.8lux\n",
+ *(ulong *)(addr - 12), *(ulong *)(addr - 8), *(ulong *)(addr - 4));
+ USED(addr, dbc);
+ dsa->p9status = SDeio;
+ wakeme = 1;
+ }
+ /*else*/ if (dstat & Bf) {
+ IPRINT("sd53c8xx: %d/%d: Bus Fault\n", dsa->target, dsa->lun);
+ dumpncrregs(c, 1);
+ dsa->p9status = SDeio;
+ wakeme = 1;
+ }
+ }
+ if (cont == -2)
+ ncrcontinue(c);
+ else if (cont >= 0)
+ start(c, cont);
+ if (wakeme){
+ if(dsa->p9status == SDnostatus)
+ dsa->p9status = SDeio;
+ wakeup(dsa);
+ }
+ iunlock(c);
+ if (DEBUG(1)) {
+ IPRINT("sd53c8xx: int end 1\n");
+ }
+}
+
+static int
+done(void *arg)
+{
+ return ((Dsa *)arg)->p9status != SDnostatus;
+}
+
+static void
+setmovedata(Movedata *d, ulong pa, ulong bc)
+{
+ d->pa[0] = pa;
+ d->pa[1] = pa>>8;
+ d->pa[2] = pa>>16;
+ d->pa[3] = pa>>24;
+ d->dbc[0] = bc;
+ d->dbc[1] = bc>>8;
+ d->dbc[2] = bc>>16;
+ d->dbc[3] = bc>>24;
+}
+
+static void
+advancedata(Movedata *d, long v)
+{
+ lesetl(d->pa, legetl(d->pa) + v);
+ lesetl(d->dbc, legetl(d->dbc) - v);
+}
+
+static void
+dumpwritedata(uchar *data, int datalen)
+{
+ int i;
+ uchar *bp;
+ if (!DEBUG(0)){
+ USED(data, datalen);
+ return;
+ }
+
+ if (datalen) {
+ KPRINT("sd53c8xx:write:");
+ for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++)
+ KPRINT("%.2ux", *bp);
+ if (i < datalen) {
+ KPRINT("...");
+ }
+ KPRINT("\n");
+ }
+}
+
+static void
+dumpreaddata(uchar *data, int datalen)
+{
+ int i;
+ uchar *bp;
+ if (!DEBUG(0)){
+ USED(data, datalen);
+ return;
+ }
+
+ if (datalen) {
+ KPRINT("sd53c8xx:read:");
+ for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++)
+ KPRINT("%.2ux", *bp);
+ if (i < datalen) {
+ KPRINT("...");
+ }
+ KPRINT("\n");
+ }
+}
+
+static void
+busreset(Controller *c)
+{
+ int x, ntarget;
+
+ /* bus reset */
+ c->n->scntl1 |= (1 << 3);
+ delay(500);
+ c->n->scntl1 &= ~(1 << 3);
+ if(!(c->v->feature & Wide))
+ ntarget = 8;
+ else
+ ntarget = MAXTARGET;
+ for (x = 0; x < ntarget; x++) {
+ setwide(0, c, x, 0);
+#ifndef ASYNC_ONLY
+ c->s[x] = NeitherDone;
+#endif
+ }
+ c->capvalid = 0;
+}
+
+static void
+reset(Controller *c)
+{
+ /* should wakeup all pending tasks */
+ softreset(c);
+ busreset(c);
+}
+
+static int
+symrio(SDreq* r)
+{
+ Dsa *d;
+ uchar *bp;
+ Controller *c;
+ uchar target_expo, my_expo;
+ int bc, check, status, target;
+
+ if((target = r->unit->subno) == 0x07)
+ return r->status = SDtimeout; /* assign */
+ c = r->unit->dev->ctlr;
+
+ check = 0;
+ d = dsaalloc(c, target, r->lun);
+
+ qlock(&c->q[target]); /* obtain access to target */
+docheck:
+ /* load the transfer control stuff */
+ d->scsi_id_buf[0] = 0;
+ d->scsi_id_buf[1] = c->sxfer[target];
+ d->scsi_id_buf[2] = target;
+ d->scsi_id_buf[3] = c->scntl3[target];
+ synctodsa(d, c);
+
+ bc = 0;
+
+ d->msg_out[bc] = 0x80 | r->lun;
+
+#ifndef NO_DISCONNECT
+ d->msg_out[bc] |= (1 << 6);
+#endif
+ bc++;
+
+ /* work out what to do about negotiation */
+ switch (c->s[target]) {
+ default:
+ KPRINT("sd53c8xx: %d: strange nego state %d\n", target, c->s[target]);
+ c->s[target] = NeitherDone;
+ /* fall through */
+ case NeitherDone:
+ if ((c->capvalid & (1 << target)) == 0)
+ break;
+ target_expo = (c->cap[target] >> 5) & 3;
+ my_expo = (c->v->feature & Wide) != 0;
+ if (target_expo < my_expo)
+ my_expo = target_expo;
+#ifdef ALWAYS_DO_WDTR
+ bc += buildwdtrmsg(d->msg_out + bc, my_expo);
+ KPRINT("sd53c8xx: %d: WDTN: initiating expo %d\n", target, my_expo);
+ c->s[target] = WideInit;
+ break;
+#else
+ if (my_expo) {
+ bc += buildwdtrmsg(d->msg_out + bc, (c->v->feature & Wide) ? 1 : 0);
+ KPRINT("sd53c8xx: %d: WDTN: initiating expo %d\n", target, my_expo);
+ c->s[target] = WideInit;
+ break;
+ }
+ KPRINT("sd53c8xx: %d: WDTN: narrow\n", target);
+ /* fall through */
+#endif
+ case WideDone:
+ if (c->cap[target] & (1 << 4)) {
+ KPRINT("sd53c8xx: %d: SDTN: initiating %d %d\n", target, c->tpf, c->v->maxsyncoff);
+ bc += buildsdtrmsg(d->msg_out + bc, c->tpf, c->v->maxsyncoff);
+ c->s[target] = SyncInit;
+ break;
+ }
+ KPRINT("sd53c8xx: %d: SDTN: async only\n", target);
+ c->s[target] = BothDone;
+ break;
+
+ case BothDone:
+ break;
+ }
+
+ setmovedata(&d->msg_out_buf, DMASEG(d->msg_out), bc);
+ setmovedata(&d->cmd_buf, DMASEG(r->cmd), r->clen);
+ calcblockdma(d, DMASEG(r->data), r->dlen);
+
+ if (DEBUG(0)) {
+ KPRINT("sd53c8xx: %d/%d: exec: ", target, r->lun);
+ for (bp = r->cmd; bp < &r->cmd[r->clen]; bp++)
+ KPRINT("%.2ux", *bp);
+ KPRINT("\n");
+ if (!r->write)
+ KPRINT("sd53c8xx: %d/%d: exec: limit=(%d)%ld\n",
+ target, r->lun, d->dmablks, legetl(d->data_buf.dbc));
+ else
+ dumpwritedata(r->data, r->dlen);
+ }
+
+ setmovedata(&d->status_buf, DMASEG(&d->status), 1);
+
+ d->p9status = SDnostatus;
+ d->parityerror = 0;
+
+ d->stateb = A_STATE_ISSUE; /* start operation */
+
+ ilock(c);
+ if (c->ssm)
+ c->n->dcntl |= 0x10; /* SSI */
+ if (c->running) {
+ c->n->istat |= Sigp;
+ }
+ else {
+ start(c, E_issue_check);
+ }
+ iunlock(c);
+
+ while(waserror())
+ ;
+ tsleep(d, done, d, 30 * 1000);
+ poperror();
+
+ if (!done(d)) {
+ KPRINT("sd53c8xx: %d/%d: exec: Timed out\n", target, r->lun);
+ dumpncrregs(c, 0);
+ dsafree(c, d);
+ reset(c);
+ qunlock(&c->q[target]);
+ r->status = SDtimeout;
+ return r->status = SDtimeout; /* assign */
+ }
+
+ if((status = d->p9status) == SDeio)
+ c->s[target] = NeitherDone;
+ if (d->parityerror) {
+ status = SDeio;
+ }
+
+ /*
+ * adjust datalen
+ */
+ r->rlen = r->dlen;
+ if (d->dmablks > 0)
+ r->rlen -= d->dmablks * A_BSIZE;
+ else if (d->flag == 0)
+ r->rlen -= legetl(d->data_buf.dbc);
+ if(!r->write)
+ dumpreaddata(r->data, r->rlen);
+ if (DEBUG(0))
+ KPRINT("53c8xx: %d/%d: exec: p9status=%d status %d rlen %ld\n",
+ target, r->lun, d->p9status, status, r->rlen);
+ /*
+ * spot the identify
+ */
+ if ((c->capvalid & (1 << target)) == 0
+ && (status == SDok || status == SDcheck)
+ && r->cmd[0] == 0x12 && r->dlen >= 8) {
+ c->capvalid |= 1 << target;
+ bp = r->data;
+ c->cap[target] = bp[7];
+ KPRINT("sd53c8xx: %d: capabilities %.2x\n", target, bp[7]);
+ }
+ if(!check && status == SDcheck && !(r->flags & SDnosense)){
+ check = 1;
+ r->write = 0;
+ memset(r->cmd, 0, sizeof(r->cmd));
+ r->cmd[0] = 0x03;
+ r->cmd[1] = r->lun<<5;
+ r->cmd[4] = sizeof(r->sense)-1;
+ r->clen = 6;
+ r->data = r->sense;
+ r->dlen = sizeof(r->sense)-1;
+ /*
+ * Clear out the microcode state
+ * so the Dsa can be re-used.
+ */
+ lesetl(d->state, A_STATE_ALLOCATED);
+ goto docheck;
+ }
+ qunlock(&c->q[target]);
+ dsafree(c, d);
+
+ if(status == SDok && check){
+ status = SDcheck;
+ r->flags |= SDvalidsense;
+ }
+ KPRINT("sd53c8xx: %d: r flags %8.8uX status %d rlen %ld\n",
+ target, r->flags, status, r->rlen);
+ return r->status = status;
+}
+
+static void
+cribbios(Controller *c)
+{
+ c->bios.scntl3 = c->n->scntl3;
+ c->bios.stest2 = c->n->stest2;
+ print("sd53c8xx: bios scntl3(%.2x) stest2(%.2x)\n", c->bios.scntl3, c->bios.stest2);
+}
+
+static int
+bios_set_differential(Controller *c)
+{
+ /* Concept lifted from FreeBSD - thanks Gerard */
+ /* basically, if clock conversion factors are set, then there is
+ * evidence the bios had a go at the chip, and if so, it would
+ * have set the differential enable bit in stest2
+ */
+ return (c->bios.scntl3 & 7) != 0 && (c->bios.stest2 & 0x20) != 0;
+}
+
+#define NCR_VID 0x1000
+#define NCR_810_DID 0x0001
+#define NCR_820_DID 0x0002 /* don't know enough about this one to support it */
+#define NCR_825_DID 0x0003
+#define NCR_815_DID 0x0004
+#define SYM_810AP_DID 0x0005
+#define SYM_860_DID 0x0006
+#define SYM_896_DID 0x000b
+#define SYM_895_DID 0x000c
+#define SYM_885_DID 0x000d /* ditto */
+#define SYM_875_DID 0x000f /* ditto */
+#define SYM_1010_DID 0x0020
+#define SYM_1011_DID 0x0021
+#define SYM_875J_DID 0x008f
+
+static Variant variant[] = {
+{ NCR_810_DID, 0x0f, "NCR53C810", Burst16, 8, 24, 0 },
+{ NCR_810_DID, 0x1f, "SYM53C810ALV", Burst16, 8, 24, Prefetch },
+{ NCR_810_DID, 0xff, "SYM53C810A", Burst16, 8, 24, Prefetch },
+{ SYM_810AP_DID, 0xff, "SYM53C810AP", Burst16, 8, 24, Prefetch },
+{ NCR_815_DID, 0xff, "NCR53C815", Burst16, 8, 24, BurstOpCodeFetch },
+{ NCR_825_DID, 0x0f, "NCR53C825", Burst16, 8, 24, Wide|BurstOpCodeFetch|Differential },
+{ NCR_825_DID, 0xff, "SYM53C825A", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide },
+{ SYM_860_DID, 0x0f, "SYM53C860", Burst16, 8, 24, Prefetch|Ultra },
+{ SYM_860_DID, 0xff, "SYM53C860LV", Burst16, 8, 24, Prefetch|Ultra },
+{ SYM_875_DID, 0x01, "SYM53C875r1", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra },
+{ SYM_875_DID, 0xff, "SYM53C875", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
+{ SYM_875J_DID, 0xff, "SYM53C875j", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Differential|Wide|Ultra|ClockDouble },
+{ SYM_885_DID, 0xff, "SYM53C885", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|ClockDouble },
+{ SYM_895_DID, 0xff, "SYM53C895", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+{ SYM_896_DID, 0xff, "SYM53C896", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+{ SYM_1010_DID, 0xff, "SYM53C1010", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+{ SYM_1011_DID, 0xff, "SYM53C1010", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 },
+};
+
+
+static int
+xfunc(Controller *c, enum na_external x, unsigned long *v)
+{
+ switch (x) {
+ default:
+ print("xfunc: can't find external %d\n", x);
+ return 0;
+ case X_scsi_id_buf:
+ *v = offsetof(Dsa, scsi_id_buf[0]);
+ break;
+ case X_msg_out_buf:
+ *v = offsetof(Dsa, msg_out_buf);
+ break;
+ case X_cmd_buf:
+ *v = offsetof(Dsa, cmd_buf);
+ break;
+ case X_data_buf:
+ *v = offsetof(Dsa, data_buf);
+ break;
+ case X_status_buf:
+ *v = offsetof(Dsa, status_buf);
+ break;
+ case X_dsa_head:
+ *v = DMASEG(&c->dsalist.head[0]);
+ break;
+ }
+ return 1;
+}
+
+static int
+na_fixup(Controller *c, ulong pa_reg,
+ struct na_patch *patch, int patches,
+ int (*externval)(Controller*, int, ulong*))
+{
+ int p;
+ int v;
+ ulong *script, pa_script;
+ unsigned long lw, lv;
+
+ script = c->script;
+ pa_script = c->scriptpa;
+ for (p = 0; p < patches; p++) {
+ switch (patch[p].type) {
+ case 1:
+ /* script relative */
+ script[patch[p].lwoff] += pa_script;
+ break;
+ case 2:
+ /* register i/o relative */
+ script[patch[p].lwoff] += pa_reg;
+ break;
+ case 3:
+ /* data external */
+ lw = script[patch[p].lwoff];
+ v = (lw >> 8) & 0xff;
+ if (!(*externval)(c, v, &lv))
+ return 0;
+ v = lv & 0xff;
+ script[patch[p].lwoff] = (lw & 0xffff00ffL) | (v << 8);
+ break;
+ case 4:
+ /* 32 bit external */
+ lw = script[patch[p].lwoff];
+ if (!(*externval)(c, lw, &lv))
+ return 0;
+ script[patch[p].lwoff] = lv;
+ break;
+ case 5:
+ /* 24 bit external */
+ lw = script[patch[p].lwoff];
+ if (!(*externval)(c, lw & 0xffffff, &lv))
+ return 0;
+ script[patch[p].lwoff] = (lw & 0xff000000L) | (lv & 0xffffffL);
+ break;
+ }
+ }
+ return 1;
+}
+
+static SDev*
+sympnp(void)
+{
+ int ba;
+ Pcidev *p;
+ Variant *v;
+ void *scriptma;
+ Controller *ctlr;
+ SDev *sdev, *head, *tail;
+ ulong regpa, *script, scriptpa;
+
+ p = nil;
+ head = tail = nil;
+ while(p = pcimatch(p, NCR_VID, 0)){
+ for(v = variant; v < &variant[nelem(variant)]; v++){
+ if(p->did == v->did && p->rid <= v->maxrid)
+ break;
+ }
+ if(v >= &variant[nelem(variant)])
+ continue;
+ print("sd53c8xx: %s rev. 0x%2.2x intr=%d command=%4.4uX\n",
+ v->name, p->rid, p->intl, p->pcr);
+
+ regpa = p->mem[1].bar;
+ ba = 2;
+ if(regpa & 0x04){
+ if(p->mem[2].bar)
+ continue;
+ ba++;
+ }
+ regpa = upamalloc(regpa & ~0x0F, p->mem[1].size, 0);
+ if(regpa == 0)
+ continue;
+
+ script = nil;
+ scriptpa = 0;
+ scriptma = nil;
+ if((v->feature & LocalRAM) && sizeof(na_script) <= 4096){
+ scriptpa = p->mem[ba].bar;
+ if((scriptpa & 0x04) && p->mem[ba+1].bar){
+ upafree(regpa, p->mem[1].size);
+ continue;
+ }
+ scriptpa = upamalloc(scriptpa & ~0x0F,
+ p->mem[ba].size, 0);
+ if(scriptpa)
+ script = KADDR(scriptpa);
+ }
+ if(scriptpa == 0){
+ /*
+ * Either the map failed, or this chip does not have
+ * local RAM. It will need a copy of the microcode.
+ */
+ scriptma = malloc(sizeof(na_script));
+ if(scriptma == nil){
+ upafree(regpa, p->mem[1].size);
+ continue;
+ }
+ scriptpa = DMASEG(scriptma);
+ script = scriptma;
+ }
+
+ ctlr = malloc(sizeof(Controller));
+ sdev = malloc(sizeof(SDev));
+ if(ctlr == nil || sdev == nil){
+buggery:
+ if(ctlr)
+ free(ctlr);
+ if(sdev)
+ free(sdev);
+ if(scriptma)
+ free(scriptma);
+ else
+ upafree(scriptpa, p->mem[ba].size);
+ upafree(regpa, p->mem[1].size);
+ continue;
+ }
+
+ ctlr->n = KADDR(regpa);
+ ctlr->v = v;
+ ctlr->script = script;
+ memmove(ctlr->script, na_script, sizeof(na_script));
+ ctlr->scriptpa = scriptpa;
+ if(!na_fixup(ctlr, regpa, na_patches, NA_PATCHES, xfunc)){
+ print("script fixup failed\n");
+ goto buggery;
+ }
+ swabl(ctlr->script, ctlr->script, sizeof(na_script));
+
+ ctlr->dsalist.freechain = 0;
+ lesetl(ctlr->dsalist.head, 0);
+
+ ctlr->pcidev = p;
+
+ sdev->ifc = &sd53c8xxifc;
+ sdev->ctlr = ctlr;
+ if(!(v->feature & Wide))
+ sdev->nunit = 8;
+ else
+ sdev->nunit = MAXTARGET;
+ ctlr->sdev = sdev;
+
+ if(head != nil)
+ tail->next = sdev;
+ else
+ head = sdev;
+ tail = sdev;
+ }
+
+ return head;
+}
+
+static SDev*
+symid(SDev* sdev)
+{
+ return scsiid(sdev, &sd53c8xxifc);
+}
+
+static int
+symenable(SDev* sdev)
+{
+ Pcidev *pcidev;
+ Controller *ctlr;
+ //char name[NAMELEN];
+
+ ctlr = sdev->ctlr;
+ pcidev = ctlr->pcidev;
+
+ pcisetbme(pcidev);
+ //snprint(name, NAMELEN, "%s (%s)", sdev->name, sdev->ifc->name);
+ intrenable(pcidev->intl, interrupt, ctlr, pcidev->tbdf, name);
+
+ ilock(ctlr);
+ synctabinit(ctlr);
+ cribbios(ctlr);
+ reset(ctlr);
+ iunlock(ctlr);
+
+ return 1;
+}
+
+static int
+symdisable(SDev* sdev)
+{
+ Ncr *n;
+ Controller *ctlr;
+
+ ctlr = sdev->ctlr;
+ n = ctlr->n;
+
+ n->istat = Srst; /* software reset */
+ microdelay(1);
+ n->istat = 0;
+
+ n->scntl1 |= (1 << 3); /* bus reset */
+ delay(500);
+ n->scntl1 &= ~(1 << 3);
+
+ return 1;
+}
+
+SDifc sd53c8xxifc = {
+ "53c8xx", /* name */
+
+ sympnp, /* pnp */
+ nil, /* legacy */
+ symid, /* id */
+ symenable, /* enable */
+ symdisable, /* disable */
+
+ scsiverify, /* verify */
+ scsionline, /* online */
+ symrio, /* rio */
+ nil, /* rctl */
+ nil, /* wctl */
+
+ scsibio, /* bio */
+};
--- /dev/null
+++ b/os/boot.original/pc/sd53c8xx.i
@@ -1,0 +1,769 @@
+unsigned long na_script[] = {
+ /* extern scsi_id_buf */
+ /* extern msg_out_buf */
+ /* extern cmd_buf */
+ /* extern data_buf */
+ /* extern status_buf */
+ /* extern msgin_buf */
+ /* extern dsa_0 */
+ /* extern dsa_1 */
+ /* extern dsa_head */
+ /* SIR_MSG_IO_COMPLETE = 0 */
+ /* error_not_cmd_complete = 1 */
+ /* error_disconnected = 2 */
+ /* error_reselected = 3 */
+ /* error_unexpected_phase = 4 */
+ /* error_weird_message = 5 */
+ /* SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT = 6 */
+ /* error_not_identify_after_reselect = 7 */
+ /* error_too_much_data = 8 */
+ /* error_too_little_data = 9 */
+ /* SIR_MSG_REJECT = 10 */
+ /* SIR_MSG_SDTR = 11 */
+ /* SIR_EV_RESPONSE_OK = 12 */
+ /* error_sigp_set = 13 */
+ /* SIR_EV_PHASE_SWITCH_AFTER_ID = 14 */
+ /* SIR_MSG_WDTR = 15 */
+ /* SIR_MSG_IGNORE_WIDE_RESIDUE = 16 */
+ /* SIR_NOTIFY_DISC = 100 */
+ /* SIR_NOTIFY_RESELECT = 101 */
+ /* SIR_NOTIFY_MSG_IN = 102 */
+ /* SIR_NOTIFY_STATUS = 103 */
+ /* SIR_NOTIFY_DUMP = 104 */
+ /* SIR_NOTIFY_DUMP2 = 105 */
+ /* SIR_NOTIFY_SIGP = 106 */
+ /* SIR_NOTIFY_ISSUE = 107 */
+ /* SIR_NOTIFY_WAIT_RESELECT = 108 */
+ /* SIR_NOTIFY_ISSUE_CHECK = 109 */
+ /* SIR_NOTIFY_DUMP_NEXT_CODE = 110 */
+ /* SIR_NOTIFY_COMMAND = 111 */
+ /* SIR_NOTIFY_DATA_IN = 112 */
+ /* SIR_NOTIFY_DATA_OUT = 113 */
+ /* SIR_NOTIFY_BLOCK_DATA_IN = 114 */
+ /* SIR_NOTIFY_WSR = 115 */
+ /* SIR_NOTIFY_LOAD_SYNC = 116 */
+ /* SIR_NOTIFY_RESELECTED_ON_SELECT = 117 */
+ /* STATE_FREE = 0 */
+ /* STATE_ALLOCATED = 1 */
+ /* STATE_ISSUE = 2 */
+ /* STATE_DISCONNECTED = 3 */
+ /* STATE_DONE = 4 */
+ /* RESULT_OK = 0 */
+ /* MSG_IDENTIFY = 0x80 */
+ /* MSG_DISCONNECT = 0x04 */
+ /* MSG_SAVE_DATA_POINTER = 0x02 */
+ /* MSG_RESTORE_POINTERS = 0x03 */
+ /* MSG_IGNORE_WIDE_RESIDUE = 0x23 */
+ /* X_MSG = 0x01 */
+ /* X_MSG_SDTR = 0x01 */
+ /* X_MSG_WDTR = 0x03 */
+ /* MSG_REJECT = 0x07 */
+ /* BSIZE = 512 */
+/* 0000 */ 0x80880000L, /* jump wait_for_reselection */
+/* 0004 */ 0x00000514L,
+/* 0008 */ 0x88880000L, /* call load_sync */
+/* 000c */ 0x0000074cL,
+/* 0010 */ 0x60000200L, /* clear target */
+/* 0014 */ 0x00000000L,
+/* 0018 */ 0x47000000L, /* select atn from scsi_id_buf, reselected_on_select */
+/* 001c */ 0x000004ecL,
+/* 0020 */ 0x878b0000L, /* jump start1, when msg_in */
+/* 0024 */ 0x00000000L,
+/* 0028 */ 0x1e000000L, /* move from msg_out_buf, when msg_out */
+/* 002c */ 0x00000001L,
+/* 0030 */ 0x868b0000L, /* jump start1, when msg_out */
+/* 0034 */ 0x00fffff0L,
+/* 0038 */ 0x82830000L, /* jump to_decisions, when not cmd */
+/* 003c */ 0x000005f0L,
+/* 0040 */ 0x60000008L, /* clear atn */
+/* 0044 */ 0x00000000L,
+/* 0048 */ 0x1a000000L, /* move from cmd_buf, when cmd */
+/* 004c */ 0x00000002L,
+/* 0050 */ 0x81830000L, /* jump to_decisions, when not data_in */
+/* 0054 */ 0x000005d8L,
+/* 0058 */ 0xc0000004L, /* move memory 4, state, scratcha */
+/* 005c */ 0x00000678L,
+/* 0060 */ 0x00000034L,
+/* 0064 */ 0xc0000004L, /* move memory 4, dmaaddr, scratchb */
+/* 0068 */ 0x0000067cL,
+/* 006c */ 0x0000005cL,
+/* 0070 */ 0x72360000L, /* move scratcha2 to sfbr */
+/* 0074 */ 0x00000000L,
+/* 0078 */ 0x808c0000L, /* jump data_in_normal, if 0 */
+/* 007c */ 0x00000078L,
+/* 0080 */ 0x29000200L, /* move BSIZE, ptr dmaaddr, when data_in */
+/* 0084 */ 0x0000067cL,
+/* 0088 */ 0x7e5d0200L, /* move scratchb1 + BSIZE / 256 to scratchb1 */
+/* 008c */ 0x00000000L,
+/* 0090 */ 0x7f5e0000L, /* move scratchb2 + 0 to scratchb2 with carry */
+/* 0094 */ 0x00000000L,
+/* 0098 */ 0x7f5f0000L, /* move scratchb3 + 0 to scratchb3 with carry */
+/* 009c */ 0x00000000L,
+/* 00a0 */ 0x7e36ff00L, /* move scratcha2 + 255 to scratcha2 */
+/* 00a4 */ 0x00000000L,
+/* 00a8 */ 0xc0000004L, /* move memory 4, scratchb, dmaaddr */
+/* 00ac */ 0x0000005cL,
+/* 00b0 */ 0x0000067cL,
+/* 00b4 */ 0x818b0000L, /* jump data_in_block_loop, when data_in */
+/* 00b8 */ 0x00ffffb4L,
+/* 00bc */ 0xc0000004L, /* move memory 4, scratcha, state */
+/* 00c0 */ 0x00000034L,
+/* 00c4 */ 0x00000678L,
+/* 00c8 */ 0x88880000L, /* call save_state */
+/* 00cc */ 0x000005e0L,
+/* 00d0 */ 0x80880000L, /* jump to_decisions */
+/* 00d4 */ 0x00000558L,
+/* 00d8 */ 0xc0000004L, /* move memory 4, scratchb, dmaaddr */
+/* 00dc */ 0x0000005cL,
+/* 00e0 */ 0x0000067cL,
+/* 00e4 */ 0xc0000004L, /* move memory 4, scratcha, state */
+/* 00e8 */ 0x00000034L,
+/* 00ec */ 0x00000678L,
+/* 00f0 */ 0x80880000L, /* jump to_decisions */
+/* 00f4 */ 0x00000538L,
+/* 00f8 */ 0x72370000L, /* move scratcha3 to sfbr */
+/* 00fc */ 0x00000000L,
+/* 0100 */ 0x98040000L, /* int error_too_much_data, if not 0 */
+/* 0104 */ 0x00000008L,
+/* 0108 */ 0x19000000L, /* move from data_buf, when data_in */
+/* 010c */ 0x00000003L,
+/* 0110 */ 0x78370100L, /* move 1 to scratcha3 */
+/* 0114 */ 0x00000000L,
+/* 0118 */ 0xc0000004L, /* move memory 4, scratcha, state */
+/* 011c */ 0x00000034L,
+/* 0120 */ 0x00000678L,
+/* 0124 */ 0x88880000L, /* call save_state */
+/* 0128 */ 0x00000584L,
+/* 012c */ 0x80880000L, /* jump post_data_to_decisions */
+/* 0130 */ 0x0000052cL,
+/* 0134 */ 0xc0000004L, /* move memory 4, state, scratcha */
+/* 0138 */ 0x00000678L,
+/* 013c */ 0x00000034L,
+/* 0140 */ 0xc0000004L, /* move memory 4, dmaaddr, scratchb */
+/* 0144 */ 0x0000067cL,
+/* 0148 */ 0x0000005cL,
+/* 014c */ 0x72360000L, /* move scratcha2 to sfbr */
+/* 0150 */ 0x00000000L,
+/* 0154 */ 0x808c0000L, /* jump data_out_normal, if 0 */
+/* 0158 */ 0x0000005cL,
+/* 015c */ 0xc0000004L, /* move memory 4, dmaaddr, scratchb */
+/* 0160 */ 0x0000067cL,
+/* 0164 */ 0x0000005cL,
+/* 0168 */ 0x28000200L, /* move BSIZE, ptr dmaaddr, when data_out */
+/* 016c */ 0x0000067cL,
+/* 0170 */ 0x7e5d0200L, /* move scratchb1 + BSIZE / 256 to scratchb1 */
+/* 0174 */ 0x00000000L,
+/* 0178 */ 0x7f5e0000L, /* move scratchb2 + 0 to scratchb2 with carry */
+/* 017c */ 0x00000000L,
+/* 0180 */ 0x7f5f0000L, /* move scratchb3 + 0 to scratchb3 with carry */
+/* 0184 */ 0x00000000L,
+/* 0188 */ 0x7e36ff00L, /* move scratcha2 + 255 to scratcha2 */
+/* 018c */ 0x00000000L,
+/* 0190 */ 0xc0000004L, /* move memory 4, scratchb, dmaaddr */
+/* 0194 */ 0x0000005cL,
+/* 0198 */ 0x0000067cL,
+/* 019c */ 0x808b0000L, /* jump data_out_block_loop, when data_out */
+/* 01a0 */ 0x00ffffa8L,
+/* 01a4 */ 0xc0000004L, /* move memory 4, scratcha, state */
+/* 01a8 */ 0x00000034L,
+/* 01ac */ 0x00000678L,
+/* 01b0 */ 0x80880000L, /* jump to_decisions */
+/* 01b4 */ 0x00000478L,
+/* 01b8 */ 0x72370000L, /* move scratcha3 to sfbr */
+/* 01bc */ 0x00000000L,
+/* 01c0 */ 0x98040000L, /* int error_too_little_data, if not 0 */
+/* 01c4 */ 0x00000009L,
+/* 01c8 */ 0x18000000L, /* move from data_buf, when data_out */
+/* 01cc */ 0x00000003L,
+/* 01d0 */ 0x78370100L, /* move 1 to scratcha3 */
+/* 01d4 */ 0x00000000L,
+/* 01d8 */ 0xc0000004L, /* move memory 4, scratcha, state */
+/* 01dc */ 0x00000034L,
+/* 01e0 */ 0x00000678L,
+/* 01e4 */ 0x88880000L, /* call save_state */
+/* 01e8 */ 0x000004c4L,
+/* 01ec */ 0x80880000L, /* jump post_data_to_decisions */
+/* 01f0 */ 0x0000046cL,
+/* 01f4 */ 0x1b000000L, /* move from status_buf, when status */
+/* 01f8 */ 0x00000004L,
+/* 01fc */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
+/* 0200 */ 0x00000004L,
+/* 0204 */ 0x0f000001L, /* move 1, scratcha, when msg_in */
+/* 0208 */ 0x00000034L,
+/* 020c */ 0x808c0007L, /* jump rejected, if MSG_REJECT */
+/* 0210 */ 0x00000088L,
+/* 0214 */ 0x808c0004L, /* jump disconnected, if MSG_DISCONNECT */
+/* 0218 */ 0x00000298L,
+/* 021c */ 0x808c0002L, /* jump msg_in_skip, if MSG_SAVE_DATA_POINTER */
+/* 0220 */ 0x00000090L,
+/* 0224 */ 0x808c0003L, /* jump msg_in_skip, if MSG_RESTORE_POINTERS */
+/* 0228 */ 0x00000088L,
+/* 022c */ 0x808c0023L, /* jump ignore_wide, if MSG_IGNORE_WIDE_RESIDUE */
+/* 0230 */ 0x000001f0L,
+/* 0234 */ 0x808c0001L, /* jump extended, if X_MSG */
+/* 0238 */ 0x00000088L,
+/* 023c */ 0x98040000L, /* int error_not_cmd_complete, if not 0 */
+/* 0240 */ 0x00000001L,
+/* 0244 */ 0x7c027e00L, /* move scntl2&0x7e to scntl2 */
+/* 0248 */ 0x00000000L,
+/* 024c */ 0x60000040L, /* clear ack */
+/* 0250 */ 0x00000000L,
+/* 0254 */ 0x48000000L, /* wait disconnect */
+/* 0258 */ 0x00000000L,
+/* 025c */ 0xc0000004L, /* move memory 4, state, scratcha */
+/* 0260 */ 0x00000678L,
+/* 0264 */ 0x00000034L,
+/* 0268 */ 0x78340400L, /* move STATE_DONE to scratcha0 */
+/* 026c */ 0x00000000L,
+/* 0270 */ 0x78350000L, /* move RESULT_OK to scratcha1 */
+/* 0274 */ 0x00000000L,
+/* 0278 */ 0xc0000004L, /* move memory 4, scratcha, state */
+/* 027c */ 0x00000034L,
+/* 0280 */ 0x00000678L,
+/* 0284 */ 0x88880000L, /* call save_state */
+/* 0288 */ 0x00000424L,
+/* 028c */ 0x98180000L, /* intfly 0 */
+/* 0290 */ 0x00000000L,
+/* 0294 */ 0x80880000L, /* jump issue_check */
+/* 0298 */ 0x0000043cL,
+/* 029c */ 0x98080000L, /* int SIR_MSG_REJECT */
+/* 02a0 */ 0x0000000aL,
+/* 02a4 */ 0x60000040L, /* clear ack */
+/* 02a8 */ 0x00000000L,
+/* 02ac */ 0x80880000L, /* jump to_decisions */
+/* 02b0 */ 0x0000037cL,
+/* 02b4 */ 0x60000040L, /* clear ack */
+/* 02b8 */ 0x00000000L,
+/* 02bc */ 0x80880000L, /* jump to_decisions */
+/* 02c0 */ 0x0000036cL,
+/* 02c4 */ 0x60000040L, /* clear ack */
+/* 02c8 */ 0x00000000L,
+/* 02cc */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
+/* 02d0 */ 0x00000004L,
+/* 02d4 */ 0x0f000001L, /* move 1, scratcha1, when msg_in */
+/* 02d8 */ 0x00000035L,
+/* 02dc */ 0x808c0003L, /* jump ext_3, if 3 */
+/* 02e0 */ 0x00000030L,
+/* 02e4 */ 0x808c0002L, /* jump ext_2, if 2 */
+/* 02e8 */ 0x00000098L,
+/* 02ec */ 0x98040001L, /* int error_weird_message, if not 1 */
+/* 02f0 */ 0x00000005L,
+/* 02f4 */ 0x60000040L, /* clear ack */
+/* 02f8 */ 0x00000000L,
+/* 02fc */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
+/* 0300 */ 0x00000004L,
+/* 0304 */ 0x0f000001L, /* move 1, scratcha1, when msg_in */
+/* 0308 */ 0x00000035L,
+/* 030c */ 0x80880000L, /* jump ext_done */
+/* 0310 */ 0x000000c8L,
+/* 0314 */ 0x60000040L, /* ext_3: clear ack */
+/* 0318 */ 0x00000000L,
+/* 031c */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
+/* 0320 */ 0x00000004L,
+/* 0324 */ 0x0f000001L, /* move 1, scratcha1, when msg_in */
+/* 0328 */ 0x00000035L,
+/* 032c */ 0x60000040L, /* clear ack */
+/* 0330 */ 0x00000000L,
+/* 0334 */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
+/* 0338 */ 0x00000004L,
+/* 033c */ 0x0f000001L, /* move 1, scratcha2, when msg_in */
+/* 0340 */ 0x00000036L,
+/* 0344 */ 0x60000040L, /* clear ack */
+/* 0348 */ 0x00000000L,
+/* 034c */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
+/* 0350 */ 0x00000004L,
+/* 0354 */ 0x0f000001L, /* move 1, scratcha3, when msg_in */
+/* 0358 */ 0x00000037L,
+/* 035c */ 0x72350000L, /* move scratcha1 to sfbr */
+/* 0360 */ 0x00000000L,
+/* 0364 */ 0x80840001L, /* jump ext_done, if not X_MSG_SDTR */
+/* 0368 */ 0x00000070L,
+/* 036c */ 0x98080000L, /* sdtr: int SIR_MSG_SDTR */
+/* 0370 */ 0x0000000bL,
+/* 0374 */ 0x60000040L, /* clear ack */
+/* 0378 */ 0x00000000L,
+/* 037c */ 0x80880000L, /* jump to_decisions */
+/* 0380 */ 0x000002acL,
+/* 0384 */ 0x60000040L, /* ext_2: clear ack */
+/* 0388 */ 0x00000000L,
+/* 038c */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
+/* 0390 */ 0x00000004L,
+/* 0394 */ 0x0f000001L, /* move 1, scratcha1, when msg_in */
+/* 0398 */ 0x00000035L,
+/* 039c */ 0x60000040L, /* clear ack */
+/* 03a0 */ 0x00000000L,
+/* 03a4 */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
+/* 03a8 */ 0x00000004L,
+/* 03ac */ 0x0f000001L, /* move 1, scratcha2, when msg_in */
+/* 03b0 */ 0x00000036L,
+/* 03b4 */ 0x72350000L, /* move scratcha1 to sfbr */
+/* 03b8 */ 0x00000000L,
+/* 03bc */ 0x80840003L, /* jump ext_done, if not X_MSG_WDTR */
+/* 03c0 */ 0x00000018L,
+/* 03c4 */ 0x98080000L, /* wdtr: int SIR_MSG_WDTR */
+/* 03c8 */ 0x0000000fL,
+/* 03cc */ 0x60000040L, /* clear ack */
+/* 03d0 */ 0x00000000L,
+/* 03d4 */ 0x80880000L, /* jump to_decisions */
+/* 03d8 */ 0x00000254L,
+/* 03dc */ 0x58000008L, /* set atn */
+/* 03e0 */ 0x00000000L,
+/* 03e4 */ 0x60000040L, /* clear ack */
+/* 03e8 */ 0x00000000L,
+/* 03ec */ 0x78340700L, /* move MSG_REJECT to scratcha */
+/* 03f0 */ 0x00000000L,
+/* 03f4 */ 0x9e030000L, /* int error_unexpected_phase, when not msg_out */
+/* 03f8 */ 0x00000004L,
+/* 03fc */ 0x60000008L, /* clear atn */
+/* 0400 */ 0x00000000L,
+/* 0404 */ 0x0e000001L, /* move 1, scratcha, when msg_out */
+/* 0408 */ 0x00000034L,
+/* 040c */ 0x60000040L, /* clear ack */
+/* 0410 */ 0x00000000L,
+/* 0414 */ 0x868b0000L, /* jump reject, when msg_out */
+/* 0418 */ 0x00ffffc0L,
+/* 041c */ 0x80880000L, /* jump to_decisions */
+/* 0420 */ 0x0000020cL,
+/* 0424 */ 0x60000040L, /* clear ack */
+/* 0428 */ 0x00000000L,
+/* 042c */ 0x9f030000L, /* int error_unexpected_phase, when not msg_in */
+/* 0430 */ 0x00000004L,
+/* 0434 */ 0x0f000001L, /* move 1, scratcha1, when msg_in */
+/* 0438 */ 0x00000035L,
+/* 043c */ 0x98080000L, /* int SIR_MSG_IGNORE_WIDE_RESIDUE */
+/* 0440 */ 0x00000010L,
+/* 0444 */ 0x60000040L, /* clear ack */
+/* 0448 */ 0x00000000L,
+/* 044c */ 0x80880000L, /* jump to_decisions */
+/* 0450 */ 0x000001dcL,
+/* 0454 */ 0x58000008L, /* set atn */
+/* 0458 */ 0x00000000L,
+/* 045c */ 0x60000040L, /* clear ack */
+/* 0460 */ 0x00000000L,
+/* 0464 */ 0x9e030000L, /* int error_unexpected_phase, when not msg_out */
+/* 0468 */ 0x00000004L,
+/* 046c */ 0x1e000000L, /* move from msg_out_buf, when msg_out */
+/* 0470 */ 0x00000001L,
+/* 0474 */ 0x868b0000L, /* jump response_repeat, when msg_out */
+/* 0478 */ 0x00fffff0L,
+/* 047c */ 0x878b0000L, /* jump response_msg_in, when msg_in */
+/* 0480 */ 0x00000010L,
+/* 0484 */ 0x98080000L, /* int SIR_EV_RESPONSE_OK */
+/* 0488 */ 0x0000000cL,
+/* 048c */ 0x80880000L, /* jump to_decisions */
+/* 0490 */ 0x0000019cL,
+/* 0494 */ 0x0f000001L, /* move 1, scratcha, when msg_in */
+/* 0498 */ 0x00000034L,
+/* 049c */ 0x808c0007L, /* jump rejected, if MSG_REJECT */
+/* 04a0 */ 0x00fffdf8L,
+/* 04a4 */ 0x98080000L, /* int SIR_EV_RESPONSE_OK */
+/* 04a8 */ 0x0000000cL,
+/* 04ac */ 0x80880000L, /* jump msg_in_not_reject */
+/* 04b0 */ 0x00fffd60L,
+/* 04b4 */ 0x7c027e00L, /* move scntl2&0x7e to scntl2 */
+/* 04b8 */ 0x00000000L,
+/* 04bc */ 0x60000040L, /* clear ack */
+/* 04c0 */ 0x00000000L,
+/* 04c4 */ 0x48000000L, /* wait disconnect */
+/* 04c8 */ 0x00000000L,
+/* 04cc */ 0xc0000004L, /* move memory 4, state, scratcha */
+/* 04d0 */ 0x00000678L,
+/* 04d4 */ 0x00000034L,
+/* 04d8 */ 0x78340300L, /* move STATE_DISCONNECTED to scratcha0 */
+/* 04dc */ 0x00000000L,
+/* 04e0 */ 0xc0000004L, /* move memory 4, scratcha, state */
+/* 04e4 */ 0x00000034L,
+/* 04e8 */ 0x00000678L,
+/* 04ec */ 0x88880000L, /* call save_state */
+/* 04f0 */ 0x000001bcL,
+/* 04f4 */ 0x74020100L, /* move scntl2&0x01 to sfbr */
+/* 04f8 */ 0x00000000L,
+/* 04fc */ 0x98040000L, /* int SIR_NOTIFY_WSR, if not 0 */
+/* 0500 */ 0x00000073L,
+/* 0504 */ 0x80880000L, /* jump issue_check */
+/* 0508 */ 0x000001ccL,
+/* 050c */ 0x98080000L, /* int SIR_NOTIFY_RESELECTED_ON_SELECT */
+/* 0510 */ 0x00000075L,
+/* 0514 */ 0x80880000L, /* jump reselected */
+/* 0518 */ 0x00000008L,
+/* 051c */ 0x54000000L, /* wait reselect sigp_set */
+/* 0520 */ 0x000001acL,
+/* 0524 */ 0x60000200L, /* clear target */
+/* 0528 */ 0x00000000L,
+/* 052c */ 0x9f030000L, /* int SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT, when not msg_in */
+/* 0530 */ 0x00000006L,
+/* 0534 */ 0x0f000001L, /* move 1, scratchb, when msg_in */
+/* 0538 */ 0x0000005cL,
+/* 053c */ 0x98041f80L, /* int error_not_identify_after_reselect, if not MSG_IDENTIFY and mask 0x1f */
+/* 0540 */ 0x00000007L,
+/* 0544 */ 0xc0000004L, /* move memory 4, dsa_head, dsa */
+/* 0548 */ 0x00000008L,
+/* 054c */ 0x00000010L,
+/* 0550 */ 0x72100000L, /* move dsa0 to sfbr */
+/* 0554 */ 0x00000000L,
+/* 0558 */ 0x80840000L, /* jump find_dsa_1, if not 0 */
+/* 055c */ 0x00000030L,
+/* 0560 */ 0x72110000L, /* move dsa1 to sfbr */
+/* 0564 */ 0x00000000L,
+/* 0568 */ 0x80840000L, /* jump find_dsa_1, if not 0 */
+/* 056c */ 0x00000020L,
+/* 0570 */ 0x72120000L, /* move dsa2 to sfbr */
+/* 0574 */ 0x00000000L,
+/* 0578 */ 0x80840000L, /* jump find_dsa_1, if not 0 */
+/* 057c */ 0x00000010L,
+/* 0580 */ 0x72130000L, /* move dsa3 to sfbr */
+/* 0584 */ 0x00000000L,
+/* 0588 */ 0x980c0000L, /* int error_reselected, if 0 */
+/* 058c */ 0x00000003L,
+/* 0590 */ 0x88880000L, /* call load_state */
+/* 0594 */ 0x000000f8L,
+/* 0598 */ 0xc0000004L, /* move memory 4, state, scratcha */
+/* 059c */ 0x00000678L,
+/* 05a0 */ 0x00000034L,
+/* 05a4 */ 0x72340000L, /* move scratcha0 to sfbr */
+/* 05a8 */ 0x00000000L,
+/* 05ac */ 0x80840003L, /* jump find_dsa_next, if not STATE_DISCONNECTED */
+/* 05b0 */ 0x00000038L,
+/* 05b4 */ 0x740a0f00L, /* move ssid & 15 to sfbr */
+/* 05b8 */ 0x00000000L,
+/* 05bc */ 0xc0000001L, /* move memory 1, targ, find_dsa_smc1 */
+/* 05c0 */ 0x00000680L,
+/* 05c4 */ 0x000005c8L,
+/* 05c8 */ 0x808400ffL, /* jump find_dsa_next, if not 255 */
+/* 05cc */ 0x0000001cL,
+/* 05d0 */ 0xc0000001L, /* move memory 1, lun, find_dsa_smc2 */
+/* 05d4 */ 0x00000684L,
+/* 05d8 */ 0x000005e4L,
+/* 05dc */ 0x725c0000L, /* move scratchb0 to sfbr */
+/* 05e0 */ 0x00000000L,
+/* 05e4 */ 0x808cf8ffL, /* jump reload_sync, if 255 and mask ~7 */
+/* 05e8 */ 0x00000034L,
+/* 05ec */ 0xc0000004L, /* move memory 4, next, dsa */
+/* 05f0 */ 0x0000068cL,
+/* 05f4 */ 0x00000010L,
+/* 05f8 */ 0x80880000L, /* jump find_dsa_loop */
+/* 05fc */ 0x00ffff50L,
+/* 0600 */ 0x60000008L, /* clear atn */
+/* 0604 */ 0x00000000L,
+/* 0608 */ 0x878b0000L, /* jump msg_in_phase, when msg_in */
+/* 060c */ 0x00fffbf4L,
+/* 0610 */ 0x98080000L, /* int SIR_MSG_REJECT */
+/* 0614 */ 0x0000000aL,
+/* 0618 */ 0x80880000L, /* jump to_decisions */
+/* 061c */ 0x00000010L,
+/* 0620 */ 0x88880000L, /* call load_sync */
+/* 0624 */ 0x00000134L,
+/* 0628 */ 0x60000040L, /* clear ack */
+/* 062c */ 0x00000000L,
+/* 0630 */ 0x818b0000L, /* jump data_in_phase, when data_in */
+/* 0634 */ 0x00fffa20L,
+/* 0638 */ 0x828a0000L, /* jump cmd_phase, if cmd */
+/* 063c */ 0x00fffa00L,
+/* 0640 */ 0x808a0000L, /* jump data_out_phase, if data_out */
+/* 0644 */ 0x00fffaecL,
+/* 0648 */ 0x838a0000L, /* jump status_phase, if status */
+/* 064c */ 0x00fffba4L,
+/* 0650 */ 0x878a0000L, /* jump msg_in_phase, if msg_in */
+/* 0654 */ 0x00fffbacL,
+/* 0658 */ 0x98080000L, /* int error_unexpected_phase */
+/* 065c */ 0x00000004L,
+/* 0660 */ 0x838b0000L, /* jump status_phase, when status */
+/* 0664 */ 0x00fffb8cL,
+/* 0668 */ 0x878a0000L, /* jump msg_in_phase, if msg_in */
+/* 066c */ 0x00fffb94L,
+/* 0670 */ 0x98080000L, /* int error_unexpected_phase */
+/* 0674 */ 0x00000004L,
+/* 0678 */ 0x00000000L, /* state: defw 0 */
+/* 067c */ 0x00000000L, /* dmaaddr: defw 0 */
+/* 0680 */ 0x00000000L, /* targ: defw 0 */
+/* 0684 */ 0x00000000L, /* lun: defw 0 */
+/* 0688 */ 0x00000000L, /* sync: defw 0 */
+/* 068c */ 0x00000000L, /* next: defw 0 */
+ /* dsa_load_len = dsa_load_end - dsa_copy */
+ /* dsa_save_len = dsa_save_end - dsa_copy */
+/* 0690 */ 0xc0000004L, /* move memory 4, dsa, load_state_smc0 + 4 */
+/* 0694 */ 0x00000010L,
+/* 0698 */ 0x000006a0L,
+/* 069c */ 0xc0000018L, /* move memory dsa_load_len, 0, dsa_copy */
+/* 06a0 */ 0x00000000L,
+/* 06a4 */ 0x00000678L,
+/* 06a8 */ 0x90080000L, /* return */
+/* 06ac */ 0x00000000L,
+/* 06b0 */ 0xc0000004L, /* move memory 4, dsa, save_state_smc0 + 8 */
+/* 06b4 */ 0x00000010L,
+/* 06b8 */ 0x000006c4L,
+/* 06bc */ 0xc0000008L, /* move memory dsa_save_len, dsa_copy, 0 */
+/* 06c0 */ 0x00000678L,
+/* 06c4 */ 0x00000000L,
+/* 06c8 */ 0x90080000L, /* return */
+/* 06cc */ 0x00000000L,
+/* 06d0 */ 0x721a0000L, /* move ctest2 to sfbr */
+/* 06d4 */ 0x00000000L,
+/* 06d8 */ 0xc0000004L, /* move memory 4, dsa_head, dsa */
+/* 06dc */ 0x00000008L,
+/* 06e0 */ 0x00000010L,
+/* 06e4 */ 0x72100000L, /* move dsa0 to sfbr */
+/* 06e8 */ 0x00000000L,
+/* 06ec */ 0x80840000L, /* jump issue_check_1, if not 0 */
+/* 06f0 */ 0x00000030L,
+/* 06f4 */ 0x72110000L, /* move dsa1 to sfbr */
+/* 06f8 */ 0x00000000L,
+/* 06fc */ 0x80840000L, /* jump issue_check_1, if not 0 */
+/* 0700 */ 0x00000020L,
+/* 0704 */ 0x72120000L, /* move dsa2 to sfbr */
+/* 0708 */ 0x00000000L,
+/* 070c */ 0x80840000L, /* jump issue_check_1, if not 0 */
+/* 0710 */ 0x00000010L,
+/* 0714 */ 0x72130000L, /* move dsa3 to sfbr */
+/* 0718 */ 0x00000000L,
+/* 071c */ 0x808c0000L, /* jump wait_for_reselection, if 0 */
+/* 0720 */ 0x00fffdf8L,
+/* 0724 */ 0x88880000L, /* call load_state */
+/* 0728 */ 0x00ffff64L,
+/* 072c */ 0xc0000004L, /* move memory 4, state, scratcha */
+/* 0730 */ 0x00000678L,
+/* 0734 */ 0x00000034L,
+/* 0738 */ 0x72340000L, /* move scratcha0 to sfbr */
+/* 073c */ 0x00000000L,
+/* 0740 */ 0x808c0002L, /* jump start, if STATE_ISSUE */
+/* 0744 */ 0x00fff8c0L,
+/* 0748 */ 0xc0000004L, /* move memory 4, next, dsa */
+/* 074c */ 0x0000068cL,
+/* 0750 */ 0x00000010L,
+/* 0754 */ 0x80880000L, /* jump issue_check_loop */
+/* 0758 */ 0x00ffff88L,
+/* 075c */ 0xc0000004L, /* move memory 4, sync, scratcha */
+/* 0760 */ 0x00000688L,
+/* 0764 */ 0x00000034L,
+/* 0768 */ 0x72340000L, /* move scratcha0 to sfbr */
+/* 076c */ 0x00000000L,
+/* 0770 */ 0x6a030000L, /* move sfbr to scntl3 */
+/* 0774 */ 0x00000000L,
+/* 0778 */ 0x72350000L, /* move scratcha1 to sfbr */
+/* 077c */ 0x00000000L,
+/* 0780 */ 0x6a050000L, /* move sfbr to sxfer */
+/* 0784 */ 0x00000000L,
+/* 0788 */ 0x90080000L, /* return */
+/* 078c */ 0x00000000L,
+};
+
+#define NA_SCRIPT_SIZE 484
+
+struct na_patch na_patches[] = {
+ { 0x0006, 5 }, /* 00000018 */
+ { 0x000b, 4 }, /* 0000002c */
+ { 0x0013, 4 }, /* 0000004c */
+ { 0x0017, 1 }, /* 0000005c */
+ { 0x0018, 2 }, /* 00000060 */
+ { 0x001a, 1 }, /* 00000068 */
+ { 0x001b, 2 }, /* 0000006c */
+ { 0x0021, 1 }, /* 00000084 */
+ { 0x002b, 2 }, /* 000000ac */
+ { 0x002c, 1 }, /* 000000b0 */
+ { 0x0030, 2 }, /* 000000c0 */
+ { 0x0031, 1 }, /* 000000c4 */
+ { 0x0037, 2 }, /* 000000dc */
+ { 0x0038, 1 }, /* 000000e0 */
+ { 0x003a, 2 }, /* 000000e8 */
+ { 0x003b, 1 }, /* 000000ec */
+ { 0x0043, 4 }, /* 0000010c */
+ { 0x0047, 2 }, /* 0000011c */
+ { 0x0048, 1 }, /* 00000120 */
+ { 0x004e, 1 }, /* 00000138 */
+ { 0x004f, 2 }, /* 0000013c */
+ { 0x0051, 1 }, /* 00000144 */
+ { 0x0052, 2 }, /* 00000148 */
+ { 0x0058, 1 }, /* 00000160 */
+ { 0x0059, 2 }, /* 00000164 */
+ { 0x005b, 1 }, /* 0000016c */
+ { 0x0065, 2 }, /* 00000194 */
+ { 0x0066, 1 }, /* 00000198 */
+ { 0x006a, 2 }, /* 000001a8 */
+ { 0x006b, 1 }, /* 000001ac */
+ { 0x0073, 4 }, /* 000001cc */
+ { 0x0077, 2 }, /* 000001dc */
+ { 0x0078, 1 }, /* 000001e0 */
+ { 0x007e, 4 }, /* 000001f8 */
+ { 0x0082, 2 }, /* 00000208 */
+ { 0x0098, 1 }, /* 00000260 */
+ { 0x0099, 2 }, /* 00000264 */
+ { 0x009f, 2 }, /* 0000027c */
+ { 0x00a0, 1 }, /* 00000280 */
+ { 0x00b6, 2 }, /* 000002d8 */
+ { 0x00c2, 2 }, /* 00000308 */
+ { 0x00ca, 2 }, /* 00000328 */
+ { 0x00d0, 2 }, /* 00000340 */
+ { 0x00d6, 2 }, /* 00000358 */
+ { 0x00e6, 2 }, /* 00000398 */
+ { 0x00ec, 2 }, /* 000003b0 */
+ { 0x0102, 2 }, /* 00000408 */
+ { 0x010e, 2 }, /* 00000438 */
+ { 0x011c, 4 }, /* 00000470 */
+ { 0x0126, 2 }, /* 00000498 */
+ { 0x0134, 1 }, /* 000004d0 */
+ { 0x0135, 2 }, /* 000004d4 */
+ { 0x0139, 2 }, /* 000004e4 */
+ { 0x013a, 1 }, /* 000004e8 */
+ { 0x014e, 2 }, /* 00000538 */
+ { 0x0152, 4 }, /* 00000548 */
+ { 0x0153, 2 }, /* 0000054c */
+ { 0x0167, 1 }, /* 0000059c */
+ { 0x0168, 2 }, /* 000005a0 */
+ { 0x0170, 1 }, /* 000005c0 */
+ { 0x0171, 1 }, /* 000005c4 */
+ { 0x0175, 1 }, /* 000005d4 */
+ { 0x0176, 1 }, /* 000005d8 */
+ { 0x017c, 1 }, /* 000005f0 */
+ { 0x017d, 2 }, /* 000005f4 */
+ { 0x01a5, 2 }, /* 00000694 */
+ { 0x01a6, 1 }, /* 00000698 */
+ { 0x01a9, 1 }, /* 000006a4 */
+ { 0x01ad, 2 }, /* 000006b4 */
+ { 0x01ae, 1 }, /* 000006b8 */
+ { 0x01b0, 1 }, /* 000006c0 */
+ { 0x01b7, 4 }, /* 000006dc */
+ { 0x01b8, 2 }, /* 000006e0 */
+ { 0x01cc, 1 }, /* 00000730 */
+ { 0x01cd, 2 }, /* 00000734 */
+ { 0x01d3, 1 }, /* 0000074c */
+ { 0x01d4, 2 }, /* 00000750 */
+ { 0x01d8, 1 }, /* 00000760 */
+ { 0x01d9, 2 }, /* 00000764 */
+};
+#define NA_PATCHES 79
+
+enum na_external {
+ X_scsi_id_buf,
+ X_msg_out_buf,
+ X_cmd_buf,
+ X_data_buf,
+ X_status_buf,
+ X_msgin_buf,
+ X_dsa_0,
+ X_dsa_1,
+ X_dsa_head,
+};
+
+enum {
+ E_issue_check_next = 1864,
+ E_issue_check_1 = 1828,
+ E_issue_check_loop = 1764,
+ E_save_state_smc0 = 1724,
+ E_load_state_smc0 = 1692,
+ E_dsa_load_end = 1680,
+ E_sync = 1672,
+ E_dsa_save_end = 1664,
+ E_dsa_copy = 1656,
+ E_id_out_mismatch_recover = 1536,
+ E_next = 1676,
+ E_reload_sync = 1568,
+ E_find_dsa_smc2 = 1508,
+ E_lun = 1668,
+ E_find_dsa_smc1 = 1480,
+ E_targ = 1664,
+ E_find_dsa_next = 1516,
+ E_load_state = 1680,
+ E_find_dsa_1 = 1424,
+ E_find_dsa_loop = 1360,
+ E_find_dsa = 1348,
+ E_sigp_set = 1744,
+ E_reselected = 1316,
+ E_wsr_check = 1268,
+ E_response_msg_in = 1172,
+ E_response_repeat = 1132,
+ E_response = 1108,
+ E_reject = 988,
+ E_wdtr = 964,
+ E_sdtr = 876,
+ E_ext_done = 988,
+ E_ext_1 = 756,
+ E_ext_2 = 900,
+ E_ext_3 = 788,
+ E_issue_check = 1752,
+ E_extended = 708,
+ E_ignore_wide = 1060,
+ E_msg_in_skip = 692,
+ E_disconnected = 1204,
+ E_msg_in_not_reject = 532,
+ E_rejected = 668,
+ E_msg_in_phase = 516,
+ E_status_phase = 500,
+ E_data_out_mismatch = 464,
+ E_data_out_block_mismatch = 368,
+ E_data_out_normal = 440,
+ E_data_out_block_loop = 332,
+ E_data_out_phase = 308,
+ E_post_data_to_decisions = 1632,
+ E_data_in_mismatch = 272,
+ E_data_block_mismatch_recover = 216,
+ E_save_state = 1712,
+ E_data_in_block_mismatch = 136,
+ E_data_in_normal = 248,
+ E_data_in_block_loop = 112,
+ E_dmaaddr = 1660,
+ E_state = 1656,
+ E_data_in_phase = 88,
+ E_cmd_out_mismatch = 80,
+ E_cmd_phase = 64,
+ E_to_decisions = 1584,
+ E_id_out_mismatch = 48,
+ E_start1 = 40,
+ E_reselected_on_select = 1292,
+ E_load_sync = 1884,
+ E_start = 8,
+ E_wait_for_reselection = 1308,
+ E_idle = 0,
+};
+#define A_dsa_save_len 8
+#define A_dsa_load_len 24
+#define A_BSIZE 512
+#define A_MSG_REJECT 7
+#define A_X_MSG_WDTR 3
+#define A_X_MSG_SDTR 1
+#define A_X_MSG 1
+#define A_MSG_IGNORE_WIDE_RESIDUE 35
+#define A_MSG_RESTORE_POINTERS 3
+#define A_MSG_SAVE_DATA_POINTER 2
+#define A_MSG_DISCONNECT 4
+#define A_MSG_IDENTIFY 128
+#define A_RESULT_OK 0
+#define A_STATE_DONE 4
+#define A_STATE_DISCONNECTED 3
+#define A_STATE_ISSUE 2
+#define A_STATE_ALLOCATED 1
+#define A_STATE_FREE 0
+#define A_SIR_NOTIFY_RESELECTED_ON_SELECT 117
+#define A_SIR_NOTIFY_LOAD_SYNC 116
+#define A_SIR_NOTIFY_WSR 115
+#define A_SIR_NOTIFY_BLOCK_DATA_IN 114
+#define A_SIR_NOTIFY_DATA_OUT 113
+#define A_SIR_NOTIFY_DATA_IN 112
+#define A_SIR_NOTIFY_COMMAND 111
+#define A_SIR_NOTIFY_DUMP_NEXT_CODE 110
+#define A_SIR_NOTIFY_ISSUE_CHECK 109
+#define A_SIR_NOTIFY_WAIT_RESELECT 108
+#define A_SIR_NOTIFY_ISSUE 107
+#define A_SIR_NOTIFY_SIGP 106
+#define A_SIR_NOTIFY_DUMP2 105
+#define A_SIR_NOTIFY_DUMP 104
+#define A_SIR_NOTIFY_STATUS 103
+#define A_SIR_NOTIFY_MSG_IN 102
+#define A_SIR_NOTIFY_RESELECT 101
+#define A_SIR_NOTIFY_DISC 100
+#define A_SIR_MSG_IGNORE_WIDE_RESIDUE 16
+#define A_SIR_MSG_WDTR 15
+#define A_SIR_EV_PHASE_SWITCH_AFTER_ID 14
+#define A_error_sigp_set 13
+#define A_SIR_EV_RESPONSE_OK 12
+#define A_SIR_MSG_SDTR 11
+#define A_SIR_MSG_REJECT 10
+#define A_error_too_little_data 9
+#define A_error_too_much_data 8
+#define A_error_not_identify_after_reselect 7
+#define A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT 6
+#define A_error_weird_message 5
+#define A_error_unexpected_phase 4
+#define A_error_reselected 3
+#define A_error_disconnected 2
+#define A_error_not_cmd_complete 1
+#define A_SIR_MSG_IO_COMPLETE 0
--- /dev/null
+++ b/os/boot.original/pc/sdaoe.c
@@ -1,0 +1,733 @@
+/*
+ * aoe sd bootstrap driver, copyright © 2007 coraid
+ */
+
+#include "u.h"
+#include "mem.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "sd.h"
+#include "aoe.h"
+
+
+enum {
+ Nctlr = 4,
+};
+
+enum {
+ /* sync with ahci.h */
+ Dllba = 1<<0,
+ Dsmart = 1<<1,
+ Dpower = 1<<2,
+ Dnop = 1<<3,
+ Datapi = 1<<4,
+ Datapi16= 1<<5,
+};
+
+enum {
+ Tfree = -1,
+ Tmgmt,
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr{
+ Ctlr *next;
+ SDunit *unit;
+
+ int ctlrno;
+ int major;
+ int minor;
+ uchar ea[Eaddrlen];
+ ushort lasttag;
+
+ ulong vers;
+ uchar mediachange;
+ uchar flag;
+ uchar smart;
+ uchar smartrs;
+ uchar feat;
+
+ uvlong sectors;
+ char serial[20+1];
+ char firmware[8+1];
+ char model[40+1];
+ char ident[0x100];
+};
+
+static Ctlr *head;
+static Ctlr *tail;
+
+static int aoeether[10];
+
+SDifc sdaoeifc;
+
+static void
+hnputs(uchar *p, ushort i)
+{
+ p[0] = i >> 8;
+ p[1] = i;
+}
+
+static void
+hnputl(uchar *p, ulong i)
+{
+ p[0] = i >> 24;
+ p[1] = i >> 16;
+ p[2] = i >> 8;
+ p[3] = i;
+}
+
+static ushort
+nhgets(uchar *p)
+{
+ return *p<<8 | p[1];
+}
+
+static ulong
+nhgetl(uchar *p)
+{
+ return p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
+}
+
+static int
+newtag(Ctlr *d)
+{
+ int t;
+
+ for(;;){
+ t = ++d->lasttag << 16;
+ t |= m->ticks & 0xffff;
+ switch(t) {
+ case Tfree:
+ case Tmgmt:
+ break;
+ default:
+ return t;
+ }
+ }
+}
+
+static int
+hset(Ctlr *d, Aoehdr *h, int cmd)
+{
+ int tag;
+
+ memmove(h->dst, d->ea, Eaddrlen);
+ hnputs(h->type, Aoetype);
+ h->verflag = Aoever << 4;
+ hnputs(h->major, d->major);
+ h->minor = d->minor;
+ h->cmd = cmd;
+ hnputl(h->tag, tag = newtag(d));
+ return tag;
+}
+
+static void
+idmove(char *p, ushort *a, int n)
+{
+ int i;
+ char *op, *e;
+
+ op = p;
+ for(i = 0; i < n / 2; i++){
+ *p++ = a[i] >> 8;
+ *p++ = a[i];
+ }
+ *p = 0;
+ while(p > op && *--p == ' ')
+ *p = 0;
+ e = p;
+ p = op;
+ while(*p == ' ')
+ p++;
+ memmove(op, p, n - (e - p));
+}
+
+static ushort
+gbit16(void *a)
+{
+ uchar *i;
+
+ i = a;
+ return i[1]<<8 | i[0];
+}
+
+static ulong
+gbit32(void *a)
+{
+ uchar *i;
+ ulong j;
+
+ i = a;
+ j = i[3] << 24;
+ j |= i[2] << 16;
+ j |= i[1] << 8;
+ j |= i[0];
+ return j;
+}
+
+static uvlong
+gbit64(void *a)
+{
+ uchar *i;
+
+ i = a;
+ return (uvlong)gbit32(i+4) << 32 | gbit32(a);
+}
+
+static int
+ataidentify(Ctlr *c, ushort *id)
+{
+ vlong s;
+ int i;
+
+ i = gbit16(id+83) | gbit16(id+86);
+ if(i & (1 << 10)){
+ c->feat |= Dllba;
+ s = gbit64(id+100);
+ }else
+ s = gbit32(id+60);
+
+ idmove(c->serial, id+10, 20);
+ idmove(c->firmware, id+23, 8);
+ idmove(c->model, id+27, 40);
+
+print("aoe discovers %d.%d: %s %s\n", c->major, c->minor, c->model, c->serial);
+
+ c->sectors = s;
+ c->mediachange = 1;
+ return 0;
+}
+
+static void
+identifydump(Aoeata *a)
+{
+ print("%E %E type=%.4ux verflag=%x error=%x %d.%d cmd=%d tag=%.8lux\n",
+ a->dst, a->src, nhgets(a->type), a->verflag, a->error,
+ nhgets(a->major), a->minor, a->cmd, nhgetl(a->tag));
+ print(" aflag=%x errfeat=%ux scnt=%d cmdstat=%ux, lba=%d? res=%.4ux\n",
+ a->aflag, a->errfeat, a->scnt, a->cmdstat, 0, nhgets(a->res));
+}
+
+static int
+idpkt(Ctlr *c, Aoeata *a)
+{
+ memset(a, 0, sizeof *a);
+ a->cmdstat = Cid;
+ a->scnt = 1;
+ a->lba[3] = 0xa0;
+ return hset(c, a, ACata);
+}
+
+static int
+chktag(int *out, int nout, int tag)
+{
+ int j;
+
+ for(j = 0; j <= nout; j++)
+ if(out[j] == tag)
+ return 0;
+print("wrong tag\n");
+ for(j = 0; j <= nout; j++)
+ print("%.8ux != %.8ux\n", out[j], tag);
+ return -1;
+}
+
+/*
+ * ignore the tag for identify. better than ignoring
+ * a response to the wrong identify request
+ */
+static int
+identify(Ctlr *c)
+{
+ int tag[5], i, n;
+ Aoeata *a;
+ Etherpkt p;
+
+ memset(&p, 0, sizeof p);
+ a = (Aoeata*)&p;
+ i = 0;
+ do {
+ if(i == 5){
+ print("aoe: identify timeout\n");
+ return -1;
+ }
+ tag[i] = idpkt(c, a);
+ ethertxpkt(c->ctlrno, &p, sizeof *a, 0);
+ memset(&p, 0, sizeof p);
+next:
+ n = etherrxpkt(c->ctlrno, &p, 125);
+ if(n == 0){
+ i++;
+ continue;
+ }
+ if(nhgets(a->type) != Aoetype)
+ goto next;
+ if(nhgets(a->major) != c->major || a->minor != c->minor){
+ print("wrong device %d.%d want %d.%d; %d\n",
+ nhgets(a->major), a->minor,
+ c->major, c->minor, n);
+ goto next;
+ }
+ if(chktag(tag, i, nhgetl(a->tag)) == -1)
+ goto next;
+ if(a->cmdstat & 0xa9){
+ print("aoe: ata error on identify: %2ux\n", a->cmdstat);
+ return -1;
+ }
+ } while (a->scnt != 1);
+
+ c->feat = 0;
+ ataidentify(c, (ushort*)(a+1));
+ return 0;
+}
+
+static Ctlr*
+ctlrlookup(int major, int minor)
+{
+ Ctlr *c;
+
+ for(c = head; c; c = c->next)
+ if(c->major == major && c->minor == minor)
+ break;
+ return c;
+}
+
+static Ctlr*
+newctlr(Etherpkt *p)
+{
+ int major, minor;
+ Aoeqc *q;
+ Ctlr *c;
+
+ q = (Aoeqc*)p;
+ if(nhgets(q->type) != Aoetype)
+ return 0;
+ major = nhgets(q->major);
+ minor = q->minor;
+
+ if(major == 0xffff || minor == 0xff)
+ return 0;
+
+ if(ctlrlookup(major, minor)){
+ print("duplicate shelf.slot\n");
+ return 0;
+ }
+
+ if((c = malloc(sizeof *c)) == 0)
+ return 0;
+ c->major = major;
+ c->minor = minor;
+ memmove(c->ea, q->src, Eaddrlen);
+
+ if(head != 0)
+ tail->next = c;
+ else
+ head = c;
+ tail = c;
+ return c;
+}
+
+static void
+discover(int major, int minor)
+{
+ int i;
+ Aoehdr *h;
+ Etherpkt p;
+
+ for(i = 0; i < nelem(aoeether); i++){
+ if(aoeether[i] == 0)
+ continue;
+ memset(&p, 0, ETHERMINTU);
+ h = (Aoehdr*)&p;
+ memset(h->dst, 0xff, sizeof h->dst);
+ hnputs(h->type, Aoetype);
+ h->verflag = Aoever << 4;
+ hnputs(h->major, major);
+ h->minor = minor;
+ h->cmd = ACconfig;
+ ethertxpkt(i, &p, ETHERMINTU, 0);
+ }
+}
+
+static int
+rxany(Etherpkt *p, int t)
+{
+ int i, n;
+
+ for(i = 0; i < nelem(aoeether); i++){
+ if(aoeether[i] == 0)
+ continue;
+ while ((n = etherrxpkt(i, p, t)) != 0)
+ if(nhgets(p->type) == Aoetype)
+ return n;
+ }
+ return 0;
+}
+
+static int
+aoeprobe(int major, int minor, SDev *s)
+{
+ Ctlr *ctlr;
+ Etherpkt p;
+ int n, i;
+
+ for(i = 0;; i += 200){
+ if(i > 8000)
+ return -1;
+ discover(major, minor);
+again:
+ n = rxany(&p, 100);
+ if(n > 0 && (ctlr = newctlr(&p)))
+ break;
+ if(n > 0)
+ goto again;
+ }
+
+ s->ctlr = ctlr;
+ s->ifc = &sdaoeifc;
+ s->nunit = 1;
+ return 0;
+}
+
+static char *probef[32];
+static int nprobe;
+
+int
+pnpprobeid(char *s)
+{
+ int id;
+
+ if(strlen(s) < 2)
+ return 0;
+ id = 'e';
+ if(s[1] == '!')
+ id = s[0];
+ return id;
+}
+
+int
+tokenize(char *s, char **args, int maxargs)
+{
+ int nargs;
+
+ for(nargs = 0; nargs < maxargs; nargs++){
+ while(*s != '\0' && strchr("\t\n ", *s) != nil)
+ s++;
+ if(*s == '\0')
+ break;
+ args[nargs] = s;
+ while(*s != '\0' && strchr("\t\n ", *s) == nil)
+ s++;
+ if(*s != '\0')
+ *s++ = 0;
+ }
+ return nargs;
+}
+
+int
+aoepnp0(void)
+{
+ int i;
+ char *p, c;
+
+ if((p = getconf("aoeif")) == nil)
+ return 0;
+print("aoeif = %s\n", p);
+ nprobe = tokenize(p, probef, nelem(probef));
+ for(i = 0; i < nprobe; i++){
+ if(strncmp(probef[i], "ether", 5) != 0)
+ continue;
+ c = probef[i][5];
+ if(c > '9' || c < '0')
+ continue;
+ aoeether[c - '0'] = 1;
+ }
+
+ if((p = getconf("aoedev")) == nil)
+ return 0;
+ return nprobe = tokenize(p, probef, nelem(probef));
+}
+
+int
+probeshelf(char *s, int *shelf, int *slot)
+{
+ int a, b;
+ char *r;
+
+ for(r = s + strlen(s) - 1; r > s; r--)
+ if((*r < '0' || *r > '9') && *r != '.'){
+ r++;
+ break;
+ }
+ a = strtoul(r, &r, 10);
+ if(*r++ != '.')
+ return -1;
+ b = strtoul(r, 0, 10);
+
+ *shelf = a;
+ *slot = b;
+print(" shelf=%d.%d\n", a, b);
+ return 0;
+}
+
+Ctlr*
+pnpprobe(SDev *sd)
+{
+ int shelf, slot;
+ char *p;
+ static int i;
+
+ if(i >= nprobe)
+ return 0;
+ p = probef[i++];
+ if(strlen(p) < 2)
+ return 0;
+ if(p[1] == '!'){
+ sd->idno = p[0];
+ p += 2;
+ }
+ if(probeshelf(p, &shelf, &slot) == -1 ||
+ aoeprobe(shelf, slot, sd) == -1 ||
+ identify(sd->ctlr) == -1)
+ return 0;
+ return sd->ctlr;
+}
+
+/*
+ * we may need to pretend we found something
+ */
+
+SDev*
+aoepnp(void)
+{
+ int n, i, id;
+ char *p;
+ SDev *h, *t, *s;
+
+ p = getconf("aoeif");
+ if (p)
+ print("aoepnp: aoeif=%s\n", p);
+
+ if((n = aoepnp0()) == 0)
+ n = 2;
+ t = h = 0;
+ for(i = 0; i < n; i++){
+ id = 'e';
+ s = malloc(sizeof *s);
+ if(s == 0)
+ break;
+ s->ctlr = 0;
+ s->idno = id;
+ s->ifc = &sdaoeifc;
+ s->nunit = 1;
+ pnpprobe(s);
+
+ if(h)
+ t->next = s;
+ else
+ h = s;
+ t = s;
+ }
+ return h;
+}
+
+static int
+aoeverify(SDunit *u)
+{
+ Ctlr *c;
+ SDev *s;
+
+ s = u->dev;
+ c = s->ctlr;
+ if(c == 0){
+ aoepnp0();
+ if((s->ctlr = c = pnpprobe(s)) == nil)
+ return 0;
+ }
+ c->mediachange = 1;
+ return 1;
+}
+
+static int
+aoeonline(SDunit *u)
+{
+ int r;
+ Ctlr *c;
+
+ c = u->dev->ctlr;
+ if(c->mediachange){
+ r = 2;
+ c->mediachange = 0;
+ u->sectors = c->sectors;
+ u->secsize = 512;
+ } else
+ r = 1;
+ return r;
+}
+
+static int
+rio(Ctlr *c, Aoeata *a, int n, int scnt)
+{
+ int i, tag, cmd;
+
+ for(i = 0; i < 5; i++){
+ tag = hset(c, a, ACata);
+ cmd = a->cmdstat;
+ ethertxpkt(c->ctlrno, (Etherpkt*)a, n, 0);
+ memset(a, 0, sizeof *a);
+again:
+ n = etherrxpkt(c->ctlrno, (Etherpkt*)a, 125);
+ if(n == 0)
+ continue;
+ if(nhgets(a->type) != Aoetype || nhgetl(a->tag) != tag ||
+ nhgets(a->major) != c->major || a->minor != c->minor)
+ goto again;
+ if(a->cmdstat & 0xa9){
+ print("aoe: ata rio error: %2ux\n", a->cmdstat);
+ return 0;
+ }
+ switch(cmd){
+ case Crd:
+ case Crdext:
+ if(n - sizeof *a < scnt * 512){
+ print("aoe: runt expect %d got %d\n",
+ scnt*512 + sizeof *a, n);
+ return 0;
+ }
+ return n - sizeof *a;
+ case Cwr:
+ case Cwrext:
+ return scnt * 512;
+ default:
+print("unknown cmd %ux\n", cmd);
+ break;
+ }
+ }
+ print("aoe: rio timeout\n");
+ return 0;
+}
+
+static void
+putlba(Aoeata *a, vlong lba)
+{
+ uchar *c;
+
+ c = a->lba;
+ c[0] = lba;
+ c[1] = lba >> 8;
+ c[2] = lba >> 16;
+ c[3] = lba >> 24;
+ c[4] = lba >> 32;
+ c[5] = lba >> 40;
+}
+
+/*
+ * you'll need to loop if you want to read more than 2 sectors. for now
+ * i'm cheeting and not bothering with a loop.
+ */
+static uchar pktbuf[1024 + sizeof(Aoeata)];
+
+static int
+aoebuild(Ctlr *c, uchar *cmd, char *data, vlong lba, int scnt)
+{
+ int n;
+ Aoeata *a;
+
+ memset(pktbuf, 0, sizeof pktbuf);
+ a = (Aoeata*)pktbuf;
+ hset(c, a, ACata);
+ putlba(a, lba);
+
+ a->cmdstat = 0x20;
+ if(c->flag & Dllba){
+ a->aflag |= AAFext;
+ a->cmdstat |= 4;
+ }else{
+ a->lba[3] &= 0xf;
+ a->lba[3] |= 0xe0; /* LBA bit+obsolete 0xa0 */
+ }
+
+ n = scnt;
+ if(n > 2)
+ n = 2;
+ a->scnt = n;
+
+ switch(*cmd){
+ case 0x2a:
+ a->aflag |= AAFwrite;
+ a->cmdstat |= 10;
+ memmove(a+1, data, n*512);
+ n = sizeof *a + n*512;
+ break;
+ case 0x28:
+ n = sizeof *a;
+ break;
+ default:
+ print("aoe: bad cmd 0x%.2ux\n", cmd[0]);
+ return -1;
+ }
+ return n;
+}
+
+static int
+aoerio(SDreq *r)
+{
+ int size, nsec, n;
+ vlong lba;
+ char *data;
+ uchar *cmd;
+ Aoeata *a;
+ Ctlr *c;
+ SDunit *unit;
+
+ unit = r->unit;
+ c = unit->dev->ctlr;
+ if(r->data == nil)
+ return SDok;
+ cmd = r->cmd;
+
+ lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5]; /* sic. */
+ nsec = cmd[7]<<8 | cmd[8];
+ a = (Aoeata*)pktbuf;
+ data = r->data;
+ r->rlen = 0;
+
+ for(; nsec > 0; nsec -= n){
+// print("aoebuild(%2x, %p, %lld, %d)\n", *cmd, data, lba, nsec);
+ size = aoebuild(c, cmd, data, lba, nsec);
+ if(size < 0){
+ r->status = SDcheck;
+ return SDcheck;
+ }
+ n = a->scnt;
+ r->rlen += rio(c, a, size, n);
+ if(*cmd == 0x28)
+ memmove(r->data, a + 1, n * 512);
+ data += n * 512;
+ lba += n;
+ }
+
+ r->status = SDok;
+ return SDok;
+}
+
+SDifc sdaoeifc = {
+ "aoe",
+
+ aoepnp,
+ nil, /* legacy */
+ nil, /* id */
+ nil, /* enable */
+ nil, /* disable */
+
+ aoeverify,
+ aoeonline,
+ aoerio,
+ nil,
+ nil,
+
+ scsibio,
+};
--- /dev/null
+++ b/os/boot.original/pc/sdata.c
@@ -1,0 +1,1652 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "error.h"
+
+#include "sd.h"
+
+extern SDifc sdataifc;
+
+enum {
+ DbgCONFIG = 0x0001, /* detected drive config info */
+ DbgIDENTIFY = 0x0002, /* detected drive identify info */
+ DbgSTATE = 0x0004, /* dump state on panic */
+ DbgPROBE = 0x0008, /* trace device probing */
+ DbgDEBUG = 0x0080, /* the current problem... */
+ DbgINL = 0x0100, /* That Inil20+ message we hate */
+ Dbg48BIT = 0x0200, /* 48-bit LBA */
+ DbgBsy = 0x0400, /* interrupt but Bsy (shared IRQ) */
+};
+#define DEBUG (DbgDEBUG|DbgCONFIG)
+
+enum { /* I/O ports */
+ Data = 0,
+ Error = 1, /* (read) */
+ Features = 1, /* (write) */
+ Count = 2, /* sector count<7-0>, sector count<15-8> */
+ Ir = 2, /* interrupt reason (PACKET) */
+ Sector = 3, /* sector number */
+ Lbalo = 3, /* LBA<7-0>, LBA<31-24> */
+ Cyllo = 4, /* cylinder low */
+ Bytelo = 4, /* byte count low (PACKET) */
+ Lbamid = 4, /* LBA<15-8>, LBA<39-32> */
+ Cylhi = 5, /* cylinder high */
+ Bytehi = 5, /* byte count hi (PACKET) */
+ Lbahi = 5, /* LBA<23-16>, LBA<47-40> */
+ Dh = 6, /* Device/Head, LBA<32-14> */
+ Status = 7, /* (read) */
+ Command = 7, /* (write) */
+
+ As = 2, /* Alternate Status (read) */
+ Dc = 2, /* Device Control (write) */
+};
+
+enum { /* Error */
+ Med = 0x01, /* Media error */
+ Ili = 0x01, /* command set specific (PACKET) */
+ Nm = 0x02, /* No Media */
+ Eom = 0x02, /* command set specific (PACKET) */
+ Abrt = 0x04, /* Aborted command */
+ Mcr = 0x08, /* Media Change Request */
+ Idnf = 0x10, /* no user-accessible address */
+ Mc = 0x20, /* Media Change */
+ Unc = 0x40, /* Uncorrectable data error */
+ Wp = 0x40, /* Write Protect */
+ Icrc = 0x80, /* Interface CRC error */
+};
+
+enum { /* Features */
+ Dma = 0x01, /* data transfer via DMA (PACKET) */
+ Ovl = 0x02, /* command overlapped (PACKET) */
+};
+
+enum { /* Interrupt Reason */
+ Cd = 0x01, /* Command/Data */
+ Io = 0x02, /* I/O direction */
+ Rel = 0x04, /* Bus Release */
+};
+
+enum { /* Device/Head */
+ Dev0 = 0xA0, /* Master */
+ Dev1 = 0xB0, /* Slave */
+ Lba = 0x40, /* LBA mode */
+};
+
+enum { /* Status, Alternate Status */
+ Err = 0x01, /* Error */
+ Chk = 0x01, /* Check error (PACKET) */
+ Drq = 0x08, /* Data Request */
+ Dsc = 0x10, /* Device Seek Complete */
+ Serv = 0x10, /* Service */
+ Df = 0x20, /* Device Fault */
+ Dmrd = 0x20, /* DMA ready (PACKET) */
+ Drdy = 0x40, /* Device Ready */
+ Bsy = 0x80, /* Busy */
+};
+
+enum { /* Command */
+ Cnop = 0x00, /* NOP */
+ Cdr = 0x08, /* Device Reset */
+ Crs = 0x20, /* Read Sectors */
+ Crs48 = 0x24, /* Read Sectors Ext */
+ Crd48 = 0x25, /* Read w/ DMA Ext */
+ Crdq48 = 0x26, /* Read w/ DMA Queued Ext */
+ Crsm48 = 0x29, /* Read Multiple Ext */
+ Cws = 0x30, /* Write Sectors */
+ Cws48 = 0x34, /* Write Sectors Ext */
+ Cwd48 = 0x35, /* Write w/ DMA Ext */
+ Cwdq48 = 0x36, /* Write w/ DMA Queued Ext */
+ Cwsm48 = 0x39, /* Write Multiple Ext */
+ Cedd = 0x90, /* Execute Device Diagnostics */
+ Cpkt = 0xA0, /* Packet */
+ Cidpkt = 0xA1, /* Identify Packet Device */
+ Crsm = 0xC4, /* Read Multiple */
+ Cwsm = 0xC5, /* Write Multiple */
+ Csm = 0xC6, /* Set Multiple */
+ Crdq = 0xC7, /* Read DMA queued */
+ Crd = 0xC8, /* Read DMA */
+ Cwd = 0xCA, /* Write DMA */
+ Cwdq = 0xCC, /* Write DMA queued */
+ Cstandby = 0xE2, /* Standby */
+ Cid = 0xEC, /* Identify Device */
+ Csf = 0xEF, /* Set Features */
+};
+
+enum { /* Device Control */
+ Nien = 0x02, /* (not) Interrupt Enable */
+ Srst = 0x04, /* Software Reset */
+};
+
+enum { /* PCI Configuration Registers */
+ Bmiba = 0x20, /* Bus Master Interface Base Address */
+ Idetim = 0x40, /* IE Timing */
+ Sidetim = 0x44, /* Slave IE Timing */
+ Udmactl = 0x48, /* Ultra DMA/33 Control */
+ Udmatim = 0x4A, /* Ultra DMA/33 Timing */
+};
+
+enum { /* Bus Master IDE I/O Ports */
+ Bmicx = 0, /* Command */
+ Bmisx = 2, /* Status */
+ Bmidtpx = 4, /* Descriptor Table Pointer */
+};
+
+enum { /* Bmicx */
+ Ssbm = 0x01, /* Start/Stop Bus Master */
+ Rwcon = 0x08, /* Read/Write Control */
+};
+
+enum { /* Bmisx */
+ Bmidea = 0x01, /* Bus Master IDE Active */
+ Idedmae = 0x02, /* IDE DMA Error (R/WC) */
+ Ideints = 0x04, /* IDE Interrupt Status (R/WC) */
+ Dma0cap = 0x20, /* Drive 0 DMA Capable */
+ Dma1cap = 0x40, /* Drive 0 DMA Capable */
+};
+enum { /* Physical Region Descriptor */
+ PrdEOT = 0x80000000, /* Bus Master IDE Active */
+};
+
+enum { /* offsets into the identify info. */
+ Iconfig = 0, /* general configuration */
+ Ilcyl = 1, /* logical cylinders */
+ Ilhead = 3, /* logical heads */
+ Ilsec = 6, /* logical sectors per logical track */
+ Iserial = 10, /* serial number */
+ Ifirmware = 23, /* firmware revision */
+ Imodel = 27, /* model number */
+ Imaxrwm = 47, /* max. read/write multiple sectors */
+ Icapabilities = 49, /* capabilities */
+ Istandby = 50, /* device specific standby timer */
+ Ipiomode = 51, /* PIO data transfer mode number */
+ Ivalid = 53,
+ Iccyl = 54, /* cylinders if (valid&0x01) */
+ Ichead = 55, /* heads if (valid&0x01) */
+ Icsec = 56, /* sectors if (valid&0x01) */
+ Iccap = 57, /* capacity if (valid&0x01) */
+ Irwm = 59, /* read/write multiple */
+ Ilba = 60, /* LBA size */
+ Imwdma = 63, /* multiword DMA mode */
+ Iapiomode = 64, /* advanced PIO modes supported */
+ Iminmwdma = 65, /* min. multiword DMA cycle time */
+ Irecmwdma = 66, /* rec. multiword DMA cycle time */
+ Iminpio = 67, /* min. PIO cycle w/o flow control */
+ Iminiordy = 68, /* min. PIO cycle with IORDY */
+ Ipcktbr = 71, /* time from PACKET to bus release */
+ Iserbsy = 72, /* time from SERVICE to !Bsy */
+ Iqdepth = 75, /* max. queue depth */
+ Imajor = 80, /* major version number */
+ Iminor = 81, /* minor version number */
+ Icsfs = 82, /* command set/feature supported */
+ Icsfe = 85, /* command set/feature enabled */
+ Iudma = 88, /* ultra DMA mode */
+ Ierase = 89, /* time for security erase */
+ Ieerase = 90, /* time for enhanced security erase */
+ Ipower = 91, /* current advanced power management */
+ Ilba48 = 100, /* 48-bit LBA size (64 bits in 100-103) */
+ Irmsn = 127, /* removable status notification */
+ Isecstat = 128, /* security status */
+};
+
+typedef struct Ctlr Ctlr;
+typedef struct Drive Drive;
+
+typedef struct Prd {
+ ulong pa; /* Physical Base Address */
+ int count;
+} Prd;
+
+enum {
+ Nprd = SDmaxio/(64*1024)+2,
+};
+
+typedef struct Ctlr {
+ int cmdport;
+ int ctlport;
+ int irq;
+ int tbdf;
+
+ Pcidev* pcidev;
+ void (*ienable)(Ctlr*);
+ SDev* sdev;
+
+ Drive* drive[2];
+
+ Prd* prdt; /* physical region descriptor table */
+
+// QLock; /* current command */
+ Drive* curdrive;
+ int command; /* last command issued (debugging) */
+// Rendez;
+ int done;
+
+ Lock; /* register access */
+} Ctlr;
+
+typedef struct Drive {
+ Ctlr* ctlr;
+
+ int dev;
+ ushort info[256];
+ int c; /* cylinder */
+ int h; /* head */
+ int s; /* sector */
+ vlong sectors; /* total */
+ int secsize; /* sector size */
+
+// int dma; /* DMA R/W possible */
+// int dmactl;
+// int rwm; /* read/write multiple possible */
+// int rwmctl;
+
+ int pkt; /* PACKET device, length of pktcmd */
+ uchar pktcmd[16];
+// int pktdma; /* this PACKET command using dma */
+
+ uchar sense[18];
+ uchar inquiry[48];
+
+// QLock; /* drive access */
+ int command; /* current command */
+ int write;
+ uchar* data;
+ int dlen;
+ uchar* limit;
+ int count; /* sectors */
+ int block; /* R/W bytes per block */
+ int status;
+ int error;
+ int flags; /* internal flags */
+} Drive;
+
+enum { /* internal flags */
+ Lba48 = 0x1, /* LBA48 mode */
+ Lba48always = 0x2, /* ... */
+};
+
+static void
+pc87415ienable(Ctlr* ctlr)
+{
+ Pcidev *p;
+ int x;
+
+ p = ctlr->pcidev;
+ if(p == nil)
+ return;
+
+ x = pcicfgr32(p, 0x40);
+ if(ctlr->cmdport == p->mem[0].bar)
+ x &= ~0x00000100;
+ else
+ x &= ~0x00000200;
+ pcicfgw32(p, 0x40, x);
+}
+
+static int
+atadebug(int cmdport, int ctlport, char* fmt, ...)
+{
+ int i, n;
+ va_list arg;
+ char buf[PRINTSIZE];
+
+ if(!(DEBUG & DbgPROBE)){
+ USED(cmdport, ctlport, fmt);
+ return 0;
+ }
+
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+
+ if(cmdport){
+ if(buf[n-1] == '\n')
+ n--;
+ n += snprint(buf+n, PRINTSIZE-n, " ataregs 0x%uX:",
+ cmdport);
+ for(i = Features; i < Command; i++)
+ n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",
+ inb(cmdport+i));
+ if(ctlport)
+ n += snprint(buf+n, PRINTSIZE-n, " 0x%2.2uX",
+ inb(ctlport+As));
+ n += snprint(buf+n, PRINTSIZE-n, "\n");
+ }
+ putstrn(buf, n);
+
+ return n;
+}
+
+static int
+ataready(int cmdport, int ctlport, int dev, int reset, int ready, int micro)
+{
+ int as;
+
+ atadebug(cmdport, ctlport, "ataready: dev %uX reset %uX ready %uX",
+ dev, reset, ready);
+
+ for(;;){
+ /*
+ * Wait for the controller to become not busy and
+ * possibly for a status bit to become true (usually
+ * Drdy). Must change to the appropriate device
+ * register set if necessary before testing for ready.
+ * Always run through the loop at least once so it
+ * can be used as a test for !Bsy.
+ */
+ as = inb(ctlport+As);
+ if(as & reset){
+ /* nothing to do */;
+ }
+ else if(dev){
+ outb(cmdport+Dh, dev);
+ dev = 0;
+ }
+ else if(ready == 0 || (as & ready)){
+ atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);
+ return as;
+ }
+
+ if(micro-- <= 0){
+ atadebug(0, 0, "ataready: %d 0x%2.2uX\n", micro, as);
+ break;
+ }
+ microdelay(1);
+ }
+ atadebug(cmdport, ctlport, "ataready: timeout");
+
+ return -1;
+}
+
+static int
+atacsfenabled(Drive* drive, vlong csf)
+{
+ int cmdset, i, x;
+
+ for(i = 0; i < 3; i++){
+ x = (csf>>(16*i)) & 0xFFFF;
+ if(x == 0)
+ continue;
+ cmdset = drive->info[Icsfe+i];
+ if(cmdset == 0 || cmdset == 0xFFFF)
+ return 0;
+ return cmdset & x;
+ }
+
+ return 0;
+}
+
+/*
+static int
+atasf(int cmdport, int ctlport, int dev, uchar* command)
+{
+ int as, i;
+
+ if(ataready(cmdport, ctlport, dev, Bsy|Drq, Drdy, 108*1000) < 0)
+ return -1;
+
+ for(i = Features; i < Dh; i++)
+ outb(cmdport+i, command[i]);
+ outb(cmdport+Command, Csf);
+ microdelay(100);
+ as = ataready(cmdport, ctlport, 0, Bsy, Drdy|Df|Err, 109*1000);
+ if(as < 0 || (as & (Df|Err)))
+ return -1;
+ return 0;
+}
+ */
+
+static int
+ataidentify(int cmdport, int ctlport, int dev, int pkt, void* info)
+{
+ int as, command, drdy;
+
+ if(pkt){
+ command = Cidpkt;
+ drdy = 0;
+ }
+ else{
+ command = Cid;
+ drdy = Drdy;
+ }
+ as = ataready(cmdport, ctlport, dev, Bsy|Drq, drdy, 103*1000);
+ if(as < 0)
+ return as;
+ outb(cmdport+Command, command);
+ microdelay(1);
+
+ as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 400*1000);
+ if(as < 0)
+ return -1;
+ if(as & Err)
+ return as;
+
+ memset(info, 0, 512);
+ inss(cmdport+Data, info, 256);
+ inb(cmdport+Status);
+
+ if(DEBUG & DbgIDENTIFY){
+ int i;
+ ushort *sp;
+
+ sp = (ushort*)info;
+ for(i = 0; i < 256; i++){
+ if(i && (i%16) == 0)
+ print("\n");
+ print(" %4.4uX ", *sp);
+ sp++;
+ }
+ print("\n");
+ }
+
+ return 0;
+}
+
+static Drive*
+atadrive(int cmdport, int ctlport, int dev)
+{
+ Drive *drive;
+ int as, i, pkt;
+ uchar buf[512], *p;
+ ushort iconfig, *sp;
+
+ atadebug(0, 0, "identify: port 0x%uX dev 0x%2.2uX\n", cmdport, dev);
+ pkt = 1;
+retry:
+ as = ataidentify(cmdport, ctlport, dev, pkt, buf);
+ if(as < 0)
+ return nil;
+ if(as & Err){
+ if(pkt == 0)
+ return nil;
+ pkt = 0;
+ goto retry;
+ }
+
+ if((drive = malloc(sizeof(Drive))) == nil)
+ return nil;
+ drive->dev = dev;
+ memmove(drive->info, buf, sizeof(drive->info));
+ drive->sense[0] = 0x70;
+ drive->sense[7] = sizeof(drive->sense)-7;
+
+ drive->inquiry[2] = 2;
+ drive->inquiry[3] = 2;
+ drive->inquiry[4] = sizeof(drive->inquiry)-4;
+ p = &drive->inquiry[8];
+ sp = &drive->info[Imodel];
+ for(i = 0; i < 20; i++){
+ *p++ = *sp>>8;
+ *p++ = *sp++;
+ }
+
+ drive->secsize = 512;
+
+ /*
+ * Beware the CompactFlash Association feature set.
+ * Now, why this value in Iconfig just walks all over the bit
+ * definitions used in the other parts of the ATA/ATAPI standards
+ * is a mystery and a sign of true stupidity on someone's part.
+ * Anyway, the standard says if this value is 0x848A then it's
+ * CompactFlash and it's NOT a packet device.
+ */
+ iconfig = drive->info[Iconfig];
+ if(iconfig != 0x848A && (iconfig & 0xC000) == 0x8000){
+ if(iconfig & 0x01)
+ drive->pkt = 16;
+ else
+ drive->pkt = 12;
+ }
+ else{
+ if(drive->info[Ivalid] & 0x0001){
+ drive->c = drive->info[Iccyl];
+ drive->h = drive->info[Ichead];
+ drive->s = drive->info[Icsec];
+ }
+ else{
+ drive->c = drive->info[Ilcyl];
+ drive->h = drive->info[Ilhead];
+ drive->s = drive->info[Ilsec];
+ }
+ if(drive->info[Icapabilities] & 0x0200){
+ if(drive->info[Icsfs+1] & 0x0400){
+ drive->sectors = drive->info[Ilba48]
+ |(drive->info[Ilba48+1]<<16)
+ |((vlong)drive->info[Ilba48+2]<<32);
+ drive->flags |= Lba48;
+ }
+ else{
+ drive->sectors = (drive->info[Ilba+1]<<16)
+ |drive->info[Ilba];
+ }
+ drive->dev |= Lba;
+ }
+ else
+ drive->sectors = drive->c*drive->h*drive->s;
+ // atarwmmode(drive, cmdport, ctlport, dev);
+ }
+// atadmamode(drive);
+
+ if(DEBUG & DbgCONFIG){
+ print("dev %2.2uX port %uX config %4.4uX capabilities %4.4uX",
+ dev, cmdport, iconfig, drive->info[Icapabilities]);
+ print(" mwdma %4.4uX", drive->info[Imwdma]);
+ if(drive->info[Ivalid] & 0x04)
+ print(" udma %4.4uX", drive->info[Iudma]);
+// print(" dma %8.8uX rwm %ud", drive->dma, drive->rwm);
+ if(drive->flags&Lba48)
+ print("\tLLBA sectors %lld", drive->sectors);
+ print("\n");
+ }
+
+ return drive;
+}
+
+static void
+atasrst(int ctlport)
+{
+ /*
+ * Srst is a big stick and may cause problems if further
+ * commands are tried before the drives become ready again.
+ * Also, there will be problems here if overlapped commands
+ * are ever supported.
+ */
+ microdelay(5);
+ outb(ctlport+Dc, Srst);
+ microdelay(5);
+ outb(ctlport+Dc, 0);
+ microdelay(2*1000);
+}
+
+static SDev*
+ataprobe(int cmdport, int ctlport, int irq)
+{
+ Ctlr* ctlr;
+ SDev *sdev;
+ Drive *drive;
+ int dev, error, rhi, rlo;
+
+// if(ioalloc(cmdport, 8, 0, "atacmd") < 0)
+// return nil;
+// if(ioalloc(ctlport+As, 1, 0, "atactl") < 0){
+// iofree(cmdport);
+// return nil;
+// }
+
+ /*
+ * Try to detect a floating bus.
+ * Bsy should be cleared. If not, see if the cylinder registers
+ * are read/write capable.
+ * If the master fails, try the slave to catch slave-only
+ * configurations.
+ * There's no need to restore the tested registers as they will
+ * be reset on any detected drives by the Cedd command.
+ * All this indicates is that there is at least one drive on the
+ * controller; when the non-existent drive is selected in a
+ * single-drive configuration the registers of the existing drive
+ * are often seen, only command execution fails.
+ */
+ dev = Dev0;
+ if(inb(ctlport+As) & Bsy){
+ outb(cmdport+Dh, dev);
+ microdelay(1);
+trydev1:
+ atadebug(cmdport, ctlport, "ataprobe bsy");
+ outb(cmdport+Cyllo, 0xAA);
+ outb(cmdport+Cylhi, 0x55);
+ outb(cmdport+Sector, 0xFF);
+ rlo = inb(cmdport+Cyllo);
+ rhi = inb(cmdport+Cylhi);
+ if(rlo != 0xAA && (rlo == 0xFF || rhi != 0x55)){
+ if(dev == Dev1){
+release:
+ // iofree(cmdport);
+ // iofree(ctlport+As);
+ return nil;
+ }
+ dev = Dev1;
+ if(ataready(cmdport, ctlport, dev, Bsy, 0, 20*1000) < 0)
+ goto trydev1;
+ }
+ }
+
+ /*
+ * Disable interrupts on any detected controllers.
+ */
+ outb(ctlport+Dc, Nien);
+tryedd1:
+ if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 105*1000) < 0){
+ /*
+ * There's something there, but it didn't come up clean,
+ * so try hitting it with a big stick. The timing here is
+ * wrong but this is a last-ditch effort and it sometimes
+ * gets some marginal hardware back online.
+ */
+ atasrst(ctlport);
+ if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 106*1000) < 0)
+ goto release;
+ }
+
+ /*
+ * Can only get here if controller is not busy.
+ * If there are drives Bsy will be set within 400nS,
+ * must wait 2mS before testing Status.
+ * Wait for the command to complete (6 seconds max).
+ */
+ outb(cmdport+Command, Cedd);
+ delay(2);
+ if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 6*1000*1000) < 0)
+ goto release;
+
+ /*
+ * If bit 0 of the error register is set then the selected drive
+ * exists. This is enough to detect single-drive configurations.
+ * However, if the master exists there is no way short of executing
+ * a command to determine if a slave is present.
+ * It appears possible to get here testing Dev0 although it doesn't
+ * exist and the EDD won't take, so try again with Dev1.
+ */
+ error = inb(cmdport+Error);
+ atadebug(cmdport, ctlport, "ataprobe: dev %uX", dev);
+ if((error & ~0x80) != 0x01){
+ if(dev == Dev1)
+ goto release;
+ dev = Dev1;
+ goto tryedd1;
+ }
+
+ /*
+ * At least one drive is known to exist, try to
+ * identify it. If that fails, don't bother checking
+ * any further.
+ * If the one drive found is Dev0 and the EDD command
+ * didn't indicate Dev1 doesn't exist, check for it.
+ */
+ if((drive = atadrive(cmdport, ctlport, dev)) == nil)
+ goto release;
+ if((ctlr = malloc(sizeof(Ctlr))) == nil){
+ free(drive);
+ goto release;
+ }
+ if((sdev = malloc(sizeof(SDev))) == nil){
+ free(ctlr);
+ free(drive);
+ goto release;
+ }
+ drive->ctlr = ctlr;
+ if(dev == Dev0){
+ ctlr->drive[0] = drive;
+ if(!(error & 0x80)){
+ /*
+ * Always leave Dh pointing to a valid drive,
+ * otherwise a subsequent call to ataready on
+ * this controller may try to test a bogus Status.
+ * Ataprobe is the only place possibly invalid
+ * drives should be selected.
+ */
+ drive = atadrive(cmdport, ctlport, Dev1);
+ if(drive != nil){
+ drive->ctlr = ctlr;
+ ctlr->drive[1] = drive;
+ }
+ else{
+ outb(cmdport+Dh, Dev0);
+ microdelay(1);
+ }
+ }
+ }
+ else
+ ctlr->drive[1] = drive;
+
+ ctlr->cmdport = cmdport;
+ ctlr->ctlport = ctlport;
+ ctlr->irq = irq;
+ ctlr->tbdf = BUSUNKNOWN;
+ ctlr->command = Cedd; /* debugging */
+
+ sdev->ifc = &sdataifc;
+ sdev->ctlr = ctlr;
+ sdev->nunit = 2;
+ ctlr->sdev = sdev;
+
+ return sdev;
+}
+
+static int
+atasetsense(Drive* drive, int status, int key, int asc, int ascq)
+{
+ drive->sense[2] = key;
+ drive->sense[12] = asc;
+ drive->sense[13] = ascq;
+
+ return status;
+}
+
+static int
+atamodesense(Drive* drive, uchar* cmd)
+{
+ int len;
+
+ /*
+ * Fake a vendor-specific request with page code 0,
+ * return the drive info.
+ */
+ if((cmd[2] & 0x3F) != 0 && (cmd[2] & 0x3F) != 0x3F)
+ return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
+ len = (cmd[7]<<8)|cmd[8];
+ if(len == 0)
+ return SDok;
+ if(len < 8+sizeof(drive->info))
+ return atasetsense(drive, SDcheck, 0x05, 0x1A, 0);
+ if(drive->data == nil || drive->dlen < len)
+ return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
+ memset(drive->data, 0, 8);
+ drive->data[0] = sizeof(drive->info)>>8;
+ drive->data[1] = sizeof(drive->info);
+ memmove(drive->data+8, drive->info, sizeof(drive->info));
+ drive->data += 8+sizeof(drive->info);
+
+ return SDok;
+}
+
+static void
+atanop(Drive* drive, int subcommand)
+{
+ Ctlr* ctlr;
+ int as, cmdport, ctlport, timeo;
+
+ /*
+ * Attempt to abort a command by using NOP.
+ * In response, the drive is supposed to set Abrt
+ * in the Error register, set (Drdy|Err) in Status
+ * and clear Bsy when done. However, some drives
+ * (e.g. ATAPI Zip) just go Bsy then clear Status
+ * when done, hence the timeout loop only on Bsy
+ * and the forced setting of drive->error.
+ */
+ ctlr = drive->ctlr;
+ cmdport = ctlr->cmdport;
+ outb(cmdport+Features, subcommand);
+ outb(cmdport+Dh, drive->dev);
+ ctlr->command = Cnop; /* debugging */
+ outb(cmdport+Command, Cnop);
+
+ microdelay(1);
+ ctlport = ctlr->ctlport;
+ for(timeo = 0; timeo < 1000; timeo++){
+ as = inb(ctlport+As);
+ if(!(as & Bsy))
+ break;
+ microdelay(1);
+ }
+ drive->error |= Abrt;
+}
+
+static void
+ataabort(Drive* drive, int dolock)
+{
+ /*
+ * If NOP is available (packet commands) use it otherwise
+ * must try a software reset.
+ */
+ if(dolock)
+ ilock(drive->ctlr);
+ if(atacsfenabled(drive, 0x0000000000004000LL))
+ atanop(drive, 0);
+ else{
+ atasrst(drive->ctlr->ctlport);
+ drive->error |= Abrt;
+ }
+ if(dolock)
+ iunlock(drive->ctlr);
+}
+
+static int
+atapktiodone(void* arg)
+{
+ return ((Ctlr*)arg)->done;
+}
+
+static void
+atapktinterrupt(Drive* drive)
+{
+ Ctlr* ctlr;
+ int cmdport, len;
+
+ ctlr = drive->ctlr;
+ cmdport = ctlr->cmdport;
+ switch(inb(cmdport+Ir) & (/*Rel|*/Io|Cd)){
+ case Cd:
+ outss(cmdport+Data, drive->pktcmd, drive->pkt/2);
+ break;
+
+ case 0:
+ len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
+ if(drive->data+len > drive->limit){
+ atanop(drive, 0);
+ break;
+ }
+ outss(cmdport+Data, drive->data, len/2);
+ drive->data += len;
+ break;
+
+ case Io:
+ len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
+ if(drive->data+len > drive->limit){
+ atanop(drive, 0);
+ break;
+ }
+ inss(cmdport+Data, drive->data, len/2);
+ drive->data += len;
+ break;
+
+ case Io|Cd:
+ // if(drive->pktdma)
+ // atadmainterrupt(drive, drive->dlen);
+ // else
+ ctlr->done = 1;
+ break;
+ }
+}
+
+static int
+atapktio(Drive* drive, uchar* cmd, int clen)
+{
+ Ctlr *ctlr;
+ int as, cmdport, ctlport, len, r;
+
+ if(cmd[0] == 0x5A && (cmd[2] & 0x3F) == 0)
+ return atamodesense(drive, cmd);
+
+ r = SDok;
+
+ drive->command = Cpkt;
+ memmove(drive->pktcmd, cmd, clen);
+ memset(drive->pktcmd+clen, 0, drive->pkt-clen);
+ drive->limit = drive->data+drive->dlen;
+
+ ctlr = drive->ctlr;
+ cmdport = ctlr->cmdport;
+ ctlport = ctlr->ctlport;
+
+ qlock(ctlr);
+
+ as = ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 107*1000);
+ if(as < 0 || (as&Chk)){
+ qunlock(ctlr);
+ return -1;
+ }
+
+ ilock(ctlr);
+// if(drive->dlen && drive->dmactl && !atadmasetup(drive, drive->dlen))
+// drive->pktdma = Dma;
+// else
+// drive->pktdma = 0;
+
+ outb(cmdport+Features, 0/*drive->pktdma*/);
+ outb(cmdport+Count, 0);
+ outb(cmdport+Sector, 0);
+ len = 16*drive->secsize;
+ outb(cmdport+Bytelo, len);
+ outb(cmdport+Bytehi, len>>8);
+ outb(cmdport+Dh, drive->dev);
+ ctlr->done = 0;
+ ctlr->curdrive = drive;
+ ctlr->command = Cpkt; /* debugging */
+// if(drive->pktdma)
+// atadmastart(ctlr, drive->write);
+ outb(cmdport+Command, Cpkt);
+
+ if((drive->info[Iconfig] & 0x0060) != 0x0020){
+ microdelay(1);
+ as = ataready(cmdport, ctlport, 0, Bsy, Drq|Chk, 4*1000);
+ if(as < 0 || (as & (Bsy|Chk))){
+ drive->status = as<0 ? 0 : as;
+ ctlr->curdrive = nil;
+ ctlr->done = 1;
+ r = SDtimeout;
+ }else
+ atapktinterrupt(drive);
+ }
+ iunlock(ctlr);
+
+ sleep(ctlr, atapktiodone, ctlr);
+
+ qunlock(ctlr);
+
+ if(drive->status & Chk)
+ r = SDcheck;
+
+ return r;
+}
+
+static int
+atageniodone(void* arg)
+{
+ return ((Ctlr*)arg)->done;
+}
+
+static uchar cmd48[256] = {
+ [Crs] Crs48,
+ [Crd] Crd48,
+ [Crdq] Crdq48,
+ [Crsm] Crsm48,
+ [Cws] Cws48,
+ [Cwd] Cwd48,
+ [Cwdq] Cwdq48,
+ [Cwsm] Cwsm48,
+};
+
+static int
+atageniostart(Drive* drive, vlong lba)
+{
+ Ctlr *ctlr;
+ uchar cmd;
+ int as, c, cmdport, ctlport, h, len, s, use48;
+
+ use48 = 0;
+ if((drive->flags&Lba48always) || (lba>>28) || drive->count > 256){
+ if(!(drive->flags & Lba48))
+ return -1;
+ use48 = 1;
+ c = h = s = 0;
+ }else if(drive->dev & Lba){
+ c = (lba>>8) & 0xFFFF;
+ h = (lba>>24) & 0x0F;
+ s = lba & 0xFF;
+ }
+ else{
+ c = lba/(drive->s*drive->h);
+ h = ((lba/drive->s) % drive->h);
+ s = (lba % drive->s) + 1;
+ }
+
+ ctlr = drive->ctlr;
+ cmdport = ctlr->cmdport;
+ ctlport = ctlr->ctlport;
+ if(ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 101*1000) < 0)
+ return -1;
+
+ ilock(ctlr);
+
+ drive->block = drive->secsize;
+ if(drive->write)
+ drive->command = Cws;
+ else
+ drive->command = Crs;
+
+ drive->limit = drive->data + drive->count*drive->secsize;
+ cmd = drive->command;
+ if(use48){
+ outb(cmdport+Count, (drive->count>>8) & 0xFF);
+ outb(cmdport+Count, drive->count & 0XFF);
+ outb(cmdport+Lbalo, (lba>>24) & 0xFF);
+ outb(cmdport+Lbalo, lba & 0xFF);
+ outb(cmdport+Lbamid, (lba>>32) & 0xFF);
+ outb(cmdport+Lbamid, (lba>>8) & 0xFF);
+ outb(cmdport+Lbahi, (lba>>40) & 0xFF);
+ outb(cmdport+Lbahi, (lba>>16) & 0xFF);
+ outb(cmdport+Dh, drive->dev|Lba);
+ cmd = cmd48[cmd];
+
+ if(DEBUG & Dbg48BIT)
+ print("using 48-bit commands\n");
+ }else{
+ outb(cmdport+Count, drive->count);
+ outb(cmdport+Sector, s);
+ outb(cmdport+Cyllo, c);
+ outb(cmdport+Cylhi, c>>8);
+ outb(cmdport+Dh, drive->dev|h);
+ }
+ ctlr->done = 0;
+ ctlr->curdrive = drive;
+ ctlr->command = drive->command; /* debugging */
+ outb(cmdport+Command, cmd);
+
+ switch(drive->command){
+ case Cws:
+ case Cwsm:
+ microdelay(1);
+ as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 1000);
+ if(as < 0 || (as & Err)){
+ iunlock(ctlr);
+ return -1;
+ }
+ len = drive->block;
+ if(drive->data+len > drive->limit)
+ len = drive->limit-drive->data;
+ outss(cmdport+Data, drive->data, len/2);
+ break;
+
+ case Crd:
+ case Cwd:
+ // atadmastart(ctlr, drive->write);
+ break;
+ }
+ iunlock(ctlr);
+
+ return 0;
+}
+
+static int
+atagenioretry(Drive* drive)
+{
+ return atasetsense(drive, SDcheck, 4, 8, drive->error);
+}
+
+static int
+atagenio(Drive* drive, uchar* cmd, int)
+{
+ uchar *p;
+ Ctlr *ctlr;
+ int count, max;
+ vlong lba, len;
+
+ /*
+ * Map SCSI commands into ATA commands for discs.
+ * Fail any command with a LUN except INQUIRY which
+ * will return 'logical unit not supported'.
+ */
+ if((cmd[1]>>5) && cmd[0] != 0x12)
+ return atasetsense(drive, SDcheck, 0x05, 0x25, 0);
+
+ switch(cmd[0]){
+ default:
+ return atasetsense(drive, SDcheck, 0x05, 0x20, 0);
+
+ case 0x00: /* test unit ready */
+ return SDok;
+
+ case 0x03: /* request sense */
+ if(cmd[4] < sizeof(drive->sense))
+ len = cmd[4];
+ else
+ len = sizeof(drive->sense);
+ if(drive->data && drive->dlen >= len){
+ memmove(drive->data, drive->sense, len);
+ drive->data += len;
+ }
+ return SDok;
+
+ case 0x12: /* inquiry */
+ if(cmd[4] < sizeof(drive->inquiry))
+ len = cmd[4];
+ else
+ len = sizeof(drive->inquiry);
+ if(drive->data && drive->dlen >= len){
+ memmove(drive->data, drive->inquiry, len);
+ drive->data += len;
+ }
+ return SDok;
+
+ case 0x1B: /* start/stop unit */
+ /*
+ * NOP for now, can use the power management feature
+ * set later.
+ */
+ return SDok;
+
+ case 0x25: /* read capacity */
+ if((cmd[1] & 0x01) || cmd[2] || cmd[3])
+ return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
+ if(drive->data == nil || drive->dlen < 8)
+ return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
+ /*
+ * Read capacity returns the LBA of the last sector.
+ */
+ len = drive->sectors-1;
+ p = drive->data;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p++ = len;
+ len = drive->secsize;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p = len;
+ drive->data += 8;
+ return SDok;
+
+ case 0x9E: /* long read capacity */
+ if((cmd[1] & 0x01) || cmd[2] || cmd[3])
+ return atasetsense(drive, SDcheck, 0x05, 0x24, 0);
+ if(drive->data == nil || drive->dlen < 8)
+ return atasetsense(drive, SDcheck, 0x05, 0x20, 1);
+ /*
+ * Read capacity returns the LBA of the last sector.
+ */
+ len = drive->sectors-1;
+ p = drive->data;
+ *p++ = len>>56;
+ *p++ = len>>48;
+ *p++ = len>>40;
+ *p++ = len>>32;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p++ = len;
+ len = drive->secsize;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p = len;
+ drive->data += 8;
+ return SDok;
+
+ case 0x28: /* read */
+ case 0x2A: /* write */
+ break;
+
+ case 0x5A:
+ return atamodesense(drive, cmd);
+ }
+
+ ctlr = drive->ctlr;
+ lba = (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5];
+ count = (cmd[7]<<8)|cmd[8];
+ if(drive->data == nil)
+ return SDok;
+ if(drive->dlen < count*drive->secsize)
+ count = drive->dlen/drive->secsize;
+ qlock(ctlr);
+ while(count){
+ max = (drive->flags&Lba48) ? 65536 : 256;
+ if(count > max)
+ drive->count = max;
+ else
+ drive->count = count;
+ if(atageniostart(drive, lba)){
+ ilock(ctlr);
+ atanop(drive, 0);
+ iunlock(ctlr);
+ qunlock(ctlr);
+ return atagenioretry(drive);
+ }
+
+ tsleep(ctlr, atageniodone, ctlr, 10*1000);
+ if(!ctlr->done){
+ /*
+ * What should the above timeout be? In
+ * standby and sleep modes it could take as
+ * long as 30 seconds for a drive to respond.
+ * Very hard to get out of this cleanly.
+ */
+ // atadumpstate(drive, cmd, lba, count);
+ ataabort(drive, 1);
+ return atagenioretry(drive);
+ }
+
+ if(drive->status & Err){
+ qunlock(ctlr);
+ return atasetsense(drive, SDcheck, 4, 8, drive->error);
+ }
+ count -= drive->count;
+ lba += drive->count;
+ }
+ qunlock(ctlr);
+
+ return SDok;
+}
+
+static int
+atario(SDreq* r)
+{
+ Ctlr *ctlr;
+ Drive *drive;
+ SDunit *unit;
+ uchar cmd10[10], *cmdp, *p;
+ int clen, reqstatus, status;
+
+ unit = r->unit;
+ if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil){
+ r->status = SDtimeout;
+ return SDtimeout;
+ }
+ drive = ctlr->drive[unit->subno];
+
+ /*
+ * Most SCSI commands can be passed unchanged except for
+ * the padding on the end. The few which require munging
+ * are not used internally. Mode select/sense(6) could be
+ * converted to the 10-byte form but it's not worth the
+ * effort. Read/write(6) are easy.
+ */
+ switch(r->cmd[0]){
+ case 0x08: /* read */
+ case 0x0A: /* write */
+ cmdp = cmd10;
+ memset(cmdp, 0, sizeof(cmd10));
+ cmdp[0] = r->cmd[0]|0x20;
+ cmdp[1] = r->cmd[1] & 0xE0;
+ cmdp[5] = r->cmd[3];
+ cmdp[4] = r->cmd[2];
+ cmdp[3] = r->cmd[1] & 0x0F;
+ cmdp[8] = r->cmd[4];
+ clen = sizeof(cmd10);
+ break;
+
+ default:
+ cmdp = r->cmd;
+ clen = r->clen;
+ break;
+ }
+
+ qlock(drive);
+ drive->write = r->write;
+ drive->data = r->data;
+ drive->dlen = r->dlen;
+
+ drive->status = 0;
+ drive->error = 0;
+ if(drive->pkt)
+ status = atapktio(drive, cmdp, clen);
+ else
+ status = atagenio(drive, cmdp, clen);
+ if(status == SDok){
+ atasetsense(drive, SDok, 0, 0, 0);
+ if(drive->data){
+ p = r->data;
+ r->rlen = drive->data - p;
+ }
+ else
+ r->rlen = 0;
+ }
+ else if(status == SDcheck && !(r->flags & SDnosense)){
+ drive->write = 0;
+ memset(cmd10, 0, sizeof(cmd10));
+ cmd10[0] = 0x03;
+ cmd10[1] = r->lun<<5;
+ cmd10[4] = sizeof(r->sense)-1;
+ drive->data = r->sense;
+ drive->dlen = sizeof(r->sense)-1;
+ drive->status = 0;
+ drive->error = 0;
+ if(drive->pkt)
+ reqstatus = atapktio(drive, cmd10, 6);
+ else
+ reqstatus = atagenio(drive, cmd10, 6);
+ if(reqstatus == SDok){
+ r->flags |= SDvalidsense;
+ atasetsense(drive, SDok, 0, 0, 0);
+ }
+ }
+ qunlock(drive);
+ r->status = status;
+ if(status != SDok)
+ return status;
+
+ /*
+ * Fix up any results.
+ * Many ATAPI CD-ROMs ignore the LUN field completely and
+ * return valid INQUIRY data. Patch the response to indicate
+ * 'logical unit not supported' if the LUN is non-zero.
+ */
+ switch(cmdp[0]){
+ case 0x12: /* inquiry */
+ if((p = r->data) == nil)
+ break;
+ if((cmdp[1]>>5) && (!drive->pkt || (p[0] & 0x1F) == 0x05))
+ p[0] = 0x7F;
+ /*FALLTHROUGH*/
+ default:
+ break;
+ }
+
+ return SDok;
+}
+
+static void
+atainterrupt(Ureg*, void* arg)
+{
+ Ctlr *ctlr;
+ Drive *drive;
+ int cmdport, len, status;
+
+ ctlr = arg;
+
+ ilock(ctlr);
+ if(inb(ctlr->ctlport+As) & Bsy){
+ iunlock(ctlr);
+ if(DEBUG & DbgBsy)
+ print("IBsy+");
+ return;
+ }
+ cmdport = ctlr->cmdport;
+ status = inb(cmdport+Status);
+ if((drive = ctlr->curdrive) == nil){
+ iunlock(ctlr);
+ if((DEBUG & DbgINL) && ctlr->command != Cedd)
+ print("Inil%2.2uX+", ctlr->command);
+ return;
+ }
+
+ if(status & Err)
+ drive->error = inb(cmdport+Error);
+ else switch(drive->command){
+ default:
+ drive->error = Abrt;
+ break;
+
+ case Crs:
+ case Crsm:
+ if(!(status & Drq)){
+ drive->error = Abrt;
+ break;
+ }
+ len = drive->block;
+ if(drive->data+len > drive->limit)
+ len = drive->limit-drive->data;
+ inss(cmdport+Data, drive->data, len/2);
+ drive->data += len;
+ if(drive->data >= drive->limit)
+ ctlr->done = 1;
+ break;
+
+ case Cws:
+ case Cwsm:
+ len = drive->block;
+ if(drive->data+len > drive->limit)
+ len = drive->limit-drive->data;
+ drive->data += len;
+ if(drive->data >= drive->limit){
+ ctlr->done = 1;
+ break;
+ }
+ if(!(status & Drq)){
+ drive->error = Abrt;
+ break;
+ }
+ len = drive->block;
+ if(drive->data+len > drive->limit)
+ len = drive->limit-drive->data;
+ outss(cmdport+Data, drive->data, len/2);
+ break;
+
+ case Cpkt:
+ atapktinterrupt(drive);
+ break;
+
+ case Crd:
+ case Cwd:
+ // atadmainterrupt(drive, drive->count*drive->secsize);
+ break;
+ }
+ iunlock(ctlr);
+
+ if(drive->error){
+ status |= Err;
+ ctlr->done = 1;
+ }
+
+ if(ctlr->done){
+ ctlr->curdrive = nil;
+ drive->status = status;
+ wakeup(ctlr);
+ }
+}
+
+static SDev*
+atapnp(void)
+{
+ Ctlr *ctlr;
+ Pcidev *p;
+ int channel, ispc87415, pi, r;
+ SDev *legacy[2], *sdev, *head, *tail;
+
+ legacy[0] = legacy[1] = head = tail = nil;
+ if(sdev = ataprobe(0x1F0, 0x3F4, IrqATA0)){
+ head = tail = sdev;
+ legacy[0] = sdev;
+ }
+ if(sdev = ataprobe(0x170, 0x374, IrqATA1)){
+ if(head != nil)
+ tail->next = sdev;
+ else
+ head = sdev;
+ tail = sdev;
+ legacy[1] = sdev;
+ }
+
+ p = nil;
+ while(p = pcimatch(p, 0, 0)){
+ /*
+ * Look for devices with the correct class and sub-class
+ * code and known device and vendor ID; add native-mode
+ * channels to the list to be probed, save info for the
+ * compatibility mode channels.
+ * Note that the legacy devices should not be considered
+ * PCI devices by the interrupt controller.
+ * For both native and legacy, save info for busmastering
+ * if capable.
+ * Promise Ultra ATA/66 (PDC20262) appears to
+ * 1) give a sub-class of 'other mass storage controller'
+ * instead of 'IDE controller', regardless of whether it's
+ * the only controller or not;
+ * 2) put 0 in the programming interface byte (probably
+ * as a consequence of 1) above).
+ * Sub-class code 0x04 is 'RAID controller', e.g. VIA VT8237.
+ */
+ if(p->ccrb != 0x01)
+ continue;
+ if(p->ccru != 0x01 && p->ccru != 0x04 && p->ccru != 0x80)
+ continue;
+ pi = p->ccrp;
+ ispc87415 = 0;
+
+ switch((p->did<<16)|p->vid){
+ default:
+ continue;
+
+ case (0x0002<<16)|0x100B: /* NS PC87415 */
+ /*
+ * Disable interrupts on both channels until
+ * after they are probed for drives.
+ * This must be called before interrupts are
+ * enabled because the IRQ may be shared.
+ */
+ ispc87415 = 1;
+ pcicfgw32(p, 0x40, 0x00000300);
+ break;
+ case (0x1000<<16)|0x1042: /* PC-Tech RZ1000 */
+ /*
+ * Turn off prefetch. Overkill, but cheap.
+ */
+ r = pcicfgr32(p, 0x40);
+ r &= ~0x2000;
+ pcicfgw32(p, 0x40, r);
+ break;
+ case (0x4D38<<16)|0x105A: /* Promise PDC20262 */
+ case (0x4D30<<16)|0x105A: /* Promise PDC202xx */
+ case (0x4D68<<16)|0x105A: /* Promise PDC20268 */
+ case (0x4D69<<16)|0x105A: /* Promise Ultra/133 TX2 */
+ case (0x3373<<16)|0x105A: /* Promise 20378 RAID */
+ case (0x3149<<16)|0x1106: /* VIA VT8237 SATA/RAID */
+ case (0x4379<<16)|0x1002: /* ATI 4379 SATA*/
+ case (0x3112<<16)|0x1095: /* SiL 3112 SATA (DMA busted?) */
+ case (0x3114<<16)|0x1095: /* SiL 3114 SATA/RAID */
+ pi = 0x85;
+ break;
+ case (0x0004<<16)|0x1103: /* HighPoint HPT-370 */
+ pi = 0x85;
+ /*
+ * Turn off fast interrupt prediction.
+ */
+ if((r = pcicfgr8(p, 0x51)) & 0x80)
+ pcicfgw8(p, 0x51, r & ~0x80);
+ if((r = pcicfgr8(p, 0x55)) & 0x80)
+ pcicfgw8(p, 0x55, r & ~0x80);
+ break;
+ case (0x0640<<16)|0x1095: /* CMD 640B */
+ /*
+ * Bugfix code here...
+ */
+ break;
+ case (0x7441<<16)|0x1022: /* AMD 768 */
+ /*
+ * Set:
+ * 0x41 prefetch, postwrite;
+ * 0x43 FIFO configuration 1/2 and 1/2;
+ * 0x44 status register read retry;
+ * 0x46 DMA read and end of sector flush.
+ */
+ r = pcicfgr8(p, 0x41);
+ pcicfgw8(p, 0x41, r|0xF0);
+ r = pcicfgr8(p, 0x43);
+ pcicfgw8(p, 0x43, (r & 0x90)|0x2A);
+ r = pcicfgr8(p, 0x44);
+ pcicfgw8(p, 0x44, r|0x08);
+ r = pcicfgr8(p, 0x46);
+ pcicfgw8(p, 0x46, (r & 0x0C)|0xF0);
+ /*FALLTHROUGH*/
+ case (0x7469<<16)|0x1022: /* AMD 3111 */
+ /*
+ * This can probably be lumped in with the 768 above.
+ */
+ /*FALLTHROUGH*/
+ case (0x209A<<16)|0x1022: /* AMD CS5536 */
+ case (0x01BC<<16)|0x10DE: /* nVidia nForce1 */
+ case (0x0065<<16)|0x10DE: /* nVidia nForce2 */
+ case (0x0085<<16)|0x10DE: /* nVidia nForce2 MCP */
+ case (0x00D5<<16)|0x10DE: /* nVidia nForce3 */
+ case (0x00E5<<16)|0x10DE: /* nVidia nForce3 Pro */
+ case (0x0035<<16)|0x10DE: /* nVidia nForce3 MCP */
+ case (0x0053<<16)|0x10DE: /* nVidia nForce4 */
+ case (0x0054<<16)|0x10DE: /* nVidia nForce4 SATA */
+ case (0x0055<<16)|0x10DE: /* nVidia nForce4 SATA */
+ /*
+ * Ditto, although it may have a different base
+ * address for the registers (0x50?).
+ */
+ break;
+ case (0x0646<<16)|0x1095: /* CMD 646 */
+ case (0x0571<<16)|0x1106: /* VIA 82C686 */
+ case (0x0211<<16)|0x1166: /* ServerWorks IB6566 */
+ case (0x1230<<16)|0x8086: /* 82371FB (PIIX) */
+ case (0x7010<<16)|0x8086: /* 82371SB (PIIX3) */
+ case (0x7111<<16)|0x8086: /* 82371[AE]B (PIIX4[E]) */
+ case (0x2411<<16)|0x8086: /* 82801AA (ICH) */
+ case (0x2421<<16)|0x8086: /* 82801AB (ICH0) */
+ case (0x244A<<16)|0x8086: /* 82801BA (ICH2, Mobile) */
+ case (0x244B<<16)|0x8086: /* 82801BA (ICH2, High-End) */
+ case (0x248A<<16)|0x8086: /* 82801CA (ICH3, Mobile) */
+ case (0x248B<<16)|0x8086: /* 82801CA (ICH3, High-End) */
+ case (0x24CA<<16)|0x8086: /* 82801DBM (ICH4, Mobile) */
+ case (0x24CB<<16)|0x8086: /* 82801DB (ICH4, High-End) */
+ case (0x24DB<<16)|0x8086: /* 82801EB (ICH5) */
+ case (0x266F<<16)|0x8086: /* 82801FB (ICH6) */
+ case (0x27C4<<16)|0x8086: /* 82801GBM SATA (ICH7) */
+ case (0x27C5<<16)|0x8086: /* 82801GBM SATA AHCI (ICH7) */
+ break;
+ }
+
+ for(channel = 0; channel < 2; channel++){
+ if(pi & (1<<(2*channel))){
+ sdev = ataprobe(p->mem[0+2*channel].bar & ~0x01,
+ p->mem[1+2*channel].bar & ~0x01,
+ p->intl);
+ if(sdev == nil)
+ continue;
+
+ ctlr = sdev->ctlr;
+ if(ispc87415)
+ ctlr->ienable = pc87415ienable;
+
+ if(head != nil)
+ tail->next = sdev;
+ else
+ head = sdev;
+ tail = sdev;
+ ctlr->tbdf = p->tbdf;
+ }
+ else if((sdev = legacy[channel]) == nil)
+ continue;
+ else
+ ctlr = sdev->ctlr;
+
+ ctlr->pcidev = p;
+ }
+ }
+
+ return head;
+}
+
+static SDev*
+atalegacy(int port, int irq)
+{
+ return ataprobe(port, port+0x204, irq);
+}
+
+static SDev*
+ataid(SDev* sdev)
+{
+ int i;
+ Ctlr *ctlr;
+
+ /*
+ * Legacy controllers are always 'C' and 'D' and if
+ * they exist and have drives will be first in the list.
+ * If there are no active legacy controllers, native
+ * controllers start at 'C'.
+ */
+ if(sdev == nil)
+ return nil;
+ ctlr = sdev->ctlr;
+ if(ctlr->cmdport == 0x1F0 || ctlr->cmdport == 0x170)
+ i = 2;
+ else
+ i = 0;
+ while(sdev){
+ if(sdev->ifc == &sdataifc){
+ ctlr = sdev->ctlr;
+ if(ctlr->cmdport == 0x1F0)
+ sdev->idno = 'C';
+ else if(ctlr->cmdport == 0x170)
+ sdev->idno = 'D';
+ else{
+ sdev->idno = 'C'+i;
+ i++;
+ }
+ // snprint(sdev->name, NAMELEN, "sd%c", sdev->idno);
+ }
+ sdev = sdev->next;
+ }
+
+ return nil;
+}
+
+static int
+ataenable(SDev* sdev)
+{
+ Ctlr *ctlr;
+
+ ctlr = sdev->ctlr;
+
+ setvec(ctlr->irq+VectorPIC, atainterrupt, ctlr);
+ outb(ctlr->ctlport+Dc, 0);
+ if(ctlr->ienable)
+ ctlr->ienable(ctlr);
+
+ return 1;
+}
+
+SDifc sdataifc = {
+ "ata", /* name */
+
+ atapnp, /* pnp */
+ atalegacy, /* legacy */
+ ataid, /* id */
+ ataenable, /* enable */
+ nil, /* disable */
+
+ scsiverify, /* verify */
+ scsionline, /* online */
+ atario, /* rio */
+ nil, /* rctl */
+ nil, /* wctl */
+
+ scsibio, /* bio */
+};
--- /dev/null
+++ b/os/boot.original/pc/sdbios.c
@@ -1,0 +1,165 @@
+/*
+ * boot driver for BIOS devices with partitions
+ * devbios must be called first
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "error.h"
+
+#include "sd.h"
+#include "fs.h"
+
+long biosread(Fs *, void *, long);
+vlong biosseek(Fs *fs, vlong off);
+
+extern SDifc sdbiosifc;
+extern int onlybios0, biosinited;
+
+int
+biosverify(SDunit* )
+{
+ if (onlybios0 || !biosinited)
+ return 0;
+ return 1;
+}
+
+int
+biosonline(SDunit* unit)
+{
+ if (onlybios0 || !biosinited || !unit)
+ return 0;
+ unit->sectors = 1UL << 30; /* a bunch */
+ unit->secsize = 512; /* conventional */
+ return 1;
+}
+
+static int
+biosrio(SDreq* r)
+{
+ int nb;
+ long got;
+ vlong len, off;
+ uchar *p;
+ Fs fs; /* just for fs->dev, which is zero */
+
+ if (onlybios0 || !biosinited)
+ return SDeio;
+ /*
+ * Most SCSI commands can be passed unchanged except for
+ * the padding on the end. The few which require munging
+ * are not used internally. Mode select/sense(6) could be
+ * converted to the 10-byte form but it's not worth the
+ * effort. Read/write(6) are easy.
+ */
+ r->rlen = 0;
+ r->status = SDok;
+ switch(r->cmd[0]){
+ case 0x08: /* read */
+ case 0x28: /* read */
+ if (r->cmd[0] == 0x08)
+ panic("biosrio: 0x08 read op\n");
+ off = r->cmd[2]<<24 | r->cmd[3]<<16 | r->cmd[4]<<8 | r->cmd[5];
+ nb = r->cmd[7]<<8 | r->cmd[8]; /* often 4 */
+ USED(nb); /* is nb*512 == r->dlen? */
+ memset(&fs, 0, sizeof fs);
+ biosseek(&fs, off*512);
+ got = biosread(&fs, r->data, r->dlen);
+ if (got < 0)
+ r->status = SDeio;
+ else
+ r->rlen = got;
+ break;
+ case 0x0A: /* write */
+ case 0x2A: /* write */
+ r->status = SDeio; /* boot programs don't write */
+ break;
+ case 0x25: /* read capacity */
+ /*
+ * Read capacity returns the LBA of the last sector.
+ */
+ len = r->unit->sectors - 1;
+ p = r->data;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p++ = len;
+ len = r->unit->secsize;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p = len;
+ r->data = (char *)r->data + 8;
+ return SDok;
+ case 0x9E: /* long read capacity */
+ /*
+ * Read capacity returns the LBA of the last sector.
+ */
+ len = r->unit->sectors - 1;
+ p = r->data;
+ *p++ = len>>56;
+ *p++ = len>>48;
+ *p++ = len>>40;
+ *p++ = len>>32;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p++ = len;
+ len = r->unit->secsize;
+ *p++ = len>>24;
+ *p++ = len>>16;
+ *p++ = len>>8;
+ *p = len;
+ r->data = (char *)r->data + 8;
+ return SDok;
+ /* ignore others */
+ }
+ return r->status;
+}
+
+SDev*
+biosid(SDev* sdev)
+{
+ for (; sdev; sdev = sdev->next)
+ if (sdev->ifc == &sdbiosifc)
+ sdev->idno = 'B';
+ return sdev;
+}
+
+static SDev*
+biospnp(void)
+{
+ SDev *sdev;
+
+ /* 9pxeload can't use bios int 13 calls; they wedge the machine */
+ if (pxe || getconf("*nobiosload") != nil || onlybios0 || !biosinited)
+ return nil;
+ if((sdev = malloc(sizeof(SDev))) != nil) {
+ sdev->ifc = &sdbiosifc;
+ sdev->index = -1;
+ sdev->nunit = 1;
+ }
+ return sdev;
+}
+
+SDifc sdbiosifc = {
+ "bios", /* name */
+
+ biospnp, /* pnp */
+ nil, /* legacy */
+ biosid, /* id */
+ nil, /* enable */
+ nil, /* disable */
+
+ biosverify, /* verify */
+ biosonline, /* online */
+ biosrio, /* rio */
+ nil, /* rctl */
+ nil, /* wctl */
+
+ scsibio, /* bio */
+};
--- /dev/null
+++ b/os/boot.original/pc/sdiahci.c
@@ -1,0 +1,1668 @@
+/*
+ * intel/amd ahci (advanced host controller interface) sata controller
+ * bootstrap driver
+ * copyright © 2007, 2008 coraid, inc.
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "error.h"
+#include "sd.h"
+#include "ahci.h"
+
+#define dprint if(debug==0){}else print
+#define idprint if(prid==0){}else print
+#define aprint if(datapi==0){}else print
+
+enum {
+ NCtlr = 2,
+ NCtlrdrv= 8,
+ NDrive = NCtlr*NCtlrdrv,
+
+ Read = 0,
+ Write
+};
+
+/* pci space configurtion */
+enum {
+ Pmap = 0x90,
+ Ppcs = 0x91,
+ Prev = 0xa8,
+};
+
+enum {
+ Tesb,
+ Tich,
+ Tsb600,
+};
+
+#define Intel(x) ((x) == Tesb || (x) == Tich)
+
+static char *tname[] = {
+ "63xxesb",
+ "ich",
+ "sb600",
+};
+
+enum {
+ Dnull,
+ Dmissing,
+ Dnew,
+ Dready,
+ Derror,
+ Dreset,
+ Doffline,
+ Dportreset,
+ Dlast
+};
+
+static char *diskstates[Dlast] = {
+ "null",
+ "missing",
+ "new",
+ "ready",
+ "error",
+ "reset",
+ "offline",
+ "portreset",
+};
+
+extern SDifc sdiahciifc;
+typedef struct Ctlr Ctlr;
+
+enum {
+ DMautoneg,
+ DMsatai,
+ DMsataii,
+};
+
+static char *modename[] = {
+ "auto",
+ "satai",
+ "sataii",
+};
+
+typedef struct {
+ Lock;
+
+ Ctlr *ctlr;
+ SDunit *unit;
+ char name[10];
+ Aport *port;
+ Aportm portm;
+ Aportc portc; /* redundant ptr to port and portm. */
+
+ uchar mediachange;
+ uchar state;
+ uchar smartrs;
+
+ uvlong sectors;
+ ulong intick;
+ int wait;
+ uchar mode; /* DMautoneg, satai or sataii. */
+ uchar active;
+
+ char serial[20+1];
+ char firmware[8+1];
+ char model[40+1];
+
+ ushort info[0x200];
+
+ int driveno; /* ctlr*NCtlrdrv + unit */
+ int portno; /* ctlr port # != drive # when not all ports enabled. */
+} Drive;
+
+struct Ctlr {
+ Lock;
+
+ int type;
+ int enabled;
+ SDev *sdev;
+ Pcidev *pci;
+
+ uchar *mmio;
+ ulong *lmmio;
+ Ahba *hba;
+
+ Drive rawdrive[NCtlrdrv];
+ Drive* drive[NCtlrdrv];
+ int ndrive;
+};
+
+static Ctlr iactlr[NCtlr];
+static SDev sdevs[NCtlr];
+static int niactlr;
+
+static int prid = 0;
+static int datapi = 0;
+
+static char stab[] = {
+[0] 'i', 'm',
+[8] 't', 'c', 'p', 'e',
+[16] 'N', 'I', 'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
+};
+
+static void
+serrstr(ulong r, char *s, char *e)
+{
+ int i;
+
+ e -= 3;
+ for(i = 0; i < nelem(stab) && s < e; i++)
+ if((r & (1<<i)) && stab[i]){
+ *s++ = stab[i];
+ if(SerrBad & (1<<i))
+ *s++ = '*';
+ }
+ *s = 0;
+}
+
+static char ntab[] = "0123456789abcdef";
+
+static void
+preg(uchar *reg, int n)
+{
+ int i;
+ char buf[25*3+1], *e;
+
+ e = buf;
+ for(i = 0; i < n; i++){
+ *e++ = ntab[reg[i] >> 4];
+ *e++ = ntab[reg[i] & 0xf];
+ *e++ = ' ';
+ }
+ *e++ = '\n';
+ *e = 0;
+ dprint(buf);
+}
+
+static void
+dreg(char *s, Aport *p)
+{
+ dprint("%stask=%lux; cmd=%lux; ci=%lux; is=%lux\n",
+ s, p->task, p->cmd, p->ci, p->isr);
+}
+
+static void
+esleep(int ms)
+{
+ delay(ms);
+}
+
+typedef struct {
+ Aport *p;
+ int i;
+} Asleep;
+
+static int
+ahciclear(void *v)
+{
+ Asleep *s;
+
+ s = v;
+ return (s->p->ci & s->i) == 0;
+}
+
+static void
+aesleep(Aportm *, Asleep *a, int ms)
+{
+ ulong start;
+
+ start = m->ticks;
+ while((a->p->ci & a->i) != 0)
+ if(TK2MS(m->ticks-start) >= ms)
+ break;
+}
+
+static int
+ahciwait(Aportc *c, int ms)
+{
+ Aport *p;
+ Asleep as;
+
+ p = c->p;
+ p->ci = 1;
+ as.p = p;
+ as.i = 1;
+ aesleep(c->m, &as, ms);
+ if((p->task & 1) == 0 && p->ci == 0)
+ return 0;
+ dreg("ahciwait timeout ", c->p);
+ return -1;
+}
+
+static int
+setfeatures(Aportc *pc, uchar f)
+{
+ uchar *c;
+ Actab *t;
+ Alist *l;
+
+ t = pc->m->ctab;
+ c = t->cfis;
+
+ memset(c, 0, 0x20);
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = 0xef;
+ c[3] = f;
+ c[7] = 0xa0; /* obsolete device bits */
+
+ l = pc->m->list;
+ l->flags = Lwrite|0x5;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ return ahciwait(pc, 3*1000);
+}
+
+static int
+setudmamode(Aportc *pc, uchar f)
+{
+ uchar *c;
+ Actab *t;
+ Alist *l;
+
+ t = pc->m->ctab;
+ c = t->cfis;
+
+ memset(c, 0, 0x20);
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = 0xef;
+ c[3] = 3; /* set transfer mode */
+ c[7] = 0xa0; /* obsolete device bits */
+ c[12] = 0x40 | f; /* sector count */
+
+ l = pc->m->list;
+ l->flags = Lwrite | 0x5;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ return ahciwait(pc, 3*1000);
+}
+
+static void
+asleep(int ms)
+{
+ delay(ms);
+}
+
+static int
+ahciportreset(Aportc *c)
+{
+ ulong *cmd, i;
+ Aport *p;
+
+ p = c->p;
+ cmd = &p->cmd;
+ *cmd &= ~(Afre|Ast);
+ for(i = 0; i < 500; i += 25){
+ if((*cmd & Acr) == 0)
+ break;
+ asleep(25);
+ }
+ p->sctl = 1 | (p->sctl & ~7);
+ delay(1);
+ p->sctl &= ~7;
+ return 0;
+}
+
+static ushort
+gbit16(void *a)
+{
+ uchar *i;
+
+ i = a;
+ return i[1]<<8 | i[0];
+}
+
+static ulong
+gbit32(void *a)
+{
+ ulong j;
+ uchar *i;
+
+ i = a;
+ j = i[3] << 24;
+ j |= i[2] << 16;
+ j |= i[1] << 8;
+ j |= i[0];
+ return j;
+}
+
+static uvlong
+gbit64(void *a)
+{
+ uchar *i;
+
+ i = a;
+ return (uvlong) gbit32(i+4)<<32 | gbit32(a);
+}
+
+static int
+ahciidentify0(Aportc *pc, void *id, int atapi)
+{
+ uchar *c;
+ Actab *t;
+ Alist *l;
+ Aprdt *p;
+ static uchar tab[] = { 0xec, 0xa1 };
+
+ t = pc->m->ctab;
+ c = t->cfis;
+
+ memset(c, 0, 0x20);
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = tab[atapi];
+ c[7] = 0xa0; /* obsolete device bits */
+
+ l = pc->m->list;
+ l->flags = 1<<16 | 0x5;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ memset(id, 0, 0x100);
+ p = &t->prdt;
+ p->dba = PCIWADDR(id);
+ p->dbahi = 0;
+ p->count = 1<<31 | (0x200-2) | 1;
+
+ return ahciwait(pc, 3*1000);
+}
+
+static vlong
+ahciidentify(Aportc *pc, ushort *id)
+{
+ int i, sig;
+ vlong s;
+ Aportm *m;
+
+ m = pc->m;
+ m->feat = 0;
+ m->smart = 0;
+ i = 0;
+ sig = pc->p->sig >> 16;
+ if(sig == 0xeb14){
+ m->feat |= Datapi;
+ i = 1;
+ }
+ if(ahciidentify0(pc, id, i) == -1)
+ return -1;
+
+ i = gbit16(id+83) | gbit16(id+86);
+ if(i & (1<<10)){
+ m->feat |= Dllba;
+ s = gbit64(id+100);
+ }else
+ s = gbit32(id+60);
+
+ if(m->feat & Datapi){
+ i = gbit16(id+0);
+ if(i & 1)
+ m->feat |= Datapi16;
+ }
+
+ i = gbit16(id+83);
+ if((i>>14) != 1)
+ return s;
+ if(i & (1<<3))
+ m->feat |= Dpower;
+ i = gbit16(id+82);
+ if(i & 1)
+ m->feat |= Dsmart;
+ if(i & (1<<14))
+ m->feat |= Dnop;
+ return s;
+}
+
+static int
+ahciquiet(Aport *a)
+{
+ ulong *p, i;
+
+ p = &a->cmd;
+ *p &= ~Ast;
+ for(i = 0; i < 500; i += 50){
+ if((*p & Acr) == 0)
+ goto stop;
+ asleep(50);
+ }
+ return -1;
+stop:
+ if((a->task & (ASdrq|ASbsy)) == 0){
+ *p |= Ast;
+ return 0;
+ }
+
+ *p |= Aclo;
+ for(i = 0; i < 500; i += 50){
+ if((*p & Aclo) == 0)
+ goto stop1;
+ asleep(50);
+ }
+ return -1;
+stop1:
+ /* extra check */
+ dprint("clo clear %lx\n", a->task);
+ if(a->task & ASbsy)
+ return -1;
+ *p |= Ast;
+ return 0;
+}
+
+static int
+ahciidle(Aport *port)
+{
+ ulong *p, i, r;
+
+ p = &port->cmd;
+ if((*p & Arun) == 0)
+ return 0;
+ *p &= ~Ast;
+ r = 0;
+ for(i = 0; i < 500; i += 25){
+ if((*p & Acr) == 0)
+ goto stop;
+ asleep(25);
+ }
+ r = -1;
+stop:
+ if((*p & Afre) == 0)
+ return r;
+ *p &= ~Afre;
+ for(i = 0; i < 500; i += 25){
+ if((*p & Afre) == 0)
+ return 0;
+ asleep(25);
+ }
+ return -1;
+}
+
+/*
+ * §6.2.2.1 first part; comreset handled by reset disk.
+ * - remainder is handled by configdisk.
+ * - ahcirecover is a quick recovery from a failed command.
+ */
+int
+ahciswreset(Aportc *pc)
+{
+ int i;
+
+ i = ahciidle(pc->p);
+ pc->p->cmd |= Afre;
+ if(i == -1)
+ return -1;
+ if(pc->p->task & (ASdrq|ASbsy))
+ return -1;
+ return 0;
+}
+
+int
+ahcirecover(Aportc *pc)
+{
+ ahciswreset(pc);
+ pc->p->cmd |= Ast;
+ if(setudmamode(pc, 5) == -1)
+ return -1;
+ return 0;
+}
+
+static void*
+malign(int size, int align)
+{
+ void *v;
+
+ v = xspanalloc(size, align, 0);
+ memset(v, 0, size);
+ return v;
+}
+
+static void
+setupfis(Afis *f)
+{
+ f->base = malign(0x100, 0x100);
+ f->d = f->base + 0;
+ f->p = f->base + 0x20;
+ f->r = f->base + 0x40;
+ f->u = f->base + 0x60;
+ f->devicebits = (ulong*)(f->base + 0x58);
+}
+
+static void
+ahciwakeup(Aport *p)
+{
+ ushort s;
+
+ s = p->sstatus;
+ if((s & 0x700) != 0x600)
+ return;
+ if((s & 7) != 1){
+ print("ahci: slumbering drive unwakeable %ux\n", s);
+ return;
+ }
+ p->sctl = 3*Aipm | 0*Aspd | Adet;
+ delay(1);
+ p->sctl &= ~7;
+// iprint("ahci: wake %ux -> %ux\n", s, p->sstatus);
+}
+
+static int
+ahciconfigdrive(Ahba *h, Aportc *c, int mode)
+{
+ Aportm *m;
+ Aport *p;
+
+ p = c->p;
+ m = c->m;
+
+ if(m->list == 0){
+ setupfis(&m->fis);
+ m->list = malign(sizeof *m->list, 1024);
+ m->ctab = malign(sizeof *m->ctab, 128);
+ }
+
+ if(p->sstatus & 3 && h->cap & Hsss){
+ dprint("configdrive: spinning up ... [%lux]\n", p->sstatus);
+ p->cmd |= Apod|Asud;
+ asleep(1400);
+ }
+
+ p->serror = SerrAll;
+
+ p->list = PCIWADDR(m->list);
+ p->listhi = 0;
+ p->fis = PCIWADDR(m->fis.base);
+ p->fishi = 0;
+ p->cmd |= Afre | Ast;
+
+ if((p->sstatus & 0x707) == 0x601) /* drive coming up in slumbering? */
+ ahciwakeup(p);
+
+ /* disable power managment sequence from book. */
+ p->sctl = (3*Aipm) | (mode*Aspd) | (0*Adet);
+ p->cmd &= ~Aalpe;
+
+ p->ie = IEM;
+
+ return 0;
+}
+
+static int
+ahcienable(Ahba *h)
+{
+ h->ghc |= Hie;
+ return 0;
+}
+
+static int
+ahcidisable(Ahba *h)
+{
+ h->ghc &= ~Hie;
+ return 0;
+}
+
+static int
+countbits(ulong u)
+{
+ int i, n;
+
+ n = 0;
+ for(i = 0; i < 32; i++)
+ if(u & (1<<i))
+ n++;
+ return n;
+}
+
+static int
+ahciconf(Ctlr *c)
+{
+ ulong u;
+ Ahba *h;
+ static int count;
+
+ h = c->hba = (Ahba*)c->mmio;
+ u = h->cap;
+
+ if((u & Hsam) == 0)
+ h->ghc |= Hae;
+
+ print("ahci%d port %#p: hba sss %ld; ncs %ld; coal %ld; mports %ld; "
+ "led %ld; clo %ld; ems %ld;\n", count++, h,
+ (u>>27) & 1, (u>>8) & 0x1f, (u>>7) & 1, u & 0x1f, (u>>25) & 1,
+ (u>>24) & 1, (u>>6) & 1);
+ return countbits(h->pi);
+}
+
+static int
+ahcihbareset(Ahba *h)
+{
+ int wait;
+
+ h->ghc |= 1;
+ for(wait = 0; wait < 1000; wait += 100){
+ if(h->ghc == 0)
+ return 0;
+ delay(100);
+ }
+ return -1;
+}
+
+static void
+idmove(char *p, ushort *a, int n)
+{
+ int i;
+ char *op, *e;
+
+ op = p;
+ for(i = 0; i < n/2; i++){
+ *p++ = a[i] >> 8;
+ *p++ = a[i];
+ }
+ *p = 0;
+ while(p > op && *--p == ' ')
+ *p = 0;
+ e = p;
+ for (p = op; *p == ' '; p++)
+ ;
+ memmove(op, p, n - (e - p));
+}
+
+static int
+identify(Drive *d)
+{
+ ushort *id;
+ vlong osectors, s;
+ uchar oserial[21];
+ SDunit *u;
+
+ id = d->info;
+ s = ahciidentify(&d->portc, id);
+ if(s == -1){
+ d->state = Derror;
+ return -1;
+ }
+ osectors = d->sectors;
+ memmove(oserial, d->serial, sizeof d->serial);
+
+ d->sectors = s;
+ d->smartrs = 0;
+
+ idmove(d->serial, id+10, 20);
+ idmove(d->firmware, id+23, 8);
+ idmove(d->model, id+27, 40);
+
+ u = d->unit;
+ memset(u->inquiry, 0, sizeof u->inquiry);
+ u->inquiry[2] = 2;
+ u->inquiry[3] = 2;
+ u->inquiry[4] = sizeof u->inquiry - 4;
+ memmove(u->inquiry+8, d->model, 40);
+
+ if((osectors == 0 || osectors != s) &&
+ memcmp(oserial, d->serial, sizeof oserial) != 0){
+ d->mediachange = 1;
+ u->sectors = 0;
+ }
+
+ return 0;
+}
+
+static void
+clearci(Aport *p)
+{
+ if((p->cmd & Ast) == 0)
+ return;
+ p->cmd &= ~Ast;
+ p->cmd |= Ast;
+}
+
+static void
+updatedrive(Drive *d)
+{
+ ulong cause, serr, s0, pr, ewake;
+ char *name;
+ Aport *p;
+ static ulong last;
+
+ pr = 1;
+ ewake = 0;
+ p = d->port;
+ cause = p->isr;
+ serr = p->serror;
+ p->isr = cause;
+ name = "??";
+ if(d->unit && d->unit->name)
+ name = d->unit->name;
+
+ if(p->ci == 0){
+ d->portm.flag |= Fdone;
+ pr = 0;
+ }else if(cause & Adps)
+ pr = 0;
+ if(cause&Ifatal){
+ ewake = 1;
+ dprint("Fatal\n");
+ }
+ if(cause & Adhrs){
+ if(p->task & (32|1)){
+ dprint("Adhrs cause = %lux; serr = %lux; task=%lux\n",
+ cause, serr, p->task);
+ d->portm.flag |= Ferror;
+ ewake = 1;
+ }
+ pr = 0;
+ }
+
+ if(pr)
+ dprint("%s: upd %lux ta %lux\n", name, cause, p->task);
+ if(cause & (Aprcs|Aifs)){
+ s0 = d->state;
+ switch(p->sstatus & 7){
+ case 0:
+ d->state = Dmissing;
+ break;
+ case 1:
+ if((p->sstatus & 0x700) == 0x600)
+ d->state = Dnew;
+ else
+ d->state = Derror;
+ break;
+ case 3:
+ /* power mgnt crap for surprise removal */
+ p->ie |= Aprcs | Apcs; /* is this required? */
+ d->state = Dreset;
+ break;
+ case 4:
+ d->state = Doffline;
+ break;
+ }
+ dprint("%s: %s → %s [Apcrs] %lux\n", name, diskstates[s0],
+ diskstates[d->state], p->sstatus);
+ if(s0 == Dready && d->state != Dready)
+ idprint("%s: pulled\n", name);
+ if(d->state != Dready)
+ d->portm.flag |= Ferror;
+ ewake = 1;
+ }
+ p->serror = serr;
+ if(ewake)
+ clearci(p);
+ last = cause;
+}
+
+static void
+pstatus(Drive *d, ulong s)
+{
+ /*
+ * bogus code because the first interrupt is currently dropped.
+ * likely my fault. serror may be cleared at the wrong time.
+ */
+ switch(s){
+ case 0:
+ d->state = Dmissing;
+ break;
+ case 2: /* should this be missing? need testcase. */
+ dprint("pstatus 2\n");
+ case 3:
+ d->wait = 0;
+ d->state = Dnew;
+ break;
+ case 4:
+ d->state = Doffline;
+ break;
+ case 6:
+ d->state = Dnew;
+ break;
+ }
+}
+
+static int
+configdrive(Drive *d)
+{
+ if(ahciconfigdrive(d->ctlr->hba, &d->portc, d->mode) == -1)
+ return -1;
+ ilock(d);
+ pstatus(d, d->port->sstatus & 7);
+ iunlock(d);
+ return 0;
+}
+
+static void
+resetdisk(Drive *d)
+{
+ uint state, det, stat;
+ Aport *p;
+
+ p = d->port;
+ det = p->sctl & 7;
+ stat = p->sstatus & 7;
+ state = (p->cmd>>28) & 0xf;
+ dprint("resetdisk: icc %ux det %d sdet %d\n", state, det, stat);
+ if(stat != 3){
+ ilock(d);
+ d->state = Dportreset;
+ iunlock(d);
+ return;
+ }
+ ilock(d);
+ state = d->state;
+ if(d->state != Dready || d->state != Dnew)
+ d->portm.flag |= Ferror;
+ clearci(p); /* satisfy sleep condition. */
+ iunlock(d);
+
+ qlock(&d->portm);
+
+ if(p->cmd & Ast && ahciswreset(&d->portc) == -1){
+ ilock(d);
+ d->state = Dportreset; /* get a bigger stick. */
+ iunlock(d);
+ } else {
+ ilock(d);
+ d->state = Dmissing;
+ iunlock(d);
+
+ configdrive(d);
+ }
+ dprint("resetdisk: %s → %s\n", diskstates[state], diskstates[d->state]);
+ qunlock(&d->portm);
+}
+
+static int
+newdrive(Drive *d)
+{
+ char *name, *s;
+ Aportc *c;
+ Aportm *m;
+
+ c = &d->portc;
+ m = &d->portm;
+
+ name = d->unit->name;
+ if(name == 0)
+ name = "??";
+
+ if(d->port->task == 0x80)
+ return -1;
+ qlock(c->m);
+ if(setudmamode(c, 5) == -1){
+ dprint("%s: can't set udma mode\n", name);
+ goto lose;
+ }
+ if(identify(d) == -1){
+ dprint("%s: identify failure\n", name);
+ goto lose;
+ }
+ if(m->feat & Dpower && setfeatures(c, 0x85) == -1){
+ m->feat &= ~Dpower;
+ if(ahcirecover(c) == -1) {
+ dprint("%s: ahcirecover failed\n", name);
+ goto lose;
+ }
+ }
+
+ ilock(d);
+ d->state = Dready;
+ iunlock(d);
+
+ qunlock(c->m);
+
+ s = "";
+ if(m->feat & Dllba)
+ s = "L";
+ idprint("%s: %sLBA %lld sectors\n", d->unit->name, s, d->sectors);
+ idprint(" %s %s %s %s\n", d->model, d->firmware, d->serial,
+ d->mediachange? "[mediachange]": "");
+
+ return 0;
+
+lose:
+ qunlock(&d->portm);
+ return -1;
+}
+
+enum {
+ Nms = 256,
+ Mphywait = 2*1024/Nms - 1,
+ Midwait = 16*1024/Nms - 1,
+ Mcomrwait = 64*1024/Nms - 1,
+};
+
+static void
+westerndigitalhung(Drive *d)
+{
+ if((d->portm.feat & Datapi) == 0 && d->active &&
+ TK2MS(m->ticks - d->intick) > 5000){
+ dprint("%s: drive hung; resetting [%lux] ci=%lx\n",
+ d->unit->name, d->port->task, d->port->ci);
+ d->state = Dreset;
+ }
+}
+
+static ushort olds[NCtlr*NCtlrdrv];
+
+static int
+doportreset(Drive *d)
+{
+ int i;
+
+ i = -1;
+ qlock(&d->portm);
+ if(ahciportreset(&d->portc) == -1)
+ dprint("ahciportreset fails\n");
+ else
+ i = 0;
+ qunlock(&d->portm);
+ dprint("portreset → %s [task %lux]\n", diskstates[d->state],
+ d->port->task);
+ return i;
+}
+
+static void
+checkdrive(Drive *d, int i)
+{
+ ushort s;
+ char *name;
+
+ ilock(d);
+ name = d->unit->name;
+ s = d->port->sstatus;
+ if(s != olds[i]){
+ dprint("%s: status: %#ux -> %#ux: %s\n", name, olds[i],
+ s, diskstates[d->state]);
+ olds[i] = s;
+ d->wait = 0;
+ }
+ westerndigitalhung(d);
+ switch(d->state){
+ case Dnull:
+ break;
+ case Dmissing:
+ case Dnew:
+ switch(s & 0x107){
+ case 1:
+ ahciwakeup(d->port);
+ case 0:
+ break;
+ default:
+ dprint("%s: unknown status %04ux\n", name, s);
+ case 0x100:
+ if(++d->wait&Mphywait)
+ break;
+reset:
+ if(++d->mode > DMsataii)
+ d->mode = 0;
+ if(d->mode == DMsatai){ /* we tried everything */
+ d->state = Dportreset;
+ goto portreset;
+ }
+ dprint("%s: reset; new mode %s\n", name,
+ modename[d->mode]);
+ iunlock(d);
+ resetdisk(d);
+ ilock(d);
+ break;
+ case 0x103:
+ if((++d->wait&Midwait) == 0){
+ dprint("%s: slow reset %#ux task=%#lux; %d\n",
+ name, s, d->port->task, d->wait);
+ goto reset;
+ }
+ s = d->port->task&0xff;
+ if(s == 0x7f || ((d->port->sig>>16) != 0xeb14 &&
+ (s & ~0x17) != (1<<6)))
+ break;
+ iunlock(d);
+ newdrive(d);
+ ilock(d);
+ break;
+ }
+ break;
+ case Doffline:
+ if(d->wait++ & Mcomrwait)
+ break;
+ case Derror:
+ case Dreset:
+ dprint("%s: reset [%s]: mode %d; status %#ux\n",
+ name, diskstates[d->state], d->mode, s);
+ iunlock(d);
+ resetdisk(d);
+ ilock(d);
+ break;
+ case Dportreset:
+portreset:
+ if(d->wait++ & 0xff && (s & 0x100) == 0)
+ break;
+ dprint("%s: portreset [%s]: mode %d; status %04ux\n",
+ name, diskstates[d->state], d->mode, s);
+ d->portm.flag |= Ferror;
+ clearci(d->port);
+ if((s & 7) == 0){
+ d->state = Dmissing;
+ break;
+ }
+ iunlock(d);
+ doportreset(d);
+ ilock(d);
+ break;
+ }
+ iunlock(d);
+}
+
+static void
+iainterrupt(Ureg*, void *a)
+{
+ int i;
+ ulong cause, m;
+ Ctlr *c;
+ Drive *d;
+
+ c = a;
+ ilock(c);
+ /* check drive here! */
+ cause = c->hba->isr;
+ for(i = 0; i < c->ndrive; i++){
+ m = 1 << i;
+ if((cause & m) == 0)
+ continue;
+ d = c->rawdrive + i;
+ ilock(d);
+ if(d->port->isr && c->hba->pi & m)
+ updatedrive(d);
+ c->hba->isr = m;
+ iunlock(d);
+ }
+ iunlock(c);
+}
+
+static int
+iaverify(SDunit *u)
+{
+ int i;
+ Ctlr *c;
+ Drive *d;
+
+ c = u->dev->ctlr;
+ d = c->drive[u->subno];
+ ilock(c);
+ ilock(d);
+ d->unit = u;
+ iunlock(d);
+ iunlock(c);
+ for(i = 0; i < 10; i++){
+ checkdrive(d, d->driveno);
+ switch(d->state){
+ case Dmissing:
+ if(i < 4 || d->port->sstatus & 0x733)
+ break;
+ /* fall through */
+ case Dnull:
+ case Dready:
+ case Doffline:
+ print("sdiahci: drive %d in state %s after %d resets\n",
+ d->driveno, diskstates[d->state], i);
+ return 1;
+ }
+ delay(100);
+ }
+ print("sdiahci: drive %d won't come up; in state %s after %d resets\n",
+ d->driveno, diskstates[d->state], i);
+ return 1;
+}
+
+static int
+iaenable(SDev *s)
+{
+ Ctlr *c;
+
+ c = s->ctlr;
+ ilock(c);
+ if(!c->enabled) {
+ if(c->ndrive == 0)
+ panic("iaenable: zero s->ctlr->ndrive");
+ pcisetbme(c->pci);
+ setvec(c->pci->intl+VectorPIC, iainterrupt, c);
+ /* supposed to squelch leftover interrupts here. */
+ ahcienable(c->hba);
+ c->enabled = 1;
+ }
+ iunlock(c);
+ return 1;
+}
+
+static int
+iadisable(SDev *s)
+{
+ Ctlr *c;
+
+ c = s->ctlr;
+ ilock(c);
+ ahcidisable(c->hba);
+// intrdisable(c->irq, iainterrupt, c, c->tbdf, name);
+ c->enabled = 0;
+ iunlock(c);
+ return 1;
+}
+
+static int
+iaonline(SDunit *unit)
+{
+ int r;
+ Ctlr *c;
+ Drive *d;
+
+ c = unit->dev->ctlr;
+ d = c->drive[unit->subno];
+ r = 0;
+
+ if(d->portm.feat & Datapi && d->mediachange){
+ r = scsionline(unit);
+ if(r > 0)
+ d->mediachange = 0;
+ return r;
+ }
+
+ ilock(d);
+ if(d->mediachange){
+ r = 2;
+ d->mediachange = 0;
+ /* devsd resets this after online is called; why? */
+ unit->sectors = d->sectors;
+ unit->secsize = 512;
+ } else if(d->state == Dready)
+ r = 1;
+ iunlock(d);
+ return r;
+}
+
+/* returns locked list! */
+static Alist*
+ahcibuild(Aportm *m, uchar *cmd, void *data, int n, vlong lba)
+{
+ uchar *c, acmd, dir, llba;
+ Alist *l;
+ Actab *t;
+ Aprdt *p;
+ static uchar tab[2][2] = { 0xc8, 0x25, 0xca, 0x35 };
+
+ dir = *cmd != 0x28;
+ llba = m->feat & Dllba? 1: 0;
+ acmd = tab[dir][llba];
+ qlock(m);
+ l = m->list;
+ t = m->ctab;
+ c = t->cfis;
+
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = acmd;
+ c[3] = 0;
+
+ c[4] = lba; /* sector lba low 7:0 */
+ c[5] = lba >> 8; /* cylinder low lba mid 15:8 */
+ c[6] = lba >> 16; /* cylinder hi lba hi 23:16 */
+ c[7] = 0xa0 | 0x40; /* obsolete device bits + lba */
+ if(llba == 0)
+ c[7] |= (lba>>24) & 7;
+
+ c[8] = lba >> 24; /* sector (exp) lba 31:24 */
+ c[9] = lba >> 32; /* cylinder low (exp) lba 39:32 */
+ c[10] = lba >> 48; /* cylinder hi (exp) lba 48:40 */
+ c[11] = 0; /* features (exp); */
+
+ c[12] = n; /* sector count */
+ c[13] = n >> 8; /* sector count (exp) */
+ c[14] = 0; /* r */
+ c[15] = 0; /* control */
+
+ *(ulong*)(c+16) = 0;
+
+ l->flags = 1<<16 | Lpref | 0x5; /* Lpref ?? */
+ if(dir == Write)
+ l->flags |= Lwrite;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ p = &t->prdt;
+ p->dba = PCIWADDR(data);
+ p->dbahi = 0;
+ p->count = 1<<31 | (512*n - 2) | 1;
+
+ return l;
+}
+
+static Alist*
+ahcibuildpkt(Aportm *m, SDreq *r, void *data, int n)
+{
+ int fill, len;
+ uchar *c;
+ Actab *t;
+ Alist *l;
+ Aprdt *p;
+
+ qlock(m);
+ l = m->list;
+ t = m->ctab;
+ c = t->cfis;
+
+ fill = m->feat & Datapi16? 16: 12;
+ if((len = r->clen) > fill)
+ len = fill;
+ memmove(t->atapi, r->cmd, len);
+ memset(t->atapi + len, 0, fill - len);
+
+ c[0] = 0x27;
+ c[1] = 0x80;
+ c[2] = 0xa0;
+ if(n != 0)
+ c[3] = 1; /* dma */
+ else
+ c[3] = 0; /* features (exp); */
+
+ c[4] = 0; /* sector lba low 7:0 */
+ c[5] = n; /* cylinder low lba mid 15:8 */
+ c[6] = n >> 8; /* cylinder hi lba hi 23:16 */
+ c[7] = 0xa0; /* obsolete device bits */
+
+ *(ulong*)(c+8) = 0;
+ *(ulong*)(c+12) = 0;
+ *(ulong*)(c+16) = 0;
+
+ l->flags = 1<<16 | Lpref | Latapi | 0x5;
+ if(r->write != 0 && data)
+ l->flags |= Lwrite;
+ l->len = 0;
+ l->ctab = PCIWADDR(t);
+ l->ctabhi = 0;
+
+ if(data == 0)
+ return l;
+
+ p = &t->prdt;
+ p->dba = PCIWADDR(data);
+ p->dbahi = 0;
+ p->count = 1<<31 | (n - 2) | 1;
+
+ return l;
+}
+
+static int
+waitready(Drive *d)
+{
+ ulong s, t, i;
+
+ for(i = 0; i < 120; i++){
+ ilock(d);
+ s = d->port->sstatus;
+ t = d->port->task;
+ iunlock(d);
+ if((s & 0x100) == 0)
+ return -1;
+ if(d->state == Dready && (s & 7) == 3)
+ return 0;
+ if((i + 1) % 30 == 0)
+ print("%s: waitready: [%s] task=%lux sstat=%lux\n",
+ d->unit->name, diskstates[d->state], t, s);
+ esleep(1000);
+ }
+ print("%s: not responding; offline\n", d->unit->name);
+ ilock(d);
+ d->state = Doffline;
+ iunlock(d);
+ return -1;
+}
+
+static int
+iariopkt(SDreq *r, Drive *d)
+{
+ int n, count, try, max, flag, task;
+ char *name;
+ uchar *cmd, *data;
+ Aport *p;
+ Asleep as;
+
+ cmd = r->cmd;
+ name = d->unit->name;
+ p = d->port;
+
+ aprint("%02ux %02ux %c %d %p\n", cmd[0], cmd[2], "rw"[r->write],
+ r->dlen, r->data);
+// if(cmd[0] == 0x5a && (cmd[2] & 0x3f) == 0x3f)
+// return sdmodesense(r, cmd, d->info, sizeof d->info);
+ r->rlen = 0;
+ count = r->dlen;
+ max = 65536;
+
+ try = 0;
+retry:
+ if(waitready(d) == -1)
+ return SDeio;
+ data = r->data;
+ n = count;
+ if(n > max)
+ n = max;
+ d->active++;
+ ahcibuildpkt(&d->portm, r, data, n);
+ ilock(d);
+ d->portm.flag = 0;
+ iunlock(d);
+ p->ci = 1;
+
+ as.p = p;
+ as.i = 1;
+ d->intick = m->ticks;
+
+ while(ahciclear(&as) == 0)
+ ;
+
+ ilock(d);
+ flag = d->portm.flag;
+ task = d->port->task;
+ iunlock(d);
+
+ if(task & (Efatal<<8) || task & (ASbsy|ASdrq) && d->state == Dready){
+ d->port->ci = 0; /* @? */
+ ahcirecover(&d->portc);
+ task = d->port->task;
+ }
+ d->active--;
+ qunlock(&d->portm);
+ if(flag == 0){
+ if(++try == 10){
+ print("%s: bad disk\n", name);
+ r->status = SDcheck;
+ return SDcheck;
+ }
+ print("%s: retry\n", name);
+ esleep(1000);
+ goto retry;
+ }
+ if(flag & Ferror){
+ if((task & Eidnf) == 0)
+ print("%s: i/o error %ux\n", name, task);
+ r->status = SDcheck;
+ return SDcheck;
+ }
+
+ data += n;
+
+ r->rlen = data - (uchar*)r->data;
+ r->status = SDok;
+ return SDok;
+}
+
+static int
+iario(SDreq *r)
+{
+ int n, count, max, flag, task;
+ vlong lba;
+ char *name;
+ uchar *cmd, *data;
+ Aport *p;
+ Asleep as;
+ Ctlr *c;
+ Drive *d;
+ SDunit *unit;
+
+ unit = r->unit;
+ c = unit->dev->ctlr;
+ d = c->drive[unit->subno];
+ if(d->portm.feat & Datapi)
+ return iariopkt(r, d);
+ cmd = r->cmd;
+ name = d->unit->name;
+ p = d->port;
+
+// if((i = sdfakescsi(r, d->info, sizeof d->info)) != SDnostatus){
+// r->status = i;
+// return i;
+// }
+
+ if(*cmd != 0x28 && *cmd != 0x2a){
+ print("%s: bad cmd 0x%.2ux\n", name, cmd[0]);
+ r->status = SDcheck;
+ return SDcheck;
+ }
+
+ lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];
+ count = cmd[7]<<8 | cmd[8];
+ if(r->data == nil)
+ return SDok;
+ if(r->dlen < count * unit->secsize)
+ count = r->dlen / unit->secsize;
+ max = 128;
+
+ if(waitready(d) == -1)
+ return SDeio;
+ data = r->data;
+ while(count > 0){
+ n = count;
+ if(n > max)
+ n = max;
+ d->active++;
+ ahcibuild(&d->portm, cmd, data, n, lba);
+ ilock(d);
+ d->portm.flag = 0;
+ iunlock(d);
+ p->ci = 1;
+
+ as.p = p;
+ as.i = 1;
+ d->intick = m->ticks;
+
+ while(ahciclear(&as) == 0)
+ ;
+
+ ilock(d);
+ flag = d->portm.flag;
+ task = d->port->task;
+ iunlock(d);
+
+ if(task & (Efatal<<8) ||
+ task & (ASbsy|ASdrq) && d->state == Dready){
+ d->port->ci = 0; /* @? */
+ ahcirecover(&d->portc);
+ task = d->port->task;
+ }
+ d->active--;
+ qunlock(&d->portm);
+ if(flag == 0 || flag & Ferror){
+ print("%s: i/o error %ux @%lld\n", name, task, lba);
+ r->status = SDeio;
+ return SDeio;
+ }
+
+ count -= n;
+ lba += n;
+ data += n * unit->secsize;
+ }
+ r->rlen = data - (uchar*)r->data;
+ r->status = SDok;
+ return SDok;
+}
+
+/*
+ * configure drives 0-5 as ahci sata (c.f. errata)
+ */
+static int
+iaahcimode(Pcidev *p)
+{
+ dprint("iaahcimode %ux %ux %ux\n", pcicfgr8(p, 0x91),
+ pcicfgr8(p, 92), pcicfgr8(p, 93));
+ pcicfgw16(p, 0x92, pcicfgr32(p, 0x92) | 0xf); /* ports 0-3 */
+// pcicfgw8(p, 0x93, pcicfgr32(p, 9x93) | 3); /* ports 4-5 */
+ return 0;
+}
+
+static void
+iasetupahci(Ctlr *c)
+{
+ /* disable cmd block decoding. */
+ pcicfgw16(c->pci, 0x40, pcicfgr16(c->pci, 0x40) & ~(1<<15));
+ pcicfgw16(c->pci, 0x42, pcicfgr16(c->pci, 0x42) & ~(1<<15));
+
+ c->lmmio[0x4/4] |= 1 << 31; /* enable ahci mode (ghc register) */
+ c->lmmio[0xc/4] = (1<<6) - 1; /* five ports (supposedly ro pi reg) */
+
+ /* enable ahci mode; from ich9 datasheet */
+ pcicfgw8(c->pci, 0x90, 1<<6 | 1<<5);
+}
+
+static SDev*
+iapnp(void)
+{
+ int i, n, nunit, type;
+ ulong io;
+ Ctlr *c;
+ Drive *d;
+ Pcidev *p;
+ SDev *head, *tail, *s;
+ static int done;
+
+ if (done || getconf("*noahciload") != nil)
+ return nil;
+ done = 1;
+ p = nil;
+ head = tail = nil;
+loop:
+ while((p = pcimatch(p, 0, 0)) != nil){
+ if(p->vid == 0x8086 && (p->did & 0xfffc) == 0x2680)
+ type = Tesb;
+ else if(p->vid == 0x8086 && p->did == 0x27c5)
+ type = Tich; /* 82801g[bh]m; compat mode fails */
+ else if(p->vid == 0x8086 && (p->did & 0xfeff) == 0x2829)
+ type = Tich; /* ich8 */
+ else if(p->vid == 0x8086 && (p->did & 0xfffe) == 0x2922)
+ type = Tich; /* ich8 */
+ else if(p->vid == 0x1002 && p->did == 0x4380)
+ type = Tsb600;
+ else
+ continue;
+ if(niactlr == NCtlr){
+ print("iapnp: %s: too many controllers\n", tname[type]);
+ break;
+ }
+ c = iactlr + niactlr;
+ s = sdevs + niactlr;
+ memset(c, 0, sizeof *c);
+ memset(s, 0, sizeof *s);
+ c->pci = p;
+ c->type = type;
+ io = p->mem[Abar].bar & ~0xf;
+ io = upamalloc(io, p->mem[Abar].size, 0);
+ if(io == 0){
+ print("%s: address %#lux in use, did %#ux\n",
+ tname[c->type], io, p->did);
+ continue;
+ }
+ /* ugly hack: get this in compatibility mode; see memory.c:271 */
+ if(io == 0x40000000) {
+ print("%s: did %#ux is in non-sata mode. bar %#lux\n",
+ tname[c->type], p->did, p->mem[Abar].bar);
+ continue;
+ }
+ c->mmio = KADDR(io);
+ c->lmmio = (ulong*)c->mmio;
+ if(Intel(c->type) && p->did != 0x2681)
+ iasetupahci(c);
+ nunit = ahciconf(c);
+// ahcihbareset((Ahba*)c->mmio);
+ if(Intel(c->type) && iaahcimode(p) == -1)
+ break;
+ if(nunit < 1){
+// vunmap(c->mmio, p->mem[Abar].size);
+ continue;
+ }
+ niactlr++;
+ i = (c->hba->cap>>21) & 1;
+ print("%s: sata-%s with %d ports\n", tname[c->type],
+ "I\0II"+i*2, nunit);
+ s->ifc = &sdiahciifc;
+ s->ctlr = c;
+ s->nunit = nunit;
+ s->idno = 'E';
+ c->sdev = s;
+ c->ndrive = nunit;
+
+ /* map the drives -- they don't all need to be enabled. */
+ memset(c->rawdrive, 0, sizeof c->rawdrive);
+ n = 0;
+ for(i = 0; i < NCtlrdrv; i++) {
+ d = c->rawdrive+i;
+ d->portno = i;
+ d->driveno = -1;
+ d->sectors = 0;
+ d->ctlr = c;
+ if((c->hba->pi & (1<<i)) == 0)
+ continue;
+// d->state = Dnew;
+ d->port = (Aport*)(c->mmio + 0x80*i + 0x100);
+ d->portc.p = d->port;
+ d->portc.m = &d->portm;
+ d->driveno = n++;
+ c->drive[d->driveno] = d;
+ }
+ for(i = 0; i < n; i++)
+ if(ahciidle(c->drive[i]->port) == -1){
+ print("%s: port %d wedged; abort\n",
+ tname[c->type], i);
+ goto loop;
+ }
+ for(i = 0; i < n; i++){
+ c->drive[i]->mode = DMsatai;
+ configdrive(c->drive[i]);
+ }
+
+ if(head)
+ tail->next = s;
+ else
+ head = s;
+ tail = s;
+ }
+ return head;
+}
+
+static SDev*
+iaid(SDev* sdev)
+{
+ int i;
+ Ctlr *c;
+
+ for(; sdev; sdev = sdev->next){
+ if(sdev->ifc != &sdiahciifc)
+ continue;
+ c = sdev->ctlr;
+ for(i = 0; i < NCtlr; i++)
+ if(c == iactlr + i)
+ sdev->idno = 'E' + i;
+ }
+ return nil;
+}
+
+SDifc sdiahciifc = {
+ "iahci",
+
+ iapnp,
+ nil, /* legacy */
+ iaid,
+ iaenable,
+ iadisable,
+
+ iaverify,
+ iaonline,
+ iario,
+ nil,
+ nil,
+
+ scsibio,
+};
--- /dev/null
+++ b/os/boot.original/pc/sdmylex.c
@@ -1,0 +1,1292 @@
+/*
+ * Mylex MultiMaster (Buslogic BT-*) SCSI Host Adapter
+ * in both 24-bit and 32-bit mode.
+ * 24-bit mode works for Adaptec AHA-154xx series too.
+ *
+ * To do:
+ * allocate more Ccb's as needed, up to NMbox-1;
+ * add nmbox and nccb to Ctlr struct for the above;
+ * 64-bit LUN/explicit wide support necessary?
+ *
+ */
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "error.h"
+
+#include "sd.h"
+
+#define waserror() (0)
+#define poperror()
+typedef struct QLock{ int r; } QLock;
+typedef struct Rendez{ int r; } Rendez;
+#define intrenable(irq, f, c, tbdf, name) setvec(VectorPIC+(irq), f, c);\
+ USED(tbdf);
+
+#define K2BPA(va, tbdf) PADDR(va)
+#define BPA2K(pa, tbdf) KADDR(pa)
+
+extern SDifc sdmylexifc;
+
+enum { /* registers */
+ Rcontrol = 0x00, /* WO: control register */
+ Rstatus = 0x00, /* RO: status register */
+ Rcpr = 0x01, /* WO: command/parameter register */
+ Rdatain = 0x01, /* RO: data-in register */
+ Rinterrupt = 0x02, /* RO: interrupt register */
+};
+
+enum { /* Rcontrol */
+ Rsbus = 0x10, /* SCSI Bus Reset */
+ Rint = 0x20, /* Interrupt Reset */
+ Rsoft = 0x40, /* Soft Reset */
+ Rhard = 0x80, /* Hard Reset */
+};
+
+enum { /* Rstatus */
+ Cmdinv = 0x01, /* Command Invalid */
+ Dirrdy = 0x04, /* Data In Register Ready */
+ Cprbsy = 0x08, /* Command/Parameter Register Busy */
+ Hardy = 0x10, /* Host Adapter Ready */
+ Inreq = 0x20, /* Initialisation Required */
+ Dfail = 0x40, /* Diagnostic Failure */
+ Dact = 0x80, /* Diagnostic Active */
+};
+
+enum { /* Rcpr */
+ Cinitialise = 0x01, /* Initialise Mailbox */
+ Cstart = 0x02, /* Start Mailbox Command */
+ Cinquiry = 0x04, /* Adapter Inquiry */
+ Ceombri = 0x05, /* Enable OMBR Interrupt */
+ Cinquire = 0x0B, /* Inquire Configuration */
+ Cextbios = 0x28, /* AHA-1542: extended BIOS info. */
+ Cmbienable = 0x29, /* AHA-1542: Mailbox interface enable */
+ Ciem = 0x81, /* Initialise Extended Mailbox */
+ Ciesi = 0x8D, /* Inquire Extended Setup Information */
+ Cerrm = 0x8F, /* Enable strict round-robin mode */
+ Cwide = 0x96, /* Wide CCB */
+};
+
+enum { /* Rinterrupt */
+ Imbl = 0x01, /* Incoming Mailbox Loaded */
+ Mbor = 0x02, /* Mailbox Out Ready */
+ Cmdc = 0x04, /* Command Complete */
+ Rsts = 0x08, /* SCSI Reset State */
+ Intv = 0x80, /* Interrupt Valid */
+};
+
+typedef struct {
+ uchar code; /* action/completion code */
+ uchar ccb[3]; /* CCB pointer (MSB, ..., LSB) */
+} Mbox24;
+
+typedef struct {
+ uchar ccb[4]; /* CCB pointer (LSB, ..., MSB) */
+ uchar btstat; /* BT-7[45]7[SD] status */
+ uchar sdstat; /* SCSI device status */
+ uchar pad;
+ uchar code; /* action/completion code */
+} Mbox32;
+
+enum { /* mailbox commands */
+ Mbfree = 0x00, /* Mailbox not in use */
+
+ Mbostart = 0x01, /* Start a mailbox command */
+ Mboabort = 0x02, /* Abort a mailbox command */
+
+ Mbiok = 0x01, /* CCB completed without error */
+ Mbiabort = 0x02, /* CCB aborted at request of host */
+ Mbinx = 0x03, /* Aborted CCB not found */
+ Mbierror = 0x04, /* CCB completed with error */
+};
+
+typedef struct Ccb24 Ccb24;
+typedef struct Ccb32 Ccb32;
+typedef union Ccb Ccb;
+
+typedef struct Ccb24 {
+ uchar opcode; /* Operation code */
+ uchar datadir; /* Data direction control */
+ uchar cdblen; /* Length of CDB */
+ uchar senselen; /* Length of sense area */
+ uchar datalen[3]; /* Data length (MSB, ..., LSB) */
+ uchar dataptr[3]; /* Data pointer (MSB, ..., LSB) */
+ uchar linkptr[3]; /* Link pointer (MSB, ..., LSB) */
+ uchar linkid; /* command linking identifier */
+ uchar btstat; /* BT-* adapter status */
+ uchar sdstat; /* SCSI device status */
+ uchar reserved[2]; /* */
+ uchar cs[12+0xFF]; /* Command descriptor block + Sense */
+
+ void* data; /* buffer if address > 24-bits */
+
+ Rendez;
+ int done; /* command completed */
+
+ Ccb* ccb; /* link on free list */
+} Ccb24;
+
+
+typedef struct Ccb32 {
+ uchar opcode; /* Operation code */
+ uchar datadir; /* Data direction control */
+ uchar cdblen; /* Length of CDB */
+ uchar senselen; /* Length of sense area */
+ uchar datalen[4]; /* Data length (LSB, ..., MSB) */
+ uchar dataptr[4]; /* Data pointer (LSB, ..., MSB) */
+ uchar reserved[2];
+ uchar btstat; /* BT-* adapter status */
+ uchar sdstat; /* SCSI device status */
+ uchar targetid; /* Target ID */
+ uchar luntag; /* LUN & tag */
+ uchar cdb[12]; /* Command descriptor block */
+ uchar ccbctl; /* CCB control */
+ uchar linkid; /* command linking identifier */
+ uchar linkptr[4]; /* Link pointer (LSB, ..., MSB) */
+ uchar senseptr[4]; /* Sense pointer (LSB, ..., MSB) */
+ uchar sense[0xFF]; /* Sense bytes */
+
+ Rendez;
+ int done; /* command completed */
+
+ Ccb* ccb; /* link on free list */
+} Ccb32;
+
+typedef union Ccb {
+ Ccb24;
+ Ccb32;
+} Ccb;
+
+enum { /* opcode */
+ OInitiator = 0x00, /* initiator CCB */
+ Ordl = 0x03, /* initiator CCB with
+ * residual data length returned
+ */
+};
+
+enum { /* datadir */
+ CCBdatain = 0x08, /* inbound, length is checked */
+ CCBdataout = 0x10, /* outbound, length is checked */
+};
+
+enum { /* btstat */
+ Eok = 0x00, /* normal completion with no errors */
+};
+
+enum { /* luntag */
+ TagEnable = 0x20, /* Tag enable */
+ SQTag = 0x00, /* Simple Queue Tag */
+ HQTag = 0x40, /* Head of Queue Tag */
+ OQTag = 0x80, /* Ordered Queue Tag */
+};
+
+enum { /* CCB control */
+ NoDisc = 0x08, /* No disconnect */
+ NoUnd = 0x10, /* No underrrun error report */
+ NoData = 0x20, /* No data transfer */
+ NoStat = 0x40, /* No CCB status if zero */
+ NoIntr = 0x80, /* No Interrupts */
+};
+
+typedef struct {
+ int port; /* I/O port */
+ int id; /* adapter SCSI id */
+ int bus; /* 24 or 32 -bit */
+ int irq;
+ int wide;
+ Pcidev* pcidev;
+ SDev* sdev;
+ int spurious;
+
+ Lock issuelock;
+
+ Lock ccblock;
+ QLock ccbq;
+ Rendez ccbr;
+
+ Lock mboxlock;
+ void* mb; /* mailbox out + mailbox in */
+ int mbox; /* current mailbox out index into mb */
+ int mbix; /* current mailbox in index into mb */
+
+ Lock cachelock;
+ Ccb* ccb; /* list of free Ccb's */
+ Ccb** cache; /* last completed Ccb */
+} Ctlr;
+
+/*
+ * The number of mailboxes should be a multiple of 8 (4 for Mbox32)
+ * to ensure the boundary between the out and in mailboxes doesn't
+ * straddle a cache-line boundary.
+ * The number of Ccb's should be less than the number of mailboxes to
+ * ensure no queueing is necessary on mailbox allocation.
+ */
+enum {
+ NMbox = 8*8, /* number of Mbox's */
+ NCcb = NMbox-1, /* number of Ccb's */
+};
+
+#define PADDR24(a, n) ((PADDR(a)+(n)) <= (1<<24))
+
+static void
+ccbfree(Ctlr* ctlr, Ccb* ccb)
+{
+ lock(&ctlr->ccblock);
+ if(ctlr->bus == 24)
+ ((Ccb24*)ccb)->ccb = ctlr->ccb;
+ else
+ ((Ccb32*)ccb)->ccb = ctlr->ccb;
+ if(ctlr->ccb == nil)
+ wakeup(&ctlr->ccbr);
+ ctlr->ccb = ccb;
+ unlock(&ctlr->ccblock);
+}
+
+static int
+ccbavailable(void* a)
+{
+ return ((Ctlr*)a)->ccb != nil;
+}
+
+static Ccb*
+ccballoc(Ctlr* ctlr)
+{
+ Ccb *ccb;
+
+ for(;;){
+ lock(&ctlr->ccblock);
+ if((ccb = ctlr->ccb) != nil){
+ if(ctlr->bus == 24)
+ ctlr->ccb = ((Ccb24*)ccb)->ccb;
+ else
+ ctlr->ccb = ((Ccb32*)ccb)->ccb;
+ unlock(&ctlr->ccblock);
+ break;
+ }
+
+ unlock(&ctlr->ccblock);
+ qlock(&ctlr->ccbq);
+ if(waserror()){
+ qunlock(&ctlr->ccbq);
+ continue;
+ }
+ sleep(&ctlr->ccbr, ccbavailable, ctlr);
+ qunlock(&ctlr->ccbq);
+ poperror();
+ }
+
+ return ccb;
+}
+
+static int
+done24(void* arg)
+{
+ return ((Ccb24*)arg)->done;
+}
+
+static int
+mylex24rio(SDreq* r)
+{
+ ulong p;
+ Ctlr *ctlr;
+ Ccb24 *ccb;
+ Mbox24 *mb;
+ uchar *data, lun, *sense;
+ int d, n, btstat, sdstat, target;
+
+ ctlr = r->unit->dev->ctlr;
+ target = r->unit->subno;
+ lun = (r->cmd[1]>>5) & 0x07;
+
+ /*
+ * Ctlr->cache holds the last completed Ccb for this target if it
+ * returned 'check condition'.
+ * If this command is a request-sense and there is valid sense data
+ * from the last completed Ccb, return it immediately.
+ */
+ lock(&ctlr->cachelock);
+ if((ccb = ctlr->cache[target]) != nil){
+ ctlr->cache[target] = nil;
+ if(r->cmd[0] == 0x03
+ && ccb->sdstat == SDcheck && lun == ((ccb->cs[1]>>5) & 0x07)){
+ unlock(&ctlr->cachelock);
+ if(r->dlen){
+ sense = &ccb->cs[ccb->cdblen];
+ n = 8+sense[7];
+ if(n > r->dlen)
+ n = r->dlen;
+ memmove(r->data, sense, n);
+ r->rlen = n;
+ }
+ ccbfree(ctlr, (Ccb*)ccb);
+ return SDok;
+ }
+ }
+ unlock(&ctlr->cachelock);
+ if(ccb == nil)
+ ccb = ccballoc(ctlr);
+
+ /*
+ * Check if the transfer is to memory above the 24-bit limit the
+ * controller can address. If it is, try to allocate a temporary
+ * buffer as a staging area.
+ */
+ n = r->dlen;
+ if(n && !PADDR24(r->data, n)){
+ data = mallocz(n, 0);
+ if(data == nil || !PADDR24(data, n)){
+ if(data != nil){
+ free(data);
+ ccb->data = nil;
+ }
+ ccbfree(ctlr, (Ccb*)ccb);
+ return SDmalloc;
+ }
+ if(r->write)
+ memmove(data, r->data, n);
+ ccb->data = r->data;
+ }
+ else
+ data = r->data;
+
+ /*
+ * Fill in the ccb.
+ */
+ ccb->opcode = Ordl;
+
+ ccb->datadir = (target<<5)|lun;
+ if(n == 0)
+ ccb->datadir |= CCBdataout|CCBdatain;
+ else if(!r->write)
+ ccb->datadir |= CCBdatain;
+ else
+ ccb->datadir |= CCBdataout;
+
+ ccb->cdblen = r->clen;
+ ccb->senselen = 0xFF;
+
+ ccb->datalen[0] = n>>16;
+ ccb->datalen[1] = n>>8;
+ ccb->datalen[2] = n;
+ p = PADDR(data);
+ ccb->dataptr[0] = p>>16;
+ ccb->dataptr[1] = p>>8;
+ ccb->dataptr[2] = p;
+
+ ccb->linkptr[0] = ccb->linkptr[1] = ccb->linkptr[2] = 0;
+ ccb->linkid = 0;
+ ccb->btstat = ccb->sdstat = 0;
+ ccb->reserved[0] = ccb->reserved[1] = 0;
+
+ memmove(ccb->cs, r->cmd, r->clen);
+
+ /*
+ * There's one more mbox than there there is
+ * ccb so there is always one free.
+ */
+ lock(&ctlr->mboxlock);
+ mb = ctlr->mb;
+ mb += ctlr->mbox;
+ p = PADDR(ccb);
+ mb->ccb[0] = p>>16;
+ mb->ccb[1] = p>>8;
+ mb->ccb[2] = p;
+ mb->code = Mbostart;
+ ctlr->mbox++;
+ if(ctlr->mbox >= NMbox)
+ ctlr->mbox = 0;
+
+ /*
+ * This command does not require Hardy
+ * and doesn't generate a Cmdc interrupt.
+ */
+ ccb->done = 0;
+ outb(ctlr->port+Rcpr, Cstart);
+ unlock(&ctlr->mboxlock);
+
+ /*
+ * Wait for the request to complete and return the status.
+ * Since the buffer is not reference counted cannot return
+ * until the DMA is done writing into the buffer so the caller
+ * cannot free the buffer prematurely.
+ */
+ while(waserror())
+ ;
+ tsleep(ccb, done24, ccb, 30*1000);
+ poperror();
+
+ if(!done24(ccb)){
+ print("%s: %d/%d: sd24rio timeout\n",
+ "sdmylex"/*ctlr->sdev->name*/, target, r->lun);
+ if(ccb->data != nil){
+ free(data);
+ ccb->data = nil;
+ }
+ ccbfree(ctlr, (Ccb*)ccb);
+
+ return SDtimeout;
+ }
+
+ /*
+ * Save the status and patch up the number of
+ * bytes actually transferred.
+ * There's a firmware bug on some 956C controllers
+ * which causes the return count from a successful
+ * READ CAPACITY not be updated, so fix it here.
+ */
+ sdstat = ccb->sdstat;
+ btstat = ccb->btstat;
+
+ d = ccb->datalen[0]<<16;
+ d |= ccb->datalen[1]<<8;
+ d |= ccb->datalen[2];
+ if(ccb->cs[0] == 0x25 && sdstat == SDok)
+ d = 0;
+ n -= d;
+ r->rlen = n;
+
+ /*
+ * Tidy things up if a staging area was used for the data,
+ */
+ if(ccb->data != nil){
+ if(sdstat == SDok && btstat == 0 && !r->write)
+ memmove(ccb->data, data, n);
+ free(data);
+ ccb->data = nil;
+ }
+
+ /*
+ * If there was a check-condition, save the
+ * ccb for a possible request-sense command.
+ */
+ if(sdstat == SDcheck){
+ if(r->flags & SDnosense){
+ lock(&ctlr->cachelock);
+ if(ctlr->cache[target])
+ ccbfree(ctlr, ctlr->cache[target]);
+ ctlr->cache[target] = (Ccb*)ccb;
+ unlock(&ctlr->cachelock);
+ return SDcheck;
+ }
+ sense = &ccb->cs[ccb->cdblen];
+ n = 8+sense[7];
+ if(n > sizeof(r->sense)-1)
+ n = sizeof(r->sense)-1;
+ memmove(r->sense, sense, n);
+ r->flags |= SDvalidsense;
+ }
+ ccbfree(ctlr, (Ccb*)ccb);
+
+ if(btstat){
+ if(btstat == 0x11)
+ return SDtimeout;
+ return SDeio;
+ }
+ return sdstat;
+}
+
+static void
+mylex24interrupt(Ureg*, void* arg)
+{
+ ulong pa;
+ Ctlr *ctlr;
+ Ccb24 *ccb;
+ Mbox24 *mb, *mbox;
+ int port, rinterrupt, rstatus;
+
+ ctlr = arg;
+ port = ctlr->port;
+
+ /*
+ * Save and clear the interrupt(s). The only
+ * interrupts expected are Cmdc, which is ignored,
+ * and Imbl which means something completed.
+ * There's one spurious interrupt left over from
+ * initialisation, ignore it.
+ */
+ rinterrupt = inb(port+Rinterrupt);
+ rstatus = inb(port+Rstatus);
+ outb(port+Rcontrol, Rint);
+ if((rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
+ print("%s: interrupt 0x%2.2ux\n",
+ "sdmylex"/*ctlr->sdev->name*/, rinterrupt);
+ if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
+ print("%s: command invalid\n", "sdmylex"/*ctlr->sdev->name*/);
+
+ /*
+ * Look for something in the mail.
+ * If there is, save the status, free the mailbox
+ * and wakeup whoever.
+ */
+ mb = ctlr->mb;
+ for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
+ pa = (mbox->ccb[0]<<16)|(mbox->ccb[1]<<8)|mbox->ccb[2];
+ ccb = BPA2K(pa, BUSUNKNOWN);
+ mbox->code = 0;
+ ccb->done = 1;
+ wakeup(ccb);
+
+ ctlr->mbix++;
+ if(ctlr->mbix >= NMbox+NMbox)
+ ctlr->mbix = NMbox;
+ }
+}
+
+static int
+done32(void* arg)
+{
+ return ((Ccb32*)arg)->done;
+}
+
+static int
+mylex32rio(SDreq* r)
+{
+ ulong p;
+ uchar lun;
+ Ctlr *ctlr;
+ Ccb32 *ccb;
+ Mbox32 *mb;
+ int d, n, btstat, sdstat, target;
+
+ ctlr = r->unit->dev->ctlr;
+ target = r->unit->subno;
+ lun = (r->cmd[1]>>5) & 0x07;
+
+ /*
+ * Ctlr->cache holds the last completed Ccb for this target if it
+ * returned 'check condition'.
+ * If this command is a request-sense and there is valid sense data
+ * from the last completed Ccb, return it immediately.
+ */
+ lock(&ctlr->cachelock);
+ if((ccb = ctlr->cache[target]) != nil){
+ ctlr->cache[target] = nil;
+ if(r->cmd[0] == 0x03
+ && ccb->sdstat == SDcheck && lun == (ccb->luntag & 0x07)){
+ unlock(&ctlr->cachelock);
+ if(r->dlen){
+ n = 8+ccb->sense[7];
+ if(n > r->dlen)
+ n = r->dlen;
+ memmove(r->data, ccb->sense, n);
+ r->rlen = n;
+ }
+ ccbfree(ctlr, (Ccb*)ccb);
+ return SDok;
+ }
+ }
+ unlock(&ctlr->cachelock);
+ if(ccb == nil)
+ ccb = ccballoc(ctlr);
+
+ /*
+ * Fill in the ccb.
+ */
+ ccb->opcode = Ordl;
+
+ n = r->dlen;
+ if(n == 0)
+ ccb->datadir = CCBdataout|CCBdatain;
+ else if(!r->write)
+ ccb->datadir = CCBdatain;
+ else
+ ccb->datadir = CCBdataout;
+
+ ccb->cdblen = r->clen;
+
+ ccb->datalen[0] = n;
+ ccb->datalen[1] = n>>8;
+ ccb->datalen[2] = n>>16;
+ ccb->datalen[3] = n>>24;
+ p = PADDR(r->data);
+ ccb->dataptr[0] = p;
+ ccb->dataptr[1] = p>>8;
+ ccb->dataptr[2] = p>>16;
+ ccb->dataptr[3] = p>>24;
+
+ ccb->targetid = target;
+ ccb->luntag = lun;
+ if(r->unit->inquiry[7] & 0x02)
+ ccb->luntag |= SQTag|TagEnable;
+ memmove(ccb->cdb, r->cmd, r->clen);
+ ccb->btstat = ccb->sdstat = 0;
+ ccb->ccbctl = 0;
+
+ /*
+ * There's one more mbox than there there is
+ * ccb so there is always one free.
+ */
+ lock(&ctlr->mboxlock);
+ mb = ctlr->mb;
+ mb += ctlr->mbox;
+ p = PADDR(ccb);
+ mb->ccb[0] = p;
+ mb->ccb[1] = p>>8;
+ mb->ccb[2] = p>>16;
+ mb->ccb[3] = p>>24;
+ mb->code = Mbostart;
+ ctlr->mbox++;
+ if(ctlr->mbox >= NMbox)
+ ctlr->mbox = 0;
+
+ /*
+ * This command does not require Hardy
+ * and doesn't generate a Cmdc interrupt.
+ */
+ ccb->done = 0;
+ outb(ctlr->port+Rcpr, Cstart);
+ unlock(&ctlr->mboxlock);
+
+ /*
+ * Wait for the request to complete and return the status.
+ * Since the buffer is not reference counted cannot return
+ * until the DMA is done writing into the buffer so the caller
+ * cannot free the buffer prematurely.
+ */
+ while(waserror())
+ ;
+ tsleep(ccb, done32, ccb, 30*1000);
+ poperror();
+
+ if(!done32(ccb)){
+ print("%s: %d/%d: sd32rio timeout\n",
+ "sdmylex"/*ctlr->sdev->name*/, target, r->lun);
+ ccbfree(ctlr, (Ccb*)ccb);
+
+ return SDtimeout;
+ }
+
+ /*
+ * Save the status and patch up the number of
+ * bytes actually transferred.
+ * There's a firmware bug on some 956C controllers
+ * which causes the return count from a successful
+ * READ CAPACITY not to be updated, so fix it here.
+ */
+ sdstat = ccb->sdstat;
+ btstat = ccb->btstat;
+
+ d = ccb->datalen[0];
+ d |= (ccb->datalen[1]<<8);
+ d |= (ccb->datalen[2]<<16);
+ d |= (ccb->datalen[3]<<24);
+ if(ccb->cdb[0] == 0x25 && sdstat == SDok)
+ d = 0;
+ n -= d;
+ r->rlen = n;
+
+ /*
+ * If there was a check-condition, save the
+ * ccb for a possible request-sense command.
+ */
+ if(sdstat == SDcheck){
+ if(r->flags & SDnosense){
+ lock(&ctlr->cachelock);
+ if(ctlr->cache[target])
+ ccbfree(ctlr, ctlr->cache[target]);
+ ctlr->cache[target] = (Ccb*)ccb;
+ unlock(&ctlr->cachelock);
+ return SDcheck;
+ }
+ n = 8+ccb->sense[7];
+ if(n > sizeof(r->sense)-1)
+ n = sizeof(r->sense)-1;
+ memmove(r->sense, ccb->sense, n);
+ r->flags |= SDvalidsense;
+ }
+ ccbfree(ctlr, (Ccb*)ccb);
+
+ if(btstat){
+ if(btstat == 0x11)
+ return SDtimeout;
+ return SDeio;
+ }
+ return sdstat;
+}
+
+static void
+mylex32interrupt(Ureg*, void* arg)
+{
+ ulong pa;
+ Ctlr *ctlr;
+ Ccb32 *ccb;
+ Mbox32 *mb, *mbox;
+ int port, rinterrupt, rstatus;
+
+ ctlr = arg;
+ port = ctlr->port;
+
+ /*
+ * Save and clear the interrupt(s). The only
+ * interrupts expected are Cmdc, which is ignored,
+ * and Imbl which means something completed.
+ * There's one spurious interrupt left over from
+ * initialisation, ignore it.
+ */
+ rinterrupt = inb(port+Rinterrupt);
+ rstatus = inb(port+Rstatus);
+ outb(port+Rcontrol, Rint);
+ if((rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
+ print("%s: interrupt 0x%2.2ux\n",
+ "sdmylex"/*ctlr->sdev->name*/, rinterrupt);
+ if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
+ print("%s: command invalid\n", "sdmylex"/*ctlr->sdev->name*/);
+
+ /*
+ * Look for something in the mail.
+ * If there is, free the mailbox and wakeup whoever.
+ */
+ mb = ctlr->mb;
+ for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
+ pa = (mbox->ccb[3]<<24)
+ |(mbox->ccb[2]<<16)
+ |(mbox->ccb[1]<<8)
+ |mbox->ccb[0];
+ if(ctlr->pcidev)
+ ccb = BPA2K(pa, ctlr->pcidev->tbdf);
+ else
+ ccb = BPA2K(pa, BUSUNKNOWN);
+ mbox->code = 0;
+ ccb->done = 1;
+ wakeup(ccb);
+
+ ctlr->mbix++;
+ if(ctlr->mbix >= NMbox+NMbox)
+ ctlr->mbix = NMbox;
+ }
+}
+
+static int
+mylexrio(SDreq* r)
+{
+ int subno;
+ Ctlr *ctlr;
+
+ subno = r->unit->subno;
+ ctlr = r->unit->dev->ctlr;
+ if(subno == ctlr->id || (!ctlr->wide && subno >= 8))
+ r->status = SDtimeout;
+ else if(ctlr->bus == 24)
+ r->status = mylex24rio(r);
+ else
+ r->status = mylex32rio(r);
+ return r->status;
+}
+
+/*
+ * Issue a command to a controller. The command and its length is
+ * contained in cmd and cmdlen. If any data is to be
+ * returned, datalen should be non-zero, and the returned data
+ * will be placed in data.
+ * If Cmdc is set, bail out, the invalid command will be handled
+ * when the interrupt is processed.
+ */
+static void
+issueio(int port, uchar* cmd, int cmdlen, uchar* data, int datalen)
+{
+ int len;
+
+ if(cmd[0] != Cstart && cmd[0] != Ceombri){
+ while(!(inb(port+Rstatus) & Hardy))
+ ;
+ }
+ outb(port+Rcpr, cmd[0]);
+
+ len = 1;
+ while(len < cmdlen){
+ if(!(inb(port+Rstatus) & Cprbsy)){
+ outb(port+Rcpr, cmd[len]);
+ len++;
+ }
+ if(inb(port+Rinterrupt) & Cmdc)
+ return;
+ }
+
+ if(datalen){
+ len = 0;
+ while(len < datalen){
+ if(inb(port+Rstatus) & Dirrdy){
+ data[len] = inb(port+Rdatain);
+ len++;
+ }
+ if(inb(port+Rinterrupt) & Cmdc)
+ return;
+ }
+ }
+}
+
+/*
+ * Issue a command to a controller, wait for it to complete then
+ * try to reset the interrupt. Should only be called at initialisation.
+ */
+static int
+issue(Ctlr* ctlr, uchar* cmd, int cmdlen, uchar* data, int datalen)
+{
+ int port;
+ uchar rinterrupt, rstatus;
+ static Lock mylexissuelock;
+
+ port = ctlr->port;
+
+ ilock(&ctlr->issuelock);
+ issueio(port, cmd, cmdlen, data, datalen);
+
+ while(!((rinterrupt = inb(port+Rinterrupt)) & Cmdc))
+ ;
+
+ rstatus = inb(port+Rstatus);
+ outb(port+Rcontrol, Rint);
+ iunlock(&ctlr->issuelock);
+
+ if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
+ return 0;
+ return 1;
+}
+
+static SDev*
+mylexprobe(int port, int irq)
+{
+ SDev *sdev;
+ Ctlr *ctlr;
+ uchar cmd[6], data[256];
+ int clen, dlen, timeo;
+
+ if(ioalloc(port, 0x3, 0, "mylex") < 0)
+ return nil;
+ ctlr = nil;
+
+ /*
+ * Attempt to hard-reset the board and reset
+ * the SCSI bus. If the board state doesn't settle to
+ * idle with mailbox initialisation required, either
+ * it isn't a compatible board or it's broken.
+ * If the controller has SCAM set this can take a while.
+ */
+ if(getconf("*noscsireset") != nil)
+ outb(port+Rcontrol, Rhard);
+ else
+ outb(port+Rcontrol, Rhard|Rsbus);
+ for(timeo = 0; timeo < 100; timeo++){
+ if(inb(port+Rstatus) == (Inreq|Hardy))
+ break;
+ delay(100);
+ }
+ if(inb(port+Rstatus) != (Inreq|Hardy)){
+buggery:
+ if(ctlr != nil)
+ free(ctlr);
+ iofree(port);
+ return nil;
+ }
+
+ if((ctlr = malloc(sizeof(Ctlr))) == nil)
+ goto buggery;
+ ctlr->port = port;
+ ctlr->irq = irq;
+ ctlr->bus = 24;
+ ctlr->wide = 0;
+
+ /*
+ * Try to determine if this is a 32-bit MultiMaster controller
+ * by attempting to obtain the extended inquiry information;
+ * this command is not implemented on Adaptec 154xx
+ * controllers. If successful, the first byte of the returned
+ * data is the host adapter bus type, 'E' for 32-bit EISA,
+ * PCI and VLB buses.
+ */
+ cmd[0] = Ciesi;
+ cmd[1] = 14;
+ clen = 2;
+ dlen = 256;
+ if(issue(ctlr, cmd, clen, data, dlen)){
+ if(data[0] == 'E')
+ ctlr->bus = 32;
+ ctlr->wide = data[0x0D] & 0x01;
+ }
+ else{
+ /*
+ * Inconceivable though it may seem, a hard controller reset
+ * is necessary here to clear out the command queue. Every
+ * board seems to lock-up in a different way if you give an
+ * invalid command and then try to clear out the
+ * command/parameter and/or data-in register.
+ * Soft reset doesn't do the job either. Fortunately no
+ * serious initialisation has been done yet so there's nothing
+ * to tidy up.
+ */
+ outb(port+Rcontrol, Rhard);
+ for(timeo = 0; timeo < 100; timeo++){
+ if(inb(port+Rstatus) == (Inreq|Hardy))
+ break;
+ delay(100);
+ }
+ if(inb(port+Rstatus) != (Inreq|Hardy))
+ goto buggery;
+ }
+
+ /*
+ * If the BIOS is enabled on the AHA-1542C/CF and BIOS options for
+ * support of drives > 1Gb, dynamic scanning of the SCSI bus or more
+ * than 2 drives under DOS 5.0 are enabled, the BIOS disables
+ * accepting Cmbinit to protect against running with drivers which
+ * don't support those options. In order to unlock the interface it
+ * is necessary to read a lock-code using Cextbios and write it back
+ * using Cmbienable; the lock-code is non-zero.
+ */
+ cmd[0] = Cinquiry;
+ clen = 1;
+ dlen = 4;
+ if(issue(ctlr, cmd, clen, data, dlen) == 0)
+ goto buggery;
+ if(data[0] >= 0x43){
+ cmd[0] = Cextbios;
+ clen = 1;
+ dlen = 2;
+ if(issue(ctlr, cmd, clen, data, dlen) == 0)
+ goto buggery;
+
+ /*
+ * Lock-code returned in data[1]. If it's non-zero write
+ * it back along with bit 0 of byte 0 cleared to enable
+ * mailbox initialisation.
+ */
+ if(data[1]){
+ cmd[0] = Cmbienable;
+ cmd[1] = 0;
+ cmd[2] = data[1];
+ clen = 3;
+ if(issue(ctlr, cmd, clen, 0, 0) == 0)
+ goto buggery;
+ }
+ }
+
+ /*
+ * Get the id, DMA and IRQ info from the board. This will
+ * cause an interrupt which will hopefully not cause any
+ * trouble because the interrupt number isn't known yet.
+ * This is necessary as the DMA won't be set up if the
+ * board has the BIOS disabled.
+ *
+ * If the IRQ is already known, this must be a 32-bit PCI
+ * or EISA card, in which case the returned DMA and IRQ can
+ * be ignored.
+ */
+ cmd[0] = Cinquire;
+ clen = 1;
+ dlen = 3;
+ if(issue(ctlr, cmd, clen, data, dlen) == 0)
+ goto buggery;
+
+ ctlr->id = data[2] & 0x07;
+ if(ctlr->irq < 0){
+ switch(data[0]){ /* DMA Arbitration Priority */
+ case 0x80: /* Channel 7 */
+ outb(0xD6, 0xC3);
+ outb(0xD4, 0x03);
+ break;
+ case 0x40: /* Channel 6 */
+ outb(0xD6, 0xC2);
+ outb(0xD4, 0x02);
+ break;
+ case 0x20: /* Channel 5 */
+ outb(0xD6, 0xC1);
+ outb(0xD4, 0x01);
+ break;
+ case 0x01: /* Channel 0 */
+ outb(0x0B, 0xC0);
+ outb(0x0A, 0x00);
+ break;
+ default:
+ if(ctlr->bus == 24)
+ goto buggery;
+ break;
+ }
+
+ switch(data[1]){ /* Interrupt Channel */
+ case 0x40:
+ ctlr->irq = 15;
+ break;
+ case 0x20:
+ ctlr->irq = 14;
+ break;
+ case 0x08:
+ ctlr->irq = 12;
+ break;
+ case 0x04:
+ ctlr->irq = 11;
+ break;
+ case 0x02:
+ ctlr->irq = 10;
+ break;
+ case 0x01:
+ ctlr->irq = 9;
+ break;
+ default:
+ goto buggery;
+ }
+ }
+
+ if((sdev = malloc(sizeof(SDev))) == nil)
+ goto buggery;
+ sdev->ifc = &sdmylexifc;
+ sdev->ctlr = ctlr;
+ ctlr->sdev = sdev;
+ if(!ctlr->wide)
+ sdev->nunit = 8;
+ else
+ sdev->nunit = 16;
+
+ return sdev;
+}
+
+static int mylexport[8] = {
+ 0x330, 0x334, 0x230, 0x234, 0x130, 0x134, 0x000, 0x000,
+};
+
+static SDev*
+mylexpnp(void)
+{
+ Pcidev *p;
+ Ctlr *ctlr;
+ ISAConf isa;
+ int cfg, ctlrno, i, x;
+ SDev *sdev, *head, *tail;
+
+ p = nil;
+ head = tail = nil;
+ while(p = pcimatch(p, 0x104B, 0)){
+ if((sdev = mylexprobe(p->mem[0].bar & ~0x01, p->intl)) == nil)
+ continue;
+
+ ctlr = sdev->ctlr;
+ ctlr->pcidev = p;
+
+ if(head != nil)
+ tail->next = sdev;
+ else
+ head = sdev;
+ tail = sdev;
+ }
+
+ if(strncmp(KADDR(0xFFFD9), "EISA", 4) == 0){
+ for(cfg = 0x1000; cfg < MaxEISA*0x1000; cfg += 0x1000){
+ x = 0;
+ for(i = 0; i < 4; i++)
+ x |= inb(cfg+CfgEISA+i)<<(i*8);
+ if(x != 0x0142B30A && x != 0x0242B30A)
+ continue;
+
+ x = inb(cfg+0xC8C);
+ if((sdev = mylexprobe(mylexport[x & 0x07], -1)) == nil)
+ continue;
+
+ if(head != nil)
+ tail->next = sdev;
+ else
+ head = sdev;
+ tail = sdev;
+ }
+ }
+
+ for(ctlrno = 0; ctlrno < 4; ctlrno++){
+ memset(&isa, 0, sizeof(isa));
+ if(!isaconfig("scsi", ctlrno, &isa))
+ continue;
+ if(strcmp(isa.type, "aha1542"))
+ continue;
+ if((sdev = mylexprobe(isa.port, -1)) == nil)
+ continue;
+
+ if(head != nil)
+ tail->next = sdev;
+ else
+ head = sdev;
+ tail = sdev;
+ }
+
+ return head;
+}
+
+static SDev*
+mylexid(SDev* sdev)
+{
+ return scsiid(sdev, &sdmylexifc);
+}
+
+static int
+mylex24enable(Ctlr* ctlr)
+{
+ ulong p;
+ Ccb24 *ccb, *ccbp;
+ uchar cmd[6], *v;
+ int len;
+
+ len = (sizeof(Mbox24)*NMbox*2)+(sizeof(Ccb24)*NCcb);
+ v = xspanalloc(len, 32, 0);
+
+ if(!PADDR24(ctlr, sizeof(Ctlr)) || !PADDR24(v, len))
+ return 0;
+
+ ctlr->mb = v;
+ v += sizeof(Mbox24)*NMbox*2;
+
+ ccb = (Ccb24*)v;
+ for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
+ ccbp->ccb = ctlr->ccb;
+ ctlr->ccb = (Ccb*)ccbp;
+ }
+
+ /*
+ * Initialise the software controller and
+ * set the board scanning the mailboxes.
+ */
+ ctlr->mbix = NMbox;
+
+ cmd[0] = Cinitialise;
+ cmd[1] = NMbox;
+ p = K2BPA(ctlr->mb, BUSUNKNOWN);
+ cmd[2] = p>>16;
+ cmd[3] = p>>8;
+ cmd[4] = p;
+
+ return issue(ctlr, cmd, 5, 0, 0);
+}
+
+static int
+mylex32enable(Ctlr* ctlr)
+{
+ ulong p;
+ Ccb32 *ccb, *ccbp;
+ uchar cmd[6], *v;
+
+ v = xspanalloc((sizeof(Mbox32)*NMbox*2)+(sizeof(Ccb32)*NCcb), 32, 0);
+
+ ctlr->mb = v;
+ v += sizeof(Mbox32)*NMbox*2;
+
+ ccb = (Ccb32*)v;
+ for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
+ /*
+ * Fill in some stuff that doesn't change.
+ */
+ ccbp->senselen = sizeof(ccbp->sense);
+ p = PADDR(ccbp->sense);
+ ccbp->senseptr[0] = p;
+ ccbp->senseptr[1] = p>>8;
+ ccbp->senseptr[2] = p>>16;
+ ccbp->senseptr[3] = p>>24;
+
+ ccbp->ccb = ctlr->ccb;
+ ctlr->ccb = (Ccb*)ccbp;
+ }
+
+ /*
+ * Attempt wide mode setup.
+ */
+ if(ctlr->wide){
+ cmd[0] = Cwide;
+ cmd[1] = 1;
+ if(!issue(ctlr, cmd, 2, 0, 0))
+ ctlr->wide = 0;
+ }
+
+ /*
+ * Initialise the software controller and
+ * set the board scanning the mailboxes.
+ */
+ ctlr->mbix = NMbox;
+
+ cmd[0] = Ciem;
+ cmd[1] = NMbox;
+ if(ctlr->pcidev)
+ p = K2BPA(ctlr->mb, ctlr->tbdf);
+ else
+ p = K2BPA(ctlr->mb, BUSUNKNOWN);
+ cmd[2] = p;
+ cmd[3] = p>>8;
+ cmd[4] = p>>16;
+ cmd[5] = p>>24;
+
+ return issue(ctlr, cmd, 6, 0, 0);
+}
+
+static int
+mylexenable(SDev* sdev)
+{
+ int tbdf;
+ Ctlr *ctlr;
+ void (*interrupt)(Ureg*, void*);
+ char name[NAMELEN];
+
+ ctlr = sdev->ctlr;
+ if(ctlr->cache == nil){
+ if((ctlr->cache = malloc(sdev->nunit*sizeof(Ccb*))) == nil)
+ return 0;
+ }
+
+ tbdf = BUSUNKNOWN;
+ if(ctlr->bus == 32){
+ if(ctlr->pcidev){
+ tbdf = ctlr->pcidev->tbdf;
+ pcisetbme(ctlr->pcidev);
+ }
+ if(!mylex32enable(ctlr))
+ return 0;
+ interrupt = mylex32interrupt;
+ }
+ else if(mylex24enable(ctlr))
+ interrupt = mylex24interrupt;
+ else
+ return 0;
+
+ snprint(name, NAMELEN, "sd%c (%s)", sdev->idno, sdev->ifc->name);
+ intrenable(ctlr->irq, interrupt, ctlr, tbdf, name);
+
+ return 1;
+}
+
+static int
+mylexdisable(SDev* sdev)
+{
+ Ctlr *ctlr;
+ int port, timeo;
+
+ ctlr = sdev->ctlr;
+ port = ctlr->port;
+
+ if(getconf("*noscsireset") != nil)
+ outb(port+Rcontrol, Rhard);
+ else
+ outb(port+Rcontrol, Rhard|Rsbus);
+ for(timeo = 0; timeo < 100; timeo++){
+ if(inb(port+Rstatus) == (Inreq|Hardy))
+ break;
+ delay(100);
+ }
+ if(inb(port+Rstatus) != (Inreq|Hardy))
+ return 0;
+
+ return 1;
+}
+
+SDifc sdmylexifc = {
+ "mylex", /* name */
+
+ mylexpnp, /* pnp */
+ nil, /* legacy */
+ mylexid, /* id */
+ mylexenable, /* enable */
+ mylexdisable, /* disable */
+
+ scsiverify, /* verify */
+ scsionline, /* online */
+ mylexrio, /* rio */
+ nil, /* rctl */
+ nil, /* wctl */
+
+ scsibio, /* bio */
+};
--- /dev/null
+++ b/os/boot.original/pc/sdscsi.c
@@ -1,0 +1,376 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "error.h"
+
+#include "sd.h"
+
+static int
+scsitest(SDreq* r)
+{
+ r->write = 0;
+ memset(r->cmd, 0, sizeof(r->cmd));
+ r->cmd[1] = r->lun<<5;
+ r->clen = 6;
+ r->data = nil;
+ r->dlen = 0;
+ r->flags = 0;
+
+ r->status = ~0;
+
+// cgascreenputs("A", 1);
+ return r->unit->dev->ifc->rio(r);
+}
+
+int
+scsiverify(SDunit* unit)
+{
+ static SDreq *r;
+ int i, status;
+ static uchar *inquiry;
+
+ if((r = sdmalloc(r, sizeof(SDreq))) == nil)
+ return 0;
+
+ if((inquiry = sdmalloc(inquiry, sizeof(unit->inquiry))) == nil)
+ return 0;
+
+ r->unit = unit;
+ r->lun = 0; /* ??? */
+
+ memset(unit->inquiry, 0, sizeof(unit->inquiry));
+ r->write = 0;
+ r->cmd[0] = 0x12;
+ r->cmd[1] = r->lun<<5;
+ r->cmd[4] = sizeof(unit->inquiry)-1;
+ r->clen = 6;
+ r->data = inquiry;
+ r->dlen = sizeof(unit->inquiry)-1;
+ r->flags = 0;
+
+ r->status = ~0;
+// cgascreenputs("B", 1);
+ if(unit->dev->ifc->rio(r) != SDok){
+ return 0;
+ }
+ memmove(unit->inquiry, inquiry, r->dlen);
+
+ SET(status);
+ for(i = 0; i < 3; i++){
+ while((status = scsitest(r)) == SDbusy)
+ ;
+ if(status == SDok || status != SDcheck)
+ break;
+ if(!(r->flags & SDvalidsense))
+ break;
+ if((r->sense[2] & 0x0F) != 0x02)
+ continue;
+
+ /*
+ * Unit is 'not ready'.
+ * If it is in the process of becoming ready or needs
+ * an initialising command, set status so it will be spun-up
+ * below.
+ * If there's no medium, that's OK too, but don't
+ * try to spin it up.
+ */
+ if(r->sense[12] == 0x04){
+ if(r->sense[13] == 0x02 || r->sense[13] == 0x01){
+ status = SDok;
+ break;
+ }
+ }
+ if(r->sense[12] == 0x3A)
+ break;
+ }
+
+ if(status == SDok){
+ /*
+ * Try to ensure a direct-access device is spinning.
+ * Ignore the result.
+ */
+ if((unit->inquiry[0] & 0x1F) == 0){
+ memset(r->cmd, 0, sizeof(r->cmd));
+ r->write = 0;
+ r->cmd[0] = 0x1B;
+ r->cmd[1] = r->lun<<5;
+ r->cmd[4] = 1;
+ r->clen = 6;
+ r->data = nil;
+ r->dlen = 0;
+ r->flags = 0;
+
+ r->status = ~0;
+ unit->dev->ifc->rio(r);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+int
+return0(void*)
+{
+ return 0;
+}
+
+static int
+scsirio(SDreq* r)
+{
+ /*
+ * Perform an I/O request, returning
+ * -1 failure
+ * 0 ok
+ * 2 retry
+ * The contents of r may be altered so the
+ * caller should re-initialise if necesary.
+ */
+ r->status = ~0;
+// cgascreenputs("C", 1);
+ switch(r->unit->dev->ifc->rio(r)){
+ default:
+ break;
+ case SDcheck:
+ if(!(r->flags & SDvalidsense))
+ return -1;
+ switch(r->sense[2] & 0x0F){
+ case 0x00: /* no sense */
+ case 0x01: /* recovered error */
+ return 2;
+ case 0x06: /* check condition */
+ /*
+ * 0x28 - not ready to ready transition,
+ * medium may have changed.
+ * 0x29 - power on or some type of reset.
+ */
+ if(r->sense[12] == 0x28 && r->sense[13] == 0)
+ return 2;
+ if(r->sense[12] == 0x29)
+ return 2;
+ break;
+ case 0x02: /* not ready */
+ /*
+ * If no medium present, bail out.
+ * If unit is becoming ready, rather than not
+ * not ready, wait a little then poke it again. */
+ if(r->sense[12] == 0x3A)
+ return -1;
+ if(r->sense[12] != 0x04 || r->sense[13] != 0x01)
+ return -1;
+
+ tsleep(nil, return0, 0, 500);
+ scsitest(r);
+ return 2;
+ default:
+ break;
+ }
+ break;
+ case SDok:
+ return 0;
+ }
+ return -1;
+}
+
+int
+scsionline(SDunit* unit)
+{
+ int ok;
+ static SDreq *r;
+ static uchar *p;
+
+ if((r = sdmalloc(r, sizeof(SDreq))) == nil)
+ return 0;
+
+ if((p = sdmalloc(p, 8)) == nil)
+ return 0;
+
+ ok = 0;
+
+ r->unit = unit;
+ r->lun = 0; /* ??? */
+ for(;;){
+ /*
+ * Read-capacity is mandatory for DA, WORM, CD-ROM and
+ * MO. It may return 'not ready' if type DA is not
+ * spun up, type MO or type CD-ROM are not loaded or just
+ * plain slow getting their act together after a reset.
+ */
+ r->write = 0;
+ memset(r->cmd, 0, sizeof(r->cmd));
+ r->cmd[0] = 0x25;
+ r->cmd[1] = r->lun<<5;
+ r->clen = 10;
+ r->data = p;
+ r->dlen = 8;
+ r->flags = 0;
+
+ r->status = ~0;
+// cgascreenputs("F", 1);
+ switch(scsirio(r)){
+ default:
+ break;
+ case 0:
+ unit->sectors = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+ /*
+ * Read-capacity returns the LBA of the last sector,
+ * therefore the number of sectors must be incremented.
+ */
+ unit->sectors++;
+ unit->secsize = (p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7];
+ ok = 1;
+ break;
+ case 2:
+ continue;
+ }
+ break;
+ }
+
+ return ok;
+}
+
+int
+scsiexec(SDunit* unit, int write, uchar* cmd, int clen, void* data, int* dlen)
+{
+ static SDreq *r;
+ int status;
+
+ if((r = sdmalloc(r, sizeof(SDreq))) == nil)
+ return SDmalloc;
+
+ r->unit = unit;
+ r->lun = cmd[1]>>5; /* ??? */
+ r->write = write;
+ memmove(r->cmd, cmd, clen);
+ r->clen = clen;
+ r->data = data;
+ if(dlen)
+ r->dlen = *dlen;
+ r->flags = 0;
+
+ r->status = ~0;
+
+ /*
+ * Call the device-specific I/O routine.
+ * There should be no calls to 'error()' below this
+ * which percolate back up.
+ */
+// cgascreenputs("D", 1);
+ switch(status = unit->dev->ifc->rio(r)){
+ case SDok:
+ if(dlen)
+ *dlen = r->rlen;
+ /*FALLTHROUGH*/
+ case SDcheck:
+ /*FALLTHROUGH*/
+ default:
+ /*
+ * It's more complicated than this. There are conditions
+ * which are 'ok' but for which the returned status code
+ * is not 'SDok'.
+ * Also, not all conditions require a reqsense, might
+ * need to do a reqsense here and make it available to the
+ * caller somehow.
+ *
+ * Mañana.
+ */
+ break;
+ }
+
+ return status;
+}
+
+long
+scsibio(SDunit* unit, int lun, int write, void* data, long nb, long bno)
+{
+ static SDreq *r;
+ long rlen;
+
+ if((r = sdmalloc(r, sizeof(SDreq))) == nil)
+ return SDmalloc;
+
+ r->unit = unit;
+ r->lun = lun;
+again:
+ r->write = write;
+ if(write == 0)
+ r->cmd[0] = 0x28;
+ else
+ r->cmd[0] = 0x2A;
+ r->cmd[1] = (lun<<5);
+ r->cmd[2] = bno>>24;
+ r->cmd[3] = bno>>16;
+ r->cmd[4] = bno>>8;
+ r->cmd[5] = bno;
+ r->cmd[6] = 0;
+ r->cmd[7] = nb>>8;
+ r->cmd[8] = nb;
+ r->cmd[9] = 0;
+ r->clen = 10;
+ r->data = data;
+ r->dlen = nb*unit->secsize;
+ r->flags = 0;
+
+ r->status = ~0;
+// cgascreenputs("E", 1);
+ switch(scsirio(r)){
+ default:
+ rlen = -1;
+ break;
+ case 0:
+ rlen = r->rlen;
+ break;
+ case 2:
+ rlen = -1;
+ if(!(r->flags & SDvalidsense))
+ break;
+ switch(r->sense[2] & 0x0F){
+ default:
+ break;
+ case 0x06: /* check condition */
+ /*
+ * Check for a removeable media change.
+ * If so, mark it and zap the geometry info
+ * to force an online request.
+ */
+ if(r->sense[12] != 0x28 || r->sense[13] != 0)
+ break;
+ if(unit->inquiry[1] & 0x80){
+ unit->sectors = 0;
+ }
+ break;
+ case 0x02: /* not ready */
+ /*
+ * If unit is becoming ready,
+ * rather than not not ready, try again.
+ */
+ if(r->sense[12] == 0x04 && r->sense[13] == 0x01)
+ goto again;
+ break;
+ }
+ break;
+ }
+
+ return rlen;
+}
+
+SDev*
+scsiid(SDev* sdev, SDifc* ifc)
+{
+ static char idno[16] = "0123456789abcdef";
+ static char *p = idno;
+
+ while(sdev){
+ if(sdev->ifc == ifc){
+ sdev->idno = *p++;
+ if(p >= &idno[sizeof(idno)])
+ break;
+ }
+ sdev = sdev->next;
+ }
+
+ return nil;
+}
--- /dev/null
+++ b/os/boot.original/pc/trap.c
@@ -1,0 +1,332 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+void intr0(void), intr1(void), intr2(void), intr3(void);
+void intr4(void), intr5(void), intr6(void), intr7(void);
+void intr8(void), intr9(void), intr10(void), intr11(void);
+void intr12(void), intr13(void), intr14(void), intr15(void);
+void intr16(void);
+void intr24(void), intr25(void), intr26(void), intr27(void);
+void intr28(void), intr29(void), intr30(void), intr31(void);
+void intr32(void), intr33(void), intr34(void), intr35(void);
+void intr36(void), intr37(void), intr38(void), intr39(void);
+void intr64(void);
+void intrbad(void);
+
+/*
+ * 8259 interrupt controllers
+ */
+enum
+{
+ Int0ctl= 0x20, /* control port (ICW1, OCW2, OCW3) */
+ Int0aux= 0x21, /* everything else (ICW2, ICW3, ICW4, OCW1) */
+ Int1ctl= 0xA0, /* control port */
+ Int1aux= 0xA1, /* everything else (ICW2, ICW3, ICW4, OCW1) */
+
+ Icw1= 0x10, /* select bit in ctl register */
+ Ocw2= 0x00,
+ Ocw3= 0x08,
+
+ EOI= 0x20, /* non-specific end of interrupt */
+
+ Elcr1= 0x4D0, /* Edge/Level Triggered Register */
+ Elcr2= 0x4D1,
+};
+
+int int0mask = 0xff; /* interrupts enabled for first 8259 */
+int int1mask = 0xff; /* interrupts enabled for second 8259 */
+int i8259elcr; /* mask of level-triggered interrupts */
+
+/*
+ * trap/interrupt gates
+ */
+Segdesc ilt[256];
+
+enum
+{
+ Maxhandler= 32, /* max number of interrupt handlers */
+};
+
+typedef struct Handler Handler;
+struct Handler
+{
+ void (*r)(Ureg*, void*);
+ void *arg;
+ Handler *next;
+};
+
+struct
+{
+ Handler *ivec[256];
+ Handler h[Maxhandler];
+ int nextfree;
+} halloc;
+
+void
+sethvec(int v, void (*r)(void), int type, int pri)
+{
+ ilt[v].d0 = ((ulong)r)&0xFFFF|(KESEL<<16);
+ ilt[v].d1 = ((ulong)r)&0xFFFF0000|SEGP|SEGPL(pri)|type;
+}
+
+void
+setvec(int v, void (*r)(Ureg*, void*), void *arg)
+{
+ Handler *h;
+
+ if(halloc.nextfree >= Maxhandler)
+ panic("out of interrupt handlers");
+ h = &halloc.h[halloc.nextfree++];
+ h->next = halloc.ivec[v];
+ h->r = r;
+ h->arg = arg;
+ halloc.ivec[v] = h;
+
+ /*
+ * enable corresponding interrupt in 8259
+ */
+ if((v&~0x7) == VectorPIC){
+ int0mask &= ~(1<<(v&7));
+ outb(Int0aux, int0mask);
+ } else if((v&~0x7) == VectorPIC+8){
+ int1mask &= ~(1<<(v&7));
+ outb(Int1aux, int1mask);
+ }
+}
+
+void
+trapdisable(void)
+{
+ outb(Int0aux, 0xFF);
+ outb(Int1aux, 0xFF);
+}
+
+void
+trapenable(void)
+{
+ outb(Int0aux, int0mask);
+ outb(Int1aux, int1mask);
+}
+
+
+/*
+ * set up the interrupt/trap gates
+ */
+void
+trapinit(void)
+{
+ int i, x;
+
+ /*
+ * set all interrupts to panics
+ */
+ for(i = 0; i < 256; i++)
+ sethvec(i, intrbad, SEGTG, 0);
+
+ /*
+ * 80386 processor (and coprocessor) traps
+ */
+ sethvec(0, intr0, SEGTG, 0);
+ sethvec(1, intr1, SEGTG, 0);
+ sethvec(2, intr2, SEGTG, 0);
+ sethvec(3, intr3, SEGTG, 0);
+ sethvec(4, intr4, SEGTG, 0);
+ sethvec(5, intr5, SEGTG, 0);
+ sethvec(6, intr6, SEGTG, 0);
+ sethvec(7, intr7, SEGTG, 0);
+ sethvec(8, intr8, SEGTG, 0);
+ sethvec(9, intr9, SEGTG, 0);
+ sethvec(10, intr10, SEGTG, 0);
+ sethvec(11, intr11, SEGTG, 0);
+ sethvec(12, intr12, SEGTG, 0);
+ sethvec(13, intr13, SEGTG, 0);
+ sethvec(14, intr14, SEGTG, 0);
+ sethvec(15, intr15, SEGTG, 0);
+ sethvec(16, intr16, SEGTG, 0);
+
+ /*
+ * device interrupts
+ */
+ sethvec(24, intr24, SEGIG, 0);
+ sethvec(25, intr25, SEGIG, 0);
+ sethvec(26, intr26, SEGIG, 0);
+ sethvec(27, intr27, SEGIG, 0);
+ sethvec(28, intr28, SEGIG, 0);
+ sethvec(29, intr29, SEGIG, 0);
+ sethvec(30, intr30, SEGIG, 0);
+ sethvec(31, intr31, SEGIG, 0);
+ sethvec(32, intr32, SEGIG, 0);
+ sethvec(33, intr33, SEGIG, 0);
+ sethvec(34, intr34, SEGIG, 0);
+ sethvec(35, intr35, SEGIG, 0);
+ sethvec(36, intr36, SEGIG, 0);
+ sethvec(37, intr37, SEGIG, 0);
+ sethvec(38, intr38, SEGIG, 0);
+ sethvec(39, intr39, SEGIG, 0);
+
+ /*
+ * tell the hardware where the table is (and how long)
+ */
+ putidt(ilt, sizeof(ilt)-1);
+
+ /*
+ * Set up the first 8259 interrupt processor.
+ * Make 8259 interrupts start at CPU vector VectorPIC.
+ * Set the 8259 as master with edge triggered
+ * input with fully nested interrupts.
+ */
+ outb(Int0ctl, Icw1|0x01); /* ICW1 - edge triggered, master,
+ ICW4 will be sent */
+ outb(Int0aux, VectorPIC); /* ICW2 - interrupt vector offset */
+ outb(Int0aux, 0x04); /* ICW3 - have slave on level 2 */
+ outb(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */
+
+ /*
+ * Set up the second 8259 interrupt processor.
+ * Make 8259 interrupts start at CPU vector VectorPIC+8.
+ * Set the 8259 as master with edge triggered
+ * input with fully nested interrupts.
+ */
+ outb(Int1ctl, Icw1|0x01); /* ICW1 - edge triggered, master,
+ ICW4 will be sent */
+ outb(Int1aux, VectorPIC+8); /* ICW2 - interrupt vector offset */
+ outb(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */
+ outb(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */
+ outb(Int1aux, int1mask);
+
+ /*
+ * pass #2 8259 interrupts to #1
+ */
+ int0mask &= ~0x04;
+ outb(Int0aux, int0mask);
+
+ /*
+ * Set Ocw3 to return the ISR when ctl read.
+ */
+ outb(Int0ctl, Ocw3|0x03);
+ outb(Int1ctl, Ocw3|0x03);
+
+ /*
+ * Check for Edge/Level register.
+ * This check may not work for all chipsets.
+ * First try a non-intrusive test - the bits for
+ * IRQs 13, 8, 2, 1 and 0 must be edge (0). If
+ * that's OK try a R/W test.
+ */
+ x = (inb(Elcr2)<<8)|inb(Elcr1);
+ if(!(x & 0x2107)){
+ outb(Elcr1, 0);
+ if(inb(Elcr1) == 0){
+ outb(Elcr1, 0x20);
+ if(inb(Elcr1) == 0x20)
+ i8259elcr = x;
+ outb(Elcr1, x & 0xFF);
+ print("ELCR: %4.4uX\n", i8259elcr);
+ }
+ }
+}
+
+/*
+ * dump registers
+ */
+static void
+dumpregs(Ureg *ur)
+{
+ print("FLAGS=%lux TRAP=%lux ECODE=%lux PC=%lux\n",
+ ur->flags, ur->trap, ur->ecode, ur->pc);
+ print(" AX %8.8lux BX %8.8lux CX %8.8lux DX %8.8lux\n",
+ ur->ax, ur->bx, ur->cx, ur->dx);
+ print(" SI %8.8lux DI %8.8lux BP %8.8lux\n",
+ ur->si, ur->di, ur->bp);
+ print(" CS %4.4lux DS %4.4lux ES %4.4lux FS %4.4lux GS %4.4lux\n",
+ ur->cs & 0xFF, ur->ds & 0xFFFF, ur->es & 0xFFFF, ur->fs & 0xFFFF, ur->gs & 0xFFFF);
+ print(" CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux\n",
+ getcr0(), getcr2(), getcr3());
+}
+
+/*
+ * All traps
+ */
+void
+trap(Ureg *ur)
+{
+ int v;
+ int c;
+ Handler *h;
+ ushort isr;
+
+ v = ur->trap;
+ /*
+ * tell the 8259 that we're done with the
+ * highest level interrupt (interrupts are still
+ * off at this point)
+ */
+ c = v&~0x7;
+ isr = 0;
+ if(c==VectorPIC || c==VectorPIC+8){
+ isr = inb(Int0ctl);
+ outb(Int0ctl, EOI);
+ if(c == VectorPIC+8){
+ isr |= inb(Int1ctl)<<8;
+ outb(Int1ctl, EOI);
+ }
+ }
+
+ if(v>=256 || (h = halloc.ivec[v]) == 0){
+ if(v >= VectorPIC && v < VectorPIC+16){
+ v -= VectorPIC;
+ /*
+ * Check for a default IRQ7. This can happen when
+ * the IRQ input goes away before the acknowledge.
+ * In this case, a 'default IRQ7' is generated, but
+ * the corresponding bit in the ISR isn't set.
+ * In fact, just ignore all such interrupts.
+ */
+ if(isr & (1<<v))
+ print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
+ return;
+ }
+
+ switch(v){
+
+ case 0x02: /* NMI */
+ print("NMI: nmisc=0x%2.2ux, nmiertc=0x%2.2ux, nmiesc=0x%2.2ux\n",
+ inb(0x61), inb(0x70), inb(0x461));
+ return;
+
+ default:
+ dumpregs(ur);
+ panic("exception/interrupt %d", v);
+ return;
+ }
+ }
+
+ /*
+ * call the trap routines
+ */
+ do {
+ (*h->r)(ur, h->arg);
+ h = h->next;
+ } while(h);
+}
+
+extern void realmode0(void); /* in l.s */
+
+extern int realmodeintr;
+extern Ureg realmoderegs;
+
+void
+realmode(int intr, Ureg *ureg)
+{
+ realmoderegs = *ureg;
+ realmodeintr = intr;
+ trapdisable();
+ realmode0();
+ trapenable();
+ *ureg = realmoderegs;
+}
--- /dev/null
+++ b/os/boot.original/pc/ureg.h
@@ -1,0 +1,27 @@
+typedef struct Ureg Ureg;
+
+struct Ureg
+{
+ ulong di; /* general registers */
+ ulong si; /* ... */
+ ulong bp; /* ... */
+ ulong nsp;
+ ulong bx; /* ... */
+ ulong dx; /* ... */
+ ulong cx; /* ... */
+ ulong ax; /* ... */
+ ulong gs; /* data segments */
+ ulong fs; /* ... */
+ ulong es; /* ... */
+ ulong ds; /* ... */
+ ulong trap; /* trap type */
+ ulong ecode; /* error code (or zero) */
+ ulong pc; /* pc */
+ ulong cs; /* old context */
+ ulong flags; /* old flags */
+ union {
+ ulong usp;
+ ulong sp;
+ };
+ ulong ss; /* old stack segment */
+};
--- /dev/null
+++ b/os/boot.original/pc/x16.h
@@ -1,0 +1,159 @@
+/*
+ * Can't write 16-bit code for 8a without getting into
+ * lots of bother, so define some simple commands and
+ * output the code directly.
+ *
+ * N.B. CALL16(x) kills DI, so don't expect it to be
+ * saved across calls.
+ */
+#define rAX 0 /* rX */
+#define rCX 1
+#define rDX 2
+#define rBX 3
+#define rSP 4 /* SP */
+#define rBP 5 /* BP */
+#define rSI 6 /* SI */
+#define rDI 7 /* DI */
+
+#define rAL 0 /* rL */
+#define rCL 1
+#define rDL 2
+#define rBL 3
+#define rAH 4 /* rH */
+#define rCH 5
+#define rDH 6
+#define rBH 7
+
+#define rES 0 /* rS */
+#define rCS 1
+#define rSS 2
+#define rDS 3
+#define rFS 4
+#define rGS 5
+
+#define xSI 4 /* rI (index) */
+#define xDI 5
+#define xBP 6
+#define xBX 7
+
+#define rCR0 0 /* rC */
+#define rCR2 2
+#define rCR3 3
+#define rCR4 4
+
+#define OP(o, m, ro, rm) BYTE $o; /* op + modr/m byte */ \
+ BYTE $(((m)<<6)|((ro)<<3)|(rm))
+#define OPrm(o, r, m) OP(o, 0x00, r, 0x06); /* general r <-> m */ \
+ WORD $m;
+#define OPrr(o, r0, r1) OP(o, 0x03, r0, r1); /* general r -> r */
+
+#define LW(m, rX) OPrm(0x8B, rX, m) /* m -> rX */
+#define LXW(x, rI, r) OP(0x8B, 0x02, r, rI); /* x(rI) -> r */ \
+ WORD $x
+#define LBPW(x, r) OP(0x8B, 0x02, r, xBP); /* x(rBP) -> r */ \
+ WORD $x
+#define LB(m, rB) OPrm(0x8A, rB, m) /* m -> r[HL] */
+#define LXB(x, rI, r) OP(0x8A, 0x01, r, rI); /* x(rI) -> r */ \
+ BYTE $x
+#define LBPB(x, r) OP(0x8A, 0x01, r, xBP); /* x(rBP) -> r */ \
+ BYTE $x
+#define SW(rX, m) OPrm(0x89, rX, m) /* rX -> m */
+#define SXW(r, x, rI) OP(0x89, 0x02, r, rI); /* r -> x(rI) */ \
+ WORD $x
+#define SBPW(r, x) OP(0x89, 0x02, r, xBP); /* r -> x(rBP) */ \
+ WORD $(x)
+#define SBPWI(i, x) OP(0xC7, 0x01, 0, xBP); /* i -> x(rBP) */ \
+ BYTE $(x); WORD $(i)
+#define STB(rB, m) OPrm(0x88, rB, m) /* rB -> m */
+#define SXB(r, x, rI) OP(0x88, 0x01, r, rI); /* rB -> x(rI) */ \
+ BYTE $x
+#define SBPB(r, x) OP(0x88, 0x01, r, xBP); /* r -> x(rBP) */ \
+ BYTE $x
+#define SBPBI(i, x) OP(0xC6, 0x01, 0, xBP); /* i -> x(rBP) */ \
+ BYTE $(x); BYTE $(i)
+#define LWI(i, rX) BYTE $(0xB8+rX); /* i -> rX */ \
+ WORD $i;
+#define LBI(i, rB) BYTE $(0xB0+rB); /* i -> r[HL] */ \
+ BYTE $i
+
+#define MW(r0, r1) OPrr(0x89, r0, r1) /* r0 -> r1 */
+#define MFSR(rS, rX) OPrr(0x8C, rS, rX) /* rS -> rX */
+#define MTSR(rX, rS) OPrr(0x8E, rS, rX) /* rX -> rS */
+#define MFCR(rC, rX) BYTE $0x0F; /* rC -> rX */ \
+ OP(0x20, 0x03, rC, rX)
+#define MTCR(rX, rC) BYTE $0x0F; /* rX -> rC */ \
+ OP(0x22, 0x03, rC, rX)
+
+#define ADC(r0, r1) OPrr(0x11, r0, r1) /* r0 + r1 -> r1 */
+#define ADD(r0, r1) OPrr(0x01, r0, r1) /* r0 + r1 -> r1 */
+#define ADDI(i, r) OP(0x81, 0x03, 0x00, r);/* i+r -> r */ \
+ WORD $i;
+#define AND(r0, r1) OPrr(0x21, r0, r1) /* r0&r1 -> r1 */
+#define ANDI(i, r) OP(0x81, 0x03, 0x04, r);/* i&r -> r */ \
+ WORD $i;
+#define CLR(r) OPrr(0x31, r, r) /* r^r -> r */
+#define CLRB(r) OPrr(0x30, r, r) /* r^r -> r */
+#define CMP(r0, r1) OPrr(0x39, r0, r1) /* r1-r0 -> flags */
+#define CMPI(i, r) OP(0x81, 0x03, 0x07, r);/* r-i -> flags */ \
+ WORD $i;
+#define CMPBR(r0, r1) OPrr(0x38, r0, r1) /* r1-r0 -> flags */
+#define DEC(r) BYTE $(0x48|r) /* r-1 -> r */
+#define DIV(r) OPrr(0xF7, 0x06, r) /* rDX:rAX/r -> rAX, rDX:rAX%r -> rDX */
+#define INC(r) BYTE $(0x40|r) /* r+1 -> r */
+#define MUL(r) OPrr(0xF7, 0x04, r) /* r*rAX -> rDX:rAX */
+#define IMUL(r0, r1) BYTE $0x0F; /* r0*r1 -> r1 */ \
+ OPrr(0xAF, r1, r0) /* (signed) */
+#define OR(r0, r1) OPrr(0x09, r0, r1) /* r0|r1 -> r1 */
+#define ORB(r0, r1) OPrr(0x08, r0, r1) /* r0|r1 -> r1 */
+#define ORI(i, r) OP(0x81, 0x03, 0x01, r);/* i|r -> r */ \
+ WORD $i;
+#define ROLI(i, r) OPrr(0xC1, 0x00, r); /* r<<>>i -> r */ \
+ BYTE $i;
+#define SHLI(i, r) OPrr(0xC1, 0x04, r); /* r<<i -> r */ \
+ BYTE $i;
+#define SHLBI(i, r) OPrr(0xC0, 0x04, r); /* r<<i -> r */ \
+ BYTE $i;
+#define SHRI(i, r) OPrr(0xC1, 0x05, r); /* r>>i -> r */ \
+ BYTE $i;
+#define SHRBI(i, r) OPrr(0xC0, 0x05, r); /* r>>i -> r */ \
+ BYTE $i;
+#define SUB(r0, r1) OPrr(0x29, r0, r1) /* r1-r0 -> r1 */
+#define SUBI(i, r) OP(0x81, 0x03, 0x05, r);/* r-i -> r */ \
+ WORD $i;
+
+#define STOSW STOSL
+
+#define CALL16(f) LWI(f, rDI); /* &f -> rDI */ \
+ BYTE $0xFF; /* (*rDI) */ \
+ BYTE $0xD7;
+#define FARJUMP16(s, o) BYTE $0xEA; /* jump to ptr16:16 */ \
+ WORD $o; WORD $s
+#define FARJUMP32(s, o) BYTE $0x66; /* jump to ptr32:16 */ \
+ BYTE $0xEA; LONG $o; WORD $s
+#define DELAY BYTE $0xEB; /* jmp .+2 */ \
+ BYTE $0x00
+#define BIOSCALL(b) INT $b /* INT $b */
+
+#define PEEKW BYTE $0x26; /* MOVW rES:[rBX], rAX */ \
+ BYTE $0x8B; BYTE $0x07
+#define POKEW BYTE $0x26; /* MOVW rAX, rES:[rBX] */ \
+ BYTE $0x89; BYTE $0x07
+#define OUTPORTB(p, d) LBI(d, rAL); /* d -> I/O port p */ \
+ BYTE $0xE6; \
+ BYTE $p; DELAY
+#define PUSHA BYTE $0x60
+#define PUSHR(r) BYTE $(0x50|r) /* r -> (--rSP) */
+#define PUSHS(rS) BYTE $(0x06|((rS)<<3)) /* rS -> (--rSP) */
+#define PUSHI(i) BYTE $0x68; WORD $i; /* i -> --(rSP) */
+#define POPA BYTE $0x61
+#define POPR(r) BYTE $(0x58|r) /* (rSP++) -> r */
+#define POPS(rS) BYTE $(0x07|((rS)<<3)) /* (rSP++) -> r */
+#define NOP BYTE $0x90 /* nop */
+
+#define LGDT(gdtptr) BYTE $0x0F; /* LGDT */ \
+ BYTE $0x01; BYTE $0x16; \
+ WORD $gdtptr
+
+/* operand size switch. */
+#define OPSIZE BYTE $0x66
+
--- /dev/null
+++ b/os/boot.original/puma/8250.c
@@ -1,0 +1,312 @@
+#include "boot.h"
+
+/*
+ * INS8250 uart
+ */
+enum
+{
+ /*
+ * register numbers
+ */
+ Data= 0, /* xmit/rcv buffer */
+ Iena= 1, /* interrupt enable */
+ Ircv= (1<<0), /* for char rcv'd */
+ Ixmt= (1<<1), /* for xmit buffer empty */
+ Irstat=(1<<2), /* for change in rcv'er status */
+ Imstat=(1<<3), /* for change in modem status */
+ Istat= 2, /* interrupt flag (read) */
+ Tctl= 2, /* test control (write) */
+ Format= 3, /* byte format */
+ Bits8= (3<<0), /* 8 bits/byte */
+ Stop2= (1<<2), /* 2 stop bits */
+ Pena= (1<<3), /* generate parity */
+ Peven= (1<<4), /* even parity */
+ Pforce=(1<<5), /* force parity */
+ Break= (1<<6), /* generate a break */
+ Dra= (1<<7), /* address the divisor */
+ Mctl= 4, /* modem control */
+ Dtr= (1<<0), /* data terminal ready */
+ Rts= (1<<1), /* request to send */
+ Ri= (1<<2), /* ring */
+ Inton= (1<<3), /* turn on interrupts */
+ Loop= (1<<4), /* loop back */
+ Lstat= 5, /* line status */
+ Inready=(1<<0), /* receive buffer full */
+ Oerror=(1<<1), /* receiver overrun */
+ Perror=(1<<2), /* receiver parity error */
+ Ferror=(1<<3), /* rcv framing error */
+ Outready=(1<<5), /* output buffer empty */
+ Mstat= 6, /* modem status */
+ Ctsc= (1<<0), /* clear to send changed */
+ Dsrc= (1<<1), /* data set ready changed */
+ Rire= (1<<2), /* rising edge of ring indicator */
+ Dcdc= (1<<3), /* data carrier detect changed */
+ Cts= (1<<4), /* complement of clear to send line */
+ Dsr= (1<<5), /* complement of data set ready line */
+ Ring= (1<<6), /* complement of ring indicator line */
+ Dcd= (1<<7), /* complement of data carrier detect line */
+ Scratch=7, /* scratchpad */
+ Dlsb= 0, /* divisor lsb */
+ Dmsb= 1, /* divisor msb */
+
+ Serial= 0,
+ Modem= 1,
+};
+
+typedef struct Uart Uart;
+struct Uart
+{
+ int port;
+ int setup;
+ uchar sticky[8]; /* sticky write register values */
+ uchar txbusy;
+
+ Queue *iq;
+ Queue *oq;
+ void (*rx)(Queue *, int);
+
+ ulong frame;
+ ulong overrun;
+};
+
+Uart uart[1];
+
+static void uartkick(void*);
+
+
+#define UartFREQ 1843200
+
+#define uartwrreg(u,r,v) outb((u)->port + r, (u)->sticky[r] | (v))
+#define uartrdreg(u,r) inb((u)->port + r)
+
+/*
+ * set the baud rate by calculating and setting the baudrate
+ * generator constant. This will work with fairly non-standard
+ * baud rates.
+ */
+static void
+uartsetbaud(Uart *up, int rate)
+{
+ ulong brconst;
+
+ brconst = (UartFREQ+8*rate-1)/(16*rate);
+
+ uartwrreg(up, Format, Dra);
+ outb(up->port+Dmsb, (brconst>>8) & 0xff);
+ outb(up->port+Dlsb, brconst & 0xff);
+ uartwrreg(up, Format, 0);
+}
+
+/*
+ * toggle DTR
+ */
+static void
+uartdtr(Uart *up, int n)
+{
+ if(n)
+ up->sticky[Mctl] |= Dtr;
+ else
+ up->sticky[Mctl] &= ~Dtr;
+ uartwrreg(up, Mctl, 0);
+}
+
+/*
+ * toggle RTS
+ */
+static void
+uartrts(Uart *up, int n)
+{
+ if(n)
+ up->sticky[Mctl] |= Rts;
+ else
+ up->sticky[Mctl] &= ~Rts;
+ uartwrreg(up, Mctl, 0);
+}
+
+static void
+uartintr(Ureg*, void *arg)
+{
+ Uart *up;
+ int ch;
+ int s, l, loops;
+
+ up = arg;
+ for(loops = 0; loops < 1024; loops++){
+ s = uartrdreg(up, Istat);
+ switch(s){
+ case 6: /* receiver line status */
+ l = uartrdreg(up, Lstat);
+ if(l & Ferror)
+ up->frame++;
+ if(l & Oerror)
+ up->overrun++;
+ break;
+
+ case 4: /* received data available */
+ case 12:
+ ch = inb(up->port+Data);
+ if(up->iq)
+ if(up->rx)
+ (*up->rx)(up->iq, ch);
+ else
+ qbputc(up->iq, ch);
+ break;
+
+ case 2: /* transmitter empty */
+ ch = -1;
+ if(up->oq)
+ ch = qbgetc(up->oq);
+ if(ch != -1)
+ outb(up->port+Data, ch);
+ else
+ up->txbusy = 0;
+ break;
+
+ case 0: /* modem status */
+ uartrdreg(up, Mstat);
+ break;
+
+ default:
+ if(s&1)
+ return;
+ print("weird modem interrupt #%2.2ux\n", s);
+ break;
+ }
+ }
+ panic("uartintr: 0x%2.2ux\n", uartrdreg(up, Istat));
+}
+
+/*
+ * turn on a port's interrupts. set DTR and RTS
+ */
+static void
+uartenable(Uart *up)
+{
+ /*
+ * turn on interrupts
+ */
+ up->sticky[Iena] = 0;
+ if(up->oq)
+ up->sticky[Iena] |= Ixmt;
+ if(up->iq)
+ up->sticky[Iena] |= Ircv|Irstat;
+ uartwrreg(up, Iena, 0);
+
+ /*
+ * turn on DTR and RTS
+ */
+ uartdtr(up, 1);
+ uartrts(up, 1);
+}
+
+void
+uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue *, int))
+{
+ Uart *up = &uart[0];
+
+ if(up->setup)
+ return;
+ up->setup = 1;
+
+ *iq = up->iq = qopen(4*1024, 0, 0, 0);
+ *oq = up->oq = qopen(16*1024, 0, uartkick, up);
+ switch(port){
+
+ case 0:
+ up->port = 0x3F8;
+ setvec(V_COM1, uartintr, up);
+ break;
+
+ case 1:
+ up->port = 0x2F8;
+ setvec(V_COM2, uartintr, up);
+ break;
+
+ default:
+ return;
+ }
+
+ /*
+ * set rate to 9600 baud.
+ * 8 bits/character.
+ * 1 stop bit.
+ * interrupts enabled.
+ */
+ uartsetbaud(up, 9600);
+ up->sticky[Format] = Bits8;
+ uartwrreg(up, Format, 0);
+ up->sticky[Mctl] |= Inton;
+ uartwrreg(up, Mctl, 0x0);
+
+ up->rx = rx;
+ uartenable(up);
+ if(baud)
+ uartsetbaud(up, baud);
+}
+
+static void
+uartputc(int c)
+{
+ Uart *up = &uart[0];
+ int i;
+
+ for(i = 0; i < 100; i++){
+ if(uartrdreg(up, Lstat) & Outready)
+ break;
+ delay(1);
+ }
+ outb(up->port+Data, c);
+}
+
+void
+uartputs(char *s, int n)
+{
+ Uart *up = &uart[0];
+ Block *b;
+ int nl;
+ char *p;
+
+ nl = 0;
+ for(p = s; p < s+n; p++)
+ if(*p == '\n')
+ nl++;
+ b = iallocb(n+nl);
+ while(n--){
+ if(*s == '\n')
+ *b->wp++ = '\r';
+ *b->wp++ = *s++;
+ }
+ qbwrite(up->oq, b);
+}
+
+/*
+ * (re)start output
+ */
+static void
+uartkick(void *arg)
+{
+ Uart *up = arg;
+ int x, n, c;
+
+ x = splhi();
+ while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1) {
+ n = 0;
+ while((uartrdreg(up, Lstat) & Outready) == 0){
+ if(++n > 100000){
+ print("stuck serial line\n");
+ break;
+ }
+ }
+ outb(up->port + Data, c);
+ }
+ splx(x);
+}
+
+void
+uartwait(void)
+{
+ Uart *up = &uart[0];
+
+ while(up->txbusy)
+ ;
+}
--- /dev/null
+++ b/os/boot.original/puma/alarm.c
@@ -1,0 +1,123 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#define MAXALARM 10
+
+Alarm alarmtab[MAXALARM];
+
+/*
+ * Insert new into list after where
+ */
+void
+insert(List **head, List *where, List *new)
+{
+ if(where == 0){
+ new->next = *head;
+ *head = new;
+ }else{
+ new->next = where->next;
+ where->next = new;
+ }
+
+}
+
+/*
+ * Delete old from list. where->next is known to be old.
+ */
+void
+delete(List **head, List *where, List *old)
+{
+ if(where == 0){
+ *head = old->next;
+ return;
+ }
+ where->next = old->next;
+}
+
+Alarm*
+newalarm(void)
+{
+ int i;
+ Alarm *a;
+
+ for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
+ if(a->busy==0 && a->f==0){
+ a->f = 0;
+ a->arg = 0;
+ a->busy = 1;
+ return a;
+ }
+ panic("newalarm");
+ return 0; /* not reached */
+}
+
+Alarm*
+alarm(int ms, void (*f)(Alarm*), void *arg)
+{
+ Alarm *a, *w, *pw;
+ ulong s;
+
+ if(ms < 0)
+ ms = 0;
+ s = splhi();
+ a = newalarm();
+ a->dt = MS2TK(ms);
+ a->f = f;
+ a->arg = arg;
+ pw = 0;
+ for(w=m->alarm; w; pw=w, w=w->next){
+ if(w->dt <= a->dt){
+ a->dt -= w->dt;
+ continue;
+ }
+ w->dt -= a->dt;
+ break;
+ }
+ insert(&m->alarm, pw, a);
+ splx(s);
+ return a;
+}
+
+void
+cancel(Alarm *a)
+{
+ a->f = 0;
+}
+
+void
+alarminit(void)
+{
+}
+
+#define NA 10 /* alarms per clock tick */
+void
+checkalarms(void)
+{
+ int i, n, s;
+ Alarm *a;
+ void (*f)(void*);
+ Alarm *alist[NA];
+
+ s = splhi();
+ a = m->alarm;
+ if(a){
+ for(n=0; a && a->dt<=0 && n<NA; n++){
+ alist[n] = a;
+ delete(&m->alarm, 0, a);
+ a = m->alarm;
+ }
+ if(a)
+ a->dt--;
+
+ for(i = 0; i < n; i++){
+ f = alist[i]->f; /* avoid race with cancel */
+ if(f)
+ (*f)(alist[i]);
+ alist[i]->busy = 0;
+ }
+ }
+ splx(s);
+}
--- /dev/null
+++ b/os/boot.original/puma/armv4.h
@@ -1,0 +1,99 @@
+/*
+ * PSR
+ */
+#define PsrMusr 0x10 /* mode */
+#define PsrMfiq 0x11
+#define PsrMirq 0x12
+#define PsrMsvc 0x13
+#define PsrMabt 0x17
+#define PsrMund 0x1B
+#define PsrMsys 0x1F
+#define PsrMask 0x1F
+
+#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
+#define PsrDirq 0x00000080 /* disable IRQ interrupts */
+
+#define PsrV 0x10000000 /* overflow */
+#define PsrC 0x20000000 /* carry/borrow/extend */
+#define PsrZ 0x40000000 /* zero */
+#define PsrN 0x80000000 /* negative/less than */
+
+/*
+ * Internal MMU coprocessor registers
+ */
+#define CpCPUID 0 /* R: */
+#define CpControl 1 /* R: */
+#define CpTTB 2 /* W: translation table base */
+#define CpDAC 3 /* W: domain access control */
+#define CpFSR 5 /* R: fault status */
+#define CpTLBflush 5 /* W: */
+#define CpFAR 6 /* R: fault address */
+#define CpTLBpurge 6 /* W: */
+#define CpCacheCtl 7 /* W: */
+
+#define CpDebug 14 /* R/W: debug registers */
+/*
+ * Coprocessors
+ */
+#define CpMMU 15
+
+/*
+ * Internal MMU coprocessor registers
+ */
+#define CpCmmu 0x00000001 /* M: MMU enable */
+#define CpCalign 0x00000002 /* A: alignment fault enable */
+#define CpCDcache 0x00000004 /* C: instruction/data cache on */
+#define CpCwb 0x00000008 /* W: write buffer turned on */
+#define CpCi32 0x00000010 /* P: 32-bit programme space */
+#define CpCd32 0x00000020 /* D: 32-bit data space */
+#define CpCbe 0x00000080 /* B: big-endian operation */
+#define CpCsystem 0x00000100 /* S: system permission */
+#define CpCrom 0x00000200 /* R: ROM permission */
+#define CpCIcache 0x00001000 /* C: Instruction Cache on */
+
+/*
+ * Debug support internal registers
+ */
+#define CpDBAR 0
+#define CpDBVR 1
+#define CpDBMR 2
+#define CpDBCR 3
+#define CpIBCR 8
+/*
+ * MMU
+ */
+/*
+ * Small pages:
+ * L1: 12-bit index -> 4096 descriptors -> 16Kb
+ * L2: 8-bit index -> 256 descriptors -> 1Kb
+ * Each L2 descriptor has access permissions for 4 1Kb sub-pages.
+ *
+ * TTB + L1Tx gives address of L1 descriptor
+ * L1 descriptor gives PTBA
+ * PTBA + L2Tx gives address of L2 descriptor
+ * L2 descriptor gives PBA
+ */
+#define MmuTTB(pa) ((pa) & ~0x3FFF) /* translation table base */
+#define MmuL1x(pa) (((pa)>>20) & 0xFFF) /* L1 table index */
+#define MmuPTBA(pa) ((pa) & ~0x3FF) /* page table base address */
+#define MmuL2x(pa) (((pa)>>12) & 0xFF) /* L2 table index */
+#define MmuPBA(pa) ((pa) & ~0xFFF) /* page base address */
+#define MmuSBA(pa) ((pa) & ~0xFFFFF) /* section base address */
+
+#define MmuL1page 0x011 /* descriptor is for L2 pages */
+#define MmuL1section 0x012 /* descriptor is for section */
+
+#define MmuL2invalid 0x000
+#define MmuL2large 0x001 /* large */
+#define MmuL2small 0x002 /* small */
+#define MmuWB 0x004 /* data goes through write buffer */
+#define MmuIDC 0x008 /* data placed in cache */
+
+#define MmuDAC(d) (((d) & 0xF)<<5) /* L1 domain */
+#define MmuAP(i, v) ((v)<<(((i)*2)+4)) /* access permissions */
+#define MmuL1AP(v) MmuAP(3, (v))
+#define MmuL2AP(v) MmuAP(3, (v))|MmuAP(2, (v))|MmuAP(1, (v))|MmuAP(0, (v))
+#define MmuAPsro 0 /* supervisor rw */
+#define MmuAPsrw 1 /* supervisor rw */
+#define MmuAPuro 2 /* supervisor rw + user ro */
+#define MmuAPurw 3 /* supervisor rw + user rw */
--- /dev/null
+++ b/os/boot.original/puma/boot.h
@@ -1,0 +1,12 @@
+#include <u.h>
+#include "lib.h"
+
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+#include "armv4.h"
+#include "puma.h"
+
--- /dev/null
+++ b/os/boot.original/puma/bootp.c
@@ -1,0 +1,502 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ip.h"
+
+uchar broadcast[Eaddrlen] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static ushort tftpport = 5000;
+static int Id = 1;
+static Netaddr myaddr;
+static Netaddr server;
+
+typedef struct {
+ uchar header[4];
+ uchar data[Segsize];
+} Tftp;
+static Tftp tftpb;
+
+static void
+hnputs(uchar *ptr, ushort val)
+{
+ ptr[0] = val>>8;
+ ptr[1] = val;
+}
+
+static void
+hnputl(uchar *ptr, ulong val)
+{
+ ptr[0] = val>>24;
+ ptr[1] = val>>16;
+ ptr[2] = val>>8;
+ ptr[3] = val;
+}
+
+static ulong
+nhgetl(uchar *ptr)
+{
+ return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+}
+
+static ushort
+nhgets(uchar *ptr)
+{
+ return ((ptr[0]<<8) | ptr[1]);
+}
+
+static short endian = 1;
+static char* aendian = (char*)&endian;
+#define LITTLE *aendian
+
+static ushort
+ptcl_csum(void *a, int len)
+{
+ uchar *addr;
+ ulong t1, t2;
+ ulong losum, hisum, mdsum, x;
+
+ addr = a;
+ losum = 0;
+ hisum = 0;
+ mdsum = 0;
+
+ x = 0;
+ if((ulong)addr & 1) {
+ if(len) {
+ hisum += addr[0];
+ len--;
+ addr++;
+ }
+ x = 1;
+ }
+ while(len >= 16) {
+ t1 = *(ushort*)(addr+0);
+ t2 = *(ushort*)(addr+2); mdsum += t1;
+ t1 = *(ushort*)(addr+4); mdsum += t2;
+ t2 = *(ushort*)(addr+6); mdsum += t1;
+ t1 = *(ushort*)(addr+8); mdsum += t2;
+ t2 = *(ushort*)(addr+10); mdsum += t1;
+ t1 = *(ushort*)(addr+12); mdsum += t2;
+ t2 = *(ushort*)(addr+14); mdsum += t1;
+ mdsum += t2;
+ len -= 16;
+ addr += 16;
+ }
+ while(len >= 2) {
+ mdsum += *(ushort*)addr;
+ len -= 2;
+ addr += 2;
+ }
+ if(x) {
+ if(len)
+ losum += addr[0];
+ if(LITTLE)
+ losum += mdsum;
+ else
+ hisum += mdsum;
+ } else {
+ if(len)
+ hisum += addr[0];
+ if(LITTLE)
+ hisum += mdsum;
+ else
+ losum += mdsum;
+ }
+
+ losum += hisum >> 8;
+ losum += (hisum & 0xff) << 8;
+ while(hisum = losum>>16)
+ losum = hisum + (losum & 0xffff);
+
+ return ~losum;
+}
+
+static ushort
+ip_csum(uchar *addr)
+{
+ int len;
+ ulong sum = 0;
+
+ len = (addr[0]&0xf)<<2;
+
+ while(len > 0) {
+ sum += addr[0]<<8 | addr[1] ;
+ len -= 2;
+ addr += 2;
+ }
+
+ sum = (sum & 0xffff) + (sum >> 16);
+ sum = (sum & 0xffff) + (sum >> 16);
+ return (sum^0xffff);
+}
+
+static void
+udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+ Udphdr *uh;
+ Etherhdr *ip;
+ Etherpkt pkt;
+ int len, ptcllen;
+
+
+ uh = (Udphdr*)&pkt;
+
+ memset(uh, 0, sizeof(Etherpkt));
+ memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
+
+ /*
+ * UDP portion
+ */
+ ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
+ uh->ttl = 0;
+ uh->udpproto = IP_UDPPROTO;
+ uh->frag[0] = 0;
+ uh->frag[1] = 0;
+ hnputs(uh->udpplen, ptcllen);
+ hnputl(uh->udpsrc, myaddr.ip);
+ hnputs(uh->udpsport, myaddr.port);
+ hnputl(uh->udpdst, a->ip);
+ hnputs(uh->udpdport, a->port);
+ hnputs(uh->udplen, ptcllen);
+ uh->udpcksum[0] = 0;
+ uh->udpcksum[1] = 0;
+ dlen = (dlen+1)&~1;
+ hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
+
+ /*
+ * IP portion
+ */
+ ip = (Etherhdr*)&pkt;
+ len = sizeof(Udphdr)+dlen;
+ ip->vihl = IP_VER|IP_HLEN;
+ ip->tos = 0;
+ ip->ttl = 255;
+ hnputs(ip->length, len-ETHER_HDR);
+ hnputs(ip->id, Id++);
+ ip->frag[0] = 0;
+ ip->frag[1] = 0;
+ ip->cksum[0] = 0;
+ ip->cksum[1] = 0;
+ hnputs(ip->cksum, ip_csum(&ip->vihl));
+
+ /*
+ * Ethernet MAC portion
+ */
+ hnputs(ip->type, ET_IP);
+ memmove(ip->d, a->ea, sizeof(ip->d));
+
+ ethertxpkt(ctlrno, &pkt, len, Timeout);
+}
+
+static void
+nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
+{
+ int n;
+ char buf[128];
+
+ buf[0] = 0;
+ buf[1] = Tftp_ERROR;
+ buf[2] = 0;
+ buf[3] = code;
+ strcpy(buf+4, msg);
+ n = strlen(msg) + 4 + 1;
+ udpsend(ctlrno, a, buf, n);
+ if(report)
+ print("\ntftp: error(%d): %s\n", code, msg);
+}
+
+static int
+udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+ int n, len;
+ ushort csm;
+ Udphdr *h;
+ ulong addr, timo;
+ Etherpkt pkt;
+ static int rxactive;
+
+ if(rxactive == 0)
+ timo = 1000;
+ else
+ timo = Timeout;
+ timo += TK2MS(m->ticks);
+ while(timo > TK2MS(m->ticks)){
+ n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
+
+ if(n <= 0)
+ continue;
+
+ h = (Udphdr*)&pkt;
+ if(nhgets(h->type) != ET_IP)
+ continue;
+
+ if(ip_csum(&h->vihl)) {
+ print("ip chksum error\n");
+ continue;
+ }
+ if(h->vihl != (IP_VER|IP_HLEN)) {
+ print("ip bad vers/hlen\n");
+ continue;
+ }
+
+ if(h->udpproto != IP_UDPPROTO)
+ continue;
+
+ h->ttl = 0;
+ len = nhgets(h->udplen);
+ hnputs(h->udpplen, len);
+
+ if(nhgets(h->udpcksum)) {
+ csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
+ if(csm != 0) {
+ print("udp chksum error csum #%4lux len %d\n", csm, n);
+ break;
+ }
+ }
+
+ if(a->port != 0 && nhgets(h->udpsport) != a->port)
+ continue;
+
+ addr = nhgetl(h->udpsrc);
+ if(a->ip != Bcastip && addr != a->ip)
+ continue;
+
+ len -= UDP_HDRSIZE-UDP_PHDRSIZE;
+ if(len > dlen) {
+ print("udp: packet too big\n");
+ continue;
+ }
+
+ memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
+ a->ip = addr;
+ a->port = nhgets(h->udpsport);
+ memmove(a->ea, pkt.s, sizeof(a->ea));
+
+ rxactive = 1;
+ return len;
+ }
+
+ return 0;
+}
+
+static int tftpblockno;
+
+static int
+tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
+{
+ int i, len, rlen, oport;
+ char buf[Segsize+2];
+
+ buf[0] = 0;
+ buf[1] = Tftp_READ;
+ len = sprint(buf+2, "%s", name) + 2;
+ len += sprint(buf+len+1, "octet") + 2;
+
+ oport = a->port;
+ for(i = 0; i < 5; i++){
+ a->port = oport;
+ udpsend(ctlrno, a, buf, len);
+ a->port = 0;
+ if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
+ continue;
+
+ switch((tftp->header[0]<<8)|tftp->header[1]){
+
+ case Tftp_ERROR:
+ print("tftpopen: error (%d): %s\n",
+ (tftp->header[2]<<8)|tftp->header[3], tftp->data);
+ return -1;
+
+ case Tftp_DATA:
+ tftpblockno = 1;
+ len = (tftp->header[2]<<8)|tftp->header[3];
+ if(len != tftpblockno){
+ print("tftpopen: block error: %d\n", len);
+ nak(ctlrno, a, 1, "block error", 0);
+ return -1;
+ }
+ return rlen-sizeof(tftp->header);
+ }
+ }
+
+ print("tftpopen: failed to connect to server\n");
+ return -1;
+}
+
+static int
+tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
+{
+ int blockno, len, retry;
+ uchar buf[4];
+
+ buf[0] = 0;
+ buf[1] = Tftp_ACK;
+ buf[2] = tftpblockno>>8;
+ buf[3] = tftpblockno;
+ tftpblockno++;
+
+ dlen += sizeof(tftp->header);
+
+ retry = 0;
+buggery:
+ udpsend(ctlrno, a, buf, sizeof(buf));
+
+ if((len = udprecv(ctlrno, a, tftp, dlen)) != dlen){
+ print("tftpread: %d != %d\n", len, dlen);
+ nak(ctlrno, a, 2, "short read", 0);
+ if(retry++ < 5)
+ goto buggery;
+ return -1;
+ }
+
+ blockno = (tftp->header[2]<<8)|tftp->header[3];
+ if(blockno != tftpblockno){
+ print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
+
+ if(blockno == tftpblockno-1 && retry++ < 5)
+ goto buggery;
+ nak(ctlrno, a, 1, "block error", 0);
+
+ return -1;
+ }
+
+ return len-sizeof(tftp->header);
+}
+
+int
+bootp(int ctlrno, char *file)
+{
+ Bootp req, rep;
+ int i, dlen, segsize, text, data, bss, total;
+ uchar *ea, *addr, *p;
+ ulong entry;
+ Exec *exec;
+ char name[128], *filename, *sysname;
+
+ if((ea = etheraddr(ctlrno)) == 0){
+ print("invalid ctlrno %d\n", ctlrno);
+ return -1;
+ }
+
+ filename = 0;
+ sysname = 0;
+ if(file && *file){
+ strcpy(name, file);
+ if(filename = strchr(name, ':')){
+ if(filename != name && *(filename-1) != '\\'){
+ sysname = name;
+ *filename++ = 0;
+ }
+ }
+ else
+ filename = name;
+ }
+
+
+ memset(&req, 0, sizeof(req));
+ req.op = Bootrequest;
+ req.htype = 1; /* ethernet */
+ req.hlen = Eaddrlen; /* ethernet */
+ memmove(req.chaddr, ea, Eaddrlen);
+
+ myaddr.ip = 0;
+ myaddr.port = BPportsrc;
+ memmove(myaddr.ea, ea, Eaddrlen);
+
+ for(i = 0; i < 10; i++) {
+ server.ip = Bcastip;
+ server.port = BPportdst;
+ memmove(server.ea, broadcast, sizeof(server.ea));
+ udpsend(ctlrno, &server, &req, sizeof(req));
+ if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
+ continue;
+ if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
+ continue;
+ if(rep.htype != 1 || rep.hlen != Eaddrlen)
+ continue;
+ if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
+ break;
+ }
+ if(i >= 10) {
+ print("bootp timed out\n");
+ return -1;
+ }
+
+ if(filename == 0 || *filename == 0)
+ filename = rep.file;
+
+ if(rep.sname[0] != '\0')
+ print("%s ", rep.sname);
+ print("(%d.%d.%d.%d!%d): %s\n",
+ rep.siaddr[0],
+ rep.siaddr[1],
+ rep.siaddr[2],
+ rep.siaddr[3],
+ server.port,
+ filename);
+
+ myaddr.ip = nhgetl(rep.yiaddr);
+ myaddr.port = tftpport++;
+ server.ip = nhgetl(rep.siaddr);
+ server.port = TFTPport;
+
+ if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
+ return -1;
+
+ exec = (Exec*)(tftpb.data);
+ if(dlen < sizeof(Exec) || GLLONG(exec->magic) != E_MAGIC){
+ nak(ctlrno, &server, 0, "bad magic number", 1);
+ return -1;
+ }
+ text = GLLONG(exec->text);
+ data = GLLONG(exec->data);
+ bss = GLLONG(exec->bss);
+ total = text+data+bss;
+ entry = GLLONG(exec->entry);
+print("load@%8.8lux: ", PADDR(entry));
+ print("%d", text);
+
+ addr = (uchar*)PADDR(entry);
+ p = tftpb.data+sizeof(Exec);
+ dlen -= sizeof(Exec);
+ segsize = text;
+ for(;;){
+ if(dlen == 0){
+ if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
+ return -1;
+ p = tftpb.data;
+ }
+ if(segsize <= dlen)
+ i = segsize;
+ else
+ i = dlen;
+ memmove(addr, p, i);
+
+ addr += i;
+ p += i;
+ segsize -= i;
+ dlen -= i;
+
+ if(segsize <= 0){
+ if(data == 0)
+ break;
+ print("+%d", data);
+ segsize = data;
+ data = 0;
+ addr = (uchar*)PGROUND((ulong)addr);
+ }
+ }
+ nak(ctlrno, &server, 3, "ok", 0); /* tftpclose */
+ print("+%d=%d\n", bss, total);
+ print("entry: 0x%lux\n", entry);
+
+ (*(void(*)(void))(PADDR(entry)))();
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/puma/cga.c
@@ -1,0 +1,92 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "io.h"
+#include "fns.h"
+
+enum {
+ Width = 160,
+ Height = 25,
+
+ Attr = 7, /* white on black */
+};
+
+#define CGASCREENBASE ((uchar*)KADDR(0xB8000))
+
+static int pos;
+static int screeninitdone;
+
+static uchar
+cgaregr(int index)
+{
+ outb(0x3D4, index);
+ return inb(0x3D4+1) & 0xFF;
+}
+
+static void
+cgaregw(int index, int data)
+{
+ outb(0x3D4, index);
+ outb(0x3D4+1, data);
+}
+
+static void
+movecursor(void)
+{
+ cgaregw(0x0E, (pos/2>>8) & 0xFF);
+ cgaregw(0x0F, pos/2 & 0xFF);
+ CGASCREENBASE[pos+1] = Attr;
+}
+
+static void
+cgascreenputc(int c)
+{
+ int i;
+
+ if(c == '\n'){
+ pos = pos/Width;
+ pos = (pos+1)*Width;
+ }
+ else if(c == '\t'){
+ i = 8 - ((pos/2)&7);
+ while(i-->0)
+ cgascreenputc(' ');
+ }
+ else if(c == '\b'){
+ if(pos >= 2)
+ pos -= 2;
+ cgascreenputc(' ');
+ pos -= 2;
+ }
+ else{
+ CGASCREENBASE[pos++] = c;
+ CGASCREENBASE[pos++] = Attr;
+ }
+ if(pos >= Width*Height){
+ memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
+ memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
+ pos = Width*(Height-1);
+ }
+ movecursor();
+}
+
+void
+screeninit(void)
+{
+ if(screeninitdone == 0){
+ pos = cgaregr(0x0E)<<8;
+ pos |= cgaregr(0x0F);
+ pos *= 2;
+ screeninitdone = 1;
+ }
+}
+
+void
+cgascreenputs(char* s, int n)
+{
+ if(screeninitdone == 0)
+ screeninit();
+ while(n-- > 0)
+ cgascreenputc(*s++);
+}
--- /dev/null
+++ b/os/boot.original/puma/clock.c
@@ -1,0 +1,154 @@
+#include "boot.h"
+
+ /*
+ * Control Word Read/Write Counter (mode 0) LSB, MSB
+ */
+#define PIT_RW_COUNTER0 0x30
+#define PIT_RW_COUNTER1 0x70
+#define PIT_RW_COUNTER2 0xB0
+#define PIT_COUNTERLATCH0 0x00
+#define PIT_COUNTERLATCH1 0x40
+#define PIT_COUNTERLATCH2 0x80
+
+#define PIT_MODE_0 0 /* Interrupt on Terminal Count */
+#define PIT_MODE_1 2 /* Hardware Retriggeable One-shot */
+#define PIT_MODE_2 4 /* Rate Generator */
+#define PIT_MODE_3 6 /* Square Wave Mode */
+#define PIT_MODE_4 8 /* Software Triggered Mode */
+#define PIT_MODE_5 10 /* Hardware Triggered Mode (Retriggeable) */
+
+/*
+ * Harris 82C54 Programmable Interval Timer
+ * On the Puma board the PIT is memory mapped
+ * starting at 0xf2000000 and with each of the 8-bit
+ * registers addressed on a consecutive 4-byte boundary.
+ */
+#undef inb
+#undef outb
+#define inb(port) ((*(uchar *)(port))&0xff)
+#define outb(port, data) (*(uchar *)(port) = (data))
+enum
+{
+ Cnt0= 0xf2000000, /* counter locations */
+ Cnt1= 0xf2000004, /* ... */
+ Cnt2= 0xf2000008, /* ... */
+ Ctlw= 0xf200000c, /* control word register*/
+
+ /* commands */
+ Latch0= 0x00, /* latch counter 0's value */
+ Load0= 0x30, /* load counter 0 with 2 bytes */
+ Latch1= 0x40, /* latch counter 1's value */
+ Load1= 0x70, /* load counter 1 with 2 bytes */
+
+ /* modes */
+ Square= 0x06, /* periodic square wave */
+ RateGen= 0x04, /* rate generator */
+
+ Freq= 3686400, /* Real clock frequency */
+};
+
+static int cpufreq = 233000000;
+static int aalcycles = 14;
+
+static void
+clockintr(Ureg*, void*)
+{
+ m->ticks++;
+ checkalarms();
+}
+
+/*
+ * delay for l milliseconds more or less. delayloop is set by
+ * clockinit() to match the actual CPU speed.
+ */
+void
+delay(int l)
+{
+ l *= m->delayloop;
+ if(l <= 0)
+ l = 1;
+ aamloop(l);
+}
+
+void
+microdelay(int l)
+{
+ l *= m->delayloop;
+ l /= 1000;
+ if(l <= 0)
+ l = 1;
+ aamloop(l);
+}
+
+void
+clockinit(void)
+{
+ int x, y; /* change in counter */
+ int loops, incr;
+
+ /*
+ * set vector for clock interrupts
+ */
+ setvec(V_TIMER0, clockintr, 0);
+
+ /*
+ * set clock for 1/HZ seconds
+ */
+ outb(Ctlw, Load0|Square);
+ outb(Cnt0, (Freq/HZ)); /* low byte */
+ outb(Cnt0, (Freq/HZ)>>8); /* high byte */
+
+ /* find biggest loop that doesn't wrap */
+ incr = 16000000/(aalcycles*HZ*2);
+ x = 2000;
+ for(loops = incr; loops < 64*1024; loops += incr) {
+ /*
+ * measure time for the loop
+ * TEXT aamloop(SB), $-4
+ * _aamloop:
+ * MOVW R0, R0
+ * MOVW R0, R0
+ * MOVW R0, R0
+ * SUB $1, R0
+ * CMP $0, R0
+ * BNE _aamloop
+ * RET
+ *
+ * the time for the loop should be independent of external
+ * cache and memory system since it fits in the execution
+ * prefetch buffer.
+ *
+ */
+ outb(Ctlw, Latch0);
+ x = inb(Cnt0);
+ x |= inb(Cnt0)<<8;
+ aamloop(loops);
+ outb(Ctlw, Latch0);
+ y = inb(Cnt0);
+ y |= inb(Cnt0)<<8;
+ x -= y;
+
+ if(x < 0)
+ x += Freq/HZ;
+
+ if(x > Freq/(3*HZ))
+ break;
+ }
+
+ /*
+ * counter goes at twice the frequency, once per transition,
+ * i.e., twice per square wave
+ */
+ x >>= 1;
+
+ /*
+ * figure out clock frequency and a loop multiplier for delay().
+ */
+ cpufreq = loops*((aalcycles*Freq)/x);
+ m->delayloop = (cpufreq/1000)/aalcycles; /* AAMLOOPs for 1 ms */
+
+ /*
+ * add in possible .2% error and convert to MHz
+ */
+ m->speed = (cpufreq + cpufreq/500)/1000000;
+}
--- /dev/null
+++ b/os/boot.original/puma/conf.c
@@ -1,0 +1,181 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "dosfs.h"
+
+static char *confname[MAXCONF];
+static char *confval[MAXCONF];
+static int nconf;
+
+static char* defplan9ini =
+ "ether0=type=CS8900\r\n"
+ "vgasize=640x480x8\r\n"
+ "kernelpercent=40\r\n"
+ "console=1\r\nbaud=9600\r\n"
+;
+
+extern char **ini;
+
+char*
+getconf(char *name)
+{
+ int i;
+
+ for(i = 0; i < nconf; i++)
+ if(strcmp(confname[i], name) == 0)
+ return confval[i];
+ return 0;
+}
+
+/*
+ * read configuration file
+ */
+int
+plan9ini(Dos *dos, char *val)
+{
+ Dosfile rc;
+ int i, n;
+ char *cp, *p, *q, *line[MAXCONF];
+
+ cp = BOOTARGS;
+ if(dos) {
+ if(dosstat(dos, *ini, &rc) <= 0)
+ return -1;
+
+ *cp = 0;
+ n = dosread(&rc, cp, BOOTARGSLEN-1);
+ if(n <= 0)
+ return -1;
+ cp[n] = 0;
+ } else if(val != nil){
+ if(memchr(val, 0, BOOTARGSLEN-1) == nil)
+ return -1;
+ print("Using flash configuration\n");
+ strcpy(cp, val);
+ n = strlen(cp);
+ }else{
+ print("Using default configuration\n");
+ strcpy(cp, defplan9ini);
+ n = strlen(cp);
+ }
+
+ /*
+ * Make a working copy.
+ * We could change this to pass the parsed strings
+ * to the booted programme instead of the raw
+ * string, then it only gets done once.
+ */
+ memmove(cp+BOOTARGSLEN, cp, n+1);
+ cp += BOOTARGSLEN;
+
+ /*
+ * Strip out '\r', change '\t' -> ' '.
+ */
+ p = cp;
+ for(q = cp; *q; q++){
+ if(*q == '\r')
+ continue;
+ if(*q == '\t')
+ *q = ' ';
+ *p++ = *q;
+ }
+ *p = 0;
+ n = getcfields(cp, line, MAXCONF, "\n");
+ for(i = 0; i < n; i++){
+ cp = strchr(line[i], '=');
+ if(cp == 0)
+ continue;
+ *cp++ = 0;
+ if(cp - line[i] >= NAMELEN+1)
+ *(line[i]+NAMELEN-1) = 0;
+ confname[nconf] = line[i];
+ confval[nconf] = cp;
+ nconf++;
+ }
+ return 0;
+}
+
+static int
+parseether(uchar *to, char *from)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ while(*p == ' ')
+ ++p;
+ for(i = 0; i < 6; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ char cc[NAMELEN], *p, *q, *r;
+ int n;
+
+ sprint(cc, "%s%d", class, ctlrno);
+ for(n = 0; n < nconf; n++){
+ if(strncmp(confname[n], cc, NAMELEN))
+ continue;
+ isa->nopt = 0;
+ p = confval[n];
+ while(*p){
+ while(*p == ' ' || *p == '\t')
+ p++;
+ if(*p == '\0')
+ break;
+ if(strncmp(p, "type=", 5) == 0){
+ p += 5;
+ for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
+ if(*p == '\0' || *p == ' ' || *p == '\t')
+ break;
+ *q = *p++;
+ }
+ *q = '\0';
+ }
+ else if(strncmp(p, "port=", 5) == 0)
+ isa->port = strtoul(p+5, &p, 0);
+ else if(strncmp(p, "irq=", 4) == 0)
+ isa->irq = strtoul(p+4, &p, 0);
+ else if(strncmp(p, "mem=", 4) == 0)
+ isa->mem = strtoul(p+4, &p, 0);
+ else if(strncmp(p, "size=", 5) == 0)
+ isa->size = strtoul(p+5, &p, 0);
+ else if(strncmp(p, "ea=", 3) == 0){
+ if(parseether(isa->ea, p+3) == -1)
+ memset(isa->ea, 0, 6);
+ }
+ else if(isa->nopt < NISAOPT){
+ r = isa->opt[isa->nopt];
+ while(*p && *p != ' ' && *p != '\t'){
+ *r++ = *p++;
+ if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
+ break;
+ }
+ *r = '\0';
+ isa->nopt++;
+ }
+ while(*p && *p != ' ' && *p != '\t')
+ p++;
+ }
+ return 1;
+ }
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/puma/console.c
@@ -1,0 +1,181 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+static Queue* consiq;
+static Queue* consoq;
+
+void
+bothputs(char *s, int n)
+{
+ uartputs(s, n);
+// cgascreenputs(s, n);
+}
+
+static void (*consputs)(char*, int) = 0;
+
+void
+consinit(void)
+{
+ char *p;
+ int baud, port;
+ static int cgadone;
+
+ if((p = getconf("console")) == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
+ consiq = qopen(4*1024, 0, 0, 0);
+ consoq = qopen(8*1024, 0, 0, 0);
+ consputs = uartputs;
+ if(!cgadone) {
+ cgadone = 1;
+ //screeninit();
+ //kbdinit();
+ port = 1;
+ baud = 9600;
+ uartspecial(port, baud, &consiq, &consoq, kbdchar);
+ }
+ return;
+ }
+ if(0 || strstr(p, "lcd") == 0)
+ consputs = bothputs;
+ else
+ consputs = uartputs;
+
+ port = strtoul(p, 0, 0);
+ baud = 0;
+ if(p = getconf("baud"))
+ baud = strtoul(p, 0, 0);
+ if(baud == 0)
+ baud = 9600;
+ uartspecial(port, baud, &consiq, &consoq, kbdchar);
+}
+
+void
+kbdchar(Queue *q, int c)
+{
+ c &= 0x7F;
+ if(c == 0x10)
+ panic("^p");
+ if(q == 0) {
+ if(consiq != 0)
+ qbputc(consiq, c);
+ } else
+ qbputc(q, c);
+}
+
+static int
+getline(char *buf, int size, int dotimeout)
+{
+ int c, i=0;
+ ulong start;
+ char echo;
+
+ for (;;) {
+ start = m->ticks;
+ do{
+ if(dotimeout && ((m->ticks - start) > 5*HZ))
+ return -2;
+ c = qbgetc(consiq);
+ }while(c == -1);
+ if(c == '\r')
+ c = '\n'; /* turn carriage return into newline */
+ if(c == '\177')
+ c = '\010'; /* turn delete into backspace */
+ if(c == '\025')
+ echo = '\n'; /* echo ^U as a newline */
+ else
+ echo = c;
+ (*consputs)(&echo, 1);
+
+ if(c == '\010'){
+ if(i > 0)
+ i--; /* bs deletes last character */
+ continue;
+ }
+ /* a newline ends a line */
+ if (c == '\n')
+ break;
+ /* ^U wipes out the line */
+ if (c =='\025')
+ return -1;
+ if(i == size)
+ return size;
+ buf[i++] = c;
+ }
+ buf[i] = 0;
+ return i;
+}
+
+int
+getstr(char *prompt, char *buf, int size, char *def)
+{
+ int len, isdefault;
+
+ buf[0] = 0;
+ isdefault = (def && *def);
+ for (;;) {
+ if(isdefault)
+ print("%s[default==%s]: ", prompt, def);
+ else
+ print("%s: ", prompt);
+ len = getline(buf, size, isdefault);
+ switch(len){
+ case -1:
+ /* ^U typed */
+ continue;
+ case -2:
+ /* timeout, use default */
+ (*consputs)("\n", 1);
+ len = 0;
+ break;
+ default:
+ break;
+ }
+ if(len >= size){
+ print("line too long\n");
+ continue;
+ }
+ break;
+ }
+ if(len == 0 && isdefault)
+ strcpy(buf, def);
+ return 0;
+}
+
+int
+sprint(char *s, char *fmt, ...)
+{
+ return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
+}
+
+int
+print(char *fmt, ...)
+{
+ char buf[PRINTSIZE];
+ int n;
+
+ if(consputs == 0)
+ return 0;
+ n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+ (*consputs)(buf, n);
+ return n;
+}
+
+void
+panic(char *fmt, ...)
+{
+ char buf[PRINTSIZE];
+ int n;
+
+ if(consputs){
+ (*consputs)("panic: ", 7);
+ n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+ (*consputs)(buf, n);
+ (*consputs)("\n", 1);
+ }
+ spllo();
+ for(;;)
+ idle();
+}
--- /dev/null
+++ b/os/boot.original/puma/dat.h
@@ -1,0 +1,205 @@
+typedef struct Block Block;
+typedef struct Queue Queue;
+
+typedef struct List {
+ void *next;
+} List;
+
+typedef struct {
+ int fake;
+ int pri;
+} Lock;
+#define lock(x)
+#define unlock(x)
+
+typedef struct Alarm {
+ List;
+ int busy;
+ long dt;
+ void (*f)(void*);
+ void *arg;
+} Alarm;
+
+enum {
+ Eaddrlen = 6,
+ ETHERMINTU = 60, /* minimum transmit size */
+ ETHERMAXTU = 1514, /* maximum transmit size */
+ ETHERHDRSIZE = 14, /* size of an ethernet header */
+
+ MaxEther = 2,
+};
+
+typedef struct {
+ uchar d[Eaddrlen];
+ uchar s[Eaddrlen];
+ uchar type[2];
+ uchar data[1500];
+ uchar crc[4];
+} Etherpkt;
+
+extern uchar broadcast[Eaddrlen];
+
+enum {
+ Npart = 20+2, /* 8 sub partitions, disk, and partition */
+ Maxxfer = 16*1024, /* maximum transfer size/cmd */
+};
+
+typedef struct {
+ ulong start;
+ ulong end;
+ char name[NAMELEN+1];
+} Partition;
+
+typedef struct {
+ int online;
+ int npart; /* number of real partitions */
+ Partition p[Npart];
+ ulong offset;
+ Partition *current; /* current partition */
+
+ ulong cap; /* total bytes */
+ int bytes; /* bytes/sector */
+ int sectors; /* sectors/track */
+ int heads; /* heads/cyl */
+ long cyl; /* cylinders/drive */
+
+ char lba; /* true if drive has logical block addressing */
+ char multi; /* non-zero if drive does multiple block xfers */
+} Disc;
+
+enum {
+ ScsiTestunit = 0x00,
+ ScsiExtsens = 0x03,
+ ScsiInquiry = 0x12,
+ ScsiModesense = 0x1a,
+ ScsiStartunit = 0x1B,
+ ScsiStopunit = 0x1B,
+ ScsiGetcap = 0x25,
+ ScsiRead = 0x08,
+ ScsiWrite = 0x0a,
+ ScsiExtread = 0x28,
+ ScsiExtwrite = 0x2a,
+
+ /* data direction */
+ ScsiIn = 1,
+ ScsiOut = 0,
+};
+
+typedef struct Scsibuf Scsibuf;
+typedef struct Scsibuf {
+ void* virt;
+ void* phys;
+ Scsibuf* next;
+};
+
+typedef struct Scsidata {
+ uchar* base;
+ uchar* lim;
+ uchar* ptr;
+} Scsidata;
+
+typedef struct Ureg Ureg;
+
+typedef struct Scsi {
+ ulong pid;
+ ushort target;
+ ushort lun;
+ ushort rflag;
+ ushort status;
+ Scsidata cmd;
+ Scsidata data;
+ Scsibuf* b;
+ uchar* save;
+ uchar cmdblk[16];
+} Scsi;
+
+typedef struct Segdesc {
+ ulong d0;
+ ulong d1;
+} Segdesc;
+
+typedef struct Mach {
+ ulong ticks; /* of the clock since boot time */
+ ulong delayloop;
+ int speed; /* general system clock in MHz */
+ int oscclk; /* oscillator frequency in MHz */
+ void* alarm; /* alarms bound to this clock */
+} Mach;
+
+extern Mach *m;
+
+#define E_MAGIC ((((4*20)+0)*20)+7)
+
+typedef struct Exec Exec;
+struct Exec
+{
+ uchar magic[4]; /* magic number */
+ uchar text[4]; /* size of text segment */
+ uchar data[4]; /* size of initialized data */
+ uchar bss[4]; /* size of uninitialized data */
+ uchar syms[4]; /* size of symbol table */
+ uchar entry[4]; /* entry point */
+ uchar spsz[4]; /* size of sp/pc offset table */
+ uchar pcsz[4]; /* size of pc/line number table */
+};
+
+/*
+ * bootline passed by boot program
+ */
+#define BOOTLINE ((char *)0x18000-150)
+
+/*
+ * Where we leave configuration info.
+ */
+#define BOOTARGS ((char*)(0x18000))
+#define BOOTARGSLEN 1024
+#define MAXCONF 32
+
+/*
+ * a parsed plan9.ini line
+ */
+#define ISAOPTLEN 16
+#define NISAOPT 8
+
+typedef struct ISAConf {
+ char type[NAMELEN];
+ ulong port;
+ ulong irq;
+ ulong mem;
+ ulong size;
+ uchar ea[6];
+
+ int nopt;
+ char opt[NISAOPT][ISAOPTLEN];
+} ISAConf;
+
+typedef struct {
+ int size;
+ ulong addr;
+} Map;
+
+typedef struct {
+ char* name;
+ Map* map;
+ Map* mapend;
+
+ Lock;
+} RMap;
+
+typedef struct PCIcfg PCIcfg;
+
+extern uchar* vgamem;
+
+struct Block {
+ uchar *rp;
+ uchar *wp;
+ uchar *lim;
+ uchar *data;
+ Block* next;
+ ulong magic;
+};
+#define BLEN(b) ((b)->wp-(b)->rp)
+
+typedef struct QLock {
+ int dummy;
+} QLock;
--- /dev/null
+++ b/os/boot.original/puma/div.s
@@ -1,0 +1,122 @@
+/*
+ * Div/Mod taken from the Inferno 2.0 ebsit code
+ */
+
+Q = 0
+N = 1
+D = 2
+CC = 3
+TMP = 11
+
+TEXT save<>(SB), 1, $0
+ MOVW R(Q), 0(FP)
+ MOVW R(N), 4(FP)
+ MOVW R(D), 8(FP)
+ MOVW R(CC), 12(FP)
+
+ MOVW R(TMP), R(Q) /* numerator */
+ MOVW 20(FP), R(D) /* denominator */
+ CMP $0, R(D)
+ BNE s1
+ MOVW -1(R(D)), R(TMP) /* divide by zero fault */
+s1: RET
+
+TEXT rest<>(SB), 1, $0
+ MOVW 0(FP), R(Q)
+ MOVW 4(FP), R(N)
+ MOVW 8(FP), R(D)
+ MOVW 12(FP), R(CC)
+/*
+ * return to caller
+ * of rest<>
+ */
+ MOVW 0(R13), R14
+ ADD $20, R13
+ B (R14)
+
+TEXT div<>(SB), 1, $0
+ MOVW $32, R(CC)
+/*
+ * skip zeros 8-at-a-time
+ */
+e1:
+ AND.S $(0xff<<24),R(Q), R(N)
+ BNE e2
+ SLL $8, R(Q)
+ SUB.S $8, R(CC)
+ BNE e1
+ RET
+e2:
+ MOVW $0, R(N)
+
+loop:
+/*
+ * shift R(N||Q) left one
+ */
+ SLL $1, R(N)
+ CMP $0, R(Q)
+ ORR.LT $1, R(N)
+ SLL $1, R(Q)
+
+/*
+ * compare numerator to denominator
+ * if less, subtract and set quotent bit
+ */
+ CMP R(D), R(N)
+ ORR.HS $1, R(Q)
+ SUB.HS R(D), R(N)
+ SUB.S $1, R(CC)
+ BNE loop
+ RET
+
+TEXT _div(SB), 1, $16
+ BL save<>(SB)
+ CMP $0, R(Q)
+ BGE d1
+ RSB $0, R(Q), R(Q)
+ CMP $0, R(D)
+ BGE d2
+ RSB $0, R(D), R(D)
+d0:
+ BL div<>(SB) /* none/both neg */
+ MOVW R(Q), R(TMP)
+ B out
+d1:
+ CMP $0, R(D)
+ BGE d0
+ RSB $0, R(D), R(D)
+d2:
+ BL div<>(SB) /* one neg */
+ RSB $0, R(Q), R(TMP)
+ B out
+
+TEXT _mod(SB), 1, $16
+ BL save<>(SB)
+ CMP $0, R(D)
+ RSB.LT $0, R(D), R(D)
+ CMP $0, R(Q)
+ BGE m1
+ RSB $0, R(Q), R(Q)
+ BL div<>(SB) /* neg numerator */
+ RSB $0, R(N), R(TMP)
+ B out
+m1:
+ BL div<>(SB) /* pos numerator */
+ MOVW R(N), R(TMP)
+ B out
+
+TEXT _divu(SB), 1, $16
+ BL save<>(SB)
+ BL div<>(SB)
+ MOVW R(Q), R(TMP)
+ B out
+
+TEXT _modu(SB), 1, $16
+ BL save<>(SB)
+ BL div<>(SB)
+ MOVW R(N), R(TMP)
+ B out
+
+out:
+ BL rest<>(SB)
+ B out
--- /dev/null
+++ b/os/boot.original/puma/donprint.c
@@ -1,0 +1,332 @@
+#include "u.h"
+#include "lib.h"
+
+#define PTR sizeof(char*)
+#define SHORT sizeof(int)
+#define INT sizeof(int)
+#define LONG sizeof(long)
+#define IDIGIT 30
+#define MAXCON 30
+
+#define FLONG (1<<0)
+#define FSHORT (1<<1)
+#define FUNSIGN (1<<2)
+
+typedef struct Op Op;
+struct Op
+{
+ char *p;
+ char *ep;
+ void *argp;
+ int f1;
+ int f2;
+ int f3;
+};
+
+static int noconv(Op*);
+static int cconv(Op*);
+static int dconv(Op*);
+static int hconv(Op*);
+static int lconv(Op*);
+static int oconv(Op*);
+static int sconv(Op*);
+static int uconv(Op*);
+static int xconv(Op*);
+static int Xconv(Op*);
+static int percent(Op*);
+
+static
+int (*fmtconv[MAXCON])(Op*) =
+{
+ noconv,
+ cconv, dconv, hconv, lconv,
+ oconv, sconv, uconv, xconv,
+ Xconv, percent,
+};
+static
+char fmtindex[128] =
+{
+ ['c'] 1,
+ ['d'] 2,
+ ['h'] 3,
+ ['l'] 4,
+ ['o'] 5,
+ ['s'] 6,
+ ['u'] 7,
+ ['x'] 8,
+ ['X'] 9,
+ ['%'] 10,
+};
+
+static int convcount = { 11 };
+static int ucase;
+
+static void
+PUT(Op *o, int c)
+{
+ static int pos;
+ int opos;
+
+ if(c == '\t'){
+ opos = pos;
+ pos = (opos+8) & ~7;
+ while(opos++ < pos && o->p < o->ep)
+ *o->p++ = ' ';
+ return;
+ }
+ if(o->p < o->ep){
+ *o->p++ = c;
+ pos++;
+ }
+ if(c == '\n')
+ pos = 0;
+}
+
+int
+fmtinstall(char c, int (*f)(Op*))
+{
+
+ c &= 0177;
+ if(fmtindex[c] == 0) {
+ if(convcount >= MAXCON)
+ return 1;
+ fmtindex[c] = convcount++;
+ }
+ fmtconv[fmtindex[c]] = f;
+ return 0;
+}
+
+char*
+donprint(char *p, char *ep, char *fmt, void *argp)
+{
+ int sf1, c;
+ Op o;
+
+ o.p = p;
+ o.ep = ep;
+ o.argp = argp;
+
+loop:
+ c = *fmt++;
+ if(c != '%') {
+ if(c == 0) {
+ if(o.p < o.ep)
+ *o.p = 0;
+ return o.p;
+ }
+ PUT(&o, c);
+ goto loop;
+ }
+ o.f1 = 0;
+ o.f2 = -1;
+ o.f3 = 0;
+ c = *fmt++;
+ sf1 = 0;
+ if(c == '-') {
+ sf1 = 1;
+ c = *fmt++;
+ }
+ while(c >= '0' && c <= '9') {
+ o.f1 = o.f1*10 + c-'0';
+ c = *fmt++;
+ }
+ if(sf1)
+ o.f1 = -o.f1;
+ if(c != '.')
+ goto l1;
+ c = *fmt++;
+ while(c >= '0' && c <= '9') {
+ if(o.f2 < 0)
+ o.f2 = 0;
+ o.f2 = o.f2*10 + c-'0';
+ c = *fmt++;
+ }
+l1:
+ if(c == 0)
+ fmt--;
+ c = (*fmtconv[fmtindex[c&0177]])(&o);
+ if(c < 0) {
+ o.f3 |= -c;
+ c = *fmt++;
+ goto l1;
+ }
+ o.argp = (char*)o.argp + c;
+ goto loop;
+}
+
+void
+strconv(char *o, Op *op, int f1, int f2)
+{
+ int n, c;
+ char *p;
+
+ n = strlen(o);
+ if(f1 >= 0)
+ while(n < f1) {
+ PUT(op, ' ');
+ n++;
+ }
+ for(p=o; c = *p++;)
+ if(f2 != 0) {
+ PUT(op, c);
+ f2--;
+ }
+ if(f1 < 0) {
+ f1 = -f1;
+ while(n < f1) {
+ PUT(op, ' ');
+ n++;
+ }
+ }
+}
+
+int
+numbconv(Op *op, int base)
+{
+ char b[IDIGIT];
+ int i, f, n, r;
+ long v;
+ short h;
+
+ f = 0;
+ switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
+ case FLONG:
+ v = *(long*)op->argp;
+ r = LONG;
+ break;
+
+ case FUNSIGN|FLONG:
+ v = *(ulong*)op->argp;
+ r = LONG;
+ break;
+
+ case FSHORT:
+ h = *(int*)op->argp;
+ v = h;
+ r = SHORT;
+ break;
+
+ case FUNSIGN|FSHORT:
+ h = *(int*)op->argp;
+ v = (ushort)h;
+ r = SHORT;
+ break;
+
+ default:
+ v = *(int*)op->argp;
+ r = INT;
+ break;
+
+ case FUNSIGN:
+ v = *(unsigned*)op->argp;
+ r = INT;
+ break;
+ }
+ if(!(op->f3 & FUNSIGN) && v < 0) {
+ v = -v;
+ f = 1;
+ }
+ b[IDIGIT-1] = 0;
+ for(i = IDIGIT-2;; i--) {
+ n = (ulong)v % base;
+ n += '0';
+ if(n > '9'){
+ n += 'a' - ('9'+1);
+ if(ucase)
+ n += 'A'-'a';
+ }
+ b[i] = n;
+ if(i < 2)
+ break;
+ v = (ulong)v / base;
+ if(op->f2 >= 0 && i >= IDIGIT-op->f2)
+ continue;
+ if(v <= 0)
+ break;
+ }
+ if(f)
+ b[--i] = '-';
+ strconv(b+i, op, op->f1, -1);
+ return r;
+}
+
+static int
+noconv(Op *op)
+{
+
+ strconv("***", op, 0, -1);
+ return 0;
+}
+
+static int
+cconv(Op *op)
+{
+ char b[2];
+
+ b[0] = *(int*)op->argp;
+ b[1] = 0;
+ strconv(b, op, op->f1, -1);
+ return INT;
+}
+
+static int
+dconv(Op *op)
+{
+ return numbconv(op, 10);
+}
+
+static int
+hconv(Op*)
+{
+ return -FSHORT;
+}
+
+static int
+lconv(Op*)
+{
+ return -FLONG;
+}
+
+static int
+oconv(Op *op)
+{
+ return numbconv(op, 8);
+}
+
+static int
+sconv(Op *op)
+{
+ strconv(*(char**)op->argp, op, op->f1, op->f2);
+ return PTR;
+}
+
+static int
+uconv(Op*)
+{
+ return -FUNSIGN;
+}
+
+static int
+xconv(Op *op)
+{
+ return numbconv(op, 16);
+}
+
+static int
+Xconv(Op *op)
+{
+ int r;
+
+ ucase = 1;
+ r = numbconv(op, 16);
+ ucase = 0;
+ return r;
+}
+
+static int
+percent(Op *op)
+{
+
+ PUT(op, '%');
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/puma/dosboot.c
@@ -1,0 +1,614 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "dosfs.h"
+
+extern char *premature;
+
+/*
+ * predeclared
+ */
+static void bootdump(Dosboot*);
+static void setname(Dosfile*, char*);
+long dosreadseg(Dosfile*, long, long);
+
+/*
+ * debugging
+ */
+#define chatty 1
+#define chat if(chatty)print
+
+/*
+ * block io buffers
+ */
+enum
+{
+ Nbio= 16,
+};
+typedef struct Clustbuf Clustbuf;
+struct Clustbuf
+{
+ int age;
+ long sector;
+ uchar *iobuf;
+ Dos *dos;
+ int size;
+};
+Clustbuf bio[Nbio];
+
+/*
+ * get an io block from an io buffer
+ */
+Clustbuf*
+getclust(Dos *dos, long sector)
+{
+ Clustbuf *p, *oldest;
+ int size;
+
+ chat("getclust @ %d\n", sector);
+
+ /*
+ * if we have it, just return it
+ */
+ for(p = bio; p < &bio[Nbio]; p++){
+ if(sector == p->sector && dos == p->dos){
+ p->age = m->ticks;
+ chat("getclust %d in cache\n", sector);
+ return p;
+ }
+ }
+
+ /*
+ * otherwise, reuse the oldest entry
+ */
+ oldest = bio;
+ for(p = &bio[1]; p < &bio[Nbio]; p++){
+ if(p->age <= oldest->age)
+ oldest = p;
+ }
+ p = oldest;
+
+ /*
+ * make sure the buffer is big enough
+ */
+ size = dos->clustsize*dos->sectsize;
+ if(p->iobuf==0 || p->size < size)
+ p->iobuf = ialloc(size, 0);
+ p->size = size;
+
+ /*
+ * read in the cluster
+ */
+ chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
+ if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
+ chat("can't seek block\n");
+ return 0;
+ }
+ if((*dos->read)(dos->dev, p->iobuf, size) != size){
+ chat("can't read block\n");
+ return 0;
+ }
+
+ p->age = m->ticks;
+ p->dos = dos;
+ p->sector = sector;
+ chat("getclust %d read\n", sector);
+ return p;
+}
+
+/*
+ * walk the fat one level ( n is a current cluster number ).
+ * return the new cluster number or -1 if no more.
+ */
+static long
+fatwalk(Dos *dos, int n)
+{
+ ulong k, sect;
+ Clustbuf *p;
+ int o;
+
+ chat("fatwalk %d\n", n);
+
+ if(n < 2 || n >= dos->fatclusters)
+ return -1;
+
+ switch(dos->fatbits){
+ case 12:
+ k = (3*n)/2; break;
+ case 16:
+ k = 2*n; break;
+ default:
+ return -1;
+ }
+ if(k >= dos->fatsize*dos->sectsize)
+ panic("getfat");
+
+ sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
+ o = k%(dos->sectsize*dos->clustsize);
+ p = getclust(dos, sect);
+ k = p->iobuf[o++];
+ if(o >= dos->sectsize*dos->clustsize){
+ p = getclust(dos, sect+dos->clustsize);
+ o = 0;
+ }
+ k |= p->iobuf[o]<<8;
+ if(dos->fatbits == 12){
+ if(n&1)
+ k >>= 4;
+ else
+ k &= 0xfff;
+ if(k >= 0xff8)
+ k |= 0xf000;
+ }
+ k = k < 0xfff8 ? k : -1;
+ chat("fatwalk %d -> %d\n", n, k);
+ return k;
+}
+
+/*
+ * map a file's logical cluster address to a physical sector address
+ */
+static long
+fileaddr(Dosfile *fp, long ltarget)
+{
+ Dos *dos = fp->dos;
+ long l;
+ long p;
+
+ chat("fileaddr %8.8s %d\n", fp->name, ltarget);
+ /*
+ * root directory is contiguous and easy
+ */
+ if(fp->pstart == 0){
+ if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
+ return -1;
+ l = dos->rootaddr + ltarget*dos->clustsize;
+ chat("fileaddr %d -> %d\n", ltarget, l);
+ return l;
+ }
+
+ /*
+ * anything else requires a walk through the fat
+ */
+ if(ltarget >= fp->lcurrent && fp->pcurrent){
+ /* start at the currrent point */
+ l = fp->lcurrent;
+ p = fp->pcurrent;
+ } else {
+ /* go back to the beginning */
+ l = 0;
+ p = fp->pstart;
+ }
+ while(l != ltarget){
+ /* walk the fat */
+ p = fatwalk(dos, p);
+ if(p < 0)
+ return -1;
+ l++;
+ }
+ fp->lcurrent = l;
+ fp->pcurrent = p;
+
+ /*
+ * clusters start at 2 instead of 0 (why? - presotto)
+ */
+ l = dos->dataaddr + (p-2)*dos->clustsize;
+ chat("fileaddr %d -> %d\n", ltarget, l);
+ return l;
+}
+
+/*
+ * read from a dos file
+ */
+long
+dosread(Dosfile *fp, void *a, long n)
+{
+ long addr;
+ long rv;
+ int i;
+ int off;
+ Clustbuf *p;
+ uchar *from, *to;
+
+ if((fp->attr & DDIR) == 0){
+ if(fp->offset >= fp->length)
+ return 0;
+ if(fp->offset+n > fp->length)
+ n = fp->length - fp->offset;
+ }
+
+ to = a;
+ for(rv = 0; rv < n; rv+=i){
+ /*
+ * read the cluster
+ */
+ addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
+ if(addr < 0)
+ return -1;
+ p = getclust(fp->dos, addr);
+ if(p == 0)
+ return -1;
+
+ /*
+ * copy the bytes we need
+ */
+ off = fp->offset % fp->dos->clustbytes;
+ from = &p->iobuf[off];
+ i = n - rv;
+ if(i > fp->dos->clustbytes - off)
+ i = fp->dos->clustbytes - off;
+ memmove(to, from, i);
+ to += i;
+ fp->offset += i;
+ }
+
+ return rv;
+}
+
+/*
+ * walk a directory returns
+ * -1 if something went wrong
+ * 0 if not found
+ * 1 if found
+ */
+int
+doswalk(Dosfile *file, char *name)
+{
+ Dosdir d;
+ long n;
+
+ if((file->attr & DDIR) == 0){
+ chat("walking non-directory!\n");
+ return -1;
+ }
+
+ setname(file, name);
+
+ file->offset = 0; /* start at the beginning */
+ while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
+ chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
+ if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
+ continue;
+ if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
+ continue;
+ if(d.attr & DVLABEL){
+ chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
+ continue;
+ }
+ file->attr = d.attr;
+ file->pstart = GSHORT(d.start);
+ file->length = GLONG(d.length);
+ file->pcurrent = 0;
+ file->lcurrent = 0;
+ file->offset = 0;
+ return 1;
+ }
+ return n >= 0 ? 0 : -1;
+}
+
+
+/*
+ * instructions that boot blocks can start with
+ */
+#define JMPSHORT 0xeb
+#define JMPNEAR 0xe9
+
+/*
+ * read dos file system properties
+ */
+int
+dosinit(Dos *dos, int start, int ishard)
+{
+ Dosboot *b;
+ int i;
+ Clustbuf *p;
+ Dospart *dp;
+ ulong mbroffset, offset;
+
+ /* defaults till we know better */
+ dos->start = start;
+ dos->sectsize = 512;
+ dos->clustsize = 1;
+ mbroffset = 0;
+
+dmddo:
+ /* get first sector */
+ p = getclust(dos, mbroffset);
+ if(p == 0){
+ chat("can't read boot block\n");
+ return -1;
+ }
+
+ /*
+ * If it's a hard disc then look for an MBR and pick either an
+ * active partition or the FAT with the lowest starting LBA.
+ * Things are tricky because we could be pointing to, amongst others:
+ * 1) a floppy BPB;
+ * 2) a hard disc MBR;
+ * 3) a hard disc extended partition table;
+ * 4) a logical drive on a hard disc;
+ * 5) a disc-manager boot block.
+ * They all have the same magic at the end of the block.
+ */
+ if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
+ chat("not DOS\n");
+ return -1;
+ }
+ p->dos = 0;
+ b = (Dosboot *)p->iobuf;
+ if(ishard && b->mediadesc != 0xF8){
+ dp = (Dospart*)&p->iobuf[0x1BE];
+ offset = 0xFFFFFFFF;
+ for(i = 0; i < 4; i++, dp++){
+ if(dp->type == DMDDO){
+ mbroffset = 63;
+ goto dmddo;
+ }
+ if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
+ continue;
+ if(dp->flag & 0x80){
+ offset = GLONG(dp->start);
+ break;
+ }
+ if(GLONG(dp->start) < offset)
+ offset = GLONG(dp->start);
+ }
+ if(i != 4 || offset != 0xFFFFFFFF){
+ dos->start = mbroffset+offset;
+ p = getclust(dos, 0);
+ if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
+ return -1;
+ }
+ p->dos = 0;
+ }
+
+ b = (Dosboot *)p->iobuf;
+ if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
+ chat("no dos file system\n");
+ return -1;
+ }
+
+ if(chatty)
+ bootdump(b);
+
+ /*
+ * determine the systems' wondersous properties
+ */
+ dos->sectsize = GSHORT(b->sectsize);
+ dos->clustsize = b->clustsize;
+ dos->clustbytes = dos->sectsize*dos->clustsize;
+ dos->nresrv = GSHORT(b->nresrv);
+ dos->nfats = b->nfats;
+ dos->rootsize = GSHORT(b->rootsize);
+ dos->volsize = GSHORT(b->volsize);
+ if(dos->volsize == 0)
+ dos->volsize = GLONG(b->bigvolsize);
+ dos->mediadesc = b->mediadesc;
+ dos->fatsize = GSHORT(b->fatsize);
+ dos->fataddr = dos->nresrv;
+ dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
+ i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
+ i = i/dos->sectsize;
+ dos->dataaddr = dos->rootaddr + i;
+ dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
+ if(dos->fatclusters < 4087)
+ dos->fatbits = 12;
+ else
+ dos->fatbits = 16;
+ dos->freeptr = 2;
+
+ /*
+ * set up the root
+ */
+ dos->root.dos = dos;
+ dos->root.pstart = 0;
+ dos->root.pcurrent = dos->root.lcurrent = 0;
+ dos->root.offset = 0;
+ dos->root.attr = DDIR;
+ dos->root.length = dos->rootsize*sizeof(Dosdir);
+
+ return 0;
+}
+
+static void
+bootdump(Dosboot *b)
+{
+ if(chatty == 0)
+ return;
+ print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
+ b->magic[0], b->magic[1], b->magic[2]);
+ print("version: \"%8.8s\"\n", b->version);
+ print("sectsize: %d\n", GSHORT(b->sectsize));
+ print("allocsize: %d\n", b->clustsize);
+ print("nresrv: %d\n", GSHORT(b->nresrv));
+ print("nfats: %d\n", b->nfats);
+ print("rootsize: %d\n", GSHORT(b->rootsize));
+ print("volsize: %d\n", GSHORT(b->volsize));
+ print("mediadesc: 0x%2.2x\n", b->mediadesc);
+ print("fatsize: %d\n", GSHORT(b->fatsize));
+ print("trksize: %d\n", GSHORT(b->trksize));
+ print("nheads: %d\n", GSHORT(b->nheads));
+ print("nhidden: %d\n", GLONG(b->nhidden));
+ print("bigvolsize: %d\n", GLONG(b->bigvolsize));
+ print("driveno: %d\n", b->driveno);
+ print("reserved0: 0x%2.2x\n", b->reserved0);
+ print("bootsig: 0x%2.2x\n", b->bootsig);
+ print("volid: 0x%8.8x\n", GLONG(b->volid));
+ print("label: \"%11.11s\"\n", b->label);
+}
+
+/*
+ * grab next element from a path, return the pointer to unprocessed portion of
+ * path.
+ */
+static char *
+nextelem(char *path, char *elem)
+{
+ int i;
+
+ while(*path == '/')
+ path++;
+ if(*path==0 || *path==' ')
+ return 0;
+ for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
+ if(i==28){
+ print("name component too long\n");
+ return 0;
+ }
+ *elem++ = *path++;
+ }
+ *elem = '\0';
+ return path;
+}
+
+int
+dosstat(Dos *dos, char *path, Dosfile *f)
+{
+ char element[NAMELEN];
+
+ *f = dos->root;
+ while(path = nextelem(path, element)){
+ switch(doswalk(f, element)){
+ case -1:
+ return -1;
+ case 0:
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * boot
+ */
+int
+dosboot(Dos *dos, char *path)
+{
+ Dosfile file;
+ long n;
+ long addr;
+ Exec *ep;
+ void (*b)(void);
+
+ switch(dosstat(dos, path, &file)){
+
+ case -1:
+ print("error walking to %s\n", path);
+ return -1;
+ case 0:
+ print("%s not found\n", path);
+ return -1;
+ case 1:
+ print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
+ file.ext, file.attr, file.pstart, file.length);
+ break;
+ }
+
+ /*
+ * read header
+ */
+ ep = (Exec*)ialloc(sizeof(Exec), 0);
+ n = sizeof(Exec);
+ if(dosreadseg(&file, n, (ulong) ep) != n){
+ print(premature);
+ return -1;
+ }
+ if(GLLONG(ep->magic) != E_MAGIC){
+ print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+ return -1;
+ }
+
+ /*
+ * read text
+ */
+ addr = PADDR(GLLONG(ep->entry));
+ n = GLLONG(ep->text);
+ print("+%d", n);
+ if(dosreadseg(&file, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * read data (starts at first page after kernel)
+ */
+ addr = PGROUND(addr+n);
+ n = GLLONG(ep->data);
+ print("+%d", n);
+ if(dosreadseg(&file, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * bss and entry point
+ */
+ print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
+
+ /*
+ * Go to new code. It's up to the program to get its PC relocated to
+ * the right place.
+ */
+ b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+ (*b)();
+ return 0;
+}
+
+/*
+ * read in a segment
+ */
+long
+dosreadseg(Dosfile *fp, long len, long addr)
+{
+ char *a;
+ long n, sofar;
+
+ a = (char *)addr;
+ for(sofar = 0; sofar < len; sofar += n){
+ n = 8*1024;
+ if(len - sofar < n)
+ n = len - sofar;
+ n = dosread(fp, a + sofar, n);
+ if(n <= 0)
+ break;
+ print(".");
+ }
+ return sofar;
+}
+
+/*
+ * set up a dos file name
+ */
+static void
+setname(Dosfile *fp, char *from)
+{
+ char *to;
+
+ to = fp->name;
+ for(; *from && to-fp->name < 8; from++, to++){
+ if(*from == '.'){
+ from++;
+ break;
+ }
+ if(*from >= 'a' && *from <= 'z')
+ *to = *from + 'A' - 'a';
+ else
+ *to = *from;
+ }
+ while(to - fp->name < 8)
+ *to++ = ' ';
+
+ to = fp->ext;
+ for(; *from && to-fp->ext < 3; from++, to++){
+ if(*from >= 'a' && *from <= 'z')
+ *to = *from + 'A' - 'a';
+ else
+ *to = *from;
+ }
+ while(to-fp->ext < 3)
+ *to++ = ' ';
+
+ chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
+}
--- /dev/null
+++ b/os/boot.original/puma/dosfs.h
@@ -1,0 +1,110 @@
+typedef struct Dosboot Dosboot;
+typedef struct Dos Dos;
+typedef struct Dosdir Dosdir;
+typedef struct Dosfile Dosfile;
+typedef struct Dospart Dospart;
+
+struct Dospart
+{
+ uchar flag; /* active flag */
+ uchar shead; /* starting head */
+ uchar scs[2]; /* starting cylinder/sector */
+ uchar type; /* partition type */
+ uchar ehead; /* ending head */
+ uchar ecs[2]; /* ending cylinder/sector */
+ uchar start[4]; /* starting sector */
+ uchar len[4]; /* length in sectors */
+};
+
+#define FAT12 0x01
+#define FAT16 0x04
+#define FATHUGE 0x06
+#define DMDDO 0x54
+
+struct Dosboot{
+ uchar magic[3];
+ uchar version[8];
+ uchar sectsize[2];
+ uchar clustsize;
+ uchar nresrv[2];
+ uchar nfats;
+ uchar rootsize[2];
+ uchar volsize[2];
+ uchar mediadesc;
+ uchar fatsize[2];
+ uchar trksize[2];
+ uchar nheads[2];
+ uchar nhidden[4];
+ uchar bigvolsize[4];
+ uchar driveno;
+ uchar reserved0;
+ uchar bootsig;
+ uchar volid[4];
+ uchar label[11];
+ uchar reserved1[8];
+};
+
+struct Dosfile{
+ Dos *dos; /* owning dos file system */
+ char name[8];
+ char ext[3];
+ uchar attr;
+ long length;
+ long pstart; /* physical start cluster address */
+ long pcurrent; /* physical current cluster address */
+ long lcurrent; /* logical current cluster address */
+ long offset;
+};
+
+struct Dos{
+ int dev; /* device id */
+ long (*read)(int, void*, long); /* read routine */
+ long (*seek)(int, long); /* seek routine */
+
+ int start; /* start of file system */
+ int sectsize; /* in bytes */
+ int clustsize; /* in sectors */
+ int clustbytes; /* in bytes */
+ int nresrv; /* sectors */
+ int nfats; /* usually 2 */
+ int rootsize; /* number of entries */
+ int volsize; /* in sectors */
+ int mediadesc;
+ int fatsize; /* in sectors */
+ int fatclusters;
+ int fatbits; /* 12 or 16 */
+ long fataddr; /* sector number */
+ long rootaddr;
+ long dataaddr;
+ long freeptr;
+
+ Dosfile root;
+};
+
+struct Dosdir{
+ uchar name[8];
+ uchar ext[3];
+ uchar attr;
+ uchar reserved[10];
+ uchar time[2];
+ uchar date[2];
+ uchar start[2];
+ uchar length[4];
+};
+
+#define DRONLY 0x01
+#define DHIDDEN 0x02
+#define DSYSTEM 0x04
+#define DVLABEL 0x08
+#define DDIR 0x10
+#define DARCH 0x20
+
+extern int chatty;
+
+extern int dosboot(Dos*, char*);
+extern int dosinit(Dos*, int, int);
+extern long dosread(Dosfile*, void*, long);
+extern int dosstat(Dos*, char*, Dosfile*);
+extern int doswalk(Dosfile*, char*);
+
+extern int plan9ini(Dos*, char*);
--- /dev/null
+++ b/os/boot.original/puma/ebsit.trap.c
@@ -1,0 +1,206 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "ebsit.h"
+#include "dat.h"
+#include "fns.h"
+
+#include "ureg.h"
+
+int inpanic;
+
+#define CSR ((ushort *) 0x2000000)
+
+
+typedef struct Irqctlr {
+ uint addr;
+ uint enabled;
+ struct {
+ void (*r)(Ureg*, void*);
+ void *a;
+ } h[16];
+} Irqctlr;
+
+static Irqctlr irqctlr;
+
+void
+csrset( int bit )
+{
+static ushort *csr_val = 0x8c;
+
+ *csr_val ^= (1 << bit);
+ putcsr(*csr_val);
+}
+
+void
+intrinit( void )
+{
+int offset;
+ulong op;
+
+
+ irqctlr.addr = 1;
+ irqctlr.enabled = 0;
+
+ /* Reset Exception */
+ offset = ((((ulong) _vsvccall) - 0x0)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0x0) = op;
+
+ /* Undefined Instruction Exception */
+ offset = ((((ulong) _vundcall) - 0x4)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0x4) = op;
+
+ /* SWI Exception */
+ offset = ((((ulong) _vsvccall) - 0x8)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0x8) = op;
+
+ /* Prefetch Abort Exception */
+ offset = ((((ulong) _vpabcall) - 0xc)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0xc) = op;
+
+ /* Data Abort Exception */
+ offset = ((((ulong) _vdabcall) - 0x10)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0x10) = op;
+
+ /* IRQ Exception */
+ offset = ((((ulong) _virqcall) - 0x18)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0x18) = op;
+
+
+}
+
+void
+intrenable(uint addr, int bit, void (*r)(Ureg*, void*), void* a)
+{
+ int i;
+ USED(addr);
+ for(i = 0; i < 16; i++)
+ {
+ if((bit & (1<<i)) == 0)
+ continue;
+ irqctlr.h[i].r = r;
+ irqctlr.h[i].a = a;
+ irqctlr.enabled |= (1<<i);
+ if (i < 7)
+ csrset(i);
+ }
+ return;
+}
+
+int lucifer; /* Global to store the last CSR (eric) */
+
+static void
+interrupt(Ureg* ureg)
+{
+ int i, mask;
+
+ mask = *CSR;
+ lucifer = mask; /* eric */
+ if(irqctlr.enabled == 0){
+
+ return;
+ }
+ for(i = 0; i < 16; i++)
+ {
+
+ if((irqctlr.enabled & (1<<i)) == 0)
+ continue;
+ if(( mask & (1 << i)) == 0)
+ continue;
+ if (!irqctlr.h[i].r)
+ continue;
+ (irqctlr.h[i].r)(ureg, irqctlr.h[i].a);
+ mask &= ~(1 << i);
+ }
+
+ if ((mask) && (mask < 0x90)) /* ignore non-maskable interrupts */
+ {
+ print("unknown or unhandled interrupt\n");
+ panic("unknown or unhandled interrupt: mask=%ux",mask);
+ }
+
+}
+
+static void
+dumpregs(Ureg* ureg)
+{
+ print("PSR %8.8uX type %2.2uX PC %8.8uX LINK %8.8uX\n",
+ ureg->psr, ureg->type, ureg->pc, ureg->link);
+ print("R14 %8.8uX R13 %8.8uX R12 %8.8uX R11 %8.8uX R10 %8.8uX\n",
+ ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
+ print("R9 %8.8uX R8 %8.8uX R7 %8.8uX R6 %8.8uX R5 %8.8uX\n",
+ ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
+ print("R4 %8.8uX R3 %8.8uX R2 %8.8uX R1 %8.8uX R0 %8.8uX\n",
+ ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
+ print("Last Interrupt's CSR: %8.8uX\n",lucifer);
+ print("CPSR %8.8uX SPSR %8.8uX\n", cpsrr(), spsrr());
+}
+
+void
+dumpstack(void)
+{
+}
+
+void
+exception(Ureg* ureg)
+{
+ static Ureg old_ureg;
+ uint far =0;
+ uint fsr =0;
+
+ static lasttype = 0;
+
+ LOWBAT;
+
+ USED(far, fsr);
+
+ lasttype = ureg->type;
+
+ /*
+ * All interrupts/exceptions should be resumed at ureg->pc-4,
+ * except for Data Abort which resumes at ureg->pc-8.
+ */
+
+ if(ureg->type == (PsrMabt+1))
+ ureg->pc -= 8;
+ else
+ ureg->pc -= 4;
+
+ switch(ureg->type){
+
+ case PsrMfiq: /* (Fast) */
+ print("Fast\n");
+ print("We should never be here\n");
+ while(1);
+
+ case PsrMirq: /* Interrupt Request */
+ interrupt(ureg);
+ break;
+
+ case PsrMund: /* Undefined instruction */
+ print("Undefined instruction\n");
+ case PsrMsvc: /* Jump through 0, SWI or reserved trap */
+ print("SWI/SVC trap\n");
+ case PsrMabt: /* Prefetch abort */
+ print("Prefetch Abort\n");
+ case PsrMabt+1: /* Data abort */
+ print("Data Abort\n");
+
+
+ default:
+ dumpregs(ureg);
+ /* panic("exception %uX\n", ureg->type); */
+ break;
+ }
+
+ LOWBAT; /* Low bat off after interrupt */
+
+ splhi();
+
+}
--- /dev/null
+++ b/os/boot.original/puma/ether.c
@@ -1,0 +1,156 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ether.h"
+
+static Ctlr ether[MaxEther];
+
+static struct {
+ char *type;
+ int (*reset)(Ctlr*);
+} cards[] = {
+ { "CS8900", cs8900reset, },
+ { 0, }
+};
+
+int
+etherinit(void)
+{
+ Ctlr *ctlr;
+ int ctlrno, i, mask, n;
+
+ mask = 0;
+ for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+ ctlr = ðer[ctlrno];
+ memset(ctlr, 0, sizeof(Ctlr));
+ if(isaconfig("ether", ctlrno, &ctlr->card) == 0)
+ continue;
+ for(n = 0; cards[n].type; n++){
+ if(strcmp(cards[n].type, ctlr->card.type))
+ continue;
+ ctlr->ctlrno = ctlrno;
+ if((*cards[n].reset)(ctlr))
+ break;
+
+ ctlr->iq = qopen(16*1024, 1, 0, 0);
+ ctlr->oq = qopen(16*1024, 1, 0, 0);
+
+ ctlr->present = 1;
+ mask |= 1<<ctlrno;
+
+ print("ether%d: %s: port 0x%luX irq %d",
+ ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
+ if(ctlr->card.mem)
+ print(" addr 0x%luX", ctlr->card.mem & ~KZERO);
+ if(ctlr->card.size)
+ print(" size 0x%luX", ctlr->card.size);
+ print(":");
+ for(i = 0; i < sizeof(ctlr->card.ea); i++)
+ print(" %2.2uX", ctlr->card.ea[i]);
+ print("\n"); uartwait();
+ setvec(ctlr->card.irq, ctlr->card.intr, ctlr);
+ break;
+ }
+ }
+
+ return mask;
+}
+
+static Ctlr*
+attach(int ctlrno)
+{
+ Ctlr *ctlr;
+
+ if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
+ return 0;
+
+ ctlr = ðer[ctlrno];
+ if(ctlr->present == 1){
+ ctlr->present = 2;
+ (*ctlr->card.attach)(ctlr);
+ }
+
+ return ctlr;
+}
+
+uchar*
+etheraddr(int ctlrno)
+{
+ Ctlr *ctlr;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ return ctlr->card.ea;
+}
+
+int
+etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
+{
+ int n;
+ Ctlr *ctlr;
+ Block *b;
+ ulong start;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ start = m->ticks;
+ while((b = qget(ctlr->iq)) == 0){
+ if(TK2MS(m->ticks - start) >= timo){
+ /*
+ print("ether%d: rx timeout\n", ctlrno);
+ */
+ return 0;
+ }
+ //delay(1);
+ }
+
+ n = BLEN(b);
+ memmove(pkt, b->rp, n);
+ freeb(b);
+
+ return n;
+}
+
+int
+etheriq(Ctlr *ctlr, Block *b, int freebp)
+{
+ if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0){
+ if(freebp)
+ freeb(b);
+ return 0;
+ }
+ qbwrite(ctlr->iq, b);
+ return 1;
+}
+
+int
+ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
+{
+ Ctlr *ctlr;
+ Block *b;
+ int s;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ if(qlen(ctlr->oq) > 16*1024){
+ print("ether%d: tx queue full\n", ctlrno);
+ return 0;
+ }
+ b = iallocb(sizeof(Etherpkt));
+ memmove(b->wp, pkt, len);
+ memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
+ b->wp += len;
+ qbwrite(ctlr->oq, b);
+ s = splhi();
+ (*ctlr->card.transmit)(ctlr);
+ splx(s);
+
+ return 1;
+}
--- /dev/null
+++ b/os/boot.original/puma/ether.h
@@ -1,0 +1,82 @@
+/*
+ * All the goo for PC ethernet cards.
+ */
+typedef struct Card Card;
+typedef struct RingBuf RingBuf;
+typedef struct Type Type;
+typedef struct Ctlr Ctlr;
+
+/*
+ * Hardware interface.
+ */
+struct Card {
+ ISAConf;
+
+ int (*reset)(Ctlr*);
+ void (*attach)(Ctlr*);
+
+ void *(*read)(Ctlr*, void*, ulong, ulong);
+ void *(*write)(Ctlr*, ulong, void*, ulong);
+
+ void (*receive)(Ctlr*);
+ void (*transmit)(Ctlr*);
+ void (*intr)(Ureg*, Ctlr*);
+ void (*overflow)(Ctlr*);
+
+ uchar bit16; /* true if a 16 bit interface */
+ uchar ram; /* true if card has shared memory */
+
+ ulong dp8390; /* I/O address of 8390 (if any) */
+ ulong data; /* I/O data port if no shared memory */
+ uchar nxtpkt; /* software bndry */
+ uchar tstart; /* 8390 ring addresses */
+ uchar pstart;
+ uchar pstop;
+
+ uchar dummyrr; /* do dummy remote read */
+};
+
+/*
+ * Software ring buffer.
+ */
+struct RingBuf {
+ uchar owner;
+ uchar busy; /* unused */
+ ushort len;
+ uchar pkt[sizeof(Etherpkt)];
+};
+
+enum {
+ Host = 0, /* buffer owned by host */
+ Interface = 1, /* buffer owned by card */
+
+ Nrb = 16, /* default number of receive buffers */
+ Ntb = 2, /* default number of transmit buffers */
+};
+
+/*
+ * Software controller.
+ */
+struct Ctlr {
+ Card card; /* hardware info */
+ int ctlrno;
+ int present;
+
+ Queue* iq;
+ Queue* oq;
+
+ int inpackets;
+ int outpackets;
+ int crcs; /* input crc errors */
+ int oerrs; /* output errors */
+ int frames; /* framing errors */
+ int overflows; /* packet overflows */
+ int buffs; /* buffering errors */
+};
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
+
+extern int cs8900reset(Ctlr*);
+extern int etheriq(Ctlr*, Block*, int);
--- /dev/null
+++ b/os/boot.original/puma/ether8900.c
@@ -1,0 +1,555 @@
+/*
+ * Crystal CS8900 ethernet controller
+ * Specifically for the Teralogic Puma architecture
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ether.h"
+#include "puma.h"
+
+/*
+ * On the Puma board the CS8900 can be addressed from either
+ * ISA I/O space or ISA memory space at the following locations.
+ * The cs8900 address pins are shifted by 1 relative to the CPU.
+ */
+enum {
+ IsaIOBase = 0xf0000000,
+ IsaMemBase = 0xe0000000,
+
+ IOBase = 0x300,
+ MemBase = 0xc0000,
+};
+
+/* I/O accesses */
+#define out16(port, val) (*((ushort *)IsaIOBase + IOBase + (port)) = (val))
+#define in16(port) *((ushort *)IsaIOBase + IOBase + (port))
+#define in8(port) *((uchar *)IsaIOBase + ((IOBase+(port))<<1))
+#define regIOw(reg, val) do {out16(PpPtr, (reg)|0x3000); out16(PpData, val);} while(0)
+#define regIOr(reg) (out16(PpPtr, (reg)|0x3000), in16(PpData))
+#define regIOr1(reg) (out16(PpPtr, (reg)|0x3000), in16(PpData1))
+
+/* Memory accesses */
+#define regw(reg, val) *((ushort *)IsaMemBase + MemBase + (reg)) = (val)
+#define regr(reg) *((ushort *)IsaMemBase + MemBase + (reg))
+
+/* Puma frame copying */
+#define copyout(src, len) { \
+ int _len = (len); \
+ ushort *_src = (ushort *)(src); \
+ ushort *_dst = (ushort *)IsaMemBase + MemBase + TxFrame; \
+ while(_len > 0) { \
+ *_dst++ = *_src++; \
+ _dst++; \
+ _len -= 2; \
+ } \
+ }
+#define copyoutIO(src, len) { \
+ int _len = (len); \
+ ushort *_src = (ushort *)(src); \
+ while(_len > 0) { \
+ out16(RxTxData, *_src); \
+ _src++; \
+ _len -= 2; \
+ } \
+ }
+#define copyin(dst, len) { \
+ int _len = (len), _len2 = (len)&~1; \
+ ushort *_src = (ushort *)IsaMemBase + MemBase + RxFrame; \
+ ushort *_dst = (ushort *)(dst); \
+ while(_len2 > 0) { \
+ *_dst++ = *_src++; \
+ _src++; \
+ _len2 -= 2; \
+ } \
+ if(_len&1) \
+ *(uchar*)_dst = (*_src)&0xff; \
+ }
+#define copyinIO(dst, len) { \
+ int _i, _len = (len), _len2 = (len)&~1; \
+ ushort *_dst = (ushort *)(dst); \
+ _i = in16(RxTxData); USED(_i); /* RxStatus */ \
+ _i = in16(RxTxData); USED(_i); /* RxLen */ \
+ while(_len2 > 0) { \
+ *_dst++ = in16(RxTxData); \
+ _len2 -= 2; \
+ } \
+ if(_len&1) \
+ *(uchar*)_dst = (in16(RxTxData))&0xff; \
+ }
+
+
+
+enum { /* I/O Mode Register Offsets */
+ RxTxData = 0x00, /* receive/transmit data - port 0 */
+ TxCmdIO = 0x04, /* transmit command */
+ TxLenIO = 0x06, /* transmit length */
+ IsqIO = 0x08, /* Interrupt status queue */
+ PpPtr = 0x0a, /* packet page pointer */
+ PpData = 0x0c, /* packet page data */
+ PpData1 = 0x0e, /* packet page data - port 1*/
+};
+
+enum { /* Memory Mode Register Offsets */
+ /* Bus Interface Registers */
+ Ern = 0x0000, /* EISA registration numberion */
+ Pic = 0x0002, /* Product identification code */
+ Iob = 0x0020, /* I/O base address */
+ Intr = 0x0022, /* interrupt number */
+ Mba = 0x002c, /* memory base address */
+
+ Ecr = 0x0040, /* EEPROM command register */
+ Edw = 0x0042, /* EEPROM data word */
+ Rbc = 0x0050, /* receive frame byte counter */
+
+ /* Status and Control Registers */
+ RxCfg = 0x0102,
+ RxCtl = 0x0104,
+ TxCfg = 0x0106,
+ BufCfg = 0x010a,
+ LineCtl = 0x0112,
+ SelfCtl = 0x0114,
+ BusCtl = 0x0116,
+ TestCtl = 0x0118,
+ Isq = 0x0120,
+ RxEvent = 0x0124,
+ TxEvent = 0x0128,
+ BufEvent = 0x012c,
+ RxMISS = 0x0130,
+ TxCol = 0x0132,
+ LineSt = 0x0134,
+ SelfSt = 0x0136,
+ BusSt = 0x0138,
+ Tdr = 0x013c,
+
+ /* Initiate Transmit Registers */
+ TxCmd = 0x0144, /* transmit command */
+ TxLen = 0x0146, /* transmit length */
+
+ /* Address Filter Registers */
+ IndAddr = 0x0158, /* individual address registers */
+
+ /* Frame Location */
+ RxStatus = 0x0400, /* receive status */
+ RxLen = 0x0402, /* receive length */
+ RxFrame = 0x0404, /* receive frame location */
+ TxFrame = 0x0a00, /* transmit frame location */
+};
+
+enum { /* Ecr */
+ Addr = 0x00ff, /* EEPROM word address (field) */
+ Opcode = 0x0300, /* command opcode (field) */
+};
+
+enum { /* Isq */
+ Regnum = 0x003f, /* register number held by Isq (field) */
+ IsqRxEvent = 0x04,
+ IsqTxEvent = 0x08,
+ IsqBufEvent = 0x0c,
+ IsqRxMiss = 0x10,
+ IsqTxCol = 0x12,
+ RegContent = 0xffc0, /* register data contents (field) */
+};
+
+enum { /* RxCfg */
+ Skip_1 = 0x0040,
+ StreamE = 0x0080,
+ RxOKiE = 0x0100,
+ RxDMAonly = 0x0200,
+ AutoRxDMAE = 0x0400,
+ BufferCRC = 0x0800,
+ CRCerroriE = 0x1000,
+ RuntiE = 0x2000,
+ ExtradataiE = 0x4000,
+};
+
+enum { /* RxEvent */
+ IAHash = 0x0040,
+ Dribblebits = 0x0080,
+ RxOK = 0x0100,
+ Hashed = 0x0200,
+ IndividualAdr = 0x0400,
+ Broadcast = 0x0800,
+ CRCerror = 0x1000,
+ Runt = 0x2000,
+ Extradata = 0x4000,
+};
+
+enum { /* RxCtl */
+ IAHashA = 0x0040,
+ PromiscuousA = 0x0080,
+ RxOKA = 0x0100,
+ MulticastA = 0x0200,
+ IndividualA = 0x0400,
+ BroadcastA = 0x0800,
+ CRCerrorA = 0x1000,
+ RuntA = 0x2000,
+ ExtradataA = 0x4000,
+};
+
+enum { /* TxCfg */
+ LossofCRSiE = 0x0040,
+ SQEerroriE = 0x0080,
+ TxOKiE = 0x0100,
+ OutofWindowiE = 0x0200,
+ JabberiE = 0x0400,
+ AnycolliE = 0x0800,
+ Coll16iE = 0x8000,
+};
+
+enum { /* TxEvent */
+ LossofCRS = 0x0040,
+ SQEerror = 0x0080,
+ TxOK = 0x0100,
+ OutofWindow = 0x0200,
+ Jabber = 0x0400,
+ NTxCols = 0x7800, /* number of Tx collisions (field) */
+ coll16 = 0x8000,
+};
+
+enum { /* BufCfg */
+ SWintX = 0x0040,
+ RxDMAiE = 0x0080,
+ Rdy4TxiE = 0x0100,
+ TxUnderruniE = 0x0200,
+ RxMissiE = 0x0400,
+ Rx128iE = 0x0800,
+ TxColOvfiE = 0x1000,
+ MissOvfloiE = 0x2000,
+ RxDestiE = 0x8000,
+};
+
+enum { /* BufEvent */
+ SWint = 0x0040,
+ RxDMAFrame = 0x0080,
+ Rdy4Tx = 0x0100,
+ TxUnderrun = 0x0200,
+ RxMiss = 0x0400,
+ Rx128 = 0x0800,
+ RxDest = 0x8000,
+};
+
+enum { /* RxMiss */
+ MissCount = 0xffc0,
+};
+
+enum { /* TxCol */
+ ColCount = 0xffc0,
+};
+
+enum { /* LineCtl */
+ SerRxOn = 0x0040,
+ SerTxOn = 0x0080,
+ Iface = 0x0300, /* (field) 01 - AUI, 00 - 10BASE-T, 10 - Auto select */
+ ModBackoffE = 0x0800,
+ PolarityDis = 0x1000,
+ DefDis = 0x2000,
+ LoRxSquelch = 0x4000,
+};
+
+enum { /* LineSt */
+ LinkOK = 0x0080,
+ AUI = 0x0100,
+ TenBT = 0x0200,
+ PolarityOK = 0x1000,
+ CRS = 0x4000,
+};
+
+enum { /* SelfCtl */
+ RESET = 0x0040,
+ SWSuspend = 0x0100,
+ HWSleepE = 0x0200,
+ HWStandbyE = 0x0400,
+};
+
+enum { /* SelfSt */
+ INITD = 0x0080,
+ SIBUSY = 0x0100,
+ EepromPresent = 0x0200,
+ EepromOK = 0x0400,
+ ElPresent = 0x0800,
+ EeSize = 0x1000,
+};
+
+enum { /* BusCtl */
+ ResetRxDMA = 0x0040,
+ UseSA = 0x0200,
+ MemoryE = 0x0400,
+ DMABurst = 0x0800,
+ EnableIRQ = 0x8000,
+};
+
+enum { /* BusST */
+ TxBidErr = 0x0080,
+ Rdy4TxNOW = 0x0100,
+};
+
+enum { /* TestCtl */
+ FDX = 0x4000, /* full duplex */
+};
+
+enum { /* TxCmd */
+ TxStart = 0x00c0, /* bytes before transmit starts (field) */
+ TxSt5 = 0x0000, /* start after 5 bytes */
+ TxSt381 = 0x0040, /* start after 381 bytes */
+ TxSt1021 = 0x0080, /* start after 1021 bytes */
+ TxStAll = 0x00c0, /* start after the entire frame is in the cs8900 */
+ Force = 0x0100,
+ Onecoll = 0x0200,
+ InhibitCRC = 0x1000,
+ TxPadDis = 0x2000,
+};
+
+static Queue *pendingTx[MaxEther];
+
+static void
+attach(Ctlr *ctlr)
+{
+ int reg;
+
+ USED(ctlr);
+ /* enable transmit and receive */
+ reg = regr(BusCtl);
+ regw(BusCtl, reg|EnableIRQ);
+ reg = regr(LineCtl);
+ regw(LineCtl, reg|SerRxOn|SerTxOn);
+}
+
+static char pbuf[200];
+int
+sprintx(void *f, char *to, int count)
+{
+ int i, printable;
+ char *start = to;
+ uchar *from = f;
+
+ if(count < 0) {
+ print("BAD DATA COUNT %d\n", count);
+ return 0;
+ }
+ printable = 1;
+ if(count > 40)
+ count = 40;
+ for(i=0; i<count && printable; i++)
+ if((from[i]<32 && from[i] !='\n' && from[i] !='\r' && from[i] !='\b' && from[i] !='\t') || from[i]>127)
+ printable = 0;
+ *to++ = '\'';
+ if(printable){
+ memmove(to, from, count);
+ to += count;
+ }else{
+ for(i=0; i<count; i++){
+ if(i>0 && i%4==0)
+ *to++ = ' ';
+ sprint(to, "%2.2ux", from[i]);
+ to += 2;
+ }
+ }
+ *to++ = '\'';
+ *to = 0;
+ return to - start;
+}
+
+static void
+transmit(Ctlr *ctlr)
+{
+ int len, status;
+ Block *b;
+
+ for(;;){
+ /* is TxCmd pending ? - check */
+ if(qlen(pendingTx[ctlr->ctlrno]) > 0)
+ break;
+ b = qget(ctlr->oq);
+ if(b == 0)
+ break;
+ len = BLEN(b);
+ regw(TxCmd, TxSt381);
+ regw(TxLen, len);
+ status = regr(BusSt);
+ if((status & Rdy4TxNOW) == 0) {
+ qbwrite(pendingTx[ctlr->ctlrno], b);
+ break;
+ }
+ /*
+ * Copy the packet to the transmit buffer.
+ */
+ copyout(b->rp, len);
+ freeb(b);
+ }
+}
+
+static void
+interrupt(Ureg*, Ctlr *ctlr)
+{
+ int len, events, status;
+ Block *b;
+ Queue *q;
+
+ while((events = regr(Isq)) != 0) {
+ status = events&RegContent;
+
+ switch(events&Regnum) {
+
+ case IsqBufEvent:
+ if(status&Rdy4Tx) {
+ if(qlen(pendingTx[ctlr->ctlrno]) > 0)
+ q = pendingTx[ctlr->ctlrno];
+ else
+ q = ctlr->oq;
+ b = qget(q);
+ if(b == 0)
+ break;
+ len = BLEN(b);
+ copyout(b->rp, len);
+ freeb(b);
+ } else
+ if(status&TxUnderrun) {
+ print("TxUnderrun\n");
+ } else
+ if(status&RxMiss) {
+ print("RxMiss\n");
+ } else {
+ print("IsqBufEvent status = %ux\n", status);
+ }
+ break;
+
+ case IsqRxEvent:
+ if(status&RxOK) {
+ len = regr(RxLen);
+ if((b = iallocb(len)) != 0) {
+ copyin(b->wp, len);
+ b->wp += len;
+ etheriq(ctlr, b, 1);
+ }
+ } else {
+ print("IsqRxEvent status = %ux\n", status);
+ }
+ break;
+
+ case IsqTxEvent:
+ if(status&TxOK) {
+ if(qlen(pendingTx[ctlr->ctlrno]) > 0)
+ q = pendingTx[ctlr->ctlrno];
+ else
+ q = ctlr->oq;
+ b = qget(q);
+ if(b == 0)
+ break;
+ len = BLEN(b);
+ regw(TxCmd, TxSt381);
+ regw(TxLen, len);
+if((regr(BusSt) & Rdy4TxNOW) == 0) {
+ print("IsqTxEvent and Rdy4TxNow == 0\n");
+}
+ copyout(b->rp, len);
+ freeb(b);
+ } else {
+ print("IsqTxEvent status = %ux\n", status);
+ }
+ break;
+ case IsqRxMiss:
+ break;
+ case IsqTxCol:
+ break;
+ }
+ }
+}
+
+int
+cs8900reset(Ctlr* ctlr)
+{
+ int i, reg;
+ uchar ea[Eaddrlen];
+
+ ctlr->card.irq = V_ETHERNET;
+ pendingTx[ctlr->ctlrno] = qopen(16*1024, 1, 0, 0);
+
+ /*
+ * If the Ethernet address is not set in the plan9.ini file
+ * a) try reading from the Puma board ROM. The ether address is found in
+ * bytes 4-9 of the ROM. The Teralogic Organizational Unique Id (OUI)
+ * is in bytes 4-6 and should be 00 10 8a.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0) {
+ uchar *rom = (uchar *)EPROM_BASE;
+ if(rom[4] != 0x00 || rom[5] != 0x10 || rom[6] != 0x8a)
+ panic("no ether address");
+ memmove(ea, &rom[4], Eaddrlen);
+ }
+ memmove(ctlr->card.ea, ea, Eaddrlen);
+
+ /*
+ * Identify the chip by reading the Pic register.
+ * The EISA registration number is in the low word
+ * and the product identification code in the high code.
+ * The ERN for Crystal Semiconductor is 0x630e.
+ * Bits 0-7 and 13-15 of the Pic should be zero for a CS8900.
+ */
+ if(regIOr(Ern) != 0x630e || (regIOr(Pic) & 0xe0ff) != 0)
+ panic("no cs8900 found");
+
+ /*
+ * Reset the chip and ensure 16-bit mode operation
+ */
+ regIOw(SelfCtl, RESET);
+ delay(10);
+ i=in8(PpPtr); USED(i);
+ i=in8(PpPtr+1); USED(i);
+ i=in8(PpPtr); USED(i);
+ i=in8(PpPtr+1); USED(i);
+
+ /*
+ * Wait for initialisation and EEPROM reads to complete
+ */
+ i=0;
+ for(;;) {
+ short st = regIOr(SelfSt);
+ if((st&SIBUSY) == 0 && st&INITD)
+ break;
+ if(i++ > 1000000)
+ panic("cs8900: initialisation failed");
+ }
+
+ /*
+ * Enable memory mode operation.
+ */
+ regIOw(Mba, MemBase & 0xffff);
+ regIOw(Mba+2, MemBase >> 16);
+ regIOw(BusCtl, MemoryE|UseSA);
+
+ /*
+ * Enable 10BASE-T half duplex, transmit in interrupt mode
+ */
+ reg = regr(LineCtl);
+ regw(LineCtl, reg&~Iface);
+ reg = regr(TestCtl);
+ regw(TestCtl, reg&~FDX);
+ regw(BufCfg, Rdy4TxiE|TxUnderruniE|RxMissiE);
+ regw(TxCfg, TxOKiE|JabberiE|Coll16iE);
+ regw(RxCfg, RxOKiE);
+ regw(RxCtl, RxOKA|IndividualA|BroadcastA);
+
+ for(i=0; i<Eaddrlen; i+=2)
+ regw(IndAddr+i, ea[i] | (ea[i+1] << 8));
+
+ /* Puma IRQ tied to INTRQ0 */
+ regw(Intr, 0);
+
+ ctlr->card.reset = cs8900reset;
+ ctlr->card.port = 0x300;
+ ctlr->card.attach = attach;
+ ctlr->card.transmit = transmit;
+ ctlr->card.intr = interrupt;
+
+ print("Ether reset...\n");uartwait();
+
+ return 0;
+}
+
--- /dev/null
+++ b/os/boot.original/puma/flash.c
@@ -1,0 +1,226 @@
+#include "boot.h"
+
+typedef struct Flashdev Flashdev;
+struct Flashdev {
+ uchar* base;
+ int size;
+ uchar* exec;
+ char* type;
+ char* config;
+ int conflen;
+};
+
+enum {
+ FLASHSEG = 256*1024,
+ CONFIGLIM = FLASHSEG,
+ BOOTOFF = FLASHSEG,
+ BOOTLEN = 3*FLASHSEG, /* third segment might be filsys */
+ /* rest of flash is free */
+};
+
+static Flashdev flash;
+
+/*
+ * configuration data is written between the bootstrap and
+ * the end of region 0. the region ends with allocation descriptors
+ * of the following form:
+ *
+ * byte order is big endian
+ *
+ * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
+ */
+typedef struct Flalloc Flalloc;
+struct Flalloc {
+ ulong check; /* checksum of data, or ~0 */
+ ulong base; /* base of region; ~0 if unallocated, 0 if deleted */
+ uchar len[3];
+ uchar tag; /* see below */
+ uchar sig[4];
+};
+
+enum {
+ /* tags */
+ Tdead= 0,
+ Tboot= 0x01, /* space reserved for boot */
+ Tconf= 0x02, /* configuration data */
+ Tnone= 0xFF,
+
+ Noval= ~0,
+};
+
+static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
+static char conftag[] = "#plan9.ini\n";
+
+static ulong
+checksum(uchar* p, int n)
+{
+ ulong s;
+
+ for(s=0; --n >= 0;)
+ s += *p++;
+ return s;
+}
+
+static int
+validptr(Flalloc *ap, uchar *p)
+{
+ return p > (uchar*)end && p < (uchar*)ap;
+}
+
+static int
+flashcheck(Flalloc *ap, char **val, int *len)
+{
+ uchar *base;
+ int n;
+
+ if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
+ return 0;
+ base = flash.base+ap->base;
+ if(!validptr(ap, base))
+ return 0;
+ n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
+ if(n == 0xFFFFFF)
+ n = 0;
+ if(n < 0)
+ return 0;
+ if(n > 0 && !validptr(ap, base+n-1))
+ return 0;
+ if(ap->check != Noval && checksum(base, n) != ap->check){
+ print("flash: bad checksum\n");
+ return 0;
+ }
+ *val = (char*)base;
+ *len = n;
+ return 1;
+}
+
+int
+flashinit(void)
+{
+ int f, n, len;
+ char *type, *val;
+ Flalloc *ap;
+
+ flash.base = 0;
+ flash.exec = 0;
+ flash.type = 0;
+ /* TODO - check for presence and type */
+/*
+ * if((m->iomem->memc[0].base & 1) == 0){
+ * print("flash: flash not present or not enabled\n");
+ * return 0;
+ * }
+ * f = (m->bcsr[2]>>28)&0xF;
+ */
+f = 0;
+ switch(f){
+ default:
+ print("flash boot: unknown or no flash\n");
+ return 0;
+ case 4: n=8; type = "SM732x8"; break;
+ case 5: n=4; type = "SM732x8"; break;
+ case 6: n=8; type = "AMD29F0x0"; break;
+ case 7: n=4; type = "AMD29F0x0"; break;
+ case 8: n=2; type = "AMD29F0x0"; break;
+ }
+ flash.type = type;
+ flash.size = n*1024*1024;
+ flash.base = KADDR(FLASH_BASE);
+ flash.exec = flash.base + BOOTOFF;
+ flash.config = nil;
+ flash.conflen = 0;
+
+ for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
+ if(1)
+ print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
+ if(ap->tag == Tconf &&
+ flashcheck(ap, &val, &len) &&
+ len >= sizeof(conftag)-1 &&
+ memcmp(val, conftag, sizeof(conftag)-1) == 0){
+ flash.config = val;
+ flash.conflen = len;
+ print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
+ }
+ }
+ if(flash.config){
+ print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
+ flash.config = nil; /* not that daring yet */
+ }else
+ print("flash: no config\n");
+ if(issqueezed(flash.exec) == E_MAGIC){
+ print("flash: squeezed StrongARM kernel installed\n");
+ return 1<<0;
+ }
+ if(GLLONG(flash.exec) == E_MAGIC){
+ print("flash: unsqueezed stringARM kernel installed\n");
+ return 1<<0;
+ }
+ flash.exec = 0;
+ print("flash: no StrongARM kernel in Flash\n");
+ return 0;
+}
+
+char*
+flashconfig(int)
+{
+ return flash.config;
+}
+
+int
+flashbootable(int)
+{
+ return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == E_MAGIC);
+}
+
+int
+flashboot(int)
+{
+ ulong entry, addr;
+ void (*b)(void);
+ Exec *ep;
+ Block in;
+ long n;
+ uchar *p;
+
+ if(flash.exec == 0)
+ return -1;
+ p = flash.exec;
+ if(GLLONG(p) == E_MAGIC){
+ /* unsqueezed: copy data and perhaps text, then jump to it */
+ ep = (Exec*)p;
+ entry = PADDR(GLLONG(ep->entry));
+ p += sizeof(Exec);
+ addr = entry;
+ n = GLLONG(ep->text);
+ if(addr != (ulong)p){
+ memmove((void*)addr, p, n);
+ print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
+ }
+ p += n;
+ if(entry >= FLASH_BASE)
+ addr = 3*BY2PG; /* kernel text is in Flash, data in RAM */
+ else
+ addr = PGROUND(addr+n);
+ n = GLLONG(ep->data);
+ memmove((void*)addr, p, n);
+ print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
+ }else{
+ in.data = p;
+ in.rp = in.data;
+ in.lim = p+BOOTLEN;
+ in.wp = in.lim;
+ n = unsqueezef(&in, &entry);
+ if(n < 0)
+ return -1;
+ }
+ print("entry=0x%lux\n", entry);
+ uartwait();
+ /* scc2stop(); */
+ /*
+ * Go to new code. It's up to the program to get its PC relocated to
+ * the right place.
+ */
+ b = (void (*)(void))KADDR(PADDR(entry));
+ (*b)();
+ return -1;
+}
--- /dev/null
+++ b/os/boot.original/puma/fns.h
@@ -1,0 +1,111 @@
+void aamloop(int);
+Alarm* alarm(int, void (*)(Alarm*), void*);
+void alarminit(void);
+int bootp(int, char*);
+void cancel(Alarm*);
+void checkalarms(void);
+void clockinit(void);
+void consinit(void);
+void delay(int);
+uchar* etheraddr(int);
+int etherinit(void);
+int etherrxpkt(int, Etherpkt*, int);
+int ethertxpkt(int, Etherpkt*, int, int);
+int flashboot(int);
+int flashbootable(int);
+char* flashconfig(int);
+int flashinit(void);
+char* getconf(char*);
+int getcfields(char*, char**, int, char*);
+int getstr(char*, char*, int, char*);
+int hardinit(void);
+long hardread(int, void*, long);
+long hardseek(int, long);
+long hardwrite(int, void*, long);
+void* ialloc(ulong, int);
+void idle(void);
+int isaconfig(char*, int, ISAConf*);
+int isgzipped(uchar*);
+int issqueezed(uchar*);
+void kbdinit(void);
+void kbdchar(Queue*, int);
+void machinit(void);
+void meminit(void);
+void microdelay(int);
+void mmuinit(void);
+uchar nvramread(int);
+void outb(int, int);
+void outs(int, ushort);
+void outl(int, ulong);
+void outsb(int, void*, int);
+void outss(int, void*, int);
+void outsl(int, void*, int);
+void panic(char*, ...);
+int optionsw(void);
+int plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
+Partition* setflashpart(int, char*);
+Partition* sethardpart(int, char*);
+Partition* setscsipart(int, char*);
+void setvec(int, void (*)(Ureg*, void*), void*);
+void screeninit(void);
+void screenputs(char*, int);
+void setr13(int, void*);
+int splhi(void);
+int spllo(void);
+void splx(int);
+void trapinit(void);
+void uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
+void uartputs(char*, int);
+void uartwait(void);
+long unsqueezef(Block*, ulong*);
+
+#define GSHORT(p) (((p)[1]<<8)|(p)[0])
+#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))
+#define GLSHORT(p) (((p)[0]<<8)|(p)[1])
+#define GLLONG(p) ((GLSHORT(p)<<16)|GLSHORT(p+2))
+
+#define KADDR(a) ((void*)((ulong)(a)|KZERO))
+#define PADDR(a) ((ulong)(a)&~KZERO)
+
+
+void mapinit(RMap*, Map*, int);
+void mapfree(RMap*, ulong, int);
+ulong mapalloc(RMap*, ulong, int, int);
+
+/* IBM bit field order */
+#define IBFEXT(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1))))
+#define IBIT(b) ((ulong)1<<(31-(b)))
+
+#define SIBIT(n) ((ushort)1<<(15-(n)))
+
+void* malloc(ulong);
+void free(void*);
+
+extern Block* iallocb(int);
+extern void freeb(Block*);
+extern Queue* qopen(int, int, void (*)(void*), void*);
+extern Block* qget(Queue*);
+extern void qbwrite(Queue*, Block*);
+extern long qlen(Queue*);
+#define qpass qbwrite
+extern void qbputc(Queue*, int);
+extern int qbgetc(Queue*);
+
+int sio_inb(int);
+void sio_outb(int, int);
+void led(int);
+
+extern void _virqcall(void);
+extern void _vfiqcall(void);
+extern void _vundcall(void);
+extern void _vsvccall(void);
+extern void _vpabcall(void);
+extern void _vdabcall(void);
+
+void flushIcache(void);
+void writeBackDC(void);
+void flushDcache(void);
+void flushIcache(void);
+void drainWBuffer(void);
+
+void pumainit(void);
--- /dev/null
+++ b/os/boot.original/puma/hard.c
@@ -1,0 +1,773 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#define DPRINT if(0)print
+
+typedef struct Drive Drive;
+typedef struct Ident Ident;
+typedef struct Controller Controller;
+
+enum
+{
+ /* ports */
+ Pbase0= 0x1F0, /* primary */
+ Pbase1= 0x170, /* secondary */
+ Pbase2= 0x1E8, /* tertiary */
+ Pbase3= 0x168, /* quaternary */
+ Pdata= 0, /* data port (16 bits) */
+ Perror= 1, /* error port (read) */
+ Pprecomp= 1, /* buffer mode port (write) */
+ Pcount= 2, /* sector count port */
+ Psector= 3, /* sector number port */
+ Pcyllsb= 4, /* least significant byte cylinder # */
+ Pcylmsb= 5, /* most significant byte cylinder # */
+ Pdh= 6, /* drive/head port */
+ DHmagic= 0xA0,
+ DHslave= 0x10,
+ Pstatus= 7, /* status port (read) */
+ Sbusy= (1<<7),
+ Sready= (1<<6),
+ Sdrq= (1<<3),
+ Serr= (1<<0),
+ Pcmd= 7, /* cmd port (write) */
+
+ /* commands */
+ Crecal= 0x10,
+ Cread= 0x20,
+ Cwrite= 0x30,
+ Cident= 0xEC,
+ Cident2= 0xFF, /* pseudo command for post Cident interrupt */
+ Csetbuf= 0xEF,
+
+ /* file types */
+ Qdir= 0,
+
+ Timeout= 5, /* seconds to wait for things to complete */
+
+ NCtlr= 4,
+ NDrive= NCtlr*2,
+};
+
+/*
+ * ident sector from drive. this is from ANSI X3.221-1994
+ */
+struct Ident
+{
+ ushort config; /* general configuration info */
+ ushort cyls; /* # of cylinders (default) */
+ ushort reserved0;
+ ushort heads; /* # of heads (default) */
+ ushort b2t; /* unformatted bytes/track */
+ ushort b2s; /* unformated bytes/sector */
+ ushort s2t; /* sectors/track (default) */
+ ushort reserved1[3];
+/* 10 */
+ ushort serial[10]; /* serial number */
+ ushort type; /* buffer type */
+ ushort bsize; /* buffer size/512 */
+ ushort ecc; /* ecc bytes returned by read long */
+ ushort firm[4]; /* firmware revision */
+ ushort model[20]; /* model number */
+/* 47 */
+ ushort s2i; /* number of sectors/interrupt */
+ ushort dwtf; /* double word transfer flag */
+ ushort capabilities;
+ ushort reserved2;
+ ushort piomode;
+ ushort dmamode;
+ ushort cvalid; /* (cvald&1) if next 4 words are valid */
+ ushort ccyls; /* current # cylinders */
+ ushort cheads; /* current # heads */
+ ushort cs2t; /* current sectors/track */
+ ushort ccap[2]; /* current capacity in sectors */
+ ushort cs2i; /* current number of sectors/interrupt */
+/* 60 */
+ ushort lbasecs[2]; /* # LBA user addressable sectors */
+ ushort dmasingle;
+ ushort dmadouble;
+/* 64 */
+ ushort reserved3[64];
+ ushort vendor[32]; /* vendor specific */
+ ushort reserved4[96];
+};
+
+/*
+ * a hard drive
+ */
+struct Drive
+{
+ Controller *cp;
+ uchar driveno;
+ uchar dh;
+
+ Disc;
+};
+
+/*
+ * a controller for 2 drives
+ */
+struct Controller
+{
+ int pbase; /* base port */
+ uchar ctlrno;
+
+ /*
+ * current operation
+ */
+ int cmd; /* current command */
+ char *buf; /* xfer buffer */
+ int tcyl; /* target cylinder */
+ int thead; /* target head */
+ int tsec; /* target sector */
+ int tbyte; /* target byte */
+ int nsecs; /* length of transfer (sectors) */
+ int sofar; /* bytes transferred so far */
+ int status;
+ int error;
+ Drive *dp; /* drive being accessed */
+};
+
+static int atactlrmask;
+static Controller *atactlr[NCtlr];
+static int atadrivemask;
+static Drive *atadrive[NDrive];
+static int pbase[NCtlr] = {
+ Pbase0, Pbase1, Pbase2, Pbase3,
+};
+
+static void hardintr(Ureg*, void*);
+static long hardxfer(Drive*, Partition*, int, ulong, long);
+static int hardident(Drive*);
+static void hardsetbuf(Drive*, int);
+static void hardpart(Drive*);
+static int hardparams(Drive*);
+static void hardrecal(Drive*);
+static int hardprobe(Drive*, int, int, int);
+
+static void
+atactlrprobe(int ctlrno, int irq)
+{
+ Controller *ctlr;
+ Drive *drive;
+ int driveno, port;
+
+ if(atactlrmask & (1<<ctlrno))
+ return;
+ atactlrmask |= 1<<ctlrno;
+
+ port = pbase[ctlrno];
+ outb(port+Pdh, DHmagic);
+ delay(1);
+ if((inb(port+Pdh) & 0xFF) != DHmagic){
+ DPRINT("ata%d: DHmagic not ok\n", ctlrno);
+ return;
+ }
+ DPRINT("ata%d: DHmagic ok\n", ctlrno);
+
+ atactlr[ctlrno] = ialloc(sizeof(Controller), 0);
+ ctlr = atactlr[ctlrno];
+ ctlr->pbase = port;
+ ctlr->ctlrno = ctlrno;
+ ctlr->buf = ialloc(Maxxfer, 0);
+ inb(ctlr->pbase+Pstatus);
+ setvec(irq, hardintr, ctlr);
+
+ driveno = ctlrno*2;
+ atadrive[driveno] = ialloc(sizeof(Drive), 0);
+ drive = atadrive[driveno];
+ drive->cp = ctlr;
+ drive->driveno = driveno;
+ drive->dh = DHmagic;
+
+ driveno++;
+ atadrive[driveno] = ialloc(sizeof(Drive), 0);
+ drive = atadrive[driveno];
+ drive->cp = ctlr;
+ drive->driveno = driveno;
+ drive->dh = DHmagic|DHslave;
+}
+
+static Drive*
+atadriveprobe(int driveno)
+{
+ Drive *drive;
+ int ctlrno;
+ ISAConf isa;
+
+ ctlrno = driveno/2;
+ if(atactlr[ctlrno] == 0){
+ if(atactlrmask & (1<<ctlrno))
+ return 0;
+ memset(&isa, 0, sizeof(ISAConf));
+ if(isaconfig("ata", ctlrno, &isa) == 0)
+ return 0;
+ if(ctlrno && isa.irq)
+ atactlrprobe(ctlrno, Int0vec+isa.irq);
+ if(atactlr[ctlrno] == 0)
+ return 0;
+ }
+
+ drive = atadrive[driveno];
+ if(drive->online == 0){
+ if(atadrivemask & (1<<driveno))
+ return 0;
+ atadrivemask |= 1<<driveno;
+ if(hardparams(drive))
+ return 0;
+ if(drive->lba)
+ print("hd%d: LBA %d sectors, %ud bytes\n",
+ drive->driveno, drive->sectors, drive->cap);
+ else
+ print("hd%d: CHS %d/%d/%d %d bytes\n",
+ drive->driveno, drive->cyl, drive->heads,
+ drive->sectors, drive->cap);
+ drive->online = 1;
+ hardpart(drive);
+ hardsetbuf(drive, 1);
+ }
+
+ return drive;
+}
+
+int
+hardinit(void)
+{
+ atactlrprobe(0, ATAvec0);
+ return 0xFF;
+}
+
+long
+hardseek(int driveno, long offset)
+{
+ Drive *drive;
+
+ if((drive = atadriveprobe(driveno)) == 0)
+ return -1;
+ drive->offset = offset;
+ return offset;
+}
+
+/*
+ * did an interrupt happen?
+ */
+static void
+hardwait(Controller *cp)
+{
+ ulong start;
+ int x;
+
+ x = spllo();
+ for(start = m->ticks; TK2SEC(m->ticks - start) < Timeout && cp->cmd;)
+ if(cp->cmd == Cident2 && TK2SEC(m->ticks - start) >= 1)
+ break;
+ if(TK2SEC(m->ticks - start) >= Timeout){
+ DPRINT("hardwait timed out %ux\n", inb(cp->pbase+Pstatus));
+ hardintr(0, cp);
+ }
+ splx(x);
+}
+
+Partition*
+sethardpart(int driveno, char *p)
+{
+ Partition *pp;
+ Drive *dp;
+
+ if((dp = atadriveprobe(driveno)) == 0)
+ return 0;
+
+ for(pp = dp->p; pp < &dp->p[dp->npart]; pp++)
+ if(strcmp(pp->name, p) == 0){
+ dp->current = pp;
+ return pp;
+ }
+ return 0;
+}
+
+long
+hardread(int driveno, void *a, long n)
+{
+ Drive *dp;
+ long rv, i;
+ int skip;
+ uchar *aa = a;
+ Partition *pp;
+ Controller *cp;
+
+ if((dp = atadriveprobe(driveno)) == 0)
+ return 0;
+
+ pp = dp->current;
+ if(pp == 0)
+ return -1;
+ cp = dp->cp;
+
+ skip = dp->offset % dp->bytes;
+ for(rv = 0; rv < n; rv += i){
+ i = hardxfer(dp, pp, Cread, dp->offset+rv-skip, n-rv+skip);
+ if(i == 0)
+ break;
+ if(i < 0)
+ return -1;
+ i -= skip;
+ if(i > n - rv)
+ i = n - rv;
+ memmove(aa+rv, cp->buf + skip, i);
+ skip = 0;
+ }
+ dp->offset += rv;
+
+ return rv;
+}
+
+/*
+ * wait for the controller to be ready to accept a command
+ */
+static int
+cmdreadywait(Drive *drive)
+{
+ ulong end;
+ uchar dh, status;
+ Controller *ctlr;
+
+ ctlr = drive->cp;
+ end = m->ticks+MS2TK(10)+1;
+ dh = (inb(ctlr->pbase+Pdh) & DHslave)^(drive->dh & DHslave);
+
+ status = 0;
+ while(m->ticks < end){
+ status = inb(ctlr->pbase+Pstatus);
+ if(status & Sbusy)
+ continue;
+ if(dh){
+ outb(ctlr->pbase+Pdh, drive->dh);
+ dh = 0;
+ continue;
+ }
+ if(status & Sready)
+ return 0;
+ }
+ USED(status);
+
+ DPRINT("hd%d: cmdreadywait failed %uX\n", drive->driveno, status);
+ outb(ctlr->pbase+Pdh, DHmagic);
+ return -1;
+}
+
+/*
+ * transfer a number of sectors. hardintr will perform all the iterative
+ * parts.
+ */
+static long
+hardxfer(Drive *dp, Partition *pp, int cmd, ulong start, long len)
+{
+ Controller *cp;
+ long lsec;
+
+ if(dp->online == 0){
+ DPRINT("disk not on line\n");
+ return -1;
+ }
+
+ if(cmd == Cwrite)
+ return -1;
+
+ /*
+ * cut transfer size down to disk buffer size
+ */
+ start = start / dp->bytes;
+ if(len > Maxxfer)
+ len = Maxxfer;
+ len = (len + dp->bytes - 1) / dp->bytes;
+
+ /*
+ * calculate physical address
+ */
+ cp = dp->cp;
+ lsec = start + pp->start;
+ if(lsec >= pp->end){
+ DPRINT("read past end of partition\n");
+ return 0;
+ }
+ if(dp->lba){
+ cp->tsec = lsec & 0xff;
+ cp->tcyl = (lsec>>8) & 0xffff;
+ cp->thead = (lsec>>24) & 0xf;
+ } else {
+ cp->tcyl = lsec/(dp->sectors*dp->heads);
+ cp->tsec = (lsec % dp->sectors) + 1;
+ cp->thead = (lsec/dp->sectors) % dp->heads;
+ }
+
+ /*
+ * can't xfer past end of disk
+ */
+ if(lsec+len > pp->end)
+ len = pp->end - lsec;
+ cp->nsecs = len;
+
+ if(cmdreadywait(dp) < 0)
+ return -1;
+
+ /*
+ * start the transfer
+ */
+ cp->cmd = cmd;
+ cp->dp = dp;
+ cp->sofar = 0;
+ cp->status = 0;
+ DPRINT("xfer:\ttcyl %d, tsec %d, thead %d\n", cp->tcyl, cp->tsec, cp->thead);
+ DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
+ outb(cp->pbase+Pcount, cp->nsecs);
+ outb(cp->pbase+Psector, cp->tsec);
+ outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | cp->thead);
+ outb(cp->pbase+Pcyllsb, cp->tcyl);
+ outb(cp->pbase+Pcylmsb, cp->tcyl>>8);
+ outb(cp->pbase+Pcmd, cmd);
+
+ hardwait(cp);
+
+ if(cp->status & Serr){
+ DPRINT("hd%d err: status %lux, err %lux\n",
+ dp->driveno, cp->status, cp->error);
+ DPRINT("\ttcyl %d, tsec %d, thead %d\n",
+ cp->tcyl, cp->tsec, cp->thead);
+ DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
+ return -1;
+ }
+
+ return cp->nsecs*dp->bytes;
+}
+
+/*
+ * set read ahead mode (1 == on, 0 == off)
+ */
+static void
+hardsetbuf(Drive *dp, int on)
+{
+ Controller *cp = dp->cp;
+
+ if(cmdreadywait(dp) < 0)
+ return;
+
+ cp->cmd = Csetbuf;
+ /* BUG: precomp varies by hard drive...this is safari-specific? */
+ outb(cp->pbase+Pprecomp, on ? 0xAA : 0x55);
+ outb(cp->pbase+Pdh, dp->dh);
+ outb(cp->pbase+Pcmd, Csetbuf);
+
+ hardwait(cp);
+}
+
+static int
+isatapi(Drive *drive)
+{
+ Controller *cp;
+
+ cp = drive->cp;
+ outb(cp->pbase+Pdh, drive->dh);
+ microdelay(1);
+ if(inb(cp->pbase+Pstatus))
+ return 0;
+ if(inb(cp->pbase+Pcylmsb) != 0xEB || inb(cp->pbase+Pcyllsb) != 0x14)
+ return 0;
+ return 1;
+}
+
+/*
+ * get parameters from the drive
+ */
+static int
+hardident(Drive *dp)
+{
+ Controller *cp;
+ Ident *ip;
+
+ dp->bytes = 512;
+ cp = dp->cp;
+
+ if(isatapi(dp) || cmdreadywait(dp) < 0)
+ return -1;
+
+ cp->nsecs = 1;
+ cp->sofar = 0;
+ cp->cmd = Cident;
+ cp->dp = dp;
+ outb(cp->pbase+Pdh, dp->dh);
+ outb(cp->pbase+Pcmd, Cident);
+
+ hardwait(cp);
+
+ if(cp->status & Serr)
+ return -1;
+
+ hardwait(cp);
+
+ ip = (Ident*)cp->buf;
+ DPRINT("LBA%d: %lud\n",
+ ip->capabilities & (1<<9) == 1, (ip->lbasecs[0]) | (ip->lbasecs[1]<<16));
+ DPRINT("DEF: %ud/%ud/%ud\nMAP %ud/%ud/%ud\n",
+ ip->cyls, ip->heads, ip->s2t,
+ ip->ccyls, ip->cheads, ip->cs2t);
+ if(ip->capabilities & (1<<9)){
+ dp->lba = 1;
+ dp->sectors = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16);
+ dp->cap = dp->bytes * dp->sectors;
+/*print("\nata%d model %s with %d lba sectors\n", dp->driveno, id, dp->sectors);/**/
+ } else {
+ dp->lba = 0;
+
+ /* use default (unformatted) settings */
+ dp->cyl = ip->cyls;
+ dp->heads = ip->heads;
+ dp->sectors = ip->s2t;
+/*print("\nata%d model %s with default %d cyl %d head %d sec\n", dp->driveno,
+ id, dp->cyl, dp->heads, dp->sectors);/**/
+
+ if(ip->cvalid&(1<<0)){
+ /* use current settings */
+ dp->cyl = ip->ccyls;
+ dp->heads = ip->cheads;
+ dp->sectors = ip->cs2t;
+/*print("\tchanged to %d cyl %d head %d sec\n", dp->cyl, dp->heads, dp->sectors);/**/
+ }
+ dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
+ }
+
+ return 0;
+}
+
+/*
+ * probe the given sector to see if it exists
+ */
+static int
+hardprobe(Drive *dp, int cyl, int sec, int head)
+{
+ Controller *cp;
+
+ cp = dp->cp;
+ if(cmdreadywait(dp) < 0)
+ return -1;
+
+ /*
+ * start the transfer
+ */
+ cp->cmd = Cread;
+ cp->dp = dp;
+ cp->sofar = 0;
+ cp->nsecs = 1;
+ cp->status = 0;
+ outb(cp->pbase+Pcount, 1);
+ outb(cp->pbase+Psector, sec+1);
+ outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | head);
+ outb(cp->pbase+Pcyllsb, cyl);
+ outb(cp->pbase+Pcylmsb, cyl>>8);
+ outb(cp->pbase+Pcmd, Cread);
+
+ hardwait(cp);
+
+ if(cp->status & Serr)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * figure out the drive parameters
+ */
+static int
+hardparams(Drive *dp)
+{
+ int i, hi, lo;
+
+ /*
+ * first try the easy way, ask the drive and make sure it
+ * isn't lying.
+ */
+ dp->bytes = 512;
+ if(hardident(dp) < 0)
+ return -1;
+ if(dp->lba){
+ i = dp->sectors - 1;
+ if(hardprobe(dp, (i>>8)&0xffff, (i&0xff)-1, (i>>24)&0xf) == 0)
+ return 0;
+ } else {
+ if(hardprobe(dp, dp->cyl-1, dp->sectors-1, dp->heads-1) == 0)
+ return 0;
+ }
+
+ DPRINT("hardparam: cyl %d sectors %d heads %d\n", dp->cyl, dp->sectors, dp->heads);
+ /*
+ * the drive lied, determine parameters by seeing which ones
+ * work to read sectors.
+ */
+ dp->lba = 0;
+ for(i = 0; i < 16; i++)
+ if(hardprobe(dp, 0, 0, i) < 0)
+ break;
+ dp->heads = i;
+ for(i = 0; i < 64; i++)
+ if(hardprobe(dp, 0, i, 0) < 0)
+ break;
+ dp->sectors = i;
+ for(i = 512; ; i += 512)
+ if(hardprobe(dp, i, dp->sectors-1, dp->heads-1) < 0)
+ break;
+ lo = i - 512;
+ hi = i;
+ for(; hi-lo > 1;){
+ i = lo + (hi - lo)/2;
+ if(hardprobe(dp, i, dp->sectors-1, dp->heads-1) < 0)
+ hi = i;
+ else
+ lo = i;
+ }
+ dp->cyl = lo + 1;
+ dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
+
+ if(dp->cyl == 0 || dp->heads == 0 || dp->sectors == 0 || dp->cap == 0)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * read partition table. The partition table is just ascii strings.
+ */
+#define MAGIC "plan9 partitions"
+static void
+hardpart(Drive *dp)
+{
+ Partition *pp;
+ Controller *cp;
+ char *field[3], *line[Npart+1], *p, buf[NAMELEN];
+ ulong n;
+ int i;
+
+ cp = dp->cp;
+
+ /*
+ * we always have a partition for the whole disk
+ * and one for the partition table
+ */
+ pp = &dp->p[0];
+ strcpy(pp->name, "disk");
+ pp->start = 0;
+ pp->end = dp->cap / dp->bytes;
+ pp++;
+ strcpy(pp->name, "partition");
+ pp->start = dp->p[0].end - 1;
+ pp->end = dp->p[0].end;
+ dp->npart = 2;
+
+ /*
+ * Check if the partitions are described in plan9.ini.
+ * If not, read the disc.
+ */
+ sprint(buf, "hd%dpartition", dp->driveno);
+ if((p = getconf(buf)) == 0){
+ /*
+ * read last sector from disk, null terminate. This used
+ * to be the sector we used for the partition tables.
+ * However, this sector is special on some PC's so we've
+ * started to use the second last sector as the partition
+ * table instead. To avoid reconfiguring all our old systems
+ * we first look to see if there is a valid partition
+ * table in the last sector. If so, we use it. Otherwise
+ * we switch to the second last.
+ */
+ hardxfer(dp, pp, Cread, 0, dp->bytes);
+ cp->buf[dp->bytes-1] = 0;
+ n = getcfields(cp->buf, line, Npart+1, "\n");
+ if(n == 0 || strncmp(line[0], MAGIC, sizeof(MAGIC)-1)){
+ dp->p[0].end--;
+ dp->p[1].start--;
+ dp->p[1].end--;
+ hardxfer(dp, pp, Cread, 0, dp->bytes);
+ cp->buf[dp->bytes-1] = 0;
+ n = getcfields(cp->buf, line, Npart+1, "\n");
+ }
+ }
+ else{
+ strcpy(cp->buf, p);
+ n = getcfields(cp->buf, line, Npart+1, "\n");
+ }
+
+ /*
+ * parse partition table.
+ */
+ if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
+ for(i = 1; i < n; i++){
+ pp++;
+ if(getcfields(line[i], field, 3, " ") != 3)
+ break;
+ strncpy(pp->name, field[0], NAMELEN);
+ pp->start = strtoul(field[1], 0, 0);
+ pp->end = strtoul(field[2], 0, 0);
+ if(pp->start > pp->end || pp->start >= dp->p[0].end)
+ break;
+ dp->npart++;
+ }
+ }
+ return;
+}
+
+/*
+ * we get an interrupt for every sector transferred
+ */
+static void
+hardintr(Ureg*, void *arg)
+{
+ Controller *cp;
+ Drive *dp;
+ long loop;
+
+ cp = arg;
+ dp = cp->dp;
+
+ loop = 0;
+ while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy)
+ if(++loop > 100000){
+ print("hardintr 0x%lux\n", cp->status);
+ break;
+ }
+ switch(cp->cmd){
+ case Cread:
+ case Cident:
+ if(cp->status & Serr){
+ cp->cmd = 0;
+ cp->error = inb(cp->pbase+Perror);
+ return;
+ }
+ loop = 0;
+ while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
+ if(++loop > 100000){
+ print("hardintr 2 cmd %ux status %ux",
+ cp->cmd, inb(cp->pbase+Pstatus));
+ cp->cmd = 0;
+ return;
+ }
+ inss(cp->pbase+Pdata, &cp->buf[cp->sofar*dp->bytes],
+ dp->bytes/2);
+ cp->sofar++;
+ if(cp->sofar >= cp->nsecs){
+ if(cp->cmd == Cident && (cp->status & Sready) == 0)
+ cp->cmd = Cident2; /* sometimes we get a second intr */
+ else
+ cp->cmd = 0;
+ inb(cp->pbase+Pstatus);
+ }
+ break;
+ case Csetbuf:
+ case Cident2:
+ cp->cmd = 0;
+ break;
+ default:
+ cp->cmd = 0;
+ break;
+ }
+}
--- /dev/null
+++ b/os/boot.original/puma/io.h
@@ -1,0 +1,3 @@
+#define inb(port) sio_inb(port)
+#define outb(port, data) sio_outb(port, data)
+
--- /dev/null
+++ b/os/boot.original/puma/ip.h
@@ -1,0 +1,98 @@
+typedef struct Udphdr Udphdr;
+struct Udphdr
+{
+ uchar d[6]; /* Ethernet destination */
+ uchar s[6]; /* Ethernet source */
+ uchar type[2]; /* Ethernet packet type */
+
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+
+ /* Udp pseudo ip really starts here */
+ uchar ttl;
+ uchar udpproto; /* Protocol */
+ uchar udpplen[2]; /* Header plus data length */
+ uchar udpsrc[4]; /* Ip source */
+ uchar udpdst[4]; /* Ip destination */
+ uchar udpsport[2]; /* Source port */
+ uchar udpdport[2]; /* Destination port */
+ uchar udplen[2]; /* data length */
+ uchar udpcksum[2]; /* Checksum */
+};
+
+typedef struct Etherhdr Etherhdr;
+struct Etherhdr
+{
+ uchar d[6];
+ uchar s[6];
+ uchar type[2];
+
+ /* Now we have the ip fields */
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+ uchar ttl; /* Time to live */
+ uchar proto; /* Protocol */
+ uchar cksum[2]; /* Header checksum */
+ uchar src[4]; /* Ip source */
+ uchar dst[4]; /* Ip destination */
+};
+
+enum
+{
+ IP_VER = 0x40,
+ IP_HLEN = 0x05,
+ UDP_EHSIZE = 22,
+ UDP_PHDRSIZE = 12,
+ UDP_HDRSIZE = 20,
+ ETHER_HDR = 14,
+ IP_UDPPROTO = 17,
+ ET_IP = 0x800,
+ Bcastip = 0xffffffff,
+ BPportsrc = 68,
+ BPportdst = 67,
+ TFTPport = 69,
+ Timeout = 5000, /* milliseconds */
+ Bootrequest = 1,
+ Bootreply = 2,
+ Tftp_READ = 1,
+ Tftp_WRITE = 2,
+ Tftp_DATA = 3,
+ Tftp_ACK = 4,
+ Tftp_ERROR = 5,
+ Segsize = 512,
+ TFTPSZ = Segsize+10,
+};
+
+typedef struct Bootp Bootp;
+struct Bootp
+{
+ uchar op; /* opcode */
+ uchar htype; /* hardware type */
+ uchar hlen; /* hardware address len */
+ uchar hops; /* hops */
+ uchar xid[4]; /* a random number */
+ uchar secs[2]; /* elapsed snce client started booting */
+ uchar pad[2];
+ uchar ciaddr[4]; /* client IP address (client tells server) */
+ uchar yiaddr[4]; /* client IP address (server tells client) */
+ uchar siaddr[4]; /* server IP address */
+ uchar giaddr[4]; /* gateway IP address */
+ uchar chaddr[16]; /* client hardware address */
+ char sname[64]; /* server host name (optional) */
+ char file[128]; /* boot file name */
+ char vend[128]; /* vendor-specific goo */
+};
+
+typedef struct Netaddr Netaddr;
+struct Netaddr
+{
+ ulong ip;
+ ushort port;
+ char ea[Eaddrlen];
+};
--- /dev/null
+++ b/os/boot.original/puma/kbd.c
@@ -1,0 +1,482 @@
+#include "boot.h"
+
+
+enum {
+ Data= 0x60, /* data port */
+
+ Status= 0x64, /* status port */
+ Inready= 0x01, /* input character ready */
+ Outbusy= 0x02, /* output busy */
+ Sysflag= 0x04, /* system flag */
+ Cmddata= 0x08, /* cmd==0, data==1 */
+ Inhibit= 0x10, /* keyboard/mouse inhibited */
+ Minready= 0x20, /* mouse character ready */
+ Rtimeout= 0x40, /* general timeout */
+ Parity= 0x80,
+
+ Cmd= 0x64, /* command port (write only) */
+
+ Spec= 0x80,
+
+ PF= Spec|0x20, /* num pad function key */
+ View= Spec|0x00, /* view (shift window up) */
+ KF= Spec|0x40, /* function key */
+ Shift= Spec|0x60,
+ Break= Spec|0x61,
+ Ctrl= Spec|0x62,
+ Latin= Spec|0x63,
+ Caps= Spec|0x64,
+ Num= Spec|0x65,
+ No= Spec|0x7F, /* no mapping */
+
+ Home= KF|13,
+ Up= KF|14,
+ Pgup= KF|15,
+ Print= KF|16,
+ Left= View,
+ Right= View,
+ End= '\r',
+ Down= View,
+ Pgdown= View,
+ Ins= KF|20,
+ Del= 0x7F,
+};
+
+uchar kbtab[] =
+{
+[0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
+[0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
+[0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+[0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
+[0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+[0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
+[0x30] 'b', 'n', 'm', ',', '.', '/', Shift, No,
+[0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
+[0x48] No, No, No, No, No, No, No, No,
+[0x50] No, No, No, No, No, No, No, KF|11,
+[0x58] KF|12, No, No, No, No, No, No, No,
+};
+
+uchar kbtabshift[] =
+{
+[0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
+[0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
+[0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
+[0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
+[0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
+[0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
+[0x30] 'B', 'N', 'M', '<', '>', '?', Shift, No,
+[0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
+[0x48] No, No, No, No, No, No, No, No,
+[0x50] No, No, No, No, No, No, No, KF|11,
+[0x58] KF|12, No, No, No, No, No, No, No,
+};
+
+uchar kbtabesc1[] =
+{
+[0x00] No, No, No, No, No, No, No, No,
+[0x08] No, No, No, No, No, No, No, No,
+[0x10] No, No, No, No, No, No, No, No,
+[0x18] No, No, No, No, No, Ctrl, No, No,
+[0x20] No, No, No, No, No, No, No, No,
+[0x28] No, No, No, No, No, No, No, No,
+[0x30] No, No, No, No, No, No, No, Print,
+[0x38] Latin, No, No, No, No, No, No, No,
+[0x40] No, No, No, No, No, No, Break, Home,
+[0x48] Up, Pgup, No, Down, No, Right, No, End,
+[0x50] Left, Pgdown, Ins, Del, No, No, No, No,
+[0x58] No, No, No, No, No, No, No, No,
+};
+
+struct latin
+{
+ uchar l;
+ char c[2];
+}latintab[] = {
+ L'¡', "!!", /* spanish initial ! */
+ L'¢', "c|", /* cent */
+ L'¢', "c$", /* cent */
+ L'£', "l$", /* pound sterling */
+ L'¤', "g$", /* general currency */
+ L'¥', "y$", /* yen */
+ L'¥', "j$", /* yen */
+ L'¦', "||", /* broken vertical bar */
+ L'§', "SS", /* section symbol */
+ L'¨', "\"\"", /* dieresis */
+ L'©', "cr", /* copyright */
+ L'©', "cO", /* copyright */
+ L'ª', "sa", /* super a, feminine ordinal */
+ L'«', "<<", /* left angle quotation */
+ L'¬', "no", /* not sign, hooked overbar */
+ L'', "--", /* soft hyphen */
+ L'®', "rg", /* registered trademark */
+ L'¯', "__", /* macron */
+ L'°', "s0", /* degree (sup o) */
+ L'±', "+-", /* plus-minus */
+ L'²', "s2", /* sup 2 */
+ L'³', "s3", /* sup 3 */
+ L'´', "''", /* grave accent */
+ L'µ', "mu", /* mu */
+ L'¶', "pg", /* paragraph (pilcrow) */
+ L'·', "..", /* centered . */
+ L'¸', ",,", /* cedilla */
+ L'¹', "s1", /* sup 1 */
+ L'º', "so", /* sup o */
+ L'»', ">>", /* right angle quotation */
+ L'¼', "14", /* 1/4 */
+ L'½', "12", /* 1/2 */
+ L'¾', "34", /* 3/4 */
+ L'¿', "??", /* spanish initial ? */
+ L'À', "A`", /* A grave */
+ L'Á', "A'", /* A acute */
+ L'Â', "A^", /* A circumflex */
+ L'Ã', "A~", /* A tilde */
+ L'Ä', "A\"", /* A dieresis */
+ L'Ä', "A:", /* A dieresis */
+ L'Å', "Ao", /* A circle */
+ L'Å', "AO", /* A circle */
+ L'Æ', "Ae", /* AE ligature */
+ L'Æ', "AE", /* AE ligature */
+ L'Ç', "C,", /* C cedilla */
+ L'È', "E`", /* E grave */
+ L'É', "E'", /* E acute */
+ L'Ê', "E^", /* E circumflex */
+ L'Ë', "E\"", /* E dieresis */
+ L'Ë', "E:", /* E dieresis */
+ L'Ì', "I`", /* I grave */
+ L'Í', "I'", /* I acute */
+ L'Î', "I^", /* I circumflex */
+ L'Ï', "I\"", /* I dieresis */
+ L'Ï', "I:", /* I dieresis */
+ L'Ð', "D-", /* Eth */
+ L'Ñ', "N~", /* N tilde */
+ L'Ò', "O`", /* O grave */
+ L'Ó', "O'", /* O acute */
+ L'Ô', "O^", /* O circumflex */
+ L'Õ', "O~", /* O tilde */
+ L'Ö', "O\"", /* O dieresis */
+ L'Ö', "O:", /* O dieresis */
+ L'Ö', "OE", /* O dieresis */
+ L'Ö', "Oe", /* O dieresis */
+ L'×', "xx", /* times sign */
+ L'Ø', "O/", /* O slash */
+ L'Ù', "U`", /* U grave */
+ L'Ú', "U'", /* U acute */
+ L'Û', "U^", /* U circumflex */
+ L'Ü', "U\"", /* U dieresis */
+ L'Ü', "U:", /* U dieresis */
+ L'Ü', "UE", /* U dieresis */
+ L'Ü', "Ue", /* U dieresis */
+ L'Ý', "Y'", /* Y acute */
+ L'Þ', "P|", /* Thorn */
+ L'Þ', "Th", /* Thorn */
+ L'Þ', "TH", /* Thorn */
+ L'ß', "ss", /* sharp s */
+ L'à', "a`", /* a grave */
+ L'á', "a'", /* a acute */
+ L'â', "a^", /* a circumflex */
+ L'ã', "a~", /* a tilde */
+ L'ä', "a\"", /* a dieresis */
+ L'ä', "a:", /* a dieresis */
+ L'å', "ao", /* a circle */
+ L'æ', "ae", /* ae ligature */
+ L'ç', "c,", /* c cedilla */
+ L'è', "e`", /* e grave */
+ L'é', "e'", /* e acute */
+ L'ê', "e^", /* e circumflex */
+ L'ë', "e\"", /* e dieresis */
+ L'ë', "e:", /* e dieresis */
+ L'ì', "i`", /* i grave */
+ L'í', "i'", /* i acute */
+ L'î', "i^", /* i circumflex */
+ L'ï', "i\"", /* i dieresis */
+ L'ï', "i:", /* i dieresis */
+ L'ð', "d-", /* eth */
+ L'ñ', "n~", /* n tilde */
+ L'ò', "o`", /* o grave */
+ L'ó', "o'", /* o acute */
+ L'ô', "o^", /* o circumflex */
+ L'õ', "o~", /* o tilde */
+ L'ö', "o\"", /* o dieresis */
+ L'ö', "o:", /* o dieresis */
+ L'ö', "oe", /* o dieresis */
+ L'÷', "-:", /* divide sign */
+ L'ø', "o/", /* o slash */
+ L'ù', "u`", /* u grave */
+ L'ú', "u'", /* u acute */
+ L'û', "u^", /* u circumflex */
+ L'ü', "u\"", /* u dieresis */
+ L'ü', "u:", /* u dieresis */
+ L'ü', "ue", /* u dieresis */
+ L'ý', "y'", /* y acute */
+ L'þ', "th", /* thorn */
+ L'þ', "p|", /* thorn */
+ L'ÿ', "y\"", /* y dieresis */
+ L'ÿ', "y:", /* y dieresis */
+ 0, 0,
+};
+
+enum
+{
+ /* controller command byte */
+ Cscs1= (1<<6), /* scan code set 1 */
+ Cmousedis= (1<<5), /* mouse disable */
+ Ckbddis= (1<<4), /* kbd disable */
+ Csf= (1<<2), /* system flag */
+ Cmouseint= (1<<1), /* mouse interrupt enable */
+ Ckbdint= (1<<0), /* kbd interrupt enable */
+};
+
+static uchar ccc;
+
+int
+latin1(int k1, int k2)
+{
+ struct latin *l;
+
+ for(l=latintab; l->l; l++)
+ if(k1==l->c[0] && k2==l->c[1])
+ return l->l;
+ return 0;
+}
+
+/*
+ * wait for output no longer busy
+ */
+static int
+outready(void)
+{
+ int tries;
+
+ for(tries = 0; (inb(Status) & Outbusy); tries++){
+ if(tries > 500)
+ return -1;
+ delay(2);
+ }
+ return 0;
+}
+
+/*
+ * wait for input
+ */
+static int
+inready(void)
+{
+ int tries;
+
+ for(tries = 0; !(inb(Status) & Inready); tries++){
+ if(tries > 500)
+ return -1;
+ delay(2);
+ }
+ return 0;
+}
+
+/*
+ * ask 8042 to enable the use of address bit 20
+ */
+void
+i8042a20(void)
+{
+ outready();
+ outb(Cmd, 0xD1);
+ outready();
+ outb(Data, 0xDF);
+ outready();
+}
+
+/*
+ * ask 8042 to reset the machine
+ */
+void
+i8042reset(void)
+{
+ ushort *s = (ushort*)(KZERO|0x472);
+ int i, x;
+
+ *s = 0x1234; /* BIOS warm-boot flag */
+
+ outready();
+ outb(Cmd, 0xFE); /* pulse reset line (means resend on AT&T machines) */
+ outready();
+
+ /*
+ * Pulse it by hand (old somewhat reliable)
+ */
+ x = 0xDF;
+ for(i = 0; i < 5; i++){
+ x ^= 1;
+ outready();
+ outb(Cmd, 0xD1);
+ outready();
+ outb(Data, x); /* toggle reset */
+ delay(100);
+ }
+}
+
+/*
+ * keyboard interrupt
+ */
+int
+kbdintr0(void)
+{
+ int s, c;
+ static int esc1, esc2;
+ static int shift;
+ static int caps;
+ static int ctl;
+ static int num;
+ static int lstate, k1, k2;
+ int keyup;
+
+ /*
+ * get status
+ */
+ s = inb(Status);
+ if(!(s&Inready))
+ return -1;
+
+ /*
+ * get the character
+ */
+ c = inb(Data);
+
+ /*
+ * e0's is the first of a 2 character sequence
+ */
+ if(c == 0xe0){
+ esc1 = 1;
+ return 0;
+ } else if(c == 0xe1){
+ esc2 = 2;
+ return 0;
+ }
+
+ keyup = c&0x80;
+ c &= 0x7f;
+ if(c > sizeof kbtab){
+ print("unknown key %ux\n", c|keyup);
+ kbdchar(0, k1);
+ return 0;
+ }
+
+ if(esc1){
+ c = kbtabesc1[c];
+ esc1 = 0;
+ kbdchar(0, c);
+ return 0;
+ } else if(esc2){
+ esc2--;
+ return 0;
+ } else if(shift)
+ c = kbtabshift[c];
+ else
+ c = kbtab[c];
+
+ if(caps && c<='z' && c>='a')
+ c += 'A' - 'a';
+
+ /*
+ * keyup only important for shifts
+ */
+ if(keyup){
+ switch(c){
+ case Shift:
+ shift = 0;
+ break;
+ case Ctrl:
+ ctl = 0;
+ break;
+ }
+ return 0;
+ }
+
+ /*
+ * normal character
+ */
+ if(!(c & Spec)){
+ if(ctl)
+ c &= 0x1f;
+ switch(lstate){
+ case 1:
+ k1 = c;
+ lstate = 2;
+ return 0;
+ case 2:
+ k2 = c;
+ lstate = 0;
+ c = latin1(k1, k2);
+ if(c == 0){
+ kbdchar(0, k1);
+ c = k2;
+ }
+ /* fall through */
+ default:
+ break;
+ }
+ } else {
+ switch(c){
+ case Caps:
+ caps ^= 1;
+ return 0;
+ case Num:
+ num ^= 1;
+ return 0;
+ case Shift:
+ shift = 1;
+ return 0;
+ case Latin:
+ lstate = 1;
+ return 0;
+ case Ctrl:
+ ctl = 1;
+ return 0;
+ }
+ }
+ kbdchar(0, c);
+ return 0;
+}
+
+static void
+kbdintr(Ureg*, void*)
+{
+ while(kbdintr0() == 0)
+ ;
+}
+
+static char *initfailed = "kbd init failed\n";
+
+void
+kbdinit(void)
+{
+ int c;
+
+ /* wait for a quiescent controller */
+ while((c = inb(Status)) & (Outbusy | Inready))
+ if(c & Inready)
+ inb(Data);
+
+ /* get current controller command byte */
+ outb(Cmd, 0x20);
+ if(inready() < 0){
+ print("kbdinit: can't read ccc\n");
+ ccc = 0;
+ } else
+ ccc = inb(Data);
+
+ /* enable kbd xfers and interrupts */
+ ccc &= ~Ckbddis;
+ ccc |= Csf | Ckbdint | Cscs1;
+ if(outready() < 0)
+ print(initfailed);
+ outb(Cmd, 0x60);
+ if(outready() < 0)
+ print(initfailed);
+ outb(Data, ccc);
+ if(outready() < 0)
+ print(initfailed);
+
+ setvec(V_KEYBOARD, kbdintr, 0);
+}
--- /dev/null
+++ b/os/boot.original/puma/l.s
@@ -1,0 +1,427 @@
+/*
+ * File: l.s
+ * Purpose:
+ * Puma Board StrongARM 110 Architecture Specific Assembly
+ *
+ */
+
+#include "mem.h"
+#include "armv4.h"
+#include "puma.h"
+
+#define DRAMWAIT 100000 /* 3.125μsec per iteration */
+#define TL750R(r) (TL750_BASE+(r)*4)
+
+#define BOOTBASE 0x00200000
+
+TEXT _main(SB),1,$-4
+ MOVW R15, R7 /* save PC on entry */
+
+/*
+ * initialise DRAM controller on the TL750 (SDRAM mode)
+ */
+ MOVW $DRAMWAIT, R0 /* wait 312 ms after reset before touching DRAM */
+dram1:
+ SUB.S $1, R0
+ BNE dram1
+
+ MOVW $TL750R(0x103), R0 /* DMC_DELAY */
+ MOVW $0x03333333, R1 /* DRAM timing parameters */
+ MOVW R1, (R0)
+
+ MOVW $TL750R(0x101), R0 /* DMC_SDRAM */
+ MOVW $0x03133011, R1 /* SDRAM parameters for Puma */
+ MOVW R1, (R0)
+
+ MOVW $DRAMWAIT, R0 /* wait 312 ms for initialisation */
+dram2:
+ SUB.S $1, R0
+ BNE dram2
+
+ MOVW $setR12(SB),R12
+
+/*
+ * copy bootstrap to final location in DRAM
+ */
+ MOVW R7, baddr(SB)
+ MOVW $(BOOTBASE+8), R0
+ CMP R0, R7
+ BEQ inplace
+ MOVW $((128*1024)/4), R6
+copyboot:
+ MOVW.P 4(R7), R5
+ MOVW.P R5, 4(R0)
+ SUB.S $1, R6
+ BNE copyboot
+ MOVW $bootrel(SB), R7
+ MOVW R7, R15
+
+TEXT bootrel(SB), $-4
+
+/*
+ * set C environment and invoke main
+ */
+inplace:
+ MOVW $mach0(SB),R13
+ MOVW R13,m(SB)
+ ADD $(MACHSIZE-12),R13
+
+ /* disable MMU activity */
+ BL mmuctlregr(SB)
+ BIC $(CpCmmu|CpCDcache|CpCwb|CpCIcache), R0
+ BL mmuctlregw(SB)
+
+ BL main(SB)
+loop:
+ B loop
+
+TEXT idle(SB),$0
+ RET
+
+/*
+ * basic timing loop to determine CPU frequency
+ */
+TEXT aamloop(SB), $-4 /* 3 */
+_aamloop:
+ MOVW R0, R0 /* 1 */
+ MOVW R0, R0 /* 1 */
+ MOVW R0, R0 /* 1 */
+ SUB $1, R0 /* 1 */
+ CMP $0, R0 /* 1 */
+ BNE _aamloop /* 3 */
+ RET /* 3 */
+
+/*
+ * Function: setr13( mode, pointer )
+ * Purpose:
+ * Sets the stack pointer for a particular mode
+ */
+
+TEXT setr13(SB), $-4
+ MOVW 4(FP), R1
+
+ MOVW CPSR, R2
+ BIC $PsrMask, R2, R3
+ ORR R0, R3
+ MOVW R3, CPSR
+
+ MOVW R13, R0
+ MOVW R1, R13
+
+ MOVW R2, CPSR
+
+ RET
+
+/*
+ * Function: _vundcall
+ * Purpose:
+ * Undefined Instruction Trap Handler
+ *
+ */
+
+TEXT _vundcall(SB), $-4
+_vund:
+ MOVM.DB [R0-R3], (R13)
+ MOVW $PsrMund, R0
+ B _vswitch
+
+/*
+ * Function: _vsvccall
+ * Purpose:
+ * Reset or SWI Handler
+ *
+ */
+
+TEXT _vsvccall(SB), $-4
+_vsvc:
+ SUB $12, R13
+ MOVW R14, 8(R13)
+ MOVW CPSR, R14
+ MOVW R14, 4(R13)
+ MOVW $PsrMsvc, R14
+ MOVW R14, (R13)
+ B _vsaveu
+
+/*
+ * Function: _pabcall
+ * Purpose:
+ * Prefetch Abort Trap Handler
+ *
+ */
+
+TEXT _vpabcall(SB), $-4
+_vpab:
+ MOVM.DB [R0-R3], (R13)
+ MOVW $PsrMabt, R0
+ B _vswitch
+
+/*
+ * Function: _vdabcall
+ * Purpose:
+ * Data Abort Trap Handler
+ *
+ */
+
+TEXT _vdabcall(SB), $-4
+_vdab:
+ MOVM.DB [R0-R3], (R13)
+ MOVW $(PsrMabt+1), R0
+ B _vswitch
+
+/*
+ * Function: _virqcall
+ * Purpose:
+ * IRQ Trap Handler
+ *
+ */
+
+TEXT _virqcall(SB), $-4 /* IRQ */
+_virq:
+ MOVM.DB [R0-R3], (R13)
+ MOVW $PsrMirq, R0
+ B _vswitch
+
+/*
+ * Function: _vfiqcall
+ * Purpose:
+ * FIQ Trap Handler
+ *
+ */
+
+TEXT _vfiqcall(SB), $-4 /* FIQ */
+_vfiq:
+ MOVM.DB [R0-R3], (R13)
+ MOVW $PsrMfiq, R0
+ /* FALLTHROUGH */
+
+_vswitch: /* switch to svc mode */
+ MOVW SPSR, R1
+ MOVW R14, R2
+ MOVW R13, R3
+
+ MOVW CPSR, R14
+ BIC $PsrMask, R14
+ ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
+ MOVW R14, CPSR
+
+ MOVM.DB.W [R0-R2], (R13)
+ MOVM.DB (R3), [R0-R3]
+
+_vsaveu: /* Save Registers */
+ SUB $4, R13 /* save link */
+ MOVW R14, (R13) /* MOVW.W R14,4(R13)*/
+
+ SUB $8, R13
+
+ MOVW R13, R14 /* ur->sp */
+ ADD $(6*4), R14
+ MOVW R14, 0(R13)
+
+ MOVW 8(SP), R14 /* ur->link */
+ MOVW R14, 4(SP)
+
+ MOVM.DB.W [R0-R12], (R13)
+ MOVW R0, R0 /* gratuitous noop */
+
+ MOVW $setR12(SB), R12 /* static base (SB) */
+ MOVW R13, R0 /* argument is ureg */
+ SUB $8, R13 /* space for arg+lnk*/
+ BL trap(SB)
+
+
+_vrfe: /* Restore Regs */
+ MOVW CPSR, R0 /* splhi on return */
+ ORR $(PsrDirq|PsrDfiq), R0, R1
+ MOVW R1, CPSR
+ ADD $(8+4*15), R13 /* [r0-R14]+argument+link */
+ MOVW (R13), R14 /* restore link */
+ MOVW 8(R13), R0
+ MOVW R0, SPSR
+ MOVM.DB.S (R13), [R0-R14] /* restore user registers */
+ MOVW R0, R0 /* gratuitous nop */
+ ADD $12, R13 /* skip saved link+type+SPSR*/
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+
+/*
+ * Function: splhi
+ * Purpose:
+ * Disable Interrupts
+ * Returns:
+ * Previous interrupt state
+ */
+
+TEXT splhi(SB), $-4
+ MOVW CPSR, R0
+ ORR $(PsrDirq|PsrDfiq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+/*
+ * Function: spllo
+ * Purpose:
+ * Enable Interrupts
+ * Returns:
+ * Previous interrupt state
+ */
+
+TEXT spllo(SB), $-4
+ MOVW CPSR, R0
+ BIC $(PsrDirq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+/*
+ * Function: splx(level)
+ * Purpose:
+ * Restore interrupt level
+ */
+
+TEXT splx(SB), $-4
+ MOVW R0, R1
+ MOVW CPSR, R0
+ MOVW R1, CPSR
+ RET
+
+/*
+ * Function: islo
+ * Purpose:
+ * Check if interrupts are enabled
+ *
+ */
+
+TEXT islo(SB), $-4
+ MOVW CPSR, R0
+ AND $(PsrDirq), R0
+ EOR $(PsrDirq), R0
+ RET
+
+/*
+ * Function: cpsrr
+ * Purpose:
+ * Returns current program status register
+ *
+ */
+
+TEXT cpsrr(SB), $-4
+ MOVW CPSR, R0
+ RET
+
+/*
+ * Function: spsrr
+ * Purpose:
+ * Returns saved program status register
+ *
+ */
+
+TEXT spsrr(SB), $-4
+ MOVW SPSR, R0
+ RET
+
+/*
+ * MMU Operations
+ */
+TEXT mmuctlregr(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0)
+ RET
+
+TEXT mmuctlregw(SB), $-4
+ MCR CpMMU, 0, R0, C(CpControl), C(0)
+ MOVW R0, R0
+ MOVW R0, R0
+ RET
+
+/*
+ * Cache Routines
+ */
+
+/*
+ * Function: flushIcache
+ * Purpose:
+ * Flushes the *WHOLE* instruction cache
+ */
+
+TEXT flushIcache(SB), $-4
+ MCR CpMMU, 0, R0, C(CpCacheCtl), C(5), 0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ RET
+
+
+
+/*
+ * Function: flushDentry
+ * Purpose:
+ * Flushes an entry of the data cache
+ */
+
+TEXT flushDentry(SB), $-4
+ MCR CpMMU, 0, R0, C(CpCacheCtl), C(6), 1
+ RET
+
+/*
+ * Function: drainWBuffer
+ * Purpose:
+ * Drains the Write Buffer
+ */
+
+TEXT drainWBuffer(SB), $-4
+ MCR CpMMU, 0, R0, C(CpCacheCtl), C(10), 4
+ RET
+
+/*
+ * Function: writeBackDC
+ * Purpose:
+ * Drains the dcache prior to flush
+ */
+
+TEXT writeBackDC(SB), $-4
+ MOVW $0xE0000000, R0
+ MOVW $8192, R1
+ ADD R0, R1
+
+wbflush:
+ MOVW (R0), R2
+ ADD $32, R0
+ CMP R1,R0
+ BNE wbflush
+ RET
+
+/*
+ * Function: flushDcache(SB)
+ * Purpose:
+ * Flush the dcache
+ */
+
+TEXT flushDcache(SB), $-4
+ MCR CpMMU, 0, R0, C(CpCacheCtl), C(6), 0
+ RET
+
+/*
+ * Function: writeBackBDC(SB)
+ * Purpose:
+ * Write back the Baby D-Cache
+ */
+
+TEXT writeBackBDC(SB), $-4
+ MOVW $0xE4000000, R0
+ MOVW $0x200, R1
+ ADD R0, R1
+
+wbbflush:
+ MOVW (R0), R2
+ ADD $32, R0
+ CMP R1,R0
+ BNE wbbflush
+ MCR CpMMU, 0, R0, C(CpCacheCtl), C(10), 4
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ RET
+
+GLOBL mach0+0(SB), $MACHSIZE
+GLOBL m(SB), $4
+GLOBL baddr(SB), $4
--- /dev/null
+++ b/os/boot.original/puma/lib.h
@@ -1,0 +1,107 @@
+/*
+ * functions (possibly) linked in, complete, from libc.
+ */
+
+/*
+ * mem routines
+ */
+extern void* memccpy(void*, void*, int, long);
+extern void* memset(void*, int, long);
+extern int memcmp(void*, void*, long);
+extern void* memmove(void*, void*, long);
+extern void* memchr(void*, int, long);
+
+/*
+ * string routines
+ */
+extern char* strcat(char*, char*);
+extern char* strchr(char*, char);
+extern int strcmp(char*, char*);
+extern char* strcpy(char*, char*);
+extern char* strncat(char*, char*, long);
+extern char* strncpy(char*, char*, long);
+extern int strncmp(char*, char*, long);
+extern long strlen(char*);
+extern char* strrchr(char*, char);
+extern char* strstr(char*, char*);
+
+/*
+ * print routines
+ * Fconv isn't used but is defined to satisfy prototypes in libg.h
+ * that are never called.
+ */
+typedef struct Fconv Fconv;
+
+extern char* donprint(char*, char*, char*, void*);
+extern int sprint(char*, char*, ...);
+extern int print(char*, ...);
+
+#define PRINTSIZE 256
+
+/*
+ * one-of-a-kind
+ */
+extern int atoi(char*);
+extern long strtol(char*, char**, int);
+extern ulong strtoul(char*, char**, int);
+extern char end[];
+extern char edata[];
+
+/*
+ * Syscall data structures
+ */
+
+#define MORDER 0x0003 /* mask for bits defining order of mounting */
+#define MREPL 0x0000 /* mount replaces object */
+#define MBEFORE 0x0001 /* mount goes before others in union directory */
+#define MAFTER 0x0002 /* mount goes after others in union directory */
+#define MCREATE 0x0004 /* permit creation in mounted directory */
+#define MMASK 0x0007 /* all bits on */
+
+#define OREAD 0 /* open for read */
+#define OWRITE 1 /* write */
+#define ORDWR 2 /* read and write */
+#define OEXEC 3 /* execute, == read but check execute permission */
+#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
+#define OCEXEC 32 /* or'ed in, close on exec */
+#define ORCLOSE 64 /* or'ed in, remove on close */
+
+#define NCONT 0 /* continue after note */
+#define NDFLT 1 /* terminate after note */
+
+typedef struct Qid Qid;
+typedef struct Dir Dir;
+typedef struct Waitmsg Waitmsg;
+
+#define ERRLEN 64
+#define DIRLEN 116
+#define NAMELEN 28
+
+struct Qid
+{
+ ulong path;
+ ulong vers;
+};
+
+struct Dir
+{
+ char name[NAMELEN];
+ char uid[NAMELEN];
+ char gid[NAMELEN];
+ Qid qid;
+ ulong mode;
+ long atime;
+ long mtime;
+ ulong length;
+ short type;
+ short dev;
+};
+
+struct Waitmsg
+{
+ int pid; /* of loved one */
+ int status; /* unused; a placeholder */
+ ulong time[3]; /* of loved one */
+ char msg[ERRLEN];
+};
+#define nelem(x) (sizeof(x)/sizeof((x)[0]))
--- /dev/null
+++ b/os/boot.original/puma/main.c
@@ -1,0 +1,552 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "dosfs.h"
+
+typedef struct Type Type;
+typedef struct Medium Medium;
+typedef struct Mode Mode;
+
+enum {
+ Dany = -1,
+ Nmedia = 16,
+
+ /* DS1 switch options */
+ Sflashfs = 1<<0, /* take local fs from flash */
+ Snotflash = 1<<1, /* don't boot from flash */
+};
+
+enum { /* type */
+ Tflash,
+ Tether,
+ Thard,
+
+ Tany = -1,
+};
+
+enum { /* flag and name */
+ Fnone = 0x00,
+
+ Fdos = 0x01,
+ Ndos = 0x00,
+ Fboot = 0x02,
+ Nboot = 0x01,
+ Fbootp = 0x04,
+ Nbootp = 0x02,
+ Fflash = 0x08,
+ NName = 0x03,
+
+ Fany = Fbootp|Fboot|Fdos|Fflash,
+
+ Fini = 0x10,
+ Fprobe = 0x80,
+};
+
+enum { /* mode */
+ Mauto = 0x00,
+ Mlocal = 0x01,
+ Manual = 0x02,
+ NMode = 0x03,
+};
+
+typedef struct Type {
+ int type;
+ char *cname;
+ int flag;
+ int (*init)(void);
+ long (*read)(int, void*, long);
+ long (*seek)(int, long);
+ Partition* (*setpart)(int, char*);
+ char* name[NName];
+
+ int mask;
+ Medium* media;
+} Type;
+
+typedef struct Medium {
+ Type* type;
+ int flag;
+ Partition* partition;
+ Dos;
+
+ Medium* next;
+} Medium;
+
+typedef struct Mode {
+ char* name;
+ int mode;
+} Mode;
+
+static Type types[] = {
+ { Tflash, "flash",
+ Fflash,
+ flashinit, 0, 0, 0,
+ { 0, "F", 0, }
+ },
+ { Tether, "ether",
+ Fbootp,
+ etherinit, 0, 0, 0,
+ { 0, 0, "e", },
+ },
+ { Thard, "ata",
+ Fini|Fboot|Fdos,
+ 0, 0, 0, 0, /* not used now, will be later with PCMCIA */
+ { "hd", "h", 0, },
+ },
+ {-1},
+};
+
+static Medium media[Nmedia];
+static Medium *curmedium = media;
+
+static Mode modes[NMode+1] = {
+ [Mauto] { "auto", Mauto, },
+ [Mlocal] { "local", Mlocal, },
+ [Manual] { "manual", Manual, },
+};
+
+static char *inis[] = {
+ "inferno/inferno.ini",
+ "inferno.ini",
+ "plan9/plan9.ini",
+ "plan9.ini",
+ 0,
+};
+char **ini;
+void printversion(void);
+
+static int
+parse(char *line, int *type, int *flag, int *dev, char *file)
+{
+ Type *tp;
+ char buf[2*NAMELEN], *v[4], *p;
+ int i;
+
+ strcpy(buf, line);
+ switch(getcfields(buf, v, 4, "!")){
+
+ case 3:
+ break;
+
+ case 2:
+ v[2] = "";
+ break;
+
+ default:
+ return 0;
+ }
+
+ *flag = 0;
+ for(tp = types; tp->cname; tp++){
+ for(i = 0; i < NName; i++){
+
+ if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
+ continue;
+ *type = tp->type;
+ *flag |= 1<<i;
+
+ if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
+ return 0;
+
+ strcpy(file, v[2]);
+
+ return 1;
+ }
+ }
+
+ return 0;
+
+}
+
+static int
+boot(Medium *mp, int flag, char *file)
+{
+ Dosfile df;
+ char ixdos[128], *p;
+
+ if(flag & Fbootp){
+ sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
+ return bootp(mp->dev, file);
+ }
+
+ if(flag & Fflash){
+ if(mp->flag & Fflash && flashbootable(0))
+ flashboot(mp->dev);
+ }
+
+ if(flag & Fboot){
+
+ if(mp->flag & Fini){
+ (*mp->type->setpart)(mp->dev, "disk");
+ plan9ini(mp, nil);
+ }
+ if(file == 0 || *file == 0)
+ file = mp->partition->name;
+ (*mp->type->setpart)(mp->dev, file);
+ sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
+ return plan9boot(mp->dev, mp->seek, mp->read);
+ }
+
+ if(flag & Fdos){
+ if(mp->type->setpart)
+ (*mp->type->setpart)(mp->dev, "disk");
+ if(mp->flag & Fini)
+ plan9ini(mp, nil);
+ if(file == 0 || *file == 0){
+ strcpy(ixdos, *ini);
+ if(p = strrchr(ixdos, '/'))
+ p++;
+ else
+ p = ixdos;
+ strcpy(p, "infernopuma");
+ if(dosstat(mp, ixdos, &df) <= 0)
+ return -1;
+ }
+ else
+ strcpy(ixdos, file);
+ sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
+ return dosboot(mp, ixdos);
+ }
+
+ return -1;
+}
+
+static Medium*
+allocm(Type *tp)
+{
+ Medium **l;
+
+ if(curmedium >= &media[Nmedia])
+ return 0;
+
+ for(l = &tp->media; *l; l = &(*l)->next)
+ ;
+ *l = curmedium++;
+ return *l;
+}
+
+Medium*
+probe(int type, int flag, int dev)
+{
+ Type *tp;
+ int dombr, i, start;
+ Medium *mp;
+ Dosfile df;
+ Partition *pp;
+
+ for(tp = types; tp->cname; tp++){
+ if(type != Tany && type != tp->type || tp->init == 0)
+ continue;
+
+ if(flag != Fnone){
+ for(mp = tp->media; mp; mp = mp->next){
+ if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
+ return mp;
+ }
+ }
+ if((tp->flag & Fprobe) == 0){
+ tp->flag |= Fprobe;
+ tp->mask = (*tp->init)();
+ }
+
+ for(i = 0; tp->mask; i++){
+ if((tp->mask & (1<<i)) == 0)
+ continue;
+ tp->mask &= ~(1<<i);
+
+ if((mp = allocm(tp)) == 0)
+ continue;
+
+ mp->dev = i;
+ mp->flag = tp->flag;
+ mp->seek = tp->seek;
+ mp->read = tp->read;
+ mp->type = tp;
+
+ if(mp->flag & Fboot){
+ if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
+ mp->flag &= ~Fboot;
+ if((mp->flag & Fflash) == 0)
+ (*tp->setpart)(i, "disk");
+ }
+
+ if(mp->flag & Fdos){
+ start = 0;
+ dombr = 1;
+ if(mp->type->setpart){
+ if(pp = (*mp->type->setpart)(i, "dos")){
+ if(start = pp->start)
+ dombr = 0;
+ }
+ (*tp->setpart)(i, "disk");
+ }
+ if(dosinit(mp, start, dombr) < 0)
+ mp->flag &= ~(Fini|Fdos);
+ else
+ print("dos init failed\n");
+ }
+
+ if(mp->flag & Fini){
+ mp->flag &= ~Fini;
+ for(ini = inis; *ini; ini++){
+ if(dosstat(mp, *ini, &df) <= 0)
+ continue;
+ mp->flag |= Fini;
+ break;
+ }
+ }
+
+ if((flag & mp->flag) && (dev == Dany || dev == i))
+ return mp;
+ }
+ }
+
+ return 0;
+}
+
+static void
+pause(void)
+{
+ long d;
+ for(d=0; d<10000000; d++)
+ ;
+ USED(d);
+}
+
+static void
+flash(int n)
+{
+ int i;
+
+ if(n <= 0)
+ return;
+ for(i=0; i<n-1; i++) {
+ led(1);
+ pause();
+ led(0);
+ pause();
+ }
+ led(1);
+ pause();pause();pause();
+ led(0);
+ pause();pause();pause();
+}
+
+void
+main(void)
+{
+ Medium *mp;
+ int dev, flag, i, mode, tried, type, options;
+ char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
+ Type *tp;
+
+ memset(edata, 0, end-edata ); /* clear the BSS */
+ pumainit();
+
+ machinit();
+ meminit();
+ trapinit();
+ consinit(); /* screen and keyboard initially */
+// screeninit();
+ alarminit();
+ clockinit();
+ printversion();
+
+ spllo();
+ options = optionsw();
+
+
+ mp = 0;
+ for(tp = types; tp->cname; tp++){
+ if(tp->type == Tether)
+ continue;
+ if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
+ plan9ini(mp, nil);
+ break;
+ }
+ }
+
+ if(mp == 0 || (mp->flag & Fini) == 0)
+ plan9ini(nil, flashconfig(0));
+
+ //consinit(); /* establish new console location */
+
+ if((options & Snotflash) == 0 && flashbootable(0)){
+ print("Flash boot\n");
+ flashboot(0);
+ }
+
+ tried = 0;
+ mode = Mauto;
+ p = getconf("bootfile");
+ flag = 0;
+
+ if(p != 0) {
+ mode = Manual;
+ for(i = 0; i < NMode; i++){
+ if(strcmp(p, modes[i].name) == 0){
+ mode = modes[i].mode;
+ goto done;
+ }
+ }
+ if(parse(p, &type, &flag, &dev, file) == 0) {
+ print("Bad bootfile syntax: %s\n", p);
+ goto done;
+ }
+ mp = probe(type, flag, dev);
+ if(mp == 0) {
+ print("Cannot access device: %s\n", p);
+ goto done;
+ }
+ tried = boot(mp, flag, file);
+ }
+done:
+ if(tried == 0 && mode != Manual){
+ flag = Fany;
+ if(mode == Mlocal)
+ flag &= ~Fbootp;
+ if(options & Snotflash)
+ flag &= ~Fflash;
+ if((mp = probe(Tany, flag, Dany)) != 0)
+ boot(mp, flag & mp->flag, 0);
+ }
+
+ def[0] = 0;
+ probe(Tany, Fnone, Dany);
+
+ flag = 0;
+ for(tp = types; tp->cname; tp++){
+ for(mp = tp->media; mp; mp = mp->next){
+ if(flag == 0){
+ flag = 1;
+ print("Boot devices:");
+ }
+
+ if(mp->flag & Fbootp)
+ print(" %s!%d", mp->type->name[Nbootp], mp->dev);
+ if(mp->flag & Fdos)
+ print(" %s!%d", mp->type->name[Ndos], mp->dev);
+ if(mp->flag & Fflash || mp->flag & Fboot)
+ print(" %s!%d", mp->type->name[Nboot], mp->dev);
+ }
+ }
+ if(flag)
+ print("\n");
+
+ for(;;){
+ if(getstr("boot from", line, sizeof(line), def) >= 0){
+ if(parse(line, &type, &flag, &dev, file)){
+ if(mp = probe(type, flag, dev))
+ boot(mp, flag, file);
+ }
+ }
+ def[0] = 0;
+ }
+}
+
+void
+machinit(void)
+{
+ memset(m, 0, sizeof(*m));
+ m->delayloop = 20000;
+}
+
+void
+printversion(void)
+{
+ print("StrongARM SA-110 ");
+ print("%d MHz system\n", m->speed);
+ print("\n");
+{extern long baddr; print("%8.8lux\n", baddr);}
+}
+
+int
+optionsw()
+{
+ return 0;
+}
+
+int
+getcfields(char* lp, char** fields, int n, char* sep)
+{
+ int i;
+
+ for(i = 0; lp && *lp && i < n; i++){
+ while(*lp && strchr(sep, *lp) != 0)
+ *lp++ = 0;
+ if(*lp == 0)
+ break;
+ fields[i] = lp;
+ while(*lp && strchr(sep, *lp) == 0){
+ if(*lp == '\\' && *(lp+1) == '\n')
+ *lp++ = ' ';
+ lp++;
+ }
+ }
+
+ return i;
+}
+
+static Map memv[512];
+static RMap rammap = {"physical memory"};
+
+void
+meminit(void)
+{
+ ulong e;
+
+ mapinit(&rammap, memv, sizeof(memv));
+ e = PADDR(end);
+ mapfree(&rammap, e, 4*1024*1024-e);
+}
+
+void*
+ialloc(ulong n, int align)
+{
+ ulong a;
+ int s;
+
+ if(align <= 0)
+ align = 4;
+ s = splhi();
+ a = mapalloc(&rammap, 0, n, align);
+ splx(s);
+ if(a == 0)
+ panic("ialloc");
+ return memset(KADDR(a), 0, n);
+}
+
+void*
+malloc(ulong n)
+{
+ ulong *p;
+
+ n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
+ p = ialloc(n, sizeof(int));
+ *p++ = 0xcafebeef;
+ *p++ = n;
+ return p;
+}
+
+void
+free(ulong *p)
+{
+ int s;
+
+ if(p){
+ if(*(p -= 2) != 0xcafebeef)
+ panic("free");
+ s = splhi();
+ mapfree(&rammap, (ulong)p, p[1]);
+ splx(s);
+ }
+}
+
+void
+sched(void)
+{
+}
--- /dev/null
+++ b/os/boot.original/puma/mem.h
@@ -1,0 +1,38 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#define BY2PG 4096 /* bytes per page */
+#define WD2PG (BY2PG/BY2WD) /* words per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
+
+#define MAXMACH 1 /* max # cpus system can run */
+
+/*
+ * Time
+ */
+#define HZ (20) /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
+#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
+
+/*
+ * Fundamental addresses
+ */
+
+/*
+ * Address spaces
+ *
+ * Kernel is at 0x00008000
+ */
+#define KZERO 0x00000000 /* base of kernel address space */
+#define KTZERO KZERO /* first address in kernel text */
+#define MACHSIZE 4096
--- /dev/null
+++ b/os/boot.original/puma/mkfile
@@ -1,0 +1,71 @@
+<../../../mkconfig
+
+SYSTARG=Inferno
+OBJTYPE=arm
+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE #set vars based on target system
+
+TARGET=${O}boot
+OBJ=\
+ l.$O\
+ div.$O\
+ 8250.$O\
+ alarm.$O\
+ bootp.$O\
+ clock.$O\
+ console.$O\
+ conf.$O\
+ dosboot.$O\
+ donprint.$O\
+ ether.$O\
+ ether8900.$O\
+ flash.$O\
+ kbd.$O\
+ main.$O\
+ plan9boot.$O\
+ puma.$O\
+ qio.$O\
+ rmap.$O\
+ trap.$O\
+ zqs.$O
+
+HFILES=\
+ lib.h\
+ mem.h\
+ dat.h\
+ fns.h\
+ io.h\
+ boot.h\
+ armv4.h\
+ puma.h\
+
+CFLAGS=-w -I.
+LFLAGS=-H1 -R4 -T0x00200000 -E_main #-a
+#LFLAGS=-H1 -R4 -T0x00008080 -E_main #-a
+#LFLAGS = -H1 -R4 -T0xa00000c0 -E_main #-a
+
+all:V: $TARGET
+
+$TARGET: $OBJ
+ $LD -o $target $LFLAGS -l $prereq -lc
+ ls -l $target
+
+installall:V: install
+install:V: bb $TARGET
+ cp $TARGET /arm
+
+%.$O: %.s
+ $AS $stem.s
+
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+
+%.$O: $HFILES
+
+clock.$O floppy.$O trap.$O: ureg.h
+conf.$O dosboot.$O main.$O: dosfs.h
+ether.$O ether2000.$O ether509.$O ether8003.$O ether8390.$O: ether.h
+bootp.$O: ip.h
+
+clean:
+ rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARGET
+
--- /dev/null
+++ b/os/boot.original/puma/outb.c
@@ -1,0 +1,20 @@
+typedef unsigned short ushort;
+typedef unsigned char uchar;
+
+enum {
+ IsaIOBase = 0xf0000000,
+ IsaMemBase = 0xe0000000,
+
+ IOBase = 0x300,
+ MemBase = 0xc0000,
+
+ TxFrame = 0x0a00,
+};
+
+#define regw(reg, val) *((ushort *)IsaMemBase + MemBase + (reg)) = (val)
+
+void
+main(void)
+{
+ regw(TxFrame, 0x1234);
+}
--- /dev/null
+++ b/os/boot.original/puma/plan9boot.c
@@ -1,0 +1,93 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+char *premature = "premature EOF\n";
+
+/*
+ * read in a segment
+ */
+static long
+readseg(int dev, long (*read)(int, void*, long), long len, long addr)
+{
+ char *a;
+ long n, sofar;
+
+ a = (char *)addr;
+ for(sofar = 0; sofar < len; sofar += n){
+ n = 8*1024;
+ if(len - sofar < n)
+ n = len - sofar;
+ n = (*read)(dev, a + sofar, n);
+ if(n <= 0)
+ break;
+ print(".");
+ }
+ return sofar;
+}
+
+/*
+ * boot
+ */
+int
+plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
+{
+ long n;
+ long addr;
+ void (*b)(void);
+ Exec *ep;
+
+ if((*seek)(dev, 0) < 0)
+ return -1;
+
+ /*
+ * read header
+ */
+ ep = (Exec *) ialloc(sizeof(Exec), 0);
+ n = sizeof(Exec);
+ if(readseg(dev, read, n, (ulong) ep) != n){
+ print(premature);
+ return -1;
+ }
+ if(GLLONG(ep->magic) != E_MAGIC){
+ print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+ return -1;
+ }
+
+ /*
+ * read text
+ */
+ addr = PADDR(GLLONG(ep->entry));
+ n = GLLONG(ep->text);
+ print("%d", n);
+ if(readseg(dev, read, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * read data (starts at first page after kernel)
+ */
+ addr = PGROUND(addr+n);
+ n = GLLONG(ep->data);
+ print("+%d", n);
+ if(readseg(dev, read, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * bss and entry point
+ */
+ print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry)); uartwait();
+
+ /*
+ * Go to new code. It's up to the program to get its PC relocated to
+ * the right place.
+ */
+ b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+ (*b)();
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/puma/puma.c
@@ -1,0 +1,123 @@
+#include "boot.h"
+
+//#define GPIO1_PORT 0x0078
+//#define GPIO2_PORT 0x0079
+
+#define GPIO2_N_LED1_DIAG 0x10 /* diagnostic led mask */
+
+#define HARI2_N_LED1 0x01
+#define HARI2_N_LED2 0x02
+#define HARI2_N_LED3 0x04
+#define HARI2_N_LED4 0x08
+
+/*
+ * National Semiconductor PC87306 Super I/O
+ */
+enum {
+ Index= 0x398, /* sio configuration index register */
+ Data= 0x399, /* sio configuration data register */
+};
+
+
+// byte flip table for Puma SuperIO port permuted as 76543210 -> 01234567
+unsigned char
+byteflip[] = {
+ 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
+ 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
+ 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
+ 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
+ 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
+ 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
+ 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
+ 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
+ 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
+ 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
+ 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
+ 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
+ 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
+ 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
+ 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
+ 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
+};
+
+int
+sio_inb(int port)
+{
+ unsigned char b = *(uchar *)IOBADDR(port);
+// b = byteflip[b];
+ return b&0xff;
+}
+
+void
+sio_outb(int port, int data)
+{
+// data = byteflip[data];
+ *(uchar *)IOBADDR(port) = data;
+}
+
+static void
+siocfg(int r, int v, int rsv)
+{
+ sio_outb(Index, r);
+ if(rsv)
+ v = (sio_inb(Data)&rsv) | (v&~rsv);
+ sio_outb(Data, v);
+ sio_outb(Data, v); /* ``write data twice'' */
+}
+
+void
+sioinit(void)
+{
+ /* determine which byte flip is required ... */
+
+ siocfg(SIO_CONFIG_FAR, FAR_LPT_LPTA | FAR_UART1_COM1 | FAR_UART2_COM2, 0);
+ siocfg(SIO_CONFIG_FER, FER_LPT_ENABLE | FER_UART1_ENABLE | FER_UART2_ENABLE | FER_IDE_ENABLE, 0);
+ siocfg(SIO_CONFIG_KRR, KRR_KBC_ENABLE | KRR_KBC_MUST_BE_1 | KRR_RTC_ENABLE, 0x50);
+ siocfg(SIO_CONFIG_SCF0,SCF0_GPIO_PORT1_ENABLE | SCF0_GPIO_PORT2_ENABLE, 0xC0);
+
+ /* force UART interrupt pins low, not tristate by setting ienable in MCR (!) */
+ sio_outb(COM1_PORT+UART_MCR, sio_inb(COM1_PORT+UART_MCR)|(1<<3));
+ sio_outb(COM2_PORT+UART_MCR, sio_inb(COM2_PORT+UART_MCR)|(1<<3));
+}
+
+void
+led(int on)
+{
+ int gpio, hari, hbits;
+ int s;
+
+ s = splhi();
+
+ gpio = sio_inb(GPIO2_PORT);
+ if (on)
+ gpio &= ~GPIO2_N_LED1_DIAG;
+ else
+ gpio |= GPIO2_N_LED1_DIAG;
+ sio_outb(GPIO2_PORT, gpio);
+
+ hari = HARI2_INIT;
+ hbits = HARI2_N_LED1|HARI2_N_LED2|HARI2_N_LED3|HARI2_N_LED4;
+ if (on)
+ hari &= ~hbits;
+ else
+ hari |= hbits;
+ *(uchar *)HARI2 = hari;
+
+
+ splx(s);
+
+}
+
+void
+pumainit(void)
+{
+ /*
+ * Initialise HARI2 for:
+ * a) Leds off
+ * b) No Timer2 aborts
+ * c) Ethernet on IRQ
+ */
+ *(uchar *)HARI2 = HARI2_INIT|HARI2_N_LED1|HARI2_N_LED2|HARI2_N_LED3|HARI2_N_LED4;
+ sioinit();
+}
+
--- /dev/null
+++ b/os/boot.original/puma/puma.h
@@ -1,0 +1,435 @@
+/*
+ * Teralogic TL750 - Puma Evaluation Board
+ */
+
+/*
+ * Puma addresses
+ */
+#define EPROM_BASE 0x80000000 /* EPROM */
+#define FLASH_BASE 0xa0000000 /* Flash */
+#define TL750_BASE 0xc0000000 /* TL750 registers */
+#define ISAMEM_BASE 0xe0000000 /* ISA memory space */
+#define ISAIO_BASE 0xf0000000 /* ISA I/O space */
+
+#define ISAIO_SHIFT 2
+#define IOBADDR(io_port) (ISAIO_BASE + (io_port << ISAIO_SHIFT))
+
+/* Hardware address register for interrupts (HARI) */
+#define HARI1 0xE2000000 /* Interrupt status on read, User interrupt on write */
+#define HARI2 0xE3000000 /* More interrupt status on read, LEDs on write */
+#define HARI1_FIQ_MASK 0x92 /* FIQ indicator bits in HARI1, others are IRQ */
+#define HARI2_INIT 0x20 /* No timer2 aborts, Ethernet on IRQ */
+
+
+
+/*
+ * Interrupt Vectors
+ * corresponding to the HARIx_xxx_IRQ/FIQ bits above.
+ *
+ * HARI1 interrupts
+ */
+#define V_LPT 0 /* Parallel port interrupt */
+#define V_NM0 1 /* MPEG Decode Interrupt */
+#define V_NM1 2 /* MPEG Decode Interrupt */
+#define V_COM2 3 /* Serial Port 2 Interrupt */
+#define V_COM1 4 /* Serial Port 1 Interrupt */
+#define V_MOUSE 5 /* Mouse Interrupt */
+#define V_KEYBOARD 6 /* Keyboard Interrupt */
+#define V_ETHERNET 7 /* Ethernet Interrupt */
+/*
+ * HARI2 interrupts
+ */
+#define V_TIMER0 8 /* 82C54 Timer 0 Interrupt */
+#define V_TIMER1 9 /* 82C54 Timer 1 Interrupt */
+#define V_TIMER2 10 /* 82C54 Timer 2 Interrupt */
+#define V_SOFTWARE 11 /* Software Interrupt */
+#define V_IDE 12 /* IDE Hard Drive Interrupt */
+#define V_SMARTCARD 13 /* Smart Card Interrupt */
+#define V_TL750 14 /* TL750 Interrupt */
+ /* Nothing in vector 15 for now */
+#define V_MAXNUM 15
+
+/*
+ * Definitions for National Semiconductor PC87306 SuperIO configuration
+ */
+#define SIO_CONFIG_INDEX 0x398 /* SuperIO configuration index register */
+#define SIO_CONFIG_DATA 0x399 /* SuperIO configuration data register */
+
+#define SIO_CONFIG_RESET_VAL 0x88 /* Value read from first read of sio_config_index reg after reset */
+/*
+ * PC87306 Configuration Registers (The value listed is the configuration space
+ * index.)
+ */
+#define SIO_CONFIG_FER 0x00 /* Function Enable Register */
+
+#define FER_LPT_ENABLE 0x01 /* Enable Parallel Port */
+#define FER_UART1_ENABLE 0x02 /* Enable Serial Port 1 */
+#define FER_UART2_ENABLE 0x04 /* Enable Serial Port 2 */
+#define FER_FDC_ENABLE 0x08 /* Enable Floppy Controller */
+#define FER_FDC_4DRIVE_ENCODING 0x10 /* Select Floppy 4 Drive Encoding */
+#define FER_FDC_ADDR_ENABLE 0x20 /* Select Floppy Secondary Address */
+ /* 0: [0x3F0..0x3F7] */
+ /* 1: [0x370..0x377] */
+#define FER_IDE_ENABLE 0x40 /* Enable IDE Controller */
+#define FER_IDE_ADDR_SELECT 0x80 /* Select IDE Secondary Address */
+ /* 0: [0x1F0..0x1F7,0x3F6,0x3F7] */
+ /* 1: [0x170..0x177,0x376,0x377] */
+
+#define SIO_CONFIG_FAR 0x01 /* Function Address Register */
+
+#define FAR_LPT_ADDR_MASK 0x03 /* Select LPT Address */
+ /* If (PNP0[4] == 0) then: */
+ /* 0: LPTB [0x378..0x37F] IRQ5/7 */
+ /* 1: LPTA [0x3BC..0x3BE] IRQ7 */
+ /* 2: LPTC [0x278..0x27F] IRQ5 */
+ /* 3: Reserved */
+ /* Else ignored. */
+#define FAR_LPT_LPTB 0 /* 0: LPTB 0x378 irq5/7 */
+#define FAR_LPT_LPTA 1 /* 1: LPTA 0x3BC irq 7 */
+#define FAR_LPT_LPTC 2 /* 2: LPTC 0x278 irq5 */
+
+#define FAR_UART1_ADDR_MASK 0x0C /* Select Serial Port 1 Address */
+ /* 0: COM1 [0x3F8..0x3FF] */
+ /* 1: COM2 [0x2F8..0x2FF] */
+ /* 2: COM3 (See FAR[7:6]) */
+ /* 3: COM4 (See FAR[7:6]) */
+#define FAR_UART1_COM1 0x00
+#define FAR_UART2_ADDR_MASK 0x30 /* Select Serial Port 2 Address */
+ /* 0: COM1 [0x3F8..0x3FF] */
+ /* 1: COM2 [0x2F8..0x2FF] */
+ /* 2: COM3 (See FAR[7:6]) */
+ /* 3: COM4 (See FAR[7:6]) */
+#define FAR_UART2_COM2 0x10
+#define FAR_EXTENDED_UART_ADDR_SELECT 0xC0 /* Extended Address Selects */
+ /* COM3@IRQ4, COM4@IRQ3 */
+ /* 0: COM3@0x3E8, COM4@0x2E8 */
+ /* 1: COM3@0x338, COM4@0x238 */
+ /* 2: COM3@0x2E8, COM4@0x2E0 */
+ /* 3: COM3@0x220, COM4@0x228 */
+
+#define SIO_CONFIG_PTR 0x02 /* Power & Test Register */
+
+#define PTR_POWER_DOWN 0x01 /* Power down all enabled functions */
+#define PTR_LPT_IRQ_SELECT 0x08 /* Select LPT IRQ if (FAR[1:0] == 0) */
+ /* 0: IRQ5 */
+ /* 1: IRQ7 */
+#define PTR_UART1_TEST_MODE 0x10 /* Set serial port 1 test mode */
+#define PTR_UART2_TEST_MODE 0x20 /* Set serial port 2 test mode */
+#define PTR_LOCK_CONFIGURATION 0x40 /* Prevent all further config writes */
+ /* Only a RESET will reenable writes */
+#define PTR_LPT_EXTENDED_MODE_SELECT 0x80 /* Select Mode if not EPP/ECP */
+ /* 0: Compatible Mode */
+ /* 1: Extended Mode */
+
+#define SIO_CONFIG_FCR 0x03 /* Function Control Register */
+ /* WARNING: The FCR register must be written */
+ /* using read-modify-write! */
+#define FCR_TDR_MODE_SELECT 0x01 /* ? (floppy/tape) */
+#define FCR_IDE_DMA_ENABLE 0x02 /* Enable IDE DMA mode */
+#define FCR_EPP_ZERO_WAIT_STATE 0x40 /* Enable EPP zero wait state */
+
+#define SIO_CONFIG_PCR 0x04 /* Printer Control Register */
+
+#define PCR_EPP_ENABLE 0x01 /* Enable parallel port EPP mode */
+#define PCR_EPP_VERSION_SELECT 0x02 /* Select version of EPP mode */
+ /* 0: Version 1.7 */
+ /* 1: Version 1.9 (IEEE 1284) */
+#define PCR_ECP_ENABLE 0x04 /* Enable parallel port ECP mode */
+#define PCR_ECP_POWER_DOWN_CLOCK_ENABLE 0x08 /* Enable clock in power-down state */
+ /* 0: Freeze ECP clock */
+ /* 1: Run ECP clock */
+#define PCR_ECP_INT_POLARITY_CONTROL 0x20 /* Interrupt polarity control */
+ /* 0: Level high or negative pulse */
+ /* 1: Level low or positive pulse */
+#define PCR_ECP_INT_IO_CONTROL 0x40 /* Interrupt I/O control */
+ /* WARNING: Slightly safer to choose */
+ /* open drain if you don't know the */
+ /* exact requirements of the circuit */
+ /* 0: Totem-pole output */
+ /* 1: Open drain output */
+#define PCR_RTC_RAM_WRITE_DISABLE 0x80 /* Disable writes to RTC RAM */
+ /* 0: Enable writes */
+ /* 1: Disable writes */
+
+#define SIO_CONFIG_KRR 0x05 /* Keyboard & RTC Control Register */
+ /* WARNING: The KRR register must be written */
+ /* with a 1 in bit 2, else the KBC will not */
+ /* work! */
+#define KRR_KBC_ENABLE 0x01 /* Enable keyboard controller */
+#define KRR_KBC_SPEED_CONTROL 0x02 /* Select clock divisor if !KRR[7] */
+ /* 0: Divide by 3 */
+ /* 1: Divide by 2 */
+#define KRR_KBC_MUST_BE_1 0x04 /* Reserved: This bit must be 1! */
+#define KRR_RTC_ENABLE 0x08 /* Enable real time clock */
+#define KRR_RTC_RAMSEL 0x20 /* Select RTC RAM bank */
+#define KRR_KBC_CLOCK_SOURCE_SELECT 0x80 /* Select clock source */
+ /* 0: Use X1 clock source */
+ /* 1: Use SYSCLK clock source */
+
+#define SIO_CONFIG_PMC 0x06 /* Power Management Control Register */
+
+#define PMC_IDE_TRISTATE_CONTROL 0x01 /* ? (power management) */
+#define PMC_FDC_TRISTATE_CONTROL 0x02 /* ? (power management) */
+#define PMC_UART1_TRISTATE_CONTROL 0x04 /* ? (power management) */
+#define PMC_SELECTIVE_LOCK 0x20 /* ? (power management) */
+#define PMC_LPT_TRISTATE_CONTROL 0x40 /* ? (power management) */
+
+#define SIO_CONFIG_TUP 0x07 /* Tape, UARTS & Parallel Port Register */
+
+#define TUP_EPP_TIMEOUT_INT_ENABLE 0x04 /* Enable EPP timeout interrupts */
+
+#define SIO_CONFIG_SID 0x08 /* Super I/O Identification Register */
+
+#define SID_ID_MASK 0xF8 /* Super I/O ID field */
+#define SID_ID_PC87306 0x70 /* PC87306 ID value */
+
+#define SIO_CONFIG_ASC 0x09 /* Advanced Super I/O Config Register */
+ /* WARNING: The ASC register must be written */
+ /* with a 0 in bit 3! */
+ /* WARNING: The ASC register resets to 1 in */
+ /* bit 7 (PC/AT mode)! */
+#define ASC_VLD_MASK 0x03 /* ? (floppy/tape) */
+#define ASC_ENHANCED_TDR_SUPPORT 0x04 /* ? (floppy/tape) */
+#define ASC_MUST_BE_0 0x08 /* Reserved: Must be 0 */
+#define ASC_ECP_CNFGA 0x20 /* ? */
+#define ASC_DENSEL_POLARITY_BIT 0x40 /* ? (floppy/tape) */
+#define ASC_SYSTEM_OPERATION_MODE 0x80 /* Select system operation mode */
+ /* 0: PS/2 mode */
+ /* 1: PC/AT mode */
+
+#define SIO_CONFIG_CS0LA 0x0A /* Chip Select 0 Low Address Register */
+
+#define SIO_CONFIG_CS0CF 0x0B /* Chip Select 0 Configuration Register */
+ /* WARNING: The CS0CF register must be */
+ /* written with a 1 in bit 7! */
+#define CS0CF_CS0_DECODE 0x08 /* Select CS0 decode sensitivity */
+ /* 0: Decode full 16-bit address */
+ /* 1: Decode only bits 15 thru 12 */
+#define CS0CF_CS0_WRITE_ENABLE 0x10 /* Enable CS0 on write cycles */
+#define CS0CF_CS0_READ_ENABLE 0x20 /* Enable CS0 on read cycles */
+#define CS0CF_CS0_MUST_BE_1 0x80 /* Reserved: Must be 1 */
+
+#define SIO_CONFIG_CS1LA 0x0C /* Chip Select 1 Low Address Register */
+
+#define SIO_CONFIG_CS1CF 0x0D /* Chip Select 1 Configuration Register */
+
+#define CS1CF_CS1_DECODE 0x08 /* Select CS1 decode sensitivity */
+ /* 0: Decode full 16-bit address */
+ /* 1: Decode only bits 15 thru 12 */
+#define CS1CF_CS1_WRITE_ENABLE 0x10 /* Enable CS1 on write cycles */
+#define CS1CF_CS1_READ_ENABLE 0x20 /* Enable CS1 on read cycles */
+
+#define SIO_CONFIG_IRC 0x0E /* Infrared Configuration Register */
+
+#define IRC_UART2_INTERFACE_MODE 0x01 /* Select UART2 interface mode */
+ /* 0: Normal (modem) mode */
+ /* 1: IR mode */
+#define IRC_IR_FULL_DUPLEX 0x02 /* Select IR duplex mode */
+ /* 0: Full duplex mode */
+ /* 1: Half duplex mode */
+#define IRC_ENCODED_IR_TRANSMITTER_DRIVE 0x10 /* IR transmitter drive control */
+ /* 0: IRTX active for 1.6usec */
+ /* 1: IRTX active for 3/16 baud */
+#define IRC_ENCODED_IR_MODE 0x20 /* IR encode mode */
+ /* 0: Encoded mode */
+ /* 1: Non-encoded mode */
+
+#define SIO_CONFIG_GPBA 0x0F /* GP I/O Port Base Address Config Register */
+
+#define SIO_CONFIG_CS0HA 0x10 /* Chip Select 0 High Address Register */
+
+#define SIO_CONFIG_CS1HA 0x11 /* Chip Select 1 High Address Register */
+
+#define SIO_CONFIG_SCF0 0x12 /* Super I/O Configuration Register 0 */
+
+#define SCF0_RTC_RAM_LOCK 0x01 /* Lock (1) will prevent all further */
+ /* accesses to RTC RAM. Only RESET */
+ /* return this bit to a 0. */
+#define SCF0_IRQ1_12_LATCH_ENABLE 0x02 /* Enable IRQ1/IRQ12 latching */
+#define SCF0_IRQ12_TRISTATE 0x04 /* IRQ12 tri-state control */
+ /* 0: Use quasi-bidirectional buffer */
+ /* 1: Tri-state IRQ12 */
+#define SCF0_UART2_TRISTATE 0x08 /* Force UART2/IR outputs to */
+ /* tri-state when disabled */
+#define SCF0_GPIO_PORT1_ENABLE 0x10 /* Enable GPIO port 1 */
+#define SCF0_GPIO_PORT2_ENABLE 0x20 /* Enable GPIO port 2 */
+
+#define SIO_CONFIG_SCF1 0x18 /* Super I/O Configuration Register 1 */
+
+#define SCF1_REPORTED_ECP_DMA 0x06 /* Reported ECP DMA number */
+ /* 0: Jumpered 8-bit DMA */
+ /* 1: DMA channel 1 */
+ /* 2: DMA channel 2 */
+ /* 3: DMA channel 3 */
+#define SCF1_SELECTED_ECP_DMA 0x08 /* Selected ECP DMA pins */
+ /* 0: PDRQ0 & PDACK0 */
+ /* 1: PDRQ1 & PDACK1 */
+#define SCF1_SCRATCH_BITS 0xC0 /* ? */
+
+#define SIO_CONFIG_LPTBA 0x19 /* LPT Base Address */
+
+#define SIO_CONFIG_PNP0 0x1B /* Plug & Play Configuration Register 0 */
+
+#define PNP0_LPT_INT_SELECT_CONTROL 0x10 /* LPT IRQ select control */
+ /* 0: IRQ selected by FAR[1:0] */
+ /* 1: IRQ selected by PNP0[5] */
+#define PNP0_LPT_INT_MAPPING 0x20 /* LPT IRQ mapping */
+ /* 0: IRQ5 */
+ /* 1: IRQ7 */
+#define PNP0_LPTA_BASE_ADDR_SELECT 0x40 /* LPTA base address */
+ /* 0: Always 0x3BC */
+ /* 1: Selected by LPTBA[7:0] */
+
+#define SIO_CONFIG_PNP1 0x1C /* Plug & Play Configuration Register 1 */
+
+#define PNP1_UARTS_INT_SELECT_CONTROL 0x01 /* UART interrupt select control */
+ /* 0: Use FAR[3:2] & FAR[5:4] */
+ /* 1: Use PNP1[2] & PNP1[6] */
+#define PNP1_UART1_INT_MAPPING 0x04 /* UART1 interrupt mapping */
+ /* 0: IRQ3 */
+ /* 1: IRQ4 */
+#define PNP1_UART2_INT_MAPPING 0x40 /* UART2 interrupt mapping */
+ /* 0: IRQ3 */
+ /* 1: IRQ4 */
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Definitions for the SuperIO UART.
+ */
+#define COM1_PORT 0x3f8
+#define COM2_PORT 0x2f8
+
+/*
+ * Register offsets.
+ */
+#define UART_RX 0 /* Receive port, read only */
+#define UART_TX 0 /* transmit port, write only */
+#define UART_IER 1 /* Interrupt enable, read/write */
+#define UART_IIR 2 /* Interrupt id, read only */
+#define UART_FIFO_CONTROL 2 /* FIFO control, write only */
+#define UART_LCR 3 /* Line control register */
+#define UART_MCR 4 /* Modem control register */
+#define UART_LSR 5 /* Line Status register */
+#define UART_MSR 6 /* Modem Status register */
+
+/* with the DLAB bit set, the first two registers contain the baud rate */
+#define UART_DLLSB 0
+#define UART_DLMSB 1
+
+/*
+ * Line control register
+ */
+#define LCR_DB 3 /* Data bits in transmission (0 = 5, 1 = 6, 2 = 7, 3 = 8) */
+#define LCR_SB 4 /* Stop bit */
+#define LCR_PE 8 /* Parity enable */
+#define LCR_EP 16 /* Even parity */
+#define LCR_SP 32 /* Stick parity */
+#define LCR_BC 64 /* break control */
+#define LCR_DLAB 128 /* Divisor latch access bit */
+
+
+/*
+ * Modem Control register
+ */
+#define MCR_DTR 1 /* Data Terminal Ready */
+#define MCR_RTS 2 /* Request To Send */
+#define MCR_OUT1 4 /* Out1 (not used) */
+#define MCR_IRQ_ENABLE 8 /* Enable IRQ */
+#define MCR_LOOP 16 /* Loopback mode */
+
+/*
+ * Line status bits.
+ */
+#define LSR_DR 0x01 /* Data ready */
+#define LSR_OE 0x02 /* Overrun error */
+#define LSR_PE 0x04 /* Parity error */
+#define LSR_FE 0x08 /* Framing error */
+#define LSR_BI 0x10 /* Break interrupt */
+#define LSR_THRE 0x20 /* Transmitter holding register empty */
+#define LSR_TEMT 0x40 /* Transmitter empty */
+#define LSR_FFE 0x80 /* Receiver FIFO error */
+
+#define LSR_ERROR (LSR_OE | LSR_PE | LSR_FE)
+
+/*
+ * Interrupt Identification register (IIR)
+ */
+#define IIR_IP 1 /* No Interrupt pending */
+#define IIR_RECEIVE_LINE_STATUS 6 /* Overrun, Parity, Framing erros, Break */
+#define IIR_RDA 4 /* Receive data available */
+#define IIR_FIFO_FLAG 8 /* FIFO flag */
+#define IIR_FIFO_TIMEOUT (IIR_RDA+IIR_FIFO_FLAG) /* Got data some time ago, but FIFO time out */
+#define IIR_THRE 2 /* Transmitter holding register empty. */
+#define IIR_MS 0 /* CTS, DSR, RING, DCD changed */
+#define IIR_HPIP 6 /* Highest priority interrupt pending */
+
+/*
+ * Interrupt enable register (IER)
+ */
+#define IER_RDA 1 /* Received data available */
+#define IER_THRE 2 /* Transmitter holding register empty */
+#define IER_RLS 4 /* Receiver line status */
+#define IER_MS 8 /* Modem status */
+
+/*
+ * PC87306 Parallel I/O Port
+ */
+#define LPT1_PORT 0x03BC
+
+/*
+ * PC87306 General Purpose I/O Ports
+ */
+#define GPIO1_PORT 0x0078
+#define GPIO2_PORT 0x0079
+
+/*
+ * PC87306 IDE Port
+ */
+#define IDE_PORT_1 0x01F0
+#define IDE_PORT_2 0x03F6
+#define IDE_PORT_3 0x03F7
+
+/*
+ * PC87306 Floppy Port
+ */
+#define FDC_PORT 0x03F0
+
+/*
+ * PC87306 Real Time Clock/battery backed up RAM port
+ */
+#define RTC_INDEX_PORT 0x0070
+#define RTC_DATA_PORT 0x0071
+
+/*
+ * Offsets in RTC memory (RAMSEL = 0)
+ */
+#define RTC_SECONDS 0
+#define RTC_SECONDS_ALARM 1
+#define RTC_MINUTES 2
+#define RTC_MINUTES_ALARM 3
+#define RTC_HOURS 4
+#define RTC_HOURS_ALARM 5
+#define RTC_DAY_OF_WEEK 6
+#define RTC_DAY_OF_MONTH 7
+#define RTC_MONTH 8
+#define RTC_YEAR 9
+#define RTC_CONTROL_A 0xA
+#define RTC_CONTROL_B 0xB
+#define RTC_CONTROL_C 0xC
+#define RTC_CONTROL_D 0xD
+
+#define RTC_NVRAM0_START 0xE
+#define RTC_NVRAM0_SIZE 114
+#define RTC_NVRAM1_START 0
+#define RTC_NVRAM1_SIZE 128
+#define RTC_NVRAM_SIZE (RTC_NVRAM0_SIZE+RTC_NVRAM1_SIZE)
+
+#define RTC_PWNVRAM_START 0x38 /* Start of protected NVRAM */
+#define RTC_PWNVRAM_SIZE 8 /* Size of protected NVRAM */
+
+
+/*
+ * PC87306 Keyboard controller ports
+ */
+#define KEYBD_DATA_PORT 0x0060
+#define KEYBD_CTRL_PORT 0x0064
--- /dev/null
+++ b/os/boot.original/puma/qio.c
@@ -1,0 +1,128 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+struct Queue {
+ Block* first;
+ Block* last;
+ void (*kick)(void*);
+ void* arg;
+ long len;
+};
+
+Block *
+iallocb(int n)
+{
+ Block *b;
+
+ b = (Block*)malloc(sizeof(Block)+n);
+ b->data = (uchar*)b + sizeof(Block);
+ b->rp = b->wp = b->data;
+ b->lim = b->data + n;
+ b->next = 0;
+ b->magic = 0xcafebee0;
+ return b;
+}
+
+void
+freeb(Block *b)
+{
+ if(b){
+ if(b->magic != 0xcafebee0)
+ panic("freeb");
+ b->magic = 0;
+ b->next = (Block*)0xdeadbabe;
+ free(b);
+ }
+}
+
+Queue *
+qopen(int limit, int msg, void (*kick)(void*), void *arg)
+{
+ Queue *q;
+
+ USED(limit, msg);
+ q = (Queue*)malloc(sizeof(Queue));
+ q->first = q->last = 0;
+ q->kick = kick;
+ q->arg = arg;
+ q->len = 0;
+ return q;
+}
+
+Block *
+qget(Queue *q)
+{
+ int s;
+ Block *b;
+
+ s = splhi();
+ if((b = q->first) != 0){
+ q->first = b->next;
+ b->next = 0;
+ q->len -= BLEN(b);
+ if(q->len < 0)
+ panic("qget");
+ }
+ splx(s);
+ return b;
+}
+
+void
+qbwrite(Queue *q, Block *b)
+{
+ int s;
+
+ s = splhi();
+ b->next = 0;
+ if(q->first == 0)
+ q->first = b;
+ else
+ q->last->next = b;
+ q->last = b;
+ q->len += BLEN(b);
+ splx(s);
+ if(q->kick)
+ q->kick(q->arg);
+}
+
+long
+qlen(Queue *q)
+{
+ return q->len;
+}
+
+int
+qbgetc(Queue *q)
+{
+ Block *b;
+ int s, c;
+
+ c = -1;
+ s = splhi();
+ while(c < 0 && (b = q->first) != nil){
+ if(b->rp < b->wp){
+ c = *b->rp++;
+ q->len--;
+ }
+ if(b->rp >= b->wp){
+ q->first = b->next;
+ b->next = nil;
+ }
+ }
+ splx(s);
+ return c;
+}
+
+void
+qbputc(Queue *q, int c)
+{
+ Block *b;
+
+ b = iallocb(1);
+ *b->wp++ = c;
+ qbwrite(q, b);
+}
--- /dev/null
+++ b/os/boot.original/puma/rmap.c
@@ -1,0 +1,104 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+void
+mapinit(RMap *rmap, Map *map, int size)
+{
+ lock(rmap);
+ rmap->map = map;
+ rmap->mapend = map+(size/sizeof(Map));
+ unlock(rmap);
+}
+
+void
+mapfree(RMap* rmap, ulong addr, int size)
+{
+ Map *mp;
+ ulong t;
+
+ if(size <= 0)
+ return;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
+ ;
+
+ if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
+ (mp-1)->size += size;
+ if(addr+size == mp->addr){
+ (mp-1)->size += mp->size;
+ while(mp->size){
+ mp++;
+ (mp-1)->addr = mp->addr;
+ (mp-1)->size = mp->size;
+ }
+ }
+ }
+ else{
+ if(addr+size == mp->addr && mp->size){
+ mp->addr -= size;
+ mp->size += size;
+ }
+ else do{
+ if(mp >= rmap->mapend){
+ print("mapfree: %s: losing 0x%uX, %d\n",
+ rmap->name, addr, size);
+ break;
+ }
+ t = mp->addr;
+ mp->addr = addr;
+ addr = t;
+ t = mp->size;
+ mp->size = size;
+ mp++;
+ }while(size = t);
+ }
+ unlock(rmap);
+}
+
+ulong
+mapalloc(RMap* rmap, ulong addr, int size, int align)
+{
+ Map *mp;
+ ulong maddr, oaddr;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->size; mp++){
+ maddr = mp->addr;
+
+ if(addr){
+ if(maddr > addr)
+ continue;
+ if(addr+size > maddr+mp->size)
+ break;
+ maddr = addr;
+ }
+
+ if(align > 0)
+ maddr = ((maddr+align-1)/align)*align;
+ if(mp->addr+mp->size-maddr < size)
+ continue;
+
+ oaddr = mp->addr;
+ mp->addr = maddr+size;
+ mp->size -= maddr-oaddr+size;
+ if(mp->size == 0){
+ do{
+ mp++;
+ (mp-1)->addr = mp->addr;
+ }while((mp-1)->size = mp->size);
+ }
+
+ unlock(rmap);
+ if(oaddr != maddr)
+ mapfree(rmap, oaddr, maddr-oaddr);
+
+ return maddr;
+ }
+ unlock(rmap);
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/puma/squeeze.h
@@ -1,0 +1,34 @@
+
+/*
+ * squeezed file format:
+ * Sqhdr
+ * original Exec header
+ * two Squeeze tables
+ * squeezed segment
+ * unsqueezed segment, if any
+ */
+#define SQMAGIC (ulong)0xFEEF0F1E
+
+typedef struct Sqhdr Sqhdr;
+struct Sqhdr {
+ uchar magic[4]; /* SQMAGIC */
+ uchar text[4]; /* squeezed length of text (excluding tables) */
+ uchar data[4]; /* squeezed length of data (excluding tables) */
+ uchar asis[4]; /* length of unsqueezed segment */
+ uchar toptxt[4]; /* value for 0 encoding in text */
+ uchar topdat[4]; /* value for 0 encoding in data */
+ uchar sum[4]; /* simple checksum of unsqueezed data */
+ uchar flags[4];
+};
+#define SQHDRLEN (8*4)
+
+/*
+ * certain power instruction types are rearranged by sqz
+ * so as to move the variable part of the instruction word to the
+ * low order bits. note that the mapping is its own inverse.
+ */
+#define QREMAP(X)\
+ switch((X)>>26){\
+ case 19: case 31: case 59: case 63:\
+ (X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
+ }
--- /dev/null
+++ b/os/boot.original/puma/sum.c
@@ -1,0 +1,13 @@
+int
+sum(int a, int b, int c)
+{
+ return a+b+c;
+}
+
+void
+main(void)
+{
+ int s;
+
+ s = sum(1, 2, 3);
+}
--- /dev/null
+++ b/os/boot.original/puma/trap.c
@@ -1,0 +1,190 @@
+#include "boot.h"
+
+typedef struct IrqEntry {
+ void (*r)(Ureg*, void*);
+ void *a;
+} IrqEntry;
+
+IrqEntry Irq[V_MAXNUM+1];
+
+static void dumpstk(ulong *);
+void dumpregs(Ureg* ureg);
+
+void
+setvec(int v, void (*f)(Ureg*, void*), void* a)
+{
+ if(v < 0 || v >= V_MAXNUM)
+ panic("setvec: interrupt source %d out of range\n", v);
+ Irq[v].r = f;
+ Irq[v].a = a;
+}
+
+ulong irqstack[64];
+ulong fiqstack[64];
+ulong abtstack[64];
+ulong undstack[64];
+
+static void
+safeintr(Ureg*, void *a)
+{
+ int v = (int)a;
+// print("spurious interrupt %d\n", v);
+ USED(v);
+}
+
+void
+trapinit(void)
+{
+ int offset;
+ ulong op;
+ int v;
+ int s;
+
+ s = splhi();
+
+ /* set up stacks for various exceptions */
+ setr13(PsrMirq, irqstack+nelem(irqstack)-1);
+ setr13(PsrMfiq, fiqstack+nelem(fiqstack)-1);
+ setr13(PsrMabt, abtstack+nelem(abtstack)-1);
+ setr13(PsrMund, undstack+nelem(undstack)-1);
+
+ for(v = 0; v <= V_MAXNUM; v++) {
+ Irq[v].r = safeintr;
+ Irq[v].a = (void *)v;
+ }
+
+ /* Reset Exception */
+ offset = ((((ulong) _vsvccall) - 0x0)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0x0) = op;
+
+ /* Undefined Instruction Exception */
+ offset = ((((ulong) _vundcall) - 0x4)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0x4) = op;
+
+ /* SWI Exception */
+ offset = ((((ulong) _vsvccall) - 0x8)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0x8) = op;
+
+ /* Prefetch Abort Exception */
+ offset = ((((ulong) _vpabcall) - 0xc)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0xc) = op;
+
+ /* Data Abort Exception */
+ offset = ((((ulong) _vdabcall) - 0x10)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0x10) = op;
+
+ /* IRQ Exception */
+ offset = ((((ulong) _virqcall) - 0x18)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0x18) = op;
+
+ /* FIQ Exception */
+ offset = ((((ulong) _vfiqcall) - 0x1c)-8) >> 2;
+ op = ( 0xea << 24 ) | offset;
+ *((ulong *) 0x1c) = op;
+
+
+ flushIcache();
+ writeBackDC();
+ flushDcache();
+ flushIcache();
+ drainWBuffer();
+
+ splx(s);
+}
+
+/*
+ * trap is called splhi().
+ */
+
+void
+trap(Ureg* ureg)
+{
+ ushort mask;
+ IrqEntry *ip;
+
+ /*
+ * All interrupts/exceptions should be resumed at ureg->pc-4,
+ * except for Data Abort which resumes at ureg->pc-8.
+ */
+ ureg->pc -= 4;
+
+ switch(ureg->type) {
+ case PsrMirq: /* Interrupt Request */
+ mask = *(uchar*)HARI1 | ((*(uchar*)HARI2) << 8);
+ ip = Irq;
+ while (mask != 0) {
+ if(mask&1)
+ ip->r(ureg, ip->a);
+ ip++;
+ mask >>= 1;
+ }
+ break;
+
+ case PsrMfiq: /* FIQ */
+ mask = *(uchar*)HARI1 & HARI1_FIQ_MASK;
+ ip = Irq;
+ while (mask != 0) {
+ if(mask&1)
+ ip->r(ureg, ip->a);
+ ip++;
+ mask >>= 1;
+ }
+ break;
+
+ case PsrMund: /* Undefined instruction */
+ dumpregs(ureg);
+ panic("Undefined Instruction Exception\n");
+ break;
+
+ case PsrMsvc: /* Jump through 0 or SWI */
+ dumpregs(ureg);
+ panic("SVC/SWI Exception\n");
+ break;
+
+ case PsrMabt: /* Prefetch abort */
+ ureg->pc -= 4;
+ /* FALLTHROUGH */
+
+ case PsrMabt+1: { /* Data abort */
+ uint far =0;
+ uint fsr =0;
+
+ USED(far,fsr);
+ fsr = 0; /*mmuregr(CpFSR);*/
+ far = 0; /*mmuregr(CpFAR); */
+ if (ureg->type == PsrMabt)
+ print("Prefetch Abort/");
+ print("Data Abort\n");
+
+ print("Data Abort: FSR %8.8uX FAR %8.8uX\n", fsr, far);
+ /* FALLTHROUGH */
+ }
+ default:
+ dumpregs(ureg);
+ panic("exception %uX\n", ureg->type);
+ break;
+ }
+
+ splhi();
+}
+
+void
+dumpregs(Ureg* ureg)
+{
+ print("PSR %8.8uX type %2.2uX PC %8.8uX LINK %8.8uX\n",
+ ureg->psr, ureg->type, ureg->pc, ureg->link);
+ print("R14 %8.8uX R13 %8.8uX R12 %8.8uX R11 %8.8uX R10 %8.8uX\n",
+ ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
+ print("R9 %8.8uX R8 %8.8uX R7 %8.8uX R6 %8.8uX R5 %8.8uX\n",
+ ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
+ print("R4 %8.8uX R3 %8.8uX R2 %8.8uX R1 %8.8uX R0 %8.8uX\n",
+ ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
+ print("Stack is at: %8.8uX\n", ureg);
+/* print("CPSR %8.8uX SPSR %8.8uX\n", cpsrr(), spsrr());*/
+}
--- /dev/null
+++ b/os/boot.original/puma/ureg.h
@@ -1,0 +1,22 @@
+typedef struct Ureg {
+ uint r0;
+ uint r1;
+ uint r2;
+ uint r3;
+ uint r4;
+ uint r5;
+ uint r6;
+ uint r7;
+ uint r8;
+ uint r9;
+ uint r10;
+ uint r11;
+ uint r12;
+ uint r13;
+ uint r14;
+ uint link;
+ uint type;
+ uint psr;
+// uint sp;
+ uint pc;
+} Ureg;
--- /dev/null
+++ b/os/boot.original/puma/zqs.c
@@ -1,0 +1,216 @@
+#include "boot.h"
+#include "squeeze.h"
+
+#define EXECHDRLEN (8*4)
+
+typedef struct Squeeze Squeeze;
+struct Squeeze {
+ int n;
+ ulong tab[7*256];
+};
+
+#define GET4(p) (((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
+
+/*
+ * for speed of unsqueezing from Flash, certain checks are
+ * not done inside the loop (as they would be in the unsqueeze program zqs),
+ * but instead the checksum is expected to catch corrupted files.
+ * in fact the Squeeze array bounds can't be exceeded in practice
+ * because the tables are always full for a squeezed kernel.
+ */
+enum {
+ QFLAG = 1, /* invert powerpc-specific code transformation */
+ CHECK = 0, /* check precise bounds in Squeeze array (otherwise checksum detects error) */
+};
+
+static ulong chksum;
+static int rdtab(Block*, Squeeze*, int);
+static ulong* unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
+static uchar* unsqzseg(uchar*, Block*, long, long, char*);
+static Alarm* unsqzal;
+
+int
+issqueezed(uchar *b)
+{
+ return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
+}
+
+static void
+unsqzdot(void*)
+{
+ unsqzal = alarm(500, unsqzdot, nil);
+ print(".");
+}
+
+long
+unsqueezef(Block *b, ulong *entryp)
+{
+ uchar *loada, *wp;
+ ulong toptxt, topdat, oldsum;
+ long asis, nst, nsd;
+ Sqhdr *sqh;
+ Exec *ex;
+
+ if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
+ return -1;
+ sqh = (Sqhdr*)b->rp;
+ if(GET4(sqh->magic) != SQMAGIC)
+ return -1;
+ chksum = 0;
+ toptxt = GET4(sqh->toptxt);
+ topdat = GET4(sqh->topdat);
+ oldsum = GET4(sqh->sum);
+ asis = GET4(sqh->asis);
+ nst = GET4(sqh->text);
+ nsd = GET4(sqh->data);
+ b->rp += SQHDRLEN;
+ ex = (Exec*)b->rp;
+ if(GET4(ex->magic) != E_MAGIC){
+ print("zqs: not StrongARM executable\n");
+ return -1;
+ }
+ *entryp = GET4(ex->entry);
+ b->rp += EXECHDRLEN;
+ loada = KADDR(PADDR(*entryp));
+ wp = unsqzseg(loada, b, nst, toptxt, "text");
+ if(wp == nil){
+ print("zqs: format error\n");
+ return -1;
+ }
+ if(nsd){
+ wp = (uchar*)PGROUND((ulong)wp);
+ wp = unsqzseg(wp, b, nsd, topdat, "data");
+ if(wp == nil){
+ print("zqs: format error\n");
+ return -1;
+ }
+ }
+ if(asis){
+ memmove(wp, b->rp, asis);
+ wp += asis;
+ b->rp += asis;
+ }
+ if(chksum != oldsum){
+ print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
+ return -1;
+ }
+ return wp-loada;
+}
+
+static uchar *
+unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
+{
+ static Squeeze sq3, sq4;
+
+ print("unpack %s %8.8lux %lud:", what, wp, ns);
+ if(ns == 0)
+ return wp;
+ if(rdtab(b, &sq3, 0) < 0)
+ return nil;
+ if(rdtab(b, &sq4, 8) < 0)
+ return nil;
+ if(BLEN(b) < ns){
+ print(" **size error\n");
+ return nil;
+ }
+ unsqzal = alarm(500, unsqzdot, nil);
+ wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
+ cancel(unsqzal);
+ unsqzal = nil;
+ print("\n");
+ if(wp == nil){
+ print("zqs: corrupt squeezed data stream\n");
+ return nil;
+ }
+ b->rp += ns;
+ return wp;
+}
+
+static ulong*
+unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
+{
+ ulong nx, csum;
+ int code, n;
+
+ if(QFLAG){
+ QREMAP(top); /* adjust top just once, outside the loop */
+ }
+ csum = chksum;
+ while(rp < ep){
+ /* no function calls within this loop for speed */
+ code = *rp;
+ rp++;
+ n = 0;
+ nx = code>>4;
+ do{
+ if(nx == 0){
+ nx = top;
+ }else{
+ if(nx==1){
+ nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
+ rp += 4;
+ }else if(nx <= 8){ /* 2 to 8 */
+ nx = ((nx-2)<<8) | rp[0];
+ if(CHECK && nx >= sq4->n)
+ return nil; /* corrupted file */
+ nx = sq4->tab[nx] | rp[1];
+ rp += 2;
+ }else{ /* 9 to 15 */
+ nx = ((nx-9)<<8) | rp[0];
+ if(CHECK && nx >= sq3->n)
+ return nil; /* corrupted file */
+ nx = sq3->tab[nx];
+ rp++;
+ }
+ if(rp > ep)
+ return nil; /* corrupted file */
+ if(QFLAG){
+ QREMAP(nx);
+ }
+ }
+ *wp = nx;
+ wp++;
+ csum += nx;
+ nx = code & 0xF;
+ }while(++n == 1);
+ }
+ chksum = csum;
+ return wp;
+}
+
+static int
+rdtab(Block *b, Squeeze *sq, int shift)
+{
+ uchar *p, *ep;
+ ulong v, w;
+ int i;
+
+ if(BLEN(b) < 2)
+ return -1;
+ i = (b->rp[0]<<8) | b->rp[1];
+ if(1)
+ print(" T%d", i);
+ b->rp += 2;
+ if((i -= 2) > 0){
+ if(BLEN(b) < i)
+ return -1;
+ }
+ sq->n = 0;
+ p = b->rp;
+ ep = b->rp+i;
+ b->rp += i;
+ v = 0;
+ while(p < ep){
+ w = 0;
+ do{
+ if(p >= ep)
+ return -1;
+ w = (w<<7) | (*p & 0x7F);
+ }while(*p++ & 0x80);
+ v += w;
+ if(0)
+ print("%d %8.8lux %8.8lux\n", sq->n, v, w);
+ sq->tab[sq->n++] = v<<shift;
+ }
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/NOTICE
@@ -1,0 +1,3 @@
+Inferno® Copyright © 1996-1999 Lucent Technologies Inc. All rights reserved.
+PowerPC support Copyright © 1995-1997 C H Forsyth (forsyth@caldo.demon.co.uk). All rights reserved.
+MPC8xx Inferno PowerPC port Copyright © 1998-2003 Vita Nuova Holdings Limited. All rights reserved.
--- /dev/null
+++ b/os/boot.original/rpcg/alarm.c
@@ -1,0 +1,123 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#define MAXALARM 10
+
+Alarm alarmtab[MAXALARM];
+
+/*
+ * Insert new into list after where
+ */
+void
+insert(List **head, List *where, List *new)
+{
+ if(where == 0){
+ new->next = *head;
+ *head = new;
+ }else{
+ new->next = where->next;
+ where->next = new;
+ }
+
+}
+
+/*
+ * Delete old from list. where->next is known to be old.
+ */
+void
+delete(List **head, List *where, List *old)
+{
+ if(where == 0){
+ *head = old->next;
+ return;
+ }
+ where->next = old->next;
+}
+
+Alarm*
+newalarm(void)
+{
+ int i;
+ Alarm *a;
+
+ for(i=0,a=alarmtab; i < nelem(alarmtab); i++,a++)
+ if(a->busy==0 && a->f==0){
+ a->f = 0;
+ a->arg = 0;
+ a->busy = 1;
+ return a;
+ }
+ panic("newalarm");
+ return 0; /* not reached */
+}
+
+Alarm*
+alarm(int ms, void (*f)(Alarm*), void *arg)
+{
+ Alarm *a, *w, *pw;
+ ulong s;
+
+ if(ms < 0)
+ ms = 0;
+ s = splhi();
+ a = newalarm();
+ a->dt = MS2TK(ms);
+ a->f = f;
+ a->arg = arg;
+ pw = 0;
+ for(w=m->alarm; w; pw=w, w=w->next){
+ if(w->dt <= a->dt){
+ a->dt -= w->dt;
+ continue;
+ }
+ w->dt -= a->dt;
+ break;
+ }
+ insert(&m->alarm, pw, a);
+ splx(s);
+ return a;
+}
+
+void
+cancel(Alarm *a)
+{
+ a->f = 0;
+}
+
+void
+alarminit(void)
+{
+}
+
+#define NA 10 /* alarms per clock tick */
+void
+checkalarms(void)
+{
+ int i, n, s;
+ Alarm *a;
+ void (*f)(Alarm*);
+ Alarm *alist[NA];
+
+ s = splhi();
+ a = m->alarm;
+ if(a){
+ for(n=0; a && a->dt<=0 && n<NA; n++){
+ alist[n] = a;
+ delete(&m->alarm, 0, a);
+ a = m->alarm;
+ }
+ if(a)
+ a->dt--;
+
+ for(i = 0; i < n; i++){
+ f = alist[i]->f; /* avoid race with cancel */
+ if(f)
+ (*f)(alist[i]);
+ alist[i]->busy = 0;
+ }
+ }
+ splx(s);
+}
--- /dev/null
+++ b/os/boot.original/rpcg/all.h
@@ -1,0 +1,6 @@
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "mem.h"
+#include "io.h"
--- /dev/null
+++ b/os/boot.original/rpcg/archrpcg.c
@@ -1,0 +1,279 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "archrpcg.h"
+#include "etherif.h"
+
+/*
+ * board-specific support for the RPCG RXLite
+ */
+
+enum {
+ SYSMHZ = 66, /* target frequency */
+
+ /* sccr */
+ RTSEL = IBIT(8), /* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
+ RTDIV = IBIT(7), /* =0, divide by 4; =1, divide by 512 */
+ CRQEN = IBIT(9), /* =1, switch to high frequency when CPM active */
+ PRQEN = IBIT(10), /* =1, switch to high frequency when interrupt pending */
+
+ /* plprcr */
+ CSRC = IBIT(21), /* =0, clock is DFNH; =1, clock is DFNL */
+};
+
+static char flashsig[] = "RPXsignature=1.0\nNAME=qbrpcg\nSTART=FFC20100\nVERSION=1.1\n";
+static char* geteeprom(char*);
+
+/*
+ * called early in main.c, after machinit:
+ * using board and architecture specific registers, initialise
+ * 8xx registers that need it and complete initialisation of the Mach structure.
+ */
+void
+archinit(void)
+{
+ IMM *io;
+ int mf, t;
+ ulong v;
+
+ v = getimmr() & 0xFFFF;
+ switch(v>>8){
+ case 0x00: t = 0x86000; break;
+ case 0x20: t = 0x82300; break;
+ case 0x21: t = 0x823a0; break;
+ default: t = 0; break;
+ }
+ m->cputype = t;
+ m->bcsr = KADDR(BCSRMEM);
+ io = m->iomem;
+ m->clockgen = 8*MHz;
+ mf = (io->plprcr >> 20)+1; /* use timing set by bootstrap */
+ m->cpuhz = m->clockgen*mf;
+ m->bcsr[0] = DisableColTest | DisableFullDplx | DisableUSB | HighSpdUSB | LedOff; /* first write enables bcsr regs */
+return;
+ io->plprcrk = KEEP_ALIVE_KEY;
+ io->plprcr &= ~CSRC; /* general system clock is DFNH */
+/* io->mptpr = 0x0800; /* memory prescaler = 8 for refresh */
+ /* use memory refresh time set by RPXLite monitor */
+ io->plprcrk = ~KEEP_ALIVE_KEY;
+}
+
+void
+cpuidprint(void)
+{
+ int t, v;
+
+ print("Inferno bootstrap\n");
+ print("PVR: ");
+ t = getpvr()>>16;
+ switch(t){
+ case 0x01: print("MPC601"); break;
+ case 0x03: print("MPC603"); break;
+ case 0x04: print("MPC604"); break;
+ case 0x06: print("MPC603e"); break;
+ case 0x07: print("MPC603e-v7"); break;
+ case 0x50: print("MPC8xx"); break;
+ default: print("PowerPC version #%x", t); break;
+ }
+ print(", revision #%lux\n", getpvr()&0xffff);
+ print("IMMR: ");
+ v = getimmr() & 0xFFFF;
+ switch(v>>8){
+ case 0x00: print("MPC860/821"); break;
+ case 0x20: print("MPC823"); break;
+ case 0x21: print("MPC823A"); break;
+ default: print("Type #%lux", v>>8); break;
+ }
+ print(", mask #%lux\n", v&0xFF);
+ print("options: #%lux\n", archoptionsw());
+ print("bcsr: %8.8lux\n", m->bcsr[0]);
+ print("PLPRCR=%8.8lux SCCR=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
+ print("%lud MHz system\n", m->cpuhz/MHz);
+ print("\n");
+//print("%s\n", geteeprom("EA"));
+print("BR0=%8.8lux OR0=%8.8lux\n", m->iomem->memc[0].base, m->iomem->memc[0].option);
+print("MPTPR=%8.8lux\n", m->iomem->mptpr);
+}
+
+static char* defplan9ini[2] = {
+ /* 860/821 */
+ "ether0=type=SCC port=1 ea=0010ec000051\r\n"
+ "vgasize=640x480x8\r\n"
+ "kernelpercent=40\r\n"
+ "console=0\r\nbaud=9600\r\n",
+
+ /* 823 */
+ "ether0=type=SCC port=2 ea=0010ec000051\r\n"
+ "vgasize=640x480x8\r\n"
+ "kernelpercent=40\r\n"
+ "console=0\r\nbaud=9600\r\n",
+};
+
+char *
+archconfig(void)
+{
+ print("Using default configuration\n");
+ return defplan9ini[MPCMODEL(m->cputype) == 0x823];
+}
+
+/*
+ * provide value for #r/switch (devrtc.c)
+ */
+int
+archoptionsw(void)
+{
+ return (m->bcsr[0]&DipSwitchMask)>>4;
+}
+
+/*
+ * invoked by clock.c:/^clockintr
+ */
+static void
+twinkle(void)
+{
+ if(m->ticks%MS2TK(1000) == 0)
+ m->bcsr[0] ^= LedOff;
+}
+
+void (*archclocktick)(void) = twinkle;
+
+/*
+ * for flash.c:/^flashreset
+ * retrieve flash type, virtual base and length and return 0;
+ * return -1 on error (no flash)
+ */
+int
+archflashreset(char *type, void **addr, long *length)
+{
+ if((m->iomem->memc[BOOTCS].base & 1) == 0)
+ return -1; /* shouldn't happen */
+ strcpy(type, "AMD29F0x0");
+ *addr = KADDR(FLASHMEM);
+ *length = 4*1024*1024;
+ return 0;
+}
+
+int
+archether(int ctlrno, Card *ether)
+{
+ char *ea;
+
+ if(ctlrno > 0)
+ return -1;
+ strcpy(ether->type, "SCC");
+ ether->port = 2;
+ ea = geteeprom("EA");
+ if(ea != nil)
+ parseether(ether->ea, ea);
+ return 1;
+}
+
+/*
+ * enable the clocks for the given SCC ether and reveal them to the caller.
+ * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
+ */
+int
+archetherenable(int cpmid, int *rcs, int *tcs)
+{
+ IMM *io;
+
+ switch(cpmid){
+ default:
+ /* no other SCCs are wired for ether on RPXLite*/
+ return -1;
+
+ case SCC2ID:
+ io = ioplock();
+ m->bcsr[0] |= EnableEnet;
+ io->papar |= SIBIT(6)|SIBIT(4); /* enable CLK2 and CLK4 */
+ io->padir &= ~(SIBIT(6)|SIBIT(4));
+ *rcs = CLK4;
+ *tcs = CLK2;
+ iopunlock();
+ break;
+ }
+ return 0;
+}
+
+void
+archetherdisable(int id)
+{
+ USED(id);
+ m->bcsr[0] &= ~EnableEnet;
+}
+
+/*
+ * do anything extra required to enable the UART on the given CPM port
+ */
+void
+archenableuart(int id, int irda)
+{
+ USED(id, irda);
+}
+
+/*
+ * do anything extra required to disable the UART on the given CPM port
+ */
+void
+archdisableuart(int id)
+{
+ USED(id);
+}
+
+/*
+ * enable/disable the LCD panel's backlight
+ */
+void
+archbacklight(int on)
+{
+ USED(on);
+}
+
+static char*
+geteeprom(char *s)
+{
+ static int init;
+ static char res[64];
+ static uchar eeprom[257];
+ uchar *l, *p;
+ int i, j;
+
+ if(!init){
+ i2csetup();
+ if(i2crecv(0xa8|1|(0<<8), eeprom, 128) < 0 ||
+ i2crecv(0xa8|1|(128<<8), eeprom+128, 128) < 0){
+ print("i2c failed\n");
+ return nil;
+ }
+ if(0){
+ print("eeprom:\n");
+ for(i=0; i<16; i++){for(j=0; j<16; j++)print(" %2.2ux[%c]", eeprom[i*16+j], eeprom[i*16+j]); print("\n");}
+ }
+ eeprom[256] = 0xFF;
+ init = 1;
+ }
+ for(l = eeprom; *l != 0xFF && *l != '\n';){
+ p = l;
+ while(*l != '\n' && *l != 0xFF && *l != '=')
+ l++;
+ if(*l == '='){
+ if(l-p == strlen(s) && strncmp(s, (char*)p, strlen(s)) == 0){
+ p = l+1;
+ while(*l != '\n' && *l != 0xFF)
+ l++;
+ memmove(res, p, l-p);
+ res[l-p] = 0;
+ return res;
+ }
+ }
+ while(*l != '\n' && *l != 0xFF)
+ l++;
+ if(*l == '\n')
+ l++;
+ }
+ return nil;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/archrpcg.h
@@ -1,0 +1,48 @@
+/*
+ * values for RPXLite AW
+ */
+enum {
+ /* CS assignment */
+ BOOTCS = 0,
+ DRAM1 = 1,
+ /* CS2 is routed to expansion header */
+ BCSRCS = 3,
+ NVRAMCS = 4,
+ /* CS5 is routed to expansion header */
+ PCMCIA0CS = 6, /* select even bytes */
+ PCMCIA1CS = 7, /* select odd bytes */
+};
+
+/*
+ * BCSR bits (there are 4 8-bit registers that we access as ulong)
+ */
+enum {
+ EnableEnet = IBIT(0),
+ EnableXcrLB= IBIT(1),
+ DisableColTest= IBIT(2),
+ DisableFullDplx=IBIT(3),
+ LedOff= IBIT(4),
+ DisableUSB= IBIT(5),
+ HighSpdUSB= IBIT(6),
+ EnableUSBPwr= IBIT(7),
+ /* 8,9,10 unused */
+ PCCVCCMask= IBIT(12)|IBIT(13),
+ PCCVPPMask= IBIT(14)|IBIT(15),
+ PCCVCC0V= 0,
+ PCCVCC5V= IBIT(13),
+ PCCVCC3V= IBIT(12),
+ PCCVPP0V= 0,
+ PCCVPP5V= IBIT(14),
+ PCCVPP12V= IBIT(15),
+ PCCVPPHiZ= IBIT(14)|IBIT(15),
+ /* 16-23 NYI */
+ DipSwitchMask= IBIT(24)|IBIT(25)|IBIT(26)|IBIT(27),
+ DipSwitch0= IBIT(24),
+ DipSwitch1= IBIT(25),
+ DipSwitch2= IBIT(26),
+ DipSwitch3= IBIT(27),
+ /* bit 28 RESERVED */
+ FlashComplete= IBIT(29),
+ NVRAMBattGood= IBIT(30),
+ RTCBattGood= IBIT(31),
+};
--- /dev/null
+++ b/os/boot.original/rpcg/boot.h
@@ -1,0 +1,8 @@
+#include <u.h>
+#include "lib.h"
+
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
--- /dev/null
+++ b/os/boot.original/rpcg/bootp.c
@@ -1,0 +1,509 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ip.h"
+
+#define XPADDR(a) ((ulong)(a) & ~KSEGM)
+
+enum {
+ CHECKSUM = 1, /* set zero if trouble booting from Linux */
+};
+
+uchar broadcast[Eaddrlen] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static ushort tftpport = 5000;
+static int Id = 1;
+static Netaddr myaddr;
+static Netaddr server;
+
+typedef struct {
+ uchar header[4];
+ uchar data[Segsize];
+} Tftp;
+static Tftp tftpb;
+
+static void
+hnputs(uchar *ptr, ushort val)
+{
+ ptr[0] = val>>8;
+ ptr[1] = val;
+}
+
+static void
+hnputl(uchar *ptr, ulong val)
+{
+ ptr[0] = val>>24;
+ ptr[1] = val>>16;
+ ptr[2] = val>>8;
+ ptr[3] = val;
+}
+
+static ulong
+nhgetl(uchar *ptr)
+{
+ return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+}
+
+static ushort
+nhgets(uchar *ptr)
+{
+ return ((ptr[0]<<8) | ptr[1]);
+}
+
+static short endian = 1;
+static char* aendian = (char*)&endian;
+#define LITTLE *aendian
+
+static ushort
+ptcl_csum(void *a, int len)
+{
+ uchar *addr;
+ ulong t1, t2;
+ ulong losum, hisum, mdsum, x;
+
+ addr = a;
+ losum = 0;
+ hisum = 0;
+ mdsum = 0;
+
+ x = 0;
+ if((ulong)addr & 1) {
+ if(len) {
+ hisum += addr[0];
+ len--;
+ addr++;
+ }
+ x = 1;
+ }
+ while(len >= 16) {
+ t1 = *(ushort*)(addr+0);
+ t2 = *(ushort*)(addr+2); mdsum += t1;
+ t1 = *(ushort*)(addr+4); mdsum += t2;
+ t2 = *(ushort*)(addr+6); mdsum += t1;
+ t1 = *(ushort*)(addr+8); mdsum += t2;
+ t2 = *(ushort*)(addr+10); mdsum += t1;
+ t1 = *(ushort*)(addr+12); mdsum += t2;
+ t2 = *(ushort*)(addr+14); mdsum += t1;
+ mdsum += t2;
+ len -= 16;
+ addr += 16;
+ }
+ while(len >= 2) {
+ mdsum += *(ushort*)addr;
+ len -= 2;
+ addr += 2;
+ }
+ if(x) {
+ if(len)
+ losum += addr[0];
+ if(LITTLE)
+ losum += mdsum;
+ else
+ hisum += mdsum;
+ } else {
+ if(len)
+ hisum += addr[0];
+ if(LITTLE)
+ hisum += mdsum;
+ else
+ losum += mdsum;
+ }
+
+ losum += hisum >> 8;
+ losum += (hisum & 0xff) << 8;
+ while(hisum = losum>>16)
+ losum = hisum + (losum & 0xffff);
+
+ return ~losum;
+}
+
+static ushort
+ip_csum(uchar *addr)
+{
+ int len;
+ ulong sum = 0;
+
+ len = (addr[0]&0xf)<<2;
+
+ while(len > 0) {
+ sum += addr[0]<<8 | addr[1] ;
+ len -= 2;
+ addr += 2;
+ }
+
+ sum = (sum & 0xffff) + (sum >> 16);
+ sum = (sum & 0xffff) + (sum >> 16);
+ return (sum^0xffff);
+}
+
+static void
+udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+ Udphdr *uh;
+ Etherhdr *ip;
+ static Etherpkt pkt;
+ int len, ptcllen;
+
+
+ uh = (Udphdr*)&pkt;
+
+ memset(uh, 0, sizeof(Etherpkt));
+ memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
+
+ /*
+ * UDP portion
+ */
+ ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
+ uh->ttl = 0;
+ uh->udpproto = IP_UDPPROTO;
+ uh->frag[0] = 0;
+ uh->frag[1] = 0;
+ hnputs(uh->udpplen, ptcllen);
+ hnputl(uh->udpsrc, myaddr.ip);
+ hnputs(uh->udpsport, myaddr.port);
+ hnputl(uh->udpdst, a->ip);
+ hnputs(uh->udpdport, a->port);
+ hnputs(uh->udplen, ptcllen);
+ uh->udpcksum[0] = 0;
+ uh->udpcksum[1] = 0;
+ /*dlen = (dlen+1)&~1; */
+ hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
+
+ /*
+ * IP portion
+ */
+ ip = (Etherhdr*)&pkt;
+ len = sizeof(Udphdr)+dlen;
+ ip->vihl = IP_VER|IP_HLEN;
+ ip->tos = 0;
+ ip->ttl = 255;
+ hnputs(ip->length, len-ETHER_HDR);
+ hnputs(ip->id, Id++);
+ ip->frag[0] = 0;
+ ip->frag[1] = 0;
+ ip->cksum[0] = 0;
+ ip->cksum[1] = 0;
+ hnputs(ip->cksum, ip_csum(&ip->vihl));
+
+ /*
+ * Ethernet MAC portion
+ */
+ hnputs(ip->type, ET_IP);
+ memmove(ip->d, a->ea, sizeof(ip->d));
+
+ ethertxpkt(ctlrno, &pkt, len, Timeout);
+}
+
+static void
+nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
+{
+ int n;
+ char buf[128];
+
+ buf[0] = 0;
+ buf[1] = Tftp_ERROR;
+ buf[2] = 0;
+ buf[3] = code;
+ strcpy(buf+4, msg);
+ n = strlen(msg) + 4 + 1;
+ udpsend(ctlrno, a, buf, n);
+ if(report)
+ print("\ntftp: error(%d): %s\n", code, msg);
+}
+
+static int
+udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
+{
+ int n, len;
+ ushort csm;
+ Udphdr *h;
+ ulong addr, timo;
+ static Etherpkt pkt;
+ static int rxactive;
+
+ if(rxactive == 0)
+ timo = 1000;
+ else
+ timo = Timeout;
+ timo += TK2MS(m->ticks);
+ while(timo > TK2MS(m->ticks)){
+ n = etherrxpkt(ctlrno, &pkt, timo-TK2MS(m->ticks));
+ if(n <= 0)
+ continue;
+
+ h = (Udphdr*)&pkt;
+ if(nhgets(h->type) != ET_IP)
+ continue;
+
+ if(ip_csum(&h->vihl)) {
+ print("ip chksum error\n");
+ continue;
+ }
+ if(h->vihl != (IP_VER|IP_HLEN)) {
+ print("ip bad vers/hlen\n");
+ continue;
+ }
+
+ if(h->udpproto != IP_UDPPROTO)
+ continue;
+
+ h->ttl = 0;
+ len = nhgets(h->udplen);
+ hnputs(h->udpplen, len);
+
+ if(CHECKSUM && nhgets(h->udpcksum)) {
+ csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
+ if(csm != 0) {
+ print("udp chksum error csum #%4lux len %d\n", csm, n);
+ break;
+ }
+ }
+
+ if(a->port != 0 && nhgets(h->udpsport) != a->port)
+ continue;
+
+ addr = nhgetl(h->udpsrc);
+ if(a->ip != Bcastip && addr != a->ip)
+ continue;
+
+ len -= UDP_HDRSIZE-UDP_PHDRSIZE;
+ if(len > dlen) {
+ print("udp: packet too big\n");
+ continue;
+ }
+
+ memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
+ a->ip = addr;
+ a->port = nhgets(h->udpsport);
+ memmove(a->ea, pkt.s, sizeof(a->ea));
+
+ rxactive = 1;
+ return len;
+ }
+
+ return 0;
+}
+
+static int tftpblockno;
+
+static int
+tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
+{
+ int i, len, rlen, oport;
+ char buf[Segsize+2];
+
+ buf[0] = 0;
+ buf[1] = Tftp_READ;
+ len = sprint(buf+2, "%s", name) + 2;
+ len += sprint(buf+len+1, "octet") + 2;
+
+ oport = a->port;
+ for(i = 0; i < 5; i++){
+ a->port = oport;
+ udpsend(ctlrno, a, buf, len);
+ a->port = 0;
+ if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
+ continue;
+
+ switch((tftp->header[0]<<8)|tftp->header[1]){
+
+ case Tftp_ERROR:
+ print("tftpopen: error (%d): %s\n",
+ (tftp->header[2]<<8)|tftp->header[3], tftp->data);
+ return -1;
+
+ case Tftp_DATA:
+ tftpblockno = 1;
+ len = (tftp->header[2]<<8)|tftp->header[3];
+ if(len != tftpblockno){
+ print("tftpopen: block error: %d\n", len);
+ nak(ctlrno, a, 1, "block error", 0);
+ return -1;
+ }
+ return rlen-sizeof(tftp->header);
+ }
+ }
+
+ print("tftpopen: failed to connect to server\n");
+ return -1;
+}
+
+static int
+tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
+{
+ int blockno, len, retry;
+ uchar buf[4];
+
+ buf[0] = 0;
+ buf[1] = Tftp_ACK;
+ buf[2] = tftpblockno>>8;
+ buf[3] = tftpblockno;
+ tftpblockno++;
+
+ dlen += sizeof(tftp->header);
+
+ retry = 0;
+buggery:
+ udpsend(ctlrno, a, buf, sizeof(buf));
+
+ if((len = udprecv(ctlrno, a, tftp, dlen)) < dlen){
+ print("tftpread: %d != %d\n", len, dlen);
+ nak(ctlrno, a, 2, "short read", 0);
+ if(retry++ < 5)
+ goto buggery;
+ return -1;
+ }
+
+ blockno = (tftp->header[2]<<8)|tftp->header[3];
+ if(blockno != tftpblockno){
+ print("?");
+
+ if(blockno == tftpblockno-1 && retry++ < 8)
+ goto buggery;
+ print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
+ nak(ctlrno, a, 1, "block error", 0);
+
+ return -1;
+ }
+
+ return len-sizeof(tftp->header);
+}
+
+int
+bootp(int ctlrno, char *file)
+{
+ Bootp req, rep;
+ int i, dlen, segsize, text, data, bss, total;
+ uchar *ea, *addr, *p;
+ ulong entry;
+ Exec *exec;
+ char name[128], *filename, *sysname;
+
+ if((ea = etheraddr(ctlrno)) == 0){
+ print("invalid ctlrno %d\n", ctlrno);
+ return -1;
+ }
+
+ filename = 0;
+ sysname = 0;
+ if(file && *file){
+ strcpy(name, file);
+ if(filename = strchr(name, ':')){
+ if(filename != name && *(filename-1) != '\\'){
+ sysname = name;
+ *filename++ = 0;
+ }
+ }
+ else
+ filename = name;
+ }
+
+
+ memset(&req, 0, sizeof(req));
+ req.op = Bootrequest;
+ req.htype = 1; /* ethernet */
+ req.hlen = Eaddrlen; /* ethernet */
+ memmove(req.chaddr, ea, Eaddrlen);
+
+ myaddr.ip = 0;
+ myaddr.port = BPportsrc;
+ memmove(myaddr.ea, ea, Eaddrlen);
+
+ for(i = 0; i < 10; i++) {
+ server.ip = Bcastip;
+ server.port = BPportdst;
+ memmove(server.ea, broadcast, sizeof(server.ea));
+ udpsend(ctlrno, &server, &req, sizeof(req));
+ if(udprecv(ctlrno, &server, &rep, sizeof(rep)) <= 0)
+ continue;
+ if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
+ continue;
+ if(rep.htype != 1 || rep.hlen != Eaddrlen)
+ continue;
+ if(sysname == 0 || strcmp(sysname, rep.sname) == 0)
+ break;
+ }
+ if(i >= 10) {
+ print("bootp timed out\n");
+ return -1;
+ }
+
+ if(filename == 0 || *filename == 0)
+ filename = rep.file;
+
+ if(rep.sname[0] != '\0')
+ print("%s ", rep.sname);
+ print("(%d.%d.%d.%d!%d): %s\n",
+ rep.siaddr[0],
+ rep.siaddr[1],
+ rep.siaddr[2],
+ rep.siaddr[3],
+ server.port,
+ filename);uartwait();
+
+ myaddr.ip = nhgetl(rep.yiaddr);
+ myaddr.port = tftpport++;
+ server.ip = nhgetl(rep.siaddr);
+ server.port = TFTPport;
+
+ if((dlen = tftpopen(ctlrno, &server, filename, &tftpb)) < 0)
+ return -1;
+ exec = (Exec*)(tftpb.data);
+ if(dlen < sizeof(Exec) || GLLONG(exec->magic) != Q_MAGIC){
+ nak(ctlrno, &server, 0, "bad magic number", 1);
+ return -1;
+ }
+ text = GLLONG(exec->text);
+ data = GLLONG(exec->data);
+ bss = GLLONG(exec->bss);
+ total = text+data+bss;
+ entry = GLLONG(exec->entry);
+print("load@%8.8lux: ", XPADDR(entry));uartwait();
+ print("%d", text);
+
+ addr = (uchar*)XPADDR(entry);
+ p = tftpb.data+sizeof(Exec);
+ dlen -= sizeof(Exec);
+ segsize = text;
+ for(;;){
+ if(dlen == 0){
+ if((dlen = tftpread(ctlrno, &server, &tftpb, sizeof(tftpb.data))) < 0)
+ return -1;
+ p = tftpb.data;
+ }
+ if(segsize <= dlen)
+ i = segsize;
+ else
+ i = dlen;
+ memmove(addr, p, i);
+
+ addr += i;
+ p += i;
+ segsize -= i;
+ dlen -= i;
+
+ if(segsize <= 0){
+ if(data == 0)
+ break;
+ print("+%d", data);
+ segsize = data;
+ data = 0;
+ addr = (uchar*)PGROUND((ulong)addr);
+ }
+ }
+ nak(ctlrno, &server, 3, "ok", 0); /* tftpclose */
+ print("+%d=%d\n", bss, total);
+ print("entry: 0x%lux\n", entry);
+ uartwait();
+ scc2stop();
+ splhi();
+ (*(void(*)(void))(XPADDR(entry)))();
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/clock.c
@@ -1,0 +1,71 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+enum {
+ Timebase = 4, /* system clock cycles per time base cycle */
+};
+
+void (*archclocktick)(void); /* set by arch*.c when desired */
+
+static ulong clkreload;
+
+void
+delay(int l)
+{
+ ulong i, j;
+
+ j = m->delayloop;
+ while(l-- > 0)
+ for(i=0; i < j; i++)
+ ;
+}
+
+void
+microdelay(int l)
+{
+ ulong i;
+
+ l *= m->delayloop;
+ l /= 1000;
+ if(l <= 0)
+ l = 1;
+ for(i = 0; i < l; i++)
+ ;
+}
+
+void
+clockintr(Ureg*, void*)
+{
+ putdec(clkreload);
+ m->ticks++;
+ checkalarms();
+ if(archclocktick != nil)
+ archclocktick();
+}
+
+void
+clockinit(void)
+{
+ long x;
+
+ m->delayloop = m->cpuhz/1000; /* initial estimate */
+ do {
+ x = gettbl();
+ delay(10);
+ x = gettbl() - x;
+ } while(x < 0);
+
+ /*
+ * fix count
+ */
+ m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase);
+ if(m->delayloop == 0)
+ m->delayloop = 1;
+ clkreload = (m->clockgen/Timebase)/HZ-1;
+ putdec(clkreload);
+}
--- /dev/null
+++ b/os/boot.original/rpcg/conf.c
@@ -1,0 +1,173 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "dosfs.h"
+
+static char *confname[MAXCONF];
+static char *confval[MAXCONF];
+static int nconf;
+
+extern char **ini;
+
+char*
+getconf(char *name)
+{
+ int i;
+
+ for(i = 0; i < nconf; i++)
+ if(strcmp(confname[i], name) == 0)
+ return confval[i];
+ return 0;
+}
+
+/*
+ * read configuration file
+ */
+int
+plan9ini(Dos *dos, char *val)
+{
+ Dosfile rc;
+ int i, n;
+ char *cp, *p, *q, *line[MAXCONF];
+
+ cp = BOOTARGS;
+ if(dos) {
+ if(dosstat(dos, *ini, &rc) <= 0)
+ return -1;
+
+ *cp = 0;
+ n = dosread(&rc, cp, BOOTARGSLEN-1);
+ if(n <= 0)
+ return -1;
+ cp[n] = 0;
+ } else if(val != nil){
+ if(memchr(val, 0, BOOTARGSLEN-1) == nil)
+ return -1;
+ print("Using flash configuration\n");
+ strcpy(cp, val);
+ n = strlen(cp);
+ }else{
+ strcpy(cp, archconfig());
+ n = strlen(cp);
+ }
+
+ /*
+ * Make a working copy.
+ * We could change this to pass the parsed strings
+ * to the booted programme instead of the raw
+ * string, then it only gets done once.
+ */
+ memmove(cp+BOOTARGSLEN, cp, n+1);
+ cp += BOOTARGSLEN;
+
+ /*
+ * Strip out '\r', change '\t' -> ' '.
+ */
+ p = cp;
+ for(q = cp; *q; q++){
+ if(*q == '\r')
+ continue;
+ if(*q == '\t')
+ *q = ' ';
+ *p++ = *q;
+ }
+ *p = 0;
+ n = getcfields(cp, line, MAXCONF, "\n");
+ for(i = 0; i < n; i++){
+ cp = strchr(line[i], '=');
+ if(cp == 0)
+ continue;
+ *cp++ = 0;
+ if(cp - line[i] >= NAMELEN+1)
+ *(line[i]+NAMELEN-1) = 0;
+ confname[nconf] = line[i];
+ confval[nconf] = cp;
+ nconf++;
+ }
+ return 0;
+}
+
+int
+parseether(uchar *to, char *from)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ while(*p == ' ')
+ ++p;
+ for(i = 0; i < 6; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ char cc[NAMELEN], *p, *q, *r;
+ int n;
+
+ sprint(cc, "%s%d", class, ctlrno);
+ for(n = 0; n < nconf; n++){
+ if(strncmp(confname[n], cc, NAMELEN))
+ continue;
+ isa->nopt = 0;
+ p = confval[n];
+ while(*p){
+ while(*p == ' ' || *p == '\t')
+ p++;
+ if(*p == '\0')
+ break;
+ if(strncmp(p, "type=", 5) == 0){
+ p += 5;
+ for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
+ if(*p == '\0' || *p == ' ' || *p == '\t')
+ break;
+ *q = *p++;
+ }
+ *q = '\0';
+ }
+ else if(strncmp(p, "port=", 5) == 0)
+ isa->port = strtoul(p+5, &p, 0);
+ else if(strncmp(p, "irq=", 4) == 0)
+ isa->irq = strtoul(p+4, &p, 0);
+ else if(strncmp(p, "mem=", 4) == 0)
+ isa->mem = strtoul(p+4, &p, 0);
+ else if(strncmp(p, "size=", 5) == 0)
+ isa->size = strtoul(p+5, &p, 0);
+ else if(strncmp(p, "ea=", 3) == 0){
+ if(parseether(isa->ea, p+3) == -1)
+ memset(isa->ea, 0, 6);
+ }
+ else if(isa->nopt < NISAOPT){
+ r = isa->opt[isa->nopt];
+ while(*p && *p != ' ' && *p != '\t'){
+ *r++ = *p++;
+ if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
+ break;
+ }
+ *r = '\0';
+ isa->nopt++;
+ }
+ while(*p && *p != ' ' && *p != '\t')
+ p++;
+ }
+ return 1;
+ }
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/console.c
@@ -1,0 +1,173 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+static Queue* consiq;
+static Queue* consoq;
+
+void
+bothputs(char *s, int n)
+{
+ uartputs(s, n);
+ screenputs(s, n);
+}
+
+static void (*consputs)(char*, int) = bothputs; /* or screenputs */
+
+void
+consinit(void)
+{
+ char *p;
+ int baud, port;
+ static int cgadone;
+
+ p = getconf("console");
+ if(0)
+ if(p == 0 || strcmp(p, "lcd") == 0 || strcmp(p, "screen") == 0){
+ consiq = qopen(4*1024, 0, 0, 0);
+ consoq = qopen(8*1024, 0, 0, 0);
+ consputs = screenputs;
+ return;
+ }
+ if(p!=0 && strstr(p, "lcd") == 0)
+ consputs = bothputs;
+ else
+ consputs = uartputs;
+//consputs = screenputs;
+ port = 0;
+ if(p)
+ port = strtoul(p, 0, 0);
+ baud = 0;
+ if(p = getconf("baud"))
+ baud = strtoul(p, 0, 0);
+ if(baud == 0)
+ baud = 9600;
+ uartspecial(port, baud, &consiq, &consoq, kbdchar);
+}
+
+void
+kbdchar(Queue *q, int c)
+{
+ c &= 0x7F;
+ if(c == 0x10)
+ panic("^p");
+ qbputc(q, c);
+}
+
+static int
+getline(char *buf, int size, int dotimeout)
+{
+ int c, i=0;
+ ulong start;
+ char echo;
+
+ for (;;) {
+ start = m->ticks;
+ do{
+ if(dotimeout && ((m->ticks - start) > 5*HZ))
+ return -2;
+ c = qbgetc(consiq);
+ }while(c == -1);
+ if(c == '\r')
+ c = '\n'; /* turn carriage return into newline */
+ if(c == '\177')
+ c = '\010'; /* turn delete into backspace */
+ if(c == '\025')
+ echo = '\n'; /* echo ^U as a newline */
+ else
+ echo = c;
+ (*consputs)(&echo, 1);
+
+ if(c == '\010'){
+ if(i > 0)
+ i--; /* bs deletes last character */
+ continue;
+ }
+ /* a newline ends a line */
+ if (c == '\n')
+ break;
+ /* ^U wipes out the line */
+ if (c =='\025')
+ return -1;
+ if(i == size)
+ return size;
+ buf[i++] = c;
+ }
+ buf[i] = 0;
+ return i;
+}
+
+int
+getstr(char *prompt, char *buf, int size, char *def)
+{
+ int len, isdefault;
+
+ buf[0] = 0;
+ isdefault = (def && *def);
+ for (;;) {
+ if(isdefault)
+ print("%s[default==%s]: ", prompt, def);
+ else
+ print("%s: ", prompt);
+ len = getline(buf, size, isdefault);
+ switch(len){
+ case -1:
+ /* ^U typed */
+ continue;
+ case -2:
+ /* timeout, use default */
+ (*consputs)("\n", 1);
+ len = 0;
+ break;
+ default:
+ break;
+ }
+ if(len >= size){
+ print("line too long\n");
+ continue;
+ }
+ break;
+ }
+ if(len == 0 && isdefault)
+ strcpy(buf, def);
+ return 0;
+}
+
+int
+sprint(char *s, char *fmt, ...)
+{
+ return donprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
+}
+
+int
+print(char *fmt, ...)
+{
+ char buf[PRINTSIZE];
+ int n;
+
+ if(consputs == 0)
+ return 0;
+ n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+ (*consputs)(buf, n);
+ return n;
+}
+
+void
+panic(char *fmt, ...)
+{
+ char buf[PRINTSIZE];
+ int n;
+
+ if(consputs){
+ (*consputs)("panic: ", 7);
+ n = donprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
+ (*consputs)(buf, n);
+ (*consputs)("\n", 1);
+ }
+ spllo();
+ for(;;)
+ idle();
+}
--- /dev/null
+++ b/os/boot.original/rpcg/cpm.c
@@ -1,0 +1,162 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum {
+ BDSIZE= 1024, /* TO DO: check this */
+};
+
+static Map bdmapv[BDSIZE/sizeof(BD)];
+static RMap bdmap = {"buffer descriptors"};
+
+void
+cpminit(void)
+{
+ IMM *io;
+
+ io = m->iomem;
+ io->sdcr = 1;
+ io->lccr &= ~1; /* disable LCD */
+ io->pcint = 0; /* disable all port C interrupts */
+ io->pcso = 0;
+ io->pcdir =0;
+ io->pcpar = 0;
+ io->pcdat = 0;
+ io->papar = 0;
+ io->padir = 0;
+ io->paodr = 0;
+ io->padat = 0;
+ io->pbpar = 0;
+ io->pbdir = 0;
+ io->pbodr = 0;
+ io->pbdat = 0;
+ eieio();
+
+ for(io->cpcr = 0x8001; io->cpcr & 1;) /* reset all CPM channels */
+ eieio();
+
+ mapinit(&bdmap, bdmapv, sizeof(bdmapv));
+ mapfree(&bdmap, DPBASE, BDSIZE);
+}
+
+void
+cpmop(int op, int cno, int param)
+{
+ IMM *io;
+ int s;
+
+ s = splhi();
+ io = m->iomem;
+ eieio();
+ while(io->cpcr & 1)
+ eieio();
+ io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1;
+ eieio();
+ while(io->cpcr & 1)
+ eieio();
+ splx(s);
+}
+
+/*
+ * connect SCCx clocks in NSMI mode (x=1 for USB)
+ */
+void
+sccnmsi(int x, int rcs, int tcs)
+{
+ IMM *io;
+ ulong v;
+ int sh;
+
+ sh = (x-1)*8; /* each SCCx field in sicr is 8 bits */
+ v = (((rcs&7)<<3) | (tcs&7)) << sh;
+ io = ioplock();
+ io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
+ iopunlock();
+}
+
+void
+scc2stop(void)
+{
+ SCC *scc;
+
+ scc = IOREGS(0xA20, SCC);
+ if(scc->gsmrl & (3<<4)){
+ cpmop(GracefulStopTx, SCC2ID, 0);
+ cpmop(CloseRxBD, SCC2ID, 0);
+ delay(1);
+ scc->gsmrl &= ~(3<<4); /* disable current use */
+ archetherdisable(SCC2ID);
+ }
+}
+
+BD *
+bdalloc(int n)
+{
+ ulong a;
+
+ a = mapalloc(&bdmap, 0, n*sizeof(BD), 0);
+ if(a == 0)
+ panic("bdalloc");
+ return KADDR(a);
+}
+
+void
+bdfree(BD *b, int n)
+{
+ if(b){
+ eieio();
+ mapfree(&bdmap, PADDR(b), n*sizeof(BD));
+ }
+}
+
+/*
+ * initialise receive and transmit buffer rings.
+ */
+int
+ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
+{
+ int i, x;
+
+ /* the ring entries must be aligned on sizeof(BD) boundaries */
+ r->nrdre = nrdre;
+ if(r->rdr == nil)
+ r->rdr = bdalloc(nrdre);
+ /* the buffer size must align with cache lines since the cache doesn't snoop */
+ bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1);
+ if(r->rrb == nil)
+ r->rrb = malloc(nrdre*bufsize);
+ if(r->rdr == nil || r->rrb == nil)
+ return -1;
+ dcflush(r->rrb, nrdre*bufsize);
+ x = PADDR(r->rrb);
+ for(i = 0; i < nrdre; i++){
+ r->rdr[i].length = 0;
+ r->rdr[i].addr = x;
+ r->rdr[i].status = BDEmpty|BDInt;
+ x += bufsize;
+ }
+ r->rdr[i-1].status |= BDWrap;
+ r->rdrx = 0;
+
+ r->ntdre = ntdre;
+ if(r->tdr == nil)
+ r->tdr = bdalloc(ntdre);
+ if(r->txb == nil)
+ r->txb = malloc(ntdre*sizeof(Block*));
+ if(r->tdr == nil || r->txb == nil)
+ return -1;
+ for(i = 0; i < ntdre; i++){
+ r->txb[i] = nil;
+ r->tdr[i].addr = 0;
+ r->tdr[i].length = 0;
+ r->tdr[i].status = 0;
+ }
+ r->tdr[i-1].status |= BDWrap;
+ r->tdrh = 0;
+ r->tdri = 0;
+ r->ntq = 0;
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/crc32.c
@@ -1,0 +1,42 @@
+#include "boot.h"
+
+/*
+ * from Rob Warnock
+ */
+static ulong crc32tab[256]; /* initialised on first call to crc32 */
+
+enum {
+ CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+ int i, j;
+ ulong c;
+
+ for(i = 0; i < 256; i++) {
+ for(c = i << 24, j = 8; j > 0; j--)
+ if(c & (1<<31))
+ c = (c<<1) ^ CRC32POLY;
+ else
+ c <<= 1;
+ crc32tab[i] = c;
+ }
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+ uchar *p;
+
+ if(crc32tab[1] == 0)
+ initcrc32();
+ crc = ~crc;
+ for(p = buf; --n >= 0;)
+ crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+ return ~crc;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/dat.h
@@ -1,0 +1,217 @@
+typedef struct Alarm Alarm;
+typedef struct Block Block;
+typedef struct IMM IMM;
+typedef struct Queue Queue;
+
+typedef struct List {
+ void *next;
+} List;
+
+typedef struct {
+ int fake;
+ int pri;
+} Lock;
+#define lock(x)
+#define unlock(x)
+
+struct Alarm {
+ List;
+ int busy;
+ long dt;
+ void (*f)(Alarm*);
+ void *arg;
+};
+
+enum {
+ Eaddrlen = 6,
+ ETHERMINTU = 60, /* minimum transmit size */
+ ETHERMAXTU = 1514, /* maximum transmit size */
+ ETHERHDRSIZE = 14, /* size of an ethernet header */
+
+ MaxEther = 4,
+};
+
+typedef struct {
+ uchar d[Eaddrlen];
+ uchar s[Eaddrlen];
+ uchar type[2];
+ uchar data[1500];
+ uchar crc[4];
+} Etherpkt;
+
+extern uchar broadcast[Eaddrlen];
+
+enum {
+ Npart = 20+2, /* 8 sub partitions, disk, and partition */
+ Maxxfer = 16*1024, /* maximum transfer size/cmd */
+};
+
+typedef struct {
+ ulong start;
+ ulong end;
+ char name[NAMELEN+1];
+} Partition;
+
+typedef struct {
+ int online;
+ int npart; /* number of real partitions */
+ Partition p[Npart];
+ ulong offset;
+ Partition *current; /* current partition */
+
+ ulong cap; /* total bytes */
+ int bytes; /* bytes/sector */
+ int sectors; /* sectors/track */
+ int heads; /* heads/cyl */
+ long cyl; /* cylinders/drive */
+
+ char lba; /* true if drive has logical block addressing */
+ char multi; /* non-zero if drive does multiple block xfers */
+} Disc;
+
+enum {
+ ScsiTestunit = 0x00,
+ ScsiExtsens = 0x03,
+ ScsiInquiry = 0x12,
+ ScsiModesense = 0x1a,
+ ScsiStartunit = 0x1B,
+ ScsiStopunit = 0x1B,
+ ScsiGetcap = 0x25,
+ ScsiRead = 0x08,
+ ScsiWrite = 0x0a,
+ ScsiExtread = 0x28,
+ ScsiExtwrite = 0x2a,
+
+ /* data direction */
+ ScsiIn = 1,
+ ScsiOut = 0,
+};
+
+typedef struct Scsibuf Scsibuf;
+typedef struct Scsibuf {
+ void* virt;
+ void* phys;
+ Scsibuf* next;
+};
+
+typedef struct Scsidata {
+ uchar* base;
+ uchar* lim;
+ uchar* ptr;
+} Scsidata;
+
+typedef struct Ureg Ureg;
+
+typedef struct Scsi {
+ ulong pid;
+ ushort target;
+ ushort lun;
+ ushort rflag;
+ ushort status;
+ Scsidata cmd;
+ Scsidata data;
+ Scsibuf* b;
+ uchar* save;
+ uchar cmdblk[16];
+} Scsi;
+
+typedef struct Segdesc {
+ ulong d0;
+ ulong d1;
+} Segdesc;
+
+typedef struct Mach {
+ ulong ticks; /* of the clock since boot time */
+ ulong delayloop;
+ long cpuhz; /* general system clock (cycles) */
+ long clockgen; /* clock generator frequency (cycles) */
+ ulong cpupvr; /* cpu type in processor version register */
+ ulong cputype; /* cpu variant in BCD (eg, 0x823xx) */
+ void* alarm; /* alarms bound to this clock */
+ ulong* bcsr;
+ IMM* iomem;
+} Mach;
+
+/* Mach.cputype */
+#define MPCREV(x) ((x) & 0xFF)
+#define MPCMODEL(x) (((x)>>8) & 0xFFF)
+#define MPCFAMILY(x) (((x)>>24) & 0x0F)
+
+
+extern Mach *m;
+
+#define Q_MAGIC ((((4*21)+0)*21)+7)
+
+typedef struct Exec Exec;
+struct Exec
+{
+ uchar magic[4]; /* magic number */
+ uchar text[4]; /* size of text segment */
+ uchar data[4]; /* size of initialized data */
+ uchar bss[4]; /* size of uninitialized data */
+ uchar syms[4]; /* size of symbol table */
+ uchar entry[4]; /* entry point */
+ uchar spsz[4]; /* size of sp/pc offset table */
+ uchar pcsz[4]; /* size of pc/line number table */
+};
+
+/*
+ * bootline passed by boot program
+ */
+#define BOOTLINE ((char *)0x200000-150)
+
+/*
+ * Where we leave configuration info.
+ */
+#define BOOTARGS ((char*)(0x200000))
+#define BOOTARGSLEN 1024
+#define MAXCONF 32
+
+/*
+ * a parsed plan9.ini line
+ */
+#define ISAOPTLEN 16
+#define NISAOPT 8
+
+typedef struct ISAConf {
+ char type[NAMELEN];
+ ulong port;
+ ulong irq;
+ ulong mem;
+ ulong size;
+ uchar ea[6];
+
+ int nopt;
+ char opt[NISAOPT][ISAOPTLEN];
+} ISAConf;
+
+typedef struct {
+ int size;
+ ulong addr;
+} Map;
+
+typedef struct {
+ char* name;
+ Map* map;
+ Map* mapend;
+
+ Lock;
+} RMap;
+
+typedef struct PCIcfg PCIcfg;
+
+extern uchar* vgamem;
+
+struct Block {
+ uchar *rp;
+ uchar *wp;
+ uchar *lim;
+ uchar *data;
+ Block* next;
+ ulong magic;
+};
+#define BLEN(b) ((b)->wp-(b)->rp)
+
+typedef struct QLock {
+ int dummy;
+} QLock;
--- /dev/null
+++ b/os/boot.original/rpcg/defont0.c
@@ -1,0 +1,216 @@
+#include <u.h>
+#include <libc.h>
+#include <libg.h>
+#include <gnot.h>
+
+
+
+static ulong bits0[] = {
+ 0x907070f0, 0xf0f07000, 0xf0888888, 0xf8707070, 0xe0e0e0e0, 0xe09070f0, 0x70f870f0, 0xf870f088,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000e0,
+ 0xd0808080, 0x80808800, 0x8888c888, 0x80888888, 0x90909090, 0x90d08080, 0x80808080, 0x80888888,
+ 0x00000000, 0x08000000, 0x0c300000, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000003c, 0xc03c0000,
+ 0x00006000, 0x06001e00, 0x60181860, 0x78000000, 0x00000000, 0x00000000, 0x0000001c, 0x18380090,
+ 0xb06060e0, 0xe0e0f800, 0xf088a888, 0x80808080, 0x90909090, 0x90b060e0, 0x808060e0, 0x80808888,
+ 0x00182428, 0x3e707018, 0x18180000, 0x00000006, 0x3c183c3c, 0x1c3e3c7e, 0x3c3c0000, 0x0200403c,
+ 0x3c187c1e, 0x787e7e1e, 0x663c7c66, 0x6066623c, 0x7c3c7c3c, 0x7e6266c2, 0x66667e30, 0xc00c1000,
+ 0x08006000, 0x06003000, 0x60181860, 0x18000000, 0x00000000, 0x10000000, 0x00000030, 0x180c0090,
+ 0x90101080, 0x80808818, 0x88f8a888, 0xe0807070, 0xe0e0e0e0, 0xe0901080, 0x70e01080, 0xe098f088,
+ 0x00182428, 0x6adad818, 0x18181000, 0x0000000c, 0x66386666, 0x2c3e667e, 0x66660000, 0x06006066,
+ 0x42186632, 0x6c606032, 0x66181864, 0x60667224, 0x66246666, 0x186262da, 0x62620630, 0x600c3800,
+ 0x10006000, 0x06003000, 0x60000060, 0x18000000, 0x00000000, 0x30000000, 0x00000030, 0x180c00e0,
+ 0x00e0e0f0, 0xf0f00018, 0x88889850, 0x80880808, 0x201c1c1c, 0x1c00e0f0, 0x0080e0f0, 0x80888888,
+ 0x00182428, 0x68dad808, 0x300c5418, 0x0000000c, 0x66580606, 0x2c206002, 0x66661818, 0x0cfe3006,
+ 0x9e2c6660, 0x66606060, 0x6618186c, 0x60667266, 0x66666660, 0x186262da, 0x36660c30, 0x600c2800,
+ 0x103c6c3c, 0x3e3c7e3e, 0x6c787866, 0x18d46c3c, 0x6c3e763c, 0x7e6666c2, 0x66667e18, 0x18180000,
+ 0x44180000, 0x18241c24, 0xf0888820, 0x8070f0f0, 0x20202020, 0x201c243e, 0x1cf8241c, 0x80708870,
+ 0x0018247c, 0x78745008, 0x300c3818, 0x00000018, 0x66180606, 0x4c206006, 0x76661818, 0x18fe180c,
+ 0xb62c6660, 0x66606060, 0x66181868, 0x607e5a66, 0x66666470, 0x186266da, 0x34340c30, 0x300c6c00,
+ 0x18667666, 0x66663066, 0x76181864, 0x18fe7666, 0x76663666, 0x306662da, 0x62620608, 0x1810323c,
+ 0x44247c7c, 0x24342042, 0x00000000, 0x00000000, 0x20202020, 0x20222408, 0x22002420, 0x00000000,
+ 0x00180028, 0x3c287610, 0x300cee7e, 0x00fe0018, 0x66180c18, 0x4c3c7c0c, 0x3c3e0000, 0x30000c18,
+ 0xb62c7c60, 0x667c7c6e, 0x7e181878, 0x605a5a66, 0x6466783c, 0x186234da, 0x18341830, 0x300c4400,
+ 0x18066660, 0x66663066, 0x66181868, 0x18d66666, 0x66663860, 0x306662da, 0x34620c30, 0x180c5a20,
+ 0x44241010, 0x242c2042, 0x0e3e103e, 0x3e3c1c3e, 0x3c1c1c1c, 0x1c3e1c08, 0x3e222418, 0x0e0e0e0e,
+ 0x0008007c, 0x1e5cdc00, 0x300c387e, 0x00fe0030, 0x66181806, 0x7e066618, 0x6e060000, 0x18001818,
+ 0xb67e6660, 0x66606066, 0x6618186c, 0x605a4e66, 0x78666c0e, 0x1862346c, 0x2c183030, 0x180c4400,
+ 0x003e6660, 0x667e3066, 0x66181878, 0x18d66666, 0x6666303c, 0x306634da, 0x18341808, 0x18104c38,
+ 0x3c181010, 0x18241c42, 0x11081008, 0x20222208, 0x00000000, 0x00220408, 0x22361804, 0x11111111,
+ 0x00000028, 0x16b6cc00, 0x300c5418, 0x00000030, 0x66183006, 0x7e066618, 0x66060000, 0x0cfe3000,
+ 0x9a466660, 0x66606066, 0x6618186c, 0x605a4e66, 0x60666606, 0x1862346c, 0x6c183030, 0x180c0000,
+ 0x00666660, 0x66603066, 0x6618186c, 0x18d66666, 0x66663006, 0x3066346c, 0x2c343018, 0x18180020,
+ 0x00091010, 0x000e0942, 0x10081008, 0x20222208, 0x0f06060f, 0x0a09041e, 0x002a0e38, 0x10101010,
+ 0x00180028, 0x56b6cc00, 0x300c1018, 0x18001860, 0x66187e66, 0x0c666630, 0x66661818, 0x06fe6018,
+ 0x40466632, 0x6c606036, 0x66181866, 0x605a4624, 0x60246666, 0x1834186c, 0x46186030, 0x0c0c0000,
+ 0x006e6666, 0x6e66306e, 0x66181866, 0x18d66666, 0x666e3066, 0x306e186c, 0x46186030, 0x180c003c,
+ 0x08090909, 0x1f110aff, 0x0e081008, 0x382c2208, 0x08020901, 0x0a0a0911, 0x09220907, 0x0e0e0e0e,
+ 0x00180028, 0x7c1c7600, 0x18180000, 0x18001860, 0x3c7e7e3c, 0x0c3c3c30, 0x3c3c1818, 0x02004018,
+ 0x3e467c1e, 0x787e601e, 0x663c1866, 0x7e42463c, 0x603c663c, 0x1818186c, 0x66187e30, 0x0c0c0000,
+ 0x00367c3c, 0x363c7c36, 0x667e1866, 0x7ed6663c, 0x7c367c3c, 0x1e36186c, 0x66187e30, 0x180c0008,
+ 0x080f0606, 0x04110c18, 0x01081008, 0x20222208, 0x0e020203, 0x0a0c0d1e, 0x0d220e08, 0x01010101,
+ 0x00000000, 0x10000000, 0x18180000, 0x080000c0, 0x00000000, 0x00000000, 0x00000008, 0x00000000,
+ 0x00000000, 0x00000000, 0x00001800, 0x00000000, 0x000c0000, 0x00000000, 0x00000030, 0x060c00fe,
+ 0x00000000, 0x00000006, 0x00001800, 0x00000000, 0x60060000, 0x00000000, 0x0010001c, 0x18380008,
+ 0x08090606, 0x040e0a18, 0x11081f08, 0x20221c3e, 0x08020401, 0x0f0a0b11, 0x0b220908, 0x11111111,
+ 0x00000000, 0x00000000, 0x0c300000, 0x080000c0, 0x00000000, 0x00000000, 0x00000008, 0x00000000,
+ 0x00000000, 0x00000000, 0x00007000, 0x00000000, 0x00060000, 0x00000000, 0x0000003c, 0x063c0000,
+ 0x00000000, 0x00000066, 0x00001800, 0x00000000, 0x60060000, 0x00000000, 0x00300000, 0x00000008,
+ 0x0f090909, 0x04030900, 0x0e000000, 0x00000000, 0x0f0f0f0f, 0x0209091e, 0x09000f07, 0x0e0e0e0e,
+ 0x00000000, 0x00000000, 0x00000000, 0x10000000, 0x00000000, 0x00000000, 0x00000010, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x0000003c, 0x00007000, 0x00000000, 0x60060000, 0x00000000, 0x00600000, 0x0000000f,
+
+};
+
+static GBitmap strike0 = {
+ bits0,
+ 0,
+ 32,
+ 0,
+ {0, 0, 1024, 14},
+ {0, 0, 1024, 14},
+};
+
+static Fontchar info0[] = {
+ { 0, 0, 14, 0, 8 },
+ { 8, 0, 14, 0, 8 },
+ { 16, 0, 14, 0, 8 },
+ { 24, 0, 14, 0, 8 },
+ { 32, 0, 14, 0, 8 },
+ { 40, 0, 14, 0, 8 },
+ { 48, 0, 14, 0, 8 },
+ { 56, 0, 14, 0, 8 },
+ { 64, 0, 14, 0, 8 },
+ { 72, 0, 14, 0, 8 },
+ { 80, 0, 14, 0, 8 },
+ { 88, 0, 14, 0, 8 },
+ { 96, 0, 14, 0, 8 },
+ { 104, 0, 14, 0, 8 },
+ { 112, 0, 14, 0, 8 },
+ { 120, 0, 14, 0, 8 },
+ { 128, 0, 14, 0, 8 },
+ { 136, 0, 14, 0, 8 },
+ { 144, 0, 14, 0, 8 },
+ { 152, 0, 14, 0, 8 },
+ { 160, 0, 14, 0, 8 },
+ { 168, 0, 14, 0, 8 },
+ { 176, 0, 14, 0, 8 },
+ { 184, 0, 14, 0, 8 },
+ { 192, 0, 14, 0, 8 },
+ { 200, 0, 14, 0, 8 },
+ { 208, 0, 14, 0, 8 },
+ { 216, 0, 14, 0, 8 },
+ { 224, 0, 14, 0, 8 },
+ { 232, 0, 14, 0, 8 },
+ { 240, 0, 14, 0, 8 },
+ { 248, 0, 14, 0, 8 },
+ { 256, 0, 0, 0, 8 },
+ { 264, 2, 11, 0, 8 },
+ { 272, 2, 6, 0, 8 },
+ { 280, 2, 11, 0, 8 },
+ { 288, 1, 12, 0, 8 },
+ { 296, 2, 11, 0, 8 },
+ { 304, 2, 11, 0, 8 },
+ { 312, 2, 7, 0, 8 },
+ { 320, 1, 13, 0, 8 },
+ { 328, 1, 13, 0, 8 },
+ { 336, 3, 10, 0, 8 },
+ { 344, 4, 10, 0, 8 },
+ { 352, 9, 14, 0, 8 },
+ { 360, 6, 8, 0, 8 },
+ { 368, 9, 11, 0, 8 },
+ { 376, 1, 13, 0, 8 },
+ { 384, 2, 11, 0, 8 },
+ { 392, 2, 11, 0, 8 },
+ { 400, 2, 11, 0, 8 },
+ { 408, 2, 11, 0, 8 },
+ { 416, 2, 11, 0, 8 },
+ { 424, 2, 11, 0, 8 },
+ { 432, 2, 11, 0, 8 },
+ { 440, 2, 11, 0, 8 },
+ { 448, 2, 11, 0, 8 },
+ { 456, 2, 11, 0, 8 },
+ { 464, 4, 11, 0, 8 },
+ { 472, 4, 14, 0, 8 },
+ { 480, 2, 11, 0, 8 },
+ { 488, 4, 10, 0, 8 },
+ { 496, 2, 11, 0, 8 },
+ { 504, 2, 11, 0, 8 },
+ { 512, 2, 11, 0, 8 },
+ { 520, 2, 11, 0, 8 },
+ { 528, 2, 11, 0, 8 },
+ { 536, 2, 11, 0, 8 },
+ { 544, 2, 11, 0, 8 },
+ { 552, 2, 11, 0, 8 },
+ { 560, 2, 11, 0, 8 },
+ { 568, 2, 11, 0, 8 },
+ { 576, 2, 11, 0, 8 },
+ { 584, 2, 11, 0, 8 },
+ { 592, 2, 13, 0, 8 },
+ { 600, 2, 11, 0, 8 },
+ { 608, 2, 11, 0, 8 },
+ { 616, 2, 11, 0, 8 },
+ { 624, 2, 11, 0, 8 },
+ { 632, 2, 11, 0, 8 },
+ { 640, 2, 11, 0, 8 },
+ { 648, 2, 13, 0, 8 },
+ { 656, 2, 11, 0, 8 },
+ { 664, 2, 11, 0, 8 },
+ { 672, 2, 11, 0, 8 },
+ { 680, 2, 11, 0, 8 },
+ { 688, 2, 11, 0, 8 },
+ { 696, 2, 11, 0, 8 },
+ { 704, 2, 11, 0, 8 },
+ { 712, 2, 11, 0, 8 },
+ { 720, 2, 11, 0, 8 },
+ { 728, 1, 13, 0, 8 },
+ { 736, 1, 13, 0, 8 },
+ { 744, 1, 13, 0, 8 },
+ { 752, 2, 8, 0, 8 },
+ { 760, 11, 12, 0, 8 },
+ { 768, 2, 7, 0, 8 },
+ { 776, 4, 11, 0, 8 },
+ { 784, 1, 11, 0, 8 },
+ { 792, 4, 11, 0, 8 },
+ { 800, 1, 11, 0, 8 },
+ { 808, 4, 11, 0, 8 },
+ { 816, 1, 11, 0, 8 },
+ { 824, 4, 14, 0, 8 },
+ { 832, 1, 11, 0, 8 },
+ { 840, 1, 11, 0, 8 },
+ { 848, 1, 14, 0, 8 },
+ { 856, 1, 11, 0, 8 },
+ { 864, 1, 11, 0, 8 },
+ { 872, 4, 11, 0, 8 },
+ { 880, 4, 11, 0, 8 },
+ { 888, 4, 11, 0, 8 },
+ { 896, 4, 14, 0, 8 },
+ { 904, 4, 14, 0, 8 },
+ { 912, 4, 11, 0, 8 },
+ { 920, 4, 11, 0, 8 },
+ { 928, 2, 11, 0, 8 },
+ { 936, 4, 11, 0, 8 },
+ { 944, 4, 11, 0, 8 },
+ { 952, 4, 11, 0, 8 },
+ { 960, 4, 11, 0, 8 },
+ { 968, 4, 14, 0, 8 },
+ { 976, 4, 11, 0, 8 },
+ { 984, 1, 12, 0, 8 },
+ { 992, 1, 12, 0, 8 },
+ { 1000, 1, 12, 0, 8 },
+ { 1008, 5, 8, 0, 8 },
+ { 1016, 0, 14, 0, 8 },
+ { 1024, 0, 14, 0, 8 },
+ { 0, 0, 0, 0, 0 }
+};
+
+GSubfont defont0 = {
+ 129,
+ 14,
+ 2,
+ info0,
+ &strike0,
+};
--- /dev/null
+++ b/os/boot.original/rpcg/devether.c
@@ -1,0 +1,157 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+static Ctlr ether[MaxEther];
+
+static struct {
+ char *type;
+ int (*reset)(Ctlr*);
+} cards[] = {
+ { "SCC", sccethreset, },
+ { "SCC2", sccethreset, },
+ { 0, }
+};
+
+int
+etherinit(void)
+{
+ Ctlr *ctlr;
+ int ctlrno, i, mask, n;
+
+ mask = 0;
+ for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+ ctlr = ðer[ctlrno];
+ memset(ctlr, 0, sizeof(Ctlr));
+ if(archether(ctlrno, &ctlr->card) <= 0)
+ continue;
+ for(n = 0; cards[n].type; n++){
+ if(strcmp(cards[n].type, ctlr->card.type))
+ continue;
+ ctlr->ctlrno = ctlrno;
+ if((*cards[n].reset)(ctlr))
+ break;
+
+ ctlr->iq = qopen(16*1024, 1, 0, 0);
+ ctlr->oq = qopen(16*1024, 1, 0, 0);
+
+ ctlr->present = 1;
+ mask |= 1<<ctlrno;
+
+ print("ether%d: %s: port 0x%luX irq %d",
+ ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq);
+ if(ctlr->card.mem)
+ print(" addr 0x%luX", PADDR(ctlr->card.mem));
+ if(ctlr->card.size)
+ print(" size 0x%luX", ctlr->card.size);
+ print(":");
+ for(i = 0; i < sizeof(ctlr->card.ea); i++)
+ print(" %2.2uX", ctlr->card.ea[i]);
+ print("\n"); uartwait();
+ setvec(VectorPIC + ctlr->card.irq, ctlr->card.intr, ctlr);
+ break;
+ }
+ }
+
+ return mask;
+}
+
+static Ctlr*
+attach(int ctlrno)
+{
+ Ctlr *ctlr;
+
+ if(ctlrno >= MaxEther || ether[ctlrno].present == 0)
+ return 0;
+
+ ctlr = ðer[ctlrno];
+ if(ctlr->present == 1){
+ ctlr->present = 2;
+ (*ctlr->card.attach)(ctlr);
+ }
+
+ return ctlr;
+}
+
+uchar*
+etheraddr(int ctlrno)
+{
+ Ctlr *ctlr;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ return ctlr->card.ea;
+}
+
+int
+etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
+{
+ int n;
+ Ctlr *ctlr;
+ Block *b;
+ ulong start;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ start = m->ticks;
+ while((b = qget(ctlr->iq)) == 0){
+ if(TK2MS(m->ticks - start) >= timo){
+ /*
+ print("ether%d: rx timeout\n", ctlrno);
+ */
+ return 0;
+ }
+ }
+
+ n = BLEN(b);
+ memmove(pkt, b->rp, n);
+ freeb(b);
+
+ return n;
+}
+
+int
+etheriq(Ctlr *ctlr, Block *b, int freebp)
+{
+ if(memcmp(((Etherpkt*)b->rp)->d, ctlr->card.ea, Eaddrlen) != 0 &&
+ memcmp(((Etherpkt*)b->rp)->d, broadcast, Eaddrlen) != 0){
+ if(freebp)
+ freeb(b);
+ return 0;
+ }
+ qbwrite(ctlr->iq, b);
+ return 1;
+}
+
+int
+ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int)
+{
+ Ctlr *ctlr;
+ Block *b;
+ int s;
+
+ if((ctlr = attach(ctlrno)) == 0)
+ return 0;
+
+ if(qlen(ctlr->oq) > 16*1024){
+ print("ether%d: tx queue full\n", ctlrno);
+ return 0;
+ }
+ b = iallocb(sizeof(Etherpkt));
+ memmove(b->wp, pkt, len);
+ memmove(((Etherpkt*)b->wp)->s, ctlr->card.ea, Eaddrlen);
+ b->wp += len;
+ qbwrite(ctlr->oq, b);
+ s = splhi();
+ (*ctlr->card.transmit)(ctlr);
+ splx(s);
+
+ return 1;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/devuart.c
@@ -1,0 +1,230 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+/*
+ * SMC1 in UART mode
+ */
+
+typedef struct Uartsmc Uartsmc;
+struct Uartsmc {
+ IOCparam;
+ ushort maxidl;
+ ushort idlc;
+ ushort brkln;
+ ushort brkec;
+ ushort brkcr;
+ ushort rmask;
+};
+
+typedef struct Uart Uart;
+struct Uart
+{
+ int port;
+ int setup;
+ uchar txbusy;
+
+ Queue* iq;
+ Queue* oq;
+ void (*rx)(Queue*, int);
+ void (*boot)(uchar*, int);
+
+ ulong frame;
+ ulong overrun;
+ uchar rxbuf[128];
+ char txbuf[16];
+ BD* rxb;
+ BD* txb;
+};
+
+Uart uart[1];
+int predawn = 1;
+
+static void uartintr(Ureg*, void*);
+static void uartkick(void*);
+
+static int
+baudgen(int baud)
+{
+ int d;
+
+ d = ((m->cpuhz/baud)+8)>>4;
+ if(d >= (1<<12))
+ return ((d+15)>>3)|1;
+ return d<<1;
+}
+
+static void
+smcsetup(Uart *up, int baud)
+{
+ IMM *io;
+ Uartsmc *p;
+ BD *bd;
+ SMC *smc;
+
+ archenableuart(SMC1ID, 0);
+ io = m->iomem;
+ io->pbpar |= IBIT(24)|IBIT(25); /* enable SMC1 TX/RX */
+ io->pbdir &= ~(IBIT(24)|IBIT(25));
+ io->brgc1 = baudgen(baud) | BaudEnable;
+ io->simode &= ~0xF000; /* SMC1 to NMSI mode, Tx/Rx clocks are BRG1 */
+
+ bd = bdalloc(1);
+ p = (Uartsmc*)KADDR(SMC1P);
+ p->rbase = (ushort)bd;
+ up->rxb = bd;
+ bd->status = BDEmpty|BDWrap|BDInt;
+ bd->length = 0;
+ bd->addr = PADDR(up->rxbuf);
+ bd = bdalloc(1);
+ p->tbase = (ushort)bd;
+ up->txb = bd;
+ bd->status = BDWrap|BDInt;
+ bd->length = 0;
+ bd->addr = PADDR(up->txbuf);
+
+ cpmop(InitRxTx, SMC1ID, 0);
+
+ /* protocol parameters */
+ p->rfcr = 0x18;
+ p->tfcr = 0x18;
+ p->mrblr = 1;
+ p->maxidl = 1;
+ p->brkln = 0;
+ p->brkec = 0;
+ p->brkcr = 1;
+ smc = IOREGS(0xA80, SMC);
+ smc->smce = 0xff; /* clear events */
+ smc->smcm = 0x17; /* enable all possible interrupts */
+ setvec(VectorCPIC+4, uartintr, up);
+ smc->smcmr = 0x4820; /* 8-bit mode, no parity, 1 stop bit, UART mode, ... */
+ smc->smcmr |= 3; /* enable rx/tx */
+}
+
+static void
+uartintr(Ureg*, void *arg)
+{
+ Uart *up;
+ int ch, i;
+ BD *bd;
+ SMC *smc;
+ Block *b;
+
+ up = arg;
+ smc = IOREGS(0xA80, SMC);
+ smc->smce = 0xff; /* clear all events */
+ if((bd = up->rxb) != nil && (bd->status & BDEmpty) == 0){
+ if(up->iq != nil && bd->length > 0){
+ if(up->boot != nil){
+ up->boot(up->rxbuf, bd->length);
+ }else if(up->rx != nil){
+ for(i=0; i<bd->length; i++){
+ ch = up->rxbuf[i];
+ up->rx(up->iq, ch);
+ }
+ }else{
+ b = iallocb(bd->length);
+ memmove(b->wp, up->rxbuf, bd->length);
+ b->wp += bd->length;
+ qbwrite(up->iq, b);
+ }
+ }
+ bd->status |= BDEmpty|BDInt;
+ } else if((bd = up->txb) != nil && (bd->status & BDReady) == 0){
+ ch = -1;
+ if(up->oq)
+ ch = qbgetc(up->oq);
+ if(ch != -1){
+ up->txbuf[0] = ch;
+ bd->length = 1;
+ bd->status |= BDReady;
+ }else
+ up->txbusy = 0;
+ }
+ /* TO DO: modem status, errors, etc */
+}
+
+static void
+uartkick(void *arg)
+{
+ Uart *up = arg;
+ int s, c, i;
+
+ s = splhi();
+ while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1){
+ if(predawn){
+ while(up->txb->status & BDReady)
+ ;
+ } else {
+ for(i = 0; i < 100; i++){
+ if((up->txb->status & BDReady) == 0)
+ break;
+ delay(1);
+ }
+ }
+ up->txbuf[0] = c;
+ up->txb->length = 1;
+ up->txb->status |= BDReady;
+ up->txbusy = !predawn;
+ }
+ splx(s);
+}
+
+void
+uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue*,int))
+{
+ Uart *up = &uart[0];
+
+ if(up->setup)
+ return;
+ up->setup = 1;
+
+ *iq = up->iq = qopen(4*1024, 0, 0, 0);
+ *oq = up->oq = qopen(16*1024, 0, uartkick, up);
+ up->rx = rx;
+ USED(port);
+ up->port = SMC1ID;
+ if(baud == 0)
+ baud = 9600;
+ smcsetup(up, baud);
+ /* if using SCCn's UART, would also set DTR and RTS, but SMC doesn't use them */
+}
+
+void
+uartsetboot(void (*f)(uchar*, int))
+{
+ uart[0].boot = f;
+}
+
+void
+uartputs(char *s, int n)
+{
+ Uart *up = &uart[0];
+ Block *b;
+ int nl;
+ char *p;
+
+ nl = 0;
+ for(p = s; p < s+n; p++)
+ if(*p == '\n')
+ nl++;
+ b = iallocb(n+nl);
+ while(n--){
+ if(*s == '\n')
+ *b->wp++ = '\r';
+ *b->wp++ = *s++;
+ }
+ qbwrite(up->oq, b);
+}
+
+void
+uartwait(void)
+{
+ Uart *up = &uart[0];
+
+ while(up->txbusy)
+ ;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/dload.c
@@ -1,0 +1,103 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+static char *kernelfile = "/power/ipaq";
+ulong crc32(void *buf, int n, ulong crc);
+
+void
+main(int argc, char **argv)
+{
+ int ifd, n;
+ char buf[64], reply[1];
+ int i, execsize;
+ Fhdr f;
+ ulong csum;
+
+ ARGBEGIN{
+ }ARGEND
+ ifd = open(kernelfile, OREAD);
+ if(ifd < 0){
+ fprint(2, "dload: can't open %s: %r\n", kernelfile);
+ exits("open");
+ }
+ i = 0;
+ if(crackhdr(ifd, &f) == 0){
+ fprint(2, "dload: not an executable file: %r\n");
+ exits("format");
+ }
+ if(f.magic != Q_MAGIC){
+ fprint(2, "dload: not a powerpc executable\n");
+ exits("format");
+ }
+ execsize = f.txtsz + f.datsz + f.txtoff;
+ seek(ifd, 0, 0);
+ csum = ~0;
+ while(execsize > 0 && (n = read(ifd, buf, sizeof(buf))) > 0){
+ if(n > execsize)
+ n = execsize;
+ for(;;){
+ if(write(1, buf, sizeof(buf)) != sizeof(buf)){ /* always writes full buffer */
+ fprint(2, "dload: write error: %r\n");
+ exits("write");
+ }
+ if(read(0, reply, 1) != 1){
+ fprint(2, "dload: bad reply\n");
+ exits("read");
+ }
+ if(reply[0] != 'n')
+ break;
+ fprint(2, "!");
+ }
+ if(reply[0] != 'y'){
+ fprint(2, "dload: bad ack: %c\n", reply[0]);
+ exits("reply");
+ }
+ if(++i%10 == 0)
+ fprint(2, ".");
+ execsize -= n;
+ }
+ exits(0);
+}
+
+/*
+ * from Rob Warnock
+ */
+static ulong crc32tab[256]; /* initialised on first call to crc32 */
+
+enum {
+ CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+ int i, j;
+ ulong c;
+
+ for(i = 0; i < 256; i++) {
+ for(c = i << 24, j = 8; j > 0; j--)
+ if(c & (1<<31))
+ c = (c<<1) ^ CRC32POLY;
+ else
+ c <<= 1;
+ crc32tab[i] = c;
+ }
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+ uchar *p;
+
+ if(crc32tab[1] == 0)
+ initcrc32();
+ crc = ~crc;
+ for(p = buf; --n >= 0;)
+ crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+ return ~crc;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/donprint.c
@@ -1,0 +1,332 @@
+#include "u.h"
+#include "lib.h"
+
+#define PTR sizeof(char*)
+#define SHORT sizeof(int)
+#define INT sizeof(int)
+#define LONG sizeof(long)
+#define IDIGIT 30
+#define MAXCON 30
+
+#define FLONG (1<<0)
+#define FSHORT (1<<1)
+#define FUNSIGN (1<<2)
+
+typedef struct Op Op;
+struct Op
+{
+ char *p;
+ char *ep;
+ void *argp;
+ int f1;
+ int f2;
+ int f3;
+};
+
+static int noconv(Op*);
+static int cconv(Op*);
+static int dconv(Op*);
+static int hconv(Op*);
+static int lconv(Op*);
+static int oconv(Op*);
+static int sconv(Op*);
+static int uconv(Op*);
+static int xconv(Op*);
+static int Xconv(Op*);
+static int percent(Op*);
+
+static
+int (*fmtconv[MAXCON])(Op*) =
+{
+ noconv,
+ cconv, dconv, hconv, lconv,
+ oconv, sconv, uconv, xconv,
+ Xconv, percent,
+};
+static
+char fmtindex[128] =
+{
+ ['c'] 1,
+ ['d'] 2,
+ ['h'] 3,
+ ['l'] 4,
+ ['o'] 5,
+ ['s'] 6,
+ ['u'] 7,
+ ['x'] 8,
+ ['X'] 9,
+ ['%'] 10,
+};
+
+static int convcount = { 11 };
+static int ucase;
+
+static void
+PUT(Op *o, int c)
+{
+ static int pos;
+ int opos;
+
+ if(c == '\t'){
+ opos = pos;
+ pos = (opos+8) & ~7;
+ while(opos++ < pos && o->p < o->ep)
+ *o->p++ = ' ';
+ return;
+ }
+ if(o->p < o->ep){
+ *o->p++ = c;
+ pos++;
+ }
+ if(c == '\n')
+ pos = 0;
+}
+
+int
+fmtinstall(char c, int (*f)(Op*))
+{
+
+ c &= 0177;
+ if(fmtindex[c] == 0) {
+ if(convcount >= MAXCON)
+ return 1;
+ fmtindex[c] = convcount++;
+ }
+ fmtconv[fmtindex[c]] = f;
+ return 0;
+}
+
+char*
+donprint(char *p, char *ep, char *fmt, void *argp)
+{
+ int sf1, c;
+ Op o;
+
+ o.p = p;
+ o.ep = ep;
+ o.argp = argp;
+
+loop:
+ c = *fmt++;
+ if(c != '%') {
+ if(c == 0) {
+ if(o.p < o.ep)
+ *o.p = 0;
+ return o.p;
+ }
+ PUT(&o, c);
+ goto loop;
+ }
+ o.f1 = 0;
+ o.f2 = -1;
+ o.f3 = 0;
+ c = *fmt++;
+ sf1 = 0;
+ if(c == '-') {
+ sf1 = 1;
+ c = *fmt++;
+ }
+ while(c >= '0' && c <= '9') {
+ o.f1 = o.f1*10 + c-'0';
+ c = *fmt++;
+ }
+ if(sf1)
+ o.f1 = -o.f1;
+ if(c != '.')
+ goto l1;
+ c = *fmt++;
+ while(c >= '0' && c <= '9') {
+ if(o.f2 < 0)
+ o.f2 = 0;
+ o.f2 = o.f2*10 + c-'0';
+ c = *fmt++;
+ }
+l1:
+ if(c == 0)
+ fmt--;
+ c = (*fmtconv[fmtindex[c&0177]])(&o);
+ if(c < 0) {
+ o.f3 |= -c;
+ c = *fmt++;
+ goto l1;
+ }
+ o.argp = (char*)o.argp + c;
+ goto loop;
+}
+
+void
+strconv(char *o, Op *op, int f1, int f2)
+{
+ int n, c;
+ char *p;
+
+ n = strlen(o);
+ if(f1 >= 0)
+ while(n < f1) {
+ PUT(op, ' ');
+ n++;
+ }
+ for(p=o; c = *p++;)
+ if(f2 != 0) {
+ PUT(op, c);
+ f2--;
+ }
+ if(f1 < 0) {
+ f1 = -f1;
+ while(n < f1) {
+ PUT(op, ' ');
+ n++;
+ }
+ }
+}
+
+int
+numbconv(Op *op, int base)
+{
+ char b[IDIGIT];
+ int i, f, n, r;
+ long v;
+ short h;
+
+ f = 0;
+ switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
+ case FLONG:
+ v = *(long*)op->argp;
+ r = LONG;
+ break;
+
+ case FUNSIGN|FLONG:
+ v = *(ulong*)op->argp;
+ r = LONG;
+ break;
+
+ case FSHORT:
+ h = *(int*)op->argp;
+ v = h;
+ r = SHORT;
+ break;
+
+ case FUNSIGN|FSHORT:
+ h = *(int*)op->argp;
+ v = (ushort)h;
+ r = SHORT;
+ break;
+
+ default:
+ v = *(int*)op->argp;
+ r = INT;
+ break;
+
+ case FUNSIGN:
+ v = *(unsigned*)op->argp;
+ r = INT;
+ break;
+ }
+ if(!(op->f3 & FUNSIGN) && v < 0) {
+ v = -v;
+ f = 1;
+ }
+ b[IDIGIT-1] = 0;
+ for(i = IDIGIT-2;; i--) {
+ n = (ulong)v % base;
+ n += '0';
+ if(n > '9'){
+ n += 'a' - ('9'+1);
+ if(ucase)
+ n += 'A'-'a';
+ }
+ b[i] = n;
+ if(i < 2)
+ break;
+ v = (ulong)v / base;
+ if(op->f2 >= 0 && i >= IDIGIT-op->f2)
+ continue;
+ if(v <= 0)
+ break;
+ }
+ if(f)
+ b[--i] = '-';
+ strconv(b+i, op, op->f1, -1);
+ return r;
+}
+
+static int
+noconv(Op *op)
+{
+
+ strconv("***", op, 0, -1);
+ return 0;
+}
+
+static int
+cconv(Op *op)
+{
+ char b[2];
+
+ b[0] = *(int*)op->argp;
+ b[1] = 0;
+ strconv(b, op, op->f1, -1);
+ return INT;
+}
+
+static int
+dconv(Op *op)
+{
+ return numbconv(op, 10);
+}
+
+static int
+hconv(Op*)
+{
+ return -FSHORT;
+}
+
+static int
+lconv(Op*)
+{
+ return -FLONG;
+}
+
+static int
+oconv(Op *op)
+{
+ return numbconv(op, 8);
+}
+
+static int
+sconv(Op *op)
+{
+ strconv(*(char**)op->argp, op, op->f1, op->f2);
+ return PTR;
+}
+
+static int
+uconv(Op*)
+{
+ return -FUNSIGN;
+}
+
+static int
+xconv(Op *op)
+{
+ return numbconv(op, 16);
+}
+
+static int
+Xconv(Op *op)
+{
+ int r;
+
+ ucase = 1;
+ r = numbconv(op, 16);
+ ucase = 0;
+ return r;
+}
+
+static int
+percent(Op *op)
+{
+
+ PUT(op, '%');
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/dosboot.c
@@ -1,0 +1,614 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "dosfs.h"
+
+extern char *premature;
+
+/*
+ * predeclared
+ */
+static void bootdump(Dosboot*);
+static void setname(Dosfile*, char*);
+long dosreadseg(Dosfile*, long, long);
+
+/*
+ * debugging
+ */
+#define chatty 1
+#define chat if(chatty)print
+
+/*
+ * block io buffers
+ */
+enum
+{
+ Nbio= 16,
+};
+typedef struct Clustbuf Clustbuf;
+struct Clustbuf
+{
+ int age;
+ long sector;
+ uchar *iobuf;
+ Dos *dos;
+ int size;
+};
+Clustbuf bio[Nbio];
+
+/*
+ * get an io block from an io buffer
+ */
+Clustbuf*
+getclust(Dos *dos, long sector)
+{
+ Clustbuf *p, *oldest;
+ int size;
+
+ chat("getclust @ %d\n", sector);
+
+ /*
+ * if we have it, just return it
+ */
+ for(p = bio; p < &bio[Nbio]; p++){
+ if(sector == p->sector && dos == p->dos){
+ p->age = m->ticks;
+ chat("getclust %d in cache\n", sector);
+ return p;
+ }
+ }
+
+ /*
+ * otherwise, reuse the oldest entry
+ */
+ oldest = bio;
+ for(p = &bio[1]; p < &bio[Nbio]; p++){
+ if(p->age <= oldest->age)
+ oldest = p;
+ }
+ p = oldest;
+
+ /*
+ * make sure the buffer is big enough
+ */
+ size = dos->clustsize*dos->sectsize;
+ if(p->iobuf==0 || p->size < size)
+ p->iobuf = ialloc(size, 0);
+ p->size = size;
+
+ /*
+ * read in the cluster
+ */
+ chat("getclust addr %d\n", (sector+dos->start)*dos->sectsize);
+ if((*dos->seek)(dos->dev, (sector+dos->start)*dos->sectsize) < 0){
+ chat("can't seek block\n");
+ return 0;
+ }
+ if((*dos->read)(dos->dev, p->iobuf, size) != size){
+ chat("can't read block\n");
+ return 0;
+ }
+
+ p->age = m->ticks;
+ p->dos = dos;
+ p->sector = sector;
+ chat("getclust %d read\n", sector);
+ return p;
+}
+
+/*
+ * walk the fat one level ( n is a current cluster number ).
+ * return the new cluster number or -1 if no more.
+ */
+static long
+fatwalk(Dos *dos, int n)
+{
+ ulong k, sect;
+ Clustbuf *p;
+ int o;
+
+ chat("fatwalk %d\n", n);
+
+ if(n < 2 || n >= dos->fatclusters)
+ return -1;
+
+ switch(dos->fatbits){
+ case 12:
+ k = (3*n)/2; break;
+ case 16:
+ k = 2*n; break;
+ default:
+ return -1;
+ }
+ if(k >= dos->fatsize*dos->sectsize)
+ panic("getfat");
+
+ sect = (k/(dos->sectsize*dos->clustsize))*dos->clustsize + dos->fataddr;
+ o = k%(dos->sectsize*dos->clustsize);
+ p = getclust(dos, sect);
+ k = p->iobuf[o++];
+ if(o >= dos->sectsize*dos->clustsize){
+ p = getclust(dos, sect+dos->clustsize);
+ o = 0;
+ }
+ k |= p->iobuf[o]<<8;
+ if(dos->fatbits == 12){
+ if(n&1)
+ k >>= 4;
+ else
+ k &= 0xfff;
+ if(k >= 0xff8)
+ k |= 0xf000;
+ }
+ k = k < 0xfff8 ? k : -1;
+ chat("fatwalk %d -> %d\n", n, k);
+ return k;
+}
+
+/*
+ * map a file's logical cluster address to a physical sector address
+ */
+static long
+fileaddr(Dosfile *fp, long ltarget)
+{
+ Dos *dos = fp->dos;
+ long l;
+ long p;
+
+ chat("fileaddr %8.8s %d\n", fp->name, ltarget);
+ /*
+ * root directory is contiguous and easy
+ */
+ if(fp->pstart == 0){
+ if(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof(Dosdir))
+ return -1;
+ l = dos->rootaddr + ltarget*dos->clustsize;
+ chat("fileaddr %d -> %d\n", ltarget, l);
+ return l;
+ }
+
+ /*
+ * anything else requires a walk through the fat
+ */
+ if(ltarget >= fp->lcurrent && fp->pcurrent){
+ /* start at the currrent point */
+ l = fp->lcurrent;
+ p = fp->pcurrent;
+ } else {
+ /* go back to the beginning */
+ l = 0;
+ p = fp->pstart;
+ }
+ while(l != ltarget){
+ /* walk the fat */
+ p = fatwalk(dos, p);
+ if(p < 0)
+ return -1;
+ l++;
+ }
+ fp->lcurrent = l;
+ fp->pcurrent = p;
+
+ /*
+ * clusters start at 2 instead of 0 (why? - presotto)
+ */
+ l = dos->dataaddr + (p-2)*dos->clustsize;
+ chat("fileaddr %d -> %d\n", ltarget, l);
+ return l;
+}
+
+/*
+ * read from a dos file
+ */
+long
+dosread(Dosfile *fp, void *a, long n)
+{
+ long addr;
+ long rv;
+ int i;
+ int off;
+ Clustbuf *p;
+ uchar *from, *to;
+
+ if((fp->attr & DDIR) == 0){
+ if(fp->offset >= fp->length)
+ return 0;
+ if(fp->offset+n > fp->length)
+ n = fp->length - fp->offset;
+ }
+
+ to = a;
+ for(rv = 0; rv < n; rv+=i){
+ /*
+ * read the cluster
+ */
+ addr = fileaddr(fp, fp->offset/fp->dos->clustbytes);
+ if(addr < 0)
+ return -1;
+ p = getclust(fp->dos, addr);
+ if(p == 0)
+ return -1;
+
+ /*
+ * copy the bytes we need
+ */
+ off = fp->offset % fp->dos->clustbytes;
+ from = &p->iobuf[off];
+ i = n - rv;
+ if(i > fp->dos->clustbytes - off)
+ i = fp->dos->clustbytes - off;
+ memmove(to, from, i);
+ to += i;
+ fp->offset += i;
+ }
+
+ return rv;
+}
+
+/*
+ * walk a directory returns
+ * -1 if something went wrong
+ * 0 if not found
+ * 1 if found
+ */
+int
+doswalk(Dosfile *file, char *name)
+{
+ Dosdir d;
+ long n;
+
+ if((file->attr & DDIR) == 0){
+ chat("walking non-directory!\n");
+ return -1;
+ }
+
+ setname(file, name);
+
+ file->offset = 0; /* start at the beginning */
+ while((n = dosread(file, &d, sizeof(d))) == sizeof(d)){
+ chat("comparing to %8.8s.%3.3s\n", d.name, d.ext);
+ if(memcmp(file->name, d.name, sizeof(d.name)) != 0)
+ continue;
+ if(memcmp(file->ext, d.ext, sizeof(d.ext)) != 0)
+ continue;
+ if(d.attr & DVLABEL){
+ chat("%8.8s.%3.3s is a LABEL\n", d.name, d.ext);
+ continue;
+ }
+ file->attr = d.attr;
+ file->pstart = GSHORT(d.start);
+ file->length = GLONG(d.length);
+ file->pcurrent = 0;
+ file->lcurrent = 0;
+ file->offset = 0;
+ return 1;
+ }
+ return n >= 0 ? 0 : -1;
+}
+
+
+/*
+ * instructions that boot blocks can start with
+ */
+#define JMPSHORT 0xeb
+#define JMPNEAR 0xe9
+
+/*
+ * read dos file system properties
+ */
+int
+dosinit(Dos *dos, int start, int ishard)
+{
+ Dosboot *b;
+ int i;
+ Clustbuf *p;
+ Dospart *dp;
+ ulong mbroffset, offset;
+
+ /* defaults till we know better */
+ dos->start = start;
+ dos->sectsize = 512;
+ dos->clustsize = 1;
+ mbroffset = 0;
+
+dmddo:
+ /* get first sector */
+ p = getclust(dos, mbroffset);
+ if(p == 0){
+ chat("can't read boot block\n");
+ return -1;
+ }
+
+ /*
+ * If it's a hard disc then look for an MBR and pick either an
+ * active partition or the FAT with the lowest starting LBA.
+ * Things are tricky because we could be pointing to, amongst others:
+ * 1) a floppy BPB;
+ * 2) a hard disc MBR;
+ * 3) a hard disc extended partition table;
+ * 4) a logical drive on a hard disc;
+ * 5) a disc-manager boot block.
+ * They all have the same magic at the end of the block.
+ */
+ if(p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA) {
+ chat("not DOS\n");
+ return -1;
+ }
+ p->dos = 0;
+ b = (Dosboot *)p->iobuf;
+ if(ishard && b->mediadesc != 0xF8){
+ dp = (Dospart*)&p->iobuf[0x1BE];
+ offset = 0xFFFFFFFF;
+ for(i = 0; i < 4; i++, dp++){
+ if(dp->type == DMDDO){
+ mbroffset = 63;
+ goto dmddo;
+ }
+ if(dp->type != FAT12 && dp->type != FAT16 && dp->type != FATHUGE)
+ continue;
+ if(dp->flag & 0x80){
+ offset = GLONG(dp->start);
+ break;
+ }
+ if(GLONG(dp->start) < offset)
+ offset = GLONG(dp->start);
+ }
+ if(i != 4 || offset != 0xFFFFFFFF){
+ dos->start = mbroffset+offset;
+ p = getclust(dos, 0);
+ if(p == 0 || p->iobuf[0x1FE] != 0x55 || p->iobuf[0x1FF] != 0xAA)
+ return -1;
+ }
+ p->dos = 0;
+ }
+
+ b = (Dosboot *)p->iobuf;
+ if(b->magic[0] != JMPNEAR && (b->magic[0] != JMPSHORT || b->magic[2] != 0x90)){
+ chat("no dos file system\n");
+ return -1;
+ }
+
+ if(chatty)
+ bootdump(b);
+
+ /*
+ * determine the systems' wondersous properties
+ */
+ dos->sectsize = GSHORT(b->sectsize);
+ dos->clustsize = b->clustsize;
+ dos->clustbytes = dos->sectsize*dos->clustsize;
+ dos->nresrv = GSHORT(b->nresrv);
+ dos->nfats = b->nfats;
+ dos->rootsize = GSHORT(b->rootsize);
+ dos->volsize = GSHORT(b->volsize);
+ if(dos->volsize == 0)
+ dos->volsize = GLONG(b->bigvolsize);
+ dos->mediadesc = b->mediadesc;
+ dos->fatsize = GSHORT(b->fatsize);
+ dos->fataddr = dos->nresrv;
+ dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;
+ i = dos->rootsize*sizeof(Dosdir) + dos->sectsize - 1;
+ i = i/dos->sectsize;
+ dos->dataaddr = dos->rootaddr + i;
+ dos->fatclusters = 2+(dos->volsize - dos->dataaddr)/dos->clustsize;
+ if(dos->fatclusters < 4087)
+ dos->fatbits = 12;
+ else
+ dos->fatbits = 16;
+ dos->freeptr = 2;
+
+ /*
+ * set up the root
+ */
+ dos->root.dos = dos;
+ dos->root.pstart = 0;
+ dos->root.pcurrent = dos->root.lcurrent = 0;
+ dos->root.offset = 0;
+ dos->root.attr = DDIR;
+ dos->root.length = dos->rootsize*sizeof(Dosdir);
+
+ return 0;
+}
+
+static void
+bootdump(Dosboot *b)
+{
+ if(chatty == 0)
+ return;
+ print("magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
+ b->magic[0], b->magic[1], b->magic[2]);
+ print("version: \"%8.8s\"\n", b->version);
+ print("sectsize: %d\n", GSHORT(b->sectsize));
+ print("allocsize: %d\n", b->clustsize);
+ print("nresrv: %d\n", GSHORT(b->nresrv));
+ print("nfats: %d\n", b->nfats);
+ print("rootsize: %d\n", GSHORT(b->rootsize));
+ print("volsize: %d\n", GSHORT(b->volsize));
+ print("mediadesc: 0x%2.2x\n", b->mediadesc);
+ print("fatsize: %d\n", GSHORT(b->fatsize));
+ print("trksize: %d\n", GSHORT(b->trksize));
+ print("nheads: %d\n", GSHORT(b->nheads));
+ print("nhidden: %d\n", GLONG(b->nhidden));
+ print("bigvolsize: %d\n", GLONG(b->bigvolsize));
+ print("driveno: %d\n", b->driveno);
+ print("reserved0: 0x%2.2x\n", b->reserved0);
+ print("bootsig: 0x%2.2x\n", b->bootsig);
+ print("volid: 0x%8.8x\n", GLONG(b->volid));
+ print("label: \"%11.11s\"\n", b->label);
+}
+
+/*
+ * grab next element from a path, return the pointer to unprocessed portion of
+ * path.
+ */
+static char *
+nextelem(char *path, char *elem)
+{
+ int i;
+
+ while(*path == '/')
+ path++;
+ if(*path==0 || *path==' ')
+ return 0;
+ for(i=0; *path!='\0' && *path!='/' && *path!=' '; i++){
+ if(i==28){
+ print("name component too long\n");
+ return 0;
+ }
+ *elem++ = *path++;
+ }
+ *elem = '\0';
+ return path;
+}
+
+int
+dosstat(Dos *dos, char *path, Dosfile *f)
+{
+ char element[NAMELEN];
+
+ *f = dos->root;
+ while(path = nextelem(path, element)){
+ switch(doswalk(f, element)){
+ case -1:
+ return -1;
+ case 0:
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * boot
+ */
+int
+dosboot(Dos *dos, char *path)
+{
+ Dosfile file;
+ long n;
+ long addr;
+ Exec *ep;
+ void (*b)(void);
+
+ switch(dosstat(dos, path, &file)){
+
+ case -1:
+ print("error walking to %s\n", path);
+ return -1;
+ case 0:
+ print("%s not found\n", path);
+ return -1;
+ case 1:
+ print("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\n", file.name,
+ file.ext, file.attr, file.pstart, file.length);
+ break;
+ }
+
+ /*
+ * read header
+ */
+ ep = (Exec*)ialloc(sizeof(Exec), 0);
+ n = sizeof(Exec);
+ if(dosreadseg(&file, n, (ulong) ep) != n){
+ print(premature);
+ return -1;
+ }
+ if(GLLONG(ep->magic) != Q_MAGIC){
+ print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+ return -1;
+ }
+
+ /*
+ * read text
+ */
+ addr = PADDR(GLLONG(ep->entry));
+ n = GLLONG(ep->text);
+ print("+%d", n);
+ if(dosreadseg(&file, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * read data (starts at first page after kernel)
+ */
+ addr = PGROUND(addr+n);
+ n = GLLONG(ep->data);
+ print("+%d", n);
+ if(dosreadseg(&file, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * bss and entry point
+ */
+ print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
+
+ /*
+ * Go to new code. It's up to the program to get its PC relocated to
+ * the right place.
+ */
+ b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+ (*b)();
+ return 0;
+}
+
+/*
+ * read in a segment
+ */
+long
+dosreadseg(Dosfile *fp, long len, long addr)
+{
+ char *a;
+ long n, sofar;
+
+ a = (char *)addr;
+ for(sofar = 0; sofar < len; sofar += n){
+ n = 8*1024;
+ if(len - sofar < n)
+ n = len - sofar;
+ n = dosread(fp, a + sofar, n);
+ if(n <= 0)
+ break;
+ print(".");
+ }
+ return sofar;
+}
+
+/*
+ * set up a dos file name
+ */
+static void
+setname(Dosfile *fp, char *from)
+{
+ char *to;
+
+ to = fp->name;
+ for(; *from && to-fp->name < 8; from++, to++){
+ if(*from == '.'){
+ from++;
+ break;
+ }
+ if(*from >= 'a' && *from <= 'z')
+ *to = *from + 'A' - 'a';
+ else
+ *to = *from;
+ }
+ while(to - fp->name < 8)
+ *to++ = ' ';
+
+ to = fp->ext;
+ for(; *from && to-fp->ext < 3; from++, to++){
+ if(*from >= 'a' && *from <= 'z')
+ *to = *from + 'A' - 'a';
+ else
+ *to = *from;
+ }
+ while(to-fp->ext < 3)
+ *to++ = ' ';
+
+ chat("name is %8.8s %3.3s\n", fp->name, fp->ext);
+}
--- /dev/null
+++ b/os/boot.original/rpcg/dosfs.h
@@ -1,0 +1,110 @@
+typedef struct Dosboot Dosboot;
+typedef struct Dos Dos;
+typedef struct Dosdir Dosdir;
+typedef struct Dosfile Dosfile;
+typedef struct Dospart Dospart;
+
+struct Dospart
+{
+ uchar flag; /* active flag */
+ uchar shead; /* starting head */
+ uchar scs[2]; /* starting cylinder/sector */
+ uchar type; /* partition type */
+ uchar ehead; /* ending head */
+ uchar ecs[2]; /* ending cylinder/sector */
+ uchar start[4]; /* starting sector */
+ uchar len[4]; /* length in sectors */
+};
+
+#define FAT12 0x01
+#define FAT16 0x04
+#define FATHUGE 0x06
+#define DMDDO 0x54
+
+struct Dosboot{
+ uchar magic[3];
+ uchar version[8];
+ uchar sectsize[2];
+ uchar clustsize;
+ uchar nresrv[2];
+ uchar nfats;
+ uchar rootsize[2];
+ uchar volsize[2];
+ uchar mediadesc;
+ uchar fatsize[2];
+ uchar trksize[2];
+ uchar nheads[2];
+ uchar nhidden[4];
+ uchar bigvolsize[4];
+ uchar driveno;
+ uchar reserved0;
+ uchar bootsig;
+ uchar volid[4];
+ uchar label[11];
+ uchar reserved1[8];
+};
+
+struct Dosfile{
+ Dos *dos; /* owning dos file system */
+ char name[8];
+ char ext[3];
+ uchar attr;
+ long length;
+ long pstart; /* physical start cluster address */
+ long pcurrent; /* physical current cluster address */
+ long lcurrent; /* logical current cluster address */
+ long offset;
+};
+
+struct Dos{
+ int dev; /* device id */
+ long (*read)(int, void*, long); /* read routine */
+ long (*seek)(int, long); /* seek routine */
+
+ int start; /* start of file system */
+ int sectsize; /* in bytes */
+ int clustsize; /* in sectors */
+ int clustbytes; /* in bytes */
+ int nresrv; /* sectors */
+ int nfats; /* usually 2 */
+ int rootsize; /* number of entries */
+ int volsize; /* in sectors */
+ int mediadesc;
+ int fatsize; /* in sectors */
+ int fatclusters;
+ int fatbits; /* 12 or 16 */
+ long fataddr; /* sector number */
+ long rootaddr;
+ long dataaddr;
+ long freeptr;
+
+ Dosfile root;
+};
+
+struct Dosdir{
+ uchar name[8];
+ uchar ext[3];
+ uchar attr;
+ uchar reserved[10];
+ uchar time[2];
+ uchar date[2];
+ uchar start[2];
+ uchar length[4];
+};
+
+#define DRONLY 0x01
+#define DHIDDEN 0x02
+#define DSYSTEM 0x04
+#define DVLABEL 0x08
+#define DDIR 0x10
+#define DARCH 0x20
+
+extern int chatty;
+
+extern int dosboot(Dos*, char*);
+extern int dosinit(Dos*, int, int);
+extern long dosread(Dosfile*, void*, long);
+extern int dosstat(Dos*, char*, Dosfile*);
+extern int doswalk(Dosfile*, char*);
+
+extern int plan9ini(Dos*, char*);
--- /dev/null
+++ b/os/boot.original/rpcg/etherif.h
@@ -1,0 +1,59 @@
+/*
+ * All the goo for PC ethernet cards.
+ */
+typedef struct Card Card;
+typedef struct Type Type;
+typedef struct Ctlr Ctlr;
+
+/*
+ * Hardware interface.
+ */
+struct Card {
+ ISAConf;
+
+ int (*reset)(Ctlr*);
+ void (*attach)(Ctlr*);
+
+ void *(*read)(Ctlr*, void*, ulong, ulong);
+ void *(*write)(Ctlr*, ulong, void*, ulong);
+
+ void (*receive)(Ctlr*);
+ void (*transmit)(Ctlr*);
+ void (*intr)(Ureg*, void*);
+ void (*overflow)(Ctlr*);
+
+ uchar bit16; /* true if a 16 bit interface */
+ uchar ram; /* true if card has shared memory */
+
+ ulong dp8390; /* I/O address of 8390 (if any) */
+ ulong data; /* I/O data port if no shared memory */
+ uchar nxtpkt; /* software bndry */
+ uchar tstart; /* 8390 ring addresses */
+ uchar pstart;
+ uchar pstop;
+
+ uchar dummyrr; /* do dummy remote read */
+};
+
+/*
+ * Software controller.
+ */
+struct Ctlr {
+ Card card; /* hardware info */
+ int ctlrno;
+ int present;
+
+ Queue* iq;
+ Queue* oq;
+
+ int inpackets;
+ int outpackets;
+ int crcs; /* input crc errors */
+ int oerrs; /* output errors */
+ int frames; /* framing errors */
+ int overflows; /* packet overflows */
+ int buffs; /* buffering errors */
+};
+
+extern int sccethreset(Ctlr*);
+extern int etheriq(Ctlr*, Block*, int);
--- /dev/null
+++ b/os/boot.original/rpcg/etherscc.c
@@ -1,0 +1,411 @@
+/*
+ * SCCn ethernet
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "etherif.h"
+
+enum {
+ Nrdre = 32, /* receive descriptor ring entries */
+ Ntdre = 4, /* transmit descriptor ring entries */
+
+ Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
+ Bufsize = (Rbsize+7)&~7, /* aligned */
+};
+
+enum {
+ /* ether-specific Rx BD bits */
+ RxMiss= 1<<8,
+ RxeLG= 1<<5,
+ RxeNO= 1<<4,
+ RxeSH= 1<<3,
+ RxeCR= 1<<2,
+ RxeOV= 1<<1,
+ RxeCL= 1<<0,
+ RxError= (RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL), /* various error flags */
+
+ /* ether-specific Tx BD bits */
+ TxPad= 1<<14, /* pad short frames */
+ TxTC= 1<<10, /* transmit CRC */
+ TxeDEF= 1<<9,
+ TxeHB= 1<<8,
+ TxeLC= 1<<7,
+ TxeRL= 1<<6,
+ TxeUN= 1<<1,
+ TxeCSL= 1<<0,
+
+ /* scce */
+ RXB= 1<<0,
+ TXB= 1<<1,
+ BSY= 1<<2,
+ RXF= 1<<3,
+ TXE= 1<<4,
+
+ /* gsmrl */
+ ENR= 1<<5,
+ ENT= 1<<4,
+
+ /* port A */
+ RXD1= SIBIT(15),
+ TXD1= SIBIT(14),
+
+ /* port B */
+ RTS1= IBIT(19),
+
+ /* port C */
+ CTS1= SIBIT(11),
+ CD1= SIBIT(10),
+};
+
+typedef struct Etherparam Etherparam;
+struct Etherparam {
+ SCCparam;
+ ulong c_pres; /* preset CRC */
+ ulong c_mask; /* constant mask for CRC */
+ ulong crcec; /* CRC error counter */
+ ulong alec; /* alighnment error counter */
+ ulong disfc; /* discard frame counter */
+ ushort pads; /* short frame PAD characters */
+ ushort ret_lim; /* retry limit threshold */
+ ushort ret_cnt; /* retry limit counter */
+ ushort mflr; /* maximum frame length reg */
+ ushort minflr; /* minimum frame length reg */
+ ushort maxd1; /* maximum DMA1 length reg */
+ ushort maxd2; /* maximum DMA2 length reg */
+ ushort maxd; /* rx max DMA */
+ ushort dma_cnt; /* rx dma counter */
+ ushort max_b; /* max bd byte count */
+ ushort gaddr[4]; /* group address filter */
+ ulong tbuf0_data0; /* save area 0 - current frm */
+ ulong tbuf0_data1; /* save area 1 - current frm */
+ ulong tbuf0_rba0;
+ ulong tbuf0_crc;
+ ushort tbuf0_bcnt;
+ ushort paddr[3]; /* physical address LSB to MSB increasing */
+ ushort p_per; /* persistence */
+ ushort rfbd_ptr; /* rx first bd pointer */
+ ushort tfbd_ptr; /* tx first bd pointer */
+ ushort tlbd_ptr; /* tx last bd pointer */
+ ulong tbuf1_data0; /* save area 0 - next frame */
+ ulong tbuf1_data1; /* save area 1 - next frame */
+ ulong tbuf1_rba0;
+ ulong tbuf1_crc;
+ ushort tbuf1_bcnt;
+ ushort tx_len; /* tx frame length counter */
+ ushort iaddr[4]; /* individual address filter*/
+ ushort boff_cnt; /* back-off counter */
+ ushort taddr[3]; /* temp address */
+};
+
+typedef struct {
+ SCC* scc;
+ int port;
+ int cpm;
+
+ BD* rdr; /* receive descriptor ring */
+ void* rrb; /* receive ring buffers */
+ int rdrx; /* index into rdr */
+
+ BD* tdr; /* transmit descriptor ring */
+ void* trb; /* transmit ring buffers */
+ int tdrx; /* index into tdr */
+} Mot;
+static Mot mot[MaxEther];
+
+static int sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID};
+static int sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P};
+static int sccreg[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60};
+static int sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B};
+
+static void
+attach(Ctlr *ctlr)
+{
+ mot[ctlr->ctlrno].scc->gsmrl |= ENR|ENT;
+ eieio();
+}
+
+static void
+transmit(Ctlr *ctlr)
+{
+ int len;
+ Mot *motp;
+ Block *b;
+ BD *tdre;
+
+ motp = &mot[ctlr->ctlrno];
+ while(((tdre = &motp->tdr[motp->tdrx])->status & BDReady) == 0){
+ b = qget(ctlr->oq);
+ if(b == 0)
+ break;
+
+ /*
+ * Copy the packet to the transmit buffer.
+ */
+ len = BLEN(b);
+ memmove(KADDR(tdre->addr), b->rp, len);
+
+ /*
+ * Give ownership of the descriptor to the chip, increment the
+ * software ring descriptor pointer and tell the chip to poll.
+ */
+ tdre->length = len;
+ eieio();
+ tdre->status = (tdre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
+ eieio();
+ motp->scc->todr = 1<<15; /* transmit now */
+ eieio();
+ motp->tdrx = NEXT(motp->tdrx, Ntdre);
+
+ freeb(b);
+
+ }
+}
+
+static void
+interrupt(Ureg*, void *ap)
+{
+ int len, events, status;
+ Mot *motp;
+ BD *rdre;
+ Block *b;
+ Ctlr *ctlr;
+
+ ctlr = ap;
+ motp = &mot[ctlr->ctlrno];
+
+ /*
+ * Acknowledge all interrupts and whine about those that shouldn't
+ * happen.
+ */
+ events = motp->scc->scce;
+ eieio();
+ motp->scc->scce = events;
+ eieio();
+ if(events & (TXE|BSY|RXB))
+ print("ETHER.SCC#%d: scce = 0x%uX\n", ctlr->ctlrno, events);
+ //print(" %ux|", events);
+ /*
+ * Receiver interrupt: run round the descriptor ring logging
+ * errors and passing valid receive data up to the higher levels
+ * until we encounter a descriptor still owned by the chip.
+ */
+ if(events & (RXF|RXB) || 1){
+ rdre = &motp->rdr[motp->rdrx];
+ while(((status = rdre->status) & BDEmpty) == 0){
+ if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
+ //if(status & RxBuff)
+ // ctlr->buffs++;
+ if(status & (1<<2))
+ ctlr->crcs++;
+ if(status & (1<<1))
+ ctlr->overflows++;
+ //print("eth rx: %ux\n", status);
+ if(status & RxError)
+ print("~");
+ else if((status & BDLast) == 0)
+ print("@");
+ }
+ else{
+ /*
+ * We have a packet. Read it into the next
+ * free ring buffer, if any.
+ */
+ len = rdre->length-4;
+ if((b = iallocb(len)) != 0){
+ memmove(b->wp, KADDR(rdre->addr), len);
+ b->wp += len;
+ etheriq(ctlr, b, 1);
+ }
+ }
+
+ /*
+ * Finished with this descriptor, reinitialise it,
+ * give it back to the chip, then on to the next...
+ */
+ rdre->length = 0;
+ rdre->status = (rdre->status & BDWrap) | BDEmpty | BDInt;
+ eieio();
+
+ motp->rdrx = NEXT(motp->rdrx, Nrdre);
+ rdre = &motp->rdr[motp->rdrx];
+ }
+ }
+
+ /*
+ * Transmitter interrupt: handle anything queued for a free descriptor.
+ */
+ if(events & TXB)
+ transmit(ctlr);
+ if(events & TXE)
+ cpmop(RestartTx, motp->cpm, 0);
+}
+
+static void
+ringinit(Mot* motp)
+{
+ int i, x;
+
+ /*
+ * Initialise the receive and transmit buffer rings. The ring
+ * entries must be aligned on 16-byte boundaries.
+ */
+ if(motp->rdr == 0)
+ motp->rdr = bdalloc(Nrdre);
+ if(motp->rrb == 0)
+ motp->rrb = ialloc(Nrdre*Bufsize, 0);
+ x = PADDR(motp->rrb);
+ for(i = 0; i < Nrdre; i++){
+ motp->rdr[i].length = 0;
+ motp->rdr[i].addr = x;
+ motp->rdr[i].status = BDEmpty|BDInt;
+ x += Bufsize;
+ }
+ motp->rdr[i-1].status |= BDWrap;
+ motp->rdrx = 0;
+
+ if(motp->tdr == 0)
+ motp->tdr = bdalloc(Ntdre);
+ if(motp->trb == 0)
+ motp->trb = ialloc(Ntdre*Bufsize, 0);
+ x = PADDR(motp->trb);
+ for(i = 0; i < Ntdre; i++){
+ motp->tdr[i].addr = x;
+ motp->tdr[i].length = 0;
+ motp->tdr[i].status = TxPad|BDInt|BDLast|TxTC;
+ x += Bufsize;
+ }
+ motp->tdr[i-1].status |= BDWrap;
+ motp->tdrx = 0;
+}
+
+/*
+ * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence,
+ * except that it sets the right bits for the MPC823ADS board when SCC2 is used,
+ * and those for the 860/821 development board for SCC1.
+ */
+static void
+sccsetup(Mot *ctlr, SCC *scc, uchar *ea)
+{
+ int i, rcs, tcs, w;
+ Etherparam *p;
+ IMM *io;
+
+
+ i = 2*(ctlr->port-1);
+ io = ioplock();
+ w = (TXD1|RXD1)<<i; /* TXDn and RXDn in port A */
+ io->papar |= w; /* enable TXDn and RXDn pins */
+ io->padir &= ~w;
+ io->paodr &= ~w; /* not open drain */
+
+ w = (CD1|CTS1)<<i; /* CLSN and RENA: CDn and CTSn in port C */
+ io->pcpar &= ~w; /* enable CLSN (CTSn) and RENA (CDn) */
+ io->pcdir &= ~w;
+ io->pcso |= w;
+ iopunlock();
+
+ /* clocks and transceiver control: details depend on the board's wiring */
+ archetherenable(ctlr->cpm, &rcs, &tcs);
+
+ sccnmsi(ctlr->port, rcs, tcs); /* connect the clocks */
+
+ p = (Etherparam*)KADDR(sccparam[ctlr->port]);
+ memset(p, 0, sizeof(*p));
+ p->rfcr = 0x18;
+ p->tfcr = 0x18;
+ p->mrblr = Bufsize;
+ p->rbase = PADDR(ctlr->rdr);
+ p->tbase = PADDR(ctlr->tdr);
+
+ cpmop(InitRxTx, ctlr->cpm, 0);
+
+ p->c_pres = ~0;
+ p->c_mask = 0xDEBB20E3;
+ p->crcec = 0;
+ p->alec = 0;
+ p->disfc = 0;
+ p->pads = 0x8888;
+ p->ret_lim = 0xF;
+ p->mflr = Rbsize;
+ p->minflr = ETHERMINTU+4;
+ p->maxd1 = Bufsize;
+ p->maxd2 = Bufsize;
+ p->p_per = 0; /* only moderate aggression */
+
+ for(i=0; i<Eaddrlen; i+=2)
+ p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i]; /* it's not the obvious byte order */
+
+ scc->psmr = (2<<10)|(5<<1); /* 32-bit CRC, ignore 22 bits before SFD */
+ scc->dsr = 0xd555;
+ scc->gsmrh = 0; /* normal operation */
+ scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC; /* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */
+ eieio();
+ scc->scce = ~0; /* clear all events */
+ eieio();
+ scc->sccm = TXE | RXF | TXB; /* enable interrupts */
+ eieio();
+
+ io = ioplock();
+ w = RTS1<<(ctlr->port-1); /* enable TENA pin (RTSn) */
+ io->pbpar |= w;
+ io->pbdir |= w;
+ iopunlock();
+
+ /* gsmrl enable is deferred until attach */
+}
+
+/*
+ * Prepare the SCCx ethernet for booting.
+ */
+int
+sccethreset(Ctlr* ctlr)
+{
+ uchar ea[Eaddrlen];
+ Mot *motp;
+ SCC *scc;
+ char line[50], def[50];
+
+ /*
+ * Since there's no EPROM, insist that the configuration entry
+ * (see conf.c and flash.c) holds the Ethernet address.
+ */
+ memset(ea, 0, Eaddrlen);
+ if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0){
+ print("no preset Ether address\n");
+ for(;;){
+ strcpy(def, "00108bf12900"); /* valid MAC address to be used only for initial configuration */
+ if(getstr("ether MAC address", line, sizeof(line), def) < 0)
+ return -1;
+ if(parseether(ctlr->card.ea, line) >= 0 || ctlr->card.ea[0] == 0xFF)
+ break;
+ print("invalid MAC address\n");
+ }
+ }
+
+ scc = IOREGS(sccreg[ctlr->card.port], SCC);
+ ctlr->card.irq = VectorCPIC+sccirq[ctlr->card.port];
+
+ motp = &mot[ctlr->ctlrno];
+ motp->scc = scc;
+ motp->port = ctlr->card.port;
+ motp->cpm = sccid[ctlr->card.port];
+
+ ringinit(motp);
+
+ sccsetup(motp, scc, ctlr->card.ea);
+
+ /* enable is deferred until attach */
+
+ ctlr->card.reset = sccethreset;
+ ctlr->card.attach = attach;
+ ctlr->card.transmit = transmit;
+ ctlr->card.intr = interrupt;
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/fblt.c
@@ -1,0 +1,531 @@
+#include <u.h>
+#include <libc.h>
+#include <libg.h>
+#include <gnot.h>
+
+/*
+ * bitblt operates a 'word' at a time.
+ * WBITS is the number of bits in a word
+ * LWBITS=log2(WBITS),
+ * W2L is the number of words in a long
+ * WMASK has bits set for the low order word of a long
+ * WType is a pointer to a word
+ */
+#ifndef WBITS
+#define WBITS 32
+#define LWBITS 5
+#define W2L 1
+#define WMASK ~0UL
+typedef ulong *WType;
+#endif
+
+#define DEBUG
+
+#ifdef TEST
+/*
+ * globals used for testing
+ */
+int FORCEFORW;
+int FORCEBAKW;
+GBitmap *curdm, *cursm;
+Point curpt;
+Rectangle curr;
+Fcode curf;
+void *mem;
+#endif
+
+static void
+gbitexplode(ulong sw, ulong *buf, int sdep, int x)
+{
+ int j, o, q, n, nw, inc, qinc;
+ ulong s, dw, pix;
+
+ inc = 1 << sdep;
+ pix = (1 << inc) - 1;
+ nw = 1 << x;
+ n = 32 >> x;
+ qinc = (nw << sdep) - inc;
+ for(o = 32 - n; o >= 0; o -= n){
+ dw = 0;
+ s = sw >> o;
+ q = 0;
+ for(j = 0; j < n; j += inc){
+ dw |= (s & (pix << j)) << q;
+ q += qinc;
+ }
+ for(j = 0; j < x; j++)
+ dw |= dw << (inc << j);
+ *buf++ = dw;
+ }
+}
+
+/*
+void
+main(void)
+{
+ ulong buf[128];
+
+ gbitexplode(0x7777, buf, 0, 3);
+ exits(0);
+}
+*/
+
+void
+gbitblt(GBitmap *dm, Point pt, GBitmap *sm, Rectangle r, Fcode fcode)
+{
+ int width; /* width in bits of dst */
+ int wwidth; /* floor width in words */
+ int height; /* height in pixels minus 1 */
+ int sdep; /* src ldepth */
+ int ddep; /* dst ldepth */
+ int deltadep; /* diff between ldepths */
+ int sspan; /* words between scanlines in src */
+ int dspan; /* words between scanlines in dst */
+ int soff; /* bit offset of src start point */
+ int sdest; /* bit offset of src start point that matches doff when expanded */
+ int doff; /* bit offset of dst start point */
+ int delta; /* amount to shift src by */
+ int sign; /* of delta */
+ ulong *saddr;
+ ulong *daddr;
+ ulong *s;
+ ulong *d;
+ ulong mask;
+ ulong tmp; /* temp storage source word */
+ ulong sw; /* source word constructed */
+ ulong dw; /* dest word fetched */
+ ulong lmask; /* affected pixels in leftmost dst word */
+ ulong rmask; /* affected pixels in rightmost dst word */
+ int i;
+ int j;
+ ulong buf[32]; /* for expanding a source */
+ ulong *p; /* pointer into buf */
+ int spare; /* number of words already converted */
+
+
+#ifdef TEST
+ curdm = dm;
+ cursm = sm;
+ curpt = pt;
+ curr = r;
+ curf = fcode;
+#endif
+
+ gbitbltclip(&dm);
+
+ width = r.max.x - r.min.x;
+ if(width <= 0)
+ return;
+ height = r.max.y - r.min.y - 1;
+ if(height < 0)
+ return;
+
+ ddep = dm->ldepth;
+ pt.x <<= ddep;
+ width <<= ddep;
+
+ sdep = sm->ldepth;
+ r.min.x <<= sdep;
+ r.max.x <<= sdep;
+
+ dspan = dm->width * W2L;
+ sspan = sm->width * W2L;
+
+ daddr = (ulong*)((WType)dm->base
+ + dm->zero*W2L + pt.y*dspan
+ + (pt.x >> LWBITS));
+ saddr = (ulong*)((WType)sm->base
+ + sm->zero*W2L + r.min.y*sspan
+ + (r.min.x >> LWBITS));
+
+ doff = pt.x & (WBITS - 1);
+ lmask = WMASK >> doff;
+ rmask = (WMASK << (WBITS - ((doff+width) & (WBITS-1))))&WMASK;
+ if(!rmask)
+ rmask = WMASK;
+ soff = r.min.x & (WBITS-1);
+ wwidth = ((pt.x+width-1)>>LWBITS) - (pt.x>>LWBITS);
+
+ if(sm == dm){
+#ifdef TEST
+ if(!FORCEBAKW &&
+ (FORCEFORW || sm != dm || saddr > daddr ||
+ (saddr == daddr && soff > doff)))
+ ;
+ else{
+ daddr += height * dspan;
+ saddr += height * sspan;
+ sspan -= 2 * W2L * sm->width;
+ dspan -= 2 * W2L * dm->width;
+ }
+#else
+ if(r.min.y < pt.y){ /* bottom to top */
+ daddr += height * dspan;
+ saddr += height * sspan;
+ sspan -= 2 * W2L * sm->width;
+ dspan -= 2 * W2L * dm->width;
+ }else if(r.min.y == pt.y && r.min.x < pt.x)
+ abort()/*goto right*/;
+#endif
+ }
+ if(wwidth == 0) /* collapse masks for narrow cases */
+ lmask &= rmask;
+ fcode &= F;
+
+ deltadep = ddep - sdep;
+ sdest = doff >> deltadep;
+ delta = soff - sdest;
+ sign = 0;
+ if(delta < 0){
+ sign = 1;
+ delta = -delta;
+ }
+
+ p = 0;
+ for(j = 0; j <= height; j++){
+ d = daddr;
+ s = saddr;
+ mask = lmask;
+ tmp = 0;
+ if(!sign)
+ tmp = *s++;
+ spare = 0;
+ for(i = wwidth; i >= 0; i--){
+ if(spare)
+ sw = *p++;
+ else{
+ if(sign){
+ sw = tmp << (WBITS-delta);
+ tmp = *s++;
+ sw |= tmp >> delta;
+ }else{
+ sw = tmp << delta;
+ tmp = *s++;
+ if(delta)
+ sw |= tmp >> (WBITS-delta);
+ }
+ spare = 1 << deltadep;
+ if(deltadep >= 1){
+ gbitexplode(sw, buf, sdep, deltadep);
+ p = buf;
+ sw = *p++;
+ }
+ }
+
+ dw = *d;
+ switch(fcode){ /* ltor bit aligned */
+ case Zero: *d = dw & ~mask; break;
+ case DnorS: *d = dw ^ ((~sw | dw) & mask); break;
+ case DandnotS: *d = dw ^ ((sw & dw) & mask); break;
+ case notS: *d = dw ^ ((~sw ^ dw) & mask); break;
+ case notDandS: *d = dw ^ ((sw | dw) & mask); break;
+ case notD: *d = dw ^ mask; break;
+ case DxorS: *d = dw ^ (sw & mask); break;
+ case DnandS: *d = dw ^ ((sw | ~dw) & mask); break;
+ case DandS: *d = dw ^ ((~sw & dw) & mask); break;
+ case DxnorS: *d = dw ^ (~sw & mask); break;
+ case D: break;
+ case DornotS: *d = dw | (~sw & mask); break;
+ case S: *d = dw ^ ((sw ^ dw) & mask); break;
+ case notDorS: *d = dw ^ (~(sw & dw) & mask); break;
+ case DorS: *d = dw | (sw & mask); break;
+ case F: *d = dw | mask; break;
+ }
+ d++;
+
+ mask = WMASK;
+ if(i == 1)
+ mask = rmask;
+ spare--;
+ }
+ saddr += sspan;
+ daddr += dspan;
+ }
+}
+
+#ifdef TEST
+void prprog(void);
+GBitmap *bb1, *bb2;
+ulong *src, *dst, *xdst, *xans;
+int swds, dwds;
+long ticks;
+int timeit;
+
+long
+func(int f, long s, int sld, long d, int dld)
+{
+ long a;
+ int sh, i, db, sb;
+
+ db = 1 << dld;
+ sb = 1 << sld;
+ sh = db - sb;
+ if(sh > 0) {
+ a = s;
+ for(i = sb; i<db; i += sb){
+ a <<= sb;
+ s |= a;
+ }
+ } else if(sh < 0)
+ s >>= -sh;
+
+ switch(f){
+ case Zero: d = 0; break;
+ case DnorS: d = ~(d|s); break;
+ case DandnotS: d = d & ~s; break;
+ case notS: d = ~s; break;
+ case notDandS: d = ~d & s; break;
+ case notD: d = ~d; break;
+ case DxorS: d = d ^ s; break;
+ case DnandS: d = ~(d&s); break;
+ case DandS: d = d & s; break;
+ case DxnorS: d = ~(d^s); break;
+ case S: d = s; break;
+ case DornotS: d = d | ~s; break;
+ case D: d = d; break;
+ case notDorS: d = ~d | s; break;
+ case DorS: d = d | s; break;
+ case F: d = ~0; break;
+ }
+
+ d &= ((1<<db)-1);
+ return d;
+}
+
+void
+run(int fr, int to, int w, int op)
+{
+ int i, j, f, t, fy, ty;
+ extern long *_clock;
+
+ fr += bb2->r.min.x;
+ to += bb1->r.min.x;
+ fy = bb2->r.min.y + 1;
+ ty = bb1->r.min.y + 1;
+ if(timeit) {
+ memcpy(dst, xdst, dwds * sizeof(long));
+ ticks -= *_clock;
+ gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
+ ticks += *_clock;
+ return;
+ }
+ f = fr;
+ t = to;
+ memcpy(dst, xdst, dwds * sizeof(long));
+ for(i=0; i<w; i++) {
+ gbitblt(bb1, Pt(t,ty), bb2, Rect(f,fy,f+1,fy+1), op);
+ gbitblt(bb1, Pt(t,ty+1), bb2, Rect(f,fy+1,f+1,fy+2), op);
+ f++;
+ t++;
+ }
+ memcpy(xans, dst, dwds * sizeof(long));
+
+ memcpy(dst, xdst, dwds * sizeof(long));
+ gbitblt(bb1, Pt(to,ty), bb2, Rect(fr,fy,fr+w,fy+2), op);
+
+ if(memcmp(xans, dst, dwds * sizeof(long))) {
+ /*
+ * print src and dst row offset, width in bits, and forw/back
+ * then print for each of the four rows: the source (s),
+ * the dest (d), the good value of the answer (g),
+ * and the actual bad value of the answer (b)
+ */
+ print("fr=%d to=%d w=%d fb=%d%d\n",
+ fr, to, w, FORCEFORW, FORCEBAKW);
+ print("dst bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
+ bb1->base, bb1->zero, bb1->width, bb1->ldepth,
+ bb1->r.min.x, bb1->r.min.y, bb1->r.max.x, bb1->r.max.y);
+ print("src bitmap b %#lux, z %d, w %d, ld %d, r [%d,%d][%d,%d]\n",
+ bb2->base, bb2->zero, bb2->width, bb2->ldepth,
+ bb2->r.min.x, bb2->r.min.y, bb2->r.max.x, bb2->r.max.y);
+ for(j=0; 7*j < dwds; j++) {
+ print("\ns");
+ for(i=0; i<7 && 7*j+i < dwds; i++)
+ print(" %.8lux", src[7*j + i]);
+ print("\nd");
+ for(i=0; i<7 && 7*j+i < dwds; i++)
+ print(" %.8lux", xdst[7*j + i]);
+ print("\ng");
+ for(i=0; i<7 && 7*j+i < dwds; i++)
+ print(" %.8lux", xans[7*j + i]);
+ print("\nb");
+ for(i=0; i<7 && 7*j+i < dwds; i++)
+ print(" %.8lux", dst[7*j + i]);
+ print("\n");
+ }
+ prprog();
+ }
+}
+
+void
+prprog(void)
+{
+ exits(0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int f, t, w, i, sld, dld, op, iters, simple;
+ ulong s, d, spix, dpix, apix, fpix, m, *ps, *pd;
+ Point sorg, dorg;
+ GBitmap *bs, *bd;
+ long seed;
+ char *ct;
+
+ sld = 0;
+ dld = 0;
+ timeit = 0;
+ iters = 200;
+ simple = 0;
+ ARGBEGIN {
+ case 'i':
+ iters = atoi(ARGF());
+ break;
+ case 's':
+ simple = 1;
+ break;
+ case 't':
+ timeit = 1;
+ ct = ARGF();
+ if(ct)
+ iters = atoi(ct);
+ break;
+ } ARGEND
+ if(argc > 0)
+ sld = atoi(argv[0]);
+ if(argc > 1)
+ dld = atoi(argv[1]);
+ if(!timeit && !simple) {
+ seed = time(0);
+ print("seed %lux\n", seed); srand(seed); /**/
+ }
+
+ print("sld %d dld %d\n", sld, dld);
+ op = 1;
+
+ /* bitmaps for 1-bit tests */
+ bd = gballoc(Rect(0,0,32,1), dld);
+ bs = gballoc(Rect(0,0,32,1), sld);
+ for(i=0; i<bs->width; i++)
+ bs->base[i] = lrand();
+
+ /* bitmaps for rect tests */
+ if(simple) {
+ dorg = Pt(0,0);
+ sorg = Pt(0,0);
+ } else {
+ dorg = Pt(nrand(63)-31,nrand(63)-31);
+ sorg = Pt(nrand(63)-31,nrand(63)-31);
+ }
+ bb1 = gballoc(Rpt(dorg,add(dorg,Pt(200,4))), dld);
+ bb2 = gballoc(Rpt(sorg,add(sorg,Pt(200,4))), sld);
+ dwds = bb1->width * Dy(bb1->r);
+ swds = bb2->width * Dy(bb2->r);
+ dst = bb1->base;
+ src = bb2->base;
+ xdst = malloc(dwds * sizeof(long));
+ xans = malloc(dwds * sizeof(long));
+ for(i=0; i<swds; i++)
+ src[i] = lrand();
+ for(i=0; i<dwds; i++)
+ xdst[i] = lrand();
+
+loop:
+ print("Op %d\n", op);
+ if(!timeit) {
+ print("one pixel\n");
+ ps = bs->base;
+ pd = bd->base;
+ FORCEFORW = 1;
+ FORCEBAKW = 0;
+ for(i=0; i<1000; i++, FORCEFORW = !FORCEFORW, FORCEBAKW = !FORCEBAKW) {
+ f = nrand(32 >> sld);
+ t = nrand(32 >> dld);
+ s = lrand();
+ d = lrand();
+ ps[0] = s;
+ pd[0] = d;
+#ifdef T386
+ spix = (byterev(s) >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
+ dpix = (byterev(d) >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
+#else
+ spix = (s >> (32 - ((f+1)<<sld))) & ((1 << (1<<sld)) - 1);
+ dpix = (d >> (32 - ((t+1)<<dld))) & ((1 << (1<<dld)) - 1);
+#endif
+#ifdef T386
+ apix = byterev(func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld)));
+#else
+ apix = func(op, spix, sld, dpix, dld) << (32 - ((t+1)<<dld));
+#endif
+ gbitblt(bd, Pt(t,0), bs, Rect(f,0,f+1,1), op);
+ if(ps[0] != s) {
+ print("bb src %.8lux %.8lux %d %d\n", ps[0], s, f, t);
+ exits("error");
+ }
+ m = ((1 << (1<<dld)) - 1) << (32 - ((t+1)<<dld));
+#ifdef T386
+ m = byterev(m);
+#endif
+ if((pd[0] & ~m) != (d & ~m)) {
+ print("bb dst1 %.8lux %.8lux\n",
+ s, d);
+ print("bb %.8lux %.8lux %d %d\n",
+ ps[0], pd[0], f, t);
+ prprog();
+ exits("error");
+ }
+ if((pd[0] & m) != apix) {
+ spix <<= 32 - ((f+1)<<sld);
+ dpix <<= 32 - ((t+1)<<dld);
+#ifdef T386
+ spix = byterev(spix);
+ dpix = byterev(dpix);
+#endif
+ print("bb dst2 %.8lux %.8lux\n",
+ s, d);
+ print("bb %.8lux %.8lux %d %d\n",
+ ps[0], pd[0], f, t);
+ print("bb %.8lux %.8lux %.8lux %.8lux\n",
+ spix, dpix, apix, pd[0] & m);
+ prprog();
+ exits("error");
+ }
+ }
+ }
+
+ print("for\n");
+ FORCEFORW = 1;
+ FORCEBAKW = 0;
+
+ for(i=0; i<iters; i++) {
+ f = nrand(64);
+ t = nrand(64);
+ w = nrand(130);
+ run(f, t, w, op);
+ }
+
+ if(sld == dld) {
+ print("bak\n");
+ FORCEFORW = 0;
+ FORCEBAKW = 1;
+
+ for(i=0; i<iters; i++) {
+ f = nrand(64);
+ t = nrand(64);
+ w = nrand(130);
+ run(f, t, w, op);
+ }
+ }
+
+ if(op < F) {
+ op++;
+ goto loop;
+ }
+ if(timeit)
+ print("time: %d ticks\n", ticks);
+ exits(0);
+}
+
+
+#endif
--- /dev/null
+++ b/os/boot.original/rpcg/flash.c
@@ -1,0 +1,212 @@
+#include "boot.h"
+
+typedef struct Flashdev Flashdev;
+struct Flashdev {
+ uchar* base;
+ int size;
+ uchar* exec;
+ char* config;
+ int conflen;
+};
+
+enum {
+ FLASHSEG = 256*1024,
+ CONFIGLIM = FLASHSEG,
+ BOOTOFF = FLASHSEG,
+ BOOTLEN = 3*FLASHSEG, /* third segment might be filsys */
+ /* rest of flash is free */
+};
+
+static Flashdev flash;
+
+/*
+ * configuration data is written between the bootstrap and
+ * the end of region 0. the region ends with allocation descriptors
+ * of the following form:
+ *
+ * byte order is big endian
+ *
+ * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini
+ */
+typedef struct Flalloc Flalloc;
+struct Flalloc {
+ ulong check; /* checksum of data, or ~0 */
+ ulong base; /* base of region; ~0 if unallocated, 0 if deleted */
+ uchar len[3];
+ uchar tag; /* see below */
+ uchar sig[4];
+};
+
+enum {
+ /* tags */
+ Tdead= 0,
+ Tboot= 0x01, /* space reserved for boot */
+ Tconf= 0x02, /* configuration data */
+ Tnone= 0xFF,
+
+ Noval= ~0,
+};
+
+static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F};
+static char conftag[] = "#plan9.ini\n";
+
+static ulong
+checksum(uchar* p, int n)
+{
+ ulong s;
+
+ for(s=0; --n >= 0;)
+ s += *p++;
+ return s;
+}
+
+static int
+validptr(Flalloc *ap, uchar *p)
+{
+ return p > (uchar*)&end && p < (uchar*)ap;
+}
+
+static int
+flashcheck(Flalloc *ap, char **val, int *len)
+{
+ uchar *base;
+ int n;
+
+ if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone)
+ return 0;
+ base = flash.base+ap->base;
+ if(!validptr(ap, base))
+ return 0;
+ n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2];
+ if(n == 0xFFFFFF)
+ n = 0;
+ if(n < 0)
+ return 0;
+ if(n > 0 && !validptr(ap, base+n-1))
+ return 0;
+ if(ap->check != Noval && checksum(base, n) != ap->check){
+ print("flash: bad checksum\n");
+ return 0;
+ }
+ *val = (char*)base;
+ *len = n;
+ return 1;
+}
+
+int
+flashinit(void)
+{
+ int len;
+ char *val;
+ Flalloc *ap;
+ void *addr;
+ long mbytes;
+ char type[20];
+
+ flash.base = 0;
+ flash.exec = 0;
+ flash.size = 0;
+ if(archflashreset(type, &addr, &mbytes) < 0){
+ print("flash: flash not present or not enabled\n"); /* shouldn't happen */
+ return 0;
+ }
+ flash.size = mbytes;
+ flash.base = addr;
+ flash.exec = flash.base + BOOTOFF;
+ flash.config = nil;
+ flash.conflen = 0;
+
+ for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){
+ if(0)
+ print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base);
+ if(ap->tag == Tconf &&
+ flashcheck(ap, &val, &len) &&
+ len >= sizeof(conftag)-1 &&
+ memcmp(val, conftag, sizeof(conftag)-1) == 0){
+ flash.config = val;
+ flash.conflen = len;
+ if(0)
+ print("flash: found config %8.8lux(%d):\n%s\n", val, len, val);
+ }
+ }
+ if(flash.config == nil)
+ print("flash: no config\n");
+ else
+ print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config);
+ if(issqueezed(flash.exec) == Q_MAGIC){
+ print("flash: squeezed powerpc kernel installed\n");
+ return 1<<0;
+ }
+ if(GLLONG(flash.exec) == Q_MAGIC){
+ print("flash: unsqueezed powerpc kernel installed\n");
+ return 1<<0;
+ }
+ flash.exec = 0;
+ print("flash: no powerpc kernel in Flash\n");
+ return 0;
+}
+
+char*
+flashconfig(int)
+{
+ return flash.config;
+}
+
+int
+flashbootable(int)
+{
+ return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == Q_MAGIC);
+}
+
+int
+flashboot(int)
+{
+ ulong entry, addr;
+ void (*b)(void);
+ Exec *ep;
+ Block in;
+ long n;
+ uchar *p;
+
+ if(flash.exec == 0)
+ return -1;
+ p = flash.exec;
+ if(GLLONG(p) == Q_MAGIC){
+ /* unsqueezed: copy data and perhaps text, then jump to it */
+ ep = (Exec*)p;
+ entry = PADDR(GLLONG(ep->entry));
+ p += sizeof(Exec);
+ addr = entry;
+ n = GLLONG(ep->text);
+ if(addr != (ulong)p){
+ memmove((void*)addr, p, n);
+ print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
+ }
+ p += n;
+ if(entry >= FLASHMEM)
+ addr = 3*BY2PG; /* kernel text is in Flash, data in RAM */
+ else
+ addr = PGROUND(addr+n);
+ n = GLLONG(ep->data);
+ memmove((void*)addr, p, n);
+ print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n);
+ }else{
+ in.data = p;
+ in.rp = in.data;
+ in.lim = p+BOOTLEN;
+ in.wp = in.lim;
+ n = unsqueezef(&in, &entry);
+ if(n < 0)
+ return -1;
+ }
+ print("entry=0x%lux\n", entry);
+ uartwait();
+ scc2stop();
+ /*
+ * Go to new code. It's up to the program to get its PC relocated to
+ * the right place.
+ */
+ b = (void (*)(void))KADDR(PADDR(entry));
+ (*b)();
+ return -1;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/fns.h
@@ -1,0 +1,118 @@
+Alarm* alarm(int, void (*)(Alarm*), void*);
+void alarminit(void);
+void archbacklight(int);
+char* archconfig(void);
+void archdisableuart(int);
+void archenableuart(int, int);
+void archenableusb(int);
+void archetherdisable(int);
+int archetherenable(int, int*, int*);
+int archflashreset(char*, void**, long*);
+void archinit(void);
+int archoptionsw(void);
+int bootp(int, char*);
+void cancel(Alarm*);
+void checkalarms(void);
+void clockinit(void);
+void clockintr(Ureg*, void*);
+void consinit(void);
+void cpminit(void);
+void cpuidprint(void);
+#define dcflush(a,b)
+void delay(int);
+void eieio(void);
+uchar* etheraddr(int);
+int etherinit(void);
+int etherrxpkt(int, Etherpkt*, int);
+int ethertxpkt(int, Etherpkt*, int, int);
+void exception(void);
+int flashboot(int);
+int flashbootable(int);
+char* flashconfig(int);
+int flashinit(void);
+void free(void*);
+void freeb(Block*);
+int getcfields(char*, char**, int, char*);
+char* getconf(char*);
+ulong getdec(void);
+ulong gethid0(void);
+ulong getimmr(void);
+ulong getmsr(void);
+ulong getpvr(void);
+int getstr(char*, char*, int, char*);
+ulong gettbl(void);
+ulong gettbu(void);
+int hardinit(void);
+long hardread(int, void*, long);
+long hardseek(int, long);
+long hardwrite(int, void*, long);
+long i2crecv(int, void*, long);
+long i2csend(int, void*, long);
+void i2csetup(void);
+void* ialloc(ulong, int);
+Block* iallocb(int);
+void idle(void);
+int isaconfig(char*, int, ISAConf*);
+int issqueezed(uchar*);
+void kbdchar(Queue*, int);
+void kbdinit(void);
+void kbdreset(void);
+void machinit(void);
+void* malloc(ulong);
+ulong mapalloc(RMap*, ulong, int, int);
+void mapfree(RMap*, ulong, int);
+void mapinit(RMap*, Map*, int);
+void meminit(void);
+void microdelay(int);
+void mmuinit(void);
+int optionsw(void);
+void panic(char*, ...);
+int parseether(uchar*, char*);
+int plan9boot(int, long (*)(int, long), long (*)(int, void*, long));
+void putdec(ulong);
+void puthid0(ulong);
+void putmsr(ulong);
+int qbgetc(Queue*);
+void qbputc(Queue*, int);
+void qbwrite(Queue*, Block*);
+Block* qget(Queue*);
+long qlen(Queue*);
+Queue* qopen(int, int, void (*)(void*), void*);
+#define qpass qbwrite
+void scc2stop(void);
+void sccnmsi(int, int, int);
+void sched(void);
+void screeninit(void);
+void screenputs(char*, int);
+void sdraminit(ulong);
+Partition* sethardpart(int, char*);
+Partition* setscsipart(int, char*);
+void setvec(int, void (*)(Ureg*, void*), void*);
+int splhi(void);
+int spllo(void);
+void splx(int);
+void trapinit(void);
+void uartputs(char*, int);
+void uartsetboot(void (*f)(uchar*, int));
+void uartspecial(int, int, Queue**, Queue**, void(*)(Queue*,int));
+void uartwait(void);
+long unsqueezef(Block*, ulong*);
+
+#define GSHORT(p) (((p)[1]<<8)|(p)[0])
+#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))
+#define GLSHORT(p) (((p)[0]<<8)|(p)[1])
+#define GLLONG(p) ((GLSHORT(p)<<16)|GLSHORT(p+2))
+
+#define KADDR(a) ((void*)((ulong)(a)|KZERO))
+#define PADDR(a) ((((ulong)(a)&KSEGM)!=KSEG0)?(ulong)(a):((ulong)(a)&~KZERO))
+
+/* IBM bit field order */
+#define IBIT(b) ((ulong)1<<(31-(b)))
+#define SIBIT(n) ((ushort)1<<(15-(n)))
+
+#define IOREGS(x, T) ((T*)((char*)m->iomem+(x)))
+
+int uartinit(void);
+Partition* setuartpart(int, char*);
+long uartread(int, void*, long);
+long uartseek(int, long);
--- /dev/null
+++ b/os/boot.original/rpcg/g.mx
@@ -1,0 +1,1987 @@
+S0030000FC
+S325000100007C6000A63C800000608480427C632078606310007C0004AC7C6001247C0004AC52
+S325000100204C00012C7C908AA63C800A007C908BA64C00012C3C800C007C908BA64C00012C0A
+S325000100403C8004007C908BA64C00012C7C0004AC7C988AA63C800A007C988BA64C00012C2F
+S325000100603C800C007C988BA64C00012C3C8004007C988BA64C00012C388000077C9E23A6D3
+S325000100807CBE9AA63C80FA207C9E9BA63860FF88906400043C6001016063244090640000DE
+S325000100A0380000003C40001460427FF83C40001460427FF83C60FFC26063D7103882800866
+S325000100C07C0418004182002C38A2A1F87CA4285038A500037CA516707CA903A63884FFFC7B
+S325000100E03863FFFC84A3000494A400044200FFF83C60FFC2606302007C6803A64E80002026
+S325000101003862A1F8388227107C8320514081001C7C8416707C8903A63863FFFC3800000065
+S32500010120940300044200FFFC3822A3C89022801438210FF8380000004800AA01480086F587
+S32500010140480000003D00FA40806800003CA008007C63287890680000480000007C6000A6CC
+S325000101604E8000207C0004AC7C6001247C0004AC4C00012C4E8000207C0006AC4E800020AE
+S325000101804E8000207C6000A6606480007C0004AC7C8001247C0004AC4C00012C4E800020C4
+S325000101A07C6000A65464045E7C0004AC7C8001247C0004AC4C00012C4E8000207C8000A61A
+S325000101C0506404207C0004AC7C8001247C0004AC4C00012C4E8000207C6C42E64E80002062
+S325000101E07C7F42A64E8000207C7E9AA64E8000207C7602A64E8000207C7603A64E800020EE
+S325000102003821FF58BC4100303C40001460427FF87C9142A69081002C7CB042A690A10028B2
+S325000102207CC902A690C100247C8102A6908100207CB342A690A1001C7CD242A690C100187C
+S325000102407C9A02A6908100107CBB02A690A1000C90010008386100087C60092D3800000018
+S325000102604E800020B8410030800100287C1043A6800100247C0903A6800100207C0103A6A8
+S325000102808001001C7C0FF120800100187C1243A6800100107C1A03A68001000C7C1B03A671
+S325000102A08021002C4E8000207C3143A67C0000267C1343A67C0802A64BFFFF4938000000D6
+S325000102C04800AC294BFFFFA17C1242A67C0803A67C1042A64C00012C4C0000647FE802A6C1
+S325000102E097E1FFE84BFFFF05812280147064FFFF5484C23F418200802C0400204182006CA6
+S325000103002C040021418200587C0A0378914900143D00FA409109001C814900203CC0007AEE
+S3250001032060C6120090C9000C80EA028454E7653E394700018089000C7C8451D6908900086D
+S3250001034080E9001C3CC03E0090C7000083E100007FE803A6382100184E8000203D40000828
+S32500010360614A23A04BFFFFA83D400008614A23004BFFFF9C3D400008614A60004BFFFF9076
+S325000103807FE802A697E1FFE038629EC0480035D538629ED3480035CD4BFFFE49546A843E40
+S325000103A02C0A0006418101B4418201A42C0A0001418201902C0A00034182017C2C0A0004DD
+S325000103C04182016838629F0891410008480035954BFFFE117066FFFF90C1001038629F1CDA
+S325000103E081010010910100084800357938629F2E480035714BFFFDF5706AFFFF9141001881
+S325000104007D464671418201182C060020418201042C060021418200F038629F4F7D4846705C
+S32500010420910100084800353D38629F5A80810018708400FF90810008480035294800019D1D
+S325000104409061001038629F6880810010908100084800351138629F7880E2801480E7001C11
+S3250001046080E7000090E10008480034F98142801438629F87808A002080840284908100083C
+S3250001048080CA002080C6028090C1000C480034D538629FA481028014810800083D20000F84
+S325000104A0612942407D084BD691010008480034B538629FB5480034AD8142801438629FB75A
+S325000104C080AA002080A5010090A1000880EA002080E7010490E1000C4800348938629FD0EB
+S325000104E08082801480840020A084017A908100084800347183E100007FE803A638210020A9
+S325000105004E80002038629F47480034594BFFFF1C38629F404800344D4BFFFF1038629F3523
+S32500010520480034414BFFFF0438629EE7480034354BFFFEA038629EE0480034294BFFFE9459
+S3250001054038629ED94800341D4BFFFE8838629EEE480034114BFFFE7C2C0A00074182001C87
+S325000105602C0A0050418200084BFFFE5C38629F01480033F14BFFFE5C38629EF6480033E5A7
+S325000105804BFFFE507FE802A697E1FFF03862A0A7480033D180628014806300145463C23EF5
+S325000105A070630FFF2C03082340820028386000015463103A388283C07C6322148063000080
+S325000105C083E100007FE803A6382100104E8000207C0303784BFFFFDC806280148063001CB5
+S325000105E080630000706300F05463E13E4E8000208102801480C8000038E000327FE63B96AB
+S325000106007FFF39D67CDF30514082001480E8001C80C700006CC6080090C700004E8000204A
+S325000106207FE802A697E1FFF080A2801480A5002080A5010070A50001408200183860FFFF96
+S3250001064083E100007FE803A6382100104E80002038E2A0C490E100084800CDA18081001802
+S325000106603CC0FFC090C4000080E1001C3C800040908700007C03037883E100007FE803A666
+S32500010680382100104E8000207FE802A697E1FFE87C030000408100183860FFFF83E100003C
+S325000106A07FE803A6382100184E800020806100203882A0CE908100084800CD4180C10020CB
+S325000106C0390000029106001C3862A0D2480000CD7C671B787C030000418200148061002037
+S325000106E03863002C90E10008480029053860000183E100007FE803A6382100184E800020D1
+S325000107003821FFF0814280142C030004418200103860FFFF382100104E800020812A002075
+S32500010720810A001C80E8000064E7800090E80000A0E9095260E70A00B0E90952A0E9095055
+S3250001074070E7F5FFB0E9095080A1001838E0000790E500008101001C38A0000590A80000D5
+S325000107607C030378382100104E80002080A2801480A5001C808500003FE07FFF63FFFFFF28
+S325000107807FE42039908500004E8000204E8000204E8000204E8000207FE802A697E1FFD073
+S325000107A09061003480C284247C0600004082006048008929386000A93882C3A89081000806
+S325000107C038C0008090C1000C48008F4D7C0300004180019C3C600000606380A93882C3A88F
+S325000107E0388400809081000838C0008090C1000C48008F257C0300004180017438E000FF00
+S3250001080098E2C4A839000001910284243922C3A888C900002C0600FF4182001088E90000EA
+S325000108202C07000A408200187C03037883E100007FE803A6382100304E80002091210028DB
+S3250001084088A900002C05000A4182001088C900002C0600FF408201009121002C88C90000DE
+S325000108602C06003D40820050806100344800CB5D8121002C810100287C8848507C041800BF
+S3250001088040820034806100344800CB41906100188061003480A1002890A1000880E10018D9
+S325000108A090E1000C4800CAAD8121002C7C03000041820038888900002C04000A418200108F
+S325000108C088A900002C0500FF40820018888900002C04000A4082FF3C392900014BFFFF34AE
+S325000108E0392900014BFFFFD039490001890900002C08000A41820010888900002C0400FF0F
+S325000109004082004C38628048914100089121002C914100287CCA485090C1000C4800C64520
+S3250001092038E2804880A1002C7CE53A14810100287CE83850980700003862804883E10000D7
+S325000109407FE803A6382100304E800020392900014BFFFF9C88E900002C07003D4082000816
+S325000109604BFFFEF8392900014BFFFED83862A0D548002FF17C03037883E100007FE803A6C8
+S32500010980382100304E8000203821FFF080A2801480A500087CA51BD638A500087CA5267000
+S325000109A02C051000418000183865000F7C631E7060630001382100104E80002054A3083CA7
+S325000109C0382100104E8000207FE802A697E1FFD89061002C38600009900100084BFFFDB10C
+S325000109E0810280148128002080A90ABC60A500C090A90ABC9121002480A90AB83FE0FFFF7F
+S32500010A0063FFFF3F7FE5283990A90AB8806100304BFFFF798121002464680001910909F076
+S32500010A2080A90AE03FE0FFFF63FF0FFF7FE5283990A90AE038600001480032B18141002C75
+S32500010A407C691B783CA0FA2060A53E8090A10020B0650000906A00B43C8000006084B000FA
+S32500010A60B0830000B0030002390A00247508E0003CA020007C0828004182011038EA002401
+S32500010A8090E9000438600001480032618141002C7C691B7881010020B0680002906A00B88A
+S32500010AA038C03000B0C30000B003000238AA00A474A5E0003CE020007C053800418200B8F0
+S32500010AC0388A00A4908900047C03037839000009910100089001000C48003085812100205A
+S32500010AE038E0001898E9000438A0001898A9000539000001B109000638C00001B0C9002870
+S32500010B00B009002CB009002E39000001B1090030808280148084002039240A8038C000FF46
+S32500010B2098C9000691210018388000179889000A386000143CA0FFC260A50C9C90A1000854
+S32500010B4080E1002C90E1000C4800A1298121001838E04820B0E90002A0A9000260A500034A
+S32500010B60B0A9000283E100007FE803A6382100284E800020388A00A43FE0FFFF63FFFFFF4D
+S32500010B807FE420394BFFFF4038EA00243FE0FFFF63FFFFFF7FE738394BFFFEE87FE802A630
+S32500010BA097E1FFD08121003880A2801480A5002038A50A8038E000FF98E50006810900B4D3
+S32500010BC0910100207C0800004182001480810020A0840000708480004182009C816900B847
+S32500010BE07C0B00004182001491610020A08B0000708480004182001483E100007FE803A694
+S32500010C00382100304E8000203940FFFF80C900107C0600004182001C9121002C806900104E
+S32500010C2048009409816100208121002C7C6A1B782C0AFFFF4182002C994900A438C00001DD
+S32500010C40B0CB0002A08B000060848000B08B000083E100007FE803A6382100304E8000205B
+S32500010C609809000883E100007FE803A6382100304E80002080A9000C7C050000418200144C
+S32500010C8080810020A08400027C0400404181002481010020A0A8000060A59000B0A8000089
+S32500010CA083E100007FE803A6382100304E80002080A900187C0500004182002438690024D4
+S32500010CC080A10020A0A5000290A1000880E900187CE803A64E8000214BFFFFB89121002CF0
+S32500010CE080C900147C060000418200487C0A037881010020A10800027C0A40404080FF945C
+S32500010D00914100247CCA4A1488C600248069000C90C1000880E900147CE803A64E800021F9
+S32500010D208121002C80A10024394500014BFFFFC480610020A0630002480090E9906100183D
+S32500010D408063000480C1002C38C6002490C1000880810020A08400029081000C4800C2054A
+S32500010D608121001881010020A1080002808900047D044214910900048061002C8063000CE7
+S32500010D80912100084800920D4BFFFF087FE802A697E1FFE09061001C4BFFF4098121001CE2
+S32500010DA090610018888900087C0400004082001C80690010480092758121001C90610014A1
+S32500010DC02C03FFFF4082001C806100184BFFF3F183E100007FE803A6382100204E800020FF
+S32500010DE080C280B47C06000041820064810900B8A108000071088000418200084BFFFFF0E5
+S32500010E0080C1001498C900A480C900B838A00001B0A6000280C900B8A0A6000060A5800073
+S32500010E20B0A600007D284B7880A280B47C0500004082001038A0000198A800084BFFFF6872
+S32500010E407C05037898A800084BFFFF5C7C0A0378914100102C0A00644080FFA880C900B8BD
+S32500010E60A0C6000070C68000408200084BFFFF943860000148001C098121001C80C1001093
+S32500010E80394600014BFFFFCC7FE802A697E1FFE0906100243902C4B080A800047C050000DF
+S32500010EA04182001483E100007FE803A6382100204E8000209101001C38C0000190C8000476
+S32500010EC038601000900100089001000C90010010480090098121001C9069000C8101002C3A
+S32500010EE09068000038604000900100083CE0FFC260E70E8C90E1000C9121001048008FDDD1
+S32500010F00814100288121001C9069001080C100309066000080A1003490A90014388000094F
+S32500010F20908900007C0A000040820008394025807D234B78914100084BFFFA9183E10000AD
+S32500010F407FE803A6382100204E8000209062C4C84E8000207FE802A697E1FFD88181003017
+S32500010F607C6D1B7838C2C4B090C100247C0B03787C6A1B7891A1002C7D0D62147C0A40402C
+S32500010F804080002C88AA00007CA507742C05000A40820008396B0001394A000191A1002C04
+S32500010FA07D0D62147C0A40404180FFDC7C6C5A1448008E71818100308141002C7C6B1B7851
+S32500010FC07D856378398CFFFF7C0500004182005488AA00007CA507742C05000A40820018EF
+S32500010FE080CB000439060001910B00043900000D99060000808B000438C4000190CB00046B
+S325000110007D465378394A000188C6000098C400007D856378398CFFFF7C0500004082FFB477
+S3250001102080610024806300109161000848008F6583E100007FE803A6382100284E80002098
+S325000110403821FFF03902C4B088E800087C070000418200084BFFFFF4382100104E80002038
+S325000110607FE802A697E1FFE0812100289061002438A2C5707C0900004081001490A1001C6E
+S32500011080808500007C0400004082001483E100007FE803A6382100204E8000207D234B78B0
+S325000110A048008D819061001880630004808100249081000880E1002890E1000C4800BEA5F4
+S325000110C08121001880E10028808900047CE43A1490E900048061001C8063000091210008F4
+S325000110E048008EB183E100007FE803A6382100204E800020386000014E8000207FE802A6F1
+S3250001110097E1FFF08061001838A2819890A100084800C3517C0300004182001C8061001889
+S325000111203882819D908100084800C3397C03000040820038900281F83CC0002090C281FC04
+S32500011140386281F83863000838E281A290E100084800C2A9386281F883E100007FE803A6E2
+S32500011160382100104E8000207C03037883E100007FE803A6382100104E8000207FE802A63D
+S3250001118097E1FFE88082C5707C0400004082001C3C600001900100089001000C90010010E0
+S325000111A048008D399062C5708102C5747C080000418200108062C57448008CC19002C57465
+S325000111C0386281A74800279D3C60FFC2606311604BFFFD7D38C0FFFF90C2C5789002C57C8D
+S325000111E09002C5C09002C5C47C03037883E100007FE803A6382100184E8000207FE802A6DA
+S3250001120097E1FFD08181003890610034810100349101001C3942C57080E2801480E70000B0
+S3250001122090E1002C918100387C0C000040810140812A000491410028900A00047C0900006A
+S32500011240408200A0900A0054806A000048008CC981810038814100287C691B787C03000095
+S325000112604082008080C2801480C600008101002C7CC8305054C5083C7CC62A1454C6183850
+S3250001128054A5482C7CC6285038E000327CC63B9628063A984180FFB480EA005438E7000171
+S325000112A090EA00542C07000341800020386281C1480026B17C03037883E100007FE803A6D9
+S325000112C0382100304E800020386281D039000001910100084BFFFC81814100284BFFFF6C6B
+S325000112E080A9000480C900007D4628507C0A6000408100087D8A63788061001C91210020D6
+S3250001130080E9000090E10008914100249141000C4800BC5181610024814100288121002009
+S32500011320808900007CE45A1490E9000080E9000080C900047C073040418000507D234B7839
+S3250001134048008B39816100248141002880E100387D8B385080E1001C7CA75A1490A1001C06
+S32500011360918100387C0C00004181FEC88061001C80E100347C67185083E100007FE803A6BB
+S32500011380382100304E800020912A00044BFFFFC07FE802A697E1FFE0808100289081001C4B
+S325000113A08122C5C07C0900004081005880E1002C7C093800408100088121002C8102C5C077
+S325000113C07CC9405090C2C5C08061001C38E2C57038E7001090E10008912100189121000CDE
+S325000113E04800BB81812100188081001C7CE44A1490E1001C8081002C7CE9205090E1002CA1
+S3250001140080E1002C7C070000408100C83862815038A0004090A100084BFFFDE58141002C56
+S325000114207C691B782C030040408000187C03037883E100007FE803A6382100204E80002011
+S325000114407C035000408100307C8A48509082C5C03862C5703863001038A281507CA55214E4
+S3250001146090A1000880A2C5C090A1000C4800BAF58121002C8061001C38C2815090C1000862
+S32500011480912100189121000C4800BAD9812100188101002C7CC9405090C1002C8101001C8A
+S325000114A07CC84A1490C1001C80C2C57C38C6000190C2C57C386281D2388000019081000842
+S325000114C04BFFFA9580E1002C7C0700004181FF408061001C810100287C68185083E10000C4
+S325000114E07FE803A6382100204E8000203821FFE87C0B03782C0B0100408000545569C00E54
+S32500011500394000087C0A00004081002875248000418200445526083C3FE004C163FF1DB7DB
+S325000115207FE93278394AFFFF7C0A00004181FFE05567103A38A2DC307CE72A1491270000A5
+S32500011540396B00012C0B01004180FFB4382100184E8000205529083C4BFFFFCC7FE802A6EE
+S3250001156097E1FFF081410018906100148082DC347C0400004082000C4BFFFF758141001826
+S3250001158080C1001C3FE0FFFF63FFFFFF7FE8327881210014394AFFFF7C0A00004180003C9F
+S325000115A05505463E7D264B783929000188C600007CA5327854A5103A38C2DC307CA53214B4
+S325000115C080A500005507402E7CE82A78394AFFFF7C0A00004080FFCC3FE0FFFF63FFFFFF00
+S325000115E07FE3427883E100007FE803A6382100104E800020816100088121000C7C0B0000DE
+S32500011600408200148083000090890000912300004E80002080AB000090A90000912B00000F
+S325000116204E800020814100088121000C7C0A00004082001080890000908300004E800020DB
+S3250001164080C9000090CA00004E8000207FE802A697E1FFE87C09037838E2ED382C09000A06
+S325000116604080002C80C700047C0600004082001080A7000C7C0500004182003039290001CE
+S3250001168038E700142C09000A4180FFDC386282D8480023597C03037883E100007FE803A60F
+S325000116A0382100184E8000209007000C9007001038A0000190A700047CE33B7883E10000F0
+S325000116C07FE803A6382100184E8000207FE802A697E1FFD89061002C7C03000040800008D2
+S325000116E09001002C4BFFEABD906100184BFFFF61818280147C6A1B7880C1002C54C5083CA8
+S325000117007CC62A1454C620367CC62A1438E003E87CC63B9690C3000880A1003090A3000C51
+S3250001172080810034908300107C0B0378812C00187C0900004182003480A90008808A0008C4
+S325000117407C0520004181005480A90008808A00087CA5205090AA00087D2B4B7881290000A0
+S325000117607C0900004082FFD4386C001891610008914100249141000C4BFFFE7D8061001800
+S325000117804BFFEA3D8061002483E100007FE803A6382100284E800020808A00088109000845
+S325000117A07C844050908900084BFFFFC09003000C4E8000204E8000207FE802A697E1FFA8BF
+S325000117C04BFFE9E1814280149061004C812A00187C090000418200A47C0B03787C09000024
+S325000117E04182001080E900087C070000408100A47C0900004182001080E9000838E7FFFFD0
+S3250001180090E900087C090378916100507C095800408000685527103A3901001C7CE7421424
+S3250001182080E7000080E7000C7C07000041820028912100545523103A38C1001C7C63321457
+S32500011840806300007CE803A64E80002181610050812100545525103A3881001C7CA522148A
+S3250001186080A500009005000439290001916100507C0958004180FFA08061004C4BFFE94120
+S3250001188083E100007FE803A6382100584E8000202C0B000A418000084BFFFF589161005041
+S325000118A05568103A38C1001C7D08321491280000386A0018900100089121000C4BFFFD69C0
+S325000118C081428014812A001880E10050396700014BFFFF0CA121000A5527043E54E7C23E7B
+S325000118E098E300005526043E98C300014E800020814100085544463E988300005546843E00
+S3250001190098C300015548C23E99030002994300034E8000207C671B78886300005463C00E76
+S32500011920888700015484801E7C63237888A7000254A5402E7C632B7888C700037C633378AA
+S325000119404E8000207C671B78886300005463402E88A700017C632B784E8000203821FFD83C
+S325000119608222809C814100307C691B787C0F03787C0C03787C0B03787C100378706500014E
+S32500011980418200207C0A000041820014888900007D8C2214394AFFFF392900013A00000191
+S325000119A02C0A001041800054A0E90000A08900027D6B3A14A0C900047DAB2214A109000660
+S325000119C07DCD3214A0A900087DCE4214A0E9000A7DCE2A14A089000C7DCE3A14A0C9000E1D
+S325000119E07DAE22147D6D3214394AFFF0392900102C0A00104080FFB42C0A00024180001C9D
+S32500011A00A0C900007D6B3214394AFFFE392900022C0A00024080FFEC7C10000041820070A2
+S32500011A207C0A00004182000C88A900007DEF2A14889100007C8407747C0400004182004850
+S32500011A407DEF5A145588C23E7D2F4214718800FF5508402E7D2942145528843F41820014F0
+S32500011A607127FFFF7D283A145528843F4082FFF43FE0FFFF63FFFFFF7FE34A7838210028BF
+S32500011A804E8000207D8C5A144BFFFFBC7C0A00004182000C88A900007D8C2A1488910000EF
+S32500011AA07C8407747C0400004182000C7D8C5A144BFFFF947DEF5A144BFFFF8C3821FFF00A
+S32500011AC07C691B787C0B037888E3000070E7000F54EA103A7C0A00004081002888C900006C
+S32500011AE054C6402E890900017CC643787D6B3214394AFFFE392900027C0A00004181FFE08E
+S32500011B007168FFFF5566843E7D0832147104FFFF5507843E7C843A146883FFFF382100106E
+S32500011B204E8000207FE802A697E1FFD0906100343862B7C89061002C9001000838E005F059
+S32500011B4090E1000C4800B1E98061002C3863002A80A1003C90A10008810100409101000C57
+S32500011B604800B4018121002C80C1004039460008980900163900001199090017980900141C
+S32500011B80980900153869001891410020914100084BFFFD458061002C3863001A8102822090
+S32500011BA0910100084BFFFD4D8061002C38630022A0E2822490E100084BFFFD1D8061002C14
+S32500011BC03863001E8101003881080000910100084BFFFD218061002C3863002480810038FB
+S32500011BE0A0840004908100084BFFFCED8061002C3863002680E1002090E100084BFFFCD983
+S32500011C008121002C98090028980900293869001680E1004038E7001490E100084BFFFD41D0
+S32500011C205464043E908100188061002C3863002881010018910100084BFFFC9D3922B7C8B9
+S32500011C40810100403948002C390000459909000E9809000F390000FF990900169121002866
+S32500011C60386900109141002438AAFFF290A100084BFFFC6580610028386300128082801CAB
+S32500011C8038E4000190E2801C908100084BFFFC49812100289809001498090015980900187C
+S32500011CA0980900193869000E4BFFFE155468043E91010018806100283863001880810018DA
+S32500011CC0908100084BFFFC11806100283863000C39000800910100084BFFFBFD80610028B7
+S32500011CE080C1003838C6000690C10008388000069081000C4800B26D8061003438E2B7C817
+S32500011D0090E10008808100249081000C38E0138890E100104800471583E100007FE803A6B5
+S32500011D20382100304E8000207FE802A697E1FF60906100A49801001C38A0000598A1001DC2
+S32500011D409801001E80C100AC98C1001F3861001C3863000480C100B090C100084800B69D27
+S32500011D60806100B04800B66538830005806100A4810100A89101000838C1001C90C1000CED
+S32500011D80908100104BFFFDA180C100B47C0600004182001C38629C48810100AC9101000897
+S32500011DA080C100B090C1000C48001BB983E100007FE803A6382100A04E8000207FE802A648
+S32500011DC097E1FFD09061003480A281F47C0500004082029C392003E880828014808400003A
+S32500011DE05485083C7C842A145484183854A5482C7C84285038C000327C8433967C89221446
+S32500011E009081001880A2801480A5000054A6083C7CA5321454A5183854C6482C7CA530509A
+S32500011E2038E000327CA53B96810100187C082840408102288061003438E2BDB890E10008D1
+S32500011E4080828014808400005486083C7C8432145484183854C6482C7C84305038E00032FD
+S32500011E607C843B96810100187C8440509081000C480044319061002C7C0300004181000820
+S32500011E804BFFFF843882BDB8908100203864000C4BFFFAB55466043E2C060800418200086C
+S32500011EA04BFFFF64806100203863000E4BFFFC11812100207C0300004182001038629C5EC5
+S32500011EC048001AA14BFFFF4088E9000E2C0700454182001038629C6F48001A894BFFFF28A4
+S32500011EE0890900172C080011418200084BFFFF1898090016386900264BFFFA4D5466043EB6
+S32500011F00806100203863001890C1002890C100084BFFF9C580610020386300284BFFFA29FB
+S32500011F207C030000408200F480A10038A0A500047C050000418200208061002038630022A1
+S32500011F404BFFFA0581010038A10800047C0340004082FEB4806100203863001A4BFFF9B9E5
+S32500011F60814100389061001C80AA00003880FFFF7C0520004182001080AA00007C0328002E
+S32500011F804082FE8480C100283926FFF880C100407C0930004081001038629CA6480019C52E
+S32500011FA04BFFFE648061003C808100203884002A90810008912100289121000C4800AFA5FD
+S32500011FC080A1003880E1001C90E5000080610020386300224BFFF97181210038B069000446
+S32500011FE03869000638A2BDB838A5000690A1000838E0000690E1000C4800AF693880000114
+S32500012000908281F48061002883E100007FE803A6382100304E80002080610020386300168C
+S32500012020808100283884000C908100084BFFF9315469043E5528043E7C0800004182FEEC2C
+S3250001204038629C815527043E90E1000880E1002C90E1000C4800190D7C03037883E10000B5
+S325000120607FE803A6382100304E800020392013884BFFFD687FE802A697E1FDC89061023CB4
+S325000120809801002638E0000198E10027386100263863000238829CBB9081000880C10244B4
+S325000120A090C1000C48001879390300023861002638630001910102307C681A1438829CBE60
+S325000120C090810008480018598161024038A3000280C102307CA62A1490A10230A08B0004C1
+S325000120E0908102287C090378912102342C0900054080007081010228B10B00048061023CC1
+S325000121009161000838E1002690E1000C80810230908100104BFFFA1181210240B0090004B8
+S325000121208061023C9121000880A1024890A1000C39000204910100104BFFFC858161024047
+S32500012140812102482C0300044080003480C1023439260001912102342C0900054180FF9814
+S3250001216038629D05480017FD3860FFFF83E100007FE803A6382102384E8000208889000024
+S325000121805484402E88C900017C8433782C040003418200482C040005418200084BFFFFB0BE
+S325000121A038629CC488C9000254C6402E890900037CC6437890C1000838A9000490A1000C36
+S325000121C0480017A13860FFFF83E100007FE803A6382102384E8000203960000188890002C0
+S325000121E05484402E88C900037C843378916283E87C0458004182004838629CDE9081000825
+S32500012200480017618061023C80C1024090C10008388000019081000C38C29CF990C1001036
+S32500012220900100144BFFFB053860FFFF83E100007FE803A6382102384E8000203863FFFC87
+S3250001224083E100007FE803A6382102384E8000207FE802A697E1FFD0812283E890610034F9
+S325000122609801002038800004988100217D25467098A100229921002338A9000190A283E899
+S32500012280810100403908000491010040900100248061003480E1003890E1000838A1002089
+S325000122A090A1000C38E0000490E100104BFFF8798061003480E1003890E1000880A1003CFE
+S325000122C090A1000C81010040910100104BFFFAF1816100408141003C7C691B787C035800B2
+S325000122E04080006438629D2C912100089161000C480016718061003480C1003890C10008E2
+S32500012300388000029081000C38C29D4090C10010900100144BFFFA158101002438C8000102
+S3250001232090C100242C080005408000084BFFFF643860FFFF83E100007FE803A638210030E0
+S325000123404E800020890A00025508402E88AA00037D082B789101002C808283E87C082000FC
+S325000123604182007C38629D4B480015F9814283E88121002C38CAFFFF7C09300040820018B4
+S3250001238080A1002439050001910100242C0500084180FF0038629D4D912100089141000CE7
+S325000123A0480015C18061003480E1003890E1000838A0000190A1000C38E29D7590E100100E
+S325000123C0900100144BFFF9653860FFFF83E100007FE803A6382100304E8000203863FFFC92
+S325000123E083E100007FE803A6382100304E8000207FE802A697E1FC48906103BC48003E6981
+S32500012400814103C0906100C07C0300004082002838629D8180A103BC90A1000848001545A3
+S325000124203860FFFF83E100007FE803A6382103B84E8000209001002C900100287C0A00008D
+S325000124404182001488AA00007CA507747C050000408205C03861024C9001000838A0016C03
+S3250001246090A1000C4800A8C938E0000198E1024C390000019901024D388000069881024E35
+S325000124803861024C3863001C80A100C090A10008390000069101000C4800AAC990028220B1
+S325000124A038A00044B0A28224386282203863000680C100C090C10008388000069081000CEF
+S325000124C04800AAA1900100DC808100DC2C04000A4080009038C0FFFF90C2823838E0004331
+S325000124E0B0E2823C3862823838630006390283689101000838A0000690A1000C4800AA655E
+S32500012500806103BC390282389101000838A1024C90A1000C38E0016C90E100104BFFF609D2
+S32500012520806103BC38C2823890C10008390100E09101000C38A0016C90A100104BFFF881E6
+S325000125407C0300004181045C80C100DC38C6000190C100DC808100DC2C04000A4180FF783B
+S3250001256080C100DC2C06000A4180002038629D94480013F13860FFFF83E100007FE803A6F9
+S32500012580382103B84E8000208101002C7C0800004182040080A1002C88A500007CA5077423
+S325000125A07C050000418203EC8901010C7D0807747C0800004182001838629DA538E100E016
+S325000125C038E7002C90E100084800139938629DA9888100F490810008888100F59081000C2B
+S325000125E0888100F690810010888100F790810014A082823C908100188081002C9081001C2C
+S32500012600480013614BFFEA3D386100E0386300104BFFF30590628220A08283A438E4000126
+S32500012620B0E283A4B0828224386100E0386300144BFFF2E59062823838E00045B0E2823C60
+S32500012640806103BC38C2823890C100088121002C9121000C38C2C5C890C100104BFFFA19F5
+S325000126607C030000408000183860FFFF83E100007FE803A6382103B84E8000203882C5C8A9
+S3250001268039440004906100D82C030020418002CC890A00005508402E88CA00017D0833782A
+S325000126A05508801E88EA000254E7402E888A00037CE723787D083B782C0806EB4082029C2B
+S325000126C088EA000454E7402E88AA00057CE72B7854E7801E88CA000654C6402E890A000744
+S325000126E07CC643787CED337888AA000854A5402E890A00097CA5437854A5801E888A000AF6
+S325000127005484402E88CA000B7C8433787CAC2378890A000C5508402E88CA000D7D083378A8
+S325000127205508801E88EA000E54E7402E888A000F7CE723787D083B78910100C8918100CCDF
+S325000127407CC8621491A100D07CC66A1490C100C488AA001454A5402E890A00157CA54378B0
+S3250001276054A5801E888A00165484402E88CA00177C8433787CA5237838629DD090A100B491
+S325000127803FE01FFF63FFFFFF7FE8283991010008480011D14BFFE8AD38629DDF80C100D003
+S325000127A090C10008480011BD808100B43FE01FFF63FFFFFF7FE42039908100BC38E2C5C821
+S325000127C039A70024808100D83944FFE0816100D0916100D47C0A000040820050806103BC09
+S325000127E0388282389081000838E2C5C890E1000C39000200910100104BFFFA59816100D4F1
+S325000128007C6A1B787C030000408000183860FFFF83E100007FE803A6382103B84E800020D5
+S3250001282038C2C5C839A60004914100D87C0B5000418100087D6A5B78806100BC91A100B89B
+S3250001284091A10008914100DC9141000C4800A715818100CC814100DC80A100BC7D05521476
+S32500012860910100BC80A100B87DA5521491A100B880A100D47D6A285080A100D87D4A28502C
+S32500012880914100D8916100D47C0B00004181FF487C0C000040820088806103BC38C282380B
+S325000128A090C10008390000039101000C38A29DE690A10010900100144BFFF47138629DE9CC
+S325000128C080E100C890E1000880A100C490A1000C4800109138629DF1810100B4910100084C
+S325000128E0480010814BFFE75D4800137D4BFFD8B580C100B43FE01FFF63FFFFFF7FE630395B
+S325000129007CC803A64E8000217C03037883E100007FE803A6382103B84E80002038629DE24B
+S32500012920918100084800103D81A100B8814100D8816100CC916100D4900100CC80E100BC7F
+S3250001294038E70FFF3FE0FFFF63FFF0007FE7383990E100BC4BFFFE80806103BC38C28238B4
+S3250001296090C100089001000C39029DBF9101001038A0000190A100144BFFF3B13860FFFF7F
+S3250001298083E100007FE803A6382103B84E80002038C100E038C6006C90C1002C4BFFFC0CA8
+S325000129A03861024C3863001C390100E03908001C9101000838A0000690A1000C4800AB0D46
+S325000129C0814100287C030000418200084BFFFB7C88E100E12C0700014082FB7088C100E225
+S325000129E02C0600064082FB647C0A00004182FB747D435378388100E03884002C908100089A
+S32500012A004800AA617C0300004182FB584BFFFB3C38610030914100084800A9E13861003008
+S32500012A203880003A908100084800A2E17C0300004182004038E100309061002C7C0338001A
+S32500012A404182FA1488A3FFFF7CA507742C05005C408200084BFFFA0038C1003090C100289C
+S32500012A6038C3000190C1002C980300004BFFF9E8390100309101002C4BFFF9DC3821FFF081
+S32500012A807C691B7880A28014814500047D254B783929FFFF7C050000408100187C0703781A
+S32500012AA07C0750404080FFE838E700014BFFFFF4382100104E8000203821FFF08102801442
+S32500012AC0810800047D0341D638A003E87D482BD741810008394000017C0903787C095040E8
+S32500012AE040800010392900017C0950404180FFF8382100104E8000207FE802A697E1FFF002
+S32500012B00806280284BFFD6F580A2801480E5000038E7000190E500004BFFECA18102823053
+S32500012B207C0800004182000C7D0803A64E80002183E100007FE803A6382100104E80002053
+S32500012B407FE802A697E1FFB88142801480CA000838E003E87CC63BD690CA00044BFFD67D36
+S32500012B60906100443860000A4BFFFF154BFFD66D808100447CE4185090E100447C07000047
+S32500012B80408000084BFFFFD83861002881028014810800049101000848009D69386100203F
+S32500012BA0810280148108000C5504103A7D0822145508083C38A003E87D082BD69101000880
+S32500012BC048009D253861003039010008392100288089000080A900049088000090A80004CD
+S32500012BE038A1001038C10020810600008126000491050000912500044800A0DD38610028C4
+S32500012C00810100445508103A9101000848009CD93861003838C10008390100308128000004
+S32500012C208088000491260000908600043881001038A1002880C500008105000490C40000C3
+S32500012C40910400044800935939010004392100388089000080A900049088000090A8000446
+S32500012C6048009DD581428014906A0004810A00047C0800004082000C38800001908A000486
+S32500012C8080AA000C38C000047CA533D638E000327CA53BD63865FFFF906280284BFFD55DA4
+S32500012CA083E100007FE803A6382100484E8000207FE802A697E1FFE89061001C7C0903788F
+S32500012CC080A282347C09280040800060912100145523103A38C226107C6332148063000088
+S32500012CE08101001C910100084800A779812100147C030000408200245523103A38822690E0
+S32500012D007C6322148063000083E100007FE803A6382100184E8000203929000180A28234A6
+S32500012D207C0928004180FFA87C03037883E100007FE803A6382100184E8000207FE802A69B
+S32500012D4097E1FF28816100E03CE0002090E100A87C0300004182021080E280A080E7000079
+S32500012D6090E1000838E100B490E1000C48002AA9814100A87C030000418100183860FFFF15
+S32500012D8083E100007FE803A6382100D84E800020980A0000386100B49141000838A003FFF6
+S32500012DA090A1000C48001FA57C6A1B787C030000418100183860FFFF83E100007FE803A6E7
+S32500012DC0382100D84E80002080A100A87CA51A1498050000806100A838630400810100A8C6
+S32500012DE09101000838CA000190C1000C4800A175808100A8396404007D6A5B787D6C5B78B4
+S32500012E00888A00007C8407747C04000041820028890A00007D0807742C08000D4082011804
+S32500012E20394A0001888A00007C8407747C0400004082FFE0980B00007D83637838E10020A2
+S32500012E4090E10008388000209081000C38C2886B90C1001048005EF1906100AC7C0A03787A
+S32500012E60808100AC7C0A200040800044914100B05543103A38A100207C632A148063000097
+S32500012E8038E0003D90E1000848009E8181828234814100B07C03000040820028394A0001DE
+S32500012EA0808100AC7C0A20004180FFC47C03037883E100007FE803A6382100D84E800020A7
+S32500012EC039630001980300005547103A390100207CE7421480E700007CE758502C07001DF8
+S32500012EE0418000185546103A38A100207CC62A1480C600009806001B5587103A38A226105F
+S32500012F007CE72A145546103A38A100207CC62A1480C6000090C700005588103A38C2269037
+S32500012F207D08321491680000388C0001908282344BFFFF6C888A00007C8407742C040009BE
+S32500012F404082000C38E0002098EA00007D685B78396B0001892A00007D29077499280000F0
+S32500012F604BFFFEC07C0B00004182005C7D635B7890010008388003FF9081000C4800A5BDCF
+S32500012F807C030000408200183860FFFF83E100007FE803A6382100D84E8000203862885036
+S32500012FA0480009C1806100A880E100E090E100084800A449806100A84800A4117C6A1B7881
+S32500012FC04BFFFE144BFFD5C190610018806100A880C1001890C100084800A421806100A8D4
+S32500012FE04800A3E97C6A1B784BFFFDEC7FE802A697E1FFD89061002C8121003088A90000CC
+S325000130007CA507742C050020408200183929000188A900007CA507742C0500204182FFF0AF
+S325000130207C0A03789141001C2C0A0006408000C0888900007C8407747C04000040820018F8
+S325000130403860FFFF83E100007FE803A6382100284E8000203889000188A900007CA5077461
+S3250001306098A10024890400007D0807747C080000408200183860FFFF83E100007FE803A6F7
+S32500013080382100284E8000203904000191010020888400007C840774988100259801002646
+S325000130A03861002490010008388000109081000C48009EB58141001C812100208101002CE5
+S325000130C07D08521498680000890900007D0807742C08003A4082000839290001394A00014D
+S325000130E09141001C2C0A00064180FF487C03037883E100007FE803A6382100284E800020BA
+S325000131007FE802A697E1FFB87C691B783861002C3902886D910100089121000C81010050D3
+S3250001312091010010480007F97C09037880C282347C093000408000489121001C5523103A59
+S3250001314038E226107C633A14806300003881002C9081000838C0001C90C1000C4800A1F5BB
+S325000131608121001C7C030000418200283929000180C282347C0930004180FFC07C03037896
+S3250001318083E100007FE803A6382100484E80002081010054900800345525103A388226904F
+S325000131A07CA5221480A5000090A1002880E1002888E700007CE707747C07000041820040D7
+S325000131C080C1002888C600007CC607742C0600204182035080E1002888E700007CE7077436
+S325000131E02C0700094182033C80C1002888C600007CC607747C060000408200183860000121
+S3250001320083E100007FE803A6382100484E80002080610028388288729081000838C00005D1
+S3250001322090C1000C4800A12D814100547C030000408200D48101002839080005910100283F
+S325000132407D49537838CA001B7C0930404080002C80A1002888A500007CA507747C05000045
+S325000132604182001880C1002888C600007CC607742C0600204082005C9809000080810028BE
+S32500013280888400007C8407747C0400004182FF2081010028890800007D0807742C080020AF
+S325000132A0408200084BFFFF0880810028888400007C8407742C040009408200084BFFFEF001
+S325000132C080A1002838A5000190A100284BFFFFB080E1002888E700007CE707742C0700095C
+S325000132E04182FF9880A10028388500019081002888A500007CA5077498A9000039290001C0
+S325000133004BFFFF448061002838E2887890E10008388000059081000C4800A0397C03000003
+S3250001332040820028806100283863000539010028910100089001000C48009C2D80A10054D4
+S325000133409065001C4BFFFF388061002838A2887E90A1000838E0000490E1000C48009FF53D
+S325000133607C03000040820028806100283863000438C1002890C100089001000C48009BE952
+S3250001338081010054906800204BFFFEF480610028390288839101000838A0000490A1000CFA
+S325000133A048009FB17C03000040820028806100283863000438810028908100089001000CC6
+S325000133C048009BA580C10054906600244BFFFEB08061002838C2888890C10008390000050D
+S325000133E09101000C48009F6D7C03000040820028806100283863000538E1002890E1000808
+S325000134009001000C48009B6180810054906400284BFFFE6C806100283882888E90810008AD
+S3250001342038C0000390C1000C48009F29812100547C0300004082003C3869002C80A1002894
+S3250001344038A5000390A100084BFFFBA52C03FFFF4082FE2C806100543863002C90010008B4
+S32500013460388000069081000C480098C54BFFFE1080C900342C0600084080FE0480A9003497
+S3250001348054A520367CA54A143945003881010028890800007D0807747C0800004182001807
+S325000134A080E1002888E700007CE707742C07002040820018980A000080C9003438C60001E4
+S325000134C090C900344BFFFDB881010028890800007D0807742C080009408200084BFFFFD8F6
+S325000134E07D445378394A000180A10028390500019101002888A500007CA5077498A400006E
+S325000135007CE9505081090034550820367CE8385038E7FFC82C07000F4180FF744BFFFF9805
+S325000135208101002839080001910100284BFFFC947FE802A697E1FFF09061001480C1001830
+S3250001354090C100084BFFDA118061001480A1001890A100084800729183E100007FE803A6B0
+S32500013560382100104E8000207FE802A697E1FFD0386295484BFFF73D7C691B787C090000A5
+S32500013580418200247D234B789121002C38A2955B90A1000848009C7D8121002C7C0300004B
+S325000135A04182009C3C80FFC260841054908282F4900100247C090000418200187D234B78E0
+S325000135C0900100089001000C4800999D90610024900100283862955F4BFFF6D981210028F1
+S325000135E07C03000041820014900100089001000C480099757C691B787C090000408200081B
+S32500013600392025808061002491210008388281909081000C38C281D890C100103D00FFC24C
+S325000136206108374C910100144BFFD86183E100007FE803A6382100304E8000203CE0FFC2A6
+S3250001364060E7363090E282F44BFFFF687FE802A697E1FFF09061001480C1001870C8007F92
+S32500013660910100182C08001040820010386295644800037981010018806100149101000803
+S3250001368048006A4D83E100007FE803A6382100104E8000207FE802A697E1FFE090610024DE
+S325000136A09001001880C2801480C6000090C100148101002C7C0800004182001C80A2801412
+S325000136C080A5000080C100147CA62850280500FA4181010480628190480069517C691B7874
+S325000136E02C03FFFF408200084BFFFFC82C03000D408200083920000A2C09007F40820008D4
+S32500013700392000089121001C2C090015408200C03900000A99010013386100133880000152
+S325000137209081000880C282F47CC803A64E80002181810024816100288141001C812100180D
+S325000137402C0A0008408200187C0900004081FF5838E9FFFF90E100184BFFFF4C2C0A000A30
+S32500013760408200207CEC4A14980700007D234B7883E100007FE803A6382100204E800020BD
+S325000137802C0A0015408200183860FFFF83E100007FE803A6382100204E8000207C095800AF
+S325000137A0408200187D635B7883E100007FE803A6382100204E8000203909000191010018AD
+S325000137C07C8C4A14994400004BFFFEDC992100134BFFFF483860FFFE83E100007FE803A614
+S325000137E0382100204E8000207FE802A697E1FFE090610024808100289804000080E100308A
+S325000138007C0700004182001880810030888400007C8407747C040000408200FC7C06037850
+S3250001382090C10018808100187C040000418200683862956780C1002490C1000880810030CF
+S325000138409081000C4800011D8061002880E1002C90E1000880C1001890C1000C4BFFFE3998
+S325000138607C691B782C03FFFE4182008C2C03FFFF4182FFB48101002C7C0940004180002C4B
+S3250001388038629580480000DD808100187C0400004082FFA03862957980E1002490E10008AD
+S325000138A0480000C14BFFFFA47C0900004082001080E100187C070000408200187C030378E4
+S325000138C083E100007FE803A6382100204E8000208061002880A1003090A1000848009B1D73
+S325000138E07C03037883E100007FE803A6382100204E8000203862957E38800001908100086D
+S3250001390080C282F47CC803A64E8000217C0903784BFFFF6438C000014BFFFF087FE802A606
+S3250001392097E1FFE89061001C38C3010090C10008808100209081000C38E1002038E7000425
+S3250001394090E10010480007F18081001C7C64185083E100007FE803A6382100184E80002067
+S325000139607FE802A697E1FEE09061012480E282F47C070000408200187C03037883E1000032
+S325000139807FE803A6382101204E8000203861002038C1002038C6010090C1000881010124D7
+S325000139A09101000C38C1012438C6000490C1001048000785390100207C881850386100208E
+S325000139C09081001C90810008810282F47D0803A64E8000218061001C83E100007FE803A613
+S325000139E0382101204E8000207FE802A697E1FEE0812282F4906101247C0900004182007408
+S32500013A003862958F38800007908100087D2803A64E8000213861002038A1002038A501003C
+S32500013A2090A1000880E1012490E1000C38A1012438A5000490A10010480006FD38E100209F
+S32500013A407D071850386100209101000880E282F47CE803A64E8000213862959738800001CD
+S32500013A609081000880C282F47CC803A64E8000214BFFC7154BFFC70D4BFFFFFC7FE802A6FA
+S32500013A8097E1FFE0808280148124002038C0000190C90030808908403FE0FFFF63FFFFFE1E
+S32500013AA07FE4203990890840B0090968B0090964B0090960B0090962B0090966B009095210
+S32500013AC0B0090950B0090954B009095690090ABC90090AB8B0090AC29121001C90090AC42B
+S32500013AE04BFFC6998101001C3CA0000060A58001B0A809C080C1001CA0C609C070C6000132
+S32500013B00418200184BFFC67580C1001CA0C609C070C600014082FFF0386281E038E2B3C83A
+S32500013B2090E10008388004009081000C480065E9386281E03CC0FA2060C6240090C10008E2
+S32500013B40390004009101000C480065F183E100007FE803A6382100204E8000207FE802A6FB
+S32500013B6097E1FFE89061001C4BFFC639906100108102801481080020910100144BFFC5FD16
+S32500013B8081010014A10809C071080001418200184BFFC5E981010014A10809C07108000147
+S32500013BA04082FFF08081001C5484402E80A1002054A520367C842B7880C1002454C6083CF4
+S32500013BC07C8433786084000180A10014B08509C04BFFC5A980E10014A0E709C070E7000146
+S32500013BE0418200184BFFC59580E10014A0E709C070E700014082FFF0806100104BFFC5C1B0
+S32500013C0083E100007FE803A6382100184E8000203821FFE85465183838A5FFF8810100200B
+S32500013C20710800075508183880E1002470E700077D083B787D0B283080E280148127002097
+S32500013C4080E90AEC390000FF7D0828307D0840F87CE740387CE75B7890E90AEC382100183B
+S32500013C604E8000207FE802A697E1FFE080E2801480E7002039270A209121001C80E90000AB
+S32500013C8070E70030418200543860000538C0000490C100089001000C4BFFFEC53860000744
+S32500013CA039000004910100089001000C4BFFFEB1386000014BFFEDC980A1001C80E5000055
+S32500013CC03FE0FFFF63FFFFCF7FE7383990E50000386000044BFFCA9983E100007FE803A687
+S32500013CE0382100204E8000207FE802A697E1FFE07C681B78386281E0900100085507183839
+S32500013D0090E1000C90010010480065997C681B789061001C7C030000408200103862833B0B
+S32500013D204BFFFCC98101001C7D03437883E100007FE803A6382100204E8000207FE802A6AA
+S32500013D4097E1FFE89061001C7C030000418200384BFFC4298121001C386281E07528E00009
+S32500013D603CA020007C0828004182002C7D274B7890E1000880810020548418389081000C5F
+S32500013D80480063B983E100007FE803A6382100184E8000203FE0FFFF63FFFFFF7FE7483981
+S32500013DA04BFFFFD07FE802A697E1FFE83E0000006210900081E1002481C100207C6A1B78D4
+S32500013DC091C3000C9061001C80E300007C070000408200247DC373784BFFFF113E000000E0
+S32500013DE06210900081E1002481C100208141001C906A000080C1002838C6000F3FE0FFFF67
+S32500013E0063FFFFF07FED3039808A00047C0400004082002C91A100287C6E69D64800518558
+S32500013E203E0000006210900081E1002481C1002081A100288141001C906A000480CA0000E3
+S32500013E407C060000418201A880AA00047C0500004182019C80AA000474A5E0003CC020001B
+S32500013E607C05300041820174808A00047C8C23787C0B03787C0B700040800044556418389B
+S32500013E8080EA00007C843A14B004000255661838808A00007CC622149186000455651838FB
+S32500013EA0810A00007CA54214B20500007D8C6A14396B00017C0B70004180FFC4556818388E
+S32500013EC080CA00007D083214A0A8FFF860A52000B0A8FFF8900A000891EA0020808A0010BC
+S32500013EE07C040000408200187DE37B784BFFFDFD81E100248141001C906A0010810A0014BD
+S32500013F007C0800004082001855E3103A4800509581E100248141001C906A001480EA0010A1
+S32500013F207C070000418200A080CA00147C060000418200947C0B03787C0B7800408000504C
+S32500013F405567103A80AA00147CE72A14900700005564183880EA00107C843A149004000475
+S32500013F6055661838808A00107CC62214B00600025568183880CA00107D083214B0080000FB
+S32500013F80396B00017C0B78004180FFB855651838810A00107CA54214A0E5FFF860E72000FF
+S32500013FA0B0E5FFF8900A0018900A001C900A00247C03037883E100007FE803A63821001869
+S32500013FC04E8000203860FFFF83E100007FE803A6382100184E800020808A00043FE0FFFF58
+S32500013FE063FFFFFF7FE420394BFFFE843860FFFF83E100007FE803A6382100184E80002069
+S325000140003821FFF0818282D0816100187C6A1B782C0B00094082005C7D8B6378388C00087C
+S325000140203FE0FFFF63FFFFF87FEC20397D675B78396B0001918282D07C07600040800014C7
+S32500014040808A0000810A00047C0440404180000C382100104E80002080EA000039270001D1
+S32500014060912A000038800020988700004BFFFFC080A30000808300047C0520404080001C97
+S325000140808103000039280001912300009968000038AC000190A282D02C0B000A408200080A
+S325000140A0900282D0382100104E800020814283E07C6907747D26077470C6007F7CC90774A5
+S325000140C07D24077438C285A87C843214888400007C8407747C0400004082002C2C0A001E07
+S325000140E04180000C386000014E8000207D26077438E285A87CC63A14390A0001910283E036
+S32500014100994600007D250774390285A87CA5421488A500007CA5077454A5103A38C284D063
+S325000141207CA5321480E1000890E500007C0303784E8000207FE802A697E1FFC890610018F4
+S3250001414080E1004090E1001C80810048908100208141004438EA000190E10044894A0000FF
+S325000141607D4A07742C0A0025418200487C0A00004082003080A1001880E1001C7C05384069
+S325000141804080000C80810018980400008061001883E100007FE803A6382100384E800020AB
+S325000141A038610018914100084BFFFE594BFFFFA49001002438A0FFFF90A100289001002C3E
+S325000141C03967000191610044894700007D4A07747C0C03782C0A002D4082001C39800001F1
+S325000141E07D6A5B78396B000191610044894A00007D4A07742C0A00304180000C2C0A00396C
+S325000142004081010C7C0C00004182001080A100247D050050910100242C0A002E41820084F6
+S325000142207C0A00004082000C38CBFFFF90C100443861001838A285A87146007F7CA5321438
+S3250001424088A500007CA5077454A5103A38C284D07CA5321480A500007CA803A64E800021B5
+S325000142607C0300004080002C7CA300508081002C7C852B7890A1002C81410044396A000185
+S3250001428091610044894A00007D4A07744BFFFF9480E100207CE71A1490E100204BFFFEB450
+S325000142A07D6A5B78396B000191610044894A00007D4A07742C0A00304180FF682C0A003950
+S325000142C0408100084BFFFF5C808100287C040000408000089001002880C1002854C5103A73
+S325000142E07CC62A1454C6083C7CC6521438C6FFD090C100287D6A5B78396B00019161004456
+S32500014300894A00007D4A07744BFFFFAC810100245507103A7D083A145508083C7D085214E1
+S325000143203908FFD0910100247D6A5B78396B000191610044894A00007D4A07744BFFFEB806
+S325000143407FE802A697E1FFE0906100244800907D7C6A1B789061001C80E1002C7C070000F0
+S325000143604180003C9141001C80C1002C7C0A30004080002C80610028388000209081000842
+S325000143804BFFFC8180C1001C394600019141001C80C1002C7C0A30004180FFDC81610024BF
+S325000143A07D665B78396B00019161001488C600007CC607747C0600004182003480E1003080
+S325000143C07C0700004182FFDC8061002890C100084BFFFC31816100148141001C8101003056
+S325000143E03908FFFF910100304BFFFFB880C1002C7C0600004080004880A1002C7D0500509E
+S325000144009101002C9141001C80A1002C7C0A28004080002C80610028390000209101000806
+S325000144204BFFFBE180A1001C394500019141001C80A1002C7C0A28004180FFDC83E10000AA
+S325000144407FE803A6382100204E8000207FE802A697E1FFA881C282E881A100607C6C1B7806
+S325000144607C0F037880C3001470C600072C0600044181015C418201442C060001418201281F
+S325000144802C0600024182010080AC00088145000038E0000490E1002880CC001470C60004D4
+S325000144A04082000C7C0A0000418000D0980100573960001C7FEA6B967FFF69D67CFF505029
+S325000144C0392700302C09003940810014392900277C0E0000418200083929FFE038C1003AB0
+S325000144E07CC65A14992600002C0B0002408000547C0F0000418200183881003A396BFFFFFE
+S325000145007C845A1438A0002D98A400003861003A7C635A149181000880EC000C90E1000CB6
+S3250001452038E0FFFF90E100104BFFFE198061002883E100007FE803A6382100584E80002060
+S325000145407D4A6B96810C00107C0800004180001880EC00103900001E7CE740507C0B38000D
+S32500014560408000107C0A0000418100084BFFFF84396BFFFF4BFFFF407D4A005039E00001EB
+S325000145804BFFFF2C80AC000880A500007CA907347D2407347C8A2378388000049081002874
+S325000145A04BFFFEF8808C00088144000038C0000490C100284BFFFEE4810C000881480000DC
+S325000145C038A0000490A100284BFFFED02C060005418200302C060006418200084BFFFEAC66
+S325000145E080AC000880A500007CA907345524043E7C8A237838800004908100284BFFFE9CC6
+S3250001460080E300088147000038800004908100284BFFFE887FE802A697E1FFE87C671B78B7
+S32500014620386280B890E100089001000C3880FFFF908100104BFFFD0D7C03037883E1000002
+S325000146407FE803A6382100184E8000207FE802A697E1FFE07C681B7880E3000880E7000035
+S3250001466098E1001E9801001F3861001E910100088088000C9081000C3880FFFF908100108B
+S325000146804BFFFCC13860000483E100007FE803A6382100204E8000207FE802A697E1FFF01F
+S325000146A03900000A910100084BFFFDA583E100007FE803A6382100104E8000203860FFFECA
+S325000146C04E8000203860FFFF4E8000207FE802A697E1FFF038E0000890E100084BFFFD719A
+S325000146E083E100007FE803A6382100104E8000207FE802A697E1FFE87C671B788063000819
+S325000147008063000090E100088107000C9101000C81070010910100104BFFFC2938600004BF
+S3250001472083E100007FE803A6382100184E8000203860FFFC4E8000207FE802A697E1FFF0A8
+S3250001474038A0001090A100084BFFFD0583E100007FE803A6382100104E8000207FE802A60B
+S3250001476097E1FFE839000001910282E838C0001090C100084BFFFCD9900282E883E10000BC
+S325000147807FE803A6382100184E8000207FE802A697E1FFF038E0002590E100084BFFF865D0
+S325000147A07C03037883E100007FE803A6382100104E8000207FE802A697E1FFD89061002CB2
+S325000147C03862889880A1003090A100084BFFF19581A100308181002C3942A1F83902A1F856
+S325000147E0390801407C0A40404080003080CA00047C0D30004082001080EA000C7C0C38002B
+S32500014800418201B4394A00143902A1F8390801407C0A40404180FFD83962A1F838C2A1F8C7
+S325000148203946001438C2A1F838C601407C0A30404080002C808A0000810B00007C044000D4
+S32500014840418100087D4B5378394A001438C2A1F838C601407C0A30404180FFDC7D6A5B783F
+S3250001486080CC001480EC00107D6639D69141002480CA00087C0600004182011480AA001087
+S325000148807C055800418001089161001C916A0010386288BD80AC000C7CAD2A14810C00103A
+S325000148A07CA541D690A100084BFFF0B98141002C806A000080EA000C812100307CE93A14BA
+S325000148C080AA00107CE729D690E1000880AA00087CA803A64E8000218141002C7C03000061
+S325000148E040800020386288CF4BFFF0797C03037883E100007FE803A6382100284E80002050
+S32500014900806A00008101002481080008910100088101001C9101000C80CA00047CC803A65E
+S325000149204E800021816100308141002480A1001C7C03280041820020386288E14BFFF02560
+S325000149407C03037883E100007FE803A6382100284E8000208082801480840000908A0000BF
+S3250001496080C1002C90CA000C916A0004386288F3916100084BFFEFED8061002483E10000C0
+S325000149807FE803A6382100284E8000207D635B789161001C90010008480045818161001C2B
+S325000149A08141002481A100308181002C906A00084BFFFED89141002480A2801480A5000097
+S325000149C090AA0000386288A791A100084BFFEF958061002483E100007FE803A638210028CB
+S325000149E04E8000207FE802A697E1FFD89061002C3862890580E1003090E100084BFFEF6577
+S32500014A00816100308141002C2C0B0002418001AC80EA00347C0B3800408001A0810A003867
+S32500014A202C08000C418201802C080010418200183860FFFF83E100007FE803A63821002841
+S32500014A404E800020556B083C810A0030812A00107D0849D6916100247C0B40404180001451
+S32500014A60386289114BFFEF85816100248141002C808A001080EA00147C8439D67C8B2396E2
+S32500014A80810A00147C8441D680EA003C7C843A1480EA0010810A00147CE741D67FEB3B9697
+S32500014AA07FFF39D67CFF585090E100187D43537890810020908100084BFFFCFD8181002C70
+S32500014AC07C6A1B7880C3000881010018396800017CC6421488C6000090C1002480CC001018
+S32500014AE080EC00147CC639D67C0B3000418000287D836378808C001480A100207C852214CB
+S32500014B00908100084BFFFCB18181002C7C6A1B787C0B0378810A00087D085A1489080000BE
+S32500014B205508402E808100247C8A437880EC00382C07000C4082002080C1003070C6000150
+S32500014B404182005C554AE13E280A0FF841800008614AF0003CE0000060E7FFF87C0A38407C
+S32500014B60408000347D4453783862891880A1003090A10008908100249081000C4BFFEDE57B
+S32500014B808061002483E100007FE803A6382100284E8000203880FFFF4BFFFFD0714A0FFF8E
+S32500014BA04BFFFFA85567083C7D0B3A14392000027D684BD64BFFFE943860FFFF83E10000F0
+S32500014BC07FE803A6382100284E8000207FE802A697E1FFD87C691B7881030000910100243F
+S32500014BE03862892A9121002C390900049101000880C1003090C1000C4BFFED6981A1002CE7
+S32500014C008181003081610024808D00147C04000040820070810B00107D0C41D680CB0014E7
+S32500014C207D0831D680AB002454A528347C082800418000183860FFFF83E100007FE803A6AE
+S32500014C40382100284E800020808B004080AB00147CAC29D67C842A143862893D9181000875
+S32500014C60908100209081000C4BFFECF98061002083E100007FE803A6382100284E800020CC
+S32500014C80808D001C7C0C20004180001080AD00187C050000408200A87C0A0378812D001478
+S32500014CA0914100207C0A6000418200507D635B78912100084BFFFD3181A1002C818100309D
+S32500014CC0816100247C691B787C030000408000183860FFFF83E100007FE803A6382100286D
+S32500014CE04E80002080C1002039460001914100207C0A60004082FFB8914D001C912D0018BD
+S32500014D0038E9FFFE80CB00147CE731D680AB00447CE53A14386289509181000890E1002069
+S32500014D2090E1000C4BFFEC3D8061002083E100007FE803A6382100284E800020814D001CAE
+S32500014D40812D00184BFFFF5C7FE802A697E1FFC87C6A1B788903000F7108001040820050E4
+S32500014D60808A0020810A00107C044000418000187C03037883E100007FE803A638210038CF
+S32500014D804E80002080EA0020810100447CE74214808A00107C07200040810014810A0010E8
+S32500014DA0812A00207D09405091010044810100409101001C7C0B03789161003080E10044FC
+S32500014DC07C0B38004080010C7D43537880CA00209141003C80EA000080E700187CC63BD601
+S32500014DE090C100084BFFFDE97C6A1B787C030000408000183860FFFF83E100007FE803A649
+S32500014E00382100384E8000208061003C80630000914100084BFFF9A18181003C7C03000091
+S32500014E20408200183860FFFF83E100007FE803A6382100384E80002080CC002080EC000030
+S32500014E4080E700187FE63BD67FFF39D67D5F3050810300087DA8521480C1004480810030A0
+S32500014E607D64305080EC000080E700187CEA38507C0B380040810010810C00008108001833
+S32500014E807D6A40508061001C91A100089161002C9161000C480080CD8161002C8141003CA0
+S32500014EA080E1001C7CA75A1490A1001C808A00207CE45A1490EA002080E100307D675A141B
+S32500014EC09161003080E100447C0B38004180FEFC7D635B7883E100007FE803A638210038D2
+S32500014EE04E8000207FE802A697E1FFC08883000F7084001040820020386289634BFFEA6558
+S32500014F003860FFFF83E100007FE803A6382100404E8000209061004480C1004890C10008E2
+S32500014F2048000EA981210044900900207D234B78388100209081000838E0002090E1000CC2
+S32500014F404BFFFE092C030020408201103862897B388100209081000838C1002038C6000828
+S32500014F6090C1000C4BFFE9FD806100443863000438A1002090A1000838E0000890E1000C0A
+S32500014F8048008549812100447C030000418200084BFFFF9C3869000C38C1002038C6000813
+S32500014FA090C10008390000039101000C4800851D812100447C030000418200084BFFFF70E4
+S32500014FC088A1002B70A500084182002838628995388100209081000838C1002038C60008A5
+S32500014FE090C1000C4BFFE97D812100444BFFFF4088A1002B98A9000F88E1003B54E7402E3D
+S325000150008901003A7CE7437890E900148881003F5484402E88A1003E7C842B785484801E0C
+S3250001502088A1003D54A5402E88C1003C7CA533787C842B7890890010900900189009001C19
+S32500015040900900203860000183E100007FE803A6382100404E8000207C03000041800018A4
+S325000150607C03037883E100007FE803A6382100404E8000203860FFFF83E100007FE803A62A
+S32500015080382100404E8000207FE802A697E1FFD07C6D1B7880E1003890E3000C38C002009E
+S325000150A090C3001038800001908300147C0903787DA36B7891A100349121001C91210008B5
+S325000150C04BFFF6F581A100347C6A1B787C03000040820020386289AD4BFFE8893860FFFF43
+S325000150E083E100007FE803A6382100304E80002081030008890801FE2C08005540820380D4
+S3250001510080C3000888C601FF2C0600AA408203709003000C8123000880C1003C7C06000094
+S3250001512041820010890900152C0800F8408201E8812A000888A900002C0500E9418200381E
+S3250001514088C900002C0600EB4082001088E900022C07009041820020386289CD4BFFE805C8
+S325000151603860FFFF83E100007FE803A6382100304E8000207D234B789121002C4800031DFE
+S325000151808141002C81210034888A000C5484402E88CA000B7C8433789089001088EA000D30
+S325000151A090E900148089001080A900147C8429D69089001888CA000F54C6402E890A000E4B
+S325000151C07CC6437890C9001C888A00109089002088CA001254C6402E890A00117CC643786E
+S325000151E090C9002488EA001454E7402E888A00137CE7237890E90028810900287C08000002
+S325000152004082003088EA002354E7402E88AA00227CE72B7854E7801E88CA002154C6402E29
+S32500015220890A00207CC643787CE7337890E90028888A00159089002C88CA001754C6402EAB
+S32500015240890A00167CC6437890C900308089001C9089003C8089002080A900307C8429D61D
+S3250001526080A9003C7C8522149089004080C9002454C6283480E900107CC63A143946FFFFC9
+S3250001528080C900107D4A33D680C900407CC6521490C900448089002880A900447C85205001
+S325000152A080A900147C842BD6388400029089003480C900342C060FF74080005038E0000CB5
+S325000152C090E9003839000002910900489129004C9009006090090068900900649009006CF7
+S325000152E038A0001098A9005B81090024550828349109005C7C03037883E100007FE803A658
+S32500015300382100304E80002038A0001090A900384BFFFFB4808A0008392401BE3980FFFFD4
+S325000153207C0B03782C0B000440800064890900042C0800544082000C3920003F4BFFFD74C6
+S3250001534088A900042C0500014182001088C900042C0600044082011889090000710800801B
+S32500015360418200A88889000B5484402E88E9000A7C843B785484801E890900095508402E4F
+S3250001538088A900087D082B787C8C43782C0B0004408200183900FFFF7C0C40004082000C00
+S325000153A0900A000C4BFFFD8C80C1001C7CC6621490CD000C7DA36B78900100084BFFF3F91D
+S325000153C07C6A1B787C0300004182001480E3000888E701FE2C070055418200183860FFFF25
+S325000153E083E100007FE803A6382100304E80002080A3000888A501FF2C0500AA4082FFE0E7
+S32500015400900A000C4BFFFD2C88E9000B54E7402E88A9000A7CE72B7854E7801E88C90009D3
+S3250001542054C6402E890900087CC643787CE733787C0760404080002C88C9000B54C6402E45
+S325000154408889000A7CC6237854C6801E88A9000954A5402E88E900087CA53B787CCC2B78BC
+S32500015460396B0001392900104BFFFEBC88E900042C0700064082FFEC4BFFFEE0386289C4A0
+S325000154804BFFE4E13860FFFF83E100007FE803A6382100304E8000207FE802A697E1FFE807
+S325000154A07C691B78386289E1888900009081000888C9000190C1000C9121001C890900022E
+S325000154C0910100104BFFE49D38628A0180A1001C38A5000390A100084BFFE4898121001C68
+S325000154E038628A138909000C5508402E88A9000B7D082B78910100084BFFE46938628A212B
+S3250001550080E1001C88E7000D90E100084BFFE4558121001C38628A308889000F5484402E17
+S3250001552088C9000E7C843378908100084BFFE43538628A3C8101001C8908001091010008A5
+S325000155404BFFE4218121001C38628A4788A9001254A5402E88E900117CA53B7890A1000893
+S325000155604BFFE4018121001C38628A55888900145484402E88C900137C843378908100082B
+S325000155804BFFE3E138628A628101001C89080015910100084BFFE3CD8121001C38628A7640
+S325000155A088A9001754A5402E88E900167CA53B7890A100084BFFE3AD8121001C38628A8362
+S325000155C0888900195484402E88C900187C843378908100084BFFE38D8121001C38628A90FB
+S325000155E08909001B5508402E88A9001A7D082B78910100084BFFE36D8121001C38628A9C07
+S3250001560088E9001F54E7402E88A9001E7CE72B7854E7801E88C9001D54C6402E8909001C78
+S325000156207CC643787CE7337890E100084BFFE3358121001C38628AA988A9002354A5402E37
+S32500015640890900227CA5437854A5801E888900215484402E88C900207C8433787CA52378CC
+S3250001566090A100084BFFE2FD38628AB98101001C89080024910100084BFFE2E938628AC6F8
+S3250001568080A1001C88A5002590A100084BFFE2D538628ADA80E1001C88E7002690E10008B1
+S325000156A04BFFE2C18121001C38628AEC8889002A5484402E88E900297C843B785484801EE4
+S325000156C0890900285508402E88A900277D082B787C844378908100084BFFE28938628AFC15
+S325000156E080E1001C38E7002B90E100084BFFE27583E100007FE803A6382100184E800020EF
+S325000157007FE802A697E1FFE8816100207C691B7888C900007CC607742C06002F4082001851
+S325000157203929000188C900007CC607742C06002F4182FFF088A900007CA507747C05000090
+S32500015740418200C088C900007CC607742C060020418200B07C0A037888A900007CA507741E
+S325000157607C0500004182001488C900007CC607742C06002F4082001C980B00007D234B7877
+S3250001578083E100007FE803A6382100184E80002088E900007CE707742C0700204082001CAF
+S325000157A0980B00007D234B7883E100007FE803A6382100184E8000202C0A001C40820020D5
+S325000157C038628B0E4BFFE19D7C03037883E100007FE803A6382100184E8000207D655B7845
+S325000157E0396B00017D264B783929000188C600007CC6077498C50000394A00014BFFFF5CA3
+S325000158007C03037883E100007FE803A6382100184E8000207FE802A697E1FFD080E1003CC1
+S325000158207C641B7838C0000380A4004C8104005090A7000080A400549107000490A7000824
+S3250001584038C6FFFF3884000C38E7000C7C0600004181FFD88061003838A1001490A10008F8
+S325000158604BFFFEA1906100387C030000418200508061003C38A1001490A100084BFFF66991
+S325000158802C03FFFF418200247C030000418200084BFFFFC47C03037883E100007FE803A628
+S325000158A0382100304E8000203860FFFF83E100007FE803A6382100304E8000203860000150
+S325000158C083E100007FE803A6382100304E8000207FE802A697E1FFA880E1006090E100086E
+S325000158E038C1003490C1000C4BFFFF2D814100602C03FFFF418204207C030000418203F82E
+S325000159002C030001418203B43860002090010008480036097C6B1B7838A0002038610034BF
+S3250001592090A1003090A10008916100289161000C4800040581410028810100307C03400002
+S3250001594041820020806282CC4BFFE0193860FFFF83E100007FE803A6382100584E80002041
+S3250001596088CA000054C6402E888A00017CC6237854C6801E88AA000254A5402E88EA00038E
+S325000159807CA53B787CC62B782C0606EB4182004C38628B7C890A00005508402E88CA0001C3
+S325000159A07D0833785508801E88EA000254E7402E888A00037CE723787D083B7891010008B3
+S325000159C04BFFDFA13860FFFF83E100007FE803A6382100584E80002088EA001454E7402E1E
+S325000159E088AA00157CE72B7854E7801E890A00165508402E892A00177D084B787CE74378D6
+S32500015A0074E7E0003C8020007C0720004182027488CA001454C6402E88EA00157CC63B7822
+S32500015A2054C6801E890A00165508402E88AA00177D082B787CC6437890C1002C890A0004B1
+S32500015A405508402E88CA00057D0833785508801E88EA000654E7402E888A00077CE72378BA
+S32500015A607D083B7838628BA791010030910100084BFFDEF13861003480A1003090A100084F
+S32500015A808101002C9101000C480002AD81610030814100287C03580041820020806282CCD6
+S32500015AA04BFFDEC13860FFFF83E100007FE803A6382100584E80002080E1002C7C8B3A146B
+S32500015AC038840FFF3FE0FFFF63FFF0007FE420399081002C88AA000854A5402E890A000950
+S32500015AE07CA5437854A5801E888A000A5484402E88CA000B7C8433787CA5237838628BAB36
+S32500015B0090A1003090A100084BFFDE593861003480E1003090E1000880A1002C90A1000C02
+S32500015B204800021581410028810100307C03400041820020806282CC4BFFDE293860FFFFAA
+S32500015B4083E100007FE803A6382100584E80002038628BAF88CA000C54C6402E888A000D52
+S32500015B607CC6237854C6801E88AA000E54A5402E88EA000F7CA53B787CC62B7890C100084F
+S32500015B80888A00145484402E88EA00157C843B785484801E890A00165508402E88AA001725
+S32500015BA07D082B787C8443789081000C4BFFDDB581410028890A00145508402E88CA00153F
+S32500015BC07D0833785508801E892A00165529402E888A00177D2923787D084B787508E000CF
+S32500015BE03CA020007C0828004182004888EA001454E7402E890A00157CE7437854E7801E1D
+S32500015C00888A00165484402E88CA00177C8433787CE723787CE803A64E8000217C03037807
+S32500015C2083E100007FE803A6382100584E80002088EA001454E7402E888A00157CE72378F6
+S32500015C4054E7801E88AA001654A5402E890A00177CA543787CE72B783FE0FFFF63FFFFFFAC
+S32500015C607FE738397CE803A64E8000217C03037883E100007FE803A6382100584E8000203D
+S32500015C8088CA001454C6402E890A00157CC6437854C6801E888A00165484402E88EA0017BB
+S32500015CA07C843B787CC623783FE0FFFF63FFFFFF7FE630394BFFFD8438628B4A38A10034BB
+S32500015CC038A5000490A1000838E1003438E7000C90E1000C888100439081001080810048F8
+S32500015CE09081001480E1004490E100184BFFDC754BFFFC1838628B3C914100084BFFDC658B
+S32500015D003860FFFF83E100007FE803A6382100584E80002038628B27914100084BFFDC4542
+S32500015D203860FFFF83E100007FE803A6382100584E8000207FE802A697E1FFD88161003043
+S32500015D409061002C80E1003490E100247C0A03787C0A580040800044392020007C8A5850EB
+S32500015D607C044800408000087D2A58508061002C808100249141001C7C845214908100089E
+S32500015D809121000C4BFFEFC58141001C906100207C030000418100187D43537883E1000009
+S32500015DA07FE803A6382100284E80002038628BC44BFFDBB1816100308081002080C1001C0E
+S32500015DC07D4622144BFFFF8C7FE802A697E1FFE0812100287C6B1B783943000488E9000053
+S32500015DE07CE707747C070000418200147CCB505038C6FFFC2C060008418001047CAB5050BD
+S32500015E0038A5FFFC2C050008408000247D455378394A000138C0002098C500007CAB505039
+S32500015E2038A5FFFC2C0500084180FFE4394B000C88A900007CA507747C05000041820014F1
+S32500015E407C8B50503884FFF42C0400034180005C7C8B50503884FFF42C0400034080002428
+S32500015E607D445378394A000138A0002098A400007C8B50503884FFF42C0400034180FFE4AA
+S32500015E8038628BC638AB000490A10008390B000C9101000C4BFFDACD83E100007FE803A69D
+S32500015EA0382100204E800020888900007C8407742C0400614180001488A900007CA50774B5
+S32500015EC02C05007A4081001C888900007C840774988A000039290001394A00014BFFFF5401
+S32500015EE0890900007D0807743908FFE0990A000039290001394A00014BFFFF3888C900008D
+S32500015F007CC607742C06002E4082000C392900014BFFFEEC88A900007CA507742C05006199
+S32500015F204180001488C900007CC607742C06007A4081001C88A900007CA5077498AA0000DF
+S32500015F4039290001394A00014BFFFE94888900007C8407743884FFE0988A000039290001CB
+S32500015F60394A00014BFFFE787FE802A697E1FFC8900100287C0A03782C0A00044080006074
+S32500015F8091410030554818387C8A4214548428347C88205038A2D7D07C642A149061003443
+S32500015FA09001000838E0011890E1000C48006D818061003080C1003490C100084BFFA6CDC1
+S32500015FC0816100347C0300004181002880810030394400012C0A00044180FFA880610028E1
+S32500015FE083E100007FE803A6382100384E8000207C0A03785547183838C282807CE7321415
+S3250001600080E700007C0700004182FFC4914100245543183838E282807C633A1480630000FF
+S32500016020916100084800743D81610034814100247C0300004182000C394A00014BFFFFB897
+S3250001604080810030908B00EC7D635B785548183838E282807D083A14810800047D0803A6B7
+S325000160604E8000217C030000418200084BFFFF603860400038A0000190A100089001000CB0
+S325000160809001001048003E5580E10034906700F43860400038C0000190C100089001000C36
+S325000160A09001001048003E3581410034906A00F839000001910A00F03880000180C10030A6
+S325000160C07C843030810100287D0423789081002838629A1180CA00EC90C100089141000CA8
+S325000160E0808A001C90810010808A0020908100144BFFD87181410034808A00247C040000CC
+S325000161004182002C38629A31808A00247484E0003D2020007C04480041820098810A0024CF
+S32500016120910100084BFFD83D8141003480CA00287C0600004182001438629A3E80AA0028DA
+S3250001614090A100084BFFD81D38629A4B4BFFD8157C0A03782C0A00064080003038629A4D5C
+S325000161609141002C80C100347CAA321488A5002C90A100084BFFD7ED80A1002C39450001CD
+S325000161802C0A00064180FFD838629A554BFFD7D54BFFAEB181410034806A0020810A00D0A1
+S325000161A0910100089141000C48004AC94BFFFE20810A00243FE0FFFF63FFFFFF7FE8403991
+S325000161C04BFFFF607FE802A697E1FFE82C03000440800080546618387CA3321454A528346A
+S325000161E07CA6285038C2D7D07CA5321480A500F07C0500004182005C546718387D033A1468
+S32500016200550828347D0740503922D7D07D484A1480AA00F02C0500014082002438C0000259
+S3250001622090CA00F07D43537891410014810A00BC7D0803A64E800021814100147D435378D7
+S3250001624083E100007FE803A6382100184E8000207C03037883E100007FE803A63821001885
+S325000162604E8000207FE802A697E1FFE84BFFFF597C030000408200187C03037883E1000062
+S325000162807FE803A6382100184E8000203863002C83E100007FE803A6382100184E800020EE
+S325000162A07FE802A697E1FFD84BFFFF1D906100207C030000408200187C03037883E100004B
+S325000162C07FE803A6382100284E80002080828014808400009081001880610020806300F49D
+S325000162E048003C357C6A1B787C0300004082005080A2801480A5000080E100187CA72850E5
+S3250001630054A4083C7CA5221454A518385484482C7CA5205038C000327CA5339680C1003434
+S325000163207C0530404180FFB47C03037883E100007FE803A6382100284E800020810300048C
+S32500016340812300007D094050806100309141001C808A000090810008910100249101000C06
+S3250001636048006C018061001C48003B118061002483E100007FE803A6382100284E800020E8
+S325000163807FE802A697E1FFE87C691B7880610020806300009121001C3889002C9081000858
+S325000163A038E0000690E1000C48007121812100207C03000041820028806900003902836826
+S325000163C09101000838A0000690A1000C480070FD812100207C030000408200288061001C24
+S325000163E0806300F49121000848003BA93860000183E100007FE803A6382100184E8000206D
+S3250001640080E100247C0700004182000C7D234B7848003A697C03037883E100007FE803A6E2
+S32500016420382100184E8000207FE802A697E1FFD89061002C4BFFFD917C030000408200184A
+S325000164407C03037883E100007FE803A6382100284E80002090610024806300F848003BC520
+S325000164602C0340004081002838629A5780A1002C90A100084BFFD4ED7C03037883E1000043
+S325000164807FE803A6382100284E800020386005F0480039919061002080630004810100302D
+S325000164A09101000880C1003490C1000C48006AB580610020806300043863000680E10024F4
+S325000164C038E7002C90E1000838A0000690A1000C48006A91812100208081003480C900044F
+S325000164E07C8622149089000480610024806300F89121000848003A9D4BFF9CA98121002432
+S325000165009061001C7D234B78810900CC7D0803A64E8000218061001C4BFF9CA53860000170
+S3250001652083E100007FE803A6382100284E8000207FE802A697E1FFF880A300EC54A7183899
+S325000165407CA53A1454A5103A3902A3387CA5421480A5000080C5000060C6003090C50000E0
+S325000165604BFF9C1983E100007FE803A6382100084E8000207FE802A697E1FFD89061002CD7
+S325000165808081002C808400EC548518387C842A145484103A38C2A3387D24321481090020E8
+S325000165A0550818389121002080C900187D08321491010018A1080000710880004082001CFF
+S325000165C08061002C806300F84800394D7C691B787C0300004082001483E100007FE803A6BD
+S325000165E0382100284E80002080A3000480C300007CA6285080610018806300049121001C73
+S32500016600810900009101000890A1002490A1000C4800695180C1001881010024B106000203
+S325000166204BFF9B5981210018A0A9000070A5200060A5DC00B0A900004BFF9B41808100205C
+S32500016640808400003D00000061088000B104000C4BFF9B298121002080C9002038C6000110
+S3250001666038E000047FE63BD67FFF39D67CDF305090C900208061001C480038018121002060
+S325000166804BFFFF1C7FE802A697E1FFC8808100409081001C80C400EC54C718387CC63A14A7
+S325000166A054C6103A3902A3387CC6421490C1002880A60000A0A5001090A100304BFF9ABDCB
+S325000166C0808100288084000081010030B10400104BFF9AA98181001C8141002881010030C8
+S325000166E0710800154182002438629BD880AC00EC90A1000880A1003090A1000C4BFFD265B1
+S325000167008181001C8141002881010030710800094082000480AA001454A5183880CA000C93
+S325000167207D65321491610024A0AB00007CA92B7870A58000408201247128003F408200C427
+S3250001674071250C002C050C00408200B8A0AB00023865FFFC90610034480036C98161002482
+S325000167607C0300004182004C9061002080630004808B000490810008808100349081000C12
+S32500016780480067E1812100208081003480C900047C862214908900048061001C9121000812
+S325000167A0390000019101000C4BFFFBD981610024B00B0002A08B0000708420006084900066
+S325000167C0B08B00004BFF99B58181001C8141002880AA001438A5000138C000207FE533D636
+S325000167E07FFF31D67CBF285090AA001480EA001454E71838810A000C7D6742144BFFFF28C1
+S32500016800712700044182001080CC010438C6000190CC01047124000241820010810C011049
+S3250001682039080001910C01107126003F4182001438629BF44BFFD12D816100244BFFFF7480
+S32500016840712808004082FF6C38629BF64BFFD115816100244BFFFF5C80E1003070E7000273
+S32500016860418200107D8363784BFFFD0D8141002880A1003070A50010418200183860000636
+S3250001688080EA000890E100089001000C4BFFD2D183E100007FE803A6382100384E80002089
+S325000168A07FE802A697E1FFE03DA0000061AD90007C6A1B78906100248103000C7C0800004E
+S325000168C04082001C386000204BFFD4213DA0000061AD900081410024906A000C80CA00101B
+S325000168E07C060000408200243C6000006063BE0090010008480026253DA0000061AD900065
+S3250001690081410024906A001080AA001074A5E0003CC020007C0530004182015C808A001046
+S325000169207C8C23787C0B03782C0B0020408000445567183880AA000C7CE72A14B0070002B4
+S325000169405564183880EA000C7C843A14918400045568183880CA000C7D083214B1A80000C3
+S32500016960398C05F0396B00012C0B00204180FFC45564183880EA000C7C843A14A0C4FFF8AE
+S3250001698060C62000B0C4FFF8900A001480CA00187C06000040820014386000044BFFD34DD1
+S325000169A081410024906A0018808A001C7C04000040820018386017C0900100084800255D86
+S325000169C081410024906A001C810A001C7508E0003D2020007C0848004182008880EA001C96
+S325000169E07CEC3B787C0B03782C0B00044080004855651838810A00187CA5421491850004F2
+S32500016A005564183880EA00187C843A14B004000255661838808A00187CC6221439005C00A6
+S32500016A20B1060000398C05F0396B00012C0B00044180FFC05567183880AA00187CE72A148F
+S32500016A40A087FFF860842000B087FFF8900A002083E100007FE803A6382100204E8000204A
+S32500016A6080EA001C3FE0FFFF63FFFFFF7FE738394BFFFF70808A00103FE0FFFF63FFFFFFE5
+S32500016A807FE420394BFFFE9C7FE802A697E1FFD080A3000454A5083C3985FFFE80A2801424
+S32500016AA08145002038A000037CAB6030A0CA09527CC75B78B0EA09527D6658F8A0AA0950B1
+S32500016AC07CA63038B0CA09507D6558F8A08A09547C852838B0AA095438E000307CEB603042
+S32500016AE07D6458F8A10A09627D042038B08A09627D6858F8A0EA09607CE84038B10A0960A2
+S32500016B00A0CA09647CC75B78B0EA0964906100348063000838E1002890E1000838810024D3
+S32500016B209081000C4BFF9BDD8061003480630004808100289081000880E1002490E1000C2F
+S32500016B404BFFD0D180A1003480A5000454A5103A38C283A87CA53214806500009061001C04
+S32500016B609001000838A000A490A1000C480061C13D8020008161001C8141003438800018B1
+S32500016B80988B000438E0001898EB000538A005F0B0AB0006810A000C7508E0007C08600009
+S32500016BA04182018480CA000CB0CB000080AA001874A5E0007C05600041820158810A0018DA
+S32500016BC0B10B00027C03037880AA000890A100089001000C4BFFCF8981A100388181003CB4
+S32500016BE08161001C38E0FFFF90EB00303CA0DEBB60A520E390AB0034900B0038900B003C39
+S32500016C00900B00403C80000060848888B08B004438E0000FB0EB004638A005EEB0AB004AEB
+S32500016C2039000040B10B004C38C005F0B0CB004E388005F0B08B0050B00B00787C0A0378AA
+S32500016C402C0A00064080003C7CEA621488E7000154E7402E7D0C5214890800007CE7437862
+S32500016C60392000027D0A4BD65508083C7D085850B0E80076394A00022C0A00064180FFCCE1
+S32500016C803900080AB10D00083CC0000060C6D555B0CD000E900D00043CC0108860C6000C9E
+S32500016CA090CD00004BFF94D580E100383C8000006084FFFFB08700104BFF94C180A1003847
+S32500016CC038E0001AB0E500144BFF94B1810280148168002081010034810800043908FFFFA1
+S32500016CE0392010007D284030808B0ABC7C87437890EB0ABC80CB0AB87CC44378908B0AB85A
+S32500016D0083E100007FE803A6382100304E800020810A00183FE0FFFF63FFFFFF7FE8403981
+S32500016D204BFFFEA080CA000C3FE0FFFF63FFFFFF7FE630394BFFFE747FE802A697E1FF7011
+S32500016D40906100943861008A9001000838A0000690A1000C48005FD93861008A8101009417
+S32500016D603908002C9101000838C0000690C1000C48006759812100947C030000408200909B
+S32500016D8038629BF84BFFCBDD3861001C39029C11910100084800666538629C1E38C1004EE8
+S32500016DA090C10008390000329101000C38C1001C90C100104BFFCA357C0300004080001854
+S32500016DC03860FFFF83E100007FE803A6382100904E800020806100943863002C3881004E88
+S32500016DE0908100084BFFC209812100947C0300004080001C88C9002C2C0600FF418200104C
+S32500016E0038629C304BFFCB5D4BFFFF8080E9001C54E7103A388280887CE7221480E70000FE
+S32500016E2080C2801480C600207D663A1480C9001C54C6103A38E280307CC63A1480C6000075
+S32500016E4038C6001090C9002080E900EC54E818387CE7421454E7103A3882A3387C672214D7
+S32500016E60916100809163000080E9001C90E3000480E9001C54E7103A390283107CE7421418
+S32500016E8080E7000090E30008906100844BFFFA158061008480A1008090A1000881010094E6
+S32500016EA03908002C9101000C4BFFFBE1812100943D00FFC261086E38910900B83CE0FFC228
+S32500016EC060E7663090E900BC3CC0FFC260C6667490C900CC3CA0FFC260A5678490A900D021
+S32500016EE07C03037883E100007FE803A6382100904E8000203821FFD08161003C82810038C5
+S32500016F00824100407C751B7838A000017CAE583038A000017CA570303A65FFFF38A0000148
+S32500016F207CAA903038A000207CAF96307D4558307E2E2850388000207DAF20507C0D000010
+S32500016F40418000787C0A03787EB06C307C0C03787C0B03787C0B7800408000247E665830D2
+S32500016F607E0630387CC660307D4A33787D8C8A147D6B72147C0B78004180FFE47C0B037820
+S32500016F807C0B90004080001C7DC758307D4738307D4A3B78396B00017C0B90004180FFEC1D
+S32500016FA07E88A3783A940004914800007DAF68507C0D00004080FF90382100304E800020CB
+S32500016FC07FE802A697E1FEF89061010C3861010C480006498141011880C101248081011C93
+S32500016FE07CC430514181001483E100007FE803A6382101084E8000208081012880E1012083
+S325000170007C8720503884FFFF908100FC80A100FC7C0500004080001483E100007FE803A649
+S32500017020382101084E80002080E1010C81A7000C808101107C87683090E1011091A100F402
+S325000170407CCB6830836A000C8081011C7C87D83090E1011C936100F8808101247C87D8307D
+S3250001706090E1012480E1010C83470008832A000880E10114934100E87CE7D1D680A1010C14
+S3250001708080A500047CE72A14808101107C842E707CE43A1454E7103A80C1010C80C60000A8
+S325000170A07EE7321492E100CC80C10120932100EC7CC6C9D6808A00047CC622148101011CD7
+S325000170C07D082E707CC8321454C6103A80AA00007EC62A1492C100D080A1011070AC001F5C
+S325000170E03900FFFF7D086430910100B0918100DC7D0C5A147108001F38A000207D08285085
+S3250001710038C0FFFF7CC840303FE0FFFF63FFFFFF7FE84039910100AC810100AC7C08000071
+S325000171204082000C38A0FFFF90A100AC80C1011C70C6001F90C100E4810101107C8B4214EF
+S325000171403884FFFF7C842E7080A101107CA52E707C8520509081010080A1010C7C0A280080
+S325000171604082005880E10120808101147C0720004080046080C100FC7CC6D1D654C6103A05
+S325000171807EF73214808100FC7C84C9D65484103A7ED6221480EA000854E7083C7F27C85036
+S325000171A0932100EC8081010C808400085484083C7F44D050934100E8808101007C040000D1
+S325000171C04082001480C100AC810100B07D06303890C100B080C1012C70C6000F90C1012C96
+S325000171E07E9B68507D85A63080C100E47E6530507C1803787C1300004080000C3B000001B1
+S325000172007E7300507C1003787C15037892A100A480A100FC7C152800418100F892E100CC6D
+S325000172207EECBB7892E100C492C100D07ECFB37881A100B091A100C07C0E03787C1800007B
+S32500017240408200107DE57B7839EF000481C500007C12037882210100922100A87C110000F9
+S325000172604180008C7C1200004182027C7E0783783A10000481670000814C00008101012CB9
+S325000172802C08000841810194418201702C08000441810110418200F87C080000418200D83B
+S325000172A02C080001418200B02C080002418200942C0800034182006C398C0004918100C48D
+S325000172C039A0FFFF91A100C02C1100014082000C81A100AC91A100C03A52FFFF3A31FFFF1F
+S325000172E0922100A87C1100004080FF7C5727103A7ED63A145747103A7EF73A143AB500015F
+S3250001730092A100A480A100FC7C1528004081FF1083E100007FE803A6382101084E80002025
+S325000173203FE0FFFF63FFFFFF7FE65A787CC652787CC668387D46327890CC00004BFFFF7C16
+S325000173407D6750387CE768387D473A7890EC00004BFFFF683FE0FFFF63FFFFFF7FE85A785E
+S325000173607D0853787D0868387D484278910C00004BFFFF483FE0FFFF63FFFFFF7FE56A7821
+S325000173807D45283890AC00004BFFFF307D6553787CA568387D452A7890AC00004BFFFF1C9C
+S325000173A02C080005418200482C080006418200302C080007418200084BFFFF003FE0FFFFE9
+S325000173C063FFFFFF7FE852787D6843787D0868387D484278910C00004BFFFEE07D67683888
+S325000173E07D473A7890EC00004BFFFED07D446A78908C00004BFFFEC43FE0FFFF63FFFFFF34
+S325000174007FE75A787CE750387CE768387D473A7890EC00004BFFFEA42C08000C41810070EF
+S32500017420418200582C080009418200342C08000A4182FE882C08000B418200084BFFFE7CA1
+S325000174403FE0FFFF63FFFFFF7FE75A787CE768387D473B7890EC00004BFFFE603FE0FFFFB5
+S3250001746063FFFFFF7FE65A787CC668387D46327890CC00004BFFFE447D6852787D08683863
+S325000174807D484278910C00004BFFFE302C08000D418200342C08000E4182001C2C08000FB5
+S325000174A0418200084BFFFE147D476B7890EC00004BFFFE087D6668387D46337890CC0000DE
+S325000174C04BFFFDF87D6750383FE0FFFF63FFFFFF7FE73A787CE768387D473A7890EC000070
+S325000174E04BFFFDD8930100D47C180000418200AC38E000207CF338507DC738307DE57B78CB
+S3250001750039EF000491E100C881C5000091C100BC926100D87DC89C307CEB437838E0000193
+S325000175207CF2A0309241001C2C1400014180FD4C7D635B7838A1002490A100089361000CE3
+S32500017540928100F0928100104BFFF9AD836100F8834100E8832100EC830100D482E100CC6F
+S3250001756082C100D082A100A4828100F0826100D88241001C822100A881E100C881C100BC2A
+S3250001758081A100C0818100C4390100243A080004816800004BFFFCE47DCB98307DE77B781E
+S325000175A039EF000491E100C881C7000091C100BC926100D87C1300004182FF6438E0002050
+S325000175C07CF338507DC73C307D6B3B784BFFFF5080C10120810101147C0640004082FBDC75
+S325000175E080A1011C80E101107C053800418000084BFFFBC84800600181A100F4836100F8AA
+S32500017600834100E8832100EC818100DC82E100CC82C100D04BFFFBA43821FFE87C691B7866
+S3250001762080E30018810300107D68385080E3001C810300147D48385080E3000480C30000B9
+S3250001764080C600207C0730004080003080E9000080E70020808900047CE43850810900109B
+S325000176607CC83A1490C9001080A900047D053A14910900047D6758508109000880E90000E6
+S3250001768080E700247C08380040800030810900008108002480A900087D0540508089001415
+S325000176A07CE4421490E9001480C900087C864214908900087D485050808900047C845A14D6
+S325000176C080C9000080C600287C0430004081002480E900047CEB3A1480A9000080A50028BF
+S325000176E07CE53850810900187CE7405090E9001880C900087CC65214810900008108002C3C
+S325000177007C06400040810024808900087C8A221480E9000080E7002C7C87205080A9001CBA
+S325000177207C8428509089001C8109001080E9000C80E700207C0838004080002C8109000CC1
+S325000177408108002080A900107D054050808900047CE4421490E9000480C900107C8642143D
+S3250001776090890010808900148109000C810800247C0440004080002C8089000C8084002490
+S3250001778080C900147C86205080A900087D0522149109000880E900147CA7221490A9001465
+S325000177A080A900188089000C808400287C0520004081001080E9000C80E7002890E9001839
+S325000177C08089001C8109000C8108002C7C0440004081001080C9000C80C6002C90C9001C65
+S325000177E0382100184E8000203821FFF0814100187C691B787C070378394AFFFF7C0A000084
+S32500017800418000207D244B7839290001888400007CE72214394AFFFF7C0A00004080FFE866
+S325000178207CE33B78382100104E80002081210008390227107C0940404081000C7C0918400D
+S325000178404180000C7C0303784E800020386000014E8000207FE802A697E1FFE080C3000438
+S3250001786038A0FFFF7C0628004182001480C300043CA000047C062840418000187C030378C6
+S3250001788083E100007FE803A6382100204E80002088C3000B2C0600FF4182FFE480E3000472
+S325000178A0810282F87D683A14906100249161001C916100084BFFFF79816100247C0300002D
+S325000178C0408200187C03037883E100007FE803A6382100204E80002088AB000854A5402E50
+S325000178E0890B00097CA5437854A5402E888B000A7CAA23783D0000FF6108FFFF7C0A40005A
+S32500017900408200087C0A03787C0A0000408000187C03037883E100007FE803A63821002050
+S325000179204E8000207C0A0000408100307D635B78914100188121001C7CAA4A1438A5FFFF21
+S3250001794090A100084BFFFEE981610024814100187C0300004182007C80CB000038A0FFFFF7
+S325000179607C062800418200288061001C91410018914100084BFFFE758141001880E100248E
+S3250001798080E700007C0338004082002C80A1002880E1001C90E500008081002C9144000097
+S325000179A03860000183E100007FE803A6382100204E80002038628CD04BFFBFA97C030378AA
+S325000179C083E100007FE803A6382100204E8000207C03037883E100007FE803A638210020DE
+S325000179E04E8000207FE802A697E1FFB8900282F890028300900282FC386100203881003879
+S32500017A009081000838C1003490C1000C4BFF8C157C0300004080002038628CE54BFFBF4519
+S32500017A207C03037883E100007FE803A6382100484E80002081010034910282FC80A1003822
+S32500017A4090A282F880E282F83CE7000490E28300900283049002830880A282F83FE0000387
+S32500017A6063FFFFF07D3F2A149121003C3869000C390282F09101000838A0000490A1000CB9
+S32500017A8048005A497C030000408200A080E1003C88E7000B2C070002408200248061003CC4
+S32500017AA038A1004090A1000838E1004490E1000C4BFFFDA57C030000408200108101003C98
+S32500017AC03928FFF04BFFFFA4808100442C04000B408000108101003C3928FFF04BFFFF8C2F
+S32500017AE080610040390280C09101000838A0000B90A1000C480059D57C0300004182001061
+S32500017B008101003C3928FFF04BFFFF6080E1004090E2830480810044908283088101003C6D
+S32500017B203928FFF04BFFFF4480A283047C050000408200B438628D504BFFBE2980628300B4
+S32500017B404800356D2C0306EB4082002038628D804BFFBE113860000183E100007FE803A665
+S32500017B60382100484E80002081028300890800005508402E80C2830088C600017D083378C9
+S32500017B805508801E80E2830088E7000254E7402E80828300888400037CE723787D083B781A
+S32500017BA02C0806EB4082002038628DAA4BFFBDB53860000183E100007FE803A6382100487C
+S32500017BC04E8000209002830038628DD64BFFBD957C03037883E100007FE803A638210048F3
+S32500017BE04E80002038628D6280E2830490E1000880A2830890A1000C81028304910100100F
+S32500017C004BFFBD614BFFFF38806283044E8000207FE802A697E1FFF080C283007C06000060
+S32500017C204182006880628300480034857C0300004082004480A2830088A5000054A5402EEE
+S32500017C4081028300890800017CA5437854A5801E80828300888400025484402E80C2830074
+S32500017C6088C600037C8433787CA523782C0506EB408200183860000183E100007FE803A63C
+S32500017C80382100104E8000207C03037883E100007FE803A6382100104E8000207FE802A6B2
+S32500017CA097E1FFB080E283007C070000408200183860FFFF83E100007FE803A638210050A1
+S32500017CC04E8000208142830088CA000054C6402E888A00017CC6237854C6801E88AA0002B3
+S32500017CE054A5402E88EA00037CA53B787CC62B782C0606EB408202387D49537888CA0014D2
+S32500017D0054C6402E888A00157CC6237854C6801E88EA001654E7402E890A00177CE743781F
+S32500017D207CC63B7874C6E0003D0020007C064000418201C488A9001454A5402E88C9001574
+S32500017D407CA5337854A5801E88E9001654E7402E888900177CE723787CA53B7890A1004C12
+S32500017D60398A00208161004C88E9000454E7402E88A900057CE72B7854E7801E88C9000661
+S32500017D8054C6402E91210040890900077CC643787CEA33787C0B6000418200507D635B780E
+S32500017DA0916100489181002091810008914100249141000C480051AD38628DF980C1004873
+S32500017DC090C10008808100209081000C80E1002490E100104BFFBB8D818100208161004821
+S32500017DE081410024812100407D8C521480A1004C3CE0FFC07C053840418000E439403000B6
+S32500017E0088A9000854A5402E890900097CA5437854A5801E8889000A5484402E88C9000BF0
+S32500017E207C8433787CA523787D43537891410048918100209181000890A1002490A1000C51
+S32500017E404800512138628E1980A1004890A10008810100209101000C80C1002490C1001078
+S32500017E604BFFBB0138628E398081004C908100084BFFBAF14BFF91CD4BFFBDED8101004CCF
+S32500017E807508E0003CA020007C0828004182002480E1004C7CE803A64E8000213860FFFFB0
+S32500017EA083E100007FE803A6382100504E80002080E1004C3FE0FFFF63FFFFFF7FE73839AF
+S32500017EC07CE803A64E8000213860FFFF83E100007FE803A6382100504E8000207C8A5A148A
+S32500017EE038840FFF3FE0FFFF63FFF0007FEA20394BFFFF1088AA001454A5402E88EA0015F3
+S32500017F007CA53B7854A5801E890A00165508402E88CA00177D0833787CA543783FE0FFFFE9
+S32500017F2063FFFFFF7FE528394BFFFE349141003480C1003490C100283D0A000C9101003090
+S32500017F4080C1003090C1002C386100283881004C90810008480032057C0300004080FF0888
+S32500017F603860FFFF83E100007FE803A6382100504E8000207FE802A697E1FF907C691B78CB
+S32500017F803861003491210008480054713861003438C1002490C10008390000049101000C28
+S32500017FA038C29AD590C1001048000D9D2C030002418201482C030003418200187C030378BA
+S32500017FC083E100007FE803A6382100704E8000208101007C9008000039429E0080AA000492
+S32500017FE07C050000418201007C0903782C090003408000E45524103A7C8452148084001C10
+S325000180007C040000418200C4806100249121001C5528103A9141006C7D0852148108001CEA
+S32500018020910100084800543D8141006C8121001C7C0300004082009480C10078810A0000C1
+S32500018040910600008101007C38A000017CA54830808800007C852B7890A800008061002825
+S3250001806038A1002090A100089001000C48004EF981010080906800007C030000408200144C
+S3250001808080A1002080E100287C053800418200288061008480A1002C90A100084800535D88
+S325000180A03860000183E100007FE803A6382100704E8000207C03037883E100007FE803A687
+S325000180C0382100704E800020392900012C0900034180FF24394A003080AA00047C05000001
+S325000180E04082FF087C03037883E100007FE803A6382100704E80002039029AD79101002C21
+S325000181004BFFFED07FE802A697E1FF30906100D47C0303784BFF8E39814100D8812100D4AA
+S3250001812071440004418200503C60001F6063FF6A38C29AD890C10008810900008108002489
+S325000181409101000C80A9000C90A100104BFFB7D1806100D48063000C810100DC9101000896
+S325000181604BFFA29183E100007FE803A6382100D04E800020714600084182002881090004B8
+S32500018180710800084182001C7C0303784BFFFA85814100D8812100D47C03000040820274EE
+S325000181A071460002418200FC8109000471080010418200348069000C38A29ADE90A10008B2
+S325000181C080E9000080E700187CE803A64E800021806100D43863000C900100084BFFAB6169
+S325000181E0812100D4808100DC7C040000418200A480C100DC88C600007CC607747C06000094
+S32500018200418200908069000C80A100DC90A1000881090000810800187D0803A64E80002191
+S32500018220812100D43C60001F6063FF6A38829AE39081000880C9000080C6002090C1000C7E
+S325000182408109000C91010010810100DC910100144BFFB6CD812100D48069000C80A9001466
+S3250001826090A1000880A9001090A1000C480017A5906100247C0303784BFF8CD58061002485
+S3250001828083E100007FE803A6382100D04E80002080E9000838E7000890E100DC4BFFFF68B6
+S325000182A0714700014182015880890000808400187C040000418200248069000C39029AECA0
+S325000182C09101000880A9000080A500187CA803A64E800021812100D480C9000470C60010D2
+S325000182E0418200103869000C900100084BFFAA5180C100DC7C06000041820084810100DCD5
+S32500018300890800007D0807747C080000418200703861002C810100DC91010008480050DDDC
+S325000183203C60001F6063FF6A38C29AF690C10008810100D4810800008108001C9101000C4A
+S3250001834080A100D480A5000C90A1001038A1002C90A100144BFFB5C9806100D43863000C41
+S325000183603901002C910100084BFFD56983E100007FE803A6382100D04E8000203861002C1E
+S32500018380808280A080840000908100084800506D3861002C38C0002F90C1000848004F3D79
+S325000183A07C03000041820050392300017D234B7838A29AF190A1000848005041806100D438
+S325000183C03863000C3881002C9081000838C100AC90C1000C4BFFD4417C0300004181FF440C
+S325000183E03860FFFF83E100007FE803A6382100D04E8000203921002C4BFFFFB43860FFFF3C
+S3250001840083E100007FE803A6382100D04E8000208069000C4BFFF889814100D8812100D4FA
+S325000184204BFFFD803821FFF08142801838C2E53838C608007C0A3040418000107C030378ED
+S32500018440382100104E8000203923002C80E900007C0700004182001880E900003927007C2A
+S3250001846080E900007C0700004082FFF038EA008090E2801891490000806900003821001080
+S325000184804E8000207FE802A697E1FFA89061005C39629E00810B00047C080000418200302C
+S325000184A080E1005C2C07FFFF41820038808B00008101005C7C08200041820028396B003080
+S325000184C0810B00047C0800004082FFD87C03037883E100007FE803A6382100584E800020DB
+S325000184E080AB000C7C0500004182FFD4808100607C0400004182005C814B002C7C0A0000A9
+S3250001850041820050810A0004812100607D2840394182003480A100642C05FFFF4182001410
+S3250001852080EA000C80C100647C063800408200187D43537883E100007FE803A638210058D5
+S325000185404E800020814A007C7C0A00004082FFB8808B0008708400804082002880AB00083C
+S3250001856060A5008090AB000891610054808B000C7C8803A64E80002181610054906B0028DA
+S325000185807C0D0378808B00287C0400004182FF30810B0028392000017D2968307D084839D9
+S325000185A04082000C39AD00014BFFFFDC3880000191A1004C7C8468307C8420F8810B00283F
+S325000185C07D042038908B00287D635B78916100544BFFFE5581A1004C816100547C6A1B78C5
+S325000185E07C0300004082000C39AD00014BFFFF9891A3000C80CB000890C30004810B0014D5
+S325000186009103001480AB001090A300109163000090610044808300047084000241820078CC
+S325000186207DA36B7838C29AFF90C10008812B00187D2803A64E80002181A1004C816100549F
+S3250001864081410044906A00087C0300004082001880EA00043FE0FFFF63FFFFFD7FE73839F2
+S3250001866090EA000480AA000470A50018408200287DA36B7838A29B0490A1000880EB0018F8
+S325000186807CE803A64E80002181A1004C816100548141004480CA000470C60001418200B82D
+S325000186A09001004838A0000190A1005080CA000080C600187C0600004182005C7DA36B7834
+S325000186C038A29B0990A10008810A0000810800187D0803A64E8000217C0300004182001839
+S325000186E080830000908100487C04000041820008900100508061004C38C29B0D90C10008C3
+S3250001870081010054810800187D0803A64E80002181410044386A000C8081004890810008A8
+S32500018720810100509101000C4BFFC96181A1004C81610054814100447C030000408000DC89
+S3250001874080EA00043FE0FFFF63FFFFEE7FE7383990EA000480AA000470A50010418200705D
+S3250001876080CA00043FE0FFFF63FFFFEF7FE6303990CA0004398282B8918280A0808C0000D7
+S325000187807C04000041820048386A000C80AC000090A1000838A1002090A1000C4BFFD0796B
+S325000187A081A1004C81610054814100447C0300004181005880C280A039860004918280A017
+S325000187C0808C00007C0400004082FFC080EA0004810100607D0738394182FDCC808100644F
+S325000187E02C04FFFF4182001080C100647C0668004082FDB47D43537883E100007FE803A670
+S32500018800382100584E800020808A000460840010908A00044BFFFFB838629B124BFFB1450A
+S3250001882081A1004C81610054814100444BFFFF287FE802A697E1FEF8480004C14BFF7AA127
+S32500018840480006654BFFB2394800254D4BFFAD1D4BFF7B314BFF8F614BFFA2E938629B23FE
+S325000188604BFFB101900280B44BFF791D38629B2C4BFFB0F14BFF7D657C6A1B7838629B32F7
+S32500018880914100E8914100084BFFB0D97C0B037839429E0080CA00047C060000418200209C
+S325000188A080AA00002C050002408203FC394A003080CA00047C0600004082FFE87C0B0000E0
+S325000188C0418203C480CB000470C60010418203B880A100E870A50002408200147C03037804
+S325000188E04BFFF3317C03000040820388900100F0900100F438629B4C4BFFA3B990610024F5
+S32500018900900100FC80A100247C0500004182005838E0000290E100F47C0A03782C0A000329
+S32500018920408002BC80610024914100F855451838388283487CA5221480A5000090A10008BF
+S3250001894048004B21814100F87C030000408202845547183838C283487CE7321480E7000416
+S3250001896090E100F4808100F07C0400004082001080C100F42C060002408201D4980100B0FF
+S325000189803860FFFF9001000838C0FFFF90C1000C4BFFFAF5900100FC39029E0091010020FD
+S325000189A081010020810800047C080000418200D480E100208147002C914101047C0A000094
+S325000189C0418200A4808100FC7C0400004082001838C0000190C100FC38629B884BFFAF8551
+S325000189E08141010480EA000470E700044182002438629B9680CA000080C6002490C1000821
+S32500018A00810A000C9101000C4BFFAF5981410104810A0004710800014182002438629B9D3F
+S32500018A2080EA000080E7001C90E10008808A000C9081000C4BFFAF2D81410104808A00049B
+S32500018A4070840018408200E4810A000471080002408200D8814A007C914101047C0A000015
+S32500018A604082FF6480A1002038A5003090A1002081010020810800047C0800004082FF3483
+S32500018A80808100FC7C0400004182000C38629BAB4BFFAED138629BAD38E1002890E100083E
+S32500018AA0388000509081000C38E100B090E100104BFFAD397C0300004180006838610028A7
+S32500018AC0388100EC9081000838C100FC90C1000C392101009121001038A1007890A10014CC
+S32500018AE04BFFF4957C03000041820038806100EC80A100FC90A10008810101009101000CDE
+S32500018B004BFFF9857C03000041820018810100FC9101000838C1007890C1000C4BFFF5E91E
+S32500018B20980100B04BFFFF7038629BA480EA000080E7002090E10008808A000C9081000CB6
+S32500018B404BFFAE21814101044BFFFF0C3900001F910100FC808100F42C04000140820018F3
+S32500018B6080C100FC3FE0FFFF63FFFFFB7FE6303990C100FC808100E8708400024182001863
+S32500018B8080C100FC3FE0FFFF63FFFFF77FE6303990C100FC3860FFFF80C100FC90C10008D5
+S32500018BA038A0FFFF90A1000C4BFFF8DD7C0300004182FDCC81030004812100FC7D2840382E
+S32500018BC0910100089001000C4BFFF53D4BFFFDB0394A00012C0A00034180FD4C8061002418
+S32500018BE038C100EC90C10008390100FC9101000C38A1010090A1001038E1007890E100142B
+S32500018C004BFFF3757C0300004082001838629B5580810024908100084BFFAD494BFFFD48AB
+S32500018C20806100EC808100FC90810008810101009101000C4BFFF8517C030000408200183D
+S32500018C4038629B6E81010024910100084BFFAD154BFFFD14810100FC9101000838E100781A
+S32500018C6090E1000C4BFFF4A1906100F04BFFFCF838629B404BFFACED7C0303784BFFF021C5
+S32500018C804BFFFC6C7C0303784BFFEF81906100187C03037880E1001890E100084BFFA0A1E7
+S32500018CA04BFFFC3091410020806A000038A0001090A1000838C0FFFF90C1000C4BFFF7C9DD
+S32500018CC0814100207C6B1B787C0300004182FBE0808B000470840010408200084BFFFBD022
+S32500018CE091610104386B000C900100084BFFA051816101044BFFFBC87FE802A697E1FFE891
+S32500018D008062801490010008388000249081000C4800401D80C2801439004E209106000487
+S32500018D204BFF74C180E28014906700103CA0FA2090A7002083E100007FE803A6382100187E
+S32500018D404E8000207FE802A697E1FFE87C691B78900100147C0900004182001488E90000C6
+S32500018D607CE707747C070000408200188061001483E100007FE803A6382100184E800020E9
+S32500018D8080C10014810100247C064000418000188061001483E100007FE803A6382100185C
+S32500018DA04E80002088A900007CA507747C05000041820028806100289121001C88C900005D
+S32500018DC07CC6077490C1000848003F418121001C7C030000408200C0890900007D0807745D
+S32500018DE07C080000408200188061001483E100007FE803A6382100184E8000208081001431
+S32500018E005484103A80E100207C843A149124000088C900007CC607747C060000418200282A
+S32500018E20806100289121001C88E900007CE7077490E1000848003ED58121001C7C030000F4
+S32500018E404182001480E1001438E7000190E100144BFFFF04888900007C8407742C04005CB5
+S32500018E604082001488A900017CA507742C05000A4182000C392900014BFFFF987D264B7893
+S32500018E803929000138E0002098E60000392900014BFFFF807D284B7839290001980800001B
+S32500018EA04BFFFF047FE802A697E1FFE03862813838C2C7D090C10008390010009101000CD4
+S32500018EC04800125538C2271074C6E0003CE020007C0638004182003038A227103862813844
+S32500018EE090A100083CE000407CE5385090E1000C4800124983E100007FE803A638210020E0
+S32500018F004E80002038A227103FE0FFFF63FFFFFF7FE528394BFFFFC87FE802A697E1FFD89A
+S32500018F209061002C810100307C0800004181000C38A0000490A100304BFF72699061002096
+S32500018F4038628138900100088081002C9081000C80E1003090E10010480013499061002409
+S32500018F60806100204BFF725980E100247C0700004082000C38629BC74BFFAA718061002498
+S32500018F809001000880A1002C90A1000C48003DA183E100007FE803A6382100284E8000209E
+S32500018FA07FE802A697E1FFE8388300033FE0FFFF63FFFFFC7FE42039386400089061001C97
+S32500018FC038800004908100084BFFFF5138A300043D00CAFE6108BEEF9103000038650004EC
+S32500018FE08121001C9125000083E100007FE803A6382100184E8000207FE802A697E1FFE0BD
+S325000190007C0300004182005038C3FFF890C1001880C600003CE0CAFE60E7BEEF7C06380084
+S325000190204182000C38629BCE4BFFA9C14BFF7175812100189061001C38628138912100089F
+S32500019040810900049101000C480010F18061001C4BFF716D83E100007FE803A63821002082
+S325000190604E8000204E8000207FE802A697E1FFF0808283809081000C390000FF9904001090
+S325000190804BFF70F98081000C88C4000060C6000198C400004BFF70E58081000C38C000177F
+S325000190A098C400144BFF70D583E100007FE803A6382100104E8000203821FFF080E2838032
+S325000190C09807001489070000710800FE99070000382100104E8000207FE802A697E1FFC092
+S325000190E038C2837090C100308106000C7C0800004182001483E100007FE803A63821004000
+S325000191004E800020386283C84BFFA8598141003038800001908A000C3CA0FA2060A50860F6
+S3250001912090A1003890AA00103CA0FA2060A53C8090AA00144BFFFF858121003080A9002C7B
+S325000191407C050000408200283860008438A0000290A100084BFFFDC5812100309069002C6B
+S3250001916080E9002C38E7008490E9002880E900307C0700004082001C3860008438E00002DF
+S3250001918090E100084BFFFD95812100309069003080E900187C0700004082004838600001D1
+S325000191A04BFFAB49812100309069001880C9003074C6E0003CE020007C06380041820248F1
+S325000191C080A9003080E9001890A7000480E90018B007000280C9001838A02000B0A600008A
+S325000191E080C9001C7C06000040820048386000024BFFAAF9812100309069001C80A9002CB4
+S3250001920074A5E0003CC020007C053000418201E48089002C80C9001C9086000480C9001CC0
+S32500019220B006000280A9001C38802800B085000080A280148145002080EA0AB860E70030D6
+S3250001924090EA0AB8A0EA0AC260E70030B0EA0AC280EA0ABC60E7003090EA0ABC81490014D3
+S3250001926080E9001874E7E0003CC020007C0730004182016C80A90018B0AA00008089001C6C
+S325000192807484E0003D0020007C0440004182013C80E9001CB0EA000238C0001898CA00043B
+S325000192A038800018988A000538E00084B0EA0006900A0008900A000CA08A0000B08A0010B8
+S325000192C0B00A0012900A0018A0AA0002B0AA0020900A001CB00A00224BFF6EA181E2801461
+S325000192E03DC0000161CE86A08181003838C0000198CC000C980C0000980C00047DCD7378F0
+S3250001930080EF00087CE773D6388000027CE723D63A07FFFD7C0B03787C0B80004080008087
+S32500019320394000037C0A000041800068808F000838AA00027C842E305567083C38E700067D
+S325000193407C843BD67D247051408000087D2900507C096800408000307D2D4B78996C00087E
+S3250001936088AC00003FE0FFFF63FFFFF97FE52839390000037D0A40505508083C7CA54378A6
+S3250001938098AC0000394AFFFF7C0A00004080FFA0396B00017C0B80004180FF883860002070
+S325000193A03CC0FFC260C6951890C10008390283709101000C480018BD83E100007FE803A660
+S325000193C0382100404E80002080E9001C3FE0FFFF63FFFFFF7FE738394BFFFEBC80A90018E1
+S325000193E03FE0FFFF63FFFFFF7FE528394BFFFE8C8089002C3FE0FFFF63FFFFFF7FE42039E2
+S325000194004BFFFE1480A900303FE0FFFF63FFFFFF7FE528394BFFFDB07FE802A697E1FFE0F1
+S3250001942080A1002890A10018812500109121001488E9001090E1001C4BFF6D418141001837
+S325000194408121001C80810014992400107126001441820034386283D6912100084BFFA50522
+S325000194608121001880C900207C060000418200089009002083E100007FE803A638210020CF
+S325000194804E8000207127000241820018808A00202C0400034082000C38A0000190AA002004
+S325000194A0712600014182FFD0810A00202C0800044082FFC438800001908A002083E10000BC
+S325000194C07FE803A6382100204E800020806300202C0300024080000C386000014E80002087
+S325000194E07C0303784E8000207FE802A697E1FFE89061001C80C1001C900600249001001446
+S325000195008061001C4BFFFFC97C0300004082007480A280B47C0500004182FFE880E100148A
+S3250001952038E7000190E100142C0700644081002C80C1001C39000001910600208081001C90
+S3250001954038C0000190C4002483E100007FE803A6382100184E800020386000014BFF952127
+S325000195607C03037880E1001C90E100084BFFFEAD8061001C4BFFFF597C0300004182FF948B
+S3250001958083E100007FE803A6382100184E8000207FE802A697E1FFD88181003439628370CF
+S325000195A02C0C0080408100183860FFFF83E100007FE803A6382100284E8000203940000120
+S325000195C080CB002C3FE0FFFF63FFFFFE7FE5183998A60000706500014182001480EB002C5A
+S325000195E07C66467098C70001394A000191610024806B002C914100207C63521480A1003033
+S3250001960090A100089181000C48003959812100243900000391090020808900183D000000F8
+S325000196206108B000B104000080A9002C74A5E0003CC020007C053000418200C88089002C7A
+S3250001964080C9001C9086000480C9001C80A10034808100207CA52214B0A600028109001C54
+S325000196603CE0000060E7B800B0E800004BFFF9FD810100248108001038E0008198E8000C8C
+S325000196804BFF6AF9806100244BFFFE614BFFFA2D81610024814B0020808B001CA0840000BA
+S325000196A0708880004082000C70850007418200183860FFFF83E100007FE803A638210028FB
+S325000196C04E8000202C0A0001418200183860FFFF83E100007FE803A6382100284E8000200A
+S325000196E0808B00247C0400004082FFC88061003483E100007FE803A6382100284E80002033
+S325000197008089002C3FE0FFFF63FFFFFF7FE420394BFFFF307FE802A697E1FFD081E1003C67
+S325000197203DC020007C6C1B78394283702C0F0080408100183860FFFF83E100007FE803A67E
+S32500019740382100304E800020808A002C6068000199040000706800014182002480AA0028DD
+S325000197603FE0FFFF63FFFFFE7FE4603998850000808A00287D8846709904000138A00004E6
+S3250001978090AA002080EA003074E7E0007C077000418201D080CA0030810A001890C8000493
+S325000197A0810A00183CE0000060E7B000B0E800007C0D0378816A001CB00B0008718500018F
+S325000197C04182002C810A00287508E0007C0870004182017C80EA002890EB00043880000284
+S325000197E0B08B0002396B000839A0040080AA002C74A5E0007C0570004182013C9141002C5E
+S32500019800808A002C908B000438CF0001B0CB000261A8A800B10B000091A100207C0D00001F
+S325000198204182001480AA001C3C80000060848000B08500004BFFF83580A1002C80A50010B6
+S32500019840388000819885000C4BFF69318061002C4BFFFC994BFFF86581C1003C8141002CBC
+S3250001986081AA0020816A001CA16B000080A100207C0500004182001080EA001CA0E70008D9
+S325000198807D6B3B78818A0018A18C00027C0C7000408100087DCC7378716800074082000C31
+S325000198A071658000418200183860FFFF83E100007FE803A6382100304E8000202C0D0001B5
+S325000198C0418200183860FFFF83E100007FE803A6382100304E800020808A0018A0840000DF
+S325000198E070848000418200183860FFFF83E100007FE803A6382100304E80002080EA002403
+S325000199007C0700004082FFA48061003880EA003090E10008918100189181000C4800364521
+S325000199208061001883E100007FE803A6382100304E8000209141002C808A002C3FE0FFFFEB
+S3250001994063FFFFFF7FE420394BFFFEBC80EA00283FE0FFFF63FFFFFF7FE738394BFFFE7C36
+S3250001996080CA00303FE0FFFF63FFFFFF7FE630394BFFFE287FE802A697E1FFD88161003437
+S325000199809061002C80A1003890A100247C0A03787C0A58004080004C392020007CEA585083
+S325000199A07C074800408000087D2A58508061002C80E100249141001C7CE7521490E10008FC
+S325000199C09121000C80C100307CC803A64E8000218141001C906100207C030000418100182D
+S325000199E07D43537883E100007FE803A6382100284E800020386285574BFF9F698161003414
+S32500019A0080E100208081001C7D443A144BFFFF847FE802A697E1FFD09061003490010008B1
+S32500019A2080A100387CA803A64E8000217C030000408000183860FFFF83E100007FE803A6A9
+S32500019A40382100304E80002038600020900100084BFFF4C97C6B1B783880002080610034C9
+S32500019A6080E1003C90E100089081002C9081000C91610020916100104BFFFEFD8141002034
+S32500019A8080C1002C7C03300041820020806282CC4BFF9ED13860FFFF83E100007FE803A6CD
+S32500019AA0382100304E800020888A00005484402E88EA00017C843B785484801E890A00029F
+S32500019AC05508402E88AA00037D082B787C8443782C0406EB4182004C3862855988CA0000A2
+S32500019AE054C6402E888A00017CC6237854C6801E88AA000254A5402E88EA00037CA53B784B
+S32500019B007CC62B7890C100084BFF9E593860FFFF83E100007FE803A6382100304E8000203E
+S32500019B2088AA001454A5402E890A00157CA5437854A5801E88CA001654C6402E88EA0017DD
+S32500019B407CC63B787CA5337874A5E0003CE020007C05380041820294888A00145484402E8A
+S32500019B6088AA00157C842B785484801E88CA001654C6402E890A00177CC643787C8433783C
+S32500019B809081002888CA000454C6402E888A00057CC6237854C6801E88AA000654A5402E5C
+S32500019BA088EA00077CA53B787CC62B783862858490C1002C90C100084BFF9DA9806100344E
+S32500019BC08081003C908100088101002C9101000C80A1002890A100104BFFFD9D8161002C60
+S32500019BE0814100207C03580041820020806282CC4BFF9D713860FFFF83E100007FE803A630
+S32500019C00382100304E800020808100287CCB221438C60FFF3FE0FFFF63FFF0007FEB3039D2
+S32500019C2088EA000854E7402E88AA00097CE72B7854E7801E88CA000A54C6402E890A000B5E
+S32500019C407CC643787CE733783862858790E1002C90E10008916100289161000C4BFF9D0532
+S32500019C60806100348101003C9101000880E1002C90E1000C80810028908100104BFFFCF9DD
+S32500019C808141002080E1002C7C03380041820020806282CC4BFF9CCD3860FFFF83E10000D7
+S32500019CA07FE803A6382100304E8000203862859388AA000C54A5402E890A000D7CA5437843
+S32500019CC054A5801E888A000E5484402E88CA000F7C8433787CA5237890A10008890A0014D8
+S32500019CE05508402E88CA00157D0833785508801E88EA001654E7402E888A00177CE72378A8
+S32500019D007D083B789101000C4BFF9C594BFF73354BFF9F554BFF648D8141002088EA001454
+S32500019D2054E7402E88AA00157CE72B7854E7801E890A00165508402E892A00177D084B78C7
+S32500019D407CE7437874E7E0003C8020007C0720004182004888CA001454C6402E88EA0015A4
+S32500019D607CC63B7854C6801E890A00165508402E88AA00177D082B787CC643787CC803A660
+S32500019D804E8000217C03037883E100007FE803A6382100304E80002088CA001454C6402EFA
+S32500019DA0890A00157CC6437854C6801E888A00165484402E88EA00177C843B787CC62378B8
+S32500019DC03FE0FFFF63FFFFFF7FE630397CC803A64E8000217C03037883E100007FE803A6E7
+S32500019DE0382100304E800020888A00145484402E88CA00157C8433785484801E88EA001669
+S32500019E0054E7402E88AA00177CE72B787C843B783FE0FFFF63FFFFFF7FE420394BFFFD64AC
+S32500019E207FE802A697E1FFE89061001C386300184BFFF17138A3001890A3000C8103000C7F
+S32500019E40910300049103000080C3000C80E1001C7CC63A1490C30008900300103D00CAFE70
+S32500019E606108BEE09103001483E100007FE803A6382100184E8000207FE802A697E1FFF0E3
+S32500019E807C691B787C0300004182004090610014810300143CE0CAFE60E7BEE07C0838009F
+S32500019EA041820010386281284BFF9B4181210014900900143CE0DEAD60E7BABE90E900100D
+S32500019EC07D234B784BFFF13583E100007FE803A6382100104E8000207FE802A697E1FFE86F
+S32500019EE0386000144BFFF0BD900300049003000080A1002490A30008808100289083000CC6
+S32500019F009003001083E100007FE803A6382100184E8000207FE802A697E1FFE89061001C49
+S32500019F204BFF62818141001C90610014812A0000912100107C0900004182003C80A90010E0
+S32500019F4090AA00009009001080E90004810900007CE83850810A00107CE7405090EA00101C
+S32500019F6080CA00107C0600004080000C3862812E4BFF9A79806100144BFF624580610010B5
+S32500019F8083E100007FE803A6382100184E8000207FE802A697E1FFE89061001C4BFF6205BB
+S32500019FA08141001C812100207C6B1B789009001080EA00007C0700004082005C912A000011
+S32500019FC0912A000480A9000480C900007CA6285080CA00107CA62A1490AA00107D635B78F4
+S32500019FE04BFF61DD8121001C80A900087C050000418200148069000C80E900087CE803A618
+S3250001A0004E80002183E100007FE803A6382100184E80002080AA0004912500104BFFFFA496
+S3250001A020806300104E8000207FE802A697E1FFE09061002438C0FFFF90C100144BFF616552
+S3250001A04081610014814100247C6C1B78916100147C0B000040800010812A00007C09000015
+S3250001A060408200207D8363784BFF61558061001483E100007FE803A6382100204E8000204C
+S3250001A08080E9000080C900047C073040408000208169000038EB000190E90000896B0000B5
+S3250001A0A0808A00103884FFFF908A001080E9000080C900047C0730404180FF9480E9001025
+S3250001A0C090EA0000900900104BFFFF847FE802A697E1FFE89061001C386000014BFFFD45E9
+S3250001A0E07C681B788083000438C4000190C3000480C1002098C400008061001C9101000833
+S3250001A1004BFFFE9183E100007FE803A6382100184E800020812100089123000480C1000CDD
+S3250001A12038A000087CC62BD654C618387CC64A1490C300084E8000207FE802A697E1FFD844
+S3250001A14081810034816100307C6E1B787C0C00004181001483E100007FE803A638210028E0
+S3250001A1604E8000208143000480AA00047C0558404181001080CA00007C0600004082011C5E
+S3250001A18080AE00047C0A28404081001C38CAFFFC80C6000080EAFFF87CC63A147C065800AD
+S3250001A1A0418200A47D0B6214812A00047C0848004082001080EA00007C07000040820060D7
+S3250001A1C0808E00087C0A20404180002C3862829880AE000090A100089161000C9181001054
+S3250001A1E04BFF978183E100007FE803A6382100284E80002081AA0004916A00047DAB6B78DA
+S3250001A20081AA0000918A0000394A00087DAC6B787C0D00004182FFD04BFFFFA880AA000420
+S3250001A2207D0C2850910A000480EA00007CA7621490AA000083E100007FE803A63821002845
+S3250001A2404E80002080CAFFF87C866214908AFFF87C8B621480AA00047C0428004082FF88A3
+S3250001A26080AA0000808AFFF87CA42A1490AAFFF880EA00007C0700004182FF6C394A000877
+S3250001A280388AFFFC80CA000490C40000810A0000910AFFF84BFFFFDC394A00084BFFFECC77
+S3250001A2A07FE802A697E1FFD881E1003081C1003481A100387C701B7881630004810B0000E4
+S3250001A2C07C08000041820028818B00047C0F00004182005C7C0C784040810028396B000879
+S3250001A2E0810B00007C0800004082FFE07C03037883E100007FE803A6382100284E800020C9
+S3250001A3007D0F7214812B00007D2C4A147C084840408100187C03037883E100007FE803A61E
+S3250001A320382100284E8000207DEC7B787C0D0000408100147C8D62143884FFFF7C846B96B3
+S3250001A3407D8469D680CB000080EB00047CC63A147CCC30507C067040408000084BFFFF80E1
+S3250001A36081AB00047CEC721490EB00047D0C72147D0D4050812B00007D084850910B0000AB
+S3250001A38080CB00007C06000040820028396B000838CBFFFC810B00049106000080AB000003
+S3250001A3A090ABFFF87C050000418200084BFFFFE07C0D6000418200207E03837891A100086D
+S3250001A3C0918100207CCD605090C1000C4BFFFD6D818100207D83637883E100007FE803A6C9
+S3250001A3E0382100284E8000207FE802A697E1FFB8388002809081003438A001E090A1003808
+S3250001A40038C0000390C1003C90010040386100344800042180E100407C07000040820014A8
+S3250001A42083E100007FE803A6382100484E800020388000039082825480A1004090A2824812
+S3250001A44038E000A090E28250900282589002825C3900028091028260388001E0908282645C
+S3250001A46038A2824838C2824880E600108106001490E5002091050024810600188086001C4C
+S3250001A480910500289085002C7C0303783880FFFF9081000838C0FFFF90C1000C3900FFFF63
+S3250001A4A09101001048000641386000FF900100089001000C900100104800062D3862824817
+S3250001A4C038A1000890A1002C80E1002C900700008081002C9004000438C2824890C1001029
+S3250001A4E0390100143882824880A4001080C4001490A8000090C8000480C4001880E4001C87
+S3250001A50090C8000890E8000C900100244BFFCAB538E0000890E280A8900280AC8102800C4B
+S3250001A52089080105910280B083E100007FE803A6382100484E8000207FE802A697E1FFB879
+S3250001A5407C691B7880C282487C0600004082001483E100007FE803A6382100484E80002015
+S3250001A5609061004C2C030008418202302C030009418201D02C03000A4182010480A282609A
+S3250001A580810280B07CA8285080C280A87C062800418000103860000A4BFFFFA18121004C06
+S3250001A5A07129007F408100C8A8E280087C093800408000BC5528183880C2800C7D28321421
+S3250001A5C03881003C38A280A880C5000080E5000490C4000090E400043862824838E100087E
+S3250001A5E090E100348081003488C900047CC607748101003C7CC8321490C4000080C1003457
+S3250001A600810100409106000480A2801090A10010390100149101003080A10030A8E90000F1
+S3250001A62090E50000808100309004000480C1003091210044A90900089106000880A10030C4
+S3250001A64088E2800A7CE7077490E5000C38E0000C90E100244BFFC96D808100448884000511
+S3250001A66080C1003C7C843214908280A883E100007FE803A6382100484E8000203900000892
+S3250001A680910280A88882800A7C840774810280AC7C882214908280AC88C2800A7CC6077431
+S3250001A6A080E282647CC63850810280AC7C0830004081000C80A2825C90A280AC386282488F
+S3250001A6C038E1000890E10034808100349004000080C10034810280AC9106000438A2824881
+S3250001A6E090A1001038E1001490E10030808100309004000080C10030810280AC91060004C4
+S3250001A70080A1003080E2826090E500088081003088C2800A7CC6077454C6083C80E280AC72
+S3250001A7207CC63A1490C4000C900100244BFFC89583E100007FE803A6382100484E800020C3
+S3250001A740808280A83884FFF880A280B07C842BD67084000738C000087C84305080E280B0B5
+S3250001A7607C8439D680A280A87C852214908280A880E280A8808282607C0720004180FEF048
+S3250001A7803860000A4BFFFDB583E100007FE803A6382100484E80002080C280B038C6000899
+S3250001A7A0810280A87C0830004180FEC480A280B080E280A87CA5385090A280A83860002019
+S3250001A7C04BFFFD7980A280B080E280A87CA5385090A280A883E100007FE803A638210048BE
+S3250001A7E04E8000207FE802A697E1FFF07C691B788101001838C8FFFF90C100187C080000F1
+S3250001A8004081002038E9000190E10014886900007C6307744BFFFD25812100144BFFFFD41F
+S3250001A82083E100007FE803A6382100104E8000207FE802A697E1FFD87C6A1B7880E2801479
+S3250001A84080E7002090E10024388001E09083000438E0028090E3000038A0000390A3000802
+S3250001A860806300009141002C80EA00047C6339D638A0001090A100084BFFE6A13DA0017D47
+S3250001A88061AD78408181002C81610024906C000C80AC000080CC00047CA531D690AC0010BF
+S3250001A8A0808B00303FE0FFFF63FFFFBF7FE42039908B0030810C000C7508E0003D2020009F
+S3250001A8C07C0848004182020C80EC000C90EB085080EC0000810C00047CE741D654E7183887
+S3250001A8E038E7007F390000807CE743D654E7881C60E70D6690EB084038A000037C050000C6
+S3250001A900418200142C050002418201A02C050003418201687C0A03782C0A00104080001C3F
+S3250001A9205546083C7CC65A14B1460E00394A00012C0A00104180FFEC808C0004548458289E
+S3250001A9403FE0100063FF00217FE42378908B084880CC000054C6502A3FE0010063FF00E48F
+S3250001A9607FE6337890CB084480C28014818600087D4C6BD67CCC53D67C0668004081000806
+S3250001A980394A00019141001C2C0A00104180000C38E0001090E1001CB00B097638E01FFF06
+S3250001A9A0B0EB0972A0AB097270A5FDFFB0AB097238A01FFFB0AB0970810B0ABC61085001F7
+S3250001A9C0910B0ABC810B0AB861085001910B0AB8A10B0AC27108AFFEB10B0AC24BFF579D44
+S3250001A9E080C100243D0055CC6108AA33910603804BFF578981410024808A02803FE0FFFF74
+S3250001AA0063FFFFE07FE4203938A281108101001C7CA5421488A500007C842B78908A028046
+S3250001AA204BFF575980A100243CE0AA3360E755CC90E503804BFF57458102825091028250D7
+S3250001AA4080A1002438E0000798E508584BFF572D8101002480A8084060A5000190A8084044
+S3250001AA60386000014BFF5D3183E100007FE803A6382100284E8000207C0A03782C0A010043
+S3250001AA804080FEB85544402E554520367C842B787C8453785545083C7CA55A14B0850E0024
+S3250001AAA0394A00014BFFFFD87C0A03782C0A00104080FE885546402E554720367CC63B786D
+S3250001AAC07CC65378B0CB0E00394A00014BFFFFE080EC000C3FE0FFFF63FFFFFF7FE7383960
+S3250001AAE04BFFFDEC80810008548B273E80E1000C54EA273E80A1001054A9273E3FE0FFFF0F
+S3250001AB0063FFFFFF7FE81A78710800FF5508083C80C2801480C600207D0832145565402E8D
+S3250001AB20554620367CA533787CA54B78B0A80E00386000014E8000203821FFE83D4055CCA2
+S3250001AB40614AAA333D20FA209149030038C000C3B0C902009149032038E000C1B0E902204B
+S3250001AB603CA0AA3360A555CC90A903209149034038C00082B0C90240382100184E800020E2
+S3250001AB807FE802A697E1FFE081410028906100247145000341820010386287E44BFF8E4D93
+S3250001ABA081410028812100243CC07C1060C643A690C900003C807C08608402A69089000405
+S3250001ABC03CE07C1260E743A690E900087544E0003CC020007C043000418200887D485378D3
+S3250001ABE07D0A437855053E7F4182000C2C05007F408200303FE003FF63FFFFFC7FE5503919
+S3250001AC003FE0480063FF00037FE52B7890A9000C83E100007FE803A6382100204E8000203A
+S3250001AC205544843E64843C009089000C7144FFFF64846000908900103C807C08608403A678
+S3250001AC40908900143CE04E8060E7002190E9001883E100007FE803A6382100204E80002002
+S3250001AC603FE0FFFF63FFFFFF7FE850394BFFFF747FE802A697E1FFE89061001C8082E53011
+S3250001AC802C0400304180000C386287EC4BFF8D5D80C1001C7D4602148082E53039040001B4
+S3250001ACA09102E5305484203638A2E03038A502007D642A145547103A38C2E0307CE7321436
+S3250001ACC080E7000090EB000881010020910B000080E1002490EB00045544103A38E2E03034
+S3250001ACE07C843A149164000080A28014816500202C0A00104180003038EAFFF070E7001F90
+S3250001AD0038C000017CC7383080CB09487CC73B7890EB094883E100007FE803A63821001845
+S3250001AD204E8000202C0A000841800038714800075508083C38E0001F7D08385039200001E8
+S3250001AD407D284030808B00147C884378910B001483E100007FE803A6382100184E80002076
+S3250001AD605544083C608400013900001F7C84405038A000017CA4203080AB00147CA42378DF
+S3250001AD80908B001483E100007FE803A6382100184E8000207FE802A697E1FFE03D4055CCA6
+S3250001ADA0614AAA33810280148128002080A900043FE0FFFF63FFFFF37FE5283990A9000484
+S3250001ADC09009001438E0FFFF90E900189009094038E0FFFF90E90944900909483CE000E173
+S3250001ADE060E79F0090E9094080A9094060A5008090A909409149030039000001B109020058
+S3250001AE0080C9001464C6004090C900149149030C4BFF53693860FFFF4BFF53E17C090378F4
+S3250001AE202C0930004080002C7D234B789121001C3D00FFC2610803A8910100084BFFFD4551
+S3250001AE4080E1001C392701002C0930004180FFDC83E100007FE803A6382100204E80002031
+S3250001AE607FE802A697E1FFD87C6A1B787C0903782C09002840800064386288065526103A86
+S3250001AE8038A284307CC62A1480C6000090C10008810A00009101000C912100245528103A38
+S3250001AEA038E284307D083A1481080004910100109141002080AA000490A100144BFF8AA5DD
+S3250001AEC0810100243928000280C10020394600082C0900284180FFA483E100007FE803A645
+S3250001AEE0382100284E8000207FE802A697E1FFE87C6A1B789061001C80C3000054C9C23E88
+S3250001AF002C090005418200802C0900094182005C38C0000190C280B47C0900004180003C4F
+S3250001AF202C09001540800034386288345524103A390295A07C8442148084000090810008D0
+S3250001AF404BFF8A218061001C4BFFFF19386288424BFF8A11480000003862881B912100080E
+S3250001AF604BFF8A014BFFFFE07D435378900100084BFF7B8983E100007FE803A63821001875
+S3250001AF804E8000204800001583E100007FE803A6382100184E8000207FE802A697E1FFD82E
+S3250001AFA09061002C810280148168002091610018890B001C550CF0BE7D8A0E7091810024C9
+S3250001AFC071880001418200E02C0A00044082002438800001B08B09304BFF51A1818100241E
+S3250001AFE081610018A0AB093054A5AAFE39450010914100205545103A3882E0307CA52214A6
+S3250001B000814500007C0A00004082000848000000808A000C7C0400004182002038A0001F5B
+S3250001B0207CAC285038C000017CC5283080CB00107CC52B7890AB00108061002C80EA0004D2
+S3250001B04090E100089141001C80EA00007CE803A64E80002180C1001C814600087C0A00006A
+S3250001B060418200084BFFFFD480C100202C060010418000248101001880A1002038A5FFF0B2
+S3250001B080392000017D2528308088094C7C852B7890A8094C83E100007FE803A638210028D2
+S3250001B0A04E800020394A00084BFFFF487C691B7888A3000054A5402E888300017CA52378AD
+S3250001B0C054A5402E88C300027CA5337854A5402E88C300037CA533783CE0FEEF60E70F1EEB
+S3250001B0E07C05380040820030886300205463402E88C900217C6333785463402E88E90022BA
+S3250001B1007C633B785463402E890900237C6343784E8000207C0303784E8000207FE802A63D
+S3250001B12097E1FFE8386001F43CA0FFC260A5B21C90A100089001000C4BFF65959062822CF2
+S3250001B14038628BE04BFF881D83E100007FE803A6382100184E8000207FE802A697E1FFB8E3
+S3250001B160818100507C6B1B788083000480A300007C8520502C040040408000183860FFFF83
+S3250001B18083E100007FE803A6382100484E80002081430000890A00005508402E88EA000110
+S3250001B1A07D083B785508402E892A00027D084B785508402E888A00037D0823783CA0FEEFBF
+S3250001B1C060A50F1E7C082800418200183860FFFF83E100007FE803A6382100484E80002016
+S3250001B1E0900282EC88CA001054C6402E88AA00117CC62B7854C6402E88EA00127CC63B7835
+S3250001B20054C6402E88EA00137CCE3B78888A00145484402E890A00157C8443785484402E08
+S3250001B22088AA00167C842B785484402E88AA00177C842B789081003888EA001854E7402E6E
+S3250001B24088CA00197CE7337854E7402E890A001A7CE7437854E7402E890A001B7CE7437885
+S3250001B26090E1003488AA000C54A5402E888A000D7CA5237854A5402E88CA000E7CA533780F
+S3250001B28054A5402E88CA000F7CA5337890A10030890A00045508402E88EA00057D083B78A1
+S3250001B2A05508402E892A00067D084B785508402E888A00077D0D237888CA000854C6402ED0
+S3250001B2C088AA00097CC62B7854C6402E88EA000A7CC63B7854C6402E88EA000B7CC63B7854
+S3250001B2E090C1002880C3000038C6002090C3000081430000888A00005484402E890A00016A
+S3250001B3007C8443785484402E88AA00027C842B785484402E88AA00037C842B782C0406EB0F
+S3250001B3204182002038628BE24BFF86393860FFFF83E100007FE803A6382100484E8000207A
+S3250001B34088CA001454C6402E88AA00157CC62B7854C6402E88EA00167CC63B7854C6402E3F
+S3250001B36088EA00177CC63B7890CC000081030000390800209103000080EC000074E7E000CC
+S3250001B3803D0020007C0740004182015480CC00007CC3337890C100449161004C916100086B
+S3250001B3A091A1000C91C1001038A28BFF90A1001448000141816100287C6A1B787C030000B1
+S3250001B3C04082002038628C044BFF85993860FFFF83E100007FE803A6382100484E80002059
+S3250001B3E07C0B00004182005C38EA0FFF3FE0FFFF63FFF0007FE3383980E1004C90E1000808
+S3250001B4009161000C810100389101001038C28C1790C10014480000DD7C6A1B787C030000AC
+S3250001B4204082002038628C1C4BFF85393860FFFF83E100007FE803A6382100484E80002040
+S3250001B44080C100307C060000418200407D435378914100408081004C8084000090810008E8
+S3250001B460808100309081000C48001AF981610030808100407D445A1480E1004C80C70000A6
+S3250001B4807C865A1490870000808282EC80C100347C0430004182003038628C2F810282EC50
+S3250001B4A09101000880C1003490C1000C4BFF84B53860FFFF83E100007FE803A638210048EB
+S3250001B4C04E80002080C100447C66505083E100007FE803A6382100484E80002080CC000021
+S3250001B4E03FE0FFFF63FFFFFF7FE630394BFFFEA47FE802A697E1FFE07C6A1B7838628C67A2
+S3250001B5008081003490810008914100249141000C80A1002C90A100104BFF84498101002CAF
+S3250001B5207C080000408200188061002483E100007FE803A6382100204E80002080610028BD
+S3250001B5403902EE00910100089001000C480003257C030000408000187C03037883E100005F
+S3250001B5607FE803A6382100204E8000208061002838E20A0890E10008388000089081000CC2
+S3250001B580480002F1814100287C030000408000187C03037883E100007FE803A63821002041
+S3250001B5A04E80002080CA000480EA00007CC7305080A1002C7C0628004080002038628C7F9F
+S3250001B5C04BFF83A17C03037883E100007FE803A6382100204E800020386001F43D00FFC296
+S3250001B5E06108B21C910100089001000C4BFF60E1814100289062822C80610024810A000031
+S3250001B60091010008810A00008121002C7D084A149101000C38E2EE0090E1001039020A08D9
+S3250001B6209101001480A1003090A100184800006D906100248062822C4BFF61759002822C09
+S3250001B64038628C8E4BFF831D814100247C0A00004082002038628C904BFF83097C03037871
+S3250001B66083E100007FE803A6382100204E80002080E100288081002C80C700007C862214B3
+S3250001B680908700007D43537883E100007FE803A6382100204E8000203821FFE8820100243F
+S3250001B6A081610030812100207C6C1B78556536BE2C050013418201942C05001F4182018C4A
+S3250001B6C02C05003B418201842C05003F4182017C81A282EC7C0980404080016088890000F7
+S3250001B6E07C8F2378392900017C0E03787C8A26707C0A00004082002C7D6A5B78914C00008E
+S3250001B700398C00047DAD521471EA000F39CE00012C0E00014082FFC07C0A00004182FFDC77
+S3250001B7202C0A00014082009488E9000354E7402E88C900027CE7337854E7402E89090001BB
+S3250001B7407CE7437854E7402E890900007CEA4378392900047C098040408100107C030378F2
+S3250001B760382100184E800020554736BE2C070013418200202C07001F418200182C07003B0F
+S3250001B780418200102C07003F418200084BFFFF703FE0FC0063FFF8017FE8503955478BFE4E
+S3250001B7A070E707FE7D083B78714407FE548478207D0A23784BFFFF48280A000841810044D1
+S3250001B7C038AAFFFE54A5402E890900007CA5437854A5103A80C1002C7CA5321480A500046E
+S3250001B7E0890900017CAA4378392900027C0980404081FF787C030378382100184E80002094
+S3250001B800390AFFF75508402E88C900007D0833785508103A80E100287D083A1481480004CC
+S3250001B820392900017C0980404081FF407C030378382100184E80002091A282EC7D83637884
+S3250001B840382100184E8000203FE0FC0063FFF8017FE6583955658BFE70A507FE7CC62B78D4
+S3250001B860716707FE54E778207CCB3B784BFFFE647FE802A697E1FFD08083000480A30000EB
+S3250001B8807C8520502C040002408000183860FFFF83E100007FE803A6382100304E800020A5
+S3250001B8A081030000890800005508402E9061003480E3000088E700017D083B7838628CB398
+S3250001B8C09101001C910100084BFF809981C100388161003480CB000038C6000290CB000080
+S3250001B8E08081001C39A4FFFE7C0D00004081002C810B0004812B00007D0940507C08680096
+S3250001B900408000183860FFFF83E100007FE803A6382100304E800020900E0000814B00005D
+S3250001B92080CB00007D866A14810B00007CC86A1490CB00007C0D03787C0A60404080009011
+S3250001B9407C0B03787C0A6040418000183860FFFF83E100007FE803A6382100304E8000205E
+S3250001B9605568383088CA000070C6007F7D0B33787D455378394A000188A5000070A500808E
+S3250001B980418200207C0A60404180FFD83860FFFF83E100007FE803A6382100304E8000207E
+S3250001B9A07DAD5A14808E000038A4000190AE00005484103A7C84721480E1003C7DA53830F0
+S3250001B9C090A400047C0A60404180FF787C03037883E100007FE803A6382100304E800020E5
+S3250001B9E03821FFF07C6B1B7880A1001C810100247D45421480C10018808100207D26221430
+S3250001BA008081001C7C0A20404080000839290001914B0004912B0000382100104E800020FE
+S3250001BA203821FFF07C6B1B788101001C80C100247D4640508081001880E100207D27205039
+S3250001BA4080E1001C7C0A3840408100083929FFFF914B0004912B0000382100104E80002048
+S3250001BA603821FFD8CA2100307C6E1B78DA210020810100203FE0000F63FFFFFF7FE84039CC
+S3250001BA80650C001081A10024810100205508653E710807FF38C004337D2830507C0B037861
+S3250001BAA07C0A03787C090000418000B02C090020408000847C090000408200607DAB6B783D
+S3250001BAC07D8A637880A1002074A580007C050000418200207C0B0000418200287C040378D2
+S3250001BAE07D6B20503FE0FFFF63FFFFFF7FEA5278914E0000916E0004382100284E800020E6
+S3250001BB007C0703787D4A3850914E0000916E0004382100284E8000207DA54C3038C00020CA
+S3250001BB207CC930507D8630307CAB33787D8A4C304BFFFF942C0900204082000C7D8B63789E
+S3250001BB404BFFFF842C0900404080FF7C38C9FFE07D8B34304BFFFF707C0703787D29385030
+S3250001BB602C09000A418100207DAB48307D85483038C000207CC930507DA634307CAA33784E
+S3250001BB804BFFFF44FC80881ED8828020814280244BFFFF347FE802A697E1FFE8C061002062
+S3250001BBA0D86100084BFFFEBD83E100007FE803A6382100184E8000203D20433080E1000430
+S3250001BBC074E780007C0700004182009C808100087C0400004182007C7C0603788101000852
+S3250001BBE07CC8305090C1000880C100043FE0FFFF63FFFFFF7FE6327890C1000480E1000496
+S3250001BC00912280206CE6800090C28024C8228020FC21D828C8828428FC01013280A100080C
+S3250001BC20912280206CA4800090828024C8628020FC63D828FC03E0004080000CC8428428DA
+S3250001BC40FC63102AFC00182AFC1C00284E8000207C04037880C100047C8620509081000411
+S3250001BC604BFFFF9C80A10004912280206CA4800090828024C8628020FC63D828C84284283B
+S3250001BC80FC0300B281010008912280206D07800090E28024C8228020FC21D828FC01E00081
+S3250001BCA04080000CC8428428FC21102AFC00082A4E8000207FE802A697E1FFF038C1000415
+S3250001BCC038E10014810700008087000491060000908600044BFFFEE5FC00001883E1000047
+S3250001BCE07FE803A6382100104E8000203821FFD83DA080008241003C822100408161002C59
+S3250001BD008181003081210034814100387C0A00004082000C7C090000418200F47C0B68405B
+S3250001BD20418000E07C0F03787C0E03787C096840418000147C096800408200307C0A784031
+S3250001BD40408000285525083C55480FFE7CA94378554A083C39CE00017C0968404180FFE8EC
+S3250001BD607C0968004182FFD87C0F03787C0D03787C0E00004180006455E4083C55A70FFEF6
+S3250001BD807C8F3B7855AD083C7C0B4840418100147C0B4800408200287C0C50404180002001
+S3250001BDA07D9063787D8A60507C0C804040810008396BFFFF7D69585061AD00015547F87E7B
+S3250001BDC05525F8007CEA2B785529F87E39CEFFFF7C0E00004080FFA47C1200004182000C9E
+S3250001BDE091B2000491F200007C1100004182000C9191000491710000382100284E8000207F
+S3250001BE007D6D5B787D8F63784BFFFF207D8C53964BFFFF0C7FE802A697E1FFE07C691B78E9
+S3250001BE2080E100287C07000040820010808100307C0400004182005438E1000439010028D6
+S3250001BE408088000080A800049087000090A7000438A1000C38C1003080E600008106000456
+S3250001BE6090E5000091050004912100147C06037890C100184BFFFE7983E100007FE803A64B
+S3250001BE80382100204E8000207C0803789109000080C1002C80A100347CC62B9690C9000479
+S3250001BEA083E100007FE803A6382100204E8000207FE802A697E1FFE07C691B788101002818
+S3250001BEC07C0800004082001080A100307C05000041820054390100043881002880A40000D9
+S3250001BEE080C4000490A8000090C8000438C1000C38E10030810700008087000491060000E7
+S3250001BF00908600047C04037890810014912100184BFFFDDD83E100007FE803A63821002005
+S3250001BF204E8000207C0403789089000080E1002C80C100347FE733967FFF31D67CFF38503F
+S3250001BF4090E9000483E100007FE803A6382100204E800020808300047C0400004082001821
+S3250001BF6080A300007C0603787CA5305090A300004E800020808300047C0503787C8428505D
+S3250001BF8090830004810300003FE0FFFF63FFFFFF7FE84278910300004E8000207FE802A6D0
+S3250001BFA097E1FFD07C691B78906100348081003C7C84FE7080C100387C06200040820018F6
+S3250001BFC0810100447D08FE7080A100407C054000418200AC80E1003854E70FFE90E1002C92
+S3250001BFE07C07000041820010386100384BFFFF698121003480E1004054E70FFE90E1002809
+S3250001C0007C07000041820010386100404BFFFF498121003438E100043901003880880000EB
+S3250001C02080A800049087000090A7000438A1000C38C1004080E600008106000490E50000F7
+S3250001C04091050004912100147C06037890C100184BFFFC9D80E1002C808100287C072000D7
+S3250001C0604182000C806100344BFFFEED83E100007FE803A6382100304E8000208081003C78
+S3250001C080810100447C8443D69089000480E900047CE7FE7090E9000083E100007FE803A672
+S3250001C0A0382100304E8000207FE802A697E1FFD07C6A1B78906100348101003C7D08FE705D
+S3250001C0C080A100387C0540004082001880E100447CE7FE70808100407C043800418200A48F
+S3250001C0E080C1003854C60FFE90C1002C7C06000041820010386100384BFFFE5D814100345B
+S3250001C10080C1004054C60FFE7C06000041820010386100404BFFFE418141003438C10004C6
+S3250001C12038E10038810700008087000491060000908600043881000C38A1004080C5000040
+S3250001C14080E5000490C4000090E400047C07037890E10014914100184BFFFB9580C1002CEF
+S3250001C1607C0600004182000C806100344BFFFDE983E100007FE803A6382100304E80002037
+S3250001C1808101003C80E100447FE83BD67FFF39D67D1F4050910A000480CA00047CC6FE7067
+S3250001C1A090CA000083E100007FE803A6382100304E8000203821FFF081610020814100180F
+S3250001C1C02C0B0020418000387D46FE7090C300002C0B0040418000147D48FE70910300046D
+S3250001C1E0382100104E800020390BFFE07D48463091030004382100104E8000207C0B00000D
+S3250001C200418100189143000080E1001C90E30004382100104E8000207D465E3090C300007A
+S3250001C22038E000207CEB38507D47383080A1001C7CA55C307CE72B7890E3000438210010D4
+S3250001C2404E8000203821FFF081410020816100182C0A0020418000387C05037890A3000047
+S3250001C2602C0A0040418000147C05037890A30004382100104E800020390AFFE07D68443067
+S3250001C28091030004382100104E8000207C0A0000418100189163000080E1001C90E3000460
+S3250001C2A0382100104E8000207D66543090C3000038E000207CEA38507D67383080A1001CB7
+S3250001C2C07CA554307CE72B7890E30004382100104E8000203821FFF0814100208161001CB6
+S3250001C2E02C0A0020418000387C05037890A300042C0A0040418000147C05037890A300003B
+S3250001C300382100104E800020390AFFE07D68403091030000382100104E8000207C0A0000D7
+S3250001C320418100189163000480E1001890E30000382100104E8000207D66503090C3000427
+S3250001C34038E000207CEA38507D673C3080A100187CA550307CE72B7890E3000038210010A4
+S3250001C3604E80002080C1000880A100107CC6283890C300008081000C810100147C8440383E
+S3250001C380908300044E8000208101000880E100107D083B789103000080C1000C80A1001448
+S3250001C3A07CC62B7890C300044E80002080A10008812100107CA54A7890A300008101000CCD
+S3250001C3C080E100147D083A78910300044E8000208121000880E9000090E300008089000491
+S3250001C3E09083000480C9000438C6000190C90004808900047C0400004082001080A90000EE
+S3250001C40038A5000190A900004E8000208121000880C9000090C300008109000491030004A4
+S3250001C420810900047C08000040820010808900003884FFFF90890000808900043884FFFF6E
+S3250001C440908900044E800020812100087C6A1B7880A9000438A5000190A9000481090004D1
+S3250001C4607C0800004082001080890000388400019089000080890000908A000080C9000410
+S3250001C48090CA00044E800020812100087C6A1B7880E900047C0700004082001081090000DA
+S3250001C4A03908FFFF91090000810900043908FFFF9109000481090000910A000080A90004DF
+S3250001C4C090AA00044E8000207FE802A697E1FFD0814100388121003C90610034390100207C
+S3250001C4E08083000080A300049088000090A8000480A100402C0500064181029C4182023CBE
+S3250001C5002C05000341810164418201002C050001418200942C05000241820030480010D915
+S3250001C5208101003438A1002080C5000080E5000490C8000090E8000483E100007FE803A64F
+S3250001C540382100304E80002088AA000090A1002C7C07037890E1002838610020390100083C
+S3250001C5603881002880A4000080C4000490A8000090C8000438C1001038E1004481070000E5
+S3250001C5808087000491060000908600047D2803A64E80002180C100388101002499060000DD
+S3250001C5A04BFFFF8088AA00007CA5077490A1002C80E1002C54E70FFE90E100283861002059
+S3250001C5C038A1000838C1002880E600008106000490E500009105000439010010388100440B
+S3250001C5E080A4000080C4000490A8000090C800047D2803A64E8000218101003880A10024F8
+S3250001C60098A800004BFFFF1CA90A00009101002C80A1002C54A50FFE90A100283861002098
+S3250001C620390100083881002880A4000080C4000490A8000090C8000438C1001038E100446A
+S3250001C640810700008087000491060000908600047D2803A64E80002180C100388101002433
+S3250001C660B10600004BFFFEBC2C050004418200702C050005418200084BFFFEA4808A000099
+S3250001C6809081002C8081002C54840FFE908100283861002038E100083901002880880000C7
+S3250001C6A080A800049087000090A7000438A1001038C1004480E600008106000490E5000069
+S3250001C6C0910500047D2803A64E80002180A1003880E1002490E500004BFFFE48A10A0000EE
+S3250001C6E09101002C7C05037890A100283861002038C1000838E10028810700008087000492
+S3250001C70091060000908600043881001038A1004480C5000080E5000490C4000090E4000401
+S3250001C7207D2803A64E8000218081003880C10024B0C400004BFFFDEC808A00009081002C29
+S3250001C7407C040378908100283861002038A1000838C1002880E600008106000490E500007D
+S3250001C76091050004390100103881004480A4000080C4000490A8000090C800047D2803A683
+S3250001C7804E8000218101003880A1002490A800004BFFFD902C050007418200DC2C05000885
+S3250001C7A0418200D42C0500094182006C2C05000A418200084BFFFD6880CA000090C1002CF6
+S3250001C7C07C06037890C100283861002038E10008390100288088000080A800049087000055
+S3250001C7E090A7000438A1001038C1004480E600008106000490E50000910500047D2803A683
+S3250001C8004E80002180A1003880E1002490E500004BFFFD1080CA000090C1002C80C1002C44
+S3250001C82054C60FFE90C10028386100203881000838A1002880C5000080E5000490C40000D4
+S3250001C84090E4000438E10010390100448088000080A800049087000090A700047D2803A6DE
+S3250001C8604E80002180E1003880810024908700004BFFFCB0386100203881000880AA000053
+S3250001C88080CA000490A4000090C4000438C1001038E1004481070000808700049106000027
+S3250001C8A0908600047D2803A64E80002180C10038390100208088000080A8000490860000FD
+S3250001C8C090A600044BFFFC5C3821FFF081010018910300047C06037890C300003821001042
+S3250001C8E04E8000203821FFF081010018910300047D06FE7090C30000382100104E8000202E
+S3250001C9003821FFF080A1001890A300047C08037891030000382100104E8000203821FFF026
+S3250001C92080A1001890A300047CA8FE7091030000382100104E8000203821FFF080E1001842
+S3250001C94090E300047C05037890A30000382100104E8000203821FFF080E1001854E7801E39
+S3250001C9607CE88670910300047D06FE7090C30000382100104E8000203821FFF080A10018A2
+S3250001C98070A5FFFF90A300047C04037890830000382100104E8000203821FFF080C1001840
+S3250001C9A054C6C00E7CC7C67090E300047CE5FE7090A30000382100104E8000203821FFF0F7
+S3250001C9C080810018708400FF908300047C08037891030000382100104E8000203821FFF0FB
+S3250001C9E080810018708400FF5483C00E7C63C670382100104E80002080610008706300FF58
+S3250001CA004E8000203821FFF0808100187084FFFF5483801E7C638670382100104E8000202D
+S3250001CA20806100087063FFFF4E800020806100084E800020806100084E80002080610008B0
+S3250001CA404E800020806100084E800020810100087C0800004082001880A100047C0500007C
+S3250001CA604082000C7C0303784E800020386000014E80002080E10008808100107C07200055
+S3250001CA804082001480C100048101000C7C0640004182000C7C0303784E80002038600001D4
+S3250001CAA04E80002080A1000880E100107C0538004082001C8081000480C1000C7C0430004E
+S3250001CAC04082000C7C0303784E800020386000014E8000208101000480A1000C7C082800B3
+S3250001CAE04180002480E100048081000C7C0720004082001C80C10008810100107C0640407A
+S3250001CB004080000C386000014E8000207C0303784E80002080A1000480E1000C7C05380088
+S3250001CB20418000248081000480C1000C7C0430004082001C8101000880A100107C08284082
+S3250001CB404181000C386000014E8000207C0303784E80002080E100048081000C7C0720007C
+S3250001CB604181002480C100048101000C7C0640004082001C80A1000880E100107C053840C2
+S3250001CB804081000C386000014E8000207C0303784E8000208081000480C1000C7C04300050
+S3250001CBA0418100248101000480A1000C7C0828004082001C80E10008808100107C072040EE
+S3250001CBC04180000C386000014E8000207C0303784E80002080C100048101000C7C0640403D
+S3250001CBE04180002480A1000480E1000C7C0538004082001C8081000880C100107C043040D6
+S3250001CC004080000C386000014E8000207C0303784E8000208101000480A1000C7C08284033
+S3250001CC204180002480E100048081000C7C0720004082001C80C10008810100107C06404038
+S3250001CC404181000C386000014E8000207C0303784E80002080A1000480E1000C7C05384005
+S3250001CC60418100248081000480C1000C7C0430004082001C8101000880A100107C08284040
+S3250001CC804081000C386000014E8000207C0303784E80002080E100048081000C7C072040FC
+S3250001CCA04181002480C100048101000C7C0640004082001C80A1000880E100107C05384081
+S3250001CCC04180000C386000014E8000207C0303784E8000208121000C814100088081001484
+S3250001CCE080A100107CC921D67CE920167D0451D67CE742147D0549D67CE7421490C3000413
+S3250001CD0090E300004E8000208881000B3863FFFF8CC300017C062000418200107C060000B7
+S3250001CD204082FFF07C0303784E800020906100048081000C7C0400004081007C80A100086B
+S3250001CD4054A5063E50A5442E50A5801E7CA62B787CA72B787CA82B782C04001040810050F2
+S3250001CD607069000741820018212900087D2103A67CA01D2A7C634A147C8920507C892671A7
+S3250001CD804081002C7D2903A690A300003943000890C3000490EA0000386A0008910A00047F
+S3250001CDA04200FFE85484073F4182000C7C8103A67CA01D2A806100044E8000209061000485
+S3250001CDC08121000C7C6A1B787C090000418200A841800184816100082C0900104081008C73
+S3250001CDE07DAB4A147D8A4A147C0A5840418100CC7D67527870E7000340820084714700038C
+S3250001CE004182002020E700047D2748507CE103A67E005C2A7D6B3A147E00552A7D4A3A148F
+S3250001CE207D2E2671408100447DC903A6396BFFFC394AFFFC860B0004960A0004862B0004AA
+S3250001CE40962A0004860B0004960A0004862B0004962A00044200FFE05529073F4182001895
+S3250001CE60396B0004394A00047D2103A67E005C2A7E00552A806100044E8000207D2E26711F
+S3250001CE80408100247DC903A67E0B84AA396B00107E0A85AA394A00104200FFF05529073F0D
+S3250001CEA04182FFD47D2103A67E005C2A7E00552A806100044E8000202C090004418000843C
+S3250001CEC07DA7627870E700034082007871A70003418200188E0DFFFF9E0CFFFF3929FFFF22
+S3250001CEE071A700034082FFF07D2E2671408100347DC903A6860DFFFC960CFFFC862DFFFC60
+S3250001CF00962CFFFC860DFFFC960CFFFC862DFFFC962CFFFC4200FFE05529073F4182FF58B8
+S3250001CF207D2E16714081001C7DC903A6860DFFFC960CFFFC4200FFF8552907BF4182FF384A
+S3250001CF407C0D58404081FF308E0DFFFF9E0CFFFF4BFFFFF090000000806100044E800020DC
+S3250001CF604BFFFE5C3821FFD08281003881C1003C7C731B787C6B1B787C1203787C0D03781C
+S3250001CF807C1003787C0F0378888B00007C8407742C04000C41810268418202502C04000939
+S3250001CFA0418202482C04000A418202402C04000B4182023888CB00007CC607742C06002D77
+S3250001CFC04182020888EB00007CE707742C07002B418201F87C0E00004082001888AB00007B
+S3250001CFE07CA507742C050030418201B039C0000A2C0E0002418000782C0E002441810070B1
+S3250001D0002C0E00104082001488EB00007CE707742C070030418200F07C0D037838A0FFFFA8
+S3250001D0207E25739688CB00007CC607747CCA33787DCC73782C0600304180000C2C0A00396A
+S3250001D040408100BC2C0A00614180000C2C0A007A408100A42C0A00414180000C2C0A005AFF
+S3250001D0604081008C7C0C7000418000547C100000408200087E6B9B787C14000041820008A2
+S3250001D080917400007C0F0000418200103860FFFF382100304E8000207C12000041820014B4
+S3250001D0A07C0303787C6D1850382100304E8000207DA36B78382100304E8000207C0D8840DC
+S3250001D0C04081000839E000017CAD71D67D4562147C0A68404080000839E000017D4D537819
+S3250001D0E0396B00013A1000014BFFFF3C398AFFC94BFFFF74398AFFA94BFFFF6C398AFFD0BA
+S3250001D1004BFFFF64890B00017D0807742C08007841820018888B00017C8407742C04005828
+S3250001D120418200084BFFFEF488AB00027CA507742C0500304180001C88CB00027CC60774C0
+S3250001D1402C0600394181000C396B00024BFFFECC88EB00027CE707742C0700614180001419
+S3250001D160890B00027D0807742C0800664081FFDC888B00027C8407742C0400414180FE9C80
+S3250001D18088AB00027CA507742C0500464181FE8C396B00024BFFFE8439C00008890B0001EC
+S3250001D1A07D0807742C08007841820018888B00017C8407742C040058418200084BFFFE3483
+S3250001D1C039C000104BFFFE2C7D685B78396B0001890800007D0807742C08002D4082FDF8C5
+S3250001D1E03A4000014BFFFDF0396B0001888B00007C8407742C04000C4081FDA02C04000D6C
+S3250001D2004182FFE82C0400204182FFE04BFFFDA87FE802A697E1FFD8814100309061002C0F
+S3250001D22088AA00007CA5077490A100207C0500004082001483E100007FE803A6382100287C
+S3250001D2404E8000207D435378480001819061001C8061002C80A1002090A100084BFFFAADFF
+S3250001D2607C691B787C0900004182005C7D234B789121002480810030908100088101001C6A
+S3250001D2809101000C480000CD812100247C030000408200187D234B7883E100007FE803A6DE
+S3250001D2A0382100284E8000203869000180C1002090C100084BFFFA557C691B787C09000006
+S3250001D2C04082FFAC7C03037883E100007FE803A6382100284E8000207FE802A697E1FFE88F
+S3250001D2E07C691B7880A100207C050000408200247D234B787C080378910100084BFFFA0DBA
+S3250001D30083E100007FE803A6382100184E8000207C040378908100147D234B78810100200E
+S3250001D320910100084BFFF9E57C0300004182001039230001906100144BFFFFE08061001452
+S3250001D34083E100007FE803A6382100184E8000203821FFF081A100188141001C7C6C1B7818
+S3250001D3607C0A0000408100587D896378398C0001892900007D2907747DAB6B7839AD00019B
+S3250001D380896B00007D6B0774394AFFFF7C095800418200247C095840408100103860000163
+S3250001D3A0382100104E8000203860FFFF382100104E8000207C0900004082FFA87C0303783A
+S3250001D3C0382100104E8000207FE802A697E1FFF0906100147C07037890E100084BFFF92D8D
+S3250001D3E0810100147C68185083E100007FE803A6382100104E8000207FE802A697E1FFE013
+S3250001D400814100287C691B789061001C7D234B789121002491410028914100087C0803788A
+S3250001D4209101000C3900271091010010480001617C0300004082001880A100243925271058
+S3250001D44081010028394827104BFFFFC48061001C83E100007FE803A6382100204E8000207E
+S3250001D4603821FFF0818100187C6B1B787D695B78396B0001892900007D2907747D8A6378B6
+S3250001D480398C0001894A00007D4A07747C095000418200247C09504040810010386000016F
+S3250001D4A0382100104E8000203860FFFF382100104E8000207C0900004082FFB47C0303782D
+S3250001D4C0382100104E8000203821FFE8812100247C6D1B78818100207C0900404081005074
+S3250001D4E07DAB6B7839AD0001896B00007D8A6378398C0001894A00007C0B50004182002406
+S3250001D5007C0B50404081001038600001382100184E8000203860FFFF382100184E8000202F
+S3250001D5203929FFFF7C0900404181FFB87C030378382100184E8000203821FFF08121001CE7
+S3250001D5407C6A1B7880E1001870EB00FF7C090040408100307D475378394A000188E7000040
+S3250001D5607C07580040820010386AFFFF382100104E8000203929FFFF7C0900404181FFD842
+S3250001D5807C030378382100104E8000203821FFF0812100207C6A1B78816100188081001C99
+S3250001D5A0708C00FF7C090040408100407D465378394A00017D645B78396B0001888400002C
+S3250001D5C0988600005484063E7C046000408200107D435378382100104E8000203929FFFF16
+S3250001D5E07C0900404181FFC87C030378382100104E8000207C040378808400007C04000006
+S3150001D600418200084BFFFFF04E8000200000000021
+S3250001D61000810E02001415F0001403E80000000000146530000000010000000000000000A0
+S3250001D6300000000000000000FFFFFFFF0000001E0000001D0000001C0000001B0000000065
+S3250001D6500000000000000000000000000000000000000000000000000000000000000000B3
+S3250001D670000000000000000000000000000000000000000000000000000000000000000093
+S3250001D690FFFFFFFF00000A0000000A2000000A4000000A6000140104000000000000000076
+S3250001D6B0000000000000000000000000000000012A2A2A000000000023706C616E392E6936
+S3250001D6D06E690A00000000005250587369676E61747572653D312E300A4E414D453D71627F
+S3250001D6F0727063670A53544152543D46464332303130300A56455253494F4E3D312E310AC9
+S3250001D710000000000001000000000401080205030C06060909070710100000000000000082
+S3250001D7306672656562007167657400000000000000141BAF0000000000000000000000003F
+S3250001D7500000000000000000000000000000000000000000000000000000000000000000B2
+S3250001D770000000000000000000000000000000000000000000000000000000000000000092
+S3250001D79000000000000000000000000000000000626F6F74006469736B00626F6F740075EA
+S3250001D7B06172743A207374617274207472616E736D697373696F6E0A00756172743A2074A5
+S3250001D7D0696D656F75740A006E007900000000000000000000000000001403200000000077
+S3250001D7F0000000000000000000000000000000000000000000000000000000000000000012
+S3250001D8100000000000000000000000000000000000000000000000000000000000000000F1
+S3250001D8300000000000000000FFC206F000000000000000000000000000000000000000001A
+S3250001D8500000000000000000000000000000000000000000000000000000000000000000B1
+S3250001D87000000000000000000000000000000000000000000000000000141A00FFC26E38FC
+S3250001D89000141A04FFC26E3800000000000000006D6170667265653A2025733A206C6F735E
+S3250001D8B0696E672030782575582C2025640A000000141A9300141AA700141AB300141AC312
+S3250001D8D0000000000014054000000000000000006E6577616C61726D000000000000000081
+S3250001D8F00000000000000000F1A55A1FFFC2363000000000000000000000000000000000DB
+S3250001D9100000000000000000FFFFFFFF0000000000000004000000080000000C00000000DC
+S3250001D9306275666665722064657363726970746F7273006264616C6C6F63000000000000B3
+S3250001D95000141A810000000000141A860000000100141A8C00000002000000000000000090
+S3250001D970FFFFFFFFFFFF000000000000000000000000000000000000000000000000000096
+S3250001D9900000000000000000000000000000000000000000000000000000000013880000D5
+S3250001D9B0FFFFFFFFFA203C00FA203D00FA203E00FA203F000000000000141FD70014203B7D
+S3250001D9D06932632073657475702E2E2E0A004932432325780A0000000000000B00000000BA
+S3250001D9F0000000000000000000140E4000000000000000200000000000000000000000008E
+S3250001DA10000004000000000E0000000000000000000004000000000E0000000000000000CB
+S3250001DA3041F0000000000000001407460014074C0014075100140754001407580014075B12
+S3250001DA500014075E0014076200140766001407690014076C0014076F001407720014077586
+S3250001DA70001407780014077B0014077E0014078100140784001407880014078C001407909D
+S3250001DA9000140794001407980014079C001407A0001407A4001407A8001407AC001407B087
+S3250001DAB0001407B4001407B8001407BC001407C0001407C4001407C8001407CC001407D067
+S3250001DAD0001407D4001407D8FFC24714FFC2474CFFC24798FFC247BCFFC247C4FFC247CCD9
+S3250001DAF0FFC247F0FFC24830FFC24838FFC2485CFFC2488C000000000000000000000000A3
+S3250001DB100000000000000000000000000000000000000000000000000000000000000000EE
+S3250001DB300000000000000000000000000000000000000000000000000000000000000000CE
+S3250001DB507072656D617475726520454F460A002E00626164206D61676963203078256C7591
+S3250001DB7078206E6F74206120706C616E20392065786563757461626C65210A002564002BDF
+S3250001DB9025644025382E386C7578002B25640A7374617274206174203078256C75780A0058
+S3250001DBB000000000000000000000000000000000000000000000000000000000000000004E
+S3250001DBD000000000000A000000000000000000000000000000000000000000000000000024
+S3250001DBF0000000000000000000000000000000000000000000000000090000000000000005
+S3250001DC100000000102000000030000000400000500000006000700000800000000000000C9
+S3250001DC30726573657276656420300073797374656D207265736574006D616368696E652040
+S3250001DC50636865636B00646174612061636365737300696E737472756374696F6E206163DD
+S3250001DC70636573730065787465726E616C20696E7465727275707400616C69676E6D656E24
+S3250001DC90740070726F6772616D20657863657074696F6E00666C6F6174696E672D706F6949
+S3250001DCB06E7420756E617661696C61626C650064656372656D656E74657200726573657218
+S3250001DCD0766564204100726573657276656420420073797374656D2063616C6C0074726123
+S3250001DCF06365207472617000666C6F6174696E6720706F696E742061737369737400726542
+S3250001DD10736572766564204600736F66747761726520656D756C6174696F6E0049544C4279
+S3250001DD30206D6973730044544C42206D6973730049544C42206572726F720044544C422033
+S3250001DD506572726F72004341555345005352523100504300474F4B004C52004352005845A5
+S3250001DD7052004354520052300052310052320052330052340052350052360052370052389B
+S3250001DD900052390052313000523131005231320052313300523134005231350052313600E7
+S3250001DDB052313700523138005231390052323000523231005232320052323300523234008D
+S3250001DDD0523235005232360052323700523238005232390052333000523331007365746866
+S3250001DDF0766563006F7574206F6620696E746572727570742068616E646C6572730025736B
+S3250001DE1009252E386C757809257309252E386C75780A00657863657074696F6E2F696E741D
+S3250001DE30657272757074202325780A00657863657074696F6E2025730A005E5020746F20DD
+S3250001DE5072657365740A00005573696E6720666C61736820636F6E66696775726174696F20
+S3250001DE706E0A000A002573256400747970653D00706F72743D006972713D006D656D3D00E2
+S3250001DE9073697A653D0065613D00000000000000676574636C75737420402025640A00678B
+S3250001DEB06574636C75737420256420696E2063616368650A00676574636C75737420616439
+S3250001DED064722025640A0063616E2774207365656B20626C6F636B0A0063616E2774207279
+S3250001DEF065616420626C6F636B0A00676574636C75737420256420726561640A0066617497
+S3250001DF1077616C6B2025640A006765746661740066617477616C6B202564202D3E20256446
+S3250001DF300A0066696C65616464722025382E38732025640A0066696C656164647220256498
+S3250001DF50202D3E2025640A0066696C6561646472202564202D3E2025640A0077616C6B6932
+S3250001DF706E67206E6F6E2D6469726563746F7279210A00636F6D706172696E6720746F203A
+S3250001DF9025382E38732E25332E33730A0025382E38732E25332E33732069732061204C4116
+S3250001DFB042454C0A0063616E2774207265616420626F6F7420626C6F636B0A006E6F74206A
+S3250001DFD0444F530A006E6F20646F732066696C652073797374656D0A006D616769633A200D
+S3250001DFF0307825322E327820307825322E327820307825322E32780A0076657273696F6E35
+S3250001E0103A202225382E3873220A007365637473697A653A2025640A00616C6C6F637369CD
+S3250001E0307A653A2025640A006E72657372763A2025640A006E666174733A2025640A0072F5
+S3250001E0506F6F7473697A653A2025640A00766F6C73697A653A2025640A006D656469616452
+S3250001E0706573633A20307825322E32780A0066617473697A653A2025640A0074726B736903
+S3250001E0907A653A2025640A006E68656164733A2025640A006E68696464656E3A2025640A76
+S3250001E0B000626967766F6C73697A653A2025640A0064726976656E6F3A2025640A00726563
+S3250001E0D0736572766564303A20307825322E32780A00626F6F747369673A20307825322EB7
+S3250001E0F032780A00766F6C69643A20307825382E38780A006C6162656C3A20222531312EBF
+S3250001E110313173220A006E616D6520636F6D706F6E656E7420746F6F206C6F6E670A0065A2
+S3250001E13072726F722077616C6B696E6720746F2025730A002573206E6F7420666F756E64EC
+S3250001E1500A00666F756E642025382E38732E25332E3373206174747220307825757820738A
+S3250001E17074617274203078256C7578206C656E2025640A00626164206D6167696320307865
+S3250001E190256C7578206E6F74206120706C616E20392065786563757461626C65210A002B3C
+S3250001E1B02564002B2564002B25640A7374617274206174203078256C75780A002E006E61DD
+S3250001E1D06D652069732025382E38732025332E33730A0000000000002E007A71733A206E5A
+S3250001E1F06F7420706F77657250432065786563757461626C650A0074657874007A71733A9C
+S3250001E21020666F726D6174206572726F720A0064617461007A71733A20666F726D617420EF
+S3250001E2306572726F720A000A73717565657A6564206B65726E656C3A20636865636B737542
+S3250001E2506D206572726F723A2025382E386C7578206E6565642025382E386C75780A007503
+S3250001E2706E7061636B2025732025382E386C757820256C75643A00202A2A73697A6520650E
+S3250001E29072726F720A000A007A71733A20636F72727570742073717565657A65642064615C
+S3250001E2B074612073747265616D0A00205425640025642025382E386C75782025382E386CAB
+S3250001E2D075780A0000000000666C6173683A2062616420636865636B73756D0A00666C61F1
+S3250001E2F073683A20666C617368206E6F742070726573656E74206F72206E6F7420656E616C
+S3250001E310626C65640A00636F6E66202325382E386C75783A20232578202325362E366C7543
+S3250001E330780A00666C6173683A20666F756E6420636F6E6669672025382E386C75782825A1
+S3250001E35064293A0A25730A00666C6173683A206E6F20636F6E6669670A00666C6173682020
+S3250001E370636F6E6669672025382E386C7578282564293A0A25730A00666C6173683A207339
+S3250001E390717565657A656420706F7765727063206B65726E656C20696E7374616C6C6564D2
+S3250001E3B00A00666C6173683A20756E73717565657A656420706F7765727063206B65726E9B
+S3250001E3D0656C20696E7374616C6C65640A00666C6173683A206E6F20706F776572706320E6
+S3250001E3F06B65726E656C20696E20466C6173680A00746578743A2025382E386C7578203CDF
+S3250001E4102D2025382E386C7578205B256C645D0A00646174613A2025382E386C7578203C39
+S3250001E4302D2025382E386C7578205B256C645D0A00656E7472793D3078256C75780A0000E6
+S3250001E450907070F0F0F07000F0888888F8707070E0E0E0E0E09070F070F870F0F870F0882D
+S3250001E470000000000000000000000000000000000000000000000000000000000000000085
+S3250001E490000000000000000000000000000000000000000000000000000000000000000065
+S3250001E4B000000000000000000000000000000000000000000000000000000000000000E065
+S3250001E4D0D0808080808088008888C888808888889090909090D0808080808080808888881D
+S3250001E4F000000000080000000C3000000000000600000000000000000000000000000000BB
+S3250001E5100000000000000000000000000000000000000000000000000000003CC03C0000AC
+S3250001E5300000600006001E00601818607800000000000000000000000000001C18380090DC
+S3250001E550B06060E0E0E0F800F088A888808080809090909090B060E0808060E080808888E4
+S3250001E570001824283E70701818180000000000063C183C3C1C3E3C7E3C3C00000200403CDE
+S3250001E5903C187C1E787E7E1E663C7C666066623C7C3C7C3C7E6266C266667E30C00C10002E
+S3250001E5B008006000060030006018186018000000000000001000000000000030180C0090AA
+S3250001E5D0901010808080881888F8A888E0807070E0E0E0E0E090108070E01080E098F08814
+S3250001E5F0001824286ADAD818181810000000000C663866662C3E667E6666000006006066D0
+S3250001E610421866326C606032661818646066722466246666186262DA62620630600C380093
+S3250001E63010006000060030006000006018000000000000003000000000000030180C00E0E1
+S3250001E65000E0E0F0F0F000188888985080880808201C1C1C1C00E0F00080E0F08088888823
+S3250001E6700018242868DAD808300C54180000000C665806062C206002666618180CFE300695
+S3250001E6909E2C6660666060606618186C6066726666666660186262DA36660C30600C2800F9
+S3250001E6B0103C6C3C3E3C7E3E6C78786618D46C3C6C3E763C7E6666C266667E1818180000C9
+S3250001E6D04418000018241C24F08888208070F0F020202020201C243E1CF8241C8070887001
+S3250001E6F00018247C78745008300C381800000018661806064C2060067666181818FE180CC1
+S3250001E710B62C66606660606066181868607E5A6666666470186266DA34340C30300C6C0072
+S3250001E73018667666666630667618186418FE766676663666306662DA626206081810323C58
+S3250001E75044247C7C2434204200000000000000002020202020222408220024200000000034
+S3250001E770001800283C287610300CEE7E00FE001866180C184C3C7C0C3C3E000030000C181A
+S3250001E790B62C7C60667C7C6E7E181878605A5A666466783C186234DA18341830300C44001E
+S3250001E7B018066660666630666618186818D6666666663860306662DA34620C30180C5A209E
+S3250001E7D044241010242C20420E3E103E3E3C1C3E3C1C1C1C1C3E1C083E2224180E0E0E0E98
+S3250001E7F00008007C1E5CDC00300C387E00FE0030661818067E0666186E06000018001818AE
+S3250001E810B67E6660666060666618186C605A4E6678666C0E1862346C2C183030180C44006D
+S3250001E830003E6660667E30666618187818D666666666303C306634DA1834180818104C3887
+S3250001E8503C18101018241C4211081008202222080000000000220408223618041111111110
+S3250001E8700000002816B6CC00300C541800000030661830067E066618660600000CFE30008D
+S3250001E8909A466660666060666618186C605A4E66606666061862346C6C183030180C00006B
+S3250001E8B000666660666030666618186C18D66666666630063066346C2C34301818180020CD
+S3250001E8D000091010000E094210081008202222080F06060F0A09041E002A0E3810101010F4
+S3250001E8F00018002856B6CC00300C10181800186066187E660C6666306666181806FE601813
+S3250001E910404666326C60603666181866605A4624602466661834186C461860300C0C00001A
+S3250001E930006E66666E66306E6618186618D66666666E3066306E186C46186030180C003C84
+S3250001E950080909091F110AFF0E081008382C2208080209010A0A0911092209070E0E0E0ED3
+S3250001E970001800287C1C760018180000180018603C7E7E3C0C3C3C303C3C18180200401848
+S3250001E9903E467C1E787E601E663C18667E42463C603C663C1818186C66187E300C0C000036
+S3250001E9B000367C3C363C7C36667E18667ED6663C7C367C3C1E36186C66187E30180C00083C
+S3250001E9D0080F060604110C1801081008202222080E0202030A0C0D1E0D220E080101010198
+S3250001E9F0000000001000000018180000080000C000000000000000000000000800000000F0
+S3250001EA1000000000000000000000180000000000000C00000000000000000030060C00FE7B
+S3250001EA300000000000000006000018000000000060060000000000000010001C18380008B7
+S3250001EA5008090606040E0A1811081F0820221C3E080204010F0A0B110B22090811111111AC
+S3250001EA7000000000000000000C300000080000C00000000000000000000000080000000073
+S3250001EA900000000000000000000070000000000000060000000000000000003C063C00006B
+S3250001EAB0000000000000006600001800000000006006000000000000003000000000000823
+S3250001EAD00F090909040309000E000000000000000F0F0F0F0209091E09000F070E0E0E0E12
+S3250001EAF00000000000000000000000001000000000000000000000000000001000000000DF
+S3250001EB100000000000000000000000000000000000000000000000000000000000000000DE
+S3250001EB30000000000000003C00007000000000006006000000000000006000000000000F3D
+S3250001EB50636F6E736F6C65006C63640073637265656E006C63640062617564005E70002536
+S3250001EB70735B64656661756C743D3D25735D3A200025733A20000A006C696E6520746F6FEC
+S3250001EB90206C6F6E670A0070616E69633A20000A0000000000000000001406200014062B96
+S3250001EBB000140638001406460014065200140665001406780014068200140694001406AFFC
+S3250001EBD0001406BB001406C6001406D1001406DD001406E8001406FE001407090014071C12
+S3250001EBF000140726001407300014073B000000000000000E000800000008000E00080000E8
+S3250001EC100010000E000800000018000E000800000020000E000800000028000E0008000015
+S3250001EC300030000E000800000038000E000800000040000E000800000048000E0008000075
+S3250001EC500050000E000800000058000E000800000060000E000800000068000E00080000D5
+S3250001EC700070000E000800000078000E000800000080000E000800000088000E0008000035
+S3250001EC900090000E000800000098000E0008000000A0000E0008000000A8000E0008000095
+S3250001ECB000B0000E0008000000B8000E0008000000C0000E0008000000C8000E00080000F5
+S3250001ECD000D0000E0008000000D8000E0008000000E0000E0008000000E8000E0008000055
+S3250001ECF000F0000E0008000000F8000E0008000001000000000800000108020B00080000C2
+S3250001ED1001100206000800000118020B000800000120010C000800000128020B0008000019
+S3250001ED300130020B0008000001380207000800000140010D000800000148010D0008000076
+S3250001ED500150030A000800000158040A000800000160090E000800000168060800080000C8
+S3250001ED700170090B000800000178010D000800000180020B000800000188020B000800002C
+S3250001ED900190020B000800000198020B0008000001A0020B0008000001A8020B0008000094
+S3250001EDB001B0020B0008000001B8020B0008000001C0020B0008000001C8020B00080000F4
+S3250001EDD001D0040B0008000001D8040E0008000001E0020B0008000001E8040A000800004C
+S3250001EDF001F0020B0008000001F8020B000800000200020B000800000208020B00080000B2
+S3250001EE100210020B000800000218020B000800000220020B000800000228020B000800000F
+S3250001EE300230020B000800000238020B000800000240020B000800000248020B000800006F
+S3250001EE500250020D000800000258020B000800000260020B000800000268020B00080000CD
+S3250001EE700270020B000800000278020B000800000280020B000800000288020D000800002D
+S3250001EE900290020B000800000298020B0008000002A0020B0008000002A8020B000800008F
+S3250001EEB002B0020B0008000002B8020B0008000002C0020B0008000002C8020B00080000EF
+S3250001EED002D0020B0008000002D8010D0008000002E0010D0008000002E8010D000800004C
+S3250001EEF002F002080008000002F80B0C0008000003000207000800000308040B00080000A8
+S3250001EF100310010B000800000318040B000800000320010B000800000328040B0008000008
+S3250001EF300330010B000800000338040E000800000340010B000800000348010B0008000068
+S3250001EF500350010E000800000358010B000800000360010B000800000368040B00080000C8
+S3250001EF700370040B000800000378040B000800000380040E000800000388040E000800001C
+S3250001EF900390040B000800000398040B0008000003A0020B0008000003A8040B0008000084
+S3250001EFB003B0040B0008000003B8040B0008000003C0040B0008000003C8040E00080000DF
+S3250001EFD003D0040B0008000003D8010C0008000003E0010C0008000003E8010C0008000048
+S3250001EFF003F005080008000003F8000E000800000400000E000800000000000000000000C7
+S3250001F010534343005343433200657468657225643A2025733A20706F7274203078256C7575
+S3250001F0305820697271202564002061646472203078256C7558002073697A65203078256C37
+S3250001F0507558003A002025322E327558000A00657468657225643A207478207175657565B8
+S3250001F0702066756C6C0A0000666C6173680046006574686572006500617461006864006861
+S3250001F090006175746F006C6F63616C006D616E75616C00696E6665726E6F2F696E666572E3
+S3250001F0B06E6F2E696E6900696E6665726E6F2E696E6900706C616E392F706C616E392E6901
+S3250001F0D06E6900706C616E392E696E69002100002573212564006469736B002573212564A0
+S3250001F0F0212573006469736B00696D706300257321256421257300626F6F74006469736B92
+S3250001F11000646F73006469736B00646F7320696E6974206661696C65640A00707265646132
+S3250001F130776E0A006461776E0A006F7074696F6E733D232575780A00466C61736820626FAE
+S3250001F1506F740A00626F6F7466696C650042616420626F6F7466696C652073796E74617815
+S3250001F1703A2025730A0043616E6E6F7420616363657373206465766963653A2025730A00FB
+S3250001F190426F6F7420646576696365733A00202573212564002025732125640020257321EA
+S3250001F1B02564000A00626F6F742066726F6D00706879736963616C206D656D6F727900699E
+S3250001F1D0616C6C6F63006672656500000000000045544845522E5343432325643A20736310
+S3250001F1F06365203D2030782575580A007E0040006E6F207072657365742045746865722089
+S3250001F210616464726573730A00303031303862663132393030006574686572204D41432001
+S3250001F2306164647265737300696E76616C6964204D414320616464726573730A00000000E9
+S3250001F2500A746674703A206572726F72282564293A2025730A0069702063686B73756D20D1
+S3250001F2706572726F720A0069702062616420766572732F686C656E0A007564702063686BC4
+S3250001F29073756D206572726F72206373756D202325346C7578206C656E2025640A00756400
+S3250001F2B0703A207061636B657420746F6F206269670A002573006F637465740074667470B2
+S3250001F2D06F70656E3A206572726F7220282564293A2025730A00746674706F70656E3A2021
+S3250001F2F0626C6F636B206572726F723A2025640A00626C6F636B206572726F720074667412
+S3250001F310706F70656E3A206661696C656420746F20636F6E6E65637420746F207365727605
+S3250001F33065720A0074667470726561643A20256420213D2025640A0073686F727420726540
+S3250001F3506164003F0074667470726561643A20626C6F636B206572726F723A2025642C205A
+S3250001F37065787065637465642025640A00626C6F636B206572726F7200696E76616C696435
+S3250001F3902063746C726E6F2025640A00626F6F74702074696D6564206F75740A0025732060
+S3250001F3B0002825642E25642E25642E2564212564293A2025730A00626164206D6167696349
+S3250001F3D0206E756D626572006C6F61644025382E386C75783A20002564002B2564006F6B00
+S3250001F3F0002B25643D25640A00656E7472793A203078256C75780A000000000000141A6820
+S3250001F41000000008FFC27AE40000000000000000000000000000000000141A6E0000000012
+S3250001F43000000000000000000000000200141A7000000004FFC26068000000000000000088
+S3250001F45000000000000000000000000000141A7600000000000000000000000300141A7848
+S3250001F470000000130000000000000000000000000000000000141A7C00141A7F000000000B
+S3250001F4900000000000000000FFFFFFFF000000000000000000000000000000000000000059
+S3250001F4B0000000000000000000000000000000000000000000000000496E6665726E6F2044
+S3250001F4D0626F6F7473747261700A005056523A20004D5043363031004D5043363033004D9E
+S3250001F4F05043363034004D504336303365004D5043363033652D7637004D5043387878002A
+S3250001F510506F77657250432076657273696F6E20232578002C207265766973696F6E202330
+S3250001F530256C75780A00494D4D523A20004D50433836302F383231004D5043383233004D8B
+S3250001F55050433832334100547970652023256C7578002C206D61736B2023256C75780A00FD
+S3250001F5706F7074696F6E733A2023256C75780A00626373723A2025382E386C75780A0050E9
+S3250001F5904C505243523D25382E386C757820534343523D25382E386C75780A00256C756460
+S3250001F5B0204D487A2073797374656D0A000A004252303D25382E386C7578204F52303D25BC
+S3250001F5D0382E386C75780A004D505450523D25382E386C75780A006574686572303D7479AB
+S3250001F5F070653D53434320706F72743D312065613D3030313065633030303035310D0A7657
+S3250001F610676173697A653D3634307834383078380D0A6B65726E656C70657263656E743DEF
+S3250001F63034300D0A636F6E736F6C653D300D0A626175643D393630300D0A006574686572EA
+S3250001F650303D747970653D53434320706F72743D322065613D303031306563303030303559
+S3250001F670310D0A76676173697A653D3634307834383078380D0A6B65726E656C7065726355
+S3250001F690656E743D34300D0A636F6E736F6C653D300D0A626175643D393630300D0A0055C9
+S3250001F6B073696E672064656661756C7420636F6E66696775726174696F6E0A00414D4432D7
+S3250001F6D039463078300053434300454100693263206661696C65640A00656570726F6D3A0E
+S3250001F6F00A002025322E3275785B25635D000A00CFFFCC240FFFCC040CAFCC0403AFCC082E
+S3250001F7103FBFCC27FFFFCC25FFFFCC25FFFFCC25CFFFCC240FFFCC040CAFCC8403AFCC8867
+S3250001F7303FBFCC27FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC2538
+S3250001F750FFFFCC25FFFFCC25FFFFCC25FFFFCC25CFFFCC240FFFCC040CFFCC0403FFCC0091
+S3250001F7703FFFCC27FFFFCC25FFFFCC25FFFFCC25CFFFCC240FFFCC040CFFCC8403FFCC842B
+S3250001F7900CFFCC0033FFCC27FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25BC
+S3250001F7B0FFFFCC25FFFFCC25FFFFCC25FFFFCC25C0FFCC2403FFCC240FFFCC240FFFCC24D9
+S3250001F7D03FFFCC27FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC25FFFFCC2558
+S3150001F7F0FFFFCC25FFFFCC25FFFFCC25FFFFCC2546
+S700000100FE
--- /dev/null
+++ b/os/boot.original/rpcg/gbitbltclip.c
@@ -1,0 +1,52 @@
+#include <u.h>
+#include <libc.h>
+#include <libg.h>
+#include <gnot.h>
+
+void
+gbitbltclip(void *vp)
+{
+ int dx, dy;
+ int i;
+ struct{
+ GBitmap *dm;
+ Point p;
+ GBitmap *sm;
+ Rectangle r;
+ Fcode f;
+ }*bp;
+
+ bp = vp;
+ dx = Dx(bp->r);
+ dy = Dy(bp->r);
+ if(bp->p.x < bp->dm->clipr.min.x){
+ i = bp->dm->clipr.min.x-bp->p.x;
+ bp->r.min.x += i;
+ bp->p.x += i;
+ dx -= i;
+ }
+ if(bp->p.y < bp->dm->clipr.min.y){
+ i = bp->dm->clipr.min.y-bp->p.y;
+ bp->r.min.y += i;
+ bp->p.y += i;
+ dy -= i;
+ }
+ if(bp->p.x+dx > bp->dm->clipr.max.x)
+ bp->r.max.x -= bp->p.x+dx-bp->dm->clipr.max.x;
+ if(bp->p.y+dy > bp->dm->clipr.max.y)
+ bp->r.max.y -= bp->p.y+dy-bp->dm->clipr.max.y;
+ if(bp->r.min.x < bp->sm->clipr.min.x){
+ i = bp->sm->clipr.min.x-bp->r.min.x;
+ bp->p.x += i;
+ bp->r.min.x += i;
+ }
+ if(bp->r.min.y < bp->sm->clipr.min.y){
+ i = bp->sm->clipr.min.y-bp->r.min.y;
+ bp->p.y += i;
+ bp->r.min.y += i;
+ }
+ if(bp->r.max.x > bp->sm->clipr.max.x)
+ bp->r.max.x = bp->sm->clipr.max.x;
+ if(bp->r.max.y > bp->sm->clipr.max.y)
+ bp->r.max.y = bp->sm->clipr.max.y;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/gnot.h
@@ -1,0 +1,71 @@
+
+extern void *bbmalloc(int);
+extern void bbfree(void *, int);
+extern int bbonstack(void);
+extern void bbexec(void(*)(void), int, int);
+
+/*
+ * Graphics types
+ */
+
+typedef struct GBitmap GBitmap;
+typedef struct GFont GFont;
+typedef struct GSubfont GSubfont;
+typedef struct GCacheinfo GCacheinfo;
+
+struct GBitmap
+{
+ ulong *base; /* pointer to start of data */
+ long zero; /* base+zero=&word containing (0,0) */
+ ulong width; /* width in 32 bit words of total data area */
+ int ldepth; /* log base 2 of number of bits per pixel */
+ Rectangle r; /* rectangle in data area, local coords */
+ Rectangle clipr; /* clipping region */
+ GBitmap *cache; /* zero; distinguishes bitmap from layer */
+};
+
+
+/*
+ * GFont etc. are not used in the library, only in devbit.c.
+ * GSubfont is only barely used.
+ */
+struct GSubfont
+{
+ short n; /* number of chars in font */
+ char height; /* height of bitmap */
+ char ascent; /* top of bitmap to baseline */
+ Fontchar *info; /* n+1 character descriptors */
+ GBitmap *bits; /* where the characters are */
+};
+struct GCacheinfo
+{
+ ulong xright; /* right edge of bits */
+ Fontchar;
+};
+
+struct GFont
+{
+ uchar height; /* max height of bitmap, interline spacing */
+ char ascent; /* top of bitmap to baseline */
+ char width; /* widest so far; used in caching only */
+ char ldepth; /* of images */
+ short id; /* of font */
+ int ncache; /* number of entries in cache */
+ GCacheinfo *cache; /* cached characters */
+ GBitmap *b; /* cached images */
+};
+
+extern ulong *gaddr(GBitmap*, Point);
+extern uchar *gbaddr(GBitmap*, Point);
+extern void gbitblt(GBitmap*, Point, GBitmap*, Rectangle, Fcode);
+extern void gbitbltclip(void*);
+extern void gtexture(GBitmap*, Rectangle, GBitmap*, Fcode);
+extern Point gsubfstrsize(GSubfont*, char*);
+extern int gsubfstrwidth(GSubfont*, char*);
+extern Point gsubfstring(GBitmap*, Point, GSubfont*, char*, Fcode);
+extern Point gbitbltstring(GBitmap*, Point, GSubfont*, char*, Fcode);
+extern void gsegment(GBitmap*, Point, Point, int, Fcode);
+extern void gpoint(GBitmap*, Point, int, Fcode);
+extern void gflushcpucache(void);
+extern GBitmap* gballoc(Rectangle, int);
+extern void gbfree(GBitmap*);
--- /dev/null
+++ b/os/boot.original/rpcg/i2c.c
@@ -1,0 +1,360 @@
+#include "boot.h"
+
+/*
+ * basic read/write interface to mpc8xx I2C bus (master mode)
+ */
+
+typedef struct I2C I2C;
+
+struct I2C {
+ uchar i2mod;
+ uchar rsv12a[3];
+ uchar i2add;
+ uchar rsv12b[3];
+ uchar i2brg;
+ uchar rsv12c[3];
+ uchar i2com;
+ uchar rsv12d[3];
+ uchar i2cer;
+ uchar rsv12e[3];
+ uchar i2cmr;
+};
+
+enum {
+ /* i2c-specific BD flags */
+ RxeOV= 1<<1, /* overrun */
+ TxS= 1<<10, /* transmit start condition */
+ TxeNAK= 1<<2, /* last transmitted byte not acknowledged */
+ TxeUN= 1<<1, /* underflow */
+ TxeCL= 1<<0, /* collision */
+ TxERR= (TxeNAK|TxeUN|TxeCL),
+
+ /* i2cmod */
+ REVD= 1<<5, /* =1, LSB first */
+ GCD= 1<<4, /* =1, general call address disabled */
+ FLT= 1<<3, /* =0, not filtered; =1, filtered */
+ PDIV= 3<<1, /* predivisor field */
+ EN= 1<<0, /* enable */
+
+ /* i2com */
+ STR= 1<<7, /* start transmit */
+ I2CM= 1<<0, /* master */
+ I2CS= 0<<0, /* slave */
+
+ /* i2cer */
+ TXE = 1<<4,
+ BSY = 1<<2,
+ TXB = 1<<1,
+ RXB = 1<<0,
+
+ /* port B bits */
+ I2CSDA = IBIT(27),
+ I2CSCL = IBIT(26),
+
+ Rbit = 1<<0, /* bit in address byte denoting read */
+
+ /* maximum I2C I/O (can change) */
+ MaxIO= 128,
+ Bufsize = MaxIO+4, /* extra space for address/clock bytes and alignment */
+ Freq = 100000,
+ I2CTimeout = 250, /* msec */
+};
+
+/* data cache needn't be flushed if buffers allocated in uncached INTMEM */
+#define DCFLUSH(a,n)
+
+/*
+ * I2C software structures
+ */
+
+struct Ctlr {
+ Lock;
+ QLock io;
+ int init;
+ I2C* i2c;
+ IOCparam* sp;
+
+ BD* rd;
+ BD* td;
+ int phase;
+ int timeout;
+ char* addr;
+ char* txbuf;
+ char* rxbuf;
+};
+typedef struct Ctlr Ctlr;
+
+static Ctlr i2ctlr[1];
+extern int predawn;
+
+static void interrupt(Ureg*, void*);
+
+static void
+enable(void)
+{
+ I2C *i2c;
+
+ i2c = i2ctlr->i2c;
+ i2c->i2cer = ~0; /* clear events */
+ eieio();
+ i2c->i2mod |= EN;
+ eieio();
+ i2c->i2cmr = TXE|BSY|TXB|RXB; /* enable all interrupts */
+ eieio();
+}
+
+static void
+disable(void)
+{
+ I2C *i2c;
+
+ i2c = i2ctlr->i2c;
+ i2c->i2cmr = 0; /* mask all interrupts */
+ i2c->i2mod &= ~EN;
+}
+
+/*
+ * called by the reset routine of any driver using the I2C
+ */
+void
+i2csetup(void)
+{
+ IMM *io;
+ I2C *i2c;
+ IOCparam *sp;
+ Ctlr *ctlr;
+ long f, e, emin;
+ int p, d, dmax;
+
+ ctlr = i2ctlr;
+ if(ctlr->init)
+ return;
+ print("i2c setup...\n");
+ ctlr->init = 1;
+ i2c = KADDR(INTMEM+0x860);
+ ctlr->i2c = i2c;
+ sp = KADDR(INTMEM+0x3c80);
+ ctlr->sp = sp;
+ disable();
+
+ if(ctlr->txbuf == nil){
+ ctlr->txbuf = ialloc(Bufsize, 2);
+ ctlr->addr = ctlr->txbuf+Bufsize;
+ }
+ if(ctlr->rxbuf == nil)
+ ctlr->rxbuf = ialloc(Bufsize, 2);
+ if(ctlr->rd == nil){
+ ctlr->rd = bdalloc(1);
+ ctlr->rd->addr = PADDR(ctlr->rxbuf);
+ ctlr->rd->length = 0;
+ ctlr->rd->status = BDWrap;
+ }
+ if(ctlr->td == nil){
+ ctlr->td = bdalloc(2);
+ ctlr->td->addr = PADDR(ctlr->txbuf);
+ ctlr->td->length = 0;
+ ctlr->td->status = BDWrap|BDLast;
+ }
+
+ /* select port pins */
+ io = ioplock();
+ io->pbdir |= I2CSDA | I2CSCL;
+ io->pbodr |= I2CSDA | I2CSCL;
+ io->pbpar |= I2CSDA | I2CSCL;
+ iopunlock();
+
+ /* explicitly initialise parameters, because InitRxTx can't be used (see i2c/spi relocation errata) */
+ sp = ctlr->sp;
+ sp->rbase = PADDR(ctlr->rd);
+ sp->tbase = PADDR(ctlr->td);
+ sp->rfcr = 0x18;
+ sp->tfcr = 0x18;
+ sp->mrblr = Bufsize;
+ sp->rstate = 0;
+ sp->rptr = 0;
+ sp->rbptr = sp->rbase;
+ sp->rcnt = 0;
+ sp->tstate = 0;
+ sp->tbptr = sp->tbase;
+ sp->tptr = 0;
+ sp->tcnt = 0;
+ eieio();
+
+ i2c->i2com = I2CM;
+ i2c->i2mod = 0; /* normal mode */
+ i2c->i2add = 0;
+
+ emin = Freq;
+ dmax = (m->cpuhz/Freq)/2-3;
+ for(d=0; d < dmax; d++){
+ for(p=3; p>=0; p--){
+ f = (m->cpuhz>>(p+2))/(2*(d+3));
+ e = Freq - f;
+ if(e < 0)
+ e = -e;
+ if(e < emin){
+ emin = e;
+ i2c->i2brg = d;
+ i2c->i2mod = (i2c->i2mod&~PDIV)|((3-p)<<1); /* set PDIV */
+ }
+ }
+ }
+ //print("i2brg=%d i2mod=#%2.2ux\n", i2c->i2brg, i2c->i2mod);
+ setvec(VectorCPIC+0x10, interrupt, i2ctlr);
+}
+
+enum {
+ Idling,
+ Done,
+ Busy,
+ Sending,
+ Recving,
+};
+
+static void
+interrupt(Ureg*, void *arg)
+{
+ int events;
+ Ctlr *ctlr;
+ I2C *i2c;
+
+ ctlr = arg;
+ i2c = ctlr->i2c;
+ events = i2c->i2cer;
+ eieio();
+ i2c->i2cer = events;
+ if(events & (BSY|TXE)){
+ print("I2C#%x\n", events);
+ if(ctlr->phase != Idling){
+ ctlr->phase = Idling;
+ }
+ }else{
+ if(events & TXB){
+ //print("i2c: xmt %d %4.4ux %4.4ux\n", ctlr->phase, ctlr->td->status, ctlr->td[1].status);
+ if(ctlr->phase == Sending){
+ ctlr->phase = Done;
+ }
+ }
+ if(events & RXB){
+ //print("i2c: rcv %d %4.4ux %d\n", ctlr->phase, ctlr->rd->status, ctlr->rd->length);
+ if(ctlr->phase == Recving){
+ ctlr->phase = Done;
+ }
+ }
+ }
+}
+
+static int
+done(void *a)
+{
+ return ((Ctlr*)a)->phase < Busy;
+}
+
+static void
+i2cwait(Ctlr *ctlr)
+{
+ int i;
+
+ ctlr->timeout = 0;
+ i = 0;
+ while(!done(ctlr)){
+ if(predawn){
+ if(++i > 100){
+ ctlr->phase = Done;
+ ctlr->timeout = 1;
+ return;
+ }
+ delay(1);
+ interrupt(nil, ctlr);
+ }
+ }
+}
+
+long
+i2csend(int addr, void *buf, long n)
+{
+ Ctlr *ctlr;
+ int i, p, s;
+
+ ctlr = i2ctlr;
+ if(n > MaxIO)
+ return -1;
+ i = 1;
+ ctlr->txbuf[0] = addr & ~1;
+ if(addr & 1){
+ ctlr->txbuf[1] = addr>>8;
+ i++;
+ }
+ memmove(ctlr->txbuf+i, buf, n);
+ DCFLUSH(ctlr->txbuf, Bufsize);
+ ctlr->phase = Sending;
+ ctlr->rd->status = BDEmpty|BDWrap|BDInt;
+ ctlr->td->addr = PADDR(ctlr->txbuf);
+ ctlr->td->length = n+i;
+ ctlr->td->status = BDReady|BDWrap|BDLast|BDInt;
+ enable();
+ ctlr->i2c->i2com = STR|I2CM;
+ eieio();
+ i2cwait(ctlr);
+ disable();
+ p = ctlr->phase;
+ s = ctlr->td->status;
+ if(s & BDReady || s & TxERR || p != Done || ctlr->timeout)
+ return -1;
+ return n;
+}
+
+long
+i2crecv(int addr, void *buf, long n)
+{
+ Ctlr *ctlr;
+ int p, s, flag;
+ BD *td;
+ long nr;
+
+ ctlr = i2ctlr;
+ if(n > MaxIO)
+ return -1;
+ ctlr->txbuf[0] = addr|Rbit;
+ if(addr & 1){ /* special select sequence */
+ ctlr->addr[0] = addr &~ 1;
+ ctlr->addr[1] = addr>>8;
+ }
+ DCFLUSH(ctlr->txbuf, Bufsize);
+ DCFLUSH(ctlr->rxbuf, Bufsize);
+ ctlr->phase = Recving;
+ ctlr->rd->addr = PADDR(ctlr->rxbuf);
+ ctlr->rd->status = BDEmpty|BDWrap|BDInt;
+ flag = 0;
+ td = ctlr->td;
+ td[1].status = 0;
+ if(addr & 1){
+ /* special select sequence */
+ td->addr = PADDR(ctlr->addr);
+ td->length = 2;
+ /* td->status made BDReady below */
+ td++;
+ flag = TxS;
+ }
+ td->addr = PADDR(ctlr->txbuf);
+ td->length = n+1;
+ td->status = BDReady|BDWrap|BDLast | flag; /* not BDInt: leave that to receive */
+ if(flag)
+ ctlr->td->status = BDReady;
+ enable();
+ ctlr->i2c->i2com = STR|I2CM;
+ eieio();
+ i2cwait(ctlr);
+ disable();
+ p = ctlr->phase;
+ s = ctlr->td->status;
+ if(flag)
+ s |= ctlr->td[1].status;
+ nr = ctlr->rd->length;
+ if(nr > n)
+ nr = n; /* shouldn't happen */
+ if(s & TxERR || s & BDReady || p != Done || ctlr->rd->status & BDEmpty || ctlr->timeout)
+ return -1;
+ memmove(buf, ctlr->rxbuf, nr);
+ return nr;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/initfads.c
@@ -1,0 +1,187 @@
+/*
+ * Called from l.s in EPROM to set up a minimal working environment.
+ * Since there is no DRAM yet, and therefore no stack, no function
+ * calls may be made from sysinit0, and values can't be stored,
+ * except to INTMEM. Global values are accessed by offset from SB,
+ * which has been set by l.s to point into EPROM.
+ *
+ * This is FADS-specific in CS assignment and access of the FADS BCSR
+ * to discover memory size and speed.
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "archfads.h"
+
+#define MB (1024*1024)
+
+enum {
+ UPMSIZE = 64, /* memory controller instruction RAM */
+ SPEED = 50, /* maximum memory clock in MHz */
+ SDRAMSIZE = 4*MB,
+
+ /* mcr */
+ WriteRAM = 0<<30,
+ ReadRAM = 1<<30,
+ ExecRAM = 2<<30,
+
+ SelUPMA = 0<<23,
+ SelUPMB = 1<<23,
+
+ Once = 1<<8,
+};
+
+/*
+ * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
+ */
+static ulong upma50[UPMSIZE] = {
+ 0x8FFFEC24, 0xFFFEC04, 0xCFFEC04, 0xFFEC04,
+ 0xFFEC00, 0x37FFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x8FFFEC24, 0xFFFEC04, 0x8FFEC04, 0xFFEC0C,
+ 0x3FFEC00, 0xFFEC44, 0xFFCC08, 0xCFFCC44,
+ 0xFFEC0C, 0x3FFEC00, 0xFFEC44, 0xFFCC00,
+ 0x3FFFC847, 0x3FFFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x11BFCC47,
+ 0xC0FFCC84, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x3AFCC4C,
+ 0xCAFCC00, 0x3AFCC4C, 0xCAFCC00, 0x3AFCC4C,
+ 0xCAFCC00, 0x33BFCC4F, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xC0FFCC84, 0xFFCC04, 0x7FFCC04, 0x3FFFCC06,
+ 0xFFFFCC85, 0xFFFFCC05, 0xFFFFCC05, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x33FFCC07, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+};
+
+/*
+ * the FADS manual table 3-7 suggests the following for 60ns EDO DRAMs at 20MHz
+ */
+static ulong upma20[UPMSIZE] = {
+ 0x8FFFCC04, 0x08FFCC00, 0x33FFCC47, ~0, ~0, ~0, ~0, ~0,
+ [0x08] 0x8FFFCC04, 0x08FFCC08, 0x08FFCC08, 0x08FFCC08, 0x08FFCC00, 0x3FFFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x18] 0x8FEFCC00, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x20] 0x8FEFCC00, 0x09AFCC48, 0x09AFCC48, 0x08AFCC48, 0x39BFCC47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x30] 0x80FFCC84, 0x17FFCC04, 0xFFFFCC86, 0xFFFFCC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x3C] 0x33FFCC07, ~0, ~0, ~0,
+};
+
+void
+sysinit0(int inrom)
+{
+ ulong *upm, *bcsr;
+ IMM *io;
+ int i, mb;
+
+ io = (IMM*)INTMEM; /* running before maps, no KADDR */
+
+ /* system interface unit initialisation, FADS manual table 3-2, except as noted */
+ io->siumcr = 0x01012440;
+ io->sypcr = 0xFFFFFF88;
+ io->tbscrk = KEEP_ALIVE_KEY;
+ io->tbscr = 0xC3; /* time base enabled */
+ io->rtcsck = KEEP_ALIVE_KEY;
+ io->rtcsc = 0xC1; /* don't FRZ, real-time clock enabled */
+ io->rtcsck = ~KEEP_ALIVE_KEY;
+ io->piscrk = KEEP_ALIVE_KEY;
+ io->piscr = 0x82;
+
+ io->memc[BCSRCS].option = 0xFFFF8110; /* 32k block, all types access, CS early negate, 1 ws */
+ io->memc[BCSRCS].base = BCSRMEM | 1; /* base, 32-bit port, no parity, GPCM */
+
+ io->memc[BOOTCS].base = FLASHMEM | 1;
+ io->memc[BOOTCS].option = 0xFF800D54;
+
+ if(!inrom)
+ return; /* can't initialise DRAM controller from DRAM */
+
+ bcsr = (ulong*)BCSRMEM;
+// bcsr[1] &= ~DisableDRAM;
+ /* could check DRAM speed here; assume 60ns */
+ switch((bcsr[2]>>23)&3){
+ default: return; /* can't happen; for the compiler */
+ case 0: mb = 4; break;
+ case 1: mb = 32; break;
+ case 2: mb = 16; break;
+ case 3: mb = 8; break;
+ }
+
+ upm = upma50;
+ for(i=0; i<UPMSIZE; i++){
+ io->mdr = upm[i];
+ io->mcr = WriteRAM | SelUPMA | i;
+ }
+ io->mptpr = 0x0400;
+ if(SPEED >= 32)
+ io->mamr = (0x9C<<24) | 0xA21114; /* 50MHz BRGCLK; FADS manual says 0xC0, mpc8bug sets 0x9C */
+ else if(SPEED >= 20)
+ io->mamr = (0x60<<24) | 0xA21114; /* 25MHz BRGCLK */
+ else
+ io->mamr = (0x40<<24) | 0xA21114; /* 16.67MHz BRGCLK */
+ io->memc[DRAM1].option = ~((mb<<20)-1)|0x0800; /* address mask, SAM=1 */
+ io->memc[DRAM1].base = 0 | 0x81; /* base at 0, 32-bit port size, no parity, UPMA */
+}
+
+/*
+ * the FADS manual table 3-9's suggestion for MB811171622A-100 32+MHz-50MHz
+ */
+static ulong upmb50[UPMSIZE] = {
+ [0x00] 0x1F07FC04, 0xEEAEFC04, 0x11ADFC04, 0xEFBBBC00, 0x1FF77C47,
+ [0x05] 0x1FF77C34, 0xEFEABC34, 0x1FB57C35,
+ [0x08] 0x1F07FC04, 0xEEAEFC04, 0x10ADFC04, 0xF0AFFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x18] 0x1F27FC04, 0xEEAEBC00, 0x01B93C04, 0x1FF77C47, ~0, ~0, ~0, ~0,
+ [0x20] 0x1F07FC04, 0xEEAEBC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C47, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x30] 0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC07, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x3C] 0x7FFFFC07, ~0, ~0, ~0,
+};
+
+/*
+ * the FADS manual table 3-8's suggestion for MB811171622A-100 up to 32MHz
+ */
+static ulong upmb32[UPMSIZE] = {
+ [0x00] 0x126CC04, 0xFB98C00, 0x1FF74C45, ~0, ~0,
+ [0x05] 0x1FE77C34, 0xEFAABC34, 0x1FA57C35,
+ [0x08] 0x0026FC04, 0x10ADFC00, 0xF0AFFC00, 0xF1AFFC00, 0xEFBBBC00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x18] 0x0E26BC04, 0x01B93C00, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0,
+ [0x20] 0x0E26BC00, 0x10AD7C00, 0xF0AFFC00, 0xF0AFFC00, 0xE1BBBC04, 0x1FF77C45, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x30] 0x1FF5FC84, 0xFFFFFC04, 0xFFFFFC84, 0xFFFFFC05, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
+ [0x3C] 0x7FFFFC07, ~0, ~0, ~0,
+};
+
+/*
+ * optionally called by archfads.c:/^archinit to initialise access to SDRAM
+ */
+void
+sdraminit(ulong base)
+{
+ ulong *upm;
+ IMM *io;
+ int i;
+
+ io = (IMM*)INTMEM; /* running before maps, no KADDR */
+ if(SPEED > 32)
+ upm = upmb50;
+ else
+ upm = upmb32;
+ for(i=0; i<UPMSIZE; i++){
+ io->mdr = upm[i];
+ io->mcr = WriteRAM | SelUPMB | i;
+ }
+ io->memc[SDRAM].option = ~(SDRAMSIZE-1)|0x0A00; /* address mask, SAM=1, G5LS=1 */
+ io->memc[SDRAM].base = base | 0xC1;
+ if(SPEED > 32){
+ io->mbmr = 0xD0802114; /* 50MHz BRGCLK */
+ io->mar = 0x88;
+ }else{
+ io->mbmr = 0x80802114; /* 32MHz BRGCLK */
+ io->mar = 0x48;
+ }
+ io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 5; /* run MRS command in locations 5-8 of UPMB */
+ io->mbmr = (io->mbmr & ~0xF) | 8;
+ io->mcr = ExecRAM | SelUPMB | (SDRAM<<13) | Once | 0x30; /* run refresh sequence */
+ io->mbmr = (io->mbmr & ~0xF) | 4; /* 4-beat refresh bursts */
+}
--- /dev/null
+++ b/os/boot.original/rpcg/initpaq.c
@@ -1,0 +1,101 @@
+/*
+ * Called from l.s in EPROM to set up a minimal working environment.
+ * Since there is no DRAM yet, and therefore no stack, no function
+ * calls may be made from sysinit0, and values can't be stored,
+ * except to INTMEM. Global values are accessed by offset from SB,
+ * which has been set by l.s to point into EPROM.
+ *
+ * This is PowerPAQ-specific:
+ * - assumes 8mbytes
+ * - powerpaq CS assignment
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "archpaq.h"
+
+#define MB (1024*1024)
+
+enum {
+ DRAMSIZE = 8*MB,
+ FLASHSIZE = 8*MB,
+
+ UPMSIZE = 64, /* memory controller instruction RAM */
+ SPEED = 50, /* maximum memory clock in MHz */
+
+ /* mcr */
+ WriteRAM = 0<<30,
+ ReadRAM = 1<<30,
+ ExecRAM = 2<<30,
+
+ SelUPMA = 0<<23,
+ SelUPMB = 1<<23,
+
+ Once = 1<<8,
+};
+
+/*
+ * mpc8bug uses the following for 60ns EDO DRAMs 32-50MHz
+ */
+static ulong upmb50[UPMSIZE] = {
+ 0x8FFFEC24, 0xFFFEC04, 0xCFFEC04, 0xFFEC04,
+ 0xFFEC00, 0x37FFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x8FFFEC24, 0xFFFEC04, 0x8FFEC04, 0xFFEC0C,
+ 0x3FFEC00, 0xFFEC44, 0xFFCC08, 0xCFFCC44,
+ 0xFFEC0C, 0x3FFEC00, 0xFFEC44, 0xFFCC00,
+ 0x3FFFC847, 0x3FFFEC47, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x11BFCC47,
+ 0xC0FFCC84, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x8FAFCC24, 0xFAFCC04, 0xCAFCC00, 0x3AFCC4C,
+ 0xCAFCC00, 0x3AFCC4C, 0xCAFCC00, 0x3AFCC4C,
+ 0xCAFCC00, 0x33BFCC4F, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xC0FFCC84, 0xFFCC04, 0x7FFCC04, 0x3FFFCC06,
+ 0xFFFFCC85, 0xFFFFCC05, 0xFFFFCC05, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x33FFCC07, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+};
+
+void
+sysinit0(int inrom)
+{
+ ulong *upm;
+ IMM *io;
+ int i;
+
+ io = (IMM*)INTMEM; /* running before maps, no KADDR */
+
+ /* system interface unit initialisation, FADS manual table 3-2, except as noted */
+ io->siumcr = 0x01012440;
+ io->sypcr = 0xFFFFFF88;
+ io->tbscrk = KEEP_ALIVE_KEY;
+ io->tbscr = 0xC3; /* time base enabled */
+ io->rtcsck = KEEP_ALIVE_KEY;
+ io->rtcsc = 0xC1; /* don't FRZ, real-time clock enabled */
+ io->rtcsck = ~KEEP_ALIVE_KEY;
+ io->piscrk = KEEP_ALIVE_KEY;
+ io->piscr = 0x82;
+
+ io->memc[BOOTCS].base = FLASHMEM | 1;
+ io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(2<<4); /* mask, BIH, 2 wait states */
+
+ if(!inrom)
+ return; /* can't initialise DRAM controller from DRAM */
+
+ /* could check DRAM speed here; assume 60ns */
+ /* could probe DRAM for size here; assume DRAMSIZE */
+ io->mptpr = 0x400; /* powerpaq flash has 0x1000 */
+ io->mbmr = (0xC0<<24) | 0xA21114; /* 50MHz BRGCLK */
+ upm = upmb50;
+ for(i=0; i<UPMSIZE; i++){
+ io->mdr = upm[i];
+ io->mcr = WriteRAM | SelUPMB | i;
+ }
+ io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0800; /* address mask, SAM=1 */
+ io->memc[DRAM1].base = 0 | 0xC1; /* base at 0, 32-bit port size, no parity, UPMB */
+}
--- /dev/null
+++ b/os/boot.original/rpcg/initrpcg.c
@@ -1,0 +1,91 @@
+
+/*
+ * Called from l.s in EPROM to set up a minimal working environment.
+ * Since there is no DRAM yet, and therefore no stack, no function
+ * calls may be made from sysinit, and values can't be stored,
+ * except to INTMEM. Global values are accessed by offset from SB,
+ * which has been set by l.s to point into EPROM.
+ */
+
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "archrpcg.h"
+
+#define MB (1024*1024)
+
+enum {
+ UPMSIZE = 64, /* memory controller instruction RAM */
+ DRAMSIZE = 16*MB,
+ FLASHSIZE = 4*MB,
+
+ WriteRAM = 0<<30,
+ ReadRAM = 1<<30,
+ ExecRAM = 2<<30,
+
+ SelUPMA = 0<<23,
+ SelUPMB = 1<<23,
+};
+/* RPCG values for RPXLite AW */
+static ulong upma50[UPMSIZE] = {
+ 0xCFFFCC24, 0x0FFFCC04, 0x0CAFCC04, 0x03AFCC08,
+ 0x3FBFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xCFFFCC24, 0x0FFFCC04, 0x0CAFCC84, 0x03AFCC88,
+ 0x3FBFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC04, 0x03FFCC00,
+ 0x3FFFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xCFFFCC24, 0x0FFFCC04, 0x0CFFCC84, 0x03FFCC84,
+ 0x0CFFCC00, 0x33FFCC27, 0xFFFFCC25, 0xFFFFCC25,
+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xC0FFCC24, 0x03FFCC24, 0x0FFFCC24, 0x0FFFCC24,
+ 0x3FFFCC27, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+ 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25, 0xFFFFCC25,
+};
+
+void
+sysinit0(int inrom)
+{
+ ulong *upm;
+ IMM *io;
+ int i;
+
+ io = (IMM*)INTMEM; /* running before maps, no KADDR */
+// io->siumcr = 0x01012440;
+// io->sypcr = 0xFFFFFF88;
+ io->tbscrk = KEEP_ALIVE_KEY;
+ io->tbscr = 0xC3;
+ io->rtcsck = KEEP_ALIVE_KEY;
+ io->rtcsc = 0xC1;
+ io->rtcsck = ~KEEP_ALIVE_KEY;
+ io->piscrk = KEEP_ALIVE_KEY;
+ io->piscr = 0x82;
+return;
+ io->memc[BCSRCS].option = 0xFFFF8910; /* 32k block, all types access, CSNT, CS early negate, burst inhibit, 1 ws */
+ io->memc[BCSRCS].base = BCSRMEM | 1; /* base, 32-bit port, no parity, GPCM */
+
+// io->memc[BOOTCS].base = FLASHMEM | 0x801; /* base, 16 bit port */
+// io->memc[BOOTCS].option = ~(FLASHSIZE-1)|(1<<8)|(4<<4); /* mask, BIH, 4 wait states */
+
+ if(1||!inrom)
+ return; /* can't initialise DRAM controller from DRAM */
+
+ /* TO DO: could check DRAM size and speed now */
+
+ upm = upma50;
+ for(i=0; i<nelem(upma50); i++){
+ io->mdr = upm[i];
+ io->mcr = WriteRAM | SelUPMA | i;
+ }
+ io->mptpr = 0x0800; /* divide by 8 */
+ io->mamr = (0x58<<24) | 0xA01430; /* 40MHz BRGCLK */
+ io->memc[DRAM1].option = ~(DRAMSIZE-1)|0x0E00; /* address mask, SAM=1, G5LA/S=3 */
+ io->memc[DRAM1].base = 0 | 0x81; /* base at 0, 32-bit port size, no parity, UPMA */
+}
--- /dev/null
+++ b/os/boot.original/rpcg/io.h
@@ -1,0 +1,463 @@
+enum
+{
+ /* software interrupt vectors (SIU and CPM) */
+ VectorPIC= 0, /* level 0 to level 7, assigned by software */
+ CPIClevel= 4,
+ VectorIRQ= VectorPIC+8, /* IRQ0 to IRQ7 */
+ VectorCPIC= VectorIRQ+8, /* 32 CPM interrupts: 0 (error) to 0x1F (PC15) */
+};
+
+enum
+{
+ BUSUNKNOWN = 0,
+};
+
+/*
+ * Buffer Descriptors and IO Rings
+ */
+
+typedef struct BD BD;
+struct BD {
+ ushort status;
+ ushort length;
+ ulong addr;
+};
+
+BD* bdalloc(int);
+void bdfree(BD*, int);
+
+enum {
+ /* Rx BDs, bits common to all protocols */
+ BDEmpty= 1<<15,
+ BDWrap= 1<<13,
+ BDInt= 1<<12,
+ BDLast= 1<<11,
+ BDFirst= 1<<10,
+
+ /* Tx BDs */
+ BDReady= 1<<15,
+ /* BDWrap, BDInt, BDLast */
+};
+
+typedef struct Ring Ring;
+struct Ring {
+ BD* rdr; /* receive descriptor ring */
+ void* rrb; /* receive ring buffers */
+ int rdrx; /* index into rdr */
+ int nrdre; /* length of rdr */
+
+ BD* tdr; /* transmit descriptor ring */
+ Block** txb; /* corresponding transmit ring buffers */
+ int tdrh; /* host index into tdr */
+ int tdri; /* interface index into tdr */
+ int ntdre; /* length of tdr */
+ int ntq; /* pending transmit requests */
+};
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
+
+int ioringinit(Ring*, int, int, int);
+
+/*
+ * CPM
+ */
+enum {
+ /* commands */
+ InitRxTx = 0,
+ InitRx = 1,
+ InitTx = 2,
+ EnterHunt= 3,
+ StopTx= 4,
+ GracefulStopTx = 5,
+ InitIDMA = 5,
+ RestartTx = 6,
+ CloseRxBD = 7,
+ SetGroupAddr = 8,
+ SetTimer = 8,
+ GCITimeout = 9,
+ GCIAbort = 10,
+ StopIDMA = 11,
+ StartDSP = 12,
+ ArmIDMA = 13,
+ InitDSP = 13,
+ USBCmd = 15,
+
+ /* channel IDs */
+ SCC1ID= 0,
+ USBID= 0,
+ I2CID= 1,
+ IDMA1ID= 1,
+ SCC2ID= 4,
+ SPIID= 5,
+ IDMA2ID= 5,
+ TIMERID= 5,
+ SCC3ID= 8,
+ SMC1ID= 9,
+ DSP1ID=9,
+ SCC4ID= 12,
+ SMC2ID= 13,
+ DSP2ID= 13,
+
+ BaudEnable = 1<<16,
+
+ /* sicr */
+ CLK1 = 4, /* SCC1,2 */
+ CLK2 = 5,
+ CLK3 = 6,
+ CLK4 = 7,
+ CLK5 = CLK1, /* SCC3,4 */
+ CLK6 = CLK2,
+ CLK7 = CLK3,
+ CLK8 = CLK4,
+};
+
+void cpmop(int, int, int);
+#define ioplock() (m->iomem)
+#define iopunlock()
+
+/*
+ * the structures below follow hardware/firmware layouts in the 8xx manuals:
+ * mind the data types, offsets and alignment
+ */
+
+/*
+ * basic IO controller parameters (SMC and SCC)
+ */
+typedef struct IOCparam IOCparam;
+struct IOCparam {
+ ushort rbase;
+ ushort tbase;
+ uchar rfcr;
+ uchar tfcr;
+ ushort mrblr;
+ ulong rstate;
+ ulong rptr;
+ ushort rbptr;
+ ushort rcnt;
+ ulong rtmp;
+ ulong tstate;
+ ulong tptr;
+ ushort tbptr;
+ ushort tcnt;
+ ulong ttmp;
+};
+
+typedef struct SCCparam SCCparam;
+struct SCCparam {
+ IOCparam;
+ ulong rcrc;
+ ulong tcrc;
+};
+
+typedef struct SCC SCC;
+struct SCC {
+ ulong gsmrl;
+ ulong gsmrh;
+ ushort psmr;
+ uchar rsvscc0[2];
+ ushort todr;
+ ushort dsr;
+ ushort scce;
+ uchar rsvscc1[2];
+ ushort sccm;
+ uchar rsvscc3;
+ uchar sccs;
+ ushort irmode;
+ ushort irsip;
+};
+
+typedef struct SMC SMC;
+struct SMC {
+ uchar pad1[2];
+ ushort smcmr;
+ uchar pad2[2];
+ uchar smce;
+ uchar pad3[3];
+ uchar smcm;
+ uchar pad4[5];
+};
+
+typedef struct SPI SPI;
+struct SPI {
+ ushort spmode;
+ uchar res1[4];
+ uchar spie;
+ uchar res2[3];
+ uchar spim;
+ uchar res3[2];
+ uchar spcom;
+ uchar res4[10];
+};
+
+typedef struct USB USB;
+struct USB { /* 823 only */
+ uchar usmod;
+ uchar usadr;
+ uchar uscom;
+ uchar rsvu1;
+ ushort usep[4];
+ uchar rsvu2[4];
+ ushort usber;
+ uchar rsvu3[2];
+ ushort usbmr;
+ uchar rsvu4;
+ uchar usbs;
+ uchar rsvu5[8];
+};
+
+typedef struct IMM IMM;
+struct IMM {
+ struct { /* general SIU */
+ ulong siumcr;
+ ulong sypcr;
+ uchar rsv0[0xE-0x8];
+ ushort swsr;
+ ulong sipend;
+ ulong simask;
+ ulong siel;
+ uchar sivec;
+ uchar padv[3];
+ ulong tesr;
+ uchar rsv1[0x30-0x24];
+ ulong sdcr;
+ uchar rsv2[0x80-0x34];
+ };
+ struct { /* PCMCIA */
+ struct {
+ ulong base;
+ ulong option;
+ } pcmr[8];
+ uchar rsv3[0xe0-0xc0];
+ ulong pgcra;
+ ulong pgcrb;
+ ulong pscr;
+ uchar rsv4[0xf0-0xec];
+ ulong pipr;
+ uchar rsv5[4];
+ ulong per;
+ uchar rsv6[4];
+ };
+ struct { /* MEMC */
+ struct {
+ ulong base;
+ ulong option;
+ } memc[8];
+ uchar rsv7a[0x24];
+ ulong mar;
+ ulong mcr;
+ uchar rsv7b[4];
+ ulong mamr;
+ ulong mbmr;
+ ushort mstat;
+ ushort mptpr;
+ ulong mdr;
+ uchar rsv7c[0x80];
+ };
+ struct { /* system integration timers */
+ ushort tbscr;
+ uchar rsv8a[2];
+ ulong tbrefu;
+ ulong tbrefl;
+ uchar rsv8b[0x14];
+ ushort rtcsc;
+ uchar rsv8c[2];
+ ulong rtc;
+ ulong rtsec;
+ ulong rtcal;
+ uchar rsv8d[0x10];
+ ushort piscr;
+ ushort rsv8e;
+ ulong pitc;
+ ulong pitr;
+ uchar rsv8f[0x34];
+ };
+ struct { /* 280: clocks and resets */
+ ulong sccr;
+ ulong plprcr;
+ ulong rsr;
+ uchar rsv9[0x300-0x28c];
+ };
+ struct { /* 300: system integration timers keys */
+ ulong tbscrk;
+ ulong tbrefuk;
+ ulong tbreflk;
+ ulong tbk;
+ uchar rsv10a[0x10];
+ ulong rtcsck;
+ ulong rtck;
+ ulong rtseck;
+ ulong rtcalk;
+ uchar rsv10b[0x10];
+ ulong piscrk;
+ ulong pitck;
+ uchar rsv10c[0x38];
+ };
+ struct { /* 380: clocks and resets keys */
+ ulong sccrk;
+ ulong plprcrk;
+ ulong rsrk;
+ uchar rsv11[0x800-0x38C];
+ };
+ struct { /* 800: video controller */
+ ushort vccr;
+ ushort pad11a;
+ uchar vsr;
+ uchar pad11b;
+ uchar vcmr;
+ uchar pad11c;
+ ulong vbcb;
+ ulong pad11d;
+ ulong vfcr0;
+ ulong vfaa0;
+ ulong vfba0;
+ ulong vfcr1;
+ ulong vfaa1;
+ ulong vfba1;
+ uchar rsv11a[0x840-0x828];
+ };
+ struct { /* 840: LCD */
+ ulong lccr;
+ ulong lchcr;
+ ulong lcvcr;
+ ulong rsv11b;
+ ulong lcfaa;
+ ulong lcfba;
+ uchar lcsr;
+ uchar rsv11c[0x860-0x859];
+ };
+ struct { /* 860: I2C */
+ uchar i2mod;
+ uchar rsv12a[3];
+ uchar i2add;
+ uchar rsv12b[3];
+ uchar i2brg;
+ uchar rsv12c[3];
+ uchar i2com;
+ uchar rsv12d[3];
+ uchar i2cer;
+ uchar rsv12e[3];
+ uchar i2cmr;
+ uchar rsv12[0x900-0x875];
+ };
+ struct { /* 900: DMA */
+ uchar rsv13[4];
+ ulong sdar;
+ uchar sdsr;
+ uchar pad1[3];
+ uchar sdmr;
+ uchar pad2[3];
+ uchar idsr1;
+ uchar pad3[3];
+ uchar idmr1;
+ uchar pad4[3];
+ uchar idsr2;
+ uchar pad5[3];
+ uchar idmr2;
+ uchar pad6[0x930-0x91D];
+ };
+ struct { /* CPM interrupt control */
+ ushort civr;
+ uchar pad7[0x940-0x932];
+ ulong cicr;
+ ulong cipr;
+ ulong cimr;
+ ulong cisr;
+ };
+ struct { /* input/output port */
+ ushort padir;
+ ushort papar;
+ ushort paodr;
+ ushort padat;
+ uchar pad8[8];
+ ushort pcdir;
+ ushort pcpar;
+ ushort pcso;
+ ushort pcdat;
+ ushort pcint;
+ uchar pad9[6];
+ ushort pddir;
+ ushort pdpar;
+ ushort rsv14a;
+ ushort pddat;
+ uchar rsv14[0x980-0x978];
+ };
+ struct { /* CPM timers */
+ ushort tgcr;
+ uchar rsv15a[0x990-0x982];
+ ushort tmr1;
+ ushort tmr2;
+ ushort trr1;
+ ushort trr2;
+ ushort tcr1;
+ ushort tcr2;
+ ushort tcn1;
+ ushort tcn2;
+ ushort tmr3;
+ ushort tmr4;
+ ushort trr3;
+ ushort trr4;
+ ushort tcr3;
+ ushort tcr4;
+ ushort tcn3;
+ ushort tcn4;
+ ushort ter1;
+ ushort ter2;
+ ushort ter3;
+ ushort ter4;
+ uchar rsv15[0x9C0-0x9B8];
+ };
+ struct { /* CPM */
+ ushort cpcr;
+ uchar res0[2];
+ ushort rccr;
+ uchar res1;
+ uchar rmds;
+ uchar res2a[4];
+ ushort rctr1;
+ ushort rctr2;
+ ushort rctr3;
+ ushort rctr4;
+ uchar res2[2];
+ ushort rter;
+ uchar res3[2];
+ ushort rtmr;
+ uchar rsv16[0x9F0-0x9DC];
+ };
+ union { /* BRG */
+ struct {
+ ulong brgc1;
+ ulong brgc2;
+ ulong brgc3;
+ ulong brgc4;
+ };
+ ulong brgc[4];
+ };
+ uchar skip0[0xAB2-0xA00]; /* USB, SCC, SMC, SPI: address using cpmdev(CP...)->regs */
+ struct { /* PIP */
+ ushort pipc; /* not 823 */
+ ushort ptpr; /* not 823 */
+ ulong pbdir;
+ ulong pbpar;
+ uchar pad10[2];
+ ushort pbodr;
+ ulong pbdat;
+ uchar pad11[0xAE0-0xAC8];
+ };
+ struct { /* SI */
+ ulong simode;
+ uchar sigmr;
+ uchar pad12;
+ uchar sistr;
+ uchar sicmr;
+ uchar pad13[4];
+ ulong sicr;
+ ulong sirp;
+ uchar pad14[0xB00-0xAF4];
+ };
+ ulong vcram[64];
+ ushort siram[256];
+ ushort lcdmap[256];
+};
--- /dev/null
+++ b/os/boot.original/rpcg/ip.h
@@ -1,0 +1,98 @@
+typedef struct Udphdr Udphdr;
+struct Udphdr
+{
+ uchar d[6]; /* Ethernet destination */
+ uchar s[6]; /* Ethernet source */
+ uchar type[2]; /* Ethernet packet type */
+
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+
+ /* Udp pseudo ip really starts here */
+ uchar ttl;
+ uchar udpproto; /* Protocol */
+ uchar udpplen[2]; /* Header plus data length */
+ uchar udpsrc[4]; /* Ip source */
+ uchar udpdst[4]; /* Ip destination */
+ uchar udpsport[2]; /* Source port */
+ uchar udpdport[2]; /* Destination port */
+ uchar udplen[2]; /* data length */
+ uchar udpcksum[2]; /* Checksum */
+};
+
+typedef struct Etherhdr Etherhdr;
+struct Etherhdr
+{
+ uchar d[6];
+ uchar s[6];
+ uchar type[2];
+
+ /* Now we have the ip fields */
+ uchar vihl; /* Version and header length */
+ uchar tos; /* Type of service */
+ uchar length[2]; /* packet length */
+ uchar id[2]; /* Identification */
+ uchar frag[2]; /* Fragment information */
+ uchar ttl; /* Time to live */
+ uchar proto; /* Protocol */
+ uchar cksum[2]; /* Header checksum */
+ uchar src[4]; /* Ip source */
+ uchar dst[4]; /* Ip destination */
+};
+
+enum
+{
+ IP_VER = 0x40,
+ IP_HLEN = 0x05,
+ UDP_EHSIZE = 22,
+ UDP_PHDRSIZE = 12,
+ UDP_HDRSIZE = 20,
+ ETHER_HDR = 14,
+ IP_UDPPROTO = 17,
+ ET_IP = 0x800,
+ Bcastip = 0xffffffff,
+ BPportsrc = 68,
+ BPportdst = 67,
+ TFTPport = 69,
+ Timeout = 5000, /* milliseconds */
+ Bootrequest = 1,
+ Bootreply = 2,
+ Tftp_READ = 1,
+ Tftp_WRITE = 2,
+ Tftp_DATA = 3,
+ Tftp_ACK = 4,
+ Tftp_ERROR = 5,
+ Segsize = 512,
+ TFTPSZ = Segsize+10,
+};
+
+typedef struct Bootp Bootp;
+struct Bootp
+{
+ uchar op; /* opcode */
+ uchar htype; /* hardware type */
+ uchar hlen; /* hardware address len */
+ uchar hops; /* hops */
+ uchar xid[4]; /* a random number */
+ uchar secs[2]; /* elapsed snce client started booting */
+ uchar pad[2];
+ uchar ciaddr[4]; /* client IP address (client tells server) */
+ uchar yiaddr[4]; /* client IP address (server tells client) */
+ uchar siaddr[4]; /* server IP address */
+ uchar giaddr[4]; /* gateway IP address */
+ uchar chaddr[16]; /* client hardware address */
+ char sname[64]; /* server host name (optional) */
+ char file[128]; /* boot file name */
+ char vend[128]; /* vendor-specific goo */
+};
+
+typedef struct Netaddr Netaddr;
+struct Netaddr
+{
+ ulong ip;
+ ushort port;
+ char ea[Eaddrlen];
+};
--- /dev/null
+++ b/os/boot.original/rpcg/l.s
@@ -1,0 +1,388 @@
+#include "mem.h"
+
+/* special instruction definitions */
+#define BDNE BC 0,2,
+#define BDNZ BC 16,0,
+#define NOOP OR R0,R0,R0
+
+/*
+ * common ppc special purpose registers
+ */
+#define DSISR 18
+#define DAR 19 /* Data Address Register */
+#define DEC 22 /* Decrementer */
+#define SRR0 26 /* Saved Registers (exception) */
+#define SRR1 27
+#define SPRG0 272 /* Supervisor Private Registers */
+#define SPRG1 273
+#define SPRG2 274
+#define SPRG3 275
+#define TBRU 269 /* Time base Upper/Lower (Reading) */
+#define TBRL 268
+#define TBWU 285 /* Time base Upper/Lower (Writing) */
+#define TBWL 284
+#define PVR 287 /* Processor Version */
+
+/*
+ * mpc82x-specific special purpose registers of interest here
+ */
+#define EIE 80
+#define EID 81
+#define NRI 82
+#define IMMR 638
+#define IC_CST 560
+#define IC_ADR 561
+#define IC_DAT 562
+#define DC_CST 568
+#define DC_ADR 569
+#define DC_DAT 570
+#define MI_CTR 784
+#define MI_AP 786
+#define MI_EPN 787
+#define MI_TWC 789
+#define MI_RPN 790
+#define MI_DBCAM 816
+#define MI_DBRAM0 817
+#define MI_DBRAM1 818
+#define MD_CTR 792
+#define M_CASID 793
+#define MD_AP 794
+#define MD_EPN 795
+#define M_TWB 796
+#define MD_TWC 797
+#define MD_RPN 798
+#define M_TW 799
+#define MD_DBCAM 824
+#define MD_DBRAM0 825
+#define MD_DBRAM1 826
+
+/* as on 603e, apparently mtmsr needs help in some chip revisions */
+#define WAITMSR SYNC; ISYNC
+
+/* use of SPRG registers in save/restore */
+#define SAVER0 SPRG0
+#define SAVER1 SPRG1
+#define SAVELR SPRG2
+#define SAVECR SPRG3
+
+#define UREGSIZE ((8+32)*4)
+#define UREGSPACE (UREGSIZE+8) /* allow for arg to trap, and align */
+
+/*
+ * This code is loaded by the ROM loader at location 0x3000,
+ * or lives in flash memory at FLASHMEM+0x100
+ * Move it to high memory so that it can load the kernel at 0x0000.
+ */
+
+#define LOADCODEBASE 0x3000 /* when downloaded in S records */
+#define FLASHCODEBASE (FLASHMEM+0x20000+0x100) /* when in flash */
+
+ TEXT start(SB), $-4
+ MOVW MSR, R3
+ MOVW $(EE|IP|RI), R4
+ ANDN R4, R3
+ OR $ME, R3
+ SYNC
+ MOVW R3, MSR /* turn off interrupts but enable traps */
+ WAITMSR
+
+/*
+ * reset the caches and disable them for now
+ */
+ MOVW SPR(IC_CST), R4 /* read and clear */
+ MOVW $(5<<25), R4
+ MOVW R4, SPR(IC_CST) /* unlock all */
+ ISYNC
+ MOVW $(6<<25), R4
+ MOVW R4, SPR(IC_CST) /* invalidate all */
+ ISYNC
+ MOVW $(2<<25), R4
+ MOVW R4, SPR(IC_CST) /* disable i-cache */
+ ISYNC
+
+ SYNC
+ MOVW SPR(DC_CST), R4 /* read and clear */
+ MOVW $(10<<24), R4
+ MOVW R4, SPR(DC_CST) /* unlock all */
+ ISYNC
+ MOVW $(12<<24), R4
+ MOVW R4, SPR(DC_CST) /* invalidate all */
+ ISYNC
+ MOVW $(4<<24), R4
+ MOVW R4, SPR(DC_CST) /* disable i-cache */
+ ISYNC
+
+ MOVW $7, R4
+ MOVW R4, SPR(158) /* cancel `show cycle' for normal instruction execution */
+
+/*
+ * set other system configuration values
+ */
+ MOVW SPR(IMMR), R5 /* save initial space pointer */
+ MOVW $INTMEM, R4
+ MOVW R4, SPR(IMMR) /* set internal memory base */
+ MOVW $0xFFFFFF88, R3
+ MOVW R3, 4(R4) /* disable watchdog in sypcr */
+ MOVW $0x01012440, R3
+ MOVW R3, 0(R4) /* siumcr */
+
+/*
+ * system initialisation (init and map DRAM)
+ */
+ MOVW $0, R0
+ MOVW $setSB(SB), R2
+#ifndef confrpcg
+ MOVW $(0xF000<<16), R3
+/*MOVW R0, R3*/
+ ANDCC R5, R3 /* initial space is high? */
+ BEQ notrom
+ MOVW $FLASHCODEBASE, R5 /* where $start(SB) actually is now */
+ MOVW $start(SB), R4 /* logical start address */
+ SUB R4, R5, R6 /* text relocation value */
+ MOVW $etext(SB), R7
+ SUB R4, R7
+ ADD R5, R7 /* data address in ROM */
+ MOVW $bdata(SB), R8
+ SUB R8, R2
+ ADD R7, R2 /* relocate SB: SB' = romdata+(SB-bdata) */
+ MOVW $sysinit0(SB), R4
+ ADD R6, R4 /* relocate sysinit0's address */
+ MOVW R4, CTR
+ MOVW $inmem(SB), R4
+ ADD R6, R4
+ MOVW R4, LR /* and the return address */
+ BR (CTR) /* call sysinit0 */
+ TEXT inmem(SB), $-4
+ MOVW $FLASHCODEBASE, R3
+ BR cpu0
+notrom:
+ MOVW $start(SB), R6
+ SUB R6, R2
+ ADD $LOADCODEBASE, R2
+ BL sysinit0(SB)
+ MOVW $LOADCODEBASE, R3
+#endif
+
+/*
+ * cpu 0
+ * relocate bootstrap to our link addresses for text and data
+ * set new PC
+ */
+cpu0:
+ MOVW $setSB(SB), R2 /* set correct static base register */
+#ifndef confrpcg
+ MOVW $start(SB), R4
+ MOVW $etext(SB), R5
+ SUB R4, R5
+ CMP R4, R3 /* already there? */
+ BNE copytext
+ ADD R5, R3 /* start of data image */
+#else
+ MOVW $etext(SB), R3
+#endif
+ BR copydata
+
+copytext:
+ ADD $3, R5
+ SRAW $2, R5
+ MOVW R5, CTR
+ SUB $4, R4
+ SUB $4, R3
+copyt: /* copy text */
+ MOVWU 4(R3), R5
+ MOVWU R5, 4(R4)
+ BDNZ copyt
+ ADD $4, R3
+
+copydata:
+ /* copy data */
+ MOVW $bdata(SB), R4
+ CMP R4, R3 /* already there? */
+ BEQ loadkpc
+ MOVW $edata(SB), R5
+ SUB R4, R5
+ ADD $3, R5
+ SRAW $2, R5
+ MOVW R5, CTR
+ SUB $4, R4
+ SUB $4, R3
+copyd:
+ MOVWU 4(R3), R5
+ MOVWU R5, 4(R4)
+ BDNZ copyd
+#endif
+
+ /* load correct PC */
+loadkpc:
+ MOVW $start1(SB), R3
+ MOVW R3, LR
+ BR (LR)
+TEXT start1(SB), $-4
+ MOVW $edata(SB), R3
+ MOVW $end(SB), R4
+ SUBCC R3, R4
+ BLE skipz
+ SRAW $2, R4
+ MOVW R4, CTR
+ SUB $4, R3
+ MOVW $0, R0
+zero:
+ MOVWU R0, 4(R3)
+ BDNZ zero
+skipz:
+ MOVW $mach0(SB), R1
+ MOVW R1, m(SB)
+ ADD $(MACHSIZE-8), R1
+ MOVW $0, R0
+
+ BL sysinit0(SB)
+
+ BL main(SB)
+ BR 0(PC)
+
+TEXT ledx(SB), $0
+
+ MOVW $BCSRMEM, R8
+ MOVW 0(R8), R3
+ MOVW $(0x0800<<16), R5
+ ANDN R5, R3, R3
+ MOVW R3, 0(R8)
+ BR 0(PC)
+
+TEXT getmsr(SB), $0
+ MOVW MSR, R3
+ RETURN
+
+TEXT putmsr(SB), $0
+ SYNC
+ MOVW R3, MSR
+ WAITMSR
+ RETURN
+
+TEXT eieio(SB), $0
+ EIEIO
+ RETURN
+
+TEXT idle(SB), $0
+ RETURN
+
+TEXT spllo(SB), $0
+ MOVW MSR, R3
+ OR $EE, R3, R4
+ SYNC
+ MOVW R4, MSR
+ WAITMSR
+ RETURN
+
+TEXT splhi(SB), $0
+ MOVW MSR, R3
+ RLWNM $0, R3, $~EE, R4
+ SYNC
+ MOVW R4, MSR
+ WAITMSR
+ RETURN
+
+TEXT splx(SB), $0
+ MOVW MSR, R4
+ RLWMI $0, R3, $EE, R4
+ SYNC
+ MOVW R4, MSR
+ WAITMSR
+ RETURN
+
+TEXT gettbl(SB), $0
+/* MOVW SPR(TBRL), R3 */
+ WORD $0x7c6c42e6 /* mftbl on 8xx series */
+ RETURN
+
+TEXT getpvr(SB), $0
+ MOVW SPR(PVR), R3
+ RETURN
+
+TEXT getimmr(SB), $0
+ MOVW SPR(IMMR), R3
+ RETURN
+
+TEXT getdec(SB), $0
+ MOVW SPR(DEC), R3
+ RETURN
+
+TEXT putdec(SB), $0
+ MOVW R3, SPR(DEC)
+ RETURN
+
+/*
+ * save state in Ureg on kernel stack.
+ * enter with R0 giving the PC from the call to `exception' from the vector.
+ * on return, SB (R2) has been set, and R3 has the Ureg*
+ */
+TEXT saveureg(SB), $-4
+ SUB $UREGSPACE, R1
+ MOVMW R2, 48(R1) /* r2:r31 */
+ MOVW $setSB(SB), R2
+ MOVW SPR(SAVER1), R4
+ MOVW R4, 44(R1)
+ MOVW SPR(SAVER0), R5
+ MOVW R5, 40(R1)
+ MOVW CTR, R6
+ MOVW R6, 36(R1)
+ MOVW XER, R4
+ MOVW R4, 32(R1)
+ MOVW SPR(SAVECR), R5 /* CR */
+ MOVW R5, 28(R1)
+ MOVW SPR(SAVELR), R6 /* LR */
+ MOVW R6, 24(R1)
+ /* pad at 20(R1) */
+ MOVW SPR(SRR0), R4
+ MOVW R4, 16(R1) /* old PC */
+ MOVW SPR(SRR1), R5
+ MOVW R5, 12(R1)
+ MOVW R0, 8(R1) /* cause/vector, encoded in LR from vector */
+ ADD $8, R1, R3 /* Ureg* */
+ STWCCC R3, (R1) /* break any pending reservations */
+ MOVW $0, R0 /* R0ISZERO */
+ BR (LR)
+
+/*
+ * restore state from Ureg
+ * SB (R2) is unusable on return
+ */
+TEXT restoreureg(SB), $-4
+ MOVMW 48(R1), R2 /* r2:r31 */
+ /* defer R1 */
+ MOVW 40(R1), R0
+ MOVW R0, SPR(SAVER0)
+ MOVW 36(R1), R0
+ MOVW R0, CTR
+ MOVW 32(R1), R0
+ MOVW R0, XER
+ MOVW 28(R1), R0
+ MOVW R0, CR /* CR */
+ MOVW 24(R1), R0
+ MOVW R0, SPR(SAVELR) /* LR */
+ /* pad, skip */
+ MOVW 16(R1), R0
+ MOVW R0, SPR(SRR0) /* old PC */
+ MOVW 12(R1), R0
+ MOVW R0, SPR(SRR1) /* old MSR */
+ /* cause, skip */
+ MOVW 44(R1), R1 /* old SP */
+ BR (LR)
+
+TEXT exception(SB), $-4
+ MOVW R1, SPR(SAVER1)
+ MOVW CR, R0
+ MOVW R0, SPR(SAVECR)
+ MOVW LR, R0
+ BL saveureg(SB)
+ MOVW $0, R0
+ BL trap(SB)
+ BL restoreureg(SB)
+ MOVW SPR(SAVELR), R0
+ MOVW R0, LR
+ MOVW SPR(SAVER0), R0
+ ISYNC
+ RFI
+
+GLOBL mach0+0(SB), $MACHSIZE
+GLOBL m(SB), $4
--- /dev/null
+++ b/os/boot.original/rpcg/lib.h
@@ -1,0 +1,106 @@
+/*
+ * functions (possibly) linked in, complete, from libc.
+ */
+
+/*
+ * mem routines
+ */
+extern void* memccpy(void*, void*, int, long);
+extern void* memset(void*, int, long);
+extern int memcmp(void*, void*, long);
+extern void* memmove(void*, void*, long);
+extern void* memchr(void*, int, long);
+
+/*
+ * string routines
+ */
+extern char* strcat(char*, char*);
+extern char* strchr(char*, char);
+extern int strcmp(char*, char*);
+extern char* strcpy(char*, char*);
+extern char* strncat(char*, char*, long);
+extern char* strncpy(char*, char*, long);
+extern int strncmp(char*, char*, long);
+extern long strlen(char*);
+extern char* strrchr(char*, char);
+extern char* strstr(char*, char*);
+
+/*
+ * print routines
+ * Fconv isn't used but is defined to satisfy prototypes in libg.h
+ * that are never called.
+ */
+typedef struct Fconv Fconv;
+
+extern char* donprint(char*, char*, char*, void*);
+extern int sprint(char*, char*, ...);
+extern int print(char*, ...);
+
+#define PRINTSIZE 256
+
+/*
+ * one-of-a-kind
+ */
+extern int atoi(char*);
+extern long strtol(char*, char**, int);
+extern ulong strtoul(char*, char**, int);
+extern long end;
+
+/*
+ * Syscall data structures
+ */
+
+#define MORDER 0x0003 /* mask for bits defining order of mounting */
+#define MREPL 0x0000 /* mount replaces object */
+#define MBEFORE 0x0001 /* mount goes before others in union directory */
+#define MAFTER 0x0002 /* mount goes after others in union directory */
+#define MCREATE 0x0004 /* permit creation in mounted directory */
+#define MMASK 0x0007 /* all bits on */
+
+#define OREAD 0 /* open for read */
+#define OWRITE 1 /* write */
+#define ORDWR 2 /* read and write */
+#define OEXEC 3 /* execute, == read but check execute permission */
+#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
+#define OCEXEC 32 /* or'ed in, close on exec */
+#define ORCLOSE 64 /* or'ed in, remove on close */
+
+#define NCONT 0 /* continue after note */
+#define NDFLT 1 /* terminate after note */
+
+typedef struct Qid Qid;
+typedef struct Dir Dir;
+typedef struct Waitmsg Waitmsg;
+
+#define ERRLEN 64
+#define DIRLEN 116
+#define NAMELEN 28
+
+struct Qid
+{
+ ulong path;
+ ulong vers;
+};
+
+struct Dir
+{
+ char name[NAMELEN];
+ char uid[NAMELEN];
+ char gid[NAMELEN];
+ Qid qid;
+ ulong mode;
+ long atime;
+ long mtime;
+ vlong length;
+ short type;
+ short dev;
+};
+
+struct Waitmsg
+{
+ int pid; /* of loved one */
+ int status; /* unused; a placeholder */
+ ulong time[3]; /* of loved one */
+ char msg[ERRLEN];
+};
+#define nelem(x) (sizeof(x)/sizeof((x)[0]))
--- /dev/null
+++ b/os/boot.original/rpcg/libg.h
@@ -1,0 +1,418 @@
+#pragma src "/sys/src/libg"
+#pragma lib "libg.a"
+
+enum /* constants for I/O to devgraphics */
+{
+ Tilehdr = 40,
+ Tilesize = 8000
+};
+
+/*
+ * you may think it's a blit, but it's gnot
+ */
+enum
+{
+ EMAXMSG = 128+8192, /* size of 9p header+data */
+};
+
+/*
+ * Types
+ */
+
+typedef struct Bitmap Bitmap;
+typedef struct Display Display;
+typedef struct Point Point;
+typedef struct Rectangle Rectangle;
+typedef struct Cursor Cursor;
+typedef struct Mouse Mouse;
+typedef struct Menu Menu;
+typedef struct Font Font;
+typedef struct Fontchar Fontchar;
+typedef struct Subfont Subfont;
+typedef struct Cachefont Cachefont;
+typedef struct Cacheinfo Cacheinfo;
+typedef struct Cachesubf Cachesubf;
+typedef struct Event Event;
+typedef struct Slave Slave;
+typedef struct Ebuf Ebuf;
+typedef struct RGB RGB;
+typedef struct Linedesc Linedesc;
+typedef struct DRefret DRefret;
+
+struct DRefret
+{
+ int n; /* number of bytes */
+ int dy; /* number of lines */
+ uchar *dp; /* pointer to data */
+};
+
+struct Point
+{
+ int x;
+ int y;
+};
+
+struct Rectangle
+{
+ Point min;
+ Point max;
+};
+
+typedef DRefret DRefresh(Display*, int, Rectangle, uchar*, uchar*, int);
+
+struct Bitmap
+{
+ Rectangle r; /* rectangle in data area, local coords */
+ Rectangle clipr; /* clipping region */
+ int ldepth; /* log base 2 of number of bits per pixel */
+ ulong *base; /* pointer to start of data */
+ int zero; /* base+zero=&word containing (0,0) */
+ ulong width; /* width in words of total data area */
+ Display *display; /* if present */
+};
+
+struct Display
+{
+ uchar *data; /* transfer buffer */
+ Rectangle r;
+ int ldepth;
+ Rectangle bb; /* bounding box of changes */
+ int waste; /* unused part of bb */
+ Rectangle bound; /* memory for boundin/boundout */
+ Bitmap *image; /* owner */
+ int id;
+ int fd;
+ int ctlfd;
+ int local;
+ int bytewidth;
+ void *drdata1; /* storage for drefresh() */
+ void *drdata2; /* storage for drefresh() */
+ DRefresh *drefresh;
+};
+
+
+struct Mouse
+{
+ int buttons; /* bit array: LMR=124 */
+ Point xy;
+ ulong msec;
+};
+
+struct Cursor
+{
+ Point offset;
+ uchar clr[2*16];
+ uchar set[2*16];
+};
+
+struct Menu
+{
+ char **item;
+ char *(*gen)(int);
+ int lasthit;
+};
+
+struct Linedesc
+{
+ int x0;
+ int y0;
+ char xmajor;
+ char slopeneg;
+ long dminor;
+ long dmajor;
+};
+
+/*
+ * Subfonts
+ *
+ * given char c, Subfont *f, Fontchar *i, and Point p, one says
+ * i = f->info+c;
+ * bitblt(b, Pt(p.x+i->left,p.y+i->top),
+ * bitmap, Rect(i->x,i->top,(i+1)->x,i->bottom),
+ * fc);
+ * p.x += i->width;
+ * where bitmap b is the repository of the images.
+ *
+ */
+
+struct Fontchar
+{
+ short x; /* left edge of bits */
+ uchar top; /* first non-zero scan-line */
+ uchar bottom; /* last non-zero scan-line + 1 */
+ char left; /* offset of baseline */
+ uchar width; /* width of baseline */
+};
+
+struct Subfont
+{
+ short n; /* number of chars in font */
+ uchar height; /* height of bitmap */
+ char ascent; /* top of bitmap to baseline */
+ Fontchar *info; /* n+1 character descriptors */
+ Bitmap *bits; /* of font */
+};
+
+enum
+{
+ /* starting values */
+ LOG2NFCACHE = 6,
+ NFCACHE = (1<<LOG2NFCACHE), /* #chars cached */
+ NFLOOK = 5, /* #chars to scan in cache */
+ NFSUBF = 2, /* #subfonts to cache */
+ /* max value */
+ MAXFCACHE = 2048+NFLOOK, /* generous upper limit */
+ MAXSUBF = 50, /* generous upper limit */
+ /* deltas */
+ DSUBF = 4,
+ /* expiry ages */
+ SUBFAGE = 10000,
+ CACHEAGE = 10000,
+};
+
+struct Cachefont
+{
+ Rune min; /* lowest rune value to be taken from subfont */
+ Rune max; /* highest rune value+1 to be taken from subfont */
+ int offset; /* position in subfont of character at min */
+ int abs; /* name has been made absolute */
+ char *name;
+};
+
+struct Cacheinfo
+{
+ Rune value; /* value of character at this slot in cache */
+ ushort age;
+ ulong xright; /* right edge of bits */
+ Fontchar;
+};
+
+struct Cachesubf
+{
+ ulong age; /* for replacement */
+ Cachefont *cf; /* font info that owns us */
+ Subfont *f; /* attached subfont */
+};
+
+struct Font
+{
+ char *name;
+ short height; /* max height of bitmap, interline spacing */
+ short ascent; /* top of bitmap to baseline */
+ int maxldepth; /* over all loaded subfonts */
+ short width; /* widest so far; used in caching only */
+ short ldepth; /* of images */
+ short nsub; /* number of subfonts */
+ ulong age; /* increasing counter; used for LRU */
+ int ncache; /* size of cache */
+ int nsubf; /* size of subfont list */
+ Cacheinfo *cache;
+ Cachesubf *subf;
+ Cachefont **sub; /* as read from file */
+ Bitmap *cacheimage;
+};
+
+struct Event
+{
+ int kbdc;
+ Mouse mouse;
+ int n; /* number of characters in mesage */
+ uchar data[EMAXMSG]; /* message from an arbitrary file descriptor */
+};
+
+struct Slave{
+ int pid;
+ Ebuf *head; /* queue of messages for this descriptor */
+ Ebuf *tail;
+};
+
+struct Ebuf{
+ Ebuf *next;
+ int n; /* number of bytes in buf */
+ uchar buf[EMAXMSG];
+};
+
+struct RGB
+{
+ ulong red;
+ ulong green;
+ ulong blue;
+};
+
+/*
+ * Codes for bitblt etc.
+ *
+ * D
+ * 0 1
+ * ---------
+ * 0 | 1 | 2 |
+ * S |---|---|
+ * 1 | 4 | 8 |
+ * ---------
+ *
+ * Usually used as D|S; DorS is so tracebacks are readable.
+ */
+typedef
+enum Fcode
+{
+ Zero = 0x0,
+ DnorS = 0x1,
+ DandnotS = 0x2,
+ notS = 0x3,
+ notDandS = 0x4,
+ notD = 0x5,
+ DxorS = 0x6,
+ DnandS = 0x7,
+ DandS = 0x8,
+ DxnorS = 0x9,
+ D = 0xA,
+ DornotS = 0xB,
+ S = 0xC,
+ notDorS = 0xD,
+ DorS = 0xE,
+ F = 0xF,
+} Fcode;
+
+/*
+ * Miscellany
+ */
+
+extern Point add(Point, Point), sub(Point, Point);
+extern Point mul(Point, int), div(Point, int);
+extern Rectangle rsubp(Rectangle, Point), raddp(Rectangle, Point), inset(Rectangle, int);
+extern Rectangle rmul(Rectangle, int), rdiv(Rectangle, int);
+extern Rectangle rshift(Rectangle, int), rcanon(Rectangle);
+extern Bitmap* balloc(Rectangle, int);
+extern Bitmap* ballocnomem(Rectangle, int);
+extern Bitmap* brealloc(Bitmap*, Rectangle, int);
+extern Bitmap* breallocnomem(Bitmap*, Rectangle, int);
+extern int bbytewidth(Bitmap*, int*, int*);
+extern void bfree(Bitmap*);
+extern void bfreemem(Bitmap*);
+extern int rectclip(Rectangle*, Rectangle);
+extern void binit(void(*)(char*), char*, char*);
+extern void binit1(void(*)(char*), char*, char*, int);
+extern void bclose(void);
+extern void berror(char*);
+extern void bitblt(Bitmap*, Point, Bitmap*, Rectangle, Fcode);
+extern int bitbltclip(void*);
+extern Font* rdfontfile(char*, int);
+extern void ffree(Font*);
+extern void fminldepth(Font*);
+extern Font* mkfont(Subfont*, Rune);
+extern Subfont* subfalloc(int, int, int, Fontchar*, Bitmap*);
+extern void subffree(Subfont*);
+extern int cachechars(Font*, char**, ushort*, int, int*);
+extern Point string(Bitmap*, Point, Font*, char*, Fcode);
+extern Point subfstring(Bitmap*, Point, Subfont*, char*, Fcode);
+extern void segment(Bitmap*, Point, Point, int, Fcode);
+extern void point(Bitmap*, Point, int, Fcode);
+extern void arc(Bitmap*, Point, Point, Point, int, Fcode);
+extern void circle(Bitmap*, Point, int, int, Fcode);
+extern void disc(Bitmap*, Point, int, int, Fcode);
+extern void ellipse(Bitmap*, Point, int, int, int, Fcode);
+extern long strwidth(Font*, char*);
+extern void agefont(Font*);
+extern int loadchar(Font*, Rune, Cacheinfo*, int, int);
+extern Point strsize(Font*, char*);
+extern long charwidth(Font*, Rune);
+extern void texture(Bitmap*, Rectangle, Bitmap*, Fcode);
+extern void wrbitmap(Bitmap*, int, int, uchar*);
+extern void rdbitmap(Bitmap*, int, int, uchar*);
+extern void wrbitmapfile(int, Bitmap*);
+extern Bitmap* rdbitmapfile(int);
+extern void wrsubfontfile(int, Subfont*);
+extern void wrcolmap(Bitmap*, RGB*);
+extern void rdcolmap(Bitmap*, RGB*);
+extern Subfont* rdsubfontfile(int, Bitmap*);
+extern void _unpackinfo(Fontchar*, uchar*, int);
+
+extern int ptinrect(Point, Rectangle), rectinrect(Rectangle, Rectangle);
+extern int rectXrect(Rectangle, Rectangle);
+extern int eqpt(Point, Point), eqrect(Rectangle, Rectangle);
+extern void border(Bitmap*, Rectangle, int, Fcode);
+extern void cursorswitch(Cursor*);
+extern void cursorset(Point);
+extern Rectangle bscreenrect(Rectangle*);
+extern void bflush(void);
+extern void bexit(void);
+extern int _clipline(Rectangle, Point*, Point*, Linedesc*);
+extern int clipline(Rectangle, Point*, Point*);
+extern int clipr(Bitmap*, Rectangle);
+
+extern void einit(ulong);
+extern ulong estart(ulong, int, int);
+extern ulong etimer(ulong, int);
+extern ulong event(Event*);
+extern ulong eread(ulong, Event*);
+extern Ebuf* ebread(Slave*);
+extern Mouse emouse(void);
+extern int ekbd(void);
+extern int ecanread(ulong);
+extern int ecanmouse(void);
+extern int ecankbd(void);
+extern void ereshaped(Rectangle); /* supplied by user */
+extern int menuhit(int, Mouse*, Menu*);
+extern Rectangle getrect(int, Mouse*);
+extern ulong rgbpix(Bitmap*, RGB);
+extern int _gminor(long, Linedesc*);
+
+enum{
+ Emouse = 1,
+ Ekeyboard = 2,
+};
+
+enum
+{
+ MAXSLAVE = 32,
+};
+
+#define Pt(x, y) ((Point){(x), (y)})
+#define Rect(x1, y1, x2, y2) ((Rectangle){Pt(x1, y1), Pt(x2, y2)})
+#define Rpt(p1, p2) ((Rectangle){(p1), (p2)})
+
+
+#define Dx(r) ((r).max.x-(r).min.x)
+#define Dy(r) ((r).max.y-(r).min.y)
+
+extern Bitmap screen;
+extern Font *font;
+extern uchar _btmp[8192];
+
+extern int _mousefd;
+extern int _cursorfd;
+
+#define BGSHORT(p) (((p)[0]<<0) | ((p)[1]<<8))
+#define BG32INT(p) ((s32int)((BGSHORT(p)<<0) | (BGSHORT(p+2)<<16)))
+#define BPSHORT(p, v) ((p)[0]=(v), (p)[1]=((v)>>8))
+#define BP32INT(p, v) (BPSHORT(p, ((s32int)v)), BPSHORT(p+2, ((s32int)v)>>16))
+
+ulong *wordaddr(Bitmap*, Point);
+uchar *byteaddr(Bitmap*, Point);
+int dfree(Display*);
+int dwritectl(Display*, char*, int);
+int dreadctl(Display*, char*, int);
+int dinfo(Display*, int, int*, Rectangle*);
+void* dinit(Display*, Bitmap*, int, int);
+int ddelete(Display*);
+void dfreemem(Display*);
+int dreadctl(Display*, char*, int);
+int dwritectl(Display*, char*, int);
+void dbound(Display*, Rectangle);
+void bload(Bitmap*, Rectangle, uchar*);
+ulong bunload(Bitmap*, Rectangle, uchar*);
+void drefresh(Display*, Rectangle);
+Display *dopen(char*, int, DRefresh*);
+Bitmap* dbitmap(Display*, DRefresh*, int);
+void dclose(Display*);
+void dflush(Display*);
+void _bltinit(void);
+Bitmap* battach(Bitmap*, int, int);
+int readmouse(Mouse*);
+int atomouse(Mouse*, char*, int);
+
+/*
+ * Refresh functions
+ */
+DRefresh drtexture;
+DRefresh drbackstore;
--- /dev/null
+++ b/os/boot.original/rpcg/main.c
@@ -1,0 +1,527 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "dosfs.h"
+
+typedef struct Type Type;
+typedef struct Medium Medium;
+typedef struct Mode Mode;
+
+enum {
+ Dany = -1,
+ Nmedia = 16,
+
+ /* DS1 switch options */
+ Sflashfs = 1<<0, /* take local fs from flash */
+ Snotflash = 1<<1, /* don't boot from flash */
+};
+
+enum { /* type */
+ Tflash,
+ Tuart,
+ Tether,
+ Thard,
+
+ Tany = -1,
+};
+
+enum { /* flag and name */
+ Fnone = 0x00,
+
+ Fdos = 0x01,
+ Ndos = 0x00,
+ Fboot = 0x02,
+ Nboot = 0x01,
+ Fbootp = 0x04,
+ Nbootp = 0x02,
+ Fflash = 0x08,
+ Fuart = 0x10,
+ NName = 0x03,
+
+ Fany = Fbootp|Fboot|Fdos|Fflash|Fuart,
+
+ Fini = 0x10,
+ Fprobe = 0x80,
+};
+
+enum { /* mode */
+ Mauto = 0x00,
+ Mlocal = 0x01,
+ Manual = 0x02,
+ NMode = 0x03,
+};
+
+typedef struct Type {
+ int type;
+ char *cname;
+ int flag;
+ int (*init)(void);
+ long (*read)(int, void*, long);
+ long (*seek)(int, long);
+ Partition* (*setpart)(int, char*);
+ char* name[NName];
+
+ int mask;
+ Medium* media;
+} Type;
+
+typedef struct Medium {
+ Type* type;
+ int flag;
+ Partition* partition;
+ Dos;
+
+ Medium* next;
+} Medium;
+
+typedef struct Mode {
+ char* name;
+ int mode;
+} Mode;
+
+static Type types[] = {
+ { Tflash, "flash",
+ Fflash,
+ flashinit, 0, 0, 0,
+ { 0, "F", 0, }
+ },
+/*
+ { Tuart, "uart",
+ Fuart|Fboot,
+ uartinit, uartread, uartseek, setuartpart,
+ { 0, "u", 0, }
+ },
+*/
+ { Tether, "ether",
+ Fbootp,
+ etherinit, 0, 0, 0,
+ { 0, 0, "e", },
+ },
+ { Thard, "ata",
+ Fini|Fboot|Fdos,
+ 0, 0, 0, 0, /* not used now, will be later with PCMCIA */
+ { "hd", "h", 0, },
+ },
+ {-1},
+};
+
+static Medium media[Nmedia];
+static Medium *curmedium = media;
+
+static Mode modes[NMode+1] = {
+ [Mauto] { "auto", Mauto, },
+ [Mlocal] { "local", Mlocal, },
+ [Manual] { "manual", Manual, },
+};
+
+static char *inis[] = {
+ "inferno/inferno.ini",
+ "inferno.ini",
+ "plan9/plan9.ini",
+ "plan9.ini",
+ 0,
+};
+char **ini;
+int predawn;
+
+static int
+parse(char *line, int *type, int *flag, int *dev, char *file)
+{
+ Type *tp;
+ char buf[2*NAMELEN], *v[4], *p;
+ int i;
+
+ strcpy(buf, line);
+ switch(getcfields(buf, v, 4, "!")){
+
+ case 3:
+ break;
+
+ case 2:
+ v[2] = "";
+ break;
+
+ default:
+ return 0;
+ }
+
+ *flag = 0;
+ for(tp = types; tp->cname; tp++){
+ for(i = 0; i < NName; i++){
+
+ if(tp->name[i] == 0 || strcmp(v[0], tp->name[i]))
+ continue;
+ *type = tp->type;
+ *flag |= 1<<i;
+
+ if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1])
+ return 0;
+
+ strcpy(file, v[2]);
+
+ return 1;
+ }
+ }
+
+ return 0;
+
+}
+
+static int
+boot(Medium *mp, int flag, char *file)
+{
+ Dosfile df;
+ char ixdos[128], *p;
+ int r;
+
+ uartsetboot(0);
+ if(flag & Fbootp){
+ sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev);
+ return bootp(mp->dev, file);
+ }
+
+ if(flag & Fflash){
+ if(mp->flag & Fflash && flashbootable(0))
+ flashboot(mp->dev);
+ }
+
+ if(flag & Fboot){
+
+ if(mp->flag & Fini){
+ (*mp->type->setpart)(mp->dev, "disk");
+ plan9ini(mp, nil);
+ }
+ if(file == 0 || *file == 0)
+ file = mp->partition->name;
+ (*mp->type->setpart)(mp->dev, file);
+ sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file);
+ r = plan9boot(mp->dev, mp->seek, mp->read);
+ uartsetboot(0);
+ return r;
+ }
+
+ if(flag & Fdos){
+ if(mp->type->setpart)
+ (*mp->type->setpart)(mp->dev, "disk");
+ if(mp->flag & Fini)
+ plan9ini(mp, nil);
+ if(file == 0 || *file == 0){
+ strcpy(ixdos, *ini);
+ if(p = strrchr(ixdos, '/'))
+ p++;
+ else
+ p = ixdos;
+ strcpy(p, "impc");
+ if(dosstat(mp, ixdos, &df) <= 0)
+ return -1;
+ }
+ else
+ strcpy(ixdos, file);
+ sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos);
+ return dosboot(mp, ixdos);
+ }
+
+ return -1;
+}
+
+static Medium*
+allocm(Type *tp)
+{
+ Medium **l;
+
+ if(curmedium >= &media[Nmedia])
+ return 0;
+
+ for(l = &tp->media; *l; l = &(*l)->next)
+ ;
+ *l = curmedium++;
+ return *l;
+}
+
+Medium*
+probe(int type, int flag, int dev)
+{
+ Type *tp;
+ int dombr, i, start;
+ Medium *mp;
+ Dosfile df;
+ Partition *pp;
+
+ for(tp = types; tp->cname; tp++){
+ if(type != Tany && type != tp->type || tp->init == 0)
+ continue;
+
+ if(flag != Fnone){
+ for(mp = tp->media; mp; mp = mp->next){
+ if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
+ return mp;
+ }
+ }
+ if((tp->flag & Fprobe) == 0){
+ tp->flag |= Fprobe;
+ tp->mask = (*tp->init)();
+ }
+
+ for(i = 0; tp->mask; i++){
+ if((tp->mask & (1<<i)) == 0)
+ continue;
+ tp->mask &= ~(1<<i);
+
+ if((mp = allocm(tp)) == 0)
+ continue;
+
+ mp->dev = i;
+ mp->flag = tp->flag;
+ mp->seek = tp->seek;
+ mp->read = tp->read;
+ mp->type = tp;
+
+ if(mp->flag & Fboot){
+ if((mp->partition = (*tp->setpart)(i, "boot")) == 0)
+ mp->flag &= ~Fboot;
+ if((mp->flag & (Fflash|Fuart)) == 0)
+ (*tp->setpart)(i, "disk");
+ }
+
+ if(mp->flag & Fdos){
+ start = 0;
+ dombr = 1;
+ if(mp->type->setpart){
+ if(pp = (*mp->type->setpart)(i, "dos")){
+ if(start = pp->start)
+ dombr = 0;
+ }
+ (*tp->setpart)(i, "disk");
+ }
+ if(dosinit(mp, start, dombr) < 0)
+ mp->flag &= ~(Fini|Fdos);
+ else
+ print("dos init failed\n");
+ }
+
+ if(mp->flag & Fini){
+ mp->flag &= ~Fini;
+ for(ini = inis; *ini; ini++){
+ if(dosstat(mp, *ini, &df) <= 0)
+ continue;
+ mp->flag |= Fini;
+ break;
+ }
+ }
+
+ if((flag & mp->flag) && (dev == Dany || dev == i))
+ return mp;
+ }
+ }
+
+ return 0;
+}
+
+void
+main(void)
+{
+ Medium *mp;
+ int dev, flag, i, mode, tried, type, options;
+ char def[2*NAMELEN], file[2*NAMELEN], line[80], *p;
+ Type *tp;
+
+ machinit();
+ archinit();
+ meminit();
+ cpminit();
+ trapinit();
+ consinit(); /* screen and keyboard initially */
+/* screeninit(); */
+ cpuidprint();
+ alarminit();
+ clockinit();
+print("predawn\n");
+ predawn = 0;
+ spllo();
+print("dawn\n");
+ options = archoptionsw();
+print("options=#%ux\n", options);
+
+ mp = 0;
+ for(tp = types; tp->cname; tp++){
+ if(tp->type == Tether)
+ continue;
+ if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
+ plan9ini(mp, nil);
+ break;
+ }
+ }
+
+ if(mp == 0 || (mp->flag & Fini) == 0)
+ plan9ini(nil, flashconfig(0));
+
+ //consinit(); /* establish new console location */
+
+ if((options & Snotflash) == 0 && flashbootable(0)){
+ print("Flash boot\n");
+ flashboot(0);
+ }
+
+ tried = 0;
+ mode = Mauto;
+ p = getconf("bootfile");
+ flag = 0;
+
+ if(p != 0) {
+ mode = Manual;
+ for(i = 0; i < NMode; i++){
+ if(strcmp(p, modes[i].name) == 0){
+ mode = modes[i].mode;
+ goto done;
+ }
+ }
+ if(parse(p, &type, &flag, &dev, file) == 0) {
+ print("Bad bootfile syntax: %s\n", p);
+ goto done;
+ }
+ mp = probe(type, flag, dev);
+ if(mp == 0) {
+ print("Cannot access device: %s\n", p);
+ goto done;
+ }
+ tried = boot(mp, flag, file);
+ }
+done:
+ if(tried == 0 && mode != Manual){
+ flag = Fany;
+ if(mode == Mlocal)
+ flag &= ~Fbootp;
+ if(options & Snotflash)
+ flag &= ~Fflash;
+ if((mp = probe(Tany, flag, Dany)) != 0)
+ boot(mp, flag & mp->flag, 0);
+ }
+
+ def[0] = 0;
+ probe(Tany, Fnone, Dany);
+
+ flag = 0;
+ for(tp = types; tp->cname; tp++){
+ for(mp = tp->media; mp; mp = mp->next){
+ if(flag == 0){
+ flag = 1;
+ print("Boot devices:");
+ }
+
+ if(mp->flag & Fbootp)
+ print(" %s!%d", mp->type->name[Nbootp], mp->dev);
+ if(mp->flag & Fdos)
+ print(" %s!%d", mp->type->name[Ndos], mp->dev);
+ if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot)
+ print(" %s!%d", mp->type->name[Nboot], mp->dev);
+ }
+ }
+ if(flag)
+ print("\n");
+
+ for(;;){
+ if(getstr("boot from", line, sizeof(line), def) >= 0){
+ if(parse(line, &type, &flag, &dev, file)){
+ if(mp = probe(type, flag, dev))
+ boot(mp, flag, file);
+ }
+ }
+ def[0] = 0;
+ }
+}
+
+void
+machinit(void)
+{
+ memset(m, 0, sizeof(*m));
+ m->delayloop = 20000;
+ m->cpupvr = getpvr();
+ m->iomem = KADDR(INTMEM);
+}
+
+int
+getcfields(char* lp, char** fields, int n, char* sep)
+{
+ int i;
+
+ for(i = 0; lp && *lp && i < n; i++){
+ while(*lp && strchr(sep, *lp) != 0)
+ *lp++ = 0;
+ if(*lp == 0)
+ break;
+ fields[i] = lp;
+ while(*lp && strchr(sep, *lp) == 0){
+ if(*lp == '\\' && *(lp+1) == '\n')
+ *lp++ = ' ';
+ lp++;
+ }
+ }
+
+ return i;
+}
+
+static Map memv[512];
+static RMap rammap = {"physical memory"};
+
+void
+meminit(void)
+{
+ ulong e;
+
+ mapinit(&rammap, memv, sizeof(memv));
+ e = PADDR(&end);
+ mapfree(&rammap, e, 4*1024*1024-e); /* fixed 4Mbytes is plenty for bootstrap */
+}
+
+void*
+ialloc(ulong n, int align)
+{
+ ulong a;
+ int s;
+
+ if(align <= 0)
+ align = 4;
+ s = splhi();
+ a = mapalloc(&rammap, 0, n, align);
+ splx(s);
+ if(a == 0)
+ panic("ialloc");
+ return memset(KADDR(a), 0, n);
+}
+
+void*
+malloc(ulong n)
+{
+ ulong *p;
+
+ n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int);
+ p = ialloc(n, sizeof(int));
+ *p++ = 0xcafebeef;
+ *p++ = n;
+ return p;
+}
+
+void
+free(void *ap)
+{
+ int s;
+ ulong *p;
+
+ p = ap;
+ if(p){
+ if(*(p -= 2) != 0xcafebeef)
+ panic("free");
+ s = splhi();
+ mapfree(&rammap, (ulong)p, p[1]);
+ splx(s);
+ }
+}
+
+void
+sched(void)
+{
+}
--- /dev/null
+++ b/os/boot.original/rpcg/mem.h
@@ -1,0 +1,94 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#define BY2PG 4096 /* bytes per page */
+#define WD2PG (BY2PG/BY2WD) /* words per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
+
+#define MAXMACH 1 /* max # cpus system can run */
+#define CACHELINELOG 4
+#define CACHELINESZ (1<<CACHELINELOG)
+
+/*
+ * Time
+ */
+#define HZ (50) /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
+#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
+#define MHz 1000000
+
+/*
+ * Fundamental values
+ */
+
+#define KZERO 0 /* bootstrap runs in real mode */
+#define MACHSIZE 4096
+
+/*
+ * physical MMU
+ */
+#define KSEG0 0x20000000
+#define KSEGM 0xE0000000 /* mask to check which seg */
+
+/*
+ * MSR bits
+ */
+
+#define POW 0x40000 /* enable power mgmt */
+#define TGPR 0x20000 /* GPR0-3 remapped; 603/603e specific */
+#define ILE 0x10000 /* interrupts little endian */
+#define EE 0x08000 /* enable external/decrementer interrupts */
+#define PR 0x04000 /* =1, user mode */
+#define FPE 0x02000 /* enable floating point */
+#define ME 0x01000 /* enable machine check exceptions */
+#define FE0 0x00800
+#define SE 0x00400 /* single-step trace */
+#define BE 0x00200 /* branch trace */
+#define FE1 0x00100
+#define IP 0x00040 /* =0, vector to nnnnn; =1, vector to FFFnnnnn */
+#define IR 0x00020 /* enable instruction address translation */
+#define DR 0x00010 /* enable data address translation */
+#define RI 0x00002 /* exception is recoverable */
+#define LE 0x00001 /* little endian mode */
+
+#define KMSR (ME|FE0|FE1|FPE)
+#define UMSR (KMSR|PR|EE|IR|DR)
+
+/*
+ * MPC82x addresses
+ */
+#define BCSRMEM 0xFA400000
+#define FLASHMEM 0xFFC00000
+#define INTMEM 0xFA200000
+
+#define DPRAM (INTMEM+0x2000)
+#define DPLEN1 0x400
+#define DPLEN2 0x200
+#define DPLEN3 0x100
+#define DPBASE (DPRAM+DPLEN1)
+
+#define SCC1P (INTMEM+0x3C00)
+#define I2CP (INTMEM+0x3C80)
+#define MISCP (INTMEM+0x3CB0)
+#define IDMA1P (INTMEM+0x3CC0)
+#define SCC2P (INTMEM+0x3D00)
+#define SCC3P (INTMEM+0x3E00)
+#define SCC4P (INTMEM+0x3F00)
+#define SPIP (INTMEM+0x3D80)
+#define TIMERP (INTMEM+0x3DB0)
+#define SMC1P (INTMEM+0x3E80)
+#define DSP1P (INTMEM+0x3EC0)
+#define SMC2P (INTMEM+0x3F80)
+#define DSP2P (INTMEM+0x3FC0)
+
+#define KEEP_ALIVE_KEY 0x55ccaa33 /* clock and rtc register key */
--- /dev/null
+++ b/os/boot.original/rpcg/mkfile
@@ -1,0 +1,120 @@
+objtype=power
+OBJTYPE=power # always
+<../../../mkconfig
+SYSTARG=$OSTARG # always
+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE
+INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin #path of directory where kernel is installed
+CONF=rpcg # selects board dependent code
+TARG=qb$CONF
+OFILES=\
+ l.$O\
+ arch$CONF.$O\
+ devuart.$O\
+ uartboot.$O\
+ alarm.$O\
+ bootp.$O\
+ clock.$O\
+ conf.$O\
+ console.$O\
+ cpm.$O\
+ defont0.$O\
+ donprint.$O\
+ dosboot.$O\
+ devether.$O\
+ etherscc.$O\
+ fblt.$O\
+ gbitbltclip.$O\
+ flash.$O\
+ main.$O\
+ i2c.$O\
+ plan9boot.$O\
+ qio.$O\
+ rmap.$O\
+ screen.$O\
+ init$CONF.$O\
+ trap.$O\
+ zqs.$O\
+
+HFILES=\
+ boot.h\
+ dat.h\
+ fns.h\
+ io.h\
+ lib.h\
+ mem.h\
+ squeeze.h\
+ gnot.h\
+ arch$CONF.h\
+
+LIBS=\
+ kern\
+
+LIBDIRS=$LIBS
+LIBNAMES=${LIBS:%=lib%.a}
+LIBFILES=${LIBS:%=$ROOT/$TARGMODEL/$OBJTYPE/lib/lib%.a}
+
+#all:NV: $TARG k.mx f.mx
+all:NV: $TARG
+install:V: $INSTALLDIR/$TARG
+installall:V: $INSTALLDIR/$TARG
+
+$INSTALLDIR/%: %
+ rm -f $INSTALLDIR/$stem && cp $stem $INSTALLDIR/$stem
+
+$TARG: $OFILES $LIBNAMES
+ $LD -o $target -l -T0x140000 -R4 $OFILES $LIBFILES
+ ls -l $target
+
+qbrom$CONF: $OFILES $LIBNAMES
+ $LD -o $target -l -T0xFFC20100 -R0 -D0x140000 $OFILES $LIBFILES
+
+k.mx: $TARG
+ ms2 -S 0x100 -a 0x140000 -3 -p 4 $TARG >$target
+
+f.mx: qbrom$CONF
+ ms2 -S 0x100 -a 0xFFC20100 -3 -p 4 $prereq >$target
+
+g.mx: qbrom$CONF
+ ms2 -S 0x100 -a 0x10000 -3 -p 4 $prereq >$target
+
+%.$O: %.s
+ $AS -Dconf$CONF $stem.s
+
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+
+%.$O: $HFILES
+
+lib%.a:V: $SHELLTYPE-lib%.a
+
+rc-lib%.a nt-lib%.a:VQ:
+ echo '@{builtin cd ' $ROOT/lib$stem ';mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install}'
+ @{builtin cd $ROOT/lib$stem ;mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE install}
+
+sh-lib%.a:VQ:
+ echo "(cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)"
+ (cd $ROOT/lib$stem ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE install)
+
+clock.$O floppy.$O trap.$O: ureg.h
+conf.$O dosboot.$O main.$O: dosfs.h
+ether.$O etherscc.$O: etherif.h
+bootp.$O: ip.h
+
+clean:V:
+ rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG qboot k.mx f.mx romboot
+
+nuke-sh:QV:
+ for i in $LIBDIRS
+ do
+ echo "(cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke)"
+ (cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke)
+ done
+
+nuke-rc nuke-nt:QV:
+ for (i in $LIBDIRS)
+ {
+ echo '@{cd $ROOT/lib$i ; mk SHELLTYPE=$SHELLTYPE SYSTARG=$SYSTARG OBJTYPE=$OBJTYPE nuke}'
+ @{cd $ROOT/lib$i; mk 'SHELLTYPE='$SHELLTYPE 'SYSTARG='$SYSTARG 'OBJTYPE='$OBJTYPE nuke}
+ }
+
+nuke:V: clean nuke-$SHELLTYPE
--- /dev/null
+++ b/os/boot.original/rpcg/ms2.c
@@ -1,0 +1,179 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+void record(uchar*, int);
+void usage(void);
+void dosegment(long, int);
+void trailer(ulong);
+
+enum
+{
+ Recordsize = 32,
+};
+
+int dsegonly;
+int supressend;
+int binary;
+int addr4;
+ulong addr;
+ulong psize = 4096;
+ulong startaddr = 0x030000;
+Biobuf stdout;
+Biobuf bio;
+
+void
+main(int argc, char **argv)
+{
+ Dir dir;
+ Fhdr f;
+ int fd;
+
+ ARGBEGIN{
+ case 'd':
+ dsegonly++;
+ break;
+ case 's':
+ supressend++;
+ break;
+ case 'a':
+ addr = strtoul(ARGF(), 0, 0);
+ break;
+ case 'p':
+ psize = strtoul(ARGF(), 0, 0);
+ break;
+ case 'b':
+ binary++;
+ break;
+ case 'S':
+ startaddr = strtoul(ARGF(), 0, 0);
+ break;
+ case '4':
+ addr4++;
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if(argc != 1)
+ usage();
+
+ Binit(&stdout, 1, OWRITE);
+
+ fd = open(argv[0], OREAD);
+ if(fd < 0) {
+ fprint(2, "ms2: open %s: %r\n", argv[0]);
+ exits("open");
+ }
+
+ if(binary) {
+ if(dirfstat(fd, &dir) < 0) {
+ fprint(2, "ms2: stat failed %r");
+ exits("dirfstat");
+ }
+ Binit(&bio, fd, OREAD);
+ dosegment(0, dir.length);
+ if(supressend == 0)
+ trailer(startaddr);
+ Bterm(&stdout);
+ Bterm(&bio);
+ exits(0);
+ }
+
+ if(crackhdr(fd, &f) == 0){
+ fprint(2, "ms2: bad magic: %r\n");
+ exits("magic");
+ }
+ seek(fd, 0, 0);
+
+ Binit(&bio, fd, OREAD);
+
+ if(dsegonly)
+ dosegment(f.datoff, f.datsz);
+ else {
+ dosegment(f.txtoff, f.txtsz);
+ addr = (addr+(psize-1))&~(psize-1);
+ dosegment(f.datoff, f.datsz);
+ }
+
+ if(supressend == 0)
+ trailer(startaddr);
+
+ Bterm(&stdout);
+ Bterm(&bio);
+ exits(0);
+}
+
+void
+dosegment(long foff, int len)
+{
+ int l, n;
+ uchar buf[2*Recordsize];
+
+ Bseek(&bio, foff, 0);
+ for(;;) {
+ l = len;
+ if(l > Recordsize)
+ l = Recordsize;
+ n = Bread(&bio, buf, l);
+ if(n == 0)
+ break;
+ if(n < 0) {
+ fprint(2, "ms2: read error: %r\n");
+ exits("read");
+ }
+ record(buf, l);
+ len -= l;
+ }
+}
+
+void
+record(uchar *s, int l)
+{
+ int i;
+ ulong cksum;
+
+ if(addr4 || addr & (0xFF<<24)){
+ Bprint(&stdout, "S3%.2X%.8luX", l+5, addr);
+ cksum = l+5;
+ cksum += (addr>>24)&0xff;
+ }else{
+ Bprint(&stdout, "S2%.2X%.6X", l+4, addr);
+ cksum = l+4;
+ }
+ cksum += addr&0xff;
+ cksum += (addr>>8)&0xff;
+ cksum += (addr>>16)&0xff;
+
+ for(i = 0; i < l; i++) {
+ cksum += *s;
+ Bprint(&stdout, "%.2X", *s++);
+ }
+ Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
+ addr += l;
+}
+
+void
+trailer(ulong a)
+{
+ ulong cksum;
+
+ cksum = 0;
+ if(addr4 || a & (0xFF<<24)){
+ Bprint(&stdout, "S7%.8luX", a);
+ cksum += (a>>24)&0xff;
+ }else
+ Bprint(&stdout, "S9%.6X", a);
+ cksum += a&0xff;
+ cksum += (a>>8)&0xff;
+ cksum += (a>>16)&0xff;
+ Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: ms2 [-ds] [-a address] [-p pagesize] ?.out\n");
+ exits("usage");
+}
--- /dev/null
+++ b/os/boot.original/rpcg/plan9boot.c
@@ -1,0 +1,96 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+char *premature = "premature EOF\n";
+
+/*
+ * read in a segment
+ */
+static long
+readseg(int dev, long (*read)(int, void*, long), long len, long addr)
+{
+ char *a;
+ long n, sofar;
+
+ a = (char *)addr;
+ for(sofar = 0; sofar < len; sofar += n){
+ n = 8*1024;
+ if(len - sofar < n)
+ n = len - sofar;
+ n = (*read)(dev, a + sofar, n);
+ if(n <= 0)
+ break;
+ print(".");
+ }
+ return sofar;
+}
+
+/*
+ * boot
+ */
+int
+plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
+{
+ long n;
+ long addr;
+ void (*b)(void);
+ Exec *ep;
+
+ if((*seek)(dev, 0) < 0)
+ return -1;
+
+ /*
+ * read header
+ */
+ ep = (Exec *) ialloc(sizeof(Exec), 0);
+ n = sizeof(Exec);
+ if(readseg(dev, read, n, (long) ep) != n){
+ print(premature);
+ return -1;
+ }
+ if(GLLONG(ep->magic) != Q_MAGIC){
+ print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+ return -1;
+ }
+
+ /*
+ * read text
+ */
+ addr = PADDR(GLLONG(ep->entry));
+ n = GLLONG(ep->text);
+ print("%d", n);
+ if(readseg(dev, read, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * read data (starts at first page after kernel)
+ */
+ addr = PGROUND(addr+n);
+ n = GLLONG(ep->data);
+ print("+%d@%8.8lux", n, addr);
+ if(readseg(dev, read, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * bss and entry point
+ */
+ print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
+ uartwait();
+ scc2stop();
+ splhi();
+
+ /*
+ * Go to new code. It's up to the program to get its PC relocated to
+ * the right place.
+ */
+ b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+ (*b)();
+ return 0;
+}
binary files /dev/null b/os/boot.original/rpcg/qbromrpcg differ
--- /dev/null
+++ b/os/boot.original/rpcg/qio.c
@@ -1,0 +1,128 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+struct Queue {
+ Block* first;
+ Block* last;
+ void (*kick)(void*);
+ void* arg;
+ long len;
+};
+
+Block *
+iallocb(int n)
+{
+ Block *b;
+
+ b = (Block*)malloc(sizeof(Block)+n);
+ b->data = (uchar*)b + sizeof(Block);
+ b->rp = b->wp = b->data;
+ b->lim = b->data + n;
+ b->next = 0;
+ b->magic = 0xcafebee0;
+ return b;
+}
+
+void
+freeb(Block *b)
+{
+ if(b){
+ if(b->magic != 0xcafebee0)
+ panic("freeb");
+ b->magic = 0;
+ b->next = (Block*)0xdeadbabe;
+ free(b);
+ }
+}
+
+Queue *
+qopen(int limit, int msg, void (*kick)(void*), void *arg)
+{
+ Queue *q;
+
+ USED(limit, msg);
+ q = (Queue*)malloc(sizeof(Queue));
+ q->first = q->last = 0;
+ q->kick = kick;
+ q->arg = arg;
+ q->len = 0;
+ return q;
+}
+
+Block *
+qget(Queue *q)
+{
+ int s;
+ Block *b;
+
+ s = splhi();
+ if((b = q->first) != 0){
+ q->first = b->next;
+ b->next = 0;
+ q->len -= BLEN(b);
+ if(q->len < 0)
+ panic("qget");
+ }
+ splx(s);
+ return b;
+}
+
+void
+qbwrite(Queue *q, Block *b)
+{
+ int s;
+
+ s = splhi();
+ b->next = 0;
+ if(q->first == 0)
+ q->first = b;
+ else
+ q->last->next = b;
+ q->last = b;
+ q->len += BLEN(b);
+ splx(s);
+ if(q->kick)
+ q->kick(q->arg);
+}
+
+long
+qlen(Queue *q)
+{
+ return q->len;
+}
+
+int
+qbgetc(Queue *q)
+{
+ Block *b;
+ int s, c;
+
+ c = -1;
+ s = splhi();
+ while(c < 0 && (b = q->first) != nil){
+ if(b->rp < b->wp){
+ c = *b->rp++;
+ q->len--;
+ }
+ if(b->rp >= b->wp){
+ q->first = b->next;
+ b->next = nil;
+ }
+ }
+ splx(s);
+ return c;
+}
+
+void
+qbputc(Queue *q, int c)
+{
+ Block *b;
+
+ b = iallocb(1);
+ *b->wp++ = c;
+ qbwrite(q, b);
+}
--- /dev/null
+++ b/os/boot.original/rpcg/rmap.c
@@ -1,0 +1,104 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+void
+mapinit(RMap *rmap, Map *map, int size)
+{
+ lock(rmap);
+ rmap->map = map;
+ rmap->mapend = map+(size/sizeof(Map));
+ unlock(rmap);
+}
+
+void
+mapfree(RMap* rmap, ulong addr, int size)
+{
+ Map *mp;
+ ulong t;
+
+ if(size <= 0)
+ return;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
+ ;
+
+ if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
+ (mp-1)->size += size;
+ if(addr+size == mp->addr){
+ (mp-1)->size += mp->size;
+ while(mp->size){
+ mp++;
+ (mp-1)->addr = mp->addr;
+ (mp-1)->size = mp->size;
+ }
+ }
+ }
+ else{
+ if(addr+size == mp->addr && mp->size){
+ mp->addr -= size;
+ mp->size += size;
+ }
+ else do{
+ if(mp >= rmap->mapend){
+ print("mapfree: %s: losing 0x%uX, %d\n",
+ rmap->name, addr, size);
+ break;
+ }
+ t = mp->addr;
+ mp->addr = addr;
+ addr = t;
+ t = mp->size;
+ mp->size = size;
+ mp++;
+ }while(size = t);
+ }
+ unlock(rmap);
+}
+
+ulong
+mapalloc(RMap* rmap, ulong addr, int size, int align)
+{
+ Map *mp;
+ ulong maddr, oaddr;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->size; mp++){
+ maddr = mp->addr;
+
+ if(addr){
+ if(maddr > addr)
+ continue;
+ if(addr+size > maddr+mp->size)
+ break;
+ maddr = addr;
+ }
+
+ if(align > 0)
+ maddr = ((maddr+align-1)/align)*align;
+ if(mp->addr+mp->size-maddr < size)
+ continue;
+
+ oaddr = mp->addr;
+ mp->addr = maddr+size;
+ mp->size -= maddr-oaddr+size;
+ if(mp->size == 0){
+ do{
+ mp++;
+ (mp-1)->addr = mp->addr;
+ }while((mp-1)->size = mp->size);
+ }
+
+ unlock(rmap);
+ if(oaddr != maddr)
+ mapfree(rmap, oaddr, maddr-oaddr);
+
+ return maddr;
+ }
+ unlock(rmap);
+
+ return 0;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/screen.c
@@ -1,0 +1,242 @@
+#include "all.h"
+#include <libg.h>
+#include <gnot.h>
+
+enum {
+ Colldepth = 3,
+ Colmaxx = 640,
+ Colmaxxvis = 640,
+ Colmaxy = 480,
+};
+
+#define MINX 8
+
+extern GSubfont defont0;
+
+struct{
+ Point pos;
+ int bwid;
+}out;
+
+typedef struct Mode Mode;
+struct Mode {
+ int x;
+ int y;
+ int d;
+ char* aperture;
+ int apsize;
+};
+
+GBitmap gscreen;
+Point gchar(GBitmap*, Point, GFont*, int, Fcode);
+int setcolor(ulong, ulong, ulong, ulong);
+static void lcdinit(Mode*);
+
+void
+screeninit(void)
+{
+ Mode m;
+
+ m.x = Colmaxx;
+ m.y = Colmaxy;
+ m.d = Colldepth;
+ m.aperture = 0;
+ lcdinit(&m);
+ if(m.aperture == 0)
+ return;
+ gscreen.ldepth = 3;
+ gscreen.base = (ulong*)m.aperture;
+ gscreen.width = Colmaxx/BY2WD;
+ gscreen.r = Rect(0, 0, Colmaxxvis, Colmaxy);
+ gscreen.clipr = gscreen.r;
+ /*
+ * For now, just use a fixed colormap:
+ * 0 == white and 255 == black
+ */
+ setcolor(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+ setcolor(255, 0x00000000, 0x00000000, 0x00000000);
+
+ gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, Zero);
+ out.pos.x = MINX;
+ out.pos.y = 0;
+ out.bwid = defont0.info[' '].width;
+}
+
+void
+screenputc(int c)
+{
+ Fontchar *i;
+ Point p;
+
+ if(gscreen.base == nil)
+ return;
+ switch(c){
+ case '\n':
+ out.pos.x = MINX;
+ out.pos.y += defont0.height;
+ if(out.pos.y > gscreen.r.max.y-defont0.height)
+ out.pos.y = gscreen.r.min.y;
+ gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
+ Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height),
+ Zero);
+ break;
+ case '\t':
+ out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
+ if(out.pos.x >= gscreen.r.max.x)
+ screenputc('\n');
+ break;
+ case '\b':
+ if(out.pos.x >= out.bwid+MINX){
+ out.pos.x -= out.bwid;
+ screenputc(' ');
+ out.pos.x -= out.bwid;
+ }
+ break;
+ default:
+ if(out.pos.x >= gscreen.r.max.x-out.bwid)
+ screenputc('\n');
+ c &= 0x7f;
+ if(c <= 0 || c >= defont0.n)
+ break;
+ i = defont0.info + c;
+ p = out.pos;
+ gbitblt(&gscreen, Pt(p.x+i->left, p.y), defont0.bits,
+ Rect(i[0].x, 0, i[1].x, defont0.height),
+ S);
+ out.pos.x = p.x + i->width;
+ break;
+ }
+}
+
+void
+screenputs(char *s, int n)
+{
+ while(n-- > 0)
+ screenputc(*s++);
+}
+
+/*
+ * See section 5.2.1 (page 5-6) of the MPC823 manual
+ */
+static uchar lcdclock[17] = { /* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */
+ 0, 0, (1<<2), 1,
+ (2<<2), 2, (1<<2)|1, 3,
+ (3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1,
+ (2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2),
+ (4<<2)
+};
+
+/*
+ * support for the Sharp LQ64D341 TFT colour display
+ */
+
+enum {
+ COLS = 640,
+ ROWS = 480,
+ LDEPTH = 3, /* screen depth */
+ LCDFREQ = 25000000,
+
+ /* lccr */
+ ClockLow = 1<<11,
+ OELow = 1<<10,
+ HsyncLow = 1<<9,
+ VsyncLow = 1<<8,
+ DataLow = 1<<7,
+ Passive8 = 1<<4,
+ DualScan = 1<<3,
+ IsColour = 1<<2,
+ IsTFT = 1<<1,
+ Enable = 1<<0,
+
+ /* lchcr */
+ BigEndian = 1<<24,
+ AT7 = 7<<21, /* access type */
+
+ /* sdcr */
+ LAM = 1<<6, /* ``LCD aggressive mode'' */
+};
+
+/*
+ * TO DO: most of the data could come from a table
+ */
+static void
+lcdinit(Mode *mode)
+{
+ IMM *io;
+ int i, d;
+ long hz;
+
+ io = m->iomem;
+ mode->y = ROWS;
+ mode->x = COLS;
+ mode->d = LDEPTH;
+ mode->aperture = ialloc(mode->x*mode->y, 16);
+ mode->apsize = mode->x*mode->y;
+
+ io->sdcr &= ~LAM; /* MPC823 errata: turn off LAM before disabling controller */
+ io->lcfaa = PADDR(mode->aperture);
+ io->lccr = (((mode->x*mode->y*(1<<LDEPTH)+127)/128) << 17) | (LDEPTH << 5) | IsColour | IsTFT | OELow | VsyncLow | ClockLow;
+
+ switch(LDEPTH){
+ default:
+ case 0:
+ /* monochrome/greyscale identity map */
+ for(i=0; i<16; i++)
+ io->lcdmap[i] = i;
+ break;
+ case 2:
+ /* 4-bit grey scale map */
+ for(i=0; i<16; i++)
+ io->lcdmap[0] = (i<<8)|(i<<4)|i;
+ break;
+ case 3:
+ /* 8-bit linear map */
+ for(i=0; i<256; i++)
+ io->lcdmap[i] = (i<<8)|(i<<4)|i;
+ break;
+ }
+
+ io->lcvcr = (mode->y << 11) | (1<<28) | 33; /* 2 line vsync pulse, 34 line wait between frames */
+ io->lchcr = (mode->x<<10) | BigEndian | 228; /* clock cycles between lines */
+
+ hz = m->cpuhz;
+ d = hz/LCDFREQ;
+ if(hz/d > LCDFREQ)
+ d++;
+ if(d >= 16)
+ d = 16;
+
+ /*
+ * enable LCD outputs
+ */
+ io->pddat = 0;
+ io->pdpar = 0x1fff;
+io->pdpar &= ~SIBIT(6); /* 823 bug fix? */
+ io->pddir = 0x1fff;
+ io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17);
+ io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17);
+ io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17));
+
+ eieio();
+ io->sccrk = KEEP_ALIVE_KEY;
+ eieio();
+ io->sccr = (io->sccr & ~0x1F) | lcdclock[d];
+ eieio();
+ io->sccrk = ~KEEP_ALIVE_KEY;
+ eieio();
+ gscreen.width = gscreen.width; /* access external memory before enabling (mpc823 errata) */
+ io->lcsr = 7; /* clear status */
+ eieio();
+ io->lccr |= Enable;
+ archbacklight(1);
+}
+
+int
+setcolor(ulong p, ulong r, ulong g, ulong b)
+{
+ r >>= 28;
+ g >>= 28;
+ b >>= 28;
+ m->iomem->lcdmap[~p&0xFF] = (r<<8) | (g<<4) | b; /* TO DO: it's a function of the ldepth */
+ return 1;
+}
binary files /dev/null b/os/boot.original/rpcg/sload differ
--- /dev/null
+++ b/os/boot.original/rpcg/sload.c
@@ -1,0 +1,71 @@
+/*
+ * send S records to rpcg
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+static int dbg;
+static char buf[2048];
+static int run=1;
+static void stuffbym(char*, int, int);
+static void getdot(void);
+
+void
+main(int argc, char **argv)
+{
+ int n;
+ char *l;
+ Biobuf *f;
+ static int p;
+
+ ARGBEGIN{
+ case 'd': dbg++; break;
+ case 'n': run=0; break;
+ }ARGEND
+
+ f = Bopen(*argv? *argv: "k.mx", OREAD);
+ if(f == 0) {
+ fprint(2, "sload: cannot open k.mx: %r\n");
+ exits("sload");
+ }
+ getdot();
+ while((l = Brdline(f, '\n')) != 0) {
+ l[Blinelen(f)-1] = '\r';
+ stuffbym(l, Blinelen(f), 16);
+ getdot();
+ if(++p % 25 == 0)
+ write(2, ".", 1);
+ }
+ exits(0);
+}
+
+static void
+stuffbym(char *l, int n, int m)
+{
+ int nr, ns;
+
+ while(n > 0) {
+ ns = n;
+ if(ns > m)
+ ns = m;
+ write(1, l, ns);
+ l += ns;
+ n -= ns;
+ }
+}
+
+static void
+getdot(void)
+{
+ char c;
+
+ for(;;){
+ if(read(0, &c, 1) != 1)
+ exits("bang");
+ write(2, &c, 1);
+ if(c == '.')
+ break;
+ }
+}
--- /dev/null
+++ b/os/boot.original/rpcg/squeeze.h
@@ -1,0 +1,34 @@
+
+/*
+ * squeezed file format:
+ * Sqhdr
+ * original Exec header
+ * two Squeeze tables
+ * squeezed segment
+ * unsqueezed segment, if any
+ */
+#define SQMAGIC (ulong)0xFEEF0F1E
+
+typedef struct Sqhdr Sqhdr;
+struct Sqhdr {
+ uchar magic[4]; /* SQMAGIC */
+ uchar text[4]; /* squeezed length of text (excluding tables) */
+ uchar data[4]; /* squeezed length of data (excluding tables) */
+ uchar asis[4]; /* length of unsqueezed segment */
+ uchar toptxt[4]; /* value for 0 encoding in text */
+ uchar topdat[4]; /* value for 0 encoding in data */
+ uchar sum[4]; /* simple checksum of unsqueezed data */
+ uchar flags[4];
+};
+#define SQHDRLEN (8*4)
+
+/*
+ * certain power instruction types are rearranged by sqz
+ * so as to move the variable part of the instruction word to the
+ * low order bits. note that the mapping is its own inverse.
+ */
+#define QREMAP(X)\
+ switch((X)>>26){\
+ case 19: case 31: case 59: case 63:\
+ (X) = (((X) & 0xFC00F801) | (((X)>>15)&0x7FE) | (((X)&0x7FE)<<15));\
+ }
--- /dev/null
+++ b/os/boot.original/rpcg/trap.c
@@ -1,0 +1,233 @@
+#include "boot.h"
+
+enum
+{
+ Maxhandler= 32+16, /* max number of interrupt handlers */
+};
+
+typedef struct Handler Handler;
+struct Handler
+{
+ void (*r)(Ureg*, void*);
+ void *arg;
+ Handler *next;
+ int edge;
+};
+
+struct
+{
+ Handler *ivec[128];
+ Handler h[Maxhandler];
+ int free;
+} halloc;
+
+char *excname[] = {
+ "reserved 0",
+ "system reset",
+ "machine check",
+ "data access",
+ "instruction access",
+ "external interrupt",
+ "alignment",
+ "program exception",
+ "floating-point unavailable",
+ "decrementer",
+ "reserved A",
+ "reserved B",
+ "system call",
+ "trace trap",
+ "floating point assist",
+ "reserved F",
+ "software emulation",
+ "ITLB miss",
+ "DTLB miss",
+ "ITLB error",
+ "DTLB error",
+};
+
+char *regname[]={
+ "CAUSE", "SRR1",
+ "PC", "GOK",
+ "LR", "CR",
+ "XER", "CTR",
+ "R0", "R1",
+ "R2", "R3",
+ "R4", "R5",
+ "R6", "R7",
+ "R8", "R9",
+ "R10", "R11",
+ "R12", "R13",
+ "R14", "R15",
+ "R16", "R17",
+ "R18", "R19",
+ "R20", "R21",
+ "R22", "R23",
+ "R24", "R25",
+ "R26", "R27",
+ "R28", "R29",
+ "R30", "R31",
+};
+
+static void intr(Ureg*);
+
+void
+sethvec(int v, void (*r)(void))
+{
+ ulong *vp, pa, o;
+
+ if((ulong)r & 3)
+ panic("sethvec");
+ vp = (ulong*)KADDR(v);
+ vp[0] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */
+ vp[1] = 0x7c0802a6; /* MOVW LR, R0 */
+ vp[2] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */
+ pa = PADDR(r);
+ o = pa >> 25;
+ if(o != 0 && o != 0x7F){
+ /* a branch too far: running from ROM */
+ vp[3] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */
+ vp[4] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */
+ vp[5] = 0x7c0803a6; /* MOVW R0, LR */
+ vp[6] = 0x4e800021; /* BL (LR) */
+ }else
+ vp[3] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */
+}
+
+#define LEV(n) (((n)<<1)|1)
+#define IRQ(n) (((n)<<1)|0)
+
+void
+setvec(int v, void (*r)(Ureg*, void*), void *arg)
+{
+ Handler *h;
+ IMM *io;
+
+ if(halloc.free >= Maxhandler)
+ panic("out of interrupt handlers");
+ v -= VectorPIC;
+ h = &halloc.h[halloc.free++];
+ h->next = halloc.ivec[v];
+ h->r = r;
+ h->arg = arg;
+ halloc.ivec[v] = h;
+
+ /*
+ * enable corresponding interrupt in SIU/CPM
+ */
+
+ io = m->iomem;
+ if(v >= VectorCPIC){
+ v -= VectorCPIC;
+ io->cimr |= 1<<(v&0x1F);
+ }
+ else if(v >= VectorIRQ)
+ io->simask |= 1<<(31-IRQ(v&7));
+ else
+ io->simask |= 1<<(31-LEV(v));
+}
+
+void
+trapinit(void)
+{
+ int i;
+ IMM *io;
+
+ io = m->iomem;
+ io->sypcr &= ~(3<<2); /* disable watchdog (821/823) */
+ io->simask = 0; /* mask all */
+ io->siel = ~0; /* edge sensitive, wake on all */
+ io->cicr = 0; /* disable CPM interrupts */
+ io->cipr = ~0; /* clear all interrupts */
+ io->cimr = 0; /* mask all events */
+ io->cicr = (0xE1<<16)|(CPIClevel<<13)|(0x1F<<8);
+ io->cicr |= 1 << 7; /* enable */
+ io->tbscrk = KEEP_ALIVE_KEY;
+ io->tbscr = 1; /* TBE */
+ io->simask |= 1<<(31-LEV(CPIClevel)); /* CPM's level */
+ io->tbk = KEEP_ALIVE_KEY;
+ eieio();
+ putdec(~0);
+
+ /*
+ * set all exceptions to trap
+ */
+ for(i = 0x0; i < 0x3000; i += 0x100)
+ sethvec(i, exception);
+}
+
+void
+dumpregs(Ureg *ur)
+{
+ int i;
+ ulong *l;
+ l = &ur->cause;
+ for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
+ print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
+}
+
+void
+trap(Ureg *ur)
+{
+ int c;
+
+ c = ur->cause >> 8;
+ switch(c){
+ default:
+ {extern int predawn; predawn = 1;}
+ if(c < 0 || c >= nelem(excname))
+ print("exception/interrupt #%x\n", c);
+ else
+ print("exception %s\n", excname[c]);
+ dumpregs(ur);
+ /* spllo(); */
+ print("^P to reset\n");
+ for(;;)
+ ;
+
+ case 0x09: /* decrementer */
+ clockintr(ur, 0);
+ return;
+
+ case 0x05: /* external interrupt */
+ intr(ur);
+ break;
+ }
+}
+
+static void
+intr(Ureg *ur)
+{
+ int b, v;
+ Handler *h;
+ IMM *io;
+
+ io = m->iomem;
+ b = io->sivec>>2;
+ v = b>>1;
+ if(b & 1) {
+ if(v == CPIClevel){
+ io->civr = 1;
+ eieio();
+ v = VectorCPIC+(io->civr>>11);
+ }
+ }else
+ v += VectorIRQ;
+ h = halloc.ivec[v];
+ if(h == nil){
+ for(;;)
+ ;
+ //print("unknown interrupt %d pc=0x%lux\n", v, ur->pc);
+ return;
+ }
+ if(h->edge)
+ io->sipend |= 1<<(31-b);
+ /*
+ * call the interrupt handlers
+ */
+ do {
+ (*h->r)(ur, h->arg);
+ h = h->next;
+ } while(h != nil);
+ if(v >= VectorCPIC)
+ io->cisr |= 1<<(v-VectorCPIC);
+}
--- /dev/null
+++ b/os/boot.original/rpcg/uartboot.c
@@ -1,0 +1,189 @@
+#include "boot.h"
+
+/*
+ * this doesn't yet use the crc
+ */
+
+typedef struct Uboot Uboot;
+struct Uboot {
+ Queue* iq;
+ Block* partial;
+ ulong csum;
+ long bno;
+ uchar buf[64];
+ int nleft;
+ int ntimeout;
+};
+
+static Uboot uboot;
+ulong crc32(void *buf, int n, ulong crc);
+
+static void
+uartbrecv(uchar *p, int n)
+{
+ Uboot *ub;
+ Block *b;
+
+ ub = &uboot;
+ if(n > 0 && ub->iq != nil){
+ b = iallocb(n);
+ memmove(b->wp, p, n);
+ b->wp += n;
+ qbwrite(ub->iq, b);
+ }
+}
+
+int
+uartinit(void)
+{
+ return 1<<0;
+}
+
+Partition*
+setuartpart(int, char *s)
+{
+ static Partition pp[1];
+
+ if(strcmp(s, "boot") != 0 && strcmp(s, "disk") != 0)
+ return 0;
+ pp[0].start = 0;
+ pp[0].end = 2*1024*1024;
+ strcpy(pp[0].name, "boot");
+ return pp;
+}
+
+long
+uartseek(int, long)
+{
+ /* start the boot */
+ if(uboot.iq == nil)
+ uboot.iq = qopen(64*1024, 0, 0, 0);
+ if(uboot.partial){
+ freeb(uboot.partial);
+ uboot.partial = 0;
+ }
+ print("uart: start transmission\n");
+ uartsetboot(uartbrecv);
+ uboot.csum = ~0;
+ uboot.bno = 0;
+ uboot.nleft = 0;
+ uboot.ntimeout = 0;
+ return 0;
+}
+
+static long
+uartreadn(void *buf, int nb)
+{
+ ulong start;
+ Uboot *ub;
+ int l;
+ Block *b;
+ uchar *p;
+
+ p = buf;
+ ub = &uboot;
+ start = m->ticks;
+ while(nb > 0){
+ b = ub->partial;
+ ub->partial = nil;
+ if(b == nil){
+ ub->ntimeout = 0;
+ while((b = qget(ub->iq)) == 0){
+ if(TK2MS(m->ticks - start) >= 15*1000){
+ if(++ub->ntimeout >= 3){
+ print("uart: timeout\n");
+ return 0;
+ }
+ uartputs("n", 1);
+ }
+ }
+ }
+ l = BLEN(b);
+ if(l > nb)
+ l = nb;
+ memmove(p, b->rp, l);
+ b->rp += l;
+ if(b->rp >= b->wp)
+ freeb(b);
+ else
+ ub->partial = b;
+ nb -= l;
+ p += l;
+ }
+ return p-(uchar*)buf;
+}
+
+long
+uartread(int, void *buf, long n)
+{
+ uchar *p;
+ int l;
+ static uchar lbuf[64];
+
+ p = buf;
+ if((l = uboot.nleft) > 0){
+ if(l > n)
+ l = n;
+ uboot.nleft -= l;
+ memmove(p, uboot.buf, l);
+ p += l;
+ n -= l;
+ }
+ while(n > 0){
+ l = uartreadn(lbuf, sizeof(lbuf));
+ if(l < sizeof(lbuf))
+ return 0;
+ if(l > n){
+ uboot.nleft = l-n;
+ memmove(uboot.buf, lbuf+n, uboot.nleft);
+ l = n;
+ }
+ memmove(p, lbuf, l);
+ n -= l;
+ p += l;
+ uboot.bno++;
+ uartputs("y", 1);
+ }
+ return p-(uchar*)buf;
+}
+
+/*
+ * from Rob Warnock
+ */
+static ulong crc32tab[256]; /* initialised on first call to crc32 */
+
+enum {
+ CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+ int i, j;
+ ulong c;
+
+ for(i = 0; i < 256; i++) {
+ for(c = i << 24, j = 8; j > 0; j--)
+ if(c & (1<<31))
+ c = (c<<1) ^ CRC32POLY;
+ else
+ c <<= 1;
+ crc32tab[i] = c;
+ }
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+ uchar *p;
+
+ if(crc32tab[1] == 0)
+ initcrc32();
+ crc = ~crc;
+ for(p = buf; --n >= 0;)
+ crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+ return ~crc;
+}
--- /dev/null
+++ b/os/boot.original/rpcg/ureg.h
@@ -1,0 +1,43 @@
+struct Ureg
+{
+ ulong cause;
+ union { ulong srr1; ulong status;};
+ ulong pc; /* SRR0 */
+ ulong pad;
+ ulong lr;
+ ulong cr;
+ ulong xer;
+ ulong ctr;
+ ulong r0;
+ union{ ulong r1; ulong sp; ulong usp; };
+ ulong r2;
+ ulong r3;
+ ulong r4;
+ ulong r5;
+ ulong r6;
+ ulong r7;
+ ulong r8;
+ ulong r9;
+ ulong r10;
+ ulong r11;
+ ulong r12;
+ ulong r13;
+ ulong r14;
+ ulong r15;
+ ulong r16;
+ ulong r17;
+ ulong r18;
+ ulong r19;
+ ulong r20;
+ ulong r21;
+ ulong r22;
+ ulong r23;
+ ulong r24;
+ ulong r25;
+ ulong r26;
+ ulong r27;
+ ulong r28;
+ ulong r29;
+ ulong r30;
+ ulong r31;
+};
--- /dev/null
+++ b/os/boot.original/rpcg/zqs.c
@@ -1,0 +1,234 @@
+#include "boot.h"
+#include "squeeze.h"
+
+/*
+ * for details of `unsqueeze' see:
+ *
+ * %A Mark Taunton
+ * %T Compressed Executables: An Exercise in Thinking Small
+ * %P 385-404
+ * %I USENIX
+ * %B USENIX Conference Proceedings
+ * %D Summer 1991
+ * %C Nashville, TN
+ *
+ * several of the unimplemented improvements described in the paper
+ * have been implemented here
+ *
+ * there is a further transformation on the powerpc (QFLAG!=0) to shuffle bits
+ * in certain instructions so as to push the fixed bits to the top of the word.
+ */
+
+#define EXECHDRLEN (8*4)
+
+typedef struct Squeeze Squeeze;
+struct Squeeze {
+ int n;
+ ulong tab[7*256];
+};
+
+#define GET4(p) (((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])
+
+/*
+ * for speed of unsqueezing from Flash, certain checks are
+ * not done inside the loop (as they would be in the unsqueeze program zqs),
+ * but instead the checksum is expected to catch corrupted files.
+ * in fact the Squeeze array bounds can't be exceeded in practice
+ * because the tables are always full for a squeezed kernel.
+ */
+enum {
+ QFLAG = 1, /* invert powerpc-specific code transformation */
+ CHECK = 0, /* check precise bounds in Squeeze array (otherwise checksum detects error) */
+};
+
+static ulong chksum;
+static int rdtab(Block*, Squeeze*, int);
+static ulong* unsqueeze(ulong*, uchar*, uchar*, Squeeze*, Squeeze*, ulong);
+static uchar* unsqzseg(uchar*, Block*, long, long, char*);
+static Alarm* unsqzal;
+
+int
+issqueezed(uchar *b)
+{
+ return GET4(b) == SQMAGIC? GET4(b+SQHDRLEN): 0;
+}
+
+static void
+unsqzdot(Alarm*)
+{
+ unsqzal = alarm(500, unsqzdot, nil);
+ print(".");
+}
+
+long
+unsqueezef(Block *b, ulong *entryp)
+{
+ uchar *loada, *wp;
+ ulong toptxt, topdat, oldsum;
+ long asis, nst, nsd;
+ Sqhdr *sqh;
+ Exec *ex;
+
+ if(BLEN(b) < SQHDRLEN+EXECHDRLEN)
+ return -1;
+ sqh = (Sqhdr*)b->rp;
+ if(GET4(sqh->magic) != SQMAGIC)
+ return -1;
+ chksum = 0;
+ toptxt = GET4(sqh->toptxt);
+ topdat = GET4(sqh->topdat);
+ oldsum = GET4(sqh->sum);
+ asis = GET4(sqh->asis);
+ nst = GET4(sqh->text);
+ nsd = GET4(sqh->data);
+ b->rp += SQHDRLEN;
+ ex = (Exec*)b->rp;
+ if(GET4(ex->magic) != Q_MAGIC){
+ print("zqs: not powerPC executable\n");
+ return -1;
+ }
+ *entryp = GET4(ex->entry);
+ b->rp += EXECHDRLEN;
+ loada = KADDR(PADDR(*entryp));
+ wp = unsqzseg(loada, b, nst, toptxt, "text");
+ if(wp == nil){
+ print("zqs: format error\n");
+ return -1;
+ }
+ if(nsd){
+ wp = (uchar*)PGROUND((ulong)wp);
+ wp = unsqzseg(wp, b, nsd, topdat, "data");
+ if(wp == nil){
+ print("zqs: format error\n");
+ return -1;
+ }
+ }
+ if(asis){
+ memmove(wp, b->rp, asis);
+ wp += asis;
+ b->rp += asis;
+ }
+ if(chksum != oldsum){
+ print("\nsqueezed kernel: checksum error: %8.8lux need %8.8lux\n", chksum, oldsum);
+ return -1;
+ }
+ return wp-loada;
+}
+
+static uchar *
+unsqzseg(uchar *wp, Block *b, long ns, long top, char *what)
+{
+ static Squeeze sq3, sq4;
+
+ print("unpack %s %8.8lux %lud:", what, wp, ns);
+ if(ns == 0)
+ return wp;
+ if(rdtab(b, &sq3, 0) < 0)
+ return nil;
+ if(rdtab(b, &sq4, 8) < 0)
+ return nil;
+ if(BLEN(b) < ns){
+ print(" **size error\n");
+ return nil;
+ }
+ unsqzal = alarm(500, unsqzdot, nil);
+ wp = (uchar*)unsqueeze((ulong*)wp, b->rp, b->rp+ns, &sq3, &sq4, top);
+ cancel(unsqzal);
+ unsqzal = nil;
+ print("\n");
+ if(wp == nil){
+ print("zqs: corrupt squeezed data stream\n");
+ return nil;
+ }
+ b->rp += ns;
+ return wp;
+}
+
+static ulong*
+unsqueeze(ulong *wp, uchar *rp, uchar *ep, Squeeze *sq3, Squeeze *sq4, ulong top)
+{
+ ulong nx, csum;
+ int code, n;
+
+ if(QFLAG){
+ QREMAP(top); /* adjust top just once, outside the loop */
+ }
+ csum = chksum;
+ while(rp < ep){
+ /* no function calls within this loop for speed */
+ code = *rp;
+ rp++;
+ n = 0;
+ nx = code>>4;
+ do{
+ if(nx == 0){
+ nx = top;
+ }else{
+ if(nx==1){
+ nx = (((((rp[3]<<8)|rp[2])<<8)|rp[1])<<8)|rp[0];
+ rp += 4;
+ }else if(nx <= 8){ /* 2 to 8 */
+ nx = ((nx-2)<<8) | rp[0];
+ if(CHECK && nx >= sq4->n)
+ return nil; /* corrupted file */
+ nx = sq4->tab[nx] | rp[1];
+ rp += 2;
+ }else{ /* 9 to 15 */
+ nx = ((nx-9)<<8) | rp[0];
+ if(CHECK && nx >= sq3->n)
+ return nil; /* corrupted file */
+ nx = sq3->tab[nx];
+ rp++;
+ }
+ if(rp > ep)
+ return nil; /* corrupted file */
+ if(QFLAG){
+ QREMAP(nx);
+ }
+ }
+ *wp = nx;
+ wp++;
+ csum += nx;
+ nx = code & 0xF;
+ }while(++n == 1);
+ }
+ chksum = csum;
+ return wp;
+}
+
+static int
+rdtab(Block *b, Squeeze *sq, int shift)
+{
+ uchar *p, *ep;
+ ulong v, w;
+ int i;
+
+ if(BLEN(b) < 2)
+ return -1;
+ i = (b->rp[0]<<8) | b->rp[1];
+ if(1)
+ print(" T%d", i);
+ b->rp += 2;
+ if((i -= 2) > 0){
+ if(BLEN(b) < i)
+ return -1;
+ }
+ sq->n = 0;
+ p = b->rp;
+ ep = b->rp+i;
+ b->rp += i;
+ v = 0;
+ while(p < ep){
+ w = 0;
+ do{
+ if(p >= ep)
+ return -1;
+ w = (w<<7) | (*p & 0x7F);
+ }while(*p++ & 0x80);
+ v += w;
+ if(0)
+ print("%d %8.8lux %8.8lux\n", sq->n, v, w);
+ sq->tab[sq->n++] = v<<shift;
+ }
+ return 0;
+}