--- sys/sys/vnioctl.h Fri Sep 17 09:33:58 1999 +++ sys/sys/vnioctl.h Thu Jul 26 20:39:28 2001 @@ -75,5 +75,6 @@ #define VN_IO 0x8 /* Debug I/O in vn driver */ #define VN_DONTCLUSTER 0x10 /* Don't cluster */ #define VN_RESERVE 0x20 /* Pre-reserve swap */ +#define VN_CDROM 0x40 /* Emulate some CDROM's ioctl */ #endif /* _SYS_VNIOCTL_H_*/ --- sys/dev/vn/vn.c Thu Jul 26 19:51:54 2001 +++ sys/dev/vn/vn.c Fri Jul 27 14:59:31 2001 @@ -77,6 +77,7 @@ #include #include #include +#include #include #include @@ -419,6 +420,109 @@ } } +static __inline void +lba2msf(u_int32_t lba, u_int8_t *m, u_int8_t *s, u_int8_t *f) +{ + lba += 150; + lba &= 0xffffff; + *m = lba / (60 * 75); + lba %= (60 * 75); + *s = lba / 75; + *f = lba % 75; +} + +static int +cdioctl(struct vn_softc *vn, u_long cmd, caddr_t data) +{ + switch (cmd) { + + /* VMWare uses CDIOCGETVOL ioctl to check CDROM drive */ + case CDIOCGETVOL: { + struct ioc_vol *vol = (struct ioc_vol *)data; + vol->vol[0] = 0; + vol->vol[1] = 0; + vol->vol[2] = 0; + vol->vol[3] = 0; + return(0); + } + + /* ISO images must have only one track */ + case CDIOREADTOCHEADER: { + struct ioc_toc_header *toc = (struct ioc_toc_header *)data; + toc->len = 18; + toc->starting_track = 1; + toc->ending_track = 1; + return(0); + } + + case CDIOREADTOCENTRY: { + struct ioc_read_toc_single_entry *te = + (struct ioc_read_toc_single_entry *)data; + struct cd_toc_entry *e = &te->entry; + + IFOPT(vn, VN_FOLLOW) { + printf("vnioctl: read_toc_entry %d, %d\n", + te->address_format, te->track); + } + + if (te->track != 0 && te->track != 1 && te->track != 170) + return(EINVAL); + + bzero(e, sizeof(struct cd_toc_entry)); + + e->control = 4; /* data track, copy protected */ + e->addr_type = CD_CURRENT_POSITION; + + if (te->track == 0 || te->track == 1) { + e->track = 1; + + if (te->address_format == CD_MSF_FORMAT) + e->addr.msf.second = 2; + + /* Lead-out, 170, 0xAA */ + } else if (te->track == 170) { + int len = (vn->sc_size * vn->sc_secsize) / 2048; + e->track = 170; + + if (te->address_format == CD_MSF_FORMAT) + lba2msf(len, &e->addr.msf.minute, + &e->addr.msf.second, + &e->addr.msf.frame); + else + e->addr.lba = htonl(len); + + } else { + return(EINVAL); + } + + return(0); + } + + case CDIOCREADSUBCHANNEL: { + struct ioc_read_subchannel *sc = + (struct ioc_read_subchannel *)data; + + bzero(sc->data, sizeof(struct cd_sub_channel_info)); + sc->data->header.audio_status = CD_AS_NO_STATUS; + + if (sc->address_format == CD_MSF_FORMAT) + sc->data->what.position.reladdr.msf.second = 2; + + return(0); + } + + case CDIOCALLOW: + case CDIOCPREVENT: + return(0); + } + + IFOPT(vn, VN_FOLLOW) { + printf("vnioctl: 0x%lx not implemented\n", cmd); + } + + return(ENOTTY); +} + /* ARGSUSED */ static int vnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) @@ -453,6 +557,10 @@ if (dkslice(dev) != WHOLE_DISK_SLICE || dkpart(dev) != RAW_PART) return (ENOTTY); + } + + IFOPT(vn,VN_CDROM) { + return(cdioctl(vn, cmd, data)); } vn_specific: --- usr.sbin/vnconfig/vnconfig.c Thu Jul 26 20:35:05 2001 +++ usr.sbin/vnconfig/vnconfig.c Thu Jul 26 20:36:40 2001 @@ -234,6 +234,7 @@ char *str; u_long *p; { + if (!strcmp(str,"cdrom")) { *p |= VN_CDROM; return 0; } if (!strcmp(str,"reserve")) { *p |= VN_RESERVE; return 0; } if (!strcmp(str,"labels")) { *p |= VN_LABELS; return 0; } if (!strcmp(str,"follow")) { *p |= VN_FOLLOW; return 0; }