static inline struct ra_softc * mscp_device_lookup(dev_t dev) { struct ra_softc *ra; int unit; unit = DISKUNIT(dev); #if NRA if (cdevsw_lookup(dev) == &ra_cdevsw) ra = device_lookup_private(&ra_cd, unit); else #endif #if NRACD if (cdevsw_lookup(dev) == &racd_cdevsw) ra = device_lookup_private(&racd_cd, unit); else #endif #if NRX if (cdevsw_lookup(dev) == &rx_cdevsw) ra = device_lookup_private(&rx_cd, unit); else #endif panic("mscp_device_lookup: unexpected major %"PRIu32" unit %u", major(dev), unit); return ra; }
/* * (Try to) put the drive online. This is done the first time the * drive is opened, or if it has fallen offline. */ int ra_putonline(dev_t dev, struct ra_softc *ra) { struct disklabel *dl; const char *msg; if (rx_putonline(ra) != MSCP_DONE) return MSCP_FAILED; dl = ra->ra_disk.dk_label; ra->ra_state = DK_RDLABEL; printf("%s", device_xname(ra->ra_dev)); if ((msg = readdisklabel( MAKEDISKDEV(major(dev), device_unit(ra->ra_dev), RAW_PART), rastrategy, dl, NULL)) == NULL) { ra->ra_havelabel = 1; ra->ra_state = DK_OPEN; } #if NRACD else if (cdevsw_lookup(dev) == &racd_cdevsw) { dl->d_partitions[0].p_offset = 0; dl->d_partitions[0].p_size = dl->d_secperunit; dl->d_partitions[0].p_fstype = FS_ISO9660; } #endif /* NRACD */ else { printf(": %s", msg); } printf(": size %d sectors\n", dl->d_secperunit); return MSCP_DONE; }
/* * XXX Pathetic hack to make svgalib work. This will fake the major * device number of an opened VT so that svgalib likes it. grmbl. * Should probably do it 'wrong the right way' and use a mapping * array for all major device numbers, and map linux_mknod too. */ dev_t linux_fakedev(dev_t dev, int raw) { extern const struct cdevsw ptc_cdevsw, pts_cdevsw; const struct cdevsw *cd = cdevsw_lookup(dev); if (raw) { #if (NWSDISPLAY > 0) extern const struct cdevsw wsdisplay_cdevsw; if (cd == &wsdisplay_cdevsw) return makedev(LINUX_CONS_MAJOR, (minor(dev) + 1)); #endif } if (cd == &ptc_cdevsw) return makedev(LINUX_PTC_MAJOR, minor(dev)); if (cd == &pts_cdevsw) return makedev(LINUX_PTS_MAJOR, minor(dev)); return dev; }
dev_t linux_fakedev(dev_t dev, int raw) { extern const struct cdevsw ptc_cdevsw, pts_cdevsw; const struct cdevsw *cd = cdevsw_lookup(dev); if (raw) { #if (NWSDISPLAY > 0) extern const struct cdevsw wsdisplay_cdevsw; if (cd == &wsdisplay_cdevsw) return makedev(LINUX_CONS_MAJOR, (minor(dev) + 1)); #endif } if (cd == &ptc_cdevsw) return makedev(LINUX_PTC_MAJOR, minor(dev)); if (cd == &pts_cdevsw) return makedev(LINUX_PTS_MAJOR, minor(dev)); return ((minor(dev) & 0xff) | ((major(dev) & 0xfff) << 8) | (((unsigned long long int) (minor(dev) & ~0xff)) << 12) | (((unsigned long long int) (major(dev) & ~0xfff)) << 32)); }
/* * Most ioctl command are just converted to their NetBSD values, * and passed on. The ones that take structure pointers and (flag) * values need some massaging. */ int linux_sys_ioctl(struct lwp *l, const struct linux_sys_ioctl_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(u_long) com; syscallarg(void *) data; } */ int error; switch (LINUX_IOCGROUP(SCARG(uap, com))) { case 'M': switch(SCARG(uap, com)) { case LINUX_MEGARAID_CMD: case LINUX_MEGARAID_GET_AEN: { struct sys_ioctl_args ua; u_long com = 0; if (SCARG(uap, com) & IOC_IN) com |= IOC_OUT; if (SCARG(uap, com) & IOC_OUT) com |= IOC_IN; SCARG(&ua, fd) = SCARG(uap, fd); SCARG(&ua, com) = SCARG(uap, com); SCARG(&ua, com) &= ~IOC_DIRMASK; SCARG(&ua, com) |= com; SCARG(&ua, data) = SCARG(uap, data); error = sys_ioctl(l, (const void *)&ua, retval); break; } default: error = oss_ioctl_mixer(l, LINUX_TO_OSS(uap), retval); break; } break; case 'Q': error = oss_ioctl_sequencer(l, LINUX_TO_OSS(uap), retval); break; case 'P': error = oss_ioctl_audio(l, LINUX_TO_OSS(uap), retval); break; case 'V': /* video4linux2 */ case 'd': /* drm */ { struct sys_ioctl_args ua; u_long com = 0; if (SCARG(uap, com) & IOC_IN) com |= IOC_OUT; if (SCARG(uap, com) & IOC_OUT) com |= IOC_IN; SCARG(&ua, fd) = SCARG(uap, fd); SCARG(&ua, com) = SCARG(uap, com); SCARG(&ua, com) &= ~IOC_DIRMASK; SCARG(&ua, com) |= com; SCARG(&ua, data) = SCARG(uap, data); error = sys_ioctl(l, (const void *)&ua, retval); break; } case 'r': /* VFAT ioctls; not yet supported */ error = ENOSYS; break; case 'S': error = linux_ioctl_cdrom(l, uap, retval); break; case 't': case 'f': error = linux_ioctl_termios(l, uap, retval); break; case 'm': error = linux_ioctl_mtio(l, uap, retval); break; case 'T': { #if NSEQUENCER > 0 /* XXX XAX 2x check this. */ /* * Both termios and the MIDI sequencer use 'T' to identify * the ioctl, so we have to differentiate them in another * way. We do it by indexing in the cdevsw with the major * device number and check if that is the sequencer entry. */ bool is_sequencer = false; struct file *fp; struct vnode *vp; struct vattr va; extern const struct cdevsw sequencer_cdevsw; if ((fp = fd_getfile(SCARG(uap, fd))) == NULL) return EBADF; if (fp->f_type == DTYPE_VNODE && (vp = (struct vnode *)fp->f_data) != NULL && vp->v_type == VCHR) { vn_lock(vp, LK_SHARED | LK_RETRY); error = VOP_GETATTR(vp, &va, l->l_cred); VOP_UNLOCK(vp); if (error == 0 && cdevsw_lookup(va.va_rdev) == &sequencer_cdevsw) is_sequencer = true; } if (is_sequencer) { error = oss_ioctl_sequencer(l, (const void *)LINUX_TO_OSS(uap), retval); } else { error = linux_ioctl_termios(l, uap, retval); } fd_putfile(SCARG(uap, fd)); #else error = linux_ioctl_termios(l, uap, retval); #endif } break; case '"': error = linux_ioctl_sg(l, uap, retval); break; case 0x89: error = linux_ioctl_socket(l, uap, retval); break; case 0x03: error = linux_ioctl_hdio(l, uap, retval); break; case 0x02: error = linux_ioctl_fdio(l, uap, retval); break; case 0x12: error = linux_ioctl_blkio(l, uap, retval); break; default: error = linux_machdepioctl(l, uap, retval); break; } if (error == EPASSTHROUGH) { /* * linux returns EINVAL or ENOTTY for not supported ioctls. */ error = EINVAL; } return error; }
/*ARGSUSED*/ int coda_mount(struct mount *vfsp, /* Allocated and initialized by mount(2) */ const char *path, /* path covered: ignored by the fs-layer */ void *data, /* Need to define a data type for this in netbsd? */ size_t *data_len) { struct lwp *l = curlwp; struct vnode *dvp; struct cnode *cp; dev_t dev; struct coda_mntinfo *mi; struct vnode *rtvp; const struct cdevsw *cdev; CodaFid rootfid = INVAL_FID; CodaFid ctlfid = CTL_FID; int error; if (data == NULL) return EINVAL; if (vfsp->mnt_flag & MNT_GETARGS) return EINVAL; ENTRY; coda_vfsopstats_init(); coda_vnodeopstats_init(); MARK_ENTRY(CODA_MOUNT_STATS); if (CODA_MOUNTED(vfsp)) { MARK_INT_FAIL(CODA_MOUNT_STATS); return(EBUSY); } /* Validate mount device. Similar to getmdev(). */ /* * XXX: coda passes the mount device as the entire mount args, * All other fs pass a structure contining a pointer. * In order to get sys_mount() to do the copyin() we've set a * fixed default size for the filename buffer. */ /* Ensure that namei() doesn't run off the filename buffer */ ((char *)data)[*data_len - 1] = 0; error = namei_simple_kernel((char *)data, NSM_FOLLOW_NOEMULROOT, &dvp); if (error) { MARK_INT_FAIL(CODA_MOUNT_STATS); return (error); } if (dvp->v_type != VCHR) { MARK_INT_FAIL(CODA_MOUNT_STATS); vrele(dvp); return(ENXIO); } dev = dvp->v_rdev; vrele(dvp); cdev = cdevsw_lookup(dev); if (cdev == NULL) { MARK_INT_FAIL(CODA_MOUNT_STATS); return(ENXIO); } /* * See if the device table matches our expectations. */ if (cdev != &vcoda_cdevsw) { MARK_INT_FAIL(CODA_MOUNT_STATS); return(ENXIO); } if (minor(dev) >= NVCODA) { MARK_INT_FAIL(CODA_MOUNT_STATS); return(ENXIO); } /* * Initialize the mount record and link it to the vfs struct */ mi = &coda_mnttbl[minor(dev)]; if (!VC_OPEN(&mi->mi_vcomm)) { MARK_INT_FAIL(CODA_MOUNT_STATS); return(ENODEV); } /* No initialization (here) of mi_vcomm! */ vfsp->mnt_data = mi; vfsp->mnt_stat.f_fsidx.__fsid_val[0] = 0; vfsp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_CODA); vfsp->mnt_stat.f_fsid = vfsp->mnt_stat.f_fsidx.__fsid_val[0]; vfsp->mnt_stat.f_namemax = CODA_MAXNAMLEN; mi->mi_vfsp = vfsp; /* * Make a root vnode to placate the Vnode interface, but don't * actually make the CODA_ROOT call to venus until the first call * to coda_root in case a server is down while venus is starting. */ cp = make_coda_node(&rootfid, vfsp, VDIR); rtvp = CTOV(cp); rtvp->v_vflag |= VV_ROOT; cp = make_coda_node(&ctlfid, vfsp, VCHR); coda_ctlvp = CTOV(cp); /* Add vfs and rootvp to chain of vfs hanging off mntinfo */ mi->mi_vfsp = vfsp; mi->mi_rootvp = rtvp; /* set filesystem block size */ vfsp->mnt_stat.f_bsize = 8192; /* XXX -JJK */ vfsp->mnt_stat.f_frsize = 8192; /* XXX -JJK */ /* error is currently guaranteed to be zero, but in case some code changes... */ CODADEBUG(1, myprintf(("coda_mount returned %d\n",error)););