/* drl18.c dr11 link echo for rev1 10118 w/9080 plx chip drl18 uses borlands power pack dos extender to test the 10118 with its "ship" eeprom installed - the board's registers may be located anywhere in 32 bit memory space */ #include #include #include "pcibios.h" #define PCI_INT 0x1a #define DEVICE_ID 0x0118 #define VENDOR_ID 0x11d5 #define DMABUFSIZEINWORDS 0x4000 /* apparently the inportb and outportb macros are not supported in 32 bit mode - by using "undef" we call for the functions - which seem to be available */ #undef inportb #undef outportb #undef inport #undef outport /* define in and out macros for ikon registers IN masks to 8 bits since all ikon regs are bytes these are changed from original code to use direct reference to maped physical address - it shouldn't be necessary to use assembler code for this now (we should also do this with PLX regs) IT MAY BE NECESSARY TO REPLACE OUT WITH A FUNCTION THAT DOES A READ AFTER WRITE TO FORCE A CACHE FLUSH (WHICH PROBABLY DOESN'T WORK) - OR DO SOME OTHER TRICK LIKE TURNING OFF CACHE FOR OUR ADDRESS RANGE IF READ AFTER WRITE IS USED - IT MUST NOT BE APPLIED TO THE FIFO RANGE, OR IT WILL CAUSE A READ OF THE INPUT FIFO!!!! */ #define OUT(offset,value) *(ikon_pointer+(offset>>2))=value #define IN(offset) ((unsigned char)(*(ikon_pointer+(offset>>2)) & 0xff)) #define SIN(offset) ((unsigned short)(*(ikon_pointer+(offset>>2)) & 0xffff)) #define LIN(offset) ((unsigned long)*(ikon_pointer+(offset>>2))) void exit(int); int bioskey(int); unsigned char ReadPciConfigLongWord(unsigned short, unsigned short int, unsigned long int *); unsigned char FindPciDevice(unsigned short int, unsigned short, unsigned short *); int FreeDOSMemory(unsigned short int); int DeleteMemoryAlias (unsigned long int); void *CreateMemoryAlias (unsigned long int mem, unsigned long int len, unsigned long int *handle_p); unsigned char WritePciConfigByte(unsigned short, unsigned short int, unsigned char value); int AllocAndMapDOSMemory (unsigned short int, unsigned long int *, unsigned long int*); int busanddev ; unsigned long int regvalue; unsigned long int dummy; unsigned long int realpointer; unsigned short int *bufpointer; int i; unsigned long buf_dos_selector; /* selector for low memory dma buffer */ unsigned long buf_dos_segment; /* segment for low mem dma bfr*/ unsigned long int longtemp ; /* generic 32 bit variable */ unsigned long int ikon_mem_base; /* ikon physical base add in memory */ unsigned long int *ikon_pointer; /* mapped ikon base address */ unsigned long int ikon_handle; /* mem block handle */ union REGS regs; void key(void) { if(bioskey(1)==0) return; bioskey(0); /* it is presumed that by the time we get to key(), both sets of registers are mapped and the DOS memory buffer is assigned! */ DeleteMemoryAlias (ikon_handle); FreeDOSMemory(buf_dos_selector); exit(0); } /* delay routine - to allow for p-i/o and dma delays. the P5 may execute test code so fast that it can beat the device handshake timing!! */ void xxdelay(void) /* there is already a delay function */ { key() ; key() ; key() ; key() ; key() ; } main() { /* find the 10118 and map the ikon and plx register sets save bus and device identifier */ if(FindPciDevice(DEVICE_ID, VENDOR_ID, &busanddev) != SUCCESSFUL) { printf("FindPciDevice error!\n"); exit(0); } /* get a pointer at ikon memory base address */ if(ReadPciConfigLongWord(busanddev, 0x18, &ikon_mem_base) != SUCCESSFUL) { printf("ReadConfigLongWord error reading offset 0x18!\n"); exit(0); } printf("ikon memory base = 0x%08lx\n",ikon_mem_base); /* make sure it is non zero */ if(ikon_mem_base == 0) { printf("***** ikon memory base zero!\n"); exit(0); } /* strip off control bits */ ikon_mem_base &= (unsigned long)0xfffffff0; /* get a mapped version of the ikon physical address map in 0x2000 bytes using Borland sample linear.c as modified */ ikon_pointer = CreateMemoryAlias(ikon_mem_base,0x2000,&ikon_handle); if(ikon_pointer == -1) { printf("CreateMemoryAlias error (ikon_mem_base)!\n"); exit(0); } printf("mapped ikon memory base = 0x%08lx\n",ikon_pointer); /* get dma buffer from DOS memory area - which is always locked and is accessible via DPMI calls BUFFER SIZE IS DEFINED IN WORDS, CALL WANTS BYTES */ if(AllocAndMapDOSMemory(DMABUFSIZEINWORDS << 1, &buf_dos_segment, &buf_dos_selector) == -1) { printf("error allocating dma buffer!\n"); DeleteMemoryAlias (ikon_handle); exit(0); } realpointer = buf_dos_segment << 4; /* initial master clear */ OUT(0x04,0x10); while(1) { key(); /* wait for attention from other end */ while(!(LIN(0x04) & 0x40)) key(); /* set up dma channel 1 */ OUT(0x114,0x1d05); /* dma mode */ OUT(0x118,realpointer);/* pci address */ OUT(0x11c,0x40); /* local add*/ OUT(0x120,0x2002); /* 0x1001 words */ OUT(0x124,0x08); /* input */ OUT(0x128,0x0300); /* go and enable*/ OUT(0x0c,0x00); /* mode (speed) */ OUT(0x00,0x10); /* in first */ OUT(0x00,0x30); /* then dma on */ OUT(0x10,0x00); /* 0x1001 xfers */ OUT(0x14,0x10); OUT(0x18,0x00); OUT(0x04,0xe0); /* clear flags */ OUT(0x08,0x05); /* go and acf2 */ while(!(LIN(0x128) & 0x1000)) key(); /* dma wait */ /* turn off dma on bit!!!!! */ OUT(0x00,0x00); /* send attention and wait for attention */ OUT(0x04,0xe0); /* clear flags */ OUT(0x08,0x04); /* pulse acf2 */ while(!(LIN(0x04) & 0x40)) key(); /* set up dma */ OUT(0x114,0x1d05); /* dma mode */ OUT(0x118,realpointer);/* pci address */ OUT(0x11c,0x40); /* local add*/ OUT(0x120,0x2002); /* 0x1001 words */ OUT(0x124,0x00); /* output */ OUT(0x128,0x0300); /* go and enable*/ OUT(0x0c,0x00); /* mode (speed) */ OUT(0x00,0x00); /* out first */ OUT(0x00,0x20); /* then dma on */ OUT(0x10,0x00); /* 0x1001 xfers */ OUT(0x14,0x10); OUT(0x18,0x00); OUT(0x04,0xe0); /* clear flags */ OUT(0x08,0x03); /* go and cycle */ while(!(LIN(0x04) & 0x80)) key(); /* eor wait */ /* turn dma enb bit off!!! */ OUT(0x00,0x00); } }