diff options
author | jkh <jkh@FreeBSD.org> | 1995-03-02 04:07:03 +0000 |
---|---|---|
committer | jkh <jkh@FreeBSD.org> | 1995-03-02 04:07:03 +0000 |
commit | 210fe3dddd329efda88d011a4a7fb0a2d6c0941a (patch) | |
tree | 1292d19796d8a9f0d0385e8dfd4d552c765f766b /sys | |
parent | 206b955407327511e61c0f5b13e75fdffa31a9d4 (diff) | |
download | FreeBSD-src-210fe3dddd329efda88d011a4a7fb0a2d6c0941a.zip FreeBSD-src-210fe3dddd329efda88d011a4a7fb0a2d6c0941a.tar.gz |
Changes to incorporate the Matsushita CDROM driver (otherwise known as
the "Sound blaster CDROM").
Submitted by: Frank Durda IV <bsdmail@nemesis.lonestar.org>
Diffstat (limited to 'sys')
-rw-r--r-- | sys/amd64/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/conf/NOTES | 13 | ||||
-rw-r--r-- | sys/i386/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/i386/conf/LINT | 13 | ||||
-rw-r--r-- | sys/i386/conf/NOTES | 13 | ||||
-rw-r--r-- | sys/i386/i386/conf.c | 28 | ||||
-rw-r--r-- | sys/i386/isa/creative.h | 129 | ||||
-rw-r--r-- | sys/i386/isa/matcd.c | 2279 | ||||
-rw-r--r-- | sys/i386/isa/matcd.h | 183 | ||||
-rw-r--r-- | sys/i386/isa/options.h | 250 |
10 files changed, 2893 insertions, 23 deletions
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 1daaec4..72e30b5 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -1,7 +1,7 @@ # # GENERIC -- Generic machine with WD/AHx/NCR/BTx family disks # -# $Id: GENERIC,v 1.31 1995/02/09 11:21:07 jkh Exp $ +# $Id: GENERIC,v 1.32 1995/02/15 20:38:36 joerg Exp $ # machine "i386" @@ -66,6 +66,8 @@ device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr device mcd1 at isa? port 0x340 bio irq 11 vector mcdintr +controller matcd0 at isa? port ? + device scd0 at isa? port 0x230 bio # syscons is the default console driver, resembling an SCO console diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 5ea553a..07080ab 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.147 1995/02/23 17:19:53 bde Exp $ +# $Id: LINT,v 1.148 1995/03/01 22:27:45 dufault Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -553,7 +553,7 @@ device pca0 at isa? tty # # mcd: Mitsumi CD-ROM # scd: Sony CD-ROM -# pcd: Panasonic CD-ROM +# matcd: Matsushita/Panasonic CD-ROM # wt: Wangtek and Archive QIC-02/QIC-36 tape drives # ctx: Cortex-I frame grabber # apm: Laptop Advanced Power Management (experimental) @@ -567,10 +567,13 @@ device pca0 at isa? tty # Note that the start address must be on an even boundary. device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr -# for the soundblaster 16 multicd +# for the Sony CDU31/33A CDROM device scd0 at isa? port 0x230 bio -# for the soundblaster 16 multicd -#device pcd0 at isa? port 0x220 bio +# for the soundblaster 16 multicd - up to 4 devices +controller matcd0 at isa? port ? +#controller matcd1 at isa? port ? +#controller matcd2 at isa? port ? +#controller matcd3 at isa? port ? device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 vector spigintr diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index 1daaec4..72e30b5 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -1,7 +1,7 @@ # # GENERIC -- Generic machine with WD/AHx/NCR/BTx family disks # -# $Id: GENERIC,v 1.31 1995/02/09 11:21:07 jkh Exp $ +# $Id: GENERIC,v 1.32 1995/02/15 20:38:36 joerg Exp $ # machine "i386" @@ -66,6 +66,8 @@ device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr device mcd1 at isa? port 0x340 bio irq 11 vector mcdintr +controller matcd0 at isa? port ? + device scd0 at isa? port 0x230 bio # syscons is the default console driver, resembling an SCO console diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index 5ea553a..07080ab 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.147 1995/02/23 17:19:53 bde Exp $ +# $Id: LINT,v 1.148 1995/03/01 22:27:45 dufault Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -553,7 +553,7 @@ device pca0 at isa? tty # # mcd: Mitsumi CD-ROM # scd: Sony CD-ROM -# pcd: Panasonic CD-ROM +# matcd: Matsushita/Panasonic CD-ROM # wt: Wangtek and Archive QIC-02/QIC-36 tape drives # ctx: Cortex-I frame grabber # apm: Laptop Advanced Power Management (experimental) @@ -567,10 +567,13 @@ device pca0 at isa? tty # Note that the start address must be on an even boundary. device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr -# for the soundblaster 16 multicd +# for the Sony CDU31/33A CDROM device scd0 at isa? port 0x230 bio -# for the soundblaster 16 multicd -#device pcd0 at isa? port 0x220 bio +# for the soundblaster 16 multicd - up to 4 devices +controller matcd0 at isa? port ? +#controller matcd1 at isa? port ? +#controller matcd2 at isa? port ? +#controller matcd3 at isa? port ? device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 vector spigintr diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index 5ea553a..07080ab 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.147 1995/02/23 17:19:53 bde Exp $ +# $Id: LINT,v 1.148 1995/03/01 22:27:45 dufault Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -553,7 +553,7 @@ device pca0 at isa? tty # # mcd: Mitsumi CD-ROM # scd: Sony CD-ROM -# pcd: Panasonic CD-ROM +# matcd: Matsushita/Panasonic CD-ROM # wt: Wangtek and Archive QIC-02/QIC-36 tape drives # ctx: Cortex-I frame grabber # apm: Laptop Advanced Power Management (experimental) @@ -567,10 +567,13 @@ device pca0 at isa? tty # Note that the start address must be on an even boundary. device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr -# for the soundblaster 16 multicd +# for the Sony CDU31/33A CDROM device scd0 at isa? port 0x230 bio -# for the soundblaster 16 multicd -#device pcd0 at isa? port 0x220 bio +# for the soundblaster 16 multicd - up to 4 devices +controller matcd0 at isa? port ? +#controller matcd1 at isa? port ? +#controller matcd2 at isa? port ? +#controller matcd3 at isa? port ? device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 vector spigintr diff --git a/sys/i386/i386/conf.c b/sys/i386/i386/conf.c index cf947de..c1690e7 100644 --- a/sys/i386/i386/conf.c +++ b/sys/i386/i386/conf.c @@ -42,7 +42,7 @@ * SUCH DAMAGE. * * from: @(#)conf.c 5.8 (Berkeley) 5/12/91 - * $Id: conf.c,v 1.70 1995/02/28 00:20:45 pst Exp $ + * $Id: conf.c,v 1.71 1995/03/01 22:29:05 dufault Exp $ */ #include <sys/param.h> @@ -332,8 +332,8 @@ struct bdevsw bdevsw[] = vndump, vnsize, 0 }, { scdopen, scdclose, scdstrategy, scdioctl, /*16*/ scddump, scdsize, 0 }, - { pcdopen, pcdclose, pcdstrategy, pcdioctl, /*17*/ - pcddump, pcdsize, 0 } + { matcdopen, matcdclose, matcdstrategy, matcdioctl, /*17*/ + matcddump, matcdsize, 0 } /* * If you need a bdev major number for a driver that you intend to donate * back to the group or release publically, please contact the FreeBSD team @@ -903,6 +903,22 @@ d_ioctl_t ispyioctl; #define ispyioctl nxioctl #endif +#include "matcd.h" +#if NMATCD > 0 +d_open_t matcdopen; +d_close_t matcdclose; +d_strategy_t matcdstrategy; +d_ioctl_t matcdioctl; +d_psize_t matcdsize; +#define matcddump nxdump +#else +#define matcdopen nxopen +#define matcdclose nxclose +#define matcdstrategy nxstrategy +#define matcdioctl nxioctl +#define matcddump nxdump +#define matcdsize (d_psize_t *)0 +#endif /* open, close, read, write, ioctl, stop, reset, ttys, select, mmap, strat */ struct cdevsw cdevsw[] = @@ -1054,9 +1070,9 @@ struct cdevsw cdevsw[] = { scdopen, scdclose, rawread, nowrite, /*45*/ scdioctl, nostop, nullreset, nodevtotty,/* sony cd */ seltrue, nommap, scdstrategy }, - { pcdopen, pcdclose, rawread, nowrite, /*46*/ - pcdioctl, nostop, nullreset, nodevtotty,/* pana cd */ - seltrue, nommap, pcdstrategy }, + { matcdopen, matcdclose, rawread, nowrite, /*46*/ + matcdioctl, nostop, nullreset, nodevtotty,/* SB cd */ + seltrue, nommap, matcdstrategy }, { gscopen, gscclose, gscread, nowrite, /*47*/ gscioctl, nostop, nullreset, nodevtotty,/* gsc */ seltrue, nommap, NULL }, diff --git a/sys/i386/isa/creative.h b/sys/i386/isa/creative.h new file mode 100644 index 0000000..ed7e1dd --- /dev/null +++ b/sys/i386/isa/creative.h @@ -0,0 +1,129 @@ +/*creative.h------------------------------------------------------------------- + Matsushita(Panasonic) / Creative CD-ROM Driver (matcd) + Authored by Frank Durda IV + + Copyright 1994, 1995 Frank Durda IV. All rights reserved. + "FDIV" is a trademark of Frank Durda IV. + + Redistribution and use in source and binary forms, with or + without modification, are permitted provided that the following + conditions are met: + 1. Redistributions of source code must retain the above copyright + notice positioned at the very beginning of this file without + modification, all copyright strings, all related programming + codes that display the copyright strings, this list of + conditions and the following disclaimer. + 2. Redistributions in binary form must contain all copyright strings + and related programming code that display the copyright strings. + 3. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 4. All advertising materials mentioning features or use of this + software must display the following acknowledgement: + "The Matsushita/Panasonic CD-ROM driver was developed + by Frank Durda IV for use with "FreeBSD" and similar + operating systems." + "Similar operating systems" includes mainly non-profit oriented + systems for research and education, including but not restricted + to "NetBSD", "386BSD", and "Mach" (by CMU). The wording of the + acknowledgement (in electronic form or printed text) may not be + changed without permission from the author. + 5. Absolutely no warranty of function, fitness or purpose is made + by the author Frank Durda IV. + 6. Neither the name of the author nor the name "FreeBSD" may + be used to endorse or promote products derived from this software + without specific prior written permission. + (The author can be reached at bsdmail@nemesis.lonestar.org) + 7. The product containing this software must meet all of these + conditions even if it is unsupported, not a complete system + and/or does not contain compiled code. + 8. These conditions will be in force for the full life of the + copyright. + 9. If all the above conditions are met, modifications to other + parts of this file may be freely made, although any person + or persons making changes do not receive the right to add their + name or names to the copyright strings and notices in this + software. Persons making changes are encouraged to insert edit + history in matcd.c and to put your name and details of the + change there. + 10. You must have prior written permission from the author to + deviate from these terms. + + Vendors who produce product(s) containing this code are encouraged + (but not required) to provide copies of the finished product(s) to + the author and to correspond with the author about development + activity relating to this code. Donations of development hardware + and/or software are also welcome. (This is one of the faster ways + to get a driver developed for a device.) + + THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER(S) BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +See matcd.c for Edit History + + These are the I/O port mapping offsets and bit assignments used + by Creative Labs in their implementation of the host interface for + the Matsushita CD-ROM drive. These may be different in the adapter + cards (including sound cards) made by other vendors. + It is unknown if the Creative interface is based on a reference design + provided by Matsushita (other interface vendors would similar or + identical if this was the case). + + The drive is actually capable of some things that the Creative + interface doesn't implement, such as DMA and interrupts. + + See matcd.h for defines related to the Matsushita drive itself. +*/ + + +/* Creative Labs (and compatible) I/O port mapping offsets +*/ + +#define NUMPORTS 4 /*Four ports are decoded by the i/f*/ + +#define CMD 0 /*Write - commands*/ +#define DATA 0 /*Read - data/status from drive*/ +#define PHASE 1 /*Write - switch between data/status*/ +#define STATUS 1 /*Read - buss status*/ +#define RESET 2 /*Write - reset all attached drives*/ + /*Any value written will reset*/ +#define SELECT 3 /*Write - drive select*/ + + +/* Creative PHASE port bit assignments +*/ + +#define PHASENA 1 /*Access data bytes instead of status*/ + + +/* Creative STATUS port register bits +*/ + +#define DTEN 2 /*When low, in data xfer phase*/ +#define STEN 4 /*When low, in status phase*/ +#define TEST 1 /*Function is unknown*/ + + +/* Creative drive SELECT port bit assignments + Note that in the Creative interface, DS0==Bit 1 and + DS1==Bit 0 (DS is Drive Select). +*/ + +#define CRDRIVE0 0x00 +#define CRDRIVE1 0x02 +#define CRDRIVE2 0x01 +#define CRDRIVE3 0x03 + +/*End of creative.h*/ + + diff --git a/sys/i386/isa/matcd.c b/sys/i386/isa/matcd.c new file mode 100644 index 0000000..8b600b1 --- /dev/null +++ b/sys/i386/isa/matcd.c @@ -0,0 +1,2279 @@ +/*matcd.c-------------------------------------------------------------------- + Matsushita(Panasonic) / Creative CD-ROM Driver (matcd) + Authored by Frank Durda IV + + Copyright 1994, 1995 Frank Durda IV. All rights reserved. + "FDIV" is a trademark of Frank Durda IV. + + + Redistribution and use in source and binary forms, with or + without modification, are permitted provided that the following + conditions are met: + 1. Redistributions of source code must retain the above copyright + notice positioned at the very beginning of this file without + modification, all copyright strings, all related programming + codes that display the copyright strings, this list of + conditions and the following disclaimer. + 2. Redistributions in binary form must contain all copyright strings + and related programming code that display the copyright strings. + 3. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 4. All advertising materials mentioning features or use of this + software must display the following acknowledgement: + "The Matsushita/Panasonic CD-ROM driver was developed + by Frank Durda IV for use with "FreeBSD" and similar + operating systems." + "Similar operating systems" includes mainly non-profit oriented + systems for research and education, including but not restricted + to "NetBSD", "386BSD", and "Mach" (by CMU). The wording of the + acknowledgement (in electronic form or printed text) may not be + changed without permission from the author. + 5. Absolutely no warranty of function, fitness or purpose is made + by the author Frank Durda IV. + 6. Neither the name of the author nor the name "FreeBSD" may + be used to endorse or promote products derived from this software + without specific prior written permission. + (The author can be reached at bsdmail@nemesis.lonestar.org) + 7. The product containing this software must meet all of these + conditions even if it is unsupported, not a complete system + and/or does not contain compiled code. + 8. These conditions will be in force for the full life of the + copyright. + 9. If all the above conditions are met, modifications to other + parts of this file may be freely made, although any person + or persons making changes do not receive the right to add their + name or names to the copyright strings and notices in this + software. Persons making changes are encouraged to insert edit + history in matcd.c and to put your name and details of the + change there. + 10. You must have prior written permission from the author to + deviate from these terms. + + Vendors who produce product(s) containing this code are encouraged + (but not required) to provide copies of the finished product(s) to + the author and to correspond with the author about development + activity relating to this code. Donations of development hardware + and/or software are also welcome. (This is one of the faster ways + to get a driver developed for a device.) + + THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER(S) BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +Dedicated to: My family and Max, my Golden Retriever + +Thanks to: Jordan Hubbard (jkh) for getting me ramped-up to 2.x system + quickly enough to make the 2.1 release. He put up with + plenty of silly questions. + +and The people who donated equipment and other material to make + development of this driver possible. Donations and + sponsors for projects are appreciated. + + +----------------------------------------------------------------------------- +Edit History - (should be in sync with any source control log entries) + + Never seen one of these before? Ok, here is how it works. + Every time you change the code, you increment the edit number, + that number over there in the <%d> and in the (%d) in the + version string. You never set this number lower than it is. + Near, or preferably on lines that change, insert the edit + number. If there is a number there already, you can replace it + with a newer one. + + In the edit history, start with the edit number, and a good + description of what changes were made. Then follow it with + the date, your name and an EMAIL address where you can be reached. + + Please follow this practice; it helps leave understandable code in + your wake. + + FYI, you have major and minor release codes. These are numbered + 1 thru n. Major feature additions should get a new major release + number. Minor releases start with a null and then letters + A thru Z. So 3A(456) is Major release 3, Minor release 1, + Edit 456 (in Microsoft-ese that would be 03.01.456), and 5(731) + is Major release 5, Minor release 0, Edit 731. Typically only the + author will change the major and minor release codes. + + EDIT edit Edit HISTORY history History + +<1> This initial version is to get basic filesystem I/O working + using the SoundBlaster 16 interface. The stand-alone adapter + card doesn't work yet. + December 1994 Frank Durda IV bsdmail@nemesis.lonestar.org + +<2> Corrections to resolve a race condition when multiple drives + on the same controller was active. Fixed drive 1 & 2 swap + problem. See selectdrive(). + 21-Jan-95 Frank Durda IV bsdmail@nemesis.lonestar.org + +<3> Added automatic probing and support for all Creative Labs sound + cards with the Creative/Panasonic interface and the stand-alone + interface adapters. See AUTOHUNT and FULLCONFIG conditionals + for more information. + 21-Jan-95 Frank Durda IV bsdmail@nemesis.lonestar.org + +<4> Rebundled debug conditionals. + 14-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org + +<5> Changes needed to work on FreeBSD 2.1. Also added draincmd + since some conditions cause the drive to produce surprise data. + See setmode and draincmd + 19-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org + +<6> Got rid of some redundant error code by creating chk_error(). + Also built a nice generic buss-lock function. + 20-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org + +<7> Improved comments, general structuring. + Fixed a problem with disc eject not working if LOCKDRIVE was set. + Apparently the drive will reject an EJECT command if the drive + is LOCKED. + 21-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org + +Edit number code marking begins here - earlier edits were during development. + +<8> Final device name selected and actually made to compile under + >2.0. For newer systems, it is "matcd", for older it is "mat". + 24-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org + +<9> Added some additional disk-related ioctl functions that didn't + make it into earlier versions. + 26-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org + +<10> Updated some conditionals so the code will compile under + 1.1.5.1, although this is not the supported platform. + Also found that some other devices probe code was changing the + settings for the port 0x302 debug board, so added code to set it + to a sane state before we use it. + 26-Feb-95 Frank Durda IV bsdmail@nemesis.lonestar.org + + +---------------------------------------------------------------------------*/ + +/*Match this format: Version__dc(d)__dd-mmm-yy */ +static char MATCDVERSION[]="Version 1(10) 26-Feb-95"; + +/* The following strings may not be changed*/ +static char MATCDCOPYRIGHT[] = "Matsushita CD-ROM driver, Copr. 1994,1995 Frank Durda IV"; +/* The proceeding strings may not be changed*/ + + +/*--------------------------------------------------------------------------- + Include declarations +---------------------------------------------------------------------------*/ + +#include "types.h" +#include "param.h" +#include "systm.h" + +#include "buf.h" +#include "dkbad.h" +#include "cdio.h" +#include "conf.h" +#include "disklabel.h" +#include "errno.h" +#include "file.h" +#include "i386/isa/isa.h" +#include "i386/isa/isa_device.h" +#include "ioctl.h" +#include "stat.h" +#include "uio.h" + +#include "options.h" /*Conditional compile options and + probe port hints*/ +#include "matcd.h" /*Drive-related defines and strings*/ +#include "creative.h" /*Host interface related defines*/ + + +/*--------------------------------------------------------------------------- + Defines and structures +---------------------------------------------------------------------------*/ + +#ifdef FULLCONFIG +#define NUMCTRLRS 4 /*With modern boards, four is max*/ +#else /*FULLCONFIG*/ +#define NUMCTRLRS 1 /*Produces a slightly smaller kernel*/ +#endif /*FULLCONFIG*/ +#define DRIVESPERC 4 /*This is a constant*/ +#define TOTALDRIVES NUMCTRLRS*DRIVESPERC /*Max possible drives*/ +#if DIAGPORT > 0xff /*<10>*/ +#define DIAGOUT outw /*<10>*/ +#else /*DIAGPORT*/ /*<10>*/ +#define DIAGOUT outb /*<10>*/ +#endif /*DIAGPORT*/ /*<10>*/ +#ifdef DIAGPORT +int diagloop; /*Used to show looping*/ +#endif /*DIAGPORT*/ + + +#define TICKRES 10 /*Our coarse timer resolution*/ +#define ISABUSKHZ 8330 /*Number of IN/OUT ISA/sec*/ + +#ifndef FREE2 +#define RAW_PART 2 /*Needs to be defined in 1.1.5.1*/ +#endif /*FREE2*/ + + +#define MATCDBLK 2048 /*Standard block size*/ +#define MATCDRBLK 2352 /*Raw and/or DA block size*/ +#define MATCD_RETRYS 5 /*Number of retries for read ops*/ +#define MATCD_READ_1 0x80 /*Read state machine defines*/ +#define MATCD_READ_2 0x90 /*Read state machine defines*/ + +struct matcd_volinfo { + unsigned char type; /*00 CD-DA or CD-ROM + 10 CD-I + 20 XA */ + unsigned char trk_low; /*Normally 1*/ + unsigned char trk_high; /*Highest track number*/ + unsigned char vol_msf[3]; /*Size of disc in min/sec/frame*/ +}; + + +struct matcd_mbx { + short controller; + short ldrive; + short partition; + short port; + short retry; + short nblk; + int sz; + u_long skip; + struct buf *bp; + int p_offset; + short count; +}; + + +struct matcd_data { + short config; + short drivemode; /*Last state drive was set to*/ + short flags; + short status; + int blksize; + u_long disksize; + int iobase; + struct disklabel dlabel; + int partflags[MAXPARTITIONS]; + int openflags; + struct matcd_volinfo volinfo; + short debug; + struct matcd_mbx mbx; +} matcd_data[TOTALDRIVES]; + + +/* Bit equates for matcd_data.flags*/ + +#define MATCDINIT 0x0001 /*Probe ran on host adapter*/ +#define MATCDLABEL 0x0004 /*Valid TOC exists*/ +#define MATCDWARN 0x0020 /*Have reported an open disc change*/ + + +/* Bit equates for matcd_data.partflags*/ + +#define MATCDOPEN 0x0001 +#define MATCDREADRAW 0x0002 + + +#define DELAY_STATUS 10000l /* 10000 * 1us */ +#define DELAY_GETREPLY 200000l /* 200000 * 2us */ +#define DELAY_SEEKREAD 20000l /* 20000 * 1us */ +#define matcd_delay DELAY + + + +/* Error classes returned by chk_error()*/ + +#define ERR_RETRY 1 /*A retry might recover this*/ +#define ERR_INIT 2 /*A retry almost certainly will get this*/ +#define ERR_FATAL 3 /*This cannot be recovered from*/ + + +struct buf request_head[NUMCTRLRS]; /*A queue for each host interface*/ + int nextcontroller=0; /*Number of interface units found*/ + int drivepresent=0; /*Don't change this - see license*/ +static struct matcd_mbx *mbxsave; + +unsigned char if_state[4]={0,0,0,0}; /*State of the host I/F and buss*/ + +/* Flags in the if_state array +*/ + +#define BUSSBUSY 0x01 /*Buss is already busy*/ + + + +struct matcd_read2 { + unsigned char start_msf[3]; + unsigned char end_msf[3]; +}; + +/*--------------------------------------------------------------------------- + These macros take apart the minor number and yield the + partition, drive on controller, and controller. + This must match the settings in /dev/MAKEDEV. +---------------------------------------------------------------------------*/ + +#define matcd_partition(dev) ((minor(dev)) & 0x07) +#define matcd_ldrive(dev) (((minor(dev)) & 0x78) >> 3) +#define matcd_cdrive(dev) (((minor(dev)) & 0x18) >> 3) +#define matcd_controller(dev) (((minor(dev)) & 0x60) >> 5) + + +#ifndef FREE2 +/*--------------------------------------------------------------------------- + This makes the long function names shorter for systems + using the older kernel config program +---------------------------------------------------------------------------*/ +#define matcdopen matopen /*<8>*/ +#define matcdclose matclose /*<8>*/ +#define matcdstrategy matstrategy /*<8>*/ +#define matcdioctl matioctl /*<8>*/ +#define matcdsize matsize /*<8>*/ +#define matcddriver matdriver /*<10>*/ +#endif /*FREE2*/ + + +/*--------------------------------------------------------------------------- + Entry points and other connections to/from kernel - see conf.c +---------------------------------------------------------------------------*/ + + int matcdopen(dev_t dev); + int matcdclose(dev_t dev); + void matcdstrategy(struct buf *bp); + int matcdioctl(dev_t dev, int command, caddr_t addr, int flags); + int matcdsize(dev_t dev); +extern int hz; +extern int matcd_probe(struct isa_device *dev); +extern int matcd_attach(struct isa_device *dev); +struct isa_driver matcddriver={matcd_probe, matcd_attach, + "matcd interface "}; + + +/*--------------------------------------------------------------------------- + Internal function declarations +---------------------------------------------------------------------------*/ + +static int matcd_getdisklabel(int ldrive); +static void matcd_start(struct buf *dp); +static void zero_cmd(char *); +static void matcd_pread(int port, int count, unsigned char * data); +static int matcd_fastcmd(int port,int ldrive,int cdrive, + unsigned char * cp); +static void matcd_slowcmd(int port,int ldrive,int cdrive, + unsigned char * cp); +static int matcd_getstat(int ldrive, int sflg); +static void matcd_setflags(int ldrive, struct matcd_data *cd); +static int msf2hsg(unsigned char *msf); +static void matcd_blockread(int state); +static int matcd_getreply(int ldrive, int dly); +static void selectdrive(int port,int drive); +static void doreset(int port,int cdrive); +static int doprobe(int port,int cdrive); +static void watchdog(int state, char * foo); +static void lockbuss(int controller, int ldrive); +static void unlockbuss(int controller, int ldrive); +static int matcd_volinfo(int ldrive); +static void draincmd(int port,int cdrive,int ldrive); +static int get_error(int port, int ldrive, int cdrive); +static int chk_error(int errnum); +static int msf_to_blk(unsigned char * cd); +#ifdef FULLDRIVER +static int matcd_playtracks(int ldrive, int cdrive, int controller, + struct ioc_play_track *pt); +static int matcd_playmsf(int ldrive, int cdrive, int controller, + struct ioc_play_msf *pt); +static int matcd_pause(int ldrive, int cdrive, int controller, + struct ioc_play_msf * addr,int action); +static int matcd_stop(int ldrive, int cdrive, int controller, + struct ioc_play_msf * addr); +#endif /*FULLDRIVER*/ + + +/*---------------------------------------------------------------------- + matcdopen - Open the device + + This routine actually gets called every time anybody opens + any partition on a drive. But the first call is the one that + does all the work. + + If you #define LOCKDRIVE, the drive eject button will be ignored + while any partition on the drive is open. +----------------------------------------------------------------------*/ +int matcdopen(dev_t dev) +{ + int cdrive,ldrive,partition,controller; + struct matcd_data *cd; + int i,z,port; + unsigned char cmd[MAXCMDSIZ]; + +#if DIAGPORT == 0x302 /*<10>*/ + DIAGOUT(0x300,0x00); /*<10>Init diag board in case some + other device probe scrambled it*/ +#endif /*<10>DIAGPORT*/ +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0x10); /*Show where we are*/ +#endif /*DIAGPORT*/ + ldrive=matcd_ldrive(dev); + cdrive=matcd_cdrive(dev); + partition=matcd_partition(dev); + controller=matcd_controller(dev); + cd= &matcd_data[ldrive]; + port=cd->iobase; /*and port#*/ + + if (ldrive >= TOTALDRIVES) return(ENXIO); + + +#ifdef DEBUGOPEN + printf("matcd%d: Open: dev %x partition %x controller %x flags %x cdrive %x\n", + ldrive,dev,partition,controller,cd->flags,matcd_cdrive(dev)); +#endif /*DEBUGOPEN*/ + + if (!(cd->flags & MATCDINIT)) { /*Did probe find this drive*/ + return(ENXIO); + } + + if (!(cd->flags & MATCDLABEL) && + cd->openflags) { /*Has drive completely closed?*/ + return(ENXIO); /*No, all partitions must close*/ + } + + +/* Now, test to see if the media is ready +*/ + + lockbuss(controller,ldrive); + zero_cmd(cmd); + cmd[0]=NOP; /*Test drive*/ + matcd_slowcmd(port,ldrive,cdrive,cmd); + i=waitforit(10*TICKRES,DTEN,port,"matcdopen"); + z=get_stat(port,ldrive); /*Read and toss status byte*/ + unlockbuss(controller, ldrive); /*Release buss lock*/ + if ((z & MATCD_ST_DSKIN)==0) { /*Is there a disc in the drive?*/ +#ifdef DEBUGOPEN + printf("matcd%d: No Disc in open\n",ldrive); +#endif /*DEBUGOPEN*/ + return(ENXIO); + } + if (z & MATCD_ST_ERROR) { /*Was there an error*/ + i=get_error(port,ldrive,cdrive); /*Find out what it was*/ + if (cd->openflags) { /*Any parts open?*/ + if (media_chk(cd,i,ldrive)) { /*Was it a disc chg?*/ +#ifdef DEBUGOPEN + printf("matcd%d: Disc change detected i %x z %x\n", + ldrive,i,z); +#endif /*DEBUGOPEN*/ + return(ENOTTY); + } + } + } + +/* Here we fill in the disklabel structure although most is + hardcoded. +*/ + + if ((cd->flags & MATCDLABEL)==0) { + bzero(&cd->dlabel,sizeof(struct disklabel)); + + +/* Now we query the drive for the actual size of the media. + This is where we find out of there is any media or if the + media isn't a Mode 1 or Mode 2/XA disc. + See version information about Mode 2/XA support. +*/ + lockbuss(controller,ldrive); + i=matcdsize(dev); + unlockbuss(controller, ldrive); /*Release buss lock*/ +#ifdef DEBUGOPEN + printf("matcd%d: Buss unlocked in open\n",ldrive); +#endif /*DEBUGOPEN*/ + if (i < 0) { + printf("matcd%d: Could not read the disc size\n",ldrive); + return(ENXIO); + } /*matcdsize filled in rest of dlabel*/ + +/* Based on the results, fill in the variable entries in the disklabel +*/ + cd->dlabel.d_secsize=cd->blksize; + cd->dlabel.d_ncylinders=(cd->disksize/100)+1; + cd->dlabel.d_secperunit=cd->disksize; + cd->dlabel.d_partitions[0].p_size=cd->disksize; + cd->dlabel.d_checksum=dkcksum(&cd->dlabel); + + +/* Now fill in the hardcoded section +*/ + /*123456789012345678*/ + strncpy(cd->dlabel.d_typename,"Matsushita CDR ",16); + strncpy(cd->dlabel.d_packname,"(c) 1994, fdiv ",16); + cd->dlabel.d_magic=DISKMAGIC; + cd->dlabel.d_magic2=DISKMAGIC; + cd->dlabel.d_nsectors=100; + cd->dlabel.d_secpercyl=100; + cd->dlabel.d_ntracks=1; + cd->dlabel.d_interleave=1; + cd->dlabel.d_rpm=300; + cd->dlabel.d_npartitions=1; /*See note below*/ + cd->dlabel.d_partitions[0].p_offset=0; + cd->dlabel.d_partitions[0].p_fstype=9; + cd->dlabel.d_flags=D_REMOVABLE; + +/* I originally considered allowing the partition match tracks or + sessions on the media, but since you are allowed up to 99 + tracks in the RedBook world, this would not fit in with the + BSD fixed partition count scheme. So ioctls are used to shift + the track to be accessed into partition 1. +*/ + + cd->flags |= MATCDLABEL; /*Mark drive as having TOC*/ + } + +#ifdef DEBUGOPEN + printf("matcd%d open2: partition=%d disksize=%d blksize=%x flags=%x\n", + ldrive,partition,cd->disksize,cd->blksize,cd->flags); +#endif /*DEBUGOPEN*/ + +#ifdef LOCKDRIVE + if (cd->openflags==0) { + lockbuss(controller,ldrive); + zero_cmd(cmd); + cmd[0]=LOCK; /*Lock drive*/ + cmd[1]=1; + matcd_slowcmd(port,ldrive,cdrive,cmd); + i=waitforit(10*TICKRES,DTEN,port,"matcdopen"); + z=get_stat(port,ldrive);/*Read and toss status byte*/ + unlockbuss(controller, ldrive); /*Release buss lock*/ + } +#endif /*LOCKDRIVE*/ + cd->openflags |= (1<<partition);/*Mark partition open*/ + + if (partition==RAW_PART || + (partition < cd->dlabel.d_npartitions && + cd->dlabel.d_partitions[partition].p_fstype != FS_UNUSED)) { + cd->partflags[partition] |= MATCDOPEN; + if (partition == RAW_PART) { + cd->partflags[partition] |= MATCDREADRAW; + } +#ifdef DEBUGOPEN + printf("matcd%d: Open is complete\n",ldrive); +#endif /*DEBUGOPEN*/ + return(0); + } +#ifdef DEBUGOPEN + printf("matcd%d: Open FAILED\n",ldrive); +#endif /*DEBUGOPEN*/ + return(ENXIO); +} + + +/*---------------------------------------------------------------------- + matcdclose - Close the device + + Depending on how you compiled the driver, close may not + do much other than clear some driver settings. + Note that audio playback will continue. + + If you did #define LOCKDRIVE, the drive was locked when the + matcdopen call is done. If we did that, then we unlock the + drive now. +----------------------------------------------------------------------*/ + +int matcdclose(dev_t dev) +{ + int ldrive,cdrive,port,partition,controller,i,z; + struct matcd_data *cd; + unsigned char cmd[MAXCMDSIZ]; + + ldrive = matcd_ldrive(dev); + cdrive=matcd_cdrive(dev); + cd=matcd_data + ldrive; + port=cd->iobase; /*and port#*/ + +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0x20); /*Show where we are*/ +#endif /*DIAGPORT*/ + if (ldrive >= TOTALDRIVES) + return(ENXIO); + + partition = matcd_partition(dev); + controller=matcd_controller(dev); +#ifdef DEBUGOPEN + printf("matcd%d: Close partition=%d\n", ldrive, partition); +#endif /*DEBUGOPEN*/ + + if (!(cd->flags & MATCDINIT)) + return(ENXIO); + + cd->partflags[partition] &= ~(MATCDOPEN|MATCDREADRAW); + cd->openflags &= ~(1<<partition); +#ifdef LOCKDRIVE + if (cd->openflags==0) { + lockbuss(controller,ldrive); + zero_cmd(cmd); + cmd[0]=LOCK; /*Unlock drive*/ + matcd_slowcmd(port,ldrive,cdrive,cmd); + i=waitforit(10*TICKRES,DTEN,port,"matcdopen"); + z=get_stat(port,ldrive);/*Read and toss status byte*/ + unlockbuss(controller, ldrive); /*Release buss lock*/ + } +#endif /*LOCKDRIVE*/ + cd->flags &= ~MATCDWARN; /*Clear any warning flag*/ + return(0); +} + + +/*---------------------------------------------------------------------- + matcdstrategy - Accepts I/O requests from kernel for processing + + This routine accepts a read request block pointer (historically + but somewhat inaccurately called *bp for buffer pointer). + Various sanity checks are performed on the request. + When we are happy with the request and the state of the device, + the request is added to the queue of requests for the controller + that the drive is connected to. We support multiple controllers + so there are multiple queues. Once the request is added, we + call the matcd_start routine to start the device in case it isn't + doing something already. All I/O including ioctl requests + rely on the current request starting the next one before exiting. +----------------------------------------------------------------------*/ + +void matcdstrategy(struct buf *bp) +{ + struct matcd_data *cd; + struct buf *dp; + int s; + int ldrive,controller; + +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0x30); /*Show where we are*/ +#endif /*DIAGPORT*/ + ldrive=matcd_ldrive(bp->b_dev); + controller=matcd_controller(bp->b_dev); + cd= &matcd_data[ldrive]; + +#ifdef DEBUGIO + printf("matcd%d: Strategy: buf=0x%lx, block#=%ld bcount=%ld\n", + ldrive,bp,bp->b_blkno,bp->b_bcount); +#endif /*DEBUGIO*/ + + + if (ldrive >= TOTALDRIVES || bp->b_blkno < 0) { + printf("matcd%d: Bogus parameters received - kernel may be corrupted\n",ldrive); + bp->b_error=EINVAL; + bp->b_flags|=B_ERROR; + goto bad; + } + + if (!(cd->flags & MATCDLABEL)) { + bp->b_error = EIO; + goto bad; + } + + if (!(bp->b_flags & B_READ)) { + bp->b_error = EROFS; + goto bad; + } + + if (bp->b_bcount==0) /*Request is zero-length - all done*/ + goto done; + + if (matcd_partition(bp->b_dev) != RAW_PART) { + if (!(cd->flags & MATCDLABEL)) { + bp->b_error = EIO; + goto bad; + } + if (bounds_check_with_label(bp,&cd->dlabel,1) <= 0) { + goto done; + } + } else { + bp->b_pblkno=bp->b_blkno; + bp->b_resid=0; + } + + s=splbio(); /*Make sure we don't get intr'ed*/ + dp=&request_head[controller]; /*Pointer to controller queue*/ + disksort(dp,bp); /*Add new request (bp) to queue (dp + and sort the requests in a way that + may not be ideal for CD-ROM media*/ + +#ifdef DEBUGQUEUE + printf("matcd%d: Dump BP chain: -------\n",ldrive); + while (bp) { + printf("Block %d\n",bp->b_pblkno); +#ifdef FREE2 + bp=bp->b_actf; +#else /*FREE2*/ + bp=bp->av_forw; +#endif /*FREE2*/ + } + printf("matcd%d: ---------------------\n",ldrive); +#endif /*DEBUGQUEUE*/ + + matcd_start(dp); /*Ok, with our newly sorted queue, + see if we can start an I/O operation + right now*/ + splx(s); /*Return priorities to normal*/ + return; /*All done*/ + +bad: bp->b_flags |= B_ERROR; /*Request bad in some way*/ +done: bp->b_resid = bp->b_bcount; /*Show un read amount*/ + biodone(bp); /*Signal we have done all we plan to*/ + return; +} + + +/*---------------------------------------------------------------------- + matcd_start - Pull a request from the queue and consider doing it. +----------------------------------------------------------------------*/ + +static void matcd_start(struct buf *dp) +{ + struct matcd_data *cd; + struct buf *bp; + struct partition *p; + int part,ldrive,controller; + register s; + +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0x40); /*Show where we are*/ + diagloop=0; +#endif /*DIAGPORT*/ + if ((bp=dp->b_actf) == NULL) { /*Nothing on read queue to do?*/ + wakeup((caddr_t)&matcd_data->status); /*Wakeup any blocked*/ + return; /* opens, ioctls, etc*/ + } + + ldrive=matcd_ldrive(bp->b_dev); /*Get logical drive#*/ + cd=&matcd_data[ldrive]; /*Get pointer to data for this drive*/ + controller=matcd_controller(bp->b_dev); /*Also get interface #*/ +#ifdef DEBUGIO + printf("matcd%d: In start controller %d\n",ldrive,controller); +#endif /*DEBUGIO*/ + + if (if_state[controller] & BUSSBUSY) { +#ifdef DEBUGIO + printf("matcd%d: Dropping thread in start, controller %d\n", + ldrive,controller); +#endif /*DEBUGIO*/ + return; + } + +#ifdef FREE2 + dp->b_actf = bp->b_actf; +#else /*FREE2*/ + dp->b_actf = bp->av_forw; /*Get next request from queue*/ +#endif /*FREE2*/ + + part=matcd_partition(bp->b_dev); + p=cd->dlabel.d_partitions + part; + + if_state[controller] |= BUSSBUSY;/*Mark buss as busy*/ + cd->mbx.ldrive=ldrive; /*Save current logical drive*/ + cd->mbx.controller=controller; /*and controller*/ + cd->mbx.partition=part; /*and partition (2048 vs 2532)*/ + cd->mbx.port=cd->iobase; /*and port#*/ + cd->mbx.retry=MATCD_RETRYS; /*and the retry count*/ + cd->mbx.bp=bp; /*and the bp*/ + cd->mbx.p_offset=p->p_offset; /*and where the data will go*/ + matcd_blockread(MATCD_READ_1+ldrive); /*Actually start the read*/ + return; /*Dropping thread. matcd_blockread + must have scheduled a timeout or + we will go to sleep forever*/ +} + + +/*---------------------------------------------------------------------- + matcdioctl - Process things that aren't block reads + + In this driver, ioctls are used mainly to change + the mode the drive is running in, play audio and other + things that don't fit into the block read scheme of things. +----------------------------------------------------------------------*/ + +int matcdioctl(dev_t dev, int command, caddr_t addr, int flags) +{ + struct matcd_data *cd; + int ldrive,cdrive,partition; + int i,z; + unsigned char * p; + int port, controller; + unsigned char zz; + +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0x50); /*Show where we are*/ +#endif /*DIAGPORT*/ + ldrive=matcd_ldrive(dev); + cdrive=matcd_cdrive(dev); + partition=matcd_partition(dev); + controller=ldrive>>2; + cd = &matcd_data[ldrive]; + port=cd->iobase; + +#ifdef DEBUGIOCTL + printf("matcd%d: ioctl %x cdrive %x parms ",ldrive,command,cdrive); + for (i=0;i<10;i++) { + zz=addr[i]; + printf("%02x ",zz); + } + printf(" flags %x\n",cd->flags); +#endif /*DEBUGIOCTL*/ + + if (!(cd->flags & MATCDLABEL)) /*Did we read TOC OK?*/ + return(EIO); + + switch(command) { + case DIOCSBAD: /*<9>*/ + return(EINVAL); /*<9>*/ + case DIOCGDINFO: /*<9>*/ + *(struct disklabel *) addr = cd->dlabel; /*<9>*/ + return(0); /*<9>*/ + case DIOCGPART: /*<9>*/ + ((struct partinfo *) addr)->disklab=&cd->dlabel;/*<9>*/ + ((struct partinfo *) addr)->part= /*<9>*/ + &cd->dlabel.d_partitions[matcd_partition(dev)];/*<9>*/ + return(0); /*<9>*/ + case DIOCWDINFO: /*<9>*/ + case DIOCSDINFO: /*<9>*/ +#ifdef FREE2 /*<10>*/ + if ((flags & FWRITE) == 0) { /*<9>*/ + return(EBADF); /*<9>*/ + } /*<9>*/ + else { /*<9>*/ + return setdisklabel(&cd->dlabel, /*<9>*/ + (struct disklabel *) addr, 0);/*<9>*/ + } /*<9>*/ +#endif /*<10>FREE2*/ + case DIOCWLABEL: /*<9>*/ + return(EBADF); /*<9>*/ + case CDIOCEJECT: + return(matcd_eject(ldrive, cdrive, controller)); +#ifdef FULLDRIVER + case CDIOCPLAYTRACKS: + return(matcd_playtracks(ldrive, cdrive, controller, + (struct ioc_play_track *) addr)); + case CDIOCPLAYMSF: + return(matcd_playmsf(ldrive, cdrive, controller, + (struct ioc_play_msf *) addr)); + case CDIOCRESUME: + return(matcd_pause(ldrive, cdrive, controller, + (struct ioc_play_msf *) addr,RESUME)); + case CDIOCPAUSE: + return(matcd_pause(ldrive, cdrive, controller, + (struct ioc_play_msf *) addr,0)); + case CDIOCSTOP: + return(matcd_stop(ldrive, cdrive, controller, + (struct ioc_play_msf *) addr)); + + case CDIOCGETVOL: + case CDIOCSETVOL: + case CDIOCSETMONO: + case CDIOCSETSTERIO: + case CDIOCSETMUTE: + case CDIOCSETLEFT: + case CDIOCSETRIGHT: +#endif /*FULLDRIVER*/ + + case CDIOCREADSUBCHANNEL: + case CDIOREADTOCHEADER: + case CDIOREADTOCENTRYS: + + case CDIOCSETPATCH: + case CDIOCSTART: + case CDIOCRESET: + return(EINVAL); + default: + return(ENOTTY); + } +} + +/*---------------------------------------------------------------------- + matcdsize - Reports how many blocks exist on the disc. +----------------------------------------------------------------------*/ + +int matcdsize(dev_t dev) +{ + int size,blksize; + int ldrive,part; + struct matcd_data *cd; + + ldrive=matcd_ldrive(dev); + part=matcd_partition(dev); + if (part==RAW_PART) + blksize=MATCDRBLK; /*2353*/ + else + blksize=MATCDBLK; /*2048*/ + + cd = &matcd_data[ldrive]; + + if (matcd_volinfo(ldrive) >= 0) { + cd->blksize=blksize; + size=msf_to_blk((char * )&cd->volinfo.vol_msf); + + cd->disksize=size*(blksize/DEV_BSIZE); +#ifdef DEBUGOPEN + printf("matcd%d: Media size %d\n",ldrive,size); +#endif /*DEBUGOPEN*/ + return(0); + } + return(-1); +} + +/*---------------------------------------------------------------------- + matcd_probe - Search for host interface/adapters + + The probe routine hunts for the first drive on the interface since + there is no way to locate just the adapter. It also resets the + entire drive chain while it is there. matcd_attach() takes care of + the rest of the initialization. + + The probe routine can be compiled two ways. In AUTOHUNT mode, + the kernel config file can say "port?" and we will check all ports + listed in the port_hint array (see above). + + Without AUTOHUNT set, the config file must list a specific port + address to check. + + Note that specifying the explicit addresses makes boot-up a lot + faster. + + The probe will locate Panasonic/Creative interface on the following + Creative adapter boards: + #1730 Sound Blaster 16 + #1740 Sound Blaster 16 (cost reduced) + #1810 omniCD upgrade kit adapter card (stand-alone CD) + #3100 PhoneBlaster SB16 + Sierra 14.4K modem combo + Creative releases a newer and cheaper-to-make Sound Blaster + board every few months, so by the original release date of this + software, there are probably 8 different board models called + Sound Blaster 16. These include "Vibra", "Value", etc. + + Please report additional part numbers and board descriptions + and new port numbers that work to the author. + +----------------------------------------------------------------------*/ + +int matcd_probe(struct isa_device *dev) +{ + int i,cdrive; + unsigned char y,z,drive; + int level; + int port = dev->id_iobase; /*Take port hint from config file*/ + cdrive=nextcontroller; /*Controller defined by pass for now*/ + +#if DIAGPORT == 0x302 /*<10>*/ + DIAGOUT(0x300,0x00); /*<10>Init diag board in case some + other device probe scrambled it*/ +#endif /*<10>DIAGPORT*/ +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0x60); /*Show where we are*/ +#endif /*DIAGPORT*/ + if (nextcontroller==NUMCTRLRS) { + printf("matcdc%d: - Too many interfaces specified in config\n", + nextcontroller); + return(0); + } + if (nextcontroller==0) { /*Very first time to be called*/ + for (i=0; i<TOTALDRIVES; i++) { + matcd_data[i].drivemode=MODE_UNKNOWN; + matcd_data[i].flags=0; + } + } + + i=nextcontroller*DRIVESPERC; /*Precompute controller offset*/ + for (y=0; y<DRIVESPERC; y++) { + matcd_data[i+y].flags=0; + matcd_data[i+y].config=0; + } + +#ifdef DEBUGPROBE + printf("matcdc%d: In probe i %d y %d port %x\n", + nextcontroller,i,y,port); +#endif /*DEBUGPROBE*/ +#ifdef AUTOHUNT +#ifdef DEBUGPROBE + printf("matcd%d: size of port_hints %d\n", + nextcontroller,sizeof(port_hints)); +#endif /*DEBUGPROBE*/ + if (port==-1) { + for(i=0;i<(sizeof(port_hints)/sizeof(short));i++) { + port=port_hints[i]; +#ifdef DEBUGPROBE + printf("matcdc%d: Port hint %x\n",nextcontroller,port); +#endif /*DEBUGPROBE*/ + if (port==-1) { + dev->id_iobase=-1; /*Put port ? back*/ + return(0);/*Nothing left to try*/ + } + if (port!=0) { /*Unused port found*/ + dev->id_iobase=port; + port_hints[i]=0;/*Don't use that port again*/ + if (doprobe(port,cdrive)==0) return(NUMPORTS); + } + } + dev->id_iobase=-1; /*Put port ? back as it was*/ + return(0); /*Interface not found*/ + + } else { /*Config specified a port*/ + i=0; /*so eliminate it from the hint list*/ + for(i=0;;i++) { /*or we might try to assign it again*/ + if (port_hints[i]== -1) break; /*End of list*/ + if (port_hints[i]==port) { + port_hints[i]=0; /*Clear duplicate*/ + break; + } + } + if (doprobe(port,cdrive)==0) return(NUMPORTS); + else return(0); + } +#else /*AUTOHUNT*/ + if (port==-1) { + printf("matcd%d: AUTOHUNT disabled but port? specified in config\n", + nextcontroller); + return(0); + } + if (doprobe(port,cdrive)==0) return(NUMPORTS); + else return(0); +#endif /*AUTOHUNT*/ +} + +/*---------------------------------------------------------------------- + doprobe - Common probe code that actually checks the ports we + have decided to test. +----------------------------------------------------------------------*/ + +int doprobe(int port,int cdrive) +{ + unsigned char cmd[MAXCMDSIZ]; + +#ifdef RESETONBOOT + doreset(port,cdrive); /*Reset what might be our device*/ +#endif /*RESETONBOOT*/ + + zero_cmd(cmd); + cmd[0]=NOP; /*A reasonably harmless command. + This command will fail after + power-up or after reset. That's OK*/ + if (matcd_fastcmd(port,0,0,cmd)==0) {/*Issue command*/ + inb(port+CMD); /*Read status byte*/ +#ifdef DEBUGPROBE + printf("matcdc%d: Probe found something\n",nextcontroller); +#endif /*DEBUGPROBE*/ + if (drivepresent==0) { /*Don't change this - see license*/ + printf("matcd - Matsushita (Panasonic) CD-ROM Driver by FDIV, %s\n",MATCDVERSION); + /*Don't change this - see license*/ + drivepresent++; /*Don't change this - see license*/ + } /*Don't change this - see license*/ + return(0); /*Drive 0 detected*/ + } +#ifdef DEBUGPROBE + printf("matcdc%d: Probe DID NOT find something\n",nextcontroller); +#endif /*DEBUGPROBE*/ + return(1); /*Nothing detected*/ +} + + +/*---------------------------------------------------------------------- + matcd_attach - Locates drives on the adapters that were located. + If we got here, we located a interface and at least one + drive. Now we figure out how many drives are under that + interface. The Panasonic interface is too simple to call + it a controller, but in the existing PDP model, that is + what it would be. +----------------------------------------------------------------------*/ + +int matcd_attach(struct isa_device *dev) +{ + int i; + unsigned char y,z,cdrive; + int level; + unsigned char cmd[MAXCMDSIZ]; + unsigned char data[12]; + struct matcd_data *cd; + int port = dev->id_iobase; /*Take port ID selected in probe()*/ + +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0x70); /*Show where we are*/ +#endif /*DIAGPORT*/ +#ifdef DEBUGPROBE + printf("matcdc: Attach dev %x id_unit %d\n",dev,dev->id_unit); +#endif /*DEBUGPROBE*/ + for (cdrive=0; cdrive<4; cdrive++) { /*We're hunting drives...*/ + zero_cmd(cmd); + cmd[0]=NOP; /*A reasonably harmless command. + This command will fail after + power-up or after reset. It's OK*/ + i=cdrive+(DRIVESPERC*nextcontroller); + if (matcd_fastcmd(port,i,cdrive,cmd)==0) { /*Issue command*/ + z=get_stat(port,cdrive);/*Read and toss status byte*/ + if ((z & MATCD_ST_ERROR)) { /*If there was an error, + we must ask for error info + or subsequent cmds fail*/ + zero_cmd(cmd); + cmd[0]=READERROR; /*Inquire*/ + matcd_fastcmd(port,i,cdrive,cmd); + matcd_pread(port,8,data);/*Read data returned*/ + z=get_stat(port,i);/*Read and toss status byte*/ +#ifdef DEBUGPROBE + printf("matcd%d: Status byte %x ",i,z); +#endif /*DEBUGPROBE*/ + } + zero_cmd(cmd); + cmd[0]=READID; /*Get drive ID*/ + matcd_fastcmd(port,i,cdrive,cmd); + matcd_pread(port,10,data);/*Read Drive Parm*/ + z=get_stat(port,i); /*Read and toss status byte*/ + data[10]=0; /*Build ASCIZ string*/ + printf("matcd%d: [%s] ",i,data); + cd=&matcd_data[i]; + cd->flags |= MATCDINIT; + cd->iobase=dev->id_iobase; + cd->openflags=0; + for (i=0; i<MAXPARTITIONS; i++) { + cd->partflags[i]=0; + } + } + } + nextcontroller++; /*Bump ctlr assign to next number*/ + printf("\n"); /*End line of drive reports*/ + return(1); +} + + +/*---------------------------------------------------------------------- + zero_cmd - Initialize command buffer +----------------------------------------------------------------------*/ + +void zero_cmd(char * lcmd) +{ + int i; + for (i=0; i<MAXCMDSIZ; lcmd[i++]=0); + return; +} + + +/*---------------------------------------------------------------------- + doreset - Resets all the drives connected to a interface +----------------------------------------------------------------------*/ + +void doreset(int port,int cdrive) +{ + register int i,z; +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0x80); /*Show where we are*/ +#endif /*DIAGPORT*/ + outb(port+RESET,0); /*Reset what might be our device*/ + /*Although this ensures a known + state, it does close the drive + door (if open) and aborts any + audio playback in progress. */ + for (i=0;i<(125*ISABUSKHZ);i++){/*DELAY 500msec minimum. Worst + case is door open and none or + unreadable media */ + z=inb(port+CMD); /*This makes the loop run at a + known speed. This value is ok + for 8.33MHz bus*/ + } + for (i=0;i<4;i++) { + matcd_data[(cdrive*4)+i].drivemode=MODE_UNKNOWN; + } + return; +} + + +/*---------------------------------------------------------------------- + matcd_fastcmd - Send a command to a drive + + This routine executed commands that return instantly (or reasonably + quick), such as RESET, NOP, READ ERROR, etc. The only difference + between it and handling for slower commands, is the slower commands + will invoke a timeout/sleep if they don't get an instant response. + + Fastcmd is mainly used in probe(), attach() and error related + functions. Every attempt should be made to NOT use this + function for any command that might be executed when the system + is up. +----------------------------------------------------------------------*/ + +int matcd_fastcmd(int port,int ldrive,int cdrive,unsigned char * cp) +{ + unsigned int i; + unsigned char z; + int level; +#ifdef DEBUGCMD + unsigned char *cx; +#endif /*DEBUGCMD*/ + +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0x90); /*Show where we are*/ +#endif /*DIAGPORT*/ + + + draincmd(port,cdrive,ldrive); /*Make sure buss is really idle*/ +#ifdef DEBUGCMD + cx=cp; + printf("matcd%d: Fast Send port %x sel %d command %x %x %x %x %x %x %x\n", + ldrive,port,cdrive,cx[0],cx[1],cx[2],cx[3],cx[4],cx[5],cx[6]); +#endif /*DEBUGCMD*/ + selectdrive(port,cdrive); /*Enable the desired target drive*/ + level=splhigh(); /*----------------------------------------*/ + for (i=0; i<7; i++) { /*The seven bytes of the command*/ + outb(port+CMD,*cp++); /*must be sent within 10msec or*/ + } /*the drive will ignore the cmd*/ + splx(level); /*------------------------------------------------*/ + +/* Now we wait a maximum of 240msec for a response. + Only in a few rare cases does it take this long. + If it is longer, the command should probably be slept on + rather than increasing the timing value +*/ + + for (i=0; i<(60*ISABUSKHZ); i++) { + z = (inb(port+STATUS)) & (DTEN|STEN); + if (z != (DTEN|STEN)) break; + } + +/* We are now either in a data or status phase, OR we timed-out.*/ + + if (z == (DTEN|STEN)) { +#ifdef DEBUGCMD + printf("matcd%d: Command time-out\n",ldrive); +#endif /*DEBUGCMD*/ + return(-1); + } + if (z != DTEN) { + return(1); + } + return(0); +} + + +/*---------------------------------------------------------------------- + matcd_slowcmd - Issue a command to the drive + + This routine is for commands that might take a long time, such + as a read or seek. The caller must determine if the command + completes instantly or schedule a poll later on. +----------------------------------------------------------------------*/ + +void matcd_slowcmd(int port,int ldrive,int cdrive,unsigned char * cp) +{ + unsigned int i; + unsigned char z; + int level,size; +#ifdef DEBUGCMD + unsigned char *cx; +#endif /*DEBUGCMD*/ + +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xa0); /*Show where we are*/ +#endif /*DIAGPORT*/ + + draincmd(port,cdrive,ldrive); /*Make sure buss is really idle*/ + +#ifdef DEBUGCMD + cx=cp; + printf("matcd%d: Slow Send port %x sel %d command %x %x %x %x %x %x %x\n", + ldrive,port,cdrive,cx[0],cx[1],cx[2],cx[3],cx[4],cx[5],cx[6]); +#endif /*DEBUGCMD*/ + selectdrive(port,cdrive); /*Enable the desired target drive*/ + if (*cp==ABORT) size=1; + else size=7; + level=splhigh(); /*----------------------------------------*/ + for (i=0; i<size; i++) { /*The seven bytes of the command*/ + outb(port+CMD,*cp++); /*must be sent within 10msec or*/ + } /*the drive will ignore the cmd*/ + splx(level); /*------------------------------------------------*/ + return; +} + + +/*---------------------------------------------------------------------- + draincmd - Makes certain the buss is idle and throws away + any residual data from the drive if there is any. + Called as preface to most commands. + Added in Edit 5. + + This was added because switching drive modes causes + the drive to emit buffers that were meant to be sent + to the D-to-A to be sent to the host. See setmode. +----------------------------------------------------------------------*/ +void draincmd(int port,int cdrive,int ldrive) +{ + int i,z; + + i=inb(port+STATUS); + if (i==0xff) return; + + printf("matcd%d: in draincmd: buss not idle %x - trying to fix\n", + ldrive,inb(port+STATUS)); + if ((i & DTEN|STEN) == STEN) { +#ifdef DEBUGCMD + printf("matcd%d: Data present READING - ",ldrive); +#endif /*DEBUGCMD*/ + i=0; + outb(port+STATUS,1); /*Enable data read*/ + while ((inb(port+STATUS) & (DTEN|STEN)) == STEN) { + inb(port+DATA); + i++; + } + outb(port+STATUS,0); +#ifdef DEBUGCMD + printf("%d bytes read\n",i); +#endif /*DEBUGCMD*/ + } +#ifdef DEBUGCMD + printf("matcd%d: Now read status: ",ldrive); +#endif /*DEBUGCMD*/ + i=get_stat(port,ldrive); /*Read and toss status byte*/ + z=inb(port+STATUS); /*Read buss status*/ +#ifdef DEBUGCMD + printf("Data byte %x and status is now %x\n",i,z); +#endif /*DEBUGCMD*/ + if (z!=0xff) { + printf("matcd%d: Buss not idle %x - resetting\n", + cdrive,inb(port+STATUS)); + doreset(port,cdrive); + } + return; +} + + +/*---------------------------------------------------------------------- + selectdrive - Swaps drive select bits + + On Creative SB/SB16/stand-alone adapters, possibly to make them + to reverse engineer. On these boards, the drive select signals + are swapped. +----------------------------------------------------------------------*/ + +void selectdrive(int port,int drive) +{ + switch(drive) { + case 0: /*0x00 -> 0x00*/ + outb(port+SELECT,CRDRIVE0); + break; + case 1: /*0x01 -> 0x02*/ + outb(port+SELECT,CRDRIVE1); + break; + case 2: /*0x02 -> 0x01*/ + outb(port+SELECT,CRDRIVE2); + break; + case 3: /*0x03 -> 0x03*/ + outb(port+SELECT,CRDRIVE3); + break; + } + return; +} + + +/*---------------------------------------------------------------------- + matcd_pread - Read small blocks of control data from a drive +----------------------------------------------------------------------*/ + +void matcd_pread(int port, int count, unsigned char * data) +{ + int i; + + for (i=0; i<count; i++) { + *data++ = inb(port+CMD); + } + return; +} + + +/*---------------------------------------------------------------------- + matcd_setmode - Configures disc to run in the desired data mode + + This routine assumes the drive is already idle. + +NOTE - Undocumented action of hardware: If you change (or reaffirm) data + modes with MODESELECT + BLOCKPARAM immediately after a command was + issued that aborted a DA play operation, the drive will unexpectedly + return 2532 bytes of data in a data phase on the first or second + subsequent command. + + Original Symptom: drive will refuse to go idle after reading data + and status expected for a command. State mechanics for this are + not fully understood. +----------------------------------------------------------------------*/ + +int matcd_setmode(int ldrive, int mode) +{ + struct matcd_data *cd; + int retries; + int i,z,port,cdrive; + unsigned char cmd[MAXCMDSIZ]; + + cd = matcd_data + ldrive; + retries=3; + cdrive=ldrive&0x03; + port=cd->iobase; + if (cd->drivemode==mode) { + return(0); /*Drive already set*/ + } + +/* The drive is not in the right mode, so we need to set it. +*/ + + zero_cmd(cmd); + cmd[0]=MODESELECT; /*Set drive transfer modes*/ +/* cmd[1]=BLOCKPARAM; BLOCKPARAM==0*/ + cmd[2]=mode; + switch(mode) { + case MODE_DATA: + cmd[3]=0x08; /*2048 bytes*/ + break; + case MODE_USER: + cmd[3]=0x09; /*2352 bytes*/ + cmd[4]=0x30; + break; + case MODE_DA: + cmd[3]=0x09; /*2352 bytes*/ + cmd[4]=0x30; + break; + } + i=0; + while(retries-- > 0) { + i=matcd_fastcmd(port,ldrive,cdrive,cmd); + z=get_stat(port,ldrive);/*Read and toss status byte*/ + if (i==0) { + cd->drivemode=mode; /*Set new mode*/ + return(i); + } + get_error(port,ldrive,cdrive); + } + cd->drivemode=MODE_UNKNOWN; /*We failed*/ + return(i); +} + + +/*---------------------------------------------------------------------- + matcd_volinfo - Read information from disc Table of Contents +----------------------------------------------------------------------*/ + +static int matcd_volinfo(int ldrive) +{ + struct matcd_data *cd; + int port,i; + int z,cdrive; + int retry; + unsigned char cmd[MAXCMDSIZ]; + unsigned char data[12]; + + retry=5; + cd = &matcd_data[ldrive]; + cdrive=ldrive&0x03; + port=cd->iobase; + +#ifdef DEBUGOPEN + printf("matcd%d: In volinfo, port %x\n",ldrive,port); +#endif /*DEBUGOPEN*/ + + while(retry>0) { +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xB0); /*Show where we are*/ +#endif /*DIAGPORT*/ + zero_cmd(cmd); + cmd[0]=READDINFO; /*Read Disc Info*/ + matcd_slowcmd(port,ldrive,cdrive,cmd); + i=waitforit(10*TICKRES,DTEN,port,"volinfo"); + if (i) { /*THIS SHOULD NOT HAPPEN*/ + z=get_stat(port,ldrive);/*Read and toss status byte*/ + printf("matcd%d: command failed, status %x\n", + ldrive,z); + return(-1); + } + matcd_pread(port, 6, data); /*Read data returned*/ + z=get_stat(port,ldrive);/*Read and toss status byte*/ +#ifdef DEBUGOPEN + printf("matcd%d: Data got was %x %x %x %x %x %x ",ldrive, + data[0],data[1],data[2], data[3],data[4],data[5]); + printf("status byte %x\n",z); +#endif /*DEBUGOPEN*/ + if ((z & MATCD_ST_ERROR)==0) + break; /*No Error*/ + +/* If media change or other error, you have to read error data or + the drive will reject subsequent commands. +*/ + + if (chk_error(get_error(port, ldrive, cdrive))==ERR_FATAL) { +#ifdef DEBUGOPEN + printf("matcd%d: command failed, status %x\n", + ldrive,z); +#endif /*DEBUGOPEN*/ + return(-1); + } + if ((--retry)==0) return(-1); +#ifdef DEBUGOPEN + printf("matcd%d: Retrying",ldrive); +#endif /*DEBUGOPEN*/ + } +#ifdef DEBUGOPEN + printf("matcd%d: Status port %x \n",ldrive,inb(port+STATUS)); +#endif /*DEBUGOPEN*/ + + cd->volinfo.type=data[0]; + cd->volinfo.trk_high=data[2]; + cd->volinfo.trk_low=data[1]; + cd->volinfo.vol_msf[0]=data[3]; + cd->volinfo.vol_msf[1]=data[4]; + cd->volinfo.vol_msf[2]=data[5]; + + if (cd->volinfo.trk_low + cd->volinfo.trk_high) { + cd->flags |= MATCDLABEL; + return(0); + } + return(-1); +} + + +/*---------------------------------------------------------------------- + blk_to_msf - Convert block numbers into CD disk block ids +----------------------------------------------------------------------*/ + +static void blk_to_msf(int blk, unsigned char *msf) +{ + blk += 150; /*2 seconds skip required to + reach ISO data*/ + msf[0] = blk/4500; + blk %= 4500; + msf[1] = blk / 75; + msf[2] = blk % 75; + return; +} + + +/*---------------------------------------------------------------------- + msf_to_blk - Convert CD disk block ids into block numbers +----------------------------------------------------------------------*/ + +static int msf_to_blk(unsigned char * cd) +{ + return(((cd[0]*60) /*Convert MSF to*/ + +cd[1])*75 /*Blocks minus 2*/ + +cd[2]-150); /*seconds*/ +} + + +/*---------------------------------------------------------------------- + matcd_blockread - Performs actual background disc I/O operations + + This routine is handed the block number to read, issues the + command to the drive, waits for it to complete, reads the + data or error, retries if needed, and returns the results + to the host. +----------------------------------------------------------------------*/ + +static void matcd_blockread(int state) +{ + struct matcd_mbx *mbx; + int ldrive,cdrive; + int port; + struct buf *bp; + struct buf *dp; + struct matcd_data *cd; + int i,k,z; + int l,m; + struct matcd_read2 rbuf; + int blknum; + caddr_t addr; + int status; + int errtyp; + int phase; + unsigned char cmd[MAXCMDSIZ]; + +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xC0 + (diagloop * 0x100));/*Show where we are*/ +#endif /*DIAGPORT*/ + mbx = &matcd_data[state & 0x0f].mbx; + ldrive=mbx->ldrive; /*ldrive is logical drive #*/ + cdrive=ldrive & 0x03; /*cdrive is drive # on a controller*/ + port=mbx->port; /*port is base port for i/f*/ + bp= mbx->bp; + cd=&matcd_data[ldrive]; + + dp=&request_head[mbx->controller]; + +#ifdef DEBUGIO + printf("matcd%d: Show state %x cdrive %d partition %d\n", + ldrive,state,cdrive,mbx->partition); +#endif /*DEBUGIO*/ + +loop: +#ifdef DEBUGIO + printf("matcd%d: Top dp %x\n",ldrive,dp); +#endif /*DEBUGIO*/ +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xCF + (diagloop * 0x100));/*Show where we are*/ +#endif /*DIAGPORT*/ + switch (state & 0xf0) { + case MATCD_READ_1: +#ifdef DEBUGIO + printf("matcd%d: State 1 cd->flags %x\n",ldrive,cd->flags); +#endif /*DEBUGIO*/ +#ifdef DIAGPORT + diagloop=0; + DIAGOUT(DIAGPORT,0xC1); /*Show where we are*/ +#endif /*DIAGPORT*/ + /* to check for raw/cooked mode */ + if (cd->partflags[mbx->partition] & MATCDREADRAW) { + mbx->sz = MATCDRBLK; + i=matcd_setmode(ldrive, MODE_DA); +#ifdef DEBUGIO + printf("matcd%d: Set MODE_DA result %d\n",ldrive,i); +#endif /*DEBUGIO*/ + } else { + mbx->sz = cd->blksize; + i=matcd_setmode(ldrive, MODE_DATA); +#ifdef DEBUGIO + printf("matcd%d: Set MODE_DATA result %d\n",ldrive,i); +#endif /*DEBUGIO*/ + } + /*for first block*/ +#ifdef DEBUGIO + printf("matcd%d: A mbx %x bp %x b_bcount %x sz %x\n", + ldrive,mbx,bp,bp->b_bcount,mbx->sz); +#endif /*DEBUGIO*/ + mbx->nblk = (bp->b_bcount + (mbx->sz-1)) / mbx->sz; + mbx->skip=0; +nextblock: +#ifdef DEBUGIO + printf("matcd%d: at Nextblock b_blkno %d\n", + ldrive,bp->b_blkno); +#endif /*DEBUGIO*/ + + blknum=(bp->b_blkno / (mbx->sz/DEV_BSIZE)) + + mbx->p_offset + mbx->skip/mbx->sz; + + blk_to_msf(blknum,rbuf.start_msf); + + zero_cmd(cmd); + cmd[0]=READ; /*Get drive ID*/ + cmd[1]=rbuf.start_msf[0]; + cmd[2]=rbuf.start_msf[1]; + cmd[3]=rbuf.start_msf[2]; + cmd[6]=1; + matcd_slowcmd(port,ldrive,cdrive,cmd); + +/* Now that we have issued the command, check immediately to + see if data is ready. The drive has read-ahead caching, so + it is possible the data is already in the drive buffer. + + If the data is not ready, schedule a wakeup and later on this + code will run again to see if the data is ready then. +*/ + + case MATCD_READ_2: + state=MATCD_READ_2+ldrive; + phase = (inb(port+STATUS)) & (DTEN|STEN); +#ifdef DEBUGIO + printf("matcd%d: In state 2 status %x ",ldrive,phase); +#endif /*DEBUGIO*/ +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xC2 + (diagloop++ * 0x100));/*Show where we are*/ +#endif /*DIAGPORT*/ + switch(phase) { + case (DTEN|STEN): /*DTEN==H STEN==H*/ +#ifdef DEBUGIO + printf("matcd%d: Sleeping\n",ldrive); +#endif /*DEBUGIO*/ + timeout((timeout_func_t)matcd_blockread, + (caddr_t)MATCD_READ_2+ldrive,hz/100); + return; + + + case STEN: /*DTEN=L STEN=H*/ + case 0: /*DTEN=L STEN=L*/ +#ifdef DEBUGIO + printf("matcd%d: Data Phase\n",ldrive); +#endif /*DEBUGIO*/ + outb(port+STATUS,1); /*Enable data read*/ + addr=bp->b_un.b_addr + mbx->skip; +#ifdef DEBUGIO + printf("matcd%d: Xfer Addr %x size %x", + ldrive,addr,mbx->sz); +#endif /*DEBUGIO*/ + i=0; + while(inb(port+STATUS)==0xfd) { + *addr++=inb(port+DATA); + i++; + } +#ifdef DEBUGIO + printf("matcd%d: Read %d bytes\n",ldrive,i); +#endif /*DEBUGIO*/ + outb(port+STATUS,0); /*Disable data read*/ + + +/* Now, wait for the Status phase to arrive. This will also + tell us if any went wrong with the request. +*/ + while((inb(port+STATUS)&(DTEN|STEN)) != DTEN); + status=get_stat(port,ldrive); /*Read and toss status byte*/ +#ifdef DEBUGIO + printf("matcd%d: Status port %x byte %x ", + ldrive,i,status); +#endif /*DEBUGIO*/ + if (status & MATCD_ST_ERROR) { + i=get_error(port,ldrive,cdrive); + printf("matcd%d: %s while reading block %d [Soft]\n", + ldrive,matcderrors[i],bp->b_blkno); + } + media_chk(cd,i,ldrive); + + if (--mbx->nblk > 0) { + mbx->skip += mbx->sz; + goto nextblock; /*Oooooh, you flunk the course*/ + } + bp->b_resid=0; + biodone(bp); + + unlockbuss(ldrive>>2, ldrive); /*Release buss lock*/ + matcd_start(dp); + return; + +/* Here we skipped the data phase and went directly to status. + This indicates a hard error. +*/ + + case DTEN: /*DTEN=H STEN=L*/ + status=get_stat(port,ldrive); /*Read and toss status byte*/ +#ifdef DEBUGIO + printf("matcd%d: error, status was %x\n", + ldrive,status); +#endif /*DEBUGIO*/ + +/* Ok, we need more details, so read error. This is needed to issue + any further commands anyway +*/ + + errtyp=get_error(port,ldrive,cdrive); + printf("matcd%d: %s while reading block %d\n", + ldrive,matcderrors[errtyp],bp->b_blkno); + + if (media_chk(cd,errtyp,ldrive)) + goto giveup; + + errtyp=chk_error(errtyp); + switch(errtyp) { + case ERR_RETRY: /*We can retry this error, but the + drive probably has already*/ + if (mbx->retry-- > 0 ) { + state=MATCD_READ_1+ldrive; +#ifdef DEBUGIO + printf("matcd%d: Attempting retry\n", + ldrive); +#endif /*DEBUGIO*/ + goto loop; + } + goto giveup; + +/* These errors usually indicate the user took the media from the + drive while the dev was open. We will invalidate the unit + until it closes when we see this. +*/ + case ERR_INIT:/*Media probably was removed + while the dev was open. + Invalidate the unit until + it is closed.*/ + + case ERR_FATAL:/*This type of error is so + bad we will never recover + even if we retry.*/ + default: +giveup: +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xCE + (diagloop * 0x100));/*Show where we are*/ +#endif /*DIAGPORT*/ + bp->b_flags |= B_ERROR; + bp->b_resid = bp->b_bcount; + biodone(bp); + unlockbuss(ldrive>>2, ldrive); + matcd_start(dp); + return; + } + } + } +} + + +/*---------------------------------------------------------------------- + matcd_eject - Open drive tray +----------------------------------------------------------------------*/ + +int matcd_eject(int ldrive, int cdrive, int controller) +{ + int retries,i,z,port; + struct matcd_data *cd; + unsigned char cmd[MAXCMDSIZ]; + + cd=&matcd_data[ldrive]; + port=cd->iobase; /*Get I/O port base*/ + + zero_cmd(cmd); /*Initialize command buffer*/ +#ifdef LOCKDRIVE + cmd[0]=LOCK; /*Unlock drive*/ + i=docmd(cmd,ldrive,cdrive,controller,port); /*Issue command*/ +#endif /*LOCKDRIVE*/ + cmd[0]=DOOROPEN; /*Open Door*/ + i=docmd(cmd,ldrive,cdrive,controller,port); /*Issue command*/ + cd->flags &= ~MATCDLABEL; /*Mark volume info invalid*/ + return(i); /*Return result we got*/ +} + + +/*---------------------------------------------------------------------- + docmd - Get the buss, do the command, wait for completion, + attempt retries, give up the buss. + For commands that do not return data. +----------------------------------------------------------------------*/ + +int docmd(char * cmd, int ldrive, int cdrive, int controller, int port) +{ + int retries,i,z; + + lockbuss(controller, ldrive); /*Request buss*/ + retries=3; + while(retries-- > 0) { +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xD0); /*Show where we are*/ +#endif /*DIAGPORT*/ + matcd_slowcmd(port,ldrive,cdrive,cmd); + i=waitforit(80*TICKRES,DTEN,port,"cmd"); + z=get_stat(port,ldrive);/*Read and toss status byte*/ + if ((z & MATCD_ST_ERROR)==0) break; + i=chk_error(get_error(port,ldrive,cdrive)); + if (i!=ERR_INIT) { + unlockbuss(controller, ldrive); /*Release buss*/ + return(EFAULT); + } + } + unlockbuss(controller, ldrive); /*Release buss*/ + return(i); +} + + +/*---------------------------------------------------------------------- + get_error - Read the error that aborted a command. + Created in Edit 6 +----------------------------------------------------------------------*/ + +int get_error(int port, int ldrive, int cdrive) +{ + int status,errnum; + unsigned char cmd1[MAXCMDSIZ]; + unsigned char data[12]; + + zero_cmd(cmd1); + cmd1[0]=READERROR; /*Enquire*/ + matcd_fastcmd(port,ldrive,cdrive,cmd1); + matcd_pread(port, 8, data); /*Read data returned*/ + errnum=data[2]; /*Caller wants it classified*/ + status=get_stat(port,ldrive); /*Read and toss status byte*/ + +#ifdef DEBUGCMD + printf("matcd%d: Chkerror found %x on command %x addrval %x statusdata %x statusport %x\n", + ldrive,errnum,data[1],data[0],status,inb(port+STATUS)); +#endif /*DEBUGCMD*/ + return(errnum); +} + + +/*---------------------------------------------------------------------- + chk_error - Classify the error that the drive reported + Created in Edit 6 +----------------------------------------------------------------------*/ + +int chk_error(int errnum) +{ + switch(errnum) { +/* These are errors we can attempt a retry for, although the drive + has already done so. +*/ + case UNRECV_ERROR: + case SEEK_ERROR: + case TRACK_ERROR: + case FOCUS_ERROR: + case CLV_ERROR: + case DATA_ERROR: + return(ERR_RETRY); + +/* These errors usually indicate the user took the media from the + drive while the dev was open. We will invalidate the unit + until it closes when we see this. +*/ + case NOT_READY: + case MEDIA_CHANGED: + case DISC_OUT: + case HARD_RESET: + return (ERR_INIT); + +/* These errors indicate the system is confused about the drive + or media, and point to bugs in the driver or OS. These errors + cannot be retried since you will always get the same error. +*/ + + case RAM_ERROR: + case DIAG_ERROR: + case CDB_ERROR: + case END_ADDRESS: + case MODE_ERROR: + case ILLEGAL_REQ: + case ADDRESS_ERROR: + default: + return (ERR_FATAL); + } +} + + +/*---------------------------------------------------------------------- + get_stat - Reads status byte + + This routine should be totally unnecessary, performing the + task with a single line of in-line code. However in special + cases, the drives return blocks of data that are not associated + with the command in question. This appears to be a firmware + error and the rest of the driver makes an effort to avoid + triggering the fault. However, reading and throwing this + bogus data is faster and less destructive than resetting all + the drives on a given controller, plus it leaves the other drives + unaffected. +----------------------------------------------------------------------*/ + +int get_stat(int port,int ldrive) +{ + int status; + status=inb(port+DATA); /*Read the status byte, last step of cmd*/ + while ((inb(port+STATUS))!=0xff) { + printf("matcd%d: get_stat: After reading status byte, buss didn't go idle\n",ldrive); + if (( status & DTEN|STEN) == STEN) { + int k; + k=0; +#ifdef DEBUGCMD + printf("matcd%d: DATA PRESENT!!!! DISCARDING\n",ldrive); +#endif /*DEBUGCMD*/ + outb(port+STATUS,1); /*Enable data read*/ + while ((inb(port+STATUS) & (DTEN|STEN)) == STEN) { + inb(port+DATA); +/* printf("%2x ",inb(port+DATA));*/ + k++; + } + outb(port+STATUS,0); +#ifdef DEBUGCMD + printf("\nmatcd%d: BYTES READ IN DATA was %d\n", + ldrive,k); +#endif /*DEBUGCMD*/ + } + status=inb(port+DATA); /*Read the status byte again*/ +#ifdef DEBUGCMD + printf("matcd%d: Next status byte is %x\n",ldrive,status); +#endif /*DEBUGCMD*/ + } + return(status); +} + + +/*---------------------------------------------------------------------- + waitforit - Waits for a command started by slowcmd to complete. +----------------------------------------------------------------------*/ + +int waitforit(int timelimit, int state, int port, char * where) +{ + int i,j; + + j=i=0; +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xE0); /*Show where we are*/ + diagloop=0; +#endif /*DIAGPORT*/ +#ifdef DEBUGCMD + printf("matcd: waitforit port %x timelimit %x hz %x\n", + port,timelimit,hz); +#endif /*DEBUGCMD*/ + while (i<timelimit) { + j=inb(port+STATUS) & (STEN|DTEN); /*Read status*/ + if (j!=(STEN|DTEN)) break; + timeout((timeout_func_t)watchdog, (caddr_t)0,hz/100); + tsleep((caddr_t)&port_hints, PRIBIO, where, 0); + i++; +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xE1+(diagloop++ * 0x100)); /*Show where we are*/ +#endif /*DIAGPORT*/ + } +#ifdef DEBUGCMD + printf("matcd: Count was %d\n",i); +#endif /*DEBUGCMD*/ + if (j==state) return(0); /*Command complete*/ +#ifdef DEBUGCMD + printf("matcd: Timeout!"); +#endif /*DEBUGCMD*/ + return(1); /*Timeout occurred*/ +} + + +/*---------------------------------------------------------------------- + watchdog - Gives us a heartbeat for things we are waiting on +----------------------------------------------------------------------*/ + +static void watchdog(int state, char * foo) +{ +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xF0); /*Show where we are*/ +#endif /*DIAGPORT*/ + wakeup((caddr_t)&port_hints); + return; +} + + +/*---------------------------------------------------------------------- + lockbuss - Wait for the buss on the requested driver interface + to go idle and acquire it. + Created in Edit 6 +----------------------------------------------------------------------*/ + +void lockbuss(int controller, int ldrive) +{ + while ((if_state[controller] & BUSSBUSY)) { +#ifdef DEBUGSLEEP + printf("matcd%d: Can't do it now - going to sleep\n, + ldrive"); +#endif /*DEBUGSLEEP*/ +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xF1); /*Show where we are*/ +#endif /*DIAGPORT*/ + tsleep((caddr_t)&matcd_data->status, PRIBIO, + "matcdopen", 0); + } + if_state[controller] |= BUSSBUSY; /*It's ours NOW*/ +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xF2); /*Show where we are*/ +#endif /*DIAGPORT*/ +#ifdef DEBUGSLEEP + printf("matcd%d: BUSS locked in lockbuss\n",ldrive); +#endif /*DEBUGSLEEP*/ +} + + +/*---------------------------------------------------------------------- + lockbuss - Wait for the buss on the requested driver interface + to go idle and acquire it. + Created in Edit 6 +----------------------------------------------------------------------*/ + +void unlockbuss(int controller, int ldrive) +{ +#ifdef DIAGPORT + DIAGOUT(DIAGPORT,0xF4); /*Show where we are*/ +#endif /*DIAGPORT*/ + if_state[controller] &= ~BUSSBUSY; +#ifdef DEBUGSLEEP + printf("matcd%d: bussunlocked\n",ldrive); +#endif /*DEBUGSLEEP*/ + wakeup((caddr_t)&matcd_data->status); /*Wakeup other users*/ + matcd_start(&request_head[controller]); /*Wake up any block I/O*/ +} + + +/*---------------------------------------------------------------------- + media_chk - Checks error for types related to media + changes. +----------------------------------------------------------------------*/ + +int media_chk(struct matcd_data *cd,int errnum,int ldrive) +{ + if (errnum==NOT_READY || + errnum==MEDIA_CHANGED || + errnum==HARD_RESET || + errnum==DISC_OUT) { + cd->flags &= ~MATCDLABEL; /*Mark label as invalid*/ + + if ((cd->flags & MATCDWARN)==0) { /*Have we said this*/ + printf("matcd%d: Media changed - Further I/O aborted until device closed\n",ldrive); + cd->flags |= MATCDWARN; + } + return(1); + } + return(0); +} + + +/*---------------------------------------------------------------------- + The following functions are related to the audio playback + capabilities of the drive. They can be omitted from the + finished driver using the FULLDRIVER conditional. + + The full set of features the drive is capable of are currently + not implemented but will be added in an upcoming release. +----------------------------------------------------------------------*/ +#ifdef FULLDRIVER +/*---------------------------------------------------------------------- + matcd_playtracks - Plays one or more audio tracks +----------------------------------------------------------------------*/ + +static int matcd_playtracks(int ldrive, int cdrive, int controller, + struct ioc_play_track *pt) +{ + struct matcd_data *cd; + int start,end; + int i,port; + unsigned char cmd[MAXCMDSIZ]; + + cd=&matcd_data[ldrive]; + port=cd->iobase; + + if ((cd->flags & MATCDLABEL)==0) + return(EIO); /*Refuse after chg error*/ + + start=pt->start_track; + end=pt->end_track; + + if (start < 1 || /*Starting track valid?*/ + end < 1 || /*Ending track valid?*/ + start > end || /*Start higher than end?*/ + end > cd->volinfo.trk_high) /*End track higher than disc size?*/ + return(ESPIPE); /*Track out of range*/ + + lockbuss(controller, ldrive); /*Request buss*/ + i=matcd_setmode(ldrive, MODE_DA);/*Force drive into audio mode*/ + unlockbuss(controller, ldrive); /*Release buss*/ + if (i!=0) { + return(i); /*Not legal for this media?*/ + } + zero_cmd(cmd); + cmd[0]=PLAYTRKS; /*Play Audio Track/Index*/ + cmd[1]=start; + cmd[2]=pt->start_index; + cmd[3]=end; + cmd[4]=pt->end_index; + i=docmd(cmd,ldrive,cdrive,controller,port); /*Issue command*/ +#ifdef DEBUGIOCTL + printf("matcd%d: Play track results %d \n",ldrive,i); +#endif /*DEBUGIOCTL*/ + return(i); +} + + +/*---------------------------------------------------------------------- + matcd_playmsf - Plays between a range of blocks +----------------------------------------------------------------------*/ + +static int matcd_playmsf(int ldrive, int cdrive, int controller, + struct ioc_play_msf *pt) +{ + struct matcd_data *cd; + int i,port; + unsigned char cmd[MAXCMDSIZ]; + + cd=&matcd_data[ldrive]; + port=cd->iobase; + +#ifdef DEBUGIOCTL + printf("matcd%d: playmsf %2x %2x %2x -> %2x %2x %2x\n", + ldrive,pt->start_m, pt->start_s, pt->start_f, pt->end_m, + pt->end_s,pt->end_f); +#endif /*DEBUGIOCTL*/ + + if ((cd->flags & MATCDLABEL)==0) + return(EIO); /*Refuse after chg error*/ + + if ((cd->volinfo.vol_msf[0]==0 && + cd->volinfo.vol_msf[1]<2) || /*Must be after 0'1"75F*/ + msf_to_blk((char *)&pt->start_m) > + msf_to_blk((char *)&cd->volinfo.vol_msf)) { +#ifdef DEBUGIOCTL + printf("matcd%d: Invalid block combination\n",ldrive); +#endif /*DEBUGIOCTL*/ + return(ESPIPE); /*Track out of range*/ + } + + + lockbuss(controller, ldrive); /*Request buss*/ + i=matcd_setmode(ldrive, MODE_DA);/*Force drive into audio mode*/ + unlockbuss(controller, ldrive); /*Release buss*/ + if (i!=0) { + return(i); /*Not legal for this media?*/ + } + zero_cmd(cmd); + cmd[0]=PLAYBLOCKS; /*Play Audio Blocks*/ + cmd[1]=pt->start_m; + cmd[2]=pt->start_s; + cmd[3]=pt->start_f; + cmd[4]=pt->end_m; + cmd[5]=pt->end_s; + cmd[6]=pt->end_f; + i=docmd(cmd,ldrive,cdrive,controller,port); /*Issue command*/ + return(i); +} + + +/*---------------------------------------------------------------------- + matcd_pause - Pause or Resume audio playback +----------------------------------------------------------------------*/ + +static int matcd_pause(int ldrive, int cdrive, int controller, + struct ioc_play_msf * addr,int action) +{ + struct matcd_data *cd; + int i,port; + unsigned char cmd[MAXCMDSIZ]; + + cd=&matcd_data[ldrive]; + port=cd->iobase; + + if ((cd->flags & MATCDLABEL)==0) + return(EIO); /*Refuse after chg error*/ + + zero_cmd(cmd); + cmd[0]=PAUSE; /*Pause or Resume playing audio*/ + cmd[1]=action; + i=docmd(cmd,ldrive,cdrive,controller,port); /*Issue command*/ +#ifdef DEBUGIOCTL + printf("matcd%d: Pause / Resume results %d \n",ldrive,i); +#endif /*DEBUGIOCTL*/ + return(i); +} + + +/*---------------------------------------------------------------------- + matcd_stop - Stop audio playback +----------------------------------------------------------------------*/ + +static int matcd_stop(int ldrive, int cdrive, int controller, + struct ioc_play_msf * addr) +{ + struct matcd_data *cd; + int i,port; + unsigned char cmd[MAXCMDSIZ]; + + cd=&matcd_data[ldrive]; + port=cd->iobase; + + if ((cd->flags & MATCDLABEL)==0) + return(EIO); /*Refuse after chg error*/ + + zero_cmd(cmd); + cmd[0]=ABORT; /*Abort playing audio*/ + i=docmd(cmd,ldrive,cdrive,controller,port); /*Issue command*/ +#ifdef DEBUGIOCTL + printf("matcd%d: Abort results %d \n",ldrive,i); +#endif /*DEBUGIOCTL*/ + return(i); +} + +#endif /*FULLDRIVER*/ + +/*End of matcd.c*/ + diff --git a/sys/i386/isa/matcd.h b/sys/i386/isa/matcd.h new file mode 100644 index 0000000..827f0a9 --- /dev/null +++ b/sys/i386/isa/matcd.h @@ -0,0 +1,183 @@ +/*matcd.h--------------------------------------------------------------------- + Matsushita(Panasonic) / Creative CD-ROM Driver (matcd) + Authored by Frank Durda IV + + Copyright 1994, 1995 Frank Durda IV. All rights reserved. + "FDIV" is a trademark of Frank Durda IV. + + + Redistribution and use in source and binary forms, with or + without modification, are permitted provided that the following + conditions are met: + 1. Redistributions of source code must retain the above copyright + notice positioned at the very beginning of this file without + modification, all copyright strings, all related programming + codes that display the copyright strings, this list of + conditions and the following disclaimer. + 2. Redistributions in binary form must contain all copyright strings + and related programming code that display the copyright strings. + 3. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 4. All advertising materials mentioning features or use of this + software must display the following acknowledgement: + "The Matsushita/Panasonic CD-ROM driver was developed + by Frank Durda IV for use with "FreeBSD" and similar + operating systems." + "Similar operating systems" includes mainly non-profit oriented + systems for research and education, including but not restricted + to "NetBSD", "386BSD", and "Mach" (by CMU). The wording of the + acknowledgement (in electronic form or printed text) may not be + changed without permission from the author. + 5. Absolutely no warranty of function, fitness or purpose is made + by the author Frank Durda IV. + 6. Neither the name of the author nor the name "FreeBSD" may + be used to endorse or promote products derived from this software + without specific prior written permission. + (The author can be reached at bsdmail@nemesis.lonestar.org) + 7. The product containing this software must meet all of these + conditions even if it is unsupported, not a complete system + and/or does not contain compiled code. + 8. These conditions will be in force for the full life of the + copyright. + 9. If all the above conditions are met, modifications to other + parts of this file may be freely made, although any person + or persons making changes do not receive the right to add their + name or names to the copyright strings and notices in this + software. Persons making changes are encouraged to insert edit + history in matcd.c and to put your name and details of the + change there. + 10. You must have prior written permission from the author to + deviate from these terms. + + Vendors who produce product(s) containing this code are encouraged + (but not required) to provide copies of the finished product(s) to + the author and to correspond with the author about development + activity relating to this code. Donations of development hardware + and/or software are also welcome. (This is one of the faster ways + to get a driver developed for a device.) + + THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER(S) BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +See matcd.c for Edit History information. + + + Matsushita CR562/CR563 Commands + This is not a complete list - just the ones this version uses +*/ + +#define NOP 0x05 /*No action - just return status*/ +#define DOOROPEN 0x06 /*Open tray*/ +#define DOORCLOSE 0x07 /*Close tray*/ +#define ABORT 0x08 /*Abort command*/ +#define MODESELECT 0x09 /*Set drive parameters*/ +#define LOCK 0x0c /*Prevent/Allow medium removal*/ +#define PAUSE 0x0d /*Pause/Resume playback*/ +#define PLAYBLOCKS 0x0e /*Play audio - block to block*/ +#define PLAYTRKS 0x0f /*Play audio - tracks & index*/ +#define READ 0x10 /*Read data*/ +#define READERROR 0x82 /*Read Error*/ +#define READID 0x83 /*Read Drive Type & Firmware Info*/ +#define READDINFO 0x8b /*Read TOC tracks & drive size*/ + +#define BLOCKPARAM 0x00 /*Used with MODESELECT command*/ +#define RESUME 0x80 /*Used with PAUSE command*/ + +#define MAXCMDSIZ 12 /*Max command size with NULL*/ + +/* Possible data transfers for MODESELECT + BLOCKPARAM */ + +#define MODE_DATA 0x00 /*2048, 2340*/ +#define MODE_DA 0x82 /*2352*/ +#define MODE_USER 0x01 /*2048, 2052, 2336, 2340, 2352*/ +#define MODE_UNKNOWN 0xff /*Uninitialized state*/ + +/*The following two modes are not implemented in the driver at this time*/ + +#define MODE_XA 0x81 /*2048, 2060, 2324, 2336, 2340, 2352*/ + + +/* Matsushita CR562/CR563 Status bits*/ + +#define MATCD_ST_DOOROPEN 0x80 /*Door is open right now*/ +#define MATCD_ST_DSKIN 0x40 /*Disc in drive*/ +#define MATCD_ST_SPIN 0x20 /*Disc is spinning*/ +#define MATCD_ST_ERROR 0x10 /*Error on command*/ +#define MATCD_ST_BUSY 0x04 /*Drive is busy*/ +#define MATCD_ST_AUDIOBSY 0x02 /*Drive is playing audio*/ + +#define MATCDAUDIOBSY MATCD_ST_AUDIOBSY +#define MATCDDSKCHNG MATCD_ST_DSKCHNG +#define MATCDDSKIN MATCD_ST_DSKIN +#define MATCDDOOROPEN MATCD_ST_DOOROPEN + + +/* Error codes returned from READERROR command.*/ + +#define NO_ERROR 0x00 +#define RECV_RETRY 0x01 +#define RECV_ECC 0x02 +#define NOT_READY 0x03 +#define TOC_ERROR 0x04 +#define UNRECV_ERROR 0x05 +#define SEEK_ERROR 0x06 +#define TRACK_ERROR 0x07 +#define RAM_ERROR 0x08 +#define DIAG_ERROR 0x09 +#define FOCUS_ERROR 0x0a +#define CLV_ERROR 0x0b +#define DATA_ERROR 0x0c +#define ADDRESS_ERROR 0x0d +#define CDB_ERROR 0x0e +#define END_ADDRESS 0x0f +#define MODE_ERROR 0x10 +#define MEDIA_CHANGED 0x11 +#define HARD_RESET 0x12 +#define ROM_ERROR 0x13 +#define CMD_ERROR 0x14 +#define DISC_OUT 0x15 +#define HARD_ERROR 0x16 +#define ILLEGAL_REQ 0x17 + + +/* Human-readable error messages - what a concept!*/ + +static unsigned char * matcderrors[]={"No error", /* 00 */ + "Soft read error after retry", /* 01 */ + "Soft read error after error-correction", /* 02 */ + "Not ready", /* 03 */ + "Unable to read TOC", /* 04 */ + "Hard read error of data track",/* 05 */ + "Seek did not complete", /* 06 */ + "Tracking servo failure", /* 07 */ + "Drive RAM failure", /* 08 */ + "Drive self-test failed", /* 09 */ + "Focusing servo failure", /* 0a */ + "Spindle servo failure", /* 0b */ + "Data path failure", /* 0c */ + "Illegal logical block address",/* 0d */ + "Illegal field in CDB", /* 0e */ + "End of user encountered on this track", /* 0f */ + "Illegal data mode for this track", /* 10 */ + "Media changed", /* 11 */ + "Power-on or drive reset occurred", /* 12 */ + "Drive ROM failure", /* 13 */ + "Illegal drive command received from host",/* 14 */ + "Disc removed during operation",/* 15 */ + "Drive Hardware error", /* 16 */ + "Illegal request from host"}; /* 17 */ + +/*End of matcd.h*/ + + diff --git a/sys/i386/isa/options.h b/sys/i386/isa/options.h new file mode 100644 index 0000000..3dd1b5f8 --- /dev/null +++ b/sys/i386/isa/options.h @@ -0,0 +1,250 @@ +/*options.h-------------------------------------------------------------------- + Matsushita(Panasonic) / Creative CD-ROM Driver (matcd) + Authored by Frank Durda IV + + Copyright 1994, 1995 Frank Durda IV. All rights reserved. + "FDIV" is a trademark of Frank Durda IV. + + + Redistribution and use in source and binary forms, with or + without modification, are permitted provided that the following + conditions are met: + 1. Redistributions of source code must retain the above copyright + notice positioned at the very beginning of this file without + modification, all copyright strings, all related programming + codes that display the copyright strings, this list of + conditions and the following disclaimer. + 2. Redistributions in binary form must contain all copyright strings + and related programming code that display the copyright strings. + 3. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 4. All advertising materials mentioning features or use of this + software must display the following acknowledgement: + "The Matsushita/Panasonic CD-ROM driver was developed + by Frank Durda IV for use with "FreeBSD" and similar + operating systems." + "Similar operating systems" includes mainly non-profit oriented + systems for research and education, including but not restricted + to "NetBSD", "386BSD", and "Mach" (by CMU). The wording of the + acknowledgement (in electronic form or printed text) may not be + changed without permission from the author. + 5. Absolutely no warranty of function, fitness or purpose is made + by the author Frank Durda IV. + 6. Neither the name of the author nor the name "FreeBSD" may + be used to endorse or promote products derived from this software + without specific prior written permission. + (The author can be reached at bsdmail@nemesis.lonestar.org) + 7. The product containing this software must meet all of these + conditions even if it is unsupported, not a complete system + and/or does not contain compiled code. + 8. These conditions will be in force for the full life of the + copyright. + 9. If all the above conditions are met, modifications to other + parts of this file may be freely made, although any person + or persons making changes do not receive the right to add their + name or names to the copyright strings and notices in this + software. Persons making changes are encouraged to insert edit + history in matcd.c and to put your name and details of the + change there. + 10. You must have prior written permission from the author to + deviate from these terms. + + Vendors who produce product(s) containing this code are encouraged + (but not required) to provide copies of the finished product(s) to + the author and to correspond with the author about development + activity relating to this code. Donations of development hardware + and/or software are also welcome. (This is one of the faster ways + to get a driver developed for a device.) + + THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER(S) BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- + Conditional compilation flags - change to suit your system +---------------------------------------------------------------------------*/ + +/* AUTOHUNT Adds extra code that allows the driver to search + for interface cards rather than having to hard-code + the locations in the kernel conf file. + Leaving AUTOHUNT enabled is the recommended setting. +*/ + +#define AUTOHUNT + + +/* FULLCONFIG Allows up to four host interface boards for a + total of 16 drives. If disabled, only a single + host interface (of any type) is allowed. The + additional driver size is insignificant. + Leaving FULLCONFIG enabled is the recommended setting. +*/ + +#define FULLCONFIG + + +/* FULLDRIVER If not set, the audio, non-data functions and + some error recovery functions are eliminated from + the compiled driver. The resulting driver will be + smaller and may help a kernel fit on a boot floppy. + Leaving FULLDRIVER enabled is the recommended setting. +*/ + +#define FULLDRIVER + + +/* RESETONBOOT causes the driver to reset the drive(s) to be + reset during probing. This causes any audio + playback to be aborted and the drives will close + their trays if they are open. + Leaving RESETONBOOT enabled is the recommended setting. +*/ + +#define RESETONBOOT + + +/* LOCKDRIVE If enabled, the when the drive is open, the + door is locked. The front panel eject button + is ignored. When the drive is completely closed, + the eject button will be honored. + Leaving LOCKDRIVE disabled is the recommended setting. +*/ + +/*#define LOCKDRIVE*/ + + +/*<5> FREE2 If enabled, the changes are inserted so this +<5> module will compile in the world of FreeBSD 2.x. +<5> Without this, it is known to work in +<5> FreeBSD 1.1.5.1. +<5>*/ + +#define FREE2 /*<5>Correct setting for 2.x*/ + + +/*--------------------------------------------------------------------------- + This structure contains the hints for where we should look for the + host adapter. If you want to change where we search or reduce the + places we search to avoid confusing some other device, either + specify explicit addresses in the kernel config file (preferred) + or change this array. + + If the kernel config fuke has multiple ? entries, the probe routines + will use this table multiple times and will eliminate each failed + entry probe tries. + + WARNING: The number of controller entries for this driver in config + must be less than or equal to the number of hints if hints are used. + + If you add entries to the table, add them immediately before + the -1 end-of-table marker. The values already present are + the ones found on standard SoundBlaster 16 and standalone cards. +---------------------------------------------------------------------------*/ + + +#ifdef AUTOHUNT +int port_hints[]={ + 0x230,0x240, /*Ports SB audio boards can use*/ + 0x250,0x260, /*Ports standalone CD/IF board can*/ + -1}; /*use. Table MUST end with -1*/ +#endif /*AUTOHUNT*/ + + +/*--------------------------------------------------------------------------- + Debugging flags - Turn these on only if you are looking at a + problem. +---------------------------------------------------------------------------*/ + +/* DEBUGOPEN If enabled, debug messages for open and close + operations. +*/ + +/*#define DEBUGOPEN*/ + + +/* DEBUGIO If enabled, reports on calls to strategy, start + and other I/O related functions. +*/ + +/*#define DEBUGIO*/ + + +/* DEBUGQUEUE If enabled, shows activity on disk request queues. + Warning - This debug is VERY VERY NOISY and will + loop endlessly if queues are not null terminated + as they should be. +*/ + +/*#define DEBUGQUEUE*/ + + +/* DEBUGCMD If enabled, shows the actual commands being issued + to the CD-ROM drives. +*/ + +/*#define DEBUGCMD*/ + + +/* DEBUGSLEEP If enabled, reports on timeouts, wakeups, dropped + threads, etc. +*/ + +/*#define DEBUGSLEEP*/ + + +/* DEBUGIOCTL If enabled, reports on the various ioctl-related + calls and operations. You might have to enable + DEBUGCMD as well to get enough debugging information. +*/ + +/*#define DEBUGIOCTL*/ + + +/* DEBUGPROBE If enabled, reports on the process of locating + adapters and drives. The debugging in matcdprobe() + and matcdattach() routines is enabled with this + flag. +*/ + +/*#define DEBUGPROBE*/ + + +/* DIAGPORT If enabled, additional code is added to send + debugging state to a debug port. This should + not be enabled in production. The value + can be set to 0x80 or 0x302, depending on what + type of debugging board you own. The global variable + diagloop is used to make looping reports on these + devices. + + Some other drivers and possible the kernel fiddle + with the 0x80 debug port, so it may not be usable + for isolating failures that result in a kernel panic. + The 0x302 debug board is recommended in these cases. + It also displays a word of data, so you get more + detail. + +<10> It was discovered the 0x302 board was getting set +<10> into a strange state by the probes for other +<10> devices. To resolve this, the display control port +<10> (0x300) is reset in our probe and open routines. +<10> DO NOT use DIAGPORT 0x302 if an adapter is present +<10> at that address. It could ruin the EEPROM settings +<10> on the device. +*/ + +/*#define DIAGPORT 0x80*/ +/*#define DIAGPORT 0x302*/ + +/*End of options.h*/ + + |