📄 matcd.c
字号:
unsigned char type; /*00 CD-DA or CD-ROM 10 CD-I 20 XA */ unsigned char trk_low; /*Normally 1*/ unsigned char trk_high; /*Highest track number*/ unsigned char vol_msf[3]; /*Size of disc in min/sec/frame*/};struct matcd_mbx { short controller; short ldrive; short partition; short port; short iftype; /*<20>Host interface type*/ short retry; short nblk; int sz; u_long skip; struct buf *bp; int p_offset; short count;};static struct matcd_data { short drivemode; /*Last state drive was set to*/ short flags; short status; /*Last audio-related function*/ int blksize; u_long disksize; short iobase; short iftype; /*<20>Host interface type*/ struct disklabel dlabel; unsigned int partflags[MAXPARTITIONS]; unsigned int openflags; struct matcd_volinfo volinfo; struct matcd_mbx mbx; u_char patch[2]; /*<12>Last known audio routing*/ u_char volume[2]; /*<12>Last known volume setting*/#ifdef DEVFS void *ra_devfs_token; /* handle for devfs entry */ void *rc_devfs_token; void *a_devfs_token; void *c_devfs_token; void *rla_devfs_token; void *rlc_devfs_token; void *la_devfs_token; void *lc_devfs_token;#endif DEVFS} matcd_data[TOTALDRIVES];/* Bit equates for matcd_data.flags*/#define MATCDINIT 0x0001 /*Probe ran on host adapter*/#define MATCDLABEL 0x0004 /*Valid TOC exists*/#define MATCDLOCK 0x0008 /*<15>Drive door is locked*/#define MATCDWARN 0x0020 /*Have reported an open disc change*//* Bit equates for matcd_data.partflags*/#define MATCDOPEN 0x0001#define MATCDREADRAW 0x0002/* Error classes returned by chk_error()*/#define ERR_RETRY 1 /*A retry might recover this*/#define ERR_INIT 2 /*A retry certainly will get this*/#define ERR_FATAL 3 /*This cannot be recovered from*/static struct buf_queue_head request_head[NUMCTRLRS]; /*<18>A queue for each host interface*/static int nextcontroller=0; /*<18>Number of interface units found*/static int drivepresent=0; /*<18>Don't change this - see license*/static int iftype; /*<20>Probe/Attach i.f. type relay*/static unsigned char if_state[4]={0,0,0,0}; /*<18>State of the host I/F and bus*//* Flags in the if_state array*/#define BUSBUSY 0x01 /*<18>Bus is already busy*/struct matcd_read2 { unsigned char start_msf[3]; unsigned char end_msf[3];};/* This mystery structure is supposed to make dynamic driver loading possible.*//*--------------------------------------------------------------------------- These macros take apart the minor number and yield the partition, drive on controller, and controller. This must match the settings in /dev/MAKEDEV.---------------------------------------------------------------------------*/#define matcd_partition(dev) ((minor(dev)) & 0x07)#define matcd_ldrive(dev) (((minor(dev)) & 0x78) >> 3)#define matcd_cdrive(dev) (((minor(dev)) & 0x18) >> 3)#define matcd_controller(dev) (((minor(dev)) & 0x60) >> 5)#ifdef LOCKDRIVE#define matcd_lockable(dev) (((minor(dev)) & 0x80) >> 5)#endif /*LOCKDRIVE*//*--------------------------------------------------------------------------- Entry points and other connections to/from kernel - see also conf.h --- not any more :)---------------------------------------------------------------------------*/static int matcd_probe(struct isa_device *dev);static int matcd_attach(struct isa_device *dev);struct isa_driver matcddriver={matcd_probe, matcd_attach, "matcdc"};static d_open_t matcdopen;static d_close_t matcdclose;static d_ioctl_t matcdioctl;static d_psize_t matcdsize;static d_strategy_t matcdstrategy;#define CDEV_MAJOR 46#define BDEV_MAJOR 17static struct cdevsw matcd_cdevsw;static struct bdevsw matcd_bdevsw = { matcdopen, matcdclose, matcdstrategy, matcdioctl, /*17*/ nodump, matcdsize, 0, "matcd", &matcd_cdevsw, -1 };/*--------------------------------------------------------------------------- Internal function declarations---------------------------------------------------------------------------*/static void matcd_drvinit(void *unused);static void matcd_start(int controller);static void zero_cmd(char *);static void matcd_pread(int port, int count, unsigned char * data);static int matcd_fastcmd(int port,int ldrive,int cdrive, unsigned char * cp);static void matcd_slowcmd(int port,int ldrive,int cdrive, unsigned char * cp);static void matcd_blockread(int state);static void selectdrive(int port,int drive);static void doreset(int port,int cdrive);static int doprobe(int port,int cdrive);static void lockbus(int controller, int ldrive);static void unlockbus(int controller, int ldrive);static int matcd_volinfo(int ldrive);static void draincmd(int port,int cdrive,int ldrive);static int get_error(int port, int ldrive, int cdrive);static int chk_error(int errnum);static int msf_to_blk(unsigned char * cd);#ifdef FULLDRIVERstatic int matcd_playtracks(int ldrive, int cdrive, int controller, struct ioc_play_track *pt);static int matcd_playmsf(int ldrive, int cdrive, int controller, struct ioc_play_msf *pt);static int matcd_pause(int ldrive, int cdrive, int controller, int action);static int matcd_stop(int ldrive, int cdrive, int controller);static int matcd_level(int ldrive, int cdrive, int controller, struct ioc_vol * volume, int action);static int matcd_patch(int ldrive, int cdrive, int controller, struct ioc_patch * routing);static int matcd_route(int ldrive, int cdrive, int controller, int command);static int matcd_pitch(int ldrive, int cdrive, int controller, struct ioc_pitch * speed);#endif /*FULLDRIVER*/static int matcd_toc_header(int ldrive, int cdrive, int controller, struct ioc_toc_header * toc);static int matcd_toc_entries(int ldrive, int cdrive, int controller, struct ioc_read_toc_entry *ioc_entry);static int matcd_read_subq(int ldrive, int cdrive, int controller, struct ioc_read_subchannel * sqp);static int matcd_igot(struct ioc_capability * sqp);static int waitforit(int timelimit, int state, int port, char * where);static int get_stat(int port, int ldrive);static int media_chk(struct matcd_data *cd,int errnum, int ldrive,int test);static int matcd_eject(int ldrive, int cdrive, int controller);static int matcd_doorclose(int ldrive, int cdrive, int controller);static int matcd_dlock(int ldrive, int cdrive, int controller, int action);static int docmd(char * cmd, int ldrive, int cdrive, int controller, int port);/*--------------------------------------------------------------------------- matcdopen - Open the device This routine actually gets called every time anybody opens any partition on a drive. But the first call is the one that does all the work.<15> If LOCKDRIVE is enabled, additional minor number devices allow<15> the drive to be locked while being accessed.---------------------------------------------------------------------------*/int matcdopen(dev_t dev, int flags, int fmt, struct proc *p){ int cdrive,ldrive,partition,controller,lock; struct matcd_data *cd; int i,z,port; unsigned char cmd[MAXCMDSIZ]; ldrive=matcd_ldrive(dev); cdrive=matcd_cdrive(dev); partition=matcd_partition(dev); controller=matcd_controller(dev); lock=matcd_lockable(dev); cd= &matcd_data[ldrive]; port=cd->iobase; /*and port#*/ if (ldrive >= TOTALDRIVES) return(ENXIO);#ifdef DEBUGOPEN printf("matcd%d: Open: dev %x partition %x controller %x flags %x cdrive %x\n", ldrive,(int)dev,partition,controller,cd->flags, matcd_cdrive(dev));#endif /*DEBUGOPEN*/ if (!(cd->flags & MATCDINIT)) { /*Did probe find this drive*/ return(ENXIO); } if (!(cd->flags & MATCDLABEL) && cd->openflags) { /*Has drive completely closed?*/ return(ENXIO); /*No, all partitions must close*/ }/* Now, test to see if the media is ready*/ lockbus(controller,ldrive); zero_cmd(cmd); cmd[0]=NOP; /*Test drive*/ matcd_slowcmd(port,ldrive,cdrive,cmd); i=waitforit(10*TICKRES,DTEN,port,"matopen"); z=get_stat(port,ldrive); /*Read status byte*/#ifdef DEBUGOPEN printf("matcd%d Result of NOP is %x %x\n",ldrive,i,z);#endif /*DEBUGOPEN*/ if ((z & MATCD_ST_DSKIN)==0) { /*Is there a disc in the drive?*/#ifdef DEBUGOPEN printf("matcd%d: No Disc in open\n",ldrive);#endif /*DEBUGOPEN*/ unlockbus(controller, ldrive); /*Release bus lock*/ cd->flags &= ~MATCDLABEL; /*<16>Mark label as invalid*/ if (major(dev)==RAW_DEVICE) { /*<16>Is the char device?*/ return(0); /*<16>Allow Semi open*/ } else { return(ENXIO); /*<16>Normally blow off*/ } } if (z & MATCD_ST_ERROR) { /*Was there an error*/ i=get_error(port,ldrive,cdrive);/*Find out what it was*/#ifdef DEBUGOPEN printf("matcd%d NOP Error was %x\n",ldrive,i);#endif /*DEBUGOPEN*/ if (cd->openflags) { /*Any parts open?*/ if (media_chk(cd,i,ldrive,0)) { /*<14>Was it a disc chg?*/#ifdef DEBUGOPEN printf("matcd%d: Disc change detected i %x z %x\n", ldrive,i,z);#endif /*DEBUGOPEN*/ unlockbus(controller, ldrive); /*Release bus lock*/ return(ENOTTY); } } else { media_chk(cd,i,ldrive,1);/*<14>Was it a disc chg?*/ /*<14>Clear volume info*/ } } unlockbus(controller, ldrive); /*Release bus lock*//* Here we fill in the disklabel structure although most is hardcoded.*/ if ((cd->flags & MATCDLABEL)==0) { bzero(&cd->dlabel,sizeof(struct disklabel));/* Now we query the drive for the actual size of the media. This is where we find out of there is any media or if the media isn't a Mode 1 or Mode 2/XA disc. See version information about Mode 2/XA support.*/ lockbus(controller,ldrive); i=matcdsize(dev); unlockbus(controller, ldrive); /*Release bus lock*/#ifdef DEBUGOPEN printf("matcd%d: Bus unlocked in open\n",ldrive);#endif /*DEBUGOPEN*/ if (i < 0) { printf("matcd%d: Could not read the disc size\n",ldrive); return(ENXIO); } /*matcdsize filled in rest of dlabel*//* Based on the results, fill in the variable entries in the disklabel*/ cd->dlabel.d_secsize=cd->blksize; cd->dlabel.d_ncylinders=(cd->disksize/100)+1; cd->dlabel.d_secperunit=cd->disksize; cd->dlabel.d_partitions[0].p_size=cd->disksize; cd->dlabel.d_checksum=dkcksum(&cd->dlabel);/* Now fill in the hardcoded section*/ /*123456789012345678*/ strncpy(cd->dlabel.d_typename,"Matsushita CDR ",16); strncpy(cd->dlabel.d_packname,"(c) 1994, fdiv ",16); cd->dlabel.d_magic=DISKMAGIC; cd->dlabel.d_magic2=DISKMAGIC; cd->dlabel.d_nsectors=100; cd->dlabel.d_secpercyl=100; cd->dlabel.d_ntracks=1; cd->dlabel.d_interleave=1; cd->dlabel.d_rpm=300; cd->dlabel.d_npartitions=1; /*See note below*/ cd->dlabel.d_partitions[0].p_offset=0; cd->dlabel.d_partitions[0].p_fstype=9; cd->dlabel.d_flags=D_REMOVABLE;/* I originally considered allowing the partition match tracks or sessions on the media, but since you are allowed up to 99 tracks in the RedBook world, this would not fit in with the BSD fixed partition count scheme. So ioctls will be used to shift the track to be accessed into partition 1.*/ cd->flags |= MATCDLABEL; /*Mark drive as having TOC*/ }#ifdef DEBUGOPEN printf("matcd%d open2: partition=%d disksize=%d blksize=%x flags=%x\n", ldrive,partition,(int)cd->disksize,cd->blksize,cd->flags);#endif /*DEBUGOPEN*/#ifdef LOCKDRIVE if (cd->openflags==0 && lock) { zero_cmd(cmd); cmd[0]=LOCK; /*Lock drive*/ cmd[1]=1; docmd(cmd,ldrive,cdrive,controller,port);/*<15>Issue cmd*/ cd->flags |= MATCDLOCK; /*<15>Drive is now locked*/ }#endif /*LOCKDRIVE*/ cd->openflags |= (1<<(partition+lock));/*<24>Mark partition open*/ if (partition==RAW_PART || (partition < cd->dlabel.d_npartitions && cd->dlabel.d_partitions[partition].p_fstype != FS_UNUSED)) { cd->partflags[partition] |= MATCDOPEN; if (partition == RAW_PART) { cd->partflags[partition] |= MATCDREADRAW; }#ifdef DEBUGOPEN printf("matcd%d: Open is complete - openflags %x\n", ldrive,cd->openflags);#endif /*DEBUGOPEN*/ return(0); }#ifdef DEBUGOPEN printf("matcd%d: Open FAILED\n",ldrive);#endif /*DEBUGOPEN*/ return(ENXIO);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -