📄 cdtest.c
字号:
/* * @(#)cdtest.c 1.1 92/07/30 SMI * Copyright (c) 1989 Sun Microsystems, Inc. * * CD ROM test, which will read the CD ROM table of contents then * read all existing data tracks and play all existing audio tracks * on the CD. If a supported known CD is used, both the TOC and the * first block of all data tracks will also be compared. Upon reading * data tracks, a random number of blocks will be read each time. */#include <stdio.h>#include <fcntl.h>#include <sys/types.h>#include <sys/file.h>#include <sys/time.h>#include "cd.h"#include "sdrtns.h"#include "../../../lib/include/libonline.h" /* online library include *//* Default device name */#define DEVICENAME "/dev/rsr0"/* Data buffer size allocation */#define MAX_DATABUF (128*CDROM_MODE2_SIZE) /* max data buffer size *//* For verbose and debug messages */#define VDEBUG VERBOSE+DEBUG/* Test to be skipped */#define SKIP_NONE 0 /* skip no tracks */#define SKIP_DATA1 1 /* skip data mode 1 tracks */#define SKIP_DATA2 2 /* skip data mode 2 tracks */#define SKIP_AUDIO 4 /* skip audio tracks *//* Data read access mode */#define RANDOM_READ 0 /* random read test */#define SEQUENTIAL_READ 1 /* sequential read test *//* Audio volume limits */#define MIN_VOLUME 0 /* minimum audio volume */#define MAX_VOLUME 255 /* maximum audio volume *//* Error codes */#define ERSYS 10#define ERIOCTL 12#define ERREAD 13#define ERSEEK 14#define ERDATA 15#define ERSTATUS 16/* Global information declarations */char *test_usage = "[D=/dev/raw] [S=data1|data2|audio] [R=random|sequential] [P=0..100] [V=0..255] [T=sony2|hitachi4|cdassist|pdo|other]";int cd_type = CD_DEFAULT; /* CD type under test */int skip_test = SKIP_NONE; /* skip test mask value */int audio_volume = MAX_VOLUME; /* audio volume control */int read_access = RANDOM_READ; /* read access mode */int percent_data = 100; /* percent of data to be tested */u_int randval = 0; /* random value generated */int fd = 0; /* device descriptor */char *databuf = 0; /* data buffer read */struct cdrom_tochdr tochdr; /* CD TOC header */struct cdrom_tocentry *cdtoc = 0; /* CD table of contents */extern char *device_name; /* device name */extern int errno; /* system error code *//* Error messages */char er_ioctl[] = "Fail ioctl %s (%s)";char er_seek[] = "Fail to seek at block %d (%s)";char er_read[] = "Fail to read %d bytes at block %d (%s)";char er_datamode[] = "Data mode %d not supported";char er_open[] = "Fail to open device %s (%s)";char er_mem[] = "Fail to allocate %d bytes of memory";char er_tochdr[] = "Invalid TOC header, first track %d, last track %d";char er_toccmp[] = "CD contains incorrect TOC info";char er_audioerr[] = "Error occurred during audio play at track %d";char er_audioplay[] = "Audio play exceeded %d second time limit at track %d";char er_audiostop[] = "Audio stop before complete at track %d";char er_audiostat[] = "Unexpected audio status %d received at track %d";char er_datacmp[] = "Data miscompare %d bytes at block %d";char warn_play[] = "The play time %d sec exceeds time usually expected (%d sec) at track %d"; /* Forward declarations */extern int errno;int routine_usage();int process_test_args();char *errmsg();char *malloc();#ifndef SVR4long random();#endiflong lseek();/* * Main entry to CD test. */main(argc,argv)int argc;char **argv;{ versionid = "1.1"; /* SCCS version id */ device_name = DEVICENAME; /* set up default device name */ /* Sundiag test start up initialization */ test_init(argc,argv,process_test_args,routine_usage,test_usage); if ((fd = open(device_name,O_RDONLY)) < 0) send_message(ERSYS,ERROR,er_open,device_name,errmsg(errno)); run_cd_test(); /* Sundiag test end condition */ clean_up(); /* expecting this to be in test_end() */ test_end(); return(0);}/* * Function to parse the specific test arguments. * It returns true if option is expected, else returns false. */process_test_args(argv,index)char **argv;int index;{ int match = TRUE; if (!strncmp(argv[index],"D=",2)) { device_name = argv[index]+2; } else if (!strncmp(argv[index],"T=",2)) { for (match = 0; cd_name[match]; match++) { if (!(strcmp(argv[index]+2,cd_name[match]))) break; } if (cd_name[match]) { cd_type = match; match = TRUE; } else match = FALSE; } else if (!strncmp(argv[index],"S=",2)) { if (!strcmp(argv[index]+2,"data1")) skip_test |= SKIP_DATA1; else if (!strcmp(argv[index]+2,"data2")) skip_test |= SKIP_DATA2; else if (!strcmp(argv[index]+2,"audio")) skip_test |= SKIP_AUDIO; else match = FALSE; } else if (!strncmp(argv[index],"R=",2)) { if (!strcmp(argv[index]+2,"random")) read_access = RANDOM_READ; else if (!strcmp(argv[index]+2,"sequential")) read_access = SEQUENTIAL_READ; else match = FALSE; } else if (!strncmp(argv[index],"P=",2)) { percent_data = atoi(argv[index]+2); if (percent_data < 0 || percent_data > 100) match = FALSE; } else if (!strncmp(argv[index],"V=",2)) { audio_volume = atoi(argv[index]+2); if (audio_volume < 0 || audio_volume > MAX_VOLUME) match = FALSE; } else match = FALSE; return(match);}/* * Function to display the test specific options. */routine_usage(){ send_message(NULL,CONSOLE,"CD-ROM test specific options:\n"); send_message(NULL,CONSOLE,"\tD = name of raw device (/dev/rsr?)\n"); send_message(NULL,CONSOLE,"\tS = skip tracks (data1|data2|audio)\n"); send_message(NULL,CONSOLE,"\tR = read access (random|sequential)\n"); send_message(NULL,CONSOLE,"\tP = percentage of data to be tested\n"); send_message(NULL,CONSOLE,"\tV = audio volume (0..255, default 255)\n"); send_message(NULL,CONSOLE,"\tT = type of CD used for test \(sonny2|hitachi4|cdassist|pdo|other)\n\n");}/* * Routine which performs the CD ROM testing. It will read the TOC header * to determine the type of each track, then perform the appropriate test * for data mode 1, data mode2, or audio track. */run_cd_test(){ struct cdrom_tocentry *toc; int track; /* issue START to restart CDROM unit */ if (ioctl(fd,CDROMSTART) < 0) send_message(ERIOCTL,ERROR,er_ioctl,"CDROMSTART",errmsg(errno)); if (!quick_test) sleep(5); /* build and check TOC */ build_check_toc(); /* allocate memory for data read buffer */ if (!(databuf = malloc((u_int)MAX_DATABUF))) send_message(ERSYS,ERROR,er_mem,MAX_DATABUF); /* generate unique random seed */# ifdef SVR4 srand(getpid());# else srandom(getpid());# endif SVR4 /* handle special case for PDO disc before performing test */#define PDO_NBLOCKS 330000 if (cd_type == CD_PDO) { toc = cdtoc; track = tochdr.cdth_trk1; (toc+track)->cdte_addr.lba = PDO_NBLOCKS; } /* read data and play audio in sequential track order */ toc = cdtoc; for (track = tochdr.cdth_trk0; track <= tochdr.cdth_trk1; track++,toc++) { if (toc->cdte_ctrl & CDTRK_DATA) { if (toc->cdte_datamode == CD_DATAMODE1) { /* check if need to skip data mode 1 test */ if (!(skip_test & SKIP_DATA1)) read_data_track(toc); } else { /* check if need to skip data mode 2 test */ if (!(skip_test & SKIP_DATA2)) read_data_track(toc); } } else { /* check if need to skip audio test */ if (!(skip_test & SKIP_AUDIO)) play_audio_track(toc); } } /* issue STOP to reset CDROM unit */ if (ioctl(fd,CDROMSTOP) < 0) send_message(ERIOCTL,ERROR,er_ioctl,"CDROMSTOP",errmsg(errno));}/* * Function to read and save the TOC then check against known TOC data. */build_check_toc(){ u_int size; int track; struct cdrom_tocentry *toc; struct toc_info *info; /* read TOC header */ if (ioctl(fd,CDROMREADTOCHDR,&tochdr) < 0) send_message(ERIOCTL,ERROR,er_ioctl,"CDROMREADTOCHDR",errmsg(errno)); /* check the TOC header info */ if (tochdr.cdth_trk0 < MIN_TRACK || tochdr.cdth_trk1 > MAX_TRACK || tochdr.cdth_trk0 > tochdr.cdth_trk1) send_message(ERDATA,ERROR,er_tochdr,tochdr.cdth_trk0,tochdr.cdth_trk1); send_message(NULL,VDEBUG,"CD table of contents (track %d thru %d)", tochdr.cdth_trk0,tochdr.cdth_trk1); /* allocate memory for TOC entry */ size = (tochdr.cdth_trk1 - tochdr.cdth_trk0 + 2) * sizeof(struct cdrom_tocentry); if (!(cdtoc = (struct cdrom_tocentry *)malloc((u_int)size))) send_message(ERSYS,ERROR,er_mem,size); /* read TOC entry include the lead out track */ toc = cdtoc; for (track = tochdr.cdth_trk0; track <= (tochdr.cdth_trk1+1); track++) { toc->cdte_track = track>tochdr.cdth_trk1 ? CDROM_LEADOUT : track; toc->cdte_format = CDROM_LBA; if (ioctl(fd,CDROMREADTOCENTRY,toc) < 0) send_message(ERIOCTL,ERROR,er_ioctl,"CDROMREADTOCENTRY",errmsg(errno)); send_message(NULL,VDEBUG,"Track %03d, type %d, mode %03d, lba %06d", toc->cdte_track,toc->cdte_ctrl, toc->cdte_datamode,toc->cdte_addr.lba); toc++; } /* check TOC entry if a known supported CD is tested */ if (cd_type != CD_OTHER) { send_message(NULL,VDEBUG,"Compare TOC information (%s)",cd_name[cd_type]); toc = cdtoc - 1; info = cd_tochdr[cd_type] - 1; do { info++; toc++; if (info->track != toc->cdte_track || info->ctrl != toc->cdte_ctrl || info->lba != toc->cdte_addr.lba || info->datamode != toc->cdte_datamode) send_message(ERDATA,ERROR,er_toccmp); } while (toc->cdte_track != CDROM_LEADOUT); }}/* * Function to read the whole specified data track. * Depending on the read access flag, either random or sequential read will * be performed. Each time a random number of blocks will be read. * The first chunk of data in each track will be compared against
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -