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. --- INSTALL | 34 +++ LICENSE | 341 ++++++++++++++++++++++++++++++ src/Makefile | 113 ++++++++++ src/config.c | 222 ++++++++++++++++++++ src/config.h | 68 ++++++ src/disk.c | 610 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/disk.h | 39 ++++ src/diskimg.c | 263 +++++++++++++++++++++++ src/diskimg.h | 99 +++++++++ src/main.c | 140 +++++++++++++ src/serial.c | 472 ++++++++++++++++++++++++++++++++++++++++++ src/serial.h | 134 ++++++++++++ src/siorc.example | 17 ++ src/tmp | Bin 0 -> 92176 bytes src/token.c | 257 +++++++++++++++++++++++ src/token.h | 71 +++++++ src/util.c | 165 +++++++++++++++ src/util.h | 82 ++++++++ 18 files changed, 3127 insertions(+) create mode 100644 INSTALL create mode 100644 LICENSE create mode 100644 src/Makefile create mode 100644 src/config.c create mode 100644 src/config.h create mode 100644 src/disk.c create mode 100644 src/disk.h create mode 100644 src/diskimg.c create mode 100644 src/diskimg.h create mode 100644 src/main.c create mode 100644 src/serial.c create mode 100644 src/serial.h create mode 100644 src/siorc.example create mode 100644 src/tmp create mode 100644 src/token.c create mode 100644 src/token.h create mode 100644 src/util.c create mode 100644 src/util.h diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..e5f0064 --- /dev/null +++ b/INSTALL @@ -0,0 +1,34 @@ + +Requirements +============ + +- an ANSI C compiler +- a BSD, UNIX, GNU/Linux, or POSIX like operating system/environment for the + Makefile (though it may work elsewhere OK too). The features used are: + + * POSIX terminal interface + * POSIX threads + * UNIX serial IO ioctls + + +Building +======== + +This program does not unfortunately use the configure script, but I have been +careful to write is as portably as possible. + +To build the software, type the following: + + cd src + make depend + make + +This will output the executable atarisio. Copy this to whereever you like to +keep your binaries. + +There is an example config file in the src directory called siorc.example. +Copy this to ~/.siorc and edit as required. + + +------------------------------------------------------------------------------- +$Id: INSTALL,v 1.1.1.1 2007-05-07 02:05:54 ianc Exp $ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..abd3cf7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,341 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..639860c --- /dev/null +++ b/src/Makefile @@ -0,0 +1,113 @@ +# atarisio - A UNIX back end 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 +# +# ------------------------------------------------------------------------- +# +# $Id: Makefile,v 1.1.1.1 2007-05-07 02:05:54 ianc Exp $ +# + + +# This CFLAGS assumes that gcc is being used. +# Simply comment out if not, and replace as needed. +# +# Note that the -pthread is *IMPORTANT* - this is a FreeBSD extension +# that links with the appropriate libc for pthreads. Consult your OS +# documentation on what to do on other systems. +# +# +CFLAGS = -g -Wall -Werror -pthread + +TARGET = atarisio + +SOURCE = main.c \ + token.c \ + config.c \ + serial.c \ + disk.c \ + diskimg.c \ + util.c + +OBJECTS = main.o \ + token.o \ + serial.o \ + config.o \ + disk.o \ + diskimg.o \ + util.o + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(CFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS) + +clean: + rm -f $(TARGET) $(OBJECTS) core + +depend: + makedepend -- $(CFLAGS) -- $(SOURCE) + if test -e Makefile ; then rm -f Makefile.bak ; fi + +# DO NOT DELETE THIS LINE -- make depend depends on it + +main.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +main.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +main.o: /usr/include/limits.h /usr/include/sys/limits.h +main.o: /usr/include/machine/_limits.h /usr/include/sys/syslimits.h +main.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h +main.o: /usr/include/errno.h /usr/include/unistd.h /usr/include/sys/types.h +main.o: /usr/include/machine/endian.h /usr/include/sys/select.h +main.o: /usr/include/sys/_sigset.h /usr/include/sys/_timeval.h +main.o: /usr/include/sys/timespec.h /usr/include/sys/unistd.h +main.o: /usr/include/fcntl.h serial.h util.h disk.h config.h token.h +token.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +token.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +token.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h +token.o: /usr/include/ctype.h /usr/include/runetype.h token.h util.h +config.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +config.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +config.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h +config.o: config.h util.h token.h +serial.o: /usr/include/pthread.h /usr/include/sys/cdefs.h +serial.o: /usr/include/sys/types.h /usr/include/machine/endian.h +serial.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +serial.o: /usr/include/sys/select.h /usr/include/sys/_sigset.h +serial.o: /usr/include/sys/_timeval.h /usr/include/sys/timespec.h +serial.o: /usr/include/sys/time.h /usr/include/time.h +serial.o: /usr/include/sys/signal.h /usr/include/machine/signal.h +serial.o: /usr/include/machine/trap.h /usr/include/limits.h +serial.o: /usr/include/sys/limits.h /usr/include/machine/_limits.h +serial.o: /usr/include/sys/syslimits.h /usr/include/sched.h +serial.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h +serial.o: /usr/include/ctype.h /usr/include/runetype.h /usr/include/unistd.h +serial.o: /usr/include/sys/unistd.h /usr/include/termios.h +serial.o: /usr/include/sys/ttycom.h /usr/include/sys/ioccom.h +serial.o: /usr/include/sys/ttydefaults.h /usr/include/fcntl.h +serial.o: /usr/include/errno.h serial.h /usr/include/stdlib.h util.h +disk.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +disk.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +disk.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h +disk.o: /usr/include/ctype.h /usr/include/runetype.h disk.h util.h diskimg.h +disk.o: config.h token.h serial.h +diskimg.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +diskimg.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +diskimg.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h +diskimg.o: diskimg.h util.h +util.o: /usr/include/stdio.h /usr/include/sys/cdefs.h +util.o: /usr/include/sys/_types.h /usr/include/machine/_types.h +util.o: /usr/include/string.h /usr/include/strings.h /usr/include/ctype.h +util.o: /usr/include/runetype.h util.h /usr/include/stdlib.h diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..6d05005 --- /dev/null +++ b/src/config.c @@ -0,0 +1,222 @@ +/* + + 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 + + ------------------------------------------------------------------------- + + Config file + +*/ +static const char ident[]="$Id$"; + +#include +#include +#include +#include "config.h" +#include "token.h" + +static const char ident_h[]=ATARIOSIO_CONFIG_H; + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + +/* ---------------------------------------- CONFIG +*/ +static char *serial_path=NULL; +static char *prompt=NULL; + +static const struct +{ + const char *name; + void *var; + int is_int; +} config[]= { + {"device", &serial_path, FALSE}, + {"prompt", &prompt, FALSE}, + {NULL, NULL, FALSE} + }; + + +/* ---------------------------------------- PRIVATE FUNCTIONS +*/ +static void Parse(FILE *fp) +{ + char buff[1024]; + + while(fgets(buff,sizeof buff,fp)) + { + size_t l; + + l=strlen(buff); + + if (buff[l-1]=='\n') + buff[--l]=0; + + if (l>0 && buff[0]!='#') + TokenRun(buff); + } +} + + +static void Set(int argc, char *argv[]) +{ + int f; + + for(f=0;config[f].name;f++) + { + if (strcmp(config[f].name,argv[1])==0) + { + if (config[f].is_int) + { + int *i; + + i=config[f].var; + *i=atoi(argv[2]); + } + else + { + char **p; + + p=config[f].var; + + if (*p) + free(*p); + + *p=StrCopy(argv[2]); + } + } + } +} + + +static void Show(int argc, char *argv[]) +{ + int f; + + if (argc==2) + { + for(f=0;config[f].name;f++) + { + if (strcmp(config[f].name,argv[1])==0) + { + if (config[f].is_int) + { + int *i; + + i=config[f].var; + printf("%s = %d\n",argv[1],*i); + } + else + { + char **p; + + p=config[f].var; + printf("%s = %s\n",argv[1],*p ? *p:"undefined"); + } + } + } + } + else + { + for(f=0;config[f].name;f++) + { + printf("%s = ",config[f].name); + + if (config[f].is_int) + { + int *i; + + i=config[f].var; + printf("%d\n",*i); + } + else + { + char **p; + + p=config[f].var; + printf("%s\n",*p ? *p:"undefined"); + } + } + } +} + + +/* ---------------------------------------- EXPORTED INTERFACES +*/ +int ConfigRead(void) +{ + static Command cmd[2]= + { + {"set",3,3,"set variable value","Set a variable",Set}, + {"show",1,2,"show [variable]","Show variables",Show} + }; + + FILE *fp; + char path[FILENAME_MAX]={0}; + + serial_path=StrCopy("/dev/cuaa0"); + prompt=StrCopy("SIO% "); + + if (getenv("HOME")) + strcpy(path,getenv("HOME")); + + strcat(path,"/.siorc"); + + if (!(fp=fopen(path,"r"))) + return FALSE; + + TokenRegister(2,cmd); + + Parse(fp); + fclose(fp); + + return TRUE; +} + + +int IConfig(IConfigVar v) +{ + static const int *vars[]= + { + NULL + }; + + return *vars[v]; +} + + +const char *SConfig(SConfigVar v) +{ + static char **vars[]= + { + &serial_path, + &prompt + }; + + return (const char *)*vars[v]; +} + + +/* END OF FILE */ diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..8e58514 --- /dev/null +++ b/src/config.h @@ -0,0 +1,68 @@ +/* + + 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 + + ------------------------------------------------------------------------- + + Config file + +*/ + +#ifndef ATARIOSIO_CONFIG_H +#define ATARIOSIO_CONFIG_H "$Id$" + +#include "util.h" + + +/* Integer settings +*/ +typedef enum +{ + CONF_NONE +} IConfigVar; + + +/* String settings +*/ +typedef enum +{ + CONF_DEVICE, + CONF_PROMPT +} SConfigVar; + + +/* Read config file +*/ +int ConfigRead(void); + + +/* Get integer setting +*/ +int IConfig(IConfigVar v); + + +/* Get string setting +*/ +const char *SConfig(SConfigVar v); + + +#endif + + +/* END OF FILE */ 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 */ diff --git a/src/disk.h b/src/disk.h new file mode 100644 index 0000000..952f6ba --- /dev/null +++ b/src/disk.h @@ -0,0 +1,39 @@ +/* + + 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 + +*/ + +#ifndef ATARIOSIO_DISK_H +#define ATARIOSIO_DISK_H "$Id$" + +#include "util.h" + +/* Initialise disk routines +*/ +void DiskInit(void); + +#endif + + +/* END OF FILE */ diff --git a/src/diskimg.c b/src/diskimg.c new file mode 100644 index 0000000..74e0243 --- /dev/null +++ b/src/diskimg.c @@ -0,0 +1,263 @@ +/* + + 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 "diskimg.h" + +static const char ident_h[]=ATARIOSIO_DISKIMG_H; + + + +/* ---------------------------------------- MACROS +*/ +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define MAGIC ('N'+'I'+'C'+'K'+'A'+'T'+'A'+'R'+'I') + +#define WRITE_PROTECT 0x01 + + +/* ---------------------------------------- TYPES +*/ +struct sDiskImg +{ + char *path; + unsigned sectors; + unsigned bps; + int flags; + uchar *data; +}; + + +/* ---------------------------------------- STATICS +*/ +static char error[256]; + + +/* ---------------------------------------- PRIVATE FUNCTIONS +*/ +static unsigned GetWord(FILE *fp) +{ + unsigned w; + int i; + + if ((i=getc(fp))==EOF) + return 0; + + w=i; + + if ((i=getc(fp))==EOF) + return 0; + + w|=i<<8; + + return w; +} + + +static void PutWord(FILE *fp,int w) +{ + uchar c; + + c=(w&0xff); + + putc(c,fp); + + c=(w>>8); + + putc(c,fp); +} + + +/* ---------------------------------------- EXPORTED INTERFACES +*/ +DiskImg DiskImgLoad(const char *path) +{ + FILE *fp; + DiskImg img; + unsigned long hi,lo; + int f; + + if (!(fp=fopen(path,"rb"))) + { + strcpy(error,"Disk file does not exist"); + return NULL; + } + + if (GetWord(fp)!=MAGIC) + { + strcpy(error,"Not an ATR disk file"); + return NULL; + } + + img=Malloc(sizeof *img); + + img->path=StrCopy(path); + + lo=GetWord(fp); + + img->bps=GetWord(fp); + + img->flags=getc(fp); + + hi=GetWord(fp); + + hi=(hi<<16)|lo; + + img->sectors=(hi*16)/img->bps; + + img->data=Malloc(img->sectors*img->bps); + + for(f=0;f<7;f++) + getc(fp); + + for(f=0;fsectors*img->bps;f++) + { + int i; + + if ((i=getc(fp))==EOF) + { + free(img->path); + free(img->data); + free(img); + strcpy(error,"Corrupt disk file - too short"); + return NULL; + } + + img->data[f]=i; + } + + return img; +} + + +const char *DiskImgError(void) +{ + return error; +} + + +const uchar *DiskImgGetSector(DiskImg img, unsigned sector) +{ + if (sector>=img->sectors) + return NULL; + + return img->data+sector*img->bps; +} + + +int DiskImgPutSector(DiskImg img, unsigned sector, const uchar *data) +{ + if (sector>=img->sectors) + return FALSE; + + memcpy(img->data+sector*img->bps,data,img->bps); + + return TRUE; +} + +DiskImg DiskImgNew(unsigned sectors, unsigned bytes_per_sector) +{ + DiskImg img; + + img=Malloc(sizeof *img); + + img->path=StrCopy("blank.atr"); + img->sectors=sectors; + img->bps=bytes_per_sector; + img->flags=0; + img->data=Malloc(sectors*bytes_per_sector); + + return img; +} + + +int DiskImgSave(DiskImg img, const char *path) +{ + unsigned long l; + FILE *fp; + int f; + + if (path) + fp=fopen(path,"wb"); + else + fp=fopen(img->path,"wb"); + + if (!fp) + return FALSE; + + l=(img->sectors/img->bps)/16; + + PutWord(fp,MAGIC); + PutWord(fp,l&0xffff); + PutWord(fp,img->bps); + putc(0,fp); + PutWord(fp,l>>16); + + for(f=0;f<7;f++) + putc(0,fp); + + for(f=0;fsectors*img->bps;f++) + { + putc(img->data[f],fp); + } + + return TRUE; +} + + +void DiskImgFree(DiskImg img) +{ + free(img->path); + free(img->data); + free(img); +} + + +void DiskImgInfo(DiskImg img, DiskInfo *info) +{ + info->sectors=img->sectors; + info->bytes_per_sector=img->bps; + info->write_protect=img->flags&WRITE_PROTECT; +} + + +const char *DiskImgPath(DiskImg img) +{ + return img->path; +} + + +/* END OF FILE */ diff --git a/src/diskimg.h b/src/diskimg.h new file mode 100644 index 0000000..f355c50 --- /dev/null +++ b/src/diskimg.h @@ -0,0 +1,99 @@ +/* + + 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 + +*/ + +#ifndef ATARIOSIO_DISKIMG_H +#define ATARIOSIO_DISKIMG_H "$Id$" + +#include "util.h" + + +/* Type representing a disk +*/ +struct sDiskImg; +typedef struct sDiskImg *DiskImg; + + +/* Type representing disk config +*/ +typedef struct +{ + unsigned sectors; + unsigned bytes_per_sector; + int write_protect; +} DiskInfo; + + +/* Load a disk - returns NULL for error. +*/ +DiskImg DiskImgLoad(const char *path); + + +/* Why the last operation failed +*/ +const char *DiskImgError(void); + + +/* Read a sector (NULL if invalid sector) +*/ +const uchar *DiskImgGetSector(DiskImg img, unsigned sector); + + +/* Write a sector (returns FALSE for invalid sector) +*/ +int DiskImgPutSector(DiskImg img, unsigned sector, + const uchar *data); + + +/* Create a blank disk +*/ +DiskImg DiskImgNew(unsigned sectors, unsigned bytes_per_sector); + + +/* Write a disk image - silently ignored for read only disks. Returns TRUE + for success. If path is NULL then the path the file was loaded from is used. +*/ +int DiskImgSave(DiskImg img, const char *path); + + +/* Free up a disk image +*/ +void DiskImgFree(DiskImg img); + + +/* Returns info on a disk +*/ +void DiskImgInfo(DiskImg img, DiskInfo *info); + + +/* Returns path to a disk +*/ +const char *DiskImgPath(DiskImg img); + + +#endif + + +/* END OF FILE */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..3c9ef78 --- /dev/null +++ b/src/main.c @@ -0,0 +1,140 @@ +/* + + 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 + + ------------------------------------------------------------------------- + +*/ +static const char id[]="$Id$"; + +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "disk.h" +#include "config.h" +#include "token.h" +#include "util.h" + + +/* ---------------------------------------- MACROS +*/ +#define TRUE 1 +#define FALSE 0 + + +/* ---------------------------------------- STATIC +*/ +static int quit=FALSE; + + +/* ---------------------------------------- COMMAND HANDLERS +*/ + +static void Quit(int argc, char *argv[]) +{ + quit=TRUE; +} + + +static void Start(int argc, char *argv[]) +{ + SerialOpen(SConfig(CONF_DEVICE)); +} + + +static void Stop(int argc, char *argv[]) +{ + SerialClose(); +} + + +static void Debug(int argc, char *argv[]) +{ + int flag; + + if (YesNo(argv[1],&flag)) + { + SerialDebug(flag); + } + else + { + printf("Invalid argument\n"); + } +} + + +/* ---------------------------------------- COMMAND TABLE +*/ + +static Command cmd[]= +{ + {"quit", 1,1, "quit", "Exit atarisio", Quit}, + {"start", 1,1, "start", "Start emulation", Start}, + {"stop", 1,1, "stop", "Stop emulation", Stop}, + {"debug", 2,2, "debug on|off", "Switch debug on/off", Debug} +}; + + +/* ---------------------------------------- MAIN +*/ +int main(int argc, char *argv[]) +{ + char buff[1024]; + + TokenRegister(sizeof cmd/sizeof cmd[0],cmd); + SerialInit(); + DiskInit(); + + printf("atarsio, Copyright (C) 2004 Ian Cowburn\n"); + printf("atarsio comes with with ABSOLUTELY NO WARRANTY.\n"); + + if (!ConfigRead()) + { + fprintf(stderr,"Failed to read ~/.siorc\n"); + return EXIT_FAILURE; + } + + if (!quit) + { + printf("%s",SConfig(CONF_PROMPT)); + fflush(stdout); + + while(fgets(buff,sizeof buff,stdin)) + { + TokenRun(buff); + + if (quit) + break; + + printf("%s",SConfig(CONF_PROMPT)); + fflush(stdout); + } + } + + return EXIT_SUCCESS; +} + + +/* END OF FILE */ diff --git a/src/serial.c b/src/serial.c new file mode 100644 index 0000000..6f25892 --- /dev/null +++ b/src/serial.c @@ -0,0 +1,472 @@ +/* + + 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 + + ------------------------------------------------------------------------- + + Serial wrappers. + +*/ +static const char ident[]="$Id$"; + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "serial.h" +#include "token.h" + +static const char ident_h[]=ATARISIO_SERIAL_H; + + +/* ---------------------------------------- MACROS +*/ +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define WHICH (pthread_equal(pthread_self(),thread) ? "READ":"MAIN") + +/* Just as I'm always forgetting how many... +*/ +#define MILLI2MICRO(x) ((x)*1000) + + +/* ---------------------------------------- EXTERN +*/ +const uchar SIO_ACK=0x41; +const uchar SIO_NACK=0x4e; +const uchar SIO_COMPLETE=0x43; +const uchar SIO_ERROR=0x45; + + +/* ---------------------------------------- STATICS +*/ +static int fd=-1; +static SIOCallback devtable[256]={0}; +static int debug=FALSE; +static int thread_created=FALSE; + +static int do_debug; + +static pthread_mutex_t mutex; +static pthread_t thread; + + +/* ---------------------------------------- PRIVATE FUNCTIONS +*/ +static void Error(const char *p) +{ + perror(p); + + if (fd!=-1) + { + if (pthread_equal(pthread_self(),thread)) + { + printf("WARNING: Reader thread exiting - " + "serial port is still open\n"); + pthread_mutex_unlock(&mutex); + pthread_exit(NULL); + } + else + { + printf("Trying to closing serial device\n"); + SerialClose(); + } + } +} + + +static void Fatal(const char *p) +{ + fprintf(stderr,"FATAL: "); + perror(p); + exit(EXIT_FAILURE); +} + + +static void Lock(void) +{ + /* printf("[LOCK %s]\n",WHICH); */ + pthread_mutex_lock(&mutex); +} + + +static void Unlock(void) +{ + /* printf("[UNLOCK %s]\n",WHICH); */ + pthread_mutex_unlock(&mutex); +} + + +void SerialPutchar(uchar c) +{ + if (do_debug) + printf("PUTCHAR: %2.2x (%c)\n",c,isprint(c) ? c:'?'); + + if (write(fd,&c,1)==-1) + { + Error("write:"); + return; + } +} + + +void SerialWrite(const uchar *p, size_t len) +{ + uchar csum; + + if (do_debug) + { + printf("SENDING:\n"); + HexDump(p,len); + } + + csum=Checksum(p,len); + + while(len>0) + { + ssize_t w; + + w=write(fd,p,len); + + if (w==-1) + { + Error("write:"); + return; + } + + p+=w; + len-=w; + } + + write(fd,&csum,1); + + if (do_debug) + printf("CHECKSUM: %2.2x\n",csum); +} + + +int SerialRead(uchar *p, size_t len) +{ + uchar *orig; + uchar csum; + + orig=p; + + while(len>0) + { + ssize_t r; + + r=read(fd,p,len); + + if (r==-1) + { + Error("read:"); + return FALSE; + } + + p+=r; + len-=r; + } + + if (read(fd,&csum,1)!=1) + { + Error("read:"); + return FALSE; + } + + return Checksum(orig,len)==csum; +} + + +/* ---------------------------------------- READER +*/ +static void *ReaderThread(void *p) +{ + SIOCommand cmd; + time_t start; + int st; + int no; + uchar frame[5]; + uchar c; + uchar csum; + + cmd.putchar=SerialPutchar; + cmd.write=SerialWrite; + cmd.read=SerialRead; + + while(TRUE) + { + Lock(); + do_debug=debug; + Unlock(); + + no=0; + + while(no<5) + { + if (read(fd,&c,1)==-1) + Error("read"); + + if (ioctl(fd,TIOCMGET,&st)==-1) + Error("ioctl(TIOCMGET)"); + + if (st&TIOCM_RNG) + { + if (do_debug) + printf("Got byte %d (%c) and RNG set\n", + c,isprint(c) ? c:'?'); + + if (no==0) + start=time(NULL); + + frame[no++]=c; + } + else if (do_debug) + { + printf("Got byte %d (%c) and RNG *NOT* set\n", + c,isprint(c) ? c:'?'); + } + } + + if ((time(NULL)-start)>1) + { + printf("Reader: Got 5 bytes, but too slowly - ignored\n"); + } + else + { + Lock(); + + csum=Checksum(frame,4); + + if (csum==frame[4]) + { + if (do_debug) + { + printf("Frame:\n"); + HexDump(frame,5); + } + + if (devtable[frame[0]]) + { + /* Fill up the command structure + */ + cmd.device=frame[0]; + cmd.cmd=frame[1]; + cmd.aux1=frame[2]; + cmd.aux2=frame[3]; + + /* Let the device do its work + */ + if (do_debug) + printf("Calling handler for device %2.2x\n",cmd.device); + + devtable[cmd.device](&cmd); + } + } + else + { + printf("Reader: Bad checksum, expected %2.2x. Frame:\n",csum); + HexDump(frame,5); + } + + Unlock(); + } + } +} + + +/* ---------------------------------------- COMMAND HANDLERS +*/ +static void Register(int argc, char *argv[]) +{ + int f; + + for(f=0;f<256;f++) + if (devtable[f]) + printf("Device %2.2x regsitered\n",f); +} + + +/* ---------------------------------------- COMMAND TABLE +*/ +static Command cmd[]= +{ + { + "register", + 1,1, + "register", + "Show registered devices", + Register + } +}; + + +/* ---------------------------------------- INTERFACES +*/ +void SerialInit(void) +{ + if (pthread_mutex_init(&mutex,NULL)==-1) + Fatal("pthread_mutex_init"); + + TokenRegister(sizeof cmd/sizeof cmd[0],cmd); +} + + +void SerialOpen(const char *path) +{ + struct termios ios; + + if (fd!=-1) + { + printf("Serial device already open\n"); + return; + } + + fd=open(path,O_RDWR|O_NOCTTY|O_NDELAY); + + if (fd==-1) + { + Error(path); + return; + } + + if (fcntl(fd,F_SETFL,0)==-1) + { + Error("fcntl(F_SETFL,0)"); + return; + } + + if (tcgetattr(fd,&ios)==-1) + { + Error("tcgetattr"); + return; + } + + cfsetispeed(&ios,B19200); + cfsetospeed(&ios,B19200); + + ios.c_cflag|=(CLOCAL|CREAD); + + ios.c_cflag&=~PARENB; + ios.c_cflag&=~CSTOPB; + ios.c_cflag&=~CSIZE; + ios.c_cflag|=CS8; + + /* Not that it'll work if we can't disable it... + */ +#ifdef CRTSCTS + ios.c_cflag&=~CRTSCTS; +#endif + + ios.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG); + + ios.c_iflag&=~(IXON|IXOFF|IXANY); + + ios.c_oflag&=~OPOST; + + if (tcsetattr(fd,TCSANOW,&ios)) + { + Error("tcsetattr"); + return; + } + + if (pthread_create(&thread,NULL,ReaderThread,NULL)==-1) + Fatal("pthread_create"); + + thread_created=TRUE; +} + + +void SerialRegister(int device, SIOCallback func) +{ + if (device<0 || device>255) + { + printf("Illegal device number %d registered\n",device); + return; + } + + Lock(); + devtable[device]=func; + Unlock(); +} + + +void SerialDeregister(int device) +{ + if (device<0 || device>255) + { + printf("Illegal device number %d deregistered\n",device); + return; + } + + Lock(); + devtable[device]=NULL; + Unlock(); +} + + +void SerialDebug(int mode) +{ + Lock(); + debug=mode; + Unlock(); +} + + +void SerialClose(void) +{ + if (fd==-1) + { + printf("Serial not open\n"); + } + + Lock(); + + if (thread_created) + { + printf("Cancelling reader thread..."); + fflush(stdout); + pthread_cancel(thread); + pthread_join(thread,NULL); + printf("Done\n"); + } + + Unlock(); + + close(fd); + + fd=-1; + thread_created=FALSE; +} + + +/* END OF FILE */ diff --git a/src/serial.h b/src/serial.h new file mode 100644 index 0000000..740bed7 --- /dev/null +++ b/src/serial.h @@ -0,0 +1,134 @@ +/* + + 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 + + ------------------------------------------------------------------------- + + Serial wrappers. + +*/ + +#ifndef ATARISIO_SERIAL_H +#define ATARISIO_SERIAL_H "$Id$" + +#include +#include "util.h" + + +/* ---------------------------------------- TYPES +*/ + +/* Private callbacks furnished to registered devices to read/write serial + data. On errors these will not return. Note that SWrite appends the sent + data with its checksum. SRead reads len+1, the last byte being the checksum. + It returns TRUE if the checksum matches. +*/ +typedef void (*SPutchar)(uchar c); +typedef void (*SWrite)(const uchar *p, size_t len); +typedef int (*SRead)(uchar *p, size_t len); + + +/* Constants (usable with SWrite) for Atari ACK, COMPLETE and ERROR repsonses +*/ +extern const uchar SIO_ACK; +extern const uchar SIO_NACK; +extern const uchar SIO_COMPLETE; +extern const uchar SIO_ERROR; + + +/* Microsecond timings +*/ +#define TIME_ACK 85 +#define TIME_ACK_TO_COMPLETE 255 +#define TIME_COMPLETE_TO_DATA 425 + + +/* A command from the Atari +*/ +typedef enum +{ + eRead = 0x52, + eWrite = 0x57, + eStatus = 0x53, + ePut = 0x50, + eFormat = 0x21, + eDownload = 0x20, + eReadAddr = 0x54, + eReadSpin = 0x51, + eMotorOn = 0x55, + eVerifySec = 0x56 +} ESIOCmdType; + + +typedef struct +{ + uchar device; /* The device ID */ + ESIOCmdType cmd; /* The command frame type */ + uchar aux1; /* Data */ + uchar aux2; /* Data */ + SPutchar putchar; /* To write a char to the serial port */ + SWrite write; /* To write to the serial port */ + SRead read; /* To read from the serial port */ +} SIOCommand; + + +/* Interface for recieving SIO commands. Note that this interface is expected + to all serial IO responses, including the initial ACK (in case the device + wants to NACK instead). +*/ +typedef void (*SIOCallback)(const SIOCommand* cmd); + + +/* ---------------------------------------- INTERFACES +*/ + +/* Initialise the serial routines. Must be called first. +*/ +void SerialInit(void); + + +/* Opens the passed serial device and configures it for SIO2PC usage. +*/ +void SerialOpen(const char *path); + + +/* Registers a command handler +*/ +void SerialRegister(int device, SIOCallback func); + + +/* Deregisters a command handler +*/ +void SerialDeregister(int device); + + +/* Switch debug mode on/off +*/ +void SerialDebug(int mode); + + +/* Close the serial device +*/ +void SerialClose(void); + + +#endif + + +/* END OF FILE */ diff --git a/src/siorc.example b/src/siorc.example new file mode 100644 index 0000000..e1d4217 --- /dev/null +++ b/src/siorc.example @@ -0,0 +1,17 @@ +# Example rc file +# +# $Id: siorc.example,v 1.1.1.1 2007-05-07 02:05:54 ianc Exp $ +# + +# Path to the serial device +# +set device /dev/cuaa0 + +# Load up initial disks +# +mount d1 /files/atari/dosdisk + + +# Open up the device +# +start diff --git a/src/tmp b/src/tmp new file mode 100644 index 0000000..05bd099 Binary files /dev/null and b/src/tmp differ diff --git a/src/token.c b/src/token.c new file mode 100644 index 0000000..b71a6cb --- /dev/null +++ b/src/token.c @@ -0,0 +1,257 @@ +/* + + 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 + + ------------------------------------------------------------------------- + + Command parsing and execution + +*/ +static const char ident[]="$Id$"; + +#include +#include +#include +#include + +#include "token.h" + +static const char ident_h[]=ATARIOSIO_TOKEN_H; + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define MAX_ARGS 128 + + +/* ---------------------------------------- STATICS +*/ + +static int no_cmds=0; +static Command *cmd_table=NULL; + + +/* ---------------------------------------- PRIVATE FUNCTIONS +*/ +static int QCompare(const void *a, const void *b) +{ + const Command *ca; + const Command *cb; + + ca=a; + cb=b; + + return strcmp(ca->cmd,cb->cmd); +} + + +static int BCompare(const void *a, const void *b) +{ + const Command *cb; + + cb=b; + + return strcmp(a,cb->cmd); +} + + +static char *GetToken(char **ptr) +{ + char qu=0; + char *tok; + char *p; + + p=*ptr; + + while(*p && isspace(*p)) + p++; + + if (!*p) + return NULL; + + if (*p=='\'' || *p=='"') + qu=*p++; + + tok=p; + + if (qu) + { + while(*p && *p!=qu) + p++; + + if (*p) + *p++=0; + else + printf("Warning: unterminated quotes\n"); + } + else + { + while(*p && !isspace(*p)) + p++; + + if (*p) + *p++=0; + } + + *ptr=p; + + return tok; +} + +static int Split(char *p, char **argv) +{ + int argc=0; + + while((argv[argc]=GetToken(&p))) + { + if (argc==MAX_ARGS) + { + argv[argc]=0; + return argc; + } + + argc++; + } + + return argc; +} + + +static void ShowHelp(const char *usage, const char *help) +{ + int l; + + printf("%s ",usage); + + for(l=strlen(usage);l<35;l++) + putchar('.'); + + printf(" %s\n",help); +} + + +static void HelpCommand(int argc, char *argv[]) +{ + if (argc==1) + { + int f; + + for(f=0;fusage,cmd->help); + } +} + + +static void Init(void) +{ + static Command cmd[]= + { + {"help",1,2,"help [command]","Get help on commands",HelpCommand} + }; + + static int init=FALSE; + + if (!init) + { + init=TRUE; + TokenRegister(sizeof cmd/sizeof cmd[0],cmd); + } +} + + +/* ---------------------------------------- EXPORTED INTERFACES +*/ +void TokenRegister(int no, const Command *cmds) +{ + Init(); + + cmd_table=Realloc(cmd_table,sizeof(*cmds)*(no+no_cmds)); + memcpy(cmd_table+no_cmds,cmds,sizeof(*cmds)*no); + no_cmds+=no; + qsort(cmd_table,no_cmds,sizeof *cmd_table,QCompare); +} + + +int TokenRun(const char *line) +{ + char *p; + char *argv[MAX_ARGS]; + int argc; + int res; + int l; + + if (!(l=strlen(line))) + return FALSE; + + res=FALSE; + + p=StrCopy(line); + + if (p[l-1]=='\n') + p[--l]=0; + + argc=Split(p,argv); + + if (argc) + { + Command *cmd; + + cmd=bsearch(argv[0],cmd_table,no_cmds,sizeof *cmd_table,BCompare); + + if (cmd) + { + if (argc>=cmd->min_args && argc<=cmd->max_args) + { + res=TRUE; + cmd->func(argc,argv); + } + else + { + printf("usage: %s\n",cmd->usage); + } + } + else + { + printf("Unrecognised command %s\n",argv[0]); + } + } + + free(p); + + return res; +} + + +/* END OF FILE */ diff --git a/src/token.h b/src/token.h new file mode 100644 index 0000000..b143aa5 --- /dev/null +++ b/src/token.h @@ -0,0 +1,71 @@ +/* + + 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 + + ------------------------------------------------------------------------- + + Command parsing and execution + +*/ + +#ifndef ATARIOSIO_TOKEN_H +#define ATARIOSIO_TOKEN_H "$Id$" + +#include "util.h" + + +/* ---------------------------------------- TYPES +*/ + +/* A command callback (note argv[0] is the command itself) +*/ +typedef void (*TokenHandler)(int argc, char *argv[]); + + +/* A command. min and max args have to include the command itself. +*/ +typedef struct +{ + const char *cmd; + int min_args; + int max_args; + const char *usage; + const char *help; + TokenHandler func; +} Command; + + + +/* ---------------------------------------- INTERFACES +*/ + +/* Register commands +*/ +void TokenRegister(int no, const Command *cmds); + + +/* Parse a command line. Returns TRUE if command parsed and run. +*/ +int TokenRun(const char *line); + + +#endif + + +/* END OF FILE */ diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..9ea5749 --- /dev/null +++ b/src/util.c @@ -0,0 +1,165 @@ +/* + + 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 + + ------------------------------------------------------------------------- + + Global utilities and types + +*/ +static const char ident[]="$Id$"; + +#include +#include +#include +#include +#include "util.h" + +static const char ident_h[]=ATARISIO_UTIL_H; + +#define HEX_DUMP_LINE 16 + + +/* ---------------------------------------- INTERFACES +*/ +void *Malloc(size_t size) +{ + void *new=malloc(size); + + if (!new) + { + fprintf(stderr,"malloc failed for %lu bytes\n",(unsigned long)size); + exit(EXIT_FAILURE); + } + + return new; +} + + +void *Realloc(void *p, size_t size) +{ + void *new=realloc(p,size); + + if (!new) + { + fprintf(stderr,"realloc failed for %lu bytes\n",(unsigned long)size); + exit(EXIT_FAILURE); + } + + return new; +} + + +char *StrCopy(const char *source) +{ + return strcpy(Malloc(strlen(source)+1),source); +} + + +int YesNo(const char *str, int *flag) +{ + if (strcasecmp(str,"on")==0 || + strcasecmp(str,"yes")==0 || + strcasecmp(str,"1")==0) + { + *flag=1; + return 1; + } + + if (strcasecmp(str,"off")==0 || + strcasecmp(str,"no")==0 || + strcasecmp(str,"0")==0) + { + *flag=0; + return 1; + } + + return 0; +} + + +void HexDump(const uchar *p, size_t len) +{ + char asc[HEX_DUMP_LINE+1]; + size_t f; + + f=0; + + while(f>8); + } + + return (uchar)(sum&0xff); +} + + + +/* END OF FILE */ diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..304e02f --- /dev/null +++ b/src/util.h @@ -0,0 +1,82 @@ +/* + + 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 + + ------------------------------------------------------------------------- + + Global utilities and types + +*/ + +#ifndef ATARISIO_UTIL_H +#define ATARISIO_UTIL_H "$Id$" + +#include + +/* ---------------------------------------- TYPES +*/ + +typedef unsigned char uchar; + + +/* ---------------------------------------- INTERFACES +*/ + +/* Returns result from malloc(size), calling exit() if it fails. +*/ +void *Malloc(size_t size); + + +/* Returns result from realloc(p,size), calling exit() if it fails. +*/ +void *Realloc(void *p, size_t size); + + +/* Copies a string. The result must be freed. +*/ +char *StrCopy(const char *source); + + +/* Set flag TRUE/FALSE depending on the contents of str. + 'on', 'yes' and '1' are TRUE, 'off', 'no' and '0' false. + + Returns FALSE is str is invalid. +*/ +int YesNo(const char *str, int *flag); + + +/* Hex dump to stdout +*/ +void HexDump(const uchar *p, size_t len); + + +/* Get an integer from a string +*/ +int GetInt(const char *p); + + +/* Returns an Atari serial style checksum. +*/ +uchar Checksum(const uchar *p, size_t len); + + +#endif + + +/* END OF FILE */ -- cgit v1.2.3