/*************************************************************************
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.)
*/