summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-03-02 04:07:03 +0000
committerjkh <jkh@FreeBSD.org>1995-03-02 04:07:03 +0000
commit210fe3dddd329efda88d011a4a7fb0a2d6c0941a (patch)
tree1292d19796d8a9f0d0385e8dfd4d552c765f766b /sys
parent206b955407327511e61c0f5b13e75fdffa31a9d4 (diff)
downloadFreeBSD-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/GENERIC4
-rw-r--r--sys/conf/NOTES13
-rw-r--r--sys/i386/conf/GENERIC4
-rw-r--r--sys/i386/conf/LINT13
-rw-r--r--sys/i386/conf/NOTES13
-rw-r--r--sys/i386/i386/conf.c28
-rw-r--r--sys/i386/isa/creative.h129
-rw-r--r--sys/i386/isa/matcd.c2279
-rw-r--r--sys/i386/isa/matcd.h183
-rw-r--r--sys/i386/isa/options.h250
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*/
+
+
OpenPOWER on IntegriCloud