bsdi_ioctl.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 772 行 · 第 1/2 页
C
772 行
switch (s->type) { case DVD_STRUCT_PHYSICAL: return dvd_read_physical(fd, s); case DVD_STRUCT_COPYRIGHT: return dvd_read_copyright(fd, s); case DVD_STRUCT_DISCKEY: return dvd_read_disckey(fd, s); case DVD_STRUCT_BCA: return dvd_read_bca(fd, s); case DVD_STRUCT_MANUFACT: return dvd_read_manufact(fd, s); default: return EINVAL; } }static u_char scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10};static int scsi_cmd(int fd, cgc_t *cgc) { int i, scsistatus, cdblen; unsigned char *cp; struct scsi_user_cdb suc; /* safety checks */ if (cgc->rw != SUC_READ && cgc->rw != SUC_WRITE) return(EINVAL); suc.suc_flags = cgc->rw; cdblen = scsi_cdblen[(cgc->cdb[0] >> 5) & 7]; suc.suc_cdblen = cdblen; bcopy(cgc->cdb, suc.suc_cdb, cdblen); suc.suc_data = cgc->buf; suc.suc_datalen = cgc->buflen; suc.suc_timeout = cgc->timeout; if (ioctl(fd, SCSIRAWCDB, &suc) == -1) return(errno); scsistatus = suc.suc_sus.sus_status;/* * If the device returns a scsi sense error and debugging is enabled print * some hopefully useful information on stderr.*/ if (scsistatus && debug) { cp = suc.suc_sus.sus_sense; fprintf(stderr,"scsistatus = %x cdb =", scsistatus); for (i = 0; i < cdblen; i++) fprintf(stderr, " %x", cgc->cdb[i]); fprintf(stderr, "\nsense ="); for (i = 0; i < 16; i++) fprintf(stderr, " %x", cp[i]); fprintf(stderr, "\n"); } if (cgc->sus) bcopy(&suc.suc_sus, cgc->sus, sizeof (struct scsi_user_sense)); if (scsistatus) return(EIO); /* generic i/o error for unsuccessful status */ return(0); }/* * The entry point for the DVDioctls for BSD/OS.*/static int dvd_ioctl(int fd, u_long cmd, void *arg) { int ret; switch (cmd) { case DVD_READ_STRUCT: ret = dvd_read_struct(fd, (dvd_struct *)arg); if (ret) errno = ret; return(ret ? -1 : 0); case DVD_AUTH: ret = dvd_do_auth(fd, (dvd_authinfo *)arg); if (ret) errno = ret; return(ret ? -1 : 0); default: errno = EINVAL; return(-1); } }/* * The entry point for the CDROMioctls for BSD/OS*/static int cdrom_read_block(int, cgc_t *, int, int, int, int);static int cdrom_read_cd(int, cgc_t *, int, int, int ); int cdrom_blocksize(int, int );static inlineint msf_to_lba(char m, char s, char f){ return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;}cdrom_ioctl(int fd, u_long cmd, void *arg) { int ret; cgc_t cgc; switch (cmd) { case CDROMREADRAW: case CDROMREADMODE1: case CDROMREADMODE2: { struct cdrom_msf *msf; int blocksize = 0, format = 0, lba; switch (cmd) { case CDROMREADRAW: blocksize = CD_FRAMESIZE_RAW; break; case CDROMREADMODE1: blocksize = CD_FRAMESIZE; format = 2; break; case CDROMREADMODE2: blocksize = CD_FRAMESIZE_RAW0; break; } msf = (struct cdrom_msf *)arg; lba = msf_to_lba(msf->cdmsf_min0,msf->cdmsf_sec0, msf->cdmsf_frame0); ret = EINVAL; if (lba < 0) break; cgc_init(&cgc, arg, blocksize, SUC_READ); ret = cdrom_read_block(fd, &cgc, lba, 1, format, blocksize); if (ret) {/* * SCSI-II devices are not required to support CMD_READ_CD (which specifies * the blocksize to read) so try switching the block size with a mode select, * doing the normal read sector command and then changing the sector size back * to 2048. * * If the program dies before changing the blocksize back sdopen() * in the kernel will fail opens with a message that looks something like: * * "sr1: blksize 2336 not multiple of 512: cannot use" * * At that point the drive has to be power cycled (or reset in some other way).*/ if (ret = cdrom_blocksize(fd, blocksize)) break; ret = cdrom_read_cd(fd, &cgc, lba, blocksize, 1); ret |= cdrom_blocksize(fd, 2048); } break; } case CDROMREADTOCHDR: { struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg; u_char buffer[12]; cgc_init(&cgc, buffer, sizeof (buffer), SUC_READ); cgc.cdb[0] = CMD_READ_TOC_PMA_ATIP; cgc.cdb[1] = 0x2; /* MSF */ cgc.cdb[8] = 12; /* LSB of length */ ret = scsi_cmd(fd, &cgc); if (!ret) { tochdr->cdth_trk0 = buffer[2]; tochdr->cdth_trk1 = buffer[3]; } break; } case CDROMREADTOCENTRY: { struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg; u_char buffer[12]; cgc_init(&cgc, buffer, sizeof (buffer), SUC_READ); cgc.cdb[0] = CMD_READ_TOC_PMA_ATIP; cgc.cdb[1] = (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0; cgc.cdb[6] = tocentry->cdte_track; cgc.cdb[8] = 12; /* LSB of length */ ret = scsi_cmd(fd, &cgc); if (ret) break; tocentry->cdte_ctrl = buffer[5] & 0xf; tocentry->cdte_adr = buffer[5] >> 4; tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0; if (tocentry->cdte_format == CDROM_MSF) { tocentry->cdte_addr.msf.minute = buffer[9]; tocentry->cdte_addr.msf.second = buffer[10]; tocentry->cdte_addr.msf.frame = buffer[11]; } else tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) + buffer[10]) << 8) + buffer[11]; break; } case CDROMEJECT: /* NO-OP for now */ ret = cdrom_tray_move(fd, 1); break; case CDROMCLOSETRAY: ret = cdrom_tray_move(fd, 0); break;/* * This sucks but emulates the expected behaviour. Instead of the return * value being the actual status a success/fail indicator should have been * returned and the 3rd arg to the ioctl should have been an 'int *' to update * with the actual status. Both the drive and disc status ioctl calls are * similarily braindamaged.*/ case CDROM_DRIVE_STATUS: return(CDS_NO_INFO); /* XXX */ case CDROM_DISC_STATUS: { tracktype tracks; int cnt; cdrom_count_tracks(fd, &tracks); if (tracks.error) return(tracks.error); if (tracks.audio > 0) { cnt = tracks.data + tracks.cdi + tracks.xa; if (cnt == 0) return(CDS_AUDIO); else return(CDS_MIXED); } if (tracks.cdi) return(CDS_XA_2_2); if (tracks.xa) return(CDS_XA_2_1); if (tracks.data) return(CDS_DATA_1); return(CDS_NO_INFO); } } errno = ret; return(ret ? -1 : 0); }static int cdrom_read_cd(int fd, cgc_t *cgc, int lba, int blocksize, int nblocks) { memset(&cgc->cdb, 0, sizeof(cgc->cdb)); cgc->cdb[0] = CMD_READ_10; cgc->cdb[2] = (lba >> 24) & 0xff; cgc->cdb[3] = (lba >> 16) & 0xff; cgc->cdb[4] = (lba >> 8) & 0xff; cgc->cdb[5] = lba & 0xff; cgc->cdb[6] = (nblocks >> 16) & 0xff; cgc->cdb[7] = (nblocks >> 8) & 0xff; cgc->cdb[8] = nblocks & 0xff; cgc->buflen = blocksize * nblocks; return(scsi_cmd(fd, cgc)); }static int cdrom_read_block(int fd, cgc_t *cgc, int lba, int nblocks, int format, int blksize) { memset(&cgc->cdb, 0, sizeof(cgc->cdb)); cgc->cdb[0] = CMD_READ_CD; /* expected sector size - cdda,mode1,etc. */ cgc->cdb[1] = format << 2; /* starting address */ cgc->cdb[2] = (lba >> 24) & 0xff; cgc->cdb[3] = (lba >> 16) & 0xff; cgc->cdb[4] = (lba >> 8) & 0xff; cgc->cdb[5] = lba & 0xff; /* number of blocks */ cgc->cdb[6] = (nblocks >> 16) & 0xff; cgc->cdb[7] = (nblocks >> 8) & 0xff; cgc->cdb[8] = nblocks & 0xff; cgc->buflen = blksize * nblocks; /* set the header info returned */ switch (blksize) { case CD_FRAMESIZE_RAW0: cgc->cdb[9] = 0x58; break; case CD_FRAMESIZE_RAW1: cgc->cdb[9] = 0x78; break; case CD_FRAMESIZE_RAW: cgc->cdb[9] = 0xf8; break; default: cgc->cdb[9] = 0x10; } return(scsi_cmd(fd, cgc)); }static void cdrom_count_tracks(int fd, tracktype *tracks) { struct cdrom_tochdr header; struct cdrom_tocentry entry; int ret, i; memset(tracks, 0, sizeof (*tracks)); ret = cdrom_ioctl(fd, CDROMREADTOCHDR, &header);/* * This whole business is a crock anyhow so we don't bother distinguishing * between no media, drive not ready, etc and on any error just say we have * no info.*/ if (ret) { tracks->error = CDS_NO_INFO; return; } entry.cdte_format = CDROM_MSF; for (i = header.cdth_trk0; i <= header.cdth_trk1; i++) { entry.cdte_track = i; if (cdrom_ioctl(fd, CDROMREADTOCENTRY, &entry)) { tracks->error = CDS_NO_INFO; return; } if (entry.cdte_ctrl & CDROM_DATA_TRACK) { if (entry.cdte_format == 0x10) tracks->cdi++; else if (entry.cdte_format == 0x20) tracks->xa++; else tracks->data++; } else tracks->audio++; } return; }static int cdrom_tray_move(int fd, int flag) { cgc_t cgc; cgc_init(&cgc, NULL, 0, SUC_READ); cgc.cdb[0] = CMD_START_STOP_UNIT; cgc.cdb[1] = 1; /* immediate */ cgc.cdb[4] = flag ? 0x2 : 0x3; /* eject : close */ return(scsi_cmd(fd, &cgc)); }/* * Required when we need to use READ_10 to issue other than 2048 block * reads */int cdrom_blocksize(int fd, int size) { cgc_t cgc; struct modesel_head mh; memset(&mh, 0, sizeof(mh)); mh.block_desc_length = 0x08; mh.block_length_med = (size >> 8) & 0xff; mh.block_length_lo = size & 0xff; memset(&cgc, 0, sizeof(cgc)); cgc.cdb[0] = 0x15; cgc.cdb[1] = 1 << 4; cgc.cdb[4] = 12; cgc.buflen = sizeof(mh); cgc.buf = (u_char *) &mh; cgc.rw = SUC_WRITE; mh.block_desc_length = 0x08; mh.block_length_med = (size >> 8) & 0xff; mh.block_length_lo = size & 0xff; return(scsi_cmd(fd, &cgc)); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?