#include #include #include #include #include #include #include #include #include #include int fd, err; #define IOCTL(code,arg,prog) if ((err = ioctl(fd, code, &arg))<0) { \ perror("ioctl code failed"); \ } else if (err != 0) { \ printf("ioctl %s returned \"%S\"\n", \ code, strerror(err)); \ } else { \ prog; \ } union params { int dummy; }; union results { char sense; }; void print_drive(struct fd_drive *drive) { printf("Drive characteristics\n" "\tejectable=%d\n" "\tmaxsearch=%d\n" "\tflags=%s%s%s\n\n", drive->fdd_ejectable, drive->fdd_maxsearch, drive->fdd_flags&FDD_READY ? "Ready " : "", drive->fdd_flags&FDD_MOTON ? "Motor_On " : "", drive->fdd_flags&FDD_POLLABLE ? "Pollable" : ""); /* However, the driver never actually sets FDD_READY or FDD_MOTON */ } void print_change(int change) { printf("0x%x Disc %s\n" "\t%s%s%S\n\n", change, change & FDGC_CURRENT ? "Out" : "In", change & FDGC_HISTORY ? " changed" : "", change & FDGC_CURWPROT ? " Write Protected" : "", change & FDGC_DETECTED ? " ?Previous?" : ""); } void print_chars(struct fd_char *chars) { printf("Floppy characteristics\n" "\tdensity: %s\n" "\trate: %d\n" "\tcylnders: %d\n" "\theads: %d\n" "\tsector_size: %d\n" "\tsectors/track: %d\n\n", chars->fdc_medium ? "high" : "medium", chars->fdc_transfer_rate, chars->fdc_ncyl, chars->fdc_nhead, chars->fdc_sec_size, chars->fdc_secptrack); } void show_status() { int i; struct fd_char chars; struct fd_drive drive; int change; drive.fdd_flags = 0; IOCTL(FDGETDRIVECHAR, drive, print_drive(&drive)); IOCTL(FDGETCHANGE, change, print_change(change)); IOCTL(FDIOGCHAR, chars, print_chars(&chars)); } void print_st3(char st3) { printf("ST3=0x%x Drive %d HD %d\n" "\t%s%s\n\n", st3, st3&3, st3&4>>2, st3&16 ? "Track_0 " : "", st3&64 ? "Write Protected" : ""); } void print_st1(char st1) { printf("ST1=0x%x Drive %d HD %d\n" "\t%s%sIC=%d\n\n", st1, st1&3, st1&4>>2, st1&16 ? "EC " : "", st1&32 ? "SE " : "", st1>>6); } void raw_cmd(char cmd, int *p, union results *r, char *bufptr) { struct fd_raw raw; bzero(&raw, sizeof(struct fd_raw)); raw.fdr_cmd[0] = cmd; raw.fdr_addr = bufptr; switch (cmd) { case FDRAW_SENSE_DRV: raw.fdr_cmd[1] = 0; raw.fdr_cnum = 2; IOCTL(FDRAW, raw, print_st3(raw.fdr_result[0])); break; case FDRAW_REZERO: raw.fdr_cmd[1] = 0; raw.fdr_cnum = 2; IOCTL(FDRAW, raw, print_st1(raw.fdr_result[0])); break; case FDRAW_SEEK: raw.fdr_cmd[1] = 0; raw.fdr_cmd[2] = p[0]; raw.fdr_cnum = 3; IOCTL(FDRAW, raw, print_st1(raw.fdr_result[0])); break; default: printf("Raw command %d not implemented\n", (int)cmd); } } void main(int argc, char *argv[]) { char readbuf[32], cmd[32]; int r_cmd, params[8]; if (argc>1) { if ((fd = open(argv[1], O_RDONLY|O_NDELAY))<0) { perror(argv[0]); exit(-1); } } else if (!system("pgrep vold > /dev/null")) { if ((fd = open("/vol/dev/aliases/floppy0", O_RDONLY|O_NDELAY))<0) { fprintf(stderr, "%s: You will need either to stop the Volume Manager,\n" "or else insert a disc and do a 'volcheck'.\n", argv[0]); exit(-1); } } else if ((fd = open("/dev/rdiskette", O_RDONLY|O_NDELAY))<0) { perror(argv[0]); exit(-1); } while ((read(0, &readbuf, 32)) >0) { *strchr(readbuf, '\n') = NULL; if (strlen(readbuf) >0) { strcpy(cmd, readbuf); } if (strcmp(cmd, "status") ==0) { show_status(); } else if (strncmp(cmd, "raw ", 4) ==0) { sscanf(cmd, "raw %d%d", &r_cmd, ¶ms[0]); raw_cmd(r_cmd, params, NULL, NULL); } else { printf("Unrecognized command\n" "Available commands are:\n" " status\n" " raw 4 #FDRAW_SENSE_DRV\n" " raw 7 #FDRAW_REZERO\n" " raw 15 #FDRAW_SEEK\n" " ^D #Exit\n"); } } close(fd); exit(0); }