diff -u --recursive --new-file v1.2.7/linux/Makefile linux/Makefile --- v1.2.7/linux/Makefile Sat Apr 29 12:42:20 1995 +++ linux/Makefile Tue May 2 08:18:15 1995 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 2 -SUBLEVEL = 7 +SUBLEVEL = 8 ARCH = i386 diff -u --recursive --new-file v1.2.7/linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c --- v1.2.7/linux/arch/i386/kernel/vm86.c Wed Mar 29 06:52:56 1995 +++ linux/arch/i386/kernel/vm86.c Tue May 2 08:02:12 1995 @@ -358,6 +358,14 @@ IP(regs) += 2; set_vflags_long(popl(ssp, sp), regs); return; + + /* iretd */ + case 0xcf: + SP(regs) += 12; + IP(regs) = (unsigned short)popl(ssp, sp); + regs->cs = (unsigned short)popl(ssp, sp); + set_vflags_long(popl(ssp, sp), regs); + return; } /* pushf */ diff -u --recursive --new-file v1.2.7/linux/drivers/block/README.sbpcd linux/drivers/block/README.sbpcd --- v1.2.7/linux/drivers/block/README.sbpcd Wed Mar 29 06:52:57 1995 +++ linux/drivers/block/README.sbpcd Tue Apr 25 00:54:36 1995 @@ -1,4 +1,4 @@ -This README belongs to release 3.4 or newer of the SoundBlaster Pro +This README belongs to release 3.5 or newer of the SoundBlaster Pro (Matsushita, Kotobuki, Panasonic, CreativeLabs, Longshine and soon TEAC, too) CD-ROM driver for Linux. @@ -16,28 +16,18 @@ an internal drive, and you can use it as an internal, too - f.e. plug it into a soundcard). -The quad-speed TEAC CD-55A drive uses the same interface types, but has a -totally different command and flow control scheme. Support is under -construction, but split: Greg Nowicki (nowicki@tardis.larc.nasa.gov) -cares about the separate driver "teaccd". Please, do not mail him merely for -asking "user questions" at the moment - the project is still a "baby". - CreativeLabs has a new drive "CD-200". Support is under construction. -Detection should already work. - -Regarding CD200 support: - Please, don't mail me about it if you are not a competent BETA tester - (if you are: mail!; I do not have such drives). - Please, don't drop simple questions about the new drives in the - newsgroups. Full support needs more or less time. -If you like to help, you can mail me the "SBPCD:..." messages, regarding the -new drives. But I mostly will not answer (just use) it. +Drive detection and playing audio should already work. I need qualified +feedback about the bugs within the data functions or a drive (I never saw +a CD200). + +The quad-speed TEAC CD-55A drive is supported. The routines may still be +a little bit buggy, but the data rate already reaches 500 kB/sec if you +set SBP_BUFFER_FRAMES to 64. The drive is able to deliver 600 kB/sec, so +this has to get a point of work. This driver is NOT for Mitsumi or Sony or Aztech or Philips or XXX drives, and this driver is in no way usable for any new IDE ATAPI drive. -For Aztech CDA-268 drives (and for some Wearnes, Okano and Orchid drives), -Werner Zimmermann has done a driver which currently resides at ftp.gwdg.de -under /pub/linux/cdrom/drivers/aztech/. This driver will work with the soundcard interfaces (SB Pro, SB 16, Galaxy, SoundFX, ...) and/or with the "no-sound" cards (Panasonic CI-101P, LaserMate, @@ -53,8 +43,8 @@ because the behavior of some sound card interfaces is different. The driver respects all known drive firmware releases - my old drive is a 2.11, -but it should work with "old" drives <2.01 ... >3.00 and with "new" drives -(which count the releases around 0.75 or 1.00). +but it should work with CR-52x drives <2.01 ... >3.00 and with CR-56x drives +<0.75 .. 5.00. Up to 4 drives per interface card, and up to 4 interface cards are supported. All supported drive families can be mixed, but the CR-521 drives are @@ -90,28 +80,30 @@ With the CR-562 and CR-563 drives, the reading of audio frames is possible. This is implemented by an IOCTL function which per default reads only up to -4 frames of 2352 bytes at once (configurable with the "READ_AUDIO" define). +4 frames of 2352 bytes at once (configurable with the "READ_AUDIO" define, +"55" is the maximum if you use sbpcd as a "module"). Reading the same frame a second time gives different data; the frame data start at a different position, but all read bytes are valid, and we always read 98 consecutive chunks (of 24 Bytes) as a frame. Reading more than 1 frame -at once misses some chunks at each frame boundary.This lack has to get -corrected by external, "higher level" software which reads the same frame +at once possibly misses some chunks at each frame boundary. This lack has to +get corrected by external, "higher level" software which reads the same frame again and tries to find and eliminate overlapping chunks (24-byte-pieces). The transfer rate with reading audio (1-frame-pieces) is as slow as 32 kB/sec. -This could be better reading bigger chunks, but the "missing" chunks occur at -the beginning of each single frame. +This could be better reading bigger chunks, but the "missing" chunks possibly +occur at the beginning of each single frame. The software interface possibly may change a bit the day the SCSI driver supports it too. -With the CR-562 and CR-563 drives, MultiSession is supported. +With all but the CR-52x drives, MultiSession is supported. Photo CDs work (the "old" drives like CR-521 can access only the first session of a photoCD). At ftp.gwdg.de:/pub/linux/hpcdtoppm/ you will find Hadmut Danisch's package to convert photo CD image files and Gerd Knorr's viewing utility. -The transfer rate will reach 150 kB/sec with "old" drives and 300 kB/sec with -double-speed drives. XA (PhotoCD) disks with "old" drives give only 50 kB/sec. +The transfer rate will reach 150 kB/sec with "old" drives, 300 kB/sec with +double-speed drives, and about 500 kB/sec with quad speed drives. +XA (PhotoCD) disks with "old" drives give only 50 kB/sec. This release is part of the standard kernel and consists of - this README file @@ -138,6 +130,7 @@ If you configure "SBPRO" wrong, the playing of audio CDs will work, but you will not be able to mount a data CD. a2. Tell the address of your CDROM_PORT (not of the sound port). + a3. Set DISTRIBUTION to 0. b. Additionally for 2.a1 and 2.a2, the setup may be done during boot time (via the "kernel command line" or "LILO option"): sbpcd=0x230,SoundBlaster @@ -145,7 +138,6 @@ sbpcd=0x320,LaserMate or sbpcd=0x330,SPEA - (these strings are case sensitive!). This is especially useful if you install a fresh distribution. 2. "cd /usr/src/linux" and do a "make config" and select "y" for Matsushita CD-ROM support and for ISO9660 FileSystem support. If you do not have a @@ -198,11 +190,15 @@ "make config" of your kernel, you can build the "loadable module" sbpcd.o. Read /usr/src/linux/README.modules on this. -If sbpcd gets used as a module, the "audio copy" feature is disabled, and the -internal read-ahead buffer has a reduced size (the latter may affect throughput -a little bit under "slow" CPUs). Further, support of more than one interface +If sbpcd gets used as a module, the support of more than one interface card (i.e. drives 4...15) is disabled. +You can specify interface address and type with the "insmod" command like: + # insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x340,0 +or + # insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x230,1 +where the last number represents the SBPRO setting (no strings allowed here). + Things of interest: ------------------- @@ -215,7 +211,6 @@ To reduce or increase the amount of kernel messages, edit sbpcd.c and play with the "DBG_xxx" switches (initialization of the variable "sbpcd_debug"). -This is the way to get rid of the initial warning message block, too. The driver uses the "variable BLOCK_SIZE" feature. To use it, you have to specify "block=2048" as a mount option. Doing this will disable the direct @@ -229,120 +224,13 @@ At the beginning of sbpcd.c, you will find some "#define"s (f.e. EJECT and JUKEBOX). With that, you can configure the driver for some special things. -The following program disables the auto-eject feature during runtime: - -/*=================== begin program ========================================*/ -/* - * set the "eject" switch (enable/disable auto-ejecting) - * - * (c) 1994 Eberhard Moenkeberg - * may be used & enhanced freely - * - * Disables or enables the auto-eject feature at run time. - * Works only if a CD is in the drive (just like the feature itself ;-) - * Useful for a "quiet" shutdown or for weird audio player programs. - */ -#define EJECT 0 /* 0: disable, 1: enable auto-ejecting */ - -#include -#include -#include - -static char arg=EJECT; -static int drive; -static int err; - -main(int argc, char *argv[]) -{ -/* - * open /dev/cdrom - */ - drive=open("/dev/cdrom", 0); - if (drive<0) - { - fprintf(stderr, "can't open drive /dev/cdrom.\n"); - exit (-1); - } -/* - * set EJECT_SW - */ - err=ioctl(drive, CDROMEJECT_SW, arg); - if (err!=0) - { - fprintf(stderr, "can't set EJECT_SW (error %d).\n", err); - exit (-1); - } - else - fprintf(stdout, "EJECT_SW set to %d\n", arg); -} -/*===================== end program ========================================*/ - -Jeff Tranter's "eject" utility can do this, too (and more) for you. +You can use the appended program "cdtester" to set the auto-eject feature +during runtime. Jeff Tranter's "eject" utility can do this, too (and more) +for you. There is a new ioctl CDROMMULTISESSION to obtain with a user program if the CD is an XA disk and - if it is - where the last session starts. The -following example illustrates how to call it: - -/*=================== begin program ========================================*/ -/* - * ask for multisession redirection info - * - * (c) 1994 Eberhard Moenkeberg - * may be used & enhanced freely - * - */ -#include -#include -#include - -static struct cdrom_multisession ms_info; -static int drive; -static int err; - -main(int argc, char *argv[]) -{ -/* - * open /dev/cdrom - */ - drive=open("/dev/cdrom", 0); - if (drive<0) - { - fprintf(stderr, "can't open drive /dev/cdrom.\n"); - exit (-1); - } -/* - * - */ - ms_info.addr_format=CDROM_LBA; - err=ioctl(drive, CDROMMULTISESSION, &ms_info); - if (err!=0) - { - fprintf(stderr, "CDROMMULTISESSION(lba) returns error %d.\n", err); - exit (-1); - } - else - if (ms_info.xa_flag) - fprintf(stdout, "lba: %d\n", ms_info.addr.lba); - else - fprintf(stdout, "not an XA disk.\n"); - - ms_info.addr_format=CDROM_MSF; - err=ioctl(drive, CDROMMULTISESSION, &ms_info); - if (err!=0) - { - fprintf(stderr, "CDROMMULTISESSION(msf) returns error %d.\n", err); - exit (-1); - } - else - if (ms_info.xa_flag) - fprintf(stdout, "msf: %02d:%02d:%02d\n", - ms_info.addr.msf.minute, - ms_info.addr.msf.second, - ms_info.addr.msf.frame); - else - fprintf(stdout, "not an XA disk.\n"); -} -/*===================== end program ========================================*/ +"cdtester" program illustrates how to call it. Auto-probing at boot time: @@ -354,7 +242,8 @@ SBPCD's auto-probing happens before the initialization of the net drivers. Those "hazardous" addresses are excluded from auto-probing; the "kernel command line" feature has to be used during installation if you have your -drive at those addresses. +drive at those addresses. The "module" version is allowed to probe at those +addresses, too. The auto-probing looks first at the configured address resp. the address submitted by the kernel command line. With this, it is possible to use this @@ -382,7 +271,7 @@ without fearing NE2000 cards). To shorten the auto-probing list to a single entry, set DISTRIBUTION 0 within -sbpcd.c. +sbpcd.h. Setting up address and interface type: @@ -569,3 +458,537 @@ D-37083 Goettingen Germany --- + + +Appendix -- the "cdtester" utility: + +/* + * cdtester.c -- test the audio functions of a CD driver + * + * (c) 1995 Eberhard Moenkeberg + * published under the GPL + * + * made under heavy use of the "Tiny Audio CD Player" + * from Werner Zimmermann + * (see linux/drivers/block/README.aztcd) + */ +#undef AZT_PRIVATE_IOCTLS /* not supported by every CDROM driver */ +#define SBP_PRIVATE_IOCTLS /* not supported by every CDROM driver */ + +#include +#include +#include +#include +#include + +#ifdef AZT_PRIVATE_IOCTLS +#include +#endif AZT_PRIVATE_IOCTLS +#ifdef SBP_PRIVATE_IOCTLS +#include +#include +#endif SBP_PRIVATE_IOCTLS + +struct cdrom_tochdr hdr; +struct cdrom_tochdr tocHdr; +struct cdrom_tocentry TocEntry[101]; +struct cdrom_tocentry entry; +struct cdrom_multisession ms_info; +struct cdrom_read_audio read_audio; +struct cdrom_ti ti; +struct cdrom_subchnl subchnl; +struct cdrom_msf msf; +struct cdrom_volctrl volctrl; +#ifdef AZT_PRIVATE_IOCTLS +union +{ + struct cdrom_msf msf; + unsigned char buf[CD_FRAMESIZE_RAW]; +} azt; +#endif AZT_PRIVATE_IOCTLS +int i, i1, i2, i3, j, k; +unsigned char sequence=0; +unsigned char command[80]; +unsigned char first=1, last=1; +char *default_device="/dev/cdrom"; +char dev[20]; +char filename[20]; +int drive; +int datafile; +int rc; + +void help(void) +{ + printf("Available Commands:\n"); + printf("STOP s EJECT e QUIT q\n"); + printf("PLAY TRACK t PAUSE p RESUME r\n"); + printf("NEXT TRACK n REPEAT LAST l HELP h\n"); + printf("SUBCHANNEL_Q c TRACK INFO i PLAY AT a\n"); + printf("READ d READ RAW w READ AUDIO A\n"); + printf("MS-INFO M TOC T START S\n"); + printf("SET EJECTSW X DEVICE D DEBUG Y\n"); + printf("AUDIO_BUFSIZ Z RESET R BLKRASET B\n"); + printf("SET VOLUME v GET VOLUME V\n"); +} + +/* + * convert MSF number (3 bytes only) to Logical_Block_Address + */ +int msf2lba(u_char *msf) +{ + int i; + + i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_BLOCK_OFFSET; + if (i<0) return (0); + return (i); +} +/* + * convert logical_block_address to m-s-f_number (3 bytes only) + */ +void lba2msf(int lba, unsigned char *msf) +{ + lba += CD_BLOCK_OFFSET; + msf[0] = lba / (CD_SECS*CD_FRAMES); + lba %= CD_SECS*CD_FRAMES; + msf[1] = lba / CD_FRAMES; + msf[2] = lba % CD_FRAMES; +} + +int init_drive(char *dev) +{ + unsigned char msf_ent[3]; + + /* + * open the device + */ + drive=open(dev,0); + if (drive<0) return (-1); + /* + * get TocHeader + */ + printf("getting TocHeader...\n"); + rc=ioctl(drive,CDROMREADTOCHDR,&hdr); + if (rc!=0) + { + printf("can't get TocHeader (error %d).\n",rc); + return (-2); + } + else + first=hdr.cdth_trk0; + last=hdr.cdth_trk1; + printf("TocHeader: %d %d\n",hdr.cdth_trk0,hdr.cdth_trk1); + /* + * get and display all TocEntries + */ + printf("getting TocEntries...\n"); + for (i=1;i<=hdr.cdth_trk1+1;i++) + { + if (i!=hdr.cdth_trk1+1) TocEntry[i].cdte_track = i; + else TocEntry[i].cdte_track = CDROM_LEADOUT; + TocEntry[i].cdte_format = CDROM_LBA; + rc=ioctl(drive,CDROMREADTOCENTRY,&TocEntry[i]); + if (rc!=0) + { + printf("can't get TocEntry #%d (error %d).\n",i,rc); + } + else + { + lba2msf(TocEntry[i].cdte_addr.lba,&msf_ent[0]); + if (TocEntry[i].cdte_track==CDROM_LEADOUT) + { + printf("TocEntry #%02X: %1X %1X %02d:%02d:%02d (lba: 0x%06X) %02X\n", + TocEntry[i].cdte_track, + TocEntry[i].cdte_adr, + TocEntry[i].cdte_ctrl, + msf_ent[0], + msf_ent[1], + msf_ent[2], + TocEntry[i].cdte_addr.lba, + TocEntry[i].cdte_datamode); + } + else + { + printf("TocEntry #%02d: %1X %1X %02d:%02d:%02d (lba: 0x%06X) %02X\n", + TocEntry[i].cdte_track, + TocEntry[i].cdte_adr, + TocEntry[i].cdte_ctrl, + msf_ent[0], + msf_ent[1], + msf_ent[2], + TocEntry[i].cdte_addr.lba, + TocEntry[i].cdte_datamode); + } + } + } + return (hdr.cdth_trk1); /* number of tracks */ +} + +void display(int size,unsigned char *buffer) +{ + k=0; + getchar(); + for (i=0;i<(size+1)/16;i++) + { + printf("%4d:",i*16); + for (j=0;j<16;j++) + { + printf(" %02X",buffer[i*16+j]); + } + printf(" "); + for (j=0;j<16;j++) + { + if (isalnum(buffer[i*16+j])) + printf("%c",buffer[i*16+j]); + else + printf("."); + } + printf("\n"); + k++; + if (k>=20) + { + printf("press ENTER to continue\n"); + getchar(); + k=0; + } + } +} + +main(int argc, char *argv[]) +{ + printf("\nTesting tool for a CDROM driver's audio functions V0.1\n"); + printf("(C) 1995 Eberhard Moenkeberg \n"); + printf("initializing...\n"); + + rc=init_drive(default_device); + if (rc<0) printf("could not open %s (rc=%d).\n",default_device,rc); + help(); + while (1) + { + printf("Give a one-letter command (h = help): "); + scanf("%s",command); + command[1]=0; + switch (command[0]) + { + case 'D': + printf("device name (f.e. /dev/sbpcd3): ? "); + scanf("%s",&dev); + close(drive); + rc=init_drive(dev); + if (rc<0) printf("could not open %s (rc %d).\n",dev,rc); + break; + case 'e': + rc=ioctl(drive,CDROMEJECT); + if (rc<0) printf("CDROMEJECT: rc=%d.\n",rc); + break; + case 'p': + rc=ioctl(drive,CDROMPAUSE); + if (rc<0) printf("CDROMPAUSE: rc=%d.\n",rc); + break; + case 'r': + rc=ioctl(drive,CDROMRESUME); + if (rc<0) printf("CDROMRESUME: rc=%d.\n",rc); + break; + case 's': + rc=ioctl(drive,CDROMSTOP); + if (rc<0) printf("CDROMSTOP: rc=%d.\n",rc); + break; + case 'S': + rc=ioctl(drive,CDROMSTART); + if (rc<0) printf("CDROMSTART: rc=%d.\n",rc); + break; + case 't': + rc=ioctl(drive,CDROMREADTOCHDR,&tocHdr); + if (rc<0) + { + printf("CDROMREADTOCHDR: rc=%d.\n",rc); + break; + } + first=tocHdr.cdth_trk0; + last= tocHdr.cdth_trk1; + if ((first==0)||(first>last)) + { + printf ("--got invalid TOC data.\n"); + } + else + { + printf("--enter track number(first=%d, last=%d): ",first,last); + scanf("%d",&i1); + ti.cdti_trk0=i1; + if (ti.cdti_trk0last) ti.cdti_trk0=last; + ti.cdti_ind0=0; + ti.cdti_trk1=last; + ti.cdti_ind1=0; + rc=ioctl(drive,CDROMSTOP); + rc=ioctl(drive,CDROMPLAYTRKIND,&ti); + if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc); + } + break; + case 'n': + rc=ioctl(drive,CDROMSTOP); + if (++ti.cdti_trk0>last) ti.cdti_trk0=last; + ti.cdti_ind0=0; + ti.cdti_trk1=last; + ti.cdti_ind1=0; + rc=ioctl(drive,CDROMPLAYTRKIND,&ti); + if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc); + break; + case 'l': + rc=ioctl(drive,CDROMSTOP); + if (--ti.cdti_trk0last) entry.cdte_track=last; + entry.cdte_format=CDROM_MSF; + rc=ioctl(drive,CDROMREADTOCENTRY,&entry); + if (rc<0) printf("CDROMREADTOCENTRY: rc=%d.\n",rc); + else + { + printf("Mode %d Track, starts at %02d:%02d:%02d\n", + entry.cdte_adr, + entry.cdte_addr.msf.minute, + entry.cdte_addr.msf.second, + entry.cdte_addr.msf.frame); + } + break; + case 'a': + printf("Address (min:sec:frm) "); + scanf("%d:%d:%d",&i1,&i2,&i3); + msf.cdmsf_min0=i1; + msf.cdmsf_sec0=i2; + msf.cdmsf_frame0=i3; + if (msf.cdmsf_sec0>59) msf.cdmsf_sec0=59; + if (msf.cdmsf_frame0>74) msf.cdmsf_frame0=74; + lba2msf(TocEntry[last+1].cdte_addr.lba-1,&msf.cdmsf_min1); + rc=ioctl(drive,CDROMSTOP); + rc=ioctl(drive,CDROMPLAYMSF,&msf); + if (rc<0) printf("CDROMPLAYMSF: rc=%d.\n",rc); + break; +#ifdef AZT_PRIVATE_IOCTLS /*not supported by every CDROM driver*/ + case 'd': + printf("Address (min:sec:frm) "); + scanf("%d:%d:%d",&i1,&i2,&i3); + azt.msf.cdmsf_min0=i1; + azt.msf.cdmsf_sec0=i2; + azt.msf.cdmsf_frame0=i3; + if (azt.msf.cdmsf_sec0>59) azt.msf.cdmsf_sec0=59; + if (azt.msf.cdmsf_frame0>74) azt.msf.cdmsf_frame0=74; + rc=ioctl(drive,CDROMREADMODE1,&azt.msf); + if (rc<0) printf("CDROMREADMODE1: rc=%d.\n",rc); + else display(CD_FRAMESIZE,azt.buf); + break; + case 'w': + printf("Address (min:sec:frame) "); + scanf("%d:%d:%d",&i1,&i2,&i3); + azt.msf.cdmsf_min0=i1; + azt.msf.cdmsf_sec0=i2; + azt.msf.cdmsf_frame0=i3; + if (azt.msf.cdmsf_sec0>59) azt.msf.cdmsf_sec0=59; + if (azt.msf.cdmsf_frame0>74) azt.msf.cdmsf_frame0=74; + rc=ioctl(drive,CDROMREADMODE2,&azt.msf); + if (rc<0) printf("CDROMREADMODE2: rc=%d.\n",rc); + else display(CD_FRAMESIZE_RAW,azt.buf); /* currently only 2336 */ + break; +#endif + case 'v': + printf("--Channel 0 (Left) (0-255): "); + scanf("%d",&i1); + volctrl.channel0=i1; + printf("--Channel 1 (Right) (0-255): "); + scanf("%d",&i1); + volctrl.channel1=i1; + volctrl.channel2=0; + volctrl.channel3=0; + rc=ioctl(drive,CDROMVOLCTRL,&volctrl); + if (rc<0) printf("CDROMVOLCTRL: rc=%d.\n",rc); + break; + case 'q': + close(drive); + exit(0); + case 'h': + help(); + break; + case 'T': /* display TOC entry - without involving the driver */ + scanf("%d",&i); + if ((ihdr.cdth_trk1)) + printf("invalid track number.\n"); + else + printf("TocEntry %02d: adr=%01X ctrl=%01X msf=%02d:%02d:%02d mode=%02X\n", + TocEntry[i].cdte_track, + TocEntry[i].cdte_adr, + TocEntry[i].cdte_ctrl, + TocEntry[i].cdte_addr.msf.minute, + TocEntry[i].cdte_addr.msf.second, + TocEntry[i].cdte_addr.msf.frame, + TocEntry[i].cdte_datamode); + break; + case 'A': /* read audio data into file */ + printf("Address (min:sec:frm) ? "); + scanf("%d:%d:%d",&i1,&i2,&i3); + read_audio.addr.msf.minute=i1; + read_audio.addr.msf.second=i2; + read_audio.addr.msf.frame=i3; + read_audio.addr_format=CDROM_MSF; + printf("# of frames ? "); + scanf("%d",&i1); + read_audio.nframes=i1; + k=read_audio.nframes*CD_FRAMESIZE_RAW; + read_audio.buf=malloc(k); + if (read_audio.buf==NULL) + { + printf("can't malloc %d bytes.\n",k); + break; + } + sprintf(filename,"audio_%02d%02d%02d_%02d.%02d\0", + read_audio.addr.msf.minute, + read_audio.addr.msf.second, + read_audio.addr.msf.frame, + read_audio.nframes, + ++sequence); + datafile=creat(filename, 0755); + if (datafile<0) + { + printf("can't open datafile %s.\n",filename); + break; + } + rc=ioctl(drive,CDROMREADAUDIO,&read_audio); + if (rc!=0) + { + printf("CDROMREADAUDIO: rc=%d.\n",rc); + } + else + { + rc=write(datafile,&read_audio.buf,k); + if (rc!=k) printf("datafile I/O error (%d).\n",rc); + } + close(datafile); + break; + case 'X': /* set EJECT_SW (0: disable, 1: enable auto-ejecting) */ + scanf("%d",&i); + rc=ioctl(drive,CDROMEJECT_SW,i); + if (rc!=0) + printf("CDROMEJECT_SW: rc=%d.\n",rc); + else + printf("EJECT_SW set to %d\n",i); + break; + case 'M': /* get the multisession redirection info */ + ms_info.addr_format=CDROM_LBA; + rc=ioctl(drive,CDROMMULTISESSION,&ms_info); + if (rc!=0) + { + printf("CDROMMULTISESSION(lba): rc=%d.\n",rc); + } + else + { + if (ms_info.xa_flag) printf("MultiSession offset (lba): %d (0x%06X)\n",ms_info.addr.lba,ms_info.addr.lba); + else + { + printf("this CD is not an XA disk.\n"); + break; + } + } + ms_info.addr_format=CDROM_MSF; + rc=ioctl(drive,CDROMMULTISESSION,&ms_info); + if (rc!=0) + { + printf("CDROMMULTISESSION(msf): rc=%d.\n",rc); + } + else + { + if (ms_info.xa_flag) + printf("MultiSession offset (msf): %02d:%02d:%02d (0x%02X%02X%02X)\n", + ms_info.addr.msf.minute, + ms_info.addr.msf.second, + ms_info.addr.msf.frame, + ms_info.addr.msf.minute, + ms_info.addr.msf.second, + ms_info.addr.msf.frame); + else printf("this CD is not an XA disk.\n"); + } + break; +#ifdef SBP_PRIVATE_IOCTLS + case 'Y': /* set the driver's message level */ +#if 0 /* not implemented yet */ + printf("enter switch name (f.e. DBG_CMD): "); + scanf("%s",&dbg_switch); + j=get_dbg_num(dbg_switch); +#else + printf("enter DDIOCSDBG switch number: "); + scanf("%d",&j); +#endif + printf("enter 0 for \"off\", 1 for \"on\": "); + scanf("%d",&i); + if (i==0) j|=0x80; + printf("calling \"ioctl(drive,DDIOCSDBG,%d)\"\n",j); + rc=ioctl(drive,DDIOCSDBG,j); + printf("DDIOCSDBG: rc=%d.\n",rc); + break; + case 'Z': /* set the audio buffer size */ + printf("# frames wanted: ? "); + scanf("%d",&j); + rc=ioctl(drive,CDROMAUDIOBUFSIZ,j); + printf("%d frames granted.\n",rc); + break; + case 'V': + rc=ioctl(drive,CDROMVOLREAD,&volctrl); + if (rc<0) printf("CDROMVOLCTRL: rc=%d.\n",rc); + printf("Volume: channel 0 (left) %d, channel 1 (right) %d\n",volctrl.channel0,volctrl.channel1); + break; + case 'R': + rc=ioctl(drive,CDROMRESET); + if (rc<0) printf("CDROMRESET: rc=%d.\n",rc); + break; + case 'B': /* set the driver's (?) read ahead value */ + printf("enter read-ahead size: ? "); + scanf("%d",&i); + rc=ioctl(drive,BLKRASET,i); + if (rc<0) printf("BLKRASET: rc=%d.\n",rc); + break; +#endif SBP_PRIVATE_IOCTLS + default: + printf("unknown command: \"%s\".\n",command); + break; + } + } +} +/*==========================================================================*/ +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ + diff -u --recursive --new-file v1.2.7/linux/drivers/block/sbpcd.c linux/drivers/block/sbpcd.c --- v1.2.7/linux/drivers/block/sbpcd.c Wed Mar 29 06:52:57 1995 +++ linux/drivers/block/sbpcd.c Tue May 2 07:26:00 1995 @@ -6,15 +6,12 @@ * Panasonic CI-101P. * Also for the Longshine LCS-7260 drive. * Also for the IBM "External ISA CD-Rom" drive. - * Still not for the CreativeLabs CD200 drive (but should work soon). - * Not for the TEAC CD-55A drive (separate project now). + * Also for the CreativeLabs CD200 drive (but I still need some + * detailed bug reports). + * Also for the TEAC CD-55A drive. * Not for Funai or Sanyo drives. * - * NOTE: This is release 3.4. - * It works with my SbPro & drive CR-521 V2.11 from 2/92 - * and with the CR-562-B V0.75 on a "naked" Panasonic - * CI-101P interface. And vice versa. - * + * NOTE: This is release 3.6. * * VERSION HISTORY * @@ -31,8 +28,8 @@ * * 0.4 use MAJOR 25 definitely. * Almost total re-design to support double-speed drives and - * "naked" (no sound) interface cards. - * Flow control should be exact now (tell me if not). + * "naked" (no sound) interface cards ("LaserMate" interface type). + * Flow control should be exact now. * Don't occupy the SbPro IRQ line (not needed either); will * live together with Hannu Savolainen's sndkit now. * Speeded up data transfer to 150 kB/sec, with help from Kai @@ -55,12 +52,12 @@ * Formal redesign to add DDI debugging. * There are still flaws in IOCTL (workman with double speed drive). * - * 1.0 Added support for all drive ids (0...3, no longer only 0) + * 1.0 Added support for all drive IDs (0...3, no longer only 0) * and up to 4 drives on one controller. * Added "#define MANY_SESSION" for "old" multi session CDs. * * 1.1 Do SpinUp for new drives, too. - * Revised for clean compile under "old" kernels (pl9). + * Revised for clean compile under "old" kernels (0.99pl9). * * 1.2 Found the "workman with double-speed drive" bug: use the driver's * audio_state, not what the drive is reporting with ReadSubQ. @@ -68,8 +65,8 @@ * 1.3 Minor cleanups. * Refinements regarding Workman. * - * 1.4 Read XA disks (PhotoCDs) with "old" drives, too (but possibly only - * the first session - I could not try a "multi-session" CD yet). + * 1.4 Read XA disks (PhotoCDs) with "old" drives, too (but only the first + * session - no chance to fully access a "multi-session" CD). * This currently still is too slow (50 kB/sec) - but possibly * the old drives won't do it faster. * Implemented "door (un)lock" for new drives (still does not work @@ -123,7 +120,7 @@ * Implemented "close tray" (done automatically during open). * * 2.4 Use different names for device registering. - * + * * 2.5 Added "#if EJECT" code (default: enabled) to automatically eject * the tray during last call to "sbpcd_release". * Added "#if JUKEBOX" code (default: disabled) to automatically eject @@ -132,11 +129,11 @@ * SOUND_BASE (in sbpcd.h) accordingly (default: disabled). * * 2.6 Nothing new. - * + * * 2.7 Added CDROMEJECT_SW ioctl to set the "EJECT" behavior on the fly: * 0 disables, 1 enables auto-ejecting. Useful to keep the tray in * during shutdown. - * + * * 2.8 Added first support (still BETA, I need feedback or a drive) for * the Longshine LCS-7260 drives. They appear as double-speed drives * using the "old" command scheme, extended by tray control and door @@ -148,8 +145,8 @@ * 16..20). * Changed default of the "JUKEBOX" define. If you use this default, * your tray will eject if you try to mount without a disk in. Next - * mount command will insert the tray - so, just insert a disk. ;-) - * + * mount command will insert the tray - so, just fill in a disk. ;-) + * * 2.9 Fulfilled the Longshine LCS-7260 support; with great help and * experiments by Serge Robyns. * First attempts to support the TEAC CD-55A drives; but still not @@ -176,10 +173,10 @@ * jumpered drive ID. This implies modifications to the /dev/sbpcd* * entries for some people, but will help the DAU (german TLA, english: * "newbie", maybe ;-) to install his "first" system from a CD. - * + * * 3.2 Still testing with CD200 and CD-55A drives. * - * 3.3 Working with CD200 support. Maybe a simple read is already possible. + * 3.3 Working with CD200 support. * * 3.4 Auto-probing stops if an address of 0 is seen (to be entered with * the kernel command line). @@ -187,20 +184,40 @@ * disabled, and the internal read ahead data buffer has a reduced size * of 4 kB; so, throughput may be reduced a little bit with slow CPUs. * + * 3.5 Provisions to handle weird photoCDs which have an interrupted + * "formatting" immediately after the last frames of some files: simply + * never "read ahead" with MultiSession CDs. By this, CPU usage may be + * increased with those CDs, and there may be a loss in speed. + * Re-structured the messaging system. + * The "loadable" version no longer has a limited READ_AUDIO buffer + * size. + * Removed "MANY_SESSION" handling for "old" multi session CDs. + * Added "private" IOCTLs CDROMRESET and CDROMVOLREAD. + * Started again to support the TEAC CD-55A drives, now that I found + * the money for "my own" drive. ;-) + * The TEAC CD-55A support is fairly working now. + * I have measured that the drive "delivers" at 600 kB/sec (even with + * bigger requests than the drive's 64 kB buffer can satisfy), but + * the "real" rate does not exceed 520 kB/sec at the moment. + * Caused by the various changes to build in TEAC support, the timed + * loops are de-optimized at the moment (less throughput with CR-52x + * drives, and the TEAC will give speed only with SBP_BUFFER_FRAMES 64). + * + * 3.6 Fixed TEAC data read problems with SbPro interfaces. + * Initial size of the READ_AUDIO buffer is 0. Can get set to any size + * during runtime. + * * TODO * * disk change detection * allow & synchronize multi-activity * (data + audio + ioctl + disk change, multiple drives) - * implement multi-controller-support with a single driver * implement "read all subchannel data" (96 bytes per frame) * - * * special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine * elaborated speed-up experiments (and the fabulous results!), for * the "push" towards load-free wait loops, and for the extensive mail * thread which brought additional hints and bug fixes. - * * * Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg * @@ -232,10 +249,12 @@ #ifdef MODULE #include #include -#include #ifndef CONFIG_MODVERSIONS char kernel_version[]=UTS_RELEASE; #endif +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT #endif MODULE #include @@ -247,12 +266,12 @@ #include #include #include -#include #include #include #include #include #include +#include #if !(SBPCD_ISSUE-1) #define MAJOR_NR MATSUSHITA_CDROM_MAJOR @@ -267,38 +286,9 @@ #define MAJOR_NR MATSUSHITA_CDROM4_MAJOR /* fourth driver issue */ #endif -#ifdef MODULE -#include "/usr/src/linux/drivers/block/blk.h" -#else #include "blk.h" -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif MODULE - -#define VERSION "3.4 Eberhard Moenkeberg " - -/* - * - */ -#define READ_AUDIO 4 /* max. number of audio frames to read with one */ - /* request (allocates n* 2352 bytes kernel memory!) */ -#define JUKEBOX 1 /* tray control: eject tray if no disk is in */ -#define EJECT 1 /* tray control: eject tray after last use */ -#define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */ -#define MANY_SESSION 0 /* this will conflict with "true" multi-session! */ -#undef FUTURE -#define WORKMAN 1 /* some testing stuff to make it better */ -#define CDMKE /* makes timing independent of processor speed */ - -#undef XA_TEST1 -#define XA_TEST2 - -#define TEST_UPC 0 -#define SPEA_TEST 0 -#define PRINTK_BUG 0 -#define TEST_STI 0 -#define DISTRIBUTION 1 /* I use it with a 0 here */ +#define VERSION "v3.6-1 Eberhard Moenkeberg " #if 0 #define INLINE @@ -328,11 +318,6 @@ #define SBPCD_INIT(a,b) sbpcd4_init(a,b) #endif /*==========================================================================*/ -#if MANY_SESSION -#undef LONG_TIMING -#define LONG_TIMING 1 -#endif -/*==========================================================================*/ #if SBPCD_DIS_IRQ #define SBPCD_CLI cli() #define SBPCD_STI sti() @@ -351,58 +336,58 @@ * The possibly conflicting ethernet card addresses get NOT probed * by default - to minimize the hang possibilities. * - * The SB Pro addresses get "mirrored" at 0x6xx - to avoid a type error, - * the 0x2xx-addresses must get checked before 0x6xx. + * The SB Pro addresses get "mirrored" at 0x6xx and some more locations - to + * avoid a type error, the 0x2xx-addresses must get checked before 0x6xx. * * send mail to emoenke@gwdg.de if your interface card is not FULLY * represented here. */ #if !(SBPCD_ISSUE-1) -static int sbpcd_probe[] = +static int sbpcd[] = { - CDROM_PORT, SBPRO, /* probe with user's setup first */ + CDROM_PORT, SBPRO, /* probe with user's setup first */ #if DISTRIBUTION - 0x230, 1, /* Soundblaster Pro and 16 (default) */ - 0x300, 0, /* CI-101P (default), WDH-7001C (default), - Galaxy (default), Reveal (one default) */ - 0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */ - 0x260, 1, /* OmniCD */ - 0x320, 0, /* Lasermate, CI-101P, WDH-7001C, Galaxy, Reveal (other default), - Longshine LCS-6853 (default) */ - 0x338, 0, /* Reveal Sound Wave 32 card model #SC600 */ - 0x340, 0, /* Mozart sound card (default), Lasermate, CI-101P */ - 0x360, 0, /* Lasermate, CI-101P */ - 0x270, 1, /* Soundblaster 16 */ - 0x670, 0, /* "sound card #9" */ - 0x690, 0, /* "sound card #9" */ - 0x330, 2, /* SPEA Media FX (default) */ - 0x320, 2, /* SPEA Media FX */ - 0x340, 2, /* SPEA Media FX */ - 0x634, 0, /* some newer sound cards */ - 0x638, 0, /* some newer sound cards */ -/* due to incomplete address decoding of the SbPro card, these must be last */ - 0x630, 0, /* "sound card #9" (default) */ - 0x650, 0, /* "sound card #9" */ + 0x230, 1, /* Soundblaster Pro and 16 (default) */ + 0x300, 0, /* CI-101P (default), WDH-7001C (default), + Galaxy (default), Reveal (one default) */ + 0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */ + 0x260, 1, /* OmniCD */ + 0x320, 0, /* Lasermate, CI-101P, WDH-7001C, Galaxy, Reveal (other default), + Longshine LCS-6853 (default) */ + 0x338, 0, /* Reveal Sound Wave 32 card model #SC600 */ + 0x340, 0, /* Mozart sound card (default), Lasermate, CI-101P */ + 0x360, 0, /* Lasermate, CI-101P */ + 0x270, 1, /* Soundblaster 16 */ + 0x670, 0, /* "sound card #9" */ + 0x690, 0, /* "sound card #9" */ + 0x330, 2, /* SPEA Media FX (default) */ + 0x320, 2, /* SPEA Media FX */ + 0x340, 2, /* SPEA Media FX */ + 0x634, 0, /* some newer sound cards */ + 0x638, 0, /* some newer sound cards */ + 0x230, 1, /* some newer sound cards */ + /* due to incomplete address decoding of the SbPro card, these must be last */ + 0x630, 0, /* "sound card #9" (default) */ + 0x650, 0, /* "sound card #9" */ #ifdef MODULE -/* - * some "hazardous" locations (no harm with the loadable version) - * (will stop the bus if a NE2000 ethernet card resides at offset -0x10) - */ - 0x330, 0, /* Lasermate, CI-101P, WDH-7001C */ - 0x350, 0, /* Lasermate, CI-101P */ - 0x350, 2, /* SPEA Media FX */ - 0x370, 0, /* Lasermate, CI-101P */ - 0x290, 1, /* Soundblaster 16 */ - 0x310, 0, /* Lasermate, CI-101P, WDH-7001C */ + /* + * some "hazardous" locations (no harm with the loadable version) + * (will stop the bus if a NE2000 ethernet card resides at offset -0x10) + */ + 0x330, 0, /* Lasermate, CI-101P, WDH-7001C */ + 0x350, 0, /* Lasermate, CI-101P */ + 0x350, 2, /* SPEA Media FX */ + 0x370, 0, /* Lasermate, CI-101P */ + 0x290, 1, /* Soundblaster 16 */ + 0x310, 0, /* Lasermate, CI-101P, WDH-7001C */ #endif MODULE #endif DISTRIBUTION }; #else -static int sbpcd_probe[] = {CDROM_PORT, SBPRO}; /* probe with user's setup only */ +static int sbpcd[] = {CDROM_PORT, SBPRO}; /* probe with user's setup only */ #endif -#define NUM_PROBE (sizeof(sbpcd_probe) / sizeof(int)) - +#define NUM_PROBE (sizeof(sbpcd) / sizeof(int)) /*==========================================================================*/ /* @@ -425,9 +410,15 @@ /* * the forward references: */ +static void sbp_sleep(u_int); +static void mark_timeout_delay(u_long); +static void mark_timeout_data(u_long); +#if 0 +static void mark_timeout_audio(u_long); +#endif static void sbp_read_cmd(void); static int sbp_data(void); -static int cmd_out(int); +static int cmd_out(void); static int DiskInfo(void); static int sbpcd_chk_disk_change(dev_t); @@ -445,11 +436,11 @@ * (1<99) msgnum=0; + sprintf(buf, "%s-%d [%02d]: ", major_name, d, msgnum); + va_start(args, fmt); + vsprintf(&buf[15], fmt, args); + va_end(args); + printk(buf); + sbp_sleep(55); /* else messages get lost */ + return; } - +/*==========================================================================*/ /* * DDI interface: runtime trace bit pattern maintenance */ static int sbpcd_dbg_ioctl(unsigned long arg, int level) { - int val; - - val = get_fs_long((int *) arg); - switch(val) - { - case 0: /* OFF */ - sbpcd_debug = 0; - break; - - default: - if (val >= 128) sbpcd_debug &= ~(1 << (val - 128)); - else sbpcd_debug |= (1 << val); - } - return(0); + switch(arg) + { + case 0: /* OFF */ + sbpcd_debug = DBG_INF; + break; + + default: + if (arg>=128) sbpcd_debug &= ~(1<<(arg-128)); + else sbpcd_debug |= (1<state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + jifs; - schedule(); - sti(); +#ifndef MODULE + if (current == task[0]) + { + del_timer(&delay_timer); + delay_timer.expires=time; + timed_out_delay=0; + add_timer(&delay_timer); + while (!timed_out_delay) ; + return; + } +#endif MODULE + sti(); + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + time; + schedule(); + sti(); } - -/*==========================================================================*/ /*==========================================================================*/ /* * convert logical_block_address to m-s-f_number (3 bytes only) */ static INLINE void lba2msf(int lba, u_char *msf) { - lba += CD_BLOCK_OFFSET; - msf[0] = lba / (CD_SECS*CD_FRAMES); - lba %= CD_SECS*CD_FRAMES; - msf[1] = lba / CD_FRAMES; - msf[2] = lba % CD_FRAMES; + lba += CD_BLOCK_OFFSET; + msf[0] = lba / (CD_SECS*CD_FRAMES); + lba %= CD_SECS*CD_FRAMES; + msf[1] = lba / CD_FRAMES; + msf[2] = lba % CD_FRAMES; } /*==========================================================================*/ /*==========================================================================*/ @@ -737,56 +781,56 @@ */ static INLINE void bin2bcdx(u_char *p) /* must work only up to 75 or 99 */ { - *p=((*p/10)<<4)|(*p%10); + *p=((*p/10)<<4)|(*p%10); } /*==========================================================================*/ static INLINE u_int blk2msf(u_int blk) { - MSF msf; - u_int mm; - - msf.c[3] = 0; - msf.c[2] = (blk + CD_BLOCK_OFFSET) / (CD_SECS * CD_FRAMES); - mm = (blk + CD_BLOCK_OFFSET) % (CD_SECS * CD_FRAMES); - msf.c[1] = mm / CD_FRAMES; - msf.c[0] = mm % CD_FRAMES; - return (msf.n); + MSF msf; + u_int mm; + + msf.c[3] = 0; + msf.c[2] = (blk + CD_BLOCK_OFFSET) / (CD_SECS * CD_FRAMES); + mm = (blk + CD_BLOCK_OFFSET) % (CD_SECS * CD_FRAMES); + msf.c[1] = mm / CD_FRAMES; + msf.c[0] = mm % CD_FRAMES; + return (msf.n); } /*==========================================================================*/ static INLINE u_int make16(u_char rh, u_char rl) { - return ((rh<<8)|rl); + return ((rh<<8)|rl); } /*==========================================================================*/ static INLINE u_int make32(u_int rh, u_int rl) { - return ((rh<<16)|rl); + return ((rh<<16)|rl); } /*==========================================================================*/ static INLINE u_char swap_nibbles(u_char i) { - return ((i<<4)|(i>>4)); + return ((i<<4)|(i>>4)); } /*==========================================================================*/ static INLINE u_char byt2bcd(u_char i) { - return (((i/10)<<4)+i%10); + return (((i/10)<<4)+i%10); } /*==========================================================================*/ static INLINE u_char bcd2bin(u_char bcd) { - return ((bcd>>4)*10+(bcd&0x0F)); + return ((bcd>>4)*10+(bcd&0x0F)); } /*==========================================================================*/ static INLINE int msf2blk(int msfx) { - MSF msf; - int i; - - msf.n=msfx; - i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_BLOCK_OFFSET; - if (i<0) return (0); - return (i); + MSF msf; + int i; + + msf.n=msfx; + i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_BLOCK_OFFSET; + if (i<0) return (0); + return (i); } /*==========================================================================*/ /* @@ -794,1869 +838,2578 @@ */ static INLINE int msf2lba(u_char *msf) { - int i; - - i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_BLOCK_OFFSET; - if (i<0) return (0); - return (i); + int i; + + i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_BLOCK_OFFSET; + if (i<0) return (0); + return (i); } /*==========================================================================*/ -/* evaluate xx_ReadError code (still mysterious) */ +/* evaluate cc_ReadError code */ static int sta2err(int sta) { - if (sta<=2) return (sta); - if (sta==0x05) return (-4); /* CRC error */ - if (sta==0x06) return (-6); /* seek error */ - if (sta==0x0d) return (-6); /* seek error */ - if (sta==0x0e) return (-3); /* unknown command */ - if (sta==0x14) return (-3); /* unknown command */ - if (sta==0x0c) return (-11); /* read fault */ - if (sta==0x0f) return (-11); /* read fault */ - if (sta==0x10) return (-11); /* read fault */ - if (sta>=0x16) return (-12); /* general failure */ - DriveStruct[d].CD_changed=0xFF; - if (sta==0x11) return (-15); /* invalid disk change (LCS: removed) */ - if (famL_drive) - if (sta==0x12) return (-15); /* invalid disk change (inserted) */ - return (-2); /* drive not ready */ + if (famT_drive) + { + if (sta==0x00) return (0); + if (sta==0x01) return (-604); /* CRC error */ + if (sta==0x02) return (-602); /* drive not ready */ + if (sta==0x03) return (-607); /* unknown media */ + if (sta==0x04) return (-612); /* general failure */ + if (sta==0x05) return (0); + if (sta==0x06) return (-615); /* invalid disk change */ + if (sta==0x0b) return (-612); /* general failure */ + if (sta==0xff) return (-612); /* general failure */ + return (0); + } + else + { + if (sta<=2) return (sta); + if (sta==0x05) return (-604); /* CRC error */ + if (sta==0x06) return (-606); /* seek error */ + if (sta==0x0d) return (-606); /* seek error */ + if (sta==0x0e) return (-603); /* unknown command */ + if (sta==0x14) return (-603); /* unknown command */ + if (sta==0x0c) return (-611); /* read fault */ + if (sta==0x0f) return (-611); /* read fault */ + if (sta==0x10) return (-611); /* read fault */ + if (sta>=0x16) return (-612); /* general failure */ + D_S[d].CD_changed=0xFF; + if (sta==0x11) return (-615); /* invalid disk change (LCS: removed) */ + if (famL_drive) + if (sta==0x12) return (-615); /* invalid disk change (inserted) */ + return (-602); /* drive not ready */ + } } /*==========================================================================*/ static INLINE void clr_cmdbuf(void) { - int i; - - for (i=0;i<10;i++) drvcmd[i]=0; - cmd_type=0; -} -/*==========================================================================*/ -static void mark_timeout(unsigned long i) -{ - timed_out=1; - DPRINTF((DBG_TIM,"SBPCD: timer expired.\n")); + int i; + + for (i=0;i<10;i++) drvcmd[i]=0; + cmd_type=0; } /*==========================================================================*/ -static struct timer_list delay_timer = { NULL, NULL, 0, 0, mark_timeout}; -#if 0 -static struct timer_list data_timer = { NULL, NULL, 0, 0, mark_timeout}; -static struct timer_list audio_timer = { NULL, NULL, 0, 0, mark_timeout}; -#endif -/*==========================================================================*/ static void flush_status(void) { -#ifdef CDMKE - int i; - + int i; + #ifdef MODULE - sbp_sleep(150); - for (i=maxtim_data;i!=0;i--) inb(CDi_status); + sbp_sleep(150); + for (i=maxtim_data;i!=0;i--) inb(CDi_status); #else - if (current == task[0]) - for (i=maxtim02;i!=0;i--) inb(CDi_status); - else - { - sbp_sleep(150); - for (i=maxtim_data;i!=0;i--) inb(CDi_status); - } + if (current == task[0]) + for (i=maxtim02;i!=0;i--) inb(CDi_status); + else + { + sbp_sleep(150); + for (i=maxtim_data;i!=0;i--) inb(CDi_status); + } #endif MODULE -#else - timed_out=0; -#if 0 - del_timer(&delay_timer); -#endif - delay_timer.expires = 150; - add_timer(&delay_timer); - do { } - while (!timed_out); -#if 0 - del_timer(&delay_timer); -#endif 0 - inb(CDi_status); -#endif CDMKE } /*==========================================================================*/ static int CDi_stat_loop(void) { - int i,j; - u_long timeout; - + int i,j; + #ifdef MODULE - for(timeout = jiffies + 1000, i=maxtim_data; timeout > jiffies; ) - { - for ( ;i!=0;i--) - { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) return (j); - if (!(j&s_not_result_ready)) return (j); - if (fam0L_drive) if (j&s_attention) return (j); - } - sbp_sleep(1); - i = 1; - } + for(timeout = jiffies + 1000, i=maxtim_data; timeout > jiffies; ) + { + for ( ;i!=0;i--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) return (j); + if (!(j&s_not_result_ready)) return (j); + if (fam0L_drive) if (j&s_attention) return (j); + } + sbp_sleep(1); + i = 1; + } #else - if (current == task[0]) - for(i=maxtim16;i!=0;i--) - { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) return (j); - if (!(j&s_not_result_ready)) return (j); - if (fam0L_drive) if (j&s_attention) return (j); - } - else - for(timeout = jiffies + 1000, i=maxtim_data; timeout > jiffies; ) - { - for ( ;i!=0;i--) - { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) return (j); - if (!(j&s_not_result_ready)) return (j); - if (fam0L_drive) if (j&s_attention) return (j); - } - sbp_sleep(1); - i = 1; - } + if (current == task[0]) + for(i=maxtim16;i!=0;i--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) return (j); + if (!(j&s_not_result_ready)) return (j); + if (fam0L_drive) if (j&s_attention) return (j); + } + else + for(timeout = jiffies + 1000, i=maxtim_data; timeout > jiffies; ) + { + for ( ;i!=0;i--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) return (j); + if (!(j&s_not_result_ready)) return (j); + if (fam0L_drive) if (j&s_attention) return (j); + } + sbp_sleep(1); + i = 1; + } #endif MODULE - DPRINTF((DBG_LCS,"SBPCD: CDi_stat_loop failed\n")); - return (-1); + msg(DBG_LCS,"CDi_stat_loop failed\n"); + return (-1); +} +/*==========================================================================*/ +#if 00000 +/*==========================================================================*/ +static int tst_DataReady(void) +{ + int i; + + i=inb(CDi_status); + if (i&s_not_data_ready) return (0); + return (1); +} +/*==========================================================================*/ +static int tst_ResultReady(void) +{ + int i; + + i=inb(CDi_status); + if (i&s_not_result_ready) return (0); + return (1); +} +/*==========================================================================*/ +static int tst_Attention(void) +{ + int i; + + i=inb(CDi_status); + if (i&s_attention) return (1); + return (0); } /*==========================================================================*/ +#endif 00000 +/*==========================================================================*/ static int ResponseInfo(void) { - int i,j, st=0; - u_long timeout; - - DPRINTF((DBG_000,"SBPCD: ResponseInfo entered.\n")); + int i,j,st=0; + u_long timeout; + #ifdef MODULE - for (i=0, timeout = jiffies + 100; i < response_count; i++) - { - for (j=maxtim_data; ; ) - { - for ( ;j!=0;j-- ) - { - st=inb(CDi_status); - if (!(st&s_not_result_ready)) break; - } - if (j != 0 || timeout <= jiffies) break; - sbp_sleep(0); - j = 1; - } - if (timeout <= jiffies) return (-1); - infobuf[i]=inb(CDi_info); - } + if (0) #else - if (current == task[0]) - for (i=0;i0) st=-st; + return (st); } /*==========================================================================*/ static void EvaluateStatus(int st) { - DriveStruct[d].status_byte=0; - if (fam0_drive) - { - if (st&p_caddin_old) DriveStruct[d].status_byte |= p_door_closed|p_caddy_in; - if (st&p_spinning) DriveStruct[d].status_byte |= p_spinning; - if (st&p_check) DriveStruct[d].status_byte |= p_check; - if (st&p_busy_old) DriveStruct[d].status_byte |= p_busy_new; - if (st&p_disk_ok) DriveStruct[d].status_byte |= p_disk_ok; - } - else if (famL_drive) - { - if (st&p_caddin_old) DriveStruct[d].status_byte |= p_disk_ok|p_caddy_in; - if (st&p_spinning) DriveStruct[d].status_byte |= p_spinning; - if (st&p_check) DriveStruct[d].status_byte |= p_check; - if (st&p_busy_old) DriveStruct[d].status_byte |= p_busy_new; - if (st&p_lcs_door_closed) DriveStruct[d].status_byte |= p_door_closed; - if (st&p_lcs_door_locked) DriveStruct[d].status_byte |= p_door_locked; - } - else if (fam2_drive) - { - if (st&p2_check) DriveStruct[d].status_byte |= p1_check; - if (st&p2_door_closed) DriveStruct[d].status_byte |= p1_door_closed; - if (st&p2_disk_in) DriveStruct[d].status_byte |= p1_disk_in; - if (st&p2_busy1) DriveStruct[d].status_byte |= p1_busy; - if (st&p2_busy2) DriveStruct[d].status_byte |= p1_busy; - if (st&p2_spinning) DriveStruct[d].status_byte |= p1_spinning; - if (st&p2_door_locked) DriveStruct[d].status_byte |= p1_door_locked; - if (st&p2_disk_ok) DriveStruct[d].status_byte |= p1_disk_ok; - } - else if (fam1_drive) DriveStruct[d].status_byte=st; - return; + D_S[d].status_bits=0; + if (fam1_drive) D_S[d].status_bits=st|p_success; + else if (fam0_drive) + { + if (st&p_caddin_old) D_S[d].status_bits |= p_door_closed|p_caddy_in; + if (st&p_spinning) D_S[d].status_bits |= p_spinning; + if (st&p_check) D_S[d].status_bits |= p_check; + if (st&p_success_old) D_S[d].status_bits |= p_success; + if (st&p_busy_old) D_S[d].status_bits |= p_busy_new; + if (st&p_disk_ok) D_S[d].status_bits |= p_disk_ok; + } + else if (famL_drive) + { + D_S[d].status_bits |= p_success; + if (st&p_caddin_old) D_S[d].status_bits |= p_disk_ok|p_caddy_in; + if (st&p_spinning) D_S[d].status_bits |= p_spinning; + if (st&p_check) D_S[d].status_bits |= p_check; + if (st&p_busy_old) D_S[d].status_bits |= p_busy_new; + if (st&p_lcs_door_closed) D_S[d].status_bits |= p_door_closed; + if (st&p_lcs_door_locked) D_S[d].status_bits |= p_door_locked; + } + else if (fam2_drive) + { + D_S[d].status_bits |= p_success; + if (st&p2_check) D_S[d].status_bits |= p1_check; + if (st&p2_door_closed) D_S[d].status_bits |= p1_door_closed; + if (st&p2_disk_in) D_S[d].status_bits |= p1_disk_in; + if (st&p2_busy1) D_S[d].status_bits |= p1_busy; + if (st&p2_busy2) D_S[d].status_bits |= p1_busy; + if (st&p2_spinning) D_S[d].status_bits |= p1_spinning; + if (st&p2_door_locked) D_S[d].status_bits |= p1_door_locked; + if (st&p2_disk_ok) D_S[d].status_bits |= p1_disk_ok; + } + else if (famT_drive) + { + return; /* still needs to get coded */ + D_S[d].status_bits |= p_success; + if (st&p2_check) D_S[d].status_bits |= p1_check; + if (st&p2_door_closed) D_S[d].status_bits |= p1_door_closed; + if (st&p2_disk_in) D_S[d].status_bits |= p1_disk_in; + if (st&p2_busy1) D_S[d].status_bits |= p1_busy; + if (st&p2_busy2) D_S[d].status_bits |= p1_busy; + if (st&p2_spinning) D_S[d].status_bits |= p1_spinning; + if (st&p2_door_locked) D_S[d].status_bits |= p1_door_locked; + if (st&p2_disk_ok) D_S[d].status_bits |= p1_disk_ok; + } + return; +} +/*==========================================================================*/ +static int get_state_T(void) +{ + int i; + + static int cmd_out_T(void); + + msg(DBG_TE2,"doing get_state_T...\n"); + clr_cmdbuf(); + D_S[d].n_bytes=1; + drvcmd[0]=CMDT_STATUS; + i=cmd_out_T(); + if (i>=0) i=infobuf[0]; + else + { + msg(DBG_TEA,"get_state_T error %d\n", i); + return (i); + } + if (i>=0) + /* 2: closed, disk in */ + D_S[d].status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok; + else if (D_S[d].error_state==6) + /* 3: closed, disk in, changed ("06 xx xx") */ + D_S[d].status_bits=p1_door_closed|p1_disk_in; + else if ((D_S[d].error_state!=2)||(D_S[d].b3!=0x3A)||(D_S[d].b4==0x00)) + { + /* 1: closed, no disk ("xx yy zz"or "02 3A 00") */ + D_S[d].status_bits=p1_door_closed; + D_S[d].open_count=0; + } + else if (D_S[d].b4==0x01) + { + /* 0: open ("02 3A 01") */ + D_S[d].status_bits=0; + D_S[d].open_count=0; + } + else + { + /* 1: closed, no disk ("02 3A xx") */ + D_S[d].status_bits=p1_door_closed; + D_S[d].open_count=0; + } + msg(DBG_TE2,"get_state_T done (%02X)...\n", D_S[d].status_bits); + return (D_S[d].status_bits); } /*==========================================================================*/ static int ResponseStatus(void) { - int i,j; - u_long timeout; - - DPRINTF((DBG_STA,"SBPCD: doing ResponseStatus...\n")); + int i,j; + u_long timeout; + + msg(DBG_STA,"doing ResponseStatus...\n"); + if (famT_drive) return (get_state_T()); #ifdef MODULE - if (flags_cmd_out & f_respo3) timeout = jiffies; - else if (flags_cmd_out & f_respo2) timeout = jiffies + 1600; - else timeout = jiffies + 400; - j=maxtim_8; - do - { - for ( ;j!=0;j--) - { - i=inb(CDi_status); - if (!(i&s_not_result_ready)) break; - } - if (j != 0 || timeout <= jiffies) break; - sbp_sleep(0); - j = 1; - } - while (1); + if (0) #else - if (current == task[0]) - { - if (flags_cmd_out & f_respo3) j = maxtim_8; - else if (flags_cmd_out&f_respo2) j=maxtim16; - else j=maxtim04; - for (;j!=0;j--) + if (current == task[0]) +#endif MODULE { - i=inb(CDi_status); - if (!(i&s_not_result_ready)) break; + if (flags_cmd_out & f_respo3) j = maxtim_8; + else if (flags_cmd_out&f_respo2) j=maxtim16; + else j=maxtim04; + for (;j!=0;j--) + { + i=inb(CDi_status); + if (!(i&s_not_result_ready)) break; + } } - } - else - { - if (flags_cmd_out & f_respo3) timeout = jiffies; - else if (flags_cmd_out & f_respo2) timeout = jiffies + 1600; - else timeout = jiffies + 400; - j=maxtim_8; - do - { - for ( ;j!=0;j--) - { - i=inb(CDi_status); - if (!(i&s_not_result_ready)) break; - } - if (j != 0 || timeout <= jiffies) break; - sbp_sleep(0); - j = 1; + else + { + if (flags_cmd_out & f_respo3) timeout = jiffies; + else if (flags_cmd_out & f_respo2) timeout = jiffies + 1600; + else timeout = jiffies + 400; + j=maxtim_8; + do + { + for ( ;j!=0;j--) + { + i=inb(CDi_status); + if (!(i&s_not_result_ready)) break; + } + if ((j!=0)||(timeout0;ntries--) + { + if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(100); +#if 1 + OUT(CDo_sel_i_d,0); +#endif + i=inb(CDi_status); + if (!(i&s_not_data_ready)) /* f.e. CMDT_DISKINFO */ + { + OUT(CDo_sel_i_d,1); + if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */ + if (drvcmd[0]==CMDT_DISKINFO) + { + l=0; + do + { + infobuf[l++]=inb(CDi_data); + i=inb(CDi_status); + } + while (!(i&s_not_data_ready)); + for (j=0;j1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (%02X): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", drvcmd[0], recursion); + clr_cmdbuf(); + drvcmd[0]=CMDT_READ_ERR; + j=cmd_out_T(); /* !!! recursive here !!! */ + --recursion; + sbp_sleep(1); + } + while (j<0); + D_S[d].error_state=infobuf[2]; + D_S[d].b3=infobuf[3]; + D_S[d].b4=infobuf[4]; + if (D_S[d].f_drv_error) + { + D_S[d].f_drv_error=0; + cc_DriveReset(); + D_S[d].error_state=2; + } + return (-D_S[d].error_state-400); + } + if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */ + sbp_sleep(1); + if (ntries>(CMDT_TRIES-50)) continue; + msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1); + } + D_S[d].f_drv_error=1; + cc_DriveReset(); + D_S[d].error_state=2; + return (-99); +} +/*==========================================================================*/ +static int cmd_out(void) +{ + int i=0; + + if (famT_drive) return(cmd_out_T()); + + if (flags_cmd_out&f_putcmd) + { + for (i=0;i<7;i++) + sprintf(&msgbuf[i*3], " %02X", drvcmd[i]); + msgbuf[i*3]=0; + msg(DBG_CMD,"cmd_out:%s\n", msgbuf); + cli(); + for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]); + sti(); } - else i=ResponseInfo(); - if (i<0) return (-9); - } - if (DriveStruct[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to CDi_stat_loop.\n")); - if (flags_cmd_out&f_lopsta) - { - i=CDi_stat_loop(); - if ((i<0)||!(i&s_attention)) return (-9); - } - if (!(flags_cmd_out&f_getsta)) goto LOC_229; - -LOC_228: - if (DriveStruct[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to xx_ReadStatus.\n")); - xx_ReadStatus(); - -LOC_229: - if (flags_cmd_out&f_ResponseStatus) - { - if (DriveStruct[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to ResponseStatus.\n")); - i=ResponseStatus(); - /* builds status_byte, returns orig. status or p_busy_new */ - if (i<0) return (-9); - if (flags_cmd_out&(f_bit1|f_wait_if_busy)) - { - if (!st_check) - { - if (flags_cmd_out&f_bit1) if (i&p_success_old) goto LOC_232; - if (!(flags_cmd_out&f_wait_if_busy)) goto LOC_228; - if (!st_busy) goto LOC_228; - } + if (response_count!=0) + { + if (cmd_type!=0) + { + if (sbpro_type==1) OUT(CDo_sel_i_d,1); + msg(DBG_INF,"misleaded to try ResponseData.\n"); + if (sbpro_type==1) OUT(CDo_sel_i_d,0); + return (-22); + } + else i=ResponseInfo(); + if (i<0) return (i); } - } -LOC_232: - if (!(flags_cmd_out&f_obey_p_check)) return (0); - if (!st_check) return (0); - if (DriveStruct[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to xx_ReadError.\n")); - i=xx_ReadError(); - if (DriveStruct[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to cmd_out OK.\n")); - return (i); -} -/*==========================================================================*/ -static int xx_Seek(u_int pos, char f_blk_msf) -{ - int i; - - clr_cmdbuf(); - if (f_blk_msf>1) return (-3); - if (fam0_drive) - { - drvcmd[0]=CMD0_SEEK; - if (f_blk_msf==1) pos=msf2blk(pos); - drvcmd[2]=(pos>>16)&0x00FF; - drvcmd[3]=(pos>>8)&0x00FF; - drvcmd[4]=pos&0x00FF; - flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | - f_ResponseStatus | f_obey_p_check | f_bit1; - } - else if (fam1L_drive) - { - drvcmd[0]=CMD1_SEEK; /* same as CMD1_ and CMDL_ */ - if (f_blk_msf==0) pos=blk2msf(pos); - drvcmd[1]=(pos>>16)&0x00FF; - drvcmd[2]=(pos>>8)&0x00FF; - drvcmd[3]=pos&0x00FF; - if (famL_drive) - flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; - else - flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_SEEK; - if (f_blk_msf==0) pos=blk2msf(pos); - drvcmd[2]=(pos>>16)&0x00FF; - drvcmd[3]=(pos>>16)&0x00FF; - drvcmd[4]=(pos>>8)&0x00FF; - drvcmd[5]=pos&0x00FF; - flags_cmd_out=f_putcmd|f_ResponseStatus; - } - response_count=0; - i=cmd_out(7); - return (i); -} -/*==========================================================================*/ -static int xx_SpinUp(void) -{ - int i; - - DPRINTF((DBG_SPI,"SBPCD: SpinUp.\n")); - DriveStruct[d].in_SpinUp = 1; - clr_cmdbuf(); - if (fam0L_drive) - { - drvcmd[0]=CMD0_SPINUP; - flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta| - f_ResponseStatus|f_obey_p_check|f_bit1; - } - else if (fam1_drive) - { - drvcmd[0]=CMD1_SPINUP; - flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_TRAY_CTL; - drvcmd[4]=0x01; - flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; - } - response_count=0; - i=cmd_out(7); - DriveStruct[d].in_SpinUp = 0; - return (i); -} -/*==========================================================================*/ -static int yy_SpinDown(void) -{ - int i; - - if (fam0_drive) return (-3); - clr_cmdbuf(); - response_count=0; - if (fam1_drive) - { - drvcmd[0]=CMD1_SPINDOWN; - flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_TRAY_CTL; - drvcmd[4]=0x02; /* "eject" */ - flags_cmd_out=f_putcmd|f_ResponseStatus; - } - else if (famL_drive) - { - drvcmd[0]=CMDL_SPINDOWN; - drvcmd[1]=1; - flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; - } - i=cmd_out(7); - return (i); + if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n"); + if (flags_cmd_out&f_lopsta) + { + i=CDi_stat_loop(); + if ((i<0)||!(i&s_attention)) return (-8); + } + if (!(flags_cmd_out&f_getsta)) goto LOC_229; + + LOC_228: + if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n"); + cc_ReadStatus(); + + LOC_229: + if (flags_cmd_out&f_ResponseStatus) + { + if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n"); + i=ResponseStatus(); + /* builds status_bits, returns orig. status or p_busy_new */ + if (i<0) return (-9); + if (flags_cmd_out&(f_bit1|f_wait_if_busy)) + { + if (!st_check) + { + if ((flags_cmd_out&f_bit1)&&(i&p_success)) goto LOC_232; + if ((!(flags_cmd_out&f_wait_if_busy))||(!st_busy)) goto LOC_228; + } + } + } + LOC_232: + if (!(flags_cmd_out&f_obey_p_check)) return (0); + if (!st_check) return (0); + if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n"); + i=cc_ReadError(); + if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n"); + msg(DBG_000,"cmd_out: cc_ReadError=%d\n", i); + return (i); } /*==========================================================================*/ -static int yy_SetSpeed(u_char speed, u_char x1, u_char x2) +static int cc_Seek(u_int pos, char f_blk_msf) { - int i; - - if (fam0L_drive) return (-3); + int i; + clr_cmdbuf(); - response_count=0; - if (fam1_drive) - { - drvcmd[0]=CMD1_SETMODE; - drvcmd[1]=0x03; - drvcmd[2]=speed; - drvcmd[3]=x1; - drvcmd[4]=x2; - flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_SETSPEED; - if (speed&speed_auto) + if (f_blk_msf>1) return (-3); + if (fam0_drive) { - drvcmd[2]=0xFF; - drvcmd[3]=0xFF; + drvcmd[0]=CMD0_SEEK; + if (f_blk_msf==1) pos=msf2blk(pos); + drvcmd[2]=(pos>>16)&0x00FF; + drvcmd[3]=(pos>>8)&0x00FF; + drvcmd[4]=pos&0x00FF; + flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | + f_ResponseStatus | f_obey_p_check | f_bit1; + } + else if (fam1L_drive) + { + drvcmd[0]=CMD1_SEEK; /* same as CMD1_ and CMDL_ */ + if (f_blk_msf==0) pos=blk2msf(pos); + drvcmd[1]=(pos>>16)&0x00FF; + drvcmd[2]=(pos>>8)&0x00FF; + drvcmd[3]=pos&0x00FF; + if (famL_drive) + flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; + else + flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; + } + else if (fam2_drive) + { + drvcmd[0]=CMD2_SEEK; + if (f_blk_msf==0) pos=blk2msf(pos); + drvcmd[2]=(pos>>24)&0x00FF; + drvcmd[3]=(pos>>16)&0x00FF; + drvcmd[4]=(pos>>8)&0x00FF; + drvcmd[5]=pos&0x00FF; + flags_cmd_out=f_putcmd|f_ResponseStatus; + } + else if (famT_drive) + { + drvcmd[0]=CMDT_SEEK; + if (f_blk_msf==1) pos=msf2blk(pos); + drvcmd[2]=(pos>>24)&0x00FF; + drvcmd[3]=(pos>>16)&0x00FF; + drvcmd[4]=(pos>>8)&0x00FF; + drvcmd[5]=pos&0x00FF; + D_S[d].n_bytes=1; + } + response_count=0; + i=cmd_out(); + return (i); +} +/*==========================================================================*/ +static int cc_SpinUp(void) +{ + int i; + + msg(DBG_SPI,"SpinUp.\n"); + D_S[d].in_SpinUp = 1; + clr_cmdbuf(); + if (fam0L_drive) + { + drvcmd[0]=CMD0_SPINUP; + flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta| + f_ResponseStatus|f_obey_p_check|f_bit1; + } + else if (fam1_drive) + { + drvcmd[0]=CMD1_SPINUP; + flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; + } + else if (fam2_drive) + { + drvcmd[0]=CMD2_TRAY_CTL; + drvcmd[4]=0x01; /* "spinup" */ + flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; + } + else if (famT_drive) + { + drvcmd[0]=CMDT_TRAY_CTL; + drvcmd[4]=0x03; /* "insert", it hopefully spins the drive up */ + } + response_count=0; + i=cmd_out(); + D_S[d].in_SpinUp = 0; + return (i); +} +/*==========================================================================*/ +static int cc_SpinDown(void) +{ + int i; + + if (fam0_drive) return (0); + clr_cmdbuf(); + response_count=0; + if (fam1_drive) + { + drvcmd[0]=CMD1_SPINDOWN; + flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; + } + else if (fam2_drive) + { + drvcmd[0]=CMD2_TRAY_CTL; + drvcmd[4]=0x02; /* "eject" */ + flags_cmd_out=f_putcmd|f_ResponseStatus; + } + else if (famL_drive) + { + drvcmd[0]=CMDL_SPINDOWN; + drvcmd[1]=1; + flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; + } + else if (famT_drive) + { + drvcmd[0]=CMDT_TRAY_CTL; + drvcmd[4]=0x02; /* "eject" */ + } + i=cmd_out(); + return (i); +} +/*==========================================================================*/ +static int cc_get_mode_T(void) +{ + int i; + + clr_cmdbuf(); + response_count=10; + drvcmd[0]=CMDT_GETMODE; + drvcmd[4]=response_count; + i=cmd_out_T(); + return (i); +} +/*==========================================================================*/ +static int cc_set_mode_T(void) +{ + int i; + + clr_cmdbuf(); + response_count=1; + drvcmd[0]=CMDT_SETMODE; + drvcmd[1]=D_S[d].speed_byte; + drvcmd[2]=D_S[d].frmsiz>>8; + drvcmd[3]=D_S[d].frmsiz&0x0FF; + drvcmd[4]=D_S[d].f_XA; /* 1: XA */ + drvcmd[5]=D_S[d].type_byte; /* 0, 1, 3 */ + drvcmd[6]=D_S[d].mode_xb_6; + drvcmd[7]=D_S[d].mode_yb_7|D_S[d].volume_control; + drvcmd[8]=D_S[d].mode_xb_8; + drvcmd[9]=D_S[d].delay; + i=cmd_out_T(); + return (i); +} +/*==========================================================================*/ +static int cc_prep_mode_T(void) +{ + int i, j; + + i=cc_get_mode_T(); + if (i<0) return (i); + for (i=0;i<10;i++) + sprintf(&msgbuf[i*3], " %02X", infobuf[i]); + msgbuf[i*3]=0; + msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf); + D_S[d].speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */ + D_S[d].frmsiz=make16(infobuf[2],infobuf[3]); + D_S[d].f_XA=infobuf[4]; + if (D_S[d].f_XA==0) D_S[d].type_byte=0; + else D_S[d].type_byte=1; + D_S[d].mode_xb_6=infobuf[6]; + D_S[d].mode_yb_7=1; + D_S[d].mode_xb_8=infobuf[8]; + D_S[d].delay=0; /* 0, 1, 2, 3 */ + j=cc_set_mode_T(); + i=cc_get_mode_T(); + for (i=0;i<10;i++) + sprintf(&msgbuf[i*3], " %02X", infobuf[i]); + msgbuf[i*3]=0; + msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf); + return (j); +} +/*==========================================================================*/ +static int cc_SetSpeed(u_char speed, u_char x1, u_char x2) +{ + int i; + + if (fam0L_drive) return (-3); + clr_cmdbuf(); + response_count=0; + if (fam1_drive) + { + drvcmd[0]=CMD1_SETMODE; + drvcmd[1]=0x03; + drvcmd[2]=speed; + drvcmd[3]=x1; + drvcmd[4]=x2; + flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; } - else + else if (fam2_drive) { - drvcmd[2]=0; - drvcmd[3]=150; + drvcmd[0]=CMD2_SETSPEED; + if (speed&speed_auto) + { + drvcmd[2]=0xFF; + drvcmd[3]=0xFF; + } + else + { + drvcmd[2]=0; + drvcmd[3]=150; + } + flags_cmd_out=f_putcmd|f_ResponseStatus; } - flags_cmd_out=f_putcmd|f_ResponseStatus; - } - i=cmd_out(7); - return (i); + else if (famT_drive) + { + return (0); + } + i=cmd_out(); + return (i); } /*==========================================================================*/ -static int xx_SetVolume(void) +static int cc_SetVolume(void) { - int i; - u_char channel0,channel1,volume0,volume1; - u_char control0,value0,control1,value1; - - DriveStruct[d].diskstate_flags &= ~volume_bit; - clr_cmdbuf(); - channel0=DriveStruct[d].vol_chan0; - volume0=DriveStruct[d].vol_ctrl0; - channel1=control1=DriveStruct[d].vol_chan1; - volume1=value1=DriveStruct[d].vol_ctrl1; - control0=value0=0; - - if (((DriveStruct[d].drv_options&audio_mono)!=0)&&(DriveStruct[d].drv_type>=drv_211)) - { - if ((volume0!=0)&&(volume1==0)) + int i; + u_char channel0,channel1,volume0,volume1; + u_char control0,value0,control1,value1; + + D_S[d].diskstate_flags &= ~volume_bit; + clr_cmdbuf(); + channel0=D_S[d].vol_chan0; + volume0=D_S[d].vol_ctrl0; + channel1=control1=D_S[d].vol_chan1; + volume1=value1=D_S[d].vol_ctrl1; + control0=value0=0; + + if (((D_S[d].drv_options&audio_mono)!=0)&&(D_S[d].drv_type>=drv_211)) { - volume1=volume0; - channel1=channel0; + if ((volume0!=0)&&(volume1==0)) + { + volume1=volume0; + channel1=channel0; + } + else if ((volume0==0)&&(volume1!=0)) + { + volume0=volume1; + channel0=channel1; + } } - else if ((volume0==0)&&(volume1!=0)) + if (channel0>1) { - volume0=volume1; - channel0=channel1; + channel0=0; + volume0=0; } - } - if (channel0>1) - { - channel0=0; - volume0=0; - } - if (channel1>1) - { - channel1=1; - volume1=0; - } - - if (fam1_drive) - { - control0=channel0+1; - control1=channel1+1; - value0=(volume0>volume1)?volume0:volume1; - value1=value0; - if (volume0==0) control0=0; - if (volume1==0) control1=0; - drvcmd[0]=CMD1_SETMODE; - drvcmd[1]=0x05; - drvcmd[3]=control0; - drvcmd[4]=value0; - drvcmd[5]=control1; - drvcmd[6]=value1; - flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; - } - else if (fam2_drive) - { - control0=channel0+1; - control1=channel1+1; - value0=(volume0>volume1)?volume0:volume1; - value1=value0; - if (volume0==0) control0=0; - if (volume1==0) control1=0; - drvcmd[0]=CMD2_SETMODE; - drvcmd[1]=0x0E; - drvcmd[3]=control0; - drvcmd[4]=value0; - drvcmd[5]=control1; - drvcmd[6]=value1; - flags_cmd_out=f_putcmd|f_ResponseStatus; - } - else if (famL_drive) - { - if ((volume0==0)||(channel0!=0)) control0 |= 0x80; - if ((volume1==0)||(channel1!=1)) control0 |= 0x40; - if (volume0|volume1) value0=0x80; - drvcmd[0]=CMDL_SETMODE; - drvcmd[1]=0x03; - drvcmd[4]=control0; - drvcmd[5]=value0; - flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; - } - else if (fam0_drive) /* different firmware levels */ - { - if (DriveStruct[d].drv_type>=drv_300) - { - control0=volume0&0xFC; - value0=volume1&0xFC; - if ((volume0!=0)&&(volume0<4)) control0 |= 0x04; - if ((volume1!=0)&&(volume1<4)) value0 |= 0x04; - if (channel0!=0) control0 |= 0x01; - if (channel1==1) value0 |= 0x01; - } - else - { - value0=(volume0>volume1)?volume0:volume1; - if (DriveStruct[d].drv_type=drv_201) - { - if (volume0==0) control0 |= 0x80; - if (volume1==0) control0 |= 0x40; - } - if (DriveStruct[d].drv_type>=drv_211) - { - if (channel0!=0) control0 |= 0x20; - if (channel1!=1) control0 |= 0x10; - } - } - drvcmd[0]=CMD0_SETMODE; - drvcmd[1]=0x83; - drvcmd[4]=control0; - drvcmd[5]=value0; - flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; - } - response_count=0; - i=cmd_out(7); - if (i>0) return (i); - DriveStruct[d].diskstate_flags |= volume_bit; - return (0); + if (channel1>1) + { + channel1=1; + volume1=0; + } + + if (fam1_drive) + { + control0=channel0+1; + control1=channel1+1; + value0=(volume0>volume1)?volume0:volume1; + value1=value0; + if (volume0==0) control0=0; + if (volume1==0) control1=0; + drvcmd[0]=CMD1_SETMODE; + drvcmd[1]=0x05; + drvcmd[3]=control0; + drvcmd[4]=value0; + drvcmd[5]=control1; + drvcmd[6]=value1; + flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; + } + else if (fam2_drive) + { + control0=channel0+1; + control1=channel1+1; + value0=(volume0>volume1)?volume0:volume1; + value1=value0; + if (volume0==0) control0=0; + if (volume1==0) control1=0; + drvcmd[0]=CMD2_SETMODE; + drvcmd[1]=0x0E; + drvcmd[3]=control0; + drvcmd[4]=value0; + drvcmd[5]=control1; + drvcmd[6]=value1; + flags_cmd_out=f_putcmd|f_ResponseStatus; + } + else if (famL_drive) + { + if ((volume0==0)||(channel0!=0)) control0 |= 0x80; + if ((volume1==0)||(channel1!=1)) control0 |= 0x40; + if (volume0|volume1) value0=0x80; + drvcmd[0]=CMDL_SETMODE; + drvcmd[1]=0x03; + drvcmd[4]=control0; + drvcmd[5]=value0; + flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; + } + else if (fam0_drive) /* different firmware levels */ + { + if (D_S[d].drv_type>=drv_300) + { + control0=volume0&0xFC; + value0=volume1&0xFC; + if ((volume0!=0)&&(volume0<4)) control0 |= 0x04; + if ((volume1!=0)&&(volume1<4)) value0 |= 0x04; + if (channel0!=0) control0 |= 0x01; + if (channel1==1) value0 |= 0x01; + } + else + { + value0=(volume0>volume1)?volume0:volume1; + if (D_S[d].drv_type=drv_201) + { + if (volume0==0) control0 |= 0x80; + if (volume1==0) control0 |= 0x40; + } + if (D_S[d].drv_type>=drv_211) + { + if (channel0!=0) control0 |= 0x20; + if (channel1!=1) control0 |= 0x10; + } + } + drvcmd[0]=CMD0_SETMODE; + drvcmd[1]=0x83; + drvcmd[4]=control0; + drvcmd[5]=value0; + flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; + } + else if (famT_drive) + { + D_S[d].volume_control=0; + if (!volume0) D_S[d].volume_control|=0x10; + if (!volume1) D_S[d].volume_control|=0x20; + i=cc_prep_mode_T(); + if (i<0) return (i); + } + if (!famT_drive) + { + response_count=0; + i=cmd_out(); + if (i<0) return (i); + } + D_S[d].diskstate_flags |= volume_bit; + return (0); } /*==========================================================================*/ static int GetStatus(void) { - int i; - - flags_cmd_out=f_getsta|f_ResponseStatus|f_obey_p_check; - response_count=0; - cmd_type=0; - i=cmd_out(7); - return (i); -} -/*==========================================================================*/ -static int xy_DriveReset(void) -{ - int i; - - DPRINTF((DBG_RES,"SBPCD: xy_DriveReset called.\n")); - clr_cmdbuf(); - response_count=0; - if (fam0L_drive) OUT(CDo_reset,0x00); - else if (fam1_drive) - { - drvcmd[0]=CMD1_RESET; - flags_cmd_out=f_putcmd; - i=cmd_out(7); - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_RESET; - flags_cmd_out=f_putcmd; - i=cmd_out(7); - OUT(CDo_reset,0x00); - } - if (famL_drive) sbp_sleep(500); /* wait 5 seconds */ - else sbp_sleep(100); /* wait a second */ - flush_status(); - i=GetStatus(); - if (i>=0) return -1; - if (DriveStruct[d].error_byte!=aud_12) return -1; - return (0); + int i; + + if (famT_drive) return (0); + flags_cmd_out=f_getsta|f_ResponseStatus|f_obey_p_check; + response_count=0; + cmd_type=0; + i=cmd_out(); + return (i); +} +/*==========================================================================*/ +static int cc_DriveReset(void) +{ + int i; + + msg(DBG_RES,"cc_DriveReset called.\n"); + clr_cmdbuf(); + response_count=0; + if (fam0L_drive) OUT(CDo_reset,0x00); + else if (fam1_drive) + { + drvcmd[0]=CMD1_RESET; + flags_cmd_out=f_putcmd; + i=cmd_out(); + } + else if (fam2_drive) + { + drvcmd[0]=CMD2_RESET; + flags_cmd_out=f_putcmd; + i=cmd_out(); + OUT(CDo_reset,0x00); + } + else if (famT_drive) + { + OUT(CDo_sel_i_d,0); + OUT(CDo_enable,D_S[d].drv_sel); + OUT(CDo_command,CMDT_RESET); + for (i=1;i<10;i++) OUT(CDo_command,0); + } + if (fam0L_drive) sbp_sleep(500); /* wait 5 seconds */ + else sbp_sleep(100); /* wait a second */ +#if 1 + if (famT_drive) + { + msg(DBG_TEA, "================CMDT_RESET given=================.\n"); + sbp_sleep(300); + } +#endif 1 + flush_status(); + i=GetStatus(); + if (i<0) return i; + if (!famT_drive) + if (D_S[d].error_byte!=aud_12) return -501; + return (0); } /*==========================================================================*/ static int SetSpeed(void) { - int i, speed; - - if (!(DriveStruct[d].drv_options&(speed_auto|speed_300|speed_150))) return (0); - speed=speed_auto; - if (!(DriveStruct[d].drv_options&speed_auto)) - { - speed |= speed_300; - if (!(DriveStruct[d].drv_options&speed_300)) speed=0; - } - i=yy_SetSpeed(speed,0,0); - return (i); + int i, speed; + + if (!(D_S[d].drv_options&(speed_auto|speed_300|speed_150))) return (0); + speed=speed_auto; + if (!(D_S[d].drv_options&speed_auto)) + { + speed |= speed_300; + if (!(D_S[d].drv_options&speed_300)) speed=0; + } + i=cc_SetSpeed(speed,0,0); + return (i); } /*==========================================================================*/ static int DriveReset(void) { - int i; - - i=xy_DriveReset(); - if (i<0) return (-2); - do - { - i=GetStatus(); - if ((i<0)&&(i!=-15)) return (-2); /* i!=-15 is from sta2err */ - if (!st_caddy_in) break; - } - while (!st_diskok); + int i; + + i=cc_DriveReset(); + if (i<0) return (-22); + do + { + i=GetStatus(); + if ((i<0)&&(i!=-615)) return (-2); /* i!=-615 is from sta2err */ + if (!st_caddy_in) break; + sbp_sleep(1); + } + while (!st_diskok); #if 000 - DriveStruct[d].CD_changed=1; + D_S[d].CD_changed=1; #endif - if ((st_door_closed) && (st_caddy_in)) - { - i=DiskInfo(); - if (i<0) return (-2); - } - return (0); + if ((st_door_closed) && (st_caddy_in)) + { + i=DiskInfo(); + if (i<0) return (-23); + } + return (0); } /*==========================================================================*/ -static int xx_Pause_Resume(int pau_res) +static int cc_PlayAudio(int pos_audio_start,int pos_audio_end) { - int i; - - clr_cmdbuf(); - response_count=0; - if (fam1_drive) - { - drvcmd[0]=CMD1_PAU_RES; - if (pau_res!=1) drvcmd[1]=0x80; - flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_PAU_RES; - if (pau_res!=1) drvcmd[2]=0x01; - flags_cmd_out=f_putcmd|f_ResponseStatus; - } - else if (fam0L_drive) - { - drvcmd[0]=CMD0_PAU_RES; - if (pau_res!=1) drvcmd[1]=0x80; - if (famL_drive) - flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus| - f_obey_p_check|f_bit1; - else - flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus| - f_obey_p_check; - } - i=cmd_out(7); - return (i); + int i, j, n; + + if (D_S[d].audio_state==audio_playing) return (-EINVAL); + clr_cmdbuf(); + response_count=0; + if (famL_drive) + { + drvcmd[0]=CMDL_PLAY; + i=msf2blk(pos_audio_start); + n=msf2blk(pos_audio_end)+1-i; + drvcmd[1]=(i>>16)&0x00FF; + drvcmd[2]=(i>>8)&0x00FF; + drvcmd[3]=i&0x00FF; + drvcmd[4]=(n>>16)&0x00FF; + drvcmd[5]=(n>>8)&0x00FF; + drvcmd[6]=n&0x00FF; + flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | + f_ResponseStatus | f_obey_p_check | f_wait_if_busy; + } + else + { + j=1; + if (fam1_drive) + { + drvcmd[0]=CMD1_PLAY_MSF; + flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | + f_obey_p_check | f_wait_if_busy; + } + else if (fam2_drive) + { + drvcmd[0]=CMD2_PLAY_MSF; + flags_cmd_out = f_putcmd | f_ResponseStatus; + } + else if (famT_drive) + { + drvcmd[0]=CMDT_PLAY_MSF; + j=3; + response_count=1; + } + else if (fam0_drive) + { + drvcmd[0]=CMD0_PLAY_MSF; + flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | + f_ResponseStatus | f_obey_p_check | f_wait_if_busy; + } + drvcmd[j]=(pos_audio_start>>16)&0x00FF; + drvcmd[j+1]=(pos_audio_start>>8)&0x00FF; + drvcmd[j+2]=pos_audio_start&0x00FF; + drvcmd[j+3]=(pos_audio_end>>16)&0x00FF; + drvcmd[j+4]=(pos_audio_end>>8)&0x00FF; + drvcmd[j+5]=pos_audio_end&0x00FF; + } + i=cmd_out(); + return (i); } /*==========================================================================*/ -static int yy_LockDoor(char lock) +static int cc_Pause_Resume(int pau_res) { - int i; - - if (fam0_drive) return (0); - DPRINTF((DBG_LCK,"SBPCD: yy_LockDoor: %d (drive %d)\n", lock, d)); - DPRINTF((DBG_LCS,"SBPCD: p_door_locked bit %d before\n", st_door_locked)); - clr_cmdbuf(); - response_count=0; - if (fam1_drive) - { - drvcmd[0]=CMD1_LOCK_CTL; - if (lock==1) drvcmd[1]=0x01; - flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_LOCK_CTL; - if (lock==1) drvcmd[4]=0x01; - flags_cmd_out=f_putcmd|f_ResponseStatus; - } - else if (famL_drive) - { - drvcmd[0]=CMDL_LOCK_CTL; - if (lock==1) drvcmd[1]=0x01; - flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; - } - i=cmd_out(7); - DPRINTF((DBG_LCS,"SBPCD: p_door_locked bit %d after\n", st_door_locked)); - return (i); + int i; + + clr_cmdbuf(); + response_count=0; + if (fam1_drive) + { + drvcmd[0]=CMD1_PAU_RES; + if (pau_res!=1) drvcmd[1]=0x80; + flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; + } + else if (fam2_drive) + { + drvcmd[0]=CMD2_PAU_RES; + if (pau_res!=1) drvcmd[2]=0x01; + flags_cmd_out=f_putcmd|f_ResponseStatus; + } + else if (fam0L_drive) + { + drvcmd[0]=CMD0_PAU_RES; + if (pau_res!=1) drvcmd[1]=0x80; + if (famL_drive) + flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus| + f_obey_p_check|f_bit1; + else + flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus| + f_obey_p_check; + } + else if (famT_drive) + { + if (pau_res==3) return (cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end)); + else if (pau_res==1) drvcmd[0]=CMDT_PAUSE; + else return (-56); + } + i=cmd_out(); + return (i); } /*==========================================================================*/ -static int yy_CloseTray(void) +static int cc_LockDoor(char lock) { - int i; - - if (fam0_drive) return (0); - DPRINTF((DBG_LCK,"SBPCD: yy_CloseTray (drive %d)\n", d)); - DPRINTF((DBG_LCS,"SBPCD: p_door_closed bit %d before\n", st_door_closed)); - - clr_cmdbuf(); - response_count=0; - if (fam1_drive) - { - drvcmd[0]=CMD1_TRAY_CTL; - flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_TRAY_CTL; - drvcmd[1]=0x01; - drvcmd[4]=0x03; /* "insert" */ - flags_cmd_out=f_putcmd|f_ResponseStatus; - } - else if (famL_drive) - { - drvcmd[0]=CMDL_TRAY_CTL; - flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta| - f_ResponseStatus|f_obey_p_check|f_bit1; - } - i=cmd_out(7); - DPRINTF((DBG_LCS,"SBPCD: p_door_closed bit %d after\n", st_door_closed)); - return (i); + int i; + + if (fam0_drive) return (0); + msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, d); + msg(DBG_LCS,"p_door_locked bit %d before\n", st_door_locked); + clr_cmdbuf(); + response_count=0; + if (fam1_drive) + { + drvcmd[0]=CMD1_LOCK_CTL; + if (lock==1) drvcmd[1]=0x01; + flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; + } + else if (fam2_drive) + { + drvcmd[0]=CMD2_LOCK_CTL; + if (lock==1) drvcmd[4]=0x01; + flags_cmd_out=f_putcmd|f_ResponseStatus; + } + else if (famL_drive) + { + drvcmd[0]=CMDL_LOCK_CTL; + if (lock==1) drvcmd[1]=0x01; + flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; + } + else if (famT_drive) + { + drvcmd[0]=CMDT_LOCK_CTL; + if (lock==1) drvcmd[4]=0x01; + } + i=cmd_out(); + msg(DBG_LCS,"p_door_locked bit %d after\n", st_door_locked); + return (i); } /*==========================================================================*/ -static int xx_ReadSubQ(void) +/*==========================================================================*/ +static int UnLockDoor(void) { - int i,j; - - DriveStruct[d].diskstate_flags &= ~subq_bit; - for (j=255;j>0;j--) - { - clr_cmdbuf(); - if (fam1_drive) + int i,j; + + j=20; + do { - drvcmd[0]=CMD1_READSUBQ; - flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; - response_count=11; + i=cc_LockDoor(0); + --j; + sbp_sleep(1); } - else if (fam2_drive) + while ((i<0)&&(j)); + if (i<0) { - drvcmd[0]=CMD2_READSUBQ; - drvcmd[1]=0x02; - drvcmd[3]=0x01; - flags_cmd_out=f_putcmd; - response_count=10; + cc_DriveReset(); + return -84; } - else if (fam0L_drive) + return (0); +} +/*==========================================================================*/ +static int LockDoor(void) +{ + int i,j; + + j=20; + do { - drvcmd[0]=CMD0_READSUBQ; - drvcmd[1]=0x02; - if (famL_drive) - flags_cmd_out=f_putcmd; - else - flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; - response_count=13; + i=cc_LockDoor(1); + --j; + sbp_sleep(1); } - i=cmd_out(7); - if (i<0) return (i); - DPRINTF((DBG_SQ,"SBPCD: xx_ReadSubQ:")); - for (i=0;i0;j--) + { + clr_cmdbuf(); + if (fam1_drive) + { + drvcmd[0]=CMD1_READSUBQ; + flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; + response_count=11; + } + else if (fam2_drive) + { + drvcmd[0]=CMD2_READSUBQ; + drvcmd[1]=0x02; + drvcmd[3]=0x01; + flags_cmd_out=f_putcmd; + response_count=10; + } + else if (fam0L_drive) + { + drvcmd[0]=CMD0_READSUBQ; + drvcmd[1]=0x02; + if (famL_drive) + flags_cmd_out=f_putcmd; + else + flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; + response_count=13; + } + else if (famT_drive) + { + response_count=12; + drvcmd[0]=CMDT_READSUBQ; + drvcmd[1]=0x02; + drvcmd[2]=0x40; + drvcmd[3]=0x01; + drvcmd[8]=response_count; + } + i=cmd_out(); + if (i<0) return (i); + for (i=0;i>8)&0xFF; - drvcmd[4]=DriveStruct[d].frame_size&0xFF; - flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; - } - else if (fam0L_drive) - { - drvcmd[0]=CMD0_SETMODE; - drvcmd[1]=0x00; - drvcmd[2]=(DriveStruct[d].frame_size>>8)&0xFF; - drvcmd[3]=DriveStruct[d].frame_size&0xFF; - drvcmd[4]=0x00; - if(famL_drive) - flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check; - else - flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; - } - response_count=0; - i=cmd_out(7); - if (i<0) return (i); - DriveStruct[d].diskstate_flags |= frame_size_bit; - return (0); + int i; + + if (fam2_drive) return (0); + D_S[d].diskstate_flags &= ~frame_size_bit; + clr_cmdbuf(); + D_S[d].frame_size=framesize; + if (framesize==CD_FRAMESIZE_RAW) D_S[d].sense_byte=0x82; + else D_S[d].sense_byte=0x00; + + msg(DBG_XA1,"cc_ModeSelect: %02X %04X\n", + D_S[d].sense_byte, D_S[d].frame_size); + + if (fam1_drive) + { + drvcmd[0]=CMD1_SETMODE; + drvcmd[1]=0x00; + drvcmd[2]=D_S[d].sense_byte; + drvcmd[3]=(D_S[d].frame_size>>8)&0xFF; + drvcmd[4]=D_S[d].frame_size&0xFF; + flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; + } + else if (fam0L_drive) + { + drvcmd[0]=CMD0_SETMODE; + drvcmd[1]=0x00; + drvcmd[2]=(D_S[d].frame_size>>8)&0xFF; + drvcmd[3]=D_S[d].frame_size&0xFF; + drvcmd[4]=0x00; + if(famL_drive) + flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check; + else + flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; + } + else if (famT_drive) + { + return (-1); + } + response_count=0; + i=cmd_out(); + if (i<0) return (i); + D_S[d].diskstate_flags |= frame_size_bit; + return (0); } /*==========================================================================*/ -#if 0000 -static int xx_TellVolume(void) +static int cc_GetVolume(void) { - int i; - u_char switches; - u_char chan0,vol0,chan1,vol1; - - DriveStruct[d].diskstate_flags &= ~volume_bit; - clr_cmdbuf(); - if (fam1_drive) - { - drvcmd[0]=CMD1_GETMODE; - drvcmd[1]=0x05; - response_count=5; - flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_GETMODE; - drvcmd[1]=0x0E; - response_count=5; - flags_cmd_out=f_putcmd; - } - else if (fam0L_drive) - { - drvcmd[0]=CMD0_GETMODE; - drvcmd[1]=0x03; - response_count=2; - if(famL_drive) - flags_cmd_out=f_putcmd; - else - flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; - } - i=cmd_out(7); - if (i<0) return (i); - if (fam1_drive) - { - chan0=infobuf[1]&0x0F; - vol0=infobuf[2]; - chan1=infobuf[3]&0x0F; - vol1=infobuf[4]; - if (chan0==0) - { - chan0=1; - vol0=0; + int i; + u_char switches; + u_char chan0=0; + u_char vol0=0; + u_char chan1=1; + u_char vol1=0; + + D_S[d].diskstate_flags &= ~volume_bit; + clr_cmdbuf(); + if (fam1_drive) + { + drvcmd[0]=CMD1_GETMODE; + drvcmd[1]=0x05; + response_count=5; + flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; + } + else if (fam2_drive) + { + drvcmd[0]=CMD2_GETMODE; + drvcmd[1]=0x0E; + response_count=5; + flags_cmd_out=f_putcmd; + } + else if (fam0L_drive) + { + drvcmd[0]=CMD0_GETMODE; + drvcmd[1]=0x03; + response_count=2; + if(famL_drive) + flags_cmd_out=f_putcmd; + else + flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; + } + else if (famT_drive) + { + i=cc_get_mode_T(); + if (i<0) return (i); + } + if (!famT_drive) + { + i=cmd_out(); + if (i<0) return (i); + } + if (fam1_drive) + { + chan0=infobuf[1]&0x0F; + vol0=infobuf[2]; + chan1=infobuf[3]&0x0F; + vol1=infobuf[4]; + if (chan0==0) + { + chan0=1; + vol0=0; + } + if (chan1==0) + { + chan1=2; + vol1=0; + } + chan0 >>= 1; + chan1 >>= 1; } - if (chan1==0) + else if (fam2_drive) { - chan1=2; - vol1=0; + chan0=infobuf[1]; + vol0=infobuf[2]; + chan1=infobuf[3]; + vol1=infobuf[4]; + } + else if (famL_drive) + { + chan0=0; + chan1=1; + vol0=vol1=infobuf[1]; + switches=infobuf[0]; + if ((switches&0x80)!=0) chan0=1; + if ((switches&0x40)!=0) chan1=0; + } + else if (fam0_drive) /* different firmware levels */ + { + chan0=0; + chan1=1; + vol0=vol1=infobuf[1]; + if (D_S[d].drv_type>=drv_201) + { + if (D_S[d].drv_type=drv_211) + { + if ((switches&0x20)!=0) chan0=1; + if ((switches&0x10)!=0) chan1=0; + } + } + else + { + vol0=infobuf[0]; + if ((vol0&0x01)!=0) chan0=1; + if ((vol1&0x01)==0) chan1=0; + vol0 &= 0xFC; + vol1 &= 0xFC; + if (vol0!=0) vol0 += 3; + if (vol1!=0) vol1 += 3; + } + } } - chan0 >>= 1; - chan1 >>= 1; - } - else if (fam2_drive) - { - chan0=infobuf[1]; - vol0=infobuf[2]; - chan1=infobuf[3]; - vol1=infobuf[4]; - } - else if (famL_drive) - { - chan0=0; - chan1=1; - vol0=vol1=infobuf[1]; - switches=infobuf[0]; - if ((switches&0x80)!=0) chan0=1; - if ((switches&0x40)!=0) chan1=0; - } - else if (fam0_drive) /* different firmware levels */ - { - chan0=0; - chan1=1; - vol0=vol1=infobuf[1]; - if (DriveStruct[d].drv_type>=drv_201) - { - if (DriveStruct[d].drv_type=drv_211) - { - if ((switches&0x20)!=0) chan0=1; - if ((switches&0x10)!=0) chan1=0; - } - } - else - { - vol0=infobuf[0]; - if ((vol0&0x01)!=0) chan0=1; - if ((vol1&0x01)==0) chan1=0; - vol0 &= 0xFC; - vol1 &= 0xFC; - if (vol0!=0) vol0 += 3; - if (vol1!=0) vol1 += 3; - } - } - } - DriveStruct[d].vol_chan0=chan0; - DriveStruct[d].vol_ctrl0=vol0; - DriveStruct[d].vol_chan1=chan1; - DriveStruct[d].vol_ctrl1=vol1; - DriveStruct[d].vol_chan2=2; - DriveStruct[d].vol_ctrl2=0xFF; - DriveStruct[d].vol_chan3=3; - DriveStruct[d].vol_ctrl3=0xFF; - DriveStruct[d].diskstate_flags |= volume_bit; - return (0); + else if (famT_drive) + { + D_S[d].volume_control=infobuf[7]; + chan0=0; + chan1=1; + if (D_S[d].volume_control&0x10) vol0=0; + else vol0=0xff; + if (D_S[d].volume_control&0x20) vol1=0; + else vol1=0xff; + } + D_S[d].vol_chan0=chan0; + D_S[d].vol_ctrl0=vol0; + D_S[d].vol_chan1=chan1; + D_S[d].vol_ctrl1=vol1; +#if 000 + D_S[d].vol_chan2=2; + D_S[d].vol_ctrl2=0xFF; + D_S[d].vol_chan3=3; + D_S[d].vol_ctrl3=0xFF; +#endif 000 + D_S[d].diskstate_flags |= volume_bit; + return (0); } -#endif /*==========================================================================*/ -static int xx_ReadCapacity(void) +static int cc_ReadCapacity(void) { - int i; + int i, j; + + if (famL_drive) return (0); + D_S[d].diskstate_flags &= ~cd_size_bit; + for (j=3;j>0;j--) + { + clr_cmdbuf(); + if (fam1_drive) + { + drvcmd[0]=CMD1_CAPACITY; + response_count=5; + flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; + } + else if (fam2_drive) + { + drvcmd[0]=CMD2_CAPACITY; + response_count=8; + flags_cmd_out=f_putcmd; + } + else if (fam0_drive) + { + drvcmd[0]=CMD0_CAPACITY; + response_count=5; + flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; + } + else if (famT_drive) + { + response_count=12; + drvcmd[0]=CMDT_DISKINFO; + drvcmd[1]=0x02; + drvcmd[6]=CDROM_LEADOUT; + drvcmd[8]=response_count; + drvcmd[9]=0x00; + } + i=cmd_out(); + if (i>=0) break; + msg(DBG_000,"cc_ReadCapacity: cmd_out: err %d\n", i); + cc_ReadError(); + } + if (j==0) return (i); + if (fam1_drive) D_S[d].CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_BLOCK_OFFSET; + else if (fam0_drive) D_S[d].CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])); + else if (fam2_drive) D_S[d].CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3])); + else if (famT_drive) + { + D_S[d].CDsize_frm=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11])); + D_S[d].n_first_track=infobuf[2]; + D_S[d].n_last_track=infobuf[3]; - if (famL_drive) return (0); - DriveStruct[d].diskstate_flags &= ~cd_size_bit; - clr_cmdbuf(); - if (fam1_drive) - { - drvcmd[0]=CMD1_CAPACITY; - response_count=5; - flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_CAPACITY; - response_count=8; - flags_cmd_out=f_putcmd; - } - else if (fam0_drive) - { - drvcmd[0]=CMD0_CAPACITY; - response_count=5; - if(famL_drive) - flags_cmd_out=f_putcmd; - else - flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; - } - i=cmd_out(7); - if (i<0) return (i); - if (fam1_drive) DriveStruct[d].CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_BLOCK_OFFSET; - else if (fam0_drive) DriveStruct[d].CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])); - else if (fam2_drive) DriveStruct[d].CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3])); - DriveStruct[d].diskstate_flags |= cd_size_bit; - return (0); + } + D_S[d].diskstate_flags |= cd_size_bit; + msg(DBG_000,"cc_ReadCapacity: %d frames.\n", D_S[d].CDsize_frm); + return (0); } /*==========================================================================*/ -static int xx_ReadTocDescr(void) +static int cc_ReadTocDescr(void) { - int i; - - DriveStruct[d].diskstate_flags &= ~toc_bit; - clr_cmdbuf(); - if (fam1_drive) - { - drvcmd[0]=CMD1_DISKINFO; - response_count=6; - flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; - } - else if (fam0L_drive) - { - drvcmd[0]=CMD0_DISKINFO; - response_count=6; - if(famL_drive) - flags_cmd_out=f_putcmd; - else - flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; - } - else if (fam2_drive) - { - /* possibly longer timeout periods necessary */ - DriveStruct[d].f_multisession=0; - drvcmd[0]=CMD2_DISKINFO; - drvcmd[1]=0x02; - drvcmd[2]=0xAB; - drvcmd[3]=0xFF; /* session */ - response_count=8; - flags_cmd_out=f_putcmd; - } - i=cmd_out(7); - if (i<0) return (i); - DriveStruct[d].xa_byte=infobuf[0]; - if (fam2_drive) - { - DriveStruct[d].first_session=infobuf[1]; - DriveStruct[d].last_session=infobuf[2]; - DriveStruct[d].n_first_track=infobuf[3]; - DriveStruct[d].n_last_track=infobuf[4]; - if (DriveStruct[d].first_session!=DriveStruct[d].last_session) - { - DriveStruct[d].f_multisession=1; - DriveStruct[d].lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]))); - } + int i; + + D_S[d].diskstate_flags &= ~toc_bit; + clr_cmdbuf(); + if (fam1_drive) + { + drvcmd[0]=CMD1_DISKINFO; + response_count=6; + flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; + } + else if (fam0L_drive) + { + drvcmd[0]=CMD0_DISKINFO; + response_count=6; + if(famL_drive) + flags_cmd_out=f_putcmd; + else + flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check; + } + else if (fam2_drive) + { + /* possibly longer timeout periods necessary */ + D_S[d].f_multisession=0; + drvcmd[0]=CMD2_DISKINFO; + drvcmd[1]=0x02; + drvcmd[2]=0xAB; + drvcmd[3]=0xFF; /* session */ + response_count=8; + flags_cmd_out=f_putcmd; + } + else if (famT_drive) + { + D_S[d].f_multisession=0; + response_count=12; + drvcmd[0]=CMDT_DISKINFO; + drvcmd[1]=0x02; + drvcmd[6]=CDROM_LEADOUT; + drvcmd[8]=response_count; + drvcmd[9]=0x00; + } + i=cmd_out(); + if (i<0) return (i); + if ((fam1_drive)||(fam2_drive)||(famL_drive)||(fam0_drive)) + D_S[d].xa_byte=infobuf[0]; + if (fam2_drive) + { + D_S[d].first_session=infobuf[1]; + D_S[d].last_session=infobuf[2]; + D_S[d].n_first_track=infobuf[3]; + D_S[d].n_last_track=infobuf[4]; + if (D_S[d].first_session!=D_S[d].last_session) + { + D_S[d].f_multisession=1; + D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]))); + } #if 0 - if (DriveStruct[d].first_session!=DriveStruct[d].last_session) - { - if (DriveStruct[d].last_session<=20) - zwanzig=DriveStruct[d].last_session+1; - else zwanzig=20; - for (count=DriveStruct[d].first_session;count>16)&0xFF; - drvcmd[2]=(block>>8)&0xFF; - drvcmd[3]=block&0xFF; + drvcmd[1]=(block>>16)&0xFF; + drvcmd[2]=(block>>8)&0xFF; + drvcmd[3]=block&0xFF; #endif TEST_UPC - response_count=8; - flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; - } - else if (fam0L_drive) - { - drvcmd[0]=CMD0_READ_UPC; + response_count=8; + flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; + } + else if (fam0L_drive) + { + drvcmd[0]=CMD0_READ_UPC; #if TEST_UPC - drvcmd[2]=(block>>16)&0xFF; - drvcmd[3]=(block>>8)&0xFF; - drvcmd[4]=block&0xFF; + drvcmd[2]=(block>>16)&0xFF; + drvcmd[3]=(block>>8)&0xFF; + drvcmd[4]=block&0xFF; #endif TEST_UPC - response_count=0; - flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; - } - else /* CD200 */ - { - return (-1); - } - i=cmd_out(7); - if (i<0) return (i); - if (fam0L_drive) - { - response_count=16; - if (famL_drive) flags_cmd_out=f_putcmd; - i=xx_ReadPacket(); - if (i<0) return (i); - } + response_count=0; + flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; + } + else if (fam2_drive) + { + return (-1); + } + else if (famT_drive) + { + return (-1); + } + i=cmd_out(); + if (i<0) + { + msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i); + return (i); + } + if (fam0L_drive) + { + response_count=16; + if (famL_drive) flags_cmd_out=f_putcmd; + i=cc_ReadPacket(); + if (i<0) + { + msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i); + return (i); + } + } #if TEST_UPC - checksum=0; + checksum=0; #endif TEST_UPC - DPRINTF((DBG_UPC,"SBPCD: UPC info: ")); - for (i=0;i<(fam1_drive?8:16);i++) - { + for (i=0;i<(fam1_drive?8:16);i++) + { #if TEST_UPC - checksum |= infobuf[i]; + checksum |= infobuf[i]; #endif TEST_UPC - DPRINTF((DBG_UPC,"%02X ", infobuf[i])); - } - DPRINTF((DBG_UPC,"\n")); + sprintf(&msgbuf[i*3], " %02X", infobuf[i]); + } + msgbuf[i*3]=0; + msg(DBG_UPC,"UPC info:%s\n", msgbuf); #if TEST_UPC - if ((checksum&0x7F)!=0) break; - } + if ((checksum&0x7F)!=0) break; + } #endif TEST_UPC - DriveStruct[d].UPC_ctl_adr=0; - if (fam1_drive) i=0; - else i=2; - if ((infobuf[i]&0x80)!=0) - { - convert_UPC(&infobuf[i]); - DriveStruct[d].UPC_ctl_adr = (DriveStruct[d].TocEnt_ctl_adr & 0xF0) | 0x02; - } - - DPRINTF((DBG_UPC,"SBPCD: UPC code: ")); - DPRINTF((DBG_UPC,"(%02X) ", DriveStruct[d].UPC_ctl_adr)); - for (i=0;i<7;i++) - { - DPRINTF((DBG_UPC,"%02X ", DriveStruct[d].UPC_buf[i])); - } - DPRINTF((DBG_UPC,"\n")); - - DriveStruct[d].diskstate_flags |= upc_bit; - return (0); + D_S[d].UPC_ctl_adr=0; + if (fam1_drive) i=0; + else i=2; + if ((infobuf[i]&0x80)!=0) + { + convert_UPC(&infobuf[i]); + D_S[d].UPC_ctl_adr = (D_S[d].TocEnt_ctl_adr & 0xF0) | 0x02; + } + for (i=0;i<7;i++) + sprintf(&msgbuf[i*3], " %02X", D_S[d].UPC_buf[i]); + sprintf(&msgbuf[i*3], " (%02X)", D_S[d].UPC_ctl_adr); + msgbuf[i*3+5]=0; + msg(DBG_UPC,"UPC code:%s\n", msgbuf); + D_S[d].diskstate_flags |= upc_bit; + return (0); } /*==========================================================================*/ -static int yy_CheckMultiSession(void) +static int cc_CheckMultiSession(void) { - int i; - - if (fam2_drive) return (0); - DriveStruct[d].f_multisession=0; - DriveStruct[d].lba_multi=0; - if (fam0_drive) return (0); - clr_cmdbuf(); - if (fam1_drive) - { - drvcmd[0]=CMD1_MULTISESS; - response_count=6; - flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; - i=cmd_out(7); - if (i<0) return (i); - if ((infobuf[0]&0x80)!=0) - { - DriveStruct[d].f_multisession=1; - DriveStruct[d].lba_multi=msf2blk(make32(make16(0,infobuf[1]), - make16(infobuf[2],infobuf[3]))); - DPRINTF((DBG_MUL,"SBPCD: MultiSession CD detected: %02X %02X %02X %02X %02X %02X (%d)\n", - infobuf[0], infobuf[1], infobuf[2], - infobuf[3], infobuf[4], infobuf[5], - DriveStruct[d].lba_multi)); + int i; + + if (fam2_drive) return (0); + D_S[d].f_multisession=0; + D_S[d].lba_multi=0; + if (fam0_drive) return (0); + clr_cmdbuf(); + if (fam1_drive) + { + drvcmd[0]=CMD1_MULTISESS; + response_count=6; + flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; + i=cmd_out(); + if (i<0) return (i); + if ((infobuf[0]&0x80)!=0) + { + D_S[d].f_multisession=1; + D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[1]), + make16(infobuf[2],infobuf[3]))); + } } - } - else if (famL_drive) - { - drvcmd[0]=CMDL_MULTISESS; - drvcmd[1]=3; - drvcmd[2]=1; - response_count=8; - flags_cmd_out=f_putcmd; - i=cmd_out(7); - if (i<0) return (i); - DriveStruct[d].lba_multi=msf2blk(make32(make16(0,infobuf[5]), - make16(infobuf[6],infobuf[7]))); - DPRINTF((DBG_MUL,"SBPCD: MultiSession Info: %02X %02X %02X %02X %02X %02X %02X %02X (%d)\n", - infobuf[0], infobuf[1], infobuf[2], infobuf[3], - infobuf[4], infobuf[5], infobuf[6], infobuf[7], - DriveStruct[d].lba_multi)); - if (DriveStruct[d].lba_multi>200) + else if (famL_drive) + { + drvcmd[0]=CMDL_MULTISESS; + drvcmd[1]=3; + drvcmd[2]=1; + response_count=8; + flags_cmd_out=f_putcmd; + i=cmd_out(); + if (i<0) return (i); + D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[5]), + make16(infobuf[6],infobuf[7]))); + } + else if (famT_drive) + { + response_count=12; + drvcmd[0]=CMDT_DISKINFO; + drvcmd[1]=0x02; + drvcmd[6]=0; + drvcmd[8]=response_count; + drvcmd[9]=0x40; + i=cmd_out(); + if (i<0) return (i); + D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11]))); + } + for (i=0;i200) { - DPRINTF((DBG_MUL,"SBPCD: MultiSession base: %06X\n", DriveStruct[d].lba_multi)); - DriveStruct[d].f_multisession=1; + D_S[d].f_multisession=1; + msg(DBG_MUL,"MultiSession base: %06X\n", D_S[d].lba_multi); } - } - return (0); + return (0); } /*==========================================================================*/ #if FUTURE -static int yy_SubChanInfo(int frame, int count, u_char *buffer) -/* "frame" is a RED BOOK (msf-bin) address */ +static int cc_SubChanInfo(int frame, int count, u_char *buffer) + /* "frame" is a RED BOOK (msf-bin) address */ { - int i; - - if (fam0L_drive) return (-ENOSYS); /* drive firmware lacks it */ + int i; + + if (fam0L_drive) return (-ENOSYS); /* drive firmware lacks it */ + if (famT_drive) + { + return (-1); + } #if 0 - if (DriveStruct[d].audio_state!=audio_playing) return (-ENODATA); + if (D_S[d].audio_state!=audio_playing) return (-ENODATA); #endif - clr_cmdbuf(); - drvcmd[0]=CMD1_SUBCHANINF; - drvcmd[1]=(frame>>16)&0xFF; - drvcmd[2]=(frame>>8)&0xFF; - drvcmd[3]=frame&0xFF; - drvcmd[5]=(count>>8)&0xFF; - drvcmd[6]=count&0xFF; - flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; - cmd_type=READ_SC; - DriveStruct[d].frame_size=CD_FRAMESIZE_SUB; - i=cmd_out(7); /* which buffer to use? */ - return (i); + clr_cmdbuf(); + drvcmd[0]=CMD1_SUBCHANINF; + drvcmd[1]=(frame>>16)&0xFF; + drvcmd[2]=(frame>>8)&0xFF; + drvcmd[3]=frame&0xFF; + drvcmd[5]=(count>>8)&0xFF; + drvcmd[6]=count&0xFF; + flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; + cmd_type=READ_SC; + D_S[d].frame_size=CD_FRAMESIZE_SUB; + i=cmd_out(); /* which buffer to use? */ + return (i); } #endif FUTURE /*==========================================================================*/ static void check_datarate(void) { -#ifdef CDMKE - int i=0; - - DPRINTF((DBG_IOX,"SBPCD: check_datarate entered.\n")); - datarate=0; + int i=0; + + msg(DBG_IOX,"check_datarate entered.\n"); + datarate=0; #if TEST_STI - for (i=0;i<=1000;i++) printk("."); + for (i=0;i<=1000;i++) printk("."); #endif - /* set a timer to make (timed_out!=0) after 1.1 seconds */ -#if 0 - del_timer(&delay_timer); + /* set a timer to make (timed_out_delay!=0) after 1.1 seconds */ +#if 1 + del_timer(&delay_timer); #endif - delay_timer.expires = 110; - timed_out=0; - add_timer(&delay_timer); - DPRINTF((DBG_TIM,"SBPCD: timer started (110).\n")); - do - { - i=inb(CDi_status); - datarate++; -#if 00000 - if (datarate>0x0FFFFFFF) break; + delay_timer.expires=110; + timed_out_delay=0; + add_timer(&delay_timer); + msg(DBG_TIM,"delay timer started (110).\n"); + do + { + i=inb(CDi_status); + datarate++; +#if 1 + if (datarate>0x6FFFFFFF) break; #endif 00000 - } - while (!timed_out); /* originally looping for 1.1 seconds */ -#if 0 - del_timer(&delay_timer); -#endif 0 - DPRINTF((DBG_TIM,"SBPCD: datarate: %d\n", datarate)); - if (datarate<65536) datarate=65536; - - maxtim16=datarate*16; - maxtim04=datarate*4; - maxtim02=datarate*2; - maxtim_8=datarate/32; + } + while (!timed_out_delay); + del_timer(&delay_timer); + msg(DBG_TIM,"datarate: %04X\n", datarate); + if (datarate<65536) datarate=65536; + maxtim16=datarate*16; + maxtim04=datarate*4; + maxtim02=datarate*2; + maxtim_8=datarate/32; #if LONG_TIMING - maxtim_data=datarate/100; + maxtim_data=datarate/100; #else - maxtim_data=datarate/300; + maxtim_data=datarate/300; #endif LONG_TIMING - DPRINTF((DBG_TIM,"SBPCD: maxtim_8 %d, maxtim_data %d.\n", - maxtim_8, maxtim_data)); -#endif CDMKE + msg(DBG_TIM,"maxtim_8 %d, maxtim_data %d.\n", + maxtim_8, maxtim_data); } /*==========================================================================*/ -#ifdef CD200 - #if 0 - -static int xx_ReadVersion(int fam) -{ - int i; - - clr_cmdbuf(); - clear_response_buffer(13); - if (fam==1) - { - drvcmd[0]=CMD0_READ_VER; /* same as CMD1_ and CMDL_ */ - response_count=13; - i=do_cmd(f_putcmd|f_lopsta|f_getsta|f_ResponseStatus); - } - else if (fam==2) - { - drvcmd[0]=CMD2_READ_VER; - response_count=12; - i=do_cmd(f_putcmd); - } - else return (-1); - return (i); -} - -static int yy_ReadError(int fam) +static int c2_ReadError(int fam) { - int i; - - clr_cmdbuf(); - response_count=9; - clr_respo_buf(9); - if (fam==1) - { - drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */ - i=do_cmd(f_putcmd|f_lopsta|f_getsta|f_ResponseStatus); - } - else if (fam==2) - { - drvcmd[0]=CMD2_READ_ERR; - i=do_cmd(f_putcmd); - } - else return (-1); - return (i); + int i; + + clr_cmdbuf(); + response_count=9; + clr_respo_buf(9); + if (fam==1) + { + drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */ + i=do_cmd(f_putcmd|f_lopsta|f_getsta|f_ResponseStatus); + } + else if (fam==2) + { + drvcmd[0]=CMD2_READ_ERR; + i=do_cmd(f_putcmd); + } + else return (-1); + return (i); } #endif - -#endif CD200 /*==========================================================================*/ static void ask_mail(void) { - int i; - - printk("SBPCD: please mail the following lines to emoenke@gwdg.de:\n"); - printk("SBPCD: address %03X, type %s, drive ID %d\n", CDo_command, type, DriveStruct[d].drv_id); - printk("SBPCD: infobuf = \""); - for (i=0;i<12;i++) printk("%02X ",infobuf[i]); - printk("\"\nSBPCD: infobuf = \""); - for (i=0;i<12;i++) printk("%c",infobuf[i]); - printk("\"\n"); + int i; + + msg(DBG_INF, "please mail the following lines to emoenke@gwdg.de:\n"); + msg(DBG_INF, "%s\n", VERSION); + msg(DBG_INF, "address %03X, type %s, drive %s (ID %d)\n", + CDo_command, type, D_S[d].drive_model, D_S[d].drv_id); + for (i=0;i<12;i++) + sprintf(&msgbuf[i*3], " %02X", infobuf[i]); + msgbuf[i*3]=0; + msg(DBG_INF,"infobuf =%s\n", msgbuf); + for (i=0;i<12;i++) + sprintf(&msgbuf[i*3], " %c ", infobuf[i]); + msgbuf[i*3]=0; + msg(DBG_INF,"infobuf =%s\n", msgbuf); } /*==========================================================================*/ static int check_version(void) { - int i, j; - u_char lcs_firm[][4]={"A4F4","A E1"}; - - DPRINTF((DBG_INI,"SBPCD: check_version entered.\n")); - DriveStruct[d].drv_type=0; - - /* check for CD200 */ - clr_cmdbuf(); - drvcmd[0]=CMD2_READ_ERR; - response_count=9; - flags_cmd_out=f_putcmd; - i=cmd_out(7); - if (i<0) DPRINTF((DBG_INI,"SBPCD: CMD2_READERR returns %d (ok anyway).\n",i)); - /* read drive version */ - clr_cmdbuf(); - for (i=0;i<12;i++) infobuf[i]=0; - if (sbpro_type==1) OUT(CDo_sel_i_d,0); + int i, j, l; + int teac_possible=0; + + msg(DBG_INI,"check_version entered.\n"); + msg(DBG_TE2,"check_version: id=%d, d=%d.\n", D_S[d].drv_id, d); + D_S[d].drv_type=0; + + /* check for CR-52x, CR-56x and LCS-7260 */ + /* clear any pending error state */ + clr_cmdbuf(); + drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */ + response_count=9; + flags_cmd_out=f_putcmd; + i=cmd_out(); + if (i<0) msg(DBG_INI,"CMD0_READERR returns %d (ok anyway).\n",i); + /* read drive version */ + clr_cmdbuf(); + for (i=0;i<12;i++) infobuf[i]=0; + drvcmd[0]=CMD0_READ_VER; /* same as CMD1_ and CMDL_ */ + response_count=12; /* fam1: only 11 */ + flags_cmd_out=f_putcmd; + i=cmd_out(); + if (i<-1) msg(DBG_INI,"CMD0_READ_VER returns %d\n",i); + if (i==-11) teac_possible++; + j=0; + for (i=0;i<12;i++) j+=infobuf[i]; + if (j) + { + for (i=0;i<12;i++) + sprintf(&msgbuf[i*3], " %02X", infobuf[i]); + msgbuf[i*3]=0; + msg(DBG_IDX,"infobuf =%s\n", msgbuf); + msg(DBG_000,"infobuf =%s\n", msgbuf); + for (i=0;i<12;i++) + sprintf(&msgbuf[i*3], " %c ", infobuf[i]); + msgbuf[i*3]=0; + msg(DBG_IDX,"infobuf =%s\n", msgbuf); + msg(DBG_000,"infobuf =%s\n", msgbuf); + } + for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break; + if (i==4) + { + D_S[d].drive_model[0]='C'; + D_S[d].drive_model[1]='R'; + D_S[d].drive_model[2]='-'; + D_S[d].drive_model[3]='5'; + D_S[d].drive_model[4]=infobuf[i++]; + D_S[d].drive_model[5]=infobuf[i++]; + D_S[d].drive_model[6]=0; + D_S[d].drv_type=drv_fam1; + } + if (!D_S[d].drv_type) + { + for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break; + if (i==8) + { + D_S[d].drive_model[0]='C'; + D_S[d].drive_model[1]='R'; + D_S[d].drive_model[2]='-'; + D_S[d].drive_model[3]='5'; + D_S[d].drive_model[4]='2'; + D_S[d].drive_model[5]='x'; + D_S[d].drive_model[6]=0; + D_S[d].drv_type=drv_fam0; + } + } + if (!D_S[d].drv_type) + { + for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break; + if (i==8) + { + for (j=0;j<8;j++) + D_S[d].drive_model[j]=infobuf[j]; + D_S[d].drive_model[8]=0; + D_S[d].drv_type=drv_famL; + } + } + if (!D_S[d].drv_type) + { + /* check for CD200 */ + clr_cmdbuf(); + drvcmd[0]=CMD2_READ_ERR; + response_count=9; + flags_cmd_out=f_putcmd; + i=cmd_out(); + if (i<0) msg(DBG_INI,"CMD2_READERR returns %d (ok anyway).\n",i); + if (i<0) msg(DBG_000,"CMD2_READERR returns %d (ok anyway).\n",i); + /* read drive version */ + clr_cmdbuf(); + for (i=0;i<12;i++) infobuf[i]=0; + if (sbpro_type==1) OUT(CDo_sel_i_d,0); #if 0 - OUT(CDo_reset,0); - sbp_sleep(600); - OUT(CDo_enable,DriveStruct[d].drv_sel); -#endif - drvcmd[0]=CMD2_READ_VER; - response_count=12; - flags_cmd_out=f_putcmd; - i=cmd_out(7); - if (i<0) DPRINTF((DBG_INI,"SBPCD: CMD2_READ_VER returns %d\n",i)); - if (i>=0) /* from CD200 */ - { - for (i=0, j=0;i<12;i++) j+=infobuf[i]; - if (j) - { - DPRINTF((DBG_ID,"SBPCD: infobuf = \"")); - for (i=0;i<12;i++) DPRINTF((DBG_ID,"%02X ",infobuf[i])); - for (i=0;i<12;i++) DPRINTF((DBG_ID,"%c",infobuf[i])); - DPRINTF((DBG_ID,"\"\n")); - } - for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break; - if (i==5) - { - DriveStruct[d].drive_model[0]='C'; - DriveStruct[d].drive_model[1]='D'; - DriveStruct[d].drive_model[2]='2'; - DriveStruct[d].drive_model[3]='0'; - DriveStruct[d].drive_model[4]='0'; - DriveStruct[d].drive_model[5]=infobuf[i++]; - DriveStruct[d].drive_model[6]=infobuf[i++]; - DriveStruct[d].drive_model[7]=0; - DriveStruct[d].drv_type=drv_fam2; + OUT(CDo_reset,0); + sbp_sleep(600); + OUT(CDo_enable,D_S[d].drv_sel); +#endif 0 + drvcmd[0]=CMD2_READ_VER; + response_count=12; + flags_cmd_out=f_putcmd; + i=cmd_out(); + if (i<0) msg(DBG_INI,"CMD2_READ_VER returns %d\n",i); + if (i==-7) teac_possible++; + j=0; + for (i=0;i<12;i++) j+=infobuf[i]; + if (j) + { + for (i=0;i<12;i++) + sprintf(&msgbuf[i*3], " %02X", infobuf[i]); + msgbuf[i*3]=0; + msg(DBG_IDX,"infobuf =%s\n", msgbuf); + for (i=0;i<12;i++) + sprintf(&msgbuf[i*3], " %c ", infobuf[i]); + msgbuf[i*3]=0; + msg(DBG_IDX,"infobuf =%s\n", msgbuf); + } + if (i>=0) + { + for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break; + if (i==5) + { + D_S[d].drive_model[0]='C'; + D_S[d].drive_model[1]='D'; + D_S[d].drive_model[2]='2'; + D_S[d].drive_model[3]='0'; + D_S[d].drive_model[4]='0'; + D_S[d].drive_model[5]=infobuf[i++]; + D_S[d].drive_model[6]=infobuf[i++]; + D_S[d].drive_model[7]=0; + D_S[d].drv_type=drv_fam2; + } + } } - } + if (!D_S[d].drv_type) + { + /* check for TEAC CD-55A */ + msg(DBG_TEA,"teac_possible: %d\n",teac_possible); + for (j=1;j<=((D_S[d].drv_id==0)?3:1);j++) + { + for (l=1;l<=((D_S[d].drv_id==0)?10:1);l++) + { + msg(DBG_TEA,"TEAC reset #%d-%d.\n", j, l); + if (sbpro_type==1) OUT(CDo_reset,0); + else + { + OUT(CDo_enable,D_S[d].drv_sel); + OUT(CDo_sel_i_d,0); + OUT(CDo_command,CMDT_RESET); + for (i=0;i<9;i++) OUT(CDo_command,0); + } + sbp_sleep(50); + OUT(CDo_enable,D_S[d].drv_sel); + OUT(CDo_sel_i_d,0); + i=inb(CDi_status); + msg(DBG_TEA,"TEAC CDi_status: %02X.\n",i); +#if 0 + if (i&s_not_result_ready) continue; /* drive not present or ready */ +#endif + i=inb(CDi_info); + msg(DBG_TEA,"TEAC CDi_info: %02X.\n",i); + if (i==0x55) break; /* drive found */ + } + if (i==0x55) break; /* drive found */ + } + if (i==0x55) /* drive found */ + { + msg(DBG_TEA,"TEAC drive found.\n"); + clr_cmdbuf(); + flags_cmd_out=f_putcmd; + response_count=12; + drvcmd[0]=CMDT_READ_VER; + drvcmd[4]=response_count; + for (i=0;i<12;i++) infobuf[i]=0; + i=cmd_out_T(); + if (i!=0) msg(DBG_TEA,"cmd_out_T(CMDT_READ_VER) returns %d.\n",i); + for (i=1;i<6;i++) if (infobuf[i]!=familyT[i-1]) break; + if (i==6) + { + D_S[d].drive_model[0]='C'; + D_S[d].drive_model[1]='D'; + D_S[d].drive_model[2]='-'; + D_S[d].drive_model[3]='5'; + D_S[d].drive_model[4]='5'; + D_S[d].drive_model[5]=0; + D_S[d].drv_type=drv_famT; + } + } + } + if (!D_S[d].drv_type) + { + msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,D_S[d].drv_id); + return (-522); + } + for (j=0;j<4;j++) D_S[d].firmware_version[j]=infobuf[i+j]; + if (famL_drive) + { + u_char lcs_firm_e1[]="A E1"; + u_char lcs_firm_f4[]="A4F4"; + + for (j=0;j<4;j++) + if (D_S[d].firmware_version[j]!=lcs_firm_e1[j]) break; + if (j==4) D_S[d].drv_type=drv_e1; + + for (j=0;j<4;j++) + if (D_S[d].firmware_version[j]!=lcs_firm_f4[j]) break; + if (j==4) D_S[d].drv_type=drv_f4; - if (!DriveStruct[d].drv_type) - { - /* check for CR-52x, CR-56x and LCS-7260 */ - /* clear any pending error state */ - clr_cmdbuf(); - drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */ - response_count=9; - flags_cmd_out=f_putcmd; - i=cmd_out(7); - if (i<0) DPRINTF((DBG_INI,"SBPCD: CMD0_READERR returns %d (ok anyway).\n",i)); - /* read drive version */ - clr_cmdbuf(); - for (i=0;i<12;i++) infobuf[i]=0; - drvcmd[0]=CMD0_READ_VER; /* same as CMD1_ and CMDL_ */ - response_count=12; - flags_cmd_out=f_putcmd; - i=cmd_out(7); - if (i<0) DPRINTF((DBG_INI,"SBPCD: CMD0_READ_VER returns %d\n",i)); - - for (i=0, j=0;i<12;i++) j+=infobuf[i]; - if (j) - { - DPRINTF((DBG_ID,"SBPCD: infobuf = \"")); - for (i=0;i<12;i++) DPRINTF((DBG_ID,"%02X ",infobuf[i])); - for (i=0;i<12;i++) DPRINTF((DBG_ID,"%c",infobuf[i])); - DPRINTF((DBG_ID,"\"\n")); - } - - for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break; - if (i==4) - { - DriveStruct[d].drive_model[0]='C'; - DriveStruct[d].drive_model[1]='R'; - DriveStruct[d].drive_model[2]='-'; - DriveStruct[d].drive_model[3]='5'; - DriveStruct[d].drive_model[4]=infobuf[i++]; - DriveStruct[d].drive_model[5]=infobuf[i++]; - DriveStruct[d].drive_model[6]=0; - DriveStruct[d].drv_type=drv_fam1; - } - if (!DriveStruct[d].drv_type) - { - for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break; - if (i==8) - { - DriveStruct[d].drive_model[0]='C'; - DriveStruct[d].drive_model[1]='R'; - DriveStruct[d].drive_model[2]='-'; - DriveStruct[d].drive_model[3]='5'; - DriveStruct[d].drive_model[4]='2'; - DriveStruct[d].drive_model[5]='x'; - DriveStruct[d].drive_model[6]=0; - DriveStruct[d].drv_type=drv_fam0; - } - } - if (!DriveStruct[d].drv_type) - { - for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break; - if (i==8) - { - for (j=0;j<8;j++) - DriveStruct[d].drive_model[j]=infobuf[j]; - DriveStruct[d].drive_model[8]=0; - DriveStruct[d].drv_type=drv_famL; - } + if (!D_S[d].drv_type) ask_mail(); } - } - if (!DriveStruct[d].drv_type) - { - DPRINTF((DBG_INI,"SBPCD: check_version: error.\n")); - return (-1); - } - for (j=0;j<4;j++) DriveStruct[d].firmware_version[j]=infobuf[i+j]; - if (famL_drive) - { - for (i=0;i<2;i++) - { - for (j=0;j<4;j++) - if (DriveStruct[d].firmware_version[j]!=lcs_firm[i][j]) break; - if (j==4) break; + else if (famT_drive) + { + j=infobuf[4]; /* one-byte version??? - here: 0x15 */ + if (j=='5') + { + D_S[d].firmware_version[0]=infobuf[7]; + D_S[d].firmware_version[1]=infobuf[8]; + D_S[d].firmware_version[2]=infobuf[10]; + D_S[d].firmware_version[3]=infobuf[11]; + } + else + { + if (j!=0x15) ask_mail(); + D_S[d].firmware_version[0]='0'; + D_S[d].firmware_version[1]='.'; + D_S[d].firmware_version[2]='0'+(j>>4); + D_S[d].firmware_version[3]='0'+(j&0x0f); + } } - if (j!=4) ask_mail(); - DriveStruct[d].drv_type=drv_260; - } - else - { - j = (DriveStruct[d].firmware_version[0] & 0x0F) * 100 + - (DriveStruct[d].firmware_version[2] & 0x0F) *10 + - (DriveStruct[d].firmware_version[3] & 0x0F); - if (fam0_drive) - { - if (j<200) DriveStruct[d].drv_type=drv_199; - else if (j<201) DriveStruct[d].drv_type=drv_200; - else if (j<210) DriveStruct[d].drv_type=drv_201; - else if (j<211) DriveStruct[d].drv_type=drv_210; - else if (j<300) DriveStruct[d].drv_type=drv_211; - else if (j>=300) DriveStruct[d].drv_type=drv_300; - } - else if (fam1_drive) - { - if (j<100) DriveStruct[d].drv_type=drv_099; - else - { - DriveStruct[d].drv_type=drv_100; - ask_mail(); - } - } - else if (fam2_drive) - { - printk("\n\nSBPCD: new drive CD200 (%s)detected.\n", - DriveStruct[d].firmware_version); - printk("SBPCD: support is not fulfilled yet.\n"); - if (j!=101) ask_mail(); /* only 1.01 known at time */ + else /* CR-52x, CR-56x, CD200 */ + { + j = (D_S[d].firmware_version[0] & 0x0F) * 100 + + (D_S[d].firmware_version[2] & 0x0F) *10 + + (D_S[d].firmware_version[3] & 0x0F); + if (fam0_drive) + { + if (j<200) D_S[d].drv_type=drv_199; + else if (j<201) D_S[d].drv_type=drv_200; + else if (j<210) D_S[d].drv_type=drv_201; + else if (j<211) D_S[d].drv_type=drv_210; + else if (j<300) D_S[d].drv_type=drv_211; + else if (j>=300) D_S[d].drv_type=drv_300; + } + else if (fam1_drive) + { + if (j<100) D_S[d].drv_type=drv_099; + else + { + D_S[d].drv_type=drv_100; + if ((j!=500)||(j!=102)) ask_mail(); + } + } + else if (fam2_drive) + { + msg(DBG_INF,"new drive CD200 (%s)detected.\n", D_S[d].firmware_version); + msg(DBG_INF,"support is not fulfilled yet - audio should work.\n"); + if ((j!=101)&&(j!=35)) ask_mail(); /* only 1.01 and 0.35 known at time */ + } } - } - DPRINTF((DBG_LCS,"SBPCD: drive type %02X\n",DriveStruct[d].drv_type)); - DPRINTF((DBG_INI,"SBPCD: check_version done.\n")); - return (0); + msg(DBG_LCS,"drive type %02X\n",D_S[d].drv_type); + msg(DBG_INI,"check_version done.\n"); + return (0); } /*==========================================================================*/ -static int switch_drive(int i) -{ - d=i; - if (DriveStruct[d].drv_id!=-1) - { - OUT(CDo_enable,DriveStruct[d].drv_sel); - DPRINTF((DBG_DID,"SBPCD: drive %d (ID=%d) activated.\n", i, DriveStruct[d].drv_id)); - return (0); - } - else return (-1); +static void switch_drive(int i) +{ + d=i; + OUT(CDo_enable,D_S[d].drv_sel); + msg(DBG_DID,"drive %d (ID=%d) activated.\n", i, D_S[d].drv_id); + return; } /*==========================================================================*/ +#ifdef PATH_CHECK /* - * probe for the presence of drives on the selected controller + * probe for the presence of an interface card */ -static int check_drives(void) +static int check_card(int port) { - int i, j; - char *printk_header=""; - - DPRINTF((DBG_INI,"SBPCD: check_drives entered.\n")); - - ndrives=0; - for (j=0;j>1; - else DriveStruct[ndrives].drv_sel=j; - switch_drive(ndrives); - DPRINTF((DBG_INI,"SBPCD: check_drives: drive %d (ID=%d) activated.\n",ndrives,j)); - i=check_version(); - if (i<0) DPRINTF((DBG_INI,"SBPCD: check_version returns %d.\n",i)); - else - { - DriveStruct[d].drv_options=drv_pattern[j]; - if (fam0L_drive) DriveStruct[d].drv_options&=~(speed_auto|speed_300|speed_150); - printk("%sDrive %d (ID=%d): %.9s (%.4s)\n", printk_header, d, - DriveStruct[d].drv_id, - DriveStruct[d].drive_model, - DriveStruct[d].firmware_version); - printk_header=" - "; - ndrives++; - } - - } - for (j=ndrives;j0;i--) OUT(port+0,0); + for (k=0;k0;i--) + { + if (inb(port+1)&s_not_result_ready) continue; + response[k]=inb(port+0); + break; + } + } + for (i=0;i0;i--) OUT(port+0,0); + for (k=0;k0;i--) + { + if (inb(port+1)&s_not_result_ready) continue; + response[k]=inb(port+0); + break; + } + } + for (i=0;i0;i--) OUT(port+0,0); + for (k=0;k0;i--) + { + if (inb(port+1)&s_not_result_ready) continue; + response[k]=inb(port+0); + break; + } + } + for (i=0;i0;i--) OUT(port+0,0); + for (k=0;k0;i--) + { + if (inb(port+1)&s_not_result_ready) continue; + response[k]=inb(port+0); + break; + } + } + for (i=0;i>1; + else D_S[ndrives].drv_sel=j; + switch_drive(ndrives); + msg(DBG_INI,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j); + msg(DBG_000,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j); + i=check_version(); + if (i<0) msg(DBG_INI,"check_version returns %d.\n",i); + else + { + D_S[d].drv_options=drv_pattern[j]; + if (fam0L_drive) D_S[d].drv_options&=~(speed_auto|speed_300|speed_150); + msg(DBG_INF, "Drive %d (ID=%d): %.9s (%.4s) at 0x%03X (type %d)\n", + d, + D_S[d].drv_id, + D_S[d].drive_model, + D_S[d].firmware_version, + CDo_command, + sbpro_type); + ndrives++; + } + } + for (j=ndrives;j=0) break; - DPRINTF((DBG_INF,"SBPCD: DiskInfo: ReadCapacity #%d returns %d\n", j, i)); - i=DriveReset(); - } - if (j==LOOP_COUNT) return (-2); /* give up */ - - i=xx_ReadTocDescr(); - if (i<0) - { - DPRINTF((DBG_INF,"SBPCD: DiskInfo: ReadTocDescr returns %d\n", i)); - return (i); - } - i=ReadToC(); - if (i<0) - { - DPRINTF((DBG_INF,"SBPCD: DiskInfo: ReadToC returns %d\n", i)); - return (i); - } - i=yy_CheckMultiSession(); - if (i<0) - { - DPRINTF((DBG_INF,"SBPCD: DiskInfo: yy_CheckMultiSession returns %d\n", i)); - return (i); - } - i=xx_ReadTocEntry(DriveStruct[d].n_first_track); - if (i<0) - { - DPRINTF((DBG_INF,"SBPCD: DiskInfo: xx_ReadTocEntry(1) returns %d\n", i)); - return (i); - } - i=xx_ReadUPC(); - if (i<0) - { - DPRINTF((DBG_INF,"SBPCD: DiskInfo: xx_ReadUPC returns %d\n", i)); - return (i); - } -#ifdef XA_TEST2 - if ((fam0L_drive) && (DriveStruct[d].xa_byte==0x20)) /* XA disk with old drive */ - { - xx_ModeSelect(CD_FRAMESIZE_XA); - xx_ModeSense(); - } -#endif XA_TEST2 - - return (0); +#define LOOP_COUNT 10 /* needed for some "old" drives */ + + msg(DBG_000,"DiskInfo entered.\n"); + for (j=1;j=0) break; + msg(DBG_INF,"DiskInfo: ReadCapacity #%d returns %d\n", j, i); + i=cc_DriveReset(); + } + if (j==LOOP_COUNT) return (-33); /* give up */ + + i=cc_ReadTocDescr(); + if (i<0) + { + msg(DBG_INF,"DiskInfo: ReadTocDescr returns %d\n", i); + return (i); + } + i=ReadToC(); + if (i<0) + { + msg(DBG_INF,"DiskInfo: ReadToC returns %d\n", i); + return (i); + } + i=cc_CheckMultiSession(); + if (i<0) + { + msg(DBG_INF,"DiskInfo: cc_CheckMultiSession returns %d\n", i); + return (i); + } + if (D_S[d].f_multisession) D_S[d].sbp_bufsiz=1; /* possibly a weird PhotoCD */ + + i=cc_ReadTocEntry(D_S[d].n_first_track); + if (i<0) + { + msg(DBG_INF,"DiskInfo: cc_ReadTocEntry(1) returns %d\n", i); + return (i); + } + i=cc_ReadUPC(); + if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i); + if ((fam0L_drive) && (D_S[d].xa_byte==0x20)) + { + /* XA disk with old drive */ + cc_ModeSelect(CD_FRAMESIZE_XA); + cc_ModeSense(); + } + if (famT_drive) cc_prep_mode_T(); + msg(DBG_000,"DiskInfo done.\n"); + return (0); } /*==========================================================================*/ +#if FUTURE /* * called always if driver gets entered * returns 0 or ERROR2 or ERROR15 */ static int prepare(u_char func, u_char subfunc) { - int i; - - if (fam0L_drive) - { - i=inb(CDi_status); - if (i&s_attention) GetStatus(); - } - else if (fam1_drive) GetStatus(); - else if (fam2_drive) GetStatus(); - if (DriveStruct[d].CD_changed==0xFF) - { -#if MANY_SESSION -#else - DriveStruct[d].diskstate_flags=0; -#endif MANY_SESSION - DriveStruct[d].audio_state=0; - if (!st_diskok) - { - i=check_allowed1(func,subfunc); - if (i<0) return (-2); - } - else - { - i=check_allowed3(func,subfunc); - if (i<0) - { - DriveStruct[d].CD_changed=1; - return (-15); - } + int i; + + if (fam0L_drive) + { + i=inb(CDi_status); + if (i&s_attention) GetStatus(); + } + else if (fam1_drive) GetStatus(); + else if (fam2_drive) GetStatus(); + else if (famT_drive) GetStatus(); + if (D_S[d].CD_changed==0xFF) + { + D_S[d].diskstate_flags=0; + D_S[d].audio_state=0; + if (!st_diskok) + { + i=check_allowed1(func,subfunc); + if (i<0) return (-2); + } + else + { + i=check_allowed3(func,subfunc); + if (i<0) + { + D_S[d].CD_changed=1; + return (-15); + } + } } - } - else - { - if (!st_diskok) + else { -#if MANY_SESSION -#else - DriveStruct[d].diskstate_flags=0; -#endif MANY_SESSION - DriveStruct[d].audio_state=0; - i=check_allowed1(func,subfunc); - if (i<0) return (-2); - } - else - { - if (st_busy) - { - if (DriveStruct[d].audio_state!=audio_pausing) - { - i=check_allowed2(func,subfunc); - if (i<0) return (-2); - } - } - else - { - if (DriveStruct[d].audio_state==audio_playing) seek_pos_audio_end(); - DriveStruct[d].audio_state=0; - } - if (!frame_size_valid) - { - i=DiskInfo(); - if (i<0) + if (!st_diskok) { -#if MANY_SESSION -#else - DriveStruct[d].diskstate_flags=0; -#endif MANY_SESSION - DriveStruct[d].audio_state=0; - i=check_allowed1(func,subfunc); - if (i<0) return (-2); + D_S[d].diskstate_flags=0; + D_S[d].audio_state=0; + i=check_allowed1(func,subfunc); + if (i<0) return (-2); + } + else + { + if (st_busy) + { + if (D_S[d].audio_state!=audio_pausing) + { + i=check_allowed2(func,subfunc); + if (i<0) return (-2); + } + } + else + { + if (D_S[d].audio_state==audio_playing) seek_pos_audio_end(); + D_S[d].audio_state=0; + } + if (!frame_size_valid) + { + i=DiskInfo(); + if (i<0) + { + D_S[d].diskstate_flags=0; + D_S[d].audio_state=0; + i=check_allowed1(func,subfunc); + if (i<0) return (-2); + } + } } - } - } - } - return (0); -} -/*==========================================================================*/ -static int xx_PlayAudio(int pos_audio_start,int pos_audio_end) -{ - int i, n; - - if (DriveStruct[d].audio_state==audio_playing) return (-EINVAL); - clr_cmdbuf(); - if (famL_drive) - { - drvcmd[0]=CMDL_PLAY; - i=msf2blk(pos_audio_start); - n=msf2blk(pos_audio_end)+1-i; - drvcmd[1]=(i>>16)&0x00FF; - drvcmd[2]=(i>>8)&0x00FF; - drvcmd[3]=i&0x00FF; - drvcmd[4]=(n>>16)&0x00FF; - drvcmd[5]=(n>>8)&0x00FF; - drvcmd[6]=n&0x00FF; - flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | - f_ResponseStatus | f_obey_p_check | f_wait_if_busy; - } - else - { - if (fam1_drive) - { - drvcmd[0]=CMD1_PLAY_MSF; - flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | - f_obey_p_check | f_wait_if_busy; - } - else if (fam2_drive) - { - drvcmd[0]=CMD2_PLAY_MSF; - flags_cmd_out = f_putcmd | f_ResponseStatus; - } - else if (fam0_drive) - { - drvcmd[0]=CMD0_PLAY_MSF; - flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta | - f_ResponseStatus | f_obey_p_check | f_wait_if_busy; - } - drvcmd[1]=(pos_audio_start>>16)&0x00FF; - drvcmd[2]=(pos_audio_start>>8)&0x00FF; - drvcmd[3]=pos_audio_start&0x00FF; - drvcmd[4]=(pos_audio_end>>16)&0x00FF; - drvcmd[5]=(pos_audio_end>>8)&0x00FF; - drvcmd[6]=pos_audio_end&0x00FF; } - response_count=0; - i=cmd_out(7); - return (i); + return (0); } -/*==========================================================================*/ +#endif FUTURE /*==========================================================================*/ /*==========================================================================*/ /* @@ -3029,43 +3727,43 @@ */ static int sbp_status(void) { - int st; - - st=ResponseStatus(); - if (st<0) - { - DPRINTF((DBG_INF,"SBPCD: sbp_status: timeout.\n")); - return (0); - } - - if (!st_spinning) DPRINTF((DBG_SPI,"SBPCD: motor got off - ignoring.\n")); - - if (st_check) - { - DPRINTF((DBG_INF,"SBPCD: st_check detected - retrying.\n")); - return (0); - } - if (!st_door_closed) - { - DPRINTF((DBG_INF,"SBPCD: door is open - retrying.\n")); - return (0); - } - if (!st_caddy_in) - { - DPRINTF((DBG_INF,"SBPCD: disk removed - retrying.\n")); - return (0); - } - if (!st_diskok) - { - DPRINTF((DBG_INF,"SBPCD: !st_diskok detected - retrying.\n")); - return (0); - } - if (st_busy) - { - DPRINTF((DBG_INF,"SBPCD: st_busy detected - retrying.\n")); - return (0); - } - return (1); + int st; + + st=ResponseStatus(); + if (st<0) + { + msg(DBG_INF,"sbp_status: timeout.\n"); + return (0); + } + + if (!st_spinning) msg(DBG_SPI,"motor got off - ignoring.\n"); + + if (st_check) + { + msg(DBG_INF,"st_check detected - retrying.\n"); + return (0); + } + if (!st_door_closed) + { + msg(DBG_INF,"door is open - retrying.\n"); + return (0); + } + if (!st_caddy_in) + { + msg(DBG_INF,"disk removed - retrying.\n"); + return (0); + } + if (!st_diskok) + { + msg(DBG_INF,"!st_diskok detected - retrying.\n"); + return (0); + } + if (st_busy) + { + msg(DBG_INF,"st_busy detected - retrying.\n"); + return (0); + } + return (1); } /*==========================================================================*/ @@ -3077,507 +3775,546 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) { - int i, st; - - DPRINTF((DBG_IO2,"SBPCD: ioctl(%d, 0x%08lX, 0x%08lX)\n", - MINOR(inode->i_rdev), cmd, arg)); - if (!inode) return (-EINVAL); - i=MINOR(inode->i_rdev); - if ((i<0) || (i>=NR_SBPCD) || (DriveStruct[i].drv_id==-1)) - { - printk("SBPCD: ioctl: bad device: %04X\n", inode->i_rdev); - return (-ENXIO); /* no such drive */ - } - switch_drive(i); - - st=GetStatus(); - if (st<0) return (-EIO); - - if (!toc_valid) - { - i=DiskInfo(); - if (i<0) return (-EIO); /* error reading TOC */ - } - - DPRINTF((DBG_IO2,"SBPCD: ioctl: device %d, request %04X\n",i,cmd)); - switch (cmd) /* Sun-compatible */ - { - case DDIOCSDBG: /* DDI Debug */ - if (! suser()) return (-EPERM); - i = verify_area(VERIFY_READ, (int *) arg, sizeof(int)); - if (i>=0) i=sbpcd_dbg_ioctl(arg,1); - return (i); - - case CDROMPAUSE: /* Pause the drive */ - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPAUSE entered.\n")); - /* pause the drive unit when it is currently in PLAY mode, */ - /* or reset the starting and ending locations when in PAUSED mode. */ - /* If applicable, at the next stopping point it reaches */ - /* the drive will discontinue playing. */ - switch (DriveStruct[d].audio_state) - { - case audio_playing: - if (famL_drive) i=xx_ReadSubQ(); - else i=xx_Pause_Resume(1); - if (i<0) return (-EIO); - if (famL_drive) i=xx_Pause_Resume(1); - else i=xx_ReadSubQ(); - if (i<0) return (-EIO); - DriveStruct[d].pos_audio_start=DriveStruct[d].SubQ_run_tot; - DriveStruct[d].audio_state=audio_pausing; - return (0); - case audio_pausing: - i=xx_Seek(DriveStruct[d].pos_audio_start,1); - if (i<0) return (-EIO); - return (0); - default: - return (-EINVAL); + int i, st; + + msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08lX)\n", + MINOR(inode->i_rdev), cmd, arg); + if (!inode) return (-EINVAL); + i=MINOR(inode->i_rdev); + if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) + { + msg(DBG_INF, "ioctl: bad device: %04X\n", inode->i_rdev); + return (-ENXIO); /* no such drive */ } - - case CDROMRESUME: /* resume paused audio play */ - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMRESUME entered.\n")); - /* resume playing audio tracks when a previous PLAY AUDIO call has */ - /* been paused with a PAUSE command. */ - /* It will resume playing from the location saved in SubQ_run_tot. */ - if (DriveStruct[d].audio_state!=audio_pausing) return -EINVAL; - if (famL_drive) - i=xx_PlayAudio(DriveStruct[d].pos_audio_start, - DriveStruct[d].pos_audio_end); - else i=xx_Pause_Resume(3); - if (i<0) return (-EIO); - DriveStruct[d].audio_state=audio_playing; - return (0); - - case CDROMPLAYMSF: - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPLAYMSF entered.\n")); - if (DriveStruct[d].audio_state==audio_playing) - { - i=xx_Pause_Resume(1); - if (i<0) return (-EIO); - i=xx_ReadSubQ(); - if (i<0) return (-EIO); - DriveStruct[d].pos_audio_start=DriveStruct[d].SubQ_run_tot; - i=xx_Seek(DriveStruct[d].pos_audio_start,1); - } - st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_msf)); - if (st) return (st); - memcpy_fromfs(&msf, (void *) arg, sizeof(struct cdrom_msf)); - /* values come as msf-bin */ - DriveStruct[d].pos_audio_start = (msf.cdmsf_min0<<16) | + if (d!=i) switch_drive(i); + +#if 0 + st=GetStatus(); + if (st<0) return (-EIO); + + if (!toc_valid) + { + i=DiskInfo(); + if (i<0) return (-EIO); /* error reading TOC */ + } +#endif + + msg(DBG_IO2,"ioctl: device %d, request %04X\n",i,cmd); + switch (cmd) /* Sun-compatible */ + { + case DDIOCSDBG: /* DDI Debug */ + if (!suser()) return (-EPERM); + i=sbpcd_dbg_ioctl(arg,1); + return (i); + + case CDROMPAUSE: /* Pause the drive */ + msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n"); + /* pause the drive unit when it is currently in PLAY mode, */ + /* or reset the starting and ending locations when in PAUSED mode. */ + /* If applicable, at the next stopping point it reaches */ + /* the drive will discontinue playing. */ + switch (D_S[d].audio_state) + { + case audio_playing: + if (famL_drive) i=cc_ReadSubQ(); + else i=cc_Pause_Resume(1); + if (i<0) return (-EIO); + if (famL_drive) i=cc_Pause_Resume(1); + else i=cc_ReadSubQ(); + if (i<0) return (-EIO); + D_S[d].pos_audio_start=D_S[d].SubQ_run_tot; + D_S[d].audio_state=audio_pausing; + return (0); + case audio_pausing: + i=cc_Seek(D_S[d].pos_audio_start,1); + if (i<0) return (-EIO); + return (0); + default: + return (-EINVAL); + } + + case CDROMRESUME: /* resume paused audio play */ + msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n"); + /* resume playing audio tracks when a previous PLAY AUDIO call has */ + /* been paused with a PAUSE command. */ + /* It will resume playing from the location saved in SubQ_run_tot. */ + if (D_S[d].audio_state!=audio_pausing) return -EINVAL; + if (famL_drive) + i=cc_PlayAudio(D_S[d].pos_audio_start, + D_S[d].pos_audio_end); + else i=cc_Pause_Resume(3); + if (i<0) return (-EIO); + D_S[d].audio_state=audio_playing; + return (0); + + case CDROMPLAYMSF: + msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n"); + if (D_S[d].audio_state==audio_playing) + { + i=cc_Pause_Resume(1); + if (i<0) return (-EIO); + i=cc_ReadSubQ(); + if (i<0) return (-EIO); + D_S[d].pos_audio_start=D_S[d].SubQ_run_tot; + i=cc_Seek(D_S[d].pos_audio_start,1); + } + st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_msf)); + if (st) return (st); + memcpy_fromfs(&msf, (void *) arg, sizeof(struct cdrom_msf)); + /* values come as msf-bin */ + D_S[d].pos_audio_start = (msf.cdmsf_min0<<16) | (msf.cdmsf_sec0<<8) | - msf.cdmsf_frame0; - DriveStruct[d].pos_audio_end = (msf.cdmsf_min1<<16) | - (msf.cdmsf_sec1<<8) | - msf.cdmsf_frame1; - DPRINTF((DBG_IOX,"SBPCD: ioctl: CDROMPLAYMSF %08X %08X\n", - DriveStruct[d].pos_audio_start,DriveStruct[d].pos_audio_end)); - i=xx_PlayAudio(DriveStruct[d].pos_audio_start,DriveStruct[d].pos_audio_end); - DPRINTF((DBG_IOC,"SBPCD: ioctl: xx_PlayAudio returns %d\n",i)); + msf.cdmsf_frame0; + D_S[d].pos_audio_end = (msf.cdmsf_min1<<16) | + (msf.cdmsf_sec1<<8) | + msf.cdmsf_frame1; + msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n", + D_S[d].pos_audio_start,D_S[d].pos_audio_end); + i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end); + msg(DBG_IOC,"ioctl: cc_PlayAudio returns %d\n",i); #if 0 - if (i<0) return (-EIO); + if (i<0) return (-EIO); #endif 0 - DriveStruct[d].audio_state=audio_playing; - return (0); - - case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPLAYTRKIND entered.\n")); - if (DriveStruct[d].audio_state==audio_playing) - { - DPRINTF((DBG_IOX,"SBPCD: CDROMPLAYTRKIND: already audio_playing.\n")); - return (0); - return (-EINVAL); - } - st=verify_area(VERIFY_READ,(void *) arg,sizeof(struct cdrom_ti)); - if (st<0) - { - DPRINTF((DBG_IOX,"SBPCD: CDROMPLAYTRKIND: verify_area error.\n")); - return (st); - } - memcpy_fromfs(&ti,(void *) arg,sizeof(struct cdrom_ti)); - DPRINTF((DBG_IOX,"SBPCD: ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n", - ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1)); - if (ti.cdti_trk0DriveStruct[d].n_last_track) return (-EINVAL); - if (ti.cdti_trk1DriveStruct[d].n_last_track) ti.cdti_trk1=DriveStruct[d].n_last_track; - DriveStruct[d].pos_audio_start=DriveStruct[d].TocBuffer[ti.cdti_trk0].address; - DriveStruct[d].pos_audio_end=DriveStruct[d].TocBuffer[ti.cdti_trk1+1].address; - i=xx_PlayAudio(DriveStruct[d].pos_audio_start,DriveStruct[d].pos_audio_end); + D_S[d].audio_state=audio_playing; + return (0); + + case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ + msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n"); + if (D_S[d].audio_state==audio_playing) + { + msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n"); + return (0); + return (-EINVAL); + } + st=verify_area(VERIFY_READ,(void *) arg,sizeof(struct cdrom_ti)); + if (st<0) + { + msg(DBG_IOX,"CDROMPLAYTRKIND: verify_area error.\n"); + return (st); + } + memcpy_fromfs(&ti,(void *) arg,sizeof(struct cdrom_ti)); + msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n", + ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1); + if (ti.cdti_trk0D_S[d].n_last_track) return (-EINVAL); + if (ti.cdti_trk1D_S[d].n_last_track) ti.cdti_trk1=D_S[d].n_last_track; + D_S[d].pos_audio_start=D_S[d].TocBuffer[ti.cdti_trk0].address; + D_S[d].pos_audio_end=D_S[d].TocBuffer[ti.cdti_trk1+1].address; + i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end); #if 0 - if (i<0) return (-EIO); + if (i<0) return (-EIO); #endif 0 - DriveStruct[d].audio_state=audio_playing; - return (0); - - case CDROMREADTOCHDR: /* Read the table of contents header */ - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADTOCHDR entered.\n")); - tochdr.cdth_trk0=DriveStruct[d].n_first_track; - tochdr.cdth_trk1=DriveStruct[d].n_last_track; - st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_tochdr)); - if (st) return (st); - memcpy_tofs((void *) arg, &tochdr, sizeof(struct cdrom_tochdr)); - return (0); - - case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADTOCENTRY entered.\n")); - st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_tocentry)); - if (st) return (st); - memcpy_fromfs(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry)); - i=tocentry.cdte_track; - if (i==CDROM_LEADOUT) i=DriveStruct[d].n_last_track+1; - else if (iDriveStruct[d].n_last_track) return (-EINVAL); - tocentry.cdte_adr=DriveStruct[d].TocBuffer[i].ctl_adr&0x0F; - tocentry.cdte_ctrl=(DriveStruct[d].TocBuffer[i].ctl_adr>>4)&0x0F; - tocentry.cdte_datamode=DriveStruct[d].TocBuffer[i].format; - if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */ - { tocentry.cdte_addr.msf.minute=(DriveStruct[d].TocBuffer[i].address>>16)&0x00FF; - tocentry.cdte_addr.msf.second=(DriveStruct[d].TocBuffer[i].address>>8)&0x00FF; - tocentry.cdte_addr.msf.frame=DriveStruct[d].TocBuffer[i].address&0x00FF; - } - else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ - tocentry.cdte_addr.lba=msf2blk(DriveStruct[d].TocBuffer[i].address); - else return (-EINVAL); - st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_tocentry)); - if (st) return (st); - memcpy_tofs((void *) arg, &tocentry, sizeof(struct cdrom_tocentry)); - return (0); - - case CDROMSTOP: /* Spin down the drive */ - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMSTOP entered.\n")); - i=xx_Pause_Resume(1); - DriveStruct[d].audio_state=0; - return (0); - - case CDROMSTART: /* Spin up the drive */ - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMSTART entered.\n")); - xx_SpinUp(); - DriveStruct[d].audio_state=0; - return (0); - - case CDROMEJECT: - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMEJECT entered.\n")); - if (fam0_drive) return (0); - do i=yy_LockDoor(0); - while (i!=0); - DriveStruct[d].open_count=0; /* to get it locked next time again */ - i=yy_SpinDown(); - DPRINTF((DBG_IOX,"SBPCD: ioctl: yy_SpinDown returned %d.\n", i)); - if (i<0) return (-EIO); - DriveStruct[d].CD_changed=0xFF; - DriveStruct[d].diskstate_flags=0; - DriveStruct[d].audio_state=0; - return (0); - - case CDROMEJECT_SW: - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMEJECT_SW entered.\n")); - if (fam0_drive) return (0); - DriveStruct[d].f_eject=arg; - return (0); - - case CDROMVOLCTRL: /* Volume control */ - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMVOLCTRL entered.\n")); - st=verify_area(VERIFY_READ,(void *) arg,sizeof(volctrl)); - if (st) return (st); - memcpy_fromfs(&volctrl,(char *) arg,sizeof(volctrl)); - DriveStruct[d].vol_chan0=0; - DriveStruct[d].vol_ctrl0=volctrl.channel0; - DriveStruct[d].vol_chan1=1; - DriveStruct[d].vol_ctrl1=volctrl.channel1; - i=xx_SetVolume(); - return (0); - - case CDROMSUBCHNL: /* Get subchannel info */ - DPRINTF((DBG_IOS,"SBPCD: ioctl: CDROMSUBCHNL entered.\n")); - if ((st_spinning)||(!subq_valid)) { i=xx_ReadSubQ(); - if (i<0) return (-EIO); - } - st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl)); - if (st) return (st); - memcpy_fromfs(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); - switch (DriveStruct[d].audio_state) - { - case audio_playing: - SC.cdsc_audiostatus=CDROM_AUDIO_PLAY; - break; - case audio_pausing: - SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED; - break; - default: - SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS; - break; - } - SC.cdsc_adr=DriveStruct[d].SubQ_ctl_adr; - SC.cdsc_ctrl=DriveStruct[d].SubQ_ctl_adr>>4; - SC.cdsc_trk=bcd2bin(DriveStruct[d].SubQ_trk); - SC.cdsc_ind=bcd2bin(DriveStruct[d].SubQ_pnt_idx); - if (SC.cdsc_format==CDROM_LBA) - { - SC.cdsc_absaddr.lba=msf2blk(DriveStruct[d].SubQ_run_tot); - SC.cdsc_reladdr.lba=msf2blk(DriveStruct[d].SubQ_run_trk); - } - else /* not only if (SC.cdsc_format==CDROM_MSF) */ - { - SC.cdsc_absaddr.msf.minute=(DriveStruct[d].SubQ_run_tot>>16)&0x00FF; - SC.cdsc_absaddr.msf.second=(DriveStruct[d].SubQ_run_tot>>8)&0x00FF; - SC.cdsc_absaddr.msf.frame=DriveStruct[d].SubQ_run_tot&0x00FF; - SC.cdsc_reladdr.msf.minute=(DriveStruct[d].SubQ_run_trk>>16)&0x00FF; - SC.cdsc_reladdr.msf.second=(DriveStruct[d].SubQ_run_trk>>8)&0x00FF; - SC.cdsc_reladdr.msf.frame=DriveStruct[d].SubQ_run_trk&0x00FF; - } - memcpy_tofs((void *) arg, &SC, sizeof(struct cdrom_subchnl)); - DPRINTF((DBG_IOS,"SBPCD: CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n", - SC.cdsc_format,SC.cdsc_audiostatus, - SC.cdsc_adr,SC.cdsc_ctrl, - SC.cdsc_trk,SC.cdsc_ind, - SC.cdsc_absaddr,SC.cdsc_reladdr)); - return (0); - - case CDROMREADMODE1: - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADMODE1 requested.\n")); - xx_ModeSelect(CD_FRAMESIZE); - xx_ModeSense(); - DriveStruct[d].mode=READ_M1; - return (0); - - case CDROMREADMODE2: /* not usable at the moment */ - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADMODE2 requested.\n")); - xx_ModeSelect(CD_FRAMESIZE_XA); - xx_ModeSense(); - DriveStruct[d].mode=READ_M2; - return (0); - - case CDROMREADAUDIO: - { /* start of CDROMREADAUDIO */ - int i=0, j=0, frame, block; - u_int try=0; - u_long timeout; - u_char *p; - u_int data_tries = 0; - u_int data_waits = 0; - u_int data_retrying = 0; - int status_tries; - int error_flag; - - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADAUDIO requested.\n")); - if (fam0_drive) return (-EINVAL); - if (famL_drive) return (-EINVAL); - if (fam2_drive) return (-EINVAL); - if (DriveStruct[d].aud_buf==NULL) return (-EINVAL); - i=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_read_audio)); - if (i) return (i); - memcpy_fromfs(&read_audio, (void *) arg, sizeof(struct cdrom_read_audio)); - if (read_audio.nframes>SBP_BUFFER_AUDIO_FRAMES) return (-EINVAL); - i=verify_area(VERIFY_WRITE, read_audio.buf, - read_audio.nframes*CD_FRAMESIZE_RAW); - if (i) return (i); - - if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */ - block=msf2lba(&read_audio.addr.msf.minute); - else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */ - block=read_audio.addr.lba; - else return (-EINVAL); - i=yy_SetSpeed(speed_150,0,0); - if (i) DPRINTF((DBG_AUD,"SBPCD: read_audio: SetSpeed error %d\n", i)); - DPRINTF((DBG_AUD,"SBPCD: read_audio: lba: %d, msf: %06X\n", - block, blk2msf(block))); - DPRINTF((DBG_AUD,"SBPCD: read_audio: before xx_ReadStatus.\n")); - while (busy_data) sbp_sleep(10); /* wait a bit */ - busy_audio=1; - error_flag=0; - for (data_tries=5; data_tries>0; data_tries--) - { - DPRINTF((DBG_AUD,"SBPCD: data_tries=%d ...\n", data_tries)); - DriveStruct[d].mode=READ_AU; - xx_ModeSelect(CD_FRAMESIZE_RAW); - xx_ModeSense(); - for (status_tries=3; status_tries > 0; status_tries--) - { - flags_cmd_out |= f_respo3; - xx_ReadStatus(); - if (sbp_status() != 0) break; - sbp_sleep(1); /* wait a bit, try again */ - } - if (status_tries == 0) - { - DPRINTF((DBG_AUD,"SBPCD: read_audio: sbp_status: failed after 3 tries.\n")); - continue; - } - DPRINTF((DBG_AUD,"SBPCD: read_audio: sbp_status: ok.\n")); - - flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; - if (fam0L_drive) - { - flags_cmd_out |= f_lopsta | f_getsta | f_bit1; - cmd_type=READ_M2; - drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ - drvcmd[1]=(block>>16)&0x000000ff; - drvcmd[2]=(block>>8)&0x000000ff; - drvcmd[3]=block&0x000000ff; - drvcmd[4]=0; - drvcmd[5]=read_audio.nframes; /* # of frames */ - drvcmd[6]=0; - } - else if (fam1_drive) - { - drvcmd[0]=CMD1_READ; /* "read frames", new drives */ - lba2msf(block,&drvcmd[1]); /* msf-bin format required */ - drvcmd[4]=0; - drvcmd[5]=0; - drvcmd[6]=read_audio.nframes; /* # of frames */ - } - else if (fam2_drive) /* CD200: not implemented yet */ - { - } - DPRINTF((DBG_AUD,"SBPCD: read_audio: before giving \"read\" command.\n")); - for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]); - sbp_sleep(0); - DPRINTF((DBG_AUD,"SBPCD: read_audio: after giving \"read\" command.\n")); - for (frame=1;frame<2 && !error_flag; frame++) - { - try=maxtim_data; - for (timeout=jiffies+900; ; ) - { - for ( ; try!=0;try--) - { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) break; - if (!(j&s_not_result_ready)) break; - if (fam0L_drive) if (j&s_attention) break; - } - if (try != 0 || timeout <= jiffies) break; - if (data_retrying == 0) data_waits++; - data_retrying = 1; - sbp_sleep(1); - try = 1; - } - if (try==0) - { - DPRINTF((DBG_INF,"SBPCD: read_audio: sbp_data: CDi_status timeout.\n")); - error_flag++; - break; - } - DPRINTF((DBG_AUD,"SBPCD: read_audio: sbp_data: CDi_status ok.\n")); - if (j&s_not_data_ready) - { - printk("SBPCD: read_audio: sbp_data: DATA_READY timeout.\n"); - error_flag++; - break; - } - DPRINTF((DBG_AUD,"SBPCD: read_audio: before reading data.\n")); - error_flag=0; - p = DriveStruct[d].aud_buf; - if (sbpro_type==1) OUT(CDo_sel_i_d,1); -#if 0 - cli(); -#endif - READ_DATA(CDi_data, p, read_audio.nframes*CD_FRAMESIZE_RAW); -#if 0 - sti(); -#endif - if (sbpro_type==1) OUT(CDo_sel_i_d,0); - data_retrying = 0; - } - DPRINTF((DBG_AUD,"SBPCD: read_audio: after reading data.\n")); - if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ - { - DPRINTF((DBG_AUD,"SBPCD: read_audio: read aborted by drive\n")); + D_S[d].audio_state=audio_playing; + return (0); + + case CDROMREADTOCHDR: /* Read the table of contents header */ + msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n"); + tochdr.cdth_trk0=D_S[d].n_first_track; + tochdr.cdth_trk1=D_S[d].n_last_track; + st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_tochdr)); + if (st) return (st); + memcpy_tofs((void *) arg, &tochdr, sizeof(struct cdrom_tochdr)); + return (0); + + case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ + msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n"); + st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_tocentry)); + if (st) return (st); + memcpy_fromfs(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry)); + i=tocentry.cdte_track; + if (i==CDROM_LEADOUT) i=D_S[d].n_last_track+1; + else if (iD_S[d].n_last_track) return (-EINVAL); + tocentry.cdte_adr=D_S[d].TocBuffer[i].ctl_adr&0x0F; + tocentry.cdte_ctrl=(D_S[d].TocBuffer[i].ctl_adr>>4)&0x0F; + tocentry.cdte_datamode=D_S[d].TocBuffer[i].format; + if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */ + { + tocentry.cdte_addr.msf.minute=(D_S[d].TocBuffer[i].address>>16)&0x00FF; + tocentry.cdte_addr.msf.second=(D_S[d].TocBuffer[i].address>>8)&0x00FF; + tocentry.cdte_addr.msf.frame=D_S[d].TocBuffer[i].address&0x00FF; + } + else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ + tocentry.cdte_addr.lba=msf2blk(D_S[d].TocBuffer[i].address); + else return (-EINVAL); + st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_tocentry)); + if (st) return (st); + memcpy_tofs((void *) arg, &tocentry, sizeof(struct cdrom_tocentry)); + return (0); + + case CDROMRESET: /* hard reset the drive */ + msg(DBG_IOC,"ioctl: CDROMRESET entered.\n"); + i=DriveReset(); + D_S[d].audio_state=0; + return (i); + + case CDROMSTOP: /* Spin down the drive */ + msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n"); + i=cc_Pause_Resume(1); + D_S[d].audio_state=0; + return (i); + + case CDROMSTART: /* Spin up the drive */ + msg(DBG_IOC,"ioctl: CDROMSTART entered.\n"); + cc_SpinUp(); + D_S[d].audio_state=0; + return (0); + + case CDROMEJECT: + msg(DBG_IOC,"ioctl: CDROMEJECT entered.\n"); + if (fam0_drive) return (0); + i=UnLockDoor(); + D_S[d].open_count=-9; /* to get it locked next time again */ + i=cc_SpinDown(); + msg(DBG_IOX,"ioctl: cc_SpinDown returned %d.\n", i); + msg(DBG_TEA,"ioctl: cc_SpinDown returned %d.\n", i); + if (i<0) return (-EIO); + D_S[d].CD_changed=0xFF; + D_S[d].diskstate_flags=0; + D_S[d].audio_state=0; + return (0); + + case CDROMEJECT_SW: + msg(DBG_IOC,"ioctl: CDROMEJECT_SW entered.\n"); + if (fam0_drive) return (0); + D_S[d].f_eject=arg; + return (0); + + case CDROMVOLCTRL: /* Volume control */ + msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n"); + st=verify_area(VERIFY_READ,(void *) arg,sizeof(volctrl)); + if (st) return (st); + memcpy_fromfs(&volctrl,(char *) arg,sizeof(volctrl)); + D_S[d].vol_chan0=0; + D_S[d].vol_ctrl0=volctrl.channel0; + D_S[d].vol_chan1=1; + D_S[d].vol_ctrl1=volctrl.channel1; + i=cc_SetVolume(); + return (0); + + case CDROMVOLREAD: /* read Volume settings from drive */ + msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n"); + st=verify_area(VERIFY_WRITE,(void *)arg,sizeof(volctrl)); + if (st) return (st); + st=cc_GetVolume(); + if (st<0) return (st); + volctrl.channel0=D_S[d].vol_ctrl0; + volctrl.channel1=D_S[d].vol_ctrl1; + volctrl.channel2=0; + volctrl.channel2=0; + memcpy_tofs((void *)arg,&volctrl,sizeof(volctrl)); + return (0); + + case CDROMSUBCHNL: /* Get subchannel info */ + msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n"); + if ((st_spinning)||(!subq_valid)) { i=cc_ReadSubQ(); + if (i<0) return (-EIO); + } + st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl)); + if (st) return (st); + memcpy_fromfs(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); + switch (D_S[d].audio_state) + { + case audio_playing: + SC.cdsc_audiostatus=CDROM_AUDIO_PLAY; + break; + case audio_pausing: + SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED; + break; + default: + SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS; + break; + } + SC.cdsc_adr=D_S[d].SubQ_ctl_adr; + SC.cdsc_ctrl=D_S[d].SubQ_ctl_adr>>4; + SC.cdsc_trk=bcd2bin(D_S[d].SubQ_trk); + SC.cdsc_ind=bcd2bin(D_S[d].SubQ_pnt_idx); + if (SC.cdsc_format==CDROM_LBA) + { + SC.cdsc_absaddr.lba=msf2blk(D_S[d].SubQ_run_tot); + SC.cdsc_reladdr.lba=msf2blk(D_S[d].SubQ_run_trk); + } + else /* not only if (SC.cdsc_format==CDROM_MSF) */ + { + SC.cdsc_absaddr.msf.minute=(D_S[d].SubQ_run_tot>>16)&0x00FF; + SC.cdsc_absaddr.msf.second=(D_S[d].SubQ_run_tot>>8)&0x00FF; + SC.cdsc_absaddr.msf.frame=D_S[d].SubQ_run_tot&0x00FF; + SC.cdsc_reladdr.msf.minute=(D_S[d].SubQ_run_trk>>16)&0x00FF; + SC.cdsc_reladdr.msf.second=(D_S[d].SubQ_run_trk>>8)&0x00FF; + SC.cdsc_reladdr.msf.frame=D_S[d].SubQ_run_trk&0x00FF; + } + memcpy_tofs((void *) arg, &SC, sizeof(struct cdrom_subchnl)); + msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n", + SC.cdsc_format,SC.cdsc_audiostatus, + SC.cdsc_adr,SC.cdsc_ctrl, + SC.cdsc_trk,SC.cdsc_ind, + SC.cdsc_absaddr,SC.cdsc_reladdr); + return (0); + + case CDROMREADMODE1: + msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n"); + cc_ModeSelect(CD_FRAMESIZE); + cc_ModeSense(); + D_S[d].mode=READ_M1; + return (0); + + case CDROMREADMODE2: /* not usable at the moment */ + msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n"); + cc_ModeSelect(CD_FRAMESIZE_XA); + cc_ModeSense(); + D_S[d].mode=READ_M2; + return (0); + + case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */ + msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n"); +#ifdef MODULE + if (D_S[d].sbp_audsiz>0) + vfree(D_S[d].aud_buf); +#endif MODULE + D_S[d].aud_buf=NULL; + D_S[d].sbp_audsiz=arg; + if (D_S[d].sbp_audsiz>0) + { + D_S[d].aud_buf=(u_char *) vmalloc(D_S[d].sbp_audsiz*CD_FRAMESIZE_RAW); + if (D_S[d].aud_buf==NULL) + { + msg(DBG_INF,"audio buffer (%d frames) not available.\n",D_S[d].sbp_audsiz); + D_S[d].sbp_audsiz=0; + } + else msg(DBG_INF,"audio buffer size: %d frames.\n",D_S[d].sbp_audsiz); + } + return (D_S[d].sbp_audsiz); + + case CDROMREADAUDIO: + { /* start of CDROMREADAUDIO */ + int i=0, j=0, frame, block; + u_int try=0; + u_long timeout; + u_char *p; + u_int data_tries = 0; + u_int data_waits = 0; + u_int data_retrying = 0; + int status_tries; + int error_flag; + + msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n"); + if (fam0_drive) return (-EINVAL); + if (famL_drive) return (-EINVAL); + if (fam2_drive) return (-EINVAL); + if (famT_drive) return (-EINVAL); + if (D_S[d].aud_buf==NULL) return (-EINVAL); + i=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_read_audio)); + if (i) return (i); + memcpy_fromfs(&read_audio, (void *) arg, sizeof(struct cdrom_read_audio)); + if (read_audio.nframes>D_S[d].sbp_audsiz) return (-EINVAL); + i=verify_area(VERIFY_WRITE, read_audio.buf, + read_audio.nframes*CD_FRAMESIZE_RAW); + if (i) return (i); + + if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */ + block=msf2lba(&read_audio.addr.msf.minute); + else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */ + block=read_audio.addr.lba; + else return (-EINVAL); + i=cc_SetSpeed(speed_150,0,0); + if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i); + msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n", + block, blk2msf(block)); + msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n"); + while (busy_data) sbp_sleep(10); /* wait a bit */ + busy_audio=1; + error_flag=0; + for (data_tries=5; data_tries>0; data_tries--) + { + msg(DBG_AUD,"data_tries=%d ...\n", data_tries); + D_S[d].mode=READ_AU; + cc_ModeSelect(CD_FRAMESIZE_RAW); + cc_ModeSense(); + for (status_tries=3; status_tries > 0; status_tries--) + { + flags_cmd_out |= f_respo3; + cc_ReadStatus(); + if (sbp_status() != 0) break; + sbp_sleep(1); /* wait a bit, try again */ + } + if (status_tries == 0) + { + msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries.\n"); + continue; + } + msg(DBG_AUD,"read_audio: sbp_status: ok.\n"); + + flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; + if (fam0L_drive) + { + flags_cmd_out |= f_lopsta | f_getsta | f_bit1; + cmd_type=READ_M2; + drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ + drvcmd[1]=(block>>16)&0x000000ff; + drvcmd[2]=(block>>8)&0x000000ff; + drvcmd[3]=block&0x000000ff; + drvcmd[4]=0; + drvcmd[5]=read_audio.nframes; /* # of frames */ + drvcmd[6]=0; + } + else if (fam1_drive) + { + drvcmd[0]=CMD1_READ; /* "read frames", new drives */ + lba2msf(block,&drvcmd[1]); /* msf-bin format required */ + drvcmd[4]=0; + drvcmd[5]=0; + drvcmd[6]=read_audio.nframes; /* # of frames */ + } + else if (fam2_drive) /* CD200: not tested yet */ + { + } + else if (famT_drive) /* CD-55A: not tested yet */ + { + } + msg(DBG_AUD,"read_audio: before giving \"read\" command.\n"); + for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]); + sbp_sleep(0); + msg(DBG_AUD,"read_audio: after giving \"read\" command.\n"); + for (frame=1;frame<2 && !error_flag; frame++) + { + try=maxtim_data; + for (timeout=jiffies+900; ; ) + { + for ( ; try!=0;try--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) break; + if (!(j&s_not_result_ready)) break; + if (fam0L_drive) if (j&s_attention) break; + } + if (try != 0 || timeout <= jiffies) break; + if (data_retrying == 0) data_waits++; + data_retrying = 1; + sbp_sleep(1); + try = 1; + } + if (try==0) + { + msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n"); + error_flag++; + break; + } + msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n"); + if (j&s_not_data_ready) + { + msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n"); + error_flag++; + break; + } + msg(DBG_AUD,"read_audio: before reading data.\n"); + error_flag=0; + p = D_S[d].aud_buf; + if (sbpro_type==1) OUT(CDo_sel_i_d,1); + insb(CDi_data, p, read_audio.nframes*CD_FRAMESIZE_RAW); + if (sbpro_type==1) OUT(CDo_sel_i_d,0); + data_retrying = 0; + } + msg(DBG_AUD,"read_audio: after reading data.\n"); + if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ + { + msg(DBG_AUD,"read_audio: read aborted by drive\n"); #if 0000 - i=DriveReset(); /* ugly fix to prevent a hang */ + i=cc_DriveReset(); /* ugly fix to prevent a hang */ #else - i=xx_ReadError(); + i=cc_ReadError(); #endif 0000 - continue; - } - if (fam0L_drive) - { - i=maxtim_data; - for (timeout=jiffies+900; timeout > jiffies; timeout--) - { - for ( ;i!=0;i--) - { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) break; - if (!(j&s_not_result_ready)) break; - if (j&s_attention) break; - } - if (i != 0 || timeout <= jiffies) break; - sbp_sleep(0); - i = 1; - } - if (i==0) { DPRINTF((DBG_AUD,"SBPCD: read_audio: STATUS TIMEOUT AFTER READ")); } - if (!(j&s_attention)) - { - DPRINTF((DBG_AUD,"SBPCD: read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n")); - i=DriveReset(); /* ugly fix to prevent a hang */ - continue; - } - } - do - { - if (fam0L_drive) xx_ReadStatus(); - i=ResponseStatus(); /* builds status_byte, returns orig. status (old) or faked p_success_old (new) */ - if (i<0) { DPRINTF((DBG_AUD, - "SBPCD: read_audio: xx_ReadStatus error after read: %02X\n", - DriveStruct[d].status_byte)); - continue; /* FIXME */ - } - } - while ((fam0L_drive)&&(!st_check)&&(!(i&p_success_old))); - if (st_check) - { - i=xx_ReadError(); - DPRINTF((DBG_AUD,"SBPCD: read_audio: xx_ReadError was necessary after read: %02X\n",i)); - continue; - } - memcpy_tofs((u_char *) read_audio.buf, - (u_char *) DriveStruct[d].aud_buf, - read_audio.nframes*CD_FRAMESIZE_RAW); - DPRINTF((DBG_AUD,"SBPCD: read_audio: memcpy_tofs done.\n")); - break; - } - xx_ModeSelect(CD_FRAMESIZE); - xx_ModeSense(); - DriveStruct[d].mode=READ_M1; - busy_audio=0; - if (data_tries == 0) - { - DPRINTF((DBG_AUD,"SBPCD: read_audio: failed after 5 tries.\n")); - return (-8); - } - DPRINTF((DBG_AUD,"SBPCD: read_audio: successful return.\n")); - return (0); - } /* end of CDROMREADAUDIO */ - - case CDROMMULTISESSION: /* tell start-of-last-session */ - DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMMULTISESSION entered.\n")); - st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_multisession)); - if (st) return (st); - memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession)); - if (ms_info.addr_format==CDROM_MSF) /* MSF-bin requested */ - lba2msf(DriveStruct[d].lba_multi,&ms_info.addr.msf.minute); - else if (ms_info.addr_format==CDROM_LBA) /* lba requested */ - ms_info.addr.lba=DriveStruct[d].lba_multi; - else return (-EINVAL); - if (DriveStruct[d].f_multisession) ms_info.xa_flag=1; /* valid redirection address */ - else ms_info.xa_flag=0; /* invalid redirection address */ - st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_multisession)); - if (st) return (st); - memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession)); - DPRINTF((DBG_MUL,"SBPCD: ioctl: CDROMMULTISESSION done (%d, %08X).\n", - ms_info.xa_flag, ms_info.addr.lba)); - return (0); - - case BLKRASET: - if(!suser()) return -EACCES; - if(!inode->i_rdev) return -EINVAL; - if(arg > 0xff) return -EINVAL; - read_ahead[MAJOR(inode->i_rdev)] = arg; - return (0); - - default: - DPRINTF((DBG_IOC,"SBPCD: ioctl: unknown function request %04X\n", cmd)); - return (-EINVAL); - } /* end switch(cmd) */ + continue; + } + if (fam0L_drive) + { + i=maxtim_data; + for (timeout=jiffies+900; timeout > jiffies; timeout--) + { + for ( ;i!=0;i--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) break; + if (!(j&s_not_result_ready)) break; + if (j&s_attention) break; + } + if (i != 0 || timeout <= jiffies) break; + sbp_sleep(0); + i = 1; + } + if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ"); + if (!(j&s_attention)) + { + msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n"); + i=cc_DriveReset(); /* ugly fix to prevent a hang */ + continue; + } + } + do + { + if (fam0L_drive) cc_ReadStatus(); + i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ + if (i<0) { msg(DBG_AUD, + "read_audio: cc_ReadStatus error after read: %02X\n", + D_S[d].status_bits); + continue; /* FIXME */ + } + } + while ((fam0L_drive)&&(!st_check)&&(!(i&p_success))); + if (st_check) + { + i=cc_ReadError(); + msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i); + continue; + } + memcpy_tofs((u_char *) read_audio.buf, + (u_char *) D_S[d].aud_buf, + read_audio.nframes*CD_FRAMESIZE_RAW); + msg(DBG_AUD,"read_audio: memcpy_tofs done.\n"); + break; + } + cc_ModeSelect(CD_FRAMESIZE); + cc_ModeSense(); + D_S[d].mode=READ_M1; + busy_audio=0; + if (data_tries == 0) + { + msg(DBG_AUD,"read_audio: failed after 5 tries.\n"); + return (-8); + } + msg(DBG_AUD,"read_audio: successful return.\n"); + return (0); + } /* end of CDROMREADAUDIO */ + + case CDROMMULTISESSION: /* tell start-of-last-session */ + msg(DBG_IOC,"ioctl: CDROMMULTISESSION entered.\n"); + st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_multisession)); + if (st) return (st); + memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession)); + if (ms_info.addr_format==CDROM_MSF) /* MSF-bin requested */ + lba2msf(D_S[d].lba_multi,&ms_info.addr.msf.minute); + else if (ms_info.addr_format==CDROM_LBA) /* lba requested */ + ms_info.addr.lba=D_S[d].lba_multi; + else return (-EINVAL); + if (D_S[d].f_multisession) ms_info.xa_flag=1; /* valid redirection address */ + else ms_info.xa_flag=0; /* invalid redirection address */ + st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_multisession)); + if (st) return (st); + memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession)); + msg(DBG_MUL,"ioctl: CDROMMULTISESSION done (%d, %08X).\n", + ms_info.xa_flag, ms_info.addr.lba); + return (0); + + case BLKRASET: + if(!suser()) return -EACCES; + if(!inode->i_rdev) return -EINVAL; + if(arg > 0xff) return -EINVAL; + read_ahead[MAJOR(inode->i_rdev)] = arg; + return (0); + + default: + msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); + return (-EINVAL); + } /* end switch(cmd) */ } /*==========================================================================*/ /* @@ -3585,18 +4322,18 @@ */ static void sbp_transfer(void) { - long offs; - - while ( (CURRENT->nr_sectors > 0) && - (CURRENT->sector/4 >= DriveStruct[d].sbp_first_frame) && - (CURRENT->sector/4 <= DriveStruct[d].sbp_last_frame) ) - { - offs = (CURRENT->sector - DriveStruct[d].sbp_first_frame * 4) * 512; - memcpy(CURRENT->buffer, DriveStruct[d].sbp_buf + offs, 512); - CURRENT->nr_sectors--; - CURRENT->sector++; - CURRENT->buffer += 512; - } + long offs; + + while ( (CURRENT->nr_sectors > 0) && + (CURRENT->sector/4 >= D_S[d].sbp_first_frame) && + (CURRENT->sector/4 <= D_S[d].sbp_last_frame) ) + { + offs = (CURRENT->sector - D_S[d].sbp_first_frame * 4) * 512; + memcpy(CURRENT->buffer, D_S[d].sbp_buf + offs, 512); + CURRENT->nr_sectors--; + CURRENT->sector++; + CURRENT->buffer += 512; + } } /*==========================================================================*/ /* @@ -3604,328 +4341,459 @@ */ static void DO_SBPCD_REQUEST(void) { - u_int block; - u_int nsect; - int i, status_tries, data_tries; - -request_loop: - INIT_REQUEST; - sti(); - - if ((CURRENT==NULL)||(CURRENT->dev<0)) goto err_done; - if (CURRENT -> sector == -1) goto err_done; - if (CURRENT->cmd != READ) - { - printk("SBPCD: bad cmd %d\n", CURRENT->cmd); - goto err_done; - } - i = MINOR(CURRENT->dev); - if ( (i<0) || (i>=NR_SBPCD) || (DriveStruct[i].drv_id==-1)) - { - printk("SBPCD: do_request: bad device: %04X\n", CURRENT->dev); - goto err_done; - } - switch_drive(i); - - block = CURRENT->sector; /* always numbered as 512-byte-pieces */ - nsect = CURRENT->nr_sectors; /* always counted as 512-byte-pieces */ - - DPRINTF((DBG_BSZ,"SBPCD: read sector %d (%d sectors)\n", block, nsect)); + u_int block; + u_int nsect; + int i, status_tries, data_tries; + + request_loop: + INIT_REQUEST; + sti(); + + if ((CURRENT==NULL)||(CURRENT->dev<0)) goto err_done; + if (CURRENT -> sector == -1) goto err_done; + if (CURRENT->cmd != READ) + { + msg(DBG_INF, "bad cmd %d\n", CURRENT->cmd); + goto err_done; + } + i = MINOR(CURRENT->dev); + if ( (i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) + { + msg(DBG_INF, "do_request: bad device: %04X\n", CURRENT->dev); + goto err_done; + } + while (busy_audio) sbp_sleep(100); /* wait a bit */ + busy_data=1; + + if (D_S[i].audio_state==audio_playing) goto err_done; + if (d!=i) switch_drive(i); + + block = CURRENT->sector; /* always numbered as 512-byte-pieces */ + nsect = CURRENT->nr_sectors; /* always counted as 512-byte-pieces */ + + msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect); #if 0 - DPRINTF((DBG_MUL,"SBPCD: read LBA %d\n", block/4)); + msg(DBG_MUL,"read LBA %d\n", block/4); #endif - - sbp_transfer(); - /* if we satisfied the request from the buffer, we're done. */ - if (CURRENT->nr_sectors == 0) - { - end_request(1); - goto request_loop; - } - - i=prepare(0,0); /* at moment not really a hassle check, but ... */ - if (i!=0) - DPRINTF((DBG_INF,"SBPCD: \"prepare\" tells error %d -- ignored\n", i)); - - while (busy_audio) sbp_sleep(100); /* wait a bit */ - busy_data=1; - - if (!st_spinning) xx_SpinUp(); - -#ifdef XA_TEST1 - if ((fam0L_drive) && (DriveStruct[d].xa_byte==0x20)) /* XA disk with old drive */ - { - xx_ModeSelect(CD_FRAMESIZE_XA); - xx_ModeSense(); - } -#endif XA_TEST1 - - for (data_tries=n_retries; data_tries > 0; data_tries--) - { - for (status_tries=3; status_tries > 0; status_tries--) + + sbp_transfer(); + /* if we satisfied the request from the buffer, we're done. */ + if (CURRENT->nr_sectors == 0) { - flags_cmd_out |= f_respo3; - xx_ReadStatus(); - if (sbp_status() != 0) break; - if (st_check) xx_ReadError(); - sbp_sleep(1); /* wait a bit, try again */ - } - if (status_tries == 0) - { - DPRINTF((DBG_INF,"SBPCD: sbp_status: failed after 3 tries\n")); - break; + end_request(1); + goto request_loop; } - sbp_read_cmd(); - sbp_sleep(0); - if (sbp_data() != 0) +#if FUTURE + i=prepare(0,0); /* at moment not really a hassle check, but ... */ + if (i!=0) + msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i); +#endif FUTURE + + if (!st_spinning) cc_SpinUp(); + + for (data_tries=n_retries; data_tries > 0; data_tries--) { - end_request(1); - goto request_loop; + for (status_tries=3; status_tries > 0; status_tries--) + { + flags_cmd_out |= f_respo3; + cc_ReadStatus(); + if (sbp_status() != 0) break; + if (st_check) cc_ReadError(); + sbp_sleep(1); /* wait a bit, try again */ + } + if (status_tries == 0) + { + msg(DBG_INF,"sbp_status: failed after 3 tries\n"); + break; + } + + sbp_read_cmd(); + sbp_sleep(0); + if (sbp_data() != 0) + { + end_request(1); + goto request_loop; + } } - } - -err_done: - busy_data=0; - end_request(0); - sbp_sleep(10); /* wait a bit, try again */ - goto request_loop; + + err_done: + busy_data=0; + end_request(0); + sbp_sleep(0); /* wait a bit, try again */ + goto request_loop; } /*==========================================================================*/ /* * build and send the READ command. - * Maybe it would be better to "set mode1" before ... */ static void sbp_read_cmd(void) { - int i; - int block; +#undef OLD - DriveStruct[d].sbp_first_frame=DriveStruct[d].sbp_last_frame=-1; /* purge buffer */ - block=CURRENT->sector/4; - if (block+SBP_BUFFER_FRAMES <= DriveStruct[d].CDsize_frm) - DriveStruct[d].sbp_read_frames = SBP_BUFFER_FRAMES; - else - { - DriveStruct[d].sbp_read_frames=DriveStruct[d].CDsize_frm-block; - /* avoid reading past end of data */ - if (DriveStruct[d].sbp_read_frames < 1) - { - DPRINTF((DBG_INF,"SBPCD: requested frame %d, CD size %d ???\n", - block, DriveStruct[d].CDsize_frm)); - DriveStruct[d].sbp_read_frames=1; + int i; + int block; + + D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1; /* purge buffer */ + D_S[d].sbp_current = 0; + block=CURRENT->sector/4; + if (block+D_S[d].sbp_bufsiz <= D_S[d].CDsize_frm) + D_S[d].sbp_read_frames = D_S[d].sbp_bufsiz; + else + { + D_S[d].sbp_read_frames=D_S[d].CDsize_frm-block; + /* avoid reading past end of data */ + if (D_S[d].sbp_read_frames < 1) + { + msg(DBG_INF,"requested frame %d, CD size %d ???\n", + block, D_S[d].CDsize_frm); + D_S[d].sbp_read_frames=1; + } } - } - DriveStruct[d].sbp_current = 0; - - flags_cmd_out = f_putcmd | - f_respo2 | - f_ResponseStatus | - f_obey_p_check; - - if (fam0L_drive) - { - flags_cmd_out |= f_lopsta | f_getsta | f_bit1; - if (DriveStruct[d].xa_byte==0x20) - { - cmd_type=READ_M2; - drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ - drvcmd[1]=(block>>16)&0x000000ff; - drvcmd[2]=(block>>8)&0x000000ff; - drvcmd[3]=block&0x000000ff; - drvcmd[4]=0; - drvcmd[5]=DriveStruct[d].sbp_read_frames; - drvcmd[6]=0; - } - else - { - drvcmd[0]=CMD0_READ; /* "read frames", old drives */ - - if (DriveStruct[d].drv_type>=drv_201) - { - lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ - bin2bcdx(&drvcmd[1]); - bin2bcdx(&drvcmd[2]); - bin2bcdx(&drvcmd[3]); - } - else - { - drvcmd[1]=(block>>16)&0x000000ff; - drvcmd[2]=(block>>8)&0x000000ff; - drvcmd[3]=block&0x000000ff; - } - drvcmd[4]=0; - drvcmd[5]=DriveStruct[d].sbp_read_frames; - drvcmd[6]=(DriveStruct[d].drv_type>16)&0x000000ff; + drvcmd[2]=(block>>8)&0x000000ff; + drvcmd[3]=block&0x000000ff; + drvcmd[5]=D_S[d].sbp_read_frames; + } + else + { + drvcmd[0]=CMD0_READ; /* "read frames", old drives */ + if (D_S[d].drv_type>=drv_201) + { + lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ + bin2bcdx(&drvcmd[1]); + bin2bcdx(&drvcmd[2]); + bin2bcdx(&drvcmd[3]); + } + else + { + drvcmd[1]=(block>>16)&0x000000ff; + drvcmd[2]=(block>>8)&0x000000ff; + drvcmd[3]=block&0x000000ff; + } + drvcmd[5]=D_S[d].sbp_read_frames; + drvcmd[6]=(D_S[d].drv_type>24)&0x0ff; + drvcmd[3]=(block>>16)&0x0ff; + drvcmd[4]=(block>>8)&0x0ff; + drvcmd[5]=block&0x0ff; + drvcmd[7]=(D_S[d].sbp_read_frames>>8)&0x0ff; + drvcmd[8]=D_S[d].sbp_read_frames&0x0ff; + } +#ifdef OLD + SBPCD_CLI; + for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]); + if (famT_drive) for (i=7;i<10;i++) OUT(CDo_command,drvcmd[i]); + SBPCD_STI; +#else + flags_cmd_out=f_putcmd; + response_count=0; + i=cmd_out(); /* immediate return here - read data "ourselves" */ + if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i); +#endif OLD + return; } /*==========================================================================*/ /* * Check the completion of the read-data command. On success, read - * the SBP_BUFFER_FRAMES * 2048 bytes of data from the disk into buffer. + * the D_S[d].sbp_bufsiz * 2048 bytes of data from the disk into buffer. */ static int sbp_data(void) { - int i=0, j=0, frame; - u_int try=0; - u_long timeout; - u_char *p; - u_int data_tries = 0; - u_int data_waits = 0; - u_int data_retrying = 0; - int error_flag; - int xa_count; - error_flag=0; - - for (frame=DriveStruct[d].sbp_current;frame= 1000) - { - DPRINTF((DBG_INF,"SBPCD: info: %d waits in %d frames.\n", - data_waits, data_tries)); - data_waits = data_tries = 0; + if (D_S[d].f_multisession) max_latency=900; + else if (fam0L_drive) max_latency=300; + else if (famT_drive) max_latency=300; + else max_latency=100; +#endif + msg(DBG_TE2,"beginning to READ\n"); + duration=jiffies; + for (frame=0;frame= 1000) + { + msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries); + data_waits = data_tries = 0; + } } - } - SBPCD_STI; - - if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ - { - DPRINTF((DBG_INF,"SBPCD: read aborted by drive\n")); + duration=jiffies-duration; + msg(DBG_TE2,"time to read %d frames: %d jiffies .\n",frame,duration); + if (famT_drive) + { + wait=8; + do + { + sbp_sleep(1); + OUT(CDo_sel_i_d,0); + i=inb(CDi_status); + if (!(i&s_not_data_ready)) + { + OUT(CDo_sel_i_d,1); + j=0; + do + { + i=inb(CDi_data); + j++; + i=inb(CDi_status); + } + while (!(i&s_not_data_ready)); + msg(DBG_TEA, "=============too much data (%d bytes)=================.\n", j); + } + if (!(i&s_not_result_ready)) + { + OUT(CDo_sel_i_d,0); + l=0; + do + { + infobuf[l++]=inb(CDi_info); + i=inb(CDi_status); + } + while (!(i&s_not_result_ready)); + if (infobuf[0]==0x00) success=1; +#if 1 + for (j=0;j1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion); + else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n"); + clr_cmdbuf(); + drvcmd[0]=CMDT_READ_ERR; + j=cmd_out_T(); /* !!! recursive here !!! */ + --recursion; + sbp_sleep(1); + } + while (j<0); + D_S[d].error_state=infobuf[2]; + D_S[d].b3=infobuf[3]; + D_S[d].b4=infobuf[4]; + } + break; + } + else + { #if 0 - i=DriveReset(); /* ugly fix to prevent a hang */ -#else - i=xx_ReadError(); + msg(DBG_TEA, "============= waiting for result=================.\n"); + sbp_sleep(1); #endif - return (0); - } - - if (fam0L_drive) - { - SBPCD_CLI; - i=maxtim_data; - for (timeout=jiffies+100; timeout > jiffies; timeout--) - { - for ( ;i!=0;i--) - { - j=inb(CDi_status); - if (!(j&s_not_data_ready)) break; - if (!(j&s_not_result_ready)) break; - if (j&s_attention) break; - } - if (i != 0 || timeout <= jiffies) break; - sbp_sleep(0); - i = 1; - } - if (i==0) { DPRINTF((DBG_INF,"SBPCD: STATUS TIMEOUT AFTER READ")); } - if (!(j&s_attention)) - { - DPRINTF((DBG_INF,"SBPCD: sbp_data: timeout waiting DRV_ATTN - retrying\n")); - i=DriveReset(); /* ugly fix to prevent a hang */ - SBPCD_STI; - return (0); + } + } + while (wait--); } - SBPCD_STI; - } - do - { - if (fam0L_drive) xx_ReadStatus(); - i=ResponseStatus(); /* builds status_byte, returns orig. status (old) or faked p_success_old (new) */ - if (i<0) { DPRINTF((DBG_INF,"SBPCD: xx_ReadStatus error after read: %02X\n", - DriveStruct[d].status_byte)); - return (0); - } - } - while ((fam0L_drive)&&(!st_check)&&(!(i&p_success_old))); - if (st_check) - { - i=xx_ReadError(); - DPRINTF((DBG_INF,"SBPCD: xx_ReadError was necessary after read: %02X\n",i)); - return (0); - } - - DriveStruct[d].sbp_first_frame = CURRENT -> sector / 4; - DriveStruct[d].sbp_last_frame = DriveStruct[d].sbp_first_frame + DriveStruct[d].sbp_read_frames - 1; - sbp_transfer(); - return (1); + if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ + { + msg(DBG_TEA, "================error flag: %d=================.\n", error_flag); + msg(DBG_INF,"sbp_data: read aborted by drive.\n"); +#if 1 + i=cc_DriveReset(); /* ugly fix to prevent a hang */ +#else + i=cc_ReadError(); +#endif + return (0); + } + + if (fam0L_drive) + { + SBPCD_CLI; + i=maxtim_data; + for (timeout=jiffies+100; timeout > jiffies; timeout--) + { + for ( ;i!=0;i--) + { + j=inb(CDi_status); + if (!(j&s_not_data_ready)) break; + if (!(j&s_not_result_ready)) break; + if (j&s_attention) break; + } + if (i != 0 || timeout <= jiffies) break; + sbp_sleep(0); + i = 1; + } + if (i==0) msg(DBG_INF,"status timeout after READ.\n"); + if (!(j&s_attention)) + { + msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n"); + i=cc_DriveReset(); /* ugly fix to prevent a hang */ + SBPCD_STI; + return (0); + } + SBPCD_STI; + } + +#if 0 + if (!success) +#endif 0 + do + { + if (fam0L_drive) cc_ReadStatus(); +#if 1 + if (famT_drive) msg(DBG_TE2, "================before ResponseStatus=================.\n", i); +#endif 1 + i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ +#if 1 + if (famT_drive) msg(DBG_TE2, "================ResponseStatus: %d=================.\n", i); +#endif 1 + if (i<0) + { + msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", D_S[d].status_bits); + return (0); + } + } + while ((fam0L_drive)&&(!st_check)&&(!(i&p_success))); + if (st_check) + { + i=cc_ReadError(); + msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i); + return (0); + } + if (fatal_err) + { + fatal_err=0; + D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1; /* purge buffer */ + D_S[d].sbp_current = 0; + msg(DBG_INF,"sbp_data: fatal_err - retrying.\n"); + return (0); + } + + D_S[d].sbp_first_frame = CURRENT -> sector / 4; + D_S[d].sbp_last_frame = D_S[d].sbp_first_frame + D_S[d].sbp_read_frames - 1; + sbp_transfer(); +#if 1 + if (famT_drive) msg(DBG_TE2, "================sbp_transfer() done=================.\n"); +#endif 1 + return (1); } /*==========================================================================*/ /*==========================================================================*/ @@ -3934,71 +4802,83 @@ */ static int sbpcd_open(struct inode *ip, struct file *fp) { - int i; - - i = MINOR(ip->i_rdev); - if ((i<0) || (i>=NR_SBPCD) || (DriveStruct[i].drv_id==-1)) - { - printk("SBPCD: open: bad device: %04X\n", ip->i_rdev); - return (-ENXIO); /* no such drive */ - } - if (fp->f_mode & 2) - return -EROFS; - - switch_drive(i); - - flags_cmd_out |= f_respo2; - xx_ReadStatus(); /* command: give 1-byte status */ - i=ResponseStatus(); - if (!st_door_closed) - { - yy_CloseTray(); - flags_cmd_out |= f_respo2; - xx_ReadStatus(); - i=ResponseStatus(); - } - if (!st_spinning) - { - xx_SpinUp(); - flags_cmd_out |= f_respo2; - xx_ReadStatus(); - i=ResponseStatus(); - } - if (i<0) - { - DPRINTF((DBG_INF,"SBPCD: sbpcd_open: xx_ReadStatus timed out\n")); - return (-EIO); /* drive doesn't respond */ - } - DPRINTF((DBG_STA,"SBPCD: sbpcd_open: status %02X\n", DriveStruct[d].status_byte)); - if (!st_door_closed||!st_caddy_in) - { - printk("SBPCD: sbpcd_open: no disk in drive\n"); + int i; + + i = MINOR(ip->i_rdev); + if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) + { + msg(DBG_INF, "open: bad device: %04X\n", ip->i_rdev); + return (-ENXIO); /* no such drive */ + } + if (fp->f_mode & 2) + return -EROFS; + + switch_drive(i); + + i=cc_ReadError(); + flags_cmd_out |= f_respo2; + cc_ReadStatus(); /* command: give 1-byte status */ + i=ResponseStatus(); + if (famT_drive&&(i<0)) + { + cc_DriveReset(); + i=ResponseStatus(); + } + if (i<0) + { + msg(DBG_INF,"sbpcd_open: ResponseStatus timed out (%d).\n",i); + return (-EIO); /* drive doesn't respond */ + } + if (famT_drive) msg(DBG_TE2,"sbpcd_open: ResponseStatus=%02X\n", i); + if (!st_door_closed) + { + if (famT_drive) msg(DBG_TE2,"sbpcd_open: !st_door_closed.\n"); + cc_CloseTray(); + flags_cmd_out |= f_respo2; + cc_ReadStatus(); + i=ResponseStatus(); + } + if (!(famT_drive)) + if (!st_spinning) + { + if (famT_drive) msg(DBG_TE2,"sbpcd_open: !st_spinning.\n"); + cc_SpinUp(); + flags_cmd_out |= f_respo2; + cc_ReadStatus(); + i=ResponseStatus(); + } + if (famT_drive) msg(DBG_TE2,"sbpcd_open: status %02X\n", D_S[d].status_bits); + if (!st_door_closed||!st_caddy_in) + { + msg(DBG_INF, "sbpcd_open: no disk in drive.\n"); + D_S[d].open_count=0; #if JUKEBOX - do - i=yy_LockDoor(0); - while (i!=0); - if (!fam0_drive) yy_SpinDown(); /* eject tray */ + if (!fam0_drive) + { + i=UnLockDoor(); + cc_SpinDown(); /* eject tray */ + } #endif - return (-ENXIO); - } -/* - * try to keep an "open" counter here and lock the door if 0->1. - */ - MOD_INC_USE_COUNT; - DPRINTF((DBG_LCK,"SBPCD: open_count: %d -> %d\n", - DriveStruct[d].open_count,DriveStruct[d].open_count+1)); - if (++DriveStruct[d].open_count==1) - { - do - i=yy_LockDoor(1); - while (i!=0); - } - if (!st_spinning) xx_SpinUp(); - - i=DiskInfo(); - if ((DriveStruct[d].ored_ctl_adr&0x40)==0) - DPRINTF((DBG_INF,"SBPCD: CD contains no data tracks.\n")); - return (0); + return (-ENXIO); + } + /* + * try to keep an "open" counter here and lock the door if 0->1. + */ + MOD_INC_USE_COUNT; + msg(DBG_LCK,"open_count: %d -> %d\n", + D_S[d].open_count,D_S[d].open_count+1); + if (++D_S[d].open_count<=1) + { + i=LockDoor(); + D_S[d].open_count=1; + if (famT_drive) msg(DBG_TE2,"sbpcd_open: before i=DiskInfo();.\n"); + i=DiskInfo(); + if (famT_drive) msg(DBG_TE2,"sbpcd_open: after i=DiskInfo();.\n"); + if ((D_S[d].ored_ctl_adr&0x40)==0) + msg(DBG_INF,"CD contains no data tracks.\n"); + } + if (!st_spinning) cc_SpinUp(); + return (0); } /*==========================================================================*/ /* @@ -4006,37 +4886,37 @@ */ static void sbpcd_release(struct inode * ip, struct file * file) { - int i; - - i = MINOR(ip->i_rdev); - if ((i<0) || (i>=NR_SBPCD) || (DriveStruct[i].drv_id==-1)) - { - printk("SBPCD: release: bad device: %04X\n", ip->i_rdev); - return; - } - switch_drive(i); - - DriveStruct[d].sbp_first_frame=DriveStruct[d].sbp_last_frame=-1; - sync_dev(ip->i_rdev); /* nonsense if read only device? */ - invalidate_buffers(ip->i_rdev); - -/* - * try to keep an "open" counter here and unlock the door if 1->0. - */ - MOD_DEC_USE_COUNT; - DPRINTF((DBG_LCK,"SBPCD: open_count: %d -> %d\n", - DriveStruct[d].open_count,DriveStruct[d].open_count-1)); - if (DriveStruct[d].open_count!=0) /* CDROMEJECT may have been done */ - { - if (--DriveStruct[d].open_count==0) - { - do - i=yy_LockDoor(0); - while (i!=0); - if (DriveStruct[d].f_eject) yy_SpinDown(); - DriveStruct[d].diskstate_flags &= ~cd_size_bit; + int i; + + i = MINOR(ip->i_rdev); + if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) + { + msg(DBG_INF, "release: bad device: %04X\n", ip->i_rdev); + return; + } + switch_drive(i); + + D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1; + sync_dev(ip->i_rdev); /* nonsense if read only device? */ + invalidate_buffers(ip->i_rdev); + + /* + * try to keep an "open" counter here and unlock the door if 1->0. + */ + MOD_DEC_USE_COUNT; + msg(DBG_LCK,"open_count: %d -> %d\n", + D_S[d].open_count,D_S[d].open_count-1); + if (D_S[d].open_count>-2) /* CDROMEJECT may have been done */ + { + if (--D_S[d].open_count<=0) + { + i=UnLockDoor(); + if (D_S[d].audio_state!=audio_playing) + if (D_S[d].f_eject) cc_SpinDown(); + D_S[d].diskstate_flags &= ~cd_size_bit; + D_S[d].open_count=0; + } } - } } /*==========================================================================*/ /* @@ -4044,19 +4924,19 @@ */ static struct file_operations sbpcd_fops = { - NULL, /* lseek - default */ - block_read, /* read - general block-dev read */ - block_write, /* write - general block-dev write */ - NULL, /* readdir - bad */ - NULL, /* select */ - sbpcd_ioctl, /* ioctl */ - NULL, /* mmap */ - sbpcd_open, /* open */ - sbpcd_release, /* release */ - NULL, /* fsync */ - NULL, /* fasync */ - sbpcd_chk_disk_change, /* media_change */ - NULL /* revalidate */ + NULL, /* lseek - default */ + block_read, /* read - general block-dev read */ + block_write, /* write - general block-dev write */ + NULL, /* readdir - bad */ + NULL, /* select */ + sbpcd_ioctl, /* ioctl */ + NULL, /* mmap */ + sbpcd_open, /* open */ + sbpcd_release, /* release */ + NULL, /* fsync */ + NULL, /* fasync */ + sbpcd_chk_disk_change, /* media_change */ + NULL /* revalidate */ }; /*==========================================================================*/ /* @@ -4084,82 +4964,80 @@ #endif void sbpcd_setup(char *s, int *p) { - setup_done++; - DPRINTF((DBG_INI,"SBPCD: sbpcd_setup called with %04X,%s\n",p[1], s)); - sbpro_type=0; - if (!strcmp(s,str_sb)) sbpro_type=1; - else if (!strcmp(s,str_sb_l)) sbpro_type=1; - else if (!strcmp(s,str_sp)) sbpro_type=2; - else if (!strcmp(s,str_sp_l)) sbpro_type=2; - if (p[0]>0) sbpcd_ioaddr=p[1]; - - CDo_command=sbpcd_ioaddr; - CDi_info=sbpcd_ioaddr; - CDi_status=sbpcd_ioaddr+1; - CDo_sel_i_d=sbpcd_ioaddr+1; - CDo_reset=sbpcd_ioaddr+2; - CDo_enable=sbpcd_ioaddr+3; - if (sbpro_type==1) - { - MIXER_addr=sbpcd_ioaddr-0x10+0x04; - MIXER_data=sbpcd_ioaddr-0x10+0x05; - CDi_data=sbpcd_ioaddr; - } - else CDi_data=sbpcd_ioaddr+2; + setup_done++; + msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s); + sbpro_type=0; + if (!strcmp(s,str_sb)) sbpro_type=1; + else if (!strcmp(s,str_sb_l)) sbpro_type=1; + else if (!strcmp(s,str_sp)) sbpro_type=2; + else if (!strcmp(s,str_sp_l)) sbpro_type=2; + if (p[0]>0) sbpcd_ioaddr=p[1]; + + CDo_command=sbpcd_ioaddr; + CDi_info=sbpcd_ioaddr; + CDi_status=sbpcd_ioaddr+1; + CDo_sel_i_d=sbpcd_ioaddr+1; + CDo_reset=sbpcd_ioaddr+2; + CDo_enable=sbpcd_ioaddr+3; + if (sbpro_type==1) + { + MIXER_addr=sbpcd_ioaddr-0x10+0x04; + MIXER_data=sbpcd_ioaddr-0x10+0x05; + CDi_data=sbpcd_ioaddr; + } + else CDi_data=sbpcd_ioaddr+2; } /*==========================================================================*/ /* * Sequoia S-1000 CD-ROM Interface Configuration * as used within SPEA Media FX card - * The SPEA soundcard has to get jumpered for + * The SPEA soundcard has to get configured for * -> interface type "Matsushita/Panasonic" (not Sony or Mitsumi) * -> I/O base address (0x320, 0x330, 0x340, 0x350) */ static int config_spea(void) { - int n_ports=0x10; /* 2:0x00, 8:0x10, 16:0x20, 32:0x30 */ -/* What is n_ports? Number of addresses or base address offset? */ - int irq_number=0; /* 2:0x01, 7:0x03, 12:0x05, 15:0x07, OFF:0x00 */ - int dma_channel=0; /* 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68, 7:0x78, OFF: 0x00 */ - int dack_polarity=0; /* L:0x00, H:0x80 */ - int drq_polarity=0x40; /* L:0x00, H:0x40 */ - - int i; - + int n_ports=0x10; /* 2:0x00, 8:0x10, 16:0x20, 32:0x30 */ + /* What is n_ports? Number of addresses or base address offset? */ + int irq_number=0; /* 2:0x01, 7:0x03, 12:0x05, 15:0x07, OFF:0x00 */ + int dma_channel=0; /* 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68, 7:0x78, OFF: 0x00 */ + int dack_polarity=0; /* L:0x00, H:0x80 */ + int drq_polarity=0x40; /* L:0x00, H:0x40 */ + + int i; + #define SPEA_REG_1 sbpcd_ioaddr+4 #define SPEA_REG_2 sbpcd_ioaddr+5 - - OUT(SPEA_REG_1,0xFF); - i=inb(SPEA_REG_1); - if (i!=0x0F) - { - DPRINTF((DBG_SEQ,"SBPCD: no SPEA interface at %04X present.\n", - sbpcd_ioaddr)); - return (-1); /* no interface found */ - } - OUT(SPEA_REG_1,0x04); - OUT(SPEA_REG_2,0xC0); - - OUT(SPEA_REG_1,0x05); - OUT(SPEA_REG_2,0x10|drq_polarity|dack_polarity); - + + OUT(SPEA_REG_1,0xFF); + i=inb(SPEA_REG_1); + if (i!=0x0F) + { + msg(DBG_SEQ,"no SPEA interface at %04X present.\n", sbpcd_ioaddr); + return (-1); /* no interface found */ + } + OUT(SPEA_REG_1,0x04); + OUT(SPEA_REG_2,0xC0); + + OUT(SPEA_REG_1,0x05); + OUT(SPEA_REG_2,0x10|drq_polarity|dack_polarity); + #if 1 #define SPEA_PATTERN 0x80 #else #define SPEA_PATTERN 0x00 #endif - OUT(SPEA_REG_1,0x06); - OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN); - OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN); - - OUT(SPEA_REG_1,0x09); - i=(inb(SPEA_REG_2)&0xCF)|n_ports; - OUT(SPEA_REG_2,i); - - sbpro_type = 0; /* acts like a LaserMate interface now */ - DPRINTF((DBG_SEQ,"SBPCD: found SPEA interface at %04X.\n", - sbpcd_ioaddr)); - return (0); + OUT(SPEA_REG_1,0x06); + OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN); + OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN); + + OUT(SPEA_REG_1,0x09); + i=(inb(SPEA_REG_2)&0xCF)|n_ports; + OUT(SPEA_REG_2,i); + + sbpro_type = 0; /* acts like a LaserMate interface now */ + msg(DBG_SEQ,"found SPEA interface at %04X.\n", sbpcd_ioaddr); + return (0); } /*==========================================================================*/ /* @@ -4168,261 +5046,261 @@ #ifdef MODULE int init_module(void) #else -unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) + unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) #endif MODULE { - int i=0, j=0; - int addr[2]={1, CDROM_PORT}; - int port_index; - - sti(); /* necessary, has consequences for other drivers' init routines */ - - DPRINTF((DBG_INF,"SBPCD version %s\n", VERSION)); - + int i=0, j=0; + int addr[2]={1, CDROM_PORT}; + int port_index; + + sti(); + + msg(DBG_INF,"sbpcd.c %s\n", VERSION); #ifndef MODULE - if (!setup_done) - { - DPRINTF((DBG_INF,"SBPCD: Looking for Matsushita, Panasonic, CreativeLabs, IBM, Longshine CD-ROM drives\n")); - DPRINTF((DBG_WRN,"SBPCD: \n")); - DPRINTF((DBG_WRN,"SBPCD: = = = = = = = = = = W A R N I N G = = = = = = = = = =\n")); - DPRINTF((DBG_WRN,"SBPCD: Auto-Probing can cause a hang (f.e. touching an ethernet card).\n")); - DPRINTF((DBG_WRN,"SBPCD: If that happens, you have to reboot and use the\n")); - DPRINTF((DBG_WRN,"SBPCD: LILO (kernel) command line feature like:\n")); - DPRINTF((DBG_WRN,"SBPCD: \n")); - DPRINTF((DBG_WRN,"SBPCD: LILO boot: linux sbpcd=0x230,SoundBlaster\n")); - DPRINTF((DBG_WRN,"SBPCD: or like:\n")); - DPRINTF((DBG_WRN,"SBPCD: LILO boot: linux sbpcd=0x300,LaserMate\n")); - DPRINTF((DBG_WRN,"SBPCD: or like:\n")); - DPRINTF((DBG_WRN,"SBPCD: LILO boot: linux sbpcd=0x330,SPEA\n")); - DPRINTF((DBG_WRN,"SBPCD: \n")); - DPRINTF((DBG_WRN,"SBPCD: with your REAL address.\n")); - DPRINTF((DBG_WRN,"SBPCD: = = = = = = = = = = END of WARNING = = = = = = = = = =\n")); - DPRINTF((DBG_WRN,"SBPCD: \n")); - } +#if DISTRIBUTION + if (!setup_done) + { + msg(DBG_INF,"Looking for Matsushita/Panasonic, CreativeLabs, IBM, Longshine, TEAC CD-ROM drives\n"); + msg(DBG_INF,"\n= = = = = = = = = = W A R N I N G = = = = = = = = = =\n"); + msg(DBG_INF,"Auto-Probing can cause a hang (f.e. touching an ethernet card).\n"); + msg(DBG_INF,"If that happens, you have to reboot and use the\n"); + msg(DBG_INF,"LILO (kernel) command line feature like:\n"); + msg(DBG_INF,"\n LILO boot: ... sbpcd=0x230,SoundBlaster\n"); + msg(DBG_INF,"or like:\n"); + msg(DBG_INF," LILO boot: ... sbpcd=0x300,LaserMate\n"); + msg(DBG_INF,"or like:\n"); + msg(DBG_INF," LILO boot: ... sbpcd=0x330,SPEA\n"); + msg(DBG_INF,"\nwith your REAL address.\n"); + msg(DBG_INF,"= = = = = = = = = = END of WARNING = = = = = = = = = =\n\n"); + } +#endif DISTRIBUTION + sbpcd[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */ + sbpcd[1]=sbpro_type; /* possibly changed by kernel command line */ #endif MODULE - sbpcd_probe[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */ - sbpcd_probe[1]=sbpro_type; /* possibly changed by kernel command line */ - - for (port_index=0;port_index=0) break; /* drive found */ - DPRINTF((DBG_INF,"\n")); - } /* end of cycling through the set of possible I/O port addresses */ - - if (ndrives==0) - { - printk("SBPCD: No drive found.\n"); -#if PRINTK_BUG - sti(); /* to avoid possible "printk" bug */ -#endif + + for (port_index=0;port_index=0) break; /* drive found */ + } /* end of cycling through the set of possible I/O port addresses */ + + if (ndrives==0) + { + msg(DBG_INF, "No drive found.\n"); #ifdef MODULE - return -EIO; + return -EIO; #else - goto init_done; + goto init_done; #endif MODULE - } - - if (port_index>0) - { - printk("SBPCD: You should configure sbpcd.h for your hardware.\n"); -#if PRINTK_BUG - sti(); /* to avoid possible "printk" bug */ -#endif - } + } + + if (port_index>0) + msg(DBG_INF, "You should configure sbpcd.h for your hardware.\n"); + check_datarate(); + msg(DBG_INI,"check_datarate done.\n"); + +#if 0 + if (!famL_drive) + { + OUT(CDo_reset,0); + sbp_sleep(100); + } +#endif 0 - printk("SBPCD: %d %s CD-ROM drive(s) at 0x%04X.\n", - ndrives, type, CDo_command); -#if PRINTK_BUG - sti(); /* to avoid possible "printk" bug */ -#endif - check_datarate(); - DPRINTF((DBG_INI,"SBPCD: check_datarate done.\n")); - - if (!famL_drive) - { - OUT(CDo_reset,0); - sbp_sleep(100); - } - - for (j=0;j=0) D_S[d].CD_changed=1; } - i=SetSpeed(); - if (i>=0) DriveStruct[d].CD_changed=1; - } - -/* - * Turn on the CD audio channels. - * For "compatible" soundcards (with "SBPRO 0" or "SBPRO 2"), the addresses - * are obtained from SOUND_BASE (see sbpcd.h). - */ - if ((sbpro_type==1) || (SOUND_BASE)) - { - if (sbpro_type!=1) + + /* + * Turn on the CD audio channels. + * For "compatible" soundcards (with "SBPRO 0" or "SBPRO 2"), the addresses + * are obtained from SOUND_BASE (see sbpcd.h). + */ + if ((sbpro_type==1) || (SOUND_BASE)) { - MIXER_addr=SOUND_BASE+0x04; /* sound card's address register */ - MIXER_data=SOUND_BASE+0x05; /* sound card's data register */ + if (sbpro_type!=1) + { + MIXER_addr=SOUND_BASE+0x04; /* sound card's address register */ + MIXER_data=SOUND_BASE+0x05; /* sound card's data register */ + } + OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */ + OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */ } - OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */ - OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */ - } - - if (register_blkdev(MAJOR_NR, major_name, &sbpcd_fops) != 0) - { - printk("SBPCD: Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR); -#if PRINTK_BUG - sti(); /* to avoid possible "printk" bug */ -#endif + + if (register_blkdev(MAJOR_NR, major_name, &sbpcd_fops) != 0) + { + msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR); #ifdef MODULE - return -EIO; + return -EIO; #else - goto init_done; + goto init_done; #endif MODULE - } - blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; - read_ahead[MAJOR_NR] = SBP_BUFFER_FRAMES * (CD_FRAMESIZE / 512); - - request_region(CDo_command,4,major_name); - - for (j=0;j0) D_S[j].sbp_audsiz=READ_AUDIO; #ifdef MODULE - DriveStruct[j].sbp_buf=(u_char *) kmalloc(SBP_BUFFER_FRAMES*CD_FRAMESIZE, GFP_KERNEL); - DriveStruct[j].aud_buf=NULL; + D_S[j].sbp_buf=(u_char *) vmalloc(D_S[j].sbp_bufsiz*CD_FRAMESIZE); + if (D_S[j].sbp_buf==NULL) + { + msg(DBG_INF,"data buffer (%d frames) not available.\n",D_S[j].sbp_bufsiz); + return -EIO; + } + msg(DBG_INF,"data buffer size: %d frames.\n",SBP_BUFFER_FRAMES); + if (D_S[j].sbp_audsiz>0) + { + D_S[j].aud_buf=(u_char *) vmalloc(D_S[j].sbp_audsiz*CD_FRAMESIZE_RAW); + if (D_S[j].aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",D_S[j].sbp_audsiz); + else msg(DBG_INF,"audio buffer size: %d frames.\n",D_S[j].sbp_audsiz); + } #else - DriveStruct[j].sbp_buf=(u_char *)mem_start; - mem_start += SBP_BUFFER_FRAMES*CD_FRAMESIZE; - if ((fam1_drive) && (SBP_BUFFER_AUDIO_FRAMES>0)) - { - DriveStruct[j].aud_buf=(u_char *)mem_start; - mem_start += SBP_BUFFER_AUDIO_FRAMES*CD_FRAMESIZE_RAW; - } - else DriveStruct[j].aud_buf=NULL; + D_S[j].sbp_buf=(u_char *)mem_start; + mem_start += D_S[j].sbp_bufsiz*CD_FRAMESIZE; + if (D_S[j].sbp_audsiz>0) + { + D_S[j].aud_buf=(u_char *)mem_start; + mem_start += D_S[j].sbp_audsiz*CD_FRAMESIZE_RAW; + } #endif MODULE -/* - * set the block size - */ - sbpcd_blocksizes[j]=CD_FRAMESIZE; - } - blksize_size[MAJOR_NR]=sbpcd_blocksizes; - + /* + * set the block size + */ + sbpcd_blocksizes[j]=CD_FRAMESIZE; + } + blksize_size[MAJOR_NR]=sbpcd_blocksizes; + #ifdef MODULE -return (0); + return (0); #else -init_done: + init_done: #if !(SBPCD_ISSUE-1) #ifdef CONFIG_SBPCD2 - mem_start=sbpcd2_init(mem_start, mem_end); + mem_start=sbpcd2_init(mem_start, mem_end); #endif #ifdef CONFIG_SBPCD3 - mem_start=sbpcd3_init(mem_start, mem_end); + mem_start=sbpcd3_init(mem_start, mem_end); #endif #ifdef CONFIG_SBPCD4 - mem_start=sbpcd4_init(mem_start, mem_end); + mem_start=sbpcd4_init(mem_start, mem_end); #endif #endif -#if !(SBPCD_ISSUE-1) - DPRINTF((DBG_INF,"SBPCD: init done.\n")); -#endif - return (mem_start); + return (mem_start); #endif MODULE } /*==========================================================================*/ #ifdef MODULE void cleanup_module(void) { - int j; - - if (MOD_IN_USE) - { - printk("%s module in use - can't remove it.\n", major_name); - return; - } - if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL)) - { - printk("What's that: can't unregister %s\n", major_name); - return; - } - release_region(CDo_command,4); - - for (j=0;j0) + vfree(D_S[j].aud_buf); + } + msg(DBG_INF, "%s module released.\n", major_name); } #endif MODULE /*==========================================================================*/ @@ -4433,53 +5311,70 @@ */ static int sbpcd_chk_disk_change(dev_t full_dev) { - int i, st; - - DPRINTF((DBG_CHK,"SBPCD: media_check (%d) called\n", MINOR(full_dev))); - return (0); /* "busy" test necessary before we really can check */ - - i=MINOR(full_dev); - if ( (i<0) || (i>=NR_SBPCD) || (DriveStruct[i].drv_id==-1) ) - { - printk("SBPCD: media_check: invalid device %04X.\n", full_dev); - return (-1); - } - - switch_drive(i); - - xx_ReadStatus(); /* command: give 1-byte status */ - st=ResponseStatus(); - DPRINTF((DBG_CHK,"SBPCD: media_check: %02X\n",DriveStruct[d].status_byte)); - if (st<0) - { - DPRINTF((DBG_INF,"SBPCD: media_check: ResponseStatus error.\n")); - return (1); /* status not obtainable */ - } - if (DriveStruct[d].CD_changed==0xFF) DPRINTF((DBG_CHK,"SBPCD: media_check: \"changed\" assumed.\n")); - if (!st_spinning) DPRINTF((DBG_CHK,"SBPCD: media_check: motor off.\n")); - if (!st_door_closed) - { - DPRINTF((DBG_CHK,"SBPCD: media_check: door open.\n")); - DriveStruct[d].CD_changed=0xFF; - } - if (!st_caddy_in) - { - DPRINTF((DBG_CHK,"SBPCD: media_check: no disk in drive.\n")); - DriveStruct[d].CD_changed=0xFF; - } - if (!st_diskok) DPRINTF((DBG_CHK,"SBPCD: media_check: !st_diskok.\n")); - + int i, st; + + msg(DBG_CHK,"media_check (%d) called\n", MINOR(full_dev)); + return (0); /* "busy" test necessary before we really can check */ + + i=MINOR(full_dev); + if ( (i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1) ) + { + msg(DBG_INF, "media_check: invalid device %04X.\n", full_dev); + return (-1); + } + + switch_drive(i); + + cc_ReadStatus(); /* command: give 1-byte status */ + st=ResponseStatus(); + msg(DBG_CHK,"media_check: %02X\n",D_S[d].status_bits); + if (st<0) + { + msg(DBG_INF,"media_check: ResponseStatus error.\n"); + return (1); /* status not obtainable */ + } + if (D_S[d].CD_changed==0xFF) msg(DBG_CHK,"media_check: \"changed\" assumed.\n"); + if (!st_spinning) msg(DBG_CHK,"media_check: motor off.\n"); + if (!st_door_closed) + { + msg(DBG_CHK,"media_check: door open.\n"); + D_S[d].CD_changed=0xFF; + } + if (!st_caddy_in) + { + msg(DBG_CHK,"media_check: no disk in drive.\n"); + D_S[d].open_count=0; + D_S[d].CD_changed=0xFF; + } + if (!st_diskok) msg(DBG_CHK,"media_check: !st_diskok.\n"); + #if 0000 - if (DriveStruct[d].CD_changed==0xFF) - { - DriveStruct[d].CD_changed=1; - return (1); /* driver had a change detected before */ - } + if (D_S[d].CD_changed==0xFF) + { + D_S[d].CD_changed=1; + return (1); /* driver had a change detected before */ + } #endif 0000 /* seems to give additional errors at the moment */ - - if (!st_diskok) return (1); /* disk not o.k. */ - if (!st_caddy_in) return (1); /* disk removed */ - if (!st_door_closed) return (1); /* door open */ - return (0); + + if (!st_diskok) return (1); /* disk not o.k. */ + if (!st_caddy_in) return (1); /* disk removed */ + if (!st_door_closed) return (1); /* door open */ + return (0); } /*==========================================================================*/ +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ diff -u --recursive --new-file v1.2.7/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog --- v1.2.7/linux/drivers/char/ChangeLog Sat Apr 29 12:42:21 1995 +++ linux/drivers/char/ChangeLog Tue May 2 08:38:31 1995 @@ -1,14 +1,36 @@ +Tue May 2 00:53:25 1995 + + * tty_io.c (tty_set_ldisc): Wait until the output buffer is + drained before closing the old line discipline --- needed + in only one case: XON/XOFF processing. + + * n_tty.c (n_tty_close): Don't bother waiting until the output + driver is closed; in general, the line discipline + shouldn't care if the hardware is finished + transmitting before the line discipline terminates. + + * tty_io.c (release_dev): Shutdown the line discipline after + decrementing the tty count variable; but set the + TTY_CLOSING flag so that we know that this tty structure + isn't long for this world. + + * tty_io.c (init_dev): Add sanity code to check to see if + TTY_CLOSING is set on a tty structure; if so, something + bad has happened (probably a line discipline close blocked + when it shouldn't have; so do a kernel printk and then + return an error). + Wed Apr 26 10:23:44 1995 Theodore Y. Ts'o - * tty_io.c (release_dev): Try to shutdown the line discpline + * tty_io.c (release_dev): Try to shutdown the line discipline *before* decrementing the tty count variable; this removes a potential race condition which occurs when the line - discpline close blocks, and another process then tries + discipline close blocks, and another process then tries open the same serial port. * serial.c (rs_hangup): When hanging up, flush the output buffer - befure shutting down the UART. Otherwise the line - discpline close blocks waiting for the characters to get + before shutting down the UART. Otherwise the line + discipline close blocks waiting for the characters to get flushed, which never happens until the serial port gets reused. Wed Apr 12 08:06:16 1995 Theodore Y. Ts'o diff -u --recursive --new-file v1.2.7/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c --- v1.2.7/linux/drivers/char/n_tty.c Mon Feb 20 21:29:52 1995 +++ linux/drivers/char/n_tty.c Tue May 2 08:33:51 1995 @@ -676,7 +676,6 @@ static void n_tty_close(struct tty_struct *tty) { - tty_wait_until_sent(tty, 0); n_tty_flush_buffer(tty); if (tty->read_buf) { free_page((unsigned long) tty->read_buf); diff -u --recursive --new-file v1.2.7/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v1.2.7/linux/drivers/char/tty_io.c Sat Apr 29 12:42:21 1995 +++ linux/drivers/char/tty_io.c Tue May 2 08:33:51 1995 @@ -204,6 +204,8 @@ return 0; /* We are already in the desired discipline */ o_ldisc = tty->ldisc; + tty_wait_until_sent(tty, 0); + /* Shutdown the current discipline. */ if (tty->ldisc.close) (tty->ldisc.close)(tty); @@ -865,8 +867,15 @@ } } tty = NULL; - } else + } else { + if ((*tty_loc)->flags & (1 << TTY_CLOSING)) { + printk("Attempt to open closing tty %s.\n", + tty_name(*tty_loc)); + printk("Ack!!!! This should never happen!!\n"); + return -EINVAL; + } (*tty_loc)->count++; + } if (driver->type == TTY_DRIVER_TYPE_PTY) { if (!*o_tp_loc) { *o_tp_loc = o_tp; @@ -1006,22 +1015,6 @@ tty->link->count = 0; } } - if (tty->count <= 1) { - /* - * Shutdown the current line discipline, and reset it - * to N_TTY. - */ - if (tty->ldisc.close) - (tty->ldisc.close)(tty); - tty->ldisc = ldiscs[N_TTY]; - tty->termios->c_line = N_TTY; - if (o_tty && o_tty->count <= 0) { - if (o_tty->ldisc.close) - (o_tty->ldisc.close)(o_tty); - o_tty->ldisc = ldiscs[N_TTY]; - o_tty->termios->c_line = N_TTY; - } - } if (--tty->count < 0) { printk("release_dev: bad tty->count (%d) for %s\n", tty->count, tty_name(tty)); @@ -1030,6 +1023,9 @@ if (tty->count) return; + /* + * We're committed; at this point, we must not block! + */ if (o_tty) { if (o_tty->count) return; @@ -1041,6 +1037,7 @@ #ifdef TTY_DEBUG_HANGUP printk("freeing tty structure..."); #endif + tty->flags |= (1 << TTY_CLOSING); /* * Make sure there aren't any processes that still think this @@ -1055,6 +1052,20 @@ (*p)->tty = NULL; } + /* + * Shutdown the current line discipline, and reset it to + * N_TTY. + */ + if (tty->ldisc.close) + (tty->ldisc.close)(tty); + tty->ldisc = ldiscs[N_TTY]; + tty->termios->c_line = N_TTY; + if (o_tty) { + if (o_tty->ldisc.close) + (o_tty->ldisc.close)(o_tty); + o_tty->ldisc = ldiscs[N_TTY]; + } + tty->driver.table[idx] = NULL; if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) { tty->driver.termios[idx] = NULL; diff -u --recursive --new-file v1.2.7/linux/drivers/net/8390.h linux/drivers/net/8390.h --- v1.2.7/linux/drivers/net/8390.h Sat Apr 29 12:42:21 1995 +++ linux/drivers/net/8390.h Tue May 2 08:01:57 1995 @@ -60,7 +60,7 @@ struct enet_statistics stat; }; -/* The maximum number of 8390 interrupt serivce routines called per IRQ. */ +/* The maximum number of 8390 interrupt service routines called per IRQ. */ #define MAX_SERVICE 12 /* The maximum number of jiffies waited before assuming a Tx failed. */ diff -u --recursive --new-file v1.2.7/linux/drivers/net/CONFIG linux/drivers/net/CONFIG --- v1.2.7/linux/drivers/net/CONFIG Sun Feb 12 16:07:22 1995 +++ linux/drivers/net/CONFIG Tue May 2 07:10:16 1995 @@ -40,10 +40,27 @@ # EWRK3_DEBUG Set the desired debug level # # DE4x5 The DIGITAL series of PCI/EISA Ethernet Cards, -# DE425, DE434 and DE435 -# DE4x5_DEBUG Set the desired debug level -# IS_ZYNX May allow driver to work with Zynx cards - +# DE425, DE434, DE435, DE500 +# DE4X5_DEBUG Set the desired debug level +# IS_NOT_DEC May allow driver to work with Zynx & SMC cards - # see linux/drivers/net/README.de4x5 +# DE4X5_AUTOSENSE (Default) auto media/mode selection +# If you want at least one board to not autosense then +# no board can autosense. For a board mix of several +# types, OR the manual values [eg for a DE500 (100M) with +# a DE450 (AUI) use '-DDE4X5_AUTOSENSE=(0x80|0x08)'] +# For full auto media/mode selection = 0x4000 +# For manual TP media selection = 0x01 +# For manual TP/Nway media selection (DC21041) = 0x02 +# For manual BNC media selection = 0x04 +# For manual AUI media selection = 0x08 +# For manual BNC/AUI media selection (DC21040) = 0x10 +# For manual 10Mb/s mode selection (DC21140) = 0x40 +# For manual 100Mb/s mode selection (DC21140) = 0x80 +# The DC21040 will default to TP if TP_NW is specified +# The DC21041 will default to BNC if BNC_AUI is specified +# The DC21140 needs it's speed to be manually set to +# 10Mb/s or 100Mb/s (AUTO defaults to 10Mb/s) # # The following options exist, but cannot be set in this file. @@ -66,4 +83,4 @@ PLIP_OPTS = DEPCA_OPTS = -DDEPCA_DEBUG=1 EWRK3_OPTS = -DEWRK3_DEBUG=1 -DE4x5_OPTS = -DDE4x5_DEBUG=1 +DE4X5_OPTS = -DDE4X5_DEBUG=1 -DDE4X5_AUTOSENSE=0x4000 diff -u --recursive --new-file v1.2.7/linux/drivers/net/README.de4x5 linux/drivers/net/README.de4x5 --- v1.2.7/linux/drivers/net/README.de4x5 Sun Feb 12 16:07:47 1995 +++ linux/drivers/net/README.de4x5 Tue May 2 07:10:16 1995 @@ -1,36 +1,47 @@ -The de425/de434/de435 driver in this distribution is designed to work with -the Digital Equipment Corporation series of PCI/EISA ethernet cards (DE425, -DE434, DE435) and with all kernels that support PCI. +The de425/de434/de435/de500 driver in this distribution is designed to work +with the Digital Equipment Corporation series of PCI/EISA ethernet cards +(DE425, DE434, DE435, DE500) and with all kernels that support PCI. Auto media detection is provided so that the media choice isn't compiled in -and is flexible enough to be able to reconfigure on-the-fly. +and is flexible enough to be able to reconfigure on-the-fly. This feature +hasn't been included for the DE500 unfortunately, due to a potential patent +dispute. When I get around to implementing the autosense algorithm by myself +(which could legally be difficult to prove since I'm part of the group that +has implemented the patented algorithm) you'll have an auto speed selection +for the de500. If you want the auto speed feature yell at Digital. If enough +of you do things might change. -The ability to load this driver as a loadable module has been included, +The ability to load this driver as a loadable module has been included, although I don't recommend its use with PCI, since PCI dynamically allocates -where the card will go at boot time. +where the card will go at boot time (i.e. the card would have to be present +in the system at boot time for its address/IRQ to be assigned). -The performance we've achieved so far has been measured through the 'ttcp' -tool at 1.08MB/s. This measures the total tcp stack performance which -includes the card, so don't expect to get much nearer the 1.25MB/s -theoretical ethernet rate. - - ************************************************************************ - However there is still a known bug which causes ttcp to hang on transmit - (receive is OK), although the adapter/driver continues to function - normally for other applications e.g. nfs mounting disks, pinging etc. - The cause is under investigation. - ************************************************************************ +The performance we've achieved so far has been measured through the 'ttcp' +tool at 1.06MB/s for TCP and 1.17MB/s for UDP. This measures the total +stack performance which includes the card, so don't expect to get much +nearer the 1.25MB/s theoretical ethernet rate. + + TCP UDP + TX RX TX RX + DE425 1030k 997k 1170k 1128k (EISA on a Dell 433DE) + DE434 1063k 995k 1170k 1125k (PCI: DECpc XL 466d2) + DE435 1063k 995k 1170k 1125k (PCI: DECpc XL 466d2) + DE500 1063k 998k 1170k 1125k in 10Mb/s mode (PCI: DECpc XL 466d2) + +All values are typical (in kBytes/sec) from a sample of 4 for each +measurement. Their error is approx +/-20k on a quiet (private) network and +also depend on what load the CPU has, CPU speed etc. -ZYNX cards, which use the PCI DECchip DC21040, are not specifically +ZYNX and SMC cards, which use the PCI DECchip DC21040, are not specifically supported in this driver because a) I have no information on them. b) I cannot test them with the driver. c) Donald Becker's 'tulip.c' driver works with them....well one person says - they do and another doesn't, so take your pick! + they do and another says they do not, so take your pick! This driver can be made to work with the ZYNX (and may be the SMC) card by -setting a compile time flag in linux/drivers/net/CONFIG +setting a compile time flag (IS_NOT_DEC) in linux/drivers/net/CONFIG Enjoy! diff -u --recursive --new-file v1.2.7/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c --- v1.2.7/linux/drivers/net/de4x5.c Sun Feb 12 16:07:22 1995 +++ linux/drivers/net/de4x5.c Wed May 3 07:17:10 1995 @@ -1,6 +1,6 @@ /* de4x5.c: A DIGITAL DE425/DE434/DE435 ethernet driver for linux. - Copyright 1994 Digital Equipment Corporation. + Copyright 1994, 1995 Digital Equipment Corporation. This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. @@ -11,17 +11,22 @@ DE425 TP/COAX EISA DE434 TP PCI DE435 TP/COAX/AUI PCI + DE500 10/100 PCI Fasternet - The driver has been tested on a relatively busy network using the DE425 - and DE435 cards and benchmarked with 'ttcp': it transferred 16M of data - at 1.08MB/s (8.6Mb/s) to a DECstation 5000/200. - - ************************************************************************ - However there is still a known bug which causes ttcp to hang on transmit - (receive is OK), although the adapter/driver continues to function - normally for other applications e.g. nfs mounting disks, pinging etc. - The cause is under investigation. - ************************************************************************ + The driver has been tested on a relatively busy network using the DE425, + DE434, DE435 and DE500 cards and benchmarked with 'ttcp': it transferred + 16M of data to a DECstation 5000/200 as follows: + + TCP UDP + TX RX TX RX + DE425 1030k 997k 1170k 1128k + DE434 1063k 995k 1170k 1125k + DE435 1063k 995k 1170k 1125k + DE500 1063k 998k 1170k 1125k in 10Mb/s mode + + All values are typical (in kBytes/sec) from a sample of 4 for each + measurement. Their error is +/-20k on a quiet (private) network and also + depend on what load the CPU has. The author may be reached as davies@wanton.lkg.dec.com or Digital Equipment Corporation, 550 King Street, Littleton MA 01460. @@ -98,9 +103,6 @@ TO DO: ------ - 1. Add DC21041 Nway/Autosense support - 2. Add DC21140 Autosense support - 3. Add timer support Revision History @@ -109,18 +111,26 @@ Version Date Description 0.1 17-Nov-94 Initial writing. ALPHA code release. - 0.2 13-Jan-95 Added PCI support for DE435's - 0.21 19-Jan-95 Added auto media detection - 0.22 10-Feb-95 Fix interrupt handler call - Fix recognition bug reported by - Add request/release_region code - Add loadable modules support for PCI - Clean up loadable modules support + 0.2 13-Jan-95 Added PCI support for DE435's. + 0.21 19-Jan-95 Added auto media detection. + 0.22 10-Feb-95 Fix interrupt handler call . + Fix recognition bug reported by . + Add request/release_region code. + Add loadable modules support for PCI. + Clean up loadable modules support. + 0.23 28-Feb-95 Added DC21041 and DC21140 support. + Fix missed frame counter value and initialisation. + Fixed EISA probe. + 0.24 11-Apr-95 Change delay routine to use . + Change TX_BUFFS_AVAIL macro. + Change media autodetection to allow manual setting. + Completed DE500 (DC21140) support. + 0.241 18-Apr-95 Interim release without DE500 Autosense Algorithm. ========================================================================= */ -static char *version = "de4x5.c:v0.22 2/10/95 davies@wanton.lkg.dec.com\n"; +static char *version = "de4x5.c:v0.241 4/18/95 davies@wanton.lkg.dec.com\n"; #include #ifdef MODULE @@ -140,6 +150,7 @@ #include #include #include +#include #include #include #include @@ -161,6 +172,12 @@ static int de4x5_debug = 1; #endif +#ifdef DE4X5_AUTOSENSE /* Should be done on a per adapter basis */ +static int de4x5_autosense = DE4X5_AUTOSENSE; +#else +static int de4x5_autosense = AUTO; /* Do auto media/mode sensing */ +#endif + /* ** Ethernet PROM defines */ @@ -198,79 +215,102 @@ #define DE4X5_PCI_TOTAL_SIZE 0x80 /* I/O address extent */ /* -** Timer defines -*/ -#define TIMER_WIDTH 16 -#define TIMER_PORT 0x43 -#define TIMER_LATCH 0x06 -#define TIMER_READ 0x40 -#define TIMER_TICK 419 /*ns*/ -#define DELAY_QUANT 5 /*us*/ - -#define LWPAD ((long)(sizeof(long) - 1)) /* for longword alignment */ +** Memory Alignment. Each descriptor is 4 longwords long. To force a +** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and +** DESC_ALIGN. ALIGN aligns the start address of the private memory area +** and hence the RX descriptor ring's first entry. +*/ +#define ALIGN4 ((u_long)4 - 1) /* 1 longword align */ +#define ALIGN8 ((u_long)8 - 1) /* 2 longword align */ +#define ALIGN16 ((u_long)16 - 1) /* 4 longword align */ +#define ALIGN32 ((u_long)32 - 1) /* 8 longword align */ +#define ALIGN64 ((u_long)64 - 1) /* 16 longword align */ +#define ALIGN128 ((u_long)128 - 1) /* 32 longword align */ + +#define ALIGN ALIGN32 /* Keep the DC21040 happy... */ +#define CACHE_ALIGN CAL_16LONG +#define DESC_SKIP_LEN DSL_0 /* Must agree with DESC_ALIGN */ +/*#define DESC_ALIGN u_long dummy[4]; / * Must agree with DESC_SKIP_LEN */ +#define DESC_ALIGN -#ifndef IS_ZYNX /* See README.de4x5 for using this */ -static int is_zynx = 0; +#ifndef IS_NOT_DEC /* See README.de4x5 for using this */ +static int is_not_dec = 0; #else -static int is_zynx = 1; +static int is_not_dec = 1; #endif /* ** DE4X5 IRQ ENABLE/DISABLE */ -static u_long irq_mask = IMR_RIM | IMR_TIM | IMR_TUM ; +static u_long irq_mask = IMR_SEM | IMR_RIM | IMR_RUM | IMR_TIM | IMR_TUM ; static u_long irq_en = IMR_NIM | IMR_AIM; -#define ENABLE_IRQs \ +#define ENABLE_IRQs { \ imr |= irq_en;\ - outl(imr, DE4X5_IMR) /* Enable the IRQs */ + outl(imr, DE4X5_IMR); /* Enable the IRQs */\ +} -#define DISABLE_IRQs \ +#define DISABLE_IRQs {\ imr = inl(DE4X5_IMR);\ imr &= ~irq_en;\ - outl(imr, DE4X5_IMR) /* Disable the IRQs */ + outl(imr, DE4X5_IMR); /* Disable the IRQs */\ +} -#define UNMASK_IRQs \ +#define UNMASK_IRQs {\ imr |= irq_mask;\ - outl(imr, DE4X5_IMR) /* Unmask the IRQs */ + outl(imr, DE4X5_IMR); /* Unmask the IRQs */\ +} -#define MASK_IRQs \ +#define MASK_IRQs {\ imr = inl(DE4X5_IMR);\ imr &= ~irq_mask;\ - outl(imr, DE4X5_IMR) /* Mask the IRQs */ + outl(imr, DE4X5_IMR); /* Mask the IRQs */\ +} /* ** DE4X5 START/STOP */ -#define START_DE4X5 \ +#define START_DE4X5 {\ omr = inl(DE4X5_OMR);\ omr |= OMR_ST | OMR_SR;\ - outl(omr, DE4X5_OMR) /* Enable the TX and/or RX */ + outl(omr, DE4X5_OMR); /* Enable the TX and/or RX */\ +} -#define STOP_DE4X5 \ +#define STOP_DE4X5 {\ omr = inl(DE4X5_OMR);\ omr &= ~(OMR_ST|OMR_SR);\ - outl(omr, DE4X5_OMR) /* Disable the TX and/or RX */ + outl(omr, DE4X5_OMR); /* Disable the TX and/or RX */ \ +} /* ** DE4X5 SIA RESET */ -#define RESET_SIA \ - outl(SICR_RESET, DE4X5_SICR); /* Reset SIA connectivity regs */ \ - outl(STRR_RESET, DE4X5_STRR); /* Write reset values */ \ - outl(SIGR_RESET, DE4X5_SIGR) /* Write reset values */ +#define RESET_SIA outl(0, DE4X5_SICR); /* Reset SIA connectivity regs */ + +/* +** SROM Structure +*/ +struct de4x5_srom { + char reserved[18]; + char version; + char num_adapters; + char ieee_addr[6]; + char info[100]; + short chksum; +}; /* ** DE4X5 Descriptors. Make sure that all the RX buffers are contiguous ** and have sizes of both a power of 2 and a multiple of 4. ** A size of 256 bytes for each buffer was chosen because over 90% of -** all packets in our network are <256 bytes long. +** all packets in our network are <256 bytes long and 64 longword alignment +** is possible. */ -#define NUM_RX_DESC 64 /* Number of RX descriptors */ +#define NUM_RX_DESC 8 /* Number of RX descriptors */ #define NUM_TX_DESC 8 /* Number of TX descriptors */ #define BUFF_ALLOC_RETRIES 10 /* In case of memory shortage */ -#define RX_BUFF_SZ 256 /* Power of 2 for kmalloc and */ +#define RX_BUFF_SZ 1536 /* Power of 2 for kmalloc and */ /* Multiple of 4 for DC21040 */ struct de4x5_desc { @@ -278,6 +318,7 @@ u_long des1; char *buf; char *next; + DESC_ALIGN }; /* @@ -308,48 +349,76 @@ char rxRingSize; char txRingSize; char bus; /* EISA or PCI */ + u_short chipset; /* DC21040, DC21041 or DC21140 */ + long media; /* Media (eg TP), mode (eg 100B)*/ + int autosense; /* Allow/disallow autosensing */ + int tx_enable; /* Enable descriptor polling */ char lostMedia; /* Possibly lost media */ + int setup_f; /* Setup frame filtering type */ }; + +/* +** The transmit ring full condition is described by the tx_old and tx_new +** pointers by: +** tx_old = tx_new Empty ring +** tx_old = tx_new+1 Full ring +** tx_old+txRingSize = tx_new+1 Full ring (wrapped condition) +*/ #define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ lp->tx_old+lp->txRingSize-lp->tx_new-1:\ lp->tx_old -lp->tx_new-1) -#define TX_SUSPENDED (((sts & STS_TS) ^ TS_SUSP)==0) +/*#define TX_BUFFS_AVAIL ((lp->tx_ring[lp->tx_new].status)>=0 ? 1 : 0)*/ /* ** Public Functions */ -static int de4x5_open(struct device *dev); -static int de4x5_queue_pkt(struct sk_buff *skb, struct device *dev); -static void de4x5_interrupt(int irq, struct pt_regs * regs); -static int de4x5_close(struct device *dev); -static struct enet_statistics *de4x5_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev, int num_addrs, void *addrs); -static int de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd); +static int de4x5_open(struct device *dev); +static int de4x5_queue_pkt(struct sk_buff *skb, struct device *dev); +static void de4x5_interrupt(int irq, struct pt_regs *regs); +static int de4x5_close(struct device *dev); +static struct enet_statistics *de4x5_get_stats(struct device *dev); +static void set_multicast_list(struct device *dev, int num_addrs, void *addrs); +static int de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd); /* ** Private functions */ -static int de4x5_hw_init(struct device *dev, short iobase); -static int de4x5_init(struct device *dev); -static int de4x5_rx(struct device *dev); -static int de4x5_tx(struct device *dev); - -static int autoconf_media(struct device *dev); -static void create_packet(struct device *dev, char *frame, int len); -static u_short dce_get_ticks(void); -static void dce_us_delay(u_long usec); -static void dce_ms_delay(u_long msec); -static void load_packet(struct device *dev, char *buf, u_long flags, struct sk_buff *skb); -static void EISA_signature(char * name, short iobase); -static int DevicePresent(short iobase); -static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs, char *multicast_table); - -static int aprom_crc (struct device *dev); - -static void eisa_probe(struct device *dev, short iobase); -static void pci_probe(struct device *dev, short iobase); -static struct device *alloc_device(struct device *dev, int iobase); +static int de4x5_hw_init(struct device *dev, short iobase); +static int de4x5_init(struct device *dev); +static int de4x5_rx(struct device *dev); +static int de4x5_tx(struct device *dev); + +static int autoconf_media(struct device *dev); +static void create_packet(struct device *dev, char *frame, int len); +static void dce_us_delay(u_long usec); +static void dce_ms_delay(u_long msec); +static void load_packet(struct device *dev, char *buf, u_long flags, struct sk_buff *skb); +static void dc21040_autoconf(struct device *dev); +static void dc21041_autoconf(struct device *dev); +static void dc21140_autoconf(struct device *dev); +static long test_media(struct device *dev, long irqs, long irq_mask, long csr13, long csr14, long csr15, long msec); +static long ping_media(struct device *dev); +static void reset_init_sia(struct device *dev, long sicr, long strr, long sigr); +static int test_ans(struct device *dev, long irqs, long irq_mask, long msec); +static void load_ms_timer(struct device *dev, u_long msec); +static int EISA_signature(char *name, long eisa_id); +static int DevicePresent(short iobase); +static short srom_rd(u_short address, u_char offset); +static void srom_latch(u_long command, u_short address); +static void srom_command(u_long command, u_short address); +static void srom_address(u_long command, u_short address, u_char offset); +static short srom_data(u_long command, u_short address); +/*static void srom_busy(u_long command, u_short address);*/ +static void sendto_srom(u_long command, u_short addr); +static long getfrom_srom(u_short addr); +static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs); +static int aprom_crc (struct device *dev); + +static void eisa_probe(struct device *dev, short iobase); +static void pci_probe(struct device *dev, short iobase); +static struct device *alloc_device(struct device *dev, int iobase); +static char *build_setup_frame(struct device *dev, int mode); #ifdef MODULE int init_module(void); @@ -371,6 +440,9 @@ static struct bus_type { int bus; int device; + int chipset; + struct de4x5_srom srom; + int autosense; } bus; /* @@ -382,8 +454,7 @@ outl(i | BMR_SWR, DE4X5_BMR);\ outl(i, DE4X5_BMR);\ for (i=0;i<5;i++) inl(DE4X5_BMR);\ - } - +} @@ -409,7 +480,7 @@ ** Walk the device list to check that at least one device ** initialised OK */ - for (; dev->priv == NULL && dev->next != NULL; dev = dev->next); + for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next); if (dev->priv) status = 0; if (iobase == 0) autoprobed = 1; @@ -422,10 +493,16 @@ de4x5_hw_init(struct device *dev, short iobase) { struct bus_type *lp = &bus; - int tmpbus, i, j, status=0; + int tmpbus, tmpchs, i, j, status=0; char *tmp; u_long nicsr; + /* Ensure we're not sleeping */ + if (lp->chipset == DC21041) { + outl(0, PCI_CFDA); + dce_ms_delay(10); + } + RESET_DE4X5; if (((nicsr=inl(DE4X5_STS)) & (STS_TS | STS_RS)) == 0) { @@ -433,10 +510,14 @@ ** Now find out what kind of DC21040/DC21041/DC21140 board we have. */ if (lp->bus == PCI) { - if (!is_zynx) { - strcpy(name, "DE435"); + if (!is_not_dec) { + if ((lp->chipset == DC21040) || (lp->chipset == DC21041)) { + strcpy(name, "DE435"); + } else if (lp->chipset == DC21140) { + strcpy(name, "DE500"); /* Must read the SROM here! */ + } } else { - strcpy(name, "ZYNX"); + strcpy(name, "UNKNOWN"); } } else { EISA_signature(name, EISA_ID0); @@ -444,8 +525,6 @@ if (*name != '\0') { /* found a board signature */ dev->base_addr = iobase; - request_region(iobase, (lp->bus == PCI ? DE4X5_PCI_TOTAL_SIZE : - DE4X5_EISA_TOTAL_SIZE), name); if (lp->bus == EISA) { printk("%s: %s at %#3x (EISA slot %d)", @@ -462,6 +541,7 @@ printk("%2.2x,\n", dev->dev_addr[i]); tmpbus = lp->bus; + tmpchs = lp->chipset; if (status == 0) { struct de4x5_private *lp; @@ -470,26 +550,50 @@ ** Reserve a section of kernel memory for the adapter ** private area and the TX/RX descriptor rings. */ - dev->priv = (void *) kmalloc(sizeof(struct de4x5_private) + LWPAD, + dev->priv = (void *) kmalloc(sizeof(struct de4x5_private) + ALIGN, GFP_KERNEL); /* ** Align to a longword boundary */ - dev->priv = (void *)(((u_long)dev->priv + LWPAD) & ~LWPAD); + dev->priv = (void *)(((u_long)dev->priv + ALIGN) & ~ALIGN); lp = (struct de4x5_private *)dev->priv; memset(dev->priv, 0, sizeof(struct de4x5_private)); lp->bus = tmpbus; - strcpy(lp->adapter_name, name); + lp->chipset = tmpchs; + + /* + ** Choose autosensing + */ + if (de4x5_autosense & AUTO) { + lp->autosense = AUTO; + } else { + if (lp->chipset != DC21140) { + if ((lp->chipset == DC21040) && (de4x5_autosense & TP_NW)) { + de4x5_autosense = TP; + } + if ((lp->chipset == DC21041) && (de4x5_autosense & BNC_AUI)) { + de4x5_autosense = BNC; + } + lp->autosense = de4x5_autosense & 0x001f; + } else { + lp->autosense = de4x5_autosense & 0x00c0; + } + } + + sprintf(lp->adapter_name,"%s (%s)", name, dev->name); + request_region(iobase, (lp->bus == PCI ? DE4X5_PCI_TOTAL_SIZE : + DE4X5_EISA_TOTAL_SIZE), + lp->adapter_name); /* ** Allocate contiguous receive buffers, long word aligned. ** This could be a possible memory leak if the private area ** is ever hosed. */ - for (tmp=NULL, j=0; jrx_ring[i].status = 0; lp->rx_ring[i].des1 = RX_BUFF_SZ; @@ -508,8 +612,10 @@ lp->tx_ring[lp->txRingSize - 1].des1 |= TD_TER; /* Tell the adapter where the TX/RX rings are located. */ - outl((u_long)lp->rx_ring, DE4X5_RRBA); - outl((u_long)lp->tx_ring, DE4X5_TRBA); + outl((long)lp->rx_ring, DE4X5_RRBA); + outl((long)lp->tx_ring, DE4X5_TRBA); + + lp->tx_enable = TRUE; if (dev->irq < 2) { #ifndef MODULE @@ -526,7 +632,7 @@ printk(" and failed to detect IRQ line.\n"); status = -ENXIO; } else { - for (dev->irq=0,i=0; iirq; i++) { + for (dev->irq=0,i=0; (iirq); i++) { if (irqnum == de4x5_irq[i]) { dev->irq = irqnum; printk(" and uses IRQ%d.\n", dev->irq); @@ -550,13 +656,13 @@ dev->name); status = -ENXIO; } + if (status) release_region(iobase, (lp->bus == PCI ? + DE4X5_PCI_TOTAL_SIZE : + DE4X5_EISA_TOTAL_SIZE)); } else { printk(" which has an Ethernet PROM CRC error.\n"); status = -ENXIO; } - if (status) release_region(iobase, (lp->bus == PCI ? - DE4X5_PCI_TOTAL_SIZE : - DE4X5_EISA_TOTAL_SIZE)); } else { status = -ENXIO; } @@ -583,13 +689,19 @@ /* Fill in the generic field of the device structure. */ ether_setup(dev); + + /* Let the adapter sleep to save power */ + if (lp->chipset == DC21041) { + outl(0, DE4X5_SICR); + outl(CFDA_PSM, PCI_CFDA); + } } else { /* Incorrectly initialised hardware */ struct de4x5_private *lp = (struct de4x5_private *)dev->priv; if (lp) { - kfree_s(lp->rx_ring[0].buf, RX_BUFF_SZ * NUM_RX_DESC + LWPAD); + kfree_s(lp->rx_ring[0].buf, RX_BUFF_SZ * NUM_RX_DESC + ALIGN); } if (dev->priv) { - kfree_s(dev->priv, sizeof(struct de4x5_private) + LWPAD); + kfree_s(dev->priv, sizeof(struct de4x5_private) + ALIGN); dev->priv = NULL; } } @@ -604,12 +716,15 @@ struct de4x5_private *lp = (struct de4x5_private *)dev->priv; short iobase = dev->base_addr; int i, status = 0; - u_long imr, omr, sts; + long imr, omr, sts; /* - ** Stop the TX and RX... + ** Wake up the adapter */ - STOP_DE4X5; + if (lp->chipset == DC21041) { + outl(0, PCI_CFDA); + dce_ms_delay(10); + } if (request_irq(dev->irq, (void *)de4x5_interrupt, 0, lp->adapter_name)) { printk("de4x5_open(): Requested IRQ%d is busy\n",dev->irq); @@ -669,21 +784,19 @@ dev->tbusy = 0; dev->start = 1; dev->interrupt = UNMASK_INTERRUPTS; - - /* - ** Reset any pending interrupts - */ - sts = inl(DE4X5_STS); - outl(sts, DE4X5_STS); + dev->trans_start = jiffies; - /* - ** Unmask and enable DE4X5 board interrupts - */ + START_DE4X5; + + /* Unmask and enable DE4X5 board interrupts */ imr = 0; UNMASK_IRQs; - ENABLE_IRQs; - START_DE4X5; + /* Reset any pending (stale) interrupts */ + sts = inl(DE4X5_STS); + outl(sts, DE4X5_STS); + + ENABLE_IRQs; } if (de4x5_debug > 1) { printk("\tsts: 0x%08x\n", inl(DE4X5_STS)); @@ -703,70 +816,63 @@ } /* -** Initialize the DE4X5 operating conditions +** Initialize the DE4X5 operating conditions. NB: a chip problem with the +** DC21140 requires using perfect filtering mode for that chip. Since I can't +** see why I'd want > 14 multicast addresses, I may change all chips to use +** the perfect filtering mode. Keep the DMA burst length at 8: there seems +** to be data corruption problems if it is larger (UDP errors seen from a +** ttcp source). */ static int de4x5_init(struct device *dev) { struct de4x5_private *lp = (struct de4x5_private *)dev->priv; short iobase = dev->base_addr; - int offset, status = 0; - u_long i, j, bmr, omr; - char *pa; + int status = 0; + long i, j, bmr, omr; + + /* Lock out other processes whilst setting up the hardware */ + set_bit(0, (void *)&dev->tbusy); - /* Ensure a full reset */ RESET_DE4X5; - /* Set up automatic transmit polling every 1.6ms */ bmr = inl(DE4X5_BMR); - bmr |= TAP_1_6MS | CAL_16LONG; + bmr |= PBL_8 | DESC_SKIP_LEN | CACHE_ALIGN; outl(bmr, DE4X5_BMR); - /* Set up imperfect filtering mode as default, turn off promiscuous mode */ - omr = OMR_HP; - offset = IMPERF_PA_OFFSET; - - /* Lock out other processes whilst setting up the hardware */ - set_bit(0, (void *)&dev->tbusy); - - /* Rewrite the descriptor lists' start addresses */ - outl((u_long)lp->rx_ring, DE4X5_RRBA); /* Start of RX Descriptor List */ - outl((u_long)lp->tx_ring, DE4X5_TRBA); /* Start of TX Descriptor List */ + if (lp->chipset != DC21140) { + omr = TR_96; + lp->setup_f = HASH_PERF; + } else { + omr = OMR_SDP | OMR_SF; + lp->setup_f = PERFECT; + } + outl((long)lp->rx_ring, DE4X5_RRBA); + outl((long)lp->tx_ring, DE4X5_TRBA); - /* Reset the buffer pointers */ lp->rx_new = lp->rx_old = 0; lp->tx_new = lp->tx_old = 0; - /* Initialize each descriptor ownership in the RX ring */ for (i = 0; i < lp->rxRingSize; i++) { lp->rx_ring[i].status = R_OWN; } - /* Initialize each descriptor ownership in the TX ring */ for (i = 0; i < lp->txRingSize; i++) { lp->tx_ring[i].status = 0; } - /* Initialise the setup frame prior to starting the receive process */ - memset(lp->setup_frame, 0, SETUP_FRAME_LEN); + /* Build the setup frame depending on filtering mode */ + SetMulticastFilter(dev, 0, NULL); - /* Insert the physical address */ - for (pa=lp->setup_frame+offset, j=0; jdev_addr[j]; - if (j & 0x01) pa += 2; + if (lp->chipset != DC21140) { + load_packet(dev, lp->setup_frame, HASH_F|TD_SET|SETUP_FRAME_LEN, NULL); + } else { + load_packet(dev, lp->setup_frame, PERFECT_F|TD_SET|SETUP_FRAME_LEN, NULL); } - - /* Clear the multicast list */ - set_multicast_list(dev, 0, NULL); - - /* Tell the hardware there's a new packet to be sent */ - load_packet(dev, lp->setup_frame, HASH_F | TD_SET | SETUP_FRAME_LEN, NULL); - - /* Start the TX process */ outl(omr|OMR_ST, DE4X5_OMR); /* Poll for completion of setup frame (interrupts are disabled for now) */ - for (j=0, i=0;i<100 && j==0;i++) { + for (j=0, i=0;(i<100) && (j==0);i++) { if (lp->tx_ring[lp->tx_new].status >= 0) j=1; } outl(omr, DE4X5_OMR); /* Stop everything! */ @@ -777,7 +883,6 @@ status = -EIO; } - /* Update pointers */ lp->tx_new = (++lp->tx_new) % lp->txRingSize; lp->tx_old = lp->tx_new; @@ -807,13 +912,9 @@ ** The 'lostMedia' threshold accounts for transient errors that ** were noticed when switching media. */ - if (dev->tbusy || (lp->lostMedia > 3)) { + if (dev->tbusy || (lp->lostMedia > LOST_MEDIA_THRESHOLD)) { int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 10 && !lp->lostMedia) { - /* Check if TX ring is full or not - 'tbusy' cleared if not full. */ - if ((TX_BUFFS_AVAIL > 0) && dev->tbusy) { - dev->tbusy = 0; - } + if (tickssofar < 10 && (lp->lostMedia <= LOST_MEDIA_THRESHOLD)) { status = -1; } else { printk("%s: transmit timed out, status %08x, tbusy:%d, lostMedia:%d tickssofar:%d, resetting.\n",dev->name, inl(DE4X5_STS), dev->tbusy, lp->lostMedia, tickssofar); @@ -825,21 +926,21 @@ /* Unmask DE4X5 board interrupts */ if (!status) { /* Start here to clean stale interrupts later */ + dev->interrupt = UNMASK_INTERRUPTS; + dev->start = 1; + dev->tbusy = 0; dev->trans_start = jiffies; + START_DE4X5; + /* Unmask DE4X5 board interrupts */ + imr = 0; + UNMASK_IRQs; + /* Clear any pending (stale) interrupts */ sts = inl(DE4X5_STS); outl(sts, DE4X5_STS); - /* Unmask DE4X5 board interrupts */ - imr = 0; - UNMASK_IRQs; - - dev->interrupt = UNMASK_INTERRUPTS; - dev->start = 1; - dev->tbusy = 0; - ENABLE_IRQs; } else { printk("%s: hardware initialisation failure, status %08x.\n", @@ -857,20 +958,18 @@ if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); - if (TX_BUFFS_AVAIL > 0) { /* Fill in a Tx ring entry */ - if (((u_long)skb->data & ~0x03) != (u_long)skb->data) { - printk("%s: TX skb buffer alignment prob..\n", dev->name); - } - + if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */ load_packet(dev, skb->data, TD_IC | TD_LS | TD_FS | skb->len, skb); - outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */ + if (lp->tx_enable) { + outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */ + } lp->tx_new = (++lp->tx_new) % lp->txRingSize; /* Ensure a wrap */ dev->trans_start = jiffies; } - if (TX_BUFFS_AVAIL > 0) { + if (TX_BUFFS_AVAIL) { dev->tbusy = 0; /* Another pkt may be queued */ } } @@ -882,12 +981,12 @@ ** The DE4X5 interrupt handler. */ static void -de4x5_interrupt(int irq, struct pt_regs * regs) +de4x5_interrupt(int irq, struct pt_regs *regs) { struct device *dev = (struct device *)(irq2dev_map[irq]); struct de4x5_private *lp; int iobase; - u_long imr, sts; + u_long imr, omr, sts; if (dev == NULL) { printk ("de4x5_interrupt(): irq %d for unknown device.\n", irq); @@ -909,19 +1008,22 @@ sts = inl(DE4X5_STS); MASK_IRQs; - /* - ** Acknowledge the DE4X5 board interrupts - */ - outl(sts, DE4X5_STS); + outl(sts, DE4X5_STS); /* Reset the board interrupts */ - if (sts & STS_RI) /* Rx interrupt (packet[s] arrived) */ + if (sts & (STS_RI | STS_RU)) /* Rx interrupt (packet[s] arrived) */ de4x5_rx(dev); - if (sts & STS_TI) /* Tx interrupt (packet sent) */ + if (sts & (STS_TI | STS_TU)) /* Tx interrupt (packet sent) */ de4x5_tx(dev); - if ((TX_BUFFS_AVAIL > 0) && dev->tbusy) { /* any resources available? */ - dev->tbusy = 0; /* clear TX busy flag */ + if (sts & STS_SE) { /* Bus Error */ + STOP_DE4X5; + printk("%s: Fatal bus error occurred, sts=0x%08lx, device stopped.\n", + dev->name, sts); + } + + if (TX_BUFFS_AVAIL && dev->tbusy) {/* Any resources available? */ + dev->tbusy = 0; /* Clear TX busy flag */ mark_bh(NET_BH); } @@ -941,7 +1043,6 @@ volatile long status; char *buf; - /* Loop over any new packets for sending up the stack */ for (entry = lp->rx_new; lp->rx_ring[entry].status >= 0;entry = lp->rx_new) { status = lp->rx_ring[entry].status; @@ -957,7 +1058,7 @@ if (status & RD_OF) lp->stats.rx_fifo_errors++; } else { /* A valid frame received */ struct sk_buff *skb; - short pkt_len = (short)(lp->rx_ring[entry].status >> 16); + short pkt_len = (short)(lp->rx_ring[entry].status >> 16) - 4; if ((skb = alloc_skb(pkt_len, GFP_ATOMIC)) != NULL) { skb->len = pkt_len; @@ -982,7 +1083,7 @@ */ lp->stats.rx_packets++; for (i=1; ipktStats.bins[i]++; i = DE4X5_PKT_STAT_SZ; } @@ -1034,7 +1135,7 @@ { struct de4x5_private *lp = (struct de4x5_private *)dev->priv; int entry, iobase = dev->base_addr; - volatile long status; + long status; for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { status = lp->tx_ring[entry].status; @@ -1100,6 +1201,12 @@ MOD_DEC_USE_COUNT; + /* Put the adapter to sleep to save power */ + if (lp->chipset == DC21041) { + outl(0, DE4X5_SICR); + outl(CFDA_PSM, PCI_CFDA); + } + return 0; } @@ -1109,7 +1216,7 @@ struct de4x5_private *lp = (struct de4x5_private *)dev->priv; int iobase = dev->base_addr; - lp->stats.rx_missed_errors = (int) inl(DE4X5_MFC); + lp->stats.rx_missed_errors = (int) (inl(DE4X5_MFC) & (MFC_OVFL | MFC_CNTR)); return &lp->stats; } @@ -1128,42 +1235,39 @@ } /* ** Set or clear the multicast filter for this adaptor. -** num_addrs == -1 Promiscuous mode, receive all packets +** num_addrs == -1 Promiscuous mode, receive all packets - not supported. +** Use the ioctls. ** num_addrs == 0 Normal mode, clear multicast list ** num_addrs > 0 Multicast mode, receive normal and MC packets, and do ** best-effort filtering. ** num_addrs == HASH_TABLE_LEN -** Set all multicast bits +** Set all multicast bits (pass all multicasts). */ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs) { struct de4x5_private *lp = (struct de4x5_private *)dev->priv; int iobase = dev->base_addr; - u_long omr; /* First, double check that the adapter is open */ if (irq2dev_map[dev->irq] != NULL) { - omr = inl(DE4X5_OMR); - if (num_addrs >= 0) { - SetMulticastFilter(dev, num_addrs, (char *)addrs, lp->setup_frame); - - /* Tell the hardware that there's a new packet to be sent */ - load_packet(dev, lp->setup_frame, TD_IC | HASH_F | TD_SET | + SetMulticastFilter(dev, num_addrs, (char *)addrs); + if (lp->setup_f == HASH_PERF) { + load_packet(dev, lp->setup_frame, TD_IC | HASH_F | TD_SET | + SETUP_FRAME_LEN, NULL); + } else { + load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | SETUP_FRAME_LEN, NULL); + } + lp->tx_new = (++lp->tx_new) % lp->txRingSize; outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */ - - omr &= ~OMR_PR; - omr |= OMR_PM; - outl(omr, DE4X5_OMR); - } else { /* set promiscuous mode */ - omr |= OMR_PR; - omr &= ~OMR_PM; - outl(omr, DE4X5_OMR); + dev->trans_start = jiffies; } } + + return; } /* @@ -1171,49 +1275,58 @@ ** from a list of ethernet multicast addresses. ** Little endian crc one liner from Matt Thomas, DEC. */ -static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs, char *multicast_table) +static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs) { - char j, bit, byte; - long *p = (long *) multicast_table; - int i; + struct de4x5_private *lp = (struct de4x5_private *)dev->priv; + int i, j, bit, byte, iobase = dev->base_addr; u_short hashcode; - u_long crc, poly = CRC_POLYNOMIAL_LE; + u_long crc, omr, poly = CRC_POLYNOMIAL_LE; + char *pa; - if (num_addrs == HASH_TABLE_LEN) { - for (i=0; i<(HASH_TABLE_LEN >> 4); i++) { - *p++ = 0x0000ffff; - } - } else { - /* Clear the multicast table except for the broadcast bit */ - memset(multicast_table, 0, (HASH_TABLE_LEN >> 2)); - *(multicast_table + (HASH_TABLE_LEN >> 3) - 3) = 0x80; - - /* Now update the table */ - for (i=0;isetup_f == HASH_PERF) { + if (num_addrs == HASH_TABLE_LEN) { /* Pass all multicasts */ + omr |= OMR_PM; + } else { + omr &= ~OMR_PM; + /* Now update the MCA table */ + for (i=0;i>=1) { - crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0); + for (bit = *addrs++,j=0;j<8;j++, bit>>=1) { + crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0); + } } - } - hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */ + hashcode = crc & HASH_BITS; /* hashcode is 9 LSb of CRC */ - byte = hashcode >> 3; /* bit[3-8] -> byte in filter */ - bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ + byte = hashcode >> 3; /* bit[3-8] -> byte in filter */ + bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ - byte <<= 1; /* calc offset into setup frame */ - if (byte & 0x02) { - byte -= 1; + byte <<= 1; /* calc offset into setup frame */ + if (byte & 0x02) { + byte -= 1; + } + lp->setup_frame[byte] |= bit; + + } else { /* skip this address */ + addrs += ETH_ALEN; } - multicast_table[byte] |= bit; - - } else { /* skip this address */ - addrs += ETH_ALEN; + } + } + } else { /* Perfect filtering */ + omr &= ~OMR_PM; + for (j=0; j 0)) return; /* PCI MODULE special */ @@ -1244,17 +1359,30 @@ maxSlots = i + 1; } - for (status = -ENODEV; i> 16); + vendor = (u_short) cfid; + + lp->bus = EISA; + lp->chipset = device; + if (DevicePresent(EISA_APROM) == 0) { + /* Write the PCI Configuration Registers */ + outl(PCI_COMMAND_IO | PCI_COMMAND_MASTER, PCI_CFCS); + outl(0x00004000, PCI_CFLT); + outl((u_long)iobase, PCI_CBIO); + + if (check_region(iobase, DE4X5_EISA_TOTAL_SIZE) == 0) { + if ((dev = alloc_device(dev, iobase)) != NULL) { + if ((status = de4x5_hw_init(dev, iobase)) == 0) { + num_de4x5s++; + } num_eth++; + } + } else if (autoprobed) { + printk("%s: region already allocated at 0x%04x.\n", dev->name, iobase); } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04x.\n", dev->name, iobase); } } } @@ -1295,15 +1423,18 @@ dev_last = PCI_LAST_DEV; } - for (; dev_num < dev_last && dev != NULL; dev_num++) { + for (; (dev_num < dev_last) && (dev != NULL); dev_num++) { pcibios_read_config_dword(pb, PCI_DEVICE, PCI_CLASS_REVISION, &class); if (class != 0xffffffff) { pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor); pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &device); - if ((vendor == DC21040_VID) && (device == DC21040_DID)) { + if (is_DC21040 || is_DC21041 || is_DC21140) { /* Set the device number information */ lp->device = dev_num; + /* Set the chipset information */ + lp->chipset = device; + /* Get the board I/O address */ pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &iobase); iobase &= CBIO_MASK; @@ -1317,7 +1448,7 @@ pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status); /* If there is a device and I/O region is open, initialise dev. */ - if ((DevicePresent(DE4X5_APROM) == 0) || is_zynx) { + if ((DevicePresent(DE4X5_APROM) == 0) || is_not_dec) { if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) { if ((dev = alloc_device(dev, iobase)) != NULL) { dev->irq = irq; @@ -1457,120 +1588,322 @@ static int autoconf_media(struct device *dev) { struct de4x5_private *lp = (struct de4x5_private *)dev->priv; - int media, entry, iobase = dev->base_addr; - char frame[64]; - u_long i, omr, sisr, linkBad; -/* u_long t_330ms = 920000;*/ - u_long t_3s = 8000000; + int iobase = dev->base_addr; - /* Set up for TP port, with LEDs */ - media = TP; - RESET_SIA; - outl(SICR_OE57 | SICR_SEL | SICR_SRL, DE4X5_SICR); + if (lp->chipset == DC21040) { + lp->media = (lp->autosense == AUTO ? TP : lp->autosense); + dc21040_autoconf(dev); + } else if (lp->chipset == DC21041) { + lp->media = (lp->autosense == AUTO ? TP_NW : lp->autosense); + dc21041_autoconf(dev); + } else if (lp->chipset == DC21140) { + /* Force 10Mb/s (_100Mb for 100Mb/s) */ + lp->media = (lp->autosense == AUTO ? _10Mb : lp->autosense); + dc21140_autoconf(dev); + } + + if (de4x5_debug >= 1 ) { + if (lp->chipset != DC21140) { + printk("%s: Media is %s\n",dev->name, + (lp->media == NC ? "unconnected!" : + (lp->media == TP ? "TP." : + (lp->media == ANS ? "TP/Nway." : + (lp->media == BNC ? "BNC." : + (lp->media == AUI ? "AUI." : + "BNC/AUI." + )))))); + } else { + printk("%s: Mode is forced to %s\n",dev->name, + (lp->media == NC ? "link down.": + (lp->media == _100Mb ? "100Mb/s." : + (lp->media == _10Mb ? "10Mb/s." : + "\?\?\?" + )))); + } + } - /* Test the TP port */ - for (linkBad=1,i=0;imedia) { + lp->lostMedia = 0; + inl(DE4X5_MFC); /* Zero the lost frames counter */ } - - if (linkBad) { - /* Set up for BNC (Thinwire) port, with LEDs */ - media = BNC; - RESET_SIA; - outl(SIGR_JCK | SIGR_HUJ, DE4X5_SIGR); - outl(STRR_CLD | STRR_CSQ | STRR_RSQ | STRR_DREN | STRR_ECEN, DE4X5_STRR); - outl(SICR_OE57| SICR_OE24 | SICR_OE13 | SICR_SEL | - SICR_AUI | SICR_SRL, DE4X5_SICR); + dce_ms_delay(10); + + return (lp->media); +} + +static void dc21040_autoconf(struct device *dev) +{ + struct de4x5_private *lp = (struct de4x5_private *)dev->priv; + int iobase = dev->base_addr; + u_long i, sisr = 0, linkBad; + u_long t_3s = 3000; + + switch (lp->media) { + case TP: + reset_init_sia(dev, 0x8f01, 0xffff, 0x0000); + for (linkBad=1,i=0;(iautosense == AUTO)) { + lp->media = BNC_AUI; + dc21040_autoconf(dev); + } + break; - /* Wait 330ms */ + case BNC: + case AUI: + case BNC_AUI: + reset_init_sia(dev, 0x8f09, 0x0705, 0x0006); dce_ms_delay(330); -/* for (i=0; iautosense == AUTO)) { + lp->media = NC; + dc21040_autoconf(dev); } + break; + + case NC: + reset_init_sia(dev, 0x8f01, 0xffff, 0x0000); + break; + } + + return; +} + +/* +** Autoconfigure the media when using the DC21041. AUI needs to be tested +** before BNC, because the BNC port will indicate activity if it's not +** terminated correctly. The only way to test for that is to place a loopback +** packet onto the network and watch for errors. */ - /* Make up a dummy packet with CRC error */ - create_packet(dev, frame, sizeof(frame)); +static void dc21041_autoconf(struct device *dev) +{ + struct de4x5_private *lp = (struct de4x5_private *)dev->priv; + int iobase = dev->base_addr; + u_long sts, irqs, irq_mask, omr; - /* Setup the packet descriptor */ - entry = lp->tx_new; /* Remember the ring position */ - load_packet(dev, frame, TD_LS | TD_FS | TD_AC | sizeof(frame), NULL); + switch (lp->media) { + case TP_NW: + omr = inl(DE4X5_OMR); /* Set up full duplex for the autonegotiate */ + outl(omr | OMR_FD, DE4X5_OMR); + irqs = STS_LNF | STS_LNP; + irq_mask = IMR_LFM | IMR_LPM; + sts = test_media(dev, irqs, irq_mask, 0xef01, 0xffff, 0x0008, 2400); + if (sts & STS_LNP) { + lp->media = ANS; + } else { + lp->media = AUI; + } + dc21041_autoconf(dev); + break; - /* Start the TX process */ - omr = inl(DE4X5_OMR); - outl(omr|OMR_ST, DE4X5_OMR); + case ANS: + irqs = STS_LNP; + irq_mask = IMR_LPM; + sts = test_ans(dev, irqs, irq_mask, 3000); + if (!(sts & STS_LNP) && (lp->autosense == AUTO)) { + lp->media = TP; + dc21041_autoconf(dev); + } + break; - /* Update pointers */ - lp->tx_new = (++lp->tx_new) % lp->txRingSize; - lp->tx_old = lp->tx_new; + case TP: + omr = inl(DE4X5_OMR); /* Set up half duplex for TP */ + outl(omr & ~OMR_FD, DE4X5_OMR); + irqs = STS_LNF | STS_LNP; + irq_mask = IMR_LFM | IMR_LPM; + sts = test_media(dev, irqs, irq_mask, 0xef01, 0xff3f, 0x0008, 2400); + if (!(sts & STS_LNP) && (lp->autosense == AUTO)) { + if (inl(DE4X5_SISR) & SISR_NRA) { /* Non selected port activity */ + lp->media = AUI; + } else { + lp->media = BNC; + } + dc21041_autoconf(dev); + } + break; - /* - ** Poll for completion of frame (interrupts are disabled for now)... - ** Allow upto 3 seconds to complete. - */ - for (linkBad=1,i=0;itx_ring[entry].status >= 0) linkBad=0; + case AUI: + omr = inl(DE4X5_OMR); /* Set up half duplex for AUI */ + outl(omr & ~OMR_FD, DE4X5_OMR); + irqs = 0; + irq_mask = 0; + sts = test_media(dev, irqs, irq_mask, 0xef09, 0xf7fd, 0x000e, 1000); + if (!(inl(DE4X5_SISR) & SISR_SRA) && (lp->autosense == AUTO)) { + lp->media = BNC; + dc21041_autoconf(dev); } - - outl(omr, DE4X5_OMR); /* Stop everything! */ + break; - if (linkBad || (lp->tx_ring[entry].status & TD_ES)) { - /* Set up for AUI (Thickwire) port, with LEDs */ - media = AUI; - RESET_SIA; - outl(SIGR_JCK | SIGR_HUJ, DE4X5_SIGR); - outl(STRR_CLD | STRR_CSQ | STRR_RSQ | STRR_DREN | STRR_ECEN, DE4X5_STRR); - outl(SICR_OE57| SICR_SEL | SICR_AUI | SICR_SRL, DE4X5_SICR); - - /* Wait 330ms */ - dce_ms_delay(330); + case BNC: + omr = inl(DE4X5_OMR); /* Set up half duplex for BNC */ + outl(omr & ~OMR_FD, DE4X5_OMR); + irqs = 0; + irq_mask = 0; + sts = test_media(dev, irqs, irq_mask, 0xef09, 0xf7fd, 0x0006, 1000); + if (!(inl(DE4X5_SISR) & SISR_SRA) && (lp->autosense == AUTO)) { + lp->media = NC; + } else { /* Ensure media connected */ + if (ping_media(dev)) lp->media = NC; + } + break; - /* Setup the packet descriptor */ - entry = lp->tx_new; /* Remember the ring position */ - load_packet(dev, frame, TD_LS | TD_FS | TD_AC | sizeof(frame), NULL); - - /* Start the TX process */ - omr = inl(DE4X5_OMR); - outl(omr|OMR_ST, DE4X5_OMR); + case NC: + omr = inl(DE4X5_OMR); /* Set up full duplex for the autonegotiate */ + outl(omr | OMR_FD, DE4X5_OMR); + reset_init_sia(dev, 0xef01, 0xffff, 0x0008);/* Initialise the SIA */ + break; + } - /* Update pointers */ - lp->tx_new = (++lp->tx_new) % lp->txRingSize; - lp->tx_old = lp->tx_new; + return; +} - /* - ** Poll for completion of frame (interrupts are disabled for now)... - ** Allow 3 seconds to complete. - */ - for (linkBad=1,i=0;itx_ring[entry].status >= 0) linkBad=0; - } - - outl(omr, DE4X5_OMR); /* Stop everything! */ +/* +** Reduced feature version (temporary I hope) +*/ +static void dc21140_autoconf(struct device *dev) +{ + struct de4x5_private *lp = (struct de4x5_private *)dev->priv; + int iobase = dev->base_addr; + u_long omr; - if (linkBad || (lp->tx_ring[entry].status & TD_ES)) { - /* Reset the SIA */ - outl(SICR_RESET, DE4X5_SICR); /* Reset SIA connectivity regs */ - outl(STRR_RESET, DE4X5_STRR); /* Write reset values */ - outl(SIGR_RESET, DE4X5_SIGR); /* Write reset values */ + switch(lp->media) { + case _100Mb: /* Set 100Mb/s, MII Port with PCS Function and Scrambler */ + omr = (inl(DE4X5_OMR) & ~(OMR_PS | OMR_HBD | OMR_TTM | OMR_PCS | OMR_SCR)); + outl(omr | OMR_PS | OMR_HBD | OMR_PCS | OMR_SCR, DE4X5_OMR); + outl(GEP_FDXD | GEP_MODE, DE4X5_GEP); + break; - media = NC; - } - } + case _10Mb: /* Set conventional 10Mb/s ENDEC interface */ + omr = (inl(DE4X5_OMR) & ~(OMR_PS | OMR_HBD | OMR_TTM | OMR_PCS | OMR_SCR)); + outl(omr | OMR_TTM, DE4X5_OMR); + outl(GEP_FDXD, DE4X5_GEP); + break; } - if (de4x5_debug >= 1 ) { - printk("%s: Media is %s.\n",dev->name, - (media == NC ? "unconnected to this device" : - (media == TP ? "TP" : - (media == BNC ? "BNC" : - "AUI")))); + return; +} + +static long test_media(struct device *dev, long irqs, long irq_mask, long csr13, long csr14, long csr15, long msec) +{ + struct de4x5_private *lp = (struct de4x5_private *)dev->priv; + int iobase = dev->base_addr; + long sts, time, csr12; + + reset_init_sia(dev, csr13, csr14, csr15); + + /* Set link_fail_inhibit_timer */ + load_ms_timer(dev, msec); + + /* clear all pending interrupts */ + sts = inl(DE4X5_STS); + outl(sts, DE4X5_STS); + + /* clear csr12 NRA and SRA bits */ + csr12 = inl(DE4X5_SISR); + outl(csr12, DE4X5_SISR); + + /* Poll for timeout - timer interrupt doesn't work correctly */ + do { + time = inl(DE4X5_GPT) & GPT_VAL; + sts = inl(DE4X5_STS); + } while ((time != 0) && !(sts & irqs)); + + sts = inl(DE4X5_STS); + + return sts; +} + +/* +** Send a packet onto the media and watch for send errors that indicate the +** media is bad or unconnected. +*/ +static long ping_media(struct device *dev) +{ + struct de4x5_private *lp = (struct de4x5_private *)dev->priv; + int entry, iobase = dev->base_addr; + char frame[64]; + long i, linkBad, omr; + u_long t_3s = 3000; + + create_packet(dev, frame, sizeof(frame)); + + entry = lp->tx_new; /* Remember the ring position */ + load_packet(dev, frame, TD_LS | TD_FS | sizeof(frame),NULL); + + omr = inl(DE4X5_OMR); + outl(omr|OMR_ST, DE4X5_OMR); + + lp->tx_new = (++lp->tx_new) % lp->txRingSize; + lp->tx_old = lp->tx_new; + + /* Poll for completion of frame (interrupts are disabled for now)... */ + for (linkBad=1,i=0;(itx_ring[entry].status >= 0) linkBad=0; + dce_ms_delay(1); } + outl(omr, DE4X5_OMR); + + return ((linkBad || (lp->tx_ring[entry].status & TD_ES)) ? 1 : 0); +} + +/* +** Check the Auto Negotiation State. Return OK when a link pass interrupt +** is received and the auto-negotiation status is NWAY OK. +*/ +static int test_ans(struct device *dev, long irqs, long irq_mask, long msec) +{ + struct de4x5_private *lp = (struct de4x5_private *)dev->priv; + int iobase = dev->base_addr; + long sts, ans; + + outl(irq_mask, DE4X5_IMR); + + /* Set timeout limit */ + load_ms_timer(dev, msec); + + /* clear all pending interrupts */ + sts = inl(DE4X5_STS); + outl(sts, DE4X5_STS); + + /* Poll for interrupts */ + do { + ans = inl(DE4X5_SISR) & SISR_ANS; + sts = inl(DE4X5_STS); + } while (!(sts & irqs) && (ans ^ ANS_NWOK) != 0); + + return ((sts & STS_LNP) && ((ans ^ ANS_NWOK) == 0) ? STS_LNP : 0); +} + +/* +** +*/ +static void reset_init_sia(struct device *dev, long sicr, long strr, long sigr) +{ + struct de4x5_private *lp = (struct de4x5_private *)dev->priv; + int iobase = dev->base_addr; + + RESET_SIA; + outl(sigr, DE4X5_SIGR); + outl(strr, DE4X5_STRR); + outl(sicr, DE4X5_SICR); + + return; +} + +/* +** Load the timer on the DC21041 and 21140. Max time is 13.42 secs. +*/ +static void load_ms_timer(struct device *dev, u_long msec) +{ + struct de4x5_private *lp = (struct de4x5_private *)dev->priv; + int iobase = dev->base_addr; - if (media) lp->lostMedia = 0; + outl((long)(msec * 10000)/2048, DE4X5_GPT); - return media; + return; } /* @@ -1578,7 +1911,7 @@ */ static void create_packet(struct device *dev, char *frame, int len) { - int i, j; + int i; char *buf = frame; for (i=0; idev_addr[i]; } - for (j=1; j>=0; j--) { /* Packet length (2 bytes) */ - *buf++ = (char) ((len >> 8*j) & 0xff); - } - *buf++ = 0; /* Data */ - for (i=len-4; i start) { /* Wrapped counter counting down */ - quant -= start; - start = (1 << TIMER_WIDTH); - } - } - } + udelay(usec); return; } /* -** Known delay in milliseconds +** Known delay in milliseconds, in millisecond steps. */ static void dce_ms_delay(u_long msec) { @@ -1655,18 +1955,19 @@ /* ** Look for a particular board name in the EISA configuration space */ -static void EISA_signature(char *name, short iobase) +int EISA_signature(char *name, long eisa_id) { unsigned long i; char *signatures[] = DE4X5_SIGNATURE; - char ManCode[8]; + char ManCode[DE4X5_STRLEN]; union { - u_long ID; - u_char Id[4]; + long ID; + char Id[4]; } Eisa; + int status = 0; - strcpy(name, ""); - Eisa.ID = inl(iobase); + *name = '\0'; + Eisa.ID = inl(eisa_id); ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40); ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40); @@ -1675,13 +1976,14 @@ ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30); ManCode[5]='\0'; - for (i=0;*signatures[i] != '\0' && *name == '\0';i++) { + for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) { if (strstr(ManCode, signatures[i]) != NULL) { strcpy(name,ManCode); + status = 1; } } - - return; /* return the device name string */ + + return status; /* return the device name string */ } /* @@ -1715,26 +2017,34 @@ dev.llsig.b = ETH_PROM_SIG; sigLength = sizeof(long) << 1; - for (i=0,j=0;jbus == PCI) { - while ((tmp = inl(aprom_addr)) < 0); - data = (char)tmp; - } else { - data = inb(aprom_addr); - } - if (dev.Sig[j] == data) { /* track signature */ - j++; - } else { /* lost signature; begin search again */ - if (data == dev.Sig[0]) { - j=1; + if (lp->chipset == DC21040) { + for (i=0,j=0;(jbus == PCI) { + while ((tmp = inl(aprom_addr)) < 0); + data = (char)tmp; } else { - j=0; + data = inb(aprom_addr); + } + if (dev.Sig[j] == data) { /* track signature */ + j++; + } else { /* lost signature; begin search again */ + if (data == dev.Sig[0]) { + j=1; + } else { + j=0; + } } } - } - if (j!=sigLength) { - status = -ENODEV; /* search failed */ + if (j!=sigLength) { + status = -ENODEV; /* search failed */ + } + + } else { /* use new srom */ + short *p = (short *)&lp->srom; + for (i=0; i<(sizeof(struct de4x5_srom)>>1); i++) { + *p++ = srom_rd(aprom_addr, i); + } } return status; @@ -1753,12 +2063,17 @@ if (k > 0xffff) k-=0xffff; if (lp->bus == PCI) { - while ((tmp = inl(DE4X5_APROM)) < 0); - k += (u_char) tmp; - dev->dev_addr[i++] = (u_char) tmp; - while ((tmp = inl(DE4X5_APROM)) < 0); - k += (u_short) (tmp << 8); - dev->dev_addr[i++] = (u_char) tmp; + if (lp->chipset == DC21040) { + while ((tmp = inl(DE4X5_APROM)) < 0); + k += (u_char) tmp; + dev->dev_addr[i++] = (u_char) tmp; + while ((tmp = inl(DE4X5_APROM)) < 0); + k += (u_short) (tmp << 8); + dev->dev_addr[i++] = (u_char) tmp; + } else { + dev->dev_addr[i] = (u_char) lp->srom.ieee_addr[i]; i++; + dev->dev_addr[i] = (u_char) lp->srom.ieee_addr[i]; i++; + } } else { k += (u_char) (tmp = inb(EISA_APROM)); dev->dev_addr[i++] = (u_char) tmp; @@ -1771,21 +2086,158 @@ if (k == 0xffff) k=0; if (lp->bus == PCI) { - while ((tmp = inl(DE4X5_APROM)) < 0); - chksum = (u_char) tmp; - while ((tmp = inl(DE4X5_APROM)) < 0); - chksum |= (u_short) (tmp << 8); + if (lp->chipset == DC21040) { + while ((tmp = inl(DE4X5_APROM)) < 0); + chksum = (u_char) tmp; + while ((tmp = inl(DE4X5_APROM)) < 0); + chksum |= (u_short) (tmp << 8); + if (k != chksum) status = -1; + } } else { chksum = (u_char) inb(EISA_APROM); chksum |= (u_short) (inb(EISA_APROM) << 8); + if (k != chksum) status = -1; } - if (k != chksum) status = -1; return status; } /* +** SROM Read +*/ +static short srom_rd(u_short addr, u_char offset) +{ + sendto_srom(SROM_RD | SROM_SR, addr); + + srom_latch(SROM_RD | SROM_SR | DT_CS, addr); + srom_command(SROM_RD | SROM_SR | DT_IN | DT_CS, addr); + srom_address(SROM_RD | SROM_SR | DT_CS, addr, offset); + + return srom_data(SROM_RD | SROM_SR | DT_CS, addr); +} + +static void srom_latch(u_long command, u_short addr) +{ + sendto_srom(command, addr); + sendto_srom(command | DT_CLK, addr); + sendto_srom(command, addr); + + return; +} + +static void srom_command(u_long command, u_short addr) +{ + srom_latch(command, addr); + srom_latch(command, addr); + srom_latch((command & 0x0000ff00) | DT_CS, addr); + + return; +} + +static void srom_address(u_long command, u_short addr, u_char offset) +{ + long i; + char a; + + a = (char)(offset << 2); + for (i=0; i<6; i++, a <<= 1) { + srom_latch(command | ((a < 0) ? DT_IN : 0), addr); + } + dce_us_delay(1); + + i = (getfrom_srom(addr) >> 3) & 0x01; + if (i != 0) { + printk("Bad SROM address phase.....\n"); + } + + return; +} + +static short srom_data(u_long command, u_short addr) +{ + int i; + short word = 0; + long tmp; + + for (i=0; i<16; i++) { + sendto_srom(command | DT_CLK, addr); + tmp = getfrom_srom(addr); + sendto_srom(command, addr); + + word = (word << 1) | ((tmp >> 3) & 0x01); + } + + sendto_srom(command & 0x0000ff00, addr); + + return word; +} + +/* +static void srom_busy(u_long command, u_short addr) +{ + sendto_srom((command & 0x0000ff00) | DT_CS, addr); + + while (!((getfrom_srom(addr) >> 3) & 0x01)) { + dce_ms_delay(1); + } + + sendto_srom(command & 0x0000ff00, addr); + + return; +} +*/ + +static void sendto_srom(u_long command, u_short addr) +{ + outl(command, addr); + dce_us_delay(1); + + return; +} + +static long getfrom_srom(u_short addr) +{ + long tmp; + + tmp = inl(addr); + dce_us_delay(1); + + return tmp; +} + +static char *build_setup_frame(struct device *dev, int mode) +{ + struct de4x5_private *lp = (struct de4x5_private *)dev->priv; + int i; + char *pa = lp->setup_frame; + + /* Initialise the setup frame */ + if (mode == ALL) { + memset(lp->setup_frame, 0, SETUP_FRAME_LEN); + } + + if (lp->setup_f == HASH_PERF) { + for (pa=lp->setup_frame+IMPERF_PA_OFFSET, i=0; idev_addr[i]; /* Host address */ + if (i & 0x01) pa += 2; + } + *(lp->setup_frame + (HASH_TABLE_LEN >> 3) - 3) = 0x80; /* B'cast address */ + } else { + for (i=0; idev_addr[i]; + if (i & 0x01) pa += 4; + } + for (i=0; idata,ETH_ALEN); for (i=0; idev_addr[i] = tmp.addr[i]; } - omr = inl(DE4X5_OMR); - if (omr & OMR_HP) { - offset = IMPERF_PA_OFFSET; - } else { - offset = PERF_PA_OFFSET; - } - /* Insert the physical address */ - for (pa=lp->setup_frame+offset, i=0; idev_addr[i]; - if (i & 0x01) pa += 2; - } + build_setup_frame(dev, PHYS_ADDR_ONLY); /* Set up the descriptor and give ownership to the card */ while (set_bit(0, (void *)&dev->tbusy) != 0); /* Wait for lock to free */ - load_packet(dev, lp->setup_frame, TD_IC | HASH_F | TD_SET | + if (lp->setup_f == HASH_PERF) { + load_packet(dev, lp->setup_frame, TD_IC | HASH_F | TD_SET | + SETUP_FRAME_LEN, NULL); + } else { + load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | SETUP_FRAME_LEN, NULL); + } lp->tx_new = (++lp->tx_new) % lp->txRingSize; outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */ dev->tbusy = 0; /* Unlock the TX ring */ @@ -1848,7 +2291,6 @@ if (suser()) { omr = inl(DE4X5_OMR); omr |= OMR_PR; - omr &= ~OMR_PM; outl(omr, DE4X5_OMR); } else { status = -EPERM; @@ -1893,11 +2335,10 @@ } break; - case DE4X5_MCA_EN: /* Enable multicast addressing */ + case DE4X5_MCA_EN: /* Enable pass all multicast addressing */ if (suser()) { omr = inl(DE4X5_OMR); omr |= OMR_PM; - omr &= ~OMR_PR; outl(omr, DE4X5_OMR); } else { status = -EPERM; @@ -2049,9 +2490,9 @@ DE4X5_PCI_TOTAL_SIZE : DE4X5_EISA_TOTAL_SIZE)); if (lp) { - kfree_s(lp->rx_ring[0].buf, RX_BUFF_SZ * NUM_RX_DESC + LWPAD); + kfree_s(lp->rx_ring[0].buf, RX_BUFF_SZ * NUM_RX_DESC + ALIGN); } - kfree_s(thisDE4X5.priv, sizeof(struct de4x5_private) + LWPAD); + kfree_s(thisDE4X5.priv, sizeof(struct de4x5_private) + ALIGN); thisDE4X5.priv = NULL; unregister_netdev(&thisDE4X5); diff -u --recursive --new-file v1.2.7/linux/drivers/net/de4x5.h linux/drivers/net/de4x5.h --- v1.2.7/linux/drivers/net/de4x5.h Tue Jan 31 09:39:01 1995 +++ linux/drivers/net/de4x5.h Wed May 3 07:17:10 1995 @@ -23,8 +23,12 @@ #define DE4X5_IMR iobase+(0x038 << lp->bus) /* Interrupt Mask Register */ #define DE4X5_MFC iobase+(0x040 << lp->bus) /* Missed Frame Counter */ #define DE4X5_APROM iobase+(0x048 << lp->bus) /* Ethernet Address PROM */ +#define DE4X5_BROM iobase+(0x048 << lp->bus) /* Boot ROM Register */ +#define DE4X5_SROM iobase+(0x048 << lp->bus) /* Serial ROM Register */ #define DE4X5_DDR iobase+(0x050 << lp->bus) /* Data Diagnostic Register */ #define DE4X5_FDR iobase+(0x058 << lp->bus) /* Full Duplex Register */ +#define DE4X5_GPT iobase+(0x058 << lp->bus) /* General Purpose Timer Reg.*/ +#define DE4X5_GEP iobase+(0x060 << lp->bus) /* General Purpose Register */ #define DE4X5_SISR iobase+(0x060 << lp->bus) /* SIA Status Register */ #define DE4X5_SICR iobase+(0x068 << lp->bus) /* SIA Connectivity Register */ #define DE4X5_STRR iobase+(0x070 << lp->bus) /* SIA TX/RX Register */ @@ -54,7 +58,9 @@ #define PCI_CFLT iobase+0x001c /* PCI Latency Timer Register */ #define PCI_CBIO iobase+0x0028 /* PCI Base I/O Register */ #define PCI_CBMA iobase+0x002c /* PCI Base Memory Address Register */ -#define PCI_CFIT iobase+0x0038 /* PCI Configuration Interrupt Register */ +#define PCI_CBER iobase+0x0030 /* PCI Expansion ROM Base Address Reg. */ +#define PCI_CFIT iobase+0x003c /* PCI Configuration Interrupt Register */ +#define PCI_CFDA iobase+0x0040 /* PCI Driver Area Register */ /* ** EISA Configuration Register 0 bit definitions @@ -94,6 +100,21 @@ #define CFID_VID 0x00ff /* Vendor ID */ #define DC21040_DID 0x0002 /* Unique Device ID # */ #define DC21040_VID 0x1011 /* DC21040 Manufacturer */ +#define DC21041_DID 0x0014 /* Unique Device ID # */ +#define DC21041_VID 0x1011 /* DC21041 Manufacturer */ +#define DC21140_DID 0x0009 /* Unique Device ID # */ +#define DC21140_VID 0x1011 /* DC21140 Manufacturer */ + +/* +** Chipset defines +*/ +#define DC21040 DC21040_DID +#define DC21041 DC21041_DID +#define DC21140 DC21140_DID + +#define is_DC21040 ((vendor == DC21040_VID) && (device == DC21040_DID)) +#define is_DC21041 ((vendor == DC21041_VID) && (device == DC21041_DID)) +#define is_DC21140 ((vendor == DC21140_VID) && (device == DC21140_DID)) /* ** PCI Configuration Command/Status Register (PCI_CFCS) @@ -136,9 +157,21 @@ #define CBIO_IOSI 0x00000001 /* I/O Space Indicator (RO, value is 1) */ /* +** PCI Configuration Expansion ROM Base Address Register (PCI_CBER) +*/ +#define CBER_MASK 0xfffffc00 /* Expansion ROM Base Address Mask */ +#define CBER_ROME 0x00000001 /* ROM Enable */ + +/* +** PCI Configuration Driver Area Register (PCI_CFDA) +*/ +#define CFDA_PSM 0x80000000 /* Power Saving Mode */ + +/* ** DC21040 Bus Mode Register (DE4X5_BMR) */ -#define BMR_TAP 0x00060000 /* Transmit Automatic Polling */ +#define BMR_DBO 0x00100000 /* Descriptor Byte Ordering (Endian) */ +#define BMR_TAP 0x000e0000 /* Transmit Automatic Polling */ #define BMR_DAS 0x00010000 /* Diagnostic Address Space */ #define BMR_CAL 0x0000c000 /* Cache Alignment */ #define BMR_PBL 0x00003f00 /* Programmable Burst Length */ @@ -151,6 +184,10 @@ #define TAP_200US 0x00020000 /* TX automatic polling every 200us */ #define TAP_800US 0x00040000 /* TX automatic polling every 800us */ #define TAP_1_6MS 0x00060000 /* TX automatic polling every 1.6ms */ +#define TAP_12_8US 0x00080000 /* TX automatic polling every 12.8us */ +#define TAP_25_6US 0x000a0000 /* TX automatic polling every 25.6us */ +#define TAP_51_2US 0x000c0000 /* TX automatic polling every 51.2us */ +#define TAP_102_4US 0x000e0000 /* TX automatic polling every 102.4us */ #define CAL_NOUSE 0x00000000 /* Not used */ #define CAL_8LONG 0x00004000 /* 8-longword alignment */ @@ -165,6 +202,7 @@ #define PBL_16 0x00001000 /* 16 longwords DMA burst length */ #define PBL_32 0x00002000 /* 32 longwords DMA burst length */ +#define DSL_0 0x00000000 /* 0 longword / descriptor */ #define DSL_1 0x00000004 /* 1 longword / descriptor */ #define DSL_2 0x00000008 /* 2 longwords / descriptor */ #define DSL_4 0x00000010 /* 4 longwords / descriptor */ @@ -195,20 +233,23 @@ /* ** DC21040 Status Register (DE4X5_STS) */ -#define STS_EB 0x03800000 /* Error Bits */ +#define STS_BE 0x03800000 /* Bus Error Bits */ #define STS_TS 0x00700000 /* Transmit Process State */ #define STS_RS 0x000e0000 /* Receive Process State */ #define STS_NIS 0x00010000 /* Normal Interrupt Summary */ #define STS_AIS 0x00008000 /* Abnormal Interrupt Summary */ +#define STS_ER 0x00004000 /* Early Receive */ #define STS_SE 0x00002000 /* System Error */ #define STS_LNF 0x00001000 /* Link Fail */ #define STS_FD 0x00000800 /* Full-Duplex Short Frame Received */ +#define STS_TM 0x00000800 /* Timer Expired (DC21041) */ #define STS_AT 0x00000400 /* AUI/TP Pin */ #define STS_RWT 0x00000200 /* Receive Watchdog Time-Out */ #define STS_RPS 0x00000100 /* Receive Process Stopped */ #define STS_RU 0x00000080 /* Receive Buffer Unavailable */ #define STS_RI 0x00000040 /* Receive Interrupt */ #define STS_UNF 0x00000020 /* Transmit Underflow */ +#define STS_LNP 0x00000010 /* Link Pass */ #define STS_TJT 0x00000008 /* Transmit Jabber Time-Out */ #define STS_TU 0x00000004 /* Transmit Buffer Unavailable */ #define STS_TPS 0x00000002 /* Transmit Process Stopped */ @@ -243,6 +284,13 @@ /* ** DC21040 Operation Mode Register (DE4X5_OMR) */ +#define OMR_SDP 0x02000000 /* SD Polarity - MUST BE ASSERTED */ +#define OMR_SCR 0x01000000 /* Scrambler Mode */ +#define OMR_PCS 0x00800000 /* PCS Function */ +#define OMR_TTM 0x00400000 /* Transmit Threshold Mode */ +#define OMR_SF 0x00200000 /* Store and Forward */ +#define OMR_HBD 0x00080000 /* HeartBeat Disable */ +#define OMR_PS 0x00040000 /* Port Select */ #define OMR_CA 0x00020000 /* Capture Effect Enable */ #define OMR_BP 0x00010000 /* Back Pressure */ #define OMR_TR 0x0000c000 /* Threshold Control Bits */ @@ -270,15 +318,18 @@ */ #define IMR_NIM 0x00010000 /* Normal Interrupt Summary Mask */ #define IMR_AIM 0x00008000 /* Abnormal Interrupt Summary Mask */ +#define IMR_ERM 0x00004000 /* Early Receive Mask */ #define IMR_SEM 0x00002000 /* System Error Mask */ #define IMR_LFM 0x00001000 /* Link Fail Mask */ -#define IMR_FDM 0x00000800 /* Full-Duplex Mask */ +#define IMR_FDM 0x00000800 /* Full-Duplex (Short Frame) Mask */ +#define IMR_TMM 0x00000800 /* Timer Expired Mask (DC21041) */ #define IMR_ATM 0x00000400 /* AUI/TP Switch Mask */ #define IMR_RWM 0x00000200 /* Receive Watchdog Time-Out Mask */ #define IMR_RSM 0x00000100 /* Receive Stopped Mask */ #define IMR_RUM 0x00000080 /* Receive Buffer Unavailable Mask */ #define IMR_RIM 0x00000040 /* Receive Interrupt Mask */ #define IMR_UNM 0x00000020 /* Underflow Interrupt Mask */ +#define IMR_LPM 0x00000010 /* Link Pass */ #define IMR_TJM 0x00000008 /* Transmit Time-Out Jabber Mask */ #define IMR_TUM 0x00000004 /* Transmit Buffer Unavailable Mask */ #define IMR_TSM 0x00000002 /* Transmission Stopped Mask */ @@ -297,27 +348,89 @@ #define APROM_DT 0x000000ff /* Address Byte */ /* +** DC21041 Boot/Ethernet Address ROM (DE4X5_BROM) +*/ +#define BROM_MODE 0x00008000 /* MODE_1: 0, MODE_0: 1 (read only) */ +#define BROM_RD 0x00004000 /* Read from Boot ROM */ +#define BROM_WR 0x00002000 /* Write to Boot ROM */ +#define BROM_BR 0x00001000 /* Select Boot ROM when set */ +#define BROM_SR 0x00000800 /* Select Serial ROM when set */ +#define BROM_REG 0x00000400 /* External Register Select */ +#define BROM_DT 0x000000ff /* Data Byte */ + +/* +** DC21041 Serial/Ethernet Address ROM (DE4X5_SROM) +*/ +#define SROM_MODE 0x00008000 /* MODE_1: 0, MODE_0: 1 (read only) */ +#define SROM_RD 0x00004000 /* Read from Boot ROM */ +#define SROM_WR 0x00002000 /* Write to Boot ROM */ +#define SROM_BR 0x00001000 /* Select Boot ROM when set */ +#define SROM_SR 0x00000800 /* Select Serial ROM when set */ +#define SROM_REG 0x00000400 /* External Register Select */ +#define SROM_DT 0x000000ff /* Data Byte */ + +#define DT_OUT 0x00000008 /* Serial Data Out */ +#define DT_IN 0x00000004 /* Serial Data In */ +#define DT_CLK 0x00000002 /* Serial ROM Clock */ +#define DT_CS 0x00000001 /* Serial ROM Chip Select */ + +/* ** DC21040 Full Duplex Register (DE4X5_FDR) */ -#define FDR_FDACV 0x0000ffff /* Full Duplex Auto Configuration Value */ +#define FDR_FDACV 0x0000ffff /* Full Duplex Auto Configuration Value */ /* -** DC21040 SIA Status Register (DE4X5_SISR) +** DC21041 General Purpose Timer Register (DE4X5_GPT) */ -#define SISR_DAO 0x00000080 /* PLL All One */ -#define SISR_DAZ 0x00000040 /* PLL All Zero */ -#define SISR_DSP 0x00000020 /* PLL Self-Test Pass */ -#define SISR_DSD 0x00000010 /* PLL Self-Test Done */ -#define SISR_APS 0x00000008 /* Auto Polarity State */ -#define SISR_LKF 0x00000004 /* Link Fail Status */ -#define SISR_NCR 0x00000002 /* Network Connection Error */ -#define SISR_PAUI 0x00000001 /* AUI_TP Indication */ +#define GPT_CON 0x00010000 /* One shot: 0, Continuous: 1 */ +#define GPT_VAL 0x0000ffff /* Timer Value */ + +/* +** DC21140 General Purpose Register (DE4X5_GEP) (hardware dependent bits) +*/ +/* Valid ONLY for DE500 hardware */ +#define GEP_LNP 0x00000080 /* Link Pass (input) */ +#define GEP_SLNK 0x00000040 /* SYM LINK (input) */ +#define GEP_SDET 0x00000020 /* Signal Detect (input) */ +#define GEP_FDXD 0x00000008 /* Full Duplex Disable (output) */ +#define GEP_PHYL 0x00000004 /* PHY Loopback (output) */ +#define GEP_FLED 0x00000002 /* Force Activity LED on (output) */ +#define GEP_MODE 0x00000001 /* 0: 10Mb/s, 1: 100Mb/s */ +#define GEP_INIT 0x0000010f /* Setup inputs (0) and outputs (1) */ -#define SIA_RESET 0x00000000 /* SIA Reset */ + +/* +** DC21040 SIA Status Register (DE4X5_SISR) +*/ +#define SISR_LPC 0xffff0000 /* Link Partner's Code Word */ +#define SISR_LPN 0x00008000 /* Link Partner Negotiable */ +#define SISR_ANS 0x00007000 /* Auto Negotiation Arbitration State */ +#define SISR_NSN 0x00000800 /* Non Stable NLPs Detected */ +#define SISR_ANR_FDS 0x00000400 /* Auto Negotiate Restart/Full Duplex Sel.*/ +#define SISR_NRA 0x00000200 /* Non Selected Port Receive Activity */ +#define SISR_SRA 0x00000100 /* Selected Port Receive Activity */ +#define SISR_DAO 0x00000080 /* PLL All One */ +#define SISR_DAZ 0x00000040 /* PLL All Zero */ +#define SISR_DSP 0x00000020 /* PLL Self-Test Pass */ +#define SISR_DSD 0x00000010 /* PLL Self-Test Done */ +#define SISR_APS 0x00000008 /* Auto Polarity State */ +#define SISR_LKF 0x00000004 /* Link Fail Status */ +#define SISR_NCR 0x00000002 /* Network Connection Error */ +#define SISR_PAUI 0x00000001 /* AUI_TP Indication */ +#define SIA_RESET 0x00000000 /* SIA Reset */ + +#define ANS_NDIS 0x00000000 /* Nway disable */ +#define ANS_TDIS 0x00001000 /* Transmit Disable */ +#define ANS_ADET 0x00002000 /* Ability Detect */ +#define ANS_ACK 0x00003000 /* Acknowledge */ +#define ANS_CACK 0x00004000 /* Complete Acknowledge */ +#define ANS_NWOK 0x00005000 /* Nway OK - FLP Link Good */ +#define ANS_LCHK 0x00006000 /* Link Check */ /* ** DC21040 SIA Connectivity Register (DE4X5_SICR) */ +#define SICR_SDM 0xffff0000 /* SIA Diagnostics Mode */ #define SICR_OE57 0x00008000 /* Output Enable 5 6 7 */ #define SICR_OE24 0x00004000 /* Output Enable 2 4 */ #define SICR_OE13 0x00002000 /* Output Enable 1 3 */ @@ -343,6 +456,7 @@ /* ** DC21040 SIA Transmit and Receive Register (DE4X5_STRR) */ +#define STRR_TAS 0x00008000 /* 10Base-T/AUI Autosensing Enable */ #define STRR_SPP 0x00004000 /* Set Polarity Plus */ #define STRR_APE 0x00002000 /* Auto Polarity Enable */ #define STRR_LTE 0x00001000 /* Link Test Enable */ @@ -350,6 +464,8 @@ #define STRR_CLD 0x00000400 /* Collision Detect Enable */ #define STRR_CSQ 0x00000200 /* Collision Squelch Enable */ #define STRR_RSQ 0x00000100 /* Receive Squelch Enable */ +#define STRR_ANE 0x00000080 /* Auto Negotiate Enable */ +#define STRR_HDE 0x00000040 /* Half Duplex Enable */ #define STRR_CPEN 0x00000030 /* Compensation Enable */ #define STRR_LSE 0x00000008 /* Link Pulse Send Enable */ #define STRR_DREN 0x00000004 /* Driver Enable */ @@ -360,13 +476,19 @@ /* ** DC21040 SIA General Register (DE4X5_SIGR) */ +#define SIGR_LV2 0x00008000 /* General Purpose LED2 value */ +#define SIGR_LE2 0x00004000 /* General Purpose LED2 enable */ #define SIGR_FRL 0x00002000 /* Force Receiver Low */ #define SIGR_DPST 0x00001000 /* PLL Self Test Start */ +#define SIGR_LSD 0x00000800 /* LED Stretch Disable */ #define SIGR_FLF 0x00000400 /* Force Link Fail */ #define SIGR_FUSQ 0x00000200 /* Force Unsquelch */ #define SIGR_TSCK 0x00000100 /* Test Clock */ +#define SIGR_LV1 0x00000080 /* General Purpose LED1 value */ +#define SIGR_LE1 0x00000040 /* General Purpose LED1 enable */ #define SIGR_RWR 0x00000020 /* Receive Watchdog Release */ #define SIGR_RWD 0x00000010 /* Receive Watchdog Disable */ +#define SIGR_ABM 0x00000008 /* BNC: 0, AUI:1 */ #define SIGR_JCK 0x00000004 /* Jabber Clock */ #define SIGR_HUJ 0x00000002 /* Host Unjab */ #define SIGR_JBD 0x00000001 /* Jabber Disable */ @@ -432,26 +554,63 @@ #define HASH_O_F TD_FT1| TD_F0 /* +** Media / mode state machine definitions +*/ +#define NC 0x0000 /* No Connection */ +#define TP 0x0001 /* 10Base-T */ +#define TP_NW 0x0002 /* 10Base-T with Nway */ +#define BNC 0x0004 /* Thinwire */ +#define AUI 0x0008 /* Thickwire */ +#define BNC_AUI 0x0010 /* BNC/AUI on DC21040 indistinguishable */ +#define ANS 0x0020 /* Intermediate AutoNegotiation State */ + +#define _10Mb 0x0040 /* 10Mb/s Ethernet */ +#define _100Mb 0x0080 /* 100Mb/s Ethernet */ +#define SYM_WAIT 0x0100 /* Wait for SYM_LINK */ +#define INIT 0x0200 /* Initial state */ + +#define AUTO 0x4000 /* Auto sense the media or speed */ + +/* ** Miscellaneous */ #define PCI 0 #define EISA 1 -#define NC 0 /* No Connection */ -#define TP 1 /* 10Base-T */ -#define BNC 2 /* Thinwire */ -#define AUI 3 /* Thickwire */ - #define HASH_TABLE_LEN 512 /* Bits */ +#define HASH_BITS 0x01ff /* 9 LS bits */ #define SETUP_FRAME_LEN 192 /* Bytes */ -#define PERF_PA_OFFSET 180 /* Bytes */ #define IMPERF_PA_OFFSET 156 /* Bytes */ -#define POLL_DEMAND 1 +#define POLL_DEMAND 1 + +#define LOST_MEDIA_THRESHOLD 3 + +#define MASK_INTERRUPTS 1 +#define UNMASK_INTERRUPTS 0 + +#define DE4X5_STRLEN 8 + +/* +** Address Filtering Modes +*/ +#define PERFECT 0 /* 16 perfect physical addresses */ +#define HASH_PERF 1 /* 1 perfect, 512 multicast addresses */ +#define PERFECT_REJ 2 /* Reject 16 perfect physical addresses */ +#define ALL_HASH 3 /* Hashes all physical & multicast addrs */ + +#define ALL 0 /* Clear out all the setup frame */ +#define PHYS_ADDR_ONLY 1 /* Update the physical address only */ + +/* +** Booleans +*/ +#define NO 0 +#define FALSE 0 -#define MASK_INTERRUPTS 1 -#define UNMASK_INTERRUPTS 0 +#define YES !0 +#define TRUE !0 /* ** Include the IOCTL stuff diff -u --recursive --new-file v1.2.7/linux/drivers/net/lance.c linux/drivers/net/lance.c --- v1.2.7/linux/drivers/net/lance.c Fri Apr 28 11:10:53 1995 +++ linux/drivers/net/lance.c Tue May 2 08:06:18 1995 @@ -608,7 +608,7 @@ outw(((int)&lp->init_block) >> 16, ioaddr+LANCE_DATA); outw(0x0004, ioaddr+LANCE_ADDR); - outw(0x0d15, ioaddr+LANCE_DATA); + outw(0x0915, ioaddr+LANCE_DATA); outw(0x0000, ioaddr+LANCE_ADDR); outw(0x0001, ioaddr+LANCE_DATA); diff -u --recursive --new-file v1.2.7/linux/drivers/net/ne.c linux/drivers/net/ne.c --- v1.2.7/linux/drivers/net/ne.c Sat Apr 29 12:42:21 1995 +++ linux/drivers/net/ne.c Tue May 2 08:02:12 1995 @@ -50,7 +50,7 @@ /* Do we implement the read before write bugfix ? */ /* #define CONFIG_NE_RW_BUGFIX */ -/* ---- No user-servicable parts below ---- */ +/* ---- No user-serviceable parts below ---- */ extern struct device *init_etherdev(struct device *dev, int sizeof_private, unsigned long *mem_startp); @@ -86,7 +86,7 @@ #define NESM_START_PG 0x40 /* First page of TX buffer */ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ -#define NE_RDC_TIMEOUT 0x03 /* Max wait in jiffies for Tx RDC */ +#define NE_RDC_TIMEOUT 0x02 /* Max wait in jiffies for Tx RDC */ int ne_probe(struct device *dev); static int ne_probe1(struct device *dev, int ioaddr); @@ -462,7 +462,6 @@ SLOW_DOWN_IO; #endif /* rw_bugfix */ - dma_start = jiffies; outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Now the normal output. */ @@ -477,6 +476,8 @@ } else { outsb(NE_BASE + NE_DATAPORT, buf, count); } + + dma_start = jiffies; #ifdef CONFIG_NE_SANITY /* This was for the ALPHA version only, but enough people have diff -u --recursive --new-file v1.2.7/linux/drivers/net/ppp.c linux/drivers/net/ppp.c --- v1.2.7/linux/drivers/net/ppp.c Thu Feb 23 13:19:17 1995 +++ linux/drivers/net/ppp.c Tue May 2 08:02:13 1995 @@ -31,6 +31,7 @@ /* #define NET02D -* */ #define NEW_TTY_DRIVERS /* */ #define OPTIMIZE_FLAG_TIME ((HZ * 3)/2) /* */ +#define CHECK_CHARACTERS #ifdef MODULE #include @@ -469,8 +470,8 @@ #endif if (ppp->dev) { - ppp->dev->flags &= ~IFF_UP; /* down the device */ - ppp->dev->flags |= IFF_POINTOPOINT; + dev_close (ppp->dev); + ppp->dev->flags = 0; } kfree (ppp->xbuff); @@ -953,14 +954,14 @@ #ifdef CHECK_CHARACTERS if (c & 0x80) - sc->sc_flags |= SC_RCV_B7_1; + ppp->flags |= SC_RCV_B7_1; else - sc->sc_flags |= SC_RCV_B7_0; + ppp->flags |= SC_RCV_B7_0; if (paritytab[c >> 5] & (1 << (c & 0x1F))) - sc->sc_flags |= SC_RCV_ODDP; + ppp->flags |= SC_RCV_ODDP; else - sc->sc_flags |= SC_RCV_EVNP; + ppp->flags |= SC_RCV_EVNP; #endif switch (c) { @@ -1005,6 +1006,7 @@ if (ppp->toss) { PRINTKN (1, (KERN_WARNING "ppp_toss: tossing frame, reason = %d\n", ppp->toss)); + slhc_toss (ppp->slcomp); ppp->stats.rerrors++; return; } @@ -1018,6 +1020,7 @@ if (count < 4) { PRINTKN (1,(KERN_WARNING "ppp: got runt ppp frame, %d chars\n", count)); + slhc_toss (ppp->slcomp); ppp->stats.runts++; return; } @@ -1025,6 +1028,7 @@ /* check PPP error detection field */ if (!ppp_check_fcs(ppp)) { PRINTKN (1,(KERN_WARNING "ppp: frame with bad fcs\n")); + slhc_toss (ppp->slcomp); ppp->stats.rerrors++; return; } @@ -1067,6 +1071,7 @@ /* couldn't cope. */ PRINTKN (1,(KERN_WARNING "ppp: dropping packet on the floor: nobody could take it.\n")); + slhc_toss (ppp->slcomp); ppp->stats.tossed++; } @@ -1109,6 +1114,7 @@ PRINTKN (1,(KERN_NOTICE "ppp: no space to decompress VJ compressed TCP header.\n")); ppp->stats.roverrun++; + slhc_toss (ppp->slcomp); return 1; } @@ -1116,6 +1122,7 @@ if (count <= 0) { ppp->stats.rerrors++; PRINTKN (1,(KERN_NOTICE "ppp: error in VJ decompression\n")); + slhc_toss (ppp->slcomp); return 1; } ppp->stats.rcomp++; @@ -1126,6 +1133,7 @@ if (slhc_remember(ppp->slcomp, c, count) <= 0) { ppp->stats.rerrors++; PRINTKN (1,(KERN_NOTICE "ppp: error in VJ memorizing\n")); + slhc_toss (ppp->slcomp); return 1; } ppp->stats.runcomp++; @@ -1709,7 +1717,12 @@ PRINTKN(4,(KERN_DEBUG "ppp_xmit [%s]: skb %lX busy %d\n", dev->name, (unsigned long int) skb, ppp->sending)); - CHECK_PPP(0); + /* avoid race conditions when the link fails */ + if (!ppp->inuse) { + dev_kfree_skb(skb, FREE_WRITE); + dev_close (dev); + return 0; + } if (tty == NULL) { PRINTKN(1,(KERN_ERR "ppp_xmit: %s not connected to a TTY!\n", dev->name)); @@ -1726,7 +1739,7 @@ /* get length from IP header as per Alan Cox bugfix for slip.c */ if (len < sizeof(struct iphdr)) { PRINTKN(0,(KERN_ERR "ppp_xmit: given runt packet, ignoring\n")); - return 1; + goto done; } len = ntohs( ((struct iphdr *)(skb->data)) -> tot_len ); @@ -1750,8 +1763,8 @@ /* try to compress, if VJ compression mode is on */ if (ppp->flags & SC_COMP_TCP) { - /* NOTE: last 0 argument says never to compress connection ID */ - len = slhc_compress(ppp->slcomp, p, len, ppp->cbuff, &p, 0); + len = slhc_compress(ppp->slcomp, p, len, ppp->cbuff, &p, + !(ppp->flags & SC_NO_TCP_CCID)); if (p[0] & SL_TYPE_COMPRESSED_TCP) proto = PROTO_VJCOMP; else { @@ -2055,10 +2068,25 @@ 0, 0, 0, 0, /* memory */ 0, 0, /* base, irq */ 0, 0, 0, NULL, ppp_init, - }, - { "ppp1" , 0, 0, 0, 0, 1, 0, 0, 0, 0, NULL, ppp_init }, - { "ppp2" , 0, 0, 0, 0, 2, 0, 0, 0, 0, NULL, ppp_init }, - { "ppp3" , 0, 0, 0, 0, 3, 0, 0, 0, 0, NULL, ppp_init }, + } + , { "ppp1" , 0, 0, 0, 0, 1, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp2" , 0, 0, 0, 0, 2, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp3" , 0, 0, 0, 0, 3, 0, 0, 0, 0, NULL, ppp_init } + +#ifdef PPP_PPP_LOTS + , { "ppp4" , 0, 0, 0, 0, 4, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp5" , 0, 0, 0, 0, 5, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp6" , 0, 0, 0, 0, 6, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp7" , 0, 0, 0, 0, 7, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp8" , 0, 0, 0, 0, 8, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp9" , 0, 0, 0, 0, 9, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp10" , 0, 0, 0, 0, 10, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp11" , 0, 0, 0, 0, 11, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp12" , 0, 0, 0, 0, 12, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp13" , 0, 0, 0, 0, 13, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp14" , 0, 0, 0, 0, 14, 0, 0, 0, 0, NULL, ppp_init } + , { "ppp15" , 0, 0, 0, 0, 15, 0, 0, 0, 0, NULL, ppp_init } +#endif }; int diff -u --recursive --new-file v1.2.7/linux/drivers/net/slip.c linux/drivers/net/slip.c --- v1.2.7/linux/drivers/net/slip.c Thu Feb 23 13:27:11 1995 +++ linux/drivers/net/slip.c Sat Apr 29 12:41:33 1995 @@ -1046,6 +1046,13 @@ } } +static int sl_open_dev(struct device *dev) +{ + struct slip *sl = &sl_ctrl[dev->base_addr]; + if(sl->tty==NULL) + return -ENODEV; + return 0; +} /* Initialize the SLIP driver. Called by DDI. */ int @@ -1103,7 +1110,7 @@ /* Finish setting up the DEVICE info. */ dev->mtu = SL_MTU; dev->hard_start_xmit = sl_xmit; - dev->open = sl_open; + dev->open = sl_open_dev; dev->stop = sl_close; dev->hard_header = sl_header; dev->type_trans = sl_type_trans; diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c --- v1.2.7/linux/drivers/scsi/53c7,8xx.c Sat Apr 29 12:42:22 1995 +++ linux/drivers/scsi/53c7,8xx.c Tue May 2 07:28:31 1995 @@ -1242,7 +1242,8 @@ sti(); timeout = jiffies + 50; /* arbitrary */ - while ((hostdata->test_completed == -1) && jiffies < timeout); + while ((hostdata->test_completed == -1) && jiffies < timeout) + barrier(); failed = 1; if (hostdata->test_completed == -1) @@ -1330,7 +1331,8 @@ sti(); timeout = jiffies + 500; /* arbitrary */ - while ((hostdata->test_completed == -1) && jiffies < timeout); + while ((hostdata->test_completed == -1) && jiffies < timeout) + barrier(); NCR53c7x0_write32 (DSA_REG, 0); if (hostdata->test_completed == 2) { diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c --- v1.2.7/linux/drivers/scsi/NCR5380.c Wed Mar 29 06:52:58 1995 +++ linux/drivers/scsi/NCR5380.c Tue May 2 07:30:44 1995 @@ -636,7 +636,8 @@ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL); - while (probe_irq == IRQ_NONE && jiffies < timeout); + while (probe_irq == IRQ_NONE && jiffies < timeout) + barrier(); NCR5380_write(SELECT_ENABLE_REG, 0); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); @@ -2147,8 +2148,8 @@ */ NCR5380_write(TARGET_COMMAND_REG, 0); - while ((NCR5380_read(STATUS_REG) & SR_BSY) && - !hostdata->connected); + while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) + barrier(); return; case MESSAGE_REJECT: /* Accept message by clearing ACK */ @@ -2187,8 +2188,8 @@ /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); /* Wait for bus free to avoid nasty timeouts */ - while ((NCR5380_read(STATUS_REG) & SR_BSY) && - !hostdata->connected); + while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) + barrier(); return; /* * The SCSI data pointer is *IMPLICITLY* saved on a disconnect diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c --- v1.2.7/linux/drivers/scsi/aha152x.c Tue Apr 4 09:05:34 1995 +++ linux/drivers/scsi/aha152x.c Tue May 2 07:31:26 1995 @@ -968,7 +968,7 @@ /* sleep until the abortion is complete */ while(!abortion_complete) - ; + barrier(); aborting=0; return abort_result; } diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c --- v1.2.7/linux/drivers/scsi/aha1542.c Mon Jan 23 10:38:29 1995 +++ linux/drivers/scsi/aha1542.c Tue May 2 07:33:59 1995 @@ -681,7 +681,8 @@ aha1542_queuecommand(SCpnt, internal_done); SCpnt->SCp.Status = 0; - while (!SCpnt->SCp.Status); + while (!SCpnt->SCp.Status) + barrier(); return SCpnt->result; } diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/buslogic.c linux/drivers/scsi/buslogic.c --- v1.2.7/linux/drivers/scsi/buslogic.c Fri Apr 28 11:10:55 1995 +++ linux/drivers/scsi/buslogic.c Tue May 2 07:47:13 1995 @@ -788,7 +788,7 @@ scpnt->SCp.Status = 0; while (!scpnt->SCp.Status) - continue; + barrier(); return scpnt->result; } #endif diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c --- v1.2.7/linux/drivers/scsi/in2000.c Thu Mar 9 20:37:34 1995 +++ linux/drivers/scsi/in2000.c Tue May 2 07:34:38 1995 @@ -462,7 +462,8 @@ if ( in2000_SCptr ) { printk("in2000_queue_command waiting for free command block!\n"); - while ( in2000_SCptr ); + while ( in2000_SCptr ) + barrier(); } for ( timeout = jiffies + 5; timeout > jiffies; ) { diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/qlogic.c linux/drivers/scsi/qlogic.c --- v1.2.7/linux/drivers/scsi/qlogic.c Thu Mar 9 20:37:35 1995 +++ linux/drivers/scsi/qlogic.c Tue May 2 08:01:57 1995 @@ -18,7 +18,7 @@ Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994 (you can reference it, but it is incomplete and inaccurate in places) - Version 0.41 + Version 0.43 4/6/95 - kernel 1.2.0+, pcmcia 2.5.4+ Functions as standalone, loadable, and PCMCIA driver, the latter from Dave Hind's PCMCIA package. @@ -29,6 +29,11 @@ /*----------------------------------------------------------------*/ /* Configuration */ +/* Set the following to 2 to use normal interrupt (active high/totempole- + tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open + drain */ +#define QL_INT_ACTIVE_HIGH 2 + /* Set the following to 1 to enable the use of interrupts. Note that 0 tends to be more stable, but slower (or ties up the system more) */ #define QL_USE_IRQ 1 @@ -100,6 +105,8 @@ /*----------------------------------------------------------------*/ #ifdef PCMCIA +#undef QL_INT_ACTIVE_HIGH +#define QL_INT_ACTIVE_HIGH 0 #define MODULE #endif @@ -143,7 +150,7 @@ /*----------------------------------------------------------------*/ /* The qlogic card uses two register maps - These macros select which one */ #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd )) -#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb6 , qbase + 0xd )) +#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd )) /* following is watchdog timeout in microseconds */ #define WATCHDOG 5000000 @@ -262,8 +269,10 @@ static int ql_wai(void) { int i,k; + k = 0; i = jiffies + WATCHDOG; - while ( i > jiffies && !qabort && !((k = inb(qbase + 4)) & 0xe0)); + while ( i > jiffies && !qabort && !((k = inb(qbase + 4)) & 0xe0)) + barrier(); if (i <= jiffies) return (DID_TIME_OUT); if (qabort) @@ -420,8 +429,10 @@ return (k << 16); /* should get bus service interrupt and disconnect interrupt */ i = inb(qbase + 5); /* should be bus service */ - while (!qabort && ((i & 0x20) != 0x20)) + while (!qabort && ((i & 0x20) != 0x20)) { + barrier(); i |= inb(qbase + 5); + } rtrc(0) if (qabort) return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); @@ -493,7 +504,8 @@ cmd->scsi_done = done; /* wait for the last command's interrupt to finish */ - while (qlcmd != NULL); + while (qlcmd != NULL) + barrier(); ql_icmd(cmd); return 0; } @@ -556,7 +568,6 @@ outb(0x40 | qlcfg8 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */ outb(qlcfg5, qbase + 5); /* select timer */ outb(qlcfg9, qbase + 9); /* prescaler */ - qlirq = -1; #if QL_RESET_AT_START outb( 3 , qbase + 3 ); REG1; @@ -565,6 +576,7 @@ #endif #if QL_USE_IRQ /* IRQ probe - toggle pin and check request pending */ + if( qlirq == -1 ) { save_flags( flags ); cli(); @@ -575,21 +587,24 @@ outb(10, 0x20); /* access pending interrupt map */ outb(10, 0xa0); while (j--) { - outb(0xb2 , qbase + 0xd); /* int pin off */ + outb(0xb0 | QL_INT_ACTIVE_HIGH , qbase + 0xd); /* int pin off */ i &= ~(inb(0x20) | (inb(0xa0) << 8)); /* find IRQ off */ - outb(0xb6 , qbase + 0xd); /* int pin on */ + outb(0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd); /* int pin on */ i &= inb(0x20) | (inb(0xa0) << 8); /* find IRQ on */ } REG0; while (inb(qbase + 5)); /* purge int */ + j = -1; while (i) /* find on bit */ - i >>= 1, qlirq++; /* should check for exactly 1 on */ - if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic")) - host->can_queue = 1; + i >>= 1, j++; /* should check for exactly 1 on */ + qlirq = j; restore_flags( flags ); } else - printk( "Ql: Using preset IRQ of %d\n", qlirq ); + printk( "Ql: Using preset IRQ %d\n", qlirq ); + + if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic")) + host->can_queue = 1; #endif request_region( qbase , 0x10 ,"qlogic"); hreg = scsi_register( host , 0 ); /* no host data */ @@ -599,7 +614,7 @@ if( qlirq != -1 ) hreg->irq = qlirq; - sprintf(qinfo, "Qlogic Driver version 0.41, chip %02X at %03X, IRQ %d, TPdma:%d", + sprintf(qinfo, "Qlogic Driver version 0.43, chip %02X at %03X, IRQ %d, TPdma:%d", qltyp, qbase, qlirq, QL_TURBO_PDMA ); host->name = qinfo; diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v1.2.7/linux/drivers/scsi/scsi.c Fri Apr 14 12:02:42 1995 +++ linux/drivers/scsi/scsi.c Tue May 2 07:38:40 1995 @@ -369,7 +369,7 @@ do it right and use a mutex */ if (current == task[0]) - while (SCpnt->request.dev != 0xfffe); + while (SCpnt->request.dev != 0xfffe) barrier(); else if (SCpnt->request.dev != 0xfffe) { struct semaphore sem = MUTEX_LOCKED; @@ -421,7 +421,7 @@ 256, scan_scsis_done, SCSI_TIMEOUT, 3); if (current == task[0]) - while (SCpnt->request.dev != 0xfffe); + while (SCpnt->request.dev != 0xfffe) barrier(); else if (SCpnt->request.dev != 0xfffe) { struct semaphore sem = MUTEX_LOCKED; @@ -584,7 +584,7 @@ SCSI_TIMEOUT, 3); if (current == task[0]) - while (SCpnt->request.dev != 0xfffe); + while (SCpnt->request.dev != 0xfffe) barrier(); else if (SCpnt->request.dev != 0xfffe) { struct semaphore sem = MUTEX_LOCKED; @@ -1551,7 +1551,8 @@ if (SCpnt->internal_timeout & IN_ABORT) { restore_flags(flags); - while (SCpnt->internal_timeout & IN_ABORT); + while (SCpnt->internal_timeout & IN_ABORT) + barrier(); } else { @@ -1644,7 +1645,8 @@ if (SCpnt->internal_timeout & IN_RESET) { restore_flags(flags); - while (SCpnt->internal_timeout & IN_RESET); + while (SCpnt->internal_timeout & IN_RESET) + barrier(); } else { diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v1.2.7/linux/drivers/scsi/sd.c Fri Apr 14 12:02:42 1995 +++ linux/drivers/scsi/sd.c Tue May 2 07:39:45 1995 @@ -89,7 +89,8 @@ /* Make sure that only one process can do a check_change_disk at one time. This is also used to lock out further access when the partition table is being re-read. */ - while (rscsi_disks[target].device->busy); + while (rscsi_disks[target].device->busy) + barrier(); if(rscsi_disks[target].device->removable) { check_disk_change(inode->i_rdev); @@ -879,7 +880,7 @@ 512, sd_init_done, SD_TIMEOUT, MAX_RETRIES); - while(SCpnt->request.dev != 0xfffe); + while(SCpnt->request.dev != 0xfffe) barrier(); the_result = SCpnt->result; @@ -905,7 +906,7 @@ 512, sd_init_done, SD_TIMEOUT, MAX_RETRIES); - while(SCpnt->request.dev != 0xfffe); + while(SCpnt->request.dev != 0xfffe) barrier(); spintime = jiffies; }; @@ -941,7 +942,7 @@ MAX_RETRIES); if (current == task[0]) - while(SCpnt->request.dev != 0xfffe); + while(SCpnt->request.dev != 0xfffe) barrier(); else if (SCpnt->request.dev != 0xfffe){ struct semaphore sem = MUTEX_LOCKED; diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v1.2.7/linux/drivers/scsi/sr.c Wed Mar 29 06:52:59 1995 +++ linux/drivers/scsi/sr.c Tue May 2 07:40:03 1995 @@ -926,7 +926,7 @@ MAX_RETRIES); if (current == task[0]) - while(SCpnt->request.dev != 0xfffe); + while(SCpnt->request.dev != 0xfffe) barrier(); else if (SCpnt->request.dev != 0xfffe){ struct semaphore sem = MUTEX_LOCKED; diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/t128.c linux/drivers/scsi/t128.c --- v1.2.7/linux/drivers/scsi/t128.c Tue Nov 29 10:07:11 1994 +++ linux/drivers/scsi/t128.c Tue May 2 07:41:02 1995 @@ -320,9 +320,9 @@ #if 0 for (; i; --i) { - while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY); + while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY) barrier(); #else - while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY); + while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY) barrier(); for (; i; --i) { #endif *d++ = *reg; @@ -363,9 +363,9 @@ #if 0 for (; i; --i) { - while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY); + while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY) barrier(); #else - while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY); + while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY) barrier(); for (; i; --i) { #endif *reg = *s++; diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c --- v1.2.7/linux/drivers/scsi/ultrastor.c Mon Jan 16 16:48:19 1995 +++ linux/drivers/scsi/ultrastor.c Tue May 2 07:42:04 1995 @@ -733,13 +733,13 @@ retry: if (config.slot) while (inb(config.ogm_address - 1) != 0 && - config.aborted[mscp_index] == 0xff); + config.aborted[mscp_index] == 0xff) barrier(); /* else??? */ while ((inb(LCL_DOORBELL_INTR(config.doorbell_address)) & (config.slot ? 2 : 1)) - && config.aborted[mscp_index] == 0xff); + && config.aborted[mscp_index] == 0xff) barrier(); /* To avoid race conditions, make the code to write to the adapter atomic. This simplifies the abort code. */ diff -u --recursive --new-file v1.2.7/linux/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c --- v1.2.7/linux/drivers/scsi/wd7000.c Mon Jan 16 07:17:37 1995 +++ linux/drivers/scsi/wd7000.c Tue May 2 07:43:45 1995 @@ -941,7 +941,7 @@ { wd7000_queuecommand(SCpnt, wd7000_scsi_done); - while (SCpnt->SCp.phase > 0); /* phase counts scbs down to 0 */ + while (SCpnt->SCp.phase > 0) barrier(); /* phase counts scbs down to 0 */ return SCpnt->result; } @@ -964,7 +964,8 @@ */ mail_out(host, (struct scb *) &icb); timeout = jiffies + WAITnexttimeout; /* wait up to 2 seconds */ - while (icb.phase && jiffies < timeout) /* wait for completion */; + while (icb.phase && jiffies < timeout) + barrier(); /* wait for completion */ if (icb.phase) { printk("wd7000_diagnostics: timed out.\n"); @@ -1074,7 +1075,8 @@ * which in turn means that scatter/gather will be disabled. */ mail_out(host, (struct scb *) &icb); - while (icb.phase) /* wait for completion */; + while (icb.phase) + barrier(); /* wait for completion */ host->rev1 = icb.primary; host->rev2 = icb.secondary; } diff -u --recursive --new-file v1.2.7/linux/include/linux/sbpcd.h linux/include/linux/sbpcd.h --- v1.2.7/linux/include/linux/sbpcd.h Sat Mar 18 12:45:46 1995 +++ linux/include/linux/sbpcd.h Mon May 1 21:45:40 1995 @@ -3,7 +3,10 @@ */ /* - * the definitions for the first controller can get overridden by + * Attention! This file contains user-serviceable parts! + * I recommend to make use of it... + * + * The definitions for the first controller can get overridden by * the kernel command line ("lilo boot option"). * Examples: * sbpcd=0x230,SoundBlaster @@ -12,64 +15,97 @@ * or * sbpcd=0x330,SPEA * - * These strings are case sensitive !!! + * If sbpcd gets used as a module, you can load it with + * insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x230,1 + * or + * insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x300,0 + * or + * insmod /usr/src/linux/modules/sbpcd.o sbpcd=0x330,2 + * respective to override the configured address and type. */ /* - * put your CDROM port base address into CDROM_PORT - * and specify the type of your interface in SBPRO. + * define your CDROM port base address as CDROM_PORT + * and specify the type of your interface card as SBPRO. * - * SBPRO addresses typically are 0x0230 (=0x220+0x10), 0x0250, ... - * LASERMATE (CI-101P, WDH-7001C) addresses typically are 0x0300, 0x0310, ... - * SPEA addresses are 0x320, 0x330, 0x340, 0x350 - * there are some soundcards on the market with 0x0630, 0x0650, ... + * Read linux/drivers/block/README.sbpcd if you are in doubt about the + * type of your interface card (you should do that anyway). * - * example: if your SBPRO audio address is 0x220, specify 0x230. + * address: + * ======== + * SBPRO type addresses typically are 0x0230 (=0x220+0x10), 0x0250, ... + * LASERMATE type (CI-101P, WDH-7001C) addresses typically are 0x0300, ... + * SPEA addresses are from the LASERMATE type and range. + * There are some soundcards on the market with 0x0630, 0x0650, ...; their + * type is not obvious (both types are possible). * + * example: if your SBPRO audio address is 0x220, specify 0x230 and SBPRO 1. + * if your soundcard has its CDROM port above 0x300, specify + * that address and try SBPRO 0 first. * + * interface type: + * =============== * set SBPRO to 1 for "true" SoundBlaster card - * set SBPRO to 0 for "poor" (no sound) interface cards - * and for "compatible" soundcards. + * set SBPRO to 0 for "compatible" soundcards and + * for "poor" (no sound) interface cards. * set SBPRO to 2 for the SPEA Media FX card * - * most "compatible" sound boards like Galaxy need to set SBPRO to 0 !!! - * if SBPRO gets set wrong, the drive will get found - but any + * Almost all "compatible" sound boards need to set SBPRO to 0. + * If SBPRO is set wrong, the drives will get found - but any * data access will give errors (audio access will work). - * The OmniCD interface card from CreativeLabs needs SBPRO 1. + * The "OmniCD" no-sound interface card from CreativeLabs needs SBPRO 1. * - * mail to emoenke@gwdg.de if your "compatible" card needs SBPRO 1 - * (currently I do not know any "compatible" with SBPRO 1) - * then I can include better information with the next release. - */ -#if !(SBPCD_ISSUE-1) /* first (or if you have only one) interface board: */ -#define CDROM_PORT 0x0340 -#define SBPRO 0 -#endif - -/* - * If you have a "compatible" soundcard of type "SBPRO 0" or "SBPRO 2", - * enter your sound card's base address here if you want sbpcd to turn - * the CD sound channels on. + * mail to emoenke@gwdg.de if you have a "compatible" sound card which + * in fact needs to set SBPRO to 1 (not any known at time). + * + * sound base: + * =========== + * The SOUND_BASE definition tells if we should try to turn the CD sound + * channels on. It will only be of use regarding soundcards with a SbPro + * compatible mixer. * * Example: #define SOUND_BASE 0x220 enables the sound card's CD channels * #define SOUND_BASE 0 leaves the soundcard untouched */ -#define SOUND_BASE 0x220 - -/* ignore the rest if you have only one interface board & driver */ - -#if !(SBPCD_ISSUE-2) /* second interface board: */ -#define CDROM_PORT 0x0320 -#define SBPRO 0 +#if !(SBPCD_ISSUE-1) /* first (or if you have only one) interface board: */ +#define CDROM_PORT 0x340 /* <-----------<< port address */ +#define SBPRO 0 /* <-----------<< interface type */ +#define SOUND_BASE 0x220 /* <-----------<< sound address of this card or 0 */ #endif -#if !(SBPCD_ISSUE-3) /* third interface board: */ -#define CDROM_PORT 0x0630 -#define SBPRO 1 +#if !(SBPCD_ISSUE-2) /* ==================== second interface board: === */ +#define CDROM_PORT 0x344 /* <-----------<< port address */ +#define SBPRO 0 /* <-----------<< interface type */ +#define SOUND_BASE 0x000 /* <-----------<< sound address of this card or 0 */ #endif -#if !(SBPCD_ISSUE-4) /* fourth interface board: */ -#define CDROM_PORT 0x0634 -#define SBPRO 0 +#if !(SBPCD_ISSUE-3) /* ===================== third interface board: === */ +#define CDROM_PORT 0x634 /* <-----------<< port address */ +#define SBPRO 1 /* <-----------<< interface type */ +#define SOUND_BASE 0x240 /* <-----------<< sound address of this card or 0 */ #endif +#if !(SBPCD_ISSUE-4) /* ==================== fourth interface board: === */ +#define CDROM_PORT 0x634 /* <-----------<< port address */ +#define SBPRO 0 /* <-----------<< interface type */ +#define SOUND_BASE 0x000 /* <-----------<< sound address of this card or 0 */ +#endif + +/* + * some more or less user dependent definitions - service them! + */ + +/* Set this to 0 after you have configured your interface definitions right. */ +#define DISTRIBUTION 1 + +/* max. number of audio frames to read with one */ +/* request (allocates n* 2352 bytes kernel memory!) */ +/* may be freely adjusted, f.e. 75 (= 1 sec.), at */ +/* runtime by use of the CDROMAUDIOBUFSIZ ioctl. */ +#define READ_AUDIO 0 + +/* tray control: eject tray if no disk is in (0 or 1) */ +#define JUKEBOX 1 + +/* tray control: eject tray after last use (0 or 1) */ +#define EJECT 1 /*==========================================================================*/ /*==========================================================================*/ @@ -79,49 +115,65 @@ #ifndef _LINUX_SBPCD_H #define _LINUX_SBPCD_H - /*==========================================================================*/ /*==========================================================================*/ +#define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */ +#undef FUTURE + +#define TEST_UPC 0 +#define SPEA_TEST 0 +#define TEST_STI 0 +#undef PATH_CHECK +/*==========================================================================*/ /* * DDI interface definitions * "invented" by Fred N. van Kempen.. */ #define DDIOCSDBG 0x9000 -#define DPRINTF(x) sbpcd_dprintf x + +/*==========================================================================*/ +/* + * "private" IOCTL functions + */ +#define CDROMRESET 0x5380 /* hard-rest the drive */ +#define CDROMVOLREAD 0x5381 /* let the drive tell its volume settings */ +#define CDROMAUDIOBUFSIZ 0x5382 /* set the audio buffer size */ /*==========================================================================*/ /* * Debug output levels */ -#define DBG_INF 1 /* necessary information */ -#define DBG_BSZ 2 /* BLOCK_SIZE trace */ -#define DBG_REA 3 /* "read" status trace */ -#define DBG_CHK 4 /* "media check" trace */ -#define DBG_TIM 5 /* datarate timer test */ -#define DBG_INI 6 /* initialization trace */ -#define DBG_TOC 7 /* tell TocEntry values */ -#define DBG_IOC 8 /* ioctl trace */ -#define DBG_STA 9 /* "ResponseStatus" trace */ -#define DBG_ERR 10 /* "xx_ReadError" trace */ -#define DBG_CMD 11 /* "cmd_out" trace */ -#define DBG_WRN 12 /* give explanation before auto-probing */ -#define DBG_MUL 13 /* multi session code test */ -#define DBG_ID 14 /* "drive_id !=0" test code */ -#define DBG_IOX 15 /* some special information */ -#define DBG_DID 16 /* drive ID test */ -#define DBG_RES 17 /* drive reset info */ -#define DBG_SPI 18 /* SpinUp test */ -#define DBG_IOS 19 /* ioctl trace: "subchannel" */ -#define DBG_IO2 20 /* ioctl trace: general */ -#define DBG_UPC 21 /* show UPC information */ -#define DBG_XA 22 /* XA mode debugging */ -#define DBG_LCK 23 /* door (un)lock info */ -#define DBG_SQ 24 /* dump SubQ frame */ -#define DBG_AUD 25 /* "read audio" debugging */ -#define DBG_SEQ 26 /* Sequoia interface configuration trace */ -#define DBG_LCS 27 /* Longshine LCS-7260 debugging trace */ -#define DBG_CD2 28 /* MKE CD200 debugging trace */ -#define DBG_000 29 /* unnecessary information */ +#define DBG_INF 1 /* necessary information */ +#define DBG_BSZ 2 /* BLOCK_SIZE trace */ +#define DBG_REA 3 /* READ status trace */ +#define DBG_CHK 4 /* MEDIA CHECK trace */ +#define DBG_TIM 5 /* datarate timer test */ +#define DBG_INI 6 /* initialization trace */ +#define DBG_TOC 7 /* tell TocEntry values */ +#define DBG_IOC 8 /* ioctl trace */ +#define DBG_STA 9 /* ResponseStatus() trace */ +#define DBG_ERR 10 /* cc_ReadError() trace */ +#define DBG_CMD 11 /* cmd_out() trace */ +#define DBG_WRN 12 /* give explanation before auto-probing */ +#define DBG_MUL 13 /* multi session code test */ +#define DBG_IDX 14 /* test code for drive_id !=0 */ +#define DBG_IOX 15 /* some special information */ +#define DBG_DID 16 /* drive ID test */ +#define DBG_RES 17 /* drive reset info */ +#define DBG_SPI 18 /* SpinUp test */ +#define DBG_IOS 19 /* ioctl trace: subchannel functions */ +#define DBG_IO2 20 /* ioctl trace: general */ +#define DBG_UPC 21 /* show UPC information */ +#define DBG_XA1 22 /* XA mode debugging */ +#define DBG_LCK 23 /* door (un)lock info */ +#define DBG_SQ1 24 /* dump SubQ frame */ +#define DBG_AUD 25 /* READ AUDIO debugging */ +#define DBG_SEQ 26 /* Sequoia interface configuration trace */ +#define DBG_LCS 27 /* Longshine LCS-7260 debugging trace */ +#define DBG_CD2 28 /* MKE CD200 debugging trace */ +#define DBG_TEA 29 /* TEAC CD-55A debugging trace */ +#define DBG_TE2 30 /* TEAC CD-55A 2nd debugging level */ +#define DBG_000 31 /* unnecessary information */ /*==========================================================================*/ /*==========================================================================*/ @@ -154,35 +206,41 @@ /* * disk states (bits of diskstate_flags): */ -#define upc_valid (DriveStruct[d].diskstate_flags&upc_bit) -#define volume_valid (DriveStruct[d].diskstate_flags&volume_bit) -#define toc_valid (DriveStruct[d].diskstate_flags&toc_bit) -#define cd_size_valid (DriveStruct[d].diskstate_flags&cd_size_bit) -#define subq_valid (DriveStruct[d].diskstate_flags&subq_bit) -#define frame_size_valid (DriveStruct[d].diskstate_flags&frame_size_bit) - -/* - * bits of the status_byte (result of xx_ReadStatus): - */ -#define p_door_closed 0x80 -#define p_caddy_in 0x40 -#define p_spinning 0x20 -#define p_check 0x10 -#define p_busy_new 0x08 -#define p_door_locked 0x04 -#define p_bit_1 0x02 /* hopefully unused now */ -#define p_lcs_door_locked 0x02 /* new use of old bit */ -#define p_disk_ok 0x01 -#define p_lcs_door_closed 0x01 /* new use of old bit */ -/* - * "old" drives status result bits: - */ -#define p_caddin_old 0x40 -#define p_success_old 0x08 -#define p_busy_old 0x04 +#define upc_valid (D_S[d].diskstate_flags&upc_bit) +#define volume_valid (D_S[d].diskstate_flags&volume_bit) +#define toc_valid (D_S[d].diskstate_flags&toc_bit) +#define cd_size_valid (D_S[d].diskstate_flags&cd_size_bit) +#define subq_valid (D_S[d].diskstate_flags&subq_bit) +#define frame_size_valid (D_S[d].diskstate_flags&frame_size_bit) /* - * "generation specific" defs of the status_byte: + * the status_bits variable + */ +#define p_success 0x100 +#define p_door_closed 0x80 +#define p_caddy_in 0x40 +#define p_spinning 0x20 +#define p_check 0x10 +#define p_busy_new 0x08 +#define p_door_locked 0x04 +#define p_disk_ok 0x01 + +/* + * LCS-7260 special status result bits: + */ +#define p_lcs_door_locked 0x02 +#define p_lcs_door_closed 0x01 + +/* + * CR-52x special status result bits: + */ +#define p_caddin_old 0x40 +#define p_success_old 0x08 +#define p_busy_old 0x04 +#define p_bit_1 0x02 /* hopefully unused now */ + +/* + * "generation specific" defs of the status result bits: */ #define p0_door_closed 0x80 #define p0_caddy_in 0x40 @@ -193,6 +251,14 @@ #define p0_bit_1 0x02 /* unused */ #define p0_disk_ok 0x01 +#define pL_disk_in 0x40 +#define pL_spinning 0x20 +#define pL_check 0x10 +#define pL_success 0x08 /* unused ?? */ +#define pL_busy 0x04 +#define pL_door_locked 0x02 +#define pL_door_closed 0x01 + #define p1_door_closed 0x80 #define p1_disk_in 0x40 #define p1_spinning 0x20 @@ -214,60 +280,66 @@ /* * used drive states: */ -#define st_door_closed (DriveStruct[d].status_byte&p_door_closed) -#define st_caddy_in (DriveStruct[d].status_byte&p_caddy_in) -#define st_spinning (DriveStruct[d].status_byte&p_spinning) -#define st_check (DriveStruct[d].status_byte&p_check) -#define st_busy (DriveStruct[d].status_byte&p_busy_new) -#define st_door_locked (DriveStruct[d].status_byte&p_door_locked) -#define st_diskok (DriveStruct[d].status_byte&p_disk_ok) +#define st_door_closed (D_S[d].status_bits&p_door_closed) +#define st_caddy_in (D_S[d].status_bits&p_caddy_in) +#define st_spinning (D_S[d].status_bits&p_spinning) +#define st_check (D_S[d].status_bits&p_check) +#define st_busy (D_S[d].status_bits&p_busy_new) +#define st_door_locked (D_S[d].status_bits&p_door_locked) +#define st_diskok (D_S[d].status_bits&p_disk_ok) /* * bits of the CDi_status register: */ -#define s_not_result_ready 0x04 /* 0: "result ready" */ -#define s_not_data_ready 0x02 /* 0: "data ready" */ -#define s_attention 0x01 /* 1: "attention required" */ +#define s_not_result_ready 0x04 /* 0: "result ready" */ +#define s_not_data_ready 0x02 /* 0: "data ready" */ +#define s_attention 0x01 /* 1: "attention required" */ /* * usable as: */ -#define DRV_ATTN ((inb(CDi_status)&s_attention)!=0) -#define DATA_READY ((inb(CDi_status)&s_not_data_ready)==0) -#define RESULT_READY ((inb(CDi_status)&s_not_result_ready)==0) +#define DRV_ATTN ((inb(CDi_status)&s_attention)!=0) +#define DATA_READY ((inb(CDi_status)&s_not_data_ready)==0) +#define RESULT_READY ((inb(CDi_status)&s_not_result_ready)==0) /* * drive types (firmware versions): */ -#define drv_fam0 0x08 /* CR-52x family */ -#define drv_199 (drv_fam0+0x01) /* <200 */ -#define drv_200 (drv_fam0+0x02) /* <201 */ -#define drv_201 (drv_fam0+0x03) /* <210 */ -#define drv_210 (drv_fam0+0x04) /* <211 */ -#define drv_211 (drv_fam0+0x05) /* <300 */ -#define drv_300 (drv_fam0+0x06) /* >=300 */ - -#define drv_famL 0x10 /* Longshine family */ -#define drv_260 (drv_famL+0x01) /* LCS-7260 */ - -#define drv_fam1 0x20 /* CR-56x family */ -#define drv_099 (drv_fam1+0x01) /* <100 */ -#define drv_100 (drv_fam1+0x02) /* >=100 */ - -#define drv_fam2 0x80 /* CD200 family */ - -#define fam0_drive (DriveStruct[d].drv_type&drv_fam0) -#define famL_drive (DriveStruct[d].drv_type&drv_famL) -#define fam1_drive (DriveStruct[d].drv_type&drv_fam1) -#define fam2_drive (DriveStruct[d].drv_type&drv_fam2) -#define fam0L_drive (DriveStruct[d].drv_type&(drv_fam0|drv_famL)) -#define fam1L_drive (DriveStruct[d].drv_type&(drv_fam1|drv_famL)) -#define fam01_drive (DriveStruct[d].drv_type&(drv_fam0|drv_fam1)) +#define drv_fam0 0x08 /* CR-52x family */ +#define drv_199 (drv_fam0+0x01) /* <200 */ +#define drv_200 (drv_fam0+0x02) /* <201 */ +#define drv_201 (drv_fam0+0x03) /* <210 */ +#define drv_210 (drv_fam0+0x04) /* <211 */ +#define drv_211 (drv_fam0+0x05) /* <300 */ +#define drv_300 (drv_fam0+0x06) /* >=300 */ + +#define drv_famL 0x10 /* Longshine family */ +#define drv_260 (drv_famL+0x01) /* LCS-7260 */ +#define drv_e1 (drv_famL+0x01) /* LCS-7260, firmware "A E1" */ +#define drv_f4 (drv_famL+0x02) /* LCS-7260, firmware "A4F4" */ + +#define drv_fam1 0x20 /* CR-56x family */ +#define drv_099 (drv_fam1+0x01) /* <100 */ +#define drv_100 (drv_fam1+0x02) /* >=100, only 5.00 known here */ + +#define drv_famT 0x40 /* TEAC CD-55A */ +#define drv_fam2 0x80 /* CD200 family */ + +#define fam0_drive (D_S[d].drv_type&drv_fam0) +#define famL_drive (D_S[d].drv_type&drv_famL) +#define fam1_drive (D_S[d].drv_type&drv_fam1) +#define fam2_drive (D_S[d].drv_type&drv_fam2) +#define famT_drive (D_S[d].drv_type&drv_famT) +#define fam0L_drive (D_S[d].drv_type&(drv_fam0|drv_famL)) +#define fam1L_drive (D_S[d].drv_type&(drv_fam1|drv_famL)) +#define fam01_drive (D_S[d].drv_type&(drv_fam0|drv_fam1)) +#define fam12_drive (D_S[d].drv_type&(drv_fam1|drv_fam2)) +#define fam2T_drive (D_S[d].drv_type&(drv_fam2|drv_famT)) /* * audio states: */ -#define audio_playing 2 -#define audio_pausing 1 +#define audio_playing 2 +#define audio_pausing 1 /* * drv_pattern, drv_options: @@ -280,10 +352,10 @@ /* * values of cmd_type (0 else): */ -#define READ_M1 0x01 /* "data mode 1": 2048 bytes per frame */ -#define READ_M2 0x02 /* "data mode 2": 12+2048+280 bytes per frame */ -#define READ_SC 0x04 /* "subchannel info": 96 bytes per frame */ -#define READ_AU 0x08 /* "audio frame": 2352 bytes per frame */ +#define READ_M1 0x01 /* "data mode 1": 2048 bytes per frame */ +#define READ_M2 0x02 /* "data mode 2": 12+2048+280 bytes per frame */ +#define READ_SC 0x04 /* "subchannel info": 96 bytes per frame */ +#define READ_AU 0x08 /* "audio frame": 2352 bytes per frame */ /* * sense_byte: @@ -314,32 +386,27 @@ /* * highest allowed drive number (MINOR+1) */ -#define NR_SBPCD 4 +#define NR_SBPCD 4 /* * we try to never disable interrupts - seems to work */ -#define SBPCD_DIS_IRQ 0 +#define SBPCD_DIS_IRQ 0 /* * "write byte to port" */ -#define OUT(x,y) outb(y,x) - -/* - * use "REP INSB" for strobing the data in: - */ -#define READ_DATA(port, buf, nr) insb(port, buf, nr) +#define OUT(x,y) outb(y,x) /*==========================================================================*/ -#define MIXER_CD_Volume 0x28 /* internal SB Pro register address */ +#define MIXER_CD_Volume 0x28 /* internal SB Pro register address */ /*==========================================================================*/ /* * Creative Labs Programmers did this: */ -#define MAX_TRACKS 120 /* why more than 99? */ +#define MAX_TRACKS 120 /* why more than 99? */ /*==========================================================================*/ /* @@ -347,17 +414,15 @@ */ typedef union _msf { - u_int n; - u_char c[4]; -} -MSF; + u_int n; + u_char c[4]; +} MSF; typedef union _blk { - u_int n; - u_char c[4]; -} -BLK; + u_int n; + u_char c[4]; +} BLK; /*==========================================================================*/ @@ -519,111 +584,177 @@ * CR-56x: CMD1_ * CD200: CMD2_ * LCS-7260: CMDL_ + * TEAC CD-55A: CMDT_ */ #define CMD1_RESET 0x0a #define CMD2_RESET 0x01 +#define CMDT_RESET 0xc0 + #define CMD1_LOCK_CTL 0x0c #define CMD2_LOCK_CTL 0x1e +#define CMDT_LOCK_CTL CMD2_LOCK_CTL #define CMDL_LOCK_CTL 0x0e + #define CMD1_TRAY_CTL 0x07 #define CMD2_TRAY_CTL 0x1b +#define CMDT_TRAY_CTL CMD2_TRAY_CTL #define CMDL_TRAY_CTL 0x0d + #define CMD1_MULTISESS 0x8d #define CMDL_MULTISESS 0x8c + #define CMD1_SUBCHANINF 0x11 -#define CMD2_SUBCHANINF 0x +#define CMD2_SUBCHANINF 0x?? + #define CMD2_x02 0x02 #define CMD1_x08 0x08 #define CMD2_x08 0x08 +#define CMDT_x08 0x08 + #define CMD2_SETSPEED 0xda #define CMD0_PATH_CHECK 0x00 -#define CMD1_PATH_CHECK 0x00 -#define CMD2_PATH_CHECK 0x -#define CMDL_PATH_CHECK 0x00 +#define CMD1_PATH_CHECK 0x??? +#define CMD2_PATH_CHECK 0x??? +#define CMDT_PATH_CHECK 0x??? +#define CMDL_PATH_CHECK CMD0_PATH_CHECK + #define CMD0_SEEK 0x01 -#define CMD1_SEEK 0x01 +#define CMD1_SEEK CMD0_SEEK #define CMD2_SEEK 0x2b -#define CMDL_SEEK 0x01 +#define CMDT_SEEK CMD2_SEEK +#define CMDL_SEEK CMD0_SEEK + #define CMD0_READ 0x02 #define CMD1_READ 0x10 #define CMD2_READ 0x28 -#define CMDL_READ 0x02 +#define CMDT_READ CMD2_READ +#define CMDL_READ CMD0_READ + #define CMD0_READ_XA 0x03 #define CMD2_READ_XA 0xd4 -#define CMDL_READ_XA 0x03 /* really ?? */ +#define CMDL_READ_XA CMD0_READ_XA /* really ?? */ + #define CMD0_READ_HEAD 0x04 + #define CMD0_SPINUP 0x05 #define CMD1_SPINUP 0x02 #define CMD2_SPINUP CMD2_TRAY_CTL -#define CMDL_SPINUP 0x05 +#define CMDL_SPINUP CMD0_SPINUP + #define CMD0_SPINDOWN 0x06 /* really??? */ #define CMD1_SPINDOWN 0x06 #define CMD2_SPINDOWN CMD2_TRAY_CTL #define CMDL_SPINDOWN 0x0d + #define CMD0_DIAG 0x07 + #define CMD0_READ_UPC 0x08 #define CMD1_READ_UPC 0x88 -#define CMD2_READ_UPC 0x -#define CMDL_READ_UPC 0x08 +#define CMD2_READ_UPC 0x??? +#define CMDL_READ_UPC CMD0_READ_UPC + #define CMD0_READ_ISRC 0x09 + #define CMD0_PLAY 0x0a -#define CMD1_PLAY 0x -#define CMD2_PLAY 0x -#define CMDL_PLAY 0x0a +#define CMD1_PLAY 0x??? +#define CMD2_PLAY 0x??? +#define CMDL_PLAY CMD0_PLAY + #define CMD0_PLAY_MSF 0x0b #define CMD1_PLAY_MSF 0x0e #define CMD2_PLAY_MSF 0x47 -#define CMDL_PLAY_MSF 0x +#define CMDT_PLAY_MSF CMD2_PLAY_MSF +#define CMDL_PLAY_MSF 0x??? + #define CMD0_PLAY_TI 0x0c + #define CMD0_STATUS 0x81 #define CMD1_STATUS 0x05 #define CMD2_STATUS 0x00 -#define CMDL_STATUS 0x81 +#define CMDT_STATUS CMD2_STATUS +#define CMDL_STATUS CMD0_STATUS + #define CMD0_READ_ERR 0x82 -#define CMD1_READ_ERR 0x82 +#define CMD1_READ_ERR CMD0_READ_ERR #define CMD2_READ_ERR 0x03 -#define CMDL_READ_ERR 0x82 +#define CMDT_READ_ERR CMD2_READ_ERR /* get audio status */ +#define CMDL_READ_ERR CMD0_READ_ERR + #define CMD0_READ_VER 0x83 -#define CMD1_READ_VER 0x83 +#define CMD1_READ_VER CMD0_READ_VER #define CMD2_READ_VER 0x12 -#define CMDL_READ_VER 0x83 +#define CMDT_READ_VER CMD2_READ_VER /* really ?? */ +#define CMDL_READ_VER CMD0_READ_VER + #define CMD0_SETMODE 0x84 #define CMD1_SETMODE 0x09 #define CMD2_SETMODE 0x55 -#define CMDL_SETMODE 0x84 +#define CMDT_SETMODE CMD2_SETMODE +#define CMDL_SETMODE CMD0_SETMODE + #define CMD0_GETMODE 0x85 #define CMD1_GETMODE 0x84 #define CMD2_GETMODE 0x5a -#define CMDL_GETMODE 0x85 +#define CMDT_GETMODE CMD2_GETMODE +#define CMDL_GETMODE CMD0_GETMODE + #define CMD0_SET_XA 0x86 + #define CMD0_GET_XA 0x87 + #define CMD0_CAPACITY 0x88 #define CMD1_CAPACITY 0x85 #define CMD2_CAPACITY 0x25 -#define CMDL_CAPACITY 0x88 +#define CMDL_CAPACITY CMD0_CAPACITY /* missing in some firmware versions */ + #define CMD0_READSUBQ 0x89 #define CMD1_READSUBQ 0x87 #define CMD2_READSUBQ 0x42 -#define CMDL_READSUBQ 0x89 +#define CMDT_READSUBQ CMD2_READSUBQ +#define CMDL_READSUBQ CMD0_READSUBQ + #define CMD0_DISKCODE 0x8a + #define CMD0_DISKINFO 0x8b -#define CMD1_DISKINFO 0x8b +#define CMD1_DISKINFO CMD0_DISKINFO #define CMD2_DISKINFO 0x43 -#define CMDL_DISKINFO 0x8b +#define CMDT_DISKINFO CMD2_DISKINFO +#define CMDL_DISKINFO CMD0_DISKINFO + #define CMD0_READTOC 0x8c -#define CMD1_READTOC 0x8c -#define CMD2_READTOC 0x -#define CMDL_READTOC 0x8c +#define CMD1_READTOC CMD0_READTOC +#define CMD2_READTOC 0x??? +#define CMDL_READTOC CMD0_READTOC + #define CMD0_PAU_RES 0x8d #define CMD1_PAU_RES 0x0d #define CMD2_PAU_RES 0x4b -#define CMDL_PAU_RES 0x8d +#define CMDT_PAUSE CMD2_PAU_RES +#define CMDL_PAU_RES CMD0_PAU_RES + #define CMD0_PACKET 0x8e -#define CMD1_PACKET 0x8e -#define CMD2_PACKET 0x -#define CMDL_PACKET 0x8e +#define CMD1_PACKET CMD0_PACKET +#define CMD2_PACKET 0x??? +#define CMDL_PACKET CMD0_PACKET /*==========================================================================*/ /*==========================================================================*/ #endif _LINUX_SBPCD_H +/*==========================================================================*/ +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ diff -u --recursive --new-file v1.2.7/linux/include/linux/sched.h linux/include/linux/sched.h --- v1.2.7/linux/include/linux/sched.h Sun Apr 9 11:59:57 1995 +++ linux/include/linux/sched.h Tue May 2 07:22:23 1995 @@ -77,6 +77,8 @@ #ifdef __KERNEL__ +#define barrier() __asm__("": : :"memory") + extern void sched_init(void); extern void show_state(void); extern void trap_init(void); diff -u --recursive --new-file v1.2.7/linux/include/linux/tty.h linux/include/linux/tty.h --- v1.2.7/linux/include/linux/tty.h Sun Feb 26 16:45:26 1995 +++ linux/include/linux/tty.h Tue May 2 08:33:51 1995 @@ -255,6 +255,7 @@ #define TTY_DEBUG 4 #define TTY_DO_WRITE_WAKEUP 5 #define TTY_PUSH 6 +#define TTY_CLOSING 7 #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty)) diff -u --recursive --new-file v1.2.7/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v1.2.7/linux/kernel/ksyms.c Fri Apr 28 11:10:56 1995 +++ linux/kernel/ksyms.c Tue May 2 08:05:05 1995 @@ -321,7 +321,6 @@ X(n_tty_ioctl), X(tty_register_ldisc), X(kill_fasync), - X(tty_hung_up_p), #endif #ifdef CONFIG_SCSI /* Supports loadable scsi drivers */ diff -u --recursive --new-file v1.2.7/linux/net/inet/datagram.c linux/net/inet/datagram.c --- v1.2.7/linux/net/inet/datagram.c Thu Mar 9 20:37:36 1995 +++ linux/net/inet/datagram.c Tue May 2 18:58:07 1995 @@ -15,6 +15,7 @@ * AX.25 now works right, and SPX is feasible. * Alan Cox : Fixed write select of non IP protocol crash. * Florian La Roche: Changed for my new skbuff handling. + * Darryl Miles : Fixed non-blocking SOCK_SEQPACKET. * * Note: * A lot of this will change when the protocol/socket separation @@ -191,6 +192,11 @@ return(0); case SEL_OUT: + if (sk->type==SOCK_SEQPACKET && sk->state==TCP_SYN_SENT) + { + /* Connection still in progress */ + return(0); + } if (sk->prot && sk->prot->wspace(sk) >= MIN_WRITE_SPACE) { return(1); diff -u --recursive --new-file v1.2.7/linux/net/inet/tcp.c linux/net/inet/tcp.c --- v1.2.7/linux/net/inet/tcp.c Wed Mar 29 06:53:01 1995 +++ linux/net/inet/tcp.c Tue May 2 18:57:03 1995 @@ -2854,7 +2854,7 @@ buff = newsk->prot->wmalloc(newsk, MAX_SYN_SIZE, 1, GFP_ATOMIC); if (buff == NULL) { - sk->err = -ENOMEM; + sk->err = ENOMEM; newsk->dead = 1; newsk->state = TCP_CLOSE; /* And this will destroy it */