Compare commits
7 Commits
776be92c56
...
ef6286d674
Author | SHA1 | Date |
---|---|---|
Zane Kaminski | ef6286d674 | |
Zane Kaminski | 51d01f815f | |
Zane Kaminski | 636e73ff23 | |
Zane Kaminski | 2cc1076981 | |
Zane Kaminski | 3d1073a665 | |
Zane Kaminski | 147cb0600d | |
Zane Kaminski | 55bc0eaeda |
|
@ -1,2 +1,4 @@
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
obj/
|
obj/
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/settings.json
|
||||||
|
|
|
@ -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.
|
152
Makefile
152
Makefile
|
@ -5,20 +5,12 @@ LD=$(PREFIX)-ld
|
||||||
OBJCOPY=$(PREFIX)-objcopy
|
OBJCOPY=$(PREFIX)-objcopy
|
||||||
OBJDUMP=$(PREFIX)-objdump
|
OBJDUMP=$(PREFIX)-objdump
|
||||||
|
|
||||||
all: bin/IIxIIcxSE30/IIxIIcxSE30_8M.bin bin/IIci/IIci_8M.bin bin/IIfx/IIfx_8M.bin bin/IIsi/IIsi_8M.bin bin/GWSys71_8M.bin bin/GWSys6_8M.bin bin/GWSys7Diagnostics_8M.bin obj/rdisk.s obj/driver.s obj/driver_abs.sym
|
all: bin/ROMBUS_8M.bin obj/rombus.s obj/driver.s obj/driver_abs.sym
|
||||||
|
|
||||||
obj:
|
obj:
|
||||||
mkdir $@
|
mkdir -p $@
|
||||||
bin:
|
bin:
|
||||||
mkdir $@
|
mkdir -p $@
|
||||||
bin/IIsi: bin
|
|
||||||
mkdir $@
|
|
||||||
bin/IIxIIcxSE30: bin
|
|
||||||
mkdir $@
|
|
||||||
bin/IIci: bin
|
|
||||||
mkdir $@
|
|
||||||
bin/IIfx: bin
|
|
||||||
mkdir $@
|
|
||||||
|
|
||||||
|
|
||||||
obj/entry.o: entry.s obj
|
obj/entry.o: entry.s obj
|
||||||
|
@ -28,14 +20,38 @@ obj/entry_rel.sym: obj obj/entry.o
|
||||||
$(OBJDUMP) -t obj/entry.o > $@
|
$(OBJDUMP) -t obj/entry.o > $@
|
||||||
|
|
||||||
|
|
||||||
obj/rdisk.o: rdisk.c obj
|
obj/spi.o: spi.c obj
|
||||||
$(CC) -Wall -march=68030 -c -Os $< -o $@
|
$(CC) -Wall -march=68020 -c -Os $< -o $@
|
||||||
|
obj/spi_hal.o: spi_hal.s spi_hal_common.s obj
|
||||||
|
$(AS) $< -o $@
|
||||||
|
obj/spi_rx8.o: spi_rx8.s spi_hal.s spi_hal_common.s obj
|
||||||
|
$(AS) $< -o $@
|
||||||
|
obj/spi_rx16.o: spi_rx16.s spi_hal.s spi_hal_common.s obj
|
||||||
|
$(AS) $< -o $@
|
||||||
|
obj/spi_tx8.o: spi_tx8.s spi_hal.s spi_hal_common.s obj
|
||||||
|
$(AS) $< -o $@
|
||||||
|
obj/spi_tx16.o: spi_tx16.s spi_hal.s spi_hal_common.s obj
|
||||||
|
$(AS) $< -o $@
|
||||||
|
obj/spi_rxtx8.o: spi_rxtx8.s spi_hal.s spi_hal_common.s obj
|
||||||
|
$(AS) $< -o $@
|
||||||
|
obj/spi_delay.o: spi_delay.s obj
|
||||||
|
$(AS) $< -o $@
|
||||||
|
|
||||||
obj/rdisk.s: obj obj/rdisk.o
|
|
||||||
$(OBJDUMP) -d obj/rdisk.o > $@
|
|
||||||
|
|
||||||
obj/driver.o: obj obj/entry.o obj/rdisk.o
|
obj/rombus.o: rombus.c obj
|
||||||
$(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rdisk.o
|
$(CC) -Wall -march=68020 -c -Os $< -o $@
|
||||||
|
|
||||||
|
obj/rombus.s: obj obj/rombus.o
|
||||||
|
$(OBJDUMP) -d obj/rombus.o > $@
|
||||||
|
|
||||||
|
obj/driver.o: obj obj/entry.o obj/rombus.o obj/spi.o obj/spi_hal.o \
|
||||||
|
obj/spi_rx8.o obj/spi_rx16.o \
|
||||||
|
obj/spi_tx8.o obj/spi_tx16.o \
|
||||||
|
obj/spi_rxtx8.o
|
||||||
|
$(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rombus.o obj/spi.o obj/spi_hal.o \
|
||||||
|
obj/spi_rx8.o obj/spi_rx16.o \
|
||||||
|
obj/spi_tx8.o obj/spi_tx16.o \
|
||||||
|
obj/spi_rxtx8.o
|
||||||
|
|
||||||
obj/driver.s: obj obj/driver.o
|
obj/driver.s: obj obj/driver.o
|
||||||
$(OBJDUMP) -d obj/driver.o > $@
|
$(OBJDUMP) -d obj/driver.o > $@
|
||||||
|
@ -43,11 +59,11 @@ obj/driver.s: obj obj/driver.o
|
||||||
obj/driver_abs.sym: obj obj/driver.o
|
obj/driver_abs.sym: obj obj/driver.o
|
||||||
$(OBJDUMP) -t obj/driver.o > $@
|
$(OBJDUMP) -t obj/driver.o > $@
|
||||||
|
|
||||||
|
|
||||||
bin/driver.bin: bin obj/driver.o
|
bin/driver.bin: bin obj/driver.o
|
||||||
$(OBJCOPY) -O binary obj/driver.o $@
|
$(OBJCOPY) -O binary obj/driver.o $@
|
||||||
|
|
||||||
bin/baserom_romdisk_ramtest.bin: bin roms/baserom.bin bin/driver.bin obj/driver_abs.sym obj/entry_rel.sym
|
|
||||||
|
bin/baserom_rombus_ramtest.bin: bin roms/baserom.bin bin/driver.bin obj/driver_abs.sym obj/entry_rel.sym
|
||||||
cp roms/baserom.bin $@ # Copy base rom
|
cp roms/baserom.bin $@ # Copy base rom
|
||||||
# Patch driver
|
# Patch driver
|
||||||
dd if=bin/driver.bin of=$@ bs=1 seek=335248 skip=32 conv=notrunc # Copy driver code
|
dd if=bin/driver.bin of=$@ bs=1 seek=335248 skip=32 conv=notrunc # Copy driver code
|
||||||
|
@ -59,107 +75,19 @@ bin/baserom_romdisk_ramtest.bin: bin roms/baserom.bin bin/driver.bin obj/driver_
|
||||||
cat obj/entry_rel.sym | grep "[0-9]\s*DStatus" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335230 count=2 conv=notrunc
|
cat obj/entry_rel.sym | grep "[0-9]\s*DStatus" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335230 count=2 conv=notrunc
|
||||||
cat obj/entry_rel.sym | grep "[0-9]\s*DClose" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335232 count=2 conv=notrunc
|
cat obj/entry_rel.sym | grep "[0-9]\s*DClose" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335232 count=2 conv=notrunc
|
||||||
|
|
||||||
bin/baserom_romdisk_noramtest.bin: bin bin/baserom_romdisk_ramtest.bin
|
bin/baserom_rombus_noramtest.bin: bin bin/baserom_rombus_ramtest.bin
|
||||||
cp bin/baserom_romdisk_ramtest.bin $@ # Copy base rom
|
cp bin/baserom_rombus_ramtest.bin $@ # Copy base rom
|
||||||
# Disable RAM test
|
# Disable RAM test
|
||||||
printf '\x4E\xD6' | dd of=$@ bs=1 seek=288736 count=2 conv=notrunc
|
printf '\x4E\xD6' | dd of=$@ bs=1 seek=288736 count=2 conv=notrunc
|
||||||
printf '\x4E\xD6' | dd of=$@ bs=1 seek=289016 count=2 conv=notrunc
|
printf '\x4E\xD6' | dd of=$@ bs=1 seek=289016 count=2 conv=notrunc
|
||||||
|
|
||||||
|
|
||||||
bin/GWSys71_8M.bin: bin bin/baserom_romdisk_noramtest.bin disks/RDisk7M5.dsk
|
bin/ROMBUS_8M.bin: bin bin/baserom_rombus_noramtest.bin disks/RDisk.dsk
|
||||||
# Copy base rom with ROM disk driver
|
# Copy base rom with ROM disk driver
|
||||||
cp bin/baserom_romdisk_noramtest.bin $@
|
cp bin/baserom_rombus_noramtest.bin $@
|
||||||
# Patch ROM disk driver parameter table
|
|
||||||
printf '\x00\x01\x2A\x29' | dd of=$@ bs=1 seek=335260 count=4 conv=notrunc # Patch CDR patch offset
|
|
||||||
printf '\x40\x89\x2A\x14' | dd of=$@ bs=1 seek=335268 count=4 conv=notrunc # Patch CDR name address
|
|
||||||
printf '\x44' | dd of=$@ bs=1 seek=335273 count=1 conv=notrunc # Patch CDR disable byte
|
|
||||||
printf '\x00\x78\x00\x00' | dd of=$@ bs=1 seek=335276 count=4 conv=notrunc # Patch ROM disk size
|
printf '\x00\x78\x00\x00' | dd of=$@ bs=1 seek=335276 count=4 conv=notrunc # Patch ROM disk size
|
||||||
# Copy ROM disk image
|
# Copy ROM disk image
|
||||||
dd if=disks/RDisk7M5.dsk of=$@ bs=1024 seek=512 conv=notrunc
|
dd if=disks/RDisk.dsk of=$@ bs=1024 seek=512 conv=notrunc
|
||||||
|
|
||||||
|
|
||||||
bin/GWSys6_4M.bin: bin bin/baserom_romdisk_noramtest.bin disks/RDisk3M5.dsk
|
|
||||||
# Copy base rom with ROM disk driver
|
|
||||||
cp bin/baserom_romdisk_noramtest.bin $@
|
|
||||||
# Patch ROM disk driver parameter table
|
|
||||||
printf '\xFF\xFF\xFF\xFF' | dd of=$@ bs=1 seek=335260 count=4 conv=notrunc # Patch CDR patch offset
|
|
||||||
printf '\x00\x00\x00\x00' | dd of=$@ bs=1 seek=335268 count=4 conv=notrunc # Patch CDR name address
|
|
||||||
printf '\x44' | dd of=$@ bs=1 seek=335273 count=1 conv=notrunc # Patch CDR disable byte
|
|
||||||
printf '\x00\x38\x00\x00' | dd of=$@ bs=1 seek=335276 count=4 conv=notrunc # Patch ROM disk size
|
|
||||||
# Copy ROM disk image
|
|
||||||
dd if=disks/RDisk3M5.dsk of=$@ bs=1024 seek=512 conv=notrunc
|
|
||||||
|
|
||||||
bin/GWSys6_8M.bin: bin/GWSys6_4M.bin
|
|
||||||
cat bin/GWSys6_4M.bin > $@
|
|
||||||
cat bin/GWSys6_4M.bin >> $@
|
|
||||||
|
|
||||||
|
|
||||||
bin/GWSys7Diagnostics_8M.bin: bin bin/baserom_romdisk_ramtest.bin disks/RDisk7M5-diagnostics.dsk
|
|
||||||
# Copy base rom with ROM disk driver
|
|
||||||
cp bin/baserom_romdisk_ramtest.bin $@
|
|
||||||
# Patch ROM disk driver parameter table
|
|
||||||
printf '\xFF\xFF\xFF\xFF' | dd of=$@ bs=1 seek=335260 count=4 conv=notrunc # Patch CDR patch offset
|
|
||||||
printf '\x00\x00\x00\x00' | dd of=$@ bs=1 seek=335268 count=4 conv=notrunc # Patch CDR name address
|
|
||||||
printf '\x44' | dd of=$@ bs=1 seek=335273 count=1 conv=notrunc # Patch CDR disable byte
|
|
||||||
printf '\x00\x78\x00\x00' | dd of=$@ bs=1 seek=335276 count=4 conv=notrunc # Patch ROM disk size
|
|
||||||
# Copy ROM disk image
|
|
||||||
dd if=disks/RDisk7M5-diagnostics.dsk of=$@ bs=1024 seek=512 conv=notrunc
|
|
||||||
|
|
||||||
|
|
||||||
bin/IIxIIcxSE30/IIxIIcxSE30_512k.bin: bin/IIxIIcxSE30 roms/IIxIIcxSE30.bin
|
|
||||||
cat roms/IIxIIcxSE30.bin > $@; cat roms/IIxIIcxSE30.bin >> $@
|
|
||||||
|
|
||||||
bin/IIxIIcxSE30/IIxIIcxSE30_1M.bin: bin/IIxIIcxSE30 bin/IIxIIcxSE30/IIxIIcxSE30_512k.bin
|
|
||||||
cat bin/IIxIIcxSE30/IIxIIcxSE30_512k.bin > $@; cat bin/IIxIIcxSE30/IIxIIcxSE30_512k.bin >> $@
|
|
||||||
|
|
||||||
bin/IIxIIcxSE30/IIxIIcxSE30_2M.bin: bin/IIxIIcxSE30 bin/IIxIIcxSE30/IIxIIcxSE30_1M.bin
|
|
||||||
cat bin/IIxIIcxSE30/IIxIIcxSE30_1M.bin > $@; cat bin/IIxIIcxSE30/IIxIIcxSE30_1M.bin >> $@
|
|
||||||
|
|
||||||
bin/IIxIIcxSE30/IIxIIcxSE30_4M.bin: bin/IIxIIcxSE30 bin/IIxIIcxSE30/IIxIIcxSE30_2M.bin
|
|
||||||
cat bin/IIxIIcxSE30/IIxIIcxSE30_2M.bin > $@; cat bin/IIxIIcxSE30/IIxIIcxSE30_2M.bin >> $@
|
|
||||||
|
|
||||||
bin/IIxIIcxSE30/IIxIIcxSE30_8M.bin: bin/IIxIIcxSE30 bin/IIxIIcxSE30/IIxIIcxSE30_4M.bin
|
|
||||||
cat bin/IIxIIcxSE30/IIxIIcxSE30_4M.bin > $@; cat bin/IIxIIcxSE30/IIxIIcxSE30_4M.bin >> $@
|
|
||||||
|
|
||||||
|
|
||||||
bin/IIci/IIci_1M.bin: bin/IIci roms/IIci.bin
|
|
||||||
cat roms/IIci.bin > $@; cat roms/IIci.bin >> $@
|
|
||||||
|
|
||||||
bin/IIci/IIci_2M.bin: bin/IIci bin/IIci/IIci_1M.bin
|
|
||||||
cat bin/IIci/IIci_1M.bin > $@; cat bin/IIci/IIci_1M.bin >> $@
|
|
||||||
|
|
||||||
bin/IIci/IIci_4M.bin: bin/IIci bin/IIci/IIci_2M.bin
|
|
||||||
cat bin/IIci/IIci_2M.bin > $@; cat bin/IIci/IIci_2M.bin >> $@
|
|
||||||
|
|
||||||
bin/IIci/IIci_8M.bin: bin/IIci bin/IIci/IIci_4M.bin
|
|
||||||
cat bin/IIci/IIci_4M.bin > $@; cat bin/IIci/IIci_4M.bin >> $@
|
|
||||||
|
|
||||||
|
|
||||||
bin/IIfx/IIfx_1M.bin: bin/IIfx roms/IIfx.bin
|
|
||||||
cat roms/IIfx.bin > $@; cat roms/IIfx.bin >> $@
|
|
||||||
|
|
||||||
bin/IIfx/IIfx_2M.bin: bin/IIfx bin/IIfx/IIfx_1M.bin
|
|
||||||
cat bin/IIfx/IIfx_1M.bin > $@; cat bin/IIfx/IIfx_1M.bin >> $@
|
|
||||||
|
|
||||||
bin/IIfx/IIfx_4M.bin: bin/IIfx bin/IIfx/IIfx_2M.bin
|
|
||||||
cat bin/IIfx/IIfx_2M.bin > $@; cat bin/IIfx/IIfx_2M.bin >> $@
|
|
||||||
|
|
||||||
bin/IIfx/IIfx_8M.bin: bin/IIfx bin/IIfx/IIfx_4M.bin
|
|
||||||
cat bin/IIfx/IIfx_4M.bin > $@; cat bin/IIfx/IIfx_4M.bin >> $@
|
|
||||||
|
|
||||||
|
|
||||||
bin/IIsi/IIsi_1M.bin: bin/IIsi roms/IIsi.bin
|
|
||||||
cat roms/IIsi.bin > $@; cat roms/IIsi.bin >> $@
|
|
||||||
|
|
||||||
bin/IIsi/IIsi_2M.bin: bin/IIsi bin/IIsi/IIsi_1M.bin
|
|
||||||
cat bin/IIsi/IIsi_1M.bin > $@; cat bin/IIsi/IIsi_1M.bin >> $@
|
|
||||||
|
|
||||||
bin/IIsi/IIsi_4M.bin: bin/IIsi bin/IIsi/IIsi_2M.bin
|
|
||||||
cat bin/IIsi/IIsi_2M.bin > $@; cat bin/IIsi/IIsi_2M.bin >> $@
|
|
||||||
|
|
||||||
bin/IIsi/IIsi_8M.bin: bin/IIsi bin/IIsi/IIsi_4M.bin
|
|
||||||
cat bin/IIsi/IIsi_4M.bin > $@; cat bin/IIsi/IIsi_4M.bin >> $@
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
||||||
#include "RDiskCP.h"
static long RDiskCPMacDev() {
int i;
// Check signature and return 0 if doesn't match
// Don't check for length byte at beginning or null byte at endss
for (i = 1; i < sizeof(RDiskSigStr)-1; i++) {
if (RDiskSigPtr[i] != RDiskSigStr[i]) {
// If signature doesn't match,
// fail if not holding R key
if (!((*((char*)0x175)) & 0x80)) { return 0; }
}
}
return 1; // Otherwise return 1 if signature matches
}
static void RDiskCPUpdate(DialogPtr cpDialog, short numItems) {
GrafPtr savePort;
Handle h;
Rect r;
short type;
char startup, ram;
// Get startup and ram from PRAM
RDiskCPReadXPRam(1, 4, &startup);
RDiskCPReadXPRam(1, 5, &ram);
// Save GrafPort and set port to dialog before updating items
GetPort(&savePort);
SetPort(cpDialog);
GetDItem(cpDialog, BootCheckbox+numItems, &type, &h, &r);
SetCtlValue((ControlHandle)h, startup & 0x01 ? 1 : 0);
GetDItem(cpDialog, MountCheckbox+numItems, &type, &h, &r);
SetCtlValue((ControlHandle)h, !(startup & 0x02) && !(startup & 0x01) ? 1 : 0);
HiliteControl((ControlHandle)h, startup & 0x01 ? 255 : 0);
GetDItem(cpDialog, RAMCheckbox+numItems, &type, &h, &r);
SetCtlValue((ControlHandle)h,
((startup & 0x01) || !(startup & 0x02)) && (ram & 0x01) ? 1 : 0);
HiliteControl((ControlHandle)h, (startup & 0x01) || !(startup & 0x02) ? 0 : 255);
GetDItem(cpDialog, DebugCheckbox+numItems, &type, &h, &r);
SetCtlValue((ControlHandle)h, startup & 0x04 && (startup & 0x01) ? 1 : 0);
HiliteControl((ControlHandle)h, !(startup & 0x01) || !*RDiskDBGDisPos ? 255 : 0);
GetDItem(cpDialog, CDROMCheckbox+numItems, &type, &h, &r);
SetCtlValue((ControlHandle)h, startup & 0x08 && (startup & 0x01) ? 1 : 0);
HiliteControl((ControlHandle)h, !(startup & 0x01) || !*RDiskCDROMDisPos ? 255 : 0);
// Restore old GrafPort
SetPort(savePort);
}
static void RDiskCPHitDev(short message, short item, short numItems,
short cpPrivateVal, EventRecord *theEvent,
void *cdevStorageValue, DialogPtr cpDialog) {
char startup, ram;
RDiskCPReadXPRam(1, 4, &startup);
RDiskCPReadXPRam(1, 5, &ram);
switch (item - numItems) {
case BootCheckbox:
if (startup & 0x01) { startup &= 0x0F & ~0x01; }
else { startup = startup & 0x0F | 0x01; }
break;
case MountCheckbox:
if (!(startup & 0x01)) {
if (startup & 0x02) { startup &= 0x0F & ~0x02; }
else { startup = startup & 0x0F | 0x02; }
}
break;
case RAMCheckbox:
if ((startup & 0x01) || !(startup & 0x02)) {
if (ram & 0x01) { ram = 0x00; }
else { ram = 0x01; }
}
break;
case DebugCheckbox:
if (startup & 0x01) {
if (startup & 0x04) { startup &= 0x0F & ~0x04; }
else { startup = startup & 0x0F | 0x04; }
}
break;
case CDROMCheckbox:
if (startup & 0x01) {
if (startup & 0x08) { startup &= 0x0F & ~0x08; }
else { startup = startup & 0x0F | 0x08; }
}
break;
};
RDiskCPWriteXPRam(1, 4, &startup);
RDiskCPWriteXPRam(1, 5, &ram);
RDiskCPUpdate(cpDialog, numItems);
}
static void RDiskCPInitDev(short message, short item, short numItems,
short cpPrivateVal, EventRecord *theEvent,
void *cdevStorageValue, DialogPtr cpDialog) {
Str15 ramSize;
Str255 dbgName = "\pMacsBug";
Str255 cdromName = "\pCD-ROM Ext.";
int i;
ramSize[0] = 2;
if (RDiskCPMacDev()) {
ramSize[1] = RDiskRAMReq[0];
ramSize[2] = RDiskRAMReq[1];
} else {
ramSize[1] = '1';
ramSize[2] = '6';
}
if (RDiskCPMacDev() && *RDiskDBGNamePos != 0) {
for (i = 0; i < 255; i++) {
dbgName[i] = (*RDiskDBGNamePos)[i];
}
}
if (RDiskCPMacDev() && *RDiskCDROMNamePos != 0) {
for (i = 0; i < 255; i++) {
cdromName[i] = (*RDiskCDROMNamePos)[i];
}
}
ParamText(ramSize, dbgName, cdromName, 0);
}
pascal long main(short message, short item, short numItems,
short cpPrivateVal, EventRecord *theEvent,
void *cdevStorageValue, DialogPtr cpDialog)
{
long ret = (long)cdevStorageValue;
// Switch to our A4 world
EnterCodeResource();
// Handle message
switch (message) {
case initDev:
RDiskCPInitDev(message, item, numItems,
cpPrivateVal, theEvent,
cdevStorageValue, cpDialog);
// (fall through to return cdevUnset)
case closeDev:
ret = cdevUnset; break;
case macDev:
ret = RDiskCPMacDev(); break;
case updateDev:
case activDev:
case deactivDev:
RDiskCPUpdate(cpDialog, numItems);
break;
case hitDev:
RDiskCPHitDev(message, item, numItems,
cpPrivateVal, theEvent,
cdevStorageValue, cpDialog);
break;
};
// Restore old A4 world and return result
ExitCodeResource();
return ret;
}
|
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
||||||
#ifndef RDISKCP_H
#define RDISKCP_H
#include <A4Stuff.h>
#define BootCheckbox 3
#define BootCaption 6
#define MountCheckbox 5
#define MountCaption 8
#define RAMCheckbox 7
#define RAMCaption 10
#define DebugCheckbox 13
#define DebugCaption 14
#define CDROMCheckbox 15
#define CDROMCaption 16
#define RDiskSigPtr ((char*)0x40851D90)
#define RDiskSigStr "\5RDisk" // sizeof(RDiskSigStr) == 7
#define RDiskDBGNamePos ((char**)0x40851DA0)
#define RDiskDBGDisPos ((char**)0x40851D98)
#define RDiskDBGDisByte ((char*)0x40851DA8)
#define RDiskCDROMNamePos ((char**)0x40851DA4)
#define RDiskCDROMDisPos ((char**)0x40851D9C)
#define RDiskCDROMDisByte ((char*)0x40851DA9)
#define RDiskRAMReq ((char*)0x40851DAA)
#pragma parameter __D0 RDiskCPReadXPRam(__D0, __D1, __A0)
short RDiskCPReadXPRam(short size, short offset, char *where) =
{0x4840, 0x3001, 0xA051};
#pragma parameter __D0 RDiskCPWriteXPRam(__D0, __D1, __A0)
short RDiskCPWriteXPRam(short size, short offset, char *where) =
{0x4840, 0x3001, 0xA052};
#endif
|
|
|
@ -1 +0,0 @@
|
||||||
(This file must be converted with BinHex 4.0)
:#9*%DA0V3e!ZD!"849K868e$3`%!!!!$q!!!!4j-8L0TCQjNC@BJ8N4*8dY$8&p
)$50NC@CTEQ8J8N4*8dY$8&p)$3dMD@jME(9NC5!m3646G(9QCLjS2Jd0)f4PCQP
ZC5"#Efpd3fKPBfYLEhJJ-`dMC'9QD@jP)%*[Eh4$BA"dD@pZ)$B0)f4PCQPZC5"
0Eh9ZG%0SC@0VBQpi)$80)f4PCQPZC5"0Eh9ZG%0KF(4TEfiJ1!dMC'9QD@jP)&*
"680SC@0VBQpi)$F0)f4PCQPZC5"538e$BA"dD@pZ)$%`$50NC@CTEQ8J4'9LG@G
$D'9MDf*[H#!a-`dMC'9QD@jP)%4PBR9R3f&`G'P[EL!a0!dMC'9QD@jP)%0%8Np
03fKPBfYLEhJJ-680)f4PCQPZC5"$4&*2680KF(4TEfiJ-6B0$50NC@CTEQ8J8N4
TFfY6D@G3G()J+#KMD'&b+LN`H$3`1$8a4$N`+3dMC'9QD@jP)&*%DA0V8fPR8h4
b)#*F09*%DA0V)L![,b"cDATPEfBS8N4TFfY6D@G6G()T)$dp)$F0$50NC@CTEQ8
J8N4TFfY%3NG1B@eP8'pc)#JSBfKKFLSU+6"i0$!i06&%36!T$50NC@CTEQ8J8N4
TFfY%3NG%DA03Eh-J+#KMD'&b+LST-(Jd-$Je-83j1#N0)f4PCQPZC5"54'PcDd4
#4d4TFd*jG'8J+#KMD'&b+LN`H$3`1$8a4%%i+3dMC'9QD@jP)&*%DA0V3d456de
1B@eP8'pc)#JSBfKKFLSU+6"i0$!i06&%363T$50NC@CTEQ8J8N4TFfY$4&*2684
TFe"[Fb!S+'0SBA)U+LN`H$3`1$8a4$P$+3dMC'9QD@jP)&*%DA0V3d456de%DA0
#HA4P)#JSBfKKFLST-(Jd-$Je-84"15N0)f4PCQPZC5"54'PcDe*"69*PF5!S+'0
SBA)U+6"i0$!i06&%38%T$3dMF(*KCfeK)("KFQ&YCA4PFL"IAd3`)&*%DA0V3e"
5C@&N@&"5B@dSAep%-#`JAep%-5`JAep"-#N0FfK[FR3J8N4TFfY$8&*PB@4B8&*
KE5KcD'pbG#"cDATP,#"cD'pbG#"[CQCcCA3X)'0SBA)J+RGSCA*P+5!p$3Pl-(J
d1$3`,#!`H$-`-$%X)$"i36!e-Adl$3dMF(*KCfeK)("KFQ&YCA4PFL"IAd3`)&*
%DA0V3e"AFQPdC9K38Q&Y+&pI4$!X)&pI4$%X)&pI36!T$A0SEh*d)&*%DA0V3e"
AFQPdC9K38Q&Y+(0SEh*d)(0THQ8X)(0SEh*d)'pQCR0PG#`JBfKKFL!UGfKPFQ8
T)$dJ$3Pl-(Jd1$3`,#!`H$-`-$%X)$"i36!e-Rdl$3dMC@jND@B0TQX!!!%!!!!
"!!!!!!!!!!!H!3")9d*3!3+#i9Ve9d*D6eT2AH3$U#iH(f!+i6X#rFS*8N4TFfY
$8#jS!J!!!%**6N&6594i!3!!!!"!!!!!!!!!3NP1390*9(J"!!!!!%!!!!!!!!!
!!!!!!!!!!!!!!!$FrS,E!!!$q!!!!4i5#!%!!!#q%J-!!!!!!3j!CQ0,@8h)Z*P
,!33S8!%%mV5$!5#!@8d#5T!!CajB!M&m!)#e@8eB!L&mIrpX6`%GI'C2`p42CB-
"@%qYBr)#3QhjVZ%45'd"qEa-!IqL%4!I!@FSi5-"qEK-!Iq8*!&R'Z%M!IQd6!(
rKL6@i5-"qE"-!3!!!3!!!!%!!!!!!!!!!"i!!!!!!!!!!!!F!"lrrbjV:
|
|
|
@ -1,126 +0,0 @@
|
||||||
(This file must be converted with BinHex 4.0)
|
|
||||||
:"e*%DA0V3e!!68e38Ne03d-"!*!$&[i!!!@q4cKMEfpX!*!$!3#3!a`!!"CU!!!
|
|
||||||
@KJ#3!hJ!N!-'!*!$1!!"!$!!!J!F!129M!#3"%#!QJS!!$2`!F92k!#3!f"@H2r
|
|
||||||
r!FkKH!!!"'`!N!-'!!)!N!-#!"`*6'PLFQ&bD@9c-CLRN!!!N"m#!"`*6'PLFQ&
|
|
||||||
bD@9c-CLRN!!!N"m#!#J!q2r`!*!&!G58!*!'-XB##!!!!3V,@!#3%#"YC@je!*!
|
|
||||||
%*!$Yr`%!!3#3$Jp$E'9KFL"'D@aP)'ePER8!N!3",3#3"3-!!3!#!*!$MJP54'P
|
|
||||||
cDd03,Q-!N"EFAP$i!3%!N!N#!!)!N!11$&*%DA0V3e!ZFR0bB`#3%paH5'J"!3#
|
|
||||||
3#30!!J!!$Qi06@&M5'9KC'9bFcBi5`#3%UZmEmN"!3#3#34!!J!!#rN*3646G(9
|
|
||||||
QCLjS!*!@Ul((UJ!"!*!*"3!#!*!$MJP54'PcDd03,QJ!N"EFAP"b!3%!N![%!!)
|
|
||||||
!AJ#3!`3!!4pG!!!%E!#3!`%!N!3*8N4TFfY$8#jM!*!C"J#3"3(FAP$i!*!$"+Z
|
|
||||||
aakS!N!-$Ula[b3#3!`AFAP"b!&`!AJ"R!!%!!3#3#3%!N!3-8N4TFfY$8#jbFh*
|
|
||||||
M!*!F!YaH5'J!N!5VX3#3"aK[b3l`!!AFA1kQ3cJ!N!J"$!$M4C!!!*!(!J#3#3(
|
|
||||||
rN!B!!J#3$8!!id@3!!%SLR#!5!#3"4)!3`!#!*!(5!#3!dJ!N!8)!!%!#!#3"L%
|
|
||||||
-!*!0*!$M4C!!!!5VXFHU!*!$!kZmEmN!N!-&h&j3FJ"F!*!(*!$M4C!!!*!A-!#
|
|
||||||
3"bJ!id@3!!!"!+3!%`$R!1hY2!#3"a!!N!m`!10&N!!!*!!!!R%"K3*f!!!#F3*
|
|
||||||
fIrm"K!*e!REqlEkY!*!'"@)!!!i)!*!$B!!!"D)!!!KQ!*!'"'`!N!F'!*!84@G
|
|
||||||
&E3#3!`%!N!-'rj!%!*!$&P*%DA0V!%9T!*!$!J#3!e!!N!-J!*!$&Nj@!!!LI%#
|
|
||||||
&(C&d!'!NF!!3-5!!3H`!!")`)!")JE*!C`i31!&e!N!!J'B%F!"J$&*#-%*`"E(
|
|
||||||
!CG4`!8jH6R@08N4TFfY$8%eKBd4PGJ!!4A3!N!-"!!%!N!-@!*!%4@N!N!-0!!!
|
|
||||||
"Y!#3!iJ!!!'B6PErkNMR%#!NEJ!)0Li!$(!"FJ4"l[rl5%!`!D"4F!&b"8(ZrqY
|
|
||||||
)3$!"S&&)E[rXU(3[#UKc,`S`!eC!2`")E[r`5'lrr%KZrr+TM5mZrr`),J!!rrY
|
|
||||||
Q"(!!B!*`!6m!U@-[#M!$@N!r!%KZrr")E[rm5'lrmUQ0,blrr!JZ!!(rqfF)##i
|
|
||||||
!!2rlC`4`!'!#F!%r!+PM,blrr!JZ!!$rqfB%F!"J"$!m!2mr!+PG,`S`!ej!2`"
|
|
||||||
)E[r`5'lrr%KZrr+TM5mZrr`3,[rl!N!!!fF)##i!!2rVCJ4`!'!#F!%r!+PM,bl
|
|
||||||
rr"!ZrrX#3!!$CJB`2!$rB!*`!$m!U9d[#R!0d%-r!%KZrr")E[rm5'lrmUQ0,bl
|
|
||||||
rr!JZ!!,rqfF)##i!!2rlCJ4`!'!#F!%r!+PM,blrr!JZ!!$rqfF%F!"J"$!m!2m
|
|
||||||
r!+PG,`T`$p"$2`")E[r`5'lrr%KZrr+TM5mZrr`),J!$rrYQ#!JZ!!$rqfB%F!"
|
|
||||||
J!R!"2`#TBbmZrr`),J!!rrYR"(!!B!3`2!$r2`#TA5mZrqbSFdcI"!K1ANjeM9*
|
|
||||||
%DA0V3e"9F'4KG'8!!%9T!*!$6`!!!9B!!!'X!!!'X8j@rrj`!A)%3HlrrdK!-!'
|
|
||||||
J8A!"FJ9"l[rq5%!`!D"4-#i!#T!!EJ!-9d"R'&9!Cca93'GUA8"R!!#)98"R!!#
|
|
||||||
`B!!!f"!Zrrm#3!!"C`S#,J!1rrpJ!!$%%#lrr`*!!!m!3!!"(8$rrf!!!,!3,[r
|
|
||||||
r!N!!!@B!!+33,[rr!N!!!QF+!Li!$IrrB!!!N!!3,[rr!N!!$`"!!!)G32rrB(`
|
|
||||||
3,[rr!N!!!fGb%#lrrJ*!!!&R"N)ZrrjJBKem!!(rrQ"D%#lrr`*!!!&R8"!Zrrm
|
|
||||||
#3!!%C`J#,J!,rrpJ2K!Zrrm#3!!2!%!!""e!rrpJ,"!Zrrm#3!!"Cb)3,[rr!N!
|
|
||||||
!#'F)!Li!"rrrB"!3,[rr!N!!$`"!!!JG32rrF!&b"%(Zrrp)3$!"S&*`!A)&3Hl
|
|
||||||
rrNK!-!'J8MmZ!!`[,J!B6U`!!%jH6R@08N4TFfY$8%KTG%4PGJ!!4B%!N!-0!!%
|
|
||||||
!!!&!!*!%4@N!N!04!*!$B!!!!Xi!!!XH6PErm#m+*(a!K4f4(A`!![r`6U`!!%U
|
|
||||||
!C`iGDJ!'rr%GDJ!(rr*J$"em!$(rm4em!$,rmNKZrr")H8#)!#T)H8#*,*C#TkQ
|
|
||||||
,*&p1ANjeMP*%DA0V3e"*EQPd4'9f!*!$4B%!N!-#!!%!N!-8!*!%4@S!N!06!*!
|
|
||||||
$XJ!!!di!!!dK6PB!!%MR(c!k,J!D1#i!&LiZ!"!QEJ!-*'i!##B,6U`!!#`!-!8
|
|
||||||
-3!!)BQM33$!l!!C1q`!#!")!4!!X!&i!1!!i!$J!AJ!`,`S[#bm(2bi!&$m%2bi
|
|
||||||
!'$m&6U`!!%r[!"4f!f!Z6U`!!#B!B#Br"#m+6U`!!&a2B"S[#Lm,,`Fr,J!82`3
|
|
||||||
r,J!B2`91V!!!6qm!&#!'`B`[3`!i60m-q%jH)&p2l`!86Y#%E@&TEJ#3!d@"!*!
|
|
||||||
$6`!"!*!$MJ#3"%@"!*!$$3!"!*!$G!#3"%@"!*!$!J!"!*!$D!#3"%@"!*!$83!
|
|
||||||
"!*!$A!#3"%@"!*!$9!!"!*!$)!#3"%9S8eP05!!!"%!!N!-8!*!9!3#3"aB!N!-
|
|
||||||
%!*!$2!#3!`S!N!18!*!$$J#3!m!!N!-L!!!"*J#3!c!!!!&F!*!$1J!!!9m!N!-
|
|
||||||
m!!!"PIq3"!!!!CB!!J#3!`2rN!2q!*!#3!``!N!-,!*!&!J!"!*!'!CJ!N!-
|
|
||||||
3!!!#4!#3!ai!!!*R!*!$,!!!!XF!N!-b!!!#h!#3!cB!!!,b!*!$6!!!!bd!N!0
|
|
||||||
L!!!$C`#3!hJ!!!1M!*!$PJ!!!r!!N!1Z!!!%,J#3!m3!!!4S!*!$j!!!"+i!N!2
|
|
||||||
q!!!%l!!!!43!!!8S!!!"-J!!"A3!!!&+!!!&Y3!!!@!!!!Aa!!!"IJ!!"N!!!!'
|
|
||||||
@!!!'QJ!!!C`!!!DZrj!%!!!'V`!)!*!$$[q3!rS!N!8+!*!$53#3!`X!N!8$!*!
|
|
||||||
$5J#3!`F!![q3!qX!N!0,!*!$"`!#rj!$q`#3!d`!N!-,!!,rN!2`!*!$6Iq3!rF
|
|
||||||
!![q3!r)!N!-S!*!$C`!#rj!$r!#3!dlrN!2k!!,rN!2X!!%!N!B(+!#3!`3!!!G
|
|
||||||
a!*!$%J!!"j3!N!-J!!!(X`#3!d3!!!IN!*!$@!!!#"J!N!0S!!!)43#3!f`!!!K
|
|
||||||
P!*!$H!!!#)%!N!1-!!!)YJ#3!j`!!!MT!*!$RJ!!#3F!N!1S!!!*)3#3!lJ!!!P
|
|
||||||
&!*!$[J!!#@-!N!2!!!!*J`#3!mS!!!QF!*!$h!!!#G%!N!2X!!!+"!#3!qi!!!S
|
|
||||||
N!*!$q!!!#Md!!!%+!!!+FJ!!!4S!!!Uc!!!"+!!!#YF!!!%f!!!+p`!!!8)!!!X
|
|
||||||
Erj!%!!!,(!!&!*!$8!#3!`X"!J#3!`S!N!0*!*!$#`%#!*!$$!#3!`lrN!2k!3)
|
|
||||||
!N!-B!*!$5J#3!`F!![q3!ri!N!0,!*!$"`!#rj!%!!%!N!B,Q!#3!`B!!![I!*!
|
|
||||||
$$!!!$!8!N!-5!!!-&J#3!aS!!!`Z!*!$)!!!$&N!N!-Q!!!-K!#3!bJ!!!b1!*!
|
|
||||||
$,J!!$+)!N!-d!!!-Z3#3!dJ!!!dHrj!%!!!0(`!#!*!$!rq3!ri!N!8+!*!$8[q
|
|
||||||
3!qi!![q3!r!!!3#3"Jfq!*!$(!!!$F!!N!-H!!!0r`#3!b3!!!iS!*!$5!!!$N`
|
|
||||||
!N!0L!!!1q!#3!fB!!!mL!*!$EJ!!$hN!N!0f!!!2R`#3!hS!!!qj!*!$P!!!%'%
|
|
||||||
!N!1B!!!3GJ#3!j`!!"#$rj!%!!!3K!!*!*!$93#3!`X!N!8&!*!$8!#3!`X"!J#
|
|
||||||
3!aJ!N!0*!*!$#`#3"33!N!0@!*!$#`%#!*!$&!#3!eIrN!2Y!*!&"`#3!ed!N!0
|
|
||||||
N!*!&#`#3!`lrN!2k!*!&#J#3!ei!N!-$!*!&"J#3!em!N!-$!*!&!`!"rj!%!*!
|
|
||||||
$"J#3!`%!N!-(!!(rN!2m!*!$"J#3!`%!N!-'!!(rN!2l!*!$!J#3!`%!N!-'!!,
|
|
||||||
rN!2p!*!$"!#3!c)!"`#3!`ArN!2m!*!("[q3!rX!N!-'!*!$"`#3!fX!N!-)!*!
|
|
||||||
$#!#3!`%!N!--!*!$#3#3!fJ!N!-X!*!$#J#3!`B!N!-`!*!$#`#3!`B!N!-a!!$
|
|
||||||
rN!2q!!(rN!2p!!,rN!2h!*!$&J#3!`J!"!#3!aF!N!-,!*!('!#3!`X!N!-#!*!
|
|
||||||
$'3#3!`X!N!-%!*!$'J#3!`X!N!-'!!,rN!2i!*!$%J#3!`i!!`#3!a-!N!0Q!*!
|
|
||||||
(&!#3!`X!N!-%!*!$&Iq3!rF!N!-'!!,rN!2e!*!$(3#3!`S!!J#3!ai!N!-,!*!
|
|
||||||
((rq3!rF!N!-#!!$rN!2f!!,rN!2e!!(rN!2c!*!$#!#3!`%!N!-'!!,rN!2d!*!
|
|
||||||
$)J#3!`J!!3#3!b2rN!2c!*!&![q3!r)!N!-Q!*!$"!!#!*!$*`#3!`X!N!FS!*!
|
|
||||||
$#`#3!`)!!2q3!qm!!3#3!fS!![q3!r!!N!-l!*!$0!!0!*!$22q3!qm!N!Fprj!
|
|
||||||
$l`#3!`3!N!-qrj!$l`#3!`J!N!-rrj!$l`#3!``!N!0!rj!$l`#3!a!!N!0"rj!
|
|
||||||
$l`#3!a3!N!0#rj!$l`#3!aJ!N!0$rj!$l`#3!a`!N!0%rj!$l`#3!b!!N!0&rj!
|
|
||||||
$l`#3!b3!N!0'rj!$l`#3!bJ!N!0(rj!$l`#3!b`!N!0)rj!$l`#3!c!!!2q3!r%
|
|
||||||
!!Iq3!r!!![q3!rN!N!-2!*!$E!!D!*!$%!#3!`X!N!F4rj!$q!#3!`)!N!-Erj!
|
|
||||||
$p`#3!a!!N!-Frj!$pJ#3!aJ!N!-Jrj!$pJ#3!a`!N!-Krj!$p!#3!b!!N!-Nrj!
|
|
||||||
$p!#3!bJ!N!-Prj!$mJ#3!c!!N!-Trj!$mJ#3!c3!N!-U!*!$#`#3!cJ!N!-Vrj!
|
|
||||||
$p!#3!cS!N!-X!*!$#`#3!d)!N!-Y!*!$#`#3!d3!N!-Z!*!$"J#3!dB!N!-[!*!
|
|
||||||
$"`#3!dF!N!-`!*!$#`#3!dJ!N!-a!*!$#`#3!dS!N!-b!*!$!`#3!d`!N!-c!*!
|
|
||||||
$!`#3!e!!N!-d!*!$!`#3!e3!N!-e!*!$#`#3!eJ!N!-f!*!$#`#3!eS!N!-h!*!
|
|
||||||
$C`#3!e`!N!-i!*!$C`#3!f!!N!-j!*!$C`#3!f3!N!-krj!$m3#3!fJ!!2q3!rS
|
|
||||||
!!Iq3!rN!!Iq3!qi!N!-3!*!$!3#3!`B!![q3!q`!N!0B!*!$%!!&!*!$@3#3!`S
|
|
||||||
!N!G9!*!$!J#3!`)!N!0D!*!$!J#3!`B!N!0Erj!$mJ#3!`S!N!0F!*!$#J#3!`i
|
|
||||||
!!2q3!qd!!Iq3!q`$H%!b-3!"FP*%DA0V3e"0B@0%CAB!!k"SC()!!)&54'PcDdK
|
|
||||||
NFJ!$BA0TC`!$eh*KE9*PFA9TFQ9N!!(#F'&dBfK'D@aP6Q&YC3!$b("KG'0S4QP
|
|
||||||
XC8jKE@9@CA*TCRN!!Ie`BA4MD%CTE'9#HA4P!!0iF'&dBfK'D@aP3RPdC8*PCQp
|
|
||||||
bC3!#(h"KG'0S4QPXC8*jG'9"CR4PFJ!"D@N!!6e54'PcDd039A"NBA4P!!$jBh"
|
|
||||||
%D@&XEfF!!'0(FQ&Q8'pbG!!#X@4PGQPMC3!!6A"[FR4#DA4c!!)Q3QPd6@&`!!#
|
|
||||||
cBQ&cC8&NC()!!(jbEhG#HA4PF`!#+f*[G@jNF`!!Ie*PBh3!!bpdEh!!!!aXC@C
|
|
||||||
d!!)LBQpdG'pY!!(@FQPRD(3!!#4`Eh*d8Q9MG!!#-(CTFe*REJ!#$e*PCfP[EJ!
|
|
||||||
$3A*REP0THQ8!!mjbCfj#3Qpi!!1NBfaTF&*REJ!"Q@*V8'&d!!1U8'&dG'9bEJ!
|
|
||||||
$BA"KG!!$&'CTE'a3BA3!!F"`ENa[B`!"T&"[D@jd!!&fGJ!"D'J!!UY`EP0THQ8
|
|
||||||
!!KP`ENe[C'8!!Ip`EP"KG!!"&h"Z9QPc!!,HG(K'Efjd!!*9G(K'B@0P!!+jCQP
|
|
||||||
XE'9b!!)aG(K0Ef4P!!,MG(K6DATP!!1lFh"&H(4bB3!$AfCR3fpXEh)!!cKLDd0
|
|
||||||
[E'pb!!1pBfpXFN*TG!!#aR"KG&0dFQ9dBfJ!!h4`D@06BACP!!1KFQGZ8f&fC3!
|
|
||||||
!$("[E(P6BACP!!%bCh*KCP"bEf0c!!-M8843FQpMF`!!4h4PH(43FQpM!!#0E'P
|
|
||||||
ZC9"bEf-!!,PbC@0d8(*[B`!"$R*5C@0d8(*[B`!!N@pfB@a3FQpM!!-KBA*M8(*
|
|
||||||
[B`!!m("[E(P3FQpM!!1"FQGZ8(*[B`!!UQ*TG(03FQpM!!2ZBfpYE@9ZG&"bEf-
|
|
||||||
!!MYdH%ePBA03FQpM!!,NCf9d8'PM8(*[B`!#FA"eG&"TBe"bEf-!!'pZG@e*G'9
|
|
||||||
YF`!$BR*KE3!$KA0dBA*dGA!!!'pdHA"P!!&bFJ!!cA0KGQ93Eh*d!!''8N4TFfY
|
|
||||||
$8%KTG%4PGJ!!S'PdC@d!!U&54'PcDd035@jTG%4PGJ!$"A*KE90THQ8!!,0YB@P
|
|
||||||
Z!!"(8f9d3h9bFQ9ZG%%d!!0,E@9cFf&RC3!!2Q0`8(*TGQ&dC9CKE!!!E(4SC89
|
|
||||||
fC@jd!!1P4ACPER45C@0[FQ3!!0PhD'&d!!"6GfKPEJ!"6hGSCA*P!!%XE@pND@C
|
|
||||||
TCA*c!!$0Bf4PGP0dEh*KCf9@B@aeC3!"HQpXC%%d!!2UFQ9d!,kVZZX!N$d"!"J
|
|
||||||
!N!8@8N4TFfY$8%eKBd4PGJ!!!3!B!*!%!CK54'PcDd039A"NBA4P!!!"!"J!N!3
|
|
||||||
'X9*%DA0V3e")DA4%CAB!!!%!'J#3"!XH8N4TFfY$8%PZDA4%CAB!#J!"!"!!!3!
|
|
||||||
!$5&YB@PZ!-N!N!2Ym$`!!!%H!!!"$P"'E(-!N!AYm$3!!!)X!*!$a&"-Fh3!N!S
|
|
||||||
"(!#3!`*38f9Rrrm!N!NF!!!"!&"6C@F!!3#3#!2`!!!4iQpLDQ3IA3#3#"A5!*!
|
|
||||||
$Y'*bGh-IA3!!jf3!!!%!N!-%h!!!!p`!N!2L!*!$!@%!N!3"B3#3"!&K!*!%!@%
|
|
||||||
!N!3"B3#3!`G54'PcDd03!J#3!de08&*0680$!3$rN!3!N!84!!"069"568e$3`%
|
|
||||||
!rj!%!*!5h&c[Q`!!&[i!!!@q!!&K!*!%!@%!N!3"B3#3"!&K!*!%!@%!N!3"B3#
|
|
||||||
3"!&K!*!%!@%!N!3"B3#3"!&K!*!%!@%!N!3"B3#3"!&K!*!%!@%!N!3"B3#3"!&
|
|
||||||
K!*!%!@%!N!3"B3#3"!&K!*!%!@%!N!3"B3#3"!&K!*!%!J!$!*!$5J!"!!N'6@p
|
|
||||||
ZB@0[!*!F"!!S!!S"`J+!!#J!#J(#!S!!N"!"!*!%!J#3"5J!"!%!rrm!N!Mrr`'
|
|
||||||
3"3#3""i"!3#3#*QC!*!&-!!&!*!($8eKBdKPB@4PFR-f1%X!N"`+!!)!N!X8!!3
|
|
||||||
!N!J"!*!-$!!%!3!!!3!"!3#3"JF!!J#3#!F!!J#3"`)%!!)""d4bEh"XCA3!N2N
|
|
||||||
""P0[Fh9YD3#3q`S!"!#3#l`!"!!"#dGA)&*265"%DA0V!*!dFQ4cDf0NCAB!N%K
|
|
||||||
MC'9fm#!!N!HF!2B"2!(F!3#3!`[#!*!$MJ#3$!%!N!-%h!!!!p`!N!2L!10'b!U
|
|
||||||
S!*!$(!$5!!*`FQ9Q!!S!'R"@CA)!N!1H8e45)`#3!kS!!2rr!*!$"J#3"3(rr`#
|
|
||||||
3!eS!N!8#rrm!N!1'!*!&"rrr!*!$ZJ#3"32rr`#3!mJ!N!8%rrm!N!2J!*!&"[r
|
|
||||||
r!*!$m!#3"3Mrr`#3!rX!N!8*rrm!!!%'!*!&b2rr!!!$$J#3"3Arr`!!!a`!N"!
|
|
||||||
$m2rr!*!$9!#3"!p3FQpUC@0d)&CPFR0TEfkbk3:
|
|
|
@ -1,34 +0,0 @@
|
||||||
(This file must be converted with BinHex 4.0)
|
|
||||||
:$&*%DA0V3e!ZFR0bB`"bFh*M8P0&4#'!!*!'#UM`C3#3"!%!N!-*N`!!#*-!!!%
|
|
||||||
98dP8C90*9%`"!*!'"BR#!3!,!90*9'96594-!J!-8N4TFfY$8#jbFh*M!J)!N!0
|
|
||||||
bFh*M8P0&4#'!rj!%!!"bFh*M8P0&4#'!rj!%!*!5h&c[T!#3"JUS8dP8C90*9%`
|
|
||||||
'!*!'"C'#!3!,!90*9'9`BA9Xr`#3"J@E3J%!#`&6594PFfKXBJ%!N!B&NS)"!!X
|
|
||||||
"8dP8CA0SE')#!*!'"C1#!J!,!90*9'9cD'aL!`#3"J@9JJ3!#`&6594PFfKXBJ3
|
|
||||||
!N!B&QB)!3!#3!`S!!Irr!&F!h`&#!*!$J!#382q3#2L)N!D2q)lSlSlSlSrrL*!
|
|
||||||
'M`rrN!F!N!Y!!*!8rrq!!CYY`!&rr`#3&[q3#(rr!*!%!3#38Iq3")!!!!'2(Ma
|
|
||||||
jL4)N5BN5*%Q*%L4*MaimHF!!!!&99G99Irprr`#3@2q3)(rrN!0rrj!$!*!+!J#
|
|
||||||
3r`#33[q3%2L)N!k2q)MZlSL1lZL)lZk)MZlSMrL)lZk)MZlSL1lZL)lZk)riL1l
|
|
||||||
ZL)lZk)MZlSL1lZL2q)MZlSL1lZL)lZk)MZlSMrL)lZk)MZlSL1lZL)lZk)rrL*!
|
|
||||||
1M`q"N!D2ri'3"Sm2rj!($rq3"`#3)`GMC'9f!*!'((*NFfX!N!-"4P*&4J#3"2!
|
|
||||||
J5801)`#3"2!J!*!$Z`#l!*!&)!!J%3'J!))"!!S!N!8J!##3!!!%!*!&)!!J!*!
|
|
||||||
&)!!J!*!&)!!J!*!Zrj!%J!!!!BmH2(Q*%L4*L4)N5BN5*%Q2(Maj`!!!!999e99
|
|
||||||
rrhrr!*!XS!#$r`#3!`3!!2rr!*!$63"0!*-!B!#9!8%4!D!!JU!!MJ%!#J#3"!,
|
|
||||||
3!N#B!"i!N`"J!*8"5!#6!'!!P3&"!*-!B!#9!8%!!!APL!'!!!APL!'!!+!!Mk!
|
|
||||||
!Jrm!!!%!N"B#Dp!!N+d#E2!!N$S#DJ!2!*!&!3!H!#8"')9*)*!54f&bFQ9dG#G
|
|
||||||
c)&G[FQYcD'p`$5#3%e*265"%DA0V)&0PG(4TEQGc!*!'!`%(!#-"*m!#!)!!N!8
|
|
||||||
V!&`!23%p"4*#Efpd)'CbEfdJ8Np0)'4TFfX!N!8j!'m!43%qL#&"E(GKHA-JBQp
|
|
||||||
[G#"cHA0dC@dJCR*[E5"56ddJC'PcDbi!N!C+!&`!A!%p"3j0Eh9ZG#"56ddJC'P
|
|
||||||
cD`#3"9J!E`"N!6k)+8e[G@jd)'4TFfXJGfKPEL"LEfpdD@jR)'CbEfdJEh4SCA)
|
|
||||||
JC(*TGQ8Z!*!'D3"F!(X"23824@jKBQaP)&*"65"NDA0V!*!'G`"[!)-"2SJU3@a
|
|
||||||
XEhFJGh*TG'PZCb"dEb"56ddJC'PcDbiJAM"03L"538dJFQ9a*f3Z!*!&cJ"F!0S
|
|
||||||
"2BJQ3fKKEQGPFb"hD@aX)(4KDf8JC@CQC@0d)'&QG'9b)(*PBQp[G#i!N!8R!&`
|
|
||||||
!+!%p`!)!J3#3"FS!A!$,!6h!!J#"!*!&L!"F!)N"2F!#!)%!N!@-!&`!QJ%p"3p
|
|
||||||
&EQ&LE'8JC'9LG@GRCA)!N!DD!'m!TJ%qL#*&EQ&LE'8J*eia*b"hD'9Z)'*[Eh4
|
|
||||||
TEQFJCR*[E5"56ddZ!*!&U`"F!,N"23894@jKBQaP)%0%,9*265"cGA"`Eh*d!*!
|
|
||||||
'Z3"[!-8"2SJL4@jKBQaP)#GH-LFJGfKPEL"LEfpdD@jR)'CbEfdJ8Np0,J!!!3#
|
|
||||||
3!`Q6!!!)N`!!!48!dqYN$CJ!N!-F!3B!#QjbBh3!N!0DD@0c0!#3!fCTBh-M!*!
|
|
||||||
$FNP$6L-!N!0q4P*&4J#3!iT#6N4-!*!$PQPME$3!N!1L8%P$9!!"!+jYB@0S!*!
|
|
||||||
$aR*NFfX!N!254%P86!#3!pl`)2rr!*!)m#$rr`#3!`i!N!6`)2rr!*!$NJ#3"2!
|
|
||||||
JrrmJ!!$@!*!%m#$rr`!!!pi!N!6`)2rr!!!$k3#3"2!Jrrm!!!(D!*!&J2rr!!!
|
|
||||||
%#3$6rVJ!JIrr!!!%d!$6rXM`)2rr!!!%b!#3#J8K!*!%m#$rr`!!"L8!drm!$Np
|
|
||||||
hEQ9b)(*PFfpeFQ0P8D8!:
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
10
entry.s
10
entry.s
|
@ -32,25 +32,25 @@ dc.l 0x00780000
|
||||||
|
|
||||||
DOpen:
|
DOpen:
|
||||||
movem.l %A0-%A1, -(%SP)
|
movem.l %A0-%A1, -(%SP)
|
||||||
bsr RDOpen
|
bsr RBOpen
|
||||||
movem.l (%SP)+, %A0-%A1
|
movem.l (%SP)+, %A0-%A1
|
||||||
rts
|
rts
|
||||||
|
|
||||||
DClose:
|
DClose:
|
||||||
movem.l %A0-%A1, -(%SP)
|
movem.l %A0-%A1, -(%SP)
|
||||||
bsr RDClose
|
bsr RBClose
|
||||||
movem.l (%SP)+, %A0-%A1
|
movem.l (%SP)+, %A0-%A1
|
||||||
rts
|
rts
|
||||||
|
|
||||||
DPrime:
|
DPrime:
|
||||||
movem.l %A0-%A1, -(%SP)
|
movem.l %A0-%A1, -(%SP)
|
||||||
bsr RDPrime
|
bsr RBPrime
|
||||||
movem.l (%SP)+, %A0-%A1
|
movem.l (%SP)+, %A0-%A1
|
||||||
bra.b IOReturn
|
bra.b IOReturn
|
||||||
|
|
||||||
DControl:
|
DControl:
|
||||||
movem.l %A0-%A1, -(%SP)
|
movem.l %A0-%A1, -(%SP)
|
||||||
bsr RDCtl
|
bsr RBCtl
|
||||||
movem.l (%SP)+, %A0-%A1
|
movem.l (%SP)+, %A0-%A1
|
||||||
cmpi.w #killCode, kcsCode(%A0)
|
cmpi.w #killCode, kcsCode(%A0)
|
||||||
bne.b IOReturn
|
bne.b IOReturn
|
||||||
|
@ -58,7 +58,7 @@ DControl:
|
||||||
|
|
||||||
DStatus:
|
DStatus:
|
||||||
movem.l %A0-%A1, -(%SP)
|
movem.l %A0-%A1, -(%SP)
|
||||||
bsr RDStat
|
bsr RBStat
|
||||||
movem.l (%SP)+, %A0-%A1
|
movem.l (%SP)+, %A0-%A1
|
||||||
|
|
||||||
IOReturn:
|
IOReturn:
|
||||||
|
|
89
old/Makefile
89
old/Makefile
|
@ -1,89 +0,0 @@
|
||||||
# path to RETRO68
|
|
||||||
RETRO68=~/Retro68-build/toolchain
|
|
||||||
|
|
||||||
PREFIX=$(RETRO68)/bin/m68k-apple-macos
|
|
||||||
AS=$(PREFIX)-as
|
|
||||||
CC=$(PREFIX)-gcc
|
|
||||||
LD=$(PREFIX)-ld
|
|
||||||
OBJCOPY=$(PREFIX)-objcopy
|
|
||||||
OBJDUMP=$(PREFIX)-objdump
|
|
||||||
CFLAGS=-march=68030 -c -Os
|
|
||||||
|
|
||||||
all: bin/rom16M_swap.bin obj/rdisk7M5.s obj/driver7M5.s obj/entry_rel.sym obj/driver_abs.sym
|
|
||||||
|
|
||||||
obj:
|
|
||||||
mkdir obj
|
|
||||||
|
|
||||||
bin:
|
|
||||||
mkdir bin
|
|
||||||
|
|
||||||
|
|
||||||
obj/entry.o: entry.s obj
|
|
||||||
$(AS) $< -o $@
|
|
||||||
|
|
||||||
obj/entry_rel.sym: obj obj/entry.o
|
|
||||||
$(OBJDUMP) -t obj/entry.o > $@
|
|
||||||
|
|
||||||
|
|
||||||
obj/rdisk7M5.o: rdisk.c obj
|
|
||||||
$(CC) -Wall -DRDiskSize=7864320 $(CFLAGS) $< -o $@
|
|
||||||
|
|
||||||
obj/rdisk7M5.s: obj obj/rdisk7M5.o
|
|
||||||
$(OBJDUMP) -d obj/rdisk7M5.o > $@
|
|
||||||
|
|
||||||
|
|
||||||
obj/spi.o: spi.c obj
|
|
||||||
$(CC) -Wall $(CFLAGS) $< -o $@
|
|
||||||
|
|
||||||
obj/spi.s: obj obj/spi.o
|
|
||||||
$(OBJDUMP) -d obj/spi.o > $@
|
|
||||||
|
|
||||||
|
|
||||||
obj/sdmmc.o: sdmmc.c obj
|
|
||||||
$(CC) -Wall $(CFLAGS) -Os $< -o $@
|
|
||||||
|
|
||||||
obj/sdmmc.s: obj obj/sdmmc.o
|
|
||||||
$(OBJDUMP) -d obj/sdmmc.o > $@
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
obj/driver7M5.o: obj obj/entry.o obj/rdisk7M5.o
|
|
||||||
$(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rdisk7M5.o obj/spi.o obj/sdmmc.o
|
|
||||||
|
|
||||||
obj/driver7M5.s: obj obj/driver7M5.o
|
|
||||||
$(OBJDUMP) -d obj/driver7M5.o > $@
|
|
||||||
|
|
||||||
obj/driver_abs.sym: obj obj/driver7M5.o
|
|
||||||
$(OBJDUMP) -t obj/driver7M5.o > $@
|
|
||||||
|
|
||||||
|
|
||||||
bin/driver7M5.bin: bin obj/driver7M5.o
|
|
||||||
$(OBJCOPY) -O binary obj/driver7M5.o $@
|
|
||||||
|
|
||||||
bin/rom8M.bin: bin baserom.bin RDisk7M5.dsk bin bin/driver7M5.bin obj/driver_abs.sym obj/entry_rel.sym
|
|
||||||
cp baserom.bin $@ # Copy base rom
|
|
||||||
# Patch driver
|
|
||||||
dd if=bin/driver7M5.bin of=$@ bs=1 seek=335248 skip=32 conv=notrunc # Copy driver code
|
|
||||||
printf '\x78' | dd of=$@ bs=1 seek=335168 count=1 conv=notrunc # Set resource flags
|
|
||||||
printf '\x4F' | dd of=$@ bs=1 seek=335216 count=1 conv=notrunc # Set driver flags
|
|
||||||
cat obj/entry_rel.sym | grep "DOpen" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335224 count=2 conv=notrunc
|
|
||||||
cat obj/entry_rel.sym | grep "DPrime" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335226 count=2 conv=notrunc
|
|
||||||
cat obj/entry_rel.sym | grep "DControl" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335228 count=2 conv=notrunc
|
|
||||||
cat obj/entry_rel.sym | grep "DStatus" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335230 count=2 conv=notrunc
|
|
||||||
cat obj/entry_rel.sym | grep "DClose" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335232 count=2 conv=notrunc
|
|
||||||
dd if=RDisk7M5.dsk of=$@ bs=1024 seek=512 count=7680 conv=notrunc # copy disk image
|
|
||||||
|
|
||||||
bin/rom8M_swap.bin: bin bin/rom8M.bin
|
|
||||||
dd if=bin/rom8M.bin of=$@ conv=swab # swap bytes
|
|
||||||
|
|
||||||
bin/iisi_swap.bin: bin iisi.bin
|
|
||||||
dd if=iisi.bin of=$@ conv=swab # swap bytes
|
|
||||||
|
|
||||||
bin/rom16M_swap.bin: bin/iisi_swap.bin bin/rom8M_swap.bin
|
|
||||||
cat bin/rom8M_swap.bin > $@
|
|
||||||
cat bin/iisi_swap.bin >> $@
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
|
||||||
rm -fr bin obj
|
|
84
old/entry.s
84
old/entry.s
|
@ -1,84 +0,0 @@
|
||||||
.EQU killCode, 1
|
|
||||||
.EQU noQueueBit, 9
|
|
||||||
.EQU kioTrap, 6
|
|
||||||
.EQU kioResult, 16
|
|
||||||
.EQU kcsCode, 26
|
|
||||||
.EQU JIODone, 0x08FC
|
|
||||||
.GLOBAL RDiskSig
|
|
||||||
.GLOBAL RDiskDBGNamePos
|
|
||||||
.GLOBAL RDiskDBGDisPos
|
|
||||||
.GLOBAL RDiskDBGDisByte
|
|
||||||
.GLOBAL RDiskCDRNamePos
|
|
||||||
.GLOBAL RDiskCDRDisPos
|
|
||||||
.GLOBAL RDiskCDRDisByte
|
|
||||||
|
|
||||||
dc.l 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
|
||||||
dc.l 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
|
||||||
|
|
||||||
RDiskSig:
|
|
||||||
.ascii "\5RDisk\0"
|
|
||||||
.align 4
|
|
||||||
RDiskDBGDisPos:
|
|
||||||
dc.l 0x00000031
|
|
||||||
RDiskCDRDisPos:
|
|
||||||
dc.l 0x00012CAF
|
|
||||||
RDiskDBGNameAddr:
|
|
||||||
dc.l 0x4088002A
|
|
||||||
RDiskCDRNameAddr:
|
|
||||||
dc.l 0x40892C96
|
|
||||||
RDiskDBGDisByte:
|
|
||||||
dc.b 0x44
|
|
||||||
RDiskCDRDisByte:
|
|
||||||
dc.b 0x44
|
|
||||||
RDiskRAMRequired:
|
|
||||||
.ascii "16"
|
|
||||||
|
|
||||||
.align 4
|
|
||||||
DOpen:
|
|
||||||
movem.l %A0-%A1, -(%SP)
|
|
||||||
bsr RDOpen
|
|
||||||
movem.l (%SP)+, %A0-%A1
|
|
||||||
rts
|
|
||||||
|
|
||||||
DClose:
|
|
||||||
movem.l %A0-%A1, -(%SP)
|
|
||||||
bsr RDClose
|
|
||||||
movem.l (%SP)+, %A0-%A1
|
|
||||||
rts
|
|
||||||
|
|
||||||
DPrime:
|
|
||||||
movem.l %A0-%A1, -(%SP)
|
|
||||||
bsr RDPrime
|
|
||||||
movem.l (%SP)+, %A0-%A1
|
|
||||||
bra.b IOReturn
|
|
||||||
|
|
||||||
DControl:
|
|
||||||
movem.l %A0-%A1, -(%SP)
|
|
||||||
bsr RDCtl
|
|
||||||
movem.l (%SP)+, %A0-%A1
|
|
||||||
cmpi.w #killCode, kcsCode(%A0)
|
|
||||||
bne.b IOReturn
|
|
||||||
rts
|
|
||||||
|
|
||||||
DStatus:
|
|
||||||
movem.l %A0-%A1, -(%SP)
|
|
||||||
bsr RDStat
|
|
||||||
movem.l (%SP)+, %A0-%A1
|
|
||||||
|
|
||||||
IOReturn:
|
|
||||||
move.w kioTrap(%A0), %D1
|
|
||||||
btst #noQueueBit, %D1
|
|
||||||
beq.b Queued
|
|
||||||
|
|
||||||
NotQueued:
|
|
||||||
tst.w %D0
|
|
||||||
ble.b ImmedRTS
|
|
||||||
clr.w %D0
|
|
||||||
|
|
||||||
ImmedRTS:
|
|
||||||
move.w %D0, kioResult(%A0)
|
|
||||||
rts
|
|
||||||
|
|
||||||
Queued:
|
|
||||||
move.l JIODone, -(%SP)
|
|
||||||
rts
|
|
361
old/rombus.c
361
old/rombus.c
|
@ -1,361 +0,0 @@
|
||||||
#include <Memory.h>
|
|
||||||
#include <Devices.h>
|
|
||||||
#include <Files.h>
|
|
||||||
#include <Disks.h>
|
|
||||||
#include <Errors.h>
|
|
||||||
#include <Events.h>
|
|
||||||
#include <OSUtils.h>
|
|
||||||
|
|
||||||
#include "rdisk.h"
|
|
||||||
|
|
||||||
// Decode keyboard/PRAM settings
|
|
||||||
static void RDDecodeSettings(Ptr recoveryEN, Ptr unmountEN, Ptr mountEN) {
|
|
||||||
// Read PRAM
|
|
||||||
char legacy_startup;
|
|
||||||
RBReadXPRAM(1, 4, &legacy_startup);
|
|
||||||
|
|
||||||
// Decode settings: boot from recovery, unmount (don't boot), mount (after boot)
|
|
||||||
if (RBIsRPressed()) { // R boots from ROM recovery
|
|
||||||
*recoveryEN = 1; // Enable recovery partition
|
|
||||||
*unmountEN = 0; // Unmount SD so we don't boot from it
|
|
||||||
*mountEN = 1; // Mount SD later
|
|
||||||
} else {
|
|
||||||
*recoveryEN = 0; // Disable recovery partition
|
|
||||||
if (legacy_startup & 0x10) { // Boot from SD disk
|
|
||||||
*unmountEN = 0; // Don't unmount so we boot from this drive
|
|
||||||
*mountEN = 0; // No need to mount later since we are boot disk
|
|
||||||
} else if (legacy_startup & 0x20) { // Mount SD disk under other boot volume
|
|
||||||
*unmountEN = 1; // Unmount to not boot from our disk
|
|
||||||
*mountEN = 1; // Mount in accRun
|
|
||||||
} else {
|
|
||||||
*unmountEN = 1; // Unmount
|
|
||||||
*mountEN = 0; // Don't mount again
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch to 32-bit mode and copy
|
|
||||||
#pragma parameter C24(__A0, __A1, __D0)
|
|
||||||
void __attribute__ ((noinline)) C24(Ptr sourcePtr, Ptr destPtr, unsigned long byteCount) {
|
|
||||||
signed char mode = true32b;
|
|
||||||
SwapMMUMode(&mode);
|
|
||||||
BlockMove(sourcePtr, destPtr, byteCount);
|
|
||||||
SwapMMUMode(&mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch to 32-bit mode and get
|
|
||||||
#pragma parameter __D0 G24(__A2)
|
|
||||||
char __attribute__ ((noinline)) G24(Ptr pos) {
|
|
||||||
long ret;
|
|
||||||
signed char mode = true32b;
|
|
||||||
SwapMMUMode(&mode);
|
|
||||||
ret = *pos; // Peek
|
|
||||||
SwapMMUMode(&mode);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch to 32-bit mode and set
|
|
||||||
#pragma parameter S24(__A2, __D3)
|
|
||||||
void __attribute__ ((noinline)) S24(Ptr pos, char patch) {
|
|
||||||
signed char mode = true32b;
|
|
||||||
SwapMMUMode(&mode);
|
|
||||||
*pos = patch; // Poke
|
|
||||||
SwapMMUMode(&mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Figure out the first available drive number >= 5
|
|
||||||
static int RBFindDrvNum() {
|
|
||||||
DrvQElPtr dq;
|
|
||||||
int drvNum = 5;
|
|
||||||
for (dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) {
|
|
||||||
if (dq->dQDrive >= drvNum) { drvNum = dq->dQDrive + 1; }
|
|
||||||
}
|
|
||||||
return drvNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void RBOpenRDisk(RDiskStorage_t *c) {
|
|
||||||
int drvNum;
|
|
||||||
|
|
||||||
// Find first available drive number for ROM recovery
|
|
||||||
drvNum = RBFindDrvNum();
|
|
||||||
|
|
||||||
// Set ROM recovery drive status
|
|
||||||
//c->rStatus.track = 0;
|
|
||||||
c->rStatus.writeProt = -1; // nonzero is write protected
|
|
||||||
c->rStatus.diskInPlace = 8; // 8 is nonejectable disk
|
|
||||||
c->rStatus.installed = 1; // drive installed
|
|
||||||
//c->rStatus.sides = 0;
|
|
||||||
//c->rStatus.qType = 1;
|
|
||||||
c->rStatus.dQDrive = drvNum;
|
|
||||||
//c->rStatus.dQFSID = 0;
|
|
||||||
c->rStatus.dQRefNum = d->dCtlRefNum;
|
|
||||||
c->rStatus.driveSize = RDiskSize / 512;
|
|
||||||
//c->rStatus.driveS1 = (RDiskSize / 512) >> 16;
|
|
||||||
|
|
||||||
// Decompress icon
|
|
||||||
#ifdef RDISK_COMPRESS_ICON_ENABLE
|
|
||||||
char *src = &RDiskIconCompressed[0];
|
|
||||||
char *dst = &c->rIcon[0];
|
|
||||||
UnpackBits(&src, &dst, RDISK_ICON_SIZE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Add RDisk to drive queue and return
|
|
||||||
RDiskAddDrive(c->rStatus.dQRefNum, drvNum, (DrvQElPtr)&c->rStatus.qLink);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void RBOpenSDisk(RDiskStorage_t *c) {
|
|
||||||
int drvNum;
|
|
||||||
|
|
||||||
// Find first available drive number for SD disk
|
|
||||||
drvNum = RBFindDrvNum();
|
|
||||||
|
|
||||||
// Set SD disk drive status
|
|
||||||
//c->rStatus.track = 0;
|
|
||||||
c->rStatus.writeProt = 0; // 0 is writable
|
|
||||||
c->rStatus.diskInPlace = 8; // 8 is nonejectable disk
|
|
||||||
c->rStatus.installed = 1; // drive installed
|
|
||||||
//c->rStatus.sides = 0;
|
|
||||||
c->rStatus.qType = 1;
|
|
||||||
c->rStatus.dQDrive = drvNum;
|
|
||||||
//c->rStatus.dQFSID = 0;
|
|
||||||
c->rStatus.dQRefNum = d->dCtlRefNum;
|
|
||||||
c->rStatus.driveSize = SDiskSize / 512;
|
|
||||||
c->rStatus.driveS1 = (SDiskSize / 512) >> 16;
|
|
||||||
|
|
||||||
// Decompress icon
|
|
||||||
#ifdef SDISK_COMPRESS_ICON_ENABLE
|
|
||||||
char *src = &SDiskIconCompressed[0];
|
|
||||||
char *dst = &c->sIcon[0];
|
|
||||||
UnpackBits(&src, &dst, SDISK_ICON_SIZE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Add SDisk to drive queue and return
|
|
||||||
RDiskAddDrive(c->rstatus.dQRefNum, drvNum, (DrvQElPtr)&c->sStatus.qLink);
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma parameter __D0 RBOpen(__A0, __A1)
|
|
||||||
OSErr RBOpen(IOParamPtr p, DCtlPtr d) {
|
|
||||||
RDiskStorage_t *c;
|
|
||||||
char legacy_startup;
|
|
||||||
|
|
||||||
// Do nothing if already opened
|
|
||||||
if (d->dCtlStorage) { return noErr; }
|
|
||||||
|
|
||||||
// Do nothing if inhibited
|
|
||||||
RBReadXPRAM(1, 4, &legacy_startup);
|
|
||||||
if (legacy_startup & 0x40) { return noErr; }
|
|
||||||
|
|
||||||
// Allocate storage struct
|
|
||||||
d->dCtlStorage = NewHandleSysClear(sizeof(RDiskStorage_t));
|
|
||||||
if (!d->dCtlStorage) { return openErr; }
|
|
||||||
|
|
||||||
// Lock our storage struct and get master pointer
|
|
||||||
HLock(d->dCtlStorage);
|
|
||||||
c = *(RDiskStorage_t**)d->dCtlStorage;
|
|
||||||
|
|
||||||
// Create RDisk and SDisk entries in drive queue, then return
|
|
||||||
RBOpenRDisk(c);
|
|
||||||
RBOpenSDisk(c);
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init is called at beginning of first prime (read/write) call
|
|
||||||
static void RBInit(IOParamPtr p, DCtlPtr d, RDiskStorage_t *c) {
|
|
||||||
char recoveryEN, unmountEN, mountEN;
|
|
||||||
// Mark init done
|
|
||||||
c->initialized = 1;
|
|
||||||
// Decode settings
|
|
||||||
RDDecodeSettings(&recoveryEN, &unmountEN, &mountEN);
|
|
||||||
|
|
||||||
// Unmount if not booting from ROM disk
|
|
||||||
if (!recoveryEN) { c->rStatus.diskInPlace = 0; }
|
|
||||||
|
|
||||||
// Unmount if not booting from ROM disk
|
|
||||||
if (unmountEN) { c->SStatus.diskInPlace = 0; }
|
|
||||||
|
|
||||||
// If mount enabled, enable accRun to post disk inserted event later
|
|
||||||
if (mountEN) {
|
|
||||||
d->dCtlDelay = 150; // Set accRun delay (150 ticks is 2.5 sec.)
|
|
||||||
d->dCtlFlags |= dNeedTimeMask; // Enable accRun
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static OSErr RDPrime(IOParamPtr p, DCtlPtr d) {
|
|
||||||
// Get pointer to correct position in ROM disk buffer
|
|
||||||
Ptr disk = RDiskBuf + d->dCtlPosition;
|
|
||||||
|
|
||||||
// Return disk offline error if virtual disk not inserted
|
|
||||||
if (!c->rStatus.diskInPlace) { return offLinErr; }
|
|
||||||
|
|
||||||
// Bounds checking
|
|
||||||
if (d->dCtlPosition >= RDiskSize || p->ioReqCount >= RDiskSize ||
|
|
||||||
d->dCtlPosition + p->ioReqCount >= RDiskSize) { return paramErr; }
|
|
||||||
|
|
||||||
// Service read or write request
|
|
||||||
cmd = p->ioTrap & 0x00FF;
|
|
||||||
if (cmd == aRdCmd) {
|
|
||||||
if (*MMU32bit) { BlockMove(disk, p->ioBuffer, p->ioReqCount); }
|
|
||||||
else { copy24(disk, StripAddress(p->ioBuffer), p->ioReqCount); }
|
|
||||||
} else if (cmd == aWrCmd) { return wPrErr;
|
|
||||||
} else { return noErr; } //FIXME: Fail if cmd isn't read or write?
|
|
||||||
|
|
||||||
// Update count and position/offset, then return
|
|
||||||
d->dCtlPosition += p->ioReqCount;
|
|
||||||
p->ioActCount = p->ioReqCount;
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static OSErr SDPrime(IOParamPtr p, DCtlPtr d) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma parameter __D0 RBPrime(__A0, __A1)
|
|
||||||
OSErr RBPrime(IOParamPtr p, DCtlPtr d) {
|
|
||||||
RDiskStorage_t *c;
|
|
||||||
char cmd;
|
|
||||||
|
|
||||||
// Return disk offline error if dCtlStorage null
|
|
||||||
if (!d->dCtlStorage) { return notOpenErr; }
|
|
||||||
// Dereference dCtlStorage to get pointer to our context
|
|
||||||
c = *(RDiskStorage_t**)d->dCtlStorage;
|
|
||||||
|
|
||||||
// Initialize if this is the first prime call
|
|
||||||
if (!c->initialized) { RBInit(p, d, c); }
|
|
||||||
|
|
||||||
if (p->ioVRefNum == c->sStatus.dQDrive) {
|
|
||||||
return SDPrime(p, d, c);
|
|
||||||
} else if (p->ioVRefNum == c->rStatus.dQDrive) {
|
|
||||||
return RDPrime(p, d, c);
|
|
||||||
} else { return nsvErr; }
|
|
||||||
}
|
|
||||||
|
|
||||||
static OSErr RDCtl(CntrlParamPtr p, DCtlPtr d, RDiskStorage_t *c) {
|
|
||||||
// Handle control request based on csCode
|
|
||||||
switch (p->csCode) {
|
|
||||||
case kFormat: return controlErr;
|
|
||||||
case kVerify:
|
|
||||||
if (!c->rStatus.diskInPlace) { return controlErr; }
|
|
||||||
return noErr;
|
|
||||||
case kEject:
|
|
||||||
// "Reinsert" disk if ejected illegally
|
|
||||||
if (c->rStatus.diskInPlace) {
|
|
||||||
PostEvent(diskEvt, c->status.dQDrive);
|
|
||||||
}
|
|
||||||
return controlErr; // Eject not allowed so return error
|
|
||||||
case kDriveIcon: case kMediaIcon: // Get icon
|
|
||||||
#ifdef RDISK_COMPRESS_ICON_ENABLE
|
|
||||||
*(Ptr*)p->csParam = (Ptr)c->rIcon;
|
|
||||||
#else
|
|
||||||
*(Ptr*)p->csParam = (Ptr)RDiskIcon;
|
|
||||||
#endif
|
|
||||||
return noErr;
|
|
||||||
case kDriveInfo:
|
|
||||||
// high word (bytes 2 & 3) clear
|
|
||||||
// byte 1 = primary + fixed media + internal
|
|
||||||
// byte 0 = drive type (0x11 is ROM disk)
|
|
||||||
*(long*)p->csParam = 0x00000411;
|
|
||||||
return noErr;
|
|
||||||
case 24: // Return SCSI partition size
|
|
||||||
*(long*)p->csParam = RDiskSize / 512;
|
|
||||||
return noErr;
|
|
||||||
default: return controlErr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static OSErr SDCtl(CntrlParamPtr p, DCtlPtr d, RDiskStorage_t *c) {
|
|
||||||
// Handle control request based on csCode
|
|
||||||
switch (p->csCode) {
|
|
||||||
case kFormat:
|
|
||||||
// FIXME: implement SD format
|
|
||||||
return controlErr;
|
|
||||||
case kVerify:
|
|
||||||
// FIXME: implement SD verify
|
|
||||||
return noErr;
|
|
||||||
case kEject:
|
|
||||||
// "Reinsert" disk if ejected illegally
|
|
||||||
if (c->sStatus.diskInPlace) {
|
|
||||||
PostEvent(diskEvt, c->sStatus.dQDrive);
|
|
||||||
}
|
|
||||||
return controlErr; // Eject not allowed so return error
|
|
||||||
case kDriveIcon: case kMediaIcon: // Get icon
|
|
||||||
#ifdef SDISK_COMPRESS_ICON_ENABLE
|
|
||||||
*(Ptr*)p->csParam = (Ptr)c->sIcon;
|
|
||||||
#else
|
|
||||||
*(Ptr*)p->csParam = (Ptr)SDiskIcon;
|
|
||||||
#endif
|
|
||||||
return noErr;
|
|
||||||
case kDriveInfo:
|
|
||||||
// high word (bytes 2 & 3) clear
|
|
||||||
// byte 1 = primary + fixed media + internal
|
|
||||||
// byte 0 = drive type (0x01 is unspecified drive)
|
|
||||||
*(long*)p->csParam = 0x00000401;
|
|
||||||
return noErr;
|
|
||||||
case 24: // Return SCSI partition size
|
|
||||||
*(long*)p->csParam = SDiskSize / 512;
|
|
||||||
return noErr;
|
|
||||||
default: return controlErr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma parameter __D0 RBCtl(__A0, __A1)
|
|
||||||
OSErr RBCtl(CntrlParamPtr p, DCtlPtr d) {
|
|
||||||
RDiskStorage_t *c;
|
|
||||||
// Fail if dCtlStorage null
|
|
||||||
if (!d->dCtlStorage) { return notOpenErr; }
|
|
||||||
// Dereference dCtlStorage to get pointer to our context
|
|
||||||
c = *(RDiskStorage_t**)d->dCtlStorage;
|
|
||||||
// Handle control request based on csCode
|
|
||||||
switch (p->csCode) {
|
|
||||||
case killCode:
|
|
||||||
return noErr;
|
|
||||||
case accRun:
|
|
||||||
d->dCtlFlags &= ~dNeedTimeMask; // Disable accRun
|
|
||||||
c->sStatus.diskInPlace = 8; // 8 is nonejectable disk
|
|
||||||
PostEvent(diskEvt, c->sStatus.dQDrive); // Post disk inserted event
|
|
||||||
return noErr;
|
|
||||||
case 2351: // Post-boot
|
|
||||||
c->initialized = 1; // Skip initialization
|
|
||||||
d->dCtlDelay = 30; // Set accRun delay (30 ticks is 0.5 sec.)
|
|
||||||
d->dCtlFlags |= dNeedTimeMask; // Enable accRun
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, dispatch to correct drive
|
|
||||||
if (p->ioVRefNum == c->sStatus.dQDrive) {
|
|
||||||
return SDCtl(p, d, c);
|
|
||||||
} else if (p->ioVRefNum == c->rStatus.dQDrive) {
|
|
||||||
return RDCtl(p, d, c);
|
|
||||||
} else { return nsvErr; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma parameter __D0 RBStat(__A0, __A1)
|
|
||||||
OSErr RBStat(CntrlParamPtr p, DCtlPtr d) {
|
|
||||||
RDiskStorage_t *c;
|
|
||||||
// Fail if dCtlStorage null
|
|
||||||
if (!d->dCtlStorage) { return notOpenErr; }
|
|
||||||
// Dereference dCtlStorage to get pointer to our context
|
|
||||||
c = *(RDiskStorage_t**)d->dCtlStorage;
|
|
||||||
// Handle status request based on csCode
|
|
||||||
switch (p->csCode) {
|
|
||||||
case kDriveStatus:
|
|
||||||
// Otherwise, copy correct drive status
|
|
||||||
if (p->ioVRefNum == c->sStatus.dQDrive) {
|
|
||||||
BlockMove(&c->sStatus, &p->csParam, sizeof(DrvSts2));
|
|
||||||
} else if (p->ioVRefNum == c->rStatus.dQDrive) {
|
|
||||||
BlockMove(&c->rStatus, &p->csParam, sizeof(DrvSts2));
|
|
||||||
} else { return nsvErr; }
|
|
||||||
return noErr;
|
|
||||||
default: return statusErr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma parameter __D0 RBClose(__A0, __A1)
|
|
||||||
OSErr RBClose(IOParamPtr p, DCtlPtr d) {
|
|
||||||
// If dCtlStorage not null, dispose of it
|
|
||||||
if (!d->dCtlStorage) { return noErr; }
|
|
||||||
//RDiskStorage_t *c = *(RDiskStorage_t**)d->dCtlStorage;
|
|
||||||
HUnlock(d->dCtlStorage);
|
|
||||||
DisposeHandle(d->dCtlStorage);
|
|
||||||
d->dCtlStorage = NULL;
|
|
||||||
return noErr;
|
|
||||||
}
|
|
179
old/rombus.h
179
old/rombus.h
|
@ -1,179 +0,0 @@
|
||||||
#ifndef ROMBUS_H
|
|
||||||
#define ROMBUS_H
|
|
||||||
|
|
||||||
#define RDiskBuf ((char*)0x408C0000)
|
|
||||||
#define SDiskSize (0x80000000L)
|
|
||||||
#define BufPtr ((Ptr*)0x10C)
|
|
||||||
#define MemTop ((Ptr*)0x108)
|
|
||||||
#define MMU32bit ((char*)0xCB2)
|
|
||||||
|
|
||||||
#pragma parameter __D0 RBReadXPRAM(__D0, __D1, __A0)
|
|
||||||
OSErr RBReadXPRAM(short numBytes, short whichByte, Ptr dest) = {0x4840, 0x3001, 0xA051};
|
|
||||||
|
|
||||||
#pragma parameter __D0 RBAddDrive(__D1, __D0, __A0)
|
|
||||||
OSErr RBAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq) = {0x4840, 0x3001, 0xA04E};
|
|
||||||
|
|
||||||
static inline char RBIsRPressed() { return *((char*)0x175) & 0x80; }
|
|
||||||
|
|
||||||
typedef struct RBStorage_s {
|
|
||||||
DrvSts2 sStatus;
|
|
||||||
DrvSts2 rStatus;
|
|
||||||
char initialized;
|
|
||||||
} RBStorage_t;
|
|
||||||
|
|
||||||
typedef void (*RDiskCopy_t)(Ptr, Ptr, unsigned long);
|
|
||||||
#define copy24(s, d, b) { RDiskCopy_t f = C24; f(s, d, b); }
|
|
||||||
|
|
||||||
typedef char (*RDiskPeek_t)(Ptr);
|
|
||||||
#define peek24(a, d) { RDiskPeek_t f = G24; d = f(a); }
|
|
||||||
|
|
||||||
typedef void (*RDiskPoke_t)(Ptr, char);
|
|
||||||
#define poke24(a, d) { RDiskPoke_t f = S24; f(a, d); }
|
|
||||||
|
|
||||||
#define RDISK_ICON_SIZE (285)
|
|
||||||
const char RDiskIcon[RDISK_ICON_SIZE] = {
|
|
||||||
// Icon
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b11111111, 0b11111111, 0b11111111, 0b11111111,
|
|
||||||
0b10000000, 0b00000000, 0b00000000, 0b00000001,
|
|
||||||
0b10001111, 0b00011110, 0b00111100, 0b01111001,
|
|
||||||
0b10001001, 0b00010010, 0b00100100, 0b01001001,
|
|
||||||
0b10001001, 0b00010010, 0b00100100, 0b01001001,
|
|
||||||
0b10001001, 0b00010010, 0b00100100, 0b01001001,
|
|
||||||
0b10001111, 0b00011110, 0b00111100, 0b01111001,
|
|
||||||
0b11000000, 0b00000000, 0b00000000, 0b00000001,
|
|
||||||
0b01010101, 0b01010101, 0b11010101, 0b01010101,
|
|
||||||
0b01111111, 0b11111111, 0b01111111, 0b11111111,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
// Mask
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b11111111, 0b11111111, 0b11111111, 0b11111111,
|
|
||||||
0b11111111, 0b11111111, 0b11111111, 0b11111111,
|
|
||||||
0b11111111, 0b11111111, 0b11111111, 0b11111111,
|
|
||||||
0b11111111, 0b11111111, 0b11111111, 0b11111111,
|
|
||||||
0b11111111, 0b11111111, 0b11111111, 0b11111111,
|
|
||||||
0b11111111, 0b11111111, 0b11111111, 0b11111111,
|
|
||||||
0b11111111, 0b11111111, 0b11111111, 0b11111111,
|
|
||||||
0b11111111, 0b11111111, 0b11111111, 0b11111111,
|
|
||||||
0b01111111, 0b11111111, 0b11111111, 0b11111111,
|
|
||||||
0b01111111, 0b11111111, 0b11111111, 0b11111111,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
27, 'G', 'a', 'r', 'r', 'e', 't', 't', '\'', 's', ' ',
|
|
||||||
'W', 'o', 'r', 'k', 's', 'h', 'o', 'p', ' ',
|
|
||||||
'R', 'O', 'M', ' ', 'D', 'i', 's', 'k', 0
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SDISK_ICON_SIZE (283)
|
|
||||||
const char const SDiskIcon[SDISK_ICON_SIZE] = {
|
|
||||||
// Icon
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000001, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000001, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00000001, 0b00000001, 0b10000000, 0b11010000,
|
|
||||||
0b00000001, 0b01101101, 0b10110110, 0b11010000,
|
|
||||||
0b00000001, 0b01101101, 0b10110110, 0b11010000,
|
|
||||||
0b00000001, 0b01101101, 0b10110110, 0b11010000,
|
|
||||||
0b00000001, 0b01101101, 0b10110110, 0b11010000,
|
|
||||||
0b00000001, 0b01101101, 0b10110110, 0b11010000,
|
|
||||||
0b00000001, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00000001, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00000010, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00000100, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001000, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001000, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001000, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001000, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001110, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00000010, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00000010, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00000010, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00000100, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001000, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001000, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001000, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001000, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001000, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001000, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001000, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001000, 0b00000000, 0b00000000, 0b00010000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
// Mask
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000001, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000001, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000001, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000001, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000001, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000001, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000001, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000001, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000001, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000001, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000011, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000011, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000011, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000011, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00001111, 0b11111111, 0b11111111, 0b11110000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
25, 'G', 'a', 'r', 'r', 'e', 't', 't', '\'', 's', ' ',
|
|
||||||
'W', 'o', 'r', 'k', 's', 'h', 'o', 'p', ' ',
|
|
||||||
'R', 'O', 'M', 'B', 'U', 'S', 0
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
220
old/sdmmc.c
220
old/sdmmc.c
|
@ -1,220 +0,0 @@
|
||||||
#include "sdmmc.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Module Private Functions
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#define INIT_PORT() init_port() /* Initialize MMC control port (CS/CLK/DI:output, DO:input) */
|
|
||||||
#define DLY_US(n) dly_us(n) /* Delay n microseconds */
|
|
||||||
#define FORWARD(d) forward(d) /* Data in-time processing function (depends on the project) */
|
|
||||||
|
|
||||||
/* Definitions for MMC/SDC command */
|
|
||||||
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
|
|
||||||
#define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
|
|
||||||
#define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
|
|
||||||
#define CMD8 (0x40+8) /* SEND_IF_COND */
|
|
||||||
#define CMD16 (0x40+16) /* SET_BLOCKLEN */
|
|
||||||
#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
|
|
||||||
#define CMD24 (0x40+24) /* WRITE_BLOCK */
|
|
||||||
#define CMD55 (0x40+55) /* APP_CMD */
|
|
||||||
#define CMD58 (0x40+58) /* READ_OCR */
|
|
||||||
|
|
||||||
/* Card type flags (CardType) */
|
|
||||||
#define CT_MMC 0x01 /* MMC ver 3 */
|
|
||||||
#define CT_SD1 0x02 /* SD ver 1 */
|
|
||||||
#define CT_SD2 0x04 /* SD ver 2 */
|
|
||||||
#define CT_SDC (CT_SD1|CT_SD2) /* SD */
|
|
||||||
#define CT_BLOCK 0x08 /* Block addressing */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static char CardType; /* 0:MMC, 1:SDv1, 2:SDv2, 3:Block addressing */
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Send a command packet to MMC */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
static char send_cmd(char cmd, long arg)
|
|
||||||
{
|
|
||||||
char n, res;
|
|
||||||
|
|
||||||
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
|
|
||||||
cmd &= 0x7F;
|
|
||||||
res = send_cmd(CMD55, 0);
|
|
||||||
if (res > 1) return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select the card */
|
|
||||||
CS_H(); spi_rx();
|
|
||||||
CS_L(); spi_rx();
|
|
||||||
|
|
||||||
/* Send a command packet */
|
|
||||||
spi_tx(cmd); /* Start + Command index */
|
|
||||||
s((BYTE)(arg >> 24)); /* Argument[31..24] */
|
|
||||||
spi_tx((BYTE)(arg >> 16)); /* Argument[23..16] */
|
|
||||||
spi_tx((BYTE)(arg >> 8)); /* Argument[15..8] */
|
|
||||||
spi_tx((BYTE)arg); /* Argument[7..0] */
|
|
||||||
n = 0x01; /* Dummy CRC + Stop */
|
|
||||||
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
|
|
||||||
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
|
|
||||||
spi_tx(n);
|
|
||||||
|
|
||||||
/* Receive a command response */
|
|
||||||
n = 10; /* Wait for a valid response in timeout of 10 attempts */
|
|
||||||
do {
|
|
||||||
res = spi_rx();
|
|
||||||
} while ((res & 0x80) && --n);
|
|
||||||
|
|
||||||
return res; /* Return with the response value */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Public Functions
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Initialize Disk Drive */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
sdstatus_t sdmmc_init()
|
|
||||||
{
|
|
||||||
char n, cmd, ty, buf[4];
|
|
||||||
uint tmr;
|
|
||||||
|
|
||||||
CS_H();
|
|
||||||
spi_skip(10); /* Dummy clocks */
|
|
||||||
|
|
||||||
ty = 0;
|
|
||||||
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
|
|
||||||
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */
|
|
||||||
for (n = 0; n < 4; n++) buf[n] = spi_rx(); /* Get trailing return value of R7 resp */
|
|
||||||
if (buf[2] == 0x01 && buf[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
|
|
||||||
for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state (ACMD41 with HCS bit) */
|
|
||||||
if (send_cmd(ACMD41, 1UL << 30) == 0) break;
|
|
||||||
DLY_US(1000);
|
|
||||||
}
|
|
||||||
if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
|
|
||||||
for (n = 0; n < 4; n++) buf[n] = spi_rx();
|
|
||||||
ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { /* SDv1 or MMCv3 */
|
|
||||||
if (send_cmd(ACMD41, 0) <= 1) {
|
|
||||||
ty = CT_SD1; cmd = ACMD41; /* SDv1 */
|
|
||||||
} else {
|
|
||||||
ty = CT_MMC; cmd = CMD1; /* MMCv3 */
|
|
||||||
}
|
|
||||||
for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state */
|
|
||||||
if (send_cmd(cmd, 0) == 0) break;
|
|
||||||
DLY_US(1000);
|
|
||||||
}
|
|
||||||
if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */
|
|
||||||
ty = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CardType = ty;
|
|
||||||
release_spi();
|
|
||||||
|
|
||||||
return ty ? 0 : STA_NOINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Read partial sector */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
sdresult_t sdmmc_readp(Ptr buf, long sector, uint offset, uint count)
|
|
||||||
{
|
|
||||||
DRESULT res;
|
|
||||||
char d;
|
|
||||||
uint bc, tmr;
|
|
||||||
|
|
||||||
|
|
||||||
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
|
|
||||||
|
|
||||||
res = RES_ERROR;
|
|
||||||
if (send_cmd(CMD17, sector) == 0) { /* READ_SINGLE_BLOCK */
|
|
||||||
|
|
||||||
tmr = 1000;
|
|
||||||
do { /* Wait for data packet in timeout of 100ms */
|
|
||||||
DLY_US(100);
|
|
||||||
d = spi_rx();
|
|
||||||
} while (d == 0xFF && --tmr);
|
|
||||||
|
|
||||||
if (d == 0xFE) { /* A data packet arrived */
|
|
||||||
bc = 514 - offset - count;
|
|
||||||
|
|
||||||
/* Skip leading bytes */
|
|
||||||
if (offset) spi_skip(offset);
|
|
||||||
|
|
||||||
/* Receive a part of the sector */
|
|
||||||
if (buff) { /* Store data to the memory */
|
|
||||||
do
|
|
||||||
*buff++ = spi_rx();
|
|
||||||
while (--count);
|
|
||||||
} else { /* Forward data to the outgoing stream */
|
|
||||||
do {
|
|
||||||
d = spi_rx();
|
|
||||||
FORWARD(d);
|
|
||||||
} while (--count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip trailing bytes and CRC */
|
|
||||||
spi_skip(bc);
|
|
||||||
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
release_spi();
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/* Write partial sector */
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
sdresult_t sdmmc_writep(const Ptr buf, long sc)
|
|
||||||
{
|
|
||||||
DRESULT res;
|
|
||||||
UINT bc, tmr;
|
|
||||||
static UINT wc;
|
|
||||||
|
|
||||||
res = RES_ERROR;
|
|
||||||
|
|
||||||
if (buff) { /* Send data bytes */
|
|
||||||
bc = (UINT)sc;
|
|
||||||
while (bc && wc) { /* Send data bytes to the card */
|
|
||||||
spi_tx(*buff++);
|
|
||||||
wc--; bc--;
|
|
||||||
}
|
|
||||||
res = RES_OK;
|
|
||||||
} else {
|
|
||||||
if (sc) { /* Initiate sector write transaction */
|
|
||||||
if (!(CardType & CT_BLOCK)) sc *= 512; /* Convert to byte address if needed */
|
|
||||||
if (send_cmd(CMD24, sc) == 0) { /* WRITE_SINGLE_BLOCK */
|
|
||||||
spi_tx(0xFF); spi_tx(0xFE); /* Data block header */
|
|
||||||
wc = 512; /* Set byte counter */
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
} else { /* Finalize sector write transaction */
|
|
||||||
bc = wc + 2;
|
|
||||||
while (bc--) spi_tx(0); /* Fill left bytes and CRC with zeros */
|
|
||||||
if ((spi_rx() & 0x1F) == 0x05) { /* Receive data resp and wait for end of write process in timeout of 300ms */
|
|
||||||
for (tmr = 10000; spi_rx() != 0xFF && tmr; tmr--) /* Wait for ready (max 1000ms) */
|
|
||||||
DLY_US(100);
|
|
||||||
if (tmr) res = RES_OK;
|
|
||||||
}
|
|
||||||
release_spi();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
29
old/sdmmc.h
29
old/sdmmc.h
|
@ -1,29 +0,0 @@
|
||||||
#ifndef SDMMC_H
|
|
||||||
#define SDMMC_H
|
|
||||||
|
|
||||||
|
|
||||||
/* Status of Disk Functions */
|
|
||||||
typedef char sdstatus_t;
|
|
||||||
|
|
||||||
#define STA_NOINIT 0x01 /* Drive not initialized */
|
|
||||||
#define STA_NODISK 0x02 /* No medium in the drive */
|
|
||||||
|
|
||||||
|
|
||||||
/* Results of Disk Functions */
|
|
||||||
typedef enum sdmmc_result_e {
|
|
||||||
RES_OK = 0, /* 0: Function succeeded */
|
|
||||||
RES_ERROR, /* 1: Disk error */
|
|
||||||
RES_NOTRDY, /* 2: Not ready */
|
|
||||||
RES_PARERR /* 3: Invalid parameter */
|
|
||||||
} sdresult_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------*/
|
|
||||||
/* Prototypes for disk control functions */
|
|
||||||
/*---------------------------------------*/
|
|
||||||
sdstatus_t sdmmc_init();
|
|
||||||
sdresult_t sdmmc_readp(Ptr buf, long sector, uint offset, uint count);
|
|
||||||
sdresult_t sdmmc_writep(const Ptr buf, long sc);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
164
old/spi.c
164
old/spi.c
|
@ -1,164 +0,0 @@
|
||||||
#include "spi.h"
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
/* Platform dependent macros and functions needed to be modified */
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
#define CS_H() bset(P0) /* Set MMC CS "high" */
|
|
||||||
#define CS_L() bclr(P0) /* Set MMC CS "low" */
|
|
||||||
#define CK_H() bset(P1) /* Set MMC SCLK "high" */
|
|
||||||
#define CK_L() bclr(P1) /* Set MMC SCLK "low" */
|
|
||||||
#define DI_H() bset(P2) /* Set MMC DI "high" */
|
|
||||||
#define DI_L() bclr(P2) /* Set MMC DI "low" */
|
|
||||||
#define DO btest(P3) /* Test MMC DO (high:true, low:false) */
|
|
||||||
|
|
||||||
|
|
||||||
// Command listing
|
|
||||||
/* T16: Transfer 16-bit
|
|
||||||
* First, the 16-bit value encoded in the address bits A[17:2] is latched.
|
|
||||||
* The data output mux is set to the current RXR and the cycle completes.
|
|
||||||
* Shortly after /AS rises, the SPI transfer engine begins
|
|
||||||
* transferring the latched value.
|
|
||||||
*/
|
|
||||||
/* T16S: Transfer 16-bit Swapped
|
|
||||||
* Same as T16L but read data is byte-swapped.
|
|
||||||
*/
|
|
||||||
/* MERT: Measure Elapsed time and Reset Timer
|
|
||||||
* The elapsed time since the last MERT command is returned in D[31:24]
|
|
||||||
* and the timer is reset.
|
|
||||||
*/
|
|
||||||
/* SKIP1: Skip Clocks with MOSI "1"
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/* SKIP0: Skip Clocks with MOSI "0"
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/* T8S: Transfer 8-bit Swapped
|
|
||||||
* Same as T8 but read data is byte-swapped.
|
|
||||||
*/
|
|
||||||
/* T8: Transfer 8-bit
|
|
||||||
* First, the 8-bit value encoded in the address bits A[9:2] is latched.
|
|
||||||
* The data output mux is set to the current RXR and the cycle completes.
|
|
||||||
* Shortly after /AS rises, the SPI transfer engine begins
|
|
||||||
* transferring the latched value.
|
|
||||||
*/
|
|
||||||
/* WRC: Write Command
|
|
||||||
* The command encoded in address bits A[9:2] is sent to the command target
|
|
||||||
* corresponding to the address bits A[15:10].
|
|
||||||
* Command targets:
|
|
||||||
* $00 - Set bitbang
|
|
||||||
* A[2] - SCS value
|
|
||||||
*/
|
|
||||||
/* RDRXR: Read Receive Data Register
|
|
||||||
* The the current RXR is returned in D[31:16] and the cycle completes.
|
|
||||||
*/
|
|
||||||
/* RDRXRS: Read Receive Data Register Swapped
|
|
||||||
* Same as RDRXR but read data is byte-swapped.
|
|
||||||
*/
|
|
||||||
/* MAGIC: Write Command
|
|
||||||
* Write sequence $FF $00 $55 $AA $C1 $AD
|
|
||||||
* to enable registers at $40890000-$4097FFFF.
|
|
||||||
* Write anything else to disable them.
|
|
||||||
* Always reads 0xC1AD
|
|
||||||
*/
|
|
||||||
|
|
||||||
// SPI controller address map:
|
|
||||||
// 40940000-4097FFFF (256 kB, D[31:16]) T16S. Write transfer data in A[17:2].
|
|
||||||
// 40900000-4093FFFF (256 kB, D[31:16]) T16. Write transfer data in A[17:2].
|
|
||||||
// 408C0000-408FFFFF (320 kB) reserved
|
|
||||||
// 408A0000-408AFFFF ( 64 kB, D[31:24]) WRC. Write port address in A[15:10] and data in A[9:2].
|
|
||||||
// 40891C00-4089FFFF ( 55 kB) reserved
|
|
||||||
// 40892000-408923FF ( 1 kB, D[31:24]) MERT.
|
|
||||||
// 40891C00-40891FFF ( 1 kB) SKIP1. Write bytes to skip in A[9:2].
|
|
||||||
// 40891800-40891BFF ( 1 kB) SKIP0. Write bytes to skip in A[9:2].
|
|
||||||
// 40891400-408917FF ( 1 kB, D[31:16]) T8S. Write transfer data in A[9:2].
|
|
||||||
// 40891000-408913FF ( 1 kB, D[31:16]) T8. Write transfer data in A[9:2].
|
|
||||||
// 40890C00-40890FFF ( 1 kB, D[31:16]) RDRXRS.
|
|
||||||
// 40890800-40890BFF ( 1 kB, D[31:16]) RDRXR.
|
|
||||||
// 40890400-408907FF ( 1 kB) reserved
|
|
||||||
// 40890000-408903FF ( 1 kB, D[31:24]) MAGIC. Write magic numbers in A[9:2].
|
|
||||||
// 40880000-408FFFFF ( 64 kB, D[31:00]) ROMBUS driver data
|
|
||||||
|
|
||||||
#define RB_T16S(x) (*(volatile int*) (0x40940000 + ((x && 0xFFFF)<<02)) )
|
|
||||||
#define RB_T16(x) (*(volatile int*) (0x40900000 + ((x && 0xFFFF)<<02)) )
|
|
||||||
#define RB_RDS(a) (*(volatile char*) (0x408B0000 + ((a && 0x003F)<<10)) )
|
|
||||||
#define RB_WRC(a,d) (*(volatile char*) (0x408A0000 + ((a && 0x003F)<<10)
|
|
||||||
+ ((d && 0x00FF)<<02)) )
|
|
||||||
#define RB_MERT(x) (*(volatile char*) (0x40892000 + ((x && 0xFFFF)<<02)) )
|
|
||||||
#define RB_SKIP1(n) (*(volatile char*) (0x40891C00 + ((x && 0xFFFF)<<02)) )
|
|
||||||
#define RB_SKIP0(n) (*(volatile char*) (0x40891800 + ((x && 0xFFFF)<<02)) )
|
|
||||||
#define RB_T8S(x) (*(volatile int*) (0x40891400 + ((x && 0xFFFF)<<02)) )
|
|
||||||
#define RB_T8(x) (*(volatile int*) (0x40891000 + ((x && 0xFFFF)<<02)) )
|
|
||||||
#define RB_RDRXRS (*(volatile int*) (0x40890C00 + ((x && 0xFFFF)<<02)) )
|
|
||||||
#define RB_RDRXR (*(volatile int*) (0x40890800 + ((x && 0xFFFF)<<02)) )
|
|
||||||
#define RB_WRMOSI(x) (*(volatile char*) (0x40890400 + ((x && 0x0001)<<02)) )
|
|
||||||
#define RB_MAGIC(x) (*(volatile char*) (0x40890000 + ((x && 0xFFFF)<<02)) )
|
|
||||||
|
|
||||||
#define SPI_GET_MISO(d) (d & 1)
|
|
||||||
|
|
||||||
void spi_select() {
|
|
||||||
ret = *SPI_CMD_SEL0;
|
|
||||||
ret = *SPI_CMD_SEL1;
|
|
||||||
ret = *SPI_CMD_SEL2;
|
|
||||||
ret = *SPI_CMD_SEL3;
|
|
||||||
}
|
|
||||||
void spi_deselect() {
|
|
||||||
ret = *SPI_CMD_DES0;
|
|
||||||
ret = *SPI_CMD_DES1;
|
|
||||||
ret = *SPI_CMD_DES2;
|
|
||||||
ret = *SPI_CMD_DES3;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_tx_slow(char d) {
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
*SPI_CMD_BBA((0 & 0x02) | (d & 0x01));
|
|
||||||
*SPI_CMD_BBA((1 & 0x02) | (d & 0x01));
|
|
||||||
d >>= 1;
|
|
||||||
}
|
|
||||||
*SPI_CMD_BBA((0 & 0x02) | (0 & 0x01));
|
|
||||||
}
|
|
||||||
|
|
||||||
char spi_rx_slow() {
|
|
||||||
char ret = 0;
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
*SPI_CMD_BBA((0 & 0x02) | (1 & 0x01));
|
|
||||||
*SPI_CMD_BBA((1 & 0x02) | (1 & 0x01));
|
|
||||||
ret = (ret << 1) + (*SPI_CMD_BBA((1 & 0x02) | (1 & 0x01)) & 1);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_skip_slow(int n) {
|
|
||||||
while (n-- > 0) {
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
*SPI_CMD_BBA((0 & 0x02) | (1 & 0x01));
|
|
||||||
*SPI_CMD_BBA((1 & 0x02) | (1 & 0x01));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*SPI_CMD_BBA((0 & 0x02) | (1 & 0x01));
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_tx_8(char d) {
|
|
||||||
*SPI_CMD_SH8(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
char spi_rx_8() {
|
|
||||||
*SPI_CMD_SH8(0xFF);
|
|
||||||
return *SPI_CMD_RD & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_tx_16(int d) {
|
|
||||||
*SPI_CMD_SH16(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_rx_16() {
|
|
||||||
*SPI_CMD_SH16(0xFFFF);
|
|
||||||
return *SPI_CMD_RD & 0xFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_skip(int n) {
|
|
||||||
while (n-- > 0) {
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
*SPI_CMD_SH8(0xFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
17
old/spi.h
17
old/spi.h
|
@ -1,17 +0,0 @@
|
||||||
#ifndef SPI_H
|
|
||||||
#define SPI_H
|
|
||||||
|
|
||||||
void spi_select();
|
|
||||||
void spi_deselect();
|
|
||||||
|
|
||||||
void spi_tx_slow(char d);
|
|
||||||
char spi_rx_slow();
|
|
||||||
void spi_skip_slow(int n);
|
|
||||||
|
|
||||||
void spi_tx_8(char d);
|
|
||||||
char spi_rx_8();
|
|
||||||
void spi_tx_16(int d);
|
|
||||||
int spi_rx_16();
|
|
||||||
void spi_skip(int n);
|
|
||||||
|
|
||||||
#endif
|
|
11
old/xfer.h
11
old/xfer.h
|
@ -1,11 +0,0 @@
|
||||||
#ifndef RDISK_H
|
|
||||||
#define RDISK_H
|
|
||||||
|
|
||||||
#pragma parameter xfer_s_256(__A0, __A1)
|
|
||||||
void xfer_s_256(Ptr srcreg, Ptr destmem);
|
|
||||||
|
|
||||||
#pragma parameter xfer_s(__D0, __A0, __A1)
|
|
||||||
void xfer_s(uint8_t numBytes, Ptr srcreg, Ptr destmem);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
34
old/xfer.s
34
old/xfer.s
|
@ -1,34 +0,0 @@
|
||||||
.macro xfer_in from, to
|
|
||||||
move.w (%A0), (%A1)+
|
|
||||||
nop
|
|
||||||
nop
|
|
||||||
nop
|
|
||||||
.if \to-\from
|
|
||||||
xfer_in "(\from+1)"
|
|
||||||
.else
|
|
||||||
|
|
||||||
.endif
|
|
||||||
.endm
|
|
||||||
|
|
||||||
|
|
||||||
;pragma parameter xfer_s_256(__A0, __A1)
|
|
||||||
;void xfer_s_256(Ptr srcreg, Ptr destmem);
|
|
||||||
xfer_256:
|
|
||||||
movem.l %D0/%A1-%A2, -(%SP)
|
|
||||||
xfer_256_loop:
|
|
||||||
xfer_s_in 0, 255
|
|
||||||
xfer_256_end:
|
|
||||||
movem.l (%SP)+, %D0/%A1-%A2
|
|
||||||
|
|
||||||
|
|
||||||
;pragma parameter xfer_s(__D0, __A0, __A1)
|
|
||||||
;void xfer_s(uint8_t numBytes, Ptr srcreg, Ptr destmem);
|
|
||||||
xfer:
|
|
||||||
movem.l %D0/%A1-%A2, -(%SP)
|
|
||||||
andi.l #0xFF, %D0
|
|
||||||
subi.l #256, %D0
|
|
||||||
neg.l %D0
|
|
||||||
lsl.l #2, %D0
|
|
||||||
addi.l #xfer_256, %D0
|
|
||||||
movea.l %D0, %A2
|
|
||||||
jmp %A2
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef _PRIV_SYSCALL_H
|
||||||
|
#define _PRIV_SYSCALL_H
|
||||||
|
|
||||||
|
#include <Disks.h>
|
||||||
|
#include <OSUtils.h>
|
||||||
|
|
||||||
|
#pragma parameter __D0 PSReadXPRAM(__D0, __D1, __A0)
|
||||||
|
OSErr PSReadXPRAM(short numBytes, short whichByte, Ptr dest) = {0x4840, 0x3001, 0xA051};
|
||||||
|
|
||||||
|
#pragma parameter __D0 PSAddDrive(__D1, __D0, __A0)
|
||||||
|
OSErr PSAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq) = {0x4840, 0x3001, 0xA04E};
|
||||||
|
|
||||||
|
// Figure out the first available drive number >= 5
|
||||||
|
static int PSFindDrvNum() {
|
||||||
|
DrvQElPtr dq;
|
||||||
|
int drvNum = 5;
|
||||||
|
for (dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) {
|
||||||
|
if (dq->dQDrive >= drvNum) { drvNum = dq->dQDrive + 1; }
|
||||||
|
}
|
||||||
|
return drvNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
353
rdisk.c
353
rdisk.c
|
@ -1,353 +0,0 @@
|
||||||
#include <Memory.h>
|
|
||||||
#include <Devices.h>
|
|
||||||
#include <Files.h>
|
|
||||||
#include <Disks.h>
|
|
||||||
#include <Errors.h>
|
|
||||||
#include <Events.h>
|
|
||||||
#include <OSUtils.h>
|
|
||||||
|
|
||||||
#include "rdisk.h"
|
|
||||||
|
|
||||||
// Decode keyboard/PRAM settings
|
|
||||||
static void RDDecodeSettings(Ptr unmountEN, Ptr mountEN, Ptr ramEN, Ptr dbgEN, Ptr cdrEN) {
|
|
||||||
// Sample R and A keys repeatedly
|
|
||||||
char r = 0, a = 0;
|
|
||||||
long tmax = TickCount() + 60;
|
|
||||||
for (long i = 0; i < 1000000; i++) {
|
|
||||||
a |= RDiskIsAPressed();
|
|
||||||
r |= RDiskIsRPressed() | a;
|
|
||||||
if (r) { break; }
|
|
||||||
if (TickCount() > tmax) { break; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read PRAM
|
|
||||||
char legacy_startup, legacy_ram;
|
|
||||||
RDiskReadXPRAM(1, 4, &legacy_startup);
|
|
||||||
RDiskReadXPRAM(1, 5, &legacy_ram);
|
|
||||||
|
|
||||||
// Decode settings: unmount (don't boot), mount (after boot), RAM disk
|
|
||||||
if (r) { // R boots from ROM disk
|
|
||||||
*unmountEN = 0; // Don't unmount so we boot from this drive
|
|
||||||
*mountEN = 0; // No need to mount later since we are boot disk
|
|
||||||
*ramEN = a; // A enables RAM disk
|
|
||||||
*dbgEN = 0;
|
|
||||||
*cdrEN = 0;
|
|
||||||
} else {
|
|
||||||
if (legacy_startup & 0x01) { // Boot from ROM disk
|
|
||||||
*unmountEN = 0; // Don't unmount so we boot from this drive
|
|
||||||
*mountEN = 0; // No need to mount later since we are boot disk
|
|
||||||
*ramEN = legacy_ram & 0x01; // Allocate RAM disk if bit 0 == 1
|
|
||||||
*dbgEN = legacy_startup & 0x04; // MacsBug enabled if bit 2 == 1
|
|
||||||
*cdrEN = legacy_startup & 0x08; // CD-ROM enabled if bit 3 == 1
|
|
||||||
} else if (!(legacy_startup & 0x02)) { // Mount ROM disk
|
|
||||||
*unmountEN = 1; // Unmount to not boot from our disk
|
|
||||||
*mountEN = 1; // Mount in accRun
|
|
||||||
*ramEN = legacy_ram & 0x01; // Allocate RAM disk if bit 0 == 1
|
|
||||||
*dbgEN = 1; // CD-ROM ext. always enabled in mount mode
|
|
||||||
*cdrEN = 1; // MacsBug always enabled in mount mode
|
|
||||||
} else {
|
|
||||||
*unmountEN = 1; // Unmount
|
|
||||||
*mountEN = 0; // Don't mount again
|
|
||||||
*ramEN = 0; // Don't allocate RAM disk
|
|
||||||
*dbgEN = 1; // CD-ROM ext. always enabled in unmount mode
|
|
||||||
*cdrEN = 1; // MacsBug always enabled in unmount mode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch to 32-bit mode and copy
|
|
||||||
#pragma parameter C24(__A0, __A1, __D0)
|
|
||||||
void __attribute__ ((noinline)) C24(Ptr sourcePtr, Ptr destPtr, unsigned long byteCount) {
|
|
||||||
signed char mode = true32b;
|
|
||||||
SwapMMUMode(&mode);
|
|
||||||
BlockMove(sourcePtr, destPtr, byteCount);
|
|
||||||
SwapMMUMode(&mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch to 32-bit mode and get
|
|
||||||
#pragma parameter __D0 G24(__A2)
|
|
||||||
char __attribute__ ((noinline)) G24(Ptr pos) {
|
|
||||||
long ret;
|
|
||||||
signed char mode = true32b;
|
|
||||||
SwapMMUMode(&mode);
|
|
||||||
ret = *pos; // Peek
|
|
||||||
SwapMMUMode(&mode);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch to 32-bit mode and set
|
|
||||||
#pragma parameter S24(__A2, __D3)
|
|
||||||
void __attribute__ ((noinline)) S24(Ptr pos, char patch) {
|
|
||||||
signed char mode = true32b;
|
|
||||||
SwapMMUMode(&mode);
|
|
||||||
*pos = patch; // Poke
|
|
||||||
SwapMMUMode(&mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Figure out the first available drive number >= 5
|
|
||||||
static int RDFindDrvNum() {
|
|
||||||
DrvQElPtr dq;
|
|
||||||
int drvNum = 5;
|
|
||||||
for (dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) {
|
|
||||||
if (dq->dQDrive >= drvNum) { drvNum = dq->dQDrive + 1; }
|
|
||||||
}
|
|
||||||
return drvNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma parameter __D0 RDOpen(__A0, __A1)
|
|
||||||
OSErr RDOpen(IOParamPtr p, DCtlPtr d) {
|
|
||||||
int drvNum;
|
|
||||||
RDiskStorage_t *c;
|
|
||||||
char legacy_startup;
|
|
||||||
|
|
||||||
// Do nothing if already opened
|
|
||||||
if (d->dCtlStorage) { return noErr; }
|
|
||||||
|
|
||||||
// Do nothing if inhibited
|
|
||||||
RDiskReadXPRAM(1, 4, &legacy_startup);
|
|
||||||
if (legacy_startup & 0x80) { return noErr; }
|
|
||||||
|
|
||||||
// Allocate storage struct
|
|
||||||
d->dCtlStorage = NewHandleSysClear(sizeof(RDiskStorage_t));
|
|
||||||
if (!d->dCtlStorage) { return openErr; }
|
|
||||||
|
|
||||||
// Lock our storage struct and get master pointer
|
|
||||||
HLock(d->dCtlStorage);
|
|
||||||
c = *(RDiskStorage_t**)d->dCtlStorage;
|
|
||||||
|
|
||||||
// Find first available drive number
|
|
||||||
drvNum = RDFindDrvNum();
|
|
||||||
|
|
||||||
// Get debug and CD-ROM disable settings from ROM table
|
|
||||||
c->dbgDisByte = RDiskDBGDisByte;
|
|
||||||
c->cdrDisByte = RDiskCDRDisByte;
|
|
||||||
|
|
||||||
// Set drive status
|
|
||||||
//c->status.track = 0;
|
|
||||||
c->status.writeProt = -1; // nonzero is write protected
|
|
||||||
c->status.diskInPlace = 8; // 8 is nonejectable disk
|
|
||||||
c->status.installed = 1; // drive installed
|
|
||||||
//c->status.sides = 0;
|
|
||||||
//c->status.qType = 1;
|
|
||||||
c->status.dQDrive = drvNum;
|
|
||||||
//c->status.dQFSID = 0;
|
|
||||||
c->status.dQRefNum = d->dCtlRefNum;
|
|
||||||
c->status.driveSize = RDiskSize / 512;
|
|
||||||
//c->status.driveS1 = (RDiskSize / 512) >> 16;
|
|
||||||
|
|
||||||
// Decompress icon
|
|
||||||
#ifdef RDISK_COMPRESS_ICON_ENABLE
|
|
||||||
char *src = &RDiskIconCompressed[0];
|
|
||||||
char *dst = &c->icon[0];
|
|
||||||
UnpackBits(&src, &dst, RDISK_ICON_SIZE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Add drive to drive queue and return
|
|
||||||
RDiskAddDrive(c->status.dQRefNum, drvNum, (DrvQElPtr)&c->status.qLink);
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init is called at beginning of first prime (read/write) call
|
|
||||||
static void RDInit(IOParamPtr p, DCtlPtr d, RDiskStorage_t *c) {
|
|
||||||
char unmountEN, mountEN, ramEN, dbgEN, cdrEN;
|
|
||||||
// Mark init done
|
|
||||||
c->initialized = 1;
|
|
||||||
// Decode settings
|
|
||||||
RDDecodeSettings(&unmountEN, &mountEN, &ramEN, &dbgEN, &cdrEN);
|
|
||||||
|
|
||||||
// If RAM disk enabled, try to allocate RAM disk buffer if not already
|
|
||||||
if (ramEN & !c->ramdisk) {
|
|
||||||
if (*MMU32bit) { // 32-bit mode
|
|
||||||
unsigned long minBufPtr, newBufPtr;
|
|
||||||
// Compute if there is enough high memory
|
|
||||||
minBufPtr = ((unsigned long)*MemTop / 2) + 1024;
|
|
||||||
newBufPtr = (unsigned long)*BufPtr - RDiskSize;
|
|
||||||
if (newBufPtr > minBufPtr && (unsigned long)*BufPtr > newBufPtr) {
|
|
||||||
// Allocate RAM disk buffer by lowering BufPtr
|
|
||||||
*BufPtr = (Ptr)newBufPtr;
|
|
||||||
// Set RAM disk buffer pointer.
|
|
||||||
c->ramdisk = *BufPtr;
|
|
||||||
// Copy ROM disk image to RAM disk
|
|
||||||
BlockMove(RDiskBuf, c->ramdisk, RDiskSize);
|
|
||||||
// Clearing write protect marks RAM disk enabled
|
|
||||||
c->status.writeProt = 0;
|
|
||||||
}
|
|
||||||
} else { // 24-bit mode
|
|
||||||
// Put RAM disk just past 8MB
|
|
||||||
c->ramdisk = (Ptr)(8 * 1024 * 1024);
|
|
||||||
// Copy ROM disk image to RAM disk
|
|
||||||
//FIXME: what if we don't have enough RAM?
|
|
||||||
// Will this wrap around and overwrite low memory?
|
|
||||||
// That's not the worst, since the system would just crash,
|
|
||||||
// but it would be better to switch to read-only status
|
|
||||||
copy24(RDiskBuf, c->ramdisk, RDiskSize);
|
|
||||||
// Clearing write protect marks RAM disk enabled
|
|
||||||
c->status.writeProt = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Patch
|
|
||||||
if (RDiskDBGDisPos < RDiskSize) {
|
|
||||||
if (c->ramdisk && !dbgEN) {
|
|
||||||
poke24(c->ramdisk + RDiskDBGDisPos, c->dbgDisByte);
|
|
||||||
} else if (dbgEN) {
|
|
||||||
peek24(RDiskBuf + RDiskDBGDisPos, c->dbgDisByte);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (RDiskCDRDisPos < RDiskSize) {
|
|
||||||
if (c->ramdisk && !cdrEN) {
|
|
||||||
poke24(c->ramdisk + RDiskCDRDisPos, c->cdrDisByte);
|
|
||||||
} else if (cdrEN) {
|
|
||||||
peek24(RDiskBuf + RDiskCDRDisPos, c->cdrDisByte);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmount if not booting from ROM disk
|
|
||||||
if (unmountEN) { c->status.diskInPlace = 0; }
|
|
||||||
|
|
||||||
// If mount enabled, enable accRun to post disk inserted event later
|
|
||||||
if (mountEN) {
|
|
||||||
d->dCtlDelay = 150; // Set accRun delay (150 ticks is 2.5 sec.)
|
|
||||||
d->dCtlFlags |= dNeedTimeMask; // Enable accRun
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma parameter __D0 RDPrime(__A0, __A1)
|
|
||||||
OSErr RDPrime(IOParamPtr p, DCtlPtr d) {
|
|
||||||
RDiskStorage_t *c;
|
|
||||||
char cmd;
|
|
||||||
Ptr disk;
|
|
||||||
|
|
||||||
// Return disk offline error if dCtlStorage null
|
|
||||||
if (!d->dCtlStorage) { return notOpenErr; }
|
|
||||||
// Dereference dCtlStorage to get pointer to our context
|
|
||||||
c = *(RDiskStorage_t**)d->dCtlStorage;
|
|
||||||
|
|
||||||
// Initialize if this is the first prime call
|
|
||||||
if (!c->initialized) { RDInit(p, d, c); }
|
|
||||||
|
|
||||||
// Return disk offline error if virtual disk not inserted
|
|
||||||
if (!c->status.diskInPlace) { return offLinErr; }
|
|
||||||
|
|
||||||
// Get pointer to RAM or ROM disk buffer
|
|
||||||
disk = (c->ramdisk ? c->ramdisk : RDiskBuf) + d->dCtlPosition;
|
|
||||||
// Bounds checking
|
|
||||||
if (d->dCtlPosition >= RDiskSize || p->ioReqCount >= RDiskSize ||
|
|
||||||
d->dCtlPosition + p->ioReqCount >= RDiskSize) { return paramErr; }
|
|
||||||
|
|
||||||
// Service read or write request
|
|
||||||
cmd = p->ioTrap & 0x00FF;
|
|
||||||
if (cmd == aRdCmd) { // Read
|
|
||||||
// Read from disk into buffer.
|
|
||||||
if (*MMU32bit) { BlockMove(disk, p->ioBuffer, p->ioReqCount); }
|
|
||||||
else { copy24(disk, StripAddress(p->ioBuffer), p->ioReqCount); }
|
|
||||||
if (!c->ramdisk && RDiskDBGDisPos >= d->dCtlPosition &&
|
|
||||||
RDiskDBGDisPos < d->dCtlPosition + p->ioReqCount) {
|
|
||||||
p->ioBuffer[RDiskDBGDisPos - d->dCtlPosition] = c->dbgDisByte;
|
|
||||||
}
|
|
||||||
if (!c->ramdisk && RDiskCDRDisPos >= d->dCtlPosition &&
|
|
||||||
RDiskCDRDisPos < d->dCtlPosition + p->ioReqCount) {
|
|
||||||
p->ioBuffer[RDiskCDRDisPos - d->dCtlPosition] = c->cdrDisByte;
|
|
||||||
}
|
|
||||||
} else if (cmd == aWrCmd) { // Write
|
|
||||||
// Fail if write protected or RAM disk buffer not set up
|
|
||||||
if (c->status.writeProt || !c->ramdisk) { return wPrErr; }
|
|
||||||
// Write from buffer into disk.
|
|
||||||
if (*MMU32bit) { BlockMove(p->ioBuffer, disk, p->ioReqCount); }
|
|
||||||
else { copy24(StripAddress(p->ioBuffer), disk, p->ioReqCount); }
|
|
||||||
} else { return noErr; } //FIXME: Fail if cmd isn't read or write?
|
|
||||||
|
|
||||||
// Update count and position/offset, then return
|
|
||||||
d->dCtlPosition += p->ioReqCount;
|
|
||||||
p->ioActCount = p->ioReqCount;
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma parameter __D0 RDCtl(__A0, __A1)
|
|
||||||
OSErr RDCtl(CntrlParamPtr p, DCtlPtr d) {
|
|
||||||
RDiskStorage_t *c;
|
|
||||||
// Fail if dCtlStorage null
|
|
||||||
if (!d->dCtlStorage) { return notOpenErr; }
|
|
||||||
// Dereference dCtlStorage to get pointer to our context
|
|
||||||
c = *(RDiskStorage_t**)d->dCtlStorage;
|
|
||||||
// Handle control request based on csCode
|
|
||||||
switch (p->csCode) {
|
|
||||||
case killCode:
|
|
||||||
return noErr;
|
|
||||||
case kFormat:
|
|
||||||
if (!c->status.diskInPlace || c->status.writeProt ||
|
|
||||||
!c->ramdisk) { return controlErr; }
|
|
||||||
long long z = 0;
|
|
||||||
Ptr pz;
|
|
||||||
if (*MMU32bit) { pz = (Ptr)&z; }
|
|
||||||
else { pz = StripAddress((Ptr)&z); }
|
|
||||||
for (int i = 0; i < 4095; i++) {
|
|
||||||
copy24(c->ramdisk + i * sizeof(z), pz, sizeof(z));
|
|
||||||
}
|
|
||||||
return noErr;
|
|
||||||
case kVerify:
|
|
||||||
if (!c->status.diskInPlace) { return controlErr; }
|
|
||||||
return noErr;
|
|
||||||
case kEject:
|
|
||||||
// "Reinsert" disk if ejected illegally
|
|
||||||
if (c->status.diskInPlace) {
|
|
||||||
PostEvent(diskEvt, c->status.dQDrive);
|
|
||||||
}
|
|
||||||
return controlErr; // Eject not allowed so return error
|
|
||||||
case accRun:
|
|
||||||
d->dCtlFlags &= ~dNeedTimeMask; // Disable accRun
|
|
||||||
c->status.diskInPlace = 8; // 8 is nonejectable disk
|
|
||||||
PostEvent(diskEvt, c->status.dQDrive); // Post disk inserted event
|
|
||||||
return noErr;
|
|
||||||
case kDriveIcon: case kMediaIcon: // Get icon
|
|
||||||
#ifdef RDISK_COMPRESS_ICON_ENABLE
|
|
||||||
*(Ptr*)p->csParam = (Ptr)c->icon;
|
|
||||||
#else
|
|
||||||
*(Ptr*)p->csParam = (Ptr)RDiskIcon;
|
|
||||||
#endif
|
|
||||||
return noErr;
|
|
||||||
case kDriveInfo:
|
|
||||||
// high word (bytes 2 & 3) clear
|
|
||||||
// byte 1 = primary + fixed media + internal
|
|
||||||
// byte 0 = drive type (0x10 is RAM disk) / (0x11 is ROM disk)
|
|
||||||
if (c->status.writeProt) { *(long*)p->csParam = 0x00000411; }
|
|
||||||
else { *(long*)p->csParam = 0x00000410; }
|
|
||||||
return noErr;
|
|
||||||
case 24: // Return SCSI partition size
|
|
||||||
*(long*)p->csParam = RDiskSize / 512;
|
|
||||||
return noErr;
|
|
||||||
case 2351: // Post-boot
|
|
||||||
c->initialized = 1; // Skip initialization
|
|
||||||
d->dCtlDelay = 30; // Set accRun delay (30 ticks is 0.5 sec.)
|
|
||||||
d->dCtlFlags |= dNeedTimeMask; // Enable accRun
|
|
||||||
return noErr;
|
|
||||||
default: return controlErr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma parameter __D0 RDStat(__A0, __A1)
|
|
||||||
OSErr RDStat(CntrlParamPtr p, DCtlPtr d) {
|
|
||||||
//RDiskStorage_t *c;
|
|
||||||
// Fail if dCtlStorage null
|
|
||||||
if (!d->dCtlStorage) { return notOpenErr; }
|
|
||||||
// Dereference dCtlStorage to get pointer to our context
|
|
||||||
//c = *(RDiskStorage_t**)d->dCtlStorage;
|
|
||||||
// Handle status request based on csCode
|
|
||||||
switch (p->csCode) {
|
|
||||||
case kDriveStatus:
|
|
||||||
BlockMove(*d->dCtlStorage, &p->csParam, sizeof(DrvSts2));
|
|
||||||
return noErr;
|
|
||||||
default: return statusErr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma parameter __D0 RDClose(__A0, __A1)
|
|
||||||
OSErr RDClose(IOParamPtr p, DCtlPtr d) {
|
|
||||||
// If dCtlStorage not null, dispose of it
|
|
||||||
if (!d->dCtlStorage) { return noErr; }
|
|
||||||
//RDiskStorage_t *c = *(RDiskStorage_t**)d->dCtlStorage;
|
|
||||||
HUnlock(d->dCtlStorage);
|
|
||||||
DisposeHandle(d->dCtlStorage);
|
|
||||||
d->dCtlStorage = NULL;
|
|
||||||
return noErr;
|
|
||||||
}
|
|
|
@ -0,0 +1,252 @@
|
||||||
|
#include <Memory.h>
|
||||||
|
#include <Devices.h>
|
||||||
|
#include <Files.h>
|
||||||
|
#include <Disks.h>
|
||||||
|
#include <Errors.h>
|
||||||
|
#include <Events.h>
|
||||||
|
#include <OSUtils.h>
|
||||||
|
|
||||||
|
#include "rombus.h"
|
||||||
|
#include "spi.h"
|
||||||
|
#include "priv_syscall.h"
|
||||||
|
|
||||||
|
// Decode keyboard settings
|
||||||
|
static void RBDecodeKeySettings(RBStorage_t *c) {
|
||||||
|
// Sample R, S, X keys repeatedly
|
||||||
|
char r = 0, s = 0, x = 0;
|
||||||
|
long tmax = TickCount() + 60;
|
||||||
|
for (long i = 0; i < 1000000; i++) {
|
||||||
|
r |= IsRPressed();
|
||||||
|
s |= IsSPressed();
|
||||||
|
x |= IsXPressed();
|
||||||
|
if (r || s || x) { break; }
|
||||||
|
if (TickCount() > tmax) { break; }
|
||||||
|
}
|
||||||
|
// Decode settings
|
||||||
|
if (x) { // Unmount everything
|
||||||
|
c->unmountROMEN = 1;
|
||||||
|
c->unmountSDEN = 1;
|
||||||
|
c->mountROMEN = 0;
|
||||||
|
c->mountSDEN = 0;
|
||||||
|
} else if (s) { // Boot from SD, don't mount ROM
|
||||||
|
c->unmountROMEN = 1;
|
||||||
|
c->unmountSDEN = 0;
|
||||||
|
c->mountROMEN = 1;
|
||||||
|
c->mountSDEN = 0;
|
||||||
|
} else if (r) { // Boot from ROM, mount SD
|
||||||
|
c->unmountROMEN = 0;
|
||||||
|
c->unmountSDEN = 1;
|
||||||
|
c->mountROMEN = 0;
|
||||||
|
c->mountSDEN = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode PRAM settings
|
||||||
|
static OSErr RBDecodePRAMSettings(RBStorage_t *c) {
|
||||||
|
// Read PRAM
|
||||||
|
char legacy_startup, legacy_ram;
|
||||||
|
PSReadXPRAM(1, 4, &legacy_startup);
|
||||||
|
PSReadXPRAM(1, 5, &legacy_ram);
|
||||||
|
|
||||||
|
// Decoded settings
|
||||||
|
const char opt_disable = legacy_startup & (1<<7);
|
||||||
|
const char opt_boot_sd = legacy_startup & (1<<2);
|
||||||
|
const char opt_boot_rom = legacy_startup & (1<<0);
|
||||||
|
const char opt_mount_sd = legacy_startup & (1<<3);
|
||||||
|
const char opt_mount_rom = legacy_startup & (1<<4);
|
||||||
|
|
||||||
|
// Old settings for ROM SIMM (not used here)
|
||||||
|
//const char opt_old_mount_rom = !(legacy_startup & (1<<1));
|
||||||
|
//const char opt_old_ram = legacy_ram & (1<<0);
|
||||||
|
|
||||||
|
// Set based on decoded settings
|
||||||
|
if (opt_disable) { return -1; }
|
||||||
|
else {
|
||||||
|
c->unmountROMEN = !opt_boot_rom;
|
||||||
|
c->unmountSDEN = !opt_boot_sd;
|
||||||
|
c->mountROMEN = opt_mount_rom && !opt_boot_rom;
|
||||||
|
c->mountSDEN = opt_mount_sd && !opt_boot_sd;
|
||||||
|
}
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch to 32-bit mode and copy
|
||||||
|
#pragma parameter C24(__A0, __A1, __D0)
|
||||||
|
void __attribute__ ((noinline)) C24(Ptr sourcePtr, Ptr destPtr, unsigned long byteCount) {
|
||||||
|
signed char mode = true32b;
|
||||||
|
SwapMMUMode(&mode);
|
||||||
|
BlockMove(sourcePtr, destPtr, byteCount);
|
||||||
|
SwapMMUMode(&mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma parameter __D0 RBClose(__A0, __A1)
|
||||||
|
OSErr RBClose(IOParamPtr p, DCtlPtr d) {
|
||||||
|
// If dCtlStorage not null, dispose of it
|
||||||
|
if (!d->dCtlStorage) { return noErr; }
|
||||||
|
HUnlock(d->dCtlStorage);
|
||||||
|
DisposeHandle(d->dCtlStorage);
|
||||||
|
d->dCtlStorage = NULL;
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma parameter __D0 RBOpen(__A0, __A1)
|
||||||
|
OSErr RBOpen(IOParamPtr p, DCtlPtr d) {
|
||||||
|
int drvNum;
|
||||||
|
RBStorage_t *c;
|
||||||
|
|
||||||
|
// Do nothing if already opened
|
||||||
|
if (d->dCtlStorage) { return noErr; }
|
||||||
|
|
||||||
|
// Allocate storage struct
|
||||||
|
d->dCtlStorage = NewHandleSysClear(sizeof(RBStorage_t));
|
||||||
|
if (!d->dCtlStorage) { return openErr; }
|
||||||
|
|
||||||
|
// Lock our storage struct and get master pointer
|
||||||
|
HLock(d->dCtlStorage);
|
||||||
|
c = *(RBStorage_t**)d->dCtlStorage;
|
||||||
|
|
||||||
|
// Do nothing if inhibited
|
||||||
|
if (RBDecodePRAMSettings(c) != noErr) {
|
||||||
|
RBClose(p, d);
|
||||||
|
return openErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iff mount enabled, enable accRun to post disk inserted event later
|
||||||
|
if (c->mountROMEN || c->mountSDEN) { d->dCtlFlags |= dNeedTimeMask; }
|
||||||
|
else { d->dCtlFlags &= ~dNeedTimeMask; }
|
||||||
|
|
||||||
|
// Set accRun delay
|
||||||
|
d->dCtlDelay = 150; // (150 ticks is 2.5 sec.)
|
||||||
|
|
||||||
|
// Find first available drive number
|
||||||
|
drvNum = PSFindDrvNum();
|
||||||
|
|
||||||
|
//TODO: set c->sdSize
|
||||||
|
|
||||||
|
// Set drive status
|
||||||
|
c->sdStatus.track = 0;
|
||||||
|
c->sdStatus.writeProt = 0; // nonzero is write protected
|
||||||
|
c->sdStatus.diskInPlace = 8; // 8 is nonejectable disk
|
||||||
|
c->sdStatus.installed = 1; // drive installed
|
||||||
|
c->sdStatus.sides = 0;
|
||||||
|
c->sdStatus.qType = 1;
|
||||||
|
c->sdStatus.dQDrive = drvNum;
|
||||||
|
c->sdStatus.dQFSID = 0;
|
||||||
|
c->sdStatus.dQRefNum = d->dCtlRefNum;
|
||||||
|
c->sdStatus.driveSize = c->sdSize / 512;
|
||||||
|
c->sdStatus.driveS1 = (c->sdSize / 512) >> 16;
|
||||||
|
|
||||||
|
// Decompress icon
|
||||||
|
#ifdef RB_COMPRESS_ICON_ENABLE
|
||||||
|
char *src = &SDIconCompressed[0];
|
||||||
|
char *dst = &c->sd[0];
|
||||||
|
UnpackBits(&src, &dst, RB_ICON_SIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Add drive to drive queue and return
|
||||||
|
PSAddDrive(c->sdStatus.dQRefNum, drvNum, (DrvQElPtr)&c->sdStatus.qLink);
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init is called at beginning of first prime (read/write) call
|
||||||
|
static void RBBootInit(IOParamPtr p, DCtlPtr d, RBStorage_t *c) {
|
||||||
|
// Mark init done
|
||||||
|
c->initialized = 1;
|
||||||
|
|
||||||
|
// Decode key settings
|
||||||
|
RBDecodeKeySettings(c);
|
||||||
|
|
||||||
|
// Unmount if not booting from ROM disk
|
||||||
|
if (c->unmountSDEN) { c->sdStatus.diskInPlace = 0; }
|
||||||
|
|
||||||
|
// Iff mount disabled, disable accRun
|
||||||
|
if (!c->mountSDEN || !c->mountROMEN) { d->dCtlFlags &= ~dNeedTimeMask; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma parameter __D0 RBPrime(__A0, __A1)
|
||||||
|
OSErr RBPrime(IOParamPtr p, DCtlPtr d) {
|
||||||
|
RBStorage_t *c;
|
||||||
|
|
||||||
|
// Return disk offline error if dCtlStorage null
|
||||||
|
if (!d->dCtlStorage) { return notOpenErr; }
|
||||||
|
// Dereference dCtlStorage to get pointer to our context
|
||||||
|
c = *(RBStorage_t**)d->dCtlStorage;
|
||||||
|
|
||||||
|
// Initialize if this is the first prime call
|
||||||
|
if (!c->initialized) { RBBootInit(p, d, c); }
|
||||||
|
|
||||||
|
// Return disk offline error if virtual disk not inserted
|
||||||
|
if (!c->sdStatus.diskInPlace) { return offLinErr; }
|
||||||
|
|
||||||
|
//TODO: Read/write
|
||||||
|
|
||||||
|
// Update count and position/offset, then return
|
||||||
|
d->dCtlPosition += p->ioReqCount;
|
||||||
|
p->ioActCount = p->ioReqCount;
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma parameter __D0 RBCtl(__A0, __A1)
|
||||||
|
OSErr RBCtl(CntrlParamPtr p, DCtlPtr d) {
|
||||||
|
RBStorage_t *c;
|
||||||
|
// Fail if dCtlStorage null
|
||||||
|
if (!d->dCtlStorage) { return notOpenErr; }
|
||||||
|
// Dereference dCtlStorage to get pointer to our context
|
||||||
|
c = *(RBStorage_t**)d->dCtlStorage;
|
||||||
|
// Handle control request based on csCode
|
||||||
|
switch (p->csCode) {
|
||||||
|
case kFormat:
|
||||||
|
if (!c->sdStatus.diskInPlace || c->sdStatus.writeProt) {
|
||||||
|
return controlErr;
|
||||||
|
}
|
||||||
|
//TODO: Format
|
||||||
|
return noErr;
|
||||||
|
case kVerify:
|
||||||
|
if (!c->sdStatus.diskInPlace) { return controlErr; }
|
||||||
|
return noErr;
|
||||||
|
case accRun:
|
||||||
|
c->initialized = 1; // Mark init done
|
||||||
|
c->sdStatus.diskInPlace = 8; // 8 is nonejectable disk
|
||||||
|
PostEvent(diskEvt, c->sdStatus.dQDrive); // Post disk inserted event
|
||||||
|
d->dCtlFlags &= ~dNeedTimeMask; // Disable accRun
|
||||||
|
return noErr;
|
||||||
|
case kDriveIcon: case kMediaIcon: // Get icon
|
||||||
|
#ifdef RB_COMPRESS_ICON_ENABLE
|
||||||
|
*(Ptr*)p->csParam = (Ptr)c->sd;
|
||||||
|
#else
|
||||||
|
*(Ptr*)p->csParam = (Ptr)RDiskIcon;
|
||||||
|
#endif
|
||||||
|
return noErr;
|
||||||
|
case kDriveInfo:
|
||||||
|
// high word (bytes 2 & 3) clear
|
||||||
|
// byte 1 = primary + fixed media + internal
|
||||||
|
// byte 0 = drive type (0x10 is RAM disk) / (0x11 is ROM disk)
|
||||||
|
if (c->sdStatus.writeProt) { *(long*)p->csParam = 0x00000400; }
|
||||||
|
else { *(long*)p->csParam = 0x00000400; }
|
||||||
|
return noErr;
|
||||||
|
case 24: // Return SCSI partition size
|
||||||
|
*(long*)p->csParam = c->sdSize / 512;
|
||||||
|
return noErr;
|
||||||
|
case killCode: return noErr;
|
||||||
|
case kEject:
|
||||||
|
// "Reinsert" disk if ejected illegally
|
||||||
|
if (c->sdStatus.diskInPlace) {
|
||||||
|
PostEvent(diskEvt, c->sdStatus.dQDrive);
|
||||||
|
}
|
||||||
|
return controlErr; // Eject not allowed so return error
|
||||||
|
default: return controlErr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma parameter __D0 RBStat(__A0, __A1)
|
||||||
|
OSErr RBStat(CntrlParamPtr p, DCtlPtr d) {
|
||||||
|
// Fail if dCtlStorage null
|
||||||
|
if (!d->dCtlStorage) { return notOpenErr; }
|
||||||
|
// Handle status request based on csCode
|
||||||
|
switch (p->csCode) {
|
||||||
|
case kDriveStatus:
|
||||||
|
BlockMove(*d->dCtlStorage, &p->csParam, sizeof(DrvSts2));
|
||||||
|
return noErr;
|
||||||
|
default: return statusErr;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,7 @@
|
||||||
#ifndef RDISK_H
|
#ifndef _RDISK_H
|
||||||
#define RDISK_H
|
#define _RDISK_H
|
||||||
|
|
||||||
#define RDiskBuf ((char*)0x40880000)
|
#define RDiskBuf ((char*)0x40880000)
|
||||||
#define BufPtr ((Ptr*)0x10C)
|
|
||||||
#define MemTop ((Ptr*)0x108)
|
|
||||||
#define MMU32bit ((char*)0xCB2)
|
#define MMU32bit ((char*)0xCB2)
|
||||||
|
|
||||||
#define RDiskDBGDisPos (*(const unsigned long*)0x40851D98)
|
#define RDiskDBGDisPos (*(const unsigned long*)0x40851D98)
|
||||||
|
@ -12,42 +10,39 @@
|
||||||
#define RDiskCDRDisByte (*(const char*)0x40851DA9)
|
#define RDiskCDRDisByte (*(const char*)0x40851DA9)
|
||||||
#define RDiskSize (*(const unsigned long*)0x40851DAC)
|
#define RDiskSize (*(const unsigned long*)0x40851DAC)
|
||||||
|
|
||||||
#define RDISK_COMPRESS_ICON_ENABLE
|
#define RB_COMPRESS_ICON_ENABLE
|
||||||
|
|
||||||
#pragma parameter __D0 RDiskReadXPRAM(__D0, __D1, __A0)
|
static inline char IsRPressed() { return *((volatile char*)0x175) & 0x80; }
|
||||||
OSErr RDiskReadXPRAM(short numBytes, short whichByte, Ptr dest) = {0x4840, 0x3001, 0xA051};
|
static inline char IsSPressed() { return *((volatile char*)0x174) & 0x02; }
|
||||||
|
static inline char IsXPressed() { return *((volatile char*)0x174) & 0x80; }
|
||||||
|
|
||||||
#pragma parameter __D0 RDiskAddDrive(__D1, __D0, __A0)
|
#define RB_ICON_SIZE (285)
|
||||||
OSErr RDiskAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq) = {0x4840, 0x3001, 0xA04E};
|
|
||||||
|
|
||||||
static inline char RDiskIsRPressed() { return *((volatile char*)0x175) & 0x80; }
|
|
||||||
static inline char RDiskIsAPressed() { return *((volatile char*)0x174) & 0x01; }
|
|
||||||
|
|
||||||
#define RDISK_ICON_SIZE (285)
|
|
||||||
typedef struct RDiskStorage_s {
|
typedef struct RDiskStorage_s {
|
||||||
DrvSts2 status;
|
DrvSts2 sdStatus;
|
||||||
|
long long sdSize;
|
||||||
|
|
||||||
char initialized;
|
char initialized;
|
||||||
#ifdef RDISK_COMPRESS_ICON_ENABLE
|
|
||||||
char icon[RDISK_ICON_SIZE+8];
|
char unmountSDEN;
|
||||||
|
char mountSDEN;
|
||||||
|
char unmountROMEN;
|
||||||
|
char mountROMEN;
|
||||||
|
|
||||||
|
#ifdef RB_COMPRESS_ICON_ENABLE
|
||||||
|
char sd[RB_ICON_SIZE+8];
|
||||||
#endif
|
#endif
|
||||||
} RDiskStorage_t;
|
} RBStorage_t;
|
||||||
|
|
||||||
typedef void (*RDiskCopy_t)(Ptr, Ptr, unsigned long);
|
typedef void (*RDiskCopy_t)(Ptr, Ptr, unsigned long);
|
||||||
#define copy24(s, d, b) { RDiskCopy_t f = C24; f(s, d, b); }
|
#define copy24(s, d, b) { RDiskCopy_t f = C24; f(s, d, b); }
|
||||||
|
|
||||||
typedef char (*RDiskPeek_t)(Ptr);
|
|
||||||
#define peek24(a, d) { RDiskPeek_t f = G24; d = f(a); }
|
|
||||||
|
|
||||||
typedef void (*RDiskPoke_t)(Ptr, char);
|
|
||||||
#define poke24(a, d) { RDiskPoke_t f = S24; f(a, d); }
|
|
||||||
|
|
||||||
#define PackBits_Repeat(count) (-1 * (count - 1))
|
#define PackBits_Repeat(count) (-1 * (count - 1))
|
||||||
#define PackBits_Literal(count) (count - 1)
|
#define PackBits_Literal(count) (count - 1)
|
||||||
|
|
||||||
#define RDISK_COMPRESSED_ICON_SIZE (87)
|
#define RDISK_COMPRESSED_ICON_SIZE (87)
|
||||||
#ifdef RDISK_COMPRESS_ICON_ENABLE
|
#ifdef RB_COMPRESS_ICON_ENABLE
|
||||||
#include <Quickdraw.h>
|
#include <Quickdraw.h>
|
||||||
const char RDiskIconCompressed[RDISK_COMPRESSED_ICON_SIZE] = {
|
const char SDIconCompressed[RDISK_COMPRESSED_ICON_SIZE] = {
|
||||||
PackBits_Repeat(76), 0b00000000, /*
|
PackBits_Repeat(76), 0b00000000, /*
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
||||||
|
@ -130,7 +125,7 @@ const char RDiskIconCompressed[RDISK_COMPRESSED_ICON_SIZE] = {
|
||||||
'R', 'O', 'M', ' ', 'D', 'i', 's', 'k', 0
|
'R', 'O', 'M', ' ', 'D', 'i', 's', 'k', 0
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
const char RDiskIcon[RDISK_ICON_SIZE] = {
|
const char RDiskIcon[RB_ICON_SIZE] = {
|
||||||
// Icon
|
// Icon
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
BIN
roms/baserom.bin
BIN
roms/baserom.bin
Binary file not shown.
|
@ -0,0 +1,129 @@
|
||||||
|
#include "spi.h"
|
||||||
|
#include "spi_hal.h"
|
||||||
|
|
||||||
|
static int _search_lt(char *buf, int stride, int threshold) {
|
||||||
|
for (int i = 1; i < 256; i++) {
|
||||||
|
if (buf[i * stride] < threshold) { return 1; }
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _spi_hal_rx8_nops, _spi_hal_tx8_nops;
|
||||||
|
int _spi_hal_rx16_nops, _spi_hal_tx16_nops;
|
||||||
|
int _spi_hal_rxtx8_nops;
|
||||||
|
|
||||||
|
short *_spi_reg_rx16;
|
||||||
|
char *_spi_reg_tx16;
|
||||||
|
short *_spi_reg_rd16;
|
||||||
|
|
||||||
|
int spi_init(int swap) {
|
||||||
|
short buf16[256];
|
||||||
|
char *buf8 = (char*)&buf16;
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
spi_hal_rx8(SPI_REG_TIMER8, buf8, 256, i);
|
||||||
|
_spi_hal_rx8_nops = i;
|
||||||
|
_spi_hal_tx8_nops = i > 0 ? i - 1 : 0;
|
||||||
|
if (!_search_lt(buf8, 1, 8)) { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
spi_hal_rx16(SPI_REG_TIMER16, buf16, 256, i);
|
||||||
|
_spi_hal_rx16_nops = i;
|
||||||
|
_spi_hal_tx16_nops = i > 0 ? i - 1 : 0;
|
||||||
|
if (!_search_lt(buf8, 2, 8)) { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
spi_hal_rxtx8(SPI_REG_EMPTY, SPI_REG_TIMER16, buf8, buf8, 256, i);
|
||||||
|
_spi_hal_rxtx8_nops = i;
|
||||||
|
if (!_search_lt(buf8, 1, 8)) { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
_spi_reg_rx16 = swap ? SPI_REG_RX16S : SPI_REG_RX16;
|
||||||
|
_spi_reg_tx16 = swap ? SPI_REG_TX16S : SPI_REG_TX16;
|
||||||
|
_spi_reg_rd16 = swap ? SPI_REG_RD16S : SPI_REG_RD16;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_cs(int cs) {
|
||||||
|
if (cs) { SPI_REG_CSR_SET_CS(); }
|
||||||
|
else { SPI_REG_CSR_CLR_CS(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
char spi_txrx8_slow(char txd) {
|
||||||
|
char rxd = 0;
|
||||||
|
for (int i = 7; i >= 0; i--) {
|
||||||
|
spi_delay(64);
|
||||||
|
SPI_REG_CSR_CLR_SCK();
|
||||||
|
spi_delay(64);
|
||||||
|
SPI_REG_SET_MOSI((txd >> i) & 1);
|
||||||
|
rxd = (rxd << 1) | SPI_REG_CSR_GET_MISO();
|
||||||
|
SPI_REG_CSR_SET_SCK();
|
||||||
|
}
|
||||||
|
spi_delay(64);
|
||||||
|
SPI_REG_CSR_CLR_SCK();
|
||||||
|
return rxd;
|
||||||
|
}
|
||||||
|
|
||||||
|
char spi_txrx8(char txd) {
|
||||||
|
spi_hal_tx8(SPI_REG_TX8, &txd, 1, _spi_hal_tx8_nops);
|
||||||
|
return *SPI_REG_RD8;
|
||||||
|
}
|
||||||
|
|
||||||
|
char spi_rxtx8(char txd) {
|
||||||
|
char rxd = *SPI_REG_RD8;
|
||||||
|
spi_hal_tx8(SPI_REG_TX8, &txd, 1, _spi_hal_tx8_nops);
|
||||||
|
return rxd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UNROLL_LENGTH 5
|
||||||
|
|
||||||
|
void spi_rx(char txd, char *rxb, unsigned int length) {
|
||||||
|
if (length == 0) { return; } // Return if length 0
|
||||||
|
|
||||||
|
// Word-align rx pointer by transferring 0/1 bytes
|
||||||
|
if ((int)rxb & 1) {
|
||||||
|
*(rxb++) = spi_rxtx8(txd);
|
||||||
|
length--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set tx pattern
|
||||||
|
reg_write16(SPI_REG_ST16, smear8to32(txd));
|
||||||
|
|
||||||
|
// Transfer all but 0-65 bytes
|
||||||
|
for (int i = length >> (UNROLL_LENGTH +1); i > 0; i--) {
|
||||||
|
// Transfer 2^UNROLL_LENGTH words (2 * 2^UNROLL_LENGTH bytes)
|
||||||
|
spi_hal_rx16(_spi_reg_rx16, rxb, UNROLL_LENGTH, _spi_hal_rx16_nops);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer remaining 1-32 words (2-64 bytes)
|
||||||
|
spi_hal_rx16(_spi_reg_rx16, rxb, length >> 1, _spi_hal_rx16_nops);
|
||||||
|
|
||||||
|
// Transfer remaining byte if any
|
||||||
|
if (length & 1) { *(rxb++) = spi_rxtx8(txd); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_tx(char *txb, unsigned int length) {
|
||||||
|
if (length == 0) { return; } // Return if length 0
|
||||||
|
|
||||||
|
// Word-align tx pointer by transferring 0/1 bytes
|
||||||
|
if ((int)txb & 1) {
|
||||||
|
spi_rxtx8(*(txb++));
|
||||||
|
length--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer all but 0-65 bytes
|
||||||
|
for (; length > UNROLL_LENGTH; length -= UNROLL_LENGTH) {
|
||||||
|
spi_hal_tx16(_spi_reg_tx16, txb, UNROLL_LENGTH, _spi_hal_tx16_nops);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer remaining 1-32 words (2-64 bytes)
|
||||||
|
spi_hal_tx16(_spi_reg_tx16, txb, length >> 1, _spi_hal_tx16_nops);
|
||||||
|
|
||||||
|
// Transfer remaining byte if any
|
||||||
|
if (length & 1) { spi_rxtx8(*(txb++)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
char spi_rd8() { return *SPI_REG_RD8; }
|
||||||
|
short spi_rd16() { return *_spi_reg_rd16; }
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef _SPI_H
|
||||||
|
#define _SPI_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
int spi_init();
|
||||||
|
|
||||||
|
void spi_cs(int cs);
|
||||||
|
|
||||||
|
char spi_txrx8_slow(char txd);
|
||||||
|
char spi_txrx8(char txd);
|
||||||
|
char spi_rxtx8(char txd);
|
||||||
|
|
||||||
|
void spi_tx(char *txb, unsigned int length);
|
||||||
|
void spi_rx(char txd, char *rxb, unsigned int length);
|
||||||
|
|
||||||
|
char spi_rd8();
|
||||||
|
short spi_rd16();
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,79 @@
|
||||||
|
#ifndef _SPI_HAL_H
|
||||||
|
#define _SPI_HAL_H
|
||||||
|
|
||||||
|
#pragma parameter spi_delay(__D0)
|
||||||
|
extern void spi_delay(char iterations);
|
||||||
|
|
||||||
|
#pragma parameter _reg_write8(__A0, __D0, __D1)
|
||||||
|
extern void _reg_write8(void *addr, char data, int tmp);
|
||||||
|
static inline void reg_write8(void *addr, char data) { _reg_write8(addr, data, 0); }
|
||||||
|
|
||||||
|
#pragma parameter _reg_write16(__A0, __D0, __D1)
|
||||||
|
extern void _reg_write16(void *addr, short data, int tmp);
|
||||||
|
static inline void reg_write16(void *addr, short data) { _reg_write16(addr, data, 0); }
|
||||||
|
|
||||||
|
#pragma parameter __D0 smear8to32(__D0)
|
||||||
|
extern long smear8to32(char data);
|
||||||
|
|
||||||
|
// Read transfer registers
|
||||||
|
#define SPI_REG_RX8 ((char*) 0x00000000) // A[01:00]==2'b00, D[31:24]==ret
|
||||||
|
#define SPI_REG_RX16 ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
|
||||||
|
#define SPI_REG_RX16S ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
|
||||||
|
#define SPI_REG_RD8 ((char*) 0x00000000) // A[01:00]==2'b00, D[31:24]==ret
|
||||||
|
#define SPI_REG_RD16 ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
|
||||||
|
#define SPI_REG_RD16S ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
|
||||||
|
#define SPI_REG_TIMER8 ((char*) 0x00000000) // A[01:00]==2'b00, D[31:24]==ret
|
||||||
|
#define SPI_REG_TIMER16 ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
|
||||||
|
// Write transfer registers
|
||||||
|
#define SPI_REG_TX8 ((char*) 0x00000000) // A[07:00]==arg
|
||||||
|
#define SPI_REG_TX16 ((char*) 0x00000000) // A[15:00]==arg
|
||||||
|
#define SPI_REG_TX16S ((char*) 0x00000000) // A[05:00]==arg
|
||||||
|
#define SPI_REG_ST16 ((char*) 0x00000000) // A[15:00]==arg
|
||||||
|
#define SPI_REG_EMPTY ((char*) 0x00000000)
|
||||||
|
// Control/status register (read/write)
|
||||||
|
#define SPI_REG_RD_CSR ((char*) 0x00000000)
|
||||||
|
#define SPI_REG_WR_CSR ((char*) 0x00000000)
|
||||||
|
#define SPI_REG_CSR_BIT_nDET (0)
|
||||||
|
#define SPI_REG_CSR_GET_nDET() ((*SPI_REG_RD_CSR>>SPI_REG_CSR_BIT_nDET) & 1)
|
||||||
|
#define SPI_REG_CSR_BIT_MISO (1)
|
||||||
|
#define SPI_REG_CSR_GET_MISO() ((*SPI_REG_RD_CSR>>SPI_REG_CSR_BIT_MISO) & 1)
|
||||||
|
#define SPI_REG_CSR_BIT_SCK (2)
|
||||||
|
#define SPI_REG_CSR_SET_SCK() reg_write16(SPI_REG_WR_CSR, *SPI_REG_RD_CSR | (1<<SPI_REG_CSR_BIT_SCK))
|
||||||
|
#define SPI_REG_CSR_CLR_SCK() reg_write16(SPI_REG_WR_CSR, *SPI_REG_RD_CSR & ~(1<<SPI_REG_CSR_BIT_SCK))
|
||||||
|
#define SPI_REG_CSR_BIT_CS (3)
|
||||||
|
#define SPI_REG_CSR_SET_CS() reg_write16(SPI_REG_WR_CSR, *SPI_REG_RD_CSR | (1<<SPI_REG_CSR_BIT_CS))
|
||||||
|
#define SPI_REG_CSR_CLR_CS() reg_write16(SPI_REG_WR_CSR, *SPI_REG_RD_CSR & ~(1<<SPI_REG_CSR_BIT_CS))
|
||||||
|
|
||||||
|
#define SPI_REG_SET_MOSI(x) reg_write16(SPI_REG_ST16, x ? 0xFFFF : 0x0000)
|
||||||
|
|
||||||
|
#pragma parameter _spi_hal_rx8(__A0, __A2, __A4, __D0, __D1, __D2)
|
||||||
|
extern void _spi_hal_rx8(void *reg, void *rx, void *tmp, int length, int nops, int tmp2);
|
||||||
|
static inline void spi_hal_rx8(void *reg, void *rx, int length, int nops) {
|
||||||
|
_spi_hal_rx8(reg, rx, 0, length, nops, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma parameter _spi_hal_rx16(__A0, __A2, __A4, __D0, __D1, __D2)
|
||||||
|
extern void _spi_hal_rx16(void *reg, void *rx, void *tmp, int length, int nops, int tmp2);
|
||||||
|
static inline void spi_hal_rx16(void *reg, void *rx, int length, int nops) {
|
||||||
|
_spi_hal_rx16(reg, rx, 0, length, nops, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma parameter _spi_hal_tx8(__A0, __A3, __A4, __D0, __D1, __D2)
|
||||||
|
extern void _spi_hal_tx8(void *reg, void *tx, void *tmp, int length, int nops, int tmp2);
|
||||||
|
static inline void spi_hal_tx8(void *reg, void *tx, int length, int nops) {
|
||||||
|
_spi_hal_tx8(reg, tx, 0, length, nops, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma parameter _spi_hal_tx16(__A0, __A3, __A4, __D0, __D1, __D2)
|
||||||
|
extern void _spi_hal_tx16(void *reg, void *tx, void *tmp, int length, int nops, int tmp2);
|
||||||
|
static inline void spi_hal_tx16(void *reg, void *tx, int length, int nops) {
|
||||||
|
_spi_hal_tx16(reg, tx, 0, length, nops, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma parameter _spi_hal_rxtx8(__A0, __A1, __A2, __A3, __A4, __D0, __D1, __D2)
|
||||||
|
extern void _spi_hal_rxtx8(void *reg, void *read, void *rx, void *tx, void *tmp, int length, int nops, int tmp2);
|
||||||
|
static inline void spi_hal_rxtx8(void *reg, void *read, void *rx, void *tx, int length, int nops) {
|
||||||
|
_spi_hal_rxtx8(reg, read, rx, tx, 0, length, nops, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,49 @@
|
||||||
|
.global spi_delay
|
||||||
|
.global _reg_write16
|
||||||
|
.global _reg_write8
|
||||||
|
.global smear8to32
|
||||||
|
|
||||||
|
* delay calling convention
|
||||||
|
* D0 - iterations
|
||||||
|
|
||||||
|
spi_delay:
|
||||||
|
subq.w #1, %D0
|
||||||
|
bne.b spi_delay
|
||||||
|
rts
|
||||||
|
|
||||||
|
* reg_write calling convention
|
||||||
|
* A0 - address
|
||||||
|
* D0 - data (clobbered)
|
||||||
|
* D1 - clobbered
|
||||||
|
|
||||||
|
_reg_write8:
|
||||||
|
move.l %A0, %D1
|
||||||
|
andi.l #0xFFFFFF00, %D1
|
||||||
|
andi.l #0x000000FF, %D0
|
||||||
|
or %D1, %D0
|
||||||
|
movea %D0, %A0
|
||||||
|
move.l (%A0), %D0
|
||||||
|
rts
|
||||||
|
|
||||||
|
_reg_write16:
|
||||||
|
move.l %A0, %D1
|
||||||
|
andi.l #0xFFFF0000, %D1
|
||||||
|
andi.l #0x0000FFFF, %D0
|
||||||
|
or %D1, %D0
|
||||||
|
movea %D0, %A0
|
||||||
|
move.l (%A0), %D0
|
||||||
|
rts
|
||||||
|
|
||||||
|
* smear8to32 calling convention
|
||||||
|
* D0 - data in/out
|
||||||
|
|
||||||
|
smear8to32:
|
||||||
|
andi.l #0xFF, %D0
|
||||||
|
move.l %D0, %D1
|
||||||
|
lsl.w #8, %D1
|
||||||
|
or.w %D1, %D0
|
||||||
|
lsl.w #8, %D1
|
||||||
|
or.w %D1, %D0
|
||||||
|
lsl.w #8, %D1
|
||||||
|
or.w %D1, %D0
|
||||||
|
rts
|
|
@ -0,0 +1,98 @@
|
||||||
|
* spi calling convention
|
||||||
|
* A0 - ROM register
|
||||||
|
* A1 - readback address
|
||||||
|
* A2 - RX buffer
|
||||||
|
* A3 - TX buffer
|
||||||
|
* A4 - clobbered
|
||||||
|
* D0 - length (clobbered)
|
||||||
|
* D1 - nops (clobbered)
|
||||||
|
* D2 - clobbered (save SR)
|
||||||
|
* D3 - clobbered (save CACR)
|
||||||
|
|
||||||
|
.macro spi_call table, maxnops
|
||||||
|
* Limit %D0 (length) to 1-256
|
||||||
|
subq.w #1, %D0
|
||||||
|
andi.l #0xFF, %D0
|
||||||
|
addq.w #1, %D0
|
||||||
|
|
||||||
|
* Limit %D1 (nops) based on maxnops
|
||||||
|
.if \maxnops == 1
|
||||||
|
andi.l #1, %D1
|
||||||
|
.elseif \maxnops == 3
|
||||||
|
andi.l #3, %D1
|
||||||
|
.elseif \maxnops == 7
|
||||||
|
andi.l #7, %D1
|
||||||
|
.elseif \maxnops == 15
|
||||||
|
andi.l #15, %D1
|
||||||
|
.elseif \maxnops != 0
|
||||||
|
.error
|
||||||
|
.endif
|
||||||
|
|
||||||
|
* Convert length to offset
|
||||||
|
* %D0 = -%D0 (-length)
|
||||||
|
neg.l %D0
|
||||||
|
* %D0 = %D0 + 256 (-length + 256)
|
||||||
|
add.l #256, %D0
|
||||||
|
|
||||||
|
.if \maxnops != 0
|
||||||
|
* Combine nops with offset to get lookup table index
|
||||||
|
* %D1 = %D1 * 4 * 256 (nops * 256)
|
||||||
|
lsl.l #8, %D1
|
||||||
|
* %D0 = %D0 + %D1 (offset + nops*256)
|
||||||
|
or.l %D1, %D0
|
||||||
|
.endif
|
||||||
|
|
||||||
|
* Get index of entry point from lookup table
|
||||||
|
* %D0 = table[%D0] (table[4*(length+nops*256)])
|
||||||
|
move.l (\table - ., %PC, %D0.w : 4), %D0
|
||||||
|
|
||||||
|
* Save status register and disable interrupts
|
||||||
|
move.w %SR, %D2
|
||||||
|
ori.w #0x0700, %SR
|
||||||
|
|
||||||
|
* Save CACR in %D3
|
||||||
|
movec %CACR, %D3
|
||||||
|
|
||||||
|
* Copy CACR to %D1
|
||||||
|
move.l %D3, %D1
|
||||||
|
* Clear CACR bits:
|
||||||
|
* DE ('040 enable data cache) (31)
|
||||||
|
* WA ('030 write allocate) (13)
|
||||||
|
* DBE ('030 data burst enable) (12)
|
||||||
|
* CD ('030 clear data cache) (11)
|
||||||
|
* CED ('030 clear entry in data cache) (10)
|
||||||
|
* FD ('030 freeze data cache) (9)
|
||||||
|
* ED ('030 enable data cache) (8)
|
||||||
|
andi.l #0x7FFFC0FF, %D1
|
||||||
|
* Set '030 CACR bits:
|
||||||
|
* FD (freeze data cache) (9)
|
||||||
|
ori.w #0x0200, %D1
|
||||||
|
* Move back into CACR
|
||||||
|
movec.l %D1, %CACR
|
||||||
|
|
||||||
|
* Jump to entry point
|
||||||
|
* (table + table[length*4 + nops*4*256])
|
||||||
|
jmp (\table - ., %PC, %D0.l)
|
||||||
|
|
||||||
|
* Return statement for use with parameter checking
|
||||||
|
ret: rts
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro lookup_table base, nbase, stride, n
|
||||||
|
dc.l \nbase - \base
|
||||||
|
dc.l \nbase + \stride - \base
|
||||||
|
dc.l \nbase + \stride+\stride - \base
|
||||||
|
dc.l \nbase + \stride+\stride+\stride - \base
|
||||||
|
.if \n > 0
|
||||||
|
lookup_table \base, \nbase + \stride+\stride+\stride+\stride, \stride, \n-4
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro unroll_table macro, nops, n
|
||||||
|
.rept \n
|
||||||
|
\macro \nops
|
||||||
|
.endr
|
||||||
|
move.w %D2, %SR
|
||||||
|
movec.l %D3, %CACR
|
||||||
|
rts
|
||||||
|
.endm
|
|
@ -0,0 +1,73 @@
|
||||||
|
* spi calling convention
|
||||||
|
* A0 - ROM register
|
||||||
|
* A1 - readback address
|
||||||
|
* A2 - RX buffer
|
||||||
|
* A3 - TX buffer
|
||||||
|
* A4 - clobbered
|
||||||
|
* D0 - length (clobbered)
|
||||||
|
* D1 - nops (clobbered)
|
||||||
|
|
||||||
|
.global _spi_hal_rx16
|
||||||
|
|
||||||
|
.include "spi_hal_common.s"
|
||||||
|
|
||||||
|
.macro _spi_hal_rx16_iteration nops
|
||||||
|
move.w (%A0), (%A2)+
|
||||||
|
.rept \nops
|
||||||
|
nop
|
||||||
|
.endr
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16:
|
||||||
|
spi_call _spi_hal_rx16_lookup, 15
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_lookup:
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_0, 2, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_1, 4, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_2, 6, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_3, 8, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_4, 10, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_5, 12, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_6, 14, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_7, 16, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_8, 18, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_9, 20, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_10, 22, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_11, 24, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_12, 26, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_13, 28, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_14, 30, 256
|
||||||
|
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_15, 32, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_0: unroll_table _spi_hal_rx16_iteration, 0, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_1: unroll_table _spi_hal_rx16_iteration, 1, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_2: unroll_table _spi_hal_rx16_iteration, 2, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_3: unroll_table _spi_hal_rx16_iteration, 3, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_4: unroll_table _spi_hal_rx16_iteration, 4, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_5: unroll_table _spi_hal_rx16_iteration, 5, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_6: unroll_table _spi_hal_rx16_iteration, 6, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_7: unroll_table _spi_hal_rx16_iteration, 7, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_8: unroll_table _spi_hal_rx16_iteration, 8, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_9: unroll_table _spi_hal_rx16_iteration, 9, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_10: unroll_table _spi_hal_rx16_iteration, 10, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_11: unroll_table _spi_hal_rx16_iteration, 11, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_12: unroll_table _spi_hal_rx16_iteration, 12, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_13: unroll_table _spi_hal_rx16_iteration, 13, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_14: unroll_table _spi_hal_rx16_iteration, 14, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx16_table_15: unroll_table _spi_hal_rx16_iteration, 15, 256
|
|
@ -0,0 +1,49 @@
|
||||||
|
* spi calling convention
|
||||||
|
* A0 - ROM register
|
||||||
|
* A1 - readback address
|
||||||
|
* A2 - RX buffer
|
||||||
|
* A3 - TX buffer
|
||||||
|
* A4 - clobbered
|
||||||
|
* D0 - length (clobbered)
|
||||||
|
* D1 - nops (clobbered)
|
||||||
|
|
||||||
|
.global _spi_hal_rx8
|
||||||
|
|
||||||
|
.include "spi_hal_common.s"
|
||||||
|
|
||||||
|
.macro _spi_hal_rx8_iteration nops
|
||||||
|
move.b (%A0), (%A2)+
|
||||||
|
.rept \nops
|
||||||
|
nop
|
||||||
|
.endr
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx8:
|
||||||
|
spi_call _spi_hal_rx8_lookup, 7
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx8_lookup:
|
||||||
|
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_0, 2, 256
|
||||||
|
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_1, 4, 256
|
||||||
|
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_2, 6, 256
|
||||||
|
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_3, 8, 256
|
||||||
|
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_4, 10, 256
|
||||||
|
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_5, 12, 256
|
||||||
|
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_6, 14, 256
|
||||||
|
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_7, 16, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx8_table_0: unroll_table _spi_hal_rx8_iteration, 0, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx8_table_1: unroll_table _spi_hal_rx8_iteration, 1, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx8_table_2: unroll_table _spi_hal_rx8_iteration, 2, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx8_table_3: unroll_table _spi_hal_rx8_iteration, 3, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx8_table_4: unroll_table _spi_hal_rx8_iteration, 4, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx8_table_5: unroll_table _spi_hal_rx8_iteration, 5, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx8_table_6: unroll_table _spi_hal_rx8_iteration, 6, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rx8_table_7: unroll_table _spi_hal_rx8_iteration, 7, 256
|
|
@ -0,0 +1,62 @@
|
||||||
|
* spi calling convention
|
||||||
|
* A0 - ROM register
|
||||||
|
* A1 - readback address
|
||||||
|
* A2 - RX buffer
|
||||||
|
* A3 - TX buffer
|
||||||
|
* A4 - clobbered
|
||||||
|
* D0 - length (clobbered)
|
||||||
|
* D1 - nops (clobbered)
|
||||||
|
|
||||||
|
* spi single calling convention
|
||||||
|
* A0 - ROM register
|
||||||
|
* A1 - readback address
|
||||||
|
* D0 - data
|
||||||
|
* D1 - clobbered
|
||||||
|
|
||||||
|
.global _spi_hal_rxtx8
|
||||||
|
.global _spi_hal_rxtx8single
|
||||||
|
|
||||||
|
.include "spi_hal_common.s"
|
||||||
|
|
||||||
|
.macro _spi_hal_rxtx8_iteration nops
|
||||||
|
move.b (%A1), (%A2)+
|
||||||
|
move.b (%A3)+, %D1
|
||||||
|
move.b (%A0, %D1.W), %D1
|
||||||
|
.rept \nops
|
||||||
|
nop
|
||||||
|
.endr
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rxtx8:
|
||||||
|
spi_call _spi_hal_rxtx8_lookup, 7
|
||||||
|
_spi_hal_rxtx8_single:
|
||||||
|
move.b (%A1), %D0
|
||||||
|
move.b (%A0, %D1.W), %D1
|
||||||
|
rts
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rxtx8_lookup:
|
||||||
|
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_0, 8, 256
|
||||||
|
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_1, 10, 256
|
||||||
|
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_2, 12, 256
|
||||||
|
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_3, 14, 256
|
||||||
|
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_4, 16, 256
|
||||||
|
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_5, 18, 256
|
||||||
|
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_6, 20, 256
|
||||||
|
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_7, 22, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rxtx8_table_0: unroll_table _spi_hal_rxtx8_iteration, 0, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rxtx8_table_1: unroll_table _spi_hal_rxtx8_iteration, 1, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rxtx8_table_2: unroll_table _spi_hal_rxtx8_iteration, 2, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rxtx8_table_3: unroll_table _spi_hal_rxtx8_iteration, 3, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rxtx8_table_4: unroll_table _spi_hal_rxtx8_iteration, 4, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rxtx8_table_5: unroll_table _spi_hal_rxtx8_iteration, 5, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rxtx8_table_6: unroll_table _spi_hal_rxtx8_iteration, 6, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_rxtx8_table_7: unroll_table _spi_hal_rxtx8_iteration, 7, 256
|
|
@ -0,0 +1,74 @@
|
||||||
|
* spi calling convention
|
||||||
|
* A0 - ROM register
|
||||||
|
* A1 - readback address
|
||||||
|
* A2 - RX buffer
|
||||||
|
* A3 - TX buffer
|
||||||
|
* A4 - clobbered
|
||||||
|
* D0 - length (clobbered)
|
||||||
|
* D1 - nops (clobbered)
|
||||||
|
|
||||||
|
.global _spi_hal_tx16
|
||||||
|
|
||||||
|
.include "spi_hal_common.s"
|
||||||
|
|
||||||
|
.macro _spi_hal_tx16_iteration nops
|
||||||
|
move.w (%A3)+, %D1
|
||||||
|
move.b (%A0, %D1.W), %D1
|
||||||
|
.rept \nops
|
||||||
|
nop
|
||||||
|
.endr
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16:
|
||||||
|
spi_call _spi_hal_tx16_lookup, 15
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_lookup:
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_0, 6, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_1, 8, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_2, 10, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_3, 12, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_4, 14, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_5, 16, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_6, 18, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_7, 20, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_8, 22, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_9, 24, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_10, 26, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_11, 28, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_12, 30, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_13, 32, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_14, 34, 256
|
||||||
|
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_15, 36, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_0: unroll_table _spi_hal_tx16_iteration, 0, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_1: unroll_table _spi_hal_tx16_iteration, 1, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_2: unroll_table _spi_hal_tx16_iteration, 2, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_3: unroll_table _spi_hal_tx16_iteration, 3, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_4: unroll_table _spi_hal_tx16_iteration, 4, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_5: unroll_table _spi_hal_tx16_iteration, 5, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_6: unroll_table _spi_hal_tx16_iteration, 6, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_7: unroll_table _spi_hal_tx16_iteration, 7, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_8: unroll_table _spi_hal_tx16_iteration, 8, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_9: unroll_table _spi_hal_tx16_iteration, 9, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_10: unroll_table _spi_hal_tx16_iteration, 10, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_11: unroll_table _spi_hal_tx16_iteration, 11, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_12: unroll_table _spi_hal_tx16_iteration, 12, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_13: unroll_table _spi_hal_tx16_iteration, 13, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_14: unroll_table _spi_hal_tx16_iteration, 14, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx16_table_15: unroll_table _spi_hal_tx16_iteration, 15, 256
|
|
@ -0,0 +1,50 @@
|
||||||
|
* spi calling convention
|
||||||
|
* A0 - ROM register
|
||||||
|
* A1 - readback address
|
||||||
|
* A2 - RX buffer
|
||||||
|
* A3 - TX buffer
|
||||||
|
* A4 - clobbered
|
||||||
|
* D0 - length (clobbered)
|
||||||
|
* D1 - nops (clobbered)
|
||||||
|
|
||||||
|
.global _spi_hal_tx8
|
||||||
|
|
||||||
|
.include "spi_hal_common.s"
|
||||||
|
|
||||||
|
.macro _spi_hal_tx8_iteration nops
|
||||||
|
move.b (%A3)+, %D1
|
||||||
|
move.b (%A0, %D1.W), %D1
|
||||||
|
.rept \nops
|
||||||
|
nop
|
||||||
|
.endr
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx8:
|
||||||
|
spi_call _spi_hal_tx8_lookup, 7
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx8_lookup:
|
||||||
|
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_0, 6, 256
|
||||||
|
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_1, 8, 256
|
||||||
|
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_2, 10, 256
|
||||||
|
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_3, 12, 256
|
||||||
|
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_4, 14, 256
|
||||||
|
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_5, 16, 256
|
||||||
|
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_6, 18, 256
|
||||||
|
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_7, 20, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx8_table_0: unroll_table _spi_hal_tx8_iteration, 0, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx8_table_1: unroll_table _spi_hal_tx8_iteration, 1, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx8_table_2: unroll_table _spi_hal_tx8_iteration, 2, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx8_table_3: unroll_table _spi_hal_tx8_iteration, 3, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx8_table_4: unroll_table _spi_hal_tx8_iteration, 4, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx8_table_5: unroll_table _spi_hal_tx8_iteration, 5, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx8_table_6: unroll_table _spi_hal_tx8_iteration, 6, 256
|
||||||
|
.align 16
|
||||||
|
_spi_hal_tx8_table_7: unroll_table _spi_hal_tx8_iteration, 7, 256
|
Loading…
Reference in New Issue