#!/bin/rc # # command: /bin/boddle /sys/src/fs/pc . # srcdir: /sys/src/fs/pc # version: 872180916 # date: Thu Aug 21 12:28:36 EDT 1997 # myname=$0 doextract=no fn usage{ echo $myname: usage: $myname '[-X] [src-directory]' >[1=2] exit usage } fn sigint{ rm -rf 872180916 exit interrupt } while(~ $1 -*){ switch($1){ case -X doextract=yes case -* usage } shift } switch($#*){ case 0 srcdir=/sys/src/fs/pc case 1 srcdir=$1 case * usage } if(! ~ $doextract yes){ echo This shell file contains a bundle of diffs representing changes echo to original source files in the Plan 9 distribution. It will run echo against the files in echo ' ' $srcdir echo '(unless overridden by the optional source directory argument)' echo and create a directory 872180916 containing the updated files. echo It will NOT automatically update the original files. echo echo Invoke with argument -X to perform the actual extraction. exit 0 } rm -rf 872180916 mkdir 872180916 target=872180916/8253.c echo -n '872180916/8253.c: ' if(! test -f $srcdir/8253.c || ! test -r $srcdir/8253.c){ echo $srcdir/8253.c unreadable exit unreadable } sum=`{sum < $srcdir/8253.c} if(! ~ db5037461800 $sum(1)^$sum(2)){ echo $srcdir/8253.c is not the original distribution file exit original } cp $srcdir/8253.c 872180916/8253.c ed 872180916/8253.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM 8253.c' 86,113c /* * add in possible .2% error and convert to MHz */ cpumhz = (cpufreq + cpufreq/500)/1000000; . 81,84c cpufreq = loops*((t->aalcycles*Freq)/x); loopconst = (cpufreq/1000)/t->aalcycles; /* AAM+LOOP's for 1 ms */ . 79c * figure out clock frequency and a loop multiplier for delay(). . 69,76c x >>= 1; . 67c * counter goes at twice the frequency, once per transition, * i.e., twice per square wave . 65a /* find biggest loop that doesn't wrap */ incr = 16000000/(t->aalcycles*HZ*2); x = 2000; for(loops = incr; loops < 64*1024; loops += incr) { /* * measure time for the loop * * MOVL loops,CX * aaml1: AAM * LOOP aaml1 * * the time for the loop should be independent of external * cache and memory system since it fits in the execution * prefetch buffer. * */ outb(Tmode, Latch0); x = inb(T0cntr); x |= inb(T0cntr)<<8; aamloop(loops); outb(Tmode, Latch0); y = inb(T0cntr); y |= inb(T0cntr)<<8; x -= y; if(x < 0) x += Freq/HZ; if(x > Freq/(3*HZ)) break; } . 61a x86cpuid(&cpuidax, &cpuiddx); family = FAMILY(cpuidax); model = MODEL(cpuidax); for(t = x86type; t->name; t++) if((t->family == family && t->model == model) || (t->family == family && t->model == -1) || (t->family == -1)) break; cputype = t; /* * set clock for 1/HZ seconds */ . 60c * figure out what we are . 52c int x, y; /* change in counter */ int family, model, loops, incr; X86type *t; . 45,46c print("CPU is a %d MHz %s (cpuid: ax %lux dx %lux)\n", cpumhz, cputype->name, cpuidax, cpuiddx); . 42,43c void printcpufreq(void) . 37,39c /* * microsecond delay */ void microdelay(int l) { l *= loopconst; l /= 1000; if(l <= 0) l = 1; aamloop(l); . 35c l *= loopconst; if(l <= 0) l = 1; aamloop(l); } . 27a static void clockintr(Ureg *ur, void *v) { USED(v); clock(0, ur->pc); } #define STEPPING(x) ((x)&0xf) #define MODEL(x) (((x)>>4)&0xf) #define FAMILY(x) (((x)>>8)&0xf) enum { /* flags */ CpuidFPU = 0x001, /* on-chip floating point unit */ CpuidMCE = 0x080, /* machine check exception */ CpuidCX8 = 0x100, /* CMPXCHG8B instruction */ }; typedef struct { int family; int model; int aalcycles; char *name; } X86type; X86type x86type[] = { /* from the cpuid instruction */ { 4, 0, 22, "Intel486DX", }, { 4, 1, 22, "Intel486DX", }, { 4, 2, 22, "Intel486SX", }, { 4, 3, 22, "Intel486DX2", }, { 4, 4, 22, "Intel486DX2", }, { 4, 5, 22, "Intel486SL", }, { 4, 8, 22, "IntelDX4", }, { 5, 1, 23, "Pentium510", }, { 5, 2, 23, "Pentium735", }, /* family defaults */ { 3, -1, 32, "Intel386", }, { 4, -1, 22, "Intel486", }, { 5, -1, 23, "Pentium", }, /* total default */ { -1, -1, 23, "unknown", }, }; static X86type *cputype; . 26c static int cpufreq = 66000000; static int cpumhz = 66; static int loopconst = 100; static int cpuidax, cpuiddx; . 21a Trigger= 0x30, /* interrupt on terminal count */ . wq //GO.SYSIN DD VADIM 8253.c sum=`{sum < 872180916/8253.c} if(~ 61820e873701 $sum(1)^$sum(2)) echo if not{ echo 872180916/8253.c checksum error creating updated file exit checksum } target=872180916/9pcfs.c echo -n '872180916/9pcfs.c: ' if(! test -f $srcdir/9pcfs.c || ! test -r $srcdir/9pcfs.c){ echo $srcdir/9pcfs.c unreadable exit unreadable } sum=`{sum < $srcdir/9pcfs.c} if(! ~ 684354542476 $sum(1)^$sum(2)){ echo $srcdir/9pcfs.c is not the original distribution file exit original } cp $srcdir/9pcfs.c 872180916/9pcfs.c ed 872180916/9pcfs.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM 9pcfs.c' 38a printcpufreq(); . wq //GO.SYSIN DD VADIM 9pcfs.c sum=`{sum < 872180916/9pcfs.c} if(~ 9df269282493 $sum(1)^$sum(2)) echo if not{ echo 872180916/9pcfs.c checksum error creating updated file exit checksum } target=872180916/dat.h echo -n '872180916/dat.h: ' if(! test -f $srcdir/dat.h || ! test -r $srcdir/dat.h){ echo $srcdir/dat.h unreadable exit unreadable } sum=`{sum < $srcdir/dat.h} if(! ~ 504f94b7514 $sum(1)^$sum(2)){ echo $srcdir/dat.h is not the original distribution file exit original } cp $srcdir/dat.h 872180916/dat.h ed 872180916/dat.h >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM dat.h' 38a /* * PCI Local Bus support. * Quick hack until we figure out how to * deal with EISA, PCI, PCMCIA, PnP, etc. */ enum { /* configuration mechanism #1 */ PCIaddr = 0xCF8, /* CONFIG_ADDRESS */ PCIdata = 0xCFC, /* CONFIG_DATA */ /* configuration mechanism #2 */ PCIcse = 0xCF8, /* configuration space enable */ PCIforward = 0xCFA, /* which bus */ MaxPCI = 32, /* 16 for mechanism #2 */ }; typedef struct PCIcfg { ushort vid; /* vendor ID */ ushort did; /* device ID */ ushort command; ushort status; uchar rid; /* revision ID */ uchar loclass; /* specific register-level programming interface */ uchar subclass; uchar baseclass; uchar clsize; /* cache line size */ uchar latency; /* latency timer */ uchar header; /* header type */ uchar bist; /* built-in self-test */ ulong baseaddr[6]; /* memory or I/O base address registers */ ulong reserved28[2]; ulong romaddr; /* expansion ROM base address */ ulong reserved34[2]; uchar irq; /* interrupt line */ uchar irp; /* interrupt pin */ uchar mingnt; /* burst period length */ uchar maxlat; /* maximum latency between bursts */ } PCIcfg; enum { ScsiTestunit = 0x00, ScsiExtsens = 0x03, ScsiInquiry = 0x12, ScsiModesense = 0x1a, ScsiStartunit = 0x1B, ScsiStopunit = 0x1B, ScsiGetcap = 0x25, ScsiRead = 0x08, ScsiWrite = 0x0a, ScsiExtread = 0x28, ScsiExtwrite = 0x2a, }; . 2d wq //GO.SYSIN DD VADIM dat.h sum=`{sum < 872180916/dat.h} if(~ 2db7dd841914 $sum(1)^$sum(2)) echo if not{ echo 872180916/dat.h checksum error creating updated file exit checksum } target=872180916/fns.h echo -n '872180916/fns.h: ' if(! test -f $srcdir/fns.h || ! test -r $srcdir/fns.h){ echo $srcdir/fns.h unreadable exit unreadable } sum=`{sum < $srcdir/fns.h} if(! ~ c6a11d731559 $sum(1)^$sum(2)){ echo $srcdir/fns.h is not the original distribution file exit original } cp $srcdir/fns.h 872180916/fns.h ed 872180916/fns.h >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM fns.h' 61,62c int x86cpuid(int*, int*); . 44a void pcicfgr(int, int, int, int, void*, int); int pcimatch(int, int, PCIcfg*); void printcpureg(void); . 4a void aamloop(int); . wq //GO.SYSIN DD VADIM fns.h sum=`{sum < 872180916/fns.h} if(~ d60ff6c31691 $sum(1)^$sum(2)) echo if not{ echo 872180916/fns.h checksum error creating updated file exit checksum } target=872180916/l.s echo -n '872180916/l.s: ' if(! test -f $srcdir/l.s || ! test -r $srcdir/l.s){ echo $srcdir/l.s unreadable exit unreadable } sum=`{sum < $srcdir/l.s} if(! ~ 18f1beb39742 $sum(1)^$sum(2)){ echo $srcdir/l.s is not the original distribution file exit original } cp $srcdir/l.s 872180916/l.s ed 872180916/l.s >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM l.s' 671a RET TEXT famd+0(SB), $4 PUSHFL CLI /* spl hi */ FMOVL b+4(FP), F0 FADDF a+0(FP), F0 FMOVL c+8(FP), F0 FMULDP F0, F1 FMOVL d+12(FP), F0 FDIVDP F0, F1 FMOVFP F0, .safe-4(SP) MOVL .safe-4(SP), AX POPFL /* splx */ RET TEXT fdf+0(SB), $4 PUSHFL CLI /* spl hi */ FMOVL b+4(FP), F0 FDIVRF a+0(FP), F0 FMOVLP F0, .safe-4(SP) MOVL .safe-4(SP), AX POPFL /* splx */ . 586a MOVL c+0(FP),CX aaml1: AAM LOOP aaml1 RET . 585a /* * basic timing loop to determine CPU frequency */ TEXT aamloop(SB),$0 . 583a POPL BX . 582c MOVL a+0(FP),CX MOVL AX,0(CX) MOVL d+4(FP),CX MOVL DX,0(CX) . 580c MOVL $(3<<8),AX MOVL $0,DX . 577c MOVL $(4<<8),AX MOVL $0,DX . 574c MOVL $1,AX /* CPUID */ BYTE $0x0F BYTE $0xA2 . 572c ANDL $0x200000,AX /* if we can't change this, there's no CPUID */ . 559c TEXT x86cpuid(SB),$0 . wq //GO.SYSIN DD VADIM l.s sum=`{sum < 872180916/l.s} if(~ 8a18317710398 $sum(1)^$sum(2)) echo if not{ echo 872180916/l.s checksum error creating updated file exit checksum } target=872180916/mkfile echo -n '872180916/mkfile: ' if(! test -f $srcdir/mkfile || ! test -r $srcdir/mkfile){ echo $srcdir/mkfile unreadable exit unreadable } sum=`{sum < $srcdir/mkfile} if(! ~ edb03a601204 $sum(1)^$sum(2)){ echo $srcdir/mkfile is not the original distribution file exit original } cp $srcdir/mkfile 872180916/mkfile ed 872180916/mkfile >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM mkfile' 56a scsi3334.$O\ . 51a pci.$O\ . wq //GO.SYSIN DD VADIM mkfile sum=`{sum < 872180916/mkfile} if(~ 098ed78b1227 $sum(1)^$sum(2)) echo if not{ echo 872180916/mkfile checksum error creating updated file exit checksum } target=872180916/pc.c echo -n '872180916/pc.c: ' if(! test -f $srcdir/pc.c || ! test -r $srcdir/pc.c){ echo $srcdir/pc.c unreadable exit unreadable } sum=`{sum < $srcdir/pc.c} if(! ~ 1ff381bc6001 $sum(1)^$sum(2)){ echo $srcdir/pc.c is not the original distribution file exit original } cp $srcdir/pc.c 872180916/pc.c ed 872180916/pc.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM pc.c' 346a */ . 335a /* in assembly language . wq //GO.SYSIN DD VADIM pc.c sum=`{sum < 872180916/pc.c} if(~ dbeaed426028 $sum(1)^$sum(2)) echo if not{ echo 872180916/pc.c checksum error creating updated file exit checksum } target=872180916/scsi.c echo -n '872180916/scsi.c: ' if(! test -f $srcdir/scsi.c || ! test -r $srcdir/scsi.c){ echo $srcdir/scsi.c unreadable exit unreadable } sum=`{sum < $srcdir/scsi.c} if(! ~ 534387094233 $sum(1)^$sum(2)){ echo $srcdir/scsi.c is not the original distribution file exit original } cp $srcdir/scsi.c 872180916/scsi.c ed 872180916/scsi.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM scsi.c' 27a { "dpt3334", dpt3334reset, }, . 19a extern Io (*dpt3334reset)(int, ISAConf*); . wq //GO.SYSIN DD VADIM scsi.c sum=`{sum < 872180916/scsi.c} if(~ a4f09d1c4306 $sum(1)^$sum(2)) echo if not{ echo 872180916/scsi.c checksum error creating updated file exit checksum } target=872180916/pci.c echo -n '872180916/pci.c (new): ' cat > 872180916/pci.c >[2]/dev/null <<'//GO.SYSIN DD VADIM .' /* * Trivial PCI configuration code. * Only deals with bus 0, amongst other glaring omissions. */ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" static Lock pcicfglock; static int pcicfgmode = -1; static void pcicfginit(int) { /* * 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 theses addresses so if Mode2 accesses fail try * for Mode1 (which is preferred, Mode2 is deprecated). */ outb(PCIcse, 0); if(inb(PCIcse) == 0){ pcicfgmode = 2; return; } outl(PCIaddr, 0); if(inl(PCIaddr) == 0){ pcicfgmode = 1; return; } pcicfgmode = -1; } /* * Read a chunk of PCI configuration space. * Assumes arguments are within limits and regno and * nbytes are DWORD aligned. */ void pcicfgr(int busno, int devno, int funcno, int regno, void* data, int nbytes) { ulong addr, *p; int base, len; lock(&pcicfglock); if(pcicfgmode == -1) pcicfginit(busno); switch(pcicfgmode){ case 1: addr = 0x80000000|((busno & 0xFF)<<16)|((devno & 0x1F)<<11)|((funcno & 0x03)<<8); p = data; for(len = nbytes/sizeof(ulong); len > 0; len--){ outl(PCIaddr, addr|(regno & 0xFF)); *p = inl(PCIdata); p++; regno += sizeof(ulong); } outl(PCIaddr, 0); break; case 2: if(devno >= 16) break; outb(PCIcse, 0x80|((funcno & 0x07)<<1)); outb(PCIforward, busno); base = (0xC000|(devno<<8)) + regno; p = data; for(len = nbytes/sizeof(ulong); len > 0; len--){ *p = inl(base); p++; base += sizeof(*p); } outb(PCIcse, 0); break; } unlock(&pcicfglock); } void pcicfgw(int busno, int devno, int funcno, int regno, void* data, int nbytes) { ulong addr, *p; int base, len; lock(&pcicfglock); if(pcicfgmode == -1) pcicfginit(busno); switch(pcicfgmode){ case 1: addr = 0x80000000|((busno & 0xFF)<<16)|((devno & 0x1F)<<11)|((funcno & 0x03)<<8); p = data; for(len = nbytes/sizeof(*p); len > 0; len--){ outl(PCIaddr, addr|(regno & 0xFF)); outl(PCIdata, *p); p++; regno += sizeof(*p); } outl(PCIaddr, 0); break; case 2: if(devno >= 16) break; outb(PCIcse, 0x80|((funcno & 0x07)<<1)); outb(PCIforward, busno); base = (0xC000|(devno<<8)) + regno; p = data; for(len = nbytes/sizeof(*p); len > 0; len--){ outl(base, *p); p++; base += sizeof(*p); } outb(PCIcse, 0); } unlock(&pcicfglock); } /* * This is not in the spec, but at least the CMD640B requires it. */ void pcicfgw8(int busno, int devno, int funcno, int regno, void* data, int nbytes) { uchar *p; int base, len; lock(&pcicfglock); if(pcicfgmode == -1) pcicfginit(busno); switch(pcicfgmode){ default: panic("pcicfgw8: pcicfgmode %d\n", pcicfgmode); break; case 2: if(devno >= 16) break; outb(PCIcse, 0x80|((funcno & 0x07)<<1)); outb(PCIforward, busno); base = (0xC000|(devno<<8)) + regno; p = data; for(len = nbytes/sizeof(*p); len > 0; len--){ outb(base, *p); p++; base += sizeof(*p); } outb(PCIcse, 0); } unlock(&pcicfglock); } int pcimatch(int busno, int devno, PCIcfg* pcicfg) { ulong l; lock(&pcicfglock); if(pcicfgmode == -1) pcicfginit(busno); unlock(&pcicfglock); while(devno < MaxPCI){ if(pcicfgmode == 2 && devno >= 16) break; l = 0; pcicfgr(busno, devno, 0, 0, &l, sizeof(ulong)); devno++; if((l & 0xFFFF) != pcicfg->vid) continue; if(pcicfg->did && ((l>>16) & 0xFFFF) != pcicfg->did) continue; pcicfgr(busno, devno-1, 0, 0, pcicfg, sizeof(PCIcfg)); return devno; } return -1; } //GO.SYSIN DD VADIM . sum=`{sum < 872180916/pci.c} if(~ dc2936de3743 $sum(1)^$sum(2)) echo if not{ echo 872180916/pci.c checksum error extracting new file exit checksum } target=872180916/scsi3334.c echo -n '872180916/scsi3334.c (new): ' cat > 872180916/scsi3334.c >[2]/dev/null <<'//GO.SYSIN DD VADIM .' /* * DPT 3334 SCSI Host Adapter. * Version 0.9 - Sun Apr 6, 1997 - John L. Chmielewski, jlc@att.com * Needs work: * handle multiple controllers; */ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #define DEBUG #define ETA_SIG (((long) 'E') | (((long) 'A') << 8) |\ (((long) 'T') << 16) | (((long) 'A') << 24)) enum { CtrlID = 7, /* Default Controller ID */ SenLen = 0xFF, /* Maximum Sense Data Length */ PCIvid = 0x1044, /* PCI Vendor ID: DPT */ PCIdid = 0xA400, /* PCI Device ID: DPT */ }; enum { /* Eata Register Commands */ ReadCfg = 0xFD, /* Read Configuration Data, DMA */ SendCP = 0xFF, /* Execute Command, DMA */ Reset = 0xF9, /* Reset Controller */ }; enum { /* Eata Register Sets - PCI */ Cmd = 0x17, /* Command Register (write) */ CP3 = 0x15, /* CP Address (MSB) (write) */ CP2 = 0x14, /* CP Address (MSB -1) (write) */ CP1 = 0x13, /* CP Address (MSB-2) (write) */ CP0 = 0x12, /* CP Address (LSB) (write) */ ASR = 0X18, /* Aux Status Register (read) */ SR = 0x17, /* Status Register (read) */ DR = 0x10, /* 16 bit Data Register (read) */ }; enum { /* Eata Register Sets Bits */ /* Status Register */ ERROR = 0x01, /* Command ended in error */ DRQ = 0x08, /* Drive is Ready */ SC = 0x10, /* Seek Complete */ RDY = 0x40, /* Active data request */ BSY = 0x80, /* Controller busy - clear IRQ */ /* Aux Status Register */ ABSY = 0x01, /* Controller busy */ IRQ = 0x02, /* Drive interrupt asserted */ }; /* * DPT DMA Status Packet * Big Endian Format */ typedef struct DPTstat DPTstat; struct DPTstat { uchar info; /* Bits defined */ uchar sbs; /* SCSI Bus Status */ uchar reserved0[2]; ulong irl; /* Bytes Not Transfered */ ulong va; /* Virtual Address of CP */ uchar idmsg; uchar quemsg; uchar tagmsg; uchar msg[9]; }; enum { /* Status Packet bits */ /* info byte bits */ CS = 0x7F, /* Controller Status */ EOC = 0x80, /* End of Command - not safe */ }; /* * EATA Command Packet * */ typedef struct EATAcp EATAcp; struct EATAcp { uchar control; /* Bits defined */ uchar ReqSenLen; /* AutoRequestSense Data length */ uchar reserved1[3]; uchar FWNest; /* Firmware Nested Byte for RAID */ uchar PhsUnit; /* Physical Byte for RAID */ uchar device; /* Bits defined */ uchar msg[4]; /* Identify and Disconnect Message */ uchar CDB[12]; /* Total SCSI CDB */ ulong DTL; /* Byte Swapped Data Length In Bytes */ ulong va; /* Command Packet Virtual Address */ ulong dataDMA; /* Byte Swapped Data Physical Address */ ulong statDMA; /* Byte Swapped Status Packet Physical */ ulong reqDMA; /* Byte Swapped AutoRequestSense Phys */ }; enum { /* Command Packet bits */ /* control byte bits */ Sreset = 0x01, /* Issue A SCSI Bus Reset */ Init = 0x02, /* ReInitialize The Controller */ ReqSen = 0x04, /* Do Auto Request Sense */ SG = 0x08, /* Data Pointer To S.G. List */ Quick = 0x10, /* Quick PIOin, DMA in/out */ Interpret = 0x20, /* CDB Interpreted By Controller */ DataOut = 0x40, /* Data Out Phase With Command */ DataIn = 0x80, /* Data In Phase With Command */ /* device byte bits */ id = 0x1F, /* SCSI Target ID */ Channel = 0xE0, /* HBA Channel Number */ /* Message byte 0 bits */ MsgLun = 0x07, /* Message Lun */ MsgLuntar = 0x20, /* Target Routine */ MsgDisPri = 0x40, /* Disconnect Reconnect */ MsgIdent = 0x80, /* Indentify */ }; /* * ReadConfig Data Structure - This Structure Contains The EATA Configuration * Big Endian Format */ typedef struct DPTcfg DPTcfg; struct DPTcfg { /* Extra bytes returned form a SCSI Inquiry Command */ uchar DevType; uchar PageCode; uchar reserved2; uchar ConfigLength; /* Length In Bytes After This Field */ ulong EATAsig; /* EATA Signature Bytes */ uchar EATAver; /* EATA Version Number */ uchar byte9; /* Bits defined */ ushort PadLen; /* Pad Bytes For PIO Commands */ uchar reserved3; uchar Chan2; /* Channel 2 SCSI ID */ uchar Chan1; /* Channel 1 SCSI ID */ uchar Chan0; /* Channel 0 SCSI ID */ ulong CPlength; /* Command Packet Length */ ulong SPlength; /* Status Packet Length */ ushort QueueSize; /* Controller Queue Depth */ uchar reserved4[2]; ushort SG_Size; /* Maximum Scatter Gather List Size */ uchar byte30; /* Bits defined */ uchar IRQ; /* IRQ address */ uchar byte32; /* Bits defined */ uchar byte33; /* Bits defined */ uchar MaxLUN; /* Maximum SCSI LUN Supported */ uchar byte35; /* Bits defined */ uchar RaidNum; /* Raid Host Adapter Number */ }; enum { /* Read Config Bits */ /* Byte 9 */ OverLapCmds = 0x01, /* Overlapped Cmds Supported */ TargetMode = 0x02, /* SCSI Target Mode Supported */ TrunNotNec = 0x04, /* Truncate Command Not Supported */ MoreSupported = 0x08, /* More Command Supported */ MAsupported = 0x10, /* DMA Mode Supported */ DMAvalid = 0x20, /* DMA Channel Field Is Valid. */ ATAdevice = 0x40, /* This Is An ATA Device */ HBAvalid = 0x80, /* HBA field Is Valid */ /* Byte 30 */ IRQn = 0x0F, /* IRQ Number */ IRQt = 0x10, /* IRQ Trigger: 0 = Edge, 1 = Level */ Secondary = 0x20, /* Controller Not At Address 0x170 */ DMAchan = 0xD0, /* DMA Channel Index For ISA */ /* Byte 32 */ Disable = 0x01, /* ISA I/O Address Disabled */ ForceAddr = 0x02, /* PCI Forced To An EISA/ISA Addr */ SG64K = 0x04, /* 64K of SG space */ SGUAE = 0x08, /* Supports unaligned SG Table */ /* Byte 33 */ MaxID = 0x1F, /* Maximun SCSI Target ID Supported */ MaxChan = 0xE0, /* Maximun Channel Number Supported */ /* Byte 35 */ AutoTerm = 0x08, /* Support auto term (low byte) */ PCIM1 = 0x10, /* PCI M1 chipset */ RIDQ = 0x20, /* Raid ID may be questionable */ PCIbus = 0x40, /* PCI Adapter Flag */ EISAbus = 0x80, /* EISA Adapter Flag */ }; typedef struct Target Target; struct Target { QLock; Rendez; int done; int senval; /* Sense data valid */ uchar sense[SenLen]; /* Sense data */ EATAcp; /* Command Packet */ uchar ctlrStatus; uchar scsiStatus; }; typedef struct Ctlr Ctlr; struct Ctlr { Lock; int port; /* base port */ int channel; /* Controller Channel Number */ int ctlrno; DPTcfg; /* Controller Configuration */ DPTstat; /* Status Packet */ PCIcfg; /* PCI info */ Lock targetlock; Target target[NTarget]; /* CCP's in use */ }; static Ctlr *ctlr[MaxScsi]; static long LongEndCvt(long x) { long t; char *p = (char *) &t; *p++ = (x>>24) & 0xFF; *p++ = (x>>16) & 0xFF; *p++ = (x>>8) & 0xFF; *p = x & 0xFF; return t; } static short ShortEndCvt(short x) { short t; char *p = (char *) &t; *p++ = (x>>8) & 0xFF; *p = x & 0xFF; return t; } #ifdef DEBUG static void printinfo(Ctlr *cp) { print("\nVendor ID: 0x%x\tDevice ID: 0x%x\tBase Address: 0x%x\n", cp->vid, cp->did, cp->baseaddr[0] & ~0x01); print("Signiture: %x\tIRQ: %d\t\t\tDMA: %d\n", LongEndCvt(cp->EATAsig), cp->byte30 & IRQn, cp->byte30 & DMAchan); print("CtlrChan0ID: %d\t\tCtlrChan1ID: %d\t\tCtlrChan2ID: %d\n", cp->Chan0, cp->Chan1, cp->Chan2); print("MaxChanID: %d\t\tMaxChanNum: %d\t\tInterrupt Vector: %d\n\n", cp->byte33 & MaxID, cp->byte33 & MaxChan, Int0vec); } #endif static void dptcmd(int port, ulong ccpaddr) { ulong paddr; paddr = PADDR(ccpaddr); outb(port+CP0, paddr & 0xFF); outb(port+CP1, (paddr>>8) & 0xFF); outb(port+CP2, (paddr>>16) & 0xFF); outb(port+CP3, (paddr>>24) & 0xFF); outb(port+Cmd, SendCP); } static int done(void *arg) { return ((Target *)arg)->done; } static int dpt3334io(Device d, int rw, uchar *cmd, int clen, void *data, int dlen) { Ctlr *cp = 0; Target *tp = &cp->target[d.unit & 0xff]; EATAcp *ccp = &tp->EATAcp; ushort status; int x; if ((cp = ctlr[d.ctrl]) == 0 || cp->port == 0) return 0x0200; if (d.unit = cp->Chan0) return 0x0300; qlock(tp); /* * If this is a request-sense and there is valid sense data * from the loas command, return it immediately. */ if (cmd[0] == ScsiExtsens && tp->senval) { memmove(data, tp->sense, tp->ReqSenLen); tp->senval = 0; qunlock(tp); return 0x6000; } tp->senval = 0; /* * Fill in the ccp */ memset(ccp, 0, sizeof(EATAcp)); ccp->control |= (rw == SCSIread ? DataIn : DataOut) | ReqSen; ccp->device = (cp->channel<<5) | (d.unit & id); ccp->ReqSenLen = SenLen; ccp->dataDMA = LongEndCvt(PADDR(data)); ccp->DTL = LongEndCvt(dlen); ccp->statDMA = LongEndCvt(PADDR(&cp->DPTstat)); ccp->reqDMA = LongEndCvt(PADDR(tp->sense)); ccp->ReqSenLen = SenLen; ccp->va = (ulong) tp; ccp->msg[0] |= (cmd[1]>>5 & MsgLun) | MsgDisPri | MsgIdent; memmove(ccp->CDB, cmd, clen); /* * Send the request */ x = splhi(); tp->done = 0; dptcmd(cp->port, (ulong) ccp); splx(x); /* * Wait for the request to complete. */ sleep(tp, done, tp); switch (tp->ctlrStatus) { case 0x00: /* no error */ status = 0x6000 | tp->scsiStatus; break; case 0x01: /* selection timed out */ status = 0x1100 | tp->scsiStatus; break; default: /* controller error */ status = (tp->ctlrStatus<<8) | tp->scsiStatus; break; } qunlock(tp); return status; } static void interrupt(Ureg *ur, void *arg) { Ctlr *cp; Target *tp; USED(ur); cp = arg; /* * Check the interrupt. */ if ((cp->info & EOC) == 0) return; /* * Get ccb address, status information, and set flags. */ tp = (Target *) cp->va; if (tp == 0) panic("DPT: no target for ccb #%lux\n", tp); tp->ctlrStatus = cp->info & CS; tp->scsiStatus = cp->sbs; cp->info &= ~EOC; tp->done = 1; if (tp->scsiStatus == 0x02) tp->senval = 1; /* indicate command returned sense data */ wakeup(tp); inb(cp->port+SR); /* clear the interrupt */ } /* * Locate the SCSI controller PCI cards. */ static Ctlr* locate(int ctlrno) { Ctlr *cp; static int devno; int i; for (i = ctlrno; i < MaxScsi; ++i) { cp = ctlr[i] = ialloc(sizeof(Ctlr), 0); memset(cp, 0, sizeof(Ctlr)); cp->vid = PCIvid; cp->did = PCIdid; if((devno = pcimatch(0, devno, cp)) == -1) break; /* no boards found */ cp->port = cp->baseaddr[0] & ~0x01; cp->ctlrno = i; } if (ctlr[ctlrno]->port) return ctlr[ctlrno]; return 0; } int (* dpt3334reset(int ctlrno, ISAConf *isa))(Device, int, uchar*, int, void*, int) { Ctlr *cp = 0; EATAcp *ccp; int x; /* * Assume one controller. */ if (isa->port == 0) if ((cp = locate(ctlrno)) == 0) return 0; isa->port = cp->port; /* * Do a Read Vital Data Page SCSI command * to get the configuration information * instead of using a Read Config Command. * This will cause an interrupt, but which * one isn't known yet. */ ccp = &cp->target[CtrlID].EATAcp; ccp->control |= (Interpret | DataIn | ReqSen); ccp->dataDMA = LongEndCvt(PADDR(&cp->DPTcfg)); ccp->DTL = LongEndCvt(sizeof(DPTcfg)); ccp->statDMA = LongEndCvt(PADDR(&cp->DPTstat)); ccp->va = (ulong) &cp->target[CtrlID]; ccp->msg[0] |= MsgIdent; ccp->CDB[0] = ScsiInquiry; /* SCSI Command */ ccp->CDB[1] |= 0x01; /* SCSI Extent */ ccp->CDB[2] = 0xC1; /* SCSI Page */ ccp->CDB[7] = sizeof(DPTcfg); /* Data Length */ x = splhi(); dptcmd(cp->port, (ulong) ccp); while ((inb(cp->port+ASR)&IRQ) == 0) ; inb(cp->port+SR); /* clear interrupt */ splx(x); setvec(Int0vec+(cp->byte30 & IRQn), interrupt, cp); outb(cp->port+Cmd, Reset); /* Reset Controller and SCSI Bus */ delay(5000); #ifdef DEBUG printinfo(cp); #endif return dpt3334io; } //GO.SYSIN DD VADIM . sum=`{sum < 872180916/scsi3334.c} if(~ f526d12c11468 $sum(1)^$sum(2)) echo if not{ echo 872180916/scsi3334.c checksum error extracting new file exit checksum }