isp16.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
- /* -- ISP16 cdrom detection and configuration
- *
- * Copyright (c) 1995,1996 Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
- *
- * Version 0.6
- *
- * History:
- * 0.5 First release.
- * Was included in the sjcd and optcd cdrom drivers.
- * 0.6 First "stand-alone" version.
- * Removed sound configuration.
- * Added "module" support.
- *
- * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * Detect cdrom interface on ISP16 sound card.
- * Configure cdrom interface.
- *
- * Algorithm for the card with OPTi 82C928 taken
- * from the CDSETUP.SYS driver for MSDOS,
- * by OPTi Computers, version 2.03.
- * Algorithm for the card with OPTi 82C929 as communicated
- * to me by Vadim Model and Leo Spiekman.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
- #define ISP16_VERSION_MAJOR 0
- #define ISP16_VERSION_MINOR 6
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/kernel.h>
- #include <linux/string.h>
- #include <linux/ioport.h>
- #include <linux/init.h>
- #include <asm/io.h>
- #include "isp16.h"
- static short isp16_detect(void);
- static short isp16_c928__detect(void);
- static short isp16_c929__detect(void);
- static short isp16_cdi_config(int base, u_char drive_type, int irq,
- int dma);
- static short isp16_type; /* dependent on type of interface card */
- static u_char isp16_ctrl;
- static u_short isp16_enable_port;
- static int isp16_cdrom_base = ISP16_CDROM_IO_BASE;
- static int isp16_cdrom_irq = ISP16_CDROM_IRQ;
- static int isp16_cdrom_dma = ISP16_CDROM_DMA;
- static char *isp16_cdrom_type = ISP16_CDROM_TYPE;
- MODULE_PARM(isp16_cdrom_base, "i");
- MODULE_PARM(isp16_cdrom_irq, "i");
- MODULE_PARM(isp16_cdrom_dma, "i");
- MODULE_PARM(isp16_cdrom_type, "s");
- #ifdef MODULE
- void isp16_exit(void);
- #endif
- #define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
- #define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
- #ifndef MODULE
- static int
- __init isp16_setup(char *str)
- {
- int ints[4];
- (void) get_options(str, ARRAY_SIZE(ints), ints);
- if (ints[0] > 0)
- isp16_cdrom_base = ints[1];
- if (ints[0] > 1)
- isp16_cdrom_irq = ints[2];
- if (ints[0] > 2)
- isp16_cdrom_dma = ints[3];
- if (str)
- isp16_cdrom_type = str;
- return 1;
- }
- __setup("isp16=", isp16_setup);
- #endif /* MODULE */
- /*
- * ISP16 initialisation.
- *
- */
- int __init isp16_init(void)
- {
- u_char expected_drive;
- printk(KERN_INFO
- "ISP16: configuration cdrom interface, version %d.%d.n",
- ISP16_VERSION_MAJOR, ISP16_VERSION_MINOR);
- if (!strcmp(isp16_cdrom_type, "noisp16")) {
- printk("ISP16: no cdrom interface configured.n");
- return (0);
- }
- if (check_region(ISP16_IO_BASE, ISP16_IO_SIZE)) {
- printk("ISP16: i/o ports already in use.n");
- return (-EIO);
- }
- if ((isp16_type = isp16_detect()) < 0) {
- printk("ISP16: no cdrom interface found.n");
- return (-EIO);
- }
- printk(KERN_INFO
- "ISP16: cdrom interface (with OPTi 82C92%d chip) detected.n",
- (isp16_type == 2) ? 9 : 8);
- if (!strcmp(isp16_cdrom_type, "Sanyo"))
- expected_drive =
- (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0);
- else if (!strcmp(isp16_cdrom_type, "Sony"))
- expected_drive = ISP16_SONY;
- else if (!strcmp(isp16_cdrom_type, "Panasonic"))
- expected_drive =
- (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0);
- else if (!strcmp(isp16_cdrom_type, "Mitsumi"))
- expected_drive = ISP16_MITSUMI;
- else {
- printk("ISP16: %s not supported by cdrom interface.n",
- isp16_cdrom_type);
- return (-EIO);
- }
- if (isp16_cdi_config(isp16_cdrom_base, expected_drive,
- isp16_cdrom_irq, isp16_cdrom_dma) < 0) {
- printk
- ("ISP16: cdrom interface has not been properly configured.n");
- return (-EIO);
- }
- printk(KERN_INFO
- "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d,"
- " type %s.n", isp16_cdrom_base, isp16_cdrom_irq,
- isp16_cdrom_dma, isp16_cdrom_type);
- return (0);
- }
- static short __init isp16_detect(void)
- {
- if (isp16_c929__detect() >= 0)
- return (2);
- else
- return (isp16_c928__detect());
- }
- static short __init isp16_c928__detect(void)
- {
- u_char ctrl;
- u_char enable_cdrom;
- u_char io;
- short i = -1;
- isp16_ctrl = ISP16_C928__CTRL;
- isp16_enable_port = ISP16_C928__ENABLE_PORT;
- /* read' and write' are a special read and write, respectively */
- /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
- ctrl = ISP16_IN(ISP16_CTRL_PORT) & 0xFC;
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
- /* read' 3,4 and 5-bit from the cdrom enable port */
- enable_cdrom = ISP16_IN(ISP16_C928__ENABLE_PORT) & 0x38;
- if (!(enable_cdrom & 0x20)) { /* 5-bit not set */
- /* read' last 2 bits of ISP16_IO_SET_PORT */
- io = ISP16_IN(ISP16_IO_SET_PORT) & 0x03;
- if (((io & 0x01) << 1) == (io & 0x02)) { /* bits are the same */
- if (io == 0) { /* ...the same and 0 */
- i = 0;
- enable_cdrom |= 0x20;
- } else { /* ...the same and 1 *//* my card, first time 'round */
- i = 1;
- enable_cdrom |= 0x28;
- }
- ISP16_OUT(ISP16_C928__ENABLE_PORT, enable_cdrom);
- } else { /* bits are not the same */
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
- return (i); /* -> not detected: possibly incorrect conclusion */
- }
- } else if (enable_cdrom == 0x20)
- i = 0;
- else if (enable_cdrom == 0x28) /* my card, already initialised */
- i = 1;
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
- return (i);
- }
- static short __init isp16_c929__detect(void)
- {
- u_char ctrl;
- u_char tmp;
- isp16_ctrl = ISP16_C929__CTRL;
- isp16_enable_port = ISP16_C929__ENABLE_PORT;
- /* read' and write' are a special read and write, respectively */
- /* read' ISP16_CTRL_PORT and save */
- ctrl = ISP16_IN(ISP16_CTRL_PORT);
- /* write' zero to the ctrl port and get response */
- ISP16_OUT(ISP16_CTRL_PORT, 0);
- tmp = ISP16_IN(ISP16_CTRL_PORT);
- if (tmp != 2) /* isp16 with 82C929 not detected */
- return (-1);
- /* restore ctrl port value */
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
- return (2);
- }
- static short __init
- isp16_cdi_config(int base, u_char drive_type, int irq, int dma)
- {
- u_char base_code;
- u_char irq_code;
- u_char dma_code;
- u_char i;
- if ((drive_type == ISP16_MITSUMI) && (dma != 0))
- printk("ISP16: Mitsumi cdrom drive has no dma support.n");
- switch (base) {
- case 0x340:
- base_code = ISP16_BASE_340;
- break;
- case 0x330:
- base_code = ISP16_BASE_330;
- break;
- case 0x360:
- base_code = ISP16_BASE_360;
- break;
- case 0x320:
- base_code = ISP16_BASE_320;
- break;
- default:
- printk
- ("ISP16: base address 0x%03X not supported by cdrom interface.n",
- base);
- return (-1);
- }
- switch (irq) {
- case 0:
- irq_code = ISP16_IRQ_X;
- break; /* disable irq */
- case 5:
- irq_code = ISP16_IRQ_5;
- printk("ISP16: irq 5 shouldn't be used by cdrom interface,"
- " due to possible conflicts with the sound card.n");
- break;
- case 7:
- irq_code = ISP16_IRQ_7;
- printk("ISP16: irq 7 shouldn't be used by cdrom interface,"
- " due to possible conflicts with the sound card.n");
- break;
- case 3:
- irq_code = ISP16_IRQ_3;
- break;
- case 9:
- irq_code = ISP16_IRQ_9;
- break;
- case 10:
- irq_code = ISP16_IRQ_10;
- break;
- case 11:
- irq_code = ISP16_IRQ_11;
- break;
- default:
- printk("ISP16: irq %d not supported by cdrom interface.n",
- irq);
- return (-1);
- }
- switch (dma) {
- case 0:
- dma_code = ISP16_DMA_X;
- break; /* disable dma */
- case 1:
- printk("ISP16: dma 1 cannot be used by cdrom interface,"
- " due to conflict with the sound card.n");
- return (-1);
- break;
- case 3:
- dma_code = ISP16_DMA_3;
- break;
- case 5:
- dma_code = ISP16_DMA_5;
- break;
- case 6:
- dma_code = ISP16_DMA_6;
- break;
- case 7:
- dma_code = ISP16_DMA_7;
- break;
- default:
- printk("ISP16: dma %d not supported by cdrom interface.n",
- dma);
- return (-1);
- }
- if (drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
- drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
- drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
- drive_type != ISP16_DRIVE_X) {
- printk
- ("ISP16: drive type (code 0x%02X) not supported by cdrom"
- " interface.n", drive_type);
- return (-1);
- }
- /* set type of interface */
- i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK; /* clear some bits */
- ISP16_OUT(ISP16_DRIVE_SET_PORT, i | drive_type);
- /* enable cdrom on interface with 82C929 chip */
- if (isp16_type > 1)
- ISP16_OUT(isp16_enable_port, ISP16_ENABLE_CDROM);
- /* set base address, irq and dma */
- i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK; /* keep some bits */
- ISP16_OUT(ISP16_IO_SET_PORT, i | base_code | irq_code | dma_code);
- return (0);
- }
- void __exit isp16_exit(void)
- {
- release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
- printk(KERN_INFO "ISP16: module released.n");
- }
- #ifdef MODULE
- module_init(isp16_init);
- #endif
- module_exit(isp16_exit);
- EXPORT_NO_SYMBOLS;
- MODULE_LICENSE("GPL");