From 024f069d1f0feb3ecb2eea6b1443536defb01f35 Mon Sep 17 00:00:00 2001 From: Ian C Date: Mon, 7 May 2007 02:05:54 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r2, which included commits to RCS files with non-trunk default branches. --- src/disk.c | 610 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 610 insertions(+) create mode 100644 src/disk.c (limited to 'src/disk.c') diff --git a/src/disk.c b/src/disk.c new file mode 100644 index 0000000..d058154 --- /dev/null +++ b/src/disk.c @@ -0,0 +1,610 @@ +/* + + atarisio - A UNIX backend for an Atari SIO2PC lead. + + Copyright (C) 2004 Ian Cowburn (ianc@noddybox.demon.co.uk) + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + + Disk handling + +*/ +static const char ident[]="$Id$"; + +#include +#include +#include +#include +#include +#include "disk.h" +#include "diskimg.h" +#include "config.h" +#include "token.h" +#include "serial.h" + +static const char ident_h[]=ATARIOSIO_DISK_H; + + + +/* ---------------------------------------- MACROS +*/ +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define HEX_DUMP_LINE 16 + +#define MAX_DRIVE 8 + + +/* ---------------------------------------- STATICS +*/ +static DiskImg drive[MAX_DRIVE]={0}; +static DiskInfo info[MAX_DRIVE]; +static uchar *buff[MAX_DRIVE]={0}; + + +/* ---------------------------------------- PRIVATE FUNCTIONS +*/ +static int Word(uchar lo, uchar hi) +{ + return ((int)hi<<8)|(int)lo; +} + + +static int ParseDrive(const char *p) +{ + int d; + + if (*p++!='d') + return -1; + + d=(*p-'0')-1; + + if (d<0 || d>=MAX_DRIVE) + return -1; + + return d; +} + + + +static void DoMount(int d, const char *p) +{ + drive[d]=DiskImgLoad(p); + + if (!drive[d]) + printf("Disk image error: %s\n",DiskImgError()); + else + { + DiskImgInfo(drive[d],info+d); + buff[d]=Malloc(info[d].bytes_per_sector); + } +} + + +static void DoUnmount(int d) +{ + if (drive[d]) + DiskImgFree(drive[d]); + + drive[d]=NULL; + free(buff[d]); +} + + +static void ShowDir(const uchar *p, unsigned len) +{ + unsigned f; + + if (!p) + return; + + f=0; + + while(f0) + { + DiskImgPutSector(img,sec++,buff); + } + } while(rd==inf.bytes_per_sector); + + fclose(fp); + + free(buff); + } + + if (!DiskImgSave(img,argv[1])) + { + printf("Failed to save image\n"); + } + + DiskImgFree(img); +} + + +static void Ls(int argc, char *argv[]) +{ + int d; + unsigned f; + + if ((d=ParseDrive(argv[1]))==-1) + { + printf("Invalid drive specifier\n"); + return; + } + + if (!drive[d]) + { + printf("Disk not mounted\n"); + return; + } + + for(f=360;f<368;f++) + ShowDir(DiskImgGetSector(drive[d],f),info[d].bytes_per_sector); +} + + +static void Save(int argc, char *argv[]) +{ + int d; + + if ((d=ParseDrive(argv[1]))==-1) + { + printf("Invalid drive specifier\n"); + return; + } + + if (!drive[d]) + { + printf("Disk not mounted\n"); + return; + } + + if (argc==2) + DiskImgSave(drive[d],NULL); + else + DiskImgSave(drive[d],argv[2]); +} + + +/* ---------------------------------------- COMMAND TABLE +*/ +static Command cmd[]= +{ + { + "mount", + 1,3, + "mount [dN file]", + "Mount a disk image", + Mount + }, + { + "umount", + 1,2, + "unmount [dN]", + "Unmount a disk image", + Unmount + }, + { + "readonly", + 3,3, + "readonly dN on|off", + "Set a disk read only/writeable", + ReadOnly + }, + { + "info", + 2,2, + "info dN", + "Returns info on a mounted disk", + Info + }, + { + "sector", + 3,3, + "sector dN sector", + "Hex dumps supplied sector", + Sector + }, + { + "new", + 4,5, + "new path sectors secsize [file]", + "Creates a new disk file, with optional data", + New + }, + { + "ls", + 2,2, + "ls dN", + "Lists directory on disk", + Ls + }, + { + "save", + 2,3, + "save dN [file]", + "Saves a disk back to, er, disk", + Save + } +}; + + +/* ---------------------------------------- SIO HANDLER +*/ +static void StatusHandler(int d, const SIOCommand *cmd) +{ + static uchar status[4]={0x00, 0x00, 0x01, 0x00}; + + usleep(TIME_ACK); + + if (!drive[d]) + { + cmd->putchar(SIO_NACK); + return; + } + + cmd->putchar(SIO_ACK); + + if (info[d].bytes_per_sector==128) + { + if (info[d].sectors>720) + status[0]=0x80; + else + status[0]=0x10; + } + else + status[0]=0x60; + + if (info[d].write_protect) + status[0]|=8; + else + status[0]&=~8; + + usleep(TIME_ACK_TO_COMPLETE); + cmd->putchar(SIO_COMPLETE); + usleep(TIME_COMPLETE_TO_DATA); + cmd->write(status,4); +} + + +static void PutHandler(int d, const SIOCommand *cmd) +{ + int sec; + size_t len; + + sec=Word(cmd->aux1,cmd->aux2); + + usleep(TIME_ACK); + + if (!drive[d] || info[d].write_protect || sec>info[d].sectors) + { + cmd->putchar(SIO_NACK); + return; + } + + if (sec<3) + len=128; + else + len=info[d].bytes_per_sector; + + sec--; + + cmd->putchar(SIO_ACK); + if (cmd->read(buff[d],len)) + { + cmd->putchar(SIO_ACK); + cmd->putchar(SIO_COMPLETE); + } + else + { + cmd->putchar(SIO_NACK); + } +} + + +static void GetHandler(int d, const SIOCommand *cmd) +{ + int sec; + size_t len; + + sec=Word(cmd->aux1,cmd->aux2); + + usleep(TIME_ACK); + + if (!drive[d] || info[d].write_protect || sec>info[d].sectors) + { + cmd->putchar(SIO_NACK); + return; + } + + if (sec<3) + len=128; + else + len=info[d].bytes_per_sector; + + sec--; + + cmd->putchar(SIO_ACK); + usleep(TIME_ACK_TO_COMPLETE); + cmd->putchar(SIO_COMPLETE); + usleep(TIME_COMPLETE_TO_DATA); + + cmd->write(DiskImgGetSector(drive[d],sec),len); +} + + +static void SIOHandler(const SIOCommand *cmd) +{ + switch(cmd->cmd) + { + case eRead: + GetHandler(cmd->device-0x31,cmd); + break; + + case eWrite: + PutHandler(cmd->device-0x31,cmd); + break; + + case eStatus: + StatusHandler(cmd->device-0x31,cmd); + break; + + case ePut: + PutHandler(cmd->device-0x31,cmd); + break; + + case eFormat: + break; + + case eVerifySec: + break; + + case eDownload: + case eReadAddr: + case eReadSpin: + case eMotorOn: + break; + } +} + + +/* ---------------------------------------- EXPORTED INTERFACES +*/ +void DiskInit(void) +{ + int f; + + TokenRegister(sizeof cmd/sizeof cmd[0],cmd); + + for(f=0x31;f<0x31+MAX_DRIVE;f++) + SerialRegister(f,SIOHandler); +} + + +/* END OF FILE */ -- cgit v1.2.3