isp16.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:9k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* -- ISP16 cdrom detection and configuration
  2.  *
  3.  *    Copyright (c) 1995,1996 Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
  4.  *
  5.  *    Version 0.6
  6.  *
  7.  *    History:
  8.  *    0.5 First release.
  9.  *        Was included in the sjcd and optcd cdrom drivers.
  10.  *    0.6 First "stand-alone" version.
  11.  *        Removed sound configuration.
  12.  *        Added "module" support.
  13.  *
  14.  *      9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
  15.  *                    Removed init_module & cleanup_module in favor of 
  16.  *    module_init & module_exit.
  17.  *    Torben Mathiasen <tmm@image.dk>
  18.  *
  19.  *    Detect cdrom interface on ISP16 sound card.
  20.  *    Configure cdrom interface.
  21.  *
  22.  *    Algorithm for the card with OPTi 82C928 taken
  23.  *    from the CDSETUP.SYS driver for MSDOS,
  24.  *    by OPTi Computers, version 2.03.
  25.  *    Algorithm for the card with OPTi 82C929 as communicated
  26.  *    to me by Vadim Model and Leo Spiekman.
  27.  *
  28.  *    This program is free software; you can redistribute it and/or modify
  29.  *    it under the terms of the GNU General Public License as published by
  30.  *    the Free Software Foundation; either version 2 of the License, or
  31.  *    (at your option) any later version.
  32.  *
  33.  *    This program is distributed in the hope that it will be useful,
  34.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  35.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  36.  *    GNU General Public License for more details.
  37.  *
  38.  *    You should have received a copy of the GNU General Public License
  39.  *    along with this program; if not, write to the Free Software
  40.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  41.  *
  42.  */
  43. #define ISP16_VERSION_MAJOR 0
  44. #define ISP16_VERSION_MINOR 6
  45. #include <linux/module.h>
  46. #include <linux/fs.h>
  47. #include <linux/kernel.h>
  48. #include <linux/string.h>
  49. #include <linux/ioport.h>
  50. #include <linux/init.h>
  51. #include <asm/io.h>
  52. #include "isp16.h"
  53. static short isp16_detect(void);
  54. static short isp16_c928__detect(void);
  55. static short isp16_c929__detect(void);
  56. static short isp16_cdi_config(int base, u_char drive_type, int irq,
  57.       int dma);
  58. static short isp16_type; /* dependent on type of interface card */
  59. static u_char isp16_ctrl;
  60. static u_short isp16_enable_port;
  61. static int isp16_cdrom_base = ISP16_CDROM_IO_BASE;
  62. static int isp16_cdrom_irq = ISP16_CDROM_IRQ;
  63. static int isp16_cdrom_dma = ISP16_CDROM_DMA;
  64. static char *isp16_cdrom_type = ISP16_CDROM_TYPE;
  65. MODULE_PARM(isp16_cdrom_base, "i");
  66. MODULE_PARM(isp16_cdrom_irq, "i");
  67. MODULE_PARM(isp16_cdrom_dma, "i");
  68. MODULE_PARM(isp16_cdrom_type, "s");
  69. #ifdef MODULE
  70. void isp16_exit(void);
  71. #endif
  72. #define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
  73. #define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
  74. #ifndef MODULE
  75. static int
  76. __init isp16_setup(char *str)
  77. {
  78. int ints[4];
  79. (void) get_options(str, ARRAY_SIZE(ints), ints);
  80. if (ints[0] > 0)
  81. isp16_cdrom_base = ints[1];
  82. if (ints[0] > 1)
  83. isp16_cdrom_irq = ints[2];
  84. if (ints[0] > 2)
  85. isp16_cdrom_dma = ints[3];
  86. if (str)
  87. isp16_cdrom_type = str;
  88. return 1;
  89. }
  90. __setup("isp16=", isp16_setup);
  91. #endif /* MODULE */
  92. /*
  93.  *  ISP16 initialisation.
  94.  *
  95.  */
  96. int __init isp16_init(void)
  97. {
  98. u_char expected_drive;
  99. printk(KERN_INFO
  100.        "ISP16: configuration cdrom interface, version %d.%d.n",
  101.        ISP16_VERSION_MAJOR, ISP16_VERSION_MINOR);
  102. if (!strcmp(isp16_cdrom_type, "noisp16")) {
  103. printk("ISP16: no cdrom interface configured.n");
  104. return (0);
  105. }
  106. if (check_region(ISP16_IO_BASE, ISP16_IO_SIZE)) {
  107. printk("ISP16: i/o ports already in use.n");
  108. return (-EIO);
  109. }
  110. if ((isp16_type = isp16_detect()) < 0) {
  111. printk("ISP16: no cdrom interface found.n");
  112. return (-EIO);
  113. }
  114. printk(KERN_INFO
  115.        "ISP16: cdrom interface (with OPTi 82C92%d chip) detected.n",
  116.        (isp16_type == 2) ? 9 : 8);
  117. if (!strcmp(isp16_cdrom_type, "Sanyo"))
  118. expected_drive =
  119.     (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0);
  120. else if (!strcmp(isp16_cdrom_type, "Sony"))
  121. expected_drive = ISP16_SONY;
  122. else if (!strcmp(isp16_cdrom_type, "Panasonic"))
  123. expected_drive =
  124.     (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0);
  125. else if (!strcmp(isp16_cdrom_type, "Mitsumi"))
  126. expected_drive = ISP16_MITSUMI;
  127. else {
  128. printk("ISP16: %s not supported by cdrom interface.n",
  129.        isp16_cdrom_type);
  130. return (-EIO);
  131. }
  132. if (isp16_cdi_config(isp16_cdrom_base, expected_drive,
  133.      isp16_cdrom_irq, isp16_cdrom_dma) < 0) {
  134. printk
  135.     ("ISP16: cdrom interface has not been properly configured.n");
  136. return (-EIO);
  137. }
  138. printk(KERN_INFO
  139.        "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d,"
  140.        " type %s.n", isp16_cdrom_base, isp16_cdrom_irq,
  141.        isp16_cdrom_dma, isp16_cdrom_type);
  142. return (0);
  143. }
  144. static short __init isp16_detect(void)
  145. {
  146. if (isp16_c929__detect() >= 0)
  147. return (2);
  148. else
  149. return (isp16_c928__detect());
  150. }
  151. static short __init isp16_c928__detect(void)
  152. {
  153. u_char ctrl;
  154. u_char enable_cdrom;
  155. u_char io;
  156. short i = -1;
  157. isp16_ctrl = ISP16_C928__CTRL;
  158. isp16_enable_port = ISP16_C928__ENABLE_PORT;
  159. /* read' and write' are a special read and write, respectively */
  160. /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
  161. ctrl = ISP16_IN(ISP16_CTRL_PORT) & 0xFC;
  162. ISP16_OUT(ISP16_CTRL_PORT, ctrl);
  163. /* read' 3,4 and 5-bit from the cdrom enable port */
  164. enable_cdrom = ISP16_IN(ISP16_C928__ENABLE_PORT) & 0x38;
  165. if (!(enable_cdrom & 0x20)) { /* 5-bit not set */
  166. /* read' last 2 bits of ISP16_IO_SET_PORT */
  167. io = ISP16_IN(ISP16_IO_SET_PORT) & 0x03;
  168. if (((io & 0x01) << 1) == (io & 0x02)) { /* bits are the same */
  169. if (io == 0) { /* ...the same and 0 */
  170. i = 0;
  171. enable_cdrom |= 0x20;
  172. } else { /* ...the same and 1 *//* my card, first time 'round */
  173. i = 1;
  174. enable_cdrom |= 0x28;
  175. }
  176. ISP16_OUT(ISP16_C928__ENABLE_PORT, enable_cdrom);
  177. } else { /* bits are not the same */
  178. ISP16_OUT(ISP16_CTRL_PORT, ctrl);
  179. return (i); /* -> not detected: possibly incorrect conclusion */
  180. }
  181. } else if (enable_cdrom == 0x20)
  182. i = 0;
  183. else if (enable_cdrom == 0x28) /* my card, already initialised */
  184. i = 1;
  185. ISP16_OUT(ISP16_CTRL_PORT, ctrl);
  186. return (i);
  187. }
  188. static short __init isp16_c929__detect(void)
  189. {
  190. u_char ctrl;
  191. u_char tmp;
  192. isp16_ctrl = ISP16_C929__CTRL;
  193. isp16_enable_port = ISP16_C929__ENABLE_PORT;
  194. /* read' and write' are a special read and write, respectively */
  195. /* read' ISP16_CTRL_PORT and save */
  196. ctrl = ISP16_IN(ISP16_CTRL_PORT);
  197. /* write' zero to the ctrl port and get response */
  198. ISP16_OUT(ISP16_CTRL_PORT, 0);
  199. tmp = ISP16_IN(ISP16_CTRL_PORT);
  200. if (tmp != 2) /* isp16 with 82C929 not detected */
  201. return (-1);
  202. /* restore ctrl port value */
  203. ISP16_OUT(ISP16_CTRL_PORT, ctrl);
  204. return (2);
  205. }
  206. static short __init
  207. isp16_cdi_config(int base, u_char drive_type, int irq, int dma)
  208. {
  209. u_char base_code;
  210. u_char irq_code;
  211. u_char dma_code;
  212. u_char i;
  213. if ((drive_type == ISP16_MITSUMI) && (dma != 0))
  214. printk("ISP16: Mitsumi cdrom drive has no dma support.n");
  215. switch (base) {
  216. case 0x340:
  217. base_code = ISP16_BASE_340;
  218. break;
  219. case 0x330:
  220. base_code = ISP16_BASE_330;
  221. break;
  222. case 0x360:
  223. base_code = ISP16_BASE_360;
  224. break;
  225. case 0x320:
  226. base_code = ISP16_BASE_320;
  227. break;
  228. default:
  229. printk
  230.     ("ISP16: base address 0x%03X not supported by cdrom interface.n",
  231.      base);
  232. return (-1);
  233. }
  234. switch (irq) {
  235. case 0:
  236. irq_code = ISP16_IRQ_X;
  237. break; /* disable irq */
  238. case 5:
  239. irq_code = ISP16_IRQ_5;
  240. printk("ISP16: irq 5 shouldn't be used by cdrom interface,"
  241.        " due to possible conflicts with the sound card.n");
  242. break;
  243. case 7:
  244. irq_code = ISP16_IRQ_7;
  245. printk("ISP16: irq 7 shouldn't be used by cdrom interface,"
  246.        " due to possible conflicts with the sound card.n");
  247. break;
  248. case 3:
  249. irq_code = ISP16_IRQ_3;
  250. break;
  251. case 9:
  252. irq_code = ISP16_IRQ_9;
  253. break;
  254. case 10:
  255. irq_code = ISP16_IRQ_10;
  256. break;
  257. case 11:
  258. irq_code = ISP16_IRQ_11;
  259. break;
  260. default:
  261. printk("ISP16: irq %d not supported by cdrom interface.n",
  262.        irq);
  263. return (-1);
  264. }
  265. switch (dma) {
  266. case 0:
  267. dma_code = ISP16_DMA_X;
  268. break; /* disable dma */
  269. case 1:
  270. printk("ISP16: dma 1 cannot be used by cdrom interface,"
  271.        " due to conflict with the sound card.n");
  272. return (-1);
  273. break;
  274. case 3:
  275. dma_code = ISP16_DMA_3;
  276. break;
  277. case 5:
  278. dma_code = ISP16_DMA_5;
  279. break;
  280. case 6:
  281. dma_code = ISP16_DMA_6;
  282. break;
  283. case 7:
  284. dma_code = ISP16_DMA_7;
  285. break;
  286. default:
  287. printk("ISP16: dma %d not supported by cdrom interface.n",
  288.        dma);
  289. return (-1);
  290. }
  291. if (drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
  292.     drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
  293.     drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
  294.     drive_type != ISP16_DRIVE_X) {
  295. printk
  296.     ("ISP16: drive type (code 0x%02X) not supported by cdrom"
  297.      " interface.n", drive_type);
  298. return (-1);
  299. }
  300. /* set type of interface */
  301. i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK; /* clear some bits */
  302. ISP16_OUT(ISP16_DRIVE_SET_PORT, i | drive_type);
  303. /* enable cdrom on interface with 82C929 chip */
  304. if (isp16_type > 1)
  305. ISP16_OUT(isp16_enable_port, ISP16_ENABLE_CDROM);
  306. /* set base address, irq and dma */
  307. i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK; /* keep some bits */
  308. ISP16_OUT(ISP16_IO_SET_PORT, i | base_code | irq_code | dma_code);
  309. return (0);
  310. }
  311. void __exit isp16_exit(void)
  312. {
  313. release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
  314. printk(KERN_INFO "ISP16: module released.n");
  315. }
  316. #ifdef MODULE
  317. module_init(isp16_init);
  318. #endif
  319. module_exit(isp16_exit);
  320. EXPORT_NO_SYMBOLS;
  321. MODULE_LICENSE("GPL");