📄 matcd.c
字号:
Creative adapter boards: #1330A Sound Blaster PRO #1730 Sound Blaster 16 #1740 Sound Blaster 16 (cost reduced) #2230 Sound Blaster 16 (cost reduced) #2770 Sound Blaster 16 Value (cost reduced) #1810 omniCD upgrade kit adapter card (stand-alone CD) #3100 PhoneBlaster SB16 + Sierra 14.4K modem combo Creative releases a newer and cheaper-to-make Sound Blaster board every few months, so by the original release date of this software, there are probably 8 different board models called Sound Blaster 16. These include "Vibra", "Value", etc. Please report additional part numbers and board descriptions and new port numbers that work to the author.---------------------------------------------------------------------------*/static intmatcd_probe(struct isa_device *dev){ int i,cdrive; unsigned char y; int port = dev->id_iobase; /*Take port hint from config file*/ cdrive=nextcontroller; /*Controller defined by pass for now*/ if (nextcontroller==NUMCTRLRS) { printf("matcdc%d: - Too many interfaces specified in config\n", nextcontroller); return(0); } if (nextcontroller==0) { /*Very first time to be called*/ for (i=0; i<TOTALDRIVES; i++) { matcd_data[i].drivemode=MODE_UNKNOWN; matcd_data[i].flags=0; } } i=nextcontroller*DRIVESPERC; /*Precompute controller offset*/ for (y=0; y<DRIVESPERC; y++) { matcd_data[i+y].flags=0; }#ifdef DEBUGPROBE printf("matcdc%d: In probe i %d y %d port %x\n", nextcontroller,i,y,port);#endif /*DEBUGPROBE*/#ifdef AUTOHUNT#ifdef DEBUGPROBE printf("matcd%d: size of port_hints %d\n", nextcontroller,sizeof(port_hints));#endif /*DEBUGPROBE*/ if (port==-1) { for(i=0;i<(sizeof(port_hints)/sizeof(short));i++) { port=port_hints[i];#ifdef DEBUGPROBE printf("matcdc%d: Port hint %x\n",nextcontroller,port);#endif /*DEBUGPROBE*/ if (port==-1) { dev->id_iobase=-1; /*Put port ? back*/ return(0);/*Nothing left to try*/ } if (port!=0) { /*Untested port found*/ dev->id_iobase=port; port_hints[i]=0;/*Don't use that port again*/ if (doprobe(port,cdrive)==0) return(NUMPORTS); } } dev->id_iobase=-1; /*Put port ? back as it was*/ return(0); /*Interface not found*/ } else { /*Config specified a port*/ i=0; /*so eliminate it from the hint list*/ for(i=0;;i++) { /*or we might try to assign it again*/ if (port_hints[i]== -1) break; /*End of list*/ if (port_hints[i]==port) { port_hints[i]=0; /*Clear duplicate*/ break; } } if (doprobe(port,cdrive)==0) return(NUMPORTS); else return(0); }#else /*AUTOHUNT*/ if (port==-1) { printf("matcdc%d: AUTOHUNT disabled but port? specified in config\n", nextcontroller); return(0); } if (doprobe(port,cdrive)==0) return(NUMPORTS); else return(0);#endif /*AUTOHUNT*/}/*--------------------------------------------------------------------------- doprobe - Common probe code that actually checks the ports we have decided to test.<20> Edit 20 changes adds code to determine if the host interface is one that behaves like the Creative SoundBlaster cards, or whether the host interface like those used by some boards made by Media Vision and a version known as Lasermate.---------------------------------------------------------------------------*/int doprobe(int port,int cdrive){ unsigned char cmd[MAXCMDSIZ]; int i;#ifdef RESETONBOOT doreset(port,cdrive); /*Reset what might be our device*/#endif /*RESETONBOOT*/ outb(port+PHASE,0); /*<16>Guarantee status phase*/ zero_cmd(cmd); cmd[0]=NOP; /*A reasonably harmless command. This command will fail after power-up or after reset. That's OK*/#ifdef RESETONBOOT if (((inb(port+STATUS) & (DTEN|STEN)) != (DTEN|STEN)) || (inb(port+DATA) != 0xff)) return(-1); /*<20>Something detected but it isn't the device we wanted*/#endif /*RESETONBOOT*/ if (matcd_fastcmd(port,0,0,cmd)==0) {/*Issue command*/ outb(port+PHASE,1); /*<20>Switch to Creative Data phase*/ i=inb(port+CMD); /*<20>Read a byte in data phase*/ outb(port+PHASE,0); /*<20>Switch to Creative Status phase*/ if ((inb(port+STATUS) & (DTEN|STEN)) == (DTEN|STEN)) { /*<20>Drive went idle*/ iftype=1; /*<20>It is not a Creative interface.*/ } else { /*<20>Status byte still available*/ iftype=0; inb(port+CMD); /*<20>Read status byte*/ }#ifdef DEBUGPROBE printf("matcdc%d: Probe found something\n",nextcontroller);#endif /*DEBUGPROBE*//*------Don't change anything below this line - see license -----------------*/ if (drivepresent==0) { /*Don't change*/ printf("matcd - Matsushita (Panasonic) CD-ROM Driver by FDIV, %s\n", /*Don't change*/ MATCDVERSION); /*Don't change*/ drivepresent++; /*Don't change*/ if (drivepresent==0) /*Don't change - make LINT happy*/ printf("%s\n",MATCDCOPYRIGHT); /*Don't change*/ } /*Don't change*//*------Don't change anything above this line - see license -----------------*/ return(0); /*Drive 0 detected*/ }#ifdef DEBUGPROBE printf("matcdc%d: Probe DID NOT find something\n",nextcontroller);#endif /*DEBUGPROBE*/ return(1);}/*--------------------------------------------------------------------------- matcd_attach - Locates drives on the adapters that were located. If we got here, we located an interface and at least one drive. Now we figure out how many drives are under that interface. The Panasonic interface is too simple to call it a controller, but in the existing PDP model, that is what it would be.---------------------------------------------------------------------------*/static intmatcd_attach(struct isa_device *dev){ int i; unsigned int z,cdrive; unsigned char cmd[MAXCMDSIZ]; unsigned char data[12]; struct matcd_data *cd; int port = dev->id_iobase; /*Take port ID selected in probe()*/#ifdef DEBUGPROBE printf("matcdc: Attach dev %x id_unit %d\n", (unsigned int)dev,dev->id_unit);#endif /*DEBUGPROBE*/ printf("matcdc%d Host interface type %d\n", nextcontroller,iftype); bufq_init(&request_head[nextcontroller]); for (cdrive=0; cdrive<4; cdrive++) { /*We're hunting drives...*/ zero_cmd(cmd); cmd[0]=NOP; /*A reasonably harmless command. This command will fail after power-up or after reset. It's OK*/ i=cdrive+(DRIVESPERC*nextcontroller); if (matcd_fastcmd(port,i,cdrive,cmd)==0) { /*Issue cmd*/ z=get_stat(port,cdrive);/*Read status byte*/ if ((z & MATCD_ST_ERROR)) { /*If there was an error, we must ask for error info or subsequent cmds fail*/ zero_cmd(cmd); cmd[0]=READERROR; /*Inquire*/ matcd_fastcmd(port,i,cdrive,cmd); matcd_pread(port,8,data);/*Read data returned*/ z=get_stat(port,i);/*Read status byte*/#ifdef DEBUGPROBE printf("matcd%d: Status byte %x ",i,z);#endif /*DEBUGPROBE*/ } zero_cmd(cmd); cmd[0]=READID; /*Get drive ID*/ matcd_fastcmd(port,i,cdrive,cmd); matcd_pread(port,10,data);/*Read Drive Parm*/ get_stat(port,i); /*Read and toss status byte*/ data[10]=0; /*Build ASCIZ string*/ printf("matcd%d: [%s] ",i,data); cd=&matcd_data[i]; cd->flags |= MATCDINIT; cd->iobase=dev->id_iobase; cd->iftype=iftype; cd->openflags=0; cd->volume[0]=cd->volume[1]=DEFVOL; /*<12>Match volume drive resets to*/ cd->patch[0]=0x01; /*<12>Channel 0 to Left*/ cd->patch[1]=0x02; /*<12>Channel 1 to Right*/ cd->status=CD_AS_NO_STATUS; for (i=0; i<MAXPARTITIONS; i++) { cd->partflags[i]=0; }#ifdef DEVFS cd->ra_devfs_token = devfs_add_devswf(&matcd_cdevsw, dkmakeminor(i, 0, 0), DV_CHR, UID_ROOT, GID_OPERATOR, 0640, "rmatcd%da", i); cd->rc_devfs_token = devfs_add_devswf(&matcd_cdevsw, dkmakeminor(i, 0, RAW_PART), DV_CHR, UID_ROOT, GID_OPERATOR, 0640, "rmatcd%dc", i); cd->a_devfs_token = devfs_add_devswf(&matcd_bdevsw, dkmakeminor(i, 0, 0), DV_BLK, UID_ROOT, GID_OPERATOR, 0640, "matcd%da", i); cd->c_devfs_token = devfs_add_devswf(&matcd_bdevsw, dkmakeminor(i, 0, RAW_PART), DV_BLK, UID_ROOT, GID_OPERATOR, 0640, "matcd%dc", i); cd->rla_devfs_token = devfs_add_devswf(&matcd_cdevsw, 0x80 | dkmakeminor(i, 0, 0), DV_CHR, UID_ROOT, GID_OPERATOR, 0640, "rmatcd%dla", i); cd->rlc_devfs_token = devfs_add_devswf(&matcd_cdevsw, 0x80 | dkmakeminor(i, 0, RAW_PART), DV_CHR, UID_ROOT, GID_OPERATOR, 0640, "rmatcd%dc", i); cd->la_devfs_token = devfs_add_devswf(&matcd_bdevsw, 0x80 | dkmakeminor(i, 0, 0), DV_BLK, UID_ROOT, GID_OPERATOR, 0640, "matcd%dla", i); cd->lc_devfs_token = devfs_add_devswf(&matcd_bdevsw, 0x80 | dkmakeminor(i, 0, RAW_PART), DV_BLK, UID_ROOT, GID_OPERATOR, 0640, "matcd%dlc", i);#endif } } nextcontroller++; /*Bump ctlr assign to next number*/ printf("\n"); /*End line of drive reports*/ return(1);}/*--------------------------------------------------------------------------- zero_cmd - Initialize command buffer---------------------------------------------------------------------------*/void zero_cmd(char * lcmd){ int i; for (i=0; i<MAXCMDSIZ; lcmd[i++]=0); return;}/*--------------------------------------------------------------------------- doreset - Resets all the drives connected to a interface---------------------------------------------------------------------------*/void doreset(int port,int cdrive){ register int i,z; outb(port+RESET,0); /*Reset what might be our device*/ /*Although this ensures a known state, it does close the drive door (if open) and aborts any audio playback in progress. */ for (i=0;i<(125*ISABUSKHZ);i++){/*DELAY 500msec minimum. Worst case is door open and none or unreadable media */ z=inb(port+CMD); /*This makes the loop run at a known speed. This value is ok for 8.33MHz bus*/ } for (i=0;i<4;i++) { matcd_data[(cdrive*4)+i].drivemode=MODE_UNKNOWN; } return;}/*--------------------------------------------------------------------------- matcd_fastcmd - Send a command to a drive This routine executed commands that return instantly (or reasonably quick), such as RESET, NOP, READ ERROR, etc. The only difference between it and handling for slower commands, is the slower commands will invoke a timeout/sleep if they don't get an instant response. Fastcmd is mainly used in probe(), attach() and error related functions. Every attempt should be made to NOT use this function for any command that might be executed when the system is up.---------------------------------------------------------------------------*/int matcd_fastcmd(int port,int ldrive,int cdrive,unsigned char * cp){ unsigned int i; unsigned char z; int level;#ifdef DEBUGCMD unsigned char *cx;#endif /*DEBUGCMD*/ draincmd(port,cdrive,ldrive); /*Make sure bus is really idle*/#ifdef DEBUGCMD cx=cp; printf("matcd%d: Fast Send port %x sel %d command %x %x %x %x %x %x %x\n", ldrive,port,cdrive,cx[0],cx[1],cx[2],cx[3],cx[4],cx[5],cx[6]);#endif /*DEBUGCMD*/ selectdrive(port,cdrive); /*Enable the desired target drive*/ level=splhigh(); /*----------------------------------------*/ for (i=0; i<7; i++) { /*The seven bytes of the command*/ outb(port+CMD,*cp++); /*must be sent within 10msec or*/ } /*the drive will ignore the cmd*/ splx(level); /*------------------------------------------------*//* Now we wait a maximum of 240msec for a response. Only in a few rare cases does it take this long. If it is longer, the command should probably be slept on rather than increasing the timing value*/ for (i=0; i<(60*ISABUSKHZ); i++) { z = (inb(port+STATUS)) & (DTEN|STEN); if (z != (DTEN|STEN)) break; }/* We are now either in a data or status phase, OR we timed-out.*/ if (z == (DTEN|STEN)) {#ifdef DEBUGCMD printf("matcd%d: Command time-out\n",ldrive);#endif /*DEBUGCMD*/ return(-1); } if (z != DTEN) { return(1); } return(0);}/*--------------------------------------------------------------------------- matcd_slowcmd - Issue a command to the drive This routine is for commands that might take a long time, such as a read or seek. The caller must determine if the command completes instantly or schedule a poll later on.---------------------------------------------------------------------------*/void matcd_slowcmd(int port,int ldrive,int cdrive,unsigned char * cp){ unsigned int i; int level,size;#ifdef DEBUGCMD unsigned char *cx;#endif /*DEBUGCMD*/ draincmd(port,cdrive,ldrive); /*Make sure bus is really idle*/#ifdef DEBUGCMD cx=cp; printf("matcd%d: Slow Send port %x sel %d command %x %x %x %x %x %x %x\n", ldrive,port,cdrive,cx[0],cx[1],cx[2],cx[3],cx[4],cx[5],cx[6]);#endif /*DEBUGCMD*/ selectdrive(port,cdrive); /*Enable the desired target drive*/ if (*cp==ABORT) size=1; else size=7; level=splhigh(); /*----------------------------------------*/ for (i=0; i<size; i++) { /*The seven bytes of the command*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -