From 78ee7d5717807e6ac779293d0d3c78341de6130a Mon Sep 17 00:00:00 2001 From: "Konstantin Kirik (snegovick)" Date: Sun, 28 Dec 2025 12:27:31 +0300 Subject: Move existing boards into subdits split per arch --- os/pc/NOTICE | 10 - os/pc/apbootstrap.h | 15 - os/pc/apbootstrap.s | 110 -- os/pc/apic.c | 378 ---- os/pc/apm.c | 151 -- os/pc/apmjump.s | 98 - os/pc/archmp.c | 138 -- os/pc/audio.h | 15 - os/pc/cga.c | 127 -- os/pc/cgamemscr.c | 203 --- os/pc/crystal.h | 1118 ------------ os/pc/dat.h | 258 --- os/pc/devarch.c | 940 ---------- os/pc/devds1620.c | 368 ---- os/pc/devether.c | 539 ------ os/pc/devfloppy.c | 1082 ----------- os/pc/devi82365.c | 1044 ----------- os/pc/devlm78.c | 346 ---- os/pc/devlpt.c | 245 --- os/pc/devmouse.c | 672 ------- os/pc/devmpeg.c | 1063 ----------- os/pc/devpccard.c | 1949 -------------------- os/pc/devpnp.c | 652 ------- os/pc/devrtc.c | 461 ----- os/pc/devtv.c | 1826 ------------------- os/pc/devusb.c | 951 ---------- os/pc/devvga.c | 620 ------- os/pc/devzt5512.c | 308 ---- os/pc/dma.c | 237 --- os/pc/ether2000.c | 232 --- os/pc/ether2114x.c | 1830 ------------------- os/pc/ether589.c | 214 --- os/pc/ether79c960.c | 523 ------ os/pc/ether79c970.c | 645 ------- os/pc/ether8003.c | 271 --- os/pc/ether8139.c | 765 -------- os/pc/ether82543gc.c | 1367 -------------- os/pc/ether82557.c | 1327 -------------- os/pc/ether83815.c | 1119 ------------ os/pc/ether8390.c | 812 --------- os/pc/ether8390.h | 74 - os/pc/etherdp83820.c | 1246 ------------- os/pc/etherec2t.c | 174 -- os/pc/etherelnk3.c | 2134 ---------------------- os/pc/etherga620.c | 1275 ------------- os/pc/etherga620fw.h | 4858 -------------------------------------------------- os/pc/etherif.h | 39 - os/pc/etherigbe.c | 1989 --------------------- os/pc/etherrhine.c | 734 -------- os/pc/ethersmc.c | 781 -------- os/pc/ethervt6102.c | 1025 ----------- os/pc/etherwavelan.c | 197 -- os/pc/flashif.h | 82 - os/pc/flashzpc.c | 371 ---- os/pc/floppy.h | 183 -- os/pc/fns.h | 165 -- os/pc/fpi.h | 61 - os/pc/fpi387.c | 742 -------- os/pc/fpsave.s | 9 - os/pc/i8250.c | 328 ---- os/pc/i8253.c | 314 ---- os/pc/i8259.c | 199 --- os/pc/io.h | 371 ---- os/pc/kbd.c | 477 ----- os/pc/l.s | 953 ---------- os/pc/main.c | 468 ----- os/pc/mem.h | 144 -- os/pc/memory.c | 588 ------ os/pc/mkfile | 83 - os/pc/mmu.c | 343 ---- os/pc/mouse.c | 84 - os/pc/mp.c | 815 --------- os/pc/mp.h | 225 --- os/pc/pc | 139 -- os/pc/pc4e | 148 -- os/pc/pcdisk | 157 -- os/pc/pci.acid | 252 --- os/pc/pci.c | 1340 -------------- os/pc/pcidb.acid | 2848 ----------------------------- os/pc/pcmciamodem.c | 75 - os/pc/piix4smbus.c | 213 --- os/pc/pix | 156 -- os/pc/ps2mouse.c | 84 - os/pc/ptclbsum386.s | 126 -- os/pc/screen.c | 410 ----- os/pc/screen.h | 173 -- os/pc/sd53c8xx.c | 2135 ---------------------- os/pc/sd53c8xx.i | 773 -------- os/pc/sd53c8xx.n | 448 ----- os/pc/sdata.c | 2206 ----------------------- os/pc/sdmylex.c | 1249 ------------- os/pc/sdscsi.c | 394 ---- os/pc/trap.c | 571 ------ os/pc/tv.h | 15 - os/pc/uarti8250.c | 740 -------- os/pc/uartisa.c | 98 - os/pc/uartpci.c | 137 -- os/pc/usb.h | 160 -- os/pc/usbuhci.c | 1538 ---------------- os/pc/vga.c | 241 --- os/pc/vga.h | 75 - os/pc/vga3dfx.c | 258 --- os/pc/vgaark2000pv.c | 190 -- os/pc/vgabt485.c | 245 --- os/pc/vgaclgd542x.c | 291 --- os/pc/vgaclgd546x.c | 277 --- os/pc/vgact65545.c | 149 -- os/pc/vgacyber938x.c | 225 --- os/pc/vgaet4000.c | 270 --- os/pc/vgahiqvideo.c | 274 --- os/pc/vgai81x.c | 282 --- os/pc/vgamach64xx.c | 1250 ------------- os/pc/vgamga2164w.c | 289 --- os/pc/vgamga4xx.c | 603 ------- os/pc/vganeomagic.c | 541 ------ os/pc/vganvidia.c | 373 ---- os/pc/vgargb524.c | 236 --- os/pc/vgas3.c | 620 ------- os/pc/vgasavage.c | 571 ------ os/pc/vgat2r4.c | 586 ------ os/pc/vgatvp3020.c | 216 --- os/pc/vgatvp3026.c | 189 -- os/pc/vgavmware.c | 386 ---- os/pc/vgax.c | 102 -- os/pc/wavelan.c | 1268 ------------- os/pc/wavelan.h | 327 ---- os/pc/x86break.c | 138 -- os/pc/zoran.h | 907 ---------- 128 files changed, 74524 deletions(-) delete mode 100644 os/pc/NOTICE delete mode 100644 os/pc/apbootstrap.h delete mode 100644 os/pc/apbootstrap.s delete mode 100644 os/pc/apic.c delete mode 100644 os/pc/apm.c delete mode 100644 os/pc/apmjump.s delete mode 100644 os/pc/archmp.c delete mode 100644 os/pc/audio.h delete mode 100644 os/pc/cga.c delete mode 100644 os/pc/cgamemscr.c delete mode 100644 os/pc/crystal.h delete mode 100644 os/pc/dat.h delete mode 100644 os/pc/devarch.c delete mode 100644 os/pc/devds1620.c delete mode 100644 os/pc/devether.c delete mode 100644 os/pc/devfloppy.c delete mode 100644 os/pc/devi82365.c delete mode 100644 os/pc/devlm78.c delete mode 100644 os/pc/devlpt.c delete mode 100644 os/pc/devmouse.c delete mode 100644 os/pc/devmpeg.c delete mode 100644 os/pc/devpccard.c delete mode 100644 os/pc/devpnp.c delete mode 100644 os/pc/devrtc.c delete mode 100644 os/pc/devtv.c delete mode 100644 os/pc/devusb.c delete mode 100644 os/pc/devvga.c delete mode 100644 os/pc/devzt5512.c delete mode 100644 os/pc/dma.c delete mode 100644 os/pc/ether2000.c delete mode 100644 os/pc/ether2114x.c delete mode 100644 os/pc/ether589.c delete mode 100644 os/pc/ether79c960.c delete mode 100644 os/pc/ether79c970.c delete mode 100644 os/pc/ether8003.c delete mode 100644 os/pc/ether8139.c delete mode 100644 os/pc/ether82543gc.c delete mode 100644 os/pc/ether82557.c delete mode 100644 os/pc/ether83815.c delete mode 100644 os/pc/ether8390.c delete mode 100644 os/pc/ether8390.h delete mode 100644 os/pc/etherdp83820.c delete mode 100644 os/pc/etherec2t.c delete mode 100644 os/pc/etherelnk3.c delete mode 100644 os/pc/etherga620.c delete mode 100644 os/pc/etherga620fw.h delete mode 100644 os/pc/etherif.h delete mode 100644 os/pc/etherigbe.c delete mode 100644 os/pc/etherrhine.c delete mode 100644 os/pc/ethersmc.c delete mode 100644 os/pc/ethervt6102.c delete mode 100644 os/pc/etherwavelan.c delete mode 100644 os/pc/flashif.h delete mode 100644 os/pc/flashzpc.c delete mode 100644 os/pc/floppy.h delete mode 100644 os/pc/fns.h delete mode 100644 os/pc/fpi.h delete mode 100644 os/pc/fpi387.c delete mode 100644 os/pc/fpsave.s delete mode 100644 os/pc/i8250.c delete mode 100644 os/pc/i8253.c delete mode 100644 os/pc/i8259.c delete mode 100644 os/pc/io.h delete mode 100644 os/pc/kbd.c delete mode 100644 os/pc/l.s delete mode 100644 os/pc/main.c delete mode 100644 os/pc/mem.h delete mode 100644 os/pc/memory.c delete mode 100644 os/pc/mkfile delete mode 100644 os/pc/mmu.c delete mode 100644 os/pc/mouse.c delete mode 100644 os/pc/mp.c delete mode 100644 os/pc/mp.h delete mode 100644 os/pc/pc delete mode 100644 os/pc/pc4e delete mode 100644 os/pc/pcdisk delete mode 100644 os/pc/pci.acid delete mode 100644 os/pc/pci.c delete mode 100644 os/pc/pcidb.acid delete mode 100644 os/pc/pcmciamodem.c delete mode 100644 os/pc/piix4smbus.c delete mode 100644 os/pc/pix delete mode 100644 os/pc/ps2mouse.c delete mode 100644 os/pc/ptclbsum386.s delete mode 100644 os/pc/screen.c delete mode 100644 os/pc/screen.h delete mode 100644 os/pc/sd53c8xx.c delete mode 100644 os/pc/sd53c8xx.i delete mode 100644 os/pc/sd53c8xx.n delete mode 100644 os/pc/sdata.c delete mode 100644 os/pc/sdmylex.c delete mode 100644 os/pc/sdscsi.c delete mode 100644 os/pc/trap.c delete mode 100644 os/pc/tv.h delete mode 100644 os/pc/uarti8250.c delete mode 100644 os/pc/uartisa.c delete mode 100644 os/pc/uartpci.c delete mode 100644 os/pc/usb.h delete mode 100644 os/pc/usbuhci.c delete mode 100644 os/pc/vga.c delete mode 100644 os/pc/vga.h delete mode 100644 os/pc/vga3dfx.c delete mode 100644 os/pc/vgaark2000pv.c delete mode 100644 os/pc/vgabt485.c delete mode 100644 os/pc/vgaclgd542x.c delete mode 100644 os/pc/vgaclgd546x.c delete mode 100644 os/pc/vgact65545.c delete mode 100644 os/pc/vgacyber938x.c delete mode 100644 os/pc/vgaet4000.c delete mode 100644 os/pc/vgahiqvideo.c delete mode 100644 os/pc/vgai81x.c delete mode 100644 os/pc/vgamach64xx.c delete mode 100644 os/pc/vgamga2164w.c delete mode 100644 os/pc/vgamga4xx.c delete mode 100644 os/pc/vganeomagic.c delete mode 100644 os/pc/vganvidia.c delete mode 100644 os/pc/vgargb524.c delete mode 100644 os/pc/vgas3.c delete mode 100644 os/pc/vgasavage.c delete mode 100644 os/pc/vgat2r4.c delete mode 100644 os/pc/vgatvp3020.c delete mode 100644 os/pc/vgatvp3026.c delete mode 100644 os/pc/vgavmware.c delete mode 100644 os/pc/vgax.c delete mode 100644 os/pc/wavelan.c delete mode 100644 os/pc/wavelan.h delete mode 100644 os/pc/x86break.c delete mode 100644 os/pc/zoran.h (limited to 'os/pc') diff --git a/os/pc/NOTICE b/os/pc/NOTICE deleted file mode 100644 index 37a147c1..00000000 --- a/os/pc/NOTICE +++ /dev/null @@ -1,10 +0,0 @@ -Most of these files are adapted from Plan 9 - Copyright © 2002 Lucent Technologies Inc - Copyright © 2021 Plan 9 Foundation -This software was originally authored by employees of Bell Laboratories, -a unit of Nokia Corporation. - -devbench.c, fpi387.c, and flashzpc.c are - Copyright © 1999-2005 Vita Nuova Holdings Ltd - -All of them are covered by the MIT licence (see /NOTICE). diff --git a/os/pc/apbootstrap.h b/os/pc/apbootstrap.h deleted file mode 100644 index 61aca70d..00000000 --- a/os/pc/apbootstrap.h +++ /dev/null @@ -1,15 +0,0 @@ -uchar apbootstrap[]={ -0xea,0x14,0x10,0x00,0x00,0x90,0x90,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x8c,0xc8,0x8e,0xd8,0x0f,0x01,0x16,0xac,0x10,0x0f,0x20,0xc0, -0x83,0xc8,0x01,0x0f,0x22,0xc0,0xeb,0x00,0xb8,0x08,0x00,0x8e,0xd8,0x8e,0xc0,0x8e, -0xe0,0x8e,0xe8,0x8e,0xd0,0x66,0xea,0x3d,0x10,0x00,0x00,0x10,0x00,0x8b,0x0d,0x0c, -0x10,0x00,0x00,0x8b,0x91,0x00,0x08,0x00,0x00,0x89,0x11,0x0f,0x22,0xd9,0x0f,0x20, -0xc2,0x81,0xca,0x00,0x00,0x01,0x80,0x81,0xe2,0xf5,0xff,0xff,0x9f,0xb8,0x67,0x10, -0x00,0x80,0x0f,0x22,0xc2,0xff,0xe0,0x89,0xc8,0x0d,0x00,0x00,0x00,0x80,0xc7,0x00, -0x00,0x00,0x00,0x00,0x0f,0x22,0xd9,0xbc,0xfc,0x5f,0x00,0x80,0x31,0xc0,0x50,0x9d, -0x8b,0x05,0x10,0x10,0x00,0x80,0x89,0x04,0x24,0x8b,0x05,0x08,0x10,0x00,0x80,0xff, -0xd0,0xf4,0xeb,0xfd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00, -0x00,0x92,0xcf,0x00,0xff,0xff,0x00,0x00,0x00,0x9a,0xcf,0x00,0x17,0x00,0x94,0x10, -0x00,0x00, - -}; diff --git a/os/pc/apbootstrap.s b/os/pc/apbootstrap.s deleted file mode 100644 index 3887d71d..00000000 --- a/os/pc/apbootstrap.s +++ /dev/null @@ -1,110 +0,0 @@ -#include "mem.h" - -#define NOP BYTE $0x90 /* NOP */ -#define LGDT(gdtptr) BYTE $0x0F; /* LGDT */ \ - BYTE $0x01; BYTE $0x16; \ - WORD $gdtptr -#define FARJUMP16(s, o) BYTE $0xEA; /* far jump to ptr16:16 */ \ - WORD $o; WORD $s; \ - NOP; NOP; NOP -#define FARJUMP32(s, o) BYTE $0x66; /* far jump to ptr32:16 */ \ - BYTE $0xEA; LONG $o; WORD $s - -#define DELAY BYTE $0xEB; /* JMP .+2 */ \ - BYTE $0x00 -#define INVD BYTE $0x0F; BYTE $0x08 -#define WBINVD BYTE $0x0F; BYTE $0x09 - -/* - * Macros for calculating offsets within the page directory base - * and page tables. Note that these are assembler-specific hence - * the '<<2'. - */ -#define PDO(a) (((((a))>>22) & 0x03FF)<<2) -#define PTO(a) (((((a))>>12) & 0x03FF)<<2) - -/* - * Start an Application Processor. This must be placed on a 4KB boundary - * somewhere in the 1st MB of conventional memory (APBOOTSTRAP). However, - * due to some shortcuts below it's restricted further to within the 1st - * 64KB. The AP starts in real-mode, with - * CS selector set to the startup memory address/16; - * CS base set to startup memory address; - * CS limit set to 64KB; - * CPL and IP set to 0. - */ -TEXT apbootstrap(SB), $0 - FARJUMP16(0, _apbootstrap(SB)) -TEXT _apvector(SB), $0 /* address APBOOTSTRAP+0x08 */ - LONG $0 -TEXT _appdb(SB), $0 /* address APBOOTSTRAP+0x0C */ - LONG $0 -TEXT _apapic(SB), $0 /* address APBOOTSTRAP+0x10 */ - LONG $0 -TEXT _apbootstrap(SB), $0 /* address APBOOTSTRAP+0x14 */ - MOVW CS, AX - MOVW AX, DS /* initialise DS */ - - LGDT(gdtptr(SB)) /* load a basic gdt */ - - MOVL CR0, AX - ORL $1, AX - MOVL AX, CR0 /* turn on protected mode */ - DELAY /* JMP .+2 */ - - BYTE $0xB8; WORD $SELECTOR(1, SELGDT, 0)/* MOVW $SELECTOR(1, SELGDT, 0), AX */ - MOVW AX, DS - MOVW AX, ES - MOVW AX, FS - MOVW AX, GS - MOVW AX, SS - - FARJUMP32(SELECTOR(2, SELGDT, 0), _ap32-KZERO(SB)) - -/* - * For Pentiums and higher, the code that enables paging must come from - * pages that are identity mapped. - * To this end double map KZERO at virtual 0 and undo the mapping once virtual - * nirvana has been obtained. - */ -TEXT _ap32(SB), $0 - MOVL _appdb-KZERO(SB), CX /* physical address of PDB */ - MOVL (PDO(KZERO))(CX), DX /* double-map KZERO at 0 */ - MOVL DX, (PDO(0))(CX) - MOVL CX, CR3 /* load and flush the mmu */ - - MOVL CR0, DX - ORL $0x80010000, DX /* PG|WP */ - ANDL $~0x6000000A, DX /* ~(CD|NW|TS|MP) */ - - MOVL $_appg(SB), AX - MOVL DX, CR0 /* turn on paging */ - JMP* AX - -TEXT _appg(SB), $0 - MOVL CX, AX /* physical address of PDB */ - ORL $KZERO, AX - MOVL $0, (PDO(0))(AX) /* undo double-map of KZERO at 0 */ - MOVL CX, CR3 /* load and flush the mmu */ - - MOVL $(MACHADDR+MACHSIZE-4), SP - - MOVL $0, AX - PUSHL AX - POPFL - - MOVL _apapic(SB), AX - MOVL AX, (SP) - MOVL _apvector(SB), AX - CALL* AX -_aphalt: - HLT - JMP _aphalt - -TEXT gdt(SB), $0 - LONG $0x0000; LONG $0 - LONG $0xFFFF; LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) - LONG $0xFFFF; LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) -TEXT gdtptr(SB), $0 - WORD $(3*8-1) - LONG $gdt-KZERO(SB) diff --git a/os/pc/apic.c b/os/pc/apic.c deleted file mode 100644 index ffb24584..00000000 --- a/os/pc/apic.c +++ /dev/null @@ -1,378 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#include "mp.h" - -enum { /* Local APIC registers */ - LapicID = 0x0020, /* ID */ - LapicVER = 0x0030, /* Version */ - LapicTPR = 0x0080, /* Task Priority */ - LapicAPR = 0x0090, /* Arbitration Priority */ - LapicPPR = 0x00A0, /* Processor Priority */ - LapicEOI = 0x00B0, /* EOI */ - LapicLDR = 0x00D0, /* Logical Destination */ - LapicDFR = 0x00E0, /* Destination Format */ - LapicSVR = 0x00F0, /* Spurious Interrupt Vector */ - LapicISR = 0x0100, /* Interrupt Status (8 registers) */ - LapicTMR = 0x0180, /* Trigger Mode (8 registers) */ - LapicIRR = 0x0200, /* Interrupt Request (8 registers) */ - LapicESR = 0x0280, /* Error Status */ - LapicICRLO = 0x0300, /* Interrupt Command */ - LapicICRHI = 0x0310, /* Interrupt Command [63:32] */ - LapicTIMER = 0x0320, /* Local Vector Table 0 (TIMER) */ - LapicPCINT = 0x0340, /* Performance COunter LVT */ - LapicLINT0 = 0x0350, /* Local Vector Table 1 (LINT0) */ - LapicLINT1 = 0x0360, /* Local Vector Table 2 (LINT1) */ - LapicERROR = 0x0370, /* Local Vector Table 3 (ERROR) */ - LapicTICR = 0x0380, /* Timer Initial Count */ - LapicTCCR = 0x0390, /* Timer Current Count */ - LapicTDCR = 0x03E0, /* Timer Divide Configuration */ -}; - -enum { /* LapicSVR */ - LapicENABLE = 0x00000100, /* Unit Enable */ - LapicFOCUS = 0x00000200, /* Focus Processor Checking Disable */ -}; - -enum { /* LapicICRLO */ - /* [14] IPI Trigger Mode Level (RW) */ - LapicDEASSERT = 0x00000000, /* Deassert level-sensitive interrupt */ - LapicASSERT = 0x00004000, /* Assert level-sensitive interrupt */ - - /* [17:16] Remote Read Status */ - LapicINVALID = 0x00000000, /* Invalid */ - LapicWAIT = 0x00010000, /* In-Progress */ - LapicVALID = 0x00020000, /* Valid */ - - /* [19:18] Destination Shorthand */ - LapicFIELD = 0x00000000, /* No shorthand */ - LapicSELF = 0x00040000, /* Self is single destination */ - LapicALLINC = 0x00080000, /* All including self */ - LapicALLEXC = 0x000C0000, /* All Excluding self */ -}; - -enum { /* LapicESR */ - LapicSENDCS = 0x00000001, /* Send CS Error */ - LapicRCVCS = 0x00000002, /* Receive CS Error */ - LapicSENDACCEPT = 0x00000004, /* Send Accept Error */ - LapicRCVACCEPT = 0x00000008, /* Receive Accept Error */ - LapicSENDVECTOR = 0x00000020, /* Send Illegal Vector */ - LapicRCVVECTOR = 0x00000040, /* Receive Illegal Vector */ - LapicREGISTER = 0x00000080, /* Illegal Register Address */ -}; - -enum { /* LapicTIMER */ - /* [17] Timer Mode (RW) */ - LapicONESHOT = 0x00000000, /* One-shot */ - LapicPERIODIC = 0x00020000, /* Periodic */ - - /* [19:18] Timer Base (RW) */ - LapicCLKIN = 0x00000000, /* use CLKIN as input */ - LapicTMBASE = 0x00040000, /* use TMBASE */ - LapicDIVIDER = 0x00080000, /* use output of the divider */ -}; - -enum { /* LapicTDCR */ - LapicX2 = 0x00000000, /* divide by 2 */ - LapicX4 = 0x00000001, /* divide by 4 */ - LapicX8 = 0x00000002, /* divide by 8 */ - LapicX16 = 0x00000003, /* divide by 16 */ - LapicX32 = 0x00000008, /* divide by 32 */ - LapicX64 = 0x00000009, /* divide by 64 */ - LapicX128 = 0x0000000A, /* divide by 128 */ - LapicX1 = 0x0000000B, /* divide by 1 */ -}; - -static ulong* lapicbase; - -struct -{ - uvlong hz; - ulong max; - ulong min; - ulong div; -} lapictimer; - -static int -lapicr(int r) -{ - return *(lapicbase+(r/sizeof(*lapicbase))); -} - -static void -lapicw(int r, int data) -{ - *(lapicbase+(r/sizeof(*lapicbase))) = data; - data = *(lapicbase+(LapicID/sizeof(*lapicbase))); - USED(data); -} - -void -lapiconline(void) -{ - /* - * Reload the timer to de-synchronise the processors, - * then lower the task priority to allow interrupts to be - * accepted by the APIC. - */ - microdelay((TK2MS(1)*1000/conf.nmach) * m->machno); - lapicw(LapicTICR, lapictimer.max); - lapicw(LapicTIMER, LapicCLKIN|LapicPERIODIC|(VectorPIC+IrqTIMER)); - - lapicw(LapicTPR, 0); -} - -/* - * use the i8253 clock to figure out our lapic timer rate. - */ -static void -lapictimerinit(void) -{ - uvlong x, v, hz; - - v = m->cpuhz/1000; - lapicw(LapicTDCR, LapicX1); - lapicw(LapicTIMER, ApicIMASK|LapicCLKIN|LapicONESHOT|(VectorPIC+IrqTIMER)); - - if(lapictimer.hz == 0ULL){ - x = fastticks(&hz); - x += hz/10; - lapicw(LapicTICR, 0xffffffff); - do{ - v = fastticks(nil); - }while(v < x); - - lapictimer.hz = (0xffffffffUL-lapicr(LapicTCCR))*10; - lapictimer.max = lapictimer.hz/HZ; - lapictimer.min = lapictimer.hz/(100*HZ); - - if(lapictimer.hz > hz) - panic("lapic clock faster than cpu clock"); - lapictimer.div = hz/lapictimer.hz; - } -} - -void -lapicinit(Apic* apic) -{ - ulong r, lvt; - - if(lapicbase == 0) - lapicbase = apic->addr; - - lapicw(LapicDFR, 0xFFFFFFFF); - r = (lapicr(LapicID)>>24) & 0xFF; - lapicw(LapicLDR, (1<cpuidax & 0xFFF){ - case 0x526: /* stepping cB1 */ - case 0x52B: /* stepping E0 */ - case 0x52C: /* stepping cC0 */ - wrmsr(0x0E, 1<<14); /* TR12 */ - break; - } - - /* - * Set the local interrupts. It's likely these should just be - * masked off for SMP mode as some Pentium Pros have problems if - * LINT[01] are set to ExtINT. - * Acknowledge any outstanding interrupts. - lapicw(LapicLINT0, apic->lintr[0]); - lapicw(LapicLINT1, apic->lintr[1]); - */ - lapiceoi(0); - - lvt = (lapicr(LapicVER)>>16) & 0xFF; - if(lvt >= 4) - lapicw(LapicPCINT, ApicIMASK); - lapicw(LapicERROR, VectorPIC+IrqERROR); - lapicw(LapicESR, 0); - lapicr(LapicESR); - - /* - * Issue an INIT Level De-Assert to synchronise arbitration ID's. - */ - lapicw(LapicICRHI, 0); - lapicw(LapicICRLO, LapicALLINC|ApicLEVEL|LapicDEASSERT|ApicINIT); - while(lapicr(LapicICRLO) & ApicDELIVS) - ; - - /* - * Do not allow acceptance of interrupts until all initialisation - * for this processor is done. For the bootstrap processor this can be - * early duing initialisation. For the application processors this should - * be after the bootstrap processor has lowered priority and is accepting - * interrupts. - lapicw(LapicTPR, 0); - */ -} - -void -lapicstartap(Apic* apic, int v) -{ - int crhi, i; - - crhi = apic->apicno<<24; - lapicw(LapicICRHI, crhi); - lapicw(LapicICRLO, LapicFIELD|ApicLEVEL|LapicASSERT|ApicINIT); - microdelay(200); - lapicw(LapicICRLO, LapicFIELD|ApicLEVEL|LapicDEASSERT|ApicINIT); - delay(10); - - for(i = 0; i < 2; i++){ - lapicw(LapicICRHI, crhi); - lapicw(LapicICRLO, LapicFIELD|ApicEDGE|ApicSTARTUP|(v/BY2PG)); - microdelay(200); - } -} - -void -lapicerror(Ureg*, void*) -{ - int esr; - - lapicw(LapicESR, 0); - esr = lapicr(LapicESR); - switch(m->cpuidax & 0xFFF){ - case 0x526: /* stepping cB1 */ - case 0x52B: /* stepping E0 */ - case 0x52C: /* stepping cC0 */ - return; - } - print("cpu%d: lapicerror: 0x%8.8uX\n", m->machno, esr); -} - -void -lapicspurious(Ureg*, void*) -{ - print("cpu%d: lapicspurious\n", m->machno); -} - -int -lapicisr(int v) -{ - int isr; - - isr = lapicr(LapicISR + (v/32)); - - return isr & (1<<(v%32)); -} - -int -lapiceoi(int v) -{ - lapicw(LapicEOI, 0); - - return v; -} - -void -lapicicrw(int hi, int lo) -{ - lapicw(LapicICRHI, hi); - lapicw(LapicICRLO, lo); -} - -void -ioapicrdtr(Apic* apic, int sel, int* hi, int* lo) -{ - ulong *iowin; - - iowin = apic->addr+(0x10/sizeof(ulong)); - sel = IoapicRDT + 2*sel; - - lock(apic); - *apic->addr = sel+1; - if(hi) - *hi = *iowin; - *apic->addr = sel; - if(lo) - *lo = *iowin; - unlock(apic); -} - -void -ioapicrdtw(Apic* apic, int sel, int hi, int lo) -{ - ulong *iowin; - - iowin = apic->addr+(0x10/sizeof(ulong)); - sel = IoapicRDT + 2*sel; - - lock(apic); - *apic->addr = sel+1; - *iowin = hi; - *apic->addr = sel; - *iowin = lo; - unlock(apic); -} - -void -ioapicinit(Apic* apic, int apicno) -{ - int hi, lo, v; - ulong *iowin; - - /* - * Initialise the I/O APIC. - * The MultiProcessor Specification says it is the responsibility - * of the O/S to set the APIC id. - * Make sure interrupts are all masked off for now. - */ - iowin = apic->addr+(0x10/sizeof(ulong)); - lock(apic); - *apic->addr = IoapicVER; - apic->mre = (*iowin>>16) & 0xFF; - - *apic->addr = IoapicID; - *iowin = apicno<<24; - unlock(apic); - - hi = 0; - lo = ApicIMASK; - for(v = 0; v <= apic->mre; v++) - ioapicrdtw(apic, v, hi, lo); -} - -void -lapictimerset(uvlong next) -{ - vlong period; - int x; - - x = splhi(); - lock(&m->apictimerlock); - - period = lapictimer.max; - if(next != 0){ - period = next - fastticks(nil); - period /= lapictimer.div; - - if(period < lapictimer.min) - period = lapictimer.min; - else if(period > lapictimer.max - lapictimer.min) - period = lapictimer.max; - } - lapicw(LapicTICR, period); - - unlock(&m->apictimerlock); - splx(x); -} - -void -lapicclock(Ureg *u, void*) -{ - timerintr(u, 0); -} diff --git a/os/pc/apm.c b/os/pc/apm.c deleted file mode 100644 index 2ea18b4d..00000000 --- a/os/pc/apm.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Interface to Advanced Power Management 1.2 BIOS - * - * This is, in many ways, a giant hack, and when things settle down - * a bit and standardize, hopefully we can write a driver that deals - * more directly with the hardware and thus might be a bit cleaner. - * - * ACPI might be the answer, but at the moment this is simpler - * and more widespread. - */ - -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" - -extern int apmfarcall(ushort, ulong, Ureg*); /* apmjump.s */ - -static int -getreg(ulong *reg, ISAConf *isa, char *name) -{ - int i; - int nl; - - nl = strlen(name); - for(i=0; inopt; i++){ - if(cistrncmp(isa->opt[i], name, nl)==0 && isa->opt[i][nl] == '='){ - *reg = strtoul(isa->opt[i]+nl+1, nil, 16); - return 0; - } - } - return -1; -} - -/* - * Segment descriptors look like this. - * - * d1: [base 31:24] [gran] [is32bit] [0] [unused] [limit 19:16] - [present] [privlev] [type 3:0] [base 23:16] - * d0: [base 15:00] [limit 15:00] - * - * gran is 0 for 1-byte granularity, 1 for 4k granularity - * type is 0 for system segment, 1 for code/data. - * - * clearly we know way too much about the memory unit. - * however, knowing this much about the memory unit - * means that the memory unit need not know anything - * about us. - * - * what a crock. - */ -static void -setgdt(int sel, ulong base, ulong limit, int flag) -{ - if(sel < 0 || sel >= NGDT) - panic("setgdt"); - - base = (ulong)KADDR(base); - m->gdt[sel].d0 = (base<<16) | (limit&0xFFFF); - m->gdt[sel].d1 = (base&0xFF000000) | (limit&0x000F0000) | - ((base>>16)&0xFF) | SEGP | SEGPL(0) | flag; -} - -static ulong ax, cx, dx, di, ebx, esi; -static Ureg apmu; -static long -apmread(Chan*, void *a, long n, vlong off) -{ - if(off < 0) - error("badarg"); - - if(n+off > sizeof apmu) - n = sizeof apmu - off; - if(n <= 0) - return 0; - memmove(a, (char*)&apmu+off, n); - return n; -} - -static long -apmwrite(Chan*, void *a, long n, vlong off) -{ - int s; - if(off || n != sizeof apmu) - error("write a Ureg"); - - memmove(&apmu, a, sizeof apmu); - s = splhi(); - apmfarcall(APMCSEL, ebx, &apmu); - splx(s); - return n; -} - -void -apmlink(void) -{ - ISAConf isa; - char *s; - - if(isaconfig("apm", 0, &isa) == 0) - return; - - /* - * APM info passed from boot loader. - * Now we need to set up the GDT entries for APM. - * - * AX = 32-bit code segment base address - * EBX = 32-bit code segment offset - * CX = 16-bit code segment base address - * DX = 32-bit data segment base address - * ESI = <16-bit code segment length> <32-bit code segment length> (hi then lo) - * DI = 32-bit data segment length - */ - - if(getreg(&ax, &isa, s="ax") < 0 - || getreg(&ebx, &isa, s="ebx") < 0 - || getreg(&cx, &isa, s="cx") < 0 - || getreg(&dx, &isa, s="dx") < 0 - || getreg(&esi, &isa, s="esi") < 0 - || getreg(&di, &isa, s="di") < 0){ - print("apm: missing register %s\n", s); - return; - } - - /* - * The NEC Versa SX bios does not report the correct 16-bit code - * segment length when loaded directly from mbr -> 9load (as compared - * with going through ld.com). We'll make both code segments 64k-1 bytes. - */ - esi = 0xFFFFFFFF; - - /* - * We are required by the BIOS to set up three consecutive segments, - * one for the APM 32-bit code, one for the APM 16-bit code, and - * one for the APM data. The BIOS handler uses the code segment it - * get called with to determine the other two segment selector. - */ - setgdt(APMCSEG, ax<<4, ((esi&0xFFFF)-1)&0xFFFF, SEGEXEC|SEGR|SEGD); - setgdt(APMCSEG16, cx<<4, ((esi>>16)-1)&0xFFFF, SEGEXEC|SEGR); - setgdt(APMDSEG, dx<<4, (di-1)&0xFFFF, SEGDATA|SEGW|SEGD); - - addarchfile("apm", 0660, apmread, apmwrite); - -print("apm0: configured cbase %.8lux off %.8lux\n", ax<<4, ebx); - - return; -} - diff --git a/os/pc/apmjump.s b/os/pc/apmjump.s deleted file mode 100644 index 6dbd19d0..00000000 --- a/os/pc/apmjump.s +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Far call, absolute indirect. - * The argument is the offset. - * We use a global structure for the jump params, - * so this is *not* reentrant or thread safe. - */ - -#include "mem.h" - -#define SSOVERRIDE BYTE $0x36 -#define CSOVERRIDE BYTE $0x2E -#define RETF BYTE $0xCB - -GLOBL apmjumpstruct+0(SB), $8 - -TEXT fortytwo(SB), $0 - MOVL $42, AX - RETF - -TEXT getcs(SB), $0 - PUSHL CS - POPL AX - RET - -TEXT apmfarcall(SB), $0 - /* - * We call push and pop ourselves. - * As soon as we do the first push or pop, - * we can't use FP anymore. - */ - MOVL off+4(FP), BX - MOVL seg+0(FP), CX - MOVL BX, apmjumpstruct+0(SB) - MOVL CX, apmjumpstruct+4(SB) - - /* load necessary registers from Ureg */ - MOVL ureg+8(FP), DI - MOVL 28(DI), AX - MOVL 16(DI), BX - MOVL 24(DI), CX - MOVL 20(DI), DX - - /* save registers, segments */ - PUSHL DS - PUSHL ES - PUSHL FS - PUSHL GS - PUSHL BP - PUSHL DI - - /* - * paranoia: zero the segments, since it's the - * BIOS's responsibility to initialize them. - * (trick picked up from Linux driver). - PUSHL DX - XORL DX, DX - PUSHL DX - POPL DS - PUSHL DX - POPL ES - PUSHL DX - POPL FS - PUSHL DX - POPL GS - POPL DX - */ - - PUSHL $APMDSEG - POPL DS - - /* - * The actual call. - */ - CSOVERRIDE; BYTE $0xFF; BYTE $0x1D - LONG $apmjumpstruct+0(SB) - - /* restore segments, registers */ - POPL DI - POPL BP - POPL GS - POPL FS - POPL ES - POPL DS - - PUSHFL - POPL 64(DI) - - /* store interesting registers back in Ureg */ - MOVL AX, 28(DI) - MOVL BX, 16(DI) - MOVL CX, 24(DI) - MOVL DX, 20(DI) - MOVL SI, 4(DI) - - PUSHFL - POPL AX - ANDL $1, AX /* carry flag */ - RET diff --git a/os/pc/archmp.c b/os/pc/archmp.c deleted file mode 100644 index fbbda091..00000000 --- a/os/pc/archmp.c +++ /dev/null @@ -1,138 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#include "mp.h" - -#define cpuserver 1 - -_MP_ *_mp_; - -static _MP_* -mpscan(uchar *addr, int len) -{ - uchar *e, *p, sum; - int i; - - e = addr+len; - for(p = addr; p < e; p += sizeof(_MP_)){ - if(memcmp(p, "_MP_", 4)) - continue; - sum = 0; - for(i = 0; i < sizeof(_MP_); i++) - sum += p[i]; - if(sum == 0) - return (_MP_*)p; - } - return 0; -} - -static _MP_* -mpsearch(void) -{ - uchar *bda; - ulong p; - _MP_ *mp; - - /* - * Search for the MP Floating Pointer Structure: - * 1) in the first KB of the EBDA; - * 2) in the last KB of system base memory; - * 3) in the BIOS ROM between 0xE0000 and 0xFFFFF. - */ - bda = KADDR(0x400); - if((p = (bda[0x0F]<<8)|bda[0x0E])){ - if(mp = mpscan(KADDR(p), 1024)) - return mp; - } - else{ - p = ((bda[0x14]<<8)|bda[0x13])*1024; - if(mp = mpscan(KADDR(p-1024), 1024)) - return mp; - } - return mpscan(KADDR(0xF0000), 0x10000); -} - -static int identify(void); - -PCArch archmp = { -.id= "_MP_", -.ident= identify, -.reset= mpshutdown, -.intrinit= mpinit, -.intrenable= mpintrenable, -.fastclock= i8253read, -.timerset= lapictimerset, -}; - -static int -identify(void) -{ - PCMP *pcmp; - uchar *p, sum; - ulong length; - - if(getconf("*nomp")) - return 1; - - /* - * Search for an MP configuration table. For now, - * don't accept the default configurations (physaddr == 0). - * Check for correct signature, calculate the checksum and, - * if correct, check the version. - * To do: check extended table checksum. - */ - if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0) - return 1; - - pcmp = KADDR(_mp_->physaddr); - if(memcmp(pcmp, "PCMP", 4)) - return 1; - - length = pcmp->length; - sum = 0; - for(p = (uchar*)pcmp; length; length--) - sum += *p++; - - if(sum || (pcmp->version != 1 && pcmp->version != 4)) - return 1; - - if(cpuserver && m->havetsc) - archmp.fastclock = tscticks; - return 0; -} - -Lock mpsynclock; - -void -syncclock(void) -{ - uvlong x; - - if(arch->fastclock != tscticks) - return; - - if(m->machno == 0){ - wrmsr(0x10, 0); - m->tscticks = 0; - } else { - x = MACHP(0)->tscticks; - while(x == MACHP(0)->tscticks) - ; - wrmsr(0x10, MACHP(0)->tscticks); - cycles(&m->tscticks); - } -} - -uvlong -tscticks(uvlong *hz) -{ - if(hz != nil) - *hz = m->cpuhz; - - cycles(&m->tscticks); /* Uses the rdtsc instruction */ - return m->tscticks; -} diff --git a/os/pc/audio.h b/os/pc/audio.h deleted file mode 100644 index d06c7bcc..00000000 --- a/os/pc/audio.h +++ /dev/null @@ -1,15 +0,0 @@ -enum -{ - Bufsize = 1024, /* 5.8 ms each, must be power of two */ - Nbuf = 128, /* .74 seconds total */ - Dma = 6, - IrqAUDIO = 7, - SBswab = 0, -}; - -#define seteisadma(a, b) dmainit(a, Bufsize); -#define CACHELINESZ 8 -#define UNCACHED(type, v) (type*)((ulong)(v)) - -#define Int0vec -#define setvec(v, f, a) intrenable(v, f, a, BUSUNKNOWN, "audio") diff --git a/os/pc/cga.c b/os/pc/cga.c deleted file mode 100644 index 6365d44c..00000000 --- a/os/pc/cga.c +++ /dev/null @@ -1,127 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -enum { - Black, - Blue, - Green, - Cyan, - Red, - Magenta, - Brown, - Grey, - - Bright = 0x08, - Blinking = 0x80, - - Yellow = Bright|Brown, - White = Bright|Grey, -}; - -enum { - Width = 80*2, - Height = 25, - - Attr = (Black<<4)|Grey, /* high nibble background - * low foreground - */ -}; - -#define CGASCREENBASE ((uchar*)KADDR(0xB8000)) - -static int cgapos; -static Lock cgascreenlock; - -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, (cgapos/2>>8) & 0xFF); - cgaregw(0x0F, cgapos/2 & 0xFF); - CGASCREENBASE[cgapos+1] = Attr; -} - -static void -cgascreenputc(int c) -{ - int i; - uchar *p; - - if(c == '\n'){ - cgapos = cgapos/Width; - cgapos = (cgapos+1)*Width; - } - else if(c == '\t'){ - i = 8 - ((cgapos/2)&7); - while(i-->0) - cgascreenputc(' '); - } - else if(c == '\b'){ - if(cgapos >= 2) - cgapos -= 2; - cgascreenputc(' '); - cgapos -= 2; - } - else{ - CGASCREENBASE[cgapos++] = c; - CGASCREENBASE[cgapos++] = Attr; - } - if(cgapos >= Width*Height){ - memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1)); - p = &CGASCREENBASE[Width*(Height-1)]; - for(i=0; i 0) - cgascreenputc(*s++); - - unlock(&cgascreenlock); -} - -void -screeninit(void) -{ - - cgapos = cgaregr(0x0E)<<8; - cgapos |= cgaregr(0x0F); - cgapos *= 2; - - screenputs = cgascreenputs; -} diff --git a/os/pc/cgamemscr.c b/os/pc/cgamemscr.c deleted file mode 100644 index 7509614a..00000000 --- a/os/pc/cgamemscr.c +++ /dev/null @@ -1,203 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#include -#include -#include - -enum { - Width = 160, - Height = 25, - - Attr = 7, /* white on black */ -}; - -#define CGASCREENBASE ((uchar*)KADDR(0xB8000)) - -static int cgapos; -static int screeninitdone; -static Lock cgascreenlock; -void (*vgascreenputc)(char*); - -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, (cgapos/2>>8) & 0xFF); - cgaregw(0x0F, cgapos/2 & 0xFF); - CGASCREENBASE[cgapos+1] = Attr; -} - -static void -cgascreenputc(int c) -{ - int i; - - if(c == '\n'){ - cgapos = cgapos/Width; - cgapos = (cgapos+1)*Width; - } - else if(c == '\t'){ - i = 8 - ((cgapos/2)&7); - while(i-->0) - cgascreenputc(' '); - } - else if(c == '\b'){ - if(cgapos >= 2) - cgapos -= 2; - cgascreenputc(' '); - cgapos -= 2; - } - else{ - CGASCREENBASE[cgapos++] = c; - CGASCREENBASE[cgapos++] = Attr; - } - if(cgapos >= Width*Height){ - memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1)); - memset(&CGASCREENBASE[Width*(Height-1)], 0, Width); - cgapos = Width*(Height-1); - } - movecursor(); -} - -void -screeninit(void) -{ - memimageinit(); - cgapos = cgaregr(0x0E)<<8; - cgapos |= cgaregr(0x0F); - cgapos *= 2; - screeninitdone = 1; -} - -void -cgascreenputs(char* s, int n) -{ - int i; - Rune r; - char buf[4]; - - if(!islo()){ - if(!canlock(&cgascreenlock)) - return; - } - else - lock(&cgascreenlock); - - if(vgascreenputc == nil){ - while(n-- > 0) - cgascreenputc(*s++); - unlock(&cgascreenlock); - return; - } - - while(n > 0) { - i = chartorune(&r, s); - if(i == 0){ - s++; - --n; - continue; - } - memmove(buf, s, i); - buf[i] = 0; - n -= i; - s += i; - vgascreenputc(buf); - } - - unlock(&cgascreenlock); -} - -void -cursorenable(void) -{ -} - -void -cursordisable(void) -{ -} - -typedef struct Drawcursor Drawcursor; - - - -void -cursorupdate(Rectangle r) -{ - USED(r); -} - -void -drawcursor(Drawcursor *c) -{ - USED(c); -} - -uchar* -attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen) -{ - static Rectangle screenr = {0, 0, 0, 0}; - static uchar *bdata; - if (bdata == nil) - if ((bdata = malloc(1)) == nil) - return nil; - *r = screenr; - *chan = RGB24; - *d = chantodepth(RGB24); - *width = 0; - *softscreen = 0; - return bdata; -} - -void -flushmemscreen(Rectangle r) -{ - USED(r); -} - -void -blankscreen(int i) -{ - USED(i); -} - -void -getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb) -{ - USED(p); - USED(pr); - USED(pg); - USED(pb); - -} - -int -setcolor(ulong p, ulong r, ulong g, ulong b) -{ - USED(p); - USED(r); - USED(g); - USED(b); - return ~0; -} - -void (*screenputs)(char*, int) = cgascreenputs; diff --git a/os/pc/crystal.h b/os/pc/crystal.h deleted file mode 100644 index 63152c8f..00000000 --- a/os/pc/crystal.h +++ /dev/null @@ -1,1118 +0,0 @@ -/* - * Micro code for the crystal musicam decoder on the Boffin MPEG decoder - */ -static -uchar crystal[] = -{ - 0x10,0x10,0x06,0x00,0x00,0x00,0x00,0x00,0x03,0xa0,0x00,0x1a,0x9f,0x00,0x39,0x5f, - 0x00,0xfe,0x9f,0x02,0x84,0x1f,0x03,0x35,0xbf,0x12,0x4e,0x1f,0x24,0xa3,0xc0,0xed, - 0xb1,0xe1,0x03,0x35,0xbf,0xfd,0x7b,0xe1,0x00,0xfe,0x9f,0xff,0xc6,0xa1,0x00,0x1a, - 0x9f,0xff,0xfc,0x60,0xff,0xff,0xe0,0x00,0x03,0x40,0x00,0x19,0xff,0x00,0x32,0x1f, - 0x01,0x01,0xe0,0x02,0x56,0x7f,0x03,0x7b,0xbf,0x11,0x66,0xff,0x24,0x9d,0xff,0xec, - 0xcb,0x00,0x02,0xe8,0xdf,0xfd,0x4e,0x61,0x00,0xf9,0xff,0xff,0xbf,0x20,0x00,0x1b, - 0x3f,0xff,0xfc,0x21,0xff,0xff,0xe0,0x00,0x03,0x00,0x00,0x19,0x3f,0x00,0x2b,0x60, - 0x01,0x03,0xff,0x02,0x29,0x20,0x03,0xba,0xff,0x10,0x7f,0xdf,0x24,0x8c,0xff,0xeb, - 0xe5,0x01,0x02,0x95,0x00,0xfd,0x21,0x20,0x00,0xf3,0xff,0xff,0xb7,0x61,0x00,0x1b, - 0xbf,0xff,0xfb,0xa0,0xff,0xff,0xe0,0x00,0x02,0xa0,0x00,0x18,0x80,0x00,0x24,0xc0, - 0x01,0x04,0xe0,0x01,0xfb,0xe0,0x03,0xf3,0x7f,0x0f,0x99,0x5f,0x24,0x70,0xc0,0xeb, - 0x00,0x41,0x02,0x3a,0x20,0xfc,0xf4,0x61,0x00,0xec,0xa0,0xff,0xaf,0x60,0x00,0x1c, - 0x20,0xff,0xfb,0x40,0xff,0xff,0xe0,0x00,0x02,0x60,0x00,0x17,0xc0,0x00,0x1e,0x80, - 0x01,0x04,0x9f,0x01,0xcf,0x1f,0x04,0x25,0x80,0x0e,0xb3,0xff,0x24,0x49,0x20,0xea, - 0x1d,0x60,0x01,0xd7,0xff,0xfc,0xc8,0x61,0x00,0xe3,0xc0,0xff,0xa7,0x21,0x00,0x1c, - 0x5f,0xff,0xfa,0xe1,0xff,0xff,0xe0,0x00,0x02,0x1f,0x00,0x16,0xdf,0x00,0x18,0x9f, - 0x01,0x03,0x5f,0x01,0xa2,0xdf,0x04,0x50,0xff,0x0d,0xd0,0x20,0x24,0x16,0x7f,0xe9, - 0x3c,0xe0,0x01,0x6e,0xe0,0xfc,0x9d,0x21,0x00,0xd9,0x5f,0xff,0x9e,0xa0,0x00,0x1c, - 0x80,0xff,0xfa,0x60,0xff,0xff,0xe0,0x00,0x02,0x00,0x00,0x16,0x00,0x00,0x13,0x20, - 0x01,0x01,0x1f,0x01,0x77,0x7f,0x04,0x76,0x5f,0x0c,0xee,0x40,0x23,0xd8,0xdf,0xe8, - 0x5f,0x40,0x00,0xfe,0x9f,0xfc,0x73,0x21,0x00,0xcd,0x7f,0xff,0x96,0x01,0x00,0x1c, - 0x80,0xff,0xf9,0xe0,0xff,0xff,0xc0,0x00,0x01,0xbf,0x00,0x15,0x1f,0x00,0x0d,0xe0, - 0x00,0xfd,0xff,0x01,0x4c,0xdf,0x04,0x95,0xa0,0x0c,0x0e,0xbf,0x23,0x90,0x5f,0xe7, - 0x84,0xe1,0x00,0x87,0x40,0xfc,0x4a,0x60,0x00,0xbf,0xdf,0xff,0x8d,0x21,0x00,0x1c, - 0x5f,0xff,0xf9,0x60,0xff,0xff,0xc0,0x00,0x01,0x9f,0x00,0x14,0x1f,0x00,0x09,0x00, - 0x00,0xfa,0x20,0x01,0x23,0x40,0x04,0xaf,0x00,0x0b,0x32,0x1f,0x23,0x3d,0x20,0xe6, - 0xae,0x61,0x00,0x08,0xbf,0xfc,0x23,0x41,0x00,0xb0,0xc0,0xff,0x84,0x20,0x00,0x1c, - 0x00,0xff,0xf8,0xc0,0xff,0xff,0xc0,0x00,0x01,0x60,0x00,0x13,0x40,0x00,0x04,0x7f, - 0x00,0xf5,0x3f,0x00,0xfa,0xc0,0x04,0xc2,0xbf,0x0a,0x58,0x9f,0x22,0xdf,0x80,0xe5, - 0xdc,0x40,0xff,0x83,0x41,0xfb,0xfd,0xe1,0x00,0xa0,0x00,0xff,0x7b,0x00,0x00,0x1b, - 0x9f,0xff,0xf8,0x20,0xff,0xff,0xc0,0x00,0x01,0x40,0x00,0x12,0x60,0x00,0x00,0x40, - 0x00,0xef,0xdf,0x00,0xd3,0x7f,0x04,0xd0,0xe0,0x09,0x82,0xbf,0x22,0x77,0xc0,0xe5, - 0x0e,0xc0,0xfe,0xf6,0xc1,0xfb,0xda,0xa0,0x00,0x8d,0x5f,0xff,0x71,0xe1,0x00,0x1a, - 0xe0,0xff,0xf7,0x80,0xff,0xff,0xa1,0x00,0x01,0x1f,0x00,0x11,0x60,0xff,0xfc,0x60, - 0x00,0xe9,0xc0,0x00,0xad,0x7f,0x04,0xd9,0xdf,0x08,0xb0,0xe0,0x22,0x05,0xdf,0xe4, - 0x46,0xc1,0xfe,0x63,0x80,0xfb,0xb9,0xa1,0x00,0x79,0x3f,0xff,0x68,0xc0,0x00,0x19, - 0xff,0xff,0xf6,0xe0,0xff,0xff,0xa1,0x00,0x00,0xff,0x00,0x10,0x7f,0xff,0xf8,0xe0, - 0x00,0xe3,0x20,0x00,0x88,0xdf,0x04,0xdd,0xc0,0x07,0xe3,0x5f,0x21,0x8a,0x7f,0xe3, - 0x84,0x61,0xfd,0xc9,0x60,0xfb,0x9b,0x40,0x00,0x63,0x40,0xff,0x5f,0xa1,0x00,0x19, - 0x00,0xff,0xf6,0x21,0xff,0xff,0x81,0x00,0x00,0xe0,0x00,0x0f,0xa0,0xff,0xf5,0xa1, - 0x00,0xdb,0xe0,0x00,0x65,0xbf,0x04,0xdc,0xdf,0x07,0x1a,0x7f,0x21,0x05,0xa0,0xe2, - 0xc8,0x40,0xfd,0x28,0xc0,0xfb,0x7f,0xa1,0x00,0x4b,0x9f,0xff,0x56,0x80,0x00,0x17, - 0x9f,0xff,0xf5,0x61,0xff,0xff,0x81,0x00,0x00,0xe0,0x00,0x0e,0x9f,0xff,0xf2,0xc0, - 0x00,0xd4,0x40,0x00,0x44,0x1f,0x04,0xd7,0x7f,0x06,0x56,0x7f,0x20,0x77,0xc0,0xe2, - 0x12,0xe0,0xfc,0x81,0xc0,0xfb,0x67,0x00,0x00,0x32,0x3f,0xff,0x4d,0x80,0x00,0x16, - 0x20,0xff,0xf4,0xa0,0xff,0xff,0x60,0x00,0x00,0xc0,0x00,0x0d,0xe0,0xff,0xf0,0x21, - 0x00,0xcc,0x3f,0x00,0x23,0xff,0x04,0xcd,0xc0,0x05,0x97,0xe0,0x1f,0xe1,0x40,0xe1, - 0x64,0x80,0xfb,0xd4,0x80,0xfb,0x51,0xe1,0x00,0x17,0x20,0xff,0x44,0xc1,0x00,0x14, - 0x60,0xff,0xf3,0xe0,0xff,0xff,0x60,0x00,0x00,0xa0,0x00,0x0c,0xff,0xff,0xed,0xc1, - 0x00,0xc3,0xdf,0x00,0x05,0xa0,0x04,0xbf,0xdf,0x04,0xde,0xe0,0x1f,0x42,0x60,0xe0, - 0xbd,0xa0,0xfb,0x21,0x20,0xfb,0x40,0x21,0xff,0xfa,0x60,0xff,0x3c,0x21,0x00,0x12, - 0x3f,0xff,0xf3,0x01,0xff,0xff,0x40,0x00,0x00,0xa0,0x00,0x0c,0x20,0xff,0xeb,0xa0, - 0x00,0xbb,0x3f,0xff,0xe8,0xe0,0x04,0xae,0x1f,0x04,0x2b,0x80,0x1e,0x9b,0x80,0xe0, - 0x1e,0xc0,0xfa,0x68,0x20,0xfb,0x32,0x40,0xff,0xdc,0x01,0xff,0x33,0xc1,0x00,0x0f, - 0xdf,0xff,0xf2,0x20,0xff,0xff,0x20,0x00,0x00,0x7f,0x00,0x0b,0x60,0xff,0xe9,0xe0, - 0x00,0xb2,0x80,0xff,0xcd,0xc1,0x04,0x99,0x00,0x03,0x7e,0x40,0x1d,0xed,0x20,0xdf, - 0x88,0x40,0xf9,0xa9,0x81,0xfb,0x28,0x81,0xff,0xbb,0xe1,0xff,0x2b,0xc0,0x00,0x0d, - 0x40,0xff,0xf1,0x61,0xff,0xff,0x20,0x00,0x00,0x7f,0x00,0x0a,0x9f,0xff,0xe8,0x61, - 0x00,0xa9,0x80,0xff,0xb4,0x61,0x04,0x80,0x5f,0x02,0xd7,0x40,0x1d,0x37,0xc0,0xde, - 0xfa,0x60,0xf8,0xe5,0x81,0xfb,0x23,0x21,0xff,0x9a,0x41,0xff,0x24,0x20,0x00,0x0a, - 0x5f,0xff,0xf0,0x60,0xff,0xff,0x01,0x00,0x00,0x5f,0x00,0x09,0xdf,0xff,0xe7,0x00, - 0x00,0xa0,0x5f,0xff,0x9c,0xc0,0x04,0x64,0xc0,0x02,0x36,0xa0,0x1c,0x7b,0x9f,0xde, - 0x75,0x81,0xf8,0x1c,0xa1,0xfb,0x22,0x40,0xff,0x77,0x21,0xff,0x1c,0xe0,0x00,0x07, - 0x20,0xff,0xef,0x81,0xff,0xfe,0xe1,0x00,0x00,0x5f,0x00,0x09,0x20,0xff,0xe6,0x01, - 0x00,0x97,0x40,0xff,0x86,0xc1,0x04,0x46,0x5f,0x01,0x9c,0x80,0x1b,0xb9,0x3f,0xdd, - 0xfa,0x21,0xf7,0x4f,0x20,0xfb,0x26,0x21,0xff,0x52,0x81,0xff,0x16,0x40,0x00,0x03, - 0xa0,0xff,0xee,0xa0,0xff,0xfe,0xc0,0x00,0x00,0x40,0x00,0x08,0x80,0xff,0xe5,0x20, - 0x00,0x8e,0x1f,0xff,0x72,0xa1,0x04,0x25,0x60,0x01,0x09,0x3f,0x1a,0xf1,0x40,0xdd, - 0x88,0x40,0xf6,0x7d,0x41,0xfb,0x2f,0x20,0xff,0x2c,0x81,0xff,0x10,0x21,0xff,0xff, - 0xc0,0xff,0xed,0xa0,0xff,0xfe,0xa0,0x00,0x00,0x40,0x00,0x07,0xe0,0xff,0xe4,0x61, - 0x00,0x85,0x00,0xff,0x60,0x00,0x04,0x02,0x1f,0x00,0x7c,0xbf,0x1a,0x23,0xc0,0xdd, - 0x20,0x80,0xf5,0xa7,0x61,0xfb,0x3d,0x41,0xff,0x05,0x40,0xff,0x0a,0xc1,0xff,0xfb, - 0x81,0xff,0xec,0xc0,0xff,0xfe,0x61,0x00,0x00,0x40,0x00,0x07,0x40,0xff,0xe4,0x00, - 0x00,0x7b,0xe0,0xff,0x4f,0x40,0x03,0xdc,0xbf,0xff,0xf7,0x41,0x19,0x51,0x9f,0xdc, - 0xc2,0xe0,0xf4,0xcd,0xe1,0xfb,0x51,0x00,0xfe,0xdc,0xc0,0xff,0x05,0xe0,0xff,0xf7, - 0x00,0xff,0xeb,0xe1,0xff,0xfe,0x41,0x00,0x00,0x40,0x00,0x06,0xa0,0xff,0xe3,0xa1, - 0x00,0x72,0xdf,0xff,0x40,0x21,0x03,0xb5,0xa0,0xff,0x78,0xc0,0x18,0x7b,0x1f,0xdc, - 0x6f,0xa1,0xf3,0xf1,0x41,0xfb,0x6a,0x60,0xfe,0xb3,0x21,0xff,0x02,0x01,0xff,0xf2, - 0x20,0xff,0xea,0xe1,0xff,0xfe,0x00,0x00,0x00,0x20,0x00,0x06,0x20,0xff,0xe3,0x80, - 0x00,0x69,0xff,0xff,0x32,0x81,0x03,0x8c,0xdf,0xff,0x01,0x61,0x17,0xa0,0xc0,0xdc, - 0x27,0x21,0xf3,0x11,0xc0,0xfb,0x89,0xa1,0xfe,0x88,0x81,0xfe,0xfe,0xe1,0xff,0xec, - 0xe0,0xff,0xea,0x00,0xff,0xfd,0xe1,0x00,0x00,0x20,0x00,0x05,0xa0,0xff,0xe3,0x80, - 0x00,0x61,0x60,0xff,0x26,0xa1,0x03,0x62,0xdf,0xfe,0x91,0x20,0x16,0xc3,0x20,0xdb, - 0xe9,0x81,0xf2,0x2f,0xe0,0xfb,0xaf,0x01,0xfe,0x5d,0x21,0xfe,0xfc,0xa1,0xff,0xe7, - 0x61,0xff,0xe9,0x21,0xff,0xfd,0xa0,0x00,0x00,0x20,0x00,0x05,0x1f,0xff,0xe3,0xa1, - 0x00,0x58,0xdf,0xff,0x1c,0x40,0x03,0x37,0x9f,0xfe,0x28,0x01,0x15,0xe2,0xa0,0xdb, - 0xb6,0xe0,0xf1,0x4c,0x01,0xfb,0xda,0x80,0xfe,0x30,0xe1,0xfe,0xfb,0x61,0xff,0xe1, - 0x80,0xff,0xe8,0x40,0xff,0xfd,0x60,0x00,0x00,0x20,0x00,0x04,0xc0,0xff,0xe3,0xe0, - 0x00,0x50,0xa0,0xff,0x13,0x60,0x03,0x0b,0x9f,0xfd,0xc5,0xe0,0x14,0xff,0xbf,0xdb, - 0x8f,0x40,0xf0,0x66,0xa1,0xfc,0x0c,0x81,0xfe,0x04,0x20,0xfe,0xfb,0x20,0xff,0xdb, - 0x40,0xff,0xe7,0x80,0xff,0xfd,0x00,0x00,0x00,0x20,0x00,0x04,0x60,0xff,0xe4,0x41, - 0x00,0x48,0x9f,0xff,0x0c,0x01,0x02,0xde,0xe0,0xfd,0x6b,0x00,0x14,0x1a,0xff,0xdb, - 0x73,0x01,0xef,0x80,0x21,0xfc,0x45,0x01,0xfd,0xd6,0xe0,0xfe,0xfc,0x01,0xff,0xd4, - 0xa0,0xff,0xe6,0xc1,0xff,0xfc,0xc0,0x00,0x00,0x20,0x00,0x03,0xdf,0xff,0xe4,0xc1, - 0x00,0x40,0xe0,0xff,0x06,0x01,0x02,0xb1,0x9f,0xfd,0x17,0x21,0x13,0x35,0x00,0xdb, - 0x62,0x01,0xee,0x99,0x01,0xfc,0x84,0x41,0xfd,0xa9,0x81,0xfe,0xfe,0x20,0xff,0xcd, - 0xe1,0xff,0xe6,0x01,0x12,0x28,0x00,0xba,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00, - 0x04,0x00,0x00,0x05,0x00,0x00,0x06,0x00,0x00,0x07,0x00,0x00,0x08,0x00,0x00,0x09, - 0x00,0x00,0x0a,0x00,0x00,0x0b,0x00,0x00,0x0c,0x00,0x00,0x0d,0x00,0x00,0x0e,0x00, - 0x00,0x0f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x02,0x00,0x00, - 0x03,0x00,0x00,0x04,0x00,0x00,0x05,0x00,0x00,0x06,0x00,0x00,0x07,0x00,0x00,0x08, - 0x00,0x00,0x09,0x00,0x00,0x0a,0x00,0x00,0x0b,0x00,0x00,0x0c,0x00,0x00,0x0d,0x00, - 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x02,0x00,0x00,0x03,0x00,0x00, - 0x04,0x00,0x00,0x05,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x10, - 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x03,0x00,0x00,0x04,0x00,0x00,0x05,0x00, - 0x00,0x06,0x00,0x00,0x07,0x00,0x00,0x08,0x00,0x00,0x09,0x00,0x00,0x0a,0x00,0x00, - 0x0b,0x00,0x00,0x0c,0x00,0x00,0x0d,0x00,0x00,0x0e,0x00,0x00,0x0f,0x00,0x00,0x00, - 0x00,0x00,0x01,0x00,0x00,0x03,0x00,0x00,0x04,0x00,0x00,0x05,0x00,0x00,0x06,0x00, - 0x00,0x07,0x12,0x66,0x00,0xbd,0x40,0x00,0x00,0x32,0xcb,0xfd,0x28,0x51,0x45,0x20, - 0x00,0x00,0x19,0x65,0xfe,0x14,0x28,0xa2,0x10,0x00,0x00,0x0c,0xb2,0xff,0x0a,0x14, - 0x51,0x08,0x00,0x00,0x06,0x59,0x7f,0x05,0x0a,0x28,0x04,0x00,0x00,0x03,0x2c,0xbf, - 0x02,0x85,0x14,0x02,0x00,0x00,0x01,0x96,0x5f,0x01,0x42,0x8a,0x01,0x00,0x00,0x00, - 0xcb,0x2f,0x00,0xa1,0x45,0x00,0x80,0x00,0x00,0x65,0x97,0x00,0x50,0xa2,0x00,0x40, - 0x00,0x00,0x32,0xcb,0x00,0x28,0x51,0x00,0x20,0x00,0x00,0x19,0x65,0x00,0x14,0x28, - 0x00,0x10,0x00,0x00,0x0c,0xb2,0x00,0x0a,0x14,0x00,0x08,0x00,0x00,0x06,0x59,0x00, - 0x05,0x0a,0x00,0x04,0x00,0x00,0x03,0x2c,0x00,0x02,0x85,0x00,0x02,0x00,0x00,0x01, - 0x96,0x00,0x01,0x42,0x00,0x01,0x00,0x00,0x00,0xcb,0x00,0x00,0xa1,0x00,0x00,0x80, - 0x00,0x00,0x65,0x00,0x00,0x50,0x00,0x00,0x40,0x00,0x00,0x32,0x00,0x00,0x28,0x00, - 0x00,0x1f,0x00,0x00,0x19,0x00,0x00,0x14,0x00,0x00,0x0f,0x00,0x00,0x0c,0x00,0x00, - 0x0a,0x00,0x00,0x08,0x00,0x00,0x06,0x00,0x00,0x05,0x00,0x00,0x03,0x00,0x00,0x03, - 0x00,0x00,0x02,0x12,0x10,0x00,0x48,0x00,0x00,0x01,0x00,0x00,0x02,0x00,0x00,0x04, - 0x00,0x00,0x08,0x00,0x00,0x10,0x00,0x00,0x20,0x00,0x00,0x40,0x00,0x00,0x80,0x00, - 0x01,0x00,0x00,0x02,0x00,0x00,0x04,0x00,0x00,0x08,0x00,0x00,0x10,0x00,0x00,0x20, - 0x00,0x00,0x40,0x00,0x00,0x80,0x00,0x01,0x00,0x00,0x02,0x00,0x00,0x04,0x00,0x00, - 0x08,0x00,0x00,0x10,0x00,0x00,0x20,0x00,0x00,0x40,0x00,0x00,0x80,0x00,0x00,0x12, - 0xa5,0x00,0x33,0xff,0xff,0xfb,0xff,0xff,0xf9,0x00,0x00,0x03,0xff,0xff,0xf6,0x00, - 0x00,0x04,0x00,0x00,0x05,0x00,0x00,0x06,0x00,0x00,0x07,0x00,0x00,0x08,0x00,0x00, - 0x09,0x00,0x00,0x0a,0x00,0x00,0x0b,0x00,0x00,0x0c,0x00,0x00,0x0d,0x00,0x00,0x0e, - 0x00,0x00,0x0f,0x00,0x00,0x10,0x12,0xb6,0x00,0x7e,0x00,0x00,0x04,0x00,0x00,0x04, - 0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00, - 0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x03,0x00,0x00, - 0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03, - 0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00, - 0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00, - 0x02,0x00,0x00,0x02,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x03,0x00,0x00,0x03, - 0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x00, - 0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x03,0x12,0xe0,0x00,0x0c,0x00,0x00,0x19,0x00, - 0x00,0x1c,0x00,0x00,0x06,0x00,0x00,0x0a,0x12,0xe4,0x00,0x0c,0x00,0x00,0x03,0x00, - 0x00,0x07,0x00,0x00,0x0b,0x00,0x00,0x0f,0x12,0xe8,0x00,0x0c,0x00,0x02,0xb6,0x00, - 0x02,0xb6,0x00,0x02,0xd4,0x00,0x02,0xd4,0x12,0xec,0x00,0x0c,0x00,0x02,0x28,0x00, - 0x02,0x28,0x00,0x02,0x50,0x00,0x02,0x50,0x12,0xf0,0x00,0x33,0x00,0x00,0x03,0x00, - 0x00,0x05,0x00,0x00,0x07,0x00,0x00,0x09,0x00,0x00,0x0f,0x00,0x00,0x1f,0x00,0x00, - 0x3f,0x00,0x00,0x7f,0x00,0x00,0xff,0x00,0x01,0xff,0x00,0x03,0xff,0x00,0x07,0xff, - 0x00,0x0f,0xff,0x00,0x1f,0xff,0x00,0x3f,0xff,0x00,0x7f,0xff,0x00,0xff,0xff,0x13, - 0x01,0x00,0x2a,0x00,0x01,0x40,0x00,0x01,0xe0,0x00,0x02,0x30,0x00,0x02,0x80,0x00, - 0x03,0x20,0x00,0x03,0xc0,0x00,0x04,0x60,0x00,0x05,0x00,0x00,0x06,0x40,0x00,0x07, - 0x80,0x00,0x08,0xc0,0x00,0x0a,0x00,0x00,0x0c,0x80,0x00,0x0f,0x00,0x13,0x0f,0x00, - 0x09,0x00,0x01,0xb9,0x00,0x01,0xe0,0x00,0x01,0x40,0x13,0x12,0x00,0x0c,0x00,0x00, - 0x58,0x00,0x00,0x5e,0x00,0x00,0x1a,0x00,0x00,0x26,0x13,0x16,0x00,0x6f,0x16,0xa0, - 0x9e,0xe9,0x5f,0x62,0x1d,0x90,0x6b,0xe2,0x6f,0x95,0x0c,0x3e,0xf1,0xf3,0xc1,0x0f, - 0x1f,0x62,0x97,0xe0,0x9d,0x69,0x1a,0x9b,0x66,0x11,0xc7,0x3b,0xee,0x38,0xc5,0x06, - 0x3e,0x2e,0x1f,0xd8,0x8d,0x1e,0x9f,0x41,0x1c,0x38,0xb2,0x18,0xbc,0x80,0x14,0x4c, - 0xf3,0x0f,0x15,0xae,0x09,0x4a,0x03,0x03,0x22,0xf4,0x01,0x91,0xf6,0x17,0xb5,0xdf, - 0x0d,0xae,0x88,0x1e,0x21,0x21,0x07,0xc6,0x7e,0x1b,0x72,0x83,0x13,0x0f,0xf7,0x1f, - 0xa7,0x55,0x1f,0xf6,0x21,0x15,0x7d,0x69,0x1c,0xed,0x7a,0x0a,0xc7,0xcd,0x1f,0x0a, - 0x7e,0x10,0x73,0x87,0x19,0xb3,0xe0,0x04,0xb2,0x04,0x00,0x00,0x00,0x1d,0x40,0x05, - 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x1f,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x01,0x5f,0x00,0x00,0x01,0x00,0x00,0x03,0x00, - 0x00,0x07,0x00,0x00,0x0f,0x00,0x00,0x1f,0x00,0x00,0x3f,0x00,0x00,0x7f,0x00,0x00, - 0xff,0x00,0x01,0xff,0x00,0x03,0xff,0x00,0x07,0xff,0x00,0x0f,0xff,0x00,0x1f,0xff, - 0x00,0x3f,0xff,0x00,0x7f,0xff,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x08,0x00, - 0x00,0x10,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, - 0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00, - 0x00,0x0d,0x40,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x05,0xc0,0x00,0x05,0xc0,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x0f,0x00,0x00,0x0f,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00, - 0x02,0x00,0x00,0x00,0x00,0x05,0xe0,0x00,0x05,0xe0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xc0,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x06,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x04,0x80,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x04,0xa0,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xc0,0x00,0x60,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xe0,0x00,0x60, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x05,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x05,0x20,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x40,0x00,0x60,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x60,0x00,0x60, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x07,0xc0,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x05,0xc0,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xe0,0x00,0x30,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x05,0x40, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x05,0x80,0x00,0x66,0x2a,0xaa,0xaa,0x33,0x33,0x33,0x24,0x92,0x49,0x38,0xe3,0x8e, - 0x22,0x22,0x22,0x21,0x08,0x42,0x20,0x82,0x08,0x20,0x40,0x81,0x20,0x20,0x20,0x20, - 0x10,0x08,0x20,0x08,0x02,0x20,0x04,0x00,0x20,0x02,0x00,0x20,0x01,0x00,0x20,0x00, - 0x80,0x20,0x00,0x40,0x20,0x00,0x20,0x10,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00, - 0x10,0x00,0x00,0x04,0x00,0x00,0x02,0x00,0x00,0x01,0x00,0x00,0x00,0x80,0x00,0x00, - 0x40,0x00,0x00,0x20,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x02, - 0x00,0x00,0x00,0xff,0x00,0x00,0x80,0x00,0x00,0x40,0x04,0x78,0x00,0x18,0x01,0xe8, - 0x0d,0x03,0x6c,0x16,0x02,0x40,0x0a,0x00,0x10,0x03,0xa8,0x00,0x00,0x00,0xcc,0x00, - 0x30,0x00,0x00,0x00,0x00,0x02,0x10,0x00,0x00,0x1b,0xcf,0x83,0x40,0x00,0x00,0x00, - 0xc7,0x8b,0x17,0x70,0x41,0xc1,0xc7,0x8c,0x26,0xc7,0x8c,0x26,0xc7,0x8b,0x36,0xc7, - 0x8b,0xf2,0xc7,0x8c,0x52,0x13,0x40,0x1b,0xea,0x97,0x80,0xc0,0x00,0x04,0x00,0x97, - 0x80,0xc8,0x00,0x04,0x00,0x70,0x78,0xcf,0x70,0x7b,0xcd,0x0f,0xd7,0xc2,0x00,0x00, - 0x01,0xc9,0x83,0x46,0x70,0x02,0xec,0x97,0x80,0xdc,0x00,0x00,0x05,0x97,0x80,0xe0, - 0x00,0x07,0xbf,0xd7,0x02,0x8f,0x70,0x7f,0xd7,0x70,0x7c,0xc7,0x70,0x7d,0xcb,0x70, - 0x7e,0xd5,0x97,0x80,0x4c,0x00,0x06,0x00,0x97,0x80,0x4d,0x00,0x0d,0x40,0x70,0x50, - 0x51,0x70,0x10,0x52,0x70,0x10,0x55,0x70,0x5a,0x5b,0x70,0x5a,0x5c,0x70,0x4e,0x62, - 0x70,0x10,0x3e,0x0f,0xcd,0xcd,0xff,0xdf,0xff,0x0f,0x4b,0x4b,0xff,0xff,0xf7,0x70, - 0x10,0x46,0xd5,0x03,0x3a,0x70,0x10,0xc2,0xd4,0x40,0x00,0xd1,0x80,0x00,0xd5,0x80, - 0x00,0x70,0x10,0xd4,0xc7,0x8a,0x47,0x70,0x00,0x1e,0x70,0x10,0x1b,0xc7,0x89,0xb0, - 0x23,0x10,0xc2,0xc9,0x83,0x70,0xcf,0x83,0x5a,0x27,0x1b,0x1b,0x00,0x00,0x01,0x37, - 0x1b,0xc2,0x00,0x00,0x0c,0xc9,0x83,0x6c,0x70,0x10,0x34,0xc7,0x89,0xb0,0x0b,0x00, - 0x20,0xc9,0x03,0x6a,0xc7,0x89,0xb0,0x0b,0x00,0xc2,0xc9,0x03,0x6a,0xc7,0x89,0xb0, - 0x0b,0x00,0xc2,0xc9,0x83,0x7c,0x97,0x80,0x21,0x00,0x00,0x02,0x70,0x00,0x1e,0xc7, - 0x89,0xb0,0x0b,0x00,0x22,0x70,0x12,0x1e,0xc7,0x89,0xb0,0x0b,0x0f,0x61,0x47,0x61, - 0x23,0x00,0x10,0x00,0x70,0x24,0x6b,0x47,0x61,0xc2,0x00,0x40,0x00,0x0b,0x01,0x24, - 0x47,0x61,0xc2,0x00,0x80,0x00,0x0b,0x00,0x25,0x47,0x61,0xc2,0x01,0x00,0x00,0x0b, - 0x00,0x26,0x47,0x61,0xc2,0x04,0x00,0x00,0x0b,0x01,0x27,0x47,0x61,0xc2,0x10,0x00, - 0x00,0x0b,0x01,0x28,0x47,0x61,0xc2,0x20,0x00,0x00,0x0b,0x00,0x29,0x47,0x61,0xc2, - 0x40,0x00,0x00,0x0b,0x00,0x2a,0x0f,0x61,0x2b,0x00,0x00,0x03,0x27,0x24,0xc2,0x00, - 0x03,0x0f,0xd1,0x40,0x00,0x90,0x00,0x1f,0x4f,0x1f,0x1f,0x00,0x10,0x00,0x27,0x23, - 0xc2,0x00,0x03,0x00,0xd1,0x40,0x00,0x90,0x00,0x30,0x4f,0x30,0x30,0x00,0x00,0x90, - 0x40,0x10,0xc2,0x70,0x30,0xc2,0xd6,0x00,0x17,0x7b,0x1f,0xc2,0x58,0x10,0x3d,0x47, - 0x3d,0x3d,0x00,0x20,0x00,0x4f,0x3d,0x3d,0x00,0x00,0x08,0x4f,0x25,0x25,0x00,0x00, - 0x08,0x70,0x25,0xc2,0x23,0x3d,0x3d,0x37,0x3d,0x3e,0x00,0x00,0x20,0xca,0x03,0x6a, - 0x27,0x3e,0xc2,0x00,0x35,0xe0,0xca,0x83,0x6a,0x27,0x23,0xc2,0x00,0x00,0x00,0xc9, - 0x03,0xeb,0x37,0x27,0xc2,0x00,0x00,0x03,0xc9,0x03,0xcc,0x37,0x23,0x1f,0x00,0x00, - 0x06,0x37,0x1f,0xc2,0x00,0x00,0x00,0xcb,0x83,0xd9,0xcf,0x83,0xd1,0x37,0x23,0x1f, - 0x00,0x00,0x02,0x37,0x1f,0xc2,0x00,0x00,0x00,0xcb,0x83,0xd9,0x37,0x24,0xc2,0x00, - 0x00,0x02,0xc9,0x03,0xd7,0x97,0x80,0x2d,0x00,0x00,0x02,0xcf,0x83,0xef,0x70,0x01, - 0x2d,0xcf,0x83,0xef,0x37,0x27,0xc2,0x00,0x00,0x03,0xc9,0x03,0xe3,0x37,0x23,0x1f, - 0x00,0x00,0x0a,0xcb,0x83,0xee,0x37,0x24,0xc2,0x00,0x00,0x01,0xc9,0x03,0xee,0xcf, - 0x83,0xe9,0x37,0x23,0xc2,0x00,0x00,0x06,0xcb,0x83,0xee,0x37,0x24,0xc2,0x00,0x00, - 0x01,0xc9,0x03,0xee,0x70,0x00,0x2d,0xcf,0x83,0xef,0x37,0x24,0xc2,0x00,0x00,0x01, - 0xc9,0x83,0xe9,0x70,0x10,0x2d,0x27,0x22,0xc2,0x00,0x00,0x00,0xc9,0x83,0xf5,0x70, - 0x12,0x1e,0xc7,0x89,0xb0,0x0b,0x0f,0x2c,0x27,0x62,0x62,0x00,0x00,0x00,0xc9,0x03, - 0xfb,0x27,0x62,0x62,0xff,0xff,0xff,0xcb,0x83,0x66,0x37,0x27,0xc2,0x00,0x00,0x03, - 0xc9,0x84,0x01,0x70,0x00,0x2e,0x70,0x00,0x2f,0xcf,0x84,0x0a,0x97,0x80,0x2e,0x00, - 0x00,0x02,0x37,0x27,0xc2,0x00,0x00,0x01,0xc9,0x84,0x08,0x70,0x01,0x2f,0xcf,0x84, - 0x0a,0x97,0x80,0x2f,0x00,0x00,0x02,0x70,0x1d,0x37,0x70,0x3e,0x38,0x70,0x1c,0x39, - 0x70,0x5b,0x5c,0x27,0x2d,0xc2,0x00,0x03,0x12,0xd1,0x40,0x00,0x90,0x00,0x5d,0x37, - 0x27,0xc2,0x00,0x00,0x03,0xc9,0x04,0x17,0x4f,0x5d,0x5d,0x00,0x00,0x02,0x70,0x2e, - 0x32,0x27,0x2d,0xc2,0x00,0x02,0xe8,0xd1,0x40,0x00,0x90,0x00,0x30,0x97,0x80,0xd8, - 0x00,0x04,0x80,0x27,0x28,0xc2,0x00,0x02,0xe4,0xd5,0x40,0x00,0x94,0x00,0x31,0x94, - 0x00,0xc2,0xd6,0x40,0x00,0xc7,0x89,0x85,0x70,0x2f,0x32,0x27,0x2d,0xc2,0x00,0x02, - 0xe0,0xd1,0x40,0x00,0x30,0x31,0xc2,0xd6,0x40,0x00,0xc7,0x89,0x85,0x70,0x2e,0x32, - 0x97,0x80,0xf0,0x00,0x04,0x80,0x97,0x80,0xd8,0x00,0x04,0xa0,0x97,0x80,0x1e,0x00, - 0x00,0x02,0x27,0x28,0xc2,0x00,0x02,0xe4,0xd5,0x40,0x00,0x94,0x00,0x31,0x94,0x00, - 0xc2,0xd6,0x40,0x00,0xc7,0x89,0x61,0x70,0x2f,0x32,0x27,0x2d,0xc2,0x00,0x02,0xe0, - 0xd1,0x40,0x00,0x30,0x31,0xc2,0xd6,0x40,0x00,0xc7,0x89,0x61,0x27,0x64,0xc2,0x00, - 0x00,0x00,0xc9,0x84,0x6d,0x27,0x22,0xc2,0x00,0x00,0x00,0xc9,0x84,0x6d,0x70,0x37, - 0x1d,0x70,0x38,0x3e,0x70,0x39,0x1c,0x97,0x80,0x63,0x00,0xff,0xff,0x0f,0x61,0xc2, - 0x00,0xff,0x00,0xc7,0x8a,0x19,0x4f,0x61,0x5f,0x00,0x01,0x00,0x0f,0x5f,0xc2,0x00, - 0xff,0x00,0xc7,0x8a,0x19,0x70,0x11,0x1e,0x27,0x5d,0x5d,0xff,0xff,0xf8,0xca,0x84, - 0x5a,0xc7,0x8a,0x15,0xcf,0x84,0x55,0x70,0x00,0x1e,0x27,0x5d,0xc2,0x00,0x00,0x08, - 0xc9,0x04,0x61,0x23,0x14,0xc2,0xd6,0x40,0x00,0xc7,0x8a,0x3a,0x0f,0x63,0x63,0x00, - 0xff,0xff,0x70,0x2c,0xc2,0x33,0x63,0xc2,0xc9,0x04,0x6d,0x0f,0x4b,0x4b,0xff,0xff, - 0xf7,0x17,0x4b,0x4b,0x00,0x00,0x07,0x27,0x59,0x59,0x00,0x00,0x01,0xcf,0x83,0x66, - 0x70,0x5c,0x5b,0x70,0x24,0xc2,0x33,0x6b,0xc2,0xc9,0x83,0x5a,0x27,0x24,0xc2,0x00, - 0x04,0x74,0xcf,0xc0,0x00,0xcf,0x84,0x78,0xcf,0x84,0x7c,0xcf,0x84,0x80,0xcf,0x83, - 0x5a,0x70,0x79,0xcf,0x0f,0xcd,0xcd,0xff,0xfb,0xff,0xcf,0x84,0x83,0x70,0x78,0xcf, - 0x0f,0xcd,0xcd,0xff,0xfb,0xff,0xcf,0x84,0x83,0x70,0x7a,0xcf,0x17,0xcd,0xcd,0x00, - 0x04,0x00,0x0f,0xcd,0xc2,0x00,0x20,0x00,0xc9,0x84,0x8d,0x27,0x57,0xc2,0x00,0x00, - 0x00,0xc9,0x84,0x8d,0x0f,0x4b,0x4b,0xff,0xff,0xfb,0x17,0x4b,0x4b,0x00,0x00,0x0b, - 0x70,0x2e,0x32,0x97,0x80,0xf0,0x00,0x04,0x80,0x97,0x80,0xd8,0x00,0x04,0xa0,0x97, - 0x80,0xe8,0x00,0x07,0xc0,0x97,0x80,0x1e,0x00,0x00,0x06,0x27,0x28,0xc2,0x00,0x02, - 0xe4,0xd5,0x40,0x00,0x94,0x00,0x31,0x94,0x00,0xc2,0xd6,0x40,0x00,0xc7,0x89,0x06, - 0x70,0x2f,0x32,0x27,0x2d,0xc2,0x00,0x02,0xe0,0xd1,0x40,0x00,0x30,0x31,0xc2,0xd6, - 0x40,0x00,0xc7,0x89,0x06,0x70,0x2e,0x32,0x70,0x10,0x1b,0x97,0x80,0xf0,0x00,0x04, - 0x80,0x27,0x28,0xc2,0x00,0x02,0xe4,0xd5,0x40,0x00,0x94,0x00,0x31,0x94,0x00,0xc2, - 0xd6,0x40,0x00,0xc7,0x88,0xba,0x70,0x2f,0x32,0x27,0x2d,0xc2,0x00,0x02,0xe0,0xd1, - 0x40,0x00,0x30,0x31,0xc2,0xd6,0x40,0x00,0xc7,0x88,0xba,0x70,0x2e,0x32,0x70,0x10, - 0x1b,0x97,0x80,0xf0,0x00,0x04,0x80,0x27,0x28,0xc2,0x00,0x02,0xe4,0xd5,0x40,0x00, - 0x94,0x00,0x31,0x94,0x00,0xc2,0xd6,0x40,0x00,0xc7,0x86,0xbd,0x70,0x2f,0x32,0x27, - 0x2d,0xc2,0x00,0x02,0xe0,0xd1,0x40,0x00,0x30,0x31,0xc2,0x90,0x00,0x31,0xd6,0x40, - 0x00,0xc7,0x86,0xbd,0x37,0x31,0xc2,0x00,0x00,0x1d,0xd6,0x40,0x00,0xc7,0x88,0x74, - 0x97,0x80,0x1f,0x00,0x00,0x06,0x37,0x27,0xc2,0x00,0x00,0x03,0xc9,0x84,0xd5,0x97, - 0x80,0x30,0x00,0x00,0x02,0xcf,0x84,0xd6,0x70,0x00,0x30,0x27,0x1f,0xc2,0x00,0x04, - 0xd9,0xcf,0xc0,0x00,0xcf,0x85,0x18,0xcf,0x85,0x13,0xcf,0x85,0x01,0xcf,0x84,0xfc, - 0xcf,0x84,0xea,0xcf,0x84,0xe5,0xcf,0x84,0xe0,0x97,0x80,0x37,0x00,0x04,0xc0,0x97, - 0x80,0x1a,0x00,0x00,0x00,0xcf,0x85,0x34,0x97,0x80,0x37,0x00,0x05,0x20,0x97,0x80, - 0x1a,0x00,0x02,0x00,0xcf,0x85,0x34,0x22,0x14,0x16,0x0f,0x16,0x16,0x00,0x00,0x0f, - 0x27,0x17,0x17,0x00,0x00,0x01,0x27,0x19,0x19,0x00,0x00,0x01,0x0f,0x19,0x19,0x00, - 0x00,0x0f,0x97,0x80,0x37,0x00,0x04,0xe0,0x97,0x80,0x1a,0x00,0x00,0x00,0x27,0x4f, - 0x4f,0x00,0x00,0x00,0xc9,0x05,0x34,0x70,0x10,0x4f,0xcf,0x85,0x34,0x97,0x80,0x37, - 0x00,0x05,0x40,0x97,0x80,0x1a,0x00,0x02,0x00,0xcf,0x85,0x34,0x22,0x14,0x16,0x0f, - 0x16,0x16,0x00,0x00,0x0f,0x27,0x17,0x17,0x00,0x00,0x01,0x27,0x19,0x19,0x00,0x00, - 0x01,0x0f,0x19,0x19,0x00,0x00,0x0f,0x97,0x80,0x37,0x00,0x05,0x00,0x97,0x80,0x1a, - 0x00,0x00,0x00,0x27,0x4f,0x4f,0x00,0x00,0x00,0xc9,0x05,0x34,0x70,0x10,0x4f,0xcf, - 0x85,0x34,0x97,0x80,0x37,0x00,0x05,0x60,0x97,0x80,0x1a,0x00,0x02,0x00,0xcf,0x85, - 0x34,0x22,0x14,0x16,0x0f,0x16,0x16,0x00,0x00,0x0f,0x27,0x17,0x17,0x00,0x00,0x01, - 0x27,0x19,0x19,0x00,0x00,0x01,0x0f,0x19,0x19,0x00,0x00,0x0f,0x27,0x4f,0x4f,0x00, - 0x00,0x00,0xc9,0x05,0x25,0x70,0x10,0x4f,0x97,0x80,0xf0,0x00,0x04,0xc0,0x97,0x80, - 0xd0,0x00,0x05,0x20,0xd5,0x03,0x3a,0xd1,0x80,0x00,0xd6,0x00,0x02,0xc7,0x8a,0x9f, - 0xd1,0x80,0x04,0x27,0x34,0x34,0x00,0x00,0x01,0x37,0x34,0xc2,0x00,0x00,0x0c,0xc9, - 0x84,0xb6,0xcf,0x83,0x66,0x70,0x37,0xf0,0x27,0x37,0xd8,0x00,0x00,0x1f,0xd6,0x00, - 0x07,0xc7,0x8c,0x5a,0x70,0x37,0xf0,0x27,0x37,0xd8,0x00,0x00,0x0f,0xd6,0x00,0x03, - 0xc7,0x8c,0x5a,0x27,0x37,0xf0,0x00,0x00,0x1b,0x27,0x37,0xd8,0x00,0x00,0x14,0xd1, - 0x03,0x16,0xd5,0x03,0x16,0xc7,0x8c,0x61,0xc7,0x8c,0x61,0xc7,0x8c,0x61,0xc7,0x8c, - 0x61,0x70,0x37,0xf0,0x27,0x37,0xd8,0x00,0x00,0x07,0xd6,0x00,0x01,0xc7,0x8c,0x5a, - 0x27,0x37,0xf0,0x00,0x00,0x0d,0x27,0x37,0xd8,0x00,0x00,0x0a,0xd6,0x00,0x01,0xc7, - 0x8c,0x61,0x27,0x37,0xf0,0x00,0x00,0x10,0x27,0x37,0xd8,0x00,0x00,0x17,0xd6,0x00, - 0x01,0xc7,0x8c,0x5a,0x27,0x37,0xf0,0x00,0x00,0x1c,0x27,0x37,0xd8,0x00,0x00,0x1b, - 0xd6,0x00,0x01,0xc7,0x8c,0x5a,0x70,0x37,0xf0,0x27,0x37,0xd8,0x00,0x00,0x03,0xc7, - 0x8c,0x5a,0x27,0x37,0xf0,0x00,0x00,0x06,0x27,0x37,0xd8,0x00,0x00,0x05,0xc7,0x8c, - 0x61,0x27,0x37,0xf0,0x00,0x00,0x08,0x27,0x37,0xd8,0x00,0x00,0x0b,0xc7,0x8c,0x5a, - 0x27,0x37,0xf0,0x00,0x00,0x0e,0x27,0x37,0xd8,0x00,0x00,0x0d,0xc7,0x8c,0x5a,0x27, - 0x37,0xf0,0x00,0x00,0x1d,0x27,0x37,0xd8,0x00,0x00,0x12,0xd1,0x03,0x1a,0xd5,0x03, - 0x18,0xd6,0x00,0x01,0xc7,0x8c,0x61,0xd1,0x03,0x19,0xd5,0x03,0x1a,0xd6,0x00,0x01, - 0xc7,0x8c,0x61,0x70,0x37,0xf0,0x27,0x37,0xd8,0x00,0x00,0x01,0xd1,0x03,0x16,0xd5, - 0x03,0x16,0xc7,0x8c,0x61,0x27,0x37,0xf0,0x00,0x00,0x03,0x27,0x37,0xd8,0x00,0x00, - 0x02,0xd1,0x03,0x1a,0xd5,0x03,0x18,0xc7,0x8c,0x6e,0x27,0x37,0xf0,0x00,0x00,0x04, - 0x27,0x37,0xd8,0x00,0x00,0x07,0xc7,0x8c,0x7b,0x27,0x37,0xf0,0x00,0x00,0x0e,0x27, - 0x37,0xd8,0x00,0x00,0x09,0xd1,0x03,0x1a,0xd5,0x03,0x18,0xc7,0x8c,0x61,0xd1,0x03, - 0x19,0xd5,0x03,0x1a,0xc7,0x8c,0x61,0x27,0x37,0xf0,0x00,0x00,0x10,0x27,0x37,0xd8, - 0x00,0x00,0x13,0xc7,0x8c,0x5a,0x27,0x37,0xf0,0x00,0x00,0x16,0x27,0x37,0xd8,0x00, - 0x00,0x15,0xc7,0x8c,0x5a,0x27,0x37,0xf0,0x00,0x00,0x18,0x27,0x37,0xd8,0x00,0x00, - 0x1b,0xc7,0x8c,0x5a,0x27,0x37,0xf0,0x00,0x00,0x1e,0x27,0x37,0xd8,0x00,0x00,0x1d, - 0xc7,0x8c,0x5a,0x27,0x37,0xf0,0x00,0x00,0x07,0x27,0x37,0xd8,0x00,0x00,0x04,0xd1, - 0x03,0x21,0xd5,0x03,0x1c,0xc7,0x8c,0x6e,0xd1,0x03,0x1e,0xd5,0x03,0x1f,0xc7,0x8c, - 0x6e,0x27,0x37,0xf0,0x00,0x00,0x08,0x27,0x37,0xd8,0x00,0x00,0x0b,0xc7,0x8c,0x7b, - 0x27,0x37,0xf0,0x00,0x00,0x0c,0x27,0x37,0xd8,0x00,0x00,0x0f,0xc7,0x8c,0x7b,0x27, - 0x37,0xf0,0x00,0x00,0x1e,0x27,0x37,0xd8,0x00,0x00,0x11,0xd1,0x03,0x21,0xd5,0x03, - 0x1c,0xc7,0x8c,0x61,0xd1,0x03,0x1d,0xd5,0x03,0x21,0xc7,0x8c,0x61,0x27,0x37,0xf0, - 0x00,0x00,0x1a,0x27,0x37,0xd8,0x00,0x00,0x15,0xd1,0x03,0x1e,0xd5,0x03,0x1f,0xc7, - 0x8c,0x61,0xd1,0x03,0x20,0xd5,0x03,0x1e,0xc7,0x8c,0x61,0x27,0x37,0xf0,0x00,0x00, - 0x0f,0x27,0x37,0xd8,0x00,0x00,0x08,0xd1,0x03,0x29,0xd5,0x03,0x22,0xc7,0x8c,0x6e, - 0xd1,0x03,0x25,0xd5,0x03,0x26,0xc7,0x8c,0x6e,0xd1,0x03,0x27,0xd5,0x03,0x24,0xc7, - 0x8c,0x6e,0xd1,0x03,0x23,0xd5,0x03,0x28,0xc7,0x8c,0x6e,0x27,0x37,0xf0,0x00,0x00, - 0x10,0x27,0x37,0xd8,0x00,0x00,0x13,0xc7,0x8c,0x7b,0x27,0x37,0xf0,0x00,0x00,0x14, - 0x27,0x37,0xd8,0x00,0x00,0x17,0xc7,0x8c,0x7b,0x27,0x37,0xf0,0x00,0x00,0x18,0x27, - 0x37,0xd8,0x00,0x00,0x1b,0xc7,0x8c,0x7b,0x27,0x37,0xf0,0x00,0x00,0x1c,0x27,0x37, - 0xd8,0x00,0x00,0x1f,0xc7,0x8c,0x7b,0xd1,0x80,0x00,0xd5,0x80,0x00,0x70,0x37,0xf0, - 0x97,0x80,0xd0,0x00,0x04,0xa0,0x97,0x80,0xd4,0x00,0x00,0x05,0x47,0xb2,0xc2,0x2d, - 0x41,0x3c,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0x96,0xd6,0x00,0x0e,0x70,0xb2, - 0x96,0x27,0x37,0xd8,0x00,0x00,0x1f,0xd1,0x03,0x2a,0xd5,0x03,0x32,0xd6,0x00,0x07, - 0xc7,0x8c,0x82,0xd1,0x03,0x31,0xd5,0x03,0x39,0x97,0x00,0xc2,0x13,0x12,0xc2,0xd7, - 0x40,0x00,0xd6,0x00,0x07,0xc7,0x8c,0x88,0x97,0x00,0xc2,0x1b,0x12,0xc2,0xd7,0x40, - 0x00,0x97,0x80,0xd4,0x00,0x00,0x09,0x97,0x80,0xd0,0x00,0x04,0xa0,0x70,0x1a,0xc2, - 0x23,0x19,0xf0,0xc7,0x8b,0x07,0x0f,0x17,0x17,0x00,0x00,0x01,0xc9,0x86,0x27,0x97, - 0x80,0xd0,0x00,0x04,0xbf,0xd6,0x00,0x1e,0xc7,0x8b,0x03,0xcf,0x86,0x29,0xd6,0x00, - 0x1e,0xc7,0x8b,0x07,0x70,0x37,0xe8,0xd1,0x80,0x04,0xd5,0x80,0x01,0x0f,0x17,0x17, - 0x00,0x00,0x01,0xc9,0x86,0x44,0x27,0x16,0xc2,0x00,0x00,0x00,0xd1,0x40,0x00,0x27, - 0x1a,0xf0,0x00,0x01,0x20,0xd6,0x00,0x0f,0xc7,0x86,0x5e,0x27,0x16,0xc2,0x00,0x01, - 0x10,0xd1,0x40,0x00,0x27,0x1a,0xf0,0x00,0x00,0x01,0xc7,0x86,0x99,0x27,0x16,0xc2, - 0x00,0x01,0x10,0xd1,0x40,0x00,0x27,0x1a,0xf0,0x00,0x00,0x10,0xd6,0x00,0x0e,0xc7, - 0x86,0x89,0xcf,0x86,0x57,0x27,0x16,0xc2,0x00,0x00,0x00,0xd1,0x40,0x00,0x27,0x1a, - 0xf0,0x00,0x01,0x00,0xd6,0x00,0x0f,0xc7,0x86,0x74,0x27,0x16,0xc2,0x00,0x01,0x10, - 0xd1,0x40,0x00,0x70,0x1a,0xf0,0xc7,0x86,0xab,0x27,0x16,0xc2,0x00,0x01,0x10,0xd1, - 0x40,0x00,0x27,0x1a,0xf0,0x00,0x02,0x10,0xd6,0x00,0x0e,0xc7,0x86,0x90,0x27,0x1a, - 0xc2,0x00,0x00,0x00,0xc9,0x06,0x5b,0xcf,0x86,0x5b,0x70,0x1f,0xc2,0x33,0x30,0x1f, - 0xcf,0x84,0xd6,0x22,0x12,0xc2,0xd1,0x40,0x00,0x27,0xf0,0xf0,0xff,0xff,0xe0,0x41, - 0xb2,0xc2,0x61,0xb2,0xc2,0x51,0xb2,0xc2,0x61,0xb2,0xc2,0x51,0xb2,0xc2,0x61,0xb2, - 0xc2,0x51,0xb2,0xc2,0x61,0xb2,0xc2,0x51,0xb2,0xc2,0x61,0xb2,0xc2,0x51,0xb2,0xc2, - 0x61,0xb2,0xc2,0x51,0xb2,0xc2,0x61,0xb2,0xc2,0x51,0xb2,0xc2,0x61,0xb2,0xc2,0x86, - 0x00,0xaa,0xdf,0x80,0x0a,0x22,0x12,0xc2,0xd1,0x40,0x00,0x40,0x10,0xc2,0x61,0xb2, - 0xc2,0x51,0xb2,0xc2,0x61,0xb2,0xc2,0x51,0xb2,0xc2,0x61,0xb2,0xc2,0x51,0xb2,0xc2, - 0x61,0xb2,0xc2,0x51,0xb2,0xc2,0x61,0xb2,0xc2,0x51,0xb2,0xc2,0x61,0xb2,0xc2,0x51, - 0xb2,0xc2,0x61,0xb2,0xc2,0x51,0xb2,0xc2,0x61,0xb2,0xc2,0x51,0xb2,0xc2,0x86,0x00, - 0xaa,0xdf,0x80,0x0a,0x22,0x12,0xc2,0xd1,0x40,0x00,0x40,0x10,0xc2,0xd6,0x00,0x0f, - 0x61,0xb2,0xc2,0x86,0x00,0xaa,0xdf,0x80,0x0a,0x22,0x12,0xc2,0xd1,0x40,0x00,0x27, - 0xf0,0xf0,0xff,0xff,0xe0,0x40,0x10,0xc2,0xd6,0x00,0x0f,0x61,0xb2,0xc2,0x86,0x00, - 0xaa,0xdf,0x80,0x0a,0x41,0x10,0xc2,0x61,0xb2,0xc2,0x61,0xb2,0x39,0x61,0xb2,0xc2, - 0x61,0xb2,0x39,0x61,0xb2,0xc2,0x61,0xb2,0x39,0x61,0xb2,0xc2,0x61,0xb2,0x39,0x61, - 0xb2,0xc2,0x61,0xb2,0x39,0x61,0xb2,0xc2,0x61,0xb2,0x39,0x61,0xb2,0xc2,0x61,0xb2, - 0x39,0x60,0xb2,0xc2,0x86,0x00,0xaa,0xdf,0x80,0x0a,0x40,0x10,0xc2,0x61,0xb2,0xc2, - 0x61,0xb2,0x39,0x61,0xb2,0xc2,0x61,0xb2,0x39,0x61,0xb2,0xc2,0x61,0xb2,0x39,0x61, - 0xb2,0xc2,0x61,0xb2,0x39,0x61,0xb2,0xc2,0x61,0xb2,0x39,0x61,0xb2,0xc2,0x61,0xb2, - 0x39,0x61,0xb2,0xc2,0x61,0xb2,0x39,0x60,0xb2,0xc2,0x86,0x00,0xaa,0xdf,0x80,0x0a, - 0x0f,0xb0,0x1f,0x00,0x0f,0xff,0xc9,0x06,0xdf,0x27,0x1b,0xc2,0x00,0x07,0xc0,0x23, - 0x1b,0xe8,0x37,0x34,0xc2,0x00,0x00,0x03,0xca,0x06,0xd1,0x37,0x34,0xc2,0x00,0x00, - 0x07,0xca,0x06,0xd8,0x47,0xa8,0xc2,0x00,0x01,0x00,0x0b,0x05,0x18,0x27,0x18,0xc2, - 0x00,0x02,0x66,0xd1,0x40,0x00,0x20,0x10,0x18,0xcf,0x86,0xdf,0x0f,0xa8,0x18,0x00, - 0x00,0x3f,0x27,0x18,0xc2,0x00,0x02,0x66,0xd1,0x40,0x00,0x20,0x10,0x18,0xcf,0x86, - 0xdf,0x47,0xa8,0xc2,0x01,0x00,0x00,0x0b,0x05,0x18,0x27,0x18,0xc2,0x00,0x02,0x66, - 0xd1,0x40,0x00,0x20,0x10,0x18,0x0f,0xb0,0xc2,0xff,0xf0,0x00,0xc9,0x07,0x01,0x27, - 0x1b,0xc2,0x00,0x07,0xc1,0x23,0x1b,0xe8,0x37,0x34,0xc2,0x00,0x00,0x03,0xca,0x06, - 0xf3,0x37,0x34,0xc2,0x00,0x00,0x07,0xca,0x06,0xfa,0x47,0xa8,0xc2,0x00,0x01,0x00, - 0x0b,0x05,0x36,0x27,0x36,0xc2,0x00,0x02,0x66,0xd1,0x40,0x00,0x20,0x10,0x36,0xcf, - 0x87,0x01,0x0f,0xa8,0x36,0x00,0x00,0x3f,0x27,0x36,0xc2,0x00,0x02,0x66,0xd1,0x40, - 0x00,0x20,0x10,0x36,0xcf,0x87,0x01,0x47,0xa8,0xc2,0x01,0x00,0x00,0x0b,0x05,0x36, - 0x27,0x36,0xc2,0x00,0x02,0x66,0xd1,0x40,0x00,0x20,0x10,0x36,0x0f,0xb0,0x1f,0x00, - 0x0f,0xff,0xc9,0x08,0x23,0x27,0x1b,0x37,0x00,0x04,0xc0,0x27,0x1b,0x38,0x00,0x04, - 0xe0,0x27,0x1b,0x39,0x00,0x05,0x00,0x27,0x1f,0xc2,0x00,0x02,0xa4,0xd1,0x40,0x00, - 0x20,0x10,0x1e,0xca,0x87,0x31,0x70,0x37,0xe8,0xc7,0x89,0xb0,0xc7,0x88,0xaa,0x57, - 0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xc2,0x23,0x10,0x3a,0x43,0x18,0xc2,0x57,0x11, - 0xc2,0x02,0x00,0x00,0x86,0x00,0xa8,0x70,0x38,0xe8,0xc7,0x89,0xb0,0xc7,0x88,0xaa, - 0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xc2,0x23,0x10,0x3b,0x43,0x18,0xc2,0x57, - 0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xa8,0x70,0x39,0xe8,0xc7,0x89,0xb0,0xc7,0x88, - 0xaa,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xc2,0x23,0x10,0x3c,0x43,0x18,0xc2, - 0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xa8,0xcf,0x88,0x2c,0x37,0x1e,0x1e,0x00, - 0x00,0x00,0x27,0x1e,0xd8,0x00,0x03,0xff,0x70,0x37,0xe8,0xc7,0x89,0xb0,0x0b,0x98, - 0xa8,0x37,0x1f,0xc2,0x00,0x00,0x04,0xc9,0x07,0x89,0x37,0x1f,0xc2,0x00,0x00,0x02, - 0xc9,0x07,0xd6,0x27,0x10,0x35,0x00,0x00,0x30,0x40,0x10,0xc2,0x70,0xa8,0xc2,0xd6, - 0x00,0x05,0x7b,0x35,0xc2,0x5f,0x10,0x30,0x00,0x00,0x00,0x4f,0x30,0x30,0x00,0x00, - 0x02,0x47,0x30,0x30,0x40,0x00,0x00,0x47,0x35,0xc2,0xf0,0x00,0x00,0x4b,0x30,0x35, - 0x70,0xa8,0xc2,0x23,0x35,0xa8,0xc7,0x88,0x9f,0x57,0x11,0xc2,0x02,0x00,0x00,0x86, - 0x00,0xc2,0x23,0x10,0x3a,0x43,0x18,0xc2,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00, - 0xa8,0x70,0x38,0xe8,0x70,0x30,0xa8,0x27,0x10,0x35,0x00,0x00,0x18,0x40,0x10,0xc2, - 0x70,0x30,0xc2,0xd6,0x00,0x03,0x7b,0x35,0xc2,0x5f,0x10,0x30,0x00,0x00,0x00,0x47, - 0x35,0xc2,0xe0,0x00,0x00,0x4b,0x30,0x35,0x70,0xa8,0xc2,0x23,0x35,0xa8,0xc7,0x88, - 0x9f,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xc2,0x23,0x10,0x3b,0x43,0x18,0xc2, - 0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xa8,0x70,0x39,0xe8,0x70,0x30,0xa8,0x27, - 0x10,0x35,0x00,0x00,0x0c,0x40,0x10,0xc2,0x70,0x30,0xc2,0xd6,0x00,0x02,0x7b,0x35, - 0xc2,0x5f,0x10,0x30,0x00,0x00,0x00,0x47,0x35,0xc2,0xc0,0x00,0x00,0x4b,0x30,0x35, - 0x70,0xa8,0xc2,0x23,0x35,0xa8,0xc7,0x88,0x9f,0x57,0x11,0xc2,0x02,0x00,0x00,0x86, - 0x00,0xc2,0x23,0x10,0x3c,0x43,0x18,0xc2,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00, - 0xa8,0xcf,0x88,0x2c,0x27,0x10,0x35,0x00,0x04,0x80,0x40,0x10,0xc2,0x70,0xa8,0xc2, - 0xd6,0x00,0x0a,0x7b,0x35,0xc2,0x5f,0x10,0x30,0x00,0x00,0x00,0x47,0x30,0x30,0x20, - 0x00,0x00,0x47,0x35,0xc2,0xfe,0x00,0x00,0x4b,0x30,0x35,0x70,0xa8,0xc2,0x23,0x35, - 0xa8,0xc7,0x88,0x94,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xc2,0x23,0x10,0x3a, - 0x43,0x18,0xc2,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xa8,0x70,0x38,0xe8,0x70, - 0x30,0xa8,0x27,0x10,0x35,0x00,0x00,0x90,0x40,0x10,0xc2,0x70,0x30,0xc2,0xd6,0x00, - 0x07,0x7b,0x35,0xc2,0x5f,0x10,0x30,0x00,0x00,0x00,0x47,0x30,0x30,0x20,0x00,0x00, - 0x47,0x35,0xc2,0xf0,0x00,0x00,0x4b,0x30,0x35,0x70,0xa8,0xc2,0x23,0x35,0xa8,0xc7, - 0x88,0x94,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xc2,0x23,0x10,0x3b,0x43,0x18, - 0xc2,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xa8,0x70,0x39,0xe8,0x70,0x30,0xa8, - 0x27,0x10,0x35,0x00,0x00,0x12,0x40,0x10,0xc2,0x70,0x30,0xc2,0xd6,0x00,0x05,0x7b, - 0x35,0xc2,0x5f,0x10,0x30,0x00,0x00,0x00,0x47,0x30,0x30,0x08,0x00,0x00,0x47,0x35, - 0xc2,0x80,0x00,0x00,0x4b,0x30,0x35,0x70,0xa8,0xc2,0x23,0x35,0xa8,0xc7,0x88,0x94, - 0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xc2,0x23,0x10,0x3c,0x43,0x18,0xc2,0x57, - 0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xa8,0xcf,0x88,0x2c,0x27,0x10,0x35,0x00,0x00, - 0xa0,0x40,0x10,0xc2,0x70,0xa8,0xc2,0xd6,0x00,0x07,0x7b,0x35,0xc2,0x5f,0x10,0x30, - 0x00,0x00,0x00,0x47,0x30,0x30,0x40,0x00,0x00,0x47,0x35,0xc2,0xf8,0x00,0x00,0x4b, - 0x30,0x35,0x70,0xa8,0xc2,0x23,0x35,0xa8,0xc7,0x88,0x89,0x57,0x11,0xc2,0x02,0x00, - 0x00,0x86,0x00,0xc2,0x23,0x10,0x3a,0x43,0x18,0xc2,0x57,0x11,0xc2,0x02,0x00,0x00, - 0x86,0x00,0xa8,0x70,0x38,0xe8,0x70,0x30,0xa8,0x27,0x10,0x35,0x00,0x00,0x28,0x40, - 0x10,0xc2,0x70,0x30,0xc2,0xd6,0x00,0x05,0x7b,0x35,0xc2,0x5f,0x10,0x30,0x00,0x00, - 0x00,0x47,0x30,0x30,0x40,0x00,0x00,0x47,0x35,0xc2,0xe0,0x00,0x00,0x4b,0x30,0x35, - 0x70,0xa8,0xc2,0x23,0x35,0xa8,0xc7,0x88,0x89,0x57,0x11,0xc2,0x02,0x00,0x00,0x86, - 0x00,0xc2,0x23,0x10,0x3b,0x43,0x18,0xc2,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00, - 0xa8,0x70,0x39,0xe8,0x70,0x30,0xa8,0x27,0x10,0x35,0x00,0x00,0x0a,0x40,0x10,0xc2, - 0x70,0x30,0xc2,0xd6,0x00,0x03,0x7b,0x35,0xc2,0x5f,0x10,0x30,0x00,0x00,0x00,0x47, - 0x30,0x30,0x40,0x00,0x00,0x47,0x35,0xc2,0x80,0x00,0x00,0x4b,0x30,0x35,0x70,0xa8, - 0xc2,0x23,0x35,0xa8,0xc7,0x88,0x89,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xc2, - 0x23,0x10,0x3c,0x43,0x18,0xc2,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xa8,0xcf, - 0x88,0x2c,0x27,0x1b,0xe8,0x00,0x04,0xc0,0x70,0x10,0xa8,0x27,0x1b,0xe8,0x00,0x04, - 0xe0,0x70,0x10,0xa8,0x27,0x1b,0xe8,0x00,0x05,0x00,0x70,0x10,0xa8,0x37,0x32,0xc2, - 0x00,0x00,0x02,0xc9,0x88,0x44,0x0f,0xe8,0xc2,0x00,0x00,0x20,0xc9,0x88,0x3f,0x27, - 0x1b,0x37,0x00,0x05,0x20,0x27,0x1b,0x38,0x00,0x05,0x40,0x27,0x1b,0x39,0x00,0x05, - 0x60,0x70,0x36,0x18,0x0f,0xb0,0x1f,0xff,0xf0,0x00,0x47,0x1f,0x1f,0x00,0x10,0x00, - 0xc9,0x87,0x0a,0xcf,0x88,0x66,0x27,0xf0,0xf0,0x00,0x00,0x01,0x27,0x1b,0x1b,0x00, - 0x00,0x01,0xdf,0x80,0x0a,0x37,0x32,0xc2,0x00,0x00,0x03,0xc9,0x88,0x66,0x0f,0xb0, - 0x1f,0xff,0xf0,0x00,0x47,0x1f,0x1f,0x00,0x10,0x00,0xc9,0x08,0x66,0x70,0x3a,0xc2, - 0x27,0x1b,0xe8,0x00,0x05,0x20,0x43,0x36,0xc2,0x57,0x11,0xc2,0x02,0x00,0x00,0x86, - 0x00,0xa8,0x70,0x3b,0xc2,0x27,0x1b,0xe8,0x00,0x05,0x40,0x43,0x36,0xc2,0x57,0x11, - 0xc2,0x02,0x00,0x00,0x86,0x00,0xa8,0x70,0x3c,0xc2,0x27,0x1b,0xe8,0x00,0x05,0x60, - 0x43,0x36,0xc2,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xa8,0x27,0x1b,0x1b,0x00, - 0x00,0x01,0x27,0xf0,0xf0,0x00,0x00,0x01,0xdf,0x80,0x0a,0x27,0x1b,0xe8,0x00,0x05, - 0x20,0x70,0x10,0xa8,0x27,0x1b,0xe8,0x00,0x05,0x40,0x70,0x10,0xa8,0x27,0x1b,0xe8, - 0x00,0x05,0x60,0x70,0x10,0xa8,0x27,0x1b,0x1b,0x00,0x00,0x01,0x27,0xf0,0xf0,0x00, - 0x00,0x01,0xdf,0x80,0x0a,0x27,0x1b,0xe8,0x00,0x04,0xc0,0x70,0x10,0xa8,0x27,0x1b, - 0xe8,0x00,0x04,0xe0,0x70,0x10,0xa8,0x27,0x1b,0xe8,0x00,0x05,0x00,0x70,0x10,0xa8, - 0x27,0x1b,0xe8,0x00,0x05,0x20,0x70,0x10,0xa8,0x27,0x1b,0xe8,0x00,0x05,0x40,0x70, - 0x10,0xa8,0x27,0x1b,0xe8,0x00,0x05,0x60,0x70,0x10,0xa8,0x27,0x1b,0x1b,0x00,0x00, - 0x01,0xdf,0x80,0x0a,0x27,0xa8,0xa8,0xff,0xff,0xfc,0x4f,0xa8,0xc2,0x08,0x00,0x00, - 0x27,0x1f,0xf8,0x00,0x05,0x90,0x23,0xb8,0xc2,0x27,0x1f,0xf8,0x00,0x05,0x7f,0x43, - 0xb8,0xc2,0xdf,0x80,0x0a,0x27,0xa8,0xa8,0xff,0xff,0xf8,0x4f,0xa8,0xc2,0x04,0x00, - 0x00,0x27,0x1f,0xf8,0x00,0x05,0x90,0x23,0xb8,0xc2,0x27,0x1f,0xf8,0x00,0x05,0x7f, - 0x43,0xb8,0xc2,0xdf,0x80,0x0a,0x27,0xa8,0xa8,0xff,0xff,0xfe,0x4f,0xa8,0xc2,0x10, - 0x00,0x00,0x27,0x1f,0xf8,0x00,0x05,0x90,0x23,0xb8,0xc2,0x27,0x1f,0xf8,0x00,0x05, - 0x7f,0x43,0xb8,0xc2,0xdf,0x80,0x0a,0x93,0x00,0xa8,0x37,0x1e,0xc2,0x00,0x02,0x28, - 0xd1,0x40,0x00,0x48,0xa8,0xa8,0x1f,0xa8,0xa8,0x80,0x00,0x00,0x47,0xa8,0xc2,0x40, - 0x00,0x00,0x27,0x1f,0xf8,0x00,0x05,0x90,0x23,0xb8,0xc2,0x27,0x1f,0xf8,0x00,0x05, - 0x7f,0x43,0xb8,0xc2,0xdf,0x80,0x0a,0x37,0x32,0xc2,0x00,0x00,0x01,0xc9,0x88,0xc6, - 0x0f,0xb0,0x30,0x00,0x0f,0xff,0x70,0x10,0xb0,0xc9,0x08,0xdb,0xc7,0x88,0xdf,0x20, - 0x00,0xb2,0x27,0x1b,0x1b,0x00,0x00,0x01,0xdf,0x80,0x0a,0x70,0xb0,0x1f,0x70,0x10, - 0xb0,0x0f,0x1f,0x30,0x00,0x0f,0xff,0xc9,0x08,0xcd,0xc7,0x88,0xdf,0x20,0x00,0xb0, - 0x0f,0x1f,0x30,0xff,0xf0,0x00,0xc9,0x08,0xdb,0x47,0x30,0x30,0x00,0x10,0x00,0xc7, - 0x88,0xdf,0x20,0x00,0x1f,0x47,0x1f,0xc2,0x00,0x10,0x00,0x5f,0xb0,0xb2,0x00,0x00, - 0x01,0x27,0x1b,0x1b,0x00,0x00,0x01,0xdf,0x80,0x0a,0x70,0xb0,0xb2,0x27,0x1b,0x1b, - 0x00,0x00,0x01,0xdf,0x80,0x0a,0x37,0x2d,0xc2,0x00,0x00,0x01,0xca,0x88,0xfb,0x37, - 0x1b,0xc2,0x00,0x00,0x02,0xca,0x08,0xf7,0x37,0x1b,0xc2,0x00,0x00,0x0a,0xca,0x08, - 0xf3,0x37,0x1b,0xc2,0x00,0x00,0x16,0xca,0x08,0xef,0x27,0x30,0xc2,0x00,0x02,0x4c, - 0xd1,0x40,0x00,0xdf,0x80,0x0a,0x27,0x30,0xc2,0x00,0x02,0x45,0xd1,0x40,0x00,0xdf, - 0x80,0x0a,0x27,0x30,0xc2,0x00,0x02,0x36,0xd1,0x40,0x00,0xdf,0x80,0x0a,0x27,0x30, - 0xc2,0x00,0x02,0x27,0xd1,0x40,0x00,0xdf,0x80,0x0a,0x37,0x1b,0xc2,0x00,0x00,0x01, - 0xca,0x09,0x02,0x27,0x30,0xc2,0x00,0x02,0x5e,0xd1,0x40,0x00,0xdf,0x80,0x0a,0x27, - 0x30,0xc2,0x00,0x02,0x4f,0xd1,0x40,0x00,0xdf,0x80,0x0a,0x37,0x32,0xc2,0x00,0x00, - 0x01,0xc9,0x89,0x13,0x0f,0xb2,0xc2,0x00,0x0f,0xff,0xc9,0x09,0x2b,0x0f,0x98,0x30, - 0x00,0x0f,0xff,0x27,0x30,0xc2,0x00,0x09,0x2f,0xc7,0xc0,0x00,0xcf,0x89,0x2b,0xdf, - 0x80,0x0a,0x70,0xb2,0x1f,0x0f,0x1f,0xc2,0x00,0x0f,0xff,0xc9,0x09,0x1c,0x0f,0x98, - 0x30,0x00,0x0f,0xff,0x27,0x30,0xc2,0x00,0x09,0x2f,0xc7,0xc0,0x00,0x0f,0x1f,0xc2, - 0xff,0xf0,0x00,0xc9,0x09,0x2b,0x27,0xe8,0xe8,0x00,0x00,0x01,0x0f,0x9a,0x30,0xff, - 0xf0,0x00,0x47,0x30,0x30,0x00,0x10,0x00,0x27,0x30,0xc2,0x00,0x09,0x2f,0xc7,0xc0, - 0x00,0x27,0xe8,0xe8,0x00,0x00,0x01,0xdf,0x80,0x0a,0x27,0xe8,0xe8,0x00,0x00,0x02, - 0x70,0x98,0x9a,0xdf,0x80,0x0a,0xcf,0x89,0x52,0xcf,0x89,0x47,0xcf,0x89,0x3e,0xcf, - 0x89,0x33,0xc7,0x89,0xb0,0x0b,0x05,0x30,0xc7,0x89,0xb0,0x0b,0x05,0xa8,0x47,0x30, - 0xc2,0x00,0x00,0x01,0x57,0xa8,0xc2,0x00,0x01,0x00,0x5f,0xa8,0xa8,0x01,0x00,0x00, - 0xdf,0x80,0x0a,0xc7,0x89,0xb0,0x0b,0x05,0xa8,0x47,0xa8,0xc2,0x00,0x00,0x01,0x57, - 0xa8,0xc2,0x00,0x01,0x00,0x5f,0xa8,0xa8,0x01,0x00,0x00,0xdf,0x80,0x0a,0xc7,0x89, - 0xb0,0x0b,0x05,0x30,0xc7,0x89,0xb0,0x0b,0x05,0xa8,0x47,0x30,0xc2,0x00,0x00,0x01, - 0x57,0x30,0xc2,0x00,0x01,0x00,0x5f,0xa8,0xa8,0x01,0x00,0x00,0xdf,0x80,0x0a,0xc7, - 0x89,0xb0,0x0b,0x05,0x30,0xc7,0x89,0xb0,0x0b,0x05,0xa8,0x47,0x30,0xc2,0x00,0x00, - 0x01,0x5f,0xa8,0x30,0x00,0x01,0x00,0xc7,0x89,0xb0,0x0b,0x05,0xa8,0x47,0x30,0xc2, - 0x00,0x00,0x01,0x5f,0xa8,0xa8,0x01,0x00,0x00,0xdf,0x80,0x0a,0x37,0x32,0xc2,0x00, - 0x00,0x01,0xc9,0x89,0x6c,0x0f,0xb2,0xc2,0x00,0x0f,0xff,0xc9,0x09,0x83,0xc7,0x89, - 0xd8,0x0b,0x01,0x9a,0x27,0x5d,0x5d,0x00,0x00,0x02,0xdf,0x80,0x0a,0x70,0xb2,0x1f, - 0x70,0x10,0x98,0x0f,0x1f,0xc2,0x00,0x0f,0xff,0xc9,0x09,0x75,0xc7,0x89,0xd8,0x0b, - 0x01,0x98,0x27,0x5d,0x5d,0x00,0x00,0x02,0x0f,0x1f,0xc2,0xff,0xf0,0x00,0xc9,0x09, - 0x81,0xc7,0x89,0xd8,0x0b,0x01,0x1f,0x47,0x1f,0xc2,0x00,0x10,0x00,0x5f,0x98,0x9a, - 0x00,0x00,0x01,0x27,0x5d,0x5d,0x00,0x00,0x02,0xdf,0x80,0x0a,0x70,0x98,0x9a,0xdf, - 0x80,0x0a,0x70,0x10,0x9a,0xdf,0x80,0x0a,0x37,0x32,0xc2,0x00,0x00,0x02,0xc9,0x09, - 0x94,0x37,0x32,0xc2,0x00,0x00,0x03,0xc9,0x09,0xa3,0x70,0x30,0xc2,0xd1,0x40,0x00, - 0x21,0x10,0x1e,0x22,0x10,0x30,0x27,0x1e,0xf0,0x00,0x03,0xff,0xc7,0x89,0xd8,0x0b, - 0xb0,0x9a,0xdf,0x80,0x0a,0x70,0x30,0xc2,0xd1,0x40,0x00,0x21,0x10,0x1e,0x22,0x10, - 0x30,0x27,0x1e,0xf0,0x00,0x03,0xff,0xc7,0x89,0xd8,0x0b,0xb0,0x98,0xc7,0x89,0xd8, - 0x0b,0xb0,0x1f,0x47,0x1f,0xc2,0x00,0x10,0x00,0x5f,0x98,0x9a,0x00,0x00,0x01,0xdf, - 0x80,0x0a,0x70,0x30,0xc2,0xd1,0x40,0x00,0x21,0x10,0x1e,0x22,0x10,0x30,0x27,0x1e, - 0xf0,0x00,0x03,0xff,0xc7,0x89,0xd8,0x0b,0xb0,0x98,0x47,0x98,0xc2,0x00,0x10,0x00, - 0x5f,0x98,0x9a,0x00,0x00,0x01,0xdf,0x80,0x0a,0x70,0x1e,0xc2,0x23,0x3e,0x3e,0x27, - 0x1e,0xc2,0x00,0x02,0x10,0xd1,0x40,0x00,0x70,0x1d,0xc2,0x33,0x1e,0x1d,0xca,0x09, - 0xd4,0x37,0x1d,0xd0,0x00,0x03,0xff,0x37,0x1d,0xc2,0x00,0x02,0x10,0xd5,0x40,0x00, - 0x40,0x1c,0x1c,0x70,0x5b,0xc2,0xd1,0x40,0x00,0x32,0x5a,0xc2,0xc9,0x89,0xc4,0xc7, - 0x8a,0x0d,0xcf,0x89,0xc0,0xc7,0x8a,0x00,0x90,0x00,0x33,0x22,0x00,0x5b,0x37,0x5b, - 0xc2,0x00,0x0f,0xff,0xca,0x09,0xcc,0x97,0x80,0x5b,0x00,0x0f,0x00,0x44,0x33,0xc2, - 0x0b,0x90,0xc2,0x13,0x1c,0xc2,0x27,0x1d,0x1d,0x00,0x00,0x18,0x5f,0x10,0x1c,0x00, - 0x00,0x00,0xdf,0x80,0x0a,0x40,0x1c,0xc2,0x5f,0x10,0x1c,0x00,0x00,0x00,0xdf,0x80, - 0x0a,0x70,0x1e,0xc2,0x23,0x3e,0x3e,0x27,0x1e,0xc2,0x00,0x02,0x10,0xd1,0x40,0x00, - 0x70,0x1d,0xc2,0x33,0x1e,0x1d,0xca,0x09,0xfc,0x37,0x1d,0xd0,0x00,0x03,0xff,0x37, - 0x1d,0xc2,0x00,0x02,0x10,0xd5,0x40,0x00,0x40,0x1c,0x1c,0x70,0x5c,0xc2,0xd1,0x40, - 0x00,0x32,0x5a,0xc2,0xc9,0x89,0xec,0xc7,0x8a,0x0d,0xcf,0x89,0xe8,0xc7,0x8a,0x00, - 0x90,0x00,0x33,0x22,0x00,0x5c,0x37,0x5c,0xc2,0x00,0x0f,0xff,0xca,0x09,0xf4,0x97, - 0x80,0x5c,0x00,0x0f,0x00,0x44,0x33,0xc2,0x0b,0x90,0xc2,0x13,0x1c,0xc2,0x27,0x1d, - 0x1d,0x00,0x00,0x18,0x5f,0x10,0x1c,0x00,0x00,0x00,0xdf,0x80,0x0a,0x40,0x1c,0xc2, - 0x5f,0x10,0x1c,0x00,0x00,0x00,0xdf,0x80,0x0a,0x4b,0x6c,0xc2,0xd9,0x00,0x02,0xcb, - 0x8a,0x04,0x23,0x6e,0xc2,0x33,0x6d,0xc2,0xdb,0x80,0x02,0x0f,0x73,0x73,0x00,0xff, - 0xff,0x17,0x73,0x58,0x0e,0x00,0x00,0xc7,0x8b,0x0b,0x70,0x10,0x6c,0xdf,0x80,0x0a, - 0x27,0x6c,0x6c,0x00,0x00,0x00,0xd9,0x00,0x02,0x97,0x80,0x58,0x0e,0x00,0x00,0xc7, - 0x8b,0x0b,0x70,0x10,0x6c,0xdf,0x80,0x0a,0xc7,0x89,0xb0,0x0b,0x07,0x5e,0x4f,0x5e, - 0xc2,0x00,0x01,0x00,0x1b,0x63,0x5e,0x0f,0x5e,0x5e,0x00,0xff,0x00,0x47,0x5e,0x60, - 0x04,0x00,0x00,0x47,0x5e,0xc2,0x02,0x00,0x00,0x1b,0x60,0x60,0x47,0x5e,0x5e,0x01, - 0x00,0x00,0x70,0x5e,0xc2,0x80,0x00,0xc2,0x1b,0x5e,0x5f,0x80,0x00,0xc2,0x1b,0x5f, - 0x5f,0x80,0x00,0xc2,0x1b,0x5f,0x5f,0x80,0x00,0xc2,0x1b,0x5f,0x5f,0x80,0x00,0xc2, - 0x1b,0x5f,0x5f,0x80,0x00,0xc2,0x1b,0x5f,0x5f,0x80,0x00,0xc2,0x1b,0x5f,0xc2,0x0b, - 0x00,0x5f,0xc9,0x0a,0x36,0x1f,0x60,0x60,0x00,0x80,0x03,0x4f,0x63,0xc2,0x00,0x01, - 0x00,0x1b,0x60,0x63,0xdf,0x80,0x0a,0xc7,0x89,0xb0,0x0b,0x00,0x5e,0x40,0x10,0xc2, - 0x70,0x63,0xc2,0x82,0x00,0x63,0x47,0x63,0xc2,0x00,0x01,0x00,0x0b,0x00,0xc2,0x1b, - 0x5e,0xc2,0xc9,0x0a,0x46,0x1f,0x63,0x63,0x00,0x80,0x05,0xdf,0x80,0x0a,0x70,0x66, - 0xc2,0x23,0x3e,0xc2,0xcb,0x8a,0x67,0x27,0x66,0xc2,0x00,0x02,0x10,0xd1,0x40,0x00, - 0x48,0x68,0x68,0x70,0x66,0x1e,0xc7,0x89,0xb0,0x27,0x66,0xd8,0x00,0x03,0xff,0x0b, - 0x98,0xc2,0x13,0x68,0x68,0xc7,0x8a,0x74,0x70,0x11,0x66,0x70,0x11,0x1e,0x37,0x3e, - 0xc2,0xff,0xff,0xf8,0xca,0x8a,0x5e,0xc7,0x89,0xb0,0x0b,0x07,0x68,0xc7,0x8a,0x74, - 0xcf,0x8a,0x57,0x37,0x3e,0x1e,0x00,0x00,0x00,0x37,0x1e,0x66,0x00,0x00,0x08,0xc7, - 0x89,0xb0,0x27,0x1e,0xd8,0x00,0x03,0xff,0x0b,0x98,0x68,0xdf,0x80,0x0a,0x93,0x00, - 0x66,0x37,0x3e,0x1e,0x00,0x00,0x00,0x27,0x1e,0xc2,0x00,0x02,0x10,0xd1,0x40,0x00, - 0x48,0x68,0x68,0xc7,0x89,0xb0,0x27,0x1e,0xd8,0x00,0x03,0xff,0x0b,0x98,0xc2,0x13, - 0x68,0x68,0xdf,0x80,0x0a,0x70,0x69,0xd8,0x37,0x67,0xc2,0x00,0x00,0x02,0xca,0x83, - 0x5a,0x27,0x67,0xc2,0x00,0x0a,0x7b,0xcf,0xc0,0x00,0xcf,0x8a,0x7e,0xcf,0x8a,0x94, - 0xcf,0x8a,0x9a,0x97,0x80,0x67,0x00,0x00,0x02,0x70,0x9a,0xc2,0x0f,0xd8,0xd8,0x00, - 0x00,0x0f,0x27,0xd8,0xc2,0x00,0x05,0xe0,0x33,0x6a,0xc2,0xc9,0x8a,0x8c,0x70,0x9a, - 0xc2,0x0f,0xd8,0xd8,0x00,0x00,0x0f,0x27,0xd8,0x6a,0x00,0x05,0xe0,0x70,0x69,0xd8, - 0x70,0x68,0xc2,0x13,0x98,0x9a,0x0f,0xd8,0xd8,0x00,0x00,0x0f,0x27,0xd8,0x69,0x00, - 0x05,0xe0,0xdf,0x80,0x0a,0x97,0x80,0x67,0x00,0x00,0x00,0x4f,0x68,0xc2,0x00,0x01, - 0x00,0x13,0x98,0x98,0xdf,0x80,0x0a,0x97,0x80,0x67,0x00,0x00,0x01,0x4f,0x68,0x98, - 0x01,0x00,0x00,0xdf,0x80,0x0a,0x70,0x4c,0xc2,0x33,0xe0,0x31,0xcb,0x0a,0xa4,0x27, - 0x31,0x31,0xff,0xfe,0x40,0x27,0x31,0x31,0x00,0x00,0x20,0xca,0x8a,0xa8,0xcf,0x8a, - 0x9f,0xc7,0x8a,0xc1,0x70,0x4c,0xf8,0x70,0x46,0xc2,0xd6,0x00,0x1f,0x43,0xb2,0xba, - 0x70,0xf8,0x4c,0x70,0x4d,0xc2,0xd1,0x40,0x00,0xd6,0x00,0x1f,0xc7,0x8a,0xbe,0x91, - 0x00,0x4d,0x37,0x4c,0xc2,0x00,0x07,0xc0,0xc9,0x8a,0xb8,0x97,0x80,0x4c,0x00,0x06, - 0x00,0x37,0x4d,0xc2,0x00,0x0f,0x00,0xc9,0x8a,0xbd,0x97,0x80,0x4d,0x00,0x0d,0x40, - 0xdf,0x80,0x0a,0x44,0x92,0xc2,0xd0,0xc0,0x00,0xdf,0x80,0x0a,0x0f,0x4b,0xc2,0x00, - 0x00,0x04,0xc9,0x0a,0xcf,0x70,0x10,0x47,0x70,0x10,0x48,0x27,0x46,0x46,0x00,0x00, - 0x00,0xc9,0x8a,0xcf,0x24,0x10,0xc2,0xc9,0x8a,0xcf,0x0f,0xcd,0xcd,0xff,0xdf,0xff, - 0x0f,0x4b,0x4b,0xff,0xff,0xfb,0x0f,0x4b,0xc2,0x00,0x00,0x08,0xc9,0x0a,0xdb,0x0f, - 0xd7,0xc2,0x00,0x00,0x01,0xc9,0x8a,0xdb,0x70,0x49,0x47,0x70,0x4a,0x48,0x17,0xcd, - 0xcd,0x00,0x20,0x00,0x0f,0x4b,0x4b,0xff,0xff,0xf7,0x0f,0x4b,0xc2,0x00,0x00,0x01, - 0xc9,0x0a,0xee,0x70,0x47,0xc2,0x33,0x46,0xc2,0xcb,0x8a,0xe6,0x23,0x0b,0xc2,0xca, - 0x0a,0xeb,0x27,0x46,0x46,0xff,0xf0,0x00,0xcf,0x8a,0xee,0x33,0x0b,0xc2,0xcb,0x0a, - 0xeb,0x27,0x46,0x46,0x00,0x0f,0xff,0xcf,0x8a,0xee,0x0f,0x4b,0x4b,0xff,0xff,0xfe, - 0x70,0x47,0x46,0x0f,0x4b,0xc2,0x00,0x00,0x02,0xc9,0x0b,0x02,0xd5,0x03,0x3a,0x34, - 0x48,0xc2,0xca,0x8a,0xf9,0x33,0x0b,0xc2,0xcb,0x0a,0xfe,0x24,0x15,0xc2,0xd4,0x40, - 0x00,0xcf,0x8b,0x02,0x23,0x0b,0xc2,0xca,0x0a,0xfe,0x24,0x0b,0xc2,0xd4,0x40,0x00, - 0xcf,0x8b,0x02,0x0f,0x4b,0x4b,0xff,0xff,0xfd,0x70,0x48,0xc2,0xd4,0x40,0x00,0xdf, - 0x80,0x0a,0x70,0x93,0xb0,0x27,0xf0,0xf0,0x00,0x00,0x10,0xdf,0x80,0x0a,0x70,0x92, - 0xb0,0x27,0xf0,0xf0,0x00,0x00,0x10,0xdf,0x80,0x0a,0x70,0xd8,0x6f,0x70,0x51,0xd8, - 0x70,0x58,0x9a,0x70,0xd8,0x51,0x0f,0xcb,0xd8,0x00,0x20,0x00,0xd9,0x00,0x02,0x47, - 0x58,0xc9,0x00,0x01,0x00,0x70,0x00,0x52,0x70,0x6f,0xd8,0xdf,0x80,0x0a,0x93,0x00, - 0x43,0x91,0x00,0x45,0x70,0xa2,0xc2,0x37,0xe0,0xc2,0x00,0x07,0xc0,0xcb,0x8b,0x1f, - 0x97,0x80,0xe0,0x00,0x06,0x00,0x27,0xe0,0xc2,0x00,0x07,0x40,0xd1,0x40,0x00,0x32, - 0x4d,0xc2,0xc9,0x0b,0x2b,0x48,0x11,0x41,0x4f,0xa0,0xc1,0x00,0x00,0x08,0x70,0x45, - 0xc2,0xd1,0x40,0x00,0x70,0x43,0xc2,0xdf,0xc0,0x0b,0x70,0xa3,0xc2,0x37,0xe0,0xc2, - 0x00,0x06,0x00,0xcb,0x0b,0x31,0x97,0x80,0xe0,0x00,0x07,0xbf,0x70,0x00,0x4f,0x70, - 0x45,0xc2,0xd1,0x40,0x00,0x70,0x43,0xc2,0xdf,0xc0,0x0b,0x93,0x00,0x43,0x5b,0x10, - 0x44,0x70,0xd8,0x45,0x27,0x55,0xc2,0x00,0x0b,0x3c,0xcf,0xc0,0x00,0xcf,0x8b,0x42, - 0xcf,0x8b,0x47,0xcf,0x8b,0x4e,0xcf,0x8b,0x55,0xcf,0x8b,0x5a,0xcf,0x8b,0x61,0x4f, - 0xc9,0x53,0x01,0x00,0x00,0x27,0x55,0x55,0x00,0x00,0x01,0xcf,0x8b,0xed,0x4f,0x53, - 0xc2,0x00,0x00,0x01,0x5f,0xc9,0x53,0x00,0x01,0x00,0x27,0x55,0x55,0x00,0x00,0x01, - 0xcf,0x8b,0xed,0x4f,0x53,0xc2,0x00,0x00,0x01,0x5f,0xc9,0x53,0x00,0x00,0x01,0x27, - 0x55,0x55,0x00,0x00,0x01,0xcf,0x8b,0xed,0x4f,0xc9,0x54,0x01,0x00,0x00,0x27,0x55, - 0x55,0x00,0x00,0x01,0xcf,0x8b,0xed,0x4f,0x54,0xc2,0x00,0x00,0x01,0x5f,0xc9,0x54, - 0x00,0x01,0x00,0x27,0x55,0x55,0x00,0x00,0x01,0xcf,0x8b,0xed,0x4f,0x54,0xc2,0x00, - 0x00,0x01,0x5f,0xc9,0x54,0x00,0x00,0x01,0x70,0x53,0xc2,0x33,0x54,0xc2,0xc9,0x8b, - 0xe2,0x0f,0x53,0x56,0x7f,0x00,0x00,0x37,0x56,0xc2,0x10,0x00,0x00,0xcb,0x0b,0xe2, - 0x97,0x80,0xc2,0x00,0x0b,0x72,0x57,0x53,0xc2,0x00,0x01,0x00,0xcf,0xc0,0x00,0xcf, - 0x8b,0x82,0xcf,0x8b,0x88,0xcf,0x8b,0x90,0xcf,0x8b,0xa0,0xcf,0x8b,0xa8,0xcf,0x8b, - 0xae,0xcf,0x8b,0xb0,0xcf,0x8b,0xb4,0xcf,0x8b,0xb7,0xcf,0x8b,0xbd,0xcf,0x8b,0xce, - 0xcf,0x8b,0xd0,0xcf,0x8b,0xd3,0xcf,0x8b,0xd7,0xcf,0x8b,0xe2,0xcf,0x8b,0xe0,0x17, - 0x4b,0x4b,0x00,0x00,0x01,0x4f,0x53,0x47,0x00,0x00,0x80,0x70,0x47,0x49,0xcf,0x8b, - 0xec,0x17,0x4b,0x4b,0x00,0x00,0x02,0x0f,0x53,0x48,0x00,0xff,0xff,0x4f,0x48,0x48, - 0x00,0x00,0x80,0x70,0x48,0x4a,0xcf,0x8b,0xec,0x0f,0x53,0xc2,0x00,0x00,0x01,0xc9, - 0x8b,0x9a,0x27,0x57,0xc2,0x00,0x00,0x00,0xc9,0x0b,0x9f,0x17,0x4b,0x4b,0x00,0x00, - 0x0b,0x70,0x10,0x57,0xcf,0x8b,0x9f,0x17,0x4b,0x4b,0x00,0x00,0x07,0x70,0x00,0x57, - 0x70,0x10,0x47,0x70,0x10,0x48,0xcf,0x8b,0xec,0x0f,0x53,0xd8,0x00,0xff,0xff,0x27, - 0xd8,0xd8,0x00,0x04,0x20,0x17,0x98,0x58,0x03,0x00,0x00,0xc7,0x8b,0x0b,0xcf,0x8b, - 0xec,0x0f,0x59,0x59,0x00,0xff,0xff,0x17,0x59,0x58,0x04,0x00,0x00,0xc7,0x8b,0x0b, - 0xcf,0x8b,0xec,0x70,0x10,0x59,0xcf,0x8b,0xec,0x0f,0x53,0xc2,0x00,0x00,0x01,0x93, - 0x00,0x64,0xcf,0x8b,0xec,0x0f,0x53,0x4e,0x00,0xff,0xff,0xcf,0x8b,0xec,0x0f,0xd7, - 0x56,0x00,0x00,0x01,0x17,0x56,0x58,0x08,0x00,0x00,0xc7,0x8b,0x0b,0xcf,0x8b,0xec, - 0x70,0x69,0xc2,0x33,0x6a,0x56,0xca,0x0b,0xc2,0x27,0x56,0x56,0x00,0x00,0x10,0x17, - 0x56,0x58,0x09,0x00,0x00,0xc7,0x8b,0x0b,0x27,0x56,0xc2,0xff,0xff,0xff,0x70,0xf0, - 0x56,0x70,0x6a,0xf0,0xd6,0x40,0x00,0xc7,0x8c,0x23,0x70,0xf0,0x6a,0x70,0x56,0xf0, - 0xcf,0x8b,0xec,0xd7,0x01,0x00,0xcf,0x8b,0xec,0x0f,0x53,0x6d,0x00,0xff,0xff,0xcf, - 0x8b,0xec,0x0f,0x53,0xc2,0x00,0x00,0x01,0x4b,0x14,0x6c,0xcf,0x8b,0xec,0x70,0x5a, - 0xc2,0x33,0x5b,0xc2,0xca,0x0b,0xdb,0x23,0x6e,0xc2,0x0b,0x0f,0x56,0x17,0x56,0x58, - 0x0d,0x00,0x00,0xc7,0x8b,0x0b,0xcf,0x8b,0xec,0x70,0x10,0x55,0xd7,0x00,0x20,0x40, - 0x10,0xc2,0x4f,0x53,0x53,0x00,0x01,0x00,0x70,0x53,0xc2,0x57,0x54,0x53,0x00,0x01, - 0x00,0x5b,0x10,0x54,0x27,0x55,0x55,0xff,0xff,0xff,0xcf,0x8b,0xed,0x70,0x10,0x55, - 0x70,0x45,0xd8,0x47,0x44,0xc2,0x00,0x00,0x01,0x70,0x43,0xc2,0xdf,0xc0,0x0b,0x93, - 0x00,0x43,0x5b,0x10,0x44,0x70,0xd8,0x45,0x27,0x52,0xc2,0x00,0x00,0x00,0xc9,0x8b, - 0xfb,0x70,0x51,0xc2,0x33,0x50,0xc2,0xc9,0x0c,0x01,0x27,0x52,0xc2,0x00,0x0b,0xfe, - 0xcf,0xc0,0x00,0xcf,0x8c,0x06,0xcf,0x8c,0x10,0xcf,0x8c,0x1a,0x70,0x45,0xd8,0x47, - 0x44,0xc2,0x00,0x00,0x01,0x70,0x43,0xc2,0xdf,0xc0,0x0b,0x70,0x50,0xd8,0x47,0x98, - 0xc9,0x00,0x01,0x00,0x27,0x52,0x52,0x00,0x00,0x01,0x70,0x45,0xd8,0x47,0x44,0xc2, - 0x00,0x00,0x01,0x70,0x43,0xc2,0xdf,0xc0,0x0b,0x70,0x50,0xd8,0x47,0x98,0xc9,0x01, - 0x00,0x00,0x27,0x52,0x52,0x00,0x00,0x01,0x70,0x45,0xd8,0x47,0x44,0xc2,0x00,0x00, - 0x01,0x70,0x43,0xc2,0xdf,0xc0,0x0b,0x70,0x50,0xd8,0x70,0x9a,0xc9,0x70,0xd8,0x50, - 0x70,0x10,0x52,0x70,0x45,0xd8,0x47,0x44,0xc2,0x00,0x00,0x01,0x70,0x43,0xc2,0xdf, - 0xc0,0x0b,0x70,0xb2,0x58,0xc7,0x8b,0x0b,0xdf,0x80,0x0a,0x95,0x00,0x45,0x93,0x00, - 0x43,0x5b,0x10,0x44,0x70,0x5a,0xc2,0xd5,0x40,0x00,0x27,0x72,0xc2,0x00,0x0c,0x2e, - 0xcf,0xc0,0x00,0xcf,0x8c,0x31,0xcf,0x8c,0x38,0xcf,0x8c,0x41,0x0f,0xc5,0x70,0x00, - 0xff,0xff,0x4f,0x70,0x70,0x00,0x01,0x00,0x27,0x72,0x72,0x00,0x00,0x01,0xcf,0x8c, - 0x4c,0x0f,0xc5,0x71,0x00,0xff,0xff,0x47,0x71,0xc2,0x01,0x00,0x00,0x13,0x70,0xc2, - 0x5b,0x10,0x70,0x27,0x72,0x72,0x00,0x00,0x01,0xcf,0x8c,0x45,0x0f,0xc5,0xc2,0x00, - 0xff,0xff,0x13,0x70,0xc2,0x70,0x10,0x72,0xd4,0x40,0x00,0x26,0x00,0x5a,0x37,0x5a, - 0xc2,0x00,0x0f,0xff,0xca,0x0c,0x4c,0x97,0x80,0x5a,0x00,0x0f,0x00,0x70,0x45,0xc2, - 0xd5,0x40,0x00,0x47,0x44,0xc2,0x00,0x00,0x01,0x70,0x43,0xc2,0xdf,0xc0,0x0b,0x70, - 0xd8,0x45,0x0f,0xd7,0xc2,0x00,0x00,0x01,0xc9,0x0c,0x58,0x0f,0xcd,0xcd,0xff,0xdf, - 0xff,0x70,0x45,0xd8,0xdf,0xc0,0x0b,0x70,0xb0,0xc2,0x23,0x98,0xb2,0x33,0x98,0x9b, - 0x70,0xb0,0xc2,0x23,0x98,0xb2,0x33,0x98,0x9b,0xdf,0x80,0x0a,0x70,0xb0,0x38,0x70, - 0x98,0x39,0x40,0x38,0xc2,0x64,0x39,0xc2,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00, - 0x9a,0x44,0x38,0xc2,0x50,0x39,0xc2,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xb3, - 0xdf,0x80,0x0a,0x70,0xb0,0x38,0x70,0x98,0x39,0x40,0x38,0xc2,0x64,0x39,0xc2,0x57, - 0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0xb3,0x44,0x38,0xc2,0x50,0x39,0xc2,0x57,0x11, - 0xc2,0x02,0x00,0x00,0x86,0x00,0x9a,0xdf,0x80,0x0a,0x70,0xb2,0xc2,0x23,0xb3,0xb2, - 0x33,0xb0,0xb0,0x70,0x9b,0xc2,0x23,0x9a,0x9b,0x33,0x98,0x98,0xdf,0x80,0x0a,0x41, - 0xb2,0xc2,0x55,0x9b,0xc2,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0x96,0xdf,0x80, - 0x0a,0x41,0xb2,0xc2,0x65,0x9b,0xc2,0x57,0x11,0xc2,0x02,0x00,0x00,0x86,0x00,0x96, - 0xdf,0x80,0x0a,0xff,0xff,0x30,0xdf,0xde -}; diff --git a/os/pc/dat.h b/os/pc/dat.h deleted file mode 100644 index 78a0e4a8..00000000 --- a/os/pc/dat.h +++ /dev/null @@ -1,258 +0,0 @@ -typedef struct Conf Conf; -typedef struct FPU FPU; -typedef struct FPenv FPenv; -typedef ulong Instr; -typedef struct ISAConf ISAConf; -typedef struct Label Label; -typedef struct Lock Lock; -typedef struct MMU MMU; -typedef struct Mach Mach; -typedef struct Notsave Notsave; -typedef struct PCArch PCArch; -typedef struct Pcidev Pcidev; -typedef struct PCMmap PCMmap; -typedef struct PCMslot PCMslot; -typedef struct Page Page; -typedef struct PMMU PMMU; -typedef struct Segdesc Segdesc; -typedef struct Ureg Ureg; -typedef struct Vctl Vctl; - -#pragma incomplete Ureg -#pragma incomplete Vctl - - -struct Lock -{ - ulong key; - ulong sr; - ulong pc; - ulong pri; -}; - -struct Label -{ - ulong sp; - ulong pc; -}; - -/* - * FPenv.status - */ -enum -{ - FPINIT, - FPACTIVE, - FPINACTIVE, -}; - -/* - * This structure must agree with FPsave and FPrestore asm routines - */ -struct FPenv -{ - ushort control; - ushort r1; - ushort status; - ushort r2; - ushort tag; - ushort r3; - ulong pc; - ushort selector; - ushort r4; - ulong operand; - ushort oselector; - ushort r5; -}; - -/* - * This structure must agree with fpsave and fprestore asm routines - */ -struct FPU -{ - FPenv env; - uchar regs[80]; /* floating point registers */ -}; - -struct Conf -{ - ulong nmach; /* processors */ - ulong nproc; /* processes */ - ulong monitor; /* has monitor? */ - ulong npage0; /* total physical pages of memory */ - ulong npage1; /* total physical pages of memory */ - ulong npage; /* total physical pages of memory */ - ulong base0; /* base of bank 0 */ - ulong base1; /* base of bank 1 */ - ulong copymode; /* 0 is copy on write, 1 is copy on reference */ - ulong ialloc; /* max interrupt time allocation in bytes */ - ulong pipeqsize; /* size in bytes of pipe queues */ - int nuart; /* number of uart devices */ -}; - -#include "../port/portdat.h" - -typedef struct { - ulong link; /* link (old TSS selector) */ - ulong esp0; /* privilege level 0 stack pointer */ - ulong ss0; /* privilege level 0 stack selector */ - ulong esp1; /* privilege level 1 stack pointer */ - ulong ss1; /* privilege level 1 stack selector */ - ulong esp2; /* privilege level 2 stack pointer */ - ulong ss2; /* privilege level 2 stack selector */ - ulong cr3; /* page directory base register */ - ulong eip; /* instruction pointer */ - ulong eflags; /* flags register */ - ulong eax; /* general registers */ - ulong ecx; - ulong edx; - ulong ebx; - ulong esp; - ulong ebp; - ulong esi; - ulong edi; - ulong es; /* segment selectors */ - ulong cs; - ulong ss; - ulong ds; - ulong fs; - ulong gs; - ulong ldt; /* selector for task's LDT */ - ulong iomap; /* I/O map base address + T-bit */ -} Tss; - -struct Segdesc -{ - ulong d0; - ulong d1; -}; - -struct Mach -{ - int machno; /* physical id of processor (KNOWN TO ASSEMBLY) */ - ulong splpc; /* pc of last caller to splhi */ - - ulong* pdb; /* page directory base for this processor (va) */ - Tss* tss; /* tss for this processor */ - Segdesc *gdt; /* gdt for this processor */ - - Proc* externup; /* extern register Proc *up */ - - ulong ticks; /* of the clock since boot time */ - Proc* proc; /* current process on this processor */ - Label sched; /* scheduler wakeup */ - Lock alarmlock; /* access to alarm list */ - void* alarm; /* alarms bound to this clock */ - int inclockintr; - - int nrdy; - int ilockdepth; - - int loopconst; - - Lock apictimerlock; - int cpumhz; - uvlong cyclefreq; /* Frequency of user readable cycle counter */ - uvlong cpuhz; - int cpuidax; - int cpuiddx; - char cpuidid[16]; - char* cpuidtype; - int havetsc; - int havepge; - uvlong tscticks; - uvlong tscoff; - int intr; - ulong spuriousintr; - int lastintr; - - vlong mtrrcap; - vlong mtrrdef; - vlong mtrrfix[11]; - vlong mtrrvar[32]; /* 256 max. */ - - int stack[1]; -}; - -struct -{ - Lock; - int machs; /* bitmap of active CPUs */ - int exiting; /* shutdown */ - int ispanic; /* shutdown in response to a panic */ - int thunderbirdsarego; /* lets the added processors continue to schedinit */ -}active; - - -/* - * routines for things outside the PC model, like power management - */ -struct PCArch -{ - char* id; - int (*ident)(void); /* this should be in the model */ - void (*reset)(void); /* this should be in the model */ - int (*serialpower)(int); /* 1 == on, 0 == off */ - int (*modempower)(int); /* 1 == on, 0 == off */ - - void (*intrinit)(void); - int (*intrenable)(Vctl*); - int (*intrvecno)(int); - int (*intrdisable)(int); - - void (*clockenable)(void); - uvlong (*fastclock)(uvlong*); - void (*timerset)(uvlong); -}; - -/* - * a parsed plan9.ini line - */ -#define NISAOPT 8 - -struct ISAConf { - char *type; - ulong port; - int irq; - ulong dma; - ulong mem; - ulong size; - ulong freq; - - int nopt; - char *opt[NISAOPT]; -}; - -extern PCArch *arch; /* PC architecture */ - -/* - * Each processor sees its own Mach structure at address MACHADDR. - * However, the Mach structures must also be available via the per-processor - * MMU information array machp, mainly for disambiguation and access to - * the clock which is only maintained by the bootstrap processor (0). - */ -Mach* machp[MAXMACH]; - -#define MACHP(n) (machp[n]) - -extern Mach *m; -//extern Proc *up; -#define up (((Mach*)MACHADDR)->externup) - -extern int swcursor; - -/* - * hardware info about a device - */ -typedef struct { - ulong port; - int size; -} Devport; - -struct DevConf -{ - ulong intnum; /* interrupt number */ - char *type; /* card type, malloced */ - int nports; /* Number of ports */ - Devport *ports; /* The ports themselves */ -}; diff --git a/os/pc/devarch.c b/os/pc/devarch.c deleted file mode 100644 index 6a7b52fe..00000000 --- a/os/pc/devarch.c +++ /dev/null @@ -1,940 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" -#include "../port/error.h" - -typedef struct IOMap IOMap; -struct IOMap -{ - IOMap *next; - int reserved; - char tag[13]; - ulong start; - ulong end; -}; - -static struct -{ - Lock; - IOMap *m; - IOMap *free; - IOMap maps[32]; // some initial free maps - - QLock ql; // lock for reading map -} iomap; - -enum { - Qdir = 0, - Qioalloc = 1, - Qiob, - Qiow, - Qiol, - Qbase, - - Qmax = 16, -}; - -typedef long Rdwrfn(Chan*, void*, long, vlong); - -static Rdwrfn *readfn[Qmax]; -static Rdwrfn *writefn[Qmax]; - -static Dirtab archdir[Qmax] = { - ".", { Qdir, 0, QTDIR }, 0, 0555, - "ioalloc", { Qioalloc, 0 }, 0, 0444, - "iob", { Qiob, 0 }, 0, 0660, - "iow", { Qiow, 0 }, 0, 0660, - "iol", { Qiol, 0 }, 0, 0660, -}; -Lock archwlock; /* the lock is only for changing archdir */ -int narchdir = Qbase; -int (*_pcmspecial)(char*, ISAConf*); -void (*_pcmspecialclose)(int); - -static int doi8253set = 1; - -/* - * Add a file to the #P listing. Once added, you can't delete it. - * You can't add a file with the same name as one already there, - * and you get a pointer to the Dirtab entry so you can do things - * like change the Qid version. Changing the Qid path is disallowed. - */ -Dirtab* -addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn) -{ - int i; - Dirtab d; - Dirtab *dp; - - memset(&d, 0, sizeof d); - strcpy(d.name, name); - d.perm = perm; - - lock(&archwlock); - if(narchdir >= Qmax){ - unlock(&archwlock); - return nil; - } - - for(i=0; inext){ - m = *l; - if (m->start < 0x400) continue; - i = m->start - port; - if(i > size) - break; - if(align > 0) - port = ((port+align-1)/align)*align; - else - port = m->end; - } - if(*l == nil){ - unlock(&iomap); - return -1; - } - m = iomap.free; - if(m == nil){ - print("ioalloc: out of maps"); - unlock(&iomap); - return port; - } - iomap.free = m->next; - m->next = *l; - m->start = port; - m->end = port + size; - m->reserved = 1; - strncpy(m->tag, tag, sizeof(m->tag)); - m->tag[sizeof(m->tag)-1] = 0; - *l = m; - - archdir[0].qid.vers++; - - unlock(&iomap); - return m->start; -} - -// -// alloc some io port space and remember who it was -// alloced to. if port < 0, find a free region. -// -int -ioalloc(int port, int size, int align, char *tag) -{ - IOMap *m, **l; - int i; - - lock(&iomap); - if(port < 0){ - // find a free port above 0x400 and below 0x1000 - port = 0x400; - for(l = &iomap.m; *l; l = &(*l)->next){ - m = *l; - if (m->start < 0x400) continue; - i = m->start - port; - if(i > size) - break; - if(align > 0) - port = ((port+align-1)/align)*align; - else - port = m->end; - } - if(*l == nil){ - unlock(&iomap); - return -1; - } - } else { - // Only 64KB I/O space on the x86. - if((port+size) > 0x10000){ - unlock(&iomap); - return -1; - } - // see if the space clashes with previously allocated ports - for(l = &iomap.m; *l; l = &(*l)->next){ - m = *l; - if(m->end <= port) - continue; - if(m->reserved && m->start == port && m->end == port + size) { - m->reserved = 0; - unlock(&iomap); - return m->start; - } - if(m->start >= port+size) - break; - unlock(&iomap); - return -1; - } - } - m = iomap.free; - if(m == nil){ - print("ioalloc: out of maps"); - unlock(&iomap); - return port; - } - iomap.free = m->next; - m->next = *l; - m->start = port; - m->end = port + size; - strncpy(m->tag, tag, sizeof(m->tag)); - m->tag[sizeof(m->tag)-1] = 0; - *l = m; - - archdir[0].qid.vers++; - - unlock(&iomap); - return m->start; -} - -void -iofree(int port) -{ - IOMap *m, **l; - - lock(&iomap); - for(l = &iomap.m; *l; l = &(*l)->next){ - if((*l)->start == port){ - m = *l; - *l = m->next; - m->next = iomap.free; - iomap.free = m; - break; - } - if((*l)->start > port) - break; - } - archdir[0].qid.vers++; - unlock(&iomap); -} - -int -iounused(int start, int end) -{ - IOMap *m; - - for(m = iomap.m; m; m = m->next){ - if(start >= m->start && start < m->end - || start <= m->start && end > m->start) - return 0; - } - return 1; -} - -static void -checkport(int start, int end) -{ - /* standard vga regs are OK */ - if(start >= 0x2b0 && end <= 0x2df+1) - return; - if(start >= 0x3c0 && end <= 0x3da+1) - return; - - if(iounused(start, end)) - return; - error(Eperm); -} - -static Chan* -archattach(char* spec) -{ - return devattach('P', spec); -} - -Walkqid* -archwalk(Chan* c, Chan *nc, char** name, int nname) -{ - return devwalk(c, nc, name, nname, archdir, narchdir, devgen); -} - -static int -archstat(Chan* c, uchar* dp, int n) -{ - return devstat(c, dp, n, archdir, narchdir, devgen); -} - -static Chan* -archopen(Chan* c, int omode) -{ - return devopen(c, omode, archdir, narchdir, devgen); -} - -static void -archclose(Chan*) -{ -} - -enum -{ - Linelen= 31, -}; - -static long -archread(Chan *c, void *a, long n, vlong offset) -{ - char *buf, *p; - int port; - ushort *sp; - ulong *lp; - IOMap *m; - Rdwrfn *fn; - - switch((ulong)c->qid.path){ - - case Qdir: - return devdirread(c, a, n, archdir, narchdir, devgen); - - case Qiob: - port = offset; - checkport(offset, offset+n); - for(p = a; port < offset+n; port++) - *p++ = inb(port); - return n; - - case Qiow: - if(n & 1) - error(Ebadarg); - checkport(offset, offset+n); - sp = a; - for(port = offset; port < offset+n; port += 2) - *sp++ = ins(port); - return n; - - case Qiol: - if(n & 3) - error(Ebadarg); - checkport(offset, offset+n); - lp = a; - for(port = offset; port < offset+n; port += 4) - *lp++ = inl(port); - return n; - - case Qioalloc: - break; - - default: - if(c->qid.path < narchdir && (fn = readfn[c->qid.path])) - return fn(c, a, n, offset); - error(Eperm); - break; - } - - if((buf = malloc(n)) == nil) - error(Enomem); - p = buf; - n = n/Linelen; - offset = offset/Linelen; - - lock(&iomap); - for(m = iomap.m; n > 0 && m != nil; m = m->next){ - if(offset-- > 0) - continue; - sprint(p, "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag); - p += Linelen; - n--; - } - unlock(&iomap); - - n = p - buf; - memmove(a, buf, n); - free(buf); - - return n; -} - -static long -archwrite(Chan *c, void *a, long n, vlong offset) -{ - char *p; - int port; - ushort *sp; - ulong *lp; - Rdwrfn *fn; - - switch((ulong)c->qid.path){ - - case Qiob: - p = a; - checkport(offset, offset+n); - for(port = offset; port < offset+n; port++) - outb(port, *p++); - return n; - - case Qiow: - if(n & 1) - error(Ebadarg); - checkport(offset, offset+n); - sp = a; - for(port = offset; port < offset+n; port += 2) - outs(port, *sp++); - return n; - - case Qiol: - if(n & 3) - error(Ebadarg); - checkport(offset, offset+n); - lp = a; - for(port = offset; port < offset+n; port += 4) - outl(port, *lp++); - return n; - - default: - if(c->qid.path < narchdir && (fn = writefn[c->qid.path])) - return fn(c, a, n, offset); - error(Eperm); - break; - } - return 0; -} - -Dev archdevtab = { - 'P', - "arch", - - devreset, - devinit, - devshutdown, - archattach, - archwalk, - archstat, - archopen, - devcreate, - archclose, - archread, - devbread, - archwrite, - devbwrite, - devremove, - devwstat, -}; - -/* - * the following is a generic version of the - * architecture specific stuff - */ - -static int -unimplemented(int) -{ - return 0; -} - -static void -nop(void) -{ -} - -/* - * On a uniprocessor, you'd think that coherence could be nop, - * but it can't. We still need a barrier when using coherence() in - * device drivers. - * - * On VMware, it's safe (and a huge win) to set this to nop. - * Aux/vmware does this via the #P/archctl file. - */ -void (*coherence)(void) = nop; - -PCArch* arch; -extern PCArch* knownarch[]; - -PCArch archgeneric = { -.id= "generic", -.ident= 0, -.reset= i8042reset, -.serialpower= unimplemented, -.modempower= unimplemented, - -.intrinit= i8259init, -.intrenable= i8259enable, -.intrvecno= i8259vecno, -.intrdisable= i8259disable, - -.clockenable= i8253enable, -.fastclock= i8253read, -.timerset= i8253timerset, -}; - -typedef struct X86type X86type; -struct X86type { - int family; - int model; - int aalcycles; - char* name; -}; - -static X86type x86intel[] = -{ - { 4, 0, 22, "486DX", }, /* known chips */ - { 4, 1, 22, "486DX50", }, - { 4, 2, 22, "486SX", }, - { 4, 3, 22, "486DX2", }, - { 4, 4, 22, "486SL", }, - { 4, 5, 22, "486SX2", }, - { 4, 7, 22, "DX2WB", }, /* P24D */ - { 4, 8, 22, "DX4", }, /* P24C */ - { 4, 9, 22, "DX4WB", }, /* P24CT */ - { 5, 0, 23, "P5", }, - { 5, 1, 23, "P5", }, - { 5, 2, 23, "P54C", }, - { 5, 3, 23, "P24T", }, - { 5, 4, 23, "P55C MMX", }, - { 5, 7, 23, "P54C VRT", }, - { 6, 1, 16, "PentiumPro", },/* trial and error */ - { 6, 3, 16, "PentiumII", }, - { 6, 5, 16, "PentiumII/Xeon", }, - { 6, 6, 16, "Celeron", }, - { 6, 7, 16, "PentiumIII/Xeon", }, - { 6, 8, 16, "PentiumIII/Xeon", }, - { 6, 0xB, 16, "PentiumIII/Xeon", }, - { 0xF, 1, 16, "P4", }, /* P4 */ - { 0xF, 2, 16, "PentiumIV/Xeon", }, - - { 3, -1, 32, "386", }, /* family defaults */ - { 4, -1, 22, "486", }, - { 5, -1, 23, "P5", }, - { 6, -1, 16, "P6", }, - { 0xF, -1, 16, "P4", }, /* P4 */ - - { -1, -1, 16, "unknown", }, /* total default */ -}; - -/* - * The AMD processors all implement the CPUID instruction. - * The later ones also return the processor name via functions - * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX - * and DX: - * K5 "AMD-K5(tm) Processor" - * K6 "AMD-K6tm w/ multimedia extensions" - * K6 3D "AMD-K6(tm) 3D processor" - * K6 3D+ ? - */ -static X86type x86amd[] = -{ - { 5, 0, 23, "AMD-K5", }, /* guesswork */ - { 5, 1, 23, "AMD-K5", }, /* guesswork */ - { 5, 2, 23, "AMD-K5", }, /* guesswork */ - { 5, 3, 23, "AMD-K5", }, /* guesswork */ - { 5, 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 */ - - { 6, 1, 11, "AMD-Athlon", },/* trial and error */ - { 6, 2, 11, "AMD-Athlon", },/* trial and error */ - - { 4, -1, 22, "Am486", }, /* guesswork */ - { 5, -1, 23, "AMD-K5/K6", }, /* guesswork */ - { 6, -1, 11, "AMD-Athlon", },/* guesswork */ - { 0xF, -1, 11, "AMD64", }, /* guesswork */ - - { -1, -1, 11, "unknown", }, /* total default */ -}; - -/* - * WinChip 240MHz - */ -static X86type x86winchip[] = -{ - {5, 4, 23, "Winchip",}, /* guesswork */ - {6, 7, 23, "Via C3 Samuel 2 or Ezra",}, - {6, 8, 23, "Via C3 Ezra-T",}, - { -1, -1, 23, "unknown", }, /* total default */ -}; - -/* - * SiS 55x - */ -static X86type x86sis[] = -{ - {5, 0, 23, "SiS 55x",}, /* guesswork */ - { -1, -1, 23, "unknown", }, /* total default */ -}; - -static X86type *cputype; - -static void simplecycles(uvlong*); -void (*cycles)(uvlong*) = simplecycles; -void _cycles(uvlong*); /* in l.s */ - -static void -simplecycles(uvlong*x) -{ - *x = m->ticks; -} - -void -cpuidprint(void) -{ - int i; - char buf[128]; - - i = sprint(buf, "cpu%d: %dMHz ", m->machno, m->cpumhz); - if(m->cpuidid[0]) - i += sprint(buf+i, "%12.12s ", m->cpuidid); - sprint(buf+i, "%s (cpuid: AX 0x%4.4uX DX 0x%4.4uX)\n", - m->cpuidtype, m->cpuidax, m->cpuiddx); - print(buf); -} - -/* - * figure out: - * - cpu type - * - whether or not we have a TSC (cycle counter) - * - whether or not it supports page size extensions - * (if so turn it on) - * - whether or not it supports machine check exceptions - * (if so turn it on) - * - whether or not it supports the page global flag - * (if so turn it on) - */ -int -cpuidentify(void) -{ - char *p; - int family, model, nomce; - X86type *t, *tab; - ulong cr4; - vlong mca, mct; - - cpuid(m->cpuidid, &m->cpuidax, &m->cpuiddx); - if(strncmp(m->cpuidid, "AuthenticAMD", 12) == 0) - tab = x86amd; - else if(strncmp(m->cpuidid, "CentaurHauls", 12) == 0) - tab = x86winchip; - else if(strncmp(m->cpuidid, "SiS SiS SiS ", 12) == 0) - tab = x86sis; - else - tab = x86intel; - - family = X86FAMILY(m->cpuidax); - model = X86MODEL(m->cpuidax); - for(t=tab; t->name; t++) - if((t->family == family && t->model == model) - || (t->family == family && t->model == -1) - || (t->family == -1)) - break; - - m->cpuidtype = t->name; - - /* - * if there is one, set tsc to a known value - */ - if(m->cpuiddx & 0x10){ - m->havetsc = 1; - cycles = _cycles; - if(m->cpuiddx & 0x20) - wrmsr(0x10, 0); - } - - /* - * use i8253 to guess our cpu speed - */ - guesscpuhz(t->aalcycles); - - /* - * If machine check exception, page size extensions or page global bit - * are supported enable them in CR4 and clear any other set extensions. - * If machine check was enabled clear out any lingering status. - */ - if(m->cpuiddx & 0x2088){ - cr4 = 0; - if(m->cpuiddx & 0x08) - cr4 |= 0x10; /* page size extensions */ - if(p = getconf("*nomce")) - nomce = strtoul(p, 0, 0); - else - nomce = 0; - if((m->cpuiddx & 0x80) && !nomce){ - cr4 |= 0x40; /* machine check enable */ - if(family == 5){ - rdmsr(0x00, &mca); - rdmsr(0x01, &mct); - } - } - - /* - * Detect whether the chip supports the global bit - * in page directory and page table entries. When set - * in a particular entry, it means ``don't bother removing - * this from the TLB when CR3 changes.'' - * - * We flag all kernel pages with this bit. Doing so lessens the - * overhead of switching processes on bare hardware, - * even more so on VMware. See mmu.c:/^memglobal. - * - * For future reference, should we ever need to do a - * full TLB flush, it can be accomplished by clearing - * the PGE bit in CR4, writing to CR3, and then - * restoring the PGE bit. - */ - if(m->cpuiddx & 0x2000){ - cr4 |= 0x80; /* page global enable bit */ - m->havepge = 1; - } - - putcr4(cr4); - if(m->cpuiddx & 0x80) - rdmsr(0x01, &mct); - } - - cputype = t; - return t->family; -} - -static long -cputyperead(Chan*, void *a, long n, vlong offset) -{ - char str[32]; - ulong mhz; - - mhz = (m->cpuhz+999999)/1000000; - - snprint(str, sizeof(str), "%s %lud\n", cputype->name, mhz); - return readstr(offset, a, n, str); -} - -static long -archctlread(Chan*, void *a, long nn, vlong offset) -{ - char buf[256]; - int n; - - n = snprint(buf, sizeof buf, "cpu %s %lud%s\n", - cputype->name, (ulong)(m->cpuhz+999999)/1000000, - m->havepge ? " pge" : ""); - n += snprint(buf+n, sizeof buf-n, "pge %s\n", getcr4()&0x80 ? "on" : "off"); - n += snprint(buf+n, sizeof buf-n, "coherence "); - if(coherence == mb386) - n += snprint(buf+n, sizeof buf-n, "mb386\n"); - else if(coherence == mb586) - n += snprint(buf+n, sizeof buf-n, "mb586\n"); - else if(coherence == nop) - n += snprint(buf+n, sizeof buf-n, "nop\n"); - else - n += snprint(buf+n, sizeof buf-n, "0x%p\n", coherence); - n += snprint(buf+n, sizeof buf-n, "i8253set %s\n", doi8253set ? "on" : "off"); - buf[n] = 0; - return readstr(offset, a, nn, buf); -} - -enum -{ - CMpge, - CMcoherence, - CMi8253set, -}; - -static Cmdtab archctlmsg[] = -{ - CMpge, "pge", 2, - CMcoherence, "coherence", 2, - CMi8253set, "i8253set", 2, -}; - -static long -archctlwrite(Chan*, void *a, long n, vlong) -{ - Cmdbuf *cb; - Cmdtab *ct; - - cb = parsecmd(a, n); - if(waserror()){ - free(cb); - nexterror(); - } - ct = lookupcmd(cb, archctlmsg, nelem(archctlmsg)); - switch(ct->index){ - case CMpge: - if(!m->havepge) - error("processor does not support pge"); - if(strcmp(cb->f[1], "on") == 0) - putcr4(getcr4() | 0x80); - else if(strcmp(cb->f[1], "off") == 0) - putcr4(getcr4() & ~0x80); - else - cmderror(cb, "invalid pge ctl"); - break; - case CMcoherence: - if(strcmp(cb->f[1], "mb386") == 0) - coherence = mb386; - else if(strcmp(cb->f[1], "mb586") == 0){ - if(X86FAMILY(m->cpuidax) < 5) - error("invalid coherence ctl on this cpu family"); - coherence = mb586; - } - else if(strcmp(cb->f[1], "nop") == 0){ - /* only safe on vmware */ - if(conf.nmach > 1) - error("cannot disable coherence on a multiprocessor"); - coherence = nop; - }else - cmderror(cb, "invalid coherence ctl"); - break; - case CMi8253set: - if(strcmp(cb->f[1], "on") == 0) - doi8253set = 1; - else if(strcmp(cb->f[1], "off") == 0){ - doi8253set = 0; - (*arch->timerset)(0); - }else - cmderror(cb, "invalid i2853set ctl"); - break; - } - free(cb); - poperror(); - return n; -} - -void -archinit(void) -{ - PCArch **p; - - arch = 0; - for(p = knownarch; *p; p++){ - if((*p)->ident && (*p)->ident() == 0){ - arch = *p; - break; - } - } - if(arch == 0) - arch = &archgeneric; - else{ - if(arch->id == 0) - arch->id = archgeneric.id; - if(arch->reset == 0) - arch->reset = archgeneric.reset; - if(arch->serialpower == 0) - arch->serialpower = archgeneric.serialpower; - if(arch->modempower == 0) - arch->modempower = archgeneric.modempower; - if(arch->intrinit == 0) - arch->intrinit = archgeneric.intrinit; - if(arch->intrenable == 0) - arch->intrenable = archgeneric.intrenable; - } - - /* - * Decide whether to use copy-on-reference (386 and mp). - * We get another chance to set it in mpinit() for a - * multiprocessor. - */ - if(X86FAMILY(m->cpuidax) == 3) - conf.copymode = 1; - - if(X86FAMILY(m->cpuidax) >= 5) - coherence = mb586; - - addarchfile("cputype", 0444, cputyperead, nil); - addarchfile("archctl", 0664, archctlread, archctlwrite); -} - -/* - * call either the pcmcia or pccard device setup - */ -int -pcmspecial(char *idstr, ISAConf *isa) -{ - return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1; -} - -/* - * call either the pcmcia or pccard device teardown - */ -void -pcmspecialclose(int a) -{ - if (_pcmspecialclose != nil) - _pcmspecialclose(a); -} - -/* - * return value and speed of timer set in arch->clockenable - */ -uvlong -fastticks(uvlong *hz) -{ - return (*arch->fastclock)(hz); -} - -/* - * set next timer interrupt - */ -void -timerset(uvlong x) -{ - if(doi8253set) - (*arch->timerset)(x); -} diff --git a/os/pc/devds1620.c b/os/pc/devds1620.c deleted file mode 100644 index b5e6fc83..00000000 --- a/os/pc/devds1620.c +++ /dev/null @@ -1,368 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "io.h" - -enum { - // Ziatech 5512 Digital I/O ASIC register info - PortSelect = 0xE7, - Port = 0xE1, - DQ = 1<<0, - CLK = 1<<1, - RST = 1<<2, - TL = 1<<3, - TH = 1<<4, - - // ds1620 Masks - Mread = 0xA0, - Mwrite = 0, - - // ds1620 Registers - Rtemp = 0x0A, - Rcounter = 0x00, - Rslope = 0x09, - Rhi = 0x01, - Rlo = 0x02, - Rconfig = 0x0C, - Cdone = 1<<7, // conversion done - Cthf = 1<<6, // temp >= Rhi - Ctlf = 1<<5, // temp <= Rlo - Cnvb = 1<<4, // e^2 nvram busy (write may take up to 10ms) - Ccpu = 1<<1, // cpu use (0=clk starts conversion when rst lo) - C1shot = 1<<0, // perform one conversion then stop - - // ds1620 Commands - Startconv = 0xEE, - Stopconv = 0x22, - - ALOTEMP = 0, - AHITEMP = 1, -}; - -#define send(v) outb(Port, v); delay(1) -#define recv() (!(inb(Port) & 1)) - -enum { - Qdir = 0, - Qtemp, - Qalarm, -}; - -Dirtab ds1620tab[]={ - "temp", {Qtemp, 0}, 0, 0666, - "alarm", {Qalarm, 0}, 0, 0444, -}; - -typedef struct Temp Temp; -struct Temp -{ - Lock; - int lo; - int cur; - int hi; - - int alo; - int ahi; - int atime; - Queue *aq; -}; - -static Temp t; - -static void -sendreg(int r) -{ - int d, i; - - r = ~r; - for(i=0;i<8;i++) { - d = (r >> i) & 1; - send(CLK|d); - send(d); - send(CLK); - } -} - -static int -ds1620rdreg(int r, int nb) -{ - int i, s; - - s = splhi(); - - outb(PortSelect, 0); - send(RST|CLK); - sendreg(r|Mread); - r = 0; - for(i=0; i < nb; i++) { - r |= recv() << i; - delay(1); - send(0); - send(CLK); - } - send(RST); - - splx(s); - return r; -} - -static void -ds1620wrreg(int r, int v, int nb) -{ - int d, i, s; - - s = splhi(); - - outb(PortSelect, 0); - send(RST|CLK); - sendreg(r|Mwrite); - v = ~v; - for(i=0; i < nb; i++) { - d = (v >> i) & 1; - send(CLK|d); - send(0); - send(CLK); - } - send(RST); - - splx(s); -} - -static void -ds1620cmd(int r) -{ - int s; - - s = splhi(); - outb(PortSelect, 0); - send(RST|CLK); - sendreg(r); - send(RST); - splx(s); -} - -static char* -t2s(int t) -{ - static char s[16]; - - sprint(s, "%4d.", t>>1); - if(t&1) - strcat(s, "5"); - else - strcat(s, "0"); - return s; -} - -static int -s2t(char *s) -{ - int v; - char *p; - p = strchr(s, '.'); - if(p != nil) - *p++ = '\0'; - v = strtoul(s, nil, 0); - v <<= 1; - if(p != nil && *p != '\0' && *p >= '5') - v |= 1; - return v; -} - -static void -alarm(int code, Temp *tt) -{ - char buf[256], *end; - int s; - - s = seconds(); - - if(s - tt->atime < 60) - return; - tt->atime = s; - - end = buf; - end += sprint(buf, "(alarm) %8.8uX %uld temp ", code, seconds()); - switch(code) { - case ALOTEMP: - end += sprint(end, "%s below threshold ", t2s(tt->lo)); - end += sprint(end, "%s.\n", t2s(tt->alo)); - break; - case AHITEMP: - end += sprint(end, "%s above threshold ", t2s(tt->hi)); - end += sprint(end, "%s.\n", t2s(tt->ahi)); - break; - } - - qproduce(tt->aq, buf, end-buf); -} - -void -tmon(void *a) -{ - int r; - Temp *t; - - t = a; - r = ds1620rdreg(Rtemp, 9); - lock(t); - t->lo = t->cur = t->hi = r; - unlock(t); - for(;;) { - tsleep(&up->sleep, return0, nil, 1000); - r = ds1620rdreg(Rtemp, 9); - lock(t); - t->cur = r; - if(r < t->lo) - t->lo = r; - if(r > t->hi) - t->hi = r; - if(t->lo < t->alo) - alarm(ALOTEMP, t); - if(t->hi > t->ahi) - alarm(AHITEMP, t); - unlock(t); - } - pexit("", 0); -} - -static void -ds1620init(void) -{ - int r; - - t.aq = qopen(8*1024, Qmsg, nil, nil); - if(t.aq == nil) - error(Enomem); - - ds1620wrreg(Rconfig, Ccpu, 8); // continuous sample mode - ds1620cmd(Startconv); - r = ds1620rdreg(Rtemp, 9); - t.alo = ds1620rdreg(Rlo, 9); - t.ahi = ds1620rdreg(Rhi, 9); - - print("#L: temp %s (c) ", t2s(r)); - print("low threshold %s (c) ", t2s(t.alo)); - print("high threshold %s (c)\n", t2s(t.ahi)); - - kproc("tempmon", tmon, &t, 0); -} - -static Chan* -ds1620attach(char *spec) -{ - return devattach('L', spec); -} - -static int -ds1620walk(Chan *c, char* name) -{ - return devwalk(c, name, ds1620tab, nelem(ds1620tab), devgen); -} - -static void -ds1620stat(Chan *c, char* db) -{ - ds1620tab[1].length = qlen(t.aq); - devstat(c, db, ds1620tab, nelem(ds1620tab), devgen); -} - -static Chan* -ds1620open(Chan *c, int omode) -{ - return devopen(c, omode, ds1620tab, nelem(ds1620tab), devgen); -} - -static void -ds1620close(Chan*) -{ -} - -static long -ds1620read(Chan *c, void *a, long n, vlong offset) -{ - Temp tt; - char buf[64]; - char *s; - if(c->qid.path & CHDIR) - return devdirread(c, a, n, ds1620tab, nelem(ds1620tab), devgen); - buf[0] = 0; - switch(c->qid.path) { - case Qtemp: - lock(&t); - tt = t; - unlock(&t); - s = buf; - s+= sprint(s, "%s ", t2s(tt.lo)); - s+= sprint(s, "%s ", t2s(tt.cur)); - s+= sprint(s, "%s ", t2s(tt.hi)); - s+= sprint(s, "%s ", t2s(tt.alo)); - sprint(s, "%s", t2s(tt.ahi)); - return readstr(offset, a, n, buf); - case Qalarm: - return qread(t.aq, a, n); - default: - error(Egreg); - return 0; - } -} - -static long -ds1620write(Chan *c, void *a, long n, vlong) -{ - char buf[64]; - char *f[2]; - int lo, hi; - int nf; - - if(c->qid.path & CHDIR) - error(Eperm); - - if(c->qid.path == Qtemp) { - if(n >= sizeof(buf)) - n = sizeof(buf)-1; - memmove(buf, a, n); - buf[n] = '\0'; - nf = getfields(buf, f, 2, 1, " \t"); - if(nf != 2) - error(Ebadarg); - lo = s2t(f[0]); - hi = s2t(f[1]); - lock(&t); - t.alo = lo; - t.ahi = hi; - t.atime = 0; - ds1620wrreg(Rlo, lo, 9); - delay(1); - ds1620wrreg(Rhi, hi, 9); - unlock(&t); - return n; - } else - error(Eio); - return 0; - -} - -Dev ds1620devtab = { - 'L', - "ds1620", - devreset, - ds1620init, - ds1620attach, - devdetach, - devclone, - ds1620walk, - ds1620stat, - ds1620open, - devcreate, - ds1620close, - ds1620read, - devbread, - ds1620write, - devbwrite, - devremove, - devwstat, -}; diff --git a/os/pc/devether.c b/os/pc/devether.c deleted file mode 100644 index 4bdc693c..00000000 --- a/os/pc/devether.c +++ /dev/null @@ -1,539 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" -#include "../port/error.h" -#include "../port/netif.h" - -#include "etherif.h" - -static Ether *etherxx[MaxEther]; - -Chan* -etherattach(char* spec) -{ - ulong ctlrno; - char *p; - Chan *chan; - - ctlrno = 0; - if(spec && *spec){ - ctlrno = strtoul(spec, &p, 0); - if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther)) - error(Ebadarg); - } - if(etherxx[ctlrno] == 0) - error(Enodev); - - chan = devattach('l', spec); - chan->dev = ctlrno; - if(etherxx[ctlrno]->attach) - etherxx[ctlrno]->attach(etherxx[ctlrno]); - return chan; -} - -static Walkqid* -etherwalk(Chan* chan, Chan* nchan, char** name, int nname) -{ - return netifwalk(etherxx[chan->dev], chan, nchan, name, nname); -} - -static int -etherstat(Chan* chan, uchar* dp, int n) -{ - return netifstat(etherxx[chan->dev], chan, dp, n); -} - -static Chan* -etheropen(Chan* chan, int omode) -{ - return netifopen(etherxx[chan->dev], chan, omode); -} - -static void -ethercreate(Chan*, char*, int, ulong) -{ -} - -static void -etherclose(Chan* chan) -{ - netifclose(etherxx[chan->dev], chan); -} - -static long -etherread(Chan* chan, void* buf, long n, vlong off) -{ - Ether *ether; - ulong offset = off; - - ether = etherxx[chan->dev]; - if((chan->qid.type & QTDIR) == 0 && ether->ifstat){ - /* - * With some controllers it is necessary to reach - * into the chip to extract statistics. - */ - if(NETTYPE(chan->qid.path) == Nifstatqid) - return ether->ifstat(ether, buf, n, offset); - else if(NETTYPE(chan->qid.path) == Nstatqid) - ether->ifstat(ether, buf, 0, offset); - } - - return netifread(ether, chan, buf, n, offset); -} - -static Block* -etherbread(Chan* chan, long n, ulong offset) -{ - return netifbread(etherxx[chan->dev], chan, n, offset); -} - -static int -etherwstat(Chan* chan, uchar* dp, int n) -{ - return netifwstat(etherxx[chan->dev], chan, dp, n); -} - -static void -etherrtrace(Netfile* f, Etherpkt* pkt, int len) -{ - int i, n; - Block *bp; - - if(qwindow(f->in) <= 0) - return; - if(len > 58) - n = 58; - else - n = len; - bp = iallocb(64); - if(bp == nil) - return; - memmove(bp->wp, pkt->d, n); - i = TK2MS(MACHP(0)->ticks); - bp->wp[58] = len>>8; - bp->wp[59] = len; - bp->wp[60] = i>>24; - bp->wp[61] = i>>16; - bp->wp[62] = i>>8; - bp->wp[63] = i; - bp->wp += 64; - qpass(f->in, bp); -} - -Block* -etheriq(Ether* ether, Block* bp, int fromwire) -{ - Etherpkt *pkt; - ushort type; - int len, multi, tome, fromme; - Netfile **ep, *f, **fp, *fx; - Block *xbp; - - ether->inpackets++; - - pkt = (Etherpkt*)bp->rp; - len = BLEN(bp); - type = (pkt->type[0]<<8)|pkt->type[1]; - fx = 0; - ep = ðer->f[Ntypes]; - - multi = pkt->d[0] & 1; - /* check for valid multcast addresses */ - if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){ - if(!activemulti(ether, pkt->d, sizeof(pkt->d))){ - if(fromwire){ - freeb(bp); - bp = 0; - } - return bp; - } - } - - /* is it for me? */ - tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0; - fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0; - - /* - * Multiplex the packet to all the connections which want it. - * If the packet is not to be used subsequently (fromwire != 0), - * attempt to simply pass it into one of the connections, thereby - * saving a copy of the data (usual case hopefully). - */ - for(fp = ether->f; fp < ep; fp++){ - if(f = *fp) - if(f->type == type || f->type < 0) - if(tome || multi || f->prom){ - /* Don't want to hear bridged packets */ - if(f->bridge && !fromwire && !fromme) - continue; - if(!f->headersonly){ - if(fromwire && fx == 0) - fx = f; - else if(xbp = iallocb(len)){ - memmove(xbp->wp, pkt, len); - xbp->wp += len; - if(qpass(f->in, xbp) < 0) - ether->soverflows++; - } - else - ether->soverflows++; - } - else - etherrtrace(f, pkt, len); - } - } - - if(fx){ - if(qpass(fx->in, bp) < 0) - ether->soverflows++; - return 0; - } - if(fromwire){ - freeb(bp); - return 0; - } - - return bp; -} - -static int -etheroq(Ether* ether, Block* bp) -{ - int len, loopback, s; - Etherpkt *pkt; - - ether->outpackets++; - - /* - * Check if the packet has to be placed back onto the input queue, - * i.e. if it's a loopback or broadcast packet or the interface is - * in promiscuous mode. - * If it's a loopback packet indicate to etheriq that the data isn't - * needed and return, etheriq will pass-on or free the block. - * To enable bridging to work, only packets that were originated - * by this interface are fed back. - */ - pkt = (Etherpkt*)bp->rp; - len = BLEN(bp); - loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0; - if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){ - s = splhi(); - etheriq(ether, bp, 0); - splx(s); - } - - if(!loopback){ - qbwrite(ether->oq, bp); - if(ether->transmit != nil) - ether->transmit(ether); - } else - freeb(bp); - - return len; -} - -static long -etherwrite(Chan* chan, void* buf, long n, vlong) -{ - Ether *ether; - Block *bp; - int nn, onoff; - Cmdbuf *cb; - - ether = etherxx[chan->dev]; - if(NETTYPE(chan->qid.path) != Ndataqid) { - nn = netifwrite(ether, chan, buf, n); - if(nn >= 0) - return nn; - cb = parsecmd(buf, n); - if(strcmp(cb->f[0], "nonblocking") == 0){ - if(cb->nf <= 1) - onoff = 1; - else - onoff = atoi(cb->f[1]); - qnoblock(ether->oq, onoff); - free(cb); - return n; - } - free(cb); - if(ether->ctl!=nil) - return ether->ctl(ether,buf,n); - - error(Ebadctl); - } - - if(n > ether->maxmtu) - error(Etoobig); - if(n < ether->minmtu) - error(Etoosmall); - - bp = allocb(n); - if(waserror()){ - freeb(bp); - nexterror(); - } - memmove(bp->rp, buf, n); - memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen); - poperror(); - bp->wp += n; - - return etheroq(ether, bp); -} - -static long -etherbwrite(Chan* chan, Block* bp, ulong) -{ - Ether *ether; - long n; - - n = BLEN(bp); - if(NETTYPE(chan->qid.path) != Ndataqid){ - if(waserror()) { - freeb(bp); - nexterror(); - } - n = etherwrite(chan, bp->rp, n, 0); - poperror(); - freeb(bp); - return n; - } - ether = etherxx[chan->dev]; - - if(n > ether->maxmtu){ - freeb(bp); - error(Etoobig); - } - if(n < ether->minmtu){ - freeb(bp); - error(Etoosmall); - } - - return etheroq(ether, bp); -} - -static struct { - char* type; - int (*reset)(Ether*); -} cards[MaxEther+1]; - -void -addethercard(char* t, int (*r)(Ether*)) -{ - static int ncard; - - if(ncard == MaxEther) - panic("too many ether cards"); - cards[ncard].type = t; - cards[ncard].reset = r; - ncard++; -} - -int -parseether(uchar *to, char *from) -{ - char nip[4]; - char *p; - int i; - - p = from; - for(i = 0; i < Eaddrlen; 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; -} - -static Ether* -etherprobe(int cardno, int ctlrno) -{ - int i; - Ether *ether; - char buf[128], name[32]; - - ether = malloc(sizeof(Ether)); - memset(ether, 0, sizeof(Ether)); - ether->ctlrno = ctlrno; - ether->tbdf = BUSUNKNOWN; - ether->mbps = 10; - ether->minmtu = ETHERMINTU; - ether->maxmtu = ETHERMAXTU; - - if(cardno < 0){ - if(isaconfig("ether", ctlrno, ether) == 0){ - free(ether); - return nil; - } - for(cardno = 0; cards[cardno].type; cardno++){ - if(cistrcmp(cards[cardno].type, ether->type)) - continue; - for(i = 0; i < ether->nopt; i++){ - if(strncmp(ether->opt[i], "ea=", 3)) - continue; - if(parseether(ether->ea, ðer->opt[i][3])) - memset(ether->ea, 0, Eaddrlen); - } - break; - } - } - - if(cardno >= MaxEther || cards[cardno].type == nil){ - free(ether); - return nil; - } - if(cards[cardno].reset(ether) < 0){ - free(ether); - return nil; - } - - /* - * IRQ2 doesn't really exist, it's used to gang the interrupt - * controllers together. A device set to IRQ2 will appear on - * the second interrupt controller as IRQ9. - */ - if(ether->irq == 2) - ether->irq = 9; - snprint(name, sizeof(name), "ether%d", ctlrno); - - /* - * If ether->irq is <0, it is a hack to indicate no interrupt - * used by ethersink. - */ - if(ether->irq >= 0) - intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name); - - i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d", - ctlrno, cards[cardno].type, ether->mbps, ether->port, ether->irq); - if(ether->mem) - i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem)); - if(ether->size) - i += sprint(buf+i, " size 0x%luX", ether->size); - i += sprint(buf+i, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", - ether->ea[0], ether->ea[1], ether->ea[2], - ether->ea[3], ether->ea[4], ether->ea[5]); - sprint(buf+i, "\n"); - print(buf); - - if (ether->mbps >= 1000) { - netifinit(ether, name, Ntypes, 512*1024); - if(ether->oq == 0) - ether->oq = qopen(512*1024, Qmsg, 0, 0); - } else if(ether->mbps >= 100){ - netifinit(ether, name, Ntypes, 256*1024); - if(ether->oq == 0) - ether->oq = qopen(256*1024, Qmsg, 0, 0); - } - else{ - netifinit(ether, name, Ntypes, 128*1024); - if(ether->oq == 0) - ether->oq = qopen(128*1024, Qmsg, 0, 0); - } - if(ether->oq == 0) - panic("etherreset %s", name); - ether->alen = Eaddrlen; - memmove(ether->addr, ether->ea, Eaddrlen); - memset(ether->bcast, 0xFF, Eaddrlen); - - return ether; -} - -static void -etherreset(void) -{ - Ether *ether; - int cardno, ctlrno; - - for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){ - if((ether = etherprobe(-1, ctlrno)) == nil) - continue; - etherxx[ctlrno] = ether; - } - - if(getconf("*noetherprobe")) - return; - - cardno = ctlrno = 0; - while(cards[cardno].type != nil && ctlrno < MaxEther){ - if(etherxx[ctlrno] != nil){ - ctlrno++; - continue; - } - if((ether = etherprobe(cardno, ctlrno)) == nil){ - cardno++; - continue; - } - etherxx[ctlrno] = ether; - ctlrno++; - } -} - -static void -ethershutdown(void) -{ - Ether *ether; - int i; - - for(i = 0; i < MaxEther; i++){ - ether = etherxx[i]; - if(ether == nil) - continue; - if(ether->shutdown == nil) { - print("#l%d: no shutdown fuction\n", i); - continue; - } - (*ether->shutdown)(ether); - } -} - - -#define POLY 0xedb88320 - -/* really slow 32 bit crc for ethers */ -ulong -ethercrc(uchar *p, int len) -{ - int i, j; - ulong crc, b; - - crc = 0xffffffff; - for(i = 0; i < len; i++){ - b = *p++; - for(j = 0; j < 8; j++){ - crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0); - b >>= 1; - } - } - return crc; -} - -Dev etherdevtab = { - 'l', - "ether", - - etherreset, - devinit, - ethershutdown, - etherattach, - etherwalk, - etherstat, - etheropen, - ethercreate, - etherclose, - etherread, - etherbread, - etherwrite, - etherbwrite, - devremove, - etherwstat, -}; diff --git a/os/pc/devfloppy.c b/os/pc/devfloppy.c deleted file mode 100644 index 2f29147c..00000000 --- a/os/pc/devfloppy.c +++ /dev/null @@ -1,1082 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#include "floppy.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(floppydebug)print -int floppydebug = 0; - -/* - * types of drive (from PC equipment byte) - */ -enum -{ - Tnone= 0, - T360kb= 1, - T1200kb= 2, - T720kb= 3, - T1440kb= 4, -}; - -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*, Cmdbuf*); -static void floppykproc(void*); -static void floppypos(FDrive*,long); -static int floppyrecal(FDrive*); -static int floppyresult(void); -static void floppyrevive(void); -static long floppyseek(FDrive*, long); -static int floppysense(void); -static void floppywait(int); -static long floppyxfer(FDrive*, int, void*, long, long); - -Dirtab floppydir[]={ - ".", {Qdir, 0, QTDIR}, 0, 0550, - "fd0disk", {Qdata + 0}, 0, 0660, - "fd0ctl", {Qctl + 0}, 0, 0660, - "fd1disk", {Qdata + 1}, 0, 0660, - "fd1ctl", {Qctl + 1}, 0, 0660, - "fd2disk", {Qdata + 2}, 0, 0660, - "fd2ctl", {Qctl + 2}, 0, 0660, - "fd3disk", {Qdata + 3}, 0, 0660, - "fd3ctl", {Qctl + 3}, 0, 0660, -}; -#define NFDIR 2 /* directory entries/drive */ - -enum -{ - CMdebug, - CMnodebug, - CMeject, - CMformat, - CMreset, -}; - -static Cmdtab floppyctlmsg[] = -{ - CMdebug, "debug", 1, - CMnodebug, "nodebug", 1, - CMeject, "eject", 1, - CMformat, "format", 0, - CMreset, "reset", 1, -}; - -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)); -} - -/* - * 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; - floppydir[1+NFDIR*dp->dev].length = dp->t->cap; - break; - } -} - -static void -floppyreset(void) -{ - FDrive *dp; - FType *t; - ulong maxtsize; - - floppysetup0(&fl); - if(fl.ndrive == 0) - return; - - /* - * 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; - } - - dmainit(DMAchan, maxtsize); - - /* - * allocate the drive storage - */ - fl.d = xalloc(fl.ndrive*sizeof(FDrive)); - fl.selected = fl.d; - - /* - * stop the motors - */ - fl.motor = 0; - delay(10); - outb(Pdor, fl.motor | Fintena | Fena); - delay(10); - - /* - * init drives - */ - for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){ - dp->dev = dp - fl.d; - dp->dt = T1440kb; - floppysetdef(dp); - dp->cyl = -1; /* because we don't know */ - dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024); - dp->ccyl = -1; - dp->vers = 0; - } - - /* - * first operation will recalibrate - */ - fl.confused = 1; - - floppysetup1(&fl); -} - -static Chan* -floppyattach(char *spec) -{ - static int kstarted; - - if(fl.ndrive == 0) - error(Enodev); - - if(kstarted == 0){ - /* - * watchdog to turn off the motors - */ - kstarted = 1; - kproc("floppy", floppykproc, 0, 0); - } - return devattach('f', spec); -} - -static Walkqid* -floppywalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, floppydir, 1+fl.ndrive*NFDIR, devgen); -} - -static int -floppystat(Chan *c, uchar *dp, int n) -{ - return devstat(c, dp, n, floppydir, 1+fl.ndrive*NFDIR, devgen); -} - -static Chan* -floppyopen(Chan *c, int omode) -{ - return devopen(c, omode, floppydir, 1+fl.ndrive*NFDIR, devgen); -} - -static void -floppyclose(Chan *) -{ -} - -static void -islegal(ulong offset, long n, FDrive *dp) -{ - if(offset % dp->t->bytes) - error(Ebadarg); - if(n % dp->t->bytes) - error(Ebadarg); -} - -/* - * 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 void -changed(Chan *c, FDrive *dp) -{ - ulong old; - FType *start; - - /* - * if floppy has changed or first time through - */ - if((inb(Pdir)&Fchange) || dp->vers == 0){ - DPRINT("changed\n"); - fldump(); - dp->vers++; - start = dp->t; - dp->maxtries = 3; /* limit it when we're probing */ - - /* floppyon will fail if there's a controller but no drive */ - dp->confused = 1; /* make floppyon recal */ - if(floppyon(dp) < 0) - error(Eio); - - /* seek to the first track */ - floppyseek(dp, dp->t->heads*dp->t->tsize); - while(waserror()){ - /* - * if first attempt doesn't reset changed bit, there's - * no floppy there - */ - if(inb(Pdir)&Fchange) - nexterror(); - - while(++dp->t){ - if(dp->t == &floppytype[nelem(floppytype)]) - dp->t = floppytype; - if(dp->dt == dp->t->dt) - break; - } - floppydir[1+NFDIR*dp->dev].length = dp->t->cap; - - /* floppyon will fail if there's a controller but no drive */ - if(floppyon(dp) < 0) - error(Eio); - - DPRINT("changed: trying %s\n", dp->t->name); - fldump(); - if(dp->t == start) - nexterror(); - } - - /* if the read succeeds, we've got the density right */ - floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize); - poperror(); - dp->maxtries = 20; - } - - old = c->qid.vers; - c->qid.vers = dp->vers; - if(old && old != dp->vers) - error(Eio); -} - -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; -} - -static long -floppyread(Chan *c, void *a, long n, vlong off) -{ - FDrive *dp; - long rv; - int sec, head, cyl; - long len; - uchar *aa; - ulong offset = off; - - if(c->qid.type & QTDIR) - return devdirread(c, a, n, floppydir, 1+fl.ndrive*NFDIR, devgen); - - rv = 0; - dp = &fl.d[c->qid.path & ~Qmask]; - switch ((int)(c->qid.path & Qmask)) { - case Qdata: - islegal(offset, n, dp); - aa = a; - - qlock(&fl); - if(waserror()){ - qunlock(&fl); - nexterror(); - } - floppyon(dp); - changed(c, dp); - 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); - } - qunlock(&fl); - poperror(); - - break; - case Qctl: - return readstr(offset, a, n, dp->t->name); - default: - panic("floppyread: bad qid"); - } - - return rv; -} - -static long -floppywrite(Chan *c, void *a, long n, vlong off) -{ - FDrive *dp; - long rv, i; - char *aa = a; - Cmdbuf *cb; - Cmdtab *ct; - ulong offset = off; - - rv = 0; - dp = &fl.d[c->qid.path & ~Qmask]; - switch ((int)(c->qid.path & Qmask)) { - case Qdata: - islegal(offset, n, dp); - qlock(&fl); - if(waserror()){ - qunlock(&fl); - nexterror(); - } - floppyon(dp); - changed(c, dp); - for(rv = 0; rv < n; rv += i){ - floppypos(dp, offset+rv); - if(dp->tcyl == dp->ccyl) - dp->ccyl = -1; - i = floppyxfer(dp, Fwrite, aa+rv, offset+rv, n-rv); - if(i < 0) - break; - if(i == 0) - error(Eio); - } - qunlock(&fl); - poperror(); - break; - case Qctl: - rv = n; - cb = parsecmd(a, n); - if(waserror()){ - free(cb); - nexterror(); - } - qlock(&fl); - if(waserror()){ - qunlock(&fl); - nexterror(); - } - ct = lookupcmd(cb, floppyctlmsg, nelem(floppyctlmsg)); - switch(ct->index){ - case CMeject: - floppyeject(dp); - break; - case CMformat: - floppyformat(dp, cb); - break; - case CMreset: - fl.confused = 1; - floppyon(dp); - break; - case CMdebug: - floppydebug = 1; - break; - case CMnodebug: - floppydebug = 0; - break; - } - poperror(); - qunlock(&fl); - poperror(); - free(cb); - break; - default: - panic("floppywrite: bad qid"); - } - - return rv; -} - -static void -floppykproc(void *) -{ - FDrive *dp; - - while(waserror()) - ; - for(;;){ - for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){ - if((fl.motor&MOTORBIT(dp->dev)) - && TK2SEC(m->ticks - dp->lasttouched) > 5 - && canqlock(&fl)){ - if(TK2SEC(m->ticks - dp->lasttouched) > 5) - floppyoff(dp); - qunlock(&fl); - } - } - tsleep(&up->sleep, return0, 0, 1000); - } -} - -/* - * start a floppy drive's motor. - */ -static int -floppyon(FDrive *dp) -{ - int alreadyon; - int tries; - - if(fl.confused) - floppyrevive(); - - /* start motor and select drive */ - alreadyon = fl.motor & MOTORBIT(dp->dev); - fl.motor |= MOTORBIT(dp->dev); - outb(Pdor, fl.motor | Fintena | Fena | dp->dev); - if(!alreadyon){ - /* wait for drive to spin up */ - tsleep(&up->sleep, 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; - - /* return -1 if this didn't work */ - 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(8); /* for machine independence */ - } - 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(8); /* for machine independence */ - } - fl.stat[i] = inb(Pfdata); - } - fl.nstat = sizeof(fl.stat); - return fl.nstat; -} - -/* - * calculate physical address of a logical byte offset into the disk - * - * truncate dp->length if it crosses a track boundary - */ -static void -floppypos(FDrive *dp, long off) -{ - int lsec; - int ltrack; - int end; - - lsec = off/dp->t->bytes; - ltrack = lsec/dp->t->sectors; - dp->tcyl = ltrack/dp->t->heads; - dp->tsec = (lsec % dp->t->sectors) + 1; - dp->thead = (lsec/dp->t->sectors) % dp->t->heads; - - /* - * can't read across track boundaries. - * if so, decrement the bytes to be read. - */ - end = (ltrack+1)*dp->t->sectors*dp->t->bytes; - if(off+dp->len > end) - dp->len = end - off; -} - -/* - * get the interrupt cause from the floppy. - */ -static int -floppysense(void) -{ - fl.ncmd = 0; - fl.cmd[fl.ncmd++] = Fsense; - if(floppycmd() < 0) - return -1; - if(floppyresult() < 2){ - DPRINT("can't read sense response\n"); - fldump(); - fl.confused = 1; - return -1; - } - return 0; -} - -static int -cmddone(void *) -{ - 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) -{ - tsleep(&fl.r, 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 known 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 long -floppyseek(FDrive *dp, long off) -{ - floppypos(dp, off); - if(dp->cyl == dp->tcyl) - return dp->tcyl; - 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; - return dp->tcyl; -} - -/* - * 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) */ - tries = 0; - while(waserror()){ - if(tries++ >= dp->maxtries) - nexterror(); - DPRINT("floppyxfer: retrying\n"); - } - - dp->len = n; - if(floppyseek(dp, off) < 0){ - DPRINT("xfer: seek failed\n"); - dp->confused = 1; - error(Eio); - } - - /* - * set up the dma (dp->len may be trimmed) - */ - if(waserror()){ - dmaend(DMAchan); - nexterror(); - } - dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread); - if(dp->len < 0) - error(Eio); - - /* - * 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) - error(Eio); - - /* Poll ready bits and transfer data */ - floppyexec((char*)a, dp->len, cmd==Fread); - - /* - * give bus to DMA, floppyintr() will read result - */ - floppywait(0); - dmaend(DMAchan); - poperror(); - - /* - * check for errors - */ - if(fl.nstat < 7){ - DPRINT("xfer: confused\n"); - fl.confused = 1; - error(Eio); - } - 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; - error(Eio); - } - - /* - * 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; - error(Eio); - } - poperror(); - - dp->lasttouched = m->ticks; - return dp->len; -} - -/* - * format a track - */ -static void -floppyformat(FDrive *dp, Cmdbuf *cb) -{ - int cyl, h, sec; - ulong track; - uchar *buf, *bp; - FType *t; - - /* - * set the type - */ - if(cb->nf == 2){ - for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){ - if(strcmp(cb->f[1], t->name)==0 && t->dt==dp->dt){ - dp->t = t; - floppydir[1+NFDIR*dp->dev].length = dp->t->cap; - break; - } - } - if(t >= &floppytype[nelem(floppytype)]) - error(Ebadarg); - } else if(cb->nf == 1){ - floppysetdef(dp); - t = dp->t; - } else { - cmderror(cb, "invalid floppy format command"); - SET(t); - } - - /* - * buffer for per track info - */ - buf = smalloc(t->sectors*4); - if(waserror()){ - free(buf); - nexterror(); - } - - /* force a recalibrate to cylinder 0 */ - dp->confused = 1; - if(!waserror()){ - floppyon(dp); - poperror(); - } - - /* - * format a track at time - */ - for(track = 0; track < t->tracks*t->heads; track++){ - cyl = track/t->heads; - h = track % t->heads; - - /* - * seek to track, ignore errors - */ - floppyseek(dp, track*t->tsize); - dp->cyl = cyl; - dp->confused = 0; - - /* - * set up the dma (dp->len may be trimmed) - */ - bp = buf; - for(sec = 1; sec <= t->sectors; sec++){ - *bp++ = cyl; - *bp++ = h; - *bp++ = sec; - *bp++ = t->bcode; - } - if(waserror()){ - dmaend(DMAchan); - nexterror(); - } - if(dmasetup(DMAchan, buf, bp-buf, 0) < 0) - error(Eio); - - /* - * start operation - */ - fl.ncmd = 0; - fl.cmd[fl.ncmd++] = Fformat; - fl.cmd[fl.ncmd++] = (h<<2) | dp->dev; - fl.cmd[fl.ncmd++] = t->bcode; - fl.cmd[fl.ncmd++] = t->sectors; - fl.cmd[fl.ncmd++] = t->fgpl; - fl.cmd[fl.ncmd++] = 0x5a; - if(floppycmd() < 0) - error(Eio); - - /* Poll ready bits and transfer data */ - floppyexec((char *)buf, bp-buf, 0); - - /* - * give bus to DMA, floppyintr() will read result - */ - floppywait(1); - dmaend(DMAchan); - poperror(); - - /* - * check for errors - */ - if(fl.nstat < 7){ - DPRINT("format: confused\n"); - fl.confused = 1; - error(Eio); - } - if((fl.stat[0]&Codemask)!=0 || fl.stat[1]|| fl.stat[2]){ - DPRINT("format: failed %ux %ux %ux\n", - fl.stat[0], fl.stat[1], fl.stat[2]); - dp->confused = 1; - error(Eio); - } - } - free(buf); - dp->confused = 1; - poperror(); -} - -static void -floppyintr(Ureg *) -{ - 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; - wakeup(&fl.r); -} - -Dev floppydevtab = { - 'f', - "floppy", - - floppyreset, - devinit, - devshutdown, - floppyattach, - floppywalk, - floppystat, - floppyopen, - devcreate, - floppyclose, - floppyread, - devbread, - floppywrite, - devbwrite, - devremove, - devwstat, -}; diff --git a/os/pc/devi82365.c b/os/pc/devi82365.c deleted file mode 100644 index 5c67847f..00000000 --- a/os/pc/devi82365.c +++ /dev/null @@ -1,1044 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/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, -}; - -#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 int pcmio(int, ISAConf*); -static long pcmread(int, int, void*, long, vlong); -static long pcmwrite(int, int, void*, long, vlong); - -static void i82365dump(PCMslot*); - -/* - * 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(5000); - - /* 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<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: out of isa space\n"); - 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<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; - - for(pp = slot; pp < lastslot; pp++){ - if(pp->special) - continue; /* already taken */ - - /* - * make sure we don't power on cards when we already know what's - * in them. We'll reread every two minutes if necessary - */ - enabled = 0; - if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000){ - 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; - - if(slotno >= nslot) - panic("pcmspecialclose"); - pp = slot + slotno; - pp->special = 0; - decrefp(pp); -} - -enum -{ - Qdir, - Qmem, - Qattr, - Qctl, - - Nents = 3, -}; - -#define SLOTNO(c) ((ulong)((c->qid.path>>8)&0xff)) -#define TYPE(c) ((ulong)(c->qid.path&0xff)) -#define QID(s,t) (((s)<<8)|(t)) - -static int -pcmgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp) -{ - int slotno; - Qid qid; - long len; - PCMslot *pp; - - if(i == DEVDOTDOT){ - mkqid(&qid, Qdir, 0, QTDIR); - devdir(c, qid, "#y", 0, eve, 0555, dp); - return 1; - } - - if(i >= Nents*nslot) - return -1; - slotno = i/Nents; - pp = slot + slotno; - len = 0; - switch(i%Nents){ - case 0: - qid.path = QID(slotno, Qmem); - snprint(up->genbuf, sizeof up->genbuf, "pcm%dmem", slotno); - len = pp->memlen; - break; - case 1: - qid.path = QID(slotno, Qattr); - snprint(up->genbuf, sizeof up->genbuf, "pcm%dattr", slotno); - len = pp->memlen; - break; - case 2: - qid.path = QID(slotno, Qctl); - snprint(up->genbuf, sizeof up->genbuf, "pcm%dctl", slotno); - break; - } - qid.vers = 0; - qid.type = QTFILE; - devdir(c, qid, up->genbuf, len, eve, 0660, dp); - return 1; -} - -static char *chipname[] = -{ -[Ti82365] "Intel 82365SL", -[Tpd6710] "Cirrus Logic CL-PD6710", -[Tpd6720] "Cirrus Logic CL-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 = IrqPCMCIA; - - 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); - print("%2.2uX ", rdreg(pp, i)); - if(((i+1) & 0x0F) == 0x08) - print(" - "); - } - print("\n"); -} - -/* - * set up for slot cards - */ -void -devi82365link(void) -{ - static int already; - int i, j; - I82365 *cp; - PCMslot *pp; - char buf[32], *p; - - if(already) - return; - already = 1; - - if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0) - return; - - if(_pcmspecial) - return; - - /* look for controllers if the ports aren't already taken */ - if(ioalloc(0x3E0, 2, 0, "i82365.0") >= 0){ - i82365probe(0x3E0, 0x3E1, 0); - i82365probe(0x3E0, 0x3E1, 1); - if(ncontroller == 0) - iofree(0x3E0); - } - if(ioalloc(0x3E2, 2, 0, "i82365.1") >= 0){ - i = ncontroller; - i82365probe(0x3E2, 0x3E3, 0); - i82365probe(0x3E2, 0x3E3, 1); - if(ncontroller == i) - iofree(0x3E2); - } - - if(ncontroller == 0) - return; - - _pcmspecial = pcmcia_pcmspecial; - _pcmspecialclose = pcmcia_pcmspecialclose; - - 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 */ - snprint(buf, sizeof buf, "i82365.%d", i); - intrenable(cp->irq, i82365intr, 0, BUSUNKNOWN, buf); - } -} - -static Chan* -i82365attach(char *spec) -{ - return devattach('y', spec); -} - -static Walkqid* -i82365walk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, 0, 0, pcmgen); -} - -static int -i82365stat(Chan *c, uchar *db, int n) -{ - return devstat(c, db, n, 0, 0, pcmgen); -} - -static Chan* -i82365open(Chan *c, int omode) -{ - if(c->qid.type & QTDIR){ - if(omode != OREAD) - error(Eperm); - } else - increfp(slot + SLOTNO(c)); - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - return c; -} - -static void -i82365close(Chan *c) -{ - if(c->flag & COPEN) - if((c->qid.type & QTDIR) == 0) - decrefp(slot+SLOTNO(c)); -} - -/* a memmove using only bytes */ -static void -memmoveb(uchar *to, uchar *from, int n) -{ - while(n-- > 0) - *to++ = *from++; -} - -/* a memmove using only shorts & bytes */ -static void -memmoves(uchar *to, uchar *from, int n) -{ - ushort *t, *f; - - if((((ulong)to) & 1) || (((ulong)from) & 1) || (n & 1)){ - while(n-- > 0) - *to++ = *from++; - } else { - n = n/2; - t = (ushort*)to; - f = (ushort*)from; - while(n-- > 0) - *t++ = *f++; - } -} - -static long -pcmread(int slotno, int attr, void *a, long n, vlong off) -{ - int i, len; - PCMmap *m; - uchar *ac; - PCMslot *pp; - ulong offset = off; - - pp = slot + slotno; - if(pp->memlen < offset) - return 0; - if(pp->memlen < offset + n) - n = pp->memlen - offset; - - m = 0; - if(waserror()){ - if(m) - pcmunmap(pp->slotno, m); - nexterror(); - } - - ac = a; - for(len = n; len > 0; len -= i){ - m = pcmmap(pp->slotno, offset, 0, attr); - if(m == 0) - error("cannot map PCMCIA card"); - if(offset + len > m->cea) - i = m->cea - offset; - else - i = len; - memmoveb(ac, KADDR(m->isa + offset - m->ca), i); - pcmunmap(pp->slotno, m); - offset += i; - ac += i; - } - - poperror(); - return n; -} - -static long -i82365read(Chan *c, void *a, long n, vlong off) -{ - char *p, *buf, *e; - PCMslot *pp; - ulong offset = off; - - switch(TYPE(c)){ - case Qdir: - return devdirread(c, a, n, 0, 0, pcmgen); - case Qmem: - case Qattr: - return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, off); - case Qctl: - buf = p = malloc(READSTR); - e = p + READSTR; - pp = slot + SLOTNO(c); - - buf[0] = 0; - if(pp->occupied){ - p = seprint(p, e, "occupied\n"); - if(pp->verstr[0]) - p = seprint(p, e, "version %s\n", pp->verstr); - } - if(pp->enabled) - p = seprint(p, e, "enabled\n"); - if(pp->powered) - p = seprint(p, e, "powered\n"); - if(pp->configed) - p = seprint(p, e, "configed\n"); - if(pp->wrprot) - p = seprint(p, e, "write protected\n"); - if(pp->busy) - p = seprint(p, e, "busy\n"); - seprint(p, e, "battery lvl %d\n", pp->battery); - - n = readstr(offset, a, n, buf); - free(buf); - - return n; - } - error(Ebadarg); - return -1; /* not reached */ -} - -static long -pcmwrite(int dev, int attr, void *a, long n, vlong off) -{ - int i, len; - PCMmap *m; - uchar *ac; - PCMslot *pp; - ulong offset = off; - - pp = slot + dev; - if(pp->memlen < offset) - return 0; - if(pp->memlen < offset + n) - n = pp->memlen - offset; - - m = 0; - if(waserror()){ - if(m) - pcmunmap(pp->slotno, m); - nexterror(); - } - - ac = a; - for(len = n; len > 0; len -= i){ - m = pcmmap(pp->slotno, offset, 0, attr); - if(m == 0) - error("cannot map PCMCIA card"); - if(offset + len > m->cea) - i = m->cea - offset; - else - i = len; - memmoveb(KADDR(m->isa + offset - m->ca), ac, i); - pcmunmap(pp->slotno, m); - offset += i; - ac += i; - } - - poperror(); - return n; -} - -static long -i82365write(Chan *c, void *a, long n, vlong off) -{ - PCMslot *pp; - char buf[32]; - - switch(TYPE(c)){ - case Qctl: - if(n >= sizeof(buf)) - n = sizeof(buf) - 1; - strncpy(buf, a, n); - buf[n] = 0; - pp = slot + SLOTNO(c); - if(!pp->occupied) - error(Eio); - - /* set vpp on card */ - if(strncmp(buf, "vpp", 3) == 0) - wrreg(pp, Rpc, vcode(atoi(buf+3))|Fautopower|Foutena|Fcardena); - return n; - case Qmem: - case Qattr: - pp = slot + SLOTNO(c); - if(pp->occupied == 0 || pp->enabled == 0) - error(Eio); - n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, off); - if(n < 0) - error(Eio); - return n; - } - error(Ebadarg); - return -1; /* not reached */ -} - -Dev i82365devtab = { - 'y', - "i82365", - - devreset, - devinit, - devshutdown, - i82365attach, - i82365walk, - i82365stat, - i82365open, - devcreate, - i82365close, - i82365read, - devbread, - i82365write, - devbwrite, - devremove, - devwstat, -}; - -/* - * 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<irqs) == 0){ - for(t = pp->ctab; t < et; t++) - if(t->nio - && t->io[0].start == isa->port - && ((1<irqs)){ - ct = t; - break; - } - } - if(ct->nio == 0 || ((1<irqs) == 0){ - for(t = pp->ctab; t < et; t++) - if(t->nio && ((1<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<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<port; - p[Riobase1 << 1] = isa->port >> 8; - } - - if(pp->cfg[0].cpresent & (1<io[0].len; - pcmunmap(slotno, m); - return 0; -} diff --git a/os/pc/devlm78.c b/os/pc/devlm78.c deleted file mode 100644 index 617d5cb9..00000000 --- a/os/pc/devlm78.c +++ /dev/null @@ -1,346 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" -#include "../port/error.h" - -/* this driver doesn't implement the management interrupts. we - * leave the LM78 interrupts set to whatever the BIOS did. we do - * allow reading and writing the the readouts and alarm values. - * Read(2)ing or write(2)ing at offset 0x0-0x1f, is - * equivalent to reading or writing lm78 registers 0x20-0x3f. - */ -enum -{ - /* address of chip on serial interface */ - Serialaddr= 0x2d, - - /* parallel access registers */ - Rpaddr= 0x5, - Bbusy= (1<<7), - Rpdata= 0x6, - - /* internal register addresses */ - Rconfig= 0x40, - Bstart= (1<<0), - Bsmiena= (1<<1), - Birqena= (1<<2), - Bintclr= (1<<3), - Breset= (1<<4), - Bnmi= (1<<5), /* if set, use nmi, else irq */ - Bpowbypass= (1<<6), - Binit= (1<<7), - Ristat1= 0x41, - Ristat2= 0x42, - Rsmimask1= 0x43, - Rsmimask2= 0x44, - Rnmimask1= 0x45, - Rnmimask2= 0x46, - Rvidfan= 0x47, /* set fan counter, and read voltage level */ - Mvid= 0x0f, - Mfan= 0xf0, - Raddr= 0x48, /* address used on serial bus */ - Rresetid= 0x49, /* chip reset and ID register */ - Rpost= 0x00, /* start of post ram */ - Rvalue= 0x20, /* start of value ram */ - - VRsize= 0x20, /* size of value ram */ -}; - -enum -{ - Qdir, - Qlm78vram, -}; - -static Dirtab lm78dir[] = { - ".", { Qdir, 0, QTDIR}, 0, 0555, - "lm78vram", { Qlm78vram, 0 }, 0, 0444, -}; - -/* interface type */ -enum -{ - None= 0, - Smbus, - Parallel, -}; - -static struct { - QLock; - int probed; - int ifc; /* which interface is connected */ - SMBus *smbus; /* serial interface */ - int port; /* parallel interface */ -} lm78; - -extern SMBus* piix4smbus(void); - -/* wait for device to become quiescent and then set the */ -/* register address */ -static void -setreg(int reg) -{ - int tries; - - for(tries = 0; tries < 1000000; tries++) - if((inb(lm78.port+Rpaddr) & Bbusy) == 0){ - outb(lm78.port+Rpaddr, reg); - return; - } - error("lm78 broken"); -} - -/* routines that actually touch the device */ -static void -lm78wrreg(int reg, uchar val) -{ - if(waserror()){ - qunlock(&lm78); - nexterror(); - } - qlock(&lm78); - - switch(lm78.ifc){ - case Smbus: - lm78.smbus->transact(lm78.smbus, SMBbytewrite, Serialaddr, reg, &val); - break; - case Parallel: - setreg(reg); - outb(lm78.port+Rpdata, val); - break; - default: - error(Enodev); - break; - } - - qunlock(&lm78); - poperror(); -} - -static int -lm78rdreg(int reg) -{ - uchar val; - - if(waserror()){ - qunlock(&lm78); - nexterror(); - } - qlock(&lm78); - - switch(lm78.ifc){ - case Smbus: - lm78.smbus->transact(lm78.smbus, SMBsend, Serialaddr, reg, nil); - lm78.smbus->transact(lm78.smbus, SMBrecv, Serialaddr, 0, &val); - break; - case Parallel: - setreg(reg); - val = inb(lm78.port+Rpdata); - break; - default: - error(Enodev); - break; - } - - qunlock(&lm78); - poperror(); - return val; -} - -/* start the chip monitoring but don't change any smi - * interrupts and/or alarms that the BIOS may have set up. - * this isn't locked because it's thought to be idempotent - */ -static void -lm78enable(void) -{ - uchar config; - - if(lm78.ifc == None) - error(Enodev); - - if(lm78.probed == 0){ - /* make sure its really there */ - if(lm78rdreg(Raddr) != Serialaddr){ - lm78.ifc = None; - error(Enodev); - } else { - /* start the sampling */ - config = lm78rdreg(Rconfig); - config = (config | Bstart) & ~(Bintclr|Binit); - lm78wrreg(Rconfig, config); -pprint("Rvidfan %2.2ux\n", lm78rdreg(Rconfig), lm78rdreg(Rvidfan)); - } - lm78.probed = 1; - } -} - -enum -{ - IntelVendID= 0x8086, - PiixID= 0x122E, - Piix3ID= 0x7000, - - Piix4PMID= 0x7113, /* PIIX4 power management function */ - - PCSC= 0x78, /* programmable chip select control register */ - PCSC8bytes= 0x01, -}; - -/* figure out what kind of interface we could have */ -void -lm78reset(void) -{ - int pcs; - Pcidev *p; - - lm78.ifc = None; - p = nil; - while((p = pcimatch(p, IntelVendID, 0)) != nil){ - switch(p->did){ - /* these bridges use the PCSC to map the lm78 into port space. */ - /* for this case the lm78's CS# select is connected to the PIIX's */ - /* PCS# output and the bottom 3 bits of address are passed to the */ - /* LM78's A0-A2 inputs. */ - case PiixID: - case Piix3ID: - pcs = pcicfgr16(p, PCSC); - if(pcs & 3) { - /* already enabled */ - lm78.port = pcs & ~3; - lm78.ifc = Parallel; - return; - } - - /* enable the chip, use default address 0x50 */ - pcicfgw16(p, PCSC, 0x50|PCSC8bytes); - pcs = pcicfgr16(p, PCSC); - lm78.port = pcs & ~3; - lm78.ifc = Parallel; - return; - - /* this bridge puts the lm78's serial interface on the smbus */ - case Piix4PMID: - lm78.smbus = piix4smbus(); - if(lm78.smbus == nil) - continue; - print("found piix4 smbus, base %lud\n", lm78.smbus->base); - lm78.ifc = Smbus; - return; - } - } -} - -Walkqid * -lm78walk(Chan* c, Chan *nc, char** name, int nname) -{ - return devwalk(c, nc, name, nname, lm78dir, nelem(lm78dir), devgen); -} - -static int -lm78stat(Chan* c, uchar* dp, int n) -{ - return devstat(c, dp, n, lm78dir, nelem(lm78dir), devgen); -} - -static Chan* -lm78open(Chan* c, int omode) -{ - return devopen(c, omode, lm78dir, nelem(lm78dir), devgen); -} - -static void -lm78close(Chan*) -{ -} - -enum -{ - Linelen= 25, -}; - -static long -lm78read(Chan *c, void *a, long n, vlong offset) -{ - uchar *va = a; - int off, e; - - off = offset; - - switch((ulong)c->qid.path){ - case Qdir: - return devdirread(c, a, n, lm78dir, nelem(lm78dir), devgen); - - case Qlm78vram: - if(off >= VRsize) - return 0; - e = off + n; - if(e > VRsize) - e = VRsize; - for(; off < e; off++) - *va++ = lm78rdreg(Rvalue+off); - return (int)(va - (uchar*)a); - } - return 0; -} - -static long -lm78write(Chan *c, void *a, long n, vlong offset) -{ - uchar *va = a; - int off, e; - - off = offset; - - switch((ulong)c->qid.path){ - default: - error(Eperm); - - case Qlm78vram: - if(off >= VRsize) - return 0; - e = off + n; - if(e > VRsize) - e = VRsize; - for(; off < e; off++) - lm78wrreg(Rvalue+off, *va++); - return va - (uchar*)a; - } - return 0; -} - -extern Dev lm78devtab; - -static Chan* -lm78attach(char* spec) -{ - lm78enable(); - - return devattach(lm78devtab.dc, spec); -} - -Dev lm78devtab = { - 'T', - "lm78", - - lm78reset, - devinit, - devshutdown, - lm78attach, - lm78walk, - lm78stat, - lm78open, - devcreate, - lm78close, - lm78read, - devbread, - lm78write, - devbwrite, - devremove, - devwstat, -}; - diff --git a/os/pc/devlpt.c b/os/pc/devlpt.c deleted file mode 100644 index 2fbc2aba..00000000 --- a/os/pc/devlpt.c +++ /dev/null @@ -1,245 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -/* Centronix parallel (printer) port */ - -/* base addresses */ -static int lptbase[] = { - 0x378, /* lpt1 */ - 0x3bc, /* lpt2 */ - 0x278 /* lpt3 (sic) */ -}; -#define NDEV nelem(lptbase) -static int lptallocd[NDEV]; - -/* offsets, and bits in the registers */ -enum -{ - Qdir= 0x8000, - /* data latch register */ - Qdlr= 0x0, - /* printer status register */ - Qpsr= 0x1, - Fnotbusy= 0x80, - Fack= 0x40, - Fpe= 0x20, - Fselect= 0x10, - Fnoerror= 0x08, - /* printer control register */ - Qpcr= 0x2, - Fie= 0x10, - Fselectin= 0x08, - Finitbar= 0x04, - Faf= 0x02, - Fstrobe= 0x01, - /* fake `data register' */ - Qdata= 0x3, -}; - -static int lptready(void*); -static void outch(int, int); -static void lptintr(Ureg*, void*); - -static Rendez lptrendez; - -Dirtab lptdir[]={ - ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, - "dlr", {Qdlr}, 1, 0666, - "psr", {Qpsr}, 5, 0444, - "pcr", {Qpcr}, 0, 0222, - "data", {Qdata}, 0, 0222, -}; - -static int -lptgen(Chan *c, char*, Dirtab *tab, int ntab, int i, Dir *dp) -{ - Qid qid; - - if(i == DEVDOTDOT){ - mkqid(&qid, Qdir, 0, QTDIR); - devdir(c, qid, ".", 0, eve, 0555, dp); - return 1; - } - i++; /* skip first element for . itself */ - if(tab==0 || i>=ntab) - return -1; - tab += i; - qid = tab->qid; - qid.path &= ~Qdir; - if(qid.path < Qdata) - qid.path += lptbase[c->dev]; - qid.vers = c->dev; - sprint(up->genbuf, "lpt%lud%s", c->dev+1, tab->name); - devdir(c, qid, up->genbuf, tab->length, eve, tab->perm, dp); - return 1; -} - -static Chan* -lptattach(char *spec) -{ - Chan *c; - int i = (spec && *spec) ? strtol(spec, 0, 0) : 1; - char name[5]; - static int set; - - if(!set){ - outb(lptbase[i-1]+Qpcr, 0); /* turn off interrupts */ - set = 1; - intrenable(IrqLPT, lptintr, 0, BUSUNKNOWN, "lpt"); - } - if(i < 1 || i > NDEV) - error(Ebadarg); - if(lptallocd[i-1] == 0){ - int ecr; - sprint(name, "lpt%d", i-1); - if(ioalloc(lptbase[i-1], 3, 0, name) < 0) - error("lpt port space in use"); - lptallocd[i-1] = 1; - // Detect ECP - if found, put into PS/2 mode to suit style of driver - ecr = lptbase[i-1] + 0x402; - if ((inb(ecr) & 3) == 1) { - outb(ecr, 0x34); - if (inb(ecr) == 0x35) { - outb(ecr, (inb(ecr) & 0x1f) | (1 << 5)); - if(ioalloc(ecr, 1, 0, name) < 0) - error("lpt ecr port space in use"); - } - } - } - c = devattach('L', spec); - c->qid.path = Qdir; - c->dev = i-1; - return c; -} - -static Walkqid* -lptwalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, lptdir, nelem(lptdir), lptgen); -} - -static int -lptstat(Chan *c, uchar *dp, int n) -{ - return devstat(c, dp, n, lptdir, nelem(lptdir), lptgen); -} - -static Chan* -lptopen(Chan *c, int omode) -{ - return devopen(c, omode, lptdir, nelem(lptdir), lptgen); -} - -static void -lptclose(Chan *) -{ -} - -static long -lptread(Chan *c, void *a, long n, vlong) -{ - char str[16]; - int size; - ulong o; - - if(c->qid.path == Qdir) - return devdirread(c, a, n, lptdir, nelem(lptdir), lptgen); - size = sprint(str, "0x%2.2ux\n", inb(c->qid.path)); - o = c->offset; - if(o >= size) - return 0; - if(o+n > size) - n = size-c->offset; - memmove(a, str+o, n); - return n; -} - -static long -lptwrite(Chan *c, void *a, long n, vlong) -{ - char str[16], *p; - long base, k; - - if(n <= 0) - return 0; - if(c->qid.path != Qdata){ - if(n > sizeof str-1) - n = sizeof str-1; - memmove(str, a, n); - str[n] = 0; - outb(c->qid.path, strtoul(str, 0, 0)); - return n; - } - p = a; - k = n; - base = lptbase[c->dev]; - if(waserror()){ - outb(base+Qpcr, Finitbar); - nexterror(); - } - while(--k >= 0) - outch(base, *p++); - poperror(); - return n; -} - -static void -outch(int base, int c) -{ - int status, tries; - - for(tries=0;; tries++) { - status = inb(base+Qpsr); - if(status&Fnotbusy) - break; - if((status&Fpe)==0 && (status&(Fselect|Fnoerror)) != (Fselect|Fnoerror)) - error(Eio); - if(tries < 10) - tsleep(&lptrendez, return0, nil, 1); - else { - outb(base+Qpcr, Finitbar|Fie); - tsleep(&lptrendez, lptready, (void *)base, 100); - } - } - outb(base+Qdlr, c); - outb(base+Qpcr, Finitbar|Fstrobe); - outb(base+Qpcr, Finitbar); -} - -static int -lptready(void *base) -{ - return inb((int)base+Qpsr)&Fnotbusy; -} - -static void -lptintr(Ureg *, void *) -{ - wakeup(&lptrendez); -} - -Dev lptdevtab = { - 'L', - "lpt", - - devreset, - devinit, - devshutdown, - lptattach, - lptwalk, - lptstat, - lptopen, - devcreate, - lptclose, - lptread, - devbread, - lptwrite, - devbwrite, - devremove, - devwstat, -}; diff --git a/os/pc/devmouse.c b/os/pc/devmouse.c deleted file mode 100644 index 1b3c55c6..00000000 --- a/os/pc/devmouse.c +++ /dev/null @@ -1,672 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -/* - * TODO - * - shift key should modify right button with non-serial mice - * + intellimouse implementation - * - acceleration for all mouse types - * + spurious interrupt 7 after probing for ps2 mouse for the first time...? - * - test with ms busmouse - * - test with logitech serial mouse - */ - -/* - * mouse types - */ -enum -{ - Mouseother, - Mouseserial, - MousePS2, - Mousebus, - Mouseintelli, - Mousemsbus, -}; - -static int mousetype; -static int mouseswap; -static int mouseport; /* port for serial mice, irq for bus mice */ -static int mousesubtype; -static int accelerated; -static QLock mouselock; - -static int msbusmousedetect(void); -static int busmousedetect(void); -static void mousectl(char *buf); -static void mouseprobe(char *buf, int len); -static void mousestatus(char *buf, int len); - -enum{ - Qdir, - Qmousectl, - Qmouseprobe, -}; - -static -Dirtab mousetab[]={ - "mousectl", {Qmousectl, 0}, 0, 0600, - "mouseprobe", {Qmouseprobe, 0}, 0, 0400, -}; - -static Chan* -mouseattach(char* spec) -{ - return devattach('m', spec); -} - -static int -mousewalk(Chan* c, char* name) -{ - return devwalk(c, name, mousetab, nelem(mousetab), devgen); -} - -static void -mousestat(Chan* c, char* db) -{ - devstat(c, db, mousetab, nelem(mousetab), devgen); -} - -static Chan* -mouseopen(Chan* c, int omode) -{ - return devopen(c, omode, mousetab, nelem(mousetab), devgen); -} - -static void -mouseclose(Chan* c) -{ - USED(c); -} - -static long -mouseread(Chan* c, void* a, long n, vlong offset) -{ - char buf[64]; - USED(offset); - - switch(c->qid.path & ~CHDIR){ - case Qdir: - return devdirread(c, a, n, mousetab, nelem(mousetab), devgen); - case Qmousectl: - qlock(&mouselock); - mousestatus(buf, sizeof(buf)); - qunlock(&mouselock); - n = readstr(offset, a, n, buf); - break; - case Qmouseprobe: - if (mousetype) - error(Emouseset); - mouseprobe(buf, sizeof(buf)); - n = readstr(offset, a, n, buf); - break; - default: - n=0; - break; - } - return n; -} - -static long -mousewrite(Chan* c, void *a, long n, vlong) -{ - char buf[64]; - if ((c->qid.path & ~CHDIR) != Qmousectl) - error(Ebadusefd); - if (n >= sizeof(buf)) - n = sizeof(buf) - 1; - strncpy(buf, a, n); - buf[n] = 0; - - qlock(&mouselock); - if (waserror()) { - qunlock(&mouselock); - nexterror(); - } - mousectl(buf); - poperror(); - qunlock(&mouselock); - return n; -} - -static void -track(int b, int dx, int dy) -{ - static uchar map[8] = {0,4,2,6,1,5,3,7}; - if (mouseswap) - b = map[b&7]; - mousetrack(b, dx, dy); -} - -static void -setintellimouse(void) -{ - i8042auxcmd(0xF3); /* set sample */ - i8042auxcmd(0xC8); - i8042auxcmd(0xF3); /* set sample */ - i8042auxcmd(0x64); - i8042auxcmd(0xF3); /* set sample */ - i8042auxcmd(0x50); -} - -/* - * check for an Intellimouse. - * this is only used when we know there's an 8042 aux device - */ -static int -intellimousedetect(void) -{ - int id; - setintellimouse(); - /* check whether the mouse is now in extended mode */ - id = i8042auxcmdval(0xf2); /* identify device */ - if (id != 3) { - /* - * set back to standard sample rate (100 per sec) - */ - i8042auxcmd(0xf3); - i8042auxcmd(0x64); - return 0; - } - return 1; -} - -static void -mouseprobe(char *buf, int len) -{ - USED(len); - /* - * bus mice are easiest, so probe them first - */ - if (busmousedetect()) - sprint(buf, "bus\n"); - else if (msbusmousedetect()) - sprint(buf, "msbus\n"); - else if (i8042auxdetect()) { - if (intellimousedetect()) - sprint(buf, "ps2intellimouse\n"); - else - sprint(buf, "ps2\n"); - } - else - *buf = 0; -} - - -static void -mousestatus(char *buf, int len) -{ - char *s; - USED(len); - s = buf; - switch (mousetype) { - case Mouseserial: - if (mousesubtype) - s += sprint(s, "serial %d %c\n", mouseport, mousesubtype); - else - s += sprint(s, "serial %d\n", mouseport); - break; - case MousePS2: - s += sprint(s, "ps2\n"); - break; - case Mousebus: - s += sprint(s, "bus %d\n", mouseport); - break; - case Mouseintelli: - s += sprint(s, "intelli\n"); - break; - case Mousemsbus: - s += sprint(s, "msbus %d\n", mouseport); - break; - default: - case Mouseother: - s += sprint(s, "unknown\n"); - break; - } - if (accelerated) - s += sprint(s, "accelerated\n"); - if (mouseswap) - sprint(s, "swap\n"); -} - -/* - * Logitech 5 byte packed binary mouse format, 8 bit bytes - * - * shift & right button is the same as middle button (for 2 button mice) - */ -static int -logitechmouseputc(Queue *q, int c) -{ - static short msg[5]; - static int nb; - static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7, 0, 2, 2, 6, 1, 5, 3, 7}; - int dx, dy, newbuttons; - int mouseshifted; - - USED(q); - if((c&0xF0) == 0x80) - nb=0; - msg[nb] = c; - if(c & 0x80) - msg[nb] |= ~0xFF; /* sign extend */ - if(++nb == 5){ - mouseshifted = 0; /* XXX should be from keyboard shift key */ - newbuttons = b[((msg[0]&7)^7) | (mouseshifted ? 8 : 0)]; - dx = msg[1]+msg[3]; - dy = -(msg[2]+msg[4]); - track(newbuttons, dx, dy); - nb = 0; - } - return 0; -} - -/* - * microsoft 3 button, 7 bit bytes - * - * byte 0 - 1 L R Y7 Y6 X7 X6 - * byte 1 - 0 X5 X4 X3 X2 X1 X0 - * byte 2 - 0 Y5 Y4 Y3 Y2 Y1 Y0 - * byte 3 - 0 M x x x x x (optional) - * - * shift & right button is the same as middle button (for 2 button mice) - */ -static int -m3mouseputc(Queue*, int c) -{ - static uchar msg[3]; - static int nb; - static int middle; - static uchar b[] = { 0, 4, 1, 5, 0, 2, 1, 5 }; - short x; - int dx, dy, buttons; - - /* - * check bit 6 for consistency - */ - if(nb==0){ - if((c&0x40) == 0){ - /* an extra byte gets sent for the middle button */ - if(c & 0x1c) - return 0; - middle = (c&0x20) ? 2 : 0; - buttons = (mouse.b & ~2) | middle; - track(buttons, 0, 0); - return 0; - } - } - msg[nb] = c&0x3f; - if(++nb == 3){ - nb = 0; - buttons = middle | b[(msg[0]>>4)&3]; - x = (msg[0]&0x3)<<14; - dx = (x>>8) | msg[1]; - x = (msg[0]&0xc)<<12; - dy = (x>>8) | msg[2]; - track(buttons, dx, dy); - } - return 0; -} - -static void -serialmouse(int port, char *type, int setspeed) -{ - int (*putc)(Queue *, int) = 0; - char pn[KNAMELEN]; - - if(mousetype) - error(Emouseset); - - if(port >= 2 || port < 0) - error(Ebadarg); - - if (type == 0) - putc = logitechmouseputc; - else if (*type == 'M') - putc = m3mouseputc; - else - error(Ebadarg); - snprint(pn, sizeof(pn), "%d", port); - i8250mouse(pn, putc, setspeed); - mousetype = Mouseserial; - mouseport = port; - mousesubtype = (type && *type == 'M') ? 'M' : 0; -} - -/* - * ps/2 mouse message is three bytes - * - * byte 0 - 0 0 SDY SDX 1 M R L - * byte 1 - DX - * byte 2 - DY - * - * shift & left button is the same as middle button - */ -static void -ps2mouseputc(int c, int shift) -{ - static short msg[3]; - static int nb; - static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 5, 2, 3, 6, 7 }; - int buttons, dx, dy; - - /* - * check byte 0 for consistency - */ - if(nb==0 && (c&0xc8)!=0x08) - return; - - msg[nb] = c; - if(++nb == 3){ - nb = 0; - if(msg[0] & 0x10) - msg[1] |= 0xFF00; - if(msg[0] & 0x20) - msg[2] |= 0xFF00; - - buttons = b[(msg[0]&7) | (shift ? 8 : 0)]; - dx = msg[1]; - dy = -msg[2]; - track(buttons, dx, dy); - } - return; -} - -/* - * set up a ps2 mouse - */ -static void -ps2mouse(void) -{ - if(mousetype) - error(Emouseset); - - i8042auxenable(ps2mouseputc); - /* make mouse streaming, enabled */ - i8042auxcmd(0xEA); - i8042auxcmd(0xF4); - - mousetype = MousePS2; -} - -/* logitech bus mouse ports and commands */ -enum { - /* ports */ - BMdatap = 0x23c, - BMsigp = 0x23d, - BMctlp = 0x23e, - BMintrp = 0x23e, - BMconfigp = 0x23f, - - /* commands */ - BMintron = 0x0, - BMintroff = 0x10, - BMrxlo = 0x80, - BMrxhi = 0xa0, - BMrylo = 0xc0, - BMryhi = 0xe0, - - BMconfig = 0x91, - BMdefault = 0x90, - - BMsigval = 0xa5 -}; - -static void -busmouseintr(Ureg *, void *) -{ - char dx, dy; - uchar b; - static uchar oldb; - static Lock intrlock; - ilock(&intrlock); - outb(BMintrp, BMintroff); - outb(BMctlp, BMrxlo); - dx = inb(BMdatap) & 0xf; - outb(BMctlp, BMrxhi); - dx |= (inb(BMdatap) & 0xf) << 4; - outb(BMctlp, BMrylo); - dy = inb(BMdatap) & 0xf; - outb(BMctlp, BMryhi); - b = inb(BMdatap); - dy |= (b & 0xf) << 4; - b = ~(b >> 5) & 7; - if (dx || dy || b != oldb) { - oldb = b; - track((b>>2)|(b&0x02)|((b&0x01)<<2), dx, dy); - } - iunlock(&intrlock); - outb(BMintrp, BMintron); -} - -static int -busmousedetect(void) -{ - outb(BMconfigp, BMconfig); - outb(BMsigp, BMsigval); - delay(2); - if (inb(BMsigp) != BMsigval) - return 0; - outb(BMconfigp, BMdefault); - return 1; -} - -/* - * set up a logitech bus mouse - */ -static void -busmouse(int irq) -{ - if (mousetype) - error(Emouseset); - if (!busmousedetect()) - error(Enodev); - - intrenable(irq >= 0 ? irq+VectorPIC : VectorBUSMOUSE, busmouseintr, 0, BUSUNKNOWN); - outb(BMintrp, BMintron); - mousetype = Mousebus; - mouseport = irq >= 0 ? irq : VectorBUSMOUSE-VectorPIC; -} - -/* microsoft bus mouse ports and commands */ -enum { - MBMdatap= 0x23d, - MBMsigp= 0x23e, - MBMctlp= 0x23c, - MBMconfigp= 0x23f, - - MBMintron= 0x11, - MBMintroff= 0x10, - MBMrbuttons= 0x00, - MBMrx= 0x01, - MBMry= 0x02, - MBMstart= 0x80, - MBMcmd= 0x07, -}; - -static void -msbusmouseintr(Ureg *, void *) -{ - char dx, dy; - uchar b; - static uchar oldb; - static Lock intrlock; - ilock(&intrlock); - outb(MBMctlp, MBMcmd); - outb(MBMdatap, inb(MBMdatap)|0x20); - - outb(MBMctlp, MBMrx); - dx = inb(MBMdatap); - - outb(MBMctlp, MBMry); - dy = inb(MBMdatap); - - outb(MBMctlp, MBMrbuttons); - b = inb(MBMdatap) & 0x7; - - outb(MBMctlp, MBMcmd); - outb(MBMdatap, inb(MBMdatap)&0xdf); - - if (dx != 0 || dy != 0 || b != oldb) { - oldb = b; - /* XXX this is almost certainly wrong */ - track((b>>2)|(b&0x02)|((b&0x01)<<2), dx, dy); - } - iunlock(&intrlock); -} - -static int -msbusmousedetect(void) -{ - if (inb(MBMsigp) == 0xde) { - int v, i; - delay(1); - v = inb(MBMsigp); - delay(1); - for (i = 0; i < 4; i++) { - if (inb(MBMsigp) != 0xde) - break; - delay(1); - if (inb(MBMsigp) != v) - break; - delay(1); - } - if (i == 4) { - outb(MBMctlp, MBMcmd); - return 1; - } - } - return 0; -} - -static void -msbusmouse(int irq) -{ - if (mousetype) - error(Emouseset); - if (!msbusmousedetect()) - error(Enodev); - mousetype = Mousemsbus; - mouseport = irq >= 0 ? irq : VectorBUSMOUSE-VectorPIC; - intrenable(irq >= 0 ? irq+VectorPIC : VectorBUSMOUSE, msbusmouseintr, 0, BUSUNKNOWN); - outb(MBMdatap, MBMintron); -} - -static void -mousectl(char *buf) -{ - int nf, x; - char *field[10]; - nf = getfields(buf, field, 10, 1, " \t\n"); - if (nf < 1) - return; - if(strncmp(field[0], "serial", 6) == 0){ - switch(nf){ - /* the difference between these two cases is intriguing - wrtp */ - case 1: - serialmouse(atoi(field[0]+6), 0, 1); - break; - case 2: - serialmouse(atoi(field[1]), 0, 0); - break; - case 3: - default: - serialmouse(atoi(field[1]), field[2], 0); - break; - } - } else if(strcmp(field[0], "ps2") == 0){ - ps2mouse(); - } else if (strcmp(field[0], "ps2intellimouse") == 0) { - ps2mouse(); - setintellimouse(); - } else if (strncmp(field[0], "bus", 3) == 0 || strncmp(field[0], "msbus", 5) == 0) { - int irq, isms; - - isms = (field[0][0] == 'm'); - if (nf == 1) - irq = atoi(field[0] + (isms ? 5 : 3)); - else - irq = atoi(field[1]); - if (irq < 1) - irq = -1; - if (isms) - msbusmouse(irq); - else - busmouse(irq); - } else if(strcmp(field[0], "accelerated") == 0){ - switch(mousetype){ - case MousePS2: - x = splhi(); - i8042auxcmd(0xE7); - splx(x); - accelerated = 1; - break; - } - } else if(strcmp(field[0], "linear") == 0){ - switch(mousetype){ - case MousePS2: - x = splhi(); - i8042auxcmd(0xE6); - splx(x); - accelerated = 0; - break; - } - } else if(strcmp(field[0], "res") == 0){ - int n,m; - switch(nf){ - default: - n = 0x02; - m = 0x23; - break; - case 2: - n = atoi(field[1])&0x3; - m = 0x7; - break; - case 3: - n = atoi(field[1])&0x3; - m = atoi(field[2])&0x7; - break; - } - - switch(mousetype){ - case MousePS2: - x = splhi(); - i8042auxcmd(0xE8); - i8042auxcmd(n); - i8042auxcmd(0x5A); - i8042auxcmd(0x30|m); - i8042auxcmd(0x5A); - i8042auxcmd(0x20|(m>>1)); - splx(x); - break; - } - } else if(strcmp(field[0], "swap") == 0) - mouseswap ^= 1; -} - -Dev mousedevtab = { /* defaults in dev.c */ - 'm', - "mouse", - - devreset, /* devreset */ - devinit, /* devinit */ - mouseattach, - devdetach, - devclone, /* devclone */ - mousewalk, - mousestat, - mouseopen, - devcreate, /* devcreate */ - mouseclose, - mouseread, - devbread, /* devbread */ - mousewrite, - devbwrite, /* devbwrite */ - devremove, /* devremove */ - devwstat, /* devwstat */ -}; - diff --git a/os/pc/devmpeg.c b/os/pc/devmpeg.c deleted file mode 100644 index 038cfa6c..00000000 --- a/os/pc/devmpeg.c +++ /dev/null @@ -1,1063 +0,0 @@ -/* - * Boffin MPEG decoder - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "zoran.h" -#include "crystal.h" -#include "io.h" - -enum -{ - - CPUACCCTRL = 0x20, /* Trident Window Chip control registers */ - CPUACCMD = 0x21, - BNKADR = 0x22, - SYSCONFIG = 0x23, - VGACOMP = 0x24, - VGAMASK = 0x25, - VIDCOMPL = 0x26, - VIDCOMPH = 0x27, - MOS = 0x28, - DISPCTRL = 0x29, - CAPCTRL = 0x2a, - OVLKT = 0x2b, - OVLWINHSTRT = 0x2c, - OVLWINVSTRT = 0x2d, - OVLWINHEND = 0x2e, - OVLWINVEND = 0x2f, - RESERVED1 = 0x30, - RESERVED2 = 0x31, - DISPWINVSTRT1 = 0x32, - DISPWINVSTRT2 = 0x33, - DISPWINVEND = 0x34, - DISPWINHSTRT1 = 0x35, - DISPWINHSTRT2 = 0x36, - DISPWINHEND = 0x37, - CAPWINVSTRT = 0x38, - CAPWINHSTRT = 0x39, - CAPWINVMF = 0x3a, - CAPWINHMF = 0x3b, - RESERVED3 = 0x3c, - CAPMASK = 0x3d, - BNKPOLATION = 0x3e, - SYNCPOL = 0x3f, - DISPVTOTAL = 0x40, - DISPHTOTAL = 0x41, - DISPVSTRT = 0x42, - DISPVEND = 0x43, - DISPHSTRT = 0x44, - DISPHEND = 0x45, - DISPSYNCW = 0x46, - DISPCRTCCTRL = 0x47, - CAPVTOTAL = 0x48, - CAPHTOTAL = 0x49, - CAPVSTRT = 0x4a, - CAPVEND = 0x4b, - CAPHSTRT = 0x4c, - CAPHEND = 0x4d, - CAPSYNCW = 0x4e, - CAPCRTCCTRL = 0x4f, - VIDLUTDACRW = 0x50, - VIDLUTDACRW0 = (VIDLUTDACRW), - VIDLUTDACRW1 = (VIDLUTDACRW+1), - VIDLUTDACRW2 = (VIDLUTDACRW+2), - VIDLUTDACRW3 = (VIDLUTDACRW+3), - VIDLUTDACRW4 = (VIDLUTDACRW+4), - VIDLUTDACRW5 = (VIDLUTDACRW+5), - VIDLUTDACRW6 = (VIDLUTDACRW+6), - VIDLUTDACRW7 = (VIDLUTDACRW+7), - VGALUTDACRW = 0x58, - VGALUTDACRW0 = (VGALUTDACRW), - VGALUTDACRW1 = (VGALUTDACRW+1), - VGALUTDACRW2 = (VGALUTDACRW+2), - VGALUTDACRW3 = (VGALUTDACRW+3), - VGALUTDACRW4 = (VGALUTDACRW+4), - VGALUTDACRW5 = (VGALUTDACRW+5), - VGALUTDACRW6 = (VGALUTDACRW+6), - VGALUTDACRW7 = (VGALUTDACRW+7), - HZOOMF = 0x60, - VZOOMF = 0x61, - DELAY1 = 0x62, - DELAY2 = 0x63, - - TRILO = 0, - TRIHI = 1, - TRIINDEX = 2, - - SCL = 0x02, - SDA = 0x01, - I2CR = 0x2B, - SAA7110 = 0x9c, - WRITE_C = 0x00, - I2DLY = 5, -}; - -enum -{ - ZR36100 = 0x1e0, - ZRIRQ = 15, - ZRDMA = 6, - - ZRIDREG = 4, /* offset */ - ZRMACH210 = 6, /* offset */ - ZRREG0 = 8, /* offset */ - ZRREG1 = 10, /* offset */ - ZRSR = ZRREG1, /* offset */ - ZRRDY = (1<<3), - ZRIDLE = (1<<2), - ZRREG2 = 12, /* offset */ - ZRREG3 = 14, /* offset */ - - SIFwidth = 320, - SIFheight = 240, - - IDPCOUNT = 3064, - PMDPCOUNT = 2048, - SVMDPCOUNT = 2048, - - HIWAT = 2*128*1024, - DMABLK = 16384, -}; - -static struct { - int zrport; - int irq; - int dma; - int trport; -} mpegconf; - -static char Evmode[] = "video format not supported"; -static char Eaudio[] = "invalid audio layer"; -static char Earate[] = "bad audio sample rate"; - -/* Status bits depend on board revision */ -static short STDBY; -static short VIDSEL; -static short VSNIRQn; -static short INTENAn; -static short DSPBOOT; -static short DSPRST; -static short MPGRST; -static int machsr; -static int dopen; -static int started; -static int stop; -static int pause; -static int sp2br; -static int sp2cd; -static char properties[] = "video mpeg1,sif\naudio musicam,I musicam,II\n"; -static void inittrident(void); -static int initzoran(void); -static void initcrystal(void); -static void mpegintr(Ureg*, void*); -static void setwindow(int, char**); -static void freebufs(void); -static int mkbuf(char*, int); - -typedef struct Buf Buf; -struct Buf -{ - int nchar; - uchar* ptr; - Buf* link; - uchar data[1]; -}; - -static struct -{ - Lock; - int qlen; - Buf* head; - Buf* tail; - Rendez flow; -} bqueue; - -static int -zrstatus(void) -{ - return ins(mpegconf.zrport+ZRSR) & 0xf; -} - -static int -zrwaitrdy(int timo, char *msg) -{ - int i; - - for(i = 0; i < timo; i++) - if(ins(mpegconf.zrport+ZRSR) & ZRRDY) - return 0; - - print("devmpeg: device not ready %s\n", msg); - return 1; -} - -static void -zrdma(Buf *b) -{ - int n; - - n = dmasetup(mpegconf.dma, b->ptr, b->nchar, 0); - b->ptr += n; - b->nchar -= n; - bqueue.qlen -= n; -} - -static void -triwr(int reg, int val) -{ - outb(mpegconf.trport+TRIINDEX, reg); - outb(mpegconf.trport+TRILO, val); - outb(mpegconf.trport+TRIHI, val>>8); -} - -static int -trird(int reg) -{ - int v; - - outb(mpegconf.trport+TRIINDEX, reg); - v = inb(mpegconf.trport+TRILO); - v |= inb(mpegconf.trport+TRIHI)<<8; - - return v; -} - -enum -{ - Qdir, - Qdata, - Qctl, -}; -static Dirtab mpegtab[]= -{ - "mpeg", {Qdata, 0}, 0, 0666, - "mpegctl", {Qctl, 0}, 0, 0666, -}; - -static void -mpegreset(void) -{ - ISAConf isa; - - mpegconf.zrport = ZR36100; - mpegconf.irq = ZRIRQ; - mpegconf.dma = ZRDMA; - - memset(&isa, 0, sizeof(isa)); - if(isaconfig("mpeg", 0, &isa) == 0) - return; - if(isa.port) - mpegconf.zrport = isa.port; - if(isa.irq) - mpegconf.irq = isa.irq; - if(isa.dma) - mpegconf.dma = isa.dma; - dmainit(mpegconf.dma, 64*1024); - print("mpeg0: port 0x%uX, irq %d, dma %d\n", - mpegconf.zrport, mpegconf.irq, mpegconf.dma); - mpegconf.trport = mpegconf.zrport+0x100; - intrenable(VectorPIC+mpegconf.irq, mpegintr, 0, BUSUNKNOWN); -} - -static void -mpeginit(void) -{ - if(mpegconf.trport == 0) - return; - - inittrident(); - setwindow(0, 0); -} - -static Chan* -mpegattach(char *spec) -{ - if(mpegconf.trport == 0) - error(Enodev); - - return devattach('E', spec); -} - -static int -mpegwalk(Chan *c, char *name) -{ - return devwalk(c, name, mpegtab, nelem(mpegtab), devgen); -} - -static void -mpegstat(Chan *c, char *db) -{ - devstat(c, db, mpegtab, nelem(mpegtab), devgen); -} - -static Chan* -mpegopen(Chan *c, int omode) -{ - switch(c->qid.path) { - default: - break; - case Qdata: - if(dopen) - error(Einuse); - dopen = 1; - break; - } - return devopen(c, omode, mpegtab, nelem(mpegtab), devgen); -} - -static void -mpegclose(Chan *c) -{ - int i; - - switch(c->qid.path) { - default: - break; - case Qdata: - if((c->flag & COPEN) == 0) - break; - if(started) { - for(i = 0; i < 50; i++) { - if(ins(mpegconf.zrport+ZRSR) & ZRIDLE) - break; - tsleep(&up->sleep, return0, 0, 100); - } - } - if(stop != 0) - outs(mpegconf.zrport+ZRREG1, 0x1000); - microdelay(15); - outs(mpegconf.zrport+ZRREG1, 0x8000); - freebufs(); - dopen = 0; - } -} - -static long -mpegread(Chan *c, void *a, long n, ulong off) -{ - switch(c->qid.path & ~CHDIR){ - default: - error(Eperm); - case Qdir: - return devdirread(c, a, n, mpegtab, nelem(mpegtab), devgen); - case Qctl: - return readstr(off, a, n, properties); - } - return 0; -} - -#define SCALE(a, b) ((((a)<<10)/(b))-1024) -enum -{ - CWINVF = 0x3ff, - CWINHF = 0x1da, -}; - -static void -setwindow(int nf, char **field) -{ - int minx, miny, maxx, maxy, width, height; - - if(field == 0) { - minx = 0; - miny = 0; - maxx = 0; - maxy = 0; - } - else { - if(nf != 5) - error(Ebadarg); - - minx = strtoul(field[1], 0, 0); - miny = strtoul(field[2], 0, 0); - maxx = strtoul(field[3], 0, 0) + 8; - maxy = strtoul(field[4], 0, 0); - } - - triwr(OVLWINHSTRT, minx); - triwr(OVLWINVSTRT, miny); - triwr(OVLWINHEND, maxx+12); - triwr(OVLWINVEND, maxy); - - width = maxx - minx; - height = maxy - miny; - if(width >= SIFwidth) { - triwr(HZOOMF, SCALE(width, SIFwidth)); - triwr(CAPWINHMF, CWINHF); - } - else { - triwr(HZOOMF, SCALE(SIFwidth, SIFwidth)); - triwr(CAPWINHMF, width*CWINHF/SIFwidth); - } - if(height >= SIFheight) { - triwr(VZOOMF, SCALE(height, SIFheight)); - triwr(CAPWINVMF, CWINVF); - } - else { - triwr(VZOOMF, SCALE(SIFheight, SIFheight)); - triwr(CAPWINVMF, height*CWINVF/SIFheight); - } -} - -static int -mpegflow(void*) -{ - return bqueue.qlen < HIWAT || stop; -} - -static int -mkbuf(char *d, int n) -{ - Buf *b; - - b = malloc(sizeof(Buf)+n); - if(b == 0) - return 0; - - memmove(b->data, d, n); - b->ptr = b->data; - b->nchar = n; - b->link = 0; - - ilock(&bqueue); - bqueue.qlen += n; - if(bqueue.head) - bqueue.tail->link = b; - else - bqueue.head = b; - bqueue.tail = b; - iunlock(&bqueue); - - return 1; -} - -static void -freebufs(void) -{ - Buf *next; - - ilock(&bqueue); - bqueue.qlen = 0; - while(bqueue.head) { - next = bqueue.head->link; - free(bqueue.head); - bqueue.head = next; - } - iunlock(&bqueue); -} - -typedef struct Audio Audio; -struct Audio { - int rate; - int cd; - int br; -}; - -static Audio AudioclkI[] = -{ - 64000, 0x000000bb, 0x00071797, - 96000, 0x0000007d, 0x00071c71, - 128000, 0x0000005d, 0x00070de1, - 160000, 0x0000004b, 0x00071c71, - 192000, 0x0000003e, 0x00070de1, - 224000, 0x00000035, 0x00070906, - 256000, 0x0000002e, 0x0006fa76, - 288000, 0x00000029, 0x0006ff51, - 320000, 0x00000025, 0x0007042b, - 352000, 0x00000022, 0x00071797, - 384000, 0x0000001f, 0x00070de1, - 416000, 0x0000001c, 0x0006e70b, - 448000, 0x0000001a, 0x0006e70b, -}; - -static Audio AudioclkII[] = -{ - 48000, 0x000000fa, 0x00071c71, - 56000, 0x000000d6, 0x00071a04, - 64000, 0x000000bb, 0x00071797, - 80000, 0x00000096, 0x00071c71, - 96000, 0x0000007d, 0x00071c71, - 112000, 0x0000006b, 0x00071a04, - 128000, 0x0000005d, 0x00070de1, - 160000, 0x0000004b, 0x00071c71, - 192000, 0x0000003e, 0x00070de1, - 224000, 0x00000035, 0x00070906, - 256000, 0x0000002e, 0x0006fa76, - 320000, 0x00000025, 0x0007042b, - 384000, 0x0000001f, 0x00070de1, -}; - -static long -mpegwrite(Chan *c, char *a, long n, vlong) -{ - Audio *t; - int i, nf, l, x; - char buf[128], *field[10]; - - switch(c->qid.path & ~CHDIR) { - case Qctl: - if(n > sizeof(buf)-1) - n = sizeof(buf)-1; - memmove(buf, a, n); - buf[n] = '\0'; - - nf = getfields(buf, field, nelem(field), 1, " \t\n"); - if(nf < 1) - error(Ebadarg); - - if(strcmp(field[0], "stop") == 0) { - if(started == 0) - error("not started"); - if(pause) { - pause = 0; - outs(mpegconf.zrport+ZRREG1, 0x9000); - } - stop = 1; - outs(mpegconf.zrport+ZRREG1, 0x1000); - microdelay(15); - outs(mpegconf.zrport+ZRREG1, 0x8000); - wakeup(&bqueue.flow); - return n; - } - if(strcmp(field[0], "pause") == 0) { - if(started == 0) - error("not started"); - if(pause == 0) { - pause = 1; - outs(mpegconf.zrport+ZRREG1, 0x1000); - } - else { - pause = 0; - outs(mpegconf.zrport+ZRREG1, 0x9000); - } - return n; - } - if(strcmp(field[0], "window") == 0) { - setwindow(nf, field); - return n; - } - if(strcmp(field[0], "audio") == 0) { - if(nf < 3) - error(Ebadarg); - t = 0; - if(strcmp(field[1], "musicam,I") == 0) - t = AudioclkI; - else - if(strcmp(field[1], "musicam,II") == 0) - t = AudioclkII; - else - error(Eaudio); - x = strtoul(field[2], 0, 0); - for(i = 0; t[i].rate != 0; i++) { - if(t[i].rate == x) { - sp2cd = t[i].cd; - sp2br = t[i].br; - return n; - } - } - error(Earate); - } - if(strcmp(field[0], "video") == 0) { - if(nf != 3) - error(Ebadarg); - if(strcmp(field[1], "iso11172") != 0) - error(Evmode); - if(strcmp(field[2], "mpeg1,sif") != 0) - error(Evmode); - return n; - } - if(strcmp(field[0], "init") == 0) { - inittrident(); - for(i = 0; i < 3; i++) - if(initzoran() != -1) - break; - initcrystal(); - started = 0; - stop = 0; - pause = 0; - return n; - } - error(Ebadarg); - case Qdata: - if(n & 1) - error("odd write"); - - while(!mpegflow(0)) - sleep(&bqueue.flow, mpegflow, 0); - - if(stop) - error("stopped"); - - x = n; - while(x) { - l = x; - if(l > DMABLK) - l = DMABLK; - if(mkbuf(a, l) == 0) - error(Enomem); - x -= l; - a += l; - } - if(started || bqueue.qlen < (HIWAT*3)/4) - break; - - zrdma(bqueue.head); - outs(mpegconf.zrport+ZRREG1, 0x0000); - outs(mpegconf.zrport+ZRREG1, 0x0000); - started = 1; - break; - default: - error(Ebadusefd); - } - return n; -} - -Dev mpegdevtab = { - 'E', - "mpeg", - - mpegreset, - mpeginit, - mpegattach, - devdetach, - devclone, - mpegwalk, - mpegstat, - mpegopen, - devcreate, - mpegclose, - mpegread, - devbread, - mpegwrite, - devbwrite, - devremove, - devwstat, -}; - -static void -initctl(void) -{ - int boardid; - static int done; - - if(done) - return; - - boardid = ins(mpegconf.zrport+ZRIDREG); - if(boardid == 0xE3E3) { /* REV c/d */ - STDBY = 0x0000; - VIDSEL = 0x2020; - VSNIRQn = 0x1010; - INTENAn = 0x0808; - DSPBOOT = 0x0404; - DSPRST = 0x0202; - MPGRST = 0x0101; - } - else { /* REV b */ - STDBY = 0x0404; - VIDSEL = 0x1010; - VSNIRQn = 0x8080; - INTENAn = 0x4040; - DSPBOOT = 0x0202; - DSPRST = 0x0101; - MPGRST = 0x2020; - } - done = 1; - -} - -/* - * nbl (reg 0x1[ab]) was 0x0022, nblf (reg 1[cd]) was 0x0006 - */ -static uchar -zrparam[] = -{ -/* 00 */ 0xEF, 0x01, 0x01, 0x01, 0x80, 0x0E, 0x31, 0x00, -/* 08 */ 0x01, 0x60, 0x00, 0x00, 0x03, 0x5A, 0x00, 0x7A, -/* 10 */ 0x00, 0x10, 0x00, 0x08, 0x00, 0xF0, 0x00, 0x00, -/* 18 */ 0x02, 0x0D, 0x00, 0x1e, 0x00, 0x0a, 0x00, 0x02, -/* 20 */ 0x40, 0x06, 0x80, 0x00, 0x80, 0x00, 0x05, 0x9B, -/* 28 */ 0x07, 0x16, 0xFD, 0x25, 0xFE, 0xA0, 0x00, 0x00, -/* 30 */ 0x00, 0x07, 0x0d, 0xe1, 0x00, 0x00, 0x00, 0x3E, -/* 38 */ 0x00, 0x00, 0x09, 0x51, 0x00, 0x00, 0xCD, 0xFE, -/* 40 */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 48 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 58 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 68 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 70 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 78 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static int -initzoran(void) -{ - int i, nbytes, zrs; - - initctl(); - freebufs(); - - machsr = DSPRST|VSNIRQn; - outs(mpegconf.zrport+ZRMACH210, machsr); - microdelay(4000); - - machsr |= STDBY; - outs(mpegconf.zrport+ZRMACH210, machsr); - microdelay(4000); - - machsr |= MPGRST; - outs(mpegconf.zrport+ZRMACH210, machsr); - microdelay(4000); - machsr &= ~MPGRST; - outs(mpegconf.zrport+ZRMACH210, machsr); - microdelay(4000); - machsr |= MPGRST; - outs(mpegconf.zrport+ZRMACH210, machsr); - microdelay(4000); - - if(zrwaitrdy(2000, "load IDP")) - return -1; - - for(i = 0; i < IDPCOUNT; i++) - outb(mpegconf.zrport+ZRREG2, zrmpeg1[i]); - - if(((zrs = zrstatus()) & 3) != 3) { -/* print("devmpeg: error loading IDP sr=%2.2ux\n", zrs); */ - USED(zrs); - return -1; - } - - if(zrwaitrdy(2000, "load PMDP")) - return -1; - - for(i = 0; i < PMDPCOUNT; i++) - outb(mpegconf.zrport+ZRREG3, zrmpeg2[i]); - - if(((zrs = zrstatus()) & 3) != 3) { -/* print("devmpeg: error loading PMDP sr=%2.2ux\n", zrs); */ - USED(zrs); - return -1; - } - - zrparam[0x36] = sp2cd>>8; - zrparam[0x37] = sp2cd>>0; - zrparam[0x31] = sp2br>>16; - zrparam[0x32] = sp2br>>8; - zrparam[0x33] = sp2br>>0; - - nbytes = 16; - for(i = 0; i < 128; i++) { - if(nbytes >= 16) { - if(zrwaitrdy(2000, "load parameters")) - return -1; - nbytes = 0; - } - outb(mpegconf.zrport+ZRREG0, zrparam[i]); - nbytes++; - } - - if(zrwaitrdy(2000, "load SVMDP")) - return -1; - - for(i = 0; i < SVMDPCOUNT; i++) - outb(mpegconf.zrport+ZRREG3, zrmpeg3s[i]); - - if(((zrs = zrstatus()) & 3) != 3) { -/* print("devmpeg: error loading SVMDP sr=%2.2ux\n", zrs); */ - USED(zrs); - return -1; - } - return 0; -} - -static struct -{ - short reg; - ushort val; -} trireg[] = -{ - 0x20, 0x0400, - 0x21, 0x00e9, - 0x22, 0x0000, - 0x23, 0x07ee, - 0x24, 0x0005, - 0x25, 0xff00, - 0x26, 0x0000, - 0x27, 0x7fff, - 0x28, 0x0004, - 0x29, 0x88a0, - 0x2a, 0x0011, - 0x2b, 0x8540, - 0x2c, 0x00c4, - 0x2d, 0x00ac, - 0x2e, 0x020f, - 0x2f, 0x019d, - 0x30, 0x00bd, - 0x31, 0x00ff, - 0x32, 0x0000, - 0x33, 0x0000, - 0x34, 0x03ff, - 0x35, 0x0000, - 0x36, 0x0000, - 0x37, 0x03ff, - 0x38, 0x0000, - 0x39, 0x0000, - 0x3a, 0x03ff, - 0x3b, 0x01da, - 0x3c, 0xe8ce, - 0x3d, 0x2ac0, - 0x3e, 0x891f, - 0x3f, 0x3e25, - 0x40, 0x03ff, - 0x41, 0x01ff, - 0x42, 0x001f, - 0x43, 0x01ff, - 0x44, 0x003b, - 0x45, 0x0186, - 0x46, 0x1d06, - 0x47, 0x1a4f, - 0x48, 0x020d, - 0x49, 0x01ad, - 0x4a, 0x001b, - 0x4b, 0x01fd, - 0x4c, 0x003a, - 0x4d, 0x034b, - 0x4e, 0x2006, - 0x4f, 0x0083, - 0x50, 0xef08, - 0x51, 0xef3a, - 0x52, 0xefff, - 0x53, 0xef08, - 0x54, 0xef08, - 0x55, 0xef15, - 0x56, 0xefc0, - 0x57, 0xef08, - 0x58, 0xefef, - 0x59, 0xefef, - 0x5a, 0xefef, - 0x5b, 0xefef, - 0x5c, 0xefef, - 0x5d, 0xefef, - 0x5e, 0xefef, - 0x5f, 0xefef, - 0x60, 0x0000, - 0x61, 0x0004, - 0x62, 0x0020, - 0x63, 0x8080, - 0x64, 0x0300, - -1 -}; - -static void -clrI2C(uchar b) -{ - uchar t; - - outb(mpegconf.trport+TRIINDEX, I2CR); - t = inb(mpegconf.trport+TRIHI); - t &= ~b; - outb(mpegconf.trport+TRIHI, t); -} - -static void -setI2C(uchar b) -{ - uchar t; - - outb(mpegconf.trport+TRIINDEX, I2CR); - t = inb(mpegconf.trport+TRIHI); - t |= b; - outb(mpegconf.trport+TRIHI, t); -} - -static void -startI2C(void) -{ - setI2C(SDA); - setI2C(SCL); - microdelay(I2DLY); - clrI2C(SDA); - microdelay(I2DLY); - clrI2C(SCL); - microdelay(I2DLY); -} - -static void -endI2C(void) -{ - clrI2C(SDA); - clrI2C(SCL); - microdelay(I2DLY); - setI2C(SCL); - microdelay(I2DLY); - setI2C(SDA); - microdelay(I2DLY); -} - -static void -wrI2Cbit(uchar b) -{ - clrI2C(SDA); - clrI2C(SCL); - microdelay(I2DLY); - if(b & 1) { - setI2C(SDA); - microdelay(I2DLY); - setI2C(SCL); - microdelay(I2DLY); - clrI2C(SCL); - microdelay(I2DLY); - clrI2C(SDA); - microdelay(I2DLY); - } - else { - setI2C(SCL); - microdelay(I2DLY); - clrI2C(SCL); - microdelay(I2DLY); - } -} - -static void -wrI2CB(unsigned char data) -{ - int i; - - for(i = 0; i < 8; i++) - wrI2Cbit(data >>(7-i)); -} - -static int -rdI2CBit(void) -{ - int bit = 1; - - setI2C(SDA); - clrI2C(SCL); - setI2C(SCL); - outb(mpegconf.trport+TRIINDEX, I2CR); - if(inb(mpegconf.trport+TRIHI) & SDA) - bit = 0; - clrI2C(SDA); - clrI2C(SCL); - - return bit; -} - -static int -wrI2CD(uchar data) -{ - int r; - ulong s; - - s = splhi(); - wrI2CB(data); - r = rdI2CBit(); - splx(s); - return r; -} - -static uchar -setupSAA7110[] = -{ - /* Digital */ - 0x4c, 0x3c, 0x0d, 0xef, 0xbd, 0xf0, 0x40, 0x03, - 0xf8, 0xf8, 0x90, 0x90, 0x00, 0x02, 0x10, 0x77, - 0x00, 0x2c, 0x40, 0x40, 0x3b, 0x10, 0xfc, 0xd2, - 0xf0, 0x80, - - /* Analog */ - 0xd9, 0x16, 0x40, 0x40, 0x80, 0x40, 0x80, 0x4f, - 0xfe, 0x01, 0xcf, 0x0f, 0x03, 0x01, 0x81, 0x0a, - 0x40, 0x35, 0x02, 0x8c, 0x03 -}; - -static void -addrI2CB(int addr, int val) -{ - ulong s; - - s = splhi(); - startI2C(); - wrI2CD(SAA7110|WRITE_C); - wrI2CD(addr); - wrI2CD(val); - endI2C(); - splx(s); -} - -static void -inittrident(void) -{ - int i; - - for(i = 0; trireg[i].reg != -1; i++) - triwr(trireg[i].reg, trireg[i].val); - - for(i = 0; i < 47; i++) - addrI2CB(i, setupSAA7110[i]); -} - -static void -initcrystal(void) -{ - int i; - static int done; - - if(done) - return; - - done = 1; - - initctl(); - - /* Reboot the Musicam decoder */ - clrI2C(SCL); - clrI2C(SDA); - machsr |= DSPRST; - outs(mpegconf.zrport+ZRMACH210, machsr); - machsr |= DSPBOOT; - outs(mpegconf.zrport+ZRMACH210, machsr); - machsr &= ~DSPRST; - outs(mpegconf.zrport+ZRMACH210, machsr); - machsr |= DSPRST; - outs(mpegconf.zrport+ZRMACH210, machsr); - machsr &= ~DSPBOOT; - outs(mpegconf.zrport+ZRMACH210, machsr); - - startI2C(); - wrI2CD(0); - for(i = 0; i < sizeof(crystal); i++ ) - wrI2CD(crystal[i]); - endI2C(); -} - -static void -mpegintr(Ureg*, void*) -{ - Buf *b; - - b = bqueue.head; - if(b == 0 || dmadone(mpegconf.dma) == 0) - return; - - dmaend(mpegconf.dma); - if(b->nchar == 0) { - bqueue.head = b->link; - free(b); - - b = bqueue.head; - if(b == 0) { - started = 0; - return; - } - } - zrdma(b); - wakeup(&bqueue.flow); -} diff --git a/os/pc/devpccard.c b/os/pc/devpccard.c deleted file mode 100644 index 3f6a09ca..00000000 --- a/os/pc/devpccard.c +++ /dev/null @@ -1,1949 +0,0 @@ -/* - cardbus and pcmcia (grmph) support. -*/ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "io.h" - -#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, - - 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", }, -}; - -/* 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, -}; - -static char *chipname[] = { -[Ti82365] "Intel 82365SL", -[Tpd6710] "Cirrus Logic PD6710", -[Tpd6720] "Cirrus Logic PD6720", -[Tvg46x] "Vadem VG-46x", -}; - -/* - * 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 */ -}; - -static int managerstarted; - -enum { - Mshift= 12, - Mgran= (1<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; - } -} - -static void -qengine(Cardbus *cb, int message) -{ - lock(cb); - engine(cb, message); - unlock(cb); -} - -typedef struct Events Events; -struct Events { - Cardbus *cb; - int message; -}; - -static Lock levents; -static Events events[NUMEVENTS]; -static Rendez revents; -static int nevents; - -static void -iengine(Cardbus *cb, int message) -{ - if (nevents >= NUMEVENTS) { - print("#Y: Too many events queued, discarding request\n"); - return; - } - ilock(&levents); - events[nevents].cb = cb; - events[nevents].message = message; - nevents++; - iunlock(&levents); - wakeup(&revents); -} - -static int -eventoccured(void) -{ - return nevents > 0; -} - -static void -processevents(void *) -{ - while (1) { - int message; - Cardbus *cb; - - sleep(&revents, (int (*)(void *))eventoccured, nil); - - cb = nil; - message = 0; - ilock(&levents); - if (nevents > 0) { - cb = events[0].cb; - message = events[0].message; - nevents--; - if (nevents > 0) - memmove(events, &events[1], nevents * sizeof(Events)); - } - iunlock(&levents); - - if (cb) - qengine(cb, message); - } -} - -static void -cbinterrupt(Ureg *, void *) -{ - int i; - - for (i = 0; i != nslots; i++) { - Cardbus *cb = &cbslots[i]; - ulong event, state; - - event= cb->regs[SocketEvent]; - state = cb->regs[SocketState]; - rdreg(cb, Rcsc); /* Ack the interrupt */ - - //print("interrupt: slot %d, event %.8lX, state %.8lX, (%s)\n", - // (int)(cb - cbslots), event, state, states[cb->state]); - - if (event & SE_CCD) { - cb->regs[SocketEvent] |= SE_CCD; /* Ack interrupt */ - if (state & SE_CCD) { - if (cb->state != SlotEmpty) { - print("#Y: take cardejected interrupt\n"); - iengine(cb, CardEjected); - } - } - else - iengine(cb, CardDetected); - } - - if (event & SE_POWER) { - cb->regs[SocketEvent] |= SE_POWER; /* Ack interrupt */ - iengine(cb, CardPowered); - } - } -} - -void -devpccardlink(void) -{ - static int initialized; - Pcidev *pci; - int i; - uchar intl; - 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; - intl = (uchar)-1; - while ((pci = pcimatch(pci, 0, 0)) != nil) { - ulong baddr; - Cardbus *cb; - int slot; - uchar pin; - - 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]; - - if (pci->vid != TI_vid) { - // Gross hack, needs a fix. Inherit the mappings from 9load - // for the TIs (pb) - pcicfgw32(pci, PciCBMBR0, 0xffffffff); - pcicfgw32(pci, PciCBMLR0, 0); - pcicfgw32(pci, PciCBMBR1, 0xffffffff); - pcicfgw32(pci, PciCBMLR1, 0); - pcicfgw32(pci, PciCBIBR0, 0xffffffff); - pcicfgw32(pci, PciCBILR0, 0); - pcicfgw32(pci, PciCBIBR1, 0xffffffff); - pcicfgw32(pci, PciCBILR1, 0); - } - - // 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 (intl != -1 && intl != pci->intl) - intrenable(pci->intl, cbinterrupt, cb, pci->tbdf, "cardbus"); - intl = pci->intl; - - if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) { - int align = (pci->did == Ricoh_478_did)? 0x10000: 0x1000; - - baddr = upamalloc(baddr, align, align); - 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){ - iofree(LegacyAddr); - 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: Not a card inserted\n", cb - cbslots); - 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 = (state & SS_PC16)? PC16: 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) -{ - int i; - Pcidev *pci; - - //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) { - ulong size, bar; - int memindex, ioindex; - - pcicfgw16(pci, PciPCR, - pcicfgr16(pci, PciPCR) & ~(PciPCR_IO|PciPCR_MEM)); - - /* 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 */ - pcicfgw16(cb->pci, PciBCR, - pcicfgr16(cb->pci, PciBCR) | - (1 << (8 + memindex))); - - //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) | 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; - - 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); - pcicfgw16(cb->pci, PciBCR, - pcicfgr16(cb->pci, PciBCR) & - ~(1 << (8 + memindex))); - 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<irqs) == 0){ - for(t = pi->ctab; t < et; t++) - if(t->nio - && t->io[0].start == isa->port - && ((1<irqs)){ - ct = t; - break; - } - } - if(ct->nio == 0 || ((1<irqs) == 0){ - for(t = pi->ctab; t < et; t++) - if(t->nio && ((1<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<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) - x |= Clevel; - *p = x; - delay(5); - - isaunmap(m); - } - - pi->port = isa->port; - pi->irq = isa->irq; - unlock(cb); - - print("#Y%d: %s irq %d, 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; lqid.path>>8)&0xff)) -#define TYPE(c) ((ulong)(c->qid.path&0xff)) -#define QID(s,t) (((s)<<8)|(t)) - -static int -pccardgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp) -{ - int slotno; - Qid qid; - long len; - int entry; - - if(i == DEVDOTDOT){ - mkqid(&qid, Qdir, 0, QTDIR); - devdir(c, qid, "#Y", 0, eve, 0555, dp); - return 1; - } - - len = 0; - if(i >= Nents * nslots) return -1; - slotno = i / Nents; - entry = i % Nents; - if (entry == 0) { - qid.path = QID(slotno, Qctl); - snprint(up->genbuf, sizeof up->genbuf, "cb%dctl", slotno); - } - else { - /* Entries for memory regions. I'll implement them when - needed. (pb) */ - } - qid.vers = 0; - qid.type = QTFILE; - devdir(c, qid, up->genbuf, len, eve, 0660, dp); - return 1; -} - -static Walkqid* -pccardwalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, 0, 0, pccardgen); -} - -static int -pccardstat(Chan *c, uchar *db, int n) -{ - return devstat(c, db, n, 0, 0, pccardgen); -} - -static void -increfp(Cardbus *cb) -{ - lock(&cb->refslock); - cb->refs++; - unlock(&cb->refslock); -} - -static void -decrefp(Cardbus *cb) -{ - lock(&cb->refslock); - cb->refs--; - unlock(&cb->refslock); -} - -static Chan* -pccardopen(Chan *c, int omode) -{ - if (c->qid.type & QTDIR){ - if(omode != OREAD) - error(Eperm); - } else - increfp(&cbslots[SLOTNO(c)]); - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - return c; -} - -static void -pccardclose(Chan *c) -{ - if(c->flag & COPEN) - if((c->qid.type & QTDIR) == 0) - decrefp(&cbslots[SLOTNO(c)]); -} - -static long -pccardread(Chan *c, void *a, long n, vlong offset) -{ - Cardbus *cb; - char *buf, *p, *e; - int i; - - switch(TYPE(c)){ - case Qdir: - return devdirread(c, a, n, 0, 0, pccardgen); - - case Qctl: - buf = p = malloc(READSTR); - buf[0] = 0; - e = p + READSTR; - - cb = &cbslots[SLOTNO(c)]; - lock(cb); - p = seprint(p, e, "slot %ld: %s; ", cb - cbslots, states[cb->state]); - - switch (cb->type) { - case -1: - seprint(p, e, "\n"); - break; - - case PC32: - if (cb->pci->bridge) { - Pcidev *pci = cb->pci->bridge; - int i; - - while (pci) { - p = seprint(p, e, "%.4uX %.4uX; irq %d\n", - pci->vid, pci->did, pci->intl); - for (i = 0; i != Nbars; i++) - if (pci->mem[i].size) - p = seprint(p, e, - "\tmem[%d] %.8ulX (%.8uX)\n", - i, pci->mem[i].bar, - pci->mem[i].size); - if (pci->rom.size) - p = seprint(p, e, "\tROM %.8ulX (%.8uX)\n", - pci->rom.bar, pci->rom.size); - pci = pci->list; - } - } - break; - - case PC16: - if (cb->state == SlotConfigured) { - Pcminfo *pi = &cb->linfo; - - p = seprint(p, e, "%s port %X; irq %d;\n", - pi->verstr, pi->port, - pi->irq); - for (i = 0; i != pi->nctab; i++) { - PCMconftab *ct; - int j; - - ct = &pi->ctab[i]; - p = seprint(p, e, - "\tconfiguration[%d] irqs %.4uX; vpp %d, %d; %s\n", - i, ct->irqs, ct->vpp1, ct->vpp2, - (ct == pi->defctab)? "(default);": ""); - for (j = 0; j != ct->nio; j++) - if (ct->io[j].len > 0) - p = seprint(p, e, "\t\tio[%d] %.8ulX %uld\n", - j, ct->io[j].start, ct->io[j].len); - } - } - break; - } - unlock(cb); - - n = readstr(offset, a, n, buf); - free(buf); - return n; - } - return 0; -} - -static long -pccardwrite(Chan *c, void *v, long n, vlong) -{ - Rune r; - ulong n0; - char *device; - Cmdbuf *cbf; - Cmdtab *ct; - Cardbus *cb; - - n0 = n; - switch(TYPE(c)){ - case Qctl: - cb = &cbslots[SLOTNO(c)]; - - cbf = parsecmd(v, n); - if(waserror()){ - free(cbf); - nexterror(); - } - ct = lookupcmd(cbf, pccardctlmsg, nelem(pccardctlmsg)); - switch(ct->index){ - case CMdown: - device = cbf->f[1]; - device += chartorune(&r, device); - if ((n = devno(r, 1)) >= 0 && devtab[n]->config) - devtab[n]->config(0, device, nil); - qengine(cb, CardEjected); - break; - case CMpower: - if ((cb->regs[SocketState] & SS_CCD) == 0) - qengine(cb, CardDetected); - break; - } - poperror(); - free(cbf); - break; - } - return n0 - n; -} - -Dev pccarddevtab = { - 'Y', - "cardbus", - - devreset, - devinit, - devshutdown, - pccardattach, - pccardwalk, - pccardstat, - pccardopen, - devcreate, - pccardclose, - pccardread, - devbread, - pccardwrite, - devbwrite, - devremove, - devwstat, -}; - -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<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/os/pc/devpnp.c b/os/pc/devpnp.c deleted file mode 100644 index fe4c05dd..00000000 --- a/os/pc/devpnp.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - * ISA PNP 1.0 support + access to PCI configuration space - * - * TODO - * - implement PNP card configuration (setting io bases etc) - * - write user program to drive PNP configuration... - * - extend PCI raw access to configuration space (writes, byte/short access?) - * - implement PCI access to memory/io space/BIOS ROM - * - use c->aux instead of performing lookup on each read/write? - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -typedef struct Pnp Pnp; -typedef struct Card Card; - -struct Pnp -{ - QLock; - int rddata; - int debug; - Card *cards; -}; - -struct Card -{ - int csn; - ulong id1; - ulong id2; - char *cfgstr; - int ncfg; - Card* next; -}; - -static Pnp pnp; - -#define DPRINT if(pnp.debug) print -#define XPRINT if(1) print - -enum { - Address = 0x279, - WriteData = 0xa79, - - Qtopdir = 0, - - Qpnpdir, - Qpnpctl, - Qcsnctl, - Qcsnraw, - - Qpcidir, - Qpcictl, - Qpciraw, -}; - -#define TYPE(q) ((ulong)(q).path & 0x0F) -#define CSN(q) (((ulong)(q).path>>4) & 0xFF) -#define QID(c, t) (((c)<<4)|(t)) - -static Dirtab topdir[] = { - ".", { Qtopdir, 0, QTDIR }, 0, 0555, - "pnp", { Qpnpdir, 0, QTDIR }, 0, 0555, - "pci", { Qpcidir, 0, QTDIR }, 0, 0555, -}; - -static Dirtab pnpdir[] = { - ".", { Qpnpdir, 0, QTDIR }, 0, 0555, - "ctl", { Qpnpctl, 0, 0 }, 0, 0666, -}; - -extern Dev pnpdevtab; -static int wrconfig(Card*, char*); - -static char key[32] = -{ - 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE, - 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61, - 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1, - 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39, -}; - -static void -cmd(int reg, int val) -{ - outb(Address, reg); - outb(WriteData, val); -} - -/* Send initiation key, putting each card in Sleep state */ -static void -initiation(void) -{ - int i; - - /* ensure each card's LFSR is reset */ - outb(Address, 0x00); - outb(Address, 0x00); - - /* send initiation key */ - for (i = 0; i < 32; i++) - outb(Address, key[i]); -} - -/* isolation protocol... */ -static int -readbit(int rddata) -{ - int r1, r2; - - r1 = inb(rddata); - r2 = inb(rddata); - microdelay(250); - return (r1 == 0x55) && (r2 == 0xaa); -} - -static int -isolate(int rddata, ulong *id1, ulong *id2) -{ - int i, csum, bit; - uchar *p, id[9]; - - outb(Address, 0x01); /* point to serial isolation register */ - delay(1); - csum = 0x6a; - for(i = 0; i < 64; i++){ - bit = readbit(rddata); - csum = (csum>>1) | (((csum&1) ^ ((csum>>1)&1) ^ bit)<<7); - p = &id[i>>3]; - *p = (*p>>1) | (bit<<7); - } - for(; i < 72; i++){ - p = &id[i>>3]; - *p = (*p>>1) | (readbit(rddata)<<7); - } - *id1 = (id[3]<<24)|(id[2]<<16)|(id[1]<<8)|id[0]; - *id2 = (id[7]<<24)|(id[6]<<16)|(id[5]<<8)|id[4]; - if(*id1 == 0) - return 0; - if(id[8] != csum) - DPRINT("pnp: bad checksum id1 %lux id2 %lux csum %x != %x\n", *id1, *id2, csum, id[8]); /**/ - return id[8] == csum; -} - -static int -getresbyte(int rddata) -{ - int tries = 0; - - outb(Address, 0x05); - while ((inb(rddata) & 1) == 0) - if (tries++ > 1000000) - error("pnp: timeout waiting for resource data\n"); - outb(Address, 0x04); - return inb(rddata); -} - -static char * -serial(ulong id1, ulong id2) -{ - int i1, i2, i3; - ulong x; - static char buf[20]; - - i1 = (id1>>2)&31; - i2 = ((id1<<3)&24)+((id1>>13)&7); - i3 = (id1>>8)&31; - x = (id1>>8)&0xff00|(id1>>24)&0x00ff; - if (i1 > 0 && i1 < 27 && i2 > 0 && i2 < 27 && i3 > 0 && i3 < 27 && (id1 & (1<<7)) == 0) - snprint(buf, sizeof(buf), "%c%c%c%.4lux.%lux", 'A'+i1-1, 'A'+i2-1, 'A'+i3-1, x, id2); - else - snprint(buf, sizeof(buf), "%.4lux%.4lux.%lux", (id1<<8)&0xff00|(id1>>8)&0x00ff, x, id2); - return buf; -} - -static Card * -findcsn(int csn, int create, int dolock) -{ - Card *c, *nc, **l; - - if(dolock) - qlock(&pnp); - l = &pnp.cards; - for(c = *l; c != nil; c = *l) { - if(c->csn == csn) - goto done; - if(c->csn > csn) - break; - l = &c->next; - } - if(create) { - *l = nc = malloc(sizeof(Card)); - nc->next = c; - nc->csn = csn; - c = nc; - } -done: - if(dolock) - qunlock(&pnp); - return c; -} - -static int -newcsn(void) -{ - int csn; - Card *c; - - csn = 1; - for(c = pnp.cards; c != nil; c = c->next) { - if(c->csn > csn) - break; - csn = c->csn+1; - } - return csn; -} - -static int -pnpncfg(int rddata) -{ - int i, n, x, ncfg, n1, n2; - - ncfg = 0; - for (;;) { - x = getresbyte(rddata); - if((x & 0x80) == 0) { - n = (x&7)+1; - for(i = 1; i < n; i++) - getresbyte(rddata); - } - else { - n1 = getresbyte(rddata); - n2 = getresbyte(rddata); - n = (n2<<8)|n1 + 3; - for (i = 3; i < n; i++) - getresbyte(rddata); - } - ncfg += n; - if((x>>3) == 0x0f) - break; - } - return ncfg; -} - -/* look for cards, and assign them CSNs */ -static int -pnpscan(int rddata, int dawn) -{ - Card *c; - int csn; - ulong id1, id2; - - initiation(); /* upsilon sigma */ - cmd(0x02, 0x04+0x01); /* reset CSN on all cards and reset logical devices */ - delay(1); /* delay after resetting cards */ - - cmd(0x03, 0); /* Wake all cards with a CSN of 0 */ - cmd(0x00, rddata>>2); /* Set the READ_DATA port on all cards */ - while(isolate(rddata, &id1, &id2)) { - for(c = pnp.cards; c != nil; c = c->next) - if(c->id1 == id1 && c->id2 == id2) - break; - if(c == nil) { - csn = newcsn(); - c = findcsn(csn, 1, 0); - c->id1 = id1; - c->id2 = id2; - } - else if(c->cfgstr != nil) { - if(!wrconfig(c, c->cfgstr)) - print("pnp%d: bad cfg: %s\n", c->csn, c->cfgstr); - c->cfgstr = nil; - } - cmd(0x06, c->csn); /* set the card's csn */ - if(dawn) - print("pnp%d: %s\n", c->csn, serial(id1, id2)); - c->ncfg = pnpncfg(rddata); - cmd(0x03, 0); /* Wake all cards with a CSN of 0, putting this card to sleep */ - } - cmd(0x02, 0x02); /* return cards to Wait for Key state */ - if(pnp.cards != 0) { - pnp.rddata = rddata; - return 1; - } - return 0; -} - -static void -pnpreset(void) -{ - Card *c; - ulong id1, id2; - int csn, i1, i2, i3, x; - char *s, *p, buf[20]; - ISAConf isa; - - memset(&isa, 0, sizeof(ISAConf)); - pnp.rddata = -1; - if (isaconfig("pnp", 0, &isa) == 0) - return; - if(isa.port < 0x203 || isa.port > 0x3ff) - return; - for(csn = 1; csn < 256; csn++) { - sprint(buf, "pnp%d", csn); - s = getconf(buf); - if(s == 0) - continue; - if(strlen(s) < 8 || s[7] != '.' || s[0] < 'A' || s[0] > 'Z' || s[1] < 'A' || s[1] > 'Z' || s[2] < 'A' || s[2] > 'Z') { -bad: - print("pnp%d: bad conf string %s\n", csn, s); - continue; - } - i1 = s[0]-'A'+1; - i2 = s[1]-'A'+1; - i3 = s[2]-'A'+1; - x = strtoul(&s[3], 0, 16); - id1 = (i1<<2)|((i2>>3)&3)|((i2&7)<<13)|(i3<<8)|((x&0xff)<<24)|((x&0xff00)<<8); - id2 = strtoul(&s[8], &p, 16); - if(*p == ' ') - p++; - else if(*p == '\0') - p = nil; - else - goto bad; - c = findcsn(csn, 1, 0); - c->id1 = id1; - c->id2 = id2; - c->cfgstr = p; - } - pnpscan(isa.port, 1); -} - -static int -csngen(Chan *c, int t, int csn, Card *cp, Dir *dp) -{ - Qid q; - - switch(t) { - case Qcsnctl: - q = (Qid){QID(csn, Qcsnctl), 0, 0}; - sprint(up->genbuf, "csn%dctl", csn); - devdir(c, q, up->genbuf, 0, eve, 0664, dp); - return 1; - case Qcsnraw: - q = (Qid){QID(csn, Qcsnraw), 0, 0}; - sprint(up->genbuf, "csn%draw", csn); - devdir(c, q, up->genbuf, cp->ncfg, eve, 0444, dp); - return 1; - } - return -1; -} - -static int -pcigen(Chan *c, int t, int tbdf, Dir *dp) -{ - Qid q; - - q = (Qid){BUSBDF(tbdf)|t, 0, 0}; - switch(t) { - case Qpcictl: - sprint(up->genbuf, "%d.%d.%dctl", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); - devdir(c, q, up->genbuf, 0, eve, 0444, dp); - return 1; - case Qpciraw: - sprint(up->genbuf, "%d.%d.%draw", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); - devdir(c, q, up->genbuf, 128, eve, 0444, dp); - return 1; - } - return -1; -} - -static int -pnpgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp) -{ - Qid q; - Card *cp; - Pcidev *p; - int csn, tbdf; - - switch(TYPE(c->qid)){ - case Qtopdir: - if(s == DEVDOTDOT){ - q = (Qid){QID(0, Qtopdir), 0, QTDIR}; - sprint(up->genbuf, "#%C", pnpdevtab.dc); - devdir(c, q, up->genbuf, 0, eve, 0555, dp); - return 1; - } - return devgen(c, nil, topdir, nelem(topdir), s, dp); - case Qpnpdir: - if(s == DEVDOTDOT){ - q = (Qid){QID(0, Qtopdir), 0, QTDIR}; - sprint(up->genbuf, "#%C", pnpdevtab.dc); - devdir(c, q, up->genbuf, 0, eve, 0555, dp); - return 1; - } - if(s < nelem(pnpdir)-1) - return devgen(c, nil, pnpdir, nelem(pnpdir), s, dp); - s -= nelem(pnpdir)-1; - qlock(&pnp); - cp = pnp.cards; - while(s >= 2 && cp != nil) { - s -= 2; - cp = cp->next; - } - qunlock(&pnp); - if(cp == nil) - return -1; - return csngen(c, s+Qcsnctl, cp->csn, cp, dp); - case Qpnpctl: - return devgen(c, nil, pnpdir, nelem(pnpdir), s, dp); - case Qcsnctl: - case Qcsnraw: - csn = CSN(c->qid); - cp = findcsn(csn, 0, 1); - if(cp == nil) - return -1; - return csngen(c, TYPE(c->qid), csn, cp, dp); - case Qpcidir: - if(s == DEVDOTDOT){ - q = (Qid){QID(0, Qtopdir), 0, QTDIR}; - sprint(up->genbuf, "#%C", pnpdevtab.dc); - devdir(c, q, up->genbuf, 0, eve, 0555, dp); - return 1; - } - p = pcimatch(nil, 0, 0); - while(s >= 2 && p != nil) { - p = pcimatch(p, 0, 0); - s -= 2; - } - if(p == nil) - return -1; - return pcigen(c, s+Qpcictl, p->tbdf, dp); - case Qpcictl: - case Qpciraw: - tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); - p = pcimatchtbdf(tbdf); - if(p == nil) - return -1; - return pcigen(c, TYPE(c->qid), tbdf, dp); - default: - break; - } - return -1; -} - -static Chan* -pnpattach(char *spec) -{ - return devattach(pnpdevtab.dc, spec); -} - -Walkqid* -pnpwalk(Chan* c, Chan *nc, char** name, int nname) -{ - return devwalk(c, nc, name, nname, (Dirtab *)0, 0, pnpgen); -} - -static int -pnpstat(Chan* c, uchar* dp, int n) -{ - return devstat(c, dp, n, (Dirtab *)0, 0L, pnpgen); -} - -static Chan* -pnpopen(Chan *c, int omode) -{ - c = devopen(c, omode, (Dirtab*)0, 0, pnpgen); - switch(TYPE(c->qid)){ - default: - break; - } - return c; -} - -static void -pnpclose(Chan*) -{ -} - -static long -pnpread(Chan *c, void *va, long n, vlong offset) -{ - ulong x; - Card *cp; - Pcidev *p; - char buf[256], *ebuf, *w; - char *a = va; - int csn, i, tbdf, r; - - switch(TYPE(c->qid)){ - case Qtopdir: - case Qpnpdir: - case Qpcidir: - return devdirread(c, a, n, (Dirtab *)0, 0L, pnpgen); - case Qpnpctl: - if(pnp.rddata > 0) - sprint(up->genbuf, "enabled 0x%x\n", pnp.rddata); - else - sprint(up->genbuf, "disabled\n"); - return readstr(offset, a, n, up->genbuf); - case Qcsnraw: - csn = CSN(c->qid); - cp = findcsn(csn, 0, 1); - if(cp == nil) - error(Egreg); - if(offset+n > cp->ncfg) - n = cp->ncfg - offset; - qlock(&pnp); - initiation(); - cmd(0x03, csn); /* Wake up the card */ - for(i = 0; i < offset+9; i++) /* 9 == skip serial + csum */ - getresbyte(pnp.rddata); - for(i = 0; i < n; i++) - a[i] = getresbyte(pnp.rddata); - cmd(0x03, 0); /* Wake all cards with a CSN of 0, putting this card to sleep */ - cmd(0x02, 0x02); /* return cards to Wait for Key state */ - qunlock(&pnp); - break; - case Qcsnctl: - csn = CSN(c->qid); - cp = findcsn(csn, 0, 1); - if(cp == nil) - error(Egreg); - sprint(up->genbuf, "%s\n", serial(cp->id1, cp->id2)); - return readstr(offset, a, n, up->genbuf); - case Qpcictl: - tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); - p = pcimatchtbdf(tbdf); - if(p == nil) - error(Egreg); - ebuf = buf+sizeof buf-1; /* -1 for newline */ - w = seprint(buf, ebuf, "%.2x.%.2x.%.2x %.4x/%.4x %3d", - p->ccrb, p->ccru, p->ccrp, p->vid, p->did, p->intl); - for(i=0; imem); i++){ - if(p->mem[i].size == 0) - continue; - w = seprint(w, ebuf, " %d:%.8lux %d", i, p->mem[i].bar, p->mem[i].size); - } - *w++ = '\n'; - *w = '\0'; - return readstr(offset, a, n, buf); - case Qpciraw: - tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); - p = pcimatchtbdf(tbdf); - if(p == nil) - error(Egreg); - if(offset > 256) - return 0; - if(n+offset > 256) - n = 256-offset; - if(offset%4) - error(Ebadarg); - r = offset; - for(i = 0; i+4 <= n; i+=4) { - x = pcicfgr32(p, r); - a[0] = x; - a[1] = (x>>8); - a[2] = (x>>16); - a[3] = (x>>24); - a += 4; - r += 4; - } - return i; - default: - error(Egreg); - } - return n; -} - -static long -pnpwrite(Chan *c, void *a, long n, vlong) -{ - int csn; - Card *cp; - ulong port; - char buf[256]; - - if(n >= sizeof(buf)) - n = sizeof(buf)-1; - strncpy(buf, a, n); - buf[n] = 0; - - switch(TYPE(c->qid)){ - case Qpnpctl: - if(strncmp(buf, "port ", 5) == 0) { - port = strtoul(buf+5, 0, 0); - if(port < 0x203 || port > 0x3ff) - error("bad value for rddata port"); - qlock(&pnp); - if(waserror()) { - qunlock(&pnp); - nexterror(); - } - if(pnp.rddata > 0) - error("pnp port already set"); - if(!pnpscan(port, 0)) - error("no cards found"); - qunlock(&pnp); - poperror(); - } - else if(strncmp(buf, "debug ", 6) == 0) - pnp.debug = strtoul(buf+6, 0, 0); - else - error(Ebadctl); - break; - case Qcsnctl: - csn = CSN(c->qid); - cp = findcsn(csn, 0, 1); - if(cp == nil) - error(Egreg); - if(!wrconfig(cp, buf)) - error(Ebadctl); - break; - default: - error(Egreg); - } - return n; -} - -static int -wrconfig(Card *c, char *cmd) -{ - /* This should implement setting of I/O bases, etc */ - USED(c, cmd); - return 1; -} - - -Dev pnpdevtab = { - '$', - "pnp", - - pnpreset, - devinit, - devshutdown, - pnpattach, - pnpwalk, - pnpstat, - pnpopen, - devcreate, - pnpclose, - pnpread, - devbread, - pnpwrite, - devbwrite, - devremove, - devwstat, -}; diff --git a/os/pc/devrtc.c b/os/pc/devrtc.c deleted file mode 100644 index f6e1d911..00000000 --- a/os/pc/devrtc.c +++ /dev/null @@ -1,461 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -/* - * real time clock and non-volatile ram - */ - -enum { - Paddr= 0x70, /* address port */ - Pdata= 0x71, /* data port */ - - Seconds= 0x00, - Minutes= 0x02, - Hours= 0x04, - Mday= 0x07, - Month= 0x08, - Year= 0x09, - Status= 0x0A, - - Nvoff= 128, /* where usable nvram lives */ - Nvsize= 256, - - Nbcd= 6, -}; - -typedef struct Rtc Rtc; -struct Rtc -{ - int sec; - int min; - int hour; - int mday; - int mon; - int year; -}; - - -enum{ - Qdir = 0, - Qrtc, - Qnvram, -}; - -Dirtab rtcdir[]={ - ".", {Qdir, 0, QTDIR}, 0, 0555, - "nvram", {Qnvram, 0}, Nvsize, 0664, - "rtc", {Qrtc, 0}, 0, 0664, -}; - -static ulong rtc2sec(Rtc*); -static void sec2rtc(ulong, Rtc*); - -void -rtcinit(void) -{ - if(ioalloc(Paddr, 2, 0, "rtc/nvr") < 0) - panic("rtcinit: ioalloc failed"); -} - -static Chan* -rtcattach(char* spec) -{ - return devattach('r', spec); -} - -static Walkqid* -rtcwalk(Chan* c, Chan *nc, char** name, int nname) -{ - return devwalk(c, nc, name, nname, rtcdir, nelem(rtcdir), devgen); -} - -static int -rtcstat(Chan* c, uchar* dp, int n) -{ - return devstat(c, dp, n, rtcdir, nelem(rtcdir), devgen); -} - -static Chan* -rtcopen(Chan* c, int omode) -{ - omode = openmode(omode); - switch((ulong)c->qid.path){ - case Qrtc: - if(strcmp(up->env->user, eve)!=0 && omode!=OREAD) - error(Eperm); - break; - case Qnvram: - if(strcmp(up->env->user, eve)!=0) - error(Eperm); - } - return devopen(c, omode, rtcdir, nelem(rtcdir), devgen); -} - -static void -rtcclose(Chan*) -{ -} - -#define GETBCD(o) ((bcdclock[o]&0xf) + 10*(bcdclock[o]>>4)) - -static long -_rtctime(void) -{ - uchar bcdclock[Nbcd]; - Rtc rtc; - int i; - - /* don't do the read until the clock is no longer busy */ - for(i = 0; i < 10000; i++){ - outb(Paddr, Status); - if(inb(Pdata) & 0x80) - continue; - - /* read clock values */ - outb(Paddr, Seconds); bcdclock[0] = inb(Pdata); - outb(Paddr, Minutes); bcdclock[1] = inb(Pdata); - outb(Paddr, Hours); bcdclock[2] = inb(Pdata); - outb(Paddr, Mday); bcdclock[3] = inb(Pdata); - outb(Paddr, Month); bcdclock[4] = inb(Pdata); - outb(Paddr, Year); bcdclock[5] = inb(Pdata); - - outb(Paddr, Status); - if((inb(Pdata) & 0x80) == 0) - break; - } - - /* - * convert from BCD - */ - rtc.sec = GETBCD(0); - rtc.min = GETBCD(1); - rtc.hour = GETBCD(2); - rtc.mday = GETBCD(3); - rtc.mon = GETBCD(4); - rtc.year = GETBCD(5); - - /* - * the world starts jan 1 1970 - */ - if(rtc.year < 70) - rtc.year += 2000; - else - rtc.year += 1900; - return rtc2sec(&rtc); -} - -static Lock nvrtlock; - -long -rtctime(void) -{ - int i; - long t, ot; - - ilock(&nvrtlock); - - /* loop till we get two reads in a row the same */ - t = _rtctime(); - for(i = 0; i < 100; i++){ - ot = t; - t = _rtctime(); - if(ot == t) - break; - } - if(i == 100) print("we are boofheads\n"); - - iunlock(&nvrtlock); - - return t; -} - -static long -rtcread(Chan* c, void* buf, long n, vlong off) -{ - ulong t; - char *a, *start; - ulong offset = off; - - if(c->qid.type & QTDIR) - return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen); - - switch((ulong)c->qid.path){ - case Qrtc: - t = rtctime(); - n = readnum(offset, buf, n, t, 12); - return n; - case Qnvram: - if(n == 0) - return 0; - if(n > Nvsize) - n = Nvsize; - a = start = smalloc(n); - - ilock(&nvrtlock); - for(t = offset; t < offset + n; t++){ - if(t >= Nvsize) - break; - outb(Paddr, Nvoff+t); - *a++ = inb(Pdata); - } - iunlock(&nvrtlock); - - if(waserror()){ - free(start); - nexterror(); - } - memmove(buf, start, t - offset); - poperror(); - - free(start); - return t - offset; - } - error(Ebadarg); - return 0; -} - -#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4) - -static long -rtcwrite(Chan* c, void* buf, long n, vlong off) -{ - int t; - char *a, *start; - Rtc rtc; - ulong secs; - uchar bcdclock[Nbcd]; - char *cp, *ep; - ulong offset = off; - - if(offset!=0) - error(Ebadarg); - - - switch((ulong)c->qid.path){ - case Qrtc: - /* - * read the time - */ - cp = ep = buf; - ep += n; - while(cp < ep){ - if(*cp>='0' && *cp<='9') - break; - cp++; - } - secs = strtoul(cp, 0, 0); - - /* - * convert to bcd - */ - sec2rtc(secs, &rtc); - PUTBCD(rtc.sec, 0); - PUTBCD(rtc.min, 1); - PUTBCD(rtc.hour, 2); - PUTBCD(rtc.mday, 3); - PUTBCD(rtc.mon, 4); - PUTBCD(rtc.year, 5); - - /* - * write the clock - */ - ilock(&nvrtlock); - outb(Paddr, Seconds); outb(Pdata, bcdclock[0]); - outb(Paddr, Minutes); outb(Pdata, bcdclock[1]); - outb(Paddr, Hours); outb(Pdata, bcdclock[2]); - outb(Paddr, Mday); outb(Pdata, bcdclock[3]); - outb(Paddr, Month); outb(Pdata, bcdclock[4]); - outb(Paddr, Year); outb(Pdata, bcdclock[5]); - iunlock(&nvrtlock); - return n; - case Qnvram: - if(n == 0) - return 0; - if(n > Nvsize) - n = Nvsize; - - start = a = smalloc(n); - if(waserror()){ - free(start); - nexterror(); - } - memmove(a, buf, n); - poperror(); - - ilock(&nvrtlock); - for(t = offset; t < offset + n; t++){ - if(t >= Nvsize) - break; - outb(Paddr, Nvoff+t); - outb(Pdata, *a++); - } - iunlock(&nvrtlock); - - free(start); - return t - offset; - } - error(Ebadarg); - return 0; -} - -Dev rtcdevtab = { - 'r', - "rtc", - - devreset, - rtcinit, - devshutdown, - rtcattach, - rtcwalk, - rtcstat, - rtcopen, - devcreate, - rtcclose, - rtcread, - devbread, - rtcwrite, - devbwrite, - devremove, - devwstat, -}; - -#define SEC2MIN 60L -#define SEC2HOUR (60L*SEC2MIN) -#define SEC2DAY (24L*SEC2HOUR) - -/* - * days per month plus days/year - */ -static int dmsize[] = -{ - 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; -static int ldmsize[] = -{ - 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -/* - * return the days/month for the given year - */ -static int* -yrsize(int y) -{ - if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0)) - return ldmsize; - else - return dmsize; -} - -/* - * compute seconds since Jan 1 1970 - */ -static ulong -rtc2sec(Rtc *rtc) -{ - ulong secs; - int i; - int *d2m; - - secs = 0; - - /* - * seconds per year - */ - for(i = 1970; i < rtc->year; i++){ - d2m = yrsize(i); - secs += d2m[0] * SEC2DAY; - } - - /* - * seconds per month - */ - d2m = yrsize(rtc->year); - for(i = 1; i < rtc->mon; i++) - secs += d2m[i] * SEC2DAY; - - secs += (rtc->mday-1) * SEC2DAY; - secs += rtc->hour * SEC2HOUR; - secs += rtc->min * SEC2MIN; - secs += rtc->sec; - - return secs; -} - -/* - * compute rtc from seconds since Jan 1 1970 - */ -static void -sec2rtc(ulong secs, Rtc *rtc) -{ - int d; - long hms, day; - int *d2m; - - /* - * break initial number into days - */ - hms = secs % SEC2DAY; - day = secs / SEC2DAY; - if(hms < 0) { - hms += SEC2DAY; - day -= 1; - } - - /* - * generate hours:minutes:seconds - */ - rtc->sec = hms % 60; - d = hms / 60; - rtc->min = d % 60; - d /= 60; - rtc->hour = d; - - /* - * year number - */ - if(day >= 0) - for(d = 1970; day >= *yrsize(d); d++) - day -= *yrsize(d); - else - for (d = 1970; day < 0; d--) - day += *yrsize(d-1); - rtc->year = d; - - /* - * generate month - */ - d2m = yrsize(rtc->year); - for(d = 1; day >= d2m[d]; d++) - day -= d2m[d]; - rtc->mday = day + 1; - rtc->mon = d; - - return; -} - -uchar -nvramread(int addr) -{ - uchar data; - - ilock(&nvrtlock); - outb(Paddr, addr); - data = inb(Pdata); - iunlock(&nvrtlock); - - return data; -} - -void -nvramwrite(int addr, uchar data) -{ - ilock(&nvrtlock); - outb(Paddr, addr); - outb(Pdata, data); - iunlock(&nvrtlock); -} diff --git a/os/pc/devtv.c b/os/pc/devtv.c deleted file mode 100644 index 5e45fa37..00000000 --- a/os/pc/devtv.c +++ /dev/null @@ -1,1826 +0,0 @@ -/* - * Driver for Hauppage TV board - * - * Control commands: - * - * init - * window %d %d %d %d - * colorkey %d %d %d %d %d %d - * capture %d %d %d %d - * capbrightness %d - * capcontrast %d - * capsaturation %d - * caphue %d - * capbw %d - * brightness %d - * contrast %d - * saturation %d - * source %d - * svideo %d - * format %d - * channel %d %d - * signal - * volume %d [ %d ] - * bass %d - * treble %d - * freeze %d - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "tv.h" - -#include - -enum { - MemSize= 1, - MemAddr= 0xB8000, - - CompressReg= -14, - - /* smart lock registers */ - SLReg1= -2, - SLReg2= -1, - - /* the Bt812 registers */ - Bt812Index= -5, - Bt812Data= -6, - - Bt2VideoPresent= 0x40, - Bt4ColorBars= 0x40, - Bt5YCFormat= 0x80, - Bt7TriState= 0x0C, - - /* VxP 500 registers */ - Vxp500Index= 0, - Vxp500Data= 1, - - /* video controller registers */ - MemoryWindowBaseAddrA= 0x14, - MemoryWindowBaseAddrB= 0x15, - MemoryPageReg= 0x16, - MemoryConfReg= 0x18, - ISAControl= 0x30, - I2CControl= 0x34, - InputVideoConfA= 0x38, - InputVideoConfB= 0x39, - ISASourceWindowWidthA= 0x3A, - ISASourceWindowWidthB= 0x3B, - ISASourceWindowHeightA= 0x3C, - ISASourceWindowHeightB= 0x3D, - InputHorzCropLeftA= 0x40, - InputHorzCropLeftB= 0x41, - InputHorzCropRightA= 0x44, - InputHorzCropRightB= 0x45, - InputHorzCropTopA= 0x48, - InputHorzCropTopB= 0x49, - InputHorzCropBottomA= 0x4C, - InputHorzCropBottomB= 0x4D, - InputHorzFilter= 0x50, - InputHorzScaleControlA= 0x54, - InputHorzScaleControlB= 0x55, - InputVertInterpolControl= 0x58, - InputVertScaleControlA= 0x5C, - InputVertScaleControlB= 0x5D, - InputFieldPixelBufStatus= 0x64, - VideoInputFrameBufDepthA= 0x68, - VideoInputFrameBufDepthB= 0x69, - AcquisitionControl= 0x6C, - AcquisitionAddrA= 0x70, - AcquisitionAddrB= 0x71, - AcquisitionAddrC= 0x72, - VideoBufferLayoutControl= 0x73, - CaptureControl= 0x80, - CaptureViewPortAddrA= 0x81, - CaptureViewPortAddrB= 0x82, - CaptureViewPortAddrC= 0x83, - CaptureViewPortWidthA= 0x84, - CaptureViewPortWidthB= 0x85, - CaptureViewPortHeightA= 0x86, - CaptureViewPortHeightB= 0x87, - CapturePixelBufLow= 0x88, - CapturePixelBufHigh= 0x89, - CaptureMultiBufDepthA= 0x8A, - CaptureMultiBufDepthB= 0x8B, - DisplayControl= 0x92, - VGAControl= 0x94, - OutputProcControlA= 0x96, - OutputProcControlB= 0x97, - DisplayViewPortStartAddrA= 0xA0, - DisplayViewPortStartAddrB= 0xA1, - DisplayViewPortStartAddrC= 0xA2, - DisplayViewPortWidthA= 0xA4, - DisplayViewPortWidthB= 0xA5, - DisplayViewPortHeightA= 0xA6, - DisplayViewPortHeightB= 0xA7, - DisplayViewPortOrigTopA= 0xA8, - DisplayViewPortOrigTopB= 0xA9, - DisplayViewPortOrigLeftA= 0xAA, - DisplayViewPortOrigLeftB= 0xAB, - DisplayWindowLeftA= 0xB0, - DisplayWindowLeftB= 0xB1, - DisplayWindowRightA= 0xB4, - DisplayWindowRightB= 0xB5, - DisplayWindowTopA= 0xB8, - DisplayWindowTopB= 0xB9, - DisplayWindowBottomA= 0xBC, - DisplayWindowBottomB= 0xBD, - OutputVertZoomControlA= 0xC0, - OutputVertZoomControlB= 0xC1, - OutputHorzZoomControlA= 0xC4, - OutputHorzZoomControlB= 0xC5, - BrightnessControl= 0xC8, - ContrastControl= 0xC9, - SaturationControl= 0xCA, - VideoOutIntrStatus= 0xD3, - - /* smart lock bits */ - PixelClk= 0x03, - SmartLock= 0x00, - FeatureConnector= 0x01, - Divider= 0x02, - Window= 0x08, - KeyWindow= 0x0C, - HSyncLow= 0x20, - VSyncLow= 0x40, - - ClkBit= 0x01, - DataBit= 0x02, - HoldBit= 0x04, - SelBit= 0x08, - DivControl= 0x40, - - /* i2c bus control bits */ - I2C_Clock= 0x02, - I2C_Data= 0x08, - I2C_RdClock= 0x10, - I2C_RdData= 0x20, - I2C_RdData_D= 0x40, - - /* I2C bus addresses */ - Adr5249= 0x22, /* teletext decoder */ - Adr8444= 0x48, /* 6-bit DAC (TDA 8444) */ - Adr6300= 0x80, /* sound fader (TEA 6300) */ - Adr6320= 0x80, /* sound fader (TEA 6320T) */ - AdrTuner= 0xC0, - - /* Philips audio chips */ - TEA6300= 0, - TEA6320T= 1, - - /* input formats */ - NTSC_M = 0, - NTSC_443 = 1, - External = 2, - - NTSCCropLeft= 36, /* NTSC 3.6 usec */ - NTSCCropRight= 558, /* NTSC 55.8 usec */ - - /* color control indices */ - Vxp500Brightness= 1, - Vxp500Contrast= 2, - Vxp500Saturation= 3, - Bt812Brightness= 4, - Bt812Contrast= 5, - Bt812Saturation= 6, - Bt812Hue= 7, - Bt812BW= 8, - - /* board revision numbers */ - RevisionPP= 0, - RevisionA= 1, - HighQ= 2, - - /* VGA controller registers */ - VGAMiscOut= 0x3CC, - VGAIndex= 0x3D4, - VGAData= 0x3D5, - VGAHorzTotal= 0x00, -}; - -enum { - Qdir, - Qdata, - Qctl, -}; - -static -Dirtab tvtab[]={ - ".", {Qdir, 0, QTDIR}, 0, 0555, - "tv", {Qdata, 0}, 0, 0666, - "tvctl", {Qctl, 0}, 0, 0666, -}; - -static -int ports[] = { /* board addresses */ - 0x51C, 0x53C, 0x55C, 0x57C, - 0x59C, 0x5BC, 0x5DC, 0x5FC -}; - -/* - * Default settings, settings between 0..100 - */ -static -int defaults[] = { - Vxp500Brightness, 0, - Vxp500Contrast, 54, - Vxp500Saturation, 54, - Bt812Brightness, 13, - Bt812Contrast, 57, - Bt812Saturation, 51, - Bt812Hue, 0, - Bt812BW, 0, -}; - -static int port; -static int soundchip; -static int boardrev; -static int left, right; -static int vsync, hsync; -static ulong xtalfreq; -static ushort cropleft, cropright; -static ushort cropbottom, croptop; -static Rectangle window, capwindow; - -static void setreg(int, int); -static void setbt812reg(int, int); -static void videoinit(void); -static void createwindow(Rectangle); -static void setcontrols(int, uchar); -static void setcolorkey(int, int, int, int, int, int); -static void soundinit(void); -static void setvolume(int, int); -static void setbass(int); -static void settreble(int); -static void setsoundsource(int); -static void tunerinit(void); -static void settuner(int, int); -static void setvideosource(int); -static int waitvideosignal(void); -static void freeze(int); -static void setsvideo(int); -static void setinputformat(int); -static void enablevideo(void); -static void *saveframe(int *); - -static int -min(int a, int b) -{ - return a < b ? a : b; -} - -static int -max(int a, int b) -{ - return a < b ? b : a; -} - -static int -present(int port) -{ - outb(port+Vxp500Index, 0xAA); - if (inb(port+Vxp500Index) != 0xAA) - return 0; - outb(port+Vxp500Index, 0x55); - outb(port+Vxp500Data, 0xAA); - if (inb(port+Vxp500Index) != 0x55) - return 0; - if (inb(port+Vxp500Data) != 0xAA) - return 0; - outb(port+Vxp500Data, 0x55); - if (inb(port+Vxp500Index) != 0x55) - return 0; - if (inb(port+Vxp500Data) != 0x55) - return 0; - return 1; -} - -static int -getvsync(void) -{ - int vslow, vshigh, s; - ushort timo; - - s = splhi(); - - outb(port+Vxp500Index, VideoOutIntrStatus); - - /* wait for VSync to go high then low */ - for (timo = ~0; timo; timo--) - if (inb(port+Vxp500Data) & 2) break; - for (timo = ~0; timo; timo--) - if ((inb(port+Vxp500Data) & 2) == 0) break; - - /* count how long it stays low and how long it stays high */ - for (vslow = 0, timo = ~0; timo; timo--, vslow++) - if (inb(port+Vxp500Data) & 2) break; - for (vshigh = 0, timo = ~0; timo; timo--, vshigh++) - if ((inb(port+Vxp500Data) & 2) == 0) break; - splx(s); - - return vslow < vshigh; -} - -static int -gethsync(void) -{ - int hslow, hshigh, s; - ushort timo; - - s = splhi(); - - outb(port+Vxp500Index, VideoOutIntrStatus); - - /* wait for HSync to go high then low */ - for (timo = ~0; timo; timo--) - if (inb(port+Vxp500Data) & 1) break; - for (timo = ~0; timo; timo--) - if ((inb(port+Vxp500Data) & 1) == 0) break; - - /* count how long it stays low and how long it stays high */ - for (hslow = 0, timo = ~0; timo; timo--, hslow++) - if (inb(port+Vxp500Data) & 1) break; - for (hshigh = 0, timo = ~0; timo; timo--, hshigh++) - if ((inb(port+Vxp500Data) & 1) == 0) break; - splx(s); - - return hslow < hshigh; -} - -static void -tvinit(void) -{ - int i; - - for (i = 0, port = 0; i < nelem(ports); i++) { - if (present(ports[i])) { - port = ports[i]; - break; - } - } - if (i == nelem(ports)) - return; - - /* - * the following routines are the prefered way to - * find out the sync polarities. Unfortunately, it - * doesn't always work. - */ -#ifndef VSync - vsync = getvsync(); - hsync = gethsync(); -#else - vsync = VSync; - hsync = HSync; -#endif - left = right = 80; - soundinit(); - tunerinit(); - videoinit(); -} - -static Chan* -tvattach(char *spec) -{ - if (port == 0) - error(Enonexist); - return devattach('V', spec); -} - -static Walkqid* -tvwalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, tvtab, nelem(tvtab), devgen); -} - -static int -tvstat(Chan *c, uchar *db, int n) -{ - return devstat(c, db, n, tvtab, nelem(tvtab), devgen); -} - -static Chan* -tvopen(Chan *c, int omode) -{ - return devopen(c, omode, tvtab, nelem(tvtab), devgen); -} - -static void -tvclose(Chan *) -{ -} - -static long -tvread(Chan *c, void *a, long n, vlong offset) -{ - static void *frame; - static int size; - - USED(offset); - - switch((ulong)c->qid.path){ - case Qdir: - return devdirread(c, a, n, tvtab, nelem(tvtab), devgen); - case Qdata: - if (eqrect(capwindow, Rect(0, 0, 0, 0))) - error(Ebadarg); - if (offset == 0) - frame = saveframe(&size); - if (frame) { - if (n > size - offset) - n = size - offset; - memmove(a, (char *)frame + offset, n); - } else - error(Enovmem); - break; - default: - n=0; - break; - } - return n; -} - -static long -tvwrite(Chan *c, void *vp, long n, vlong offset) -{ - char buf[128], *field[10], *a; - int i, nf, source; - static Rectangle win; - static int hsize, size = 0; - static void *frame; - - USED(offset); - - a = vp; - switch((ulong)c->qid.path){ - case Qctl: - if (n > sizeof(buf)-1) - n = sizeof(buf)-1; - memmove(buf, a, n); - buf[n] = '\0'; - - nf = getfields(buf, field, nelem(field), 1, " \t"); - if (nf < 1) error(Ebadarg); - - if (strcmp(field[0], "init") == 0) { - window = Rect(0, 0, 0, 0); - capwindow = Rect(0, 0, 0, 0); - source = 0; /* video 0 input */ - setvideosource(source); - left = right = 80; - setsoundsource(source); - for (i = 0; i < nelem(defaults); i += 2) - setcontrols(defaults[i], defaults[i+1]); - } else if (strcmp(field[0], "colorkey") == 0) { - if (nf < 7) error(Ebadarg); - setcolorkey(strtoul(field[1], 0, 0), strtoul(field[2], 0, 0), - strtoul(field[3], 0, 0), strtoul(field[4], 0, 0), - strtoul(field[5], 0, 0), strtoul(field[6], 0, 0)); - } else if (strcmp(field[0], "window") == 0) { - if (nf < 5) error(Ebadarg); - createwindow(Rect(strtoul(field[1], 0, 0), strtoul(field[2], 0, 0), - strtoul(field[3], 0, 0), strtoul(field[4], 0, 0))); - setvolume(left, right); - } else if (strcmp(field[0], "capture") == 0) { - if (nf < 5) error(Ebadarg); - capwindow = Rect(strtoul(field[1], 0, 0), strtoul(field[2], 0, 0), - strtoul(field[3], 0, 0), strtoul(field[4], 0, 0)); - } else if (strcmp(field[0], "freeze") == 0) { - if (nf < 2) error(Ebadarg); - freeze(strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "capbrightness") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Bt812Brightness, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "capcontrast") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Bt812Contrast, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "capsaturation") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Bt812Saturation, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "caphue") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Bt812Hue, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "capbw") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Bt812BW, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "brightness") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Vxp500Brightness, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "contrast") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Vxp500Contrast, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "saturation") == 0) { - if (nf < 2) error(Ebadarg); - setcontrols(Vxp500Saturation, strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "source") == 0) { - if (nf < 2) error(Ebadarg); - source = strtoul(field[1], 0, 0); - setvideosource(source); - setsoundsource(source); - } else if (strcmp(field[0], "svideo") == 0) { - if (nf < 2) error(Ebadarg); - setsvideo(strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "format") == 0) { - if (nf < 2) error(Ebadarg); - setinputformat(strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "channel") == 0) { - if (nf < 3) error(Ebadarg); - setvolume(0, 0); - settuner(strtoul(field[1], 0, 0), strtoul(field[2], 0, 0)); - tsleep(&up->sleep, return0, 0, 300); - setvolume(left, right); - } else if (strcmp(field[0], "signal") == 0) { - if (!waitvideosignal()) - error(Etimedout); - } else if (strcmp(field[0], "volume") == 0) { - if (nf < 2) error(Ebadarg); - left = strtoul(field[1], 0, 0); - if (nf < 3) - right = left; - else - right = strtoul(field[2], 0, 0); - setvolume(left, right); - } else if (strcmp(field[0], "bass") == 0) { - if (nf < 2) error(Ebadarg); - setbass(strtoul(field[1], 0, 0)); - } else if (strcmp(field[0], "treble") == 0) { - if (nf < 2) error(Ebadarg); - settreble(strtoul(field[1], 0, 0)); - } else - error(Ebadctl); - break; - default: - error(Ebadusefd); - } - return n; -} - - -Dev tvdevtab = { - 'V', - "tv", - - devreset, - tvinit, - devshutdown, - tvattach, - tvwalk, - tvstat, - tvopen, - devcreate, - tvclose, - tvread, - devbread, - tvwrite, - devbwrite, - devremove, - devwstat, -}; - -static void -setreg(int index, int data) -{ - outb(port+Vxp500Index, index); - outb(port+Vxp500Data, data); -} - -static unsigned int -getreg(int index) -{ - outb(port+Vxp500Index, index); - return inb(port+Vxp500Data); -} - -/* - * I2C routines - */ -static void -delayi2c(void) -{ - int i, val; - - /* delay for 4.5 usec to guarantee clock time */ - for (i = 0; i < 75; i++) { /* was 50 */ - val = inb(port+Vxp500Data); - USED(val); - } -} - -static int -waitSDA(void) -{ - ushort timo; - - /* wait for i2c clock to float high */ - for (timo = ~0; timo; timo--) - if (inb(port+Vxp500Data) & I2C_RdData) - break; - if (!timo) print("devtv: waitSDA fell out of loop\n"); - return !timo; -} - -static int -waitSCL(void) -{ - ushort timo; - - /* wait for i2c clock to float high */ - for (timo = ~0; timo; timo--) - if (inb(port+Vxp500Data) & I2C_RdClock) - break; - delayi2c(); - if (!timo) print("devtv: waitSCL fell out of loop\n"); - return !timo; -} - -static int -seti2cdata(int data) -{ - int b, reg, val; - int error; - - error = 0; - reg = inb(port+Vxp500Data); - for (b = 0x80; b; b >>= 1) { - if (data & b) - reg |= I2C_Data; - else - reg &= ~I2C_Data; - outb(port+Vxp500Data, reg); - reg |= I2C_Clock; - outb(port+Vxp500Data, reg); - error |= waitSCL(); - reg &= ~I2C_Clock; - outb(port+Vxp500Data, reg); - delayi2c(); - } - reg |= I2C_Data; - outb(port+Vxp500Data, reg); - reg |= I2C_Clock; - outb(port+Vxp500Data, reg); - error |= waitSCL(); - val = inb(port+Vxp500Data); - USED(val); - reg &= ~I2C_Clock; - outb(port+Vxp500Data, reg); - delayi2c(); - return error; -} - -static int -seti2creg(int id, int index, int data) -{ - int reg, error; - - error = 0; - /* set i2c control register to enable i2c clock and data lines */ - setreg(I2CControl, I2C_Data|I2C_Clock); - error |= waitSDA(); - error |= waitSCL(); - outb(port+Vxp500Data, I2C_Clock); - delayi2c(); - outb(port+Vxp500Data, 0); - delayi2c(); - - error |= seti2cdata(id); - error |= seti2cdata(index); - error |= seti2cdata(data); - - reg = inb(port+Vxp500Data); - reg &= ~I2C_Data; - outb(port+Vxp500Data, reg); - reg |= I2C_Clock; - outb(port+Vxp500Data, reg); - error |= waitSCL(); - reg |= I2C_Data; - outb(port+Vxp500Data, reg); - error |= waitSDA(); - return error; -} - -static int -seti2cregs(int id, int index, int n, uchar *data) -{ - int reg, error; - - error = 0; - /* set i2c control register to enable i2c clock and data lines */ - setreg(I2CControl, I2C_Data|I2C_Clock); - error |= waitSDA(); - error |= waitSCL(); - outb(port+Vxp500Data, I2C_Clock); - delayi2c(); - outb(port+Vxp500Data, 0); - delayi2c(); - - /* send data */ - error |= seti2cdata(id); - error |= seti2cdata(index); - while (n--) - error |= seti2cdata(*data++); - - /* send stop */ - reg = inb(port+Vxp500Data); - reg &= ~I2C_Data; - outb(port+Vxp500Data, reg); - reg |= I2C_Clock; - outb(port+Vxp500Data, reg); - error |= waitSCL(); - reg |= I2C_Data; - outb(port+Vxp500Data, reg); - error |= waitSDA(); - return error; -} - -/* - * Audio routines - */ -static void -setvolume(int left, int right) -{ - int vol, loudness = 0; - - if (soundchip == TEA6300) { - seti2creg(Adr6300, 0, (63L * left) / 100); - seti2creg(Adr6300, 1, (63L * right) / 100); - vol = (15L * max(left, right)) / 100; - seti2creg(Adr6300, 4, 0x30 | vol); - } else { - vol = (63L * max(left, right)) / 100; - seti2creg(Adr6320, 0, vol | (loudness << 6)); - seti2creg(Adr6320, 1, (63L * right) / 100); - seti2creg(Adr6320, 2, (63L * left) / 100); - } -} - -static void -setbass(int bass) -{ - if (soundchip == TEA6300) - seti2creg(Adr6300, 2, (15L * bass) / 100); - else - seti2creg(Adr6320, 5, max((31L * bass) / 100, 4)); -} - -static void -settreble(int treble) -{ - if (soundchip == TEA6300) - seti2creg(Adr6300, 3, (15L * treble) / 100); - else - seti2creg(Adr6320, 6, max((31L * treble) / 100, 7)); - -} - -static void -setsoundsource(int source) -{ - if (soundchip == TEA6300) - seti2creg(Adr6300, 5, 1 << source); - else - seti2creg(Adr6320, 7, source); - setbass(50); - settreble(50); - setvolume(left, right); -} - -static void -soundinit(void) -{ - if (seti2creg(Adr6320, 7, 0) && seti2creg(Adr6300, 4, 0)) - print("devtv: Audio init failed\n"); - - soundchip = AudioChip; - setvolume(0, 0); -} - -/* - * Tuner routines - */ -static -long hrcfreq[] = { /* HRC CATV frequencies */ - 0, 7200, 5400, 6000, 6600, 7800, 8400, 17400, - 18000, 18600, 19200, 19800, 20400, 21000, 12000, 12600, - 13200, 13800, 14400, 15000, 15600, 16200, 16800, 21600, - 22200, 22800, 23400, 24000, 24600, 25200, 25800, 26400, - 27000, 27600, 28200, 28800, 29400, 30000, 30600, 31200, - 31800, 32400, 33000, 33600, 34200, 34800, 35400, 36000, - 36600, 37200, 37800, 38400, 39000, 39600, 40200, 40800, - 41400, 42000, 42600, 43200, 43800, 44400, 45000, 45600, - 46200, 46800, 47400, 48000, 48600, 49200, 49800, 50400, - 51000, 51600, 52200, 52800, 53400, 54000, 54600, 55200, - 55800, 56400, 57000, 57600, 58200, 58800, 59400, 60000, - 60600, 61200, 61800, 62400, 63000, 63600, 64200, 9000, - 9600, 10200, 10800, 11400, 64800, 65400, 66000, 66600, - 67200, 67800, 68400, 69000, 69600, 70200, 70800, 71400, - 72000, 72600, 73200, 73800, 74400, 75000, 75600, 76200, - 76800, 77400, 78000, 78600, 79200, 79800, -}; - -static void -settuner(int channel, int finetune) -{ - static long lastfreq; - uchar data[3]; - long freq; - int cw2, n, sa; - - if (channel < 0 || channel > nelem(hrcfreq)) - error(Ebadarg); - - freq = hrcfreq[channel]; - - /* these settings are all for (FS936E) USA Tuners */ - if (freq < 16025) /* low band */ - cw2 = 0xA4; - else if (freq < 45425) /* mid band */ - cw2 = 0x94; - else - cw2 = 0x34; - - /* - * Channels are stored are 1/100 MHz resolutions, but - * the tuner wants stuff in MHZ, so divide by 100, we - * then have to shift by 4 to get the prog. div. value - */ - n = ((freq + 4575L) * 16) / 100L + finetune; - - if (freq > lastfreq) { - sa = (n >> 8) & 0xFF; - data[0] = n & 0xFF; - data[1] = 0x8E; - data[2] = cw2; - } else { - sa = 0x8E; - data[0] = cw2; - data[1] = (n >> 8) & 0xFF; - data[2] = n & 0xFF; - } - lastfreq = freq; - seti2cregs(AdrTuner, sa, 3, data); -} - -static void -tunerinit(void) -{ - if (seti2creg(AdrTuner, 0, 0)) - print("devtv: Tuner init failed\n"); -} - -/* - * Video routines - */ -static int slreg1 = 0; -static int slreg2 = 0; -static int vcogain = 0; -static int phdetgain = 2; -static int plln1 = 2; -static int pllp2 = 1; - -static void -waitforretrace(void) -{ - ushort timo; - - for (timo = ~0; (getreg(VideoOutIntrStatus) & 2) == 0 && timo; timo--) - /* wait for VSync inactive */; - for (timo = ~0; (getreg(VideoOutIntrStatus) & 2) && timo; timo--) - /* wait for VSync active */; -} - -static void -updateshadowregs(void) -{ - int val; - - setreg(InputVideoConfA, getreg(InputVideoConfA) | 0x40); - val = getreg(OutputProcControlB); - setreg(OutputProcControlB, val & 0x7F); - setreg(OutputProcControlB, val | 0x80); -} - -static void -setvgareg(int data) -{ - /* set HSync & VSync first, to make sure VSync works properly */ - setreg(VGAControl, (getreg(VGAControl) & ~0x06) | (data & 0x06)); - - /* wait for VSync and set the whole register */ - waitforretrace(); - setreg(VGAControl, data); -} - -static void -setbt812reg(int index, int data) -{ - outb(port+Bt812Index, index); - outb(port+Bt812Data, data); -} - -static int -getbt812reg(int index) -{ - outb(port+Bt812Index, index); - return inb(port+Bt812Data); -} - -static void -setbt812regpair(int index, ushort data) -{ - outb(port+Bt812Index, index); - outb(port+Bt812Data, data); - outb(port+Bt812Data, data >> 8); -} - -static void -setvideosource(int source) -{ - int s; - - source &= 7; - s = source & 3; - setbt812reg(0, ((s << 2) | s) << 3); - s = (source & 4) << 4; - setbt812reg(4, (getbt812reg(4) & ~Bt4ColorBars) | s); -} - -static void -setsvideo(int enable) -{ - if (enable) - setbt812reg(5, getbt812reg(5) | Bt5YCFormat); - else - setbt812reg(5, getbt812reg(5) & ~Bt5YCFormat); -} - -static int -waitvideosignal(void) -{ - ushort timo; - - for (timo = ~0; timo; timo--) - if (getbt812reg(2) & Bt2VideoPresent) - return 1; - return 0; -} - -/* - * ICS1572 Programming Configuration - * - * R = 1 - * M = x - * A = x - * N1 = 4 - * N2 = internal divide ratio - */ -static -uchar ICSbits[7] = { - 0x01, /* bits 8 - 1 00000001 */ - 0x05, /* bits 16 - 9 00000101 */ - 0xFF, /* bits 24 - 17 11111111 */ - 0x8C, /* bits 32 - 25 10001100 */ - 0xBF, /* bits 40 - 33 10111111 */ - 0x00, /* bits 48 - 41 00000000 */ - 0x00, /* bits 56 - 49 00000000 */ -}; - -static void -sendbit(int val, int hold) -{ - slreg2 &= ~(HoldBit|DataBit|ClkBit); - if (val) slreg2 |= DataBit; - if (hold) slreg2 |= HoldBit; - outb(port+SLReg2, slreg2); - outb(port+SLReg2, slreg2|ClkBit); - outb(port+SLReg2, slreg2); -} - -static void -load1572(int select) -{ - int reg; - uchar mask; - - if (select) - slreg2 |= SelBit; - else - slreg2 &= ~SelBit; - outb(port+SLReg2, slreg2); - - for (reg = 0; reg < sizeof(ICSbits); reg++) { - for (mask = 1; mask != 0; mask <<= 1) { - if (reg == sizeof(ICSbits)-1 && mask == 0x80) { - sendbit(ICSbits[reg] & mask, 1); - } else - sendbit(ICSbits[reg] & mask, 0); - } - } -} - -static void -smartlockdiv(int count, int vcogain, int phdetgain, int n1, int p2) -{ - int extdiv, intdiv; - int nslreg2, external; - - nslreg2 = slreg2; - extdiv = ((count - 1) / 512) + 1; - intdiv = (count / extdiv); - nslreg2 &= ~0xC0; - switch (extdiv) { - case 1: external = 0; break; - case 2: external = 1; break; - case 3: external = 1; nslreg2 |= 0x40; break; - case 4: external = 1; nslreg2 |= 0x80; break; - default: return; - } - if ((slreg1 & PixelClk) == 0) { - slreg2 = nslreg2; - outb(port+SLReg2, slreg2); - } - - /* set PLL divider */ - ICSbits[0] &= ~0x07; - ICSbits[0] |= n1 & 0x07; - ICSbits[3] &= ~0xB7; - ICSbits[3] |= vcogain & 0x07; - ICSbits[3] |= (phdetgain & 0x03) << 4; - ICSbits[3] |= p2 << 7; - if (external) - ICSbits[1] |= 0x04; /* set EXTFBKEN */ - else - ICSbits[1] &= ~0x04; /* clear EXTFBKEN */ - intdiv--; - ICSbits[2] = intdiv; /* set N2 */ - ICSbits[3] &= ~ 0x08; - ICSbits[3] |= (intdiv >> 5) & 0x08; - load1572(1); -} - -static void -disablecolorkey(void) -{ - setreg(DisplayControl, getreg(DisplayControl) & 0xFE); - updateshadowregs(); -} - -static -uchar colorkeylimit[6] = { - 15, /* upper limit green */ - 255, /* lower limit green */ - 63, /* upper limit red */ - 63, /* upper limit blue */ - 15, /* lower limit red */ - 15, /* lower limit blue */ -}; - -static void -enablecolorkey(int enable) -{ - int i; - - if (enable) { - for (i = 0; i < 6; i++) - seti2creg(Adr8444, 0xF0 | i, colorkeylimit[i]); - slreg1 &= ~0x1C; - if (colorkeylimit[4] == 255) - slreg1 |= 0x04; /* disable red lower limit */ - if (colorkeylimit[1] == 255) - slreg1 |= 0x08; /* disable green lower limit */ - if (colorkeylimit[5] == 255) - slreg1 |= 0x10; /* disable blue lower limit */ - } else { - for (i = 0; i < 6; i++) - seti2creg(Adr8444, 0xF0 | i, 63); - slreg1 |= 0x1C; - } - outb(port+SLReg1, slreg1); - disablecolorkey(); -} - -static void -setcolorkey(int rl, int rh, int gl, int gh, int bl, int bh) -{ - colorkeylimit[0] = gh; - colorkeylimit[1] = gl; - colorkeylimit[2] = rh; - colorkeylimit[3] = bh; - colorkeylimit[4] = rl; - colorkeylimit[5] = bl; - enablecolorkey(1); -} - -static void -waitvideoframe(void) -{ - ushort timo; - int val; - - /* clear status bits and wait for start of an even field */ - val = getreg(InputFieldPixelBufStatus); - USED(val); - for (timo = ~0; timo; timo--) - if ((getreg(InputFieldPixelBufStatus) & 2) == 0) - break; - if (!timo) print("devtv: Wait for video frame failed\n"); -} - -static void -freeze(int enable) -{ - ushort timo; - int reg; - - if (enable) { - waitvideoframe(); - waitvideoframe(); - - setreg(InputVideoConfB, getreg(InputVideoConfB) | 0x08); - updateshadowregs(); - - for (timo = ~0; timo; timo--) - if (getreg(InputVideoConfB) & 0x80) break; - waitvideoframe(); - - reg = getreg(OutputProcControlB); - if ((reg & 0x20) == 0) { - setreg(ISAControl, 0x80); - setreg(OutputProcControlB, getreg(OutputProcControlB) | 0x20); - setreg(ISAControl, 0x42); - - reg = getreg(OutputProcControlB); - setreg(OutputProcControlB, reg & 0x7F); - setreg(OutputProcControlB, reg | 0x80); - } - } else { - setreg(InputVideoConfB, getreg(InputVideoConfB) & ~0x08); - updateshadowregs(); - - for (timo = ~0; timo; timo--) - if (getreg(InputVideoConfB) & 0x40) break; - waitvideoframe(); - reg = getreg(InputFieldPixelBufStatus); - USED(reg); - } -} - -static void -enablevideo(void) -{ - setreg(DisplayControl, 0x04); - updateshadowregs(); -} - -static void -disablevideo(void) -{ - setreg(DisplayControl, 0x18); - updateshadowregs(); -} - -static -uchar vxp500init[] = { /* video register initialization in (index,data) hex pairs */ - 0x30, 0x82, 0x39, 0x40, 0x58, 0x0C, 0x73, 0x02, 0x80, 0x00, 0x25, 0x0F, - 0x26, 0x0F, 0x38, 0x46, 0x30, 0x03, 0x12, 0x3B, 0x97, 0x20, 0x13, 0x00, - 0x14, 0x34, 0x15, 0x04, 0x16, 0x00, 0x17, 0x53, 0x18, 0x04, 0x19, 0x62, - 0x1C, 0x00, 0x1D, 0x00, 0x34, 0x3A, 0x38, 0x06, 0x3A, 0x00, 0x3B, 0x00, - 0x3C, 0x00, 0x3D, 0x00, 0x40, 0x40, 0x41, 0x40, 0x44, 0xFF, 0x45, 0xFF, - 0x48, 0x40, 0x49, 0x40, 0x4C, 0xFF, 0x4D, 0xFF, 0x50, 0xF0, 0x54, 0x30, - 0x55, 0x00, 0x5C, 0x04, 0x5D, 0x00, 0x60, 0x00, 0x68, 0x00, 0x69, 0x00, - 0x6C, 0x06, 0x6D, 0x00, 0x70, 0x00, 0x71, 0x00, 0x72, 0x00, 0x78, 0x01, - 0x79, 0x0C, 0x80, 0x10, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, - 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, 0x88, 0x04, 0x89, 0x10, 0x8A, 0x00, - 0x8B, 0x00, 0x90, 0x05, 0x91, 0x0C, 0x92, 0x18, 0x93, 0x00, 0x96, 0x18, - 0x9A, 0x30, 0x9C, 0x2D, 0x9D, 0x00, 0xA0, 0x00, 0xA1, 0x00, 0xA2, 0x00, - 0xA4, 0x50, 0xA5, 0x50, 0xA6, 0xF0, 0xA7, 0xF0, 0xA8, 0x19, 0xA9, 0x18, - 0xAA, 0x64, 0xAB, 0x64, 0xB0, 0x64, 0xB1, 0x64, 0xB4, 0xA4, 0xB5, 0xA5, - 0xB8, 0x19, 0xB9, 0x18, 0xBC, 0x09, 0xBD, 0x09, 0xC0, 0x00, 0xC1, 0x02, - 0xC4, 0x00, 0xC5, 0x00, 0xC8, 0x00, 0xC9, 0x08, 0xCA, 0x08, 0xCE, 0x00, - 0xCF, 0x00, 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD8, 0x00, 0xD9, 0x00, - 0xDA, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0xDD, 0x00, 0x38, 0x46, 0x97, 0xA0, - 0x97, 0x20, 0x97, 0xA0, -}; - -static -uchar bt812init[] = { /* bt812 initializations */ - 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0xC0, - 0x04, 0x08, 0x05, 0x00, 0x06, 0x40, 0x07, 0x00, 0x08, 0x10, - 0x09, 0x90, 0x0A, 0x80, 0x0B, 0x00, 0x0C, 0x0C, 0x0D, 0x03, - 0x0E, 0x66, 0x0F, 0x00, 0x10, 0x80, 0x11, 0x02, 0x12, 0x16, - 0x13, 0x00, 0x14, 0xE5, 0x15, 0x01, 0x16, 0xAB, 0x17, 0xAA, - 0x18, 0x12, 0x19, 0x51, 0x1A, 0x46, 0x1B, 0x00, 0x1C, 0x00, - 0x1D, 0x37, -}; - -static ushort actpixs = 720; -static ulong Hdesired = 13500000L; - -/* NTSC-M NTSC-443 EXTERNAL */ -static ushort horzfreq[] = { 15734, 15625, 0 }; -static ushort Vdelay[] = { 22, 25, 25 }; -static ushort s2b[] = { 90, 90, 0 }; -static ushort actlines[] = { 485, 485, 575 }; -static ulong subcarfreq[] = { 3579545, 4433619, 4433619 }; - -static -unsigned int framewidth[5][4] = { - 1024, 512, 512, 512, /* mode 0 - single, double, single, quad */ - 1536, 768, 768, 384, /* mode 1 - single, double, single, quad */ - 2048, 1024, 1024, 512, /* mode 2 - single, double, single, quad */ - 1024, 512, 512, 512, /* mode 3 - single, double, single, quad */ - 1536, 768, 768, 384 /* mode 4 - single, double, single, quad */ -}; - -static -unsigned int frameheight[5][4] = { - 512, 512, 1024, 512, /* mode 0 - single, double, single, quad */ - 512, 512, 1024, 512, /* mode 1 - single, double, single, quad */ - 512, 512, 1024, 512, /* mode 2 - single, double, single, quad */ - 512, 512, 1024, 512, /* mode 3 - single, double, single, quad */ - 512, 512, 1024, 256 /* mode 4 - single, double, single, quad */ -}; - -static -uchar horzfilter[] = { 3, 3, 2, 2, 1, 1, 0, 0 }; - -static -uchar interleave[] = { 2, 3, 4, 2, 3 }; - -#define ADJUST(n) (((n) * hrsmult + hrsdiv - 1) / hrsdiv) - -static int q = 100; -static int ilv = 2; -static int hrsmult = 1; -static int hrsdiv = 2; - -static ushort panmask[] = { 0xFFFE, 0xFFFC, 0xFFFF, 0xFFFF, 0xFFFE }; - - -static void -cropwindow(int left, int right, int top, int bottom) -{ - top &= 0x3FE; - bottom &= 0x3FE; - setreg(InputHorzCropLeftA, left); - setreg(InputHorzCropLeftB, left >> 8); - setreg(InputHorzCropRightA, right); - setreg(InputHorzCropRightB, right >> 8); - setreg(InputHorzCropTopA, top); - setreg(InputHorzCropTopB, top >> 8); - setreg(InputHorzCropBottomA, bottom); - setreg(InputHorzCropBottomB, bottom >> 8); -} - -static void -setinputformat(int format) -{ - ushort hclock, hclockdesired; - ulong subcarrier; - int cr7; - - cr7 = getbt812reg(7) & ~Bt7TriState; - if (format == External) - cr7 |= Bt7TriState; - setbt812reg(7, cr7); - setbt812reg(5, getbt812reg(5) & 2); - - hclock = (xtalfreq >> 1) / horzfreq[format]; - setbt812regpair(0x0C, hclock); - setbt812regpair(0x0E, - (ushort)(s2b[format] * (Hdesired / 10) / 1000000L) | 1); - setbt812regpair(0x10, actpixs); - setbt812regpair(0x12, Vdelay[format]); - setbt812regpair(0x14, actlines[format]); - - subcarrier = (ulong) - ((((long long)subcarfreq[format] * 0x1000000) / xtalfreq + 1) / 2); - setbt812regpair(0x16, (int)(subcarrier & 0xFFFF)); /* subcarrier */ - setbt812reg(0x18, (int)(subcarrier >> 16)); - - setbt812reg(0x19, (uchar)(((xtalfreq / 200) * 675) / 1000000L + 8)); - setbt812reg(0x1A, (uchar)((xtalfreq * 65) / 20000000L - 10)); - hclockdesired = (ushort) (Hdesired / horzfreq[format]); - setbt812regpair(0x1B, - (ushort)(((hclock - hclockdesired) * 65536L) / hclockdesired)); -} - -static ushort -vgadivider(void) -{ - ushort horztotal; - - outb(VGAIndex, VGAHorzTotal); - horztotal = (inb(VGAData) << 3) + 40; - if (horztotal > ScreenWidth && horztotal < ((ScreenWidth * 3 ) / 2)) - return horztotal; - else - return (ScreenWidth * 5) / 4; -} - -static void -videoinit(void) -{ - int i, reg, width, tuner; - - /* early PLL smart lock initialization */ - if (ScreenWidth == 640) { - slreg1 = Window|HSyncLow|VSyncLow; - slreg2 = 0x0D; - } else { - slreg1 = Window; - slreg2 = 0x0C; - } - outb(port+CompressReg, 2); - outb(port+SLReg1, slreg1); - outb(port+SLReg2, slreg2); - smartlockdiv((vgadivider() * hrsmult)/hrsdiv, vcogain, phdetgain, 2, 1); - - /* program the VxP-500 chip (disables video) */ - waitforretrace(); - for (i = 0; i < sizeof(vxp500init); i += 2) - setreg(vxp500init[i], vxp500init[i+1]); - - /* set memory base for frame capture */ - setreg(MemoryWindowBaseAddrA, MemAddr >> 14); - setreg(MemoryWindowBaseAddrB, ((MemAddr >> 22) & 3) | (MemSize << 2)); - setreg(MemoryPageReg, 0); - - /* generic 422 decoder, mode 3 and 4 */ - setreg(MemoryConfReg, ilv+1); - - setreg(AcquisitionAddrA, 0); - setreg(AcquisitionAddrB, 0); - setreg(AcquisitionAddrC, 0); - - /* program VxP-500 for correct sync polarity */ - reg = ScreenWidth > 1023 ? 0x01 : 0x00; - reg |= (vsync << 1) | (hsync << 2); - setvgareg(reg); - setreg(VGAControl, reg); - - setreg(VideoBufferLayoutControl, 0); /* for ilv = 2 */ - - /* set sync polarities to get proper blanking */ - if (vsync) - slreg1 |= VSyncLow; - if (!hsync) { - slreg1 ^= HSyncLow; - setreg(VGAControl, reg | 4); - } - outb(port+SLReg1, slreg1); - - if ((slreg1 & PixelClk) == 0) { /* smart lock active */ - enablecolorkey(1); - setreg(VGAControl, getreg(VGAControl) & 6); - } else - enablecolorkey(0); - - /* color key initializations */ - if ((slreg1 & PixelClk) == 0) - setreg(VGAControl, getreg(VGAControl) & 7); - - /* initialize Bt812 */ - for (i = 0; i < sizeof(bt812init); i += 2) - setbt812reg(bt812init[i], bt812init[i+1]); - - /* figure out clock source (Xtal or Oscillator) and revision */ - setbt812reg(6, 0x40); - reg = getreg(InputFieldPixelBufStatus) & 3; - if ((getreg(InputFieldPixelBufStatus) & 3) == reg) { - /* crystal - could be revision PP if R34 is installed */ - setbt812reg(6, 0x00); - reg = inb(port+SLReg1); - if (reg & 0x20) { - if ((reg & 0xE0) == 0xE0) - boardrev = HighQ; - else - boardrev = RevisionA; - } else - boardrev = RevisionPP; - } else /* revision A or newer with 27 MHz oscillator */ - boardrev = RevisionA; - - /* figure out xtal frequency */ - if (xtalfreq == 0) { - if (boardrev == RevisionPP) { - tuner = (inb(port+SLReg1) >> 6) & 3; - if (tuner == 0) /* NTSC */ - xtalfreq = 24545400L; - else - xtalfreq = 29500000L; - } else if (boardrev == HighQ) - xtalfreq = 29500000L; - else - xtalfreq = 27000000L; - } - -// print("Hauppage revision %d (xtalfreq %ld)\n", boardrev, xtalfreq); - - /* on RevPP boards set early sync, on rev A and newer clear it */ - if (boardrev == RevisionPP) - setreg(InputVideoConfA, getreg(InputVideoConfA) | 4); - else - setreg(InputVideoConfA, getreg(InputVideoConfA) & ~4); - - switch (xtalfreq) { - case 24545400L: - actpixs = 640; - break; - case 29500000L: - actpixs = 768; - break; - default: - actpixs = 720; - break; - } - - /* set crop window (these values are for NTSC!) */ - if (boardrev == RevisionPP) { - Hdesired = xtalfreq / 2; - cropleft = (NTSCCropLeft * ((Hdesired / 10))) / 1000000L; - cropright = (NTSCCropRight * ((Hdesired / 10))) / 1000000L; - } else { - cropleft = actpixs / 100; - cropright = actpixs - cropleft; - } - width = ((cropright - cropleft + ilv) / ilv) * ilv; - cropright = cropleft + width + 1; - croptop = 26; - cropbottom = 505; - cropwindow(cropleft, cropright, croptop, cropbottom); - - /* set input format */ - setinputformat(NTSC_M); - setsvideo(0); -} - -static void -panwindow(Point p) -{ - int memmode, ilv, frw; - ulong pos; - - memmode = getreg(MemoryConfReg) & 7; - ilv = interleave[memmode]; - frw = framewidth[memmode][getreg(VideoBufferLayoutControl) & 3]; - - pos = (p.y * (frw/ilv)) + ((p.x/ilv) & panmask[memmode]); - setreg(DisplayViewPortStartAddrA, (uchar) pos); - setreg(DisplayViewPortStartAddrB, (uchar) (pos >> 8)); - setreg(DisplayViewPortStartAddrC, (uchar) (pos >> 16) & 0x03); - updateshadowregs(); -} - -static int -testqfactor(void) -{ - ulong timo; - int reg; - - waitvideoframe(); - for (reg = 0, timo = ~0; timo; timo--) { - reg |= getreg(InputFieldPixelBufStatus); - if (reg & 0xE) break; - } - if (reg & 0xC) return 0; - - waitvideoframe(); - for (reg = 0, timo = ~0; timo; timo--) { - reg |= getreg(InputFieldPixelBufStatus); - if (reg & 0xE) break; - } - return (reg & 0xC) == 0; -} - -static void -newwindow(Rectangle r) -{ - unsigned ww, wh, dx, dy, xs, ys, xe, ye; - unsigned scalex, scaley; - int frwidth, frheight, vidwidth, vidheight; - int memmode, layout; - int width, height; - int filter, changed, val; - - changed = r.min.x != window.min.x || r.min.y != window.min.y || - r.max.x != window.max.x || r.max.y != window.max.y; - if (changed) window = r; - - if (r.min.x < 0) r.min.x = 0; - if (r.max.x > ScreenWidth) r.max.x = ScreenWidth; - if (r.min.y < 0) r.min.y = 0; - if (r.max.y > ScreenHeight) r.max.y = ScreenHeight; - - if ((dx = r.max.x - r.min.x) <= 0) dx = 1; - if ((dy = r.max.y - r.min.y) <= 0) dy = 1; - - wh = dy; - ww = dx = ADJUST(dx); - r.min.x = (r.min.x * hrsmult) / hrsdiv; - - memmode = getreg(MemoryConfReg) & 7; - layout = getreg(VideoBufferLayoutControl) & 3; - vidwidth = cropright - cropleft + 1; - vidheight = (cropbottom & 0x3FE) - (croptop & 0x3FE) + 1; - frwidth = min(framewidth[memmode][layout], vidwidth); - frheight = min(frameheight[memmode][layout], vidheight); - - /* round up scale width to nearest multiple of interleave factor */ - dx = ((ulong)dx * q) / 100; - dx = ilv * ((dx + ilv - 1) / ilv); - - scalex = (((ulong)dx * 1024L) + vidwidth - 2) / (vidwidth - 1); - if (dy > frheight) dy = frheight - 1; - scaley = (((ulong)dy * 1024L) + vidheight - 2) / (vidheight - 1); - - setreg(InputHorzScaleControlA, (scalex << 6) & 0xC0); - setreg(InputHorzScaleControlB, (scalex >> 2) & 0xFF); - setreg(InputVertScaleControlA, (scaley << 6) & 0xC0); - setreg(InputVertScaleControlB, (scaley >> 2) & 0xFF); - - /* turn on horizontal filtering if we are scaling down */ - setreg(InputHorzFilter, horzfilter[((scalex - 1) >> 7) & 7]); - - /* set vertical interpolation */ - filter = scaley > 512 ? (ScreenWidth == 640 ? 0x44 : 0xC5) : 0x46; /* magic */ - if ((getreg(InputVertInterpolControl) & 0x1F) != (filter & 0x1F)) { - setreg(ISAControl, 0x80); - setreg(InputVertInterpolControl, filter & 0x1F); - setreg(ISAControl, 0x42); - } - setreg(AcquisitionControl, ((filter >> 6) ^ 3) | 0x04); - - /* set viewport position and size */ - width = ((ulong)ww * q) / 100; - if (width >= frwidth - ilv) - width = frwidth - ilv; - width = ((width + ilv - 1) / ilv) + 2; - - height = ((ulong)wh * dy + wh - 1) / wh; - if (height >= frheight) - height = frheight - 3; - height += 2; - - xs = r.min.x + XCorrection; - if (xs < 0) xs = 2; - ys = r.min.y + YCorrection; - if (ys < 0) ys = 2; - if (ScreenWidth > 1023) ys |= 1; - - setreg(DisplayViewPortWidthA, width); - setreg(DisplayViewPortWidthB, width >> 8); - setreg(DisplayViewPortHeightA, height); - setreg(DisplayViewPortHeightB, height >> 8); - setreg(DisplayViewPortOrigTopA, ys); - setreg(DisplayViewPortOrigTopB, ys >> 8); - setreg(DisplayViewPortOrigLeftA, xs); - setreg(DisplayViewPortOrigLeftB, xs >> 8); - - xe = r.min.x + ww - 1 + XCorrection; - if (xe < 0) xe = 2; - ye = r.min.y + wh - 1 + YCorrection; - if (ye < 0) ye = 2; - - setreg(DisplayWindowLeftA, xs); - setreg(DisplayWindowLeftB, xs >> 8); - setreg(DisplayWindowRightA, xe); - setreg(DisplayWindowRightB, xe >> 8); - setreg(DisplayWindowTopA, ys); - setreg(DisplayWindowTopB, ys >> 8); - setreg(DisplayWindowBottomA, ye); - setreg(DisplayWindowBottomB, ye >> 8); - - if (dx < ww) { /* horizontal zoom */ - int zoom = ((ulong) (dx - 1) * 2048) / ww; - setreg(OutputProcControlA, getreg(OutputProcControlA) | 6); - setreg(OutputHorzZoomControlA, zoom); - setreg(OutputHorzZoomControlB, zoom >> 8); - } else - setreg(OutputProcControlA, getreg(OutputProcControlA) & 0xF9); - - if (dy < wh) { /* vertical zoom */ - int zoom = ((ulong) (dy - 1) * 2048) / wh; - setreg(OutputProcControlB, getreg(OutputProcControlB) | 1); - setreg(OutputVertZoomControlA, zoom); - setreg(OutputVertZoomControlB, zoom >> 8); - } else - setreg(OutputProcControlB, getreg(OutputProcControlB) & 0xFE); - - setreg(OutputProcControlB, getreg(OutputProcControlB) | 0x20); - updateshadowregs(); - - if (changed) { - setreg(OutputProcControlA, getreg(OutputProcControlA) & 0xDF); - } else { - val = getreg(InputFieldPixelBufStatus); - USED(val); - } - - panwindow(Pt(0, 0)); -} - -static void -createwindow(Rectangle r) -{ - for (q = 100; q >= 30; q -= 10) { - newwindow(r); - if (testqfactor()) - break; - } - enablevideo(); -} - -static void -setcontrols(int index, uchar val) -{ - switch (index) { - case Vxp500Brightness: - setreg(BrightnessControl, (127L * val) / 100); - updateshadowregs(); - break; - case Vxp500Contrast: - setreg(ContrastControl, (15L * val) / 100); - updateshadowregs(); - break; - case Vxp500Saturation: - setreg(SaturationControl, (15L * val) / 100); - updateshadowregs(); - break; - case Bt812Brightness: - setbt812reg(0x08, ((126L * val) / 100) & 0xFE); - break; - case Bt812Contrast: - setbt812reg(0x09, ((254L * val) / 100) & 0xFE); - break; - case Bt812Saturation: - setbt812reg(0x0A, ((254L * val) / 100) & 0xFE); - break; - case Bt812Hue: - setbt812reg(0x0B, ((254L * val) / 100) & 0xFE); - break; - case Bt812BW: - setbt812reg(0x05, (getbt812reg(0x5) & ~2) | ((val << 1) & 2)); - break; - } -} - -static void -enablememwindow(void) -{ - setreg(MemoryWindowBaseAddrB, getreg(MemoryWindowBaseAddrB) | 0x20); -} - -static void -disablememwindow(void) -{ - setreg(MemoryWindowBaseAddrB, getreg(MemoryWindowBaseAddrB) & ~0x20); -} - -volatile static ushort *fb = (ushort *)EISA(MemAddr); -static uchar yuvpadbound[] = { 4, 12, 4, 2, 6 }; - -/* - * Capture a frame in UY0, VY1 format - */ -static void * -saveframe(int *nb) -{ - int memmode, layout, ilv; - int frwidth, frheight; - int bound, n, val, toggle; - unsigned save58, save6C; - int x, y, w, h, width, height; - ulong pos, size; - char *p; - static void *frame = 0; - static ulong framesize = 0; - - width = capwindow.max.x - capwindow.min.x; - height = capwindow.max.y - capwindow.min.y; - - memmode = getreg(MemoryConfReg) & 7; - if (memmode <= 2) { - print("devtv: cannot handle YUV411\n"); - error(Egreg); /* actually, Eleendert */ - } - layout = getreg(VideoBufferLayoutControl) & 3; - ilv = interleave[memmode]; - frwidth = framewidth[memmode][layout]; - frheight = frameheight[memmode][layout]; - - pos = getreg(AcquisitionAddrA) + - (getreg(AcquisitionAddrB) << 8) + (getreg(AcquisitionAddrC) & 3) << 16; - - x = capwindow.min.x + (pos % frwidth); - y = capwindow.min.y + (pos / frwidth); - if (x > frwidth || y > frheight) - return 0; - if (x + width > frwidth) - width = frwidth - x; - if (y + height > frheight) - height = frheight - y; - - pos = y * (frwidth / ilv) + (x / ilv); - - /* compute padding for each scan line */ - bound = yuvpadbound[memmode]; - switch (bound) { - case 2: - width = (width + 1) & ~1; - break; - case 4: - width = (width + 3) & ~3; - break; - default: - width = (width + (bound - 1)) / bound; - break; - } - - size = width * height * sizeof(ushort); - if (size != framesize) { - framesize = 0; - if (frame) - free(frame); - frame = malloc(size + 256); - } - if (frame == 0) - return 0; - - memset(frame, 0, size + 256); - - framesize = size; - p = (char *) frame + snprint(frame, 256, - "TYPE=ccir601\nWINDOW=%d %d %d %d\n\n", - capwindow.min.x, capwindow.min.y, - capwindow.min.x+width, capwindow.min.y+height); - - freeze(1); - - save58 = getreg(InputVertInterpolControl); - save6C = getreg(AcquisitionControl); - - waitforretrace(); - setreg(ISAControl, 0xC0); /* global reset */ - setreg(InputVertInterpolControl, 0x0D); - setreg(AcquisitionControl, 0x04); - setreg(CaptureControl, 0x80); /* set capture mode */ - setreg(VideoInputFrameBufDepthA, 0xFF); - setreg(VideoInputFrameBufDepthB, 0x03); - setreg(InputVideoConfA, getreg(InputVideoConfA) | 0x40); - setreg(ISAControl, 0x44); /* tight decode, global reset off */ - - setreg(CaptureViewPortAddrA, (int) pos & 0xFF); - setreg(CaptureViewPortAddrB, (int) (pos >> 8) & 0xFF); - setreg(CaptureViewPortAddrC, (int) (pos >> 16) & 0x03); - n = (width / ilv) - 1; - setreg(CaptureViewPortWidthA, n & 0xFF); - setreg(CaptureViewPortWidthB, n >> 8); - setreg(CaptureViewPortHeightA, (height-1) & 0xFF); - setreg(CaptureViewPortHeightB, (height-1) >> 8); - setreg(CapturePixelBufLow, 0x04); /* pix buffer low */ - setreg(CapturePixelBufHigh, 0x0E); /* pix buffer high */ - setreg(CaptureMultiBufDepthA, 0xFF); /* multi buffer depth maximum */ - setreg(CaptureMultiBufDepthB, 0x03); - updateshadowregs(); - - setreg(CaptureControl, 0x90); /* capture reset */ - val = getreg(InputFieldPixelBufStatus); /* clear read status */ - USED(val); - - toggle = !(getreg(OutputProcControlA) & 0x01) ? 0x8000 : 0x0000; - setreg(CaptureControl, 0xC0); /* capture enable, active */ - - while ((getreg(InputFieldPixelBufStatus) & 0x10) == 0) - /* wait for capture FIFO to become ready */; - - enablememwindow(); - for (h = height; h > 0; h--) { - for (w = width; w > 0; w -= 2) { - ushort uy0 = swab16(fb[0]) ^ toggle; - ushort vy1 = swab16(fb[1]) ^ toggle; - /* unfortunately p may not be properly aligned */ - *p++ = uy0 >> 8; - *p++ = uy0; - *p++ = vy1 >> 8; - *p++ = vy1; - } - } - disablememwindow(); - - waitforretrace(); - setreg(ISAControl, 0xC0); /* global reset */ - setreg(CaptureControl, 0); /* clear capture mode */ - setreg(InputVertInterpolControl, save58); - setreg(AcquisitionControl, save6C); - setreg(InputVideoConfA, getreg(InputVideoConfA) | 0x40); - setreg(ISAControl, 0x40); /* clear global reset */ - updateshadowregs(); - - freeze(0); - - *nb = p - (char *) frame; - return frame; -} diff --git a/os/pc/devusb.c b/os/pc/devusb.c deleted file mode 100644 index 56a3442a..00000000 --- a/os/pc/devusb.c +++ /dev/null @@ -1,951 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#include "usb.h" - -static int debug = 0; - -#define Chatty 1 -#define DPRINT if(Chatty)print -#define XPRINT if(debug)iprint - -Usbhost* usbhost[MaxUsb]; - -static char *devstates[] = { - [Disabled] "Disabled", - [Attached] "Attached", - [Enabled] "Enabled", - [Assigned] "Assigned", - [Configured] "Configured", -}; - -static char Ebadusbmsg[] = "invalid parameters to USB ctl message"; - -enum -{ - Qtopdir = 0, - Q2nd, - Qnew, - Qport, - Q3rd, - Qctl, - Qstatus, - Qep0, - /* other endpoint files */ -}; - -/* - * Qid path is: - * 8 bits of file type (qids above) - * 8 bits of slot number; default address 0 used for per-controller files - * 4 bits of controller number - */ -enum { - TYPEBITS = 8, - SLOTBITS = 8, - CTLRBITS = 4, - - SLOTSHIFT = TYPEBITS, - CTLRSHIFT = SLOTSHIFT+SLOTBITS, - - TYPEMASK = (1<>SLOTSHIFT)&SLOTMASK) -#define CTLR(q) ((((ulong)(q).path)>>CTLRSHIFT)&CTLRMASK) -#define PATH(t, s, c) ((t)|((s)< nelem(uh->dev)) - return nil; - return uh->dev[s]; -} - -static Udev* -usbdevice(Chan *c) -{ - int bus; - Udev *d; - Usbhost *uh; - - bus = CTLR(c->qid); - if(bus > nelem(usbhost) || (uh = usbhost[bus]) == nil) { - error(Egreg); - return nil; /* for compiler */ - } - d = usbdeviceofslot(uh, SLOT(c->qid)); - if(d == nil || d->id != c->qid.vers || d->state == Disabled) - error(Ehungup); - return d; -} - -static Endpt * -devendpt(Udev *d, int id, int add) -{ - Usbhost *uh; - Endpt *e, **p; - - p = &d->ep[id&0xF]; - lock(d); - e = *p; - if(e != nil){ - incref(e); - XPRINT("incref(0x%p) in devendpt, new value %ld\n", e, e->ref); - unlock(d); - return e; - } - unlock(d); - if(!add) - return nil; - - e = mallocz(sizeof(*e), 1); - e->ref = 1; - e->x = id&0xF; - e->id = id; - e->sched = -1; - e->maxpkt = 8; - e->nbuf = 1; - e->dev = d; - e->active = 0; - - uh = d->uh; - uh->epalloc(uh, e); - - lock(d); - if(*p != nil){ - incref(*p); - XPRINT("incref(0x%p) in devendpt, new value %ld\n", *p, (*p)->ref); - unlock(d); - uh->epfree(uh, e); - free(e); - return *p; - } - *p = e; - unlock(d); - e->rq = qopen(8*1024, 0, nil, e); - e->wq = qopen(8*1024, 0, nil, e); - return e; -} - -static void -freept(Endpt *e) -{ - Usbhost *uh; - - if(e != nil && decref(e) == 0){ - XPRINT("freept(%d,%d)\n", e->dev->x, e->x); - uh = e->dev->uh; - uh->epclose(uh, e); - e->dev->ep[e->x] = nil; - uh->epfree(uh, e); - free(e); - } -} - -static Udev* -usbnewdevice(Usbhost *uh) -{ - int i; - Udev *d; - Endpt *e; - - d = nil; - qlock(uh); - if(waserror()){ - qunlock(uh); - nexterror(); - } - for(i=0; idev); i++) - if(uh->dev[i] == nil){ - uh->idgen++; - d = mallocz(sizeof(*d), 1); - d->uh = uh; - d->ref = 1; - d->x = i; - d->id = (uh->idgen << 8) | i; - d->state = Enabled; - XPRINT("calling devendpt in usbnewdevice\n"); - e = devendpt(d, 0, 1); /* always provide control endpoint 0 */ - e->mode = ORDWR; - e->iso = 0; - e->sched = -1; - uh->dev[i] = d; - break; - } - poperror(); - qunlock(uh); - return d; -} - -static void -freedev(Udev *d, int ept) -{ - int i; - Endpt *e; - Usbhost *uh; - - uh = d->uh; - if(decref(d) == 0){ - XPRINT("freedev 0x%p, 0\n", d); - for(i=0; iep); i++) - freept(d->ep[i]); - if(d->x >= 0) - uh->dev[d->x] = nil; - free(d); - } else { - if(ept >= 0 && ept < nelem(d->ep)){ - e = d->ep[ept]; - XPRINT("freedev, freept 0x%p\n", e); - if(e != nil) - uh->epclose(uh, e); - } - } -} - -static int -usbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp) -{ - Qid q; - Udev *d; - Endpt *e; - Dirtab *tab; - Usbhost *uh; - int t, bus, slot, perm; - - /* - * Top level directory contains the controller names. - */ - if(c->qid.path == Qtopdir){ - if(s == DEVDOTDOT){ - mkqid(&q, Qtopdir, 0, QTDIR); - devdir(c, q, "#U", 0, eve, 0555, dp); - return 1; - } - if(s >= nelem(usbhost) || usbhost[s] == nil) - return -1; - mkqid(&q, PATH(Q2nd, 0, s), 0, QTDIR); - snprint(up->genbuf, sizeof up->genbuf, "usb%d", s); - devdir(c, q, up->genbuf, 0, eve, 0555, dp); - return 1; - } - bus = CTLR(c->qid); - if(bus >= nelem(usbhost) || (uh = usbhost[bus]) == nil) - return -1; - - /* - * Second level contains "new", "port", and a numbered - * directory for each enumerated device on the bus. - */ - t = TYPE(c->qid); - if(t < Q3rd){ - if(s == DEVDOTDOT){ - mkqid(&q, Qtopdir, 0, QTDIR); - devdir(c, q, "#U", 0, eve, 0555, dp); - return 1; - } - if(s < nelem(usbdir2)){ - d = uh->dev[0]; - if(d == nil) - return -1; - tab = &usbdir2[s]; - mkqid(&q, PATH(tab->qid.path, 0, bus), d->id, QTFILE); - devdir(c, q, tab->name, tab->length, eve, tab->perm, dp); - return 1; - } - s -= nelem(usbdir2); - if(s >= 0 && s < nelem(uh->dev)) { - d = uh->dev[s]; - if(d == nil) - return 0; - sprint(up->genbuf, "%d", s); - mkqid(&q, PATH(Q3rd, s, bus), d->id, QTDIR); - devdir(c, q, up->genbuf, 0, eve, 0555, dp); - return 1; - } - return -1; - } - - /* - * Third level. - */ - slot = SLOT(c->qid); - if(s == DEVDOTDOT) { - mkqid(&q, PATH(Q2nd, 0, bus), c->qid.vers, QTDIR); - snprint(up->genbuf, sizeof up->genbuf, "usb%d", bus); - devdir(c, q, up->genbuf, 0, eve, 0555, dp); - return 1; - } - if(s < nelem(usbdir3)) { - tab = &usbdir3[s]; - mkqid(&q, PATH(tab->qid.path, slot, bus), c->qid.vers, QTFILE); - devdir(c, q, tab->name, tab->length, eve, tab->perm, dp); - return 1; - } - s -= nelem(usbdir3); - - /* active endpoints */ - d = usbdeviceofslot(uh, slot); - if(d == nil || s >= nelem(d->ep)) - return -1; - if(s == 0 || (e = d->ep[s]) == nil) /* ep0data is called "setup" */ - return 0; - sprint(up->genbuf, "ep%ddata", s); - mkqid(&q, PATH(Qep0+s, slot, bus), c->qid.vers, QTFILE); - switch(e->mode) { - case OREAD: - perm = 0444; - break; - case OWRITE: - perm = 0222; - break; - default: - perm = 0666; - break; - } - devdir(c, q, up->genbuf, e->buffered, eve, perm, dp); - return 1; -} - -static Usbhost* -usbprobe(int cardno, int ctlrno) -{ - Usbhost *uh; - char buf[128], *ebuf, name[64], *p, *type; - - uh = malloc(sizeof(Usbhost)); - memset(uh, 0, sizeof(Usbhost)); - uh->tbdf = BUSUNKNOWN; - - if(cardno < 0){ - if(isaconfig("usb", ctlrno, uh) == 0){ - free(uh); - return nil; - } - for(cardno = 0; usbtypes[cardno].type; cardno++){ - type = uh->type; - if(type==nil || *type==0) - type = "uhci"; - if(cistrcmp(usbtypes[cardno].type, type)) - continue; - break; - } - } - - if(cardno >= MaxUsb || usbtypes[cardno].type == nil){ - free(uh); - return nil; - } - if(usbtypes[cardno].reset(uh) < 0){ - free(uh); - return nil; - } - - /* - * IRQ2 doesn't really exist, it's used to gang the interrupt - * controllers together. A device set to IRQ2 will appear on - * the second interrupt controller as IRQ9. - */ - if(uh->irq == 2) - uh->irq = 9; - snprint(name, sizeof(name), "usb%d", ctlrno); - intrenable(uh->irq, uh->interrupt, uh, uh->tbdf, name); - - ebuf = buf + sizeof buf; - p = seprint(buf, ebuf, "#U/usb%d: %s: port 0x%luX irq %d", ctlrno, usbtypes[cardno].type, uh->port, uh->irq); - if(uh->mem) - p = seprint(p, ebuf, " addr 0x%luX", PADDR(uh->mem)); - if(uh->size) - seprint(p, ebuf, " size 0x%luX", uh->size); - print("%s\n", buf); - - return uh; -} - -static void -usbreset(void) -{ - int cardno, ctlrno; - Usbhost *uh; - - for(ctlrno = 0; ctlrno < MaxUsb; ctlrno++){ - if((uh = usbprobe(-1, ctlrno)) == nil) - continue; - usbhost[ctlrno] = uh; - } - - if(getconf("*nousbprobe")) - return; - - cardno = ctlrno = 0; - while(usbtypes[cardno].type != nil && ctlrno < MaxUsb){ - if(usbhost[ctlrno] != nil){ - ctlrno++; - continue; - } - if((uh = usbprobe(cardno, ctlrno)) == nil){ - cardno++; - continue; - } - usbhost[ctlrno] = uh; - ctlrno++; - } -} - -void -usbinit(void) -{ - Udev *d; - int ctlrno; - Usbhost *uh; - - for(ctlrno = 0; ctlrno < MaxUsb; ctlrno++){ - uh = usbhost[ctlrno]; - if(uh == nil) - continue; - if(uh->init != 0) - uh->init(uh); - - /* reserve device for configuration */ - d = usbnewdevice(uh); - incref(d); - d->state = Attached; - } -} - -Chan * -usbattach(char *spec) -{ - return devattach('U', spec); -} - -static Walkqid* -usbwalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, nil, 0, usbgen); -} - -static int -usbstat(Chan *c, uchar *db, int n) -{ - return devstat(c, db, n, nil, 0, usbgen); -} - -Chan* -usbopen(Chan *c, int omode) -{ - Udev *d; - Endpt *e; - int f, s, type; - Usbhost *uh; - - if(c->qid.type == QTDIR) - return devopen(c, omode, nil, 0, usbgen); - - f = 0; - type = TYPE(c->qid); - if(type == Qnew){ - d = usbdevice(c); - d = usbnewdevice(d->uh); - XPRINT("usbopen, new dev 0x%p\n", d); - if(d == nil) { - XPRINT("usbopen failed (usbnewdevice)\n"); - error(Enodev); - } - type = Qctl; - mkqid(&c->qid, PATH(type, d->x, CTLR(c->qid)), d->id, QTFILE); - f = 1; - } - - if(type < Q3rd){ - XPRINT("usbopen, devopen < Q3rd\n"); - return devopen(c, omode, nil, 0, usbgen); - } - - d = usbdevice(c); - uh = d->uh; - qlock(uh); - if(waserror()){ - qunlock(uh); - nexterror(); - } - - switch(type){ - case Qctl: - if(0&&d->busy) - error(Einuse); - d->busy = 1; - if(!f) - incref(d); - XPRINT("usbopen, Qctl 0x%p\n", d); - break; - - default: - s = type - Qep0; - XPRINT("usbopen, default 0x%p, %d\n", d, s); - if(s >= 0 && s < nelem(d->ep)){ - if((e = d->ep[s]) == nil) { - XPRINT("usbopen failed (endpoint)\n"); - error(Enodev); - } - XPRINT("usbopen: dev 0x%p, ept 0x%p\n", d, e); - uh->epopen(uh, e); - e->foffset = 0; - e->toffset = 0; - e->poffset = 0; - e->buffered = 0; - } - incref(d); - break; - } - poperror(); - qunlock(uh); - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - return c; -} - -void -usbclose(Chan *c) -{ - Udev *d; - int ept, type; - Usbhost *uh; - - type = TYPE(c->qid); - if(c->qid.type == QTDIR || type < Q3rd) - return; - d = usbdevice(c); - uh = d->uh; - qlock(uh); - if(waserror()){ - qunlock(uh); - nexterror(); - } - if(type == Qctl) - d->busy = 0; - XPRINT("usbclose: dev 0x%p\n", d); - if(c->flag & COPEN){ - ept = (type != Qctl) ? type - Qep0 : -1; - XPRINT("usbclose: freedev 0x%p\n", d); - freedev(d, ept); - } - poperror(); - qunlock(uh); -} - -static char * -epstatus(char *s, char *se, Endpt *e, int i) -{ - char *p; - - p = seprint(s, se, "%2d %#6.6lux %10lud bytes %10lud blocks\n", i, e->csp, e->nbytes, e->nblocks); - if(e->iso){ - p = seprint(p, se, "bufsize %6d buffered %6d", e->maxpkt, e->buffered); - if(e->toffset) - p = seprint(p, se, " offset %10lud time %19lld\n", e->toffset, e->time); - p = seprint(p, se, "\n"); - } - return p; -} - -long -usbread(Chan *c, void *a, long n, vlong offset) -{ - int t, i; - Udev *d; - Endpt *e; - Usbhost *uh; - char *s, *se, *p; - - if(c->qid.type == QTDIR) - return devdirread(c, a, n, nil, 0, usbgen); - - d = usbdevice(c); - uh = d->uh; - t = TYPE(c->qid); - - if(t >= Qep0) { - t -= Qep0; - if(t >= nelem(d->ep)) - error(Eio); - e = d->ep[t]; - if(e == nil || e->mode == OWRITE) - error(Egreg); - if(t == 0) { - if(e->iso) - error(Egreg); - e->data01 = 1; - n = uh->read(uh, e, a, n, 0LL); - if(e->setin){ - e->setin = 0; - e->data01 = 1; - uh->write(uh, e, "", 0, 0LL, TokOUT); - } - return n; - } - return uh->read(uh, e, a, n, offset); - } - - s = smalloc(READSTR); - se = s+READSTR; - if(waserror()){ - free(s); - nexterror(); - } - switch(t){ - case Qport: - uh->portinfo(uh, s, se); - break; - - case Qctl: - seprint(s, se, "%11d %11d\n", d->x, d->id); - break; - - case Qstatus: - if (d->did || d->vid) - p = seprint(s, se, "%s %#6.6lux %#4.4ux %#4.4ux\n", devstates[d->state], d->csp, d->vid, d->did); - else - p = seprint(s, se, "%s %#6.6lux\n", devstates[d->state], d->csp); - for(i=0; iep); i++) { - e = d->ep[i]; - if(e == nil) - continue; - /* TO DO: freeze e */ - p = epstatus(p, se, e, i); - } - } - n = readstr(offset, a, n, s); - poperror(); - free(s); - return n; -} - -long -usbwrite(Chan *c, void *a, long n, vlong offset) -{ - Udev *d; - Endpt *e; - Cmdtab *ct; - Cmdbuf *cb; - Usbhost *uh; - int id, nw, t, i; - char cmd[50]; - - if(c->qid.type == QTDIR) - error(Egreg); - d = usbdevice(c); - uh = d->uh; - t = TYPE(c->qid); - switch(t){ - case Qport: - cb = parsecmd(a, n); - if(waserror()){ - free(cb); - nexterror(); - } - - ct = lookupcmd(cb, usbportmsg, nelem(usbportmsg)); - id = strtol(cb->f[1], nil, 0); - switch(ct->index){ - case PMdisable: - uh->portenable(uh, id, 0); - break; - case PMenable: - uh->portenable(uh, id, 1); - break; - case PMreset: - uh->portreset(uh, id); - break; - } - - poperror(); - free(cb); - return n; - case Qctl: - cb = parsecmd(a, n); - if(waserror()){ - free(cb); - nexterror(); - } - - ct = lookupcmd(cb, usbctlmsg, nelem(usbctlmsg)); - switch(ct->index){ - case CMspeed: - d->ls = strtoul(cb->f[1], nil, 0) == 0; - break; - case CMclass: - if (cb->nf != 4 && cb->nf != 6) - cmderror(cb, Ebadusbmsg); - /* class #ifc ept csp ( == class subclass proto) [vendor product] */ - d->npt = strtoul(cb->f[1], nil, 0); /* # of interfaces */ - i = strtoul(cb->f[2], nil, 0); /* endpoint */ - if (i < 0 || i >= nelem(d->ep) - || d->npt > nelem(d->ep) || i >= d->npt) - cmderror(cb, Ebadusbmsg); - if (cb->nf == 6) { - d->vid = strtoul(cb->f[4], nil, 0); - d->did = strtoul(cb->f[5], nil, 0); - } - if (i == 0) - d->csp = strtoul(cb->f[3], nil, 0); - if(d->ep[i] == nil){ - XPRINT("calling devendpt in usbwrite (CMclass)\n"); - d->ep[i] = devendpt(d, i, 1); - } - d->ep[i]->csp = strtoul(cb->f[3], nil, 0); - break; - case CMdata: - i = strtoul(cb->f[1], nil, 0); - if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadusbmsg); - e = d->ep[i]; - e->data01 = strtoul(cb->f[2], nil, 0) != 0; - break; - case CMmaxpkt: - i = strtoul(cb->f[1], nil, 0); - if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadusbmsg); - e = d->ep[i]; - e->maxpkt = strtoul(cb->f[2], nil, 0); - if(e->maxpkt > 1500) - e->maxpkt = 1500; - break; - case CMadjust: - i = strtoul(cb->f[1], nil, 0); - if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadusbmsg); - e = d->ep[i]; - if (e->iso == 0) - error(Eperm); - i = strtoul(cb->f[2], nil, 0); - /* speed may not result in change of maxpkt */ - if (i < (e->maxpkt-1)/e->samplesz * 1000/e->pollms - || i > e->maxpkt/e->samplesz * 1000/e->pollms){ - snprint(cmd, sizeof(cmd), "%d < %d < %d?", - (e->maxpkt-1)/e->samplesz * 1000/e->pollms, - i, - e->maxpkt/e->samplesz * 1000/e->pollms); - error(cmd); - } - e->hz = i; - break; - case CMdebug: - i = strtoul(cb->f[1], nil, 0); - if(i < -1 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadusbmsg); - if (i == -1) - debug = 0; - else { - debug = 1; - e = d->ep[i]; - e->debug = strtoul(cb->f[2], nil, 0); - } - break; - case CMunstall: - i = strtoul(cb->f[1], nil, 0); - if(i < 0 || i >= nelem(d->ep) || d->ep[i] == nil) - error(Ebadusbmsg); - e = d->ep[i]; - e->err = nil; - break; - case CMep: - /* ep n `bulk' mode maxpkt nbuf OR - * ep n period mode samplesize Hz - */ - i = strtoul(cb->f[1], nil, 0); - if(i < 0 || i >= nelem(d->ep)) { - XPRINT("field 1: 0 <= %d < %d\n", i, nelem(d->ep)); - error(Ebadarg); - } - if((e = d->ep[i]) == nil){ - XPRINT("calling devendpt in usbwrite (CMep)\n"); - e = devendpt(d, i, 1); - } - qlock(uh); - if(waserror()){ - freept(e); - qunlock(uh); - nexterror(); - } - if(e->active) - error(Eperm); - if(strcmp(cb->f[2], "bulk") == 0){ - /* ep n `bulk' mode maxpkt nbuf */ - e->iso = 0; - i = strtoul(cb->f[4], nil, 0); - if(i < 8 || i > 1023) - i = 8; - e->maxpkt = i; - i = strtoul(cb->f[5], nil, 0); - if(i >= 1 && i <= 32) - e->nbuf = i; - } else { - /* ep n period mode samplesize Hz */ - i = strtoul(cb->f[2], nil, 0); - if(i > 0 && i <= 1000){ - e->pollms = i; - }else { - XPRINT("field 4: 0 <= %d <= 1000\n", i); - error(Ebadarg); - } - i = strtoul(cb->f[4], nil, 0); - if(i >= 1 && i <= 8){ - e->samplesz = i; - }else { - XPRINT("field 4: 0 < %d <= 8\n", i); - error(Ebadarg); - } - i = strtoul(cb->f[5], nil, 0); - if(i >= 1 && i*e->samplesz <= 12*1000*1000){ - /* Hz */ - e->hz = i; - e->remain = 0; - }else { - XPRINT("field 5: 1 < %d <= 100000 Hz\n", i); - error(Ebadarg); - } - e->maxpkt = (e->hz * e->pollms + 999)/1000 * e->samplesz; - e->iso = 1; - } - e->mode = strcmp(cb->f[3],"r") == 0? OREAD : - strcmp(cb->f[3],"w") == 0? OWRITE : ORDWR; - uh->epmode(uh, e); - poperror(); - qunlock(uh); - } - - poperror(); - free(cb); - return n; - - case Qep0: /* SETUP endpoint 0 */ - /* should canqlock etc */ - e = d->ep[0]; - if(e == nil || e->iso) - error(Egreg); - if(n < 8) - error(Eio); - nw = *(uchar*)a & RD2H; - e->data01 = 0; - n = uh->write(uh, e, a, n, 0LL, TokSETUP); - if(nw == 0) { /* host to device: use IN[DATA1] to ack */ - e->data01 = 1; - nw = uh->read(uh, e, cmd, 0LL, 8); - if(nw != 0) - error(Eio); /* could provide more status */ - }else - e->setin = 1; /* two-phase */ - break; - - default: /* sends DATA[01] */ - t -= Qep0; - if(t < 0 || t >= nelem(d->ep)) - error(Egreg); - e = d->ep[t]; - if(e == nil || e->mode == OREAD) - error(Egreg); - n = uh->write(uh, e, a, n, offset, TokOUT); - break; - } - return n; -} - -Dev usbdevtab = { - 'U', - "usb", - - usbreset, - usbinit, - devshutdown, - usbattach, - usbwalk, - usbstat, - usbopen, - devcreate, - usbclose, - usbread, - devbread, - usbwrite, - devbwrite, - devremove, - devwstat, -}; diff --git a/os/pc/devvga.c b/os/pc/devvga.c deleted file mode 100644 index 0d7a9f0d..00000000 --- a/os/pc/devvga.c +++ /dev/null @@ -1,620 +0,0 @@ -/* - * VGA controller - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -typedef struct Vgaseg Vgaseg; -struct Vgaseg { - QLock; - ulong pa; - ulong len; - void* va; -}; - -enum { - Nvgaseg = 4, - - Qdir = 0, - Qvgactl, - Qvgaovl, - Qvgaovlctl, - - Qsegs, - Qmax = Qsegs+Nvgaseg -}; - -static Dirtab vgadir[Qmax] = { - ".", { Qdir, 0, QTDIR }, 0, 0550, - "vgactl", { Qvgactl, 0 }, 0, 0660, - "vgaovl", { Qvgaovl, 0 }, 0, 0660, - "vgaovlctl", { Qvgaovlctl, 0 }, 0, 0660, - /* dynamically-created memory segments are added here */ -}; - -static Vgaseg vgasegs[Nvgaseg]; -static Lock vgadirlock; -static int nvgadir = Qsegs; - -enum { - CMactualsize, - CMblank, - CMblanktime, - CMdrawinit, - CMhwaccel, - CMhwblank, - CMhwgc, - CMlinear, - CMpalettedepth, - CMpanning, - CMsize, - CMtype, - CMunblank, -}; - -static Cmdtab vgactlmsg[] = { - CMactualsize, "actualsize", 2, - CMblank, "blank", 1, - CMblanktime, "blanktime", 2, - CMdrawinit, "drawinit", 1, - CMhwaccel, "hwaccel", 2, - CMhwblank, "hwblank", 2, - CMhwgc, "hwgc", 2, - CMlinear, "linear", 0, - CMpalettedepth, "palettedepth", 2, - CMpanning, "panning", 2, - CMsize, "size", 3, - CMtype, "type", 2, - CMunblank, "unblank", 1, -}; - -static void -vgareset(void) -{ - /* reserve the 'standard' vga registers */ - if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0) - panic("vga ports already allocated"); - if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0) - panic("vga ports already allocated"); - conf.monitor = 1; -} - -void -addvgaseg(char *name, ulong pa, ulong size) -{ - int i; - Dirtab d; - Vgaseg *s; - ulong va; - - va = mmukmap(pa, 0, size); - if(va == 0) - return; - memset(&d, 0, sizeof(d)); - strecpy(d.name, d.name+sizeof(name), name); - lock(&vgadirlock); - for(i=0; i= nelem(vgadir)){ - unlock(&vgadirlock); - print("devvga: segment %s: too many segments\n", name); - return; - } - d.qid.path = nvgadir; - d.perm = 0660; - d.length = size; - s = &vgasegs[nvgadir-Qsegs]; - s->pa = pa; - s->len = size; - s->va = (void*)va; - vgadir[nvgadir] = d; - nvgadir++; - unlock(&vgadirlock); -} - -static long -vgasegrd(Vgaseg *s, uchar *buf, long n, ulong offset) -{ - int i; - uchar *a, *d; - ulong v; - - if(offset >= s->len) - return 0; - if(offset+n > s->len) - n = s->len - offset; - d = (uchar*)s->va + offset; - qlock(s); - if(waserror()){ - qunlock(s); - nexterror(); - } - a = buf; - while(n > 0){ - i = 4 - ((ulong)d & 3); - if(i > n) - i = n; - if(i == 3) - i = 2; - switch(i){ - case 4: - v = (a[3]<<24) | (a[2]<<16) | (a[1]<<8) | a[0]; - *(ulong*)d = v; - break; - case 2: - v = (a[1]<<8) | a[0]; - *(ushort*)d = v; - break; - case 1: - *d = *a; - break; - } - d += i; - a += i; - n -= i; - } - poperror(); - qunlock(s); - return a-buf; -} - -static long -vgasegwr(Vgaseg *s, uchar *buf, long n, ulong offset) -{ - int i; - uchar *a, *r; - ulong v; - - if(offset >= s->len) - return 0; - if(offset+n > s->len) - n = s->len - offset; - r = (uchar*)s->va + offset; - qlock(s); - if(waserror()){ - qunlock(s); - nexterror(); - } - a = buf; - while(n > 0){ - i = 4 - ((ulong)r & 3); - if(i > n) - i = n; - if(i == 3) - i = 2; - switch(i){ - case 4: - v = *(ulong*)r; - a[0] = v; - a[1] = v>>8; - a[2] = v>>16; - a[3] = v>>24; - break; - case 2: - v = *(ushort*)r; - a[0] = v; - a[1] = v>>8; - break; - case 1: - *a = *r; - break; - } - r += i; - a += i; - n -= i; - } - poperror(); - qunlock(s); - return a-buf; -} - -static Chan* -vgaattach(char* spec) -{ - if(*spec && strcmp(spec, "0")) - error(Eio); - return devattach('v', spec); -} - -Walkqid* -vgawalk(Chan* c, Chan *nc, char** name, int nname) -{ - return devwalk(c, nc, name, nname, vgadir, nvgadir, devgen); -} - -static int -vgastat(Chan* c, uchar* dp, int n) -{ - return devstat(c, dp, n, vgadir, nvgadir, devgen); -} - -static Chan* -vgaopen(Chan* c, int omode) -{ - VGAscr *scr; - static char *openctl = "openctl\n"; - - scr = &vgascreen[0]; - if ((ulong)c->qid.path == Qvgaovlctl) { - if (scr->dev && scr->dev->ovlctl) - scr->dev->ovlctl(scr, c, openctl, strlen(openctl)); - else - error(Enonexist); - } - return devopen(c, omode, vgadir, nvgadir, devgen); -} - -static void -vgaclose(Chan* c) -{ - VGAscr *scr; - static char *closectl = "closectl\n"; - - scr = &vgascreen[0]; - if((ulong)c->qid.path == Qvgaovlctl) - if(scr->dev && scr->dev->ovlctl){ - if(waserror()){ - print("ovlctl error: %s\n", up->env->errstr); - return; - } - scr->dev->ovlctl(scr, c, closectl, strlen(closectl)); - poperror(); - } -} - -static void -checkport(int start, int end) -{ - /* standard vga regs are OK */ - if(start >= 0x2b0 && end <= 0x2df+1) - return; - if(start >= 0x3c0 && end <= 0x3da+1) - return; - - if(iounused(start, end)) - return; - error(Eperm); -} - -static long -vgaread(Chan* c, void* a, long n, vlong off) -{ - int len; - char *p, *s; - VGAscr *scr; - ulong offset = off; - char chbuf[30]; - - switch((ulong)c->qid.path){ - - case Qdir: - return devdirread(c, a, n, vgadir, nvgadir, devgen); - - case Qvgactl: - scr = &vgascreen[0]; - - p = malloc(READSTR); - if(waserror()){ - free(p); - nexterror(); - } - - len = 0; - - if(scr->dev) - s = scr->dev->name; - else - s = "cga"; - len += snprint(p+len, READSTR-len, "type %s\n", s); - - if(scr->gscreen) { - len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n", - scr->gscreen->r.max.x, scr->gscreen->r.max.y, - scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan)); - - if(Dx(scr->gscreen->r) != Dx(physgscreenr) - || Dy(scr->gscreen->r) != Dy(physgscreenr)) - len += snprint(p+len, READSTR-len, "actualsize %dx%d\n", - physgscreenr.max.x, physgscreenr.max.y); - } - - len += snprint(p+len, READSTR-len, "blank time %lud idle %d state %s\n", - blanktime, drawidletime(), scr->isblank ? "off" : "on"); - len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off"); - len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off"); - len += snprint(p+len, READSTR-len, "panning %s\n", panning ? "on" : "off"); - snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->aperture); - n = readstr(offset, a, n, p); - poperror(); - free(p); - - return n; - - case Qvgaovl: - case Qvgaovlctl: - error(Ebadusefd); - break; - - default: - if(c->qid.path < nvgadir) - return vgasegrd(&vgasegs[c->qid.path], a, n, offset); - error(Egreg); - break; - } - - return 0; -} - -static char Ebusy[] = "vga already configured"; - -static void -vgactl(Cmdbuf *cb) -{ - int align, i, size, x, y, z; - char *chanstr, *p; - ulong chan; - Cmdtab *ct; - VGAscr *scr; - extern VGAdev *vgadev[]; - extern VGAcur *vgacur[]; - - scr = &vgascreen[0]; - ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg)); - switch(ct->index){ - case CMhwgc: - if(strcmp(cb->f[1], "off") == 0){ - lock(&cursor); - if(scr->cur){ - if(scr->cur->disable) - scr->cur->disable(scr); - scr->cur = nil; - } - unlock(&cursor); - return; - } - - for(i = 0; vgacur[i]; i++){ - if(strcmp(cb->f[1], vgacur[i]->name)) - continue; - lock(&cursor); - if(scr->cur && scr->cur->disable) - scr->cur->disable(scr); - scr->cur = vgacur[i]; - if(scr->cur->enable) - scr->cur->enable(scr); - unlock(&cursor); - return; - } - break; - - case CMtype: - for(i = 0; vgadev[i]; i++){ - if(strcmp(cb->f[1], vgadev[i]->name)) - continue; - if(scr->dev && scr->dev->disable) - scr->dev->disable(scr); - scr->dev = vgadev[i]; - if(scr->dev->enable) - scr->dev->enable(scr); - return; - } - break; - - case CMsize: - if(drawhasclients()) - error(Ebusy); - - x = strtoul(cb->f[1], &p, 0); - if(x == 0 || x > 2048) - error(Ebadarg); - if(*p) - p++; - - y = strtoul(p, &p, 0); - if(y == 0 || y > 2048) - error(Ebadarg); - if(*p) - p++; - - z = strtoul(p, &p, 0); - - chanstr = cb->f[2]; - if((chan = strtochan(chanstr)) == 0) - error("bad channel"); - - if(chantodepth(chan) != z) - error("depth, channel do not match"); - - cursoroff(1); - deletescreenimage(); - if(screensize(x, y, z, chan)) - error(Egreg); - vgascreenwin(scr); - cursoron(1); - return; - - case CMactualsize: - if(scr->gscreen == nil) - error("set the screen size first"); - - x = strtoul(cb->f[1], &p, 0); - if(x == 0 || x > 2048) - error(Ebadarg); - if(*p) - p++; - - y = strtoul(p, nil, 0); - if(y == 0 || y > 2048) - error(Ebadarg); - - if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y) - error("physical screen bigger than virtual"); - - physgscreenr = Rect(0,0,x,y); - scr->gscreen->clipr = physgscreenr; - return; - - case CMpalettedepth: - x = strtoul(cb->f[1], &p, 0); - if(x != 8 && x != 6) - error(Ebadarg); - - scr->palettedepth = x; - return; - - case CMdrawinit: - memimagedraw(scr->gscreen, scr->gscreen->r, memblack, ZP, nil, ZP, S); - if(scr && scr->dev && scr->dev->drawinit) - scr->dev->drawinit(scr); - return; - - case CMlinear: - if(cb->nf!=2 && cb->nf!=3) - error(Ebadarg); - size = strtoul(cb->f[1], 0, 0); - if(cb->nf == 2) - align = 0; - else - align = strtoul(cb->f[2], 0, 0); - if(screenaperture(size, align)) - error("not enough free address space"); - return; - - case CMblank: - drawblankscreen(1); - return; - - case CMunblank: - drawblankscreen(0); - return; - - case CMblanktime: - blanktime = strtoul(cb->f[1], 0, 0); - return; - - case CMpanning: - if(strcmp(cb->f[1], "on") == 0){ - if(scr == nil || scr->cur == nil) - error("set screen first"); - if(!scr->cur->doespanning) - error("panning not supported"); - scr->gscreen->clipr = scr->gscreen->r; - panning = 1; - } - else if(strcmp(cb->f[1], "off") == 0){ - scr->gscreen->clipr = physgscreenr; - panning = 0; - }else - break; - return; - - case CMhwaccel: - if(strcmp(cb->f[1], "on") == 0) - hwaccel = 1; - else if(strcmp(cb->f[1], "off") == 0) - hwaccel = 0; - else - break; - return; - - case CMhwblank: - if(strcmp(cb->f[1], "on") == 0) - hwblank = 1; - else if(strcmp(cb->f[1], "off") == 0) - hwblank = 0; - else - break; - return; - } - - cmderror(cb, "bad VGA control message"); -} - -char Enooverlay[] = "No overlay support"; - -static long -vgawrite(Chan* c, void* a, long n, vlong off) -{ - ulong offset = off; - Cmdbuf *cb; - VGAscr *scr; - - switch((ulong)c->qid.path){ - - case Qdir: - error(Eperm); - - case Qvgactl: - if(offset || n >= READSTR) - error(Ebadarg); - cb = parsecmd(a, n); - if(waserror()){ - free(cb); - nexterror(); - } - vgactl(cb); - poperror(); - free(cb); - return n; - - case Qvgaovl: - scr = &vgascreen[0]; - if (scr->dev == nil || scr->dev->ovlwrite == nil) { - error(Enooverlay); - break; - } - return scr->dev->ovlwrite(scr, a, n, off); - - case Qvgaovlctl: - scr = &vgascreen[0]; - if (scr->dev == nil || scr->dev->ovlctl == nil) { - error(Enooverlay); - break; - } - scr->dev->ovlctl(scr, c, a, n); - return n; - - default: - if(c->qid.path < nvgadir) - return vgasegwr(&vgasegs[c->qid.path], a, n, offset); - error(Egreg); - break; - } - - return 0; -} - -Dev vgadevtab = { - 'v', - "vga", - - vgareset, - devinit, - devshutdown, - vgaattach, - vgawalk, - vgastat, - vgaopen, - devcreate, - vgaclose, - vgaread, - devbread, - vgawrite, - devbwrite, - devremove, - devwstat, -}; diff --git a/os/pc/devzt5512.c b/os/pc/devzt5512.c deleted file mode 100644 index af189fff..00000000 --- a/os/pc/devzt5512.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Namespace Interface for Ziatech 5512 System Registers - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - - -enum{ - Qdir, - Qsysid, - Qwatchdog, - Qledctl, - Qpower, - Qswitch, - Qstat, -}; - -static -Dirtab zttab[]={ - ".", {Qdir,0,QTDIR}, 0, 0555, - "id", {Qsysid, 0}, 0, 0444, - "watchdog", {Qwatchdog, 0}, 0, 0600, - "ledctl", {Qledctl, 0}, 0, 0666, - "powerstat", {Qpower, 0}, 0, 0444, - "switch", {Qswitch, 0}, 0, 0444, - "stat", {Qstat, 0}, 0, 0444, -}; - -extern int watchdog; -void -watchdog_strobe(void) -{ - uchar sysreg; - - sysreg = inb(0x78); - sysreg &= (~1); - outb(0x78, sysreg); /* disable/strobe watchdog */ - sysreg |= 1; - outb(0x78, sysreg); /* enable watchdog */ -} - -static void -ztreset(void) /* default in dev.c */ -{ - uchar sysreg; - - if(watchdog) - addclock0link(watchdog_strobe); - /* clear status LEDs */ - sysreg = inb(0xe2); - sysreg &= ~3; /* clear usr1 */ - sysreg &= ~(3 << 2); /* clear usr2 */ - outb(0xe2, sysreg); -} - -static Chan* -ztattach(char* spec) -{ - return devattach('Z', spec); -} - -static int -ztwalk(Chan* c, char* name) -{ - return devwalk(c, name, zttab, nelem(zttab), devgen); -} - -static void -ztstat(Chan* c, char* db) -{ - devstat(c, db, zttab, nelem(zttab), devgen); -} - -static Chan* -ztopen(Chan* c, int omode) -{ - return devopen(c, omode, zttab, nelem(zttab), devgen); -} - -static void -ztclose(Chan* c) -{ - USED(c); -} - -static long -ztread(Chan* c, void* a, long n, vlong offset) -{ - uchar sysreg; - char buf[256]; - - USED(offset); - - switch(c->qid.path & ~CHDIR) { - case Qdir: - return devdirread(c, a, n, zttab, nelem(zttab), devgen); - case Qsysid: { - ulong rev; - sysreg = inb(0xe3); - rev = (ulong) (sysreg & 0x7f); - sysreg = inb(0xe2); - sprint(buf, "Board Rev: %lud\nSerial #: %lud\n", rev, (ulong)(sysreg >> 4)); - return readstr(offset, a, n, buf); - }; - case Qwatchdog: - sysreg = inb(0x78); - if((sysreg & 1) == 1) { - n = readstr(offset, a, n, "enabled"); - } else { - n = readstr(offset, a, n, "disabled"); - } - return n; - case Qledctl: - { - char usr1[6], usr2[6]; - sysreg = inb(0xe2); - switch( sysreg & 3 ) { - case 0: - case 3: - sprint(usr1, "off"); - break; - case 1: - sprint(usr1, "red"); - break; - case 2: - sprint(usr1, "green"); - }; - switch( (sysreg >> 2) & 3) { - case 0: - case 3: - sprint(usr2, "off"); - break; - case 1: - sprint(usr2, "red"); - break; - case 2: - sprint(usr2, "green"); - }; - sprint(buf, "usr1: %s\nusr2: %s\n",usr1, usr2); - return readstr(offset, a, n, buf); - }; - case Qpower: - sysreg = inb(0xe4); - sprint(buf, "DEG#: %d\nFAL#: %d\n", (sysreg & 2), (sysreg & 1)); - return readstr(offset, a, n, buf); - case Qswitch: - sysreg = inb(0xe4); - sprint(buf, "%d %d %d %d", (sysreg & (1<<6)), (sysreg & (1<<5)), (sysreg & (1<<4)), (sysreg & (1<<3))); - return readstr(offset, a, n, buf); - case Qstat: { - char bus[10],cpu[20], mode[20], boot[20]; - - sysreg = inb(0xe5); - switch (sysreg & 0x7) { - case 1: - sprint(bus, "66 MHz"); - break; - case 2: - sprint(bus, "60 MHz"); - break; - case 3: - sprint(bus, "50 MHz"); - break; - default: - sprint(bus, "unknown"); - }; - switch ((sysreg>>3)&0x7) { - case 0: - sprint(cpu, "75, 90, 100 MHz"); - break; - case 1: - sprint(cpu, "120, 133 MHz"); - break; - case 2: - sprint(cpu, "180, 200 MHz"); - break; - case 3: - sprint(cpu, "150, 166 MHz"); - default: - sprint(cpu, "unknown"); - }; - if(sysreg & (1<<6)) - sprint(mode, "Port 80 test mode"); - else - sprint(mode, "Normal decode"); - if(sysreg & (1<<7)) - sprint(boot,"EEPROM"); - else - sprint(boot,"Flash"); - sprint(buf,"Bus Frequency: %s\nPentium: %s\nTest Mode Status: %s\nBIOS Boot ROM: %s\n", - bus, cpu, mode, boot); - return readstr(offset, a, n, buf); - }; - default: - n=0; - break; - } - return n; -} - - - -static long -ztwrite(Chan* c, void *vp, long n, vlong offset) -{ - uchar sysreg; - char buf[256]; - char *a; - int nf; - char *fields[3]; - - a = vp; - if(n >= sizeof(buf)) - n = sizeof(buf)-1; - strncpy(buf, a, n); - buf[n] = 0; - - USED(a, offset); - - switch(c->qid.path & ~CHDIR){ - case Qwatchdog: - sysreg = inb(0x78); - - if(strncmp(buf, "enable", 6) == 0) { - if((sysreg & 1) != 1) - addclock0link(watchdog_strobe); - break; - } - n = 0; - error(Ebadarg); - case Qledctl: - nf = getfields(buf, fields, 3, 1, " \t\n"); - if(nf < 2) { - error(Ebadarg); - n = 0; - break; - } - sysreg = inb(0xe2); - USED(sysreg); - if(strncmp(fields[0],"usr1", 4)==0) { - sysreg &= ~3; - if(strncmp(fields[1], "off", 3)==0) { - outb(0xe2, sysreg); - break; - } - if(strncmp(fields[1], "red", 3)==0) { - sysreg |= 1; - outb(0xe2, sysreg); - break; - } - if(strncmp(fields[1], "green", 5)==0) { - sysreg |= 2; - outb(0xe2, sysreg); - break; - } - } - if(strncmp(fields[0],"usr2", 4)==0) { - sysreg &= ~(3 << 2); - if(strncmp(fields[1], "off", 3)==0) { - outb(0xe2, sysreg); - break; - } - if(strncmp(fields[1], "red", 3)==0) { - sysreg |= (1 << 2); - outb(0xe2, sysreg); - break; - } - if(strncmp(fields[1], "green", 5)==0) { - sysreg |= (2 << 2); - outb(0xe2, sysreg); - break; - } - } - n = 0; - error(Ebadarg); - default: - error(Ebadusefd); - } - return n; -} - - - -Dev zt5512devtab = { /* defaults in dev.c */ - 'Z', - "Ziatech5512", - - ztreset, /* devreset */ - devinit, /* devinit */ - ztattach, - devdetach, - devclone, /* devclone */ - ztwalk, - ztstat, - ztopen, - devcreate, /* devcreate */ - ztclose, - ztread, - devbread, /* devbread */ - ztwrite, - devbwrite, /* devbwrite */ - devremove, /* devremove */ - devwstat, /* devwstat */ -}; diff --git a/os/pc/dma.c b/os/pc/dma.c deleted file mode 100644 index 9da7bddd..00000000 --- a/os/pc/dma.c +++ /dev/null @@ -1,237 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" - -typedef struct DMAport DMAport; -typedef struct DMA DMA; -typedef struct DMAxfer DMAxfer; - -/* - * state of a dma transfer - */ -struct DMAxfer -{ - ulong bpa; /* bounce buffer physical address */ - void* bva; /* bounce buffer virtual address */ - int blen; /* bounce buffer length */ - 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. - */ -int -dmainit(int chan, int maxtransfer) -{ - DMA *dp; - DMAxfer *xp; - 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"); - once = 1; - } - - if(maxtransfer > 64*1024) - maxtransfer = 64*1024; - - dp = &dma[(chan>>2)&1]; - chan = chan & 3; - xp = &dp->x[chan]; - if(xp->bva != nil){ - if(xp->blen < maxtransfer) - return 1; - return 0; - } - - xp->bva = xspanalloc(maxtransfer, BY2PG, 64*1024); - if(xp->bva == nil) - return 1; - xp->bpa = PADDR(xp->bva); - if(xp->bpa >= 16*MB){ - /* - * This will panic with the current - * implementation of xspanalloc(). - xfree(xp->bva); - */ - xp->bva = nil; - return 1; - } - xp->blen = maxtransfer; - xp->len = 0; - xp->isread = 0; - - return 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 bounce buffer. - */ - pa = PADDR(va); - if((((ulong)va)&0xF0000000) != KZERO - || (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000) - || pa >= 16*MB) { - if(xp->bva == nil) - return -1; - if(len > xp->blen) - len = xp->blen; - 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<>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<shift)+1); -} - */ diff --git a/os/pc/ether2000.c b/os/pc/ether2000.c deleted file mode 100644 index 8fc8911e..00000000 --- a/os/pc/ether2000.c +++ /dev/null @@ -1,232 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.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 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; - } -} - -static int -ne2000reset(Ether* edev) -{ - ushort buf[16]; - ulong port; - Dp8390 *dp8390; - int i; - uchar ea[Eaddrlen]; - - if(edev->port == 0) - ne2000pnp(edev); - - /* - * Set up the software configuration. - * Use defaults for irq, mem and size - * if not specified. - * Must have a port, no more default. - */ - if(edev->port == 0) - return -1; - if(edev->irq == 0) - edev->irq = 2; - if(edev->mem == 0) - edev->mem = 0x4000; - if(edev->size == 0) - edev->size = 16*1024; - port = edev->port; - - if(ioalloc(edev->port, 0x20, 0, "ne2000") < 0) - return -1; - - edev->ctlr = malloc(sizeof(Dp8390)); - dp8390 = edev->ctlr; - dp8390->width = 2; - dp8390->ram = 0; - - dp8390->port = port; - dp8390->data = port+Data; - - dp8390->tstart = HOWMANY(edev->mem, Dp8390BufSz); - dp8390->pstart = dp8390->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz); - dp8390->pstop = dp8390->tstart + HOWMANY(edev->size, Dp8390BufSz); - - dp8390->dummyrr = 1; - for(i = 0; i < edev->nopt; i++){ - if(strcmp(edev->opt[i], "nodummyrr")) - continue; - dp8390->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(edev); - memset(buf, 0, sizeof(buf)); - dp8390read(dp8390, buf, 0, sizeof(buf)); - i = buf[0x0E] & 0xFF; - if((i != 0x00 && i != 0x57) || (buf[0x0F] & 0xFF) != 0x57){ - iofree(edev->port); - free(edev->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, edev->ea, Eaddrlen) == 0){ - for(i = 0; i < sizeof(edev->ea); i++) - edev->ea[i] = buf[i]; - } - dp8390setea(edev); - - return 0; -} - -void -ether2000link(void) -{ - addethercard("NE2000", ne2000reset); -} diff --git a/os/pc/ether2114x.c b/os/pc/ether2114x.c deleted file mode 100644 index f71773c0..00000000 --- a/os/pc/ether2114x.c +++ /dev/null @@ -1,1830 +0,0 @@ -/* - * Digital Semiconductor DECchip 2114x PCI Fast Ethernet LAN Controller. - * To do: - * thresholds; - * ring sizing; - * handle more error conditions; - * tidy setup packet mess; - * push initialisation back to attach; - * full SROM decoding. - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" - -#include "etherif.h" - -#define DEBUG (0) -#define debug if(DEBUG)print - -enum { - Nrde = 64, - Ntde = 64, -}; - -#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; - Block* 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; /* address size in bits */ - 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; - - Lock lock; - - 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* setupbp; - - ulong of; /* receive statistics */ - ulong ce; - ulong cs; - ulong tl; - ulong rf; - ulong de; - - ulong ru; - ulong rps; - ulong rwt; - - ulong uf; /* transmit statistics */ - ulong ec; - ulong lc; - ulong nc; - ulong lo; - ulong to; - - ulong tps; - ulong tu; - ulong tjt; - ulong unf; -} 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 -promiscuous(void* arg, int on) -{ - Ctlr *ctlr; - - ctlr = ((Ether*)arg)->ctlr; - ilock(&ctlr->lock); - if(on) - ctlr->csr6 |= Pr; - else - ctlr->csr6 &= ~Pr; - csr32w(ctlr, 6, ctlr->csr6); - iunlock(&ctlr->lock); -} - -/* multicast already on, don't need to do anything */ -static void -multicast(void*, uchar*, int) -{ -} - -static void -attach(Ether* ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ilock(&ctlr->lock); - if(!(ctlr->csr6 & Sr)){ - ctlr->csr6 |= Sr; - csr32w(ctlr, 6, ctlr->csr6); - } - iunlock(&ctlr->lock); -} - -static long -ifstat(Ether* ether, void* a, long n, ulong offset) -{ - Ctlr *ctlr; - char *buf, *p; - int i, l, len; - - ctlr = ether->ctlr; - - ether->crcs = ctlr->ce; - ether->frames = ctlr->rf+ctlr->cs; - ether->buffs = ctlr->de+ctlr->tl; - ether->overflows = ctlr->of; - - if(n == 0) - return 0; - - p = malloc(READSTR); - l = snprint(p, READSTR, "Overflow: %lud\n", ctlr->of); - l += snprint(p+l, READSTR-l, "Ru: %lud\n", ctlr->ru); - l += snprint(p+l, READSTR-l, "Rps: %lud\n", ctlr->rps); - l += snprint(p+l, READSTR-l, "Rwt: %lud\n", ctlr->rwt); - l += snprint(p+l, READSTR-l, "Tps: %lud\n", ctlr->tps); - l += snprint(p+l, READSTR-l, "Tu: %lud\n", ctlr->tu); - l += snprint(p+l, READSTR-l, "Tjt: %lud\n", ctlr->tjt); - l += snprint(p+l, READSTR-l, "Unf: %lud\n", ctlr->unf); - l += snprint(p+l, READSTR-l, "CRC Error: %lud\n", ctlr->ce); - l += snprint(p+l, READSTR-l, "Collision Seen: %lud\n", ctlr->cs); - l += snprint(p+l, READSTR-l, "Frame Too Long: %lud\n", ctlr->tl); - l += snprint(p+l, READSTR-l, "Runt Frame: %lud\n", ctlr->rf); - l += snprint(p+l, READSTR-l, "Descriptor Error: %lud\n", ctlr->de); - l += snprint(p+l, READSTR-l, "Underflow Error: %lud\n", ctlr->uf); - l += snprint(p+l, READSTR-l, "Excessive Collisions: %lud\n", ctlr->ec); - l += snprint(p+l, READSTR-l, "Late Collision: %lud\n", ctlr->lc); - l += snprint(p+l, READSTR-l, "No Carrier: %lud\n", ctlr->nc); - l += snprint(p+l, READSTR-l, "Loss of Carrier: %lud\n", ctlr->lo); - l += snprint(p+l, READSTR-l, "Transmit Jabber Timeout: %lud\n", - ctlr->to); - l += snprint(p+l, READSTR-l, "csr6: %luX %uX\n", csr32r(ctlr, 6), - ctlr->csr6); - snprint(p+l, READSTR-l, "ntqmax: %d\n", ctlr->ntqmax); - ctlr->ntqmax = 0; - buf = a; - len = readstr(offset, buf, n, p); - if(offset > l) - offset -= l; - else - offset = 0; - buf += len; - n -= len; - - l = snprint(p, READSTR, "srom:"); - for(i = 0; i < (1<<(ctlr->sromsz)*sizeof(ushort)); i++){ - if(i && ((i & 0x0F) == 0)) - l += snprint(p+l, READSTR-l, "\n "); - l += snprint(p+l, READSTR-l, " %2.2uX", ctlr->srom[i]); - } - - snprint(p+l, READSTR-l, "\n"); - len += readstr(offset, buf, n, p); - free(p); - - return len; -} - -static void -txstart(Ether* ether) -{ - Ctlr *ctlr; - Block *bp; - Des *des; - int control; - - ctlr = ether->ctlr; - while(ctlr->ntq < (ctlr->ntdr-1)){ - if(ctlr->setupbp){ - bp = ctlr->setupbp; - ctlr->setupbp = 0; - control = Ic|Set|BLEN(bp); - } - else{ - bp = qget(ether->oq); - if(bp == nil) - break; - 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 = PCIWADDR(bp->rp); - des->control |= control; - ctlr->ntq++; - coherence(); - des->status = Own; - csr32w(ctlr, 1, 0); - ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr); - } - - if(ctlr->ntq > ctlr->ntqmax) - ctlr->ntqmax = ctlr->ntq; -} - -static void -transmit(Ether* ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ilock(&ctlr->tlock); - txstart(ether); - iunlock(&ctlr->tlock); -} - -static void -interrupt(Ureg*, void* arg) -{ - Ctlr *ctlr; - Ether *ether; - int len, status; - Des *des; - Block *bp; - - 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|Ti)); - - if(status & Ais){ - if(status & Tps) - ctlr->tps++; - if(status & Tu) - ctlr->tu++; - if(status & Tjt) - ctlr->tjt++; - if(status & Ru) - ctlr->ru++; - if(status & Rps) - ctlr->rps++; - if(status & Rwt) - ctlr->rwt++; - status &= ~(Ais|Rwt|Rps|Ru|Tjt|Tu|Tps); - } - - /* - * Received packets. - */ - if(status & Ri){ - des = &ctlr->rdr[ctlr->rdrx]; - while(!(des->status & Own)){ - 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 if(bp = iallocb(Rbsz)){ - len = ((des->status & Fl)>>16)-4; - des->bp->wp = des->bp->rp+len; - etheriq(ether, des->bp, 1); - des->bp = bp; - des->addr = PCIWADDR(bp->rp); - } - - des->control &= Er; - des->control |= Rbsz; - coherence(); - 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){ - ctlr->unf++; - ilock(&ctlr->lock); - 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); - iunlock(&ctlr->lock); - csr32w(ctlr, 5, Tps); - status &= ~(Unf|Tps); - } - - ilock(&ctlr->tlock); - 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++; - ether->oerrs++; - } - - freeb(des->bp); - des->control &= Er; - - ctlr->ntq--; - ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr); - } - txstart(ether); - iunlock(&ctlr->tlock); - - /* - * Anything left not catered for? - */ - if(status) - panic("#l%d: status %8.8uX\n", ether->ctlrno, status); - } -} - -static void -ctlrinit(Ether* ether) -{ - Ctlr *ctlr; - Des *des; - Block *bp; - int i; - uchar bi[Eaddrlen*2]; - - ctlr = ether->ctlr; - - /* - * Allocate and initialise the receive ring; - * allocate and initialise the transmit ring; - * unmask interrupts and start the transmit side; - * create and post a setup packet to initialise - * the physical ethernet address. - */ - ctlr->rdr = xspanalloc(ctlr->nrdr*sizeof(Des), 8*sizeof(ulong), 0); - for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){ - des->bp = iallocb(Rbsz); - if(des->bp == nil) - panic("can't allocate ethernet receive ring\n"); - des->status = Own; - des->control = Rbsz; - des->addr = PCIWADDR(des->bp->rp); - } - ctlr->rdr[ctlr->nrdr-1].control |= Er; - ctlr->rdrx = 0; - csr32w(ctlr, 3, PCIWADDR(ctlr->rdr)); - - ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0); - ctlr->tdr[ctlr->ntdr-1].control |= Er; - ctlr->tdrh = 0; - ctlr->tdri = 0; - csr32w(ctlr, 4, PCIWADDR(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|Pm; - 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 = iallocb(Eaddrlen*2*16); - if(bp == nil) - panic("can't allocate ethernet setup buffer\n"); - 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; - ether->oq = qopen(256*1024, Qmsg, 0, 0); - 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<= 0; i--){ - if(bits & (1<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<sromsz == 0){ - ctlr->sromsz = 8-size; - goto reread; - } - - return data & 0xFFFF; -} - -static void -shutdown(Ether* ether) -{ - Ctlr *ctlr = ether->ctlr; - -print("ether2114x shutting down\n"); - csr32w(ctlr, 0, Swr); -} - -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<type5block) - type5block(ctlr, &ctlr->type5block[2]); - else - type5block(ctlr, &block[4+len*block[3]]); - debug("\n"); - ctlr->phyreset |= (1<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 < 45; 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 */ - nil, -}; - -/* - * 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. - * Do a dummy read first to get the size and allocate ctlr->srom. - */ - sromr(ctlr, 0); - if(ctlr->srom == nil) - ctlr->srom = malloc((1<sromsz)*sizeof(ushort)); - for(i = 0; i < (1<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<sromsz)*sizeof(ushort)); i++){ - if(i && ((i & 0x0F) == 0)) - print("\n "); - print(" %2.2uX", ctlr->srom[i]); - } - print("\n"); - } - - /* - * There are at least 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 and AMDtek. - * They look like a 21140 with a PHY. - * The MAC address is byte-swapped in the orginal - * PNIC 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; - debug("phy reg 2 %4.4uX\n", oui); - 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; - - if(ioalloc(ctlr->port, p->mem[0].size, 0, "dec2114x") < 0){ - print("dec2114x: port 0x%uX in use\n", ctlr->port); - free(ctlr); - continue; - } - - /* - * 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)){ - iofree(ctlr->port); - free(ctlr); - continue; - } - - 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 int -reset(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; - } - } - - ether->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->ifstat = ifstat; - - ether->arg = ether; - ether->shutdown = shutdown; - ether->multicast = multicast; - ether->promiscuous = promiscuous; - - return 0; -} - -void -ether2114xlink(void) -{ - addethercard("2114x", reset); - addethercard("21140", reset); -} diff --git a/os/pc/ether589.c b/os/pc/ether589.c deleted file mode 100644 index ef19093f..00000000 --- a/os/pc/ether589.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * 3C589 and 3C562. - * To do: - * check xcvr10Base2 still works (is GlobalReset necessary?). - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.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 etherelnk3reset(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 etherelnk3reset(ether); -} - -static int -reset(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((slot = pcmspecial(type, ether)) >= 0) - break; - } - if(slot < 0){ - 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(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); - } - } - /* - * 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 */ -} - -void -ether589link(void) -{ - addethercard("3C589", reset); - addethercard("3C562", reset); - addethercard("589E", reset); -} diff --git a/os/pc/ether79c960.c b/os/pc/ether79c960.c deleted file mode 100644 index f74574cd..00000000 --- a/os/pc/ether79c960.c +++ /dev/null @@ -1,523 +0,0 @@ -/* - * AM79C960 - * PCnet Single-Chip Ethernet Controller for ISA Bus - * To do: - * only issue transmit interrupt if necessary? - * dynamically increase rings as necessary? - * use Blocks as receive buffers? - * currently hardwires 10Base-T - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" - -#include "etherif.h" - -#define chatty 1 -#define DPRINT if(chatty)print - -enum { - Lognrdre = 6, - Nrdre = (1<ctlr; - ilock(ctlr); - if(ctlr->init){ - iunlock(ctlr); - return; - } - port = ether->port; - outs(port+Rdp, Iena|Strt); - iunlock(ctlr); -} - -static void -ringinit(Ctlr* ctlr) -{ - int i, x; - - /* - * 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 = xspanalloc(Nrdre*sizeof(Rdre), 0x10, 0); - if(ctlr->rrb == 0) - ctlr->rrb = xalloc(Nrdre*Rbsize); - - x = PADDR(ctlr->rrb); - if ((x >> 24)&0xFF) - panic("ether79c960: address>24bit"); - for(i = 0; i < Nrdre; i++){ - ctlr->rdr[i].rbadr = x&0xFFFF; - ctlr->rdr[i].rmd1 = Own|(x>>16)&0xFF; - x += Rbsize; - ctlr->rdr[i].rmd2 = 0xF000|-Rbsize&0x0FFF; - ctlr->rdr[i].rmd3 = 0; - } - ctlr->rdrx = 0; - - if(ctlr->tdr == 0) - ctlr->tdr = xspanalloc(Ntdre*sizeof(Tdre), 0x10, 0); - if(ctlr->trb == 0) - ctlr->trb = xalloc(Ntdre*Rbsize); - - x = PADDR(ctlr->trb); - if ((x >> 24)&0xFF) - panic("ether79c960: address>24bit"); - for(i = 0; i < Ntdre; i++){ - ctlr->tdr[i].tbadr = x&0xFFFF; - ctlr->tdr[i].tmd1 = (x>>16)&0xFF; - x += Rbsize; - ctlr->tdr[i].tmd2 = 0xF000|-Rbsize&0x0FFF; - } - ctlr->tdrx = 0; -} - -static void -promiscuous(void* arg, int on) -{ - Ether *ether; - int port, x; - Ctlr *ctlr; - - ether = arg; - port = ether->port; - ctlr = ether->ctlr; - - /* - * Put the chip into promiscuous mode. First we must wait until - * anyone transmitting is done, then we can stop the chip and put - * it in promiscuous mode. Restarting is made harder by the chip - * reloading the transmit and receive descriptor pointers with their - * base addresses when Strt is set (unlike the older Lance chip), - * so the rings must be re-initialised. - */ - ilock(ctlr); - if(ctlr->init){ - iunlock(ctlr); - return; - } - ctlr->init = 1; - iunlock(ctlr); - - outs(port+Rdp, Stop); - - outs(port+Rap, 15); - x = ins(port+Rdp) & ~Prom; - if(on) - x |= Prom; /* BUG: multicast ... */ - outs(port+Rdp, x); - outs(port+Rap, 0); - - ringinit(ctlr); - - ilock(ctlr); - ctlr->init = 0; - outs(port+Rdp, Iena|Strt); - iunlock(ctlr); -} - -static int -owntdre(void* arg) -{ - return (((Tdre*)arg)->tmd1 & Own) == 0; -} - -static void -txstart(Ether *ether) -{ - int port; - Ctlr *ctlr; - Tdre *tdre; - Etherpkt *pkt; - Block *bp; - int n; - - port = ether->port; - ctlr = ether->ctlr; - - if(ctlr->init) - return; - - /* - * Take the next transmit buffer, if it is free. - */ - tdre = &ctlr->tdr[ctlr->tdrx]; - if(owntdre(tdre) == 0) - return; - bp = qget(ether->oq); - if(bp == nil) - return; - - /* - * Copy the packet to the transmit buffer and fill in our - * source ethernet address. There's no need to pad to ETHERMINTU - * here as we set ApadXmit in CSR4. - */ - n = BLEN(bp); - pkt = KADDR(tdre->tbadr|(tdre->tmd1&0xFF)<<16); - memmove(pkt->d, bp->rp, n); - memmove(pkt->s, ether->ea, sizeof(pkt->s)); - freeb(bp); - - /* - * Give ownership of the descriptor to the chip, increment the - * software ring descriptor pointer and tell the chip to poll. - */ - tdre->tmd3 = 0; - tdre->tmd2 = 0xF000|(-n)&0x0FFF; - tdre->tmd1 |= Own|Stp|Enp; - ctlr->tdrx = NEXT(ctlr->tdrx, Ntdre); - outs(port+Rdp, Iena|Tdmd); - - ether->outpackets++; -} - -static void -transmit(Ether *ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - - ilock(ctlr); - txstart(ether); - iunlock(ctlr); -} - -static void -interrupt(Ureg*, void* arg) -{ - Ether *ether; - int port, csr0, status; - Ctlr *ctlr; - Rdre *rdre; - Etherpkt *pkt; - Block *bp; - int len; - - ether = arg; - port = ether->port; - ctlr = ether->ctlr; - - /* - * Acknowledge all interrupts and whine about those that shouldn't - * happen. - */ - csr0 = ins(port+Rdp); - outs(port+Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena); - if(csr0 & (Babl|Miss|Merr)) - print("AMD70C960#%d: csr0 = 0x%uX\n", ether->ctlrno, csr0); - - /* - * Receiver interrupt: run round the descriptor ring logging - * errors and passing valid receive data up to the higher levels - * until we encounter a descriptor still owned by the chip. - */ - if(csr0 & Rint){ - rdre = &ctlr->rdr[ctlr->rdrx]; - while(((status = rdre->rmd1) & Own) == 0){ - if(status & RxErr){ - if(status & RxBuff) - ether->buffs++; - if(status & RxCrc) - ether->crcs++; - if(status & RxOflo) - ether->overflows++; - } - else { - len = (rdre->rmd3 & 0x0FFF)-4; - if((bp = iallocb(len)) != nil){ - ether->inpackets++; - pkt = KADDR(rdre->rbadr|(rdre->rmd1&0xFF)<<16); - memmove(bp->wp, pkt, len); - bp->wp += len; - etheriq(ether, bp, 1); - } - } - - /* - * Finished with this descriptor, reinitialise it, - * give it back to the chip, then on to the next... - */ - rdre->rmd3 = 0; - rdre->rmd2 = 0xF000|-Rbsize&0x0FFF; - rdre->rmd1 |= Own; - - ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre); - rdre = &ctlr->rdr[ctlr->rdrx]; - } - } - - /* - * Transmitter interrupt: start next block if waiting for free descriptor. - */ - if(csr0 & Tint){ - lock(ctlr); - txstart(ether); - unlock(ctlr); - } -} - -static int -reset(Ether* ether) -{ - int port, x, i; - uchar ea[Eaddrlen]; - Ctlr *ctlr; - - if(ether->port == 0) - ether->port = 0x300; - if(ether->irq == 0) - ether->irq = 10; - if(ether->irq == 2) - ether->irq = 9; - if(ether->dma == 0) - ether->dma = 5; - port = ether->port; - - if(port == 0 || ether->dma == 0) - return -1; - - /* - * Allocate a controller structure and start to fill in the - * initialisation block (must be DWORD aligned). - */ - ether->ctlr = malloc(sizeof(Ctlr)); - ctlr = ether->ctlr; - - ilock(ctlr); - ctlr->init = 1; - - /* - * Set the auto pad transmit in CSR4. - */ - /*outs(port+Rdp, 0x00);/**/ - ins(port+Sreset); /**/ - delay(1); - outs(port+Rap, 0); - outs(port+Rdp, Stop); - - outs(port+Rap, 4); - x = ins(port+Rdp) & 0xFFFF; - outs(port+Rdp, ApadXmt|x); - - outs(port+Rap, 0); - - /* - * Check if we are going to override the adapter's station address. - * 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) == 0){ - for(i=0; i<6; i++) - ether->ea[i] = inb(port + Aprom + i); - } - - ctlr->iblock.rlen = Lognrdre<<5; - ctlr->iblock.tlen = Logntdre<<5; - memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr)); - - ringinit(ctlr); - - x = PADDR(ctlr->rdr); - ctlr->iblock.rdra0 = x&0xFFFF; - ctlr->iblock.rdra16 = (x >> 16)&0xFF; - x = PADDR(ctlr->tdr); - ctlr->iblock.tdra0 = x&0xFFFF; - ctlr->iblock.tdra16 = (x >> 16)&0xFF; - - /* - * set the DMA controller to cascade mode for bus master - */ - switch(ether->dma){ - case 5: - outb(0xd6, 0xc1); outb(0xd4, 1); break; - case 6: - outb(0xd6, 0xc2); outb(0xd4, 2); break; - case 7: - outb(0xd6, 0xc3); outb(0xd4, 3); break; - } - - /* - * Ensure 10Base-T (for now) - */ - ctlr->iblock.mode = TenBaseT; - outs(port+Rap, 2); - x = ins(port+Idp); - x &= ~Isamedia; - x |= Isa10; - x |= Isaawake; - outs(port+Idp, x); - - /* - * 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 we're ready to attach to the network. - */ - x = PADDR(&ctlr->iblock); - if((x>>24)&0xFF) - panic("ether79c960: address>24bit"); - outs(port+Rap, 1); - outs(port+Rdp, x & 0xFFFF); - outs(port+Rap, 2); - outs(port+Rdp, (x>>16) & 0xFF); - outs(port+Rap, 3); - outs(port+Rdp, Idonm); - outs(port+Rap, 0); - outs(port+Rdp, Init); - - while((ins(port+Rdp) & Idon) == 0) - ; - outs(port+Rdp, Idon|Stop); - ctlr->init = 0; - iunlock(ctlr); - - ether->port = port; - ether->attach = attach; - ether->transmit = transmit; - ether->interrupt = interrupt; - ether->ifstat = 0; - - ether->promiscuous = promiscuous; - ether->arg = ether; - - return 0; -} - -void -ether79c960link(void) -{ - addethercard("AMD79C960", reset); -} diff --git a/os/pc/ether79c970.c b/os/pc/ether79c970.c deleted file mode 100644 index 43924a3f..00000000 --- a/os/pc/ether79c970.c +++ /dev/null @@ -1,645 +0,0 @@ -/* - * AMD79C970 - * PCnet-PCI Single-Chip Ethernet Controller for PCI Local Bus - * To do: - * finish this rewrite - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" - -#include "etherif.h" - -enum { - Lognrdre = 6, - Nrdre = (1<= 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 long -ifstat(Ether* ether, void* a, long n, ulong offset) -{ - char *p; - int len; - Ctlr *ctlr; - - ctlr = ether->ctlr; - - ether->crcs = ctlr->crc; - ether->frames = ctlr->fram; - ether->buffs = ctlr->rxbuff+ctlr->txbuff; - ether->overflows = ctlr->oflo; - - if(n == 0) - return 0; - - p = malloc(READSTR); - len = snprint(p, READSTR, "Rxbuff: %ld\n", ctlr->rxbuff); - len += snprint(p+len, READSTR-len, "Crc: %ld\n", ctlr->crc); - len += snprint(p+len, READSTR-len, "Oflo: %ld\n", ctlr->oflo); - len += snprint(p+len, READSTR-len, "Fram: %ld\n", ctlr->fram); - len += snprint(p+len, READSTR-len, "Rtry: %ld\n", ctlr->rtry); - len += snprint(p+len, READSTR-len, "Lcar: %ld\n", ctlr->lcar); - len += snprint(p+len, READSTR-len, "Lcol: %ld\n", ctlr->lcol); - len += snprint(p+len, READSTR-len, "Uflo: %ld\n", ctlr->uflo); - len += snprint(p+len, READSTR-len, "Txbuff: %ld\n", ctlr->txbuff); - len += snprint(p+len, READSTR-len, "Merr: %ld\n", ctlr->merr); - len += snprint(p+len, READSTR-len, "Miss: %ld\n", ctlr->miss); - snprint(p+len, READSTR-len, "Babl: %ld\n", ctlr->babl); - - n = readstr(offset, a, n, p); - free(p); - - return n; -} - -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 = xspanalloc(Nrdre*sizeof(Dre), 0x10, 0); - for(dre = ctlr->rdr; dre < &ctlr->rdr[Nrdre]; dre++){ - dre->bp = iallocb(Rbsize); - if(dre->bp == nil) - panic("can't allocate ethernet receive ring\n"); - dre->addr = PADDR(dre->bp->rp); - dre->md2 = 0; - dre->md1 = Own|(-Rbsize & 0xFFFF); - } - } - ctlr->rdrx = 0; - - if(ctlr->tdr == 0) - ctlr->tdr = xspanalloc(Ntdre*sizeof(Dre), 0x10, 0); - memset(ctlr->tdr, 0, Ntdre*sizeof(Dre)); - ctlr->tdrh = ctlr->tdri = 0; -} - -static void -promiscuous(void* arg, int on) -{ - Ether *ether; - int x; - Ctlr *ctlr; - - ether = arg; - ctlr = ether->ctlr; - - /* - * Put the chip into promiscuous mode. First must wait until - * anyone transmitting is done, then stop the chip and put - * it in promiscuous mode. Restarting is made harder by the chip - * reloading the transmit and receive descriptor pointers with their - * base addresses when Strt is set (unlike the older Lance chip), - * so the rings must be re-initialised. - */ - ilock(ctlr); - if(ctlr->init){ - iunlock(ctlr); - return; - } - ctlr->init = 1; - iunlock(ctlr); - - while(ctlr->ntq) - ; - - ctlr->iow(ctlr, Rdp, Stop); - - ctlr->iow(ctlr, Rap, 15); - x = ctlr->ior(ctlr, Rdp) & ~Prom; - if(on) - x |= Prom; - ctlr->iow(ctlr, Rdp, x); - ctlr->iow(ctlr, Rap, 0); - - ringinit(ctlr); - - ilock(ctlr); - ctlr->init = 0; - ctlr->iow(ctlr, Rdp, Iena|Strt); - iunlock(ctlr); -} - -static void -multicast(void* arg, uchar*, int) -{ - promiscuous(arg, 1); -} - -static void -txstart(Ether* ether) -{ - Ctlr *ctlr; - Block *bp; - Dre *dre; - - ctlr = ether->ctlr; - - if(ctlr->init) - return; - - while(ctlr->ntq < (Ntdre-1)){ - bp = qget(ether->oq); - if(bp == nil) - break; - - /* - * 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->bp = bp; - dre->addr = PADDR(bp->rp); - dre->md2 = 0; - dre->md1 = Own|Stp|Enp|(-BLEN(bp) & 0xFFFF); - ctlr->ntq++; - ctlr->iow(ctlr, Rdp, Iena|Tdmd); - ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre); - } -} - -static void -transmit(Ether* ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ilock(ctlr); - txstart(ether); - iunlock(ctlr); -} - -static void -interrupt(Ureg*, void* arg) -{ - Ctlr *ctlr; - Ether *ether; - int csr0, len; - Dre *dre; - Block *bp; - - 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)){ - 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(bp = iallocb(Rbsize)){ - len = (dre->md2 & 0x0FFF)-4; - dre->bp->wp = dre->bp->rp+len; - etheriq(ether, dre->bp, 1); - dre->bp = bp; - dre->addr = PADDR(bp->rp); - } - - /* - * 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++; - ether->oerrs++; - } - - freeb(dre->bp); - - ctlr->ntq--; - ctlr->tdri = NEXT(ctlr->tdri, Ntdre); - } - txstart(ether); - unlock(ctlr); - } - goto intrloop; -} - -static void -amd79c970pci(void) -{ - int port; - Ctlr *ctlr; - Pcidev *p; - - p = nil; - while(p = pcimatch(p, 0x1022, 0x2000)){ - port = p->mem[0].bar & ~0x01; - if(ioalloc(port, p->mem[0].size, 0, "amd79c970") < 0){ - print("amd79c970: port 0x%uX in use\n", port); - continue; - } - 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; - } -} - -static int -reset(Ether* ether) -{ - int x; - uchar ea[Eaddrlen]; - Ctlr *ctlr; - - if(ctlrhead == nil) - amd79c970pci(); - - /* - * Any adapter matches if no port is supplied, - * otherwise the ports must match. - */ - for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){ - if(ctlr->active) - continue; - if(ether->port == 0 || ether->port == ctlr->port){ - ctlr->active = 1; - break; - } - } - if(ctlr == nil) - return -1; - - /* - * Allocate a controller structure and start to initialise it. - */ - ether->ctlr = ctlr; - ether->port = ctlr->port; - ether->irq = ctlr->pcidev->intl; - ether->tbdf = ctlr->pcidev->tbdf; - pcisetbme(ctlr->pcidev); - ilock(ctlr); - ctlr->init = 1; - - io32r(ctlr, Sreset); - io16r(ctlr, Sreset); - - if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){ - ctlr->ior = io16r; - ctlr->iow = io16w; - }else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){ - ctlr->ior = io32r; - ctlr->iow = io32w; - }else{ - print("#l%d: card doesn't talk right\n", ether->ctlrno); - iunlock(ctlr); - return -1; - } - - ctlr->iow(ctlr, Rap, 88); - x = ctlr->ior(ctlr, Rdp); - ctlr->iow(ctlr, Rap, 89); - x |= ctlr->ior(ctlr, Rdp)<<16; - - switch(x&0xFFFFFFF){ - case 0x2420003: /* PCnet/PCI 79C970 */ - case 0x2621003: /* PCnet/PCI II 79C970A */ - break; - default: - print("#l%d: unknown PCnet card version %.7ux\n", - ether->ctlrno, 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->ifstat = ifstat; - - ether->arg = ether; - ether->promiscuous = promiscuous; - ether->multicast = multicast; -// ether->shutdown = shutdown; - - return 0; -} - -void -ether79c970link(void) -{ - addethercard("AMD79C970", reset); -} diff --git a/os/pc/ether8003.c b/os/pc/ether8003.c deleted file mode 100644 index 41244c09..00000000 --- a/os/pc/ether8003.c +++ /dev/null @@ -1,271 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.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. - */ -static int -reset(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; - if(ioalloc(ether->port, 0x20, 0, "wd8003") < 0) - return -1; - - /* - * 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){ - iofree(ether->port); - 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\n", - PADDR(ether->mem)); - - return 0; -} - -void -ether8003link(void) -{ - addethercard("WD8003", reset); -} diff --git a/os/pc/ether8139.c b/os/pc/ether8139.c deleted file mode 100644 index dd3653e3..00000000 --- a/os/pc/ether8139.c +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Realtek 8139 (but not the 8129). - * Error recovery for the various over/under -flow conditions - * may need work. - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.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 */ - Timerbit = 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, - Rtl8139ArevG = 0x00800000, /* RTL8139A Rev. G ID */ - IfgSHIFT = 24, /* Interframe Gap */ - IfgMASK = 0x03000000, - HwveridSHIFT = 26, /* Hardware Version ID */ - HwveridMASK = 0x7C000000, -}; - -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 Td Td; -struct Td { /* Soft Transmit Descriptor */ - int tsd; - int tsad; - uchar* data; - Block* bp; -}; - -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; - - QLock alock; /* attach */ - 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 void -rtl8139promiscuous(void* arg, int on) -{ - Ether *edev; - Ctlr * ctlr; - - edev = arg; - ctlr = edev->ctlr; - ilock(&ctlr->ilock); - - if(on) - ctlr->rcr |= Aap; - else - ctlr->rcr &= ~Aap; - csr32w(ctlr, Rcr, ctlr->rcr); - iunlock(&ctlr->ilock); -} - -static void -rtl8139multicast(void* arg, uchar*, int) -{ - rtl8139promiscuous(arg, 1); -} - -static long -rtl8139ifstat(Ether* edev, void* a, long n, ulong offset) -{ - int l; - char *p; - Ctlr *ctlr; - - ctlr = edev->ctlr; - p = malloc(READSTR); - l = snprint(p, READSTR, "rcr %#8.8ux\n", ctlr->rcr); - l += snprint(p+l, READSTR-l, "ierrs %d\n", ctlr->ierrs); - l += snprint(p+l, READSTR-l, "etxth %d\n", ctlr->etxth); - l += snprint(p+l, READSTR-l, "taligned %d\n", ctlr->taligned); - l += snprint(p+l, READSTR-l, "tunaligned %d\n", ctlr->tunaligned); - ctlr->dis += csr16r(ctlr, Dis); - l += snprint(p+l, READSTR-l, "dis %d\n", ctlr->dis); - ctlr->fcsc += csr16r(ctlr, Fcsc); - l += snprint(p+l, READSTR-l, "fcscnt %d\n", ctlr->fcsc); - ctlr->rec += csr16r(ctlr, Rec); - l += snprint(p+l, READSTR-l, "rec %d\n", ctlr->rec); - - l += snprint(p+l, READSTR-l, "Tcr %#8.8lux\n", csr32r(ctlr, Tcr)); - l += snprint(p+l, READSTR-l, "Config0 %#2.2ux\n", csr8r(ctlr, Config0)); - l += snprint(p+l, READSTR-l, "Config1 %#2.2ux\n", csr8r(ctlr, Config1)); - l += snprint(p+l, READSTR-l, "Msr %#2.2ux\n", csr8r(ctlr, Msr)); - l += snprint(p+l, READSTR-l, "Config3 %#2.2ux\n", csr8r(ctlr, Config3)); - l += snprint(p+l, READSTR-l, "Config4 %#2.2ux\n", csr8r(ctlr, Config4)); - - l += snprint(p+l, READSTR-l, "Bmcr %#4.4ux\n", csr16r(ctlr, Bmcr)); - l += snprint(p+l, READSTR-l, "Bmsr %#4.4ux\n", csr16r(ctlr, Bmsr)); - l += snprint(p+l, READSTR-l, "Anar %#4.4ux\n", csr16r(ctlr, Anar)); - l += snprint(p+l, READSTR-l, "Anlpar %#4.4ux\n", csr16r(ctlr, Anlpar)); - l += snprint(p+l, READSTR-l, "Aner %#4.4ux\n", csr16r(ctlr, Aner)); - l += snprint(p+l, READSTR-l, "Nwaytr %#4.4ux\n", csr16r(ctlr, Nwaytr)); - snprint(p+l, READSTR-l, "Cscr %#4.4ux\n", csr16r(ctlr, Cscr)); - n = readstr(offset, a, n, p); - free(p); - - return n; -} - -static int -rtl8139reset(Ctlr* ctlr) -{ - int timeo; - - /* - * Soft reset the controller. - */ - csr8w(ctlr, Cr, Rst); - for(timeo = 0; timeo < 1000; timeo++){ - if(!(csr8r(ctlr, Cr) & Rst)) - return 0; - delay(1); - } - - return -1; -} - -static void -rtl8139halt(Ctlr* ctlr) -{ - int i; - - csr8w(ctlr, Cr, 0); - csr16w(ctlr, Imr, 0); - csr16w(ctlr, Isr, ~0); - - for(i = 0; i < Ntd; i++){ - if(ctlr->td[i].bp == nil) - continue; - freeb(ctlr->td[i].bp); - ctlr->td[i].bp = nil; - } -} - -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, PCIWADDR(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->td[i].bp = nil; - } - ctlr->ntd = ctlr->tdh = ctlr->tdi = 0; - ctlr->etxth = 128/32; - - /* - * Interrupts. - */ - csr32w(ctlr, TimerInt, 0); - csr16w(ctlr, Imr, Serr|Timerbit|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; - qlock(&ctlr->alock); - if(ctlr->alloc == nil){ - ctlr->rblen = 1<<((Rblen>>RblenSHIFT)+13); - ctlr->alloc = mallocz(ctlr->rblen+16 + Ntd*Tdbsz + 32, 0); - rtl8139init(edev); - } - qunlock(&ctlr->alock); -} - -static void -rtl8139txstart(Ether* edev) -{ - Td *td; - int size; - Block *bp; - Ctlr *ctlr; - - ctlr = edev->ctlr; - while(ctlr->ntd < Ntd){ - bp = qget(edev->oq); - if(bp == nil) - break; - size = BLEN(bp); - - td = &ctlr->td[ctlr->tdh]; - if(((int)bp->rp) & 0x03){ - memmove(td->data, bp->rp, size); - freeb(bp); - csr32w(ctlr, td->tsad, PCIWADDR(td->data)); - ctlr->tunaligned++; - } - else{ - td->bp = bp; - csr32w(ctlr, td->tsad, PCIWADDR(bp->rp)); - ctlr->taligned++; - } - csr32w(ctlr, td->tsd, (ctlr->etxth<ntd++; - ctlr->tdh = NEXT(ctlr->tdh, Ntd); - } -} - -static void -rtl8139transmit(Ether* edev) -{ - Ctlr *ctlr; - - ctlr = edev->ctlr; - ilock(&ctlr->tlock); - rtl8139txstart(edev); - iunlock(&ctlr->tlock); -} - -static void -rtl8139receive(Ether* edev) -{ - Block *bp; - Ctlr *ctlr; - 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)){ - if(status & (Ise|Fae)) - edev->frames++; - if(status & Crc) - edev->crcs++; - if(status & (Runt|Long)) - edev->buffs++; - - /* - * 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, PCIWADDR(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; - - if((bp = iallocb(length)) != nil){ - if(p+length >= ctlr->rbstart+ctlr->rblen){ - l = ctlr->rbstart+ctlr->rblen - p; - memmove(bp->wp, p, l); - bp->wp += l; - length -= l; - p = ctlr->rbstart; - } - if(length > 0){ - memmove(bp->wp, p, length); - bp->wp += length; - } - bp->wp -= 4; - etheriq(edev, bp, 1); - } - - capr = ROUNDUP(capr, 4); - csr16w(ctlr, Capr, capr-16); - } -} - -static void -rtl8139interrupt(Ureg*, void* arg) -{ - Td *td; - Ctlr *ctlr; - Ether *edev; - int isr, msr, 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++; - } - edev->oerrs++; - } - - if(td->bp != nil){ - freeb(td->bp); - td->bp = nil; - } - - ctlr->ntd--; - ctlr->tdi = NEXT(ctlr->tdi, Ntd); - } - rtl8139txstart(edev); - iunlock(&ctlr->tlock); - isr &= ~(Ter|Tok); - } - - if(isr & PunLc){ - /* - * Maybe the link changed - do we care very much? - */ - msr = csr8r(ctlr, Msr); - if(!(msr & Linkb)){ - if(!(msr & Speed10) && edev->mbps != 100){ - edev->mbps = 100; - qsetlimit(edev->oq, 256*1024); - } - else if((msr & Speed10) && edev->mbps != 10){ - edev->mbps = 10; - qsetlimit(edev->oq, 65*1024); - } - } - isr &= ~(Clc|PunLc); - } - - /* - * Only Serr|Timerbit 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|Timerbit)) != 0){ - iprint("rtl8139interrupt: imr %#4.4ux isr %#4.4ux\n", - csr16r(ctlr, Imr), isr); - if(isr & Timerbit) - csr32w(ctlr, TimerInt, 0); - if(isr & Serr) - rtl8139init(edev); - } - } -} - -static Ctlr* -rtl8139match(Ether* edev, int id) -{ - Pcidev *p; - Ctlr *ctlr; - int i, port; - - /* - * 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; - - if(ioalloc(port, p->mem[0].size, 0, "rtl8139") < 0){ - print("rtl8139: port %#ux in use\n", port); - 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); - } - - ctlr->port = port; - if(rtl8139reset(ctlr)) { - iofree(port); - 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 }, -}; - -static 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->ifstat = rtl8139ifstat; - - edev->arg = edev; - edev->promiscuous = rtl8139promiscuous; - edev->multicast = rtl8139multicast; -// edev->shutdown = rtl8139shutdown; - - /* - * This should be much more dynamic but will do for now. - */ - if((csr8r(ctlr, Msr) & (Speed10|Linkb)) == 0) - edev->mbps = 100; - - return 0; -} - -void -ether8139link(void) -{ - addethercard("rtl8139", rtl8139pnp); -} diff --git a/os/pc/ether82543gc.c b/os/pc/ether82543gc.c deleted file mode 100644 index 86ec7b75..00000000 --- a/os/pc/ether82543gc.c +++ /dev/null @@ -1,1367 +0,0 @@ -/* - * Intel RS-82543GC Gigabit Ethernet Controller - * 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. - * The datasheet is not very clear about running on a big-endian system - * and this driver assumes little-endian throughout. - * To do: - * GMII/MII - * receive tuning - * transmit tuning - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" - -#include "etherif.h" - -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 reg. */ - Rxcw = 0x00000180, /* Receive configuration word reg. */ - 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 */ - Rdfh = 0x00002410, /* Receive data fifo head */ - Rdft = 0x00002418, /* Receive data fifo tail */ - Rdfhs = 0x00002420, /* Receive data fifo head saved */ - Rdfts = 0x00002428, /* Receive data fifo tail saved */ - Rdfpc = 0x00002430, /* Receive data fifo packet count */ - 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 */ - Txdmac = 0x00003000, /* Transfer DMA Control */ - Ett = 0x00003008, /* Early Transmit Control */ - Tdfh = 0x00003410, /* Transmit data fifo head */ - Tdft = 0x00003418, /* Transmit data fifo tail */ - Tdfhs = 0x00003420, /* Transmit data Fifo Head saved */ - Tdfts = 0x00003428, /* Transmit data fifo tail saved */ - Tdfpc = 0x00003430, /* Trasnmit data Fifo packet count */ - 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 */ - - 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 */ -}; - -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) */ - Frcspd = 0x00000800, /* Force Speed */ - Frcdplx = 0x00001000, /* Force Duplex */ - Swdpinslo = 0x003C0000, /* Software Defined Pins - lo nibble */ - Swdpin0 = 0x00040000, - Swdpin1 = 0x00080000, - Swdpin2 = 0x00100000, - Swdpin3 = 0x00200000, - Swdpiolo = 0x03C00000, /* Software Defined I/O Pins */ - Swdpio0 = 0x00400000, - Swdpio1 = 0x00800000, - Swdpio2 = 0x01000000, - Swdpio3 = 0x02000000, - Devrst = 0x04000000, /* Device Reset */ - Rfce = 0x08000000, /* Receive Flow Control Enable */ - Tfce = 0x10000000, /* Transmit Flow Control Enable */ - Vme = 0x40000000, /* VLAN Mode Enable */ -}; - -enum { /* Status */ - Lu = 0x00000002, /* Link Up */ - 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 */ -}; - -enum { /* Ctrlext */ - Gpien = 0x0000000F, /* General Purpose Interrupt Enables */ - Swdpinshi = 0x000000F0, /* Software Defined Pins - hi nibble */ - Swdpiohi = 0x00000F00, /* Software Defined Pins - I or O */ - 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, -}; - -enum { /* Txcw */ - Ane = 0x80000000, /* Autonegotiate enable */ - Np = 0x00008000, /* Next Page */ - As = 0x00000100, /* Asymmetric Flow control desired */ - Ps = 0x00000080, /* Pause supported */ - Hd = 0x00000040, /* Half duplex supported */ - TxcwFd = 0x00000020, /* Full Duplex supported */ -}; - -enum { /* Rxcw */ - Rxword = 0x0000FFFF, /* Data from auto-negotiation process */ - Rxnocarrier = 0x04000000, /* Carrier Sense indication */ - Rxinvalid = 0x08000000, /* Invalid Symbol during configuration */ - Rxchange = 0x10000000, /* Change to the Rxword indication */ - Rxconfig = 0x20000000, /* /C/ order set reception indication */ - Rxsync = 0x40000000, /* Lost bit synchronization indication */ - Anc = 0x80000000, /* Auto Negotiation Complete */ -}; - -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, /* Bsex = 0 */ - Bsize1024 = 0x00010000, /* Bsex = 0 */ - Bsize512 = 0x00020000, /* Bsex = 0 */ - Bsize256 = 0x00030000, /* Bsex = 0 */ - Bsize16384 = 0x00010000, /* Bsex = 1 */ - 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, /* Writeback Threshold */ - WthreshSHIFT = 16, - Gran = 0x00000000, /* Granularity */ - RxGran = 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 { /* Receive Delay Timer Ring */ - Fpd = 0x80000000, /* Flush partial Descriptor Block */ -}; - -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 */ - CsoMASK = 0x00000F00, /* Checksum Offset */ - CsoSHIFT = 16, - Teop = 0x01000000, /* End of Packet */ - Ifcs = 0x02000000, /* Insert FCS */ - Ic = 0x04000000, /* Insert Checksum (Dext == 0) */ - Tse = 0x04000000, /* TCP Segmentaion Enable (Dext == 1) */ - Rs = 0x08000000, /* Report Status */ - Rps = 0x10000000, /* Report Status Sent */ - Dext = 0x20000000, /* Extension (!legacy) */ - 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 = 256, /* multiple of 8 */ - Ntdesc = 256, /* multiple of 8 */ - Nblocks = 4098, /* total number of blocks to use */ - - SBLOCKSIZE = 2048, - JBLOCKSIZE = 16384, - - NORMAL = 1, - JUMBO = 2, -}; - -typedef struct Ctlr Ctlr; -typedef struct Ctlr { - int port; - Pcidev* pcidev; - Ctlr* next; - int active; - int started; - int id; - ushort eeprom[0x40]; - - int* nic; - int im; /* interrupt mask */ - - Lock slock; - uint statistics[Nstatistics]; - - Lock rdlock; - Rdesc* rdba; /* receive descriptor base address */ - Block* rb[Nrdesc]; /* receive buffers */ - int rdh; /* receive descriptor head */ - int rdt; /* receive descriptor tail */ - Block** freehead; /* points to long or short head */ - - Lock tdlock; - Tdesc* tdba; /* transmit descriptor base address */ - Block* tb[Ntdesc]; /* transmit buffers */ - int tdh; /* transmit descriptor head */ - int tdt; /* transmit descriptor tail */ - int txstalled; /* count of times unable to send */ - - int txcw; - int fcrtl; - int fcrth; - - ulong multimask[128]; /* bit mask for multicast addresses */ -} Ctlr; - -static Ctlr* gc82543ctlrhead; -static Ctlr* gc82543ctlrtail; - -static Lock freelistlock; -static Block* freeShortHead; -static Block* freeJumboHead; - -#define csr32r(c, r) (*((c)->nic+((r)/4))) -#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) - -static void gc82543watchdog(void* arg); - -static void -gc82543attach(Ether* edev) -{ - int ctl; - Ctlr *ctlr; - char name[KNAMELEN]; - - /* - * To do here: - * one-time stuff; - * adjust queue length depending on speed; - * flow control. - * more needed here... - */ - ctlr = edev->ctlr; - lock(&ctlr->slock); - if(ctlr->started == 0){ - ctlr->started = 1; - snprint(name, KNAMELEN, "#l%d82543", edev->ctlrno); - kproc(name, gc82543watchdog, edev, 0); - } - unlock(&ctlr->slock); - - ctl = csr32r(ctlr, Rctl)|Ren; - csr32w(ctlr, Rctl, ctl); - ctl = csr32r(ctlr, Tctl)|Ten; - csr32w(ctlr, Tctl, ctl); - - csr32w(ctlr, Ims, ctlr->im); -} - -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 long -gc82543ifstat(Ether* edev, void* a, long n, ulong offset) -{ - Ctlr *ctlr; - char *p, *s; - int i, l, r; - uvlong tuvl, ruvl; - - ctlr = edev->ctlr; - lock(&ctlr->slock); - p = malloc(2*READSTR); - l = 0; - for(i = 0; i < Nstatistics; i++){ - r = csr32r(ctlr, Statistics+i*4); - if((s = statistics[i]) == nil) - continue; - switch(i){ - case Gorcl: - case Gotcl: - case Torl: - case Totl: - ruvl = r; - ruvl += ((uvlong)csr32r(ctlr, Statistics+(i+1)*4))<<32; - tuvl = ruvl; - tuvl += ctlr->statistics[i]; - tuvl += ((uvlong)ctlr->statistics[i+1])<<32; - if(tuvl == 0) - continue; - ctlr->statistics[i] = tuvl; - ctlr->statistics[i+1] = tuvl>>32; - l += snprint(p+l, 2*READSTR-l, "%s: %llud %llud\n", - s, tuvl, ruvl); - i++; - break; - - default: - ctlr->statistics[i] += r; - if(ctlr->statistics[i] == 0) - continue; - l += snprint(p+l, 2*READSTR-l, "%s: %ud %ud\n", - s, ctlr->statistics[i], r); - break; - } - } - - l += snprint(p+l, 2*READSTR-l, "eeprom:"); - for(i = 0; i < 0x40; i++){ - if(i && ((i & 0x07) == 0)) - l += snprint(p+l, 2*READSTR-l, "\n "); - l += snprint(p+l, 2*READSTR-l, " %4.4uX", ctlr->eeprom[i]); - } - - snprint(p+l, 2*READSTR-l, "\ntxstalled %d\n", ctlr->txstalled); - n = readstr(offset, a, n, p); - free(p); - unlock(&ctlr->slock); - - return n; -} - -static void -gc82543promiscuous(void* arg, int on) -{ - int rctl; - Ctlr *ctlr; - Ether *edev; - - edev = arg; - ctlr = edev->ctlr; - - rctl = csr32r(ctlr, Rctl); - rctl &= ~MoMASK; /* make sure we're using bits 47:36 */ - if(on) - rctl |= Upe|Mpe; - else - rctl &= ~(Upe|Mpe); - csr32w(ctlr, Rctl, rctl); -} - -static void -gc82543multicast(void* arg, uchar* addr, int on) -{ - int bit, x; - Ctlr *ctlr; - Ether *edev; - - edev = arg; - ctlr = edev->ctlr; - x = addr[5]>>1; - bit = ((addr[5] & 1)<<4)|(addr[4]>>4); - if(on) - ctlr->multimask[x] |= 1<multimask[x] &= ~(1<multimask[x]); -} - -static long -gc82543ctl(Ether* edev, void* buf, long n) -{ - Cmdbuf *cb; - Ctlr *ctlr; - int ctrl, i, r; - - ctlr = edev->ctlr; - if(ctlr == nil) - error(Enonexist); - - lock(&ctlr->slock); - r = 0; - cb = parsecmd(buf, n); - if(cb->nf < 2) - r = -1; - else if(cistrcmp(cb->f[0], "auto") == 0){ - ctrl = csr32r(ctlr, Ctrl); - if(cistrcmp(cb->f[1], "off") == 0){ - csr32w(ctlr, Txcw, ctlr->txcw & ~Ane); - ctrl |= (Slu|Fd); - if(ctlr->txcw & As) - ctrl |= Rfce; - if(ctlr->txcw & Ps) - ctrl |= Tfce; - csr32w(ctlr, Ctrl, ctrl); - } - else if(cistrcmp(cb->f[1], "on") == 0){ - csr32w(ctlr, Txcw, ctlr->txcw); - ctrl &= ~(Slu|Fd); - csr32w(ctlr, Ctrl, ctrl); - } - else - r = -1; - } - else if(cistrcmp(cb->f[0], "clear") == 0){ - if(cistrcmp(cb->f[1], "stats") == 0){ - for(i = 0; i < Nstatistics; i++) - ctlr->statistics[i] = 0; - } - else - r = -1; - } - else - r = -1; - unlock(&ctlr->slock); - - free(cb); - return (r == 0) ? n : r; -} - -static void -gc82543txinit(Ctlr* ctlr) -{ - int i; - int tdsize; - Block *bp, **bpp; - - tdsize = ROUND(Ntdesc*sizeof(Tdesc), 4096); - - if(ctlr->tdba == nil) - ctlr->tdba = xspanalloc(tdsize, 32, 0); - - for(i = 0; i < Ntdesc; i++){ - bpp = &ctlr->tb[i]; - bp = *bpp; - if(bp != nil){ - *bpp = nil; - freeb(bp); - } - memset(&ctlr->tdba[i], 0, sizeof(Tdesc)); - } - - csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba)); - csr32w(ctlr, Tdbah, 0); - csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc)); - - /* - * set the ring head and tail pointers. - */ - ctlr->tdh = 0; - csr32w(ctlr, Tdh, ctlr->tdh); - ctlr->tdt = 0; - csr32w(ctlr, Tdt, ctlr->tdt); - - csr32w(ctlr, Tipg, (6<<20)|(8<<10)|6); - csr32w(ctlr, Tidv, 128); - csr32w(ctlr, Ait, 0); - csr32w(ctlr, Txdmac, 0); - csr32w(ctlr, Txdctl, Gran|(4<im |= Txdw; -} - -static void -gc82543transmit(Ether* edev) -{ - Block *bp, **bpp; - Ctlr *ctlr; - Tdesc *tdesc; - int tdh, tdt, s; - - ctlr = edev->ctlr; - - ilock(&ctlr->tdlock); - tdh = ctlr->tdh; - for(;;){ - /* - * Free any completed packets - */ - tdesc = &ctlr->tdba[tdh]; - if(!(tdesc->status & Tdd)) - break; - memset(tdesc, 0, sizeof(Tdesc)); - bpp = &ctlr->tb[tdh]; - bp = *bpp; - if(bp != nil){ - *bpp = nil; - freeb(bp); - } - tdh = NEXT(tdh, Ntdesc); - } - ctlr->tdh = tdh; - s = csr32r(ctlr, Status); - - /* - * Try to fill the ring back up - * but only if link is up and transmission isn't paused. - */ - if((s & (Txoff|Lu)) == Lu){ - tdt = ctlr->tdt; - while(NEXT(tdt, Ntdesc) != tdh){ - if((bp = qget(edev->oq)) == nil) - break; - - tdesc = &ctlr->tdba[tdt]; - tdesc->addr[0] = PCIWADDR(bp->rp); - tdesc->control = Ide|Rs|Ifcs|Teop|BLEN(bp); - ctlr->tb[tdt] = bp; - tdt = NEXT(tdt, Ntdesc); - } - - if(tdt != ctlr->tdt){ - ctlr->tdt = tdt; - csr32w(ctlr, Tdt, tdt); - } - } - else - ctlr->txstalled++; - - iunlock(&ctlr->tdlock); -} - -static Block * -gc82543allocb(Ctlr* ctlr) -{ - Block *bp; - - ilock(&freelistlock); - if((bp = *(ctlr->freehead)) != nil){ - *(ctlr->freehead) = bp->next; - bp->next = nil; - } - iunlock(&freelistlock); - return bp; -} - -static void -gc82543replenish(Ctlr* ctlr) -{ - int rdt; - Block *bp; - Rdesc *rdesc; - - ilock(&ctlr->rdlock); - rdt = ctlr->rdt; - while(NEXT(rdt, Nrdesc) != ctlr->rdh){ - rdesc = &ctlr->rdba[rdt]; - if(ctlr->rb[rdt] == nil){ - bp = gc82543allocb(ctlr); - if(bp == nil){ - iprint("no available buffers\n"); - break; - } - ctlr->rb[rdt] = bp; - rdesc->addr[0] = PCIWADDR(bp->rp); - rdesc->addr[1] = 0; - } - coherence(); - rdesc->status = 0; - rdt = NEXT(rdt, Nrdesc); - } - ctlr->rdt = rdt; - csr32w(ctlr, Rdt, rdt); - iunlock(&ctlr->rdlock); -} - -static void -gc82543rxinit(Ctlr* ctlr) -{ - int rdsize, i; - - csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF); - - /* - * Allocate the descriptor ring and load its - * address and length into the NIC. - */ - rdsize = ROUND(Nrdesc*sizeof(Rdesc), 4096); - if(ctlr->rdba == nil) - ctlr->rdba = xspanalloc(rdsize, 32, 0); - memset(ctlr->rdba, 0, rdsize); - - ctlr->rdh = 0; - ctlr->rdt = 0; - - csr32w(ctlr, Rdtr, Fpd|64); - csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba)); - csr32w(ctlr, Rdbah, 0); - csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc)); - csr32w(ctlr, Rdh, 0); - csr32w(ctlr, Rdt, 0); - for(i = 0; i < Nrdesc; i++){ - if(ctlr->rb[i] != nil){ - freeb(ctlr->rb[i]); - ctlr->rb[i] = nil; - } - } - gc82543replenish(ctlr); - - csr32w(ctlr, Rxdctl, RxGran|(8<im |= Rxt0|Rxo|Rxdmt0|Rxseq; -} - -static void -gc82543recv(Ether* edev, int icr) -{ - Block *bp; - Ctlr *ctlr; - Rdesc *rdesc; - int rdh; - - ctlr = edev->ctlr; - - 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; - bp->wp += rdesc->length; - bp->next = nil; - etheriq(edev, bp, 1); - } - - if(ctlr->rb[rdh] != nil){ - /* either non eop packet, or error */ - freeb(ctlr->rb[rdh]); - ctlr->rb[rdh] = nil; - } - memset(rdesc, 0, sizeof(Rdesc)); - coherence(); - rdh = NEXT(rdh, Nrdesc); - } - ctlr->rdh = rdh; - - if(icr & Rxdmt0) - gc82543replenish(ctlr); -} - -static void -freegc82543short(Block *bp) -{ - ilock(&freelistlock); - /* reset read/write pointer to proper positions */ - bp->rp = bp->lim - ROUND(SBLOCKSIZE, BLOCKALIGN); - bp->wp = bp->rp; - bp->next = freeShortHead; - freeShortHead = bp; - iunlock(&freelistlock); -} - -static void -freegc82532jumbo(Block *bp) -{ - ilock(&freelistlock); - /* reset read/write pointer to proper positions */ - bp->rp = bp->lim - ROUND(JBLOCKSIZE, BLOCKALIGN); - bp->wp = bp->rp; - bp->next = freeJumboHead; - freeJumboHead = bp; - iunlock(&freelistlock); -} - -static void -linkintr(Ctlr* ctlr) -{ - int ctrl; - - ctrl = csr32r(ctlr, Ctrl); - - if((ctrl & Swdpin1) || - ((csr32r(ctlr, Rxcw) & Rxconfig) && !(csr32r(ctlr, Txcw) & Ane))){ - csr32w(ctlr, Txcw, ctlr->txcw); - ctrl &= ~(Slu|Fd|Frcdplx); - csr32w(ctlr, Ctrl, ctrl); - } -} - -static void -gc82543interrupt(Ureg*, void* arg) -{ - Ctlr *ctlr; - Ether *edev; - int icr; - - edev = arg; - ctlr = edev->ctlr; - - while((icr = csr32r(ctlr, Icr) & ctlr->im) != 0){ - /* - * Link status changed. - */ - if(icr & (Lsc|Rxseq)) - linkintr(ctlr); - - /* - * Process recv buffers. - */ - gc82543recv(edev, icr); - - /* - * Refill transmit ring and free packets. - */ - gc82543transmit(edev); - } -} - -static int -gc82543init(Ether* edev) -{ - int csr, i; - Block *bp; - Ctlr *ctlr; - - ctlr = edev->ctlr; - - /* - * Allocate private buffer pool to use for receiving packets. - */ - ilock(&freelistlock); - if (ctlr->freehead == nil){ - for(i = 0; i < Nblocks; i++){ - bp = iallocb(SBLOCKSIZE); - if(bp != nil){ - bp->next = freeShortHead; - bp->free = freegc82543short; - freeShortHead = bp; - } - else{ - print("82543gc: no memory\n"); - break; - } - } - ctlr->freehead = &freeShortHead; - } - iunlock(&freelistlock); - - /* - * 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); - - gc82543txinit(ctlr); - gc82543rxinit(ctlr); - - 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 */ - if(lp != nil){ - if(p != (lp+1) || loop != 7) - return -1; - lp = p; - loop = 15; - continue; - } - lp = p; - loop = 7; - 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<= 0) - r |= (i<= 0) - return -1; - return r; -} - -static int -at93c46r(Ctlr* ctlr) -{ - ushort sum; - int addr, data; - - sum = 0; - 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, "S ICc :DCc;", (0x02<<6)|addr) != 0) - break; - data = at93c46io(ctlr, "::COc;", 0); - at93c46io(ctlr, "sic", 0); - ctlr->eeprom[addr] = data; - sum += data; - } - - return sum; -} - -static void -gc82543detach(Ctlr* ctlr) -{ - /* - * 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(10); - - csr32w(ctlr, Ctrl, Devrst); - while(csr32r(ctlr, Ctrl) & Devrst) - ; - - csr32w(ctlr, Ctrlext, Eerst); - while(csr32r(ctlr, Ctrlext) & Eerst) - ; - - csr32w(ctlr, Imc, ~0); - while(csr32r(ctlr, Icr)) - ; -} - -static void -gc82543checklink(Ctlr* ctlr) -{ - int ctrl, status, rxcw; - - ctrl = csr32r(ctlr, Ctrl); - status = csr32r(ctlr, Status); - rxcw = csr32r(ctlr, Rxcw); - - if(!(status & Lu)){ - if(!(ctrl & (Swdpin1|Slu)) && !(rxcw & Rxconfig)){ - csr32w(ctlr, Txcw, ctlr->txcw & ~Ane); - ctrl |= (Slu|Fd); - if(ctlr->txcw & As) - ctrl |= Rfce; - if(ctlr->txcw & Ps) - ctrl |= Tfce; - csr32w(ctlr, Ctrl, ctrl); - } - } - else if((ctrl & Slu) && (rxcw & Rxconfig)){ - csr32w(ctlr, Txcw, ctlr->txcw); - ctrl &= ~(Slu|Fd); - csr32w(ctlr, Ctrl, ctrl); - } -} - -static void -gc82543shutdown(Ether* ether) -{ - gc82543detach(ether->ctlr); -} - -static int -gc82543reset(Ctlr* ctlr) -{ - int ctl; - int te; - - /* - * Read the EEPROM, validate the checksum - * then get the device back to a power-on state. - */ - if(at93c46r(ctlr) != 0xBABA) - return -1; - - gc82543detach(ctlr); - - te = ctlr->eeprom[Icw2]; - if((te & 0x3000) == 0){ - ctlr->fcrtl = 0x00002000; - ctlr->fcrth = 0x00004000; - ctlr->txcw = Ane|TxcwFd; - } - else if((te & 0x3000) == 0x2000){ - ctlr->fcrtl = 0; - ctlr->fcrth = 0; - ctlr->txcw = Ane|TxcwFd|As; - } - else{ - ctlr->fcrtl = 0x00002000; - ctlr->fcrth = 0x00004000; - ctlr->txcw = Ane|TxcwFd|As|Ps; - } - - csr32w(ctlr, Txcw, ctlr->txcw); - - csr32w(ctlr, Ctrlext, (te & 0x00f0)<<4); - - csr32w(ctlr, Tctl, csr32r(ctlr, Tctl)|(64<eeprom[Icw1]; - ctl = ((te & 0x01E0)<<17)|(te & 0x0010)<<3; - csr32w(ctlr, Ctrl, ctl); - - delay(10); - - /* - * 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); - - ctlr->im = Lsc; - gc82543checklink(ctlr); - - return 0; -} - -static void -gc82543watchdog(void* arg) -{ - Ether *edev; - Ctlr *ctlr; - - edev = arg; - for(;;){ - tsleep(&up->sleep, return0, 0, 1000); - - ctlr = edev->ctlr; - if(ctlr == nil){ - print("%s: exiting\n", up->text); - pexit("disabled", 0); - } - - gc82543checklink(ctlr); - gc82543replenish(ctlr); - } -} - -static void -gc82543pci(void) -{ - int cls; - void *mem; - 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){ - case (0x1000<<16)|0x8086: /* LSI L2A1157 (82542) */ - case (0x1004<<16)|0x8086: /* Intel PRO/1000 T */ - case (0x1008<<16)|0x8086: /* Intel PRO/1000 XT */ - default: - continue; - case (0x1001<<16)|0x8086: /* Intel PRO/1000 F */ - break; - } - - mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size); - if(mem == 0){ - print("gc82543: can't map %8.8luX\n", p->mem[0].bar); - continue; - } - cls = pcicfgr8(p, PciCLS); - switch(cls){ - case 0x00: - case 0xFF: - print("82543gc: unusable cache line size\n"); - continue; - case 0x08: - break; - default: - print("82543gc: cache line size %d, expected 32\n", - cls*4); - } - ctlr = malloc(sizeof(Ctlr)); - ctlr->port = p->mem[0].bar & ~0x0F; - ctlr->pcidev = p; - ctlr->id = (p->did<<16)|p->vid; - ctlr->nic = mem; - - if(gc82543reset(ctlr)){ - free(ctlr); - continue; - } - - if(gc82543ctlrhead != nil) - gc82543ctlrtail->next = ctlr; - else - gc82543ctlrhead = ctlr; - gc82543ctlrtail = ctlr; - } -} - -static int -gc82543pnp(Ether* edev) -{ - int i; - Ctlr *ctlr; - uchar ea[Eaddrlen]; - - if(gc82543ctlrhead == nil) - gc82543pci(); - - /* - * Any adapter matches if no edev->port is supplied, - * otherwise the ports must match. - */ - for(ctlr = gc82543ctlrhead; 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 = Ea; i < Eaddrlen/2; i++){ - edev->ea[2*i] = ctlr->eeprom[i]; - edev->ea[2*i+1] = ctlr->eeprom[i]>>8; - } - } - gc82543init(edev); - - /* - * Linkage to the generic ethernet driver. - */ - edev->attach = gc82543attach; - edev->transmit = gc82543transmit; - edev->interrupt = gc82543interrupt; - edev->ifstat = gc82543ifstat; - edev->shutdown = gc82543shutdown; - edev->ctl = gc82543ctl; - edev->arg = edev; - edev->promiscuous = gc82543promiscuous; - edev->multicast = gc82543multicast; - - return 0; -} - -void -ether82543gclink(void) -{ - addethercard("82543GC", gc82543pnp); -} diff --git a/os/pc/ether82557.c b/os/pc/ether82557.c deleted file mode 100644 index 4dba07bd..00000000 --- a/os/pc/ether82557.c +++ /dev/null @@ -1,1327 +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 they're not all in the right place. - * To do: - * the PCI scanning code could be made common to other adapters; - * auto-negotiation, full-duplex; - * optionally use memory-mapped registers; - * detach for PCI reset problems (also towards loadable drivers). - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" - -#include "etherif.h" - -enum { - Nrfd = 64, /* receive frame area */ - Ncb = 64, /* maximum control blocks queued */ - - 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 */ - General = 0x04, /* dword */ - Port = 0x08, /* dword */ - Fcr = 0x0C, /* Flash control register */ - Ecr = 0x0E, /* EEPROM control register */ - Mcr = 0x10, /* MDI control register */ - Gstatus = 0x1D, /* General status 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; - - uchar data[1700]; -} 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 = 0x4000, - RfdEOF = 0x8000, -}; - -typedef struct Cb Cb; -typedef struct Cb { - ushort status; - ushort command; - ulong link; - union { - uchar data[24]; /* CbIAS + CbConfigure */ - struct { - ulong tbd; - ushort count; - uchar threshold; - uchar number; - - ulong tba; - ushort tbasz; - ushort pad; - }; - }; - - Block* bp; - Cb* next; -} Cb; - -enum { /* action command */ - CbU = 0x1000, /* transmit underrun */ - CbOK = 0x2000, /* DMA completed OK */ - CbC = 0x8000, /* execution Complete */ - - CbNOP = 0x0000, - CbIAS = 0x0001, /* Individual Address Setup */ - CbConfigure = 0x0002, - CbMAS = 0x0003, /* Multicast Address Setup */ - CbTransmit = 0x0004, - CbDump = 0x0006, - CbDiagnose = 0x0007, - CbCommand = 0x0007, /* mask */ - - CbSF = 0x0008, /* Flexible-mode CbTransmit */ - - CbI = 0x2000, /* Interrupt after completion */ - CbS = 0x4000, /* Suspend after completion */ - CbEL = 0x8000, /* End of List */ -}; - -enum { /* CbTransmit count */ - CbEOF = 0x8000, -}; - -typedef struct Ctlr Ctlr; -typedef struct Ctlr { - Lock slock; /* attach */ - int state; - - int port; - Pcidev* pcidev; - Ctlr* next; - int active; - - int eepromsz; /* address size in bits */ - ushort* eeprom; - - Lock miilock; - - int tick; - - Lock rlock; /* registers */ - int command; /* last command issued */ - - Block* rfdhead; /* receive side */ - Block* rfdtail; - int nrfd; - - Lock cblock; /* transmit side */ - int action; - int nop; - uchar configdata[24]; - int threshold; - int ncb; - Cb* cbr; - Cb* cbhead; - Cb* cbtail; - int cbq; - int cbqmax; - int cbqmaxhw; - - Lock dlock; /* dump statistical counters */ - ulong dump[17]; -} Ctlr; - -static Ctlr* ctlrhead; -static Ctlr* ctlrtail; - -static uchar configdata[24] = { - 0x16, /* byte count */ - 0x08, /* Rx/Tx FIFO limit */ - 0x00, /* adaptive IFS */ - 0x00, - 0x00, /* Rx DMA maximum byte count */ -// 0x80, /* Tx DMA maximum byte count */ - 0x00, /* Tx DMA maximum byte count */ - 0x32, /* !late SCB, CNA interrupts */ - 0x03, /* discard short Rx frames */ - 0x00, /* 503/MII */ - - 0x00, - 0x2E, /* normal operation, NSAI */ - 0x00, /* linear priority */ - 0x60, /* inter-frame spacing */ - 0x00, - 0xF2, - 0xC8, /* 503, promiscuous mode off */ - 0x00, - 0x40, - 0xF3, /* 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 -command(Ctlr* ctlr, int c, int v) -{ - int timeo; - - ilock(&ctlr->rlock); - - /* - * Only back-to-back CUresume can be done - * without waiting for any previous command to complete. - * This should be the common case. - * Unfortunately there's a chip errata where back-to-back - * CUresumes can be lost, the fix is to always wait. - if(c == CUresume && ctlr->command == CUresume){ - csr8w(ctlr, CommandR, c); - iunlock(&ctlr->rlock); - return; - } - */ - - for(timeo = 0; timeo < 100; timeo++){ - if(!csr8r(ctlr, CommandR)) - break; - microdelay(1); - } - if(timeo >= 100){ - ctlr->command = -1; - iunlock(&ctlr->rlock); - iprint("i82557: command %#ux %#ux timeout\n", c, v); - return; - } - - switch(c){ - - case CUstart: - case LoadDCA: - case LoadCUB: - case RUstart: - case LoadHDS: - case LoadRUB: - csr32w(ctlr, General, v); - break; - - /* - case CUnop: - case CUresume: - case DumpSC: - case ResetSA: - case RUresume: - case RUabort: - */ - default: - break; - } - csr8w(ctlr, CommandR, c); - ctlr->command = c; - - iunlock(&ctlr->rlock); -} - -static Block* -rfdalloc(ulong link) -{ - Block *bp; - Rfd *rfd; - - if(bp = iallocb(sizeof(Rfd))){ - rfd = (Rfd*)bp->rp; - rfd->field = 0; - rfd->link = link; - rfd->rbd = NullPointer; - rfd->count = 0; - rfd->size = sizeof(Etherpkt); - } - - return bp; -} - -static void -watchdog(void* arg) -{ - Ether *ether; - Ctlr *ctlr; - static void txstart(Ether*); - - ether = arg; - for(;;){ - tsleep(&up->sleep, return0, 0, 4000); - - /* - * Hmmm. This doesn't seem right. Currently - * the device can't be disabled but it may be in - * the future. - */ - ctlr = ether->ctlr; - if(ctlr == nil || ctlr->state == 0){ - print("%s: exiting\n", up->text); - pexit("disabled", 0); - } - - ilock(&ctlr->cblock); - if(ctlr->tick++){ - ctlr->action = CbMAS; - txstart(ether); - } - iunlock(&ctlr->cblock); - } -} - -static void -attach(Ether* ether) -{ - Ctlr *ctlr; - char name[KNAMELEN]; - - ctlr = ether->ctlr; - lock(&ctlr->slock); - if(ctlr->state == 0){ - ilock(&ctlr->rlock); - csr8w(ctlr, Interrupt, 0); - iunlock(&ctlr->rlock); - command(ctlr, RUstart, PADDR(ctlr->rfdhead->rp)); - ctlr->state = 1; - - /* - * Start the watchdog timer for the receive lockup errata - * unless the EEPROM compatibility word indicates it may be - * omitted. - */ - if((ctlr->eeprom[0x03] & 0x0003) != 0x0003){ - snprint(name, KNAMELEN, "#l%dwatchdog", ether->ctlrno); - kproc(name, watchdog, ether, 0); - } - } - unlock(&ctlr->slock); -} - -static long -ifstat(Ether* ether, void* a, long n, ulong offset) -{ - char *p; - int i, len, phyaddr; - Ctlr *ctlr; - ulong dump[17]; - - ctlr = ether->ctlr; - lock(&ctlr->dlock); - - /* - * Start the command then - * wait for completion status, - * should be 0xA005. - */ - ctlr->dump[16] = 0; - command(ctlr, DumpSC, 0); - while(ctlr->dump[16] == 0) - ; - - ether->oerrs = ctlr->dump[1]+ctlr->dump[2]+ctlr->dump[3]; - ether->crcs = ctlr->dump[10]; - ether->frames = ctlr->dump[11]; - ether->buffs = ctlr->dump[12]+ctlr->dump[15]; - ether->overflows = ctlr->dump[13]; - - if(n == 0){ - unlock(&ctlr->dlock); - return 0; - } - - memmove(dump, ctlr->dump, sizeof(dump)); - unlock(&ctlr->dlock); - - p = malloc(READSTR); - len = snprint(p, READSTR, "transmit good frames: %lud\n", dump[0]); - len += snprint(p+len, READSTR-len, "transmit maximum collisions errors: %lud\n", dump[1]); - len += snprint(p+len, READSTR-len, "transmit late collisions errors: %lud\n", dump[2]); - len += snprint(p+len, READSTR-len, "transmit underrun errors: %lud\n", dump[3]); - len += snprint(p+len, READSTR-len, "transmit lost carrier sense: %lud\n", dump[4]); - len += snprint(p+len, READSTR-len, "transmit deferred: %lud\n", dump[5]); - len += snprint(p+len, READSTR-len, "transmit single collisions: %lud\n", dump[6]); - len += snprint(p+len, READSTR-len, "transmit multiple collisions: %lud\n", dump[7]); - len += snprint(p+len, READSTR-len, "transmit total collisions: %lud\n", dump[8]); - len += snprint(p+len, READSTR-len, "receive good frames: %lud\n", dump[9]); - len += snprint(p+len, READSTR-len, "receive CRC errors: %lud\n", dump[10]); - len += snprint(p+len, READSTR-len, "receive alignment errors: %lud\n", dump[11]); - len += snprint(p+len, READSTR-len, "receive resource errors: %lud\n", dump[12]); - len += snprint(p+len, READSTR-len, "receive overrun errors: %lud\n", dump[13]); - len += snprint(p+len, READSTR-len, "receive collision detect errors: %lud\n", dump[14]); - len += snprint(p+len, READSTR-len, "receive short frame errors: %lud\n", dump[15]); - len += snprint(p+len, READSTR-len, "nop: %d\n", ctlr->nop); - if(ctlr->cbqmax > ctlr->cbqmaxhw) - ctlr->cbqmaxhw = ctlr->cbqmax; - len += snprint(p+len, READSTR-len, "cbqmax: %d\n", ctlr->cbqmax); - ctlr->cbqmax = 0; - len += snprint(p+len, READSTR-len, "threshold: %d\n", ctlr->threshold); - - len += snprint(p+len, READSTR-len, "eeprom:"); - for(i = 0; i < (1<eepromsz); i++){ - if(i && ((i & 0x07) == 0)) - len += snprint(p+len, READSTR-len, "\n "); - len += snprint(p+len, READSTR-len, " %4.4ux", ctlr->eeprom[i]); - } - - if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000)){ - phyaddr = ctlr->eeprom[6] & 0x00FF; - len += snprint(p+len, READSTR-len, "\nphy %2d:", phyaddr); - for(i = 0; i < 6; i++){ - static int miir(Ctlr*, int, int); - - len += snprint(p+len, READSTR-len, " %4.4ux", - miir(ctlr, phyaddr, i)); - } - } - - snprint(p+len, READSTR-len, "\n"); - n = readstr(offset, a, n, p); - free(p); - - return n; -} - -static void -txstart(Ether* ether) -{ - Ctlr *ctlr; - Block *bp; - Cb *cb; - - ctlr = ether->ctlr; - while(ctlr->cbq < (ctlr->ncb-1)){ - cb = ctlr->cbhead->next; - if(ctlr->action == 0){ - bp = qget(ether->oq); - if(bp == nil) - break; - - cb->command = CbS|CbSF|CbTransmit; - cb->tbd = PADDR(&cb->tba); - cb->count = 0; - cb->threshold = ctlr->threshold; - cb->number = 1; - cb->tba = PADDR(bp->rp); - cb->bp = bp; - cb->tbasz = BLEN(bp); - } - else if(ctlr->action == CbConfigure){ - cb->command = CbS|CbConfigure; - memmove(cb->data, ctlr->configdata, sizeof(ctlr->configdata)); - ctlr->action = 0; - } - else if(ctlr->action == CbIAS){ - cb->command = CbS|CbIAS; - memmove(cb->data, ether->ea, Eaddrlen); - ctlr->action = 0; - } - else if(ctlr->action == CbMAS){ - cb->command = CbS|CbMAS; - memset(cb->data, 0, sizeof(cb->data)); - ctlr->action = 0; - } - else{ - print("#l%d: action %#ux\n", ether->ctlrno, ctlr->action); - ctlr->action = 0; - break; - } - cb->status = 0; - - coherence(); - ctlr->cbhead->command &= ~CbS; - ctlr->cbhead = cb; - ctlr->cbq++; - } - - /* - * Workaround for some broken HUB chips - * when connected at 10Mb/s half-duplex. - */ - if(ctlr->nop){ - command(ctlr, CUnop, 0); - microdelay(1); - } - command(ctlr, CUresume, 0); - - if(ctlr->cbq > ctlr->cbqmax) - ctlr->cbqmax = ctlr->cbq; -} - -static void -configure(Ether* ether, int promiscuous) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ilock(&ctlr->cblock); - if(promiscuous){ - ctlr->configdata[6] |= 0x80; /* Save Bad Frames */ - //ctlr->configdata[6] &= ~0x40; /* !Discard Overrun Rx Frames */ - ctlr->configdata[7] &= ~0x01; /* !Discard Short Rx Frames */ - ctlr->configdata[15] |= 0x01; /* Promiscuous mode */ - ctlr->configdata[18] &= ~0x01; /* (!Padding enable?), !stripping enable */ - ctlr->configdata[21] |= 0x08; /* Multi Cast ALL */ - } - else{ - ctlr->configdata[6] &= ~0x80; - //ctlr->configdata[6] |= 0x40; - ctlr->configdata[7] |= 0x01; - ctlr->configdata[15] &= ~0x01; - ctlr->configdata[18] |= 0x01; /* 0x03? */ - ctlr->configdata[21] &= ~0x08; - } - ctlr->action = CbConfigure; - txstart(ether); - iunlock(&ctlr->cblock); -} - -static void -promiscuous(void* arg, int on) -{ - configure(arg, on); -} - -static void -multicast(void* arg, uchar *addr, int on) -{ - USED(addr, on); - configure(arg, 1); -} - -static void -transmit(Ether* ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ilock(&ctlr->cblock); - txstart(ether); - iunlock(&ctlr->cblock); -} - -static void -receive(Ether* ether) -{ - Rfd *rfd; - Ctlr *ctlr; - int count; - Block *bp, *pbp, *xbp; - - ctlr = ether->ctlr; - bp = ctlr->rfdhead; - for(rfd = (Rfd*)bp->rp; rfd->field & RfdC; rfd = (Rfd*)bp->rp){ - /* - * If it's an OK receive frame - * 1) save the count - * 2) if it's small, try to allocate a block and copy - * the data, then adjust the necessary fields for reuse; - * 3) if it's big, try to allocate a new Rfd and if - * successful - * adjust the received buffer pointers for the - * actual data received; - * initialise the replacement buffer to point to - * the next in the ring; - * initialise bp to point to the replacement; - * 4) if there's a good packet, pass it on for disposal. - */ - if(rfd->field & RfdOK){ - pbp = nil; - count = rfd->count & 0x3FFF; - if((count < ETHERMAXTU/4) && (pbp = iallocb(count))){ - memmove(pbp->rp, bp->rp+offsetof(Rfd, data[0]), count); - pbp->wp = pbp->rp + count; - - rfd->count = 0; - rfd->field = 0; - } - else if(xbp = rfdalloc(rfd->link)){ - bp->rp += offsetof(Rfd, data[0]); - bp->wp = bp->rp + count; - - xbp->next = bp->next; - bp->next = 0; - - pbp = bp; - bp = xbp; - } - if(pbp != nil) - etheriq(ether, pbp, 1); - } - else{ - rfd->count = 0; - rfd->field = 0; - } - - /* - * The ring tail pointer follows the head with with one - * unused buffer in between to defeat hardware prefetch; - * once the tail pointer has been bumped on to the next - * and the new tail has the Suspend bit set, it can be - * removed from the old tail buffer. - * As a replacement for the current head buffer may have - * been allocated above, ensure that the new tail points - * to it (next and link). - */ - rfd = (Rfd*)ctlr->rfdtail->rp; - ctlr->rfdtail = ctlr->rfdtail->next; - ctlr->rfdtail->next = bp; - ((Rfd*)ctlr->rfdtail->rp)->link = PADDR(bp->rp); - ((Rfd*)ctlr->rfdtail->rp)->field |= RfdS; - coherence(); - rfd->field &= ~RfdS; - - /* - * Finally done with the current (possibly replaced) - * head, move on to the next and maintain the sentinel - * between tail and head. - */ - ctlr->rfdhead = bp->next; - bp = ctlr->rfdhead; - } -} - -static void -interrupt(Ureg*, void* arg) -{ - Cb* cb; - Ctlr *ctlr; - Ether *ether; - int status; - - ether = arg; - ctlr = ether->ctlr; - - for(;;){ - ilock(&ctlr->rlock); - status = csr16r(ctlr, Status); - csr8w(ctlr, Ack, (status>>8) & 0xFF); - iunlock(&ctlr->rlock); - - if(!(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI))) - break; - - /* - * If the watchdog timer for the receiver lockup errata is running, - * let it know the receiver is active. - */ - if(status & (StatFR|StatRNR)){ - ilock(&ctlr->cblock); - ctlr->tick = 0; - iunlock(&ctlr->cblock); - } - - if(status & StatFR){ - receive(ether); - status &= ~StatFR; - } - - if(status & StatRNR){ - command(ctlr, RUresume, 0); - status &= ~StatRNR; - } - - if(status & StatCNA){ - ilock(&ctlr->cblock); - - cb = ctlr->cbtail; - while(ctlr->cbq){ - if(!(cb->status & CbC)) - break; - if(cb->bp){ - freeb(cb->bp); - cb->bp = nil; - } - if((cb->status & CbU) && ctlr->threshold < 0xE0) - ctlr->threshold++; - - ctlr->cbq--; - cb = cb->next; - } - ctlr->cbtail = cb; - - txstart(ether); - iunlock(&ctlr->cblock); - - status &= ~StatCNA; - } - - if(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI)) - panic("#l%d: status %#ux\n", ether->ctlrno, status); - } -} - -static void -ctlrinit(Ctlr* ctlr) -{ - int i; - Block *bp; - Rfd *rfd; - ulong link; - - /* - * Create the Receive Frame Area (RFA) as a ring of allocated - * buffers. - * A sentinel buffer is maintained between the last buffer in - * the ring (marked with RfdS) and the head buffer to defeat the - * hardware prefetch of the next RFD and allow dynamic buffer - * allocation. - */ - link = NullPointer; - for(i = 0; i < Nrfd; i++){ - bp = rfdalloc(link); - if(ctlr->rfdhead == nil) - ctlr->rfdtail = bp; - bp->next = ctlr->rfdhead; - ctlr->rfdhead = bp; - link = PADDR(bp->rp); - } - ctlr->rfdtail->next = ctlr->rfdhead; - rfd = (Rfd*)ctlr->rfdtail->rp; - rfd->link = PADDR(ctlr->rfdhead->rp); - rfd->field |= RfdS; - ctlr->rfdhead = ctlr->rfdhead->next; - - /* - * Create a ring of control blocks for the - * transmit side. - */ - ilock(&ctlr->cblock); - ctlr->cbr = malloc(ctlr->ncb*sizeof(Cb)); - for(i = 0; i < ctlr->ncb; i++){ - ctlr->cbr[i].status = CbC|CbOK; - ctlr->cbr[i].command = CbS|CbNOP; - ctlr->cbr[i].link = PADDR(&ctlr->cbr[NEXT(i, ctlr->ncb)].status); - ctlr->cbr[i].next = &ctlr->cbr[NEXT(i, ctlr->ncb)]; - } - ctlr->cbhead = ctlr->cbr; - ctlr->cbtail = ctlr->cbr; - ctlr->cbq = 0; - - memmove(ctlr->configdata, configdata, sizeof(configdata)); - ctlr->threshold = 80; - ctlr->tick = 0; - - iunlock(&ctlr->cblock); -} - -static int -miir(Ctlr* ctlr, int phyadd, int regadd) -{ - int mcr, timo; - - lock(&ctlr->miilock); - 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); - } - unlock(&ctlr->miilock); - - if(mcr & MDIready) - return mcr & 0xFFFF; - - return -1; -} - -static int -miiw(Ctlr* ctlr, int phyadd, int regadd, int data) -{ - int mcr, timo; - - lock(&ctlr->miilock); - 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); - } - unlock(&ctlr->miilock); - - 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<eepromsz == 0){ - ctlr->eepromsz = 8-size; - ctlr->eeprom = malloc((1<eepromsz)*sizeof(ushort)); - goto reread; - } - - return data; -} - -static void -i82557pci(void) -{ - Pcidev *p; - Ctlr *ctlr; - int i, nop, port; - - p = nil; - nop = 0; - while(p = pcimatch(p, 0x8086, 0)){ - switch(p->did){ - default: - continue; - case 0x1031: /* Intel 82562EM */ - case 0x1050: /* Intel 82562EZ */ - case 0x1039: /* Intel 82801BD PRO/100 VE */ - case 0x103A: /* Intel 82562 PRO/100 VE */ - case 0x103D: /* Intel 82562 PRO/100 VE */ - case 0x1064: /* Intel 82562 PRO/100 VE */ - case 0x2449: /* Intel 82562ET */ - nop = 1; - /*FALLTHROUGH*/ - case 0x1209: /* Intel 82559ER */ - case 0x1229: /* Intel 8255[789] */ - case 0x1030: /* Intel 82559 InBusiness 10/100 */ - break; - } - - 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); - } - - /* - * 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). - */ - port = p->mem[1].bar & ~0x01; - if(ioalloc(port, p->mem[1].size, 0, "i82557") < 0){ - print("i82557: port %#ux in use\n", port); - continue; - } - - ctlr = malloc(sizeof(Ctlr)); - ctlr->port = port; - ctlr->pcidev = p; - ctlr->nop = nop; - - if(ctlrhead != nil) - ctlrtail->next = ctlr; - else - ctlrhead = ctlr; - ctlrtail = ctlr; - - pcisetbme(p); - } -} - -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 -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)); - - ctlr->eeprom[6] = i; - 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; -} - -static void -shutdown(Ether* ether) -{ - Ctlr *ctlr = ether->ctlr; - -print("ether82557 shutting down\n"); - csr32w(ctlr, Port, 0); - delay(1); - csr8w(ctlr, Interrupt, InterruptM); -} - - -static int -reset(Ether* ether) -{ - int anar, anlpar, bmcr, bmsr, i, k, medium, phyaddr, x; - unsigned short sum; - uchar ea[Eaddrlen]; - Ctlr *ctlr; - - 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 should 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; - - ilock(&ctlr->rlock); - csr32w(ctlr, Port, 0); - delay(1); - csr8w(ctlr, Interrupt, InterruptM); - iunlock(&ctlr->rlock); - - command(ctlr, LoadRUB, 0); - command(ctlr, LoadCUB, 0); - command(ctlr, LoadDCA, PADDR(ctlr->dump)); - - /* - * Initialise the receive frame, transmit ring and configuration areas. - */ - ctlr->ncb = Ncb; - 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<eepromsz); i++){ - x = hy93c46r(ctlr, i); - ctlr->eeprom[i] = x; - sum += x; - } - if(sum != 0xBABA) - print("#l%d: EEPROM checksum - %#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. - */ - miir(ctlr, phyaddr, 0x01); - 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){ - medium = -1; - for(i = 0; i < ether->nopt; i++){ - for(k = 0; k < nelem(mediatable); k++){ - if(cistrcmp(mediatable[k], ether->opt[i])) - continue; - medium = k; - break; - } - - switch(medium){ - default: - break; - - case 0x00: /* 10BASE-T */ - case 0x01: /* 10BASE-2 */ - case 0x02: /* 10BASE-5 */ - bmcr &= ~(0x2000|0x0100); - ctlr->configdata[19] &= ~0x40; - break; - - case 0x03: /* 100BASE-TX */ - case 0x06: /* 100BASE-T4 */ - case 0x07: /* 100BASE-FX */ - ctlr->configdata[19] &= ~0x40; - bmcr |= 0x2000; - break; - - case 0x04: /* 10BASE-TFD */ - bmcr = (bmcr & ~0x2000)|0x0100; - ctlr->configdata[19] |= 0x40; - break; - - case 0x05: /* 100BASE-TXFD */ - case 0x08: /* 100BASE-FXFD */ - bmcr |= 0x2000|0x0100; - ctlr->configdata[19] |= 0x40; - break; - } - } - if(medium != -1) - miiw(ctlr, phyaddr, 0x00, bmcr); - } - - if(bmcr & 0x2000) - ether->mbps = 100; - - ctlr->configdata[8] = 1; - ctlr->configdata[15] &= ~0x80; - } - else{ - ctlr->configdata[8] = 0; - ctlr->configdata[15] |= 0x80; - } - - /* - * Workaround for some broken HUB chips when connected at 10Mb/s - * half-duplex. - * This is a band-aid, but as there's no dynamic auto-negotiation - * code at the moment, only deactivate the workaround code in txstart - * if the link is 100Mb/s. - */ - if(ether->mbps != 10) - ctlr->nop = 0; - - /* - * Load the chip configuration and start it off. - */ - if(ether->oq == 0) - ether->oq = qopen(256*1024, Qmsg, 0, 0); - configure(ether, 0); - command(ctlr, CUstart, PADDR(&ctlr->cbr->status)); - - /* - * 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; - ether->ea[2*i+1] = x>>8; - } - } - - ilock(&ctlr->cblock); - ctlr->action = CbIAS; - txstart(ether); - iunlock(&ctlr->cblock); - - /* - * Linkage to the generic ethernet driver. - */ - ether->attach = attach; - ether->transmit = transmit; - ether->interrupt = interrupt; - ether->ifstat = ifstat; - ether->shutdown = shutdown; - - ether->promiscuous = promiscuous; - ether->multicast = multicast; - ether->arg = ether; - - return 0; -} - -void -ether82557link(void) -{ - addethercard("i82557", reset); -} diff --git a/os/pc/ether83815.c b/os/pc/ether83815.c deleted file mode 100644 index 3d2d9d76..00000000 --- a/os/pc/ether83815.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* - * National Semiconductor DP83815 - * - * Supports only internal PHY and has been tested on: - * Netgear FA311TX (using Netgear DS108 10/100 hub) - * To do: - * check Ethernet address; - * test autonegotiation on 10 Mbit, and 100 Mbit full duplex; - * external PHY via MII (should be common code for MII); - * thresholds; - * ring sizing; - * physical link changes/disconnect; - * push initialisation back to attach. - * - * C H Forsyth, forsyth@vitanuova.com, 18th June 2001. - */ - -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" - -#include "etherif.h" - -#define DEBUG (0) -#define debug if(DEBUG)print - -enum { - Nrde = 64, - Ntde = 64, -}; - -#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 */ -}; - -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 lock; - - 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; - - ulong rxa; /* receive statistics */ - ulong rxo; - ulong rlong; - ulong runt; - ulong ise; - ulong crce; - ulong fae; - ulong lbp; - ulong col; - ulong rxsovr; - ulong rxorn; - - ulong txa; /* transmit statistics */ - ulong tfu; - ulong crs; - ulong td; - ulong ed; - ulong owc; - ulong ec; - ulong txurn; - - ulong dperr; /* system errors */ - ulong rmabt; - ulong rtabt; - ulong sserr; - ulong rxsover; -} Ctlr; - -static Ctlr* ctlrhead; -static Ctlr* ctlrtail; - -enum { - /* registers (could memory map) */ - Rcr= 0x00, /* command register */ - Rst= 1<<8, - Rxr= 1<<5, /* receiver reset */ - Txr= 1<<4, /* transmitter reset */ - Rxd= 1<<3, /* receiver disable */ - Rxe= 1<<2, /* receiver enable */ - Txd= 1<<1, /* transmitter disable */ - Txe= 1<<0, /* transmitter enable */ - Rcfg= 0x04, /* configuration */ - Lnksts= 1<<31, /* link good */ - Speed100= 1<<30, /* 100 Mb/s link */ - Fdup= 1<<29, /* full duplex */ - Pol= 1<<28, /* polarity reversal (10baseT) */ - Aneg_dn= 1<<27, /* autonegotiation done */ - Pint_acen= 1<<17, /* PHY interrupt auto clear enable */ - Pause_adv= 1<<16, /* advertise pause during auto neg */ - Paneg_ena= 1<<13, /* auto negotiation enable */ - Paneg_all= 7<<13, /* auto negotiation enable 10/100 half & full */ - Ext_phy= 1<<12, /* enable MII for external PHY */ - Phy_rst= 1<<10, /* reset internal PHY */ - Phy_dis= 1<<9, /* disable internal PHY (eg, low power) */ - Req_alg= 1<<7, /* PCI bus request: set means less aggressive */ - Sb= 1<<6, /* single slot back-off not random */ - Pow= 1<<5, /* out of window timer selection */ - Exd= 1<<4, /* disable excessive deferral timer */ - Pesel= 1<<3, /* parity error algorithm selection */ - Brom_dis= 1<<2, /* disable boot rom interface */ - Bem= 1<<0, /* big-endian mode */ - Rmear= 0x08, /* eeprom access */ - Mdc= 1<<6, /* MII mangement check */ - Mddir= 1<<5, /* MII management direction */ - Mdio= 1<<4, /* MII mangement data */ - Eesel= 1<<3, /* EEPROM chip select */ - Eeclk= 1<<2, /* EEPROM clock */ - Eedo= 1<<1, /* EEPROM data out (from chip) */ - Eedi= 1<<0, /* EEPROM data in (to chip) */ - Rptscr= 0x0C, /* pci test control */ - Risr= 0x10, /* interrupt status */ - Txrcmp= 1<<25, /* transmit reset complete */ - Rxrcmp= 1<<24, /* receiver reset complete */ - Dperr= 1<<23, /* detected parity error */ - Sserr= 1<<22, /* signalled system error */ - Rmabt= 1<<21, /* received master abort */ - Rtabt= 1<<20, /* received target abort */ - Rxsovr= 1<<16, /* RX status FIFO overrun */ - Hiberr= 1<<15, /* high bits error set (OR of 25-16) */ - Phy= 1<<14, /* PHY interrupt */ - Pme= 1<<13, /* power management event (wake online) */ - Swi= 1<<12, /* software interrupt */ - Mib= 1<<11, /* MIB service */ - Txurn= 1<<10, /* TX underrun */ - Txidle= 1<<9, /* TX idle */ - Txerr= 1<<8, /* TX packet error */ - Txdesc= 1<<7, /* TX descriptor (with Intr bit done) */ - Txok= 1<<6, /* TX ok */ - Rxorn= 1<<5, /* RX overrun */ - Rxidle= 1<<4, /* RX idle */ - Rxearly= 1<<3, /* RX early threshold */ - Rxerr= 1<<2, /* RX packet error */ - Rxdesc= 1<<1, /* RX descriptor (with Intr bit done) */ - Rxok= 1<<0, /* RX ok */ - Rimr= 0x14, /* interrupt mask */ - Rier= 0x18, /* interrupt enable */ - Ie= 1<<0, /* interrupt enable */ - Rtxdp= 0x20, /* transmit descriptor pointer */ - Rtxcfg= 0x24, /* transmit configuration */ - Csi= 1<<31, /* carrier sense ignore (needed for full duplex) */ - Hbi= 1<<30, /* heartbeat ignore (needed for full duplex) */ - Atp= 1<<28, /* automatic padding of runt packets */ - Mxdma= 7<<20, /* maximum dma transfer field */ - Mxdma32= 4<<20, /* 4x32-bit words (32 bytes) */ - Mxdma64= 5<<20, /* 8x32-bit words (64 bytes) */ - Flth= 0x3F<<8,/* Tx fill threshold, units of 32 bytes (must be > Mxdma) */ - Drth= 0x3F<<0,/* Tx drain threshold (units of 32 bytes) */ - Flth128= 4<<8, /* fill at 128 bytes */ - Drth512= 16<<0, /* drain at 512 bytes */ - Rrxdp= 0x30, /* receive descriptor pointer */ - Rrxcfg= 0x34, /* receive configuration */ - Atx= 1<<28, /* accept transmit packets (needed for full duplex) */ - Rdrth= 0x1F<<1,/* Rx drain threshold (units of 32 bytes) */ - Rdrth64= 2<<1, /* drain at 64 bytes */ - Rccsr= 0x3C, /* CLKRUN control/status */ - Pmests= 1<<15, /* PME status */ - Rwcsr= 0x40, /* wake on lan control/status */ - Rpcr= 0x44, /* pause control/status */ - Rrfcr= 0x48, /* receive filter/match control */ - Rfen= 1<<31, /* receive filter enable */ - Aab= 1<<30, /* accept all broadcast */ - Aam= 1<<29, /* accept all multicast */ - Aau= 1<<28, /* accept all unicast */ - Apm= 1<<27, /* accept on perfect match */ - Apat= 0xF<<23,/* accept on pattern match */ - Aarp= 1<<22, /* accept ARP */ - Mhen= 1<<21, /* multicast hash enable */ - Uhen= 1<<20, /* unicast hash enable */ - Ulm= 1<<19, /* U/L bit mask */ - /* bits 0-9 are rfaddr */ - Rrfdr= 0x4C, /* receive filter/match data */ - Rbrar= 0x50, /* boot rom address */ - Rbrdr= 0x54, /* boot rom data */ - Rsrr= 0x58, /* silicon revision */ - Rmibc= 0x5C, /* MIB control */ - /* 60-78 MIB data */ - - /* PHY registers */ - Rbmcr= 0x80, /* basic mode configuration */ - Reset= 1<<15, - Sel100= 1<<13, /* select 100Mb/sec if no auto neg */ - Anena= 1<<12, /* auto negotiation enable */ - Anrestart= 1<<9, /* restart auto negotiation */ - Selfdx= 1<<8, /* select full duplex if no auto neg */ - Rbmsr= 0x84, /* basic mode status */ - Ancomp= 1<<5, /* autonegotiation complete */ - Rphyidr1= 0x88, - Rphyidr2= 0x8C, - Ranar= 0x90, /* autonegotiation advertisement */ - Ranlpar= 0x94, /* autonegotiation link partner ability */ - Raner= 0x98, /* autonegotiation expansion */ - Rannptr= 0x9C, /* autonegotiation next page TX */ - Rphysts= 0xC0, /* PHY status */ - Rmicr= 0xC4, /* MII control */ - Inten= 1<<1, /* PHY interrupt enable */ - Rmisr= 0xC8, /* MII status */ - Rfcscr= 0xD0, /* false carrier sense counter */ - Rrecr= 0xD4, /* receive error counter */ - Rpcsr= 0xD8, /* 100Mb config/status */ - Rphycr= 0xE4, /* PHY control */ - Rtbscr= 0xE8, /* 10BaseT status/control */ -}; - -/* - * eeprom addresses - * 7 to 9 (16 bit words): mac address, shifted and reversed - */ - -#define csr32r(c, r) (inl((c)->port+(r))) -#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l))) -#define csr16r(c, r) (ins((c)->port+(r))) -#define csr16w(c, r, l) (outs((c)->port+(r), (ulong)(l))) - -static void -dumpcregs(Ctlr *ctlr) -{ - int i; - - for(i=0; i<=0x5C; i+=4) - print("%2.2ux %8.8lux\n", i, csr32r(ctlr, i)); -} - -static void -promiscuous(void* arg, int on) -{ - Ctlr *ctlr; - ulong w; - - ctlr = ((Ether*)arg)->ctlr; - ilock(&ctlr->lock); - w = csr32r(ctlr, Rrfcr); - if(on != ((w&Aau)!=0)){ - csr32w(ctlr, Rrfcr, w & ~Rfen); - csr32w(ctlr, Rrfcr, Rfen | (w ^ Aau)); - } - iunlock(&ctlr->lock); -} - -static void -attach(Ether* ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ilock(&ctlr->lock); - if(0) - dumpcregs(ctlr); - csr32w(ctlr, Rcr, Rxe); - iunlock(&ctlr->lock); -} - -static long -ifstat(Ether* ether, void* a, long n, ulong offset) -{ - Ctlr *ctlr; - char *buf, *p; - int i, l, len; - - ctlr = ether->ctlr; - - ether->crcs = ctlr->crce; - ether->frames = ctlr->runt+ctlr->ise+ctlr->rlong+ctlr->fae; - ether->buffs = ctlr->rxorn+ctlr->tfu; - ether->overflows = ctlr->rxsovr; - - if(n == 0) - return 0; - - p = malloc(READSTR); - l = snprint(p, READSTR, "Rxa: %lud\n", ctlr->rxa); - l += snprint(p+l, READSTR-l, "Rxo: %lud\n", ctlr->rxo); - l += snprint(p+l, READSTR-l, "Rlong: %lud\n", ctlr->rlong); - l += snprint(p+l, READSTR-l, "Runt: %lud\n", ctlr->runt); - l += snprint(p+l, READSTR-l, "Ise: %lud\n", ctlr->ise); - l += snprint(p+l, READSTR-l, "Fae: %lud\n", ctlr->fae); - l += snprint(p+l, READSTR-l, "Lbp: %lud\n", ctlr->lbp); - l += snprint(p+l, READSTR-l, "Tfu: %lud\n", ctlr->tfu); - l += snprint(p+l, READSTR-l, "Txa: %lud\n", ctlr->txa); - l += snprint(p+l, READSTR-l, "CRC Error: %lud\n", ctlr->crce); - l += snprint(p+l, READSTR-l, "Collision Seen: %lud\n", ctlr->col); - l += snprint(p+l, READSTR-l, "Frame Too Long: %lud\n", ctlr->rlong); - l += snprint(p+l, READSTR-l, "Runt Frame: %lud\n", ctlr->runt); - l += snprint(p+l, READSTR-l, "Rx Underflow Error: %lud\n", ctlr->rxorn); - l += snprint(p+l, READSTR-l, "Tx Underrun: %lud\n", ctlr->txurn); - l += snprint(p+l, READSTR-l, "Excessive Collisions: %lud\n", ctlr->ec); - l += snprint(p+l, READSTR-l, "Late Collision: %lud\n", ctlr->owc); - l += snprint(p+l, READSTR-l, "Loss of Carrier: %lud\n", ctlr->crs); - l += snprint(p+l, READSTR-l, "Parity: %lud\n", ctlr->dperr); - l += snprint(p+l, READSTR-l, "Aborts: %lud\n", ctlr->rmabt+ctlr->rtabt); - l += snprint(p+l, READSTR-l, "RX Status overrun: %lud\n", ctlr->rxsover); - snprint(p+l, READSTR-l, "ntqmax: %d\n", ctlr->ntqmax); - ctlr->ntqmax = 0; - buf = a; - len = readstr(offset, buf, n, p); - if(offset > l) - offset -= l; - else - offset = 0; - buf += len; - n -= len; - - l = snprint(p, READSTR, "srom:"); - for(i = 0; i < nelem(ctlr->srom); i++){ - if(i && ((i & 0x0F) == 0)) - l += snprint(p+l, READSTR-l, "\n "); - l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->srom[i]); - } - - snprint(p+l, READSTR-l, "\n"); - len += readstr(offset, buf, n, p); - free(p); - - return len; -} - -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 = qget(ether->oq); - if(bp == nil) - break; - 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; - - ctlr = ether->ctlr; - ilock(&ctlr->tlock); - txstart(ether); - 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) -{ - int len, status, cmdsts, n; - Ctlr *ctlr; - Ether *ether; - Des *des; - Block *bp; - - ether = arg; - ctlr = ether->ctlr; - - while((status = csr32r(ctlr, Risr)) != 0){ - - status &= ~(Pme|Mib); - - if(status & Hiberr){ - if(status & Rxsovr) - ctlr->rxsover++; - if(status & Sserr) - ctlr->sserr++; - if(status & Dperr) - ctlr->dperr++; - if(status & Rmabt) - ctlr->rmabt++; - if(status & Rtabt) - ctlr->rtabt++; - status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt); - } - - /* update link state */ - if(status&Phy){ - status &= ~Phy; - csr32r(ctlr, Rcfg); - n = csr32r(ctlr, Rcfg); -// iprint("83815 phy %x %x\n", n, n&Lnksts); - ether->link = (n&Lnksts) != 0; - } - - /* - * Received packets. - */ - if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){ - des = &ctlr->rdr[ctlr->rdrx]; - while((cmdsts = des->cmdsts) & Own){ - if((cmdsts&Ok) == 0){ - if(cmdsts & Rxa) - ctlr->rxa++; - if(cmdsts & Rxo) - ctlr->rxo++; - if(cmdsts & Long) - ctlr->rlong++; - if(cmdsts & Runt) - ctlr->runt++; - if(cmdsts & Ise) - ctlr->ise++; - if(cmdsts & Crce) - ctlr->crce++; - if(cmdsts & Fae) - ctlr->fae++; - if(cmdsts & Lbp) - ctlr->lbp++; - if(cmdsts & Col) - ctlr->col++; - } - else if(bp = iallocb(Rbsz)){ - len = (cmdsts&Size)-4; - if(len <= 0){ - debug("ns83815: packet len %d <=0\n", len); - freeb(des->bp); - }else{ - des->bp->wp = des->bp->rp+len; - etheriq(ether, des->bp, 1); - } - des->bp = bp; - des->addr = PADDR(bp->rp); - coherence(); - }else{ - debug("ns83815: interrupt: iallocb for input buffer failed\n"); - des->bp->next = 0; - } - - 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->lock); - /* change threshold */ - iunlock(&ctlr->lock); - status &= ~(Txurn); - } - - ilock(&ctlr->tlock); - while(ctlr->ntq){ - des = &ctlr->tdr[ctlr->tdri]; - cmdsts = des->cmdsts; - if(cmdsts & Own) - break; - - if((cmdsts & Ok) == 0){ - if(cmdsts & Txa) - ctlr->txa++; - if(cmdsts & Tfu) - ctlr->tfu++; - if(cmdsts & Td) - ctlr->td++; - if(cmdsts & Ed) - ctlr->ed++; - if(cmdsts & Owc) - ctlr->owc++; - if(cmdsts & Ec) - ctlr->ec++; - ether->oerrs++; - } - - 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 suitable aligned descriptors - * for the transmit and receive rings; - * initialise the receive ring; - * initialise the transmit ring; - * unmask interrupts and start the transmit side. - */ - des = xspanalloc((ctlr->nrdr+ctlr->ntdr)*sizeof(Des), 32, 0); - ctlr->tdr = des; - ctlr->rdr = des+ctlr->ntdr; - - last = nil; - for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){ - des->bp = iallocb(Rbsz); - if(des->bp == nil) - error(Enomem); - 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)); - - 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 */ - csr32w(ctlr, Rmicr, Inten); /* enable phy interrupts */ - csr32r(ctlr, Risr); /* clear status */ - csr32w(ctlr, Rier, Ie); -} - -static void -eeclk(Ctlr *ctlr, int clk) -{ - csr32w(ctlr, Rmear, Eesel | clk); - microdelay(2); -} - -static void -eeidle(Ctlr *ctlr) -{ - int i; - - eeclk(ctlr, 0); - eeclk(ctlr, Eeclk); - for(i=0; i<25; i++){ - eeclk(ctlr, 0); - eeclk(ctlr, Eeclk); - } - eeclk(ctlr, 0); - csr32w(ctlr, Rmear, 0); - microdelay(2); -} - -static int -eegetw(Ctlr *ctlr, int a) -{ - int d, i, w, v; - - eeidle(ctlr); - eeclk(ctlr, 0); - eeclk(ctlr, Eeclk); - d = 0x180 | a; - for(i=0x400; i; i>>=1){ - v = (d & i) ? Eedi : 0; - eeclk(ctlr, v); - eeclk(ctlr, Eeclk|v); - } - eeclk(ctlr, 0); - - w = 0; - for(i=0x8000; i; i >>= 1){ - eeclk(ctlr, Eeclk); - if(csr32r(ctlr, Rmear) & Eedo) - w |= i; - microdelay(2); - eeclk(ctlr, 0); - } - eeidle(ctlr); - return w; -} - -static void -resetctlr(Ctlr *ctlr) -{ - int i; - - csr32w(ctlr, Rcr, Rst); - for(i=0;; i++){ - if(i > 100) - panic("ns83815: soft reset did not complete"); - microdelay(250); - if((csr32r(ctlr, Rcr) & Rst) == 0) - break; - delay(1); - } -} - -static void -shutdown(Ether* ether) -{ - Ctlr *ctlr = ether->ctlr; - -print("ether83815 shutting down\n"); - csr32w(ctlr, Rcr, Rxd|Txd); /* disable transceiver */ - resetctlr(ctlr); -} - -static void -softreset(Ctlr* ctlr, int resetphys) -{ - int i, w; - - /* - * Soft-reset the controller - */ - resetctlr(ctlr); - csr32w(ctlr, Rccsr, Pmests); - csr32w(ctlr, Rccsr, 0); - csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen); - - if(resetphys){ - /* - * Soft-reset the PHY - */ - csr32w(ctlr, Rbmcr, Reset); - for(i=0;; i++){ - if(i > 100) - panic("ns83815: PHY soft reset time out"); - if((csr32r(ctlr, Rbmcr) & Reset) == 0) - break; - delay(1); - } - } - - /* - * Initialisation values, in sequence (see 4.4 Recommended Registers Configuration) - */ - csr16w(ctlr, 0xCC, 0x0001); /* PGSEL */ - csr16w(ctlr, 0xE4, 0x189C); /* PMCCSR */ - csr16w(ctlr, 0xFC, 0x0000); /* TSTDAT */ - csr16w(ctlr, 0xF4, 0x5040); /* DSPCFG */ - csr16w(ctlr, 0xF8, 0x008C); /* SDCFG */ - - /* - * Auto negotiate - */ - w = csr16r(ctlr, Rbmsr); /* clear latched bits */ - debug("anar: %4.4ux\n", csr16r(ctlr, Ranar)); - csr16w(ctlr, Rbmcr, Anena); - if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){ - csr16w(ctlr, Rbmcr, Anena|Anrestart); - for(i=0;; i++){ - if(i > 3000){ - print("ns83815: auto neg timed out\n"); - break; - } - if((w = csr16r(ctlr, Rbmsr)) & Ancomp) - break; - delay(1); - } - debug("%d ms\n", i); - w &= 0xFFFF; - debug("bmsr: %4.4ux\n", w); - } - 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)); -} - -static int -media(Ether* ether) -{ - Ctlr* ctlr; - ulong cfg; - - ctlr = ether->ctlr; - cfg = csr32r(ctlr, Rcfg); - ctlr->fd = (cfg & Fdup) != 0; - ether->link = (cfg&Lnksts) != 0; - return (cfg&(Lnksts|Speed100)) == Lnksts? 10: 100; -} - -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 */ -}; - -/* 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); - } -} - -static void -nssrom(Ctlr* ctlr) -{ - int i, j; - - for(i = 0; i < nelem(ctlr->srom); i++) - ctlr->srom[i] = eegetw(ctlr, i); - - /* - * the MAC address is reversed, straddling word boundaries - */ - 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 -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; - ulong id; - - p = nil; - while(p = pcimatch(p, 0, 0)){ - if(p->ccrb != Pcibcnet || p->ccru != 0) - continue; - id = (p->did<<16)|p->vid; - switch(id){ - default: - continue; - - case Nat83815: - break; - 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 = id; - - if(ioalloc(ctlr->port, p->mem[0].size, 0, "ns83815") < 0){ - print("ns83815: port 0x%uX in use\n", ctlr->port); - free(ctlr); - continue; - } - - softreset(ctlr, 0); - srom(ctlr); - - if(ctlrhead != nil) - ctlrtail->next = ctlr; - else - ctlrhead = ctlr; - ctlrtail = ctlr; - } -} - -/* multicast already on, don't need to do anything */ -static void -multicast(void*, uchar*, int) -{ -} - -static int -reset(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; iea[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); - - ether->mbps = media(ether); - - /* - * 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){ - if(x != 4 && x >= 3) - ether->mbps = 100; - else - ether->mbps = 10; - 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->ifstat = ifstat; - - ether->arg = ether; - ether->promiscuous = promiscuous; - ether->multicast = multicast; - ether->shutdown = shutdown; - return 0; -} - -void -ether83815link(void) -{ - addethercard("83815", reset); -} diff --git a/os/pc/ether8390.c b/os/pc/ether8390.c deleted file mode 100644 index 50d7ce39..00000000 --- a/os/pc/ether8390.c +++ /dev/null @@ -1,812 +0,0 @@ -/* - * National Semiconductor DP8390 and clone - * Network Interface Controller. - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.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 */ - Ref0 = 0x0D, /* frame alignment errors */ - Ref1 = 0x0E, /* CRC errors */ - Ref2 = 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 Hdr Hdr; -struct Hdr { - uchar status; - uchar next; - uchar len0; - uchar len1; -}; - -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 %lud to %lud\n", crda, to); - - break; - } - } - } - else{ - regw(ctlr, Rsar0, to & 0xFF); - regw(ctlr, Rsar1, (to>>8) & 0xFF); - regw(ctlr, Rbcr0, len & 0xFF); - regw(ctlr, Rbcr1, (len>>8) & 0xFF); - regw(ctlr, Cr, Page0|RdWRITE|Sta); - } - - /* - * Pump the data into the I/O port - * then wait for the remote DMA to finish. - */ - rdwrite(ctlr, from, len); - for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--) - ; - - regw(ctlr, Isr, Rdc); - regw(ctlr, Cr, cr); - - return (void*)to; -} - -static void -ringinit(Dp8390* ctlr) -{ - regw(ctlr, Pstart, ctlr->pstart); - regw(ctlr, Pstop, ctlr->pstop); - regw(ctlr, Bnry, ctlr->pstop-1); - - regw(ctlr, Cr, Page1|RdABORT|Stp); - regw(ctlr, Curr, ctlr->pstart); - regw(ctlr, Cr, Page0|RdABORT|Stp); - - ctlr->nxtpkt = ctlr->pstart; -} - -static uchar -getcurr(Dp8390* ctlr) -{ - uchar cr, curr; - - cr = regr(ctlr, Cr) & ~Txp; - regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr)); - curr = regr(ctlr, Curr); - regw(ctlr, Cr, cr); - - return curr; -} - -static void -receive(Ether* ether) -{ - Dp8390 *ctlr; - uchar curr, *p; - Hdr hdr; - ulong count, data, len; - Block *bp; - - 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. - */ - if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && (bp = iallocb(len))){ - p = bp->rp; - bp->wp = p+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. - */ - etheriq(ether, bp, 1); - } - - /* - * 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; - Block *bp; - 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(ctlr->txbusy) - return; - bp = qget(ether->oq); - if(bp == nil) - return; - - /* - * Make sure the packet is of minimum length; - * copy it to the card's memory by the appropriate means; - * start the transmission. - */ - len = BLEN(bp); - rp = bp->rp; - if(len < ETHERMINTU){ - rp = minpkt; - memmove(rp, bp->rp, 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); - freeb(bp); - - regw(ctlr, Tbcr0, len & 0xFF); - regw(ctlr, Tbcr1, (len>>8) & 0xFF); - regw(ctlr, Cr, Page0|RdABORT|Txp|Sta); - - ether->outpackets++; - ctlr->txbusy = 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; - 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); - ether->overflows++; - } - - /* - * 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); - ether->oerrs++; - } - - regw(ctlr, Isr, Txe|Ptx); - - if(isr & Ptx) - ether->outpackets++; - ctlr->txbusy = 0; - txstart(ether); - } - - if(isr & Cnt){ - ether->frames += regr(ctlr, Ref0); - ether->crcs += regr(ctlr, Ref1); - ether->buffs += regr(ctlr, Ref2); - regw(ctlr, Isr, Cnt); - } - } - regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx); - iunlock(ctlr); -} - -static uchar allmar[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - -static void -setfilter(Ether *ether, Dp8390 *ctlr) -{ - uchar r, cr; - int i; - uchar *mar; - - r = Ab; - mar = 0; - if(ether->prom){ - r |= Pro|Am; - mar = allmar; - } else if(ether->nmaddr){ - r |= Am; - mar = ctlr->mar; - } - if(mar){ - cr = regr(ctlr, Cr) & ~Txp; - regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr)); - for(i = 0; i < 8; i++) - regw(ctlr, Mar0+i, *(mar++)); - regw(ctlr, Cr, cr); - } - regw(ctlr, Rcr, r); -} - -static void -promiscuous(void *arg, int ) -{ - Ether *ether; - Dp8390 *ctlr; - - ether = arg; - ctlr = ether->ctlr; - - ilock(ctlr); - setfilter(ether, ctlr); - iunlock(ctlr); -} - -static void -setbit(Dp8390 *ctlr, int bit, int on) -{ - int i, h; - - i = bit/8; - h = bit%8; - if(on){ - if(++(ctlr->mref[bit]) == 1) - ctlr->mar[i] |= 1<mref[bit]) <= 0){ - ctlr->mref[bit] = 0; - ctlr->mar[i] &= ~(1<ctlr; - if(reverse[1] == 0){ - for(i = 0; i < 64; i++) - reverse[i] = ((i&1)<<5) | ((i&2)<<3) | ((i&4)<<1) - | ((i&8)>>1) | ((i&16)>>3) | ((i&32)>>5); - } - - /* - * change filter bits - */ - h = ethercrc(addr, 6); - ilock(ctlr); - setbit(ctlr, reverse[h&0x3f], on); - setfilter(ether, ctlr); - 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; - if(ether->prom) - r |= Pro; - if(ether->nmaddr) - r |= Am; - ilock(ctlr); - regw(ctlr, Isr, 0xFF); - regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx); - regw(ctlr, Rcr, r); - r = regr(ctlr, Ref2); - regw(ctlr, Tcr, LpbkNORMAL); - iunlock(ctlr); - USED(r); -} - -static void -disable(Dp8390* ctlr) -{ - int timo; - - /* - * 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. - */ - 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. - */ - disable(ctlr); - 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->ifstat = 0; - - ether->promiscuous = promiscuous; - ether->multicast = multicast; - ether->arg = ether; - - return 0; -} diff --git a/os/pc/ether8390.h b/os/pc/ether8390.h deleted file mode 100644 index b5bf6e55..00000000 --- a/os/pc/ether8390.h +++ /dev/null @@ -1,74 +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 */ - - uchar mar[8]; /* shadow multicast address registers */ - int mref[64]; /* reference counts for multicast groups */ -} 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/os/pc/etherdp83820.c b/os/pc/etherdp83820.c deleted file mode 100644 index aeda3713..00000000 --- a/os/pc/etherdp83820.c +++ /dev/null @@ -1,1246 +0,0 @@ -/* - * 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 "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" - -#include "etherif.h" -#include "ethermii.h" - -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 = 256, - Nrb = 4*Nrd, - Rbsz = ROUNDUP(sizeof(Etherpkt)+8, 8), - Ntd = 128, -}; - -typedef struct Ctlr Ctlr; -typedef 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; - - QLock 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; -} Ctlr; - -#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<= 0; i--){ - if(bits & (1<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)<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)<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<ilock); -} - -static void -dp83820attach(Ether* edev) -{ - Block *bp; - Ctlr *ctlr; - - ctlr = edev->ctlr; - qlock(&ctlr->alock); - if(ctlr->alloc != nil){ - qunlock(&ctlr->alock); - return; - } - - if(waserror()){ - if(ctlr->mii != nil){ - free(ctlr->mii); - ctlr->mii = nil; - } - if(ctlr->alloc != nil){ - free(ctlr->alloc); - ctlr->alloc = nil; - } - qunlock(&ctlr->alock); - nexterror(); - } - - if(!(ctlr->cfg & Tbien)){ - if((ctlr->mii = malloc(sizeof(Mii))) == nil) - error(Enomem); - ctlr->mii->ctlr = ctlr; - ctlr->mii->mir = dp83820miimir; - ctlr->mii->miw = dp83820miimiw; - if(mii(ctlr->mii, ~0) == 0) - error("no PHY"); - ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien; - ctlr->imr |= Phy; - } - - ctlr->nrd = Nrd; - ctlr->nrb = Nrb; - ctlr->ntd = Ntd; - ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0); - if(ctlr->alloc == nil) - error(Enomem); - - for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){ - if((bp = allocb(Rbsz)) == nil) - break; - bp->free = dp83820rbfree; - dp83820rbfree(bp); - } - - dp83820init(edev); - - qunlock(&ctlr->alock); - poperror(); -} - -static void -dp83820transmit(Ether* edev) -{ - Block *bp; - Ctlr *ctlr; - Desc *desc; - 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++; - edev->oerrs++; - } - desc->bp->next = bp; - bp = desc->bp; - desc->bp = nil; - - ctlr->ntq--; - } - ctlr->tdh = x; - if(bp != nil) - freeblist(bp); - - x = ctlr->tdt; - while(ctlr->ntq < (ctlr->ntd-1)){ - if((bp = qget(edev->oq)) == nil) - break; - - desc = &ctlr->td[x]; - desc->bufptr = PCIWADDR(bp->rp); - desc->bp = bp; - ctlr->ntq++; - coherence(); - desc->cmdsts = Own|Intr|BLEN(bp); - - 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){ - bp = desc->bp; - desc->bp = nil; - bp->wp += cmdsts & SizeMASK; - etheriq(edev, bp, 1); - } - //else if(!(cmdsts & Ok)){ - // iprint("dp83820: rx %8.8uX:", cmdsts); - // bp = desc->bp; - // for(i = 0; i < 20; i++) - // iprint(" %2.2uX", bp->rp[i]); - // iprint("\n"); - //} - 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<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; - } - if(isr) - iprint("dp83820: isr %8.8uX\n", isr); - } -} - -static long -dp83820ifstat(Ether* edev, void* a, long n, ulong offset) -{ - char *p; - Ctlr *ctlr; - int i, l, r; - - ctlr = edev->ctlr; - - edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))]; - edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))]; - edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))]; - edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))]; - - if(n == 0) - return 0; - - p = malloc(READSTR); - l = 0; - for(i = 0; i < Nmibd; i++){ - r = csr32r(ctlr, Mibd+(i*sizeof(int))); - ctlr->mibd[i] += r & 0xFFFF; - if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil) - l += snprint(p+l, READSTR-l, "%s: %ud %ud\n", - dp83820mibs[i], ctlr->mibd[i], r); - } - l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle); - l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec); - l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc); - l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed); - l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs); - l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu); - l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa); - - l += snprint(p+l, READSTR, "rom:"); - for(i = 0; i < 0x10; i++){ - if(i && ((i & 0x07) == 0)) - l += snprint(p+l, READSTR-l, "\n "); - l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]); - } - l += snprint(p+l, READSTR-l, "\n"); - - if(ctlr->mii != nil && ctlr->mii->curphy != nil){ - l += snprint(p+l, READSTR, "phy:"); - for(i = 0; i < NMiiPhyr; i++){ - if(i && ((i & 0x07) == 0)) - l += snprint(p+l, READSTR-l, "\n "); - r = miimir(ctlr->mii, i); - l += snprint(p+l, READSTR-l, " %4.4uX", r); - } - snprint(p+l, READSTR-l, "\n"); - } - - n = readstr(offset, a, n, p); - free(p); - - return n; -} - -static void -dp83820promiscuous(void* arg, int on) -{ - USED(arg, on); -} - -/* multicast already on, don't need to do anything */ -static void -dp83820multicast(void*, uchar*, int) -{ -} - -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<eepromsz) == 0) - size = 8; - - for(size = size-1; size >= 0; size--){ - if(address & (1<= 0; i--){ - csr32w(ctlr, Mear, Eeclk|r); - microdelay(1); - if(csr32r(ctlr, Mear) & Eedo) - data |= (1<eepromsz == 0){ - ctlr->eepromsz = 8-size; - ctlr->eeprom = malloc((1<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. - */ - dp83820detach(ctlr); - - 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) -{ - void *mem; - Pcidev *p; - Ctlr *ctlr; - - p = nil; - while(p = pcimatch(p, 0, 0)){ - if(p->ccrb != Pcibcnet || p->ccru != Pciscether) - continue; - - switch((p->did<<16)|p->vid){ - default: - continue; - case (0x0022<<16)|0x100B: /* DP83820 (Gig-NIC) */ - break; - } - - mem = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size); - if(mem == 0){ - print("DP83820: can't map %8.8luX\n", p->mem[1].bar); - continue; - } - - ctlr = malloc(sizeof(Ctlr)); - ctlr->port = p->mem[1].bar & ~0x0F; - ctlr->pcidev = p; - ctlr->id = (p->did<<16)|p->vid; - - ctlr->nic = mem; - if(dp83820reset(ctlr)){ - free(ctlr); - continue; - } - pcisetbme(p); - - if(dp83820ctlrhead != nil) - dp83820ctlrtail->next = ctlr; - else - dp83820ctlrhead = ctlr; - dp83820ctlrtail = ctlr; - } -} - -static 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; - 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[0x0C-i]; - edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8; - } - - edev->attach = dp83820attach; - edev->transmit = dp83820transmit; - edev->interrupt = dp83820interrupt; - edev->ifstat = dp83820ifstat; - - edev->arg = edev; - edev->promiscuous = dp83820promiscuous; - edev->multicast = dp83820multicast; - edev->shutdown = dp83820shutdown; - - return 0; -} - -void -etherdp83820link(void) -{ - addethercard("DP83820", dp83820pnp); -} diff --git a/os/pc/etherec2t.c b/os/pc/etherec2t.c deleted file mode 100644 index c7625060..00000000 --- a/os/pc/etherec2t.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Supposed NE2000 PCMCIA clones, see the comments in ether2000.c - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.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 */ -}; - -typedef struct Ec2t { - char* name; - int iochecksum; -} Ec2t; - -static Ec2t ec2tpcmcia[] = { - { "EC2T", 0, }, /* Linksys Combo PCMCIA EthernetCard */ - { "PCMPC100", 1, }, /* EtherFast 10/100 PC Card */ - { "PCM100", 1, }, /* EtherFast PCM100 Card */ - { "EN2216", 0, }, /* Accton EtherPair-PCMCIA */ - { "FA410TX", 1, }, /* Netgear FA410TX */ - { "Network Everywhere", 0, }, /* Linksys NP10T 10BaseT Card */ - { "10/100 Port Attached", 1, }, /* SMC 8040TX */ - { "8041TX-10/100-PC-Card-V2", 0 }, /* SMC 8041TX */ - { "FA411", 0 }, /* Netgear FA411 PCMCIA */ - { nil, 0, }, -}; - -static int -reset(Ether* ether) -{ - ushort buf[16]; - ulong port; - Dp8390 *ctlr; - int i, slot; - uchar ea[Eaddrlen], sum, x; - Ec2t *ec2t, tmpec2t; - - /* - * 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; - for(ec2t = ec2tpcmcia; ec2t->name != nil; ec2t++){ - if((slot = pcmspecial(ec2t->name, ether)) >= 0) - break; - } - if(ec2t->name == nil){ - ec2t = &tmpec2t; - ec2t->name = nil; - ec2t->iochecksum = 0; - for(i = 0; i < ether->nopt; i++){ - if(cistrncmp(ether->opt[i], "id=", 3) == 0){ - ec2t->name = ðer->opt[i][3]; - slot = pcmspecial(ec2t->name, ether); - } - else if(cistrncmp(ether->opt[i], "iochecksum", 10) == 0) - ec2t->iochecksum = 1; - } - } - 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(ec2t->iochecksum){ - /* - * These cards have 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; -} - -void -etherec2tlink(void) -{ - addethercard("EC2T", reset); -} diff --git a/os/pc/etherelnk3.c b/os/pc/etherelnk3.c deleted file mode 100644 index 9c612b13..00000000 --- a/os/pc/etherelnk3.c +++ /dev/null @@ -1,2134 +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. - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.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 = 32, - Ndn = 64, -}; - -/* - * Up/Dn Packet Descriptors. - * The hardware info (np, control, addr, len) must be 8-byte aligned - * and this structure size must be a multiple of 8. - */ -typedef struct Pd Pd; -typedef struct Pd { - ulong np; /* next pointer */ - ulong control; /* FSH or UpPktStatus */ - ulong addr; - ulong len; - - Pd* next; - Block* bp; -} Pd; - -typedef struct Ctlr Ctlr; -typedef 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 bogusinterrupts; - 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; -} Ctlr; - -static Ctlr* ctlrhead; -static Ctlr* ctlrtail; - -static void -init905(Ctlr* ctlr) -{ - Block *bp; - Pd *pd, *prev; - - /* - * 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); - - prev = ctlr->upr; - for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){ - pd->np = PADDR(&prev->np); - pd->control = 0; - bp = iallocb(sizeof(Etherpkt)); - if(bp == nil) - panic("can't allocate ethernet receive ring"); - pd->addr = PADDR(bp->rp); - pd->len = updnLastFrag|sizeof(Etherpkt); - - pd->next = prev; - prev = pd; - pd->bp = bp; - } - ctlr->uphead = ctlr->upr; - - ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd)); - ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8); - - prev = ctlr->dnr; - for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){ - pd->next = prev; - 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; -} - -static void -promiscuous(void* arg, int on) -{ - int filter, port; - Ether *ether; - - ether = (Ether*)arg; - port = ether->port; - - filter = receiveBroadcast|receiveIndividual; - if(ether->nmaddr) - filter |= receiveMulticast; - if(on) - filter |= receiveAllFrames; - COMMAND(port, SetRxFilter, filter); -} - -static void -multicast(void* arg, uchar *addr, int on) -{ - int filter, port; - Ether *ether; - - USED(addr, on); - - ether = (Ether*)arg; - port = ether->port; - - filter = receiveBroadcast|receiveIndividual; - if(ether->nmaddr) - filter |= receiveMulticast; - if(ether->prom) - filter |= receiveAllFrames; - COMMAND(port, SetRxFilter, filter); -} - -/* 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; - - /* - * Set the receiver packet filter for this and broadcast addresses, - * set the interrupt masks for all interrupts, enable the receiver - * and transmitter. - */ - promiscuous(ether, ether->prom); - - 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; - Block *bp; - - 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(;;){ - if(ctlr->txbp){ - bp = ctlr->txbp; - ctlr->txbp = 0; - } - else{ - bp = qget(ether->oq); - if(bp == nil) - break; - } - - len = ROUNDUP(BLEN(bp), 4); - if(len+4 <= ins(port+TxFree)){ - outl(port+Fifo, BLEN(bp)); - outsl(port+Fifo, bp->rp, len/4); - - freeb(bp); - - ether->outpackets++; - } - else{ - ctlr->txbp = bp; - 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; - Block *bp; - 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; - if(pd->bp){ - freeb(pd->bp); - pd->bp = nil; - } - ctlr->dnq--; - pd = pd->next; - } - ctlr->dntail = pd; - - stalled = 0; - while(ctlr->dnq < (ctlr->ndn-1)){ - bp = qget(ether->oq); - if(bp == nil) - break; - - pd = ctlr->dnhead->next; - pd->np = 0; - pd->control = dnIndicate|BLEN(bp); - pd->addr = PADDR(bp->rp); - pd->len = updnLastFrag|BLEN(bp); - pd->bp = bp; - - 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; - Block *bp; - - 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){ - if(pd->control & upOverrun) - ether->overflows++; - if(pd->control & (upOversizedFrame|upRuntFrame)) - ether->buffs++; - if(pd->control & upAlignmentError) - ether->frames++; - if(pd->control & upCRCError) - ether->crcs++; - } - else if(bp = iallocb(sizeof(Etherpkt)+4)){ - len = pd->control & rxBytes; - pd->bp->wp = pd->bp->rp+len; - etheriq(ether, pd->bp, 1); - pd->bp = bp; - pd->addr = PADDR(bp->rp); - coherence(); - } - - 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, rxerror, rxstatus; - Ctlr *ctlr; - Block *bp; - - 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){ - if(ctlr->rxstatus9){ - switch(rxstatus & rxError9){ - - case rxOverrun9: - ether->overflows++; - break; - - case oversizedFrame9: - case runtFrame9: - ether->buffs++; - break; - - case alignmentError9: - ether->frames++; - break; - - case crcError9: - ether->crcs++; - break; - - } - } - else{ - rxerror = inb(port+RxError); - if(rxerror & rxOverrun) - ether->overflows++; - if(rxerror & (oversizedFrame|runtFrame)) - ether->buffs++; - if(rxerror & alignmentError) - ether->frames++; - if(rxerror & crcError) - ether->crcs++; - } - } - - /* - * If there was an error or a new receive buffer can't be - * allocated, discard the packet and go on to the next. - */ - if((rxstatus & rxError) || (bp = rbpalloc(iallocb)) == 0){ - COMMAND(port, RxDiscard, 0); - while(STATUS(port) & commandInProgress) - ; - - if(ctlr->busmaster == 1) - startdma(ether, PADDR(ctlr->rbp->rp)); - - continue; - } - - /* - * A valid receive packet awaits: - * if using PIO, read it into the buffer; - * discard the packet from the FIFO; - * if using busmastering, start a new transfer for - * the next packet and as a side-effect get the - * end-pointer of the one just received; - * pass the packet on to whoever wants it. - */ - if(ctlr->busmaster == 0 || ctlr->busmaster == 2){ - len = (rxstatus & rxBytes9); - ctlr->rbp->wp = ctlr->rbp->rp + len; - insl(port+Fifo, ctlr->rbp->rp, HOWMANY(len, 4)); - } - - COMMAND(port, RxDiscard, 0); - while(STATUS(port) & commandInProgress) - ; - - if(ctlr->busmaster == 1) - ctlr->rbp->wp = startdma(ether, PADDR(bp->rp)); - - etheriq(ether, ctlr->rbp, 1); - ctlr->rbp = bp; - } -} - -static int -ejectable(int did) -{ - switch (did) { - case 0x5157: - return 1; - - default: - return 0; - } -} - -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))){ - ctlr->bogusinterrupts++; - 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); - - if (status == 0xFFFF && x == 0xFFFF && ejectable(ctlr->did)) { - print("#l%d: Card ejected?\n", ether->ctlrno); - iunlock(&ctlr->wlock); - return; - } - - 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); - ether->oerrs++; - status &= ~txComplete; - status |= txAvailable; - } - - if(status & txAvailable){ - COMMAND(port, AcknowledgeInterrupt, txAvailable); - ctlr->txbusy = 0; - txstart(ether); - status &= ~txAvailable; - } - - if(status & dnComplete){ - COMMAND(port, AcknowledgeInterrupt, dnComplete); - txstart905(ether); - status &= ~dnComplete; - ctlr->dninterrupts++; - } - - if(status & updateStats){ - statistics(ether); - status &= ~updateStats; - } - - /* - * Currently, this shouldn't happen. - */ - if(status & rxEarly){ - COMMAND(port, AcknowledgeInterrupt, rxEarly); - status &= ~rxEarly; - } - - /* - * Panic if there are any interrupts not dealt with. - */ - if(status & interruptMask) - panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status); - - COMMAND(port, AcknowledgeInterrupt, interruptLatch); - if(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 long -ifstat(Ether* ether, void* a, long n, ulong offset) -{ - char *p; - int len; - Ctlr *ctlr; - - if(n == 0) - return 0; - - ctlr = ether->ctlr; - - ilock(&ctlr->wlock); - statistics(ether); - iunlock(&ctlr->wlock); - - p = malloc(READSTR); - len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts); - len += snprint(p+len, READSTR-len, "bogusinterrupts: %lud\n", ctlr->bogusinterrupts); - len += snprint(p+len, READSTR-len, "timer: %lud %lud\n", - ctlr->timer[0], ctlr->timer[1]); - len += snprint(p+len, READSTR-len, "carrierlost: %lud\n", - ctlr->stats[CarrierLost]); - len += snprint(p+len, READSTR-len, "sqeerrors: %lud\n", - ctlr->stats[SqeErrors]); - len += snprint(p+len, READSTR-len, "multiplecolls: %lud\n", - ctlr->stats[MultipleColls]); - len += snprint(p+len, READSTR-len, "singlecollframes: %lud\n", - ctlr->stats[SingleCollFrames]); - len += snprint(p+len, READSTR-len, "latecollisions: %lud\n", - ctlr->stats[LateCollisions]); - len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n", - ctlr->stats[RxOverruns]); - len += snprint(p+len, READSTR-len, "framesxmittedok: %lud\n", - ctlr->stats[FramesXmittedOk]); - len += snprint(p+len, READSTR-len, "framesrcvdok: %lud\n", - ctlr->stats[FramesRcvdOk]); - len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n", - ctlr->stats[FramesDeferred]); - len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n", - ctlr->stats[BytesRcvdOk]); - len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n", - ctlr->stats[BytesRcvdOk+1]); - - if(ctlr->upenabled){ - if(ctlr->upqmax > ctlr->upqmaxhw) - ctlr->upqmaxhw = ctlr->upqmax; - len += snprint(p+len, READSTR-len, "up: q %lud i %lud m %d h %d s %lud\n", - ctlr->upqueued, ctlr->upinterrupts, - ctlr->upqmax, ctlr->upqmaxhw, ctlr->upstalls); - ctlr->upqmax = 0; - } - if(ctlr->dnenabled){ - if(ctlr->dnqmax > ctlr->dnqmaxhw) - ctlr->dnqmaxhw = ctlr->dnqmax; - len += snprint(p+len, READSTR-len, "dn: q %lud i %lud m %d h %d\n", - ctlr->dnqueued, ctlr->dninterrupts, ctlr->dnqmax, ctlr->dnqmaxhw); - ctlr->dnqmax = 0; - } - - snprint(p+len, READSTR-len, "badssd: %lud\n", ctlr->stats[BytesRcvdOk+2]); - - n = readstr(offset, a, n, p); - free(p); - - return n; -} - -static void -txrxreset(int port) -{ - COMMAND(port, TxReset, 0); - 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()){ - if(ioalloc(port, 0x10, 0, "tcm509isa") < 0){ - print("tcm509isa: port 0x%uX in use\n", port); - continue; - } - - /* - * 6. Tag the adapter so it won't respond in future. - */ - outb(IDport, 0xD1); - if(port == 0x3F0){ - iofree(port); - 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(ioalloc(port, 0x1000, 0, "tcm5XXeisa") < 0){ - print("tcm5XXeisa: port 0x%uX in use\n", port); - continue; - } - if(ins(port+0xC80+ManufacturerID) != 0x6D50){ - iofree(port); - continue; - } - x = ins(port+0xC80+ProductID); - if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900){ - iofree(port); - 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; - if((port = ioalloc((port == 0)? -1: port, p->mem[0].size, - 0, "tcm59Xpci")) < 0){ - print("tcm59Xpci: port 0x%uX in use\n", port); - continue; - } - 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 = vmap(p->mem[2].bar&~0x0F, p->mem[2].size); - break; - case 0x6056: - ctlr->eepromcmd = EepromReadOffRegister; - ctlr->cbfnpa = p->mem[2].bar&~0x0F; - ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size); - 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<= 0; i--){ - if(bits & (1<>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; -} - -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 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); - } -} - -static void -shutdown(Ether *ether) -{ -print("etherelnk3 shutting down\n"); - resetctlr(ether->ctlr); -} - -int -etherelnk3reset(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 - * and enable statistics collection. - */ - ilock(&ctlr->wlock); - statistics(ether); - memset(ctlr->stats, 0, sizeof(ctlr->stats)); - - COMMAND(port, StatisticsEnable, 0); - - /* - * Allocate any receive buffers. - */ - switch(ctlr->busmaster){ - case 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); - - if(ctlr->upenabled || ctlr->dnenabled){ - ctlr->nup = Nup; - ctlr->ndn = Ndn; - init905(ctlr); - } - else { - ctlr->rbp = rbpalloc(iallocb); - if(ctlr->rbp == nil) - panic("can't reset ethernet: out of memory"); - } - outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256)); - break; - default: - ctlr->rbp = rbpalloc(iallocb); - if(ctlr->rbp == nil) - panic("can't reset ethernet: out of memory"); - break; - } - - /* - * 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; - ether->ifstat = ifstat; - - ether->promiscuous = promiscuous; - ether->multicast = multicast; - ether->shutdown = shutdown; - ether->arg = ether; - - return 0; -} - -void -etherelnk3link(void) -{ - addethercard("elnk3", etherelnk3reset); - addethercard("3C509", etherelnk3reset); - addethercard("3C575", etherelnk3reset); -} diff --git a/os/pc/etherga620.c b/os/pc/etherga620.c deleted file mode 100644 index 3d555be0..00000000 --- a/os/pc/etherga620.c +++ /dev/null @@ -1,1275 +0,0 @@ -/* - * 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 "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.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 = 0x2000, /* 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 = 512, /* 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* edev) -{ - Ctlr *ctlr; - - ctlr = edev->ctlr; - USED(ctlr); -} - -static long -ga620ifstat(Ether* edev, void* a, long n, ulong offset) -{ - char *p; - Ctlr *ctlr; - int i, l, r; - - ctlr = edev->ctlr; - - if(n == 0) - return 0; - p = malloc(READSTR); - l = 0; - for(i = 0; i < 256; i++){ - if((r = ctlr->gib->statistics[i]) == 0) - continue; - l += snprint(p+l, READSTR-l, "%d: %ud\n", i, r); - } - - l += snprint(p+l, READSTR-l, "interrupts: %ud\n", ctlr->interrupts); - l += snprint(p+l, READSTR-l, "mi: %ud\n", ctlr->mi); - l += snprint(p+l, READSTR-l, "ticks: %llud\n", ctlr->ticks); - l += snprint(p+l, READSTR-l, "coalupdateonly: %d\n", ctlr->coalupdateonly); - l += snprint(p+l, READSTR-l, "hardwarecksum: %d\n", ctlr->hardwarecksum); - l += snprint(p+l, READSTR-l, "rct: %d\n", ctlr->rct); - l += snprint(p+l, READSTR-l, "sct: %d\n", ctlr->sct); - l += snprint(p+l, READSTR-l, "smcbd: %d\n", ctlr->smcbd); - snprint(p+l, READSTR-l, "rmcbd: %d\n", ctlr->rmcbd); - - n = readstr(offset, a, n, p); - free(p); - - return n; -} - -static long -ga620ctl(Ether* edev, void* buf, long n) -{ - char *p; - Cmdbuf *cb; - Ctlr *ctlr; - int control, i, r; - - ctlr = edev->ctlr; - if(ctlr == nil) - error(Enonexist); - r = 0; - cb = parsecmd(buf, n); - if(cb->nf < 2) - r = -1; - else if(cistrcmp(cb->f[0], "coalupdateonly") == 0){ - if(cistrcmp(cb->f[1], "off") == 0){ - control = ctlr->gib->srcb.control; - control &= ~CoalUpdateOnly; - ctlr->gib->srcb.control = control; - ctlr->coalupdateonly = 0; - } - else if(cistrcmp(cb->f[1], "on") == 0){ - control = ctlr->gib->srcb.control; - control |= CoalUpdateOnly; - ctlr->gib->srcb.control = control; - ctlr->coalupdateonly = 1; - } - else - r = -1; - } - else if(cistrcmp(cb->f[0], "hardwarecksum") == 0){ - if(cistrcmp(cb->f[1], "off") == 0){ - control = ctlr->gib->srcb.control; - control &= ~(TcpUdpCksum|NoPseudoHdrCksum); - ctlr->gib->srcb.control = control; - - control = ctlr->gib->rsrcb.control; - control &= ~(TcpUdpCksum|NoPseudoHdrCksum); - ctlr->gib->rsrcb.control = control; - - ctlr->hardwarecksum = 0; - } - else if(cistrcmp(cb->f[1], "on") == 0){ - control = ctlr->gib->srcb.control; - control |= (TcpUdpCksum|NoPseudoHdrCksum); - ctlr->gib->srcb.control = control; - - control = ctlr->gib->rsrcb.control; - control |= (TcpUdpCksum|NoPseudoHdrCksum); - ctlr->gib->rsrcb.control = control; - - ctlr->hardwarecksum = 1; - } - else - r = -1; - } - else if(cistrcmp(cb->f[0], "rct") == 0){ - i = strtol(cb->f[1], &p, 0); - if(i < 0 || p == cb->f[1]) - r = -1; - else{ - ctlr->rct = i; - csr32w(ctlr, Rct, ctlr->rct); - } - } - else if(cistrcmp(cb->f[0], "sct") == 0){ - i = strtol(cb->f[1], &p, 0); - if(i < 0 || p == cb->f[1]) - r = -1; - else{ - ctlr->sct = i; - csr32w(ctlr, Sct, ctlr->sct); - } - } - else if(cistrcmp(cb->f[0], "st") == 0){ - i = strtol(cb->f[1], &p, 0); - if(i < 0 || p == cb->f[1]) - r = -1; - else{ - ctlr->st = i; - csr32w(ctlr, St, ctlr->st); - } - } - else if(cistrcmp(cb->f[0], "smcbd") == 0){ - i = strtol(cb->f[1], &p, 0); - if(i < 0 || p == cb->f[1]) - r = -1; - else{ - ctlr->smcbd = i; - csr32w(ctlr, SmcBD, ctlr->smcbd); - } - } - else if(cistrcmp(cb->f[0], "rmcbd") == 0){ - i = strtol(cb->f[1], &p, 0); - if(i < 0 || p == cb->f[1]) - r = -1; - else{ - ctlr->rmcbd = i; - csr32w(ctlr, RmcBD, ctlr->rmcbd); - } - } - else - r = -1; - - free(cb); - if(r == 0) - return n; - return r; -} - -static int -_ga620transmit(Ether* edev) -{ - Sbd *sbd; - Block *bp; - Ctlr *ctlr; - 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; - 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); - for(spi = csr32r(ctlr, Spi); spi != sci; spi = NEXT(spi, Nsr)){ - if((bp = qget(edev->oq)) == nil) - break; - - sbd = &ctlr->sr[spi]; - sethost64(&sbd->addr, bp->rp); - sbd->lenflags = BLEN(bp)<<16 | Fend; - - ctlr->srb[spi] = bp; - work++; - } - 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 = iallocb(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; - etheriq(edev, bp, 1); - } - 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; - uvlong tsc0, tsc1; - - edev = arg; - ctlr = edev->ctlr; - - if(!(csr32r(ctlr, Mhc) & Is)) - return; - cycles(&tsc0); - - 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; - } - - cycles(&tsc1); - ctlr->ticks += tsc1-tsc0; -} - -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<= 0) - r |= (i<= 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); - - return 0; -} - -static void -ga620pci(void) -{ - void *mem; - 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; - } - - mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size); - if(mem == 0){ - print("ga620: can't map %8.8luX\n", p->mem[0].bar); - continue; - } - - ctlr = malloc(sizeof(Ctlr)); - ctlr->port = p->mem[0].bar & ~0x0F; - ctlr->pcidev = p; - ctlr->id = p->did<<16 | p->vid; - - ctlr->nic = mem; - if(ga620reset(ctlr)){ - free(ctlr); - continue; - } - - if(ctlrhead != nil) - ctlrtail->next = ctlr; - else - ctlrhead = ctlr; - ctlrtail = ctlr; - } -} - -static void -ga620promiscuous(void *arg, int on) -{ - Ether *ether = arg; - - /* 3rd arg: 1 enables, 2 disables */ - ga620command(ether->ctlr, 0xa, (on? 1: 2), 0); -} - -static void -ga620multicast(void *arg, uchar *addr, int on) -{ - Ether *ether = arg; - - USED(addr); - /* 3rd arg: 1 enables, 2 disables */ - ga620command(ether->ctlr, 0xe, (on? 1: 2), 0); -} - -static 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; - edev->mbps = 1000; /* placeholder */ - - /* - * 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); - - /* - * Linkage to the generic ethernet driver. - */ - edev->attach = ga620attach; - edev->transmit = ga620transmit; - edev->interrupt = ga620interrupt; - edev->ifstat = ga620ifstat; - edev->ctl = ga620ctl; - - edev->arg = edev; - edev->promiscuous = ga620promiscuous; - edev->multicast = ga620multicast; - edev->shutdown = ga620shutdown; - - return 0; -} - -void -etherga620link(void) -{ - addethercard("GA620", ga620pnp); -} diff --git a/os/pc/etherga620fw.h b/os/pc/etherga620fw.h deleted file mode 100644 index c30859e7..00000000 --- a/os/pc/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/os/pc/etherif.h b/os/pc/etherif.h deleted file mode 100644 index d80e06c9..00000000 --- a/os/pc/etherif.h +++ /dev/null @@ -1,39 +0,0 @@ -enum { - MaxEther = 24, - Ntypes = 8, -}; - -typedef struct Ether Ether; -struct Ether { - ISAConf; /* hardware info */ - - int ctlrno; - int tbdf; /* type+busno+devno+funcno */ - int minmtu; - int maxmtu; - uchar ea[Eaddrlen]; - - void (*attach)(Ether*); /* filled in by reset routine */ - void (*detach)(Ether*); - void (*transmit)(Ether*); - void (*interrupt)(Ureg*, void*); - long (*ifstat)(Ether*, void*, long, ulong); - long (*ctl)(Ether*, void*, long); /* custom ctl messages */ - void (*power)(Ether*, int); /* power on/off */ - void (*shutdown)(Ether*); /* shutdown hardware before reboot */ - void *ctlr; - - Queue* oq; - - Netif; -}; - -extern Block* etheriq(Ether*, Block*, int); -extern void addethercard(char*, int(*)(Ether*)); -extern ulong ethercrc(uchar*, int); -extern int parseether(uchar*, char*); - -#define NEXT(x, l) (((x)+1)%(l)) -#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1) -#define HOWMANY(x, y) (((x)+((y)-1))/(y)) -#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) diff --git a/os/pc/etherigbe.c b/os/pc/etherigbe.c deleted file mode 100644 index 10515097..00000000 --- a/os/pc/etherigbe.c +++ /dev/null @@ -1,1989 +0,0 @@ -/* - * Intel 8254[340]NN Gigabit Ethernet Controller - * as found on the Intel PRO/1000 series of adapters: - * 82543GC Intel PRO/1000 T - * 82544EI Intel PRO/1000 XT - * 82540EM Intel PRO/1000 MT - * 82541[GP]I - * 82547GI - * 82546GB - * 82546EB - * To Do: - * finish autonegotiation code; - * integrate fiber stuff back in (this ONLY handles - * the CAT5 cards at the moment); - * add checksum-offload; - * add tuning control via ctl file; - * this driver is little-endian specific. - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" - -#include "etherif.h" -#include "ethermii.h" - -enum { - i82542 = (0x1000<<16)|0x8086, - i82543gc = (0x1004<<16)|0x8086, - i82544ei = (0x1008<<16)|0x8086, - i82547ei = (0x1019<<16)|0x8086, - i82540em = (0x100E<<16)|0x8086, - i82540eplp = (0x101E<<16)|0x8086, - i82545gmc = (0x1026<<16)|0x8086, - i82547gi = (0x1075<<16)|0x8086, - i82541gi = (0x1076<<16)|0x8086, - i82541gi2 = (0x1077<<16)|0x8086, - i82546gb = (0x1079<<16)|0x8086, - i82541pi = (0x107c<<16)|0x8086, - i82546eb = (0x1010<<16)|0x8086, -}; - -enum { - Ctrl = 0x00000000, /* Device Control */ - Ctrldup = 0x00000004, /* Device Control Duplicate */ - 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 */ - Rxcw = 0x00000180, /* Receive 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 */ - Rdfh = 0x00002410, /* Receive data fifo head */ - Rdft = 0x00002418, /* Receive data fifo tail */ - Rdfhs = 0x00002420, /* Receive data fifo head saved */ - Rdfts = 0x00002428, /* Receive data fifo tail saved */ - Rdfpc = 0x00002430, /* Receive data fifo packet count */ - Rdbal = 0x00002800, /* Rd Base Address Low */ - Rdbah = 0x00002804, /* Rd 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 */ - Tdfh = 0x00003410, /* Transmit data fifo head */ - Tdft = 0x00003418, /* Transmit data fifo tail */ - Tdfhs = 0x00003420, /* Transmit data Fifo Head saved */ - Tdfts = 0x00003428, /* Transmit data fifo tail saved */ - Tdfpc = 0x00003430, /* Trasnmit data Fifo packet count */ - Tdbal = 0x00003800, /* Td Base Address Low */ - Tdbah = 0x00003804, /* Td 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 */ -}; - -enum { /* Status */ - Lu = 0x00000002, /* Link Up */ - Tckok = 0x00000004, /* Transmit clock is running */ - Rbcok = 0x00000008, /* Receive clock is running */ - Txoff = 0x00000010, /* Transmission Paused */ - Tbimode = 0x00000020, /* TBI Mode Indication */ - LspeedMASK = 0x000000C0, /* Link Speed Setting */ - LspeedSHIFT = 6, - Lspeed10 = 0x00000000, /* 10Mb/s */ - Lspeed100 = 0x00000040, /* 100Mb/s */ - Lspeed1000 = 0x00000080, /* 1000Mb/s */ - Mtxckok = 0x00000400, /* MTX clock is running */ - Pci66 = 0x00000800, /* PCI Bus speed indication */ - Bus64 = 0x00001000, /* PCI Bus width indication */ - Pcixmode = 0x00002000, /* PCI-X mode */ - PcixspeedMASK = 0x0000C000, /* PCI-X bus speed */ - PcixspeedSHIFT = 14, - Pcix66 = 0x00000000, /* 50-66MHz */ - Pcix100 = 0x00004000, /* 66-100MHz */ - Pcix133 = 0x00008000, /* 100-133MHz */ -}; - -enum { /* Ctrl and Status */ - Fd = 0x00000001, /* Full-Duplex */ - AsdvMASK = 0x00000300, - AsdvSHIFT = 8, - 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, /* Rd 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)<nic+((r)/4))) -#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) - -static Ctlr* igbectlrhead; -static Ctlr* igbectlrtail; - -static Lock igberblock; /* free receive Blocks */ -static Block* igberbpool; /* receive Blocks for all igbe controllers */ - -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 long -igbeifstat(Ether* edev, void* a, long n, ulong offset) -{ - Ctlr *ctlr; - char *p, *s; - int i, l, r; - uvlong tuvl, ruvl; - - ctlr = edev->ctlr; - qlock(&ctlr->slock); - p = malloc(2*READSTR); - l = 0; - for(i = 0; i < Nstatistics; i++){ - r = csr32r(ctlr, Statistics+i*4); - if((s = statistics[i]) == nil) - continue; - switch(i){ - case Gorcl: - case Gotcl: - case Torl: - case Totl: - ruvl = r; - ruvl += ((uvlong)csr32r(ctlr, Statistics+(i+1)*4))<<32; - tuvl = ruvl; - tuvl += ctlr->statistics[i]; - tuvl += ((uvlong)ctlr->statistics[i+1])<<32; - if(tuvl == 0) - continue; - ctlr->statistics[i] = tuvl; - ctlr->statistics[i+1] = tuvl>>32; - l += snprint(p+l, 2*READSTR-l, "%s: %llud %llud\n", - s, tuvl, ruvl); - i++; - break; - - default: - ctlr->statistics[i] += r; - if(ctlr->statistics[i] == 0) - continue; - l += snprint(p+l, 2*READSTR-l, "%s: %ud %ud\n", - s, ctlr->statistics[i], r); - break; - } - } - - l += snprint(p+l, 2*READSTR-l, "lintr: %ud %ud\n", - ctlr->lintr, ctlr->lsleep); - l += snprint(p+l, 2*READSTR-l, "rintr: %ud %ud\n", - ctlr->rintr, ctlr->rsleep); - l += snprint(p+l, 2*READSTR-l, "tintr: %ud %ud\n", - ctlr->tintr, ctlr->txdw); - l += snprint(p+l, 2*READSTR-l, "ixcs: %ud %ud %ud\n", - ctlr->ixsm, ctlr->ipcs, ctlr->tcpcs); - l += snprint(p+l, 2*READSTR-l, "rdtr: %ud\n", ctlr->rdtr); - l += snprint(p+l, 2*READSTR-l, "Ctrlext: %08x\n", csr32r(ctlr, Ctrlext)); - - l += snprint(p+l, 2*READSTR-l, "eeprom:"); - for(i = 0; i < 0x40; i++){ - if(i && ((i & 0x07) == 0)) - l += snprint(p+l, 2*READSTR-l, "\n "); - l += snprint(p+l, 2*READSTR-l, " %4.4uX", ctlr->eeprom[i]); - } - l += snprint(p+l, 2*READSTR-l, "\n"); - - if(ctlr->mii != nil && ctlr->mii->curphy != nil){ - l += snprint(p+l, 2*READSTR, "phy: "); - for(i = 0; i < NMiiPhyr; i++){ - if(i && ((i & 0x07) == 0)) - l += snprint(p+l, 2*READSTR-l, "\n "); - r = miimir(ctlr->mii, i); - l += snprint(p+l, 2*READSTR-l, " %4.4uX", r); - } - snprint(p+l, 2*READSTR-l, "\n"); - } - n = readstr(offset, a, n, p); - free(p); - qunlock(&ctlr->slock); - - return n; -} - -enum { - CMrdtr, -}; - -static Cmdtab igbectlmsg[] = { - CMrdtr, "rdtr", 2, -}; - -static long -igbectl(Ether* edev, void* buf, long n) -{ - int v; - char *p; - Ctlr *ctlr; - Cmdbuf *cb; - Cmdtab *ct; - - if((ctlr = edev->ctlr) == nil) - error(Enonexist); - - cb = parsecmd(buf, n); - if(waserror()){ - free(cb); - nexterror(); - } - - ct = lookupcmd(cb, igbectlmsg, nelem(igbectlmsg)); - switch(ct->index){ - case CMrdtr: - v = strtol(cb->f[1], &p, 0); - if(v < 0 || p == cb->f[1] || v > 0xFFFF) - error(Ebadarg); - ctlr->rdtr = v;; - csr32w(ctlr, Rdtr, Fpd|v); - break; - } - free(cb); - poperror(); - - return n; -} - -static void -igbepromiscuous(void* arg, int on) -{ - int rctl; - Ctlr *ctlr; - Ether *edev; - - edev = arg; - ctlr = edev->ctlr; - - rctl = csr32r(ctlr, Rctl); - rctl &= ~MoMASK; - rctl |= Mo47b36; - if(on) - rctl |= Upe|Mpe; - else - rctl &= ~(Upe|Mpe); - csr32w(ctlr, Rctl, rctl); -} - -static void -igbemulticast(void* arg, uchar* addr, int on) -{ - int bit, x; - Ctlr *ctlr; - Ether *edev; - - edev = arg; - ctlr = edev->ctlr; - - x = addr[5]>>1; - bit = ((addr[5] & 1)<<4)|(addr[4]>>4); - if(on) - ctlr->mta[x] |= 1<mta[x] &= ~(1<mta[x]); -} - -static Block* -igberballoc(void) -{ - Block *bp; - - ilock(&igberblock); - if((bp = igberbpool) != nil){ - igberbpool = bp->next; - bp->next = nil; - } - iunlock(&igberblock); - - return bp; -} - -static void -igberbfree(Block* bp) -{ - bp->rp = bp->lim - Rbsz; - bp->wp = bp->rp; - - ilock(&igberblock); - bp->next = igberbpool; - igberbpool = bp; - iunlock(&igberblock); -} - -static void -igbeim(Ctlr* ctlr, int im) -{ - ilock(&ctlr->imlock); - ctlr->im |= im; - csr32w(ctlr, Ims, ctlr->im); - iunlock(&ctlr->imlock); -} - -static int -igbelim(void* ctlr) -{ - return ((Ctlr*)ctlr)->lim != 0; -} - -static void -igbelproc(void* arg) -{ - Ctlr *ctlr; - Ether *edev; - MiiPhy *phy; - int ctrl, r; - - edev = arg; - ctlr = edev->ctlr; - for(;;){ - if(ctlr->mii == nil || ctlr->mii->curphy == nil) - continue; - - /* - * To do: - * logic to manage status change, - * this is incomplete but should work - * one time to set up the hardware. - * - * MiiPhy.speed, etc. should be in Mii. - */ - if(miistatus(ctlr->mii) < 0) - //continue; - goto enable; - - phy = ctlr->mii->curphy; - ctrl = csr32r(ctlr, Ctrl); - - switch(ctlr->id){ - case i82543gc: - case i82544ei: - default: - if(!(ctrl & Asde)){ - ctrl &= ~(SspeedMASK|Ilos|Fd); - ctrl |= Frcdplx|Frcspd; - if(phy->speed == 1000) - ctrl |= Sspeed1000; - else if(phy->speed == 100) - ctrl |= Sspeed100; - if(phy->fd) - ctrl |= Fd; - } - break; - - case i82540em: - case i82540eplp: - case i82547gi: - case i82541gi: - case i82541gi2: - case i82541pi: - break; - } - - /* - * Collision Distance. - */ - r = csr32r(ctlr, Tctl); - r &= ~ColdMASK; - if(phy->fd) - r |= 64<rfc) - ctrl |= Rfce; - if(phy->tfc) - ctrl |= Tfce; - csr32w(ctlr, Ctrl, ctrl); - -enable: - ctlr->lim = 0; - igbeim(ctlr, Lsc); - - ctlr->lsleep++; - sleep(&ctlr->lrendez, igbelim, ctlr); - } -} - -static void -igbetxinit(Ctlr* ctlr) -{ - int i, r; - Block *bp; - - csr32w(ctlr, Tctl, (0x0F<id){ - default: - r = 6; - break; - case i82543gc: - case i82544ei: - case i82547ei: - case i82540em: - case i82540eplp: - case i82541gi: - case i82541gi2: - case i82541pi: - case i82545gmc: - case i82546gb: - case i82546eb: - case i82547gi: - r = 8; - break; - } - csr32w(ctlr, Tipg, (6<<20)|(8<<10)|r); - csr32w(ctlr, Ait, 0); - csr32w(ctlr, Txdmac, 0); - - csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba)); - csr32w(ctlr, Tdbah, 0); - csr32w(ctlr, Tdlen, ctlr->ntd*sizeof(Td)); - ctlr->tdh = PREV(0, ctlr->ntd); - csr32w(ctlr, Tdh, 0); - ctlr->tdt = 0; - csr32w(ctlr, Tdt, 0); - - for(i = 0; i < ctlr->ntd; i++){ - if((bp = ctlr->tb[i]) != nil){ - ctlr->tb[i] = nil; - freeb(bp); - } - memset(&ctlr->tdba[i], 0, sizeof(Td)); - } - ctlr->tdfree = ctlr->ntd; - - csr32w(ctlr, Tidv, 128); - r = (4<id){ - default: - break; - case i82540em: - case i82540eplp: - case i82547gi: - case i82545gmc: - case i82546gb: - case i82546eb: - case i82541gi: - case i82541gi2: - case i82541pi: - r = csr32r(ctlr, Txdctl); - r &= ~WthreshMASK; - r |= Gran|(4<ctlr; - - ilock(&ctlr->tlock); - - /* - * Free any completed packets - */ - tdh = ctlr->tdh; - while(NEXT(tdh, ctlr->ntd) != csr32r(ctlr, Tdh)){ - if((bp = ctlr->tb[tdh]) != nil){ - ctlr->tb[tdh] = nil; - freeb(bp); - } - memset(&ctlr->tdba[tdh], 0, sizeof(Td)); - tdh = NEXT(tdh, ctlr->ntd); - } - ctlr->tdh = tdh; - - /* - * Try to fill the ring back up. - */ - tdt = ctlr->tdt; - while(NEXT(tdt, ctlr->ntd) != tdh){ - if((bp = qget(edev->oq)) == nil) - break; - td = &ctlr->tdba[tdt]; - td->addr[0] = PCIWADDR(bp->rp); - td->control = ((BLEN(bp) & LenMASK)<control |= Dext|Ifcs|Teop|DtypeDD; - ctlr->tb[tdt] = bp; - tdt = NEXT(tdt, ctlr->ntd); - if(NEXT(tdt, ctlr->ntd) == tdh){ - td->control |= Rs; - ctlr->txdw++; - ctlr->tdt = tdt; - csr32w(ctlr, Tdt, tdt); - igbeim(ctlr, Txdw); - break; - } - ctlr->tdt = tdt; - csr32w(ctlr, Tdt, tdt); - } - - iunlock(&ctlr->tlock); -} - -static void -igbereplenish(Ctlr* ctlr) -{ - Rd *rd; - int rdt; - Block *bp; - - rdt = ctlr->rdt; - while(NEXT(rdt, ctlr->nrd) != ctlr->rdh){ - rd = &ctlr->rdba[rdt]; - if(ctlr->rb[rdt] == nil){ - bp = igberballoc(); - if(bp == nil){ - iprint("#l%d: igbereplenish: no available buffers\n", - ctlr->edev->ctlrno); - break; - } - ctlr->rb[rdt] = bp; - rd->addr[0] = PCIWADDR(bp->rp); - rd->addr[1] = 0; - } - coherence(); - rd->status = 0; - rdt = NEXT(rdt, ctlr->nrd); - ctlr->rdfree++; - } - ctlr->rdt = rdt; - csr32w(ctlr, Rdt, rdt); -} - -static void -igberxinit(Ctlr* ctlr) -{ - int i; - Block *bp; - - csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF); - - csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba)); - csr32w(ctlr, Rdbah, 0); - csr32w(ctlr, Rdlen, ctlr->nrd*sizeof(Rd)); - ctlr->rdh = 0; - csr32w(ctlr, Rdh, 0); - ctlr->rdt = 0; - csr32w(ctlr, Rdt, 0); - ctlr->rdtr = 0; - csr32w(ctlr, Rdtr, Fpd|0); - - for(i = 0; i < ctlr->nrd; i++){ - if((bp = ctlr->rb[i]) != nil){ - ctlr->rb[i] = nil; - freeb(bp); - } - } - igbereplenish(ctlr); - - switch(ctlr->id){ - case i82540em: - case i82540eplp: - case i82541gi: - case i82541gi2: - case i82541pi: - case i82545gmc: - case i82546gb: - case i82546eb: - case i82547gi: - csr32w(ctlr, Radv, 64); - break; - } - csr32w(ctlr, Rxdctl, (8<rim != 0; -} - -static void -igberproc(void* arg) -{ - Rd *rd; - Block *bp; - Ctlr *ctlr; - int r, rdh; - Ether *edev; - - edev = arg; - ctlr = edev->ctlr; - - igberxinit(ctlr); - r = csr32r(ctlr, Rctl); - r |= Ren; - csr32w(ctlr, Rctl, r); - - for(;;){ - ctlr->rim = 0; - igbeim(ctlr, Rxt0|Rxo|Rxdmt0|Rxseq); - ctlr->rsleep++; - sleep(&ctlr->rrendez, igberim, ctlr); - - rdh = ctlr->rdh; - for(;;){ - rd = &ctlr->rdba[rdh]; - - if(!(rd->status & Rdd)) - break; - - /* - * Accept eop packets with no errors. - * With no errors and the Ixsm bit set, - * the descriptor status Tpcs and Ipcs bits give - * an indication of whether the checksums were - * calculated and valid. - */ - if((rd->status & Reop) && rd->errors == 0){ - bp = ctlr->rb[rdh]; - ctlr->rb[rdh] = nil; - bp->wp += rd->length; - bp->next = nil; - if(!(rd->status & Ixsm)){ - ctlr->ixsm++; - if(rd->status & Ipcs){ - /* - * IP checksum calculated - * (and valid as errors == 0). - */ - ctlr->ipcs++; - bp->flag |= Bipck; - } - if(rd->status & Tcpcs){ - /* - * TCP/UDP checksum calculated - * (and valid as errors == 0). - */ - ctlr->tcpcs++; - bp->flag |= Btcpck|Budpck; - } - bp->checksum = rd->checksum; - bp->flag |= Bpktck; - } - etheriq(edev, bp, 1); - } - else if(ctlr->rb[rdh] != nil){ - freeb(ctlr->rb[rdh]); - ctlr->rb[rdh] = nil; - } - - memset(rd, 0, sizeof(Rd)); - coherence(); - ctlr->rdfree--; - rdh = NEXT(rdh, ctlr->nrd); - } - ctlr->rdh = rdh; - - if(ctlr->rdfree < ctlr->nrd/2 || (ctlr->rim & Rxdmt0)) - igbereplenish(ctlr); - } -} - -static void -igbeattach(Ether* edev) -{ - Block *bp; - Ctlr *ctlr; - char name[KNAMELEN]; - - ctlr = edev->ctlr; - ctlr->edev = edev; /* point back to Ether* */ - qlock(&ctlr->alock); - if(ctlr->alloc != nil){ - qunlock(&ctlr->alock); - return; - } - - ctlr->nrd = ROUND(Nrd, 8); - ctlr->ntd = ROUND(Ntd, 8); - ctlr->alloc = malloc(ctlr->nrd*sizeof(Rd)+ctlr->ntd*sizeof(Td) + 127); - if(ctlr->alloc == nil){ - qunlock(&ctlr->alock); - return; - } - ctlr->rdba = (Rd*)ROUNDUP((uintptr)ctlr->alloc, 128); - ctlr->tdba = (Td*)(ctlr->rdba+ctlr->nrd); - - ctlr->rb = malloc(ctlr->nrd*sizeof(Block*)); - ctlr->tb = malloc(ctlr->ntd*sizeof(Block*)); - - if(waserror()){ - while(ctlr->nrb > 0){ - bp = igberballoc(); - bp->free = nil; - freeb(bp); - ctlr->nrb--; - } - free(ctlr->tb); - ctlr->tb = nil; - free(ctlr->rb); - ctlr->rb = nil; - free(ctlr->alloc); - ctlr->alloc = nil; - qunlock(&ctlr->alock); - nexterror(); - } - - for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){ - if((bp = allocb(Rbsz)) == nil) - break; - bp->free = igberbfree; - freeb(bp); - } - - snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno); - kproc(name, igbelproc, edev, 0); - - snprint(name, KNAMELEN, "#l%drproc", edev->ctlrno); - kproc(name, igberproc, edev, 0); - - igbetxinit(ctlr); - - qunlock(&ctlr->alock); - poperror(); -} - -static void -igbeinterrupt(Ureg*, void* arg) -{ - Ctlr *ctlr; - Ether *edev; - int icr, im, txdw; - - edev = arg; - ctlr = edev->ctlr; - - ilock(&ctlr->imlock); - csr32w(ctlr, Imc, ~0); - im = ctlr->im; - txdw = 0; - - while((icr = csr32r(ctlr, Icr) & ctlr->im) != 0){ - if(icr & Lsc){ - im &= ~Lsc; - ctlr->lim = icr & Lsc; - wakeup(&ctlr->lrendez); - ctlr->lintr++; - } - if(icr & (Rxt0|Rxo|Rxdmt0|Rxseq)){ - im &= ~(Rxt0|Rxo|Rxdmt0|Rxseq); - ctlr->rim = icr & (Rxt0|Rxo|Rxdmt0|Rxseq); - wakeup(&ctlr->rrendez); - ctlr->rintr++; - } - if(icr & Txdw){ - im &= ~Txdw; - txdw++; - ctlr->tintr++; - } - } - - ctlr->im = im; - csr32w(ctlr, Ims, im); - iunlock(&ctlr->imlock); - - if(txdw) - igbetransmit(edev); -} - -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<= 0; i--){ - if(bits & (1<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<ctlr; - - data &= MDIdMASK; - csr32w(ctlr, Mdic, MDIwop|(pa<mii = malloc(sizeof(Mii))) == nil) - return -1; - ctlr->mii->ctlr = ctlr; - - ctrl = csr32r(ctlr, Ctrl); - ctrl |= Slu; - - switch(ctlr->id){ - case i82543gc: - ctrl |= Frcdplx|Frcspd; - csr32w(ctlr, Ctrl, ctrl); - - /* - * The reset pin direction (Mdro) should already - * be set from the EEPROM load. - * If it's not set this configuration is unexpected - * so bail. - */ - r = csr32r(ctlr, Ctrlext); - if(!(r & Mdro)) - return -1; - csr32w(ctlr, Ctrlext, r); - delay(20); - r = csr32r(ctlr, Ctrlext); - r &= ~Mdr; - csr32w(ctlr, Ctrlext, r); - delay(20); - r = csr32r(ctlr, Ctrlext); - r |= Mdr; - csr32w(ctlr, Ctrlext, r); - delay(20); - - ctlr->mii->mir = i82543miimir; - ctlr->mii->miw = i82543miimiw; - break; - case i82544ei: - case i82547ei: - case i82540em: - case i82540eplp: - case i82547gi: - case i82541gi: - case i82541gi2: - case i82541pi: - case 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){ - free(ctlr->mii); - ctlr->mii = nil; - return -1; - } - USED(phy); - // print("oui %X phyno %d\n", phy->oui, phy->phyno); - - /* - * 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 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); - p = 0; - if(ctlr->txcw & TxcwPs) - p |= AnaP; - if(ctlr->txcw & TxcwAs) - p |= AnaAP; - miiane(ctlr->mii, ~0, p, ~0); - break; - } - 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<= 0) - r |= (i<= 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 i82541gi: - case i82547gi: - case i82540em: - case i82540eplp: - case i82541pi: - case i82541gi2: - case i82545gmc: - case i82546gb: - case i82546eb: - areq = 1; - csr32w(ctlr, Eecd, eecd|Areq); - for(i = 0; i < 1000; i++){ - if((eecd = csr32r(ctlr, Eecd)) & Agnt) - break; - microdelay(5); - } - if(!(eecd & Agnt)){ - print("igbe: not granted EEPROM access\n"); - goto release; - } - break; - } - snprint(rop, sizeof(rop), "S :%dDCc;", bits+3); - - for(addr = 0; addr < 0x40; addr++){ - /* - * Read a word at address 'addr' from the Atmel AT93C46 - * 3-Wire Serial EEPROM or compatible. The EEPROM access is - * controlled by 4 bits in Eecd. See the AT93C46 datasheet - * for protocol details. - */ - if(at93c46io(ctlr, rop, (0x06<eeprom[addr] = data; - sum += data; - } - -release: - if(areq) - csr32w(ctlr, Eecd, eecd & ~Areq); - return sum; -} - -static int -igbedetach(Ctlr* ctlr) -{ - int r, timeo; - - /* - * 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(10); - - csr32w(ctlr, Ctrl, Devrst); - delay(1); - for(timeo = 0; timeo < 1000; timeo++){ - if(!(csr32r(ctlr, Ctrl) & Devrst)) - break; - delay(1); - } - if(csr32r(ctlr, Ctrl) & Devrst) - return -1; - r = csr32r(ctlr, Ctrlext); - csr32w(ctlr, Ctrlext, r|Eerst); - delay(1); - for(timeo = 0; timeo < 1000; timeo++){ - if(!(csr32r(ctlr, Ctrlext) & Eerst)) - break; - delay(1); - } - if(csr32r(ctlr, Ctrlext) & Eerst) - return -1; - - switch(ctlr->id){ - default: - break; - case i82540em: - case i82540eplp: - case i82541gi: - case i82541pi: - case i82547gi: - case i82541gi2: - case i82545gmc: - case i82546gb: - case i82546eb: - r = csr32r(ctlr, Manc); - r &= ~Arpen; - csr32w(ctlr, Manc, r); - break; - } - - csr32w(ctlr, Imc, ~0); - delay(1); - for(timeo = 0; timeo < 1000; timeo++){ - if(!csr32r(ctlr, Icr)) - break; - delay(1); - } - if(csr32r(ctlr, Icr)) - return -1; - - return 0; -} - -static void -igbeshutdown(Ether* ether) -{ - igbedetach(ether->ctlr); -} - -static int -igbereset(Ctlr* ctlr) -{ - int ctrl, i, pause, r, swdpio, txcw; - - if(igbedetach(ctlr)) - return -1; - - /* - * Read the EEPROM, validate the checksum - * then get the device back to a power-on state. - */ - if((r = at93c46r(ctlr)) != 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++){ -if(i == Ea && ctlr->id == i82541gi && ctlr->eeprom[i] == 0xFFFF) - ctlr->eeprom[i] = 0xD000; - ctlr->ra[2*i] = ctlr->eeprom[i]; - ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8; - } - 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 82543GC), 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<eeprom[Icw2] & 0x00F0)>>4; - if(ctlr->eeprom[Icw1] & 0x1000) - ctrl |= Ips; - ctrl |= swdpio<eeprom[Icw2] & 0x0800) - txcw |= TxcwAne; - pause = (ctlr->eeprom[Icw2] & 0x3000)>>12; - txcw |= pause<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); - - if(!(csr32r(ctlr, Status) & Tbimode) && igbemii(ctlr) < 0) - return -1; - - return 0; -} - -static void -igbepci(void) -{ - int cls; - Pcidev *p; - Ctlr *ctlr; - void *mem; - - 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 i82543gc: - case i82544ei: - case i82547ei: - case i82540em: - case i82540eplp: - case i82541gi: - case i82547gi: - case i82541gi2: - case i82541pi: - case i82545gmc: - case i82546gb: - case i82546eb: - break; - } - - mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size); - if(mem == nil){ - print("igbe: can't map %8.8luX\n", p->mem[0].bar); - continue; - } - cls = pcicfgr8(p, PciCLS); - switch(cls){ - default: - print("igbe: unexpected CLS - %d\n", cls*4); - break; - case 0x00: - case 0xFF: - print("igbe: unusable CLS\n"); - continue; - case 0x08: - case 0x10: - break; - } - ctlr = malloc(sizeof(Ctlr)); - ctlr->port = p->mem[0].bar & ~0x0F; - ctlr->pcidev = p; - ctlr->id = (p->did<<16)|p->vid; - ctlr->cls = cls*4; - ctlr->nic = mem; - - if(igbereset(ctlr)){ - free(ctlr); - vunmap(mem, p->mem[0].size); - continue; - } - pcisetbme(p); - - if(igbectlrhead != nil) - igbectlrtail->next = ctlr; - else - igbectlrhead = ctlr; - igbectlrtail = ctlr; - } -} - -static int -igbepnp(Ether* edev) -{ - Ctlr *ctlr; - - if(igbectlrhead == nil) - igbepci(); - - /* - * Any adapter matches if no edev->port is supplied, - * otherwise the ports must match. - */ - for(ctlr = igbectlrhead; 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; - memmove(edev->ea, ctlr->ra, Eaddrlen); - - /* - * Linkage to the generic ethernet driver. - */ - edev->attach = igbeattach; - edev->transmit = igbetransmit; - edev->interrupt = igbeinterrupt; - edev->ifstat = igbeifstat; - edev->ctl = igbectl; - - edev->arg = edev; - edev->promiscuous = igbepromiscuous; - edev->shutdown = igbeshutdown; - edev->multicast = igbemulticast; - - return 0; -} - -void -etherigbelink(void) -{ - addethercard("i82543", igbepnp); - addethercard("igbe", igbepnp); -} - diff --git a/os/pc/etherrhine.c b/os/pc/etherrhine.c deleted file mode 100644 index 5d25a6f0..00000000 --- a/os/pc/etherrhine.c +++ /dev/null @@ -1,734 +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 "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" -#include "etherif.h" - -#include "ethermii.h" - -typedef struct Desc Desc; -typedef struct Ctlr Ctlr; - -enum { - Ntxd = 16, - Nrxd = 64, - Nwait = 50, - Ntxstats = 9, - Nrxstats = 8, - BIGSTR = 8192, -}; - -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; - - ulong txstats[Ntxstats]; - ulong rxstats[Nrxstats]; - - Desc *txd; /* wants to be aligned on 16-byte boundary */ - Desc *rxd; - - QLock attachlck; - Lock lock; -}; - -#define ior8(c, r) (inb((c)->port+(r))) -#define ior16(c, r) (ins((c)->port+(r))) -#define ior32(c, r) (inl((c)->port+(r))) -#define iow8(c, r, b) (outb((c)->port+(r), (int)(b))) -#define iow16(c, r, w) (outs((c)->port+(r), (ushort)(w))) -#define iow32(c, r, l) (outl((c)->port+(r), (ulong)(l))) - -enum Regs { - Eaddr = 0x0, - Rcr = 0x6, - Tcr = 0x7, - Cr = 0x8, - Isr = 0xc, - Imr = 0xe, - McastAddr = 0x10, - RxdAddr = 0x18, - TxdAddr = 0x1C, - Bcr = 0x6e, - RhineMiiPhy = 0x6C, - RhineMiiSr = 0x6D, - RhineMiiCr = 0x70, - RhineMiiAddr = 0x71, - RhineMiiData = 0x72, - Eecsr = 0x74, - ConfigB = 0x79, - ConfigD = 0x7B, - MiscCr = 0x80, - HwSticky = 0x83, - MiscIsr = 0x84, - MiscImr = 0x86, - WolCrSet = 0xA0, - WolCfgSet = 0xA1, - WolCgSet = 0xA3, - WolCrClr = 0xA4, - PwrCfgClr = 0xA5, - WolCgClr = 0xA7, -}; - -enum Rcrbits { - RxErrX = 1<<0, - RxSmall = 1<<1, - RxMcast = 1<<2, - RxBcast = 1<<3, - RxProm = 1<<4, - RxFifo64 = 0<<5, RxFifo32 = 1<<5, RxFifo128 = 2<<5, RxFifo256 = 3<<5, - RxFifo512 = 4<<5, RxFifo768 = 5<<5, RxFifo1024 = 6<<5, - RxFifoStoreForward = 7<<5, -}; - -enum Tcrbits { - TxLoopback0 = 1<<1, - TxLoopback1 = 1<<2, - TxBackoff = 1<<3, - TxFifo128 = 0<<5, TxFifo256 = 1<<5, TxFifo512 = 2<<5, TxFifo1024 = 3<<5, - TxFifoStoreForward = 7<<5, -}; - -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 Bcrbits { - Dma32 = 0<<0, Dma64 = 1<<0, Dma128 = 2<<0, - Dma256 = 3<<0, Dma512 = 4<<0, Dma1024 = 5<<0, - DmaStoreForward = 7<<0, - DupRxFifo0 = 1<<3, DupRxFifo1 = 1<<4, DupRxFifo2 = 1<<5, - ExtraLed = 1<<6, - MediumSelect = 1<<7, - PollTimer0 = 1<<8, PollTimer1 = 1<<9, PollTimer2 = 1<<10, - DupTxFifo0 = 1<<11, DupTxFifo1 = 1<<12, DupTxFifo2 = 1<<13, -}; - -enum Eecsrbits { - EeAutoLoad = 1<<5, -}; - -enum MiscCrbits { - Timer0Enable= 1<<0, - Timer0Suspend = 1<<1, - HalfDuplexFlowControl = 1<<2, - FullDuplexFlowControl = 1<<3, - Timer1Enable = 1<<8, - ForceSoftReset = 1<<14, -}; - -enum HwStickybits { - StickyDS0 = 1<<0, - StickyDS1 = 1<<1, - WOLEna = 1<<2, - WOLStat = 1<<3, -}; - -enum WolCgbits { - PmeOvr = 1<<7, -}; - -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 ConfigDbits { - BackoffOptional = 1<<0, - BackoffAMD = 1<<1, - BackoffDEC = 1<<2, - BackoffRandom = 1<<3, - PmccTestMode = 1<<4, - PciReadlineCap = 1<<5, - DiagMode = 1<<6, - MmioEnable = 1<<7, -}; - -enum ConfigBbits { - LatencyTimer = 1<<0, - WriteWaitState = 1<<1, - ReadWaitState = 1<<2, - RxArbit = 1<<3, - TxArbit = 1<<4, - NoMemReadline = 1<<5, - NoParity = 1<<6, - NoTxQueuing = 1<<7, -}; - -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, -}; - -enum RhineMiiSrbits { - Speed10M = 1<<0, - LinkFail = 1<<1, - PhyError = 1<<3, - DefaultPhy = 1<<4, - ResetPhy = 1<<7, -}; - -enum RhineMiiAddrbits { - Mdone = 1<<5, - Msrcen = 1<<6, - Midle = 1<<7, -}; - -static char * -txstatnames[Ntxstats] = { - "aborts (excess collisions)", - "out of window collisions", - "carrier sense losses", - "fifo underflows", - "invalid descriptor format or underflows", - "system errors", - "reserved", - "transmit errors", - "collisions", -}; - -static char * -rxstatnames[Nrxstats] = { - "receiver errors", - "crc errors", - "frame alignment errors", - "fifo overflows", - "long packets", - "run packets", - "system errors", - "buffer underflows", -}; - -static void -attach(Ether *edev) -{ - Ctlr *ctlr; - Desc *txd, *rxd, *td, *rd; - Mii *mi; - MiiPhy *phy; - int i, s; - - ctlr = edev->ctlr; - qlock(&ctlr->attachlck); - if (ctlr->attached == 0) { - txd = ctlr->txd; - rxd = ctlr->rxd; - for (i = 0; i < Ntxd; ++i) { - td = &txd[i]; - td->next = PCIWADDR(&txd[(i+1) % Ntxd]); - td->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0); - td->addr = PCIWADDR(td->buf); - td->size = 0; - coherence(); - td->stat = 0; - } - for (i = 0; i < Nrxd; ++i) { - rd = &rxd[i]; - rd->next = PCIWADDR(&rxd[(i+1) % Nrxd]); - rd->buf = xspanalloc(sizeof(Etherpkt)+4, 4, 0); - rd->addr = PCIWADDR(rd->buf); - rd->size = sizeof(Etherpkt)+4; - coherence(); - rd->stat = OwnNic; - } - - ctlr->txhead = ctlr->txtail = ctlr->rxtail = 0; - mi = &ctlr->mii; - miistatus(mi); - phy = mi->curphy; - s = splhi(); - iow32(ctlr, TxdAddr, PCIWADDR(&txd[0])); - iow32(ctlr, RxdAddr, PCIWADDR(&rxd[0])); - iow16(ctlr, Cr, (phy->fd ? FullDuplex : 0) | NoAutoPoll | TxOn | RxOn | Start | Rdmd); - iow16(ctlr, Isr, 0xFFFF); - iow16(ctlr, Imr, 0xFFFF); - iow8(ctlr, MiscIsr, 0xFF); - iow8(ctlr, MiscImr, ~(3<<5)); - splx(s); - } - ctlr->attached++; - qunlock(&ctlr->attachlck); -} - -static void -txstart(Ether *edev) -{ - Ctlr *ctlr; - Desc *txd, *td; - Block *b; - int i, txused, n; - ulong size; - - ctlr = edev->ctlr; - - txd = ctlr->txd; - i = ctlr->txhead; - txused = ctlr->txused; - n = 0; - while (txused < Ntxd) { - if ((b = qget(edev->oq)) == nil) - break; - - td = &txd[i]; - - size = BLEN(b); - memmove(td->buf, b->rp, size); - freeb(b); - td->size = size | TxChainStart | TxChainEnd | TxInt; /* could reduce number of ints here */ - coherence(); - td->stat = OwnNic; - i = (i + 1) % Ntxd; - txused++; - n++; - } - 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->lock); - txstart(edev); - iunlock(&ctlr->lock); -} - -static void -txcomplete(Ether *edev) -{ - Ctlr *ctlr; - Desc *txd, *td; - int i, txused, j; - ulong stat; - - ctlr = edev->ctlr; - txd = ctlr->txd; - txused = ctlr->txused; - i = ctlr->txtail; - while (txused > 0) { - td = &txd[i]; - stat = td->stat; - - if (stat & OwnNic) - break; - - ctlr->txstats[Ntxstats-1] += stat & 0xF; - for (j = 0; j < Ntxstats-1; ++j) - if (stat & (1<<(j+8))) - ctlr->txstats[j]++; - - i = (i + 1) % Ntxd; - txused--; - } - ctlr->txused = txused; - ctlr->txtail = i; - - if (txused <= Ntxd/2) - txstart(edev); -} - -static void -interrupt(Ureg *, void *arg) -{ - Ether *edev; - Ctlr *ctlr; - ushort isr, misr; - ulong stat; - Desc *rxd, *rd; - int i, n, j; - - edev = (Ether*)arg; - ctlr = edev->ctlr; - iow16(ctlr, Imr, 0); - isr = ior16(ctlr, Isr); - iow16(ctlr, Isr, 0xFFFF); - misr = ior16(ctlr, MiscIsr) & ~(3<<5); /* don't care about used defined ints */ - - if (isr & RxOk) { - Block *b; - int size; - rxd = ctlr->rxd; - i = ctlr->rxtail; - - n = 0; - while ((rxd[i].stat & OwnNic) == 0) { - rd = &rxd[i]; - stat = rd->stat; - for (j = 0; j < Nrxstats; ++j) - if (stat & (1<rxstats[j]++; - - if (stat & 0xFF) - iprint("rx: %lux\n", stat & 0xFF); - - size = ((rd->stat>>16) & 2047) - 4; - b = iallocb(sizeof(Etherpkt)); - memmove(b->wp, rd->buf, size); - b->wp += size; - etheriq(edev, b, 1); - 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 void -promiscuous(void *arg, int enable) -{ - Ether *edev; - Ctlr *ctlr; - - edev = arg; - ctlr = edev->ctlr; - ilock(&ctlr->lock); - iow8(ctlr, Rcr, (ior8(ctlr, Rcr) & ~(RxProm|RxBcast)) | - (enable ? RxProm : RxBcast)); - iunlock(&ctlr->lock); -} - -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"); - - n = ior16(ctlr, RhineMiiData); - - return n; -} - -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; -} - -/* multicast already on, don't need to do anything */ -static void -multicast(void*, uchar*, int) -{ -} - -static void -shutdown(Ether *edev) -{ - int i; - Ctlr *ctlr = edev->ctlr; - - ilock(&ctlr->lock); - pcisetbme(ctlr->pci); - - iow16(ctlr, Cr, ior16(ctlr, Cr) | Stop); - iow16(ctlr, Cr, ior16(ctlr, Cr) | Reset); - - for (i = 0; i < Nwait; ++i) { - if ((ior16(ctlr, Cr) & Reset) == 0) - break; - delay(5); - } - if (i == Nwait) - iprint("etherrhine: reset timeout\n"); - iunlock(&ctlr->lock); -} - -static void -init(Ether *edev) -{ - Ctlr *ctlr; - MiiPhy *phy; - int i; - - shutdown(edev); - - ctlr = edev->ctlr; - ilock(&ctlr->lock); - 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){ - iprint("etherrhine: init mii failure\n"); - return; - } - for (i = 0; i < NMiiPhy; ++i) - if (ctlr->mii.phy[i]) - if (ctlr->mii.phy[i]->oui != 0xFFFFF) - ctlr->mii.curphy = ctlr->mii.phy[i]; - - miistatus(&ctlr->mii); - phy = ctlr->mii.curphy; - edev->mbps = phy->speed; - - iow16(ctlr, Imr, 0); - iow16(ctlr, Cr, ior16(ctlr, Cr) | Stop); - iow8(ctlr, Rcr, ior8(ctlr, Rcr) | RxMcast); - - iunlock(&ctlr->lock); -} - -static Pcidev * -rhinematch(ulong) -{ - static int nrhines = 0; - int nfound = 0; - Pcidev *p = nil; - - while (p = pcimatch(p, 0x1106, 0)) - if (p->did == 0x3065) - if (++nfound > nrhines) { - nrhines++; - break; - } - return p; -} -static long -ifstat(Ether* edev, void* a, long n, ulong offset) -{ - int l = 0, i; - char *p; - Ctlr *ctlr; - ctlr = edev->ctlr; - p = malloc(BIGSTR); - - for (i = 0; i < Ntxstats; ++i) - if (txstatnames[i]) - l += snprint(p+l, BIGSTR - l, "tx: %s: %lud\n", txstatnames[i], ctlr->txstats[i]); - - for (i = 0; i < Nrxstats; ++i) - if (rxstatnames[i]) - l += snprint(p+l, BIGSTR - l, "rx: %s: %lud\n", rxstatnames[i], ctlr->rxstats[i]); - -/* - for (i = 0; i < NMiiPhyr; ++i) { - if ((i % 8) == 0) - l += snprint(p + l, BIGSTR - l, "\nmii 0x%02x:", i); - reg=miimir(&ctlr->mii, i); - reg=miimir(&ctlr->mii, i); - l += snprint(p + l, BIGSTR - l, " %4ux", reg); - } - - for (i = 0; i < 0x100; i+=1) { - if ((i % 16) == 0) - l += snprint(p + l, BIGSTR - l, "\nreg 0x%02x:", i); - else if ((i % 2) == 0) - l += snprint(p + l, BIGSTR - l, " "); - reg=ior8(ctlr, i); - l += snprint(p + l, BIGSTR - l, "%02x", reg); - } - l += snprint(p + l, BIGSTR - l, " \n"); -*/ - - - n = readstr(offset, a, n, p); - free(p); - - return n; -} - -static int -pnp(Ether *edev) -{ - Pcidev *p; - Ctlr *ctlr; - ulong port; - ulong size; - - p = rhinematch(edev->port); - if (p == nil) - return -1; - - port = p->mem[0].bar & ~1; - size = p->mem[0].size; - if (ioalloc(port, size, 0, "rhine") < 0) { - print("etherrhine: couldn't allocate port %lud\n", port); - return -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->interrupt = interrupt; - edev->arg = edev; - - edev->attach = attach; - edev->transmit = transmit; - edev->ifstat = ifstat; - edev->promiscuous = promiscuous; - edev->multicast = multicast; - edev->shutdown = shutdown; - return 0; -} - -void -etherrhinelink(void) -{ - addethercard("rhine", pnp); -} diff --git a/os/pc/ethersmc.c b/os/pc/ethersmc.c deleted file mode 100644 index 65ebffca..00000000 --- a/os/pc/ethersmc.c +++ /dev/null @@ -1,781 +0,0 @@ -/* - * SMC EtherEZ (SMC91cXX chip) PCMCIA card support. - */ - -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" -#include "etherif.h" - -enum { - IoSize = 0x10, /* port pool size */ - TxTimeout = 150, -}; - -enum { /* PCMCIA related */ - TupleFunce = 0x22, - TfNodeId = 0x04, -}; - -enum { /* bank 0 registers */ - Tcr = 0x0000, /* transmit control */ - Eph = 0x0002, /* ethernet protocol handler */ - Rcr = 0x0004, /* receiver control */ - Counter = 0x0006, /* statistics counter */ - MemInfo = 0x0008, - MemCfg = 0x000A, -}; - -enum { /* bank 1 registers */ - Config = 0x0000, - BaseAddr = 0x0002, - Addr0 = 0x0004, /* ethernet address */ - Addr1 = 0x0006, - Addr2 = 0x0008, - General = 0x000A, - Control = 0x000C, -}; - -enum { /* bank 2 registers */ - MmuCmd = 0x0000, - PktNo = 0x0002, - AllocRes = 0x0003, - FifoPorts = 0x0004, - Pointer = 0x0006, - Data1 = 0x0008, - Interrupt = 0x000C, - IntrMask = 0x000D, -}; - -enum { /* bank 3 registers */ - Mcast0 = 0x0000, - Mcast2 = 0x0002, - Mcast4 = 0x0004, - Mcast6 = 0x0006, - Revision = 0x000A, -}; - -enum { - BankSelect = 0x000E /* bank select register */ -}; - -enum { - BsrMask = 0xFF00, /* mask for chip identification */ - BsrId = 0x3300, -}; - - -enum { /* Tcr values */ - TcrClear = 0x0000, - TcrEnable = 0x0001, /* enable transmit */ - TcrLoop = 0x0002, /* enable internal analogue loopback */ - TcrForceCol = 0x0004, /* force collision on next tx */ - TcrPadEn = 0x0080, /* pad short packets to 64 bytes */ - TcrNoCrc = 0x0100, /* do not append CRC */ - TcrMonCns = 0x0400, /* monitor carrier status */ - TcrFduplx = 0x0800, - TcrStpSqet = 0x1000, - TcrEphLoop = 0x2000, - TcrNormal = TcrEnable, -}; - -enum { /* Eph values */ - EphTxOk = 0x0001, - Eph1Col = 0x0002, /* single collision */ - EphMCol = 0x0004, /* multiple collisions */ - EphTxMcast = 0x0008, /* multicast transmit */ - Eph16Col = 0x0010, /* 16 collisions, tx disabled */ - EphSqet = 0x0020, /* SQE test failed, tx disabled */ - EphTxBcast = 0x0040, /* broadcast tx */ - EphDefr = 0x0080, /* deffered tx */ - EphLatCol = 0x0200, /* late collision, tx disabled */ - EphLostCarr = 0x0400, /* lost carrier, tx disabled */ - EphExcDefr = 0x0800, /* excessive defferals */ - EphCntRol = 0x1000, /* ECR counter(s) rolled over */ - EphRxOvrn = 0x2000, /* receiver overrun, packets dropped */ - EphLinkOk = 0x4000, - EphTxUnrn = 0x8000, /* tx underrun */ -}; - -enum { /* Rcr values */ - RcrClear = 0x0000, - RcrPromisc = 0x0002, - RcrAllMcast = 0x0004, - RcrEnable = 0x0100, - RcrStripCrc = 0x0200, - RcrSoftReset = 0x8000, - RcrNormal = RcrStripCrc | RcrEnable, -}; - -enum { /* Counter value masks */ - CntColMask = 0x000F, /* collisions */ - CntMColMask = 0x00F0, /* multiple collisions */ - CntDtxMask = 0x0F00, /* deferred transmits */ - CntExDtxMask = 0xF000, /* excessively deferred transmits */ - - CntColShr = 1, - CntMColShr = 4, - CntDtxShr = 8, -}; - -enum { /* MemInfo value masks */ - MirTotalMask = 0x00FF, - MirFreeMask = 0xFF00, -}; - -enum { /* Config values */ - CfgIrqSel0 = 0x0002, - CfgIrqSel1 = 0x0004, - CfgDisLink = 0x0040, /* disable 10BaseT link test */ - Cfg16Bit = 0x0080, - CfgAuiSelect = 0x0100, - CfgSetSqlch = 0x0200, - CfgFullStep = 0x0400, - CfgNoWait = 0x1000, - CfgMiiSelect = 0x8000, -}; - -enum { /* Control values */ - CtlStore = 0x0001, /* store to EEPROM */ - CtlReload = 0x0002, /* reload EEPROM into registers */ - CtlEeSelect = 0x0004, /* select registers for reload/store */ - CtlTeEnable = 0x0020, /* tx error detection via eph irq */ - CtlCrEnable = 0x0040, /* counter rollover via eph irq */ - CtlLeEnable = 0x0080, /* link error detection via eph irq*/ - CtlAutoRls = 0x0800, /* auto release mode */ - CtlPowerDn = 0x2000, -}; - -enum { /* MmuCmd values */ - McBusy = 0x0001, - McAlloc = 0x0020, /* | with number of 256 byte packets - 1 */ - McReset = 0x0040, - McRelease = 0x0080, /* dequeue (but not free) current rx packet */ - McFreePkt = 0x00A0, /* dequeue and free current rx packet */ - McEnqueue = 0x00C0, /* enqueue the packet for tx */ - McTxReset = 0x00E0, /* reset transmit queues */ -}; - -enum { /* AllocRes values */ - ArFailed = 0x80, -}; - -enum { /* FifoPorts values */ - FpTxEmpty = 0x0080, - FpRxEmpty = 0x8000, - FpTxMask = 0x007F, - FpRxMask = 0x7F00, -}; - -enum { /* Pointer values */ - PtrRead = 0x2000, - PtrAutoInc = 0x4000, - PtrRcv = 0x8000, -}; - -enum { /* Interrupt values */ - IntRcv = 0x0001, - IntTxError = 0x0002, - IntTxEmpty = 0x0004, - IntAlloc = 0x0008, - IntRxOvrn = 0x0010, - IntEph = 0x0020, -}; - -enum { /* transmit status bits */ - TsSuccess = 0x0001, - Ts16Col = 0x00A0, - TsLatCol = 0x0200, - TsLostCar = 0x0400, -}; - -enum { /* receive status bits */ - RsMcast = 0x0001, - RsTooShort = 0x0400, - RsTooLong = 0x0800, - RsOddFrame = 0x1000, - RsBadCrc = 0x2000, - RsAlgnErr = 0x8000, - RsError = RsAlgnErr | RsBadCrc | RsTooLong | RsTooShort, -}; - -enum { - RxLenMask = 0x07FF, /* significant rx len bits */ - HdrSize = 6, /* packet header length */ - PageSize = 256, /* page length */ -}; - -typedef struct Smc91xx Smc91xx; -struct Smc91xx { - Lock; - ushort rev; - int attached; - Block *txbp; - ulong txtime; - - ulong rovrn; - ulong lcar; - ulong col; - ulong scol; - ulong mcol; - ulong lcol; - ulong dfr; -}; - -#define SELECT_BANK(x) outs(port + BankSelect, x) - -static int -readnodeid(int slot, Ether* ether) -{ - uchar data[Eaddrlen + 1]; - int len; - - len = sizeof(data); - if (pcmcistuple(slot, TupleFunce, TfNodeId, data, len) != len) - return -1; - - if (data[0] != Eaddrlen) - return -1; - - memmove(ether->ea, &data[1], Eaddrlen); - return 0; -} - -static void -chipreset(Ether* ether) -{ - int port; - int i; - - port = ether->port; - - /* reset the chip */ - SELECT_BANK(0); - outs(port + Rcr, RcrSoftReset); - delay(1); - outs(port + Rcr, RcrClear); - outs(port + Tcr, TcrClear); - SELECT_BANK(1); - outs(port + Control, CtlAutoRls | CtlTeEnable | - CtlCrEnable); - - for(i = 0; i < 6; i++) { - outb(port + Addr0 + i, ether->ea[i]); - } - - SELECT_BANK(2); - outs(port + MmuCmd, McReset); -} - -static void -chipenable(Ether* ether) -{ - int port; - - port = ether->port; - SELECT_BANK(0); - outs(port + Tcr, TcrNormal); - outs(port + Rcr, RcrNormal); - SELECT_BANK(2); - outb(port + IntrMask, IntEph | IntRxOvrn | IntRcv); -} - -static void -attach(Ether *ether) -{ - Smc91xx* ctlr; - - ctlr = ether->ctlr; - ilock(ctlr); - - if (ctlr->attached) { - iunlock(ctlr); - return; - } - - chipenable(ether); - ctlr->attached = 1; - iunlock(ctlr); -} - -static void -txstart(Ether* ether) -{ - int port; - Smc91xx* ctlr; - Block* bp; - int len, npages; - int pno; - - /* assumes ctlr is locked and bank 2 is selected */ - /* leaves bank 2 selected on return */ - port = ether->port; - ctlr = ether->ctlr; - - if (ctlr->txbp) { - bp = ctlr->txbp; - ctlr->txbp = 0; - } else { - bp = qget(ether->oq); - if (bp == 0) - return; - - len = BLEN(bp); - npages = (len + HdrSize) / PageSize; - outs(port + MmuCmd, McAlloc | npages); - } - - pno = inb(port + AllocRes); - if (pno & ArFailed) { - outb(port + IntrMask, inb(port + IntrMask) | IntAlloc); - ctlr->txbp = bp; - ctlr->txtime = MACHP(0)->ticks; - return; - } - - outb(port + PktNo, pno); - outs(port + Pointer, PtrAutoInc); - - len = BLEN(bp); - outs(port + Data1, 0); - outb(port + Data1, (len + HdrSize) & 0xFF); - outb(port + Data1, (len + HdrSize) >> 8); - outss(port + Data1, bp->rp, len / 2); - if ((len & 1) == 0) { - outs(port + Data1, 0); - } else { - outb(port + Data1, bp->rp[len - 1]); - outb(port + Data1, 0x20); /* no info what 0x20 means */ - } - - outb(port + IntrMask, inb(port + IntrMask) | - IntTxError | IntTxEmpty); - - outs(port + MmuCmd, McEnqueue); - freeb(bp); -} - -static void -receive(Ether* ether) -{ - int port; - Block* bp; - int pktno, status, len; - - /* assumes ctlr is locked and bank 2 is selected */ - /* leaves bank 2 selected on return */ - port = ether->port; - - pktno = ins(port + FifoPorts); - if (pktno & FpRxEmpty) { - return; - } - - outs(port + Pointer, PtrRead | PtrRcv | PtrAutoInc); - status = ins(port + Data1); - len = ins(port + Data1) & RxLenMask - HdrSize; - - if (status & RsOddFrame) - len++; - - if ((status & RsError) || (bp = iallocb(len)) == 0) { - - if (status & RsAlgnErr) - ether->frames++; - if (status & (RsTooShort | RsTooLong)) - ether->buffs++; - if (status & RsBadCrc) - ether->crcs++; - - outs(port + MmuCmd, McRelease); - return; - } - - /* packet length is padded to word */ - inss(port + Data1, bp->rp, len / 2); - bp->wp = bp->rp + (len & ~1); - - if (len & 1) { - *bp->wp = inb(port + Data1); - bp->wp++; - } - - etheriq(ether, bp, 1); - ether->inpackets++; - outs(port + MmuCmd, McRelease); -} - -static void -txerror(Ether* ether) -{ - int port; - Smc91xx* ctlr; - int save_pkt; - int pktno, status; - - /* assumes ctlr is locked and bank 2 is selected */ - /* leaves bank 2 selected on return */ - port = ether->port; - ctlr = ether->ctlr; - - save_pkt = inb(port + PktNo); - - pktno = ins(port + FifoPorts) & FpTxMask; - outb(port + PktNo, pktno); - outs(port + Pointer, PtrAutoInc | PtrRead); - status = ins(port + Data1); - - if (status & TsLostCar) - ctlr->lcar++; - - if (status & TsLatCol) - ctlr->lcol++; - - if (status & Ts16Col) - ctlr->scol++; - - ether->oerrs++; - - SELECT_BANK(0); - outs(port + Tcr, ins(port + Tcr) | TcrEnable); - - SELECT_BANK(2); - outs(port + MmuCmd, McFreePkt); - - outb(port + PktNo, save_pkt); -} - -static void -eph_irq(Ether* ether) -{ - int port; - Smc91xx* ctlr; - ushort status; - int n; - - /* assumes ctlr is locked and bank 2 is selected */ - /* leaves bank 2 selected on return */ - port = ether->port; - ctlr = ether->ctlr; - - SELECT_BANK(0); - status = ins(port + Eph); - - if (status & EphCntRol) { - /* read the counter register even if we don't need it */ - /* otherwise we will keep getting this interrupt */ - n = ins(port + Counter); - ctlr->col += (n & CntColMask) >> CntColShr; - ctlr->mcol += (n & CntMColMask) >> CntMColShr; - ctlr->dfr += (n & CntDtxMask) >> CntDtxShr; - } - - /* if there was a transmit error, Tcr is disabled */ - outs(port + Tcr, ins(port + Tcr) | TcrEnable); - - /* clear a link error interrupt */ - SELECT_BANK(1); - outs(port + Control, CtlAutoRls); - outs(port + Control, CtlAutoRls | CtlTeEnable | CtlCrEnable); - - SELECT_BANK(2); -} - -static void -transmit(Ether* ether) -{ - Smc91xx* ctlr; - int port, n; - - ctlr = ether->ctlr; - port = ether->port; - ilock(ctlr); - - if (ctlr->txbp) { - n = TK2MS(MACHP(0)->ticks - ctlr->txtime); - if (n > TxTimeout) { - chipreset(ether); - chipenable(ether); - freeb(ctlr->txbp); - ctlr->txbp = 0; - } - iunlock(ctlr); - return; - } - - SELECT_BANK(2); - txstart(ether); - iunlock(ctlr); -} - -static void -interrupt(Ureg*, void *arg) -{ - int port; - Smc91xx* ctlr; - Ether* ether; - int save_bank; - int save_pointer; - int mask, status; - - ether = arg; - port = ether->port; - ctlr = ether->ctlr; - - ilock(ctlr); - save_bank = ins(port + BankSelect); - SELECT_BANK(2); - save_pointer = ins(port + Pointer); - - mask = inb(port + IntrMask); - outb(port + IntrMask, 0); - - while ((status = inb(port + Interrupt) & mask) != 0) { - if (status & IntRcv) { - receive(ether); - } - - if (status & IntTxError) { - txerror(ether); - } - - if (status & IntTxEmpty) { - outb(port + Interrupt, IntTxEmpty); - outb(port + IntrMask, mask & ~IntTxEmpty); - txstart(ether); - mask = inb(port + IntrMask); - } - - if (status & IntAlloc) { - outb(port + IntrMask, mask & ~IntAlloc); - txstart(ether);; - mask = inb(port + IntrMask); - } - - if (status & IntRxOvrn) { - ctlr->rovrn++; - ether->misses++; - outb(port + Interrupt,IntRxOvrn); - } - - if (status & IntEph) - eph_irq(ether); - } - - outb(port + IntrMask, mask); - outs(port + Pointer, save_pointer); - outs(port + BankSelect, save_bank); - iunlock(ctlr); -} - -static void -promiscuous(void* arg, int on) -{ - int port; - Smc91xx *ctlr; - Ether* ether; - ushort x; - - ether = arg; - port = ether->port; - ctlr = ether->ctlr; - - ilock(ctlr); - SELECT_BANK(0); - x = ins(port + Rcr); - if (on) - x |= RcrPromisc; - else - x &= ~RcrPromisc; - - outs(port + Rcr, x); - iunlock(ctlr); -} - -static void -multicast(void* arg, uchar *addr, int on) -{ - int port; - Smc91xx*ctlr; - Ether *ether; - ushort x; - - USED(addr, on); - - ether = arg; - port = ether->port; - ctlr = ether->ctlr; - ilock(ctlr); - - SELECT_BANK(0); - x = ins(port + Rcr); - - if (ether->nmaddr) - x |= RcrAllMcast; - else - x &= ~RcrAllMcast; - - outs(port + Rcr, x); - iunlock(ctlr); -} - -static long -ifstat(Ether* ether, void* a, long n, ulong offset) -{ - static char *chiprev[] = { - [3] "92", - [5] "95", - [7] "100", - [8] "100-FD", - [9] "110", - }; - - Smc91xx* ctlr; - char* p; - int r, len; - char* s; - - if (n == 0) - return 0; - - ctlr = ether->ctlr; - p = malloc(READSTR); - - s = 0; - if (ctlr->rev > 0) { - r = ctlr->rev >> 4; - if (r < nelem(chiprev)) - s = chiprev[r]; - - if (r == 4) { - if ((ctlr->rev & 0x0F) >= 6) - s = "96"; - else - s = "94"; - } - } - - len = snprint(p, READSTR, "rev: 91c%s\n", (s) ? s : "???"); - len += snprint(p + len, READSTR - len, "rxovrn: %uld\n", ctlr->rovrn); - len += snprint(p + len, READSTR - len, "lcar: %uld\n", ctlr->lcar); - len += snprint(p + len, READSTR - len, "col: %uld\n", ctlr->col); - len += snprint(p + len, READSTR - len, "16col: %uld\n", ctlr->scol); - len += snprint(p + len, READSTR - len, "mcol: %uld\n", ctlr->mcol); - len += snprint(p + len, READSTR - len, "lcol: %uld\n", ctlr->lcol); - len += snprint(p + len, READSTR - len, "dfr: %uld\n", ctlr->dfr); - USED(len); - - n = readstr(offset, a, n, p); - free(p); - - return n; -} - -static int -reset(Ether* ether) -{ - int port; - int i, x; - char* type; - Smc91xx* ctlr; - int slot; - uchar ea[Eaddrlen]; - - if (ether->irq == 0) - ether->irq = 9; - - if (ether->port == 0) - ether->port = 0x100; - - type = "8020"; - for(i = 0; i < ether->nopt; i++) { - if (cistrncmp(ether->opt[i], "id=", 3)) - continue; - type = ðer->opt[i][3]; - break; - } - - if ((slot = pcmspecial(type, ether)) < 0) - return -1; - - if (ioalloc(ether->port, IoSize, 0, "smc91cXX") < 0) { - pcmspecialclose(slot); - return -1; - } - - ether->ctlr = malloc(sizeof(Smc91xx)); - ctlr = ether->ctlr; - if (ctlr == 0) { - iofree(ether->port); - pcmspecialclose(slot); - return -1; - } - - ilock(ctlr); - ctlr->rev = 0; - ctlr->txbp = nil; - ctlr->attached = 0; - ctlr->rovrn = 0; - ctlr->lcar = 0; - ctlr->col = 0; - ctlr->scol = 0; - ctlr->mcol = 0; - ctlr->lcol = 0; - ctlr->dfr = 0; - - port = ether->port; - - SELECT_BANK(1); - if ((ins(port + BankSelect) & BsrMask) != BsrId) { - outs(port + Control, 0); /* try powering up the chip */ - delay(55); - } - - outs(port + Config, ins(port + Config) | Cfg16Bit); - x = ins(port + BaseAddr); - - if (((ins(port + BankSelect) & BsrMask) != BsrId) || - ((x >> 8) == (x & 0xFF))) { - iunlock(ctlr); - iofree(port); - pcmspecialclose(slot); - return -1; - } - - SELECT_BANK(3); - ctlr->rev = ins(port + Revision) & 0xFF; - - memset(ea, 0, Eaddrlen); - if (memcmp(ea, ether->ea, Eaddrlen) == 0) { - if (readnodeid(slot, ether) < 0) { - print("Smc91cXX: cannot find ethernet address\n"); - iunlock(ctlr); - iofree(port); - pcmspecialclose(slot); - return -1; - } - } - - chipreset(ether); - - ether->attach = attach; - ether->transmit = transmit; - ether->interrupt = interrupt; - ether->ifstat = ifstat; - ether->promiscuous = promiscuous; - ether->multicast = multicast; - ether->arg = ether; - iunlock(ctlr); - return 0; -} - -void -ethersmclink(void) -{ - addethercard("smc91cXX", reset); -} diff --git a/os/pc/ethervt6102.c b/os/pc/ethervt6102.c deleted file mode 100644 index 20d43a4e..00000000 --- a/os/pc/ethervt6102.c +++ /dev/null @@ -1,1025 +0,0 @@ -/* - * VIA VT6102 Fast Ethernet Controller (Rhine II). - * To do: - * cache-line size alignments - done - * reduce tx interrupts - * use 2 descriptors on tx for alignment - done - * reorganise initialisation/shutdown/reset - * adjust Tx FIFO threshold on underflow - untested - * why does the link status never cause an interrupt? - * use the lproc as a periodic timer for stalls, etc. - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" - -#include "etherif.h" -#include "ethermii.h" - -enum { - Par0 = 0x00, /* Ethernet Address */ - Rcr = 0x06, /* Receive Configuration */ - Tcr = 0x07, /* Transmit Configuration */ - Cr = 0x08, /* Control */ - Isr = 0x0C, /* Interrupt Status */ - Imr = 0x0E, /* Interrupt Mask */ - Rxdaddr = 0x18, /* Current Rx Descriptor Address */ - Txdaddr = 0x1C, /* Current Tx Descriptor Address */ - Phyadr = 0x6C, /* Phy Address */ - Miisr = 0x6D, /* MII Status */ - Bcr0 = 0x6E, /* Bus Control */ - Bcr1 = 0x6F, - Miicr = 0x70, /* MII Control */ - Miiadr = 0x71, /* MII Address */ - Miidata = 0x72, /* MII Data */ - Eecsr = 0x74, /* EEPROM Control and Status */ -}; - -enum { /* Rcr */ - Sep = 0x01, /* Accept Error Packets */ - Ar = 0x02, /* Accept Small Packets */ - Am = 0x04, /* Accept Multicast */ - Ab = 0x08, /* Accept Broadcast */ - Prom = 0x10, /* Accept Physical Address Packets */ - RrftMASK = 0xE0, /* Receive FIFO Threshold */ - RrftSHIFT = 5, - Rrft64 = 0<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, w) (outl((c)->port+(r), (ulong)(w))) - -static char* rxstats[Nrxstats] = { - "Receiver Error", - "CRC Error", - "Frame Alignment Error", - "FIFO Overflow", - "Long Packet", - "Runt Packet", - "System Error", - "Buffer Underflow Error", -}; -static char* txstats[Ntxstats] = { - "Aborted after Excessive Collisions", - "Out of Window Collision Seen", - "Carrier Sense Lost", - "FIFO Underflow", - "Invalid Td", - "System Error", - nil, - "Excessive Collisions", -}; - -static long -vt6102ifstat(Ether* edev, void* a, long n, ulong offset) -{ - char *p; - Ctlr *ctlr; - int i, l, r; - - ctlr = edev->ctlr; - - p = malloc(2*READSTR); - l = 0; - for(i = 0; i < Nrxstats; i++){ - l += snprint(p+l, 2*READSTR-l, "%s: %ud\n", - rxstats[i], ctlr->rxstats[i]); - } - for(i = 0; i < Ntxstats; i++){ - if(txstats[i] == nil) - continue; - l += snprint(p+l, 2*READSTR-l, "%s: %ud\n", - txstats[i], ctlr->txstats[i]); - } - l += snprint(p+l, 2*READSTR-l, "cls: %ud\n", ctlr->cls); - l += snprint(p+l, 2*READSTR-l, "intr: %ud\n", ctlr->intr); - l += snprint(p+l, 2*READSTR-l, "lintr: %ud\n", ctlr->lintr); - l += snprint(p+l, 2*READSTR-l, "lsleep: %ud\n", ctlr->lsleep); - l += snprint(p+l, 2*READSTR-l, "rintr: %ud\n", ctlr->rintr); - l += snprint(p+l, 2*READSTR-l, "tintr: %ud\n", ctlr->tintr); - l += snprint(p+l, 2*READSTR-l, "taligned: %ud\n", ctlr->taligned); - l += snprint(p+l, 2*READSTR-l, "tsplit: %ud\n", ctlr->tsplit); - l += snprint(p+l, 2*READSTR-l, "tcopied: %ud\n", ctlr->tcopied); - l += snprint(p+l, 2*READSTR-l, "txdw: %ud\n", ctlr->txdw); - l += snprint(p+l, 2*READSTR-l, "tft: %ud\n", ctlr->tft); - - if(ctlr->mii != nil && ctlr->mii->curphy != nil){ - l += snprint(p+l, 2*READSTR, "phy: "); - for(i = 0; i < NMiiPhyr; i++){ - if(i && ((i & 0x07) == 0)) - l += snprint(p+l, 2*READSTR-l, "\n "); - r = miimir(ctlr->mii, i); - l += snprint(p+l, 2*READSTR-l, " %4.4uX", r); - } - snprint(p+l, 2*READSTR-l, "\n"); - } - snprint(p+l, 2*READSTR-l, "\n"); - - n = readstr(offset, a, n, p); - free(p); - - return n; -} - -static void -vt6102promiscuous(void* arg, int on) -{ - int rcr; - Ctlr *ctlr; - Ether *edev; - - edev = arg; - ctlr = edev->ctlr; - rcr = csr8r(ctlr, Rcr); - if(on) - rcr |= Prom; - else - rcr &= ~Prom; - csr8w(ctlr, Rcr, rcr); -} - -static void -vt6102multicast(void* arg, uchar* addr, int on) -{ - /* - * For now Am is set in Rcr. - * Will need to interlock with promiscuous - * when this gets filled in. - */ - USED(arg, addr, on); -} - -static int -vt6102wakeup(void* v) -{ - return *((int*)v) != 0; -} - -static void -vt6102imr(Ctlr* ctlr, int imr) -{ - ilock(&ctlr->clock); - ctlr->imr |= imr; - csr16w(ctlr, Imr, ctlr->imr); - iunlock(&ctlr->clock); -} - -static void -vt6102lproc(void* arg) -{ - Ctlr *ctlr; - Ether *edev; - MiiPhy *phy; - - edev = arg; - ctlr = edev->ctlr; - for(;;){ - if(ctlr->mii == nil || ctlr->mii->curphy == nil) - break; - if(miistatus(ctlr->mii) < 0) - goto enable; - - phy = ctlr->mii->curphy; - ilock(&ctlr->clock); - if(phy->fd) - ctlr->cr |= Fdx; - else - ctlr->cr &= ~Fdx; - csr16w(ctlr, Cr, ctlr->cr); - iunlock(&ctlr->clock); -enable: - ctlr->lwakeup = 0; - vt6102imr(ctlr, Srci); - - ctlr->lsleep++; - sleep(&ctlr->lrendez, vt6102wakeup, &ctlr->lwakeup); - - } - pexit("vt6102lproc: done", 1); -} - -static void -vt6102attach(Ether* edev) -{ - int i; - Ctlr *ctlr; - Ds *ds, *prev; - uchar *alloc, *bounce; - char name[KNAMELEN]; - - ctlr = edev->ctlr; - qlock(&ctlr->alock); - if(ctlr->alloc != nil){ - qunlock(&ctlr->alock); - return; - } - - /* - * Descriptor and bounce-buffer space. - * Must all be aligned on a 4-byte boundary, - * but try to align on cache-lines. - */ - ctlr->nrd = Nrd; - ctlr->ntd = Ntd; - alloc = malloc((ctlr->nrd+ctlr->ntd)*ctlr->cls + ctlr->ntd*Txcopy + ctlr->cls-1); - if(alloc == nil){ - qunlock(&ctlr->alock); - return; - } - ctlr->alloc = alloc; - alloc = (uchar*)ROUNDUP((ulong)alloc, ctlr->cls); - - ctlr->rd = (Ds*)alloc; - - if(waserror()){ - ds = ctlr->rd; - for(i = 0; i < ctlr->nrd; i++){ - if(ds->bp != nil){ - freeb(ds->bp); - ds->bp = nil; - } - if((ds = ds->next) == nil) - break; - } - free(ctlr->alloc); - ctlr->alloc = nil; - qunlock(&ctlr->alock); - nexterror(); - } - - prev = ctlr->rd + ctlr->nrd-1; - for(i = 0; i < ctlr->nrd; i++){ - ds = (Ds*)alloc; - alloc += ctlr->cls; - - ds->control = Rdbsz; - ds->branch = PCIWADDR(alloc); - - ds->bp = iallocb(Rdbsz+3); - if(ds->bp == nil) - error("vt6102: can't allocate receive ring\n"); - ds->bp->rp = (uchar*)ROUNDUP((ulong)ds->bp->rp, 4); - ds->addr = PCIWADDR(ds->bp->rp); - - ds->next = (Ds*)alloc; - ds->prev = prev; - prev = ds; - - ds->status = Own; - } - prev->branch = 0; - prev->next = ctlr->rd; - prev->status = 0; - ctlr->rdh = ctlr->rd; - - ctlr->td = (Ds*)alloc; - prev = ctlr->td + ctlr->ntd-1; - bounce = alloc + ctlr->ntd*ctlr->cls; - for(i = 0; i < ctlr->ntd; i++){ - ds = (Ds*)alloc; - alloc += ctlr->cls; - - ds->bounce = bounce; - bounce += Txcopy; - ds->next = (Ds*)alloc; - ds->prev = prev; - prev = ds; - } - prev->next = ctlr->td; - ctlr->tdh = ctlr->tdt = ctlr->td; - ctlr->tdused = 0; - - ctlr->cr = Dpoll|Rdmd|Txon|Rxon|Strt; - /*Srci|Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx*/ - ctlr->imr = Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx; - - ilock(&ctlr->clock); - csr32w(ctlr, Rxdaddr, PCIWADDR(ctlr->rd)); - csr32w(ctlr, Txdaddr, PCIWADDR(ctlr->td)); - csr16w(ctlr, Isr, ~0); - csr16w(ctlr, Imr, ctlr->imr); - csr16w(ctlr, Cr, ctlr->cr); - iunlock(&ctlr->clock); - - snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno); - kproc(name, vt6102lproc, edev, 0); - - qunlock(&ctlr->alock); - poperror(); -} - -static void -vt6102transmit(Ether* edev) -{ - Block *bp; - Ctlr *ctlr; - Ds *ds, *next; - int control, i, o, prefix, size, tdused, timeo; - - ctlr = edev->ctlr; - - ilock(&ctlr->tlock); - - /* - * Free any completed packets - */ - ds = ctlr->tdh; - for(tdused = ctlr->tdused; tdused > 0; tdused--){ - /* - * For some errors the chip will turn the Tx engine - * off. Wait for that to happen. - * Could reset and re-init the chip here if it doesn't - * play fair. - * To do: adjust Tx FIFO threshold on underflow. - */ - if(ds->status & (Abt|Tbuff|Udf)){ - for(timeo = 0; timeo < 1000; timeo++){ - if(!(csr16r(ctlr, Cr) & Txon)) - break; - microdelay(1); - } - ds->status = Own; - csr32w(ctlr, Txdaddr, PCIWADDR(ds)); - } - - if(ds->status & Own) - break; - ds->addr = 0; - ds->branch = 0; - - if(ds->bp != nil){ - freeb(ds->bp); - ds->bp = nil; - } - for(i = 0; i < Ntxstats-1; i++){ - if(ds->status & (1<txstats[i]++; - } - ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT; - - ds = ds->next; - } - ctlr->tdh = ds; - - /* - * Try to fill the ring back up. - */ - ds = ctlr->tdt; - while(tdused < ctlr->ntd-2){ - if((bp = qget(edev->oq)) == nil) - break; - tdused++; - - size = BLEN(bp); - prefix = 0; - - if(o = (((int)bp->rp) & 0x03)){ - prefix = Txcopy-o; - if(prefix > size) - prefix = size; - memmove(ds->bounce, bp->rp, prefix); - ds->addr = PCIWADDR(ds->bounce); - bp->rp += prefix; - size -= prefix; - } - - next = ds->next; - ds->branch = PCIWADDR(ds->next); - - if(size){ - if(prefix){ - next->bp = bp; - next->addr = PCIWADDR(bp->rp); - next->branch = PCIWADDR(next->next); - next->control = Edp|Chain|((size<next; - tdused++; - ctlr->tsplit++; - } - else{ - ds->bp = bp; - ds->addr = PCIWADDR(bp->rp); - control = Edp|Stp|((size<taligned++; - } - } - else{ - freeb(bp); - control = Edp|Stp|((prefix<tcopied++; - } - - ds->control = control; - if(tdused >= ctlr->ntd-2){ - ds->control |= Ic; - ctlr->txdw++; - } - coherence(); - ds->status = Own; - - ds = next; - } - ctlr->tdt = ds; - ctlr->tdused = tdused; - if(ctlr->tdused) - csr16w(ctlr, Cr, Tdmd|ctlr->cr); - - iunlock(&ctlr->tlock); -} - -static void -vt6102receive(Ether* edev) -{ - Ds *ds; - Block *bp; - Ctlr *ctlr; - int i, len; - - ctlr = edev->ctlr; - - ds = ctlr->rdh; - while(!(ds->status & Own) && ds->status != 0){ - if(ds->status & Rerr){ - for(i = 0; i < Nrxstats; i++){ - if(ds->status & (1<rxstats[i]++; - } - } - else if(bp = iallocb(Rdbsz+3)){ - len = ((ds->status & LengthMASK)>>LengthSHIFT)-4; - ds->bp->wp = ds->bp->rp+len; - etheriq(edev, ds->bp, 1); - bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4); - ds->addr = PCIWADDR(bp->rp); - ds->bp = bp; - } - ds->control = Rdbsz; - ds->branch = 0; - ds->status = 0; - - ds->prev->branch = PCIWADDR(ds); - coherence(); - ds->prev->status = Own; - - ds = ds->next; - } - ctlr->rdh = ds; - - csr16w(ctlr, Cr, ctlr->cr); -} - -static void -vt6102interrupt(Ureg*, void* arg) -{ - Ctlr *ctlr; - Ether *edev; - int imr, isr, r, timeo; - - edev = arg; - ctlr = edev->ctlr; - - ilock(&ctlr->clock); - csr16w(ctlr, Imr, 0); - imr = ctlr->imr; - ctlr->intr++; - for(;;){ - if((isr = csr16r(ctlr, Isr)) != 0) - csr16w(ctlr, Isr, isr); - if((isr & ctlr->imr) == 0) - break; - - if(isr & Srci){ - imr &= ~Srci; - ctlr->lwakeup = isr & Srci; - wakeup(&ctlr->lrendez); - isr &= ~Srci; - ctlr->lintr++; - } - if(isr & (Norbf|Pktrace|Ovfi|Ru|Rxe|Prx)){ - vt6102receive(edev); - isr &= ~(Norbf|Pktrace|Ovfi|Ru|Rxe|Prx); - ctlr->rintr++; - } - if(isr & (Abti|Udfi|Tu|Txe|Ptx)){ - if(isr & (Abti|Udfi|Tu)){ - for(timeo = 0; timeo < 1000; timeo++){ - if(!(csr16r(ctlr, Cr) & Txon)) - break; - microdelay(1); - } - - if((isr & Udfi) && ctlr->tft < CtftSAF){ - ctlr->tft += 1<tft); - } - } - vt6102transmit(edev); - isr &= ~(Abti|Udfi|Tu|Txe|Ptx); - ctlr->tintr++; - } - if(isr) - panic("vt6102: isr %4.4uX\n", isr); - } - ctlr->imr = imr; - csr16w(ctlr, Imr, ctlr->imr); - iunlock(&ctlr->clock); -} - -static int -vt6102miimicmd(Mii* mii, int pa, int ra, int cmd, int data) -{ - Ctlr *ctlr; - int r, timeo; - - ctlr = mii->ctlr; - - csr8w(ctlr, Miicr, 0); - r = csr8r(ctlr, Phyadr); - csr8w(ctlr, Phyadr, (r & ~PhyadMASK)|pa); - csr8w(ctlr, Phyadr, pa); - csr8w(ctlr, Miiadr, ra); - if(cmd == Wcmd) - csr16w(ctlr, Miidata, data); - csr8w(ctlr, Miicr, cmd); - - for(timeo = 0; timeo < 10000; timeo++){ - if(!(csr8r(ctlr, Miicr) & cmd)) - break; - microdelay(1); - } - if(timeo >= 10000) - return -1; - - if(cmd == Wcmd) - return 0; - return csr16r(ctlr, Miidata); -} - -static int -vt6102miimir(Mii* mii, int pa, int ra) -{ - return vt6102miimicmd(mii, pa, ra, Rcmd, 0); -} - -static int -vt6102miimiw(Mii* mii, int pa, int ra, int data) -{ - return vt6102miimicmd(mii, pa, ra, Wcmd, data); -} - -static int -vt6102detach(Ctlr* ctlr) -{ - int timeo; - - /* - * Soft reset the controller. - */ - csr16w(ctlr, Cr, Sfrst); - for(timeo = 0; timeo < 10000; timeo++){ - if(!(csr16r(ctlr, Cr) & Sfrst)) - break; - microdelay(1); - } - if(timeo >= 1000) - return -1; - - return 0; -} - -static int -vt6102reset(Ctlr* ctlr) -{ - MiiPhy *phy; - int i, r, timeo; - - if(vt6102detach(ctlr) < 0) - return -1; - - /* - * Load the MAC address into the PAR[01] - * registers. - */ - r = csr8r(ctlr, Eecsr); - csr8w(ctlr, Eecsr, Autold|r); - for(timeo = 0; timeo < 100; timeo++){ - if(!(csr8r(ctlr, Cr) & Autold)) - break; - microdelay(1); - } - if(timeo >= 100) - return -1; - - for(i = 0; i < Eaddrlen; i++) - ctlr->par[i] = csr8r(ctlr, Par0+i); - - /* - * 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|ctlr->tft); - - r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep); - csr8w(ctlr, Rcr, r|Ab|Am); - - r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0); - csr8w(ctlr, Tcr, r); - - /* - * Link management. - */ - if((ctlr->mii = malloc(sizeof(Mii))) == nil) - return -1; - ctlr->mii->mir = vt6102miimir; - ctlr->mii->miw = vt6102miimiw; - ctlr->mii->ctlr = ctlr; - - if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){ - free(ctlr->mii); - ctlr->mii = nil; - return -1; - } - // print("oui %X phyno %d\n", phy->oui, phy->phyno); - USED(phy); - - //miiane(ctlr->mii, ~0, ~0, ~0); - - return 0; -} - -static void -vt6102pci(void) -{ - Pcidev *p; - Ctlr *ctlr; - int cls, port; - - p = nil; - while(p = pcimatch(p, 0, 0)){ - if(p->ccrb != Pcibcnet || p->ccru != Pciscether) - continue; - - switch((p->did<<16)|p->vid){ - default: - continue; - case (0x3065<<16)|0x1106: /* Rhine II */ - case (0x3106<<16)|0x1106: /* Rhine III */ - break; - } - - port = p->mem[0].bar & ~0x01; - if(ioalloc(port, p->mem[0].size, 0, "vt6102") < 0){ - print("vt6102: port 0x%uX in use\n", port); - continue; - } - ctlr = malloc(sizeof(Ctlr)); - ctlr->port = port; - ctlr->pcidev = p; - ctlr->id = (p->did<<16)|p->vid; - if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF) - cls = 0x10; - ctlr->cls = cls*4; - if(ctlr->cls < sizeof(Ds)){ - print("vt6102: cls %d < sizeof(Ds)\n", ctlr->cls); - iofree(port); - free(ctlr); - continue; - } - ctlr->tft = Ctft64; - - if(vt6102reset(ctlr)){ - iofree(port); - free(ctlr); - continue; - } - pcisetbme(p); - - if(vt6102ctlrhead != nil) - vt6102ctlrtail->next = ctlr; - else - vt6102ctlrhead = ctlr; - vt6102ctlrtail = ctlr; - } -} - -static int -vt6102pnp(Ether* edev) -{ - Ctlr *ctlr; - - if(vt6102ctlrhead == nil) - vt6102pci(); - - /* - * Any adapter matches if no edev->port is supplied, - * otherwise the ports must match. - */ - for(ctlr = vt6102ctlrhead; 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; - memmove(edev->ea, ctlr->par, Eaddrlen); - - /* - * Linkage to the generic ethernet driver. - */ - edev->attach = vt6102attach; - edev->transmit = vt6102transmit; - edev->interrupt = vt6102interrupt; - edev->ifstat = vt6102ifstat; - edev->ctl = nil; - - edev->arg = edev; - edev->promiscuous = vt6102promiscuous; - edev->multicast = vt6102multicast; - - return 0; -} - -void -ethervt6102link(void) -{ - addethercard("vt6102", vt6102pnp); - addethercard("rhine", vt6102pnp); -} diff --git a/os/pc/etherwavelan.c b/os/pc/etherwavelan.c deleted file mode 100644 index e76905b5..00000000 --- a/os/pc/etherwavelan.c +++ /dev/null @@ -1,197 +0,0 @@ -/* Pci/pcmcia code for wavelan.c */ - -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" -#include "etherif.h" - -#include "wavelan.h" - -static int -wavelanpcmciareset(Ether *ether) -{ - int i; - char *p; - Ctlr *ctlr; - - if((ctlr = malloc(sizeof(Ctlr))) == nil) - return -1; - - ilock(ctlr); - ctlr->ctlrno = ether->ctlrno; - - if (ether->port==0) - ether->port=WDfltIOB; - ctlr->iob = ether->port; - - if (ether->irq==0) - ether->irq=WDfltIRQ; - - if (ioalloc(ether->port,WIOLen,0,"wavelan")<0){ - // print("#l%d: port 0x%lx in use\n", - // ether->ctlrno, ether->port); - goto abort1; - } - - /* - * If id= is specified, card must match. Otherwise try generic. - */ - ctlr->slot = -1; - for(i=0; inopt; i++){ - if(cistrncmp(ether->opt[i], "id=", 3) == 0){ - if((ctlr->slot = pcmspecial(ðer->opt[i][3], ether)) < 0) - goto abort; - break; - } - } - if(ctlr->slot == -1){ - for (i=0; wavenames[i]; i++) - if((ctlr->slot = pcmspecial(wavenames[i], ether))>=0) - break; - if(!wavenames[i]){ - DEBUG("no wavelan found\n"); - goto abort; - } - } - - // DEBUG("#l%d: port=0x%lx irq=%ld\n", - // ether->ctlrno, ether->port, ether->irq); - - if(wavelanreset(ether, ctlr) < 0){ - abort: - iofree(ether->port); - abort1: - iunlock(ctlr); - free(ctlr); - ether->ctlr = nil; - return -1; - } - - for(i = 0; i < ether->nopt; i++){ - if(p = strchr(ether->opt[i], '=')) - *p = ' '; - w_option(ctlr, ether->opt[i], strlen(ether->opt[i])); - } - - iunlock(ctlr); - return 0; -} - -static struct { - int vid; - int did; -} wavelanpci[] = { - 0x1260, 0x3873, /* Intersil Prism2.5 */ - 0x1737, 0x0019, /* Linksys WPC-11 untested */ -}; - -static Ctlr *ctlrhead, *ctlrtail; - -static void -wavelanpciscan(void) -{ - int i; - void *mem; - Pcidev *p; - Ctlr *ctlr; - - p = nil; - while(p = pcimatch(p, 0, 0)){ - for(i=0; ivid == wavelanpci[i].vid && p->did == wavelanpci[i].did) - break; - if(i==nelem(wavelanpci)) - continue; - - /* - * On the Prism, bar[0] is the memory-mapped register address (4KB), - */ - if(p->mem[0].size != 4096){ - print("wavelanpci: %.4ux %.4ux: unlikely mmio size\n", p->vid, p->did); - continue; - } - - ctlr = malloc(sizeof(Ctlr)); - ctlr->pcidev = p; - mem = vmap(p->mem[0].bar&~0xF, p->mem[0].size); - if(mem == nil){ - print("wavelanpci: %.4ux %.4ux: vmap 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size); - free(ctlr); - continue; - } - ctlr->mmb = mem; - if(ctlrhead != nil) - ctlrtail->next = ctlr; - else - ctlrhead = ctlr; - ctlrtail = ctlr; - pcisetbme(p); - } -} - -static int -wavelanpcireset(Ether *ether) -{ - int i; - char *p; - Ctlr *ctlr; - - if(ctlrhead == nil) - wavelanpciscan(); - - /* - * Allow plan9.ini to set vid, did? - */ - for(ctlr=ctlrhead; ctlr!=nil; ctlr=ctlr->next) - if(ctlr->active == 0) - break; - if(ctlr == nil) - return -1; - - ctlr->active = 1; - ilock(ctlr); - ether->irq = ctlr->pcidev->intl; - ether->tbdf = ctlr->pcidev->tbdf; - - /* - * Really hard reset. - */ - csr_outs(ctlr, WR_PciCor, 0x0080); - delay(250); - csr_outs(ctlr, WR_PciCor, 0x0000); - delay(500); - for(i=0; i<2*10; i++){ - if(!(csr_ins(ctlr, WR_Cmd)&WCmdBusy)) - break; - delay(100); - } - if(i >= 2*10) - print("wavelan pci %.4ux %.4ux: reset timeout %.4ux\n", - ctlr->pcidev->vid, ctlr->pcidev->did, csr_ins(ctlr, WR_Cmd)); - - if(wavelanreset(ether, ctlr) < 0){ - iunlock(ctlr); - ether->ctlr = nil; - return -1; - } - - for(i = 0; i < ether->nopt; i++){ - if(p = strchr(ether->opt[i], '=')) - *p = ' '; - w_option(ctlr, ether->opt[i], strlen(ether->opt[i])); - } - iunlock(ctlr); - return 0; -} - -void -etherwavelanlink(void) -{ - addethercard("wavelan", wavelanpcmciareset); - addethercard("wavelanpci", wavelanpcireset); -} diff --git a/os/pc/flashif.h b/os/pc/flashif.h deleted file mode 100644 index b5391798..00000000 --- a/os/pc/flashif.h +++ /dev/null @@ -1,82 +0,0 @@ -typedef struct Flash Flash; -typedef struct Flashpart Flashpart; -typedef struct Flashregion Flashregion; - -/* - * logical partitions - */ -enum { - Maxflashpart = 8 -}; - -struct Flashpart { - char* name; - ulong start; - ulong end; -}; - -enum { - Maxflashregion = 8 -}; - -/* - * physical erase block regions - */ -struct Flashregion { - int n; /* number of blocks in region */ - ulong start; /* physical base address (allowing for banks) */ - ulong end; - ulong erasesize; -}; - -/* - * structure defining a flash memory card - */ -struct Flash { - QLock; /* interlock on flash operations */ - Flash* next; - - /* the following are filled in by devflash before Flash.reset called */ - char* name; - void* addr; - ulong size; - int (*reset)(Flash*); - - /* the following are filled in by the reset routine */ - int (*eraseall)(Flash*); - int (*erasezone)(Flash*, int); - int (*write)(Flash*, ulong, void*, long); /* writes of correct width and alignment */ - int (*suspend)(Flash*); - int (*resume)(Flash*); - - /* the following might be filled in by either archflashreset or the reset routine */ - int nr; - Flashregion regions[Maxflashregion]; - - uchar id; /* flash manufacturer ID */ - uchar devid; /* flash device ID */ - int width; /* bytes per flash line */ - int erasesize; /* size of erasable unit (accounting for width) */ - void* data; /* flash type routines' private storage, or nil */ - ulong unusable; /* bit mask of unusable sections */ - Flashpart part[Maxflashpart]; /* logical partitions */ - int protect; /* software protection */ -}; - -/* - * called by link routine of driver for specific flash type: arguments are - * conventional name for card type/model, and card driver's reset routine. - */ -void addflashcard(char*, int (*)(Flash*)); - -/* - * called by devflash.c:/^flashreset; if flash exists, - * sets type, address, and size in bytes of flash - * and returns 0; returns -1 if flash doesn't exist - */ -int archflashreset(char*, void**, long*); - -/* - * enable/disable write protect - */ -void archflashwp(int); diff --git a/os/pc/flashzpc.c b/os/pc/flashzpc.c deleted file mode 100644 index c360f7bf..00000000 --- a/os/pc/flashzpc.c +++ /dev/null @@ -1,371 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#include "flashif.h" - -#define FLASHMEM 0xfff80000 -#define FLASHPGSZ 0x40000 -#define FLASHBKSZ (FLASHPGSZ>>2) -#define LOG2FPGSZ 18 -#define FLASHEND (FLASHMEM+FLASHPGSZ) -#define SYSREG0 0x78 -#define SYSREG1 0x878 - -/* Intel28F016SA flash memory family (8SA and (DD)32SA as well) in byte mode */ - -/* - * word mode does not work - a 2 byte write to a location results in the lower address - * byte being unchanged (4 byte writes are even stranger) and no indication of error. - * Perhaps the bridge is interfering with the address lines. - * Looks like the BIOS code doesn't use it either but that's not certain. - */ - -/* - * When port 0x78 bit 2 is set to 1 (flash device 1) - * 0xfff80000-0xfffbffff seems to be free but has dos block headers - * 0xfffc0000-0xfffdffff seems to be the DOS P: drive - * 0xfffe0000-0xffffffff is the BIOS - * When port 0x78 bit 2 is set to 0 (flash device 0) - * 0xfff80000-0xffffffff is a mixture of used and unused DOS blocks and apparently - * many copies of the BIOS - * - * In the absence of information from Ziatech and to preserve the BIOS and DOS sections, - * this driver only uses the first range for a total of 8 x 0x40000 = 2Mb - */ - -enum { - DQ7 = 0x80, - DQ6 = 0x40, - DQ5 = 0x20, - DQ4 = 0x10, - DQ3 = 0x08, - DQ2 = 0x04, - DQ1 = 0x02, - DQ0 = 0x01, -}; - -enum { - FLRDM = 0xFF, /* read */ - FLWTM = 0x10, /* write/program */ - FLCLR = 0x50, /* clear SR */ - FLBE1 = 0x20, /* block erase */ - FLBE2 = 0xD0, /* block erase */ - FLRSR = 0x70, /* read SR */ - FLDID = 0x90, /* read id */ -}; - -#define DPRINT if(0)print -#define EPRINT if(1)print - -static int -zpcwait(uchar *p, ulong ticks) -{ - uchar csr; - - ticks += m->ticks+1; - while((*p & DQ7) != DQ7){ - sched(); - if(m->ticks >= ticks){ - EPRINT("flash: timed out: %8.8lux\n", (ulong)*p); - return -1; - } - } - csr = *p; - if(csr & (DQ5|DQ4|DQ3)){ - EPRINT("flash: DQ5 error: %8.8lux %8.8lux\n", p, (ulong)csr); - return 0; - } - return 1; -} - -static int -eraseall(Flash *f) -{ - uchar r; - uchar *p; - int i, j, s; - - DPRINT("flash: erase all\n"); - for (i = 0; i < 8; i++) { /* page */ - /* set page */ - r = inb(SYSREG0); - r &= 0x8f; - r |= i<<4; - outb(SYSREG0, r); - p = (uchar *)f->addr; - for (j = 0; j < 4; j++) { /* block within page */ - DPRINT("erasing page %d block %d addr %lux\n", i, j, p); - s = splhi(); - *p = FLBE1; - *p = FLBE2; - splx(s); - if(zpcwait(p, MS2TK(16*1000)) <= 0){ - *p = FLCLR; /* clr SR */ - *p = FLRDM; /* read mode */ - f->unusable = ~0; - return -1; - } - *p = FLCLR; - *p = FLRDM; - p += FLASHPGSZ>>2; - } - } - return 0; -} - -static int -erasezone(Flash *f, int zone) -{ - uchar r; - uchar *p; - int s, pg, blk; - - DPRINT("flash: erase zone %d\n", zone); - if(zone & ~31) { - EPRINT("flash: bad erasezone %d\n", zone); - return -1; /* bad zone */ - } - pg = zone>>2; - blk = zone&3; - /* set page */ - r = inb(SYSREG0); - r &= 0x8f; - r |= pg<<4; - outb(SYSREG0, r); - p = (uchar *)f->addr + blk*(FLASHPGSZ>>2); - DPRINT("erasing zone %d pg %d blk %d addr %lux\n", zone, pg, blk, p); - s = splhi(); - *p = FLBE1; - *p = FLBE2; - splx(s); - if(zpcwait(p, MS2TK(8*1000)) <= 0){ - *p = FLCLR; - *p = FLRDM; /* reset */ - f->unusable |= 1<>LOG2FPGSZ; - o = offset&(FLASHPGSZ-1); - while (n > 0) { - if (pg < 0 || pg > 7) { - EPRINT("flash: bad read %ld %ld\n", offset, n); - return -1; - } - /* set page */ - r = inb(SYSREG0); - r &= 0x8f; - r |= pg<<4; - outb(SYSREG0, r); - if (o+n > FLASHPGSZ) - m = FLASHPGSZ-o; - else - m = n; - DPRINT("flash: read page %ld offset %lux buf %lux n %ld\n", pg, o, p-(uchar*)buf, m); - memmove(p, (uchar *)f->addr + o, m); - p += m; - n -= m; - pg++; - o = 0; - } - return 0; -} - -static int -writex(Flash *f, ulong offset, void *buf, long n) -{ - int i, s; - uchar r; - ulong pg, o; - long m; - uchar *a, *v = buf; - - DPRINT("flash: writex\n"); - pg = offset>>LOG2FPGSZ; - o = offset&(FLASHPGSZ-1); - while (n > 0) { - if (pg < 0 || pg > 7) { - EPRINT("flash: bad write %ld %ld\n", offset, n); - return -1; - } - /* set page */ - r = inb(SYSREG0); - r &= 0x8f; - r |= pg<<4; - outb(SYSREG0, r); - if (o+n > FLASHPGSZ) - m = FLASHPGSZ-o; - else - m = n; - a = (uchar *)f->addr + o; - DPRINT("flash: write page %ld offset %lux buf %lux n %ld\n", pg, o, v-(uchar*)buf, m); - for (i = 0; i < m; i++, v++, a++) { - if (~*a & *v) { - EPRINT("flash: bad write: %lux %lux -> %lux\n", (ulong)a, (ulong)*a, (ulong)*v); - return -1; - } - if (*a == *v) - continue; - s = splhi(); - *a = FLWTM; /* program */ - *a = *v; - splx(s); - microdelay(8); - if(zpcwait(a, 5) <= 0){ - *a = FLCLR; /* clr SR */ - *a = FLRDM; /* read mode */ - f->unusable = ~0; - return -1; - } - *a = FLCLR; - *a = FLRDM; - if (*a != *v) { - EPRINT("flash: write %lux %lux -> %lux failed\n", (ulong)a, (ulong)*a, (ulong)*v); - return -1; - } - } - n -= m; - pg++; - o = 0; - } - return 0; -} - -#ifdef ZERO -/* search the whole of flash */ -static void -flashsearch(Flash *f) -{ - int d, m, p, b, n, i; - uchar r, buf[64]; - - for (d = 0; d < 2; d++) { /* flash device */ - r = inb(SYSREG0); - r &= 0xfb; - r |= (d<<2); - outb(SYSREG0, r); - for (m = 0; m < 2; m++) { /* lower/upper mem */ - if (m == 0) - f->addr = (void *)FLASHMEM; - else - f->addr = (void *)FLASHEND; - for (p = 0; p < 8; p++) { /* page */ - for (b = 0; b < 4; b++) { /* block */ - n = readx(f, (4*p+b)*FLASHBKSZ, buf, 64); - if (n != 0) { - print("bad read in search %d\n", n); - goto end; - } - print("%d %d %d %d : ", d, m, p, b); - if (buf[0] == 0x5a && buf[1] == 0x54) { /* DOS block */ - n = 0; - for (i = 0; i < 64; i++) { - if (buf[i] == 0xff) - n++; - } - if (n == 64-28) - print("un"); - print("used dos\n"); - } - else if (buf[0] == 0x55 && buf[1] == 0xaa) - print("bios start\n"); - else - print("bios ?\n"); - } - } - } - } -end: - r = inb(SYSREG0); - r |= 4; - outb(SYSREG0, r); - f->addr = (void *)FLASHMEM; -} -#endif - -static int -reset(Flash *f) -{ - uchar r; - int s; - ulong pa; - Pcidev *bridge; - - /* get bridge device */ - bridge = pcimatch(nil, 0x8086, 0x7000); /* Intel PIIX3 ISA bridge device */ - if (bridge == nil) { - EPRINT("flash : failed to find bridge device\n"); - return 1; - } - /* enable extended BIOS and read/write */ - s = splhi(); - r = pcicfgr8(bridge, 0x4e); - r |= 0x84; - pcicfgw8(bridge, 0x4e, r); - splx(s); - /* set system register bits */ - r = inb(SYSREG0); - r |= 0x86; /* chip enable, non-BIOS part, set r/w */ - outb(SYSREG0, r); - /* - * might have to grab memory starting at PADDR(FLASHMEM) ie 0x7ff80000 - * because if this is mapped via virtual address FLASHMEM we would get a - * a kernel panic in mmukmap(). - * va = 0xfff80000 pa = 0xfff80000 for flash - * va = 0xfff80000 pa = 0x7ff80000 if lower memory grabbed by anything - */ - /* - * upafree(FLASHMEM, FLASHPGSZ); - * pa = upamalloc(FLASHMEM, FLASHPGSZ, 0); - * if (pa != FLASHMEM) - * error - */ - pa = mmukmap(FLASHMEM, FLASHMEM, FLASHPGSZ); - if (pa != FLASHEND) { - EPRINT("failed to map flash memory"); - return 1; - } -/* - pa = mmukmap(FLASHEND, FLASHEND, FLASHPGSZ); - if (pa != 0) { - EPRINT("failed to map flash memory"); - return 1; - } -*/ - f->id = 0x0089; /* can't use autoselect: might be running in flash */ - f->devid = 0x66a0; - f->read = readx; - f->write = writex; - f->eraseall = eraseall; - f->erasezone = erasezone; - f->suspend = nil; - f->resume = nil; - f->width = 1; /* must be 1 since devflash.c must not read directly */ - f->erasesize = 64*1024; - *(uchar*)f->addr = FLCLR; /* clear status registers */ - *(uchar*)f->addr = FLRDM; /* reset to read mode */ - return 0; -} - -void -flashzpclink(void) -{ - addflashcard("DD28F032SA", reset); -} diff --git a/os/pc/floppy.h b/os/pc/floppy.h deleted file mode 100644 index f84c9eae..00000000 --- a/os/pc/floppy.h +++ /dev/null @@ -1,183 +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 vers; - int maxtries; /* max read attempts before Eio */ - - 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; -}; - -/* - * 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 */ -}; - -/* - * 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, -}; - - -static void -pcfloppyintr(Ureg *ur, void *a) -{ - USED(a); - - floppyintr(ur); -} - -void -floppysetup0(FController *fl) -{ - fl->ndrive = 0; - if(ioalloc(Psra, 6, 0, "floppy") < 0) - return; - if(ioalloc(Pdir, 1, 0, "floppy") < 0){ - iofree(Psra); - return; - } - fl->ndrive = 2; -} - -void -floppysetup1(FController *fl) -{ - uchar equip; - - /* - * read nvram for types of floppies 0 & 1 - */ - equip = nvramread(0x10); - if(fl->ndrive > 0){ - fl->d[0].dt = (equip >> 4) & 0xf; - floppysetdef(&fl->d[0]); - } - if(fl->ndrive > 1){ - fl->d[1].dt = equip & 0xf; - floppysetdef(&fl->d[1]); - } - intrenable(IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN, "floppy"); -} - -/* - * eject disk ( unknown on safari ) - */ -void -floppyeject(FDrive *dp) -{ - floppyon(dp); - dp->vers++; - floppyoff(dp); -} - -int -floppyexec(char *a, long b, int c) -{ - USED(a, b, c); - return b; -} diff --git a/os/pc/fns.h b/os/pc/fns.h deleted file mode 100644 index aa326111..00000000 --- a/os/pc/fns.h +++ /dev/null @@ -1,165 +0,0 @@ -#include "../port/portfns.h" -void aamloop(int); -Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong)); -void archinit(void); -void bootargs(ulong); -int cistrcmp(char*, char*); -int cistrncmp(char*, char*, int); -#define clearmmucache() /* x86 doesn't have one */ -void clockintr(Ureg*, void*); -void (*coherence)(void); -void cpuid(char*, int*, int*); -int cpuidentify(void); -void cpuidprint(void); -void (*cycles)(uvlong*); -void delay(int); -int dmacount(int); -int dmadone(int); -void dmaend(int); -int dmainit(int, int); -long dmasetup(int, void*, long, int); -void dumpregs(Ureg*); -#define evenaddr(x) /* x86 doesn't care */ -void fpinit(void); -void fpoff(void); -void fprestore(FPU*); -void fpsave(FPU*); -ulong fpstatus(void); -ulong getcr0(void); -ulong getcr2(void); -ulong getcr3(void); -ulong getcr4(void); -char* getconf(char*); -void guesscpuhz(int); -int i8042auxcmd(int); -int i8042auxcmdval(int); -void i8042auxenable(void (*)(int, int)); -int i8042auxdetect(void); -void i8042reset(void); -void i8250console(void); -void i8253enable(void); -void i8253init(void); -void i8253link(void); -uvlong i8253read(uvlong*); -void i8253timerset(uvlong); -void i8259init(void); -int i8259isr(int); -int i8259enable(Vctl*); -int i8259vecno(int); -int i8259disable(int); -void idle(void); -void idlehands(void); -int inb(int); -void insb(int, void*, int); -ushort ins(int); -void inss(int, void*, int); -ulong inl(int); -void insl(int, void*, int); -int intrdisable(int, void (*)(Ureg *, void *), void*, int, char*); -void intrenable(int, void (*)(Ureg*, void*), void*, int, char*); -void iofree(int); -void ioinit(void); -int iounused(int, int); -int ioalloc(int, int, int, char*); -int ioreserve(int, int, int, char*); -int iprint(char*, ...); -int isaconfig(char*, int, ISAConf*); -int isvalid_va(void*); -void kbdenable(void); -void kbdinit(void); -void kdbenable(void); -#define kmapinval() -void lapicclock(Ureg*, void*); -void lapictimerset(uvlong); -void lgdt(ushort[3]); -void lidt(ushort[3]); -void links(void); -void ltr(ulong); -void mach0init(void); -void machinit(void); -void mathinit(void); -void mb386(void); -void mb586(void); -void meminit(ulong); -#define mmuflushtlb(pdb) putcr3(pdb) -void mmuinit(void); -ulong mmukmap(ulong, ulong, int); -int mmukmapsync(ulong); -ulong* mmuwalk(ulong*, ulong, int, int); -uchar nvramread(int); -void nvramwrite(int, uchar); -void outb(int, int); -void outsb(int, void*, int); -void outs(int, ushort); -void outss(int, void*, int); -void outl(int, ulong); -void outsl(int, void*, int); -int pciscan(int, Pcidev**); -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*); -uchar pciipin(Pcidev*, uchar); -Pcidev* pcimatch(Pcidev*, int, int); -Pcidev* pcimatchtbdf(int); -void pcireset(void); -void pcisetbme(Pcidev*); -void pcisetioe(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*); -int (*_pcmspecial)(char *, ISAConf *); -void pcmspecialclose(int); -void (*_pcmspecialclose)(int); -void pcmunmap(int, PCMmap*); -void poolinit(void); -void poolsizeinit(void); -void procsave(Proc*); -void procsetup(Proc*); -void putcr3(ulong); -void putcr4(ulong); -void rdmsr(int, vlong*); -ulong rdtsc32(void); -void screeninit(void); -int screenprint(char*, ...); /* debugging */ -void (*screenputs)(char*, int); -int segflush(void*, ulong); -void syncclock(void); -uvlong tscticks(uvlong*); -void trapenable(int, void (*)(Ureg*, void*), void*, char*); -void trapinit(void); -ulong umbmalloc(ulong, int, int); -void umbfree(ulong, int); -ulong umbrwmalloc(ulong, int, int); -void umbrwfree(ulong, int); -ulong upamalloc(ulong, int, int); -void upafree(ulong, int); -void upareserve(ulong, int); -void vectortable(void); -void* vmap(ulong, int); -void vunmap(void*, int); -void wrmsr(ulong, ulong); -int xchgw(ushort*, int); -ulong kzeromap(ulong, ulong, int); -void nmiscreen(void); -int kbdinready(void); - -#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1])) -#define getcallerpc(x) (((ulong*)(x))[-1]) -#define KADDR(a) ((void*)((ulong)(a)|KZERO)) -#define PADDR(a) ((ulong)(a)&~KZERO) - -#define dcflush(a, b) -#define clockcheck(); -#define dumplongs(x, y, z) -#define setpanic() diff --git a/os/pc/fpi.h b/os/pc/fpi.h deleted file mode 100644 index 7a368d18..00000000 --- a/os/pc/fpi.h +++ /dev/null @@ -1,61 +0,0 @@ -typedef int Word; -typedef unsigned long Single; -typedef struct { - unsigned long l; - unsigned long h; -} Double; - -enum { - FractBits = 28, - CarryBit = 0x10000000, - HiddenBit = 0x08000000, - MsBit = HiddenBit, - NGuardBits = 3, - GuardMask = 0x07, - LsBit = (1<e >= ExpInfinity) -#define IsInfinity(n) (IsWeird(n) && (n)->h == HiddenBit && (n)->l == 0) -#define SetInfinity(n) ((n)->e = ExpInfinity, (n)->h = HiddenBit, (n)->l = 0) -#define IsNaN(n) (IsWeird(n) && (((n)->h & ~HiddenBit) || (n)->l)) -#define SetQNaN(n) ((n)->s = 0, (n)->e = ExpInfinity, \ - (n)->h = HiddenBit|(LsBit<<1), (n)->l = 0) -#define IsZero(n) ((n)->e == 1 && (n)->h == 0 && (n)->l == 0) -#define SetZero(n) ((n)->e = 1, (n)->h = 0, (n)->l = 0) - -/* - * fpi.c - */ -extern void fpiround(Internal *); -extern void fpiadd(Internal *, Internal *, Internal *); -extern void fpisub(Internal *, Internal *, Internal *); -extern void fpimul(Internal *, Internal *, Internal *); -extern void fpidiv(Internal *, Internal *, Internal *); -extern int fpicmp(Internal *, Internal *); -extern void fpinormalise(Internal*); - -/* - * fpimem.c - */ -extern void fpis2i(Internal *, void *); -extern void fpid2i(Internal *, void *); -extern void fpiw2i(Internal *, void *); -extern void fpii2s(void *, Internal *); -extern void fpii2d(void *, Internal *); -extern void fpii2w(Word *, Internal *); diff --git a/os/pc/fpi387.c b/os/pc/fpi387.c deleted file mode 100644 index 76677549..00000000 --- a/os/pc/fpi387.c +++ /dev/null @@ -1,742 +0,0 @@ -/* - * Copyright © 1999 Vita Nuova Limited - * - * this doesn't attempt to implement 387 floating-point properties - * that aren't visible in the Inferno environment. in particular, - * all arithmetic is done in double precision, not extended precision. - * furthermore, the FP trap status isn't updated. - */ - -#ifdef TEST -#include -#include -#include -#include "fpi.h" -#include "tst.h" -#else -#include -#include "ureg.h" -#include "fpi.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#endif - -#define fabs Fabs - -typedef struct FPI FPI; - -struct FPI { - char* name; - void (*f)(Ureg*, int, void*, Internal*, Internal*); - int dstf; -}; - -enum { - RndNearest = 0, - RndDown, - RndUp, - Rnd0, - - C0 = 1<<8, - C1 = 1<<9, - C2 = 1<<10, - C3 = 1<<14, -}; - - -int fpemudebug = 0; - -static Internal fpconst[7] = { /* indexed by op&7 */ - /* s, e, l, h */ - {0, 0x3FF, 0x00000000, 0x08000000}, /* 1 */ - {0, 0x400, 0x0BCD1B8A, 0x0D49A784}, /* l2t */ - {0, 0x3FF, 0x095C17F0, 0x0B8AA3B2}, /* l2e */ - {0, 0x400, 0x022168C2, 0x0C90FDAA}, /* pi */ - {0, 0x3FD, 0x04FBCFF7, 0x09A209A8}, /* lg2 */ - {0, 0x3FE, 0x07D1CF79, 0x0B17217F}, /* ln2 */ - {0, 0x1, 0x00000000, 0x00000000}, /* z */ -}; - -static Internal *fpstk(int i); -#define ST(x) (*fpstk((x))) - -#define I387 (up->env->fpu) - -/* BUG: check fetch (not worthwhile in Inferno) */ -#define getubyte(a) (*(uchar*)(a)) -#define getuword(a) (*(ushort*)(a)) -#define getulong(a) (*(ulong*)(a)) - -static void -popfp(void) -{ - ushort *s; - - s = &I387.status; - *s = (*s & ~0x3800) | ((*s + 0x0800) & 0x3800); -} - -static void -pushfp(void) -{ - ushort *s; - - s = &I387.status; - *s = (*s & ~0x3800) | ((*s + 0x3800) & 0x3800); -} - -static Internal * -fpstk(int i) -{ - return (Internal*)I387.istack[(i+(I387.status>>11))&7]; -} - -static void -fldc(Ureg*, int op, void*, Internal*, Internal *d) -{ - *d = fpconst[op&7]; -} - -static void -fabs(Ureg*, int, void*, Internal*, Internal *d) -{ - d->s = 0; -} - -static void -fchs(Ureg*, int, void*, Internal*, Internal *d) -{ - d->s ^= 1; -} - -static void -fadd(Ureg*, int, void*, Internal *s, Internal *d) -{ - Internal l, r; - - l = *s; - r = *d; - (l.s == r.s? fpiadd: fpisub)(&l, &r, d); -} - -static void -fsub(Ureg*, int, void*, Internal *s, Internal *d) -{ - Internal l, r; - - l = *s; - r = *d; - l.s ^= 1; - (l.s == r.s? fpiadd: fpisub)(&l, &r, d); -} - -static void -fsubr(Ureg*, int, void*, Internal *s, Internal *d) -{ - Internal l, r; - - l = *s; - r = *d; - r.s ^= 1; - (l.s == r.s? fpiadd: fpisub)(&r, &l, d); -} - -static void -fmul(Ureg*, int, void*, Internal *s, Internal *d) -{ - Internal l, r; - - l = *s; - r = *d; - fpimul(&l, &r, d); -} - -static void -fdiv(Ureg*, int, void*, Internal *s, Internal *d) -{ - Internal l, r; - - l = *s; - r = *d; - fpidiv(&l, &r, d); -} - -static void -fdivr(Ureg*, int, void*, Internal *s, Internal *d) -{ - Internal l, r; - - l = *s; - r = *d; - fpidiv(&r, &l, d); -} - -static void -fcom(Ureg*, int, void*, Internal *s, Internal *d) -{ - int i; - ushort *p; - - p = &I387.status; - if(IsWeird(s) || IsWeird(d)){ - *p |= C0|C2|C3; - /* BUG: should trap if not masked */ - return; - } - *p &= ~(C0|C2|C3); - i = fpicmp(d, s); - if(i < 0) - *p |= C0; - else if(i == 0) - *p |= C3; -} - -static void -fpush(Ureg*, int op, void*, Internal*, Internal*) -{ - Internal *p; - - p = &ST(op & 7); - pushfp(); - ST(0) = *p; -} - -static void -fmov(Ureg*, int, void*, Internal *s, Internal *d) -{ - *d = *s; -} - -static void -fmovr(Ureg*, int, void*, Internal *s, Internal *d) -{ - *s = *d; -} - -static void -fxch(Ureg*, int, void*, Internal *s, Internal *d) -{ - Internal t; - - t = *s; *s = *d; *d = t; -} - -static void -frstor(Ureg*, int, void *s, Internal*, Internal*) -{ - validaddr(s, 108, 0); - memmove(&I387, s, 108); -} - -static void -fsave(Ureg*, int, void *d, Internal*, Internal*) -{ - validaddr(d, 108, 1); - memmove(d, &I387, 108); - I387.control = 0x037F; - I387.status = 0; - I387.tag = 0; -} - -static void -fstsw(Ureg*, int, void *d, Internal*, Internal*) -{ - validaddr(d, 2, 1); - *(short*)d = I387.status; -} - -static void -fldenv(Ureg*, int, void *s, Internal*, Internal*) -{ - validaddr(s, 28, 0); - memmove(&I387, s, 28); -} - -static void -fldcw(Ureg*, int, void *s, Internal*, Internal*) -{ - validaddr(s, 2, 0); - I387.control = *(short*)s; -} - -static void -fstenv(Ureg*, int, void *d, Internal*, Internal*) -{ - validaddr(d, 4*7, 1); - memmove(d, &I387, 4*7); -} - -static void -fstcw(Ureg*, int, void *d, Internal*, Internal*) -{ - validaddr(d, 2, 1); - *(short*)d = I387.control; -} - -static void -fincstp(Ureg*, int, void*, Internal*, Internal*) -{ - popfp(); -} - -static void -fdecstp(Ureg*, int, void*, Internal*, Internal*) -{ - pushfp(); -} - -static void -fscale(Ureg*, int, void*, Internal *s, Internal *d) -{ - Word w; - - fpii2w(&w, s); /* should truncate towards zero ... */ - d->e += w; -} - -static void -fstswax(Ureg *ur, int, void*, Internal*, Internal*) -{ - ur->ax = (ur->ax & ~0xFFFF) | (I387.status & 0xFFFF); -} - -static void -ftst(Ureg*, int, void*, Internal*, Internal *d) -{ - ushort *p; - - p = &I387.status; - if(IsWeird(d)){ - *p |= C0|C2|C3; - return; - } - *p &= ~(C0|C2|C3); - fpinormalise(d); - if(IsZero(d)) - *p |= C3; - else if(d->s) - *p |=C0; -} - -static void -frndint(Ureg*, int, void*, Internal*, Internal *d) -{ - fpiround(d); /* BUG: doesn't look at rounding mode */ -} - -static void -fnop(Ureg*, int, void*, Internal*, Internal*) -{ -} - -enum { - Fpop1= 1<<0, - Fpop2 = 1<<1, - Fload = 1<<2, -}; - -/* - * %e - effective address - Mod R/M value - * %f - floating point register F0-F7 - from Mod R/M register - */ - -static void fload(Ureg*, int, void*, Internal*, Internal*); -static void fstore(Ureg*, int, void*, Internal*, Internal*); - -#define X(a,b) (((a)<<2)|(b)) - -static FPI optab1[4][4] = { /* normal mod r/m operand */ -[0] { - [0] {"FLDENV %e", fldenv, 0}, - [1] {"FLDCW %e", fldcw, 0}, - [2] {"FSTENV %e", fstenv, 0}, - [3] {"FSTCW %e", fstcw, 0}, - }, -[1] { - [1] {"FMOVX %e,F0", nil, Fload}, - [3] {"FMOVXP F0,%e", nil, Fpop1}, - }, -[2] { - [0] {"FRSTOR %e", frstor, 0}, - [2] {"FSAVE %e", fsave, 0}, - [3] {"FSTSW %e", fstsw, 0}, - }, -[3] { - [0] {"FMOVB %e", nil, 0}, - [1] {"FMOVV %e,F0", nil, Fload}, - [2] {"FMOVBP %e", nil, Fpop1}, - [3] {"FMOVVP F0,%e", nil, Fpop1}, - }, -}; - -#undef X - -static FPI optab2a[1<<3] = { /* A=0 */ -[0] {"FADDx %e,F0", fadd, 0}, -[1] {"FMULx %e,F0", fmul, 0}, -[2] {"FCOMx %e,F0", fcom, 0}, -[3] {"FCOMxP %e,F0", fcom, Fpop1}, -[4] {"FSUBx %e,F0", fsub, 0}, -[5] {"FSUBRx %e,F0", fsubr, 0}, /* ?? */ -[6] {"FDIVx %e,F0", fdiv, 0}, -[7] {"FDIVRx %e,F0", fdivr, 0}, /* ?? */ -}; - -static FPI optab2b[1<<2] = { /* A=1, B=0,2,3 */ -[0] {"FMOVx %e,F0", fload, Fload}, -[2] {"FMOVx F0,%e", fstore, 0}, -[3] {"FMOVxP F0,%e", fstore, Fpop1}, -}; - -#define X(d,P,B) ((d<<4)|(P<<3)|B) - -static FPI optab3a[1<<5] = { /* A=0 */ -[X(0,0,0)] {"FADDD %f,F0", fadd, 0}, -[X(1,0,0)] {"FADDD F0,%f", fadd, 0}, -[X(1,1,0)] {"FADDDP F0,%f", fadd, Fpop1}, -[X(0,0,1)] {"FMULD %f,F0", fmul, 0}, -[X(1,0,1)] {"FMULD F0,%f", fmul, 0}, -[X(1,1,1)] {"FMULDP F0,%f", fmul, Fpop1}, -[X(0,0,2)] {"FCOMD %f,F0", fcom, 0}, -[X(0,0,3)] {"FCOMDP %f,F0", fcom, Fpop1}, -[X(1,1,3)] {"FCOMDPP", fcom, Fpop1|Fpop2}, -[X(0,0,4)] {"FSUBD %f,F0", fsub, 0}, -[X(1,0,4)] {"FSUBRD F0,%f", fsubr, 0}, -[X(1,1,4)] {"FSUBRDP F0,%f", fsubr, Fpop1}, -[X(0,0,5)] {"FSUBRD %f,F0", fsubr, 0}, -[X(1,0,5)] {"FSUBD F0,%f", fsub, 0}, -[X(1,1,5)] {"FSUBDP F0,%f", fsub, Fpop1}, -[X(0,1,5)] {"FUCOMPP", fcom, Fpop1|Fpop2}, -[X(0,0,6)] {"FDIVD %f,F0", fdiv, 0}, -[X(1,0,6)] {"FDIVRD F0,%f", fdivr, 0}, -[X(1,1,6)] {"FDIVRDP F0,%f", fdivr, Fpop1}, -[X(0,0,7)] {"FDIVRD %f,F0", fdivr, 0}, -[X(1,0,7)] {"FDIVD F0,%f", fdiv, 0}, -[X(1,1,7)] {"FDIVDP F0,%f", fdiv, Fpop1}, -}; - -static FPI optab3b[1<<5] = { /* A=1 */ -[X(0,0,0)] {"FMOVD %f,F0", fmov, Fload}, -[X(0,0,1)] {"FXCHD %f,F0", fxch, 0}, -[X(0,0,2)] {"FNOP", fnop, 0}, /* F0 only */ -[X(1,0,0)] {"FFREED %f", fnop, 0}, -[X(1,0,2)] {"FMOVD F0,%f", fmovr, 0}, -[X(1,0,3)] {"FMOVDP F0,%f", fmovr, Fpop1}, -[X(1,1,4)] {"FSTSW AX", fstswax, 0}, -[X(1,0,4)] {"FUCOMD %f,F0", fcom, 0}, -[X(1,0,5)] {"FUCOMDP %f,F0", fcom, Fpop1}, -}; - -#undef X - -static FPI optab4[1<<6] = { -[0x00] {"FCHS", fchs, 0}, -[0x01] {"FABS", fabs, 0}, -[0x04] {"FTST", ftst, 0}, -[0x05] {"FXAM", nil, 0}, -[0x08] {"FLD1", fldc, Fload}, -[0x09] {"FLDL2T", fldc, Fload}, -[0x0a] {"FLDL2E", fldc, Fload}, -[0x0b] {"FLDPI", fldc, Fload}, -[0x0c] {"FLDLG2", fldc, Fload}, -[0x0d] {"FLDLN2", fldc, Fload}, -[0x0e] {"FLDZ", fldc, Fload}, -[0x10] {"F2XM1", nil, 0}, -[0x11] {"FYL2X", nil, 0}, -[0x12] {"FPTAN", nil, 0}, -[0x13] {"FPATAN", nil, 0}, -[0x14] {"FXTRACT", nil, 0}, -[0x15] {"FPREM1", nil, 0}, -[0x16] {"FDECSTP", fdecstp, 0}, -[0x17] {"FINCSTP", fincstp, 0}, -[0x18] {"FPREM", nil, 0}, -[0x19] {"FYL2XP1", nil, 0}, -[0x1a] {"FSQRT", nil, 0}, -[0x1b] {"FSINCOS", nil, 0}, -[0x1c] {"FRNDINT", frndint, 0}, -[0x1d] {"FSCALE", fscale, 0}, -[0x1e] {"FSIN", nil, 0}, -[0x1f] {"FCOS", nil, 0}, -}; - -static void -loadr32(void *s, Internal *d) -{ - validaddr(s, 4, 0); - fpis2i(d, s); -} - -static void -loadi32(void *s, Internal *d) -{ - validaddr(s, 4, 0); - fpiw2i(d, s); -} - -static void -loadr64(void *s, Internal *d) -{ - validaddr(s, 8, 0); - fpid2i(d, s); -} - -static void -loadi16(void *s, Internal *d) -{ - Word w; - - validaddr(s, 2, 0); - w = *(short*)s; - fpiw2i(d, &w); -} - -static void (*loadf[4])(void*, Internal*) ={ - loadr32, loadi32, loadr64, loadi16 -}; - -static void -storer32(Internal s, void *d) -{ - validaddr(d, 4, 1); - fpii2s(d, &s); -} - -static void -storei32(Internal s, void *d) -{ - validaddr(d, 4, 1); - fpii2w(d, &s); -} - -static void -storer64(Internal s, void *d) -{ - validaddr(d, 8, 1); - fpii2d(d, &s); -} - -static void -storei16(Internal s, void *d) -{ - Word w; - - validaddr(d, 2, 1); - fpii2w(&w, &s); - if((short)w != w) - ; /* overflow */ - *(short*)d = w; -} - -static void (*storef[4])(Internal, void*) ={ - storer32, storei32, storer64, storei16 -}; - -static void -fload(Ureg*, int op, void *mem, Internal*, Internal *d) -{ - (*loadf[(op>>9)&3])(mem, d); -} - -static void -fstore(Ureg*, int op, void *mem, Internal *s, Internal*) -{ - (*storef[(op>>9)&3])(*s, mem); -} - -#define REG(x) (*(ulong*)(((char*)ur)+roff[(x)])) - -static int roff[] = { - offsetof(Ureg, ax), - offsetof(Ureg, cx), - offsetof(Ureg, dx), - offsetof(Ureg, bx), - offsetof(Ureg, ecode), /* ksp */ - offsetof(Ureg, bp), - offsetof(Ureg, si), - offsetof(Ureg, di), -}; - -static long -getdisp(Ureg *ur, int mod, int rm) -{ - uchar c; - long disp; - - if(mod > 2) - return 0; - disp = 0; - if(mod == 1) { - c = getubyte(ur->pc++); - if(c&0x80) - disp = c|(~0<<8); - else - disp = c; - } else if(mod == 2 || rm == 5) { - disp = getulong(ur->pc); - ur->pc += 4; - } - if(mod || rm != 5) - disp += REG(rm); /* base */ - return disp; -} - -static ulong -modrm(Ureg *ur, uchar c) -{ - uchar rm, mod; - int reg; - ulong base; - - mod = (c>>6)&3; - rm = c&7; - if(mod == 3) /* register */ - error("sys: fpemu: invalid addr mode"); - /* no 16-bit mode */ - if(rm == 4) { /* scummy sib byte */ - c = getubyte(ur->pc++); - reg = (c>>3)&0x07; /* index */ - base = getdisp(ur, mod, c&7); - if(reg != 4) - base += (REG(reg) << (c>>6)); /* index */ - if(fpemudebug>1) - print("ur=#%lux sib=#%x reg=%d mod=%d base=%d basev=#%lux sp=%lux\n", ur, c, reg, mod, c&7, base, ur->usp); - return base; - } - if(rm == 5 && mod == 0){ - ur->pc += 4; - return getulong(ur->pc-4); - } - return getdisp(ur, mod, rm); -} - -static void * -ea(Ureg *ur, uchar op) -{ - ulong addr; - - addr = modrm(ur, op); - I387.operand = addr; - if(fpemudebug>1) - print("EA=#%lux\n", addr); - return (void*)addr; -} - -void -fpi387(Ureg *ur) -{ - int op, i; - ulong pc; - FPenv *ufp; - FPI *fp; - Internal tmp, *s, *d; - void *mem; - char buf[60]; - - ur->ecode = (ulong)&ur->sp; /* BUG: TEMPORARY compensation for incorrect Ureg for kernel mode */ - ufp = &up->env->fpu; /* because all the state is in Osenv, it need not be saved/restored */ - if(ufp->fpistate != FPACTIVE) { - ufp->fpistate = FPACTIVE; - ufp->control = 0x037f; - ufp->status = 0; - ufp->tag = 0; - ufp->oselector = 0x17; - } - while((op = getubyte(ur->pc)) >= 0xd8 && op <= 0xdf || op == 0x9B){ - if(op == 0x9B){ /* WAIT */ - ur->pc++; - continue; - } - if(ufp->control & ufp->status & 0x3F) - ufp->status |= 0x8000; - else - ufp->status &= 0x7FFF; - pc = ur->pc; - op = (op<<8) | getubyte(pc+1); - ufp->selector = ur->cs; - ufp->r4 = op-0xD800; - ur->pc += 2; - mem = nil; - s = nil; - d = nil; - /* decode op, following table 10.2.4 in i486 handbook */ - i = op & 0xFFE0; - if(i == 0xD9E0){ - fp = &optab4[op&0x1F]; - s = &ST(0); - if(fp->dstf & Fload) - pushfp(); - d = &ST(0); - } else if(i == 0xDBE0){ - i = op & 0x1F; - if(i == 2){ /* FCLEX */ - ufp->status &= 0x7f00; - continue; - } else if(i == 3){ /* FINIT */ - ufp->control = 0x037f; - ufp->status = 0; - ufp->tag = 0; - continue; - } - fp = nil; - } else if((op & 0xF8C0) == 0xD8C0){ - i = ((op>>6)&030)|((op>>3)&7); - if(op & (1<<8)){ - fp = &optab3b[i]; - s = &ST(op&7); - if(fp->dstf & Fload) - pushfp(); - d = &ST(0); - } else { - fp = &optab3a[i]; - i = op & 7; - if(op & (1<<10)){ - s = &ST(0); - d = &ST(i); - }else{ - s = &ST(i); - d = &ST(0); - } - } - } else if((op & 0xF920) == 0xD920){ - mem = ea(ur, op&0xFF); - fp = &optab1[(op>>9)&3][(op>>3)&3]; - } else { - mem = ea(ur, op&0xFF); - if(op & (1<<8)){ - /* load/store */ - fp = &optab2b[(op>>3)&7]; - if(fp->dstf & Fload){ - pushfp(); - d = &ST(0); - } else - s = &ST(0); - } else { - /* mem OP reg */ - fp = &optab2a[(op>>3)&7]; - (*loadf[(op>>9)&3])(mem, &tmp); - s = &tmp; - d = &ST(0); - } - } - if(fp == nil || fp->f == nil){ - if(fp == nil || fp->name == nil) - snprint(buf, sizeof(buf), "sys: fp: pc=%lux invalid fp 0x%.4x", pc, op); - else - snprint(buf, sizeof(buf), "sys: fp: pc=%lux unimp fp 0x%.4x (%s)", pc, op, fp->name); - error(buf); - } - if(fpemudebug) - print("%8.8lux %.4x %s\n", pc, op, fp->name); - (*fp->f)(ur, op, mem, s, d); - if(fp->dstf & Fpop1){ - popfp(); - if(fp->dstf & Fpop2) - popfp(); - } - if(anyhigher()) - sched(); - } -} diff --git a/os/pc/fpsave.s b/os/pc/fpsave.s deleted file mode 100644 index 8bf9448e..00000000 --- a/os/pc/fpsave.s +++ /dev/null @@ -1,9 +0,0 @@ -TEXT FPsave(SB), 1, $0 /* save FPU environment without waiting */ - MOVL fpu+0(FP), AX - FSTENV 0(AX) - RET - -TEXT FPrestore(SB), 1, $0 /* restore FPU environment without waiting */ - MOVL fpu+0(FP), AX - FLDENV 0(AX) - RET diff --git a/os/pc/i8250.c b/os/pc/i8250.c deleted file mode 100644 index c625013e..00000000 --- a/os/pc/i8250.c +++ /dev/null @@ -1,328 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.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) */ - Fenabd=(3<<6), /* on if fifo's enabled */ - Fifoctl=2, /* fifo control (write) */ - Fena= (1<<0), /* enable xmit/rcv fifos */ - Ftrig= (1<<6), /* trigger after 4 input characters */ - Fclear=(3<<1), /* clear xmit & rcv fifos */ - 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 */ - int nofifo; - - 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 i8250uart[1]; - -#define UartFREQ 1843200 - -#define i8250regw(u, r, v) outb((u)->port+(r), (u)->sticky[(r)]|(v)) -#define i8250regr(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 -i8250setbaud(Uart* uart, int rate) -{ - ulong brconst; - - brconst = (UartFREQ+8*rate-1)/(16*rate); - - i8250regw(uart, Format, Dra); - outb(uart->port+Dmsb, (brconst>>8) & 0xff); - outb(uart->port+Dlsb, brconst & 0xff); - i8250regw(uart, Format, 0); -} - -/* - * toggle DTR - */ -static void -i8250dtr(Uart* uart, int n) -{ - if(n) - uart->sticky[Mctl] |= Dtr; - else - uart->sticky[Mctl] &= ~Dtr; - i8250regw(uart, Mctl, 0); -} - -/* - * toggle RTS - */ -static void -i8250rts(Uart* uart, int n) -{ - if(n) - uart->sticky[Mctl] |= Rts; - else - uart->sticky[Mctl] &= ~Rts; - i8250regw(uart, Mctl, 0); -} - -/* - * Enable/disable FIFOs (if possible). - */ -static void -i8250fifo(Uart* uart, int n) -{ - int i, s; - - if(uart->nofifo) - return; - - s = splhi(); - - /* reset fifos */ - i8250regw(uart, Fifoctl, Fclear); - - /* empty buffer and interrupt conditions */ - for(i = 0; i < 16; i++){ - if(i8250regr(uart, Istat)) - {} - if(i8250regr(uart, Data)) - {} - } - - /* turn on fifo */ - if(n){ - i8250regw(uart, Fifoctl, Fena|Ftrig); - - if((i8250regr(uart, Istat) & Fenabd) == 0){ - /* didn't work, must be an earlier chip type */ - uart->nofifo = 1; - } - } - - splx(s); -} - -#ifdef notdef -static void -i8250intr(Ureg*, void* arg) -{ - Uart *uart; - int ch; - int s, l, loops; - - uart = arg; - for(loops = 0; loops < 1024; loops++){ - s = i8250regr(uart, Istat); - switch(s & 0x3F){ - case 6: /* receiver line status */ - l = i8250regr(uart, Lstat); - if(l & Ferror) - uart->frame++; - if(l & Oerror) - uart->overrun++; - break; - - case 4: /* received data available */ - case 12: - ch = inb(uart->port+Data); - if(uart->rx) - (*uart->rx)(ch & 0x7F); - break; - - case 2: /* transmitter empty */ - ch = -1; - if(uart->tx) - ch = (*uart->tx)(); - if(ch != -1) - outb(uart->port+Data, ch); - break; - - case 0: /* modem status */ - i8250regr(uart, Mstat); - break; - - default: - if(s&1) - return; - print("weird modem interrupt #%2.2ux\n", s); - break; - } - } - panic("i8250intr: 0x%2.2ux\n", i8250regr(uart, Istat)); -} -#endif /* notdef */ - -/* - * turn on a port's interrupts. set DTR and RTS - */ -static void -i8250enable(Uart* uart) -{ - /* - * turn on interrupts - */ - uart->sticky[Iena] = 0; -#ifdef notdef - if(uart->tx) - uart->sticky[Iena] |= Ixmt; - if(uart->rx) - uart->sticky[Iena] |= Ircv|Irstat; -#endif /* notdef */ - - /* - * turn on DTR and RTS - */ - i8250dtr(uart, 1); - i8250rts(uart, 1); - i8250fifo(uart, 1); - - i8250regw(uart, Iena, 0); -} - -void -i8250special(int port, void (*rx)(int), int (*tx)(void), int baud) -{ - Uart *uart = &i8250uart[0]; - - if(uart->port) - return; - - switch(port){ - - case 0: - uart->port = 0x3F8; -#ifdef notdef - intrenable(VectorUART0, i8250intr, uart, BUSUNKNOWN); -#endif /* notdef */ - break; - - case 1: - uart->port = 0x2F8; -#ifdef notdef - intrenable(VectorUART1, i8250intr, uart, BUSUNKNOWN); -#endif /* notdef */ - break; - - default: - return; - } - - /* - * set rate to 9600 baud. - * 8 bits/character. - * 1 stop bit. - * interrupts enabled. - */ - i8250setbaud(uart, 9600); - uart->sticky[Format] = Bits8; - i8250regw(uart, Format, 0); - uart->sticky[Mctl] |= Inton; - i8250regw(uart, Mctl, 0x0); - - uart->rx = rx; - uart->tx = tx; - i8250enable(uart); - if(baud) - i8250setbaud(uart, baud); -} - -int -i8250getc(void) -{ - Uart *uart = &i8250uart[0]; - - if(i8250regr(uart, Lstat) & Inready) - return inb(uart->port+Data); - return 0; -} - -void -i8250putc(int c) -{ - Uart *uart = &i8250uart[0]; - int i; - - for(i = 0; i < 100; i++){ - if(i8250regr(uart, Lstat) & Outready) - break; - delay(1); - } - outb(uart->port+Data, c); -} - -void -i8250puts(char* s, int n) -{ - int x; - - x = splhi(); - while(n--){ - if(*s == '\n') - i8250putc('\r'); - i8250putc(*s++); - } - splx(x); -} diff --git a/os/pc/i8253.c b/os/pc/i8253.c deleted file mode 100644 index 0759088f..00000000 --- a/os/pc/i8253.c +++ /dev/null @@ -1,314 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -/* - * 8253 timer - */ -enum -{ - T0cntr= 0x40, /* counter ports */ - T1cntr= 0x41, /* ... */ - T2cntr= 0x42, /* ... */ - Tmode= 0x43, /* mode port (control word register) */ - T2ctl= 0x61, /* counter 2 control port */ - - /* commands */ - Latch0= 0x00, /* latch counter 0's value */ - Load0l= 0x10, /* load counter 0's lsb */ - Load0m= 0x20, /* load counter 0's msb */ - Load0= 0x30, /* load counter 0 with 2 bytes */ - - Latch1= 0x40, /* latch counter 1's value */ - Load1l= 0x50, /* load counter 1's lsb */ - Load1m= 0x60, /* load counter 1's msb */ - Load1= 0x70, /* load counter 1 with 2 bytes */ - - Latch2= 0x80, /* latch counter 2's value */ - Load2l= 0x90, /* load counter 2's lsb */ - Load2m= 0xa0, /* load counter 2's msb */ - Load2= 0xb0, /* load counter 2 with 2 bytes */ - - /* 8254 read-back command: everything > pc-at has an 8254 */ - Rdback= 0xc0, /* readback counters & status */ - Rdnstat=0x10, /* don't read status */ - Rdncnt= 0x20, /* don't read counter value */ - Rd0cntr=0x02, /* read back for which counter */ - Rd1cntr=0x04, - Rd2cntr=0x08, - - /* modes */ - ModeMsk=0xe, - Square= 0x6, /* periodic square wave */ - Trigger=0x0, /* interrupt on terminal count */ - Sstrobe=0x8, /* software triggered strobe */ - - /* T2ctl bits */ - T2gate= (1<<0), /* enable T2 counting */ - T2spkr= (1<<1), /* connect T2 out to speaker */ - T2out= (1<<5), /* output of T2 */ - - Freq= 1193182, /* Real clock frequency */ - Tickshift=8, /* extra accuracy */ - MaxPeriod=Freq/HZ, - MinPeriod=Freq/(100*HZ), -}; - -typedef struct I8253 I8253; -struct I8253 -{ - Lock; - ulong period; /* current clock period */ - int enabled; - uvlong hz; - - ushort last; /* last value of clock 1 */ - uvlong ticks; /* cumulative ticks of counter 1 */ - - ulong periodset; -}; -I8253 i8253; - -void -i8253init(void) -{ - int loops, x; - - ioalloc(T0cntr, 4, 0, "i8253"); - ioalloc(T2ctl, 1, 0, "i8253.cntr2ctl"); - - i8253.period = Freq/HZ; - - /* - * enable a 1/HZ interrupt for providing scheduling interrupts - */ - outb(Tmode, Load0|Square); - outb(T0cntr, (Freq/HZ)); /* low byte */ - outb(T0cntr, (Freq/HZ)>>8); /* high byte */ - - /* - * enable a longer period counter to use as a clock - */ - outb(Tmode, Load2|Square); - outb(T2cntr, 0); /* low byte */ - outb(T2cntr, 0); /* high byte */ - x = inb(T2ctl); - x |= T2gate; - outb(T2ctl, x); - - /* - * 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; - } -} - -void -guesscpuhz(int aalcycles) -{ - int loops, incr, x, y; - uvlong a, b, cpufreq; - - /* find biggest loop that doesn't wrap */ - incr = 16000000/(aalcycles*HZ*2); - x = 2000; - for(loops = incr; loops < 64*1024; loops += incr) { - - /* - * measure time for the loop - * - * 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); - cycles(&a); - x = inb(T0cntr); - x |= inb(T0cntr)<<8; - aamloop(loops); - outb(Tmode, Latch0); - 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(). - * n.b. counter goes up by 2*Freq - */ - cpufreq = (vlong)loops*((aalcycles*2*Freq)/x); - m->loopconst = (cpufreq/1000)/aalcycles; /* AAM+LOOP's for 1 ms */ - - if(m->havetsc){ - /* counter goes up by 2*Freq */ - b = (b-a)<<1; - b *= Freq; - b /= x; - - /* - * round to the nearest megahz - */ - m->cpumhz = (b+500000)/1000000L; - m->cpuhz = b; - m->cyclefreq = b; - } else { - /* - * add in possible 0.5% error and convert to MHz - */ - m->cpumhz = (cpufreq + cpufreq/200)/1000000; - m->cpuhz = cpufreq; - } - - i8253.hz = Freq<>Tickshift; - now = i8253.ticks; /* assuming whomever called us just did fastticks() */ - - period = want - now; - if(period < MinPeriod) - period = MinPeriod; - else if(period > MaxPeriod) - period = MaxPeriod; - } - - /* hysteresis */ - if(i8253.period != period){ - ilock(&i8253); - /* load new value */ - outb(Tmode, Load0|Square); - outb(T0cntr, period); /* low byte */ - outb(T0cntr, period >> 8); /* high byte */ - - /* remember period */ - i8253.period = period; - i8253.periodset++; - iunlock(&i8253); - } -} - -static void -i8253clock(Ureg* ureg, void*) -{ - timerintr(ureg, 0); -} - -void -i8253enable(void) -{ - i8253.enabled = 1; - i8253.period = Freq/HZ; - intrenable(IrqCLOCK, i8253clock, 0, BUSUNKNOWN, "clock"); -} - -void -i8253link(void) -{ -} - -/* - * return the total ticks of counter 2. We shift by - * 8 to give timesync more wriggle room for interpretation - * of the frequency - */ -uvlong -i8253read(uvlong *hz) -{ - ushort y, x; - uvlong ticks; - - if(hz) - *hz = i8253.hz; - - ilock(&i8253); - outb(Tmode, Latch2); - y = inb(T2cntr); - y |= inb(T2cntr)<<8; - - if(y < i8253.last) - x = i8253.last - y; - else { - x = i8253.last + (0x10000 - y); - if (x > 3*MaxPeriod) { - outb(Tmode, Load2|Square); - outb(T2cntr, 0); /* low byte */ - outb(T2cntr, 0); /* high byte */ - y = 0xFFFF; - x = i8253.period; - } - } - i8253.last = y; - i8253.ticks += x>>1; - ticks = i8253.ticks; - iunlock(&i8253); - - return ticks<loopconst; - if(millisecs <= 0) - millisecs = 1; - aamloop(millisecs); -} - -void -microdelay(int microsecs) -{ - microsecs *= m->loopconst; - microsecs /= 1000; - if(microsecs <= 0) - microsecs = 1; - aamloop(microsecs); -} - -/* - * performance measurement ticks. must be low overhead. - * doesn't have to count over a second. - */ -ulong -perfticks(void) -{ - uvlong x; - - if(m->havetsc) - cycles(&x); - else - x = 0; - return x; -} diff --git a/os/pc/i8259.c b/os/pc/i8259.c deleted file mode 100644 index 562196b9..00000000 --- a/os/pc/i8259.c +++ /dev/null @@ -1,199 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -/* - * 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, -}; - -static Lock i8259lock; -static int i8259mask = 0xFFFF; /* disabled interrupts */ -int i8259elcr; /* mask of level-triggered interrupts */ - -void -i8259init(void) -{ - int x; - - ioalloc(Int0ctl, 2, 0, "i8259.0"); - ioalloc(Int1ctl, 2, 0, "i8259.1"); - ilock(&i8259lock); - - /* - * 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, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered, - 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 slave with edge triggered - * input with fully nested interrupts. - */ - outb(Int1ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered, - 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, (i8259mask>>8) & 0xFF); - - /* - * pass #2 8259 interrupts to #1 - */ - i8259mask &= ~0x04; - outb(Int0aux, i8259mask & 0xFF); - - /* - * Set Ocw3 to return the ISR when ctl read. - * After initialisation status read is set to IRR. - * Read IRR first to possibly deassert an outstanding - * interrupt. - */ - inb(Int0ctl); - outb(Int0ctl, Ocw3|0x03); - inb(Int1ctl); - 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); - } - } - iunlock(&i8259lock); -} - -int -i8259isr(int vno) -{ - int irq, isr; - - if(vno < VectorPIC || vno > VectorPIC+MaxIrqPIC) - return 0; - irq = vno-VectorPIC; - - /* - * tell the 8259 that we're done with the - * highest level interrupt (interrupts are still - * off at this point) - */ - ilock(&i8259lock); - isr = inb(Int0ctl); - outb(Int0ctl, EOI); - if(irq >= 8){ - isr |= inb(Int1ctl)<<8; - outb(Int1ctl, EOI); - } - iunlock(&i8259lock); - - return isr & (1<irq; - if(irq < 0 || irq > MaxIrqPIC){ - print("i8259enable: irq %d out of range\n", irq); - return -1; - } - irqbit = 1<>8) & 0xFF); - - if(i8259elcr & irqbit) - v->eoi = i8259isr; - else - v->isr = i8259isr; - iunlock(&i8259lock); - - return VectorPIC+irq; -} - -int -i8259vecno(int irq) -{ - return VectorPIC+irq; -} - -int -i8259disable(int irq) -{ - int irqbit; - - /* - * Given an IRQ, disable the corresponding interrupt - * in the 8259. - */ - if(irq < 0 || irq > MaxIrqPIC){ - print("i8259disable: irq %d out of range\n", irq); - return -1; - } - irqbit = 1<>8) & 0xFF); - } - iunlock(&i8259lock); - return 0; -} diff --git a/os/pc/io.h b/os/pc/io.h deleted file mode 100644 index 2a89edee..00000000 --- a/os/pc/io.h +++ /dev/null @@ -1,371 +0,0 @@ -#define X86STEPPING(x) ((x) & 0x0F) -#define X86MODEL(x) (((x)>>4) & 0x0F) -#define X86FAMILY(x) (((x)>>8) & 0x0F) - -enum { - VectorDBG = 1, /* debug exception */ - VectorNMI = 2, /* non-maskable interrupt */ - VectorBPT = 3, /* breakpoint */ - VectorUD = 6, /* invalid opcode exception */ - VectorCNA = 7, /* coprocessor not available */ - Vector2F = 8, /* double fault */ - VectorCSO = 9, /* coprocessor segment overrun */ - VectorPF = 14, /* page fault */ - Vector15 = 15, /* reserved */ - VectorCERR = 16, /* coprocessor error */ - - VectorPIC = 32, /* external i8259 interrupts */ - IrqCLOCK = 0, - IrqKBD = 1, - IrqUART1 = 3, - IrqUART0 = 4, - IrqPCMCIA = 5, - IrqFLOPPY = 6, - IrqLPT = 7, - IrqIRQ7 = 7, - IrqAUX = 12, /* PS/2 port */ - IrqIRQ13 = 13, /* coprocessor on 386 */ - IrqATA0 = 14, - IrqATA1 = 15, - MaxIrqPIC = 15, - - VectorLAPIC = VectorPIC+16, /* local APIC interrupts */ - IrqLINT0 = 16, /* LINT[01] must be offsets 0 and 1 */ - IrqLINT1 = 17, - IrqTIMER = 18, - IrqERROR = 19, - IrqPCINT = 20, - IrqSPURIOUS = 31, /* must have bits [3-0] == 0x0F */ - MaxIrqLAPIC = 31, - - VectorSYSCALL = 64, - - VectorAPIC = 65, /* external APIC interrupts */ - MaxVectorAPIC = 255, -}; - -typedef struct Vctl { - Vctl* next; /* handlers on this vector */ - - char name[KNAMELEN]; /* of driver */ - int isintr; /* interrupt or fault/trap */ - int irq; - int tbdf; - int (*isr)(int); /* get isr bit for this irq */ - int (*eoi)(int); /* eoi */ - - void (*f)(Ureg*, void*); /* handler to call */ - void* a; /* argument to call it with */ -} Vctl; - -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 & 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 */ - 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 */ - 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; -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) - -/* SMBus transactions */ -enum -{ - SMBquick, /* sends address only */ - - /* write */ - SMBsend, /* sends address and cmd */ - SMBbytewrite, /* sends address and cmd and 1 byte */ - SMBwordwrite, /* sends address and cmd and 2 bytes */ - - /* read */ - SMBrecv, /* sends address, recvs 1 byte */ - SMBbyteread, /* sends address and cmd, recv's byte */ - SMBwordread, /* sends address and cmd, recv's 2 bytes */ -}; - -typedef struct SMBus SMBus; -struct SMBus { - QLock; /* mutex */ - Rendez r; /* rendezvous point for completion interrupts */ - void *arg; /* implementation dependent */ - ulong base; /* port or memory base of smbus */ - int busy; - void (*transact)(SMBus*, int, int, int, uchar*); -}; - -/* - * 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/os/pc/kbd.c b/os/pc/kbd.c deleted file mode 100644 index 8db7009c..00000000 --- a/os/pc/kbd.c +++ /dev/null @@ -1,477 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.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= 0xF000, /* function key (begin Unicode private space) */ - Shift= Spec|0x60, - Break= Spec|0x61, - Ctrl= Spec|0x62, - Latin= Spec|0x63, - Caps= Spec|0x64, - Num= Spec|0x65, - Middle= Spec|0x66, - No= 0x00, /* peter */ - - Home= KF|13, - Up= KF|14, - Pgup= KF|15, - Print= KF|16, - Left= KF|17, - Right= KF|18, - End= '\r', - Down= View, - Pgdown= KF|19, - Ins= KF|20, - Del= 0x7F, - Scroll= KF|21, -}; - -/* - * The codes at 0x79 and 0x81 are produed by the PFU Happy Hacking keyboard. - * A 'standard' keyboard doesn't produce anything above 0x58. - */ -Rune 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, '*', -[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5, -[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7', -[0x48] '8', '9', '-', '4', '5', '6', '+', '1', -[0x50] '2', '3', '0', '.', No, No, No, KF|11, -[0x58] KF|12, No, No, No, No, No, No, No, -[0x60] No, No, No, No, No, No, No, No, -[0x68] No, No, No, No, No, No, No, No, -[0x70] No, No, No, No, No, No, No, No, -[0x78] No, View, No, Up, No, No, No, No, -}; - -Rune 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, '*', -[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5, -[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7', -[0x48] '8', '9', '-', '4', '5', '6', '+', '1', -[0x50] '2', '3', '0', '.', No, No, No, KF|11, -[0x58] KF|12, No, No, No, No, No, No, No, -[0x60] No, No, No, No, No, No, No, No, -[0x68] No, No, No, No, No, No, No, No, -[0x70] No, No, No, No, No, No, No, No, -[0x78] No, Up, No, Up, No, No, No, No, -}; - -Rune 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, '\n', Ctrl, No, No, -[0x20] No, No, No, No, No, No, No, No, -[0x28] No, No, Shift, No, No, No, No, No, -[0x30] 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, Left, No, Right, No, End, -[0x50] Down, Pgdown, Ins, Del, No, No, No, No, -[0x58] No, No, No, No, No, No, No, No, -[0x60] No, No, No, No, No, No, No, No, -[0x68] No, No, No, No, No, No, No, No, -[0x70] No, No, No, No, No, No, No, No, -[0x78] No, Up, No, No, No, No, No, No, -}; - -enum -{ - /* controller command byte */ - Cscs1= (1<<6), /* scan code set 1 */ - Cauxdis= (1<<5), /* mouse disable */ - Ckbddis= (1<<4), /* kbd disable */ - Csf= (1<<2), /* system flag */ - Cauxint= (1<<1), /* mouse interrupt enable */ - Ckbdint= (1<<0), /* kbd interrupt enable */ -}; - -int mouseshifted; - -static Lock i8042lock; -static uchar ccc; -static void (*auxputc)(int, int); - -/* - * 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 reset the machine - */ -void -i8042reset(void) -{ - ushort *s = KADDR(0x472); - int i, x; - - *s = 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); - } -} - -int -i8042auxcmd(int cmd) -{ - unsigned int c; - int tries; - - c = 0; - tries = 0; - - ilock(&i8042lock); - do{ - if(tries++ > 2) - break; - if(outready() < 0) - break; - outb(Cmd, 0xD4); - if(outready() < 0) - break; - outb(Data, cmd); - if(outready() < 0) - break; - if(inready() < 0) - break; - c = inb(Data); - } while(c == 0xFE || c == 0); - iunlock(&i8042lock); - - if(c != 0xFA){ - print("i8042: %2.2ux returned to the %2.2ux command\n", c, cmd); - return -1; - } - return 0; -} - -int -i8042auxcmds(uchar *cmd, int ncmd) -{ - int i; - - ilock(&i8042lock); - for(i=0; i 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; - mouseshifted = 0; - break; - case Ctrl: - ctl = 0; - break; - } - return; - } - - /* - * normal character - */ - if(!(c & (Spec|KF))){ - if(ctl){ - if(alt && c == Del) - exit(0); - c &= 0x1f; - } - if(!collecting){ - kbdputc(kbdq, c); - return; - } - kc[nk++] = c; - c = latin1(kc, nk); - if(c < -1) /* need more keystrokes */ - return; - if(c != -1) /* valid sequence */ - kbdputc(kbdq, c); - else /* dump characters */ - for(i=0; i>22) & 0x03FF)<<2) -#define PTO(a) (((((a))>>12) & 0x03FF)<<2) - -/* - * For backwards compatiblity with 9load - should go away when 9load is changed - * 9load currently sets up the mmu, however the first 16MB of memory is identity - * mapped, so behave as if the mmu was not setup - */ -TEXT _start0x80100020(SB), $0 - MOVL $_start0x00100020(SB), AX - ANDL $~KZERO, AX - JMP* AX - -/* - * Must be 4-byte aligned. - */ -TEXT _multibootheader(SB), $0 - LONG $0x1BADB002 /* magic */ - LONG $0x00010003 /* flags */ - LONG $-(0x1BADB002 + 0x00010003) /* checksum */ - LONG $_multibootheader-KZERO(SB) /* header_addr */ - LONG $_start0x80100020-KZERO(SB) /* load_addr */ - LONG $edata-KZERO(SB) /* load_end_addr */ - LONG $end-KZERO(SB) /* bss_end_addr */ - LONG $_start0x80100020-KZERO(SB) /* entry_addr */ - LONG $0 /* mode_type */ - LONG $0 /* width */ - LONG $0 /* height */ - LONG $0 /* depth */ - -/* - * In protected mode with paging turned off and segment registers setup to linear map all memory. - * Entered via a jump to 0x00100020, the physical address of the virtual kernel entry point of 0x80100020 - * Make the basic page tables for processor 0. Four pages are needed for the basic set: - * a page directory, a page table for mapping the first 4MB of physical memory to KZERO, - * and virtual and physical pages for mapping the Mach structure. - * The remaining PTEs will be allocated later when memory is sized. - * An identity mmu map is also needed for the switch to virtual mode. This - * identity mapping is removed once the MMU is going and the JMP has been made - * to virtual memory. - */ -TEXT _start0x00100020(SB), $0 - CLI /* make sure interrupts are off */ - - /* set up the gdt so we have sane plan 9 style gdts. */ - MOVL $tgdtptr(SB), AX - ANDL $~KZERO, AX - MOVL (AX), GDTR - MOVW $1, AX - MOVW AX, MSW - - /* clear prefetch queue (weird code to avoid optimizations) */ - DELAY - - /* set segs to something sane (avoid traps later) */ - MOVW $(1<<3), AX - MOVW AX, DS - MOVW AX, SS - MOVW AX, ES - MOVW AX, FS - MOVW AX, GS - -/* JMP $(2<<3):$mode32bit(SB) /**/ - BYTE $0xEA - LONG $mode32bit-KZERO(SB) - WORD $(2<<3) - -/* - * gdt to get us to 32-bit/segmented/unpaged mode - */ -TEXT tgdt(SB), $0 - - /* null descriptor */ - LONG $0 - LONG $0 - - /* data segment descriptor for 4 gigabytes (PL 0) */ - LONG $(0xFFFF) - LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) - - /* exec segment descriptor for 4 gigabytes (PL 0) */ - LONG $(0xFFFF) - LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) - -/* - * pointer to initial gdt - * Note the -KZERO which puts the physical address in the gdtptr. - * that's needed as we start executing in physical addresses. - */ -TEXT tgdtptr(SB), $0 - - WORD $(3*8) - LONG $tgdt-KZERO(SB) - -TEXT mode32bit(SB), $0 - /* At this point, the GDT setup is done. */ - - MOVL $PADDR(CPU0PDB), DI /* clear 4 pages for the tables etc. */ - XORL AX, AX - MOVL $(4*BY2PG), CX - SHRL $2, CX - - CLD - REP; STOSL - - MOVL $PADDR(CPU0PDB), AX - ADDL $PDO(KZERO), AX /* page directory offset for KZERO */ - MOVL $PADDR(CPU0PTE), (AX) /* PTE's for 0x80000000 */ - MOVL $(PTEWRITE|PTEVALID), BX /* page permissions */ - ORL BX, (AX) - - MOVL $PADDR(CPU0PTE), AX /* first page of page table */ - MOVL $1024, CX /* 1024 pages in 4MB */ -_setpte: - MOVL BX, (AX) - ADDL $(1<machno */ - - ADDL $(MACHSIZE-4), SP /* initialise stack */ - -/* - * Need to do one final thing to ensure a clean machine environment, - * clear the EFLAGS register, which can only be done once there is a stack. - */ - MOVL $0, AX - PUSHL AX - POPFL - - CALL main(SB) - -/* - * Park a processor. Should never fall through a return from main to here, - * should only be called by application processors when shutting down. - */ -TEXT idle(SB), $0 -_idle: - STI - HLT - JMP _idle - -/* - * Port I/O. - * in[bsl] input a byte|short|long - * ins[bsl] input a string of bytes|shorts|longs - * out[bsl] output a byte|short|long - * outs[bsl] output a string of bytes|shorts|longs - */ -TEXT inb(SB), $0 - MOVL port+0(FP), DX - XORL AX, AX - INB - RET - -TEXT insb(SB), $0 - MOVL port+0(FP), DX - MOVL address+4(FP), DI - MOVL count+8(FP), CX - CLD - REP; INSB - RET - -TEXT ins(SB), $0 - MOVL port+0(FP), DX - XORL AX, AX - OP16; INL - RET - -TEXT inss(SB), $0 - MOVL port+0(FP), DX - MOVL address+4(FP), DI - MOVL count+8(FP), CX - CLD - REP; OP16; INSL - RET - -TEXT inl(SB), $0 - MOVL port+0(FP), DX - INL - RET - -TEXT insl(SB), $0 - MOVL port+0(FP), DX - MOVL address+4(FP), DI - MOVL count+8(FP), CX - CLD - REP; INSL - RET - -TEXT outb(SB), $0 - MOVL port+0(FP), DX - MOVL byte+4(FP), AX - OUTB - RET - -TEXT outsb(SB), $0 - MOVL port+0(FP), DX - MOVL address+4(FP), SI - MOVL count+8(FP), CX - CLD - REP; OUTSB - RET - -TEXT outs(SB), $0 - MOVL port+0(FP), DX - MOVL short+4(FP), AX - OP16; OUTL - RET - -TEXT outss(SB), $0 - MOVL port+0(FP), DX - MOVL address+4(FP), SI - MOVL count+8(FP), CX - CLD - REP; OP16; OUTSL - RET - -TEXT outl(SB), $0 - MOVL port+0(FP), DX - MOVL long+4(FP), AX - OUTL - RET - -TEXT outsl(SB), $0 - MOVL port+0(FP), DX - MOVL address+4(FP), SI - MOVL count+8(FP), CX - CLD - REP; OUTSL - RET - -/* there's a macro in fns.h but libinterp can't see it */ -TEXT getcallerpc(SB), $0 - MOVL a+0(FP), AX - RET - -/* - * Read/write various system registers. - * CR4 and the 'model specific registers' should only be read/written - * after it has been determined the processor supports them - */ -TEXT lgdt(SB), $0 /* GDTR - global descriptor table */ - MOVL gdtptr+0(FP), AX - MOVL (AX), GDTR - RET - -TEXT lidt(SB), $0 /* IDTR - interrupt descriptor table */ - MOVL idtptr+0(FP), AX - MOVL (AX), IDTR - RET - -TEXT ltr(SB), $0 /* TR - task register */ - MOVL tptr+0(FP), AX - MOVW AX, TASK - RET - -TEXT getcr0(SB), $0 /* CR0 - processor control */ - MOVL CR0, AX - RET - -TEXT getcr2(SB), $0 /* CR2 - page fault linear address */ - MOVL CR2, AX - RET - -TEXT getcr3(SB), $0 /* CR3 - page directory base */ - MOVL CR3, AX - RET - -TEXT putcr3(SB), $0 - MOVL cr3+0(FP), AX - MOVL AX, CR3 - RET - -TEXT getcr4(SB), $0 /* CR4 - extensions */ - MOVL CR4, AX - RET - -TEXT putcr4(SB), $0 - MOVL cr4+0(FP), AX - MOVL AX, CR4 - RET - -TEXT _cycles(SB), $0 /* time stamp counter; cycles since power up */ - RDTSC - MOVL vlong+0(FP), CX /* &vlong */ - MOVL AX, 0(CX) /* lo */ - MOVL DX, 4(CX) /* hi */ - RET - -TEXT rdmsr(SB), $0 /* model-specific register */ - MOVL index+0(FP), CX - RDMSR - MOVL vlong+4(FP), CX /* &vlong */ - MOVL AX, 0(CX) /* lo */ - MOVL DX, 4(CX) /* hi */ - RET - -TEXT wrmsr(SB), $0 - MOVL index+0(FP), CX - MOVL lo+4(FP), AX - MOVL hi+8(FP), DX - WRMSR - RET - -TEXT wbinvd(SB), $0 - WBINVD - RET - -TEXT rdtsc32(SB), $0 - CPUID - RDTSC - RET - -/* - * Try to determine the CPU type which requires fiddling with EFLAGS. - * If the Id bit can be toggled then the CPUID instruction 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); - */ -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 count+0(FP), CX -_aamloop: - AAM - LOOP _aamloop - RET - -/* - * Floating point. - * Note: the encodings for the FCLEX, FINIT, FSAVE, FSTCW, FSENV and FSTSW - * instructions do NOT have the WAIT prefix byte (i.e. they act like their - * FNxxx variations) so WAIT instructions must be explicitly placed in the - * code as necessary. - */ -#define FPOFF(l) ;\ - MOVL CR0, AX ;\ - ANDL $0xC, AX /* EM, TS */ ;\ - CMPL AX, $0x8 ;\ - JEQ l ;\ - WAIT ;\ -l: ;\ - MOVL CR0, AX ;\ - ANDL $~0x4, AX /* EM=0 */ ;\ - ORL $0x28, AX /* NE=1, TS=1 */ ;\ - MOVL AX, CR0 - -#define FPON ;\ - MOVL CR0, AX ;\ - ANDL $~0xC, AX /* EM=0, TS=0 */ ;\ - MOVL AX, CR0 - -TEXT fpoff(SB), $0 /* disable */ - FPOFF(l1) - RET - -TEXT fpinit(SB), $0 /* enable and init */ - FPON - FINIT - WAIT - /* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */ - /* note that low 6 bits are masks, not enables, on this chip */ - PUSHW $0x0232 - FLDCW 0(SP) - POPW AX - WAIT - RET - -TEXT fpsave(SB), $0 /* save state and disable */ - MOVL p+0(FP), AX - FSAVE 0(AX) /* no WAIT */ - FPOFF(l2) - RET - -TEXT fprestore(SB), $0 /* enable and restore state */ - FPON - MOVL p+0(FP), AX - FRSTOR 0(AX) - WAIT - RET - -TEXT fpstatus(SB), $0 /* get floating point status */ - FSTSW AX - RET - -TEXT fpenv(SB), $0 /* save state without waiting */ - MOVL p+0(FP), AX - FSTENV 0(AX) - RET - -TEXT fpclear(SB), $0 /* clear pending exceptions */ - FPON - FCLEX /* no WAIT */ - FPOFF(l3) - RET - -/* - */ -TEXT splhi(SB), $0 - MOVL $(MACHADDR+0x04), AX /* save PC in m->splpc */ - MOVL (SP), BX - MOVL BX, (AX) - - PUSHFL - POPL AX - CLI - RET - -TEXT spllo(SB), $0 - PUSHFL - POPL AX - STI - RET - -TEXT splx(SB), $0 - MOVL $(MACHADDR+0x04), AX /* save PC in m->splpc */ - MOVL (SP), BX - MOVL BX, (AX) - /*FALLTHROUGH*/ - -TEXT splxpc(SB), $0 /* for iunlock */ - MOVL s+0(FP), AX - PUSHL AX - POPFL - RET - -TEXT spldone(SB), $0 - RET - -TEXT islo(SB), $0 - PUSHFL - POPL AX - ANDL $0x200, AX /* interrupt enable flag */ - RET - -/* - * Test-And-Set - */ -TEXT _tas(SB), $0 - MOVL $0xDEADDEAD, AX - MOVL lock+0(FP), BX - XCHGL AX, (BX) /* lock->key */ - RET - -TEXT _xinc(SB), $0 /* void _xinc(long*); */ - MOVL l+0(FP), AX - LOCK; INCL 0(AX) - RET - -TEXT _xdec(SB), $0 /* long _xdec(long*); */ - MOVL l+0(FP), BX - XORL AX, AX - LOCK; DECL 0(BX) - JLT _xdeclt - JGT _xdecgt - RET -_xdecgt: - INCL AX - RET -_xdeclt: - DECL AX - RET - -TEXT mb386(SB), $0 - POPL AX /* return PC */ - PUSHFL - PUSHL CS - PUSHL AX - IRETL - -TEXT mb586(SB), $0 - XORL AX, AX - CPUID - RET - -TEXT xchgw(SB), $0 - MOVL v+4(FP), AX - MOVL p+0(FP), BX - XCHGW AX, (BX) - RET - -TEXT mul64fract(SB), $0 -/* - * Multiply two 64-bit number s and keep the middle 64 bits from the 128-bit result - * See ../port/tod.c for motivation. - */ - MOVL r+0(FP), CX - XORL BX, BX /* BX = 0 */ - - MOVL a+8(FP), AX - MULL b+16(FP) /* a1*b1 */ - MOVL AX, 4(CX) /* r2 = lo(a1*b1) */ - - MOVL a+8(FP), AX - MULL b+12(FP) /* a1*b0 */ - MOVL AX, 0(CX) /* r1 = lo(a1*b0) */ - ADDL DX, 4(CX) /* r2 += hi(a1*b0) */ - - MOVL a+4(FP), AX - MULL b+16(FP) /* a0*b1 */ - ADDL AX, 0(CX) /* r1 += lo(a0*b1) */ - ADCL DX, 4(CX) /* r2 += hi(a0*b1) + carry */ - - MOVL a+4(FP), AX - MULL b+12(FP) /* a0*b0 */ - ADDL DX, 0(CX) /* r1 += hi(a0*b0) */ - ADCL BX, 4(CX) /* r2 += carry */ - RET - -/* - * label consists of a stack pointer and a PC - */ -TEXT gotolabel(SB), $0 - MOVL label+0(FP), AX - MOVL 0(AX), SP /* restore sp */ - MOVL 4(AX), AX /* put return pc on the stack */ - MOVL AX, 0(SP) - MOVL $1, AX /* return 1 */ - RET - -TEXT setlabel(SB), $0 - MOVL label+0(FP), AX - MOVL SP, 0(AX) /* store sp */ - MOVL 0(SP), BX /* store return pc */ - MOVL BX, 4(AX) - MOVL $0, AX /* return 0 */ - RET - -TEXT halt(SB), $0 - STI - HLT - RET - -/* - * Interrupt/exception handling. - * Each entry in the vector table calls either _strayintr or _strayintrx depending - * on whether an error code has been automatically pushed onto the stack - * (_strayintrx) or not, in which case a dummy entry must be pushed before retrieving - * the trap type from the vector table entry and placing it on the stack as part - * of the Ureg structure. - * The size of each entry in the vector table (6 bytes) is known in trapinit(). - */ -TEXT _strayintr(SB), $0 - PUSHL AX /* save AX */ - MOVL 4(SP), AX /* return PC from vectortable(SB) */ - JMP intrcommon - -TEXT _strayintrx(SB), $0 - XCHGL AX, (SP) /* exchange AX with pointer to trap type */ -intrcommon: - PUSHL DS - MOVBLZX (AX), AX /* trap type -> AX */ - XCHGL AX, 4(SP) /* exchange trap type with AX */ - PUSHL ES - PUSHL FS - PUSHL GS - PUSHAL - MOVL $(KDSEL), AX - MOVW AX, DS - MOVW AX, ES - PUSHL SP /* Ureg* argument to trap */ - CALL trap(SB) - -TEXT forkret(SB), $0 - POPL AX - POPAL - POPL GS - POPL FS - POPL ES - POPL DS - ADDL $8, SP /* pop error code and trap type */ - IRETL - -TEXT vectortable(SB), $0 - CALL _strayintr(SB); BYTE $0x00 /* divide error */ - CALL _strayintr(SB); BYTE $0x01 /* debug exception */ - CALL _strayintr(SB); BYTE $0x02 /* NMI interrupt */ - CALL _strayintr(SB); BYTE $0x03 /* breakpoint */ - CALL _strayintr(SB); BYTE $0x04 /* overflow */ - CALL _strayintr(SB); BYTE $0x05 /* bound */ - CALL _strayintr(SB); BYTE $0x06 /* invalid opcode */ - CALL _strayintr(SB); BYTE $0x07 /* no coprocessor available */ - CALL _strayintrx(SB); BYTE $0x08 /* double fault */ - CALL _strayintr(SB); BYTE $0x09 /* coprocessor segment overflow */ - CALL _strayintrx(SB); BYTE $0x0A /* invalid TSS */ - CALL _strayintrx(SB); BYTE $0x0B /* segment not available */ - CALL _strayintrx(SB); BYTE $0x0C /* stack exception */ - CALL _strayintrx(SB); BYTE $0x0D /* general protection error */ - CALL _strayintrx(SB); BYTE $0x0E /* page fault */ - CALL _strayintr(SB); BYTE $0x0F /* */ - CALL _strayintr(SB); BYTE $0x10 /* coprocessor error */ - CALL _strayintrx(SB); BYTE $0x11 /* alignment check */ - CALL _strayintr(SB); BYTE $0x12 /* machine check */ - CALL _strayintr(SB); BYTE $0x13 - CALL _strayintr(SB); BYTE $0x14 - CALL _strayintr(SB); BYTE $0x15 - CALL _strayintr(SB); BYTE $0x16 - CALL _strayintr(SB); BYTE $0x17 - CALL _strayintr(SB); BYTE $0x18 - CALL _strayintr(SB); BYTE $0x19 - CALL _strayintr(SB); BYTE $0x1A - CALL _strayintr(SB); BYTE $0x1B - CALL _strayintr(SB); BYTE $0x1C - CALL _strayintr(SB); BYTE $0x1D - CALL _strayintr(SB); BYTE $0x1E - CALL _strayintr(SB); BYTE $0x1F - CALL _strayintr(SB); BYTE $0x20 /* VectorLAPIC */ - CALL _strayintr(SB); BYTE $0x21 - CALL _strayintr(SB); BYTE $0x22 - CALL _strayintr(SB); BYTE $0x23 - CALL _strayintr(SB); BYTE $0x24 - CALL _strayintr(SB); BYTE $0x25 - CALL _strayintr(SB); BYTE $0x26 - CALL _strayintr(SB); BYTE $0x27 - CALL _strayintr(SB); BYTE $0x28 - CALL _strayintr(SB); BYTE $0x29 - CALL _strayintr(SB); BYTE $0x2A - CALL _strayintr(SB); BYTE $0x2B - CALL _strayintr(SB); BYTE $0x2C - CALL _strayintr(SB); BYTE $0x2D - CALL _strayintr(SB); BYTE $0x2E - CALL _strayintr(SB); BYTE $0x2F - CALL _strayintr(SB); BYTE $0x30 - CALL _strayintr(SB); BYTE $0x31 - CALL _strayintr(SB); BYTE $0x32 - CALL _strayintr(SB); BYTE $0x33 - CALL _strayintr(SB); BYTE $0x34 - CALL _strayintr(SB); BYTE $0x35 - CALL _strayintr(SB); BYTE $0x36 - CALL _strayintr(SB); BYTE $0x37 - CALL _strayintr(SB); BYTE $0x38 - CALL _strayintr(SB); BYTE $0x39 - CALL _strayintr(SB); BYTE $0x3A - CALL _strayintr(SB); BYTE $0x3B - CALL _strayintr(SB); BYTE $0x3C - CALL _strayintr(SB); BYTE $0x3D - CALL _strayintr(SB); BYTE $0x3E - CALL _strayintr(SB); BYTE $0x3F - CALL _strayintr(SB); BYTE $0x40 /* VectorSYSCALL */ - CALL _strayintr(SB); BYTE $0x41 - CALL _strayintr(SB); BYTE $0x42 - CALL _strayintr(SB); BYTE $0x43 - CALL _strayintr(SB); BYTE $0x44 - CALL _strayintr(SB); BYTE $0x45 - CALL _strayintr(SB); BYTE $0x46 - CALL _strayintr(SB); BYTE $0x47 - CALL _strayintr(SB); BYTE $0x48 - CALL _strayintr(SB); BYTE $0x49 - CALL _strayintr(SB); BYTE $0x4A - CALL _strayintr(SB); BYTE $0x4B - CALL _strayintr(SB); BYTE $0x4C - CALL _strayintr(SB); BYTE $0x4D - CALL _strayintr(SB); BYTE $0x4E - CALL _strayintr(SB); BYTE $0x4F - CALL _strayintr(SB); BYTE $0x50 - CALL _strayintr(SB); BYTE $0x51 - CALL _strayintr(SB); BYTE $0x52 - CALL _strayintr(SB); BYTE $0x53 - CALL _strayintr(SB); BYTE $0x54 - CALL _strayintr(SB); BYTE $0x55 - CALL _strayintr(SB); BYTE $0x56 - CALL _strayintr(SB); BYTE $0x57 - CALL _strayintr(SB); BYTE $0x58 - CALL _strayintr(SB); BYTE $0x59 - CALL _strayintr(SB); BYTE $0x5A - CALL _strayintr(SB); BYTE $0x5B - CALL _strayintr(SB); BYTE $0x5C - CALL _strayintr(SB); BYTE $0x5D - CALL _strayintr(SB); BYTE $0x5E - CALL _strayintr(SB); BYTE $0x5F - CALL _strayintr(SB); BYTE $0x60 - CALL _strayintr(SB); BYTE $0x61 - CALL _strayintr(SB); BYTE $0x62 - CALL _strayintr(SB); BYTE $0x63 - CALL _strayintr(SB); BYTE $0x64 - CALL _strayintr(SB); BYTE $0x65 - CALL _strayintr(SB); BYTE $0x66 - CALL _strayintr(SB); BYTE $0x67 - CALL _strayintr(SB); BYTE $0x68 - CALL _strayintr(SB); BYTE $0x69 - CALL _strayintr(SB); BYTE $0x6A - CALL _strayintr(SB); BYTE $0x6B - CALL _strayintr(SB); BYTE $0x6C - CALL _strayintr(SB); BYTE $0x6D - CALL _strayintr(SB); BYTE $0x6E - CALL _strayintr(SB); BYTE $0x6F - CALL _strayintr(SB); BYTE $0x70 - CALL _strayintr(SB); BYTE $0x71 - CALL _strayintr(SB); BYTE $0x72 - CALL _strayintr(SB); BYTE $0x73 - CALL _strayintr(SB); BYTE $0x74 - CALL _strayintr(SB); BYTE $0x75 - CALL _strayintr(SB); BYTE $0x76 - CALL _strayintr(SB); BYTE $0x77 - CALL _strayintr(SB); BYTE $0x78 - CALL _strayintr(SB); BYTE $0x79 - CALL _strayintr(SB); BYTE $0x7A - CALL _strayintr(SB); BYTE $0x7B - CALL _strayintr(SB); BYTE $0x7C - CALL _strayintr(SB); BYTE $0x7D - CALL _strayintr(SB); BYTE $0x7E - CALL _strayintr(SB); BYTE $0x7F - CALL _strayintr(SB); BYTE $0x80 /* Vector[A]PIC */ - CALL _strayintr(SB); BYTE $0x81 - CALL _strayintr(SB); BYTE $0x82 - CALL _strayintr(SB); BYTE $0x83 - CALL _strayintr(SB); BYTE $0x84 - CALL _strayintr(SB); BYTE $0x85 - CALL _strayintr(SB); BYTE $0x86 - CALL _strayintr(SB); BYTE $0x87 - CALL _strayintr(SB); BYTE $0x88 - CALL _strayintr(SB); BYTE $0x89 - CALL _strayintr(SB); BYTE $0x8A - CALL _strayintr(SB); BYTE $0x8B - CALL _strayintr(SB); BYTE $0x8C - CALL _strayintr(SB); BYTE $0x8D - CALL _strayintr(SB); BYTE $0x8E - CALL _strayintr(SB); BYTE $0x8F - CALL _strayintr(SB); BYTE $0x90 - CALL _strayintr(SB); BYTE $0x91 - CALL _strayintr(SB); BYTE $0x92 - CALL _strayintr(SB); BYTE $0x93 - CALL _strayintr(SB); BYTE $0x94 - CALL _strayintr(SB); BYTE $0x95 - CALL _strayintr(SB); BYTE $0x96 - CALL _strayintr(SB); BYTE $0x97 - CALL _strayintr(SB); BYTE $0x98 - CALL _strayintr(SB); BYTE $0x99 - CALL _strayintr(SB); BYTE $0x9A - CALL _strayintr(SB); BYTE $0x9B - CALL _strayintr(SB); BYTE $0x9C - CALL _strayintr(SB); BYTE $0x9D - CALL _strayintr(SB); BYTE $0x9E - CALL _strayintr(SB); BYTE $0x9F - CALL _strayintr(SB); BYTE $0xA0 - CALL _strayintr(SB); BYTE $0xA1 - CALL _strayintr(SB); BYTE $0xA2 - CALL _strayintr(SB); BYTE $0xA3 - CALL _strayintr(SB); BYTE $0xA4 - CALL _strayintr(SB); BYTE $0xA5 - CALL _strayintr(SB); BYTE $0xA6 - CALL _strayintr(SB); BYTE $0xA7 - CALL _strayintr(SB); BYTE $0xA8 - CALL _strayintr(SB); BYTE $0xA9 - CALL _strayintr(SB); BYTE $0xAA - CALL _strayintr(SB); BYTE $0xAB - CALL _strayintr(SB); BYTE $0xAC - CALL _strayintr(SB); BYTE $0xAD - CALL _strayintr(SB); BYTE $0xAE - CALL _strayintr(SB); BYTE $0xAF - CALL _strayintr(SB); BYTE $0xB0 - CALL _strayintr(SB); BYTE $0xB1 - CALL _strayintr(SB); BYTE $0xB2 - CALL _strayintr(SB); BYTE $0xB3 - CALL _strayintr(SB); BYTE $0xB4 - CALL _strayintr(SB); BYTE $0xB5 - CALL _strayintr(SB); BYTE $0xB6 - CALL _strayintr(SB); BYTE $0xB7 - CALL _strayintr(SB); BYTE $0xB8 - CALL _strayintr(SB); BYTE $0xB9 - CALL _strayintr(SB); BYTE $0xBA - CALL _strayintr(SB); BYTE $0xBB - CALL _strayintr(SB); BYTE $0xBC - CALL _strayintr(SB); BYTE $0xBD - CALL _strayintr(SB); BYTE $0xBE - CALL _strayintr(SB); BYTE $0xBF - CALL _strayintr(SB); BYTE $0xC0 - CALL _strayintr(SB); BYTE $0xC1 - CALL _strayintr(SB); BYTE $0xC2 - CALL _strayintr(SB); BYTE $0xC3 - CALL _strayintr(SB); BYTE $0xC4 - CALL _strayintr(SB); BYTE $0xC5 - CALL _strayintr(SB); BYTE $0xC6 - CALL _strayintr(SB); BYTE $0xC7 - CALL _strayintr(SB); BYTE $0xC8 - CALL _strayintr(SB); BYTE $0xC9 - CALL _strayintr(SB); BYTE $0xCA - CALL _strayintr(SB); BYTE $0xCB - CALL _strayintr(SB); BYTE $0xCC - CALL _strayintr(SB); BYTE $0xCD - CALL _strayintr(SB); BYTE $0xCE - CALL _strayintr(SB); BYTE $0xCF - CALL _strayintr(SB); BYTE $0xD0 - CALL _strayintr(SB); BYTE $0xD1 - CALL _strayintr(SB); BYTE $0xD2 - CALL _strayintr(SB); BYTE $0xD3 - CALL _strayintr(SB); BYTE $0xD4 - CALL _strayintr(SB); BYTE $0xD5 - CALL _strayintr(SB); BYTE $0xD6 - CALL _strayintr(SB); BYTE $0xD7 - CALL _strayintr(SB); BYTE $0xD8 - CALL _strayintr(SB); BYTE $0xD9 - CALL _strayintr(SB); BYTE $0xDA - CALL _strayintr(SB); BYTE $0xDB - CALL _strayintr(SB); BYTE $0xDC - CALL _strayintr(SB); BYTE $0xDD - CALL _strayintr(SB); BYTE $0xDE - CALL _strayintr(SB); BYTE $0xDF - CALL _strayintr(SB); BYTE $0xE0 - CALL _strayintr(SB); BYTE $0xE1 - CALL _strayintr(SB); BYTE $0xE2 - CALL _strayintr(SB); BYTE $0xE3 - CALL _strayintr(SB); BYTE $0xE4 - CALL _strayintr(SB); BYTE $0xE5 - CALL _strayintr(SB); BYTE $0xE6 - CALL _strayintr(SB); BYTE $0xE7 - CALL _strayintr(SB); BYTE $0xE8 - CALL _strayintr(SB); BYTE $0xE9 - CALL _strayintr(SB); BYTE $0xEA - CALL _strayintr(SB); BYTE $0xEB - CALL _strayintr(SB); BYTE $0xEC - CALL _strayintr(SB); BYTE $0xED - CALL _strayintr(SB); BYTE $0xEE - CALL _strayintr(SB); BYTE $0xEF - CALL _strayintr(SB); BYTE $0xF0 - CALL _strayintr(SB); BYTE $0xF1 - CALL _strayintr(SB); BYTE $0xF2 - CALL _strayintr(SB); BYTE $0xF3 - CALL _strayintr(SB); BYTE $0xF4 - CALL _strayintr(SB); BYTE $0xF5 - CALL _strayintr(SB); BYTE $0xF6 - CALL _strayintr(SB); BYTE $0xF7 - CALL _strayintr(SB); BYTE $0xF8 - CALL _strayintr(SB); BYTE $0xF9 - CALL _strayintr(SB); BYTE $0xFA - CALL _strayintr(SB); BYTE $0xFB - CALL _strayintr(SB); BYTE $0xFC - CALL _strayintr(SB); BYTE $0xFD - CALL _strayintr(SB); BYTE $0xFE - CALL _strayintr(SB); BYTE $0xFF diff --git a/os/pc/main.c b/os/pc/main.c deleted file mode 100644 index 11e8d4db..00000000 --- a/os/pc/main.c +++ /dev/null @@ -1,468 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" - -extern int main_pool_pcnt; -extern int heap_pool_pcnt; -extern int image_pool_pcnt; -int pckdebug; - -Mach *m; - -static uchar *sp; /* stack pointer for /boot */ - -/* - * 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. - */ -#define BOOTLINE ((char*)CONFADDR) -#define BOOTLINELEN 64 -#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN)) -#define BOOTARGSLEN (4096-0x200-BOOTLINELEN) -#define MAXCONF 64 - -char bootdisk[KNAMELEN]; -char *confname[MAXCONF]; -char *confval[MAXCONF]; -int nconf; - -static void -options(void) -{ - long i, n; - char *cp, *line[MAXCONF], *p, *q; - - /* - * parse configuration args from dos file plan9.ini - */ - cp = BOOTARGS; /* where b.com leaves its config */ - cp[BOOTARGSLEN-1] = 0; - - /* - * Strip out '\r', change '\t' -> ' '. - */ - p = cp; - for(q = cp; *q; q++){ - if(*q == '\r') - continue; - if(*q == '\t') - *q = ' '; - *p++ = *q; - } - *p = 0; - - n = getfields(cp, line, MAXCONF, 1, "\n"); - for(i = 0; i < n; i++){ - if(*line[i] == '#') - continue; - cp = strchr(line[i], '='); - if(cp == nil) - continue; - *cp++ = '\0'; - confname[nconf] = line[i]; - confval[nconf] = cp; - nconf++; - } -} - -static void -doc(char *m) -{ - int i; - print("%s...\n", m); - for(i = 0; i < 100*1024*1024; i++) - i++; -} - -void -main(void) -{ - outb(0x3F2, 0x00); /* botch: turn off the floppy motor */ - - mach0init(); - options(); - ioinit(); - i8250console(); - quotefmtinstall(); - kbdinit(); - i8253init(); - cpuidentify(); - confinit(); - archinit(); - xinit(); - poolsizeinit(); - trapinit(); - printinit(); - screeninit(); - cpuidprint(); - mmuinit(); - eve = strdup("inferno"); - if(arch->intrinit){ /* launches other processors on an mp */ - doc("intrinit"); - arch->intrinit(); - } - doc("timersinit"); - timersinit(); - doc("mathinit"); - mathinit(); - doc("kbdenable"); - kbdenable(); - if(arch->clockenable){ - doc("clockinit"); - arch->clockenable(); - } - doc("procinit"); - procinit(); - doc("links"); - links(); - doc("chandevreset"); - chandevreset(); - doc("userinit"); - userinit(); - doc("schedinit"); - active.thunderbirdsarego = 1; - schedinit(); - -} - -void -mach0init(void) -{ - conf.nmach = 1; - MACHP(0) = (Mach*)CPU0MACH; - m->pdb = (ulong*)CPU0PDB; - m->gdt = (Segdesc*)CPU0GDT; - - machinit(); - - active.machs = 1; - active.exiting = 0; -} - -void -machinit(void) -{ - int machno; - ulong *pdb; - Segdesc *gdt; - - machno = m->machno; - pdb = m->pdb; - gdt = m->gdt; - memset(m, 0, sizeof(Mach)); - m->machno = machno; - m->pdb = pdb; - m->gdt = gdt; - - /* - * For polled uart output at boot, need - * a default delay constant. 100000 should - * be enough for a while. Cpuidentify will - * calculate the real value later. - */ - m->loopconst = 100000; -} - -void -init0(void) -{ - Osenv *o; - int i; - char buf[2*KNAMELEN]; - - up->nerrlab = 0; - - spllo(); - if(waserror()) - panic("init0: %r"); - /* - * These are o.k. because rootinit is null. - * Then early kproc's will have a root and dot. - */ - o = up->env; - o->pgrp->slash = namec("#/", Atodir, 0, 0); - cnameclose(o->pgrp->slash->name); - o->pgrp->slash->name = newcname("/"); - o->pgrp->dot = cclone(o->pgrp->slash); - - chandevinit(); - - if(!waserror()){ - ksetenv("cputype", "386", 0); - snprint(buf, sizeof(buf), "386 %s", conffile); - ksetenv("terminal", buf, 0); - for(i = 0; i < nconf; i++){ - if(confname[i][0] != '*') - ksetenv(confname[i], confval[i], 0); - ksetenv(confname[i], confval[i], 1); - } - poperror(); - } - - poperror(); - - disinit("/osinit.dis"); -} - -void -userinit(void) -{ - Proc *p; - Osenv *o; - - p = newproc(); - o = p->env; - - o->fgrp = newfgrp(nil); - - o->pgrp = newpgrp(); - kstrdup(&o->user, eve); - - strcpy(p->text, "interp"); - - p->fpstate = FPINIT; - fpoff(); - - /* - * Kernel Stack - * - * N.B. make sure there's - * 4 bytes for gotolabel's return PC - */ - p->sched.pc = (ulong)init0; - p->sched.sp = (ulong)p->kstack+KSTACK-BY2WD; - - ready(p); -} - -Conf conf; - -char* -getconf(char *name) -{ - int i; - - for(i = 0; i < nconf; i++) - if(cistrcmp(confname[i], name) == 0) - return confval[i]; - return 0; -} - -void -confinit(void) -{ - char *p; - int pcnt; - ulong maxmem; - - if(p = getconf("*maxmem")) - maxmem = strtoul(p, 0, 0); - else - maxmem = 0; - if(p = getconf("*kernelpercent")) - pcnt = 100 - strtol(p, 0, 0); - else - pcnt = 0; - - meminit(maxmem); - - conf.npage = conf.npage0 + conf.npage1; - if(pcnt < 10) - pcnt = 70; - conf.ialloc = (((conf.npage*(100-pcnt))/100)/2)*BY2PG; - - conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5; -} - -void -poolsizeinit(void) -{ - ulong nb; - - nb = conf.npage*BY2PG; - poolsize(mainmem, (nb*main_pool_pcnt)/100, 0); - poolsize(heapmem, (nb*heap_pool_pcnt)/100, 0); - poolsize(imagmem, (nb*image_pool_pcnt)/100, 1); -} - -static char *mathmsg[] = -{ - "invalid operation", - "denormalized operand", - "division by zero", - "numeric overflow", - "numeric underflow", - "precision loss", - "stack", - "error", -}; - -/* - * math coprocessor error - */ -void -matherror(Ureg* ureg, void* arg) -{ - ulong status; - int i; - char *msg; - char note[ERRMAX]; - - USED(arg); - - /* - * a write cycle to port 0xF0 clears the interrupt latch attached - * to the error# line from the 387 - */ - if(!(m->cpuiddx & 0x01)) - outb(0xF0, 0xFF); - - /* - * save floating point state to check out error - */ - FPsave(&up->fpsave.env); - status = up->fpsave.env.status; - - msg = 0; - for(i = 0; i < 8; i++) - if((1<fpsave.env.pc); - error(note); - break; - } - if(msg == 0){ - sprint(note, "sys: fp: unknown fppc=0x%lux", up->fpsave.env.pc); - error(note); - } - if(ureg->pc & KZERO) - panic("fp: status %lux fppc=0x%lux pc=0x%lux", status, - up->fpsave.env.pc, ureg->pc); -} - -/* - * math coprocessor emulation fault - */ -void -mathemu(Ureg* ureg, void* arg) -{ - USED(ureg, arg); - switch(up->fpstate){ - case FPINIT: - fpinit(); - up->fpstate = FPACTIVE; - break; - case FPINACTIVE: - fprestore(&up->fpsave); - up->fpstate = FPACTIVE; - break; - case FPACTIVE: - panic("math emu"); - break; - } -} - -/* - * math coprocessor segment overrun - */ -void -mathover(Ureg* ureg, void* arg) -{ - USED(arg); - print("sys: fp: math overrun pc 0x%lux pid %ld\n", ureg->pc, up->pid); - pexit("math overrun", 0); -} - -void -mathinit(void) -{ - trapenable(VectorCERR, matherror, 0, "matherror"); - if(X86FAMILY(m->cpuidax) == 3) - intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror"); - trapenable(VectorCNA, mathemu, 0, "mathemu"); - trapenable(VectorCSO, mathover, 0, "mathover"); -} - -/* - * Save the mach dependent part of the process state. - */ -void -procsave(Proc *p) -{ - if(p->fpstate == FPACTIVE){ - if(p->state == Moribund) - fpoff(); - else - fpsave(&up->fpsave); - p->fpstate = FPINACTIVE; - } -} - -void -exit(int ispanic) -{ - USED(ispanic); - - up = 0; - print("exiting\n"); - - /* Shutdown running devices */ - chandevshutdown(); - - arch->reset(); -} - -void -reboot(void) -{ - exit(0); -} - -int -isaconfig(char *class, int ctlrno, ISAConf *isa) -{ - char cc[32], *p; - int i; - - snprint(cc, sizeof cc, "%s%d", class, ctlrno); - p = getconf(cc); - if(p == nil) - return 0; - - isa->nopt = tokenize(p, isa->opt, NISAOPT); - for(i = 0; i < isa->nopt; i++){ - p = isa->opt[i]; - if(cistrncmp(p, "type=", 5) == 0) - isa->type = p + 5; - 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, "dma=", 4) == 0) - isa->dma = 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, "freq=", 5) == 0) - isa->freq = strtoul(p+5, &p, 0); - } - return 1; -} - -/* - * put the processor in the halt state if we've no processes to run. - * an interrupt will get us going again. - */ -void -idlehands(void) -{ - if(conf.nmach == 1) - halt(); -} diff --git a/os/pc/mem.h b/os/pc/mem.h deleted file mode 100644 index b67252ee..00000000 --- a/os/pc/mem.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Memory and machine-specific definitions. Used in C and assembler. - */ - -/* - * Sizes - */ -#define BI2BY 8 /* bits per byte */ -#define BI2WD 32 /* bits per word */ -#define BY2WD 4 /* bytes per word */ -#define BY2V 8 /* bytes per double word */ -#define BY2PG 4096 /* bytes per page */ -#define WD2PG (BY2PG/BY2WD) /* words per page */ -#define PGSHIFT 12 /* log(BY2PG) */ -#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1)) -#define PGROUND(s) ROUND(s, BY2PG) -#define BLOCKALIGN 8 - -#define MAXMACH 8 /* max # cpus system can run */ -#define KSTACK 8192 /* Size of kernel stack */ - -/* - * Time - */ -#define HZ (100) /* clock frequency */ -#define MS2HZ (1000/HZ) /* millisec per clock tick */ -#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */ -#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */ - -/* - * Fundamental addresses - */ -#define IDTADDR 0x80000800 /* idt */ -#define REBOOTADDR 0x00001000 /* reboot code - physical address */ -#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 CPU0GDT 0x80004000 /* bootstrap processor GDT */ -#define MACHADDR 0x80005000 /* as seen by current processor */ -#define CPU0MACH 0x80006000 /* Mach for bootstrap processor */ -#define MACHSIZE BY2PG -/* - * N.B. ramscan knows that CPU0MACH+BY2PG is the end of reserved data - * N.B. _start0x00100020 knows that CPU0PDB is the first reserved page - * and that there are 5 of them. - */ - -/* - * Address spaces - * - * User is at 0-2GB - * Kernel is at 2GB-4GB - */ -#define UZERO 0 /* base of user address space */ -#define UTZERO (UZERO+BY2PG) /* first address in user text */ -#define KZERO 0x80000000 /* base of kernel address space */ -#define KTZERO 0x80100000 /* first address in kernel text */ -#define USTKTOP (KZERO-BY2PG) /* byte just beyond user stack */ -#define USTKSIZE (16*1024*1024) /* size of user stack */ -#define TSTKTOP (USTKTOP-USTKSIZE) /* end of new stack in sysexec */ -#define TSTKSIZ 100 - -/* - * known x86 segments (in GDT) and their selectors - */ -#define NULLSEG 0 /* null segment */ -#define KDSEG 1 /* kernel data/stack */ -#define KESEG 2 /* kernel executable */ -#define UDSEG 3 /* user data/stack */ -#define UESEG 4 /* user executable */ -#define TSSSEG 5 /* task segment */ -#define APMCSEG 6 /* APM code segment */ -#define APMCSEG16 7 /* APM 16-bit code segment */ -#define APMDSEG 8 /* APM data segment */ -#define NGDT 10 /* number of GDT entries required */ -/* #define APM40SEG 8 /* APM segment 0x40 */ - -#define SELGDT (0<<2) /* selector is in gdt */ -#define SELLDT (1<<2) /* selector is in ldt */ - -#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p)) - -#define NULLSEL SELECTOR(NULLSEG, SELGDT, 0) -#define KDSEL SELECTOR(KDSEG, SELGDT, 0) -#define KESEL SELECTOR(KESEG, SELGDT, 0) -#define UESEL SELECTOR(UESEG, SELGDT, 3) -#define UDSEL SELECTOR(UDSEG, SELGDT, 3) -#define TSSSEL SELECTOR(TSSSEG, SELGDT, 0) -#define APMCSEL SELECTOR(APMCSEG, SELGDT, 0) -#define APMCSEL16 SELECTOR(APMCSEG16, SELGDT, 0) -#define APMDSEL SELECTOR(APMDSEG, SELGDT, 0) -/* #define APM40SEL SELECTOR(APM40SEG, SELGDT, 0) */ - -/* - * fields in segment descriptors - */ -#define SEGDATA (0x10<<8) /* data/stack segment */ -#define SEGEXEC (0x18<<8) /* executable segment */ -#define SEGTSS (0x9<<8) /* TSS segment */ -#define SEGCG (0x0C<<8) /* call gate */ -#define SEGIG (0x0E<<8) /* interrupt gate */ -#define SEGTG (0x0F<<8) /* trap gate */ -#define SEGTYPE (0x1F<<8) - -#define SEGP (1<<15) /* segment present */ -#define SEGPL(x) ((x)<<13) /* priority level */ -#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */ -#define SEGG (1<<23) /* granularity 1==4k (for other) */ -#define SEGE (1<<10) /* expand down */ -#define SEGW (1<<9) /* writable (for data/stack) */ -#define SEGR (1<<9) /* readable (for code) */ -#define SEGD (1<<22) /* default 1==32bit (for code) */ - -/* - * virtual MMU - */ -#define PTEMAPMEM (1024*1024) -#define PTEPERTAB (PTEMAPMEM/BY2PG) -#define SEGMAPSIZE 1984 -#define SSEGMAPSIZE 16 -#define PPN(x) ((x)&~(BY2PG-1)) - -/* - * physical MMU - */ -#define PTEVALID (1<<0) -#define PTEWT (1<<3) -#define PTEUNCACHED (1<<4) -#define PTEWRITE (1<<1) -#define PTERONLY (0<<1) -#define PTEKERNEL (0<<2) -#define PTEUSER (1<<2) -#define PTESIZE (1<<7) -#define PTEGLOBAL (1<<8) - -/* - * Macros for calculating offsets within the page directory base - * and page tables. - */ -#define PDX(va) ((((ulong)(va))>>22) & 0x03FF) -#define PTX(va) ((((ulong)(va))>>12) & 0x03FF) - -#define getpgcolor(a) 0 diff --git a/os/pc/memory.c b/os/pc/memory.c deleted file mode 100644 index 85658248..00000000 --- a/os/pc/memory.c +++ /dev/null @@ -1,588 +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 "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#define MEMDEBUG 0 - -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[16]; -static RMap rmapupa = { - "unallocated unbacked physical memory", - mapupa, - &mapupa[nelem(mapupa)-1], -}; - -static Map xmapupa[16]; -static RMap xrmapupa = { - "unbacked physical memory", - xmapupa, - &xmapupa[nelem(xmapupa)-1], -}; - -static Map mapram[16]; -static RMap rmapram = { - "physical memory", - mapram, - &mapram[nelem(mapram)-1], -}; - -static Map mapumb[64]; -static RMap rmapumb = { - "upper memory block", - mapumb, - &mapumb[nelem(mapumb)-1], -}; - -static Map mapumbrw[16]; -static RMap rmapumbrw = { - "UMB device memory", - mapumbrw, - &mapumbrw[nelem(mapumbrw)-1], -}; - -void -mapprint(RMap *rmap) -{ - Map *mp; - - print("%s\n", rmap->name); - for(mp = rmap->map; mp->size; mp++) - print("\t%8.8luX %8.8uX %8.8luX\n", mp->addr, mp->size, mp->addr+mp->size); -} - -void -memdebug(void) -{ - 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); - - mapprint(&rmapram); - mapprint(&rmapumb); - mapprint(&rmapumbrw); - mapprint(&rmapupa); -} - -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, %ld\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); - while(p < (uchar*)KADDR(0xE0000)){ - /* - * Test for 0x55 0xAA before poking obtrusively, - * some machines (e.g. Thinkpad X20) seem to map - * something dynamic here (cardbus?) causing weird - * problems if it is changed. - */ - if(p[0] == 0x55 && p[1] == 0xAA){ - 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); - } -} - - -static void -ramscan(ulong maxmem) -{ - ulong *k0, kzero, map, maxpa, pa, *pte, *table, *va, x, n; - int nvalid[NMemType]; - uchar *bda; - - /* - * The bootstrap code has has created a prototype page - * table which maps the first MemMinMB of physical memory to KZERO. - * The page directory is at m->pdb and the first page of - * free memory is after the per-processor MMU information. - */ - /* - * Initialise the memory bank information for conventional memory - * (i.e. less than 640KB). The base is the first location after the - * bootstrap processor MMU information and the limit is obtained from - * the BIOS data area. - */ - x = PADDR(CPU0MACH+BY2PG); - bda = (uchar*)KADDR(0x400); - n = ((bda[0x14]<<8)|bda[0x13])*KB-x; - mapfree(&rmapram, x, n); -// memset(KADDR(x), 0, n); /* keep us honest */ - - x = PADDR(PGROUND((ulong)end)); - pa = MemMinMB*MB; - mapfree(&rmapram, x, pa-x); -// memset(KADDR(x), 0, pa-x); /* keep us honest */ - - /* - * Check if the extended memory size can be obtained from the CMOS. - * If it's 0 then it's either not known or >= 64MB. Always check - * at least 24MB in case there's a memory gap (up to 8MB) below 16MB; - * in this case the memory from the gap is remapped to the top of - * memory. - * The value in CMOS is supposed to be the number of KB above 1MB. - */ - if(maxmem == 0){ - x = (nvramread(0x18)<<8)|nvramread(0x17); - if(x == 0 || x >= (63*KB)) - maxpa = MemMaxMB*MB; - else - maxpa = MB+x*KB; - if(maxpa < 24*MB) - maxpa = 24*MB; - maxmem = MemMaxMB*MB; - } - else - maxpa = maxmem; - - /* - * March up memory from MemMinMB to maxpa 1MB at a time, - * mapping the first page and checking the page can - * be written and read correctly. The page tables are created here - * on the fly, allocating from low memory as necessary. - */ - k0 = (ulong*)KADDR(0); - kzero = *k0; - map = 0; - x = 0x12345678; - memset(nvalid, 0, sizeof(nvalid)); - while(pa < maxpa){ - /* - * Map the page. Use mapalloc(&rmapram, ...) to make - * the page table if necessary, it will be returned to the - * pool later if it isn't needed. - */ - va = KADDR(pa); - table = &m->pdb[PDX(va)]; - if(*table == 0){ - if(map == 0 && (map = mapalloc(&rmapram, 0, BY2PG, BY2PG)) == 0) - break; - memset(KADDR(map), 0, BY2PG); - *table = map|PTEWRITE|PTEVALID; - memset(nvalid, 0, sizeof(nvalid)); - } - table = KADDR(PPN(*table)); - pte = &table[PTX(va)]; - - *pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID; - mmuflushtlb(PADDR(m->pdb)); - - /* - * Write a pattern to the page and write a different - * pattern to a possible mirror at KZER0. If the data - * reads back correctly the chunk is some type of RAM (possibly - * a linearly-mapped VGA framebuffer, for instance...) and - * can be cleared and added to the memory pool. If not, the - * chunk is marked uncached and added to the UMB pool if <16MB - * or is marked invalid and added to the UPA pool. - */ - *va = x; - *k0 = ~x; - if(*va == x){ - nvalid[MemRAM] += MB/BY2PG; - mapfree(&rmapram, pa, MB); - - do{ - *pte++ = pa|PTEWRITE|PTEVALID; - pa += BY2PG; - }while(pa % MB); - mmuflushtlb(PADDR(m->pdb)); - /* memset(va, 0, MB); so damn slow to memset all of memory */ - } - else if(pa < 16*MB){ - nvalid[MemUMB] += MB/BY2PG; - mapfree(&rmapumb, pa, MB); - - do{ - *pte++ = pa|PTEWRITE|PTEUNCACHED|PTEVALID; - pa += BY2PG; - }while(pa % MB); - } - else{ - nvalid[MemUPA] += MB/BY2PG; - mapfree(&rmapupa, pa, MB); - - *pte = 0; - pa += MB; - } - - /* - * Done with this 4MB chunk, review the options: - * 1) not physical memory and >=16MB - invalidate the PDB entry; - * 2) physical memory - use the 4MB page extension if possible; - * 3) not physical memory and <16MB - use the 4MB page extension - * if possible; - * 4) mixed or no 4MB page extension - commit the already - * initialised space for the page table. - */ - if((pa % (4*MB)) == 0){ - table = &m->pdb[PDX(va)]; - if(nvalid[MemUPA] == (4*MB)/BY2PG) - *table = 0; - else if(nvalid[MemRAM] == (4*MB)/BY2PG && (m->cpuiddx & 0x08)) - *table = (pa - 4*MB)|PTESIZE|PTEWRITE|PTEVALID; - else if(nvalid[MemUMB] == (4*MB)/BY2PG && (m->cpuiddx & 0x08)) - *table = (pa - 4*MB)|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID; - else - map = 0; - } - - mmuflushtlb(PADDR(m->pdb)); - x += 0x3141526; - } - - /* - * If we didn't reach the end of the 4MB chunk, that part won't - * be mapped. Commit the already initialised space for the page table. - */ - if(pa % (4*MB)) - map = 0; - - if(map) - mapfree(&rmapram, map, BY2PG); - if(pa < maxmem) - mapfree(&rmapupa, pa, maxmem-pa); - if(maxmem < 0xFFE00000) - mapfree(&rmapupa, maxmem, 0x00000000-maxmem); - if(MEMDEBUG) - print("maxmem %luX %luX\n", maxmem, 0x00000000-maxmem); - *k0 = kzero; -} - -void -meminit(ulong maxmem) -{ - Map *mp, *xmp; - ulong pa, *pte; - - /* - * Set special attributes for memory between 640KB and 1MB: - * VGA memory is writethrough; - * BIOS ROM's/UMB's are uncached; - * then scan for useful memory. - */ - for(pa = 0xA0000; pa < 0xC0000; pa += BY2PG){ - pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 2, 0); - *pte |= PTEWT; - } - for(pa = 0xC0000; pa < 0x100000; pa += BY2PG){ - pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 2, 0); - *pte |= PTEUNCACHED; - } - mmuflushtlb(PADDR(m->pdb)); - - umbscan(); - ramscan(maxmem); - - /* - * Set the conf entries describing two banks of allocatable memory. - * Grab the first and largest entries in rmapram as left by ramscan(). - * - * It would be nice to have more than 2 memory banks describable in conf. - */ - mp = rmapram.map; - conf.base0 = mp->addr; - conf.npage0 = mp->size/BY2PG; - mp++; - for(xmp = 0; mp->size; mp++){ - if(xmp == 0 || mp->size > xmp->size) - xmp = mp; - } - - if(xmp){ - conf.base1 = xmp->addr; - conf.npage1 = xmp->size/BY2PG; - } - 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 -upamalloc(ulong pa, int size, int align) -{ - ulong a, ae; - - if(a = mapalloc(&xrmapupa, pa, size, align)) - return a; - - if((a = mapalloc(&rmapupa, pa, size, align)) == 0){ - memdebug(); - return 0; - } - - /* - * Upamalloc is a request to map a range of physical addresses. - * Therefore, if pa is 0 mapalloc will choose the base address. - * Note, however, mmukmap is always asked to give a 1-to-1 mapping - * of va to pa. - */ - ae = mmukmap(a, a, 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 - * mapped 1-to-1 with the virtual address. - * If a < KZERO it's probably not a good idea to - * try KADDR(a)... - */ - return a; -} - -void -upafree(ulong pa, int size) -{ - mapfree(&xrmapupa, pa, size); -} - -void -upareserve(ulong pa, int size) -{ - ulong a; - - a = mapalloc(&rmapupa, pa, size, 0); - if(a != pa){ - /* - * This can happen when we're using the E820 - * map, which might have already reserved some - * of the regions claimed by the pci devices. - */ - // print("upareserve: cannot reserve pa=%#.8lux size=%d\n", pa, size); - if(a != 0) - mapfree(&rmapupa, a, size); - } -} diff --git a/os/pc/mkfile b/os/pc/mkfile deleted file mode 100644 index c7366fd2..00000000 --- a/os/pc/mkfile +++ /dev/null @@ -1,83 +0,0 @@ -<../../mkconfig - -#Configurable parameters - -CONF=pc #default configuration -CONFLIST=pc pcdisk -CLEANCONFLIST=pc pcdisk zpc zpcrem pix pcsoe - -SYSTARG=$OSTARG -OBJTYPE=386 -INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin #path of directory where kernel is installed -#INSTALLDIR=/$OBJTYPE - -#end configurable parameters - -<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE #set vars based on target system - -<| $SHELLNAME ../port/mkdevlist $CONF #sets $IP, $DEVS, $ETHERS, $VGAS, $PORT, $MISC, $LIBS, $OTHERS - -OBJ=\ - l.$O\ - fpsave.$O\ - portclock.$O\ - tod.$O\ - i8250.$O\ - i8253.$O\ - i8259.$O\ - kbd.$O\ - main.$O\ - memory.$O\ - mmu.$O\ - trap.$O\ - $CONF.root.$O\ - $IP\ - $DEVS\ - $ETHERS\ - $LINKS\ - $PORT\ - $MISC\ - $OTHERS\ - -LIBNAMES=${LIBS:%=lib%.a} - -HFILES=\ - mem.h\ - dat.h\ - fns.h\ - io.h\ - -CFLAGS=-wFVT -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include -I$ROOT/libinterp -I../port -KERNDATE=`{$NDATE} - -default:V: i$CONF - -i$CONF: $OBJ $CONF.c $CONF.root.h $LIBNAMES - $CC $CFLAGS '-DKERNDATE='$KERNDATE $CONF.c - $LD -o $target -T0x80100020 -l $OBJ $CONF.$O $LIBFILES - $KSIZE $target - -install:V: i$CONF - cp i$CONF $INSTALLDIR/i$CONF - -<../port/portmkfile - -clock.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h -devether.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h -fault386.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h -main.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h -trap.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h - -devether.$O $ETHERS: etherif.h ../port/netif.h -$IP devip.$O: ../ip/ip.h - -# to be moved to port/interp -bench.h:D: ../../module/bench.m - rm -f $target && limbo -a -I../../module ../../module/bench.m > $target -benchmod.h:D: ../../module/bench.m - rm -f $target && limbo -t Bench -I../../module ../../module/bench.m > $target -devbench.$O: bench.h benchmod.h -$VGA screen.$O: screen.h vga.h - -devuart.$O: ../port/devuart.c ../port/uart.h - $CC $CFLAGS ../port/devuart.c diff --git a/os/pc/mmu.c b/os/pc/mmu.c deleted file mode 100644 index da86517d..00000000 --- a/os/pc/mmu.c +++ /dev/null @@ -1,343 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#define DATASEGM(p) { 0xFFFF, SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } -#define EXECSEGM(p) { 0xFFFF, SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } -#define TSSSEGM(b,p) { ((b)<<16)|sizeof(Tss),\ - ((b)&0xFF000000)|(((b)>>16)&0xFF)|SEGTSS|SEGPL(p)|SEGP } - -Segdesc gdt[NGDT] = -{ -[NULLSEG] { 0, 0}, /* null descriptor */ -[KDSEG] DATASEGM(0), /* kernel data/stack */ -[KESEG] EXECSEGM(0), /* kernel code */ -[UDSEG] DATASEGM(3), /* user data/stack */ -[UESEG] EXECSEGM(3), /* user code */ -[TSSSEG] TSSSEGM(0,0), /* tss segment */ -}; - -static void -taskswitch(ulong pdb, ulong stack) -{ - Tss *tss; - - tss = m->tss; - tss->ss0 = KDSEL; - tss->esp0 = stack; - tss->ss1 = KDSEL; - tss->esp1 = stack; - tss->ss2 = KDSEL; - tss->esp2 = stack; - tss->cr3 = pdb; - putcr3(pdb); -} - -/* - * On processors that support it, we set the PTEGLOBAL bit in - * page table and page directory entries that map kernel memory. - * Doing this tells the processor not to bother flushing them - * from the TLB when doing the TLB flush associated with a - * context switch (write to CR3). Since kernel memory mappings - * are never removed, this is safe. (If we ever remove kernel memory - * mappings, we can do a full flush by turning off the PGE bit in CR4, - * writing to CR3, and then turning the PGE bit back on.) - * - * See also mmukmap below. - * - * Processor support for the PTEGLOBAL bit is enabled in devarch.c. - */ -static void -memglobal(void) -{ - int i, j; - ulong *pde, *pte; - - /* only need to do this once, on bootstrap processor */ - if(m->machno != 0) - return; - - if(!m->havepge) - return; - - pde = m->pdb; - for(i=512; i<1024; i++){ /* 512: start at entry for virtual 0x80000000 */ - if(pde[i] & PTEVALID){ - pde[i] |= PTEGLOBAL; - if(!(pde[i] & PTESIZE)){ - pte = KADDR(pde[i]&~(BY2PG-1)); - for(j=0; j<1024; j++) - if(pte[j] & PTEVALID) - pte[j] |= PTEGLOBAL; - } - } - } -} - -void -mmuinit(void) -{ - ulong x, *p; - ushort ptr[3]; - - memglobal(); - - m->tss = malloc(sizeof(Tss)); - memset(m->tss, 0, sizeof(Tss)); - m->tss->iomap = 0xDFFF<<16; - - /* - * We used to keep the GDT in the Mach structure, but it - * turns out that that slows down access to the rest of the - * page. Since the Mach structure is accessed quite often, - * it pays off anywhere from a factor of 1.25 to 2 on real - * hardware to separate them (the AMDs are more sensitive - * than Intels in this regard). Under VMware it pays off - * a factor of about 10 to 100. - */ - - memmove(m->gdt, gdt, sizeof gdt); - x = (ulong)m->tss; - m->gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss); - m->gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP; - - ptr[0] = sizeof(gdt)-1; - x = (ulong)m->gdt; - ptr[1] = x & 0xFFFF; - ptr[2] = (x>>16) & 0xFFFF; - lgdt(ptr); - - ptr[0] = sizeof(Segdesc)*256-1; - x = IDTADDR; - ptr[1] = x & 0xFFFF; - ptr[2] = (x>>16) & 0xFFFF; - lidt(ptr); - - /* make kernel text unwritable */ - for(x = KTZERO; x < (ulong)etext; x += BY2PG){ - p = mmuwalk(m->pdb, x, 2, 0); - if(p == nil) - panic("mmuinit"); - *p &= ~PTEWRITE; - } - - taskswitch(PADDR(m->pdb), (ulong)m + BY2PG); - ltr(TSSSEL); -} - - - - -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 %luX entry %luX\n", va, *table); - if(!(*table & PTEVALID)){ - pa = PADDR(xspanalloc(BY2PG, BY2PG, 0)); - *table = pa|PTEWRITE|PTEVALID; - } - table = KADDR(PPN(*table)); - - return &table[PTX(va)]; - } -} - -static Lock mmukmaplock; - -int -mmukmapsync(ulong va) -{ - Mach *mach0; - ulong entry, *pte; - - mach0 = MACHP(0); - - ilock(&mmukmaplock); - - if((pte = mmuwalk(mach0->pdb, va, 1, 0)) == nil){ - iunlock(&mmukmaplock); - return 0; - } - if(!(*pte & PTESIZE) && mmuwalk(mach0->pdb, va, 2, 0) == nil){ - iunlock(&mmukmaplock); - return 0; - } - entry = *pte; - - if(!(m->pdb[PDX(va)] & PTEVALID)) - m->pdb[PDX(va)] = entry; - -// if(up && up->mmupdb){ -// ((ulong*)up->mmupdb->va)[PDX(va)] = entry; -// mmuflushtlb(up->mmupdb->pa); -// } -// else - mmuflushtlb(PADDR(m->pdb)); - - iunlock(&mmukmaplock); - - return 1; -} - -ulong -mmukmap(ulong pa, ulong va, int size) -{ - Mach *mach0; - ulong ova, pae, *table, pgsz, *pte, x; - int pse, sync; - - mach0 = MACHP(0); - if((mach0->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); - ova = va; - - pae = pa + size; - ilock(&mmukmaplock); - while(pa < pae){ - table = &mach0->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 %luX entry %luX\n", - pa, *table); - x += 4*MB; - if(pae <= x){ - pa = pae; - break; - } - pgsz = x - pa; - pa += pgsz; - va += pgsz; - - continue; - } - else{ - /* - * Little page. Walk to the entry. - * If the entry is valid, set pgsz and continue. - * If not, make it so, set pgsz, sync and continue. - */ - pte = mmuwalk(mach0->pdb, va, 2, 0); - if(pte && *pte & PTEVALID){ - x = PPN(*pte); - if(x != pa) - panic("mmukmap2: pa %luX entry %luX\n", - pa, *pte); - pgsz = BY2PG; - pa += pgsz; - va += pgsz; - sync++; - - continue; - } - } - } - - /* - * Not mapped. Check if it can be mapped using a big page - - * starts on a 4MB boundary, size >= 4MB and processor can do it. - * If not a big page, walk the walk, talk the talk. - * Sync is set. - * - * If we're creating a kernel mapping, we know that it will never - * expire and thus we can set the PTEGLOBAL bit to make the entry - * persist in the TLB across flushes. If we do add support later for - * unmapping kernel addresses, see devarch.c for instructions on - * how to do a full TLB flush. - */ - if(pse && (pa % (4*MB)) == 0 && (pae >= pa+4*MB)){ - *table = pa|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID; - if((va&KZERO) && m->havepge) - *table |= PTEGLOBAL; - pgsz = 4*MB; - } - else{ - pte = mmuwalk(mach0->pdb, va, 2, 1); - *pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID; - if((va&KZERO) && m->havepge) - *pte |= PTEGLOBAL; - pgsz = BY2PG; - } - pa += pgsz; - va += pgsz; - sync++; - } - iunlock(&mmukmaplock); - - /* - * If something was added - * then need to sync up. - */ - if(sync) - mmukmapsync(ova); - - return pa; -} - -void* -vmap(ulong pa, int size) -{ - pa = upamalloc(pa, size, 0); - if(pa == 0) - return nil; - return KADDR(pa); -} - -void -vunmap(void *va, int size) -{ - if(va != nil) - upafree(PADDR(va), size); -} - -int -segflush(void*, ulong) -{ - return 0; -} diff --git a/os/pc/mouse.c b/os/pc/mouse.c deleted file mode 100644 index 49654bad..00000000 --- a/os/pc/mouse.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "io.h" - -/* - * mouse types - */ -enum -{ - Mouseother= 0, - Mouseserial= 1, - MousePS2= 2, -}; - -static int mousetype; - -/* - * ps/2 mouse message is three bytes - * - * byte 0 - 0 0 SDY SDX 1 M R L - * byte 1 - DX - * byte 2 - DY - * - * shift & left button is the same as middle button - */ -static void -ps2mouseputc(int c, int shift) -{ - static short msg[3]; - static int nb; - static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 5, 2, 3, 6, 7 }; - int buttons, dx, dy; - - /* - * check byte 0 for consistency - */ - if(nb==0 && (c&0xc8)!=0x08) - return; - - msg[nb] = c; - if(++nb == 3){ - nb = 0; - if(msg[0] & 0x10) - msg[1] |= 0xFF00; - if(msg[0] & 0x20) - msg[2] |= 0xFF00; - - buttons = b[(msg[0]&7) | (shift ? 8 : 0)]; - dx = msg[1]; - dy = -msg[2]; - mousetrack(buttons, dx, dy, 1); - } - return; -} - -/* - * set up a ps2 mouse - */ -static void -ps2mouse(void) -{ - if(mousetype == MousePS2) - return; - - i8042auxenable(ps2mouseputc); - /* make mouse streaming, enabled */ - i8042auxcmd(0xEA); - i8042auxcmd(0xF4); - - mousetype = MousePS2; -} - -void -ps2mouselink(void) -{ - /* - * hack - */ - ps2mouse(); -} diff --git a/os/pc/mp.c b/os/pc/mp.c deleted file mode 100644 index f16fab91..00000000 --- a/os/pc/mp.c +++ /dev/null @@ -1,815 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" - -#include "mp.h" -#include "apbootstrap.h" - -static Bus* mpbus; -static Bus* mpbuslast; -static int mpisabus = -1; -static int mpeisabus = -1; -extern int i8259elcr; /* mask of level-triggered interrupts */ -static Apic mpapic[MaxAPICNO+1]; -static int machno2apicno[MaxAPICNO+1]; /* inverse map: machno -> APIC ID */ -static Lock mprdthilock; -static int mprdthi; -static Ref mpvnoref; /* unique vector assignment */ -static int mpmachno = 1; - -static char* buses[] = { - "CBUSI ", - "CBUSII", - "EISA ", - "FUTURE", - "INTERN", - "ISA ", - "MBI ", - "MBII ", - "MCA ", - "MPI ", - "MPSA ", - "NUBUS ", - "PCI ", - "PCMCIA", - "TC ", - "VL ", - "VME ", - "XPRESS", - 0, -}; - -static Apic* -mkprocessor(PCMPprocessor* p) -{ - Apic *apic; - - if(!(p->flags & PcmpEN) || p->apicno > MaxAPICNO) - return 0; - - apic = &mpapic[p->apicno]; - apic->type = PcmpPROCESSOR; - apic->apicno = p->apicno; - apic->flags = p->flags; - apic->lintr[0] = ApicIMASK; - apic->lintr[1] = ApicIMASK; - - if(p->flags & PcmpBP){ - machno2apicno[0] = p->apicno; - apic->machno = 0; - } - else{ - machno2apicno[mpmachno] = p->apicno; - apic->machno = mpmachno; - mpmachno++; - } - - return apic; -} - -static Bus* -mkbus(PCMPbus* p) -{ - Bus *bus; - int i; - - for(i = 0; buses[i]; i++){ - if(strncmp(buses[i], p->string, sizeof(p->string)) == 0) - break; - } - if(buses[i] == 0) - return 0; - - bus = xalloc(sizeof(Bus)); - if(mpbus) - mpbuslast->next = bus; - else - mpbus = bus; - mpbuslast = bus; - - bus->type = i; - bus->busno = p->busno; - if(bus->type == BusEISA){ - bus->po = PcmpLOW; - bus->el = PcmpLEVEL; - if(mpeisabus != -1) - print("mkbus: more than one EISA bus\n"); - mpeisabus = bus->busno; - } - else if(bus->type == BusPCI){ - bus->po = PcmpLOW; - bus->el = PcmpLEVEL; - } - else if(bus->type == BusISA){ - bus->po = PcmpHIGH; - bus->el = PcmpEDGE; - if(mpisabus != -1) - print("mkbus: more than one ISA bus\n"); - mpisabus = bus->busno; - } - else{ - bus->po = PcmpHIGH; - bus->el = PcmpEDGE; - } - - return bus; -} - -static Bus* -mpgetbus(int busno) -{ - Bus *bus; - - for(bus = mpbus; bus; bus = bus->next){ - if(bus->busno == busno) - return bus; - } - print("mpgetbus: can't find bus %d\n", busno); - - return 0; -} - -static Apic* -mkioapic(PCMPioapic* p) -{ - Apic *apic; - - if(!(p->flags & PcmpEN) || p->apicno > MaxAPICNO) - return 0; - - /* - * Map the I/O APIC. - */ - if(mmukmap(p->addr, 0, 1024) == 0) - return 0; - - apic = &mpapic[p->apicno]; - apic->type = PcmpIOAPIC; - apic->apicno = p->apicno; - apic->addr = KADDR(p->addr); - apic->flags = p->flags; - - return apic; -} - -static Aintr* -mkiointr(PCMPintr* p) -{ - Bus *bus; - Aintr *aintr; - - /* - * According to the MultiProcessor Specification, a destination - * I/O APIC of 0xFF means the signal is routed to all I/O APICs. - * It's unclear how that can possibly be correct so treat it as - * an error for now. - */ - if(p->apicno == 0xFF) - return 0; - if((bus = mpgetbus(p->busno)) == 0) - return 0; - - aintr = xalloc(sizeof(Aintr)); - aintr->intr = p; - aintr->apic = &mpapic[p->apicno]; - aintr->next = bus->aintr; - bus->aintr = aintr; - - return aintr; -} - -static int -mpintrinit(Bus* bus, PCMPintr* intr, int vno, int /*irq*/) -{ - int el, po, v; - - /* - * Parse an I/O or Local APIC interrupt table entry and - * return the encoded vector. - */ - v = vno; - - po = intr->flags & PcmpPOMASK; - el = intr->flags & PcmpELMASK; - - switch(intr->intr){ - - default: /* PcmpINT */ - v |= ApicLOWEST; - break; - - case PcmpNMI: - v |= ApicNMI; - po = PcmpHIGH; - el = PcmpEDGE; - break; - - case PcmpSMI: - v |= ApicSMI; - break; - - case PcmpExtINT: - v |= ApicExtINT; - /* - * The AMI Goliath doesn't boot successfully with it's LINTR0 - * entry which decodes to low+level. The PPro manual says ExtINT - * should be level, whereas the Pentium is edge. Setting the - * Goliath to edge+high seems to cure the problem. Other PPro - * MP tables (e.g. ASUS P/I-P65UP5 have a entry which decodes - * to edge+high, so who knows. - * Perhaps it would be best just to not set an ExtINT entry at - * all, it shouldn't be needed for SMP mode. - */ - po = PcmpHIGH; - el = PcmpEDGE; - break; - } - - /* - */ - if(bus->type == BusEISA && !po && !el /*&& !(i8259elcr & (1<po; - if(po == PcmpLOW) - v |= ApicLOW; - else if(po != PcmpHIGH){ - print("mpintrinit: bad polarity 0x%uX\n", po); - return ApicIMASK; - } - - if(!el) - el = bus->el; - if(el == PcmpLEVEL) - v |= ApicLEVEL; - else if(el != PcmpEDGE){ - print("mpintrinit: bad trigger 0x%uX\n", el); - return ApicIMASK; - } - - return v; -} - -static int -mklintr(PCMPintr* p) -{ - Apic *apic; - Bus *bus; - int intin, v; - - /* - * The offsets of vectors for LINT[01] are known to be - * 0 and 1 from the local APIC vector space at VectorLAPIC. - */ - if((bus = mpgetbus(p->busno)) == 0) - return 0; - intin = p->intin; - - /* - * Pentium Pros have problems if LINT[01] are set to ExtINT - * so just bag it, SMP mode shouldn't need ExtINT anyway. - */ - if(p->intr == PcmpExtINT || p->intr == PcmpNMI) - v = ApicIMASK; - else - v = mpintrinit(bus, p, VectorLAPIC+intin, p->irq); - - if(p->apicno == 0xFF){ - for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ - if((apic->flags & PcmpEN) - && apic->type == PcmpPROCESSOR) - apic->lintr[intin] = v; - } - } - else{ - apic = &mpapic[p->apicno]; - if((apic->flags & PcmpEN) && apic->type == PcmpPROCESSOR) - apic->lintr[intin] = v; - } - - return v; -} - -static void -checkmtrr(void) -{ - int i, vcnt; - Mach *mach0; - - /* - * If there are MTRR registers, snarf them for validation. - */ - if(!(m->cpuiddx & 0x1000)) - return; - - rdmsr(0x0FE, &m->mtrrcap); - rdmsr(0x2FF, &m->mtrrdef); - if(m->mtrrcap & 0x0100){ - rdmsr(0x250, &m->mtrrfix[0]); - rdmsr(0x258, &m->mtrrfix[1]); - rdmsr(0x259, &m->mtrrfix[2]); - for(i = 0; i < 8; i++) - rdmsr(0x268+i, &m->mtrrfix[(i+3)]); - } - vcnt = m->mtrrcap & 0x00FF; - if(vcnt > nelem(m->mtrrvar)) - vcnt = nelem(m->mtrrvar); - for(i = 0; i < vcnt; i++) - rdmsr(0x200+i, &m->mtrrvar[i]); - - /* - * If not the bootstrap processor, compare. - */ - if(m->machno == 0) - return; - - mach0 = MACHP(0); - if(mach0->mtrrcap != m->mtrrcap) - print("mtrrcap%d: %lluX %lluX\n", - m->machno, mach0->mtrrcap, m->mtrrcap); - if(mach0->mtrrdef != m->mtrrdef) - print("mtrrdef%d: %lluX %lluX\n", - m->machno, mach0->mtrrdef, m->mtrrdef); - for(i = 0; i < 11; i++){ - if(mach0->mtrrfix[i] != m->mtrrfix[i]) - print("mtrrfix%d: i%d: %lluX %lluX\n", - m->machno, i, mach0->mtrrfix[i], m->mtrrfix[i]); - } - for(i = 0; i < vcnt; i++){ - if(mach0->mtrrvar[i] != m->mtrrvar[i]) - print("mtrrvar%d: i%d: %lluX %lluX\n", - m->machno, i, mach0->mtrrvar[i], m->mtrrvar[i]); - } -} - -static void -squidboy(Apic* apic) -{ -// iprint("Hello Squidboy\n"); - - machinit(); - mmuinit(); - - cpuidentify(); - cpuidprint(); - checkmtrr(); - - lock(&mprdthilock); - mprdthi |= (1<apicno)<<24; - unlock(&mprdthilock); - - lapicinit(apic); - lapiconline(); - syncclock(); - timersinit(); - - fpoff(); - - lock(&active); - active.machs |= 1<machno; - unlock(&active); - - while(!active.thunderbirdsarego) - microdelay(100); - - schedinit(); -} - -static void -mpstartap(Apic* apic) -{ - ulong *apbootp, *pdb, *pte; - Mach *mach, *mach0; - int i, machno; - uchar *p; - - mach0 = MACHP(0); - - /* - * Initialise the AP page-tables and Mach structure. The page-tables - * are the same as for the bootstrap processor with the exception of - * the PTE for the Mach structure. - * Xspanalloc will panic if an allocation can't be made. - */ - p = xspanalloc(4*BY2PG, BY2PG, 0); - pdb = (ulong*)p; - memmove(pdb, mach0->pdb, BY2PG); - p += BY2PG; - - if((pte = mmuwalk(pdb, MACHADDR, 1, 0)) == nil) - return; - memmove(p, KADDR(PPN(*pte)), BY2PG); - *pte = PADDR(p)|PTEWRITE|PTEVALID; - if(mach0->havepge) - *pte |= PTEGLOBAL; - p += BY2PG; - - mach = (Mach*)p; - if((pte = mmuwalk(pdb, MACHADDR, 2, 0)) == nil) - return; - *pte = PADDR(mach)|PTEWRITE|PTEVALID; - if(mach0->havepge) - *pte |= PTEGLOBAL; - p += BY2PG; - - machno = apic->machno; - MACHP(machno) = mach; - mach->machno = machno; - mach->pdb = pdb; - mach->gdt = (Segdesc*)p; /* filled by mmuinit */ - - /* - * Tell the AP where its kernel vector and pdb are. - * The offsets are known in the AP bootstrap code. - */ - apbootp = (ulong*)(APBOOTSTRAP+0x08); - *apbootp++ = (ulong)squidboy; - *apbootp++ = PADDR(pdb); - *apbootp = (ulong)apic; - - /* - * Universal Startup Algorithm. - */ - p = KADDR(0x467); - *p++ = PADDR(APBOOTSTRAP); - *p++ = PADDR(APBOOTSTRAP)>>8; - i = (PADDR(APBOOTSTRAP) & ~0xFFFF)/16; - *p++ = i; - *p = i>>8; - - nvramwrite(0x0F, 0x0A); - lapicstartap(apic, PADDR(APBOOTSTRAP)); - for(i = 0; i < 1000; i++){ - lock(&mprdthilock); - if(mprdthi & ((1<apicno)<<24)){ - unlock(&mprdthilock); - break; - } - unlock(&mprdthilock); - delay(10); - } - nvramwrite(0x0F, 0x00); -} - -void -mpinit(void) -{ - int ncpu; - char *cp; - PCMP *pcmp; - uchar *e, *p; - Apic *apic, *bpapic; - - i8259init(); - syncclock(); - - if(_mp_ == 0) - return; - pcmp = KADDR(_mp_->physaddr); - - /* - * Map the local APIC. - */ - if(mmukmap(pcmp->lapicbase, 0, 1024) == 0) - return; - - bpapic = nil; - - /* - * Run through the table saving information needed for starting - * application processors and initialising any I/O APICs. The table - * is guaranteed to be in order such that only one pass is necessary. - */ - p = ((uchar*)pcmp)+sizeof(PCMP); - e = ((uchar*)pcmp)+pcmp->length; - while(p < e) switch(*p){ - - default: - print("mpinit: unknown PCMP type 0x%uX (e-p 0x%luX)\n", - *p, e-p); - while(p < e){ - print("%uX ", *p); - p++; - } - break; - - case PcmpPROCESSOR: - if(apic = mkprocessor((PCMPprocessor*)p)){ - /* - * Must take a note of bootstrap processor APIC - * now as it will be needed in order to start the - * application processors later and there's no - * guarantee that the bootstrap processor appears - * first in the table before the others. - */ - apic->addr = KADDR(pcmp->lapicbase); - if(apic->flags & PcmpBP) - bpapic = apic; - } - p += sizeof(PCMPprocessor); - continue; - - case PcmpBUS: - mkbus((PCMPbus*)p); - p += sizeof(PCMPbus); - continue; - - case PcmpIOAPIC: - if(apic = mkioapic((PCMPioapic*)p)) - ioapicinit(apic, ((PCMPioapic*)p)->apicno); - p += sizeof(PCMPioapic); - continue; - - case PcmpIOINTR: - mkiointr((PCMPintr*)p); - p += sizeof(PCMPintr); - continue; - - case PcmpLINTR: - mklintr((PCMPintr*)p); - p += sizeof(PCMPintr); - continue; - } - - /* - * No bootstrap processor, no need to go further. - */ - if(bpapic == 0) - return; - - lapicinit(bpapic); - lock(&mprdthilock); - mprdthi |= (1<apicno)<<24; - unlock(&mprdthilock); - - /* - * These interrupts are local to the processor - * and do not appear in the I/O APIC so it is OK - * to set them now. - */ - intrenable(IrqTIMER, lapicclock, 0, BUSUNKNOWN, "clock"); - intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror"); - intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious"); - lapiconline(); - - checkmtrr(); - - /* - * Initialise the application processors. - */ - if(cp = getconf("*ncpu")){ - ncpu = strtol(cp, 0, 0); - if(ncpu < 1) - ncpu = 1; - } - else - ncpu = MaxAPICNO; - memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap)); - for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ - if(ncpu <= 1) - break; - if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN - && apic->type == PcmpPROCESSOR){ - mpstartap(apic); - conf.nmach++; - ncpu--; - } - } - - /* - * we don't really know the number of processors till - * here. - * - * set conf.copymode here if nmach > 1. - * Should look for an ExtINT line and enable it. - */ - if(X86FAMILY(m->cpuidax) == 3 || conf.nmach > 1) - conf.copymode = 1; -} - -static int -mpintrenablex(Vctl* v, int tbdf) -{ - Bus *bus; - Aintr *aintr; - Apic *apic; - Pcidev *pcidev; - int bno, dno, irq, lo, n, type, vno; - - /* - * Find the bus. - */ - type = BUSTYPE(tbdf); - bno = BUSBNO(tbdf); - dno = BUSDNO(tbdf); - n = 0; - for(bus = mpbus; bus != nil; bus = bus->next){ - if(bus->type != type) - continue; - if(n == bno) - break; - n++; - } - if(bus == nil){ - print("ioapicirq: can't find bus type %d\n", type); - return -1; - } - - /* - * For PCI devices the interrupt pin (INT[ABCD]) and device - * number are encoded into the entry irq field, so create something - * to match on. The interrupt pin used by the device has to be - * obtained from the PCI config space. - */ - if(bus->type == BusPCI){ - pcidev = pcimatchtbdf(tbdf); - if(pcidev != nil && (n = pcicfgr8(pcidev, PciINTP)) != 0) - irq = (dno<<2)|(n-1); - else - irq = -1; - //print("pcidev %uX: irq %uX v->irq %uX\n", tbdf, irq, v->irq); - } - else - irq = v->irq; - - /* - * Find a matching interrupt entry from the list of interrupts - * attached to this bus. - */ - for(aintr = bus->aintr; aintr; aintr = aintr->next){ - if(aintr->intr->irq != irq) - continue; - - /* - * Check if already enabled. Multifunction devices may share - * INT[A-D]# so, if already enabled, check the polarity matches - * and the trigger is level. - * - * Should check the devices differ only in the function number, - * but that can wait for the planned enable/disable rewrite. - * The RDT read here is safe for now as currently interrupts - * are never disabled once enabled. - */ - apic = aintr->apic; - ioapicrdtr(apic, aintr->intr->intin, 0, &lo); - if(!(lo & ApicIMASK)){ - vno = lo & 0xFF; - n = mpintrinit(bus, aintr->intr, vno, v->irq); - n |= ApicLOGICAL; - if(n != lo || !(n & ApicLEVEL)){ - print("mpintrenable: multiple botch irq%d, tbdf %uX, lo %8.8uX, n %8.8uX\n", - v->irq, tbdf, lo, n); - return -1; - } - - v->isr = lapicisr; - v->eoi = lapiceoi; - - return vno; - } - - /* - * With the APIC a unique vector can be assigned to each - * request to enable an interrupt. There are two reasons this - * is a good idea: - * 1) to prevent lost interrupts, no more than 2 interrupts - * should be assigned per block of 16 vectors (there is an - * in-service entry and a holding entry for each priority - * level and there is one priority level per block of 16 - * interrupts). - * 2) each input pin on the IOAPIC will receive a different - * vector regardless of whether the devices on that pin use - * the same IRQ as devices on another pin. - */ - vno = VectorAPIC + (incref(&mpvnoref)-1)*8; - if(vno > MaxVectorAPIC){ - print("mpintrenable: vno %d, irq %d, tbdf %uX\n", - vno, v->irq, tbdf); - return -1; - } - lo = mpintrinit(bus, aintr->intr, vno, v->irq); - //print("lo 0x%uX: busno %d intr %d vno %d irq %d elcr 0x%uX\n", - // lo, bus->busno, aintr->intr->irq, vno, - // v->irq, i8259elcr); - if(lo & ApicIMASK) - return -1; - lo |= ApicLOGICAL; - - if((apic->flags & PcmpEN) && apic->type == PcmpIOAPIC){ - lock(&mprdthilock); - ioapicrdtw(apic, aintr->intr->intin, mprdthi, lo); - unlock(&mprdthilock); - } - //else - // print("lo not enabled 0x%uX %d\n", - // apic->flags, apic->type); - - v->isr = lapicisr; - v->eoi = lapiceoi; - - return vno; - } - - return -1; -} - -int -mpintrenable(Vctl* v) -{ - int irq, tbdf, vno; - - /* - * If the bus is known, try it. - * BUSUNKNOWN is given both by [E]ISA devices and by - * interrupts local to the processor (local APIC, coprocessor - * breakpoint and page-fault). - */ - tbdf = v->tbdf; - if(tbdf != BUSUNKNOWN && (vno = mpintrenablex(v, tbdf)) != -1) - return vno; - - irq = v->irq; - if(irq >= IrqLINT0 && irq <= MaxIrqLAPIC){ - if(irq != IrqSPURIOUS) - v->isr = lapiceoi; - return VectorPIC+irq; - } - if(irq < 0 || irq > MaxIrqPIC){ - print("mpintrenable: irq %d out of range\n", irq); - return -1; - } - - /* - * Either didn't find it or have to try the default buses - * (ISA and EISA). This hack is due to either over-zealousness - * or laziness on the part of some manufacturers. - * - * The MP configuration table on some older systems - * (e.g. ASUS PCI/E-P54NP4) has an entry for the EISA bus - * but none for ISA. It also has the interrupt type and - * polarity set to 'default for this bus' which wouldn't - * be compatible with ISA. - */ - if(mpeisabus != -1){ - vno = mpintrenablex(v, MKBUS(BusEISA, 0, 0, 0)); - if(vno != -1) - return vno; - } - if(mpisabus != -1){ - vno = mpintrenablex(v, MKBUS(BusISA, 0, 0, 0)); - if(vno != -1) - return vno; - } - - return -1; -} - -static Lock mpshutdownlock; - -void -mpshutdown(void) -{ - /* - * To be done... - */ - if(!canlock(&mpshutdownlock)){ - /* - * If this processor received the CTRL-ALT-DEL from - * the keyboard, acknowledge it. Send an INIT to self. - */ -#ifdef FIXTHIS - if(lapicisr(VectorKBD)) - lapiceoi(VectorKBD); -#endif /* FIX THIS */ - idle(); - } - - print("apshutdown: active = 0x%2.2uX\n", active.machs); - delay(1000); - splhi(); - - /* - * INIT all excluding self. - */ - lapicicrw(0, 0x000C0000|ApicINIT); - -#ifdef notdef - /* - * 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. - */ - *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */ - outb(0xCF9, 0x02); - outb(0xCF9, 0x06); -#else - pcireset(); - i8042reset(); -#endif /* notdef */ -} diff --git a/os/pc/mp.h b/os/pc/mp.h deleted file mode 100644 index 9195c9e9..00000000 --- a/os/pc/mp.h +++ /dev/null @@ -1,225 +0,0 @@ -/* - * MultiProcessor Specification Version 1.[14]. - */ -typedef struct { /* floating pointer */ - uchar signature[4]; /* "_MP_" */ - long physaddr; /* physical address of MP configuration table */ - uchar length; /* 1 */ - uchar specrev; /* [14] */ - uchar checksum; /* all bytes must add up to 0 */ - uchar type; /* MP system configuration type */ - uchar imcrp; - uchar reserved[3]; -} _MP_; - -typedef struct { /* configuration table header */ - uchar signature[4]; /* "PCMP" */ - ushort length; /* total table length */ - uchar version; /* [14] */ - uchar checksum; /* all bytes must add up to 0 */ - uchar product[20]; /* product id */ - ulong oemtable; /* OEM table pointer */ - ushort oemlength; /* OEM table length */ - ushort entry; /* entry count */ - ulong lapicbase; /* address of local APIC */ - ushort xlength; /* extended table length */ - uchar xchecksum; /* extended table checksum */ - uchar reserved; -} PCMP; - -typedef struct { /* processor table entry */ - uchar type; /* entry type (0) */ - uchar apicno; /* local APIC id */ - uchar version; /* local APIC verison */ - uchar flags; /* CPU flags */ - uchar signature[4]; /* CPU signature */ - ulong feature; /* feature flags from CPUID instruction */ - uchar reserved[8]; -} PCMPprocessor; - -typedef struct { /* bus table entry */ - uchar type; /* entry type (1) */ - uchar busno; /* bus id */ - char string[6]; /* bus type string */ -} PCMPbus; - -typedef struct { /* I/O APIC table entry */ - uchar type; /* entry type (2) */ - uchar apicno; /* I/O APIC id */ - uchar version; /* I/O APIC version */ - uchar flags; /* I/O APIC flags */ - ulong addr; /* I/O APIC address */ -} PCMPioapic; - -typedef struct { /* interrupt table entry */ - uchar type; /* entry type ([34]) */ - uchar intr; /* interrupt type */ - ushort flags; /* interrupt flag */ - uchar busno; /* source bus id */ - uchar irq; /* source bus irq */ - uchar apicno; /* destination APIC id */ - uchar intin; /* destination APIC [L]INTIN# */ -} PCMPintr; - -typedef struct { /* system address space mapping entry */ - uchar type; /* entry type (128) */ - uchar length; /* of this entry (20) */ - uchar busno; /* bus id */ - uchar addrtype; - ulong addrbase[2]; - ulong addrlength[2]; -} PCMPsasm; - -typedef struct { /* bus hierarchy descriptor entry */ - uchar type; /* entry type (129) */ - uchar length; /* of this entry (8) */ - uchar busno; /* bus id */ - uchar info; /* bus info */ - uchar parent; /* parent bus */ - uchar reserved[3]; -} PCMPhierarchy; - -typedef struct { /* compatibility bus address space modifier entry */ - uchar type; /* entry type (130) */ - uchar length; /* of this entry (8) */ - uchar busno; /* bus id */ - uchar modifier; /* address modifier */ - ulong range; /* predefined range list */ -} PCMPcbasm; - -enum { /* table entry types */ - PcmpPROCESSOR = 0x00, /* one entry per processor */ - PcmpBUS = 0x01, /* one entry per bus */ - PcmpIOAPIC = 0x02, /* one entry per I/O APIC */ - PcmpIOINTR = 0x03, /* one entry per bus interrupt source */ - PcmpLINTR = 0x04, /* one entry per system interrupt source */ - - PcmpSASM = 0x80, - PcmpHIERARCHY = 0x81, - PcmpCBASM = 0x82, - - /* PCMPprocessor and PCMPioapic flags */ - PcmpEN = 0x01, /* enabled */ - PcmpBP = 0x02, /* bootstrap processor */ - - /* PCMPiointr and PCMPlintr flags */ - PcmpPOMASK = 0x03, /* polarity conforms to specifications of bus */ - PcmpHIGH = 0x01, /* active high */ - PcmpLOW = 0x03, /* active low */ - PcmpELMASK = 0x0C, /* trigger mode of APIC input signals */ - PcmpEDGE = 0x04, /* edge-triggered */ - PcmpLEVEL = 0x0C, /* level-triggered */ - - /* PCMPiointr and PCMPlintr interrupt type */ - PcmpINT = 0x00, /* vectored interrupt from APIC Rdt */ - PcmpNMI = 0x01, /* non-maskable interrupt */ - PcmpSMI = 0x02, /* system management interrupt */ - PcmpExtINT = 0x03, /* vectored interrupt from external PIC */ - - /* PCMPsasm addrtype */ - PcmpIOADDR = 0x00, /* I/O address */ - PcmpMADDR = 0x01, /* memory address */ - PcmpPADDR = 0x02, /* prefetch address */ - - /* PCMPhierarchy info */ - PcmpSD = 0x01, /* subtractive decode bus */ - - /* PCMPcbasm modifier */ - PcmpPR = 0x01, /* predefined range list */ -}; - -/* - * Condensed form of the MP Configuration Table. - * This is created during a single pass through the MP Configuration - * table. - */ -typedef struct Aintr Aintr; -typedef struct Bus Bus; -typedef struct Apic Apic; - -typedef struct Bus { - uchar type; - uchar busno; - uchar po; - uchar el; - - Aintr* aintr; /* interrupts tied to this bus */ - Bus* next; -} Bus; - -typedef struct Aintr { - PCMPintr* intr; - Apic* apic; - Aintr* next; -}; - -typedef struct Apic { - int type; - int apicno; - ulong* addr; /* register base address */ - int flags; /* PcmpBP|PcmpEN */ - - Lock; /* I/O APIC: register access */ - int mre; /* I/O APIC: maximum redirection entry */ - - int lintr[2]; /* Local APIC */ - int machno; -} Apic; - -enum { - MaxAPICNO = 31, -}; - -enum { /* I/O APIC registers */ - IoapicID = 0x00, /* ID */ - IoapicVER = 0x01, /* version */ - IoapicARB = 0x02, /* arbitration ID */ - IoapicRDT = 0x10, /* redirection table */ -}; - -/* - * Common bits for - * I/O APIC Redirection Table Entry; - * Local APIC Local Interrupt Vector Table; - * Local APIC Inter-Processor Interrupt; - * Local APIC Timer Vector Table. - */ -enum { - ApicFIXED = 0x00000000, /* [10:8] Delivery Mode */ - ApicLOWEST = 0x00000100, /* Lowest priority */ - ApicSMI = 0x00000200, /* System Management Interrupt */ - ApicRR = 0x00000300, /* Remote Read */ - ApicNMI = 0x00000400, - ApicINIT = 0x00000500, /* INIT/RESET */ - ApicSTARTUP = 0x00000600, /* Startup IPI */ - ApicExtINT = 0x00000700, - - ApicPHYSICAL = 0x00000000, /* [11] Destination Mode (RW) */ - ApicLOGICAL = 0x00000800, - - ApicDELIVS = 0x00001000, /* [12] Delivery Status (RO) */ - ApicHIGH = 0x00000000, /* [13] Interrupt Input Pin Polarity (RW) */ - ApicLOW = 0x00002000, - ApicRemoteIRR = 0x00004000, /* [14] Remote IRR (RO) */ - ApicEDGE = 0x00000000, /* [15] Trigger Mode (RW) */ - ApicLEVEL = 0x00008000, - ApicIMASK = 0x00010000, /* [16] Interrupt Mask */ -}; - -extern void ioapicrdtr(Apic*, int, int*, int*); -extern void ioapicrdtw(Apic*, int, int, int); -extern void ioapicinit(Apic*, int); -extern void lapiconline(void); -extern void lapicinit(Apic*); -extern void lapicstartap(Apic*, int); -extern void lapicerror(Ureg*, void*); -extern void lapicspurious(Ureg*, void*); -extern int lapicisr(int); -extern int lapiceoi(int); -extern void lapicicrw(int, int); - -extern void mpinit(void); -extern void mpshutdown(void); -extern int mpintrenable(Vctl*); - -extern _MP_ *_mp_; diff --git a/os/pc/pc b/os/pc/pc deleted file mode 100644 index 56d82a89..00000000 --- a/os/pc/pc +++ /dev/null @@ -1,139 +0,0 @@ -dev - root - cons - arch - env - mnt - pipe - prog - rtc - srv - dup - ssl - cap - - draw screen vga vgax cga - pointer - vga - - ip bootp ip ipv6 ipaux iproute arp netlog ptclbsum386 iprouter plan9 nullmedium pktmedium - ether netif netaux ethermedium - -# ata - audio dma - uart -# floppy dma - tinyfs -# mouse -# dbg x86break -ip - tcp - udp -# rudp -# igmp - ipifc - icmp - icmp6 - ipmux -lib - interp - keyring - draw - memlayer - memdraw - tk - sec - mp - math - kern - -link - ether2114x pci -# ether82557 pci - ether83815 pci - etherelnk3 pci - ps2mouse - ethermedium -# pppmedium ppp compress - -misc - vgas3 +cur vgasavage - vgamach64xx - cga - uarti8250 - -mod - sys - draw - tk - keyring - math - -init - wminit - -code - int kernel_pool_pcnt = 10; - int main_pool_pcnt = 40; - int heap_pool_pcnt = 20; - int image_pool_pcnt = 40; - int cflag=0; - int swcursor=0; - int consoleprint=0; - -port - alarm - alloc - allocb - chan - dev - dial - dis - discall - exception - exportfs - inferno - latin1 - nocache - nodynld - parse - pgrp - print - proc - qio - qlock - random - sysfile - taslock - xalloc - -root - /chan / - /dev / - /dis - /env / - /fd / - /n - /n/remote - /net / - /nvfs / - /prog / - /dis/lib - /dis/svc - /dis/wm - /osinit.dis - /dis/sh.dis - /dis/ls.dis - /dis/cat.dis - /dis/bind.dis - /dis/mount.dis - /dis/pwd.dis - /dis/echo.dis - /dis/cd.dis - /dis/lib/bufio.dis - /dis/lib/string.dis - /dis/lib/readdir.dis - /dis/lib/workdir.dis - /dis/lib/daytime.dis - /dis/lib/auth.dis - /dis/lib/ssl.dis diff --git a/os/pc/pc4e b/os/pc/pc4e deleted file mode 100644 index 3bb235e4..00000000 --- a/os/pc/pc4e +++ /dev/null @@ -1,148 +0,0 @@ -dev - root - cons - arch - pnp pci - env - mnt - pipe - prog - rtc - srv - dup - ssl - cap - draw - ip bootp ip ipv6 ipaux iproute arp netlog ptclbsum386 iprouter plan9 nullmedium pktmedium netaux - ether netif netaux ethermedium - -# ata -# audio - uart - floppy dma -# tinyfs -# mouse -# dbg x86break -ip - tcp - udp -# rudp -# igmp - ipifc - icmp - icmp6 - ipmux -lib - interp - keyring - draw - memlayer - memdraw - tk - sec - mp - math - kern - -link -# ether2114x pci -# ether82557 pci - ether83815 pci - etherelnk3 pci -# ps2mouse -# pppmedium ppp compress - ethermedium - -misc - cgamemscr -# vgaclgd542x -# vgas3 -# vgamach64ct - uarti8250 - -mod - sys - draw - tk - keyring - crypt - ipints - - math - -init - i4e - -code - int kernel_pool_pcnt = 10; - int main_pool_pcnt = 40; - int heap_pool_pcnt = 20; - int image_pool_pcnt = 40; - int cflag=0; - int swcursor=0; - int consoleprint=1; - -port - alarm - alloc - allocb - chan - dev - dial - dis - discall - exception - exportfs - inferno - latin1 - nocache - nodynld - parse - pgrp - print - proc - qio - qlock - random - sysfile - taslock - xalloc - -root - /chan / - /dev / - /dis / - /env / - /fd / - /n - /n/remote - /net / - /net.alt / - /nvfs / - /prog / - /dis/lib - /dis/svc - /dis/wm - /osinit.dis - /dis/sh.dis - /dis/ls.dis - /dis/cat.dis - /dis/bind.dis - /dis/mount.dis - /dis/pwd.dis - /dis/echo.dis - /dis/cd.dis - /dis/lib/arg.dis - /dis/lib/bufio.dis - /dis/lib/dhcpclient.dis - /dis/lib/filepat.dis - /dis/lib/ip.dis - /dis/lib/string.dis - /dis/lib/readdir.dis - /dis/lib/workdir.dis - /dis/lib/daytime.dis - /dis/lib/auth.dis - /dis/lib/ssl.dis - /keydb / - /keydb/mutual /usr/i4e/keyring/mutual - /keydb/spree /usr/i4e/keyring/spree diff --git a/os/pc/pcdisk b/os/pc/pcdisk deleted file mode 100644 index 743286b3..00000000 --- a/os/pc/pcdisk +++ /dev/null @@ -1,157 +0,0 @@ -dev - root - cons - arch - env - mnt - pipe - prog - rtc - srv - dup - ssl - cap - - ip bootp ip ipv6 ipaux iproute arp netlog ptclbsum386 iprouter plan9 nullmedium pktmedium - ether netif netaux ethermedium - - draw screen vga vgax cga - pointer - vga - - sd - ds - floppy dma - -# audio - uart - tinyfs - -# dbg x86break - -ip - tcp - udp -# rudp -# igmp - ipifc - icmp - icmp6 - ipmux -lib - interp - keyring - sec - mp - draw - memlayer - memdraw - tk - math - kern - -link - ether2114x pci -# ether82557 pci - ether83815 pci - etherelnk3 pci - ps2mouse - ethermedium -# pppmedium ppp compress - -misc - vgas3 +cur vgasavage - vgamach64xx - cga - - sdata pci sdscsi - sd53c8xx pci sdscsi - - uarti8250 - -mod - sys - draw - tk - keyring - crypt - ipints - - math - -init - wminit - -code - int kernel_pool_pcnt = 10; - int main_pool_pcnt = 40; - int heap_pool_pcnt = 20; - int image_pool_pcnt = 40; - int cflag=0; - int swcursor=0; - int consoleprint=0; - int novgascreen=1; - -port - alarm - alloc - allocb - chan - dev - dial - dis - discall - exception - exportfs - inferno - latin1 - nocache - nodynld - parse - pgrp - print - proc - qio - qlock - random - sysfile - taslock - xalloc - -root - /chan - /dev - /dis - /env - /fd / - /n - /n/remote - /net - /nvfs - /prog - /dis/lib - /dis/svc - /dis/wm - /osinit.dis - /dis/sh.dis - /dis/ls.dis - /dis/cat.dis - /dis/bind.dis - /dis/mount.dis - /dis/pwd.dis - /dis/echo.dis - /dis/cd.dis - /dis/lib/bufio.dis - /dis/lib/string.dis - /dis/lib/readdir.dis - /dis/lib/workdir.dis - /dis/lib/daytime.dis - /dis/lib/auth.dis - /dis/lib/ssl.dis - -# kfs - /dis/disk/kfs.dis - /dis/lib/arg.dis - /dis/lib/daytime.dis - /dis/lib/string.dis - /dis/lib/styx.dis diff --git a/os/pc/pci.acid b/os/pc/pci.acid deleted file mode 100644 index 46da501e..00000000 --- a/os/pc/pci.acid +++ /dev/null @@ -1,252 +0,0 @@ -// ACID PCI support - -pciclassdb = { - {0x0000, "Unclassified device", { - {0x0000,"Non-VGA unclassified device"}, - {0x0001,"VGA compatible unclassified device"}, - }}, - {0x0001, "Mass storage controller", { - {0x0000,"SCSI storage controller"}, - {0x0001,"IDE interface"}, - {0x0002,"Floppy disk controller"}, - {0x0003,"IPI bus controller"}, - {0x0004,"RAID bus controller"}, - {0x0080,"Unknown mass storage controller"}, - }}, - {0x0002, "Network controller", { - {0x0000,"Ethernet controller"}, - {0x0001,"Token ring network controller"}, - {0x0002,"FDDI network controller"}, - {0x0003,"ATM network controller"}, - {0x0080,"Network controller"}, - }}, - {0x0003, "Display controller", { - {0x0000,"VGA compatible controller"}, - {0x0001,"XGA compatible controller"}, - {0x0080,"Display controller"}, - }}, - {0x0004, "Multimedia controller", { - {0x0000,"Multimedia video controller"}, - {0x0001,"Multimedia audio controller"}, - {0x0080,"Multimedia controller"}, - }}, - {0x0005, "Memory controller", { - {0x0000,"RAM memory"}, - {0x0001,"FLASH memory"}, - {0x0080,"Memory"}, - }}, - {0x0006, "Bridge", { - {0x0000,"Host bridge"}, - {0x0001,"ISA bridge"}, - {0x0002,"EISA bridge"}, - {0x0003,"MicroChannel bridge"}, - {0x0004,"PCI bridge"}, - {0x0005,"PCMCIA bridge"}, - {0x0006,"NuBus bridge"}, - {0x0007,"CardBus bridge"}, - {0x0080,"Bridge"}, - }}, - {0x0007, "Communication controller", { - {0x0000,"Serial controller"}, - {0x0001,"Parallel controller"}, - {0x0080,"Communication controller"}, - }}, - {0x0008, "Generic system peripheral", { - {0x0000,"PIC"}, - {0x0001,"DMA controller"}, - {0x0002,"Timer"}, - {0x0003,"RTC"}, - {0x0080,"System peripheral"}, - }}, - {0x0009, "Input device controller", { - {0x0000,"Keyboard controller"}, - {0x0001,"Digitizer Pen"}, - {0x0002,"Mouse controller"}, - {0x0080,"Input device controller"}, - }}, - {0x000A, "Docking station", { - {0x0000,"Generic Docking Station"}, - {0x0080,"Docking Station"}, - }}, - {0x000B, "Processor", { - {0x0000,"386"}, - {0x0001,"486"}, - {0x0002,"Pentium"}, - {0x0010,"Alpha"}, - {0x0020,"Power PC"}, - {0x0040,"Co-processor"}, - }}, - {0x000C, "Serial bus controller", { - {0x0000,"FireWire (IEEE 1394)"}, - {0x0001,"ACCESS Bus"}, - {0x0002,"SSA"}, - {0x0003,"USB Controller"}, - {0x0004,"Fiber Channel"}, - }}, -}; - -// -// Include the vendor and device id database -// - -include( "pcidb.acid" ); - -defn test(thingy) -{ - return thingy; -} - -defn BUSFNO(tbdf) -{ - return (((tbdf\X)>>8)&0x07); -} - -defn BUSDNO(tbdf) -{ - return (((tbdf\X)>>11)&0x1F); -} - -defn BUSBNO(tbdf) -{ - return (((tbdf\X)>>16)&0xFF); -} - -defn lookup( key, dictionary ) -{ - local d, e; - - d = dictionary; - while(d != {}) do { - e = head d; - if e[0] == key then - return e; - d = tail d; - } - return {}; -} - -defn pciclass( ccru ) -{ - local c, sc; - local class, subclass; - c = ccru >> 8; - sc = ccru & 0xff; - - class = lookup( c, pciclassdb ); - subclass = lookup( sc, class[2] ); - - if (subclass != {}) then { - print(" ",subclass[1]); - return 1; - } - if (class != {}) then { - print(" ",class[1]); - return 1; - } - - print(" type=",ccru\x); - return 0; -} - -defn pcivendor( vid ) -{ - local v; - v = lookup( vid, pcivendordb ); - if (v != {}) then { - print(" ",v[1]); - } else { - print(" VendorID=",vid\x,":"); - } -} - -defn pcidev( vid, did ) -{ - local v; - local d; - v = lookup( vid, pcivendordb ); - if (v != {}) then { - d = lookup( did, v[2] ); - if (d != {}) then { - print(" ",d[1]); - return 1; - } - } - print(" DeviceID=",did\x); - return 0; -} - -// -// Dump PCI Info (short form) -// - -defn pciinfo( r ) -{ - local t; - local pcicount; - t = r; - pcicount = 0\d; - while t != 0 do { - print(pcicount\d,":","Bus:",BUSBNO(t.tbdf)\u," dev:",BUSDNO(t.tbdf)\u," fn:",BUSFNO(t.tbdf)\u,":"); - pciclass(t.ccru); - print(":"); - pcivendor(t.vid); - pcidev(t.vid, t.did); - print("\n"); - pcicount = pcicount+1 ; - t = t.link; - } - t = r; - while t!= 0 do { - if (t.bridge !=0) then - pciinfo(t.bridge); - t = t.link; - } -} - -defn lspci() -{ - pciinfo( *pciroot ); -} - -// -// Dump PCI Info (long form - includes interrupt lines & memory segments) -// - -defn pcidumper( r ) -{ - local t; - local m; - t = r; - while t != 0 do { - print("Bus\t",BUSBNO(t.tbdf)\u); - print(", device\t",BUSDNO(t.tbdf)\u); - print(", function\t",BUSFNO(t.tbdf)\u,":\n"); - print(" "); - pciclass(t.ccru); - print(":"); - pcivendor(t.vid); - pcidev(t.vid, t.did); - print("\n"); - print(" Interrupt Line: ",t.intl\u,"\n"); - m =0\d; - loop 0,5 do { - if t.mem[m] != 0 then - print("\t",(m/2)\d,":",t.mem[m]\X," ",t.mem[m+1]\X,"\n"); - m = m + 2; - } - t = t.link; - } - t = r; - while t!= 0 do { - if (t.bridge !=0) then - pcidumper(t.bridge); - t = t.link; - } -} - -defn pcidump() -{ - pcidumper( *pciroot ); -} - -print("/os/pc/pci"); diff --git a/os/pc/pci.c b/os/pc/pci.c deleted file mode 100644 index d35a306a..00000000 --- a/os/pc/pci.c +++ /dev/null @@ -1,1340 +0,0 @@ -/* - * PCI support code. - * Needs a massive rewrite. - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define DBG if(0) pcilog - -struct -{ - char output[16384]; - int ptr; -}PCICONS; - -int -pcilog(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); - - memmove(PCICONS.output+PCICONS.ptr, buf, n); - PCICONS.ptr += n; - return n; -} - -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 nobios, nopcirouting; - -static int pcicfgrw32(int, int, int, int); -static int pcicfgrw16(int, int, int, int); -static int pcicfgrw8(int, int, int, int); - -static char* bustypes[] = { - "CBUSI", - "CBUSII", - "EISA", - "FUTURE", - "INTERN", - "ISA", - "MBI", - "MBII", - "MCA", - "MPI", - "MPSA", - "NUBUS", - "PCI", - "PCMCIA", - "TC", - "VL", - "VME", - "XPRESS", -}; - -#pragma varargck type "T" int - -static int -tbdffmt(Fmt* fmt) -{ - char *p; - int l, r, type, tbdf; - - if((p = malloc(READSTR)) == nil) - return fmtstrcpy(fmt, "(tbdfconv)"); - - switch(fmt->r){ - case 'T': - tbdf = va_arg(fmt->args, int); - type = BUSTYPE(tbdf); - if(type < nelem(bustypes)) - l = snprint(p, READSTR, bustypes[type]); - else - l = snprint(p, READSTR, "%d", type); - snprint(p+l, READSTR-l, ".%d.%d.%d", - BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); - break; - - default: - snprint(p, READSTR, "(tbdfconv)"); - break; - } - r = fmtstrcpy(fmt, p); - free(p); - - return r; -} - -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); -} - -static int -pcisizcmp(void *a, void *b) -{ - Pcisiz *aa, *bb; - - aa = a; - bb = b; - return aa->siz - bb->siz; -} - -static ulong -pcimask(ulong v) -{ - ulong m; - - m = BI2BY*sizeof(v); - for(m = 1<<(m-1); m != 0; m >>= 1) { - if(m & v) - break; - } - - m--; - if((v & m) == 0) - return v; - - v |= m; - return v+1; -} - -static void -pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg) -{ - Pcidev *p; - int ntb, i, size, rno, hole; - ulong v, mema, ioa, sioa, smema, base, limit; - Pcisiz *table, *tptr, *mtb, *itb; - - if(!nobios) - return; - - ioa = *pioa; - mema = *pmema; - - DBG("pcibusmap wr=%d %T mem=%luX io=%luX\n", - wrreg, root->tbdf, mema, ioa); - - ntb = 0; - for(p = root; p != nil; p = p->link) - ntb++; - - ntb *= (PciCIS-PciBAR0)/4; - table = malloc(2*ntb*sizeof(Pcisiz)); - itb = table; - mtb = table+ntb; - - /* - * Build a table of sizes - */ - for(p = root; p != nil; p = p->link) { - if(p->ccrb == 0x06) { - if(p->ccru != 0x04 || p->bridge == nil) { -// DBG("pci: ignored bridge %T\n", p->tbdf); - continue; - } - - sioa = ioa; - smema = mema; - pcibusmap(p->bridge, &smema, &sioa, 0); - - hole = pcimask(smema-mema); - if(hole < (1<<20)) - hole = 1<<20; - p->mema.size = hole; - - hole = pcimask(sioa-ioa); - if(hole < (1<<12)) - hole = 1<<12; - - p->ioa.size = hole; - - itb->dev = p; - itb->bar = -1; - itb->siz = p->ioa.size; - itb++; - - mtb->dev = p; - mtb->bar = -1; - mtb->siz = p->mema.size; - mtb++; - continue; - } - - for(i = 0; i <= 5; i++) { - rno = PciBAR0 + i*4; - v = pcicfgrw32(p->tbdf, rno, 0, 1); - size = pcibarsize(p, rno); - if(size == 0) - continue; - - if(v & 1) { - itb->dev = p; - itb->bar = i; - itb->siz = size; - itb++; - } - else { - mtb->dev = p; - mtb->bar = i; - mtb->siz = size; - mtb++; - } - - p->mem[i].size = size; - } - } - - /* - * Sort both tables IO smallest first, Memory largest - */ - qsort(table, itb-table, sizeof(Pcisiz), pcisizcmp); - tptr = table+ntb; - qsort(tptr, mtb-tptr, sizeof(Pcisiz), pcisizcmp); - - /* - * Allocate IO address space on this bus - */ - for(tptr = table; tptr < itb; tptr++) { - hole = tptr->siz; - if(tptr->bar == -1) - hole = 1<<12; - ioa = (ioa+hole-1) & ~(hole-1); - - p = tptr->dev; - if(tptr->bar == -1) - p->ioa.bar = ioa; - else { - p->pcr |= IOen; - p->mem[tptr->bar].bar = ioa|1; - if(wrreg) - pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0); - } - - ioa += tptr->siz; - } - - /* - * Allocate Memory address space on this bus - */ - for(tptr = table+ntb; tptr < mtb; tptr++) { - hole = tptr->siz; - if(tptr->bar == -1) - hole = 1<<20; - mema = (mema+hole-1) & ~(hole-1); - - p = tptr->dev; - if(tptr->bar == -1) - p->mema.bar = mema; - else { - p->pcr |= MEMen; - p->mem[tptr->bar].bar = mema; - if(wrreg) - pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), mema, 0); - } - mema += tptr->siz; - } - - *pmema = mema; - *pioa = ioa; - free(table); - - if(wrreg == 0) - return; - - /* - * Finally set all the bridge addresses & registers - */ - for(p = root; p != nil; p = p->link) { - if(p->bridge == nil) { - pcicfgrw8(p->tbdf, PciLTR, 64, 0); - - p->pcr |= MASen; - pcicfgrw16(p->tbdf, PciPCR, p->pcr, 0); - continue; - } - - base = p->ioa.bar; - limit = base+p->ioa.size-1; - v = pcicfgrw32(p->tbdf, PciIBR, 0, 1); - v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8); - pcicfgrw32(p->tbdf, PciIBR, v, 0); - v = (limit & 0xFFFF0000)|(base>>16); - pcicfgrw32(p->tbdf, PciIUBR, v, 0); - - base = p->mema.bar; - limit = base+p->mema.size-1; - v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16); - pcicfgrw32(p->tbdf, PciMBR, v, 0); - - /* - * Disable memory prefetch - */ - pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0); - pcicfgrw8(p->tbdf, PciLTR, 64, 0); - - /* - * Enable the bridge - */ - p->pcr |= IOen|MEMen|MASen; - pcicfgrw32(p->tbdf, PciPCR, 0xFFFF0000|p->pcr , 0); - - sioa = p->ioa.bar; - smema = p->mema.bar; - pcibusmap(p->bridge, &smema, &sioa, 1); - } -} - -static int -pcilscan(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->pcr = pcicfgr16(p, PciPCR); - p->rid = pcicfgr8(p, PciRID); - p->ccrp = pcicfgr8(p, PciCCRp); - p->ccru = pcicfgr8(p, PciCCRu); - p->ccrb = pcicfgr8(p, PciCCRb); - p->cls = pcicfgr8(p, PciCLS); - p->ltr = pcicfgr8(p, PciLTR); - - p->intl = pcicfgr8(p, PciINTL); - - /* - * If the device is a multi-function device adjust the - * loop count so all possible functions are checked. - */ - hdt = pcicfgr8(p, PciHDT); - if(hdt & 0x80) - maxfno = MaxFNO; - - /* - * If appropriate, read the base address registers - * and work out the sizes. - */ - switch(p->ccrb) { - case 0x01: /* mass storage controller */ - case 0x02: /* network controller */ - case 0x03: /* display controller */ - case 0x04: /* multimedia device */ - case 0x07: /* simple comm. controllers */ - case 0x08: /* base system peripherals */ - case 0x09: /* input devices */ - case 0x0A: /* docking stations */ - case 0x0B: /* processors */ - case 0x0C: /* serial bus controllers */ - if((hdt & 0x7F) != 0) - break; - rno = PciBAR0 - 4; - for(i = 0; i < nelem(p->mem); i++) { - rno += 4; - p->mem[i].bar = pcicfgr32(p, rno); - p->mem[i].size = pcibarsize(p, rno); - } - break; - - case 0x00: - case 0x05: /* memory controller */ - case 0x06: /* bridge device */ - default: - break; - } - - if(head != nil) - tail->link = p; - else - head = p; - tail = p; - } - } - - *list = head; - for(p = head; p != nil; p = p->link){ - /* - * Find PCI-PCI 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. - */ - sbn = pcicfgr8(p, PciSBN); - ubn = pcicfgr8(p, PciUBN); - - if(sbn == 0 || ubn == 0 || nobios) { - 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 = pcilscan(sbn, &p->bridge); - l = (maxubn<<16)|(sbn<<8)|bno; - - pcicfgw32(p, PciPBN, l); - } - else { - if(ubn > maxubn) - maxubn = ubn; - pcilscan(sbn, &p->bridge); - } - } - - return maxubn; -} - -int -pciscan(int bno, Pcidev **list) -{ - int ubn; - - lock(&pcicfginitlock); - ubn = pcilscan(bno, list); - unlock(&pcicfginitlock); - return ubn; -} - -static uchar -pIIxget(Pcidev *router, uchar link) -{ - uchar pirq; - - /* link should be 0x60, 0x61, 0x62, 0x63 */ - pirq = pcicfgr8(router, link); - return (pirq < 16)? pirq: 0; -} - -static void -pIIxset(Pcidev *router, uchar link, uchar irq) -{ - pcicfgw8(router, link, irq); -} - -static uchar -viaget(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 -viaset(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 -optiget(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 -optiset(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 -aliget(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 -aliset(Pcidev *router, uchar link, uchar irq) -{ - /* Inverse of map in aliget */ - 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 -cyrixget(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 -cyrixset(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 Bridge Bridge; -struct Bridge -{ - ushort vid; - ushort did; - uchar (*get)(Pcidev *, uchar); - void (*set)(Pcidev *, uchar, uchar); -}; - -static Bridge southbridges[] = { - { 0x8086, 0x122e, pIIxget, pIIxset }, // Intel 82371FB - { 0x8086, 0x1234, pIIxget, pIIxset }, // Intel 82371MX - { 0x8086, 0x7000, pIIxget, pIIxset }, // Intel 82371SB - { 0x8086, 0x7110, pIIxget, pIIxset }, // Intel 82371AB - { 0x8086, 0x7198, pIIxget, pIIxset }, // Intel 82443MX (fn 1) - { 0x8086, 0x2410, pIIxget, pIIxset }, // Intel 82801AA - { 0x8086, 0x2420, pIIxget, pIIxset }, // Intel 82801AB - { 0x8086, 0x2440, pIIxget, pIIxset }, // Intel 82801BA - { 0x8086, 0x244c, pIIxget, pIIxset }, // Intel 82801BAM - { 0x8086, 0x248c, pIIxget, pIIxset }, // Intel 82801CAM - { 0x8086, 0x24cc, pIIxget, pIIxset }, // Intel 82801DBM - { 0x8086, 0x24d0, pIIxget, pIIxset }, // Intel 82801EB - { 0x8086, 0x2640, pIIxget, pIIxset }, // Intel 82801FB - { 0x1106, 0x0586, viaget, viaset }, // Viatech 82C586 - { 0x1106, 0x0596, viaget, viaset }, // Viatech 82C596 - { 0x1106, 0x0686, viaget, viaset }, // Viatech 82C686 - { 0x1106, 0x3227, viaget, viaset }, // Viatech VT8237 - { 0x1045, 0xc700, optiget, optiset }, // Opti 82C700 - { 0x10b9, 0x1533, aliget, aliset }, // Al M1533 - { 0x1039, 0x0008, pIIxget, pIIxset }, // SI 503 - { 0x1039, 0x0496, pIIxget, pIIxset }, // SI 496 - { 0x1078, 0x0100, cyrixget, cyrixset }, // Cyrix 5530 Legacy - - { 0x1022, 0x746B, nil, nil }, // AMD 8111 - { 0x10DE, 0x00D1, nil, nil }, // NVIDIA nForce 3 - { 0x1166, 0x0200, nil, nil }, // ServerWorks ServerSet III LE -}; - -typedef struct Slot Slot; -struct Slot { - uchar bus; // Pci bus number - uchar dev; // Pci device number - uchar maps[12]; // Avoid structs! Link and mask. - uchar slot; // Add-in/built-in slot - uchar reserved; -}; - -typedef struct Router Router; -struct Router { - uchar signature[4]; // Routing table signature - uchar version[2]; // Version number - uchar size[2]; // Total table size - uchar bus; // Interrupt router bus number - uchar devfn; // Router's devfunc - uchar pciirqs[2]; // Exclusive PCI irqs - uchar compat[4]; // Compatible PCI interrupt router - uchar miniport[4]; // Miniport data - uchar reserved[11]; - uchar checksum; -}; - -static ushort pciirqs; // Exclusive PCI irqs -static Bridge *southbridge; // Which southbridge to use. - -static void -pcirouting(void) -{ - Slot *e; - Router *r; - int size, i, fn, tbdf; - Pcidev *sbpci, *pci; - uchar *p, pin, irq, link, *map; - - // Search for PCI interrupt routing table in 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 *)p; - - // print("PCI interrupt routing table version %d.%d at %.6uX\n", - // r->version[0], r->version[1], (ulong)r & 0xfffff); - - tbdf = (BusPCI << 24)|(r->bus << 16)|(r->devfn << 8); - sbpci = pcimatchtbdf(tbdf); - if(sbpci == nil) { - print("pcirouting: Cannot find south bridge %T\n", tbdf); - return; - } - - for(i = 0; i != nelem(southbridges); i++) - if(sbpci->vid == southbridges[i].vid && sbpci->did == southbridges[i].did) - break; - - if(i == nelem(southbridges)) { - print("pcirouting: ignoring south bridge %T %.4uX/%.4uX\n", tbdf, sbpci->vid, sbpci->did); - return; - } - southbridge = &southbridges[i]; - if(southbridge->get == nil || southbridge->set == nil) - return; - - pciirqs = (r->pciirqs[1] << 8)|r->pciirqs[0]; - - size = (r->size[1] << 8)|r->size[0]; - for(e = (Slot *)&r[1]; (uchar *)e < p + size; e++) { - // print("%.2uX/%.2uX %.2uX: ", e->bus, e->dev, e->slot); - // for (i = 0; i != 4; i++) { - // uchar *m = &e->maps[i * 3]; - // print("[%d] %.2uX %.4uX ", - // i, m[0], (m[2] << 8)|m[1]); - // } - // print("\n"); - - for(fn = 0; fn != 8; fn++) { - tbdf = (BusPCI << 24)|(e->bus << 16)|((e->dev | fn) << 8); - pci = pcimatchtbdf(tbdf); - if(pci == nil) - continue; - pin = pcicfgr8(pci, PciINTP); - if(pin == 0 || pin == 0xff) - continue; - - map = &e->maps[(pin - 1) * 3]; - link = map[0]; - irq = southbridge->get(sbpci, link); - if(irq == 0 || irq == pci->intl) - continue; - if(pci->intl != 0 && pci->intl != 0xFF) { - print("pcirouting: BIOS workaround: %T at pin %d link %d irq %d -> %d\n", - tbdf, pin, link, irq, pci->intl); - southbridge->set(sbpci, link, pci->intl); - continue; - } - print("pcirouting: %T at pin %d link %d irq %d\n", tbdf, pin, link, irq); - pcicfgw8(pci, PciINTL, irq); - pci->intl = irq; - } - } -} - -static void -pcicfginit(void) -{ - char *p; - Pcidev **list; - ulong mema, ioa; - int bno, n, pcibios; - - lock(&pcicfginitlock); - if(pcicfgmode != -1) - goto out; - - pcibios = 0; - if(getconf("*nobios")) - nobios = 1; - else if(getconf("*pcibios")) - pcibios = 1; - if(getconf("*nopcirouting")) - nopcirouting = 1; - - /* - * 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). - */ - if(!pcibios){ - /* - * 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; - - fmtinstall('T', tbdffmt); - - if(p = getconf("*pcimaxbno")){ - n = strtoul(p, 0, 0); - if(n < pcimaxbno) - pcimaxbno = n; - } - if(p = getconf("*pcimaxdno")){ - n = strtoul(p, 0, 0); - if(n < pcimaxdno) - pcimaxdno = n; - } - - list = &pciroot; - for(bno = 0; bno <= pcimaxbno; bno++) { - int sbno = bno; - bno = pcilscan(bno, list); - - while(*list) - list = &(*list)->link; - - if (sbno == 0) { - Pcidev *pci; - - /* - * If we have found a PCI-to-Cardbus bridge, make sure - * it has no valid mappings anymore. - */ - pci = pciroot; - while (pci) { - if (pci->ccrb == 6 && pci->ccru == 7) { - ushort bcr; - - /* reset the cardbus */ - bcr = pcicfgr16(pci, PciBCR); - pcicfgw16(pci, PciBCR, 0x40 | bcr); - delay(50); - } - pci = pci->link; - } - } - } - - if(pciroot == nil) - goto out; - - if(nobios) { - /* - * Work out how big the top bus is - */ - mema = 0; - ioa = 0; - pcibusmap(pciroot, &mema, &ioa, 0); - - DBG("Sizes: mem=%8.8lux size=%8.8lux io=%8.8lux\n", - mema, pcimask(mema), ioa); - - /* - * Align the windows and map it - */ - ioa = 0x1000; - mema = 0x90000000; - - pcilog("Mask sizes: mem=%lux io=%lux\n", mema, ioa); - - pcibusmap(pciroot, &mema, &ioa, 1); - DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa); - - unlock(&pcicfginitlock); - return; - } - - if (!nopcirouting) - pcirouting(); - -out: - unlock(&pcicfginitlock); - - if(getconf("*pcihinv")) - pcihinv(nil); -} - -static int -pcicfgrw8(int tbdf, int rno, int data, int read) -{ - int o, type, x; - - if(pcicfgmode == -1) - pcicfginit(); - - if(BUSBNO(tbdf)) - type = 0x01; - else - type = 0x00; - x = -1; - if(BUSDNO(tbdf) > pcimaxdno) - return x; - - lock(&pcicfglock); - switch(pcicfgmode){ - - case 1: - o = rno & 0x03; - rno &= ~0x03; - outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); - if(read) - x = inb(PciDATA+o); - else - outb(PciDATA+o, data); - outl(PciADDR, 0); - break; - - case 2: - outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); - outb(PciFORWARD, BUSBNO(tbdf)); - if(read) - x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno); - else - outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); - outb(PciCSE, 0); - break; - } - unlock(&pcicfglock); - - return x; -} - -int -pcicfgr8(Pcidev* pcidev, int rno) -{ - return pcicfgrw8(pcidev->tbdf, rno, 0, 1); -} - -void -pcicfgw8(Pcidev* pcidev, int rno, int data) -{ - pcicfgrw8(pcidev->tbdf, rno, data, 0); -} - -static int -pcicfgrw16(int tbdf, int rno, int data, int read) -{ - int o, type, x; - - if(pcicfgmode == -1) - pcicfginit(); - - if(BUSBNO(tbdf)) - type = 0x01; - else - type = 0x00; - x = -1; - if(BUSDNO(tbdf) > pcimaxdno) - return x; - - lock(&pcicfglock); - switch(pcicfgmode){ - - case 1: - o = rno & 0x02; - rno &= ~0x03; - outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); - if(read) - x = ins(PciDATA+o); - else - outs(PciDATA+o, data); - outl(PciADDR, 0); - break; - - case 2: - outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); - outb(PciFORWARD, BUSBNO(tbdf)); - if(read) - x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno); - else - outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); - outb(PciCSE, 0); - break; - } - unlock(&pcicfglock); - - return x; -} - -int -pcicfgr16(Pcidev* pcidev, int rno) -{ - return pcicfgrw16(pcidev->tbdf, rno, 0, 1); -} - -void -pcicfgw16(Pcidev* pcidev, int rno, int data) -{ - pcicfgrw16(pcidev->tbdf, rno, data, 0); -} - -static int -pcicfgrw32(int tbdf, int rno, int data, int read) -{ - int type, x; - - if(pcicfgmode == -1) - pcicfginit(); - - if(BUSBNO(tbdf)) - type = 0x01; - else - type = 0x00; - x = -1; - if(BUSDNO(tbdf) > pcimaxdno) - return x; - - lock(&pcicfglock); - switch(pcicfgmode){ - - case 1: - rno &= ~0x03; - outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); - if(read) - x = inl(PciDATA); - else - outl(PciDATA, data); - outl(PciADDR, 0); - break; - - case 2: - outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); - outb(PciFORWARD, BUSBNO(tbdf)); - if(read) - x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno); - else - outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); - outb(PciCSE, 0); - break; - } - unlock(&pcicfglock); - - return x; -} - -int -pcicfgr32(Pcidev* pcidev, int rno) -{ - return pcicfgrw32(pcidev->tbdf, rno, 0, 1); -} - -void -pcicfgw32(Pcidev* pcidev, int rno, int data) -{ - pcicfgrw32(pcidev->tbdf, rno, data, 0); -} - -Pcidev* -pcimatch(Pcidev* prev, int vid, int did) -{ - if(pcicfgmode == -1) - pcicfginit(); - - if(prev == nil) - prev = pcilist; - else - prev = prev->list; - - while(prev != nil){ - if((vid == 0 || prev->vid == vid) - && (did == 0 || prev->did == did)) - break; - prev = prev->list; - } - return prev; -} - -Pcidev* -pcimatchtbdf(int tbdf) -{ - Pcidev *pcidev; - - if(pcicfgmode == -1) - pcicfginit(); - - for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) { - if(pcidev->tbdf == tbdf) - break; - } - return pcidev; -} - -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 void -pcilhinv(Pcidev* p) -{ - int i; - Pcidev *t; - - if(p == nil) { - putstrn(PCICONS.output, PCICONS.ptr); - p = pciroot; - print("bus dev type vid did intl memory\n"); - } - for(t = p; t != nil; t = t->link) { - print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ", - BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf), - t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl); - - for(i = 0; i < nelem(p->mem); i++) { - if(t->mem[i].size == 0) - continue; - print("%d:%.8lux %d ", i, - t->mem[i].bar, t->mem[i].size); - } - if(t->ioa.bar || t->ioa.size) - print("ioa:%.8lux %d ", t->ioa.bar, t->ioa.size); - if(t->mema.bar || t->mema.size) - print("mema:%.8lux %d ", t->mema.bar, t->mema.size); - if(t->bridge) - print("->%d", BUSBNO(t->bridge->tbdf)); - print("\n"); - } - while(p != nil) { - if(p->bridge != nil) - pcilhinv(p->bridge); - p = p->link; - } -} - -void -pcihinv(Pcidev* p) -{ - if(pcicfgmode == -1) - pcicfginit(); - lock(&pcicfginitlock); - pcilhinv(p); - unlock(&pcicfginitlock); -} - -void -pcireset(void) -{ - Pcidev *p; - - if(pcicfgmode == -1) - pcicfginit(); - - for(p = pcilist; p != nil; p = p->list) { - /* don't mess with the bridges */ - if(p->ccrb == 0x06) - continue; - pciclrbme(p); - } -} - -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(!(p->pcr & 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/os/pc/pcidb.acid b/os/pc/pcidb.acid deleted file mode 100644 index 0ab443d5..00000000 --- a/os/pc/pcidb.acid +++ /dev/null @@ -1,2848 +0,0 @@ -pcivendordb = { - {0x0000, "Gammagraphx, Inc.", { - }}, - {0x001a, "Ascend Communications, Inc.", { - }}, - {0x003d, "Lockheed Martin-Marietta Corp", { - }}, - {0x0e11, "Compaq Computer Corporation", { - {0x3032,"QVision 1280/p Rev 0"}, - {0x3033,"QVision 1280/p Rev 1"}, - {0x3034,"QVision 1280/p Rev 2"}, - {0x4000,"4000 [Triflex]"}, - {0xae10,"Smart-2/P RAID Controller"}, - {0xae29,"MIS-L"}, - {0xae2a,"MPC"}, - {0xae2b,"MIS-E"}, - {0xae32,"Netelligent 10/100"}, - {0xae34,"Netelligent 10"}, - {0xae35,"Integrated NetFlex-3/P"}, - {0xae40,"Netelligent 10/100 Dual"}, - {0xae43,"ProLiant Integrated Netelligent 10/100"}, - {0xae69,"CETUS-L"}, - {0xae6c,"Northstar"}, - {0xb011,"Integrated Netelligent 10/100"}, - {0xb012,"Netelligent 10 T/2"}, - {0xf130,"NetFlex-3/P ThunderLAN 1.0"}, - {0xf150,"NetFlex-3/P ThunderLAN 2.3"}, - }}, - {0x1000, "Symbios Logic Inc. (formerly NCR)", { - {0x0001,"53c810"}, - {0x0002,"53c820"}, - {0x0003,"53c825"}, - {0x0004,"53c815"}, - {0x0005,"53c810AP"}, - {0x0006,"53c860"}, - {0x000b,"53c896"}, - {0x000c,"53c895"}, - {0x000d,"53c885"}, - {0x000f,"53c875"}, - {0x008f,"53c875J"}, - {0x0901,"61C102"}, - {0x1000,"63C815"}, - }}, - {0x1002, "ATI Technologies Inc", { - {0x4158,"68800AX [Mach32]"}, - {0x4354,"215CT [Mach64 CT]"}, - {0x4358,"210888CX [Mach64 CX]"}, - {0x4554,"210888ET [Mach64 ET]"}, - {0x4742,"215GB [Mach64 GB]"}, - {0x4744,"215GD [Mach64 GD]"}, - {0x4749,"215GI [Mach64 GI]"}, - {0x4750,"215GP [Mach64 GP]"}, - {0x4751,"215GQ [Mach64 GQ]"}, - {0x4754,"215GT [Mach64 GT]"}, - {0x4755,"215GTB [Mach64 GTB]"}, - {0x4756,"215IIC [Mach64 GT IIC]"}, - {0x4758,"210888GX [Mach64 GX]"}, - {0x4c47,"215LG [Mach64 LG]"}, - {0x4c54,"264LT [Mach64 LT]"}, - {0x5654,"264VT [Mach64 VT]"}, - {0x5655,"264VTB [Mach64 VTB]"}, - {0x5656,"264VT4 [Mach64 VT4]"}, - }}, - {0x1003, "ULSI Systems", { - {0x0201,"US201"}, - }}, - {0x1004, "VLSI Technology Inc", { - {0x0005,"82C592-FC1"}, - {0x0006,"82C593-FC1"}, - {0x0007,"82C594-AFC2"}, - {0x0008,"82C596/7 [Wildcat]"}, - {0x0009,"82C597-AFC2"}, - {0x000c,"82C541 [Lynx]"}, - {0x000d,"82C543 [Lynx]"}, - {0x0101,"82C532"}, - {0x0102,"82C534"}, - {0x0103,"82C538"}, - {0x0104,"82C535"}, - {0x0105,"82C147"}, - {0x0200,"82C975"}, - {0x0280,"82C925"}, - {0x0702,"VAS96011 [Golden Gate II]"}, - }}, - {0x1005, "Avance Logic, Inc.", { - {0x2301,"ALG2301"}, - {0x2302,"ALG2302"}, - {0x2364,"ALG2364"}, - }}, - {0x1006, "Reply Group", { - }}, - {0x1007, "NetFrame Systems Inc", { - }}, - {0x1008, "Epson", { - }}, - {0x100a, "Phoenix Technologies", { - }}, - {0x100b, "National Semiconductor Corporation", { - {0x0001,"DP83810"}, - {0x0002,"87415"}, - {0xd001,"87410"}, - }}, - {0x100c, "Tseng Labs Inc", { - {0x3202,"ET4000/W32p rev A"}, - {0x3205,"ET4000/W32p rev B"}, - {0x3206,"ET4000/W32p rev C"}, - {0x3207,"ET4000/W32p rev D"}, - {0x3208,"ET6000"}, - }}, - {0x100d, "AST Research Inc", { - }}, - {0x100e, "Weitek", { - {0x9001,"P9000"}, - {0x9100,"P9100"}, - }}, - {0x1010, "Video Logic, Ltd.", { - }}, - {0x1011, "Digital Equipment Corporation", { - {0x0001,"DECchip 21050"}, - {0x0002,"DECchip 21040 [Tulip]"}, - {0x0004,"DECchip 21030 [TGA]"}, - {0x0007,"NVRAM [Zephyr NVRAM]"}, - {0x0008,"KZPSA [KZPSA]"}, - {0x0009,"DECchip 21140 [FasterNet]"}, - {0x000d,"PBXGB [TGA2]"}, - {0x000f,"DEFPA"}, - {0x0014,"DECchip 21041 [Tulip Pass 3]"}, - {0x0016,"DGLPB [OPPO]"}, - {0x0019,"DECchip 21142/43"}, - {0x0021,"DECchip 21052"}, - {0x0022,"DECchip 21150"}, - {0x0024,"DECchip 21152"}, - }}, - {0x1012, "Micronics Computers Inc", { - }}, - {0x1013, "Cirrus Logic", { - {0x0038,"GD 7548"}, - {0x00a0,"GD 5430/40 [Alpine]"}, - {0x00a4,"GD 5434-4 [Alpine]"}, - {0x00a8,"GD 5434-8 [Alpine]"}, - {0x00ac,"GD 5436 [Alpine]"}, - {0x00b8,"GD 5446"}, - {0x00bc,"GD 5480"}, - {0x00d0,"GD 5462"}, - {0x00d4,"GD 5464 [Laguna]"}, - {0x00d6,"GD 5465 [Laguna]"}, - {0x1100,"CL 6729"}, - {0x1110,"PD 6832"}, - {0x1200,"GD 7542 [Nordic]"}, - {0x1202,"GD 7543 [Viking]"}, - {0x1204,"GD 7541 [Nordic Light]"}, - }}, - {0x1014, "IBM", { - {0x000a,"Fire Coral"}, - {0x0018,"TR"}, - {0x001b,"GXT-150P"}, - {0x001d,"82G2675"}, - {0x0020,"MCA"}, - {0x0022,"IBM27-82351"}, - {0x002e,"ServeRAID controller"}, - {0x0036,"Miami"}, - {0x003e,"TR_Wake"}, - {0x0046,"MPIC interrupt controller"}, - {0x007d,"3780IDSP [MWave]"}, - {0xffff,"MPIC-2 interrupt controller"}, - }}, - {0x1015, "LSI Logic Corp of Canada", { - }}, - {0x1016, "ICL Personal Systems", { - }}, - {0x1017, "SPEA Software AG", { - }}, - {0x1018, "Unisys Systems", { - }}, - {0x1019, "Elitegroup Computer Systems", { - }}, - {0x101a, "AT&T GIS (NCR)", { - }}, - {0x101b, "Vitesse Semiconductor", { - }}, - {0x101c, "Western Digital", { - {0x0193,"33C193A"}, - {0x0197,"33C197A"}, - {0x0296,"33C296A"}, - {0x3193,"7193"}, - {0x3197,"WD 7197"}, - {0x3296,"33C296A"}, - {0x4296,"34C296"}, - {0xc24a,"90C"}, - }}, - {0x101e, "American Megatrends Inc.", { - {0x9010,"MegaRAID"}, - }}, - {0x101f, "PictureTel", { - }}, - {0x1020, "Hitachi Computer Products", { - }}, - {0x1021, "OKI Electric Industry Co. Ltd.", { - }}, - {0x1022, "Advanced Micro Devices", { - {0x2000,"79c970 [PCnet LANCE]"}, - {0x2020,"53c974 [PCscsi]"}, - {0x2040,"79c974"}, - }}, - {0x1023, "Trident Microsystems", { - {0x9320,"TGUI 9320"}, - {0x9397,"Cyber9397"}, - {0x9420,"TGUI 9420"}, - {0x9430,"TGUI 9430"}, - {0x9440,"TGUI 9440"}, - {0x9660,"TGUI 9660/9680/9682"}, - {0x9750,"3DIm`age 975"}, - }}, - {0x1024, "Zenith Data Systems", { - }}, - {0x1025, "Acer Incorporated", { - {0x1435,"M1435"}, - {0x1445,"M1445"}, - {0x1449,"M1449"}, - {0x1451,"M1451"}, - {0x1461,"M1461"}, - {0x3141,"M3141"}, - {0x3143,"M3143"}, - {0x3145,"M3145"}, - {0x3147,"M3147"}, - {0x3149,"M3149"}, - {0x3151,"M3151"}, - }}, - {0x1028, "Dell Computer Corporation", { - }}, - {0x1029, "Siemens Nixdorf IS", { - }}, - {0x102a, "LSI Logic", { - {0x0000,"HYDRA"}, - {0x0010,"ASPEN"}, - }}, - {0x102b, "Matrox Graphics, Inc.", { - {0x0518,"2085PX [Atlas MGA-2]"}, - {0x0519,"MGA 2064W [Millennium]"}, - {0x051a,"MGA 1064SG [Mystique]"}, - {0x051b,"MGA 2164W [Millennium II]"}, - {0x051f,"MGA 2164W AGP [Millennium II AGP]"}, - {0x0d10,"MGA Ultima/Impression"}, - }}, - {0x102c, "Chips and Technologies", { - {0x00b8,"64310"}, - {0x00d8,"65545"}, - {0x00dc,"65548"}, - {0x00e0,"65550"}, - {0x00e4,"65554"}, - {0x00e5,"65555"}, - }}, - {0x102d, "Wyse Technology Inc.", { - }}, - {0x102e, "Olivetti Advanced Technology", { - }}, - {0x102f, "Toshiba America", { - }}, - {0x1030, "TMC Research", { - }}, - {0x1031, "Miro Computer Products AG", { - {0x5601,"DC20 ASIC"}, - }}, - {0x1033, "NEC Corporation", { - {0x0035,"USB"}, - {0x0046,"PowerVR PCX2 [midas]"}, - }}, - {0x1034, "Framatome Connectors USA Inc.", { - }}, - {0x1035, "Comp. & Comm. Research Lab", { - }}, - {0x1036, "Future Domain Corp.", { - {0x0000,"TMC-18C30 [36C70]"}, - }}, - {0x1037, "Hitachi Micro Systems", { - }}, - {0x1038, "AMP, Inc", { - }}, - {0x1039, "Silicon Integrated Systems", { - {0x0001,"5591/5592 AGP"}, - {0x0002,"SG86C202"}, - {0x0008,"85C503"}, - {0x0009,"ACPI"}, - {0x0200,"5597/5598 VGA"}, - {0x0204,"82C204"}, - {0x0205,"SG86C205"}, - {0x0406,"85C501/2"}, - {0x0496,"85C496"}, - {0x0597,"5513C"}, - {0x0601,"85C601"}, - {0x5107,"5107"}, - {0x5511,"5511/5512"}, - {0x5513,"5513"}, - {0x5571,"5571"}, - {0x5591,"5591/5592 Host"}, - {0x5597,"5597 [SiS5582]"}, - {0x7001,"7001"}, - }}, - {0x103a, "Seiko Epson Corporation", { - }}, - {0x103b, "Tatung Co. of America", { - }}, - {0x103c, "Hewlett-Packard Company", { - {0x1030,"J2585A"}, - {0x1031,"J2585B"}, - {0x2910,"E2910A"}, - {0x2925,"E2925A"}, - }}, - {0x103e, "Solliday Engineering", { - }}, - {0x103f, "Synopsys/Logic Modeling Group", { - }}, - {0x1040, "Accelgraphics Inc.", { - }}, - {0x1041, "Computrend", { - }}, - {0x1042, "Micron", { - {0x1000,"FDC 37C665"}, - {0x1001,"37C922"}, - {0x3000,"Samurai_0"}, - {0x3010,"Samurai_1"}, - {0x3020,"Samurai_IDE"}, - }}, - {0x1043, "Asustek Computer, Inc.", { - }}, - {0x1044, "Distributed Processing Technology", { - {0xa400,"SmartCache/Raid III or IV"}, - }}, - {0x1045, "OPTi Inc.", { - {0xc178,"92C178"}, - {0xc557,"82C557 [Viper-M]"}, - {0xc558,"82C558 [Viper-M ISA+IDE]"}, - {0xc621,"82C621"}, - {0xc700,"82C700"}, - {0xc701,"82C701 [FireStar Plus]"}, - {0xc814,"82C814 [Firebridge 1]"}, - {0xc822,"82C822"}, - {0xc824,"82C824"}, - {0xd568,"82C825 [Firebridge 2]"}, - }}, - {0x1046, "IPC Corporation, Ltd.", { - }}, - {0x1047, "Genoa Systems Corp", { - }}, - {0x1048, "Elsa AG", { - }}, - {0x1049, "Fountain Technologies, Inc.", { - }}, - {0x104a, "SGS Thomson Microelectronics", { - {0x0008,"STG 2000X"}, - {0x0009,"STG 1764X"}, - }}, - {0x104b, "BusLogic", { - {0x0140,"BT-946C (old) [multimaster 01]"}, - {0x1040,"BT-946C (BA80C30) [MultiMaster 10]"}, - {0x8130,"Flashpoint LT"}, - }}, - {0x104c, "Texas Instruments", { - {0x3d04,"TVP4010 [Permedia]"}, - {0x3d07,"TVP4020 [Permedia 2]"}, - {0xa001,"TDC1570"}, - {0xa100,"TDC1561"}, - {0xac10,"PCI1050"}, - {0xac11,"PCI1053"}, - {0xac12,"PCI1130"}, - {0xac13,"PCI1031"}, - {0xac15,"PCI1131"}, - {0xac16,"PCI-1250"}, - {0xac17,"PCI-1220"}, - }}, - {0x104d, "Sony Corporation", { - }}, - {0x104e, "Oak Technology, Inc", { - {0x0107,"OTI107"}, - }}, - {0x104f, "Co-time Computer Ltd", { - }}, - {0x1050, "Winbond Electronics Corp", { - {0x0940,"89C940"}, - }}, - {0x1051, "Anigma, Inc.", { - }}, - {0x1053, "Young Micro Systems", { - }}, - {0x1054, "Hitachi, Ltd", { - }}, - {0x1055, "EFAR Microsystems", { - }}, - {0x1056, "ICL", { - }}, - {0x1057, "Motorola Computer Group", { - {0x0001,"MPC105 [Eagle]"}, - {0x0002,"MPC106 [Grackle]"}, - {0x4801,"Raven"}, - }}, - {0x1058, "Electronics & Telecommunications RSH", { - }}, - {0x1059, "Teknor Industrial Computers Inc", { - }}, - {0x105a, "Promise Technology, Inc.", { - {0x4d33,"20246"}, - {0x5300,"DC5300"}, - }}, - {0x105b, "Foxconn International, Inc.", { - }}, - {0x105c, "Wipro Infotech Limited", { - }}, - {0x105d, "Number 9 Computer Company", { - {0x2309,"Imagine 128"}, - {0x2339,"Imagine 128-II"}, - {0x493d,"Imagine 128 T2R [Ticket to Ride]"}, - }}, - {0x105e, "Vtech Computers Ltd", { - }}, - {0x105f, "Infotronic America Inc", { - }}, - {0x1060, "United Microelectronics", { - {0x0001,"UM82C881"}, - {0x0002,"UM82C886"}, - {0x0101,"UM8673F"}, - {0x0881,"UM8881"}, - {0x0886,"UM8886F"}, - {0x0891,"UM8891A"}, - {0x1001,"UM886A"}, - {0x673a,"UM8886BF"}, - {0x8710,"UM8710"}, - {0x886a,"UM8886A"}, - {0x8881,"UM8881F"}, - {0x8886,"UM8886F"}, - {0x888a,"UM8886A"}, - {0x8891,"UM8891A"}, - {0x9017,"UM9017F"}, - {0xe881,"UM8881N"}, - {0xe886,"UM8886N"}, - {0xe891,"UM8891N"}, - }}, - {0x1061, "I.I.T.", { - {0x0001,"AGX016"}, - {0x0002,"IIT3204/3501"}, - }}, - {0x1062, "Maspar Computer Corp", { - }}, - {0x1063, "Ocean Office Automation", { - }}, - {0x1064, "Alcatel CIT", { - }}, - {0x1065, "Texas Microsystems", { - }}, - {0x1066, "PicoPower Technology", { - {0x0000,"PT80C826"}, - {0x0001,"PT86C52x [Vesuvius]"}, - {0x0002,"PT80C524 [Nile]"}, - }}, - {0x1067, "Mitsubishi Electronics", { - }}, - {0x1068, "Diversified Technology", { - }}, - {0x1069, "Mylex Corporation", { - {0x0001,"DAC960P"}, - }}, - {0x106a, "Aten Research Inc", { - }}, - {0x106b, "Apple Computer Inc.", { - {0x0001,"Bandit PowerPC host bridge"}, - {0x0002,"Grand Central I/O"}, - {0x000e,"Hydra Mac I/O"}, - }}, - {0x106c, "Hyundai Electronics America", { - }}, - {0x106d, "Sequent Computer Systems", { - }}, - {0x106e, "DFI, Inc", { - }}, - {0x106f, "City Gate Development Ltd", { - }}, - {0x1070, "Daewoo Telecom Ltd", { - }}, - {0x1071, "Mitac", { - }}, - {0x1072, "GIT Co Ltd", { - }}, - {0x1073, "Yamaha Corporation", { - {0x0002,"YGV615 [RPA3 3D-Graphics Controller]"}, - }}, - {0x1074, "NexGen Microsystems", { - {0x4e78,"82c501"}, - }}, - {0x1075, "Advanced Integrations Research", { - }}, - {0x1076, "Chaintech Computer Co. Ltd", { - }}, - {0x1077, "Q Logic", { - {0x1020,"ISP1020"}, - {0x1022,"ISP1022"}, - }}, - {0x1078, "Cyrix Corporation", { - {0x0000,"5510 [Grappa]"}, - {0x0001,"PCI_Master"}, - {0x0002,"5520 [Cognac]"}, - {0x0100,"5530_Legacy [Kahlua]"}, - {0x0101,"5530_SMI [Kahlua]"}, - {0x0102,"5530_IDE [Kahlua]"}, - {0x0103,"5530_Audio [Kahlua]"}, - {0x0104,"5530_Video [Kahlua]"}, - }}, - {0x1079, "I-Bus", { - }}, - {0x107a, "NetWorth", { - }}, - {0x107b, "Gateway 2000", { - }}, - {0x107c, "Goldstar", { - }}, - {0x107d, "LeadTek Research Inc.", { - {0x0000,"P86C850"}, - }}, - {0x107e, "Interphase Corporation", { - }}, - {0x107f, "Data Technology Corporation", { - {0x0802,"SL82C105"}, - }}, - {0x1080, "Contaq Microsystems", { - {0x0600,"82C599"}, - {0xc693,"82c693"}, - }}, - {0x1081, "Supermac Technology", { - }}, - {0x1082, "EFA Corporation of America", { - }}, - {0x1083, "Forex Computer Corporation", { - {0x0001,"FR710"}, - }}, - {0x1084, "Parador", { - }}, - {0x1085, "Tulip Computers Int.B.V.", { - }}, - {0x1086, "J. Bond Computer Systems", { - }}, - {0x1087, "Cache Computer", { - }}, - {0x1088, "Microcomputer Systems (M) Son", { - }}, - {0x1089, "Data General Corporation", { - }}, - {0x108a, "Bit3 Computer Corp.", { - }}, - {0x108c, "Oakleigh Systems Inc.", { - }}, - {0x108d, "Olicom", { - {0x0001,"OC-3136/3137"}, - {0x0011,"OC-2315"}, - {0x0012,"OC-2325"}, - {0x0013,"OC-2183/2185"}, - {0x0014,"OC-2326"}, - {0x0021,"OC-6151/6152 [RapidFire ATM PCI 155]"}, - }}, - {0x108e, "Sun Microsystems Computer Corp.", { - {0x1000,"EBUS"}, - {0x1001,"Happy Meal"}, - {0x5000,"Advanced PCI Bridge"}, - {0x8000,"PCI Bus Module"}, - {0xa000,"Ultra IIi PCI"}, - }}, - {0x108f, "Systemsoft", { - }}, - {0x1090, "Encore Computer Corporation", { - }}, - {0x1091, "Intergraph Corporation", { - }}, - {0x1092, "Diamond Multimedia Systems", { - }}, - {0x1093, "National Instruments", { - {0xc801,"PCI_GPIB"}, - }}, - {0x1094, "First International Computers", { - }}, - {0x1095, "CMD Technology Inc", { - {0x0640,"PCI0640"}, - {0x0643,"PCI0643"}, - {0x0646,"PCI0646"}, - {0x0650,"PBC0650A"}, - {0x0670,"670"}, - }}, - {0x1096, "Alacron", { - }}, - {0x1097, "Appian Technology", { - }}, - {0x1098, "Quantum Designs (H.K.) Ltd", { - {0x0001,"QD-8500"}, - {0x0002,"QD-8580"}, - }}, - {0x1099, "Samsung Electronics Co., Ltd", { - }}, - {0x109a, "Packard Bell", { - }}, - {0x109b, "Gemlight Computer Ltd.", { - }}, - {0x109c, "Megachips Corporation", { - }}, - {0x109d, "Zida Technologies Ltd.", { - }}, - {0x109e, "Brooktree Corporation", { - {0x0350,"Bt848"}, - {0x0351,"Bt849A"}, - {0x8472,"Bt8472"}, - {0x8474,"Bt8474"}, - }}, - {0x109f, "Trigem Computer Inc.", { - }}, - {0x10a0, "Meidensha Corporation", { - }}, - {0x10a1, "Juko Electronics Ind. Co. Ltd", { - }}, - {0x10a2, "Quantum Corporation", { - }}, - {0x10a3, "Everex Systems Inc", { - }}, - {0x10a4, "Globe Manufacturing Sales", { - }}, - {0x10a5, "Racal Interlan", { - }}, - {0x10a6, "Informtech Industrial Ltd.", { - }}, - {0x10a7, "Benchmarq Microelectronics", { - }}, - {0x10a8, "Sierra Semiconductor", { - {0x0000,"STB Horizon 64"}, - }}, - {0x10a9, "Silicon Graphics", { - }}, - {0x10aa, "ACC Microelectronics", { - {0x0000,"ACCM 2188"}, - }}, - {0x10ab, "Digicom", { - }}, - {0x10ac, "Honeywell IAC", { - }}, - {0x10ad, "Symphony Labs", { - {0x0001,"W83769F"}, - {0x0103,"SL82c103"}, - {0x0105,"SL82c105"}, - {0x0565,"W83C553"}, - }}, - {0x10ae, "Cornerstone Technology", { - }}, - {0x10af, "Micro Computer Systems Inc", { - }}, - {0x10b0, "CardExpert Technology", { - }}, - {0x10b1, "Cabletron Systems Inc", { - }}, - {0x10b2, "Raytheon Company", { - }}, - {0x10b3, "Databook Inc", { - {0x3106,"DB87144"}, - {0xb106,"DB87144"}, - }}, - {0x10b4, "STB Systems Inc", { - }}, - {0x10b5, "PLX Technology, Inc.", { - {0x9036,"9036"}, - {0x9060,"9060"}, - {0x906e,"9060ES"}, - {0x9080,"9080"}, - }}, - {0x10b6, "Madge Networks", { - {0x0001,"Smart"}, - {0x0002,"Smart 16/4 BM Mk2 PCI Ringnode"}, - {0x1001,"Collage 155 Server"}, - }}, - {0x10b7, "3Com Corporation", { - {0x0001,"3c985 1000BaseSX"}, - {0x3390,"Token Link Velocity"}, - {0x5900,"3c590 10BaseT [Vortex]"}, - {0x5950,"3c595 100BaseTX [Vortex]"}, - {0x5951,"3c595 100BaseT4 [Vortex]"}, - {0x5952,"3c595 100Base-MII [Vortex]"}, - {0x9000,"3c900 10BaseT [Boomerang]"}, - {0x9001,"3c900 Combo [Boomerang]"}, - {0x9050,"3c905 100BaseTX [Boomerang]"}, - {0x9051,"3c905 100BaseT4"}, - {0x9055,"3c905B 100BaseTX [Cyclone]"}, - }}, - {0x10b8, "Standard Microsystems", { - {0x0005,"9432 TX"}, - {0x1000,"37c665"}, - {0x1001,"37C922"}, - }}, - {0x10b9, "Acer Laboratories Inc.", { - {0x1435,"M1435"}, - {0x1445,"M1445"}, - {0x1449,"M1449"}, - {0x1451,"M1451"}, - {0x1461,"M1461"}, - {0x1489,"M1489"}, - {0x1511,"M1511"}, - {0x1513,"M1513"}, - {0x1521,"M1521"}, - {0x1523,"M1523"}, - {0x1531,"M1531"}, - {0x1533,"M1533"}, - {0x1541,"M1541"}, - {0x1543,"M1543"}, - {0x3141,"M3141"}, - {0x3143,"M3143"}, - {0x3145,"M3145"}, - {0x3147,"M3147"}, - {0x3149,"M3149"}, - {0x3151,"M3151"}, - {0x3307,"M3307"}, - {0x5215,"M4803"}, - {0x5217,"m5217h"}, - {0x5219,"M5219"}, - {0x5229,"M5229"}, - {0x5235,"m5225"}, - {0x5237,"M5237"}, - {0x7101,"M7101"}, - }}, - {0x10ba, "Mitsubishi Electric Corp.", { - }}, - {0x10bb, "Dapha Electronics Corporation", { - }}, - {0x10bc, "Advanced Logic Research", { - }}, - {0x10bd, "Surecom Technology", { - {0x0e34,"NE-34PCI LAN"}, - }}, - {0x10be, "Tseng Labs International Co.", { - }}, - {0x10bf, "Most Inc", { - }}, - {0x10c0, "Boca Research Inc.", { - }}, - {0x10c1, "ICM Co., Ltd.", { - }}, - {0x10c2, "Auspex Systems Inc.", { - }}, - {0x10c3, "Samsung Semiconductors, Inc.", { - }}, - {0x10c4, "Award Software International Inc.", { - }}, - {0x10c5, "Xerox Corporation", { - }}, - {0x10c6, "Rambus Inc.", { - }}, - {0x10c7, "Media Vision", { - }}, - {0x10c8, "Neomagic Corporation", { - {0x0001,"NM2070 [MagicGraph NM2070]"}, - {0x0002,"NM2090 [MagicGraph 128V]"}, - {0x0003,"NM2093 [MagicGraph 128ZV]"}, - {0x0004,"NM2160 [MagicGraph 128XD]"}, - }}, - {0x10c9, "Dataexpert Corporation", { - }}, - {0x10ca, "Fujitsu Microelectr., Inc.", { - }}, - {0x10cb, "Omron Corporation", { - }}, - {0x10cc, "Mentor ARC Inc", { - }}, - {0x10cd, "Advanced System Products, Inc", { - {0x1200,"ASC1200 [(abp940) Fast SCSI-II]"}, - {0x1300,"ABP940-U"}, - {0x2300,"ABP940-UW"}, - }}, - {0x10ce, "Radius", { - }}, - {0x10cf, "Citicorp TTI", { - {0x2001,"mb86605"}, - }}, - {0x10d0, "Fujitsu Limited", { - }}, - {0x10d1, "FuturePlus Systems Corp.", { - }}, - {0x10d2, "Molex Incorporated", { - }}, - {0x10d3, "Jabil Circuit Inc", { - }}, - {0x10d4, "Hualon Microelectronics", { - }}, - {0x10d5, "Autologic Inc.", { - }}, - {0x10d6, "Cetia", { - }}, - {0x10d7, "BCM Advanced Research", { - }}, - {0x10d8, "Advanced Peripherals Labs", { - }}, - {0x10d9, "Macronix, Inc.", { - {0x0512,"MX98713"}, - {0x0531,"MX987x5"}, - }}, - {0x10da, "Compaq IPG-Austin", { - }}, - {0x10db, "Rohm LSI Systems, Inc.", { - }}, - {0x10dc, "CERN/ECP/EDU", { - {0x0001,"STAR/RD24 SCI-PCI (PMC)"}, - {0x0002,"TAR/RD24 SCI-PCI (PMC) [ATT 2C15-3 (FPGA) SCI bridge on PCI 5 Volt card]"}, - {0x0021,"HIPPI destination"}, - {0x0022,"HIPPI source"}, - }}, - {0x10dd, "Evans & Sutherland", { - }}, - {0x10de, "Nvidia Corporation", { - {0x0008,"NV1"}, - {0x0009,"DAC64"}, - }}, - {0x10df, "Emulex Corporation", { - }}, - {0x10e0, "Integrated Micro Solutions Inc.", { - {0x5026,"IMS5026/27/28"}, - {0x8849,"8849"}, - {0x9128,"IMS9129"}, - }}, - {0x10e1, "Tekram Technology Co.,Ltd.", { - {0x690c,"690c"}, - {0xdc29,"DC290"}, - }}, - {0x10e2, "Aptix Corporation", { - }}, - {0x10e3, "Tundra Semiconductor Corp.", { - {0x0000,"CA91C042 [Universe]"}, - {0x0860,"CA91C860 [QSpan]"}, - }}, - {0x10e4, "Tandem Computers", { - }}, - {0x10e5, "Micro Industries Corporation", { - }}, - {0x10e6, "Gainbery Computer Products Inc.", { - }}, - {0x10e7, "Vadem", { - }}, - {0x10e8, "Applied Micro Circuits Corporation", { - {0x5920,"S5920"}, - {0x8043,"LANai4.x [Myrinet LANai interface chip]"}, - {0x8062,"S5933_PARASTATION"}, - {0x807d,"S5933 [Matchmaker]"}, - {0x809c,"S5933_HEPC3"}, - }}, - {0x10e9, "Alps Electric Co., Ltd.", { - }}, - {0x10ea, "Intergraphics Systems", { - {0x1680,"IGA-1680"}, - {0x1682,"IGA-1682"}, - }}, - {0x10eb, "Artists Graphics", { - {0x0101,"3GA"}, - }}, - {0x10ec, "Realtek Semiconductor Co., Ltd.", { - {0x8029,"8029"}, - {0x8129,"8129"}, - {0x8139,"8139"}, - }}, - {0x10ed, "Ascii Corporation", { - {0x7310,"V7310"}, - }}, - {0x10ee, "Xilinx, Inc.", { - }}, - {0x10ef, "Racore Computer Products, Inc.", { - }}, - {0x10f0, "Peritek Corporation", { - }}, - {0x10f1, "Tyan Computer", { - }}, - {0x10f2, "Achme Computer, Inc.", { - }}, - {0x10f3, "Alaris, Inc.", { - }}, - {0x10f4, "S-MOS Systems, Inc.", { - }}, - {0x10f5, "NKK Corporation", { - {0xa001,"NDR4000 [NR4600 Bridge]"}, - }}, - {0x10f6, "Creative Electronic Systems SA", { - }}, - {0x10f7, "Matsushita Electric Industrial Co., Ltd.", { - }}, - {0x10f8, "Altos India Ltd", { - }}, - {0x10f9, "PC Direct", { - }}, - {0x10fa, "Truevision", { - {0x000c,"TARGA 1000"}, - }}, - {0x10fb, "Thesys Gesellschaft f€r Mikroelektronik mbH", { - }}, - {0x10fc, "I-O Data Device, Inc.", { - }}, - {0x10fd, "Soyo Computer, Inc", { - }}, - {0x10fe, "Fast Multimedia AG", { - }}, - {0x10ff, "NCube", { - }}, - {0x1100, "Jazz Multimedia", { - }}, - {0x1101, "Initio Corporation", { - {0x9100,"320 P"}, - {0x9500,"360P"}, - }}, - {0x1102, "Creative Labs", { - }}, - {0x1103, "Triones Technologies, Inc.", { - }}, - {0x1104, "RasterOps Corp.", { - }}, - {0x1105, "Sigma Designs, Inc.", { - }}, - {0x1106, "VIA Technologies, Inc.", { - {0x0505,"VT 82C505"}, - {0x0561,"VT 82C561"}, - {0x0571,"VT82C586 IDE [Apollo]"}, - {0x0576,"VT 82C576 3V [Apollo Master]"}, - {0x0585,"VT82C585VP [Apollo VP1/VPX]"}, - {0x0586,"VT82C586 ISA [Apollo VP]"}, - {0x0595,"VT82C595 [Apollo VP2]"}, - {0x0597,"VT82C597 [Apollo VP3]"}, - {0x0926,"VT82C926 [Amazon]"}, - {0x1000,"82C570MV"}, - {0x1106,"82C570MV"}, - {0x1571,"VT 82C416MV"}, - {0x1595,"VT82C595/97 [Apollo VP2/97]"}, - {0x3038,"VT82C586B USB"}, - {0x3040,"VT82C586B ACPI"}, - {0x6100,"VT85C100A [Rhine II]"}, - {0x8597,"VT82C597 [Apollo VP3 AGP]"}, - }}, - {0x1107, "Stratus Computers", { - }}, - {0x1108, "Proteon, Inc.", { - {0x0100,"p1690plus_AA"}, - {0x0101,"p1690plus_AB"}, - }}, - {0x1109, "Cogent Data Technologies, Inc.", { - {0x1400,"EM110TX [EX110TX PCI Fast Ethernet Adapter]"}, - }}, - {0x110a, "Siemens Nixdorf AG", { - {0x6120,"SZB6120"}, - }}, - {0x110b, "Chromatic Research Inc.", { - }}, - {0x110c, "Mini-Max Technology, Inc.", { - }}, - {0x110d, "Znyx Advanced Systems", { - }}, - {0x110e, "CPU Technology", { - }}, - {0x110f, "Ross Technology", { - }}, - {0x1110, "Powerhouse Systems", { - }}, - {0x1111, "Santa Cruz Operation", { - }}, - {0x1112, "RNS - Div. of Meret Communications Inc", { - }}, - {0x1113, "Accton Technology Corporation", { - }}, - {0x1114, "Atmel Corporation", { - }}, - {0x1115, "3D Labs", { - }}, - {0x1116, "Data Translation", { - }}, - {0x1117, "Datacube, Inc", { - }}, - {0x1118, "Berg Electronics", { - }}, - {0x1119, "ICP Vortex Computersysteme GmbH", { - {0x0000,"GDT6000/6020/6050"}, - {0x0001,"GDT6000b/6010"}, - {0x0002,"GDT6110/6510"}, - {0x0003,"GDT6120/6520"}, - {0x0004,"GDT6530"}, - {0x0005,"GDT6550"}, - {0x0006,"GDT6x17"}, - {0x0007,"GDT6x27"}, - {0x0008,"GDT6537"}, - {0x0009,"GDT5557"}, - {0x000a,"GDT6x15"}, - {0x000b,"GDT6x25"}, - {0x000c,"GDT6535"}, - {0x000d,"GDT6555"}, - {0x0100,"GDT 6117RP/6517RP"}, - {0x0101,"GDT 6127RP/6527RP"}, - {0x0102,"GDT 6537RP"}, - {0x0103,"GDT 6557RP"}, - {0x0104,"GDT 6111RP/6511RP"}, - {0x0105,"GDT 6121RP/6521RP"}, - {0x0110,"GDT 6117RP1/6517RP1"}, - {0x0111,"GDT 6127RP1/6527RP1"}, - {0x0112,"GDT 6537RP1"}, - {0x0113,"GDT 6557RP1"}, - {0x0114,"GDT 6111RP1/6511RP1"}, - {0x0115,"GDT 6121RP1/6521RP1"}, - {0x0120,"GDT 6117RP2/6517RP2"}, - {0x0121,"GDT 6127RP2/6527RP2"}, - {0x0122,"GDT 6537RP2"}, - {0x0123,"GDT 6557RP2"}, - {0x0124,"GDT 6111RP2/6511RP2"}, - {0x0125,"GDT 6121RP2/6521RP2"}, - }}, - {0x111a, "Efficient Networks, Inc", { - {0x0000,"155P-MF1 (FPGA)"}, - {0x0002,"155P-MF1 (ASIC)"}, - }}, - {0x111b, "Teledyne Electronic Systems", { - }}, - {0x111c, "Tricord Systems Inc.", { - }}, - {0x111d, "Integrated Device Tech", { - }}, - {0x111e, "Eldec", { - }}, - {0x111f, "Precision Digital Images", { - }}, - {0x1120, "EMC Corporation", { - }}, - {0x1121, "Zilog", { - }}, - {0x1122, "Multi-tech Systems, Inc.", { - }}, - {0x1123, "Excellent Design, Inc.", { - }}, - {0x1124, "Leutron Vision AG", { - }}, - {0x1125, "Eurocore", { - }}, - {0x1127, "FORE Systems Inc", { - {0x0210,"PCA-200PC"}, - {0x0300,"PCA-200E"}, - }}, - {0x1129, "Firmworks", { - }}, - {0x112a, "Hermes Electronics Company, Ltd.", { - }}, - {0x112b, "Linotype - Hell AG", { - }}, - {0x112c, "Zenith Data Systems", { - }}, - {0x112d, "Ravicad", { - }}, - {0x112e, "Infomedia Microelectronics Inc.", { - }}, - {0x112f, "Imaging Technology Inc", { - {0x0000,"MVC IC-PCI"}, - }}, - {0x1130, "Computervision", { - }}, - {0x1131, "Philips Semiconductors", { - {0x7145,"SAA7145"}, - {0x7146,"SAA7146"}, - }}, - {0x1132, "Mitel Corp.", { - }}, - {0x1133, "Eicon Technology Corporation", { - {0xe001,"DIVA20PRO"}, - {0xe002,"DIVA20"}, - {0xe003,"DIVA20PRO_U"}, - {0xe004,"DIVA20_U"}, - }}, - {0x1134, "Mercury Computer Systems", { - }}, - {0x1135, "Fuji Xerox Co Ltd", { - }}, - {0x1136, "Momentum Data Systems", { - }}, - {0x1137, "Cisco Systems Inc", { - }}, - {0x1138, "Ziatech Corporation", { - {0x8905,"8905 [STD 32 Bridge]"}, - }}, - {0x1139, "Dynamic Pictures, Inc", { - }}, - {0x113a, "FWB Inc", { - }}, - {0x113b, "Network Computing Devices", { - }}, - {0x113c, "Cyclone Microsystems, Inc.", { - {0x0001,"PCI-SDK [PCI i960 Evaluation Platform]"}, - {0x0911,"PCI-911 [PCI-based i960Jx Intelligent I/O Controller]"}, - {0x0912,"PCI-912 [i960CF-based Intelligent I/O Controller]"}, - {0x0913,"PCI-913"}, - }}, - {0x113d, "Leading Edge Products Inc", { - }}, - {0x113e, "Sanyo Electric Co - Computer Engineering Dept", { - }}, - {0x113f, "Equinox Systems, Inc.", { - }}, - {0x1140, "Intervoice Inc", { - }}, - {0x1141, "Crest Microsystem Inc", { - }}, - {0x1142, "Alliance Semiconductor Corporation", { - {0x3210,"AP6410"}, - {0x6422,"AP6422"}, - {0x6424,"AT24"}, - {0x643d,"AT3D"}, - }}, - {0x1143, "NetPower, Inc", { - }}, - {0x1144, "Cincinnati Milacron", { - }}, - {0x1145, "Workbit Corporation", { - }}, - {0x1146, "Force Computers", { - }}, - {0x1147, "Interface Corp", { - }}, - {0x1148, "Schneider & Koch", { - }}, - {0x1149, "Win System Corporation", { - }}, - {0x114a, "VMIC", { - {0x7587,"VMIVME-7587"}, - }}, - {0x114b, "Canopus Co., Ltd", { - }}, - {0x114c, "Annabooks", { - }}, - {0x114d, "IC Corporation", { - }}, - {0x114e, "Nikon Systems Inc", { - }}, - {0x114f, "Digi International", { - {0x0002,"AccelePort EPC"}, - {0x0003,"RightSwitch SE-6"}, - {0x0004,"AccelePort Xem"}, - {0x0006,"AccelePort Xr,C/X"}, - {0x0009,"AccelePort Xr/J"}, - {0x000a,"AccelePort EPC/J"}, - {0x0027,"AccelePort Xr 920"}, - }}, - {0x1150, "Thinking Machines Corp", { - }}, - {0x1151, "JAE Electronics Inc.", { - }}, - {0x1152, "Megatek", { - }}, - {0x1153, "Land Win Electronic Corp", { - }}, - {0x1154, "Melco Inc", { - }}, - {0x1155, "Pine Technology Ltd", { - }}, - {0x1156, "Periscope Engineering", { - }}, - {0x1157, "Avsys Corporation", { - }}, - {0x1158, "Voarx R & D Inc", { - }}, - {0x1159, "Mutech Corp", { - {0x0001,"MV-1000"}, - }}, - {0x115a, "Harlequin Ltd", { - }}, - {0x115b, "Parallax Graphics", { - }}, - {0x115c, "Photron Ltd.", { - }}, - {0x115d, "Xircom", { - }}, - {0x115e, "Peer Protocols Inc", { - }}, - {0x115f, "Maxtor Corporation", { - }}, - {0x1160, "Megasoft Inc", { - }}, - {0x1161, "PFU Limited", { - }}, - {0x1162, "OA Laboratory Co Ltd", { - }}, - {0x1163, "Rendition", { - {0x0001,"Verite 1000 PCI"}, - {0x2000,"Verite V2100"}, - }}, - {0x1164, "Advanced Peripherals Technologies", { - }}, - {0x1165, "Imagraph Corporation", { - }}, - {0x1166, "Pequr Technology", { - }}, - {0x1167, "Mutoh Industries Inc", { - }}, - {0x1168, "Thine Electronics Inc", { - }}, - {0x1169, "Centre for Development of Advanced Computing", { - }}, - {0x116a, "Polaris Communications", { - }}, - {0x116b, "Connectware Inc", { - }}, - {0x116c, "Intelligent Resources Integrated Systems", { - }}, - {0x116d, "Martin-Marietta", { - }}, - {0x116e, "Electronics for Imaging", { - }}, - {0x116f, "Workstation Technology", { - }}, - {0x1170, "Inventec Corporation", { - }}, - {0x1171, "Loughborough Sound Images Plc", { - }}, - {0x1172, "Altera Corporation", { - }}, - {0x1173, "Adobe Systems, Inc", { - }}, - {0x1174, "Bridgeport Machines", { - }}, - {0x1175, "Mitron Computer Inc.", { - }}, - {0x1176, "SBE Incorporated", { - }}, - {0x1177, "Silicon Engineering", { - }}, - {0x1178, "Alfa, Inc.", { - }}, - {0x1179, "Toshiba America Info Systems", { - {0x0601,"601"}, - {0x060a,"ToPIC95"}, - {0x060f,"ToPIC97"}, - {0x0701,"Lucent DSP1645 [Mars]"}, - }}, - {0x117b, "L G Electronics, Inc.", { - }}, - {0x117c, "Atto Technology", { - }}, - {0x117d, "Becton & Dickinson", { - }}, - {0x117e, "T/R Systems", { - }}, - {0x117f, "Integrated Circuit Systems", { - }}, - {0x1180, "Ricoh Co Ltd", { - {0x0466,"RL5C466"}, - }}, - {0x1181, "Telmatics International", { - }}, - {0x1183, "Fujikura Ltd", { - }}, - {0x1184, "Forks Inc", { - }}, - {0x1185, "Dataworld International Ltd", { - }}, - {0x1186, "D-Link System Inc", { - }}, - {0x1187, "Advanced Technology Laboratories, Inc.", { - }}, - {0x1188, "Shima Seiki Manufacturing Ltd.", { - }}, - {0x1189, "Matsushita Electronics Co Ltd", { - }}, - {0x118a, "Hilevel Technology", { - }}, - {0x118b, "Hypertec Pty Limited", { - }}, - {0x118c, "Corollary, Inc", { - {0x0014,"PCIB [C-bus II to PCI bus host bridge chip]"}, - }}, - {0x118d, "BitFlow Inc", { - {0x0001,"n/a [Raptor-PCI framegrabber]"}, - }}, - {0x118e, "Hermstedt GmbH", { - }}, - {0x118f, "Green Logic", { - }}, - {0x1191, "Artop Electronic Corp", { - {0x0004,"ATP8400"}, - {0x0005,"ATP850UF"}, - }}, - {0x1192, "Densan Company Ltd", { - }}, - {0x1193, "Zeitnet Inc.", { - {0x0001,"1221"}, - {0x0002,"1225"}, - }}, - {0x1194, "Toucan Technology", { - }}, - {0x1195, "Ratoc System Inc", { - }}, - {0x1196, "Hytec Electronics Ltd", { - }}, - {0x1197, "Gage Applied Sciences, Inc.", { - }}, - {0x1198, "Lambda Systems Inc", { - }}, - {0x1199, "Attachmate Corporation", { - }}, - {0x119a, "Mind Share, Inc.", { - }}, - {0x119b, "Omega Micro Inc.", { - {0x1221,"82C092G"}, - }}, - {0x119c, "Information Technology Inst.", { - }}, - {0x119d, "Bug, Inc. Sapporo Japan", { - }}, - {0x119e, "Fujitsu Microelectronics Ltd.", { - }}, - {0x119f, "Bull HN Information Systems", { - }}, - {0x11a0, "Convex Computer Corporation", { - }}, - {0x11a1, "Hamamatsu Photonics K.K.", { - }}, - {0x11a2, "Sierra Research and Technology", { - }}, - {0x11a3, "Deuretzbacher GmbH & Co. Eng. KG", { - }}, - {0x11a4, "Barco Graphics NV", { - }}, - {0x11a5, "Microunity Systems Eng. Inc", { - }}, - {0x11a6, "Pure Data Ltd.", { - }}, - {0x11a7, "Power Computing Corp.", { - }}, - {0x11a8, "Systech Corp.", { - }}, - {0x11a9, "InnoSys Inc.", { - }}, - {0x11aa, "Actel", { - }}, - {0x11ab, "Galileo Technology Ltd.", { - {0x0146,"GT-64010"}, - {0x4801,"GT-48001"}, - }}, - {0x11ac, "Canon Information Systems Research Aust.", { - }}, - {0x11ad, "Lite-On Communications Inc", { - {0x0002,"LNE100TX"}, - }}, - {0x11ae, "Aztech System Ltd", { - }}, - {0x11af, "Avid Technology Inc.", { - }}, - {0x11b0, "V3 Semiconductor Inc.", { - {0x0292,"V292PBC [Am29030/40 Bridge]"}, - {0x0960,"V96xPBC"}, - {0xc960,"V96DPC"}, - }}, - {0x11b1, "Apricot Computers", { - }}, - {0x11b2, "Eastman Kodak", { - }}, - {0x11b3, "Barr Systems Inc.", { - }}, - {0x11b4, "Leitch Technology International", { - }}, - {0x11b5, "Radstone Technology Plc", { - }}, - {0x11b6, "United Video Corp", { - }}, - {0x11b8, "XPoint Technologies, Inc", { - }}, - {0x11b9, "Pathlight Technology Inc.", { - }}, - {0x11ba, "Videotron Corp", { - }}, - {0x11bb, "Pyramid Technology", { - }}, - {0x11bc, "Network Peripherals Inc", { - {0x0001,"NP-PCI"}, - }}, - {0x11bd, "Pinnacle Systems Inc.", { - }}, - {0x11be, "International Microcircuits Inc", { - }}, - {0x11bf, "Astrodesign, Inc.", { - }}, - {0x11c0, "Hewlett Packard", { - }}, - {0x11c1, "Lucent Microelectronics", { - {0x0440,"L56xMF"}, - }}, - {0x11c2, "Sand Microelectronics", { - }}, - {0x11c4, "Document Technologies, Inc", { - }}, - {0x11c5, "Shiva Corporation", { - }}, - {0x11c6, "Dainippon Screen Mfg. Co. Ltd", { - }}, - {0x11c7, "D.C.M. Data Systems", { - }}, - {0x11c8, "Dolphin Interconnect Solutions AS", { - {0x0658,"PSB"}, - }}, - {0x11c9, "Magma", { - }}, - {0x11ca, "LSI Systems, Inc", { - }}, - {0x11cb, "Specialix Research Ltd.", { - {0x2000,"PCI_9050"}, - {0x4000,"SUPI_1"}, - {0x8000,"T225"}, - }}, - {0x11cc, "Michels & Kleberhoff Computer GmbH", { - }}, - {0x11cd, "HAL Computer Systems, Inc.", { - }}, - {0x11ce, "Netaccess", { - }}, - {0x11cf, "Pioneer Electronic Corporation", { - }}, - {0x11d0, "Lockheed Martin Federal Systems-Manassas", { - }}, - {0x11d1, "Auravision", { - {0x01f7,"VxP524"}, - }}, - {0x11d2, "Intercom Inc.", { - }}, - {0x11d3, "Trancell Systems Inc", { - }}, - {0x11d4, "Analog Devices", { - }}, - {0x11d5, "Ikon Corporation", { - {0x0115,"10115"}, - {0x0117,"10117"}, - }}, - {0x11d6, "Tekelec Telecom", { - }}, - {0x11d7, "Trenton Technology, Inc.", { - }}, - {0x11d8, "Image Technologies Development", { - }}, - {0x11d9, "TEC Corporation", { - }}, - {0x11da, "Novell", { - }}, - {0x11db, "Sega Enterprises Ltd", { - }}, - {0x11dc, "Questra Corporation", { - }}, - {0x11dd, "Crosfield Electronics Limited", { - }}, - {0x11de, "Zoran Corporation", { - {0x6057,"ZR36057"}, - {0x6120,"ZR36120"}, - }}, - {0x11df, "New Wave PDG", { - }}, - {0x11e0, "Cray Communications A/S", { - }}, - {0x11e1, "GEC Plessey Semi Inc.", { - }}, - {0x11e2, "Samsung Information Systems America", { - }}, - {0x11e3, "Quicklogic Corporation", { - }}, - {0x11e4, "Second Wave Inc", { - }}, - {0x11e5, "IIX Consulting", { - }}, - {0x11e6, "Mitsui-Zosen System Research", { - }}, - {0x11e7, "Toshiba America, Elec. Company", { - }}, - {0x11e8, "Digital Processing Systems Inc.", { - }}, - {0x11e9, "Highwater Designs Ltd.", { - }}, - {0x11ea, "Elsag Bailey", { - }}, - {0x11eb, "Formation Inc.", { - }}, - {0x11ec, "Coreco Inc", { - }}, - {0x11ed, "Mediamatics", { - }}, - {0x11ee, "Dome Imaging Systems Inc", { - }}, - {0x11ef, "Nicolet Technologies B.V.", { - }}, - {0x11f0, "Compu-Shack GmbH", { - }}, - {0x11f1, "Symbios Logic Inc", { - }}, - {0x11f2, "Picture Tel Japan K.K.", { - }}, - {0x11f3, "Keithley Metrabyte", { - }}, - {0x11f4, "Kinetic Systems Corporation", { - {0x2915,"CAMAC controller"}, - }}, - {0x11f5, "Computing Devices International", { - }}, - {0x11f6, "Compex", { - {0x0112,"ENet100VG4"}, - {0x1401,"ReadyLink 2000"}, - }}, - {0x11f7, "Scientific Atlanta", { - }}, - {0x11f8, "PMC-Sierra Inc.", { - {0x7375,"PM7375 [LASAR-155 ATM SAR]"}, - }}, - {0x11f9, "I-Cube Inc", { - }}, - {0x11fa, "Kasan Electronics Company, Ltd.", { - }}, - {0x11fb, "Datel Inc", { - }}, - {0x11fc, "Silicon Magic", { - }}, - {0x11fd, "High Street Consultants", { - }}, - {0x11fe, "Comtrol Corporation", { - {0x0001,"RocketPort 8 Oct"}, - {0x0002,"RocketPort 8 Intf"}, - {0x0003,"RocketPort 16 Intf"}, - {0x0004,"RocketPort 32 Intf"}, - }}, - {0x11ff, "Scion Corporation", { - }}, - {0x1200, "CSS Corporation", { - }}, - {0x1201, "Vista Controls Corp", { - }}, - {0x1202, "Network General Corp.", { - }}, - {0x1203, "Bayer Corporation, Agfa Division", { - }}, - {0x1204, "Lattice Semiconductor Corporation", { - }}, - {0x1205, "Array Corporation", { - }}, - {0x1206, "Amdahl Corporation", { - }}, - {0x1208, "Parsytec GmbH", { - }}, - {0x1209, "SCI Systems Inc", { - }}, - {0x120a, "Synaptel", { - }}, - {0x120b, "Adaptive Solutions", { - }}, - {0x120c, "Technical Corp.", { - }}, - {0x120d, "Compression Labs, Inc.", { - }}, - {0x120e, "Cyclades Corporation", { - {0x0100,"Cyclom_Y"}, - {0x0200,"Cyclom_Z"}, - }}, - {0x120f, "Essential Communications", { - {0x0001,"Roadrunner serial HIPPI"}, - }}, - {0x1210, "Hyperparallel Technologies", { - }}, - {0x1211, "Braintech Inc", { - }}, - {0x1212, "Kingston Technology Corp.", { - }}, - {0x1213, "Applied Intelligent Systems, Inc.", { - }}, - {0x1214, "Performance Technologies, Inc.", { - }}, - {0x1215, "Interware Co., Ltd", { - }}, - {0x1216, "Purup Prepress A/S", { - }}, - {0x1217, "O2 Micro, Inc.", { - {0x6729,"6729"}, - {0x673a,"6730"}, - {0x6832,"6832"}, - }}, - {0x1218, "Hybricon Corp.", { - }}, - {0x1219, "First Virtual Corporation", { - }}, - {0x121a, "3Dfx Interactive, Inc.", { - {0x0001,"Voodoo"}, - {0x0002,"Voodoo2"}, - }}, - {0x121b, "Advanced Telecommunications Modules", { - }}, - {0x121c, "Nippon Texaco., Ltd", { - }}, - {0x121d, "Lippert Automationstechnik GmbH", { - }}, - {0x121e, "CSPI", { - }}, - {0x121f, "Arcus Technology, Inc.", { - }}, - {0x1220, "Ariel Corporation", { - }}, - {0x1221, "Contec Co., Ltd", { - }}, - {0x1222, "Ancor Communications, Inc.", { - }}, - {0x1223, "Heurikon/Computer Products", { - }}, - {0x1224, "Interactive Images", { - }}, - {0x1225, "Power I/O, Inc.", { - }}, - {0x1227, "Tech-Source", { - }}, - {0x1228, "Norsk Elektro Optikk A/S", { - }}, - {0x1229, "Data Kinesis Inc.", { - }}, - {0x122a, "Integrated Telecom", { - }}, - {0x122b, "LG Industrial Systems Co., Ltd", { - }}, - {0x122c, "Sican GmbH", { - }}, - {0x122d, "Aztech System Ltd", { - }}, - {0x122e, "Xyratex", { - }}, - {0x122f, "Andrew Corporation", { - }}, - {0x1230, "Fishcamp Engineering", { - }}, - {0x1231, "Woodward McCoach, Inc.", { - }}, - {0x1232, "GPT Limited", { - }}, - {0x1233, "Bus-Tech, Inc.", { - }}, - {0x1234, "Technical Corp.", { - }}, - {0x1235, "Risq Modular Systems, Inc.", { - }}, - {0x1236, "Sigma Designs Corporation", { - {0x6401,"REALmagic 64/GX (SD 6425)"}, - }}, - {0x1237, "Alta Technology Corporation", { - }}, - {0x1238, "Adtran", { - }}, - {0x1239, "3DO Company", { - }}, - {0x123a, "Visicom Laboratories, Inc.", { - }}, - {0x123b, "Seeq Technology, Inc.", { - }}, - {0x123c, "Century Systems, Inc.", { - }}, - {0x123d, "Engineering Design Team, Inc.", { - }}, - {0x123e, "Simutech, Inc.", { - }}, - {0x123f, "C-Cube Microsystems", { - {0x00e4,"MPEG"}, - }}, - {0x1240, "Marathon Technologies Corp.", { - }}, - {0x1241, "DSC Communications", { - }}, - {0x1243, "Delphax", { - }}, - {0x1244, "AVM Audiovisuelles MKTG & Computer System GmbH", { - }}, - {0x1245, "A.P.D., S.A.", { - }}, - {0x1246, "Dipix Technologies, Inc.", { - }}, - {0x1247, "Xylon Research, Inc.", { - }}, - {0x1248, "Central Data Corporation", { - }}, - {0x1249, "Samsung Electronics Co., Ltd.", { - }}, - {0x124a, "AEG Electrocom GmbH", { - }}, - {0x124b, "SBS/Greenspring Modular I/O", { - }}, - {0x124c, "Solitron Technologies, Inc.", { - }}, - {0x124d, "Stallion Technologies, Inc.", { - {0x0000,"EasyConnection 8/32 - PCI"}, - {0x0002,"EasyConnection 8/64 - PCI"}, - {0x0003,"EasyIO - PCI"}, - }}, - {0x124e, "Cylink", { - }}, - {0x124f, "Infotrend Technology, Inc.", { - }}, - {0x1250, "Hitachi Microcomputer System Ltd", { - }}, - {0x1251, "VLSI Solutions Oy", { - }}, - {0x1253, "Guzik Technical Enterprises", { - }}, - {0x1254, "Linear Systems Ltd.", { - }}, - {0x1255, "Optibase Ltd", { - {0x1110,"MPEG Forge"}, - {0x1210,"MPEG Fusion"}, - {0x2110,"VideoPlex"}, - {0x2120,"VideoPlex CC"}, - {0x2130,"VideoQuest"}, - }}, - {0x1256, "Perceptive Solutions, Inc.", { - }}, - {0x1257, "Vertex Networks, Inc.", { - }}, - {0x1258, "Gilbarco, Inc.", { - }}, - {0x1259, "Allied Telesyn International", { - }}, - {0x125a, "ABB Power Systems", { - }}, - {0x125b, "Asix Electronics Corporation", { - }}, - {0x125c, "Aurora Technologies, Inc.", { - }}, - {0x125d, "ESS Technology", { - }}, - {0x125e, "Specialvideo Engineering SRL", { - }}, - {0x125f, "Concurrent Technologies, Inc.", { - }}, - {0x1260, "Harris Semiconductor", { - }}, - {0x1261, "Matsushita-Kotobuki Electronics Industries, Ltd.", { - }}, - {0x1262, "ES Computer Company, Ltd.", { - }}, - {0x1263, "Sonic Solutions", { - }}, - {0x1264, "Aval Nagasaki Corporation", { - }}, - {0x1265, "Casio Computer Co., Ltd.", { - }}, - {0x1266, "Microdyne Corporation", { - }}, - {0x1267, "S. A. Telecommunications", { - {0x5352,"PCR2101"}, - {0x5a4b,"Telsat Turbo"}, - }}, - {0x1268, "Tektronix", { - }}, - {0x1269, "Thomson-CSF/TTM", { - }}, - {0x126a, "Lexmark International, Inc.", { - }}, - {0x126b, "Adax, Inc.", { - }}, - {0x126c, "Northern Telecom", { - }}, - {0x126d, "Splash Technology, Inc.", { - }}, - {0x126e, "Sumitomo Metal Industries, Ltd.", { - }}, - {0x126f, "Silicon Motion, Inc.", { - }}, - {0x1270, "Olympus Optical Co., Ltd.", { - }}, - {0x1271, "GW Instruments", { - }}, - {0x1272, "Telematics International", { - }}, - {0x1273, "Hughes Network Systems", { - {0x0002,"DirecPC"}, - }}, - {0x1274, "Ensoniq", { - {0x5000,"AudioPCI"}, - }}, - {0x1275, "Network Appliance Corporation", { - }}, - {0x1276, "Switched Network Technologies, Inc.", { - }}, - {0x1277, "Comstream", { - }}, - {0x1278, "Transtech Parallel Systems Ltd.", { - }}, - {0x1279, "Transmeta Corporation", { - }}, - {0x127a, "Rockwell International", { - }}, - {0x127b, "Pixera Corporation", { - }}, - {0x127c, "Crosspoint Solutions, Inc.", { - }}, - {0x127d, "Vela Research", { - }}, - {0x127e, "Winnov, L.P.", { - }}, - {0x127f, "Fujifilm", { - }}, - {0x1280, "Photoscript Group Ltd.", { - }}, - {0x1281, "Yokogawa Electric Corporation", { - }}, - {0x1282, "Davicom Semiconductor, Inc.", { - }}, - {0x1283, "Integrated Technology Express, Inc.", { - }}, - {0x1284, "Sahara Networks, Inc.", { - }}, - {0x1285, "Platform Technologies, Inc.", { - }}, - {0x1286, "Mazet GmbH", { - }}, - {0x1287, "M-Pact, Inc.", { - }}, - {0x1288, "Timestep Corporation", { - }}, - {0x1289, "AVC Technology, Inc.", { - }}, - {0x128a, "Asante Technologies, Inc.", { - }}, - {0x128b, "Transwitch Corporation", { - }}, - {0x128c, "Retix Corporation", { - }}, - {0x128d, "G2 Networks, Inc.", { - }}, - {0x128e, "Samho Multi Tech Ltd.", { - }}, - {0x128f, "Tateno Dennou, Inc.", { - }}, - {0x1290, "Sord Computer Corporation", { - }}, - {0x1291, "NCS Computer Italia", { - }}, - {0x1292, "Tritech Microelectronics Inc", { - }}, - {0x1293, "Media Reality Technology", { - }}, - {0x1294, "Rhetorex, Inc.", { - }}, - {0x1295, "Imagenation Corporation", { - }}, - {0x1296, "Kofax Image Products", { - }}, - {0x1297, "Holco Enterprise Co, Ltd/Shuttle Computer", { - }}, - {0x1298, "Spellcaster Telecommunications Inc.", { - }}, - {0x1299, "Knowledge Technology Lab.", { - }}, - {0x129b, "Image Access", { - }}, - {0x129c, "Jaycor", { - }}, - {0x129d, "Compcore Multimedia, Inc.", { - }}, - {0x129e, "Victor Company of Japan, Ltd.", { - }}, - {0x129f, "OEC Medical Systems, Inc.", { - }}, - {0x12a0, "Allen-Bradley Company", { - }}, - {0x12a1, "Simpact Associates, Inc.", { - }}, - {0x12a2, "Newgen Systems Corporation", { - }}, - {0x12a3, "Lucent Technologies", { - }}, - {0x12a4, "NTT Electronics Technology Company", { - }}, - {0x12a5, "Vision Dynamics Ltd.", { - }}, - {0x12a6, "Scalable Networks, Inc.", { - }}, - {0x12a7, "AMO GmbH", { - }}, - {0x12a8, "News Datacom", { - }}, - {0x12a9, "Xiotech Corporation", { - }}, - {0x12aa, "SDL Communications, Inc.", { - }}, - {0x12ab, "Yuan Yuan Enterprise Co., Ltd.", { - }}, - {0x12ac, "Measurex Corporation", { - }}, - {0x12ad, "Multidata GmbH", { - }}, - {0x12ae, "Alteon Networks Inc.", { - {0x0001,"AceNIC Gigabit Ethernet"}, - }}, - {0x12af, "TDK USA Corp", { - }}, - {0x12b0, "Jorge Scientific Corp", { - }}, - {0x12b1, "GammaLink", { - }}, - {0x12b2, "General Signal Networks", { - }}, - {0x12b3, "Inter-Face Co Ltd", { - }}, - {0x12b4, "FutureTel Inc", { - }}, - {0x12b5, "Granite Systems Inc.", { - }}, - {0x12b6, "Natural Microsystems", { - }}, - {0x12b7, "Cognex Modular Vision Systems Div. - Acumen Inc.", { - }}, - {0x12b8, "Korg", { - }}, - {0x12b9, "US Robotics", { - }}, - {0x12ba, "PMC Sierra", { - }}, - {0x12bb, "Nippon Unisoft Corporation", { - }}, - {0x12bc, "Array Microsystems", { - }}, - {0x12bd, "Computerm Corp.", { - }}, - {0x12be, "Anchor Chips Inc.", { - }}, - {0x12bf, "Fujifilm Microdevices", { - }}, - {0x12c0, "Infimed", { - }}, - {0x12c1, "GMM Research Corp", { - }}, - {0x12c2, "Mentec Limited", { - }}, - {0x12c3, "Holtek Microelectronics Inc", { - }}, - {0x12c4, "Connect Tech Inc", { - }}, - {0x12c5, "Picture Elements Incorporated", { - {0x0081,"PCIVST [PCI Grayscale Thresholding Engine]"}, - }}, - {0x12c6, "Mitani Corporation", { - }}, - {0x12c7, "Dialogic Corp", { - }}, - {0x12c8, "G Force Co, Ltd", { - }}, - {0x12c9, "Gigi Operations", { - }}, - {0x12ca, "Integrated Computing Engines", { - }}, - {0x12cb, "Antex Electronics Corporation", { - }}, - {0x12cc, "Pluto Technologies International", { - }}, - {0x12cd, "Aims Lab", { - }}, - {0x12ce, "Netspeed Inc.", { - }}, - {0x12cf, "Prophet Systems, Inc.", { - }}, - {0x12d0, "GDE Systems, Inc.", { - }}, - {0x12d1, "PSITech", { - }}, - {0x12d2, "NVidia / SGS Thomson (Joint Venture)", { - {0x0018,"Riva128"}, - }}, - {0x12d3, "Vingmed Sound A/S", { - }}, - {0x12d4, "DGM&S", { - }}, - {0x12d5, "Equator Technologies", { - }}, - {0x12d6, "Analogic Corp", { - }}, - {0x12d7, "Biotronic SRL", { - }}, - {0x12d8, "Pericom Semiconductor", { - }}, - {0x12d9, "Aculab PLC", { - }}, - {0x12da, "True Time Inc.", { - }}, - {0x12db, "Annapolis Micro Systems, Inc", { - }}, - {0x12dc, "Symicron Computer Communication Ltd.", { - }}, - {0x12dd, "Management Graphics", { - }}, - {0x12de, "Rainbow Technologies", { - }}, - {0x12df, "SBS Technologies Inc", { - }}, - {0x12e0, "Chase Research", { - }}, - {0x12e1, "Nintendo Co, Ltd", { - }}, - {0x12e2, "Datum Inc. Bancomm-Timing Division", { - }}, - {0x12e3, "Imation Corp - Medical Imaging Systems", { - }}, - {0x12e4, "Brooktrout Technology Inc", { - }}, - {0x12e5, "Apex Semiconductor Inc", { - }}, - {0x12e6, "Cirel Systems", { - }}, - {0x12e7, "Sunsgroup Corporation", { - }}, - {0x12e8, "Crisc Corp", { - }}, - {0x12e9, "GE Spacenet", { - }}, - {0x12ea, "Zuken", { - }}, - {0x12eb, "Aureal Semiconductor", { - }}, - {0x12ec, "3A International, Inc.", { - }}, - {0x12ed, "Optivision Inc.", { - }}, - {0x12ee, "Orange Micro", { - }}, - {0x12ef, "Vienna Systems", { - }}, - {0x12f0, "Pentek", { - }}, - {0x12f1, "Sorenson Vision Inc", { - }}, - {0x12f2, "Gammagraphx, Inc.", { - }}, - {0x12f3, "Radstone Technology", { - }}, - {0x12f4, "Megatel", { - }}, - {0x12f5, "Forks", { - }}, - {0x12f6, "Dawson France", { - }}, - {0x12f7, "Cognex", { - }}, - {0x12f8, "Electronic Design GmbH", { - }}, - {0x12f9, "Four Fold Ltd", { - }}, - {0x12fb, "Spectrum Signal Processing", { - }}, - {0x12fc, "Capital Equipment Corp", { - }}, - {0x12fd, "I2S", { - }}, - {0x12fe, "ESD Electronic System Design GmbH", { - }}, - {0x12ff, "Lexicon", { - }}, - {0x1300, "Harman International Industries Inc", { - }}, - {0x1302, "Computer Sciences Corp", { - }}, - {0x1303, "Innovative Integration", { - }}, - {0x1304, "Juniper Networks", { - }}, - {0x1305, "Netphone, Inc", { - }}, - {0x1306, "Duet Technologies", { - }}, - {0x1307, "Computer Boards", { - {0x0001,"DAS1602/16"}, - }}, - {0x1308, "Jato Technologies Inc.", { - }}, - {0x1309, "AB Semiconductor Ltd", { - }}, - {0x130a, "Mitsubishi Electric Microcomputer", { - }}, - {0x130b, "Colorgraphic Communications Corp", { - }}, - {0x130c, "Ambex Technologies, Inc", { - }}, - {0x130d, "Accelerix Inc", { - }}, - {0x130e, "Yamatake-Honeywell Co. Ltd", { - }}, - {0x130f, "Advanet Inc", { - }}, - {0x1310, "Gespac", { - }}, - {0x1311, "Videoserver, Inc", { - }}, - {0x1312, "Acuity Imaging, Inc", { - }}, - {0x1313, "Yaskawa Electric Co.", { - }}, - {0x1316, "Teradyne Inc", { - }}, - {0x1317, "Bridgecom, Inc", { - }}, - {0x1318, "Packet Engines Inc.", { - }}, - {0x1319, "Fortemedia, Inc", { - }}, - {0x131a, "Finisar Corp.", { - }}, - {0x131c, "Nippon Electro-Sensory Devices Corp", { - }}, - {0x131d, "Sysmic, Inc.", { - }}, - {0x131e, "Xinex Networks Inc", { - }}, - {0x131f, "Siig Inc", { - }}, - {0x1320, "Crypto AG", { - }}, - {0x1321, "Arcobel Graphics BV", { - }}, - {0x1322, "MTT Co., Ltd", { - }}, - {0x1323, "Dome Inc", { - }}, - {0x1324, "Sphere Communications", { - }}, - {0x1325, "Salix Technologies, Inc", { - }}, - {0x1326, "Seachange international", { - }}, - {0x1327, "Voss scientific", { - }}, - {0x1328, "quadrant international", { - }}, - {0x1329, "Productivity Enhancement", { - }}, - {0x132a, "Microcom Inc.", { - }}, - {0x132b, "Broadband Technologies", { - }}, - {0x132c, "Micrel Inc", { - }}, - {0x132d, "Integrated Silicon Solution, Inc.", { - }}, - {0x1330, "MMC Networks", { - }}, - {0x1331, "Radisys Corp.", { - }}, - {0x1332, "Micro Memory", { - }}, - {0x1334, "Redcreek Communications, Inc", { - }}, - {0x1335, "Videomail, Inc", { - }}, - {0x1337, "Third Planet Publishing", { - }}, - {0x1338, "BT Electronics", { - }}, - {0x133a, "Vtel Corp", { - }}, - {0x133b, "Softcom Microsystems", { - }}, - {0x133c, "Holontech Corp", { - }}, - {0x133d, "SS Technologies", { - }}, - {0x133e, "Virtual Computer Corp", { - }}, - {0x133f, "SCM Microsystems", { - }}, - {0x1340, "Atalla Corp", { - }}, - {0x1341, "Kyoto Microcomputer Co", { - }}, - {0x1342, "Promax Systems Inc", { - }}, - {0x1343, "Phylon Communications Inc", { - }}, - {0x1344, "Crucial Technology", { - }}, - {0x1345, "Arescom Inc", { - }}, - {0x1347, "Odetics", { - }}, - {0x1349, "Sumitomo Electric Industries, Ltd.", { - }}, - {0x134a, "DTC Technology Corp.", { - }}, - {0x134b, "ARK Research Corp.", { - }}, - {0x134c, "Chori Joho System Co. Ltd", { - }}, - {0x134d, "PCTel Inc", { - }}, - {0x134e, "CSTI", { - }}, - {0x134f, "Algo System Co Ltd", { - }}, - {0x1350, "Systec Co. Ltd", { - }}, - {0x1351, "Sonix Inc", { - }}, - {0x1353, "Dassault A.T.", { - }}, - {0x1354, "Dwave System Inc", { - }}, - {0x1355, "Kratos Analytical Ltd", { - }}, - {0x1356, "The Logical Co", { - }}, - {0x1359, "Prisa Networks", { - }}, - {0x135a, "Brain Boxes", { - }}, - {0x135b, "Giganet Inc", { - }}, - {0x135c, "Quatech Inc", { - }}, - {0x135d, "ABB Network Partner AB", { - }}, - {0x135e, "Sealevel Systems Inc", { - }}, - {0x135f, "I-Data International A-S", { - }}, - {0x1360, "Meinberg Funkuhren", { - }}, - {0x1361, "Soliton Systems K.K.", { - }}, - {0x1362, "Fujifacom Corporation", { - }}, - {0x1363, "Phoenix Technology Ltd", { - }}, - {0x1364, "ATM Communications Inc", { - }}, - {0x1365, "Hypercope GmbH", { - }}, - {0x1366, "Teijin Seiki Co. Ltd", { - }}, - {0x1367, "Hitachi Zosen Corporation", { - }}, - {0x1368, "Skyware Corporation", { - }}, - {0x1369, "Digigram", { - }}, - {0x136a, "High Soft Tech", { - }}, - {0x136b, "Kawasaki Steel Corporation", { - }}, - {0x136c, "Adtek System Science Co Ltd", { - }}, - {0x136d, "Gigalabs Inc", { - }}, - {0x136f, "Applied Magic Inc", { - }}, - {0x1370, "ATL Products", { - }}, - {0x1371, "CNet Technology Inc", { - }}, - {0x1373, "Silicon Vision Inc", { - }}, - {0x1374, "Silicom Ltd", { - }}, - {0x1375, "Argosystems Inc", { - }}, - {0x1376, "LMC", { - }}, - {0x1377, "Electronic Equipment Production & Distribution GmbH", { - }}, - {0x1378, "Telemann Co. Ltd", { - }}, - {0x1379, "Asahi Kasei Microsystems Co Ltd", { - }}, - {0x137a, "Mark of the Unicorn Inc", { - }}, - {0x137b, "PPT Vision", { - }}, - {0x137c, "Iwatsu Electric Co Ltd", { - }}, - {0x137d, "Dynachip Corporation", { - }}, - {0x137e, "Patriot Scientific Corporation", { - }}, - {0x137f, "Japan Satellite Systems Inc", { - }}, - {0x1380, "Sanritz Automation Co Ltd", { - }}, - {0x1381, "Brains Co. Ltd", { - }}, - {0x1382, "Marian - Electronic & Software", { - }}, - {0x1383, "Controlnet Inc", { - }}, - {0x1384, "Reality Simulation Systems Inc", { - }}, - {0x1385, "Netgear", { - }}, - {0x1386, "Video Domain Technologies", { - }}, - {0x1387, "Systran Corp", { - }}, - {0x1388, "Hitachi Information Technology Co Ltd", { - }}, - {0x1389, "Applicom International", { - }}, - {0x138a, "Fusion Micromedia Corp", { - }}, - {0x138b, "Tokimec Inc", { - }}, - {0x138c, "Silicon Reality", { - }}, - {0x138d, "Future Techno Designs pte Ltd", { - }}, - {0x138e, "Basler GmbH", { - }}, - {0x138f, "Patapsco Designs Inc", { - }}, - {0x1390, "Concept Development Inc", { - }}, - {0x1391, "Development Concepts Inc", { - }}, - {0x1392, "Medialight Inc", { - }}, - {0x1393, "Moxa Technologies Co Ltd", { - }}, - {0x1394, "Level One Communications", { - }}, - {0x1395, "Ambicom Inc", { - }}, - {0x1396, "Cipher Systems Inc", { - }}, - {0x1397, "Cologne Chip Designs GmbH", { - }}, - {0x1398, "Clarion co. Ltd", { - }}, - {0x1399, "Rios systems Co Ltd", { - }}, - {0x139a, "Alacritech Inc", { - }}, - {0x139b, "Mediasonic Multimedia Systems Ltd", { - }}, - {0x139c, "Quantum 3d Inc", { - }}, - {0x139d, "EPL limited", { - }}, - {0x139e, "Media4", { - }}, - {0x139f, "Aethra s.r.l.", { - }}, - {0x13a0, "Crystal Group Inc", { - }}, - {0x13a1, "Kawasaki Heavy Industries Ltd", { - }}, - {0x13a2, "Ositech Communications Inc", { - }}, - {0x13a3, "Hi-Fn", { - }}, - {0x13a4, "Rascom Inc", { - }}, - {0x13a5, "Audio Digital Imaging Inc", { - }}, - {0x13a6, "Videonics Inc", { - }}, - {0x13a7, "Teles AG", { - }}, - {0x13a8, "Exar Corp.", { - }}, - {0x13a9, "Siemens Medical Systems, Ultrasound Group", { - }}, - {0x13aa, "Broadband Networks Inc", { - }}, - {0x13ab, "Arcom Control Systems Ltd", { - }}, - {0x13ac, "Motion Media Technology Ltd", { - }}, - {0x13ad, "Nexus Inc", { - }}, - {0x13ae, "ALD Technology Ltd", { - }}, - {0x13af, "T.Sqware", { - }}, - {0x13b0, "Maxspeed Corp", { - }}, - {0x13b1, "Tamura corporation", { - }}, - {0x13b2, "Techno Chips Co. Ltd", { - }}, - {0x13b3, "Lanart Corporation", { - }}, - {0x13b4, "Wellbean Co Inc", { - }}, - {0x13b5, "ARM", { - }}, - {0x13b6, "Dlog GmbH", { - }}, - {0x13b7, "Logic Devices Inc", { - }}, - {0x13b8, "Nokia Telecommunications oy", { - }}, - {0x13b9, "Elecom Co Ltd", { - }}, - {0x13ba, "Oxford Instruments", { - }}, - {0x13bb, "Sanyo Technosound Co Ltd", { - }}, - {0x13bc, "Bitran Corporation", { - }}, - {0x13bd, "Sharp corporation", { - }}, - {0x13be, "Miroku Jyoho Service Co. Ltd", { - }}, - {0x13bf, "Sharewave Inc", { - }}, - {0x13c0, "Microgate Corporation", { - }}, - {0x13c1, "3ware Inc", { - }}, - {0x13c2, "Technotrend Systemtechnik GmbH", { - }}, - {0x13c3, "Janz Computer AG", { - }}, - {0x13c4, "Phase Metrics", { - }}, - {0x13c5, "Alphi Technology Corp", { - }}, - {0x13c6, "Condor Engineering Inc", { - }}, - {0x13c7, "Blue Chip Technology Ltd", { - }}, - {0x13c8, "Apptech Inc", { - }}, - {0x13c9, "Eaton Corporation", { - }}, - {0x13ca, "Iomega Corporation", { - }}, - {0x13cb, "Yano Electric Co Ltd", { - }}, - {0x13cc, "Metheus Corporation", { - }}, - {0x13cd, "Compatible Systems Corporation", { - }}, - {0x13ce, "Cocom A/S", { - }}, - {0x13cf, "Studio Audio & Video Ltd", { - }}, - {0x13d0, "Techsan Electronics Co Ltd", { - }}, - {0x13d1, "Abocom Systems Inc", { - }}, - {0x13d2, "Shark Multimedia Inc", { - }}, - {0x13d3, "IMC Networks", { - }}, - {0x13d4, "Graphics Microsystems Inc", { - }}, - {0x13d5, "Media 100 Inc", { - }}, - {0x13d6, "K.I. Technology Co Ltd", { - }}, - {0x13d7, "Toshiba Engineering Corporation", { - }}, - {0x13d8, "Phobos corporation", { - }}, - {0x13d9, "Apex PC Solutions Inc", { - }}, - {0x13da, "Intresource Systems pte Ltd", { - }}, - {0x13db, "Janich & Klass Computertechnik GmbH", { - }}, - {0x13dc, "Netboost Corporation", { - }}, - {0x13dd, "Multimedia Bundle Inc", { - }}, - {0x13de, "ABB Robotics Products AB", { - }}, - {0x13df, "E-Tech Inc", { - }}, - {0x13e0, "GVC Corporation", { - }}, - {0x13e1, "Silicom Multimedia Systems Inc", { - }}, - {0x13e2, "Dynamics Research Corporation", { - }}, - {0x13e3, "Nest Inc", { - }}, - {0x13e4, "Calculex Inc", { - }}, - {0x13e5, "Telesoft Design Ltd", { - }}, - {0x13e6, "Argosy research Inc", { - }}, - {0x13e7, "NAC Incorporated", { - }}, - {0x13e8, "Chip Express Corporation", { - }}, - {0x13e9, "Chip Express Corporation", { - }}, - {0x13ea, "Dallas Semiconductor", { - }}, - {0x13eb, "Hauppauge Computer Works Inc", { - }}, - {0x13ec, "Zydacron Inc", { - }}, - {0x13ed, "Raytheion E-Systems", { - }}, - {0x13ee, "Hayes Microcomputer Products Inc", { - }}, - {0x13ef, "Coppercom Inc", { - }}, - {0x13f0, "Sundance technology Inc", { - }}, - {0x13f1, "Oce' - Technologies B.V.", { - }}, - {0x13f2, "Ford Microelectronics Inc", { - }}, - {0x13f3, "Mcdata Corporation", { - }}, - {0x13f4, "Troika Design Inc", { - }}, - {0x13f5, "Kansai Electric Co. Ltd", { - }}, - {0x13f6, "C-Media Electronics Inc", { - }}, - {0x13f7, "Wildfire Communications", { - }}, - {0x13f8, "Ad Lib Multimedia Inc", { - }}, - {0x13f9, "NTT Advanced Technology Corp.", { - }}, - {0x13fa, "Pentland Systems Ltd", { - }}, - {0x13fb, "Aydin Corp", { - }}, - {0x13fc, "Computer Peripherals International", { - }}, - {0x13fd, "Micro Science Inc", { - }}, - {0x13fe, "Advantech Co. Ltd", { - }}, - {0x13ff, "Silicon Spice Inc", { - }}, - {0x1400, "Artx Inc", { - }}, - {0x1401, "CR-Systems A/S", { - }}, - {0x1402, "Meilhaus Electronic GmbH", { - }}, - {0x1403, "Ascor Inc", { - }}, - {0x1404, "Fundamental Software Inc", { - }}, - {0x1405, "Excalibur Systems Inc", { - }}, - {0x1406, "Oce' Printing Systems GmbH", { - }}, - {0x1407, "Lava Computer mfg Inc", { - }}, - {0x1408, "Aloka Co. Ltd", { - }}, - {0x1409, "Timedia Technology Co Ltd", { - }}, - {0x140a, "DSP Research Inc", { - }}, - {0x140b, "Ramix Inc", { - }}, - {0x140c, "Elmic Systems Inc", { - }}, - {0x140d, "Matsushita Electric Works Ltd", { - }}, - {0x140e, "Goepel Electronic GmbH", { - }}, - {0x140f, "Salient Systems Corp", { - }}, - {0x1410, "Midas lab Inc", { - }}, - {0x1411, "Ikos Systems Inc", { - }}, - {0x1412, "IC Ensemble Inc", { - }}, - {0x1413, "Addonics", { - }}, - {0x1414, "Microsoft Corporation", { - }}, - {0x1415, "Oxford Semiconductor Ltd", { - }}, - {0x1416, "Multiwave Innovation pte Ltd", { - }}, - {0x1417, "Convergenet Technologies Inc", { - }}, - {0x1418, "Kyushu electronics systems Inc", { - }}, - {0x1419, "Excel Switching Corp", { - }}, - {0x141a, "Apache Micro Peripherals Inc", { - }}, - {0x141b, "Zoom Telephonics Inc", { - }}, - {0x141d, "Digitan Systems Inc", { - }}, - {0x141e, "Fanuc Ltd", { - }}, - {0x141f, "Visiontech Ltd", { - }}, - {0x1420, "Psion Dacom plc", { - }}, - {0x1421, "Ads Technologies Inc", { - }}, - {0x1422, "Ygrec Systems Co Ltd", { - }}, - {0x1423, "Custom Technology Corp.", { - }}, - {0x1424, "Videoserver Connections", { - }}, - {0x1425, "ASIC Designers Inc", { - }}, - {0x1426, "Storage Technology Corp.", { - }}, - {0x1427, "Better On-Line Solutions", { - }}, - {0x1428, "Edec Co Ltd", { - }}, - {0x1429, "Unex Technology Corp.", { - }}, - {0x142a, "Kingmax Technology Inc", { - }}, - {0x142b, "Radiolan", { - }}, - {0x142c, "Minton Optic Industry Co Ltd", { - }}, - {0x142d, "Pix stream Inc", { - }}, - {0x142e, "Vitec Multimedia", { - }}, - {0x142f, "Radicom Research Inc", { - }}, - {0x1430, "ITT Aerospace/Communications Division", { - }}, - {0x1431, "Gilat Satellite Networks", { - }}, - {0x1432, "Edimax Computer Co.", { - }}, - {0x1433, "Eltec Elektronik GmbH", { - }}, - {0x1435, "Real Time Devices US Inc.", { - }}, - {0x1436, "CIS Technology Inc", { - }}, - {0x1668, "Action Tec Electronics Inc", { - }}, - {0x1b13, "Jaton Corp", { - }}, - {0x1c1c, "Symphony", { - {0x0001,"82C101"}, - }}, - {0x21c3, "21st Century Computer Corp.", { - }}, - {0x270b, "Xantel Corporation", { - }}, - {0x270f, "Chaintech Computer Co. Ltd", { - }}, - {0x3388, "Hint Corp", { - }}, - {0x3d3d, "3DLabs", { - {0x0001,"GLINT 300SX"}, - {0x0002,"GLINT 500TX"}, - {0x0003,"GLINT Delta"}, - {0x0004,"Permedia"}, - {0x0006,"GLINT MX"}, - }}, - {0x4005, "Avance Logic Inc.", { - {0x2064,"ALG2064i"}, - {0x2301,"ALG2301"}, - {0x2302,"ALG2302"}, - }}, - {0x4444, "Internext Compression Inc", { - }}, - {0x4680, "Umax Computer Corp", { - }}, - {0x4843, "Hercules Computer Technology Inc", { - }}, - {0x4978, "Axil Computer Inc", { - }}, - {0x4a14, "NetVin", { - {0x5000,"PCI NV5000SC"}, - }}, - {0x4ddc, "ILC Data Device Corp", { - }}, - {0x5053, "Voyetra Technologies", { - }}, - {0x5143, "Qualcomm Inc", { - }}, - {0x5333, "S3 Inc.", { - {0x0551,"Plato/PX (system)"}, - {0x5631,"86C325 [ViRGE]"}, - {0x8810,"86C764_0 [Trio 32 vers 0]"}, - {0x8811,"86C764_1 [Trio 32/64 vers 1]"}, - {0x8812,"Aurora64V+"}, - {0x8813,"86C764_3 [Trio 32/64 vers 3]"}, - {0x8814,"Trio64UV+"}, - {0x8815,"Aurora128"}, - {0x883d,"ViRGE/VX"}, - {0x8880,"Vision 868 vers 0"}, - {0x8881,"Vision 868 vers 1"}, - {0x8882,"Vision 868 vers 2"}, - {0x8883,"Vision 868 vers 3"}, - {0x88b0,"Vision 928 vers 0"}, - {0x88b1,"Vision 928 vers 1"}, - {0x88b2,"Vision 928 vers 2"}, - {0x88b3,"Vision 928 vers 3"}, - {0x88c0,"Vision 864 vers 0"}, - {0x88c1,"Vision 864 vers 1"}, - {0x88c2,"86C864"}, - {0x88c3,"86C864"}, - {0x88d0,"Vision 964 vers 0"}, - {0x88d1,"Vision 964 vers 1"}, - {0x88d2,"86C964"}, - {0x88d3,"86C964"}, - {0x88f0,"Vision 968"}, - {0x88f1,"86C968"}, - {0x88f2,"86C968"}, - {0x88f3,"86C968"}, - {0x8901,"Trio64V2/DX or /GX"}, - {0x8902,"Plato/PX (graphics)"}, - {0x8a01,"ViRGE/DX or /GX"}, - {0x8a10,"ViRGE/GX2"}, - {0x8c01,"ViRGE/MX"}, - {0x8c02,"ViRGE/MX+"}, - {0x8c03,"ViRGE/MX+MV"}, - {0xca00,"SonicVibes"}, - }}, - {0x5555, "Genroco, Inc", { - {0x0003,"TURBOstor HFP-832 [HiPPI NIC]"}, - }}, - {0x6374, "c't Magazin f€r Computertechnik", { - {0x6773,"GPPCI"}, - }}, - {0x6666, "Decision Computer International Co.", { - }}, - {0x8008, "Quancm Electronic GmbH", { - {0x0010,"WDOG1 [PCI-Watchdog 1]"}, - {0x0011,"PWDOG2 [Watchdog2/PCI]"}, - }}, - {0x8086, "Intel Corporation", { - {0x0482,"82375EB"}, - {0x0483,"82424ZX [Saturn]"}, - {0x0484,"82378IB [SIO ISA Bridge]"}, - {0x0486,"82430ZX [Aries]"}, - {0x04a3,"82434LX [Mercury/Neptune]"}, - {0x0960,"80960RP [i960 RP Microprocessor/Bridge]"}, - {0x1221,"82092AA_0"}, - {0x1222,"82092AA_1"}, - {0x1223,"SAA7116"}, - {0x1226,"82596"}, - {0x1227,"82865"}, - {0x1228,"82556"}, - {0x1229,"82557"}, - {0x122d,"430FX - 82437FX TSC [Triton I]"}, - {0x122e,"82371FB PIIX ISA [Triton I]"}, - {0x1230,"82371FB PIIX IDE [Triton I]"}, - {0x1234,"430MX - 82371MX MPIIX [430MX PCIset - 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX)]"}, - {0x1235,"430MX - 82437MX MTSC [430MX PCIset - 82437MX Mobile System Controller (MTSC) and 82438MX Mobile Data Path (MTDP)]"}, - {0x1237,"440FX - 82441FX PMC [Natoma]"}, - {0x124b,"82380FB"}, - {0x1250,"430HX - 82439HX TXC [Triton II]"}, - {0x1960,"80960RP [i960RP Microprocessor]"}, - {0x7000,"82371SB PIIX3 ISA [Natoma/Triton II]"}, - {0x7010,"82371SB PIIX3 IDE [Natoma/Triton II]"}, - {0x7020,"82371SB PIIX3 USB [Natoma/Triton II]"}, - {0x7030,"430VX - 82437VX TVX [Triton VX]"}, - {0x7100,"430TX - 82439TX MTXC"}, - {0x7110,"82371AB PIIX4 ISA"}, - {0x7111,"82371AB PIIX4 IDE"}, - {0x7112,"82371AB PIIX4 USB"}, - {0x7113,"82371AB PIIX4 ACPI"}, - {0x7180,"440LX - 82443LX PAC Host"}, - {0x7181,"440LX - 82443LX PAC AGP"}, - {0x7190,"440BX - 82443BX Host"}, - {0x7191,"440BX - 82443BX AGP"}, - {0x7192,"440BX - 82443BX (AGP disabled)"}, - {0x7800,"i740"}, - {0x84c4,"82450KX [Orion]"}, - {0x84c5,"82450GX [Orion]"}, - }}, - {0x8800, "Trigem Computer Inc.", { - }}, - {0x8888, "Silicon Magic", { - }}, - {0x8e0e, "Computone Corporation", { - }}, - {0x8e2e, "KTI", { - {0x3000,"ET32P2"}, - }}, - {0x9004, "Adaptec", { - {0x1078,"AIC-7810"}, - {0x5078,"AIC-7850"}, - {0x5178,"7851"}, - {0x5278,"7852"}, - {0x5575,"2930"}, - {0x5578,"AIC-7855"}, - {0x5800,"AIC-5800"}, - {0x6075,"AIC-1480"}, - {0x6078,"AIC-7860"}, - {0x6178,"AIC-7861"}, - {0x6278,"AIC-7860"}, - {0x6378,"AIC-7860"}, - {0x7078,"AIC-7870"}, - {0x7178,"AIC-7871"}, - {0x7278,"AIC-7872"}, - {0x7378,"AIC-7873"}, - {0x7478,"AIC-7874 [AHA-2944]"}, - {0x7578,"7875"}, - {0x7678,"7876"}, - {0x7895,"AIC-7895"}, - {0x8078,"AIC-7880U"}, - {0x8178,"AIC-7881U"}, - {0x8278,"AIC-7882U"}, - {0x8378,"AIC-7883U"}, - {0x8478,"AIC-7884U"}, - {0x8578,"7885"}, - {0x8678,"7886"}, - {0x8b78,"ABA-1030"}, - }}, - {0x907f, "Atronics", { - {0x2015,"IDE-2015PL"}, - }}, - {0x9412, "Holtek", { - {0x6565,"6565"}, - }}, - {0xa200, "NEC Corporation", { - }}, - {0xa259, "Hewlett Packard", { - }}, - {0xa25b, "Hewlett Packard GmbH PL24-MKT", { - }}, - {0xa304, "Sony", { - }}, - {0xa727, "3Com Corporation", { - }}, - {0xaa42, "Scitex Digital Video", { - }}, - {0xb1b3, "Shiva Europe Limited", { - }}, - {0xc001, "TSI Telsys", { - }}, - {0xc0a9, "Micron/Crucial Technology", { - }}, - {0xc0de, "Motorola", { - }}, - {0xc0fe, "Motion Engineering, Inc.", { - }}, - {0xcafe, "Chrysalis-ITS", { - }}, - {0xd4d4, "Dy4 Systems Inc", { - }}, - {0xe159, "Tiger Jet Network Inc.", { - {0x0001,"300"}, - }}, - {0xecc0, "Echo Corporation", { - }}, - {0xedd8, "ARK Logic Inc", { - {0xa091,"1000PV [Stingray]"}, - {0xa099,"2000PV [Stingray]"}, - {0xa0a1,"2000MT"}, - {0xa0a9,"2000MI"}, - }}, -}; - diff --git a/os/pc/pcmciamodem.c b/os/pc/pcmciamodem.c deleted file mode 100644 index 800f406c..00000000 --- a/os/pc/pcmciamodem.c +++ /dev/null @@ -1,75 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" -#include "../port/error.h" - -/* - * PCMCIA modem. - * By default, this will set it up with the port and irq of - * COM2 unless a serialx=type=com line is found in plan9.ini. - * The assumption is that a laptop with a pcmcia will have only - * one com port. - */ - -enum { - Maxcard= 8, -}; - -static char* modems[] = { - "IBM 33.6 Data/Fax/Voice Modem", - "CM-56G", /* Xircom CreditCard Modem 56 - GlobalACCESS */ - "KeepInTouch", - "CEM56", - "MONTANA V.34 FAX/MODEM", /* Motorola */ - "REM10", - "GSM/GPRS", - "AirCard 555", - "Gold Card Global", /* Psion V90 Gold card */ - "Merlin UMTS Modem", /* Novatel card */ - 0, -}; - -void -pcmciamodemlink(void) -{ - ISAConf isa; - int i, j, slot, com2used, usingcom2; - - i = 0; - com2used = 0; - for(j = 0; modems[j]; j++){ - memset(&isa, 0, sizeof(isa)); - - /* look for a configuration line */ - for(; i < Maxcard; i++){ - if(isaconfig("serial", i, &isa)) - if(cistrcmp(isa.type, "com") == 0) - break; - memset(&isa, 0, sizeof(isa)); - } - - usingcom2 = 0; - if (isa.irq == 0 && isa.port == 0) { - if (com2used == 0) { - /* default is COM2 */ - isa.irq = 3; - isa.port = 0x2F8; - usingcom2 = 1; - } else - break; - } - slot = pcmspecial(modems[j], &isa); - if(slot >= 0){ - if(usingcom2) - com2used = 1; - if(ioalloc(isa.port, 8, 0, modems[j]) < 0) - print("%s port %lux already in use\n", modems[j], isa.port); - print("%s in pcmcia slot %d port 0x%lux irq %d\n", - modems[j], slot, isa.port, isa.irq); - } - } -} diff --git a/os/pc/piix4smbus.c b/os/pc/piix4smbus.c deleted file mode 100644 index ced41001..00000000 --- a/os/pc/piix4smbus.c +++ /dev/null @@ -1,213 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -// -// SMBus support for the PIIX4 -// -enum -{ - IntelVendID= 0x8086, - Piix4PMID= 0x7113, /* PIIX4 power management function */ - - // SMBus configuration registers (function 3) - SMBbase= 0x90, // 4 byte base address (bit 0 == 1, bit 3:1 == 0) - SMBconfig= 0xd2, - SMBintrselect= (7<<1), - SMIenable= (0<<1), // interrupts sent to SMI# - IRQ9enable= (4<<1), // intettupts sent to IRQ9 - SMBenable= (1<<0), // 1 enables - - // SMBus IO space registers - Hoststatus= 0x0, // (writing 1 bits reset the interrupt bits) - Failed= (1<<4), // transaction terminated by KILL - Bus_error= (1<<3), // transactio collision - Dev_error= (1<<2), // device error interrupt - Host_complete= (1<<1), // host command completion interrupt - Host_busy= (1<<0), // - Slavestatus= 0x1, // (writing 1 bits reset) - Alert_sts= (1<<5), // someone asserted SMBALERT# - Shdw2_sts= (1<<4), // slave accessed shadow 2 port - Shdw1_sts= (1<<3), // slave accessed shadow 1 port - Slv_sts= (1<<2), // slave accessed shadow 1 port - Slv_bsy= (1<<0), - Hostcontrol= 0x2, - Start= (1<<6), // start execution - Cmd_prot= (7<<2), // command protocol mask - Quick= (0<<2), // address only - Byte= (1<<2), // address + cmd - ByteData= (2<<2), // address + cmd + data - WordData= (3<<2), // address + cmd + data + data - Kill= (1<<1), // abort in progress command - Ienable= (1<<0), // enable completion interrupts - Hostcommand= 0x3, - Hostaddress= 0x4, - AddressMask= (0x7f<<1), // target address - Read= (1<<0), // 1 == read, 0 == write - Hostdata0= 0x5, - Hostdata1= 0x6, - Blockdata= 0x7, - Slavecontrol= 0x8, - Alert_en= (1<<3), // enable inter on SMBALERT# - Shdw2_en= (1<<2), // enable inter on external shadow 2 access - Shdw1_en= (1<<1), // enable inter on external shadow 1 access - Slv_en= (1<<0), // enable inter on access of host ctlr slave port - Shadowcommand= 0x9, - Slaveevent= 0xa, - Slavedata= 0xc, -}; - -static struct -{ - int rw; - int cmd; - int len; - int proto; -} proto[] = -{ - [SMBquick] { 0, 0, 0, Quick }, - [SMBsend] { 0, 1, 0, Byte }, - [SMBbytewrite] { 0, 1, 1, ByteData }, - [SMBwordwrite] { 0, 1, 2, WordData }, - [SMBrecv] { Read, 0, 1, Byte }, - [SMBbyteread] { Read, 1, 1, ByteData }, - [SMBwordread] { Read, 1, 2, WordData }, -}; - -static void -transact(SMBus *s, int type, int addr, int cmd, uchar *data) -{ - int tries, status; - char err[256]; - - if(type < 0 || type > nelem(proto)) - panic("piix4smbus: illegal transaction type %d", type); - - if(waserror()){ - qunlock(s); - nexterror(); - } - qlock(s); - - // wait a while for the host interface to be available - for(tries = 0; tries < 1000000; tries++){ - if((inb(s->base+Hoststatus) & Host_busy) == 0) - break; - sched(); - } - if(tries >= 1000000){ - // try aborting current transaction - outb(s->base+Hostcontrol, Kill); - for(tries = 0; tries < 1000000; tries++){ - if((inb(s->base+Hoststatus) & Host_busy) == 0) - break; - sched(); - } - if(tries >= 1000000){ - snprint(err, sizeof(err), "SMBus jammed: %2.2ux", inb(s->base+Hoststatus)); - error(err); - } - } - - // set up for transaction - outb(s->base+Hostaddress, (addr<<1)|proto[type].rw); - if(proto[type].cmd) - outb(s->base+Hostcommand, cmd); - if(proto[type].rw != Read){ - switch(proto[type].len){ - case 2: - outb(s->base+Hostdata1, data[1]); - // fall through - case 1: - outb(s->base+Hostdata0, data[0]); - break; - } - } - - - // reset the completion/error bits and start transaction - outb(s->base+Hoststatus, Failed|Bus_error|Dev_error|Host_complete); - outb(s->base+Hostcontrol, Start|proto[type].proto); - - // wait for completion - status = 0; - for(tries = 0; tries < 1000000; tries++){ - status = inb(s->base+Hoststatus); - if(status & (Failed|Bus_error|Dev_error|Host_complete)) - break; - sched(); - } - if((status & Host_complete) == 0){ - snprint(err, sizeof(err), "SMBus request failed: %2.2ux", status); - error(err); - } - - // get results - if(proto[type].rw == Read){ - switch(proto[type].len){ - case 2: - data[1] = inb(s->base+Hostdata1); - // fall through - case 1: - data[0] = inb(s->base+Hostdata0); - break; - } - } - qunlock(s); - poperror(); -} - -static SMBus smbusproto = -{ - .transact = transact, -}; - -// -// return 0 if this is a piix4 with an smbus interface -// -SMBus* -piix4smbus(void) -{ - Pcidev *p; - static SMBus *s; - - if(s != nil) - return s; - - p = pcimatch(nil, IntelVendID, Piix4PMID); - if(p == nil) - return nil; - - s = smalloc(sizeof(*s)); - memmove(s, &smbusproto, sizeof(*s)); - s->arg = p; - - // disable the smbus - pcicfgw8(p, SMBconfig, IRQ9enable|0); - - // see if bios gave us a viable port space - s->base = pcicfgr32(p, SMBbase) & ~1; -print("SMB base from bios is 0x%lux\n", s->base); - if(ioalloc(s->base, 0xd, 0, "piix4smbus") < 0){ - s->base = ioalloc(-1, 0xd, 2, "piix4smbus"); - if(s->base < 0){ - free(s); - print("piix4smbus: can't allocate io port\n"); - return nil; - } -print("SMB base ialloc is 0x%lux\n", s->base); - pcicfgw32(p, SMBbase, s->base|1); - } - - // disable SMBus interrupts, abort any transaction in progress - outb(s->base+Hostcontrol, Kill); - outb(s->base+Slavecontrol, 0); - - // enable the smbus - pcicfgw8(p, SMBconfig, IRQ9enable|SMBenable); - - return s; -} diff --git a/os/pc/pix b/os/pc/pix deleted file mode 100644 index 2fa7639b..00000000 --- a/os/pc/pix +++ /dev/null @@ -1,156 +0,0 @@ -dev - root - cons - arch - env - mnt - pipe - prog - rtc - srv - dup - ssl - cap - -# draw screen vga vgax cga -# pointer -# vga - - ip bootp ip ipv6 ipaux iproute arp netlog ptclbsum386 iprouter plan9 nullmedium pktmedium - ether netif netaux - - sd - ds - uart - floppy dma - tinyfs -# mouse -# dbg x86break - -ip - il - tcp - udp - rudp - gre - ipifc - icmp - icmp6 - ipmux -lib - interp - keyring - sec - mp -# draw -# memlayer -# memdraw -# tk - math - kern - -link -# ps2mouse - ether82557 pci - ethermedium - loopbackmedium - netdevmedium - -misc -# vgaclgd542x -# vgas3 +cur vgasavage -# cga - sdata pci sdscsi - - uarti8250 - -mod - sys -# draw -# tk - keyring - crypt - ipints - - math - -init - soeinit # it will do - -code - int kernel_pool_pcnt = 10; - int main_pool_pcnt = 40; - int heap_pool_pcnt = 20; - int image_pool_pcnt = 0; - int cflag=0; - int swcursor=0; - int consoleprint=0; - void screeninit(void){} - -port - alarm - alloc - allocb - chan - dev - dial - dis - discall - exception - exportfs - inferno - latin1 - nocache - nodynld - parse - pgrp - print - proc - qio - qlock - random - sysfile - taslock - xalloc - -root - /chan - /dev - /dis - /env - /fd / - /n - /n/remote - /net - /nvfs - /prog - /dis/lib - /dis/svc - /dis/wm - /osinit.dis - /dis/sh.dis - /dis/ls.dis - /dis/cat.dis - /dis/bind.dis - /dis/mount.dis - /dis/pwd.dis - /dis/echo.dis - /dis/cd.dis - /dis/lib/bufio.dis - /dis/lib/string.dis - /dis/lib/readdir.dis - /dis/lib/workdir.dis - /dis/lib/daytime.dis - /dis/lib/auth.dis - /dis/lib/ssl.dis - /dis/lib/filepat.dis - -# kfs - /dis/disk/kfs.dis - /dis/lib/arg.dis - /dis/lib/daytime.dis - /dis/lib/string.dis - /dis/lib/styx.dis - -# auth - /nvfs/default /usr/inferno/keyring/default diff --git a/os/pc/ps2mouse.c b/os/pc/ps2mouse.c deleted file mode 100644 index 49654bad..00000000 --- a/os/pc/ps2mouse.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "io.h" - -/* - * mouse types - */ -enum -{ - Mouseother= 0, - Mouseserial= 1, - MousePS2= 2, -}; - -static int mousetype; - -/* - * ps/2 mouse message is three bytes - * - * byte 0 - 0 0 SDY SDX 1 M R L - * byte 1 - DX - * byte 2 - DY - * - * shift & left button is the same as middle button - */ -static void -ps2mouseputc(int c, int shift) -{ - static short msg[3]; - static int nb; - static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 5, 2, 3, 6, 7 }; - int buttons, dx, dy; - - /* - * check byte 0 for consistency - */ - if(nb==0 && (c&0xc8)!=0x08) - return; - - msg[nb] = c; - if(++nb == 3){ - nb = 0; - if(msg[0] & 0x10) - msg[1] |= 0xFF00; - if(msg[0] & 0x20) - msg[2] |= 0xFF00; - - buttons = b[(msg[0]&7) | (shift ? 8 : 0)]; - dx = msg[1]; - dy = -msg[2]; - mousetrack(buttons, dx, dy, 1); - } - return; -} - -/* - * set up a ps2 mouse - */ -static void -ps2mouse(void) -{ - if(mousetype == MousePS2) - return; - - i8042auxenable(ps2mouseputc); - /* make mouse streaming, enabled */ - i8042auxcmd(0xEA); - i8042auxcmd(0xF4); - - mousetype = MousePS2; -} - -void -ps2mouselink(void) -{ - /* - * hack - */ - ps2mouse(); -} diff --git a/os/pc/ptclbsum386.s b/os/pc/ptclbsum386.s deleted file mode 100644 index ba0a6a4d..00000000 --- a/os/pc/ptclbsum386.s +++ /dev/null @@ -1,126 +0,0 @@ -TEXT ptclbsum(SB), $0 - MOVL addr+0(FP), SI - MOVL len+4(FP), CX - - XORL AX, AX /* sum */ - - TESTL $1, SI /* byte aligned? */ - MOVL SI, DI - JEQ _2align - - DECL CX - JLT _return - - MOVB 0x00(SI), AH - INCL SI - -_2align: - TESTL $2, SI /* word aligned? */ - JEQ _32loop - - CMPL CX, $2 /* less than 2 bytes? */ - JLT _1dreg - SUBL $2, CX - - XORL BX, BX - MOVW 0x00(SI), BX - ADDL BX, AX - ADCL $0, AX - LEAL 2(SI), SI - -_32loop: - CMPL CX, $0x20 - JLT _8loop - - MOVL CX, BP - SHRL $5, BP - ANDL $0x1F, CX - -_32loopx: - MOVL 0x00(SI), BX - MOVL 0x1C(SI), DX - ADCL BX, AX - MOVL 0x04(SI), BX - ADCL DX, AX - MOVL 0x10(SI), DX - ADCL BX, AX - MOVL 0x08(SI), BX - ADCL DX, AX - MOVL 0x14(SI), DX - ADCL BX, AX - MOVL 0x0C(SI), BX - ADCL DX, AX - MOVL 0x18(SI), DX - ADCL BX, AX - LEAL 0x20(SI), SI - ADCL DX, AX - - DECL BP - JNE _32loopx - - ADCL $0, AX - -_8loop: - CMPL CX, $0x08 - JLT _2loop - - MOVL CX, BP - SHRL $3, BP - ANDL $0x07, CX - -_8loopx: - MOVL 0x00(SI), BX - ADCL BX, AX - MOVL 0x04(SI), DX - ADCL DX, AX - - LEAL 0x08(SI), SI - DECL BP - JNE _8loopx - - ADCL $0, AX - -_2loop: - CMPL CX, $0x02 - JLT _1dreg - - MOVL CX, BP - SHRL $1, BP - ANDL $0x01, CX - -_2loopx: - MOVWLZX 0x00(SI), BX - ADCL BX, AX - - LEAL 0x02(SI), SI - DECL BP - JNE _2loopx - - ADCL $0, AX - -_1dreg: - TESTL $1, CX /* 1 byte left? */ - JEQ _fold - - XORL BX, BX - MOVB 0x00(SI), BX - ADDL BX, AX - ADCL $0, AX - -_fold: - MOVL AX, BX - SHRL $16, BX - JEQ _swab - - ANDL $0xFFFF, AX - ADDL BX, AX - JMP _fold - -_swab: - TESTL $1, addr+0(FP) - /*TESTL $1, DI*/ - JNE _return - XCHGB AH, AL - -_return: - RET diff --git a/os/pc/screen.c b/os/pc/screen.c deleted file mode 100644 index e879b050..00000000 --- a/os/pc/screen.c +++ /dev/null @@ -1,410 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" -#include "../port/error.h" - -#include -#include -#include -#include "screen.h" - -#define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19) - -Point ZP = {0, 0}; - -Rectangle physgscreenr; -Cursorinfo cursor; /* TO DO */ - -Memdata gscreendata; -Memimage *gscreen; - -VGAscr vgascreen[1]; - -Cursor arrow = { - { -1, -1 }, - { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04, - 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04, - 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40, - }, - { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0, - 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8, - 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8, - 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00, - }, -}; - -int -screensize(int x, int y, int z, ulong chan) -{ - VGAscr *scr; - - memimageinit(); - scr = &vgascreen[0]; - - /* - * BUG: need to check if any xalloc'ed memory needs to - * be given back if aperture is set. - */ - if(scr->aperture == 0){ - int width = (x*z)/BI2WD; - - gscreendata.bdata = xalloc(width*BY2WD*y); - if(gscreendata.bdata == 0) - error("screensize: vga soft memory"); -/* memset(gscreendata.bdata, 0x72, width*BY2WD*y); /* not really black */ - scr->useflush = 1; - scr->aperture = VGAMEM(); - scr->apsize = 1<<16; - } - else - gscreendata.bdata = KADDR(scr->aperture); - - if(gscreen) - freememimage(gscreen); - - gscreen = allocmemimaged(Rect(0,0,x,y), chan, &gscreendata); - vgaimageinit(chan); - if(gscreen == nil) - return -1; - - if(scr->dev && scr->dev->flush) - scr->useflush = 1; - - scr->palettedepth = 6; /* default */ - scr->gscreendata = &gscreendata; - scr->memdefont = getmemdefont(); - scr->gscreen = gscreen; - - physgscreenr = gscreen->r; - - drawcmap(); - return 0; -} - -int -screenaperture(int size, int align) -{ - VGAscr *scr; - ulong aperture; - - scr = &vgascreen[0]; - - if(size == 0){ - if(scr->aperture && scr->isupamem) - upafree(scr->aperture, scr->apsize); - scr->aperture = 0; - scr->isupamem = 0; - return 0; - } - if(scr->dev && scr->dev->linear){ - aperture = scr->dev->linear(scr, &size, &align); - if(aperture == 0) - return 1; - }else{ - aperture = upamalloc(0, size, align); - if(aperture == 0) - return 1; - - if(scr->aperture && scr->isupamem) - upafree(scr->aperture, scr->apsize); - scr->isupamem = 1; - } - - scr->aperture = aperture; - scr->apsize = size; - - return 0; -} - -uchar* -attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen) -{ - VGAscr *scr; - - scr = &vgascreen[0]; - if(scr->gscreen == nil || scr->gscreendata == nil) - return nil; - - *r = scr->gscreen->clipr; - *chan = scr->gscreen->chan; - *d = scr->gscreen->depth; - *width = scr->gscreen->width; - *softscreen = scr->useflush; - - return scr->gscreendata->bdata; -} - -/* - * It would be fair to say that this doesn't work for >8-bit screens. - */ -void -flushmemscreen(Rectangle r) -{ - VGAscr *scr; - uchar *sp, *disp, *sdisp, *edisp; - int y, len, incs, off, page; - - scr = &vgascreen[0]; - if(scr->dev && scr->dev->flush){ - scr->dev->flush(scr, r); - return; - } - if(scr->gscreen == nil || scr->useflush == 0) - return; - if(scr->dev == nil || scr->dev->page == nil) - return; - - if(rectclip(&r, scr->gscreen->r) == 0) - return; - - incs = scr->gscreen->width * BY2WD; - - switch(scr->gscreen->depth){ - default: - len = 0; - panic("flushmemscreen: depth\n"); - break; - case 8: - len = Dx(r); - break; - } - if(len < 1) - return; - - off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8; - page = off/scr->apsize; - off %= scr->apsize; - disp = KADDR(scr->aperture); - sdisp = disp+off; - edisp = disp+scr->apsize; - - off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8; - - sp = scr->gscreendata->bdata + off; - - scr->dev->page(scr, page); - for(y = r.min.y; y < r.max.y; y++) { - if(sdisp + incs < edisp) { - memmove(sdisp, sp, len); - sp += incs; - sdisp += incs; - } - else { - off = edisp - sdisp; - page++; - if(off <= len){ - if(off > 0) - memmove(sdisp, sp, off); - scr->dev->page(scr, page); - if(len - off > 0) - memmove(disp, sp+off, len - off); - } - else { - memmove(sdisp, sp, len); - scr->dev->page(scr, page); - } - sp += incs; - sdisp += incs - scr->apsize; - } - } -} - -void -getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb) -{ - VGAscr *scr; - ulong x; - - scr = &vgascreen[0]; - if(scr->gscreen == nil) - return; - - switch(scr->gscreen->depth){ - default: - x = 0x0F; - break; - case 8: - x = 0xFF; - break; - } - p &= x; - - lock(&cursor); - *pr = scr->colormap[p][0]; - *pg = scr->colormap[p][1]; - *pb = scr->colormap[p][2]; - unlock(&cursor); -} - -int -setpalette(ulong p, ulong r, ulong g, ulong b) -{ - VGAscr *scr; - int d; - - scr = &vgascreen[0]; - d = scr->palettedepth; - - lock(&cursor); - scr->colormap[p][0] = r; - scr->colormap[p][1] = g; - scr->colormap[p][2] = b; - vgao(PaddrW, p); - vgao(Pdata, r>>(32-d)); - vgao(Pdata, g>>(32-d)); - vgao(Pdata, b>>(32-d)); - unlock(&cursor); - - return ~0; -} - -/* - * On some video cards (e.g. Mach64), the palette is used as the - * DAC registers for >8-bit modes. We don't want to set them when the user - * is trying to set a colormap and the card is in one of these modes. - */ -int -setcolor(ulong p, ulong r, ulong g, ulong b) -{ - VGAscr *scr; - int x; - - scr = &vgascreen[0]; - if(scr->gscreen == nil) - return 0; - - switch(scr->gscreen->depth){ - case 1: - case 2: - case 4: - x = 0x0F; - break; - case 8: - x = 0xFF; - break; - default: - return 0; - } - p &= x; - - return setpalette(p, r, g, b); -} - -int -cursoron(int dolock) -{ - VGAscr *scr; - int v; - - scr = &vgascreen[0]; - if(scr->cur == nil || scr->cur->move == nil) - return 0; - - if(dolock) - lock(&cursor); - v = scr->cur->move(scr, mousexy()); - if(dolock) - unlock(&cursor); - - return v; -} - -void -cursoroff(int) -{ -} - -void -setcursor(Cursor* curs) -{ - VGAscr *scr; - - scr = &vgascreen[0]; - if(scr->cur == nil || scr->cur->load == nil) - return; - - scr->cur->load(scr, curs); -} - -int hwaccel = 1; -int hwblank = 0; /* turned on by drivers that are known good */ -int panning = 0; - -int -hwdraw(Memdrawparam *par) -{ - VGAscr *scr; - Memimage *dst, *src; - int m; - - if(hwaccel == 0) - return 0; - - dst = par->dst; - scr = &vgascreen[0]; - if(dst == nil || dst->data == nil) - return 0; - - if(dst->data->bdata != gscreendata.bdata) - return 0; - - if(scr->fill==nil && scr->scroll==nil) - return 0; - - /* - * If we have an opaque mask and source is one opaque - * pixel we can convert to the destination format and just - * replicate with memset. - */ - m = Simplesrc|Simplemask|Fullmask; - if(scr->fill - && (par->state&m)==m - && ((par->srgba&0xFF) == 0xFF) - && (par->op&S) == S) - return scr->fill(scr, par->r, par->sdval); - - /* - * If no source alpha, an opaque mask, we can just copy the - * source onto the destination. If the channels are the same and - * the source is not replicated, memmove suffices. - */ - m = Simplemask|Fullmask; - src = par->src; - if(scr->scroll - && src->data->bdata==dst->data->bdata - && !(src->flags&Falpha) - && (par->state&m)==m - && (par->op&S) == S) - return scr->scroll(scr, par->r, par->sr); - - return 0; -} - -void -blankscreen(int blank) -{ - VGAscr *scr; - - scr = &vgascreen[0]; - if(hwblank){ - if(scr->blank) - scr->blank(scr, blank); - else - vgablank(scr, blank); - } -} - -void -cursorenable(void) -{ -} - -void -cursordisable(void) -{ -} diff --git a/os/pc/screen.h b/os/pc/screen.h deleted file mode 100644 index bcc1f230..00000000 --- a/os/pc/screen.h +++ /dev/null @@ -1,173 +0,0 @@ -typedef struct Cursor Cursor; - -enum { - CURSWID = 16, - CURSHGT = 16, -}; - -struct Cursor -{ - Point offset; - uchar clr[CURSWID/BI2BY*CURSHGT]; - uchar set[CURSWID/BI2BY*CURSHGT]; -}; -typedef struct Cursorinfo Cursorinfo; -struct Cursorinfo { - Cursor; - Lock; -}; - -/* devmouse.c */ -extern void mousetrack(int, int, int, int); -extern Point mousexy(void); - -extern void mouseaccelerate(int); -extern int m3mouseputc(Queue*, int); -extern int m5mouseputc(Queue*, int); -extern int mouseputc(Queue*, int); - -extern Cursorinfo cursor; -extern Cursor arrow; - -/* - * Generic VGA registers. - */ -enum { - MiscW = 0x03C2, /* Miscellaneous Output (W) */ - MiscR = 0x03CC, /* Miscellaneous Output (R) */ - Status0 = 0x03C2, /* Input status 0 (R) */ - Status1 = 0x03DA, /* Input Status 1 (R) */ - FeatureR = 0x03CA, /* Feature Control (R) */ - FeatureW = 0x03DA, /* Feature Control (W) */ - - Seqx = 0x03C4, /* Sequencer Index, Data at Seqx+1 */ - Crtx = 0x03D4, /* CRT Controller Index, Data at Crtx+1 */ - Grx = 0x03CE, /* Graphics Controller Index, Data at Grx+1 */ - Attrx = 0x03C0, /* Attribute Controller Index and Data */ - - PaddrW = 0x03C8, /* Palette Address Register, write */ - Pdata = 0x03C9, /* Palette Data Register */ - Pixmask = 0x03C6, /* Pixel Mask Register */ - PaddrR = 0x03C7, /* Palette Address Register, read */ - Pstatus = 0x03C7, /* DAC Status (RO) */ - - Pcolours = 256, /* Palette */ - Pred = 0, - Pgreen = 1, - Pblue = 2, - - Pblack = 0x00, - Pwhite = 0xFF, -}; - -#define VGAMEM() 0xA0000 -#define vgai(port) inb(port) -#define vgao(port, data) outb(port, data) - -extern int vgaxi(long, uchar); -extern int vgaxo(long, uchar, uchar); - -/* - */ -typedef struct VGAdev VGAdev; -typedef struct VGAcur VGAcur; -typedef struct VGAscr VGAscr; - -struct VGAdev { - char* name; - - void (*enable)(VGAscr*); - void (*disable)(VGAscr*); - void (*page)(VGAscr*, int); - ulong (*linear)(VGAscr*, int*, int*); - void (*drawinit)(VGAscr*); - int (*fill)(VGAscr*, Rectangle, ulong); - void (*ovlctl)(VGAscr*, Chan*, void*, int); - int (*ovlwrite)(VGAscr*, void*, int, vlong); - void (*flush)(VGAscr*, Rectangle); -}; - -struct VGAcur { - char* name; - - void (*enable)(VGAscr*); - void (*disable)(VGAscr*); - void (*load)(VGAscr*, Cursor*); - int (*move)(VGAscr*, Point); - - int doespanning; -}; - -/* - */ -struct VGAscr { - Lock devlock; - VGAdev* dev; - - VGAcur* cur; - ulong storage; - Cursor; - - int useflush; - - ulong aperture; /* physical address */ - int isupamem; - int apsize; - - ulong io; /* device specific registers */ - - ulong colormap[Pcolours][3]; - int palettedepth; - - ulong *mmio; - Memimage* gscreen; - Memdata* gscreendata; - Memsubfont* memdefont; - - int (*fill)(VGAscr*, Rectangle, ulong); - int (*scroll)(VGAscr*, Rectangle, Rectangle); - void (*blank)(VGAscr*, int); - ulong id; /* internal identifier for driver use */ - int isblank; - int overlayinit; -}; - -extern VGAscr vgascreen[]; - -enum { - Backgnd = 0, /* black */ -}; - -/* mouse.c */ -extern void mousectl(Cmdbuf*); - -/* screen.c */ -extern int hwaccel; /* use hw acceleration; default on */ -extern int hwblank; /* use hw blanking; default on */ -extern int panning; /* use virtual screen panning; default off */ -extern void addvgaseg(char*, ulong, ulong); -extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*); -extern void flushmemscreen(Rectangle); -extern int cursoron(int); -extern void cursoroff(int); -extern void setcursor(Cursor*); -extern int screensize(int, int, int, ulong); -extern int screenaperture(int, int); -extern Rectangle physgscreenr; /* actual monitor size */ -extern void blankscreen(int); - -/* devdraw.c */ -extern void deletescreenimage(void); -extern int drawhasclients(void); -extern ulong blanktime; -extern void setscreenimageclipr(Rectangle); -extern void drawflush(void); -extern int drawidletime(void); - -/* vga.c */ -extern void vgascreenwin(VGAscr*); -extern void vgaimageinit(ulong); -extern ulong vgapcilinear(VGAscr*, int*, int*, int, int); - -extern void drawblankscreen(int); -extern void vgablank(VGAscr*, int); diff --git a/os/pc/sd53c8xx.c b/os/pc/sd53c8xx.c deleted file mode 100644 index a03ac93c..00000000 --- a/os/pc/sd53c8xx.c +++ /dev/null @@ -1,2135 +0,0 @@ -/* - * NCR/Symbios/LSI Logic 53c8xx driver for Plan 9 - * Nigel Roles (nigel@9fs.org) - * - * 27/5/02 Fixed problems with transfers >= 256 * 512 - * - * 13/3/01 Fixed microcode to support targets > 7 - * - * 01/12/00 Removed previous comments. Fixed a small problem in - * mismatch recovery for targets with synchronous offsets of >=16 - * connected to >=875s. Thanks, Jean. - * - * Known problems - * - * Read/write mismatch recovery may fail on 53c1010s. Really need to get a manual. - */ - -#define MAXTARGET 16 /* can be 8 or 16 */ - -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#include "../port/sd.h" -extern SDifc sd53c8xxifc; - -/**********************************/ -/* Portable configuration macros */ -/**********************************/ - -//#define BOOTDEBUG -//#define ASYNC_ONLY -//#define INTERNAL_SCLK -//#define ALWAYS_DO_WDTR -#define WMR_DEBUG - -/**********************************/ -/* CPU specific macros */ -/**********************************/ - -#define PRINTPREFIX "sd53c8xx: " - -#ifdef BOOTDEBUG - -#define KPRINT oprint -#define IPRINT intrprint -#define DEBUG(n) 1 -#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) PCIWADDR(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((x)-PCIWINDOW) -#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 { - 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; - -#define SYNCOFFMASK(c) (((c)->v->maxsyncoff * 2) - 1) -#define SSIDMASK(c) (((c)->v->feature & Wide) ? 15 : 7) - -/* 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 = vseprint(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 = vseprint(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(PRINTPREFIX "%d/%d: allocated new dsa %lux\n", target, lun, (ulong)d); - } - lesetl(d->next, 0); - lesetl(&d->stateb, 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(PRINTPREFIX "%d/%d: reused dsa %lux\n", target, lun, (ulong)d); - } - c->dsalist.freechain = d->freechain; - lesetl(&d->stateb, 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->stateb, 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; - - if (intr) { - IPRINT("sa = %.8lux\n", c->scriptpa); - } - else { - 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(PRINTPREFIX "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(PRINTPREFIX "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(PRINTPREFIX "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(PRINTPREFIX "can't go differential; wrong cable\n"); - else { - n->stest2 = (1 << 5); - print(PRINTPREFIX "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(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target); - KPRINT(PRINTPREFIX "%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(PRINTPREFIX "%d: SDTN: rejected SDTR\n", dsa->target); - //async: - KPRINT(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%d: WDTN: target init %d\n", - dsa->target, hiswide); - if (hiswide < mywide) - mywide = hiswide; - KPRINT(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%d: WDTN: response accepted\n", dsa->target); - *cont = -2; - return; - case A_SIR_MSG_REJECT: - setwide(dsa, c, dsa->target, 0); - KPRINT(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%d: SDTN: response REJECTed\n", dsa->target); - *cont = -2; - return; - } - break; - } - KPRINT(PRINTPREFIX "%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); - d->flag = legetl(d->data_buf.dbc) == 0; -} - -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(PRINTPREFIX "%d/%d: read_mismatch_recover: DMA FIFO = %d\n", - dsa->target, dsa->lun, inchip); - } - if (n->sxfer & SYNCOFFMASK(c)) { - /* SCSI FIFO */ - uchar fifo = n->sstat1 >> 4; - if (c->v->maxsyncoff > 8) - fifo |= (n->sstat2 & (1 << 4)); - if (fifo) { - inchip += fifo; - IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SCSI FIFO = %d\n", - dsa->target, dsa->lun, fifo); - } - } - else { - if (n->sstat0 & (1 << 7)) { - inchip++; - IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL full\n", - dsa->target, dsa->lun); - } - if (n->sstat2 & (1 << 7)) { - inchip++; - IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL msb full\n", - dsa->target, dsa->lun); - } - } - USED(inchip); - return dbc; -} - -static ulong -write_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]; - 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(PRINTPREFIX "%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(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun); -#endif - } - if (n->sstat2 & (1 << 5)) { - inchip++; -#ifdef WMR_DEBUG - IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun); -#endif - } - if (n->sxfer & SYNCOFFMASK(c)) { - /* synchronous SODR */ - if (n->sstat0 & (1 << 6)) { - inchip++; -#ifdef WMR_DEBUG - IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODR full\n", - dsa->target, dsa->lun); -#endif - } - if (n->sstat2 & (1 << 6)) { - inchip++; -#ifdef WMR_DEBUG - IPRINT(PRINTPREFIX "%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 -sd53c8xxinterrupt(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(PRINTPREFIX "int\n"); - } - ilock(c); - istat = n->istat; - if (istat & Intf) { - Dsa *d; - int wokesomething = 0; - if (DEBUG(1)) { - IPRINT(PRINTPREFIX "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(PRINTPREFIX "waking up dsa %lux\n", (ulong)d); - } - wakeup(d); - wokesomething = 1; - } - } - if (!wokesomething) { - IPRINT(PRINTPREFIX "nothing to wake up\n"); - } - } - - if ((istat & (Sip | Dip)) == 0) { - if (DEBUG(1)) { - IPRINT(PRINTPREFIX "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(PRINTPREFIX "%d/%d: Phase Mismatch sa=%.8lux\n", - dsa->target, dsa->lun, sa); - } - /* - * now recover - */ - if (sa == E_data_in_mismatch) { - /* - * though this is a failure in the residue, there may have been blocks - * as well. if so, dmablks will not have been zeroed, since the state - * was not saved by the microcode. - */ - dbc = read_mismatch_recover(c, n, dsa); - tbc = legetl(dsa->data_buf.dbc) - dbc; - dsa->dmablks = 0; - n->scratcha[2] = 0; - advancedata(&dsa->data_buf, tbc); - if (DEBUG(1) || DEBUG(2)) { - IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n", - dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc)); - } - cont = E_data_mismatch_recover; - } - 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(c, n, dsa); - tbc = legetl(dsa->data_buf.dbc) - dbc; - dsa->dmablks = 0; - n->scratcha[2] = 0; - advancedata(&dsa->data_buf, tbc); - if (DEBUG(1) || DEBUG(2)) { - IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n", - dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc)); - } - cont = E_data_mismatch_recover; - } - else if (sa == E_data_out_block_mismatch) { - dbc = write_mismatch_recover(c, 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(c, n, dsa); - tbc = lim - dbc; - IPRINT(PRINTPREFIX "%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(c, n, dsa); - tbc = lim - dbc; - IPRINT(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%d/%d: parity error\n", dsa->target, dsa->lun); - dsa->parityerror = 1; - } - if (sist & 0x4) { - IPRINT(PRINTPREFIX "%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(PRINTPREFIX "%d/%d: ignore wide residue %d, WSR = %d\n", - dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1); - if (dsa->flag == 2) { - IPRINT(PRINTPREFIX "%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(PRINTPREFIX "%d: not msg_in after reselect (%s)", - n->ssid & SSIDMASK(c), phase[n->sstat1 & 7]); - dsa = dsafind(c, n->ssid & SSIDMASK(c), -1, A_STATE_DISCONNECTED); - dumpncrregs(c, 1); - wakeme = 1; - break; - case A_SIR_NOTIFY_MSG_IN: - IPRINT(PRINTPREFIX "%d/%d: msg_in %d\n", - dsa->target, dsa->lun, n->sfbr); - cont = -2; - break; - case A_SIR_NOTIFY_DISC: - IPRINT(PRINTPREFIX "%d/%d: disconnect:", dsa->target, dsa->lun); - goto dsadump; - case A_SIR_NOTIFY_STATUS: - IPRINT(PRINTPREFIX "%d/%d: status\n", dsa->target, dsa->lun); - cont = -2; - break; - case A_SIR_NOTIFY_COMMAND: - IPRINT(PRINTPREFIX "%d/%d: commands\n", dsa->target, dsa->lun); - cont = -2; - break; - case A_SIR_NOTIFY_DATA_IN: - IPRINT(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%d/%d: data out\n", dsa->target, dsa->lun); - cont = -2; - break; - case A_SIR_NOTIFY_DUMP: - IPRINT(PRINTPREFIX "%d/%d: dump\n", dsa->target, dsa->lun); - dumpncrregs(c, 1); - cont = -2; - break; - case A_SIR_NOTIFY_DUMP2: - IPRINT(PRINTPREFIX "%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", legetl(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(PRINTPREFIX "wait reselect\n"); - cont = -2; - break; - case A_SIR_NOTIFY_RESELECT: - IPRINT(PRINTPREFIX "reselect: ssid %.2x sfbr %.2x at %ld\n", - n->ssid, n->sfbr, TK2MS(m->ticks)); - cont = -2; - break; - case A_SIR_NOTIFY_ISSUE: - IPRINT(PRINTPREFIX "%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(PRINTPREFIX "issue check\n"); - cont = -2; - break; - case A_SIR_NOTIFY_SIGP: - IPRINT(PRINTPREFIX "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(PRINTPREFIX "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(PRINTPREFIX "%d/%d: WSR set\n", dsa->target, dsa->lun); - cont = -2; - break; - case A_SIR_NOTIFY_LOAD_SYNC: - IPRINT(PRINTPREFIX "%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: - if (DEBUG(2)) { - IPRINT(PRINTPREFIX "%d/%d: reselected during select\n", - dsa->target, dsa->lun); - } - cont = -2; - break; - case A_error_reselected: /* dsa isn't valid here */ - print(PRINTPREFIX "reselection error\n"); - dumpncrregs(c, 1); - for (dsa = KPTR(legetl(c->dsalist.head)); dsa; dsa = KPTR(legetl(dsa->next))) { - IPRINT(PRINTPREFIX "dsa target %d lun %d state %d\n", dsa->target, dsa->lun, dsa->stateb); - } - break; - default: - IPRINT(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "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(PRINTPREFIX "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(PRINTPREFIX "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 -sd53c8xxrio(SDreq* r) -{ - Dsa *d; - uchar *bp; - Controller *c; - uchar target_expo, my_expo; - int bc, check, i, 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(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo); - c->s[target] = WideInit; - break; - } - KPRINT(PRINTPREFIX "%d: WDTN: narrow\n", target); - /* fall through */ -#endif - case WideDone: - if (c->cap[target] & (1 << 4)) { - KPRINT(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%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(PRINTPREFIX "%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, 600 * 1000); - poperror(); - - if (!done(d)) { - KPRINT(PRINTPREFIX "%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 (DEBUG(0)) { - KPRINT(PRINTPREFIX "%d/%d: exec: before rlen adjust: dmablks %d flag %d dbc %lud\n", - target, r->lun, d->dmablks, d->flag, legetl(d->data_buf.dbc)); - } - r->rlen = r->dlen; - if (d->flag != 2) { - r->rlen -= d->dmablks * A_BSIZE; - r->rlen -= legetl(d->data_buf.dbc); - } - if(!r->write) - dumpreaddata(r->data, r->rlen); - if (DEBUG(0)) { - KPRINT(PRINTPREFIX "%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(PRINTPREFIX "%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->stateb, A_STATE_ALLOCATED); - goto docheck; - } - qunlock(&c->q[target]); - dsafree(c, d); - - if(status == SDok && check){ - status = SDcheck; - r->flags |= SDvalidsense; - } - if(DEBUG(0)) - KPRINT(PRINTPREFIX "%d: r flags %8.8uX status %d rlen %ld\n", - target, r->flags, status, r->rlen); - if(r->flags & SDvalidsense){ - if(!DEBUG(0)) - KPRINT(PRINTPREFIX "%d: r flags %8.8uX status %d rlen %ld\n", - target, r->flags, status, r->rlen); - for(i = 0; i < r->rlen; i++) - KPRINT(" %2.2uX", r->sense[i]); - KPRINT("\n"); - } - return r->status = status; -} - -static void -cribbios(Controller *c) -{ - c->bios.scntl3 = c->n->scntl3; - c->bios.stest2 = c->n->stest2; - KPRINT(PRINTPREFIX "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) - { - case X_scsi_id_buf: - *v = offsetof(Dsa, scsi_id_buf[0]); return 1; - case X_msg_out_buf: - *v = offsetof(Dsa, msg_out_buf); return 1; - case X_cmd_buf: - *v = offsetof(Dsa, cmd_buf); return 1; - case X_data_buf: - *v = offsetof(Dsa, data_buf); return 1; - case X_status_buf: - *v = offsetof(Dsa, status_buf); return 1; - case X_dsa_head: - *v = DMASEG(&c->dsalist.head[0]); return 1; - case X_ssid_mask: - *v = SSIDMASK(c); return 1; - default: - print("xfunc: can't find external %d\n", x); - return 0; - } -} - -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* -sd53c8xxpnp(void) -{ - char *cp; - Pcidev *p; - Variant *v; - int ba, nctlr; - void *scriptma; - Controller *ctlr; - SDev *sdev, *head, *tail; - ulong regpa, *script, scriptpa; - - if(cp = getconf("*maxsd53c8xx")) - nctlr = strtoul(cp, 0, 0); - else - nctlr = 32; - - p = nil; - head = tail = nil; - while((p = pcimatch(p, NCR_VID, 0)) != nil && nctlr > 0){ - for(v = variant; v < &variant[nelem(variant)]; v++){ - if(p->did == v->did && p->rid <= v->maxrid) - break; - } - if(v >= &variant[nelem(variant)]) { - print("no match\n"); - continue; - } - print(PRINTPREFIX "%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)); - - /* - * Because we don't yet have an abstraction for the - * addresses as seen from the controller side (and on - * the 386 it doesn't matter), the follwong two lines - * are different between the 386 and alpha copies of - * this driver. - */ - 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; - - nctlr--; - } - - return head; -} - -static SDev* -sd53c8xxid(SDev* sdev) -{ - return scsiid(sdev, &sd53c8xxifc); -} - -static int -sd53c8xxenable(SDev* sdev) -{ - Pcidev *pcidev; - Controller *ctlr; - char name[32]; - - ctlr = sdev->ctlr; - pcidev = ctlr->pcidev; - - pcisetbme(pcidev); - snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name); - intrenable(pcidev->intl, sd53c8xxinterrupt, ctlr, pcidev->tbdf, name); - - ilock(ctlr); - synctabinit(ctlr); - cribbios(ctlr); - reset(ctlr); - iunlock(ctlr); - - return 1; -} - -SDifc sd53c8xxifc = { - "53c8xx", /* name */ - - sd53c8xxpnp, /* pnp */ - nil, /* legacy */ - sd53c8xxid, /* id */ - sd53c8xxenable, /* enable */ - nil, /* disable */ - - scsiverify, /* verify */ - scsionline, /* online */ - sd53c8xxrio, /* rio */ - nil, /* rctl */ - nil, /* wctl */ - - scsibio, /* bio */ - nil, /* probe */ - nil, /* clear */ - nil, /* stat */ -}; diff --git a/os/pc/sd53c8xx.i b/os/pc/sd53c8xx.i deleted file mode 100644 index 6ef50e02..00000000 --- a/os/pc/sd53c8xx.i +++ /dev/null @@ -1,773 +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 */ - /* extern ssid_mask */ - /* 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 */ 0x78370200L, /* move 2 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 */ 0x78370200L, /* move 2 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 */ 0x740a0900L, /* move ssid & ssid_mask 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 */ - { 0x016d, 3 }, /* 000005b4 */ - { 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 80 - -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, - X_ssid_mask, -}; - -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_mismatch_recover = 228, - 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/os/pc/sd53c8xx.n b/os/pc/sd53c8xx.n deleted file mode 100644 index d9dc2fa1..00000000 --- a/os/pc/sd53c8xx.n +++ /dev/null @@ -1,448 +0,0 @@ -// NCR 53c8xx driver for Plan 9 -// Nigel Roles (nigel@9fs.org) -// -// Microcode -// -// 27/5/02 Fixed problems with transfers >= 256 * 512 -// -// 13/3/01 Fixed microcode to support targets > 7 -// - -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 -extern ssid_mask - -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 -//BSIZE=4096 - -idle: - jump wait_for_reselection -start: - call load_sync -// move 13 to ctest0 -// int SIR_NOTIFY_ISSUE - clear target - select atn from scsi_id_buf, reselected_on_select // do I need to clear ATN here? - jump start1, when msg_in -start1: -// move 14 to ctest0 - move from msg_out_buf, when msg_out -id_out_mismatch: - jump start1, when msg_out // repeat on parity grounds - jump to_decisions, when not cmd -cmd_phase: -// int SIR_NOTIFY_COMMAND - clear atn - move from cmd_buf, when cmd -cmd_out_mismatch: - jump to_decisions, when not data_in -data_in_phase: - move memory 4, state, scratcha - move memory 4, dmaaddr, scratchb -// int SIR_NOTIFY_DATA_IN -data_in_block_loop: - move scratcha2 to sfbr - jump data_in_normal, if 0 -// int SIR_NOTIFY_BLOCK_DATA_IN - move BSIZE, ptr dmaaddr, when data_in // transfer BSIZE bytes -data_in_block_mismatch: - move scratchb1 + BSIZE / 256 to scratchb1 // add BSIZE to scratchb - move scratchb2 + 0 to scratchb2 with carry - move scratchb3 + 0 to scratchb3 with carry - move scratcha2 + 255 to scratcha2 // sub one from block count - move memory 4, scratchb, dmaaddr // save latest dmaddr - jump data_in_block_loop, when data_in - move memory 4, scratcha, state // save latest state - call save_state - jump to_decisions -data_block_mismatch_recover: - move memory 4, scratchb, dmaaddr // save latest dmaddr -data_mismatch_recover: - move memory 4, scratcha, state // save latest state - jump to_decisions // no need to save - // as interrupt routine - // did this -data_in_normal: - move scratcha3 to sfbr - int error_too_much_data, if not 0 - move from data_buf, when data_in -data_in_mismatch: - move 2 to scratcha3 - move memory 4, scratcha, state - call save_state - jump post_data_to_decisions -data_out_phase: -// int SIR_NOTIFY_DATA_OUT - move memory 4, state, scratcha - move memory 4, dmaaddr, scratchb -data_out_block_loop: - move scratcha2 to sfbr - jump data_out_normal, if 0 - move memory 4, dmaaddr, scratchb - move BSIZE, ptr dmaaddr, when data_out // transfer BSIZE bytes -data_out_block_mismatch: - move scratchb1 + BSIZE / 256 to scratchb1 // add BSIZE to scratchb - move scratchb2 + 0 to scratchb2 with carry - move scratchb3 + 0 to scratchb3 with carry - move scratcha2 + 255 to scratcha2 // sub one from block count - move memory 4, scratchb, dmaaddr // save latest dmaddr - jump data_out_block_loop, when data_out - move memory 4, scratcha, state // save latest state - jump to_decisions -data_out_normal: - move scratcha3 to sfbr - int error_too_little_data, if not 0 - move from data_buf, when data_out -data_out_mismatch: - move 2 to scratcha3 - move memory 4, scratcha, state - call save_state - jump post_data_to_decisions -status_phase: - move from status_buf, when status -// int SIR_NOTIFY_STATUS - int error_unexpected_phase, when not msg_in -msg_in_phase: - move 1, scratcha, when msg_in -// int SIR_NOTIFY_MSG_IN - jump rejected, if MSG_REJECT -msg_in_not_reject: - jump disconnected, if MSG_DISCONNECT - jump msg_in_skip, if MSG_SAVE_DATA_POINTER - jump msg_in_skip, if MSG_RESTORE_POINTERS - jump ignore_wide, if MSG_IGNORE_WIDE_RESIDUE - jump extended, if X_MSG - int error_not_cmd_complete, if not 0 - move scntl2&0x7e to scntl2 // take care not to clear WSR - clear ack - wait disconnect - // update state - move memory 4, state, scratcha - move STATE_DONE to scratcha0 - move RESULT_OK to scratcha1 - move memory 4, scratcha, state - call save_state -// int SIR_MSG_IO_COMPLETE - intfly 0 - jump issue_check - -rejected: - int SIR_MSG_REJECT - clear ack - jump to_decisions -msg_in_skip: - clear ack - jump to_decisions - -extended: - clear ack - int error_unexpected_phase, when not msg_in - move 1, scratcha1, when msg_in - jump ext_3, if 3 - jump ext_2, if 2 - int error_weird_message, if not 1 -ext_1: - clear ack - int error_unexpected_phase, when not msg_in - move 1, scratcha1, when msg_in - jump ext_done - -ext_3: clear ack - int error_unexpected_phase, when not msg_in - move 1, scratcha1, when msg_in - clear ack - int error_unexpected_phase, when not msg_in - move 1, scratcha2, when msg_in - clear ack - int error_unexpected_phase, when not msg_in - move 1, scratcha3, when msg_in - move scratcha1 to sfbr - jump ext_done, if not X_MSG_SDTR - -// the target sent SDTR - leave ACK asserted and signal kernel -// kernel will either restart at reject, or continue -sdtr: int SIR_MSG_SDTR - clear ack - jump to_decisions - -ext_2: clear ack - int error_unexpected_phase, when not msg_in - move 1, scratcha1, when msg_in - clear ack - int error_unexpected_phase, when not msg_in - move 1, scratcha2, when msg_in - move scratcha1 to sfbr - jump ext_done, if not X_MSG_WDTR - -wdtr: int SIR_MSG_WDTR - clear ack - jump to_decisions - -ext_done: -// ought to check message here, but instead reject all -// NB ATN set -reject: - set atn // get target's ATN - clear ack // finish ACK - move MSG_REJECT to scratcha // prepare message - int error_unexpected_phase, when not msg_out// didn't get ATN - clear atn // last byte coming - move 1, scratcha, when msg_out // send byte - clear ack // finish ACK - jump reject, when msg_out // parity error - jump to_decisions - -ignore_wide: - clear ack - int error_unexpected_phase, when not msg_in - move 1, scratcha1, when msg_in - int SIR_MSG_IGNORE_WIDE_RESIDUE - clear ack - jump to_decisions - -// sends a response to a message -response: - set atn - clear ack - int error_unexpected_phase, when not msg_out -response_repeat: - move from msg_out_buf, when msg_out - jump response_repeat, when msg_out // repeat on parity grounds -// now look for response -// msg_in could be a REJECT -// anything other message is something else so signal kernel first - jump response_msg_in, when msg_in - int SIR_EV_RESPONSE_OK // not a MSG_IN so OK - jump to_decisions - -response_msg_in: - move 1, scratcha, when msg_in - jump rejected, if MSG_REJECT // go and generate rej interrupt - int SIR_EV_RESPONSE_OK // not a REJECT so OK - jump msg_in_not_reject // try others - -disconnected: -// move 5 to ctest0 - move scntl2&0x7e to scntl2 // don't clear WSR - clear ack - wait disconnect - // UPDATE state to disconnected - move memory 4, state, scratcha - move STATE_DISCONNECTED to scratcha0 - move memory 4, scratcha, state - call save_state -wsr_check: - move scntl2&0x01 to sfbr - int SIR_NOTIFY_WSR, if not 0 -// int SIR_NOTIFY_DISC - jump issue_check - -reselected_on_select: - int SIR_NOTIFY_RESELECTED_ON_SELECT - jump reselected - -wait_for_reselection: -// move 11 to ctest0 -// int SIR_NOTIFY_WAIT_RESELECT - wait reselect sigp_set -reselected: -// move 12 to ctest0 - clear target - int SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT, when not msg_in - move 1, scratchb, when msg_in - int error_not_identify_after_reselect, if not MSG_IDENTIFY and mask 0x1f -// int SIR_NOTIFY_RESELECT - // now locate the right DSA - note do not clear ACK, so target doesn't start - // synchronous transfer until we are ready -find_dsa: -// move 6 to ctest0 - move memory 4, dsa_head, dsa -find_dsa_loop: -// move 7 to ctest0 - move dsa0 to sfbr - jump find_dsa_1, if not 0 - move dsa1 to sfbr - jump find_dsa_1, if not 0 - move dsa2 to sfbr - jump find_dsa_1, if not 0 - move dsa3 to sfbr - int error_reselected, if 0 // couldn't match dsa (panic) -find_dsa_1: -// move 8 to ctest0 - // load state from DSA into dsa_copy - call load_state - move memory 4, state, scratcha // get dsastate in scratcha - move scratcha0 to sfbr // and state variable in sfbr - jump find_dsa_next, if not STATE_DISCONNECTED // wrong state - move ssid & ssid_mask to sfbr // get target ID - move memory 1, targ, find_dsa_smc1 // forge target comparison instruction -find_dsa_smc1: - jump find_dsa_next, if not 255 // jump if not matched - move memory 1, lun, find_dsa_smc2 // forge lun comparison instruction - move scratchb0 to sfbr // recover IDENTIFY message -find_dsa_smc2: - jump reload_sync, if 255 and mask ~7 // off we jolly well go -find_dsa_next: - move memory 4, next, dsa // find next - jump find_dsa_loop - -// id_out terminated early -// most likely the message wasn't recognised -// clear ATN and accept the message in -id_out_mismatch_recover: - clear atn - jump msg_in_phase, when msg_in - int SIR_MSG_REJECT - jump to_decisions - -// Reload synchronous registers after a reconnect. If the transfer is a synchronous read, then -// as soon as we clear ACK, the target will switch to data_in and start blasting data into the -// fifo. We need to be executing the 'jump when data_in' instruction before the target stops REQing -// since it is the REQ which latches the 'when'. The target will do 16 REQs before stopping, so -// we have 16 bytes (160uS) plus delays to do this after clearing ACK. Once the jump is executing, -// the target will wait, so as much debugging as you like can happen in data_in_phase, just don't -// stick any delays between 'clear ack' and 'jump data_in_phase, when data_in'. - -reload_sync: - call load_sync - clear ack -to_decisions: - jump data_in_phase, when data_in - jump cmd_phase, if cmd - jump data_out_phase, if data_out - jump status_phase, if status - jump msg_in_phase, if msg_in - int error_unexpected_phase -post_data_to_decisions: - jump status_phase, when status - jump msg_in_phase, if msg_in - int error_unexpected_phase - -// -// MULTI_TARGET -// -// following must mirror top of dsa structure -// the first section is loaded and saved, the -// second section loaded only -dsa_copy: -state: defw 0 // a0 is state, a1 result, a2 dma block count -dmaaddr: defw 0 // dma address for block moves -dsa_save_end: -targ: defw 0 // lsb is target -lun: defw 0 // lsb is lun -sync: defw 0 // lsb is scntl3, sxfer -next: defw 0 -dsa_load_end: -dsa_load_len = dsa_load_end - dsa_copy -dsa_save_len = dsa_save_end - dsa_copy - -load_state: - // load state from DSA into dsa_copy -// move 9 to ctest0 - move memory 4, dsa, load_state_smc0 + 4 -load_state_smc0: - move memory dsa_load_len, 0, dsa_copy -// move 20 to ctest0 - return -save_state: - move memory 4, dsa, save_state_smc0 + 8 -save_state_smc0: - move memory dsa_save_len, dsa_copy, 0 - return - -sigp_set: -// int SIR_NOTIFY_SIGP - move ctest2 to sfbr // clear SIGP -issue_check: -// int SIR_NOTIFY_ISSUE_CHECK -// move 1 to ctest0 - move memory 4, dsa_head, dsa -issue_check_loop: -// move 2 to ctest0 - move dsa0 to sfbr - jump issue_check_1, if not 0 - move dsa1 to sfbr - jump issue_check_1, if not 0 - move dsa2 to sfbr - jump issue_check_1, if not 0 - move dsa3 to sfbr - jump wait_for_reselection, if 0 // nothing to do -issue_check_1: -// move 3 to ctest0 - call load_state - move memory 4, state, scratcha // get dsastate in scratcha - move scratcha0 to sfbr // and state variable in sfbr - jump start, if STATE_ISSUE // right state -issue_check_next: -// move 4 to ctest0 - move memory 4, next, dsa // find next - jump issue_check_loop -load_sync: - move memory 4, sync, scratcha // load the sync stuff - move scratcha0 to sfbr // assuming load_state has been called - move sfbr to scntl3 - move scratcha1 to sfbr - move sfbr to sxfer -// int SIR_NOTIFY_LOAD_SYNC - return diff --git a/os/pc/sdata.c b/os/pc/sdata.c deleted file mode 100644 index 1e438986..00000000 --- a/os/pc/sdata.c +++ /dev/null @@ -1,2206 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" -#include "../port/error.h" - -#include "../port/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|DbgSTATE) - -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 { /* internal flags */ - Lba48 = 0x1, /* LBA48 mode */ - Lba48always = 0x2, /* ... */ -}; - -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 */ - Hob = 0x80, /* High Order Bit [sic] */ -}; - -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 */ - Icfapwr = 160, /* CFA power mode */ - Imediaserial = 176, /* current media serial number */ - Icksum = 255, /* checksum */ -}; - -enum { /* bit masks for config identify info */ - Mpktsz = 0x0003, /* packet command size */ - Mincomplete = 0x0004, /* incomplete information */ - Mdrq = 0x0060, /* DRQ type */ - Mrmdev = 0x0080, /* device is removable */ - Mtype = 0x1F00, /* device type */ - Mproto = 0x8000, /* command protocol */ -}; - -enum { /* bit masks for capabilities identify info */ - Mdma = 0x0100, /* DMA supported */ - Mlba = 0x0200, /* LBA supported */ - Mnoiordy = 0x0400, /* IORDY may be disabled */ - Miordy = 0x0800, /* IORDY supported */ - Msoftrst = 0x1000, /* needs soft reset when Bsy */ - Mstdby = 0x2000, /* standby supported */ - Mqueueing = 0x4000, /* queueing overlap supported */ - Midma = 0x8000, /* interleaved DMA supported */ -}; - -enum { /* bit masks for supported/enabled features */ - Msmart = 0x0001, - Msecurity = 0x0002, - Mrmmedia = 0x0004, - Mpwrmgmt = 0x0008, - Mpkt = 0x0010, - Mwcache = 0x0020, - Mlookahead = 0x0040, - Mrelirq = 0x0080, - Msvcirq = 0x0100, - Mreset = 0x0200, - Mprotected = 0x0400, - Mwbuf = 0x1000, - Mrbuf = 0x2000, - Mnop = 0x4000, - Mmicrocode = 0x0001, - Mqueued = 0x0002, - Mcfa = 0x0004, - Mapm = 0x0008, - Mnotify = 0x0010, - Mstandby = 0x0020, - Mspinup = 0x0040, - Mmaxsec = 0x0100, - Mautoacoustic = 0x0200, - Maddr48 = 0x0400, - Mdevconfov = 0x0800, - Mflush = 0x1000, - Mflush48 = 0x2000, - Msmarterror = 0x0001, - Msmartselftest = 0x0002, - Mmserial = 0x0004, - Mmpassthru = 0x0008, - Mlogging = 0x0020, -}; - -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; - int bmiba; /* bus master interface base address */ - - Pcidev* pcidev; - void (*ienable)(Ctlr*); - void (*idisable)(Ctlr*); - SDev* sdev; - - Drive* drive[2]; - - Prd* prdt; /* physical region descriptor table */ - void* prdtbase; - - 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; - -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 void -atadumpstate(Drive* drive, uchar* cmd, vlong lba, int count) -{ - Prd *prd; - Pcidev *p; - Ctlr *ctlr; - int i, bmiba; - - if(!(DEBUG & DbgSTATE)){ - USED(drive, cmd, lba, count); - return; - } - - ctlr = drive->ctlr; - print("command %2.2uX\n", ctlr->command); - print("data %8.8p limit %8.8p dlen %d status %uX error %uX\n", - drive->data, drive->limit, drive->dlen, - drive->status, drive->error); - if(cmd != nil){ - print("lba %d -> %lld, count %d -> %d (%d)\n", - (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5], lba, - (cmd[7]<<8)|cmd[8], count, drive->count); - } - if(!(inb(ctlr->ctlport+As) & Bsy)){ - for(i = 1; i < 7; i++) - print(" 0x%2.2uX", inb(ctlr->cmdport+i)); - print(" 0x%2.2uX\n", inb(ctlr->ctlport+As)); - } - if(drive->command == Cwd || drive->command == Crd){ - bmiba = ctlr->bmiba; - prd = ctlr->prdt; - print("bmicx %2.2uX bmisx %2.2uX prdt %8.8p\n", - inb(bmiba+Bmicx), inb(bmiba+Bmisx), prd); - for(;;){ - print("pa 0x%8.8luX count %8.8uX\n", - prd->pa, prd->count); - if(prd->count & PrdEOT) - break; - prd++; - } - } - if(ctlr->pcidev && ctlr->pcidev->vid == 0x8086){ - p = ctlr->pcidev; - print("0x40: %4.4uX 0x42: %4.4uX", - pcicfgr16(p, 0x40), pcicfgr16(p, 0x42)); - print("0x48: %2.2uX\n", pcicfgr8(p, 0x48)); - print("0x4A: %4.4uX\n", pcicfgr16(p, 0x4A)); - } -} - -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 -atacsf(Drive* drive, vlong csf, int supported) -{ - ushort *info; - int cmdset, i, x; - - if(supported) - info = &drive->info[Icsfs]; - else - info = &drive->info[Icsfe]; - - for(i = 0; i < 3; i++){ - x = (csf>>(16*i)) & 0xFFFF; - if(x == 0) - continue; - cmdset = info[i]; - if(cmdset == 0 || cmdset == 0xFFFF) - return 0; - return cmdset & x; - } - - return 0; -} -*/ - -static int -atadone(void* arg) -{ - return ((Ctlr*)arg)->done; -} - -static int -atarwmmode(Drive* drive, int cmdport, int ctlport, int dev) -{ - int as, maxrwm, rwm; - - maxrwm = (drive->info[Imaxrwm] & 0xFF); - if(maxrwm == 0) - return 0; - - /* - * Sometimes drives come up with the current count set - * to 0; if so, set a suitable value, otherwise believe - * the value in Irwm if the 0x100 bit is set. - */ - if(drive->info[Irwm] & 0x100) - rwm = (drive->info[Irwm] & 0xFF); - else - rwm = 0; - if(rwm == 0) - rwm = maxrwm; - if(rwm > 16) - rwm = 16; - if(ataready(cmdport, ctlport, dev, Bsy|Drq, Drdy, 102*1000) < 0) - return 0; - outb(cmdport+Count, rwm); - outb(cmdport+Command, Csm); - microdelay(1); - as = ataready(cmdport, ctlport, 0, Bsy, Drdy|Df|Err, 1000); - inb(cmdport+Status); - if(as < 0 || (as & (Df|Err))) - return 0; - - drive->rwm = rwm; - - return rwm; -} - -static int -atadmamode(Drive* drive) -{ - int dma; - - /* - * Check if any DMA mode enabled. - * Assumes the BIOS has picked and enabled the best. - * This is completely passive at the moment, no attempt is - * made to ensure the hardware is correctly set up. - */ - dma = drive->info[Imwdma] & 0x0707; - drive->dma = (dma>>8) & dma; - if(drive->dma == 0 && (drive->info[Ivalid] & 0x04)){ - dma = drive->info[Iudma] & 0x7F7F; - drive->dma = (dma>>8) & dma; - if(drive->dma) - drive->dma |= 'U'<<16; - } - - return dma; -} - -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] & Mlba){ - if(drive->info[Icsfs+1] & Maddr48){ - 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\n", drive->dma, drive->rwm); - if(drive->flags&Lba48) - print("\tLLBA sectors %lld\n", drive->sectors); - } - - 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) { - print("ataprobe: Cannot allocate %X\n", cmdport); - return nil; - } - if(ioalloc(ctlport+As, 1, 0, "atactl") < 0){ - print("ataprobe: Cannot allocate %X\n", ctlport + As); - 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; - } - memset(ctlr, 0, sizeof(Ctlr)); - if((sdev = malloc(sizeof(SDev))) == nil){ - free(ctlr); - free(drive); - goto release; - } - memset(sdev, 0, sizeof(SDev)); - 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 void -ataclear(SDev *sdev) -{ - Ctlr* ctlr; - - ctlr = sdev->ctlr; - iofree(ctlr->cmdport); - iofree(ctlr->ctlport + As); - - if (ctlr->drive[0]) - free(ctlr->drive[0]); - if (ctlr->drive[1]) - free(ctlr->drive[1]); - if (sdev->name) - free(sdev->name); - if (sdev->unitflg) - free(sdev->unitflg); - if (sdev->unit) - free(sdev->unit); - free(ctlr); - free(sdev); -} - -static char * -atastat(SDev *sdev, char *p, char *e) -{ - Ctlr *ctlr = sdev->ctlr; - - return seprint(p, e, "%s ata port %X ctl %X irq %d\n", - sdev->name, ctlr->cmdport, ctlr->ctlport, ctlr->irq); -} - -static SDev* -ataprobew(DevConf *cf) -{ - if (cf->nports != 2) - error(Ebadarg); - - return ataprobe(cf->ports[0].port, cf->ports[1].port, cf->intnum); -} - -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 -atastandby(Drive* drive, int period) -{ - Ctlr* ctlr; - int cmdport, done; - - ctlr = drive->ctlr; - drive->command = Cstandby; - qlock(ctlr); - - cmdport = ctlr->cmdport; - ilock(ctlr); - outb(cmdport+Count, period); - outb(cmdport+Dh, drive->dev); - ctlr->done = 0; - ctlr->curdrive = drive; - ctlr->command = Cstandby; /* debugging */ - outb(cmdport+Command, Cstandby); - iunlock(ctlr); - - while(waserror()) - ; - tsleep(ctlr, atadone, ctlr, 30*1000); - poperror(); - - done = ctlr->done; - qunlock(ctlr); - - if(!done || (drive->status & Err)) - return atasetsense(drive, SDcheck, 4, 8, drive->error); - return SDok; -} - -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(drive->info[Icsfs] & Mnop) - atanop(drive, 0); - else{ - atasrst(drive->ctlr->ctlport); - drive->error |= Abrt; - } - if(dolock) - iunlock(drive->ctlr); -} - -static int -atadmasetup(Drive* drive, int len) -{ - Prd *prd; - ulong pa; - Ctlr *ctlr; - int bmiba, bmisx, count; - - pa = PCIWADDR(drive->data); - if(pa & 0x03) - return -1; - ctlr = drive->ctlr; - prd = ctlr->prdt; - - /* - * Sometimes drives identify themselves as being DMA capable - * although they are not on a busmastering controller. - */ - if(prd == nil){ - drive->dmactl = 0; - print("disabling dma: not on a busmastering controller\n"); - return -1; - } - - for(;;){ - prd->pa = pa; - count = 64*1024 - (pa & 0xFFFF); - if(count >= len){ - prd->count = PrdEOT|(len & 0xFFFF); - break; - } - prd->count = count; - len -= count; - pa += count; - prd++; - } - - bmiba = ctlr->bmiba; - outl(bmiba+Bmidtpx, PCIWADDR(ctlr->prdt)); - if(drive->write) - outb(ctlr->bmiba+Bmicx, 0); - else - outb(ctlr->bmiba+Bmicx, Rwcon); - bmisx = inb(bmiba+Bmisx); - outb(bmiba+Bmisx, bmisx|Ideints|Idedmae); - - return 0; -} - -static void -atadmastart(Ctlr* ctlr, int write) -{ - if(write) - outb(ctlr->bmiba+Bmicx, Ssbm); - else - outb(ctlr->bmiba+Bmicx, Rwcon|Ssbm); -} - -static int -atadmastop(Ctlr* ctlr) -{ - int bmiba; - - bmiba = ctlr->bmiba; - outb(bmiba+Bmicx, inb(bmiba+Bmicx) & ~Ssbm); - - return inb(bmiba+Bmisx); -} - -static void -atadmainterrupt(Drive* drive, int count) -{ - Ctlr* ctlr; - int bmiba, bmisx; - - ctlr = drive->ctlr; - bmiba = ctlr->bmiba; - bmisx = inb(bmiba+Bmisx); - switch(bmisx & (Ideints|Idedmae|Bmidea)){ - case Bmidea: - /* - * Data transfer still in progress, nothing to do - * (this should never happen). - */ - return; - - case Ideints: - case Ideints|Bmidea: - /* - * Normal termination, tidy up. - */ - drive->data += count; - break; - - default: - /* - * What's left are error conditions (memory transfer - * problem) and the device is not done but the PRD is - * exhausted. For both cases must somehow tell the - * drive to abort. - */ - ataabort(drive, 0); - break; - } - atadmastop(ctlr); - ctlr->done = 1; -} - -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, timeo; - - 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); - - if(ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 107*1000) < 0){ - 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, 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] & Mdrq) != 0x0020){ - microdelay(1); - as = ataready(cmdport, ctlport, 0, Bsy, Drq|Chk, 4*1000); - if(as < 0) - r = SDtimeout; - else if(as & Chk) - r = SDcheck; - else - atapktinterrupt(drive); - } - iunlock(ctlr); - - while(waserror()) - ; - if(!drive->pktdma) - sleep(ctlr, atadone, ctlr); - else for(timeo = 0; !ctlr->done; timeo++){ - tsleep(ctlr, atadone, ctlr, 1000); - if(ctlr->done) - break; - ilock(ctlr); - atadmainterrupt(drive, 0); - if(!drive->error && timeo > 10){ - ataabort(drive, 0); - atadmastop(ctlr); - drive->dmactl = 0; - drive->error |= Abrt; - } - if(drive->error){ - drive->status |= Chk; - ctlr->curdrive = nil; - } - iunlock(ctlr); - } - poperror(); - - qunlock(ctlr); - - if(drive->status & Chk) - r = SDcheck; - - return r; -} - -static uchar cmd48[256] = { - [Crs] Crs48, - [Crd] Crd48, - [Crdq] Crdq48, - [Crsm] Crsm48, - [Cws] Cws48, - [Cwd] Cwd48, - [Cwdq] Cwdq48, - [Cwsm] Cwsm48, -}; - -static int -atageniostart(Drive* drive, vlong lba) -{ - Ctlr *ctlr; - uchar cmd; - int as, c, cmdport, ctlport, h, len, s, use48; - - use48 = 0; - if((drive->flags&Lba48always) || (lba>>28) || drive->count > 256){ - if(!(drive->flags & Lba48)) - return -1; - use48 = 1; - c = h = s = 0; - }else if(drive->dev & Lba){ - c = (lba>>8) & 0xFFFF; - h = (lba>>24) & 0x0F; - s = lba & 0xFF; - }else{ - c = lba/(drive->s*drive->h); - h = ((lba/drive->s) % drive->h); - s = (lba % drive->s) + 1; - } - - ctlr = drive->ctlr; - cmdport = ctlr->cmdport; - ctlport = ctlr->ctlport; - if(ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 101*1000) < 0) - return -1; - - ilock(ctlr); - if(drive->dmactl && !atadmasetup(drive, drive->count*drive->secsize)){ - if(drive->write) - drive->command = Cwd; - else - drive->command = Crd; - } - else if(drive->rwmctl){ - drive->block = drive->rwm*drive->secsize; - if(drive->write) - drive->command = Cwsm; - else - drive->command = Crsm; - } - else{ - 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) -{ - if(drive->dmactl){ - drive->dmactl = 0; - print("atagenioretry: disabling dma\n"); - } - else if(drive->rwmctl) - drive->rwmctl = 0; - else - return atasetsense(drive, SDcheck, 4, 8, drive->error); - - return SDretry; -} - -static int -atagenio(Drive* drive, uchar* cmd, int) -{ - uchar *p; - Ctlr *ctlr; - int count, max; - vlong lba, len; - - /* - * Map SCSI commands into ATA commands for discs. - * Fail any command with a LUN except INQUIRY which - * will return 'logical unit not supported'. - */ - if((cmd[1]>>5) && cmd[0] != 0x12) - return atasetsense(drive, SDcheck, 0x05, 0x25, 0); - - switch(cmd[0]){ - default: - return atasetsense(drive, SDcheck, 0x05, 0x20, 0); - - case 0x00: /* test unit ready */ - return SDok; - - case 0x03: /* request sense */ - if(cmd[4] < sizeof(drive->sense)) - len = cmd[4]; - else - len = sizeof(drive->sense); - if(drive->data && drive->dlen >= len){ - memmove(drive->data, drive->sense, len); - drive->data += len; - } - return SDok; - - case 0x12: /* inquiry */ - if(cmd[4] < sizeof(drive->inquiry)) - len = cmd[4]; - else - len = sizeof(drive->inquiry); - if(drive->data && drive->dlen >= len){ - memmove(drive->data, drive->inquiry, len); - drive->data += len; - } - return SDok; - - case 0x1B: /* start/stop unit */ - /* - * NOP for now, can use the power management feature - * set later. - */ - return SDok; - - case 0x25: /* read capacity */ - if((cmd[1] & 0x01) || cmd[2] || cmd[3]) - return atasetsense(drive, SDcheck, 0x05, 0x24, 0); - if(drive->data == nil || drive->dlen < 8) - return atasetsense(drive, SDcheck, 0x05, 0x20, 1); - /* - * Read capacity returns the LBA of the last sector. - */ - len = drive->sectors-1; - p = drive->data; - *p++ = len>>24; - *p++ = len>>16; - *p++ = len>>8; - *p++ = len; - len = drive->secsize; - *p++ = len>>24; - *p++ = len>>16; - *p++ = len>>8; - *p = len; - drive->data += 8; - return SDok; - - case 0x9E: /* long read capacity */ - if((cmd[1] & 0x01) || cmd[2] || cmd[3]) - return atasetsense(drive, SDcheck, 0x05, 0x24, 0); - if(drive->data == nil || drive->dlen < 8) - return atasetsense(drive, SDcheck, 0x05, 0x20, 1); - /* - * Read capacity returns the LBA of the last sector. - */ - len = drive->sectors-1; - p = drive->data; - *p++ = len>>56; - *p++ = len>>48; - *p++ = len>>40; - *p++ = len>>32; - *p++ = len>>24; - *p++ = len>>16; - *p++ = len>>8; - *p++ = len; - len = drive->secsize; - *p++ = len>>24; - *p++ = len>>16; - *p++ = len>>8; - *p = len; - drive->data += 8; - return SDok; - - case 0x28: /* read */ - case 0x2A: /* write */ - break; - - case 0x5A: - return atamodesense(drive, cmd); - } - - ctlr = drive->ctlr; - lba = (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5]; - count = (cmd[7]<<8)|cmd[8]; - if(drive->data == nil) - return SDok; - if(drive->dlen < count*drive->secsize) - count = drive->dlen/drive->secsize; - qlock(ctlr); - while(count){ - max = (drive->flags&Lba48) ? 65536 : 256; - if(count > max) - drive->count = max; - else - drive->count = count; - if(atageniostart(drive, lba)){ - ilock(ctlr); - atanop(drive, 0); - iunlock(ctlr); - qunlock(ctlr); - return atagenioretry(drive); - } - - while(waserror()) - ; - tsleep(ctlr, atadone, ctlr, 30*1000); - poperror(); - 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); - qunlock(ctlr); - 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); -retry: - 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 == SDretry){ - if(DbgDEBUG) - print("%s: retry: dma %8.8uX rwm %4.4uX\n", - unit->name, drive->dmactl, drive->rwmctl); - goto retry; - } - 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; - - case Cstandby: - ctlr->done = 1; - break; - } - iunlock(ctlr); - - if(drive->error){ - status |= Err; - ctlr->done = 1; - } - - if(ctlr->done){ - ctlr->curdrive = nil; - drive->status = status; - wakeup(ctlr); - } -} - -static SDev* -atapnp(void) -{ - Ctlr *ctlr; - Pcidev *p; - int channel, ispc87415, pi, r; - SDev *legacy[2], *sdev, *head, *tail; - - legacy[0] = legacy[1] = head = tail = nil; - if(sdev = ataprobe(0x1F0, 0x3F4, IrqATA0)){ - head = tail = sdev; - legacy[0] = sdev; - } - if(sdev = ataprobe(0x170, 0x374, IrqATA1)){ - if(head != nil) - tail->next = sdev; - else - head = sdev; - tail = sdev; - legacy[1] = sdev; - } - - p = nil; - while(p = pcimatch(p, 0, 0)){ - /* - * Look for devices with the correct class and sub-class - * code and known device and vendor ID; add native-mode - * channels to the list to be probed, save info for the - * compatibility mode channels. - * Note that the legacy devices should not be considered - * PCI devices by the interrupt controller. - * For both native and legacy, save info for busmastering - * if capable. - * Promise Ultra ATA/66 (PDC20262) appears to - * 1) give a sub-class of 'other mass storage controller' - * instead of 'IDE controller', regardless of whether it's - * the only controller or not; - * 2) put 0 in the programming interface byte (probably - * as a consequence of 1) above). - * Sub-class code 0x04 is 'RAID controller', e.g. VIA VT8237. - */ - if(p->ccrb != 0x01) - continue; - if(p->ccru != 0x01 && p->ccru != 0x04 && p->ccru != 0x80) - continue; - pi = p->ccrp; - ispc87415 = 0; - - switch((p->did<<16)|p->vid){ - default: - continue; - - case (0x0002<<16)|0x100B: /* NS PC87415 */ - /* - * Disable interrupts on both channels until - * after they are probed for drives. - * This must be called before interrupts are - * enabled because the IRQ may be shared. - */ - ispc87415 = 1; - pcicfgw32(p, 0x40, 0x00000300); - break; - case (0x1000<<16)|0x1042: /* PC-Tech RZ1000 */ - /* - * Turn off prefetch. Overkill, but cheap. - */ - r = pcicfgr32(p, 0x40); - r &= ~0x2000; - pcicfgw32(p, 0x40, r); - break; - case (0x4D38<<16)|0x105A: /* Promise PDC20262 */ - case (0x4D30<<16)|0x105A: /* Promise PDC202xx */ - case (0x4D68<<16)|0x105A: /* Promise PDC20268 */ - case (0x3373<<16)|0x105A: /* Promise 20378 RAID */ - case (0x3149<<16)|0x1106: /* VIA VT8237 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); - break; - case (0x0646<<16)|0x1095: /* CMD 646 */ - case (0x0571<<16)|0x1106: /* VIA 82C686 */ - case (0x0211<<16)|0x1166: /* ServerWorks IB6566 */ - case (0x1230<<16)|0x8086: /* 82371FB (PIIX) */ - case (0x7010<<16)|0x8086: /* 82371SB (PIIX3) */ - case (0x7111<<16)|0x8086: /* 82371[AE]B (PIIX4[E]) */ - case (0x2411<<16)|0x8086: /* 82801AA (ICH) */ - case (0x2421<<16)|0x8086: /* 82801AB (ICH0) */ - case (0x244A<<16)|0x8086: /* 82801BA (ICH2, Mobile) */ - case (0x244B<<16)|0x8086: /* 82801BA (ICH2, High-End) */ - case (0x248A<<16)|0x8086: /* 82801CA (ICH3, Mobile) */ - case (0x248B<<16)|0x8086: /* 82801CA (ICH3, High-End) */ - case (0x24CA<<16)|0x8086: /* 82801DBM (ICH4, Mobile) */ - case (0x24CB<<16)|0x8086: /* 82801DB (ICH4, High-End) */ - case (0x24DB<<16)|0x8086: /* 82801EB (ICH5) */ - 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; - print("pc87415disable: not yet implemented\n"); - } - - 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; - if(!(pi & 0x80)) - continue; - ctlr->bmiba = (p->mem[4].bar & ~0x01) + channel*8; - } - } - -if(0){ - int port; - ISAConf isa; - - /* - * Hack for PCMCIA drives. - * This will be tidied once we figure out how the whole - * removeable device thing is going to work. - */ - memset(&isa, 0, sizeof(isa)); - isa.port = 0x180; /* change this for your machine */ - isa.irq = 11; /* change this for your machine */ - - port = isa.port+0x0C; - channel = pcmspecial("MK2001MPL", &isa); - if(channel == -1) - channel = pcmspecial("SunDisk", &isa); - if(channel == -1){ - isa.irq = 10; - channel = pcmspecial("CF", &isa); - } - if(channel == -1){ - isa.irq = 10; - channel = pcmspecial("OLYMPUS", &isa); - } - if(channel == -1){ - port = isa.port+0x204; - channel = pcmspecial("ATA/ATAPI", &isa); - } - if(channel >= 0 && (sdev = ataprobe(isa.port, port, isa.irq)) != nil){ - if(head != nil) - tail->next = sdev; - else - head = sdev; - } -} - return head; -} - -static SDev* -atalegacy(int port, int irq) -{ - return ataprobe(port, port+0x204, irq); -} - -static SDev* -ataid(SDev* sdev) -{ - int i; - Ctlr *ctlr; - char name[32]; - - /* - * 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(name, sizeof(name), "sd%c", sdev->idno); - kstrdup(&sdev->name, name); - } - sdev = sdev->next; - } - - return nil; -} - -static int -ataenable(SDev* sdev) -{ - Ctlr *ctlr; - char name[32]; - - ctlr = sdev->ctlr; - - if(ctlr->bmiba){ -#define ALIGN (4 * 1024) - if(ctlr->pcidev != nil) - pcisetbme(ctlr->pcidev); - // ctlr->prdt = xspanalloc(Nprd*sizeof(Prd), 4, 4*1024); - ctlr->prdtbase = xalloc(Nprd * sizeof(Prd) + ALIGN); - ctlr->prdt = (Prd *)(((ulong)ctlr->prdtbase + ALIGN) & ~(ALIGN - 1)); - } - snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name); - intrenable(ctlr->irq, atainterrupt, ctlr, ctlr->tbdf, name); - outb(ctlr->ctlport+Dc, 0); - if(ctlr->ienable) - ctlr->ienable(ctlr); - - return 1; -} - -static int -atadisable(SDev *sdev) -{ - Ctlr *ctlr; - char name[32]; - - ctlr = sdev->ctlr; - outb(ctlr->ctlport+Dc, Nien); /* disable interrupts */ - if (ctlr->idisable) - ctlr->idisable(ctlr); - snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name); - intrdisable(ctlr->irq, atainterrupt, ctlr, ctlr->tbdf, name); - if (ctlr->bmiba) { - if (ctlr->pcidev) - pciclrbme(ctlr->pcidev); - xfree(ctlr->prdtbase); - } - return 0; -} - -static int -atarctl(SDunit* unit, char* p, int l) -{ - int n; - Ctlr *ctlr; - Drive *drive; - - if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil) - return 0; - drive = ctlr->drive[unit->subno]; - - qlock(drive); - n = snprint(p, l, "config %4.4uX capabilities %4.4uX", - drive->info[Iconfig], drive->info[Icapabilities]); - if(drive->dma) - n += snprint(p+n, l-n, " dma %8.8uX dmactl %8.8uX", - drive->dma, drive->dmactl); - if(drive->rwm) - n += snprint(p+n, l-n, " rwm %ud rwmctl %ud", - drive->rwm, drive->rwmctl); - if(drive->flags&Lba48) - n += snprint(p+n, l-n, " lba48always %s", - (drive->flags&Lba48always) ? "on" : "off"); - n += snprint(p+n, l-n, "\n"); - if(drive->sectors){ - n += snprint(p+n, l-n, "geometry %lld %d", - drive->sectors, drive->secsize); - if(drive->pkt == 0) - n += snprint(p+n, l-n, " %d %d %d", - drive->c, drive->h, drive->s); - n += snprint(p+n, l-n, "\n"); - } - qunlock(drive); - - return n; -} - -static int -atawctl(SDunit* unit, Cmdbuf* cb) -{ - int period; - Ctlr *ctlr; - Drive *drive; - - if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil) - return 0; - drive = ctlr->drive[unit->subno]; - - qlock(drive); - if(waserror()){ - qunlock(drive); - nexterror(); - } - - /* - * Dma and rwm control is passive at the moment, - * i.e. it is assumed that the hardware is set up - * correctly already either by the BIOS or when - * the drive was initially identified. - */ - if(strcmp(cb->f[0], "dma") == 0){ - if(cb->nf != 2 || drive->dma == 0) - error(Ebadctl); - if(strcmp(cb->f[1], "on") == 0) - drive->dmactl = drive->dma; - else if(strcmp(cb->f[1], "off") == 0) - drive->dmactl = 0; - else - error(Ebadctl); - } - else if(strcmp(cb->f[0], "rwm") == 0){ - if(cb->nf != 2 || drive->rwm == 0) - error(Ebadctl); - if(strcmp(cb->f[1], "on") == 0) - drive->rwmctl = drive->rwm; - else if(strcmp(cb->f[1], "off") == 0) - drive->rwmctl = 0; - else - error(Ebadctl); - } - else if(strcmp(cb->f[0], "standby") == 0){ - switch(cb->nf){ - default: - error(Ebadctl); - case 2: - period = strtol(cb->f[1], 0, 0); - if(period && (period < 30 || period > 240*5)) - error(Ebadctl); - period /= 5; - break; - } - if(atastandby(drive, period) != SDok) - error(Ebadctl); - } - else if(strcmp(cb->f[0], "lba48always") == 0){ - if(cb->nf != 2 || !(drive->flags&Lba48)) - error(Ebadctl); - if(strcmp(cb->f[1], "on") == 0) - drive->flags |= Lba48always; - else if(strcmp(cb->f[1], "off") == 0) - drive->flags &= ~Lba48always; - else - error(Ebadctl); - } - else - error(Ebadctl); - qunlock(drive); - poperror(); - - return 0; -} - -SDifc sdataifc = { - "ata", /* name */ - - atapnp, /* pnp */ - atalegacy, /* legacy */ - ataid, /* id */ - ataenable, /* enable */ - atadisable, /* disable */ - - scsiverify, /* verify */ - scsionline, /* online */ - atario, /* rio */ - atarctl, /* rctl */ - atawctl, /* wctl */ - - scsibio, /* bio */ - ataprobew, /* probe */ - ataclear, /* clear */ - atastat, /* stat */ -}; diff --git a/os/pc/sdmylex.c b/os/pc/sdmylex.c deleted file mode 100644 index cb132991..00000000 --- a/os/pc/sdmylex.c +++ /dev/null @@ -1,1249 +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 "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" -#include "../port/error.h" - -#include "../port/sd.h" - -#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 Mbox24 Mbox24; -struct Mbox24 { - uchar code; /* action/completion code */ - uchar ccb[3]; /* CCB pointer (MSB, ..., LSB) */ -}; - -typedef struct Mbox32 Mbox32; -struct Mbox32 { - 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 */ -}; - -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 Ctlr Ctlr; -struct Ctlr { - 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 */ -}; - -/* - * 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()) - ; - sleep(ccb, done24, ccb); - poperror(); - - /* - * 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", - ctlr->sdev->name, rinterrupt); - if((rinterrupt & Cmdc) && (rstatus & Cmdinv)) - print("%s: command invalid\n", 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()) - ; - sleep(ccb, done32, ccb); - poperror(); - - /* - * 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", - ctlr->sdev->name, rinterrupt); - if((rinterrupt & Cmdc) && (rstatus & Cmdinv)) - print("%s: command invalid\n", 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; - sdev = 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); - if (sdev != nil) - free(sdev); - 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] = 4; - clen = 2; - dlen = 256; - if(issue(ctlr, cmd, clen, data, dlen)){ - if(data[0] == 'E') - ctlr->bus = 32; - ctlr->wide = data[0x0D] & 0x01; - } - else{ - /* - * Inconceivable though it may seem, a hard controller reset - * is necessary here to clear out the command queue. Every - * board seems to lock-up in a different way if you give an - * invalid command and then try to clear out the - * command/parameter and/or data-in register. - * Soft reset doesn't do the job either. Fortunately no - * serious initialisation has been done yet so there's nothing - * to tidy up. - */ - outb(port+Rcontrol, Rhard); - for(timeo = 0; timeo < 100; timeo++){ - if(inb(port+Rstatus) == (Inreq|Hardy)) - break; - delay(100); - } - if(inb(port+Rstatus) != (Inreq|Hardy)) - goto buggery; - } - - /* - * If the BIOS is enabled on the AHA-1542C/CF and BIOS options for - * support of drives > 1Gb, dynamic scanning of the SCSI bus or more - * than 2 drives under DOS 5.0 are enabled, the BIOS disables - * accepting Cmbinit to protect against running with drivers which - * don't support those options. In order to unlock the interface it - * is necessary to read a lock-code using Cextbios and write it back - * using Cmbienable; the lock-code is non-zero. - */ - cmd[0] = Cinquiry; - clen = 1; - dlen = 4; - if(issue(ctlr, cmd, clen, data, dlen) == 0) - goto buggery; - if(data[0] >= 0x43){ - cmd[0] = Cextbios; - clen = 1; - dlen = 2; - if(issue(ctlr, cmd, clen, data, dlen) == 0) - goto buggery; - - /* - * Lock-code returned in data[1]. If it's non-zero write - * it back along with bit 0 of byte 0 cleared to enable - * mailbox initialisation. - */ - if(data[1]){ - cmd[0] = Cmbienable; - cmd[1] = 0; - cmd[2] = data[1]; - clen = 3; - if(issue(ctlr, cmd, clen, 0, 0) == 0) - goto buggery; - } - } - - /* - * Get the id, DMA and IRQ info from the board. This will - * cause an interrupt which will hopefully not cause any - * trouble because the interrupt number isn't known yet. - * This is necessary as the DMA won't be set up if the - * board has the BIOS disabled. - * - * If the IRQ is already known, this must be a 32-bit PCI - * or EISA card, in which case the returned DMA and IRQ can - * be ignored. - */ - cmd[0] = Cinquire; - clen = 1; - dlen = 3; - if(issue(ctlr, cmd, clen, data, dlen) == 0) - goto buggery; - - ctlr->id = data[2] & 0x07; - if(ctlr->irq < 0){ - switch(data[0]){ /* DMA Arbitration Priority */ - case 0x80: /* Channel 7 */ - outb(0xD6, 0xC3); - outb(0xD4, 0x03); - break; - case 0x40: /* Channel 6 */ - outb(0xD6, 0xC2); - outb(0xD4, 0x02); - break; - case 0x20: /* Channel 5 */ - outb(0xD6, 0xC1); - outb(0xD4, 0x01); - break; - case 0x01: /* Channel 0 */ - outb(0x0B, 0xC0); - outb(0x0A, 0x00); - break; - default: - if(ctlr->bus == 24) - goto buggery; - break; - } - - switch(data[1]){ /* Interrupt Channel */ - case 0x40: - ctlr->irq = 15; - break; - case 0x20: - ctlr->irq = 14; - break; - case 0x08: - ctlr->irq = 12; - break; - case 0x04: - ctlr->irq = 11; - break; - case 0x02: - ctlr->irq = 10; - break; - case 0x01: - ctlr->irq = 9; - break; - default: - goto buggery; - } - } - - if((sdev = malloc(sizeof(SDev))) == nil) - goto buggery; - sdev->ifc = &sdmylexifc; - sdev->ctlr = ctlr; - ctlr->sdev = sdev; - if(!ctlr->wide) - sdev->nunit = 8; - else - sdev->nunit = 16; - - return sdev; -} - -static int mylexport[8] = { - 0x330, 0x334, 0x230, 0x234, 0x130, 0x134, 0x000, 0x000, -}; - -static SDev* -mylexpnp(void) -{ - Pcidev *p; - Ctlr *ctlr; - ISAConf isa; - int cfg, ctlrno, i, x; - SDev *sdev, *head, *tail; - - p = nil; - head = tail = nil; - while(p = pcimatch(p, 0x104B, 0)){ - if((sdev = mylexprobe(p->mem[0].bar & ~0x01, p->intl)) == nil) - continue; - - ctlr = sdev->ctlr; - ctlr->pcidev = p; - - if(head != nil) - tail->next = sdev; - else - head = sdev; - tail = sdev; - } - - if(strncmp(KADDR(0xFFFD9), "EISA", 4) == 0){ - for(cfg = 0x1000; cfg < MaxEISA*0x1000; cfg += 0x1000){ - x = 0; - for(i = 0; i < 4; i++) - x |= inb(cfg+CfgEISA+i)<<(i*8); - if(x != 0x0142B30A && x != 0x0242B30A) - continue; - - x = inb(cfg+0xC8C); - if((sdev = mylexprobe(mylexport[x & 0x07], -1)) == nil) - continue; - - if(head != nil) - tail->next = sdev; - else - head = sdev; - tail = sdev; - } - } - - for(ctlrno = 0; ctlrno < 4; ctlrno++){ - memset(&isa, 0, sizeof(isa)); - if(!isaconfig("scsi", ctlrno, &isa)) - continue; - if(strcmp(isa.type, "aha1542")) - continue; - if((sdev = mylexprobe(isa.port, -1)) == nil) - continue; - - if(head != nil) - tail->next = sdev; - else - head = sdev; - tail = sdev; - } - - return head; -} - -static SDev* -mylexid(SDev* sdev) -{ - return scsiid(sdev, &sdmylexifc); -} - -static int -mylex24enable(Ctlr* ctlr) -{ - ulong p; - Ccb24 *ccb, *ccbp; - uchar cmd[6], *v; - int len; - - len = (sizeof(Mbox24)*NMbox*2)+(sizeof(Ccb24)*NCcb); - v = xspanalloc(len, 32, 0); - - if(!PADDR24(ctlr, sizeof(Ctlr)) || !PADDR24(v, len)) - return 0; - - ctlr->mb = v; - v += sizeof(Mbox24)*NMbox*2; - - ccb = (Ccb24*)v; - for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){ - ccbp->ccb = ctlr->ccb; - ctlr->ccb = (Ccb*)ccbp; - } - - /* - * Initialise the software controller and - * set the board scanning the mailboxes. - */ - ctlr->mbix = NMbox; - - cmd[0] = Cinitialise; - cmd[1] = NMbox; - p = K2BPA(ctlr->mb, BUSUNKNOWN); - cmd[2] = p>>16; - cmd[3] = p>>8; - cmd[4] = p; - - return issue(ctlr, cmd, 5, 0, 0); -} - -static int -mylex32enable(Ctlr* ctlr) -{ - ulong p; - Ccb32 *ccb, *ccbp; - uchar cmd[6], *v; - - v = xspanalloc((sizeof(Mbox32)*NMbox*2)+(sizeof(Ccb32)*NCcb), 32, 0); - - ctlr->mb = v; - v += sizeof(Mbox32)*NMbox*2; - - ccb = (Ccb32*)v; - for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){ - /* - * Fill in some stuff that doesn't change. - */ - ccbp->senselen = sizeof(ccbp->sense); - p = PADDR(ccbp->sense); - ccbp->senseptr[0] = p; - ccbp->senseptr[1] = p>>8; - ccbp->senseptr[2] = p>>16; - ccbp->senseptr[3] = p>>24; - - ccbp->ccb = ctlr->ccb; - ctlr->ccb = (Ccb*)ccbp; - } - - /* - * Attempt wide mode setup. - */ - if(ctlr->wide){ - cmd[0] = Cwide; - cmd[1] = 1; - if(!issue(ctlr, cmd, 2, 0, 0)) - ctlr->wide = 0; - } - - /* - * Initialise the software controller and - * set the board scanning the mailboxes. - */ - ctlr->mbix = NMbox; - - cmd[0] = Ciem; - cmd[1] = NMbox; - if(ctlr->pcidev) - p = K2BPA(ctlr->mb, ctlr->tbdf); - else - p = K2BPA(ctlr->mb, BUSUNKNOWN); - cmd[2] = p; - cmd[3] = p>>8; - cmd[4] = p>>16; - cmd[5] = p>>24; - - return issue(ctlr, cmd, 6, 0, 0); -} - -static int -mylexenable(SDev* sdev) -{ - int tbdf; - Ctlr *ctlr; - void (*interrupt)(Ureg*, void*); - char name[32]; - - 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, sizeof(name), "sd%c (%s)", sdev->idno, sdev->ifc->name); - intrenable(ctlr->irq, interrupt, ctlr, tbdf, name); - - return 1; -} - -SDifc sdmylexifc = { - "mylex", /* name */ - - mylexpnp, /* pnp */ - nil, /* legacy */ - mylexid, /* id */ - mylexenable, /* enable */ - nil, /* disable */ - - scsiverify, /* verify */ - scsionline, /* online */ - mylexrio, /* rio */ - nil, /* rctl */ - nil, /* wctl */ - - scsibio, /* bio */ - nil, /* probe */ - nil, /* clear */ - nil, /* stat */ -}; diff --git a/os/pc/sdscsi.c b/os/pc/sdscsi.c deleted file mode 100644 index 0340564c..00000000 --- a/os/pc/sdscsi.c +++ /dev/null @@ -1,394 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" -#include "../port/error.h" - -#include "../port/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; - - return r->unit->dev->ifc->rio(r); -} - -int -scsiverify(SDunit* unit) -{ - SDreq *r; - int i, status; - uchar *inquiry; - - if((r = malloc(sizeof(SDreq))) == nil) - return 0; - if((inquiry = sdmalloc(sizeof(unit->inquiry))) == nil){ - free(r); - 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; - if(unit->dev->ifc->rio(r) != SDok){ - free(r); - return 0; - } - memmove(unit->inquiry, inquiry, r->dlen); - free(inquiry); - - 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. - * Don't wait for completion, 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)|0x01; - r->cmd[4] = 1; - r->clen = 6; - r->data = nil; - r->dlen = 0; - r->flags = 0; - - r->status = ~0; - unit->dev->ifc->rio(r); - } - } - free(r); - - if(status == SDok || status == SDcheck) - return 1; - return 0; -} - -static int -scsirio(SDreq* r) -{ - /* - * Perform an I/O request, returning - * -1 failure - * 0 ok - * 1 no medium present - * 2 retry - * The contents of r may be altered so the - * caller should re-initialise if necesary. - */ - r->status = ~0; - switch(r->unit->dev->ifc->rio(r)){ - default: - return -1; - 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; - return -1; - 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; - - while(waserror()) - ; - tsleep(&up->sleep, return0, 0, 500); - poperror(); - scsitest(r); - return 2; - default: - return -1; - } - return -1; - case SDok: - return 0; - } - return -1; -} - -int -scsionline(SDunit* unit) -{ - SDreq *r; - uchar *p; - int ok, retries; - - if((r = malloc(sizeof(SDreq))) == nil) - return 0; - if((p = sdmalloc(8)) == nil){ - free(r); - return 0; - } - - ok = 0; - - r->unit = unit; - r->lun = 0; /* ??? */ - for(retries = 0; retries < 10; retries++){ - /* - * 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; - switch(scsirio(r)){ - default: - break; - case 0: - unit->sectors = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; - if(unit->sectors == 0) - continue; - /* - * 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]; - - /* - * Some ATAPI CD readers lie about the block size. - * Since we don't read audio via this interface - * it's okay to always fudge this. - */ - if(unit->secsize == 2352) - unit->secsize = 2048; - ok = 1; - break; - case 1: - ok = 1; - break; - case 2: - continue; - } - break; - } - free(p); - free(r); - - if(ok) - return ok+retries; - else - return 0; -} - -int -scsiexec(SDunit* unit, int write, uchar* cmd, int clen, void* data, int* dlen) -{ - SDreq *r; - int status; - - if((r = malloc(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. - */ - 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; - } - sdfree(r); - - return status; -} - -long -scsibio(SDunit* unit, int lun, int write, void* data, long nb, long bno) -{ - SDreq *r; - long rlen; - - if((r = malloc(sizeof(SDreq))) == nil) - error(Enomem); - 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; - 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 by zapping 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; - } - free(r); - - return rlen; -} - -SDev* -scsiid(SDev* sdev, SDifc* ifc) -{ - char name[32]; - static char idno[16] = "0123456789abcdef"; - static char *p = idno; - - while(sdev){ - if(sdev->ifc == ifc){ - sdev->idno = *p++; - snprint(name, sizeof(name), "sd%c", sdev->idno); - kstrdup(&sdev->name, name); - if(p >= &idno[sizeof(idno)]) - break; - } - sdev = sdev->next; - } - - return nil; -} diff --git a/os/pc/trap.c b/os/pc/trap.c deleted file mode 100644 index 465c9bab..00000000 --- a/os/pc/trap.c +++ /dev/null @@ -1,571 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" -#include "../port/error.h" - -int (*breakhandler)(Ureg *ur, Proc*); - -static void debugbpt(Ureg*, void*); -static void fault386(Ureg*, void*); -static void doublefault(Ureg*, void*); -static void unexpected(Ureg*, void*); -static void _dumpstack(Ureg*); - -static Lock vctllock; -static Vctl *vctl[256]; - -enum -{ - Ntimevec = 20 /* number of time buckets for each intr */ -}; -ulong intrtimes[256][Ntimevec]; - -void -intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name) -{ - int vno; - Vctl *v; - - if(f == nil){ - print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n", - irq, tbdf, name); - return; - } - - v = xalloc(sizeof(Vctl)); - v->isintr = 1; - v->irq = irq; - v->tbdf = tbdf; - v->f = f; - v->a = a; - strncpy(v->name, name, KNAMELEN-1); - v->name[KNAMELEN-1] = 0; - - ilock(&vctllock); - vno = arch->intrenable(v); - if(vno == -1){ - iunlock(&vctllock); - print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n", - irq, tbdf, v->name); - xfree(v); - return; - } - if(vctl[vno]){ - if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi) - panic("intrenable: handler: %s %s %luX %luX %luX %luX\n", - vctl[vno]->name, v->name, - vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi); - v->next = vctl[vno]; - } - vctl[vno] = v; - iunlock(&vctllock); -} - -int -intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name) -{ - Vctl **pv, *v; - int vno; - - /* - * For now, none of this will work with the APIC code, - * there is no mapping between irq and vector as the IRQ - * is pretty meaningless. - */ - if(arch->intrvecno == nil) - return -1; - vno = arch->intrvecno(irq); - ilock(&vctllock); - pv = &vctl[vno]; - while (*pv && - ((*pv)->irq != irq || (*pv)->tbdf != tbdf || (*pv)->f != f || (*pv)->a != a || - strcmp((*pv)->name, name))) - pv = &((*pv)->next); - assert(*pv); - - v = *pv; - *pv = (*pv)->next; /* Link out the entry */ - - if(vctl[vno] == nil && arch->intrdisable != nil) - arch->intrdisable(irq); - iunlock(&vctllock); - xfree(v); - return 0; -} - -static long -irqallocread(Chan*, void *vbuf, long n, vlong offset) -{ - char *buf, *p, str[2*(11+1)+KNAMELEN+1+1]; - int m, vno; - long oldn; - Vctl *v; - - if(n < 0 || offset < 0) - error(Ebadarg); - - oldn = n; - buf = vbuf; - for(vno=0; vnonext){ - m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name); - if(m <= offset) /* if do not want this, skip entry */ - offset -= m; - else{ - /* skip offset bytes */ - m -= offset; - p = str+offset; - offset = 0; - - /* write at most max(n,m) bytes */ - if(m > n) - m = n; - memmove(buf, p, m); - n -= m; - buf += m; - - if(n == 0) - return oldn; - } - } - } - return oldn - n; -} - -void -trapenable(int vno, void (*f)(Ureg*, void*), void* a, char *name) -{ - Vctl *v; - - if(vno < 0 || vno >= VectorPIC) - panic("trapenable: vno %d\n", vno); - v = xalloc(sizeof(Vctl)); - v->tbdf = BUSUNKNOWN; - v->f = f; - v->a = a; - strncpy(v->name, name, KNAMELEN); - v->name[KNAMELEN-1] = 0; - - lock(&vctllock); - if(vctl[vno]) - v->next = vctl[vno]->next; - vctl[vno] = v; - unlock(&vctllock); -} - -static void -nmienable(void) -{ - int x; - - /* - * Hack: should be locked with NVRAM access. - */ - outb(0x70, 0x80); /* NMI latch clear */ - outb(0x70, 0); - - x = inb(0x61) & 0x07; /* Enable NMI */ - outb(0x61, 0x08|x); - outb(0x61, x); -} - -void -trapinit(void) -{ - int d1, v; - ulong vaddr; - Segdesc *idt; - - idt = (Segdesc*)IDTADDR; - vaddr = (ulong)vectortable; - for(v = 0; v < 256; v++){ - d1 = (vaddr & 0xFFFF0000)|SEGP; - switch(v){ - - case VectorBPT: - d1 |= SEGPL(3)|SEGIG; - break; - - case VectorSYSCALL: - d1 |= SEGPL(3)|SEGIG; - break; - - default: - d1 |= SEGPL(0)|SEGIG; - break; - } - idt[v].d0 = (vaddr & 0xFFFF)|(KESEL<<16); - idt[v].d1 = d1; - vaddr += 6; - } - - /* - * Special traps. - * Syscall() is called directly without going through trap(). - */ - trapenable(VectorBPT, debugbpt, 0, "debugpt"); - trapenable(VectorPF, fault386, 0, "fault386"); - trapenable(Vector2F, doublefault, 0, "doublefault"); - trapenable(Vector15, unexpected, 0, "unexpected"); - - nmienable(); - - addarchfile("irqalloc", 0444, irqallocread, nil); -} - -static char* excname[32] = { - "divide error", - "debug exception", - "nonmaskable interrupt", - "breakpoint", - "overflow", - "bounds check", - "invalid opcode", - "coprocessor not available", - "double fault", - "coprocessor segment overrun", - "invalid TSS", - "segment not present", - "stack exception", - "general protection violation", - "page fault", - "15 (reserved)", - "coprocessor error", - "alignment check", - "machine check", - "19 (reserved)", - "20 (reserved)", - "21 (reserved)", - "22 (reserved)", - "23 (reserved)", - "24 (reserved)", - "25 (reserved)", - "26 (reserved)", - "27 (reserved)", - "28 (reserved)", - "29 (reserved)", - "30 (reserved)", - "31 (reserved)", -}; - -/* - * keep histogram of interrupt service times - */ -void -intrtime(Mach*, int vno) -{ - USED(vno); -} - -/* - * All traps come here. It is slower to have all traps call trap() - * rather than directly vectoring the handler. However, this avoids a - * lot of code duplication and possible bugs. The only exception is - * VectorSYSCALL. - * Trap is called with interrupts disabled via interrupt-gates. - */ -void -trap(Ureg* ureg) -{ - int i, vno; - char buf[ERRMAX]; - Vctl *ctl, *v; - Mach *mach; - - vno = ureg->trap; - if(ctl = vctl[vno]){ - if(ctl->isintr){ - m->intr++; - if(vno >= VectorPIC && vno != VectorSYSCALL) - m->lastintr = ctl->irq; - } - - if(ctl->isr) - ctl->isr(vno); - for(v = ctl; v != nil; v = v->next){ - if(v->f) - v->f(ureg, v->a); - } - if(ctl->eoi) - ctl->eoi(vno); - - if(ctl->isintr){ - if(up && ctl->irq != IrqTIMER && ctl->irq != IrqCLOCK) - preemption(0); - } - } - else if(vno <= nelem(excname) && up->type == Interp){ - spllo(); - sprint(buf, "sys: trap: %s", excname[vno]); - error(buf); - } - else if(vno >= VectorPIC && vno != VectorSYSCALL){ - /* - * An unknown interrupt. - * 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. - */ - - /* call all interrupt routines, just in case */ - for(i = VectorPIC; i <= MaxIrqLAPIC; i++){ - ctl = vctl[i]; - if(ctl == nil) - continue; - if(!ctl->isintr) - continue; - for(v = ctl; v != nil; v = v->next){ - if(v->f) - v->f(ureg, v->a); - } - /* should we do this? */ - if(ctl->eoi) - ctl->eoi(i); - } - - /* clear the interrupt */ - i8259isr(vno); - - if(0)print("cpu%d: spurious interrupt %d, last %d", - m->machno, vno, m->lastintr); - if(0)if(conf.nmach > 1){ - for(i = 0; i < 32; i++){ - if(!(active.machs & (1<machno == mach->machno) - continue; - print(" cpu%d: last %d", - mach->machno, mach->lastintr); - } - print("\n"); - } - m->spuriousintr++; - return; - } - else{ - if(vno == VectorNMI){ - nmienable(); - if(m->machno != 0){ - print("cpu%d: PC %8.8luX\n", - m->machno, ureg->pc); - for(;;); - } - } - dumpregs(ureg); - if(vno < nelem(excname)) - panic("%s", excname[vno]); - panic("unknown trap/intr: %d\n", vno); - } - - /* delaysched set because we held a lock or because our quantum ended */ - if(up && up->delaysched){ - sched(); - splhi(); - } -} - -/* - * dump registers - */ -void -dumpregs2(Ureg* ureg) -{ - if(up) - print("cpu%d: registers for %s %lud\n", - m->machno, up->text, up->pid); - else - print("cpu%d: registers for kernel\n", m->machno); - print("FLAGS=%luX TRAP=%luX ECODE=%luX PC=%luX", - ureg->flags, ureg->trap, ureg->ecode, ureg->pc); - print(" SS=%4.4luX USP=%luX\n", ureg->ss & 0xFFFF, ureg->usp); - print(" AX %8.8luX BX %8.8luX CX %8.8luX DX %8.8luX\n", - ureg->ax, ureg->bx, ureg->cx, ureg->dx); - print(" SI %8.8luX DI %8.8luX BP %8.8luX\n", - ureg->si, ureg->di, ureg->bp); - print(" CS %4.4luX DS %4.4luX ES %4.4luX FS %4.4luX GS %4.4luX\n", - ureg->cs & 0xFFFF, ureg->ds & 0xFFFF, ureg->es & 0xFFFF, - ureg->fs & 0xFFFF, ureg->gs & 0xFFFF); -} - -void -dumpregs(Ureg* ureg) -{ - extern ulong etext; - vlong mca, mct; - - dumpregs2(ureg); - - /* - * Processor control registers. - * If machine check exception, time stamp counter, page size extensions - * or enhanced virtual 8086 mode extensions are supported, there is a - * CR4. If there is a CR4 and machine check extensions, read the machine - * check address and machine check type registers if RDMSR supported. - */ - print(" CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux", - getcr0(), getcr2(), getcr3()); - if(m->cpuiddx & 0x9A){ - print(" CR4 %8.8lux", getcr4()); - if((m->cpuiddx & 0xA0) == 0xA0){ - rdmsr(0x00, &mca); - rdmsr(0x01, &mct); - print("\n MCA %8.8llux MCT %8.8llux", mca, mct); - } - } - print("\n ur %lux up %lux\n", ureg, up); -} - -/* - * Fill in enough of Ureg to get a stack trace, and call a function. - * Used by debugging interface rdb. - */ -void -callwithureg(void (*fn)(Ureg*)) -{ - Ureg ureg; - ureg.pc = getcallerpc(&fn); - ureg.sp = (ulong)&fn; - fn(&ureg); -} - -static void -_dumpstack(Ureg *ureg) -{ - ulong l, v, i, estack; - extern ulong etext; - - print("ktrace /kernel/path %.8lux %.8lux\n", ureg->pc, ureg->sp); - i = 0; - if(up - && (ulong)&l >= (ulong)up->kstack - && (ulong)&l <= (ulong)up->kstack+KSTACK) - estack = (ulong)up->kstack+KSTACK; - else if((ulong)&l >= (ulong)m->stack - && (ulong)&l <= (ulong)m+BY2PG) - estack = (ulong)m+MACHSIZE; - else - return; - - for(l=(ulong)&l; lpc--; - sprint(buf, "sys: breakpoint"); - error(buf); -} - -static void -doublefault(Ureg*, void*) -{ - panic("double fault"); -} - -static void -unexpected(Ureg* ureg, void*) -{ - print("unexpected trap %lud; ignoring\n", ureg->trap); -} - -static void -fault386(Ureg* ureg, void*) -{ - ulong addr; - int read, user; - char buf[ERRMAX]; - - addr = getcr2(); - user = (ureg->cs & 0xFFFF) == UESEL; - if(!user && mmukmapsync(addr)) - return; - read = !(ureg->ecode & 2); - spllo(); - snprint(buf, sizeof(buf), "trap: fault %s pc=0x%lux addr=0x%lux", - read ? "read" : "write", ureg->pc, addr); - if(up->type == Interp) - disfault(ureg, buf); - dumpregs(ureg); - panic("fault: %s\n", buf); -} - - - - - -static void -linkproc(void) -{ - spllo(); - up->kpfun(up->arg); - pexit("kproc dying", 0); -} - -void -kprocchild(Proc* p, void (*func)(void*), void* arg) -{ - /* - * gotolabel() needs a word on the stack in - * which to place the return PC used to jump - * to linkproc(). - */ - p->sched.pc = (ulong)linkproc; - p->sched.sp = (ulong)p->kstack+KSTACK-BY2WD; - - p->kpfun = func; - p->arg = arg; -} - - - -ulong -dbgpc(Proc *p) -{ - Ureg *ureg; - - ureg = p->dbgreg; - if(ureg == 0) - return 0; - - return ureg->pc; -} diff --git a/os/pc/tv.h b/os/pc/tv.h deleted file mode 100644 index 181563b8..00000000 --- a/os/pc/tv.h +++ /dev/null @@ -1,15 +0,0 @@ -static ushort -swab16(ushort u) { - return u; -} - -#define ScreenWidth 640 /* screen width */ -#define ScreenHeight 480 /* screen height */ -#define XCorrection 9 /* correction for x axes (trial and error) */ -#define YCorrection 32 /* correction for y axes (trial and error) */ -#define HSync 1 -#define VSync 1 - -#define AudioChip TEA6320T /* new board has TEA6320T */ - -#define EISA(a) (a) diff --git a/os/pc/uarti8250.c b/os/pc/uarti8250.c deleted file mode 100644 index 2d6c0da2..00000000 --- a/os/pc/uarti8250.c +++ /dev/null @@ -1,740 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/uart.h" - -/* - * 8250 UART and compatibles. - */ -enum { - Uart0 = 0x3F8, /* COM1 */ - Uart0IRQ = 4, - Uart1 = 0x2F8, /* COM2 */ - Uart1IRQ = 3, - - UartFREQ = 1843200, -}; - -enum { /* I/O ports */ - Rbr = 0, /* Receiver Buffer (RO) */ - Thr = 0, /* Transmitter Holding (WO) */ - Ier = 1, /* Interrupt Enable */ - Iir = 2, /* Interrupt Identification (RO) */ - Fcr = 2, /* FIFO Control (WO) */ - Lcr = 3, /* Line Control */ - Mcr = 4, /* Modem Control */ - Lsr = 5, /* Line Status */ - Msr = 6, /* Modem Status */ - Scr = 7, /* Scratch Pad */ - Dll = 0, /* Divisor Latch LSB */ - Dlm = 1, /* Divisor Latch MSB */ -}; - -enum { /* Ier */ - Erda = 0x01, /* Enable Received Data Available */ - Ethre = 0x02, /* Enable Thr Empty */ - Erls = 0x04, /* Enable Receiver Line Status */ - Ems = 0x08, /* Enable Modem Status */ -}; - -enum { /* Iir */ - Ims = 0x00, /* Ms interrupt */ - Ip = 0x01, /* Interrupt Pending (not) */ - Ithre = 0x02, /* Thr Empty */ - Irda = 0x04, /* Received Data Available */ - Irls = 0x06, /* Receiver Line Status */ - Ictoi = 0x0C, /* Character Time-out Indication */ - IirMASK = 0x3F, - Ifena = 0xC0, /* FIFOs enabled */ -}; - -enum { /* Fcr */ - FIFOena = 0x01, /* FIFO enable */ - FIFOrclr = 0x02, /* clear Rx FIFO */ - FIFOtclr = 0x04, /* clear Tx FIFO */ - FIFO1 = 0x00, /* Rx FIFO trigger level 1 byte */ - FIFO4 = 0x40, /* 4 bytes */ - FIFO8 = 0x80, /* 8 bytes */ - FIFO14 = 0xC0, /* 14 bytes */ -}; - -enum { /* Lcr */ - Wls5 = 0x00, /* Word Length Select 5 bits/byte */ - Wls6 = 0x01, /* 6 bits/byte */ - Wls7 = 0x02, /* 7 bits/byte */ - Wls8 = 0x03, /* 8 bits/byte */ - WlsMASK = 0x03, - Stb = 0x04, /* 2 stop bits */ - Pen = 0x08, /* Parity Enable */ - Eps = 0x10, /* Even Parity Select */ - Stp = 0x20, /* Stick Parity */ - Brk = 0x40, /* Break */ - Dlab = 0x80, /* Divisor Latch Access Bit */ -}; - -enum { /* Mcr */ - Dtr = 0x01, /* Data Terminal Ready */ - Rts = 0x02, /* Ready To Send */ - Out1 = 0x04, /* no longer in use */ - Ie = 0x08, /* IRQ Enable */ - Dm = 0x10, /* Diagnostic Mode loopback */ -}; - -enum { /* Lsr */ - Dr = 0x01, /* Data Ready */ - Oe = 0x02, /* Overrun Error */ - Pe = 0x04, /* Parity Error */ - Fe = 0x08, /* Framing Error */ - Bi = 0x10, /* Break Interrupt */ - Thre = 0x20, /* Thr Empty */ - Temt = 0x40, /* Tramsmitter Empty */ - FIFOerr = 0x80, /* error in receiver FIFO */ -}; - -enum { /* Msr */ - Dcts = 0x01, /* Delta Cts */ - Ddsr = 0x02, /* Delta Dsr */ - Teri = 0x04, /* Trailing Edge of Ri */ - Ddcd = 0x08, /* Delta Dcd */ - Cts = 0x10, /* Clear To Send */ - Dsr = 0x20, /* Data Set Ready */ - Ri = 0x40, /* Ring Indicator */ - Dcd = 0x80, /* Data Set Ready */ -}; - -typedef struct Ctlr { - int io; - int irq; - int tbdf; - int iena; - - uchar sticky[8]; - - Lock; - int hasfifo; - int checkfifo; - int fena; -} Ctlr; - -extern PhysUart i8250physuart; - -static Ctlr i8250ctlr[2] = { -{ .io = Uart0, - .irq = Uart0IRQ, - .tbdf = BUSUNKNOWN, }, - -{ .io = Uart1, - .irq = Uart1IRQ, - .tbdf = BUSUNKNOWN, }, -}; - -static Uart i8250uart[2] = { -{ .regs = &i8250ctlr[0], - .name = "COM1", - .freq = UartFREQ, - .phys = &i8250physuart, - .special= 0, - .next = &i8250uart[1], }, - -{ .regs = &i8250ctlr[1], - .name = "COM2", - .freq = UartFREQ, - .phys = &i8250physuart, - .special= 0, - .next = nil, }, -}; - -#define csr8r(c, r) inb((c)->io+(r)) -#define csr8w(c, r, v) outb((c)->io+(r), (c)->sticky[(r)]|(v)) - -static long -i8250status(Uart* uart, void* buf, long n, long offset) -{ - char *p; - Ctlr *ctlr; - uchar ier, lcr, mcr, msr; - - ctlr = uart->regs; - p = malloc(READSTR); - mcr = ctlr->sticky[Mcr]; - msr = csr8r(ctlr, Msr); - ier = ctlr->sticky[Ier]; - lcr = ctlr->sticky[Lcr]; - snprint(p, READSTR, - "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n" - "dev(%d) type(%d) framing(%d) overruns(%d) " - "berr(%d) serr(%d)%s%s%s%s\n", - - uart->baud, - uart->hup_dcd, - (msr & Dsr) != 0, - uart->hup_dsr, - (lcr & WlsMASK) + 5, - (ier & Ems) != 0, - (lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n', - (mcr & Rts) != 0, - (lcr & Stb) ? 2: 1, - ctlr->fena, - - uart->dev, - uart->type, - uart->ferr, - uart->oerr, - uart->berr, - uart->serr, - (msr & Cts) ? " cts": "", - (msr & Dsr) ? " dsr": "", - (msr & Dcd) ? " dcd": "", - (msr & Ri) ? " ring": "" - ); - n = readstr(offset, buf, n, p); - free(p); - - return n; -} - -static void -i8250fifo(Uart* uart, int level) -{ - Ctlr *ctlr; - - ctlr = uart->regs; - if(ctlr->hasfifo == 0) - return; - - /* - * Changing the FIFOena bit in Fcr flushes data - * from both receive and transmit FIFOs; there's - * no easy way to guarantee not losing data on - * the receive side, but it's possible to wait until - * the transmitter is really empty. - */ - ilock(ctlr); - while(!(csr8r(ctlr, Lsr) & Temt)) - ; - - /* - * Set the trigger level, default is the max. - * value. - * Some UARTs require FIFOena to be set before - * other bits can take effect, so set it twice. - */ - ctlr->fena = level; - switch(level){ - case 0: - break; - case 1: - level = FIFO1|FIFOena; - break; - case 4: - level = FIFO4|FIFOena; - break; - case 8: - level = FIFO8|FIFOena; - break; - default: - level = FIFO14|FIFOena; - break; - } - csr8w(ctlr, Fcr, level); - csr8w(ctlr, Fcr, level); - iunlock(ctlr); -} - -static void -i8250dtr(Uart* uart, int on) -{ - Ctlr *ctlr; - - /* - * Toggle DTR. - */ - ctlr = uart->regs; - if(on) - ctlr->sticky[Mcr] |= Dtr; - else - ctlr->sticky[Mcr] &= ~Dtr; - csr8w(ctlr, Mcr, 0); -} - -static void -i8250rts(Uart* uart, int on) -{ - Ctlr *ctlr; - - /* - * Toggle RTS. - */ - ctlr = uart->regs; - if(on) - ctlr->sticky[Mcr] |= Rts; - else - ctlr->sticky[Mcr] &= ~Rts; - csr8w(ctlr, Mcr, 0); -} - -static void -i8250modemctl(Uart* uart, int on) -{ - Ctlr *ctlr; - - ctlr = uart->regs; - ilock(&uart->tlock); - if(on){ - ctlr->sticky[Ier] |= Ems; - csr8w(ctlr, Ier, ctlr->sticky[Ier]); - uart->modem = 1; - uart->cts = csr8r(ctlr, Msr) & Cts; - } - else{ - ctlr->sticky[Ier] &= ~Ems; - csr8w(ctlr, Ier, ctlr->sticky[Ier]); - uart->modem = 0; - uart->cts = 1; - } - iunlock(&uart->tlock); - - /* modem needs fifo */ - (*uart->phys->fifo)(uart, on); -} - -static int -i8250parity(Uart* uart, int parity) -{ - int lcr; - Ctlr *ctlr; - - ctlr = uart->regs; - lcr = ctlr->sticky[Lcr] & ~(Eps|Pen); - - switch(parity){ - case 'e': - lcr |= Eps|Pen; - break; - case 'o': - lcr |= Pen; - break; - case 'n': - break; - default: - return -1; - } - ctlr->sticky[Lcr] = lcr; - csr8w(ctlr, Lcr, 0); - - uart->parity = parity; - - return 0; -} - -static int -i8250stop(Uart* uart, int stop) -{ - int lcr; - Ctlr *ctlr; - - ctlr = uart->regs; - lcr = ctlr->sticky[Lcr] & ~Stb; - - switch(stop){ - case 1: - break; - case 2: - lcr |= Stb; - break; - default: - return -1; - } - ctlr->sticky[Lcr] = lcr; - csr8w(ctlr, Lcr, 0); - - uart->stop = stop; - - return 0; -} - -static int -i8250bits(Uart* uart, int bits) -{ - int lcr; - Ctlr *ctlr; - - ctlr = uart->regs; - lcr = ctlr->sticky[Lcr] & ~WlsMASK; - - switch(bits){ - case 5: - lcr |= Wls5; - break; - case 6: - lcr |= Wls6; - break; - case 7: - lcr |= Wls7; - break; - case 8: - lcr |= Wls8; - break; - default: - return -1; - } - ctlr->sticky[Lcr] = lcr; - csr8w(ctlr, Lcr, 0); - - uart->bits = bits; - - return 0; -} - -static int -i8250baud(Uart* uart, int baud) -{ - ulong bgc; - Ctlr *ctlr; - - /* - * Set the Baud rate by calculating and setting the Baud rate - * Generator Constant. This will work with fairly non-standard - * Baud rates. - */ - if(uart->freq == 0 || baud <= 0) - return -1; - bgc = (uart->freq+8*baud-1)/(16*baud); - - ctlr = uart->regs; - csr8w(ctlr, Lcr, Dlab); - outb(ctlr->io+Dlm, bgc>>8); - outb(ctlr->io+Dll, bgc); - csr8w(ctlr, Lcr, 0); - - uart->baud = baud; - - return 0; -} - -static void -i8250break(Uart* uart, int ms) -{ - Ctlr *ctlr; - - /* - * Send a break. - */ - if(ms <= 0) - ms = 200; - - ctlr = uart->regs; - csr8w(ctlr, Lcr, Brk); - tsleep(&up->sleep, return0, 0, ms); - csr8w(ctlr, Lcr, 0); -} - -static void -i8250kick(Uart* uart) -{ - int i; - Ctlr *ctlr; - - if(uart->cts == 0 || uart->blocked) - return; - - /* - * 128 here is an arbitrary limit to make sure - * we don't stay in this loop too long. If the - * chip's output queue is longer than 128, too - * bad -- presotto - */ - ctlr = uart->regs; - for(i = 0; i < 128; i++){ - if(!(csr8r(ctlr, Lsr) & Thre)) - break; - if(uart->op >= uart->oe && uartstageoutput(uart) == 0) - break; - outb(ctlr->io+Thr, *(uart->op++)); - } -} - -static void -i8250interrupt(Ureg*, void* arg) -{ - Ctlr *ctlr; - Uart *uart; - int iir, lsr, old, r; - - uart = arg; - - ctlr = uart->regs; - for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){ - switch(iir & IirMASK){ - case Ims: /* Ms interrupt */ - r = csr8r(ctlr, Msr); - if(r & Dcts){ - ilock(&uart->tlock); - old = uart->cts; - uart->cts = r & Cts; - if(old == 0 && uart->cts) - uart->ctsbackoff = 2; - iunlock(&uart->tlock); - } - if(r & Ddsr){ - old = r & Dsr; - if(uart->hup_dsr && uart->dsr && !old) - uart->dohup = 1; - uart->dsr = old; - } - if(r & Ddcd){ - old = r & Dcd; - if(uart->hup_dcd && uart->dcd && !old) - uart->dohup = 1; - uart->dcd = old; - } - break; - case Ithre: /* Thr Empty */ - uartkick(uart); - break; - case Irda: /* Received Data Available */ - case Irls: /* Receiver Line Status */ - case Ictoi: /* Character Time-out Indication */ - /* - * Consume any received data. - * If the received byte came in with a break, - * parity or framing error, throw it away; - * overrun is an indication that something has - * already been tossed. - */ - while((lsr = csr8r(ctlr, Lsr)) & Dr){ - if(lsr & (FIFOerr|Oe)) - uart->oerr++; - if(lsr & Pe) - uart->perr++; - if(lsr & Fe) - uart->ferr++; - r = csr8r(ctlr, Rbr); - if(!(lsr & (Bi|Fe|Pe))) - uartrecv(uart, r); - } - break; - - default: - iprint("weird uart interrupt 0x%2.2uX\n", iir); - break; - } - } -} - -static void -i8250disable(Uart* uart) -{ - Ctlr *ctlr; - - /* - * Turn off DTR and RTS, disable interrupts and fifos. - */ - (*uart->phys->dtr)(uart, 0); - (*uart->phys->rts)(uart, 0); - (*uart->phys->fifo)(uart, 0); - - ctlr = uart->regs; - ctlr->sticky[Ier] = 0; - csr8w(ctlr, Ier, ctlr->sticky[Ier]); - - if(ctlr->iena != 0){ - if(intrdisable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name) == 0) - ctlr->iena = 0; - } -} - -static void -i8250enable(Uart* uart, int ie) -{ - Ctlr *ctlr; - - ctlr = uart->regs; - - /* - * Check if there is a FIFO. - * Changing the FIFOena bit in Fcr flushes data - * from both receive and transmit FIFOs; there's - * no easy way to guarantee not losing data on - * the receive side, but it's possible to wait until - * the transmitter is really empty. - * Also, reading the Iir outwith i8250interrupt() - * can be dangerous, but this should only happen - * once, before interrupts are enabled. - */ - ilock(ctlr); - if(!ctlr->checkfifo){ - /* - * Wait until the transmitter is really empty. - */ - while(!(csr8r(ctlr, Lsr) & Temt)) - ; - csr8w(ctlr, Fcr, FIFOena); - if(csr8r(ctlr, Iir) & Ifena) - ctlr->hasfifo = 1; - csr8w(ctlr, Fcr, 0); - ctlr->checkfifo = 1; - } - iunlock(ctlr); - - /* - * Enable interrupts and turn on DTR and RTS. - * Be careful if this is called to set up a polled serial line - * early on not to try to enable interrupts as interrupt- - * -enabling mechanisms might not be set up yet. - */ - if(ie){ - if(ctlr->iena == 0){ - intrenable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name); - ctlr->iena = 1; - } - ctlr->sticky[Ier] = Ethre|Erda; - ctlr->sticky[Mcr] |= Ie; - } - else{ - ctlr->sticky[Ier] = 0; - ctlr->sticky[Mcr] = 0; - } - csr8w(ctlr, Ier, ctlr->sticky[Ier]); - csr8w(ctlr, Mcr, ctlr->sticky[Mcr]); - - (*uart->phys->dtr)(uart, 1); - (*uart->phys->rts)(uart, 1); - - /* - * During startup, the i8259 interrupt controller is reset. - * This may result in a lost interrupt from the i8250 uart. - * The i8250 thinks the interrupt is still outstanding and does not - * generate any further interrupts. The workaround is to call the - * interrupt handler to clear any pending interrupt events. - * Note: this must be done after setting Ier. - */ - if(ie) - i8250interrupt(nil, uart); -} - -void* -i8250alloc(int io, int irq, int tbdf) -{ - Ctlr *ctlr; - - if((ctlr = malloc(sizeof(Ctlr))) != nil){ - ctlr->io = io; - ctlr->irq = irq; - ctlr->tbdf = tbdf; - } - - return ctlr; -} - -static Uart* -i8250pnp(void) -{ - return i8250uart; -} - -static int -i8250getc(Uart *uart) -{ - Ctlr *ctlr; - - ctlr = uart->regs; - while(!(csr8r(ctlr, Lsr)&Dr)) - delay(1); - return csr8r(ctlr, Rbr); -} - -static void -i8250putc(Uart *uart, int c) -{ - int i; - Ctlr *ctlr; - - ctlr = uart->regs; - for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++) - delay(1); - outb(ctlr->io+Thr, c); - for(i = 0; !(csr8r(ctlr, Lsr)&Thre) && i < 128; i++) - delay(1); -} - -PhysUart i8250physuart = { - .name = "i8250", - .pnp = i8250pnp, - .enable = i8250enable, - .disable = i8250disable, - .kick = i8250kick, - .dobreak = i8250break, - .baud = i8250baud, - .bits = i8250bits, - .stop = i8250stop, - .parity = i8250parity, - .modemctl = i8250modemctl, - .rts = i8250rts, - .dtr = i8250dtr, - .status = i8250status, - .fifo = i8250fifo, - .getc = i8250getc, - .putc = i8250putc, -}; - -void -i8250console(void) -{ - Uart *uart; - int n; - char *cmd, *p; - - if((p = getconf("console")) == nil) - return; - n = strtoul(p, &cmd, 0); - if(p == cmd) - return; - switch(n){ - default: - return; - case 0: - uart = &i8250uart[0]; - break; - case 1: - uart = &i8250uart[1]; - break; - } - - (*uart->phys->enable)(uart, 0); - uartctl(uart, "b9600 l8 pn s1"); - if(*cmd != '\0') - uartctl(uart, cmd); - - consuart = uart; - uart->console = 1; -} - -void -i8250mouse(char* which, int (*putc)(Queue*, int), int setb1200) -{ - char *p; - int port; - - port = strtol(which, &p, 0); - if(p == which || port < 0 || port > 1) - error(Ebadarg); - uartmouse(&i8250uart[port], putc, setb1200); -} - -void -i8250setmouseputc(char* which, int (*putc)(Queue*, int)) -{ - char *p; - int port; - - port = strtol(which, &p, 0); - if(p == which || port < 0 || port > 1) - error(Ebadarg); - uartsetmouseputc(&i8250uart[port], putc); - -} diff --git a/os/pc/uartisa.c b/os/pc/uartisa.c deleted file mode 100644 index de4a8dcc..00000000 --- a/os/pc/uartisa.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/uart.h" - -extern PhysUart i8250physuart; -extern PhysUart isaphysuart; -extern void* i8250alloc(int, int, int); - -static Uart* -uartisa(int ctlrno, ISAConf* isa) -{ - int io; - void *ctlr; - Uart *uart; - char buf[64]; - - io = isa->port; - snprint(buf, sizeof(buf), "%s%d", isaphysuart.name, ctlrno); - if(ioalloc(io, 8, 0, buf) < 0){ - print("uartisa: I/O 0x%uX in use\n", io); - return nil; - } - - uart = malloc(sizeof(Uart)); - ctlr = i8250alloc(io, isa->irq, BUSUNKNOWN); - if(ctlr == nil){ - iofree(io); - free(uart); - return nil; - } - - uart->regs = ctlr; - snprint(buf, sizeof(buf), "COM%d", ctlrno+1); - kstrdup(&uart->name, buf); - uart->freq = isa->freq; - uart->phys = &i8250physuart; - - return uart; -} - -static Uart* -uartisapnp(void) -{ - int ctlrno; - ISAConf isa; - Uart *head, *tail, *uart; - - /* - * Look for up to 4 discrete UARTs on the ISA bus. - * All suitable devices are configured to simply point - * to the generic i8250 driver. - */ - head = tail = nil; - for(ctlrno = 2; ctlrno < 6; ctlrno++){ - memset(&isa, 0, sizeof(isa)); - if(!isaconfig("uart", ctlrno, &isa)) - continue; - if(strcmp(isa.type, "isa") != 0) - continue; - if(isa.port == 0 || isa.irq == 0) - continue; - if(isa.freq == 0) - isa.freq = 1843200; - uart = uartisa(ctlrno, &isa); - if(uart == nil) - continue; - if(head != nil) - tail->next = uart; - else - head = uart; - tail = uart; - } - - return head; -} - -PhysUart isaphysuart = { - .name = "UartISA", - .pnp = uartisapnp, - .enable = nil, - .disable = nil, - .kick = nil, - .dobreak = nil, - .baud = nil, - .bits = nil, - .stop = nil, - .parity = nil, - .modemctl = nil, - .rts = nil, - .dtr = nil, - .status = nil, - .fifo = nil, -}; diff --git a/os/pc/uartpci.c b/os/pc/uartpci.c deleted file mode 100644 index e84592b0..00000000 --- a/os/pc/uartpci.c +++ /dev/null @@ -1,137 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/uart.h" - -extern PhysUart i8250physuart; -extern PhysUart pciphysuart; -extern void* i8250alloc(int, int, int); - -static Uart* -uartpci(int ctlrno, Pcidev* p, int barno, int n, int freq, char* name) -{ - int i, io; - void *ctlr; - char buf[64]; - Uart *head, *uart; - - io = p->mem[barno].bar & ~0x01; - snprint(buf, sizeof(buf), "%s%d", pciphysuart.name, ctlrno); - if(ioalloc(io, p->mem[barno].size, 0, buf) < 0){ - print("uartpci: I/O 0x%uX in use\n", io); - return nil; - } - - head = uart = malloc(sizeof(Uart)*n); - - for(i = 0; i < n; i++){ - ctlr = i8250alloc(io, p->intl, p->tbdf); - io += 8; - if(ctlr == nil) - continue; - - uart->regs = ctlr; - snprint(buf, sizeof(buf), "%s.%8.8uX", name, p->tbdf); - kstrdup(&uart->name, buf); - uart->freq = freq; - uart->phys = &i8250physuart; - if(uart != head) - (uart-1)->next = uart; - uart++; - } - - return head; -} - -static Uart* -uartpcipnp(void) -{ - Pcidev *p; - char *name; - int ctlrno, n, subid; - Uart *head, *tail, *uart; - - /* - * Loop through all PCI devices looking for simple serial - * controllers (ccrb == 0x07) and configure the ones which - * are familiar. All suitable devices are configured to - * simply point to the generic i8250 driver. - */ - head = tail = nil; - ctlrno = 0; - for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){ - if(p->ccrb != 0x07 || p->ccru != 0) - continue; - - switch((p->did<<16)|p->vid){ - default: - continue; - case (0x9050<<16)|0x10B5: /* Perle PCI-Fast4 series */ - case (0x9030<<16)|0x10B5: /* Perle Ultraport series */ - /* - * These devices consists of a PLX bridge (the above - * PCI VID+DID) behind which are some 16C654 UARTs. - * Must check the subsystem VID and DID for correct - * match. - */ - subid = pcicfgr16(p, PciSVID); - subid |= pcicfgr16(p, PciSID)<<16; - switch(subid){ - default: - continue; - case (0x0011<<16)|0x12E0: /* Perle PCI-Fast16 */ - n = 16; - name = "PCI-Fast16"; - break; - case (0x0021<<16)|0x12E0: /* Perle PCI-Fast8 */ - n = 8; - name = "PCI-Fast8"; - break; - case (0x0031<<16)|0x12E0: /* Perle PCI-Fast4 */ - n = 4; - name = "PCI-Fast4"; - break; - case (0x0021<<16)|0x155F: /* Perle Ultraport8 */ - n = 8; - name = "Ultraport8"; /* 16C754 UARTs */ - break; - } - uart = uartpci(ctlrno, p, 2, n, 7372800, name); - if(uart == nil) - continue; - break; - } - - if(head != nil) - tail->next = uart; - else - head = uart; - for(tail = uart; tail->next != nil; tail = tail->next) - ; - ctlrno++; - } - - return head; -} - -PhysUart pciphysuart = { - .name = "UartPCI", - .pnp = uartpcipnp, - .enable = nil, - .disable = nil, - .kick = nil, - .dobreak = nil, - .baud = nil, - .bits = nil, - .stop = nil, - .parity = nil, - .modemctl = nil, - .rts = nil, - .dtr = nil, - .status = nil, - .fifo = nil, -}; diff --git a/os/pc/usb.h b/os/pc/usb.h deleted file mode 100644 index 32da4d51..00000000 --- a/os/pc/usb.h +++ /dev/null @@ -1,160 +0,0 @@ -typedef struct Ctlr Ctlr; -typedef struct Endpt Endpt; -typedef struct Udev Udev; -typedef struct Usbhost Usbhost; - -enum -{ - MaxUsb = 10, /* max number of USB Host Controller Interfaces (Usbhost*) */ - MaxUsbDev = 32, /* max number of attached USB devices, including root hub (Udev*) */ - - /* - * USB packet definitions... - */ - TokIN = 0x69, - TokOUT = 0xE1, - TokSETUP = 0x2D, - - /* request type */ - RH2D = 0<<7, - RD2H = 1<<7, - Rstandard = 0<<5, - Rclass = 1<<5, - Rvendor = 2<<5, - Rdevice = 0, - Rinterface = 1, - Rendpt = 2, - Rother = 3, -}; - -#define Class(csp) ((csp)&0xff) -#define Subclass(csp) (((csp)>>8)&0xff) -#define Proto(csp) (((csp)>>16)&0xff) -#define CSP(c, s, p) ((c) | ((s)<<8) | ((p)<<16)) - -/* - * device endpoint - */ -struct Endpt -{ - Ref; - Lock; - int x; /* index in Udev.ep */ - int id; /* hardware endpoint address */ - int maxpkt; /* maximum packet size (from endpoint descriptor) */ - int data01; /* 0=DATA0, 1=DATA1 */ - uchar eof; - ulong csp; - uchar mode; /* OREAD, OWRITE, ORDWR */ - uchar nbuf; /* number of buffers allowed */ - uchar iso; - uchar debug; - uchar active; /* listed for examination by interrupts */ - int setin; - /* ISO related: */ - int hz; - int remain; /* for packet size calculations */ - int samplesz; - int sched; /* schedule index; -1 if undefined or aperiodic */ - int pollms; /* polling interval in msec */ - int psize; /* (remaining) size of this packet */ - int off; /* offset into packet */ - /* Real-time iso stuff */ - ulong foffset; /* file offset (to detect seeks) */ - ulong poffset; /* offset of next packet to be queued */ - ulong toffset; /* offset associated with time */ - vlong time; /* timeassociated with offset */ - int buffered; /* bytes captured but unread, or written but unsent */ - /* end ISO stuff */ - - Udev* dev; /* owning device */ - - ulong nbytes; - ulong nblocks; - - void *private; - - // all the rest could (should?) move to the driver private structure; except perhaps err - QLock rlock; - Rendez rr; - Queue* rq; - QLock wlock; - Rendez wr; - Queue* wq; - - int ntd; - char* err; // needs to be global for unstall; fix? - - Endpt* activef; /* active endpoint list */ -}; - -/* device parameters */ -enum -{ - /* Udev.state */ - Disabled = 0, - Attached, - Enabled, - Assigned, - Configured, - - /* Udev.class */ - Noclass = 0, - Hubclass = 9, -}; - -/* - * active USB device - */ -struct Udev -{ - Ref; - Lock; - Usbhost *uh; - int x; /* index in usbdev[] */ - int busy; - int state; - int id; - uchar port; /* port number on connecting hub */ - ulong csp; - ushort vid; /* vendor id */ - ushort did; /* product id */ - int ls; - int npt; - Endpt* ep[16]; /* active end points */ - Udev* ports; /* active ports, if hub */ - Udev* next; /* next device on this hub */ -}; - -/* - * One of these per active Host Controller Interface (HCI) - */ -struct Usbhost -{ - ISAConf; /* hardware info */ - int tbdf; /* type+busno+devno+funcno */ - - QLock; /* protects namespace state */ - int idgen; /* version number to distinguish new connections */ - Udev* dev[MaxUsbDev]; /* device endpoints managed by this HCI */ - - void (*init)(Usbhost*); - void (*interrupt)(Ureg*, void*); - - void (*portinfo)(Usbhost*, char*, char*); - void (*portreset)(Usbhost*, int); - void (*portenable)(Usbhost*, int, int); - - void (*epalloc)(Usbhost*, Endpt*); - void (*epfree)(Usbhost*, Endpt*); - void (*epopen)(Usbhost*, Endpt*); - void (*epclose)(Usbhost*, Endpt*); - void (*epmode)(Usbhost*, Endpt*); - - long (*read)(Usbhost*, Endpt*, void*, long, vlong); - long (*write)(Usbhost*, Endpt*, void*, long, vlong, int); - - void *ctlr; -}; - -extern void addusbtype(char*, int(*)(Usbhost*)); diff --git a/os/pc/usbuhci.c b/os/pc/usbuhci.c deleted file mode 100644 index 4d65726c..00000000 --- a/os/pc/usbuhci.c +++ /dev/null @@ -1,1538 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#include "usb.h" - -#define XPRINT if(debug)print - -static int Chatty = 0; -static int debug = 0; - -static char Estalled[] = "usb endpoint stalled"; - -/* - * UHCI interface registers and bits - */ -enum -{ - /* i/o space */ - Cmd = 0, - Status = 2, - Usbintr = 4, - Frnum = 6, - Flbaseadd = 8, - SOFMod = 0xC, - Portsc0 = 0x10, - Portsc1 = 0x12, - - /* port status */ - Suspend = 1<<12, - PortReset = 1<<9, - SlowDevice = 1<<8, - ResumeDetect = 1<<6, - PortChange = 1<<3, /* write 1 to clear */ - PortEnable = 1<<2, - StatusChange = 1<<1, /* write 1 to clear */ - DevicePresent = 1<<0, - - NFRAME = 1024, - FRAMESIZE= NFRAME*sizeof(ulong), /* fixed by hardware; aligned to same */ - - Vf = 1<<2, /* TD only */ - IsQH = 1<<1, - Terminate = 1<<0, - - /* TD.status */ - SPD = 1<<29, - ErrLimit0 = 0<<27, - ErrLimit1 = 1<<27, - ErrLimit2 = 2<<27, - ErrLimit3 = 3<<27, - LowSpeed = 1<<26, - IsoSelect = 1<<25, - IOC = 1<<24, - Active = 1<<23, - Stalled = 1<<22, - DataBufferErr = 1<<21, - Babbling = 1<<20, - NAKed = 1<<19, - CRCorTimeout = 1<<18, - BitstuffErr = 1<<17, - AnyError = (Stalled | DataBufferErr | Babbling | NAKed | CRCorTimeout | BitstuffErr), - - /* TD.dev */ - IsDATA1 = 1<<19, - - /* TD.flags (software) */ - CancelTD= 1<<0, - IsoClean= 1<<2, -}; - -static struct -{ - int bit; - char *name; -} -portstatus[] = -{ - { Suspend, "suspend", }, - { PortReset, "reset", }, - { SlowDevice, "lowspeed", }, - { ResumeDetect, "resume", }, - { PortChange, "portchange", }, - { PortEnable, "enable", }, - { StatusChange, "statuschange", }, - { DevicePresent, "present", }, -}; - -typedef struct Ctlr Ctlr; -typedef struct Endptx Endptx; -typedef struct QH QH; -typedef struct TD TD; - -/* - * software structures - */ -struct Ctlr -{ - Lock; /* protects state shared with interrupt (eg, free list) */ - Ctlr* next; - Pcidev* pcidev; - int active; - - int io; - ulong* frames; /* frame list */ - ulong* frameld; /* real time load on each of the frame list entries */ - QLock resetl; /* lock controller during USB reset */ - - TD* tdpool; - TD* freetd; - QH* qhpool; - QH* freeqh; - - QH* ctlq; /* queue for control i/o */ - QH* bwsop; /* empty bandwidth sop (to PIIX4 errata specifications) */ - QH* bulkq; /* queue for bulk i/o (points back to bandwidth sop) */ - QH* recvq; /* receive queues for bulk i/o */ - - Udev* ports[2]; - - struct { - Lock; - Endpt* f; - } activends; - - long usbints; /* debugging */ - long framenumber; - long frameptr; - long usbbogus; -}; - -#define IN(x) ins(ctlr->io+(x)) -#define OUT(x, v) outs(ctlr->io+(x), (v)) - -static Ctlr* ctlrhead; -static Ctlr* ctlrtail; - -struct Endptx -{ - QH* epq; /* queue of TDs for this endpoint */ - - /* ISO related: */ - void* tdalloc; - void* bpalloc; - uchar* bp0; /* first block in array */ - TD * td0; /* first td in array */ - TD * etd; /* pointer into circular list of TDs for isochronous ept */ - TD * xtd; /* next td to be cleaned */ -}; - -/* - * UHCI hardware structures, aligned on 16-byte boundary - */ -struct TD -{ - ulong link; - ulong status; /* controller r/w */ - ulong dev; - ulong buffer; - - /* software */ - ulong flags; - union{ - Block* bp; /* non-iso */ - ulong offset; /* iso */ - }; - Endpt* ep; - TD* next; -}; -#define TFOL(p) ((TD*)KADDR((ulong)(p) & ~(0xF|PCIWINDOW))) - -struct QH -{ - ulong head; - ulong entries; /* address of next TD or QH to process (updated by controller) */ - - /* software */ - QH* hlink; - TD* first; - QH* next; /* free list */ - TD* last; - ulong _d1; /* fillers */ - ulong _d2; -}; -#define QFOL(p) ((QH*)KADDR((ulong)(p) & ~(0xF|PCIWINDOW))) - -static TD * -alloctd(Ctlr *ctlr) -{ - TD *t; - - ilock(ctlr); - t = ctlr->freetd; - if(t == nil) - panic("alloctd"); /* TO DO */ - ctlr->freetd = t->next; - t->next = nil; - iunlock(ctlr); - t->ep = nil; - t->bp = nil; - t->status = 0; - t->link = Terminate; - t->buffer = 0; - t->flags = 0; - return t; -} - -static void -freetd(Ctlr *ctlr, TD *t) -{ - t->ep = nil; - if(t->bp) - freeb(t->bp); - t->bp = nil; - ilock(ctlr); - t->buffer = 0xdeadbeef; - t->next = ctlr->freetd; - ctlr->freetd = t; - iunlock(ctlr); -} - -static void -dumpdata(Block *b, int n) -{ - int i; - - XPRINT("\tb %8.8lux[%d]: ", (ulong)b->rp, n); - if(n > 16) - n = 16; - for(i=0; irp[i]); - XPRINT("\n"); -} - -static void -dumptd(TD *t, int follow) -{ - int i, n; - char buf[20], *s; - TD *t0; - - t0 = t; - while(t){ - i = t->dev & 0xFF; - if(i == TokOUT || i == TokSETUP) - n = ((t->dev>>21) + 1) & 0x7FF; - else if((t->status & Active) == 0) - n = (t->status + 1) & 0x7FF; - else - n = 0; - s = buf; - if(t->status & Active) - *s++ = 'A'; - if(t->status & Stalled) - *s++ = 'S'; - if(t->status & DataBufferErr) - *s++ = 'D'; - if(t->status & Babbling) - *s++ = 'B'; - if(t->status & NAKed) - *s++ = 'N'; - if(t->status & CRCorTimeout) - *s++ = 'T'; - if(t->status & BitstuffErr) - *s++ = 'b'; - if(t->status & LowSpeed) - *s++ = 'L'; - *s = 0; - XPRINT("td %8.8lux: ", t); - XPRINT("l=%8.8lux s=%8.8lux d=%8.8lux b=%8.8lux %8.8lux f=%8.8lux\n", - t->link, t->status, t->dev, t->buffer, t->bp?(ulong)t->bp->rp:0, t->flags); - XPRINT("\ts=%s,ep=%ld,d=%ld,D=%ld\n", - buf, (t->dev>>15)&0xF, (t->dev>>8)&0xFF, (t->dev>>19)&1); - if(debug && t->bp && (t->flags & CancelTD) == 0) - dumpdata(t->bp, n); - if(!follow || t->link & Terminate || t->link & IsQH) - break; - t = TFOL(t->link); - if(t == t0) - break; /* looped */ - } -} - -static TD * -alloctde(Ctlr *ctlr, Endpt *e, int pid, int n) -{ - TD *t; - int tog, id; - - t = alloctd(ctlr); - id = (e->x<<7)|(e->dev->x&0x7F); - tog = 0; - if(e->data01 && pid != TokSETUP) - tog = IsDATA1; - t->ep = e; - t->status = ErrLimit3 | Active | IOC; /* or put IOC only on last? */ - if(e->dev->ls) - t->status |= LowSpeed; - t->dev = ((n-1)<<21) | ((id&0x7FF)<<8) | pid | tog; - return t; -} - -static QH * -allocqh(Ctlr *ctlr) -{ - QH *qh; - - ilock(ctlr); - qh = ctlr->freeqh; - if(qh == nil) - panic("allocqh"); /* TO DO */ - ctlr->freeqh = qh->next; - qh->next = nil; - iunlock(ctlr); - qh->head = Terminate; - qh->entries = Terminate; - qh->hlink = nil; - qh->first = nil; - qh->last = nil; - return qh; -} - -static void -freeqh(Ctlr *ctlr, QH *qh) -{ - ilock(ctlr); - qh->next = ctlr->freeqh; - ctlr->freeqh = qh; - iunlock(ctlr); -} - -static void -dumpqh(QH *q) -{ - int i; - QH *q0; - - q0 = q; - for(i = 0; q != nil && i < 10; i++){ - XPRINT("qh %8.8lux: %8.8lux %8.8lux\n", q, q->head, q->entries); - if((q->entries & Terminate) == 0) - dumptd(TFOL(q->entries), 1); - if(q->head & Terminate) - break; - if((q->head & IsQH) == 0){ - XPRINT("head:"); - dumptd(TFOL(q->head), 1); - break; - } - q = QFOL(q->head); - if(q == q0) - break; /* looped */ - } -} - -static void -queuetd(Ctlr *ctlr, QH *q, TD *t, int vf, char *why) -{ - TD *lt; - - for(lt = t; lt->next != nil; lt = lt->next) - lt->link = PCIWADDR(lt->next) | vf; - lt->link = Terminate; - ilock(ctlr); - XPRINT("queuetd %s: t=%p lt=%p q=%p first=%p last=%p entries=%.8lux\n", - why, t, lt, q, q->first, q->last, q->entries); - if(q->first != nil){ - q->last->link = PCIWADDR(t) | vf; - q->last->next = t; - }else{ - q->first = t; - q->entries = PCIWADDR(t); - } - q->last = lt; - XPRINT(" t=%p q=%p first=%p last=%p entries=%.8lux\n", - t, q, q->first, q->last, q->entries); - dumpqh(q); - iunlock(ctlr); -} - -static void -cleantd(Ctlr *ctlr, TD *t, int discard) -{ - Block *b; - int n, err; - - XPRINT("cleanTD: %8.8lux %8.8lux %8.8lux %8.8lux\n", t->link, t->status, t->dev, t->buffer); - if(t->ep != nil && t->ep->debug) - dumptd(t, 0); - if(t->status & Active) - panic("cleantd Active"); - err = t->status & (AnyError&~NAKed); - /* TO DO: on t->status&AnyError, q->entries will not have advanced */ - if (err) { - XPRINT("cleanTD: Error %8.8lux %8.8lux %8.8lux %8.8lux\n", t->link, t->status, t->dev, t->buffer); -// print("cleanTD: Error %8.8lux %8.8lux %8.8lux %8.8lux\n", t->link, t->status, t->dev, t->buffer); - } - switch(t->dev&0xFF){ - case TokIN: - if(discard || (t->flags & CancelTD) || t->ep == nil || t->ep->x!=0&&err){ - if(t->ep != nil){ - if(err != 0) - t->ep->err = err==Stalled? Estalled: Eio; - wakeup(&t->ep->rr); /* in case anyone cares */ - } - break; - } - b = t->bp; - n = (t->status + 1) & 0x7FF; - if(n > b->lim - b->wp) - n = 0; - b->wp += n; - if(Chatty) - dumpdata(b, n); - t->bp = nil; - t->ep->nbytes += n; - t->ep->nblocks++; - qpass(t->ep->rq, b); /* TO DO: flow control */ - wakeup(&t->ep->rr); /* TO DO */ - break; - case TokSETUP: - XPRINT("cleanTD: TokSETUP %lux\n", &t->ep); - /* don't really need to wakeup: subsequent IN or OUT gives status */ - if(t->ep != nil) { - wakeup(&t->ep->wr); /* TO DO */ - XPRINT("cleanTD: wakeup %lux\n", &t->ep->wr); - } - break; - case TokOUT: - /* TO DO: mark it done somewhere */ - XPRINT("cleanTD: TokOut %lux\n", &t->ep); - if(t->ep != nil){ - if(t->bp){ - n = BLEN(t->bp); - t->ep->nbytes += n; - t->ep->nblocks++; - } - if(t->ep->x!=0 && err != 0) - t->ep->err = err==Stalled? Estalled: Eio; - if(--t->ep->ntd < 0) - panic("cleantd ntd"); - wakeup(&t->ep->wr); /* TO DO */ - XPRINT("cleanTD: wakeup %lux\n", &t->ep->wr); - } - break; - } - freetd(ctlr, t); -} - -static void -cleanq(Ctlr *ctlr, QH *q, int discard, int vf) -{ - TD *t, *tp; - - ilock(ctlr); - tp = nil; - for(t = q->first; t != nil;){ - XPRINT("cleanq: %8.8lux %8.8lux %8.8lux %8.8lux %8.8lux %8.8lux\n", t->link, t->status, t->dev, t->buffer, t->flags, t->next); - if(t->status & Active){ - if(t->status & NAKed){ - t->status = (t->status & ~NAKed) | IOC; /* ensure interrupt next frame */ - tp = t; - t = t->next; - continue; - } - if(t->flags & CancelTD){ - XPRINT("cancelTD: %8.8lux\n", (ulong)t); - t->status = (t->status & ~Active) | IOC; /* ensure interrupt next frame */ - tp = t; - t = t->next; - continue; - } - tp = t; - t = t->next; - continue; - } - t->status &= ~IOC; - if (tp == nil) { - q->first = t->next; - if(q->first != nil) - q->entries = PCIWADDR(q->first); - else - q->entries = Terminate; - } else { - tp->next = t->next; - if (t->next != nil) - tp->link = PCIWADDR(t->next) | vf; - else - tp->link = Terminate; - } - if (q->last == t) - q->last = tp; - iunlock(ctlr); - cleantd(ctlr, t, discard); - ilock(ctlr); - if (tp) - t = tp->next; - else - t = q->first; - XPRINT("t = %8.8lux\n", t); - dumpqh(q); - } - if(q->first && q->entries != PCIWADDR(q->first)){ - ctlr->usbbogus++; - q->entries = PCIWADDR(q->first); - } - iunlock(ctlr); -} - -static void -canceltds(Ctlr *ctlr, QH *q, Endpt *e) -{ - TD *t; - - if(q != nil){ - ilock(ctlr); - for(t = q->first; t != nil; t = t->next) - if(t->ep == e) - t->flags |= CancelTD; - iunlock(ctlr); - XPRINT("cancel:\n"); - dumpqh(q); - } -} - -static void -eptcancel(Ctlr *ctlr, Endpt *e) -{ - Endptx *x; - - if(e == nil) - return; - x = e->private; - canceltds(ctlr, x->epq, e); - canceltds(ctlr, ctlr->ctlq, e); - canceltds(ctlr, ctlr->bulkq, e); -} - -static void -eptactivate(Ctlr *ctlr, Endpt *e) -{ - ilock(&ctlr->activends); - if(e->active == 0){ - XPRINT("activate 0x%p\n", e); - e->active = 1; - e->activef = ctlr->activends.f; - ctlr->activends.f = e; - } - iunlock(&ctlr->activends); -} - -static void -eptdeactivate(Ctlr *ctlr, Endpt *e) -{ - Endpt **l; - - /* could be O(1) but not worth it yet */ - ilock(&ctlr->activends); - if(e->active){ - e->active = 0; - XPRINT("deactivate 0x%p\n", e); - for(l = &ctlr->activends.f; *l != e; l = &(*l)->activef) - if(*l == nil){ - iunlock(&ctlr->activends); - panic("usb eptdeactivate"); - } - *l = e->activef; - } - iunlock(&ctlr->activends); -} - -static void -queueqh(Ctlr *ctlr, QH *qh) -{ - QH *q; - - // See if it's already queued - for (q = ctlr->recvq->next; q; q = q->hlink) - if (q == qh) - return; - if ((qh->hlink = ctlr->recvq->next) == nil) - qh->head = Terminate; - else - qh->head = PCIWADDR(ctlr->recvq->next) | IsQH; - ctlr->recvq->next = qh; - ctlr->recvq->entries = PCIWADDR(qh) | IsQH; -} - -static QH* -qxmit(Ctlr *ctlr, Endpt *e, Block *b, int pid) -{ - TD *t; - int n, vf; - QH *qh; - Endptx *x; - - x = e->private; - if(b != nil){ - n = BLEN(b); - t = alloctde(ctlr, e, pid, n); - t->bp = b; - t->buffer = PCIWADDR(b->rp); - }else - t = alloctde(ctlr, e, pid, 0); - ilock(ctlr); - e->ntd++; - iunlock(ctlr); - if(e->debug) pprint("QTD: %8.8lux n=%ld\n", t, b?BLEN(b): 0); - vf = 0; - if(e->x == 0){ - qh = ctlr->ctlq; - vf = 0; - }else if((qh = x->epq) == nil || e->mode != OWRITE){ - qh = ctlr->bulkq; - vf = Vf; - } - queuetd(ctlr, qh, t, vf, "qxmit"); - return qh; -} - -static QH* -qrcv(Ctlr *ctlr, Endpt *e) -{ - TD *t; - Block *b; - QH *qh; - int vf; - Endptx *x; - - x = e->private; - t = alloctde(ctlr, e, TokIN, e->maxpkt); - b = allocb(e->maxpkt); - t->bp = b; - t->buffer = PCIWADDR(b->wp); - vf = 0; - if(e->x == 0){ - qh = ctlr->ctlq; - }else if((qh = x->epq) == nil || e->mode != OREAD){ - qh = ctlr->bulkq; - vf = Vf; - } - queuetd(ctlr, qh, t, vf, "qrcv"); - return qh; -} - -static int -usbsched(Ctlr *ctlr, int pollms, ulong load) -{ - int i, d, q; - ulong best, worst; - - best = 1000000; - q = -1; - for (d = 0; d < pollms; d++){ - worst = 0; - for (i = d; i < NFRAME; i++){ - if (ctlr->frameld[i] + load > worst) - worst = ctlr->frameld[i] + load; - } - if (worst < best){ - best = worst; - q = d; - } - } - return q; -} - -static int -schedendpt(Ctlr *ctlr, Endpt *e) -{ - TD *td; - Endptx *x; - uchar *bp; - int i, id, ix, size, frnum; - - if(!e->iso || e->sched >= 0) - return 0; - - if (e->active){ - return -1; - } - e->off = 0; - e->sched = usbsched(ctlr, e->pollms, e->maxpkt); - if(e->sched < 0) - return -1; - - x = e->private; - if (x->tdalloc || x->bpalloc) - panic("usb: tdalloc/bpalloc"); - x->tdalloc = mallocz(0x10 + NFRAME*sizeof(TD), 1); - x->bpalloc = mallocz(0x10 + e->maxpkt*NFRAME/e->pollms, 1); - x->td0 = (TD*)(((ulong)x->tdalloc + 0xf) & ~0xf); - x->bp0 = (uchar *)(((ulong)x->bpalloc + 0xf) & ~0xf); - frnum = (IN(Frnum) + 1) & 0x3ff; - frnum = (frnum & ~(e->pollms - 1)) + e->sched; - x->xtd = &x->td0[(frnum+8)&0x3ff]; /* Next td to finish */ - x->etd = nil; - e->remain = 0; - e->nbytes = 0; - td = x->td0; - for(i = e->sched; i < NFRAME; i += e->pollms){ - bp = x->bp0 + e->maxpkt*i/e->pollms; - td->buffer = PCIWADDR(bp); - td->ep = e; - td->next = &td[1]; - ctlr->frameld[i] += e->maxpkt; - td++; - } - td[-1].next = x->td0; - for(i = e->sched; i < NFRAME; i += e->pollms){ - ix = (frnum+i) & 0x3ff; - td = &x->td0[ix]; - - id = (e->x<<7)|(e->dev->x&0x7F); - if (e->mode == OREAD) - /* enable receive on this entry */ - td->dev = ((e->maxpkt-1)<<21) | ((id&0x7FF)<<8) | TokIN; - else{ - size = (e->hz + e->remain)*e->pollms/1000; - e->remain = (e->hz + e->remain)*e->pollms%1000; - size *= e->samplesz; - td->dev = ((size-1)<<21) | ((id&0x7FF)<<8) | TokOUT; - } - td->status = ErrLimit1 | Active | IsoSelect | IOC; - td->link = ctlr->frames[ix]; - td->flags |= IsoClean; - ctlr->frames[ix] = PCIWADDR(td); - } - return 0; -} - -static void -unschedendpt(Ctlr *ctlr, Endpt *e) -{ - int q; - TD *td; - Endptx *x; - ulong *addr; - - if(!e->iso || e->sched < 0) - return; - - x = e->private; - if (x->tdalloc == nil) - panic("tdalloc"); - for (q = e->sched; q < NFRAME; q += e->pollms){ - td = x->td0++; - addr = &ctlr->frames[q]; - while(*addr != PADDR(td)) { - if(*addr & IsQH) - panic("usb: TD expected"); - addr = &TFOL(*addr)->link; - } - *addr = td->link; - ctlr->frameld[q] -= e->maxpkt; - } - free(x->tdalloc); - free(x->bpalloc); - x->tdalloc = nil; - x->bpalloc = nil; - x->etd = nil; - x->td0 = nil; - e->sched = -1; -} - -static void -epalloc(Usbhost *uh, Endpt *e) -{ - Endptx *x; - - x = malloc(sizeof(Endptx)); - e->private = x; - x->epq = allocqh(uh->ctlr); - if(x->epq == nil) - panic("devendptx"); -} - -static void -epfree(Usbhost *uh, Endpt *e) -{ - Ctlr *ctlr; - Endptx *x; - - ctlr = uh->ctlr; - x = e->private; - if(x->epq != nil) - freeqh(ctlr, x->epq); -} - -static void -epopen(Usbhost *uh, Endpt *e) -{ - Ctlr *ctlr; - - ctlr = uh->ctlr; - if(e->iso && e->active) - error("already open"); - if(schedendpt(ctlr, e) < 0){ - if(e->active) - error("cannot schedule USB endpoint, active"); - else - error("cannot schedule USB endpoint"); - } - eptactivate(ctlr, e); -} - -static void -epclose(Usbhost *uh, Endpt *e) -{ - Ctlr *ctlr; - - ctlr = uh->ctlr; - eptdeactivate(ctlr, e); - unschedendpt(ctlr, e); -} - -static void -epmode(Usbhost *uh, Endpt *e) -{ - Ctlr *ctlr; - Endptx *x; - - ctlr = uh->ctlr; - x = e->private; - if(e->iso) { - if(x->epq != nil) { - freeqh(ctlr, x->epq); - x->epq = nil; - } - } - else { - /* Each bulk device gets a queue head hanging off the - * bulk queue head - */ - if(x->epq == nil) { - x->epq = allocqh(ctlr); - if(x->epq == nil) - panic("epbulk: allocqh"); - } - queueqh(ctlr, x->epq); - } -} - -static int ioport[] = {-1, Portsc0, Portsc1}; - -static void -portreset(Usbhost *uh, int port) -{ - int i, p; - Ctlr *ctlr; - - ctlr = uh->ctlr; - if(port != 1 && port != 2) - error(Ebadarg); - - /* should check that device not being configured on other port? */ - p = ioport[port]; - qlock(&ctlr->resetl); - if(waserror()){ - qunlock(&ctlr->resetl); - nexterror(); - } - XPRINT("r: %x\n", IN(p)); - ilock(ctlr); - OUT(p, PortReset); - delay(12); /* BUG */ - XPRINT("r2: %x\n", IN(p)); - OUT(p, IN(p) & ~PortReset); - XPRINT("r3: %x\n", IN(p)); - OUT(p, IN(p) | PortEnable); - microdelay(64); - for(i=0; i<1000 && (IN(p) & PortEnable) == 0; i++) - ; - XPRINT("r': %x %d\n", IN(p), i); - OUT(p, (IN(p) & ~PortReset)|PortEnable); - iunlock(ctlr); - poperror(); - qunlock(&ctlr->resetl); -} - -static void -portenable(Usbhost *uh, int port, int on) -{ - int w, p; - Ctlr *ctlr; - - ctlr = uh->ctlr; - if(port != 1 && port != 2) - error(Ebadarg); - - /* should check that device not being configured on other port? */ - p = ioport[port]; - qlock(&ctlr->resetl); - if(waserror()){ - qunlock(&ctlr->resetl); - nexterror(); - } - ilock(ctlr); - w = IN(p); - if(on) - w |= PortEnable; - else - w &= ~PortEnable; - OUT(p, w); - microdelay(64); - iunlock(ctlr); - XPRINT("e: %x\n", IN(p)); - poperror(); - qunlock(&ctlr->resetl); -} - -static void -portinfo(Usbhost *uh, char *s, char *se) -{ - int x, i, j; - Ctlr *ctlr; - - ctlr = uh->ctlr; - for(i = 1; i <= 2; i++) { - ilock(ctlr); - x = IN(ioport[i]); - if((x & (PortChange|StatusChange)) != 0) - OUT(ioport[i], x); - iunlock(ctlr); - s = seprint(s, se, "%d %ux", i, x); - for(j = 0; j < nelem(portstatus); j++) { - if((x & portstatus[j].bit) != 0) - s = seprint(s, se, " %s", portstatus[j].name); - } - s = seprint(s, se, "\n"); - } -} - -static void -cleaniso(Endpt *e, int frnum) -{ - TD *td; - int id, n, i; - Endptx *x; - uchar *bp; - - x = e->private; - td = x->xtd; - if (td->status & Active) - return; - id = (e->x<<7)|(e->dev->x&0x7F); - do { - if (td->status & AnyError) - XPRINT("usbisoerror 0x%lux\n", td->status); - n = (td->status + 1) & 0x3ff; - e->nbytes += n; - if ((td->flags & IsoClean) == 0) - e->nblocks++; - if (e->mode == OREAD){ - e->buffered += n; - e->poffset += (td->status + 1) & 0x3ff; - td->offset = e->poffset; - td->dev = ((e->maxpkt -1)<<21) | ((id&0x7FF)<<8) | TokIN; - e->toffset = td->offset; - }else{ - if ((td->flags & IsoClean) == 0){ - e->buffered -= n; - if (e->buffered < 0){ -// print("e->buffered %d?\n", e->buffered); - e->buffered = 0; - } - } - e->toffset = td->offset; - n = (e->hz + e->remain)*e->pollms/1000; - e->remain = (e->hz + e->remain)*e->pollms%1000; - n *= e->samplesz; - td->dev = ((n -1)<<21) | ((id&0x7FF)<<8) | TokOUT; - td->offset = e->poffset; - e->poffset += n; - } - td = td->next; - if (x->xtd == td){ - XPRINT("@"); - break; - } - } while ((td->status & Active) == 0); - e->time = todget(nil); - x->xtd = td; - for (n = 2; n < 4; n++){ - i = ((frnum + n)&0x3ff); - td = x->td0 + i; - bp = x->bp0 + e->maxpkt*i/e->pollms; - if (td->status & Active) - continue; - - if (e->mode == OWRITE){ - if (td == x->etd) { - XPRINT("*"); - memset(bp+e->off, 0, e->maxpkt-e->off); - if (e->off == 0) - td->flags |= IsoClean; - else - e->buffered += (((td->dev>>21) +1) & 0x3ff) - e->off; - x->etd = nil; - }else if ((td->flags & IsoClean) == 0){ - XPRINT("-"); - memset(bp, 0, e->maxpkt); - td->flags |= IsoClean; - } - } else { - /* Unread bytes are now lost */ - e->buffered -= (td->status + 1) & 0x3ff; - } - td->status = ErrLimit1 | Active | IsoSelect | IOC; - } - wakeup(&e->wr); -} - -static void -interrupt(Ureg*, void *a) -{ - QH *q; - Ctlr *ctlr; - Endpt *e; - Endptx *x; - int s, frnum; - Usbhost *uh; - - uh = a; - ctlr = uh->ctlr; - s = IN(Status); - ctlr->frameptr = inl(ctlr->io+Flbaseadd); - ctlr->framenumber = IN(Frnum) & 0x3ff; - OUT(Status, s); - if ((s & 0x1f) == 0) - return; - ctlr->usbints++; - frnum = IN(Frnum) & 0x3ff; - if (s & 0x1a) { - XPRINT("cmd #%x sofmod #%x\n", IN(Cmd), inb(ctlr->io+SOFMod)); - XPRINT("sc0 #%x sc1 #%x\n", IN(Portsc0), IN(Portsc1)); - } - - ilock(&ctlr->activends); - for(e = ctlr->activends.f; e != nil; e = e->activef) { - x = e->private; - if(!e->iso && x->epq != nil) { - XPRINT("cleanq(ctlr, x->epq, 0, 0)\n"); - cleanq(ctlr, x->epq, 0, 0); - } - if(e->iso) { - XPRINT("cleaniso(e)\n"); - cleaniso(e, frnum); - } - } - iunlock(&ctlr->activends); - XPRINT("cleanq(ctlr, ctlr->ctlq, 0, 0)\n"); - cleanq(ctlr, ctlr->ctlq, 0, 0); - XPRINT("cleanq(ctlr, ctlr->bulkq, 0, Vf)\n"); - cleanq(ctlr, ctlr->bulkq, 0, Vf); - XPRINT("clean recvq\n"); - for (q = ctlr->recvq->next; q; q = q->hlink) { - XPRINT("cleanq(ctlr, q, 0, Vf)\n"); - cleanq(ctlr, q, 0, Vf); - } -} - -static int -eptinput(void *arg) -{ - Endpt *e; - - e = arg; - return e->eof || e->err || qcanread(e->rq); -} - -static int -isoreadyx(Endptx *x) -{ - return x->etd == nil || (x->etd != x->xtd && (x->etd->status & Active) == 0); -} - -static int -isoready(void *arg) -{ - int ret; - Ctlr *ctlr; - Endpt *e; - Endptx *x; - - e = arg; - ctlr = e->dev->uh->ctlr; - x = e->private; - ilock(&ctlr->activends); - ret = isoreadyx(x); - iunlock(&ctlr->activends); - return ret; -} - -static long -isoio(Ctlr *ctlr, Endpt *e, void *a, long n, ulong offset, int w) -{ - TD *td; - Endptx *x; - int i, frnum; - uchar *p, *q, *bp; - volatile int isolock; - - x = e->private; - qlock(&e->rlock); - isolock = 0; - if(waserror()){ - if (isolock){ - isolock = 0; - iunlock(&ctlr->activends); - } - qunlock(&e->rlock); - eptcancel(ctlr, e); - nexterror(); - } - p = a; - if (offset != 0 && offset != e->foffset){ - iprint("offset %lud, foffset %lud\n", offset, e->foffset); - /* Seek to a specific position */ - frnum = (IN(Frnum) + 8) & 0x3ff; - td = x->td0 +frnum; - if (offset < td->offset) - error("ancient history"); - while (offset > e->toffset){ - tsleep(&e->wr, return0, 0, 500); - } - while (offset >= td->offset + ((w?(td->dev >> 21):td->status) + 1) & 0x7ff){ - td = td->next; - if (td == x->xtd) - iprint("trouble\n"); - } - ilock(&ctlr->activends); - isolock = 1; - e->off = td->offset - offset; - if (e->off >= e->maxpkt){ - iprint("I can't program: %d\n", e->off); - e->off = 0; - } - x->etd = td; - e->foffset = offset; - } - do { - if (isolock == 0){ - ilock(&ctlr->activends); - isolock = 1; - } - td = x->etd; - if (td == nil || e->off == 0){ - if (td == nil){ - XPRINT("0"); - if (w){ - frnum = (IN(Frnum) + 1) & 0x3ff; - td = x->td0 + frnum; - while(td->status & Active) - td = td->next; - }else{ - frnum = (IN(Frnum) - 4) & 0x3ff; - td = x->td0 + frnum; - while(td->next != x->xtd) - td = td->next; - } - x->etd = td; - e->off = 0; - }else{ - /* New td, make sure it's ready */ - while (isoreadyx(x) == 0){ - isolock = 0; - iunlock(&ctlr->activends); - sleep(&e->wr, isoready, e); - ilock(&ctlr->activends); - isolock = 1; - } - if (x->etd == nil){ - XPRINT("!"); - continue; - } - } - if (w) - e->psize = ((td->dev >> 21) + 1) & 0x7ff; - else - e->psize = (x->etd->status + 1) & 0x7ff; - if(e->psize > e->maxpkt) - panic("packet size > maximum"); - } - if((i = n) >= e->psize) - i = e->psize; - if (w) - e->buffered += i; - else{ - e->buffered -= i; - if (e->buffered < 0) - e->buffered = 0; - } - isolock = 0; - iunlock(&ctlr->activends); - td->flags &= ~IsoClean; - bp = x->bp0 + (td - x->td0) * e->maxpkt / e->pollms; - q = bp + e->off; - if (w){ - memmove(q, p, i); - }else{ - memmove(p, q, i); - } - p += i; - n -= i; - e->off += i; - e->psize -= i; - if (e->psize){ - if (n != 0) - panic("usb iso: can't happen"); - break; - } - if(w) - td->offset = offset + (p-(uchar*)a) - (((td->dev >> 21) + 1) & 0x7ff); - td->status = ErrLimit3 | Active | IsoSelect | IOC; - x->etd = td->next; - e->off = 0; - } while(n > 0); - n = p-(uchar*)a; - e->foffset += n; - poperror(); - if (isolock) - iunlock(&ctlr->activends); - qunlock(&e->rlock); - return n; -} - -static long -read(Usbhost *uh, Endpt *e, void *a, long n, vlong offset) -{ - long l, i; - Block *b; - Ctlr *ctlr; - uchar *p; - - ctlr = uh->ctlr; - if(e->iso) - return isoio(ctlr, e, a, n, (ulong)offset, 0); - - XPRINT("qlock(%p)\n", &e->rlock); - qlock(&e->rlock); - XPRINT("got qlock(%p)\n", &e->rlock); - if(waserror()){ - qunlock(&e->rlock); - eptcancel(ctlr, e); - nexterror(); - } - p = a; - do { - if(e->eof) { - XPRINT("e->eof\n"); - break; - } - if(e->err) - error(e->err); - qrcv(ctlr, e); - if(!e->iso) - e->data01 ^= 1; - sleep(&e->rr, eptinput, e); - if(e->err) - error(e->err); - b = qget(e->rq); /* TO DO */ - if(b == nil) { - XPRINT("b == nil\n"); - break; - } - if(waserror()){ - freeb(b); - nexterror(); - } - l = BLEN(b); - if((i = l) > n) - i = n; - if(i > 0){ - memmove(p, b->rp, i); - p += i; - } - poperror(); - freeb(b); - n -= i; - if (l != e->maxpkt) - break; - } while (n > 0); - poperror(); - qunlock(&e->rlock); - return p-(uchar*)a; -} - -static int -qisempty(void *arg) -{ - return ((QH*)arg)->entries & Terminate; -} - -static long -write(Usbhost *uh, Endpt *e, void *a, long n, vlong offset, int tok) -{ - int i, j; - QH *qh; - Block *b; - Ctlr *ctlr; - uchar *p; - - ctlr = uh->ctlr; - if(e->iso) - return isoio(ctlr, e, a, n, (ulong)offset, 1); - - p = a; - qlock(&e->wlock); - if(waserror()){ - qunlock(&e->wlock); - eptcancel(ctlr, e); - nexterror(); - } - do { - if(e->err) - error(e->err); - if((i = n) >= e->maxpkt) - i = e->maxpkt; - b = allocb(i); - if(waserror()){ - freeb(b); - nexterror(); - } - XPRINT("out [%d]", i); - for (j = 0; j < i; j++) XPRINT(" %.2x", p[j]); - XPRINT("\n"); - memmove(b->wp, p, i); - b->wp += i; - p += i; - n -= i; - poperror(); - qh = qxmit(ctlr, e, b, tok); - tok = TokOUT; - e->data01 ^= 1; - if(e->ntd >= e->nbuf) { -XPRINT("qh %s: q=%p first=%p last=%p entries=%.8lux\n", - "writeusb sleep", qh, qh->first, qh->last, qh->entries); - XPRINT("write: sleep %lux\n", &e->wr); - sleep(&e->wr, qisempty, qh); - XPRINT("write: awake\n"); - } - } while(n > 0); - poperror(); - qunlock(&e->wlock); - return p-(uchar*)a; -} - -static void -init(Usbhost* uh) -{ - Ctlr *ctlr; - - ctlr = uh->ctlr; - ilock(ctlr); - outl(ctlr->io+Flbaseadd, PCIWADDR(ctlr->frames)); - OUT(Frnum, 0); - OUT(Usbintr, 0xF); /* enable all interrupts */ - XPRINT("cmd 0x%x sofmod 0x%x\n", IN(Cmd), inb(ctlr->io+SOFMod)); - XPRINT("sc0 0x%x sc1 0x%x\n", IN(Portsc0), IN(Portsc1)); - if((IN(Cmd)&1)==0) - OUT(Cmd, 1); /* run */ -// pprint("at: c=%x s=%x c0=%x\n", IN(Cmd), IN(Status), IN(Portsc0)); - iunlock(ctlr); -} - -static void -scanpci(void) -{ - int io; - Ctlr *ctlr; - Pcidev *p; - static int already = 0; - - if(already) - return; - already = 1; - p = nil; - while(p = pcimatch(p, 0, 0)) { - /* - * Find UHCI controllers. Class = 12 (serial controller), - * Sub-class = 3 (USB) and Programming Interface = 0. - */ - if(p->ccrb != 0x0C || p->ccru != 0x03 || p->ccrp != 0x00) - continue; - io = p->mem[4].bar & ~0x0F; - if(io == 0) { - print("usbuhci: failed to map registers\n"); - continue; - } - if(ioalloc(io, p->mem[4].size, 0, "usbuhci") < 0){ - print("usbuhci: port %d in use\n", io); - continue; - } - if(p->intl == 0xFF || p->intl == 0) { - print("usbuhci: no irq assigned for port %d\n", io); - continue; - } - - XPRINT("usbuhci: %x/%x port 0x%ux size 0x%x irq %d\n", - p->vid, p->did, io, p->mem[4].size, p->intl); - - ctlr = malloc(sizeof(Ctlr)); - ctlr->pcidev = p; - ctlr->io = io; - if(ctlrhead != nil) - ctlrtail->next = ctlr; - else - ctlrhead = ctlr; - ctlrtail = ctlr; - } -} - -static int -reset(Usbhost *uh) -{ - int i; - TD *t; - ulong io; - Ctlr *ctlr; - Pcidev *p; - - scanpci(); - - /* - * Any adapter matches if no uh->port is supplied, - * otherwise the ports must match. - */ - for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){ - if(ctlr->active) - continue; - if(uh->port == 0 || uh->port == ctlr->io){ - ctlr->active = 1; - break; - } - } - if(ctlr == nil) - return -1; - - io = ctlr->io; - p = ctlr->pcidev; - - uh->ctlr = ctlr; - uh->port = io; - uh->irq = p->intl; - uh->tbdf = p->tbdf; - - XPRINT("usbcmd\t0x%.4x\nusbsts\t0x%.4x\nusbintr\t0x%.4x\nfrnum\t0x%.2x\n", - IN(Cmd), IN(Status), IN(Usbintr), inb(io+Frnum)); - XPRINT("frbaseadd\t0x%.4x\nsofmod\t0x%x\nportsc1\t0x%.4x\nportsc2\t0x%.4x\n", - IN(Flbaseadd), inb(io+SOFMod), IN(Portsc0), IN(Portsc1)); - - OUT(Cmd, 0); /* stop */ - while((IN(Status) & (1<<5)) == 0) /* wait for halt */ - ; - OUT(Status, 0xFF); /* clear pending interrupts */ - pcicfgw16(p, 0xc0, 0x2000); /* legacy support register: turn off lunacy mode */ - - if(0){ - i = inb(io+SOFMod); - OUT(Cmd, 4); /* global reset */ - delay(15); - OUT(Cmd, 0); /* end reset */ - delay(4); - outb(io+SOFMod, i); - } - - ctlr->tdpool = xspanalloc(128*sizeof(TD), 16, 0); - for(i=128; --i>=0;){ - ctlr->tdpool[i].next = ctlr->freetd; - ctlr->freetd = &ctlr->tdpool[i]; - } - ctlr->qhpool = xspanalloc(64*sizeof(QH), 16, 0); - for(i=64; --i>=0;){ - ctlr->qhpool[i].next = ctlr->freeqh; - ctlr->freeqh = &ctlr->qhpool[i]; - } - - /* - * the last entries of the periodic (interrupt & isochronous) scheduling TD entries - * points to the control queue and the bandwidth sop for bulk traffic. - * this is looped following the instructions in PIIX4 errata 29773804.pdf: - * a QH links to a looped but inactive TD as its sole entry, - * with its head entry leading on to the bulk traffic, the last QH of which - * links back to the empty QH. - */ - ctlr->ctlq = allocqh(ctlr); - ctlr->bwsop = allocqh(ctlr); - ctlr->bulkq = allocqh(ctlr); - ctlr->recvq = allocqh(ctlr); - t = alloctd(ctlr); /* inactive TD, looped */ - t->link = PCIWADDR(t); - ctlr->bwsop->entries = PCIWADDR(t); - - ctlr->ctlq->head = PCIWADDR(ctlr->bulkq) | IsQH; - ctlr->bulkq->head = PCIWADDR(ctlr->recvq) | IsQH; - ctlr->recvq->head = PCIWADDR(ctlr->bwsop) | IsQH; - if (1) /* don't use loop back */ - ctlr->bwsop->head = Terminate; - else /* set up loop back */ - ctlr->bwsop->head = PCIWADDR(ctlr->bwsop) | IsQH; - - ctlr->frames = xspanalloc(FRAMESIZE, FRAMESIZE, 0); - ctlr->frameld = xallocz(FRAMESIZE, 1); - for (i = 0; i < NFRAME; i++) - ctlr->frames[i] = PCIWADDR(ctlr->ctlq) | IsQH; - - /* - * Linkage to the generic USB driver. - */ - uh->init = init; - uh->interrupt = interrupt; - - uh->portinfo = portinfo; - uh->portreset = portreset; - uh->portenable = portenable; - - uh->epalloc = epalloc; - uh->epfree = epfree; - uh->epopen = epopen; - uh->epclose = epclose; - uh->epmode = epmode; - - uh->read = read; - uh->write = write; - - return 0; -} - -void -usbuhcilink(void) -{ - addusbtype("uhci", reset); -} diff --git a/os/pc/vga.c b/os/pc/vga.c deleted file mode 100644 index 0d6c7743..00000000 --- a/os/pc/vga.c +++ /dev/null @@ -1,241 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -static Memimage* back; -static Memimage *conscol; - -static Point curpos; -static Rectangle window; -static int *xp; -static int xbuf[256]; -static Lock vgascreenlock; -int drawdebug; - -void -vgaimageinit(ulong chan) -{ - if(back == nil){ - back = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */ - if(back == nil) - panic("back alloc"); /* RSC BUG */ - back->flags |= Frepl; - back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); - memfillcolor(back, DBlack); - } - - if(conscol == nil){ - conscol = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */ - if(conscol == nil) - panic("conscol alloc"); /* RSC BUG */ - conscol->flags |= Frepl; - conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); - memfillcolor(conscol, DWhite); - } -} - -static void -vgascroll(VGAscr* scr) -{ - int h, o; - Point p; - Rectangle r; - - h = scr->memdefont->height; - o = 8*h; - r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); - p = Pt(window.min.x, window.min.y+o); - memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p, S); - r = Rpt(Pt(window.min.x, window.max.y-o), window.max); - memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S); - - curpos.y -= o; -} - -static void -vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr) -{ - Point p; - int h, w, pos; - Rectangle r; - -// drawdebug = 1; - if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)]) - xp = xbuf; - - h = scr->memdefont->height; - switch(buf[0]){ - - case '\n': - if(curpos.y+h >= window.max.y){ - vgascroll(scr); - *flushr = window; - } - curpos.y += h; - vgascreenputc(scr, "\r", flushr); - break; - - case '\r': - xp = xbuf; - curpos.x = window.min.x; - break; - - case '\t': - p = memsubfontwidth(scr->memdefont, " "); - w = p.x; - if(curpos.x >= window.max.x-4*w) - vgascreenputc(scr, "\n", flushr); - - pos = (curpos.x-window.min.x)/w; - pos = 4-(pos%4); - *xp++ = curpos.x; - r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h); - memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S); - curpos.x += pos*w; - break; - - case '\b': - if(xp <= xbuf) - break; - xp--; - r = Rect(*xp, curpos.y, curpos.x, curpos.y+h); - memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP, S); - combinerect(flushr, r); - curpos.x = *xp; - break; - - case '\0': - break; - - default: - p = memsubfontwidth(scr->memdefont, buf); - w = p.x; - - if(curpos.x >= window.max.x-w) - vgascreenputc(scr, "\n", flushr); - - *xp++ = curpos.x; - r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h); - memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S); - memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf); - combinerect(flushr, r); - curpos.x += w; - } -// drawdebug = 0; -} - -static void -vgascreenputs(char* s, int n) -{ - int i; - Rune r; - char buf[4]; - VGAscr *scr; - Rectangle flushr; - - scr = &vgascreen[0]; - - if(!islo()){ - /* - * Don't deadlock trying to - * print in an interrupt. - */ - if(!canlock(&vgascreenlock)) - return; - } - else - lock(&vgascreenlock); - - flushr = Rect(10000, 10000, -10000, -10000); - - while(n > 0){ - i = chartorune(&r, s); - if(i == 0){ - s++; - --n; - continue; - } - memmove(buf, s, i); - buf[i] = 0; - n -= i; - s += i; - vgascreenputc(scr, buf, &flushr); - } - flushmemscreen(flushr); - - unlock(&vgascreenlock); -} - -void -vgascreenwin(VGAscr* scr) -{ - int h, w; - - h = scr->memdefont->height; - w = scr->memdefont->info[' '].width; - - window = insetrect(scr->gscreen->r, 48); - window.max.x = window.min.x+((window.max.x-window.min.x)/w)*w; - window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; - curpos = window.min; - - screenputs = vgascreenputs; -} - -/* - * Supposedly this is the way to turn DPMS - * monitors off using just the VGA registers. - * Unfortunately, it seems to mess up the video mode - * on the cards I've tried. - */ -void -vgablank(VGAscr*, int blank) -{ - uchar seq1, crtc17; - - if(blank) { - seq1 = 0x00; - crtc17 = 0x80; - } else { - seq1 = 0x20; - crtc17 = 0x00; - } - - outs(Seqx, 0x0100); /* synchronous reset */ - seq1 |= vgaxi(Seqx, 1) & ~0x20; - vgaxo(Seqx, 1, seq1); - crtc17 |= vgaxi(Crtx, 0x17) & ~0x80; - delay(10); - vgaxo(Crtx, 0x17, crtc17); - outs(Crtx, 0x0300); /* end synchronous reset */ -} - -void -cornerstring(char *s) -{ - int h, w; - VGAscr *scr; - Rectangle r; - Point p; - - scr = &vgascreen[0]; - if(scr->aperture == 0 || screenputs != vgascreenputs) - return; - p = memsubfontwidth(scr->memdefont, s); - w = p.x; - h = scr->memdefont->height; - - r = Rect(0, 0, w, h); - memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S); - memimagestring(scr->gscreen, r.min, conscol, ZP, scr->memdefont, s); -// flushmemscreen(r); -} diff --git a/os/pc/vga.h b/os/pc/vga.h deleted file mode 100644 index 685a8ee5..00000000 --- a/os/pc/vga.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Generic VGA registers. - */ -enum { - MiscW = 0x03C2, /* Miscellaneous Output (W) */ - MiscR = 0x03CC, /* Miscellaneous Output (R) */ - Status0 = 0x03C2, /* Input status 0 (R) */ - Status1 = 0x03DA, /* Input Status 1 (R) */ - FeatureR = 0x03CA, /* Feature Control (R) */ - FeatureW = 0x03DA, /* Feature Control (W) */ - - Seqx = 0x03C4, /* Sequencer Index, Data at Seqx+1 */ - Crtx = 0x03D4, /* CRT Controller Index, Data at Crtx+1 */ - Grx = 0x03CE, /* Graphics Controller Index, Data at Grx+1 */ - Attrx = 0x03C0, /* Attribute Controller Index and Data */ - - PaddrW = 0x03C8, /* Palette Address Register, write */ - Pdata = 0x03C9, /* Palette Data Register */ - Pixmask = 0x03C6, /* Pixel Mask Register */ - PaddrR = 0x03C7, /* Palette Address Register, read */ - Pstatus = 0x03C7, /* DAC Status (RO) */ - - Pcolours = 256, /* Palette */ - Pred = 0, - Pgreen = 1, - Pblue = 2, - - Pblack = 0x00, - Pwhite = 0xFF, -}; - -#define vgai(port) inb(port) -#define vgao(port, data) outb(port, data) - -extern int vgaxi(long, uchar); -extern int vgaxo(long, uchar, uchar); - -typedef struct Cursor Cursor; -struct Cursor -{ - Point offset; - uchar clr[2*16]; - uchar set[2*16]; -}; - -/* - * First pass at tidying this up... - */ -typedef struct Mode { - int x; - int y; - int d; - - ulong aperture; /* this is a physical address */ - int apsize; - int apshift; -} Mode; - -/* - * Definitions of known VGA controllers. - */ -typedef struct Vgac Vgac; -struct Vgac { - char* name; - void (*page)(int); - void (*init)(Mode*); - int (*ident)(void); - void (*enable)(void); - void (*disable)(void); - void (*move)(int, int); - void (*load)(Cursor*); - Vgac* link; -}; - -extern void addvgaclink(Vgac*); diff --git a/os/pc/vga3dfx.c b/os/pc/vga3dfx.c deleted file mode 100644 index cce27185..00000000 --- a/os/pc/vga3dfx.c +++ /dev/null @@ -1,258 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -typedef struct { - int vidProcCfg; - int hwCurPatAddr; - int hwCurLoc; - int hwCurC0; - int hwCurC1; -} Cursor3dfx; - -enum { - dramInit0 = 0x18, - dramInit1 = 0x1C, - - hwCur = 0x5C, -}; - -static ulong -tdfxlinear(VGAscr* scr, int* size, int* align) -{ - Pcidev *p; - int oapsize, wasupamem; - ulong aperture, oaperture; - - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - - aperture = 0; - if(p = pcimatch(nil, 0x121A, 0)){ - switch(p->did){ - case 0x0003: /* Banshee */ - case 0x0005: /* Avenger (a.k.a. Voodoo3) */ - case 0x0009: /* Voodoo5 */ - aperture = p->mem[1].bar & ~0x0F; - *size = p->mem[1].size; - break; - default: - break; - } - } - - if(wasupamem){ - if(oaperture == aperture) - return oaperture; - upafree(oaperture, oapsize); - } - scr->isupamem = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)){ - aperture = oaperture; - scr->isupamem = 1; - } - else - scr->isupamem = 0; - } - else - scr->isupamem = 1; - - return aperture; -} - -static void -tdfxenable(VGAscr* scr) -{ - Pcidev *p; - ulong aperture; - int align, i, *mmio, size; - - /* - * Only once, can't be disabled for now. - * scr->io holds the physical address of - * the MMIO registers. - */ - if(scr->io) - return; - if(p = pcimatch(nil, 0x121A, 0)){ - switch(p->did){ - case 0x0003: /* Banshee */ - case 0x0005: /* Avenger (a.k.a. Voodoo3) */ - break; - default: - return; - } - } - else - return; - scr->io = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0); - if(scr->io == 0) - return; - - addvgaseg("3dfxmmio", (ulong)scr->io, p->mem[0].size); - - size = p->mem[1].size; - align = 0; - aperture = tdfxlinear(scr, &size, &align); - if(aperture){ - scr->aperture = aperture; - scr->apsize = size; - addvgaseg("3dfxscreen", aperture, size); - } - - /* - * Find a place for the cursor data in display memory. - * If SDRAM then there's 16MB memory else it's SGRAM - * and can count it based on the power-on straps - - * chip size can be 8Mb or 16Mb, and there can be 4 or - * 8 of them. - * Use the last 1KB of the framebuffer. - */ - mmio = KADDR(scr->io + dramInit0); - if(*(mmio+1) & 0x40000000) - i = 16*1024*1024; - else{ - if(*mmio & 0x08000000) - i = 16*1024*1024/8; - else - i = 8*1024*1024/8; - if(*mmio & 0x04000000) - i *= 8; - else - i *= 4; - } - scr->storage = i - 1024; -} - -static void -tdfxcurdisable(VGAscr* scr) -{ - Cursor3dfx *cursor3dfx; - - if(scr->io == 0) - return; - cursor3dfx = KADDR(scr->io+hwCur); - cursor3dfx->vidProcCfg &= ~0x08000000; -} - -static void -tdfxcurload(VGAscr* scr, Cursor* curs) -{ - int y; - uchar *p; - Cursor3dfx *cursor3dfx; - - if(scr->io == 0) - return; - cursor3dfx = KADDR(scr->io+hwCur); - - /* - * Disable the cursor then load the new image in - * the top-left of the 64x64 array. - * The cursor data is stored in memory as 128-bit - * words consisting of plane 0 in the least significant 64-bits - * and plane 1 in the most significant. - * The X11 cursor truth table is: - * p0 p1 colour - * 0 0 transparent - * 0 1 transparent - * 1 0 hwCurC0 - * 1 1 hwCurC1 - * Unused portions of the image have been initialised to be - * transparent. - */ - cursor3dfx->vidProcCfg &= ~0x08000000; - p = KADDR(scr->aperture + scr->storage); - for(y = 0; y < 16; y++){ - *p++ = curs->clr[2*y]|curs->set[2*y]; - *p++ = curs->clr[2*y+1]|curs->set[2*y+1]; - p += 6; - *p++ = curs->set[2*y]; - *p++ = curs->set[2*y+1]; - p += 6; - } - - /* - * Save the cursor hotpoint and enable the cursor. - * The 0,0 cursor point is bottom-right. - */ - scr->offset.x = 63+curs->offset.x; - scr->offset.y = 63+curs->offset.y; - cursor3dfx->vidProcCfg |= 0x08000000; -} - -static int -tdfxcurmove(VGAscr* scr, Point p) -{ - Cursor3dfx *cursor3dfx; - - if(scr->io == 0) - return 1; - cursor3dfx = KADDR(scr->io+hwCur); - - cursor3dfx->hwCurLoc = ((p.y+scr->offset.y)<<16)|(p.x+scr->offset.x); - - return 0; -} - -static void -tdfxcurenable(VGAscr* scr) -{ - Cursor3dfx *cursor3dfx; - - tdfxenable(scr); - if(scr->io == 0) - return; - cursor3dfx = KADDR(scr->io+hwCur); - - /* - * Cursor colours. - */ - cursor3dfx->hwCurC0 = 0xFFFFFFFF; - cursor3dfx->hwCurC1 = 0x00000000; - - /* - * Initialise the 64x64 cursor to be transparent (X11 mode). - */ - cursor3dfx->hwCurPatAddr = scr->storage; - memset(KADDR(scr->aperture + scr->storage), 0, 64*16); - - /* - * Load, locate and enable the 64x64 cursor in X11 mode. - */ - tdfxcurload(scr, &arrow); - tdfxcurmove(scr, ZP); - cursor3dfx->vidProcCfg |= 0x08000002; -} - -VGAdev vga3dfxdev = { - "3dfx", - - tdfxenable, - nil, - nil, - tdfxlinear, -}; - -VGAcur vga3dfxcur = { - "3dfxhwgc", - - tdfxcurenable, - tdfxcurdisable, - tdfxcurload, - tdfxcurmove, -}; diff --git a/os/pc/vgaark2000pv.c b/os/pc/vgaark2000pv.c deleted file mode 100644 index d42eccc3..00000000 --- a/os/pc/vgaark2000pv.c +++ /dev/null @@ -1,190 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -static int -ark2000pvpageset(VGAscr*, int page) -{ - uchar seq15; - - seq15 = vgaxi(Seqx, 0x15); - vgaxo(Seqx, 0x15, page); - vgaxo(Seqx, 0x16, page); - - return seq15; -} - -static void -ark2000pvpage(VGAscr* scr, int page) -{ - lock(&scr->devlock); - ark2000pvpageset(scr, page); - unlock(&scr->devlock); -} - -static void -ark2000pvdisable(VGAscr*) -{ - uchar seq20; - - seq20 = vgaxi(Seqx, 0x20) & ~0x08; - vgaxo(Seqx, 0x20, seq20); -} - -static void -ark2000pvenable(VGAscr* scr) -{ - uchar seq20; - ulong storage; - - /* - * Disable the cursor then configure for X-Windows style, - * 32x32 and 4/8-bit colour depth. - * Set cursor colours for 4/8-bit. - */ - seq20 = vgaxi(Seqx, 0x20) & ~0x1F; - vgaxo(Seqx, 0x20, seq20); - seq20 |= 0x18; - - vgaxo(Seqx, 0x26, 0x00); - vgaxo(Seqx, 0x27, 0x00); - vgaxo(Seqx, 0x28, 0x00); - vgaxo(Seqx, 0x29, 0xFF); - vgaxo(Seqx, 0x2A, 0xFF); - vgaxo(Seqx, 0x2B, 0xFF); - - /* - * Cursor storage is a 256 byte or 1Kb block located in the last - * 16Kb of video memory. Crt25 is the index of which block. - */ - storage = (vgaxi(Seqx, 0x10)>>6) & 0x03; - storage = (1024*1024)<storage = storage; - vgaxo(Seqx, 0x25, 0x3F); - - /* - * Enable the cursor. - */ - vgaxo(Seqx, 0x20, seq20); -} - -static void -ark2000pvload(VGAscr* scr, Cursor* curs) -{ - uchar *p, seq10; - int opage, x, y; - - /* - * Is linear addressing turned on? This will determine - * how we access the cursor storage. - */ - seq10 = vgaxi(Seqx, 0x10); - opage = 0; - p = KADDR(scr->aperture); - if(!(seq10 & 0x10)){ - lock(&scr->devlock); - opage = ark2000pvpageset(scr, scr->storage>>16); - p += (scr->storage & 0xFFFF); - } - else - p += scr->storage; - - /* - * The cursor is set in X11 mode which gives the following - * truth table: - * and xor colour - * 0 0 underlying pixel colour - * 0 1 underlying pixel colour - * 1 0 background colour - * 1 1 foreground colour - * Put the cursor into the top-left of the 32x32 array. - * The manual doesn't say what the data layout in memory is - - * this worked out by trial and error. - */ - for(y = 0; y < 32; y++){ - for(x = 0; x < 32/8; x++){ - if(x < 16/8 && y < 16){ - *p++ = curs->clr[2*y + x]|curs->set[2*y + x]; - *p++ = curs->set[2*y + x]; - } - else { - *p++ = 0x00; - *p++ = 0x00; - } - } - } - - if(!(seq10 & 0x10)){ - ark2000pvpageset(scr, opage); - unlock(&scr->devlock); - } - - /* - * Save the cursor hotpoint. - */ - scr->offset = curs->offset; -} - -static int -ark2000pvmove(VGAscr* scr, Point p) -{ - int x, xo, y, yo; - - /* - * Mustn't position the cursor offscreen even partially, - * or it might disappear. Therefore, if x or y is -ve, adjust the - * cursor origins instead. - */ - if((x = p.x+scr->offset.x) < 0){ - xo = -x; - x = 0; - } - else - xo = 0; - if((y = p.y+scr->offset.y) < 0){ - yo = -y; - y = 0; - } - else - yo = 0; - - /* - * Load the new values. - */ - vgaxo(Seqx, 0x2C, xo); - vgaxo(Seqx, 0x2D, yo); - vgaxo(Seqx, 0x21, (x>>8) & 0x0F); - vgaxo(Seqx, 0x22, x & 0xFF); - vgaxo(Seqx, 0x23, (y>>8) & 0x0F); - vgaxo(Seqx, 0x24, y & 0xFF); - - return 0; -} - -VGAdev vgaark2000pvdev = { - "ark2000pv", - - 0, - 0, - ark2000pvpage, - 0, -}; - -VGAcur vgaark2000pvcur = { - "ark2000pvhwgc", - - ark2000pvenable, - ark2000pvdisable, - ark2000pvload, - ark2000pvmove, -}; diff --git a/os/pc/vgabt485.c b/os/pc/vgabt485.c deleted file mode 100644 index 1c155e6d..00000000 --- a/os/pc/vgabt485.c +++ /dev/null @@ -1,245 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -/* - * Hardware graphics cursor support for - * Brooktree Bt485 Monolithic True-Color RAMDAC. - * Assumes hooked up to an S3 86C928. - * - * BUGS: - * 64x64x2 cursor always used; - * no support for interlaced mode. - */ -enum { - AddrW = 0x00, /* Address register; palette/cursor RAM write */ - Palette = 0x01, /* 6/8-bit color palette data */ - Pmask = 0x02, /* Pixel mask register */ - AddrR = 0x03, /* Address register; palette/cursor RAM read */ - ColorW = 0x04, /* Address register; cursor/overscan color write */ - Color = 0x05, /* Cursor/overscan color data */ - Cmd0 = 0x06, /* Command register 0 */ - ColorR = 0x07, /* Address register; cursor/overscan color read */ - Cmd1 = 0x08, /* Command register 1 */ - Cmd2 = 0x09, /* Command register 2 */ - Status = 0x0A, /* Status */ - Cmd3 = 0x1A, /* Command register 3 */ - Cram = 0x0B, /* Cursor RAM array data */ - Cxlr = 0x0C, /* Cursor x-low register */ - Cxhr = 0x0D, /* Cursor x-high register */ - Cylr = 0x0E, /* Cursor y-low register */ - Cyhr = 0x0F, /* Cursor y-high register */ - - Nreg = 0x10, -}; - -/* - * Lower 2-bits of indirect DAC register - * addressing. - */ -static ushort dacxreg[4] = { - PaddrW, Pdata, Pixmask, PaddrR -}; - -static uchar -bt485io(uchar reg) -{ - uchar crt55, cr0; - - crt55 = vgaxi(Crtx, 0x55) & 0xFC; - if((reg & 0x0F) == Status){ - /* - * 1,2: Set indirect addressing for Status or - * Cmd3 - set bit7 of Cr0. - */ - vgaxo(Crtx, 0x55, crt55|((Cmd0>>2) & 0x03)); - cr0 = vgai(dacxreg[Cmd0 & 0x03])|0x80; - vgao(dacxreg[Cmd0 & 0x03], cr0); - - /* - * 3,4: Set the index into the Write register, - * index == 0x00 for Status, 0x01 for Cmd3. - */ - vgaxo(Crtx, 0x55, crt55|((AddrW>>2) & 0x03)); - vgao(dacxreg[AddrW & 0x03], (reg == Status) ? 0x00: 0x01); - - /* - * 5,6: Get the contents of the appropriate - * register at 0x0A. - */ - } - - return crt55; -} - -static uchar -bt485i(uchar reg) -{ - uchar crt55, r; - - crt55 = bt485io(reg); - vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03)); - r = vgai(dacxreg[reg & 0x03]); - vgaxo(Crtx, 0x55, crt55); - - return r; -} - -static void -bt485o(uchar reg, uchar data) -{ - uchar crt55; - - crt55 = bt485io(reg); - vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03)); - vgao(dacxreg[reg & 0x03], data); - vgaxo(Crtx, 0x55, crt55); -} - -static void -bt485disable(VGAscr*) -{ - uchar r; - - /* - * Disable - * cursor mode 3; - * cursor control enable for Bt485 DAC; - * the hardware cursor external operation mode. - */ - r = bt485i(Cmd2) & ~0x03; - bt485o(Cmd2, r); - - r = vgaxi(Crtx, 0x45) & ~0x20; - vgaxo(Crtx, 0x45, r); - - r = vgaxi(Crtx, 0x55) & ~0x20; - vgaxo(Crtx, 0x55, r); -} - -static void -bt485enable(VGAscr*) -{ - uchar r; - - /* - * Turn cursor off. - */ - r = bt485i(Cmd2) & 0xFC; - bt485o(Cmd2, r); - - /* - * Overscan colour, - * cursor colour 1 (white), - * cursor colour 2, 3 (black). - */ - bt485o(ColorW, 0x00); - bt485o(Color, Pwhite); bt485o(Color, Pwhite); bt485o(Color, Pwhite); - - bt485o(Color, Pwhite); bt485o(Color, Pwhite); bt485o(Color, Pwhite); - - bt485o(Color, Pblack); bt485o(Color, Pblack); bt485o(Color, Pblack); - bt485o(Color, Pblack); bt485o(Color, Pblack); bt485o(Color, Pblack); - - /* - * Finally, enable - * the hardware cursor external operation mode; - * cursor control enable for Bt485 DAC. - * The #9GXE cards seem to need the 86C928 Bt485 support - * enabled in order to work at all in enhanced mode. - */ - - r = vgaxi(Crtx, 0x55)|0x20; - vgaxo(Crtx, 0x55, r); - - r = vgaxi(Crtx, 0x45)|0x20; - vgaxo(Crtx, 0x45, r); -} - -static void -bt485load(VGAscr* scr, Cursor* curs) -{ - uchar r; - int x, y; - - /* - * Turn cursor off; - * put cursor into 64x64x2 mode and clear MSBs of address; - * clear LSBs of address; - */ - r = bt485i(Cmd2) & 0xFC; - bt485o(Cmd2, r); - - r = (bt485i(Cmd3) & 0xFC)|0x04; - bt485o(Cmd3, r); - - bt485o(AddrW, 0x00); - - /* - * Now load the cursor RAM array, both planes. - * The cursor is 16x16, the array 64x64; put - * the cursor in the top left. The 0,0 cursor - * point is bottom-right, so positioning will - * have to take that into account. - */ - for(y = 0; y < 64; y++){ - for(x = 0; x < 64/8; x++){ - if(x < 16/8 && y < 16) - bt485o(Cram, curs->clr[x+y*2]); - else - bt485o(Cram, 0x00); - } - } - for(y = 0; y < 64; y++){ - for(x = 0; x < 64/8; x++){ - if(x < 16/8 && y < 16) - bt485o(Cram, curs->set[x+y*2]); - else - bt485o(Cram, 0x00); - } - } - - /* - * Initialise the cursor hot-point - * and enable the cursor. - */ - scr->offset.x = 64+curs->offset.x; - scr->offset.y = 64+curs->offset.y; - - r = (bt485i(Cmd2) & 0xFC)|0x01; - bt485o(Cmd2, r); -} - -static int -bt485move(VGAscr* scr, Point p) -{ - int x, y; - - x = p.x+scr->offset.x; - y = p.y+scr->offset.y; - - bt485o(Cxlr, x & 0xFF); - bt485o(Cxhr, (x>>8) & 0x0F); - bt485o(Cylr, y & 0xFF); - bt485o(Cyhr, (y>>8) & 0x0F); - - return 0; -} - -VGAcur vgabt485cur = { - "bt485hwgc", - - bt485enable, - bt485disable, - bt485load, - bt485move, -}; diff --git a/os/pc/vgaclgd542x.c b/os/pc/vgaclgd542x.c deleted file mode 100644 index 6dd95e9e..00000000 --- a/os/pc/vgaclgd542x.c +++ /dev/null @@ -1,291 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -static int -clgd542xpageset(VGAscr*, int page) -{ - uchar gr09; - int opage; - - if(vgaxi(Seqx, 0x07) & 0xF0) - page = 0; - gr09 = vgaxi(Grx, 0x09); - if(vgaxi(Grx, 0x0B) & 0x20){ - vgaxo(Grx, 0x09, page<<2); - opage = gr09>>2; - } - else{ - vgaxo(Grx, 0x09, page<<4); - opage = gr09>>4; - } - - return opage; -} - -static void -clgd542xpage(VGAscr* scr, int page) -{ - lock(&scr->devlock); - clgd542xpageset(scr, page); - unlock(&scr->devlock); -} - -static ulong -clgd542xlinear(VGAscr* scr, int* size, int* align) -{ - ulong aperture, oaperture; - int oapsize, wasupamem; - Pcidev *p; - - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - if(wasupamem) - upafree(oaperture, oapsize); - scr->isupamem = 0; - - if(p = pcimatch(nil, 0x1013, 0)){ - aperture = p->mem[0].bar & ~0x0F; - *size = p->mem[0].size; - } - else - aperture = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)) - scr->isupamem = 1; - } - else - scr->isupamem = 1; - - return aperture; -} - -static void -clgd542xdisable(VGAscr*) -{ - uchar sr12; - - sr12 = vgaxi(Seqx, 0x12); - vgaxo(Seqx, 0x12, sr12 & ~0x01); -} - -static void -clgd542xenable(VGAscr* scr) -{ - uchar sr12; - int mem, x; - - /* - * Disable the cursor. - */ - sr12 = vgaxi(Seqx, 0x12); - vgaxo(Seqx, 0x12, sr12 & ~0x01); - - /* - * Cursor colours. - * Can't call setcolor here as cursor is already locked. - */ - vgaxo(Seqx, 0x12, sr12|0x02); - vgao(PaddrW, 0x00); - vgao(Pdata, Pwhite); - vgao(Pdata, Pwhite); - vgao(Pdata, Pwhite); - vgao(PaddrW, 0x0F); - vgao(Pdata, Pblack); - vgao(Pdata, Pblack); - vgao(Pdata, Pblack); - vgaxo(Seqx, 0x12, sr12); - - mem = 0; - switch(vgaxi(Crtx, 0x27) & ~0x03){ - - case 0x88: /* CL-GD5420 */ - case 0x8C: /* CL-GD5422 */ - case 0x94: /* CL-GD5424 */ - case 0x80: /* CL-GD5425 */ - case 0x90: /* CL-GD5426 */ - case 0x98: /* CL-GD5427 */ - case 0x9C: /* CL-GD5429 */ - /* - * The BIOS leaves the memory size in Seq0A, bits 4 and 3. - * See Technical Reference Manual Appendix E1, Section 1.3.2. - * - * The storage area for the 64x64 cursors is the last 16Kb of - * display memory. - */ - mem = (vgaxi(Seqx, 0x0A)>>3) & 0x03; - break; - - case 0xA0: /* CL-GD5430 */ - case 0xA8: /* CL-GD5434 */ - case 0xAC: /* CL-GD5436 */ - case 0xB8: /* CL-GD5446 */ - case 0x30: /* CL-GD7543 */ - /* - * Attempt to intuit the memory size from the DRAM control - * register. Minimum is 512KB. - * If DRAM bank switching is on then there's double. - */ - x = vgaxi(Seqx, 0x0F); - mem = (x>>3) & 0x03; - if(x & 0x80) - mem++; - break; - - default: /* uh, ah dunno */ - break; - } - scr->storage = ((256<aperture); - if(!(seq07 & 0xF0)){ - lock(&scr->devlock); - opage = clgd542xpageset(scr, scr->storage>>16); - p += (scr->storage & 0xFFFF); - } - else - p += scr->storage; - p += index*1024; - - for(y = yo; y < 16; y++){ - p0 = scr->set[2*y]; - p1 = scr->set[2*y+1]; - if(xo){ - p0 = (p0<>(8-xo)); - p1 <<= xo; - } - *p++ = p0; - *p++ = p1; - - for(x = 16; x < 64; x += 8) - *p++ = 0x00; - - p0 = scr->clr[2*y]|scr->set[2*y]; - p1 = scr->clr[2*y+1]|scr->set[2*y+1]; - if(xo){ - p0 = (p0<>(8-xo)); - p1 <<= xo; - } - *p++ = p0; - *p++ = p1; - - for(x = 16; x < 64; x += 8) - *p++ = 0x00; - } - while(y < 64+yo){ - for(x = 0; x < 64; x += 8){ - *p++ = 0x00; - *p++ = 0x00; - } - y++; - } - - if(!(seq07 & 0xF0)){ - clgd542xpageset(scr, opage); - unlock(&scr->devlock); - } -} - -static void -clgd542xload(VGAscr* scr, Cursor* curs) -{ - uchar sr12; - - /* - * Disable the cursor. - */ - sr12 = vgaxi(Seqx, 0x12); - vgaxo(Seqx, 0x12, sr12 & ~0x01); - - memmove(&scr->Cursor, curs, sizeof(Cursor)); - clgd542xinitcursor(scr, 0, 0, 0); - - /* - * Enable the cursor. - */ - vgaxo(Seqx, 0x13, 0); - vgaxo(Seqx, 0x12, sr12|0x05); -} - -static int -clgd542xmove(VGAscr* scr, Point p) -{ - int index, x, xo, y, yo; - - index = 0; - if((x = p.x+scr->offset.x) < 0){ - xo = -x; - x = 0; - } - else - xo = 0; - if((y = p.y+scr->offset.y) < 0){ - yo = -y; - y = 0; - } - else - yo = 0; - - if(xo || yo){ - clgd542xinitcursor(scr, xo, yo, 1); - index = 1; - } - vgaxo(Seqx, 0x13, index<<2); - - vgaxo(Seqx, 0x10|((x & 0x07)<<5), (x>>3) & 0xFF); - vgaxo(Seqx, 0x11|((y & 0x07)<<5), (y>>3) & 0xFF); - - return 0; -} - -VGAdev vgaclgd542xdev = { - "clgd542x", - - 0, - 0, - clgd542xpage, - clgd542xlinear, -}; - -VGAcur vgaclgd542xcur = { - "clgd542xhwgc", - - clgd542xenable, - clgd542xdisable, - clgd542xload, - clgd542xmove, -}; diff --git a/os/pc/vgaclgd546x.c b/os/pc/vgaclgd546x.c deleted file mode 100644 index 62bcd82a..00000000 --- a/os/pc/vgaclgd546x.c +++ /dev/null @@ -1,277 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -typedef struct Cursor546x Cursor546x; -struct Cursor546x { - ushort x; - ushort y; - ushort preset; - ushort enable; - ushort addr; -}; - -enum { - PaletteState = 0xB0, - CursorMMIO = 0xE0, -}; - -static ulong -clgd546xlinear(VGAscr* scr, int* size, int* align) -{ - ulong aperture, oaperture; - int oapsize, wasupamem; - Pcidev *p; - - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - - aperture = 0; - if(p = pcimatch(nil, 0x1013, 0)){ - switch(p->did){ - case 0xD0: - case 0xD4: - case 0xD6: - aperture = p->mem[0].bar & ~0x0F; - *size = p->mem[0].size; - break; - default: - break; - } - } - - if(wasupamem){ - if(oaperture == aperture) - return oaperture; - upafree(oaperture, oapsize); - } - scr->isupamem = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)){ - aperture = oaperture; - scr->isupamem = 1; - } - else - scr->isupamem = 0; - } - else - scr->isupamem = 1; - - return aperture; -} -static void -clgd546xenable(VGAscr* scr) -{ - Pcidev *p; - int size, align; - ulong aperture; - - /* - * Only once, can't be disabled for now. - * scr->io holds the virtual address of - * the MMIO registers. - */ - if(scr->io) - return; - if(p = pcimatch(nil, 0x1013, 0)){ - switch(p->did){ - case 0xD0: - case 0xD4: - case 0xD6: - break; - default: - return; - } - } - else - return; - scr->io = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0); - if(scr->io == 0) - return; - addvgaseg("clgd546xmmio", scr->io, p->mem[1].size); - - scr->io = (ulong)KADDR(scr->io); - - size = p->mem[0].size; - align = 0; - aperture = clgd546xlinear(scr, &size, &align); - if(aperture) { - scr->aperture = aperture; - scr->apsize = size; - addvgaseg("clgd546xscreen", aperture, size); - } -} - -static void -clgd546xcurdisable(VGAscr* scr) -{ - Cursor546x *cursor546x; - - if(scr->io == 0) - return; - cursor546x = (Cursor546x*)(scr->io+CursorMMIO); - cursor546x->enable = 0; -} - -static void -clgd546xcurload(VGAscr* scr, Cursor* curs) -{ - int c, i, m, y; - uchar *p; - Cursor546x *cursor546x; - - if(scr->io == 0) - return; - cursor546x = (Cursor546x*)(scr->io+CursorMMIO); - - /* - * Disable the cursor then change only the bits - * that need it. - */ - cursor546x->enable = 0; - p = (uchar*)(scr->aperture + scr->storage); - for(y = 0; y < 16; y++){ - c = curs->set[2*y]; - m = 0; - for(i = 0; i < 8; i++){ - if(c & (1<<(7-i))) - m |= 1<set[2*y + 1]; - m = 0; - for(i = 0; i < 8; i++){ - if(c & (1<<(7-i))) - m |= 1<set[2*y]|curs->clr[2*y]; - m = 0; - for(i = 0; i < 8; i++){ - if(c & (1<<(7-i))) - m |= 1<set[2*y + 1]|curs->clr[2*y + 1]; - m = 0; - for(i = 0; i < 8; i++){ - if(c & (1<<(7-i))) - m |= 1<offset = curs->offset; - cursor546x->enable = 1; -} - -static int -clgd546xcurmove(VGAscr* scr, Point p) -{ - int x, xo, y, yo; - Cursor546x *cursor546x; - - if(scr->io == 0) - return 1; - cursor546x = (Cursor546x*)(scr->io+CursorMMIO); - - if((x = p.x+scr->offset.x) < 0){ - xo = -x; - x = 0; - } - else - xo = 0; - if((y = p.y+scr->offset.y) < 0){ - yo = -y; - y = 0; - } - else - yo = 0; - - cursor546x->preset = (xo<<8)|yo; - cursor546x->x = x; - cursor546x->y = y; - - return 0; -} - -static void -clgd546xcurenable(VGAscr* scr) -{ - uchar *p; - Cursor546x *cursor546x; - - clgd546xenable(scr); - if(scr->io == 0) - return; - cursor546x = (Cursor546x*)(scr->io+CursorMMIO); - - /* - * Cursor colours. - * Can't call setcolor here as cursor is already locked. - */ - p = (uchar*)(scr->io+PaletteState); - *p |= 0x08; - vgao(PaddrW, 0x00); - vgao(Pdata, Pwhite); - vgao(Pdata, Pwhite); - vgao(Pdata, Pwhite); - vgao(PaddrW, 0x0F); - vgao(Pdata, Pblack); - vgao(Pdata, Pblack); - vgao(Pdata, Pblack); - *p &= ~0x08; - - /* - * Find a place for the cursor data in display memory. - * 2 cursor images might be needed, 1KB each so use the last - * 2KB of the framebuffer and initialise them to be - * transparent. - */ - scr->storage = ((vgaxi(Seqx, 0x14) & 0x07)+1)*1024*1022; - cursor546x->addr = (scr->storage>>10)<<2; - memset((uchar*)(scr->aperture + scr->storage), 0, 2*64*16); - - /* - * Load, locate and enable the 64x64 cursor. - */ - clgd546xcurload(scr, &arrow); - clgd546xcurmove(scr, ZP); - cursor546x->enable = 1; -} - -VGAdev vgaclgd546xdev = { - "clgd546x", - - clgd546xenable, - nil, - nil, - clgd546xlinear, -}; - -VGAcur vgaclgd546xcur = { - "clgd546xhwgc", - - clgd546xcurenable, - clgd546xcurdisable, - clgd546xcurload, - clgd546xcurmove, -}; diff --git a/os/pc/vgact65545.c b/os/pc/vgact65545.c deleted file mode 100644 index 9a1467ac..00000000 --- a/os/pc/vgact65545.c +++ /dev/null @@ -1,149 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -static void -ct65545page(VGAscr*, int page) -{ - outb(0x3D6, 0x10); - outb(0x3D7, page<<6); -} - -static void -ct65545disable(VGAscr*) -{ - outl(0xA3D0, 0); -} - -static void -ct65545enable(VGAscr* scr) -{ - ulong storage; - - /* - * Find a place for the cursor data in display memory. - * Must be on a 1024-byte boundary. - */ - storage = ROUND(scr->gscreen->width*BY2WD*scr->gscreen->r.max.y, 1024); - outl(0xB3D0, storage); - scr->storage = storage; - - /* - * Set the colours. - * Enable the cursor. - */ - outl(0xA7D0, 0xFFFF0000); - outl(0xA3D0, 2); -} - -static void -ct65545initcursor(VGAscr* scr, int xo, int yo, int index) -{ - uchar *mem; - uint and, clr, set, xor; - int i, x, y; - - mem = KADDR(scr->aperture); - mem += scr->storage + index*1024; - - for(y = yo; y < 16; y++){ - clr = (scr->clr[2*y]<<8)|scr->clr[2*y+1]; - set = (scr->set[2*y]<<8)|scr->set[2*y+1]; - if(xo){ - clr <<= xo; - set <<= xo; - } - - and = 0; - xor = 0; - for(i = 0; i < 16; i++){ - if(set & (1<>8; - *mem++ = xor>>8; - *mem++ = and; - *mem++ = xor; - - for(x = 16; x < 64; x += 8){ - *mem++ = 0xFF; - *mem++ = 0x00; - } - } - while(y < 64+yo){ - for(x = 0; x < 64; x += 8){ - *mem++ = 0xFF; - *mem++ = 0x00; - } - y++; - } -} - -static void -ct65545load(VGAscr* scr, Cursor* curs) -{ - memmove(&scr->Cursor, curs, sizeof(Cursor)); - ct65545initcursor(scr, 0, 0, 0); -} - -static int -ct65545move(VGAscr* scr, Point p) -{ - int index, x, xo, y, yo; - - index = 0; - if((x = p.x+scr->offset.x) < 0){ - xo = -x; - x = 0; - } - else - xo = 0; - if((y = p.y+scr->offset.y) < 0){ - yo = -y; - y = 0; - } - else - yo = 0; - - if(xo || yo){ - ct65545initcursor(scr, xo, yo, 1); - index = 1; - } - outl(0xB3D0, scr->storage + index*1024); - - outl(0xAFD0, (y<<16)|x); - - return 0; -} - -VGAdev vgact65545dev = { - "ct65540", /* BUG: really 65545 */ - - 0, - 0, - ct65545page, - 0, -}; - -VGAcur vgact65545cur = { - "ct65545hwgc", - - ct65545enable, - ct65545disable, - ct65545load, - ct65545move, -}; diff --git a/os/pc/vgacyber938x.c b/os/pc/vgacyber938x.c deleted file mode 100644 index 7c86679c..00000000 --- a/os/pc/vgacyber938x.c +++ /dev/null @@ -1,225 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -enum { - CursorON = 0xC8, - CursorOFF = 0x00, -}; - -static int -cyber938xpageset(VGAscr*, int page) -{ - int opage; - - opage = inb(0x3D8); - - outb(0x3D8, page); - outb(0x3D9, page); - - return opage; -} - -static void -cyber938xpage(VGAscr* scr, int page) -{ - lock(&scr->devlock); - cyber938xpageset(scr, page); - unlock(&scr->devlock); -} - -static ulong -cyber938xlinear(VGAscr* scr, int* size, int* align) -{ - ulong aperture, oaperture; - int oapsize, wasupamem; - int osize; - Pcidev *p; - - osize = *size; - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - if(wasupamem) - upafree(oaperture, oapsize); - scr->isupamem = 0; - scr->mmio = 0; - - if(p = pcimatch(nil, 0x1023, 0)){ - aperture = p->mem[0].bar & ~0x0F; - *size = p->mem[0].size; - /* - * Heuristic to detect the MMIO space. We're flying blind - * here, with only the XFree86 source to guide us. - */ - if(p->mem[1].size == 0x20000) - scr->mmio = (ulong*)(p->mem[1].bar & ~0x0F); - } - else - aperture = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)) - scr->isupamem = 1; - } - else - scr->isupamem = 1; - - if(aperture) - addvgaseg("cyber938xscreen", aperture, osize); - if(scr->mmio) - addvgaseg("cyber938xmmio", (ulong)scr->mmio, 0x20000); - - return aperture; -} - -static void -cyber938xcurdisable(VGAscr*) -{ - vgaxo(Crtx, 0x50, CursorOFF); -} - -static void -cyber938xcurload(VGAscr* scr, Cursor* curs) -{ - uchar *p; - int islinear, opage, y; - - cyber938xcurdisable(scr); - - opage = 0; - p = KADDR(scr->aperture); - islinear = vgaxi(Crtx, 0x21) & 0x20; - if(!islinear){ - lock(&scr->devlock); - opage = cyber938xpageset(scr, scr->storage>>16); - p += (scr->storage & 0xFFFF); - } - else - p += scr->storage; - - for(y = 0; y < 16; y++){ - *p++ = curs->set[2*y]|curs->clr[2*y]; - *p++ = curs->set[2*y + 1]|curs->clr[2*y + 1]; - *p++ = 0x00; - *p++ = 0x00; - *p++ = curs->set[2*y]; - *p++ = curs->set[2*y + 1]; - *p++ = 0x00; - *p++ = 0x00; - } - memset(p, 0, (32-y)*8); - - if(!islinear){ - cyber938xpageset(scr, opage); - unlock(&scr->devlock); - } - - /* - * Save the cursor hotpoint and enable the cursor. - */ - scr->offset = curs->offset; - vgaxo(Crtx, 0x50, CursorON); -} - -static int -cyber938xcurmove(VGAscr* scr, Point p) -{ - int x, xo, y, yo; - - /* - * Mustn't position the cursor offscreen even partially, - * or it might disappear. Therefore, if x or y is -ve, adjust the - * cursor origins instead. - */ - if((x = p.x+scr->offset.x) < 0){ - xo = -x; - x = 0; - } - else - xo = 0; - if((y = p.y+scr->offset.y) < 0){ - yo = -y; - y = 0; - } - else - yo = 0; - - /* - * Load the new values. - */ - vgaxo(Crtx, 0x46, xo); - vgaxo(Crtx, 0x47, yo); - vgaxo(Crtx, 0x40, x & 0xFF); - vgaxo(Crtx, 0x41, (x>>8) & 0xFF); - vgaxo(Crtx, 0x42, y & 0xFF); - vgaxo(Crtx, 0x43, (y>>8) & 0xFF); - - return 0; -} - -static void -cyber938xcurenable(VGAscr* scr) -{ - int i; - ulong storage; - - cyber938xcurdisable(scr); - - /* - * Cursor colours. - */ - for(i = 0x48; i < 0x4C; i++) - vgaxo(Crtx, i, 0x00); - for(i = 0x4C; i < 0x50; i++) - vgaxo(Crtx, i, 0xFF); - - /* - * Find a place for the cursor data in display memory. - */ - storage = ((scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024); - vgaxo(Crtx, 0x44, storage & 0xFF); - vgaxo(Crtx, 0x45, (storage>>8) & 0xFF); - storage *= 1024; - scr->storage = storage; - - /* - * Load, locate and enable the 32x32 cursor. - * (64x64 is bit 0, X11 format is bit 6 and cursor - * enable is bit 7). Bit 3 needs to be set on 9382 - * chips otherwise even the white bits are black. - */ - cyber938xcurload(scr, &arrow); - cyber938xcurmove(scr, ZP); - vgaxo(Crtx, 0x50, CursorON); -} - -VGAdev vgacyber938xdev = { - "cyber938x", - - nil, /* enable */ - nil, /* disable */ - cyber938xpage, /* page */ - cyber938xlinear, /* linear */ - nil, /* drawinit */ -}; - -VGAcur vgacyber938xcur = { - "cyber938xhwgc", - - cyber938xcurenable, /* enable */ - cyber938xcurdisable, /* disable */ - cyber938xcurload, /* load */ - cyber938xcurmove, /* move */ -}; diff --git a/os/pc/vgaet4000.c b/os/pc/vgaet4000.c deleted file mode 100644 index f3ede446..00000000 --- a/os/pc/vgaet4000.c +++ /dev/null @@ -1,270 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -static void -setet4000page(int page) -{ - uchar p; - - p = page & 0x0F; - p |= p<<4; - outb(0x3CD, p); - - p = (page & 0x30); - p |= p>>4; - outb(0x3CB, p); -} - -static void -et4000page(VGAscr *scr, int page) -{ - lock(&scr->devlock); - setet4000page(page); - unlock(&scr->devlock); -} - -static void -et4000disable(VGAscr*) -{ - uchar imaF7; - - outb(0x217A, 0xF7); - imaF7 = inb(0x217B) & ~0x80; - outb(0x217B, imaF7); -} - -static void -et4000enable(VGAscr *scr) -{ - uchar imaF7; - - et4000disable(scr); - - /* - * Configure CRTCB for Sprite, 64x64, - * CRTC pixel overlay. - */ - outb(0x217A, 0xEF); - outb(0x217B, 0x02); - - /* - * Cursor goes in the top left corner - * of the Sprite area, so the horizontal and - * vertical presets are 0. - */ - outb(0x217A, 0xE2); - outb(0x217B, 0x00); - outb(0x217A, 0xE3); - outb(0x217B, 0x00); - - outb(0x217A, 0xE6); - outb(0x217B, 0x00); - outb(0x217A, 0xE7); - outb(0x217B, 0x00); - - /* - * Find a place for the cursor data in display memory. - * Must be on a "doubleword" boundary, but put it on a - * 1024-byte boundary so that there's no danger of it - * crossing a page. - */ - scr->storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024; - scr->storage *= 1024/4; - outb(0x217A, 0xE8); - outb(0x217B, scr->storage & 0xFF); - outb(0x217A, 0xE9); - outb(0x217B, (scr->storage>>8) & 0xFF); - outb(0x217A, 0xEA); - outb(0x217B, (scr->storage>>16) & 0x0F); - scr->storage *= 4; - - /* - * Row offset in "quadwords". Must be 2 for Sprite. - * Bag the pixel-panning. - * Colour depth, must be 2 for Sprite. - */ - outb(0x217A, 0xEB); - outb(0x217B, 0x02); - outb(0x217A, 0xEC); - outb(0x217B, 0x00); - - outb(0x217A, 0xED); - outb(0x217B, 0x00); - - outb(0x217A, 0xEE); -// if(vgascreen.ldepth == 3) - outb(0x217B, 0x01); -// else -// outb(0x217B, 0x00); - - /* - * Enable the CRTCB/Sprite. - */ - outb(0x217A, 0xF7); - imaF7 = inb(0x217B); - outb(0x217B, 0x80|imaF7); -} - -static void -et4000load(VGAscr *scr, Cursor *c) -{ - uchar p0, p1, *mem; - int i, x, y; - ushort p; - uchar clr[2*16], set[2*16]; - - /* - * Lock the display memory so we can update the - * cursor bitmap if necessary. - */ - lock(&scr->devlock); - - /* - * Disable the cursor. - * Set the display page (do we need to restore - * the current contents when done?) and the - * pointer to the two planes. What if this crosses - * into a new page? - */ - et4000disable(scr); - - setet4000page(scr->storage>>16); - mem = (uchar*)KADDR(scr->aperture) + (scr->storage & 0xFFFF); - - /* - * Initialise the 64x64 cursor RAM array. There are 2 planes, - * p0 and p1. Data is written 4 pixels per byte, with p1 the - * MS bit of each pixel. - * The cursor mode gives the following truth table: - * p1 p0 colour - * 0 0 Sprite Colour 0 (defined as 0x00) - * 0 1 Sprite Colour 1 (defined as 0xFF) - * 1 0 Transparent (allow CRTC pixel pass through) - * 1 1 Invert (allow CRTC pixel invert through) - * Put the cursor into the top-left of the 64x64 array. - * - * This is almost certainly wrong, since it has not - * been updated for the 3rd edition color values. - */ - memmove(clr, c->clr, sizeof(clr)); -// pixreverse(clr, sizeof(clr), 0); - memmove(set, c->set, sizeof(set)); -// pixreverse(set, sizeof(set), 0); - for(y = 0; y < 64; y++){ - for(x = 0; x < 64/8; x++){ - if(x < 16/8 && y < 16){ - p0 = clr[x+y*2]; - p1 = set[x+y*2]; - - p = 0x0000; - for(i = 0; i < 8; i++){ - if(p1 & (1<<(7-i))){ - /* nothing to do */ - } - else if(p0 & (1<<(7-i))) - p |= 0x01<<(2*i); - else - p |= 0x02<<(2*i); - } - *mem++ = p & 0xFF; - *mem++ = (p>>8) & 0xFF; - } - else { - *mem++ = 0xAA; - *mem++ = 0xAA; - } - } - } - - /* - * enable the cursor. - */ - outb(0x217A, 0xF7); - p = inb(0x217B)|0x80; - outb(0x217B, p); - - unlock(&scr->devlock); -} - -static int -et4000move(VGAscr *scr, Point p) -{ - int x, xo, y, yo; - - if(canlock(&scr->devlock) == 0) - return 1; - - /* - * Mustn't position the cursor offscreen even partially, - * or it disappears. Therefore, if x or y is -ve, adjust the - * cursor presets instead. - */ - if((x = p.x+scr->offset.x) < 0){ - xo = -x; - x = 0; - } - else - xo = 0; - if((y = p.y+scr->offset.y) < 0){ - yo = -y; - y = 0; - } - else - yo = 0; - - /* - * The cursor image is jerky if we don't do this. - * The cursor information is probably fetched from - * display memory during the horizontal blank active - * time and it doesn't like it if the coordinates - * are changed underneath. - */ - while((vgai(Status1) & 0x08) == 0) - ; - - outb(0x217A, 0xE2); - outb(0x217B, xo); - - outb(0x217A, 0xE6); - outb(0x217B, yo); - - outb(0x217A, 0xE1); - outb(0x217B, (x>>8) & 0xFF); - outb(0x217A, 0xE0); - outb(0x217B, x & 0xFF); - outb(0x217A, 0xE5); - outb(0x217B, (y>>8) & 0xFF); - outb(0x217A, 0xE4); - outb(0x217B, y & 0xFF); - - unlock(&scr->devlock); - return 0; -} - -VGAcur vgaet4000cur = { - "et4000hwgc", - - et4000enable, - et4000disable, - et4000load, - et4000move, -}; - -VGAdev vgaet4000dev = { - "et4000", - - 0, - 0, - et4000page, - 0 -}; diff --git a/os/pc/vgahiqvideo.c b/os/pc/vgahiqvideo.c deleted file mode 100644 index 6ae02b04..00000000 --- a/os/pc/vgahiqvideo.c +++ /dev/null @@ -1,274 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -enum { - Xrx = 0x3D6, /* Configuration Extensions Index */ -}; - -static uchar -hiqvideoxi(long port, uchar index) -{ - uchar data; - - outb(port, index); - data = inb(port+1); - - return data; -} - -static void -hiqvideoxo(long port, uchar index, uchar data) -{ - outb(port, index); - outb(port+1, data); -} - -static ulong -hiqvideolinear(VGAscr* scr, int* size, int* align) -{ - ulong aperture, oaperture; - int oapsize, wasupamem; - Pcidev *p; - - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - - aperture = 0; - if(p = pcimatch(nil, 0x102C, 0)){ - switch(p->did){ - case 0x00C0: /* 69000 HiQVideo */ - case 0x00E0: /* 65550 HiQV32 */ - case 0x00E4: /* 65554 HiQV32 */ - case 0x00E5: /* 65555 HiQV32 */ - aperture = p->mem[0].bar & ~0x0F; - *size = p->mem[0].size; - break; - default: - break; - } - } - - if(wasupamem){ - if(oaperture == aperture) - return oaperture; - upafree(oaperture, oapsize); - } - scr->isupamem = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)){ - aperture = oaperture; - scr->isupamem = 1; - } - else - scr->isupamem = 0; - } - else - scr->isupamem = 1; - - return aperture; -} - -static void -hiqvideoenable(VGAscr* scr) -{ - Pcidev *p; - int align, size, vmsize; - ulong aperture; - - /* - * Only once, can't be disabled for now. - */ - if(scr->io) - return; - if(p = pcimatch(nil, 0x102C, 0)){ - switch(p->did){ - case 0x00C0: /* 69000 HiQVideo */ - vmsize = 2*1024*1024; - break; - case 0x00E0: /* 65550 HiQV32 */ - case 0x00E4: /* 65554 HiQV32 */ - case 0x00E5: /* 65555 HiQV32 */ - switch((hiqvideoxi(Xrx, 0x43)>>1) & 0x03){ - default: - case 0: - vmsize = 1*1024*1024; - break; - case 1: - vmsize = 2*1024*1024; - break; - } - break; - default: - return; - } - } - else - return; - - size = p->mem[0].size; - align = 0; - aperture = hiqvideolinear(scr, &size, &align); - if(aperture) { - scr->aperture = aperture; - scr->apsize = size; - addvgaseg("hiqvideoscreen", aperture, size); - } - - /* - * Find a place for the cursor data in display memory. - * Must be on a 4096-byte boundary. - * scr->io holds the physical address of the cursor - * storage area in the framebuffer region. - */ - scr->storage = vmsize-4096; - scr->io = scr->aperture+scr->storage; -} - -static void -hiqvideocurdisable(VGAscr*) -{ - hiqvideoxo(Xrx, 0xA0, 0x10); -} - -static void -hiqvideocurload(VGAscr* scr, Cursor* curs) -{ - uchar *p; - int x, y; - - /* - * Disable the cursor. - */ - hiqvideocurdisable(scr); - - if(scr->io == 0) - return; - p = KADDR(scr->io); - - for(y = 0; y < 16; y += 2){ - *p++ = ~(curs->clr[2*y]|curs->set[2*y]); - *p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]); - *p++ = 0xFF; - *p++ = 0xFF; - *p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]); - *p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]); - *p++ = 0xFF; - *p++ = 0xFF; - *p++ = curs->set[2*y]; - *p++ = curs->set[2*y+1]; - *p++ = 0x00; - *p++ = 0x00; - *p++ = curs->set[2*y+2]; - *p++ = curs->set[2*y+3]; - *p++ = 0x00; - *p++ = 0x00; - } - while(y < 32){ - for(x = 0; x < 64; x += 8) - *p++ = 0xFF; - for(x = 0; x < 64; x += 8) - *p++ = 0x00; - y += 2; - } - - /* - * Save the cursor hotpoint and enable the cursor. - */ - scr->offset = curs->offset; - hiqvideoxo(Xrx, 0xA0, 0x11); -} - -static int -hiqvideocurmove(VGAscr* scr, Point p) -{ - int x, y; - - if(scr->io == 0) - return 1; - - if((x = p.x+scr->offset.x) < 0) - x = 0x8000|(-x & 0x07FF); - if((y = p.y+scr->offset.y) < 0) - y = 0x8000|(-y & 0x07FF); - - hiqvideoxo(Xrx, 0xA4, x & 0xFF); - hiqvideoxo(Xrx, 0xA5, (x>>8) & 0xFF); - hiqvideoxo(Xrx, 0xA6, y & 0xFF); - hiqvideoxo(Xrx, 0xA7, (y>>8) & 0xFF); - - return 0; -} - -static void -hiqvideocurenable(VGAscr* scr) -{ - uchar xr80; - - hiqvideoenable(scr); - if(scr->io == 0) - return; - - /* - * Disable the cursor. - */ - hiqvideocurdisable(scr); - - /* - * Cursor colours. - * Can't call setcolor here as cursor is already locked. - * When done make sure the cursor enable in Xr80 is set. - */ - xr80 = hiqvideoxi(Xrx, 0x80); - hiqvideoxo(Xrx, 0x80, xr80|0x01); - vgao(PaddrW, 0x04); - vgao(Pdata, Pwhite); - vgao(Pdata, Pwhite); - vgao(Pdata, Pwhite); - vgao(Pdata, Pblack); - vgao(Pdata, Pblack); - vgao(Pdata, Pblack); - hiqvideoxo(Xrx, 0x80, xr80|0x10); - - hiqvideoxo(Xrx, 0xA2, (scr->storage>>12)<<4); - hiqvideoxo(Xrx, 0xA3, (scr->storage>>16) & 0x3F); - - /* - * Load, locate and enable the 32x32 cursor. - * Cursor enable in Xr80 better be set already. - */ - hiqvideocurload(scr, &arrow); - hiqvideocurmove(scr, ZP); - hiqvideoxo(Xrx, 0xA0, 0x11); -} - -VGAdev vgahiqvideodev = { - "hiqvideo", - - hiqvideoenable, /* enable */ - nil, /* disable */ - nil, /* page */ - hiqvideolinear, /* linear */ -}; - -VGAcur vgahiqvideocur = { - "hiqvideohwgc", - - hiqvideocurenable, /* enable */ - hiqvideocurdisable, /* disable */ - hiqvideocurload, /* load */ - hiqvideocurmove, /* move */ -}; diff --git a/os/pc/vgai81x.c b/os/pc/vgai81x.c deleted file mode 100644 index ac840fe6..00000000 --- a/os/pc/vgai81x.c +++ /dev/null @@ -1,282 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -typedef struct -{ - ushort ctl; - ushort pad; - ulong base; - ulong pos; -} CursorI81x; - -enum { - Fbsize = 8*MB, - - hwCur = 0x70080, -}; - -static Pcidev * -i81xpcimatch(void) -{ - Pcidev *p; - - p = nil; - while((p = pcimatch(p, 0x8086, 0)) != nil){ - switch(p->did){ - default: - continue; - case 0x7121: - case 0x7123: - case 0x7125: - case 0x1102: - case 0x1112: - case 0x1132: - case 0x3577: /* IBM R31 uses intel 830M chipset */ - return p; - } - } - return nil; -} - -static ulong -i81xlinear(VGAscr* scr, int* size, int* align) -{ - Pcidev *p; - int oapsize, wasupamem; - ulong aperture, oaperture, fbuf, fbend, *rp; - - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - - aperture = 0; - p = i81xpcimatch(); - if(p != nil) { - aperture = p->mem[0].bar & ~0x0F; - *size = p->mem[0].size; - if(*size > Fbsize) - *size = Fbsize; - } - - if(wasupamem){ - if(oaperture == aperture) - return oaperture; - upafree(oaperture, oapsize); - } - scr->isupamem = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)){ - aperture = oaperture; - scr->isupamem = 1; - } - else - scr->isupamem = 0; - } - else - scr->isupamem = 1; - - /* allocate space for frame buffer, populate page table */ - if(oapsize == 0) { - fbuf = PADDR(xspanalloc(*size, BY2PG, 0)); - fbend = PGROUND(fbuf+*size); - rp = KADDR(scr->io+0x10000); - while(fbuf < fbend) { - *rp++ = fbuf | (1<<0); - fbuf += BY2PG; - } - } - return aperture; -} - -static void -i81xenable(VGAscr* scr) -{ - Pcidev *p; - int align, size; - Mach *mach0; - ulong aperture, pgtbl, *rp, cursor, *pte; - - /* - * Only once, can't be disabled for now. - * scr->io holds the physical address of - * the MMIO registers. - */ - if(scr->io) - return; - p = i81xpcimatch(); - if(p == nil) - return; - scr->io = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0); - if(scr->io == 0) - return; - - /* allocate page table */ - pgtbl = PADDR(xspanalloc(64*1024, BY2PG, 0)); - rp = KADDR(scr->io+0x2020); - *rp = pgtbl | 1; - - addvgaseg("i81xmmio", (ulong)scr->io, p->mem[0].size); - - size = p->mem[0].size; - align = 0; - aperture = i81xlinear(scr, &size, &align); - if(aperture){ - scr->aperture = aperture; - scr->apsize = size; - addvgaseg("i81xscreen", aperture, size); - } - - /* - * allocate space for the cursor data in system memory. - * must be uncached. - */ - cursor = (ulong)xspanalloc(BY2PG, BY2PG, 0); - mach0 = MACHP(0); - pte = mmuwalk(mach0->pdb, cursor, 2, 0); - if(pte == nil) - panic("i81x cursor"); - *pte |= PTEUNCACHED; - scr->storage = PADDR(cursor); -} - -static void -i81xcurdisable(VGAscr* scr) -{ - CursorI81x *hwcurs; - - if(scr->io == 0) - return; - hwcurs = KADDR(scr->io+hwCur); - hwcurs->ctl = (1<<4); -} - -static void -i81xcurload(VGAscr* scr, Cursor* curs) -{ - int y; - uchar *p; - CursorI81x *hwcurs; - - if(scr->io == 0) - return; - hwcurs = KADDR(scr->io+hwCur); - - /* - * Disable the cursor then load the new image in - * the top-left of the 32x32 array. - * Unused portions of the image have been initialised to be - * transparent. - */ - hwcurs->ctl = (1<<4); - p = KADDR(scr->storage); - for(y = 0; y < 16; y += 2) { - *p++ = ~(curs->clr[2*y]|curs->set[2*y]); - *p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]); - p += 2; - *p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]); - *p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]); - p += 2; - *p++ = curs->set[2*y]; - *p++ = curs->set[2*y+1]; - p += 2; - *p++ = curs->set[2*y+2]; - *p++ = curs->set[2*y+3]; - p += 2; - } - - /* - * Save the cursor hotpoint and enable the cursor. - * The 0,0 cursor point is top-left. - */ - scr->offset.x = curs->offset.x; - scr->offset.y = curs->offset.y; - hwcurs->ctl = (1<<4)|1; -} - -static int -i81xcurmove(VGAscr* scr, Point p) -{ - int x, y; - ulong pos; - CursorI81x *hwcurs; - - if(scr->io == 0) - return 1; - hwcurs = KADDR(scr->io+hwCur); - - x = p.x+scr->offset.x; - y = p.y+scr->offset.y; - pos = 0; - if(x < 0) { - pos |= (1<<15); - x = -x; - } - if(y < 0) { - pos |= (1<<31); - y = -y; - } - pos |= ((y&0x7ff)<<16)|(x&0x7ff); - hwcurs->pos = pos; - - return 0; -} - -static void -i81xcurenable(VGAscr* scr) -{ - int i; - uchar *p; - CursorI81x *hwcurs; - - i81xenable(scr); - if(scr->io == 0) - return; - hwcurs = KADDR(scr->io+hwCur); - - /* - * Initialise the 32x32 cursor to be transparent in 2bpp mode. - */ - hwcurs->base = scr->storage; - p = KADDR(scr->storage); - for(i = 0; i < 32/2; i++) { - memset(p, 0xff, 8); - memset(p+8, 0, 8); - p += 16; - } - /* - * Load, locate and enable the 32x32 cursor in 2bpp mode. - */ - i81xcurload(scr, &arrow); - i81xcurmove(scr, ZP); -} - -VGAdev vgai81xdev = { - "i81x", - - i81xenable, - nil, - nil, - i81xlinear, -}; - -VGAcur vgai81xcur = { - "i81xhwgc", - - i81xcurenable, - i81xcurdisable, - i81xcurload, - i81xcurmove, -}; diff --git a/os/pc/vgamach64xx.c b/os/pc/vgamach64xx.c deleted file mode 100644 index 322c449c..00000000 --- a/os/pc/vgamach64xx.c +++ /dev/null @@ -1,1250 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -char Eunsupportedformat[] = "unsupported video format"; -char Enotconfigured[] = "device not configured"; - -#define SCALE_ZERO_EXTEND 0x0 -#define SCALE_DYNAMIC 0x1 -#define SCALE_RED_TEMP_6500K 0x0 -#define SCALE_RED_TEMP_9800K 0x2 -#define SCALE_HORZ_BLEND 0x0 -#define SCALE_HORZ_REP 0x4 -#define SCALE_VERT_BLEND 0x0 -#define SCALE_VERT_REP 0x8 -#define SCALE_BANDWIDTH_NORMAL 0x0 -#define SCALE_BANDWIDTH_EXCEEDED 0x4000000 -#define SCALE_BANDWIDTH_RESET 0x4000000 -#define SCALE_CLK_ACTIVITY 0x0 -#define SCALE_CLK_CONTINUOUS 0x20000000 -#define OVERLAY_DISABLE 0x0 -#define OVERLAY_ENABLE 0x40000000 -#define SCALE_DISABLE 0x0 -#define SCALE_ENABLE 0x80000000 - -#define SCALER_FRAME_READ_MODE_FULL 0x0 -#define SCALER_BUF_MODE_SINGLE 0x0 -#define SCALER_BUF_MODE_DOUBLE 0x40000 -#define SCALER_BUF_NEXT_0 0x0 -#define SCALER_BUF_NEXT_1 0x80000 -#define SCALER_BUF_STATUS_0 0x0 -#define SCALER_BUF_STATUS_1 0x100000 - -#define OVERLAY_MIX_G_CMP 0x0 -#define OVERLAY_MIX_ALWAYS_G 0x100 -#define OVERLAY_MIX_ALWAYS_V 0x200 -#define OVERLAY_MIX_NOT_G 0x300 -#define OVERLAY_MIX_NOT_V 0x400 -#define OVERLAY_MIX_G_XOR_V 0x500 -#define OVERLAY_MIX_NOT_G_XOR_V 0x600 -#define OVERLAY_MIX_V_CMP 0x700 -#define OVERLAY_MIX_NOT_G_OR_NOT_V 0x800 -#define OVERLAY_MIX_G_OR_NOT_V 0x900 -#define OVERLAY_MIX_NOT_G_OR_V 0xA00 -#define OVERLAY_MIX_G_OR_V 0xB00 -#define OVERLAY_MIX_G_AND_V 0xC00 -#define OVERLAY_MIX_NOT_G_AND_V 0xD00 -#define OVERLAY_MIX_G_AND_NOT_V 0xE00 -#define OVERLAY_MIX_NOT_G_AND_NOT_V 0xF00 -#define OVERLAY_EXCLUSIVE_NORMAL 0x0 -#define OVERLAY_EXCLUSIVE_V_ONLY 0x80000000 - -#define VIDEO_IN_8BPP 0x2 -#define VIDEO_IN_16BPP 0x4 -#define VIDEO_IN_32BPP 0x6 -#define VIDEO_IN_VYUY422 0xB /*16 bpp */ -#define VIDEO_IN_YVYU422 0xC /* 16 bpp */ -#define SCALE_IN_15BPP 0x30000 /* aRGB 1555 */ -#define SCALE_IN_16BPP 0x40000 /* RGB 565 */ -#define SCALE_IN_32BPP 0x60000 /* aRGB 8888 */ -#define SCALE_IN_YUV9 0x90000 /* planar */ -#define SCALE_IN_YUV12 0xA0000 /* planar */ -#define SCALE_IN_VYUY422 0xB0000 /* 16 bpp */ -#define SCALE_IN_YVYU422 0xC0000 /* 16 bpp */ -#define HOST_YUV_APERTURE_UPPER 0x0 -#define HOST_YUV_APERTURE_LOWER 0x20000000 -#define HOST_MEM_MODE_Y 0x40000000 -#define HOST_MEM_MODE_U 0x80000000 -#define HOST_MEM_MODE_V 0xC0000000 -#define HOST_MEM_MODE_NORMAL HOST_YUV_APERTURE_UPPER - -static Chan *ovl_chan; /* Channel of controlling process */ -static int ovl_width; /* Width of input overlay buffer */ -static int ovl_height; /* Height of input overlay buffer */ -static int ovl_format; /* Overlay format */ -static ulong ovl_fib; /* Frame in bytes */ - -enum { - VTGTB1S1 = 0x01, // Asic description for VTB1S1 and GTB1S1. - VT4GTIIC = 0x3A, // asic descr for VT4 and RAGE IIC - GTB1U1 = 0x19, // Asic description for GTB1U1. - GTB1S2 = 0x41, // Asic description for GTB1S2. - GTB2U1 = 0x1A, - GTB2U2 = 0x5A, - GTB2U3 = 0x9A, - GTIIIC1U1 = 0x1B, // 3D RAGE PRO asic descrp. - GTIIIC1U2 = 0x5B, // 3D RAGE PRO asic descrp. - GTIIIC2U1 = 0x1C, // 3D RAGE PRO asic descrp. - GTIIIC2U2 = 0x5C, // 3D RAGE PRO asic descrp. - GTIIIC2U3 = 0x7C, // 3D RAGE PRO asic descrp. - GTBC = 0x3A, // 3D RAGE IIC asic descrp. - LTPRO = 0x9C, // 3D RAGE LT PRO -}; - -/* - * ATI Mach64(CT|ET|G*|V*|L*). - */ -typedef struct Mach64types Mach64types; -struct Mach64types { - ushort m64_id; /* Chip ID */ - int m64_vtgt; /* Is this a VT or GT chipset? */ - ulong m64_ovlclock; /* Max. overlay clock frequency */ - int m64_pro; /* Is this a PRO? */ -}; - -static ulong mach64refclock; -static Mach64types *mach64type; -static int mach64revb; /* Revision B or greater? */ -static ulong mach64overlay; /* Overlay buffer */ - -static Mach64types mach64s[] = { - ('C'<<8)|'T', 0, 1350000, /*?*/ 0, /* 4354: CT */ - ('E'<<8)|'T', 0, 1350000, /*?*/ 0, /* 4554: ET */ - ('G'<<8)|'B', 1, 1250000, 1, /* 4742: 264GT PRO */ - ('G'<<8)|'D', 1, 1250000, 1, /* 4744: 264GT PRO */ - ('G'<<8)|'I', 1, 1250000, 1, /* 4749: 264GT PRO */ - ('G'<<8)|'M', 0, 1350000, 0, /* 474D: Rage XL */ - ('G'<<8)|'P', 1, 1250000, 1, /* 4750: 264GT PRO */ - ('G'<<8)|'Q', 1, 1250000, 1, /* 4751: 264GT PRO */ - ('G'<<8)|'R', 1, 1250000, 1, /* 4752: */ - ('G'<<8)|'T', 1, 800000, 0, /* 4754: 264GT[B] */ - ('G'<<8)|'U', 1, 1000000, 0, /* 4755: 264GT DVD */ - ('G'<<8)|'V', 1, 1000000, 0, /* 4756: Rage2C */ - ('G'<<8)|'Z', 1, 1000000, 0, /* 475A: Rage2C */ - ('V'<<8)|'T', 1, 800000, 0, /* 5654: 264VT/GT/VTB */ - ('V'<<8)|'U', 1, 800000, 0, /* 5655: 264VT3 */ - ('V'<<8)|'V', 1, 1000000, 0, /* 5656: 264VT4 */ - ('L'<<8)|'B', 0, 1350000, 1, /* 4C42: Rage LTPro AGP */ - ('L'<<8)|'I', 0, 1350000, 0, /* 4C49: Rage LTPro AGP */ - ('L'<<8)|'M', 0, 1350000, 0, /* 4C4D: Rage Mobility */ - ('L'<<8)|'P', 0, 1350000, 1, /* 4C50: 264LT PRO */ -}; - - -static int hwfill(VGAscr*, Rectangle, ulong); -static int hwscroll(VGAscr*, Rectangle, Rectangle); -static void initengine(VGAscr*); - -static Pcidev* -mach64xxpci(void) -{ - Pcidev *p; - int i; - - if((p = pcimatch(nil, 0x1002, 0)) == nil) - return nil; - - for (i = 0; i != nelem(mach64s); i++) - if (mach64s[i].m64_id == p->did) { - mach64type = &mach64s[i]; - return p; - } - return nil; -} - -static void -mach64xxenable(VGAscr* scr) -{ - Pcidev *p; - - /* - * Only once, can't be disabled for now. - */ - if(scr->io) - return; - if(p = mach64xxpci()){ - scr->id = p->did; - - /* - * The CT doesn't always have the I/O base address - * in the PCI base registers. There is a way to find - * it via the vendor-specific PCI config space but - * this will do for now. - */ - scr->io = p->mem[1].bar & ~0x03; - - if(scr->io == 0) - scr->io = 0x2EC; - } -} - -static ulong -mach64xxlinear(VGAscr* scr, int* size, int* align) -{ - ulong aperture, osize, oaperture; - int i, oapsize, wasupamem; - Pcidev *p; - - osize = *size; - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - - if(p = mach64xxpci()){ - for(i=0; imem); i++){ - if(p->mem[i].size >= *size - && ((p->mem[i].bar & ~0x0F) & (*align-1)) == 0) - break; - } - if(i >= nelem(p->mem)){ - print("vgamach64xx: aperture not found\n"); - return 0; - } - aperture = p->mem[i].bar & ~0x0F; - *size = p->mem[i].size; - } - else - aperture = 0; - - if(wasupamem) - upafree(oaperture, oapsize); - scr->isupamem = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)) - scr->isupamem = 1; - } - else - scr->isupamem = 1; - - scr->mmio = KADDR(aperture+osize-0x400); - if(oaperture && oaperture != aperture) - print("warning (BUG): redefinition of aperture does not change mach64mmio segment\n"); - addvgaseg("mach64mmio", aperture+osize-BY2PG, BY2PG); - addvgaseg("mach64screen", aperture, osize); - - return aperture; -} - -enum { - CrtcOffPitch = 0x05, - CrtcGenCtl = 0x07, - CurClr0 = 0x0B, /* I/O Select */ - CurClr1 = 0x0C, - CurOffset = 0x0D, - CurHVposn = 0x0E, - CurHVoff = 0x0F, - BusCntl = 0x13, - GenTestCntl = 0x19, - - CrtcHsyncDis = 0x04, - CrtcVsyncDis = 0x08, - - ContextMask = 0x100, /* not accessible via I/O */ - FifoStat, - GuiStat, - DpFrgdClr, - DpBkgdClr, - DpWriteMask, - DpMix, - DpPixWidth, - DpSrc, - ClrCmpCntl, - GuiTrajCntl, - ScLeftRight, - ScTopBottom, - DstOffPitch, - DstYX, - DstHeightWidth, - DstCntl, - DstHeight, - DstBresErr, - DstBresInc, - DstBresDec, - SrcCntl, - SrcHeight1Width1, - SrcHeight2Width2, - SrcYX, - SrcWidth1, - SrcYXstart, - HostCntl, - PatReg0, - PatReg1, - PatCntl, - ScBottom, - ScLeft, - ScRight, - ScTop, - ClrCmpClr, - ClrCmpMask, - DpChainMask, - SrcOffPitch, - LcdIndex, - LcdData, - ClockCntl, - OverlayScaleCntl, - ConfigChipId, - Buf0Pitch, - ScalerBuf0Pitch, - CaptureConfig, - OverlayKeyCntl, - ScalerColourCntl, - ScalerHCoef0, - ScalerHCoef1, - ScalerHCoef2, - ScalerHCoef3, - ScalerHCoef4, - VideoFormat, - Buf0Offset, - ScalerBuf0Offset, - CrtcGenCntl, - OverlayScaleInc, - OverlayYX, - OverlayYXEnd, - ScalerHeightWidth, - HTotalDisp, - VTotalDisp, -}; - -enum { - LCD_ConfigPanel = 0, - LCD_GenCtrl, - LCD_DstnCntl, - LCD_HfbPitchAddr, - LCD_HorzStretch, - LCD_VertStretch, - LCD_ExtVertStretch, - LCD_LtGio, - LCD_PowerMngmnt, - LCD_ZvgPio, - Nlcd, -}; - -#define Bank1 (-0x100) /* 1KB */ - -static int mmoffset[] = { - [HTotalDisp] 0x00, - [VTotalDisp] 0x02, - [CrtcOffPitch] 0x05, - [CrtcGenCntl] 0x07, - [CurClr0] 0x18, - [CurClr1] 0x19, - [CurOffset] 0x1A, - [CurHVposn] 0x1B, - [CurHVoff] 0x1C, - [ClockCntl] 0x24, - [BusCntl] 0x28, - [LcdIndex] 0x29, - [LcdData] 0x2A, - [GenTestCntl] 0x34, - [ConfigChipId] 0x38, - [DstOffPitch] 0x40, - [DstYX] 0x43, - [DstHeight] 0x45, - [DstHeightWidth] 0x46, - [DstBresErr] 0x49, - [DstBresInc] 0x4A, - [DstBresDec] 0x4B, - [DstCntl] 0x4C, - [SrcOffPitch] 0x60, - [SrcYX] 0x63, - [SrcWidth1] 0x64, - [SrcYXstart] 0x69, - [SrcHeight1Width1] 0x66, - [SrcHeight2Width2] 0x6C, - [SrcCntl] 0x6D, - [HostCntl] 0x90, - [PatReg0] 0xA0, - [PatReg1] 0xA1, - [PatCntl] 0xA2, - [ScLeft] 0xA8, - [ScRight] 0xA9, - [ScLeftRight] 0xAA, - [ScTop] 0xAB, - [ScBottom] 0xAC, - [ScTopBottom] 0xAD, - [DpBkgdClr] 0xB0, - [DpFrgdClr] 0xB1, - [DpWriteMask] 0xB2, - [DpChainMask] 0xB3, - [DpPixWidth] 0xB4, - [DpMix] 0xB5, - [DpSrc] 0xB6, - [ClrCmpClr] 0xC0, - [ClrCmpMask] 0xC1, - [ClrCmpCntl] 0xC2, - [FifoStat] 0xC4, - [ContextMask] 0xC8, - [GuiTrajCntl] 0xCC, - [GuiStat] 0xCE, - - /* Bank1 */ - [OverlayYX] Bank1 + 0x00, - [OverlayYXEnd] Bank1 + 0x01, - [OverlayKeyCntl] Bank1 + 0x06, - [OverlayScaleInc] Bank1 + 0x08, - [OverlayScaleCntl] Bank1 + 0x09, - [ScalerHeightWidth] Bank1 + 0x0A, - [ScalerBuf0Offset] Bank1 + 0x0D, - [ScalerBuf0Pitch] Bank1 + 0x0F, - [VideoFormat] Bank1 + 0x12, - [CaptureConfig] Bank1 + 0x14, - [Buf0Offset] Bank1 + 0x20, - [Buf0Pitch] Bank1 + 0x23, - [ScalerColourCntl] Bank1 + 0x54, - [ScalerHCoef0] Bank1 + 0x55, - [ScalerHCoef1] Bank1 + 0x56, - [ScalerHCoef2] Bank1 + 0x57, - [ScalerHCoef3] Bank1 + 0x58, - [ScalerHCoef4] Bank1 + 0x59, -}; - -static ulong -ior32(VGAscr* scr, int r) -{ - if(scr->io == 0x2EC || scr->io == 0x1C8) - return inl((r<<10)+scr->io); - if(r >= 0x100 && scr->mmio != nil) - return scr->mmio[mmoffset[r]]; - return inl((mmoffset[r]<<2)+scr->io); -} - -static void -iow32(VGAscr* scr, int r, ulong l) -{ - if(scr->io == 0x2EC || scr->io == 0x1C8) - outl(((r)<<10)+scr->io, l); - else if(r >= 0x100 && scr->mmio != nil) - scr->mmio[mmoffset[r]] = l; - else - outl((mmoffset[r]<<2)+scr->io, l); -} - -static ulong -lcdr32(VGAscr *scr, ulong r) -{ - ulong or; - - or = ior32(scr, LcdIndex); - iow32(scr, LcdIndex, (or&~0x0F) | (r&0x0F)); - return ior32(scr, LcdData); -} - -static void -lcdw32(VGAscr *scr, ulong r, ulong v) -{ - ulong or; - - or = ior32(scr, LcdIndex); - iow32(scr, LcdIndex, (or&~0x0F) | (r&0x0F)); - iow32(scr, LcdData, v); -} - -static void -mach64xxcurdisable(VGAscr* scr) -{ - ulong r; - - r = ior32(scr, GenTestCntl); - iow32(scr, GenTestCntl, r & ~0x80); -} - -static void -mach64xxcurload(VGAscr* scr, Cursor* curs) -{ - uchar *p; - int i, y; - ulong c, s, m, r; - - /* - * Disable the cursor. - */ - r = ior32(scr, GenTestCntl); - iow32(scr, GenTestCntl, r & ~0x80); - - p = KADDR(scr->aperture); - p += scr->storage; - - /* - * Initialise the 64x64 cursor RAM array. - * The cursor mode gives the following truth table: - * p1 p0 colour - * 0 0 Cursor Colour 0 - * 0 1 Cursor Colour 1 - * 1 0 Transparent - * 1 1 Complement - * Put the cursor into the top-right of the 64x64 array. - */ - for(y = 0; y < 16; y++){ - for(i = 0; i < (64-16)/8; i++){ - *p++ = 0xAA; - *p++ = 0xAA; - } - - c = (curs->clr[2*y]<<8)|curs->clr[y*2 + 1]; - s = (curs->set[2*y]<<8)|curs->set[y*2 + 1]; - - m = 0x00000000; - for(i = 0; i < 16; i++){ - if(s & (1<<(15-i))) - m |= 0x01<<(2*i); - else if(c & (1<<(15-i))){ - /* nothing to do */ - } - else - m |= 0x02<<(2*i); - } - *p++ = m; - *p++ = m>>8; - *p++ = m>>16; - *p++ = m>>24; - } - memset(p, 0xAA, (64-16)*16); - - /* - * Set the cursor hotpoint and enable the cursor. - */ - scr->offset = curs->offset; - iow32(scr, GenTestCntl, 0x80|r); -} - -static int -ptalmostinrect(Point p, Rectangle r) -{ - return p.x>=r.min.x && p.x<=r.max.x && - p.y>=r.min.y && p.y<=r.max.y; -} - -/* - * If necessary, translate the rectangle physr - * some multiple of [dx dy] so that it includes p. - * Return 1 if the rectangle changed. - */ -static int -screenpan(Point p, Rectangle *physr, int dx, int dy) -{ - int d; - - if(ptalmostinrect(p, *physr)) - return 0; - - if(p.y < physr->min.y){ - d = physr->min.y - (p.y&~(dy-1)); - physr->min.y -= d; - physr->max.y -= d; - } - if(p.y > physr->max.y){ - d = ((p.y+dy-1)&~(dy-1)) - physr->max.y; - physr->min.y += d; - physr->max.y += d; - } - - if(p.x < physr->min.x){ - d = physr->min.x - (p.x&~(dx-1)); - physr->min.x -= d; - physr->max.x -= d; - } - if(p.x > physr->max.x){ - d = ((p.x+dx-1)&~(dx-1)) - physr->max.x; - physr->min.x += d; - physr->max.x += d; - } - return 1; -} - -static int -mach64xxcurmove(VGAscr* scr, Point p) -{ - int x, xo, y, yo; - int dx; - ulong off, pitch; - - /* - * If the point we want to display is outside the current - * screen rectangle, pan the screen to display it. - * - * We have to move in 64-bit chunks. - */ - if(scr->gscreen->depth == 24) - dx = (64*3)/24; - else - dx = 64 / scr->gscreen->depth; - - if(panning && screenpan(p, &physgscreenr, dx, 1)){ - off = (physgscreenr.min.y*Dx(scr->gscreen->r)+physgscreenr.min.x)/dx; - pitch = Dx(scr->gscreen->r)/8; - iow32(scr, CrtcOffPitch, (pitch<<22)|off); - } - - p.x -= physgscreenr.min.x; - p.y -= physgscreenr.min.y; - - /* - * Mustn't position the cursor offscreen even partially, - * or it disappears. Therefore, if x or y is -ve, adjust the - * cursor presets instead. If y is negative also have to - * adjust the starting offset. - */ - if((x = p.x+scr->offset.x) < 0){ - xo = x; - x = 0; - } - else - xo = 0; - if((y = p.y+scr->offset.y) < 0){ - yo = y; - y = 0; - } - else - yo = 0; - - iow32(scr, CurHVoff, ((64-16-yo)<<16)|(64-16-xo)); - iow32(scr, CurOffset, scr->storage/8 + (-yo*2)); - iow32(scr, CurHVposn, (y<<16)|x); - - return 0; -} - -static void -mach64xxcurenable(VGAscr* scr) -{ - ulong r, storage; - - mach64xxenable(scr); - if(scr->io == 0) - return; - - r = ior32(scr, GenTestCntl); - iow32(scr, GenTestCntl, r & ~0x80); - - iow32(scr, CurClr0, (Pwhite<<24)|(Pwhite<<16)|(Pwhite<<8)|Pwhite); - iow32(scr, CurClr1, (Pblack<<24)|(Pblack<<16)|(Pblack<<8)|Pblack); - - /* - * Find a place for the cursor data in display memory. - * Must be 64-bit aligned. - */ - storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+7)/8; - iow32(scr, CurOffset, storage); - scr->storage = storage*8; - - /* - * Cursor goes in the top right corner of the 64x64 array - * so the horizontal and vertical presets are 64-16. - */ - iow32(scr, CurHVposn, (0<<16)|0); - iow32(scr, CurHVoff, ((64-16)<<16)|(64-16)); - - /* - * Load, locate and enable the 64x64 cursor. - */ - mach64xxcurload(scr, &arrow); - mach64xxcurmove(scr, ZP); - iow32(scr, GenTestCntl, 0x80|r); -} - -static void -waitforfifo(VGAscr *scr, int entries) -{ - int x; - - x = 0; - while((ior32(scr, FifoStat)&0xFF) > (0x8000>>entries) && x++ < 1000000) - ; - if(x >= 1000000) - iprint("fifo %d stat %.8lux %.8lux scrio %.8lux mmio %p scr %p pc %luX\n", entries, ior32(scr, FifoStat), scr->mmio[mmoffset[FifoStat]], scr->io, scr->mmio, scr, getcallerpc(&scr)); -} - -static void -waitforidle(VGAscr *scr) -{ - int x; - - waitforfifo(scr, 16); - x = 0; - while((ior32(scr, GuiStat)&1) && x++ < 1000000) - ; - if(x >= 1000000) - iprint("idle stat %.8lux %.8lux scrio %.8lux mmio %p scr %p pc %luX\n", ior32(scr, GuiStat), scr->mmio[mmoffset[GuiStat]], scr->io, scr->mmio, scr, getcallerpc(&scr)); -} - -static void -resetengine(VGAscr *scr) -{ - ulong x; - x = ior32(scr, GenTestCntl); - iow32(scr, GenTestCntl, x&~0x100); - iow32(scr, GenTestCntl, x|0x100); - iow32(scr, BusCntl, ior32(scr, BusCntl)|0x00A00000); -} - -static void -init_overlayclock(VGAscr *scr) -{ - uchar *cc, save, pll_ref_div, pll_vclk_cntl, vclk_post_div, - vclk_fb_div, ecp_div; - int i; - ulong dotclock; - - /* Taken from GLX */ - /* Get monitor dotclock, check for Overlay Scaler clock limit */ - cc = (uchar *)&scr->mmio[mmoffset[ClockCntl]]; - save = cc[1]; i = cc[0] & 3; - cc[1] = 2<<2; pll_ref_div = cc[2]; - cc[1] = 5<<2; pll_vclk_cntl = cc[2]; - cc[1] = 6<<2; vclk_post_div = (cc[2]>>(i+i)) & 3; - cc[1] = (7+i)<<2; vclk_fb_div = cc[2]; - - dotclock = 2 * mach64refclock * vclk_fb_div / - (pll_ref_div * (1 << vclk_post_div)); - /* ecp_div: 0=dotclock, 1=dotclock/2, 2=dotclock/4 */ - ecp_div = dotclock / mach64type->m64_ovlclock; - if (ecp_div>2) ecp_div = 2; - - /* Force a scaler clock factor of 1 if refclock * - * is unknown (VCLK_SRC not PLLVCLK) */ - if ((pll_vclk_cntl & 0x03) != 0x03) - ecp_div = 0; - if ((pll_vclk_cntl & 0x30) != ecp_div<<4) { - cc[1] = (5<<2)|2; - cc[2] = (pll_vclk_cntl&0xCF) | (ecp_div<<4); - } - - /* Restore PLL Register Index */ - cc[1] = save; -} - -static void -initengine(VGAscr *scr) -{ - ulong pitch; - uchar *bios; - ushort table; - - pitch = Dx(scr->gscreen->r)/8; - if(scr->gscreen->depth == 24) - pitch *= 3; - - resetengine(scr); - waitforfifo(scr, 14); - iow32(scr, ContextMask, ~0); - iow32(scr, DstOffPitch, pitch<<22); - iow32(scr, DstYX, 0); - iow32(scr, DstHeight, 0); - iow32(scr, DstBresErr, 0); - iow32(scr, DstBresInc, 0); - iow32(scr, DstBresDec, 0); - iow32(scr, DstCntl, 0x23); - iow32(scr, SrcOffPitch, pitch<<22); - iow32(scr, SrcYX, 0); - iow32(scr, SrcHeight1Width1, 1); - iow32(scr, SrcYXstart, 0); - iow32(scr, SrcHeight2Width2, 1); - iow32(scr, SrcCntl, 0x01); - - waitforfifo(scr, 13); - iow32(scr, HostCntl, 0); - iow32(scr, PatReg0, 0); - iow32(scr, PatReg1, 0); - iow32(scr, PatCntl, 0); - iow32(scr, ScLeft, 0); - iow32(scr, ScTop, 0); - iow32(scr, ScBottom, 0xFFFF); - iow32(scr, ScRight, 0xFFFF); - iow32(scr, DpBkgdClr, 0); - iow32(scr, DpFrgdClr, ~0); - iow32(scr, DpWriteMask, ~0); - iow32(scr, DpMix, 0x70003); - iow32(scr, DpSrc, 0x00010100); - - waitforfifo(scr, 3); - iow32(scr, ClrCmpClr, 0); - iow32(scr, ClrCmpMask, ~0); - iow32(scr, ClrCmpCntl, 0); - - waitforfifo(scr, 2); - switch(scr->gscreen->depth){ - case 8: - case 24: /* [sic] */ - iow32(scr, DpPixWidth, 0x00020202); - iow32(scr, DpChainMask, 0x8080); - break; - case 16: - iow32(scr, DpPixWidth, 0x00040404); - iow32(scr, DpChainMask, 0x8410); - break; - case 32: - iow32(scr, DpPixWidth, 0x00060606); - iow32(scr, DpChainMask, 0x8080); - break; - } - - /* Get the base freq from the BIOS */ - bios = KADDR(0xC000); - table = *(ushort *)(bios + 0x48); - table = *(ushort *)(bios + table + 0x10); - switch (*(ushort *)(bios + table + 0x08)) { - case 2700: - mach64refclock = 270000; - break; - case 2863: - case 2864: - mach64refclock = 286363; - break; - case 2950: - mach64refclock = 294989; - break; - case 1432: - default: - mach64refclock = 143181; - break ; - } - - /* Figure out which revision this chip is */ - switch ((scr->mmio[mmoffset[ConfigChipId]] >> 24) & 0xFF) { - case VTGTB1S1: - case GTB1U1: - case GTB1S2: - case GTB2U1: - case GTB2U2: - case GTB2U3: - case GTBC: - case GTIIIC1U1: - case GTIIIC1U2: - case GTIIIC2U1: - case GTIIIC2U2: - case GTIIIC2U3: - case LTPRO: - mach64revb = 1; - break; - default: - mach64revb = 0; - break; - } - - waitforidle(scr); -} - -static int -mach64hwfill(VGAscr *scr, Rectangle r, ulong sval) -{ - ulong pitch; - ulong ctl; - -if(drawdebug) - iprint("hwfill %R val %lux...\n", r, sval); - - /* shouldn't happen */ - if(scr->io == 0x2EC || scr->io == 0x1C8 || scr->io == 0) - return 0; - - pitch = Dx(scr->gscreen->r)/8; - ctl = 1|2; /* left-to-right, top-to-bottom */ - if(scr->gscreen->depth == 24){ - r.min.x *= 3; - r.max.x *= 3; - pitch *= 3; - ctl |= (1<<7)|(((r.min.x/4)%6)<<8); - } - - waitforfifo(scr, 11); - iow32(scr, DpFrgdClr, sval); - iow32(scr, DpWriteMask, 0xFFFFFFFF); - iow32(scr, DpMix, 0x00070003); - iow32(scr, DpSrc, 0x00000111); - iow32(scr, ClrCmpCntl, 0x00000000); - iow32(scr, ScLeftRight, 0x1FFF0000); - iow32(scr, ScTopBottom, 0x1FFF0000); - iow32(scr, DstOffPitch, pitch<<22); - iow32(scr, DstCntl, ctl); - iow32(scr, DstYX, (r.min.x<<16)|r.min.y); - iow32(scr, DstHeightWidth, (Dx(r)<<16)|Dy(r)); - - waitforidle(scr); - return 1; -} - -static int -mach64hwscroll(VGAscr *scr, Rectangle r, Rectangle sr) -{ - ulong pitch; - Point dp, sp; - ulong ctl; - int dx, dy; - - dx = Dx(r); - dy = Dy(r); - pitch = Dx(scr->gscreen->r)/8; - if(scr->gscreen->depth == 24){ - dx *= 3; - pitch *= 3; - r.min.x *= 3; - sr.min.x *= 3; - } - - ctl = 0; - if(r.min.x <= sr.min.x){ - ctl |= 1; - dp.x = r.min.x; - sp.x = sr.min.x; - }else{ - dp.x = r.min.x+dx-1; - sp.x = sr.min.x+dx-1; - } - - if(r.min.y <= sr.min.y){ - ctl |= 2; - dp.y = r.min.y; - sp.y = sr.min.y; - }else{ - dp.y = r.min.y+dy-1; - sp.y = sr.min.y+dy-1; - } - - if(scr->gscreen->depth == 24) - ctl |= (1<<7)|(((dp.x/4)%6)<<8); - - waitforfifo(scr, 6); - iow32(scr, ScLeftRight, 0x1FFF0000); - iow32(scr, ScTopBottom, 0x1FFF0000); - iow32(scr, DpWriteMask, 0xFFFFFFFF); - iow32(scr, DpMix, 0x00070003); - iow32(scr, DpSrc, 0x00000300); - iow32(scr, ClrCmpCntl, 0x00000000); - - waitforfifo(scr, 8); - iow32(scr, SrcOffPitch, pitch<<22); - iow32(scr, SrcCntl, 0x00000000); - iow32(scr, SrcYX, (sp.x<<16)|sp.y); - iow32(scr, SrcWidth1, dx); - iow32(scr, DstOffPitch, pitch<<22); - iow32(scr, DstCntl, ctl); - - iow32(scr, DstYX, (dp.x<<16)|dp.y); - iow32(scr, DstHeightWidth, (dx<<16)|dy); - - waitforidle(scr); - - return 1; -} - -/* - * This should work, but doesn't. - * It messes up the screen timings for some reason. - */ -static void -mach64blank(VGAscr *scr, int blank) -{ - ulong ctl; - - ctl = ior32(scr, CrtcGenCtl) & ~(CrtcHsyncDis|CrtcVsyncDis); - if(blank) - ctl |= CrtcHsyncDis|CrtcVsyncDis; - iow32(scr, CrtcGenCtl, ctl); -} - -/* - * We squirrel away whether the LCD and/or CRT were - * on when we were called to blank the screen, and - * restore the old state. If we are called to blank the - * screen when it is already blank, we don't update the state. - * Such a call sequence should not happen, though. - * - * We could try forcing the chip into power management - * mode instead, but I'm not sure how that would interact - * with screen updates going on while the screen is blanked. - */ -static void -mach64lcdblank(VGAscr *scr, int blank) -{ - static int crtlcd; - ulong x; - - if(blank) { - x = lcdr32(scr, LCD_GenCtrl); - if(x & 3) { - crtlcd = x & 3; - lcdw32(scr, LCD_GenCtrl, x&~3); - } - } else { - if(crtlcd == 0) - crtlcd = 2; /* lcd only */ - x = lcdr32(scr, LCD_GenCtrl); - lcdw32(scr, LCD_GenCtrl, x | crtlcd); - } -} - -static void -mach64xxdrawinit(VGAscr *scr) -{ - if(scr->io > 0x2FF){ - initengine(scr); - scr->fill = mach64hwfill; - scr->scroll = mach64hwscroll; - } -/* scr->blank = mach64blank; */ - switch(scr->id){ - default: - break; - case ('L'<<8)|'B': /* 4C42: Rage 3D LTPro */ - case ('L'<<8)|'I': /* 4C49: Rage 3D LTPro */ - case ('L'<<8)|'M': /* 4C4D: Rage Mobility */ - case ('L'<<8)|'P': /* 4C50: Rage 3D LTPro */ - scr->blank = mach64lcdblank; - hwblank = 1; - break; - } -} - -static void -ovl_configure(VGAscr *scr, Chan *c, char **field) -{ - int w, h; - char *format; - - w = (int)strtol(field[1], nil, 0); - h = (int)strtol(field[2], nil, 0); - format = field[3]; - - if (c != ovl_chan) - error(Einuse); - if (strcmp(format, "YUYV")) - error(Eunsupportedformat); - - ovl_width = w; - ovl_height = h; - ovl_fib = w * h * sizeof(ushort); - - waitforidle(scr); - scr->mmio[mmoffset[BusCntl]] |= 0x08000000; /* Enable regblock 1 */ - scr->mmio[mmoffset[OverlayScaleCntl]] = - SCALE_ZERO_EXTEND|SCALE_RED_TEMP_6500K| - SCALE_HORZ_BLEND|SCALE_VERT_BLEND; - scr->mmio[mmoffset[!mach64revb? Buf0Pitch: ScalerBuf0Pitch]] = w; - scr->mmio[mmoffset[CaptureConfig]] = - SCALER_FRAME_READ_MODE_FULL| - SCALER_BUF_MODE_SINGLE| - SCALER_BUF_NEXT_0; - scr->mmio[mmoffset[OverlayKeyCntl]] = !mach64revb? - OVERLAY_MIX_ALWAYS_V|(OVERLAY_EXCLUSIVE_NORMAL << 28): - 0x011; - - if (mach64type->m64_pro) { - waitforfifo(scr, 6); - - /* set the scaler co-efficient registers */ - scr->mmio[mmoffset[ScalerColourCntl]] = - (0x00) | (0x10 << 8) | (0x10 << 16); - scr->mmio[mmoffset[ScalerHCoef0]] = - (0x00) | (0x20 << 8); - scr->mmio[mmoffset[ScalerHCoef1]] = - (0x0D) | (0x20 << 8) | (0x06 << 16) | (0x0D << 24); - scr->mmio[mmoffset[ScalerHCoef2]] = - (0x0D) | (0x1C << 8) | (0x0A << 16) | (0x0D << 24); - scr->mmio[mmoffset[ScalerHCoef3]] = - (0x0C) | (0x1A << 8) | (0x0E << 16) | (0x0C << 24); - scr->mmio[mmoffset[ScalerHCoef4]] = - (0x0C) | (0x14 << 8) | (0x14 << 16) | (0x0C << 24); - } - - waitforfifo(scr, 3); - scr->mmio[mmoffset[VideoFormat]] = SCALE_IN_YVYU422 | - (!mach64revb? 0xC: 0); - - if (mach64overlay == 0) - mach64overlay = scr->storage + 64 * 64 * sizeof(uchar); - scr->mmio[mmoffset[!mach64revb? Buf0Offset: ScalerBuf0Offset]] = - mach64overlay; -} - -static void -ovl_enable(VGAscr *scr, Chan *c, char **field) -{ - int x, y, w, h; - long h_inc, v_inc; - - x = (int)strtol(field[1], nil, 0); - y = (int)strtol(field[2], nil, 0); - w = (int)strtol(field[3], nil, 0); - h = (int)strtol(field[4], nil, 0); - - if (x < 0 || x + w > physgscreenr.max.x || - y < 0 || y + h > physgscreenr.max.y) - error(Ebadarg); - - if (c != ovl_chan) - error(Einuse); - if (scr->mmio[mmoffset[CrtcGenCntl]] & 1) { /* double scan enable */ - y *= 2; - h *= 2; - } - - waitforfifo(scr, 2); - scr->mmio[mmoffset[OverlayYX]] = - ((x & 0xFFFF) << 16) | (y & 0xFFFF); - scr->mmio[mmoffset[OverlayYXEnd]] = - (((x + w) & 0xFFFF) << 16) | ((y + h) & 0xFFFF); - - h_inc = (ovl_width << 12) / (w >> 1); /* ??? */ - v_inc = (ovl_height << 12) / h; - waitforfifo(scr, 2); - scr->mmio[mmoffset[OverlayScaleInc]] = - ((h_inc & 0xFFFF) << 16) | (v_inc & 0xFFFF); - scr->mmio[mmoffset[ScalerHeightWidth]] = - ((ovl_width & 0xFFFF) << 16) | (ovl_height & 0xFFFF); - waitforidle(scr); - scr->mmio[mmoffset[OverlayScaleCntl]] |= - (SCALE_ENABLE|OVERLAY_ENABLE); -} - -static void -ovl_status(VGAscr *scr, Chan *, char **field) -{ - pprint("%s: %s %.4uX, VT/GT %s, PRO %s, ovlclock %d, rev B %s, refclock %ld\n", - scr->dev->name, field[0], mach64type->m64_id, - mach64type->m64_vtgt? "yes": "no", - mach64type->m64_pro? "yes": "no", - mach64type->m64_ovlclock, - mach64revb? "yes": "no", - mach64refclock); - pprint("%s: storage @%.8luX, aperture @%8.ulX, ovl buf @%.8ulX\n", - scr->dev->name, scr->storage, scr->aperture, - mach64overlay); -} - -static void -ovl_openctl(VGAscr *, Chan *c, char **) -{ - if (ovl_chan) - error(Einuse); - ovl_chan = c; -} - -static void -ovl_closectl(VGAscr *scr, Chan *c, char **) -{ - if (c != ovl_chan) return; - - waitforidle(scr); - scr->mmio[mmoffset[OverlayScaleCntl]] &= - ~(SCALE_ENABLE|OVERLAY_ENABLE); - ovl_chan = nil; - ovl_width = ovl_height = ovl_fib = 0; -} - -enum -{ - CMclosectl, - CMconfigure, - CMenable, - CMopenctl, - CMstatus, -}; - -static void (*ovl_cmds[])(VGAscr *, Chan *, char **) = -{ - [CMclosectl] ovl_closectl, - [CMconfigure] ovl_configure, - [CMenable] ovl_enable, - [CMopenctl] ovl_openctl, - [CMstatus] ovl_status, -}; - -static Cmdtab mach64xxcmd[] = -{ - CMclosectl, "closectl", 1, - CMconfigure, "configure", 4, - CMenable, "enable", 5, - CMopenctl, "openctl", 1, - CMstatus, "status", 1, -}; - -static void -mach64xxovlctl(VGAscr *scr, Chan *c, void *a, int n) -{ - Cmdbuf *cb; - Cmdtab *ct; - - if(!mach64type->m64_vtgt) - error(Enodev); - - if(!scr->overlayinit){ - scr->overlayinit = 1; - init_overlayclock(scr); - } - cb = parsecmd(a, n); - if(waserror()){ - free(cb); - nexterror(); - } - - ct = lookupcmd(cb, mach64xxcmd, nelem(mach64xxcmd)); - - ovl_cmds[ct->index](scr, c, cb->f); - - poperror(); - free(cb); -} - -static int -mach64xxovlwrite(VGAscr *scr, void *a, int len, vlong offs) -{ - uchar *src; - int _len; - - if (ovl_chan == nil) return len; /* Acts as a /dev/null */ - - /* Calculate the destination address */ - _len = len; - src = (uchar *)a; - while (len > 0) { - ulong _offs; - int nb; - - _offs = (ulong)(offs % ovl_fib); - nb = (_offs + len > ovl_fib)? ovl_fib - _offs: len; - memmove((uchar *)KADDR(scr->aperture + mach64overlay + _offs), - src, nb); - offs += nb; - src += nb; - len -= nb; - } - return _len; -} - -VGAdev vgamach64xxdev = { - "mach64xx", - - mach64xxenable, /* enable */ - 0, /* disable */ - 0, /* page */ - mach64xxlinear, /* linear */ - mach64xxdrawinit, /* drawinit */ - 0, - mach64xxovlctl, /* overlay control */ - mach64xxovlwrite, /* write the overlay */ -}; - -VGAcur vgamach64xxcur = { - "mach64xxhwgc", - - mach64xxcurenable, /* enable */ - mach64xxcurdisable, /* disable */ - mach64xxcurload, /* load */ - mach64xxcurmove, /* move */ - - 1 /* doespanning */ -}; - diff --git a/os/pc/vgamga2164w.c b/os/pc/vgamga2164w.c deleted file mode 100644 index 6332236a..00000000 --- a/os/pc/vgamga2164w.c +++ /dev/null @@ -1,289 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -/* - * Matrox Millennium and Matrox Millennium II. - * Matrox MGA-2064W, MGA-2164W 3D graphics accelerators. - * Texas Instruments Tvp3026 RAMDAC. - */ - -enum { - /* pci chip manufacturer */ - MATROX = 0x102B, - - /* pci chip device ids */ - MGA2064 = 0x0519, - MGA2164 = 0x051B, - MGA2164AGP = 0x051F -}; - -static Pcidev* -mgapcimatch(void) -{ - Pcidev *p; - - p = pcimatch(nil, MATROX, MGA2164AGP); - if(p == nil) { - p = pcimatch(nil, MATROX, MGA2164); - if(p == nil) - p = pcimatch(nil, MATROX, MGA2064); - } - return p; -} - -static ulong -mga2164wlinear(VGAscr* scr, int* size, int* align) -{ - ulong aperture, oaperture; - int oapsize, wasupamem; - Pcidev *p; - - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - - if(p = mgapcimatch()){ - aperture = p->mem[p->did==MGA2064? 1 : 0].bar & ~0x0F; - *size = (p->did==MGA2064? 8 :16)*1024*1024; - } - else - aperture = 0; - - if(wasupamem) { - if(oaperture == aperture) - return oaperture; - upafree(oaperture, oapsize); - } - scr->isupamem = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)) { - aperture = oaperture; - scr->isupamem = 1; - } - else - scr->isupamem = 0; - } - else - scr->isupamem = 1; - - return aperture; -} - -static void -mga2164wenable(VGAscr* scr) -{ - Pcidev *p; - int size, align, immio; - ulong aperture; - - /* - * Only once, can't be disabled for now. - * scr->io holds the virtual address of - * the MMIO registers. - */ - if(scr->io) - return; - - p = mgapcimatch(); - if(p == nil) - return; - - immio = p->did==MGA2064? 0 : 1; - scr->io = upamalloc(p->mem[immio].bar & ~0x0F, p->mem[immio].size, 0); - if(scr->io == 0) - return; - addvgaseg("mga2164wmmio", scr->io, p->mem[immio].size); - - scr->io = (ulong)KADDR(scr->io); - - /* need to map frame buffer here too, so vga can find memory size */ - size = (p->did==MGA2064? 8 :16)*1024*1024; - align = 0; - aperture = mga2164wlinear(scr, &size, &align); - if(aperture) { - scr->aperture = aperture; - scr->apsize = size; - addvgaseg("mga2164wscreen", aperture, size); - } -} - -enum { - Index = 0x00, /* Index */ - Data = 0x0A, /* Data */ - - CaddrW = 0x04, /* Colour Write Address */ - Cdata = 0x05, /* Colour Data */ - - Cctl = 0x09, /* Direct Cursor Control */ - Cram = 0x0B, /* Cursor Ram Data */ - Cxlsb = 0x0C, /* Cursor X LSB */ - Cxmsb = 0x0D, /* Cursor X MSB */ - Cylsb = 0x0E, /* Cursor Y LSB */ - Cymsb = 0x0F, /* Cursor Y MSB */ - - Icctl = 0x06, /* Indirect Cursor Control */ -}; - -static void -tvp3026disable(VGAscr* scr) -{ - uchar *tvp3026; - - if(scr->io == 0) - return; - tvp3026 = KADDR(scr->io+0x3C00); - - /* - * Make sure cursor is off - * and direct control enabled. - */ - *(tvp3026+Index) = Icctl; - *(tvp3026+Data) = 0x90; - *(tvp3026+Cctl) = 0x00; -} - -static void -tvp3026load(VGAscr* scr, Cursor* curs) -{ - int x, y; - uchar *tvp3026; - - if(scr->io == 0) - return; - tvp3026 = KADDR(scr->io+0x3C00); - - /* - * Make sure cursor is off by initialising the cursor - * control to defaults. - * Write to the indirect control register to make sure - * direct register is enabled and upper 2 bits of cursor - * RAM address are 0. - * Put 0 in index register for lower 8 bits of cursor RAM address. - */ - tvp3026disable(scr); - *(tvp3026+Index) = 0; - - /* - * Initialise the 64x64 cursor RAM array. There are 2 planes, - * p0 and p1. Data is written 8 pixels per byte, with p0 in the - * first 512 bytes of the array and p1 in the second. - * The cursor is set in 3-colour mode which gives the following - * truth table: - * p1 p0 colour - * 0 0 transparent - * 0 1 cursor colour 0 - * 1 0 cursor colour 1 - * 1 1 cursor colour 2 - * Put the cursor into the top-left of the 64x64 array. - * The 0,0 cursor point is bottom-right, so positioning will - * have to take that into account. - */ - for(y = 0; y < 64; y++){ - for(x = 0; x < 64/8; x++){ - if(x < 16/8 && y < 16) - *(tvp3026+Cram) = curs->clr[x+y*2]; - else - *(tvp3026+Cram) = 0x00; - } - } - for(y = 0; y < 64; y++){ - for(x = 0; x < 64/8; x++){ - if(x < 16/8 && y < 16) - *(tvp3026+Cram) = curs->set[x+y*2]; - else - *(tvp3026+Cram) = 0x00; - } - } - - /* - * Initialise the cursor hotpoint - * and enable the cursor in 3-colour mode. - */ - scr->offset.x = 64+curs->offset.x; - scr->offset.y = 64+curs->offset.y; - *(tvp3026+Cctl) = 0x01; -} - -static int -tvp3026move(VGAscr* scr, Point p) -{ - int x, y; - uchar *tvp3026; - - if(scr->io == 0) - return 1; - tvp3026 = KADDR(scr->io+0x3C00); - - x = p.x+scr->offset.x; - y = p.y+scr->offset.y; - - *(tvp3026+Cxlsb) = x & 0xFF; - *(tvp3026+Cxmsb) = (x>>8) & 0x0F; - *(tvp3026+Cylsb) = y & 0xFF; - *(tvp3026+Cymsb) = (y>>8) & 0x0F; - - return 0; -} - -static void -tvp3026enable(VGAscr* scr) -{ - int i; - uchar *tvp3026; - - if(scr->io == 0) - return; - tvp3026 = KADDR(scr->io+0x3C00); - - tvp3026disable(scr); - - /* - * Overscan colour, - * cursor colour 1 (white), - * cursor colour 2, 3 (black). - */ - *(tvp3026+CaddrW) = 0x00; - for(i = 0; i < 6; i++) - *(tvp3026+Cdata) = Pwhite; - for(i = 0; i < 6; i++) - *(tvp3026+Cdata) = Pblack; - - /* - * Load, locate and enable the - * 64x64 cursor in 3-colour mode. - */ - tvp3026load(scr, &arrow); - tvp3026move(scr, ZP); - *(tvp3026+Cctl) = 0x01; -} - -VGAdev vgamga2164wdev = { - "mga2164w", - - mga2164wenable, /* enable */ - 0, /* disable */ - 0, /* page */ - mga2164wlinear, /* linear */ -}; - -VGAcur vgamga2164wcur = { - "mga2164whwgc", - - tvp3026enable, - tvp3026disable, - tvp3026load, - tvp3026move, -}; diff --git a/os/pc/vgamga4xx.c b/os/pc/vgamga4xx.c deleted file mode 100644 index 7ddeebf1..00000000 --- a/os/pc/vgamga4xx.c +++ /dev/null @@ -1,603 +0,0 @@ - -/* - * Matrox G200, G400 and G450. - * see /sys/src/cmd/aux/vga/mga4xx.c - */ - -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -enum { - MATROX = 0x102B, - MGA4xx = 0x0525, - MGA200 = 0x0521, - - Kilo = 1024, - Meg = 1024*1024, - - FCOL = 0x1c24, - FXRIGHT = 0x1cac, - FXLEFT = 0x1ca8, - YDST = 0x1c90, - YLEN = 0x1c5c, - DWGCTL = 0x1c00, - DWG_TRAP = 0x04, - DWG_BITBLT = 0x08, - DWG_ILOAD = 0x09, - DWG_LINEAR = 0x0080, - DWG_SOLID = 0x0800, - DWG_ARZERO = 0x1000, - DWG_SGNZERO = 0x2000, - DWG_SHIFTZERO = 0x4000, - DWG_REPLACE = 0x000C0000, - DWG_REPLACE2 = (DWG_REPLACE | 0x40), - DWG_XOR = 0x00060010, - DWG_BFCOL = 0x04000000, - DWG_BMONOWF = 0x08000000, - DWG_TRANSC = 0x40000000, - SRCORG = 0x2cb4, - PITCH = 0x1c8c, - DSTORG = 0x2cb8, - PLNWRT = 0x1c1c, - ZORG = 0x1c0c, - MACCESS = 0x1c04, - STATUS = 0x1e14, - FXBNDRY = 0x1C84, - CXBNDRY = 0x1C80, - YTOP = 0x1C98, - YBOT = 0x1C9C, - YDSTLEN = 0x1C88, - AR0 = 0x1C60, - AR1 = 0x1C64, - AR2 = 0x1C68, - AR3 = 0x1C6C, - AR4 = 0x1C70, - AR5 = 0x1C74, - SGN = 0x1C58, - SGN_SCANLEFT = 1, - SGN_SCANRIGHT = 0, - SGN_SDY_POSITIVE = 0, - SGN_SDY_NEGATIVE = 4, - - GO = 0x0100, - FIFOSTATUS = 0x1E10, - CACHEFLUSH = 0x1FFF, - - CRTCEXTIDX = 0x1FDE, /* CRTC Extension Index */ - CRTCEXTDATA = 0x1FDF, /* CRTC Extension Data */ - - FILL_OPERAND = 0x800c7804, -}; - -static Pcidev* -mgapcimatch(void) -{ - Pcidev* p; - - p = pcimatch(nil, MATROX, MGA4xx); - if (p == nil) - p = pcimatch(nil, MATROX, MGA200); - return p; -} - -static ulong -mga4xxlinear(VGAscr* scr, int* size, int* align) -{ - ulong aperture, oaperture; - int oapsize, wasupamem; - Pcidev * p; - - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - - if(p = mgapcimatch()){ - aperture = p->mem[0].bar & ~0x0F; - if(p->did == MGA4xx) - *size = 32*Meg; - else - *size = 8*Meg; - } - else - aperture = 0; - - if(wasupamem) { - if(oaperture == aperture) - return oaperture; - upafree(oaperture, oapsize); - } - scr->isupamem = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)) { - aperture = oaperture; - scr->isupamem = 1; - } - else - scr->isupamem = 0; - } - else - scr->isupamem = 1; - - return aperture; -} - -static void -mgawrite8(VGAscr* scr, int index, uchar val) -{ - ((uchar*)scr->io)[index] = val; -} - -static uchar -mgaread8(VGAscr* scr, int index) -{ - return ((uchar*)scr->io)[index]; -} - -static uchar -crtcextset(VGAscr* scr, int index, uchar set, uchar clr) -{ - uchar tmp; - - mgawrite8(scr, CRTCEXTIDX, index); - tmp = mgaread8(scr, CRTCEXTDATA); - mgawrite8(scr, CRTCEXTIDX, index); - mgawrite8(scr, CRTCEXTDATA, (tmp & ~clr) | set); - - return tmp; -} - -static void -mga4xxenable(VGAscr* scr) -{ - Pcidev * pci; - int size, align; - ulong aperture; - int i, n, k; - uchar * p; - uchar x[16]; - uchar crtcext3; - - /* - * Only once, can't be disabled for now. - * scr->io holds the virtual address of - * the MMIO registers. - */ - if(scr->io) - return; - - pci = mgapcimatch(); - if(pci == nil) - return; - - scr->io = upamalloc(pci->mem[1].bar & ~0x0F, 16*1024, 0); - if(scr->io == 0) - return; - - addvgaseg("mga4xxmmio", scr->io, pci->mem[1].size); - - scr->io = (ulong)KADDR(scr->io); - - /* need to map frame buffer here too, so vga can find memory size */ - size = 8*Meg; - align = 0; - aperture = mga4xxlinear(scr, &size, &align); - if(aperture) { - scr->aperture = aperture; - addvgaseg("mga4xxscreen", aperture, size); - - /* Find out how much memory is here, some multiple of 2 Meg */ - - /* First Set MGA Mode ... */ - crtcext3 = crtcextset(scr, 3, 0x80, 0x00); - - p = (uchar*)aperture; - n = (size / Meg) / 2; - for (i = 0; i < n; i++) { - k = (2*i+1)*Meg; - p[k] = 0; - p[k] = i+1; - *((uchar*)(scr->io + CACHEFLUSH)) = 0; - x[i] = p[k]; - } - for(i = 1; i < n; i++) - if(x[i] != i+1) - break; - scr->apsize = 2*i*Meg; - - crtcextset(scr, 3, crtcext3, 0xff); - } -} - -enum { - Index = 0x00, /* Index */ - Data = 0x0A, /* Data */ - - Cxlsb = 0x0C, /* Cursor X LSB */ - Cxmsb = 0x0D, /* Cursor X MSB */ - Cylsb = 0x0E, /* Cursor Y LSB */ - Cymsb = 0x0F, /* Cursor Y MSB */ - - Icuradrl = 0x04, /* Cursor Base Address Low */ - Icuradrh = 0x05, /* Cursor Base Address High */ - Icctl = 0x06, /* Indirect Cursor Control */ -}; - -static void -dac4xxdisable(VGAscr* scr) -{ - uchar * dac4xx; - - if(scr->io == 0) - return; - - dac4xx = KADDR(scr->io+0x3C00); - - *(dac4xx+Index) = Icctl; - *(dac4xx+Data) = 0x00; -} - -static void -dac4xxload(VGAscr* scr, Cursor* curs) -{ - int y; - uchar * p; - uchar * dac4xx; - - if(scr->io == 0) - return; - - dac4xx = KADDR(scr->io+0x3C00); - - dac4xxdisable(scr); - - p = KADDR(scr->storage); - for(y = 0; y < 64; y++){ - *p++ = 0; *p++ = 0; *p++ = 0; - *p++ = 0; *p++ = 0; *p++ = 0; - if(y <16){ - *p++ = curs->set[1+y*2]|curs->clr[1+2*y]; - *p++ = curs->set[y*2]|curs->clr[2*y]; - } else{ - *p++ = 0; *p++ = 0; - } - - *p++ = 0; *p++ = 0; *p++ = 0; - *p++ = 0; *p++ = 0; *p++ = 0; - if(y <16){ - *p++ = curs->set[1+y*2]; - *p++ = curs->set[y*2]; - } else{ - *p++ = 0; *p++ = 0; - } - } - scr->offset.x = 64 + curs->offset.x; - scr->offset.y = 64 + curs->offset.y; - - *(dac4xx+Index) = Icctl; - *(dac4xx+Data) = 0x03; -} - -static int -dac4xxmove(VGAscr* scr, Point p) -{ - int x, y; - uchar * dac4xx; - - if(scr->io == 0) - return 1; - - dac4xx = KADDR(scr->io + 0x3C00); - - x = p.x + scr->offset.x; - y = p.y + scr->offset.y; - - *(dac4xx+Cxlsb) = x & 0xFF; - *(dac4xx+Cxmsb) = (x>>8) & 0x0F; - - *(dac4xx+Cylsb) = y & 0xFF; - *(dac4xx+Cymsb) = (y>>8) & 0x0F; - - return 0; -} - -static void -dac4xxenable(VGAscr* scr) -{ - uchar * dac4xx; - ulong storage; - - if(scr->io == 0) - return; - dac4xx = KADDR(scr->io+0x3C00); - - dac4xxdisable(scr); - - storage = (scr->apsize - 4096) & ~0x3ff; - - *(dac4xx+Index) = Icuradrl; - *(dac4xx+Data) = 0xff & (storage >> 10); - *(dac4xx+Index) = Icuradrh; - *(dac4xx+Data) = 0xff & (storage >> 18); - - scr->storage = (ulong) KADDR((ulong)scr->aperture + (ulong)storage); - - /* Show X11-Like Cursor */ - *(dac4xx+Index) = Icctl; - *(dac4xx+Data) = 0x03; - - /* Cursor Color 0 : White */ - *(dac4xx+Index) = 0x08; - *(dac4xx+Data) = 0xff; - *(dac4xx+Index) = 0x09; - *(dac4xx+Data) = 0xff; - *(dac4xx+Index) = 0x0a; - *(dac4xx+Data) = 0xff; - - /* Cursor Color 1 : Black */ - *(dac4xx+Index) = 0x0c; - *(dac4xx+Data) = 0x00; - *(dac4xx+Index) = 0x0d; - *(dac4xx+Data) = 0x00; - *(dac4xx+Index) = 0x0e; - *(dac4xx+Data) = 0x00; - - /* Cursor Color 2 : Red */ - *(dac4xx+Index) = 0x10; - *(dac4xx+Data) = 0xff; - *(dac4xx+Index) = 0x11; - *(dac4xx+Data) = 0x00; - *(dac4xx+Index) = 0x12; - *(dac4xx+Data) = 0x00; - - /* - * Load, locate and enable the - * 64x64 cursor in X11 mode. - */ - dac4xxload(scr, &arrow); - dac4xxmove(scr, ZP); -} - -static void -mga4xxblank(VGAscr* scr, int blank) -{ - char * cp; - uchar * mga; - uchar seq1, crtcext1; - - /* blank = 0 -> turn screen on */ - /* blank = 1 -> turn screen off */ - - if(scr->io == 0) - return; - mga = KADDR(scr->io); - - if (blank == 0) { - seq1 = 0x00; - crtcext1 = 0x00; - } else { - seq1 = 0x20; - crtcext1 = 0x10; /* Default value ... : standby */ - cp = getconf("*dpms"); - if (cp) { - if (cistrcmp(cp, "standby") == 0) { - crtcext1 = 0x10; - } else if (cistrcmp(cp, "suspend") == 0) { - crtcext1 = 0x20; - } else if (cistrcmp(cp, "off") == 0) { - crtcext1 = 0x30; - } - } - } - - *(mga + 0x1fc4) = 1; - seq1 |= *(mga + 0x1fc5) & ~0x20; - *(mga + 0x1fc5) = seq1; - - *(mga + 0x1fde) = 1; - crtcext1 |= *(mga + 0x1fdf) & ~0x30; - *(mga + 0x1fdf) = crtcext1; -} - -static void -mgawrite32(uchar * mga, ulong reg, ulong val) -{ - ulong * l; - - l = (ulong *)(&mga[reg]); - l[0] = val; -} - -static ulong -mgaread32(uchar * mga, ulong reg) -{ - return *((ulong *)(&mga[reg])); -} - -static int -mga4xxfill(VGAscr* scr, Rectangle r, ulong color) -{ - uchar * mga; - - /* Constant Shaded Trapezoids / Rectangle Fills */ - if(scr->io == 0) - return 0; - mga = KADDR(scr->io); - - mgawrite32(mga, DWGCTL, 0); - mgawrite32(mga, FCOL, color); - mgawrite32(mga, FXRIGHT, r.max.x); - mgawrite32(mga, FXLEFT, r.min.x); - mgawrite32(mga, YDST, r.min.y); - mgawrite32(mga, YLEN, Dy(r)); - mgawrite32(mga, DWGCTL + GO, FILL_OPERAND); - - while (mgaread32(mga, STATUS) & 0x00010000) - ; - return 1; -} - -#define mga_fifo(n) do {} while ((mgaread32(mga, FIFOSTATUS) & 0xFF) < (n)) - -static int -mga4xxscroll(VGAscr* scr, Rectangle r_dst, Rectangle r_src) -{ - uchar * mga; - ulong pitch, y; - ulong width, height, start, end, scandir; - int ydir; - - /* Two-operand Bitblts */ - if(scr->io == 0) - return 0; - - mga = KADDR(scr->io); - - pitch = Dx(scr->gscreen->r); - - mgawrite32(mga, DWGCTL, 0); - - scandir = 0; - - height = abs(Dy(r_src)); - width = abs(Dx(r_src)); - - assert(height == abs(Dy(r_dst))); - assert(width == abs(Dx(r_dst))); - - if ((r_src.min.y == r_dst.min.y) && (r_src.min.x == r_dst.min.x)) - { - if (0) - print("move x,y to x,y !\n"); - return 1; - } - - ydir = 1; - if (r_dst.min.y > r_src.min.y) - { - if (0) - print("ydir = -1\n"); - ydir = -1; - scandir |= 4; // Blit UP - } - - if (r_dst.min.x > r_src.min.x) - { - if (0) - print("xdir = -1\n"); - scandir |= 1; // Blit Left - } - - mga_fifo(4); - if (scandir) - { - mgawrite32(mga, DWGCTL, DWG_BITBLT | DWG_SHIFTZERO | - DWG_SGNZERO | DWG_BFCOL | DWG_REPLACE); - mgawrite32(mga, SGN, scandir); - } else - { - mgawrite32(mga, DWGCTL, DWG_BITBLT | DWG_SHIFTZERO | - DWG_BFCOL | DWG_REPLACE); - } - mgawrite32(mga, AR5, ydir * pitch); - - width--; - start = end = r_src.min.x + (r_src.min.y * pitch); - if ((scandir & 1) == 1) - { - start += width; - } else - { - end += width; - } - - y = r_dst.min.y; - if ((scandir & 4) == 4) - { - start += (height - 1) * pitch; - end += (height - 1) * pitch; - y += (height - 1); - } - - mga_fifo(4); - mgawrite32(mga, AR0, end); - mgawrite32(mga, AR3, start); - mgawrite32(mga, FXBNDRY, ((r_dst.min.x+width)<<16) | r_dst.min.x); - mgawrite32(mga, YDSTLEN + GO, (y << 16) | height); - - if (1) - { - while (mgaread32(mga, STATUS) & 0x00010000) - ; - } - - return 1; -} - -static void -mga4xxdrawinit(VGAscr* scr) -{ - uchar * mga; - Pcidev* p; - - p = pcimatch(nil, MATROX, MGA4xx); - if (p == nil) - return ; - - if(scr->io == 0) - return; - mga = KADDR(scr->io); - - mgawrite32(mga, SRCORG, 0); - mgawrite32(mga, DSTORG, 0); - mgawrite32(mga, ZORG, 0); - mgawrite32(mga, PLNWRT, ~0); - mgawrite32(mga, FCOL, 0xffff0000); - mgawrite32(mga, CXBNDRY, 0xFFFF0000); - mgawrite32(mga, YTOP, 0); - mgawrite32(mga, YBOT, 0x01FFFFFF); - mgawrite32(mga, PITCH, Dx(scr->gscreen->r) & ((1 << 13) - 1)); - switch(scr->gscreen->depth) { - case 8: - mgawrite32(mga, MACCESS, 0); - break; - case 32: - mgawrite32(mga, MACCESS, 2); - break; - default: - return; /* depth not supported ! */ - } - scr->fill = mga4xxfill; - scr->scroll = mga4xxscroll; - scr->blank = mga4xxblank; -} - -VGAdev vgamga4xxdev = { - "mga4xx", - - mga4xxenable, /* enable */ - 0, /* disable */ - 0, /* page */ - mga4xxlinear, /* linear */ - mga4xxdrawinit, -}; - -VGAcur vgamga4xxcur = { - "mga4xxhwgc", - dac4xxenable, - dac4xxdisable, - dac4xxload, - dac4xxmove, -}; diff --git a/os/pc/vganeomagic.c b/os/pc/vganeomagic.c deleted file mode 100644 index ba25a581..00000000 --- a/os/pc/vganeomagic.c +++ /dev/null @@ -1,541 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -typedef struct CursorNM CursorNM; -struct CursorNM { - int enable; - int x; - int y; - int colour1; - int colour2; - int addr; -}; - -static ulong -neomagiclinear(VGAscr* scr, int* size, int* align) -{ - ulong aperture, oaperture; - int oapsize, wasupamem; - Pcidev *p; - - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - - aperture = 0; - if(p = pcimatch(nil, 0x10C8, 0)){ - switch(p->did){ - case 0x0004: /* MagicGraph 128XD */ - case 0x0005: /* MagicMedia 256AV */ - case 0x0006: /* MagicMedia 256ZX */ - aperture = p->mem[0].bar & ~0x0F; - *size = p->mem[0].size; - break; - default: - break; - } - } - - if(wasupamem){ - if(oaperture == aperture) - return oaperture; - upafree(oaperture, oapsize); - } - scr->isupamem = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)){ - aperture = oaperture; - scr->isupamem = 1; - } - else - scr->isupamem = 0; - } - else - scr->isupamem = 1; - - return aperture; -} - -static void -neomagicenable(VGAscr* scr) -{ - Pcidev *p; - int align, curoff, size, vmsize; - ulong aperture; - - /* - * Only once, can't be disabled for now. - * scr->io holds the physical address of the cursor registers - * in the MMIO space. This may need to change for older chips - * which have the MMIO space offset in the framebuffer region. - */ - if(scr->io) - return; - if(p = pcimatch(nil, 0x10C8, 0)){ - switch(p->did){ - case 0x0004: /* MagicGraph 128XD */ - curoff = 0x100; - vmsize = 2048*1024; - break; - case 0x0005: /* MagicMedia 256AV */ - curoff = 0x1000; - vmsize = 2560*1024; - break; - case 0x0006: /* MagicMedia 256ZX */ - curoff = 0x1000; - vmsize = 4096*1024; - break; - default: - return; - } - } - else - return; - scr->io = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0); - if(scr->io == 0) - return; - addvgaseg("neomagicmmio", scr->io, p->mem[1].size); - scr->mmio = KADDR(scr->io); - - /* - * Find a place for the cursor data in display memory. - * 2 cursor images might be needed, 1KB each so use the - * last 2KB of the framebuffer. - */ - scr->storage = vmsize-2*1024; - scr->io += curoff; - - size = p->mem[0].size; - align = 0; - aperture = neomagiclinear(scr, &size, &align); - if(aperture) { - scr->aperture = aperture; - scr->apsize = size; - addvgaseg("neomagicscreen", aperture, size); - } -} - -static void -neomagiccurdisable(VGAscr* scr) -{ - CursorNM *cursornm; - - if(scr->io == 0) - return; - cursornm = KADDR(scr->io); - cursornm->enable = 0; -} - -static void -neomagicinitcursor(VGAscr* scr, int xo, int yo, int index) -{ - uchar *p; - uint p0, p1; - int x, y; - - p = KADDR(scr->aperture); - p += scr->storage + index*1024; - - for(y = yo; y < 16; y++){ - p0 = scr->set[2*y]; - p1 = scr->set[2*y+1]; - if(xo){ - p0 = (p0<>(8-xo)); - p1 <<= xo; - } - *p++ = p0; - *p++ = p1; - - for(x = 16; x < 64; x += 8) - *p++ = 0x00; - - p0 = scr->clr[2*y]|scr->set[2*y]; - p1 = scr->clr[2*y+1]|scr->set[2*y+1]; - if(xo){ - p0 = (p0<>(8-xo)); - p1 <<= xo; - } - *p++ = p0; - *p++ = p1; - - for(x = 16; x < 64; x += 8) - *p++ = 0x00; - } - while(y < 64+yo){ - for(x = 0; x < 64; x += 8){ - *p++ = 0x00; - *p++ = 0x00; - } - y++; - } -} - -static void -neomagiccurload(VGAscr* scr, Cursor* curs) -{ - CursorNM *cursornm; - - if(scr->io == 0) - return; - cursornm = KADDR(scr->io); - - cursornm->enable = 0; - memmove(&scr->Cursor, curs, sizeof(Cursor)); - neomagicinitcursor(scr, 0, 0, 0); - cursornm->enable = 1; -} - -static int -neomagiccurmove(VGAscr* scr, Point p) -{ - CursorNM *cursornm; - int addr, index, x, xo, y, yo; - - if(scr->io == 0) - return 1; - cursornm = KADDR(scr->io); - - index = 0; - if((x = p.x+scr->offset.x) < 0){ - xo = -x; - x = 0; - } - else - xo = 0; - if((y = p.y+scr->offset.y) < 0){ - yo = -y; - y = 0; - } - else - yo = 0; - - if(xo || yo){ - index = 1; - neomagicinitcursor(scr, xo, yo, index); - } - addr = ((scr->storage+(1024*index))>>10) & 0xFFF; - addr = ((addr & 0x00F)<<8)|((addr>>4) & 0xFF); - if(cursornm->addr != addr) - cursornm->addr = addr; - - cursornm->x = x; - cursornm->y = y; - - return 0; -} - -static void -neomagiccurenable(VGAscr* scr) -{ - CursorNM *cursornm; - - neomagicenable(scr); - if(scr->io == 0) - return; - cursornm = KADDR(scr->io); - cursornm->enable = 0; - - /* - * Cursor colours. - */ - cursornm->colour1 = (Pblack<<16)|(Pblack<<8)|Pblack; - cursornm->colour2 = (Pwhite<<16)|(Pwhite<<8)|Pwhite; - - /* - * Load, locate and enable the 64x64 cursor. - */ - neomagiccurload(scr, &arrow); - neomagiccurmove(scr, ZP); - cursornm->enable = 1; -} - -static int neomagicbltflags; - -/* registers */ -enum { - BltStat = 0, - BltCntl = 1, - XPColor = 2, - FGColor = 3, - BGColor = 4, - Pitch = 5, - ClipLT = 6, - ClipRB = 7, - SrcBitOff = 8, - SrcStartOff = 9, - - DstStartOff = 11, - XYExt = 12, - - PageCntl = 20, - PageBase, - PostBase, - PostPtr, - DataPtr, -}; - -/* flags */ -enum { - NEO_BS0_BLT_BUSY = 0x00000001, - NEO_BS0_FIFO_AVAIL = 0x00000002, - NEO_BS0_FIFO_PEND = 0x00000004, - - NEO_BC0_DST_Y_DEC = 0x00000001, - NEO_BC0_X_DEC = 0x00000002, - NEO_BC0_SRC_TRANS = 0x00000004, - NEO_BC0_SRC_IS_FG = 0x00000008, - NEO_BC0_SRC_Y_DEC = 0x00000010, - NEO_BC0_FILL_PAT = 0x00000020, - NEO_BC0_SRC_MONO = 0x00000040, - NEO_BC0_SYS_TO_VID = 0x00000080, - - NEO_BC1_DEPTH8 = 0x00000100, - NEO_BC1_DEPTH16 = 0x00000200, - NEO_BC1_DEPTH24 = 0x00000300, - NEO_BC1_X_320 = 0x00000400, - NEO_BC1_X_640 = 0x00000800, - NEO_BC1_X_800 = 0x00000c00, - NEO_BC1_X_1024 = 0x00001000, - NEO_BC1_X_1152 = 0x00001400, - NEO_BC1_X_1280 = 0x00001800, - NEO_BC1_X_1600 = 0x00001c00, - NEO_BC1_DST_TRANS = 0x00002000, - NEO_BC1_MSTR_BLT = 0x00004000, - NEO_BC1_FILTER_Z = 0x00008000, - - NEO_BC2_WR_TR_DST = 0x00800000, - - NEO_BC3_SRC_XY_ADDR = 0x01000000, - NEO_BC3_DST_XY_ADDR = 0x02000000, - NEO_BC3_CLIP_ON = 0x04000000, - NEO_BC3_FIFO_EN = 0x08000000, - NEO_BC3_BLT_ON_ADDR = 0x10000000, - NEO_BC3_SKIP_MAPPING = 0x80000000, - - NEO_MODE1_DEPTH8 = 0x0100, - NEO_MODE1_DEPTH16 = 0x0200, - NEO_MODE1_DEPTH24 = 0x0300, - NEO_MODE1_X_320 = 0x0400, - NEO_MODE1_X_640 = 0x0800, - NEO_MODE1_X_800 = 0x0c00, - NEO_MODE1_X_1024 = 0x1000, - NEO_MODE1_X_1152 = 0x1400, - NEO_MODE1_X_1280 = 0x1800, - NEO_MODE1_X_1600 = 0x1c00, - NEO_MODE1_BLT_ON_ADDR = 0x2000, -}; - -/* Raster Operations */ -enum { - GXclear = 0x000000, /* 0x0000 */ - GXand = 0x080000, /* 0x1000 */ - GXandReverse = 0x040000, /* 0x0100 */ - GXcopy = 0x0c0000, /* 0x1100 */ - GXandInvert = 0x020000, /* 0x0010 */ - GXnoop = 0x0a0000, /* 0x1010 */ - GXxor = 0x060000, /* 0x0110 */ - GXor = 0x0e0000, /* 0x1110 */ - GXnor = 0x010000, /* 0x0001 */ - GXequiv = 0x090000, /* 0x1001 */ - GXinvert = 0x050000, /* 0x0101 */ - GXorReverse = 0x0d0000, /* 0x1101 */ - GXcopyInvert = 0x030000, /* 0x0011 */ - GXorInverted = 0x0b0000, /* 0x1011 */ - GXnand = 0x070000, /* 0x0111 */ - GXset = 0x0f0000, /* 0x1111 */ -}; - -static void -waitforidle(VGAscr *scr) -{ - ulong *mmio; - long x; - - mmio = scr->mmio; - x = 0; - while((mmio[BltStat] & NEO_BS0_BLT_BUSY) && x++ < 1000000) - ; - //if(x >= 1000000) - // iprint("idle stat %lud scrmmio %.8lux scr %p pc %luX\n", mmio[BltStat], scr->mmio, scr, getcallerpc(&scr)); -} - -static void -waitforfifo(VGAscr *scr, int entries) -{ - ulong *mmio; - long x; - - mmio = scr->mmio; - x = 0; - while(((mmio[BltStat]>>8) < entries) && x++ < 1000000) - ; - //if(x >= 1000000) - // iprint("fifo stat %d scrmmio %.8lux scr %p pc %luX\n", mmio[BltStat]>>8, scr->mmio, scr, getcallerpc(&scr)); - /* DirectFB says the above doesn't work. if so... */ - /* waitforidle(scr); */ -} - -static int -neomagichwfill(VGAscr *scr, Rectangle r, ulong sval) -{ - ulong *mmio; - - mmio = scr->mmio; - - waitforfifo(scr, 1); - mmio[FGColor] = sval; - waitforfifo(scr, 3); - mmio[BltCntl] = neomagicbltflags - | NEO_BC3_FIFO_EN - | NEO_BC0_SRC_IS_FG - | NEO_BC3_SKIP_MAPPING - | GXcopy; - mmio[DstStartOff] = scr->aperture - + r.min.y*scr->gscreen->width*BY2WD - + r.min.x*scr->gscreen->depth/BI2BY; - mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff); - waitforidle(scr); - return 1; -} - -static int -neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr) -{ - ulong *mmio; - int pitch, pixel; - - mmio = scr->mmio; - - pitch = scr->gscreen->width*BY2WD; - pixel = scr->gscreen->depth/BI2BY; - - waitforfifo(scr, 4); - if (r.min.y < sr.min.y || (r.min.y == sr.min.y && r.min.x < sr.min.x)) { - /* start from upper-left */ - mmio[BltCntl] = neomagicbltflags - | NEO_BC3_FIFO_EN - | NEO_BC3_SKIP_MAPPING - | GXcopy; - mmio[SrcStartOff] = scr->aperture - + sr.min.y*pitch + sr.min.x*pixel; - mmio[DstStartOff] = scr->aperture - + r.min.y*pitch + r.min.x*pixel; - } else { - /* start from lower-right */ - mmio[BltCntl] = neomagicbltflags - | NEO_BC0_X_DEC - | NEO_BC0_DST_Y_DEC - | NEO_BC0_SRC_Y_DEC - | NEO_BC3_FIFO_EN - | NEO_BC3_SKIP_MAPPING - | GXcopy; - mmio[SrcStartOff] = scr->aperture - + (sr.max.y-1)*pitch + (sr.max.x-1)*pixel; - mmio[DstStartOff] = scr->aperture - + (r.max.y-1)*pitch + (r.max.x-1)*pixel; - } - mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff); - waitforidle(scr); - return 1; -} - -static void -neomagicdrawinit(VGAscr *scr) -{ - ulong *mmio; - uint bltmode, pitch; - - mmio = scr->mmio; - - pitch = scr->gscreen->width*BY2WD; - - neomagicbltflags = bltmode = 0; - - switch(scr->gscreen->depth) { - case 8: - bltmode |= NEO_MODE1_DEPTH8; - neomagicbltflags |= NEO_BC1_DEPTH8; - break; - case 16: - bltmode |= NEO_MODE1_DEPTH16; - neomagicbltflags |= NEO_BC1_DEPTH16; - break; - case 24: /* I can't get it to work, and XFree86 doesn't either. */ - default: /* give up */ - return; - } - - switch(Dx(scr->gscreen->r)) { - case 320: - bltmode |= NEO_MODE1_X_320; - neomagicbltflags |= NEO_BC1_X_320; - break; - case 640: - bltmode |= NEO_MODE1_X_640; - neomagicbltflags |= NEO_BC1_X_640; - break; - case 800: - bltmode |= NEO_MODE1_X_800; - neomagicbltflags |= NEO_BC1_X_800; - break; - case 1024: - bltmode |= NEO_MODE1_X_1024; - neomagicbltflags |= NEO_BC1_X_1024; - break; - case 1152: - bltmode |= NEO_MODE1_X_1152; - neomagicbltflags |= NEO_BC1_X_1152; - break; - case 1280: - bltmode |= NEO_MODE1_X_1280; - neomagicbltflags |= NEO_BC1_X_1280; - break; - case 1600: - bltmode |= NEO_MODE1_X_1600; - neomagicbltflags |= NEO_BC1_X_1600; - break; - default: - /* don't worry about it */ - break; - } - - waitforidle(scr); - mmio[BltStat] = bltmode << 16; - mmio[Pitch] = (pitch << 16) | (pitch & 0xffff); - - scr->fill = neomagichwfill; - scr->scroll = neomagichwscroll; -} - -VGAdev vganeomagicdev = { - "neomagic", - - neomagicenable, - nil, - nil, - neomagiclinear, - neomagicdrawinit, -}; - -VGAcur vganeomagiccur = { - "neomagichwgc", - - neomagiccurenable, - neomagiccurdisable, - neomagiccurload, - neomagiccurmove, -}; - diff --git a/os/pc/vganvidia.c b/os/pc/vganvidia.c deleted file mode 100644 index e057ef1f..00000000 --- a/os/pc/vganvidia.c +++ /dev/null @@ -1,373 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -enum { - Pramin = 0x00710000, - Pramdac = 0x00680000, - Fifo = 0x00800000, - Pgraph = 0x00400000 -}; - -enum { - hwCurPos = Pramdac + 0x0300, - hwCurImage = Pramin + (0x00010000 - 0x0800), -}; - -/* Nvidia is good about backwards compatibility -- any did >= 0x20 is fine */ -static Pcidev* -nvidiapci(void) -{ - Pcidev *p; - - p = nil; - while((p = pcimatch(p, 0x10DE, 0)) != nil){ - if(p->did >= 0x20 && p->ccrb == 3) /* video card */ - return p; - } - return nil; -} - -static ulong -nvidialinear(VGAscr* scr, int* size, int* align) -{ - Pcidev *p; - int oapsize, wasupamem; - ulong aperture, oaperture; - - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - - aperture = 0; - if(p = nvidiapci()){ - aperture = p->mem[1].bar & ~0x0F; - *size = p->mem[1].size; - } - - if(wasupamem){ - if(oaperture == aperture) - return oaperture; - upafree(oaperture, oapsize); - } - scr->isupamem = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)){ - aperture = oaperture; - scr->isupamem = 1; - } - else - scr->isupamem = 0; - } - else - scr->isupamem = 1; - - return aperture; -} - -static void -nvidiaenable(VGAscr* scr) -{ - Pcidev *p; - ulong aperture; - int align, size; - - /* - * Only once, can't be disabled for now. - * scr->io holds the physical address of - * the MMIO registers. - */ - if(scr->io) - return; - p = nvidiapci(); - if(p == nil) - return; - scr->id = p->did; - - scr->io = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0); - if(scr->io == 0) - return; - addvgaseg("nvidiammio", scr->io, p->mem[0].size); - - size = p->mem[1].size; - align = 0; - aperture = nvidialinear(scr, &size, &align); - if(aperture){ - scr->aperture = aperture; - scr->apsize = size; - addvgaseg("nvidiascreen", aperture, size); - } -} - -static void -nvidiacurdisable(VGAscr* scr) -{ - if(scr->io == 0) - return; - - vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01); -} - -static void -nvidiacurload(VGAscr* scr, Cursor* curs) -{ - ulong* p; - int i,j; - ushort c,s; - ulong tmp; - - if(scr->io == 0) - return; - - vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01); - - p = KADDR(scr->io + hwCurImage); - - for(i=0; i<16; i++) { - switch(scr->id){ - default: - c = (curs->clr[2 * i] << 8) | curs->clr[2 * i+1]; - s = (curs->set[2 * i] << 8) | curs->set[2 * i+1]; - break; - case 0x171: /* for Geforece4 MX bug, K.Okamoto */ - case 0x181: - c = (curs->clr[2 * i+1] << 8) | curs->clr[2 * i]; - s = (curs->set[2 * i+1] << 8) | curs->set[2 * i]; - break; - } - tmp = 0; - for (j=0; j<16; j++){ - if(s&0x8000) - tmp |= 0x80000000; - else if(c&0x8000) - tmp |= 0xFFFF0000; - if (j&0x1){ - *p++ = tmp; - tmp = 0; - } else { - tmp>>=16; - } - c<<=1; - s<<=1; - } - for (j=0; j<8; j++) - *p++ = 0; - } - for (i=0; i<256; i++) - *p++ = 0; - - scr->offset = curs->offset; - vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01); - - return; -} - -static int -nvidiacurmove(VGAscr* scr, Point p) -{ - ulong* cursorpos; - - if(scr->io == 0) - return 1; - - cursorpos = KADDR(scr->io + hwCurPos); - *cursorpos = ((p.y+scr->offset.y)<<16)|((p.x+scr->offset.x) & 0xFFFF); - - return 0; -} - -static void -nvidiacurenable(VGAscr* scr) -{ - nvidiaenable(scr); - if(scr->io == 0) - return; - - vgaxo(Crtx, 0x1F, 0x57); - - nvidiacurload(scr, &arrow); - nvidiacurmove(scr, ZP); - - vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01); -} - -enum { - RopFifo = 0x00000000, - ClipFifo = 0x00002000, - PattFifo = 0x00004000, - BltFifo = 0x00008000, - BitmapFifo = 0x0000A000, -}; - -enum { - RopRop3 = RopFifo + 0x300, - - ClipTopLeft = ClipFifo + 0x300, - ClipWidthHeight = ClipFifo + 0x304, - - PattShape = PattFifo + 0x0308, - PattColor0 = PattFifo + 0x0310, - PattColor1 = PattFifo + 0x0314, - PattMonochrome0 = PattFifo + 0x0318, - PattMonochrome1 = PattFifo + 0x031C, - - BltTopLeftSrc = BltFifo + 0x0300, - BltTopLeftDst = BltFifo + 0x0304, - BltWidthHeight = BltFifo + 0x0308, - - BitmapColor1A = BitmapFifo + 0x03FC, - BitmapURect0TopLeft = BitmapFifo + 0x0400, - BitmapURect0WidthHeight = BitmapFifo + 0x0404, -}; - -static void -waitforidle(VGAscr *scr) -{ - ulong* pgraph; - int x; - - pgraph = KADDR(scr->io + Pgraph); - - x = 0; - while(pgraph[0x00000700/4] & 0x01 && x++ < 1000000) - ; - - if(x >= 1000000) - iprint("idle stat %lud scrio %.8lux scr %p pc %luX\n", *pgraph, scr->io, scr, getcallerpc(&scr)); -} - -static void -waitforfifo(VGAscr *scr, int fifo, int entries) -{ - ushort* fifofree; - int x; - - x = 0; - fifofree = KADDR(scr->io + Fifo + fifo + 0x10); - - while(((*fifofree >> 2) < entries) && x++ < 1000000) - ; - - if(x >= 1000000) - iprint("fifo stat %d scrio %.8lux scr %p pc %luX\n", *fifofree, scr->io, scr, getcallerpc(&scr)); -} - -static int -nvidiahwfill(VGAscr *scr, Rectangle r, ulong sval) -{ - ulong* fifo; - - fifo = KADDR(scr->io + Fifo); - - waitforfifo(scr, BitmapFifo, 1); - - fifo[BitmapColor1A/4] = sval; - - waitforfifo(scr, BitmapFifo, 2); - - fifo[BitmapURect0TopLeft/4] = (r.min.x << 16) | r.min.y; - fifo[BitmapURect0WidthHeight/4] = (Dx(r) << 16) | Dy(r); - - waitforidle(scr); - - return 1; -} - -static int -nvidiahwscroll(VGAscr *scr, Rectangle r, Rectangle sr) -{ - ulong* fifo; - - fifo = KADDR(scr->io + Fifo); - - waitforfifo(scr, BltFifo, 3); - - fifo[BltTopLeftSrc/4] = (sr.min.y << 16) | sr.min.x; - fifo[BltTopLeftDst/4] = (r.min.y << 16) | r.min.x; - fifo[BltWidthHeight/4] = (Dy(r) << 16) | Dx(r); - - waitforidle(scr); - - return 1; -} - -void -nvidiablank(VGAscr*, int blank) -{ - uchar seq1, crtc1A; - - seq1 = vgaxi(Seqx, 1) & ~0x20; - crtc1A = vgaxi(Crtx, 0x1A) & ~0xC0; - - if(blank){ - seq1 |= 0x20; -// crtc1A |= 0xC0; - crtc1A |= 0x80; - } - - vgaxo(Seqx, 1, seq1); - vgaxo(Crtx, 0x1A, crtc1A); -} - -static void -nvidiadrawinit(VGAscr *scr) -{ - ulong* fifo; - - fifo = KADDR(scr->io + Fifo); - - waitforfifo(scr, ClipFifo, 2); - - fifo[ClipTopLeft/4] = 0x0; - fifo[ClipWidthHeight/4] = 0x80008000; - - waitforfifo(scr, PattFifo, 5); - - fifo[PattShape/4] = 0; - fifo[PattColor0/4] = 0xffffffff; - fifo[PattColor1/4] = 0xffffffff; - fifo[PattMonochrome0/4] = 0xffffffff; - fifo[PattMonochrome1/4] = 0xffffffff; - - waitforfifo(scr, RopFifo, 1); - - fifo[RopRop3/4] = 0xCC; - - waitforidle(scr); - - scr->blank = nvidiablank; - hwblank = 1; - scr->fill = nvidiahwfill; - scr->scroll = nvidiahwscroll; -} - -VGAdev vganvidiadev = { - "nvidia", - - nvidiaenable, - nil, - nil, - nvidialinear, - nvidiadrawinit, -}; - -VGAcur vganvidiacur = { - "nvidiahwgc", - - nvidiacurenable, - nvidiacurdisable, - nvidiacurload, - nvidiacurmove, -}; diff --git a/os/pc/vgargb524.c b/os/pc/vgargb524.c deleted file mode 100644 index 89c2129d..00000000 --- a/os/pc/vgargb524.c +++ /dev/null @@ -1,236 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -/* - * IBM RGB524. - * 170/220MHz High Performance Palette DAC. - * - * Assumes hooked up to an S3 Vision96[48]. - */ -enum { - IndexLo = 0x00, - IndexHi = 0x01, - Data = 0x02, - IndexCtl = 0x03, -}; - -enum { /* index registers */ - CursorCtl = 0x30, - CursorXLo = 0x31, - CursorXHi = 0x32, - CursorYLo = 0x33, - CursorYHi = 0x34, - CursorHotX = 0x35, - CursorHotY = 0x36, - - CursorR1 = 0x40, - CursorG1 = 0x41, - CursorB1 = 0x42, - CursorR2 = 0x43, - CursorG2 = 0x44, - CursorB2 = 0x45, - CursorR3 = 0x46, - CursorG3 = 0x47, - CursorB3 = 0x48, - - CursorArray = 0x100, -}; - -/* - * Lower 2-bits of indirect DAC register - * addressing. - */ -static ushort dacxreg[4] = { - PaddrW, Pdata, Pixmask, PaddrR -}; - -static uchar -rgb524setrs2(void) -{ - uchar rs2; - - rs2 = vgaxi(Crtx, 0x55); - vgaxo(Crtx, 0x55, (rs2 & 0xFC)|0x01); - - return rs2; -} - -static void -rgb524xo(int index, uchar data) -{ - vgao(dacxreg[IndexLo], index & 0xFF); - vgao(dacxreg[IndexHi], (index>>8) & 0xFF); - vgao(dacxreg[Data], data); -} - -static void -rgb524disable(VGAscr*) -{ - uchar rs2; - - rs2 = rgb524setrs2(); - rgb524xo(CursorCtl, 0x00); - vgaxo(Crtx, 0x55, rs2); -} - -static void -rgb524enable(VGAscr*) -{ - uchar rs2; - - rs2 = rgb524setrs2(); - - /* - * Make sure cursor is off by initialising the cursor - * control to defaults. - */ - rgb524xo(CursorCtl, 0x00); - - /* - * Cursor colour 1 (white), - * cursor colour 2 (black). - */ - rgb524xo(CursorR1, Pwhite); rgb524xo(CursorG1, Pwhite); rgb524xo(CursorB1, Pwhite); - rgb524xo(CursorR2, Pblack); rgb524xo(CursorG2, Pblack); rgb524xo(CursorB2, Pblack); - - /* - * Enable the cursor, 32x32, mode 2. - */ - rgb524xo(CursorCtl, 0x23); - - vgaxo(Crtx, 0x55, rs2); -} - -static void -rgb524load(VGAscr*, Cursor* curs) -{ - uchar p, p0, p1, rs2; - int x, y; - - rs2 = rgb524setrs2(); - - /* - * Make sure cursor is off by initialising the cursor - * control to defaults. - */ - rgb524xo(CursorCtl, 0x00); - - /* - * Set auto-increment mode for index-register addressing - * and initialise the cursor array index. - */ - vgao(dacxreg[IndexCtl], 0x01); - vgao(dacxreg[IndexLo], CursorArray & 0xFF); - vgao(dacxreg[IndexHi], (CursorArray>>8) & 0xFF); - - /* - * Initialise the 32x32 cursor RAM array. There are 2 planes, - * p0 and p1. Data is written 4 pixels per byte, with p1 the - * MS bit of each pixel. - * The cursor is set in X-Windows mode which gives the following - * truth table: - * p1 p0 colour - * 0 0 underlying pixel colour - * 0 1 underlying pixel colour - * 1 0 cursor colour 1 - * 1 1 cursor colour 2 - * Put the cursor into the top-left of the 32x32 array. - */ - for(y = 0; y < 32; y++){ - for(x = 0; x < 32/8; x++){ - if(x < 16/8 && y < 16){ - p0 = curs->clr[x+y*2]; - p1 = curs->set[x+y*2]; - - p = 0x00; - if(p1 & 0x80) - p |= 0xC0; - else if(p0 & 0x80) - p |= 0x80; - if(p1 & 0x40) - p |= 0x30; - else if(p0 & 0x40) - p |= 0x20; - if(p1 & 0x20) - p |= 0x0C; - else if(p0 & 0x20) - p |= 0x08; - if(p1 & 0x10) - p |= 0x03; - else if(p0 & 0x10) - p |= 0x02; - vgao(dacxreg[Data], p); - - p = 0x00; - if(p1 & 0x08) - p |= 0xC0; - else if(p0 & 0x08) - p |= 0x80; - if(p1 & 0x04) - p |= 0x30; - else if(p0 & 0x04) - p |= 0x20; - if(p1 & 0x02) - p |= 0x0C; - else if(p0 & 0x02) - p |= 0x08; - if(p1 & 0x01) - p |= 0x03; - else if(p0 & 0x01) - p |= 0x02; - vgao(dacxreg[Data], p); - } - else{ - vgao(dacxreg[Data], 0x00); - vgao(dacxreg[Data], 0x00); - } - } - } - - /* - * Initialise the cursor hotpoint, - * enable the cursor and restore state. - */ - rgb524xo(CursorHotX, -curs->offset.x); - rgb524xo(CursorHotY, -curs->offset.y); - - rgb524xo(CursorCtl, 0x23); - - vgaxo(Crtx, 0x55, rs2); -} - -static int -rgb524move(VGAscr*, Point p) -{ - uchar rs2; - - rs2 = rgb524setrs2(); - - rgb524xo(CursorXLo, p.x & 0xFF); - rgb524xo(CursorXHi, (p.x>>8) & 0x0F); - rgb524xo(CursorYLo, p.y & 0xFF); - rgb524xo(CursorYHi, (p.y>>8) & 0x0F); - - vgaxo(Crtx, 0x55, rs2); - - return 0; -} - -VGAcur vgargb524cur = { - "rgb524hwgc", - - rgb524enable, - rgb524disable, - rgb524load, - rgb524move, -}; diff --git a/os/pc/vgas3.c b/os/pc/vgas3.c deleted file mode 100644 index b23657e6..00000000 --- a/os/pc/vgas3.c +++ /dev/null @@ -1,620 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -enum { - PCIS3 = 0x5333, /* PCI VID */ - - SAVAGE3D = 0x8A20, /* PCI DID */ - SAVAGE3DMV = 0x8A21, - SAVAGE4 = 0x8A22, - PROSAVAGEP = 0x8A25, - PROSAVAGEK = 0x8A26, - PROSAVAGE8 = 0x8D04, - SAVAGEMXMV = 0x8C10, - SAVAGEMX = 0x8C11, - SAVAGEIXMV = 0x8C12, - SAVAGEIX = 0x8C13, - SUPERSAVAGEIXC16 = 0x8C2E, - SAVAGE2000 = 0x9102, - - VIRGE = 0x5631, - VIRGEGX2 = 0x8A10, - VIRGEDXGX = 0x8A01, - VIRGEVX = 0x883D, - VIRGEMX = 0x8C01, - VIRGEMXP = 0x8C03, - - VIRTUALPC2004 = 0x8810, - AURORA64VPLUS = 0x8812, -}; - -static int -s3pageset(VGAscr* scr, int page) -{ - uchar crt35, crt51; - int opage; - - crt35 = vgaxi(Crtx, 0x35); - if(scr->gscreen->depth >= 8){ - /* - * The S3 registers need to be unlocked for this. - * Let's hope they are already: - * vgaxo(Crtx, 0x38, 0x48); - * vgaxo(Crtx, 0x39, 0xA0); - * - * The page is 6 bits, the lower 4 bits in Crt35<3:0>, - * the upper 2 in Crt51<3:2>. - */ - vgaxo(Crtx, 0x35, page & 0x0F); - crt51 = vgaxi(Crtx, 0x51); - vgaxo(Crtx, 0x51, (crt51 & ~0x0C)|((page & 0x30)>>2)); - opage = ((crt51 & 0x0C)<<2)|(crt35 & 0x0F); - } - else{ - vgaxo(Crtx, 0x35, (page<<2) & 0x0C); - opage = (crt35>>2) & 0x03; - } - - return opage; -} - -static void -s3page(VGAscr* scr, int page) -{ - int id; - - id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); - switch(id){ - - case VIRGEGX2: - break; - - default: - lock(&scr->devlock); - s3pageset(scr, page); - unlock(&scr->devlock); - break; - } -} - -static ulong -s3linear(VGAscr* scr, int* size, int* align) -{ - char *mmioname; - ulong aperture, oaperture, mmiobase, mmiosize; - int i, id, j, osize, oapsize, wasupamem; - Pcidev *p; - - osize = *size; - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - - mmiosize = 0; - mmiobase = 0; - mmioname = nil; - - /* - * S3 makes cards other than display controllers, so - * look for the first S3 display controller (device class 3) - * and not one of their sound cards. - */ - p = nil; - while(p = pcimatch(p, PCIS3, 0)){ - if(p->ccrb == 0x03) - break; - } - if(p != nil){ - for(i=0; imem); i++){ - if(p->mem[i].size >= *size - && ((p->mem[i].bar & ~0x0F) & (*align-1)) == 0) - break; - } - if(i >= nelem(p->mem)){ - print("vgas3: aperture not found\n"); - return 0; - } - aperture = p->mem[i].bar & ~0x0F; - *size = p->mem[i].size; - - id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); - switch(id){ /* find mmio */ - case SAVAGE4: - case PROSAVAGEP: - case PROSAVAGEK: - case PROSAVAGE8: - case SUPERSAVAGEIXC16: - /* - * We could assume that the MMIO registers - * will be in the screen segment and just use - * that, but PCI software is allowed to move them - * if it feels like it, so we look for an aperture of - * the right size; only the first 512k actually means - * anything. The S3 engineers overestimated how - * much space they would need in the first design. - */ - for(j=0; jmem); j++){ - if(i == j) - continue; - if(p->mem[j].size==512*1024 || p->mem[j].size==16*1024*1024){ - mmiobase = p->mem[j].bar & ~0x0F; - mmiosize = 512*1024; - scr->mmio = (ulong*)upamalloc(mmiobase, mmiosize, 0); - mmioname = "savagemmio"; - break; - } - } - if(mmiosize == 0){ - print("savage4: mmio not found\n"); - return 0; - } - } - }else - aperture = 0; - - if(wasupamem) - upafree(oaperture, oapsize); - scr->isupamem = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)) - scr->isupamem = 1; - } - else - scr->isupamem = 1; - - if(oaperture && oaperture != aperture) - print("warning (BUG): redefinition of aperture does not change s3screen segment\n"); - addvgaseg("s3screen", aperture, osize); - - if(mmiosize) - addvgaseg(mmioname, mmiobase, mmiosize); - - return aperture; -} - -static void -s3vsyncactive(void) -{ - /* - * Hardware cursor information is fetched from display memory - * during the horizontal blank active time. The 80x chips may hang - * if the cursor is turned on or off during this period. - */ - while((vgai(Status1) & 0x08) == 0) - ; -} - -static void -s3disable(VGAscr*) -{ - uchar crt45; - - /* - * Turn cursor off. - */ - crt45 = vgaxi(Crtx, 0x45) & 0xFE; - s3vsyncactive(); - vgaxo(Crtx, 0x45, crt45); -} - -static void -s3load(VGAscr* scr, Cursor* curs) -{ - uchar *p; - int id, dolock, opage, x, y; - - /* - * Disable the cursor and - * set the pointer to the two planes. - */ - s3disable(scr); - - opage = 0; - p = KADDR(scr->aperture); - id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); - switch(id){ - - case VIRTUALPC2004: - case VIRGE: - case VIRGEDXGX: - case VIRGEGX2: - case VIRGEVX: - case SAVAGEMXMV: - case SAVAGEIXMV: - case SAVAGE4: - case PROSAVAGEP: - case PROSAVAGEK: - case PROSAVAGE8: - case SUPERSAVAGEIXC16: - dolock = 0; - p += scr->storage; - break; - - default: - dolock = 1; - lock(&scr->devlock); - opage = s3pageset(scr, scr->storage>>16); - p += (scr->storage & 0xFFFF); - break; - } - - /* - * The cursor is set in Microsoft Windows format (the ViRGE/GX2 doesn't - * support the X11 format) which gives the following truth table: - * and xor colour - * 0 0 background colour - * 0 1 foreground colour - * 1 0 current screen pixel - * 1 1 NOT current screen pixel - * Put the cursor into the top-left of the 64x64 array. - * - * The cursor pattern in memory is interleaved words of - * AND and XOR patterns. - */ - for(y = 0; y < 64; y++){ - for(x = 0; x < 64/8; x += 2){ - if(x < 16/8 && y < 16){ - *p++ = ~(curs->clr[2*y + x]|curs->set[2*y + x]); - *p++ = ~(curs->clr[2*y + x+1]|curs->set[2*y + x+1]); - *p++ = curs->set[2*y + x]; - *p++ = curs->set[2*y + x+1]; - } - else { - *p++ = 0xFF; - *p++ = 0xFF; - *p++ = 0x00; - *p++ = 0x00; - } - } - } - - if(dolock){ - s3pageset(scr, opage); - unlock(&scr->devlock); - } - - /* - * Save the cursor hotpoint and enable the cursor. - */ - scr->offset = curs->offset; - s3vsyncactive(); - vgaxo(Crtx, 0x45, 0x01); -} - -static int -s3move(VGAscr* scr, Point p) -{ - int x, xo, y, yo; - - /* - * Mustn't position the cursor offscreen even partially, - * or it disappears. Therefore, if x or y is -ve, adjust the - * cursor offset instead. - * There seems to be a bug in that if the offset is 1, the - * cursor doesn't disappear off the left edge properly, so - * round it up to be even. - */ - if((x = p.x+scr->offset.x) < 0){ - xo = -x; - xo = ((xo+1)/2)*2; - x = 0; - } - else - xo = 0; - if((y = p.y+scr->offset.y) < 0){ - yo = -y; - y = 0; - } - else - yo = 0; - - vgaxo(Crtx, 0x46, (x>>8) & 0x07); - vgaxo(Crtx, 0x47, x & 0xFF); - vgaxo(Crtx, 0x49, y & 0xFF); - vgaxo(Crtx, 0x4E, xo); - vgaxo(Crtx, 0x4F, yo); - vgaxo(Crtx, 0x48, (y>>8) & 0x07); - - return 0; -} - -static void -s3enable(VGAscr* scr) -{ - int i; - ulong storage; - - s3disable(scr); - - /* - * Cursor colours. Set both the CR0[EF] and the colour - * stack in case we are using a 16-bit RAMDAC. - */ - vgaxo(Crtx, 0x0E, Pwhite); - vgaxo(Crtx, 0x0F, Pblack); - vgaxi(Crtx, 0x45); - - for(i = 0; i < 3; i++) - vgaxo(Crtx, 0x4A, Pblack); - vgaxi(Crtx, 0x45); - for(i = 0; i < 3; i++) - vgaxo(Crtx, 0x4B, Pwhite); - - /* - * Find a place for the cursor data in display memory. - * Must be on a 1024-byte boundary. - */ - storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024; - vgaxo(Crtx, 0x4C, storage>>8); - vgaxo(Crtx, 0x4D, storage & 0xFF); - storage *= 1024; - scr->storage = storage; - - /* - * Load, locate and enable the cursor - * in Microsoft Windows format. - */ - s3load(scr, &arrow); - s3move(scr, ZP); - vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55) & ~0x10); - s3vsyncactive(); - vgaxo(Crtx, 0x45, 0x01); -} - -/* - * The manual gives byte offsets, but we want ulong offsets, hence /4. - */ -enum { - SrcBase = 0xA4D4/4, - DstBase = 0xA4D8/4, - Stride = 0xA4E4/4, - FgrdData = 0xA4F4/4, - WidthHeight = 0xA504/4, - SrcXY = 0xA508/4, - DestXY = 0xA50C/4, - Command = 0xA500/4, - SubStat = 0x8504/4, - FifoStat = 0x850C/4, -}; - -/* - * Wait for writes to VGA memory via linear aperture to flush. - */ -enum {Maxloop = 1<<24}; -struct { - ulong linear; - ulong fifo; - ulong idle; - ulong lineartimeout; - ulong fifotimeout; - ulong idletimeout; -} waitcount; - -static void -waitforlinearfifo(VGAscr *scr) -{ - ulong *mmio; - long x; - static ulong nwaitforlinearfifo; - ulong mask, val; - - switch(scr->id){ - default: - panic("unknown scr->id in s3 waitforlinearfifo"); - case 0x8A01: /* ViRGE/[DG]X. XFree86 says no waiting necessary */ - return; - case 0x5631: /* ViRGE */ - case 0x883D: /* ViRGE/VX */ - mask = 0x0F<<6; - val = 0x08<<6; - break; - case 0x8A10: /* ViRGE/GX2 */ - mask = 0x1F<<6; - val = 0x10<<6; - break; - } - mmio = scr->mmio; - x = 0; - while((mmio[FifoStat]&mask) != val && x++ < Maxloop) - waitcount.linear++; - if(x >= Maxloop) - waitcount.lineartimeout++; -} - -static void -waitforfifo(VGAscr *scr, int entries) -{ - ulong *mmio; - long x; - static ulong nwaitforfifo; - - mmio = scr->mmio; - x = 0; - while((mmio[SubStat]&0x1F00) < ((entries+2)<<8) && x++ < Maxloop) - waitcount.fifo++; - if(x >= Maxloop) - waitcount.fifotimeout++; -} - -static void -waitforidle(VGAscr *scr) -{ - ulong *mmio; - long x; - - mmio = scr->mmio; - x = 0; - while((mmio[SubStat]&0x3F00) != 0x3000 && x++ < Maxloop) - waitcount.idle++; - if(x >= Maxloop) - waitcount.idletimeout++; -} - -static int -hwscroll(VGAscr *scr, Rectangle r, Rectangle sr) -{ - enum { Bitbltop = 0xCC }; /* copy source */ - ulong *mmio; - ulong cmd, stride; - Point dp, sp; - int did, d; - - d = scr->gscreen->depth; - did = (d-8)/8; - cmd = 0x00000020|(Bitbltop<<17)|(did<<2); - stride = Dx(scr->gscreen->r)*d/8; - - if(r.min.x <= sr.min.x){ - cmd |= 1<<25; - dp.x = r.min.x; - sp.x = sr.min.x; - }else{ - dp.x = r.max.x-1; - sp.x = sr.max.x-1; - } - - if(r.min.y <= sr.min.y){ - cmd |= 1<<26; - dp.y = r.min.y; - sp.y = sr.min.y; - }else{ - dp.y = r.max.y-1; - sp.y = sr.max.y-1; - } - - mmio = scr->mmio; - waitforlinearfifo(scr); - waitforfifo(scr, 7); - mmio[SrcBase] = scr->aperture; - mmio[DstBase] = scr->aperture; - mmio[Stride] = (stride<<16)|stride; - mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r); - mmio[SrcXY] = (sp.x<<16)|sp.y; - mmio[DestXY] = (dp.x<<16)|dp.y; - mmio[Command] = cmd; - waitforidle(scr); - return 1; -} - -static int -hwfill(VGAscr *scr, Rectangle r, ulong sval) -{ - enum { Bitbltop = 0xCC }; /* copy source */ - ulong *mmio; - ulong cmd, stride; - int did, d; - - d = scr->gscreen->depth; - did = (d-8)/8; - cmd = 0x16000120|(Bitbltop<<17)|(did<<2); - stride = Dx(scr->gscreen->r)*d/8; - mmio = scr->mmio; - waitforlinearfifo(scr); - waitforfifo(scr, 8); - mmio[SrcBase] = scr->aperture; - mmio[DstBase] = scr->aperture; - mmio[DstBase] = scr->aperture; - mmio[Stride] = (stride<<16)|stride; - mmio[FgrdData] = sval; - mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r); - mmio[DestXY] = (r.min.x<<16)|r.min.y; - mmio[Command] = cmd; - waitforidle(scr); - return 1; -} - -enum { - CursorSyncCtl = 0x0D, /* in Seqx */ - VsyncHi = 0x80, - VsyncLo = 0x40, - HsyncHi = 0x20, - HsyncLo = 0x10, -}; - -static void -s3blank(VGAscr*, int blank) -{ - uchar x; - - x = vgaxi(Seqx, CursorSyncCtl); - x &= ~0xF0; - if(blank) - x |= VsyncLo | HsyncLo; - vgaxo(Seqx, CursorSyncCtl, x); -} - -static void -s3drawinit(VGAscr *scr) -{ - extern void savageinit(VGAscr*); /* vgasavage.c */ - ulong id; - - id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); - scr->id = id; - - /* - * It's highly likely that other ViRGEs will work without - * change to the driver, with the exception of the size of - * the linear aperture memory write FIFO. Since we don't - * know that size, I'm not turning them on. See waitforlinearfifo - * above. - */ - scr->blank = s3blank; - /* hwblank = 1; not known to work well */ - - switch(id){ - case VIRGE: - case VIRGEVX: - case VIRGEGX2: - scr->mmio = (ulong*)(scr->aperture+0x1000000); - scr->fill = hwfill; - scr->scroll = hwscroll; - break; - case SAVAGEMXMV: - case SAVAGEIXMV: - scr->mmio = (ulong*)(scr->aperture+0x1000000); - savageinit(scr); - break; - case SUPERSAVAGEIXC16: - case SAVAGE4: - case PROSAVAGEP: - case PROSAVAGE8: - case PROSAVAGEK: - /* scr->mmio is set by s3linear */ - savageinit(scr); - break; - } -} - -VGAdev vgas3dev = { - "s3", - - 0, - 0, - s3page, - s3linear, - s3drawinit, -}; - -VGAcur vgas3cur = { - "s3hwgc", - - s3enable, - s3disable, - s3load, - s3move, -}; - diff --git a/os/pc/vgasavage.c b/os/pc/vgasavage.c deleted file mode 100644 index 263b688b..00000000 --- a/os/pc/vgasavage.c +++ /dev/null @@ -1,571 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -enum { - PCIS3 = 0x5333, /* PCI VID */ - - SAVAGE3D = 0x8A20, /* PCI DID */ - SAVAGE3DMV = 0x8A21, - SAVAGE4 = 0x8A22, - PROSAVAGEP = 0x8A25, - PROSAVAGEK = 0x8A26, - PROSAVAGE8 = 0x8D04, - SAVAGEMXMV = 0x8C10, - SAVAGEMX = 0x8C11, - SAVAGEIXMV = 0x8C12, - SAVAGEIX = 0x8C13, - SUPERSAVAGEIXC16 = 0x8C2E, - SAVAGE2000 = 0x9102, - - VIRGE = 0x5631, - VIRGEGX2 = 0x8A10, - VIRGEDXGX = 0x8A01, - VIRGEVX = 0x883D, - VIRGEMX = 0x8C01, - VIRGEMXP = 0x8C03, - - AURORA64VPLUS = 0x8812, -}; - -/* - * Savage4 et al. acceleration. - * - * This is based only on the Savage4 documentation. - * It is expected to work on other Savage cards as well, - * but has not been tried. - * - * There are five ways to access the 2D graphics engine registers: - * - Old MMIO non-packed format - * - Old MMIO packed format - * - New MMIO non-packed format - * - New MMIO packed format - * - Burst Command Interface (BCI) - * - * Of these, the manual hints that the first three are deprecated, - * and it does not document any of those three well enough to use. - * - * I have tried for many hours with no success to understand the BCI - * interface well enough to use it. It is not well documented, and the - * XFree86 driver seems to completely contradict what little documentation - * there is. - * - * This leaves the packed new MMIO. - * The manual contradicts itself here, claming that the registers - * start at 0x2008100 as well as at 0x0008100 from the base of the - * mmio segment. Since the segment is only 512k, we assume that - * the latter is the correct offset. - * - * According to the manual, only 16-bit reads of the 2D registers - * are supported: 32-bit reads will return garbage in the upper word. - * 32-bit writes must be enabled explicitly. - * - * 32-bit reads of the status registers seem just fine. - */ - -/* 2D graphics engine registers for Savage4; others appear to be mostly the same */ -enum { - SubsystemStatus = 0x8504, /* Subsystem Status: read only */ - /* read only: whether we get interrupts on various events */ - VsyncInt = 1<<0, /* vertical sync */ - GeBusyInt = 1<<1, /* 2D graphics engine busy */ - BfifoFullInt = 1<<2, /* BIU FIFO full */ - BfifoEmptyInt = 1<<3, /* BIU FIFO empty */ - CfifoFullInt = 1<<4, /* command FIFO full */ - CfifoEmptyInt = 1<<5, /* command FIFO empty */ - BciInt = 1<<6, /* BCI */ - LpbInt = 1<<7, /* LPB */ - CbHiInt = 1<<16, /* COB upper threshold */ - CbLoInt = 1<<17, /* COB lower threshold */ - - SubsystemCtl = 0x8504, /* Subsystem Control: write only */ - /* clear interrupts for various events */ - VsyncClr = 1<<0, - GeBusyClr = 1<<1, - BfifoFullClr = 1<<2, - BfifoEmptyClr = 1<<3, - CfifoFullClr = 1<<4, - CfifoEmptyClr = 1<<5, - BciClr = 1<<6, - LpbClr = 1<<7, - CbHiClr = 1<<16, - CbLoClr = 1<<17, - - /* enable interrupts for various events */ - VsyncEna = 1<<8, - Busy2DEna = 1<<9, - BfifoFullEna = 1<<10, - BfifoEmptyEna = 1<<11, - CfifoFullEna = 1<<12, - CfifoEmptyEna = 1<<13, - SubsysBciEna = 1<<14, - CbHiEna = 1<<24, - CbLoEna = 1<<25, - - /* 2D graphics engine software reset */ - GeSoftReset = 1<<15, - - FifoStatus = 0x8508, /* FIFO status: read only */ - CwbEmpty = 1<<0, /* command write buffer empty */ - CrbEmpty = 1<<1, /* command read buffer empty */ - CobEmpty = 1<<2, /* command overflow buffer empty */ - CfifoEmpty = 1<<3, /* command FIFO empty */ - CwbFull = 1<<8, /* command write buffer full */ - CrbFull = 1<<9, /* command read buffer full */ - CobFull = 1<<10, /* command overflow buffer full */ - CfifoFull = 1<<11, /* command FIFO full */ - - AdvFunCtl = 0x850C, /* Advanced Function Control: read/write */ - GeEna = 1<<0, /* enable 2D/3D engine */ - /* - * according to the manual, BigPixel should be - * set when bpp >= 8 (bpp != 4), and then CR50_5-4 are - * used to figure out bpp example. however, it does bad things - * to the screen in 8bpp mode. - */ - BigPixel = 1<<2, /* 8 or more bpp enhanced mode */ - LaEna = 1<<3, /* linear addressing ena: or'ed with CR58_4 */ - Mclk_2 = 0<<8, /* 2D engine clock divide: MCLK/2 */ - Mclk_4 = 1<<8, /* " MCLK/4 */ - Mclk = 2<<8, /* " MCLK */ - /* Mclk = 3<<8, /* " MCLK */ - Ic33mhz = 1<<16, /* Internal clock 33 MHz (instead of 66) */ - - WakeupReg = 0x8510, /* Wakeup: read/write */ - WakeupBit = 1<<0, /* wake up: or'ed with 3C3_0 */ - - SourceY = 0x8100, /* UL corner of bitblt source */ - SourceX = 0x8102, /* " */ - RectY = 0x8100, /* UL corner of rectangle fill */ - RectX = 0x8102, /* " */ - DestY = 0x8108, /* UL corner of bitblt dest */ - DestX = 0x810A, /* " */ - Height = 0x8148, /* bitblt, image xfer rectangle height */ - Width = 0x814A, /* bitblt, image xfer rectangle width */ - - StartY = 0x8100, /* Line draw: first point*/ - StartX = 0x8102, /* " */ - /* - * For line draws, the following must be programmed: - * axial step constant = 2*min(|dx|,|dy|) - * diagonal step constant = 2*[min(|dx|,|dy|) - max(|dx|,|dy|)] - * error term = 2*min(|dx|,|dy|) - max(|dx|,|dy| - 1 - * [sic] when start X < end X - * error term = 2*min(|dx|,|dy|) - max(|dx|,|dy| - * [sic] when start X >= end X - */ - AxialStep = 0x8108, - DiagonalStep = 0x810A, - LineError = 0x8110, - MinorLength = 0x8148, /* pixel count along minor axis */ - MajorLength = 0x814A, /* pixel count along major axis */ - - DrawCmd = 0x8118, /* Drawing Command: write only */ - CmdMagic = 0<<1, - AcrossPlane = 1<<1, /* across the plane mode */ - LastPixelOff = 1<<2, /* last pixel of line or vector draw not drawn */ - Radial = 1<<3, /* enable radial direction (else axial) */ - DoDraw = 1<<4, /* draw pixels (else only move current pos) */ - - DrawRight = 1<<5, /* axial drawing direction: left to right */ - /* DrawLeft = 0<<5, */ - MajorY = 1<<6, - /* MajorX = 0<<6, */ - DrawDown = 1<<7, - /* DrawUp = 0<<7, */ - Degree0 = 0<<5, /* drawing direction when Radial */ - Degree45 = 1<<5, - /* ... */ - Degree315 = 7<<5, - - UseCPUData = 1<<8, - - /* image write bus transfer width */ - Bus8 = 0<<9, - Bus16 = 1<<9, - /* - * in Bus32 mode, doubleword bits beyond the image rect width are - * discarded. each line starts on a new doubleword. - * Bus32AP is intended for across-the-plane mode and - * rounds to byte boundaries instead. - */ - Bus32 = 2<<9, - Bus32AP = 3<<9, - - CmdNop = 0<<13, /* nop */ - CmdLine = 1<<13, /* draw line */ - CmdFill = 2<<13, /* fill rectangle */ - CmdBitblt = 6<<13, /* bitblt */ - CmdPatblt = 7<<13, /* 8x8 pattern blt */ - - SrcGBD = 0<<16, - SrcPBD = 1<<16, - SrcSBD = 2<<16, - - DstGBD = 0<<18, - DstPBD = 1<<18, - DstSBD = 2<<18, - - /* color sources, controls */ - BgColor = 0x8120, /* Background Color: read/write */ - FgColor = 0x8124, /* Foreground Color: read/write */ - BitplaneWmask = 0x8128, /* Bitplane Write Mask: read/write */ - BitplaneRmask = 0x812C, /* Bitplane Read Mask: read/write */ - CmpColor = 0x8130, /* Color Compare: read/write */ - BgMix = 0x8134, - FgMix = 0x8136, - MixNew = 7, - SrcBg = 0<<5, - SrcFg = 1<<5, - SrcCPU = 2<<5, - SrcDisp = 3<<5, - - /* clipping rectangle */ - TopScissors = 0x8138, /* Top Scissors: write only */ - LeftScissors = 0x813A, /* Left Scissors: write only */ - BottomScissors = 0x813C, /* Bottom Scissors: write only */ - RightScissors = 0x813E, /* Right Scissors: write only */ - - /* - * Registers with Magic were indirectly accessed in older modes. - * It is not clear whether the Magic is necessary. - * In the older modes, writes to these registers were pipelined, - * so that you had to issue an engine command and wait for engine - * idle before reading a write back. It is not clear if this is - * still the case either. - */ - PixCtl = 0x8140, /* Pixel Control: write only */ - PixMagic = 0xA<<12, - PixMixFg = 0<<6, /* foreground mix register always */ - PixMixCPU = 2<<6, /* CPU data determines mix register */ - PixMixDisp = 3<<6, /* display data determines mix register */ - - MfMisc2Ctl = 0x8142, /* Multifunction Control Misc. 2: write only */ - MfMisc2Magic = 0xD<<12, - DstShift = 0, /* 3 bits: destination base address in MB */ - SrcShift = 4, /* 3 bits: source base address in MB */ - WaitFifoEmpty = 2<<8, /* wait for write FIFO empty between draws */ - - MfMiscCtl = 0x8144, /* Multifunction Control Misc: write only */ - MfMiscMagic = 0xE<<12, - UseHighBits = 1<<4, /* select upper 16 bits for 32-bit reg access */ - ClipInvert = 1<<5, /* only touch pixels outside clip rectangle */ - SkipSame = 0<<6, /* ignore pixels with color CmpColor */ - SkipDifferent = 1<<7, /* ignore pixels not color CmpColor */ - CmpEna = 1<<8, /* enable color compare */ - W32Ena = 1<<9, /* enable 32-bit register write */ - ClipDis = 1<<11, /* disable clipping */ - - /* - * The bitmap descriptor 1 registers contain the starting - * address of the bitmap (in bytes). - * The bitmap descriptor 2 registesr contain stride (in pixels) - * in the lower 16 bits, depth (in bits) in the next 8 bits, - * and whether block write is disabled. - */ - GBD1 = 0x8168, /* Global Bitmap Descriptor 1: read/write */ - GBD2 = 0x816C, /* Global Bitmap Descriptor 2: read/write */ - /* GBD2-only bits */ - BDS64 = 1<<0, /* bitmap descriptor size 64 bits */ - GBDBciEna = 1<<3, /* BCI enable */ - /* generic BD2 bits */ - BlockWriteDis = 1<<28, - StrideShift = 0, - DepthShift = 16, - - PBD1 = 0x8170, /* Primary Bitmap Descriptor: read/write */ - PBD2 = 0x8174, - SBD1 = 0x8178, /* Secondary Bitmap Descriptor: read/write */ - SBD2 = 0x817C, -}; - -/* mastered data transfer registers */ - -/* configuration/status registers */ -enum { - XStatus0 = 0x48C00, /* Status Word 0: read only */ - /* rev. A silicon differs from rev. B; use AltStatus0 */ - CBEMaskA = 0x1FFFF, /* filled command buffer entries */ - CBEShiftA = 0, - BciIdleA = 1<<17, /* BCI idle */ - Ge3IdleA = 1<<18, /* 3D engine idle */ - Ge2IdleA = 1<<19, /* 2D engine idle */ - McpIdleA = 1<<20, /* motion compensation processor idle */ - MeIdleA = 1<<22, /* master engine idle */ - PfPendA = 1<<23, /* page flip pending */ - - CBEMaskB = 0x1FFFFF, - CBEShiftB = 0, - BciIdleB = 1<<25, - Ge3IdleB = 1<<26, - Ge2IdleB = 1<<27, - McpIdleB = 1<<28, - MeIdleB = 1<<30, - PfPendB = 1<<31, - - AltStatus0 = 0x48C60, /* Alternate Status Word 0: read only */ - CBEMask = 0x1FFFF, - CBEShift = 0, - /* the Savage4 manual says bits 17..23 for these, like Status0 */ - /* empirically, they are bits 21..26 */ - BciIdle = 1<<21, - Ge3Idle = 1<<22, - Ge2Idle = 1<<23, - McpIdle = 1<<24, - MeIdle = 1<<25, - PfPend = 1<<26, - - XStatus1 = 0x48C04, /* Status Word 1: read only */ - /* contains event tag 1, event tag 0, both 16 bits */ - - XStatus2 = 0x48C08, /* Status Word 2: read only */ - ScanMask = 0x3FF, /* current scan line */ - ScanShift = 0, - VRTMask = 0x7F100, /* vert retrace count */ - VRTShift = 11, - - CbThresh = 0x48C10, /* Command Buffer Thresholds: read/write */ - CobOff = 0x48C14, /* Command Overflow Buffer: read/write */ - - CobPtr = 0x48C18, /* Command Overflow Buffer Pointers: read/write */ - CobEna = 1<<2, /* command overflow buffer enable */ - CobBciEna = 1<<3, /* BCI function enable */ - CbeMask = 0xFFFF8000, /* no. of entries in command buffer */ - CbeShift = 15, - - AltStatus1 = 0x48C64, /* Alternate Status Word 1: read onnly */ - /* contains current texture surface tag, vertex buffer tag */ - -}; - -struct { - ulong idletimeout; - ulong tostatw[16]; -} savagestats; - -enum { - Maxloop = 1<<20 -}; - -static void -savagewaitidle(VGAscr *scr) -{ - long x; - ulong *statw, mask, goal; - - switch(scr->id){ - case SAVAGE4: - case PROSAVAGEP: - case PROSAVAGEK: - case PROSAVAGE8: - /* wait for engine idle and FIFO empty */ - statw = (ulong*)((uchar*)scr->mmio+AltStatus0); - mask = CBEMask | Ge2Idle; - goal = Ge2Idle; - break; - /* case SAVAGEMXMV: ? */ - /* case SAVAGEMX: ? */ - /* case SAVAGEIX: ? */ - case SUPERSAVAGEIXC16: - case SAVAGEIXMV: - case SAVAGEMXMV: - /* wait for engine idle and FIFO empty */ - statw = (ulong*)((uchar*)scr->mmio+XStatus0); - mask = CBEMaskA | Ge2IdleA; - goal = Ge2IdleA; - break; - default: - /* - * best we can do: can't print or we'll call ourselves. - * savageinit is supposed to not let this happen. - */ - return; - } - - for(x=0; xmmio; - - *(ulong*)(mmio+FgColor) = sval; - *(ulong*)(mmio+BgColor) = sval; - *(ulong*)(mmio+BgMix) = SrcFg|MixNew; - *(ulong*)(mmio+FgMix) = SrcFg|MixNew; - *(ushort*)(mmio+RectY) = r.min.y; - *(ushort*)(mmio+RectX) = r.min.x; - *(ushort*)(mmio+Width) = Dx(r)-1; - *(ushort*)(mmio+Height) = Dy(r)-1; - *(ulong*)(mmio+DrawCmd) = CmdMagic | DoDraw | CmdFill | DrawRight | DrawDown; - savagewaitidle(scr); - return 1; -} - -static int -savagescroll(VGAscr *scr, Rectangle r, Rectangle sr) -{ - uchar *mmio; - ulong cmd; - Point dp, sp; - - cmd = CmdMagic | DoDraw | CmdBitblt | SrcPBD | DstGBD; - - if(r.min.x <= sr.min.x){ - cmd |= DrawRight; - dp.x = r.min.x; - sp.x = sr.min.x; - }else{ - dp.x = r.max.x-1; - sp.x = sr.max.x-1; - } - - if(r.min.y <= sr.min.y){ - cmd |= DrawDown; - dp.y = r.min.y; - sp.y = sr.min.y; - }else{ - dp.y = r.max.y-1; - sp.y = sr.max.y-1; - } - - mmio = (uchar*)scr->mmio; - - *(ushort*)(mmio+SourceX) = sp.x; - *(ushort*)(mmio+SourceY) = sp.y; - *(ushort*)(mmio+DestX) = dp.x; - *(ushort*)(mmio+DestY) = dp.y; - *(ushort*)(mmio+Width) = Dx(r)-1; - *(ushort*)(mmio+Height) = Dy(r)-1; - *(ulong*)(mmio+BgMix) = SrcDisp|MixNew; - *(ulong*)(mmio+FgMix) = SrcDisp|MixNew; - *(ulong*)(mmio+DrawCmd) = cmd; - savagewaitidle(scr); - return 1; -} - -static void -savageblank(VGAscr*, int blank) -{ - uchar seqD; - - /* - * Will handle DPMS to monitor - */ - vgaxo(Seqx, 8, vgaxi(Seqx,8)|0x06); - seqD = vgaxi(Seqx, 0xD); - seqD &= 0x03; - if(blank) - seqD |= 0x50; - vgaxo(Seqx, 0xD, seqD); - - /* - * Will handle LCD - */ - if(blank) - vgaxo(Seqx, 0x31, vgaxi(Seqx, 0x31) & ~0x10); - else - vgaxo(Seqx, 0x31, vgaxi(Seqx, 0x31) | 0x10); -} - - -void -savageinit(VGAscr *scr) -{ - uchar *mmio; - ulong bd; - - /* if you add chip IDs here be sure to update savagewaitidle */ - switch(scr->id){ - case SAVAGE4: - case PROSAVAGEP: - case PROSAVAGEK: - case PROSAVAGE8: - case SAVAGEIXMV: - case SUPERSAVAGEIXC16: - case SAVAGEMXMV: - break; - default: - print("unknown savage %.4lux\n", scr->id); - return; - } - - mmio = (uchar*)scr->mmio; - if(mmio == nil) { - print("savageinit: no mmio\n"); - return; - } - - /* 2D graphics engine software reset */ - *(ushort*)(mmio+SubsystemCtl) = GeSoftReset; - delay(2); - *(ushort*)(mmio+SubsystemCtl) = 0; - savagewaitidle(scr); - - /* disable BCI as much as possible */ - *(ushort*)(mmio+CobPtr) &= ~CobBciEna; - *(ushort*)(mmio+GBD2) &= ~GBDBciEna; - savagewaitidle(scr); - - /* enable 32-bit writes, disable clipping */ - *(ushort*)(mmio+MfMiscCtl) = MfMiscMagic|W32Ena|ClipDis; - savagewaitidle(scr); - - /* enable all read, write planes */ - *(ulong*)(mmio+BitplaneRmask) = ~0; - *(ulong*)(mmio+BitplaneWmask) = ~0; - savagewaitidle(scr); - - /* turn on linear access, 2D engine */ - *(ulong*)(mmio+AdvFunCtl) |= GeEna|LaEna; - savagewaitidle(scr); - - /* set bitmap descriptors */ - bd = (scr->gscreen->depth<gscreen->r)<>16; - savagewaitidle(scr); - - scr->fill = savagefill; - scr->scroll = savagescroll; - scr->blank = savageblank; - hwblank = 0; -} diff --git a/os/pc/vgat2r4.c b/os/pc/vgat2r4.c deleted file mode 100644 index b8003b87..00000000 --- a/os/pc/vgat2r4.c +++ /dev/null @@ -1,586 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -/* - * #9 Ticket to Ride IV. - */ -enum { - IndexLo = 0x10/4, - IndexHi = 0x14/4, - Data = 0x18/4, - IndexCtl = 0x1C/4, - - Zoom = 0x54/4, -}; - -enum { /* index registers */ - CursorSyncCtl = 0x03, - HsyncHi = 0x01, - HsyncLo = 0x02, - VsyncHi = 0x04, - VsyncLo = 0x08, - - CursorCtl = 0x30, - CursorXLo = 0x31, - CursorXHi = 0x32, - CursorYLo = 0x33, - CursorYHi = 0x34, - CursorHotX = 0x35, - CursorHotY = 0x36, - - CursorR1 = 0x40, - CursorG1 = 0x41, - CursorB1 = 0x42, - CursorR2 = 0x43, - CursorG2 = 0x44, - CursorB2 = 0x45, - CursorR3 = 0x46, - CursorG3 = 0x47, - CursorB3 = 0x48, - - CursorArray = 0x100, - - CursorMode32x32 = 0x23, - CursorMode64x64 = 0x27, - CursorMode = CursorMode32x32, -}; - -static ulong -t2r4linear(VGAscr* scr, int* size, int* align) -{ - ulong aperture, oaperture; - int oapsize, wasupamem; - Pcidev *p; - - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - - aperture = 0; - if(p = pcimatch(nil, 0x105D, 0)){ - switch(p->did){ - case 0x5348: - aperture = p->mem[0].bar & ~0x0F; - *size = p->mem[0].size; - break; - default: - break; - } - } - - if(wasupamem){ - if(oaperture == aperture) - return oaperture; - upafree(oaperture, oapsize); - } - scr->isupamem = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)){ - aperture = oaperture; - scr->isupamem = 1; - } - else - scr->isupamem = 0; - } - else - scr->isupamem = 1; - - return aperture; -} - -static void -t2r4enable(VGAscr* scr) -{ - Pcidev *p; - int size, align; - ulong aperture, mmio; - - /* - * Only once, can't be disabled for now. - * scr->mmio holds the virtual address of - * the MMIO registers. - */ - if(scr->mmio) - return; - if(p = pcimatch(nil, 0x105D, 0)){ - switch(p->did){ - case 0x5348: - break; - default: - return; - } - } - else - return; - mmio = upamalloc(p->mem[4].bar & ~0x0F, p->mem[4].size, 0); - if(mmio == 0) - return; - addvgaseg("t2r4mmio", mmio, p->mem[4].size); - - scr->mmio = KADDR(mmio); - - size = p->mem[0].size; - align = 0; - aperture = t2r4linear(scr, &size, &align); - if(aperture){ - scr->aperture = aperture; - scr->apsize = size; - addvgaseg("t2r4screen", aperture, size); - } -} - -static uchar -t2r4xi(VGAscr* scr, int index) -{ - ulong *mmio; - - mmio = scr->mmio; - mmio[IndexLo] = index & 0xFF; - mmio[IndexHi] = (index>>8) & 0xFF; - - return mmio[Data]; -} - -static void -t2r4xo(VGAscr* scr, int index, uchar data) -{ - ulong *mmio; - - mmio = scr->mmio; - mmio[IndexLo] = index & 0xFF; - mmio[IndexHi] = (index>>8) & 0xFF; - - mmio[Data] = data; -} - -static void -t2r4curdisable(VGAscr* scr) -{ - if(scr->mmio == 0) - return; - t2r4xo(scr, CursorCtl, 0x00); -} - -static void -t2r4curload(VGAscr* scr, Cursor* curs) -{ - uchar *data; - int size, x, y, zoom; - ulong clr, *mmio, pixels, set; - - mmio = scr->mmio; - if(mmio == 0) - return; - - /* - * Make sure cursor is off by initialising the cursor - * control to defaults. - */ - t2r4xo(scr, CursorCtl, 0x00); - - /* - * Set auto-increment mode for index-register addressing - * and initialise the cursor array index. - */ - mmio[IndexCtl] = 0x01; - mmio[IndexLo] = CursorArray & 0xFF; - mmio[IndexHi] = (CursorArray>>8) & 0xFF; - - /* - * Initialise the cursor RAM array. There are 2 planes, - * p0 and p1. Data is written 4 pixels per byte, with p1 the - * MS bit of each pixel. - * The cursor is set in X-Windows mode which gives the following - * truth table: - * p1 p0 colour - * 0 0 underlying pixel colour - * 0 1 underlying pixel colour - * 1 0 cursor colour 1 - * 1 1 cursor colour 2 - * Put the cursor into the top-left of the array. - * - * Although this looks a lot like the IBM RGB524 cursor, the - * scanlines appear to be twice as long as they should be and - * some of the other features are missing. - */ - if(mmio[Zoom] & 0x0F) - zoom = 32; - else - zoom = 16; - data = (uchar*)&mmio[Data]; - for(y = 0; y < zoom; y++){ - clr = (curs->clr[2*y]<<8)|curs->clr[y*2 + 1]; - set = (curs->set[2*y]<<8)|curs->set[y*2 + 1]; - pixels = 0; - for(x = 0; x < 16; x++){ - if(set & (1<>24; - *data = pixels>>16; - *data = pixels>>8; - *data = pixels; - - *data = 0x00; - *data = 0x00; - *data = 0x00; - *data = 0x00; - - if(CursorMode == CursorMode32x32 && zoom == 16) - continue; - *data = pixels>>24; - *data = pixels>>16; - *data = pixels>>8; - *data = pixels; - - *data = 0x00; - *data = 0x00; - *data = 0x00; - *data = 0x00; - } - if(CursorMode == CursorMode32x32) - size = 32; - else - size = 64; - while(y < size){ - for(x = 0; x < size/8; x++){ - *data = 0x00; - *data = 0x00; - } - y++; - } - mmio[IndexCtl] = 0x00; - - /* - * Initialise the hotpoint and enable the cursor. - */ - t2r4xo(scr, CursorHotX, -curs->offset.x); - zoom = (scr->mmio[Zoom] & 0x0F)+1; - t2r4xo(scr, CursorHotY, -curs->offset.y*zoom); - - t2r4xo(scr, CursorCtl, CursorMode); -} - -static int -t2r4curmove(VGAscr* scr, Point p) -{ - int y, zoom; - - if(scr->mmio == 0) - return 1; - - t2r4xo(scr, CursorXLo, p.x & 0xFF); - t2r4xo(scr, CursorXHi, (p.x>>8) & 0x0F); - - zoom = (scr->mmio[Zoom] & 0x0F)+1; - y = p.y*zoom; - t2r4xo(scr, CursorYLo, y & 0xFF); - t2r4xo(scr, CursorYHi, (y>>8) & 0x0F); - - return 0; -} - -static void -t2r4curenable(VGAscr* scr) -{ - t2r4enable(scr); - if(scr->mmio == 0) - return; - - /* - * Make sure cursor is off by initialising the cursor - * control to defaults. - */ - t2r4xo(scr, CursorCtl, 0x00); - - /* - * Cursor colour 1 (white), - * cursor colour 2 (black). - */ - t2r4xo(scr, CursorR1, Pwhite); - t2r4xo(scr, CursorG1, Pwhite); - t2r4xo(scr, CursorB1, Pwhite); - - t2r4xo(scr, CursorR2, Pblack); - t2r4xo(scr, CursorG2, Pblack); - t2r4xo(scr, CursorB2, Pblack); - - /* - * Load, locate and enable the cursor, 64x64, mode 2. - */ - t2r4curload(scr, &arrow); - t2r4curmove(scr, ZP); - t2r4xo(scr, CursorCtl, CursorMode); -} - -enum { - Flow = 0x08/4, - Busy = 0x0C/4, - BufCtl = 0x20/4, - DeSorg = 0x28/4, - DeDorg = 0x2C/4, - DeSptch = 0x40/4, - DeDptch = 0x44/4, - CmdOpc = 0x50/4, - CmdRop = 0x54/4, - CmdStyle = 0x58/4, - CmdPatrn = 0x5C/4, - CmdClp = 0x60/4, - CmdPf = 0x64/4, - Fore = 0x68/4, - Back = 0x6C/4, - Mask = 0x70/4, - DeKey = 0x74/4, - Lpat = 0x78/4, - Pctrl = 0x7C/4, - Clptl = 0x80/4, - Clpbr = 0x84/4, - XY0 = 0x88/4, - XY1 = 0x8C/4, - XY2 = 0x90/4, - XY3 = 0x94/4, - XY4 = 0x98/4, - Alpha = 0x128/4, - ACtl = 0x16C/4, - - RBaseD = 0x4000/4, -}; - -/* wait until pipeline ready for new command */ -static void -waitforfifo(VGAscr *scr) -{ - int x; - ulong *d; - x = 0; - - d = scr->mmio + RBaseD; - while((d[Busy]&1) && x++ < 1000000) - ; - if(x >= 1000000) /* shouldn't happen */ - iprint("busy %8lux\n", d[Busy]); -} - -/* wait until command has finished executing */ -static void -waitforcmd(VGAscr *scr) -{ - int x; - ulong *d; - x = 0; - - d = scr->mmio + RBaseD; - while((d[Flow]&0x1B) && x++ < 1000000) - ; - if(x >= 1000000) /* shouldn't happen */ - iprint("flow %8lux\n", d[Flow]); -} - -/* wait until memory controller not busy (i.e. wait for writes to flush) */ -static void -waitformem(VGAscr *scr) -{ - int x; - ulong *d; - x = 0; - - d = scr->mmio + RBaseD; - while((d[Flow]&2)&& x++ < 1000000) - ; - if(x >= 1000000) /* shouldn't happen */ - iprint("mem %8lux\n", d[Busy]); -} - -static int -t2r4hwscroll(VGAscr *scr, Rectangle r, Rectangle sr) -{ - int ctl; - Point dp, sp; - ulong *d; - int depth; - - if(r.min.y == sr.min.y){ /* a purely horizontal scroll */ - depth = scr->gscreen->depth; - switch(depth){ - case 32: - /* - * Using the SGI flat panels with the Ticket-to-Ride IV, horizontal - * 32-bit scrolls don't work perfectly on rectangles of width <= 24. - * we bail on a bigger bound for padding. - */ - if(Dx(r) < 32) - return 0; - break; - case 16: - /* - * Using the SGI flat panels with the Ticket-to-Ride IV, horizontal - * 16-bit scrolls don't work perfectly on rectangles of width <= 96. - * we bail on a bigger bound for padding. - */ - if(Dx(r) < 104) - return 0; - break; - } - } - waitformem(scr); - waitforfifo(scr); - d = scr->mmio + RBaseD; - ctl = 0; - if(r.min.x <= sr.min.x){ - dp.x = r.min.x; - sp.x = sr.min.x; - }else{ - ctl |= 2; - dp.x = r.max.x-1; - sp.x = sr.max.x-1; - } - - if(r.min.y < sr.min.y){ - dp.y = r.min.y; - sp.y = sr.min.y; - }else{ - ctl |= 1; - dp.y = r.max.y-1; - sp.y = sr.max.y-1; - } - - d[CmdOpc] = 0x1; /* bitblt */ - d[CmdRop] = 0xC; /* copy source */ - d[CmdStyle] = 0; - d[CmdPatrn] = 0; - d[Fore] = 0; - d[Back] = 0; - - /* writing XY1 executes cmd */ - d[XY3] = ctl; - d[XY0] = (sp.x<<16)|sp.y; - d[XY2] = (Dx(r)<<16)|Dy(r); - d[XY4] = 0; - d[XY1] = (dp.x<<16)|dp.y; - waitforcmd(scr); - - return 1; -} - -static int -t2r4hwfill(VGAscr *scr, Rectangle r, ulong sval) -{ - ulong *d; - - d = scr->mmio + RBaseD; - - waitformem(scr); - waitforfifo(scr); - d[CmdOpc] = 0x1; /* bitblt */ - d[CmdRop] = 0xC; /* copy source */ - d[CmdStyle] = 1; /* use source from Fore register */ - d[CmdPatrn] = 0; /* no stipple */ - d[Fore] = sval; - d[Back] = sval; - - /* writing XY1 executes cmd */ - d[XY3] = 0; - d[XY0] = (r.min.x<<16)|r.min.y; - d[XY2] = (Dx(r)<<16)|Dy(r); - d[XY4] = 0; - d[XY1] = (r.min.x<<16)|r.min.y; - waitforcmd(scr); - - return 1; -} - -static void -t2r4blank(VGAscr *scr, int blank) -{ - uchar x; - - x = t2r4xi(scr, CursorSyncCtl); - x &= ~0x0F; - if(blank) - x |= HsyncLo | VsyncLo; - t2r4xo(scr, CursorSyncCtl, x); -} - -static void -t2r4drawinit(VGAscr *scr) -{ - ulong pitch; - int depth; - int fmt; - ulong *d; - - pitch = Dx(scr->gscreen->r); - depth = scr->gscreen->depth; - - switch(scr->gscreen->chan){ - case RGB16: - fmt = 3; - break; - case XRGB32: - fmt = 2; - break; - case RGB15: - fmt = 1; - break; - default: - scr->fill = nil; - scr->scroll = nil; - return; - } - - d = scr->mmio + RBaseD; - - d[BufCtl] = fmt<<24; - d[DeSorg] = 0; - d[DeDorg] = 0; - d[DeSptch] = (pitch*depth)/8; - d[DeDptch] = (pitch*depth)/8; - d[CmdClp] = 0; /* 2 = inside rectangle */ - d[Mask] = ~0; - d[DeKey] = 0; - d[Clptl] = 0; - d[Clpbr] = 0xFFF0FFF0; - d[Alpha] = 0; - d[ACtl] = 0; - - scr->fill = t2r4hwfill; - scr->scroll = t2r4hwscroll; - scr->blank = t2r4blank; - hwblank = 1; -} - -VGAdev vgat2r4dev = { - "t2r4", - - t2r4enable, - nil, - nil, - t2r4linear, - t2r4drawinit, -}; - -VGAcur vgat2r4cur = { - "t2r4hwgc", - - t2r4curenable, - t2r4curdisable, - t2r4curload, - t2r4curmove, -}; - diff --git a/os/pc/vgatvp3020.c b/os/pc/vgatvp3020.c deleted file mode 100644 index 08871d4a..00000000 --- a/os/pc/vgatvp3020.c +++ /dev/null @@ -1,216 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -/* - * TVP3020 Viewpoint Video Interface Pallette. - * Assumes hooked up to an S3 86C928. - */ -enum { - Index = 0x06, /* Index register */ - Data = 0x07, /* Data register */ -}; - -/* - * Lower 2-bits of indirect DAC register - * addressing. - */ -static ushort dacxreg[4] = { - PaddrW, Pdata, Pixmask, PaddrR -}; - -static uchar -tvp3020io(uchar reg, uchar data) -{ - uchar crt55; - - crt55 = vgaxi(Crtx, 0x55) & 0xFC; - vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03)); - vgao(dacxreg[reg & 0x03], data); - - return crt55; -} - -static void -tvp3020xo(uchar index, uchar data) -{ - uchar crt55; - - crt55 = tvp3020io(Index, index); - vgao(dacxreg[Data & 0x03], data); - vgaxo(Crtx, 0x55, crt55); -} - -static void -tvp3020disable(VGAscr*) -{ - uchar r; - - /* - * Disable - * cursor; - * cursor control enable for Bt485 DAC (!); - * the hardware cursor external operation mode. - */ - tvp3020xo(0x06, 0x10); /* Cursor Control Register */ - - r = vgaxi(Crtx, 0x45) & ~0x20; - vgaxo(Crtx, 0x45, r); - - r = vgaxi(Crtx, 0x55) & ~0x20; - vgaxo(Crtx, 0x55, r); -} - -static void -tvp3020enable(VGAscr*) -{ - uchar r; - - /* - * Make sure cursor is off by initialising the cursor - * control to defaults + X-Windows cursor mode. - */ - tvp3020xo(0x06, 0x10); /* Cursor Control Register */ - - /* - * Overscan colour, - * cursor colour 1 (white), - * cursor colour 2 (black). - */ - tvp3020xo(0x20, Pwhite); tvp3020xo(0x21, Pwhite); tvp3020xo(0x22, Pwhite); - tvp3020xo(0x23, Pwhite); tvp3020xo(0x24, Pwhite); tvp3020xo(0x25, Pwhite); - tvp3020xo(0x26, Pblack); tvp3020xo(0x27, Pblack); tvp3020xo(0x28, Pblack); - - /* - * Finally, enable - * the hardware cursor external operation mode; - * cursor control enable for Bt485 DAC (!). - */ - r = vgaxi(Crtx, 0x55)|0x20; - vgaxo(Crtx, 0x55, r); - - r = vgaxi(Crtx, 0x45)|0x20; - vgaxo(Crtx, 0x45, r); -} - -static void -tvp3020load(VGAscr*, Cursor* curs) -{ - uchar p, p0, p1; - int x, y; - - /* - * Make sure cursor is off by initialising the cursor - * control to defaults + X-Windows cursor mode. - */ - tvp3020xo(0x06, 0x10); /* Cursor Control Register */ - - /* - * Initialise the cursor RAM LS and MS address - * (LS must be first). - */ - tvp3020xo(0x08, 0x00); /* Cursor RAM LS Address */ - tvp3020xo(0x09, 0x00); /* Cursor RAM MS Address */ - - /* - * Initialise the 64x64 cursor RAM array. There are 2 planes, - * p0 and p1. Data is written 4 pixels per byte, with p1 the - * MS bit of each pixel. - * The cursor is set in X-Windows mode which gives the following - * truth table: - * p1 p0 colour - * 0 0 underlying pixel colour - * 0 1 underlying pixel colour - * 1 0 cursor colour 1 - * 1 1 cursor colour 2 - * Put the cursor into the top-left of the 64x64 array. - */ - for(y = 0; y < 64; y++){ - for(x = 0; x < 64/8; x++){ - if(x < 16/8 && y < 16){ - p0 = curs->clr[x+y*2]; - p1 = curs->set[x+y*2]; - - p = 0x00; - if(p1 & 0x10) - p |= 0x03; - else if(p0 & 0x10) - p |= 0x02; - if(p1 & 0x20) - p |= 0x0C; - else if(p0 & 0x20) - p |= 0x08; - if(p1 & 0x40) - p |= 0x30; - else if(p0 & 0x40) - p |= 0x20; - if(p1 & 0x80) - p |= 0xC0; - else if(p0 & 0x80) - p |= 0x80; - tvp3020xo(0x0A, p); /* Cursor RAM Data */ - - p = 0x00; - if(p1 & 0x01) - p |= 0x03; - else if(p0 & 0x01) - p |= 0x02; - if(p1 & 0x02) - p |= 0x0C; - else if(p0 & 0x02) - p |= 0x08; - if(p1 & 0x04) - p |= 0x30; - else if(p0 & 0x04) - p |= 0x20; - if(p1 & 0x08) - p |= 0xC0; - else if(p0 & 0x08) - p |= 0x80; - tvp3020xo(0x0A, p); /* Cursor RAM Data */ - } - else{ - tvp3020xo(0x0A, 0x00); /* Cursor RAM Data */ - tvp3020xo(0x0A, 0x00); - } - } - } - - /* - * Initialise the cursor hotpoint - * and enable the cursor. - */ - tvp3020xo(0x04, -curs->offset.x); /* Sprite Origin X */ - tvp3020xo(0x05, -curs->offset.y); /* Sprite Origin Y */ - - tvp3020xo(0x06, 0x40|0x10); /* Cursor Control Register */ -} - -static int -tvp3020move(VGAscr*, Point p) -{ - tvp3020xo(0x00, p.x & 0xFF); /* Cursor Position X LSB */ - tvp3020xo(0x01, (p.x>>8) & 0x0F); /* Cursor Position X MSB */ - tvp3020xo(0x02, p.y & 0xFF); /* Cursor Position Y LSB */ - tvp3020xo(0x03, (p.y>>8) & 0x0F); /* Cursor Position Y MSB */ - - return 0; -} - -VGAcur vgatvp3020cur = { - "tvp3020hwgc", - - tvp3020enable, - tvp3020disable, - tvp3020load, - tvp3020move, -}; diff --git a/os/pc/vgatvp3026.c b/os/pc/vgatvp3026.c deleted file mode 100644 index 1b97d1bf..00000000 --- a/os/pc/vgatvp3026.c +++ /dev/null @@ -1,189 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -/* - * TVP3026 Viewpoint Video Interface Pallette. - * Assumes hooked up to an S3 Vision968. - */ -enum { - Index = 0x00, /* Index */ - Data = 0x0A, /* Data */ - - CaddrW = 0x04, /* Colour Write Address */ - Cdata = 0x05, /* Colour Data */ - - Cctl = 0x09, /* Direct Cursor Control */ - Cram = 0x0B, /* Cursor Ram Data */ - Cxlsb = 0x0C, /* Cursor X LSB */ - Cxmsb = 0x0D, /* Cursor X MSB */ - Cylsb = 0x0E, /* Cursor Y LSB */ - Cymsb = 0x0F, /* Cursor Y MSB */ - - Icctl = 0x06, /* Indirect Cursor Control */ -}; - -/* - * Lower 2-bits of indirect DAC register - * addressing. - */ -static ushort dacxreg[4] = { - PaddrW, Pdata, Pixmask, PaddrR -}; - -static uchar -tvp3026io(uchar reg, uchar data) -{ - uchar crt55; - - crt55 = vgaxi(Crtx, 0x55) & 0xFC; - vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03)); - vgao(dacxreg[reg & 0x03], data); - - return crt55; -} - -static void -tvp3026o(uchar reg, uchar data) -{ - uchar crt55; - - crt55 = tvp3026io(reg, data); - vgaxo(Crtx, 0x55, crt55); -} - -void -tvp3026xo(uchar index, uchar data) -{ - uchar crt55; - - crt55 = tvp3026io(Index, index); - vgaxo(Crtx, 0x55, crt55|((Data>>2) & 0x03)); - vgao(dacxreg[Data & 0x03], data); - vgaxo(Crtx, 0x55, crt55); -} - -static void -tvp3026disable(VGAscr*) -{ - tvp3026xo(Icctl, 0x90); - tvp3026o(Cctl, 0x00); -} - -static void -tvp3026enable(VGAscr*) -{ - /* - * Make sure cursor is off and direct control enabled. - */ - tvp3026xo(Icctl, 0x90); - tvp3026o(Cctl, 0x00); - - /* - * Overscan colour, - * cursor colour 1 (white), - * cursor colour 2, 3 (black). - */ - tvp3026o(CaddrW, 0x00); - tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); - tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); - tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); - tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); - - /* - * Enable the cursor in 3-colour mode. - */ - tvp3026o(Cctl, 0x01); -} - -static void -tvp3026load(VGAscr* scr, Cursor* curs) -{ - int x, y; - - /* - * Make sure cursor is off by initialising the cursor - * control to defaults. - * Write to the indirect control register to make sure - * direct register is enabled and upper 2 bits of cursor - * RAM address are 0. - * The LSBs of the cursor RAM address are in PaddrW. - */ - tvp3026xo(Icctl, 0x90); - tvp3026o(Cctl, 0x00); - vgao(PaddrW, 0x00); - - /* - * Initialise the 64x64 cursor RAM array. There are 2 planes, - * p0 and p1. Data is written 8 pixels per byte, with p0 in the - * first 512 bytes of the array and p1 in the second. - * The cursor is set in 3-colour mode which gives the following - * truth table: - * p1 p0 colour - * 0 0 transparent - * 0 1 cursor colour 0 - * 1 0 cursor colour 1 - * 1 1 cursor colour 2 - * Put the cursor into the top-left of the 64x64 array. - * The 0,0 cursor point is bottom-right, so positioning will - * have to take that into account. - */ - for(y = 0; y < 64; y++){ - for(x = 0; x < 64/8; x++){ - if(x < 16/8 && y < 16) - tvp3026o(Cram, curs->clr[x+y*2]); - else - tvp3026o(Cram, 0x00); - } - } - for(y = 0; y < 64; y++){ - for(x = 0; x < 64/8; x++){ - if(x < 16/8 && y < 16) - tvp3026o(Cram, curs->set[x+y*2]); - else - tvp3026o(Cram, 0x00); - } - } - - /* - * Initialise the cursor hotpoint - * and enable the cursor in 3-colour mode. - */ - scr->offset.x = 64+curs->offset.x; - scr->offset.y = 64+curs->offset.y; - tvp3026o(Cctl, 0x01); -} - -static int -tvp3026move(VGAscr* scr, Point p) -{ - int x, y; - - x = p.x+scr->offset.x; - y = p.y+scr->offset.y; - - tvp3026o(Cxlsb, x & 0xFF); - tvp3026o(Cxmsb, (x>>8) & 0x0F); - tvp3026o(Cylsb, y & 0xFF); - tvp3026o(Cymsb, (y>>8) & 0x0F); - - return 0; -} - -VGAcur vgatvp3026cur = { - "tvp3026hwgc", - - tvp3026enable, - tvp3026disable, - tvp3026load, - tvp3026move, -}; diff --git a/os/pc/vgavmware.c b/os/pc/vgavmware.c deleted file mode 100644 index 4cf09e48..00000000 --- a/os/pc/vgavmware.c +++ /dev/null @@ -1,386 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -enum { - PCIVMWARE = 0x15AD, /* PCI VID */ - - VMWARE1 = 0x0710, /* PCI DID */ - VMWARE2 = 0x0405, -}; - -enum { - Rid = 0, - Renable, - Rwidth, - Rheight, - Rmaxwidth, - - Rmaxheight, - Rdepth, - Rbpp, - Rpseudocolor, - Rrmask, - - Rgmask, - Rbmask, - Rbpl, - Rfbstart, - Rfboffset, - - Rfbmaxsize, - Rfbsize, - Rcap, - Rmemstart, - Rmemsize, - - Rconfigdone, - Rsync, - Rbusy, - Rguestid, - Rcursorid, - - Rcursorx, - Rcursory, - Rcursoron, - Nreg, - - Crectfill = 1<<0, - Crectcopy = 1<<1, - Crectpatfill = 1<<2, - Coffscreen = 1<<3, - Crasterop = 1<<4, - Ccursor = 1<<5, - Ccursorbypass = 1<<6, - Ccursorbypass2 = 1<<7, - C8bitemulation = 1<<8, - Calphacursor = 1<<9, - - FifoMin = 0, - FifoMax = 1, - FifoNextCmd = 2, - FifoStop = 3, - FifoUser = 4, - - Xupdate = 1, - Xrectfill = 2, - Xrectcopy = 3, - Xdefinebitmap = 4, - Xdefinebitmapscanline = 5, - Xdefinepixmap = 6, - Xdefinepixmapscanline = 7, - Xrectbitmapfill = 8, - Xrectpixmapfill = 9, - Xrectbitmapcopy = 10, - Xrectpixmapcopy = 11, - Xfreeobject = 12, - Xrectropfill = 13, - Xrectropcopy = 14, - Xrectropbitmapfill = 15, - Xrectroppixmapfill = 16, - Xrectropbitmapcopy = 17, - Xrectroppixmapcopy = 18, - Xdefinecursor = 19, - Xdisplaycursor = 20, - Xmovecursor = 21, - Xdefinealphacursor = 22, - Xcmdmax = 23, - - CursorOnHide = 0, - CursorOnShow = 1, - CursorOnRemoveFromFb = 2, - CursorOnRestoreToFb = 3, - - Rpalette = 1024, -}; - -typedef struct Vmware Vmware; -struct Vmware { - ulong fb; - - ulong ra; - ulong rd; - - ulong r[Nreg]; - ulong *mmio; - ulong mmiosize; - - char chan[32]; - int depth; -}; - -Vmware xvm; -Vmware *vm=&xvm; - -static ulong -vmrd(Vmware *vm, int i) -{ - outl(vm->ra, i); - return inl(vm->rd); -} - -static void -vmwr(Vmware *vm, int i, ulong v) -{ - outl(vm->ra, i); - outl(vm->rd, v); -} - -static void -vmwait(Vmware *vm) -{ - vmwr(vm, Rsync, 1); - while(vmrd(vm, Rbusy)) - ; -} - -static ulong -vmwarelinear(VGAscr* scr, int* size, int* align) -{ - char err[64]; - ulong aperture, oaperture; - int osize, oapsize, wasupamem; - Pcidev *p; - - osize = *size; - oaperture = scr->aperture; - oapsize = scr->apsize; - wasupamem = scr->isupamem; - - p = pcimatch(nil, PCIVMWARE, 0); - if(p == nil) - error("no vmware card found"); - - switch(p->did){ - default: - snprint(err, sizeof err, "unknown vmware id %.4ux", p->did); - error(err); - - case VMWARE1: - vm->ra = 0x4560; - vm->rd = 0x4560+4; - break; - - case VMWARE2: - vm->ra = p->mem[0].bar&~3; - vm->rd = vm->ra + 1; - } - - aperture = (ulong)(vmrd(vm, Rfbstart)); - *size = vmrd(vm, Rfbsize); - - if(wasupamem) - upafree(oaperture, oapsize); - scr->isupamem = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)) - scr->isupamem = 1; - }else - scr->isupamem = 1; - - if(oaperture && aperture != oaperture) - print("warning (BUG): redefinition of aperture does not change vmwarescreen segment\n"); - addvgaseg("vmwarescreen", aperture, osize); - - return aperture; -} - -static void -vmfifowr(Vmware *vm, ulong v) -{ - ulong *mm; - - mm = vm->mmio; - if(mm == nil){ - iprint("!"); - return; - } - - if(mm[FifoNextCmd]+sizeof(ulong) == mm[FifoStop] - || (mm[FifoNextCmd]+sizeof(ulong) == mm[FifoMax] - && mm[FifoStop] == mm[FifoMin])) - vmwait(vm); - - mm[mm[FifoNextCmd]/sizeof(ulong)] = v; - - /* must do this way so mm[FifoNextCmd] is never mm[FifoMax] */ - v = mm[FifoNextCmd] + sizeof(ulong); - if(v == mm[FifoMax]) - v = mm[FifoMin]; - mm[FifoNextCmd] = v; -} - -static void -vmwareflush(VGAscr*, Rectangle r) -{ - if(vm->mmio == nil) - return; - - vmfifowr(vm, Xupdate); - vmfifowr(vm, r.min.x); - vmfifowr(vm, r.min.y); - vmfifowr(vm, r.max.x-r.min.x); - vmfifowr(vm, r.max.y-r.min.y); - vmwait(vm); -} - -static void -vmwareload(VGAscr*, Cursor *c) -{ - int i; - ulong clr, set; - ulong and[16]; - ulong xor[16]; - - if(vm->mmio == nil) - return; - vmfifowr(vm, Xdefinecursor); - vmfifowr(vm, 1); /* cursor id */ - vmfifowr(vm, -c->offset.x); - vmfifowr(vm, -c->offset.y); - - vmfifowr(vm, 16); /* width */ - vmfifowr(vm, 16); /* height */ - vmfifowr(vm, 1); /* depth for and mask */ - vmfifowr(vm, 1); /* depth for xor mask */ - - for(i=0; i<16; i++){ - clr = (c->clr[i*2+1]<<8) | c->clr[i*2]; - set = (c->set[i*2+1]<<8) | c->set[i*2]; - and[i] = ~(clr|set); /* clr and set pixels => black */ - xor[i] = clr&~set; /* clr pixels => white */ - } - for(i=0; i<16; i++) - vmfifowr(vm, and[i]); - for(i=0; i<16; i++) - vmfifowr(vm, xor[i]); - - vmwait(vm); -} - -static int -vmwaremove(VGAscr*, Point p) -{ - vmwr(vm, Rcursorid, 1); - vmwr(vm, Rcursorx, p.x); - vmwr(vm, Rcursory, p.y); - vmwr(vm, Rcursoron, CursorOnShow); - return 0; -} - -static void -vmwaredisable(VGAscr*) -{ - vmwr(vm, Rcursorid, 1); - vmwr(vm, Rcursoron, CursorOnHide); -} - -static void -vmwareenable(VGAscr*) -{ - vmwr(vm, Rcursorid, 1); - vmwr(vm, Rcursoron, CursorOnShow); -} - -static void -vmwareblank(int) -{ -} - -static int -vmwarescroll(VGAscr*, Rectangle r, Rectangle sr) -{ - if(vm->mmio == nil) - return 0; - vmfifowr(vm, Xrectcopy); - vmfifowr(vm, sr.min.x); - vmfifowr(vm, sr.min.y); - vmfifowr(vm, r.min.x); - vmfifowr(vm, r.min.y); - vmfifowr(vm, Dx(r)); - vmfifowr(vm, Dy(r)); - vmwait(vm); - return 1; -} - -static int -vmwarefill(VGAscr*, Rectangle r, ulong sval) -{ - if(vm->mmio == nil) - return 0; - vmfifowr(vm, Xrectfill); - vmfifowr(vm, sval); - vmfifowr(vm, r.min.x); - vmfifowr(vm, r.min.y); - vmfifowr(vm, r.max.x-r.min.x); - vmfifowr(vm, r.max.y-r.min.y); - vmwait(vm); - return 1; -} - -static void -vmwaredrawinit(VGAscr *scr) -{ - ulong offset; - ulong mmiobase, mmiosize; - - if(scr->mmio==nil){ - mmiobase = vmrd(vm, Rmemstart); - if(mmiobase == 0) - return; - mmiosize = vmrd(vm, Rmemsize); - scr->mmio = KADDR(upamalloc(mmiobase, mmiosize, 0)); - vm->mmio = scr->mmio; - vm->mmiosize = mmiosize; - if(scr->mmio == nil) - return; - addvgaseg("vmwaremmio", mmiobase, mmiosize); - } - - scr->mmio[FifoMin] = 4*sizeof(ulong); - scr->mmio[FifoMax] = vm->mmiosize; - scr->mmio[FifoNextCmd] = 4*sizeof(ulong); - scr->mmio[FifoStop] = 4*sizeof(ulong); - vmwr(vm, Rconfigdone, 1); - - scr->scroll = vmwarescroll; - scr->fill = vmwarefill; - - offset = vmrd(vm, Rfboffset); - scr->gscreendata->bdata += offset; -} - -VGAdev vgavmwaredev = { - "vmware", - - 0, - 0, - 0, - vmwarelinear, - vmwaredrawinit, - 0, - 0, - 0, - vmwareflush, -}; - -VGAcur vgavmwarecur = { - "vmwarehwgc", - - vmwareenable, - vmwaredisable, - vmwareload, - vmwaremove, -}; diff --git a/os/pc/vgax.c b/os/pc/vgax.c deleted file mode 100644 index c765508e..00000000 --- a/os/pc/vgax.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -static Lock vgaxlock; /* access to index registers */ - -int -vgaxi(long port, uchar index) -{ - uchar data; - - ilock(&vgaxlock); - switch(port){ - - case Seqx: - case Crtx: - case Grx: - outb(port, index); - data = inb(port+1); - break; - - case Attrx: - /* - * Allow processor access to the colour - * palette registers. Writes to Attrx must - * be preceded by a read from Status1 to - * initialise the register to point to the - * index register and not the data register. - * Processor access is allowed by turning - * off bit 0x20. - */ - inb(Status1); - if(index < 0x10){ - outb(Attrx, index); - data = inb(Attrx+1); - inb(Status1); - outb(Attrx, 0x20|index); - } - else{ - outb(Attrx, 0x20|index); - data = inb(Attrx+1); - } - break; - - default: - iunlock(&vgaxlock); - return -1; - } - iunlock(&vgaxlock); - - return data & 0xFF; -} - -int -vgaxo(long port, uchar index, uchar data) -{ - ilock(&vgaxlock); - switch(port){ - - case Seqx: - case Crtx: - case Grx: - /* - * We could use an outport here, but some chips - * (e.g. 86C928) have trouble with that for some - * registers. - */ - outb(port, index); - outb(port+1, data); - break; - - case Attrx: - inb(Status1); - if(index < 0x10){ - outb(Attrx, index); - outb(Attrx, data); - inb(Status1); - outb(Attrx, 0x20|index); - } - else{ - outb(Attrx, 0x20|index); - outb(Attrx, data); - } - break; - - default: - iunlock(&vgaxlock); - return -1; - } - iunlock(&vgaxlock); - - return 0; -} diff --git a/os/pc/wavelan.c b/os/pc/wavelan.c deleted file mode 100644 index 0916f460..00000000 --- a/os/pc/wavelan.c +++ /dev/null @@ -1,1268 +0,0 @@ -/* - Lucent Wavelan IEEE 802.11 pcmcia. - There is almost no documentation for the card. - the driver is done using both the FreeBSD, Linux and - original Plan 9 drivers as `documentation'. - - Has been used with the card plugged in during all up time. - no cards removals/insertions yet. - - For known BUGS see the comments below. Besides, - the driver keeps interrupts disabled for just too - long. When it gets robust, locks should be revisited. - - BUGS: check endian, alignment and mem/io issues; - multicast; - receive watchdog interrupts. - TODO: automatic power management; - improve locking. - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" -#include "etherif.h" -#include "wavelan.h" - -enum -{ - MSperTick= 50, /* ms between ticks of kproc */ -}; - -/* - * When we're using a PCI device and memory-mapped I/O, - * the registers are spaced out as though each takes 32 bits, - * even though they are only 16-bit registers. Thus, - * ctlr->mmb[reg] is the right way to access register reg, - * even though a priori you'd expect to use ctlr->mmb[reg/2]. - */ -void -csr_outs(Ctlr *ctlr, int reg, ushort arg) -{ - if(ctlr->mmb) - ctlr->mmb[reg] = arg; - else - outs(ctlr->iob+reg, arg); -} - -ushort -csr_ins(Ctlr *ctlr, int reg) -{ - if(ctlr->mmb) - return ctlr->mmb[reg]; - else - return ins(ctlr->iob+reg); -} - -static void -csr_ack(Ctlr *ctlr, int ev) -{ - csr_outs(ctlr, WR_EvAck, ev); -} - -static void -csr_inss(Ctlr *ctlr, int reg, void *dat, int ndat) -{ - ushort *rp, *wp; - - if(ctlr->mmb){ - rp = &ctlr->mmb[reg]; - wp = dat; - while(ndat-- > 0) - *wp++ = *rp; - }else - inss(ctlr->iob+reg, dat, ndat); -} - -static void -csr_outss(Ctlr *ctlr, int reg, void *dat, int ndat) -{ - ushort *rp, *wp; - - if(ctlr->mmb){ - rp = dat; - wp = &ctlr->mmb[reg]; - while(ndat-- > 0) - *wp = *rp++; - }else - outss(ctlr->iob+reg, dat, ndat); -} - -// w_... routines do not ilock the Ctlr and should -// be called locked. - -void -w_intdis(Ctlr* ctlr) -{ - csr_outs(ctlr, WR_IntEna, 0); - csr_ack(ctlr, 0xffff); -} - -static void -w_intena(Ctlr* ctlr) -{ - csr_outs(ctlr, WR_IntEna, WEvs); -} - -int -w_cmd(Ctlr *ctlr, ushort cmd, ushort arg) -{ - int i, rc; - - for(i=0; ictlrno, cmd, csr_ins(ctlr, WR_Cmd)); - return -1; - } - - csr_outs(ctlr, WR_Parm0, arg); - csr_outs(ctlr, WR_Cmd, cmd); - - for(i=0; ictlrno, cmd, i); - if(i == IniTmOut){ - print("#l%d: execing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_EvSts)); - return -1; - } - } - rc = csr_ins(ctlr, WR_Sts); - csr_ack(ctlr, WCmdEv); - - if((rc&WCmdMsk) != (cmd&WCmdMsk)){ - print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc); - return -1; - } - if(rc&WResSts){ - /* - * Don't print; this happens on every WCmdAccWr for some reason. - */ - if(0) print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc); - return -1; - } - return 0; -} - -static int -w_seek(Ctlr* ctlr, ushort id, ushort offset, int chan) -{ - int i, rc; - static ushort sel[] = { WR_Sel0, WR_Sel1 }; - static ushort off[] = { WR_Off0, WR_Off1 }; - - if(chan != 0 && chan != 1) - panic("wavelan: bad chan\n"); - csr_outs(ctlr, sel[chan], id); - csr_outs(ctlr, off[chan], offset); - for (i=0; itype)){ - DEBUG("wavelan: access read failed\n"); - return -1; - } - if(w_seek(ctlr,ltv->type,0,1)){ - DEBUG("wavelan: seek failed\n"); - return -1; - } - len = csr_ins(ctlr, WR_Data1); - if(len > ltv->len) - return -1; - ltv->len = len; - if((code=csr_ins(ctlr, WR_Data1)) != ltv->type){ - USED(code); - DEBUG("wavelan: type %x != code %x\n",ltv->type,code); - return -1; - } - if(ltv->len > 0) - csr_inss(ctlr, WR_Data1, <v->val, ltv->len-1); - - return 0; -} - -static void -w_outltv(Ctlr* ctlr, Wltv* ltv) -{ - if(w_seek(ctlr,ltv->type, 0, 1)) - return; - csr_outss(ctlr, WR_Data1, ltv, ltv->len+1); - w_cmd(ctlr, WCmdAccWr, ltv->type); -} - -void -ltv_outs(Ctlr* ctlr, int type, ushort val) -{ - Wltv ltv; - - ltv.len = 2; - ltv.type = type; - ltv.val = val; - w_outltv(ctlr, <v); -} - -int -ltv_ins(Ctlr* ctlr, int type) -{ - Wltv ltv; - - ltv.len = 2; - ltv.type = type; - ltv.val = 0; - if(w_inltv(ctlr, <v)) - return -1; - return ltv.val; -} - -static void -ltv_outstr(Ctlr* ctlr, int type, char* val) -{ - Wltv ltv; - int len; - - len = strlen(val); - if(len > sizeof(ltv.s)) - len = sizeof(ltv.s); - memset(<v, 0, sizeof(ltv)); - ltv.len = (sizeof(ltv.type)+sizeof(ltv.slen)+sizeof(ltv.s))/2; - ltv.type = type; - -// This should be ltv.slen = len; according to Axel Belinfante - ltv.slen = len; - - strncpy(ltv.s, val, len); - w_outltv(ctlr, <v); -} - -static char Unkname[] = "who knows"; -static char Nilname[] = "card does not tell"; - -static char* -ltv_inname(Ctlr* ctlr, int type) -{ - static Wltv ltv; - int len; - - memset(<v,0,sizeof(ltv)); - ltv.len = WNameLen/2+2; - ltv.type = type; - if(w_inltv(ctlr, <v)) - return Unkname; - len = ltv.slen; - if(len == 0 || ltv.s[0] == 0) - return Nilname; - if(len >= sizeof ltv.s) - len = sizeof ltv.s - 1; - ltv.s[len] = '\0'; - return ltv.s; -} - -static int -w_read(Ctlr* ctlr, int type, int off, void* buf, ulong len) -{ - if(w_seek(ctlr, type, off, 1)){ - DEBUG("wavelan: w_read: seek failed"); - return 0; - } - csr_inss(ctlr, WR_Data1, buf, len/2); - - return len; -} - -static int -w_write(Ctlr* ctlr, int type, int off, void* buf, ulong len) -{ - int tries; - - for (tries=0; tries < WTmOut; tries++){ - if(w_seek(ctlr, type, off, 0)){ - DEBUG("wavelan: w_write: seek failed\n"); - return 0; - } - - csr_outss(ctlr, WR_Data0, buf, len/2); - - csr_outs(ctlr, WR_Data0, 0xdead); - csr_outs(ctlr, WR_Data0, 0xbeef); - if(w_seek(ctlr, type, off + len, 0)){ - DEBUG("wavelan: write seek failed\n"); - return 0; - } - if(csr_ins(ctlr, WR_Data0) == 0xdead) - if(csr_ins(ctlr, WR_Data0) == 0xbeef) - return len; - DEBUG("wavelan: Hermes bug byte.\n"); - return 0; - } - DEBUG("wavelan: tx timeout\n"); - return 0; -} - -static int -w_alloc(Ctlr* ctlr, int len) -{ - int rc; - int i,j; - - if(w_cmd(ctlr, WCmdMalloc, len)==0) - for (i = 0; ictlr; - - if(!ctlr) - return -1; - - w_intdis(ctlr); - w_cmd(ctlr, WCmdDis, 0); - w_intdis(ctlr); - if(w_cmd(ctlr, WCmdIni, 0)) - return -1; - w_intdis(ctlr); - - ltv_outs(ctlr, WTyp_Tick, 8); - ltv_outs(ctlr, WTyp_MaxLen, ctlr->maxlen); - ltv_outs(ctlr, WTyp_Ptype, ctlr->ptype); - ltv_outs(ctlr, WTyp_CreateIBSS, ctlr->createibss); - ltv_outs(ctlr, WTyp_RtsThres, ctlr->rtsthres); - ltv_outs(ctlr, WTyp_TxRate, ctlr->txrate); - ltv_outs(ctlr, WTyp_ApDens, ctlr->apdensity); - ltv_outs(ctlr, WTyp_PMWait, ctlr->pmwait); - ltv_outs(ctlr, WTyp_PM, ctlr->pmena); - if(*ctlr->netname) - ltv_outstr(ctlr, WTyp_NetName, ctlr->netname); - if(*ctlr->wantname) - ltv_outstr(ctlr, WTyp_WantName, ctlr->wantname); - ltv_outs(ctlr, WTyp_Chan, ctlr->chan); - if(*ctlr->nodename) - ltv_outstr(ctlr, WTyp_NodeName, ctlr->nodename); - ltv.len = 4; - ltv.type = WTyp_Mac; - memmove(ltv.addr, ether->ea, Eaddrlen); - w_outltv(ctlr, <v); - - ltv_outs(ctlr, WTyp_Prom, (ether->prom?1:0)); - - if(ctlr->hascrypt && ctlr->crypt){ - ltv_outs(ctlr, WTyp_Crypt, ctlr->crypt); - ltv_outs(ctlr, WTyp_TxKey, ctlr->txkey); - w_outltv(ctlr, &ctlr->keys); - ltv_outs(ctlr, WTyp_XClear, ctlr->xclear); - } - - // BUG: set multicast addresses - - if(w_cmd(ctlr, WCmdEna, 0)){ - DEBUG("wavelan: Enable failed"); - return -1; - } - ctlr->txdid = w_alloc(ctlr, 1518 + sizeof(WFrame) + 8); - ctlr->txmid = w_alloc(ctlr, 1518 + sizeof(WFrame) + 8); - if(ctlr->txdid == -1 || ctlr->txmid == -1) - DEBUG("wavelan: alloc failed"); - ctlr->txbusy = 0; - w_intena(ctlr); - return 0; -} - -static void -w_rxdone(Ether* ether) -{ - Ctlr* ctlr = (Ctlr*) ether->ctlr; - int len, sp; - WFrame f; - Block* bp=0; - Etherpkt* ep; - - sp = csr_ins(ctlr, WR_RXId); - len = w_read(ctlr, sp, 0, &f, sizeof(f)); - if(len == 0){ - DEBUG("wavelan: read frame error\n"); - goto rxerror; - } - if(f.sts&WF_Err){ - goto rxerror; - } - switch(f.sts){ - case WF_1042: - case WF_Tunnel: - case WF_WMP: - len = f.dlen + WSnapHdrLen; - bp = iallocb(ETHERHDRSIZE + len + 2); - if(!bp) - goto rxerror; - ep = (Etherpkt*) bp->wp; - memmove(ep->d, f.addr1, Eaddrlen); - memmove(ep->s, f.addr2, Eaddrlen); - memmove(ep->type,&f.type,2); - bp->wp += ETHERHDRSIZE; - if(w_read(ctlr, sp, WF_802_11_Off, bp->wp, len+2) == 0){ - DEBUG("wavelan: read 802.11 error\n"); - goto rxerror; - } - bp->wp = bp->rp+(ETHERHDRSIZE+f.dlen); - break; - default: - len = ETHERHDRSIZE + f.dlen + 2; - bp = iallocb(len); - if(!bp) - goto rxerror; - if(w_read(ctlr, sp, WF_802_3_Off, bp->wp, len) == 0){ - DEBUG("wavelan: read 800.3 error\n"); - goto rxerror; - } - bp->wp += len; - } - - ctlr->nrx++; - etheriq(ether,bp,1); - ctlr->signal = ((ctlr->signal*15)+((f.qinfo>>8) & 0xFF))/16; - ctlr->noise = ((ctlr->noise*15)+(f.qinfo & 0xFF))/16; - return; - -rxerror: - freeb(bp); - ctlr->nrxerr++; -} - -static void -w_txstart(Ether* ether) -{ - Etherpkt *pkt; - Ctlr *ctlr; - Block *bp; - int len, off; - - if((ctlr = ether->ctlr) == nil || (ctlr->state & (Attached|Power)) != (Attached|Power) || ctlr->txbusy) - return; - - if((bp = qget(ether->oq)) == nil) - return; - pkt = (Etherpkt*)bp->rp; - - // - // If the packet header type field is > 1500 it is an IP or - // ARP datagram, otherwise it is an 802.3 packet. See RFC1042. - // - memset(&ctlr->txf, 0, sizeof(ctlr->txf)); - if(((pkt->type[0]<<8)|pkt->type[1]) > 1500){ - ctlr->txf.framectl = WF_Data; - memmove(ctlr->txf.addr1, pkt->d, Eaddrlen); - memmove(ctlr->txf.addr2, pkt->s, Eaddrlen); - memmove(ctlr->txf.dstaddr, pkt->d, Eaddrlen); - memmove(ctlr->txf.srcaddr, pkt->s, Eaddrlen); - memmove(&ctlr->txf.type, pkt->type, 2); - bp->rp += ETHERHDRSIZE; - len = BLEN(bp); - off = WF_802_11_Off; - ctlr->txf.dlen = len+ETHERHDRSIZE-WSnapHdrLen; - hnputs((uchar*)&ctlr->txf.dat[0], WSnap0); - hnputs((uchar*)&ctlr->txf.dat[1], WSnap1); - hnputs((uchar*)&ctlr->txf.len, len+ETHERHDRSIZE-WSnapHdrLen); - } - else{ - len = BLEN(bp); - off = WF_802_3_Off; - ctlr->txf.dlen = len; - } - w_write(ctlr, ctlr->txdid, 0, &ctlr->txf, sizeof(ctlr->txf)); - w_write(ctlr, ctlr->txdid, off, bp->rp, len+2); - - if(w_cmd(ctlr, WCmdReclaim|WCmdTx, ctlr->txdid)){ - DEBUG("wavelan: transmit failed\n"); - ctlr->ntxerr++; - } - else{ - ctlr->txbusy = 1; - ctlr->txtmout = 2; - } - freeb(bp); -} - -static void -w_txdone(Ctlr* ctlr, int sts) -{ - ctlr->txbusy = 0; - ctlr->txtmout = 0; - if(sts & WTxErrEv) - ctlr->ntxerr++; - else - ctlr->ntx++; -} - -/* save the stats info in the ctlr struct */ -static void -w_stats(Ctlr* ctlr, int len) -{ - int i, rc; - ulong* p = (ulong*)&ctlr->WStats; - ulong* pend = (ulong*)&ctlr->end; - - for (i = 0; i < len && p < pend; i++){ - rc = csr_ins(ctlr, WR_Data1); - if(rc > 0xf000) - rc = ~rc & 0xffff; - p[i] += rc; - } -} - -/* send the base station scan info to any readers */ -static void -w_scaninfo(Ether* ether, Ctlr *ctlr, int len) -{ - int i, j; - Netfile **ep, *f, **fp; - Block *bp; - WScan *wsp; - ushort *scanbuf; - - scanbuf = malloc(len*2); - if(scanbuf == nil) - return; - - for (i = 0; i < len ; i++) - scanbuf[i] = csr_ins(ctlr, WR_Data1); - - /* calculate number of samples */ - len /= 25; - if(len == 0) - goto out; - - i = ether->scan; - ep = ðer->f[Ntypes]; - for(fp = ether->f; fp < ep && i > 0; fp++){ - f = *fp; - if(f == nil || f->scan == 0) - continue; - - bp = iallocb(100*len); - if(bp == nil) - break; - for(j = 0; j < len; j++){ - wsp = (WScan*)(&scanbuf[j*25]); - if(wsp->ssid_len > 32) - wsp->ssid_len = 32; - bp->wp = (uchar*)seprint((char*)bp->wp, (char*)bp->lim, - "ssid=%.*s;bssid=%E;signal=%d;noise=%d;chan=%d%s\n", - wsp->ssid_len, wsp->ssid, wsp->bssid, wsp->signal, - wsp->noise, wsp->chan, (wsp->capinfo&(1<<4))?";wep":""); - } - qpass(f->in, bp); - i--; - } -out: - free(scanbuf); -} - -static int -w_info(Ether *ether, Ctlr* ctlr) -{ - int sp; - Wltv ltv; - - sp = csr_ins(ctlr, WR_InfoId); - ltv.len = ltv.type = 0; - w_read(ctlr, sp, 0, <v, 4); - ltv.len--; - switch(ltv.type){ - case WTyp_Stats: - w_stats(ctlr, ltv.len); - return 0; - case WTyp_Scan: - w_scaninfo(ether, ctlr, ltv.len); - return 0; - } - return -1; -} - -/* set scanning interval */ -static void -w_scanbs(void *a, uint secs) -{ - Ether *ether = a; - Ctlr* ctlr = (Ctlr*) ether->ctlr; - - ctlr->scanticks = secs*(1000/MSperTick); -} - -static void -w_intr(Ether *ether) -{ - int rc, txid; - Ctlr* ctlr = (Ctlr*) ether->ctlr; - - if((ctlr->state & Power) == 0) - return; - - if((ctlr->state & Attached) == 0){ - csr_ack(ctlr, 0xffff); - csr_outs(ctlr, WR_IntEna, 0); - return; - } - - rc = csr_ins(ctlr, WR_EvSts); - csr_ack(ctlr, ~WEvs); // Not interested in them - if(rc & WRXEv){ - w_rxdone(ether); - csr_ack(ctlr, WRXEv); - } - if(rc & WTXEv){ - w_txdone(ctlr, rc); - csr_ack(ctlr, WTXEv); - } - if(rc & WAllocEv){ - ctlr->nalloc++; - txid = csr_ins(ctlr, WR_Alloc); - csr_ack(ctlr, WAllocEv); - if(txid == ctlr->txdid){ - if((rc & WTXEv) == 0) - w_txdone(ctlr, rc); - } - } - if(rc & WInfoEv){ - ctlr->ninfo++; - w_info(ether, ctlr); - csr_ack(ctlr, WInfoEv); - } - if(rc & WTxErrEv){ - w_txdone(ctlr, rc); - csr_ack(ctlr, WTxErrEv); - } - if(rc & WIDropEv){ - ctlr->nidrop++; - csr_ack(ctlr, WIDropEv); - } - w_txstart(ether); -} - -// Watcher to ensure that the card still works properly and -// to request WStats updates once a minute. -// BUG: it runs much more often, see the comment below. - -static void -w_timer(void* arg) -{ - Ether* ether = (Ether*) arg; - Ctlr* ctlr = (Ctlr*)ether->ctlr; - - ctlr->timerproc = up; - for(;;){ - tsleep(&up->sleep, return0, 0, MSperTick); - ctlr = (Ctlr*)ether->ctlr; - if(ctlr == 0) - break; - if((ctlr->state & (Attached|Power)) != (Attached|Power)) - continue; - ctlr->ticks++; - - ilock(ctlr); - - // Seems that the card gets frames BUT does - // not send the interrupt; this is a problem because - // I suspect it runs out of receive buffers and - // stops receiving until a transmit watchdog - // reenables the card. - // The problem is serious because it leads to - // poor rtts. - // This can be seen clearly by commenting out - // the next if and doing a ping: it will stop - // receiving (although the icmp replies are being - // issued from the remote) after a few seconds. - // Of course this `bug' could be because I'm reading - // the card frames in the wrong way; due to the - // lack of documentation I cannot know. - - if(csr_ins(ctlr, WR_EvSts)&WEvs){ - ctlr->tickintr++; - w_intr(ether); - } - - if((ctlr->ticks % 10) == 0) { - if(ctlr->txtmout && --ctlr->txtmout == 0){ - ctlr->nwatchdogs++; - w_txdone(ctlr, WTxErrEv); - if(w_enable(ether)){ - DEBUG("wavelan: wdog enable failed\n"); - } - w_txstart(ether); - } - if((ctlr->ticks % 120) == 0) - if(ctlr->txbusy == 0) - w_cmd(ctlr, WCmdEnquire, WTyp_Stats); - if(ctlr->scanticks > 0) - if((ctlr->ticks % ctlr->scanticks) == 0) - if(ctlr->txbusy == 0) - w_cmd(ctlr, WCmdEnquire, WTyp_Scan); - } - iunlock(ctlr); - } - pexit("terminated", 0); -} - -void -w_multicast(void*, uchar*, int) -{ - // BUG: to be added. -} - -void -w_attach(Ether* ether) -{ - Ctlr* ctlr; - char name[64]; - int rc; - - if(ether->ctlr == 0) - return; - - snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno); - ctlr = (Ctlr*) ether->ctlr; - if((ctlr->state & Attached) == 0){ - ilock(ctlr); - rc = w_enable(ether); - iunlock(ctlr); - if(rc == 0){ - ctlr->state |= Attached; - kproc(name, w_timer, ether, 0); - } else - print("#l%d: enable failed\n",ether->ctlrno); - } -} - -void -w_detach(Ether* ether) -{ - Ctlr* ctlr; - char name[64]; - - if(ether->ctlr == nil) - return; - - snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno); - ctlr = (Ctlr*) ether->ctlr; - if(ctlr->state & Attached){ - ilock(ctlr); - w_intdis(ctlr); - if(ctlr->timerproc){ - if(!postnote(ctlr->timerproc, 1, "kill", 0)) - print("timerproc note not posted\n"); - print("w_detach, killing 0x%p\n", ctlr->timerproc); - } - ctlr->state &= ~Attached; - iunlock(ctlr); - } - ether->ctlr = nil; -} - -void -w_power(Ether* ether, int on) -{ - Ctlr *ctlr; - - ctlr = (Ctlr*) ether->ctlr; - ilock(ctlr); -iprint("w_power %d\n", on); - if(on){ - if((ctlr->state & Power) == 0){ - if (wavelanreset(ether, ctlr) < 0){ - iprint("w_power: reset failed\n"); - iunlock(ctlr); - w_detach(ether); - free(ctlr); - return; - } - if(ctlr->state & Attached) - w_enable(ether); - ctlr->state |= Power; - } - }else{ - if(ctlr->state & Power){ - if(ctlr->state & Attached) - w_intdis(ctlr); - ctlr->state &= ~Power; - } - } - iunlock(ctlr); -} - -#define PRINTSTAT(fmt,val) l += snprint(p+l, READSTR-l, (fmt), (val)) -#define PRINTSTR(fmt) l += snprint(p+l, READSTR-l, (fmt)) - -long -w_ifstat(Ether* ether, void* a, long n, ulong offset) -{ - Ctlr *ctlr = (Ctlr*) ether->ctlr; - char *k, *p; - int i, l, txid; - - ether->oerrs = ctlr->ntxerr; - ether->crcs = ctlr->nrxfcserr; - ether->frames = 0; - ether->buffs = ctlr->nrxdropnobuf; - ether->overflows = 0; - - // - // Offset must be zero or there's a possibility the - // new data won't match the previous read. - // - if(n == 0 || offset != 0) - return 0; - - p = malloc(READSTR); - l = 0; - - PRINTSTAT("Signal: %d\n", ctlr->signal-149); - PRINTSTAT("Noise: %d\n", ctlr->noise-149); - PRINTSTAT("SNR: %ud\n", ctlr->signal-ctlr->noise); - PRINTSTAT("Interrupts: %lud\n", ctlr->nints); - PRINTSTAT("Double Interrupts: %lud\n", ctlr->ndoubleint); - PRINTSTAT("TxPackets: %lud\n", ctlr->ntx); - PRINTSTAT("RxPackets: %lud\n", ctlr->nrx); - PRINTSTAT("TxErrors: %lud\n", ctlr->ntxerr); - PRINTSTAT("RxErrors: %lud\n", ctlr->nrxerr); - PRINTSTAT("TxRequests: %lud\n", ctlr->ntxrq); - PRINTSTAT("AllocEvs: %lud\n", ctlr->nalloc); - PRINTSTAT("InfoEvs: %lud\n", ctlr->ninfo); - PRINTSTAT("InfoDrop: %lud\n", ctlr->nidrop); - PRINTSTAT("WatchDogs: %lud\n", ctlr->nwatchdogs); - PRINTSTAT("Ticks: %ud\n", ctlr->ticks); - PRINTSTAT("TickIntr: %ud\n", ctlr->tickintr); - k = ((ctlr->state & Attached) ? "attached" : "not attached"); - PRINTSTAT("Card %s", k); - k = ((ctlr->state & Power) ? "on" : "off"); - PRINTSTAT(", power %s", k); - k = ((ctlr->txbusy)? ", txbusy" : ""); - PRINTSTAT("%s\n", k); - - if(ctlr->hascrypt){ - PRINTSTR("Keys: "); - for (i = 0; i < WNKeys; i++){ - if(ctlr->keys.keys[i].len == 0) - PRINTSTR("none "); - else if(SEEKEYS == 0) - PRINTSTR("set "); - else - PRINTSTAT("%s ", ctlr->keys.keys[i].dat); - } - PRINTSTR("\n"); - } - - // real card stats - ilock(ctlr); - PRINTSTR("\nCard stats: \n"); - PRINTSTAT("Status: %ux\n", csr_ins(ctlr, WR_Sts)); - PRINTSTAT("Event status: %ux\n", csr_ins(ctlr, WR_EvSts)); - i = ltv_ins(ctlr, WTyp_Ptype); - PRINTSTAT("Port type: %d\n", i); - PRINTSTAT("Transmit rate: %d\n", ltv_ins(ctlr, WTyp_TxRate)); - PRINTSTAT("Current Transmit rate: %d\n", - ltv_ins(ctlr, WTyp_CurTxRate)); - PRINTSTAT("Channel: %d\n", ltv_ins(ctlr, WTyp_Chan)); - PRINTSTAT("AP density: %d\n", ltv_ins(ctlr, WTyp_ApDens)); - PRINTSTAT("Promiscuous mode: %d\n", ltv_ins(ctlr, WTyp_Prom)); - if(i == WPTypeAdHoc) - PRINTSTAT("SSID name: %s\n", ltv_inname(ctlr, WTyp_NetName)); - else { - Wltv ltv; - PRINTSTAT("Current name: %s\n", ltv_inname(ctlr, WTyp_CurName)); - ltv.type = WTyp_BaseID; - ltv.len = 4; - if(w_inltv(ctlr, <v)) - print("#l%d: unable to read base station mac addr\n", ether->ctlrno); - l += snprint(p+l, READSTR-l, "Base station: %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", - ltv.addr[0], ltv.addr[1], ltv.addr[2], ltv.addr[3], ltv.addr[4], ltv.addr[5]); - } - PRINTSTAT("Net name: %s\n", ltv_inname(ctlr, WTyp_WantName)); - PRINTSTAT("Node name: %s\n", ltv_inname(ctlr, WTyp_NodeName)); - if(ltv_ins(ctlr, WTyp_HasCrypt) == 0) - PRINTSTR("WEP: not supported\n"); - else { - if(ltv_ins(ctlr, WTyp_Crypt) == 0) - PRINTSTR("WEP: disabled\n"); - else{ - PRINTSTR("WEP: enabled\n"); - k = ((ctlr->xclear)? "excluded": "included"); - PRINTSTAT("Clear packets: %s\n", k); - txid = ltv_ins(ctlr, WTyp_TxKey); - PRINTSTAT("Transmit key id: %d\n", txid); - } - } - iunlock(ctlr); - - PRINTSTAT("ntxuframes: %lud\n", ctlr->ntxuframes); - PRINTSTAT("ntxmframes: %lud\n", ctlr->ntxmframes); - PRINTSTAT("ntxfrags: %lud\n", ctlr->ntxfrags); - PRINTSTAT("ntxubytes: %lud\n", ctlr->ntxubytes); - PRINTSTAT("ntxmbytes: %lud\n", ctlr->ntxmbytes); - PRINTSTAT("ntxdeferred: %lud\n", ctlr->ntxdeferred); - PRINTSTAT("ntxsretries: %lud\n", ctlr->ntxsretries); - PRINTSTAT("ntxmultiretries: %lud\n", ctlr->ntxmultiretries); - PRINTSTAT("ntxretrylimit: %lud\n", ctlr->ntxretrylimit); - PRINTSTAT("ntxdiscards: %lud\n", ctlr->ntxdiscards); - PRINTSTAT("nrxuframes: %lud\n", ctlr->nrxuframes); - PRINTSTAT("nrxmframes: %lud\n", ctlr->nrxmframes); - PRINTSTAT("nrxfrags: %lud\n", ctlr->nrxfrags); - PRINTSTAT("nrxubytes: %lud\n", ctlr->nrxubytes); - PRINTSTAT("nrxmbytes: %lud\n", ctlr->nrxmbytes); - PRINTSTAT("nrxfcserr: %lud\n", ctlr->nrxfcserr); - PRINTSTAT("nrxdropnobuf: %lud\n", ctlr->nrxdropnobuf); - PRINTSTAT("nrxdropnosa: %lud\n", ctlr->nrxdropnosa); - PRINTSTAT("nrxcantdecrypt: %lud\n", ctlr->nrxcantdecrypt); - PRINTSTAT("nrxmsgfrag: %lud\n", ctlr->nrxmsgfrag); - PRINTSTAT("nrxmsgbadfrag: %lud\n", ctlr->nrxmsgbadfrag); - USED(l); - n = readstr(offset, a, n, p); - free(p); - return n; -} -#undef PRINTSTR -#undef PRINTSTAT - -static int -parsekey(WKey* key, char* a) -{ - int i, k, len, n; - char buf[WMaxKeyLen]; - - len = strlen(a); - if(len == WMinKeyLen || len == WMaxKeyLen){ - memset(key->dat, 0, sizeof(key->dat)); - memmove(key->dat, a, len); - key->len = len; - - return 0; - } - else if(len == WMinKeyLen*2 || len == WMaxKeyLen*2){ - k = 0; - for(i = 0; i < len; i++){ - if(*a >= '0' && *a <= '9') - n = *a++ - '0'; - else if(*a >= 'a' && *a <= 'f') - n = *a++ - 'a' + 10; - else if(*a >= 'A' && *a <= 'F') - n = *a++ - 'A' + 10; - else - return -1; - - if(i & 1){ - buf[k] |= n; - k++; - } - else - buf[k] = n<<4; - } - - memset(key->dat, 0, sizeof(key->dat)); - memmove(key->dat, buf, k); - key->len = k; - - return 0; - } - - return -1; -} - -int -w_option(Ctlr* ctlr, char* buf, long n) -{ - char *p; - int i, r; - Cmdbuf *cb; - - r = 0; - - cb = parsecmd(buf, n); - if(cb->nf < 2) - r = -1; - else if(cistrcmp(cb->f[0], "essid") == 0){ - if(cistrcmp(cb->f[1],"default") == 0) - p = ""; - else - p = cb->f[1]; - if(ctlr->ptype == WPTypeAdHoc){ - memset(ctlr->netname, 0, sizeof(ctlr->netname)); - strncpy(ctlr->netname, p, WNameLen); - } - else{ - memset(ctlr->wantname, 0, sizeof(ctlr->wantname)); - strncpy(ctlr->wantname, p, WNameLen); - } - } - else if(cistrcmp(cb->f[0], "station") == 0){ - memset(ctlr->nodename, 0, sizeof(ctlr->nodename)); - strncpy(ctlr->nodename, cb->f[1], WNameLen); - } - else if(cistrcmp(cb->f[0], "channel") == 0){ - if((i = atoi(cb->f[1])) >= 1 && i <= 16) - ctlr->chan = i; - else - r = -1; - } - else if(cistrcmp(cb->f[0], "mode") == 0){ - if(cistrcmp(cb->f[1], "managed") == 0) - ctlr->ptype = WPTypeManaged; - else if(cistrcmp(cb->f[1], "wds") == 0) - ctlr->ptype = WPTypeWDS; - else if(cistrcmp(cb->f[1], "adhoc") == 0) - ctlr->ptype = WPTypeAdHoc; - else if((i = atoi(cb->f[1])) >= 0 && i <= 3) - ctlr->ptype = i; - else - r = -1; - } - else if(cistrcmp(cb->f[0], "ibss") == 0){ - if(cistrcmp(cb->f[1], "on") == 0) - ctlr->createibss = 1; - else - ctlr->createibss = 0; - } - else if(cistrcmp(cb->f[0], "crypt") == 0){ - if(cistrcmp(cb->f[1], "off") == 0) - ctlr->crypt = 0; - else if(cistrcmp(cb->f[1], "on") == 0 && ctlr->hascrypt) - ctlr->crypt = 1; - else - r = -1; - } - else if(cistrcmp(cb->f[0], "clear") == 0){ - if(cistrcmp(cb->f[1], "on") == 0) - ctlr->xclear = 0; - else if(cistrcmp(cb->f[1], "off") == 0 && ctlr->hascrypt) - ctlr->xclear = 1; - else - r = -1; - } - else if(cistrncmp(cb->f[0], "key", 3) == 0){ - if((i = atoi(cb->f[0]+3)) >= 1 && i <= WNKeys){ - ctlr->txkey = i-1; - if(parsekey(&ctlr->keys.keys[ctlr->txkey], cb->f[1])) - r = -1; - } - else - r = -1; - } - else if(cistrcmp(cb->f[0], "txkey") == 0){ - if((i = atoi(cb->f[1])) >= 1 && i <= WNKeys) - ctlr->txkey = i-1; - else - r = -1; - } - else if(cistrcmp(cb->f[0], "pm") == 0){ - if(cistrcmp(cb->f[1], "off") == 0) - ctlr->pmena = 0; - else if(cistrcmp(cb->f[1], "on") == 0){ - ctlr->pmena = 1; - if(cb->nf == 3){ - i = atoi(cb->f[2]); - // check range here? what are the units? - ctlr->pmwait = i; - } - } - else - r = -1; - } - else - r = -2; - free(cb); - - return r; -} - -long -w_ctl(Ether* ether, void* buf, long n) -{ - Ctlr *ctlr; - - if((ctlr = ether->ctlr) == nil) - error(Enonexist); - if((ctlr->state & Attached) == 0) - error(Eshutdown); - - ilock(ctlr); - if(w_option(ctlr, buf, n)){ - iunlock(ctlr); - error(Ebadctl); - } - if(ctlr->txbusy) - w_txdone(ctlr, WTxErrEv); - w_enable(ether); - w_txstart(ether); - iunlock(ctlr); - - return n; -} - -void -w_transmit(Ether* ether) -{ - Ctlr* ctlr = ether->ctlr; - - if(ctlr == 0) - return; - - ilock(ctlr); - ctlr->ntxrq++; - w_txstart(ether); - iunlock(ctlr); -} - -void -w_promiscuous(void* arg, int on) -{ - Ether* ether = (Ether*)arg; - Ctlr* ctlr = ether->ctlr; - - if(ctlr == nil) - error("card not found"); - if((ctlr->state & Attached) == 0) - error("card not attached"); - ilock(ctlr); - ltv_outs(ctlr, WTyp_Prom, (on?1:0)); - iunlock(ctlr); -} - -void -w_interrupt(Ureg* ,void* arg) -{ - Ether* ether = (Ether*) arg; - Ctlr* ctlr = (Ctlr*) ether->ctlr; - - if(ctlr == 0) - return; - ilock(ctlr); - ctlr->nints++; - w_intr(ether); - iunlock(ctlr); -} - -int -wavelanreset(Ether* ether, Ctlr *ctlr) -{ - Wltv ltv; - - iprint("wavelanreset, iob 0x%ux\n", ctlr->iob); - w_intdis(ctlr); - if(w_cmd(ctlr,WCmdIni,0)){ - iprint("#l%d: init failed\n", ether->ctlrno); - return -1; - } - w_intdis(ctlr); - ltv_outs(ctlr, WTyp_Tick, 8); - - ctlr->chan = 0; - ctlr->ptype = WDfltPType; - ctlr->txkey = 0; - ctlr->createibss = 0; - ctlr->keys.len = sizeof(WKey)*WNKeys/2 + 1; - ctlr->keys.type = WTyp_Keys; - if(ctlr->hascrypt = ltv_ins(ctlr, WTyp_HasCrypt)) - ctlr->crypt = 1; - *ctlr->netname = *ctlr->wantname = 0; - strcpy(ctlr->nodename, "Plan 9 STA"); - - ctlr->netname[WNameLen-1] = 0; - ctlr->wantname[WNameLen-1] = 0; - ctlr->nodename[WNameLen-1] =0; - - ltv.type = WTyp_Mac; - ltv.len = 4; - if(w_inltv(ctlr, <v)){ - iprint("#l%d: unable to read mac addr\n", - ether->ctlrno); - return -1; - } - memmove(ether->ea, ltv.addr, Eaddrlen); - - if(ctlr->chan == 0) - ctlr->chan = ltv_ins(ctlr, WTyp_Chan); - ctlr->apdensity = WDfltApDens; - ctlr->rtsthres = WDfltRtsThres; - ctlr->txrate = WDfltTxRate; - ctlr->maxlen = WMaxLen; - ctlr->pmena = 0; - ctlr->pmwait = 100; - ctlr->signal = 1; - ctlr->noise = 1; - ctlr->state |= Power; - - // free old Ctlr struct if resetting after suspend - if(ether->ctlr && ether->ctlr != ctlr) - free(ether->ctlr); - - // link to ether - ether->ctlr = ctlr; - ether->mbps = 10; - ether->attach = w_attach; - ether->detach = w_detach; - ether->interrupt = w_interrupt; - ether->transmit = w_transmit; - ether->ifstat = w_ifstat; - ether->ctl = w_ctl; - ether->power = w_power; - ether->promiscuous = w_promiscuous; - ether->multicast = w_multicast; - ether->scanbs = w_scanbs; - ether->arg = ether; - - DEBUG("#l%d: irq %d port %lx type %s", - ether->ctlrno, ether->irq, ether->port, ether->type); - DEBUG(" %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux\n", - ether->ea[0], ether->ea[1], ether->ea[2], - ether->ea[3], ether->ea[4], ether->ea[5]); - - return 0; -} - -char* wavenames[] = { - "WaveLAN/IEEE", - "TrueMobile 1150", - "Instant Wireless ; Network PC CARD", - "Instant Wireless Network PC Card", - "Avaya Wireless PC Card", - "AirLancer MC-11", - "INTERSIL;HFA384x/IEEE;Version 01.02;", - nil, -}; diff --git a/os/pc/wavelan.h b/os/pc/wavelan.h deleted file mode 100644 index 7f76149e..00000000 --- a/os/pc/wavelan.h +++ /dev/null @@ -1,327 +0,0 @@ -#define DEBUG if(1){}else print - -#define SEEKEYS 0 - -// Lucent's Length-Type-Value records to talk to the wavelan. -// most operational parameters are read/set using this. -enum -{ - WTyp_Stats = 0xf100, - WTyp_Scan = 0xf101, - WTyp_Link = 0xf200, - WTyp_Ptype = 0xfc00, - WTyp_Mac = 0xfc01, - WTyp_WantName = 0xfc02, - WTyp_Chan = 0xfc03, - WTyp_NetName = 0xfc04, - WTyp_ApDens = 0xfc06, - WTyp_MaxLen = 0xfc07, - WTyp_PM = 0xfc09, - WTyp_PMWait = 0xfc0c, - WTyp_NodeName = 0xfc0e, - WTyp_Crypt = 0xfc20, - WTyp_XClear = 0xfc22, - WTyp_CreateIBSS = 0xfc81, - WTyp_RtsThres = 0xfc83, - WTyp_TxRate = 0xfc84, - WTx1Mbps = 0x0, - WTx2Mbps = 0x1, - WTxAuto = 0x3, - WTyp_Prom = 0xfc85, - WTyp_Keys = 0xfcb0, - WTyp_TxKey = 0xfcb1, - WTyp_StationID = 0xfd20, - WTyp_CurName = 0xfd41, - WTyp_BaseID = 0xfd42, // ID of the currently connected-to base station - WTyp_CurTxRate = 0xfd44, // Current TX rate - WTyp_HasCrypt = 0xfd4f, - WTyp_Tick = 0xfce0, -}; - -// Controller -enum -{ - WDfltIRQ = 3, // default irq - WDfltIOB = 0x180, // default IO base - - WIOLen = 0x40, // Hermes IO length - - WTmOut = 65536, // Cmd time out - - WPTypeManaged = 1, - WPTypeWDS = 2, - WPTypeAdHoc = 3, - WDfltPType = WPTypeManaged, - - WDfltApDens = 1, - WDfltRtsThres = 2347, // == disabled - WDfltTxRate = WTxAuto, // 2Mbps - - WMaxLen = 2304, - WNameLen = 32, - - WNKeys = 4, - WKeyLen = 14, - WMinKeyLen = 5, - WMaxKeyLen = 13, - - // Wavelan hermes registers - WR_Cmd = 0x00, - WCmdIni = 0x0000, - WCmdEna = 0x0001, - WCmdDis = 0x0002, - WCmdTx = 0x000b, - WCmdMalloc = 0x000a, - WCmdEnquire = 0x0011, - WCmdMsk = 0x003f, - WCmdAccRd = 0x0021, - WCmdReclaim = 0x0100, - WCmdAccWr = 0x0121, - WCmdBusy = 0x8000, - WR_Parm0 = 0x02, - WR_Parm1 = 0x04, - WR_Parm2 = 0x06, - WR_Sts = 0x08, - WR_InfoId = 0x10, - WR_Sel0 = 0x18, - WR_Sel1 = 0x1a, - WR_Off0 = 0x1c, - WR_Off1 = 0x1e, - WBusyOff = 0x8000, - WErrOff = 0x4000, - WResSts = 0x7f00, - WR_RXId = 0x20, - WR_Alloc = 0x22, - WR_EvSts = 0x30, - WR_IntEna = 0x32, - WCmdEv = 0x0010, - WRXEv = 0x0001, - WTXEv = 0x0002, - WTxErrEv = 0x0004, - WAllocEv = 0x0008, - WInfoEv = 0x0080, - WIDropEv = 0x2000, - WTickEv = 0x8000, - WEvs = WRXEv|WTXEv|WAllocEv|WInfoEv|WIDropEv, - - WR_EvAck = 0x34, - WR_Data0 = 0x36, - WR_Data1 = 0x38, - - WR_PciCor = 0x26, - WR_PciHcr = 0x2E, - - // Frame stuff - - WF_Err = 0x0003, - WF_1042 = 0x2000, - WF_Tunnel = 0x4000, - WF_WMP = 0x6000, - - WF_Data = 0x0008, - - WSnapK1 = 0xaa, - WSnapK2 = 0x00, - WSnapCtlr = 0x03, - WSnap0 = (WSnapK1|(WSnapK1<<8)), - WSnap1 = (WSnapK2|(WSnapCtlr<<8)), - WSnapHdrLen = 6, - - WF_802_11_Off = 0x44, - WF_802_3_Off = 0x2e, - -}; - -typedef struct Ctlr Ctlr; -typedef struct Wltv Wltv; -typedef struct WFrame WFrame; -typedef struct Stats Stats; -typedef struct WStats WStats; -typedef struct WScan WScan; -typedef struct WKey WKey; - -struct WStats -{ - ulong ntxuframes; // unicast frames - ulong ntxmframes; // multicast frames - ulong ntxfrags; // fragments - ulong ntxubytes; // unicast bytes - ulong ntxmbytes; // multicast bytes - ulong ntxdeferred; // deferred transmits - ulong ntxsretries; // single retries - ulong ntxmultiretries; // multiple retries - ulong ntxretrylimit; - ulong ntxdiscards; - ulong nrxuframes; // unicast frames - ulong nrxmframes; // multicast frames - ulong nrxfrags; // fragments - ulong nrxubytes; // unicast bytes - ulong nrxmbytes; // multicast bytes - ulong nrxfcserr; - ulong nrxdropnobuf; - ulong nrxdropnosa; - ulong nrxcantdecrypt; - ulong nrxmsgfrag; - ulong nrxmsgbadfrag; - ulong end; -}; - -struct WScan -{ - ushort chan; /* dss channel */ - ushort noise; /* average noise in the air */ - ushort signal; /* signal strength */ - uchar bssid[Eaddrlen]; /* MAC address of the ap */ - ushort interval; /* beacon transmit interval */ - ushort capinfo; /* capability bits (0-ess, 1-ibss, 4-privacy [wep]) */ - ushort ssid_len; /* ssid length */ - char ssid[WNameLen]; /* ssid (ap name) */ -}; - -struct WFrame -{ - ushort sts; - ushort rsvd0; - ushort rsvd1; - ushort qinfo; - ushort rsvd2; - ushort rsvd3; - ushort txctl; - ushort framectl; - ushort id; - uchar addr1[Eaddrlen]; - uchar addr2[Eaddrlen]; - uchar addr3[Eaddrlen]; - ushort seqctl; - uchar addr4[Eaddrlen]; - ushort dlen; - uchar dstaddr[Eaddrlen]; - uchar srcaddr[Eaddrlen]; - ushort len; - ushort dat[3]; - ushort type; -}; - -struct WKey -{ - ushort len; - char dat[WKeyLen]; -}; - -struct Wltv -{ - ushort len; - ushort type; - union - { - struct { - ushort val; - ushort pad; - }; - struct { - uchar addr[8]; - }; - struct { - ushort slen; - char s[WNameLen]; - }; - struct { - char name[WNameLen]; - }; - struct { - WKey keys[WNKeys]; - }; - }; -}; - -// What the driver thinks. Not what the card thinks. -struct Stats -{ - ulong nints; - ulong ndoubleint; - ulong nrx; - ulong ntx; - ulong ntxrq; - ulong nrxerr; - ulong ntxerr; - ulong nalloc; // allocation (reclaim) events - ulong ninfo; - ulong nidrop; - ulong nwatchdogs; // transmit time outs, actually - int ticks; - int tickintr; - int signal; - int noise; -}; - -enum { - Attached = 0x01, - Power = 0x02, -}; - -struct Ctlr -{ - Lock; - - int state; // Attached | Power - int slot; - int iob; - int createibss; - int ptype; - int apdensity; - int rtsthres; - int txbusy; - int txrate; - int txdid; - int txmid; - int txtmout; - int maxlen; - int chan; - int pmena; - int pmwait; - - Proc *timerproc; - int scanticks; - - char netname[WNameLen]; - char wantname[WNameLen]; - char nodename[WNameLen]; - WFrame txf; - uchar txbuf[1536]; - - int hascrypt; // card has encryption - int crypt; // encryption off/on - int txkey; // transmit key - Wltv keys; // default keys - int xclear; // exclude clear packets off/on - - int ctlrno; - - ushort *mmb; - /* for PCI-based devices */ - Ctlr *next; - int active; - Pcidev *pcidev; - - Stats; - WStats; -}; - -extern char* wavenames[]; - -void csr_outs(Ctlr*, int, ushort); -ushort csr_ins(Ctlr*, int); -void w_intdis(Ctlr*); -int w_cmd(Ctlr *, ushort, ushort); -void ltv_outs(Ctlr*, int, ushort); -int ltv_ins(Ctlr*, int); -int w_option(Ctlr*, char*, long); -int w_inltv(Ctlr*, Wltv*); -void w_attach(Ether*); -void w_interrupt(Ureg*,void*); -void w_transmit(Ether*); -long w_ifstat(Ether*, void*, long, ulong); -long w_ctl(Ether*, void*, long); -void w_promiscuous(void*, int); -void w_multicast(void*, uchar*, int); -int wavelanreset(Ether*, Ctlr*); diff --git a/os/pc/x86break.c b/os/pc/x86break.c deleted file mode 100644 index db31fe4f..00000000 --- a/os/pc/x86break.c +++ /dev/null @@ -1,138 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" -#include "../port/error.h" - -// -// from trap.c -// - -uchar BREAK = 0xcc; -static ulong skipflags; -extern int (*breakhandler)(Ureg *ur, Proc*); -static Bkpt *skip; -int breakmatch(BkptCond *cond, Ureg *ur, Proc *p); -void breaknotify(Bkpt *b, Proc *p); -void breakrestore(Bkpt *b); -Bkpt* breakclear(int id); - -void -skiphandler(Ureg *ur, void*) -{ - if (skip == 0) - panic("single step outside of skip"); - - breakrestore( skip ); - skip = 0; - ur->flags = skipflags; - if (up != 0) - up->state = Running; -} - -void -machbreakinit(void) -{ - breakhandler = breakhit; - trapenable(VectorDBG, skiphandler, nil, "bkpt.skip"); -} - -Instr -machinstr(ulong addr) -{ - if (addr < KTZERO) - error(Ebadarg); - return *(uchar*)addr; -} - -void -machbreakset(ulong addr) -{ - if (addr < KTZERO) - error(Ebadarg); - *(uchar*)addr = BREAK; -} - -void -machbreakclear(ulong addr, Instr i) -{ - if (addr < KTZERO) - error(Ebadarg); - *(uchar*)addr = i; -} - -// -// Called from the exception handler when a breakpoint instruction has been -// hit. This cannot not be called unless at least one breakpoint with this -// address is in the list of breakpoints. (All breakpoint notifications must -// previously have been set via setbreak()) -// -// foreach breakpoint in list -// if breakpoint matches conditions -// notify the break handler -// if no breakpoints matched the conditions -// pick a random breakpoint set to this address -// -// set a breakpoint at the next instruction to be executed, -// and pass the current breakpoint to the "skiphandler" -// -// clear the current breakpoint -// -// Tell the scheduler to stop scheduling, so the caller is -// guaranteed to execute the instruction, followed by the -// added breakpoint. -// -// - -extern Bkpt *breakpoints; - - -int -breakhit(Ureg *ur, Proc *p) -{ - Bkpt *b; - int nmatched; - - ur->pc--; - - nmatched = 0; - for(b = breakpoints; b != nil; b = b->next) { - if(breakmatch(b->conditions, ur, p)) { - breaknotify(b, p); - ++nmatched; - } - } - - if (nmatched) - return 1; - - if (skip != nil) - panic("x86break: non-nil skip in breakhit\n"); - - for(b = breakpoints; b != (Bkpt*) nil; b = b->next) { - if(b->addr == ur->pc) { - if(breakclear(b->id) == 0) - panic("breakhit: breakclear() failed"); - - skip = b; - skipflags = ur->flags; - if (p != 0) - p->state = Stopped; /* this should disable scheduling */ - - if (ur->flags & (1 << 9)) { /* mask all interrupts */ - ur->flags &= ~(1<<9); - } - ur->flags |= (1 << 8); - } - } - return 1; -} - -int -isvalid_va(void*) -{ - return 1; -} diff --git a/os/pc/zoran.h b/os/pc/zoran.h deleted file mode 100644 index b54305ef..00000000 --- a/os/pc/zoran.h +++ /dev/null @@ -1,907 +0,0 @@ -static uchar -zrmpeg1[] = { -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x66, 0x05, -0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x5a, 0x00, -0x00, 0x08, 0x58, 0x01, 0x00, 0x08, 0x6e, 0x00, -0x00, 0x08, 0x6c, 0x00, 0x00, 0x03, 0x81, 0x03, -0x00, 0x08, 0x9a, 0x00, 0x00, 0x08, 0xfc, 0x3f, -0x00, 0x0d, 0x02, 0x97, 0x00, 0x06, 0x01, 0xfa, -0x00, 0x0c, 0xa2, 0xd1, 0x00, 0x08, 0x6a, 0x00, -0x00, 0x06, 0x01, 0x00, 0x00, 0x0c, 0xa0, 0x6b, -0x00, 0x06, 0x01, 0xb3, 0x00, 0x0c, 0xa8, 0x09, -0x00, 0x0c, 0xd8, 0x12, 0x00, 0x08, 0x5c, 0x01, -0x00, 0x08, 0x02, 0xf0, 0x00, 0x08, 0xe4, 0x33, -0x00, 0x08, 0x0c, 0x0c, 0x00, 0x08, 0x04, 0x08, -0x00, 0x00, 0xe3, 0x80, 0x00, 0x04, 0x85, 0x90, -0x00, 0x08, 0x0c, 0x0c, 0x00, 0x00, 0xe3, 0x80, -0x00, 0x04, 0x85, 0xb1, 0x00, 0x08, 0x0c, 0x08, -0x00, 0x04, 0x8d, 0x08, 0x00, 0x06, 0x81, 0x08, -0x00, 0x0c, 0xa8, 0x22, 0x00, 0x08, 0x64, 0xff, -0x00, 0x01, 0x01, 0x07, 0x00, 0x08, 0x02, 0x00, -0x00, 0x06, 0x01, 0x02, 0x00, 0x0c, 0x90, 0x27, -0x00, 0x08, 0x02, 0x01, 0x00, 0x06, 0x6b, 0x00, -0x00, 0x08, 0xde, 0x01, 0x00, 0x0c, 0xa8, 0x09, -0x00, 0x08, 0x0c, 0x0f, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x0c, 0x10, 0x00, 0x06, 0x8d, 0x01, -0x00, 0x0c, 0xa0, 0x3a, 0x00, 0x08, 0x0a, 0x00, -0x00, 0x08, 0x60, 0x00, 0x00, 0x08, 0x0c, 0x08, -0x00, 0x04, 0x9d, 0x08, 0x00, 0x08, 0x8b, 0x41, -0x00, 0x02, 0x50, 0x05, 0x00, 0x06, 0x0b, 0x40, -0x00, 0x0c, 0xa8, 0x31, 0x00, 0x06, 0x6b, 0x00, -0x00, 0x0c, 0xa8, 0x3f, 0x00, 0x0d, 0x00, 0x3b, -0x00, 0x08, 0x60, 0x01, 0x00, 0x08, 0x0a, 0x40, -0x00, 0x08, 0x0c, 0x01, 0x00, 0x06, 0x0d, 0x00, -0x00, 0x0c, 0x98, 0x49, 0x00, 0x08, 0x0a, 0x40, -0x00, 0x08, 0x0c, 0x08, 0x00, 0x04, 0x9d, 0x08, -0x00, 0x08, 0x8b, 0x41, 0x00, 0x02, 0x50, 0x05, -0x00, 0x06, 0x0b, 0x80, 0x00, 0x0c, 0xa8, 0x40, -0x00, 0x06, 0x6b, 0x00, 0x00, 0x0c, 0xa8, 0x16, -0x00, 0x0d, 0x00, 0x4e, 0x00, 0x08, 0x02, 0x10, -0x00, 0x08, 0x8a, 0x41, 0x00, 0x02, 0x50, 0x05, -0x00, 0x06, 0x0b, 0x80, 0x00, 0x0c, 0xa8, 0x4a, -0x00, 0x08, 0xfc, 0x3f, 0x00, 0x0d, 0x02, 0x97, -0x00, 0x08, 0xfc, 0x3f, 0x00, 0x0d, 0x02, 0x95, -0x00, 0x06, 0x01, 0xb8, 0x00, 0x0c, 0xa9, 0xff, -0x00, 0x06, 0x6f, 0x00, 0x00, 0x0c, 0xa0, 0x57, -0x00, 0x08, 0x58, 0x00, 0x00, 0x08, 0x6e, 0x01, -0x00, 0x08, 0x0c, 0x10, 0x00, 0x08, 0x0c, 0x09, -0x00, 0x08, 0x0c, 0x01, 0x00, 0x08, 0x80, 0x06, -0x00, 0x08, 0x0c, 0x01, 0x00, 0x04, 0x9d, 0x0f, -0x00, 0x03, 0x12, 0x6c, 0x00, 0x08, 0xd8, 0x01, -0x00, 0x08, 0x6c, 0x00, 0x00, 0x06, 0x01, 0x00, -0x00, 0x0c, 0x98, 0x64, 0x00, 0x08, 0x58, 0x00, -0x00, 0x08, 0xfc, 0x3f, 0x00, 0x0d, 0x02, 0x97, -0x00, 0x08, 0xfc, 0x3f, 0x00, 0x0d, 0x02, 0x95, -0x00, 0x0d, 0x01, 0xf7, 0x00, 0x06, 0x5d, 0x01, -0x00, 0x0c, 0xa0, 0x6c, 0x00, 0x0c, 0xd8, 0x6b, -0x00, 0x09, 0x20, 0xe5, 0x00, 0x09, 0x62, 0xe6, -0x00, 0x09, 0x5e, 0xe3, 0x00, 0x09, 0x60, 0xc2, -0x00, 0x08, 0x5c, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x02, 0x00, 0x2d, 0x00, 0x0c, 0xa0, 0x75, -0x00, 0x08, 0xda, 0x00, 0x00, 0x0c, 0xd0, 0x76, -0x00, 0x08, 0x50, 0x00, 0x00, 0x08, 0x23, 0xff, -0x00, 0x08, 0x24, 0x00, 0x00, 0x08, 0x0c, 0x0a, -0x00, 0x08, 0xe6, 0x32, 0x00, 0x04, 0x8d, 0x06, -0x00, 0x08, 0xe8, 0x00, 0x00, 0x08, 0x0c, 0x03, -0x00, 0x04, 0x8d, 0x0d, 0x00, 0x08, 0xaa, 0x00, -0x00, 0x08, 0x0c, 0x10, 0x00, 0x06, 0x2b, 0x01, -0x00, 0x0c, 0xa8, 0x8c, 0x00, 0x06, 0x6d, 0x00, -0x00, 0x0c, 0xa8, 0x8a, 0x00, 0x08, 0x80, 0x2c, -0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0xd8, 0x00, -0x00, 0x08, 0x6c, 0x01, 0x00, 0x0d, 0x00, 0xab, -0x00, 0x08, 0x58, 0x00, 0x00, 0x0d, 0x00, 0xab, -0x00, 0x06, 0x2b, 0x02, 0x00, 0x0c, 0xa8, 0x97, -0x00, 0x06, 0x6d, 0x00, 0x00, 0x0c, 0xa0, 0x99, -0x00, 0x08, 0x58, 0x00, 0x00, 0x0d, 0x00, 0x9a, -0x00, 0x08, 0x02, 0x03, 0x00, 0x06, 0x5b, 0x01, -0x00, 0x0c, 0xa8, 0xb0, 0x00, 0x08, 0x02, 0x01, -0x00, 0x0d, 0x00, 0xb0, 0x00, 0x06, 0xd9, 0x01, -0x00, 0x0c, 0xa0, 0x9a, 0x00, 0x08, 0x58, 0x03, -0x00, 0x08, 0xfc, 0x3f, 0x00, 0x0d, 0x02, 0xab, -0x00, 0x08, 0xd4, 0x02, 0x00, 0x08, 0xae, 0x00, -0x00, 0x08, 0xac, 0x03, 0x00, 0x01, 0xc1, 0x9e, -0x00, 0x02, 0xc1, 0x9f, 0x00, 0x08, 0x80, 0x00, -0x00, 0x06, 0x2b, 0x03, 0x00, 0x0c, 0xa8, 0xab, -0x00, 0x08, 0xfc, 0x3f, 0x00, 0x0d, 0x02, 0xab, -0x00, 0x08, 0xd6, 0x02, 0x00, 0x08, 0xb2, 0x00, -0x00, 0x08, 0xb0, 0x03, 0x00, 0x01, 0xc1, 0xa0, -0x00, 0x02, 0xc1, 0xa1, 0x00, 0x08, 0xfc, 0x3f, -0x00, 0x0d, 0x02, 0x97, 0x00, 0x08, 0x82, 0x15, -0x00, 0x06, 0xd9, 0x02, 0x00, 0x0c, 0xa8, 0x92, -0x00, 0x09, 0x02, 0xe7, 0x00, 0x08, 0xfc, 0x3f, -0x00, 0x0d, 0x02, 0x95, 0x00, 0x08, 0x88, 0x0d, -0x00, 0x08, 0x90, 0x04, 0x00, 0x08, 0x92, 0x04, -0x00, 0x08, 0x94, 0x04, 0x00, 0x08, 0x45, 0xfe, -0x00, 0x08, 0x34, 0x00, 0x00, 0x08, 0x36, 0x00, -0x00, 0x08, 0x38, 0x00, 0x00, 0x08, 0x3a, 0x00, -0x00, 0x08, 0x0c, 0x05, 0x00, 0x04, 0x8d, 0x0b, -0x00, 0x09, 0x00, 0xc0, 0x00, 0x08, 0x46, 0x01, -0x00, 0x08, 0x0c, 0x01, 0x00, 0x08, 0x80, 0x28, -0x00, 0x08, 0x0c, 0x1c, 0x00, 0x08, 0x0e, 0x01, -0x00, 0x08, 0xce, 0x00, 0x00, 0x06, 0x0f, 0x22, -0x00, 0x0c, 0xa0, 0xc2, 0x00, 0x0c, 0x82, 0x7c, -0x00, 0x00, 0x80, 0xa2, 0x00, 0x06, 0x47, 0x00, -0x00, 0x08, 0xd0, 0x00, 0x00, 0x0c, 0xaa, 0x77, -0x00, 0x08, 0x4c, 0x01, 0x00, 0x0d, 0x02, 0x85, -0x00, 0x06, 0x5b, 0x00, 0x00, 0x0c, 0xa2, 0xbe, -0x00, 0x08, 0x52, 0x00, 0x00, 0x08, 0x4c, 0x00, -0x00, 0x08, 0xfc, 0x3f, 0x00, 0x0d, 0x02, 0xd5, -0x00, 0x09, 0x52, 0xe0, 0x00, 0x06, 0x2b, 0x01, -0x00, 0x0c, 0xa0, 0xf0, 0x00, 0x08, 0x0c, 0x1c, -0x00, 0x06, 0x2b, 0x03, 0x00, 0x0c, 0xa1, 0x01, -0x00, 0x0c, 0x91, 0xff, 0x00, 0x08, 0x0e, 0x02, -0x00, 0x08, 0x80, 0x00, 0x00, 0x06, 0x8f, 0x01, -0x00, 0x0c, 0xa8, 0xf8, 0x00, 0x08, 0xa6, 0x07, -0x00, 0x08, 0x52, 0x20, 0x00, 0x08, 0x80, 0x00, -0x00, 0x06, 0xa7, 0x08, 0x00, 0x0c, 0xa9, 0x0c, -0x00, 0x08, 0x34, 0x00, 0x00, 0x08, 0x36, 0x00, -0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, -0x00, 0x08, 0x8a, 0x2a, 0x00, 0x08, 0x48, 0x03, -0x00, 0x08, 0x46, 0x06, 0x00, 0x08, 0xfc, 0x3f, -0x00, 0x0d, 0x02, 0x23, 0x00, 0x06, 0x4d, 0x00, -0x00, 0x0c, 0xa9, 0x66, 0x00, 0x0d, 0x01, 0x0c, -0x00, 0x08, 0x0c, 0x01, 0x00, 0x06, 0x0d, 0x00, -0x00, 0x0c, 0x80, 0xf6, 0x00, 0x08, 0x0c, 0x01, -0x00, 0x08, 0x26, 0x11, 0x00, 0x0d, 0x01, 0x0e, -0x00, 0x08, 0x26, 0x01, 0x00, 0x0d, 0x01, 0x0e, -0x00, 0x06, 0xd9, 0x02, 0x00, 0x0c, 0xa1, 0x0c, -0x00, 0x08, 0xa6, 0x07, 0x00, 0x08, 0x52, 0x00, -0x00, 0x08, 0x46, 0x06, 0x00, 0x08, 0x48, 0x03, -0x00, 0x08, 0xfc, 0x3f, 0x00, 0x0d, 0x02, 0x23, -0x00, 0x0d, 0x01, 0x0c, 0x00, 0x08, 0x0e, 0x03, -0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x8f, 0x01, -0x00, 0x0c, 0xa8, 0xf8, 0x00, 0x06, 0x8f, 0x04, -0x00, 0x0c, 0xa1, 0x08, 0x00, 0x03, 0x01, 0x04, -0x00, 0x06, 0x8f, 0x08, 0x00, 0x0c, 0xa1, 0x0b, -0x00, 0x03, 0x01, 0x20, 0x00, 0x08, 0xd2, 0x00, -0x00, 0x08, 0xa6, 0x07, 0x00, 0x08, 0x80, 0x00, -0x00, 0x06, 0xa7, 0x10, 0x00, 0x0c, 0xa1, 0x13, -0x00, 0x08, 0x0c, 0x05, 0x00, 0x04, 0x8d, 0x0b, -0x00, 0x09, 0x00, 0xc0, 0x00, 0x06, 0xa7, 0x08, -0x00, 0x0c, 0xa1, 0x2f, 0x00, 0x08, 0x88, 0x17, -0x00, 0x08, 0x8a, 0x1e, 0x00, 0x08, 0x84, 0x1f, -0x00, 0x08, 0x80, 0x16, 0x00, 0x08, 0x86, 0x1a, -0x00, 0x08, 0xc8, 0x02, 0x00, 0x08, 0xc6, 0x03, -0x00, 0x08, 0xfc, 0x3f, 0x00, 0x0d, 0x02, 0x00, -0x00, 0x08, 0x84, 0x1b, 0x00, 0x08, 0x80, 0x16, -0x00, 0x08, 0xb4, 0x01, 0x00, 0x08, 0xc6, 0x02, -0x00, 0x08, 0xfc, 0x3f, 0x00, 0x0d, 0x02, 0x00, -0x00, 0x08, 0xb6, 0x01, 0x00, 0x08, 0x80, 0x00, -0x00, 0x06, 0xa7, 0x08, 0x00, 0x0c, 0xa1, 0x2f, -0x00, 0x08, 0x82, 0x1b, 0x00, 0x08, 0x80, 0x1a, -0x00, 0x08, 0x8a, 0x2a, 0x00, 0x08, 0x46, 0x06, -0x00, 0x08, 0x48, 0x03, 0x00, 0x08, 0xfc, 0x3f, -0x00, 0x0d, 0x02, 0x23, 0x00, 0x06, 0xa7, 0x04, -0x00, 0x0c, 0xa1, 0x4e, 0x00, 0x06, 0x4d, 0x00, -0x00, 0x0c, 0xa9, 0x44, 0x00, 0x08, 0x80, 0x18, -0x00, 0x08, 0x88, 0x19, 0x00, 0x08, 0x8a, 0x20, -0x00, 0x08, 0x84, 0x21, 0x00, 0x08, 0x86, 0x1c, -0x00, 0x08, 0xc8, 0x02, 0x00, 0x08, 0xc6, 0x03, -0x00, 0x08, 0xfc, 0x3f, 0x00, 0x0d, 0x02, 0x00, -0x00, 0x08, 0xb8, 0x01, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x84, 0x1d, 0x00, 0x08, 0x80, 0x18, -0x00, 0x08, 0xc6, 0x02, 0x00, 0x08, 0xfc, 0x3f, -0x00, 0x0d, 0x02, 0x00, 0x00, 0x08, 0xba, 0x01, -0x00, 0x0c, 0xc9, 0x44, 0x00, 0x08, 0x82, 0x1d, -0x00, 0x08, 0x80, 0x1c, 0x00, 0x08, 0x8a, 0x2b, -0x00, 0x08, 0x46, 0x06, 0x00, 0x08, 0x48, 0x00, -0x00, 0x08, 0xfc, 0x3f, 0x00, 0x0d, 0x02, 0x23, -0x00, 0x06, 0x4d, 0x00, 0x00, 0x0c, 0xa9, 0x66, -0x00, 0x06, 0x4d, 0x00, 0x00, 0x0c, 0xa9, 0x58, -0x00, 0x06, 0xa7, 0x02, 0x00, 0x08, 0x28, 0x00, -0x00, 0x0c, 0xa1, 0x58, 0x00, 0x08, 0x0c, 0x1c, -0x00, 0x08, 0x0e, 0x04, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0xa8, 0x07, 0x00, 0x08, 0x80, 0x00, -0x00, 0x06, 0xd9, 0x02, 0x00, 0x0c, 0xa1, 0x5c, -0x00, 0x08, 0x00, 0x00, 0x00, 0x0d, 0x01, 0x5e, -0x00, 0x08, 0x80, 0x13, 0x00, 0x01, 0x01, 0x01, -0x00, 0x09, 0x00, 0xc1, 0x00, 0x06, 0xa7, 0x01, -0x00, 0x0c, 0xa1, 0x66, 0x00, 0x08, 0x28, 0x3f, -0x00, 0x08, 0x34, 0x00, 0x00, 0x08, 0x36, 0x00, -0x00, 0x08, 0x38, 0x00, 0x00, 0x08, 0x3a, 0x00, -0x00, 0x08, 0x46, 0x06, 0x00, 0x0c, 0xd9, 0x69, -0x00, 0x0d, 0x01, 0xff, 0x00, 0x0c, 0xd1, 0x67, -0x00, 0x0c, 0xc9, 0x6b, 0x00, 0x08, 0x00, 0x01, -0x00, 0x01, 0x80, 0x23, 0x00, 0x06, 0xa7, 0x01, -0x00, 0x08, 0xc6, 0x00, 0x00, 0x0c, 0xa1, 0xa5, -0x00, 0x08, 0x0c, 0x1c, 0x00, 0x06, 0x47, 0x02, -0x00, 0x0c, 0x81, 0x75, 0x00, 0x08, 0x0e, 0x06, -0x00, 0x0d, 0x01, 0x76, 0x00, 0x08, 0x0e, 0x07, -0x00, 0x08, 0x08, 0x00, 0x00, 0x06, 0x0f, 0x00, -0x00, 0x0c, 0xa1, 0x85, 0x00, 0x08, 0xfa, 0x07, -0x00, 0x08, 0x8c, 0x3d, 0x00, 0x05, 0x4f, 0x10, -0x00, 0x04, 0xe9, 0x84, 0x00, 0x01, 0x90, 0x07, -0x00, 0x03, 0xa2, 0x81, 0x00, 0x06, 0x88, 0x02, -0x00, 0x0c, 0xa9, 0x85, 0x00, 0x08, 0x05, 0xff, -0x00, 0x03, 0xaf, 0x82, 0x00, 0x02, 0x10, 0x04, -0x00, 0x03, 0x15, 0x84, 0x00, 0x03, 0xc9, 0x03, -0x00, 0x06, 0x47, 0x04, 0x00, 0x0c, 0x91, 0x96, -0x00, 0x06, 0x47, 0x02, 0x00, 0x0c, 0x81, 0x96, -0x00, 0x00, 0xc8, 0x48, 0x00, 0x0d, 0x01, 0x9f, -0x00, 0x06, 0x47, 0x04, 0x00, 0x0c, 0x91, 0x8a, -0x00, 0x06, 0x47, 0x01, 0x00, 0x0c, 0xa1, 0x93, -0x00, 0x00, 0xc8, 0x4a, 0x00, 0x08, 0x94, 0x04, -0x00, 0x0d, 0x01, 0xa0, 0x00, 0x00, 0xc8, 0x49, -0x00, 0x08, 0x92, 0x04, 0x00, 0x0d, 0x01, 0xa0, -0x00, 0x08, 0x84, 0x28, 0x00, 0x05, 0x14, 0x22, -0x00, 0x06, 0x03, 0x01, 0x00, 0x0c, 0xa1, 0x8c, -0x00, 0x00, 0xc8, 0x4d, 0x00, 0x06, 0x47, 0x01, -0x00, 0x0c, 0xa1, 0x94, 0x00, 0x06, 0x47, 0x00, -0x00, 0x0c, 0xa1, 0x91, 0x00, 0x08, 0x90, 0x04, -0x00, 0x08, 0x0a, 0x80, 0x00, 0x06, 0xd9, 0x02, -0x00, 0x0c, 0xa9, 0xcc, 0x00, 0x08, 0x8b, 0x44, -0x00, 0x0d, 0x01, 0xbc, 0x00, 0x06, 0x47, 0x00, -0x00, 0x0c, 0xa1, 0xaf, 0x00, 0x06, 0xd3, 0x20, -0x00, 0x0c, 0xa1, 0xaf, 0x00, 0x08, 0x80, 0x1a, -0x00, 0x08, 0x82, 0x1b, 0x00, 0x08, 0x8a, 0x2a, -0x00, 0x08, 0x48, 0x03, 0x00, 0x08, 0xfc, 0x3f, -0x00, 0x0d, 0x02, 0x23, 0x00, 0x06, 0x4d, 0x00, -0x00, 0x0c, 0xa9, 0xd5, 0x00, 0x08, 0x80, 0x23, -0x00, 0x03, 0x80, 0x81, 0x00, 0x06, 0x80, 0x14, -0x00, 0x0c, 0xa1, 0xd5, 0x00, 0x08, 0x0c, 0x1c, -0x00, 0x08, 0x0e, 0x08, 0x00, 0x08, 0x0a, 0x80, -0x00, 0x00, 0xda, 0x3c, 0x00, 0x06, 0xd9, 0x02, -0x00, 0x0c, 0xa9, 0xd1, 0x00, 0x08, 0x8b, 0x47, -0x00, 0x08, 0x7a, 0x1c, 0x00, 0x08, 0x8c, 0x3d, -0x00, 0x08, 0x0e, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x0c, 0xb1, 0xd5, 0x00, 0x00, 0xda, 0x3c, -0x00, 0x02, 0x50, 0x05, 0x00, 0x08, 0x8b, 0xc7, -0x00, 0x0c, 0xc1, 0xc0, 0x00, 0x08, 0x52, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x09, 0x52, 0xe0, -0x00, 0x0c, 0xb1, 0xd5, 0x00, 0x08, 0x8c, 0x3d, -0x00, 0x0c, 0xc1, 0xc8, 0x00, 0x0d, 0x01, 0xc8, -0x00, 0x06, 0x47, 0x00, 0x00, 0x0c, 0xa1, 0xd1, -0x00, 0x08, 0x48, 0x03, 0x00, 0x08, 0xfc, 0x3f, -0x00, 0x0d, 0x02, 0x23, 0x00, 0x08, 0x7a, 0x1c, -0x00, 0x08, 0x8c, 0x3d, 0x00, 0x08, 0x0e, 0x00, -0x00, 0x0d, 0x01, 0xc8, 0x00, 0x06, 0x47, 0x00, -0x00, 0x0c, 0xa1, 0xdf, 0x00, 0x06, 0xd3, 0x04, -0x00, 0x0c, 0xa1, 0xdf, 0x00, 0x08, 0x80, 0x1c, -0x00, 0x08, 0x82, 0x1d, 0x00, 0x08, 0x8a, 0x2b, -0x00, 0x08, 0x48, 0x00, 0x00, 0x08, 0xfc, 0x3f, -0x00, 0x0d, 0x02, 0x23, 0x00, 0x08, 0x82, 0x29, -0x00, 0x01, 0x13, 0x24, 0x00, 0x06, 0x47, 0x00, -0x00, 0x08, 0xd2, 0x01, 0x00, 0x0c, 0xa9, 0x67, -0x00, 0x06, 0x4d, 0x00, 0x00, 0x0c, 0xaa, 0x8d, -0x00, 0x06, 0xa7, 0x01, 0x00, 0x0c, 0xa1, 0xea, -0x00, 0x08, 0x80, 0x28, 0x00, 0x08, 0xc4, 0x00, -0x00, 0x08, 0x0c, 0x1c, 0x00, 0x08, 0x0e, 0x01, -0x00, 0x08, 0x80, 0x28, 0x00, 0x06, 0x0f, 0x24, -0x00, 0x0c, 0xa1, 0xf1, 0x00, 0x08, 0xce, 0x00, -0x00, 0x0d, 0x00, 0xc5, 0x00, 0x08, 0xfc, 0x3f, -0x00, 0x0d, 0x02, 0x97, 0x00, 0x06, 0x01, 0x01, -0x00, 0x0c, 0x81, 0xf7, 0x00, 0x06, 0x01, 0xaf, -0x00, 0x0c, 0x88, 0xb3, 0x00, 0x06, 0x01, 0x00, -0x00, 0x0c, 0xa0, 0x69, 0x00, 0x06, 0x01, 0xb8, -0x00, 0x0c, 0xa0, 0x54, 0x00, 0x06, 0x01, 0xb3, -0x00, 0x0c, 0xa0, 0x12, 0x00, 0x06, 0x01, 0xb7, -0x00, 0x0c, 0xa2, 0xbe, 0x00, 0x0d, 0x00, 0x09, -0x00, 0x08, 0x0c, 0x1c, 0x00, 0x08, 0x0e, 0x05, -0x00, 0x08, 0x02, 0x00, 0x00, 0x08, 0x86, 0x07, -0x00, 0x03, 0x88, 0x81, 0x00, 0x06, 0x01, 0x01, -0x00, 0x0c, 0xa2, 0x0f, 0x00, 0x06, 0x07, 0x00, -0x00, 0x0c, 0xa2, 0x0f, 0x00, 0x08, 0xfa, 0x04, -0x00, 0x08, 0x8c, 0x3d, 0x00, 0x05, 0x29, 0x10, -0x00, 0x04, 0xe5, 0x82, 0x00, 0x05, 0x10, 0x81, -0x00, 0x05, 0x23, 0x81, 0x00, 0x08, 0x04, 0x00, -0x00, 0x03, 0xb9, 0x83, 0x00, 0x06, 0x07, 0x00, -0x00, 0x0c, 0xa2, 0x1b, 0x00, 0x03, 0xa1, 0x05, -0x00, 0x06, 0x07, 0x00, 0x00, 0x0c, 0x92, 0x19, -0x00, 0x00, 0x97, 0x83, 0x00, 0x00, 0xa7, 0x82, -0x00, 0x0d, 0x02, 0x1b, 0x00, 0x05, 0x17, 0x83, -0x00, 0x05, 0x27, 0x82, 0x00, 0x00, 0x96, 0x23, -0x00, 0x06, 0x02, 0x05, 0x00, 0x0c, 0x92, 0x21, -0x00, 0x06, 0x48, 0x01, 0x00, 0x0c, 0x92, 0x21, -0x00, 0x08, 0xfe, 0x3e, 0x00, 0x00, 0x94, 0x23, -0x00, 0x08, 0xfe, 0x3e, 0x00, 0x06, 0xd9, 0x02, -0x00, 0x0c, 0xa2, 0x27, 0x00, 0x08, 0x00, 0x00, -0x00, 0x08, 0x02, 0x00, 0x00, 0x06, 0x0b, 0x01, -0x00, 0x0c, 0xaa, 0x2b, 0x00, 0x03, 0x81, 0x01, -0x00, 0x03, 0x93, 0x01, 0x00, 0x06, 0x47, 0x02, -0x00, 0x0c, 0x92, 0x41, 0x00, 0x06, 0x01, 0x00, -0x00, 0x0c, 0x9a, 0x30, 0x00, 0x00, 0x81, 0x01, -0x00, 0x04, 0x21, 0x01, 0x00, 0x04, 0x05, 0x01, -0x00, 0x03, 0xc1, 0x01, 0x00, 0x05, 0x45, 0x82, -0x00, 0x06, 0x03, 0x00, 0x00, 0x0c, 0x9a, 0x37, -0x00, 0x00, 0x93, 0x01, 0x00, 0x04, 0x33, 0x01, -0x00, 0x04, 0x17, 0x01, 0x00, 0x03, 0xc3, 0x01, -0x00, 0x05, 0x47, 0x83, 0x00, 0x08, 0x0a, 0x03, -0x00, 0x03, 0xca, 0x11, 0x00, 0x00, 0xc1, 0x80, -0x00, 0x03, 0xca, 0x12, 0x00, 0x00, 0xc3, 0x81, -0x00, 0x0d, 0x02, 0x4a, 0x00, 0x01, 0x21, 0x01, -0x00, 0x04, 0x01, 0x01, 0x00, 0x01, 0x33, 0x01, -0x00, 0x04, 0x13, 0x01, 0x00, 0x08, 0x0a, 0x04, -0x00, 0x03, 0xca, 0x11, 0x00, 0x00, 0xc1, 0x80, -0x00, 0x03, 0xca, 0x12, 0x00, 0x00, 0xc3, 0x81, -0x00, 0x08, 0x88, 0x29, 0x00, 0x03, 0xa4, 0x64, -0x00, 0x03, 0x45, 0x84, 0x00, 0x02, 0x50, 0x24, -0x00, 0x03, 0xbb, 0x83, 0x00, 0x03, 0x47, 0x84, -0x00, 0x01, 0x28, 0xa4, 0x00, 0x06, 0x05, 0x24, -0x00, 0x0c, 0xaa, 0x58, 0x00, 0x06, 0x49, 0x00, -0x00, 0x0c, 0xaa, 0x58, 0x00, 0x0c, 0xda, 0x57, -0x00, 0x0d, 0x01, 0xff, 0x00, 0x0c, 0xca, 0x55, -0x00, 0x06, 0xd9, 0x02, 0x00, 0x0c, 0xa2, 0x5f, -0x00, 0x06, 0x6d, 0x00, 0x00, 0x0c, 0xa2, 0x5e, -0x00, 0x08, 0x08, 0x04, 0x00, 0x0d, 0x02, 0x5f, -0x00, 0x08, 0x08, 0x20, 0x00, 0x08, 0xd2, 0x04, -0x00, 0x09, 0x08, 0xe0, 0x00, 0x01, 0xc0, 0x23, -0x00, 0x03, 0xc9, 0x01, 0x00, 0x08, 0x0a, 0x26, -0x00, 0x03, 0xdb, 0x04, 0x00, 0x03, 0x5b, 0x08, -0x00, 0x00, 0xd9, 0x84, 0x00, 0x08, 0xfe, 0x04, -0x00, 0x0d, 0x02, 0x72, 0x00, 0x08, 0x80, 0x00, -0x00, 0x0d, 0x02, 0x72, 0x00, 0x08, 0x80, 0x00, -0x00, 0x00, 0x81, 0x08, 0x00, 0x0d, 0x02, 0x75, -0x00, 0x00, 0x93, 0x08, 0x00, 0x0d, 0x02, 0x72, -0x00, 0x00, 0x81, 0x08, 0x00, 0x08, 0x80, 0x00, -0x00, 0x09, 0x00, 0xe1, 0x00, 0x09, 0x02, 0xe2, -0x00, 0x08, 0xfe, 0x3e, 0x00, 0x00, 0x93, 0x08, -0x00, 0x0d, 0x02, 0x72, 0x00, 0x08, 0x0c, 0x1c, -0x00, 0x08, 0x0e, 0x01, 0x00, 0x08, 0x80, 0x00, -0x00, 0x06, 0x0f, 0x23, 0x00, 0x0c, 0xa0, 0xc8, -0x00, 0x08, 0x82, 0x28, 0x00, 0x08, 0xce, 0x01, -0x00, 0x00, 0xf3, 0x80, 0x00, 0x08, 0xd0, 0x00, -0x00, 0x06, 0x0f, 0x01, 0x00, 0x0c, 0xa0, 0xce, -0x00, 0x06, 0x47, 0x00, 0x00, 0x0c, 0xa8, 0xce, -0x00, 0x08, 0x4c, 0x02, 0x00, 0x08, 0x00, 0x00, -0x00, 0x09, 0x00, 0xc1, 0x00, 0x08, 0xfc, 0x3f, -0x00, 0x0d, 0x02, 0xd5, 0x00, 0x06, 0x2b, 0x02, -0x00, 0x0c, 0xa9, 0x26, 0x00, 0x08, 0x26, 0x00, -0x00, 0x0d, 0x00, 0xe0, 0x00, 0x02, 0x00, 0x27, -0x00, 0x02, 0x10, 0x00, 0x00, 0x06, 0x50, 0x01, -0x00, 0x08, 0xce, 0x00, 0x00, 0x0c, 0x92, 0x85, -0x00, 0x06, 0x4d, 0x01, 0x00, 0x0c, 0xa2, 0x77, -0x00, 0x0d, 0x00, 0xce, 0x00, 0x06, 0x01, 0xb2, -0x00, 0x0c, 0xaa, 0xa7, 0x00, 0x08, 0x0d, 0x08, -0x00, 0x06, 0x0d, 0x00, 0x00, 0x0c, 0xaa, 0x97, -0x00, 0x08, 0x0c, 0x08, 0x00, 0x04, 0x8d, 0x08, -0x00, 0x0c, 0xaa, 0x97, 0x00, 0x08, 0x0c, 0x10, -0x00, 0x06, 0x0d, 0x00, 0x00, 0x0c, 0xa2, 0x9d, -0x00, 0x06, 0x0d, 0x01, 0x00, 0x0c, 0xa2, 0xa8, -0x00, 0x04, 0x8d, 0x08, 0x00, 0x06, 0x01, 0x01, -0x00, 0x0c, 0xaa, 0x97, 0x00, 0x03, 0x8d, 0x08, -0x00, 0x04, 0x81, 0x08, 0x00, 0x08, 0xfe, 0x3e, -0x00, 0x08, 0x0c, 0x08, 0x00, 0x04, 0x8d, 0x08, -0x00, 0x08, 0xfe, 0x3e, 0x00, 0x08, 0x0c, 0x01, -0x00, 0x04, 0xad, 0x0f, 0x00, 0x08, 0x0c, 0x03, -0x00, 0x04, 0x8d, 0x0d, 0x00, 0x06, 0x67, 0xff, -0x00, 0x0c, 0xa2, 0xba, 0x00, 0x08, 0x82, 0x33, -0x00, 0x05, 0x92, 0x34, 0x00, 0x01, 0x13, 0x1f, -0x00, 0x02, 0x10, 0x01, 0x00, 0x00, 0x83, 0x80, -0x00, 0x06, 0x01, 0x07, 0x00, 0x0c, 0x8a, 0xba, -0x00, 0x05, 0x00, 0x87, 0x00, 0x0d, 0x02, 0xb6, -0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0xb0, 0x81, -0x00, 0x03, 0xc7, 0x04, 0x00, 0x08, 0xfe, 0x3e, -0x00, 0x06, 0x5b, 0x01, 0x00, 0x0c, 0xa2, 0xc2, -0x00, 0x09, 0x00, 0xe8, 0x00, 0x0d, 0x00, 0x01, -0x00, 0x0c, 0xda, 0xc2, 0x00, 0x08, 0x5a, 0x00, -0x00, 0x08, 0x23, 0xff, 0x00, 0x08, 0x24, 0x00, -0x00, 0x08, 0x4e, 0x00, 0x00, 0x08, 0x2a, 0x02, -0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x2a, 0xe7, -0x00, 0x08, 0x82, 0x10, 0x00, 0x00, 0x80, 0x71, -0x00, 0x01, 0x90, 0x01, 0x00, 0x0c, 0xaa, 0xcb, -0x00, 0x02, 0x01, 0xa8, 0x00, 0x08, 0x4c, 0x02, -0x00, 0x0d, 0x02, 0x85, 0x00, 0x08, 0xe4, 0x33, -0x00, 0x08, 0x60, 0x00, 0x00, 0x08, 0x6a, 0x01, -0x00, 0x0d, 0x00, 0x2f, 0x00, 0x02, 0x00, 0x11, -0x00, 0x06, 0x20, 0x00, 0x00, 0x08, 0xa2, 0x00, -0x00, 0x0c, 0x92, 0xdd, 0x00, 0x02, 0x00, 0x12, -0x00, 0x08, 0x22, 0x00, 0x00, 0x08, 0xa4, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0xfe, 0x3e, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, -0x0a, 0x0d, -}; -static uchar -zrmpeg2[] = { -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0xc1, 0x81, -0x00, 0x02, 0xee, 0x00, 0x00, 0x03, 0x2e, 0x01, -0x00, 0x02, 0xee, 0x00, 0x00, 0x03, 0x47, 0x17, -0x00, 0x03, 0x2e, 0x02, 0x00, 0x02, 0xee, 0x00, -0x00, 0x03, 0x74, 0x17, 0x00, 0x02, 0x9c, 0x02, -0x00, 0x03, 0x88, 0x0c, 0x00, 0x03, 0x46, 0x81, -0x00, 0x03, 0x50, 0x07, 0x00, 0x02, 0x80, 0x80, -0x00, 0x03, 0x88, 0x13, 0x00, 0x03, 0x43, 0x81, -0x00, 0x02, 0x9c, 0x01, 0x00, 0x03, 0x88, 0x14, -0x00, 0x03, 0x48, 0x80, 0x00, 0x03, 0x40, 0x80, -0x00, 0x02, 0x9c, 0x80, 0x00, 0x03, 0x88, 0x17, -0x00, 0x03, 0x44, 0x81, 0x00, 0x02, 0x9c, 0x04, -0x00, 0x03, 0x88, 0x1a, 0x00, 0x03, 0x45, 0x81, -0x00, 0x02, 0xee, 0x00, 0x00, 0x03, 0x50, 0x17, -0x00, 0x00, 0x5c, 0x8f, 0x00, 0x02, 0x84, 0x01, -0x00, 0x03, 0x88, 0x20, 0x00, 0x03, 0x49, 0x81, -0x00, 0x02, 0xee, 0x00, 0x00, 0x00, 0x5d, 0x0f, -0x00, 0x00, 0xc9, 0x04, 0x00, 0x03, 0x4d, 0x12, -0x00, 0x00, 0xa4, 0x2d, 0x00, 0x02, 0xe8, 0x00, -0x00, 0x02, 0x80, 0x01, 0x00, 0x03, 0x8a, 0x29, -0x00, 0x02, 0xe8, 0x01, 0x00, 0x03, 0x4d, 0x14, -0x00, 0x00, 0x41, 0x10, 0x00, 0x01, 0x49, 0x02, -0x00, 0x00, 0xab, 0x6d, 0x00, 0x00, 0x41, 0x20, -0x00, 0x01, 0x49, 0x02, 0x00, 0x00, 0xaa, 0x0d, -0x00, 0x02, 0x9c, 0x01, 0x00, 0x03, 0x8a, 0x33, -0x00, 0x00, 0x92, 0x10, 0x00, 0x03, 0x4d, 0x14, -0x00, 0x00, 0x5d, 0x10, 0x00, 0x00, 0xc9, 0x02, -0x00, 0x00, 0xab, 0x6d, 0x00, 0x00, 0x5d, 0x20, -0x00, 0x00, 0xc9, 0x02, 0x00, 0x00, 0xaa, 0x0d, -0x00, 0x02, 0xee, 0x00, 0x00, 0x03, 0x28, 0x5f, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x42, 0x17, -0x00, 0x03, 0x2e, 0x20, 0x00, 0x01, 0xdc, 0x01, -0x00, 0x03, 0xa6, 0x43, 0x00, 0x03, 0x4d, 0x17, -0x00, 0x00, 0x20, 0x0d, 0x00, 0x03, 0x20, 0x17, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x2e, 0x21, -0x00, 0x00, 0x3c, 0x02, 0x00, 0x03, 0x20, 0x24, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x75, 0x17, -0x00, 0x03, 0x2e, 0x68, 0x00, 0x02, 0xef, 0x00, -0x00, 0x03, 0x43, 0x17, 0x00, 0x02, 0xef, 0x00, -0x00, 0x03, 0x44, 0x17, 0x00, 0x02, 0xef, 0x00, -0x00, 0x03, 0x45, 0x17, 0x00, 0x00, 0x1c, 0x01, -0x00, 0x03, 0x46, 0x10, 0x00, 0x00, 0x20, 0x02, -0x00, 0x03, 0x47, 0x10, 0x00, 0x00, 0x22, 0x23, -0x00, 0x00, 0x20, 0x02, 0x00, 0x03, 0x49, 0x10, -0x00, 0x00, 0x23, 0xa3, 0x00, 0x03, 0x50, 0x35, -0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xe0, 0x04, -0x00, 0x03, 0xa6, 0x5e, 0x00, 0x01, 0xe0, 0x02, -0x00, 0x03, 0x4f, 0x10, 0x00, 0x00, 0x20, 0x02, -0x00, 0x03, 0x58, 0x10, 0x00, 0x03, 0x50, 0x35, -0x00, 0x01, 0x40, 0x01, 0x00, 0x00, 0x00, 0x01, -0x00, 0x00, 0x20, 0x83, 0x00, 0x03, 0x59, 0x11, -0x00, 0x01, 0xe0, 0x84, 0x00, 0x03, 0x5a, 0x11, -0x00, 0x02, 0xe2, 0x01, 0x00, 0x00, 0x26, 0x83, -0x00, 0x00, 0x36, 0xa5, 0x00, 0x03, 0x14, 0x69, -0x00, 0x03, 0x10, 0x6a, 0x00, 0x03, 0xa6, 0x6f, -0x00, 0x03, 0x1c, 0x6a, 0x00, 0x03, 0x1e, 0x6b, -0x00, 0x03, 0xa6, 0x72, 0x00, 0x03, 0x30, 0x6b, -0x00, 0x03, 0x2a, 0x6c, 0x00, 0x03, 0xa8, 0x77, -0x00, 0x03, 0x0e, 0x6c, 0x00, 0x03, 0xa6, 0x77, -0x00, 0x03, 0x12, 0x6c, 0x00, 0x03, 0x32, 0x6d, -0x00, 0x03, 0x34, 0x6e, 0x00, 0x03, 0xa8, 0x7c, -0x00, 0x03, 0x0c, 0x6d, 0x00, 0x03, 0x2a, 0x6e, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x42, 0x17, -0x00, 0x03, 0x2e, 0x22, 0x00, 0x00, 0x1c, 0x01, -0x00, 0x01, 0x40, 0x01, 0x00, 0x00, 0xc0, 0x01, -0x00, 0x03, 0x20, 0x18, 0x00, 0x02, 0xef, 0x00, -0x00, 0x03, 0x73, 0x17, 0x00, 0x03, 0x2e, 0x23, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x76, 0x17, -0x00, 0x03, 0x2e, 0x60, 0x00, 0x01, 0x5f, 0x01, -0x00, 0x02, 0x9c, 0x01, 0x00, 0x03, 0x88, 0x8d, -0x00, 0x03, 0x41, 0x81, 0x00, 0x02, 0xef, 0x00, -0x00, 0x03, 0x43, 0x17, 0x00, 0x03, 0x2e, 0x61, -0x00, 0x02, 0x9c, 0x01, 0x00, 0x03, 0x88, 0x94, -0x00, 0x03, 0x42, 0x81, 0x00, 0x03, 0x47, 0x80, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x44, 0x17, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x45, 0x17, -0x00, 0x03, 0x4d, 0x33, 0x00, 0x01, 0xff, 0x2d, -0x00, 0x03, 0x73, 0x0c, 0x00, 0x03, 0x5b, 0x1f, -0x00, 0x03, 0x8f, 0x94, 0x00, 0x03, 0x4d, 0x36, -0x00, 0x03, 0x50, 0x05, 0x00, 0x00, 0x20, 0x02, -0x00, 0x03, 0x51, 0x03, 0x00, 0x00, 0x24, 0x84, -0x00, 0x03, 0xa6, 0xa7, 0x00, 0x00, 0xc0, 0x01, -0x00, 0x01, 0xa3, 0x6d, 0x00, 0x01, 0xa7, 0x6d, -0x00, 0x03, 0x8e, 0xab, 0x00, 0x01, 0xa0, 0x0d, -0x00, 0x00, 0xc0, 0x01, 0x00, 0x03, 0x4d, 0x11, -0x00, 0x01, 0xe3, 0x6d, 0x00, 0x03, 0x72, 0x0d, -0x00, 0x00, 0x1c, 0x81, 0x00, 0x03, 0x41, 0x11, -0x00, 0x00, 0x3d, 0xa2, 0x00, 0x02, 0xee, 0x00, -0x00, 0x00, 0x1f, 0x81, 0x00, 0x03, 0x2e, 0x6f, -0x00, 0x02, 0xee, 0x00, 0x00, 0x03, 0x4c, 0x17, -0x00, 0x03, 0x51, 0x03, 0x00, 0x01, 0x45, 0x01, -0x00, 0x00, 0x28, 0x86, 0x00, 0x03, 0x47, 0x11, -0x00, 0x00, 0x06, 0x01, 0x00, 0x03, 0x51, 0x06, -0x00, 0x00, 0xc4, 0x81, 0x00, 0x03, 0x48, 0x11, -0x00, 0x00, 0x26, 0x63, 0x00, 0x00, 0x08, 0x81, -0x00, 0x03, 0x4e, 0x11, 0x00, 0x00, 0x28, 0x05, -0x00, 0x03, 0x4f, 0x10, 0x00, 0x00, 0x00, 0x01, -0x00, 0x03, 0x71, 0x10, 0x00, 0x03, 0x50, 0x05, -0x00, 0x00, 0xc1, 0x81, 0x00, 0x03, 0x4b, 0x13, -0x00, 0x00, 0x2c, 0x03, 0x00, 0x03, 0x58, 0x10, -0x00, 0x03, 0x50, 0x36, 0x00, 0x01, 0x41, 0x81, -0x00, 0x03, 0x4d, 0x13, 0x00, 0x03, 0x52, 0x04, -0x00, 0x01, 0x48, 0x81, 0x00, 0x01, 0xa5, 0x0d, -0x00, 0x01, 0xca, 0x81, 0x00, 0x03, 0x53, 0x32, -0x00, 0x00, 0x2d, 0x08, 0x00, 0x00, 0x29, 0x03, -0x00, 0x01, 0xc9, 0x01, 0x00, 0x03, 0x56, 0x12, -0x00, 0x03, 0x52, 0x31, 0x00, 0x00, 0x2b, 0x62, -0x00, 0x01, 0x4d, 0x81, 0x00, 0x00, 0x2d, 0x8d, -0x00, 0x03, 0x5a, 0x13, 0x00, 0x01, 0xcd, 0x81, -0x00, 0x03, 0x59, 0x13, 0x00, 0x01, 0xc0, 0x01, -0x00, 0x03, 0x4d, 0x11, 0x00, 0x01, 0xe2, 0xad, -0x00, 0x03, 0x18, 0x62, 0x00, 0x03, 0x1c, 0x63, -0x00, 0x03, 0x1e, 0x64, 0x00, 0x03, 0x0e, 0x65, -0x00, 0x03, 0x32, 0x66, 0x00, 0x03, 0xa6, 0xed, -0x00, 0x03, 0xa8, 0xf2, 0x00, 0x03, 0xa3, 0x03, -0x00, 0x03, 0xab, 0x09, 0x00, 0x03, 0x0a, 0x62, -0x00, 0x03, 0x50, 0x31, 0x00, 0x03, 0x20, 0x64, -0x00, 0x03, 0x28, 0x65, 0x00, 0x03, 0x34, 0x66, -0x00, 0x03, 0x8f, 0x0c, 0x00, 0x03, 0xa9, 0x0c, -0x00, 0x03, 0xaa, 0xfb, 0x00, 0x03, 0xa2, 0xfe, -0x00, 0x03, 0x02, 0x62, 0x00, 0x03, 0x8f, 0x0c, -0x00, 0x03, 0xa2, 0xf6, 0x00, 0x03, 0xa5, 0x0c, -0x00, 0x03, 0x2a, 0x66, 0x00, 0x03, 0x8f, 0x0c, -0x00, 0x03, 0x30, 0x63, 0x00, 0x03, 0x12, 0x64, -0x00, 0x03, 0x2c, 0x65, 0x00, 0x03, 0x2a, 0x66, -0x00, 0x03, 0x8f, 0x0c, 0x00, 0x03, 0x02, 0x62, -0x00, 0x03, 0x0c, 0x65, 0x00, 0x03, 0x8f, 0x0c, -0x00, 0x03, 0x0a, 0x62, 0x00, 0x03, 0x30, 0x64, -0x00, 0x03, 0x12, 0x65, 0x00, 0x03, 0x2c, 0x66, -0x00, 0x03, 0x8f, 0x0c, 0x00, 0x03, 0x0a, 0x62, -0x00, 0x03, 0x30, 0x63, 0x00, 0x03, 0x12, 0x64, -0x00, 0x03, 0x2c, 0x65, 0x00, 0x03, 0x16, 0x66, -0x00, 0x03, 0x8f, 0x0c, 0x00, 0x03, 0x02, 0x62, -0x00, 0x03, 0x0c, 0x65, 0x00, 0x03, 0x34, 0x66, -0x00, 0x03, 0x14, 0x67, 0x00, 0x03, 0xa9, 0x0f, -0x00, 0x03, 0x10, 0x67, 0x00, 0x03, 0x4c, 0x1f, -0x00, 0x03, 0x8f, 0x86, 0x00, 0x02, 0xda, 0x44, -0x00, 0x02, 0xe2, 0x01, 0x00, 0x02, 0xe0, 0x04, -0x00, 0x02, 0xee, 0x00, 0x00, 0x03, 0x4d, 0x57, -0x00, 0x00, 0x27, 0x6d, 0x00, 0x01, 0xc0, 0x01, -0x00, 0x03, 0x8b, 0x14, 0x00, 0x02, 0xe0, 0x04, -0x00, 0x02, 0xef, 0x00, 0x00, 0x01, 0x5d, 0x0a, -0x00, 0x03, 0x4d, 0x52, 0x00, 0x00, 0x27, 0x6d, -0x00, 0x03, 0x4d, 0x57, 0x00, 0x00, 0x27, 0x6d, -0x00, 0x01, 0xc0, 0x01, 0x00, 0x03, 0x8b, 0x1a, -0x00, 0x02, 0xe0, 0x06, 0x00, 0x02, 0xee, 0x00, -0x00, 0x03, 0x4d, 0x57, 0x00, 0x00, 0x27, 0x6d, -0x00, 0x01, 0xc0, 0x01, 0x00, 0x03, 0x8b, 0x23, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x2e, 0x56, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x2e, 0x57, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x71, 0x17, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x72, 0x17, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x77, 0x17, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x41, 0x17, -0x00, 0x03, 0xa1, 0x36, 0x00, 0x01, 0x5f, 0x82, -0x00, 0x02, 0xf1, 0x75, 0x00, 0x03, 0x59, 0x17, -0x00, 0x03, 0x5b, 0x1f, 0x00, 0x03, 0x8f, 0xc5, -0x00, 0x00, 0xc4, 0x89, 0x00, 0x01, 0x40, 0x07, -0x00, 0x03, 0x4d, 0x10, 0x00, 0x00, 0xa4, 0x0d, -0x00, 0x03, 0x73, 0x10, 0x00, 0x02, 0xee, 0x00, -0x00, 0x03, 0x50, 0x34, 0x00, 0x03, 0x20, 0x03, -0x00, 0x02, 0xe4, 0x00, 0x00, 0x03, 0x53, 0x00, -0x00, 0x03, 0xb3, 0x48, 0x00, 0x01, 0x4d, 0x84, -0x00, 0x02, 0x8c, 0x01, 0x00, 0x03, 0x89, 0x50, -0x00, 0x00, 0x4c, 0x0e, 0x00, 0x01, 0x40, 0x01, -0x00, 0x02, 0x40, 0x05, 0x00, 0x03, 0x81, 0x50, -0x00, 0x02, 0xe4, 0x01, 0x00, 0x02, 0x40, 0x03, -0x00, 0x03, 0x81, 0x50, 0x00, 0x02, 0xe4, 0x02, -0x00, 0x03, 0x75, 0x12, 0x00, 0x02, 0xe0, 0x00, -0x00, 0x03, 0x76, 0x10, 0x00, 0x02, 0x48, 0x02, -0x00, 0x03, 0x85, 0x70, 0x00, 0x03, 0x59, 0x37, -0x00, 0x03, 0x50, 0x33, 0x00, 0x01, 0x40, 0x02, -0x00, 0x03, 0x58, 0x10, 0x00, 0x03, 0x5b, 0x1f, -0x00, 0x03, 0x8f, 0xc5, 0x00, 0x00, 0xc4, 0x81, -0x00, 0x01, 0x40, 0x0f, 0x00, 0x03, 0x4d, 0x10, -0x00, 0x00, 0xa4, 0x0d, 0x00, 0x00, 0x23, 0xaf, -0x00, 0x03, 0x59, 0x31, 0x00, 0x03, 0xb3, 0x63, -0x00, 0x03, 0x59, 0x32, 0x00, 0x03, 0x4c, 0x1f, -0x00, 0x03, 0x8f, 0x7c, 0x00, 0x03, 0x72, 0x10, -0x00, 0x03, 0x4b, 0x0e, 0x00, 0x02, 0x60, 0x0e, -0x00, 0x03, 0x85, 0x6a, 0x00, 0x03, 0x4b, 0x10, -0x00, 0x03, 0x50, 0x0e, 0x00, 0x01, 0xa0, 0x0b, -0x00, 0x03, 0x76, 0x10, 0x00, 0x03, 0x51, 0x32, -0x00, 0x01, 0xa4, 0x8b, 0x00, 0x03, 0x72, 0x11, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x50, 0x10, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x4a, 0x17, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x4b, 0x17, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x4b, 0x17, -0x00, 0x02, 0xee, 0x00, 0x00, 0x03, 0x45, 0x17, -0x00, 0x02, 0xee, 0x00, 0x00, 0x03, 0x8f, 0x7a, -0x00, 0x03, 0x50, 0x33, 0x00, 0x01, 0x40, 0x02, -0x00, 0x03, 0x58, 0x10, 0x00, 0x03, 0x5b, 0x1f, -0x00, 0x03, 0x8f, 0xc5, 0x00, 0x00, 0xc4, 0x81, -0x00, 0x01, 0x40, 0x0f, 0x00, 0x03, 0x4d, 0x10, -0x00, 0x03, 0x5f, 0x0c, 0x00, 0x00, 0xa4, 0x0d, -0x00, 0x03, 0x58, 0x35, 0x00, 0x03, 0x59, 0x36, -0x00, 0x03, 0x5b, 0x1f, 0x00, 0x03, 0x8f, 0xc5, -0x00, 0x00, 0xc4, 0x89, 0x00, 0x01, 0x40, 0x07, -0x00, 0x03, 0x4d, 0x10, 0x00, 0x00, 0xa4, 0x0d, -0x00, 0x03, 0xa1, 0x90, 0x00, 0x01, 0x40, 0x02, -0x00, 0x03, 0xb1, 0x92, 0x00, 0x00, 0xc0, 0x02, -0x00, 0x03, 0x5f, 0x0c, 0x00, 0x03, 0x4f, 0x10, -0x00, 0x03, 0xa7, 0x96, 0x00, 0x02, 0xec, 0x0f, -0x00, 0x03, 0x4c, 0x33, 0x00, 0x00, 0x3b, 0x0c, -0x00, 0x03, 0x87, 0x9a, 0x00, 0x02, 0xec, 0x00, -0x00, 0x03, 0x4d, 0x16, 0x00, 0x00, 0xd8, 0x01, -0x00, 0x00, 0x22, 0x03, 0x00, 0x03, 0x52, 0x03, -0x00, 0x01, 0x49, 0x01, 0x00, 0x00, 0x2a, 0x8d, -0x00, 0x03, 0x50, 0x15, 0x00, 0x03, 0xa9, 0xbf, -0x00, 0x03, 0xa7, 0xb5, 0x00, 0x03, 0xab, 0xb0, -0x00, 0x03, 0xad, 0xab, 0x00, 0x03, 0xa3, 0xa8, -0x00, 0x03, 0xa5, 0xc2, 0x00, 0x03, 0x8f, 0xc3, -0x00, 0x03, 0x50, 0x14, 0x00, 0x03, 0xa5, 0xc3, -0x00, 0x03, 0x8f, 0xc2, 0x00, 0x03, 0xa3, 0xae, -0x00, 0x03, 0xaf, 0xc3, 0x00, 0x03, 0x8f, 0xc2, -0x00, 0x03, 0x50, 0x14, 0x00, 0x03, 0x8f, 0xc2, -0x00, 0x03, 0x50, 0x16, 0x00, 0x03, 0xa3, 0xb3, -0x00, 0x03, 0x8f, 0xc3, 0x00, 0x00, 0xc0, 0x01, -0x00, 0x03, 0x8f, 0xc2, 0x00, 0x03, 0xab, 0xbc, -0x00, 0x03, 0xa3, 0xb9, 0x00, 0x03, 0xaf, 0xc3, -0x00, 0x03, 0x8f, 0xc2, 0x00, 0x03, 0x50, 0x14, -0x00, 0x03, 0xaf, 0xc3, 0x00, 0x03, 0x8f, 0xc2, -0x00, 0x03, 0x50, 0x16, 0x00, 0x01, 0xc0, 0x01, -0x00, 0x03, 0x8f, 0xc3, 0x00, 0x03, 0xa7, 0xc1, -0x00, 0x03, 0x8f, 0xa4, 0x00, 0x03, 0xaf, 0xc3, -0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x5f, 0x1b, -0x00, 0x03, 0x20, 0x70, 0x00, 0x02, 0xe4, 0x01, -0x00, 0x02, 0xe0, 0x01, 0x00, 0x00, 0xc0, 0x0f, -0x00, 0x03, 0x5a, 0x10, 0x00, 0x02, 0xe0, 0x00, -0x00, 0x02, 0xe2, 0x00, 0x00, 0x02, 0xa8, 0x19, -0x00, 0x03, 0x89, 0xce, 0x00, 0x00, 0x24, 0x98, -0x00, 0x01, 0x40, 0x01, 0x00, 0x02, 0x84, 0x01, -0x00, 0x03, 0x89, 0xd2, 0x00, 0x00, 0xa0, 0x1a, -0x00, 0x01, 0x44, 0x81, 0x00, 0x00, 0xc9, 0x01, -0x00, 0x03, 0x8b, 0xcb, 0x00, 0x03, 0x5f, 0x1b, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x0a, 0x0d, -}; -static uchar -zrmpeg3s[] = { -0x00, 0x03, 0x8e, 0x00, 0x00, 0x03, 0xc0, 0x0a, -0x00, 0x03, 0x50, 0x0b, 0x00, 0x01, 0x40, 0x08, -0x00, 0x02, 0x80, 0x02, 0x00, 0x03, 0x8a, 0x07, -0x00, 0x02, 0xca, 0x00, 0x00, 0x02, 0x80, 0x01, -0x00, 0x03, 0x8a, 0x0a, 0x00, 0x02, 0xd6, 0xe0, -0x00, 0x02, 0xce, 0x00, 0x00, 0x03, 0x4c, 0x80, -0x00, 0x02, 0xde, 0x04, 0x00, 0x02, 0xc2, 0x00, -0x00, 0x02, 0xd2, 0x00, 0x00, 0x02, 0xf8, 0x00, -0x00, 0x03, 0x5d, 0x10, 0x00, 0x03, 0x5b, 0x1f, -0x00, 0x03, 0x8f, 0x8c, 0x00, 0x03, 0x88, 0x1d, -0x00, 0x02, 0x5c, 0xfa, 0x00, 0x03, 0x8a, 0x11, -0x00, 0x02, 0xe8, 0x46, 0x00, 0x02, 0xf8, 0x00, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x5d, 0x17, -0x00, 0x01, 0xd2, 0x01, 0x00, 0x03, 0x8a, 0x18, -0x00, 0x03, 0x8e, 0x11, 0x00, 0x02, 0xee, 0x00, -0x00, 0x03, 0x5b, 0x1f, 0x00, 0x03, 0x8f, 0xd2, -0x00, 0x03, 0xa0, 0x22, 0x00, 0x03, 0x46, 0x17, -0x00, 0x03, 0x5b, 0x1f, 0x00, 0x03, 0x8f, 0x8c, -0x00, 0x02, 0x5c, 0xbb, 0x00, 0x03, 0x8a, 0x29, -0x00, 0x03, 0x5b, 0x1f, 0x00, 0x03, 0x8f, 0x8c, -0x00, 0x03, 0x88, 0x1d, 0x00, 0x02, 0x5c, 0xb9, -0x00, 0x03, 0x89, 0x00, 0x00, 0x02, 0x5c, 0xbc, -0x00, 0x03, 0x84, 0x26, 0x00, 0x03, 0x50, 0x17, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x54, 0x17, -0x00, 0x02, 0xee, 0x00, 0x00, 0x01, 0xd2, 0x01, -0x00, 0x02, 0x5c, 0xff, 0x00, 0x03, 0x88, 0x30, -0x00, 0x01, 0x5d, 0x06, 0x00, 0x02, 0x48, 0x01, -0x00, 0x03, 0x8a, 0x3a, 0x00, 0x02, 0xee, 0x00, -0x00, 0x01, 0xd2, 0x02, 0x00, 0x02, 0xee, 0x00, -0x00, 0x01, 0x5d, 0x04, 0x00, 0x03, 0x88, 0x46, -0x00, 0x03, 0x5b, 0x1f, 0x00, 0x03, 0x8f, 0xd2, -0x00, 0x03, 0x44, 0x17, 0x00, 0x01, 0xd2, 0x04, -0x00, 0x02, 0x48, 0x03, 0x00, 0x03, 0x8a, 0x46, -0x00, 0x02, 0xee, 0x00, 0x00, 0x03, 0x5b, 0x1f, -0x00, 0x03, 0x8f, 0xd2, 0x00, 0x01, 0xd2, 0x05, -0x00, 0x02, 0x50, 0x05, 0x00, 0x03, 0x86, 0x26, -0x00, 0x02, 0xe2, 0xff, 0x00, 0x00, 0x67, 0x6b, -0x00, 0x02, 0x60, 0x0d, 0x00, 0x03, 0x85, 0xfa, -0x00, 0x03, 0xb2, 0xab, 0x00, 0x02, 0x88, 0x02, -0x00, 0x03, 0x89, 0x16, 0x00, 0x03, 0x42, 0x17, -0x00, 0x03, 0x8e, 0xa0, 0x00, 0x02, 0x88, 0x02, -0x00, 0x03, 0x89, 0x16, 0x00, 0x03, 0x55, 0x00, -0x00, 0x02, 0x94, 0x01, 0x00, 0x03, 0x88, 0x5a, -0x00, 0x01, 0x57, 0x01, 0x00, 0x00, 0x5b, 0x07, -0x00, 0x03, 0xb5, 0x16, 0x00, 0x03, 0x8e, 0x5f, -0x00, 0x02, 0x94, 0x10, 0x00, 0x03, 0x89, 0x16, -0x00, 0x01, 0x57, 0x05, 0x00, 0x00, 0x5b, 0x07, -0x00, 0x03, 0xb7, 0x16, 0x00, 0x01, 0x41, 0x05, -0x00, 0x02, 0x48, 0x06, 0x00, 0x03, 0x8b, 0x16, -0x00, 0x02, 0x58, 0x00, 0x00, 0x03, 0x8b, 0x16, -0x00, 0x03, 0x55, 0x00, 0x00, 0x02, 0x94, 0x01, -0x00, 0x03, 0x8a, 0x69, 0x00, 0x03, 0x4b, 0x81, -0x00, 0x03, 0x8e, 0x6a, 0x00, 0x03, 0x4a, 0x81, -0x00, 0x03, 0x45, 0x10, 0x00, 0x03, 0xa0, 0x6e, -0x00, 0x03, 0x40, 0x81, 0x00, 0x03, 0x22, 0x16, -0x00, 0x03, 0x50, 0x35, 0x00, 0x02, 0x40, 0x01, -0x00, 0x03, 0x80, 0x75, 0x00, 0x03, 0x84, 0x7d, -0x00, 0x02, 0xe0, 0x00, 0x00, 0x02, 0xe2, 0x00, -0x00, 0x03, 0x8e, 0x79, 0x00, 0x03, 0x4d, 0x32, -0x00, 0x03, 0x50, 0x04, 0x00, 0x03, 0x4c, 0x1f, -0x00, 0x03, 0x8f, 0x83, 0x00, 0x03, 0x20, 0x10, -0x00, 0x03, 0x22, 0x11, 0x00, 0x03, 0x20, 0x12, -0x00, 0x03, 0x22, 0x13, 0x00, 0x03, 0xb4, 0x80, -0x00, 0x03, 0xb6, 0x80, 0x00, 0x03, 0x8e, 0x51, -0x00, 0x03, 0x55, 0x1c, 0x00, 0x02, 0xf8, 0x01, -0x00, 0x03, 0xb4, 0x84, 0x00, 0x02, 0xf8, 0x02, -0x00, 0x03, 0x51, 0x07, 0x00, 0x03, 0x5d, 0x11, -0x00, 0x01, 0xd2, 0x02, 0x00, 0x03, 0xa6, 0x90, -0x00, 0x03, 0x43, 0x81, 0x00, 0x02, 0xe2, 0xff, -0x00, 0x00, 0xc4, 0x88, 0x00, 0x00, 0x67, 0x65, -0x00, 0x02, 0xee, 0x00, 0x00, 0x00, 0xbc, 0x8d, -0x00, 0x03, 0x5d, 0x11, 0x00, 0x01, 0xd2, 0x01, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x5d, 0x17, -0x00, 0x01, 0xd2, 0x02, 0x00, 0x02, 0x50, 0x01, -0x00, 0x03, 0x80, 0x90, 0x00, 0x02, 0xef, 0x00, -0x00, 0x03, 0x47, 0x17, 0x00, 0x02, 0x90, 0x01, -0x00, 0x03, 0x88, 0x26, 0x00, 0x02, 0xee, 0x00, -0x00, 0x00, 0xdd, 0x08, 0x00, 0x02, 0xe0, 0xff, -0x00, 0x00, 0x61, 0x65, 0x00, 0x00, 0xa9, 0x65, -0x00, 0x03, 0x43, 0x80, 0x00, 0x03, 0x8e, 0x26, -0x00, 0x03, 0x48, 0x81, 0x00, 0x03, 0x49, 0x81, -0x00, 0x03, 0xa0, 0xa5, 0x00, 0x03, 0x40, 0x81, -0x00, 0x03, 0x22, 0x16, 0x00, 0x03, 0x4d, 0x36, -0x00, 0x03, 0x50, 0x02, 0x00, 0x03, 0x4c, 0x1f, -0x00, 0x03, 0x8f, 0x83, 0x00, 0x03, 0x20, 0x14, -0x00, 0x03, 0x22, 0x15, 0x00, 0x03, 0x50, 0x0e, -0x00, 0x02, 0xf8, 0x00, 0x00, 0x03, 0x51, 0x07, -0x00, 0x03, 0x5d, 0x11, 0x00, 0x03, 0x45, 0x80, -0x00, 0x03, 0xa5, 0x1d, 0x00, 0x01, 0xd2, 0x02, -0x00, 0x03, 0xa2, 0xbc, 0x00, 0x03, 0x41, 0x81, -0x00, 0x02, 0xe2, 0xff, 0x00, 0x00, 0xc4, 0x88, -0x00, 0x00, 0x67, 0x60, 0x00, 0x02, 0xee, 0x00, -0x00, 0x00, 0xbf, 0x8d, 0x00, 0x00, 0x12, 0x01, -0x00, 0x03, 0x8e, 0xbd, 0x00, 0x03, 0x50, 0x17, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0xa8, 0xc7, -0x00, 0x02, 0x5d, 0xe0, 0x00, 0x03, 0x89, 0x98, -0x00, 0x02, 0x5c, 0x00, 0x00, 0x03, 0x8a, 0xc7, -0x00, 0x02, 0xec, 0x01, 0x00, 0x01, 0xbb, 0xef, -0x00, 0x03, 0x8a, 0xcd, 0x00, 0x02, 0xde, 0x01, -0x00, 0x03, 0x8e, 0xcf, 0x00, 0x02, 0xde, 0x04, -0x00, 0x02, 0x5c, 0x01, 0x00, 0x03, 0x89, 0x1d, -0x00, 0x01, 0x5f, 0x08, 0x00, 0x02, 0x58, 0x01, -0x00, 0x03, 0x89, 0x70, 0x00, 0x03, 0xa8, 0xcf, -0x00, 0x03, 0x5d, 0x17, 0x00, 0x01, 0xd2, 0x02, -0x00, 0x02, 0x50, 0x01, 0x00, 0x03, 0x80, 0xbb, -0x00, 0x03, 0x51, 0x17, 0x00, 0x02, 0xef, 0x00, -0x00, 0x03, 0x45, 0x81, 0x00, 0x03, 0x42, 0x80, -0x00, 0x02, 0xce, 0x00, 0x00, 0x03, 0x4e, 0x17, -0x00, 0x03, 0xa8, 0xda, 0x00, 0x03, 0x47, 0x17, -0x00, 0x02, 0xd8, 0x26, 0x00, 0x02, 0x90, 0x01, -0x00, 0x03, 0x88, 0xde, 0x00, 0x02, 0xd8, 0xf9, -0x00, 0x03, 0x4f, 0x81, 0x00, 0x02, 0x5c, 0x01, -0x00, 0x03, 0x88, 0xea, 0x00, 0x01, 0x5e, 0x88, -0x00, 0x02, 0x54, 0x01, 0x00, 0x03, 0x88, 0xe5, -0x00, 0x03, 0x5f, 0x0c, 0x00, 0x02, 0xda, 0xff, -0x00, 0x00, 0x7f, 0x0d, 0x00, 0x02, 0x44, 0x00, -0x00, 0x03, 0x89, 0x2d, 0x00, 0x03, 0x5f, 0x0c, -0x00, 0x02, 0x84, 0xff, 0x00, 0x03, 0x8a, 0xf1, -0x00, 0x02, 0x90, 0x01, 0x00, 0x03, 0x8a, 0xf4, -0x00, 0x03, 0x42, 0x81, 0x00, 0x02, 0xce, 0x00, -0x00, 0x02, 0xdc, 0x00, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x5f, 0x0c, 0x00, 0x03, 0x50, 0x10, -0x00, 0x02, 0xee, 0x00, 0x00, 0x00, 0xdd, 0x08, -0x00, 0x03, 0x56, 0x17, 0x00, 0x02, 0xd8, 0xfb, -0x00, 0x03, 0x8f, 0x2d, 0x00, 0x02, 0xee, 0x00, -0x00, 0x00, 0xdd, 0x08, 0x00, 0x02, 0xe0, 0xff, -0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0xa8, 0x20, -0x00, 0x03, 0x41, 0x80, 0x00, 0x03, 0x8e, 0x26, -0x00, 0x03, 0xb9, 0x0a, 0x00, 0x03, 0x50, 0x1e, -0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x89, 0x06, -0x00, 0x02, 0x40, 0x90, 0x00, 0x03, 0x8b, 0x08, -0x00, 0x02, 0xe0, 0x10, 0x00, 0x03, 0x20, 0xc0, -0x00, 0x02, 0xe0, 0x80, 0x00, 0x03, 0x20, 0xc0, -0x00, 0x03, 0x50, 0x07, 0x00, 0x03, 0xa7, 0x0e, -0x00, 0x03, 0x50, 0x05, 0x00, 0x03, 0x8f, 0x0f, -0x00, 0x03, 0x50, 0x05, 0x00, 0x02, 0xf8, 0x00, -0x00, 0x03, 0x5d, 0x10, 0x00, 0x03, 0x4c, 0x1f, -0x00, 0x03, 0x8f, 0x7c, 0x00, 0x02, 0xe0, 0xf0, -0x00, 0x03, 0x20, 0xc0, 0x00, 0x03, 0x8e, 0x00, -0x00, 0x02, 0x50, 0x00, 0x00, 0x03, 0x88, 0x26, -0x00, 0x01, 0xd2, 0x02, 0x00, 0x02, 0xef, 0x00, -0x00, 0x01, 0xd2, 0x02, 0x00, 0x03, 0x85, 0x19, -0x00, 0x03, 0x8e, 0x26, 0x00, 0x03, 0x4f, 0x80, -0x00, 0x03, 0x56, 0x10, 0x00, 0x03, 0xbf, 0x21, -0x00, 0x00, 0xdb, 0x08, 0x00, 0x02, 0x58, 0x00, -0x00, 0x03, 0x8a, 0xcd, 0x00, 0x02, 0xd8, 0xcd, -0x00, 0x03, 0xbf, 0x2b, 0x00, 0x01, 0xd2, 0x02, -0x00, 0x02, 0x50, 0x01, 0x00, 0x03, 0x87, 0x72, -0x00, 0x02, 0xef, 0x00, 0x00, 0x01, 0x5f, 0x08, -0x00, 0x03, 0x8f, 0x2d, 0x00, 0x00, 0xdf, 0x08, -0x00, 0x01, 0x5b, 0x08, 0x00, 0x02, 0x58, 0xb7, -0x00, 0x03, 0x89, 0x6b, 0x00, 0x02, 0x58, 0xb8, -0x00, 0x03, 0x89, 0x5e, 0x00, 0x02, 0xea, 0x00, -0x00, 0x02, 0x74, 0x0a, 0x00, 0x03, 0x89, 0x63, -0x00, 0x02, 0x58, 0xb3, 0x00, 0x03, 0x89, 0x5f, -0x00, 0x02, 0x58, 0xb8, 0x00, 0x03, 0x89, 0x5f, -0x00, 0x02, 0x58, 0x00, 0x00, 0x03, 0x8b, 0x63, -0x00, 0x02, 0xec, 0x01, 0x00, 0x00, 0x3a, 0x69, -0x00, 0x03, 0xa9, 0x5f, 0x00, 0x02, 0x50, 0x01, -0x00, 0x03, 0x87, 0x63, 0x00, 0x03, 0x56, 0x0a, -0x00, 0x02, 0x78, 0x09, 0x00, 0x03, 0x83, 0x63, -0x00, 0x03, 0xbf, 0x49, 0x00, 0x00, 0xdf, 0x88, -0x00, 0x03, 0x4d, 0x17, 0x00, 0x02, 0xee, 0x00, -0x00, 0x00, 0xbf, 0x8d, 0x00, 0x01, 0xd2, 0x01, -0x00, 0x03, 0x8f, 0x4b, 0x00, 0x02, 0xef, 0x00, -0x00, 0x01, 0xd2, 0x02, 0x00, 0x00, 0x5f, 0x38, -0x00, 0x02, 0x58, 0x18, 0x00, 0x03, 0x8b, 0x59, -0x00, 0x03, 0x44, 0x81, 0x00, 0x03, 0x56, 0x0a, -0x00, 0x01, 0xba, 0x69, 0x00, 0x00, 0x38, 0x61, -0x00, 0x03, 0x56, 0x01, 0x00, 0x01, 0xbb, 0x0b, -0x00, 0x02, 0x78, 0x0a, 0x00, 0x03, 0x81, 0x58, -0x00, 0x02, 0xc2, 0x00, 0x00, 0x01, 0xba, 0x69, -0x00, 0x03, 0x8f, 0x68, 0x00, 0x02, 0xec, 0x00, -0x00, 0x03, 0x5d, 0x16, 0x00, 0x02, 0xed, 0x00, -0x00, 0x03, 0x5d, 0x16, 0x00, 0x03, 0x8f, 0x68, -0x00, 0x03, 0xaf, 0x75, 0x00, 0x03, 0x44, 0x80, -0x00, 0x02, 0xec, 0x00, 0x00, 0x03, 0x5d, 0x16, -0x00, 0x03, 0x47, 0x0e, 0x00, 0x03, 0xbf, 0x68, -0x00, 0x03, 0xa9, 0x68, 0x00, 0x03, 0xab, 0x68, -0x00, 0x02, 0xec, 0x01, 0x00, 0x03, 0x5d, 0x16, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x5f, 0x0c, -0x00, 0x03, 0x50, 0x10, 0x00, 0x02, 0xec, 0xcd, -0x00, 0x02, 0x78, 0x0c, 0x00, 0x03, 0x8b, 0x76, -0x00, 0x02, 0xd8, 0xcf, 0x00, 0x03, 0x8f, 0x76, -0x00, 0x03, 0x4f, 0x81, 0x00, 0x03, 0x8f, 0x1e, -0x00, 0x02, 0xe2, 0x01, 0x00, 0x02, 0xd8, 0xd4, -0x00, 0x03, 0x8f, 0x28, 0x00, 0x02, 0xd9, 0x00, -0x00, 0x03, 0x4c, 0x81, 0x00, 0x02, 0xce, 0x00, -0x00, 0x02, 0xe6, 0x00, 0x00, 0x03, 0x5d, 0x13, -0x00, 0x02, 0xe7, 0xb7, 0x00, 0x03, 0x5d, 0x13, -0x00, 0x02, 0xec, 0x0a, 0x00, 0x02, 0xe6, 0x00, -0x00, 0x03, 0x5d, 0x13, 0x00, 0x01, 0xdb, 0x01, -0x00, 0x03, 0x8b, 0x7e, 0x00, 0x03, 0x5f, 0x0c, -0x00, 0x03, 0x50, 0x10, 0x00, 0x01, 0xe0, 0x06, -0x00, 0x01, 0x40, 0x01, 0x00, 0x03, 0x58, 0x10, -0x00, 0x03, 0x59, 0x33, 0x00, 0x03, 0x5b, 0x1f, -0x00, 0x03, 0x8f, 0xda, 0x00, 0x00, 0x24, 0x0d, -0x00, 0x03, 0x5f, 0x0c, 0x00, 0x01, 0x40, 0x88, -0x00, 0x02, 0xe0, 0x00, 0x00, 0x02, 0xee, 0x00, -0x00, 0x02, 0x5c, 0x01, 0x00, 0x03, 0x89, 0x93, -0x00, 0x03, 0x81, 0x8c, 0x00, 0x00, 0x00, 0x01, -0x00, 0x03, 0x8f, 0x8d, 0x00, 0x02, 0x40, 0x02, -0x00, 0x03, 0x85, 0x8c, 0x00, 0x02, 0xee, 0x00, -0x00, 0x03, 0x5f, 0x1b, 0x00, 0x02, 0x5c, 0xba, -0x00, 0x02, 0x50, 0x0d, 0x00, 0x03, 0x84, 0xc0, -0x00, 0x02, 0xea, 0x02, 0x00, 0x02, 0xe2, 0x3c, -0x00, 0x02, 0x50, 0x0d, 0x00, 0x03, 0x83, 0xa0, -0x00, 0x02, 0xef, 0x00, 0x00, 0x03, 0x8e, 0xc0, -0x00, 0x00, 0x16, 0x81, 0x00, 0x02, 0xee, 0x00, -0x00, 0x02, 0xc4, 0xff, 0x00, 0x00, 0x64, 0xa2, -0x00, 0x02, 0x7c, 0x02, 0x00, 0x03, 0x8b, 0xb0, -0x00, 0x00, 0x45, 0x07, 0x00, 0x01, 0x44, 0x83, -0x00, 0x00, 0xc9, 0x08, 0x00, 0x03, 0x42, 0x12, -0x00, 0x00, 0xa4, 0x82, 0x00, 0x02, 0x54, 0x0b, -0x00, 0x03, 0x85, 0xa0, 0x00, 0x02, 0xea, 0x00, -0x00, 0x01, 0xd2, 0x0b, 0x00, 0x03, 0x8f, 0x9c, -0x00, 0x03, 0x43, 0x15, 0x00, 0x01, 0xf2, 0x03, -0x00, 0x02, 0xe2, 0x07, 0x00, 0x00, 0xc4, 0x88, -0x00, 0x00, 0x04, 0x81, 0x00, 0x00, 0xc5, 0x08, -0x00, 0x02, 0x54, 0x02, 0x00, 0x03, 0x81, 0xc3, -0x00, 0x03, 0x85, 0xbd, 0x00, 0x03, 0x42, 0x12, -0x00, 0x00, 0xbf, 0x82, 0x00, 0x00, 0x12, 0x02, -0x00, 0x03, 0x8e, 0xc0, 0x00, 0x00, 0xdd, 0x08, -0x00, 0x03, 0x43, 0x12, 0x00, 0x02, 0xee, 0x00, -0x00, 0x00, 0xbf, 0x83, 0x00, 0x00, 0x12, 0x01, -0x00, 0x03, 0x8e, 0xc0, 0x00, 0x03, 0x43, 0x12, -0x00, 0x03, 0x4f, 0x80, 0x00, 0x00, 0x45, 0x07, -0x00, 0x01, 0x44, 0x83, 0x00, 0x00, 0xc9, 0x08, -0x00, 0x03, 0x42, 0x12, 0x00, 0x00, 0xa4, 0x82, -0x00, 0x03, 0xbf, 0xb5, 0x00, 0x00, 0xc5, 0x08, -0x00, 0x01, 0x49, 0x08, 0x00, 0x00, 0xa9, 0x03, -0x00, 0x03, 0x5d, 0x12, 0x00, 0x01, 0xd6, 0x82, -0x00, 0x03, 0x4f, 0x81, 0x00, 0x03, 0x8f, 0xc5, -0x00, 0x02, 0xef, 0x00, 0x00, 0x00, 0x5f, 0x82, -0x00, 0x00, 0xdf, 0x8e, 0x00, 0x03, 0x5a, 0x17, -0x00, 0x02, 0xef, 0x00, 0x00, 0x01, 0x5f, 0x81, -0x00, 0x03, 0x5f, 0x1b, 0x00, 0x00, 0xbf, 0x9a, -0x00, 0x02, 0xe4, 0x01, 0x00, 0x02, 0xe0, 0x01, -0x00, 0x00, 0xc0, 0x0f, 0x00, 0x03, 0x5a, 0x10, -0x00, 0x02, 0xe0, 0x00, 0x00, 0x02, 0xe2, 0x00, -0x00, 0x02, 0xa8, 0x19, 0x00, 0x03, 0x89, 0xe3, -0x00, 0x00, 0x24, 0x98, 0x00, 0x01, 0x40, 0x01, -0x00, 0x02, 0x84, 0x01, 0x00, 0x03, 0x89, 0xe7, -0x00, 0x00, 0xa0, 0x1a, 0x00, 0x01, 0x44, 0x81, -0x00, 0x00, 0xc9, 0x01, 0x00, 0x03, 0x8b, 0xe0, -0x00, 0x03, 0x5f, 0x1b, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x50, 0x10, 0x00, 0x03, 0x50, 0x10, -0x00, 0x03, 0x3c, 0xc0, 0x00, 0x03, 0x70, 0x10, -0x00, 0x03, 0x50, 0x1e, 0x00, 0x02, 0x40, 0xe0, -0x00, 0x03, 0x8b, 0xf6, 0x00, 0x03, 0x47, 0x81, -0x00, 0x01, 0x40, 0x04, 0x00, 0x03, 0x88, 0x01, -0x00, 0x03, 0x60, 0x80, 0x00, 0x03, 0x50, 0x30, -0x00, 0x02, 0xea, 0xff, 0x00, 0x00, 0x77, 0x65, -0x00, 0x03, 0x88, 0x51, 0x00, 0x02, 0x60, 0x0d, -0x00, 0x03, 0x88, 0x7d, 0x00, 0x03, 0x8f, 0x16, -0x0a, 0x0d, -}; -- cgit v1.2.3