mwavedd.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:19k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2. *
  3. * mwavedd.c -- mwave device driver
  4. *
  5. *
  6. * Written By: Mike Sullivan IBM Corporation
  7. *
  8. * Copyright (C) 1999 IBM Corporation
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. * GNU General Public License for more details.
  19. *
  20. * NO WARRANTY
  21. * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
  22. * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
  23. * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
  24. * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
  25. * solely responsible for determining the appropriateness of using and
  26. * distributing the Program and assumes all risks associated with its
  27. * exercise of rights under this Agreement, including but not limited to
  28. * the risks and costs of program errors, damage to or loss of data,
  29. * programs or equipment, and unavailability or interruption of operations.
  30. *
  31. * DISCLAIMER OF LIABILITY
  32. * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
  33. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  34. * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
  35. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  36. * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  37. * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
  38. * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
  39. *
  40. * You should have received a copy of the GNU General Public License
  41. * along with this program; if not, write to the Free Software
  42. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  43. *
  44. *
  45. * 10/23/2000 - Alpha Release
  46. * First release to the public
  47. */
  48. #include <linux/version.h>
  49. #include <linux/module.h>
  50. #include <linux/kernel.h>
  51. #include <linux/fs.h>
  52. #include <linux/init.h>
  53. #include <linux/major.h>
  54. #include <linux/miscdevice.h>
  55. #include <linux/proc_fs.h>
  56. #include <linux/serial.h>
  57. #include <linux/sched.h>
  58. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  59. #include <linux/spinlock.h>
  60. #else
  61. #include <asm/spinlock.h>
  62. #endif
  63. #include <linux/delay.h>
  64. #include "smapi.h"
  65. #include "mwavedd.h"
  66. #include "3780i.h"
  67. #include "tp3780i.h"
  68. #ifndef __exit
  69. #define __exit
  70. #endif
  71. MODULE_DESCRIPTION("3780i Advanced Communications Processor (Mwave) driver");
  72. MODULE_AUTHOR("Mike Sullivan and Paul Schroeder");
  73. MODULE_LICENSE("GPL");
  74. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  75. static int mwave_get_info(char *buf, char **start, off_t offset, int len);
  76. #else
  77. static int mwave_read_proc(char *buf, char **start, off_t offset, int xlen, int unused);
  78. static struct proc_dir_entry mwave_proc = {
  79. 0,                      /* unsigned short low_ino */
  80. 5,                      /* unsigned short namelen */
  81. "mwave",                /* const char *name */
  82. S_IFREG | S_IRUGO,      /* mode_t mode */
  83. 1,                      /* nlink_t nlink */
  84. 0,                      /* uid_t uid */
  85. 0,                      /* gid_t gid */
  86. 0,                      /* unsigned long size */
  87. NULL,                   /* struct inode_operations *ops */
  88. &mwave_read_proc        /* int (*get_info) (...) */
  89. };
  90. #endif
  91. /*
  92. * These parameters support the setting of MWave resources. Note that no
  93. * checks are made against other devices (ie. superio) for conflicts.
  94. * We'll depend on users using the tpctl utility to do that for now
  95. */
  96. int mwave_debug = 0;
  97. int mwave_3780i_irq = 0;
  98. int mwave_3780i_io = 0;
  99. int mwave_uart_irq = 0;
  100. int mwave_uart_io = 0;
  101. MODULE_PARM(mwave_debug, "i");
  102. MODULE_PARM(mwave_3780i_irq, "i");
  103. MODULE_PARM(mwave_3780i_io, "i");
  104. MODULE_PARM(mwave_uart_irq, "i");
  105. MODULE_PARM(mwave_uart_io, "i");
  106. static int mwave_open(struct inode *inode, struct file *file);
  107. static int mwave_close(struct inode *inode, struct file *file);
  108. static int mwave_ioctl(struct inode *inode, struct file *filp,
  109.                        unsigned int iocmd, unsigned long ioarg);
  110. MWAVE_DEVICE_DATA mwave_s_mdd;
  111. static int mwave_open(struct inode *inode, struct file *file)
  112. {
  113. unsigned int retval = 0;
  114. PRINTK_3(TRACE_MWAVE,
  115. "mwavedd::mwave_open, entry inode %x file %xn",
  116. (int) inode, (int) file);
  117. PRINTK_2(TRACE_MWAVE,
  118. "mwavedd::mwave_open, exit return retval %xn", retval);
  119. MOD_INC_USE_COUNT;
  120. return retval;
  121. }
  122. static int mwave_close(struct inode *inode, struct file *file)
  123. {
  124. unsigned int retval = 0;
  125. PRINTK_3(TRACE_MWAVE,
  126. "mwavedd::mwave_close, entry inode %x file %xn",
  127. (int) inode, (int) file);
  128. PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_close, exit retval %xn",
  129. retval);
  130. MOD_DEC_USE_COUNT;
  131. return retval;
  132. }
  133. static int mwave_ioctl(struct inode *inode, struct file *file,
  134.                        unsigned int iocmd, unsigned long ioarg)
  135. {
  136. unsigned int retval = 0;
  137. pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
  138. PRINTK_5(TRACE_MWAVE,
  139. "mwavedd::mwave_ioctl, entry inode %x file %x cmd %x arg %xn",
  140. (int) inode, (int) file, iocmd, (int) ioarg);
  141. switch (iocmd) {
  142. case IOCTL_MW_RESET:
  143. PRINTK_1(TRACE_MWAVE,
  144. "mwavedd::mwave_ioctl, IOCTL_MW_RESET calling tp3780I_ResetDSPn");
  145. retval = tp3780I_ResetDSP(&pDrvData->rBDData);
  146. PRINTK_2(TRACE_MWAVE,
  147. "mwavedd::mwave_ioctl, IOCTL_MW_RESET retval %x from tp3780I_ResetDSPn",
  148. retval);
  149. break;
  150. case IOCTL_MW_RUN:
  151. PRINTK_1(TRACE_MWAVE,
  152. "mwavedd::mwave_ioctl, IOCTL_MW_RUN calling tp3780I_StartDSPn");
  153. retval = tp3780I_StartDSP(&pDrvData->rBDData);
  154. PRINTK_2(TRACE_MWAVE,
  155. "mwavedd::mwave_ioctl, IOCTL_MW_RUN retval %x from tp3780I_StartDSPn",
  156. retval);
  157. break;
  158. case IOCTL_MW_DSP_ABILITIES: {
  159. MW_ABILITIES rAbilities;
  160. PRINTK_1(TRACE_MWAVE,
  161. "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES calling tp3780I_QueryAbilitiesn");
  162. retval = tp3780I_QueryAbilities(&pDrvData->rBDData, &rAbilities);
  163. PRINTK_2(TRACE_MWAVE,
  164. "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES retval %x from tp3780I_QueryAbilitiesn",
  165. retval);
  166. if (retval == 0) {
  167. if( copy_to_user((char *) ioarg, (char *) &rAbilities, sizeof(MW_ABILITIES)) )
  168. return -EFAULT;
  169. }
  170. PRINTK_2(TRACE_MWAVE,
  171. "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES exit retval %xn",
  172. retval);
  173. }
  174. break;
  175. case IOCTL_MW_READ_DATA:
  176. case IOCTL_MW_READCLEAR_DATA: {
  177. MW_READWRITE rReadData;
  178. unsigned short *pusBuffer = 0;
  179. if( copy_from_user((char *) &rReadData, (char *) ioarg, sizeof(MW_READWRITE)) )
  180. return -EFAULT;
  181. pusBuffer = (unsigned short *) (rReadData.pBuf);
  182. PRINTK_4(TRACE_MWAVE,
  183. "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA, size %lx, ioarg %lx pusBuffer %pn",
  184. rReadData.ulDataLength, ioarg, pusBuffer);
  185. retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd,
  186. (void *) pusBuffer, rReadData.ulDataLength, rReadData.usDspAddress);
  187. }
  188. break;
  189. case IOCTL_MW_READ_INST: {
  190. MW_READWRITE rReadData;
  191. unsigned short *pusBuffer = 0;
  192. if( copy_from_user((char *) &rReadData, (char *) ioarg, sizeof(MW_READWRITE)) )
  193. return -EFAULT;
  194. pusBuffer = (unsigned short *) (rReadData.pBuf);
  195. PRINTK_4(TRACE_MWAVE,
  196. "mwavedd::mwave_ioctl IOCTL_MW_READ_INST, size %lx, ioarg %lx pusBuffer %pn",
  197. rReadData.ulDataLength / 2, ioarg,
  198. pusBuffer);
  199. retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
  200. iocmd, pusBuffer,
  201. rReadData.ulDataLength / 2,
  202. rReadData.usDspAddress);
  203. }
  204. break;
  205. case IOCTL_MW_WRITE_DATA: {
  206. MW_READWRITE rWriteData;
  207. unsigned short *pusBuffer = 0;
  208. if( copy_from_user((char *) &rWriteData, (char *) ioarg, sizeof(MW_READWRITE)) )
  209. return -EFAULT;
  210. pusBuffer = (unsigned short *) (rWriteData.pBuf);
  211. PRINTK_4(TRACE_MWAVE,
  212. "mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA, size %lx, ioarg %lx pusBuffer %pn",
  213. rWriteData.ulDataLength, ioarg,
  214. pusBuffer);
  215. retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd,
  216. pusBuffer, rWriteData.ulDataLength, rWriteData.usDspAddress);
  217. }
  218. break;
  219. case IOCTL_MW_WRITE_INST: {
  220. MW_READWRITE rWriteData;
  221. unsigned short *pusBuffer = 0;
  222. if( copy_from_user((char *) &rWriteData, (char *) ioarg, sizeof(MW_READWRITE)) )
  223. return -EFAULT;
  224. pusBuffer = (unsigned short *) (rWriteData.pBuf);
  225. PRINTK_4(TRACE_MWAVE,
  226. "mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST, size %lx, ioarg %lx pusBuffer %pn",
  227. rWriteData.ulDataLength, ioarg,
  228. pusBuffer);
  229. retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, iocmd,
  230. pusBuffer, rWriteData.ulDataLength, rWriteData.usDspAddress);
  231. }
  232. break;
  233. case IOCTL_MW_REGISTER_IPC: {
  234. unsigned int ipcnum = (unsigned int) ioarg;
  235. PRINTK_3(TRACE_MWAVE,
  236. "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC ipcnum %x entry usIntCount %xn",
  237. ipcnum,
  238. pDrvData->IPCs[ipcnum].usIntCount);
  239. if (ipcnum > 16) {
  240. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: IOCTL_MW_REGISTER_IPC: Error: Invalid ipcnum %xn", ipcnum);
  241. return -EINVAL;
  242. }
  243. pDrvData->IPCs[ipcnum].bIsHere = FALSE;
  244. pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
  245. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  246. current->nice = -20; /* boost to provide priority timing */
  247. #else
  248. current->priority = 0x28; /* boost to provide priority timing */
  249. #endif
  250. PRINTK_2(TRACE_MWAVE,
  251. "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC ipcnum %x exitn",
  252. ipcnum);
  253. }
  254. break;
  255. case IOCTL_MW_GET_IPC: {
  256. unsigned int ipcnum = (unsigned int) ioarg;
  257. spinlock_t ipc_lock = SPIN_LOCK_UNLOCKED;
  258. unsigned long flags;
  259. PRINTK_3(TRACE_MWAVE,
  260. "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC ipcnum %x, usIntCount %xn",
  261. ipcnum,
  262. pDrvData->IPCs[ipcnum].usIntCount);
  263. if (ipcnum > 16) {
  264. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: IOCTL_MW_GET_IPC: Error: Invalid ipcnum %xn", ipcnum);
  265. return -EINVAL;
  266. }
  267. if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
  268. PRINTK_2(TRACE_MWAVE,
  269. "mwavedd::mwave_ioctl, thread for ipc %x going to sleepn",
  270. ipcnum);
  271. spin_lock_irqsave(&ipc_lock, flags);
  272. /* check whether an event was signalled by */
  273. /* the interrupt handler while we were gone */
  274. if (pDrvData->IPCs[ipcnum].usIntCount == 1) { /* first int has occurred (race condition) */
  275. pDrvData->IPCs[ipcnum].usIntCount = 2; /* first int has been handled */
  276. spin_unlock_irqrestore(&ipc_lock, flags);
  277. PRINTK_2(TRACE_MWAVE,
  278. "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC ipcnum %x handling first intn",
  279. ipcnum);
  280. } else { /* either 1st int has not yet occurred, or we have already handled the first int */
  281. pDrvData->IPCs[ipcnum].bIsHere = TRUE;
  282. interruptible_sleep_on(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
  283. pDrvData->IPCs[ipcnum].bIsHere = FALSE;
  284. if (pDrvData->IPCs[ipcnum].usIntCount == 1) {
  285. pDrvData->IPCs[ipcnum].
  286. usIntCount = 2;
  287. }
  288. spin_unlock_irqrestore(&ipc_lock, flags);
  289. PRINTK_2(TRACE_MWAVE,
  290. "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC ipcnum %x woke up and returning to applicationn",
  291. ipcnum);
  292. }
  293. PRINTK_2(TRACE_MWAVE,
  294. "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC, returning thread for ipc %x processingn",
  295. ipcnum);
  296. }
  297. }
  298. break;
  299. case IOCTL_MW_UNREGISTER_IPC: {
  300. unsigned int ipcnum = (unsigned int) ioarg;
  301. PRINTK_2(TRACE_MWAVE,
  302. "mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC ipcnum %xn",
  303. ipcnum);
  304. if (ipcnum > 16) {
  305. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: IOCTL_MW_UNREGISTER_IPC: Error: Invalid ipcnum %xn", ipcnum);
  306. return -EINVAL;
  307. }
  308. if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
  309. pDrvData->IPCs[ipcnum].bIsEnabled = FALSE;
  310. if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) {
  311. wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
  312. }
  313. }
  314. }
  315. break;
  316. default:
  317. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: Error: Unrecognized iocmd %xn", iocmd);
  318. return -ENOTTY;
  319. break;
  320. } /* switch */
  321. PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, exit retval %xn", retval);
  322. return retval;
  323. }
  324. static ssize_t mwave_read(struct file *file, char *buf, size_t count,
  325.                           loff_t * ppos)
  326. {
  327. PRINTK_5(TRACE_MWAVE,
  328. "mwavedd::mwave_read entry file %p, buf %p, count %x ppos %pn",
  329. file, buf, count, ppos);
  330. return -EINVAL;
  331. }
  332. static ssize_t mwave_write(struct file *file, const char *buf,
  333.                            size_t count, loff_t * ppos)
  334. {
  335. PRINTK_5(TRACE_MWAVE,
  336. "mwavedd::mwave_write entry file %p, buf %p, count %x ppos %pn",
  337. file, buf, count, ppos);
  338. return -EINVAL;
  339. }
  340. static int register_serial_portandirq(unsigned int port, int irq)
  341. {
  342. struct serial_struct serial;
  343. switch ( port ) {
  344. case 0x3f8:
  345. case 0x2f8:
  346. case 0x3e8:
  347. case 0x2e8:
  348. /* OK */
  349. break;
  350. default:
  351. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::register_serial_portandirq: Error: Illegal port %xn", port );
  352. return -1;
  353. } /* switch */
  354. /* port is okay */
  355. switch ( irq ) {
  356. case 3:
  357. case 4:
  358. case 5:
  359. case 7:
  360. /* OK */
  361. break;
  362. default:
  363. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::register_serial_portandirq: Error: Illegal irq %xn", irq );
  364. return -1;
  365. } /* switch */
  366. /* irq is okay */
  367. memset(&serial, 0, sizeof(serial));
  368. serial.port = port;
  369. serial.irq = irq;
  370. serial.flags = ASYNC_SHARE_IRQ;
  371. return register_serial(&serial);
  372. }
  373. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  374. static struct file_operations mwave_fops = {
  375. owner:THIS_MODULE,
  376. read:mwave_read,
  377. write:mwave_write,
  378. ioctl:mwave_ioctl,
  379. open:mwave_open,
  380. release:mwave_close
  381. };
  382. #else
  383. static struct file_operations mwave_fops = {
  384. NULL, /* lseek */
  385. mwave_read, /* read */
  386. mwave_write, /* write */
  387. NULL, /* readdir */
  388. NULL, /* poll */
  389. mwave_ioctl, /* ioctl */
  390. NULL, /* mmap */
  391. mwave_open, /* open */
  392. NULL, /* flush */
  393. mwave_close /* release */
  394. };
  395. #endif
  396. static struct miscdevice mwave_misc_dev = { MWAVE_MINOR, "mwave", &mwave_fops };
  397. /*
  398. * mwave_init is called on module load
  399. *
  400. * mwave_exit is called on module unload
  401. * mwave_exit is also used to clean up after an aborted mwave_init
  402. */
  403. static void mwave_exit(void)
  404. {
  405. pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
  406. PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_exit entryn");
  407. if (pDrvData->bProcEntryCreated) {
  408. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  409. remove_proc_entry("mwave", NULL);
  410. #else
  411. proc_unregister(&proc_root, mwave_proc.low_ino);
  412. #endif
  413. }
  414. if ( pDrvData->sLine >= 0 ) {
  415. unregister_serial(pDrvData->sLine);
  416. }
  417. if (pDrvData->bMwaveDevRegistered) {
  418. misc_deregister(&mwave_misc_dev);
  419. }
  420. if (pDrvData->bDSPEnabled) {
  421. tp3780I_DisableDSP(&pDrvData->rBDData);
  422. }
  423. if (pDrvData->bResourcesClaimed) {
  424. tp3780I_ReleaseResources(&pDrvData->rBDData);
  425. }
  426. if (pDrvData->bBDInitialized) {
  427. tp3780I_Cleanup(&pDrvData->rBDData);
  428. }
  429. PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_exit exitn");
  430. }
  431. module_exit(mwave_exit);
  432. static int __init mwave_init(void)
  433. {
  434. int i;
  435. int retval = 0;
  436. unsigned int resultMiscRegister;
  437. pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
  438. memset(&mwave_s_mdd, 0, sizeof(MWAVE_DEVICE_DATA));
  439. PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_init entryn");
  440. pDrvData->bBDInitialized = FALSE;
  441. pDrvData->bResourcesClaimed = FALSE;
  442. pDrvData->bDSPEnabled = FALSE;
  443. pDrvData->bDSPReset = FALSE;
  444. pDrvData->bMwaveDevRegistered = FALSE;
  445. pDrvData->sLine = -1;
  446. pDrvData->bProcEntryCreated = FALSE;
  447. for (i = 0; i < 16; i++) {
  448. pDrvData->IPCs[i].bIsEnabled = FALSE;
  449. pDrvData->IPCs[i].bIsHere = FALSE;
  450. pDrvData->IPCs[i].usIntCount = 0; /* no ints received yet */
  451. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  452. init_waitqueue_head(&pDrvData->IPCs[i].ipc_wait_queue);
  453. #endif
  454. }
  455. retval = tp3780I_InitializeBoardData(&pDrvData->rBDData);
  456. PRINTK_2(TRACE_MWAVE,
  457. "mwavedd::mwave_init, return from tp3780I_InitializeBoardData retval %xn",
  458. retval);
  459. if (retval) {
  460. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_init: Error: Failed to initialize board datan");
  461. goto cleanup_error;
  462. }
  463. pDrvData->bBDInitialized = TRUE;
  464. retval = tp3780I_CalcResources(&pDrvData->rBDData);
  465. PRINTK_2(TRACE_MWAVE,
  466. "mwavedd::mwave_init, return from tp3780I_CalcResources retval %xn",
  467. retval);
  468. if (retval) {
  469. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to calculate resourcesn");
  470. goto cleanup_error;
  471. }
  472. retval = tp3780I_ClaimResources(&pDrvData->rBDData);
  473. PRINTK_2(TRACE_MWAVE,
  474. "mwavedd::mwave_init, return from tp3780I_ClaimResources retval %xn",
  475. retval);
  476. if (retval) {
  477. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to claim resourcesn");
  478. goto cleanup_error;
  479. }
  480. pDrvData->bResourcesClaimed = TRUE;
  481. retval = tp3780I_EnableDSP(&pDrvData->rBDData);
  482. PRINTK_2(TRACE_MWAVE,
  483. "mwavedd::mwave_init, return from tp3780I_EnableDSP retval %xn",
  484. retval);
  485. if (retval) {
  486. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to enable DSPn");
  487. goto cleanup_error;
  488. }
  489. pDrvData->bDSPEnabled = TRUE;
  490. resultMiscRegister = misc_register(&mwave_misc_dev);
  491. if (resultMiscRegister < 0) {
  492. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to register misc devicen");
  493. goto cleanup_error;
  494. }
  495. pDrvData->bMwaveDevRegistered = TRUE;
  496. pDrvData->sLine = register_serial_portandirq(
  497. pDrvData->rBDData.rDspSettings.usUartBaseIO,
  498. pDrvData->rBDData.rDspSettings.usUartIrq
  499. );
  500. if (pDrvData->sLine < 0) {
  501. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to register serial drivern");
  502. goto cleanup_error;
  503. }
  504. /* uart is registered */
  505. if (
  506. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  507. !create_proc_info_entry("mwave", 0, NULL, mwave_get_info)
  508. #else
  509. proc_register(&proc_root, &mwave_proc)
  510. #endif
  511. ) {
  512. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_init: Error: Failed to register /proc/mwaven");
  513. goto cleanup_error;
  514. }
  515. pDrvData->bProcEntryCreated = TRUE;
  516. /* SUCCESS! */
  517. return 0;
  518. cleanup_error:
  519. PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_init: Error: Failed to initializen");
  520. mwave_exit(); /* clean up */
  521. return -EIO;
  522. }
  523. module_init(mwave_init);
  524. /*
  525. * proc entry stuff added by Ian Pilcher <pilcher@us.ibm.com>
  526. */
  527. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  528. static int mwave_get_info(char *buf, char **start, off_t offset, int len)
  529. {
  530. DSP_3780I_CONFIG_SETTINGS *pSettings = &mwave_s_mdd.rBDData.rDspSettings;
  531. char *out = buf;
  532. out += sprintf(out, "3780i_IRQ %in", pSettings->usDspIrq);
  533. out += sprintf(out, "3780i_DMA %in", pSettings->usDspDma);
  534. out += sprintf(out, "3780i_IO  %#.4xn", pSettings->usDspBaseIO);
  535. out += sprintf(out, "UART_IRQ  %in", pSettings->usUartIrq);
  536. out += sprintf(out, "UART_IO   %#.4xn", pSettings->usUartBaseIO);
  537. return out - buf;
  538. }
  539. #else /* kernel version < 2.4.0 */
  540. static int mwave_read_proc(char *buf, char **start, off_t offset,
  541.                            int xlen, int unused)
  542. {
  543. DSP_3780I_CONFIG_SETTINGS *pSettings = &mwave_s_mdd.rBDData.rDspSettings;
  544. int len;
  545. len = sprintf(buf,        "3780i_IRQ %in", pSettings->usDspIrq);
  546. len += sprintf(&buf[len], "3780i_DMA %in", pSettings->usDspDma);
  547. len += sprintf(&buf[len], "3780i_IO  %#.4xn", pSettings->usDspBaseIO);
  548. len += sprintf(&buf[len], "UART_IRQ  %in", pSettings->usUartIrq);
  549. len += sprintf(&buf[len], "UART_IO   %#.4xn", pSettings->usUartBaseIO);
  550. return len;
  551. }
  552. #endif