/* SHSMODe -- Serial High Speed Mode enabler/patcher V1.91releas for Linux */ /* Written by gigo http://homepage1.nifty.com/gigo/ (imaizumi@nisiq.net) */ /* Modified and Distributed by Device Drivers Limited(tom@devdrv.com) */ /* Special thanks for h-mio@mx5.nisiq.net */ /* V1.0f Modified for Linux by mizuhara@acm.org */ /* V1.6 Modified for Linux by ytakeuch@po.iijnet.or.jp */ /* compiler DOS:MSC6.00A with /AH option, Linux:gcc */ /* History: 1.91release(2/14/2003) Support Linux 2.4.x, delete 686a detection code for Windows Fix some detection bug. 1.9release(9/18/2000) Add ITE Chip detection. 1.9beta1(8/22/2000) Use shstable.c to use same table for win2k. Add List mode & Unsupported message. Add VIA Chip support. 1.8beta5(3/??/2000) Some bug fix for BIOS chek, *Not released. 1.8beta4(3/11/2000) Add Winbond Chips and Revision check, by Device Drivers Limited 1.8beta3(07-Sep-99) Fix x8_tbl bug 1.8beta2(28-Jun-99) 87338 PnP mode 1.8beta1(29-Apr-99) bug fix 1.7e(26-Apr-99) Verify BIOS work area COM port address. 1.7d(25-Apr-99) Support M1543C ? 1.7c(17-Feb-99) Support W83977EF ? 1.7b(04-Oct-98) Support ALI M1543? 1.7a(29-Aug-98) compile with #define PC87338, without NOACPI. 1.7(25-Aug-98) Support ALI M1543(Aladdin V south bridge) 1.6(17-Aug-98) Support NS PC87307,97307,87317,87308,87309(,87338) Fix/Add/Del SMC Table. WinBond W83877TF support ? Fix Winbond patch. Linux/FreeBSD support.(by youji takeuchi) 1.5(23-Jul-98) Support Winbond 87977F/AF/TF/ATF Support Windows98 Support 37N769,37M60x/61x/70x,37B77x/78x,37N958FR Added patch/depatch function 1.3-1.4 experimental,not released. 1.2b(25-Dec-96) Added support for 67x,68x 1.2a(01-Nov-96) Add 'B'(oth) port option. 1.2(31-Oct-96) Add support for 669FR,93xFR,93xAPM,957FR(Not tested yet.) Display port address for convenience. 1.0f add debug code & adaptation for linux. 1.0d, 1.0e experimental,not released. 1.0b -> 1.0c display string "com" -> "port", function exactly same. Known limitation for linux: Perhaps, this version fail to detect/set operation rare. You must check result. In hsmode,you can use ordinary setserial command to over 115kbps. For SMC 230kbps: setserial spd_cust divisor 0x8002 460kbps: setserial spd_cust divisor 0x8001 For NS/WinBond 230kbps: setserial spd_cust divisor 0x4 460kbps: setserial spd_cust divisor 0x2 921kbps: setserial spd_cust divisor 0x1 */ #define PATCH #define PC87338 /**/ #define BIOSCOM /**/ /* #define CHKENB */ #if defined(unix) /* disable patch function */ #undef PATCH /* disable BIOS COM port address compare */ #undef BIOSCOM #endif #include #include #include #if defined(unix) void port_init(void); void port_finish(void); #define _disable() port_init() #define _enable() port_finish() #if defined(linux) int inp(unsigned); void outp(unsigned, unsigned char); #elif defined(__FreeBSD__) #include #define inp(port) inb(port) #define outp(port, val) outb(port, val) #endif /* !defined(linux) && defined(__FreeBSD__) */ #else /* !defined(unix) */ #include #include #include #endif /* !defined(unix) */ #include /* functions */ extern int via686a(int port, int mode, unsigned int *io); void usage(void); void showlist(void); void bios_check(void); int chip(int n, char opr); /* chip detect */ int ope(int n, char opr, int portNo); /* option D,H,L operation */ void srdump(int n,int start,int end); /* register dump for debug */ #if defined(PATCH) int dopatch(int dist,char opr); /* patch/depatch */ long search(long fsize, int n, unsigned char *code); /* search pattern in serail.vxd */ int check_drv(char opr); /* check applied patch */ void chg_autoexec(char opr,char *path); /* process autoexec.bat */ #endif #if defined(BIOSCOM) unsigned short int _huge *bioscomp; #endif #include "shstable.h" /* TABLE DEFINES */ #include "shstable.c" /* TABLE CONTENTS */ #if defined(PATCH) unsigned char org_code[] = { 0x33,0xC0, 0x81,0xF9,0x00,0xC2,0x01,0x00,0x74,0x0D, 0x81,0xF9,0x10,0xFF,0x00,0x00,0x73,0x17, 0x83,0xF9,0x02,0x72,0x09,0x33,0xD2,0xB8, 0x00,0xC2,0x01,0x00,0xF7,0xF1,0x8B,0xC8, 0xB8,0xF4,0xFF,0xFF,0xFF,0x5A,0xC3,0x81, 0xF9,0x1F,0xFF,0x00,0x00,0x77,0xE6,0x53, 0x8B,0xD9,0x81,0xEB,0x10,0xFF,0x00,0x00, 0xD1,0xE3,0x0F,0xB7,0x83,0xA8,0x11,0x00, 0x00,0x5B,0xEB,0xDA }; unsigned char smc_code[] = { 0x33,0xC0, 0x8B,0xD1,0x81,0xEA,0x10,0xFF,0x00,0x00, 0x76,0x05,0x83,0xFA,0x0F,0x72,0x29,0x83, 0xF9,0x02,0x72,0x1B,0x33,0xD2,0xB8,0x00, 0x08,0x07,0x00,0xF7,0xF1,0x8B,0xD0,0x4A, 0x74,0x03,0x4A,0x75,0x07,0x0D,0x00,0x80, 0x00,0x00,0xEB,0x03,0xC1,0xE8,0x02,0x8B, 0xC8,0xB8,0xF4,0xFF,0xFF,0xFF,0x5A,0xC3, 0xD1,0xE2,0x0F,0xB7,0x82,0xA8,0x11,0x00, 0x00,0x90,0xEB,0xEB }; #define SMC_LEN0 63 #define TBL_ADR_LEN 4 #define SMC_LEN1 3 #define SMC_LEN 70 #define DVS1_OFS 2 #define DVS2_OFS 24 #define DVS 921600 static unsigned char wb_code[] = { 0x33,0xC0, 0x81,0xF9,0x00,0x10,0x0E,0x00,0x74,0x0D, 0x81,0xF9,0x10,0xFF,0x00,0x00,0x73,0x17, 0x83,0xF9,0x02,0x72,0x09,0x33,0xD2,0xB8, 0x00,0x10,0x0E,0x00,0xF7,0xF1,0x8B,0xC8, 0xB8,0xF4,0xFF,0xFF,0xFF,0x5A,0xC3,0x81, 0xF9,0x1F,0xFF,0x00,0x00,0x77,0xE6,0x53, 0x8B,0xD9,0x81,0xEB,0x10,0xFF,0x00,0x00, 0xD1,0xE3,0x0F,0xB7,0x83,0xA8,0x11,0x00, 0x00,0x5B,0xEB,0xDA }; static unsigned char ns_code[] = { 0x83,0xF8,0xFB, /* cmp eax,IE_Default ; bad coding.. sorry.*/ 0x74,0x0F, /* jz SetComChk ; check only -> */ /* ; (edx points LCR) */ 0x90, /* nop */ 0x90, /* nop */ 0xB0,0xE0, /* mov al,0e0h ; select bank2 */ 0xEE, /* out dx,al ; */ 0x42, /* inc edx ; set EXCR2 */ 0xEC, /* in al,dx ; */ 0x24,0xCF, /* and al,0CFh ; mask PRESL1,PRESL0 */ 0x0C,0x10, /* or al,010h ; divisor = 1.625 */ 0xEE, /* out dx,al ; */ 0x90, /* nop */ 0x90, /* nop */ 0x90, /* nop */ /*SetComChk: ; */ 0x33,0xC0, /* xor eax,eax ; assume error */ 0x8B,0xD1, /* mov edx,ecx ; */ 0x81,0xEA, /* sub edx,CBR_110 ; */ 0x10,0xFF,0x00,0x00, 0x76,0x05, /* jna SetCom921600 ; < CBR_110 ? -> Not Index */ 0x83,0xFA,0x0F, /* cmp edx,CBR_56000-CBR_110 */ 0x72,0x15, /* jnae by_index ; ? -> Index */ /*SetCom921600: ; */ 0x83,0xF9,0x02, /* cmp ecx,2 ; */ 0x72,0x09, /* jnae SetCom310 ; Error -> */ 0x33,0xD2, /* xor edx,edx ; EDX:EAX = 921,600 */ 0xB8,0x00,0x10,0x0E,0x00, /* mov eax,921600 */ 0xF7,0xF1, /* div ecx ; (EAX) = 921,600/baud */ /*SetCom310: ; */ 0x8B,0xC8, /* mov ecx,eax ;(ECX) = baud rate, or error code (0) */ 0x83,0xE8,0x0C, /* sub eax,0-IE_BAUDRATE ;set error code incase bad baud */ 0x5A, /* pop edx ; */ 0xC3, /* ret ; */ /*by_index: ; */ 0xD1,0xE2, /* shl edx,1 ; */ 0x0F,0xB7,0x82, /* movzx eax,WORD PTR [edx+BaudRateByIndexTable] ; get divisor */ 0xA8,0x11,0x00,0x00,/* 000000FC R ; !! don't move !! */ 0x90, /* nop */ 0xEB,0xED /*jmp SetCom310 ; return */ }; static unsigned char x1_tbl[] = { 0x17,0x04,0x80,0x01,0xC0,0x00,0x60,0x00, 0x30,0x00,0x18,0x00,0x0C,0x00,0x08,0x00, 0x06,0x00,0x00,0x00,0x00,0x00,0x03,0x00 }; static unsigned char x8_tbl[] = { 0xC7,0x20,0x04,0x0c,0x02,0x06,0x01,0x03, 0x80,0x01,0xC0,0x00,0x60,0x00,0x40,0x00, 0x30,0x00,0x00,0x00,0x00,0x00,0x18,0x00 }; typedef struct pch { unsigned char* code; int len; char *name; } pch_t; pch_t patch[] = { {org_code, SMC_LEN0, "Original"}, {smc_code, SMC_LEN0, "SMC/ALi/VIA Patch"}, /* 1 */ {wb_code , SMC_LEN0, "Winbond Patch"}, /* 2 */ {ns_code , SMC_LEN0, "NS Patch"}, /* 3 */ {NULL , 0 , "Unknown"}, /* 4 */ {NULL , 0 , "Old patch"} /* 5 */ }; FILE *fd; char fname[128]; char sysdir[128]="c:\\windows\\system"; char *windir; int drv_type; long adr1,adr2; char buf[256]; #else //!PATCH typedef struct pch { unsigned char* code; int len; char *name; } pch_t; pch_t patch[] = { {NULL, 0, "Original"}, {NULL, 0, "SMC/ALi/VIA Patch"}, /* 1 */ {NULL , 0, "Winbond Patch"}, /* 2 */ {NULL , 0, "NS Patch"}, /* 3 */ {NULL , 0, "Unknown"}, /* 4 */ {NULL , 0, "Old patch"} /* 5 */ }; #endif unsigned int portAdr[3]; int portStat[3]; unsigned short bios_port[5]; static unsigned short std_port[4] = {0x3F8, 0x2F8, 0x3E8, 0x2E8}; int divisor; #if defined(DEBUG) #define outp(p,v) outNT(p,v) #define inp(p) inpNT(p) void outNT(unsigned port, int val) { printf("out 0x%04x, 0x%02x\n",port,val); } int inpNT(unsigned port) { char buf[256]; unsigned c; printf("inp(0x%04x) = ?",port); scanf("%s",buf); sscanf(buf,"%x",&c); return c; /* printf("inp(0x%04x) \n",port); return 0xff; */ } #endif int ndev; void main(int argc, char *argv[]) { char opr; int n,portNo,force,detect; char *os; fputs("shsmod V1.91 release for Linux(2/14/2003) http://www.devdrv.com/\n",stdout); fputs("copyright(c) 1996-2003 O.Imaizumi, Device Drivers Limited.\n\n",stdout); #if !defined(unix) os = getenv("OS"); if (os != NULL && strcmp(os,"Windows_NT") == 0) { #if defined(DEBUG) fprintf(stderr,"Windows NT, Debug only!\n"); #else fprintf(stderr,"You must run this on DOS/Windows95/Windows98 !\n"); exit(1); #endif } else if ((windir = getenv("windir")) != NULL) { strcpy(sysdir,windir); strcat(sysdir,"\\system"); } #endif n = 1; portNo = 0; opr = 'D'; /* display only */ detect = -1; force = -1; if (argc > 1) { switch (argv[1][0]) { case 'l': case 'L': showlist(); exit(0); break; case '0': break; case '1': portNo = 0x40; break; case '2': portNo = 0x80; break; case '3': case 'b': case 'B': portNo = 0xC0; break; #if defined(PATCH) case 'p': case 'P': if (stricmp(argv[1],"patch") == 0) { opr = 'P'; break; } /* no break for syntax error */ case 'd': case 'D': if (stricmp(argv[1],"depatch") == 0) { opr = 'R'; break; } /* no break for syntax error */ #endif default: usage(); break; } } divisor = -1; if (argc > 2){ if (opr != 'D') { #if defined(PATCH) strcpy(sysdir,argv[2]); #endif } else { opr = (char)(toupper(argv[2][0])); switch (opr) { case 'D': portNo = 0; /* no break; */ case 'H': case 'L': case 'C': break; default: { long l; l = atol(argv[2]); if (l > 0) { if ((l<110)|| (l > 921600) || (921600%l)) usage(); divisor = (unsigned) (921600L/l); }else if (l==0) divisor = 0; opr = 'H'; } } } } #if defined(PATCH) strcpy(fname,sysdir); strcat(fname,"\\serial.vxd"); #endif if (argc > 3) { force = atoi(argv[3]); for (n=1; idnt[n].type && n!=force; n++); force = n; printf("***Force %s***\n",idnt[force].name); } for (; idnt[n].type != 0; n++) { if ((n == force) || (chip(n,opr) != -1)) { detect = n; break; } } if (detect == -1) { fputs(" Sorry! it cannot detect high speed SIO chipset.\n",stdout); fputs(" (Maybe unsupported SIO chipset?)\n",stdout); fputs(" Please check supported chipset with below command.\n",stdout); fputs("\n SHSMOD L[ist]\n\n",stdout); exit(1); } printf("%s%s at %04xh detected\n",fab[idnt[n].fab],idnt[n].name,idnt[n].port); /* if (opr == 'H' && idnt[n].pch == 0) { */ if (idnt[n].pch == 0) { printf("Sorry, This chip doesn\'t have a high-speed serial mode!\n"); exit(1); } else if ((opr == 'L') && (idnt[n].pch == 4)){ printf("!!! SHSMOD can't return to Low with this chip.!!!\n"); exit(1); } else if ((divisor >= 0) && (idnt[n].pch != 4 )){ printf("!!! SHSMOD can't set baud with this chip.!!!\n"); exit(1); } #if defined(PATCH) drv_type = check_drv(opr); switch(opr) { case 'P': /* patch */ case 'R': if (dopatch(idnt[n].pch,opr) > 0 ) { chg_autoexec(opr,argv[0]); fputs("\n*** Restart windows to take effect. ***\n",stderr); } break; case 'H': if (drv_type == 0) {/* Winbond & NS87308 */ if ((idnt[n].pch==2)||(idnt[n].type==20)) { fputs("Warning -- driver mismatch, may unexpected effect occur.\n",stdout); } } /* no break; */ #else switch(opr) { case 'H': #endif case 'L': case 'D': ope(n,opr,portNo); break; case 'C': /* debug */ #if defined(BIOSCOM) /* windir = getenv("windir"); */ /* if (windir == NULL) */ bios_check(); srdump(n,0,0x4F); #endif break; default: break; } exit(0); } void usage(void) { fputs("usage:shsmod [port# [H/L/D/C]]\n",stderr); fputs(" Note: port# is 1(COM1), 2(COM2), or 3(Both)\n",stderr); fputs(" H: high mode, L: low mode\n",stderr); fputs(" D: display status, C: check for debug\n",stderr); fputs(" shsmod port# baud (NS chip only. except PC87308)\n",stderr); fputs(" shsmod port# (H|L) [force-mode#] (force mode, dangerous!)\n", stderr); #if defined(PATCH) fputs(" shsmod patch|depatch [sysdir [force-mode#]]\n",stderr); #endif fputs(" shsmod L[ist] -- show supported chipset list\n",stderr); fputs(" shsmod help|/?|-? -- show this message\n",stderr); exit(1); } void showlist() { int n; printf(" <>\n"); for(n = 1; idnt[n].port; n++) { printf("% 4d: %s%s at %04xh, id = %02x, rev = %02x, type = %s.\n", n, fab[idnt[n].fab],idnt[n].name, idnt[n].port, idnt[n].id, idnt[n].rev, idnt[n].pch ? patch[idnt[n].pch].name : "No high speed mode" ); } } #if defined(unix) #if defined(linux) #define PORT_DEV "/dev/port" #elif defined(__FreeBSD__) #define PORT_DEV "/dev/io" #endif /* !defined(linux) && defined(__FreeBSD__) */ FILE *fp = NULL; void port_init(void) { if (fp == NULL ) { if ((fp = fopen(PORT_DEV, "r+")) == NULL) { perror("error in fopen " PORT_DEV); exit(2); } } } void port_finish(void) { if(fp) { fclose(fp); fp = NULL; } } #if defined(linux) void port_error(const char *msg) { perror(msg); fclose(fp); exit(2); } int inp(unsigned port) { unsigned char buf[1]; #if 0 fprintf(stderr, "inp: port = 0x%x\n", port); #endif /* DEBUG */ if (fseek(fp, port, SEEK_SET)) { port_error("error in fseek " PORT_DEV); } if (!fread(buf, 1, 1, fp)) { port_error("error in fread " PORT_DEV); } return buf[0]; } void outp(unsigned port, unsigned char val) { #if 0 fprintf(stderr, "outp: port = 0x%x, val = 0x%x\n", port, val); #endif /* DEBUG */ if (fseek(fp, port, SEEK_SET)) { port_error("error in fseek " PORT_DEV); } if (!fwrite(&val, 1, 1, fp)) { port_error("error in fwrite " PORT_DEV); } } #endif /* defined(linux) */ #endif /* defined(unix) */ #include "shschip.c" /* ope(), chip() functions */ void srdump(int n,int start,int end) { int i; unsigned char buf[256], *bp; if ((end-start) > 255) { fprintf(stderr,"Too big to dump\n"); return; } printf(" +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F"); bp = &buf[0]; _disable(); /* cli */ /* write ini value 2 times to enter config mode */ if (idnt[n].ini1) outp(idnt[n].port,idnt[n].ini1); if (idnt[n].ini2) outp(idnt[n].port,idnt[n].ini2); if (idnt[n].type == 8) idnt[n].port++; for (i=start;i<=end;++i) { outp(idnt[n].port,i); *bp++ = (unsigned char)inp(idnt[n].port+1); } if (idnt[n].type == 8) idnt[n].port--; outp(idnt[n].port,idnt[n].fin); /* exit config mode */ _enable(); /* sti */ bp = &buf[0]; for (i=start;i<=end;++i) { if (((i-start)%16)==0) printf("\n%02x:",i); printf("%02x ",*bp++); } printf("\n"); } #if defined(PATCH) int dopatch(int dist,char opr) { int i,source; source = 0; if (dist == 4) /* ALI patch is same as SMC */ dist = 1; if (opr == 'R') { /* depatch */ i = source; source = dist; dist = i; } if (drv_type == dist) { fputs("\nNo need to patch/depatch process.\n\n",stderr); return 0; } if (dist == 0) { /* backup exist, (if not do real depatch) */ strcpy(buf,"copy "); strcat(buf,sysdir); strcat(buf,"\\$erial.vxd"); if (access(&buf[5],4) == 0) { /* backup exist ? */ strcat(buf," "); strcat(buf,fname); fprintf(stderr,"\n%s\n",buf); if (system(buf)==0) {/* copy $erial -> Serial */ fputs("Restore vxd backup file successful.\n\n",stderr); return 1; } } else { fputs("\nvxd backup file not exist.\n\n",stderr); } } if (patch[drv_type].code == NULL) { fputs("Error -- unknown driver.\n",stderr); exit(1); } if (drv_type != source) { fputs("Error -- unexpected driver.\n",stderr); exit(1); } if (drv_type == 0) { /* make backup */ strcpy(buf,"copy "); strcat(buf,fname); strcat(buf," "); strcat(buf,sysdir); strcat(buf,"\\$erial.vxd"); fprintf(stderr,"\n%s\n",buf); if (system(buf)!=0){ fputs("Error -- Can't backup.\n",stderr); exit(1); } fputs("Backup original to $erial.vxd successful.\n\n",stderr); } if ((fd = fopen(fname,"r+b")) == NULL) { fputs("Error -- Can't open driver file.\n",stderr); exit(1); } if (fseek(fd,adr1,SEEK_SET) != 0) { fputs("Error -- Seek.\n",stderr); exit(1); } if (fwrite(patch[dist].code,patch[dist].len,1,fd)!=1) { fputs("Error -- write.\n",stderr); exit(1); } if (fseek(fd,(long)TBL_ADR_LEN,SEEK_CUR) != 0) { /* skip table address */ fputs("Error -- Seek.\n",stderr); exit(1); } if (fwrite(&patch[dist].code[SMC_LEN0+TBL_ADR_LEN],SMC_LEN1,1,fd)!=1) { fputs("Error -- write.\n",stderr); exit(1); } if (fseek(fd,adr2,SEEK_SET) != 0) { fputs("Error -- Seek.\n",stderr); exit(1); } if (fwrite((dist<2)? x1_tbl:x8_tbl ,24,1,fd)!=1) { fputs("Error -- write.\n",stderr); exit(1); } fclose(fd); fprintf(stderr,"Apply %s successful.\n\n",patch[dist].name); return 2; } int check_drv(char opr) { int i; long fsize; if ((fd = fopen(fname,"rb")) == NULL) { if ( (opr == 'P') || (opr == 'R')) { fprintf(stderr,"Error -- Can't open driver file '%s'.\n",fname); exit(1); } return -1; } fseek(fd,0L,SEEK_END); fsize = ftell(fd); for (i = 0; patch[i].code != NULL; i++) { if ((adr1 = search(fsize,patch[i].len,patch[i].code)) != 0L) break; } if (i<2) adr2 = search(fsize,24,x1_tbl); else if (i<4) adr2 = search(fsize,24,x8_tbl); if (adr2 == 0L) i = 5; /* old */ fclose(fd); fprintf(stdout,"%s driver detected\n",patch[i].name); return i; } void chg_autoexec(char opr,char *path) { char *p; int replace = 0; FILE *ofd; if ((ofd = fopen("C:\\AUTOEXEC.TMP","w")) == NULL) { fputs("Error -- Can't open 'autoexec.tmp' file.\n",stderr); exit(1); } if (access("C:\\AUTOEXEC.BAT",0) == 0) { /* autoexec.bat is exist */ sprintf(buf,"copy C:\\AUTOEXEC.BAT C:\\AUTOEXEC.SHD"); fprintf(stderr,"%s\n",buf); if (system(buf) != 0 ) { fputs("Error -- Autoexec.bat can't backup !\n",stderr); exit(1); } fprintf(stderr,"Backup AUTOEXEC.BAT successful.\n\n",buf); if ((fd = fopen("C:\\AUTOEXEC.BAT","r+")) == NULL) { fputs("Error -- Can't open 'autoexec.bat' file.\n",stderr); exit(1); } while (fgets(buf,256,fd)!=NULL) { p = buf; do { if ( (*p == 's') || (*p == 'S') ){ if ( (strnicmp(p,"SHSMOD",6) == 0) || (strnicmp(p,"SMCHSMOD",8) == 0) ) { fprintf(stderr,"SHSMOD will replace line,\n %s",buf); if (opr == 'P') sprintf(buf," %s B H\n",path); else sprintf(buf,"REM %s B H\n",path); fprintf(stderr, " -> %s\n",buf); replace++; break; } } } while (*p++); if (fputs(buf,ofd) < 0) { fputs("Error -- write to autoexec.tmp\n",stderr); exit(1); } } if (feof(fd) == 0) { fputs("Error -- Can't read autoexec.bat\n",stderr); exit(1); } fclose(fd); } if ( (replace == 0) && (opr == 'P') ) { sprintf(buf,"%s B H\n",path); fprintf(stderr,"SHSMOD will append line,\n %s\n",buf); if (fputs(buf,ofd) < 0) { fputs("Error -- apend to autoexec.tmp\n",stderr); exit(1); } replace++; } fclose(ofd); if (replace != 0) { sprintf(buf,"copy C:\\AUTOEXEC.TMP C:\\AUTOEXEC.BAT"); fprintf(stderr,"%s\n",buf); if (system(buf) != 0 ) { fputs("Error -- Autoexec.bat can't overwrite !\n",stderr); exit(1); } fprintf(stderr,"Overwrite AUTOEXEC.BAT successful.\n",buf); } unlink("C:\\AUTOEXEC.TMP"); return; } long search(long fsize, int len, unsigned char *code) { int stat; long adr; stat = 1; for(adr = 0x200;adr 4) ? 0 : *bioscomp; } printf("\n"); #endif } #if defined(linux) /* #define DEBUG_686A */ static unsigned char save_config; #define MODE_HI 2 #define MODE_LO 1 #define MODE_INQ 0 typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; #define pci_find_device(a, b, c) find_pci() static const char vt82c686[] = " ISA bridge: VIA Technologies, Inc. VT82C686"; int find_pci(void) { int fd; int n; int bus, dev, func; char line[512]; char buf[256]; char proc_bus_pci[256]; FILE *proc_pci; proc_pci = fopen("/proc/pci", "r"); if (proc_pci == NULL) { printf("cannnot open /proc/pci\n"); return(0); } while(1){ n = -1; if (fgets(line, 512, proc_pci) == NULL) break; n = sscanf(line, " Bus %d, device %d, function %d:", &bus, &dev, &func); /* printf("n = %d\n", n); */ if (n == 3) { if (fgets(line, 512, proc_pci) == NULL) break; n = strncmp(vt82c686, line, strlen(vt82c686)); /* printf("second = %d\n", n); */ if (n == 0) { strcpy(buf, line + 4); break; } } } fclose(proc_pci); if (n == 0) { #ifdef DEBUG_686A printf("Found = %s\n", buf); printf("bus = %02x, dev = %02x, func = %01x\n", bus, dev, func); #endif ; } else return(0); sprintf(proc_bus_pci, "/proc/bus/pci/%02x/%02x.%01x", bus, dev, func); fd = open(proc_bus_pci, O_RDWR); if (fd <= 0) { printf("open error = %s\n", proc_bus_pci); fd = 0; } return(fd); } #define pci_read_config_byte(pcidev, offset, ptr) \ lseek(pcidev, offset, SEEK_SET); \ read(pcidev, ptr, 1) #define pci_write_config_byte(pcidev, offset, data) \ lseek(pcidev, offset, SEEK_SET); \ write(pcidev, &data, 1) static FILE *fp_copy = NULL; #define cli() if ((fp_copy = fp) == NULL) _disable() #define sti() if (!fp_copy) _enable() const unsigned short INX=0x3F0; const unsigned short DAT=0x3F1; /* * via686A() usage: * * port=0, mode=0 -- Chip detect mode, return (ID|Rev) or NONE * port=[1|2|3], mode=0 -- Status detect mode, return status Reg. * port=[1|2|3], mode=[1|2] -- Set mode, return status Reg. */ int via686a(int port, int mode, unsigned int *io) { typedef unsigned char UCH; UCH v; int val = 0; struct pci_dev *pcidev = NULL; unsigned char confval; #ifdef DEBUG_686A printf("port = %d, mode = %d, io = %08x\n", port, mode, io); #endif pcidev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL); if (pcidev) { cli(); /* start config */ pci_read_config_byte(pcidev, 0x85, &confval); confval |= 0x2; pci_write_config_byte(pcidev, 0x85, confval); outp(INX, 0xE0); v = (UCH) inp(DAT); val = v << 8; /* for INQ mode */ #ifdef DEBUG_686A printf("SuperI/O ID = %02x\n", v); #endif outp(INX, 0xE1); v = (UCH) inp(DAT); val |= v; /* for INQ mode */ #ifdef DEBUG_686A printf("SuperI/O Rev = %02x\n", v); #endif outp(INX, 0xEE); v = (UCH) inp(DAT); #ifdef DEBUG_686A printf("Config Reg. = %02x, port = %02x, mode = %02x\n", v, port, mode); #endif if(port && mode) { /* Set mode & return status */ port <<= 6; if (mode == MODE_HI) v |= port; else if (mode == MODE_LO) v &= ~port; outp(INX, 0xEE); outp(DAT, v); outp(INX, 0xEE); v = (UCH) inp(DAT); #ifdef DEBUG_686A printf("*Config Reg. = %02x\n", (int) v); #endif val = v & 0xC0; /* for return status */ } else if(port) { /* Inquire Status */ outp(INX, 0xEE); v = (UCH) inp(DAT); #ifdef DEBUG_686A printf("*Config Reg. = %02x\n", (int) v); #endif val = v & 0xC0; /* for return status */ } #ifdef DEBUG_686A printf("io = %08x\n", (int) io); #endif if (io) { /* IOport inq */ /* Serial Port1 Address */ outp(INX, 0xE7); v = (UCH) inp(DAT); io[0] = (unsigned) (v << 2); #ifdef DEBUG_686A printf("COM1 Address = %04x\n", (v << 2)); #endif /* Serial Port3 Address */ outp(INX, 0xE8); v = (UCH) inp(DAT); io[1] = (unsigned) (v << 2); #ifdef DEBUG_686A printf("COM2 Address = %04x\n", (v << 2)); #endif /* Get Function Select Register */ outp(INX, 0xE2); v = (UCH) inp(DAT); #ifdef DEBUG_686A printf("SIO Function = %04x\n", v); #endif if ((v & 0x04) == 0 ) { /* COM1 Disable */ #ifdef DEBUG_686A printf("COM1 is disabled\n"); #endif /* io[0] = 0; */ } if ((v & 0x08) == 0 ) { /* COM2 Disable */ #ifdef DEBUG_686A printf("COM2 is disabled\n"); #endif /* io[1] = 0; */ } /* Get Serial Port Configuration */ outp(INX, 0xEE); v = (UCH) inp(DAT); if (v & 0x3F) { /* Check COM2 use */ #ifdef DEBUG_686A printf("COM2 is not standard = %02x\n", (v & 0x3F)); #endif io[1] = 0; } #if 0 /* Power Down Control */ outp(INX, 0xEF); v = (UCH) inp(DAT); #ifdef DEBUG_686A printf("EF - Power Down Control = %x\n", v); #endif /* Serial Port Control */ outp(INX, 0xF1); v = (UCH) inp(DAT); #ifdef DEBUG_686A printf("F1 - Serial Port Control = %x\n", v); #endif #endif /* #if 0 */ } /* io != 0 */ /*stop config*/ confval &= ~0x2; pci_write_config_byte(pcidev, 0x85, confval); sti(); } return(val); } #else int via686a(int port, int mode, unsigned int *io) { return(0); } #endif