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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * drivers/sbus/char/vfc_dev.c
  3.  *
  4.  * Driver for the Videopix Frame Grabber.
  5.  * 
  6.  * In order to use the VFC you need to program the video controller
  7.  * chip. This chip is the Phillips SAA9051.  You need to call their
  8.  * documentation ordering line to get the docs.
  9.  *
  10.  * There is very little documentation on the VFC itself.  There is
  11.  * some useful info that can be found in the manuals that come with
  12.  * the card.  I will hopefully write some better docs at a later date.
  13.  *
  14.  * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu)
  15.  * */
  16. #include <linux/module.h>
  17. #include <linux/kernel.h>
  18. #include <linux/string.h>
  19. #include <linux/slab.h>
  20. #include <linux/errno.h>
  21. #include <linux/sched.h>
  22. #include <linux/fs.h>
  23. #include <linux/smp_lock.h>
  24. #include <linux/delay.h>
  25. #include <linux/spinlock.h>
  26. #include <asm/openprom.h>
  27. #include <asm/oplib.h>
  28. #include <asm/io.h>
  29. #include <asm/system.h>
  30. #include <asm/sbus.h>
  31. #include <asm/page.h>
  32. #include <asm/pgtable.h>
  33. #include <asm/uaccess.h>
  34. #define VFC_MAJOR (60)
  35. #if 0
  36. #define VFC_IOCTL_DEBUG
  37. #endif
  38. #include "vfc.h"
  39. #include <asm/vfc_ioctls.h>
  40. static struct file_operations vfc_fops;
  41. static devfs_handle_t devfs_handle;  /*  For the directory  */
  42. struct vfc_dev **vfc_dev_lst;
  43. static char vfcstr[]="vfc";
  44. static unsigned char saa9051_init_array[VFC_SAA9051_NR] = {
  45. 0x00, 0x64, 0x72, 0x52,
  46. 0x36, 0x18, 0xff, 0x20,
  47. 0xfc, 0x77, 0xe3, 0x50,
  48. 0x3e
  49. };
  50. void vfc_lock_device(struct vfc_dev *dev)
  51. {
  52. down(&dev->device_lock_sem);
  53. }
  54. void vfc_unlock_device(struct vfc_dev *dev)
  55. {
  56. up(&dev->device_lock_sem);
  57. }
  58. void vfc_captstat_reset(struct vfc_dev *dev) 
  59. {
  60. dev->control_reg |= VFC_CONTROL_CAPTRESET;
  61. sbus_writel(dev->control_reg, &dev->regs->control);
  62. dev->control_reg &= ~VFC_CONTROL_CAPTRESET;
  63. sbus_writel(dev->control_reg, &dev->regs->control);
  64. dev->control_reg |= VFC_CONTROL_CAPTRESET;
  65. sbus_writel(dev->control_reg, &dev->regs->control);
  66. }
  67. void vfc_memptr_reset(struct vfc_dev *dev) 
  68. {
  69. dev->control_reg |= VFC_CONTROL_MEMPTR;
  70. sbus_writel(dev->control_reg, &dev->regs->control);
  71. dev->control_reg &= ~VFC_CONTROL_MEMPTR;
  72. sbus_writel(dev->control_reg, &dev->regs->control);
  73. dev->control_reg |= VFC_CONTROL_MEMPTR; 
  74. sbus_writel(dev->control_reg, &dev->regs->control);
  75. }
  76. int vfc_csr_init(struct vfc_dev *dev)
  77. {
  78. dev->control_reg = 0x80000000;
  79. sbus_writel(dev->control_reg, &dev->regs->control);
  80. udelay(200); 
  81. dev->control_reg &= ~0x80000000;
  82. sbus_writel(dev->control_reg, &dev->regs->control);
  83. udelay(100); 
  84. sbus_writel(0x0f000000, &dev->regs->i2c_magic2);
  85. vfc_memptr_reset(dev);
  86. dev->control_reg &= ~VFC_CONTROL_DIAGMODE;
  87. dev->control_reg &= ~VFC_CONTROL_CAPTURE;
  88. dev->control_reg |= 0x40000000;
  89. sbus_writel(dev->control_reg, &dev->regs->control);
  90. vfc_captstat_reset(dev);
  91. return 0;
  92. }
  93. int vfc_saa9051_init(struct vfc_dev *dev)
  94. {
  95. int i;
  96. for (i = 0; i < VFC_SAA9051_NR; i++)
  97. dev->saa9051_state_array[i] = saa9051_init_array[i];
  98. vfc_i2c_sendbuf(dev,VFC_SAA9051_ADDR,
  99. dev->saa9051_state_array, VFC_SAA9051_NR);
  100. return 0;
  101. }
  102. int init_vfc_hw(struct vfc_dev *dev) 
  103. {
  104. vfc_lock_device(dev);
  105. vfc_csr_init(dev);
  106. vfc_pcf8584_init(dev);
  107. vfc_init_i2c_bus(dev); /* hopefully this doesn't undo the magic
  108.   sun code above*/
  109. vfc_saa9051_init(dev);
  110. vfc_unlock_device(dev);
  111. return 0; 
  112. }
  113. int init_vfc_devstruct(struct vfc_dev *dev, int instance) 
  114. {
  115. dev->instance=instance;
  116. init_MUTEX(&dev->device_lock_sem);
  117. dev->control_reg=0;
  118. init_waitqueue_head(&dev->poll_wait);
  119. dev->busy=0;
  120. return 0;
  121. }
  122. int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance)
  123. {
  124. char devname[8];
  125. if(dev == NULL) {
  126. printk(KERN_ERR "VFC: Bogus pointer passedn");
  127. return -ENOMEM;
  128. }
  129. printk("Initializing vfc%dn",instance);
  130. dev->regs = NULL;
  131. dev->regs = (volatile struct vfc_regs *)
  132. sbus_ioremap(&sdev->resource[0], 0,
  133.      sizeof(struct vfc_regs), vfcstr);
  134. dev->which_io = sdev->reg_addrs[0].which_io;
  135. dev->phys_regs = (struct vfc_regs *) sdev->reg_addrs[0].phys_addr;
  136. if (dev->regs == NULL)
  137. return -EIO;
  138. printk("vfc%d: registers mapped at phys_addr: 0x%lxn    virt_addr: 0x%lxn",
  139.        instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs);
  140. if (init_vfc_devstruct(dev, instance))
  141. return -EINVAL;
  142. if (init_vfc_hw(dev))
  143. return -EIO;
  144. sprintf (devname, "%d", instance);
  145. dev->de = devfs_register (devfs_handle, devname, DEVFS_FL_DEFAULT,
  146.   VFC_MAJOR, instance,
  147.   S_IFCHR | S_IRUSR | S_IWUSR,
  148.   &vfc_fops, NULL);
  149. return 0;
  150. }
  151. struct vfc_dev *vfc_get_dev_ptr(int instance) 
  152. {
  153. return vfc_dev_lst[instance];
  154. }
  155. static spinlock_t vfc_dev_lock = SPIN_LOCK_UNLOCKED;
  156. static int vfc_open(struct inode *inode, struct file *file) 
  157. {
  158. struct vfc_dev *dev;
  159. spin_lock(&vfc_dev_lock);
  160. dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
  161. if (dev == NULL) {
  162. spin_unlock(&vfc_dev_lock);
  163. return -ENODEV;
  164. }
  165. if (dev->busy) {
  166. spin_unlock(&vfc_dev_lock);
  167. return -EBUSY;
  168. }
  169. dev->busy = 1;
  170. spin_unlock(&vfc_dev_lock);
  171. vfc_lock_device(dev);
  172. vfc_csr_init(dev);
  173. vfc_pcf8584_init(dev);
  174. vfc_init_i2c_bus(dev);
  175. vfc_saa9051_init(dev);
  176. vfc_memptr_reset(dev);
  177. vfc_captstat_reset(dev);
  178. vfc_unlock_device(dev);
  179. return 0;
  180. }
  181. static int vfc_release(struct inode *inode,struct file *file) 
  182. {
  183. struct vfc_dev *dev;
  184. spin_lock(&vfc_dev_lock);
  185. dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
  186. if (!dev || !dev->busy) {
  187. spin_unlock(&vfc_dev_lock);
  188. return -EINVAL;
  189. }
  190. dev->busy = 0;
  191. spin_unlock(&vfc_dev_lock);
  192. return 0;
  193. }
  194. static int vfc_debug(struct vfc_dev *dev, int cmd, unsigned long arg) 
  195. {
  196. struct vfc_debug_inout inout;
  197. unsigned char *buffer;
  198. if (!capable(CAP_SYS_ADMIN))
  199. return -EPERM;
  200. switch(cmd) {
  201. case VFC_I2C_SEND:
  202. if(copy_from_user(&inout, (void *)arg, sizeof(inout)))
  203. return -EFAULT;
  204. buffer = kmalloc(inout.len*sizeof(char), GFP_KERNEL);
  205. if (buffer == NULL)
  206. return -ENOMEM;
  207. if(copy_from_user(buffer, inout.buffer, 
  208.   inout.len*sizeof(char))) {
  209. kfree(buffer);
  210. return -EFAULT;
  211. }
  212. vfc_lock_device(dev);
  213. inout.ret=
  214. vfc_i2c_sendbuf(dev,inout.addr & 0xff,
  215. inout.buffer,inout.len);
  216. if (copy_to_user((void *)arg,&inout,sizeof(inout))) {
  217. kfree(buffer);
  218. return -EFAULT;
  219. }
  220. vfc_unlock_device(dev);
  221. break;
  222. case VFC_I2C_RECV:
  223. if (copy_from_user(&inout, (void *)arg, sizeof(inout)))
  224. return -EFAULT;
  225. buffer = kmalloc(inout.len, GFP_KERNEL);
  226. if (buffer == NULL)
  227. return -ENOMEM;
  228. memset(buffer,0,inout.len*sizeof(char));
  229. vfc_lock_device(dev);
  230. inout.ret=
  231. vfc_i2c_recvbuf(dev,inout.addr & 0xff
  232. ,buffer,inout.len);
  233. vfc_unlock_device(dev);
  234. if (copy_to_user(inout.buffer, buffer, inout.len)) {
  235. kfree(buffer);
  236. return -EFAULT;
  237. }
  238. if (copy_to_user((void *)arg,&inout,sizeof(inout))) {
  239. kfree(buffer);
  240. return -EFAULT;
  241. }
  242. kfree(buffer);
  243. break;
  244. default:
  245. return -EINVAL;
  246. };
  247. return 0;
  248. }
  249. int vfc_capture_start(struct vfc_dev *dev) 
  250. {
  251. vfc_captstat_reset(dev);
  252. dev->control_reg = sbus_readl(&dev->regs->control);
  253. if((dev->control_reg & VFC_STATUS_CAPTURE)) {
  254. printk(KERN_ERR "vfc%d: vfc capture status not resetn",
  255.        dev->instance);
  256. return -EIO;
  257. }
  258. vfc_lock_device(dev);
  259. dev->control_reg &= ~VFC_CONTROL_CAPTURE;
  260. sbus_writel(dev->control_reg, &dev->regs->control);
  261. dev->control_reg |= VFC_CONTROL_CAPTURE;
  262. sbus_writel(dev->control_reg, &dev->regs->control);
  263. dev->control_reg &= ~VFC_CONTROL_CAPTURE;
  264. sbus_writel(dev->control_reg, &dev->regs->control);
  265. vfc_unlock_device(dev);
  266. return 0;
  267. }
  268. int vfc_capture_poll(struct vfc_dev *dev) 
  269. {
  270. int timeout = 1000;
  271. while (!timeout--) {
  272. if (dev->regs->control & VFC_STATUS_CAPTURE)
  273. break;
  274. vfc_i2c_delay_no_busy(dev, 100);
  275. }
  276. if(!timeout) {
  277. printk(KERN_WARNING "vfc%d: capture timed outn",
  278.        dev->instance);
  279. return -ETIMEDOUT;
  280. }
  281. return 0;
  282. }
  283. static int vfc_set_control_ioctl(struct inode *inode, struct file *file, 
  284.   struct vfc_dev *dev, unsigned long arg) 
  285. {
  286. int setcmd, ret = 0;
  287. if (copy_from_user(&setcmd,(void *)arg,sizeof(unsigned int)))
  288. return -EFAULT;
  289. VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%xn",
  290. dev->instance,setcmd));
  291. switch(setcmd) {
  292. case MEMPRST:
  293. vfc_lock_device(dev);
  294. vfc_memptr_reset(dev);
  295. vfc_unlock_device(dev);
  296. ret=0;
  297. break;
  298. case CAPTRCMD:
  299. vfc_capture_start(dev);
  300. vfc_capture_poll(dev);
  301. break;
  302. case DIAGMODE:
  303. if(capable(CAP_SYS_ADMIN)) {
  304. vfc_lock_device(dev);
  305. dev->control_reg |= VFC_CONTROL_DIAGMODE;
  306. sbus_writel(dev->control_reg, &dev->regs->control);
  307. vfc_unlock_device(dev);
  308. ret = 0;
  309. } else {
  310. ret = -EPERM; 
  311. }
  312. break;
  313. case NORMMODE:
  314. vfc_lock_device(dev);
  315. dev->control_reg &= ~VFC_CONTROL_DIAGMODE;
  316. sbus_writel(dev->control_reg, &dev->regs->control);
  317. vfc_unlock_device(dev);
  318. ret = 0;
  319. break;
  320. case CAPTRSTR:
  321. vfc_capture_start(dev);
  322. ret = 0;
  323. break;
  324. case CAPTRWAIT:
  325. vfc_capture_poll(dev);
  326. ret = 0;
  327. break;
  328. default:
  329. ret = -EINVAL;
  330. break;
  331. };
  332. return ret;
  333. }
  334. int vfc_port_change_ioctl(struct inode *inode, struct file *file, 
  335.   struct vfc_dev *dev, unsigned long arg) 
  336. {
  337. int ret = 0;
  338. int cmd;
  339. if(copy_from_user(&cmd, (void *)arg, sizeof(unsigned int))) {
  340. VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to "
  341. "vfc_port_change_ioctln",
  342. dev->instance));
  343. return -EFAULT;
  344. }
  345. VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%xn",
  346. dev->instance, cmd));
  347. switch(cmd) {
  348. case 1:
  349. case 2:
  350. VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x72; 
  351. VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x52;
  352. VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0x36;
  353. VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0x18;
  354. VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = VFC_SAA9051_BP2;
  355. VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_CT | VFC_SAA9051_SS3;
  356. VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0x3e;
  357. break;
  358. case 3:
  359. VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x3a;
  360. VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x17;
  361. VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0xfa;
  362. VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0xde;
  363. VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) =
  364. VFC_SAA9051_BY | VFC_SAA9051_PF | VFC_SAA9051_BP2;
  365. VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_YC;
  366. VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0;
  367. VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &=
  368. ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
  369. break;
  370. default:
  371. ret = -EINVAL;
  372. return ret;
  373. break;
  374. }
  375. switch(cmd) {
  376. case 1:
  377. VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |=
  378. (VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
  379. break;
  380. case 2:
  381. VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &=
  382. ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
  383. VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= VFC_SAA9051_SS0; 
  384. break;
  385. case 3:
  386. break;
  387. default:
  388. ret = -EINVAL;
  389. return ret;
  390. break;
  391. }
  392. VFC_SAA9051_SA(dev,VFC_SAA9051_C3) &= ~(VFC_SAA9051_SS2);
  393. ret=vfc_update_saa9051(dev);
  394. udelay(500);
  395. VFC_SAA9051_SA(dev,VFC_SAA9051_C3) |= (VFC_SAA9051_SS2);
  396. ret=vfc_update_saa9051(dev);
  397. return ret;
  398. }
  399. int vfc_set_video_ioctl(struct inode *inode, struct file *file, 
  400. struct vfc_dev *dev, unsigned long arg) 
  401. {
  402. int ret = 0;
  403. int cmd;
  404. if(copy_from_user(&cmd, (void *)arg, sizeof(unsigned int))) {
  405. VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to "
  406. "vfc_set_video_ioctln",
  407. dev->instance));
  408. return ret;
  409. }
  410. VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%xn",
  411. dev->instance, cmd));
  412. switch(cmd) {
  413. case STD_NTSC:
  414. VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~VFC_SAA9051_ALT;
  415. VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_YPN | 
  416. VFC_SAA9051_CCFR0 | VFC_SAA9051_CCFR1 | VFC_SAA9051_FS;
  417. ret = vfc_update_saa9051(dev);
  418. break;
  419. case STD_PAL:
  420. VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_YPN | 
  421. VFC_SAA9051_CCFR1 | 
  422. VFC_SAA9051_CCFR0 |
  423. VFC_SAA9051_FS);
  424. VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_ALT;
  425. ret = vfc_update_saa9051(dev);
  426. break;
  427. case COLOR_ON:
  428. VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_CO;
  429. VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) &=
  430. ~(VFC_SAA9051_BY | VFC_SAA9051_PF);
  431. ret = vfc_update_saa9051(dev);
  432. break;
  433. case MONO:
  434. VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_CO);
  435. VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) |=
  436. (VFC_SAA9051_BY | VFC_SAA9051_PF);
  437. ret = vfc_update_saa9051(dev);
  438. break;
  439. default:
  440. ret = -EINVAL;
  441. break;
  442. };
  443. return ret;
  444. }
  445. int vfc_get_video_ioctl(struct inode *inode, struct file *file, 
  446. struct vfc_dev *dev, unsigned long arg) 
  447. {
  448. int ret = 0;
  449. unsigned int status = NO_LOCK;
  450. unsigned char buf[1];
  451. if(vfc_i2c_recvbuf(dev, VFC_SAA9051_ADDR, buf, 1)) {
  452. printk(KERN_ERR "vfc%d: Unable to get statusn",
  453.        dev->instance);
  454. return -EIO;
  455. }
  456. if(buf[0] & VFC_SAA9051_HLOCK) {
  457. status = NO_LOCK;
  458. } else if(buf[0] & VFC_SAA9051_FD) {
  459. if(buf[0] & VFC_SAA9051_CD)
  460. status = NTSC_COLOR;
  461. else
  462. status = NTSC_NOCOLOR;
  463. } else {
  464. if(buf[0] & VFC_SAA9051_CD)
  465. status = PAL_COLOR;
  466. else
  467. status = PAL_NOCOLOR;
  468. }
  469. VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; "
  470. "buf[0]=%xn", dev->instance, status, buf[0]));
  471. if (copy_to_user((void *)arg,&status,sizeof(unsigned int))) {
  472. VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to "
  473. "vfc_get_video_ioctln",
  474. dev->instance));
  475. return ret;
  476. }
  477. return ret;
  478. }
  479. static int vfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
  480.       unsigned long arg) 
  481. {
  482. int ret = 0;
  483. unsigned int tmp;
  484. struct vfc_dev *dev;
  485. dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
  486. if(dev == NULL)
  487. return -ENODEV;
  488. switch(cmd & 0x0000ffff) {
  489. case VFCGCTRL:
  490. #if 0
  491. VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)n", dev->instance));
  492. #endif
  493. tmp = sbus_readl(&dev->regs->control);
  494. if(copy_to_user((void *)arg, &tmp, sizeof(unsigned int))) {
  495. ret = -EFAULT;
  496. break;
  497. }
  498. ret = 0;
  499. break;
  500. case VFCSCTRL:
  501. ret = vfc_set_control_ioctl(inode, file, dev, arg);
  502. break;
  503. case VFCGVID:
  504. ret = vfc_get_video_ioctl(inode, file, dev, arg);
  505. break;
  506. case VFCSVID:
  507. ret = vfc_set_video_ioctl(inode, file, dev, arg);
  508. break;
  509. case VFCHUE:
  510. VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)n", dev->instance));
  511. if(copy_from_user(&tmp,(void *)arg,sizeof(unsigned int))) {
  512. VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer "
  513. "to IOCTL(VFCHUE)", dev->instance));
  514. ret = -EFAULT;
  515. } else {
  516. VFC_SAA9051_SA(dev,VFC_SAA9051_HUE) = tmp;
  517. vfc_update_saa9051(dev);
  518. ret = 0;
  519. }
  520. break;
  521. case VFCPORTCHG:
  522. ret = vfc_port_change_ioctl(inode, file, dev, arg);
  523. break;
  524. case VFCRDINFO:
  525. ret = -EINVAL;
  526. VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)n", dev->instance));
  527. break;
  528. default:
  529. ret = vfc_debug(vfc_get_dev_ptr(MINOR(inode->i_rdev)),
  530. cmd, arg);
  531. break;
  532. };
  533. return ret;
  534. }
  535. static int vfc_mmap(struct inode *inode, struct file *file, 
  536.     struct vm_area_struct *vma) 
  537. {
  538. unsigned int map_size, ret, map_offset;
  539. struct vfc_dev *dev;
  540. dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
  541. if(dev == NULL)
  542. return -ENODEV;
  543. map_size = vma->vm_end - vma->vm_start;
  544. if(map_size > sizeof(struct vfc_regs)) 
  545. map_size = sizeof(struct vfc_regs);
  546. vma->vm_flags |=
  547. (VM_SHM | VM_LOCKED | VM_IO | VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE);
  548. map_offset = (unsigned int) (long)dev->phys_regs;
  549. ret = io_remap_page_range(vma->vm_start, map_offset, map_size, 
  550.   vma->vm_page_prot, dev->which_io);
  551. if(ret)
  552. return -EAGAIN;
  553. return 0;
  554. }
  555. static struct file_operations vfc_fops = {
  556. owner: THIS_MODULE,
  557. llseek: no_llseek,
  558. ioctl: vfc_ioctl,
  559. mmap: vfc_mmap,
  560. open: vfc_open,
  561. release: vfc_release,
  562. };
  563. static int vfc_probe(void)
  564. {
  565. struct sbus_bus *sbus;
  566. struct sbus_dev *sdev = NULL;
  567. int ret;
  568. int instance = 0, cards = 0;
  569. for_all_sbusdev(sdev, sbus) {
  570. if (strcmp(sdev->prom_name, "vfc") == 0) {
  571. cards++;
  572. continue;
  573. }
  574. }
  575. if (!cards)
  576. return -ENODEV;
  577. vfc_dev_lst = (struct vfc_dev **)kmalloc(sizeof(struct vfc_dev *) *
  578.  (cards+1),
  579.  GFP_KERNEL);
  580. if (vfc_dev_lst == NULL)
  581. return -ENOMEM;
  582. memset(vfc_dev_lst, 0, sizeof(struct vfc_dev *) * (cards + 1));
  583. vfc_dev_lst[cards] = NULL;
  584. ret = devfs_register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops);
  585. if(ret) {
  586. printk(KERN_ERR "Unable to get major number %dn", VFC_MAJOR);
  587. kfree(vfc_dev_lst);
  588. return -EIO;
  589. }
  590. devfs_handle = devfs_mk_dir (NULL, "vfc", NULL);
  591. instance = 0;
  592. for_all_sbusdev(sdev, sbus) {
  593. if (strcmp(sdev->prom_name, "vfc") == 0) {
  594. vfc_dev_lst[instance]=(struct vfc_dev *)
  595. kmalloc(sizeof(struct vfc_dev), GFP_KERNEL);
  596. if (vfc_dev_lst[instance] == NULL)
  597. return -ENOMEM;
  598. ret = init_vfc_device(sdev,
  599.       vfc_dev_lst[instance],
  600.       instance);
  601. if(ret) {
  602. printk(KERN_ERR "Unable to initialize"
  603.        " vfc%d devicen",
  604.        instance);
  605. } else {
  606. }
  607. instance++;
  608. continue;
  609. }
  610. }
  611. return 0;
  612. }
  613. #ifdef MODULE
  614. int init_module(void)
  615. #else 
  616. int vfc_init(void)
  617. #endif
  618. {
  619. return vfc_probe();
  620. }
  621. #ifdef MODULE
  622. static void deinit_vfc_device(struct vfc_dev *dev)
  623. {
  624. if(dev == NULL)
  625. return;
  626. devfs_unregister (dev->de);
  627. sbus_iounmap((unsigned long)dev->regs, sizeof(struct vfc_regs));
  628. kfree(dev);
  629. }
  630. void cleanup_module(void)
  631. {
  632. struct vfc_dev **devp;
  633. devfs_unregister_chrdev(VFC_MAJOR,vfcstr);
  634. for (devp = vfc_dev_lst; *devp; devp++)
  635. deinit_vfc_device(*devp);
  636. devfs_unregister (devfs_handle);
  637. kfree(vfc_dev_lst);
  638. return;
  639. }
  640. #endif