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