isp16.c 9.6 KB

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