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