5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/param.h> 30#include <sys/systm.h> 31#include <sys/malloc.h> 32#include <sys/kernel.h> 33#include <sys/sysctl.h> 34#include <sys/lock.h> 35#include <sys/mutex.h> 36#include <sys/bus.h> 37#include <sys/fcntl.h> 38#include <sys/file.h> 39#include <sys/filio.h> 40#include <sys/rwlock.h> 41 42#include <vm/vm.h> 43#include <vm/pmap.h> 44 45#include <machine/stdarg.h> 46#include <machine/pmap.h> 47 48#include <linux/kobject.h> 49#include <linux/device.h> 50#include <linux/slab.h> 51#include <linux/module.h> 52#include <linux/cdev.h> 53#include <linux/file.h> 54#include <linux/sysfs.h> 55#include <linux/mm.h> 56#include <linux/io.h> 57#include <linux/vmalloc.h> 58 59#include <vm/vm_pager.h> 60 61MALLOC_DEFINE(M_KMALLOC, "linux", "Linux kmalloc compat"); 62 63#include <linux/rbtree.h> 64/* Undo Linux compat changes. */ 65#undef RB_ROOT 66#undef file 67#undef cdev 68#define RB_ROOT(head) (head)->rbh_root 69#undef LIST_HEAD 70/* From sys/queue.h */ 71#define LIST_HEAD(name, type) \ 72struct name { \ 73 struct type *lh_first; /* first element */ \ 74} 75 76struct kobject class_root; 77struct device linux_rootdev; 78struct class miscclass; 79struct list_head pci_drivers; 80struct list_head pci_devices; 81spinlock_t pci_lock; 82 83int 84panic_cmp(struct rb_node *one, struct rb_node *two) 85{ 86 panic("no cmp"); 87} 88 89RB_GENERATE(linux_root, rb_node, __entry, panic_cmp); 90 91int 92kobject_set_name(struct kobject *kobj, const char *fmt, ...) 93{ 94 va_list args; 95 int error; 96 97 va_start(args, fmt); 98 error = kobject_set_name_vargs(kobj, fmt, args); 99 va_end(args); 100 101 return (error); 102} 103 104static inline int 105kobject_add_complete(struct kobject *kobj, struct kobject *parent) 106{ 107 struct kobj_type *t; 108 int error; 109 110 kobj->parent = kobject_get(parent); 111 error = sysfs_create_dir(kobj); 112 if (error == 0 && kobj->ktype && kobj->ktype->default_attrs) { 113 struct attribute **attr; 114 t = kobj->ktype; 115 116 for (attr = t->default_attrs; *attr != NULL; attr++) { 117 error = sysfs_create_file(kobj, *attr); 118 if (error) 119 break; 120 } 121 if (error) 122 sysfs_remove_dir(kobj); 123 124 } 125 return (error); 126} 127 128int 129kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...) 130{ 131 va_list args; 132 int error; 133 134 va_start(args, fmt); 135 error = kobject_set_name_vargs(kobj, fmt, args); 136 va_end(args); 137 if (error) 138 return (error); 139 140 return kobject_add_complete(kobj, parent); 141} 142 143void 144kobject_release(struct kref *kref) 145{ 146 struct kobject *kobj; 147 char *name; 148 149 kobj = container_of(kref, struct kobject, kref); 150 sysfs_remove_dir(kobj); 151 if (kobj->parent) 152 kobject_put(kobj->parent); 153 kobj->parent = NULL; 154 name = kobj->name; 155 if (kobj->ktype && kobj->ktype->release) 156 kobj->ktype->release(kobj); 157 kfree(name); 158} 159 160static void 161kobject_kfree(struct kobject *kobj) 162{
| 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice unmodified, this list of conditions, and the following 13 * disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/malloc.h> 33#include <sys/kernel.h> 34#include <sys/sysctl.h> 35#include <sys/lock.h> 36#include <sys/mutex.h> 37#include <sys/bus.h> 38#include <sys/fcntl.h> 39#include <sys/file.h> 40#include <sys/filio.h> 41#include <sys/rwlock.h> 42 43#include <vm/vm.h> 44#include <vm/pmap.h> 45 46#include <machine/stdarg.h> 47#include <machine/pmap.h> 48 49#include <linux/kobject.h> 50#include <linux/device.h> 51#include <linux/slab.h> 52#include <linux/module.h> 53#include <linux/cdev.h> 54#include <linux/file.h> 55#include <linux/sysfs.h> 56#include <linux/mm.h> 57#include <linux/io.h> 58#include <linux/vmalloc.h> 59 60#include <vm/vm_pager.h> 61 62MALLOC_DEFINE(M_KMALLOC, "linux", "Linux kmalloc compat"); 63 64#include <linux/rbtree.h> 65/* Undo Linux compat changes. */ 66#undef RB_ROOT 67#undef file 68#undef cdev 69#define RB_ROOT(head) (head)->rbh_root 70#undef LIST_HEAD 71/* From sys/queue.h */ 72#define LIST_HEAD(name, type) \ 73struct name { \ 74 struct type *lh_first; /* first element */ \ 75} 76 77struct kobject class_root; 78struct device linux_rootdev; 79struct class miscclass; 80struct list_head pci_drivers; 81struct list_head pci_devices; 82spinlock_t pci_lock; 83 84int 85panic_cmp(struct rb_node *one, struct rb_node *two) 86{ 87 panic("no cmp"); 88} 89 90RB_GENERATE(linux_root, rb_node, __entry, panic_cmp); 91 92int 93kobject_set_name(struct kobject *kobj, const char *fmt, ...) 94{ 95 va_list args; 96 int error; 97 98 va_start(args, fmt); 99 error = kobject_set_name_vargs(kobj, fmt, args); 100 va_end(args); 101 102 return (error); 103} 104 105static inline int 106kobject_add_complete(struct kobject *kobj, struct kobject *parent) 107{ 108 struct kobj_type *t; 109 int error; 110 111 kobj->parent = kobject_get(parent); 112 error = sysfs_create_dir(kobj); 113 if (error == 0 && kobj->ktype && kobj->ktype->default_attrs) { 114 struct attribute **attr; 115 t = kobj->ktype; 116 117 for (attr = t->default_attrs; *attr != NULL; attr++) { 118 error = sysfs_create_file(kobj, *attr); 119 if (error) 120 break; 121 } 122 if (error) 123 sysfs_remove_dir(kobj); 124 125 } 126 return (error); 127} 128 129int 130kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...) 131{ 132 va_list args; 133 int error; 134 135 va_start(args, fmt); 136 error = kobject_set_name_vargs(kobj, fmt, args); 137 va_end(args); 138 if (error) 139 return (error); 140 141 return kobject_add_complete(kobj, parent); 142} 143 144void 145kobject_release(struct kref *kref) 146{ 147 struct kobject *kobj; 148 char *name; 149 150 kobj = container_of(kref, struct kobject, kref); 151 sysfs_remove_dir(kobj); 152 if (kobj->parent) 153 kobject_put(kobj->parent); 154 kobj->parent = NULL; 155 name = kobj->name; 156 if (kobj->ktype && kobj->ktype->release) 157 kobj->ktype->release(kobj); 158 kfree(name); 159} 160 161static void 162kobject_kfree(struct kobject *kobj) 163{
|
167struct kobj_type kfree_type = { .release = kobject_kfree }; 168 169struct device * 170device_create(struct class *class, struct device *parent, dev_t devt, 171 void *drvdata, const char *fmt, ...) 172{ 173 struct device *dev; 174 va_list args; 175 176 dev = kzalloc(sizeof(*dev), M_WAITOK); 177 dev->parent = parent; 178 dev->class = class; 179 dev->devt = devt; 180 dev->driver_data = drvdata; 181 va_start(args, fmt); 182 kobject_set_name_vargs(&dev->kobj, fmt, args); 183 va_end(args); 184 device_register(dev); 185 186 return (dev); 187} 188 189int 190kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype, 191 struct kobject *parent, const char *fmt, ...) 192{ 193 va_list args; 194 int error; 195 196 kobject_init(kobj, ktype); 197 kobj->ktype = ktype; 198 kobj->parent = parent; 199 kobj->name = NULL; 200 201 va_start(args, fmt); 202 error = kobject_set_name_vargs(kobj, fmt, args); 203 va_end(args); 204 if (error) 205 return (error); 206 return kobject_add_complete(kobj, parent); 207} 208 209static void 210linux_file_dtor(void *cdp) 211{ 212 struct linux_file *filp; 213 214 filp = cdp; 215 filp->f_op->release(filp->f_vnode, filp); 216 vdrop(filp->f_vnode); 217 kfree(filp); 218} 219 220static int 221linux_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 222{ 223 struct linux_cdev *ldev; 224 struct linux_file *filp; 225 struct file *file; 226 int error; 227 228 file = curthread->td_fpop; 229 ldev = dev->si_drv1; 230 if (ldev == NULL) 231 return (ENODEV); 232 filp = kzalloc(sizeof(*filp), GFP_KERNEL); 233 filp->f_dentry = &filp->f_dentry_store; 234 filp->f_op = ldev->ops; 235 filp->f_flags = file->f_flag; 236 vhold(file->f_vnode); 237 filp->f_vnode = file->f_vnode; 238 if (filp->f_op->open) { 239 error = -filp->f_op->open(file->f_vnode, filp); 240 if (error) { 241 kfree(filp); 242 return (error); 243 } 244 } 245 error = devfs_set_cdevpriv(filp, linux_file_dtor); 246 if (error) { 247 filp->f_op->release(file->f_vnode, filp); 248 kfree(filp); 249 return (error); 250 } 251 252 return 0; 253} 254 255static int 256linux_dev_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 257{ 258 struct linux_cdev *ldev; 259 struct linux_file *filp; 260 struct file *file; 261 int error; 262 263 file = curthread->td_fpop; 264 ldev = dev->si_drv1; 265 if (ldev == NULL) 266 return (0); 267 if ((error = devfs_get_cdevpriv((void **)&filp)) != 0) 268 return (error); 269 filp->f_flags = file->f_flag; 270 devfs_clear_cdevpriv(); 271 272 273 return (0); 274} 275 276static int 277linux_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 278 struct thread *td) 279{ 280 struct linux_cdev *ldev; 281 struct linux_file *filp; 282 struct file *file; 283 int error; 284 285 file = curthread->td_fpop; 286 ldev = dev->si_drv1; 287 if (ldev == NULL) 288 return (0); 289 if ((error = devfs_get_cdevpriv((void **)&filp)) != 0) 290 return (error); 291 filp->f_flags = file->f_flag; 292 /* 293 * Linux does not have a generic ioctl copyin/copyout layer. All 294 * linux ioctls must be converted to void ioctls which pass a 295 * pointer to the address of the data. We want the actual user 296 * address so we dereference here. 297 */ 298 data = *(void **)data; 299 if (filp->f_op->unlocked_ioctl) 300 error = -filp->f_op->unlocked_ioctl(filp, cmd, (u_long)data); 301 else 302 error = ENOTTY; 303 304 return (error); 305} 306 307static int 308linux_dev_read(struct cdev *dev, struct uio *uio, int ioflag) 309{ 310 struct linux_cdev *ldev; 311 struct linux_file *filp; 312 struct file *file; 313 ssize_t bytes; 314 int error; 315 316 file = curthread->td_fpop; 317 ldev = dev->si_drv1; 318 if (ldev == NULL) 319 return (0); 320 if ((error = devfs_get_cdevpriv((void **)&filp)) != 0) 321 return (error); 322 filp->f_flags = file->f_flag; 323 if (uio->uio_iovcnt != 1) 324 panic("linux_dev_read: uio %p iovcnt %d", 325 uio, uio->uio_iovcnt); 326 if (filp->f_op->read) { 327 bytes = filp->f_op->read(filp, uio->uio_iov->iov_base, 328 uio->uio_iov->iov_len, &uio->uio_offset); 329 if (bytes >= 0) { 330 uio->uio_iov->iov_base += bytes; 331 uio->uio_iov->iov_len -= bytes; 332 uio->uio_resid -= bytes; 333 } else 334 error = -bytes; 335 } else 336 error = ENXIO; 337 338 return (error); 339} 340 341static int 342linux_dev_write(struct cdev *dev, struct uio *uio, int ioflag) 343{ 344 struct linux_cdev *ldev; 345 struct linux_file *filp; 346 struct file *file; 347 ssize_t bytes; 348 int error; 349 350 file = curthread->td_fpop; 351 ldev = dev->si_drv1; 352 if (ldev == NULL) 353 return (0); 354 if ((error = devfs_get_cdevpriv((void **)&filp)) != 0) 355 return (error); 356 filp->f_flags = file->f_flag; 357 if (uio->uio_iovcnt != 1) 358 panic("linux_dev_write: uio %p iovcnt %d", 359 uio, uio->uio_iovcnt); 360 if (filp->f_op->write) { 361 bytes = filp->f_op->write(filp, uio->uio_iov->iov_base, 362 uio->uio_iov->iov_len, &uio->uio_offset); 363 if (bytes >= 0) { 364 uio->uio_iov->iov_base += bytes; 365 uio->uio_iov->iov_len -= bytes; 366 uio->uio_resid -= bytes; 367 } else 368 error = -bytes; 369 } else 370 error = ENXIO; 371 372 return (error); 373} 374 375static int 376linux_dev_poll(struct cdev *dev, int events, struct thread *td) 377{ 378 struct linux_cdev *ldev; 379 struct linux_file *filp; 380 struct file *file; 381 int revents; 382 int error; 383 384 file = curthread->td_fpop; 385 ldev = dev->si_drv1; 386 if (ldev == NULL) 387 return (0); 388 if ((error = devfs_get_cdevpriv((void **)&filp)) != 0) 389 return (error); 390 filp->f_flags = file->f_flag; 391 if (filp->f_op->poll) 392 revents = filp->f_op->poll(filp, NULL) & events; 393 else 394 revents = 0; 395 396 return (revents); 397} 398 399static int 400linux_dev_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, 401 int nprot, vm_memattr_t *memattr) 402{ 403 404 /* XXX memattr not honored. */ 405 *paddr = offset; 406 return (0); 407} 408 409static int 410linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t *offset, 411 vm_size_t size, struct vm_object **object, int nprot) 412{ 413 struct linux_cdev *ldev; 414 struct linux_file *filp; 415 struct file *file; 416 struct vm_area_struct vma; 417 vm_paddr_t paddr; 418 vm_page_t m; 419 int error; 420 421 file = curthread->td_fpop; 422 ldev = dev->si_drv1; 423 if (ldev == NULL) 424 return (ENODEV); 425 if (size != PAGE_SIZE) 426 return (EINVAL); 427 if ((error = devfs_get_cdevpriv((void **)&filp)) != 0) 428 return (error); 429 filp->f_flags = file->f_flag; 430 vma.vm_start = 0; 431 vma.vm_end = PAGE_SIZE; 432 vma.vm_pgoff = *offset / PAGE_SIZE; 433 vma.vm_pfn = 0; 434 vma.vm_page_prot = 0; 435 if (filp->f_op->mmap) { 436 error = -filp->f_op->mmap(filp, &vma); 437 if (error == 0) { 438 paddr = (vm_paddr_t)vma.vm_pfn << PAGE_SHIFT; 439 *offset = paddr; 440 m = PHYS_TO_VM_PAGE(paddr); 441 *object = vm_pager_allocate(OBJT_DEVICE, dev, 442 PAGE_SIZE, nprot, *offset, curthread->td_ucred); 443 if (*object == NULL) 444 return (EINVAL); 445 if (vma.vm_page_prot != VM_MEMATTR_DEFAULT) 446 pmap_page_set_memattr(m, vma.vm_page_prot); 447 } 448 } else 449 error = ENODEV; 450 451 return (error); 452} 453 454struct cdevsw linuxcdevsw = { 455 .d_version = D_VERSION, 456 .d_flags = D_TRACKCLOSE, 457 .d_open = linux_dev_open, 458 .d_close = linux_dev_close, 459 .d_read = linux_dev_read, 460 .d_write = linux_dev_write, 461 .d_ioctl = linux_dev_ioctl, 462 .d_mmap_single = linux_dev_mmap_single, 463 .d_mmap = linux_dev_mmap, 464 .d_poll = linux_dev_poll, 465}; 466 467static int 468linux_file_read(struct file *file, struct uio *uio, struct ucred *active_cred, 469 int flags, struct thread *td) 470{ 471 struct linux_file *filp; 472 ssize_t bytes; 473 int error; 474 475 error = 0; 476 filp = (struct linux_file *)file->f_data; 477 filp->f_flags = file->f_flag; 478 if (uio->uio_iovcnt != 1) 479 panic("linux_file_read: uio %p iovcnt %d", 480 uio, uio->uio_iovcnt); 481 if (filp->f_op->read) { 482 bytes = filp->f_op->read(filp, uio->uio_iov->iov_base, 483 uio->uio_iov->iov_len, &uio->uio_offset); 484 if (bytes >= 0) { 485 uio->uio_iov->iov_base += bytes; 486 uio->uio_iov->iov_len -= bytes; 487 uio->uio_resid -= bytes; 488 } else 489 error = -bytes; 490 } else 491 error = ENXIO; 492 493 return (error); 494} 495 496static int 497linux_file_poll(struct file *file, int events, struct ucred *active_cred, 498 struct thread *td) 499{ 500 struct linux_file *filp; 501 int revents; 502 503 filp = (struct linux_file *)file->f_data; 504 filp->f_flags = file->f_flag; 505 if (filp->f_op->poll) 506 revents = filp->f_op->poll(filp, NULL) & events; 507 else 508 revents = 0; 509 510 return (0); 511} 512 513static int 514linux_file_close(struct file *file, struct thread *td) 515{ 516 struct linux_file *filp; 517 int error; 518 519 filp = (struct linux_file *)file->f_data; 520 filp->f_flags = file->f_flag; 521 error = -filp->f_op->release(NULL, filp); 522 funsetown(&filp->f_sigio); 523 kfree(filp); 524 525 return (error); 526} 527 528static int 529linux_file_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *cred, 530 struct thread *td) 531{ 532 struct linux_file *filp; 533 int error; 534 535 filp = (struct linux_file *)fp->f_data; 536 filp->f_flags = fp->f_flag; 537 error = 0; 538 539 switch (cmd) { 540 case FIONBIO: 541 break; 542 case FIOASYNC: 543 if (filp->f_op->fasync == NULL) 544 break; 545 error = filp->f_op->fasync(0, filp, fp->f_flag & FASYNC); 546 break; 547 case FIOSETOWN: 548 error = fsetown(*(int *)data, &filp->f_sigio); 549 if (error == 0) 550 error = filp->f_op->fasync(0, filp, 551 fp->f_flag & FASYNC); 552 break; 553 case FIOGETOWN: 554 *(int *)data = fgetown(&filp->f_sigio); 555 break; 556 default: 557 error = ENOTTY; 558 break; 559 } 560 return (error); 561} 562 563struct fileops linuxfileops = { 564 .fo_read = linux_file_read, 565 .fo_poll = linux_file_poll, 566 .fo_close = linux_file_close, 567 .fo_ioctl = linux_file_ioctl, 568 .fo_chmod = invfo_chmod, 569 .fo_chown = invfo_chown, 570 .fo_sendfile = invfo_sendfile, 571}; 572 573/* 574 * Hash of vmmap addresses. This is infrequently accessed and does not 575 * need to be particularly large. This is done because we must store the 576 * caller's idea of the map size to properly unmap. 577 */ 578struct vmmap { 579 LIST_ENTRY(vmmap) vm_next; 580 void *vm_addr; 581 unsigned long vm_size; 582}; 583 584LIST_HEAD(vmmaphd, vmmap); 585#define VMMAP_HASH_SIZE 64 586#define VMMAP_HASH_MASK (VMMAP_HASH_SIZE - 1) 587#define VM_HASH(addr) ((uintptr_t)(addr) >> PAGE_SHIFT) & VMMAP_HASH_MASK 588static struct vmmaphd vmmaphead[VMMAP_HASH_SIZE]; 589static struct mtx vmmaplock; 590 591static void 592vmmap_add(void *addr, unsigned long size) 593{ 594 struct vmmap *vmmap; 595 596 vmmap = kmalloc(sizeof(*vmmap), GFP_KERNEL); 597 mtx_lock(&vmmaplock); 598 vmmap->vm_size = size; 599 vmmap->vm_addr = addr; 600 LIST_INSERT_HEAD(&vmmaphead[VM_HASH(addr)], vmmap, vm_next); 601 mtx_unlock(&vmmaplock); 602} 603 604static struct vmmap * 605vmmap_remove(void *addr) 606{ 607 struct vmmap *vmmap; 608 609 mtx_lock(&vmmaplock); 610 LIST_FOREACH(vmmap, &vmmaphead[VM_HASH(addr)], vm_next) 611 if (vmmap->vm_addr == addr) 612 break; 613 if (vmmap) 614 LIST_REMOVE(vmmap, vm_next); 615 mtx_unlock(&vmmaplock); 616 617 return (vmmap); 618} 619 620void * 621_ioremap_attr(vm_paddr_t phys_addr, unsigned long size, int attr) 622{ 623 void *addr; 624 625 addr = pmap_mapdev_attr(phys_addr, size, attr); 626 if (addr == NULL) 627 return (NULL); 628 vmmap_add(addr, size); 629 630 return (addr); 631} 632 633void 634iounmap(void *addr) 635{ 636 struct vmmap *vmmap; 637 638 vmmap = vmmap_remove(addr); 639 if (vmmap == NULL) 640 return; 641 pmap_unmapdev((vm_offset_t)addr, vmmap->vm_size); 642 kfree(vmmap); 643} 644 645 646void * 647vmap(struct page **pages, unsigned int count, unsigned long flags, int prot) 648{ 649 vm_offset_t off; 650 size_t size; 651 652 size = count * PAGE_SIZE; 653 off = kva_alloc(size); 654 if (off == 0) 655 return (NULL); 656 vmmap_add((void *)off, size); 657 pmap_qenter(off, pages, count); 658 659 return ((void *)off); 660} 661 662void 663vunmap(void *addr) 664{ 665 struct vmmap *vmmap; 666 667 vmmap = vmmap_remove(addr); 668 if (vmmap == NULL) 669 return; 670 pmap_qremove((vm_offset_t)addr, vmmap->vm_size / PAGE_SIZE); 671 kva_free((vm_offset_t)addr, vmmap->vm_size); 672 kfree(vmmap); 673} 674 675static void 676linux_compat_init(void) 677{ 678 struct sysctl_oid *rootoid; 679 int i; 680 681 rootoid = SYSCTL_ADD_NODE(NULL, SYSCTL_STATIC_CHILDREN(), 682 OID_AUTO, "sys", CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, "sys"); 683 kobject_init(&class_root, &class_ktype); 684 kobject_set_name(&class_root, "class"); 685 class_root.oidp = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(rootoid), 686 OID_AUTO, "class", CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, "class"); 687 kobject_init(&linux_rootdev.kobj, &dev_ktype); 688 kobject_set_name(&linux_rootdev.kobj, "device"); 689 linux_rootdev.kobj.oidp = SYSCTL_ADD_NODE(NULL, 690 SYSCTL_CHILDREN(rootoid), OID_AUTO, "device", CTLFLAG_RD, NULL, 691 "device"); 692 linux_rootdev.bsddev = root_bus; 693 miscclass.name = "misc"; 694 class_register(&miscclass); 695 INIT_LIST_HEAD(&pci_drivers); 696 INIT_LIST_HEAD(&pci_devices); 697 spin_lock_init(&pci_lock); 698 mtx_init(&vmmaplock, "IO Map lock", NULL, MTX_DEF); 699 for (i = 0; i < VMMAP_HASH_SIZE; i++) 700 LIST_INIT(&vmmaphead[i]); 701} 702 703SYSINIT(linux_compat, SI_SUB_DRIVERS, SI_ORDER_SECOND, linux_compat_init, NULL);
| 175struct kobj_type kfree_type = { .release = kobject_kfree }; 176 177struct device * 178device_create(struct class *class, struct device *parent, dev_t devt, 179 void *drvdata, const char *fmt, ...) 180{ 181 struct device *dev; 182 va_list args; 183 184 dev = kzalloc(sizeof(*dev), M_WAITOK); 185 dev->parent = parent; 186 dev->class = class; 187 dev->devt = devt; 188 dev->driver_data = drvdata; 189 va_start(args, fmt); 190 kobject_set_name_vargs(&dev->kobj, fmt, args); 191 va_end(args); 192 device_register(dev); 193 194 return (dev); 195} 196 197int 198kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype, 199 struct kobject *parent, const char *fmt, ...) 200{ 201 va_list args; 202 int error; 203 204 kobject_init(kobj, ktype); 205 kobj->ktype = ktype; 206 kobj->parent = parent; 207 kobj->name = NULL; 208 209 va_start(args, fmt); 210 error = kobject_set_name_vargs(kobj, fmt, args); 211 va_end(args); 212 if (error) 213 return (error); 214 return kobject_add_complete(kobj, parent); 215} 216 217static void 218linux_file_dtor(void *cdp) 219{ 220 struct linux_file *filp; 221 222 filp = cdp; 223 filp->f_op->release(filp->f_vnode, filp); 224 vdrop(filp->f_vnode); 225 kfree(filp); 226} 227 228static int 229linux_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 230{ 231 struct linux_cdev *ldev; 232 struct linux_file *filp; 233 struct file *file; 234 int error; 235 236 file = curthread->td_fpop; 237 ldev = dev->si_drv1; 238 if (ldev == NULL) 239 return (ENODEV); 240 filp = kzalloc(sizeof(*filp), GFP_KERNEL); 241 filp->f_dentry = &filp->f_dentry_store; 242 filp->f_op = ldev->ops; 243 filp->f_flags = file->f_flag; 244 vhold(file->f_vnode); 245 filp->f_vnode = file->f_vnode; 246 if (filp->f_op->open) { 247 error = -filp->f_op->open(file->f_vnode, filp); 248 if (error) { 249 kfree(filp); 250 return (error); 251 } 252 } 253 error = devfs_set_cdevpriv(filp, linux_file_dtor); 254 if (error) { 255 filp->f_op->release(file->f_vnode, filp); 256 kfree(filp); 257 return (error); 258 } 259 260 return 0; 261} 262 263static int 264linux_dev_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 265{ 266 struct linux_cdev *ldev; 267 struct linux_file *filp; 268 struct file *file; 269 int error; 270 271 file = curthread->td_fpop; 272 ldev = dev->si_drv1; 273 if (ldev == NULL) 274 return (0); 275 if ((error = devfs_get_cdevpriv((void **)&filp)) != 0) 276 return (error); 277 filp->f_flags = file->f_flag; 278 devfs_clear_cdevpriv(); 279 280 281 return (0); 282} 283 284static int 285linux_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 286 struct thread *td) 287{ 288 struct linux_cdev *ldev; 289 struct linux_file *filp; 290 struct file *file; 291 int error; 292 293 file = curthread->td_fpop; 294 ldev = dev->si_drv1; 295 if (ldev == NULL) 296 return (0); 297 if ((error = devfs_get_cdevpriv((void **)&filp)) != 0) 298 return (error); 299 filp->f_flags = file->f_flag; 300 /* 301 * Linux does not have a generic ioctl copyin/copyout layer. All 302 * linux ioctls must be converted to void ioctls which pass a 303 * pointer to the address of the data. We want the actual user 304 * address so we dereference here. 305 */ 306 data = *(void **)data; 307 if (filp->f_op->unlocked_ioctl) 308 error = -filp->f_op->unlocked_ioctl(filp, cmd, (u_long)data); 309 else 310 error = ENOTTY; 311 312 return (error); 313} 314 315static int 316linux_dev_read(struct cdev *dev, struct uio *uio, int ioflag) 317{ 318 struct linux_cdev *ldev; 319 struct linux_file *filp; 320 struct file *file; 321 ssize_t bytes; 322 int error; 323 324 file = curthread->td_fpop; 325 ldev = dev->si_drv1; 326 if (ldev == NULL) 327 return (0); 328 if ((error = devfs_get_cdevpriv((void **)&filp)) != 0) 329 return (error); 330 filp->f_flags = file->f_flag; 331 if (uio->uio_iovcnt != 1) 332 panic("linux_dev_read: uio %p iovcnt %d", 333 uio, uio->uio_iovcnt); 334 if (filp->f_op->read) { 335 bytes = filp->f_op->read(filp, uio->uio_iov->iov_base, 336 uio->uio_iov->iov_len, &uio->uio_offset); 337 if (bytes >= 0) { 338 uio->uio_iov->iov_base += bytes; 339 uio->uio_iov->iov_len -= bytes; 340 uio->uio_resid -= bytes; 341 } else 342 error = -bytes; 343 } else 344 error = ENXIO; 345 346 return (error); 347} 348 349static int 350linux_dev_write(struct cdev *dev, struct uio *uio, int ioflag) 351{ 352 struct linux_cdev *ldev; 353 struct linux_file *filp; 354 struct file *file; 355 ssize_t bytes; 356 int error; 357 358 file = curthread->td_fpop; 359 ldev = dev->si_drv1; 360 if (ldev == NULL) 361 return (0); 362 if ((error = devfs_get_cdevpriv((void **)&filp)) != 0) 363 return (error); 364 filp->f_flags = file->f_flag; 365 if (uio->uio_iovcnt != 1) 366 panic("linux_dev_write: uio %p iovcnt %d", 367 uio, uio->uio_iovcnt); 368 if (filp->f_op->write) { 369 bytes = filp->f_op->write(filp, uio->uio_iov->iov_base, 370 uio->uio_iov->iov_len, &uio->uio_offset); 371 if (bytes >= 0) { 372 uio->uio_iov->iov_base += bytes; 373 uio->uio_iov->iov_len -= bytes; 374 uio->uio_resid -= bytes; 375 } else 376 error = -bytes; 377 } else 378 error = ENXIO; 379 380 return (error); 381} 382 383static int 384linux_dev_poll(struct cdev *dev, int events, struct thread *td) 385{ 386 struct linux_cdev *ldev; 387 struct linux_file *filp; 388 struct file *file; 389 int revents; 390 int error; 391 392 file = curthread->td_fpop; 393 ldev = dev->si_drv1; 394 if (ldev == NULL) 395 return (0); 396 if ((error = devfs_get_cdevpriv((void **)&filp)) != 0) 397 return (error); 398 filp->f_flags = file->f_flag; 399 if (filp->f_op->poll) 400 revents = filp->f_op->poll(filp, NULL) & events; 401 else 402 revents = 0; 403 404 return (revents); 405} 406 407static int 408linux_dev_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, 409 int nprot, vm_memattr_t *memattr) 410{ 411 412 /* XXX memattr not honored. */ 413 *paddr = offset; 414 return (0); 415} 416 417static int 418linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t *offset, 419 vm_size_t size, struct vm_object **object, int nprot) 420{ 421 struct linux_cdev *ldev; 422 struct linux_file *filp; 423 struct file *file; 424 struct vm_area_struct vma; 425 vm_paddr_t paddr; 426 vm_page_t m; 427 int error; 428 429 file = curthread->td_fpop; 430 ldev = dev->si_drv1; 431 if (ldev == NULL) 432 return (ENODEV); 433 if (size != PAGE_SIZE) 434 return (EINVAL); 435 if ((error = devfs_get_cdevpriv((void **)&filp)) != 0) 436 return (error); 437 filp->f_flags = file->f_flag; 438 vma.vm_start = 0; 439 vma.vm_end = PAGE_SIZE; 440 vma.vm_pgoff = *offset / PAGE_SIZE; 441 vma.vm_pfn = 0; 442 vma.vm_page_prot = 0; 443 if (filp->f_op->mmap) { 444 error = -filp->f_op->mmap(filp, &vma); 445 if (error == 0) { 446 paddr = (vm_paddr_t)vma.vm_pfn << PAGE_SHIFT; 447 *offset = paddr; 448 m = PHYS_TO_VM_PAGE(paddr); 449 *object = vm_pager_allocate(OBJT_DEVICE, dev, 450 PAGE_SIZE, nprot, *offset, curthread->td_ucred); 451 if (*object == NULL) 452 return (EINVAL); 453 if (vma.vm_page_prot != VM_MEMATTR_DEFAULT) 454 pmap_page_set_memattr(m, vma.vm_page_prot); 455 } 456 } else 457 error = ENODEV; 458 459 return (error); 460} 461 462struct cdevsw linuxcdevsw = { 463 .d_version = D_VERSION, 464 .d_flags = D_TRACKCLOSE, 465 .d_open = linux_dev_open, 466 .d_close = linux_dev_close, 467 .d_read = linux_dev_read, 468 .d_write = linux_dev_write, 469 .d_ioctl = linux_dev_ioctl, 470 .d_mmap_single = linux_dev_mmap_single, 471 .d_mmap = linux_dev_mmap, 472 .d_poll = linux_dev_poll, 473}; 474 475static int 476linux_file_read(struct file *file, struct uio *uio, struct ucred *active_cred, 477 int flags, struct thread *td) 478{ 479 struct linux_file *filp; 480 ssize_t bytes; 481 int error; 482 483 error = 0; 484 filp = (struct linux_file *)file->f_data; 485 filp->f_flags = file->f_flag; 486 if (uio->uio_iovcnt != 1) 487 panic("linux_file_read: uio %p iovcnt %d", 488 uio, uio->uio_iovcnt); 489 if (filp->f_op->read) { 490 bytes = filp->f_op->read(filp, uio->uio_iov->iov_base, 491 uio->uio_iov->iov_len, &uio->uio_offset); 492 if (bytes >= 0) { 493 uio->uio_iov->iov_base += bytes; 494 uio->uio_iov->iov_len -= bytes; 495 uio->uio_resid -= bytes; 496 } else 497 error = -bytes; 498 } else 499 error = ENXIO; 500 501 return (error); 502} 503 504static int 505linux_file_poll(struct file *file, int events, struct ucred *active_cred, 506 struct thread *td) 507{ 508 struct linux_file *filp; 509 int revents; 510 511 filp = (struct linux_file *)file->f_data; 512 filp->f_flags = file->f_flag; 513 if (filp->f_op->poll) 514 revents = filp->f_op->poll(filp, NULL) & events; 515 else 516 revents = 0; 517 518 return (0); 519} 520 521static int 522linux_file_close(struct file *file, struct thread *td) 523{ 524 struct linux_file *filp; 525 int error; 526 527 filp = (struct linux_file *)file->f_data; 528 filp->f_flags = file->f_flag; 529 error = -filp->f_op->release(NULL, filp); 530 funsetown(&filp->f_sigio); 531 kfree(filp); 532 533 return (error); 534} 535 536static int 537linux_file_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *cred, 538 struct thread *td) 539{ 540 struct linux_file *filp; 541 int error; 542 543 filp = (struct linux_file *)fp->f_data; 544 filp->f_flags = fp->f_flag; 545 error = 0; 546 547 switch (cmd) { 548 case FIONBIO: 549 break; 550 case FIOASYNC: 551 if (filp->f_op->fasync == NULL) 552 break; 553 error = filp->f_op->fasync(0, filp, fp->f_flag & FASYNC); 554 break; 555 case FIOSETOWN: 556 error = fsetown(*(int *)data, &filp->f_sigio); 557 if (error == 0) 558 error = filp->f_op->fasync(0, filp, 559 fp->f_flag & FASYNC); 560 break; 561 case FIOGETOWN: 562 *(int *)data = fgetown(&filp->f_sigio); 563 break; 564 default: 565 error = ENOTTY; 566 break; 567 } 568 return (error); 569} 570 571struct fileops linuxfileops = { 572 .fo_read = linux_file_read, 573 .fo_poll = linux_file_poll, 574 .fo_close = linux_file_close, 575 .fo_ioctl = linux_file_ioctl, 576 .fo_chmod = invfo_chmod, 577 .fo_chown = invfo_chown, 578 .fo_sendfile = invfo_sendfile, 579}; 580 581/* 582 * Hash of vmmap addresses. This is infrequently accessed and does not 583 * need to be particularly large. This is done because we must store the 584 * caller's idea of the map size to properly unmap. 585 */ 586struct vmmap { 587 LIST_ENTRY(vmmap) vm_next; 588 void *vm_addr; 589 unsigned long vm_size; 590}; 591 592LIST_HEAD(vmmaphd, vmmap); 593#define VMMAP_HASH_SIZE 64 594#define VMMAP_HASH_MASK (VMMAP_HASH_SIZE - 1) 595#define VM_HASH(addr) ((uintptr_t)(addr) >> PAGE_SHIFT) & VMMAP_HASH_MASK 596static struct vmmaphd vmmaphead[VMMAP_HASH_SIZE]; 597static struct mtx vmmaplock; 598 599static void 600vmmap_add(void *addr, unsigned long size) 601{ 602 struct vmmap *vmmap; 603 604 vmmap = kmalloc(sizeof(*vmmap), GFP_KERNEL); 605 mtx_lock(&vmmaplock); 606 vmmap->vm_size = size; 607 vmmap->vm_addr = addr; 608 LIST_INSERT_HEAD(&vmmaphead[VM_HASH(addr)], vmmap, vm_next); 609 mtx_unlock(&vmmaplock); 610} 611 612static struct vmmap * 613vmmap_remove(void *addr) 614{ 615 struct vmmap *vmmap; 616 617 mtx_lock(&vmmaplock); 618 LIST_FOREACH(vmmap, &vmmaphead[VM_HASH(addr)], vm_next) 619 if (vmmap->vm_addr == addr) 620 break; 621 if (vmmap) 622 LIST_REMOVE(vmmap, vm_next); 623 mtx_unlock(&vmmaplock); 624 625 return (vmmap); 626} 627 628void * 629_ioremap_attr(vm_paddr_t phys_addr, unsigned long size, int attr) 630{ 631 void *addr; 632 633 addr = pmap_mapdev_attr(phys_addr, size, attr); 634 if (addr == NULL) 635 return (NULL); 636 vmmap_add(addr, size); 637 638 return (addr); 639} 640 641void 642iounmap(void *addr) 643{ 644 struct vmmap *vmmap; 645 646 vmmap = vmmap_remove(addr); 647 if (vmmap == NULL) 648 return; 649 pmap_unmapdev((vm_offset_t)addr, vmmap->vm_size); 650 kfree(vmmap); 651} 652 653 654void * 655vmap(struct page **pages, unsigned int count, unsigned long flags, int prot) 656{ 657 vm_offset_t off; 658 size_t size; 659 660 size = count * PAGE_SIZE; 661 off = kva_alloc(size); 662 if (off == 0) 663 return (NULL); 664 vmmap_add((void *)off, size); 665 pmap_qenter(off, pages, count); 666 667 return ((void *)off); 668} 669 670void 671vunmap(void *addr) 672{ 673 struct vmmap *vmmap; 674 675 vmmap = vmmap_remove(addr); 676 if (vmmap == NULL) 677 return; 678 pmap_qremove((vm_offset_t)addr, vmmap->vm_size / PAGE_SIZE); 679 kva_free((vm_offset_t)addr, vmmap->vm_size); 680 kfree(vmmap); 681} 682 683static void 684linux_compat_init(void) 685{ 686 struct sysctl_oid *rootoid; 687 int i; 688 689 rootoid = SYSCTL_ADD_NODE(NULL, SYSCTL_STATIC_CHILDREN(), 690 OID_AUTO, "sys", CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, "sys"); 691 kobject_init(&class_root, &class_ktype); 692 kobject_set_name(&class_root, "class"); 693 class_root.oidp = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(rootoid), 694 OID_AUTO, "class", CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, "class"); 695 kobject_init(&linux_rootdev.kobj, &dev_ktype); 696 kobject_set_name(&linux_rootdev.kobj, "device"); 697 linux_rootdev.kobj.oidp = SYSCTL_ADD_NODE(NULL, 698 SYSCTL_CHILDREN(rootoid), OID_AUTO, "device", CTLFLAG_RD, NULL, 699 "device"); 700 linux_rootdev.bsddev = root_bus; 701 miscclass.name = "misc"; 702 class_register(&miscclass); 703 INIT_LIST_HEAD(&pci_drivers); 704 INIT_LIST_HEAD(&pci_devices); 705 spin_lock_init(&pci_lock); 706 mtx_init(&vmmaplock, "IO Map lock", NULL, MTX_DEF); 707 for (i = 0; i < VMMAP_HASH_SIZE; i++) 708 LIST_INIT(&vmmaphead[i]); 709} 710 711SYSINIT(linux_compat, SI_SUB_DRIVERS, SI_ORDER_SECOND, linux_compat_init, NULL);
|