Add pcxt project (#679)
Initially, with serdrive as HDD/FDD image server, only active when starting the PCXT core, never on other cores.
This commit is contained in:
2
Makefile
2
Makefile
@@ -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)
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
339
lib/serial_server/gpl-2.0.txt
Normal file
339
lib/serial_server/gpl-2.0.txt
Normal file
@@ -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.
|
||||
372
lib/serial_server/library/Checksum.cpp
Normal file
372
lib/serial_server/library/Checksum.cpp
Normal file
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
97
lib/serial_server/library/FlatImage.h
Normal file
97
lib/serial_server/library/FlatImage.h
Normal file
@@ -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 );
|
||||
}
|
||||
};
|
||||
|
||||
498
lib/serial_server/library/Image.cpp
Normal file
498
lib/serial_server/library/Image.cpp
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
104
lib/serial_server/library/Library.h
Normal file
104
lib/serial_server/library/Library.h
Normal file
@@ -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
|
||||
140
lib/serial_server/library/LinuxFile.h
Normal file
140
lib/serial_server/library/LinuxFile.h
Normal file
@@ -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;
|
||||
};
|
||||
|
||||
122
lib/serial_server/library/LinuxSerial.h
Normal file
122
lib/serial_server/library/LinuxSerial.h
Normal file
@@ -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;
|
||||
};
|
||||
|
||||
404
lib/serial_server/library/Process.cpp
Normal file
404
lib/serial_server/library/Process.cpp
Normal file
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
71
lib/serial_server/library/Serial.cpp
Normal file
71
lib/serial_server/library/Serial.cpp
Normal file
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
25
menu.cpp
25
menu.cpp
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
317
support/pcxt/pcxt.cpp
Normal file
317
support/pcxt/pcxt.cpp
Normal file
@@ -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];
|
||||
}
|
||||
21
support/pcxt/pcxt.h
Normal file
21
support/pcxt/pcxt.h
Normal file
@@ -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
|
||||
14
user_io.cpp
14
user_io.cpp
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user