diff options
author | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-04-11 15:30:05 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-04-11 15:30:05 +0000 |
commit | 0da340bf2d7511d031d59e3caf86d83dde4cb394 (patch) | |
tree | fecad66bbe4e9b924a9c91f267d514f73dbd91ec | |
parent | 85b5f73c40de553134fa1492e8ef2ae5d374822a (diff) | |
download | plan9front-0da340bf2d7511d031d59e3caf86d83dde4cb394.tar.xz |
newboot
94 files changed, 1365 insertions, 48613 deletions
diff --git a/sys/src/boot/pc/8250.c b/sys/src/boot/pc/8250.c deleted file mode 100644 index da3171c90..000000000 --- a/sys/src/boot/pc/8250.c +++ /dev/null @@ -1,309 +0,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", 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 < 2000 && up->txbusy; timeo++) - delay(1); - up->txbusy = 0; -} diff --git a/sys/src/boot/pc/ahci.h b/sys/src/boot/pc/ahci.h deleted file mode 100644 index 931b84e5c..000000000 --- a/sys/src/boot/pc/ahci.h +++ /dev/null @@ -1,302 +0,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, /* aggressive slumber & partial sleep */ - Aalpe = 1<<26, /* aggressive 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 */ -}; - -/* sstatus register bits */ -enum{ - /* sstatus det */ - Smissing = 0<<0, - Spresent = 1<<0, - Sphylink = 3<<0, - Sbist = 4<<0, - Smask = 7<<0, - - /* sstatus speed */ - Gmissing = 0<<4, - Gi = 1<<4, - Gii = 2<<4, - Giii = 3<<4, - Gmask = 7<<4, - - /* sstatus ipm */ - Imissing = 0<<8, - Iactive = 1<<8, - Isleepy = 2<<8, - Islumber = 6<<8, - Imask = 7<<8, - - SImask = Smask | Imask, - SSmask = Smask | Isleepy, -}; - -#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; diff --git a/sys/src/boot/pc/alarm.c b/sys/src/boot/pc/alarm.c deleted file mode 100644 index f07d038b7..000000000 --- a/sys/src/boot/pc/alarm.c +++ /dev/null @@ -1,124 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#define NA 10 /* max. alarms per clock tick */ -#define MAXALARM (3 * NA) - -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) -{ -} - -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); -} diff --git a/sys/src/boot/pc/aoe.h b/sys/src/boot/pc/aoe.h deleted file mode 100644 index b06a1a92d..000000000 --- a/sys/src/boot/pc/aoe.h +++ /dev/null @@ -1,76 +0,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[]; diff --git a/sys/src/boot/pc/apm.c b/sys/src/boot/pc/apm.c deleted file mode 100644 index 6c662d6ca..000000000 --- a/sys/src/boot/pc/apm.c +++ /dev/null @@ -1,16 +0,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); -} diff --git a/sys/src/boot/pc/askbiosload.c b/sys/src/boot/pc/askbiosload.c deleted file mode 100644 index 3c92dd883..000000000 --- a/sys/src/boot/pc/askbiosload.c +++ /dev/null @@ -1 +0,0 @@ -int askbiosload = 1; diff --git a/sys/src/boot/pc/bcom.c b/sys/src/boot/pc/bcom.c deleted file mode 100644 index dcfba003e..000000000 --- a/sys/src/boot/pc/bcom.c +++ /dev/null @@ -1,465 +0,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"; - -int vga; - -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"); - - 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) -{ -} diff --git a/sys/src/boot/pc/biosload.c b/sys/src/boot/pc/biosload.c deleted file mode 100644 index 232d4e001..000000000 --- a/sys/src/boot/pc/biosload.c +++ /dev/null @@ -1 +0,0 @@ -int biosload = 1; /* enable booting from usb devices if bios permits */ diff --git a/sys/src/boot/pc/boot.c b/sys/src/boot/pc/boot.c deleted file mode 100644 index 234036816..000000000 --- a/sys/src/boot/pc/boot.c +++ /dev/null @@ -1,455 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#include "/sys/src/libmach/elf.h" - -enum { - Maxkernel = 4*1024*1024, -}; - -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(Maxkernel); - b->wp = b->bp; - b->ep = b->wp + Maxkernel; - 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; -} diff --git a/sys/src/boot/pc/bootld.c b/sys/src/boot/pc/bootld.c deleted file mode 100644 index c7c5c35c5..000000000 --- a/sys/src/boot/pc/bootld.c +++ /dev/null @@ -1,112 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -enum { - Max9load = 1024*1024, -}; - -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 + Max9load; - 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 > Max9load) { - 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; -} diff --git a/sys/src/boot/pc/bootp.c b/sys/src/boot/pc/bootp.c deleted file mode 100644 index 60dad75ca..000000000 --- a/sys/src/boot/pc/bootp.c +++ /dev/null @@ -1,726 +0,0 @@ -/* - * bootp & tftp clients, mainly for pxe booting - * - * intel says that pxe can only load into the bottom 640K, - * and intel's boot agent takes 128K, leaving only 512K - * for 9pxeload (or a tiny kernel). - */ -#include "u.h" -#include "lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#include "ip.h" -#include "aoe.h" - -extern char *persist; - -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 = 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 "); -} - /* - * if packet is too short, make it longer rather than relying - * on ethernet interface or lower layers to pad it. - */ - if (len < ETHERMINTU) - len = ETHERMINTU; - if (ethertxpkt(ctlrno, &pkt, len, Timeout) == 0) - print("xmit failure\n"); -} - -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; - strncpy(buf+4, msg, sizeof buf - 4); - 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 (%ld.%ld.%ld.%ld!%d)\n", - (a->ip >> 24) & 0xff, - (a->ip >> 16) & 0xff, - (a->ip >> 8) & 0xff, - a->ip & 0xff, - oport); - 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) - if (file == nil) - print("bootpopen: ether%d...", ctlrno); - else - 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){ - strncpy(name, file, sizeof name); - 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 < 20; 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 >= 20) { - if (file == nil) - print("bootp on ether%d timed out\n", ctlrno); - else - print("bootp on ether%d for %s timed out\n", - ctlrno, file); - 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; -} - -/* - * hack to avoid queueing packets we don't care about. - * needs to admit udp and aoe packets. - */ -int -interesting(void* pkt) -{ - ulong addr; - Netaddr *a = &server; - Udphdr *h; - - h = pkt; - if(debug) - print("inpkt %E to %E...\n", h->s, h->d); - - switch(nhgets(h->type)){ - case Aoetype: - return 1; - case ET_IP: - break; - default: - if(debug) - print("not ipv4..."); - return 0; - } - - if(h->vihl != (IP_VER|IP_HLEN)) { - print("ip bad vers/hlen\n"); - return 0; - } - if(h->udpproto != IP_UDPPROTO) { - if(debug) - print("not udp (%d)...", h->udpproto); - return 0; - } - - if(debug) - print("okay udp..."); - - if(a->port != 0 && nhgets(h->udpsport) != a->port) { - if(debug) - print("udpport %ux not %ux\n", - nhgets(h->udpsport), a->port); - return 0; - } - - addr = nhgetl(h->udpsrc); - if(a->ip != Bcastip && a->ip != addr) { - if(debug) - print("bad ip %lux not %lux\n", addr, a->ip); - return 0; - } - return 1; -} diff --git a/sys/src/boot/pc/cga.c b/sys/src/boot/pc/cga.c deleted file mode 100644 index 90e08aafa..000000000 --- a/sys/src/boot/pc/cga.c +++ /dev/null @@ -1,91 +0,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++); -} diff --git a/sys/src/boot/pc/cis.c b/sys/src/boot/pc/cis.c deleted file mode 100644 index 5c28506bc..000000000 --- a/sys/src/boot/pc/cis.c +++ /dev/null @@ -1,539 +0,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; - } -} diff --git a/sys/src/boot/pc/clock.c b/sys/src/boot/pc/clock.c deleted file mode 100644 index 0d6320770..000000000 --- a/sys/src/boot/pc/clock.c +++ /dev/null @@ -1,329 +0,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) -/* incorporates extended-model and -family bits */ -#define X86MODEL(x) ((((x)>>4)&0xf) | (((x)>>16)&0xf)<<4) -#define X86FAMILY(x) ((((x)>>8)&0xf) | (((x)>>20)&0xff)<<4) - -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", }, - { 6, 0xF, 16, "Core 2/Xeon", }, - { 6, 0x16, 16, "Celeron", }, - { 6, 0x17, 16, "Core 2/Xeon", }, - { 6, 0x1A, 16, "Core i7/Xeon", }, - { 6, 0x1C, 16, "Atom", }, - { 6, 0x1D, 16, "Xeon MP", }, - { 0xF, 1, 16, "P4", }, /* P4 */ - { 0xF, 2, 16, "PentiumIV/Xeon", }, - { 0xF, 6, 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 */ - - /* opteron 6168 matches this entry */ - { 0x1F, 9, 11, "AMD-K10 Opteron G34", },/* guesswork */ - - { 4, -1, 22, "Am486", }, /* guesswork */ - { 5, -1, 23, "AMD-K5/K6", }, /* guesswork */ - { 6, -1, 11, "AMD-Athlon", },/* guesswork */ - { 0xF, -1, 11, "AMD-K8", }, /* guesswork */ - { 0x1F, -1, 11, "AMD-K10", }, /* 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 -prcpuid(void) -{ - if (cputype == nil) - panic("prcpuid: clockinit not called"); - print("cpu0: %dMHz %s loop %d\n", cpumhz, cputype->name, loopconst); -} - -void -clockinit(void) -{ - uvlong a, b, cpufreq; - int loops, incr, x, y; - X86type *t; - - /* - * set vector for clock interrupts - */ - setvec(VectorCLOCK, clockintr, 0); - - cputype = 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"); - } -} diff --git a/sys/src/boot/pc/conf.c b/sys/src/boot/pc/conf.c deleted file mode 100644 index 51821668c..000000000 --- a/sys/src/boot/pc/conf.c +++ /dev/null @@ -1,554 +0,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[120]; - - 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 -dumpbootargs(void) -{ - char *p, *nl; - - /* in the boot, we can only print PRINTSIZE (256) bytes at a time. */ - print("boot args: "); - for (p = (char *)BOOTARGS; *p != '\0'; p = nl) { - nl = strchr(p, '\n'); - if (nl != nil) { - ++nl; - print("%.*s", (int)(nl - p), p); - } - } -} - -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); - - pref[0] = '\n'; - 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= */ - 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; -} diff --git a/sys/src/boot/pc/console.c b/sys/src/boot/pc/console.c deleted file mode 100644 index 3afb74c07..000000000 --- a/sys/src/boot/pc/console.c +++ /dev/null @@ -1,239 +0,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) /* control-r? */ - 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(); - - /* - * Often the BIOS hangs during restart if a conventional 8042 - * warm-boot sequence is tried. The following is Intel specific and - * seems to perform a cold-boot, but at least it comes back. - * And sometimes there is no keyboard... - * - * The reset register (0xcf9) is usually in one of the bridge - * chips. The actual location and sequence could be extracted from - * ACPI but why bother, this is the end of the line anyway. - */ - print("Takes a licking and keeps on ticking...\n"); - *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */ - outb(0xcf9, 0x02); - outb(0xcf9, 0x06); - - 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); - consdrain(); - 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) - strncpy(buf, def, size); - 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; -} - -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); -} diff --git a/sys/src/boot/pc/dat.h b/sys/src/boot/pc/dat.h deleted file mode 100644 index ab8e283e4..000000000 --- a/sys/src/boot/pc/dat.h +++ /dev/null @@ -1,221 +0,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 int debugload; -extern Apminfo apm; -extern char *defaultpartition; -extern int iniread; -extern int pxe; -extern int vga; - -extern int onlybios0; -extern int biosinited; -extern int biosload; diff --git a/sys/src/boot/pc/devbios.c b/sys/src/boot/pc/devbios.c deleted file mode 100644 index 8144cea7b..000000000 --- a/sys/src/boot/pc/devbios.c +++ /dev/null @@ -1,580 +0,0 @@ -/* - * boot driver for BIOS LBA devices - * heavily dependent upon correct BIOS implementation - */ -#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, - Pause = 0, /* delay to read debugging */ - - Maxdevs = 8, - CF = 1, /* carry flag: indicates an error */ - Flopid = 0, /* first floppy */ - Baseid = 0x80, /* first disk */ - - /* cx bits of Biosckext results */ - Dap = 1<<0, - Drlock = 1<<1, - Edd = 1<<2, - - /* bios calls: int 0x13 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, - - /* magic numbers for bios calls */ - Imok = 0x55aa, - Youreok = 0xaa55, -}; - -struct Biosdrive { - int ndevs; -}; - -struct Biosdev { - Devbytes size; - Devbytes offset; - uchar id; /* drive number; e.g., 0x80 */ - char type; - ushort sectsz; -}; - -typedef struct Extread { /* a device address packet */ - uchar size; - uchar unused1; - uchar nsects; - uchar unused2; - union { - ulong addr; /* actual address (nominally seg:off) */ - struct { - ushort addroff; /* :offset */ - ushort addrseg; /* segment: */ - }; - }; - uvlong stsect; /* starting sector */ - /* from edd 3.0: */ - uvlong buffer; /* instead of addr, if addr is ~0 */ -} Extread; - -typedef struct Edrvparam { - /* from edd 1.1 spec */ - ushort size; /* max. buffer (struct) size */ - ushort flags; - ulong physcyls; - ulong physheads; - ulong phystracksects; - uvlong physsects; - ushort sectsz; - /* pointer is required to be unaligned, bytes 26-29. ick. */ -// void *dpte; /* ~0ull: invalid */ - uchar dpte[4]; - - /* 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); - -void -stopbiosload(void) -{ - biosload = 0; - print("disabling bios loading\n"); -} - -/* convert ah error code to a string (just common cases) */ -static char * -strerr(uchar err) -{ - switch (err) { - case 0: - return "none"; - case 0x80: - return "disk timeout"; - default: - return "unknown"; - } -} - -/* - * caller must zero or otherwise initialise *rp, - * other than ax, bx, dx, si & ds. - */ -static int -biosdiskcall(Ureg *up, uchar op, ulong bx, ulong dx, ulong si) -{ - int s; - uchar err; - - s = splhi(); /* don't let the bios call be interrupted */ - - up->ax = op << 8; - up->bx = bx; - up->dx = dx; /* often drive id */ - /* - * ensure that dap addr fits in a short. - */ - if((si & 0xffff0000) != 0) - print("biosdiskcall: dap address %#lux not a short\n", si); - - /* assume si is in first 64K */ - if((si & 0xffff0000) != ((si + 512 - 1) & 0xffff0000)) - print("biosdiskcall: dap address %#lux too near segment boundary\n", - si); - up->si = si; /* ds:si forms data access packet addr */ - up->ds = 0; - up->di = 0; - - /* - * *up is copied into low memory (realmoderegs) and thence into - * the machine registers before the BIOS call, and the registers are - * copied into realmoderegs and thence into *up after. - * - * realmode loads these registers: di, si, ax, bx, cx, dx, ds, es. - */ - realmode(0x13, up); - - splx(s); - - if (up->flags & CF) { - if (Debug && dx == Baseid) { - err = up->ax >> 8; - print("\nbiosdiskcall: int 0x13 op %#ux drive %#lux " - "failed, ah error code %#ux (%s)\n", - op, dx, err, strerr(err)); - } - 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, ndrive; - Devbytes size; - char type; - Biosdev *bdp; - static int beenhere; - - delay(Pause); /* pause to read the screen (DEBUG) */ - - /* - * 9pxeload can't use bios int 13 calls; they wedge the machine. - */ - if (pxe || !biosload || onlybios0 || biosinited || beenhere) - return 0; - beenhere = 1; - - ndrive = *(uchar *)KADDR(0x475); - if (Debug) - print("bios claims %d drive(s)\n", ndrive); - mask = lastbit = 0; - for (devid = Baseid; devid < (1 << 8) && bdrive.ndevs < Maxdevs; - devid++) { - lba = islba(devid); - if (lba < 0) - break; - - /* don't reset; it seems to hang the bios */ - if(!lba /* || devid != Baseid && dreset(devid) < 0 */ ) - continue; - type = Typenone; - if (getsize(devid, &type) == 0) /* no device */ - 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 %#ux: %,llud bytes, type %d\n", - bdrive.ndevs, devid, size, type); - bdrive.ndevs++; - } - USED(lastbit); -// islba(Baseid); /* do a successful operation to make bios happy again */ - - if (Debug && ndrive != bdrive.ndevs) - print("bios: ndrive %d != bdrive.ndevs %d\n", - ndrive, bdrive.ndevs); - if (ndrive < bdrive.ndevs) - bdrive.ndevs = ndrive; /* use smaller estimate */ - - /* - * some 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. - */ - if (bdrive.ndevs > 0) - biosinited = 1; - delay(Pause); /* pause to read the screen (DEBUG) */ - - 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); -} - -static void -dump(void *addr, int wds) -{ - unsigned i; - ulong *p = addr; - - for (i = 0; i < wds; i++) - print("%lux ", p[i]); - if (i % 8 == 7) - print("\n"); - print("\n"); -} - -/* realmode loads these registers: di, si, ax, bx, cx, dx, ds, es */ -static void -initrealregs(Ureg *up) -{ - memset(up, 0, sizeof *up); -} - -/* 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) - /* scribble on the buffer to provoke trouble */ - memset((uchar *)BIOSXCHG, 'r', bdp->sectsz); - - /* space for a big, optical-size 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->stsect = offset; - erp->buffer = PADDR(BIOSXCHG); - - erp->addr = PADDR(BIOSXCHG); - erp->addroff = PADDR(BIOSXCHG); /* pedantic seg:off */ - erp->addrseg = 0; - /* - * ensure that buffer addr fits in a short. - */ - if((erp->addr & 0xffff0000) != 0) - print("sectread: address %#lux not a short\n", erp->addr); - if((erp->addr & 0xffff0000) != ((erp->addr + 512 - 1) & 0xffff0000)) - print("sectread: address %#lux too near seg boundary\n", - erp->addr); - if (Debug) - print("reading drive %#ux sector %lld -> %#lux...", - bdp->id, offset, erp->addr); - - initrealregs(®s); -// regs.es = erp->addr >> 16; - regs.es = 0; - delay(Pause); /* pause to read the screen (DEBUG) */ - /* - * int 13 read sector expects, buffer seg in di?, - * dap (erp) in si, 0x42 in ah, drive in dl. - */ - if (biosdiskcall(®s, Biosrdsect, erp->addr, bdp->id, PADDR(erp)) < 0) { - print("sectread: bios failed to read %ld @ sector %lld of %#ux\n", - n, offset, bdp->id); - stopbiosload(); /* stop trying before we wedge */ - return -1; - } - if (Debug) - print("OK\n"); - - /* copy into caller's buffer */ - memmove(a, (char *)BIOSXCHG, n); - if(0 && Debug){ - cp = (uchar *)BIOSXCHG; - print("-%ux %ux %ux %ux--%16.16s-\n", - cp[0], cp[1], cp[2], cp[3], (char *)cp + 480); - } - delay(Pause); /* pause to read the screen (DEBUG) */ - return n; -} - -/* not tested yet. */ -static int -dreset(uchar drive) -{ - print("devbios: resetting %#ux...", drive); - initrealregs(®s); - if (biosdiskcall(®s, Biosinit, 0, drive, 0) < 0) - print("failed"); - print("\n"); - return regs.ax? -1: 0; /* ax!=0 on error */ -} - -static int -islba(uchar drive) -{ - initrealregs(®s); - if (biosdiskcall(®s, Biosckext, Imok, drive, 0) < 0) - /* - * we have an old bios without extensions, in theory. - * in practice, there may just be no drive for this number. - */ - return -1; - if(regs.bx != Youreok){ - print("islba: buggy bios: drive %#ux extension check returned " - "%lux in bx\n", drive, regs.bx); - stopbiosload(); - return -1; - } - if (Debug) { - print("islba: drive %#ux extensions version %d.%d cx %#lux\n", - drive, (uchar)(regs.ax >> 8), (uchar)regs.ax, regs.cx); - print("\tsubsets supported:"); - if (regs.cx & Dap) - print(" disk access;"); - if (regs.cx & Drlock) - print(" drive locking;"); - if (regs.cx & Edd) - print(" enhanced disk support;"); - print("\n"); - } - delay(Pause); /* pause to read the screen (DEBUG) */ - return regs.cx & Dap; -} - -/* - * 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; - - initrealregs(®s); - if (biosdiskcall(®s, Biosdrvtype, Imok, id, 0) < 0) - return 0; - - *typep = dtype = (ushort)regs.ax >> 8; - if(dtype == Typenone){ - print("no such device %#ux of type %d\n", id, dtype); - return 0; - } - if(dtype != Typedisk){ - print("non-disk device %#ux of type %d\n", id, dtype); - return 0; - } - 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; - - initrealregs(®s); - if (biosdiskcall(®s, Biosedrvparam, 0, bdp->id, PADDR(edp)) < 0) - return 0; /* old bios without extensions */ - if(Debug) { - print("extgetsize: drive %#ux info flags %#ux", - bdp->id, edp->flags); - if (edp->key == 0xbedd) - print(" %.4s %.8s", edp->bustype, edp->ifctype); - print("\n"); - } - if (edp->sectsz <= 0) { - print("extgetsize: drive %#ux: sector size <= 0\n", bdp->id); - edp->sectsz = 1; /* don't divide by 0 */ - } - 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(!biosload || 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) { - if (bdp->sectsz == 0) { - print("devbios: zero sector size\n"); - return -1; - } - want = bdp->sectsz; - if (totnr + want > n) - want = n - totnr; - if(0 && Debug && debugload) - print("bios%d, read: %ld @ off %lld, want: %d, id: %#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) - 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; -} diff --git a/sys/src/boot/pc/devfloppy.c b/sys/src/boot/pc/devfloppy.c deleted file mode 100644 index d70918b77..000000000 --- a/sys/src/boot/pc/devfloppy.c +++ /dev/null @@ -1,860 +0,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; - - /* native access to disks seems to interfere with bios loading */ - if (biosload) - return 0; - - 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; - - /* there are no partitions on floppies */ - if(strncmp(file, "dos!", 4) == 0) - file += 4; - if(strchr(file, '!') != nil || 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; - - if (dp->t->bytes == 0 || dp->t->sectors == 0 || dp->t->heads == 0) - panic("floppypos: zero geometry"); - 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; -} diff --git a/sys/src/boot/pc/devfloppy.h b/sys/src/boot/pc/devfloppy.h deleted file mode 100644 index 1d9a76a85..000000000 --- a/sys/src/boot/pc/devfloppy.h +++ /dev/null @@ -1,196 +0,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); -} diff --git a/sys/src/boot/pc/devi82365.c b/sys/src/boot/pc/devi82365.c deleted file mode 100644 index 456d911df..000000000 --- a/sys/src/boot/pc/devi82365.c +++ /dev/null @@ -1,742 +0,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; -} diff --git a/sys/src/boot/pc/devpccard.c b/sys/src/boot/pc/devpccard.c deleted file mode 100644 index 8db7545ec..000000000 --- a/sys/src/boot/pc/devpccard.c +++ /dev/null @@ -1,1606 +0,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; - } -} diff --git a/sys/src/boot/pc/devsd.c b/sys/src/boot/pc/devsd.c deleted file mode 100644 index 17aa35677..000000000 --- a/sys/src/boot/pc/devsd.c +++ /dev/null @@ -1,632 +0,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) -{ - /* native access to disks seems to interfere with bios loading */ - if(sdnunit == 0 && !biosload) - _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 offset; - uvlong bno, max, nb; - char *a; - static ulong bsz; - static uchar *b; - - 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. - */ - if (unit->secsize == 0) - panic("sdbio: zero sector size"); - 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); -} - -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); -} - -void* -sdmalloc(void *p, ulong sz) -{ - if(p != nil) { - memset(p, 0, sz); - return p; - } - return malloc(sz); -} diff --git a/sys/src/boot/pc/dma.c b/sys/src/boot/pc/dma.c deleted file mode 100644 index edaaa2fe5..000000000 --- a/sys/src/boot/pc/dma.c +++ /dev/null @@ -1,245 +0,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); -} - */ diff --git a/sys/src/boot/pc/dosboot.c b/sys/src/boot/pc/dosboot.c deleted file mode 100644 index 9a0f5bc4f..000000000 --- a/sys/src/boot/pc/dosboot.c +++ /dev/null @@ -1,584 +0,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; /* assume dos is embedded at start of an Fs */ - 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"); - - if (dos->sectsize == 0 || dos->clustsize == 0) - panic("fatwalk: zero sector or cluster size"); - 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; /* don't cache this block */ - 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); -} diff --git a/sys/src/boot/pc/dosfs.h b/sys/src/boot/pc/dosfs.h deleted file mode 100644 index 1107c4cec..000000000 --- a/sys/src/boot/pc/dosfs.h +++ /dev/null @@ -1,62 +0,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*); diff --git a/sys/src/boot/pc/eoffs b/sys/src/boot/pc/eoffs deleted file mode 100644 index e69de29bb..000000000 --- a/sys/src/boot/pc/eoffs +++ /dev/null diff --git a/sys/src/boot/pc/error.h b/sys/src/boot/pc/error.h deleted file mode 100644 index 98277d632..000000000 --- a/sys/src/boot/pc/error.h +++ /dev/null @@ -1,58 +0,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 */ diff --git a/sys/src/boot/pc/ether.c b/sys/src/boot/pc/ether.c deleted file mode 100644 index 1e7543fbd..000000000 --- a/sys/src/boot/pc/ether.c +++ /dev/null @@ -1,331 +0,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, }, - { "vt6105m", rhinepnp, 0, }, /* until we have a 6105 boot driver */ -// { "GA620", ga620pnp, 0, }, - { "83820", dp83820pnp, 0, }, - { "dp83820", dp83820pnp, 0, }, - - { 0, } -}; - -static void xetherdetach(void); - -static void -fakeintrs(Alarm *) -{ - int ctlrno; - Ether *eth; - - for(ctlrno = 0; ctlrno < MaxEther; ctlrno++) { - eth = ðer[ctlrno]; - if (eth->interrupt) - eth->interrupt(nil, eth); - } - alarm(TK2MS(1), fakeintrs, nil); -} - -/* - * terrible temporary hack for 82575. - * if we do actually get the right interrupts, this quickly floods - * the alarm table and we panic, so use with caution. - */ -static void -startfakeintrs(void) -{ - static int first = 1; - - if (first) { - first = 0; - fakeintrs(nil); - } -} - -int -etherinit(void) -{ - Ether *ctlr; - int ctlrno, i, mask, n, x; - - fmtinstall('E', eipfmt); - - if (getconf("*fakeintrs") != nil || getconf("*9loadfakeintrs") != nil) - startfakeintrs(); - 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; - } - } - if (mask == 0) { - print("no ethernet interfaces recognised\n"); - pcihinv(nil, Pcibcnet); - } - 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; - /* - * idling here cuts time to load 9pc.gz in a parallels vm - * from 4 minutes to about 1 second. - */ - idle(); - } - - 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; -} diff --git a/sys/src/boot/pc/ether2000.c b/sys/src/boot/pc/ether2000.c deleted file mode 100644 index bbd47d8ae..000000000 --- a/sys/src/boot/pc/ether2000.c +++ /dev/null @@ -1,247 +0,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 */ -}; - -typedef struct Ctlr Ctlr; -typedef struct Ctlr { - Pcidev* pcidev; - Ctlr* next; - int active; -} Ctlr; - -static Ctlr* ctlrhead; -static Ctlr* ctlrtail; - -static struct { - char* name; - int id; -} ne2000pci[] = { - { "Realtek 8029", (0x8029<<16)|0x10EC, }, - { "Winbond 89C940", (0x0940<<16)|0x1050, }, - { nil }, -}; - -static int nextport; -static ulong portsinuse[16]; - -static int -inuse(ulong port) -{ - int i; - - for (i = 0; i < nextport; i++) - if (portsinuse[i] == port) - return 1; - - /* port is available. mark it as used now. */ - if (nextport >= nelem(portsinuse)) - return 1; /* too many ports in use */ - portsinuse[nextport++] = port; - return 0; -} - -static Ctlr* -ne2000match(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; - - /* - * It suffices to fill these in, - * the rest is gleaned from the card. - */ - edev->port = port; - edev->irq = p->intl; - - ctlr->active = 1; - return ctlr; - } - - return nil; -} - -static void -ne2000pnp(Ether* edev) -{ - int i, id; - Pcidev *p; - Ctlr *ctlr; - - /* - * 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; - - if(ctlrhead != nil) - ctlrtail->next = ctlr; - else - ctlrhead = ctlr; - ctlrtail = ctlr; - } - } - - /* - * Is it a card with an unrecognised vid+did? - * 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); - } - - if(id != 0) - ne2000match(edev, id); - else for(i = 0; ne2000pci[i].name; i++){ - if(ne2000match(edev, ne2000pci[i].id) != nil) - break; - } -} - -/* may be called more than once */ -int -ne2000reset(Ether* ether) -{ - ushort buf[16]; - ulong port; - Dp8390 *ctlr; - int i; - uchar ea[Eaddrlen]; - - if(ether->port == 0) - ne2000pnp(ether); - - /* - * port == 0 is a desperate attempt to find something at the - * default port. only allow one of these to be found, and - * only if no other card has been found. - */ - if(ether->port == 0 && ether->ctlrno > 0) - return -1; - /* - * 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; - - if(inuse(ether->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 = 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. - * Parallels has buf[0x0E] == 0x00 whereas real hardware - * usually has 0x57. - */ - dp8390reset(ether); - memset(buf, 0, sizeof(buf)); - dp8390read(ctlr, buf, 0, sizeof(buf)); - i = buf[0x0E] & 0xFF; - if((i != 0x00 && i != 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; -} diff --git a/sys/src/boot/pc/ether2114x.c b/sys/src/boot/pc/ether2114x.c deleted file mode 100644 index 33bcff2c4..000000000 --- a/sys/src/boot/pc/ether2114x.c +++ /dev/null @@ -1,1679 +0,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, - CentaurP = (0x0985<<16)|0x1317, - CentaurPcb = (0x1985<<16)|0x1317, -}; - -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", 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]; - } - } - if(ctlr->id == CentaurP || ctlr->id == CentaurPcb){ - memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic)); - for(i = 0; i < Eaddrlen; i += 2){ - ctlr->srom[20+i] = ctlr->srom[8+i]; - ctlr->srom[20+i+1] = ctlr->srom[8+i+1]; - } - } - - /* - * 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((ctlr->id == CentaurP || ctlr->id == CentaurPcb) && k != 1) - continue; - 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 Tulip0: /* 21140 */ - case Tulip1: /* 21041 */ - case Pnic: /* PNIC */ - case Pnic2: /* PNIC-II */ - case CentaurP: /* ADMtek */ - case CentaurPcb: /* ADMtek CardBus */ - 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; - case CentaurP: - case CentaurPcb: - /* - * Nice - the register offsets change from *8 to *4 - * for CSR16 and up... - * CSR25/26 give the MAC address read from the SROM. - * Don't really need to use this other than as a check, - * the SROM will be read in anyway so the value there - * can be used directly. - */ - debug("csr25 %8.8luX csr26 %8.8luX\n", - inl(ctlr->port+0xA4), inl(ctlr->port+0xA8)); - debug("phyidr1 %4.4luX phyidr2 %4.4luX\n", - inl(ctlr->port+0xBC), inl(ctlr->port+0xC0)); - 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; -} diff --git a/sys/src/boot/pc/ether589.c b/sys/src/boot/pc/ether589.c deleted file mode 100644 index d9923062d..000000000 --- a/sys/src/boot/pc/ether589.c +++ /dev/null @@ -1,211 +0,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 */ -} diff --git a/sys/src/boot/pc/ether79c970.c b/sys/src/boot/pc/ether79c970.c deleted file mode 100644 index 1c3259d6f..000000000 --- a/sys/src/boot/pc/ether79c970.c +++ /dev/null @@ -1,540 +0,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 */ - case 0x2625003: /* PCnet-FAST III 79C973 */ - break; - default: - print("unknown PCnet card version 0x%.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; -} diff --git a/sys/src/boot/pc/ether8003.c b/sys/src/boot/pc/ether8003.c deleted file mode 100644 index 1ea9be218..000000000 --- a/sys/src/boot/pc/ether8003.c +++ /dev/null @@ -1,258 +0,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; -} diff --git a/sys/src/boot/pc/ether8139.c b/sys/src/boot/pc/ether8139.c deleted file mode 100644 index 650df1b30..000000000 --- a/sys/src/boot/pc/ether8139.c +++ /dev/null @@ -1,614 +0,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; -} diff --git a/sys/src/boot/pc/ether8169.c b/sys/src/boot/pc/ether8169.c deleted file mode 100644 index 1cfd1b03c..000000000 --- a/sys/src/boot/pc/ether8169.c +++ /dev/null @@ -1,1008 +0,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. - * 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 - -#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 */ - Coal = 0xE2, /* Interrupt Mitigation (Coalesce) */ - Rdsar = 0xE4, /* Receive Descriptor Start Address */ - Etx = 0xEC, /* Early Transmit Threshold */ -}; - -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 */ - Macv07 = 0x24800000, /* RTL8102e */ - Macv07a = 0x34800000, /* RTL8102e */ - Macv11 = 0x30000000, /* RTL8168B/8111B */ - Macv12 = 0x38000000, /* RTL8169B/8111B */ - Macv12a = 0x3c000000, /* RTL8169C/8111C */ - Macv13 = 0x34000000, /* RTL8101E */ - Macv14 = 0x30800000, /* RTL8100E */ - Macv15 = 0x38800000, /* RTL8100E */ -// Macv19 = 0x3c000000, /* dup with Macv12a: RTL8111c-gr */ - Macv25 = 0x28000000, /* RTL8168D */ - 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 { - u32int control; - u32int vlan; - u32int addrlo; - u32int 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, /* TSO; WARNING: contains lark's vomit */ -}; - -enum { /* Receive Descriptor control */ - RxflMASK = 0x00001FFF, /* Receive Frame Length */ - 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; - u32int rxer; - u16int misspkt; - u16int fae; - u32int tx1col; - u32int txmcol; - u64int rxokph; - u64int rxokbrd; - u32int rxokmu; - u16int txabt; - u16int txundrn; -}; - -enum { /* Variants */ - Rtl8100e = (0x8136<<16)|0x10EC, /* RTL810[01]E: pci-e */ - Rtl8169c = (0x0116<<16)|0x16EC, /* RTL8169C+ (USR997902) */ - Rtl8169sc = (0x8167<<16)|0x10EC, /* RTL8169SC */ - Rtl8168b = (0x8168<<16)|0x10EC, /* RTL8168B: pci-e */ - Rtl8169 = (0x8169<<16)|0x10EC, /* RTL8169 */ -}; - -typedef struct Ctlr Ctlr; -typedef struct Ctlr { - int port; - Pcidev* pcidev; - Ctlr* next; - int active; - - QLock alock; /* attach */ - Lock ilock; /* init */ - int init; /* */ - - int pciv; /* */ - int macv; /* MAC version */ - int phyv; /* PHY version */ -// int pcie; /* flag: pci-express device? */ - -// uvlong mchash; /* multicast hash */ - - 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; - - 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 */ - int imr; - - 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("ether8169: 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) -{ - u32int 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. - * This better be aligned on 8. - */ - 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) -{ - u32int r; - Ctlr *ctlr; - u8int cplusc; - - ctlr = edev->ctlr; - ilock(&ctlr->ilock); - - rtl8169halt(ctlr); - - /* - * MAC Address is not settable on some (all?) chips. - * 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|Am|Apm; - - /* - * Setting Mulrw in Cplusc disables the Tx/Rx DMA burst - * settings in Tcr/Rcr; the 1<<14 is magic. - */ - cplusc = csr16r(ctlr, Cplusc) & ~(1<<14); - cplusc |= Rxchksum | Mulrw; - switch(ctlr->macv){ - default: - panic("ether8169: unknown macv %#08ux for vid %#ux did %#ux", - ctlr->macv, ctlr->pcidev->vid, ctlr->pcidev->did); - case Macv01: - 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 Macv07: - case Macv07a: - case Macv11: - case Macv12: - case Macv12a: - case Macv14: - case Macv15: - case Macv25: - 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); - csr32w(ctlr, Mar0, 0); - csr32w(ctlr, Mar0+4, 0); - 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); - ctlr->imr = Serr|Timeout|Fovw|Punlc|Rdu|Ter|Rer|Rok; - csr16w(ctlr, Imr, ctlr->imr); - - /* - * Clear missed-packet counter; - * clear early transmit threshold value; - * set the descriptor ring base addresses; - * set the maximum receive packet size; - * no early-receive interrupts. - * - * note: the maximum rx size is a filter. the size of the buffer - * in the descriptor ring is still honored. we will toss >Mtu - * packets because they've been fragmented into mutiple - * rx buffers. - */ - csr32w(ctlr, Mpc, 0); - csr8w(ctlr, Etx, 0x3f); /* magic */ - 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, 16383); /* was Mps; see above comment */ - r = csr16r(ctlr, Mulint) & 0xF000; /* no early rx interrupts */ - csr16w(ctlr, Mulint, r); - csr16w(ctlr, Cplusc, cplusc); - csr16w(ctlr, Coal, 0); - - /* - * Set configuration. - */ - switch(ctlr->pciv){ - case Rtl8169sc: - csr8w(ctlr, Cr, Te|Re); - csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited); - csr32w(ctlr, Rcr, ctlr->rcr); - break; - case Rtl8168b: - case Rtl8169c: - csr16w(ctlr, Cplusc, 0x2000); /* magic */ - csr8w(ctlr, Cr, Te|Re); - csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited); - csr32w(ctlr, Rcr, ctlr->rcr); - 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); - if (ctlr->td == nil || ctlr->tb == nil || - ctlr->rd == nil || ctlr->rb == nil || ctlr->dtcc == nil) - panic("rtl8169attach: out of memory"); - if(rtl8169init(edev) == -1) - panic("rtl8169attach: init fail"); - ctlr->init = 1; - } - qunlock(&ctlr->alock); - - /* - * Wait for link to be ready. - */ - for(timeo = 0; timeo < 350; timeo++){ - if(miistatus(ctlr->mii) == 0) - break; - delay(100); /* print fewer miistatus messages */ - } -} - -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); - - 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; - u32int 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) - 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--; - if (!ctlr->init) - print("rtl8169receive: ctlr not initialised\n"); - if (ctlr->nrd == 0) - print("rtl8169receive: zero ctlr->nrd\n"); - rdh = NEXT(rdh, ctlr->nrd); - - if(ctlr->nrdfree < ctlr->nrd/2) - rtl8169replenish(ctlr); - } - ctlr->rdh = rdh; -} - -static void -rtl8169interrupt(Ureg*, void* arg) -{ - Ctlr *ctlr; - Ether *edev; - u32int isr; - - edev = arg; - ctlr = edev->ctlr; - - while((isr = csr16r(ctlr, Isr)) != 0 && isr != 0xFFFF){ - csr16w(ctlr, Isr, isr); - if((isr & ctlr->imr) == 0) - break; - 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", - csr16r(ctlr, Imr), isr); - } -} - -static int -vetmacv(Ctlr *ctlr, uint *macv) -{ - *macv = csr32r(ctlr, Tcr) & HwveridMASK; - switch(*macv){ - default: - return -1; - case Macv01: - case Macv02: - case Macv03: - case Macv04: - case Macv05: - case Macv07: - case Macv07a: - case Macv11: - case Macv12: - case Macv12a: - case Macv13: - case Macv14: - case Macv15: - case Macv25: - break; - } - return 0; -} - -static void -rtl8169pci(void) -{ - Pcidev *p; - Ctlr *ctlr; - int i, port; -// int pcie; - uint macv; - - p = nil; - while(p = pcimatch(p, 0, 0)){ - if(p->ccrb != Pcibcnet || p->ccru != 0) - continue; - -// pcie = 0; - switch(i = p->did<<16 | p->vid){ - default: - continue; - case Rtl8100e: /* RTL810[01]E ? */ - case Rtl8168b: /* RTL8168B */ -// pcie = 1; - break; - case Rtl8169c: /* RTL8169C */ - case Rtl8169sc: /* RTL8169SC */ - case Rtl8169: /* RTL8169 */ - break; - case (0xC107<<16)|0x1259: /* Corega CG-LAPCIGT */ - i = Rtl8169; - break; - } - - port = p->mem[0].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; -// ctlr->pcie = pcie; - - if(vetmacv(ctlr, &macv) == -1){ - iofree(port); - free(ctlr); - print("rtl8169: unknown mac %.4ux %.8ux\n", p->did, macv); - continue; - } - - 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 = macv; - - rtl8169mii(ctlr); - - pcisetbme(p); - - if(rtl8169ctlrhead != nil) - rtl8169ctlrtail->next = ctlr; - else - rtl8169ctlrhead = ctlr; - rtl8169ctlrtail = ctlr; - } -} - -int -rtl8169pnp(Ether* edev) -{ - u32int r; - Ctlr *ctlr; - static int once; - - if(once == 0){ - once = 1; - 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; - return 0; -} diff --git a/sys/src/boot/pc/ether82557.c b/sys/src/boot/pc/ether82557.c deleted file mode 100644 index fef59eec9..000000000 --- a/sys/src/boot/pc/ether82557.c +++ /dev/null @@ -1,885 +0,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", 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 0x103B: /* Intel 82562EM */ - case 0x103C: /* 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 0x27DC: /* Intel 82801G PRO/100 VE */ - 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; -} diff --git a/sys/src/boot/pc/ether82563.c b/sys/src/boot/pc/ether82563.c deleted file mode 100644 index 8ff1d1e39..000000000 --- a/sys/src/boot/pc/ether82563.c +++ /dev/null @@ -1,1165 +0,0 @@ -/* - * Bootstrap driver for - * Intel 82563, 82571, 82573, 82575, 82576 - * GbE 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, /* MAC-PHY Interface */ - 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 */ - Pbs = 0x00001008, /* Packet Buffer Size */ - - /* 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, /* Writeback Threshold */ - WthreshSHIFT = 16, - Gran = 0x01000000, /* Granularity */ - Qenable = 0x02000000, /* Queue Enable (82575eb) */ -}; - -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, -}; - -typedef struct { - ushort *reg; - ulong *reg32; - int sz; -} Flash; - -enum { - /* 16 and 32-bit flash registers for ich flash parts */ - Bfpr = 0x00/4, /* flash base 0:12; lim 16:28 */ - Fsts = 0x04/2, /* flash status; Hsfsts */ - Fctl = 0x06/2, /* flash control; Hsfctl */ - Faddr = 0x08/4, /* flash address to r/w */ - Fdata = 0x10/4, /* data @ address */ - - /* status register */ - Fdone = 1<<0, /* flash cycle done */ - Fcerr = 1<<1, /* cycle error; write 1 to clear */ - Ael = 1<<2, /* direct access error log; 1 to clear */ - Scip = 1<<5, /* spi cycle in progress */ - Fvalid = 1<<14, /* flash descriptor valid */ - - /* control register */ - Fgo = 1<<0, /* start cycle */ - Flcycle = 1<<1, /* two bits: r=0; w=2 */ - Fdbc = 1<<8, /* bytes to read; 5 bits */ -}; - -enum { - Nrdesc = 32, /* multiple of 8 */ - Ntdesc = 8, /* multiple of 8 */ -}; - -enum { - i82563, - i82566, - i82567, - i82571, - i82572, - i82573, - i82575, - i82576, -}; - -static char *tname[] = { - "i82563", - "i82566", - "i82567", - "i82571", - "i82572", - "i82573", - "i82575", - "i82576", -}; - -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; - - u32int* 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); -} - -int interesting(void*); - -static void -i82563interrupt(Ureg*, void* arg) -{ - int icr, im, rdh, txdw = 0, rxcnt; - Block *bp; - Ctlr *ctlr; - Ether *edev; - Rdesc *rdesc; - - edev = arg; - ctlr = edev->ctlr; - - ilock(&ctlr->imlock); - csr32w(ctlr, Imc, ~0); - im = ctlr->im; - - rxcnt = 0; - 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; - if (interesting(bp->rp)) - toringbuf(edev, bp); - freeb(bp); - } else if (rdesc->status & Reop && rdesc->errors) - print("%s: input packet error %#ux\n", - tname[ctlr->type], rdesc->errors); - rdesc->status = 0; - rdh = NEXT(rdh, Nrdesc); - if (++rxcnt >= 16 && ctlr->type == i82576) { - i82563replenish(ctlr); - rxcnt = 0; - } - } - ctlr->rdh = rdh; - if(icr & Rxdmt0 || ctlr->type == i82576) - 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) -{ - Ctlr *ctlr; - u32int r, rctl; - - ctlr = edev->ctlr; - - rctl = Dpf | Bsize2048 | Bam | RdtmsHALF; - if(ctlr->type == i82575 || ctlr->type == i82576){ - /* - * Setting Qenable in Rxdctl does not - * appear to stick unless Ren is on. - */ - csr32w(ctlr, Rctl, Ren|rctl); - r = csr32r(ctlr, Rxdctl); - r |= Qenable; - csr32w(ctlr, Rxdctl, r); - } - csr32w(ctlr, Rctl, rctl); - ctlr->rdba = mallocalign(Nrdesc*sizeof(Rdesc), 256, 0, 0); /* 256 was 128 */ - 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, Radv, 0); - - if(ctlr->type == i82573) - csr32w(ctlr, Ert, 1024/8); - if(ctlr->type == i82566 || ctlr->type == i82567) - csr32w(ctlr, Pbs, 16); - 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 = mallocalign(Ntdesc*sizeof(Tdesc), 256, 0, 0); /* 256 was 128 */ - 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 = csr32r(ctlr, Txdctl); - r &= ~(WthreshMASK|PthreshMASK); - r |= 4<<WthreshSHIFT | 4<<PthreshSHIFT; - if(ctlr->type == i82575 || ctlr->type == i82576) - r |= Qenable; - csr32w(ctlr, Txdctl, r); - - /* - * Don't enable checksum offload. In practice, it interferes with - * tftp booting on at least the 82575. - */ -// csr32w(ctlr, Rxcsum, Tuofl | Ipofl | ETHERHDRSIZE<<PcssSHIFT); - csr32w(ctlr, Rxcsum, 0); - 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); - if(ctlr->type == i82566 || ctlr->type == i82567) - r |= Phy_rst; - 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 -fcycle(Ctlr *, Flash *f) -{ - ushort s, i; - - s = f->reg[Fsts]; - if((s&Fvalid) == 0) - return -1; - f->reg[Fsts] |= Fcerr | Ael; - for(i = 0; i < 10; i++){ - if((s&Scip) == 0) - return 0; - delay(1); - s = f->reg[Fsts]; - } - return -1; -} - -static int -fread(Ctlr *c, Flash *f, int ladr) -{ - ushort s; - - delay(1); - if(fcycle(c, f) == -1) - return -1; - f->reg[Fsts] |= Fdone; - f->reg32[Faddr] = ladr; - - /* setup flash control register */ - s = f->reg[Fctl]; - s &= ~(0x1f << 8); - s |= (2-1) << 8; /* 2 bytes */ - s &= ~(2*Flcycle); /* read */ - f->reg[Fctl] = s | Fgo; - - while((f->reg[Fsts] & Fdone) == 0) - ; - if(f->reg[Fsts] & (Fcerr|Ael)) - return -1; - return f->reg32[Fdata] & 0xffff; -} - -static int -fload(Ctlr *c) -{ - ulong data, io, r, adr; - ushort sum; - Flash f; - Pcidev *p; - -// io = c->pcidev->mem[1].bar & ~0x0f; -// f.reg = vmap(io, c->pcidev->mem[1].size); -// if(f.reg == nil) -// return -1; - - p = c->pcidev; - io = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0); - if(io == 0){ - print("igbepcie: can't map flash @ 0x%8.8lux\n", p->mem[1].bar); - return -1; - } - f.reg = KADDR(io); - - f.reg32 = (ulong*)f.reg; - f.sz = f.reg32[Bfpr]; - r = f.sz & 0x1fff; - if(csr32r(c, Eec) & (1<<22)) - ++r; - r <<= 12; - - sum = 0; - for (adr = 0; adr < 0x40; adr++) { - data = fread(c, &f, r + adr*2); - if(data == -1) - break; - c->eeprom[adr] = data; - sum += data; - } -// vunmap(f.reg, c->pcidev->mem[1].size); - return sum; -} - -static int -i82563reset(Ctlr* ctlr) -{ - int i, r; - - detach(ctlr); - - if(ctlr->type == i82566 || ctlr->type == i82567) - r = fload(ctlr); - else - r = eeload(ctlr); - if (r != 0 && r != 0xBABA){ - print("%s: bad EEPROM checksum - 0x%4.4ux\n", - tname[ctlr->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)){ - if(p->ccrb != 0x02 || p->ccru != 0) - continue; -//print("i82563pci: did %4.4#x\n", p->did); - switch(p->did){ - case 0x1096: - case 0x10ba: - type = i82563; - break; - case 0x1049: /* mm */ - case 0x104a: /* dm */ - case 0x104b: /* dc */ - case 0x104d: /* mc */ - case 0x10bd: /* dm */ - case 0x294c: /* dc-2 */ - type = i82566; - break; - case 0x10cd: /* lf */ - case 0x10ce: /* v-2 */ - case 0x10de: /* lm-3 */ - case 0x10f5: /* lm-2 */ - type = i82567; - break; - case 0x10a4: - case 0x105e: - type = i82571; - break; - case 0x10b9: /* sic, 82572gi */ - type = i82572; - break; - case 0x108b: /* v */ - case 0x108c: /* e (iamt) */ - case 0x109a: /* l */ - type = i82573; - break; -// case 0x10d3: /* l */ -// type = i82574; /* never heard of it */ -// break; - case 0x10a7: /* 82575eb */ - type = i82575; - break; - case 0x10c9: /* 82576 copper */ - case 0x10e6: /* 82576 fiber */ - case 0x10e7: /* 82576 serdes */ - type = i82576; - 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, tname[ctlr->type]); - return -1; - } - */ - - return 0; -} diff --git a/sys/src/boot/pc/ether83815.c b/sys/src/boot/pc/ether83815.c deleted file mode 100644 index 4db3a5375..000000000 --- a/sys/src/boot/pc/ether83815.c +++ /dev/null @@ -1,1021 +0,0 @@ -/* - * National Semiconductor DP83815 - * - * Supports only internal PHY and has been tested on: - * Netgear FA311TX (using Netgear DS108 10/100 hub) - * SiS 900 within SiS 630 - * 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 0 -#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 { /* PCI vendor & device IDs */ - Nat83815 = (0x0020<<16)|0x100B, - SiS = 0x1039, - SiS900 = (0x0900<<16)|SiS, - SiS7016 = (0x7016<<16)|SiS, - - SiS630bridge = 0x0008, - - /* SiS 900 PCI revision codes */ - SiSrev630s = 0x81, - SiSrev630e = 0x82, - SiSrev630ea1 = 0x83, - - SiSeenodeaddr = 8, /* short addr of SiS eeprom mac addr */ - SiS630eenodeaddr = 9, /* likewise for the 630 */ - Nseenodeaddr = 6, /* " for NS eeprom */ - Nat83815avng = 0x403, - Nat83816avng = 0x505, /* 83816 acts like submodel of 83815 */ - /* using reg. 0x58 to disambiguate. */ -}; - -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; - - ulong version; /* silicon version; register 0x58h */ -} 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 ushort -eegetw(Ctlr *ctlr, int a) -{ - int d, i, w; - - eeidle(ctlr); - eeclk(ctlr, 0); - eeclk(ctlr, Eeclk); - d = 0x180 | a; - for(i=0x400; i; i>>=1){ - if(d & i) - csr32w(ctlr, Rmear, Eesel|Eedi); - else - csr32w(ctlr, Rmear, Eesel); - eeclk(ctlr, Eeclk); - eeclk(ctlr, 0); - microdelay(2); - } - 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 int -softreset(Ctlr* ctlr, int resetphys) -{ - int i, w; - - /* - * Soft-reset the controller - */ - csr32w(ctlr, Rcr, Rst); - for(i=0;; i++){ - if(i > 100){ - print("ns83815: soft reset did not complete\n"); - return -1; - } - 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); - ctlr->version = csr32r(ctlr, Rsrr); - if(resetphys){ - /* - * Soft-reset the PHY - */ - csr32w(ctlr, Rbmcr, Reset); - for(i=0;; i++){ - if(i > 100){ - print("ns83815: PHY soft reset time out\n"); - return -1; - } - 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 - */ - 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"); - return -1; - } - if((w = csr16r(ctlr, Rbmsr)) & Ancomp) - break; - delay(1); - } - debug("%d ms\n", i); - w &= 0xFFFF; - debug("bmsr: %4.4ux\n", w); - USED(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)); - 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 int -is630(ulong id, Pcidev *p) -{ - if(id == SiS900) - switch (p->rid) { - case SiSrev630s: - case SiSrev630e: - case SiSrev630ea1: - return 1; - } - return 0; -} - -enum { - MagicReg = 0x48, - MagicRegSz = 1, - Magicrden = 0x40, /* read enable, apparently */ - Paddr= 0x70, /* address port */ - Pdata= 0x71, /* data port */ - Pcinetctlr = 2, -}; - -/* rcmos() originally from LANL's SiS 900 driver's rcmos() */ -static int -sisrdcmos(Ctlr *ctlr) -{ - int i; - unsigned reg; - ulong port; - Pcidev *p; - - debug("ns83815: SiS 630 rev. %ux reading mac address from cmos\n", ctlr->pcidev->rid); - p = pcimatch(nil, SiS, SiS630bridge); - if(p == nil) { - print("ns83815: no SiS 630 rev. %ux bridge for mac addr\n", - ctlr->pcidev->rid); - return 0; - } - port = p->mem[0].bar & ~0x01; - debug("ns83815: SiS 630 rev. %ux reading mac addr from cmos via bridge at port 0x%lux\n", ctlr->pcidev->rid, port); - - reg = pcicfgr8(p, MagicReg); - pcicfgw8(p, MagicReg, reg|Magicrden); - - for (i = 0; i < Eaddrlen; i++) { - outb(port+Paddr, SiS630eenodeaddr + i); - ctlr->sromea[i] = inb(port+Pdata); - } - - pcicfgw8(p, MagicReg, reg & ~Magicrden); - return 1; -} - -/* - * If this is a SiS 630E chipset with an embedded SiS 900 controller, - * we have to read the MAC address from the APC CMOS RAM. - sez freebsd. - * However, CMOS *is* NVRAM normally. See devrtc.c:440, memory.c:88. - */ -static void -sissrom(Ctlr *ctlr) -{ - union { - uchar eaddr[Eaddrlen]; - ushort alignment; - } ee; - int i, off = SiSeenodeaddr, cnt = sizeof ee.eaddr / sizeof(short); - ushort *shp = (ushort *)ee.eaddr; - - if(!is630(ctlr->id, ctlr->pcidev) || !sisrdcmos(ctlr)) { - for (i = 0; i < cnt; i++) - *shp++ = eegetw(ctlr, off++); - memmove(ctlr->sromea, ee.eaddr, sizeof ctlr->sromea); - } -} - -ushort -søkrisee(Ctlr *c, int n) -{ - int i; - uint cmd; - ushort r; - - csr32w(c, Rmear, Eesel); - - cmd = 0x180|n; - for(i = 10; i >= 0; i--){ - n = 1<<3; - if(cmd&(1<<i)) - n |= 1; - csr32w(c, Rmear, n); - csr32r(c, Rmear); - csr32w(c, Rmear, n|4); - csr32r(c, Rmear); - } - - csr32w(c, Rmear, 1<<3); - csr32r(c, Rmear); - - r = 0; - for(i = 0; i < 16; i++){ - csr32w(c, Rmear, 1<<3 | 1<<2); - csr32r(c, Rmear); - if(csr32r(c, Rmear) & 2) - r |= 1<<i; - csr32w(c, Rmear, 1<<3); - csr32r(c, Rmear); - } - - csr32w(c, Rmear, 1<<3); - csr32w(c, Rmear, 0); - - return r; -} - -static void -nsnormalea(Ctlr *ctlr) -{ - int i, j; - - /* - * the MAC address is reversed, straddling word boundaries - */ - j = Nseenodeaddr*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 -ns403ea(Ctlr *ctlr) -{ - int i; - ushort s, t; - - s = ctlr->srom[6]; - for(i = 0; i < 3; i++){ - t = ctlr->srom[i+7]; - ctlr->sromea[i*2] = t<<1 | s>>15; - ctlr->sromea[i*2+1] = t>>7; - s = t; - } -} - -static void -nssrom(Ctlr* ctlr) -{ - int i, ns403; - ulong vers; - ushort (*ee)(Ctlr*, int); - - vers = ctlr->version; - ns403 = vers == Nat83815avng || vers == Nat83816avng; - if(ns403){ - ee = søkrisee; - print("soekris %lx\n", vers); - }else - ee = eegetw; - - for(i = 0; i < nelem(ctlr->srom); i++) - ctlr->srom[i] = ee(ctlr, i); - - if(ns403) - ns403ea(ctlr); - else - nsnormalea(ctlr); -} - -static void -srom(Ctlr* ctlr) -{ - memset(ctlr->sromea, 0, sizeof(ctlr->sromea)); - switch (ctlr->id) { - case SiS900: - case SiS7016: - sissrom(ctlr); - break; - case Nat83815: - nssrom(ctlr); - break; - default: - print("ns83815: srom: unknown id 0x%ux\n", ctlr->id); - break; - } -} - -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: - case SiS900: - 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; - - if(softreset(ctlr, 0) == -1){ - free(ctlr); - continue; - } - srom(ctlr); - - if(ctlrhead != nil) - ctlrtail->next = ctlr; - else - ctlrhead = ctlr; - ctlrtail = ctlr; - } -} - -int -ether83815reset(Ether* ether) -{ - Ctlr *ctlr; - int i, x; - ulong ctladdr; - 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); - ctladdr = (ctlr->id == Nat83815? i: i<<15); - csr32w(ctlr, Rrfcr, ctladdr); - 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; -} diff --git a/sys/src/boot/pc/ether8390.c b/sys/src/boot/pc/ether8390.c deleted file mode 100644 index dcaf838bc..000000000 --- a/sys/src/boot/pc/ether8390.c +++ /dev/null @@ -1,715 +0,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", 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; -} diff --git a/sys/src/boot/pc/ether8390.h b/sys/src/boot/pc/ether8390.h deleted file mode 100644 index 1c4641109..000000000 --- a/sys/src/boot/pc/ether8390.h +++ /dev/null @@ -1,71 +0,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; - } -} diff --git a/sys/src/boot/pc/etherdp83820.c b/sys/src/boot/pc/etherdp83820.c deleted file mode 100644 index a7b2c7704..000000000 --- a/sys/src/boot/pc/etherdp83820.c +++ /dev/null @@ -1,1222 +0,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 { - u32int link; /* Link to the next descriptor */ - u32int bufptr; /* pointer to data Buffer */ - int cmdsts; /* Command/Status */ - int extsts; /* optional Extended Status */ - - Block* bp; /* Block containing bufptr */ - u32int 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; -} diff --git a/sys/src/boot/pc/etherec2t.c b/sys/src/boot/pc/etherec2t.c deleted file mode 100644 index 71487ec19..000000000 --- a/sys/src/boot/pc/etherec2t.c +++ /dev/null @@ -1,160 +0,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 */ - { "PCM100" }, /* EtherFast PCM100 Card */ - { "EN2216" }, /* Accton EtherPair-PCMCIA */ - { "FA410TX" }, /* Netgear FA410TX */ - { "FA411" }, /* Netgear FA411 PCMCIA */ - { "Network Everywhere" }, /* Linksys NP10T 10BaseT Card */ - { "10/100 Port Attached" }, /* SMC 8040TX */ - { "8041TX-10/100-PC-Card-V2" }, /* SMC 8041TX */ - { "SMC8022" }, /* SMC 8022 / EZCard-10-PCMCIA */ - { 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; -} diff --git a/sys/src/boot/pc/etherelnk3.c b/sys/src/boot/pc/etherelnk3.c deleted file mode 100644 index ab5afc04b..000000000 --- a/sys/src/boot/pc/etherelnk3.c +++ /dev/null @@ -1,1931 +0,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, - EepromReadOffRegister = 0x00B0, - EepromRead8bRegister = 0x0230, - 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, - - 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 = 16, - Ndn = 8, -}; - -/* - * 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 Ctlr Ctlr; -struct Ctlr { - int port; - Pcidev* pcidev; - int irq; - Ctlr* next; - int active; - int did; - - 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 eepromcmd; /* EEPROM read command */ - int rxstatus9; /* old-style RxStatus register */ - int rxearly; /* RxEarlyThreshold */ - int ts; /* threshold shift */ - int upenabled; - int dnenabled; - - ulong cbfnpa; /* CardBus functions */ - ulong* cbfn; -}; - -static Ctlr* ctlrhead; -static Ctlr* ctlrtail; - -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 -intrackcb(ulong *cbfn) -{ - cbfn[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 this is a CardBus card, acknowledge any interrupts. - */ - if(ctlr->cbfn != nil) - intrackcb(ctlr->cbfn); - - /* - * 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", ether->ctlrno, status); - - COMMAND(port, AcknowledgeInterrupt, interruptLatch); - if(ctlr->cbfn != nil) - intrackcb(ctlr->cbfn); - - }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) -{ - while(STATUS(port) & commandInProgress) - ; - COMMAND(port, RxReset, 0); - while(STATUS(port) & commandInProgress) - ; -} - -static Ctlr* -tcmadapter(int port, int irq, Pcidev* pcidev) -{ - Ctlr *ctlr; - - ctlr = malloc(sizeof(Ctlr)); - ctlr->port = port; - ctlr->irq = irq; - ctlr->pcidev = pcidev; - ctlr->eepromcmd = EepromReadRegister; - - if(ctlrhead != nil) - ctlrtail->next = ctlr; - else - ctlrhead = ctlr; - ctlrtail = ctlr; - - return ctlr; -} - -/* - * 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, nil); - } -} - -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, nil); - } -} - -static void -tcm59Xpci(void) -{ - Pcidev *p; - Ctlr *ctlr; - int irq, port; - - p = nil; - while(p = pcimatch(p, 0x10B7, 0)){ - if(p->ccrb != 0x02 || p->ccru != 0) - continue; - /* - * 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; - - txrxreset(port); - COMMAND(port, AcknowledgeInterrupt, 0xFF); - - ctlr = tcmadapter(port, irq, p); - switch(p->did){ - default: - break; - case 0x5157: - ctlr->eepromcmd = EepromRead8bRegister; - ctlr->cbfnpa = p->mem[2].bar&~0x0F; - ctlr->cbfn = KADDR(ctlr->cbfnpa); - break; - case 0x6056: - ctlr->eepromcmd = EepromReadOffRegister; - ctlr->cbfnpa = p->mem[2].bar&~0x0F; - ctlr->cbfn = KADDR(ctlr->cbfnpa); - break; - } - pcisetbme(p); - } -} - -static char* tcmpcmcia[] = { - "3C589", /* 3COM 589[ABCD] */ - "3C562", /* 3COM 562 */ - "589E", /* 3COM Megahertz 589E */ - nil, -}; - -static Ctlr* -tcm5XXpcmcia(Ether* ether) -{ - int i; - Ctlr *ctlr; - - if(ether->type == nil) - return nil; - - for(i = 0; tcmpcmcia[i] != nil; i++){ - if(cistrcmp(ether->type, tcmpcmcia[i])) - continue; - ctlr = tcmadapter(ether->port, ether->irq, nil); - ctlr->active = 1; - return ctlr; - } - - return nil; -} - -static void -setxcvr(Ctlr* ctlr, int xcvr) -{ - int port, x; - - port = ctlr->port; - if(ctlr->rxstatus9){ - 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 int -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); - - return i; - } - return 24; -} - -#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(Ctlr* ctlr) -{ - int media, port, x; - - /* - * 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. - */ - port = ctlr->port; - if(ctlr->rxstatus9){ - 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(ctlr, xcvr100BaseTX); - - 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(ctlr, xcvr10BaseT); - - 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(Ctlr* ctlr, int offset) -{ - int port; - - port = ctlr->port; - - COMMAND(port, SelectRegisterWindow, Wsetup); - while(EEPROMBUSY(port)) - ; - EEPROMCMD(port, ctlr->eepromcmd, offset); - while(EEPROMBUSY(port)) - ; - return EEPROMDATA(port); -} - -static void -resetctlr(Ctlr *ctlr) -{ - int port, x; - - port = ctlr->port; - - txrxreset(port); - x = ins(port+ResetOp905B); - XCVRDEBUG("905[BC] reset ops 0x%uX\n", x); - x &= ~0x4010; - if(ctlr->did == 0x5157){ - x |= 0x0010; /* Invert LED */ - outs(port+ResetOp905B, x); - } - if(ctlr->did == 0x6056){ - x |= 0x4000; - outs(port+ResetOp905B, x); - - COMMAND(port, SelectRegisterWindow, Wsetup); - outs(port, 0x0800); - } -} - -int -elnk3reset(Ether* ether) -{ - char *p; - Ctlr *ctlr; - uchar ea[Eaddrlen]; - static int scandone; - int anar, anlpar, i, j, phyaddr, phystat, port, timeo, x; - - /* - * Scan for adapter on PCI, EISA and finally - * using the little ISA configuration dance. - */ - if(scandone == 0){ - tcm59Xpci(); - tcm5XXeisa(); - tcm509isa(); - 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 && (ctlr = tcm5XXpcmcia(ether)) == 0) - return -1; - - ether->ctlr = ctlr; - port = ctlr->port; - ether->port = port; - ether->irq = ctlr->irq; - if(ctlr->pcidev != nil) - ether->tbdf = ctlr->pcidev->tbdf; - else - ether->tbdf = BUSUNKNOWN; - - /* - * Read the DeviceID from the EEPROM, it's at offset 0x03, - * and do something depending on capabilities. - */ - switch(ctlr->did = eepromdata(ctlr, 0x03)){ - case 0x5157: /* 3C575 Cyclone */ - case 0x6056: - /*FALLTHROUGH*/ - case 0x4500: /* 3C450 HomePNA Tornado */ - case 0x7646: /* 3CSOHO100-TX */ - case 0x9055: /* 3C905B-TX */ - case 0x9200: /* 3C905C-TX */ - case 0x9201: /* 3C920 */ - case 0x9805: /* 3C9805: 3C980-TX Python-T 10/100baseTX */ - /*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; - ctlr->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 */ - ctlr->busmaster = 1; - vortex: - COMMAND(port, SelectRegisterWindow, Wfifo); - ctlr->xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask); - ctlr->rxearly = 8188; - ctlr->rxstatus9 = 0; - break; - buggery: - default: - ctlr->busmaster = 0; - COMMAND(port, SelectRegisterWindow, Wsetup); - x = ins(port+AddressConfig); - ctlr->xcvr = ((x & xcvrMask9)>>14)<<20; - if(x & autoSelect9) - ctlr->xcvr |= autoSelect; - ctlr->rxearly = 2044; - ctlr->rxstatus9 = 1; - break; - } - if(ctlr->rxearly >= 2048) - ctlr->ts = 2; - - /* - * 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(ctlr, 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", ctlr->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) - ctlr->xcvr = media[j].xcvr; - } - - /* - * forgive me, but i am weak - */ - switch(ctlr->did){ - default: - if(ctlr->xcvr & autoSelect) - ctlr->xcvr = autoselect(ctlr); - break; - case 0x5157: - case 0x6056: - case 0x4500: - case 0x7646: - case 0x9055: - case 0x9200: - case 0x9201: - case 0x9805: - ctlr->xcvr = xcvrMii; - resetctlr(ctlr); - break; - } - XCVRDEBUG("xcvr selected: %uX, did 0x%uX\n", ctlr->xcvr, ctlr->did); - - switch(ctlr->xcvr){ - case xcvrMii: - /* - * Quick hack. - */ - if(ctlr->did == 0x5157) - phyaddr = 0; - else if(ctlr->did == 0x6056) - phyaddr = scanphy(port); - else - phyaddr = 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 */ - //ether->mbps = 100; - setfullduplex(port); - } - else if(anar & 0x0200){ /* 100BASE-T4 */ - /* nothing to do */ - } - else if(anar & 0x0080){ /* 100BASE-TX */ - //ether->mbps = 100; - } - 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); - - //if(x & dataRate100) - // ether->mbps = 100; - 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((ctlr->did & 0xFF00) == 0x5900) - ctlr->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(ctlr->busmaster == 2) - x = port+TxStatus905; - else - x = port+TxStatus; - while(inb(x)) - outb(x, 0); - - /* - * Clear out the - * adapter statistics, clear the statistics logged into ctlr. - */ - ilock(&ctlr->wlock); - statistics(ether); - memset(ctlr->stats, 0, sizeof(ctlr->stats)); - - //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(ctlr, 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, ctlr->rxearly>>ctlr->ts); - - iunlock(&ctlr->wlock); - - /* - * Linkage to the generic ethernet driver. - */ - ether->attach = attach; - ether->transmit = transmit; - ether->interrupt = interrupt; - - return 0; -} diff --git a/sys/src/boot/pc/etherelnk3x.c b/sys/src/boot/pc/etherelnk3x.c deleted file mode 100644 index 138179646..000000000 --- a/sys/src/boot/pc/etherelnk3x.c +++ /dev/null @@ -1,1074 +0,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", 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; -} diff --git a/sys/src/boot/pc/etherif.h b/sys/src/boot/pc/etherif.h deleted file mode 100644 index f4a6482c4..000000000 --- a/sys/src/boot/pc/etherif.h +++ /dev/null @@ -1,47 +0,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) diff --git a/sys/src/boot/pc/etherigbe.c b/sys/src/boot/pc/etherigbe.c deleted file mode 100644 index 739454b84..000000000 --- a/sys/src/boot/pc/etherigbe.c +++ /dev/null @@ -1,1772 +0,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, - i82544eif = (0x1009<<16)|0x8086, - i82544gc = (0x100d<<16)|0x8086, - i82540em = (0x100E<<16)|0x8086, - i82540eplp = (0x101E<<16)|0x8086, - i82545em = (0x100F<<16)|0x8086, - i82545gmc = (0x1026<<16)|0x8086, - i82547ei = (0x1019<<16)|0x8086, - i82547gi = (0x1075<<16)|0x8086, - i82541ei = (0x1013<<16)|0x8086, - i82541gi = (0x1076<<16)|0x8086, - i82541gi2 = (0x1077<<16)|0x8086, - i82541pi = (0x107c<<16)|0x8086, - i82546gb = (0x1079<<16)|0x8086, - i82546eb = (0x1010<<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 i82545em: - case i82545gmc: - 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 i82544eif: - case i82544gc: - case i82540em: - case i82540eplp: - case i82541ei: - case i82541gi: - case i82541gi2: - case i82541pi: - case i82546gb: - case i82546eb: - case i82547gi: - case i82547ei: - case i82545em: - case i82545gmc: - 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 i82545em: - case i82545gmc: - case i82546gb: - case i82546eb: - case i82541gi: - case i82541gi2: - case i82541pi: - 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 i82544eif: - case i82544gc: - case i82540em: - case i82540eplp: - case i82547ei: - case i82547gi: - case i82541gi: - case i82541gi2: - case i82541pi: - case i82545em: - case i82545gmc: - 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 i82545em: - case i82545gmc: - 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 i82541ei: - case i82541gi: - case i82541gi2: - case i82541pi: - case i82545em: - case i82545gmc: - case i82546gb: - case i82546eb: - case i82547ei: - case i82547gi: - 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 i82545em: - case i82545gmc: - 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 i82544eif: - case i82544gc: - case i82547ei: - case i82547gi: - case i82540em: - case i82540eplp: - case i82541ei: - case i82541gi: - case i82541gi2: - case i82541pi: - case i82545em: - case i82545gmc: - 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; -} diff --git a/sys/src/boot/pc/ethermii.c b/sys/src/boot/pc/ethermii.c deleted file mode 100644 index 160e4fe0f..000000000 --- a/sys/src/boot/pc/ethermii.c +++ /dev/null @@ -1,224 +0,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; -} diff --git a/sys/src/boot/pc/ethermii.h b/sys/src/boot/pc/ethermii.h deleted file mode 100644 index 80c4ed06d..000000000 --- a/sys/src/boot/pc/ethermii.h +++ /dev/null @@ -1,116 +0,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*); diff --git a/sys/src/boot/pc/etherrhine.c b/sys/src/boot/pc/etherrhine.c deleted file mode 100644 index 1f88111aa..000000000 --- a/sys/src/boot/pc/etherrhine.c +++ /dev/null @@ -1,679 +0,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" - -#define iprint print - -#include "etherif.h" -#include "ethermii.h" - -enum { - Ntxd = 16, - Nrxd = 32, - Nwait = 50, -}; - -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, - Mcfilt0 = 0x10, /* Multicast Filter 0 */ - Mcfilt1 = 0x14, /* Multicast Filter 1 */ - 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, - Stickhw = 0x83, /* Sticky Hardware Control */ - MiscIsr = 0x84, - MiscImr = 0x86, - WolCrSet = 0xA0, - WolCfgSet = 0xA1, - WolCgSet = 0xA3, - Wolcrclr = 0xA4, - PwrCfgClr = 0xA5, - Wolcgclr = 0xA7, - Pwrcsrclr = 0xAC, -}; - -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 s; - uint i; - - 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 txused, n; - uint i; - 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 txused; - uint i; - 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 n, size; - uint i; - - 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); - } else - print("etherrhine: ether%d discarding input pkt;" - " buffer ring too small\n", - edev->ctlrno); - - 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, revid; - - /* - * Reset power management registers. - */ - revid = pcicfgr8(ctlr->pci, PciRID); - if(revid >= 0x40){ - /* Set power state D0. */ - csr8w(ctlr, Stickhw, csr8r(ctlr, Stickhw) & 0xFC); - - /* Disable force PME-enable. */ - csr8w(ctlr, Wolcgclr, 0x80); - - /* Clear WOL config and status bits. */ - csr8w(ctlr, Wolcrclr, 0xFF); - csr8w(ctlr, Pwrcsrclr, 0xFF); - } - - /* - * 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); - csr32w(ctlr, Mcfilt0, ~0UL); /* accept all multicast */ - csr32w(ctlr, Mcfilt1, ~0UL); - - 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] && 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); -} diff --git a/sys/src/boot/pc/fat.c b/sys/src/boot/pc/fat.c new file mode 100644 index 000000000..624b6f149 --- /dev/null +++ b/sys/src/boot/pc/fat.c @@ -0,0 +1,253 @@ +#include <u.h> +#include "fns.h" + +enum { + Sectsz = 0x200, + Dirsz = 0x20, + Maxpath = 64, +}; + +typedef struct Extend Extend; +typedef struct Dir Dir; +typedef struct Pbs Pbs; + +struct Extend +{ + int drive; + ulong lba; + ulong len; + uchar *rp; + uchar *ep; + uchar buf[Sectsz]; +}; + +struct Dir +{ + char name[11]; + uchar attr; + uchar reserved; + uchar ctime; + uchar ctime[2]; + uchar cdate[2]; + uchar adate[2]; + uchar starthi[2]; + uchar mtime[2]; + uchar mdate[2]; + uchar startlo[2]; + uchar len[4]; +}; + +struct Pbs +{ + uchar magic[3]; + uchar version[8]; + uchar sectsize[2]; + uchar clustsize; + uchar nreserv[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 type[8]; +}; + +int readsect(ulong drive, ulong lba, void *buf); + +int +read(void *f, void *data, int len) +{ + Extend *ex = f; + + if(ex->len > 0 && ex->rp >= ex->ep) + if(readsect(ex->drive, ex->lba++, ex->rp = ex->buf)) + return -1; + if(ex->len < len) + len = ex->len; + if(len > (ex->ep - ex->rp)) + len = ex->ep - ex->rp; + memmove(data, ex->rp, len); + ex->rp += len; + ex->len -= len; + return len; +} + +void +close(void *f) +{ + Extend *ex = f; + + ex->drive = 0; + ex->lba = 0; + ex->len = 0; + ex->rp = ex->ep = ex->buf + Sectsz; +} + +static ulong +rootlba(Extend *fat) +{ + ulong lba; + Pbs *p = (Pbs*)fat->buf; + + lba = fat->lba; + lba += *((ushort*)p->nreserv); + lba += *((ushort*)p->fatsize) * p->nfats; + return lba; +} + +static ulong +dirlba(Extend *fat, Dir *d) +{ + ulong clust; + ulong dirs; + ulong lba; + Pbs *p = (Pbs*)fat->buf; + + lba = rootlba(fat); + dirs = *((ushort*)p->rootsize); + lba += (dirs * Dirsz + Sectsz-1) / Sectsz; + clust = *((ushort*)d->starthi)<<16 | *((ushort*)d->startlo); + lba += (clust - 2) * p->clustsize; + return lba; +} + +static int +dirname(Dir *d, char buf[Maxpath]) +{ + char c, *x; + + if(d->attr == 0x0F || *d->name <= 0) + return -1; + memmove(buf, d->name, 8); + x = buf+8; + while(x > buf && x[-1] == ' ') + x--; + if(d->name[8] != ' '){ + *x++ = '.'; + memmove(x, d->name+8, 3); + x += 3; + } + while(x > buf && x[-1] == ' ') + x--; + *x = 0; + x = buf; + while(c = *x){ + if(c >= 'A' && c <= 'Z'){ + c -= 'A'; + c += 'a'; + } + *x++ = c; + } + return x - buf; +} + +static int +fatwalk(Extend *ex, Extend *fat, char *path) +{ + char name[Maxpath], *end; + Pbs *pbs = (Pbs*)fat->buf; + int i, j; + Dir d; + + close(ex); + ex->drive = fat->drive; + ex->lba = rootlba(fat); + ex->len = *((ushort*)pbs->rootsize) * Dirsz; + for(;;){ + if(readn(ex, &d, Dirsz) != Dirsz) + break; + if((i = dirname(&d, name)) <= 0) + continue; + while(*path == '/') + path++; + if((end = strchr(path, '/')) == 0) + end = path + strlen(path); + j = end - path; + if(i == j && memcmp(name, path, j) == 0){ + ex->rp = ex->ep; + ex->lba = dirlba(fat, &d); + ex->len = *((ulong*)d.len); + if(*end == 0) + return 0; + else if(d.attr & 0x10){ + ex->len = pbs->clustsize * Sectsz; + path = end; + continue; + } + break; + } + } + close(ex); + return -1; +} + +static int +findfat(Extend *fat, int drive) +{ + struct { + uchar status; + uchar bchs[3]; + uchar typ; + uchar echs[3]; + uchar lba[4]; + uchar len[4]; + } *p; + int i; + + if(readsect(drive, 0, fat->buf)) + return -1; + if(fat->buf[0x1fe] != 0x55 || fat->buf[0x1ff] != 0xAA) + return -1; + p = (void*)&fat->buf[0x1be]; + for(i=0; i<4; i++){ + if(p[i].status != 0x80) + continue; + close(fat); + fat->drive = drive; + fat->lba = *((ulong*)p[i].lba); + if(readsect(drive, fat->lba, fat->buf)) + continue; + return 0; + } + return -1; +} + +void +start(void *sp) +{ + char path[Maxpath], *kern; + int drive; + Extend fat, ex; + void *f; + + /* drive passed in DL */ + drive = ((ushort*)sp)[5] & 0xFF; + + if(findfat(&fat, drive)){ + print("no fat\r\n"); + halt(); + } + if(fatwalk(f = &ex, &fat, "plan9.ini")){ + print("no config\r\n"); + f = 0; + } + for(;;){ + kern = configure(f, path); f = 0; + if(fatwalk(&ex, &fat, kern)){ + print("not found\r\n"); + continue; + } + print(bootkern(&ex)); + print(crnl); + } +} + diff --git a/sys/src/boot/pc/fns.h b/sys/src/boot/pc/fns.h index 90f36cb38..cd08c92e3 100644 --- a/sys/src/boot/pc/fns.h +++ b/sys/src/boot/pc/fns.h @@ -1,177 +1,30 @@ -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*, int); -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 prcpuid(void); -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); +/* handy strings in l.s */ +extern char origin[]; +extern char hex[]; +extern char crnl[]; +extern char bootname[]; + +/* l.s */ +void start(void *sp); +int getc(void); +int gotc(void); +void putc(int c); +void a20(void); +void halt(void); +void jump(void *pc); + +int read(void *f, void *data, int len); +int readn(void *f, void *data, int len); +void close(void *f); + +void memset(void *p, int v, int n); +void memmove(void *dst, void *src, int n); +int memcmp(void *src, void *dst, int n); +int strlen(char *s); +char *strchr(char *s, int c); +char *strrchr(char *s, int c); +void print(char *s); + +char *configure(void *f, char *path); +char *bootkern(void *f); -#define malloc(n) ialloc(n, 0) -#define mallocz(n, c) ialloc(n, 0) -#define mallocalign(n, a, o, s) ialloc((n), (a)) -#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); diff --git a/sys/src/boot/pc/fs.c b/sys/src/boot/pc/fs.c deleted file mode 100644 index 24b33c09e..000000000 --- a/sys/src/boot/pc/fs.c +++ /dev/null @@ -1,94 +0,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); -} diff --git a/sys/src/boot/pc/fs.h b/sys/src/boot/pc/fs.h deleted file mode 100644 index 1b53e929a..000000000 --- a/sys/src/boot/pc/fs.h +++ /dev/null @@ -1,36 +0,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) diff --git a/sys/src/boot/pc/ilock.c b/sys/src/boot/pc/ilock.c deleted file mode 100644 index 977b9ad24..000000000 --- a/sys/src/boot/pc/ilock.c +++ /dev/null @@ -1,24 +0,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); -} diff --git a/sys/src/boot/pc/inflate.c b/sys/src/boot/pc/inflate.c deleted file mode 100644 index 262511a0f..000000000 --- a/sys/src/boot/pc/inflate.c +++ /dev/null @@ -1,199 +0,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 *) -{ -} diff --git a/sys/src/boot/pc/io.h b/sys/src/boot/pc/io.h deleted file mode 100644 index 6e7564f4c..000000000 --- a/sys/src/boot/pc/io.h +++ /dev/null @@ -1,317 +0,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 */ -}; diff --git a/sys/src/boot/pc/ip.h b/sys/src/boot/pc/ip.h deleted file mode 100644 index 6dfb7cdd9..000000000 --- a/sys/src/boot/pc/ip.h +++ /dev/null @@ -1,100 +0,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*); diff --git a/sys/src/boot/pc/iso.c b/sys/src/boot/pc/iso.c new file mode 100644 index 000000000..9f0d010aa --- /dev/null +++ b/sys/src/boot/pc/iso.c @@ -0,0 +1,164 @@ +#include <u.h> +#include "fns.h" + +enum { + Sectsz = 0x800, + Maxpath = 256, + Dirsz = 33, +}; + +typedef struct Extend Extend; +typedef struct Dir Dir; + +struct Extend +{ + int drive; + ulong lba; + ulong len; + uchar *rp; + uchar *ep; + uchar buf[Sectsz]; +}; + +struct Dir +{ + uchar dirlen; + uchar extlen; + + uchar lba[8]; + uchar len[8]; + + uchar date[7]; + + uchar flags[3]; + + uchar seq[4]; + + uchar namelen; +}; + +int readsect(ulong drive, ulong lba, void *buf); + +int +read(void *f, void *data, int len) +{ + Extend *ex = f; + + if(ex->len > 0 && ex->rp >= ex->ep) + if(readsect(ex->drive, ex->lba++, ex->rp = ex->buf)) + return -1; + if(ex->len < len) + len = ex->len; + if(len > (ex->ep - ex->rp)) + len = ex->ep - ex->rp; + memmove(data, ex->rp, len); + ex->rp += len; + ex->len -= len; + return len; +} + +void +close(void *f) +{ + Extend *ex = f; + + ex->drive = 0; + ex->lba = 0; + ex->len = 0; + ex->rp = ex->ep = ex->buf + Sectsz; +} + +static int +isowalk(Extend *ex, int drive, char *path) +{ + char name[Maxpath], pad, *end; + int i; + Dir d; + + close(ex); + ex->drive = drive; + + /* find pvd */ + for(i=0x10; i<0x1000; i++){ + if(readsect(drive, i, ex->buf)) + return -1; + if(*ex->buf == 1) + break; + } + ex->lba = *((ulong*)(ex->buf + 156 + 2)); + ex->len = *((ulong*)(ex->buf + 156 + 10)); + + for(;;){ + if(readn(ex, &d, Dirsz) != Dirsz) + break; + if(d.dirlen == 0) + break; + if(readn(ex, name, d.namelen) != d.namelen) + break; + i = d.dirlen - (Dirsz + d.namelen); + while(i-- > 0) + read(ex, &pad, 1); + name[d.namelen] = 0; + while(*path == '/') + path++; + if((end = strchr(path, '/')) == 0) + end = path + strlen(path); + i = end - path; + if(d.namelen == i && memcmp(name, path, i) == 0){ + ex->rp = ex->ep; + ex->lba = *((ulong*)d.lba); + ex->len = *((ulong*)d.len); + if(*end == 0) + return 0; + else if(d.flags[0] & 2){ + path = end; + continue; + } + break; + } + } + close(ex); + return -1; +} + +void +start(void *sp) +{ + char path[Maxpath], *kern; + int drive; + Extend ex; + void *f; + + /* drive passed in DL */ + drive = ((ushort*)sp)[5] & 0xFF; + + /* + * load full bootblock as only the frist 2K get + * loaded from bios. the code is specially arranged + * to have all the important routines in the first + * 2K of the 9bootiso image. (strings have been + * placed in l.s to make sure they will be < 2K) + */ + if(isowalk(&ex, drive, bootname)){ + print(bootname); + putc('?'); + halt(); + } + readn(&ex, origin, ex.len); + close(&ex); + + if(isowalk(f = &ex, drive, "plan9.ini")){ + print("no config\r\n"); + f = 0; + } + for(;;){ + kern = configure(f, path); f = 0; + if(isowalk(&ex, drive, kern)){ + print("not found\r\n"); + continue; + } + print(bootkern(&ex)); + print(crnl); + } +} + diff --git a/sys/src/boot/pc/kbd.c b/sys/src/boot/pc/kbd.c deleted file mode 100644 index 898f1578c..000000000 --- a/sys/src/boot/pc/kbd.c +++ /dev/null @@ -1,516 +0,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; -static int nokbd = 1; - -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; - - if(nokbd) - return; - - *((ushort*)KADDR(0x472)) = 0x1234; /* BIOS warm-boot flag */ - - /* - * newer reset the machine command - */ - outready(); - outb(Cmd, 0xFE); - 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 = "i8042: kbdinit failed\n"; - -static int -outbyte(int port, int c) -{ - outb(port, c); - if(outready() < 0) { - vga = 0; - print(initfailed); - return -1; - } - return 0; -} - -void -i8042init(void) -{ - int c, try; - - /* wait for a quiescent controller */ - try = 1000; - while(try-- > 0 && (c = inb(Status)) & (Outbusy | Inready)) { - if(c & Inready) - inb(Data); - delay(1); - } - if (try <= 0) { - vga = 0; - print(initfailed); - return; - } - - /* get current controller command byte */ - outb(Cmd, 0x20); - if(inready() < 0){ - print("i8042: 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) { - vga = 0; - print(initfailed); - return; - } - - nokbd = 0; - - /* disable mouse */ - if (outbyte(Cmd, 0x60) < 0 || outbyte(Data, ccc) < 0) - print("i8042: kbdinit mouse disable failed\n"); - - setvec(VectorKBD, i8042intr, 0); -} diff --git a/sys/src/boot/pc/kfs.h b/sys/src/boot/pc/kfs.h deleted file mode 100644 index a08ad37a9..000000000 --- a/sys/src/boot/pc/kfs.h +++ /dev/null @@ -1,57 +0,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*); - diff --git a/sys/src/boot/pc/kfsboot.c b/sys/src/boot/pc/kfsboot.c deleted file mode 100644 index a99d226da..000000000 --- a/sys/src/boot/pc/kfsboot.c +++ /dev/null @@ -1,256 +0,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; -} diff --git a/sys/src/boot/pc/l.s b/sys/src/boot/pc/l.s index 4216bfef7..23cb1539d 100644 --- a/sys/src/boot/pc/l.s +++ b/sys/src/boot/pc/l.s @@ -1,1088 +1,253 @@ #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) */ +#undef ORB -#ifdef PXE -#define PDB 0x90000 /* temporary page tables (24KB) */ -#else -#define PDB 0x08000 -#endif PXE - -/*#define VGA 1 */ -#define NoScreenBlank 1 -/*#define ResetDiscs 1*/ +#define DATA32SEL SELECTOR(1, SELGDT, 0) +#define EXEC32SEL SELECTOR(2, SELGDT, 0) +#define EXEC16SEL SELECTOR(3, SELGDT, 0) +#define SEGSS BYTE $0x36 +#define SEGES BYTE $0x26 +#define FARRET BYTE $0xCB 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 VGA -#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)) -#endif /* VGA */ -#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) + CLR(rCX) + MTSR(rCX, rSS) + OPSIZE; MOVL $origin(SB), SP + PUSHA + OPSIZE; ADSIZE; PUSHL SP + OPSIZE; ADSIZE; PUSHL CX + PUSHI(start(SB)) + +TEXT pmode32(SB), $0 + POPR(rDI) + SEGSS; LGDT(tgdtptr(SB)) + MFCR(rCR0, rCX) + ORB $1, CL + MTCR(rCX, rCR0) + PUSHI(EXEC32SEL) PUSHR(rDI) - PUSHR(rDX) + LWI(DATA32SEL, rCX) +_segret: + MTSR(rCX, rDS) + MTSR(rCX, rES) + MTSR(rCX, rSS) + FARRET + +TEXT rmode16(SB), $0 + POPL DI + OPSIZE; BYTE $0xEA + WORD $unreal(SB) + WORD $EXEC16SEL + +TEXT unreal(SB), $0 + MFCR(rCR0, rCX) + ANDB $0xfe, CL + MTCR(rCX, rCR0) + CLR(rCX) 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 + PUSHR(rDI) + JMP _segret +TEXT tgdt(SB), $0 /* null descriptor */ - LONG $0 - LONG $0 + LONG $0 + LONG $0 /* data segment descriptor for 4 gigabytes (PL 0) */ - LONG $(0xFFFF) - LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) + 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) + 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) + 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 +TEXT tgdtptr(SB), $0 + WORD $(4*8) + LONG $tgdt(SB) -_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 +TEXT jump(SB), $0 + MOVL 4(SP), AX + JMP *AX -/* - * input a long from a port - */ -TEXT inl(SB), $0 +TEXT halt(SB), $0 +_halt: + JMP _halt - MOVL p+0(FP), DX - XORL AX, AX - INL +TEXT getc(SB), $0 + CALL rmode16(SB) + STI + MOVB $0x00, AH + BIOSCALL(0x16) +_getcret: + CLI + CALL16(pmode32(SB)) + ANDL $0xFF, AX RET -/* - * output a byte - */ -TEXT outb(SB),$0 - - MOVL p+0(FP),DX - MOVL b+4(FP),AX - OUTB +TEXT gotc(SB), $0 + CALL rmode16(SB) + STI + MOVB $0x01, AH + BIOSCALL(0x16) + JNZ _getcret + CLR(rAX) + JMP _getcret + +TEXT putc(SB), $0 + MOVL 4(SP),AX + CALL rmode16(SB) + STI + MOVB $0x0E, AH + BIOSCALL(0x10) +_pret32: + CLI + CALL16(pmode32(SB)) + ANDL $0xFFFF, AX RET -/* - * output a short to a port - */ -TEXT outs(SB), $0 - MOVL p+0(FP), DX - MOVL s+4(FP), AX - OPSIZE; OUTL - RET +TEXT a20(SB), $0 + CALL rmode16(SB) + STI + LWI(0x2401, rAX) + BIOSCALL(0x15) + JMP _pret32 -/* - * output a long to a port - */ -TEXT outl(SB), $0 - MOVL p+0(FP), DX - MOVL s+4(FP), AX - OUTL - RET +#ifdef PXE -/* - * input a string of bytes from a port - */ -TEXT insb(SB),$0 +TEXT pxecallret(SB), $0 + ADDI(6, rSP) + JMP _pret32 - MOVL p+0(FP),DX - MOVL a+4(FP),DI - MOVL c+8(FP),CX - CLD; REP; INSB - RET +TEXT pxecall(SB), $0 + MOVL op+4(SP),AX + MOVL buf+8(SP),SI + CALL rmode16(SB) + CLI -/* - * 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 + CLR(rCX) + PUSHR(rCX) + PUSHR(rSI) -/* - * output a string of bytes to a port - */ -TEXT outsb(SB),$0 + /* opcode */ + PUSHR(rAX) - MOVL p+0(FP),DX - MOVL a+4(FP),SI - MOVL c+8(FP),CX - CLD; REP; OUTSB - RET + PUSHR(rCX) + PUSHI(pxecallret(SB)) + + /* get pxe env structure in ES:BX */ + LWI(0x5650, rAX) + BIOSCALL(0x1A) + JC _farret + + /* !PXE or PXEENV+ signature */ + SEGES; LXW(0, xBX, rAX) + CMPI((('!'<<0)|('P'<<8)), rAX) + JEQ _getentry + CMPI((('P'<<0)|('X'<<8)), rAX) + JNE _farret + + SEGES; LXW(0x2A, xBX, rAX) + SEGES; LXW(0x28, xBX, rBX) + MTSR(rAX, rES) -/* - * 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 +_getentry: + SEGES; LXW(0x12, xBX, rAX) + PUSHR(rAX) + SEGES; LXW(0x10, xBX, rAX) + PUSHR(rAX) -/* - * input a string of longs from a port - */ -TEXT insl(SB),$0 +_pxecall: + CLR(rAX) + CLR(rBX) + CLR(rCX) + CLR(rDX) + CLR(rDI) + CLR(rSI) +_farret: + FARRET - MOVL p+0(FP),DX - MOVL a+4(FP),DI - MOVL c+8(FP),CX - CLD; REP; INSL - RET +_pxeplus: + CMPI((('P'<<0)|('X'<<8)), rAX) + JNE _farret -/* - * output a string of longs to a port - */ -TEXT outsl(SB),$0 + PUSHR(rAX) + JMP _pxecall - MOVL p+0(FP),DX - MOVL a+4(FP),SI - MOVL c+8(FP),CX - CLD; REP; OUTSL - RET +#else /* PXE */ /* - * routines to load/read various system registers + * in: + * DL drive + * AX:BX lba32, + * 0000:SI buffer */ -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 readsect16(SB), $0 + PUSHA + CLR(rCX) -TEXT getcr2(SB),$0 /* fault address */ - MOVL CR2,AX - RET + PUSHR(rCX) /* qword lba */ + PUSHR(rCX) + PUSHR(rBX) + PUSHR(rAX) -TEXT getcr3(SB),$0 /* page directory base */ - MOVL CR3,AX - RET + PUSHR(rCX) /* dword buffer */ + PUSHR(rSI) -TEXT getcr4(SB), $0 /* CR4 - extensions */ - MOVL CR4, AX - RET + INC(rCX) + PUSHR(rCX) /* word # of sectors */ -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 + PUSHI(0x0010) /* byte reserved, byte packet size */ -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 */ + MW(rSP, rSI) + LWI(0x4200, rAX) + BIOSCALL(0x13) + JCC _readok + ADDI(0x10, rSP) + POPA + CLR(rAX) + DEC(rAX) RET - -TEXT wrmsr(SB), $0 - MOVL index+0(FP), CX - MOVL lo+4(FP), AX - MOVL hi+8(FP), DX - WRMSR +_readok: + ADDI(0x10, rSP) + POPA + CLR(rAX) 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 +TEXT readsect(SB), $0 + MOVL 4(SP), DX + MOVW 8(SP), AX + MOVW 10(SP), BX + MOVL 12(SP), SI + CALL rmode16(SB) STI - RET - -TEXT splhi(SB),$0 - PUSHFL - POPL AX + CALL16(readsect16(SB)) CLI + CALL16(pmode32(SB)) + ANDL $0xFFFF, AX 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 $'\r'; - BYTE $'\n'; - 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 +#ifdef ISO - /* switch to low stack */ - MOVL SP, AX - MOVL $0x7C00, SP - PUSHL AX +TEXT bootname(SB), $0 + BYTE $'9'; BYTE $'b'; BYTE $'o'; BYTE $'o'; + BYTE $'t'; BYTE $'i'; BYTE $'s'; BYTE $'o'; + BYTE $0 - /* 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 +#endif -TEXT realmodeintr(SB), $0 - LONG $0 +TEXT crnl(SB), $0 + BYTE $'\r'; BYTE $'\n'; BYTE $0 +TEXT hex(SB), $0 + BYTE $'0'; BYTE $'1'; BYTE $'2'; BYTE $'3'; + BYTE $'4'; BYTE $'5'; BYTE $'6'; BYTE $'7'; + BYTE $'8'; BYTE $'9'; BYTE $'a'; BYTE $'b'; + BYTE $'c'; BYTE $'d'; BYTE $'e'; BYTE $'f' diff --git a/sys/src/boot/pc/lib.h b/sys/src/boot/pc/lib.h deleted file mode 100644 index 9b0d3631c..000000000 --- a/sys/src/boot/pc/lib.h +++ /dev/null @@ -1,118 +0,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 "lux" void* -#pragma varargck type "E" uchar* /* eipfmt */ - -/* from /sys/include/libc.h */ -#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 "lb" long -#pragma varargck type "ld" ulong -#pragma varargck type "lx" ulong -#pragma varargck type "lb" ulong -#pragma varargck type "d" int -#pragma varargck type "x" int -#pragma varargck type "c" int -#pragma varargck type "C" int -#pragma varargck type "b" int -#pragma varargck type "d" uint -#pragma varargck type "x" uint -#pragma varargck type "c" uint -#pragma varargck type "C" uint -#pragma varargck type "b" 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 "n" int* -#pragma varargck type "p" uintptr -#pragma varargck type "p" void* -#pragma varargck flag ',' -#pragma varargck flag 'h' -#pragma varargck type "<" void* -#pragma varargck type "[" void* -#pragma varargck type "H" void* -#pragma varargck type "lH" void* - -#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 diff --git a/sys/src/boot/pc/load.c b/sys/src/boot/pc/load.c deleted file mode 100644 index 07c5b639f..000000000 --- a/sys/src/boot/pc/load.c +++ /dev/null @@ -1,691 +0,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" - -/* - * "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. - * "nvram" is for the benefit of AoE clients. - */ -static char *diskparts[] = { - "dos", "plan9", "9fat", "fs", "data", "cdboot", "cache", "nvram", 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", -}; - -extern SDifc sdataifc; -extern SDifc sdiahciifc; -extern SDifc sdaoeifc; -extern SDifc sdbiosifc; - -extern SDifc sdmylexifc; -extern SDifc sd53c8xxifc; - -SDifc* sdifc[] = { - &sdataifc, - &sdiahciifc, - &sdmylexifc, - &sd53c8xxifc, - &sdbiosifc, - &sdaoeifc, - 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; - 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; - -/* - * Is it safe to probe the bios? - * - * Empirically, we can't touch any disks natively (not through the - * bios) if we want to read them through the bios. So we have to - * choose bios (usb) loading or everything-else loading. - */ -int biosload; -int askbiosload; - -int iniread; -int debugload; -int vga; -char *persist; - -static char * -typename(int type) -{ - if (type < 0 || type >= nelem(typenm) || typenm[type] == nil) - return "**gok**"; - return typenm[type]; -} - -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(); - - /* - * the soekris machines have no video but each has a serial port. - * they must see serial output, if any, before cga output because - * otherwise the soekris bios will translate cga output to serial - * output, which will garble serial console output. - */ - pcimatch(nil, 0, 0); /* force scan of pci table */ - if (!vga) { - consinit("0", "9600"); /* e.g., for soekris debugging */ - print("no vga; serial console only\n"); - } - kbdinit(); - if((ulong)&end > (KZERO|(640*1024))) - panic("i'm too big"); - - if (!pxe) - /* TODO turning off debug and debugload makes loading fail */ - debug = 1; - - /* this is too early for the non-soekris serial console, alas */ - if (askbiosload) { - line[0] = '\0'; - getstr("use bios drivers (e.g., for usb)", line, sizeof line, - "no", 60); - biosload = strncmp(line, "yes", 3) == 0; - } - - /* - * find and read plan9.ini, setting configuration variables. - */ - if (debug) - print("plan9.ini probe..."); - for(tp = types; tp->type != Tnil; tp++){ - /* - * we don't know which ether interface to use nor - * whether bios loading is disabled until we have read - * plan9.ini. make an exception for 9pxeload: probe - * ethers anyway. - */ - if(!pxe && tp->type == Tether /*|| !vga && tp->type == Tbios */) - continue; - if (debug) - print("probing %s...", typename(tp->type)); - if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){ - if (debug) - print("using %s!%s!%s\n", - mp->name, mp->part, mp->ini); - iniread = !dotini(mp->inifs); - break; - } - } - if (debug) - print("\n"); - - /* - * we should now have read plan9.ini, if any. - */ - if (!iniread) - print("no plan9.ini\n"); - - persist = getconf("*bootppersist"); - if (!pxe) - debug = 0; /* stop the flood of output */ - debugload = getconf("*debugload") != nil; - /* - * !vga is a hack for soekris-like machines. - * 9pxeload can't use bios int 13 calls; they wedge the machine. - */ - if(!vga || pxe || getconf("*nobiosload") != nil) - biosload = 0; - if((p = getconf("console")) != nil) - consinit(p, getconf("baud")); - - prcpuid(); - readlsconf(); - apminit(); - print("bios (usb) loading %s\n", biosload? "enabled": "disabled"); - - 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-boot probe\n"); - } - - def[0] = 0; - probe(Tany, Fnone, Dany); - if (debugload) - print("end final probe\n"); - - if(p = getconf("bootdef")) - strncpy(def, p, sizeof def); - - /* print possible boot methods */ - 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"); - - /* - * e.g., *bootppersist=ether0 - * - * previously, we looped in bootpopen if we were pxeload or if - * *bootppersist was set. that doesn't work well for pxeload - * in configurations where bootp will never succeed on the first - * interface but only on another interface. - */ - if (mode == Mauto && persist != nil && - (mp = parse(persist, &file)) != nil) { - boot(mp, file); - print("pausing before retry..."); - delay(30*1000); - 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, 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", - 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", - 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"); - - 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)))(); -} diff --git a/sys/src/boot/pc/mem.h b/sys/src/boot/pc/mem.h index 4a290deff..15760c0c5 100644 --- a/sys/src/boot/pc/mem.h +++ b/sys/src/boot/pc/mem.h @@ -18,9 +18,7 @@ /* * Time */ -// #define HZ 100 /* clock frequency */ -/* 1000Hz for *9loadfakeintrs */ -#define HZ 1000 /* clock frequency */ +#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)) @@ -29,13 +27,12 @@ /* * Fundamental addresses */ -/* edd says BDA (bios data area) is at 40:00 = 0x400 - 0x500 */ #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 (unused by boot) */ +#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 */ diff --git a/sys/src/boot/pc/memory.c b/sys/src/boot/pc/memory.c deleted file mode 100644 index 9b2f1587b..000000000 --- a/sys/src/boot/pc/memory.c +++ /dev/null @@ -1,504 +0,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", 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", - 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", - 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); -} - diff --git a/sys/src/boot/pc/mkfile b/sys/src/boot/pc/mkfile index 34e2e1f52..b4b5ab01d 100644 --- a/sys/src/boot/pc/mkfile +++ b/sys/src/boot/pc/mkfile @@ -2,166 +2,23 @@ objtype=386 </$objtype/mkfile BIN=/386 -TARG=\ - 9load\ - 9loadask\ - 9loaddebug\ - 9loadlite\ - 9loadlitedebug\ - 9loadusb\ - 9pxeload\ - 9pxeloaddebug\ - 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\ - -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\ - 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\ - 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=-FTVw -I. - -all:V: $TARG - -9load: l.$O $CORE $LOAD $ETHER nobiosload.$O - $LD -o $target -H3 -T0x80010000 -l $prereq -lflate -lc -lip - ls -l $target - -9pxeload: lpxe.$O $CORE $LOAD $ETHER nobiosload.$O - $LD -o $target -H3 -T0x80007C00 -l $prereq -lflate -lc -lip - ls -l $target - -9loaddebug: l.$O $CORE $LOAD $ETHER nobiosload.$O - $LD -o $target -T0x80010000 -l $prereq -lflate -lc -lip - ls -l $target - # acid $target - # map({"text", 0x80010000, 0x80090000, 0x00000020}) - -9pxeloaddebug: lpxe.$O $CORE $LOAD $ETHER nobiosload.$O - $LD -o $target -T0x80007C00 -l $prereq -lflate -lc -lip - ls -l $target - # acid $target - # map({"text", 0x80010000, 0x80090000, 0x00000020}) - -9loadlite: l.$O $CORE $LOAD noether.$O nobiosload.$O - $LD -o $target -H3 -T0x80010000 -l $prereq -lflate -lc - ls -l $target - -9loadlitedebug: l.$O $CORE $LOAD noether.$O nobiosload.$O - $LD -o $target -T0x80010000 -l $prereq -lflate -lc - ls -l $target - # acid $target - # map({"text", 0x80010000, 0x80090000, 0x00000020}) - -9loadusb: l.$O $CORE $LOAD $ETHER biosload.$O - $LD -o $target -H3 -T0x80010000 -l $prereq -lflate -lc -lip - ls -l $target +TARG=9bootiso 9bootpxe 9bootfat mbr pbs -9loadask: l.$O $CORE $LOAD $ETHER askbiosload.$O - $LD -o $target -H3 -T0x80010000 -l $prereq -lflate -lc -lip - ls -l $target - -ld.com: ld.$O $CORE $BCOM - $LD -o $target -H3 -T0x80080100 -l $prereq -lc - ls -l $target +HFILES=mem.h fns.h x16.h -lddebug: ld.$O $CORE $BCOM - $LD -o $target -T0x80080100 -l $prereq -lc - ls -l $target - # acid $target - # map({"text", 0x80080100, 0x800B0000, 0x00000020}) - -ld.$O: l.s - $AS -DDOTCOM -o $target l.s +all: 9bootiso 9bootpxe 9bootfat mbr pbs + +clean:V: + rm -rf $TARG *.$O test.* tmp -l.$O: l.s - $AS -DVGA -o $target l.s +liso.$O: l.s + $AS -DISO -o $target l.s lpxe.$O: l.s - $AS -DPXE -DVGA -o $target l.s - -lnovga.$O: l.s - $AS -o $target l.s - -lpxenovga.$O: l.s $AS -DPXE -o $target l.s -loadverb.$O: load.c - $CC -o $target $CFLAGS '-DVERBOSE=1' load.c +lfat.$O: l.s + $AS -DFAT -o $target l.s %.$O: %.s $AS $stem.s @@ -171,67 +28,66 @@ loadverb.$O: load.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 +pbs: pbs.$O + $LD -o $target -H3 -T0x0600 -l $prereq ls -l $target -pbs&.debug: pbs%.$O - $LD -o $target -T0x7C00 -l $prereq +9boot&: l%.$O %.$O sub.$O + $LD -o $target -H3 -T0x7c00 -l $prereq ls -l $target - # acid $target - # map({"text", 0x7C00, 0x7E00, 0x00000020}) - -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/% -# for (fs in $EXTRACOPIES) -# 9fs $fs && cp $prereq /n/$fs/$prereq - ; + $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 +test.iso: 9bootiso + rm -fr tmp $target + mkdir tmp + cp 9bootiso tmp + touch tmp/foo + touch tmp/bar + touch tmp/baz + touch tmp/386aaa + mkdir tmp/386 + cp /386/9pc tmp/386 + cp /386/9pcload tmp/386 + cp /386/9pcf tmp/386 + #echo 'bootfile=/386/9pc' >tmp/plan9.ini + disk/mk9660 -B 9bootiso -p /sys/lib/sysconfig/proto/allproto -s tmp $target + rm -fr tmp + +test.dsk: 9bootfat mbr pbs + rm -fr tmp $target + mkdir tmp + cp 9bootfat tmp + mkdir tmp/386 + cp /386/9pc tmp/386 + echo 'bootfile=/386/9pc' >tmp/plan9.ini + dd -if /dev/zero -of $target -bs 512 -count 32768 + disk/partfs -m /n/$target $target + disk=/n/$target/sdXX + disk/mbr -m mbr $disk/data + disk/fdisk -baw $disk/data + disk/prep -bw -a 9fat $disk/plan9 + disk/format -b pbs -d -r 2 $disk/9fat + s=$target.dos + m=/n/$target.9fat + rm -f /srv/$s + dossrv -f $disk/9fat $s + mount -c /srv/$s $m + @{cd tmp; tar c .} | @{cd $m; tar xv} + unmount $m + rm -f /srv/$s + unmount /n/$target + rm -fr tmp diff --git a/sys/src/boot/pc/nobiosload.c b/sys/src/boot/pc/nobiosload.c deleted file mode 100644 index 9384ec72a..000000000 --- a/sys/src/boot/pc/nobiosload.c +++ /dev/null @@ -1 +0,0 @@ -int biosload = 0; /* for old machines with broken bioses */ diff --git a/sys/src/boot/pc/noether.c b/sys/src/boot/pc/noether.c deleted file mode 100644 index b607b5bc7..000000000 --- a/sys/src/boot/pc/noether.c +++ /dev/null @@ -1,46 +0,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; -} diff --git a/sys/src/boot/pc/part.c b/sys/src/boot/pc/part.c deleted file mode 100644 index e7dfc72fc..000000000 --- a/sys/src/boot/pc/part.c +++ /dev/null @@ -1,354 +0,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]; - { - /* 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; - } - - /* - * there might be no mbr (e.g. on a very large device), so look for - * a bare plan 9 partition table if mbrpart fails. - */ - if((type & NEW) && mbrpart(unit) >= 0){ - /* nothing to do */ - } - else if (type & NEW) - p9part(unit, "data"); - else if(type & OLD) - oldp9part(unit); -} diff --git a/sys/src/boot/pc/pbs.s b/sys/src/boot/pc/pbs.s index bd95a04dc..a4c1fc191 100644 --- a/sys/src/boot/pc/pbs.s +++ b/sys/src/boot/pc/pbs.s @@ -1,46 +1,7 @@ -/* - * 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 */ +#define RELOC 0x7c00 TEXT _magic(SB), $0 BYTE $0xEB; BYTE $0x3C; /* jmp .+ 0x3C (_start0x3E) */ @@ -96,57 +57,73 @@ _start0x3E: 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 */ + LWI(0x100, rCX) + LWI(RELOC, rSI) + MW(rSI, rSP) + LWI(_magic(SB), rDI) + CLD + REP; MOVSL /* MOV DS:[(E)SI] -> ES:[(E)DI] */ - /* 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 + PUSHA + MW(rSP, rBP) - LWI(confidence(SB), rSI) /* for that warm, fuzzy feeling */ - CALL16(BIOSputs(SB)) + PUSHR(rCX) + PUSHI(start16(SB)) + BYTE $0xCB /* FAR RET */ - CALL16(dreset(SB)) +TEXT halt(SB), $0 +_halt: + JMP _halt -_jmp00: +TEXT start16(SB), $0 + STI + LWI(hello(SB), rSI) + CALL16(print16(SB)) + LWI(crnl(SB), rSI) + CALL16(print16(SB)) LW(_volid(SB), rAX) /* Xrootlo */ - LW(_volid+2(SB), rDX) /* Xroothi */ - - LWI(_magic+DIROFF(SB), rBX) - CALL16(BIOSread(SB)) /* read the root directory */ + LW(_volid+2(SB), rBX) /* Xroothi */ + PUSHR(rBP) + LW(_sectsize(SB), rCX) + SUB(rCX, rSP) + MW(rSP, rBP) + MW(rSP, rSI) - LWI((512/Dirsz), rBX) +_nextsect: + PUSHR(rAX) + CALL16(readsect16(SB)) + OR(rAX, rAX) + JNE _halt - LWI(_magic+DIROFF(SB), rDI) /* compare first directory entry */ + LW(_sectsize(SB), rCX) + SHRI(5, rCX) -_cmp00: - PUSHR(rDI) /* save for later if it matches */ - LWI(bootfile(SB), rSI) - LWI(Dattr, rCX) +_nextdir: + PUSHR(rCX) + PUSHR(rSI) /* save for later if it matches */ + LWI(bootname(SB), rDI) + LW(bootnamelen(SB), rCX) + CLD REP CMPSB - POPR(rDI) - JEQ _jmp02 + POPR(rSI) + POPR(rCX) + JEQ _found + ADDI(0x20, rSI) + LOOP _nextdir + POPR(rAX) + ADDI(1, rAX) + ADC(rCX, rBX) + JMP _nextsect - DEC(rBX) - JEQ _jmp01 +_found: + PUSHR(rDX) - ADDI(Dirsz, rDI) - JMP _cmp00 -_jmp01: - CALL16(buggery(SB)) + CLR(rBX) -_jmp02: - CLR(rBX) /* a handy value */ LW(_rootsize(SB), rAX) /* calculate and save Xrootsz */ - LWI(Dirsz, rCX) + LWI(0x20, rCX) MUL(rCX) LW(_sectsize(SB), rCX) PUSHR(rCX) @@ -157,10 +134,7 @@ _jmp02: DIV(rCX) PUSHR(rAX) /* Xrootsz */ - /* - * rDI points to the matching directory entry. - */ - LXW(Dstart, xDI, rAX) /* starting sector address */ + LXW(0x1a, xSI, rAX) /* starting sector address */ DEC(rAX) /* that's just the way it is */ DEC(rAX) LB(_clustsize(SB), rCL) @@ -176,8 +150,8 @@ _jmp02: PUSHR(rAX) /* calculate how many sectors to read */ PUSHR(rDX) - LXW(Dlengthlo, xDI, rAX) - LXW(Dlengthhi, xDI, rDX) + LXW(0x1c, xSI, rAX) + LXW(0x1e, xSI, rDX) LW(_sectsize(SB), rCX) PUSHR(rCX) DEC(rCX) @@ -186,187 +160,100 @@ _jmp02: POPR(rCX) /* _sectsize(SB) */ DIV(rCX) MW(rAX, rCX) - POPR(rDX) + POPR(rBX) POPR(rAX) + POPR(rDX) - 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) + LWI(RELOC, rSI) + PUSHR(rSI) -_reset: - CLR(rBX) /* set ES segment for BIOS area */ - MTSR(rBX, rES) +_loadnext: + PUSHR(rCX) + PUSHR(rAX) + CALL16(readsect16(SB)) + OR(rAX, rAX) + JNE _loaderror + POPR(rAX) + CLR(rCX) + ADDI(1, rAX) + ADC(rCX, rBX) + LW(_sectsize(SB), rCX) + ADD(rCX, rSI) + POPR(rCX) + LOOP _loadnext + CLI + RET - LWI(0x0472, rBX) /* warm-start code address */ - LWI(0x1234, rAX) /* warm-start code */ - POKEW /* MOVW AX, ES:[BX] */ +_loaderror: + LWI(ioerror(SB), rSI) + CALL16(print16(SB)) + CALL16(halt(SB)) - FARJUMP16(0xFFFF, 0x0000) /* reset */ +TEXT print16(SB), $0 + PUSHA + CLR(rBX) +_printnext: + LODSB + ORB(rAL, rAL) + JEQ _printret + LBI(0x0E, rAH) + BIOSCALL(0x10) + JMP _printnext +_printret: + POPA + RET /* - * 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 + * in: + * DL drive + * AX:BX lba32, + * 0000:SI buffer */ -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 +TEXT readsect16(SB), $0 + PUSHA + CLR(rCX) - POPA - DEC(rDI) /* too many retries? */ - JEQ _ioerror + PUSHR(rCX) /* qword lba */ + PUSHR(rCX) + PUSHR(rBX) + PUSHR(rAX) - CALL16(dreset(SB)) - JMP _retry + PUSHR(rCX) /* dword buffer */ + PUSHR(rSI) -_ioerror: - LWI(ioerror(SB), rSI) - CALL16(BIOSputs(SB)) - JMP _wait + INC(rCX) + PUSHR(rCX) /* word # of sectors */ -_BIOSreadret: - POPA - RET + PUSHI(0x0010) /* byte reserved, byte packet size */ -TEXT dreset(SB), $0 - PUSHA - CLR(rAX) /* rAH == 0 == reset disc system */ - LBPB(Xdrive, rDL) + MW(rSP, rSI) + LWI(0x4200, rAX) BIOSCALL(0x13) - ORB(rAH, rAH) /* status (0 == success) */ + JCC _readok + ADDI(0x10, rSP) POPA - JNE _ioerror + CLR(rAX) + DEC(rAX) 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: +_readok: + ADDI(0x10, rSP) POPA + CLR(rAX) 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 bootnamelen(SB), $0 + WORD $8 +TEXT bootname(SB), $0 + BYTE $'9'; BYTE $'B'; BYTE $'O'; BYTE $'O'; + BYTE $'T'; BYTE $'F'; BYTE $'A'; BYTE $'T'; + BYTE $0 + 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'; + BYTE $'i'; BYTE $'/'; BYTE $'o'; BYTE $'-'; + BYTE $'e'; BYTE $'r'; BYTE $'r'; BYTE $0 -#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 */ +TEXT hello(SB), $0 + BYTE $'p'; BYTE $'b'; BYTE $'s'; BYTE $0 -/* "PBS..." */ -TEXT confidence(SB), $0 - BYTE $'P'; BYTE $'B'; BYTE $'S'; BYTE $'1'; - BYTE $'.'; BYTE $'.'; BYTE $'.'; - BYTE $'\z'; +TEXT crnl(SB), $0 + BYTE $'\r'; BYTE $'\n'; BYTE $0 diff --git a/sys/src/boot/pc/pbsdebug.s b/sys/src/boot/pc/pbsdebug.s deleted file mode 100644 index f879e79ec..000000000 --- a/sys/src/boot/pc/pbsdebug.s +++ /dev/null @@ -1,344 +0,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' diff --git a/sys/src/boot/pc/pbslba.s b/sys/src/boot/pc/pbslba.s deleted file mode 100644 index 4f7b83258..000000000 --- a/sys/src/boot/pc/pbslba.s +++ /dev/null @@ -1,363 +0,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'; diff --git a/sys/src/boot/pc/pbslbadebug.s b/sys/src/boot/pc/pbslbadebug.s deleted file mode 100644 index c3712f82c..000000000 --- a/sys/src/boot/pc/pbslbadebug.s +++ /dev/null @@ -1,327 +0,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'; diff --git a/sys/src/boot/pc/pci.c b/sys/src/boot/pc/pci.c deleted file mode 100644 index f2aeac524..000000000 --- a/sys/src/boot/pc/pci.c +++ /dev/null @@ -1,1009 +0,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); -} - -/* side effect: if a video controller is seen, set vga non-zero */ -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 0x03: /* display controller */ - vga = 1; - /* fall through */ - case 0x01: /* mass storage controller */ - case 0x02: /* network 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, 0x25a1, pIIx_link, pIIx_init }, // Intel 6300ESB - { 0x8086, 0x2640, pIIx_link, pIIx_init }, // Intel 82801FB - { 0x8086, 0x2641, pIIx_link, pIIx_init }, // Intel 82801FBM - { 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 - { 0x10DE, 0x00E1, 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, -1); -} - - -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 base) -{ - 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) { - if (base >= 0 && base != t->ccrb) - continue; - 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, base); - 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; -} diff --git a/sys/src/boot/pc/print.c b/sys/src/boot/pc/print.c deleted file mode 100644 index 313329211..000000000 --- a/sys/src/boot/pc/print.c +++ /dev/null @@ -1,25 +0,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; -} diff --git a/sys/src/boot/pc/pxe.c b/sys/src/boot/pc/pxe.c new file mode 100644 index 000000000..13a1a413d --- /dev/null +++ b/sys/src/boot/pc/pxe.c @@ -0,0 +1,326 @@ +#include <u.h> +#include "fns.h" + +enum { + Tftp_READ = 1, + Tftp_WRITE = 2, + Tftp_DATA = 3, + Tftp_ACK = 4, + Tftp_ERROR = 5, + Tftp_OACK = 6, + + TftpPort = 69, + + Segsize = 512, + Maxpath = 64, +}; + +typedef uchar IP4[4]; + +typedef struct Tftp Tftp; +typedef struct Dhcp Dhcp; + +struct Tftp +{ + IP4 sip; + IP4 dip; + IP4 gip; + + int sport; + int dport; + + char *rp; + char *ep; + + int eof; + + char pkt[2+2+Segsize]; + char nul; +}; + +struct Dhcp +{ + uchar opcode; + uchar hardware; + uchar hardlen; + uchar gatehops; + uchar ident[4]; + uchar seconds[2]; + uchar flags[2]; + uchar cip[4]; + uchar yip[4]; + uchar sip[4]; + uchar gip[4]; + uchar mac[16]; + char sname[64]; + char bootfile[128]; +}; + +int pxecall(int op, void *buf); + +static void* +unfar(ulong seg, ulong off) +{ + return (void*)((off & 0xFFFF) + (seg & 0xFFFF)*16); +} + +static void +puts(void *x, ushort v) +{ + uchar *p = x; + + p[1] = (v>>8) & 0xFF; + p[0] = v & 0xFF; +} + +static ushort +gets(void *x) +{ + uchar *p = x; + + return p[1]<<8 | p[0]; +} + +static void +hnputs(void *x, ushort v) +{ + uchar *p = x; + + p[0] = (v>>8) & 0xFF; + p[1] = v & 0xFF; +} + +static ushort +nhgets(void *x) +{ + uchar *p = x; + + return p[0]<<8 | p[1]; +} + +static void +moveip(IP4 d, IP4 s) +{ + memmove(d, s, sizeof(d)); +} + +static int +getip(IP4 yip, IP4 sip, IP4 gip, char mac[16]) +{ + struct { + uchar status[2]; + uchar pkttype[2]; + uchar bufsize[2]; + uchar off[2]; + uchar seg[2]; + uchar lim[2]; + } buf; + int i, r; + Dhcp *p; + + memset(&buf, 0, sizeof(buf)); + puts(buf.pkttype, 3); + + if(r = pxecall(0x71, &buf)) + return -r; + if((p = unfar(gets(buf.seg), gets(buf.off))) == 0) + return -1; + moveip(yip, p->yip); + moveip(sip, p->sip); + moveip(gip, p->gip); + mac[12] = 0; + for(i=0; i<6; i++){ + mac[i*2] = hex[p->mac[i]>>4]; + mac[i*2+1] = hex[p->mac[i]&15]; + } + return 0; +} + +static int +udpopen(IP4 sip) +{ + struct { + uchar status[2]; + uchar sip[4]; + } buf; + + puts(buf.status, 0); + moveip(buf.sip, sip); + return pxecall(0x30, &buf); +} + +static int +udpclose(void) +{ + char status[2]; + puts(status, 0); + return pxecall(0x31, status); +} + +static int +udpread(IP4 sip, IP4 dip, int *sport, int dport, int *len, void *data) +{ + struct { + uchar status[2]; + uchar sip[4]; + uchar dip[4]; + uchar sport[2]; + uchar dport[2]; + uchar len[2]; + uchar off[2]; + uchar seg[2]; + } buf; + int r; + + puts(buf.status, 0); + moveip(buf.sip, sip); + moveip(buf.dip, dip); + hnputs(buf.sport, *sport); + hnputs(buf.dport, dport); + puts(buf.len, *len); + puts(buf.off, (long)data); + puts(buf.seg, 0); + if(r = pxecall(0x32, &buf)) + return r; + moveip(sip, buf.sip); + *sport = nhgets(buf.sport); + *len = gets(buf.len); + return 0; +} + +static int +udpwrite(IP4 ip, IP4 gw, int sport, int dport, int len, void *data) +{ + struct { + uchar status[2]; + uchar ip[4]; + uchar gw[4]; + uchar sport[2]; + uchar dport[2]; + uchar len[2]; + uchar off[2]; + uchar seg[2]; + } buf; + + puts(buf.status, 0); + moveip(buf.ip, ip); + moveip(buf.gw, gw); + hnputs(buf.sport, sport); + hnputs(buf.dport, dport); + puts(buf.len, len); + puts(buf.off, (long)data); + puts(buf.seg, 0); + return pxecall(0x33, &buf); +} + +int +read(void *f, void *data, int len) +{ + Tftp *t = f; + int n; + + if(!t->eof && t->rp >= t->ep){ + if(t->rp){ + hnputs(t->pkt, Tftp_ACK); + udpwrite(t->dip, t->gip, t->sport, t->dport, 4, t->pkt); + t->rp = t->ep = 0; + } + for(;;){ + n = sizeof(t->pkt); + if(udpread(t->dip, t->sip, &t->dport, t->sport, &n, t->pkt)) + continue; + if(n >= 4) + break; + } + switch(nhgets(t->pkt)){ + case Tftp_DATA: + t->rp = t->pkt + 4; + t->ep = t->pkt + n; + t->eof = n < Segsize; + break; + case Tftp_ERROR: + print(t->pkt+4); + print(crnl); + default: + t->eof = 1; + return -1; + } + } + n = t->ep - t->rp; + if(len > n) + len = n; + memmove(data, t->rp, len); + t->rp += len; + return len; +} + +void +close(void *f) +{ + Tftp *t = f; + t->eof = 1; + udpclose(); +} + +static int +tftpopen(Tftp *t, char *path, IP4 sip, IP4 dip, IP4 gip) +{ + static ushort xport = 6666; + int r, n; + char *p; + + moveip(t->sip, sip); + moveip(t->gip, gip); + memset(t->dip, 0, sizeof(t->dip)); + t->sport = xport++; + t->dport = 0; + t->rp = t->ep = 0; + t->eof = 0; + t->nul = 0; + if(r = udpopen(t->sip)) + return r; + p = t->pkt; + hnputs(p, Tftp_READ); p += 2; + n = strlen(path)+1; + memmove(p, path, n); p += n; + memmove(p, "octet", 6); p += 6; + n = p - t->pkt; + for(;;){ + if(r = udpwrite(dip, t->gip, t->sport, TftpPort, n, t->pkt)) + break; + if(r = read(t, 0, 0)) + break; + return 0; + } + close(t); + return r; +} + +void +start(void *) +{ + char mac[16], path[Maxpath], *kern; + IP4 yip, sip, gip; + void *f; + Tftp t; + + if(getip(yip, sip, gip, mac)){ + print("bad dhcp\r\n"); + halt(); + } + memmove(path, "/cfg/pxe/", 9); + memmove(path+9, mac, 13); + if(tftpopen(f = &t, path, yip, sip, gip)){ + print("no config\r\n"); + f = 0; + } + for(;;){ + kern = configure(f, path); f = 0; + if(tftpopen(&t, kern, yip, sip, gip)){ + print("not found\r\n"); + continue; + } + print(bootkern(&t)); + print(crnl); + } +} diff --git a/sys/src/boot/pc/queue.c b/sys/src/boot/pc/queue.c deleted file mode 100644 index d2a529cdf..000000000 --- a/sys/src/boot/pc/queue.c +++ /dev/null @@ -1,44 +0,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; -} diff --git a/sys/src/boot/pc/sd.h b/sys/src/boot/pc/sd.h deleted file mode 100644 index 25a19cf40..000000000 --- a/sys/src/boot/pc/sd.h +++ /dev/null @@ -1,126 +0,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); diff --git a/sys/src/boot/pc/sd53c8xx.c b/sys/src/boot/pc/sd53c8xx.c deleted file mode 100644 index 12a8e1800..000000000 --- a/sys/src/boot/pc/sd53c8xx.c +++ /dev/null @@ -1,2129 +0,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; - - /* native access to disks seems to interfere with bios loading */ - if (biosload) - return 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 */ -}; diff --git a/sys/src/boot/pc/sd53c8xx.i b/sys/src/boot/pc/sd53c8xx.i deleted file mode 100644 index 503223669..000000000 --- a/sys/src/boot/pc/sd53c8xx.i +++ /dev/null @@ -1,769 +0,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 diff --git a/sys/src/boot/pc/sdaoe.c b/sys/src/boot/pc/sdaoe.c deleted file mode 100644 index 665bbaa19..000000000 --- a/sys/src/boot/pc/sdaoe.c +++ /dev/null @@ -1,760 +0,0 @@ -/* - * aoe (ata over ethernet) 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, - Ctlrlet = 'e', /* first sd controller letter */ - - Probeintvl = 100, /* ms. between probes */ - Probemax = 8000, /* max ms. to wait */ - Probetries = Probemax / Probeintvl, /* max tries */ -}; - -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 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 Ctlr aoectlr[NCtlr]; -// static SDev sdevs[NCtlr]; -// static int naoectlr; - -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("sdaoe: discovered %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("sdaoe: chktag: wrong aoe tag: "); - for(j = 0; j <= nout; j++) - print("%.8ux != %.8ux\n", out[j], tag); - return -1; -} - -static int -etherrxany(Etherpkt *p, int t) -{ - int i, n; - - for(i = 0; i < nelem(aoeether); i++) - if(aoeether[i]) - while ((n = etherrxpkt(i, p, t)) != 0) - if(nhgets(p->type) == Aoetype) - return n; - return 0; -} - -static int -ethertxany(Etherpkt *p, int n) -{ - int i; - - for(i = 0; i < nelem(aoeether); i++) - if(aoeether[i]) - ethertxpkt(i, p, n, 0); - return 0; -} - -/* - * 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 == Probetries){ - print("sdaoe: identify: timeout\n"); - return -1; - } - tag[i] = idpkt(c, a); - ethertxany(&p, sizeof *a); - memset(&p, 0, sizeof p); -next: - n = etherrxany(&p, Probeintvl); - 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("sdaoe: 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 -aoeprobe(int major, int minor, SDev *s) -{ - Ctlr *ctlr; - Etherpkt p; - int n, i; - - n = -1; - ctlr = nil; - for(i = 0; n <= 0 || ctlr == nil; i += Probeintvl){ - if(i > Probemax) - return -1; - discover(major, minor); - while ((n = etherrxany(&p, Probeintvl)) > 0 && - (ctlr = newctlr(&p)) == nil) - ; - } - s->ctlr = ctlr; - s->ifc = &sdaoeifc; - s->nunit = 1; - return 0; -} - -static char *probef[32]; -static int nprobe; - -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; -} - -static int -aoepnp0(void) -{ - int i; - char *p, c; - - if((p = getconf("aoeif")) == nil) - return 0; - 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 tokenize(p, probef, nelem(probef)); -} - -static 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("sdaoe: found shelf=%d.%d\n", a, b); - return 0; -} - -static Ctlr* -pnpprobe(SDev *sd) -{ - int shelf, slot; - char *p; - static int i; - - if(i >= nprobe) - return nil; - p = probef[i++]; - if(strlen(p) < 2) - return nil; - 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 nil; - return sd->ctlr; -} - -/* - * we may need to pretend we found something - */ - -static 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 = nil; - for(i = 0; i < n; i++){ - id = Ctlrlet + i; -// print("aoepnp: id sd%C\n", id); - s = malloc(sizeof *s); - if(s == nil) - break; - s->ctlr = 0; - s->idno = id; - s->ifc = &sdaoeifc; - s->nunit = 1; - pnpprobe(s); - /* if pnpprobe failed, *s may contain rubbish */ - - if(h) - t->next = s; - else - h = s; - t = s; - } - return h; -} - -static int -aoeverify(SDunit *u) -{ - Ctlr *c; - SDev *s; - - if (u == nil || u->dev == nil) - return 0; - s = u->dev; - c = s->ctlr; - if(c == nil){ - aoepnp0(); - if((s->ctlr = c = pnpprobe(s)) == nil) - return 0; - } - c->mediachange = 1; - return 1; -} - -static int -aoeonline(SDunit *u) -{ - int r; - Ctlr *c; - - if (u == nil || u->dev == nil || u->dev->ctlr == nil) - return 0; - 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 < Probetries; i++){ - tag = hset(c, a, ACata); - cmd = a->cmdstat; - ethertxany((Etherpkt*)a, n); - memset(a, 0, sizeof *a); -again: - n = etherrxany((Etherpkt*)a, Probeintvl); - 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("sdaoe: ata rio error: %2ux\n", a->cmdstat); - return 0; - } - switch(cmd){ - case Crd: - case Crdext: - if(n - sizeof *a < scnt * 512){ - print("sdaoe: 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 aoe cmd %ux\n", cmd); - break; - } - } - print("sdaoe: 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 cheating 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("sdaoe: 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; -} - -static SDev* -aoeid(SDev* sdev) -{ - int i; - Ctlr *c, *aec; - - for(; sdev; sdev = sdev->next){ - if(sdev->ifc != &sdaoeifc) - continue; - c = sdev->ctlr; - i = 0; - for(aec = head; aec; aec = aec->next) { - if(c == aec) - sdev->idno = Ctlrlet + i; - i++; - } - } - return nil; -} - -SDifc sdaoeifc = { - "aoe", - - aoepnp, - nil, /* legacy */ - aoeid, /* id */ - nil, /* enable */ - nil, /* disable */ - - aoeverify, - aoeonline, - aoerio, - nil, - nil, - - scsibio, -}; diff --git a/sys/src/boot/pc/sdata.c b/sys/src/boot/pc/sdata.c deleted file mode 100644 index e728b3e27..000000000 --- a/sys/src/boot/pc/sdata.c +++ /dev/null @@ -1,1673 +0,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, Drdy, 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{ - if (drive->s == 0 || drive->h == 0) - panic("atageniostart: zero s or h"); - 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, Drdy, 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 = p; - 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 = p; - 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->secsize == 0) - panic("atagenio: zero sector size"); - 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; - - /* native access to disks seems to interfere with bios loading */ - if (biosload) - return 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 (0x0680<<16)|0x1095: /* SiI 0680/680A PATA133 ATAPI/RAID */ - 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 */ - case (0x4376<<16)|0x1002: /* ATI SB400 PATA */ - case (0x4379<<16)|0x1002: /* ATI SB400 SATA */ - case (0x437a<<16)|0x1002: /* ATI SB400 SATA */ - /* - * 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 (0x00E3<<16)|0x10DE: /* nVidia nForce2 250 SATA */ - case (0x00D5<<16)|0x10DE: /* nVidia nForce3 */ - case (0x00E5<<16)|0x10DE: /* nVidia nForce3 Pro */ - case (0x00EE<<16)|0x10DE: /* nVidia nForce3 250 SATA */ - 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 (0x2363<<16)|0x197b: /* JMicron SATA */ - 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 (0x25A3<<16)|0x8086: /* 6300ESB (E7210) */ - case (0x266F<<16)|0x8086: /* 82801FB (ICH6) */ - case (0x27DF<<16)|0x8086: /* 82801G SATA (ICH7) */ - case (0x27C0<<16)|0x8086: /* 82801GB SATA AHCI (ICH7) */ -// case (0x27C4<<16)|0x8086: /* 82801GBM SATA (ICH7) */ - case (0x27C5<<16)|0x8086: /* 82801GBM SATA AHCI (ICH7) */ - case (0x2920<<16)|0x8086: /* 82801(IB)/IR/IH/IO SATA IDE (ICH9) */ - case (0x3a20<<16)|0x8086: /* 82801JI (ICH10) */ - case (0x3a26<<16)|0x8086: /* 82801JI (ICH10) */ - 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 */ -}; diff --git a/sys/src/boot/pc/sdbios.c b/sys/src/boot/pc/sdbios.c deleted file mode 100644 index 1f5dc4ccc..000000000 --- a/sys/src/boot/pc/sdbios.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * boot driver for BIOS devices with partitions. - * devbios must be initialised 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; - -uchar * -putbeul(ulong ul, uchar *p) -{ - *p++ = ul >> 24; - *p++ = ul >> 16; - *p++ = ul >> 8; - *p++ = ul; - return p; -} - -uchar * -putbeuvl(uvlong uvl, uchar *p) -{ - *p++ = uvl >> 56; - *p++ = uvl >> 48; - *p++ = uvl >> 40; - *p++ = uvl >> 32; - *p++ = uvl >> 24; - *p++ = uvl >> 16; - *p++ = uvl >> 8; - *p++ = uvl; - return p; -} - -int -biosverify(SDunit* ) -{ - if (onlybios0 || !biosinited) - return 0; - return 1; -} - -int -biosonline(SDunit* unit) -{ - if (onlybios0 || !biosinited || !unit) - return 0; - unit->secsize = 512; /* conventional */ - unit->sectors = ~0ULL / unit->secsize; /* all of them, and then some */ - return 1; -} - -static int -biosrio(SDreq* r) -{ - int nb; - long got; - vlong 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"); - 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; - - /* - * Read capacity returns the LBA of the last sector. - */ - case 0x25: /* read capacity */ - p = putbeul(r->unit->sectors - 1, r->data); - r->data = putbeul(r->unit->secsize, p); - return SDok; - case 0x9E: /* long read capacity */ - p = putbeuvl(r->unit->sectors - 1, r->data); - r->data = putbeul(r->unit->secsize, p); - 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 || !biosload || 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 */ -}; diff --git a/sys/src/boot/pc/sdiahci.c b/sys/src/boot/pc/sdiahci.c deleted file mode 100644 index 09ff69697..000000000 --- a/sys/src/boot/pc/sdiahci.c +++ /dev/null @@ -1,1778 +0,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 == 1) print(__VA_ARGS__); else USED(debug) -#define idprint(...) if(prid == 1) print(__VA_ARGS__); else USED(prid) -#define aprint(...) if(datapi == 1) print(__VA_ARGS__); else USED(datapi) - -enum { - NCtlr = 2, - NCtlrdrv= 8, - NDrive = NCtlr*NCtlrdrv, - - Read = 0, - Write, -}; - -/* pci space configuration */ -enum { - Pmap = 0x90, - Ppcs = 0x91, - Prev = 0xa8, -}; - -enum { - Tesb, - Tich, - Tsb600, - Tunk, -}; - -#define Intel(x) ((x)->pci->vid == 0x8086) - -static char *tname[] = { - "63xxesb", - "ich", - "sb600", - "unk", -}; - -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; - ulong lastseen; - 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; - int mport; -}; - -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("ahci: %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, 500); -} - -static int -setudmamode(Aportc *pc, uchar f) -{ - uchar *c; - Actab *t; - Alist *l; - - /* hack */ - if((pc->p->sig >> 16) == 0xeb14) - return 0; - - 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, 500); -} - -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, 500); -} - -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) { - 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("ahci: 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 & 0xF00) != 0x600) - return; - if((s & 7) != 1){ /* not (device, no phy) */ - print("ahci: slumbering drive unwakeable %ux\n", s); - return; - } - p->sctl = 3*Aipm | 0*Aspd | Adet; - delay(1); - p->sctl &= ~7; -// print("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("ahci: configdrive: spinning up ... [%lux]\n", - p->sstatus); - p->cmd |= Apod|Asud; - asleep(400); - } - - 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 & 0xF0F) == 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 < 500; 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 char* -dnam(Drive *d) -{ - char *s; - - s = d->name; - if(d->unit && d->unit->name) - s = d->unit->name; - return s; -} - -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 != 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) { - 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("ahci: updatedrive: fatal\n"); - } - if(cause & Adhrs){ - if(p->task & (1<<5|1)){ - dprint("ahci: 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: /* no device */ - d->state = Dmissing; - break; - case 1: /* device but no phy comm. */ - if((p->sstatus & 0xF00) == 0x600) - d->state = Dnew; /* slumbering */ - else - d->state = Derror; - break; - case 3: /* device & phy comm. estab. */ - /* power mgnt crap for surprise removal */ - p->ie |= Aprcs|Apcs; /* is this required? */ - d->state = Dreset; - break; - case 4: /* phy off-line */ - d->state = Doffline; - break; - } - dprint("%s: %s → %s [Apcrs] %lux\n", name, - diskstates[s0], diskstates[d->state], p->sstatus); - /* print pulled message here. */ - 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: /* no device */ - d->state = Dmissing; - break; - case 1: /* device but no phy. comm. */ - break; - case 2: /* should this be missing? need testcase. */ - dprint("ahci: pstatus 2\n"); - /* fallthrough */ - case 3: /* device & phy. comm. */ - d->wait = 0; - d->state = Dnew; - break; - case 4: /* offline */ - d->state = Doffline; - break; - case 6: /* ? not sure this makes sense. TODO */ - 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("ahci: 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; - 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) - goto lose; - } - if (d->sectors == 0) { - idprint("%s: no sectors\n", d->unit->name); - goto lose; - } - - ilock(d); - d->state = Dready; - iunlock(d); - - qunlock(c->m); - - idprint("%s: %sLBA %,llud sectors: %s %s %s %s\n", d->unit->name, - (m->feat & Dllba? "L": ""), d->sectors, d->model, d->firmware, - d->serial, d->mediachange? "[mediachange]": ""); - return 0; - -lose: - idprint("sdiachi: %s can't be initialized\n", name); - ilock(d); - d->state = Dnull; - iunlock(d); - qunlock(c->m); - 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("ahci: doportreset: fails\n"); - else - i = 0; - qunlock(&d->portm); - dprint("ahci: 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) - d->lastseen = m->ticks; - if(s != olds[i]){ - dprint("%s: status: %04ux -> %04ux: %s\n", - name, olds[i], s, diskstates[d->state]); - olds[i] = s; - d->wait = 0; - } - westerndigitalhung(d); - switch(d->state){ - case Dnull: - case Dready: - break; - case Dmissing: - case Dnew: - switch(s & 0x107){ - case 1: /* no device (pm), device but no phy. comm. */ - ahciwakeup(d->port); - /* fall through */ - case 0: /* no device */ - break; - default: - dprint("%s: unknown status %04ux\n", name, s); - /* fall through */ - case 0x100: /* active, no device */ - 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: /* active, device, phy. comm. */ - if((++d->wait&Midwait) == 0){ - dprint("%s: slow reset %04ux task=%lux; %d\n", - name, s, d->port->task, d->wait); - goto reset; - } - s = (uchar)d->port->task; - 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; - /* fallthrough */ - case Derror: - case Dreset: - dprint("%s: reset [%s]: mode %d; status %04ux\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; - /* device is active */ - 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){ /* no device */ - 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); - cause = c->hba->isr; - for(i = 0; i < c->mport; 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, reset; - Ctlr *c; - Drive *d; - - c = u->dev->ctlr; - d = c->drive[u->subno]; - ilock(c); - ilock(d); - d->unit = u; - iunlock(d); - iunlock(c); - - reset = 0; - /* we may be waiting for a cd drive to spin up, so be a bit patient. */ - for(i = 0; i < 50; i++){ - checkdrive(d, d->driveno); - switch(d->state){ - case Dnew: - if(d->port->task & 0x80){ - d->state = Dportreset; - reset = 1; - } - break; - case Dmissing: - if(reset || d->port->sstatus & 0x733) - break; - /* - * don't print messages about missing drives; - * it's just noise. - */ - break; - case Dnull: - case Doffline: - if(0)print("sdiahci: drive %d in state %s after %d resets\n", - d->driveno, diskstates[d->state], i); - return 1; - case Dready: - if(d->portm.feat & Datapi) - return scsiverify(d->unit); - return 1; - } - if(d->state != Dnew && i >= 10) - break; - /* Dnew means there's something there. it's just really slow. */ - delay(100); - } - if(d->state != Dmissing) - print("sdiahci: drive %d won't come up; " - "in state %s after %d ms.\n", - d->driveno, diskstates[d->state], i*100); - return 0; -} - -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, i, δ; - - /* don't wait long; we're only the bootstrap */ - for(i = 0; i < 8000; i += 250){ - if(d->state == Dreset || d->state == Dportreset || - d->state == Dnew) - return 1; - if(d->lastseen == 0) - δ = 0; - else - δ = TK2MS(m->ticks - d->lastseen); - if(d->state == Dnull || δ > 10*1000) - return -1; - ilock(d); - s = d->port->sstatus; - iunlock(d); - if((s & Imask) == 0 && δ > 1500) - return -1; - if(d->state == Dready && (s & Smask) == Sphylink) - return 0; - esleep(250); - } - print("%s: not responding; offline\n", dnam(d)); - 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) - ; - - if (d->port == nil) - panic("iariopkt: nil d->port"); - 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 (unit->secsize <= 0) - unit->secsize = 512; - 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) - ; - - if (d->port == nil) - panic("iario: nil d->port"); - 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-15 as ahci sata (c.f. errata) - */ -static int -iaahcimode(Pcidev *p) -{ - uint u; - - u = pcicfgr16(p, 0x92); - dprint("ahci: %ux: iaahcimode %.2ux %.4ux\n", - p->tbdf, pcicfgr8(p, 0x91), u); - pcicfgw16(p, 0x92, u | 0xf); - return 0; -} - -enum { - Ghc = 0x04/4, /* global host control */ - Pi = 0x0c/4, /* ports implemented */ - - Cmddec = 1<<15, /* enable command block decode */ - - /* Ghc bits */ - Ahcien = 1<<31, /* ahci enable */ -}; - -static void -iasetupahci(Ctlr *c) -{ - pcicfgw16(c->pci, 0x40, pcicfgr16(c->pci, 0x40) & ~Cmddec); - pcicfgw16(c->pci, 0x42, pcicfgr16(c->pci, 0x42) & ~Cmddec); - - c->lmmio[Ghc] |= Ahcien; - c->lmmio[Pi] = (1 << 6) - 1; /* 5 ports (supposedly ro pi reg) */ - - /* enable ahci mode; from ich9 datasheet */ - pcicfgw16(c->pci, 0x90, 1<<6 | 1<<5); -} - -static int -didtype(Pcidev *p) -{ - switch(p->vid){ - case 0x8086: - if((p->did & 0xfffc) == 0x2680) - return Tesb; - /* - * 0x27c4 is the intel 82801 in compatibility (not sata) mode. - */ - if ((p->did & 0xfffb) == 0x27c1 || /* 82801g[bh]m ich7 */ - p->did == 0x2821 || /* 82801h[roh] */ - (p->did & 0xfffe) == 0x2824 || /* 82801h[b] */ - (p->did & 0xfeff) == 0x2829 || /* ich8/9m */ - (p->did & 0xfffe) == 0x2922 || /* ich9 */ - p->did == 0x3a02 || /* 82801jd/do */ - (p->did & 0xfefe) == 0x3a22 || /* ich10, pch */ - (p->did & 0xfff7) == 0x3b28) /* pchm */ - return Tich; - break; - case 0x1002: /* ATI */ - if (p->did == 0x4380 || p->did == 0x4390 || p->did == 0x4391) - return Tsb600; - break; - } - if(p->ccrb == Pcibcstore && p->ccru == 6 && p->ccrp == 1) - return Tunk; - return -1; -} - -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; - - /* native access to disks seems to interfere with bios loading */ - if (biosload) - return nil; - - done = 1; - memset(olds, 0xff, sizeof olds); - p = nil; - head = tail = nil; -loop: - while((p = pcimatch(p, 0, 0)) != nil){ - if((type = didtype(p)) == -1) - continue; - if(niactlr == NCtlr){ - print("ahci: 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(p->mem[Abar].bar == 0) { - if(0)print("%s: did %#ux has zero bar\n", tname[c->type], - p->did); - continue; - } - 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) && p->did != 0x2681) - iasetupahci(c); - nunit = ahciconf(c); -// ahcihbareset((Ahba*)c->mmio); - if(Intel(c) && 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; - c->mport = c->hba->cap & 0x1f; - - /* 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->serial[0] = ' '; - d->ctlr = c; - if((c->hba->pi & (1<<i)) == 0) - continue; - 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, -}; diff --git a/sys/src/boot/pc/sdmylex.c b/sys/src/boot/pc/sdmylex.c deleted file mode 100644 index 457d235d5..000000000 --- a/sys/src/boot/pc/sdmylex.c +++ /dev/null @@ -1,1297 +0,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; - - /* native access to disks seems to interfere with bios loading */ - if (biosload) - return 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 */ -}; diff --git a/sys/src/boot/pc/sdscsi.c b/sys/src/boot/pc/sdscsi.c deleted file mode 100644 index c39bbcd02..000000000 --- a/sys/src/boot/pc/sdscsi.c +++ /dev/null @@ -1,376 +0,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; -} diff --git a/sys/src/boot/pc/sub.c b/sys/src/boot/pc/sub.c new file mode 100644 index 000000000..ab59237ea --- /dev/null +++ b/sys/src/boot/pc/sub.c @@ -0,0 +1,208 @@ +#include <u.h> +#include <a.out.h> +#include "fns.h" +#include "mem.h" + +void +memset(void *p, int v, int n) +{ + uchar *d = p; + while(n > 0){ + *d++ = v; + n--; + } +} + +void +memmove(void *dst, void *src, int n) +{ + uchar *d = dst; + uchar *s = src; + while(n > 0){ + *d++ = *s++; + n--; + } +} + +int +memcmp(void *src, void *dst, int n) +{ + uchar *d = dst; + uchar *s = src; + int r = 0; + while((n > 0) && (r = (*d++ - *s++)) == 0) + n--; + return r; +} + +int +strlen(char *s) +{ + char *p = s; + while(*p) + p++; + return p - s; +} + +char* +strchr(char *s, int c) +{ + for(; *s; s++) + if(*s == c) + return s; + return 0; +} + +char* +strrchr(char *s, int c) +{ + char *r; + r = 0; + while(s = strchr(s, c)) + r = s++; + return r; +} + +void +print(char *s) +{ + while(*s) + putc(*s++); +} + +int +readn(void *f, void *data, int len) +{ + uchar *p, *e; + + p = data; + e = p + len; + while(p < e){ + if((len = read(f, p, e - p)) <= 0) + break; + p += len; + } + return p - (uchar*)data; +} + +static ushort +beswab(ushort s) +{ + uchar *p; + + p = (uchar*)&s; + return (p[0]<<8) | p[1]; +} + +static ulong +beswal(ulong l) +{ + uchar *p; + + p = (uchar*)&l; + return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; +} + +char* +bootkern(void *f) +{ + uchar *e, *d; + Exec ex; + int n; + + a20(); + if(readn(f, &ex, sizeof(ex)) != sizeof(ex)) + return "bad header"; + if(beswal(ex.magic) != I_MAGIC) + return "bad magic"; + e = (uchar*)(beswal(ex.entry) & ~0xF0000000UL); + n = beswal(ex.text); + if(readn(f, e, n) != n) + goto err; + d = (uchar*)(((ulong)e + n + 0xFFF) & ~0xFFFUL); + n = beswal(ex.data); + if(readn(f, d, n) != n) + goto err; + close(f); + jump(e); +err: + return "i/o error"; +} + +static int +readline(void *f, char buf[64]) +{ + static char white[] = "\t "; + char *p; + + p = buf; + do{ + if(!f) + putc('>'); + while(p < buf + 64-1){ + if(!f){ + putc(*p = getc()); + if(*p == '\r') + putc('\n'); + else if(*p == 0x08 && p > buf){ + p--; + continue; + } + }else if(read(f, p, 1) <= 0) + return 0; + if(p == buf && strchr(white, *p)) + continue; + if(strchr(crnl, *p)) + break; + p++; + } + while(p > buf && strchr(white, p[-1])) + p--; + }while(p == buf); + *p = 0; + return p - buf; +} + +char* +configure(void *f, char *path) +{ + char line[64], *p, *kern; + int inblock, n; + + kern = 0; + inblock = 0; + p = (char*)((CONFADDR + 64) & ~0xF0000000UL); +Loop: + while((n = readline(f, line)) > 0){ + if(*line == 0 || strchr("#;=", *line)) + continue; + if(*line == '['){ + inblock = memcmp("[common]", line, 8); + continue; + } + if(memcmp("boot", line, 5) == 0) + break; + if(inblock || !strrchr(line, '=')) + continue; + print(line); print(crnl); + if(memcmp("bootfile=", line, 9) == 0) + memmove(kern = path, line+9, 1 + n-9); + memmove(p, line, n); p += n; + *p++ = '\n'; + } + *p = 0; + if(f){ + close(f); + f = 0; + } + if(!kern){ + print("no bootfile\r\n"); + goto Loop; + } + for(n=0; n<10000; n++) + if(gotc()) + goto Loop; + if(p = strrchr(kern, '!')) + kern = p+1; + return kern; +} diff --git a/sys/src/boot/pc/trap.c b/sys/src/boot/pc/trap.c deleted file mode 100644 index e1030eeca..000000000 --- a/sys/src/boot/pc/trap.c +++ /dev/null @@ -1,332 +0,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; -} diff --git a/sys/src/boot/pc/unused/etherga620.c b/sys/src/boot/pc/unused/etherga620.c deleted file mode 100644 index d1711900c..000000000 --- a/sys/src/boot/pc/unused/etherga620.c +++ /dev/null @@ -1,1150 +0,0 @@ -/* - * this driver is too bloated with firmware to include in 9pxeload, - * which must fit in 512K. it's also for a very old card. - * - * 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; -} diff --git a/sys/src/boot/pc/unused/etherga620fw.h b/sys/src/boot/pc/unused/etherga620fw.h deleted file mode 100644 index c30859e75..000000000 --- a/sys/src/boot/pc/unused/etherga620fw.h +++ /dev/null @@ -1,4858 +0,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 }; diff --git a/sys/src/boot/pc/ureg.h b/sys/src/boot/pc/ureg.h deleted file mode 100644 index 0d0d43f05..000000000 --- a/sys/src/boot/pc/ureg.h +++ /dev/null @@ -1,27 +0,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 */ -}; diff --git a/sys/src/boot/pc/x16.h b/sys/src/boot/pc/x16.h index 9727a11e8..36fa40fc7 100644 --- a/sys/src/boot/pc/x16.h +++ b/sys/src/boot/pc/x16.h @@ -156,4 +156,4 @@ /* operand size switch. */ #define OPSIZE BYTE $0x66 - +#define ADSIZE BYTE $0x67 |