M Makefile => Makefile +2 -0
@@ 24,6 24,7 @@ INCLUDE += -I./lib/libchdr/include
INCLUDE += -I./lib/flac/include
INCLUDE += -I./lib/flac/src/include
INCLUDE += -I./lib/bluetooth
+INCLUDE += -I./lib/serial_server/library
PRJ = MiSTer
C_SRC = $(wildcard *.c) \
@@ 35,6 36,7 @@ C_SRC = $(wildcard *.c) \
lib/libco/arm.c
CPP_SRC = $(wildcard *.cpp) \
+ $(wildcard ./lib/serial_server/library/*.cpp) \
$(wildcard ./support/*/*.cpp)
IMG = $(wildcard *.png)
M MiSTer.vcxproj => MiSTer.vcxproj +10 -0
@@ 71,6 71,10 @@
<ClCompile Include="lib\miniz\miniz_tdef.c" />
<ClCompile Include="lib\miniz\miniz_tinfl.c" />
<ClCompile Include="lib\miniz\miniz_zip.c" />
+ <ClCompile Include="lib\serial_server\library\Checksum.cpp" />
+ <ClCompile Include="lib\serial_server\library\Image.cpp" />
+ <ClCompile Include="lib\serial_server\library\Process.cpp" />
+ <ClCompile Include="lib\serial_server\library\Serial.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="menu.cpp" />
<ClCompile Include="offload.cpp" />
@@ 99,6 103,7 @@
<ClCompile Include="support\pcecd\pcecd.cpp" />
<ClCompile Include="support\pcecd\pcecdd.cpp" />
<ClCompile Include="support\pcecd\seektime.cpp" />
+ <ClCompile Include="support\pcxt\pcxt.cpp" />
<ClCompile Include="support\psx\psx.cpp" />
<ClCompile Include="support\sharpmz\sharpmz.cpp" />
<ClCompile Include="support\snes\snes.cpp" />
@@ 143,6 148,10 @@
<ClInclude Include="lib\miniz\miniz_tdef.h" />
<ClInclude Include="lib\miniz\miniz_tinfl.h" />
<ClInclude Include="lib\miniz\miniz_zip.h" />
+ <ClInclude Include="lib\serial_server\library\FlatImage.h" />
+ <ClInclude Include="lib\serial_server\library\Library.h" />
+ <ClInclude Include="lib\serial_server\library\LinuxFile.h" />
+ <ClInclude Include="lib\serial_server\library\LinuxSerial.h" />
<ClInclude Include="logo.h" />
<ClInclude Include="menu.h" />
<ClInclude Include="offload.h" />
@@ 170,6 179,7 @@
<ClInclude Include="support\minimig\minimig_share.h" />
<ClInclude Include="support\neogeo\neogeo_loader.h" />
<ClInclude Include="support\pcecd\pcecd.h" />
+ <ClInclude Include="support\pcxt\pcxt.h" />
<ClInclude Include="support\psx\mcdheader.h" />
<ClInclude Include="support\psx\psx.h" />
<ClInclude Include="support\sharpmz\sharpmz.h" />
M MiSTer.vcxproj.filters => MiSTer.vcxproj.filters +36 -0
@@ 42,6 42,12 @@
<Filter Include="Source Files\lodepng">
<UniqueIdentifier>{9e138a0b-53c4-4ae8-a59b-6b7bf2dcc01b}</UniqueIdentifier>
</Filter>
+ <Filter Include="Header Files\serial_server">
+ <UniqueIdentifier>{6dcec61d-6e11-4dd2-b86b-0e60c7b7815d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\serial_server">
+ <UniqueIdentifier>{63e50b49-7ff8-4651-a8a9-0b17cef3d364}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<None Include="build.sh" />
@@ 232,6 238,21 @@
<ClCompile Include="str_util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="support\pcxt\pcxt.cpp">
+ <Filter>Source Files\support</Filter>
+ </ClCompile>
+ <ClCompile Include="lib\serial_server\library\Checksum.cpp">
+ <Filter>Source Files\serial_server</Filter>
+ </ClCompile>
+ <ClCompile Include="lib\serial_server\library\Image.cpp">
+ <Filter>Source Files\serial_server</Filter>
+ </ClCompile>
+ <ClCompile Include="lib\serial_server\library\Process.cpp">
+ <Filter>Source Files\serial_server</Filter>
+ </ClCompile>
+ <ClCompile Include="lib\serial_server\library\Serial.cpp">
+ <Filter>Source Files\serial_server</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="battery.h">
@@ 450,5 471,20 @@
<ClInclude Include="str_util.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="support\pcxt\pcxt.h">
+ <Filter>Header Files\support</Filter>
+ </ClInclude>
+ <ClInclude Include="lib\serial_server\library\FlatImage.h">
+ <Filter>Header Files\serial_server</Filter>
+ </ClInclude>
+ <ClInclude Include="lib\serial_server\library\Library.h">
+ <Filter>Header Files\serial_server</Filter>
+ </ClInclude>
+ <ClInclude Include="lib\serial_server\library\LinuxFile.h">
+ <Filter>Header Files\serial_server</Filter>
+ </ClInclude>
+ <ClInclude Include="lib\serial_server\library\LinuxSerial.h">
+ <Filter>Header Files\serial_server</Filter>
+ </ClInclude>
</ItemGroup>
</Project>=
\ No newline at end of file
A lib/serial_server/gpl-2.0.txt => lib/serial_server/gpl-2.0.txt +339 -0
@@ 0,0 1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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.
+
+ <signature of Ty Coon>, 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 Lesser General
+Public License instead of this License.
A lib/serial_server/library/Checksum.cpp => lib/serial_server/library/Checksum.cpp +372 -0
@@ 0,0 1,372 @@
+//======================================================================
+//
+// Project: XTIDE Universal BIOS, Serial Port Server
+//
+// File: checksum.cpp - Checksum function and test routines
+
+//
+// XTIDE Universal BIOS and Associated Tools
+// Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
+//
+// 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.
+// Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+//
+
+//
+// This file implements Fletcher's Checksum. The serial code uses this checksum, as it is very quick
+// to calculate in assembly and offers reasonable error detection.
+// For more information, see http://en.wikipedia.org/wiki/Fletcher%27s_checksum.
+//
+// Since it is faster in 8088 assembly code to deal with 16-bit quantities than 8-bit quantities,
+// Fletcher's Checksum has been modified to calculate the 32-bit checksum, and then "fold" the result into a
+// 16-bit quantity. Fletcher's 32-bit Checksum consists of two parts: concatenated 16-bit accumulators.
+// To "fold" to 16-bits, The upper and lower 8-bits of each of these accumulators is XOR'd independently, and then
+// the two results concatenated together, resulting in 16-bits. Although simpler, an early attempt to XOR the
+// 16-bit accumulators results in poorer error detection behavior. Folding as described here results in error
+// detection on par with Fletcher's 16-bit Checksum.
+//
+// With #define CHECKSUM_TEST, this file becomes a self-contained command line program that runs
+// some statistical tests comparing various checksum algorithms with random 512-byte sectors and various
+// levels of errors introduced.
+//
+
+#include "Library.h"
+
+unsigned short checksum( unsigned short *wbuff, int wlen )
+{
+ unsigned long a = 0xffff;
+ unsigned long b = 0xffff;
+ int t;
+
+ for( t = 0; t < wlen; t++ )
+ {
+ a += wbuff[t];
+ b += a;
+ }
+
+ a = (a & 0xffff) + (a >> 16);
+ b = (b & 0xffff) + (b >> 16);
+ a = (a & 0xffff) + (a >> 16);
+ b = (b & 0xffff) + (b >> 16);
+
+// Although tempting to use, for its simplicity and size/speed in assembly, the following folding
+// algorithm results in many undetected single bit errors and therefore should not be used.
+// return( (unsigned short) (a ^ b) );
+
+ return( (unsigned short) (((a & 0xff) << 8) ^ (a & 0xff00)) + (((b & 0xff00) >> 8) ^ (b & 0xff)) );
+}
+
+#ifdef CHECKSUM_TEST
+
+//====================================================================================================
+//
+// Test Code
+//
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <math.h>
+
+#define BUCKETS 65536
+#define BITTEST 16
+
+unsigned char bit[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+
+class algorithm
+{
+public:
+ virtual unsigned short checksum( unsigned char *data, int len ) = 0;
+ char *title;
+ unsigned long *found;
+ unsigned long zero;
+ unsigned long total;
+ unsigned long empty;
+ unsigned long min;
+ unsigned long max;
+ double stdev;
+ unsigned long bittest[ BITTEST ];
+ unsigned long missed[ BITTEST ];
+ algorithm *next;
+ algorithm( algorithm *last, char *new_title );
+};
+
+algorithm::algorithm( algorithm *last, char *new_title )
+{
+ zero = total = empty = min = max = 0;
+ stdev = 0.0;
+ for( int t = 0; t < BITTEST; t++ )
+ {
+ bittest[t] = missed[t] = 0;
+ }
+ title = new_title;
+ next = last;
+}
+
+//----------------------------------------------------------------------------------------------------
+//
+// Standard CRC-16
+//
+// http://sanity-free.org/134/standard_crc_16_in_csharp.html
+//
+
+static unsigned short crc16_table[256];
+
+class crc16_algorithm : public algorithm
+{
+public:
+ crc16_algorithm( algorithm *last ) : algorithm( last, (char *) "crc-16" )
+ {
+ unsigned short value;
+ unsigned short temp;
+ unsigned short i;
+ unsigned short j;
+
+ for(i = 0; i < 256; ++i)
+ {
+ value = 0;
+ temp = i;
+ for(j = 0; j < 8; ++j) {
+ if(((value ^ temp) & 0x0001) != 0) {
+ value = (unsigned short)((value >> 1) ^ this->crc16_polynomial);
+ }else {
+ value >>= 1;
+ }
+ temp >>= 1;
+ }
+ crc16_table[i] = value;
+ }
+ }
+
+ unsigned short checksum( unsigned char *data, int len );
+
+private:
+ static const unsigned short crc16_polynomial = 0xA001;
+};
+
+unsigned short crc16_algorithm::checksum( unsigned char *data, int len )
+{
+ unsigned short crc = 0;
+ int i;
+
+ for(i = 0; i < len; ++i)
+ {
+ unsigned char index = (unsigned char)(crc ^ data[i]);
+ crc = (unsigned short)((crc >> 8) ^ crc16_table[index]);
+ }
+
+ return( crc );
+}
+
+//----------------------------------------------------------------------------------------------------
+//
+// Basic checksum (just add up the bytes)
+//
+
+class basic_algorithm : public algorithm
+{
+public:
+ unsigned short checksum( unsigned char *data, int len );
+ basic_algorithm( algorithm *last ) : algorithm( last, (char *) "basic" ) { };
+};
+
+unsigned short basic_algorithm::checksum( unsigned char *bbuff, int blen )
+{
+ unsigned short sum = 0;
+ int i;
+ for( i = 0; i < blen; i++ )
+ {
+ sum += bbuff[ i ];
+ }
+ return( sum );
+}
+
+class fletcher16_algorithm : public algorithm
+{
+public:
+ unsigned short checksum( unsigned char *data, int len );
+ fletcher16_algorithm( algorithm *last ) : algorithm( last, (char *) "f-16" ) { }
+};
+
+unsigned short fletcher16_algorithm::checksum( unsigned char* data, int count )
+{
+ unsigned short sum1 = 0;
+ unsigned short sum2 = 0;
+ int index;
+
+ for( index = 0; index < count; ++index )
+ {
+ sum1 = (sum1 + data[index]) % 255;
+ sum2 = (sum2 + sum1) % 255;
+ }
+
+ return (sum2 << 8) | sum1;
+}
+
+//----------------------------------------------------------------------------------------------------
+//
+// Folded Fletcher's Checksum (what we use in the serial code, from the top of this file)
+//
+
+class folded_fletcher32_algorithm : public algorithm
+{
+public:
+ unsigned short checksum( unsigned char *data, int len );
+ folded_fletcher32_algorithm( algorithm *last ) : algorithm( last, (char *) "fold-f-32" ) { }
+};
+
+unsigned short folded_fletcher32_algorithm::checksum( unsigned char* data, int count )
+{
+ return( ::checksum( (unsigned short *) data, count/2 ) );
+}
+
+//----------------------------------------------------------------------------------------------------
+//
+// Test Driver and Support routines
+//
+
+void randomize_buff( unsigned char *bbuff, int blen )
+{
+ int i;
+ for( i = 0; i < blen; i++ )
+ bbuff[i] = rand() % 255;
+}
+
+#define BBUFF_LENGTH 512
+
+unsigned char bbuff[ BBUFF_LENGTH ];
+
+int main( int argc, char *argv[] )
+{
+ algorithm *a, *algorithms;
+
+ unsigned short c;
+
+ double p;
+ double average;
+
+ unsigned long iterations;
+
+ time_t now;
+
+ algorithms = new folded_fletcher32_algorithm( NULL );
+ algorithms = new fletcher16_algorithm( algorithms );
+ algorithms = new crc16_algorithm( algorithms );
+ algorithms = new basic_algorithm( algorithms );
+
+ time( &now );
+ srand((unsigned int)now);
+
+ if( argc != 2 )
+ {
+ fprintf( stderr, "usage: checksum number_of_iterations\n" );
+ exit( 1 );
+ }
+ else
+ iterations = atol( argv[1] );
+
+#define PRINTROW( E, F, G ) { printf( E ); for( a = algorithms; a; a = a->next ) printf( F, G ); printf( "\n" ); }
+
+ printf( "\nnumber of iterations: %d\n\n", iterations );
+ PRINTROW( " ", "%10s ", a->title );
+ PRINTROW( "=======", "============", NULL );
+
+ for( a = algorithms; a; a = a->next )
+ {
+ a->found = (unsigned long *) calloc( BUCKETS, sizeof(long) );
+
+ a->zero = (unsigned long) a->checksum( bbuff, BBUFF_LENGTH );
+
+ a->min = iterations+1;
+ }
+
+ printf( "\n" );
+ PRINTROW( "zero ", "%10d ", a->zero );
+
+ for( int t = 0; t < iterations; t++ )
+ {
+ randomize_buff( bbuff, BBUFF_LENGTH );
+
+ for( a = algorithms; a; a = a->next )
+ a->found[ a->checksum( bbuff, BBUFF_LENGTH ) ]++;
+ }
+
+ average = iterations / 65536.0;
+
+ for( int t = 0; t < 65536; t++ )
+ {
+ for( a = algorithms; a; a = a->next )
+ {
+ a->total += a->found[ t ];
+ if( !a->found[ t ] )
+ a->empty++;
+ if( a->found[ t ] > a->max )
+ a->max = a->found[ t ];
+ if( a->found[ t ] < a->min )
+ a->min = a->found[ t ];
+ p = a->found[ t ] - average;
+ a->stdev += p*p;
+ }
+ }
+
+ p = 1.0 / (65536.0-1.0);
+ for( a = algorithms; a; a = a->next )
+ {
+ a->stdev = sqrt( p * a->stdev );
+ if( a->total != iterations )
+ fprintf( stderr, "Bad %s\n", a->title );
+ }
+
+ printf( "\nchecksum distribution test:\n" );
+ PRINTROW( "empty ", "%10d ", a->empty );
+ PRINTROW( "min ", "%10d ", a->min );
+ PRINTROW( "max ", "%10d ", a->max );
+ PRINTROW( "stdev ", "%10.4lf ", a->stdev );
+
+ for( int t = 0; t < iterations; t++ )
+ {
+ randomize_buff( bbuff, BBUFF_LENGTH );
+
+ for( int b = 0; b < BITTEST; b++ )
+ {
+ for( a = algorithms; a; a = a->next )
+ {
+ a->bittest[ b ] = (a->checksum)( bbuff, BBUFF_LENGTH );
+ }
+
+ bbuff[ rand() % 512 ] ^= bit[ rand() % 8 ];
+
+ if( b > 0 )
+ {
+ for( a = algorithms; a; a = a->next )
+ {
+ if( a->bittest[ 0 ] == a->bittest[ b ] )
+ a->missed[ b ]++;
+ }
+ }
+ }
+ }
+
+ printf( "\nbit change test:\n" );
+ for( int t = 1; t < BITTEST; t++ )
+ {
+ printf( "%2d ", t );
+ for( a = algorithms; a; a = a->next )
+ printf( "%7d ", a->missed[ t ] );
+ printf( "\n" );
+ }
+}
+
+#endif
+
+
+
+
A lib/serial_server/library/FlatImage.h => lib/serial_server/library/FlatImage.h +97 -0
@@ 0,0 1,97 @@
+//======================================================================
+//
+// Project: XTIDE Universal BIOS, Serial Port Server
+//
+// File: FlatImage.h - Header file for basic flat disk image support
+//
+
+//
+// XTIDE Universal BIOS and Associated Tools
+// Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
+//
+// 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.
+// Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+//
+
+#include "Library.h"
+#include <string.h>
+
+class FlatImage : public Image
+{
+private:
+ class FileAccess fp;
+
+public:
+ FlatImage( char *name, int p_readOnly, int p_drive, int p_create, unsigned long p_cyl, unsigned long p_head, unsigned long p_sect, int p_useCHS ) : Image( name, p_readOnly, p_drive, p_create, p_cyl, p_head, p_sect, p_useCHS )
+ {
+ //long filesize;
+
+ if( p_create )
+ {
+ char buff[512];
+ unsigned long size;
+ double sizef;
+ FileAccess cf;
+ char sizeChar;
+
+ size = (unsigned long) p_cyl * (unsigned long) p_sect * (unsigned long) p_head;
+ if( size > cf.MaxSectors )
+ log( -1, "'%s', can't create flat file with size greater than %lu 512-byte sectors", name, cf.MaxSectors );
+ sizef = size / 2048.0; // 512 byte sectors -> MB
+ sizeChar = 'M';
+ if( sizef < 1 )
+ {
+ sizef *= 1024;
+ sizeChar = 'K';
+ }
+
+ if( cf.Create( name ) )
+ {
+ memset( &buff[0], 0, 512 );
+ while( size-- )
+ cf.Write( &buff[0], 512 );
+
+ if( p_cyl > 1024 )
+ log( 0, "Created file '%s', size %.2lf %cB", name, sizef, sizeChar );
+ else
+ log( 0, "Created file '%s', geometry %u:%u:%u, size %.2lf %cB", name, p_cyl, p_head, p_sect, sizef, sizeChar );
+ cf.Close();
+ }
+ }
+
+ fp.Open( name );
+
+ totallba = fp.SizeSectors();
+
+ init( name, p_readOnly, p_drive, p_cyl, p_head, p_sect, p_useCHS );
+ }
+
+ ~FlatImage()
+ {
+ fp.Close();
+ }
+
+ void seekSector( unsigned long lba )
+ {
+ fp.SeekSectors( lba );
+ }
+
+ void writeSector( void *buff )
+ {
+ fp.Write( buff, 512 );
+ }
+
+ void readSector( void *buff )
+ {
+ fp.Read( buff, 512 );
+ }
+};
+
A lib/serial_server/library/Image.cpp => lib/serial_server/library/Image.cpp +498 -0
@@ 0,0 1,498 @@
+//======================================================================
+//
+// Project: XTIDE Universal BIOS, Serial Port Server
+//
+// File: image.cpp - Abstract base class for disk image support
+//
+
+//
+// XTIDE Universal BIOS and Associated Tools
+// Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
+//
+// 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.
+// Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+//
+
+#include "Library.h"
+#include <memory.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+unsigned int hdd_table[128][3] = {
+ { 306, 4, 17 }, /* 0 - 7 */
+ { 615, 2, 17 },
+ { 306, 4, 26 },
+ { 1024, 2, 17 },
+ { 697, 3, 17 },
+ { 306, 8, 17 },
+ { 614, 4, 17 },
+ { 615, 4, 17 },
+
+ { 670, 4, 17 }, /* 8 - 15 */
+ { 697, 4, 17 },
+ { 987, 3, 17 },
+ { 820, 4, 17 },
+ { 670, 5, 17 },
+ { 697, 5, 17 },
+ { 733, 5, 17 },
+ { 615, 6, 17 },
+
+ { 462, 8, 17 }, /* 016-023 */
+ { 306, 8, 26 },
+ { 615, 4, 26 },
+ { 1024, 4, 17 },
+ { 855, 5, 17 },
+ { 925, 5, 17 },
+ { 932, 5, 17 },
+ { 1024, 2, 40 },
+
+ { 809, 6, 17 }, /* 024-031 */
+ { 976, 5, 17 },
+ { 977, 5, 17 },
+ { 698, 7, 17 },
+ { 699, 7, 17 },
+ { 981, 5, 17 },
+ { 615, 8, 17 },
+ { 989, 5, 17 },
+
+ { 820, 4, 26 }, /* 032-039 */
+ { 1024, 5, 17 },
+ { 733, 7, 17 },
+ { 754, 7, 17 },
+ { 733, 5, 26 },
+ { 940, 6, 17 },
+ { 615, 6, 26 },
+ { 462, 8, 26 },
+
+ { 830, 7, 17 }, /* 040-047 */
+ { 855, 7, 17 },
+ { 751, 8, 17 },
+ { 1024, 4, 26 },
+ { 918, 7, 17 },
+ { 925, 7, 17 },
+ { 855, 5, 26 },
+ { 977, 7, 17 },
+
+ { 987, 7, 17 }, /* 048-055 */
+ { 1024, 7, 17 },
+ { 823, 4, 38 },
+ { 925, 8, 17 },
+ { 809, 6, 26 },
+ { 976, 5, 26 },
+ { 977, 5, 26 },
+ { 698, 7, 26 },
+
+ { 699, 7, 26 }, /* 056-063 */
+ { 940, 8, 17 },
+ { 615, 8, 26 },
+ { 1024, 5, 26 },
+ { 733, 7, 26 },
+ { 1024, 8, 17 },
+ { 823, 10, 17 },
+ { 754, 11, 17 },
+
+ { 830, 10, 17 }, /* 064-071 */
+ { 925, 9, 17 },
+ { 1224, 7, 17 },
+ { 940, 6, 26 },
+ { 855, 7, 26 },
+ { 751, 8, 26 },
+ { 1024, 9, 17 },
+ { 965, 10, 17 },
+
+ { 969, 5, 34 }, /* 072-079 */
+ { 980, 10, 17 },
+ { 960, 5, 35 },
+ { 918, 11, 17 },
+ { 1024, 10, 17 },
+ { 977, 7, 26 },
+ { 1024, 7, 26 },
+ { 1024, 11, 17 },
+
+ { 940, 8, 26 }, /* 080-087 */
+ { 776, 8, 33 },
+ { 755, 16, 17 },
+ { 1024, 12, 17 },
+ { 1024, 8, 26 },
+ { 823, 10, 26 },
+ { 830, 10, 26 },
+ { 925, 9, 26 },
+
+ { 960, 9, 26 }, /* 088-095 */
+ { 1024, 13, 17 },
+ { 1224, 11, 17 },
+ { 900, 15, 17 },
+ { 969, 7, 34 },
+ { 917, 15, 17 },
+ { 918, 15, 17 },
+ { 1524, 4, 39 },
+
+ { 1024, 9, 26 }, /* 096-103 */
+ { 1024, 14, 17 },
+ { 965, 10, 26 },
+ { 980, 10, 26 },
+ { 1020, 15, 17 },
+ { 1023, 15, 17 },
+ { 1024, 15, 17 },
+ { 1024, 16, 17 },
+
+ { 1224, 15, 17 }, /* 104-111 */
+ { 755, 16, 26 },
+ { 903, 8, 46 },
+ { 984, 10, 34 },
+ { 900, 15, 26 },
+ { 917, 15, 26 },
+ { 1023, 15, 26 },
+ { 684, 16, 38 },
+
+ { 1930, 4, 62 }, /* 112-119 */
+ { 967, 16, 31 },
+ { 1013, 10, 63 },
+ { 1218, 15, 36 },
+ { 654, 16, 63 },
+ { 659, 16, 63 },
+ { 702, 16, 63 },
+ { 1002, 13, 63 },
+
+ { 854, 16, 63 }, /* 119-127 */
+ { 987, 16, 63 },
+ { 995, 16, 63 },
+ { 1024, 16, 63 },
+ { 1036, 16, 63 },
+ { 1120, 16, 59 },
+ { 1054, 16, 63 },
+ { 0, 0, 0 }
+};
+
+struct floppyInfo floppyInfos[] =
+{
+ { 1, 2949120 / 512, 6, 80, 2, 36 }, // 2.88MB 3.5"
+ { 0, 2867200 / 512, 6, 80, 2, 36 }, // 2.88MB 3.5" (alternate spelling with 2.8)
+ { 0, 2969600 / 512, 6, 80, 2, 36 }, // 2.88MB 3.5" (alternate spelling with 2.9)
+ { 1, 1474560 / 512, 4, 80, 2, 18 }, // 1.44MB 3.5"
+ { 0, 1433600 / 512, 4, 80, 2, 18 }, // 1.44MB 3.5" (alternate spelling with 1.4)
+ { 1, 1228800 / 512, 2, 80, 2, 15 }, // 1.2MB 5.25"
+ { 1, 737280 / 512, 3, 80, 1, 18 }, // 720KB 3.5"
+ { 1, 368640 / 512, 1, 40, 2, 9 }, // 360KB 5.25"
+ { 1, 327680 / 512, 0, 40, 2, 8 }, // 320KB 5.25"
+ { 1, 184320 / 512, 0, 40, 1, 9 }, // 180KB 5.25" single sided
+ { 1, 163840 / 512, 0, 40, 1, 8 }, // 160KB 5.25" single sided
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+struct hddInfo hddInfos[] = { { 0, 0, 0, 0 } };
+
+struct floppyInfo *FindFloppyInfoBySize( double size )
+{
+ struct floppyInfo *fi;
+
+ for( fi = floppyInfos; fi->size != 0 && !(size+5 > fi->size && size-5 < fi->size); fi++ ) ;
+
+ if( fi->size == 0 )
+ fi = NULL;
+
+ return( fi );
+}
+
+struct hddInfo* FindHDDInfoBySize(unsigned long size)
+{
+ struct hddInfo* fi;
+ unsigned long size_chs;
+ bool is_chs = false;
+
+
+ for (int i = 0; i < 127; i++) {
+ size_chs = ((unsigned long)hdd_table[i][0]) * (unsigned long)hdd_table[i][1] * (unsigned long)hdd_table[i][2] * 512;
+ if (size == size_chs)
+ {
+ fi = hddInfos;
+ fi->size = size;
+ fi->cylinders = hdd_table[i][0];
+ fi->heads = hdd_table[i][1];
+ fi->sectors = hdd_table[i][2];
+ is_chs = true;
+ break;
+ }
+ }
+
+ if (!is_chs)
+ fi = NULL;
+
+ return(fi);
+}
+
+void flipEndian( unsigned short *buff, unsigned int len )
+{
+ for( unsigned int t = 0; t < len/2; t++ )
+ buff[t] = (buff[t] & 0xff) << 8 | (buff[t] & 0xff00) >> 8;
+}
+
+Image::Image( const char *, int, int, int, unsigned long, unsigned long, unsigned long, int)
+{
+}
+
+
+void Image::init( const char *name, int p_readOnly, int p_drive, unsigned long p_cyl, unsigned long p_head, unsigned long p_sect, int p_useCHS )
+{
+ double sizef;
+ char sizeChar;
+ struct floppyInfo *f;
+
+ for( const char *c = shortFileName = name; *c; c++ )
+ if( *c == '\\' || *c == '/' || *c == ':' )
+ shortFileName = c+1;
+
+ if( *(shortFileName) == 0 )
+ {
+ log( 1, "Can't parse '%s' for short file name\n\n", name );
+ shortFileName = "SerDrive";
+ }
+
+ readOnly = p_readOnly;
+ drive = p_drive;
+
+ if( totallba > 0xfffffff ) // lba28 limit - 28 bits
+ log( -1, "'%s', Image size larger than LBA28 maximum of 137,438,952,960 bytes, %lu", name, totallba );
+
+ if( totallba == 0 )
+ log( -1, "'%s', Image size zero?" );
+
+ floppy = 0;
+ for( f = floppyInfos; f->size && !(f->size == totallba && f->real); f++ ) ;
+ if( f->size )
+ {
+ floppy = 1;
+ floppyType = f->type;
+ p_useCHS = 1;
+ p_cyl = f->cylinders;
+ p_head = f->heads;
+ p_sect = f->sectors;
+ totallba = p_cyl * p_head * p_sect;
+ }
+
+ if( p_cyl )
+ {
+ if( (p_sect > 255 || p_sect < 1) || (p_head > 16 || p_head < 1) || (p_cyl > 65536 || p_cyl < 1) )
+ log( -1, "'%s', parts of the CHS geometry (%lu:%lu:%lu) are out of the range (1-65536:1-16:1-255)", name, p_cyl, p_head, p_sect );
+ else if( totallba != (p_sect * p_head * p_cyl) )
+ log( -1, "'%s', file size does not match geometry", name );
+ sect = p_sect;
+ head = p_head;
+ cyl = p_cyl;
+ }
+ else
+ {
+ if( totallba > 65536*16*63 )
+ {
+ log( 0, "'%s': Warning: Image size is greater than derived standard CHS maximum, limiting CHS to 65535:16:63, consider using -g to specify geometry", name );
+ cyl = 65536;
+ head = 16;
+ sect = 63;
+ }
+ else if( (totallba % 16) != 0 || ((totallba/16) % 63) != 0 )
+ {
+ log( -1, "'%s', file size does not match standard CHS geometry (x:16:63), please specify geometry explicitly with -g", name );
+ }
+ else
+ {
+ sect = 63;
+ head = 16;
+ cyl = (totallba / sect / head);
+ if( cyl > 65536 )
+ {
+ log( -1, "'%s', derived standard CHS geometry of %lu:16:63 is has more cylinders than 65536, please specify geometry explicitly with -g", name, cyl, head, sect );
+ }
+ }
+ }
+
+ useCHS = p_useCHS;
+
+ sizef = totallba/2048.0;
+ sizeChar = 'M';
+ if( sizef < 1 )
+ {
+ sizef *= 1024;
+ sizeChar = 'K';
+ }
+ if( useCHS )
+ log( 0, "%s: %s with CHS geometry %u:%u:%u, size %.2lf %cB",
+ name, (floppy ? "Floppy Disk" : "Hard Disk"), cyl, head, sect, sizef, sizeChar );
+ else
+ log( 0, "%s: %s with %lu LBA sectors, size %.2lf %cB (CHS geometry %u:%u:%u)",
+ name, (floppy ? "Floppy Disk" : "Hard Disk"), totallba, sizef, sizeChar, cyl, head, sect );
+}
+
+int Image::parseGeometry( char *str, unsigned long *p_cyl, unsigned long *p_head, unsigned long *p_sect )
+{
+ char *c, *s, *h;
+ unsigned long cyl, sect, head;
+
+ c = str;
+ for( h = c; *h && *h != ':' && *h != 'x' && *h != 'X'; h++ ) ;
+ if( !*h )
+ return( 0 );
+
+ *h = '\0';
+ h++;
+ for( s = h+1; *s && *s != ':' && *s != 'x' && *s != 'X'; s++ ) ;
+ if( !*s )
+ return( 0 );
+
+ *s = '\0';
+ s++;
+
+ cyl = atol(c);
+ head = atol(h);
+ sect = atol(s);
+
+ if( cyl == 0 || sect == 0 || head == 0 )
+ return( 0 );
+
+ *p_cyl = cyl;
+ *p_head = head;
+ *p_sect = sect;
+
+ return( 1 );
+}
+
+#define ATA_wGenCfg 0
+#define ATA_wCylCnt 1
+#define ATA_wHeadCnt 3
+#define ATA_wBpTrck 4
+#define ATA_wBpSect 5
+#define ATA_wSPT 6
+
+#define ATA_strSerial 10
+#define ATA_strSerial_Length 20
+
+#define ATA_strFirmware 23
+#define ATA_strFirmware_Length 8
+
+#define ATA_strModel 27
+#define ATA_strModel_Length 40 // Maximum allowable length of the string according to the ATA spec
+#define XTIDEBIOS_strModel_Length 30 // Maximum length copied out of the ATA information by the BIOS
+
+#define ATA_wCaps 49
+#define ATA_wCurCyls 54
+#define ATA_wCurHeads 55
+#define ATA_wCurSPT 56
+#define ATA_dwCurSCnt 57
+#define ATA_dwLBACnt 60
+
+// Words carved out of the vendor specific area for our use
+//
+#define ATA_wSerialServerVersion 157
+#define ATA_wSerialDriveFlags 158
+#define ATA_wSerialPortAndBaud 159
+
+// Defines used in the words above
+//
+#define ATA_wCaps_LBA 0x200
+
+#define ATA_wGenCfg_FIXED 0x40
+
+// These are all shifted by 1 bit to the right, so that SerialDPT_Finalize can shift them into proper position
+// and shift the high order bit into the carry flag to indicate a floppy drive is present.
+//
+#define ATA_wSerialDriveFlags_Floppy 0x88
+#define ATA_wSerialDriveFlags_Present 0x02
+#define ATA_wSerialDriveFlags_FloppyType_FieldPosition 4
+
+struct comPorts {
+ unsigned long port;
+ unsigned char com;
+};
+struct comPorts supportedComPorts[] =
+{
+ { 0x3f8, '1' },
+ { 0x2f8, '2' },
+ { 0x3e8, '3' },
+ { 0x2e8, '4' },
+ { 0x2f0, '5' },
+ { 0x3e0, '6' },
+ { 0x2e0, '7' },
+ { 0x260, '8' },
+ { 0x368, '9' },
+ { 0x268, 'A' },
+ { 0x360, 'B' },
+ { 0x270, 'C' },
+ { 0, 0 }
+};
+
+void Image::respondInquire( unsigned short *buff, unsigned short originalPortAndBaud, struct baudRate *baudRate, unsigned short port, unsigned char scan )
+{
+ char formatBuff[ 128 ];
+ char speedBuff[XTIDEBIOS_strModel_Length];
+
+ memset( &buff[0], 0, 514 );
+
+ if( scan )
+ {
+ unsigned short comPort = 0;
+ struct comPorts *cp;
+
+ if( port )
+ {
+ for( cp = supportedComPorts; cp->port && cp->port != port; cp++ ) ;
+ if( cp->port )
+ comPort = cp->com;
+ }
+
+ if( comPort )
+ sprintf( speedBuff, " (COM%c/%s)", comPort, baudRate->display );
+ else
+ sprintf( speedBuff, " %s (%s baud)", shortFileName, baudRate->display );
+
+ sprintf( formatBuff, "%.*s%s ", XTIDEBIOS_strModel_Length - strlen(speedBuff), shortFileName, speedBuff );
+ }
+ else
+ sprintf( formatBuff, "%.*s ", XTIDEBIOS_strModel_Length, shortFileName );
+ strncpy( (char *) &buff[ATA_strModel], formatBuff, ATA_strModel_Length );
+ flipEndian( &buff[ATA_strModel], ATA_strModel_Length );
+
+ strncpy( (char *) &buff[ATA_strSerial], "SerialDrive ", ATA_strSerial_Length );
+ flipEndian( &buff[ATA_strSerial], ATA_strSerial_Length );
+
+ sprintf( formatBuff, "%d.%d ", SERIAL_SERVER_MAJORVERSION, SERIAL_SERVER_MINORVERSION );
+ strncpy( (char *) &buff[ATA_strFirmware], formatBuff, ATA_strFirmware_Length );
+ flipEndian( &buff[ATA_strFirmware], ATA_strFirmware_Length );
+
+ buff[ ATA_wCylCnt ] = cyl;
+ buff[ ATA_wHeadCnt ] = head;
+ buff[ ATA_wSPT ] = sect;
+
+ if( !useCHS )
+ {
+ buff[ ATA_wCaps ] = ATA_wCaps_LBA;
+ buff[ ATA_dwLBACnt ] = (unsigned short) (totallba & 0xffff);
+ buff[ ATA_dwLBACnt+1 ] = (unsigned short) (totallba >> 16);
+ }
+
+ // We echo back the port and baud that we were called on from the client,
+ // the client then uses this value to finalize the DPT.
+ //
+ buff[ ATA_wSerialPortAndBaud ] = originalPortAndBaud;
+
+ // In case the client requires a specific server version...
+ //
+ buff[ ATA_wSerialServerVersion ] = (SERIAL_SERVER_MAJORVERSION << 8) | SERIAL_SERVER_MINORVERSION;
+
+ buff[ ATA_wSerialDriveFlags ] = ATA_wSerialDriveFlags_Present;
+ if( floppy )
+ buff[ ATA_wSerialDriveFlags ] |=
+ ATA_wSerialDriveFlags_Floppy | (floppyType << ATA_wSerialDriveFlags_FloppyType_FieldPosition);
+
+ // we always set this, so that the bulk of the BIOS will consider this disk as a hard disk
+ //
+ buff[ ATA_wGenCfg ] = ATA_wGenCfg_FIXED;
+}
+
A lib/serial_server/library/Library.h => lib/serial_server/library/Library.h +104 -0
@@ 0,0 1,104 @@
+//======================================================================
+//
+// Project: XTIDE Universal BIOS, Serial Port Server
+//
+// File: library.h - Include file for users of the library
+//
+
+//
+// XTIDE Universal BIOS and Associated Tools
+// Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
+//
+// 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.
+// Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+//
+
+#ifndef LIBRARY_H_INCLUDED
+#define LIBRARY_H_INCLUDED
+
+#define SERIAL_SERVER_MAJORVERSION 1
+#define SERIAL_SERVER_MINORVERSION 0
+
+#include <termios.h>
+
+void log( int level, const char *message, ... );
+
+unsigned long GetTime(void);
+unsigned long GetTime_Timeout(void);
+
+unsigned short checksum( unsigned short *wbuff, int wlen );
+
+struct floppyInfo {
+ unsigned char real;
+ unsigned long size;
+ unsigned char type;
+ unsigned char cylinders;
+ unsigned char heads;
+ unsigned char sectors;
+};
+
+struct hddInfo {
+ unsigned long size;
+ unsigned long cylinders;
+ unsigned long heads;
+ unsigned long sectors;
+};
+
+struct floppyInfo *FindFloppyInfoBySize( double size );
+struct hddInfo* FindHDDInfoBySize(unsigned long size);
+
+class Image
+{
+public:
+ virtual void seekSector( unsigned long lba ) = 0;
+
+ virtual void writeSector( void *buff ) = 0;
+
+ virtual void readSector( void *buff ) = 0;
+
+ Image( const char *name, int p_readOnly, int p_drive );
+ Image( const char *name, int p_readOnly, int p_drive, int p_create, unsigned long p_lba );
+ Image( const char *name, int p_readOnly, int p_drive, int p_create, unsigned long p_cyl, unsigned long p_head, unsigned long p_sect, int p_useCHS );
+
+ virtual ~Image() {};
+
+ unsigned long cyl, sect, head;
+ unsigned char floppy, floppyType;
+ int useCHS;
+
+ unsigned long totallba;
+
+ const char *shortFileName;
+ int readOnly;
+ int drive;
+
+ static int parseGeometry( char *str, unsigned long *p_cyl, unsigned long *p_head, unsigned long *p_sect );
+
+ void respondInquire( unsigned short *buff, unsigned short originalPortAndBaud, struct baudRate *baudRate, unsigned short port, unsigned char scan );
+
+ void init( const char *name, int p_readOnly, int p_drive, unsigned long p_cyl, unsigned long p_head, unsigned long p_sect, int p_useCHS );
+};
+
+struct baudRate {
+ unsigned long rate;
+ unsigned char divisor;
+ const char *display;
+ speed_t speed;
+};
+struct baudRate *baudRateMatchString( const char *str );
+struct baudRate *baudRateMatchDivisor( unsigned char divisor );
+
+#include <LinuxSerial.h>
+#include <LinuxFile.h>
+
+void processRequests( SerialAccess *serial, Image *image0, Image *image1, int timeoutEnabled, int verboseLevel );
+
+#endif
A lib/serial_server/library/LinuxFile.h => lib/serial_server/library/LinuxFile.h +140 -0
@@ 0,0 1,140 @@
+//======================================================================
+//
+// Project: XTIDE Universal BIOS, Serial Port Server
+//
+// File: Win32File.h - Microsoft Windows file system access.
+//
+// Routines for accessing the file system under Win32. It's important
+// to use these direct Win32 calls for large files, since FILE * routines,
+// in particular ftell() and fseek(), are limited to signed 32-bits (2 GB).
+// These are also likely faster since they are more direct.
+//
+
+//
+// XTIDE Universal BIOS and Associated Tools
+// Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
+//
+// 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.
+// Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+//
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "../library/Library.h"
+
+class FileAccess
+{
+public:
+ int Create( char *p_name )
+ {
+ fp = open(p_name, O_CREAT | O_EXCL | O_RDWR, 0666);
+
+ if( fp < 0 )
+ {
+ if( errno == EEXIST )
+ {
+ log( 0, "'%s', file already exists", p_name );
+ return( 0 );
+ }
+ else
+ log( -1, "'%s', could not create file", p_name );
+ }
+
+ name = p_name;
+
+ return( 1 );
+ }
+
+ void Open( char *p_name )
+ {
+ fp = open(p_name, O_RDWR);
+
+ if( fp < 0 )
+ log( -1, "'%s', could not open file", p_name );
+
+ name = p_name;
+ }
+
+ void Close()
+ {
+ if( fp )
+ {
+ if( close( fp ) )
+ log( 0, "'%s', could not close file handle", name ? name : "unknown" );
+ }
+ }
+
+ unsigned long SizeSectors(void)
+ {
+ struct stat64 st;
+ unsigned long i;
+
+ if( fstat64( fp, &st ) )
+ log( -1, "'%s', could not retrieve file size (error %i)", name, errno );
+
+ if( st.st_size & 0x1ff )
+ log( -1, "'%s', file size is not a multiple of 512 byte sectors", name );
+
+ if( (st.st_size >> 32) > 0x1f )
+ log( -1, "'%s', file size greater than LBA28 limit of 137,438,952,960 bytes", name );
+
+ i = st.st_size >> 9;
+
+ return( (unsigned long) i );
+ }
+
+ void SeekSectors( unsigned long lba )
+ {
+ off64_t offset, result;
+
+ offset = lba;
+ offset <<= 9;
+
+ result = lseek64(fp, offset, SEEK_SET);
+ if( result < 0 || result != offset)
+ log( -1, "'%s', Failed to seek to lba=%lu", name, lba );
+ }
+
+ void Read( void *buff, long len )
+ {
+ long out_len;
+
+ out_len = read(fp, buff, len);
+ if( out_len < 0 || len != out_len )
+ log( -1, "'%s', ReadFile failed", name );
+ }
+
+ void Write( void *buff, long len )
+ {
+ long out_len;
+
+ out_len = write(fp, buff, len);
+ if( out_len < 0 || len != out_len )
+ log( -1, "'%s', WriteFile failed", name );
+ }
+
+ FileAccess()
+ {
+ fp = 0;
+ name = NULL;
+ }
+
+ // LBA 28 limit - 28-bits (could be 1 more, but not worth pushing it)
+ const static unsigned long MaxSectors = 0xfffffff;
+#define USAGE_MAXSECTORS "137438 MB (LBA28 limit)"
+
+private:
+ int fp;
+ char *name;
+};
+
A lib/serial_server/library/LinuxSerial.h => lib/serial_server/library/LinuxSerial.h +122 -0
@@ 0,0 1,122 @@
+//======================================================================
+//
+// Project: XTIDE Universal BIOS, Serial Port Server
+//
+// File: Win32Serial.h - Microsoft Windows serial code
+//
+
+//
+// XTIDE Universal BIOS and Associated Tools
+// Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
+//
+// 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.
+// Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+//
+
+#include <stdio.h>
+#include <unistd.h>
+#include <termios.h>
+#include <errno.h>
+#include <fcntl.h>
+#include "../library/Library.h"
+
+#define PIPENAME "\\\\.\\pipe\\xtide"
+
+class SerialAccess
+{
+public:
+ void Connect( const char *name, struct baudRate *p_baudRate )
+ {
+// char buff1[20], buff2[1024];
+
+ baudRate = p_baudRate;
+
+ pipe = -1;
+
+ if( !access(name, R_OK | W_OK) )
+ {
+ struct termios state;
+
+ log( 0, "Opening %s (%s baud)", name, baudRate->display );
+
+ pipe = open(name, O_RDWR);
+ if( pipe < 0 )
+ log( -1, "Could not Open \"%s\"", name );
+
+ tcgetattr(pipe, &state);
+ cfmakeraw(&state);
+ state.c_cflag |= CRTSCTS | CLOCAL;
+ state.c_lflag &= ~ECHO;
+ cfsetispeed(&state, baudRate->speed);
+ cfsetospeed(&state, baudRate->speed);
+ tcsetattr(pipe, TCSAFLUSH, &state);
+ }
+ else
+ log( -1, "Serial port '%s' not found", name );
+ }
+
+ void Disconnect()
+ {
+ if( pipe )
+ {
+ close( pipe );
+ pipe = -1;
+ }
+ }
+
+ unsigned long readCharacters( void *buff, unsigned long len )
+ {
+ long readLen;
+// int ret;
+
+ readLen = read(pipe, buff, len);
+
+ if( readLen < 0 )
+ log( -1, "read serial failed (error code %i)", errno );
+
+ return( readLen );
+ }
+
+ int writeCharacters( void *buff, unsigned long len )
+ {
+ long writeLen;
+// int ret;
+
+ writeLen = write(pipe, buff, len);
+
+ if( writeLen < 0 )
+ log( -1, "write serial failed (error code %i)", errno );
+
+ return( 1 );
+ }
+
+ SerialAccess()
+ {
+ pipe = 0;
+ speedEmulation = 0;
+ resetConnection = 0;
+ baudRate = NULL;
+ }
+
+ ~SerialAccess()
+ {
+ Disconnect();
+ }
+
+ int speedEmulation;
+ int resetConnection;
+
+ struct baudRate *baudRate;
+
+private:
+ int pipe;
+};
+
A lib/serial_server/library/Process.cpp => lib/serial_server/library/Process.cpp +404 -0
@@ 0,0 1,404 @@
+//======================================================================
+//
+// Project: XTIDE Universal BIOS, Serial Port Server
+//
+// File: process.cpp - Processes commands received over the serial port
+//
+
+//
+// XTIDE Universal BIOS and Associated Tools
+// Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
+//
+// 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.
+// Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+//
+
+#include "Library.h"
+#include <memory.h>
+#include <string.h>
+#include <stdio.h>
+
+union _buff {
+ struct {
+ unsigned char command;
+ unsigned char driveAndHead;
+ unsigned char count;
+ unsigned char sector;
+ unsigned short cylinder;
+ } chs;
+ struct {
+ unsigned char command;
+ unsigned char bits24;
+ unsigned char count;
+ unsigned char bits00;
+ unsigned char bits08;
+ unsigned char bits16;
+ } lba;
+ struct {
+ unsigned char command;
+ unsigned char driveAndHead;
+ unsigned char count;
+ unsigned char scan;
+ unsigned char port;
+ unsigned char baud;
+ } inquire;
+ struct {
+ unsigned char command;
+ unsigned char driveAndHead;
+ unsigned char count;
+ unsigned char scan;
+ unsigned short PackedPortAndBaud;
+ } inquirePacked;
+ unsigned char b[514];
+ unsigned short w[257];
+} buff;
+
+#define SERIAL_COMMAND_HEADER 0xa0
+
+#define SERIAL_COMMAND_WRITE 1
+#define SERIAL_COMMAND_READWRITE 2
+#define SERIAL_COMMAND_RWMASK 3
+#define SERIAL_COMMAND_INQUIRE 0
+
+#define SERIAL_COMMAND_MASK 0xe3
+#define SERIAL_COMMAND_HEADERMASK 0xe0
+
+#define ATA_COMMAND_LBA 0x40
+#define ATA_COMMAND_HEADMASK 0xf
+
+#define ATA_DriveAndHead_Drive 0x10
+
+void logBuff( const char *message, unsigned long buffoffset, unsigned long readto, int verboseLevel )
+{
+ char logBuff[ 514*9 + 10 ];
+ unsigned long logCount;
+
+ if( verboseLevel == 5 || (verboseLevel >= 3 && buffoffset == readto) )
+ {
+ if( verboseLevel == 3 && buffoffset > 11 )
+ logCount = 11;
+ else
+ logCount = buffoffset;
+
+ for(unsigned long t = 0; t < logCount; t++ )
+ sprintf( &logBuff[t*9], "[%3lu:%02x] ", t, buff.b[t] );
+ if( logCount != buffoffset )
+ sprintf( &logBuff[logCount*9], "... " );
+
+ log( 3, "%s%s", message, logBuff );
+ }
+}
+
+void processRequests( SerialAccess *serial, Image *image0, Image *image1, int timeoutEnabled, int verboseLevel )
+{
+ unsigned char workCommand;
+ int workOffset, workCount;
+
+ unsigned long mylba = 0;
+ unsigned long readto;
+ unsigned long buffoffset;
+ unsigned long lasttick;
+ unsigned short crc;
+ unsigned long GetTime_Timeout_Local;
+ unsigned long len;
+ Image *img = NULL;
+ unsigned long cyl = 0, sect = 0, head = 0;
+ unsigned long perfTimer = 0;
+ unsigned char lastScan;
+
+ GetTime_Timeout_Local = GetTime_Timeout();
+
+ buffoffset = 0;
+ readto = 0;
+ workCount = workOffset = workCommand = 0;
+ lastScan = 0;
+
+ //
+ // Floppy disks must come after any hard disks
+ //
+ if( (image0 && image0->floppy) && (image1 && !image1->floppy) )
+ {
+ img = image0;
+ image0 = image1;
+ image1 = img;
+ }
+
+ lasttick = GetTime();
+
+ while( (len = serial->readCharacters( &buff.b[buffoffset], (readto ? readto-buffoffset : 1) )) )
+ {
+ buffoffset += len;
+
+ //
+ // For debugging, look at the incoming packet
+ //
+ if( verboseLevel >= 3 )
+ logBuff( " Received: ", buffoffset, readto, verboseLevel );
+
+ if( timeoutEnabled && readto && GetTime() > lasttick + GetTime_Timeout_Local )
+ {
+ log( 1, "Timeout waiting on data from client, aborting previous command" );
+
+ workCount = workOffset = workCommand = 0;
+ readto = 0;
+
+ if( len <= 8 && (buff.b[buffoffset-len] & SERIAL_COMMAND_HEADERMASK) == SERIAL_COMMAND_HEADER )
+ {
+ // assume that we are at the front of a new command
+ //
+ memcpy( &buff.b[0], &buff.b[buffoffset-len], len );
+ buffoffset = len;
+ readto = 8;
+ // fall through to normal processing
+ }
+ else if( len == 1 )
+ {
+ // one new character, treat it like any other new character received, discarding the buffer
+ //
+ buff.b[0] = buff.b[buffoffset-1];
+ buffoffset = 1;
+ // fall through to normal processing
+ }
+ else
+ {
+ // discard even the newly received data and start listening anew
+ //
+ buffoffset = 0;
+ continue;
+ }
+ }
+
+ lasttick = GetTime();
+
+ //
+ // No work currently to do, look at each character as they come in...
+ //
+ if( !readto )
+ {
+ if( (buff.b[0] & SERIAL_COMMAND_HEADERMASK) == SERIAL_COMMAND_HEADER )
+ {
+ //
+ // Found our command header byte to start a commnad sequence, read the next 7 and evaluate
+ //
+ readto = 8;
+ continue;
+ }
+ else
+ {
+ //
+ // Spurious characters, discard
+ //
+ if( verboseLevel >= 2 )
+ {
+ if( buff.b[0] >= 0x20 && buff.b[0] <= 0x7e )
+ log( 2, "Spurious: [%d:%c]", buff.b[0], buff.b[0] );
+ else
+ log( 2, "Spurious: [%d]", buff.b[0] );
+ }
+ buffoffset = 0;
+ continue;
+ }
+ }
+
+ //
+ // Partial packet received, keep reading...
+ //
+ if( readto && buffoffset < readto )
+ continue;
+
+ //
+ // Read 512 bytes from serial port, only one command reads that many characters: Write Sector
+ //
+ if( buffoffset == readto && readto == 514 )
+ {
+ buffoffset = readto = 0;
+ if( (crc = checksum( &buff.w[0], 256 )) != buff.w[256] )
+ {
+ log( 0, "Bad Write Sector Checksum" );
+ continue;
+ }
+
+ if( img->readOnly )
+ {
+ log( 1, "Attempt to write to read-only image" );
+ continue;
+ }
+
+ img->seekSector( mylba + workOffset );
+ img->writeSector( &buff.w[0] );
+
+ //
+ // Echo back the CRC
+ //
+ if( !serial->writeCharacters( &buff.w[256], 2 ) )
+ break;
+
+ workOffset++;
+ workCount--;
+
+ if( workCount )
+ readto = 1; // looking for continuation ACK
+ }
+
+ //
+ // 8 byte command received, or a continuation of the previous command
+ //
+ else if( (buffoffset == readto && readto == 8) ||
+ (buffoffset == readto && readto == 1 && workCount) )
+ {
+ buffoffset = readto = 0;
+ if( workCount )
+ {
+ if( verboseLevel > 1 )
+ log( 2, " Continuation: Offset=%u, Checksum=%04x", workOffset-1, buff.w[256] );
+
+ //
+ // Continuation...
+ //
+ if( buff.b[0] != (workCount-0) )
+ {
+ log( 0, "Continue Fault: Received=%d, Expected=%d", buff.b[0], workCount );
+ workCount = 0;
+ continue;
+ }
+ }
+ else
+ {
+ //
+ // New Command...
+ //
+ if( (crc = checksum( &buff.w[0], 3 )) != buff.w[3] )
+ {
+ log( 0, "Bad Command Checksum: %02x %02x %02x %02x %02x %02x %02x %02x, Checksum=%04x",
+ buff.b[0], buff.b[1], buff.b[2], buff.b[3], buff.b[4], buff.b[5], buff.b[6], buff.b[7], crc);
+ continue;
+ }
+
+ img = (buff.inquire.driveAndHead & ATA_DriveAndHead_Drive) ? image1 : image0;
+
+ workCommand = buff.chs.command & SERIAL_COMMAND_RWMASK;
+
+ if( (workCommand != SERIAL_COMMAND_INQUIRE) && (buff.chs.driveAndHead & ATA_COMMAND_LBA) )
+ {
+ mylba = ((((unsigned long) buff.lba.bits24) & ATA_COMMAND_HEADMASK) << 24)
+ | (((unsigned long) buff.lba.bits16) << 16)
+ | (((unsigned long) buff.lba.bits08) << 8)
+ | ((unsigned long) buff.lba.bits00);
+ }
+ else
+ {
+ cyl = buff.chs.cylinder;
+ sect = buff.chs.sector;
+ head = (buff.chs.driveAndHead & ATA_COMMAND_HEADMASK);
+ mylba = img ? (((cyl*img->head + head)*img->sect) + sect-1) : 0;
+ }
+
+ workOffset = 0;
+ workCount = buff.chs.count;
+
+ if( verboseLevel > 0 )
+ {
+ const char *comStr = (workCommand & SERIAL_COMMAND_WRITE ? "Write" : "Read");
+
+ if( workCommand == SERIAL_COMMAND_INQUIRE )
+ log( 1, "Inquire %d: Client Port=0x%x, Client Baud=%s", img == image0 ? 0 : 1,
+ ((unsigned short) buff.inquire.port) << 2,
+ baudRateMatchDivisor( buff.inquire.baud )->display );
+ else if( buff.chs.driveAndHead & ATA_COMMAND_LBA )
+ log( 1, "%s %d: LBA=%u, Count=%u", comStr, img == image0 ? 0 : 1,
+ mylba, workCount );
+ else
+ log( 1, "%s %d: Cylinder=%u, Sector=%u, Head=%u, Count=%u, LBA=%u", comStr, img == image0 ? 0 : 1,
+ cyl, sect, head, workCount, mylba );
+ }
+
+ if( !img )
+ {
+ log( 1, " No slave drive provided" );
+ workCount = 0;
+ continue;
+ }
+
+ if( (workCommand & SERIAL_COMMAND_WRITE) && img->readOnly )
+ {
+ log( 1, " Write attempt to Read Only disk" );
+ workCount = 0;
+ continue;
+ }
+
+ if( verboseLevel > 0 && workCount > 100 )
+ perfTimer = GetTime();
+ }
+
+ if( workCount && (workCommand == (SERIAL_COMMAND_WRITE | SERIAL_COMMAND_READWRITE)) )
+ {
+ //
+ // Write command... Setup to receive a sector
+ //
+ readto = 514;
+ }
+ else
+ {
+ //
+ // Inquire command...
+ //
+ if( workCommand == SERIAL_COMMAND_INQUIRE )
+ {
+ unsigned char localScan;
+
+ if( serial->speedEmulation &&
+ buff.inquire.baud != serial->baudRate->divisor )
+ {
+ log( 1, " Ignoring Inquire with wrong baud rate" );
+ workCount = 0;
+ continue;
+ }
+
+ localScan = buff.inquire.scan; // need to do this before the call to
+ // img->respondInquire, as it will clear the buff
+ img->respondInquire( &buff.w[0], buff.inquirePacked.PackedPortAndBaud,
+ serial->baudRate,
+ ((unsigned short) buff.inquire.port) << 2,
+ (img == image1 && lastScan) || buff.inquire.scan );
+ lastScan = localScan;
+ }
+ //
+ // Read command...
+ //
+ else
+ {
+ img->seekSector( mylba + workOffset );
+ img->readSector( &buff.w[0] );
+ lastScan = 0;
+ }
+
+ buff.w[256] = checksum( &buff.w[0], 256 );
+
+ if( !serial->writeCharacters( &buff.w[0], 514 ) )
+ break;
+
+ if( verboseLevel >= 3 )
+ logBuff( " Sending: ", 514, 514, verboseLevel );
+
+ workCount--;
+ workOffset++;
+
+ if( workCount )
+ readto = 1; // looking for continuation ACK
+ }
+ }
+
+ if( workCount == 0 && workOffset > 100 )
+ log( 1, " Performance: %.2lf bytes per second", (512.0 * workOffset) / (GetTime() - perfTimer) * 1000.0 );
+ }
+}
+
+
A lib/serial_server/library/Serial.cpp => lib/serial_server/library/Serial.cpp +71 -0
@@ 0,0 1,71 @@
+//======================================================================
+//
+// Project: XTIDE Universal BIOS, Serial Port Server
+//
+// File: Serial.cpp - Generic functions for dealing with serial communications
+//
+
+//
+// XTIDE Universal BIOS and Associated Tools
+// Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
+//
+// 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.
+// Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+//
+
+#include "Library.h"
+#include <stdlib.h>
+#include <string.h>
+
+struct baudRate supportedBaudRates[] =
+{
+ { 2400, 0x30, "2400", B2400 },
+ { 4800, 0x18, "4800", B4800 },
+ { 9600, 0xc, "9600", B9600 },
+ { 19200, 0xff, "19.2K", B19200 },
+//{ 28800, 0x4, "28.8K", B28800 },
+ { 38400, 0xff, "38.4K", B38400 },
+ { 57600, 0x2, "57.6K", B57600 },
+//{ 76800, 0xff, "76.8K", B76800 },
+ { 115200, 0x1, "115.2K", B115200 },
+//{ 153600, 0xff, "153.6K", B153600 },
+ { 230400, 0xff, "230.4K", B230400 },
+ { 460800, 0xff, "460.8K", B460800 },
+ { 921600, 0xff, "921.6K", B921600 },
+ { 0, 0, "Unknown", 0 },
+};
+
+struct baudRate *baudRateMatchString( const char *str )
+{
+ struct baudRate *b = NULL;
+
+ unsigned long a = atol( str );
+ if( a )
+ {
+ for( b = supportedBaudRates; b->rate; b++ )
+ if( b->rate == a || (b->rate / 1000) == a || ((b->rate + 500) / 1000) == a )
+ return( b );
+ }
+
+ return( b );
+}
+
+struct baudRate *baudRateMatchDivisor( unsigned char divisor )
+{
+ struct baudRate *b;
+
+ for( b = supportedBaudRates; b->rate && b->divisor != divisor; b++ )
+ ;
+
+ return( b );
+}
+
+
M => +22 -3
@@ 1331,7 1331,7 @@ void HandleUI(void)
}
else
{
if ((get_key_mod() & (LGUI | RGUI)) && !is_x86() && has_menu()) //Win+Menu
if ((get_key_mod() & (LGUI | RGUI)) && !is_x86() && !is_pcxt() && has_menu()) //Win+Menu
{
menustate = MENU_COMMON1;
}
@@ 1687,6 1687,13 @@ void HandleUI(void)
strcat(s, " ");
strcat(s, x86_get_image_name(num));
}
else if (is_pcxt() && pcxt_get_image_name(num))
{
strcpy(s, " ");
substrcpy(s + 1, p, 2);
strcat(s, " ");
strcat(s, pcxt_get_image_name(num));
}
else
{
if (strlen(s))
@@ 2130,7 2137,12 @@ void HandleUI(void)
if (!strlen(s) || get_arc(s) < 0) x = 0;
}
user_io_status_set(p + 1, x, ex);
user_io_status_set(p + 1, x, ex);
if (is_pcxt() && (p[1] == 'J' || p[1] == 'L'))
{
pcxt_load_images();
}
if (is_x86() && p[1] == 'A')
{
@@ 2170,6 2182,7 @@ void HandleUI(void)
if (is_pce() && !bit) pcecd_reset();
if (is_saturn() && !bit) saturn_reset();
if (is_pcxt() && !bit) pcxt_init();
user_io_status_set(opt, 1, ex);
user_io_status_set(opt, 0, ex);
@@ 2274,7 2287,11 @@ void HandleUI(void)
char idx = user_io_ext_idx(selPath, fs_pFileExt) << 6 | ioctl_index;
if (addon[0] == 'f' && addon[1] != '1') process_addon(addon, idx);
if (is_x86())
if (is_pcxt())
{
pcxt_set_image(ioctl_index, selPath);
}
else if (is_x86())
{
x86_set_image(ioctl_index, selPath);
}
@@ 2527,6 2544,7 @@ void HandleUI(void)
user_io_status_save(filename);
if (is_x86()) x86_config_save();
if (is_arcade()) arcade_nvm_save();
if (is_pcxt()) pcxt_config_save();
}
break;
@@ 4695,6 4713,7 @@ void HandleUI(void)
OsdWrite(OsdGetSize() / 2, " Unmounting the image", 0, 0);
OsdUpdate();
sleep(1);
if (is_pcxt()) pcxt_load_images();
}
input_poll(0);
menu_key_set(0);
M support.h => support.h +3 -0
@@ 11,6 11,9 @@
// Archie support
#include "support/archie/archie.h"
+// PCXT support
+#include "support/pcxt/pcxt.h"
+
// ST (Atari) support
#include "support/st/st_tos.h"
A support/pcxt/pcxt.cpp => support/pcxt/pcxt.cpp +317 -0
@@ 0,0 1,317 @@
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <pthread.h>
+
+#include "../../cfg.h"
+#include "../../hardware.h"
+#include "../../fpga_io.h"
+#include "../../menu.h"
+#include "../../debug.h"
+#include "../../user_io.h"
+#include "../../input.h"
+#include "../../support.h"
+#include "../../lib/serial_server/library/Library.h"
+#include "../../lib/serial_server/library/FlatImage.h"
+#include "pcxt.h"
+
+int verbose = 0;
+
+int timeoutEnabled = 1;
+int createFile = 0;
+int useCHS = 0;
+
+pthread_t uart_thread;
+SerialAccess serial;
+bool in_process;
+
+#define CFG_VER 1
+
+typedef struct
+{
+ uint32_t ver;
+ char img_name[2][1024];
+} pcxt_config;
+
+static pcxt_config config;
+
+void pcxt_init()
+{
+ user_io_status_set("[0]", 1);
+ const char* home = HomeDir();
+ static char mainpath[512];
+
+ int status = user_io_status_get("[3]");
+ if (status)
+ {
+ sprintf(mainpath, "%s/tandy.rom", home);
+ }
+ else
+ {
+ sprintf(mainpath, "%s/pcxt.rom", home);
+ }
+
+ user_io_file_tx(mainpath);
+}
+
+void* OpenUART(void*) {
+
+ char ComPortBuff[20];
+ sprintf(ComPortBuff, "/dev/ttyS1");
+ const char* ComPort = NULL;
+ ComPort = &ComPortBuff[0];
+
+ struct baudRate* baudRate = NULL;
+ int status;
+
+ status = user_io_status_get("[22:21]");
+ switch (status)
+ {
+ case 1:
+ baudRate = baudRateMatchString("230400");
+ break;
+ case 2:
+ baudRate = baudRateMatchString("460800");
+ break;
+ case 3:
+ baudRate = baudRateMatchString("921600");
+ break;
+ case 0:
+ default:
+ baudRate = baudRateMatchString("115200");
+ break;
+ };
+
+ Image* images[2] = { NULL, NULL };
+ int timeoutEnabled = 1;
+ FILE* fd;
+ long size;
+
+ // FDD CHS Calculator
+
+ unsigned long fdd_cyl = 0, fdd_sect = 0, fdd_head = 0;
+ bool is_fdd = false;
+ struct floppyInfo* fdd_fi;
+
+ if (strlen(config.img_name[1]))
+ {
+ fd = fopen(config.img_name[1], "r");
+ if (fd)
+ {
+ is_fdd = true;
+ fseek(fd, 0L, SEEK_END);
+ size = ftell(fd);
+
+ if ((fdd_fi = FindFloppyInfoBySize(size)))
+ {
+ fdd_sect = fdd_fi->sectors;
+ fdd_head = fdd_fi->heads;
+ fdd_cyl = fdd_fi->cylinders;
+ }
+ else
+ {
+ fdd_sect = 63;
+ fdd_head = 16;
+ fdd_cyl = size / (16 * 63);
+ }
+ }
+ }
+
+ // HDD CHS Calculator
+
+ unsigned long hdd_cyl = 0, hdd_sect = 0, hdd_head = 0;
+ bool is_hdd = false;
+ struct hddInfo *hdd_fi;
+
+ if (strlen(config.img_name[0]))
+ {
+ fd = fopen(config.img_name[0], "r");
+ if (fd)
+ {
+ is_hdd = true;
+ fseek(fd, 0L, SEEK_END);
+ size = ftell(fd);
+
+ if ((hdd_fi = FindHDDInfoBySize(size)))
+ {
+ hdd_sect = hdd_fi->sectors;
+ hdd_head = hdd_fi->heads;
+ hdd_cyl = hdd_fi->cylinders;
+ }
+ else
+ {
+ hdd_sect = 63;
+ hdd_head = 16;
+ hdd_cyl = size / (16 * 63);
+ }
+ }
+ }
+ // Prepare Images
+
+ status = user_io_status_get("[20:19]");
+
+ if (is_hdd)
+ {
+ images[0] = new FlatImage(config.img_name[0], status & 2, 0, createFile, hdd_cyl, hdd_head, hdd_sect, useCHS);
+
+ if (is_fdd)
+ {
+ images[1] = new FlatImage(config.img_name[1], status & 1, 1, createFile, fdd_cyl, fdd_head, fdd_sect, useCHS);
+ }
+ }
+ else if (is_fdd)
+ {
+ images[0] = new FlatImage(config.img_name[1], status & 1, 0, createFile, fdd_cyl, fdd_head, fdd_sect, useCHS);
+ }
+
+ // Mount Images
+
+ serial.Connect(ComPort, baudRate);
+ processRequests(&serial, images[0], images[1], timeoutEnabled, verbose);
+
+ pthread_exit(NULL);
+}
+
+
+
+void log(int level, const char* message, ...)
+{
+ va_list args;
+
+ va_start(args, message);
+
+ if (level < 0)
+ {
+ fprintf(stderr, "ERROR: ");
+ vfprintf(stderr, message, args);
+ fprintf(stderr, "\n");
+ if (level < -1)
+ {
+ fprintf(stderr, "\n");
+ //usage();
+ }
+ //exit(1);
+ }
+ else if (verbose >= level)
+ {
+ vprintf(message, args);
+ printf("\n");
+ }
+
+ va_end(args);
+}
+
+
+unsigned long GetTime(void)
+{
+ struct timespec now;
+
+
+ if (clock_gettime(CLOCK_MONOTONIC, &now))
+ return 0;
+ return now.tv_sec * 1000.0 + now.tv_nsec / 1000000.0;
+}
+
+unsigned long GetTime_Timeout(void)
+{
+ return(1000);
+}
+
+void pcxt_unmount_images()
+{
+ void* status;
+ printf("Unmounting Images...");
+ if (in_process)
+ {
+ in_process = false;
+ serial.Disconnect();
+ pthread_cancel(uart_thread);
+ pthread_join(uart_thread, &status);
+ usleep(100000);
+ printf("OK\n");
+ }
+ else
+ {
+ printf("No serdrive is running\n");
+ }
+
+}
+
+void pcxt_load_images()
+{
+ pcxt_unmount_images();
+ pthread_create(&uart_thread, NULL, OpenUART, NULL);
+ usleep(100000);
+ in_process = true;
+}
+
+void pcxt_set_image(int num, char* filename)
+{
+ const char* imghome = "/media/fat";
+
+ memset(config.img_name[num], 0, sizeof(config.img_name[num]));
+
+ if (strlen(filename))
+ {
+ memset(config.img_name[num], 0, sizeof(config.img_name[num]));
+ sprintf(config.img_name[num], "%s/%s", imghome, filename);
+ pcxt_load_images();
+ }
+
+}
+
+static char* get_config_name()
+{
+ static char str[256];
+ snprintf(str, sizeof(str), "%ssys.cfg", user_io_get_core_name());
+ return str;
+}
+
+
+void pcxt_config_save()
+{
+ config.ver = CFG_VER;
+ FileSaveConfig(get_config_name(), &config, sizeof(config));
+}
+
+void pcxt_config_load()
+{
+ static pcxt_config tmp;
+ memset(&config, 0, sizeof(config));
+ if (FileLoadConfig(get_config_name(), &tmp, sizeof(tmp)) && (tmp.ver == CFG_VER))
+ {
+ memcpy(&config, &tmp, sizeof(config));
+ pcxt_load_images();
+ }
+}
+
+const char* pcxt_get_image_name(int num)
+{
+ static char res[32];
+
+ char* name = config.img_name[num];
+ if (!name[0]) return NULL;
+
+ char* p = strrchr(name, '/');
+ if (!p) p = name;
+ else p++;
+
+ if (strlen(p) < 19) strcpy(res, p);
+ else
+ {
+ strncpy(res, p, 19);
+ res[19] = 0;
+ }
+
+ return res;
+}
+
+const char* pcxt_get_image_path(int num)
+{
+ return config.img_name[num];
+}
A support/pcxt/pcxt.h => support/pcxt/pcxt.h +21 -0
@@ 0,0 1,21 @@
+#ifndef PCXT_H
+#define PCXT_H
+
+#include "../../file_io.h"
+
+void pcxt_init(void);
+void* OpenUART(void*);
+void log(int level, const char* message, ...);
+unsigned long GetTime(void);
+unsigned long GetTime_Timeout(void);
+
+void pcxt_unmount_images();
+void pcxt_load_images();
+void pcxt_set_image(int num, char* selPath);
+void pcxt_config_load();
+void pcxt_config_save();
+const char* pcxt_get_image_name(int num);
+const char* pcxt_get_image_path(int num);
+
+
+#endif // PCXT_H<
\ No newline at end of file
M user_io.cpp => user_io.cpp +13 -1
@@ 255,6 255,13 @@ char is_archie()
return (is_archie_type == 1);
}
+static int is_pcxt_type = 0;
+char is_pcxt()
+{
+ if (!is_pcxt_type) is_pcxt_type = strcasecmp(orig_name, "PCXT") ? 2 : 1;
+ return (is_pcxt_type == 1);
+}
+
static int is_gba_type = 0;
char is_gba()
{
@@ 1396,6 1403,11 @@ void user_io_init(const char *path, const char *xml)
printf("Identified Archimedes core");
archie_init();
}
+ else if (is_pcxt())
+ {
+ pcxt_config_load();
+ pcxt_init();
+ }
else
{
const char *home = HomeDir();
@@ 3785,7 3797,7 @@ void user_io_kbd(uint16_t key, int press)
{
if (is_menu() && !video_fb_state()) printf("PS2 code(make)%s for core: %d(0x%X)\n", (code & EXT) ? "(ext)" : "", code & 255, code & 255);
if (!osd_is_visible && !is_menu() && key == KEY_MENU && press == 3) open_joystick_setup();
- else if ((has_menu() || osd_is_visible || (get_key_mod() & (LALT | RALT | RGUI | LGUI))) && (((key == KEY_F12) && ((!is_x86() && !is_archie()) || (get_key_mod() & (RGUI | LGUI)))) || key == KEY_MENU))
+ else if ((has_menu() || osd_is_visible || (get_key_mod() & (LALT | RALT | RGUI | LGUI))) && (((key == KEY_F12) && ((!is_x86() && !is_pcxt() && !is_archie()) || (get_key_mod() & (RGUI | LGUI)))) || key == KEY_MENU))
{
if (press == 1) menu_key_set(KEY_F12);
}
M user_io.h => user_io.h +1 -0
@@ 275,6 275,7 @@ char is_st();
char is_psx();
char is_arcade();
char is_saturn();
+char is_pcxt();
#define HomeDir(x) user_io_get_core_path(x)
#define CoreName user_io_get_core_name()