/************************************************************************* writeti -- Reads sector images and writes them on floppy disks for the TI-99/4A and Geneve computer family Copyright (C) 2009 Michael Zapf (Michael.Zapf@mizapf.de) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . **************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #define COMMAND 0 #define PHEAD 1 #define LCYL 2 #define LHEAD 3 #define SECTOR 4 #define SECTSIZE 5 #define SECTPERCYL 6 #define GAP 7 #define SIZE2 8 #define FM 1 #define MFM 0 #define SINGLE 1 #define DOUBLE 2 struct geometry_t { int tracks; int sectors; int sides; int rate; int density; int stepping; } geometry; int verbose; struct floppy_raw_cmd raw_cmd; void writetrack(int fdflop, int track, int head, char *buffer) { int tmp, size; // char buffer[ 512 * 2 * 24 ]; raw_cmd.data = buffer; raw_cmd.cmd[PHEAD] = head*4; // 0 and 4 are the sides raw_cmd.cmd[LHEAD] = head; raw_cmd.cmd[SECTOR] = 0; raw_cmd.cmd[SECTSIZE] = 1; // 0 = 128, 1 = 256, 2 = 512, 3 = 1024 ... raw_cmd.cmd[SECTPERCYL] = geometry.sectors; raw_cmd.cmd[GAP] = 0x1b; // not needed, default raw_cmd.cmd[SIZE2] = 0xff; // not needed, default raw_cmd.cmd_count = 9; raw_cmd.length = 0x100 * geometry.sectors; size = raw_cmd.length; raw_cmd.rate = geometry.rate; raw_cmd.flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK; raw_cmd.cmd[COMMAND] = FD_WRITE; if (geometry.density==FM) raw_cmd.cmd[0] &= ~0x40; raw_cmd.cmd[LCYL] = track; raw_cmd.track = raw_cmd.cmd[LCYL]*geometry.stepping; tmp = ioctl( fdflop, FDRAWCMD, &raw_cmd ); printf("Writing track %d, head %d, status %2x\n", track, head, raw_cmd.reply[0]); if ( tmp < 0 ){ perror("error executing command"); exit(1); } } // WEITER: // param.rate ist anscheinend ein Kombi-Wert. Herausfinden, ob man f??r 256- // Byte-Sektoren tats??chlich 0x38 auf rate ORen muss /* Ein paar Werte: Single-sided, 80 tracks, 9 sec/track, 512 byte/sect. Total capacity 360 kB. size = 720 sect = 9 head = 1 track= 80 stretch = 0 gap = 42 rate = 2 spec1 = 223 fmt_gap = 80 Double-sided, 80 tracks, 9 sec/track, 512 byte/sect. Total capacity 720 kB. size = 1440 sect = 9 head = 2 track= 80 stretch = 0 gap = 42 rate = 2 spec1 = 223 fmt_gap = 80 Double-sided, 80 tracks, 18 sec/track, 512 byte/sect. Total capacity 1440 kB. size = 2880 sect = 18 head = 2 track= 80 stretch = 0 gap = 27 rate = 0 spec1 = 207 fmt_gap = 108 floppy->rate: frss sMrr M=2M-Flag sss = sector size rrr = rate f = FM */ static void format_disk(int fdflop) { struct format_descr descr; int track; struct floppy_struct param; param.size = geometry.sectors * geometry.tracks * geometry.sides; param.sect = geometry.sectors; param.head = geometry.sides; param.track = geometry.tracks; param.stretch = (geometry.stepping==2)? FD_STRETCH:0; param.gap = (geometry.sectors < 10)? (char)0x2a : (char)0x1b; param.rate = (char)(geometry.rate | 0x38 | (geometry.density<<7)); // 0x38 = 7 << 3 param.spec1 = (char)220; param.fmt_gap = (char)80; printf("size = %d\n", param.size); printf("sect = %d\n", param.sect); printf("head = %d\n", param.head); printf("track= %d\n", param.track); printf("stretch = %d\n", param.stretch); printf("gap = %d\n", param.gap); printf("rate = %d\n", param.rate); printf("spec1 = %d\n", param.spec1); printf("fmt_gap = %d\n", param.fmt_gap); printf("Formatting ... "); fflush(stdout); if (ioctl(fdflop,FDFMTBEG,NULL) < 0) { perror("\nError when starting formatting"); exit(1); } for (track = 0; track < param.track; track++) { descr.track = track; descr.head = 0; if (ioctl(fdflop, FDFMTTRK, (long)&descr) < 0) { perror("\nError formatting track (1)"); exit(1); } printf("%3d\b\b\b",track); fflush(stdout); if (param.head == 2) { descr.head = 1; if (ioctl(fdflop, FDFMTTRK, (long)&descr) < 0) { perror("\nError formatting track (2)"); exit(1); } } } if (ioctl(fdflop,FDFMTEND,NULL) < 0) { perror("\nError when ending formatting"); exit(1); } printf("done\n"); } int main(int argc, char **argv) { int fdflop, fdfile, i; int index=1; verbose = 0; char c; char *buffer; geometry.stepping = SINGLE; geometry.sectors = 18; geometry.tracks = 40; geometry.rate = 1; geometry.sides = 2; geometry.density = MFM; if (argc < 3) { printf("Usage: writeti [-v] [-r1234] [-f] [-h1] [-s9] [-t40] [-d] infile device (=/dev/fd0)\n"); exit(1); } while ((c = getopt (argc, argv, "vr:fh:s:t:d")) != -1) { switch (c) { case 'v': verbose = 1; break; case 'r': geometry.rate = (int)(optarg[0]-0x30); break; case 'f': geometry.density = FM; break; case 'h': geometry.sides = (int)(optarg[0]-0x30); break; case 's': geometry.sectors = (int)(optarg[0]-0x30); if (optarg[1]!=0) { geometry.sectors = 10*geometry.sectors + (int)(optarg[1]-0x30); if (optarg[2]!=0) { printf("Error: Sector number cannot be higher than 99\n"); exit(1); } } break; case 't': geometry.tracks = (int)(optarg[0]-0x30); if (optarg[1]==0) { printf("Error: Track number must be higher than 9\n"); } else { geometry.tracks = 10*geometry.tracks + (int)(optarg[1]-0x30); if (optarg[2]!=0) { printf("Error: Track number cannot be higher than 99\n"); exit(1); } } break; case 'd': geometry.stepping = DOUBLE; break; } } if (geometry.sectors==9) geometry.density = FM; if (geometry.density==FM) geometry.sectors = 9; if (verbose) { printf("Rate = %d\n", geometry.rate); printf("Single density = %d\n", geometry.density); printf("Sectors = %d\n", geometry.sectors); printf("Heads = %d\n", geometry.sides); printf("physical/logical tracks = %d\n", geometry.stepping); printf("Logical tracks = %d\n", geometry.tracks); } fdflop = open(argv[optind+1], O_ACCMODE | O_NDELAY); if ( fdflop < 0 ){ perror("error opening floppy"); exit(1); } fdfile = open(argv[optind], O_RDONLY); if ( fdfile < 0 ){ perror("error opening input file"); exit(1); } buffer = malloc(geometry.sectors*256); // First format the disk // Funktioniert nicht. Muss noch herausgefunden werden. Eventuell gibt es // Probleme mit Sektorgr????en ungleich 512 (Bug in floppy.c?) // format_disk(fdflop); // Test wiederholt, diesmal mit vorformatierter Diskette (auf dem Geneve formatiert) // Beim Schreiben wird ein Status 0x40 geliefert, der vermutlich Fehler bedeutet. // Bei der anderen Seite kommt dann entsprechend Status 0x44. // Jedenfalls ist nicht auf die Diskette geschrieben worden. Der Test wurde mit // dem 3,5"-Laufwerk durchgef??hrt. Achtung: Der TI schreibt nur die ersten // 40 Tracks, auch wenn das Laufwerk 80 Tracks kann. Er macht auch kein Double // Step! // Achtung: Wenn man eine vorformatierte Diskette nimmt, muss man das Format // von der Diskette ablesen! Dann muss man testen, ob das Image auf die Diskette // geschrieben werden kann (kann sein, dass in Sektor 0 andere Angaben sind) // for (i=0; i < geometry.tracks; i++) { read(fdfile, buffer, geometry.sectors*256); writetrack(fdflop, i, 0, buffer); } if (geometry.sides==2) { for (i=geometry.tracks-1; i >=0; i--) { read(fdfile, buffer, geometry.sectors*256); writetrack(fdflop, i, 1, buffer); } } if (close(fdfile)) perror("close error for input file"); if (close(fdflop)) perror("close error for floppy"); free(buffer); return 0; } /* Neues Ergebnis (11.06.2009) write funktioniert auf vorformatierte 3,5"-Diskette (setdsk 108, format a: /2 /18 /80) mit 720K-Image Ein Status von 0x40/0x44 kann auch bedeuten, dass das Floppy nicht richtig zur??ckgesetzt wurde, denn nach korrekter Zur??cksetzung (cat /dev/fd0) funktionierte das Schreiben. Vorgehen: 1. Geneve formatiert Diskette /2 /18 /80 2. Diskette in PC 3. dsk-Image per writeti auf Diskette schreiben 4. Im Geneve lesen Disk image -> TIFILE-Datei -> imgtool(720K) -> draufschreiben -> writeti -> Lesen im Geneve OK Achtung: Auch darauf achten, dass bei der Trackanalyse nicht f??lschlich 80 Tracks angenommen werden, obwohl nur 40 beschrieben sind. (Kann passieren, wenn tats??chlich einmal 80 Tracks beschrieben werden, danach aber nur 40.) */