From 060002c5ae6e3fea8af884c70d175fd6c653d81a Mon Sep 17 00:00:00 2001 From: Jim Hall Date: Sat, 6 May 2000 19:34:20 +0000 Subject: [PATCH] Initial revision git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@2 6ac86273-5f31-0410-b378-82cca8765d1b --- bin/autoexec.bat | 2 + bin/config.sys | 3 + bin/copying | 339 +++++++ bin/install.bat | 49 + bin/mkboot.txt | 11 + boot/boot.asm | 598 ++++++++++++ boot/boot.mak | 59 ++ build.bat | 75 ++ clean.bat | 66 ++ clobber.bat | 60 ++ config.b | 1 + config.m | 63 ++ docs/bugs.txt | 6 + docs/build.txt | 78 ++ docs/contrib.txt | 17 + docs/copying | 339 +++++++ docs/history.txt | 543 +++++++++++ docs/intfns.txt | 209 +++++ docs/mkboot.txt | 11 + docs/readme.cvs | 15 + drivers/devend.asm | 78 ++ drivers/device.mak | 103 +++ drivers/floppy.asm | 331 +++++++ drivers/getvec.asm | 92 ++ drivers/rdatclk.asm | 117 +++ drivers/rdpcclk.asm | 82 ++ drivers/timer.asm | 159 ++++ drivers/wratclk.asm | 101 +++ drivers/wrpcclk.asm | 82 ++ fdkernel.lsm | 14 + hdr/cds.h | 112 +++ hdr/clock.h | 86 ++ hdr/date.h | 95 ++ hdr/dcb.h | 109 +++ hdr/device.h | 421 +++++++++ hdr/dirmatch.h | 117 +++ hdr/dosnames.h | 79 ++ hdr/error.h | 124 +++ hdr/exe.h | 93 ++ hdr/fat.h | 139 +++ hdr/fcb.h | 167 ++++ hdr/file.h | 76 ++ hdr/fnode.h | 115 +++ hdr/kbd.h | 83 ++ hdr/mcb.h | 102 +++ hdr/network.h | 87 ++ hdr/pcb.h | 177 ++++ hdr/portab.h | 201 ++++ hdr/process.h | 172 ++++ hdr/sft.h | 199 ++++ hdr/stacks.inc | 136 +++ hdr/tail.h | 83 ++ hdr/time.h | 91 ++ hdr/version.h | 46 + kernel/001-437.nls | 233 +++++ kernel/apisupt.asm | 169 ++++ kernel/asmsupt.asm | 195 ++++ kernel/blockio.c | 587 ++++++++++++ kernel/break.c | 84 ++ kernel/chario.c | 404 +++++++++ kernel/config.c | 925 +++++++++++++++++++ kernel/console.asm | 279 ++++++ kernel/dosfns.c | 1148 +++++++++++++++++++++++ kernel/dosidle.asm | 100 ++ kernel/dosnames.c | 481 ++++++++++ kernel/dsk.c | 671 ++++++++++++++ kernel/entry.asm | 633 +++++++++++++ kernel/error.c | 145 +++ kernel/execrh.asm | 129 +++ kernel/fatdir.c | 829 +++++++++++++++++ kernel/fatfs.c | 2117 +++++++++++++++++++++++++++++++++++++++++++ kernel/fattab.c | 378 ++++++++ kernel/fcbfns.c | 1169 ++++++++++++++++++++++++ kernel/globals.h | 713 +++++++++++++++ kernel/init-mod.h | 28 + kernel/initoem.c | 105 +++ kernel/int2f.asm | 232 +++++ kernel/inthndlr.c | 1702 ++++++++++++++++++++++++++++++++++ kernel/io.asm | 619 +++++++++++++ kernel/io.inc | 72 ++ kernel/ioctl.c | 356 ++++++++ kernel/irqstack.asm | 268 ++++++ kernel/kernel.asm | 606 +++++++++++++ kernel/kernel.cfg | 13 + kernel/kernel.mak | 415 +++++++++ kernel/main.c | 524 +++++++++++ kernel/memmgr.c | 572 ++++++++++++ kernel/misc.c | 140 +++ kernel/network.c | 209 +++++ kernel/newstuff.c | 326 +++++++ kernel/nls.c | 667 ++++++++++++++ kernel/nlssupt.asm | 103 +++ kernel/prf.c | 410 +++++++++ kernel/printer.asm | 201 ++++ kernel/procsupt.asm | 312 +++++++ kernel/proto.h | 452 +++++++++ kernel/segs.inc | 63 ++ kernel/serial.asm | 171 ++++ kernel/strings.c | 199 ++++ kernel/sysclk.c | 321 +++++++ kernel/syspack.c | 157 ++++ kernel/systime.c | 242 +++++ kernel/task.c | 914 +++++++++++++++++++ lib/libm.mak | 41 + readme.txt | 36 + sys/bin2c.c | 51 ++ sys/bin2c.mak | 55 ++ sys/sys.c | 666 ++++++++++++++ sys/sys.mak | 73 ++ utils/indent.ini | 17 + utils/proto.bat | 2 + 111 files changed, 29542 insertions(+) create mode 100644 bin/autoexec.bat create mode 100644 bin/config.sys create mode 100644 bin/copying create mode 100644 bin/install.bat create mode 100644 bin/mkboot.txt create mode 100644 boot/boot.asm create mode 100644 boot/boot.mak create mode 100644 build.bat create mode 100644 clean.bat create mode 100644 clobber.bat create mode 100644 config.b create mode 100644 config.m create mode 100644 docs/bugs.txt create mode 100644 docs/build.txt create mode 100644 docs/contrib.txt create mode 100644 docs/copying create mode 100644 docs/history.txt create mode 100644 docs/intfns.txt create mode 100644 docs/mkboot.txt create mode 100644 docs/readme.cvs create mode 100644 drivers/devend.asm create mode 100644 drivers/device.mak create mode 100644 drivers/floppy.asm create mode 100644 drivers/getvec.asm create mode 100644 drivers/rdatclk.asm create mode 100644 drivers/rdpcclk.asm create mode 100644 drivers/timer.asm create mode 100644 drivers/wratclk.asm create mode 100644 drivers/wrpcclk.asm create mode 100644 fdkernel.lsm create mode 100644 hdr/cds.h create mode 100644 hdr/clock.h create mode 100644 hdr/date.h create mode 100644 hdr/dcb.h create mode 100644 hdr/device.h create mode 100644 hdr/dirmatch.h create mode 100644 hdr/dosnames.h create mode 100644 hdr/error.h create mode 100644 hdr/exe.h create mode 100644 hdr/fat.h create mode 100644 hdr/fcb.h create mode 100644 hdr/file.h create mode 100644 hdr/fnode.h create mode 100644 hdr/kbd.h create mode 100644 hdr/mcb.h create mode 100644 hdr/network.h create mode 100644 hdr/pcb.h create mode 100644 hdr/portab.h create mode 100644 hdr/process.h create mode 100644 hdr/sft.h create mode 100644 hdr/stacks.inc create mode 100644 hdr/tail.h create mode 100644 hdr/time.h create mode 100644 hdr/version.h create mode 100644 kernel/001-437.nls create mode 100644 kernel/apisupt.asm create mode 100644 kernel/asmsupt.asm create mode 100644 kernel/blockio.c create mode 100644 kernel/break.c create mode 100644 kernel/chario.c create mode 100644 kernel/config.c create mode 100644 kernel/console.asm create mode 100644 kernel/dosfns.c create mode 100644 kernel/dosidle.asm create mode 100644 kernel/dosnames.c create mode 100644 kernel/dsk.c create mode 100644 kernel/entry.asm create mode 100644 kernel/error.c create mode 100644 kernel/execrh.asm create mode 100644 kernel/fatdir.c create mode 100644 kernel/fatfs.c create mode 100644 kernel/fattab.c create mode 100644 kernel/fcbfns.c create mode 100644 kernel/globals.h create mode 100644 kernel/init-mod.h create mode 100644 kernel/initoem.c create mode 100644 kernel/int2f.asm create mode 100644 kernel/inthndlr.c create mode 100644 kernel/io.asm create mode 100644 kernel/io.inc create mode 100644 kernel/ioctl.c create mode 100644 kernel/irqstack.asm create mode 100644 kernel/kernel.asm create mode 100644 kernel/kernel.cfg create mode 100644 kernel/kernel.mak create mode 100644 kernel/main.c create mode 100644 kernel/memmgr.c create mode 100644 kernel/misc.c create mode 100644 kernel/network.c create mode 100644 kernel/newstuff.c create mode 100644 kernel/nls.c create mode 100644 kernel/nlssupt.asm create mode 100644 kernel/prf.c create mode 100644 kernel/printer.asm create mode 100644 kernel/procsupt.asm create mode 100644 kernel/proto.h create mode 100644 kernel/segs.inc create mode 100644 kernel/serial.asm create mode 100644 kernel/strings.c create mode 100644 kernel/sysclk.c create mode 100644 kernel/syspack.c create mode 100644 kernel/systime.c create mode 100644 kernel/task.c create mode 100644 lib/libm.mak create mode 100644 readme.txt create mode 100644 sys/bin2c.c create mode 100644 sys/bin2c.mak create mode 100644 sys/sys.c create mode 100644 sys/sys.mak create mode 100644 utils/indent.ini create mode 100644 utils/proto.bat diff --git a/bin/autoexec.bat b/bin/autoexec.bat new file mode 100644 index 0000000..8ef3942 --- /dev/null +++ b/bin/autoexec.bat @@ -0,0 +1,2 @@ +@echo off +echo Welcome to FreeDOS (http://www.freedos.org)! diff --git a/bin/config.sys b/bin/config.sys new file mode 100644 index 0000000..b3c420c --- /dev/null +++ b/bin/config.sys @@ -0,0 +1,3 @@ +files=20 +buffers=20 +rem screen=0x12 diff --git a/bin/copying b/bin/copying new file mode 100644 index 0000000..b8cf3a1 --- /dev/null +++ b/bin/copying @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/bin/install.bat b/bin/install.bat new file mode 100644 index 0000000..8562e5e --- /dev/null +++ b/bin/install.bat @@ -0,0 +1,49 @@ +@echo off +rem +rem Create a distribution floppy +rem +rem $Header$ +rem $Log$ +rem Revision 1.1 2000/05/06 19:34:23 jhall1 +rem Initial revision +rem +rem Revision 1.3 1999/08/25 03:15:33 jprice +rem ror4 patches to allow TC 2.01 compile. +rem +rem Revision 1.2 1999/04/01 07:22:58 jprice +rem no message +rem +rem Revision 1.1.1.1 1999/03/29 15:40:21 jprice +rem New version without IPL.SYS +rem +rem + +set D=A: +if "%1" == "b:" set D=B: +if "%1" == "B:" set D=B: +if "%1" == "b" set D=B: +if "%1" == "B" set D=B: + +echo This utility will create a distribution floppy on the disk in drive %D% +pause + +rem try to transfer system files -- abort if it cannot. +sys %D% +if errorlevel 1 goto out + +rem copy remaining files +echo copying remaining files... +echo copying autoexec.bat... +copy autoexec.bat %D% +echo copying config.sys.. +copy config.sys %D% +echo copying sys.com.. +copy sys.com %D% +label %D% freedos + +rem exit methods +goto done +:out +echo Floppy creation aborted +:done +set D= diff --git a/bin/mkboot.txt b/bin/mkboot.txt new file mode 100644 index 0000000..73be5d6 --- /dev/null +++ b/bin/mkboot.txt @@ -0,0 +1,11 @@ +To create a bootable floppy suitable for copying the system to +another drive: + +1. Change directory (if necessary) to where the FreeDOS Kernel BIN +directory. + +3. Enter the command "install" to transfer the system files to the +diskette in drive A. If you want to install on drive B, type +"install b:" + +4. Write protect this disk and use it to boot from. diff --git a/boot/boot.asm b/boot/boot.asm new file mode 100644 index 0000000..9fdcb9e --- /dev/null +++ b/boot/boot.asm @@ -0,0 +1,598 @@ +; +; File: +; boot.asm +; Description: +; DOS-C boot +; +; Copyright (c) 1997; +; Svante Frey +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; + + +; $Log$ +; Revision 1.1 2000/05/06 19:34:38 jhall1 +; Initial revision +; +; Revision 1.12 1999/09/25 06:42:18 jprice +; Optimize boot loader. Documentation. +; +; Revision 1.11 1999/09/24 19:04:55 jprice +; Added changes recommended by Jens Horstmeier + +; to make their bootable CD work. +; +; Revision 1.10 1999/09/23 04:39:02 jprice +; *** empty log message *** +; +; Revision 1.7 1999/04/23 03:43:46 jprice +; Ported to NASM by ror4 +; +; Revision 1.6 1999/04/17 19:14:03 jprice +; Fixed multi-sector code +; +; Revision 1.5 1999/04/17 06:23:26 jprice +; Changed so multi-sector IO is optional. +; +; Revision 1.4 1999/04/13 15:52:22 jprice +; Moves boot sector to top of mem +; +; Revision 1.3 1999/04/06 22:53:36 jprice +; Put back code to read multiple sectors at a time. +; +; Revision 1.2 1999/04/01 07:23:20 jprice +; New boot loader +; +; Revision 1.1.1.1 1999/03/29 15:39:39 jprice +; New version without IPL.SYS +; +; Revision 1.3 1999/03/02 06:57:14 jprice +; Added entry address for more recent versions of TLINK +; +; Revision 1.2 1999/01/21 05:03:58 jprice +; Formating. +; +; Revision 1.1.1.1 1999/01/20 05:51:00 jprice +; Imported sources +; +; +; Rev 1.5 10 Jan 1997 4:58:06 patv +; Corrected copyright +; +; Rev 1.4 10 Jan 1997 4:52:50 patv +; Re-written to support C drive and eliminate restrictions on IPL.SYS +; +; Rev 1.3 29 Aug 1996 13:06:50 patv +; Bug fixes for v0.91b +; +; Rev 1.2 01 Sep 1995 17:56:44 patv +; First GPL release. +; +; Rev 1.1 30 Jul 1995 20:37:38 patv +; Initialized stack before use. +; +; Rev 1.0 02 Jul 1995 10:57:52 patv +; Initial revision. +; + +; +--------+ +; | | +; | | +; |--------| 4000:0000 +; | | +; | FAT | +; | | +; |--------| 2000:0000 +; |BOOT SEC| +; |RELOCATE| +; |--------| 1FE0:0000 +; | | +; | | +; | | +; | | +; |--------| +; |BOOT SEC| +; |ORIGIN | 07C0:0000 +; |--------| +; | | +; | | +; | | +; |--------| +; |KERNEL | +; |LOADED | +; |--------| 0060:0000 +; | | +; +--------+ + + +;%define ISFAT12 1 +;%define ISFAT16 1 +;%define CALCPARAMS 1 +;%define MULTI_SEC_READ 1 + + +segment .text + +%define BASE 0x7c00 + + org BASE + +Entry: jmp short real_start + nop + +; bp is initialized to 7c00h +%define bsOemName bp+0x03 ; OEM label +%define bsBytesPerSec bp+0x0b ; bytes/sector +%define bsSecPerClust bp+0x0d ; sectors/allocation unit +%define bsResSectors bp+0x0e ; # reserved sectors +%define bsFATs bp+0x10 ; # of fats +%define bsRootDirEnts bp+0x11 ; # of root dir entries +%define bsSectors bp+0x13 ; # sectors total in image +%define bsMedia bp+0x15 ; media descrip: fd=2side9sec, etc... +%define sectPerFat bp+0x16 ; # sectors in a fat +%define sectPerTrack bp+0x18 ; # sectors/track +%define nHeads bp+0x1a ; # heads +%define nHidden bp+0x1c ; # hidden sectors +%define nSectorHuge bp+0x20 ; # sectors if > 65536 +%define drive bp+0x24 ; drive number +%define extBoot bp+0x26 ; extended boot signature +%define volid bp+0x27 +%define vollabel bp+0x2b +%define filesys bp+0x36 + +%define LOADSEG 0x0060 + +%define FATBUF 0x2000 ; offset of temporary buffer for FAT + ; chain + +; Some extra variables + +;%define StoreSI bp+3h ;temp store + +; To save space, functions that are just called once are +; implemented as macros instead. Four bytes are saved by +; avoiding the call / ret instructions. + + +; GETDRIVEPARMS: Calculate start of some disk areas. +; + +%macro GETDRIVEPARMS 0 + mov si, word [nHidden] + mov di, word [nHidden+2] + add si, word [bsResSectors] + adc di, byte 0 ; DI:SI = first FAT sector + + mov word [fat_start], si + mov word [fat_start+2], di + + mov al, [bsFATs] + xor ah, ah + mul word [sectPerFat] ; DX:AX = total number of FAT sectors + + add si, ax + adc di, dx ; DI:SI = first root directory sector + mov word [root_dir_start], si + mov word [root_dir_start+2], di + + ; Calculate how many sectors the root directory occupies. + mov bx, [bsBytesPerSec] + mov cl, 5 ; divide BX by 32 + shr bx, cl ; BX = directory entries per sector + + mov ax, [bsRootDirEnts] + xor dx, dx + div bx + + mov word [RootDirSecs], ax ; AX = sectors per root directory + + add si, ax + adc di, byte 0 ; DI:SI = first data sector + + mov [data_start], si + mov [data_start+2], di +%endmacro + +;----------------------------------------------------------------------- + + times 0x3E-$+$$ db 0 + +%define tempbuf bp+0x3E + dw LOADSEG + +%ifdef CALCPARAMS +%define RootDirSecs bp+0x27 ; # of sectors root dir uses + +%define fat_start bp+0x29 ; first FAT sector + +%define root_dir_start bp+0x2D ; first root directory sector + +%define data_start bp+0x31 ; first data sector + +%else +%define RootDirSecs bp+0x40 ; # of sectors root dir uses + dw 0 + +%define fat_start bp+0x42 ; first FAT sector + dd 0 + +%define root_dir_start bp+0x46 ; first root directory sector + dd 0 + +%define data_start bp+0x4A ; first data sector + dd 0 +%endif + +;----------------------------------------------------------------------- +; ENTRY +;----------------------------------------------------------------------- + +real_start: cli + cld + xor ax, ax + mov ss, ax ; initialize stack + mov ds, ax + mov bp, 0x7c00 + lea sp, [bp-0x20] + sti + int 0x13 ; reset drive +; int 0x12 ; get memory available in AX +; mov ax, 0x01e0 +; mov cl, 6 ; move boot sector to higher memory +; shl ax, cl +; sub ax, 0x07e0 + + mov ax, 0x1FE0 + mov es, ax + mov si, bp + mov di, bp + mov cx, 0x0100 + rep movsw + push es + mov bx, cont + push bx + retf + +cont: mov ds, ax + mov ss, ax + mov [drive], dl ; BIOS passes drive number in DL + + call print + db "Loading FreeDOS...",13,10,"ROOT",0 + +%ifdef CALCPARAMS + GETDRIVEPARMS +%endif + + +; FINDFILE: Searches for the file in the root directory. +; +; Returns: +; AX = first cluster of file + + ; First, read the whole root directory + ; into the temporary buffer. + + mov ax, word [root_dir_start] + mov dx, word [root_dir_start+2] + mov di, word [RootDirSecs] + xor bx, bx + mov es, [tempbuf] + call readDisk + jc jmp_boot_error + + xor di, di + + ; Search for KERNEL.SYS file name, and find start cluster. + +next_entry: mov cx, 11 + mov si, filename + push di + repe cmpsb + pop di + mov ax, [es:di+0x1A]; get cluster number from directory entry + je ffDone + + add di, byte 0x20 ; go to next directory entry + cmp byte [es:di], 0 ; if the first byte of the name is 0, + jnz next_entry ; there is no more files in the directory + + jc boot_error ; fail if not found +ffDone: + push ax ; store first cluster number + + call print + db " FAT",0 + + + +; GETFATCHAIN: +; +; Reads the FAT chain and stores it in a temporary buffer in the first +; 64 kb. The FAT chain is stored an array of 16-bit cluster numbers, +; ending with 0. +; +; The file must fit in conventional memory, so it can't be larger than +; 640 kb. The sector size must be at least 512 bytes, so the FAT chain +; can't be larger than around 3 kb. +; +; Call with: AX = first cluster in chain + + ; Load the complete FAT into memory. The FAT can't be larger + ; than 128 kb, so it should fit in the temporary buffer. + + mov es, [tempbuf] + xor bx, bx + mov di, [sectPerFat] + mov ax, word [fat_start] + mov dx, word [fat_start+2] + call readDisk + pop ax ; restore first cluster number +jmp_boot_error: jc boot_error + + ; Set ES:DI to the temporary storage for the FAT chain. + push ds + push es + pop ds + pop es + mov di, FATBUF + +next_clust: stosw ; store cluster number + mov si, ax ; SI = cluster number + +%ifdef ISFAT12 + ; This is a FAT-12 disk. + +fat_12: add si, si ; multiply cluster number by 3... + add si, ax + shr si, 1 ; ...and divide by 2 + lodsw + + ; If the cluster number was even, the cluster value is now in + ; bits 0-11 of AX. If the cluster number was odd, the cluster + ; value is in bits 4-15, and must be shifted right 4 bits. If + ; the number was odd, CF was set in the last shift instruction. + + jnc fat_even + mov cl, 4 + shr ax, cl ; shift the cluster number + +fat_even: and ah, 0x0f ; mask off the highest 4 bits + cmp ax, 0x0fff ; check for EOF + jb next_clust ; continue if not EOF + +%endif +%ifdef ISFAT16 + ; This is a FAT-16 disk. The maximal size of a 16-bit FAT + ; is 128 kb, so it may not fit within a single 64 kb segment. + +fat_16: mov dx, [tempbuf] + add si, si ; multiply cluster number by two + jnc first_half ; if overflow... + add dh, 0x10 ; ...add 64 kb to segment value + +first_half: mov ds, dx ; DS:SI = pointer to next cluster + lodsw ; AX = next cluster + + cmp ax, 0xfff8 ; >= FFF8 = 16-bit EOF + jb next_clust ; continue if not EOF +%endif + +finished: ; Mark end of FAT chain with 0, so we have a single + ; EOF marker for both FAT-12 and FAT-16 systems. + + xor ax, ax + stosw + + push cs + pop ds + + call print + db " KERNEL",0 + +; loadFile: Loads the file into memory, one cluster at a time. + + mov es, [tempbuf] ; set ES:BX to load address + xor bx, bx + + mov si, FATBUF ; set DS:SI to the FAT chain + +cluster_next: lodsw ; AX = next cluster to read + or ax, ax ; if EOF... + je boot_success ; ...boot was successful + + dec ax ; cluster numbers start with 2 + dec ax + + mov di, word [bsSecPerClust] + and di, 0xff ; DI = sectors per cluster + mul di + add ax, [data_start] + adc dx, [data_start+2] ; DX:AX = first sector to read + call readDisk + jnc cluster_next + + +boot_error: call print + db 13,10,"BOOT error!",13,10,0 + + xor ah,ah + int 0x16 ; wait for a key + int 0x19 ; reboot the machine + +boot_success: call print + db " GO!",13,10,0 + mov bl, [drive] + jmp word LOADSEG:0 + + +; prints text after call to this function. + +print: pop si ; this is the first character + xor bx, bx ; video page 0 + mov ah, 0x0E ; else print it +print1: lodsb ; get token + cmp al, 0 ; end of string? + je print2 ; if so, exit + int 0x10 ; via TTY mode + jmp short print1 ; until done +print2: push si ; stack up return address + ret ; and jump to it + + +; readDisk: Reads a number of sectors into memory. +; +; Call with: DX:AX = 32-bit DOS sector number +; DI = number of sectors to read +; ES:BX = destination buffer +; ES must be 64k aligned (1000h, 2000h etc). +; +; Returns: CF set on error +; ES:BX points one byte after the last byte read. + +readDisk: push si +read_next: push dx + push ax + + ; + ; translate sector number to BIOS parameters + ; + + ; + ; abs = sector offset in track + ; + head * sectPerTrack offset in cylinder + ; + track * sectPerTrack * nHeads offset in platter + ; + ; t1 = abs / sectPerTrack (ax has t1) + ; sector = abs mod sectPerTrack (cx has sector) + ; + div word [sectPerTrack] + mov cx, dx + + ; + ; t1 = head + track * nHeads + ; + ; track = t1 / nHeads (ax has track) + ; head = t1 mod nHeads (dl has head) + ; + xor dx, dx + div word [nHeads] + + ; the following manipulations are necessary in order to + ; properly place parameters into registers. + ; ch = cylinder number low 8 bits + ; cl = 7-6: cylinder high two bits + ; 5-0: sector + mov dh, dl ; save head into dh for bios + ror ah, 1 ; move track high bits into + ror ah, 1 ; bits 7-6 (assumes top = 0) + xchg al, ah ; swap for later + mov dl, byte [sectPerTrack] + sub dl, cl + inc cl ; sector offset from 1 + or cx, ax ; merge cylinder into sector + mov al, dl ; al has # of sectors left + +%ifdef MULTI_SEC_READ + ; Calculate how many sectors can be transfered in this read + ; due to dma boundary conditions. + push dx + + mov si, di ; temp register save + ; this computes remaining bytes because of modulo 65536 + ; nature of dma boundary condition + mov ax, bx ; get offset pointer + neg ax ; and convert to bytes + jz ax_min_1 ; started at seg:0, skip ahead + + xor dx, dx ; convert to sectors + div word [bsBytesPerSec] + + cmp ax, di ; check remainder vs. asked + jb ax_min_1 ; less, skip ahead + mov si, ax ; transfer only what we can + +ax_min_1: pop dx + + ; Check that request sectors do not exceed track boundary + mov si, [sectPerTrack] + inc si + mov ax, cx ; get the sector/cyl byte + and ax, 0x3f ; and mask out sector + sub si, ax ; si has how many we can read + mov ax, di + cmp si, di ; see if asked <= available + jge ax_min_2 + mov ax, si ; get what can be xfered + +ax_min_2: push ax + mov ah, 2 + mov dl, [drive] + int 0x13 + pop ax +%else + mov ax, 0x0201 + mov dl, [drive] + int 0x13 +%endif + jnc read_ok ; jump if no error + xor ah, ah ; else, reset floppy + int 0x13 + pop ax + pop dx ; and... + jmp short read_next ; read the same sector again + +read_ok: +%ifdef MULTI_SEC_READ + mul word [bsBytesPerSec] ; add number of bytes read to BX + add bx, ax +%else + add bx, word [bsBytesPerSec] +%endif + jnc no_incr_es ; if overflow... + + mov ax, es + add ah, 0x10 ; ...add 1000h to ES + mov es, ax + +no_incr_es: pop ax + pop dx ; DX:AX = last sector number + +%ifdef MULTI_SEC_READ + add ax, si + adc dx, byte 0 ; DX:AX = next sector to read + sub di,si ; if there is anything left to read, + jg read_next ; continue +%else + add ax, 1 + adc dx, byte 0 ; DX:AX = next sector to read + dec di ; if there is anything left to read, + jnz read_next ; continue +%endif + + clc + pop si + ret + +filename db "KERNEL SYS" + + times 0x01fe-$+$$ db 0 + +sign dw 0xAA55 diff --git a/boot/boot.mak b/boot/boot.mak new file mode 100644 index 0000000..b35efb2 --- /dev/null +++ b/boot/boot.mak @@ -0,0 +1,59 @@ +# +# makefile for DOS-C boot +# +# $Id$ +# + +# $Log$ +# Revision 1.1 2000/05/06 19:34:38 jhall1 +# Initial revision +# +# Revision 1.3 1999/04/23 03:44:17 jprice +# Ported to NASM by ror4. Improvements +# +# Revision 1.2 1999/04/01 07:23:20 jprice +# New boot loader +# +# Revision 1.1.1.1 1999/03/29 15:39:39 jprice +# New version without IPL.SYS +# +# Revision 1.3 1999/02/09 04:49:17 jprice +# Make makefile use common config.mak file +# +# Revision 1.2 1999/01/21 05:03:58 jprice +# Formating. +# +# Revision 1.1.1.1 1999/01/20 05:51:00 jprice +# Imported sources +# +# +# Rev 1.3 10 Jan 1997 4:51:54 patv +#Changed to use FreeDOS exe2bin and support new boot code +# +# Rev 1.2 17 Dec 1996 12:52:32 patv +#Converted to FreeDOS exe2bin. +# +# Rev 1.1 29 Aug 1996 13:06:50 patv +#Bug fixes for v0.91b +# +# Rev 1.0 02 Jul 1995 9:11:26 patv +#Initial revision. +# + +!include "..\config.mak" + +production: b_fat12.bin b_fat16.bin + +b_fat12.bin: boot.asm + $(NASM) -dISFAT12 boot.asm -ob_fat12.bin + +b_fat16.bin: boot.asm + $(NASM) -dISFAT16 boot.asm -ob_fat16.bin + +clobber: clean + $(RM) b_fat12.bin b_fat16.bin status.me + +clean: + $(RM) *.lst *.map *.bak *.obj + + diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..e5d752e --- /dev/null +++ b/build.bat @@ -0,0 +1,75 @@ +@echo off + +rem batch file to build everything + +rem $Id$ + +rem $Log$ +rem Revision 1.1 2000/05/06 19:34:02 jhall1 +rem Initial revision +rem +rem Revision 1.5 1999/08/25 03:59:14 jprice +rem New build batch files. +rem +rem Revision 1.4 1999/08/25 03:38:16 jprice +rem New build config +rem +rem Revision 1.3 1999/04/23 03:46:02 jprice +rem Improved by jprice +rem +rem Revision 1.2 1999/04/17 19:13:29 jprice +rem ror4 patches +rem +rem Revision 1.1.1.1 1999/03/29 15:39:13 jprice +rem New version without IPL.SYS +rem +rem Revision 1.5 1999/02/09 04:47:54 jprice +rem Make makefile use common config.mak file +rem +rem Revision 1.4 1999/01/30 08:29:10 jprice +rem Clean up +rem +rem Revision 1.3 1999/01/30 07:49:16 jprice +rem Clean up +rem + +if not exist config.bat goto noconfigbat +if not exist config.mak goto noconfigmak +goto start + +:noconfigbat +echo You must copy CONFIG.B to CONFIG.BAT and edit it to reflect your setup! +goto end + +:noconfigmak +echo You must copy CONFIG.M to CONFIG.MAK and edit it to reflect your setup! +goto end + +:start +call config.bat + +cd lib +%MAKE% -flibm.mak +if errorlevel 1 goto abort + +cd ..\drivers +%MAKE% -fdevice.mak production +if errorlevel 1 goto abort + +cd ..\boot +%MAKE% -fboot.mak production +if errorlevel 1 goto abort + +cd ..\sys +%MAKE% -fbin2c.mak production +if errorlevel 1 goto abort +%MAKE% -fsys.mak production +if errorlevel 1 goto abort + +cd ..\kernel +%MAKE% -fkernel.mak production + +:abort +cd .. +:end +set MAKE= diff --git a/clean.bat b/clean.bat new file mode 100644 index 0000000..5515f4e --- /dev/null +++ b/clean.bat @@ -0,0 +1,66 @@ +@echo off + +rem batch file to clean everything + +rem $Id$ + +rem $Log$ +rem Revision 1.1 2000/05/06 19:34:02 jhall1 +rem Initial revision +rem +rem Revision 1.3 1999/08/25 03:59:14 jprice +rem New build batch files. +rem +rem Revision 1.2 1999/04/23 03:46:02 jprice +rem Improved by jprice +rem +rem Revision 1.1.1.1 1999/03/29 15:39:15 jprice +rem New version without IPL.SYS +rem +rem Revision 1.4 1999/02/09 04:47:54 jprice +rem Make makefile use common config.mak file +rem +rem Revision 1.3 1999/01/30 08:29:10 jprice +rem Clean up +rem + +if not exist config.bat goto noconfigbat +if not exist config.mak goto noconfigmak +goto start + +:noconfigbat +echo You must copy CONFIG.B to CONFIG.BAT and edit it to reflect your setup! +goto end + +:noconfigmak +echo You must copy CONFIG.M to CONFIG.MAK and edit it to reflect your setup! +goto end + +:start +call config.bat + +cd lib +%MAKE% -flibm.mak clean + +cd ..\drivers +%MAKE% -fdevice.mak clean + +cd ..\boot +%MAKE% -fboot.mak clean + +cd ..\sys +%MAKE% -fbin2c.mak clean +%MAKE% -fsys.mak clean + +cd ..\kernel +%MAKE% -fkernel.mak clean + +cd ..\hdr +del *.bak + +cd .. + +del *.bak + +:end +set MAKE= diff --git a/clobber.bat b/clobber.bat new file mode 100644 index 0000000..8105e74 --- /dev/null +++ b/clobber.bat @@ -0,0 +1,60 @@ +@echo off +rem batch file to clobber everything + +rem $Id$ + +rem $Log$ +rem Revision 1.1 2000/05/06 19:34:02 jhall1 +rem Initial revision +rem +rem Revision 1.3 1999/08/25 03:59:14 jprice +rem New build batch files. +rem +rem Revision 1.2 1999/08/10 18:34:06 jprice +rem case +rem +rem Revision 1.1 1999/04/23 03:47:19 jprice +rem Initial include +rem + +if not exist config.bat goto noconfigbat +if not exist config.mak goto noconfigmak +goto start + +:noconfigbat +echo You must copy CONFIG.B to CONFIG.BAT and edit it to reflect your setup! +goto end + +:noconfigmak +echo You must copy CONFIG.M to CONFIG.MAK and edit it to reflect your setup! +goto end + +:start +call config.bat + +cd lib +%MAKE% -flibm.mak clobber + +cd ..\drivers +%MAKE% -fdevice.mak clobber + +cd ..\boot +%MAKE% -fboot.mak clobber + +cd ..\sys +%MAKE% -fbin2c.mak clobber +%MAKE% -fsys.mak clobber + +cd ..\kernel +%MAKE% -fkernel.mak clobber + +cd ..\hdr +del *.bak + +cd .. + +del *.bak +del status.me + +:end +set MAKE= diff --git a/config.b b/config.b new file mode 100644 index 0000000..3f5bf68 --- /dev/null +++ b/config.b @@ -0,0 +1 @@ +set MAKE=c:\tc201\make diff --git a/config.m b/config.m new file mode 100644 index 0000000..7769c8d --- /dev/null +++ b/config.m @@ -0,0 +1,63 @@ +# +# makefile that is included in all other makefiles for configuration +# + +################################################################ +# NOTICE! You must edit and rename this file to CONFIG.MAK! # +################################################################ + +# These are generic definitions +RM=..\utils\rm -f +NASM=nasm + + +# Use these for Turbo C 2.01 +#COMPILER=TC2 +#COMPILERPATH=c:\tc201 +#CC=$(COMPILERPATH)\tcc +#LINK=$(COMPILERPATH)\tlink +#LIBUTIL=$(COMPILERPATH)\tlib +#LIBPATH=$(COMPILERPATH)\lib +#CLIB=$(COMPILERPATH)\lib\cs.lib +#INCLUDEPATH=$(COMPILERPATH)\include + + +# Use these for Turbo C 3.0 +#COMPILER=TC3 +#COMPILERPATH=c:\tc +#CC=$(COMPILERPATH)\bin\tcc +#LINK=$(COMPILERPATH)\bin\tlink +#LIBUTIL=$(COMPILERPATH)\bin\tlib +#LIBPATH=$(COMPILERPATH)\lib +#CLIB=$(COMPILERPATH)\lib\cs.lib +#INCLUDEPATH=$(COMPILERPATH)\include + + +# Use these for Borland C++ +#COMPILER=BC5 +#COMPILERPATH=c:\bc5 +#CC=$(COMPILERPATH)\bin\tcc +#LINK=$(COMPILERPATH)\bin\tlink +#LIBUTIL=$(COMPILERPATH)\bin\tlib +#LIBPATH=$(COMPILERPATH)\lib +#CLIB=$(COMPILERPATH)\lib\cs.lib +#INCLUDEPATH=$(COMPILERPATH)\include + + +# +# $Id$ +# +# $Log$ +# Revision 1.1 2000/05/06 19:34:02 jhall1 +# Initial revision +# +# Revision 1.3 1999/09/13 20:40:17 jprice +# Added COMPILER variable +# +# Revision 1.2 1999/08/25 03:59:14 jprice +# New build batch files. +# +# Revision 1.1 1999/08/25 03:20:39 jprice +# ror4 patches to allow TC 2.01 compile. +# +# diff --git a/docs/bugs.txt b/docs/bugs.txt new file mode 100644 index 0000000..c44f37e --- /dev/null +++ b/docs/bugs.txt @@ -0,0 +1,6 @@ +The current bug database is available on the web at + +http://www.gcfl.net/bugs/kernel + +Send bug reports to kernel-bugs@gcfl.net. + diff --git a/docs/build.txt b/docs/build.txt new file mode 100644 index 0000000..837b534 --- /dev/null +++ b/docs/build.txt @@ -0,0 +1,78 @@ +To build the operating system, a batch file (BUILD.BAT) is included +to make life easier. This file is in the FDKERNEL directory of the +distribution. In addition, there is a corresponding batch file +(CLEAN.BAT) to clean up the source directories. + +There is a CONFIG.M file that specifies all the paths and names of +the compiler, assembler, etc. that you want to use. You MUST copy +it to CONFIG.MAK first, then edit it to reflect your setup. + +Likewise, there is a CONFIG.B file that should be copied to +CONFIG.BAT, and then edited to reflect your setup. + +The reason for this copying of files is that when new releases of the +kernel come out, you can extract them over your previous source, and +not have to worry about resetting up your configuration because your +CONFIG.BAT and CONFIG.MAK files will not get replaced! + +You will also need to download the latest version of NASM (a mirror +is at ftp://ftp.gcfl.net/freedos/nasm) and Turbo C 2.01 (a mirror is +at ftp://ftp.gcfl.net/freedos/tools/borland/tc201.zip). Install +Turbo C and NASM somewhere (it doesn't really matter where) and then +be sure to edit the CONFIG.MAK file to reflect where you put the +tools. + +This program will now compile with Turbo C 2.01 (now freely +available!), Turbo C 3.0, Borland C 4.51 & 5.01. It should work with +other Borland compilers as well. + +If you feel hardy, read on to understand the directory structure. A +more complete description of the build environment is contained in a +companion book, "The FreeDOS Kernel" (ISBN: 0-87930-436-7) published +by R&D Books, an imprint of Miller Freeman of Lawrence, Kansas (USA) +and distributed in the USA and Canada by Publishers Group West. See +the file README.TXT for more details. + + +Directory Structure +------------------- + +fdkernel root directory + +-----bin holds image of distribution disk + +-----boot boot.bin (boot sector) + +-----docs documentation directory + +-----drivers DEVICE.LIB + +-----hdr common *.h files + +-----kernel The kernel itself + +-----lib LIBM.LIB and DEVICE.LIB + +-----sys SYS.COM and supporting programs + +-----utils Miscellaneous utilities + + +Organization in a nutshell +-------------------------- +Each component or group of utilities is segregated into its own +directory. In order to build that component or utility, a makefile +exists in the directory that bears the component's or utility's +basename. + +Each makefile has at least two targets, production and clean. The +target production builds the expected component or utility and the +component clean cleans up the directory for distribution. The +makefile may have at least one additional target that builds the +component. Study the makefile to better understand this. + +--------------------------------------------------------------------- + +$Id$ + +$Log$ +Revision 1.1 2000/05/06 19:34:38 jhall1 +Initial revision + +Revision 1.2 1999/08/25 04:12:31 jprice +update + +Revision 1.1 1999/08/25 03:46:41 jprice +New build config + diff --git a/docs/contrib.txt b/docs/contrib.txt new file mode 100644 index 0000000..fa35655 --- /dev/null +++ b/docs/contrib.txt @@ -0,0 +1,17 @@ +These are the know contributors of the FreeDOS kernel. If you have +contributed in any way to the kernel, but are not on this list, +please email me at linux-guru@gcfl.net so I can add you to the list! + +Thanx to all the following for contributing to the FreeDOS kernel: + +ror4 (ror4@angelfire.com) +Steffen Kaiser (Steffen.Kaiser@fh-rhein-sieg.de) +Charles Dye (raster@highfiber.com) +John Price (linux-guru@gcfl.net) +Steve Miller (SMiller@dsfx.com) +Jens Horstmeier (Jens.Horstmeier@Abg1.SIEMENS.DE) +James Tabor (jimtabor@infohwy.com) + +And last, but not least, a big thanx to Pasquale J. Villani +(patv@iop.com), who was the original author of DOS-C, in which the +FreeDOS kernel was based. diff --git a/docs/copying b/docs/copying new file mode 100644 index 0000000..b8cf3a1 --- /dev/null +++ b/docs/copying @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/docs/history.txt b/docs/history.txt new file mode 100644 index 0000000..ab82ce1 --- /dev/null +++ b/docs/history.txt @@ -0,0 +1,543 @@ +2000 Mar 09 - Build 2018 +-------- James Tabor (jimtabor@infohwy.com) +Added CDS and made FD CDS based. Changes encompass all of the + code for FD. +Fixed Task.c, rewritten code from FINODE to SFT function calls. + Unable to execute from CD. Main.c and Config.c has small + changes. +Fixed Device drivers are unable to write to con. Rewritten code to + relocate DOS_PSP pointer to 050:0000. Removed references to + DOS_PSP in DosFns.c. +Added Network and Redirection function calls in Inthndlr.c and + network.c. + +I have a note in FatFs.c line 313, describing functions not yet +supported for networking. I don't understand Pats thoughts on SFT to +FINODE. IMHO it would have been easier to stay with SFT all through +the code. + +I tested MS-Dos 6.22 Command and found it unable to do Find First or +Next. This too could explain why MSCDEX does the same thing. I only +test this with the current FDCommand at the time, so this could have +changed. + +1999 Sep 24 - Build 2017 +-------- John Price (linux-guru@gcfl.net) +* Per Jens Horstmeier's email, changed boot sector code to make + Siemens CDROM's bootable. The changes should be OK for all other + machines too (in theory). + +1999 Sep 22 - Build 2016 +-------- John Price (linux-guru@gcfl.net) +* Turned off debug output from the kernel. It does not seem to be + necessary at this time. +* Changed boot sector to do single-sector reads instead of + multi-sector reads. Appearantly this was part of the reason the + kernel would not boot from a 720K, or other format floppies. Thanx + to Charles Dye for the info. + +1999 Sep 16 - Build 2016 +-------- James Tabor (jimtabor@infohwy.com) +* Added Networking and Server Call +* Added Dos Idle call +* fixed Console.asm ConInStat + +1999 Sep 13 - Build 2014 +-------- John Price (linux-guru@gcfl.net) +* Deleted some files from the drivers directory that were not being + used. +* Changed the LIB.MAK file so it would work for TC2 or TC3 or higher. +* Changed SYS.COM so that it creates a sys.log file with more debug + information to help debug problems with making boot disks. + +1999 Sep 13 - Build 2014 +-------- James Tabor (jimtabor@infohwy.com) +* Submitted changes to CONSOLE.ASM & INTHNDLR.ASM to fix the INT21 + func 0B bug. + +1999 Sep 13 - Build 2014 +-------- Helmut Fritsch (helmut.fritsch@gcd-hs.de) +* Submitted changes to CONSOLE.ASM to fix the INT21 func 0B bug. + +1999 Sep 10 - Build 2014 +-------- ror4 (f2xm1@crosswinds.net) +* At the suggestion of Mr John Price, modified the int 0x25 and int + 0x26 so that they no longer update the disk buffers (int 0x26 only + invalidates the buffers for the specified drive). This is to avoid + inconsistent disk buffers from appearing in the buffer chain due to + interactions between int 0x25/0x26 and file read/write operations. + +1999 Aug 24 - Build 2013 +-------- John Price (linux-guru@gcfl.net) +* With ideas from ror4, I redid the build batch file so you can + specify where what make to use. +* Also created CONFIG.M and CONFIG.B which should be copied to + CONFIG.MAK and CONFIG.BAT, respecively, and edited to reflect the + users configuration. This keeps new versions from replacing the + configuration files so the user does not have to keep reseting + their configutation. + +1999 Aug 15 - Build 2013 +-------- ror4 (ror4@angelfire.com) +* Patched the source so that it can be compiled with Turbo C 2.01. + (`asm' statements were rewritten into very ugly equivalents... they + probably need more work. :( ) +* Modified the `dmatch' structure in `hdr/dirmatch.h' so that the + `dm_dirstart' field is in the right place, and also to make it + compile under TC 2.01, which doesn't allow bit fields of any types + other than signed or unsigned int. +* Fixed a few minor bugs in error code returning in `kernel/fatfs.c'. + +1999 Jul 16 - Build 2012 +-------- ror4 (ror4@iname.com) +* Finally ported all the assembly modules to `nasm'. *phew* +* Undid plonee's patches to `kernel/fatfs.c' (sorry). They were + causing the resulting findfirst/findnext DTA structures to be + incompatible with MSDOS's. +* Also rewrote all the pattern copying code in `dos_findfirst' in + `kernel/fatdir.c' to prevent a bad buffer overflow problem. +* Modified the disk buffer handling code, so that logical sector + numbers in disk buffers are now 0-based instead of 1-based. +* int 0x25 and int 0x26 now do multi-sector reads/writes. + +1999 Jul 14 - Build 2012 +-------- ror4 (ror4@iname.com) +* Ported the modules in the `drivers/' branch to `nasm'. + +1999 May 04 - Build 2011 +-------- ror4 (ror4@cryogen.com) +* Fixed the code for converting day numbers into Julian calendar + dates: the first and last days of each month are now returned + correctly. +* Undid a change to the code to get the day of the week. + +1999 May 02 - Build 2011 +-------- John Price (linux-guru@gcfl.net) +* blockio.c: changed getblock and getbuf so that they leave at least + 3 FAT type buffers valid. This helps because the FAT is accessed + very often compared to other sectors. +* fatfs.c: Fixed a bug in map_cluster so it will optimize FAT reads + on disks that have more than one sector per cluster. This + sigificantly improved disk access of big files on hard drives. + +1999 May 02 - Build 2011 +-------- ror4 (ror4@cryogen.com) +* Corrected the `struct buffer' definition in `kernel/globals.h' so + that it corresponds exactly to Ralf Brown's description of a DOS 3.x + buffer. +* Also fixed the problem with FATs > 255 sectors, by making use of an + originally unused field in the buffer structure. + +1999 May 01 - Build 2011 +-------- ror4 (ror4@cryogen.com) +* Fixed a problem which caused disk corruption on partitions with + FATs larger than 127 sectors. (However, FATs larger than 255 + sectors may still experience problems -- this is due to a + limitation of the DOS 3.x buffering scheme.) +* Fixed a bug in the handling of the `stacks=' command in + `(fd)config.sys' which caused the system to behave strangely. + +1999 Apr 22 - Build 2011 +-------- Steffen Kaiser (Steffen.Kaiser@fh-rhein-sieg.de) +bugfix: memmgr.c: Invalid returned largest size in MemLargest() +fix: memmgr.c: DosMemLargest: change prototype to match its useage +bugfix: inthdlr.c: 0x49: ES is decremented +fix: inthdlr.c: 0x00: DosMemCheck() does nothing --> added panic() +fix: inthdlr.c: 0x4c: DosMemCheck() does nothing --> added panic() +fix: inthdlr.c: 0x00: changed to make it the same as DOS-4C-00 + Both actions differed e.g. in ErrorMode +chg: memmgr.c: the 'name' field of the MCB is never initialized by + DOS-48, DOS-49 or DOS-4A. Leave this to the program loading function. +bugfix: memmgr.c: adjust_far() / add_far(): + Both function together (and the way they are used) don't make sense: + adjust_far() normalizes a far pointer, add_far() generates a linear + address. Usually both are used this way: + far_poi = adjust_far(far_poi); + while(...) { + ... + far_poi = add_far(far_poi, uword); + ... + } + First one makes sure that 'far_poi' is normalized, then far_poi + becomes a linear address, which makes it very difficult to use + it, because the possibility to get a segment warp gets very high. + --> + Change: add_far() also returns a normalized real mode pointer + as adjust_far() does. + Probably in DOS-C supporting various architecures thee functions + served other duties, but the current useage is highly dangerous. +bugfix: task.c: ChildEnv(): nEnvSize didn't counted the last '\0' +bugfix: task.c: ChildEnv(): Allocation: maximum absolute filename to + short and forgot the word counter +bugfix: task.c: ChildEnv(): for very corrupt environments, the + copy function failed. +bugfix: task.c: DosExeLoader(): If exe_size > allocated_size or + DosMemLargest() failes, the environment is not deallocated +bugfix: task.c: DosExeLoader(): Calculating the exe_size to be + allocated. At both places (+ header.exMinAlloc & ...MaxAlloc) + sizeof(psp) is added to exe_size. Why? image_size already + contains sizeof(psp). +chg: task.c: DosExeLoader()/DosComLoader(): MCB patching and command + line copying is no outside of those functions +chg: asmsupt.asm: _fbcopy: re-use parts of _bcopy +add: asmsupt.asm: fmemset, fmemclr, fmemclra {Replace the explicit + for() loops} + +1999 Apr 22 - Build 2011 +-------- ror4 (ror4@cryogen.com) +* Ported boot.asm to NASM. The plan is to port all assembly to NASM + over time. + +1999 Apr 19 - Build 2010 +-------- John Price (linux-guru@gcfl.net) +* Undid the change I made to getblock below because it DID NOT speed +anything up, and in fact slowed access down. + +1999 Apr 18 - Build 2009 +-------- John Price (linux-guru@gcfl.net) +* change getblock so that it flushes all buffers for a drive when it + has to flush one of them to make room. This should speed disk + access slightly. +* Change the boot sector so there is a compile-time option to use + multi-sector IO or single-sector IO. The default is multi since + ror4 seemed to have fixed the problem we had before. + +1999 Apr 18 - Build 2009 +-------- ror4 (ror4@cryogen.com) +* The boot sector can now load the kernel properly from a hard disk. +* Other minor changes. + +1999 Apr 16 - Build 2008 +-------- ror4 (ror4@cryogen.com) +* Modified the block device driver to prepare it for multi-sector I/O + support. Among other things, the driver can now handle transfer + buffers which cross DMA boundaries. +* Some other minor changes. + +1999 Apr 15 - Build 2008 +-------- John Price (linux-guru@gcfl.net) +* Changed mainly the map_cluster function in fatfs.c so that instead + of starting at the beginning of the FAT chain every time, it will + be smart about it, and start at the last FAT location that it was + before if it can. This speeds up disk access considerably + especially on slower machines. + +1999 Apr 15 - Build 2008 +-------- Steffen Kaiser (Steffen.Kaiser@fh-rhein-sieg.de) +bugfix: ^Break handler according cmt1.txt +bugfix: DosCreat(): Detection for Devices and extension: + the semi-colon behind if(*froot) is definitely wrong, whether + one wants CON.EXT to be interpreted as CON or not. +bugfix: DosOpen(): dito + +* Re-implementation of ^Break handler -- 1999/03/27 ska + + Warning: The handle_break() function assumes that the InDOS flag + was incremented (except if ErrorMode is true). Never call + handle_break() unless the InDOS flag has been incremented within + this reentrant call of DOS. + + + ^Break is detected and handled at certain places within the + kernel only: a) within the CON: device when reading or writing a + character, and b) when entering the INT-21 service (if extended + break checking is enabled). At these places the process flow can + be modified to: either a) redo the interrupted function or b) abort + the currently running process. + + + Both actions are performed by switching back to the user stack + and enter INT-21 handler again. If to terminate the program, AX is + modified into 4C00h. + + + By default, if the user has no ^Break handler installed, the + program is terminated. + + + Heavy change: The original implementation installed an unique + INT-23 handler that directly called the actions performed + DOS-4C-XX. In fact, this was identically with when the user had an + own handler installed and returned the Carry flag set, except that + it was somewhat quicker, because the kernel need not decode the + 4C00h command. Now the Carry flag is set prior the call of INT-23, + so the default action is to terminate the program. + + + Note: INT-23 is called with all registers as they are passed to + the INT-21 entry. When they are modified, they are passed + _modified_ to the API interpreter. This also allows the DOS1-style + termination by to load register AH with 0 (zero). + + + RBIL says: + "any DOS call may safely be made within the INT 23 handler, + although the handler must check for a recursive invocation if it + does call DOS" + This can be interpreted so or so, the problem is that the user can + call DOS again, what would overwrite the saved _usr_stack pointer + with a different value and, therefore, cannot be used to check if + INT-23 was returned by RETF or RETF2/IRET. + + Because a recursive invokation of INT-23 is to prevented by the + user, the kernel could internally save SP to somewhere else. + However: + a) where? + b) is it reliable that the user ever returns from INT-23 at all? + + The implemented method uses the same mechanism as fail-safe intr() + function is implemented: A little piece of code is constructed + within the stack, which contains the value of SP as an operand of + an immediate MOV instruction. + + +1999 Apr 13 - Build 2007 +-------- ror4 (ror4@cryogen.com) +* The boot sector now moves itself to the last 512 bytes of + conventional memory instead of a lower memory location. +* The kernel startup code has also been modified so that it works + with the new boot sector. + +1999 Apr 12 - Build 2007 +-------- ror4 (ror4@cryogen.com) +* The directory scanning functions (`findfirst'/`findnext') now also + recognize more flavours of the volume label attribute byte (namely + 0x09, 0x28 and 0x29). +* Subdirectories are now no longer assumed to have the same size as + the root directory. +* `device/device.lib' is now included as a dependency in the kernel + makefile. +* Removed several unused assembler modules from the `device/' branch + (see `device/device.mak'). + +1999 Apr 11 - Build 2007 +-------- ror4 (ror4@cryogen.com) +* The kernel now reads times from the system clock (0x40:0x6c) + instead of the RTC. The RTC is only used during startup to + initialize the system clock. (As a side effect of this, + `ReadATClock' has been moved from `_TEXT' to `INIT_TEXT'.) +* Checking for leap years is now improved -- year numbers which are + divisible by 100 but not by 400 are not counted as leap years. (Not + that it matters for year 2000, though.) +* The scaling factor used to convert the system time count to a + second count has been changed from 18.2 to the more accurate (?) + 19663/1080. +* Day numbers used by `clock$' are now 0-based (as in MSDOS) instead + of 1-based. Thus 1 Jan 1980 is now day number 0. + +1999 Apr 10 - Build 2007 +-------- ror4 (ror4@cryogen.com) +* Added code to prevent the kernel from returning path names + containing double backslashes. + +1999 Apr 9 - Build 2007 +-------- ror4 (ror4@usa.net) +* File handles are now cloned properly when a child process is spawned. +* The `DosClose' function now also frees SFT entries corresponding to + devices, not only those entries corresponding to files. +* Removed a (minor) memory corruption bug in the code for int 0x21, + ah = 0x09. + +1999 Apr 6 - Build 2007 +-------- ror4 (ror4@cryogen.com) +* Functions ax = 0x5700 and 0x5701 (get/set file date and time) now + return the right values at the right times. (They used to return + success when there's an error, and return error when there's a + success.) +* Removed the `/k' switch to the linker in `sys/sys.mak'. + +1999 Apr 4 - Build 2006 +-------- John Price (linux-guru@gcfl.net) +* added "version=" directive so that you can change the version that + the kernel reports. Usage: version=. (i.e. + version=6.22) + +1999 Apr 4 - Build 2006 +-------- ror4 (ror4@usa.net) +* Fixed the file name parsing function (`ParseDosNames') so that it + handles single-character path names correctly. +* Also modified the functions which call `ParseDosNames' to check its + return value instead of assuming that it is always successful. + (This is not currentl useful, but it will be when error checking is + introduced into `ParseDosNames'. In other words, there'll be more + changes to `ParseDosNames' in the near future...) + +* After wondering for a long time why the kernel text segment was + always getting corrupted when I ran DJGPP `bash' 1.14.7, I finally + decided to examine the code occurring before the handler for int + 0x21, ah = 0x60, and I found out why... :) +* Fixed the problem of int 0x21, ax = 0x5d06 causing memory + corruption. +* Corrected the types of `internal_data', `swap_always' and + `swap_indos' in `kernel/globals.h'. + +* Improved checking for invalid file names in `ParseDosName' + (although I'm still not sure whether the check is water-tight or + not). +* Changed the default path setting from `PATH=' to `PATH=.'. + +* Output from character I/O functions now goes to standard output as + it should, instead of the console. Also, there's now a clear + distinction between console input/output and standard input/output. +* Tabs are now expanded during writes to the console device. +* Removed a hard-wired limit on the number of entries in a JFT. + (Although I'm not sure whether this is really correct...) +* Many other changes to the file descriptor handling code. + +1999 Mar 29 - Build 2006 +-------- John Price (linux-guru@gcfl.net) +* Changed boot loader so it prints some feedback info while booting. + Removed code to handle FAT12 and FAT16, and code to calculate the + start of the fat, rootdir, and data. Moved these functions into + the sys command. Now there are two versions of the boot loader + created, one to handle FAT16, and one for FAT12. These are + hard-coded into the sys command, so the need for the boot.bin file + is obsolete. +* created a new program (bin2c) to convert the boot loader binary + file into a header file that can be included in the sys program as + an array of bytes. + +1999 Mar 29 - Build 2006 +-------- ror4 (ror4@usa.net) +* Changed the class of `_BSSEND' from "STACK" to "BSS" in the + `drivers/' branch (which I forgot about in my last patch). +* Removed all traces of the `CONST' segment, since it was causing + `IGROUP' to be assimilated into `DGROUP', which shouldn't happen. +* Added a `(void)' cast to the `setvec' macro in `kernel/globals.h' + (`setvec' no longer returns the original ISR vector). +* Changed an incorrect error message in `sys/sys.c'. +* Removed `drivers/setvec.asm', since it's no longer needed. +* Also removed `kernel/krnstart'. +* The name field in a process's MCB is now filled in the same manner + as in MSDOS -- instead of being padded to the right with spaces, it + is now terminated with '\0'. Also, if the original file name + doesn't have an extension, the code will stop copying the file name + at '\0' instead of continuing to look for a '.'. +* Fixed the problem of the `switchar' syscall (int 0x21, ax = 0x3700) not + returning the correct value. + + +1999 Mar 28 - Build 2005 +-------- ror4 (ror4@usa.net) +* Removed the need for `ipl.sys'. (!) The kernel makefile now + statically relocates `kernel.exe' to 0x60:0 and outputs the + resulting binary to `kernel.sys', and the boot sector has also been + modified to load `kernel.sys' at 0x60:0 instead of `ipl.sys' at + 0x2000:0. (I chose 0x60:0 because it's the first 512-byte boundary + occurring after the BIOS data area, 0x40:0.) Finally, `sys.com' has + also been updated. + +* Also changed the boot sector code in some other ways. In + particular, because `kernel.sys' is rather large, I had to add some + code to move the boot sector away from 0:0x7c00 to somewhere + higher. (For 640K systems the boot sector will be shifted to + 0x6000:0x7c00. However, there may be problems on systems with very + little conventional memory -- I'll probably look into this later.) + +* Made some minor changes to the assembler source files so that they + can compile on `masm'. (JP: The code still compiles fine with tasm + too). + +* Also changed several incorrect label references in the assembler + sources. (JP: These changes fixed the "Fixup" errors we been + talking about in the list) + +* Eliminated redundant re-makes of files in the various makefiles. + For one thing, `*.cfg' files are no longer generated from the + makefiles, but are independent from them. (I didn't like the idea + of having to compile an entire branch each time I edit a + makefile...) Also, intermediate files are now retained instead of + deleted. + +* Also made some changes to `build.bat' (you'll know them when you + see them). + +* Added a file `lib/libm.mak' + +* Added a file `kernel/krnstart + +* The code required to initialize the kernel (or rather most of it) + is no longer retained in memory after the initialization process is + done. I accomplished this by moving most of the initialization code + from `_TEXT' to a new segment named `INIT_TEXT'. Of course, I also + had to introduce lots of other changes in order for everything to + compile and run properly: + - Added code to `kernel/src/kernel/kernel.asm' to move the contents + of `INIT_TEXT' to the top of conventional memory and continue + from there. Control is only transferred back to `_TEXT' when the + kernel calls `p_0'. + - Many functions are called from both `_TEXT' and `INIT_TEXT'. To + fix this, I created far wrappers for these functions which can + then be called from `INIT_TEXT'. (E.g. for `execrh' there's a + corresponding far function named `init_call_execrh' which simply + calls `execrh' with its own parameters.) One exception to this is + `printf' -- instead of creating a far wrapper for a near + `printf', I created a near wrapper for a far `printf' (now called + `init_call_printf'), because it was easier that way. :) + - Most functions which are required only during initialization time + were shifted into `INIT_TEXT'. (There are still some functions + which should rightfully go into `INIT_TEXT', but are retained in + `_TEXT' as far functions, because I found it too difficult to + move them out. :( ) Because Turbo C only allows at most one code + segment to be defined for each module, I had to shift some + functions around within the source tree -- the file + `kernel/src/kernel/proto.h' says it all. + - A cosmetic change mentioned here for completeness: all functions + defined in `INIT_TEXT' are now marked with the word `INIT' (in + fact a null macro) so that the reader can easily distinguish them + from functions defined in `_TEXT'. + +* Replaced `exit' calls with `for (;;);'. + +* Changed `strcpy' into a macro which calls `scopy'. + +* Also redefined `setvec' to be a macro (I didn't want to waste time + writing a far wrapper for it). + +* Removed the `break_key' function in `kernel/src/kernel/kernel.asm'. + +* `low_int25_handler' and `low_int26_handler' are now of type + `void interrupt far()' instead of `void near()'. (I hope I updated + `entry.asm' correctly -- I never tested `int 0x25' and `int 0x26'...) + +* Changed the class of `_BSSEND' from "STACK" to "BSS" -- "STACK" is + now used for a separate stack segment (`_STACK'). + +* Assembler modules now include `segs.inc' instead of having their + own long list of segment definitions. (Some day I'll update the + makefile dependencies to reflect this.) + +* Also made a few minor changes to the assembler modules so that + `masm' won't complain. + +* Changed the `-X' switch in `kernel.cfg' to `-X-', so that I don't + have to worry about C module dependencies. + +* Removed the definition of `CFLAGS' from the makefile -- everything + is now in `kernel.cfg'. + +* Created a file `kernel/src/kernel/init-mod.h' which is included by + modules whose code is supposed to go into `INIT_TEXT' instead of + `TEXT'. + +* This diff solves the problem of the MCB of a process not having a + correct value in its name field (bug report #6). + (The definition of the `toupper' macro is because I shifted the + `toupper' function into `INIT_TEXT' a while ago, and therefore + can't be called from `_TEXT' now...) + + +-------- John Price (linux-guru@gcfl.net) +* Made changes so you can create a directory with the same name as a + volume label, but you still can't rename or delete it! + +* Fix findfirst and findnext functions so that act as they should. + (i.e. If the attrib has only the volume label set, then it returns + the volume label entry in the root directory, else it returns the + files/directories that are specified with the attrib, ignoring the + read-only and archive bits (these are always returned). + +* reorginize the source tree. Removed IPL directory, and command. + Moved all the file system C files into the kernel directory. + Modifed build.bat, clean.bat, and all the make files to reflect the + new tree. + +* changed so that kernel will look for a "fdconfig.sys" file, and use + it INSTEAD of config.sys. If it does not find it, it will look + for, and read config.sys, if it exists. + +* Fixed so that if you call an INT 21 function with AH containing a + unsupported function, the carry flag is set. diff --git a/docs/intfns.txt b/docs/intfns.txt new file mode 100644 index 0000000..579e3f3 --- /dev/null +++ b/docs/intfns.txt @@ -0,0 +1,209 @@ + Technical Data + DOS-C Systems Calls + +The following table represents the industry standard kernel DOS calls +currently supported by DOS-C. This list is for Release 1.1, build +2003 as issued on Feb 28, 1999. + +int 20: Terminated Current Process + Supported + +int 21: DOS System Call + Supported. See table below. + +int 21 Description State Ver Status +--------------------------------------------------------------------------- +00h Terminate Program superseded 1.00 supported +01h Read Keyboard with Echo superseded 1.00 supported +02h Display Character superseded 1.00 supported +03h Auxilliary Input superseded 1.00 Note 1 +04h Auxilliary Output superseded 1.00 Note 1 +05h Print Character superseded 1.00 Note 1 +06h Direct Console I/O active 1.00 supported +07h Direct Console Input active 1.00 supported +08h Read Keyboard Without Echo active 1.00 supported +09h Display String superseded 1.00 supported +0ah Buffered Keyboard Input superseded 1.00 supported +0bh Check Keyboard Status active 1.00 supported +0ch Flush Buffer, Read Keyboard active 1.00 supported +0dh Reset Drive active 1.00 supported +0eh Set Default Drive active 1.00 supported +0fh Open File with FCB superseded 1.00 supported +10h Close File with FCB superseded 1.00 supported +11h Find First File with FCB superseded 1.00 supported +12h Find Next File with FCB superseded 1.00 supported +13h Delete File with FCB superseded 1.00 supported +14h Sequential Read superseded 1.00 supported +15h Sequential Write superseded 1.00 supported +16h Create File with FCB superseded 1.00 supported +17h Rename File with FCB superseded 1.00 supported +18h CP/M compatibility obsolete 1.00 supported +19h Get Default Drive active 1.00 supported +1ah Set Disk Transfer Address active 1.00 supported +1bh Get Default Drive Data superseded 2.00 supported +1ch Get Drive Data superseded 2.00 supported +1dh CP/M compatibility obsolete 1.00 supported +1eh CP/M compatibility obsolete 1.00 supported +1fh Get Default DPB active 5.00 Note 2 +20h CP/M compatibility obsolete 1.00 supported +21h Random Read superseded 1.00 supported +22h Random Write superseded 1.00 supported +23h Get File Size superseded 1.00 supported +24h Set Random Record Number superseded 1.00 supported +25h Set Interrupt Vector active 1.00 supported +26h Create New PSP superseded 1.00 supported +27h Random Block Read superseded 1.00 supported +28h Random Block Write superseded 1.00 supported +29h Parse Filename active 1.00 supported +2ah Get Date active 1.00 supported +2bh Set Date active 1.00 supported +2ch Get Time active 1.00 supported +2dh Set Time active 1.00 supported +2eh Set/Reset Verify Flag active 1.00 supported +2fh Get DTA active 2.00 supported +30h Get Version Number active 2.00 supported +31h Keep Program active 2.00 supported +32h Get DPB active 5.00 Note 2 +3300h Get CTRL+C Check Flag active 2.00 supported +3301h Set CTRL+C Check Flag active 2.00 supported +3305h Get Startup Drive active 2.00 supported +3306h Get MS-DOS Version active 5.00 supported +33ffh Get DOS-C Release superset supported +34h Get InDOS Flag Address active 2.00 supported +35h Get Interrupt Vector active 2.00 supported +36h Get Disk Free Space active 2.00 supported +37h Get/Set Switchar undocumented 2.00 supported +38h Get/Set Country Information active 2.00 supported +39h Create Directory active 2.00 supported +3ah Remove Directory active 2.00 supported +3bh Change Current Directory active 2.00 supported +3ch Create File with Handle active 2.00 supported +3dh Open File with Handle active 2.00 supported +3eh Close File with Handle active 2.00 supported +3fh Read File or Device active 2.00 supported +40h Write File or Device active 2.00 supported +41h Delete File active 2.00 supported +42h Move File Pointer active 2.00 supported +4300h Get File Attributes active 2.00 supported +4301h Set File Attributes active 2.00 supported +44h Ioctl entry active 2.00 supported +45h Duplicate File Handle active 2.00 supported +46h Force Duplicate File Handle active 2.00 supported +47h Get Current Directory active 2.00 supported +48h Allocate Memory active 2.00 supported +49h Free Allocated Memory active 2.00 supported +4ah Set Memory Block Size active 2.00 supported +4b00h Load and Execute Program active 2.00 supported +4b01h Load Program active 5.00 supported +4b03h Load Overlay active 2.00 supported +4b05h Set Execution State active 5.00 planned +4ch End Program active 2.00 supported +4dh Get Child-Program Return Value active 2.00 supported +4eh Find First File active 2.00 supported +4fh Find Next File active 2.00 supported +50h Set PSP Address active 2.00 supported +51h Get PSP Address active 2.00 supported +52h Get List of Lists undocumented 2.00 supported +53h undocumented not supported +54h Get Verify State active 2.00 supported +55h Create New Psp undocumented 2.00 supported +56h Rename File active 2.00 supported +5700h Get File Date and Time active 2.00 supported +5701h Set File Date and Time active 2.00 supported +5800h Get Allocation Strategy active 3.00 supported +5801h Set Allocation Strategy active 3.00 supported +5802h Get Upper-Memory Link active 5.00 planned +5803h Set Upper-Memory Link active 5.00 planned +59h Get Extended Error active 3.00 planned +5ah Create Temporary File active 3.00 +5bh Create New File active 3.00 +5ch Lock/Unlock File active 3.10 planned +5d00h Server Function Call active 3.10 planned +5d01h Commit All Files active 3.10 planned +5d02h Close File by Name active 3.10 planned +5d03h Close All Files for Computer active 3.10 planned +5d04h Close All Files for Process active 3.10 planned +5d05h Get Open File List active 3.10 planned +5d06h Get Multiple SDA active 4.00 supported +5d07h Get Redirected Printer Mode active 3.10 planned +5d08h Set Redirected Printer Mode active 4.00 planned +5d09h Flush Redirected Printer Output active 4.00 planned +5d0ah Set Extended Error active 4.00 planned +5eh Generic Network Functions #1 active 3.10 planned +5fh Generic Network Functions #2 active 3.10 planned +60h Truename function undocumented 3.00 supported +61h UNUSED obsolete supported +62h Get current PSP active 3.00 supported +63h Multibyte char ops undocumented 3.20 Note 4 +64h ? undocumented returns error +65h NLS Functions active 3.30 supported +66h Code Page Functions active 3.30 supported +67h Set Maximum Handle Count active 3.30 supported +68h Commit File active 3.30 dummy func +69h GET/SET DISK SERIAL NUMBER active 4.00 not supported +6ah COMMIT FILE (same as 68h) active 4.00 not supported +6bh NULL FUNCTION active 5.00 not supported +6ch Extended Open/Create active 4.00 not supported +71h LONG FILENAME FUNCTIONS active 7.00 not supported + +int 22: Program Termination Address. + Supported. + +int 23: Ctrl-C/Ctrl_Break Handler. + Supported. + +int 24: Critical Error Handler + Dummy routine default. + +int 25: Absolute Disk Read + Supported. + +int 26: Absolute Disk Write + Supported. + +int 27: TSR + Supported. + +int 28: DOS Idle. + Note 5. + +int 29: Fast Console Output. + Supported. + +int 2F: DOS Multiplex. + Supported. + +Notes: +Note 1 - Although this system call is supported, there are no device +drivers to support these devices in this release. + +Note 2 - Returns error code because internal data structures differ. + +Note 3 - Only sub-functions 0 and 1 are currently supported. + +Note 4 - Returns error code. + +Note 5 - Vector supported but performs no action. + +License +------- +See COPYING in DOS-C root directory for license. + + +--------------------------------------------------------------------- + +$Id$ + +$Log$ +Revision 1.1 2000/05/06 19:34:43 jhall1 +Initial revision + +Revision 1.1 1999/08/25 03:46:42 jprice +New build config + +Revision 1.1.1.1 1999/03/29 15:39:16 jprice +New version without IPL.SYS + +Revision 1.2 1999/03/02 06:55:51 jprice +Updated interrupt list + diff --git a/docs/mkboot.txt b/docs/mkboot.txt new file mode 100644 index 0000000..73be5d6 --- /dev/null +++ b/docs/mkboot.txt @@ -0,0 +1,11 @@ +To create a bootable floppy suitable for copying the system to +another drive: + +1. Change directory (if necessary) to where the FreeDOS Kernel BIN +directory. + +3. Enter the command "install" to transfer the system files to the +diskette in drive A. If you want to install on drive B, type +"install b:" + +4. Write protect this disk and use it to boot from. diff --git a/docs/readme.cvs b/docs/readme.cvs new file mode 100644 index 0000000..de51b31 --- /dev/null +++ b/docs/readme.cvs @@ -0,0 +1,15 @@ +You can check out the latest code (from a UNIX type machine) using +CVS as follows: + +cvs -d :pserver:guest@gcfl.net:/home/cvsroot login +Password: guest + +Then, to get the kernel code: +cvs -d :pserver:guest@gcfl.net:/home/cvsroot checkout fdkernel + +To get the FreeCom code: +cvs -d :pserver:guest@gcfl.net:/home/cvsroot checkout FreeCom + + +You can also view the CVS code from the web at +http://www.gcfl.net/cgi-bin/cvsweb diff --git a/drivers/devend.asm b/drivers/devend.asm new file mode 100644 index 0000000..0b890ed --- /dev/null +++ b/drivers/devend.asm @@ -0,0 +1,78 @@ +; +; File: +; devend.asm +; Description: +; get end of device driver primitive +; +; Copyright (c) 1995 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/dos-c/src/drivers/devend.asv $ +; +; $Header$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:34:43 jhall1 +; Initial revision +; +; Revision 1.3 1999/08/10 17:21:08 jprice +; ror4 2011-01 patch +; +; Revision 1.2 1999/03/29 17:08:31 jprice +; ror4 changes +; +; Revision 1.1.1.1 1999/03/29 15:40:22 jprice +; New version without IPL.SYS +; +; Revision 1.2 1999/01/22 04:16:39 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:00 jprice +; Imported sources +; +; +; Rev 1.2 29 Aug 1996 13:07:14 patv +;Bug fixes for v0.91b +; +; Rev 1.1 01 Sep 1995 18:50:34 patv +;Initial GPL release. +; +; Rev 1.0 02 Jul 1995 7:56:50 patv +;Initial revision. +; + +group TGROUP _TEXT +group DGROUP _DATA + +segment _DATA align=2 class=DATA + extern last:wrt DGROUP + +segment _TEXT class=CODE + + global _device_end + +_device_end: + push bp + mov bp,sp + mov ax,last + mov dx,DGROUP + pop bp + ret diff --git a/drivers/device.mak b/drivers/device.mak new file mode 100644 index 0000000..0448248 --- /dev/null +++ b/drivers/device.mak @@ -0,0 +1,103 @@ +# +# makefile for device.lib +# +# $Id$ +# + +# $Log$ +# Revision 1.1 2000/05/06 19:34:43 jhall1 +# Initial revision +# +# Revision 1.6 1999/08/25 03:16:36 jprice +# ror4 patches to allow TC 2.01 compile. +# +# Revision 1.5 1999/08/10 17:21:08 jprice +# ror4 2011-01 patch +# +# Revision 1.4 1999/04/23 03:44:52 jprice +# Improved by jprice +# +# Revision 1.3 1999/04/13 15:47:07 jprice +# no message +# +# Revision 1.2 1999/03/29 17:08:31 jprice +# ror4 changes +# +# Revision 1.1.1.1 1999/03/29 15:40:23 jprice +# New version without IPL.SYS +# +# Revision 1.3 1999/02/09 04:49:25 jprice +# Make makefile use common config.mak file +# +# Revision 1.2 1999/01/22 04:16:39 jprice +# Formating +# +# Revision 1.1.1.1 1999/01/20 05:51:00 jprice +# Imported sources +# +# +# Rev 1.2 29 Aug 1996 13:07:12 patv +#Bug fixes for v0.91b +# +# Rev 1.1 19 Feb 1996 3:19:26 patv +#Added NLS, int2f and config.sys processing +# +# Rev 1.0 02 Jul 1995 7:54:52 patv +#Initial revision. +# + +!include "..\config.mak" + + +# MICROSOFT C +# ----------- +#MODEL = s +#CFLAGS = /c /Gs /A$(MODEL) +#AFLAGS = /Mx /Dmem$(MODEL)=1 +#TERM = ; + +# BORLAND C +# ----------- +MODEL = s +CFLAGS = -c -m$(MODEL) +AFLAGS = /Mx /Dmem$(MODEL)=1 +LIBFLAGS = /c +TERM = + +OBJS = devend.obj floppy.obj getvec.obj timer.obj rdpcclk.obj rdatclk.obj \ +wrpcclk.obj wratclk.obj + +LIBOBJS= +devend +floppy +getvec +timer +rdpcclk +rdatclk +wrpcclk +wratclk + + + +# Build the LIBRARY +# ----------------- +all: production + +production: ..\lib\device.lib + +..\lib\device.lib: device.lib + copy device.lib ..\lib + +clobber: clean + $(RM) device.lib status.me ..\lib\device.lib + +clean: + $(RM) *.obj *.bak *.crf *.xrf *.map *.lst + +device.lib : $(OBJS) + del device.lib + $(LIBUTIL) $(LIBFLAGS) device $(LIBOBJS) $(TERM) + + + +# RULES (DEPENDENCIES) +# ---------------- +.c.obj : + $(CC) $(CFLAGS) $< + +.asm.obj : + $(NASM) -f obj $< + + diff --git a/drivers/floppy.asm b/drivers/floppy.asm new file mode 100644 index 0000000..d4ea2aa --- /dev/null +++ b/drivers/floppy.asm @@ -0,0 +1,331 @@ +; +; File: +; floppy.asm +; Description: +; floppy disk driver primitives +; +; Copyright (c) 1995 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/usr/patv/dos-c/src/drivers/floppy.asv $ +; +; $Id$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:34:45 jhall1 +; Initial revision +; +; Revision 1.4 1999/08/10 17:21:08 jprice +; ror4 2011-01 patch +; +; Revision 1.3 1999/04/16 21:29:17 jprice +; ror4 multi-sector IO +; +; Revision 1.2 1999/03/29 17:08:31 jprice +; ror4 changes +; +; Revision 1.1.1.1 1999/03/29 15:40:24 jprice +; New version without IPL.SYS +; +; Revision 1.4 1999/02/14 04:25:16 jprice +; Added functions to check if a floppy disk has been changed. +; +; Revision 1.3 1999/02/08 05:49:47 jprice +; Added Pat's 1937 kernel patches +; +; Revision 1.2 1999/01/22 04:16:39 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:00 jprice +; Imported sources +; +; Rev 1.3 06 Dec 1998 8:43:00 patv +;New floppy support functions. +; +; Rev 1.2 29 Aug 1996 13:07:14 patv +;Bug fixes for v0.91b +; +; Rev 1.1 01 Sep 1995 18:50:34 patv +;Initial GPL release. +; +; Rev 1.0 02 Jul 1995 7:57:02 patv +;Initial revision. +; + +group TGROUP _TEXT + +segment _TEXT class=CODE + +; +; +; Reset both the diskette and hard disk system +; +; BOOL fl_reset(WORD drive) +; +; returns TRUE if successful +; + + global _fl_reset +_fl_reset: + mov bx,sp + mov ah,0 ; BIOS reset disketter & fixed disk + mov dl,[bx+2] + int 13h + + jc fl_rst1 ; cy==1 is error + mov ax,1 ; TRUE on success + ret + +fl_rst1: xor ax,ax ; FALSE on error + ret + + +; +; +; Read DASD Type +; +; COUNT fl_readdasd(WORD drive) +; +; returns 0-3 if successful, 0xFF if error +; +; Code Meaning +; 0 The drive is not present +; 1 Drive present, cannot detect disk change +; 2 Drive present, can detect disk change +; 3 Fixed disk +; + + global _fl_readdasd +_fl_readdasd: + push bp + mov bp,sp + + mov dl,[bp+4] ; get the drive number + mov ah,15h ; read DASD type + int 13h + + jc fl_rdasd1 ; cy==1 is error + mov al,ah ; for the return code + xor ah,ah + pop bp ; C exit + ret + +fl_rdasd1: mov ah,0 ; BIOS reset disketter & fixed disk + int 13h + mov ax,0FFh ; 0xFF on error + pop bp ; C exit + ret + + +; +; +; Read disk change line status +; +; COUNT fl_diskchanged(WORD drive) +; +; returns 1 if disk has changed, 0 if not, 0xFF if error +; + + global _fl_diskchanged +_fl_diskchanged: + push bp ; C entry + mov bp,sp + + mov dl,[bp+4] ; get the drive number + mov ah,16h ; read change status type + int 13h + + jc fl_dchanged1 ; cy==1 is error or disk has changed + xor ax,ax ; disk has not changed + pop bp ; C exit + ret + +fl_dchanged1: cmp ah,6 + jne fl_dc_error + mov ax,1 + pop bp ; C exit + ret + +fl_dc_error: mov ax,0FFh ; 0xFF on error + pop bp ; C exit + ret + + +; +; Read the disk system status +; +; COUNT fl_rd_status(WORD drive) +; +; Returns error codes +; +; See Phoenix Bios Book for error code meanings +; + + global _fl_rd_status +_fl_rd_status: + push bp ; C entry + mov bp,sp + + mov dl,[bp+4] ; get the drive number + mov ah,1 ; read status + int 13h + + mov al,ah ; for the return code + xor ah,ah + + pop bp ; C exit + ret + + +; +; Read Sectors +; +; COUNT fl_read(WORD drive, WORD head, WORD track, WORD sector, WORD count, BYTE FAR *buffer); +; +; Reads one or more sectors. +; +; Returns 0 if successful, error code otherwise. +; + global _fl_read +_fl_read: + push bp ; C entry + mov bp,sp + + mov dl,[bp+4] ; get the drive (if or'ed 80h its + ; hard drive. + mov dh,[bp+6] ; get the head number + mov ch,[bp+8] ; cylinder number (lo only if hard) + mov al,[bp+9h] ; get the top of cylinder + xor ah,ah + mov cl,6 ; form top of cylinder for sector + shl ax,cl + mov cl,[bp+0Ah] ; sector number + and cl,03fh ; mask to sector field bits 5-0 + or cl,al ; or in bits 7-6 + mov al,[bp+0Ch] + les bx,[bp+0Eh] ; Load 32 bit buffer ptr + + mov ah,2 + int 13h ; read sectors to memory es:bx + + mov al,ah + jc fl_rd1 ; error, return error code + xor al,al ; Zero transfer count +fl_rd1: + xor ah,ah ; force into < 255 count + pop bp + ret + + +; +; Write Sectors +; +; COUNT fl_write(WORD drive, WORD head, WORD track, WORD sector, WORD count, BYTE FAR *buffer); +; +; Writes one or more sectors. +; +; Returns 0 if successful, error code otherwise. +; + global _fl_write +_fl_write: + push bp ; C entry + mov bp,sp + + mov dl,[bp+4] ; get the drive (if or'ed 80h its + ; hard drive. + mov dh,[bp+6] ; get the head number + mov ch,[bp+8] ; cylinder number (lo only if hard) + mov al,[bp+9h] ; get the top of cylinder + xor ah,ah + mov cl,6 ; form top of cylinder for sector + shl ax,cl + mov cl,[bp+0Ah] ; sector number + and cl,03fh ; mask to sector field bits 5-0 + or cl,al ; or in bits 7-6 + mov al,[bp+0Ch] + les bx,[bp+0Eh] ; Load 32 bit buffer ptr + + mov ah,3 + int 13h ; write sectors from mem es:bx + + mov al,ah + jc fl_wr1 ; error, return error code + xor al,al ; Zero transfer count +fl_wr1: + xor ah,ah ; force into < 255 count + pop bp + ret + + +; +; SUBROUTINE +; + + global _fl_verify +_fl_verify: + push bp + mov bp,sp + mov dl,[bp+4] + mov dh,[bp+6] + mov ch,[bp+8] + mov cl,[bp+0Ah] + mov al,[bp+0Ch] + mov ah,4 + int 13h ; Disk dl=drive a: ah=func 04h + ; verify sectors with mem es:bx + mov al,ah + jc fl_ver1 ; Jump if carry Set + xor al,al ; Zero register +fl_ver1: + xor ah,ah ; Zero register + pop bp + ret + + + global _fl_format +_fl_format: + + xor ax,ax + ret + + +; +; +; Get number of disks +; +; COUNT fl_nrdrives(VOID) +; +; returns AX = number of harddisks +; + + global _fl_nrdrives +_fl_nrdrives: + push di ; di reserved by C-code ??? + + mov ah,8 ; DISK, get drive parameters + mov dl,80h + int 13h + mov ax,0 ; fake 0 drives on error + jc fl_nrd1 + mov al,dl +fl_nrd1: + pop di + ret diff --git a/drivers/getvec.asm b/drivers/getvec.asm new file mode 100644 index 0000000..7270f38 --- /dev/null +++ b/drivers/getvec.asm @@ -0,0 +1,92 @@ +; +; File: +; getvec.asm +; Description: +; get an interrupt vector - simple version +; +; Copyright (c) 1995 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/dos-c/src/drivers/getvec.asv $ +; +; $Header$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:34:45 jhall1 +; Initial revision +; +; Revision 1.3 1999/08/10 17:21:08 jprice +; ror4 2011-01 patch +; +; Revision 1.2 1999/03/29 17:08:31 jprice +; ror4 changes +; +; Revision 1.1.1.1 1999/03/29 15:40:27 jprice +; New version without IPL.SYS +; +; Revision 1.2 1999/01/22 04:16:39 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:00 jprice +; Imported sources +; +; +; Rev 1.2 29 Aug 1996 13:07:10 patv +;Bug fixes for v0.91b +; +; Rev 1.1 01 Sep 1995 18:50:40 patv +;Initial GPL release. +; +; Rev 1.0 02 Jul 1995 8:00:36 patv +;Initial revision. +; + +group TGROUP _TEXT + +segment _TEXT class=CODE + + global _getvec +_getvec: + push bp + mov bp,sp + mov ax,[bp+4] + call getvec + pop bp + ret + +; +; assembler version - ax = vector number +; returns vector in dx:ax +; + + global getvec +getvec: + shl ax,1 ; Multiply by 4 + shl ax,1 + xor dx,dx ; and set segment to 0 + mov es,dx + mov bx,ax + pushf ; Push flags + cli ; Disable interrupts + mov ax,[es:bx] + mov dx,[es:bx+2] + popf ; Pop flags + ret diff --git a/drivers/rdatclk.asm b/drivers/rdatclk.asm new file mode 100644 index 0000000..9f9b04d --- /dev/null +++ b/drivers/rdatclk.asm @@ -0,0 +1,117 @@ +; +; File: +; rdatclk.asm +; Description: +; read the AT style clock from bios +; +; Copyright (c) 1995 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; @Logfile: C:/dos-c/src/drivers/rdatclk.asv @ +; +; @Header: /home/cvsroot/fdkernel/DRIVERS/RDATCLK.ASM,v 1.3 1999/04/12 03:19:44 jprice Exp @ +; +; @Log: RDATCLK.ASM,v @ +; Revision 1.3 1999/04/12 03:19:44 jprice +; more ror4 patches +; +; Revision 1.2 1999/03/29 17:08:31 jprice +; ror4 changes +; +; Revision 1.1.1.1 1999/03/29 15:40:31 jprice +; New version without IPL.SYS +; +; Revision 1.2 1999/01/22 04:16:39 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:00 jprice +; Imported sources +; +; +; Rev 1.2 29 Aug 1996 13:07:10 patv +;Bug fixes for v0.91b +; +; Rev 1.1 01 Sep 1995 18:50:40 patv +;Initial GPL release. +; +; Rev 1.0 02 Jul 1995 8:00:16 patv +;Initial revision. +; + +group IGROUP INIT_TEXT + +segment INIT_TEXT class=INIT + +; +;COUNT ReadATClock(bcdDays, bcdHours, bcdMinutes, bcdSeconds) +;BYTE *bcdDays; +;BYTE *bcdHours; +;BYTE *bcdMinutes; +;BYTE *bcdSeconds; +; + global _ReadATClock +_ReadATClock: + push bp + mov bp,sp + sub sp,byte 10 +; Days = -6 +; Hours = -2 +; Minutes = -8 +; Seconds = -10 +; bcdSeconds = 10 +; bcdMinutes = 8 +; bcdHours = 6 +; bcdDays = 4 + mov ah,2 + int 26 + jnc @RdAT1140 + sbb ax,ax + mov sp,bp + pop bp + ret + nop +@RdAT1140: + mov byte [bp-2],ch ;Hours + mov byte [bp-8],cl ;Minutes + mov byte [bp-10],dh ;Seconds + mov ah,4 + int 26 + mov word [bp-6],dx ;Days + mov word [bp-4],cx + mov ax,word [bp-6] ;Days + mov dx,word [bp-4] + mov bx,word [bp+4] ;bcdDays + mov word [bx],ax + mov word [bx+2],dx + mov al,byte [bp-2] ;Hours + mov bx,word [bp+6] ;bcdHours + mov byte [bx],al + mov al,byte [bp-8] ;Minutes + mov bx,word [bp+8] ;bcdMinutes + mov byte [bx],al + mov al,byte [bp-10] ;Seconds + mov bx,word [bp+10] ;bcdSeconds + mov byte [bx],al + sub ax,ax + mov sp,bp + pop bp + ret + nop diff --git a/drivers/rdpcclk.asm b/drivers/rdpcclk.asm new file mode 100644 index 0000000..3456c5d --- /dev/null +++ b/drivers/rdpcclk.asm @@ -0,0 +1,82 @@ +; +; File: +; rdpcclk.asm +; Description: +; read the PC style clock from bios +; +; Copyright (c) 1995 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/dos-c/src/drivers/rdpcclk.asv $ +; +; $Header$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:34:45 jhall1 +; Initial revision +; +; Revision 1.4 1999/08/10 17:21:08 jprice +; ror4 2011-01 patch +; +; Revision 1.3 1999/04/12 03:19:44 jprice +; more ror4 patches +; +; Revision 1.2 1999/03/29 17:08:31 jprice +; ror4 changes +; +; Revision 1.1.1.1 1999/03/29 15:40:32 jprice +; New version without IPL.SYS +; +; Revision 1.2 1999/01/22 04:16:39 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:00 jprice +; Imported sources +; +; +; Rev 1.2 29 Aug 1996 13:07:10 patv +;Bug fixes for v0.91b +; +; Rev 1.1 01 Sep 1995 18:50:40 patv +;Initial GPL release. +; +; Rev 1.0 02 Jul 1995 8:00:26 patv +;Initial revision. +; + +group TGROUP _TEXT + +segment _TEXT class=CODE + +; +; BOOL ReadPCClock(Ticks) +; ULONG *Ticks; +; + global _ReadPCClock +_ReadPCClock: + xor ah,ah + int 26 + mov bx,sp + mov bx,[bx+2] + mov [bx],dx + mov [bx+2],cx + cbw + ret diff --git a/drivers/timer.asm b/drivers/timer.asm new file mode 100644 index 0000000..d5db337 --- /dev/null +++ b/drivers/timer.asm @@ -0,0 +1,159 @@ +; +; File: +; timer.asm +; Description: +; Set a single timer and check when expired +; +; Copyright (c) 1995 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/dos-c/src/drivers/timer.asv $ +; +; $Header$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:34:45 jhall1 +; Initial revision +; +; Revision 1.3 1999/08/10 17:21:08 jprice +; ror4 2011-01 patch +; +; Revision 1.2 1999/03/29 17:08:31 jprice +; ror4 changes +; +; Revision 1.1.1.1 1999/03/29 15:40:34 jprice +; New version without IPL.SYS +; +; Revision 1.2 1999/01/22 04:16:39 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:00 jprice +; Imported sources +; +; +; Rev 1.2 29 Aug 1996 13:07:12 patv +;Bug fixes for v0.91b +; +; Rev 1.1 01 Sep 1995 18:50:42 patv +;Initial GPL release. +; +; Rev 1.0 02 Jul 1995 8:01:04 patv +;Initial revision. +; + +group TGROUP _TEXT +group DGROUP _BSS + +segment _TEXT class=CODE + +; +; void tmark() +; + global _tmark +_tmark: + push bp + mov bp,sp + xor ah,ah + int 01aH ; get current time in ticks + xor ah,ah + mov word [LastTime],dx ; and store it + mov word [LastTime+2],cx + pop bp + ret + + +; +; int tdelay(Ticks) +; + global _tdelay +_tdelay: + push bp + mov bp,sp + sub sp,byte 4 + xor ah,ah + int 01aH ; get current time in ticks + xor ah,ah + mov word [bp-4],dx ; and save it to a local variable + mov word [bp-2],cx ; "Ticks" +; +; Do a c equivalent of: +; +; return Now >= (LastTime + Ticks); +; + mov ax,word [LastTime+2] + mov dx,word [LastTime] + add dx,word [bp+4] + adc ax,word [bp+6] + cmp ax,word [bp-2] + ja short tdel_1 + jne short tdel_2 + cmp dx,word [bp-4] + ja short tdel_1 +tdel_2: + mov ax,1 ; True return + jmp short tdel_3 +tdel_1: + xor ax,ax ; False return +tdel_3: + mov sp,bp + pop bp + ret + + +; +; void twait(Ticks) +; + global _twait +_twait: + push bp + mov bp,sp + sub sp,byte 4 + call _tmark ; mark a start +; +; c equivalent +; do +; GetNowTime(&Now); +; while((LastTime + Ticks) < Now); +twait_1: + xor ah,ah + int 01aH + xor ah,ah ; do GetNowTime + mov word [bp-4],dx ; and save it to "Now" + mov word [bp-2],cx +; +; do comparison +; + mov ax,word [LastTime+2] + mov dx,word [LastTime] + add dx,word [bp+4] + adc ax,word [bp+6] + cmp ax,word [bp-2] + jb short twait_1 + jne short twait_2 + cmp dx,word [bp-4] + jb short twait_1 +twait_2: + mov sp,bp + pop bp + ret + +segment _BSS align=2 class=BSS +LastTime: resd 1 diff --git a/drivers/wratclk.asm b/drivers/wratclk.asm new file mode 100644 index 0000000..27fa122 --- /dev/null +++ b/drivers/wratclk.asm @@ -0,0 +1,101 @@ +; +; File: +; wratclk.asm +; Description: +; WriteATClock - sysclock support +; +; Copyright (c) 1995 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/dos-c/src/drivers/wratclk.asv $ +; +; $Header$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:34:45 jhall1 +; Initial revision +; +; Revision 1.3 1999/08/10 17:21:08 jprice +; ror4 2011-01 patch +; +; Revision 1.2 1999/03/29 17:08:31 jprice +; ror4 changes +; +; Revision 1.1.1.1 1999/03/29 15:40:34 jprice +; New version without IPL.SYS +; +; Revision 1.2 1999/01/22 04:16:40 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:00 jprice +; Imported sources +; +; +; Rev 1.2 29 Aug 1996 13:07:12 patv +;Bug fixes for v0.91b +; +; Rev 1.1 01 Sep 1995 18:50:42 patv +;Initial GPL release. +; +; Rev 1.0 02 Jul 1995 8:01:18 patv +;Initial revision. +; + +group TGROUP _TEXT + +segment _TEXT class=CODE + +; +; VOID WriteATClock(bcdDays, bcdHours, bcdMinutes, bcdSeconds) +; BYTE *bcdDays; +; BYTE bcdHours; +; BYTE bcdMinutes; +; BYTE bcdSeconds; +; + global _WriteATClock +_WriteATClock: + push bp + mov bp,sp + sub sp,byte 4 +; LocalCopy = -4 +; bcdSeconds = 10 +; bcdMinutes = 8 +; bcdHours = 6 +; bcdDays = 4 + mov bx,word [bp+4] ;bcdDays + mov ax,word [bx] + mov dx,word [bx+2] + mov word [bp-4],ax ;LocalCopy + mov word [bp-2],dx + mov ch,byte [bp+6] ;bcdHours + mov cl,byte [bp+8] ;bcdMinutes + mov dh,byte [bp+10] ;bcdSeconds + mov dl,0 + mov ah,3 + int 26 + mov cx,word [bp-2] + mov dx,word [bp-4] ;LocalCopy + mov ah,5 + int 26 + mov sp,bp + pop bp + ret + nop diff --git a/drivers/wrpcclk.asm b/drivers/wrpcclk.asm new file mode 100644 index 0000000..bd9e633 --- /dev/null +++ b/drivers/wrpcclk.asm @@ -0,0 +1,82 @@ +; +; File: +; wrpcclk.asm +; Description: +; WritePCClock - sysclock support +; +; Copyright (c) 1995 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/dos-c/src/drivers/wrpcclk.asv $ +; +; $Header$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:34:45 jhall1 +; Initial revision +; +; Revision 1.3 1999/08/10 17:21:08 jprice +; ror4 2011-01 patch +; +; Revision 1.2 1999/03/29 17:08:31 jprice +; ror4 changes +; +; Revision 1.1.1.1 1999/03/29 15:40:35 jprice +; New version without IPL.SYS +; +; Revision 1.2 1999/01/22 04:16:40 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:00 jprice +; Imported sources +; +; +; Rev 1.2 29 Aug 1996 13:07:12 patv +;Bug fixes for v0.91b +; +; Rev 1.1 01 Sep 1995 18:50:42 patv +;Initial GPL release. +; +; Rev 1.0 02 Jul 1995 8:01:30 patv +;Initial revision. +; + +group TGROUP _TEXT + +segment _TEXT class=CODE + +; +; VOID WritePCClock(Ticks) +; ULONG Ticks; +; + global _WritePCClock +_WritePCClock: + push bp + mov bp,sp +; Ticks = 4 + mov cx,word [bp+6] + mov dx,word [bp+4] ;Ticks + mov ah,1 + int 26 + mov sp,bp + pop bp + ret + nop diff --git a/fdkernel.lsm b/fdkernel.lsm new file mode 100644 index 0000000..2da0a9f --- /dev/null +++ b/fdkernel.lsm @@ -0,0 +1,14 @@ +Begin3 +Title: The FreeDOS Kernel +Version: 1.1.18 +Entered-date: 9 March 2000 +Description: The FreeDOS Kernel +Keywords: kernel freedos dos msdos +Author: kernel@gcfl.net (developers) +Maintained-by: linux-guru@gcfl.net +Primary-site: http://www.gcfl.net/pub/FreeDOS/kernel +Alternate-site: www.freedos.org +Original-site: http://www.gcfl.net/pub/FreeDOS/kernel +Platforms: dos dosemu +Copying-policy: GPL +End diff --git a/hdr/cds.h b/hdr/cds.h new file mode 100644 index 0000000..bc4abbf --- /dev/null +++ b/hdr/cds.h @@ -0,0 +1,112 @@ +/****************************************************************/ +/* */ +/* cds.h */ +/* */ +/* Current Directory structures */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *Cds_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:47 jhall1 + * Initial revision + * + * Revision 1.2 2000/03/09 06:06:38 kernel + * 2017f updates by James Tabor + * + * Revision 1.1.1.1 1999/03/29 15:39:22 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.3 1999/01/30 08:21:43 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + + Rev 1.1 04 Jan 1998 23:14:18 patv + Changed Log for strip utility + + Rev 1.0 19 Feb 1996 3:15:52 patv + Added NLS, int2f and config.sys processing + */ + +#define MAX_CDSPATH 67 + +struct cds +{ + BYTE cdsCurrentPath[MAX_CDSPATH]; + UWORD cdsFlags; + struct dpb FAR *cdsDpb; + + union + { + BYTE FAR * + _cdsRedirRec; + struct + { + WORD _cdsStrtClst; + UWORD _cdsParam; + } + _cdsRedir; + } + _cdsUnion; + + WORD cdsStoreUData; + + WORD cdsJoinOffset; + + BYTE cdsNetFlag1; + BYTE FAR *cdsIfs; + UWORD cdsNetFlags2; + +}; + +#define cdsStrtClst _cdsUnion._cdsRedir._cdsStrtClst +#define cdsRedirRec _cdsUnion._cdsRedirRec +#define cdsParam _cdsUnion._cdsRedir._cdsParam + +typedef struct _cdstbl +{ + struct cds cds_table[26]; +} +cdstbl; + +/* Bits for cdsFlags */ +#define CDSNETWDRV 0x8000 +#define CDSPHYSDRV 0x4000 +#define CDSJOINED 0x2000 +#define CDSSUBST 0x1000 + diff --git a/hdr/clock.h b/hdr/clock.h new file mode 100644 index 0000000..9fbff30 --- /dev/null +++ b/hdr/clock.h @@ -0,0 +1,86 @@ +/****************************************************************/ +/* */ +/* clock.h */ +/* */ +/* Clock Driver data structures & declarations */ +/* */ +/* November 26, 1991 */ +/* */ +/* Adapted to DOS/NT June 12, 1993 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *clock_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:47 jhall1 + * Initial revision + * + * Revision 1.1.1.1 1999/03/29 15:39:22 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.3 1999/01/30 08:21:43 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:18 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:20 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:30 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:38 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:46 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:26 patv + * Initial revision. + */ + +struct ClockRecord +{ + UWORD clkDays; /* days since Jan 1, 1980. */ + UBYTE clkMinutes; /* residual minutes. */ + UBYTE clkHours; /* residual hours. */ + UBYTE clkHundredths; /* residual hundredths of a second. */ + UBYTE clkSeconds; /* residual seconds. */ +}; diff --git a/hdr/date.h b/hdr/date.h new file mode 100644 index 0000000..affc58b --- /dev/null +++ b/hdr/date.h @@ -0,0 +1,95 @@ +/****************************************************************/ +/* */ +/* date.h */ +/* */ +/* DOS General Date Structure */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +/* TC 2.01 complains if `date' is defined twice. -- ror4 */ +#ifndef DOSC_DATE_H +#define DOSC_DATE_H + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *date_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:47 jhall1 + * Initial revision + * + * Revision 1.2 1999/08/25 03:17:11 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.1.1.1 1999/03/29 15:39:23 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:18 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:20 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:30 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:40 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:48 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:28 patv + * Initial revision. + */ + +/* FAT file date - takes the form of yyyy yyym mmmd dddd where physical */ +/* year=1980+yyyyyy */ + +#define DT_YEAR(d) (((d)>>9)&0x7f) +#define DT_MONTH(d) (((d)>>5)&0x0f) +#define DT_DAY(d) ((d)&0x1f) + +#define DT_ENCODE(m,d,y) ((((m)&0x0f)<<5)|((d)&0x1f)|(((y)&0x7f)<<9)) + +#define EPOCH_WEEKDAY 2 /* Tuesday (i. e.- 0 == Sunday) */ +#define EPOCH_MONTH 1 /* January */ +#define EPOCH_DAY 1 /* 1 for January 1 */ +#define EPOCH_YEAR 1980 /* for Tues 1-1-80 epoch */ + +typedef UWORD date; + +#endif diff --git a/hdr/dcb.h b/hdr/dcb.h new file mode 100644 index 0000000..35c8e5c --- /dev/null +++ b/hdr/dcb.h @@ -0,0 +1,109 @@ +/****************************************************************/ +/* */ +/* dcb.h */ +/* */ +/* DOS Device Control Block Structure */ +/* */ +/* November 20, 1991 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *clock_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:47 jhall1 + * Initial revision + * + * Revision 1.3 2000/03/09 06:06:38 kernel + * 2017f updates by James Tabor + * + * Revision 1.2 1999/04/16 00:52:09 jprice + * Optimized FAT handling + * + * Revision 1.1.1.1 1999/03/29 15:39:23 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:18 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:20 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:30 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:40 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:48 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:30 patv + * Initial revision. + */ + +/* Internal drive parameter block */ +struct dpb +{ + BYTE dpb_unit; /* unit for error reporting */ + BYTE dpb_subunit; /* the sub-unit for driver */ + UWORD dpb_secsize; /* sector size */ + UBYTE dpb_clsmask; /* mask (sectors/cluster-1) */ + UBYTE dpb_shftcnt; /* log base 2 of cluster size */ + UWORD dpb_fatstrt; /* FAT start sector */ + UBYTE dpb_fats; /* # of FAT copies */ + UWORD dpb_dirents; /* # of dir entries */ + UWORD dpb_data; /* start of data area */ + UWORD dpb_size; /* # of clusters+1 on media */ + UWORD dpb_fatsize; /* # of sectors / FAT */ + UWORD dpb_dirstrt; /* start sec. of root dir */ + struct dhdr FAR * /* pointer to device header */ + dpb_device; + UBYTE dpb_mdb; /* media descr. byte */ + BYTE dpb_flags; /* -1 = force MEDIA CHK */ + struct dpb FAR * /* next dpb in chain */ + dpb_next; /* -1 = end */ + UWORD dpb_cluster; /* cluster # of first free */ + /* -1 if not known */ + UWORD dpb_nfreeclst; /* number of free clusters */ + /* -1 if not known */ + +}; + +#define UNKNCLUSTER 0xffff /* 0xffff = unknown for DOS */ + diff --git a/hdr/device.h b/hdr/device.h new file mode 100644 index 0000000..daecb33 --- /dev/null +++ b/hdr/device.h @@ -0,0 +1,421 @@ +/****************************************************************/ +/* */ +/* device.h */ +/* Device Driver Header File */ +/* */ +/* November 20, 1991 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *device_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:46 jhall1 + * Initial revision + * + * Revision 1.3 2000/03/09 06:06:38 kernel + * 2017f updates by James Tabor + * + * Revision 1.2 1999/04/04 18:50:14 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:39:26 jprice + * New version without IPL.SYS + * + * Revision 1.5 1999/02/08 05:58:24 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/04 03:08:47 jprice + * no message + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.8 06 Dec 1998 8:41:30 patv + * Changed for new I/O subsystem + * + * Rev 1.7 11 Jan 1998 2:05:54 patv + * Added functionality to ioctl. + * + * Rev 1.6 04 Jan 1998 23:14:20 patv + * Changed Log for strip utility + * + * Rev 1.5 16 Jan 1997 12:46:06 patv + * pre-Release 0.92 feature additions + * + * Rev 1.4 29 May 1996 21:25:12 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:30 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:40 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:48 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:30 patv + * Initial revision. + */ + +/* + * Status Word Bits + */ + +#define S_ERROR 0x8000 /* Error bit */ +#define S_BUSY 0x0200 /* Device busy bit */ +#define S_DONE 0x0100 /* Device operation completed */ +#define S_MASK 0x00ff /* Mask to extract error code */ + +/* + * MEDIA Descriptor Byte Bits + */ + +#define MD_2SIDE 1 /* MEDIA is two sided */ +#define MD_8SECTOR 2 /* MEDIA is eight sectored */ +#define MD_REMOVABLE 4 /* MEDIA is removable (floppy) */ + +/* + * Media Return Codes + */ +#define M_CHANGED -1 /* MEDIA was changed */ +#define M_DONT_KNOW 0 /* MEDIA state unkown */ +#define M_NOT_CHANGED 1 /* MEDIA was not changed */ + +/* + * Error Return Codes + */ + +#define E_WRPRT 0 /* Write Protect */ +#define E_UNIT 1 /* Unknown Unit */ +#define E_NOTRDY 2 /* Device Not Ready */ +#define E_CMD 3 /* Unknown Command */ +#define E_CRC 4 /* Crc Error */ +#define E_LENGTH 5 /* Bad Length */ +#define E_SEEK 6 /* Seek Error */ +#define E_MEDIA 7 /* Unknown MEDIA */ +#define E_NOTFND 8 /* Sector Not Found */ +#define E_PAPER 9 /* No Paper */ +#define E_WRITE 10 /* Write Fault */ +#define E_READ 11 /* Read Fault */ +#define E_FAILURE 12 /* General Failure */ + +/* + * Command codes + */ + +#define C_INIT 0x00 /* Initialize */ +#define C_MEDIACHK 0x01 /* MEDIA Check */ +#define C_BLDBPB 0x02 /* Build BPB */ +#define C_IOCTLIN 0x03 /* Ioctl In */ +#define C_INPUT 0x04 /* Input (Read) */ +#define C_NDREAD 0x05 /* Non-destructive Read */ +#define C_ISTAT 0x06 /* Input Status */ +#define C_IFLUSH 0x07 /* Input Flush */ +#define C_OUTPUT 0x08 /* Output (Write) */ +#define C_OUTVFY 0x09 /* Output with verify */ +#define C_OSTAT 0x0a /* Output */ +#define C_OFLUSH 0x0b /* Output Flush */ +#define C_IOCTLOUT 0x0c /* Ioctl Out */ +#define C_OPEN 0x0d /* Device Open */ +#define C_CLOSE 0x0e /* Device Close */ +#define C_REMMEDIA 0x0f /* Removable MEDIA */ +#define C_OUB 0x10 /* Output till busy */ +#define C_GENIOCTL 0x13 /* Generic Ioctl */ +#define C_GETLDEV 0x17 /* Get Logical Device */ +#define C_SETLDEV 0x18 /* Set Logical Device */ +#define C_IOCTLQRY 0x19 /* Ioctl Query */ + +/* + * Convienence macros + */ +#define failure(x) (S_ERROR+S_DONE+x) +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#define mk_offset(far_ptr) ((UWORD)(far_ptr)) +#define mk_segment(far_ptr) ((UWORD)((ULONG)(far_ptr) >> 16)) +#define far_ptr(seg, off) ((VOID FAR *)(((ULONG)(off))+((ULONG)(seg) << 16))) + +/* + * structures + */ + +/* Device header */ + +struct dhdr +{ + struct dhdr + FAR *dh_next; + UWORD dh_attr; + VOID(*dh_strategy) (); + VOID(*dh_interrupt) (); + BYTE dh_name[8]; +}; + +#define ATTR_CHAR 0x8000 +#define ATTR_IOCTL 0x4000 +#define ATTR_BLDFAT 0x2000 +#define ATTR_EXCALLS 0x0800 +#define ATTR_QRYIOCTL 0x0080 +#define ATTR_GENIOCTL 0x0040 +#define ATTR_RAW 0x0400 +#define ATTR_FASTCON 0x0010 +#define ATTR_CLOCK 0x0008 +#define ATTR_NULL 0x0004 +#define ATTR_CONOUT 0x0002 +#define ATTR_HUGE 0x0002 +#define ATTR_CONIN 0x0001 + +/* */ +/* Bios Parameter Block structure */ +/* */ +/* The following offsets are computed as byte offsets and are based on */ +/* the struct below. The struct itself cannot be used because on some */ +/* compilers, structure alignement may be forced, throwing following */ +/* fields off (e.g. - BYTE, followed by a WORD may have a byte of fill */ +/* inserted in between; the WORD would then be at offset 2, not 1). */ +/* */ +#define BPB_NBYTE 0 +#define BPB_NSECTOR 2 +#define BPB_NRESERVED 3 +#define BPB_NFAT 5 +#define BPB_NDIRENT 6 +#define BPB_NSIZE 8 +#define BPB_MDESC 10 +#define BPB_NFSECT 11 +#define BPB_NSECS 13 +#define BPB_NHEADS 15 +#define BPB_HIDDEN 17 +#define BPB_HUGE 21 +#define BPB_SIZEOF 25 + +typedef struct +{ + UWORD bpb_nbyte; /* Bytes per Sector */ + UBYTE bpb_nsector; /* Sectors per Allocation Unit */ + UWORD bpb_nreserved; /* # Reserved Sectors */ + UBYTE bpb_nfat; /* # FAT's */ + UWORD bpb_ndirent; /* # Root Directory entries */ + UWORD bpb_nsize; /* Size in sectors */ + UBYTE bpb_mdesc; /* MEDIA Descriptor Byte */ + UWORD bpb_nfsect; /* FAT size in sectors */ + UWORD bpb_nsecs; /* Sectors per track */ + UWORD bpb_nheads; /* Number of heads */ + ULONG bpb_hidden; /* Hidden sectors */ + ULONG bpb_huge; /* Size in sectors if */ + /* bpb_nsize== 0 */ +} +bpb; + +/* */ +/* Boot Block (Super Block) */ +/* */ +/* See BPB comments for the offsets below */ +/* */ +#define BT_JUMP 0 +#define BT_OEM 3 +#define BT_BPB 11 +#define BT_SIZEOF 36 + +typedef struct +{ + BYTE bt_jump[3]; /* Boot Jump opcodes */ + BYTE bt_oem[8]; /* OEM Name */ + bpb bt_bpb; /* BPB for this media/device */ + WORD bt_nsecs; /* # Sectors per Track */ + WORD bt_nheads; /* # Heads */ + WORD bt_hidden; /* # Hidden sectors */ + LONG bt_huge; /* use if nsecs == 0 */ +} +boot; + +typedef boot super; /* Alias for boot structure */ + +typedef struct +{ + BYTE r_length; /* Request Header length */ + BYTE r_unit; /* Unit Code */ + BYTE r_command; /* Command Code */ + WORD r_status; /* Status */ + BYTE r_reserved[8]; /* DOS Reserved Area */ + union + { + struct + { + BYTE _r_nunits; /* number of units */ + BYTE FAR *_r_endaddr; /* Ending Address */ + bpb *FAR * _r_bpbptr; /* ptr to BPB array */ + BYTE _r_firstunit; + } + _r_init; + struct + { + BYTE _r_meddesc; /* MEDIA Descriptor */ + BYTE _r_retcode; /* Return Code */ + BYTE FAR + * _r_vid; /* volume id */ + } + _r_media; + struct + { + BYTE _r_meddesc; /* MEDIA Descriptor */ + boot FAR + * _r_fat; /* boot sector pointer */ + bpb FAR + * _r_bpbpt; /* ptr to BPB table */ + } + _r_bpb; + struct + { + BYTE _r_meddesc; /* MEDIA Descriptor */ + BYTE FAR + * _r_trans; /* Transfer Address */ + UWORD _r_count; /* Byte/Sector Count */ + UWORD _r_start; /* Starting Sector No. */ + BYTE FAR + * _r_vid; /* Pointer to volume id */ + LONG _r_huge; /* for > 32Mb drives */ + } + _r_rw; + struct + { + BYTE _r_ndbyte; /* Byte Read From Device */ + } + _r_nd; + } + _r_x; +} +request; + +#define HUGECOUNT 0xffff +#define MAXSHORT 0xffffl + +/* + * Macros to assist request structure legibility + */ + +/* Init packet macros */ +#define r_nunits _r_x._r_init._r_nunits +#define r_endaddr _r_x._r_init._r_endaddr +#define r_bpbptr _r_x._r_init._r_bpbptr +#define r_firstunit _r_x._r_init._r_firstunit + +/* MEDIA Check packet macros */ +#define r_mcmdesc _r_x._r_media._r_meddesc +#define r_mcretcode _r_x._r_media._r_retcode +#define r_mcvid _r_x._r_media._r_vid + +/* Build BPB packet macros */ +#define r_bpmdesc _r_x._r_bpb._r_meddesc +#define r_bpfat _r_x._r_bpb._r_fat +#define r_bpptr _r_x._r_bpb._r_bpbpt + +/* rw packet macros */ +#define r_meddesc _r_x._r_rw._r_meddesc +#define r_trans _r_x._r_rw._r_trans +#define r_count _r_x._r_rw._r_count +#define r_start _r_x._r_rw._r_start +#define r_rwvid _r_x._r_rw._r_vid +#define r_huge _r_x._r_rw._r_huge + +/* ndread packet macros */ +#define r_ndbyte _r_x._r_nd._r_ndbyte + +/* + *interrupt support (spl & splx) support - IBM style + */ + +#define I_NONE 0 /* Initial value */ + +/* predefined interrupt levels - 8259 support */ +#define IRQ0 0x01 /* Level 0 - highest */ +#define IRQ1 0x02 +#define IRQ2 0x04 +#define IRQ3 0x08 +#define IRQ4 0x10 +#define IRQ5 0x20 +#define IRQ6 0x40 +#define IRQ7 0x80 /* Level 7 - lowest */ + +/* standard hardware configuration */ +#define I_RTC IRQ0 /* Timer */ +#define I_KBD IRQ1 /* Keyboard */ +#define I_COM2 IRQ3 /* COM1: */ +#define I_COM1 IRQ4 /* COM2: */ +#define I_HDC IRQ5 /* Fixed disk */ +#define I_FDC IRQ6 /* Diskette */ +#define I_PRT IRQ7 /* Printer */ + +/* standard hardware vectors - 8259 defined */ +#define V_RTC 0x08 /* Timer */ +#define V_KBD 0x09 /* Keyboard */ +#define V_LEV2 0x0a /* Level 2 - uncomitted */ +#define V_COM2 0x0b /* COM1: */ +#define V_COM1 0x0c /* COM2: */ +#define V_HDC 0x0d /* Fixed disk */ +#define V_FDC 0x0e /* Diskette */ +#define V_PRT 0x0f /* Printer */ + +#define V_LEV0 0x08 /* Level 0 - highest */ +#define V_LEV1 0x09 +#define V_LEV2 0x0a /* Level 2 - uncomitted */ +#define V_LEV3 0x0b +#define V_LEV4 0x0c +#define V_LEV5 0x0d +#define V_LEV6 0x0e +#define V_LEV7 0x0f /* Level 7 - lowest */ + +/* + */ +typedef request FAR *rqptr; +typedef bpb FAR *bpbptr; +typedef BYTE FAR *byteptr; +typedef struct dhdr FAR *dhdrptr; + +/* + * externals + */ + +extern BYTE FAR *device_end(); + +/* + * end of device.h + */ + diff --git a/hdr/dirmatch.h b/hdr/dirmatch.h new file mode 100644 index 0000000..dcf14e3 --- /dev/null +++ b/hdr/dirmatch.h @@ -0,0 +1,117 @@ +/****************************************************************/ +/* */ +/* dirmatch.h */ +/* */ +/* FAT File System Match Data Structure */ +/* */ +/* January 4, 1992 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *dirmatch_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:47 jhall1 + * Initial revision + * + * Revision 1.3 2000/03/09 06:06:38 kernel + * 2017f updates by James Tabor + * + * Revision 1.2 1999/08/25 03:17:11 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.1.1.1 1999/03/29 15:39:21 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:16 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:18 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:34 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:40 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:48 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:34 patv + * Initial revision. + * + * Rev 1.0 25 May 1993 23:30:26 patv + * Initial revision. + * + */ + +typedef struct +{ + BYTE dm_drive; + BYTE dm_name_pat[FNAME_SIZE + FEXT_SIZE]; + BYTE dm_attr_srch; + UWORD dm_entry; + UWORD dm_cluster; + + struct + { + UWORD /* directory has been modified */ + f_dmod:1; + UWORD /* directory is the root */ + f_droot:1; + UWORD /* fnode is new and needs fill */ + f_dnew:1; + UWORD /* fnode is assigned to dir */ + f_ddir:1; + UWORD /* directory is full */ + f_dfull:1; + UWORD /* filler to avoid a bad bug (feature?) in */ + f_filler:11; /* TC 2.01 */ + } + dm_flags; /* file flags */ + UWORD dm_dirstart; + + BYTE dm_attr_fnd; /* found file attribute */ + time dm_time; /* file time */ + date dm_date; /* file date */ + LONG dm_size; /* file size */ + BYTE dm_name[FNAME_SIZE + FEXT_SIZE + 2]; /* file name */ +} +dmatch; + diff --git a/hdr/dosnames.h b/hdr/dosnames.h new file mode 100644 index 0000000..e941060 --- /dev/null +++ b/hdr/dosnames.h @@ -0,0 +1,79 @@ +/****************************************************************/ +/* */ +/* dosnames.h */ +/* */ +/* FAT File System Name Parse Structure */ +/* */ +/* March 5, 1995 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *dosnames_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:47 jhall1 + * Initial revision + * + * Revision 1.1.1.1 1999/03/29 15:39:27 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.4 29 May 1996 21:25:14 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:30 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:40 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:48 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:34 patv + * Initial revision. + */ + +#define PARSE_MAX 64 + +struct dosnames +{ + UBYTE dn_drive; /* the drive that was parsed */ + UBYTE dn_network[PARSE_MAX]; /* specified network */ + UBYTE dn_path[PARSE_MAX]; /* the path */ + UBYTE dn_name[FNAME_SIZE + FEXT_SIZE + 1]; /* the file name */ +}; diff --git a/hdr/error.h b/hdr/error.h new file mode 100644 index 0000000..3632584 --- /dev/null +++ b/hdr/error.h @@ -0,0 +1,124 @@ +/****************************************************************/ +/* */ +/* error.h */ +/* */ +/* DOS-C error return codes */ +/* */ +/* December 1, 1991 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *error_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:47 jhall1 + * Initial revision + * + * Revision 1.1.1.1 1999/03/29 15:39:27 jprice + * New version without IPL.SYS + * + * Revision 1.5 1999/02/08 05:58:24 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.3 1999/01/30 08:21:43 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.6 06 Dec 1998 8:41:00 patv + * Added new errors for new I/O subsystem. + * + * Rev 1.5 04 Jan 1998 23:14:16 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:18 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:28 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:38 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:42:28 patv + * fixed ipl + * + * Rev 1.0 02 Jul 1995 10:39:36 patv + * Initial revision. + */ + +/* Internal system error returns */ +#define SUCCESS 0 /* Function was successful */ +#define DE_INVLDFUNC -1 /* Invalid function number */ +#define DE_FILENOTFND -2 /* File not found */ +#define DE_PATHNOTFND -3 /* Path not found */ +#define DE_TOOMANY -4 /* Too many open files */ +#define DE_ACCESS -5 /* Access denied */ +#define DE_INVLDHNDL -6 /* Invalid handle */ +#define DE_MCBDESTRY -7 /* Memory control blocks shot */ +#define DE_NOMEM -8 /* Insufficient memory */ +#define DE_INVLDMCB -9 /* Invalid memory control block */ +#define DE_INVLDENV -10 /* Invalid enviornement */ +#define DE_INVLDFMT -11 /* Invalid format */ +#define DE_INVLDACC -12 /* Invalid access */ +#define DE_INVLDDATA -13 /* Inavalid data */ +#define DE_INVLDDRV -15 /* Invalid drive */ +#define DE_RMVCUDIR -16 /* Attempt remove current dir */ +#define DE_DEVICE -17 /* Not same device */ +#define DE_NFILES -18 /* No more files */ +#define DE_WRTPRTCT -19 /* No more files */ +#define DE_BLKINVLD -20 /* invalid block */ +#define DE_SEEK -25 /* error on file seek */ +#define DE_HNDLDSKFULL -39 /* handle disk full (?) */ + +/* Critical error flags */ +#define EFLG_READ 0x00 /* Read error */ +#define EFLG_WRITE 0x01 /* Write error */ +#define EFLG_RSVRD 0x00 /* Error in rserved area */ +#define EFLG_FAT 0x02 /* Error in FAT area */ +#define EFLG_DIR 0x04 /* Error in dir area */ +#define EFLG_DATA 0x06 /* Error in data area */ +#define EFLG_ABORT 0x08 /* Handler can abort */ +#define EFLG_RETRY 0x10 /* Handler can retry */ +#define EFLG_IGNORE 0x20 /* Handler can ignore */ +#define EFLG_CHAR 0x80 /* Error in char or FAT image */ + +/* error results returned after asking user */ +/* MS-DOS compatible -- returned by CriticalError */ +#define CONTINUE 0 +#define RETRY 1 +#define ABORT 2 +#define FAIL 3 diff --git a/hdr/exe.h b/hdr/exe.h new file mode 100644 index 0000000..653a596 --- /dev/null +++ b/hdr/exe.h @@ -0,0 +1,93 @@ +/****************************************************************/ +/* */ +/* exe.h */ +/* */ +/* DOS EXE Header Data Structure */ +/* */ +/* December 1, 1991 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *exe_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:47 jhall1 + * Initial revision + * + * Revision 1.1.1.1 1999/03/29 15:39:28 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:16 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:18 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:34 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:38 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:41:56 patv + * Fixed ipl + * + * Rev 1.0 02 Jul 1995 10:39:38 patv + * Initial revision. + */ + +typedef struct +{ + UWORD exSignature; + UWORD exExtraBytes; + UWORD exPages; + UWORD exRelocItems; + UWORD exHeaderSize; + UWORD exMinAlloc; + UWORD exMaxAlloc; + UWORD exInitSS; + UWORD exInitSP; + UWORD exCheckSum; + UWORD exInitIP; + UWORD exInitCS; + UWORD exRelocTable; + UWORD exOverlay; +} +exe_header; + +#define MAGIC 0x5a4d diff --git a/hdr/fat.h b/hdr/fat.h new file mode 100644 index 0000000..55dfaf6 --- /dev/null +++ b/hdr/fat.h @@ -0,0 +1,139 @@ +/****************************************************************/ +/* */ +/* fat.h */ +/* */ +/* FAT File System data structures & declarations */ +/* */ +/* November 26, 1991 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *fat_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:48 jhall1 + * Initial revision + * + * Revision 1.2 1999/05/03 06:28:00 jprice + * Changed some variables from signed to unsigned. + * + * Revision 1.1.1.1 1999/03/29 15:39:28 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.3 1999/01/30 08:21:43 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:18 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:14 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:30 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:42 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:48 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:40 patv + * Initial revision. + */ + +/* FAT file system attribute bits */ +#define D_NORMAL 0 /* normal */ +#define D_RDONLY 0x01 /* read-only file */ +#define D_HIDDEN 0x02 /* hidden */ +#define D_SYSTEM 0x04 /* system */ +#define D_VOLID 0x08 /* volume id */ +#define D_DIR 0x10 /* subdir */ +#define D_ARCHIVE 0x20 /* archive bit */ + +/* FAT file name constants */ +#define FNAME_SIZE 8 +#define FEXT_SIZE 3 + +/* FAT deleted flag */ +#define DELETED 0xe5 /* if first char, delete file */ + +/* FAT cluster to physical conversion macros */ +#define clus_add(cl_no) ((ULONG) (((ULONG) cl_no - 2L) \ + * (ULONG) cluster_size \ + + (ULONG) data_start)) + +#define clus2phys(cl_no,cl_size,d_st) ((ULONG) (((ULONG) cl_no - 2L) \ + * (ULONG) cl_size \ + + (ULONG) d_st)) + +/* Test for 16 bit or 12 bit FAT */ +#define SIZEOF_CLST16 2 +#define FAT_MAGIC 4086 + +#define ISFAT16(dpbp) (((dpbp)->dpb_size)>FAT_MAGIC) +#define ISFAT12(dpbp) (((dpbp)->dpb_size)<=FAT_MAGIC) + +/* FAT file system directory entry */ +struct dirent +{ + UBYTE dir_name[FNAME_SIZE]; /* Filename */ + UBYTE dir_ext[FEXT_SIZE]; /* Filename extension */ + UBYTE dir_attrib; /* File Attribute */ + BYTE dir_reserved[10]; /* reserved */ + time dir_time; /* Time file created/updated */ + date dir_date; /* Date file created/updated */ + UWORD dir_start; /* Starting cluster */ + /* 1st available = 2 */ + ULONG dir_size; /* File size in bytes */ +}; + +/* */ +/* filesystem sizeof(dirent) - may be different from core */ +/* */ + +#define DIR_NAME 0 +#define DIR_EXT FNAME_SIZE +#define DIR_ATTRIB FNAME_SIZE+FEXT_SIZE +#define DIR_RESERVED FNAME_SIZE+FEXT_SIZE+1 +#define DIR_TIME FNAME_SIZE+FEXT_SIZE+11 +#define DIR_DATE FNAME_SIZE+FEXT_SIZE+13 +#define DIR_START FNAME_SIZE+FEXT_SIZE+15 +#define DIR_SIZE FNAME_SIZE+FEXT_SIZE+17 + +#define DIRENT_SIZE 32 diff --git a/hdr/fcb.h b/hdr/fcb.h new file mode 100644 index 0000000..810e137 --- /dev/null +++ b/hdr/fcb.h @@ -0,0 +1,167 @@ +/****************************************************************/ +/* */ +/* fcb.h */ +/* */ +/* FAT FCB and extended FCB data structures & declarations */ +/* */ +/* November 23, 1991 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *fcb_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:48 jhall1 + * Initial revision + * + * Revision 1.2 1999/09/20 21:24:54 jprice + * *** empty log message *** + * + * Revision 1.1.1.1 1999/03/29 15:39:29 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.6 04 Jan 1998 23:14:16 patv + * Changed Log for strip utility + * + * Rev 1.5 16 Jan 1997 12:46:06 patv + * pre-Release 0.92 feature additions + * + * Rev 1.4 29 May 1996 21:25:14 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:32 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:42 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:48 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:40 patv + * Initial revision. + */ + +/* fcb convience defines */ +/* block device info */ +#define FID_CHARDEV 0x80 /* 1 defines character device */ + /* 0 defines block file */ +#define FID_NOWRITE 0x40 /* 0 file dirty (write occured) */ + /* 1 file has no changes */ +#define FID_MASK 0x3f /* file # */ +/* char device info */ +#define FID_EOF 0x40 /* 1 = no eof detected */ + /* 0 = end of file on input */ +#define FID_BINARY 0x20 /* 1 = binary (raw) mode device */ + /* 0 = ascii (cooked) mode device */ +#define FID_CLOCK 0x08 /* Clock device */ +#define FID_NULL 0x04 /* Null device */ +#define FID_CONOUT 0x02 /* Console output device */ +#define FID_CONIN 0x01 /* Console input device */ + +#ifndef FNAME_SIZE +#define FNAME_SIZE 8 /* limit on file name */ +#endif + +#ifndef FEXT_SIZE +#define FEXT_SIZE 3 /* limit on extension */ +#endif + +#ifndef FDFLT_DRIVE +#define FDFLT_DRIVE 0 /* default drive */ +#endif + +#define PARSE_SEP_STOP 0x01 +#define PARSE_DFLT_DRIVE 0x02 +#define PARSE_BLNK_FNAME 0x04 +#define PARSE_BLNK_FEXT 0x08 + +#define PARSE_RET_NOWILD 0 +#define PARSE_RET_WILD 1 +#define PARSE_RET_BADDRIVE 0xff + +#define FCB_READ 0 +#define FCB_WRITE 1 + +/* File Control Block (FCB) */ +typedef struct +{ + BYTE fcb_drive; /* Drive number 0=default, 1=A, etc */ + BYTE fcb_fname[FNAME_SIZE]; /* File name */ + BYTE fcb_fext[FEXT_SIZE]; /* File name Extension */ + UWORD fcb_cublock; /* Current block number of */ + /* 128 records/block, for seq. r/w */ + UWORD fcb_recsiz; /* Logical record size in bytes, */ + /* default = 128 */ + ULONG fcb_fsize; /* File size in bytes */ + date fcb_date; /* Date file created */ + time fcb_time; /* Time of last write */ + /* the following are reserved by system */ + BYTE fcb_sftno; /* Device ID */ + BYTE fcb_attrib_hi; /* share info, dev attrib word hi */ + BYTE fcb_attrib_lo; /* dev attrib word lo, open mode */ + UWORD fcb_strtclst; /* file starting cluster */ + UWORD fcb_dirclst; /* cluster of the dir entry */ + UBYTE fcb_diroff; /* offset of the dir entry */ + /* end reserved */ + UBYTE fcb_curec; /* Current block number of */ + ULONG fcb_rndm; /* Current relative record number */ +} +fcb; + +/* FAT extended fcb */ +typedef struct +{ + UBYTE xfcb_flag; /* 0xff indicates Extended FCB */ + BYTE xfcb_resvrd[5]; /* Reserved */ + UBYTE xfcb_attrib; /* Attribute */ + fcb xfcb_fcb; +} +xfcb; + +typedef struct +{ + UBYTE renDriveID; /* drive no. */ + BYTE renOldName[8]; /* Old Filename */ + BYTE renOldExtent[3]; /* Old File Extension */ + BYTE renReserved1[5]; + BYTE renNewName[8]; /* New Filename */ + BYTE renNewExtent[3]; /* New FileExtension */ + BYTE renReserved2[9]; +} +rfcb; diff --git a/hdr/file.h b/hdr/file.h new file mode 100644 index 0000000..75990ff --- /dev/null +++ b/hdr/file.h @@ -0,0 +1,76 @@ +/****************************************************************/ +/* */ +/* file.h */ +/* */ +/* DOS File mode flags */ +/* */ +/* December 1, 1991 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *file_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:48 jhall1 + * Initial revision + * + * Revision 1.1.1.1 1999/03/29 15:39:30 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:18 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:14 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:32 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:42 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:48 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:42 patv + * Initial revision. + */ + +#define O_RDONLY SFT_MREAD +#define O_WRONLY SFT_MWRITE +#define O_RDWR SFT_MRDWR diff --git a/hdr/fnode.h b/hdr/fnode.h new file mode 100644 index 0000000..d9415a6 --- /dev/null +++ b/hdr/fnode.h @@ -0,0 +1,115 @@ +/****************************************************************/ +/* */ +/* fnode.h */ +/* */ +/* Internal File Node for FAT File System */ +/* */ +/* January 4, 1992 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *fnode_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:48 jhall1 + * Initial revision + * + * Revision 1.3 2000/03/09 06:06:38 kernel + * 2017f updates by James Tabor + * + * Revision 1.2 1999/04/16 00:52:10 jprice + * Optimized FAT handling + * + * Revision 1.1.1.1 1999/03/29 15:39:30 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.3 1999/01/30 08:21:43 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:18 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:16 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:32 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:42 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:48 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:44 patv + * Initial revision. + */ + +struct f_node +{ + UWORD f_count; /* number of uses of this file */ + COUNT f_mode; /* read, write, read-write, etc */ + + struct + { + BOOL f_dmod:1; /* directory has been modified */ + BOOL f_droot:1; /* directory is the root */ + BOOL f_dnew:1; /* fnode is new and needs fill */ + BOOL f_ddir:1; /* fnode is assigned to dir */ + BOOL f_dfull:1; /* directory is full */ + BOOL f_dremote:1; /* Remote Fake FNode */ + } + f_flags; /* file flags */ + + struct dirent f_dir; /* this file's dir entry image */ + + ULONG f_diroff; /* offset of the dir entry */ + UWORD f_dirstart; /* the starting cluster of dir */ + /* when dir is not root */ + struct dpb *f_dpb; /* the block device for file */ + + ULONG f_dsize; /* file size (for directories) */ + ULONG f_offset; /* byte offset for next op */ + ULONG f_highwater; /* the largest offset ever */ + UWORD f_back; /* the cluster we were at */ + ULONG f_cluster_offset; /* byte offset that the next 3 point to */ + UWORD f_cluster; /* the cluster we are at */ + UWORD f_sector; /* the sector in the cluster */ + UWORD f_boff; /* the byte in the cluster */ +}; + diff --git a/hdr/kbd.h b/hdr/kbd.h new file mode 100644 index 0000000..adac73d --- /dev/null +++ b/hdr/kbd.h @@ -0,0 +1,83 @@ +/****************************************************************/ +/* */ +/* kbd.h */ +/* */ +/* Buffered Keyboard Input data structures & declarations */ +/* */ +/* July 5, 1993 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *kbd_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:48 jhall1 + * Initial revision + * + * Revision 1.1.1.1 1999/03/29 15:39:31 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:18 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:20 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:28 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:38 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:42:22 patv + * fixed ipl + * + * Rev 1.0 02 Jul 1995 10:39:46 patv + * Initial revision. + */ + +#define KBD_MAXLENGTH 256 + +/* Keyboard buffer */ +typedef struct +{ + UBYTE kb_size; /* size of buffer in bytes */ + UBYTE kb_count; /* number of bytes returned */ + BYTE kb_buf[KBD_MAXLENGTH]; /* the buffer itself */ +} +keyboard; diff --git a/hdr/mcb.h b/hdr/mcb.h new file mode 100644 index 0000000..9a428f6 --- /dev/null +++ b/hdr/mcb.h @@ -0,0 +1,102 @@ +/****************************************************************/ +/* */ +/* mcb.h */ +/* */ +/* Memory Control Block data structures and declarations */ +/* */ +/* November 23, 1991 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *mcb_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:48 jhall1 + * Initial revision + * + * Revision 1.2 2000/03/09 06:06:38 kernel + * 2017f updates by James Tabor + * + * Revision 1.1.1.1 1999/03/29 15:39:31 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:18 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:16 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:32 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:42 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:50 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:46 patv + * Initial revision. + */ + +#define LARGEST -1 +#define FIRST_FIT 0 +#define BEST_FIT 1 +#define LAST_FIT 2 + +#define MCB_NORMAL 0x4d +#define MCB_LAST 0x5a + +#define DOS_PSP 0x0050 /* 0x0008 What? seg 8 =0:0080 */ +#define FREE_PSP 0 + +#define MCB_SIZE(x) ((((LONG)(x))<<4)+sizeof(mcb)) + +typedef UWORD seg; +typedef UWORD offset; + +typedef struct +{ + BYTE m_type; /* mcb type - chain or end */ + UWORD m_psp; /* owner id via psp segment */ + UWORD m_size; /* size of segment in paragraphs */ + BYTE m_fill[3]; + BYTE m_name[8]; /* owner name limited to 8 bytes */ +} +mcb; + diff --git a/hdr/network.h b/hdr/network.h new file mode 100644 index 0000000..137e62c --- /dev/null +++ b/hdr/network.h @@ -0,0 +1,87 @@ +/****************************************************************/ +/* */ +/* network.h */ +/* */ +/* DOS Networking */ +/* */ +/* October 10, 1999 */ +/* */ +/* Copyright (c) 1999 */ +/* James Tabor */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +/* Defines for remote access functions */ +#define REM_RMDIR 0x1101 +#define REM_MKDIR 0x1103 +#define REM_CHDIR 0x1105 +#define REM_CLOSE 0x1106 +#define REM_FLUSH 0x1107 +#define REM_READ 0x1108 +#define REM_WRITE 0x1109 +#define REM_LOCK 0x110a +#define REM_UNLOCK 0x110b +#define REM_GETSPACE 0x110c +#define REM_SETATTR 0x110e +#define REM_GETATTRZ 0x110f +#define REM_RENAME 0x1111 +#define REM_DELETE 0x1113 +#define REM_OPEN 0x1116 +#define REM_CREATE 0x1117 +#define REM_CRTRWOCDS 0x1118 +#define REM_FND1WOCDS 0x1119 +#define REM_FINDFIRST 0x111B +#define REM_FINDNEXT 0x111C +#define REM_CLOSEALL 0x111d +#define REM_DOREDIRECT 0x111e +#define REM_PRINTSET 0x111f +#define REM_FLUSHALL 0x1120 +#define REM_LSEEK 0x1121 +#define REM_FILENAME 0x1123 +#define REM_PRINTREDIR 0x1125 +#define REM_EXTOC 0x112e + +struct rgds +{ + UWORD r_spc; + UWORD r_navc; + UWORD r_bps; + UWORD r_nc; +}; + +struct remote_fileattrib +{ + UWORD rfa_file; /* File Attributes */ + union + { + ULONG rfa_filesize; /* file size */ + struct + { + UWORD rfa_filesize_lo; /* DI Low */ + UWORD rfa_filesize_hi; /* BX High */ + } + _split_rfa_fz; + } + rfa_fz_union; + UWORD rfa_time; + UWORD rfa_date; +}; + + diff --git a/hdr/pcb.h b/hdr/pcb.h new file mode 100644 index 0000000..f8fd97d --- /dev/null +++ b/hdr/pcb.h @@ -0,0 +1,177 @@ +/****************************************************************/ +/* */ +/* pcb.h */ +/* */ +/* Process Control and Interrupt data structures */ +/* */ +/* November 26, 1991 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *pcb_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:49 jhall1 + * Initial revision + * + * Revision 1.1.1.1 1999/03/29 15:39:32 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.6 07 Feb 1998 20:47:40 patv + * Modified stack frame to match DOS standard + * + * Rev 1.5 04 Jan 1998 23:14:18 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:16 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:32 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:44 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:50 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:48 patv + * Initial revision. + */ + +/* */ +/* interrupt handler structure definition */ +/* */ +typedef union +{ + UWORD x; /* access mode for ax, bx, etc. */ + struct + { + UBYTE l; /* access mode for al, bl, etc. */ + UBYTE h; /* access mode for ah, bh, etc. */ + } + b; +} +xreg; + +/* maps MS-DOS unique stacking order */ +typedef struct +{ + xreg a, + b, + c, + d; + UWORD si, + di, + bp, + ds, + es; + UWORD ip, + cs, + flags; +} +iregs; + +/* Process control block for task switching */ +typedef struct +{ + UWORD pc_ss; + UWORD pc_sp; + iregs pc_regs; +} +pcb; + +/* For MSC, the following offsets must match the assembly process */ +/* support offsets */ +/* NOTE: Alignemnts must be set to 1 (-Zp1) */ +/* ss: 0 */ +/* sp: 2 */ +/* es: 4 */ +/* ds: 6 */ +/* di: 8 */ +/* si: 10 */ +/* bp: 12 */ +/* sp: 14 NOTE: not used in this structure */ +/* bx: 16 */ +/* dx: 18 */ +/* cx: 20 */ +/* ax: 22 */ +/* ip: 24 */ +/* cs: 26 */ +/* flags: 28 */ +/* */ +/* For Borland C, the following offsets must match the assembly process */ +/* support offsets */ +/* ss: 0 */ +/* sp: 2 */ +/* bp: 4 */ +/* di: 6 */ +/* si: 8 */ +/* ds: 10 */ +/* es: 12 */ +/* dx: 14 */ +/* cx: 16 */ +/* bx: 18 */ +/* ax: 20 */ +/* ip: 22 */ +/* cs: 24 */ +/* flags: 26 */ + +#define BP bp +#define DI di +#define SI si +#define DS ds +#define ES es +#define DX d.x +#define CX c.x +#define BX b.x +#define AX a.x +#define DH d.b.h +#define CH c.b.h +#define BH b.b.h +#define AH a.b.h +#define DL d.b.l +#define CL c.b.l +#define BL b.b.l +#define AL a.b.l +#define IP ip +#define CS cs +#define FLAGS flags + +#define FLG_ZERO 0x0040 +#define FLG_CARRY 0x0001 diff --git a/hdr/portab.h b/hdr/portab.h new file mode 100644 index 0000000..f51b82c --- /dev/null +++ b/hdr/portab.h @@ -0,0 +1,201 @@ +/****************************************************************/ +/* */ +/* portab.h */ +/* */ +/* DOS-C portability typedefs, etc. */ +/* */ +/* May 1, 1995 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static char *portab_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:49 jhall1 + * Initial revision + * + * Revision 1.2 1999/08/25 03:17:11 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.1.1.1 1999/03/29 15:39:33 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:16 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:16 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:32 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:44 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:50 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:50 patv + * Initial revision. + */ + +/****************************************************************/ +/* */ +/* Machine dependant portable types. Note that this section is */ +/* used primarily for segmented architectures. Common types and */ +/* types used relating to segmented operations are found here. */ +/* */ +/* Be aware that segmented architectures impose on linear */ +/* architectures because they require special types to be used */ +/* throught the code that must be reduced to empty preprocessor */ +/* replacements in the linear machine. */ +/* */ +/* #ifdef */ +/* # define FAR far */ +/* # define NEAR near */ +/* #endif */ +/* */ +/* #ifdef */ +/* # define FAR */ +/* # define NEAR */ +/* #endif */ +/* */ +/****************************************************************/ + +#ifdef MC68K + +#define far /* No far type */ +#define interrupt /* No interrupt type */ + +#define VOID void +#define FAR /* linear architecture */ +#define NEAR /* " " */ +#define INRPT interrupt + +#define CONST +#define REG register + +#define API int /* linear architecture */ +#define NONNATIVE + +#define PARASIZE 4096 /* "paragraph" size */ +#endif + +#ifdef I86 + +#define VOID void +#define FAR far /* segment architecture */ +#define NEAR near /* " " */ +#define INRPT interrupt + +#define CONST const +#define REG register + +#define API int far pascal /* segment architecture */ +#define NATIVE + +#define PARASIZE 16 /* "paragraph" size */ +#endif + +/* */ +/* Boolean type & definitions of TRUE and FALSE boolean values */ +/* */ +typedef int BOOL; +#define FALSE (1==0) +#define TRUE (1==1) + +/* */ +/* Common pointer types */ +/* */ +#ifndef NULL +#define NULL 0 +#endif + +/* */ +/* Convienence defines */ +/* */ +#define FOREVER while(TRUE) +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +/* */ +/* Common byte, 16 bit and 32 bit types */ +/* */ +typedef char BYTE; +typedef short WORD; +typedef long DWORD; + +typedef unsigned char UBYTE; +typedef unsigned short UWORD; + +typedef short SHORT; + +typedef unsigned int BITS; /* for use in bit fields(!) */ + +typedef int COUNT; +typedef unsigned int UCOUNT; +typedef unsigned long ULONG; + +#ifdef UNIX +typedef char FAR *ADDRESS; +#else +typedef void FAR *ADDRESS; +#endif + +#ifdef STRICT +typedef signed long LONG; +#else +#define LONG long +#endif + +/* General far pointer macros */ +#ifdef I86 +#define MK_FP(seg,ofs) ((VOID far *)(((LONG)(seg)<<16)|(UWORD)(ofs))) +#define FP_SEG(fp) ((UWORD)((LONG)(VOID FAR *)(fp)>>16)) +#define FP_OFF(fp) ((UWORD)(fp)) +#endif + +#ifdef MC68K +#define MK_FP(seg,ofs) ((VOID *)(&(((BYTE *)(seg))[(ofs)]))) +#define FP_SEG(fp) (0) +#define FP_OFF(fp) (fp) +#endif diff --git a/hdr/process.h b/hdr/process.h new file mode 100644 index 0000000..830c4cb --- /dev/null +++ b/hdr/process.h @@ -0,0 +1,172 @@ +/****************************************************************/ +/* */ +/* process.h */ +/* */ +/* DOS exec data structures & declarations */ +/* */ +/* November 23, 1991 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *process_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:49 jhall1 + * Initial revision + * + * Revision 1.1.1.1 1999/03/29 15:39:34 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.7 22 Jan 1998 22:13:00 patv + * Had to change ps_prevps to VOID FAR * due to BC++ error. + * + * Rev 1.6 22 Jan 1998 22:05:22 patv + * Corrected ps_prevpsp declaration. + * + * Rev 1.5 04 Jan 1998 23:14:16 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:16 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:32 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:44 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:50 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:52 patv + * Initial revision. + */ + +/* Modes available as first argument to the spawnxx functions. */ + +#define P_WAIT 0 /* child runs separately, parent waits until exit */ +#define P_NOWAIT 1 /* both concurrent -- not implemented */ +#define P_OVERLAY 2 /* child replaces parent, parent no longer exists */ + +typedef struct +{ + union + { + struct + { + UWORD load_seg; + UWORD reloc; + } + _load; + struct + { + UWORD env_seg; + CommandTail FAR *cmd_line; + BYTE FAR *fcb_1; + BYTE FAR *fcb_2; + BYTE FAR *stack; + BYTE FAR *start_addr; + } + _exec; + } + ldata; +} +exec_blk; + +#define exec ldata._exec +#define load ldata._load + +typedef struct +{ + UWORD ps_exit; /* CP/M-like exit poimt */ + UWORD ps_size; /* memory size in paragraphs */ + BYTE ps_fill1; /* single char fill */ + + /* CP/M-like entry point */ + BYTE ps_farcall; /* far call opcode */ + VOID(FAR * ps_reentry) (); /* re-entry point */ + VOID(interrupt FAR * ps_isv22) (), /* terminate address */ + (interrupt FAR * ps_isv23) (), /* break address */ + (interrupt FAR * ps_isv24) (); /* critical error address */ + UWORD ps_parent; /* parent psp segment */ + UBYTE ps_files[20]; /* file table - 0xff is unused */ + UWORD ps_environ; /* environment paragraph */ + BYTE FAR *ps_stack; /* user stack pointer - int 21 */ + WORD ps_maxfiles; /* maximum open files */ + UBYTE FAR *ps_filetab; /* open file table pointer */ + VOID FAR *ps_prevpsp; /* previous psp pointer */ + BYTE FAR *ps_dta; /* process dta address */ + BYTE ps_fill2[16]; + BYTE ps_unix[3]; /* unix style call - 0xcd 0x21 0xcb */ + BYTE ps_fill3[9]; + union + { + struct + { + fcb + _ps_fcb1; /* first command line argument */ + } + _u1; + struct + { + BYTE + fill4[16]; + fcb + _ps_fcb2; /* second command line argument */ + } + _u2; + struct + { + BYTE fill5[36]; + struct + { + BYTE _ps_cmd_count; + BYTE _ps_cmd[127]; /* command tail */ + } + _u4; + } + _u3; + } + _u; +} +psp; + +#define ps_fcb1 _u._u1._ps_fcb1 +#define ps_fcb2 _u._u2._ps_fcb2 +#define ps_cmd _u._u3._u4._ps_cmd +#define ps_cmd_count _u._u3._u4._ps_cmd_count diff --git a/hdr/sft.h b/hdr/sft.h new file mode 100644 index 0000000..7314e30 --- /dev/null +++ b/hdr/sft.h @@ -0,0 +1,199 @@ +/****************************************************************/ +/* */ +/* sft.h */ +/* DOS-C */ +/* */ +/* DOS System File Table Structure */ +/* */ +/* Copyright (c) 1995, 1996 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *sft_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:50 jhall1 + * Initial revision + * + * Revision 1.3 2000/03/09 06:06:38 kernel + * 2017f updates by James Tabor + * + * Revision 1.2 1999/04/04 18:50:25 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:39:35 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.6 04 Jan 1998 23:14:18 patv + * Changed Log for strip utility + * + * Rev 1.5 16 Jan 1997 12:46:04 patv + * pre-Release 0.92 feature additions + * + * Rev 1.4 29 May 1996 21:25:18 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:34 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:44 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:50 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:52 patv + * Initial revision. + */ + +#define SFTMAX 128 + +/* Handle Definition entry */ +typedef struct +{ + WORD sft_count; /* reference count */ + WORD sft_mode; /* open mode - see below */ + BYTE sft_attrib; /* file attribute - dir style */ + + union + { + WORD _sft_flags; + struct + { + BYTE _sft_flags_lo; + BYTE _sft_flags_hi; + } + _split_sft_flags; + } + sft_flags_union; + + union + { + struct dpb FAR * + _sft_dcb; /* The device control block */ + struct dhdr FAR * + _sft_dev; /* device driver for char dev */ + } + sft_dcb_or_dev; + WORD sft_stclust; /* Starting cluster */ + time sft_time; /* File time */ + date sft_date; /* File date */ + LONG sft_size; /* File size */ + LONG sft_posit; /* Current file position */ + WORD sft_relclust; /* File relative cluster */ + WORD sft_cuclust; /* File current cluster */ + WORD sft_dirdlust; /* Sector containing cluster */ + BYTE sft_diridx; /* directory index */ + BYTE sft_name[11]; /* dir style file name */ + BYTE FAR * + sft_bshare; /* backward link of file sharing sft */ + WORD sft_mach; /* machine number - network apps */ + WORD sft_psp; /* owner psp */ + WORD sft_shroff; /* Sharing offset */ + WORD sft_status; /* this sft status */ +} +sft; + +/* SFT Table header definition */ +typedef struct _sftheader +{ + struct _sfttbl FAR * /* link to next table in list */ + sftt_next; + WORD sftt_count; /* # of handle definition */ + /* entries, this table */ +} +sftheader; + +/* System File Definition List */ +typedef struct _sfttbl +{ + struct _sfttbl FAR * /* link to next table in list */ + sftt_next; + WORD sftt_count; /* # of handle definition */ + /* entries, this table */ + sft sftt_table[SFTMAX]; /* The array of sft for block */ +} +sfttbl; + +/* defines for sft use */ +#define SFT_MASK 0x0060 /* splits device data */ + +/* mode bits */ +#define SFT_MFCB 0x8000 /* entry is for fcb */ +#define SFT_MDENYNONE 0x0040 /* sharing bits */ +#define SFT_MDENYREAD 0x0030 /* " " */ +#define SFT_MDENYWRITE 0x0020 /* " " */ +#define SFT_MEXCLUSIVE 0x0010 /* " " */ +#define SFT_NOINHERIT 0x0080 /* inhibit inherting of file */ +#define SFT_NETFCB 0x0070 /* networked fcb */ +#define SFT_MSHAREMASK 0x0070 /* mask to isolate shared bits */ +#define SFT_MRDWR 0x0002 /* read/write bit */ +#define SFT_MWRITE 0x0001 /* write bit */ +#define SFT_MREAD 0x0000 /* ~ write bit */ +#define SFT_OMASK 0x00f3 /* valid open mask */ + +/* flag bits */ + +/* the following bit is for redirection */ +#define SFT_FSHARED 0x8000 /* Networked access */ + +/* the following entry differntiates char & block access */ +#define SFT_FDEVICE 0x0080 /* device entry */ + +/* the following bits are file (block) unique */ +#define SFT_FDATE 0x4000 /* File date set */ +#define SFT_FDIRTY 0x0040 /* File has been written to */ +#define SFT_FDMASK 0x003f /* File mask for drive no */ + +/* the following bits are device (char) unique */ +#define SFT_FIOCTL 0x4000 /* IOCTL support - device */ +#define SFT_FEOF 0x0040 /* device eof */ +#define SFT_FBINARY 0x0020 /* device binary mode */ +#define SFT_FSPECIAL 0x0010 /* int 29 support */ +#define SFT_FCLOCK 0x0008 /* device is clock */ +#define SFT_FNUL 0x0004 /* device is nul */ +#define SFT_FCONOUT 0x0002 /* device is console output */ +#define SFT_FCONIN 0x0001 /* device is console input */ + +/* Covienence defines */ +#define sft_dcb sft_dcb_or_dev._sft_dcb +#define sft_dev sft_dcb_or_dev._sft_dev + +#define sft_flags sft_flags_union._sft_flags +#define sft_flags_hi sft_flags_union._split_sft_flags._sft_flags_hi +#define sft_flags_lo sft_flags_union._split_sft_flags._sft_flags_lo + + diff --git a/hdr/stacks.inc b/hdr/stacks.inc new file mode 100644 index 0000000..25503f7 --- /dev/null +++ b/hdr/stacks.inc @@ -0,0 +1,136 @@ +; +; File: +; stacks.inc +; Description: +; Macro support for register stack frame +; +; Copyright (c) 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/dos-c/hdr/stacks.inv $ +; +; $Id$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:34:50 jhall1 +; Initial revision +; +; Revision 1.3 2000/03/09 06:06:38 kernel +; 2017f updates by James Tabor +; +; Revision 1.2 1999/08/10 17:56:26 jprice +; ror4 2011-02 patch +; +; Revision 1.1.1.1 1999/03/29 15:39:35 jprice +; New version without IPL.SYS +; +; Revision 1.3 1999/02/01 01:40:06 jprice +; Clean up +; +; Revision 1.2 1999/01/22 04:17:40 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:01 jprice +; Imported sources +; +; +; Rev 1.0 07 Feb 1998 20:59:16 patv +;Modified stack frame to match DOS standard +; $EndLog$ + + +; +; Standard stack frame used throughout DOS-C +; +; MS-DOS specific +; +; +---------------+ +; | irp hi | 26 +; +---------------+ +; | irp low | 24 +; +---------------+ +; | flags | 22 +; +---------------+ +; | cs | 20 +; +---------------+ +; | ip | 18 +; +---------------+ +; | es | 16 +; +---------------+ +; | ds | 14 +; +---------------+ +; | bp | 12 +; +---------------+ +; | di | 10 +; +---------------+ +; | si | 8 +; +---------------+ +; | dx | 6 +; +---------------+ +; | cx | 4 +; +---------------+ +; | bx | 2 +; +---------------+ +; | ax | 0 +; +---------------+ +; + +; Don't use `struc RegFrame' etc. here because it interferes with segment +; definitions. +reg_ax equ 0 +reg_bx equ 2 +reg_cx equ 4 +reg_dx equ 6 +reg_si equ 8 +reg_di equ 10 +reg_bp equ 12 +reg_ds equ 14 +reg_es equ 16 +reg_ip equ 18 +reg_cs equ 20 +reg_flags equ 22 +irp_low equ 24 +irp_hi equ 26 + +%macro PUSH$ALL 0 + push es + push ds + push bp + push di + push si + push dx + push cx + push bx + push ax +%endmacro + +%macro POP$ALL 0 + pop ax + pop bx + pop cx + pop dx + pop si + pop di + pop bp + pop ds + pop es +%endmacro + diff --git a/hdr/tail.h b/hdr/tail.h new file mode 100644 index 0000000..7e50777 --- /dev/null +++ b/hdr/tail.h @@ -0,0 +1,83 @@ +/****************************************************************/ +/* */ +/* tail.h */ +/* */ +/* Command tail data structures */ +/* */ +/* July 1, 1993 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *tail_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:50 jhall1 + * Initial revision + * + * Revision 1.1.1.1 1999/03/29 15:39:36 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:16 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:18 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:34 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:44 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:50 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:54 patv + * Initial revision. + */ + +#ifndef LINESIZE +#define LINESIZE 127 +#endif + +typedef struct +{ + UBYTE ctCount; /* number of bytes returned */ + BYTE ctBuffer[LINESIZE]; /* the buffer itself */ +} +CommandTail; diff --git a/hdr/time.h b/hdr/time.h new file mode 100644 index 0000000..b945a37 --- /dev/null +++ b/hdr/time.h @@ -0,0 +1,91 @@ +/****************************************************************/ +/* */ +/* time.h */ +/* */ +/* DOS General Time Structure */ +/* */ +/* January 21, 1993 */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +/* TC 2.01 complains if `time' is defined twice. -- ror4 */ +#ifndef DOSC_TIME_H +#define DOSC_TIME_H + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *time_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:50 jhall1 + * Initial revision + * + * Revision 1.2 1999/08/25 03:17:11 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.1.1.1 1999/03/29 15:39:36 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:40:06 jprice + * Clean up + * + * Revision 1.2 1999/01/22 04:17:40 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:16 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:25:18 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:15:34 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:35:46 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:43:50 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 10:39:56 patv + * Initial revision. + */ + +/* FAT Time notation in the form of hhhh hmmm mmmd dddd */ + +#define TM_HOUR(t) (((t)>>11)&0x1f) +#define TM_MIN(t) (((t)>>5)&0x3f) +#define TM_DEC(t) ((t)&0x1f) + +#define TM_ENCODE(h,m,d) ((((h&0x1f))<<11)|(((m)&0x3f)<<5)|((d)&0x1f)) + +typedef UWORD time; + +#endif diff --git a/hdr/version.h b/hdr/version.h new file mode 100644 index 0000000..f303307 --- /dev/null +++ b/hdr/version.h @@ -0,0 +1,46 @@ +/****************************************************************/ +/* */ +/* version.h */ +/* */ +/* Common version information */ +/* */ +/* Copyright (c) 1997 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *date_hRcsId = "$Id$"; +#endif +#endif + +/* This Kernel is at a min Dos Ver. 4.00 */ + +#define MAJOR_RELEASE 4 +#define MINOR_RELEASE 00 + +#define REV_NUMBER 0 +#define OEM_ID 0xfd /* FreeDos version */ + +#define REVISION_MAJOR 1 +#define REVISION_MINOR 1 +#define REVISION_SEQ 18 +#define BUILD 2018 diff --git a/kernel/001-437.nls b/kernel/001-437.nls new file mode 100644 index 0000000..780c9c5 --- /dev/null +++ b/kernel/001-437.nls @@ -0,0 +1,233 @@ + +/****************************************************************/ +/* */ +/* 001-437.nls */ +/* DOS-C */ +/* */ +/* National Languge Support USA Code Page */ +/* */ +/* Copyright (c) 1996 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* Copyright (c) 1996 */ +/* Steffen Kaiser */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +/* $Logfile: D:/dos-c/src/kernel/001-437.nlv $ */ +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Header$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:52 jhall1 + * Initial revision + * + * Revision 1.2 2000/03/09 06:07:10 kernel + * 2017f updates by James Tabor + * + * Revision 1.1.1.1 1999/03/29 15:40:36 jprice + * New version without IPL.SYS + * + * Revision 1.2 1999/01/22 04:13:25 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.2 29 May 1996 21:03:46 patv + * bug fixes for v0.91a + * + * Rev 1.1 19 Feb 1996 4:34:48 patv + * Corrected typo + * + * Rev 1.0 19 Feb 1996 3:37:48 patv + * Initial revision. + */ + +/* This initialization segment is included into the file where needed. */ +/* It's cuurently included in the following file: nls.c. */ +{ + { + { + 0, 0, 0, 0, 0, 0, 0, 0 + } + , + "\\COUNTRY.SYS", + 437, + 6, + { + { + (VOID FAR *) & nlsInfo.upNCsize, 2 + } + , + { + (VOID FAR *) & nlsInfo.upFCsize, 4 + } + , + { + (VOID FAR *) & nlsInfo.nlsFn, 5 + } + , + { + (VOID FAR *) & nlsInfo.collSize, 6 + } + , + { + (VOID FAR *) & nlsInfo.nlsExtCtryInfo.countryCode, 1 + } + , + { + (VOID FAR *) & nlsInfo.dbcSize, 7 + } + } + , + + 1, /* country code */ + 437, /* code page */ + { + 0, /* date format */ + { + /* currency string */ + '$', '\x00', '\x00', '\x00', '\x00', /* 0 - 4 */ + } + , + { /* thousand separator */ + ',', '\x00' /* 0 - 1 */ + } + , + { /* decimal point */ + '.', '\x00' /* 0 - 1 */ + } + , + { /* date separator */ + '-', '\x00' /* 0 - 1 */ + } + , + { /* time separator */ + ':', '\x00' /* 0 - 1 */ + } + , + 0, /* currency format */ + 2, /* currency prescision */ + 0, /* time format */ + CharMapSrvc, /* upcase function */ + { /* data separator */ + ',', '\x00' /* 0 - 1 */ + } + } + } + , + 'Y', 'N', /* Yes/No prompt characters */ + 128, /* upcase table */ + { + '\x80', '\x9a', 'E', 'A', '\x8e', 'A', '\x8f', '\x80' /* 0 - 7 */ + ,'E', 'E', 'E', 'I', 'I', 'I', '\x8e', '\x8f' /* 8 - 15 */ + ,'\x90', '\x92', '\x92', 'O', '\x99', 'O', 'U', 'U' /* 16 - 23 */ + ,'Y', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f' /* 24 - 31 */ + ,'A', 'I', 'O', 'U', '\xa5', '\xa5', '\xa6', '\xa7' /* 32 - 39 */ + ,'\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf' /* 40 - 47 */ + ,'\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7' /* 48 - 55 */ + ,'\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf' /* 56 - 63 */ + ,'\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7' /* 64 - 71 */ + ,'\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf' /* 72 - 79 */ + ,'\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7' /* 80 - 87 */ + ,'\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf' /* 88 - 95 */ + ,'\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7' /* 96 - 103 */ + ,'\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef' /* 104 - 111 */ + ,'\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7' /* 112 - 119 */ + ,'\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff' /* 120 - 127 */ + } + , + 128, /* file name upcase table */ + { + '\x80', '\x9a', 'E', 'A', '\x8e', 'A', '\x8f', '\x80' /* 0 - 7 */ + ,'E', 'E', 'E', 'I', 'I', 'I', '\x8e', '\x8f' /* 8 - 15 */ + ,'\x90', '\x92', '\x92', 'O', '\x99', 'O', 'U', 'U' /* 16 - 23 */ + ,'Y', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f' /* 24 - 31 */ + ,'A', 'I', 'O', 'U', '\xa5', '\xa5', '\xa6', '\xa7' /* 32 - 39 */ + ,'\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf' /* 40 - 47 */ + ,'\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7' /* 48 - 55 */ + ,'\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf' /* 56 - 63 */ + ,'\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7' /* 64 - 71 */ + ,'\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf' /* 72 - 79 */ + ,'\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7' /* 80 - 87 */ + ,'\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf' /* 88 - 95 */ + ,'\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7' /* 96 - 103 */ + ,'\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef' /* 104 - 111 */ + ,'\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7' /* 112 - 119 */ + ,'\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff' /* 120 - 127 */ + } + , + 256, /* collating sequence table */ + { + '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07' /* 0 - 7 */ + ,'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f' /* 8 - 15 */ + ,'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17' /* 16 - 23 */ + ,'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f' /* 24 - 31 */ + ,' ', '!', '"', '#', '$', '%', '&', '\'' /* 32 - 39 */ + ,'(', ')', '*', '+', ',', '-', '.', '/' /* 40 - 47 */ + ,'0', '1', '2', '3', '4', '5', '6', '7' /* 48 - 55 */ + ,'8', '9', ':', ';', '<', '=', '>', '?' /* 56 - 63 */ + ,'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G' /* 64 - 71 */ + ,'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O' /* 72 - 79 */ + ,'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W' /* 80 - 87 */ + ,'X', 'Y', 'Z', '[', '\\', ']', '^', '_' /* 88 - 95 */ + ,'`', 'A', 'B', 'C', 'D', 'E', 'F', 'G' /* 96 - 103 */ + ,'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O' /* 104 - 111 */ + ,'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W' /* 112 - 119 */ + ,'X', 'Y', 'Z', '{', '|', '}', '~', '\x7f' /* 120 - 127 */ + ,'C', 'U', 'E', 'A', 'A', 'A', 'A', 'C' /* 128 - 135 */ + ,'E', 'E', 'E', 'I', 'I', 'I', 'A', 'A' /* 136 - 143 */ + ,'E', 'A', 'A', 'O', 'O', 'O', 'U', 'U' /* 144 - 151 */ + ,'Y', 'O', 'U', '$', '$', '$', '$', '$' /* 152 - 159 */ + ,'A', 'I', 'O', 'U', 'N', 'N', '\xa6', '\xa7' /* 160 - 167 */ + ,'?', '\xa9', '\xaa', '\xab', '\xac', '!', '"', '"' /* 168 - 175 */ + ,'\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7' /* 176 - 183 */ + ,'\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf' /* 184 - 191 */ + ,'\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7' /* 192 - 199 */ + ,'\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf' /* 200 - 207 */ + ,'\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7' /* 208 - 215 */ + ,'\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf' /* 216 - 223 */ + ,'\xe0', 'S', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7' /* 224 - 231 */ + ,'\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef' /* 232 - 239 */ + ,'\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7' /* 240 - 247 */ + ,'\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff' /* 248 - 255 */ + } + , + 0, /* no DBC support */ + 0, /* DBC end marker */ + { + 22, /* size of permittable character structure */ + 1, /* reserved */ + '\x00', '\xff', /* first/last permittable character */ + 0, /* reserved */ + '\x00', ' ', /* first/last excluded character */ + 2, /* reserved */ + 14, /* number of separators */ + { /* separators */ + '.', '"', '/', '\\', '[', ']', ':', '|', /* 0 - 7 */ + '<', '>', '+', '=', ';', ',' /* 8 - 13 */ + } + } +} diff --git a/kernel/apisupt.asm b/kernel/apisupt.asm new file mode 100644 index 0000000..efbd2b0 --- /dev/null +++ b/kernel/apisupt.asm @@ -0,0 +1,169 @@ +; File: +; apisupt.asm +; Description: +; Assembly support routines for stack manipulation, etc. +; +; Copyright (c) 1995, 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Id$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:34:52 jhall1 +; Initial revision +; +; Revision 1.2 1999/08/10 17:57:12 jprice +; ror4 2011-02 patch +; +; Revision 1.1.1.1 1999/03/29 15:40:38 jprice +; New version without IPL.SYS +; +; Revision 1.4 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; Revision 1.3 1999/02/01 01:48:41 jprice +; Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) +; +; Revision 1.2 1999/01/22 04:13:25 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:01 jprice +; Imported sources +; +; Rev 1.4 06 Dec 1998 8:47:02 patv +;Expanded due to new I/O subsystem. +; +; Rev 1.3 16 Jan 1997 12:46:44 patv +;pre-Release 0.92 feature additions +; +; Rev 1.2 29 May 1996 21:03:38 patv +;bug fixes for v0.91a +; +; Rev 1.1 01 Sep 1995 17:54:26 patv +;First GPL release. +; +; Rev 1.0 02 Jul 1995 9:04:50 patv +;Initial revision. +; $EndLog$ +; + + %include "segs.inc" + + extern _api_sp:wrt DGROUP ; api stacks - for context + extern _api_ss:wrt DGROUP ; switching + extern _usr_sp:wrt DGROUP ; user stacks + extern _usr_ss:wrt DGROUP + +segment _TEXT + global _set_stack +; +; void far set_stack(void) - +; save current stack and setup our local stack +; +_set_stack: + + ; save foreground stack + + ; we need to get the return values from the stack + ; since the current stack will change + pop ax ;get return offset + pop bx ;get return segment + + ; Save the flags so that we can restore correct interrupt + ; state later. We need to disable interrupts so that we + ; don't trash memory with new sp-old ss combination + pushf + pop dx + cli + + ; save bp + push bp + + mov cx, sp + neg cx + + ; save away foreground process' stack + push word [_usr_ss] + push word [_usr_sp] + + mov word [_usr_ss],ss + mov word [_usr_sp],sp + + ; setup our local stack + mov ss,word [_api_ss] + mov sp,word [_api_sp] + + add cx, sp + add bp, cx + + ; setup for ret + push bx + push ax + + ; now restore interrupt state + push dx + popf + + retf + +; +; void far restore_stack(void) - +; restore foreground stack, throw ours away +; + global _restore_stack +_restore_stack: + + ; we need to get the return values from the stack + ; since the current stack will change + pop cx ;get return offset + pop bx ;get return segment + + ; Save the flags so that we can restore correct interrupt + ; state later. We need to disable interrupts so that we + ; don't trash memory with new sp-old ss combination + pushf + pop dx + cli + + ; save background stack + mov word [_api_ss],ss + mov word [_api_sp],sp + + ; restore foreground stack here + mov ss,word [_usr_ss] + mov sp,word [_usr_sp] + + pop word [_usr_sp] + pop word [_usr_ss] + + ; make bp relative to our stack frame + pop bp + ;mov bp,sp + + ; setup for ret + push bx + push cx + + ; now restore interrupt state + push dx + popf + + retf diff --git a/kernel/asmsupt.asm b/kernel/asmsupt.asm new file mode 100644 index 0000000..32194d7 --- /dev/null +++ b/kernel/asmsupt.asm @@ -0,0 +1,195 @@ +; File: +; asmsupt.asm +; Description: +; Assembly support routines for miscellaneous functions +; +; Copyright (c) 1995, 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Id$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:34:52 jhall1 +; Initial revision +; +; Revision 1.3 1999/08/10 17:57:12 jprice +; ror4 2011-02 patch +; +; Revision 1.2 1999/04/23 04:24:39 jprice +; Memory manager changes made by ska +; +; Revision 1.1.1.1 1999/03/29 15:40:41 jprice +; New version without IPL.SYS +; +; Revision 1.4 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; Revision 1.3 1999/02/01 01:48:41 jprice +; Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) +; +; Revision 1.2 1999/01/22 04:13:25 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:01 jprice +; Imported sources +; +; Rev 1.4 06 Dec 1998 8:46:50 patv +; Bug fixes. +; +; Rev 1.3 03 Jan 1998 8:36:44 patv +; Converted data area to SDA format +; +; Rev 1.2 29 May 1996 21:03:38 patv +; bug fixes for v0.91a +; +; Rev 1.1 01 Sep 1995 17:54:26 patv +; First GPL release. +; +; Rev 1.0 05 Jul 1995 11:38:42 patv +; Initial revision. +; $EndLog$ +; + + %include "segs.inc" + +segment _TEXT +; +; VOID bcopy(s, d, n) +; REG BYTE *s, *d; +; REG COUNT n; +; +; + global _bcopy +_bcopy: + push bp ; Standard C entry + mov bp,sp + push si + push di + push ds + push es + + ; Get the repitition count, n + mov cx,[bp+8] + jcxz bcopy_exit + + ; Set both ds and es to same segment (for near copy) + mov ax,ds + mov es,ax + + ; Get the source pointer, ss + mov si,[bp+4] + + ; and the destination pointer, d + mov di,[bp+6] + +?doIt: + ; Set direction to autoincrement + cld + + ; And do the built-in byte copy, but do a 16-bit transfer + ; whenever possible. + mov al, cl + and al,1 ; test for odd count + jz b_even + movsb +b_even: shr cx,1 + rep movsw + + ; Finally do a C exit to return +fbcopy_exit: +bcopy_exit: pop es + pop ds + pop di + pop si + pop bp + ret + + +; +; VOID fbcopy(s, d, n) +; +; REG VOID FAR *s, FAR *d; +; REG COUNT n; + global _fbcopy +_fbcopy: + push bp ; Standard C entry + mov bp,sp + push si + push di + + ; Save ds, since we won't necessarily be within our + ; small/tiny environment + push ds + push es + + ; Get the repititon count, n + mov cx,[bp+12] + jcxz fbcopy_exit + + ; Get the far source pointer, s + lds si,[bp+4] + + ; Get the far destination pointer d + les di,[bp+8] + + jmp short ?doIt + +; +; VOID fmemset(s, ch, n) +; +; REG VOID FAR *s +; REG int ch +; REG COUNT n; + global _fmemset +_fmemset: + push bp ; Standard C entry + mov bp,sp + push di + + ; Save ds, since we won't necessarily be within our + ; small/tiny environment + push es + + ; Get the repititon count, n + mov cx,[bp+10] + jcxz fmemset_exit + + ; Get the far source pointer, s + les di,[bp+4] + + ; Test if odd or even + mov al, cl + and al, 1 + + ; Get the far destination pointer ch + mov al,[bp+8] + mov ah, al + + jz m_even + stosb +m_even: shr cx,1 + rep stosw + + +fmemset_exit: pop es + pop di + pop bp + ret diff --git a/kernel/blockio.c b/kernel/blockio.c new file mode 100644 index 0000000..b5eb874 --- /dev/null +++ b/kernel/blockio.c @@ -0,0 +1,587 @@ +/****************************************************************/ +/* */ +/* blockio.c */ +/* DOS-C */ +/* */ +/* Block cache functions and device driver interface */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/* */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *blockioRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:53 jhall1 + * Initial revision + * + * Revision 1.14 2000/03/09 06:07:10 kernel + * 2017f updates by James Tabor + * + * Revision 1.13 1999/08/25 03:18:07 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.12 1999/08/10 18:03:39 jprice + * ror4 2011-03 patch + * + * Revision 1.11 1999/05/03 06:25:45 jprice + * Patches from ror4 and many changed of signed to unsigned variables. + * + * Revision 1.10 1999/05/03 04:55:35 jprice + * Changed getblock & getbuf so that they leave at least 3 buffer for FAT data. + * + * Revision 1.9 1999/04/21 01:44:40 jprice + * no message + * + * Revision 1.8 1999/04/18 05:28:39 jprice + * no message + * + * Revision 1.7 1999/04/16 21:43:40 jprice + * ror4 multi-sector IO + * + * Revision 1.6 1999/04/16 00:53:32 jprice + * Optimized FAT handling + * + * Revision 1.5 1999/04/12 23:41:53 jprice + * Using getbuf to write data instead of getblock + * using getblock made it read the block before it wrote it + * + * Revision 1.4 1999/04/11 05:28:10 jprice + * Working on multi-block IO + * + * Revision 1.3 1999/04/11 04:33:38 jprice + * ror4 patches + * + * Revision 1.1.1.1 1999/03/29 15:41:43 jprice + * New version without IPL.SYS + * + * Revision 1.5 1999/02/09 02:54:23 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/01 01:43:27 jprice + * Fixed findfirst function to find volume label with Windows long filenames + * + * Revision 1.3 1999/01/30 08:25:34 jprice + * Clean up; Fixed bug with set attribute function. If you tried to + * change the attributes of a directory, it would erase it. + * + * Revision 1.2 1999/01/22 04:15:28 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * + * Rev 1.8 06 Dec 1998 8:43:16 patv + * Changes in block I/O because of new I/O subsystem. + * + * Rev 1.7 22 Jan 1998 4:09:00 patv + * Fixed pointer problems affecting SDA + * + * Rev 1.6 04 Jan 1998 23:14:36 patv + * Changed Log for strip utility + * + * Rev 1.5 03 Jan 1998 8:36:02 patv + * Converted data area to SDA format + * + * Rev 1.4 16 Jan 1997 12:46:34 patv + * pre-Release 0.92 feature additions + * + * Rev 1.3 29 May 1996 21:15:10 patv + * bug fixes for v0.91a + * + * Rev 1.2 01 Sep 1995 17:48:46 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:50:28 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:04:06 patv + * Initial revision. + */ + +/************************************************************************/ +/* */ +/* block cache routines */ +/* */ +/************************************************************************/ + +/* */ +/* Initialize the buffer structure */ +/* */ +/* XXX: This should go into `INIT_TEXT'. -- ror4 */ +VOID FAR init_buffers(void) +{ + REG WORD i; + REG WORD count; + + for (i = 0; i < Config.cfgBuffers; ++i) + { + buffers[i].b_unit = 0; + buffers[i].b_flag = 0; + buffers[i].b_blkno = 0; + buffers[i].b_copies = 0; + buffers[i].b_offset_lo = 0; + buffers[i].b_offset_hi = 0; + if (i < (Config.cfgBuffers - 1)) + buffers[i].b_next = &buffers[i + 1]; + else + buffers[i].b_next = NULL; + } + firstbuf = &buffers[0]; + lastbuf = &buffers[Config.cfgBuffers - 1]; +} + +/* Extract the block number from a buffer structure. */ +ULONG getblkno(struct buffer FAR * bp) +{ + if (bp->b_blkno == 0xffffu) + return bp->b_huge_blkno; + else + return bp->b_blkno; +} + +/* Set the block number of a buffer structure. (The caller should */ +/* set the unit number before calling this function.) */ +VOID setblkno(struct buffer FAR * bp, ULONG blkno) +{ + if (blkno >= 0xffffu) + { + bp->b_blkno = 0xffffu; + bp->b_huge_blkno = blkno; + } + else + { + bp->b_blkno = blkno; + bp->b_dpbp = &blk_devices[bp->b_unit]; + } +} + +/* */ +/* Return the address of a buffer structure containing the */ +/* requested block. */ +/* */ +/* returns: */ +/* requested block with data */ +/* failure: */ +/* returns NULL */ +/* */ +struct buffer FAR *getblock(ULONG blkno, COUNT dsk) +{ + REG struct buffer FAR *bp; + REG struct buffer FAR *lbp; + REG struct buffer FAR *mbp; + REG BYTE fat_count = 0; + + /* Search through buffers to see if the required block */ + /* is already in a buffer */ + +#ifdef DISPLAY_GETBLOCK + printf("[getblock %d, blk %ld, buf ", dsk, blkno); +#endif + bp = firstbuf; + lbp = NULL; + mbp = NULL; + while (bp != NULL) + { + if ((bp->b_flag & BFR_VALID) && (bp->b_unit == dsk) + && (getblkno(bp) == blkno)) + { + /* found it -- rearrange LRU links */ + if (lbp != NULL) + { + lbp->b_next = bp->b_next; + bp->b_next = firstbuf; + firstbuf = bp; + } +#ifdef DISPLAY_GETBLOCK + printf("HIT]\n"); +#endif + return (bp); + } + else + { + if (bp->b_flag & BFR_FAT) + fat_count++; + mbp = lbp; /* move along to next buffer */ + lbp = bp; + bp = bp->b_next; + } + } + /* The block we need is not in a buffer, we must make a buffer */ + /* available, and fill it with the desired block */ + + /* detach lru buffer */ +#ifdef DISPLAY_GETBLOCK + printf("MISS]\n"); +#endif + + /* make sure we keep at least 3 buffers for the FAT. If this is not a */ + /* FAT buffer, or there are at least 3 already, then we can use this */ + /* buffer. */ + /* otherwise, search again, and find the last non-FAT buffer. */ + if ((lbp->b_flag & BFR_FAT) && (fat_count < 3)) + { + bp = firstbuf; + lbp = NULL; + mbp = NULL; + while ((bp != NULL) && (bp->b_flag & BFR_FAT)) + { + /* if this is a FAT buffer, then move to the next one, else we found */ + /* the one we want. */ + mbp = lbp; /* move along to next buffer */ + lbp = bp; + bp = bp->b_next; + } + /* if we get to the end of the list here, then we must only have 3 */ + /* buffers, which is not suppose to happen, but if it does, then we */ + /* end up using the last buffer (even though it is FAT). */ + + if (bp == NULL) + { + /* put lbp at the top of the chain. */ + if (mbp != NULL) + mbp->b_next = NULL; + lbp->b_next = firstbuf; + firstbuf = bp = lbp; + } + else if (lbp != NULL) + { + lbp->b_next = bp->b_next; + bp->b_next = firstbuf; + firstbuf = bp; + } + lbp = bp; + } + else + { + /* put lbp at the top of the chain. */ + if (mbp != NULL) + mbp->b_next = NULL; + lbp->b_next = firstbuf; + firstbuf = lbp; + } + + /* take the buffer than lbp points to and flush it, then read new block. */ + if (flush1(lbp) && fill(lbp, blkno, dsk)) /* success */ + mbp = lbp; + else + mbp = NULL; /* failure */ + return (mbp); +} + +/* + Return the address of a buffer structure for the + requested block. This is for writing new data to a block, so + we really don't care what is in the buffer now. + + returns: + TRUE = buffer available, flushed if necessary + parameter is filled with pointer to buffer + FALSE = there was an error flushing the buffer. + parameter is set to NULL + */ +BOOL getbuf(struct buffer FAR ** pbp, ULONG blkno, COUNT dsk) +{ + REG struct buffer FAR *bp; + REG struct buffer FAR *lbp; + REG struct buffer FAR *mbp; + REG BYTE fat_count = 0; + + /* Search through buffers to see if the required block */ + /* is already in a buffer */ + +#ifdef DISPLAY_GETBLOCK + printf("[getbuf %d, blk %ld, buf ", dsk, blkno); +#endif + bp = firstbuf; + lbp = NULL; + mbp = NULL; + while (bp != NULL) + { + if ((bp->b_flag & BFR_VALID) && (bp->b_unit == dsk) + && (getblkno(bp) == blkno)) + { + /* found it -- rearrange LRU links */ + if (lbp != NULL) + { + lbp->b_next = bp->b_next; + bp->b_next = firstbuf; + firstbuf = bp; + } + *pbp = bp; +#ifdef DISPLAY_GETBLOCK + printf("HIT]\n"); +#endif + return TRUE; + } + else + { + if (bp->b_flag & BFR_FAT) + fat_count++; + mbp = lbp; /* move along to next buffer */ + lbp = bp; + bp = bp->b_next; + } + } + /* The block we need is not in a buffer, we must make a buffer */ + /* available. */ + +#ifdef DISPLAY_GETBLOCK + printf("MISS]\n"); +#endif + + /* make sure we keep at least 3 buffers for the FAT. If this is not a */ + /* FAT buffer, or there are at least 3 already, then we can use this */ + /* buffer. */ + /* otherwise, search again, and find the last non-FAT buffer. */ + if ((lbp->b_flag & BFR_FAT) && (fat_count < 3)) + { + bp = firstbuf; + lbp = NULL; + mbp = NULL; + while ((bp != NULL) && (bp->b_flag & BFR_FAT)) + { + /* if this is a FAT buffer, then move to the next one, else we found */ + /* the one we want. */ + mbp = lbp; /* move along to next buffer */ + lbp = bp; + bp = bp->b_next; + } + /* if we get to the end of the list here, then we must only have 3 */ + /* buffers, which is not suppose to happen, but if it does, then we */ + /* end up using the last buffer (even though it is FAT). */ + + if (bp == NULL) + { + /* put lbp at the top of the chain. */ + if (mbp != NULL) + mbp->b_next = NULL; + lbp->b_next = firstbuf; + firstbuf = bp = lbp; + } + else if (lbp != NULL) + { + lbp->b_next = bp->b_next; + bp->b_next = firstbuf; + firstbuf = bp; + } + lbp = bp; + } + else + { + /* put lbp at the top of the chain. */ + if (mbp != NULL) + mbp->b_next = NULL; + lbp->b_next = firstbuf; + firstbuf = lbp; + } + + /* take the buffer than lbp points to and flush it, then make it available. */ + if (flush1(lbp)) /* success */ + { + lbp->b_flag = 0; + lbp->b_unit = dsk; + setblkno(lbp, blkno); + *pbp = lbp; + return TRUE; + } + else + /* failure */ + { + *pbp = NULL; + return FALSE; + } +} + +/* */ +/* Mark all buffers for a disk as not valid */ +/* */ +VOID setinvld(REG COUNT dsk) +{ + REG struct buffer FAR *bp; + + bp = firstbuf; + while (bp) + { + if (bp->b_unit == dsk) + bp->b_flag = 0; + bp = bp->b_next; + } +} + +/* */ +/* Flush all buffers for a disk */ +/* */ +/* returns: */ +/* TRUE on success */ +/* */ +BOOL flush_buffers(REG COUNT dsk) +{ + REG struct buffer FAR *bp; + REG BOOL ok = TRUE; + + bp = firstbuf; + while (bp) + { + if (bp->b_unit == dsk) + if (!flush1(bp)) + ok = FALSE; + bp = bp->b_next; + } + return ok; +} + +/* */ +/* Write one disk buffer */ +/* */ +BOOL flush1(struct buffer FAR * bp) +{ + REG WORD ok; + + if ((bp->b_flag & BFR_VALID) && (bp->b_flag & BFR_DIRTY)) + { + ok = dskxfer(bp->b_unit, getblkno(bp), + (VOID FAR *) bp->b_buffer, 1, DSKWRITE); + if (bp->b_flag & BFR_FAT) + { + int i = bp->b_copies; + LONG blkno = getblkno(bp); + UWORD offset = ((UWORD) bp->b_offset_hi << 8) | bp->b_offset_lo; + + while (--i > 0) + { + blkno += offset; + ok &= dskxfer(bp->b_unit, blkno, + (VOID FAR *) bp->b_buffer, 1, DSKWRITE); + } + } + } + else + ok = TRUE; + bp->b_flag &= ~BFR_DIRTY; /* even if error, mark not dirty */ + if (!ok) /* otherwise system has trouble */ + bp->b_flag &= ~BFR_VALID; /* continuing. */ + return (ok); +} + +/* */ +/* Write all disk buffers */ +/* */ +BOOL flush(void) +{ + REG struct buffer FAR *bp; + REG BOOL ok; + + ok = TRUE; + bp = firstbuf; + while (bp) + { + if (!flush1(bp)) + ok = FALSE; + bp->b_flag &= ~BFR_VALID; + bp = bp->b_next; + } + + int2f_Remote_call(REM_FLUSHALL, 0, 0, 0, 0, 0, 0); + + return (ok); +} + +/* */ +/* Fill the indicated disk buffer with the current track and sector */ +/* */ +/* This function assumes that the buffer is ready for use and that the + sector is not already in the buffer ring */ +BOOL fill(REG struct buffer FAR * bp, ULONG blkno, COUNT dsk) +{ + REG WORD ok; + + ok = dskxfer(dsk, blkno, (VOID FAR *) bp->b_buffer, 1, DSKREAD); + bp->b_flag = BFR_VALID | BFR_DATA; + bp->b_unit = dsk; + setblkno(bp, blkno); + return (ok); +} + +/************************************************************************/ +/* */ +/* Device Driver Interface Functions */ +/* */ +/************************************************************************/ +/* */ +/* Transfer one or more blocks to/from disk */ +/* */ +BOOL dskxfer(COUNT dsk, ULONG blkno, VOID FAR * buf, UWORD numblocks, COUNT mode) +{ + REG struct dpb *dpbp = &blk_devices[dsk]; + + for (;;) + { + IoReqHdr.r_length = sizeof(request); + IoReqHdr.r_unit = dpbp->dpb_subunit; + IoReqHdr.r_command = + mode == DSKWRITE ? + (verify_ena ? C_OUTVFY : C_OUTPUT) + : C_INPUT; + IoReqHdr.r_status = 0; + IoReqHdr.r_meddesc = dpbp->dpb_mdb; + IoReqHdr.r_trans = (BYTE FAR *) buf; + IoReqHdr.r_count = numblocks; + if (blkno >= MAXSHORT) + { + IoReqHdr.r_start = HUGECOUNT; + IoReqHdr.r_huge = blkno; + } + else + IoReqHdr.r_start = blkno; + execrh((request FAR *) & IoReqHdr, dpbp->dpb_device); + if (!(IoReqHdr.r_status & S_ERROR) && (IoReqHdr.r_status & S_DONE)) + break; + else + { + loop: + switch (block_error(&IoReqHdr, dpbp->dpb_unit, dpbp->dpb_device)) + { + case ABORT: + case FAIL: + return FALSE; + + case RETRY: + continue; + + case CONTINUE: + break; + + default: + goto loop; + } + } + } + return TRUE; +} diff --git a/kernel/break.c b/kernel/break.c new file mode 100644 index 0000000..fe84ebf --- /dev/null +++ b/kernel/break.c @@ -0,0 +1,84 @@ +/****************************************************************/ +/* */ +/* break.c */ +/* FreeDOS */ +/* */ +/* Control Break detection and handling */ +/* */ +/* Copyright (c) 1999 */ +/* Steffen Kaiser */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +extern void spawn_int23(void); + +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:54 jhall1 + * Initial revision + * + * Revision 1.2 2000/03/09 06:07:10 kernel + * 2017f updates by James Tabor + * + * Revision 1.1 1999/04/16 21:18:17 jprice + * Steffen contributed. + * + */ + +#define CB_FLG *(UBYTE FAR*)MK_FP(0x40, 0x71) +#define CB_MSK 0x80 + +/* Check for ^Break. + + * Two sources are available: + * 1) flag at 40:71 bit 7 + * 2) STDIN str‘am via con_break() + */ +int control_break(void) +{ + return (CB_FLG & CB_MSK) || con_break(); +} + +/* + * Handles a ^Break state + * + * Actions: + * 1) clear the ^Break flag + * 2) clear the STDIN stream + * 3) decrease the InDOS flag as the kernel drops back to user space + * 4) invoke INT-23 and never come back + */ +void handle_break(void) +{ + CB_FLG &= ~CB_MSK; /* reset the ^Break flag */ + KbdFlush(); /* Er, this is con_flush() */ + if (!ErrorMode) /* within int21_handler, InDOS is not incremented */ + if (InDOS) + --InDOS; /* fail-safe */ + + spawn_int23(); /* invoke user INT-23 and never come back */ +} diff --git a/kernel/chario.c b/kernel/chario.c new file mode 100644 index 0000000..77b9e67 --- /dev/null +++ b/kernel/chario.c @@ -0,0 +1,404 @@ +/****************************************************************/ +/* */ +/* chario.c */ +/* DOS-C */ +/* */ +/* Character device functions and device driver interface */ +/* */ +/* Copyright (c) 1994 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/* */ +/****************************************************************/ + +#include "portab.h" + +#ifdef VERSION_STRINGS +static BYTE *charioRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:54 jhall1 + * Initial revision + * + * Revision 1.7 2000/03/09 06:07:10 kernel + * 2017f updates by James Tabor + * + * Revision 1.6 1999/09/23 04:40:45 jprice + * *** empty log message *** + * + * Revision 1.4 1999/08/25 03:18:07 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.3 1999/04/16 12:21:21 jprice + * Steffen c-break handler changes + * + * Revision 1.2 1999/04/04 18:51:42 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:41:45 jprice + * New version without IPL.SYS + * + * Revision 1.5 1999/02/09 02:54:23 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/04 03:18:37 jprice + * Formating. Added comments. + * + * Revision 1.3 1999/02/01 01:43:28 jprice + * Fixed findfirst function to find volume label with Windows long filenames + * + * Revision 1.2 1999/01/22 04:15:28 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * + * Rev 1.9 06 Dec 1998 8:43:36 patv + * changes in character I/O because of new I/O subsystem. + * + * Rev 1.8 11 Jan 1998 2:06:08 patv + * Added functionality to ioctl. + * + * Rev 1.7 08 Jan 1998 21:36:40 patv + * Changed automatic requestic packets to static to save stack space. + * + * Rev 1.6 04 Jan 1998 23:14:38 patv + * Changed Log for strip utility + * + * Rev 1.5 30 Dec 1997 4:00:20 patv + * Modified to support SDA + * + * Rev 1.4 16 Jan 1997 12:46:36 patv + * pre-Release 0.92 feature additions + * + * Rev 1.3 29 May 1996 21:15:12 patv + * bug fixes for v0.91a + * + * Rev 1.2 01 Sep 1995 17:48:42 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:50:26 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:05:44 patv + * Initial revision. + * + */ + +#include "globals.h" + +static BYTE *con_name = "CON"; + +#ifdef PROTO +VOID kbfill(keyboard FAR *, UCOUNT, BOOL, UWORD *); +struct dhdr FAR *finddev(UWORD attr_mask); + +#else +VOID kbfill(); +struct dhdr FAR *finddev(); +#endif + +/* Return a pointer to the first driver in the chain that + * matches the attributes. + */ + +struct dhdr FAR *finddev(UWORD attr_mask) +{ + struct dhdr far *dh; + + for (dh = nul_dev.dh_next; FP_OFF(dh) != 0xFFFF; dh = dh->dh_next) + { + if (dh->dh_attr & attr_mask) + return dh; + } + + /* return dev/null if no matching driver found */ + return &nul_dev; +} +/* + VOID cso(COUNT c) + { + BYTE buf = c; + struct dhdr FAR *lpDevice; + + CharReqHdr.r_length = sizeof(request); + CharReqHdr.r_command = C_OUTPUT; + CharReqHdr.r_count = 1; + CharReqHdr.r_trans = (BYTE FAR *) (&buf); + CharReqHdr.r_status = 0; + execrh((request FAR *) & CharReqHdr, + lpDevice = (struct dhdr FAR *)finddev(ATTR_CONOUT)); + if (CharReqHdr.r_status & S_ERROR) + char_error(&CharReqHdr, lpDevice); + } + */ + +VOID sto(COUNT c) +{ + static COUNT scratch; /* make this static to save stack space */ + + DosWrite(STDOUT, 1, (BYTE FAR *) & c, (COUNT FAR *) scratch); +} + +VOID mod_sto(REG UCOUNT c) +{ + if (c < ' ' && c != HT) + { + sto('^'); + sto(c + '@'); + } + else + sto(c); +} + +VOID destr_bs(void) +{ + sto(BS); + sto(' '); + sto(BS); +} + +VOID Do_DosIdle_loop(void) +{ + FOREVER + { + if (StdinBusy()) + return; + else + { + DosIdle_int(); + continue; + } + } +} + +UCOUNT _sti(void) +{ + static COUNT scratch; + UBYTE c; + /* + * XXX: If there's a read error, this will just keep retrying the read until + * the error disappears. Maybe it should do something else instead. -- ror4 + */ + while (GenericRead(STDIN, 1, (BYTE FAR *) & c, (COUNT FAR *) & scratch, TRUE) + != 1) ; + return c; +} + +BOOL con_break(void) +{ + CharReqHdr.r_unit = 0; + CharReqHdr.r_status = 0; + CharReqHdr.r_command = C_NDREAD; + CharReqHdr.r_length = sizeof(request); + execrh((request FAR *) & CharReqHdr, (struct dhdr FAR *)finddev(ATTR_CONIN)); + if (CharReqHdr.r_status & S_BUSY) + return FALSE; + if (CharReqHdr.r_ndbyte == CTL_C) + { + _sti(); + return TRUE; + } + else + return FALSE; +} + +BOOL StdinBusy(void) +{ + sft FAR *s; + + if ((s = get_sft(STDIN)) == (sft FAR *) - 1) + return FALSE; /* XXX */ + if (s->sft_count == 0 || (s->sft_mode & SFT_MWRITE)) + return FALSE; /* XXX */ + if (s->sft_flags & SFT_FDEVICE) + { + CharReqHdr.r_unit = 0; + CharReqHdr.r_status = 0; + CharReqHdr.r_command = C_ISTAT; + CharReqHdr.r_length = sizeof(request); + execrh((request FAR *) & CharReqHdr, s->sft_dev); + if (CharReqHdr.r_status & S_BUSY) + return TRUE; + else + return FALSE; + } + else + return FALSE; /* XXX */ +} + +VOID KbdFlush(void) +{ + CharReqHdr.r_unit = 0; + CharReqHdr.r_status = 0; + CharReqHdr.r_command = C_IFLUSH; + CharReqHdr.r_length = sizeof(request); + execrh((request FAR *) & CharReqHdr, (struct dhdr FAR *)finddev(ATTR_CONIN)); +} + +static VOID kbfill(keyboard FAR * kp, UCOUNT c, BOOL ctlf, UWORD * vp) +{ + if (kp->kb_count > kp->kb_size) + { + sto(BELL); + return; + } + kp->kb_buf[kp->kb_count++] = c; + if (!ctlf) + { + mod_sto(c); + *vp += 2; + } + else + { + sto(c); + if (c != HT) + ++ * vp; + else + *vp = (*vp + 8) & -8; + } +} + +VOID sti(keyboard FAR * kp) +{ + REG UWORD c, + cu_pos = scr_pos; + UWORD + virt_pos = scr_pos; + WORD init_count = kp->kb_count; +#ifndef NOSPCL + static BYTE local_buffer[LINESIZE]; +#endif + + if (kp->kb_size == 0) + return; + if (kp->kb_size <= kp->kb_count || kp->kb_buf[kp->kb_count] != CR) + kp->kb_count = 0; + FOREVER + { + + Do_DosIdle_loop(); + + switch (c = _sti()) + { + case CTL_C: + handle_break(); + case CTL_F: + continue; + +#ifndef NOSPCL + case SPCL: + switch (c = _sti()) + { + case LEFT: + goto backspace; + + case F3: + { + REG COUNT i; + + for (i = kp->kb_count; local_buffer[i] != '\0'; i++) + { + c = local_buffer[kp->kb_count]; + if (c == '\r' || c == '\n') + break; + kbfill(kp, c, FALSE, &virt_pos); + } + break; + } + + case RIGHT: + c = local_buffer[kp->kb_count]; + if (c == '\r' || c == '\n') + break; + kbfill(kp, c, FALSE, &virt_pos); + break; + } + break; +#endif + + case CTL_BS: + case BS: + backspace: + if (kp->kb_count > 0) + { + if (kp->kb_buf[kp->kb_count - 1] >= ' ') + { + destr_bs(); + --virt_pos; + } + else if ((kp->kb_buf[kp->kb_count - 1] < ' ') + && (kp->kb_buf[kp->kb_count - 1] != HT)) + { + destr_bs(); + destr_bs(); + virt_pos -= 2; + } + else if (kp->kb_buf[kp->kb_count - 1] == HT) + { + do + { + destr_bs(); + --virt_pos; + } + while ((virt_pos > cu_pos) && (virt_pos & 7)); + } + --kp->kb_count; + } + break; + + case CR: + kbfill(kp, CR, TRUE, &virt_pos); + kbfill(kp, LF, TRUE, &virt_pos); +#ifndef NOSPCL + fbcopy((BYTE FAR *) kp->kb_buf, + (BYTE FAR *) local_buffer, (COUNT) kp->kb_count); + local_buffer[kp->kb_count] = '\0'; +#endif + return; + + case LF: + sto(CR); + sto(LF); + break; + + case ESC: + sto('\\'); + sto(CR); + sto(LF); + for (c = 0; c < cu_pos; c++) + sto(' '); + kp->kb_count = init_count; + break; + + default: + kbfill(kp, c, FALSE, &virt_pos); + break; + } + } +} + +VOID FAR init_call_sti(keyboard FAR * kp) +{ + sti(kp); +} diff --git a/kernel/config.c b/kernel/config.c new file mode 100644 index 0000000..338cca8 --- /dev/null +++ b/kernel/config.c @@ -0,0 +1,925 @@ +/****************************************************************/ +/* */ +/* config.c */ +/* DOS-C */ +/* */ +/* config.sys Processing Functions */ +/* */ +/* Copyright (c) 1996 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "init-mod.h" + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:56 jhall1 + * Initial revision + * + * Revision 1.13 2000/03/09 06:07:10 kernel + * 2017f updates by James Tabor + * + * Revision 1.12 1999/09/23 04:40:46 jprice + * *** empty log message *** + * + * Revision 1.10 1999/08/25 03:18:07 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.9 1999/05/03 06:25:45 jprice + * Patches from ror4 and many changed of signed to unsigned variables. + * + * Revision 1.8 1999/04/16 21:43:40 jprice + * ror4 multi-sector IO + * + * Revision 1.7 1999/04/16 12:21:21 jprice + * Steffen c-break handler changes + * + * Revision 1.6 1999/04/16 00:53:32 jprice + * Optimized FAT handling + * + * Revision 1.5 1999/04/12 03:21:17 jprice + * more ror4 patches. Changes for multi-block IO + * + * Revision 1.4 1999/04/11 04:33:38 jprice + * ror4 patches + * + * Revision 1.2 1999/04/04 22:57:47 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:40:46 jprice + * New version without IPL.SYS + * + * Revision 1.6 1999/03/23 23:38:15 jprice + * Now checks for a reads fdconfig.sys file, if exists + * + * Revision 1.5 1999/02/08 05:55:57 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.3 1999/01/30 08:28:11 jprice + * Clean up; Fixed bug with set attribute function. + * + * Revision 1.2 1999/01/22 04:13:25 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.6 22 Jan 1998 4:09:24 patv + * Fixed pointer problems affecting SDA + * + * Rev 1.5 04 Jan 1998 23:15:18 patv + * Changed Log for strip utility + * + * Rev 1.4 04 Jan 1998 17:26:14 patv + * Corrected subdirectory bug + * + * Rev 1.3 16 Jan 1997 12:46:50 patv + * pre-Release 0.92 feature additions + * + * Rev 1.1 29 May 1996 21:03:44 patv + * bug fixes for v0.91a + * + * Rev 1.0 19 Feb 1996 3:22:16 patv + * Added NLS, int2f and config.sys processing + */ + +#ifdef __TURBOC__ +void __int__(int); /* TC 2.01 requires this. :( -- ror4 */ +#endif + +#ifdef KDB +#include + +#define KernelAlloc(x) adjust_far((void far *)malloc((unsigned long)(x))) +#endif + +BYTE FAR *lpBase; +static BYTE FAR *lpOldLast; +static COUNT nCfgLine; +static COUNT nPass; +static BYTE szLine[256]; +static BYTE szBuf[256]; + +int singleStep = 0; + +INIT VOID Buffers(BYTE * pLine); +INIT VOID sysScreenMode(BYTE * pLine); +INIT VOID sysVersion(BYTE * pLine); +INIT VOID Break(BYTE * pLine); +INIT VOID Device(BYTE * pLine); +INIT VOID Files(BYTE * pLine); +INIT VOID Fcbs(BYTE * pLine); +INIT VOID Lastdrive(BYTE * pLine); +INIT VOID Country(BYTE * pLine); +INIT VOID InitPgm(BYTE * pLine); +INIT VOID Switchar(BYTE * pLine); +INIT VOID CfgFailure(BYTE * pLine); +INIT VOID Stacks(BYTE * pLine); +INIT BYTE *GetNumArg(BYTE * pLine, COUNT * pnArg); +INIT BYTE *GetStringArg(BYTE * pLine, BYTE * pszString); +INIT struct dhdr FAR *linkdev(struct dhdr FAR * dhp); +INIT UWORD initdev(struct dhdr FAR * dhp, BYTE FAR * cmdTail); +INIT int SkipLine(char *pLine); + +INIT static VOID FAR *AlignParagraph(VOID FAR * lpPtr); +#ifndef I86 +#define AlignParagraph(x) (x) +#endif + +#define EOF 0x1a + +INIT struct table *LookUp(struct table *p, BYTE * token); + +struct table +{ + BYTE *entry; + BYTE pass; + VOID(*func) (BYTE * pLine); +}; + +static struct table commands[] = +{ + {"break", 1, Break}, + {"buffers", 1, Buffers}, + {"command", 1, InitPgm}, + {"country", 1, Country}, + {"device", 2, Device}, + {"fcbs", 1, Fcbs}, + {"files", 1, Files}, + {"lastdrive", 1, Lastdrive}, + /* rem is never executed by locking out pass */ + {"rem", 0, CfgFailure}, + {"shell", 1, InitPgm}, + {"stacks", 1, Stacks}, + {"switchar", 1, Switchar}, + {"screen", 1, sysScreenMode}, /* JPP */ + {"version", 1, sysVersion}, /* JPP */ + /* default action */ + {"", -1, CfgFailure} +}; + +#ifndef KDB +INIT BYTE FAR *KernelAlloc(WORD nBytes); +INIT BYTE FAR *KernelAllocDma(WORD); +#endif + +BYTE *pLineStart; + +/* Do first time initialization. Store last so that we can reset it */ +/* later. */ +INIT void PreConfig(void) +{ + /* Set pass number */ + nPass = 0; + + /* Initialize the base memory pointers */ + lpOldLast = lpBase = AlignParagraph((BYTE FAR *) & last); + + /* Begin by initializing our system buffers */ + dma_scratch = (BYTE FAR *) KernelAllocDma(BUFFERSIZE); +#ifdef DEBUG + printf("Preliminary DMA scratchpad allocated at 0x%04x:0x%04x\n", + FP_SEG(dma_scratch), FP_OFF(dma_scratch)); +#endif + buffers = (struct buffer FAR *) + KernelAlloc(Config.cfgBuffers * sizeof(struct buffer)); +#ifdef DEBUG + printf("Preliminary %d buffers allocated at 0x%04x:0x%04x\n", Config.cfgBuffers, + FP_SEG(buffers), FP_OFF(buffers)); +#endif + + /* Initialize the file table */ + f_nodes = (struct f_node FAR *) + KernelAlloc(Config.cfgFiles * sizeof(struct f_node)); + /* sfthead = (sfttbl FAR *)&basesft; */ + /* FCBp = (sfttbl FAR *)&FcbSft; */ + FCBp = (sfttbl FAR *) + KernelAlloc(sizeof(sftheader) + + Config.cfgFiles * sizeof(sft)); + sfthead = (sfttbl FAR *) + KernelAlloc(sizeof(sftheader) + + Config.cfgFiles * sizeof(sft)); + + CDSp = (cdstbl FAR *) + KernelAlloc(0x58 * lastdrive + 1); + +#ifdef DEBUG + + printf("Preliminary f_node allocated at 0x%04x:0x%04x\n", + FP_SEG(f_nodes), FP_OFF(f_nodes)); + printf("Preliminary FCB table allocated at 0x%04x:0x%04x\n", + FP_SEG(FCBp), FP_OFF(FCBp)); + printf("Preliminary sft table allocated at 0x%04x:0x%04x\n", + FP_SEG(sfthead), FP_OFF(sfthead)); + printf("Preliminary CDS table allocated at 0x%04x:0x%04x\n", + FP_SEG(CDSp), FP_OFF(CDSp)); +#endif + + /* Done. Now initialize the MCB structure */ + /* This next line is 8086 and 80x86 real mode specific */ +#ifdef DEBUG + printf("Preliminary allocation completed: top at 0x%04x:0x%04x\n", + FP_SEG(lpBase), FP_OFF(lpBase)); +#endif + +#ifdef KDB + lpBase = malloc(4096); + first_mcb = FP_SEG(lpBase) + ((FP_OFF(lpBase) + 0x0f) >> 4); +#else + first_mcb = FP_SEG(lpBase) + ((FP_OFF(lpBase) + 0x0f) >> 4); +#endif + + /* We expect ram_top as Kbytes, so convert to paragraphs */ + mcb_init((mcb FAR *) (MK_FP(first_mcb, 0)), + (ram_top << 6) - first_mcb - 1); + nPass = 1; +} + +/* Do second pass initialization. */ +/* Also, run config.sys to load drivers. */ +INIT void PostConfig(void) +{ + /* Set pass number */ + nPass = 2; + + /* Initialize the base memory pointers from last time. */ + lpBase = AlignParagraph(lpOldLast); + + /* Begin by initializing our system buffers */ + dma_scratch = (BYTE FAR *) KernelAllocDma(BUFFERSIZE); +#ifdef DEBUG + printf("DMA scratchpad allocated at 0x%04x:0x%04x\n", FP_SEG(dma_scratch), + FP_OFF(dma_scratch)); +#endif + buffers = (struct buffer FAR *) + KernelAlloc(Config.cfgBuffers * sizeof(struct buffer)); +#ifdef DEBUG + printf("%d buffers allocated at 0x%04x:0x%04x\n", Config.cfgBuffers, + FP_SEG(buffers), FP_OFF(buffers)); +#endif + + /* Initialize the file table */ + f_nodes = (struct f_node FAR *) + KernelAlloc(Config.cfgFiles * sizeof(struct f_node)); + /* sfthead = (sfttbl FAR *)&basesft; */ + /* FCBp = (sfttbl FAR *)&FcbSft; */ + FCBp = (sfttbl FAR *) + KernelAlloc(sizeof(sftheader) + + Config.cfgFiles * sizeof(sft)); + sfthead = (sfttbl FAR *) + KernelAlloc(sizeof(sftheader) + + Config.cfgFiles * sizeof(sft)); + + CDSp = (cdstbl FAR *) + KernelAlloc(0x58 * lastdrive + 1); + +#ifdef DEBUG + + printf("f_node allocated at 0x%04x:0x%04x\n", + FP_SEG(f_nodes), FP_OFF(f_nodes)); + printf("FCB table allocated at 0x%04x:0x%04x\n", + FP_SEG(FCBp), FP_OFF(FCBp)); + printf("sft table allocated at 0x%04x:0x%04x\n", + FP_SEG(sfthead), FP_OFF(sfthead)); + printf("CDS table allocated at 0x%04x:0x%04x\n", + FP_SEG(CDSp), FP_OFF(CDSp)); +#endif + if (Config.cfgStacks) + { + VOID FAR *stackBase = KernelAlloc(Config.cfgStacks * Config.cfgStackSize); + init_stacks(stackBase, Config.cfgStacks, Config.cfgStackSize); + +#ifdef DEBUG + printf("Stacks allocated at %04x:%04x\n", + FP_SEG(stackBase), FP_OFF(stackBase)); +#endif + } +#ifdef DEBUG + printf("Allocation completed: top at 0x%04x:0x%04x\n", + FP_SEG(lpBase), FP_OFF(lpBase)); +#endif +} + +/* This code must be executed after device drivers has been loaded */ +INIT VOID configDone(VOID) +{ + COUNT i; + + first_mcb = FP_SEG(lpBase) + ((FP_OFF(lpBase) + 0x0f) >> 4); + + /* We expect ram_top as Kbytes, so convert to paragraphs */ + mcb_init((mcb FAR *) (MK_FP(first_mcb, 0)), + (ram_top << 6) - first_mcb - 1); + + /* The standard handles should be reopened here, because + we may have loaded new console or printer drivers in CONFIG.SYS */ +} + +INIT VOID DoConfig(VOID) +{ + COUNT nFileDesc; + COUNT nRetCode; + BYTE *pLine, + *pTmp; + BOOL bEof; + + /* Check to see if we have a config.sys file. If not, just */ + /* exit since we don't force the user to have one. */ + if ((nFileDesc = dos_open((BYTE FAR *) "fdconfig.sys", 0)) < 0) + { +#ifdef DEBUG + printf("FDCONFIG.SYS not found\n"); +#endif + if ((nFileDesc = dos_open((BYTE FAR *) "config.sys", 0)) < 0) + { +#ifdef DEBUG + printf("CONFIG.SYS not found\n"); +#endif + return; + } +#ifdef DEBUG + else + printf("Reading CONFIG.SYS...\n"); +#endif + } +#ifdef DEBUG + else + printf("Reading FDCONFIG.SYS...\n"); +#endif + + /* Have one -- initialize. */ + nCfgLine = 0; + bEof = 0; + pLine = szLine; + + /* Read each line into the buffer and then parse the line, */ + /* do the table lookup and execute the handler for that */ + /* function. */ + while (!bEof) + { + struct table *pEntry; + UWORD bytesLeft = 0; + + if (pLine > szLine) + bytesLeft = LINESIZE - (pLine - szLine); + + if (bytesLeft) + { + fbcopy(pLine, szLine, LINESIZE - bytesLeft); + pLine = szLine + bytesLeft; + } + + /* Read a line from config */ + /* Interrupt processing if read error or no bytes read */ + if ((nRetCode = dos_read(nFileDesc, pLine, LINESIZE - bytesLeft)) <= 0) + break; + + /* If the buffer was not filled completely, append a + CTRL-Z character to mark where the file ends */ + + if (nRetCode + bytesLeft < LINESIZE) + szLine[nRetCode + bytesLeft] = EOF; + + /* Process the buffer, line by line */ + pLine = szLine; + + while (!bEof && *pLine != EOF) + { + for (pTmp = pLine; pTmp - szLine < LINESIZE; pTmp++) + { + if (*pTmp == '\r' || *pTmp == EOF) + break; + } + + if (pTmp - szLine >= LINESIZE) + break; + + if (*pTmp == EOF) + bEof = TRUE; + + *pTmp = '\0'; + pLineStart = pLine; + + /* Skip leading white space and get verb. */ + pLine = scan(pLine, szBuf); + + /* Translate the verb to lower case ... */ + for (pTmp = szBuf; *pTmp != '\0'; pTmp++) + *pTmp = tolower(*pTmp); + + /* If the line was blank, skip it. Otherwise, look up */ + /* the verb and execute the appropriate function. */ + if (*szBuf != '\0') + { + pEntry = LookUp(commands, szBuf); + + if (pEntry->pass < 0 || pEntry->pass == nPass) + { + if (!singleStep || !SkipLine(pLineStart)) + { + skipwh(pLine); + + if ('=' != *pLine) + CfgFailure(pLine); + else + (*(pEntry->func)) (++pLine); + } + } + } + skipLine:nCfgLine++; + pLine += strlen(pLine) + 1; + } + } + dos_close(nFileDesc); +} + +INIT struct table *LookUp(struct table *p, BYTE * token) +{ + while (*(p->entry) != '\0') + { + if (strcmp(p->entry, token) == 0) + break; + else + ++p; + } + return p; +} + +INIT BOOL SkipLine(char *pLine) +{ + char kbdbuf[16]; + keyboard *kp = (keyboard *) kbdbuf; + char *pKbd = &kp->kb_buf[0]; + + kp->kb_size = 12; + kp->kb_count = 0; + + printf("%s [Y,N]?", pLine); + sti(kp); + + pKbd = skipwh(pKbd); + + if (*pKbd == 'n' || *pKbd == 'N') + return TRUE; + + return FALSE; +} + +INIT BYTE *GetNumArg(BYTE * pLine, COUNT * pnArg) +{ + /* look for NUMBER */ + pLine = skipwh(pLine); + if (!isnum(pLine)) + { + CfgFailure(pLine); + return (BYTE *) 0; + } + return GetNumber(pLine, pnArg); +} + +INIT BYTE *GetStringArg(BYTE * pLine, BYTE * pszString) +{ + /* look for STRING */ + pLine = skipwh(pLine); + + /* just return whatever string is there, including null */ + return scan(pLine, pszString); +} + +INIT static VOID Buffers(BYTE * pLine) +{ + COUNT nBuffers; + + /* Get the argument */ + if (GetNumArg(pLine, &nBuffers) == (BYTE *) 0) + return; + + /* Got the value, assign either default or new value */ + Config.cfgBuffers = max(Config.cfgBuffers, nBuffers); +} + +INIT static VOID sysScreenMode(BYTE * pLine) +{ + COUNT nMode; + + /* Get the argument */ + if (GetNumArg(pLine, &nMode) == (BYTE *) 0) + return; + + if ((nMode != 0x11) && (nMode != 0x12) && (nMode != 0x14)) + return; + +/* Modes + 0x11 (17) 28 lines + 0x12 (18) 43/50 lines + 0x14 (20) 25 lines + */ + _AX = (0x11 << 8) + nMode; + _BL = 0; + __int__(0x10); +} + +INIT static VOID sysVersion(BYTE * pLine) +{ + COUNT major, + minor; + char *p; + + p = pLine; + while (*p && *p != '.') + p++; + + if (*p++ == '\0') + return; + + /* Get major number */ + if (GetNumArg(pLine, &major) == (BYTE *) 0) + return; + + /* Get minor number */ + if (GetNumArg(p, &minor) == (BYTE *) 0) + return; + + printf("Changing reported version to %d.%d\n", major, minor); + + os_major = major; + os_minor = minor; +} + +INIT static VOID Files(BYTE * pLine) +{ + COUNT nFiles; + + /* Get the argument */ + if (GetNumArg(pLine, &nFiles) == (BYTE *) 0) + return; + + /* Got the value, assign either default or new value */ + Config.cfgFiles = max(Config.cfgFiles, nFiles); +} + +INIT static VOID Lastdrive(BYTE * pLine) +{ + /* Format: LASTDRIVE = letter */ + COUNT nFiles; + BYTE drv; + + pLine = skipwh(pLine); + drv = *pLine & ~0x20; + + if (drv < 'A' || drv > 'Z') + { + CfgFailure(pLine); + return; + } + drv -= 'A'; + Config.cfgLastdrive = max(Config.cfgLastdrive, drv); +} + +INIT static VOID Switchar(BYTE * pLine) +{ + /* Format: SWITCHAR = character */ + + GetStringArg(pLine, szBuf); + switchar = *szBuf; +} + +INIT static VOID Fcbs(BYTE * pLine) +{ + /* Format: FCBS = totalFcbs [,protectedFcbs] */ + COUNT fcbs; + + if ((pLine = GetNumArg(pLine, &fcbs)) == 0) + return; + Config.cfgFcbs = fcbs; + + pLine = skipwh(pLine); + + if (*pLine == ',') + { + GetNumArg(++pLine, &fcbs); + Config.cfgProtFcbs = fcbs; + } + + if (Config.cfgProtFcbs > Config.cfgFcbs) + Config.cfgProtFcbs = Config.cfgFcbs; +} + +INIT static VOID Country(BYTE * pLine) +{ + /* Format: COUNTRY = countryCode, [codePage], filename */ + COUNT ctryCode; + COUNT codePage; + + if ((pLine = GetNumArg(pLine, &ctryCode)) == 0) + return; + + pLine = skipwh(pLine); + if (*pLine == ',') + { + pLine = skipwh(pLine); + + if (*pLine == ',') + { + codePage = 0; + ++pLine; + } + else + { + if ((pLine = GetNumArg(pLine, &codePage)) == 0) + return; + } + + pLine = skipwh(pLine); + if (*pLine == ',') + { + GetStringArg(++pLine, szBuf); + + if (LoadCountryInfo(szBuf, ctryCode, codePage)) + return; + } + } + CfgFailure(pLine); +} + +INIT static VOID Stacks(BYTE * pLine) +{ + COUNT stacks; + + /* Format: STACKS = stacks [, stackSize] */ + pLine = GetNumArg(pLine, &stacks); + Config.cfgStacks = stacks; + + pLine = skipwh(pLine); + + if (*pLine == ',') + { + GetNumArg(++pLine, &stacks); + Config.cfgStackSize = stacks; + } + + if (Config.cfgStacks) + { + if (Config.cfgStackSize < 32) + Config.cfgStackSize = 32; + if (Config.cfgStackSize > 512) + Config.cfgStackSize = 512; + if (Config.cfgStacks > 64) + Config.cfgStacks = 64; + } +} + +INIT static VOID InitPgm(BYTE * pLine) +{ + /* Get the string argument that represents the new init pgm */ + pLine = GetStringArg(pLine, Config.cfgInit); + + /* Now take whatever tail is left and add it on as a single */ + /* string. */ + strcpy(Config.cfgInitTail, pLine); + + /* and add a DOS new line just to be safe */ + strcat(Config.cfgInitTail, "\r\n"); +} + +INIT static VOID Break(BYTE * pLine) +{ + /* Format: BREAK = (ON | OFF) */ + BYTE *pTmp; + + GetStringArg(pLine, szBuf); + break_ena = strcmp(szBuf, "OFF") ? 1 : 0; +} + +INIT static VOID Device(BYTE * pLine) +{ + VOID FAR *driver_ptr; + BYTE *pTmp; + exec_blk eb; + struct dhdr FAR *dhp; + struct dhdr FAR *next_dhp; + UWORD dev_seg = (((ULONG) FP_SEG(lpBase) << 4) + FP_OFF(lpBase) + 0xf) >> 4; + + /* Get the device driver name */ + GetStringArg(pLine, szBuf); + + /* The driver is loaded at the top of allocated memory. */ + /* The device driver is paragraph aligned. */ + eb.load.reloc = eb.load.load_seg = dev_seg; + dhp = MK_FP(dev_seg, 0); + +#ifdef DEBUG + printf("Loading device driver %s at segment %04x\n", + szBuf, dev_seg); +#endif + + if (DosExec(3, &eb, szBuf) == SUCCESS) + { + while (FP_OFF(dhp) != 0xFFFF) + { + next_dhp = MK_FP(FP_SEG(dhp), FP_OFF(dhp->dh_next)); + dhp->dh_next = nul_dev.dh_next; + link_dhdr(&nul_dev, dhp, pLine); + dhp = next_dhp; + } + } + else + CfgFailure(pLine); +} + +INIT static VOID CfgFailure(BYTE * pLine) +{ + BYTE *pTmp = pLineStart; + + printf("CONFIG.SYS error in line %d\n", nCfgLine); + printf(">>>%s\n", pTmp); + while (++pTmp != pLine) + printf(" "); + printf("^\n"); +} + +#ifndef KDB +INIT static BYTE FAR *KernelAlloc(WORD nBytes) +{ + BYTE FAR *lpAllocated; + + lpBase = AlignParagraph(lpBase); + lpAllocated = lpBase; + + if (0x10000 - FP_OFF(lpBase) <= nBytes) + { + UWORD newOffs = (FP_OFF(lpBase) + nBytes) & 0xFFFF; + UWORD newSeg = FP_SEG(lpBase) + 0x1000; + + lpBase = MK_FP(newSeg, newOffs); + } + else + lpBase += nBytes; + + return lpAllocated; +} +#endif + +#ifdef I86 +INIT static BYTE FAR *KernelAllocDma(WORD bytes) +{ + BYTE FAR *allocated; + + lpBase = AlignParagraph(lpBase); + if ((FP_SEG(lpBase) & 0x0fff) + (bytes >> 4) > 0x1000) + lpBase = MK_FP((FP_SEG(lpBase) + 0x0fff) & 0xf000, 0); + allocated = lpBase; + lpBase += bytes; + return allocated; +} + +INIT static VOID FAR *AlignParagraph(VOID FAR * lpPtr) +{ + ULONG lTemp; + UWORD uSegVal; + + /* First, convert the segmented pointer to linear address */ + lTemp = FP_SEG(lpPtr); + lTemp = (lTemp << 4) + FP_OFF(lpPtr); + + /* Next, round up the linear address to a paragraph boundary. */ + lTemp += 0x0f; + lTemp &= 0xfffffff0l; + + /* Break it into segments. */ + uSegVal = (UWORD) (lTemp >> 4); + + /* and return an adddress adjusted to the nearest paragraph */ + /* boundary. */ + return MK_FP(uSegVal, 0); +} +#endif + +INIT BYTE * + skipwh(BYTE * s) +{ + while (*s && (*s == 0x0d || *s == 0x0a || *s == ' ' || *s == '\t')) + ++s; + return s; +} + +INIT BYTE * + scan(BYTE * s, BYTE * d) +{ + s = skipwh(s); + while (*s && + !(*s == 0x0d + || *s == 0x0a + || *s == ' ' + || *s == '\t' + || *s == '=')) + *d++ = *s++; + *d = '\0'; + return s; +} + +INIT BYTE *scan_seperator(BYTE * s, BYTE * d) +{ + s = skipwh(s); + if (*s) + *d++ = *s++; + *d = '\0'; + return s; +} + +INIT BOOL isnum(BYTE * pLine) +{ + return (*pLine >= '0' && *pLine <= '9'); +} + +/* JPP - changed so will accept hex number. */ +INIT BYTE *GetNumber(REG BYTE * pszString, REG COUNT * pnNum) +{ + BYTE Base = 10; + + *pnNum = 0; + while (isnum(pszString) || toupper(*pszString) == 'X') + { + if (toupper(*pszString) == 'X') + { + Base = 16; + pszString++; + } + else + *pnNum = *pnNum * Base + (*pszString++ - '0'); + } + return pszString; +} + +/* Yet another change for true portability (WDL) */ +INIT COUNT tolower(COUNT c) +{ + if (c >= 'A' && c <= 'Z') + return (c + ('a' - 'A')); + else + return c; +} + +/* Yet another change for true portability (PJV) */ +INIT COUNT toupper(COUNT c) +{ + if (c >= 'a' && c <= 'z') + return (c - ('a' - 'A')); + else + return c; +} + +/* The following code is 8086 dependant */ + +#ifdef KERNEL +INIT VOID + mcb_init(mcb FAR * mcbp, UWORD size) +{ + COUNT i; + + mcbp->m_type = MCB_LAST; + mcbp->m_psp = FREE_PSP; + mcbp->m_size = size; + for (i = 0; i < 8; i++) + mcbp->m_name[i] = '\0'; + mem_access_mode = FIRST_FIT; +} +#endif + +INIT VOID + strcat(REG BYTE * d, REG BYTE * s) +{ + while (*d != 0) + ++d; + strcpy(d, s); +} + diff --git a/kernel/console.asm b/kernel/console.asm new file mode 100644 index 0000000..9dadbfb --- /dev/null +++ b/kernel/console.asm @@ -0,0 +1,279 @@ +; +; File: +; console.asm +; Description: +; Console device driver +; +; Copyright (c) 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Header$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:34:56 jhall1 +; Initial revision +; +; Revision 1.8 2000/03/09 06:07:10 kernel +; 2017f updates by James Tabor +; +; Revision 1.7 1999/09/23 04:40:46 jprice +; *** empty log message *** +; +; Revision 1.5 1999/09/14 16:31:38 jprice +; no message +; +; Revision 1.4 1999/09/13 22:16:14 jprice +; Fix 210B function +; +; Revision 1.3 1999/09/13 21:00:19 jprice +; Changes from Helmut Fritsch to fix INT21 func B +; +; Revision 1.2 1999/08/10 17:57:12 jprice +; ror4 2011-02 patch +; +; Revision 1.1.1.1 1999/03/29 15:40:47 jprice +; New version without IPL.SYS +; +; Revision 1.1 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; $EndLog$ +; + + %include "io.inc" + + +segment _IO_FIXED_DATA + + global ConTable +ConTable db 0Ah + dw _IOExit + dw _IOExit + dw _IOExit + dw _IOCommandError + dw ConRead + dw CommonNdRdExit + dw ConInStat + dw ConInpFlush + dw ConWrite + dw ConWrite + dw _IOExit + +PRT_SCREEN equ 7200h +CTL_P equ 10h + +segment _IO_TEXT + +uScanCode db 0 ; Scan code for con: device + +; +; Name: +; ConRead +; +; Function: +; Read to address in es:di characters from the keyboard. Cx contains +; a count of how many characters are to be transferred. +; +; Description: +; Calls KbdRdChar to read the characters. Destroys ax. +; + global ConRead +ConRead: + jcxz ConRead2 ; Exit if read of zero + +ConRead1: + call KbdRdChar ; Get a char from kbd in al + stosb ; Store al to es:[di] + loop ConRead1 ; Loop until all are read + +ConRead2: + jmp _IOExit + + +; +; Name: +; KbdRdChar +; +; Function: +; Read a character from the keyboard. +; +; Description: +; This subroutine reads a character fromthe keyboard. It also handles +; a couple of special functions. It converts the print screen key to +; a control-P. It also accounts for extended scan codes by saving off +; the high byte of the return and returning it if it was non-zero on +; the previous read. +; + global KbdRdChar +KbdRdChar: + xor ax,ax ; Zero the scratch register + xchg [cs:uScanCode],al ; and swap with scan code + or al,al ; Test to see if it was set + jnz KbdRdRtn ; Exit if it was, returning it + int 16h ; get keybd char in al, ah=scan + or ax,ax ; Zero ? + jz KbdRdChar ; Loop if it is + cmp ax,PRT_SCREEN ; Print screen? + jne KbdRd1 ; Nope, keep going + mov al,CTL_P ; Yep, make it ^P +KbdRd1: + or al,al ; Extended key? + jnz KbdRdRtn ; Nope, just exit + mov [cs:uScanCode],ah ; Yep, save the scan code +KbdRdRtn: + retn + + + + global CommonNdRdExit +CommonNdRdExit: + mov al,[cs:uScanCode] ; Test for last scan code + or al,al ; Was it zero ? + jnz ConNdRd2 ; Jump if there's a char waiting + mov ah,1 + int 16h ; Get status, if zf=0 al=char + jz ConNdRd4 ; Jump if chrar available + or ax,ax ; Zero ? + jnz ConNdRd1 ; Jump if not zero + int 16h ; get status, if zf=0 al=char + jmp short CommonNdRdExit + +ConNdRd1: + cmp ax,PRT_SCREEN ; Was print screen key pressed? + jne ConNdRd2 ; Jump if not + mov al,CTL_P + +ConNdRd2: + lds bx,[_ReqPktPtr] ; Set the status + mov [bx+0Dh],al + +ConNdRd3: + jmp _IOExit + +ConNdRd4: + jmp _IODone + + + + global ConInpFlush +ConInpFlush: + call KbdInpChar + jmp _IOExit + + + +KbdInpChar: + mov byte [cs:uScanCode],0 +KbdInpCh1: + mov ah,1 + int 16h ; get status, if zf=0 al=char + jz KbdInpRtn ; Jump if zero + xor ah,ah ; Zero register + int 16h ; get keybd char in al, ah=scan + jmp short KbdInpCh1 +KbdInpRtn: + retn + + + global ConWrite +ConWrite: + jcxz ConNdRd3 ; Exit if nothing to write +ConWr1: + mov al,[es:di] + inc di + int 29h ; Do fast output call + loop ConWr1 ; Loop if more to output + jmp _IOExit + +CBreak: + mov byte [cs:uScanCode],3 ; Put a ^C into the buffer +IntRetn: + iret + + + global _cso +_cso + push bp + mov bp,sp + push ax + mov ax,[bp+4] + int 29h + pop ax + pop bp + retn + + global _int29_handler +_int29_handler: + push ax + push si + push di + push bp + push bx + mov ah,0Eh + mov bh,0 + mov bl,7 + int 10h ; write char al, teletype mode + pop bx + pop bp + pop di + pop si + pop ax + iret + + +; +; Name: +; ConInStat +; +; Function: +; Checks the keybord input buffer. +; +; Description: +; Calls int 16 (get status). Sets Busy-Flag in status field. Destroys ax. +; + global ConInStat +ConInStat: + mov al,[cs:uScanCode] ; Test for last scan code + or al,al ; Was it zero ? + jnz ConCharReady ; Jump if there's a char waiting + mov ah,1 + int 16h ; get status, if zf=0 al=char + jz ConNoChar ; Jump if zero + + or ax,ax ; Zero ? + jnz ConIS1 ; Jump if not zero + int 16h ; get status, if zf=0 al=char + jmp short ConInStat + +ConIS1: + cmp ax,PRT_SCREEN ; Was print screen key pressed? + jne ConIS2 ; Jump if not + mov al,CTL_P + +ConIS2: + lds bx,[_ReqPktPtr] ; Set the status + mov [bx+0Dh],al +ConCharReady: + jmp _IODone ; key ready (busy=1) +ConNoChar: + jmp _IOExit ; no key ready (busy=0) + + diff --git a/kernel/dosfns.c b/kernel/dosfns.c new file mode 100644 index 0000000..536a0d6 --- /dev/null +++ b/kernel/dosfns.c @@ -0,0 +1,1148 @@ +/****************************************************************/ +/* */ +/* dosfns.c */ +/* */ +/* DOS functions */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" + +#ifdef VERSION_STRINGS +static BYTE *dosfnsRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:34:59 jhall1 + * Initial revision + * + * Revision 1.11 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.10 1999/09/23 04:40:46 jprice + * *** empty log message *** + * + * Revision 1.8 1999/09/14 01:01:53 jprice + * Fixed bug where you could write over directories. + * + * Revision 1.7 1999/08/25 03:18:07 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.6 1999/05/03 06:25:45 jprice + * Patches from ror4 and many changed of signed to unsigned variables. + * + * Revision 1.5 1999/04/16 12:21:22 jprice + * Steffen c-break handler changes + * + * Revision 1.4 1999/04/12 03:21:17 jprice + * more ror4 patches. Changes for multi-block IO + * + * Revision 1.3 1999/04/11 04:33:38 jprice + * ror4 patches + * + * Revision 1.2 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:41:52 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/09 02:54:23 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.3 1999/02/01 01:43:28 jprice + * Fixed findfirst function to find volume label with Windows long filenames + * + * Revision 1.2 1999/01/22 04:15:28 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * Rev 1.10 06 Dec 1998 8:44:42 patv + * Expanded dos functions due to new I/O subsystem. + * + * Rev 1.9 04 Jan 1998 23:14:38 patv + * Changed Log for strip utility + * + * Rev 1.8 03 Jan 1998 8:36:04 patv + * Converted data area to SDA format + * + * Rev 1.7 22 Jan 1997 12:59:56 patv + * pre-0.92 bug fixes + * + * Rev 1.6 16 Jan 1997 12:46:32 patv + * pre-Release 0.92 feature additions + * + * Rev 1.5 29 May 1996 21:15:20 patv + * bug fixes for v0.91a + * + * Rev 1.4 19 Feb 1996 3:20:08 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:48:48 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:50:24 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:04:20 patv + * Initial revision. + */ + +#include "globals.h" + +sft FAR *get_sft(COUNT); +WORD get_free_hndl(VOID); +sft FAR *get_free_sft(WORD FAR *); +BYTE FAR *get_root(BYTE FAR *); +BOOL cmatch(COUNT, COUNT, COUNT); +BOOL fnmatch(BYTE FAR *, BYTE FAR *, COUNT, COUNT); + +struct f_node FAR *xlt_fd(COUNT); + +static VOID DosGetFile(BYTE FAR * lpszPath, BYTE FAR * lpszDosFileName) +{ + BYTE szLclName[FNAME_SIZE + 1]; + BYTE szLclExt[FEXT_SIZE + 1]; + + ParseDosName(lpszPath, (COUNT *) 0, (BYTE *) 0, + szLclName, szLclExt, FALSE); + SpacePad(szLclName, FNAME_SIZE); + SpacePad(szLclExt, FEXT_SIZE); + fbcopy((BYTE FAR *) szLclName, lpszDosFileName, FNAME_SIZE); + fbcopy((BYTE FAR *) szLclExt, &lpszDosFileName[FNAME_SIZE], FEXT_SIZE); +} + +sft FAR *get_sft(COUNT hndl) +{ + psp FAR *p = MK_FP(cu_psp, 0); + WORD sys_idx; + sfttbl FAR *sp; + + if (hndl >= p->ps_maxfiles) + return (sft FAR *) - 1; + + /* Get the SFT block that contains the SFT */ + if (p->ps_filetab[hndl] == 0xff) + return (sft FAR *) - 1; + + sys_idx = p->ps_filetab[hndl]; + for (sp = sfthead; sp != (sfttbl FAR *) - 1; sp = sp->sftt_next) + { + if (sys_idx < sp->sftt_count) + break; + else + sys_idx -= sp->sftt_count; + } + + /* If not found, return an error */ + if (sp == (sfttbl FAR *) - 1) + return (sft FAR *) - 1; + + /* finally, point to the right entry */ + return (sft FAR *) & (sp->sftt_table[sys_idx]); +} + +/* + * The `force_binary' parameter is a hack to allow functions 0x01, 0x06, 0x07, + * and function 0x40 to use the same code for performing reads, even though the + * two classes of functions behave quite differently: 0x01 etc. always do + * binary reads, while for 0x40 the type of read (binary/text) depends on what + * the SFT says. -- ror4 + */ +UCOUNT GenericRead(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err, + BOOL force_binary) +{ + sft FAR *s; + WORD sys_idx; + sfttbl FAR *sp; + UCOUNT ReadCount; + + /* Test that the handle is valid */ + if (hndl < 0) + { + *err = DE_INVLDHNDL; + return 0; + } + + /* Get the SFT block that contains the SFT */ + if ((s = get_sft(hndl)) == (sft FAR *) - 1) + { + *err = DE_INVLDHNDL; + return 0; + } + + /* If not open or write permission - exit */ + if (s->sft_count == 0 || (s->sft_mode & SFT_MWRITE)) + { + *err = DE_INVLDACC; + return 0; + } + +/* + * Do remote first or return error. + * must have been opened from remote. + */ + if (s->sft_flags & SFT_FSHARED) + { + ReadCount = Remote_RW(REM_READ, n, bp, s, err); + if (err) + { + *err = SUCCESS; + return ReadCount; + } + else + return 0; + } + /* Do a device read if device */ + if (s->sft_flags & SFT_FDEVICE) + { + request rq; + + /* First test for eof and exit */ + /* immediately if it is */ + if (!(s->sft_flags & SFT_FEOF) || (s->sft_flags & SFT_FNUL)) + { + s->sft_flags &= ~SFT_FEOF; + *err = SUCCESS; + return 0; + } + + /* Now handle raw and cooked modes */ + if (force_binary || (s->sft_flags & SFT_FBINARY)) + { + rq.r_length = sizeof(request); + rq.r_command = C_INPUT; + rq.r_count = n; + rq.r_trans = (BYTE FAR *) bp; + rq.r_status = 0; + execrh((request FAR *) & rq, s->sft_dev); + if (rq.r_status & S_ERROR) + { + char_error(&rq, s->sft_dev); + } + else + { + *err = SUCCESS; + return rq.r_count; + } + } + else if (s->sft_flags & SFT_FCONIN) + { + kb_buf.kb_size = LINESIZE - 1; + kb_buf.kb_count = 0; + sti((keyboard FAR *) & kb_buf); + fbcopy((BYTE FAR *) kb_buf.kb_buf, bp, kb_buf.kb_count); + *err = SUCCESS; + return kb_buf.kb_count; + } + else + { + *bp = _sti(); + *err = SUCCESS; + return 1; + } + } + else + /* a block read */ + { + COUNT rc; + + ReadCount = readblock(s->sft_status, bp, n, &rc); + if (rc != SUCCESS) + { + *err = rc; + return 0; + } + else + { + *err = SUCCESS; + return ReadCount; + } + } + *err = SUCCESS; + return 0; +} + +UCOUNT DosRead(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err) +{ + return GenericRead(hndl, n, bp, err, FALSE); +} + +UCOUNT DosWrite(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err) +{ + sft FAR *s; + WORD sys_idx; + sfttbl FAR *sp; + UCOUNT ReadCount; + + /* Test that the handle is valid */ + if (hndl < 0) + { + *err = DE_INVLDHNDL; + return 0; + } + + /* Get the SFT block that contains the SFT */ + if ((s = get_sft(hndl)) == (sft FAR *) - 1) + { + *err = DE_INVLDHNDL; + return 0; + } + + /* If this is not opened and it's not a write */ + /* another error */ + if (s->sft_count == 0 || + (!(s->sft_mode & SFT_MWRITE) && !(s->sft_mode & SFT_MRDWR))) + { + *err = DE_ACCESS; + return 0; + } + if (s->sft_flags & SFT_FSHARED) + { + ReadCount = Remote_RW(REM_WRITE, n, bp, s, err); + if (err) + { + return ReadCount; + } + else + return 0; + } + + /* Do a device write if device */ + if (s->sft_flags & SFT_FDEVICE) + { + request rq; + + /* set to no EOF */ + s->sft_flags &= ~SFT_FEOF; + + /* if null just report full transfer */ + if (s->sft_flags & SFT_FNUL) + { + *err = SUCCESS; + return n; + } + + /* Now handle raw and cooked modes */ + if (s->sft_flags & SFT_FBINARY) + { + rq.r_length = sizeof(request); + rq.r_command = C_OUTPUT; + rq.r_count = n; + rq.r_trans = (BYTE FAR *) bp; + rq.r_status = 0; + execrh((request FAR *) & rq, s->sft_dev); + if (rq.r_status & S_ERROR) + { + char_error(&rq, s->sft_dev); + } + else + { + if (s->sft_flags & SFT_FCONOUT) + { + WORD cnt = rq.r_count; + while (cnt--) + { + switch (*bp++) + { + case CR: + scr_pos = 0; + break; + case LF: + case BELL: + break; + case BS: + --scr_pos; + break; + default: + ++scr_pos; + } + } + } + *err = SUCCESS; + return rq.r_count; + } + } + else + { + REG WORD c, + cnt = n, + spaces_left = 0, + next_pos, + xfer = 0; + static BYTE space = ' '; + + start: + if (cnt-- == 0) + goto end; + if (*bp == CTL_Z) + goto end; + if (s->sft_flags & SFT_FCONOUT) + { + switch (*bp) + { + case CR: + next_pos = 0; + break; + case LF: + case BELL: + next_pos = scr_pos; + break; + case BS: + next_pos = scr_pos ? scr_pos - 1 : 0; + break; + case HT: + spaces_left = 8 - (scr_pos & 7); + next_pos = scr_pos + spaces_left; + goto output_space; + default: + next_pos = scr_pos + 1; + } + } + rq.r_length = sizeof(request); + rq.r_command = C_OUTPUT; + rq.r_count = 1; + rq.r_trans = bp; + rq.r_status = 0; + execrh((request FAR *) & rq, s->sft_dev); + if (rq.r_status & S_ERROR) + char_error(&rq, s->sft_dev); + goto post; + output_space: + rq.r_length = sizeof(request); + rq.r_command = C_OUTPUT; + rq.r_count = 1; + rq.r_trans = &space; + rq.r_status = 0; + execrh((request FAR *) & rq, s->sft_dev); + if (rq.r_status & S_ERROR) + char_error(&rq, s->sft_dev); + --spaces_left; + post: + if (spaces_left) + goto output_space; + ++bp; + ++xfer; + if (s->sft_flags & SFT_FCONOUT) + scr_pos = next_pos; + if (break_ena && control_break()) + { + handle_break(); + goto end; + } + goto start; + end: + *err = SUCCESS; + return xfer; + } + } + else + /* a block write */ + { + COUNT rc; + + ReadCount = writeblock(s->sft_status, bp, n, &rc); + if (rc < SUCCESS) + { + *err = rc; + return 0; + } + else + { + *err = SUCCESS; + return ReadCount; + } + } + *err = SUCCESS; + return 0; +} + +COUNT DosSeek(COUNT hndl, LONG new_pos, COUNT mode, ULONG * set_pos) +{ + sft FAR *s; + ULONG lrx; + + /* Test for invalid mode */ + if (mode < 0 || mode > 2) + return DE_INVLDFUNC; + + /* Test that the handle is valid */ + if (hndl < 0) + return DE_INVLDHNDL; + + /* Get the SFT block that contains the SFT */ + if ((s = get_sft(hndl)) == (sft FAR *) - 1) + return DE_INVLDHNDL; + + lpCurSft = (sfttbl FAR *) s; + + if (s->sft_flags & SFT_FSHARED) + { + if (mode == 2) + { /* seek from end of file */ + int2f_Remote_call(REM_LSEEK, 0, (UWORD) FP_SEG(new_pos), (UWORD) FP_OFF(new_pos), (VOID FAR *) s, 0, 0); + *set_pos = s->sft_posit; + return SUCCESS; + } + if (mode == 0) + { + s->sft_posit = new_pos; + *set_pos = new_pos; + return SUCCESS; + } + if (mode == 1) + { + s->sft_posit += new_pos; + *set_pos = s->sft_posit; + return SUCCESS; + } + return DE_INVLDFUNC; + } + + /* Do special return for character devices */ + if (s->sft_flags & SFT_FDEVICE) + { + *set_pos = 0l; + return SUCCESS; + } + else + { + *set_pos = dos_lseek(s->sft_status, new_pos, mode); + if ((LONG) * set_pos < 0) + return (int)*set_pos; + else + return SUCCESS; + } +} + +static WORD get_free_hndl(void) +{ + psp FAR *p = MK_FP(cu_psp, 0); + WORD hndl; + + for (hndl = 0; hndl < p->ps_maxfiles; hndl++) + { + if (p->ps_filetab[hndl] == 0xff) + return hndl; + } + return 0xff; +} + +static sft FAR *get_free_sft(WORD FAR * sft_idx) +{ + WORD sys_idx = 0; + sfttbl FAR *sp; + + /* Get the SFT block that contains the SFT */ + for (sp = sfthead; sp != (sfttbl FAR *) - 1; sp = sp->sftt_next) + { + REG WORD i; + + for (i = 0; i < sp->sftt_count; i++) + { + if (sp->sftt_table[i].sft_count == 0) + { + *sft_idx = sys_idx + i; + return (sft FAR *) & sp->sftt_table[sys_idx + i]; + } + } + sys_idx += i; + } + /* If not found, return an error */ + return (sft FAR *) - 1; +} + +static BYTE FAR *get_root(BYTE FAR * fname) +{ + BYTE FAR *froot; + REG WORD length; + + /* find the end */ + for (length = 0, froot = fname; *froot != '\0'; ++froot) + ++length; + /* now back up to first path seperator or start */ + for (--froot; length > 0 && !(*froot == '/' || *froot == '\\'); --froot) + --length; + return ++froot; +} + +/* Ascii only file name match routines */ +static BOOL cmatch(COUNT s, COUNT d, COUNT mode) +{ + if (s >= 'a' && s <= 'z') + s -= 'a' - 'A'; + if (d >= 'a' && d <= 'z') + d -= 'a' - 'A'; + if (mode && s == '?' && (d >= 'A' && s <= 'Z')) + return TRUE; + return s == d; +} + +static BOOL fnmatch(BYTE FAR * s, BYTE FAR * d, COUNT n, COUNT mode) +{ + while (n--) + { + if (!cmatch(*s++, *d++, mode)) + return FALSE; + } + return TRUE; +} + +COUNT DosCreat(BYTE FAR * fname, COUNT attrib) +{ + psp FAR *p = MK_FP(cu_psp, 0); + WORD hndl, + sft_idx; + sft FAR *sftp; + struct dhdr FAR *dhp; + BYTE FAR *froot; + WORD i; + + /* get a free handle */ + if ((hndl = get_free_hndl()) == 0xff) + return DE_TOOMANY; + + /* now get a free system file table entry */ + if ((sftp = get_free_sft((WORD FAR *) & sft_idx)) == (sft FAR *) - 1) + return DE_TOOMANY; + + /* check for a device */ + froot = get_root(fname); + for (i = 0; i < FNAME_SIZE; i++) + { + if (*froot != '\0' && *froot != '.') + PriPathName[i] = *froot++; + else + break; + } + + for (; i < FNAME_SIZE; i++) + PriPathName[i] = ' '; + + /* if we have an extension, can't be a device */ + if (*froot != '.') + { + for (dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp->dh_next) + { + if (fnmatch((BYTE FAR *) PriPathName, (BYTE FAR *) dhp->dh_name, FNAME_SIZE, FALSE)) + { + sftp->sft_count += 1; + sftp->sft_mode = SFT_MRDWR; + sftp->sft_attrib = attrib; + sftp->sft_flags = + ((dhp->dh_attr & ~SFT_MASK) & ~SFT_FSHARED) | SFT_FDEVICE | SFT_FEOF; + sftp->sft_psp = cu_psp; + fbcopy((BYTE FAR *) PriPathName, sftp->sft_name, FNAME_SIZE + FEXT_SIZE); + sftp->sft_dev = dhp; + p->ps_filetab[hndl] = sft_idx; + return hndl; + } + } + } + + if (Remote_OCT(REM_CREATE, fname, attrib, sftp) == 0) + { + if (sftp->sft_flags & SFT_FSHARED) + { + sftp->sft_count += 1; + p->ps_filetab[hndl] = sft_idx; + return hndl; + } + } + + sftp->sft_status = dos_creat(fname, attrib); + if (sftp->sft_status >= 0) + { + p->ps_filetab[hndl] = sft_idx; + sftp->sft_count += 1; + sftp->sft_mode = SFT_MRDWR; + sftp->sft_attrib = attrib; + sftp->sft_flags = 0; + sftp->sft_psp = cu_psp; + DosGetFile(fname, sftp->sft_name); + return hndl; + } + else + return sftp->sft_status; +} + +COUNT CloneHandle(COUNT hndl) +{ + sft FAR *sftp; + + /* now get the system file table entry */ + if ((sftp = get_sft(hndl)) == (sft FAR *) - 1) + return DE_INVLDHNDL; + + /* now that we have the system file table entry, get the fnode */ + /* index, and increment the count, so that we've effectively */ + /* cloned the file. */ + sftp->sft_count += 1; + return SUCCESS; +} + +COUNT DosDup(COUNT Handle) +{ + psp FAR *p = MK_FP(cu_psp, 0); + COUNT NewHandle; + sft FAR *Sftp; + + /* Get the SFT block that contains the SFT */ + if ((Sftp = get_sft(Handle)) == (sft FAR *) - 1) + return DE_INVLDHNDL; + + /* If not open - exit */ + if (Sftp->sft_count <= 0) + return DE_INVLDHNDL; + + /* now get a free handle */ + if ((NewHandle = get_free_hndl()) == 0xff) + return DE_TOOMANY; + + /* If everything looks ok, bump it up. */ + if ((Sftp->sft_flags & SFT_FDEVICE) || (Sftp->sft_status >= 0)) + { + p->ps_filetab[NewHandle] = p->ps_filetab[Handle]; + Sftp->sft_count += 1; + return NewHandle; + } + else + return DE_INVLDHNDL; +} + +COUNT DosForceDup(COUNT OldHandle, COUNT NewHandle) +{ + psp FAR *p = MK_FP(cu_psp, 0); + sft FAR *Sftp; + + /* Get the SFT block that contains the SFT */ + if ((Sftp = get_sft(OldHandle)) == (sft FAR *) - 1) + return DE_INVLDHNDL; + + /* If not open - exit */ + if (Sftp->sft_count <= 0) + return DE_INVLDHNDL; + + /* now close the new handle if it's open */ + if ((UBYTE) p->ps_filetab[NewHandle] != 0xff) + { + COUNT ret; + + if ((ret = DosClose(NewHandle)) != SUCCESS) + return ret; + } + + /* If everything looks ok, bump it up. */ + if ((Sftp->sft_flags & SFT_FDEVICE) || (Sftp->sft_status >= 0)) + { + p->ps_filetab[NewHandle] = p->ps_filetab[OldHandle]; + + Sftp->sft_count += 1; + return NewHandle; + } + else + return DE_INVLDHNDL; +} + +COUNT DosOpen(BYTE FAR * fname, COUNT mode) +{ + psp FAR *p = MK_FP(cu_psp, 0); + WORD hndl; + WORD sft_idx; + sft FAR *sftp; + struct dhdr FAR *dhp; + BYTE FAR *froot; + WORD i; + + /* test if mode is in range */ + if ((mode & ~SFT_OMASK) != 0) + return DE_INVLDACC; + + mode &= 3; + /* get a free handle */ + if ((hndl = get_free_hndl()) == 0xff) + return DE_TOOMANY; + + OpenMode = (BYTE) mode; + + /* now get a free system file table entry */ + if ((sftp = get_free_sft((WORD FAR *) & sft_idx)) == (sft FAR *) - 1) + return DE_TOOMANY; + + /* check for a device */ + froot = get_root(fname); + for (i = 0; i < FNAME_SIZE; i++) + { + if (*froot != '\0' && *froot != '.') + PriPathName[i] = *froot++; + else + break; + } + + for (; i < FNAME_SIZE; i++) + PriPathName[i] = ' '; + + /* if we have an extension, can't be a device */ + if (*froot != '.') + { + for (dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp->dh_next) + { + if (fnmatch((BYTE FAR *) PriPathName, (BYTE FAR *) dhp->dh_name, FNAME_SIZE, FALSE)) + { + sftp->sft_count += 1; + sftp->sft_mode = mode; + sftp->sft_attrib = 0; + sftp->sft_flags = + ((dhp->dh_attr & ~SFT_MASK) & ~SFT_FSHARED) | SFT_FDEVICE | SFT_FEOF; + sftp->sft_psp = cu_psp; + fbcopy((BYTE FAR *) PriPathName, sftp->sft_name, FNAME_SIZE + FEXT_SIZE); + sftp->sft_dev = dhp; + sftp->sft_date = dos_getdate(); + sftp->sft_time = dos_gettime(); + + p->ps_filetab[hndl] = sft_idx; + return hndl; + } + } + } + + if (Remote_OCT(REM_OPEN, fname, mode, sftp) == 0) + { + if (sftp->sft_flags & SFT_FSHARED) + { + sftp->sft_count += 1; + p->ps_filetab[hndl] = sft_idx; + return hndl; + } + } + + sftp->sft_status = dos_open(fname, mode); + + if (sftp->sft_status >= 0) + { + struct f_node FAR *fnp = xlt_fd(sftp->sft_status); + + sftp->sft_attrib = fnp->f_dir.dir_attrib; + + /* Check permissions. -- JPP */ + if ((sftp->sft_attrib & (D_DIR | D_VOLID)) || + ((sftp->sft_attrib & D_RDONLY) && (mode != O_RDONLY))) + { + return DE_ACCESS; + } + p->ps_filetab[hndl] = sft_idx; + + sftp->sft_count += 1; + sftp->sft_mode = mode; + sftp->sft_attrib = 0; + sftp->sft_flags = 0; + sftp->sft_psp = cu_psp; + DosGetFile(fname, sftp->sft_name); + return hndl; + } + else + return sftp->sft_status; +} + +COUNT DosClose(COUNT hndl) +{ + psp FAR *p = MK_FP(cu_psp, 0); + sft FAR *s; + + /* Test that the handle is valid */ + if (hndl < 0) + return DE_INVLDHNDL; + + /* Get the SFT block that contains the SFT */ + if ((s = get_sft(hndl)) == (sft FAR *) - 1) + return DE_INVLDHNDL; + + /* If this is not opened another error */ + if (s->sft_count == 0) + return DE_ACCESS; + + lpCurSft = (sfttbl FAR *) s; +/* + remote sub sft_count. + */ + if (s->sft_flags & SFT_FSHARED) + { + int2f_Remote_call(REM_CLOSE, 0, 0, 0, (VOID FAR *) s, 0, 0); + p->ps_filetab[hndl] = 0xff; + s->sft_flags = 0; + return SUCCESS; + } + + /* now just drop the count if a device, else */ + /* call file system handler */ + if (s->sft_flags & SFT_FDEVICE) + { + p->ps_filetab[hndl] = 0xff; + s->sft_count -= 1; + return SUCCESS; + } + else + { + p->ps_filetab[hndl] = 0xff; + s->sft_count -= 1; + if (s->sft_count > 0) + return SUCCESS; + else + return dos_close(s->sft_status); + } +} + +VOID DosGetFree(COUNT drive, COUNT FAR * spc, COUNT FAR * navc, COUNT FAR * bps, COUNT FAR * nc) +{ + struct dpb *dpbp; + struct cds FAR *cdsp; + static char rg[8]; + + /* next - "log" in the drive */ + drive = (drive == 0 ? default_drive : drive - 1); + + cdsp = &CDSp->cds_table[drive]; + if (cdsp->cdsFlags & 0x8000) + { + int2f_Remote_call(REM_GETSPACE, 0, 0, 0, cdsp, 0, &rg); + + *spc = (COUNT) rg[0]; + *navc = (COUNT) rg[2]; + *bps = (COUNT) rg[4]; + *nc = (COUNT) rg[6]; + return; + } + + /* first check for valid drive */ + if (drive < 0 || drive > lastdrive) + { + *spc = -1; + return; + } + + dpbp = (struct dpb *)CDSp->cds_table[drive].cdsDpb; + if (dpbp == 0) + { + *spc = -1; + return; + } + + if ((media_check(dpbp) < 0)) + { + *spc = -1; + return; + } + + /* get the data vailable from dpb */ + *nc = dpbp->dpb_size; + *spc = dpbp->dpb_clsmask + 1; + *bps = dpbp->dpb_secsize; + + /* now tell fs to give us free cluster */ + /* count */ + *navc = dos_free(dpbp); +} + +COUNT DosGetCuDir(COUNT drive, BYTE FAR * s) +{ + REG struct cds FAR *cdsp; + + /* next - "log" in the drive */ + drive = (drive == 0 ? default_drive : drive - 1); + + cdsp = &CDSp->cds_table[drive]; + + current_ldt = cdsp; + + if (cdsp->cdsFlags & 0x8000) + { + dos_pwd(cdsp, s); + return SUCCESS; + } + + /* first check for valid drive */ + + if (cdsp->cdsDpb == 0) + return DE_INVLDDRV; + +/* if (drive < 0 || drive > nblkdev) + return DE_INVLDDRV; + */ + dos_pwd(cdsp, s); + return SUCCESS; +} + +COUNT DosChangeDir(BYTE FAR * s) +{ + REG struct dpb *dpbp; + REG struct cds FAR *cdsp; + REG COUNT drive; + struct f_node FAR *fp; + COUNT ret; + /* Parse and extract drive */ + if (*(s + 1) == ':') + { + drive = *s - '@'; + if (drive > 26) + drive -= 'a' - 'A'; + } + else + drive = 0; + + /* next - "log" in the drive */ + drive = (drive == 0 ? default_drive : drive - 1); + + cdsp = &CDSp->cds_table[drive]; + + current_ldt = cdsp; + + if (cdsp->cdsFlags & 0x8000) + { + ret = dos_cd(cdsp, s); + return ret; + } + + /* first check for valid drive */ + if (cdsp->cdsDpb == 0) + return DE_INVLDDRV; + + /* test for path existance from fs */ + if ((fp = dir_open((BYTE FAR *) s)) == (struct f_node FAR *)0) + return DE_PATHNOTFND; + else + dir_close(fp); + +/* if (drive < 0 || drive > nblkdev) + return DE_INVLDDRV; */ + + dpbp = (struct dpb *)cdsp->cdsDpb; + if ((media_check(dpbp) < 0)) + return DE_INVLDDRV; + /* now get fs to change to new */ + /* directory */ + ret = dos_cd(cdsp, s); + return ret; +} + +COUNT DosFindFirst(UCOUNT attr, BYTE FAR * name) +{ + SAttr = (BYTE) attr; + return dos_findfirst(attr, name); +} + +COUNT DosFindNext(void) +{ + return dos_findnext(); +} + +COUNT DosGetFtime(COUNT hndl, date FAR * dp, time FAR * tp) +{ + sft FAR *s; + sfttbl FAR *sp; + + /* Test that the handle is valid */ + if (hndl < 0) + return DE_INVLDHNDL; + + /* Get the SFT block that contains the SFT */ + if ((s = get_sft(hndl)) == (sft FAR *) - 1) + return DE_INVLDHNDL; + + /* If this is not opened another error */ + if (s->sft_count == 0) + return DE_ACCESS; + + /* If SFT entry refers to a device, return the date and time of opening */ + if (s->sft_flags & (SFT_FDEVICE | SFT_FSHARED)) + { + *dp = s->sft_date; + *tp = s->sft_time; + return SUCCESS; + } + + /* call file system handler */ + return dos_getftime(s->sft_status, dp, tp); +} + +COUNT DosSetFtime(COUNT hndl, date FAR * dp, time FAR * tp) +{ + sft FAR *s; + sfttbl FAR *sp; + + /* Test that the handle is valid */ + if (hndl < 0) + return DE_INVLDHNDL; + + /* Get the SFT block that contains the SFT */ + if ((s = get_sft(hndl)) == (sft FAR *) - 1) + return DE_INVLDHNDL; + + /* If this is not opened another error */ + if (s->sft_count == 0) + return DE_ACCESS; + + /* If SFT entry refers to a device, do nothing */ + if (s->sft_flags & SFT_FDEVICE) + return SUCCESS; + + if (s->sft_flags & SFT_FSHARED) + { + s->sft_date = *dp; + s->sft_time = *tp; + return SUCCESS; + } + + /* call file system handler */ + return dos_setftime(s->sft_status, dp, tp); +} + +COUNT DosGetFattr(BYTE FAR * name, UWORD FAR * attrp) +{ + + if (Remote_GSattr(REM_GETATTRZ, name, attrp) == 0) + return SUCCESS; + + return dos_getfattr(name, attrp); + +} + +COUNT DosSetFattr(BYTE FAR * name, UWORD FAR * attrp) +{ + if (Remote_GSattr(REM_SETATTR, name, attrp) == 0) + return SUCCESS; + + return dos_setfattr(name, attrp); +} + +BYTE DosSelectDrv(BYTE drv) +{ + if (CDSp->cds_table[drv].cdsFlags & 0xf000) + { + current_ldt = &CDSp->cds_table[drv]; + default_drive = drv; + } + return lastdrive; +} + diff --git a/kernel/dosidle.asm b/kernel/dosidle.asm new file mode 100644 index 0000000..7ef3329 --- /dev/null +++ b/kernel/dosidle.asm @@ -0,0 +1,100 @@ +; File: +; DosIdle.asm +; Description: +; Dos Idle Interrupt Call +; +; DOS-C +; Copyright (c) 1995, 1999 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; + %include "segs.inc" + +PSP_USERSP equ 2eh +PSP_USERSS equ 30h + +segment _TEXT + + global _DosIdle_int + + + extern _InDOS:wrt DGROUP + extern _cu_psp:wrt DGROUP + extern _MachineId:wrt DGROUP + extern critical_sp:wrt DGROUP + extern _lpUserStack:wrt DGROUP + extern _user_r:wrt DGROUP + extern _api_sp:wrt DGROUP ; api stacks - for context + extern _api_ss:wrt DGROUP ; switching + extern _usr_sp:wrt DGROUP ; user stacks + extern _usr_ss:wrt DGROUP + extern _dosidle_flag:wrt DGROUP +; +; +_DosIdle_int: + push ds + push ax + mov ax,DGROUP + mov ds,ax + pop ax + cmp byte [_dosidle_flag],0 + jnz DosId1 + call Do_DosI +DosId1: + pop ds + retn + +Do_DosI: + inc byte [_dosidle_flag] + push ax + push es + push word [_MachineId] + push word [_user_r] + push word [_user_r+2] + push word [_lpUserStack] + push word [_lpUserStack+2] + push word [_api_sp] + push word [_api_ss] + push word [_usr_sp] + push word [_usr_ss] + mov es,word [_cu_psp] + push word [es:PSP_USERSS] + push word [es:PSP_USERSP] + + int 28h + + mov es,word [_cu_psp] + pop word [es:PSP_USERSP] + pop word [es:PSP_USERSS] + pop word [_usr_ss] + pop word [_usr_sp] + pop word [_api_ss] + pop word [_api_sp] + pop word [_lpUserStack+2] + pop word [_lpUserStack] + pop word [_user_r+2] + pop word [_user_r] + pop word [_MachineId] + pop es + pop ax + dec byte [_dosidle_flag] + ret + diff --git a/kernel/dosnames.c b/kernel/dosnames.c new file mode 100644 index 0000000..ce06c87 --- /dev/null +++ b/kernel/dosnames.c @@ -0,0 +1,481 @@ +/****************************************************************/ +/* */ +/* dosnames.c */ +/* DOS-C */ +/* */ +/* Generic parsing functions for file name specifications */ +/* */ +/* Copyright (c) 1994 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/* */ +/****************************************************************/ + +#include "portab.h" + +#ifdef VERSION_STRINGS +static BYTE *dosnamesRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:00 jhall1 + * Initial revision + * + * Revision 1.3 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.2 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:41:54 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/02 04:40:49 jprice + * Steve Miller fixed a bug with doing "cd ." would lock the machine. + * + * Revision 1.3 1999/02/01 01:43:28 jprice + * Fixed findfirst function to find volume label with Windows long filenames + * + * Revision 1.2 1999/01/22 04:15:28 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * + * Rev 1.8 22 Jan 1998 4:09:00 patv + * Fixed pointer problems affecting SDA + * + * Rev 1.7 04 Jan 1998 23:14:38 patv + * Changed Log for strip utility + * + * Rev 1.6 03 Jan 1998 8:36:04 patv + * Converted data area to SDA format + * + * Rev 1.5 16 Jan 1997 12:46:36 patv + * pre-Release 0.92 feature additions + * + * Rev 1.4 29 May 1996 21:15:12 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:20:08 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:48:44 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:50:26 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:05:56 patv + * Initial revision. + * + */ + +#include "globals.h" + +#define PathSep(c) ((c)=='/'||(c)=='\\') +#define DriveChar(c) (((c)>='A'&&(c)<='Z')||((c)>='a'&&(c)<='z')) +#define DirChar(c) (!strchr("\"[]:|<>+=;,", (c))) +#define NameChar(c) (!strchr(".\"/\\[]:|<>+=;,*?", (c))) +#define WildChar(c) (!strchr(".\"/\\[]:|<>+=;,", (c))) + +VOID XlateLcase(BYTE * szFname, COUNT nChars); +VOID DosTrimPath(BYTE FAR * lpszPathNamep); + +/* Should be converted to a portable version after v1.0 is released. */ +VOID XlateLcase(BYTE * szFname, COUNT nChars) +{ + while (nChars--) + { + if (*szFname >= 'a' && *szFname <= 'z') + *szFname -= ('a' - 'A'); + ++szFname; + } +} + +VOID SpacePad(BYTE * szString, COUNT nChars) +{ + REG COUNT i; + + for (i = strlen(szString); i < nChars; i++) + szString[i] = ' '; +} + +COUNT ParseDosName(BYTE FAR * lpszFileName, + COUNT * pnDrive, + BYTE * pszDir, + BYTE * pszFile, + BYTE * pszExt, + BOOL bAllowWildcards) +{ + COUNT nDirCnt, + nFileCnt, + nExtCnt; + BYTE FAR *lpszLclDir, + FAR * lpszLclFile, + FAR * lpszLclExt; + + /* Initialize the users data fields */ + if (pszDir) + *pszDir = '\0'; + if (pszFile) + *pszFile = '\0'; + if (pszExt) + *pszExt = '\0'; + lpszLclFile = lpszLclExt = lpszLclDir = 0; + nDirCnt = nFileCnt = nExtCnt = 0; + + /* Start by cheking for a drive specifier ... */ + if (DriveChar(*lpszFileName) && ':' == lpszFileName[1]) + { + /* found a drive, fetch it and bump pointer past drive */ + /* NB: this code assumes ASCII */ + if (pnDrive) + { + *pnDrive = *lpszFileName - 'A'; + if (*pnDrive > 26) + *pnDrive -= ('a' - 'A'); + } + lpszFileName += 2; + } + else + { + if (pnDrive) + { + *pnDrive = -1; + } + } + if (!pszDir && !pszFile && !pszExt) + return SUCCESS; + + /* Now see how long a directory component we have. */ + lpszLclDir = lpszLclFile = lpszFileName; + while (DirChar(*lpszFileName)) + { + if (PathSep(*lpszFileName)) + lpszLclFile = lpszFileName + 1; + ++lpszFileName; + } + nDirCnt = lpszLclFile - lpszLclDir; + + /* Parse out the file name portion. */ + lpszFileName = lpszLclFile; + while (bAllowWildcards ? WildChar(*lpszFileName) : NameChar(*lpszFileName)) + { + ++nFileCnt; + ++lpszFileName; + } + if (nFileCnt == 0) + return DE_FILENOTFND; + + /* Now we have pointers set to the directory portion and the */ + /* file portion. Now determine the existance of an extension. */ + lpszLclExt = lpszFileName; + if ('.' == *lpszFileName) + { + lpszLclExt = ++lpszFileName; + while (*lpszFileName) + { + if (bAllowWildcards ? WildChar(*lpszFileName) : NameChar(*lpszFileName)) + { + ++nExtCnt; + ++lpszFileName; + } + else + return DE_FILENOTFND; + } + } + else if (*lpszFileName) + return DE_FILENOTFND; + + /* Fix lengths to maximums allowed by MS-DOS. */ + if (nDirCnt > PARSE_MAX) + nDirCnt = PARSE_MAX; + if (nFileCnt > FNAME_SIZE) + nFileCnt = FNAME_SIZE; + if (nExtCnt > FEXT_SIZE) + nExtCnt = FEXT_SIZE; + + /* Finally copy whatever the user wants extracted to the user's */ + /* buffers. */ + if (pszDir) + { + fbcopy(lpszLclDir, (BYTE FAR *) pszDir, nDirCnt); + pszDir[nDirCnt] = '\0'; + } + if (pszFile) + { + fbcopy(lpszLclFile, (BYTE FAR *) pszFile, nFileCnt); + pszFile[nFileCnt] = '\0'; + } + if (pszExt) + { + fbcopy(lpszLclExt, (BYTE FAR *) pszExt, nExtCnt); + pszExt[nExtCnt] = '\0'; + } + + /* Clean up before leaving */ + if (pszDir) + DosTrimPath(pszDir); + + return SUCCESS; +} + +COUNT ParseDosPath(BYTE FAR * lpszFileName, + COUNT * pnDrive, + BYTE * pszDir, + BYTE FAR * pszCurPath) +{ + COUNT nDirCnt, + nPathCnt; + BYTE FAR *lpszLclDir, + *pszBase = pszDir; + + /* Initialize the users data fields */ + *pszDir = '\0'; + lpszLclDir = 0; + nDirCnt = nPathCnt = 0; + + /* Start by cheking for a drive specifier ... */ + if (DriveChar(*lpszFileName) && ':' == lpszFileName[1]) + { + /* found a drive, fetch it and bump pointer past drive */ + /* NB: this code assumes ASCII */ + if (pnDrive) + { + *pnDrive = *lpszFileName - 'A'; + if (*pnDrive > 26) + *pnDrive -= ('a' - 'A'); + } + lpszFileName += 2; + } + else + { + if (pnDrive) + { + *pnDrive = -1; + } + } + + lpszLclDir = lpszFileName; + if (!PathSep(*lpszLclDir)) + { + fstrncpy(pszDir, pszCurPath, PARSE_MAX); + nPathCnt = fstrlen(pszCurPath); + if (!PathSep(pszDir[nPathCnt - 1]) && nPathCnt < PARSE_MAX) + pszDir[nPathCnt++] = '\\'; + if (nPathCnt > PARSE_MAX) + nPathCnt = PARSE_MAX; + pszDir += nPathCnt; + } + + /* Now see how long a directory component we have. */ + while (NameChar(*lpszFileName) + || PathSep(*lpszFileName) + || '.' == *lpszFileName) + { + ++nDirCnt; + ++lpszFileName; + } + + /* Fix lengths to maximums allowed by MS-DOS. */ + if ((nDirCnt + nPathCnt) > PARSE_MAX) + nDirCnt = PARSE_MAX - nPathCnt; + + /* Finally copy whatever the user wants extracted to the user's */ + /* buffers. */ + if (pszDir) + { + fbcopy(lpszLclDir, (BYTE FAR *) pszDir, nDirCnt); + pszDir[nDirCnt] = '\0'; + } + + /* Clean up before leaving */ + DosTrimPath((BYTE FAR *) pszBase); + + /* Before returning to the user, eliminate any useless */ + /* trailing "\\." since the path prior to this is sufficient. */ + nPathCnt = strlen(pszBase); + if (2 == nPathCnt) /* Special case, root */ + { + if (!strcmp(pszBase, "\\.")) + pszBase[1] = '\0'; + } + else if (2 < nPathCnt) + { + if (!strcmp(&pszBase[nPathCnt - 2], "\\.")) + pszBase[nPathCnt - 2] = '\0'; + } + + return SUCCESS; +} + +BOOL IsDevice(BYTE * pszFileName) +{ + REG struct dhdr FAR *dhp = (struct dhdr FAR *)&nul_dev; + BYTE szName[FNAME_SIZE]; + + /* break up the name first */ + if (ParseDosName((BYTE FAR *) pszFileName, + (COUNT *) 0, TempBuffer, szName, (BYTE *) 0, FALSE) + != SUCCESS) + return FALSE; + SpacePad(szName, FNAME_SIZE); + + /* Test 1 - does it start with a \dev or /dev */ + if ((strcmp(szName, "/dev") == 0) + || (strcmp(szName, "\\dev") == 0)) + return TRUE; + + /* Test 2 - is it on the device chain? */ + for (; -1l != (LONG) dhp; dhp = dhp->dh_next) + { + COUNT nIdx; + + /* Skip if not char device */ + if (!(dhp->dh_attr & ATTR_CHAR)) + continue; + + /* now compare */ + for (nIdx = 0; nIdx < FNAME_SIZE; ++nIdx) + { + if (dhp->dh_name[nIdx] != szName[nIdx]) + break; + } + if (nIdx >= FNAME_SIZE) + return TRUE; + } + + return FALSE; +} + +VOID DosTrimPath(BYTE FAR * lpszPathNamep) +{ + BYTE FAR *lpszLast, + FAR * lpszNext, + FAR * lpszRoot = (BYTE FAR *) 0; + COUNT nChars, + flDotDot; + + /* First, convert all '/' to '\'. Look for root as we scan */ + if (*lpszPathNamep == '\\') + lpszRoot = lpszPathNamep; + for (lpszNext = lpszPathNamep; *lpszNext; ++lpszNext) + { + if (*lpszNext == '/') + *lpszNext = '\\'; + if (!lpszRoot && + *lpszNext == ':' && *(lpszNext + 1) == '\\') + lpszRoot = lpszNext + 1; + } + + for (lpszLast = lpszNext = lpszPathNamep, nChars = 0; + *lpszNext != '\0' && nChars < NAMEMAX;) + { + /* Initialize flag for loop. */ + flDotDot = FALSE; + + /* If we are at a path seperator, check for extra path */ + /* seperator, '.' and '..' to reduce. */ + if (*lpszNext == '\\') + { + /* If it's '\', just move everything down one. */ + if (*(lpszNext + 1) == '\\') + fstrncpy(lpszNext, lpszNext + 1, NAMEMAX); + /* also check for '.' and '..' and move down */ + /* as appropriate. */ + else if (*(lpszNext + 1) == '.') + { + if (*(lpszNext + 2) == '.' + && !(*(lpszNext + 3))) + { + /* At the end, just truncate */ + /* and exit. */ + if (lpszLast == lpszRoot) + *(lpszLast + 1) = '\0'; + else + *lpszLast = '\0'; + return; + } + + if (*(lpszNext + 2) == '.' + && *(lpszNext + 3) == '\\') + { + fstrncpy(lpszLast, lpszNext + 3, NAMEMAX); + /* bump back to the last */ + /* seperator. */ + lpszNext = lpszLast; + /* set lpszLast to the last one */ + if (lpszLast <= lpszPathNamep) + continue; + do + { + --lpszLast; + } + while (lpszLast != lpszPathNamep + && *lpszLast != '\\'); + flDotDot = TRUE; + } + /* Note: we skip strange stuff that */ + /* starts with '.' */ + else if (*(lpszNext + 2) == '\\') + { + fstrncpy(lpszNext, lpszNext + 2, NAMEMAX); + } + /* If we're at the end of a string, */ + /* just exit. */ + else if (*(lpszNext + 2) == NULL) + { + return; + } + /* + Added this "else" because otherwise we might not pass + any of the foregoing tests, as in the case where the + incoming string refers to a suffix only, like ".bat" + + -SRM + */ + else + { + lpszLast = lpszNext++; + } + } + else + { + /* No '.' or '\' so mark it and bump */ + /* past */ + lpszLast = lpszNext++; + continue; + } + + /* Done. Now set last to next to mark this */ + /* instance of path seperator. */ + if (!flDotDot) + lpszLast = lpszNext; + } + else + /* For all other cases, bump lpszNext for the */ + /* next check */ + ++lpszNext; + } +} + diff --git a/kernel/dsk.c b/kernel/dsk.c new file mode 100644 index 0000000..9e88d10 --- /dev/null +++ b/kernel/dsk.c @@ -0,0 +1,671 @@ +/****************************************************************/ +/* */ +/* dsk.c */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *dskRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:01 jhall1 + * Initial revision + * + * Revision 1.5 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.4 1999/08/10 18:07:57 jprice + * ror4 2011-04 patch + * + * Revision 1.3 1999/04/16 21:43:40 jprice + * ror4 multi-sector IO + * + * Revision 1.2 1999/04/16 00:53:32 jprice + * Optimized FAT handling + * + * Revision 1.1.1.1 1999/03/29 15:40:51 jprice + * New version without IPL.SYS + * + * Revision 1.5 1999/02/14 04:26:46 jprice + * Changed check media so that it checks if a floppy disk has been changed. + * + * Revision 1.4 1999/02/08 05:55:57 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.3 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.2 1999/01/22 04:13:25 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.7 06 Dec 1998 8:45:18 patv + * Changed due to new I/O subsystem. + * + * Rev 1.6 04 Jan 1998 23:15:16 patv + * Changed Log for strip utility + * + * Rev 1.5 10 Jan 1997 5:41:48 patv + * Modified for extended partition support + * + * Rev 1.4 29 May 1996 21:03:32 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:21:36 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:54:18 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:52:00 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:32:42 patv + * Initial revision. + */ + +#ifdef PROTO +BOOL fl_reset(WORD); +COUNT fl_readdasd(WORD); +COUNT fl_diskchanged(WORD); +COUNT fl_rd_status(WORD); +COUNT fl_read(WORD, WORD, WORD, WORD, WORD, BYTE FAR *); +COUNT fl_write(WORD, WORD, WORD, WORD, WORD, BYTE FAR *); +COUNT fl_verify(WORD, WORD, WORD, WORD, WORD, BYTE FAR *); +BOOL fl_format(WORD, BYTE FAR *); +#else +BOOL fl_reset(); +COUNT fl_readdasd(); +COUNT fl_diskchanged(); +COUNT fl_rd_status(); +COUNT fl_read(); +COUNT fl_write(); +COUNT fl_verify(); +BOOL fl_format(); +#endif + +#define NDEV 8 /* only one for demo */ +#define SEC_SIZE 512 /* size of sector in bytes */ +#define N_RETRY 5 /* number of retries permitted */ +#define NENTRY 25 /* total size of dispatch table */ + +union +{ + BYTE bytes[2 * SEC_SIZE]; + boot boot_sector; +} +buffer; + +static struct media_info +{ + ULONG mi_size; /* physical sector count */ + UWORD mi_heads; /* number of heads (sides) */ + UWORD mi_cyls; /* number of cyl/drive */ + UWORD mi_sectors; /* number of sectors/cyl */ + ULONG mi_offset; /* relative partition offset */ + BYTE mi_drive; /* BIOS drive number */ + COUNT mi_partidx; /* Index to partition array */ +}; + +static struct media_info miarray[NDEV]; /* Internal media info structs */ +static bpb bpbarray[NDEV]; /* BIOS parameter blocks */ +static bpb *bpbptrs[NDEV]; /* pointers to bpbs */ + +#define N_PART 4 /* number of partitions per + table partition */ + +static WORD head, + track, + sector, + ret; /* globals for blockio */ +static WORD count; +static COUNT nUnits; /* number of returned units */ +static COUNT nPartitions; /* number of DOS partitions */ + +#define PARTOFF 0x1be + +static struct +{ + BYTE peDrive; /* BIOS drive number */ + BYTE peBootable; + BYTE peBeginHead; + BYTE peBeginSector; + UWORD peBeginCylinder; + BYTE peFileSystem; + BYTE peEndHead; + BYTE peEndSector; + UWORD peEndCylinder; + LONG peStartSector; + LONG peSectors; + LONG peAbsStart; /* Absolute sector start */ +} +dos_partition[NDEV - 2]; + +#ifdef PROTO +WORD init(rqptr), + mediachk(rqptr), + bldbpb(rqptr), + blockio(rqptr), + blk_error(rqptr); +COUNT ltop(WORD *, WORD *, WORD *, COUNT, COUNT, LONG, byteptr); +WORD dskerr(COUNT); +COUNT processtable(COUNT ptDrive, BYTE ptHead, UWORD ptCylinder, BYTE ptSector, LONG ptAccuOff); +#else +WORD init(), + mediachk(), + bldbpb(), + blockio(), + blk_error(); +WORD dskerr(); +COUNT processtable(); +#endif + +/* */ +/* the function dispatch table */ +/* */ + +#ifdef PROTO +static WORD(*dispatch[NENTRY]) (rqptr) = +#else +static WORD(*dispatch[NENTRY]) () = +#endif +{ + init, /* Initialize */ + mediachk, /* Media Check */ + bldbpb, /* Build BPB */ + blk_error, /* Ioctl In */ + blockio, /* Input (Read) */ + blk_error, /* Non-destructive Read */ + blk_error, /* Input Status */ + blk_error, /* Input Flush */ + blockio, /* Output (Write) */ + blockio, /* Output with verify */ + blk_error, /* Output Status */ + blk_error, /* Output Flush */ + blk_error, /* Ioctl Out */ + blk_error, /* Device Open */ + blk_error, /* Device Close */ + blk_error, /* Removable Media */ + blk_error, /* Output till busy */ + blk_error, /* undefined */ + blk_error, /* undefined */ + blk_error, /* Generic Ioctl */ + blk_error, /* undefined */ + blk_error, /* undefined */ + blk_error, /* undefined */ + blk_error, /* Get Logical Device */ + blk_error /* Set Logical Device */ +}; + +#define SIZEOF_PARTENT 16 + +#define FAT12 0x01 +#define FAT16SMALL 0x04 +#define EXTENDED 0x05 +#define FAT16LARGE 0x06 + +#define hd(x) ((x) & 0x80) + +COUNT processtable(COUNT ptDrive, BYTE ptHead, UWORD ptCylinder, + BYTE ptSector, LONG ptAccuOff) +{ + struct /* Temporary partition table */ + { + BYTE peBootable; + BYTE peBeginHead; + BYTE peBeginSector; + UWORD peBeginCylinder; + BYTE peFileSystem; + BYTE peEndHead; + BYTE peEndSector; + UWORD peEndCylinder; + LONG peStartSector; + LONG peSectors; + } + temp_part[N_PART]; + + REG retry = N_RETRY; + UBYTE packed_byte, + pb1; + COUNT Part; + + /* Read partition table */ + do + { + ret = fl_read((WORD) ptDrive, (WORD) ptHead, (WORD) ptCylinder, + (WORD) ptSector, (WORD) 1, (byteptr) & buffer); + } + while (ret != 0 && --retry > 0); + if (ret != 0) + return FALSE; + + /* Read each partition into temporary array */ + for (Part = 0; Part < N_PART; Part++) + { + REG BYTE *p = + (BYTE *) & buffer.bytes[PARTOFF + (Part * SIZEOF_PARTENT)]; + + getbyte((VOID *) p, &temp_part[Part].peBootable); + ++p; + getbyte((VOID *) p, &temp_part[Part].peBeginHead); + ++p; + getbyte((VOID *) p, &packed_byte); + temp_part[Part].peBeginSector = packed_byte & 0x3f; + ++p; + getbyte((VOID *) p, &pb1); + ++p; + temp_part[Part].peBeginCylinder = pb1 + ((UWORD) (0xc0 & packed_byte) << 2); + getbyte((VOID *) p, &temp_part[Part].peFileSystem); + ++p; + getbyte((VOID *) p, &temp_part[Part].peEndHead); + ++p; + getbyte((VOID *) p, &packed_byte); + temp_part[Part].peEndSector = packed_byte & 0x3f; + ++p; + getbyte((VOID *) p, &pb1); + ++p; + temp_part[Part].peEndCylinder = pb1 + ((UWORD) (0xc0 & packed_byte) << 2); + getlong((VOID *) p, &temp_part[Part].peStartSector); + p += sizeof(LONG); + getlong((VOID *) p, &temp_part[Part].peSectors); + }; + + /* Walk through the table, add DOS partitions to global + array and process extended partitions */ + for (Part = 0; Part < N_PART && nUnits < NDEV; Part++) + { + if (temp_part[Part].peFileSystem == FAT12 || + temp_part[Part].peFileSystem == FAT16SMALL || + temp_part[Part].peFileSystem == FAT16LARGE) + { + miarray[nUnits].mi_offset = + temp_part[Part].peStartSector + ptAccuOff; + miarray[nUnits].mi_drive = ptDrive; + miarray[nUnits].mi_partidx = nPartitions; + nUnits++; + + dos_partition[nPartitions].peDrive = ptDrive; + dos_partition[nPartitions].peBootable = + temp_part[Part].peBootable; + dos_partition[nPartitions].peBeginHead = + temp_part[Part].peBeginHead; + dos_partition[nPartitions].peBeginSector = + temp_part[Part].peBeginSector; + dos_partition[nPartitions].peBeginCylinder = + temp_part[Part].peBeginCylinder; + dos_partition[nPartitions].peFileSystem = + temp_part[Part].peFileSystem; + dos_partition[nPartitions].peEndHead = + temp_part[Part].peEndHead; + dos_partition[nPartitions].peEndSector = + temp_part[Part].peEndSector; + dos_partition[nPartitions].peEndCylinder = + temp_part[Part].peEndCylinder; + dos_partition[nPartitions].peStartSector = + temp_part[Part].peStartSector; + dos_partition[nPartitions].peSectors = + temp_part[Part].peSectors; + dos_partition[nPartitions].peAbsStart = + temp_part[Part].peStartSector + ptAccuOff; + nPartitions++; + } + else if (temp_part[Part].peFileSystem == EXTENDED) + { + /* call again to process extended part table */ + processtable(ptDrive, + temp_part[Part].peBeginHead, + temp_part[Part].peBeginCylinder, + temp_part[Part].peBeginSector, + temp_part[Part].peStartSector + ptAccuOff); + }; + }; + return TRUE; +} + +COUNT blk_driver(rqptr rp) +{ + if (rp->r_unit >= nUnits && rp->r_command != C_INIT) + return failure(E_UNIT); + if (rp->r_command > NENTRY) + { + return failure(E_FAILURE); /* general failure */ + } + else + return ((*dispatch[rp->r_command]) (rp)); +} + +static WORD init(rqptr rp) +{ + extern COUNT fl_nrdrives(VOID); + COUNT HardDrive, + nHardDisk, + Unit; + + /* Reset the drives */ + fl_reset(0x80); + + /* Initial number of disk units */ + nUnits = 2; + /* Initial number of DOS partitions */ + nPartitions = 0; + + /* Setup media info and BPBs arrays */ + for (Unit = 0; Unit < NDEV; Unit++) + { + miarray[Unit].mi_size = 720l; + miarray[Unit].mi_heads = 2; + miarray[Unit].mi_cyls = 40; + miarray[Unit].mi_sectors = 9; + miarray[Unit].mi_offset = 0l; + miarray[Unit].mi_drive = Unit; + + bpbarray[Unit].bpb_nbyte = SEC_SIZE; + bpbarray[Unit].bpb_nsector = 2; + bpbarray[Unit].bpb_nreserved = 1; + bpbarray[Unit].bpb_nfat = 2; + bpbarray[Unit].bpb_ndirent = 112; + bpbarray[Unit].bpb_nsize = 720l; + bpbarray[Unit].bpb_mdesc = 0xfd; + bpbarray[Unit].bpb_nfsect = 2; + + bpbptrs[Unit] = &bpbarray[Unit]; + }; + + nHardDisk = fl_nrdrives(); + for (HardDrive = 0; HardDrive < nHardDisk; HardDrive++) + { + /* Process primary partition table */ + if (!processtable((HardDrive | 0x80), 0, 0l, 1, 0l)) + /* Exit if no hard drive */ + break; + }; + + rp->r_nunits = nUnits; + rp->r_bpbptr = bpbptrs; + rp->r_endaddr = device_end(); + return S_DONE; +} + +static WORD mediachk(rqptr rp) +{ + COUNT drive = miarray[rp->r_unit].mi_drive; + COUNT result; + + /* if it's a hard drive, media never changes */ + if (hd(drive)) + rp->r_mcretcode = M_NOT_CHANGED; + else + /* else, check floppy status */ + { + if ((result = fl_readdasd(drive)) == 2) /* if we can detect a change ... */ + { + if ((result = fl_diskchanged(drive)) == 1) /* check if it has changed... */ + rp->r_mcretcode = M_CHANGED; + else if (result == 0) + rp->r_mcretcode = M_NOT_CHANGED; + else + rp->r_mcretcode = tdelay((LONG) 37) ? M_DONT_KNOW : M_NOT_CHANGED; + } + else if (result == 3) /* if it's a fixed disk, then no change */ + rp->r_mcretcode = M_NOT_CHANGED; + else /* can not detect or error... */ + rp->r_mcretcode = tdelay((LONG) 37) ? M_DONT_KNOW : M_NOT_CHANGED; + } + + return S_DONE; +} + +static WORD bldbpb(rqptr rp) +{ + REG retry = N_RETRY; + ULONG count; + byteptr trans; + WORD local_word; + + if (hd(miarray[rp->r_unit].mi_drive)) + { + COUNT partidx = miarray[rp->r_unit].mi_partidx; + head = dos_partition[partidx].peBeginHead; + sector = dos_partition[partidx].peBeginSector; + track = dos_partition[partidx].peBeginCylinder; + } + else + { + head = 0; + sector = 1; + track = 0; + } + + do + { + ret = fl_read((WORD) miarray[rp->r_unit].mi_drive, + (WORD) head, (WORD) track, (WORD) sector, (WORD) 1, (byteptr) & buffer); + } + while (ret != 0 && --retry > 0); + if (ret != 0) + return (dskerr(ret)); + + getword(&((((BYTE *) & buffer.bytes[BT_BPB]))[BPB_NBYTE]), &bpbarray[rp->r_unit].bpb_nbyte); + getbyte(&((((BYTE *) & buffer.bytes[BT_BPB]))[BPB_NSECTOR]), &bpbarray[rp->r_unit].bpb_nsector); + getword(&((((BYTE *) & buffer.bytes[BT_BPB]))[BPB_NRESERVED]), &bpbarray[rp->r_unit].bpb_nreserved); + getbyte(&((((BYTE *) & buffer.bytes[BT_BPB]))[BPB_NFAT]), &bpbarray[rp->r_unit].bpb_nfat); + getword(&((((BYTE *) & buffer.bytes[BT_BPB]))[BPB_NDIRENT]), &bpbarray[rp->r_unit].bpb_ndirent); + getword(&((((BYTE *) & buffer.bytes[BT_BPB]))[BPB_NSIZE]), &bpbarray[rp->r_unit].bpb_nsize); + getword(&((((BYTE *) & buffer.bytes[BT_BPB]))[BPB_NSIZE]), &bpbarray[rp->r_unit].bpb_nsize); + getbyte(&((((BYTE *) & buffer.bytes[BT_BPB]))[BPB_MDESC]), &bpbarray[rp->r_unit].bpb_mdesc); + getword(&((((BYTE *) & buffer.bytes[BT_BPB]))[BPB_NFSECT]), &bpbarray[rp->r_unit].bpb_nfsect); + getword(&((((BYTE *) & buffer.bytes[BT_BPB]))[BPB_NSECS]), &bpbarray[rp->r_unit].bpb_nsecs); + getword(&((((BYTE *) & buffer.bytes[BT_BPB]))[BPB_NHEADS]), &bpbarray[rp->r_unit].bpb_nheads); + getlong(&((((BYTE *) & buffer.bytes[BT_BPB])[BPB_HIDDEN])), &bpbarray[rp->r_unit].bpb_hidden); + getlong(&((((BYTE *) & buffer.bytes[BT_BPB])[BPB_HUGE])), &bpbarray[rp->r_unit].bpb_huge); +#ifdef DSK_DEBUG + printf("BPB_NBYTE = %04x\n", bpbarray[rp->r_unit].bpb_nbyte); + printf("BPB_NSECTOR = %02x\n", bpbarray[rp->r_unit].bpb_nsector); + printf("BPB_NRESERVED = %04x\n", bpbarray[rp->r_unit].bpb_nreserved); + printf("BPB_NFAT = %02x\n", bpbarray[rp->r_unit].bpb_nfat); + printf("BPB_NDIRENT = %04x\n", bpbarray[rp->r_unit].bpb_ndirent); + printf("BPB_NSIZE = %04x\n", bpbarray[rp->r_unit].bpb_nsize); + printf("BPB_MDESC = %02x\n", bpbarray[rp->r_unit].bpb_mdesc); + printf("BPB_NFSECT = %04x\n", bpbarray[rp->r_unit].bpb_nfsect); +#endif + rp->r_bpptr = &bpbarray[rp->r_unit]; + count = miarray[rp->r_unit].mi_size = + bpbarray[rp->r_unit].bpb_nsize == 0 ? + bpbarray[rp->r_unit].bpb_huge : + bpbarray[rp->r_unit].bpb_nsize; + getword((&(((BYTE *) & buffer.bytes[BT_BPB])[BPB_NHEADS])), &miarray[rp->r_unit].mi_heads); + head = miarray[rp->r_unit].mi_heads; + getword((&(((BYTE *) & buffer.bytes[BT_BPB])[BPB_NSECS])), &miarray[rp->r_unit].mi_sectors); + if (miarray[rp->r_unit].mi_size == 0) + getlong(&((((BYTE *) & buffer.bytes[BT_BPB])[BPB_HUGE])), &miarray[rp->r_unit].mi_size); + sector = miarray[rp->r_unit].mi_sectors; + if (head == 0 || sector == 0) + { + tmark(); + return failure(E_FAILURE); + } + miarray[rp->r_unit].mi_cyls = count / (head * sector); + tmark(); +#ifdef DSK_DEBUG + printf("BPB_NSECS = %04x\n", sector); + printf("BPB_NHEADS = %04x\n", head); + printf("BPB_HIDDEN = %08lx\n", bpbarray[rp->r_unit].bpb_hidden); + printf("BPB_HUGE = %08lx\n", bpbarray[rp->r_unit].bpb_huge); +#endif + return S_DONE; +} + +static COUNT write_and_verify(WORD drive, WORD head, WORD track, WORD sector, + WORD count, BYTE FAR * buffer) +{ + REG COUNT ret; + + ret = fl_write(drive, head, track, sector, count, buffer); + if (ret != 0) + return ret; + return fl_verify(drive, head, track, sector, count, buffer); +} + +static WORD blockio(rqptr rp) +{ + REG retry = N_RETRY, + remaining; + UWORD cmd, + total; + ULONG start; + byteptr trans; + COUNT(*action) (WORD, WORD, WORD, WORD, WORD, BYTE FAR *); + + cmd = rp->r_command; + total = 0; + trans = rp->r_trans; + tmark(); + for ( + remaining = rp->r_count, + start = (rp->r_start != HUGECOUNT ? rp->r_start : rp->r_huge) + + miarray[rp->r_unit].mi_offset; + remaining > 0; + remaining -= count, trans += count * SEC_SIZE, start += count + ) + { + count = ltop(&track, §or, &head, rp->r_unit, remaining, start, trans); + do + { + switch (cmd) + { + case C_INPUT: + action = fl_read; + break; + case C_OUTPUT: + action = fl_write; + break; + case C_OUTVFY: + action = write_and_verify; + break; + default: + return failure(E_FAILURE); + } + if (count) + ret = action((WORD) miarray[rp->r_unit].mi_drive, head, track, sector, + count, trans); + else + { + count = 1; + /* buffer crosses DMA boundary, use scratchpad */ + if (cmd != C_INPUT) + fbcopy(trans, dma_scratch, SEC_SIZE); + ret = action((WORD) miarray[rp->r_unit].mi_drive, head, track, sector, + 1, dma_scratch); + if (cmd == C_INPUT) + fbcopy(dma_scratch, trans, SEC_SIZE); + } + if (ret != 0) + fl_reset((WORD) miarray[rp->r_unit].mi_drive); + } + while (ret != 0 && --retry > 0); + if (ret != 0) + { + rp->r_count = total; + return dskerr(ret); + } + total += count; + } + rp->r_count = total; + return S_DONE; +} + +static WORD blk_error(rqptr rp) +{ + rp->r_count = 0; + return failure(E_FAILURE); /* general failure */ +} + +static WORD dskerr(COUNT code) +{ +/* printf("diskette error:\nhead = %d\ntrack = %d\nsector = %d\ncount = %d\n", + head, track, sector, count); */ + switch (code & 0x03) + { + case 1: /* invalid command - general failure */ + if (code & 0x08) + return (E_FAILURE); + else + return failure(E_CMD); + + case 2: /* address mark not found - general failure */ + return failure(E_FAILURE); + + case 3: /* write protect */ + return failure(E_WRPRT); + + default: + if (code & 0x80) /* time-out */ + return failure(E_NOTRDY); + else if (code & 0x40) /* seek error */ + return failure(E_SEEK); + else if (code & 0x10) /* CRC error */ + return failure(E_CRC); + else if (code & 0x04) + return failure(E_NOTFND); + else + return failure(E_FAILURE); + } +} + +/* */ +/* Do logical block number to physical head/track/sector mapping */ +/* */ +static COUNT ltop(WORD * trackp, WORD * sectorp, WORD * headp, REG COUNT unit, COUNT count, LONG strt_sect, byteptr strt_addr) +{ +#ifdef I86 + ULONG ltemp; +#endif + REG ls, + ps; + +#ifdef I86 + /* Adjust for segmented architecture */ + ltemp = (((ULONG) mk_segment(strt_addr) << 4) + mk_offset(strt_addr)) & 0xffff; + /* Test for 64K boundary crossing and return count large */ + /* enough not to exceed the threshold. */ + count = (((ltemp + SEC_SIZE * count) & 0xffff0000l) != 0l) + ? (0xffffl - ltemp) / SEC_SIZE + : count; +#endif + + *trackp = strt_sect / (miarray[unit].mi_heads * miarray[unit].mi_sectors); + *sectorp = strt_sect % miarray[unit].mi_sectors + 1; + *headp = (strt_sect % (miarray[unit].mi_sectors * miarray[unit].mi_heads)) + / miarray[unit].mi_sectors; + if (*sectorp + count > miarray[unit].mi_sectors + 1) + count = miarray[unit].mi_sectors + 1 - *sectorp; + return count; +} diff --git a/kernel/entry.asm b/kernel/entry.asm new file mode 100644 index 0000000..daf1b2d --- /dev/null +++ b/kernel/entry.asm @@ -0,0 +1,633 @@ +; +; File: +; entry.asm +; Description: +; System call entry code +; +; Copyright (c) 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Id$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:35:03 jhall1 +; Initial revision +; +; Revision 1.4 1999/09/23 04:40:46 jprice +; *** empty log message *** +; +; Revision 1.2 1999/08/10 17:57:12 jprice +; ror4 2011-02 patch +; +; Revision 1.1.1.1 1999/03/29 15:40:53 jprice +; New version without IPL.SYS +; +; Revision 1.4 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; Revision 1.3 1999/02/01 01:48:41 jprice +; Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) +; +; Revision 1.2 1999/01/22 04:13:25 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:01 jprice +; Imported sources +; +; Rev 1.1 06 Dec 1998 8:48:40 patv +; New int 21h handler code. +; +; Rev 1.0 07 Feb 1998 20:42:08 patv +; Modified stack frame to match DOS standard +; $EndLog$ + + %include "segs.inc" + %include "stacks.inc" + +segment _TEXT + extern _int21_syscall:wrt TGROUP + extern _int25_handler:wrt TGROUP + extern _int26_handler:wrt TGROUP + extern _set_stack:wrt TGROUP + extern _restore_stack:wrt TGROUP + extern _error_tos:wrt DGROUP + extern _char_api_tos:wrt DGROUP + extern _disk_api_tos:wrt DGROUP + extern _lpUserStack:wrt DGROUP + extern _user_r:wrt DGROUP + extern _ErrorMode:wrt DGROUP + extern _InDOS:wrt DGROUP + extern _cu_psp:wrt DGROUP + extern _MachineId:wrt DGROUP + extern critical_sp:wrt DGROUP + + extern _api_sp:wrt DGROUP ; api stacks - for context + extern _api_ss:wrt DGROUP ; switching + extern _usr_sp:wrt DGROUP ; user stacks + extern _usr_ss:wrt DGROUP + extern int21regs_seg:wrt DGROUP + extern int21regs_off:wrt DGROUP + + extern _dosidle_flag:wrt DGROUP + extern _Int21AX:wrt DGROUP + + + global _cpm_entry + global _int20_handler + global _int21_handler + global _low_int25_handler + global _low_int26_handler + global _int27_handler + + +; +; MS-DOS CP/M style entry point +; +; VOID FAR +; cpm_entry(iregs UserRegs) +; +; This one is a strange one. The call is to psp:0005h but it returns to the +; function after the call. What we do is convert it to a normal call and +; fudge the stack to look like an int 21h call. +; +_cpm_entry: + ; Stack is: + ; return offset + ; psp seg + ; 000ah + ; + push bp ; trash old return address + mov bp,sp + xchg bp,[2+bp] + pop bp + pushf ; start setting up int 21h stack + ; + ; now stack is + ; return offset + ; psp seg + ; flags + ; + push bp + mov bp,sp ; set up reference frame + ; + ; reference frame stack is + ; return offset bp + 6 + ; psp seg bp + 4 + ; flags bp + 2 + ; bp <--- bp + ; + push ax + mov ax,[2+bp] ; get the flags + xchg ax,[6+bp] ; swap with return address + mov [2+bp],ax + pop ax ; restore working registers + pop bp + ; + ; Done. Stack is + ; flags + ; psp seg (alias .COM cs) + ; return offset + ; + cmp cl,024h + jbe cpm_error + mov ah,cl ; get the call # from cl to ah + jmp short _int21_handler ; do the system call +cpm_error: mov al,0 + iret + +; +; Restart the int 21h system call. Call never returns. +; +; VOID +; RestartSysCall(VOID); +; +; NOTE: On exit, DS must point to kernel stack, SS:SP user stack after +; PUSH$ALL and BP == SP. +; +_RestartSysCall: + cli ; no interrupts + mov bp,word [_lpUserStack+2] ;Get frame + mov ss,bp + mov bp,word [_lpUserStack] + mov sp,bp + sti + POP$ALL ; get the original regs + jmp short int21_reentry ; restart the system call + + +; +; Terminate the current process +; +; VOID INRPT far +; int20_handler(iregs UserRegs) +; +_int20_handler: + mov ah,0 ; terminate through int 21h + + +; +; MS-DOS system call entry point +; +; VOID INRPT far +; int21_handler(iregs UserRegs) +; +_int21_handler: + ; + ; Create the stack frame for C call. This is done to + ; preserve machine state and provide a C structure for + ; access to registers. + ; + ; Since this is an interrupt routine, CS, IP and flags were + ; pushed onto the stack by the processor, completing the + ; stack frame. + ; + ; NB: stack frame is MS-DOS dependent and not compatible + ; with compiler interrupt stack frames. + ; + PUSH$ALL + + ; + ; Create kernel refernce frame. + ; + ; NB: At this point, SS != DS and won't be set that way + ; until later when which stack to run on is determined. + ; + mov bp,DGROUP + mov ds,bp + + ; + ; Now DS is set, let's save our stack for rentry + ; + mov bp,ss + mov word [_lpUserStack+2],bp + mov word [_user_r+2],bp + mov bp,sp + mov word [_lpUserStack],bp ; store and init + mov word [_user_r],bp ; store and init + + ; + ; Decide which stack to run on. + ; + ; Unlike previous versions of DOS-C, we need to do this here + ; to guarantee the user stack for critical error handling. + ; We need to do the int 24h from this stack location. + ; + ; There are actually four stacks to run on. The first is the + ; user stack which is determined by system call number in + ; AH. The next is the error stack determined by _ErrorMode. + ; Then there's the character stack also determined by system + ; call number. Finally, all others run on the disk stack. + ; They are evaluated in that order. + +int21_reentry: + cmp ah,33h + je int21_user + cmp ah,50h + je int21_user + cmp ah,51h + je int21_user + cmp ah,62h + jne int21_1 + +int21_user: push word [_user_r+2] + push word [_user_r] + call _int21_syscall + pop cx + pop cx + jmp int21_ret + +int21_1: sti + cmp byte [_ErrorMode],0 + je int21_2 + mov bp,ds + mov ss,bp + mov bp,_error_tos + mov sp,bp + cli + push word [_user_r+2] + push word [_user_r] + call _int21_syscall + jmp short int21_exit + +int21_2: inc byte [_InDOS] + cmp ah,0ch + jg int21_3 +; +; Make FreeDOS better than the others! +; + cmp byte [_dosidle_flag],0 + jne int21_user + + mov bp,ds + mov ss,bp + mov bp,_char_api_tos + mov sp,bp + cli + push word [_user_r+2] + push word [_user_r] + call _int21_syscall + jmp short int21_exit + +int21_3: + call dos_crit_sect + + mov bp,ds + mov ss,bp + mov bp,_disk_api_tos + mov sp,bp + cli + ; + ; Push the far pointer to the register frame for + ; int21_syscall and remainder of kernel. + ; + push word [_user_r+2] + push word [_user_r] + call _int21_syscall + + ; + ; Recover registers from system call. Registers and flags + ; were modified by the system call. + ; +int21_exit: sti + mov bp,word [_user_r+2] + mov ss,bp + mov bp,word [_user_r] ; store and init + mov sp,bp + dec byte [_InDOS] + cli +int21_ret: POP$ALL + + ; + ; ... and return. + ; + iret +; +; end Dos Critical Section 0 thur 7 +; +; +dos_crit_sect: + mov [_Int21AX],ax ; needed! + push ax ; This must be here!!! + mov ah,82h ; re-enrty sake before disk stack + int 2ah ; Calling Server Hook! + pop ax + ret + +; +; Terminate the current process +; +; VOID INRPT far +; int27_handler(iregs UserRegs) +; +_int27_handler: + ; + ; First convert the memory to paragraphs + ; + add dx,byte 0fh ; round up + rcr dx,1 + shr dx,1 + shr dx,1 + shr dx,1 + ; + ; ... then use the standard system call + ; + mov ax,3100h + jmp _int21_handler ; terminate through int 21h + +; +; I really do need to get rid of this because it's the only thing stopping +; us from being ROMABLE. +; +stkframe dd 0 + +_low_int25_handler: + sti + pushf + push ax + push cx + push dx + push bx + push sp + push bp + push si + push di + push ds + push es + + mov word [cs:stkframe], sp ; save stack frame + mov word [cs:stkframe+2], ss + + cld + mov ax, DGROUP + mov ds, ax + + mov word [_api_sp], _disk_api_tos + mov word [_api_ss], ds + + call far _set_stack + + push word [cs:stkframe+2] + push word [cs:stkframe] + call _int25_handler + add sp, byte 4 + + call far _restore_stack + + pop es + pop ds + pop di + pop si + pop bp + pop bx ; pop off sp value + pop bx + pop dx + pop cx + pop ax + popf + retf ; Bug-compatiblity with MS-DOS. + ; This function is supposed to leave the original + ; flag image on the stack. + + +_low_int26_handler: + sti + pushf + push ax + push cx + push dx + push bx + push sp + push bp + push si + push di + push ds + push es + + mov word [cs:stkframe], sp ; save stack frame + mov word [cs:stkframe+2], ss + + cld + mov ax, DGROUP + mov ds, ax + + mov word [_api_sp], _disk_api_tos + mov word [_api_ss], ds + + call far _set_stack + + push word [cs:stkframe+2] + push word [cs:stkframe] + call _int26_handler + add sp, 4 + + call far _restore_stack + + pop es + pop ds + pop di + pop si + pop bp + pop bx ; pop off sp value + pop bx + pop dx + pop cx + pop ax + popf + retf + + +CONTINUE equ 00h +RETRY equ 01h +ABORT equ 02h +FAIL equ 03h + +OK_IGNORE equ 20h +OK_RETRY equ 10h +OK_FAIL equ 08h + +PSP_PARENT equ 16h +PSP_USERSP equ 2eh +PSP_USERSS equ 30h + + +; +; Default Int 24h handler -- always returns fail +; + global _int24_handler +_int24_handler: mov al,FAIL + iret + +; +; COUNT +; CriticalError(COUNT nFlag, COUNT nDrive, COUNT nError, struct dhdr FAR *lpDevice); +; + global _CriticalError +_CriticalError: + ; + ; Skip critical error routine if handler is active + ; + cmp byte [_ErrorMode],0 + je CritErr05 ; Jump if equal + + mov ax,FAIL + retn + ; + ; Do local error processing + ; +CritErr05: + ; + ; C Entry + ; + push bp + mov bp,sp + push si + push di + ; + ; Get parameters + ; + mov ah,byte [bp+4] ; nFlags + mov al,byte [bp+6] ; nDrive + mov di,word [bp+8] ; nError + ; + ; make bp:si point to dev header + ; + mov si,word [bp+10] ; lpDevice Offset + mov bp,word [bp+12] ; lpDevice segment + ; + ; Now save real ss:sp and retry info in internal stack + ; + cli + mov es,[_cu_psp] + push word [es:PSP_USERSS] + push word [es:PSP_USERSP] + push word [_MachineId] + push word [int21regs_seg] + push word [int21regs_off] + push word [_api_sp] + push word [_api_ss] + push word [_usr_sp] + push word [_usr_ss] + push word [_user_r+2] + push word [_user_r] + mov [critical_sp],sp + ; + ; do some clean up because user may never return + ; + inc byte [_ErrorMode] + dec byte [_InDOS] + ; + ; switch to user's stack + ; + mov ss,[es:PSP_USERSS] + mov sp,[es:PSP_USERSP] + ; + ; and call critical error handler + ; + int 24h ; DOS Critical error handler + + ; + ; recover context + ; + cld + cli + mov bp, DGROUP + mov ds,bp + mov ss,bp + mov sp,[critical_sp] + pop word [_user_r] + pop word [_user_r+2] + pop word [_usr_ss] + pop word [_usr_sp] + pop word [_api_ss] + pop word [_api_sp] + pop word [int21regs_off] + pop word [int21regs_seg] + pop word [_MachineId] + mov es,[_cu_psp] + pop word [es:PSP_USERSP] + pop word [es:PSP_USERSS] + sti ; Enable interrupts + ; + ; clear flags + ; + mov byte [_ErrorMode],0 + inc byte [_InDOS] + ; + ; Check for ignore and force fail if not ok + cmp al,CONTINUE + jne CritErr10 ; not ignore, keep testing + test bh,OK_IGNORE + jnz CritErr10 + mov al,FAIL + ; + ; Check for retry and force fail if not ok + ; +CritErr10: + cmp al,RETRY + jne CritErr20 ; not retry, keep testing + test bh,OK_RETRY + jnz CritErr20 + mov al,FAIL + ; + ; You know the drill, but now it's different. + ; check for fail and force abort if not ok + ; +CritErr20: + cmp al,FAIL + jne CritErr30 ; not fail, do exit processing + test bh,OK_FAIL + jnz CritErr30 + mov al,ABORT + ; + ; OK, if it's abort we do extra processing. Otherwise just + ; exit. + ; +CritErr30: + cmp al,ABORT + je CritErrAbort ; process abort + +CritErrExit: + xor ah,ah ; clear out top for return + pop di + pop si + pop bp + ret + + ; + ; Abort processing. + ; +CritErrAbort: + mov ax,[_cu_psp] + mov es,ax + cmp ax,[es:PSP_PARENT] + mov al,FAIL + jz CritErrExit + cli + mov bp,word [_user_r+2] ;Get frame + mov ss,bp + mov es,bp + mov bp,word [_user_r] + mov sp,bp + mov byte [_ErrorMode],1 ; flag abort + mov ax,4C00h + mov [es:reg_ax],ax + sti + jmp int21_reentry ; restart the system call diff --git a/kernel/error.c b/kernel/error.c new file mode 100644 index 0000000..50c95b9 --- /dev/null +++ b/kernel/error.c @@ -0,0 +1,145 @@ +/****************************************************************/ +/* */ +/* error.c */ +/* */ +/* Main Kernel Error Handler Functions */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" + +#ifdef VERSION_STRINGS +static BYTE *errorRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:03 jhall1 + * Initial revision + * + * Revision 1.2 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.1.1.1 1999/03/29 15:41:55 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/09 02:54:23 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.3 1999/02/01 01:43:28 jprice + * Fixed findfirst function to find volume label with Windows long filenames + * + * Revision 1.2 1999/01/22 04:15:28 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * + * Rev 1.5 06 Dec 1998 8:43:54 patv + * Now handles errors like MS-DOS. + * + * Rev 1.4 04 Jan 1998 23:14:36 patv + * Changed Log for strip utility + * + * Rev 1.3 29 May 1996 21:15:10 patv + * bug fixes for v0.91a + * + * Rev 1.2 01 Sep 1995 17:48:46 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:50:26 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:06:14 patv + * Initial revision. + */ + +#include "globals.h" + +/* error registers */ +VOID dump(void) +{ + printf("Register Dump [AH = %02x CS:IP = %04x:%04x]\n", + error_regs.AH, + error_regs.CS, + error_regs.IP); + printf("AX:%04x BX:%04x CX:%04x DX:%04x\n", + error_regs.AX, + error_regs.BX, + error_regs.CX, + error_regs.DX); + printf("SI:%04x DI:%04x DS:%04x ES:%04x\n", + error_regs.SI, + error_regs.DI, + error_regs.DS, + error_regs.ES); +} + +/* issue a panic message for corrupted data structures */ +VOID panic(BYTE * s) +{ + printf("\nPANIC: %s\nSystem halted\n", s); + for (;;) ; +} + +#ifdef IPL +/* issue an internal error message */ +VOID fatal(BYTE * err_msg) +{ + printf("\nInternal IPL error - %s\nSystem halted\n", err_msg); + exit(-1); +} +#else +/* issue an internal error message */ +VOID fatal(BYTE * err_msg) +{ + printf("\nInternal kernel error - %s\nSystem halted\n", err_msg); + for (;;) ; +} + +VOID FAR init_call_fatal(BYTE * err_msg) +{ + fatal(err_msg); +} +#endif + +/* Abort, retry or fail for character devices */ +COUNT char_error(request * rq, struct dhdr FAR * lpDevice) +{ + return CriticalError( + EFLG_CHAR | EFLG_ABORT | EFLG_RETRY | EFLG_IGNORE, + 0, + rq->r_status & S_MASK, + lpDevice); +} + +/* Abort, retry or fail for block devices */ +COUNT block_error(request * rq, COUNT nDrive, struct dhdr FAR * lpDevice) +{ + return CriticalError( + EFLG_ABORT | EFLG_RETRY | EFLG_IGNORE, + nDrive, + rq->r_status & S_MASK, + lpDevice); +} diff --git a/kernel/execrh.asm b/kernel/execrh.asm new file mode 100644 index 0000000..138a79c --- /dev/null +++ b/kernel/execrh.asm @@ -0,0 +1,129 @@ +; +; File: +; execrh.asm +; Description: +; request handler for calling device drivers +; +; Copyright (c) 1995, 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/usr/patv/dos-c/src/kernel/execrh.asv $ +; +; $Id$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:35:03 jhall1 +; Initial revision +; +; Revision 1.3 2000/03/09 06:07:11 kernel +; 2017f updates by James Tabor +; +; Revision 1.2 1999/08/10 17:57:12 jprice +; ror4 2011-02 patch +; +; Revision 1.1.1.1 1999/03/29 15:40:54 jprice +; New version without IPL.SYS +; +; Revision 1.4 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; Revision 1.3 1999/02/01 01:48:41 jprice +; Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) +; +; Revision 1.2 1999/01/22 04:13:25 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:01 jprice +; Imported sources +; +; +; Rev 1.3 06 Dec 1998 8:45:06 patv +;Bug fixes. +; +; Rev 1.2 29 May 1996 21:03:30 patv +;bug fixes for v0.91a +; +; Rev 1.1 01 Sep 1995 17:54:22 patv +;First GPL release. +; +; Rev 1.0 02 Jul 1995 9:05:34 patv +;Initial revision. +; $EndLog$ +; + + %include "segs.inc" + +segment _TEXT + ; _execrh + ; Execute Device Request + ; + ; execrh(rhp, dhp) + ; request far *rhp; + ; struct dhdr far *dhp; + ; +; +; The stack is very critical in here. +; + global _execrh +_execrh: + push bp ; perform c entry + mov bp,sp + push bp ; it will get destroyed + push bx ; random char on display + push si + push es ; sometimes it get lost + push ds + + lds si,[bp+8] ; ds:si = device header + les bx,[bp+4] ; es:bx = request header + + push cs ; do this, the right way! + push word exit_execrh ; like 68k code + push ds + push word [ds:si+8] ; interrupt + push ds + push word [ds:si+6] ; strategy + retf +exit_execrh: sti ; damm driver turn off ints + cld ; has gone backwards + pop ds + pop es + pop si + pop bx + pop bp + mov sp,bp + pop bp + ret + + global _init_call_execrh + +_init_call_execrh: + push bp + mov bp,sp + push word [bp+12] + push word [bp+10] + push word [bp+8] + push word [bp+6] + call _execrh + mov sp,bp + pop bp + retf + diff --git a/kernel/fatdir.c b/kernel/fatdir.c new file mode 100644 index 0000000..1c2d823 --- /dev/null +++ b/kernel/fatdir.c @@ -0,0 +1,829 @@ +/****************************************************************/ +/* */ +/* fatdir.c */ +/* DOS-C */ +/* */ +/* FAT File System dir Functions */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *fatdirRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:05 jhall1 + * Initial revision + * + * Revision 1.10 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.9 1999/08/25 03:18:07 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.8 1999/08/10 17:57:12 jprice + * ror4 2011-02 patch + * + * Revision 1.7 1999/05/03 06:25:45 jprice + * Patches from ror4 and many changed of signed to unsigned variables. + * + * Revision 1.6 1999/04/16 00:53:32 jprice + * Optimized FAT handling + * + * Revision 1.5 1999/04/13 15:48:20 jprice + * no message + * + * Revision 1.4 1999/04/11 04:33:38 jprice + * ror4 patches + * + * Revision 1.2 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:41:58 jprice + * New version without IPL.SYS + * + * Revision 1.7 1999/03/25 05:06:57 jprice + * Fixed findfirst & findnext functions to treat the attributes like MSDOS does. + * + * Revision 1.6 1999/02/14 04:27:09 jprice + * Changed check media so that it checks if a floppy disk has been changed. + * + * Revision 1.5 1999/02/09 02:54:23 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/01 01:43:28 jprice + * Fixed findfirst function to find volume label with Windows long filenames + * + * Revision 1.3 1999/01/30 08:25:34 jprice + * Clean up; Fixed bug with set attribute function. If you tried to + * change the attributres of a directory, it would erase it. + * + * Revision 1.2 1999/01/22 04:15:28 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * + * Rev 1.10 06 Dec 1998 8:44:36 patv + * Bug fixes. + * + * Rev 1.9 22 Jan 1998 4:09:00 patv + * Fixed pointer problems affecting SDA + * + * Rev 1.8 04 Jan 1998 23:14:36 patv + * Changed Log for strip utility + * + * Rev 1.7 03 Jan 1998 8:36:02 patv + * Converted data area to SDA format + * + * Rev 1.6 16 Jan 1997 12:46:30 patv + * pre-Release 0.92 feature additions + * + * Rev 1.5 29 May 1996 21:15:18 patv + * bug fixes for v0.91a + * + * Rev 1.4 19 Feb 1996 3:20:12 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:48:38 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:50:24 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:04:34 patv + * Initial revision. + */ + +VOID pop_dmp(dmatch FAR *, struct f_node FAR *); + +struct f_node FAR *dir_open(BYTE FAR * dirname) +{ + struct f_node FAR *fnp; + COUNT drive; + BYTE *p; + WORD i, + x; + BYTE *s; + struct cds FAR *cdsp; + BYTE *pszPath = &TempCDS.cdsCurrentPath[2]; + + /* Allocate an fnode if possible - error return (0) if not. */ + if ((fnp = get_f_node()) == (struct f_node FAR *)0) + { + return (struct f_node FAR *)NULL; + } + + /* Force the fnode into read-write mode */ + fnp->f_mode = RDWR; + + /* and initialize temporary CDS */ + TempCDS.cdsFlags = 0; + /* determine what drive we are using... */ + dirname = adjust_far(dirname); + if (ParseDosName(dirname, &drive, (BYTE *) 0, (BYTE *) 0, (BYTE *) 0, FALSE) + != SUCCESS) + { + release_f_node(fnp); + return NULL; + } + + /* If the drive was specified, drive is non-negative and */ + /* corresponds to the one passed in, i.e., 0 = A, 1 = B, etc. */ + /* We use that and skip the "D:" part of the string. */ + /* Otherwise, just use the default drive */ + if (drive >= 0) + { + dirname += 2; /* Assume FAT style drive */ + TempCDS.cdsDpb = CDSp->cds_table[drive].cdsDpb; + } + else + { + drive = default_drive; + TempCDS.cdsDpb = CDSp->cds_table[drive].cdsDpb; + + } + + cdsp = &CDSp->cds_table[drive]; + + TempCDS.cdsCurrentPath[0] = 'A' + drive; + TempCDS.cdsCurrentPath[1] = ':'; + TempCDS.cdsJoinOffset = 2; + + x = cdsp->cdsJoinOffset; + + /* Generate full path name */ + ParseDosPath(dirname, (COUNT *) 0, pszPath, (BYTE FAR *) & cdsp->cdsCurrentPath[x]); + + if ((cdsp->cdsFlags & 0x8000)) + { + printf("FailSafe %x \n", Int21AX); + return fnp; + } + + if (TempCDS.cdsDpb == 0) + { + release_f_node(fnp); + return NULL; + } + +/* if (drive >= lastdrive) + { + release_f_node(fnp); + return NULL; + } + */ + fnp->f_dpb = (struct dpb *)TempCDS.cdsDpb; + + /* Perform all directory common handling after all special */ + /* handling has been performed. */ + + if (media_check((struct dpb *)TempCDS.cdsDpb) < 0) + { + release_f_node(fnp); + return (struct f_node FAR *)0; + } + + fnp->f_dsize = DIRENT_SIZE * TempCDS.cdsDpb->dpb_dirents; + + fnp->f_diroff = 0l; + fnp->f_flags.f_dmod = FALSE; /* a brand new fnode */ + fnp->f_flags.f_dnew = TRUE; + fnp->f_flags.f_dremote = FALSE; + + fnp->f_dirstart = 0; + + /* Walk the directory tree to find the starting cluster */ + /* */ + /* Set the root flags since we always start from the root */ + + fnp->f_flags.f_droot = TRUE; + for (p = pszPath; *p != '\0';) + { + /* skip all path seperators */ + while (*p == '\\') + ++p; + /* don't continue if we're at the end */ + if (*p == '\0') + break; + + /* Convert the name into an absolute name for */ + /* comparison... */ + /* first the file name with trailing spaces... */ + for (i = 0; i < FNAME_SIZE; i++) + { + if (*p != '\0' && *p != '.' && *p != '/' && *p != '\\') + TempBuffer[i] = *p++; + else + break; + } + + for (; i < FNAME_SIZE; i++) + TempBuffer[i] = ' '; + + /* and the extension (don't forget to */ + /* add trailing spaces)... */ + if (*p == '.') + ++p; + for (i = 0; i < FEXT_SIZE; i++) + { + if (*p != '\0' && *p != '.' && *p != '/' && *p != '\\') + TempBuffer[i + FNAME_SIZE] = *p++; + else + break; + } + for (; i < FEXT_SIZE; i++) + TempBuffer[i + FNAME_SIZE] = ' '; + + /* Now search through the directory to */ + /* find the entry... */ + i = FALSE; + + upMem((BYTE FAR *) TempBuffer, FNAME_SIZE + FEXT_SIZE); + + while (dir_read(fnp) == DIRENT_SIZE) + { + if (fnp->f_dir.dir_name[0] != '\0' && fnp->f_dir.dir_name[0] != DELETED) + { + if (fcmp((BYTE FAR *) TempBuffer, (BYTE FAR *) fnp->f_dir.dir_name, FNAME_SIZE + FEXT_SIZE)) + { + i = TRUE; + break; + } + } + } + + if (!i || !(fnp->f_dir.dir_attrib & D_DIR)) + { + + release_f_node(fnp); + return (struct f_node FAR *)0; + } + else + { + /* make certain we've moved off */ + /* root */ + fnp->f_flags.f_droot = FALSE; + fnp->f_flags.f_ddir = TRUE; + /* set up for file read/write */ + fnp->f_offset = 0l; + fnp->f_cluster_offset = 0l; /*JPP */ + fnp->f_highwater = 0l; + fnp->f_cluster = fnp->f_dir.dir_start; + fnp->f_dirstart = fnp->f_dir.dir_start; + /* reset the directory flags */ + fnp->f_diroff = 0l; + fnp->f_flags.f_dmod = FALSE; + fnp->f_flags.f_dnew = TRUE; + fnp->f_dsize = DIRENT_SIZE * TempCDS.cdsDpb->dpb_dirents; + + } + } + return fnp; +} + +COUNT dir_read(REG struct f_node FAR * fnp) +{ + REG i; + REG j; + struct buffer FAR *bp; + + /* Directories need to point to their current offset, not for */ + /* next op. Therefore, if it is anything other than the first */ + /* directory entry, we will update the offset on entry rather */ + /* than wait until exit. If it was new, clear the special new */ + /* flag. */ + if (fnp->f_flags.f_dnew) + fnp->f_flags.f_dnew = FALSE; + else + fnp->f_diroff += DIRENT_SIZE; + + /* Determine if we hit the end of the directory. If we have, */ + /* bump the offset back to the end and exit. If not, fill the */ + /* dirent portion of the fnode, clear the f_dmod bit and leave, */ + /* but only for root directories */ + if (fnp->f_flags.f_droot && fnp->f_diroff >= fnp->f_dsize) + { + fnp->f_diroff -= DIRENT_SIZE; + return 0; + } + else + { + if (fnp->f_flags.f_droot) + { + if ((fnp->f_diroff / fnp->f_dpb->dpb_secsize + + fnp->f_dpb->dpb_dirstrt) + >= fnp->f_dpb->dpb_data) + { + fnp->f_flags.f_dfull = TRUE; + return 0; + } + + bp = getblock((ULONG) (fnp->f_diroff / fnp->f_dpb->dpb_secsize + + fnp->f_dpb->dpb_dirstrt), + fnp->f_dpb->dpb_unit); + bp->b_flag &= ~(BFR_DATA | BFR_FAT); + bp->b_flag |= BFR_DIR; +#ifdef DISPLAY_GETBLOCK + printf("DIR (dir_read)\n"); +#endif + } + else + { + REG UWORD secsize = fnp->f_dpb->dpb_secsize; + + /* Do a "seek" to the directory position */ + fnp->f_offset = fnp->f_diroff; + + /* Search through the FAT to find the block */ + /* that this entry is in. */ +#ifdef DISPLAY_GETBLOCK + printf("dir_read: "); +#endif + if (map_cluster(fnp, XFR_READ) != SUCCESS) + { + fnp->f_flags.f_dfull = TRUE; + return 0; + } + + /* If the returned cluster is FREE, return zero */ + /* bytes read. */ + if (fnp->f_cluster == FREE) + return 0; + + /* If the returned cluster is LAST_CLUSTER or */ + /* LONG_LAST_CLUSTER, return zero bytes read */ + /* and set the directory as full. */ + + if (last_link(fnp)) + { + fnp->f_diroff -= DIRENT_SIZE; + fnp->f_flags.f_dfull = TRUE; + return 0; + } + + /* Compute the block within the cluster and the */ + /* offset within the block. */ + fnp->f_sector = (fnp->f_offset / secsize) & fnp->f_dpb->dpb_clsmask; + fnp->f_boff = fnp->f_offset % secsize; + + /* Get the block we need from cache */ + bp = getblock((ULONG) clus2phys(fnp->f_cluster, + (fnp->f_dpb->dpb_clsmask + 1), + fnp->f_dpb->dpb_data) + + fnp->f_sector, + fnp->f_dpb->dpb_unit); + bp->b_flag &= ~(BFR_DATA | BFR_FAT); + bp->b_flag |= BFR_DIR; +#ifdef DISPLAY_GETBLOCK + printf("DIR (dir_read)\n"); +#endif + } + + /* Now that we have the block for our entry, get the */ + /* directory entry. */ + if (bp != NULL) + getdirent((BYTE FAR *) & bp->b_buffer[fnp->f_diroff % fnp->f_dpb->dpb_secsize], + (struct dirent FAR *)&fnp->f_dir); + else + { + fnp->f_flags.f_dfull = TRUE; + return 0; + } + + /* Update the fnode's directory info */ + fnp->f_flags.f_dfull = FALSE; + fnp->f_flags.f_dmod = FALSE; + + /* and for efficiency, stop when we hit the first */ + /* unused entry. */ + if (fnp->f_dir.dir_name[0] == '\0') + return 0; + else + return DIRENT_SIZE; + } +} + +#ifndef IPL +COUNT dir_write(REG struct f_node FAR * fnp) +{ + struct buffer FAR *bp; + + /* Update the entry if it was modified by a write or create... */ + if (fnp->f_flags.f_dmod) + { + /* Root is a consecutive set of blocks, so handling is */ + /* simple. */ + if (fnp->f_flags.f_droot) + { + bp = getblock( + (ULONG) (fnp->f_diroff / fnp->f_dpb->dpb_secsize + + fnp->f_dpb->dpb_dirstrt), + fnp->f_dpb->dpb_unit); + bp->b_flag &= ~(BFR_DATA | BFR_FAT); + bp->b_flag |= BFR_DIR; +#ifdef DISPLAY_GETBLOCK + printf("DIR (dir_write)\n"); +#endif + } + + /* All other directories are just files. The only */ + /* special handling is resetting the offset so that we */ + /* can continually update the same directory entry. */ + else + { + REG UWORD secsize = fnp->f_dpb->dpb_secsize; + + /* Do a "seek" to the directory position */ + /* and convert the fnode to a directory fnode. */ + fnp->f_offset = fnp->f_diroff; + fnp->f_back = LONG_LAST_CLUSTER; + fnp->f_cluster = fnp->f_dirstart; + fnp->f_cluster_offset = 0l; /*JPP */ + + /* Search through the FAT to find the block */ + /* that this entry is in. */ +#ifdef DISPLAY_GETBLOCK + printf("dir_write: "); +#endif + if (map_cluster(fnp, XFR_READ) != SUCCESS) + { + fnp->f_flags.f_dfull = TRUE; + release_f_node(fnp); + return 0; + } + + /* If the returned cluster is FREE, return zero */ + /* bytes read. */ + if (fnp->f_cluster == FREE) + { + release_f_node(fnp); + return 0; + } + + /* Compute the block within the cluster and the */ + /* offset within the block. */ + fnp->f_sector = (fnp->f_offset / secsize) & fnp->f_dpb->dpb_clsmask; + fnp->f_boff = fnp->f_offset % secsize; + + /* Get the block we need from cache */ + bp = getblock((ULONG) clus2phys(fnp->f_cluster, + (fnp->f_dpb->dpb_clsmask + 1), + fnp->f_dpb->dpb_data) + + fnp->f_sector, + fnp->f_dpb->dpb_unit); + bp->b_flag &= ~(BFR_DATA | BFR_FAT); + bp->b_flag |= BFR_DIR; +#ifdef DISPLAY_GETBLOCK + printf("DIR (dir_write)\n"); +#endif + } + + /* Now that we have a block, transfer the diectory */ + /* entry into the block. */ + if (bp == NULL) + { + release_f_node(fnp); + return 0; + } + putdirent((struct dirent FAR *)&fnp->f_dir, + (VOID FAR *) & bp->b_buffer[fnp->f_diroff % fnp->f_dpb->dpb_secsize]); + bp->b_flag |= BFR_DIRTY; + } + return DIRENT_SIZE; +} +#endif + +VOID dir_close(REG struct f_node FAR * fnp) +{ + REG COUNT disk = fnp->f_dpb->dpb_unit; + + /* Test for invalid f_nodes */ + if (fnp == NULL) + return; + +#ifndef IPL + /* Write out the entry */ + dir_write(fnp); + +#endif + /* Clear buffers after release */ + flush_buffers(disk); + + /* and release this instance of the fnode */ + release_f_node(fnp); +} + +#ifndef IPL +COUNT dos_findfirst(UCOUNT attr, BYTE FAR * name) +{ + REG struct f_node FAR *fnp; + REG dmatch FAR *dmp = (dmatch FAR *) dta; + REG COUNT i; + COUNT nDrive; + BYTE *p; + struct cds FAR *cdsp; + + static BYTE local_name[FNAME_SIZE + 1], + local_ext[FEXT_SIZE + 1]; + + /* The findfirst/findnext calls are probably the worst of the */ + /* DOS calls. They must work somewhat on the fly (i.e. - open */ + /* but never close). Since we don't want to lose fnodes every */ + /* time a directory is searched, we will initialize the DOS */ + /* dirmatch structure and then for every find, we will open the */ + /* current directory, do a seek and read, then close the fnode. */ + + /* Start out by initializing the dirmatch structure. */ + dmp->dm_drive = default_drive; + dmp->dm_entry = 0; + dmp->dm_cluster = 0; + + dmp->dm_attr_srch = attr | D_RDONLY | D_ARCHIVE; + + /* Parse out the drive, file name and file extension. */ + i = ParseDosName(name, &nDrive, &LocalPath[2], local_name, local_ext, TRUE); + if (i != SUCCESS) + return i; + + if (nDrive >= 0) + { + dmp->dm_drive = nDrive; + } + else + nDrive = default_drive; + + cdsp = &CDSp->cds_table[nDrive]; + + if (cdsp->cdsFlags & 0x8000) + { + if (Remote_find(REM_FINDFIRST, attr, name, dmp) != 0) + return DE_FILENOTFND; + return SUCCESS; + } + + /* Now build a directory. */ + if (!LocalPath[2]) + strcpy(&LocalPath[2], "."); + + /* Build the match pattern out of the passed string */ + /* copy the part of the pattern which belongs to the filename and is fixed */ + for (p = local_name, i = 0; i < FNAME_SIZE && *p && *p != '*'; ++p, ++i) + SearchDir.dir_name[i] = *p; + if (*p == '*') + { + for (; i < FNAME_SIZE; ++i) + SearchDir.dir_name[i] = '?'; + while (*++p) ; + } + else + for (; i < FNAME_SIZE; i++) + SearchDir.dir_name[i] = ' '; + + /* and the extension (don't forget to add trailing spaces)... */ + for (p = local_ext, i = 0; i < FEXT_SIZE && *p && *p != '*'; ++p, ++i) + SearchDir.dir_ext[i] = *p; + if (*p == '*') + { + for (; i < FEXT_SIZE; ++i) + SearchDir.dir_ext[i] = '?'; + while (*++p) ; + } + else + for (; i < FEXT_SIZE; i++) + SearchDir.dir_ext[i] = ' '; + + /* Convert everything to uppercase. */ + upMem(SearchDir.dir_name, FNAME_SIZE + FEXT_SIZE); + + /* Copy the raw pattern from our data segment to the DTA. */ + fbcopy((BYTE FAR *) SearchDir.dir_name, dmp->dm_name_pat, + FNAME_SIZE + FEXT_SIZE); + + /* Now search through the directory to find the entry... */ + /* Special handling - the volume id is only in the root */ + /* directory and only searched for once. So we need to open */ + /* the root and return only the first entry that contains the */ + /* volume id bit set. */ + if ((attr & ~(D_RDONLY | D_ARCHIVE)) == D_VOLID) + { + /* Now open this directory so that we can read the */ + /* fnode entry and do a match on it. */ + if ((fnp = dir_open((BYTE FAR *) "\\")) == NULL) + return DE_PATHNOTFND; + + /* Now do the search */ + while (dir_read(fnp) == DIRENT_SIZE) + { + /* Test the attribute and return first found */ + if ((fnp->f_dir.dir_attrib & ~(D_RDONLY | D_ARCHIVE)) == D_VOLID) + { + pop_dmp(dmp, fnp); + dir_close(fnp); + return SUCCESS; + } + } + + /* Now that we've done our failed search, close it and */ + /* return an error. */ + dir_close(fnp); + return DE_FILENOTFND; + } + + /* Otherwise just do a normal find next */ + else + { + /* Complete building the directory from the passed in */ + /* name */ + if (nDrive >= 0) + LocalPath[0] = 'A' + nDrive; + else + LocalPath[0] = 'A' + default_drive; + LocalPath[1] = ':'; + + /* Now open this directory so that we can read the */ + /* fnode entry and do a match on it. */ + if ((fnp = dir_open((BYTE FAR *) LocalPath)) == NULL) + return DE_PATHNOTFND; + + pop_dmp(dmp, fnp); + dmp->dm_entry = 0; + if (!fnp->f_flags.f_droot) + { + dmp->dm_cluster = fnp->f_dirstart; + dmp->dm_dirstart = fnp->f_dirstart; + } + else + { + dmp->dm_cluster = 0; + dmp->dm_dirstart = 0; + } + dir_close(fnp); + return dos_findnext(); + } +} + +COUNT dos_findnext(void) +{ + REG dmatch FAR *dmp = (dmatch FAR *) dta; + REG struct f_node FAR *fnp; + BOOL found = FALSE; + BYTE FAR *p; + BYTE FAR *q; + COUNT nDrive; + struct cds FAR *cdsp; + + /* assign our match parameters pointer. */ + dmp = (dmatch FAR *) dta; + + nDrive = dmp->dm_drive; + + cdsp = &CDSp->cds_table[nDrive]; + if (cdsp->cdsFlags & 0x8000) + { + if (Remote_find(REM_FINDNEXT, 0, 0, dmp) != 0) + return DE_FILENOTFND; + return SUCCESS; + } + + /* Allocate an fnode if possible - error return (0) if not. */ + if ((fnp = get_f_node()) == (struct f_node FAR *)0) + { + return DE_FILENOTFND; + } + + /* Force the fnode into read-write mode */ + fnp->f_mode = RDWR; + + /* Select the default to help non-drive specified path */ + /* searches... */ + fnp->f_dpb = (struct dpb *)CDSp->cds_table[dmp->dm_drive].cdsDpb; + if (media_check(fnp->f_dpb) < 0) + { + release_f_node(fnp); + return DE_FILENOTFND; + } + + fnp->f_dsize = DIRENT_SIZE * (fnp->f_dpb)->dpb_dirents; + + /* Search through the directory to find the entry, but do a */ + /* seek first. */ + if (dmp->dm_entry > 0) + fnp->f_diroff = (dmp->dm_entry - 1) * DIRENT_SIZE; + + fnp->f_offset = fnp->f_highwater = fnp->f_diroff; + fnp->f_cluster = dmp->dm_cluster; + fnp->f_cluster_offset = 0l; /*JPP */ + fnp->f_flags.f_dmod = dmp->dm_flags.f_dmod; + fnp->f_flags.f_droot = dmp->dm_flags.f_droot; + fnp->f_flags.f_dnew = dmp->dm_flags.f_dnew; + fnp->f_flags.f_ddir = dmp->dm_flags.f_ddir; + fnp->f_flags.f_dfull = dmp->dm_flags.f_dfull; + + fnp->f_dirstart = dmp->dm_dirstart; + + /* Loop through the directory */ + while (dir_read(fnp) == DIRENT_SIZE) + { + ++dmp->dm_entry; + if (fnp->f_dir.dir_name[0] != '\0' && fnp->f_dir.dir_name[0] != DELETED) + { + if (fcmp_wild((BYTE FAR *) (dmp->dm_name_pat), (BYTE FAR *) fnp->f_dir.dir_name, FNAME_SIZE + FEXT_SIZE)) + { + /* Test the attribute as the final step */ + if (!(~dmp->dm_attr_srch & fnp->f_dir.dir_attrib)) + { + found = TRUE; + break; + } + else + continue; + } + } + } + + /* If found, transfer it to the dmatch structure */ + if (found) + pop_dmp(dmp, fnp); + + /* return the result */ + release_f_node(fnp); + + return found ? SUCCESS : DE_FILENOTFND; +} + +static VOID pop_dmp(dmatch FAR * dmp, struct f_node FAR * fnp) +{ + COUNT idx; + BYTE FAR *p; + BYTE FAR *q; + + dmp->dm_attr_fnd = fnp->f_dir.dir_attrib; + dmp->dm_time = fnp->f_dir.dir_time; + dmp->dm_date = fnp->f_dir.dir_date; + dmp->dm_size = fnp->f_dir.dir_size; +/* dmp -> dm_cluster = fnp -> f_cluster; /* */ + dmp->dm_flags.f_droot = fnp->f_flags.f_droot; + dmp->dm_flags.f_ddir = fnp->f_flags.f_ddir; + dmp->dm_flags.f_dmod = fnp->f_flags.f_dmod; + dmp->dm_flags.f_dnew = fnp->f_flags.f_dnew; + p = dmp->dm_name; + if (fnp->f_dir.dir_name[0] == '.') + { + for (idx = 0, q = (BYTE FAR *) fnp->f_dir.dir_name; + idx < FNAME_SIZE; idx++) + { + if (*q == ' ') + break; + *p++ = *q++; + } + } + else + { + for (idx = 0, q = (BYTE FAR *) fnp->f_dir.dir_name; + idx < FNAME_SIZE; idx++) + { + if (*q == ' ') + break; + *p++ = *q++; + } + if (fnp->f_dir.dir_ext[0] != ' ') + { + *p++ = '.'; + for (idx = 0, q = (BYTE FAR *) fnp->f_dir.dir_ext; idx < FEXT_SIZE; idx++) + { + if (*q == ' ') + break; + *p++ = *q++; + } + } + } + *p++ = NULL; +} +#endif + diff --git a/kernel/fatfs.c b/kernel/fatfs.c new file mode 100644 index 0000000..e938f02 --- /dev/null +++ b/kernel/fatfs.c @@ -0,0 +1,2117 @@ +/****************************************************************/ +/* */ +/* fatfs.c */ +/* DOS-C */ +/* */ +/* FAT File System I/O Functions */ +/* */ +/* Copyright (c) 1995,1998 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:09 jhall1 + * Initial revision + * + * Revision 1.16 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.15 1999/09/23 04:40:46 jprice + * *** empty log message *** + * + * Revision 1.12 1999/09/14 01:01:54 jprice + * Fixed bug where you could write over directories. + * + * Revision 1.11 1999/08/25 03:18:08 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.10 1999/08/10 18:03:42 jprice + * ror4 2011-03 patch + * + * Revision 1.9 1999/05/03 06:25:45 jprice + * Patches from ror4 and many changed of signed to unsigned variables. + * + * Revision 1.8 1999/05/03 05:00:24 jprice + * Fixed bug in map_cluster function + * + * Revision 1.7 1999/04/16 00:53:33 jprice + * Optimized FAT handling + * + * Revision 1.6 1999/04/12 23:41:54 jprice + * Using getbuf to write data instead of getblock + * using getblock made it read the block before it wrote it + * + * Revision 1.5 1999/04/12 03:21:17 jprice + * more ror4 patches. Changes for multi-block IO + * + * Revision 1.4 1999/04/11 04:33:38 jprice + * ror4 patches + * + * Revision 1.2 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:42:07 jprice + * New version without IPL.SYS + * + * Revision 1.8 1999/03/23 23:37:39 jprice + * Fixed mkdir DOS function so it will create a directory with same name as the volument label + * + * Revision 1.7 1999/03/02 07:00:51 jprice + * Fixed bugs with dos set attribute function. Now returns correct + * error code, and errors if user tries to set bits 6 & 7. + * + * Revision 1.6 1999/02/09 02:54:23 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.5 1999/02/04 03:18:37 jprice + * Formating. Added comments. + * + * Revision 1.4 1999/02/01 01:43:28 jprice + * Fixed findfirst function to find volume label with Windows long filenames + * + * Revision 1.3 1999/01/30 08:25:34 jprice + * Clean up; Fixed bug with set attribute function. If you tried to + * change the attributes of a directory, it would erase it. + * + * Revision 1.2 1999/01/22 04:15:28 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * + * Rev 1.14 06 Dec 1998 8:44:26 patv + * Bug fixes. + * + * Rev 1.13 09 Feb 1998 5:43:30 patv + * Eliminated FAT12 EOF and error useage. + * + * Rev 1.12 03 Feb 1998 11:28:04 patv + * Fixed lseek bug. + * + * Rev 1.11 22 Jan 1998 5:38:08 patv + * Corrected remaining file name and extension copies that did not + * account for far file nodes due to allocated FILES= spec. + * + * Rev 1.10 22 Jan 1998 4:09:00 patv + * Fixed pointer problems affecting SDA + * + * Rev 1.9 04 Jan 1998 23:14:40 patv + * Changed Log for strip utility + * + * Rev 1.8 04 Jan 1998 17:24:14 patv + * Corrected subdirectory bug + * + * Rev 1.7 03 Jan 1998 8:36:04 patv + * Converted data area to SDA format + * + * Rev 1.6 22 Jan 1997 13:00:30 patv + * pre-0.92 bug fixes + * + * Rev 1.5 16 Jan 1997 12:46:24 patv + * pre-Release 0.92 feature additions + * + * Rev 1.4 29 May 1996 21:15:16 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:20:10 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:48:40 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:50:24 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:04:46 patv + * Initial revision. + */ + +/* */ +/* function prototypes */ +/* */ +struct f_node FAR *xlt_fd(COUNT); +COUNT xlt_fnp(struct f_node FAR *); +struct f_node FAR *split_path(BYTE FAR *, BYTE *, BYTE *, BYTE *); +BOOL find_fname(struct f_node FAR *, BYTE *, BYTE *); +date dos_getdate(VOID); +time dos_gettime(VOID); +BOOL find_free(struct f_node FAR *); +UWORD find_fat_free(struct f_node FAR *); +VOID wipe_out(struct f_node FAR *); +BOOL last_link(struct f_node FAR *); +BOOL extend(struct f_node FAR *); +COUNT extend_dir(struct f_node FAR *); +BOOL first_fat(struct f_node FAR *); +COUNT map_cluster(struct f_node FAR *, COUNT); + +/************************************************************************/ +/* */ +/* Internal file handlers - open, create, read, write, close, etc. */ +/* */ +/************************************************************************/ + +/* Open a file given the path. Flags is 0 for read, 1 for write and 2 */ +/* for update. */ +/* Returns an integer file desriptor or a negative error code */ + +COUNT dos_open(BYTE FAR * path, COUNT flag) +{ + REG struct f_node FAR *fnp; + COUNT i; + BYTE FAR *fnamep; + + /* First test the flag to see if the user has passed a valid */ + /* file mode... */ + if (flag < 0 || flag > 2) + return DE_INVLDACC; + + /* first split the passed dir into comopnents (i.e. - path to */ + /* new directory and name of new directory. */ + if ((fnp = split_path(path, szDirName, szFileName, szFileExt)) == NULL) + { + dir_close(fnp); + return DE_PATHNOTFND; + } + + /* Look for the file. If we can't find it, just return a not */ + /* found error. */ + if (!find_fname(fnp, szFileName, szFileExt)) + { + dir_close(fnp); + return DE_FILENOTFND; + } + + /* Set the fnode to the desired mode */ + fnp->f_mode = flag; + + /* Initialize the rest of the fnode. */ + fnp->f_offset = 0l; + fnp->f_highwater = fnp->f_dir.dir_size; + + fnp->f_back = LONG_LAST_CLUSTER; + fnp->f_cluster = fnp->f_dir.dir_start; + fnp->f_cluster_offset = 0l; /*JPP */ + + fnp->f_flags.f_dmod = FALSE; + fnp->f_flags.f_dnew = FALSE; + fnp->f_flags.f_ddir = FALSE; + + return xlt_fnp(fnp); +} + +COUNT FAR init_call_dos_open(BYTE FAR * path, COUNT flag) +{ + return dos_open(path, flag); +} + +BOOL fcmp(BYTE FAR * s1, BYTE FAR * s2, COUNT n) +{ + while (n--) + if (*s1++ != *s2++) + return FALSE; + return TRUE; +} + +BOOL fcmp_wild(BYTE FAR * s1, BYTE FAR * s2, COUNT n) +{ + while (n--) + { + if (*s1 == '?') + { + ++s1, ++s2; + continue; + } + if (*s1++ != *s2++) + return FALSE; + } + return TRUE; +} + +COUNT dos_close(COUNT fd) +{ + struct f_node FAR *fnp; + + /* Translate the fd into a useful pointer */ + fnp = xlt_fd(fd); + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit */ + /* note: an invalid fd is indicated by a 0 return */ + if (fnp == (struct f_node FAR *)0 || fnp->f_count <= 0) + return DE_INVLDHNDL; + + if (fnp->f_mode != RDONLY) + { + fnp->f_dir.dir_size = fnp->f_highwater; + fnp->f_flags.f_dmod = TRUE; + } + fnp->f_flags.f_ddir = TRUE; + + dir_close(fnp); + return SUCCESS; +} + +COUNT FAR init_call_dos_close(COUNT fd) +{ + return dos_close(fd); +} + +/* */ +/* split a path into it's component directory and file name */ +/* */ +static struct f_node FAR * + split_path(BYTE FAR * path, BYTE * dname, BYTE * fname, BYTE * fext) +{ + REG struct f_node FAR *fnp; + COUNT nDrive; + struct cds FAR *cdsp; + + /* Start off by parsing out the components. */ + if (ParseDosName(adjust_far(path), &nDrive, &dname[2], fname, fext, FALSE) + != SUCCESS) + return (struct f_node FAR *)0; + if (nDrive < 0) + nDrive = default_drive; + + dname[0] = 'A' + nDrive; + dname[1] = ':'; + + /* Add trailing spaces to the file name and extension */ + SpacePad(fname, FNAME_SIZE); + SpacePad(fext, FEXT_SIZE); + + cdsp = &CDSp->cds_table[nDrive]; + + /* If the path is null, we to default to the current */ + /* directory... */ + if (!dname[2]) + { + fsncopy(cdsp->cdsCurrentPath, (BYTE FAR *) dname, PARSE_MAX); + } + +/* 11/29/99 jt + * Networking and Cdroms. You can put in here a return. + * Maybe a return of 0xDEADBEEF or something for Split or Dir_open. + * Just to let upper level Fdos know its a sft, CDS function. + * Right now for Networking there is no support for Rename, MkDir + * RmDir & Delete. + + + + */ + + /* Translate the path into a useful pointer */ + fnp = dir_open((BYTE FAR *) dname); + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit... */ + /* note: an invalid fd is indicated by a 0 return */ + if (fnp == (struct f_node FAR *)0 || fnp->f_count <= 0) + { + dir_close(fnp); + return (struct f_node FAR *)0; + } + + /* Convert the name into an absolute name for comparison... */ + upMem((BYTE FAR *) dname, strlen(dname)); + upMem((BYTE FAR *) fname, FNAME_SIZE); + upMem((BYTE FAR *) fext, FEXT_SIZE); + + return fnp; +} + +static BOOL find_fname(struct f_node FAR * fnp, BYTE * fname, BYTE * fext) +{ + BOOL found = FALSE; + + while (dir_read(fnp) == DIRENT_SIZE) + { + if (fnp->f_dir.dir_name[0] != '\0') + { + if (fnp->f_dir.dir_name[0] == DELETED) + continue; + + if (fcmp((BYTE FAR *) fname, (BYTE FAR *) fnp->f_dir.dir_name, FNAME_SIZE) + && fcmp((BYTE FAR *) fext, (BYTE FAR *) fnp->f_dir.dir_ext, FEXT_SIZE) + && ((fnp->f_dir.dir_attrib & D_VOLID) == 0)) + { + found = TRUE; + break; + } + } + } + return found; +} + +COUNT dos_creat(BYTE FAR * path, COUNT attrib) +{ + REG struct f_node FAR *fnp; + + /* first split the passed dir into comopnents (i.e. - */ + /* path to new directory and name of new directory */ + if ((fnp = split_path(path, szDirName, szFileName, szFileExt)) == NULL) + { + dir_close(fnp); + return DE_PATHNOTFND; + } + + /* Check that we don't have a duplicate name, so if we */ + /* find one, truncate it. */ + if (find_fname(fnp, szFileName, szFileExt)) + { + /* The only permissable attribute is archive, */ + /* check for any other bit set. If it is, give */ + /* an access error. */ + if ((fnp->f_dir.dir_attrib & (D_RDONLY | D_DIR | D_VOLID)) + || (fnp->f_dir.dir_attrib & ~D_ARCHIVE & ~attrib)) + { + dir_close(fnp); + return DE_ACCESS; + } + + /* Release the existing files FAT and set the */ + /* length to zero, effectively truncating the */ + /* file to zero. */ + wipe_out(fnp); + } + else + { + BOOL is_free; + REG COUNT idx; + struct buffer FAR *bp; + BYTE FAR *p; + + /* Reset the directory by a close followed by */ + /* an open */ + fnp->f_flags.f_dmod = FALSE; + dir_close(fnp); + fnp = dir_open((BYTE FAR *) szDirName); + + /* Get a free f_node pointer so that we can use */ + /* it in building the new file. */ + /* Note that if we're in the root and we don't */ + /* find an empty slot, we need to abort. */ + if (!(is_free = find_free(fnp)) && (fnp->f_flags.f_droot)) + { + fnp->f_flags.f_dmod = FALSE; + dir_close(fnp); + return DE_TOOMANY; + } + + /* Otherwise just expand the directory */ + else if (!is_free && !(fnp->f_flags.f_droot)) + { + COUNT ret; + + if ((ret = extend_dir(fnp)) != SUCCESS) + return ret; + } + + /* put the fnode's name into the directory. */ + fbcopy((BYTE FAR *) szFileName, + (BYTE FAR *) fnp->f_dir.dir_name, FNAME_SIZE); + fbcopy((BYTE FAR *) szFileExt, + (BYTE FAR *) fnp->f_dir.dir_ext, FEXT_SIZE); + } + /* Set the fnode to the desired mode */ + /* Updating the directory entry first. */ + fnp->f_mode = RDWR; + + fnp->f_dir.dir_size = 0l; + fnp->f_dir.dir_start = FREE; + fnp->f_dir.dir_attrib = attrib | D_ARCHIVE; + fnp->f_dir.dir_time = dos_gettime(); + fnp->f_dir.dir_date = dos_getdate(); + + fnp->f_flags.f_dmod = TRUE; + fnp->f_flags.f_dnew = FALSE; + fnp->f_flags.f_ddir = TRUE; + if (dir_write(fnp) != DIRENT_SIZE) + { + release_f_node(fnp); + return DE_ACCESS; + } + + /* Now change to file */ + fnp->f_offset = 0l; + fnp->f_highwater = 0l; + + fnp->f_back = LONG_LAST_CLUSTER; + fnp->f_cluster = fnp->f_dir.dir_start = FREE; + fnp->f_cluster_offset = 0l; /*JPP */ + fnp->f_flags.f_dmod = TRUE; + fnp->f_flags.f_dnew = FALSE; + fnp->f_flags.f_ddir = FALSE; + + return xlt_fnp(fnp); +} + +COUNT dos_delete(BYTE FAR * path) +{ + REG struct f_node FAR *fnp; + + /* first split the passed dir into components (i.e. - */ + /* path to new directory and name of new directory */ + if ((fnp = split_path(path, szDirName, szFileName, szFileExt)) == NULL) + { + dir_close(fnp); + return DE_PATHNOTFND; + } + + /* Check that we don't have a duplicate name, so if we */ + /* find one, it's an error. */ + if (find_fname(fnp, szFileName, szFileExt)) + { + /* The only permissable attribute is archive, */ + /* check for any other bit set. If it is, give */ + /* an access error. */ + if (fnp->f_dir.dir_attrib & ~D_ARCHIVE) + { + dir_close(fnp); + return DE_ACCESS; + } + + /* Ok, so we can delete. Start out by */ + /* clobbering all FAT entries for this file */ + /* (or, in English, truncate the FAT). */ + wipe_out(fnp); + fnp->f_dir.dir_size = 0l; + *(fnp->f_dir.dir_name) = DELETED; + + /* The directory has been modified, so set the */ + /* bit before closing it, allowing it to be */ + /* updated */ + fnp->f_flags.f_dmod = TRUE; + dir_close(fnp); + + /* SUCCESSful completion, return it */ + return SUCCESS; + } + else + { + /* No such file, return the error */ + dir_close(fnp); + return DE_FILENOTFND; + } +} + +COUNT dos_rmdir(BYTE FAR * path) +{ + REG struct f_node FAR *fnp; + REG struct f_node FAR *fnp1; + BOOL found; + + /* first split the passed dir into comopnents (i.e. - */ + /* path to new directory and name of new directory */ + if ((fnp = split_path(path, szDirName, szFileName, szFileExt)) == NULL) + { + dir_close(fnp); + return DE_PATHNOTFND; + } + + /* Check that we're not trying to remove the root! */ + if ((path[0] == '\\') && (path[1] == NULL)) + { + dir_close(fnp); + return DE_ACCESS; + } + + /* Check that we don't have a duplicate name, so if we */ + /* find one, it's an error. */ + if (find_fname(fnp, szFileName, szFileExt)) + { + /* The only permissable attribute is directory, */ + /* check for any other bit set. If it is, give */ + /* an access error. */ + if (fnp->f_dir.dir_attrib & ~D_DIR) + { + dir_close(fnp); + return DE_ACCESS; + } + + /* Check that the directory is empty. Only the */ + /* "." and ".." are permissable. */ + fnp->f_flags.f_dmod = FALSE; + fnp1 = dir_open((BYTE FAR *) path); + dir_read(fnp1); + if (fnp1->f_dir.dir_name[0] != '.') + { + dir_close(fnp); + return DE_ACCESS; + } + + dir_read(fnp1); + if (fnp1->f_dir.dir_name[0] != '.') + { + dir_close(fnp); + return DE_ACCESS; + } + + /* Now search through the directory and make certain */ + /* that there are no entries. */ + found = FALSE; + while (dir_read(fnp1) == DIRENT_SIZE) + { + if (fnp1->f_dir.dir_name[0] == '\0') + break; + if (fnp1->f_dir.dir_name[0] == DELETED) + continue; + else + { + found = TRUE; + break; + } + } + + dir_close(fnp1); + /* If anything was found, exit with an error. */ + if (found) + { + dir_close(fnp); + return DE_ACCESS; + } + + /* Ok, so we can delete. Start out by */ + /* clobbering all FAT entries for this file */ + /* (or, in English, truncate the FAT). */ + wipe_out(fnp); + fnp->f_dir.dir_size = 0l; + *(fnp->f_dir.dir_name) = DELETED; + + /* The directory has been modified, so set the */ + /* bit before closing it, allowing it to be */ + /* updated */ + fnp->f_flags.f_dmod = TRUE; + dir_close(fnp); + + /* SUCCESSful completion, return it */ + return SUCCESS; + } + else + { + /* No such file, return the error */ + dir_close(fnp); + return DE_FILENOTFND; + } +} + +COUNT dos_rename(BYTE FAR * path1, BYTE FAR * path2) +{ + REG struct f_node FAR *fnp1; + REG struct f_node FAR *fnp2; + BOOL is_free; + + /* first split the passed target into compnents (i.e. - path to */ + /* new file name and name of new file name */ + if ((fnp2 = split_path(path2, szSecDirName, szSecFileName, szSecFileExt)) == NULL) + { + dir_close(fnp2); + return DE_PATHNOTFND; + } + + /* Check that we don't have a duplicate name, so if we find */ + /* one, it's an error. */ + if (find_fname(fnp2, szSecFileName, szSecFileExt)) + { + dir_close(fnp2); + return DE_ACCESS; + } + + /* next split the passed source into compnents (i.e. - path to */ + /* old file name and name of old file name */ + if ((fnp1 = split_path(path1, szPriDirName, szPriFileName, szPriFileExt)) == NULL) + { + dir_close(fnp1); + dir_close(fnp2); + return DE_PATHNOTFND; + } + + /* Reset the directory by a close followed by an open */ + fnp2->f_flags.f_dmod = FALSE; + dir_close(fnp2); + fnp2 = dir_open((BYTE FAR *) szSecDirName); + + /* Now find a free slot to put the file into. */ + /* If it's the root and we don't have room, return an error. */ + if (!(is_free = find_free(fnp2)) && (fnp2->f_flags.f_droot)) + { + fnp2->f_flags.f_dmod = FALSE; + dir_close(fnp1); + dir_close(fnp2); + return DE_TOOMANY; + } + + /* Otherwise just expand the directory */ + else if (!is_free && !(fnp2->f_flags.f_droot)) + { + COUNT ret; + + if ((ret = extend_dir(fnp2)) != SUCCESS) + return ret; + } + + if (!find_fname(fnp1, szPriFileName, szPriFileExt)) + { + /* No such file, return the error */ + dir_close(fnp1); + dir_close(fnp2); + return DE_FILENOTFND; + } + + /* put the fnode's name into the directory. */ + fbcopy((BYTE FAR *) szSecFileName, + (BYTE FAR *) fnp2->f_dir.dir_name, FNAME_SIZE); + fbcopy((BYTE FAR *) szSecFileExt, + (BYTE FAR *) fnp2->f_dir.dir_ext, FEXT_SIZE); + + /* Set the fnode to the desired mode */ + fnp2->f_dir.dir_size = fnp1->f_dir.dir_size; + fnp2->f_dir.dir_start = fnp1->f_dir.dir_start; + fnp2->f_dir.dir_attrib = fnp1->f_dir.dir_attrib; + fnp2->f_dir.dir_time = fnp1->f_dir.dir_time; + fnp2->f_dir.dir_date = fnp1->f_dir.dir_date; + + /* The directory has been modified, so set the bit before */ + /* closing it, allowing it to be updated. */ + fnp1->f_flags.f_dmod = fnp2->f_flags.f_dmod = TRUE; + fnp1->f_flags.f_dnew = fnp2->f_flags.f_dnew = FALSE; + fnp1->f_flags.f_ddir = fnp2->f_flags.f_ddir = TRUE; + + fnp2->f_highwater = fnp2->f_offset = fnp1->f_dir.dir_size; + + /* Ok, so we can delete this one. Save the file info. */ + fnp1->f_dir.dir_size = 0l; + *(fnp1->f_dir.dir_name) = DELETED; + + dir_close(fnp1); + dir_close(fnp2); + + /* SUCCESSful completion, return it */ + return SUCCESS; +} + +/* */ +/* wipe out all FAT entries for create, delete, etc. */ +/* */ +static VOID wipe_out(struct f_node FAR * fnp) +{ + REG UWORD st, + next; + struct dpb *dpbp = fnp->f_dpb; + + /* if already free or not valid file, just exit */ + if ((fnp == NULL) || (fnp->f_dir.dir_start == FREE)) + return; + + /* if there are no FAT entries, just exit */ + if (fnp->f_dir.dir_start == FREE) + return; + + /* Loop from start until either a FREE entry is */ + /* encountered (due to a fractured file system) of the */ + /* last cluster is encountered. */ + for (st = fnp->f_dir.dir_start; + st != LONG_LAST_CLUSTER;) + { + /* get the next cluster pointed to */ + next = next_cluster(dpbp, st); + + /* just exit if a damaged file system exists */ + if (next == FREE) + return; + + /* zap the FAT pointed to */ + link_fat(dpbp, st, FREE); + + /* and the start of free space pointer */ + if ((dpbp->dpb_cluster == UNKNCLUSTER) + || (dpbp->dpb_cluster > st)) + dpbp->dpb_cluster = st; + + /* and just follow the linked list */ + st = next; + } +} + +static BOOL find_free(struct f_node FAR * fnp) +{ + while (dir_read(fnp) == DIRENT_SIZE) + { + if (fnp->f_dir.dir_name[0] == '\0' + || fnp->f_dir.dir_name[0] == DELETED) + { + return TRUE; + } + } + return !fnp->f_flags.f_dfull; +} + +/* */ +/* dos_getdate for the file date */ +/* */ +date dos_getdate() +{ +#ifndef NOTIME + BYTE WeekDay, + Month, + MonthDay; + COUNT Year; + date Date; + + /* First - get the system date set by either the user */ + /* on start-up or the CMOS clock */ + DosGetDate((BYTE FAR *) & WeekDay, + (BYTE FAR *) & Month, + (BYTE FAR *) & MonthDay, + (COUNT FAR *) & Year); + Date = DT_ENCODE(Month, MonthDay, Year - EPOCH_YEAR); + return Date; + +#else + + return 0; + +#endif +} + +date FAR init_call_dos_getdate() +{ + return dos_getdate(); +} + +/* */ +/* dos_gettime for the file time */ +/* */ +time dos_gettime() +{ +#ifndef NOTIME + BYTE Hour, + Minute, + Second, + Hundredth; + time Time; + BYTE h; + + /* First - get the system time set by either the user */ + /* on start-up or the CMOS clock */ + DosGetTime((BYTE FAR *) & Hour, + (BYTE FAR *) & Minute, + (BYTE FAR *) & Second, + (BYTE FAR *) & Hundredth); + h = Second * 10 + ((Hundredth + 5) / 10); + Time = TM_ENCODE(Hour, Minute, h); + return Time; +#else + return 0; +#endif +} + +time FAR init_call_dos_gettime() +{ + return dos_gettime(); +} + +/* */ +/* dos_getftime for the file time */ +/* */ +COUNT dos_getftime(COUNT fd, date FAR * dp, time FAR * tp) +{ + struct f_node FAR *fnp; + + /* Translate the fd into an fnode pointer, since all internal */ + /* operations are achieved through fnodes. */ + fnp = xlt_fd(fd); + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit */ + /* note: an invalid fd is indicated by a 0 return */ + if (fnp == (struct f_node FAR *)0 || fnp->f_count <= 0) + return DE_INVLDHNDL; + + /* Get the date and time from the fnode and return */ + *dp = fnp->f_dir.dir_date; + *tp = fnp->f_dir.dir_time; + + return SUCCESS; +} + +/* */ +/* dos_setftime for the file time */ +/* */ +COUNT dos_setftime(COUNT fd, date FAR * dp, time FAR * tp) +{ + struct f_node FAR *fnp; + + /* Translate the fd into an fnode pointer, since all internal */ + /* operations are achieved through fnodes. */ + fnp = xlt_fd(fd); + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit */ + /* note: an invalid fd is indicated by a 0 return */ + if (fnp == (struct f_node FAR *)0 || fnp->f_count <= 0) + return DE_INVLDHNDL; + + /* Set the date and time from the fnode and return */ + fnp->f_dir.dir_date = *dp; + fnp->f_dir.dir_time = *tp; + + return SUCCESS; +} + +/* */ +/* dos_getfsize for the file time */ +/* */ +LONG dos_getcufsize(COUNT fd) +{ + struct f_node FAR *fnp; + + /* Translate the fd into an fnode pointer, since all internal */ + /* operations are achieved through fnodes. */ + fnp = xlt_fd(fd); + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit */ + /* note: an invalid fd is indicated by a 0 return */ + if (fnp == (struct f_node FAR *)0 || fnp->f_count <= 0) + return -1l; + + /* Return the file size */ + return fnp->f_highwater; +} + +/* */ +/* dos_getfsize for the file time */ +/* */ +LONG dos_getfsize(COUNT fd) +{ + struct f_node FAR *fnp; + + /* Translate the fd into an fnode pointer, since all internal */ + /* operations are achieved through fnodes. */ + fnp = xlt_fd(fd); + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit */ + /* note: an invalid fd is indicated by a 0 return */ + if (fnp == (struct f_node FAR *)0 || fnp->f_count <= 0) + return -1l; + + /* Return the file size */ + return fnp->f_dir.dir_size; +} + +/* */ +/* dos_setfsize for the file time */ +/* */ +BOOL dos_setfsize(COUNT fd, LONG size) +{ + struct f_node FAR *fnp; + + /* Translate the fd into an fnode pointer, since all internal */ + /* operations are achieved through fnodes. */ + fnp = xlt_fd(fd); + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit */ + /* note: an invalid fd is indicated by a 0 return */ + if (fnp == (struct f_node FAR *)0 || fnp->f_count <= 0) + return FALSE; + + /* Change the file size */ + fnp->f_dir.dir_size = size; + fnp->f_highwater = size; + return TRUE; +} + +/* */ +/* Find free cluster in disk FAT table */ +/* */ +static UWORD find_fat_free(struct f_node FAR * fnp) +{ + REG UWORD idx; + +#ifdef DISPLAY_GETBLOCK + printf("[find_fat_free]\n"); +#endif + /* Start from optimized lookup point for start of FAT */ + if (fnp->f_dpb->dpb_cluster != UNKNCLUSTER) + idx = fnp->f_dpb->dpb_cluster; + else + idx = 2; + + /* Search the FAT table looking for the first free */ + /* entry. */ + for (; idx < fnp->f_dpb->dpb_size; idx++) + { + if (next_cluster(fnp->f_dpb, idx) == FREE) + break; + } + + /* No empty clusters, disk is FULL! */ + if (idx >= fnp->f_dpb->dpb_size) + { + fnp->f_dpb->dpb_cluster = UNKNCLUSTER; + dir_close(fnp); + return LONG_LAST_CLUSTER; + } + + /* return the free entry */ + fnp->f_dpb->dpb_cluster = idx; + return idx; +} + +/* */ +/* crate a directory - returns success or a negative error */ +/* number */ +/* */ +COUNT dos_mkdir(BYTE FAR * dir) +{ + REG struct f_node FAR *fnp; + REG COUNT idx; + struct buffer FAR *bp; + BYTE FAR *p; + UWORD free_fat; + UWORD parent; + + /* first split the passed dir into comopnents (i.e. - */ + /* path to new directory and name of new directory */ + if ((fnp = split_path(dir, szDirName, szFileName, szFileExt)) == NULL) + { + dir_close(fnp); + return DE_PATHNOTFND; + } + + /* Check that we don't have a duplicate name, so if we */ + /* find one, it's an error. */ + if (find_fname(fnp, szFileName, szFileExt)) + { + dir_close(fnp); + return DE_ACCESS; + } + else + { + BOOL is_free; + + /* Reset the directory by a close followed by */ + /* an open */ + fnp->f_flags.f_dmod = FALSE; + parent = fnp->f_dirstart; + dir_close(fnp); + fnp = dir_open((BYTE FAR *) szDirName); + + /* Get a free f_node pointer so that we can use */ + /* it in building the new file. */ + /* Note that if we're in the root and we don't */ + /* find an empty slot, we need to abort. */ + if (!(is_free = find_free(fnp)) && (fnp->f_flags.f_droot)) + { + fnp->f_flags.f_dmod = FALSE; + dir_close(fnp); + return DE_TOOMANY; + } + + /* Otherwise just expand the directory */ + else if (!is_free && !(fnp->f_flags.f_droot)) + { + COUNT ret; + + if ((ret = extend_dir(fnp)) != SUCCESS) + return ret; + } + + /* put the fnode's name into the directory. */ + fbcopy((BYTE FAR *) szFileName, + (BYTE FAR *) fnp->f_dir.dir_name, FNAME_SIZE); + fbcopy((BYTE FAR *) szFileExt, + (BYTE FAR *) fnp->f_dir.dir_ext, FEXT_SIZE); + + /* Set the fnode to the desired mode */ + fnp->f_mode = WRONLY; + fnp->f_back = LONG_LAST_CLUSTER; + + fnp->f_dir.dir_size = 0l; + fnp->f_dir.dir_start = FREE; + fnp->f_dir.dir_attrib = D_DIR; + fnp->f_dir.dir_time = dos_gettime(); + fnp->f_dir.dir_date = dos_getdate(); + + fnp->f_flags.f_dmod = TRUE; + fnp->f_flags.f_dnew = FALSE; + fnp->f_flags.f_ddir = TRUE; + + fnp->f_highwater = 0l; + fnp->f_offset = 0l; + } + + /* get an empty cluster, so that we make it into a */ + /* directory. */ + free_fat = find_fat_free(fnp); + + /* No empty clusters, disk is FULL! Translate into a */ + /* useful error message. */ + if (free_fat == LONG_LAST_CLUSTER) + { + dir_close(fnp); + return DE_HNDLDSKFULL; + } + + /* Mark the cluster in the FAT as used */ + fnp->f_dir.dir_start = fnp->f_cluster = free_fat; + link_fat(fnp->f_dpb, (UCOUNT) free_fat, LONG_LAST_CLUSTER); + + /* Craft the new directory. Note that if we're in a new */ + /* directory just under the root, ".." pointer is 0. */ + bp = getblock((ULONG) clus2phys(free_fat, + (fnp->f_dpb->dpb_clsmask + 1), + fnp->f_dpb->dpb_data), + fnp->f_dpb->dpb_unit); +#ifdef DISPLAY_GETBLOCK + printf("FAT (dos_mkdir)\n"); +#endif + if (bp == NULL) + { + dir_close(fnp); + return DE_BLKINVLD; + } + + /* Create the "." entry */ + bcopy(". ", (BYTE *) DirEntBuffer.dir_name, FNAME_SIZE); + bcopy(" ", (BYTE *) DirEntBuffer.dir_ext, FEXT_SIZE); + DirEntBuffer.dir_attrib = D_DIR; + DirEntBuffer.dir_time = dos_gettime(); + DirEntBuffer.dir_date = dos_getdate(); + DirEntBuffer.dir_start = free_fat; + DirEntBuffer.dir_size = 0l; + + /* And put it out */ + putdirent((struct dirent FAR *)&DirEntBuffer, (BYTE FAR *) bp->b_buffer); + + /* create the ".." entry */ + bcopy(".. ", (BYTE *) DirEntBuffer.dir_name, FNAME_SIZE); + DirEntBuffer.dir_start = parent; + + /* and put it out */ + putdirent((struct dirent FAR *)&DirEntBuffer, (BYTE FAR *) & bp->b_buffer[DIRENT_SIZE]); + + /* fill the rest of the block with zeros */ + for (p = (BYTE FAR *) & bp->b_buffer[2 * DIRENT_SIZE]; + p < &bp->b_buffer[BUFFERSIZE];) + *p++ = NULL; + + /* Mark the block to be written out */ + bp->b_flag |= BFR_DIRTY; + + /* clear out the rest of the blocks in the cluster */ + for (idx = 1; idx < (fnp->f_dpb->dpb_clsmask + 1); idx++) + { + REG COUNT i; + + bp = getblock((ULONG) clus2phys(fnp->f_dir.dir_start, + (fnp->f_dpb->dpb_clsmask + 1), + fnp->f_dpb->dpb_data) + idx, + fnp->f_dpb->dpb_unit); +#ifdef DISPLAY_GETBLOCK + printf("DIR (dos_mkdir)\n"); +#endif + if (bp == NULL) + { + dir_close(fnp); + return DE_BLKINVLD; + } + for (i = 0, p = (BYTE FAR *) bp->b_buffer; i < BUFFERSIZE; i++) + *p++ = NULL; + bp->b_flag |= BFR_DIRTY; + } + + /* flush the drive buffers so that all info is written */ + flush_buffers((COUNT) (fnp->f_dpb->dpb_unit)); + + /* Close the directory so that the entry is updated */ + fnp->f_flags.f_dmod = TRUE; + dir_close(fnp); + + return SUCCESS; +} + +BOOL last_link(struct f_node FAR * fnp) +{ + return (((UWORD) fnp->f_cluster == (UWORD) LONG_LAST_CLUSTER)); +} + +static BOOL extend(struct f_node FAR * fnp) +{ + UWORD free_fat; + +#ifdef DISPLAY_GETBLOCK + printf("extend\n"); +#endif + /* get an empty cluster, so that we use it to extend the file. */ + free_fat = find_fat_free(fnp); + + /* No empty clusters, disk is FULL! Translate into a useful */ + /* error message. */ + if (free_fat == LONG_LAST_CLUSTER) + return FALSE; + + /* Now that we've found a free FAT entry, mark it as the last */ + /* entry and save. */ + link_fat(fnp->f_dpb, (UCOUNT) fnp->f_back, free_fat); + fnp->f_cluster = free_fat; + link_fat(fnp->f_dpb, (UCOUNT) free_fat, LONG_LAST_CLUSTER); + + /* Mark the directory so that the entry is updated */ + fnp->f_flags.f_dmod = TRUE; + return TRUE; +} + +static COUNT extend_dir(struct f_node FAR * fnp) +{ + REG COUNT idx; + + if (!extend(fnp)) + { + dir_close(fnp); + return DE_HNDLDSKFULL; + } + + /* clear out the rest of the blocks in the cluster */ + for (idx = 0; idx < (fnp->f_dpb->dpb_clsmask + 1); idx++) + { + REG COUNT i; + REG BYTE FAR *p; + REG struct buffer FAR *bp; + + bp = getblock((ULONG) clus2phys(fnp->f_cluster, + (fnp->f_dpb->dpb_clsmask + 1), + fnp->f_dpb->dpb_data) + idx, + fnp->f_dpb->dpb_unit); +#ifdef DISPLAY_GETBLOCK + printf("DIR (extend_dir)\n"); +#endif + if (bp == NULL) + { + dir_close(fnp); + return DE_BLKINVLD; + } + for (i = 0, p = (BYTE FAR *) bp->b_buffer; i < BUFFERSIZE; i++) + *p++ = NULL; + bp->b_flag |= BFR_DIRTY; + } + + if (!find_free(fnp)) + { + dir_close(fnp); + return DE_HNDLDSKFULL; + } + + /* flush the drive buffers so that all info is written */ + flush_buffers((COUNT) (fnp->f_dpb->dpb_unit)); + + return SUCCESS; + +} + +/* JPP: finds the next free cluster in the FAT */ +static BOOL first_fat(struct f_node FAR * fnp) +{ + UWORD free_fat; + + /* get an empty cluster, so that we make it into a file. */ + free_fat = find_fat_free(fnp); + + /* No empty clusters, disk is FULL! Translate into a useful */ + /* error message. */ + if (free_fat == LONG_LAST_CLUSTER) + return FALSE; + + /* Now that we've found a free FAT entry, mark it as the last */ + /* entry and save it. */ + fnp->f_dir.dir_start = free_fat; + link_fat(fnp->f_dpb, (UCOUNT) free_fat, LONG_LAST_CLUSTER); + + /* Mark the directory so that the entry is updated */ + fnp->f_flags.f_dmod = TRUE; + return TRUE; +} + +/* JPP: I think this starts at the beginning of a file, and follows + the fat chain to find the cluster that contains the data for the + file at f_offset. */ + +/* JPP: new map_cluster. If we are moving forward, then use the offset + that we are at now (f_cluster_offset) to start, instead of starting + at the beginning. */ +COUNT map_cluster(REG struct f_node FAR * fnp, COUNT mode) +{ + ULONG idx; + UWORD clssize; + UWORD secsize; + +#ifdef DISPLAY_GETBLOCK + printf("map_cluster: current %lu, offset %lu, diff=%lu ", + fnp->f_cluster_offset, fnp->f_offset, + fnp->f_offset - fnp->f_cluster_offset); +#endif + /* The variable clssize will be used later. */ + secsize = fnp->f_dpb->dpb_secsize; + clssize = secsize * (fnp->f_dpb->dpb_clsmask + 1); + + /* If someone did a seek, but no writes have occured, we will */ + /* need to initialize the fnode. */ + if ((mode == XFR_WRITE) && (fnp->f_dir.dir_start == FREE)) + { + /* If there are no more free fat entries, then we are full! */ + if (!first_fat(fnp)) + return DE_HNDLDSKFULL; + } + + if (fnp->f_offset >= fnp->f_cluster_offset) /*JPP */ + { + /* Set internal index and cluster size. */ + idx = fnp->f_offset - fnp->f_cluster_offset; + } + else + { + /* Set internal index and cluster size. */ + idx = fnp->f_offset; + + fnp->f_cluster = fnp->f_flags.f_ddir ? fnp->f_dirstart : + fnp->f_dir.dir_start; + fnp->f_cluster_offset = 0; + } + + /* Now begin the linear search. The relative cluster is */ + /* maintained as part of the set of physical indices. It is */ + /* also the highest order index and is mapped directly into */ + /* physical cluster. Our search is performed by pacing an index */ + /* up to the relative cluster position where the index falls */ + /* within the cluster. */ + /* */ + /* NOTE: make sure your compiler does not optimize for loop */ + /* tests to the loop exit. We need to fall out immediately for */ + /* files whose length < cluster size. */ + for (; idx >= clssize; idx -= clssize) + { + /* If this is a read and the next is a LAST_CLUSTER, */ + /* then we are going to read past EOF, return zero read */ + if ((mode == XFR_READ) && last_link(fnp)) + return DE_SEEK; +/* expand the list if we're going to write and have run into */ +/* the last cluster marker. */ + else if ((mode == XFR_WRITE) && last_link(fnp)) + { + + if (!extend(fnp)) + { + dir_close(fnp); + return DE_HNDLDSKFULL; + } + } + fnp->f_back = fnp->f_cluster; + + /* get next cluster in the chain */ + fnp->f_cluster = next_cluster(fnp->f_dpb, fnp->f_cluster); + fnp->f_cluster_offset += clssize; + } +#ifdef DISPLAY_GETBLOCK + printf("done.\n"); +#endif + + return SUCCESS; +} + +/* Read block from disk */ +UCOUNT readblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err) +{ + REG struct f_node FAR *fnp; + REG struct buffer FAR *bp; + UCOUNT xfr_cnt = 0; + UCOUNT ret_cnt = 0; + ULONG idx; + UWORD secsize; + UCOUNT to_xfer = count; + +#ifdef DEBUG + if (bDumpRdWrParms) + { + printf("readblock:\n"); + printf(" fd buffer count\n -- ------ -----\n"); + printf(" %02d %04x:%04x %d\n", + fd, (COUNT) FP_SEG(buffer), (COUNT) FP_OFF(buffer), count); + } +#endif + /* Translate the fd into an fnode pointer, since all internal */ + /* operations are achieved through fnodes. */ + fnp = xlt_fd(fd); + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit */ + /* note: an invalid fd is indicated by a 0 return */ + if (fnp == (struct f_node FAR *)0 || fnp->f_count <= 0) + { + *err = DE_INVLDHNDL; + return 0; + } + + /* Test that we are really about to do a data transfer. If the + count is zero, just exit. (Any read with a count of zero is a nop). */ + + /* NOTE: doing this up front saves a lot of headaches later. */ + if (count == 0) + { + *err = SUCCESS; + return 0; + } + + /* Another test is to check for a seek past EOF */ + if (!fnp->f_flags.f_ddir && (fnp->f_offset >= fnp->f_dir.dir_size)) + { + *err = SUCCESS; + return 0; + } + + /* test that we have a valid mode for this fnode */ + if (fnp->f_mode != RDONLY && fnp->f_mode != RDWR) + { + *err = DE_INVLDACC; + return 0; + } + + /* The variable secsize will be used later. */ + secsize = fnp->f_dpb->dpb_secsize; + + /* Adjust the far pointer from user space to supervisor space */ + buffer = adjust_far((VOID FAR *) buffer); + + /* Do the data transfer. Use block transfer methods so that we */ + /* can utilize memory management in future DOS-C versions. */ + while (ret_cnt < count) + { + /* Position the file to the fnode's pointer position. This is */ + /* done by updating the fnode's cluster, block (sector) and */ + /* byte offset so that read becomes a simple data move */ + /* out of the block data buffer. */ + if (fnp->f_offset == 0l) + { + /* complete the common operations of */ + /* initializing to the starting cluster and */ + /* setting all offsets to zero. */ + fnp->f_cluster = fnp->f_flags.f_ddir ? fnp->f_dirstart : + fnp->f_dir.dir_start; + + fnp->f_cluster_offset = 0l; + fnp->f_back = LONG_LAST_CLUSTER; + fnp->f_sector = 0; + fnp->f_boff = 0; + } + /* The more difficult scenario is the (more common) */ + /* file offset case. Here, we need to take the fnode's */ + /* offset pointer (f_offset) and translate it into a */ + /* relative cluster position, cluster block (sector) */ + /* offset (f_sector) and byte offset (f_boff). Once we */ + /* have this information, we need to translate the */ + /* relative cluster position into an absolute cluster */ + /* position (f_cluster). This is unfortunate because it */ + /* requires a linear search through the file's FAT */ + /* entries. It made sense when DOS was originally */ + /* designed as a simple floppy disk operating system */ + /* where the FAT was contained in core, but now */ + /* requires a search through the FAT blocks. */ + /* */ + /* The algorithm in this function takes advantage of */ + /* the blockio block buffering scheme to simplify the */ + /* task. */ + else + { +#ifdef DISPLAY_GETBLOCK + printf("readblock: "); +#endif + switch (map_cluster(fnp, XFR_READ)) + { + case DE_SEEK: + *err = DE_SEEK; + dir_close(fnp); + return ret_cnt; + + default: + dir_close(fnp); + *err = DE_HNDLDSKFULL; + return ret_cnt; + + case SUCCESS: + break; + } + } + + /* Compute the block within the cluster and the offset */ + /* within the block. */ + fnp->f_sector = (fnp->f_offset / secsize) & fnp->f_dpb->dpb_clsmask; + fnp->f_boff = fnp->f_offset & (secsize - 1); + +#ifdef DSK_DEBUG + printf("read %d links; dir offset %ld, cluster %d\n", + fnp->f_count, + fnp->f_diroff, + fnp->f_cluster); +#endif + /* Do an EOF test and return whatever was transferred */ + /* but only for regular files. */ + if (!(fnp->f_flags.f_ddir) + && (fnp->f_offset >= fnp->f_dir.dir_size)) + { + *err = SUCCESS; + return ret_cnt; + } + + /* Get the block we need from cache */ + bp = getblock((ULONG) clus2phys(fnp->f_cluster, + (fnp->f_dpb->dpb_clsmask + 1), + fnp->f_dpb->dpb_data) + fnp->f_sector, + fnp->f_dpb->dpb_unit); + +#ifdef DISPLAY_GETBLOCK + printf("DATA (readblock)\n"); +#endif + if (bp == (struct buffer *)0) + { + *err = DE_BLKINVLD; + return ret_cnt; + } + + /* transfer a block */ + /* Transfer size as either a full block size, or the */ + /* requested transfer size, whichever is smaller. */ + /* Then compare to what is left, since we can transfer */ + /* a maximum of what is left. */ + if (fnp->f_flags.f_ddir) + xfr_cnt = min(to_xfer, secsize - fnp->f_boff); + else + xfr_cnt = min(min(to_xfer, secsize - fnp->f_boff), + fnp->f_dir.dir_size - fnp->f_offset); + + fbcopy((BYTE FAR *) & bp->b_buffer[fnp->f_boff], buffer, xfr_cnt); + + /* update pointers and counters */ + ret_cnt += xfr_cnt; + to_xfer -= xfr_cnt; + fnp->f_offset += xfr_cnt; + buffer = add_far((VOID FAR *) buffer, (ULONG) xfr_cnt); + } + *err = SUCCESS; + return ret_cnt; +} + +/* Write block to disk */ +UCOUNT writeblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err) +{ + REG struct f_node FAR *fnp; + struct buffer FAR *bp; + UCOUNT xfr_cnt = 0; + UCOUNT ret_cnt = 0; + ULONG idx; + UWORD secsize; + UCOUNT to_xfer = count; + +#ifdef DEBUG + if (bDumpRdWrParms) + { + printf("writeblock:\n"); + printf(" fd buffer count\n -- ------ -----\n"); + printf(" %02d %04x:%04x %d\n", + fd, (COUNT) FP_SEG(buffer), (COUNT) FP_OFF(buffer), count); + } +#endif + /* Translate the fd into an fnode pointer, since all internal */ + /* operations are achieved through fnodes. */ + fnp = xlt_fd(fd); + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit */ + /* note: an invalid fd is indicated by a 0 return */ + if (fnp == (struct f_node FAR *)0 || fnp->f_count <= 0) + { + *err = DE_INVLDHNDL; + return 0; + } + + /* Test that we are really about to do a data transfer. If the */ + /* count is zero and the mode is XFR_READ, just exit. (Any */ + /* read with a count of zero is a nop). */ + /* */ + /* A write (mode is XFR_WRITE) is a special case. It sets the */ + /* file length to the current length (truncates it). */ + /* */ + /* NOTE: doing this up front saves a lot of headaches later. */ + if (count == 0) + { + fnp->f_highwater = fnp->f_offset; + + *err = SUCCESS; + return 0; + } + + /* test that we have a valid mode for this fnode */ + if (fnp->f_mode != WRONLY && fnp->f_mode != RDWR) + { + *err = DE_INVLDACC; + return 0; + } + + /* The variable secsize will be used later. */ + secsize = fnp->f_dpb->dpb_secsize; + + /* Adjust the far pointer from user space to supervisor space */ + buffer = adjust_far((VOID FAR *) buffer); + + /* Do the data transfer. Use block transfer methods so that we */ + /* can utilize memory management in future DOS-C versions. */ + while (ret_cnt < count) + { + /* Position the file to the fnode's pointer position. This is */ + /* done by updating the fnode's cluster, block (sector) and */ + /* byte offset so that read or write becomes a simple data move */ + /* into or out of the block data buffer. */ + if (fnp->f_offset == 0l) + { + /* For the write case, a newly created file */ + /* will have a start cluster of FREE. If we're */ + /* doing a write and this is the first time */ + /* through, allocate a new cluster to the file. */ + if (fnp->f_dir.dir_start == FREE) + if (!first_fat(fnp)) /* get a free cluster */ + { /* error means disk full */ + dir_close(fnp); + *err = DE_HNDLDSKFULL; + return ret_cnt; + } + /* complete the common operations of */ + /* initializing to the starting cluster and */ + /* setting all offsets to zero. */ + fnp->f_cluster = fnp->f_flags.f_ddir ? fnp->f_dirstart : + fnp->f_dir.dir_start; + + fnp->f_cluster_offset = 0l; + fnp->f_back = LONG_LAST_CLUSTER; + fnp->f_sector = 0; + fnp->f_boff = 0; + } + + /* The more difficult scenario is the (more common) */ + /* file offset case. Here, we need to take the fnode's */ + /* offset pointer (f_offset) and translate it into a */ + /* relative cluster position, cluster block (sector) */ + /* offset (f_sector) and byte offset (f_boff). Once we */ + /* have this information, we need to translate the */ + /* relative cluster position into an absolute cluster */ + /* position (f_cluster). This is unfortunate because it */ + /* requires a linear search through the file's FAT */ + /* entries. It made sense when DOS was originally */ + /* designed as a simple floppy disk operating system */ + /* where the FAT was contained in core, but now */ + /* requires a search through the FAT blocks. */ + /* */ + /* The algorithm in this function takes advantage of */ + /* the blockio block buffering scheme to simplify the */ + /* task. */ + else + { +#ifdef DISPLAY_GETBLOCK + printf("writeblock: "); +#endif + switch (map_cluster(fnp, XFR_WRITE)) + { + case DE_SEEK: + *err = DE_SEEK; + dir_close(fnp); + return ret_cnt; + + default: + dir_close(fnp); + *err = DE_HNDLDSKFULL; + return ret_cnt; + + case SUCCESS: + break; + } + } + + /* XFR_WRITE case only - if we're at the end, the next */ + /* FAT is an EOF marker, so just extend the file length */ + if (last_link(fnp)) + if (!extend(fnp)) + { + dir_close(fnp); + *err = DE_HNDLDSKFULL; + return ret_cnt; + } + + /* Compute the block within the cluster and the offset */ + /* within the block. */ + fnp->f_sector = + (fnp->f_offset / secsize) & fnp->f_dpb->dpb_clsmask; + fnp->f_boff = fnp->f_offset & (secsize - 1); + +#ifdef DSK_DEBUG + printf("write %d links; dir offset %ld, cluster %d\n", + fnp->f_count, + fnp->f_diroff, + fnp->f_cluster); +#endif + + /* get a buffer to store the block in */ + if (!getbuf(&bp, (ULONG) clus2phys(fnp->f_cluster, + (fnp->f_dpb->dpb_clsmask + 1), + fnp->f_dpb->dpb_data) + fnp->f_sector, + fnp->f_dpb->dpb_unit)) + { + *err = DE_BLKINVLD; + return ret_cnt; + } + + /* transfer a block */ + /* Transfer size as either a full block size, or the */ + /* requested transfer size, whichever is smaller. */ + /* Then compare to what is left, since we can transfer */ + /* a maximum of what is left. */ + xfr_cnt = min(to_xfer, secsize - fnp->f_boff); + fbcopy(buffer, (BYTE FAR *) & bp->b_buffer[fnp->f_boff], xfr_cnt); + bp->b_flag |= BFR_DIRTY | BFR_VALID; + + /* update pointers and counters */ + ret_cnt += xfr_cnt; + to_xfer -= xfr_cnt; + fnp->f_offset += xfr_cnt; + buffer = add_far((VOID FAR *) buffer, (ULONG) xfr_cnt); + if (fnp->f_offset > fnp->f_highwater) + { + fnp->f_highwater = fnp->f_offset; + fnp->f_dir.dir_size = fnp->f_highwater; + } + } + *err = SUCCESS; + return ret_cnt; +} + +COUNT dos_read(COUNT fd, VOID FAR * buffer, UCOUNT count) +{ + COUNT err; + UCOUNT xfr; + + xfr = readblock(fd, buffer, count, &err); + return err != SUCCESS ? err : xfr; +} + +COUNT FAR init_call_dos_read(COUNT fd, VOID FAR * buffer, UCOUNT count) +{ + return dos_read(fd, buffer, count); +} + +#ifndef IPL +COUNT dos_write(COUNT fd, VOID FAR * buffer, UCOUNT count) +{ + REG struct f_node FAR *fnp; + COUNT err, + xfr; + + /* First test if we need to fill to new EOF. */ + + /* Translate the fd into an fnode pointer, since all internal */ + /* operations are achieved through fnodes. */ + fnp = xlt_fd(fd); + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit */ + /* note: an invalid fd is indicated by a 0 return */ + if (fnp == (struct f_node FAR *)0 || fnp->f_count <= 0) + { + return DE_INVLDHNDL; + } + + /* Future note: for security purposes, this should be set to */ + /* blocks of 0. This satisfies spec and guarantees no secure */ + /* info is written to disk. */ + /* Also, with real memory management, this may cause a page */ + /* fault. */ + if (fnp->f_offset > fnp->f_highwater) + { + ULONG lCount = fnp->f_offset - fnp->f_highwater; + + while (lCount > 0) + { + writeblock(fd, buffer, + lCount > 512l ? 512 : (UCOUNT) lCount, + &err); + lCount -= 512; + } + } + + xfr = writeblock(fd, buffer, count, &err); + return err != SUCCESS ? err : xfr; +} +#endif + +/* Position the file pointer to the desired offset */ +/* Returns a long current offset or a negative error code */ +LONG dos_lseek(COUNT fd, LONG foffset, COUNT origin) +{ + REG struct f_node FAR *fnp; + + /* Translate the fd into a useful pointer */ + + fnp = xlt_fd(fd); + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit */ + /* note: an invalid fd is indicated by a 0 return */ + + if (fnp == (struct f_node FAR *)0 || fnp->f_count <= 0) + return (LONG) DE_INVLDHNDL; + + /* now do the actual lseek adjustment to the file poitner */ + + switch (origin) + { + /* offset from beginning of file */ + case 0: + return fnp->f_offset = (ULONG) foffset; + + /* offset from current location */ + case 1: + return fnp->f_offset += foffset; + + /* offset from eof */ + case 2: + return fnp->f_offset = fnp->f_highwater + foffset; + + /* default to an invalid function */ + default: + return (LONG) DE_INVLDFUNC; + } +} + +/* returns the number of unused clusters */ +UWORD dos_free(struct dpb * dpbp) +{ + /* There's an unwritten rule here. All fs */ + /* cluster start at 2 and run to max_cluster+2 */ + REG UWORD i; + REG UWORD cnt = 0; + UWORD max_cluster = ((ULONG) dpbp->dpb_size + * (ULONG) (dpbp->dpb_clsmask + 1) - dpbp->dpb_data + 1) + / (dpbp->dpb_clsmask + 1) + 2; + + if (dpbp->dpb_nfreeclst != UNKNCLUSTER) + return dpbp->dpb_nfreeclst; + else + { + for (i = 2; i < max_cluster; i++) + { + if (next_cluster(dpbp, i) == 0) + ++cnt; + } + dpbp->dpb_nfreeclst = cnt; + return cnt; + } +} + +VOID dos_pwd(struct cds FAR * cdsp, BYTE FAR * s) +{ + WORD x = 1 + cdsp->cdsJoinOffset; + fsncopy((BYTE FAR *) & cdsp->cdsCurrentPath[x], s, 64); +} + +#ifndef IPL +COUNT dos_cd(struct cds FAR * cdsp, BYTE FAR * s) +{ + BYTE FAR *p; + struct f_node FAR *fnp; + COUNT x; + + /* Get the current directory so that we initialize all access */ + /* relative to root. */ + truename(s, PriPathName, FALSE); + + if (cdsp->cdsFlags & 0x8000) + { + if ((int2f_Remote_call(REM_CHDIR, 0, 0, 0, PriPathName, 0, 0)) != 0) + return DE_PATHNOTFND; + fscopy(&PriPathName[0], cdsp->cdsCurrentPath); + if (PriPathName[7] == 0) + cdsp->cdsCurrentPath[8] = 0; + return SUCCESS; + } + + /* now test for its existance. If it doesn't, return an error. */ + /* If it does, copy the path to the current directory */ + /* structure. */ + if ((fnp = dir_open((BYTE FAR *) PriPathName)) == NULL) + return DE_PATHNOTFND; + cdsp->cdsStrtClst = fnp->f_dirstart; + dir_close(fnp); + fscopy(&PriPathName[0], cdsp->cdsCurrentPath); + return SUCCESS; +} +#endif + +/* Try to allocate an f_node from the available files array */ + +struct f_node FAR *get_f_node(void) +{ + REG i; + + for (i = 0; i < NFILES; i++) + { + if (f_nodes[i].f_count == 0) + { + ++f_nodes[i].f_count; + return &f_nodes[i]; + } + } + return (struct f_node FAR *)0; +} + +VOID release_f_node(struct f_node FAR * fnp) +{ + if (fnp->f_count > 0) + --fnp->f_count; + else + fnp->f_count = 0; +} + +#ifndef IPL +VOID dos_setdta(BYTE FAR * newdta) +{ + dta = newdta; +} + +COUNT dos_getfattr(BYTE FAR * name, UWORD FAR * attrp) +{ + struct f_node FAR *fnp; + COUNT fd; + + /* Translate the fd into an fnode pointer, since all internal */ + /* operations are achieved through fnodes. */ + if ((fd = dos_open(name, O_RDONLY)) < SUCCESS) + return DE_FILENOTFND; + + /* note: an invalid fd is indicated by a 0 return */ + if ((fnp = xlt_fd(fd)) == (struct f_node FAR *)0) + return DE_TOOMANY; + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit */ + if (fnp->f_count <= 0) + { + dos_close(fd); + return DE_FILENOTFND; + } + + /* Get the attribute from the fnode and return */ + *attrp = fnp->f_dir.dir_attrib; + dos_close(fd); + return SUCCESS; +} + +COUNT dos_setfattr(BYTE FAR * name, UWORD FAR * attrp) +{ + struct f_node FAR *fnp; + COUNT fd; + + /* Translate the fd into an fnode pointer, since all internal */ + /* operations are achieved through fnodes. */ + if ((fd = dos_open(name, O_RDONLY)) < SUCCESS) + return DE_FILENOTFND; + + /* note: an invalid fd is indicated by a 0 return */ + if ((fnp = xlt_fd(fd)) == (struct f_node FAR *)0) + return DE_TOOMANY; + + /* If the fd was invalid because it was out of range or the */ + /* requested file was not open, tell the caller and exit */ + if (fnp->f_count <= 0) + { + dos_close(fd); + return DE_FILENOTFND; + } + /* JPP-If user tries to set VOLID or DIR bits, return error */ + if ((*attrp & (D_VOLID | D_DIR | 0xC0)) != 0) + { + dos_close(fd); + return DE_ACCESS; + } + + /* Set the attribute from the fnode and return */ + /* clear all attributes but DIR and VOLID */ + fnp->f_dir.dir_attrib &= (D_VOLID | D_DIR); /* JPP */ + + /* set attributes that user requested */ + fnp->f_dir.dir_attrib |= *attrp; /* JPP */ + fnp->f_flags.f_dmod = TRUE; + dos_close(fd); + return SUCCESS; +} +#endif + +COUNT media_check(REG struct dpb * dpbp) +{ + bpb FAR *bpbp; + ULONG size; + REG COUNT i; + /* First test if anyone has changed the removable media */ + FOREVER + { + MediaReqHdr.r_length = sizeof(request); + MediaReqHdr.r_unit = dpbp->dpb_subunit; + MediaReqHdr.r_command = C_MEDIACHK; + MediaReqHdr.r_mcmdesc = dpbp->dpb_mdb; + MediaReqHdr.r_status = 0; + execrh((request FAR *) & MediaReqHdr, dpbp->dpb_device); + if (!(MediaReqHdr.r_status & S_ERROR) && (MediaReqHdr.r_status & S_DONE)) + break; + else + { + loop1: + switch (block_error(&MediaReqHdr, dpbp->dpb_unit, dpbp->dpb_device)) + { + case ABORT: + case FAIL: + return DE_INVLDDRV; + + case RETRY: + continue; + + case CONTINUE: + break; + + default: + goto loop1; + } + } + } + + switch (MediaReqHdr.r_mcretcode | dpbp->dpb_flags) + { + case M_NOT_CHANGED: + /* It was definitely not changed, so ignore it */ + return SUCCESS; + + /* If it is forced or the media may have changed, */ + /* rebuild the bpb */ + case M_DONT_KNOW: + flush_buffers(dpbp->dpb_unit); + + /* If it definitely changed, don't know (falls through) */ + /* or has been changed, rebuild the bpb. */ + case M_CHANGED: + default: + setinvld(dpbp->dpb_unit); + FOREVER + { + MediaReqHdr.r_length = sizeof(request); + MediaReqHdr.r_unit = dpbp->dpb_subunit; + MediaReqHdr.r_command = C_BLDBPB; + MediaReqHdr.r_mcmdesc = dpbp->dpb_mdb; + MediaReqHdr.r_status = 0; + execrh((request FAR *) & MediaReqHdr, dpbp->dpb_device); + if (!(MediaReqHdr.r_status & S_ERROR) && (MediaReqHdr.r_status & S_DONE)) + break; + else + { + loop2: + switch (block_error(&MediaReqHdr, dpbp->dpb_unit, dpbp->dpb_device)) + { + case ABORT: + case FAIL: + return DE_INVLDDRV; + + case RETRY: + continue; + + case CONTINUE: + break; + + default: + goto loop2; + } + } + } + bpbp = MediaReqHdr.r_bpptr; + dpbp->dpb_mdb = bpbp->bpb_mdesc; + dpbp->dpb_secsize = bpbp->bpb_nbyte; + dpbp->dpb_clsmask = bpbp->bpb_nsector - 1; + dpbp->dpb_fatstrt = bpbp->bpb_nreserved; + dpbp->dpb_fats = bpbp->bpb_nfat; + dpbp->dpb_dirents = bpbp->bpb_ndirent; + size = bpbp->bpb_nsize == 0 ? + bpbp->bpb_huge : + (ULONG) bpbp->bpb_nsize; + dpbp->dpb_size = size / ((ULONG) bpbp->bpb_nsector); + dpbp->dpb_fatsize = bpbp->bpb_nfsect; + dpbp->dpb_dirstrt = dpbp->dpb_fatstrt + + dpbp->dpb_fats * dpbp->dpb_fatsize; + dpbp->dpb_data = dpbp->dpb_dirstrt + + ((DIRENT_SIZE * dpbp->dpb_dirents + + (dpbp->dpb_secsize - 1)) + / dpbp->dpb_secsize); + dpbp->dpb_flags = 0; + dpbp->dpb_next = (struct dpb FAR *)-1; + dpbp->dpb_cluster = UNKNCLUSTER; + dpbp->dpb_nfreeclst = UNKNCLUSTER; /* number of free clusters */ + for (i = 1, dpbp->dpb_shftcnt = 0; + i < (sizeof(dpbp->dpb_shftcnt) * 8); /* 8 bit bytes in C */ + dpbp->dpb_shftcnt++, i <<= 1) + { + if (i >= bpbp->bpb_nsector) + break; + } + return SUCCESS; + } +} + +/* translate the fd into an f_node pointer */ +struct f_node FAR *xlt_fd(COUNT fd) +{ + return fd >= NFILES ? (struct f_node FAR *)0 : &f_nodes[fd]; +} + +/* translate the f_node pointer into an fd */ +COUNT xlt_fnp(struct f_node FAR * fnp) +{ + return fnp - f_nodes; +} + +struct dhdr FAR *select_unit(COUNT drive) +{ + /* Just get the header from the dhdr array */ + return blk_devices[drive].dpb_device; +} + diff --git a/kernel/fattab.c b/kernel/fattab.c new file mode 100644 index 0000000..8869c38 --- /dev/null +++ b/kernel/fattab.c @@ -0,0 +1,378 @@ +/****************************************************************/ +/* */ +/* fattab.c */ +/* */ +/* FAT File System Table Functions */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:09 jhall1 + * Initial revision + * + * Revision 1.6 1999/08/10 18:03:42 jprice + * ror4 2011-03 patch + * + * Revision 1.5 1999/05/03 06:25:45 jprice + * Patches from ror4 and many changed of signed to unsigned variables. + * + * Revision 1.4 1999/04/16 00:53:33 jprice + * Optimized FAT handling + * + * Revision 1.3 1999/04/11 04:33:38 jprice + * ror4 patches + * + * Revision 1.1.1.1 1999/03/29 15:42:09 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/09 02:54:23 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.3 1999/02/01 01:43:28 jprice + * Fixed findfirst function to find volume label with Windows long filenames + * + * Revision 1.2 1999/01/22 04:15:28 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * + * Rev 1.7 09 Feb 1998 5:41:08 patv + * Eliminated FAT12 EOF and error returns. + * + * Rev 1.6 04 Jan 1998 23:14:38 patv + * Changed Log for strip utility + * + * Rev 1.5 16 Jan 1997 12:46:22 patv + * pre-Release 0.92 feature additions + * + * Rev 1.4 29 May 1996 21:15:14 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:20:08 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:48:42 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:50:26 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:04:56 patv + * Initial revision. + */ + +#ifdef PROTO +UCOUNT link_fat12(struct dpb *, UCOUNT, UCOUNT); +UCOUNT link_fat16(struct dpb *, UCOUNT, UCOUNT); +UWORD next_cl12(struct dpb *, UCOUNT); +UWORD next_cl16(struct dpb *, UCOUNT); +#else +UCOUNT link_fat12(); +UCOUNT link_fat16(); +UWORD next_cl12(); +UWORD next_cl16(); +#endif + +/************************************************************************/ +/* */ +/* cluster/sector routines */ +/* */ +/************************************************************************/ + +/* */ +/* The FAT file system is difficult to trace through FAT table. */ +/* There are two kinds of FAT's, 12 bit and 16 bit. The 16 bit */ +/* FAT is the easiest, since it is noting more than a series of */ +/* UWORD's. The 12 bit FAT is difficult, because it packs 3 FAT */ +/* entries into two BYTE's. The are packed as follows: */ +/* */ +/* 0x0003 0x0004 0x0005 0x0006 0x0007 0x0008 0x0009 ... */ +/* */ +/* are packed as */ +/* */ +/* 0x03 0x40 0x00 0x05 0x60 0x00 0x07 0x80 0x00 0x09 ... */ +/* */ +/* 12 bytes are compressed to 9 bytes */ +/* */ + +UCOUNT link_fat(struct dpb *dpbp, UCOUNT Cluster1, REG UCOUNT Cluster2) +{ + if (ISFAT12(dpbp)) + return link_fat12(dpbp, Cluster1, Cluster2); + else if (ISFAT16(dpbp)) + return link_fat16(dpbp, Cluster1, Cluster2); + else + return DE_BLKINVLD; +} + +UCOUNT link_fat16(struct dpb * dpbp, UCOUNT Cluster1, UCOUNT Cluster2) +{ + UCOUNT idx; + struct buffer FAR *bp; + UWORD Cl2 = Cluster2; + + /* Get the block that this cluster is in */ + bp = getblock((ULONG) (((ULONG) Cluster1) * SIZEOF_CLST16) / dpbp->dpb_secsize + dpbp->dpb_fatstrt, + dpbp->dpb_unit); +#ifdef DISPLAY_GETBLOCK + printf("FAT (link_fat16)\n"); +#endif + if (bp == NULL) + return DE_BLKINVLD; + bp->b_flag &= ~(BFR_DATA | BFR_DIR); + bp->b_flag |= BFR_FAT; + bp->b_copies = dpbp->dpb_fats; + bp->b_offset_lo = dpbp->dpb_fatsize; + bp->b_offset_hi = dpbp->dpb_fatsize >> 8; + + /* form an index so that we can read the block as a */ + /* byte array */ + idx = (((LONG) Cluster1) * SIZEOF_CLST16) % dpbp->dpb_secsize; + + /* Finally, put the word into the buffer and mark the */ + /* buffer as dirty. */ + fputword((WORD FAR *) & Cl2, (VOID FAR *) & (bp->b_buffer[idx])); + bp->b_flag |= BFR_DIRTY; + + /* Return successful. */ + /* update the free space count */ + if (Cluster2 == FREE) + { + /* update the free space count for returned */ + /* cluster */ + if (dpbp->dpb_nfreeclst != UNKNCLUSTER) + ++dpbp->dpb_nfreeclst; + } + else + { + /* update the free space count for removed */ + /* cluster */ + if (dpbp->dpb_nfreeclst != UNKNCLUSTER) + --dpbp->dpb_nfreeclst; + } + + return SUCCESS; +} + +UCOUNT link_fat12(struct dpb * dpbp, UCOUNT Cluster1, UCOUNT Cluster2) +{ + REG UBYTE FAR *fbp0, + FAR * fbp1; + UCOUNT idx; + struct buffer FAR *bp, + FAR * bp1; + + /* Get the block that this cluster is in */ + bp = getblock((ULONG) ((((Cluster1 << 1) + Cluster1) >> 1) / dpbp->dpb_secsize + dpbp->dpb_fatstrt), + dpbp->dpb_unit); +#ifdef DISPLAY_GETBLOCK + printf("FAT (link_fat12)\n"); +#endif + if (bp == NULL) + return DE_BLKINVLD; + bp->b_flag &= ~(BFR_DATA | BFR_DIR); + bp->b_flag |= BFR_FAT; + bp->b_copies = dpbp->dpb_fats; + bp->b_offset_lo = dpbp->dpb_fatsize; + bp->b_offset_hi = dpbp->dpb_fatsize >> 8; + + /* form an index so that we can read the block as a */ + /* byte array */ + idx = (((Cluster1 << 1) + Cluster1) >> 1) % dpbp->dpb_secsize; + + /* Test to see if the cluster straddles the block. If */ + /* it does, get the next block and use both to form the */ + /* the FAT word. Otherwise, just point to the next */ + /* block. */ + if (idx >= dpbp->dpb_secsize - 1) + { + bp1 = getblock((ULONG) (dpbp->dpb_fatstrt + + ((((Cluster1 << 1) + Cluster1) >> 1) / dpbp->dpb_secsize)) + + 1, + dpbp->dpb_unit); +#ifdef DISPLAY_GETBLOCK + printf("FAT (link_fat12)\n"); +#endif + if (bp1 == (struct buffer *)0) + return DE_BLKINVLD; + bp1->b_flag &= ~(BFR_DATA | BFR_DIR); + bp1->b_flag |= BFR_FAT | BFR_DIRTY; + bp1->b_copies = dpbp->dpb_fats; + bp1->b_offset_lo = dpbp->dpb_fatsize; + bp1->b_offset_hi = dpbp->dpb_fatsize >> 8; + fbp1 = (UBYTE FAR *) & (bp1->b_buffer[0]); + } + else + fbp1 = (UBYTE FAR *) & (bp->b_buffer[idx + 1]); + fbp0 = (UBYTE FAR *) & (bp->b_buffer[idx]); + bp->b_flag |= BFR_DIRTY; + + /* Now pack the value in */ + if (Cluster1 & 0x01) + { + *fbp0 = (*fbp0 & 0x0f) | ((Cluster2 & 0x0f) << 4); + *fbp1 = (Cluster2 >> 4) & 0xff; + } + else + { + *fbp0 = Cluster2 & 0xff; + *fbp1 = (*fbp1 & 0xf0) | (Cluster2 >> 8) & 0x0f; + } + + /* update the free space count */ + if (Cluster2 == FREE) + { + /* update the free space count for returned */ + /* cluster */ + if (dpbp->dpb_nfreeclst != UNKNCLUSTER) + ++dpbp->dpb_nfreeclst; + } + else + { + /* update the free space count for removed */ + /* cluster */ + if (dpbp->dpb_nfreeclst != UNKNCLUSTER) + --dpbp->dpb_nfreeclst; + } + + return SUCCESS; +} + +/* Given the disk parameters, and a cluster number, this function + looks at the FAT, and returns the next cluster in the clain. */ +UWORD next_cluster(struct dpb * dpbp, REG UCOUNT ClusterNum) +{ + if (ISFAT12(dpbp)) + return next_cl12(dpbp, ClusterNum); + else if (ISFAT16(dpbp)) + return next_cl16(dpbp, ClusterNum); + else + return LONG_LAST_CLUSTER; +} + +UWORD next_cl16(struct dpb * dpbp, REG UCOUNT ClusterNum) +{ + UCOUNT idx; + struct buffer FAR *bp; + UWORD RetCluster; + + /* Get the block that this cluster is in */ + bp = getblock((ULONG) (((ULONG) ClusterNum) * SIZEOF_CLST16) / dpbp->dpb_secsize + dpbp->dpb_fatstrt, + dpbp->dpb_unit); +#ifdef DISPLAY_GETBLOCK + printf("FAT (next_cl16)\n"); +#endif + if (bp == NULL) + return DE_BLKINVLD; + bp->b_flag &= ~(BFR_DATA | BFR_DIR); + bp->b_flag |= BFR_FAT; + bp->b_copies = dpbp->dpb_fats; + bp->b_offset_lo = dpbp->dpb_fatsize; + bp->b_offset_hi = dpbp->dpb_fatsize >> 8; + + /* form an index so that we can read the block as a */ + /* byte array */ + idx = (((LONG) ClusterNum) * SIZEOF_CLST16) % dpbp->dpb_secsize; + + /* Get the cluster number, */ + fgetword((VOID FAR *) & (bp->b_buffer[idx]), (WORD FAR *) & RetCluster); + + /* and return successful. */ + return RetCluster; +} + +UWORD next_cl12(struct dpb * dpbp, REG UCOUNT ClusterNum) +{ + REG UBYTE FAR *fbp0, + FAR * fbp1; + UCOUNT idx; + struct buffer FAR *bp, + FAR * bp1; + + /* Get the block that this cluster is in */ + bp = getblock((ULONG) ((((ClusterNum << 1) + ClusterNum) >> 1) / dpbp->dpb_secsize + dpbp->dpb_fatstrt), + dpbp->dpb_unit); +#ifdef DISPLAY_GETBLOCK + printf("FAT (next_cl12)\n"); +#endif + if (bp == NULL) + return LONG_BAD; + bp->b_flag &= ~(BFR_DATA | BFR_DIR); + bp->b_flag |= BFR_FAT; + bp->b_copies = dpbp->dpb_fats; + bp->b_offset_lo = dpbp->dpb_fatsize; + bp->b_offset_hi = dpbp->dpb_fatsize >> 8; + + /* form an index so that we can read the block as a */ + /* byte array */ + idx = (((ClusterNum << 1) + ClusterNum) >> 1) % dpbp->dpb_secsize; + + /* Test to see if the cluster straddles the block. If it */ + /* does, get the next block and use both to form the */ + /* the FAT word. Otherwise, just point to the next */ + /* block. */ + if (idx >= dpbp->dpb_secsize - 1) + { + bp1 = getblock((ULONG) (dpbp->dpb_fatstrt + + ((((ClusterNum << 1) + ClusterNum) >> 1) / dpbp->dpb_secsize)) + + 1, + dpbp->dpb_unit); +#ifdef DISPLAY_GETBLOCK + printf("FAT (next_cl12)\n"); +#endif + if (bp1 == (struct buffer *)0) + return LONG_BAD; + bp1->b_flag &= ~(BFR_DATA | BFR_DIR); + bp1->b_flag |= BFR_FAT; + bp1->b_copies = dpbp->dpb_fats; + bp1->b_offset_lo = dpbp->dpb_fatsize; + bp1->b_offset_hi = dpbp->dpb_fatsize >> 8; + fbp1 = (UBYTE FAR *) & (bp1->b_buffer[0]); + } + else + fbp1 = (UBYTE FAR *) & (bp->b_buffer[idx + 1]); + fbp0 = (UBYTE FAR *) & (bp->b_buffer[idx]); + + /* Now to unpack the contents of the FAT entry. Odd and */ + /* even bytes are packed differently. */ + if (ClusterNum & 0x01) + ClusterNum = ((*fbp0 & 0xf0) >> 4) | *fbp1 << 4; + else + ClusterNum = *fbp0 | ((*fbp1 & 0x0f) << 8); + + if ((ClusterNum & MASK) == MASK) + ClusterNum = LONG_LAST_CLUSTER; + else if ((ClusterNum & BAD) == BAD) + ClusterNum = LONG_BAD; + return ClusterNum; +} diff --git a/kernel/fcbfns.c b/kernel/fcbfns.c new file mode 100644 index 0000000..d3bce15 --- /dev/null +++ b/kernel/fcbfns.c @@ -0,0 +1,1169 @@ +/****************************************************************/ +/* */ +/* fcbfns.c */ +/* */ +/* Old CP/M Style Function Handlers for Kernel */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:12 jhall1 + * Initial revision + * + * Revision 1.5 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.4 1999/09/23 04:40:46 jprice + * *** empty log message *** + * + * Revision 1.2 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:42:15 jprice + * New version without IPL.SYS + * + * Revision 1.5 1999/02/09 02:54:23 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/04 03:18:37 jprice + * Formating. Added comments. + * + * Revision 1.3 1999/02/01 01:43:28 jprice + * Fixed findfirst function to find volume label with Windows long filenames + * + * Revision 1.2 1999/01/22 04:15:28 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * + * Rev 1.7 06 Dec 1998 8:44:10 patv + * Expanded fcb functions for new I/O subsystem. + * + * Rev 1.6 04 Jan 1998 23:14:38 patv + * Changed Log for strip utility + * + * Rev 1.5 03 Jan 1998 8:36:02 patv + * Converted data area to SDA format + * + * Rev 1.4 16 Jan 1997 12:46:38 patv + * pre-Release 0.92 feature additions + * + * Rev 1.3 29 May 1996 21:15:14 patv + * bug fixes for v0.91a + * + * Rev 1.2 01 Sep 1995 17:48:44 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:50:26 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:06:06 patv + * Initial revision. + */ + +#define FCB_SUCCESS 0 +#define FCB_ERR_NODATA 1 +#define FCB_ERR_EOF 3 +#define FCB_ERR_WRITE 1 +#define D_ALL D_NORMAL | D_RDONLY | D_HIDDEN | D_SYSTEM | D_DIR | D_ARCHIVE + +#ifdef PROTO +fcb FAR *ExtFcbToFcb(xfcb FAR * lpExtFcb); +fcb FAR *CommonFcbInit(xfcb FAR * lpExtFcb, BYTE * pszBuffer, COUNT * pCurDrive); +void FcbNameInit(fcb FAR * lpFcb, BYTE * pszBuffer, COUNT * pCurDrive); +sft FAR *FcbGetSft(COUNT SftIndex); +VOID FcbNextRecord(fcb FAR * lpFcb); +sft FAR *FcbGetFreeSft(WORD FAR * sft_idx); +BOOL FcbFnameMatch(BYTE FAR * s, BYTE FAR * d, COUNT n, COUNT mode); +BOOL FcbCharMatch(COUNT s, COUNT d, COUNT mode); +BOOL FcbCalcRec(xfcb FAR * lpXfcb); +VOID MoveDirInfo(dmatch FAR * lpDmatch, struct dirent FAR * lpDir); +#else +fcb FAR *ExtFcbToFcb(); +fcb FAR *CommonFcbInit(); +void FcbNameInit(); +sft FAR *FcbGetSft(); +VOID FcbNextRecord(); +sft FAR *FcbGetFreeSft(); +BOOL FcbFnameMatch(); +BOOL FcbCharMatch(); +BOOL FcbCalcRec(); +VOID MoveDirInfo(); +#endif + +static dmatch Dmatch; + +VOID FatGetDrvData(COUNT drive, COUNT FAR * spc, COUNT FAR * bps, + COUNT FAR * nc, BYTE FAR ** mdp) +{ + struct dpb *dpbp; + + printf("FGDD\n"); + + /* first check for valid drive */ + if (drive < 0 || drive > NDEVS) + { + *spc = -1; + return; + } + + /* next - "log" in the drive */ + drive = (drive == 0 ? default_drive : drive - 1); + dpbp = (struct dpb *)CDSp->cds_table[drive].cdsDpb; + dpbp->dpb_flags = -1; + if ((media_check(dpbp) < 0)) + { + *spc = -1; + return; + } + + /* get the data vailable from dpb */ + *nc = dpbp->dpb_size; + *spc = dpbp->dpb_clsmask + 1; + *bps = dpbp->dpb_secsize; + + /* Point to the media desctriptor fotr this drive */ + *mdp = &(dpbp->dpb_mdb); +} + +#define PARSE_SEP_STOP 0x01 +#define PARSE_DFLT_DRIVE 0x02 +#define PARSE_BLNK_FNAME 0x04 +#define PARSE_BLNK_FEXT 0x08 + +#define PARSE_RET_NOWILD 0 +#define PARSE_RET_WILD 1 +#define PARSE_RET_BADDRIVE 0xff + +#ifndef IPL +WORD FcbParseFname(int wTestMode, BYTE FAR ** lpFileName, fcb FAR * lpFcb) +{ + COUNT nIndex; + WORD wRetCode = PARSE_RET_NOWILD; + + /* pjv -- ExtFcbToFcb? */ + /* Start out with some simple stuff first. Check if we are */ + /* going to use a default drive specificaton. */ + if (!(wTestMode & PARSE_DFLT_DRIVE)) + lpFcb->fcb_drive = FDFLT_DRIVE; + if (!(wTestMode & PARSE_BLNK_FNAME)) + { + for (nIndex = 0; nIndex < FNAME_SIZE; ++nIndex) + lpFcb->fcb_fname[nIndex] = ' '; + } + if (!(wTestMode & PARSE_BLNK_FEXT)) + { + for (nIndex = 0; nIndex < FEXT_SIZE; ++nIndex) + lpFcb->fcb_fext[nIndex] = ' '; + } + + /* Undocumented behavior, set record number & record size to 0 */ + lpFcb->fcb_cublock = lpFcb->fcb_recsiz = 0; + + if (!(wTestMode & PARSE_SEP_STOP)) + { + *lpFileName = ParseSkipWh(*lpFileName); + if (TestCmnSeps(*lpFileName)) + ++ * lpFileName; + } + + /* Undocumented "feature," we skip white space anyway */ + *lpFileName = ParseSkipWh(*lpFileName); + + /* Now check for drive specification */ + if (*(*lpFileName + 1) == ':') + { + REG BYTE Drive = upChar(**lpFileName); + + /* non-portable construct to be changed */ + if (Drive < 'A' || Drive > 'Z') + return PARSE_RET_BADDRIVE; + Drive -= ('A' - 1); + if (Drive > lastdrive) + return PARSE_RET_BADDRIVE; + else + lpFcb->fcb_drive = Drive; + *lpFileName += 2; + } + + /* Now to format the file name into the string */ + *lpFileName = GetNameField(*lpFileName, (BYTE FAR *) lpFcb->fcb_fname, FNAME_SIZE, (BOOL *) & wRetCode); + + /* Do we have an extension? If do, format it else return */ + if (**lpFileName == '.') + *lpFileName = GetNameField(++*lpFileName, (BYTE FAR *) lpFcb->fcb_fext, FEXT_SIZE, (BOOL *) & wRetCode); + + return wRetCode ? PARSE_RET_WILD : PARSE_RET_NOWILD; +} + +BYTE FAR *ParseSkipWh(BYTE FAR * lpFileName) +{ + while (*lpFileName == ' ' || *lpFileName == '\t') + ++lpFileName; + return lpFileName; +} + +BOOL TestCmnSeps(BYTE FAR * lpFileName) +{ + BYTE *pszTest, + *pszCmnSeps = ":<|>+=,"; + + for (pszTest = pszCmnSeps; *pszTest != '\0'; ++pszTest) + if (*lpFileName == *pszTest) + return TRUE; + return FALSE; +} + +BOOL TestFieldSeps(BYTE FAR * lpFileName) +{ + BYTE *pszTest, + *pszCmnSeps = "/\"[]<>|."; + + /* Another non-portable construct */ + if (*lpFileName <= ' ') + return TRUE; + + for (pszTest = pszCmnSeps; *pszTest != '\0'; ++pszTest) + if (*lpFileName == *pszTest) + return TRUE; + return FALSE; +} + +BYTE FAR *GetNameField(BYTE FAR * lpFileName, BYTE FAR * lpDestField, + COUNT nFieldSize, BOOL * pbWildCard) +{ + COUNT nIndex = 0; + BYTE cFill = ' '; + + *pbWildCard = FALSE; + while (*lpFileName != '\0' && !TestFieldSeps(lpFileName) && nIndex < nFieldSize) + { + if (*lpFileName == ' ') + break; + if (*lpFileName == '*') + { + *pbWildCard = TRUE; + cFill = '?'; + ++lpFileName; + break; + } + if (*lpFileName == '?') + *pbWildCard = TRUE; + *lpDestField++ = upChar(*lpFileName++); + ++nIndex; + } + + /* Blank out remainder of field on exit */ + for (; nIndex < nFieldSize; ++nIndex) + *lpDestField++ = cFill; + return lpFileName; +} + +static sft FAR *FcbGetSft(COUNT SftIndex) +{ + /* Get the SFT block that contains the SFT */ + for (lpCurSft = sfthead; lpCurSft != (sfttbl FAR *) - 1; + lpCurSft = lpCurSft->sftt_next) + { + if (SftIndex < lpCurSft->sftt_count) + break; + else + SftIndex -= lpCurSft->sftt_count; + } + + /* If not found, return an error */ + if (lpCurSft == (sfttbl FAR *) - 1) + return (sft FAR *) - 1; + + /* finally, point to the right entry */ + return (sft FAR *) & (lpCurSft->sftt_table[SftIndex]); +} + +static VOID FcbNextRecord(fcb FAR * lpFcb) +{ + if (++lpFcb->fcb_curec > 128) + { + lpFcb->fcb_curec = 0; + ++lpFcb->fcb_cublock; + } +} + +BOOL FcbRead(xfcb FAR * lpXfcb, COUNT * nErrorCode) +{ + sft FAR *s; + LONG lPosit; + COUNT nRead; + psp FAR *p = MK_FP(cu_psp, 0); + + /* Convert to fcb if necessary */ + lpFcb = ExtFcbToFcb(lpXfcb); + + /* Get the SFT block that contains the SFT */ + if ((s = FcbGetSft(lpFcb->fcb_sftno)) == (sft FAR *) - 1) + return FALSE; + + /* If this is not opened another error */ + if (s->sft_count == 0) + return FALSE; + + /* Now update the fcb and compute where we need to position */ + /* to. */ + lPosit = ((lpFcb->fcb_cublock * 128) + lpFcb->fcb_curec) + * lpFcb->fcb_recsiz; + if (dos_lseek(s->sft_status, lPosit, 0) < 0) + { + *nErrorCode = FCB_ERR_EOF; + return FALSE; + } + + if (s->sft_flags & SFT_FSHARED) + { + nRead = Remote_RW(REM_READ, lpFcb->fcb_recsiz, p->ps_dta, s, nErrorCode); + } + else + { + + /* Do the read */ + nRead = dos_read(s->sft_status, p->ps_dta, lpFcb->fcb_recsiz); + } + + /* Now find out how we will return and do it. */ + if (nRead == lpFcb->fcb_recsiz) + { + *nErrorCode = FCB_SUCCESS; + FcbNextRecord(lpFcb); + return TRUE; + } + else if (nRead < 0) + { + *nErrorCode = FCB_ERR_EOF; + return TRUE; + } + else if (nRead == 0) + { + *nErrorCode = FCB_ERR_NODATA; + return FALSE; + } + else + { + COUNT nIdx, + nCount; + BYTE FAR *lpDta; + + nCount = lpFcb->fcb_recsiz - nRead; + lpDta = (BYTE FAR *) & (p->ps_dta[nRead]); + for (nIdx = 0; nIdx < nCount; nIdx++) + *lpDta++ = 0; + *nErrorCode = FCB_ERR_EOF; + FcbNextRecord(lpFcb); + return FALSE; + } +} + +BOOL FcbWrite(xfcb FAR * lpXfcb, COUNT * nErrorCode) +{ + sft FAR *s; + LONG lPosit; + COUNT nWritten; + psp FAR *p = MK_FP(cu_psp, 0); + + /* Convert to fcb if necessary */ + lpFcb = ExtFcbToFcb(lpXfcb); + + /* Get the SFT block that contains the SFT */ + if ((s = FcbGetSft(lpFcb->fcb_sftno)) == (sft FAR *) - 1) + return FALSE; + + /* If this is not opened another error */ + if (s->sft_count == 0) + return FALSE; + + /* Now update the fcb and compute where we need to position */ + /* to. */ + lPosit = ((lpFcb->fcb_cublock * 128) + lpFcb->fcb_curec) + * lpFcb->fcb_recsiz; + if (dos_lseek(s->sft_status, lPosit, 0) < 0) + { + *nErrorCode = FCB_ERR_EOF; + return FALSE; + } + + if (s->sft_flags & SFT_FSHARED) + { + nWritten = Remote_RW(REM_WRITE, lpFcb->fcb_recsiz, p->ps_dta, s, nErrorCode); + } + else + { + + /* Do the read */ + nWritten = dos_write(s->sft_status, p->ps_dta, lpFcb->fcb_recsiz); + } + + /* Now find out how we will return and do it. */ + if (nWritten == lpFcb->fcb_recsiz) + { + lpFcb->fcb_fsize = dos_getcufsize(s->sft_status); + FcbNextRecord(lpFcb); + *nErrorCode = FCB_SUCCESS; + return TRUE; + } + else if (nWritten <= 0) + { + *nErrorCode = FCB_ERR_WRITE; + return TRUE; + } + *nErrorCode = FCB_ERR_WRITE; + return FALSE; +} + +BOOL FcbGetFileSize(xfcb FAR * lpXfcb) +{ + COUNT FcbDrive, + FileNum; + + /* Build a traditional DOS file name */ + lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); + + /* check for a device */ + /* if we have an extension, can't be a device */ + if (IsDevice(PriPathName) || (lpFcb->fcb_recsiz == 0)) + { + return FALSE; + } + FileNum = dos_open(PriPathName, O_RDONLY); + if (FileNum >= 0) + { + LONG fsize; + + /* Get the size */ + fsize = dos_getfsize(FileNum); + + /* compute the size and update the fcb */ + lpFcb->fcb_rndm = fsize / lpFcb->fcb_recsiz; + if ((fsize % lpFcb->fcb_recsiz) != 0) + ++lpFcb->fcb_rndm; + + /* close the file and leave */ + return dos_close(FileNum) == SUCCESS; + } + else + return FALSE; +} + +BOOL FcbSetRandom(xfcb FAR * lpXfcb) +{ + LONG lPosit; + + /* Convert to fcb if necessary */ + lpFcb = ExtFcbToFcb(lpXfcb); + + /* Now update the fcb and compute where we need to position */ + /* to. */ + lpFcb->fcb_rndm = (lpFcb->fcb_cublock * 128) + + lpFcb->fcb_curec; + + return TRUE; +} + +BOOL FcbCalcRec(xfcb FAR * lpXfcb) +{ + LONG lPosit; + + /* Convert to fcb if necessary */ + lpFcb = ExtFcbToFcb(lpXfcb); + + /* Now update the fcb and compute where we need to position */ + /* to. */ + lpFcb->fcb_cublock = lpFcb->fcb_rndm / 128; + lpFcb->fcb_curec = lpFcb->fcb_rndm % 128; + + return TRUE; +} + +BOOL FcbRandomBlockRead(xfcb FAR * lpXfcb, COUNT nRecords, COUNT * nErrorCode) +{ + FcbCalcRec(lpXfcb); + + /* Convert to fcb if necessary */ + lpFcb = ExtFcbToFcb(lpXfcb); + + do + FcbRead(lpXfcb, nErrorCode); + while ((--nRecords > 0) && (*nErrorCode == 0)); + + /* Now update the fcb */ + lpFcb->fcb_rndm = lpFcb->fcb_cublock * 128 + lpFcb->fcb_curec; + + return TRUE; +} + +BOOL FcbRandomBlockWrite(xfcb FAR * lpXfcb, COUNT nRecords, COUNT * nErrorCode) +{ + FcbCalcRec(lpXfcb); + + /* Convert to fcb if necessary */ + lpFcb = ExtFcbToFcb(lpXfcb); + + do + FcbWrite(lpXfcb, nErrorCode); + while ((--nRecords > 0) && (*nErrorCode == 0)); + + /* Now update the fcb */ + lpFcb->fcb_rndm = lpFcb->fcb_cublock * 128 + lpFcb->fcb_curec; + + return TRUE; +} + +BOOL FcbRandomRead(xfcb FAR * lpXfcb, COUNT * nErrorCode) +{ + UWORD uwCurrentBlock; + UBYTE ucCurrentRecord; + + FcbCalcRec(lpXfcb); + + /* Convert to fcb if necessary */ + lpFcb = ExtFcbToFcb(lpXfcb); + + uwCurrentBlock = lpFcb->fcb_cublock; + ucCurrentRecord = lpFcb->fcb_curec; + + FcbRead(lpXfcb, nErrorCode); + + lpFcb->fcb_cublock = uwCurrentBlock; + lpFcb->fcb_curec = ucCurrentRecord; + return TRUE; +} + +BOOL FcbRandomWrite(xfcb FAR * lpXfcb, COUNT * nErrorCode) +{ + UWORD uwCurrentBlock; + UBYTE ucCurrentRecord; + + FcbCalcRec(lpXfcb); + + /* Convert to fcb if necessary */ + lpFcb = ExtFcbToFcb(lpXfcb); + + uwCurrentBlock = lpFcb->fcb_cublock; + ucCurrentRecord = lpFcb->fcb_curec; + + FcbWrite(lpXfcb, nErrorCode); + + lpFcb->fcb_cublock = uwCurrentBlock; + lpFcb->fcb_curec = ucCurrentRecord; + return TRUE; +} + +static sft FAR *FcbGetFreeSft(WORD FAR * sft_idx) +{ + WORD sys_idx = 0; + sfttbl FAR *sp; + + /* Get the SFT block that contains the SFT */ + for (sp = sfthead; sp != (sfttbl FAR *) - 1; sp = sp->sftt_next) + { + REG WORD i; + + for (i = 0; i < sp->sftt_count; i++) + { + if (sp->sftt_table[i].sft_count == 0) + { + *sft_idx = sys_idx + i; + return (sft FAR *) & sp->sftt_table[sys_idx + i]; + } + } + sys_idx += i; + } + + /* If not found, return an error */ + return (sft FAR *) - 1; +} + +BOOL FcbCreate(xfcb FAR * lpXfcb) +{ + WORD sft_idx; + sft FAR *sftp; + struct dhdr FAR *dhp; + COUNT FcbDrive; + + /* get a free system file table entry */ + if ((sftp = FcbGetFreeSft((WORD FAR *) & sft_idx)) == (sft FAR *) - 1) + return DE_TOOMANY; + + /* Build a traditional DOS file name */ + lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); + + /* check for a device */ + /* if we have an extension, can't be a device */ + if (IsDevice(PriPathName)) + { + for (dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp->dh_next) + { + if (FcbFnameMatch((BYTE FAR *) PriPathName, (BYTE FAR *) dhp->dh_name, FNAME_SIZE, FALSE)) + { + sftp->sft_count += 1; + sftp->sft_mode = O_RDWR; + sftp->sft_attrib = 0; + sftp->sft_flags = + (dhp->dh_attr & ~SFT_MASK) | SFT_FDEVICE | SFT_FEOF; + sftp->sft_psp = cu_psp; + fbcopy(lpFcb->fcb_fname, sftp->sft_name, FNAME_SIZE + FEXT_SIZE); + sftp->sft_dev = dhp; + lpFcb->fcb_sftno = sft_idx; + lpFcb->fcb_curec = 0; + lpFcb->fcb_recsiz = 0; + lpFcb->fcb_fsize = 0; + lpFcb->fcb_date = dos_getdate(); + lpFcb->fcb_time = dos_gettime(); + lpFcb->fcb_rndm = 0; + return TRUE; + } + } + } + sftp->sft_status = dos_creat(PriPathName, 0); + if (sftp->sft_status >= 0) + { + lpFcb->fcb_drive = FcbDrive; + lpFcb->fcb_sftno = sft_idx; + lpFcb->fcb_curec = 0; + lpFcb->fcb_recsiz = 128; + lpFcb->fcb_fsize = 0; + lpFcb->fcb_date = dos_getdate(); + lpFcb->fcb_time = dos_gettime(); + lpFcb->fcb_rndm = 0; + sftp->sft_count += 1; + sftp->sft_mode = O_RDWR; + sftp->sft_attrib = 0; + sftp->sft_flags = 0; + sftp->sft_psp = cu_psp; + fbcopy((BYTE FAR *) & lpFcb->fcb_fname, (BYTE FAR *) & sftp->sft_name, FNAME_SIZE + FEXT_SIZE); + return TRUE; + } + else + return FALSE; +} + +static fcb FAR *ExtFcbToFcb(xfcb FAR * lpExtFcb) +{ + if (*((UBYTE FAR *) lpExtFcb) == 0xff) + return &lpExtFcb->xfcb_fcb; + else + return (fcb FAR *) lpExtFcb; +} + +static fcb FAR *CommonFcbInit(xfcb FAR * lpExtFcb, BYTE * pszBuffer, + COUNT * pCurDrive) +{ + BYTE FAR *lpszFcbFname, + *lpszFcbFext; + COUNT nDrvIdx, + nFnameIdx, + nFextIdx; + fcb FAR *lpFcb; + + /* convert to fcb if needed first */ + lpFcb = ExtFcbToFcb(lpExtFcb); + + /* Build a traditional DOS file name */ + FcbNameInit(lpFcb, pszBuffer, pCurDrive); + + /* and return the fcb pointer */ + return lpFcb; +} + +void FcbNameInit(fcb FAR * lpFcb, BYTE * pszBuffer, COUNT * pCurDrive) +{ + BYTE FAR *lpszFcbFname, + FAR * lpszFcbFext; + COUNT nDrvIdx, + nFnameIdx, + nFextIdx; + + /* Build a traditional DOS file name */ + lpszFcbFname = (BYTE FAR *) lpFcb->fcb_fname; + if (lpFcb->fcb_drive != 0) + { + *pCurDrive = lpFcb->fcb_drive; + pszBuffer[0] = 'A' + lpFcb->fcb_drive - 1; + pszBuffer[1] = ':'; + nDrvIdx = 2; + } + else + { + *pCurDrive = default_drive + 1; + nDrvIdx = 0; + } + + for (nFnameIdx = 0; nFnameIdx < FNAME_SIZE; nFnameIdx++) + { + if (*lpszFcbFname != ' ') + pszBuffer[nDrvIdx + nFnameIdx] = *lpszFcbFname++; + else + break; + } + + lpszFcbFext = (BYTE FAR *) lpFcb->fcb_fext; + if (*lpszFcbFext != ' ') + { + pszBuffer[nDrvIdx + nFnameIdx++] = '.'; + for (nFextIdx = 0; nFextIdx < FEXT_SIZE; nFextIdx++) + { + if (*lpszFcbFext != ' ') + pszBuffer[nDrvIdx + nFnameIdx + nFextIdx] = + *lpszFcbFext++; + else + break; + } + } + else + nFextIdx = 0; + pszBuffer[nDrvIdx + nFnameIdx + nFextIdx] = '\0'; +} + +/* Ascii only file name match routines */ +static BOOL FcbCharMatch(COUNT s, COUNT d, COUNT mode) +{ + if (s >= 'a' && s <= 'z') + s -= 'a' - 'A'; + if (d >= 'a' && d <= 'z') + d -= 'a' - 'A'; + if (mode && s == '?' && (d >= 'A' && s <= 'Z')) + return TRUE; + return s == d; +} + +static BOOL FcbFnameMatch(BYTE FAR * s, BYTE FAR * d, COUNT n, COUNT mode) +{ + while (n--) + { + if (!FcbCharMatch(*s++, *d++, mode)) + return FALSE; + } + return TRUE; +} + +BOOL FcbOpen(xfcb FAR * lpXfcb) +{ + WORD sft_idx; + sft FAR *sftp; + struct dhdr FAR *dhp; + COUNT FcbDrive; + + /* get a free system file table entry */ + if ((sftp = FcbGetFreeSft((WORD FAR *) & sft_idx)) == (sft FAR *) - 1) + return DE_TOOMANY; + + /* Build a traditional DOS file name */ + lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); + + /* check for a device */ + /* if we have an extension, can't be a device */ + if (IsDevice(PriPathName)) + { + for (dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp->dh_next) + { + if (FcbFnameMatch((BYTE FAR *) PriPathName, (BYTE FAR *) dhp->dh_name, FNAME_SIZE, FALSE)) + { + sftp->sft_count += 1; + sftp->sft_mode = O_RDWR; + sftp->sft_attrib = 0; + sftp->sft_flags = + (dhp->dh_attr & ~SFT_MASK) | SFT_FDEVICE | SFT_FEOF; + sftp->sft_psp = cu_psp; + fbcopy(lpFcb->fcb_fname, sftp->sft_name, FNAME_SIZE + FEXT_SIZE); + sftp->sft_dev = dhp; + lpFcb->fcb_sftno = sft_idx; + lpFcb->fcb_curec = 0; + lpFcb->fcb_recsiz = 0; + lpFcb->fcb_fsize = 0; + lpFcb->fcb_date = dos_getdate(); + lpFcb->fcb_time = dos_gettime(); + lpFcb->fcb_rndm = 0; + return TRUE; + } + } + } + sftp->sft_status = dos_open(PriPathName, O_RDWR); + if (sftp->sft_status >= 0) + { + lpFcb->fcb_drive = FcbDrive; + lpFcb->fcb_sftno = sft_idx; + lpFcb->fcb_curec = 0; + lpFcb->fcb_recsiz = 128; + lpFcb->fcb_fsize = dos_getfsize(sftp->sft_status); + dos_getftime(sftp->sft_status, + (date FAR *) & lpFcb->fcb_date, + (time FAR *) & lpFcb->fcb_time); + lpFcb->fcb_rndm = 0; + sftp->sft_count += 1; + sftp->sft_mode = O_RDWR; + sftp->sft_attrib = 0; + sftp->sft_flags = 0; + sftp->sft_psp = cu_psp; + fbcopy((BYTE FAR *) & lpFcb->fcb_fname, (BYTE FAR *) & sftp->sft_name, FNAME_SIZE + FEXT_SIZE); + return TRUE; + } + else + return FALSE; +} + +BOOL FcbDelete(xfcb FAR * lpXfcb) +{ + COUNT FcbDrive; + + /* Build a traditional DOS file name */ + CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); + + /* check for a device */ + /* if we have an extension, can't be a device */ + if (IsDevice(PriPathName)) + { + return FALSE; + } + else + { + BYTE FAR *lpOldDta = dta; + dmatch Dmatch; + + dta = (BYTE FAR *) & Dmatch; + if (dos_findfirst(D_ALL, PriPathName[1] == ':' ? &PriPathName[2] : PriPathName) != SUCCESS) + { + dta = lpOldDta; + return FALSE; + } + do + { + if (dos_delete(Dmatch.dm_name) != SUCCESS) + { + dta = lpOldDta; + return FALSE; + } + } + while (dos_findnext() == SUCCESS); + dta = lpOldDta; + return TRUE; + } +} + +BOOL FcbRename(xfcb FAR * lpXfcb) +{ + rfcb FAR *lpRenameFcb; + COUNT FcbDrive; + + /* Build a traditional DOS file name */ + lpRenameFcb = (rfcb FAR *) CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); + + /* check for a device */ + /* if we have an extension, can't be a device */ + if (IsDevice(PriPathName)) + { + return FALSE; + } + else + { + BYTE FAR *lpOldDta = dta; + dmatch Dmatch; + + dta = (BYTE FAR *) & Dmatch; + if (dos_findfirst(D_ALL, PriPathName[1] == ':' ? &PriPathName[2] : PriPathName) != SUCCESS) + { + dta = lpOldDta; + return FALSE; + } + + do + { + fcb LocalFcb; + BYTE *pToName, + *pszFrom; + BYTE FAR *pFromPattern; + COUNT nIndex; + + /* First, expand the find match into fcb style */ + /* file name entry */ + /* Fill with blanks first */ + for (pToName = LocalFcb.fcb_fname, nIndex = 0; + nIndex < FNAME_SIZE; nIndex++) + { + *pToName++ = ' '; + } + for (pToName = LocalFcb.fcb_fext, nIndex = 0; + nIndex < FEXT_SIZE; nIndex++) + { + *pToName++ = ' '; + } + + /* next move in the file name while overwriting */ + /* the filler blanks */ + pszFrom = Dmatch.dm_name; + pToName = LocalFcb.fcb_fname; + for (nIndex = 0; nIndex < FNAME_SIZE; nIndex++) + { + if (*pszFrom != 0 && *pszFrom != '.') + *pToName++ = *pszFrom++; + else if (*pszFrom == '.') + { + ++pszFrom; + break; + } + else + break; + } + + if (*pszFrom != '\0') + { + pToName = LocalFcb.fcb_fext; + for (nIndex = 0; nIndex < FEXT_SIZE; nIndex++) + { + if (*pszFrom != '\0') + *pToName++ = *pszFrom++; + else + break; + } + } + + /* Overlay the pattern, skipping '?' */ + /* I'm cheating because this assumes that the */ + /* struct alignments are on byte boundaries */ + pToName = LocalFcb.fcb_fname; + for (pFromPattern = lpRenameFcb->renNewName, + nIndex = 0; nIndex < FNAME_SIZE + FEXT_SIZE; nIndex++) + { + if (*pFromPattern != '?') + *pToName++ = *pFromPattern++; + else + ++pFromPattern; + } + + /* now to build a dos name again */ + LocalFcb.fcb_drive = 0; + FcbNameInit((fcb FAR *) & LocalFcb, PriPathName, &FcbDrive); + + if (dos_rename(Dmatch.dm_name, + PriPathName[1] == ':' ? &PriPathName[2] : PriPathName) != SUCCESS) + { + dta = lpOldDta; + return FALSE; + } + } + while (dos_findnext() == SUCCESS); + dta = lpOldDta; + return TRUE; + } +} + +void MoveDirInfo(dmatch FAR * lpDmatch, struct dirent FAR * lpDir) +{ + BYTE FAR *lpToName, + FAR * lpszFrom; + COUNT nIndex; + + /* First, expand the find match into dir style */ + /* file name entry */ + /* Fill with blanks first */ + for (lpToName = lpDir->dir_name, nIndex = 0; + nIndex < FNAME_SIZE; nIndex++) + { + *lpToName++ = ' '; + } + for (lpToName = lpDir->dir_ext, nIndex = 0; + nIndex < FEXT_SIZE; nIndex++) + { + *lpToName++ = ' '; + } + + /* next move in the file name while overwriting */ + /* the filler blanks */ + lpszFrom = lpDmatch->dm_name; + lpToName = lpDir->dir_name; + for (nIndex = 0; nIndex < FNAME_SIZE; nIndex++) + { + if (*lpszFrom != 0 && *lpszFrom != '.') + *lpToName++ = *lpszFrom++; + else + break; + } + + if (*lpszFrom != '\0') + { + if (*lpszFrom == '.') + ++lpszFrom; + lpToName = lpDir->dir_ext; + for (nIndex = 0; nIndex < FEXT_SIZE; nIndex++) + { + if (*lpszFrom != '\0') + *lpToName++ = *lpszFrom++; + else + break; + } + } + for (nIndex = 0; nIndex < 10; nIndex++) + lpDir->dir_reserved[nIndex] = 0; + lpDir->dir_attrib = lpDmatch->dm_attr_fnd; + lpDir->dir_time = lpDmatch->dm_time; + lpDir->dir_date = lpDmatch->dm_date; + lpDir->dir_start = lpDmatch->dm_cluster; + lpDir->dir_size = lpDmatch->dm_size; +} + +BOOL FcbClose(xfcb FAR * lpXfcb) +{ + sft FAR *s; + + /* Convert to fcb if necessary */ + lpFcb = ExtFcbToFcb(lpXfcb); + + /* Get the SFT block that contains the SFT */ + if ((s = FcbGetSft(lpFcb->fcb_sftno)) == (sft FAR *) - 1) + return FALSE; + + /* If this is not opened another error */ + if (s->sft_count == 0) + return FALSE; + + if (s->sft_flags & SFT_FSHARED) + { + int2f_Remote_call(REM_CLOSE, 0, 0, 0, (VOID FAR *) s, 0, 0); + } + + /* now just drop the count if a device, else */ + /* call file system handler */ + if (s->sft_flags & SFT_FDEVICE) + { + s->sft_count -= 1; + return TRUE; + } + else + { + s->sft_count -= 1; + if (s->sft_count > 0) + return SUCCESS; + else + { + /* change time and set file size */ + dos_setftime(s->sft_status, + (date FAR *) & lpFcb->fcb_date, + (time FAR *) & lpFcb->fcb_time); + dos_setfsize(s->sft_status, + lpFcb->fcb_fsize); + return dos_close(s->sft_status) == SUCCESS; + } + } +} + +BOOL FcbFindFirst(xfcb FAR * lpXfcb) +{ + BYTE FAR *lpOldDta; + BYTE FAR *lpDir; + COUNT nIdx, + FcbDrive; + psp FAR *lpPsp = MK_FP(cu_psp, 0); + + /* First, move the dta to a local and change it around to match */ + /* our functions. */ + lpDir = (BYTE FAR *) dta; + dta = (BYTE FAR *) & Dmatch; + + /* Next initialze local variables by moving them from the fcb */ + lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); + if (lpXfcb->xfcb_flag == 0xff) + { + wAttr = lpXfcb->xfcb_attrib; + fbcopy(lpXfcb, lpDir, 7); + lpDir += 7; + } + else + wAttr = D_ALL; + + *lpDir++ = PriPathName[0] - 'A'; + if (dos_findfirst(wAttr, PriPathName) != SUCCESS) + { + dta = lpPsp->ps_dta; + return FALSE; + } + + MoveDirInfo((dmatch FAR *) & Dmatch, (struct dirent FAR *)lpDir); + lpFcb->fcb_dirclst = Dmatch.dm_cluster; + lpFcb->fcb_diroff = Dmatch.dm_entry; + dta = lpPsp->ps_dta; + return TRUE; +} + +BOOL FcbFindNext(xfcb FAR * lpXfcb) +{ + BYTE FAR *lpOldDta; + BYTE FAR *lpDir; + COUNT nIdx, + FcbDrive; + psp FAR *lpPsp = MK_FP(cu_psp, 0); + + /* First, move the dta to a local and change it around to match */ + /* our functions. */ + lpDir = (BYTE FAR *) dta; + dta = (BYTE FAR *) & Dmatch; + + /* Next initialze local variables by moving them from the fcb */ + lpFcb = CommonFcbInit(lpXfcb, PriPathName, &FcbDrive); + if ((xfcb FAR *) lpFcb != lpXfcb) + { + wAttr = lpXfcb->xfcb_attrib; + fbcopy(lpXfcb, lpDir, 7); + lpDir += 7; + } + else + wAttr = D_ALL; + + /* Reconstrct the dirmatch structure from the fcb */ + *lpDir++ = FcbDrive; + Dmatch.dm_drive = FcbDrive ? FcbDrive - 1 : default_drive; + + fbcopy(lpFcb->fcb_fname, (BYTE FAR *) Dmatch.dm_name_pat, FNAME_SIZE + FEXT_SIZE); + upMem((BYTE FAR *) Dmatch.dm_name_pat, FNAME_SIZE + FEXT_SIZE); + Dmatch.dm_attr_srch = wAttr; + Dmatch.dm_entry = lpFcb->fcb_diroff; + Dmatch.dm_cluster = lpFcb->fcb_dirclst; + + if (dos_findnext() != SUCCESS) + { + dta = lpPsp->ps_dta; + return FALSE; + } + + MoveDirInfo((dmatch FAR *) & Dmatch, (struct dirent FAR *)lpDir); + lpFcb->fcb_dirclst = Dmatch.dm_cluster; + lpFcb->fcb_diroff = Dmatch.dm_entry; + dta = lpPsp->ps_dta; + return TRUE; +} +#endif + diff --git a/kernel/globals.h b/kernel/globals.h new file mode 100644 index 0000000..195226f --- /dev/null +++ b/kernel/globals.h @@ -0,0 +1,713 @@ +/****************************************************************/ +/* */ +/* globals.h */ +/* DOS-C */ +/* */ +/* Global data structures and declarations */ +/* */ +/* Copyright (c) 1995, 1996 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +/* $Logfile: C:/usr/patv/dos-c/src/kernel/globals.h_v $ */ +#ifdef VERSION_STRINGS +#ifdef MAIN +static BYTE *Globals_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:18 jhall1 + * Initial revision + * + * Revision 1.16 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.15 1999/09/23 04:40:47 jprice + * *** empty log message *** + * + * Revision 1.13 1999/08/25 03:18:08 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.12 1999/08/10 18:03:43 jprice + * ror4 2011-03 patch + * + * Revision 1.11 1999/05/03 06:25:45 jprice + * Patches from ror4 and many changed of signed to unsigned variables. + * + * Revision 1.10 1999/04/16 21:43:40 jprice + * ror4 multi-sector IO + * + * Revision 1.9 1999/04/16 12:21:22 jprice + * Steffen c-break handler changes + * + * Revision 1.8 1999/04/16 00:53:33 jprice + * Optimized FAT handling + * + * Revision 1.7 1999/04/12 03:21:17 jprice + * more ror4 patches. Changes for multi-block IO + * + * Revision 1.6 1999/04/11 04:33:39 jprice + * ror4 patches + * + * Revision 1.4 1999/04/04 22:57:47 jprice + * no message + * + * Revision 1.3 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.2 1999/03/29 17:05:09 jprice + * ror4 changes + * + * Revision 1.1.1.1 1999/03/29 15:40:58 jprice + * New version without IPL.SYS + * + * Revision 1.5 1999/02/08 05:55:57 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.3 1999/01/30 08:26:46 jprice + * Clean up; commented out copyright messages while we debug. + * + * Revision 1.2 1999/01/22 04:13:26 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + + Rev 1.16 06 Dec 1998 8:45:56 patv + Expanded due to new I/O subsystem. + + Rev 1.15 07 Feb 1998 20:38:00 patv + Modified stack fram to match DOS standard + + Rev 1.14 02 Feb 1998 22:33:46 patv + Fixed size of default_drive. Caused failures when break_ena was not zero. + + Rev 1.13 22 Jan 1998 4:09:24 patv + Fixed pointer problems affecting SDA + + Rev 1.12 04 Jan 1998 23:16:22 patv + Changed Log for strip utility + + Rev 1.11 03 Jan 1998 8:36:50 patv + Converted data area to SDA format + + Rev 1.10 06 Feb 1997 21:57:04 patv + Changed version format string + + Rev 1.9 06 Feb 1997 21:35:08 patv + Modified to support new version format + + Rev 1.8 22 Jan 1997 13:17:14 patv + Changed to support version.h and pre-0.92 Svante Frey bug fixes. + + Rev 1.6 16 Jan 1997 12:47:00 patv + pre-Release 0.92 feature additions + + Rev 1.5 13 Sep 1996 19:26:32 patv + Fixed boot for hard drive + + Rev 1.4 29 Aug 1996 13:07:22 patv + Bug fixes for v0.91b + + Rev 1.3 29 May 1996 21:03:34 patv + bug fixes for v0.91a + + Rev 1.2 19 Feb 1996 3:23:04 patv + Added NLS, int2f and config.sys processing + + Rev 1.1 01 Sep 1995 17:54:16 patv + First GPL release. + + Rev 1.0 02 Jul 1995 8:31:00 patv + Initial revision. + */ + +#include "device.h" +#include "mcb.h" +#include "pcb.h" +#include "date.h" +#include "time.h" +#include "fat.h" +#include "fcb.h" +#include "tail.h" +#include "process.h" +#include "dcb.h" +#include "sft.h" +#include "cds.h" +#include "exe.h" +#include "fnode.h" +#include "dirmatch.h" +#include "file.h" +#include "clock.h" +#include "kbd.h" +#include "error.h" +#include "version.h" +#include "network.h" + +/* JPP: for testing/debuging disk IO */ +/*#define DISPLAY_GETBLOCK */ + +/* */ +/* Convience switch for maintaining variables in a single location */ +/* */ +#ifdef MAIN +#define GLOBAL +#else +#define GLOBAL extern +#endif + +/* */ +/* Convience definitions of TRUE and FALSE */ +/* */ +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +/* */ +/* Constants and macros */ +/* */ +/* Defaults and limits - System wide */ +#define PARSE_MAX 67 /* maximum # of bytes in path */ +#define NFILES 16 /* number of files in table */ +#define NFCBS 16 /* number of fcbs */ +#define NDEVS 8 /* number of supported devices */ +#define NSTACKS 8 /* number of stacks */ +#define NLAST 2 /* last drive */ +#define NAMEMAX PARSE_MAX /* Maximum path for CDS */ +#define NUMBUFF 6 /* Number of track buffers */ + /* -- must be at least 3 */ + +/* 0 = CON, standard input, can be redirected */ +/* 1 = CON, standard output, can be redirected */ +/* 2 = CON, standard error */ +/* 3 = AUX, auxiliary */ +/* 4 = PRN, list device */ +/* 5 = 1st user file ... */ +#define STDIN 0 +#define STDOUT 1 +#define STDERR 2 +#define STDAUX 3 +#define STDPRN 4 + +/* internal error from failure or aborted operation */ +#define ERROR -1 +#define OK 0 + +/* internal transfer direction flags */ +#define XFR_READ 1 +#define XFR_WRITE 2 + +#define RDONLY 0 +#define WRONLY 1 +#define RDWR 2 + +/* special ascii code equates */ +#define SPCL 0x00 +#define CTL_C 0x03 +#define CTL_F 0x06 +#define BELL 0x07 +#define BS 0x08 +#define HT 0x09 +#define LF 0x0a +#define CR 0x0d +#define CTL_Q 0x11 +#define CTL_S 0x13 +#define CTL_Z 0x1a +#define ESC 0x1b +#define CTL_BS 0x7f + +#define F3 0x3d +#define LEFT 0x4b +#define RIGHT 0x4d + +/* Blockio constants */ +#define DSKWRITE 1 /* dskxfr function parameters */ +#define DSKREAD 2 + +/* FAT cluster special flags */ +#define FREE 0x000 + +#define LONG_LAST_CLUSTER 0xFFFF +#define LONG_MASK 0xFFF8 +#define LONG_BAD 0xFFF0 +#define LAST_CLUSTER 0x0FFF +#define MASK 0xFF8 +#define BAD 0xFF0 + +/* Keyboard buffer maximum size */ +#ifdef LINESIZE +#undef LINESIZE +#endif +#define LINESIZE 256 + +/* */ +/* Data structures and unions */ +/* */ +/* Sector buffer structure */ +#define BUFFERSIZE 512 +struct buffer +{ + struct buffer + FAR *b_next; /* form linked list for LRU */ + BYTE b_unit; /* disk for this buffer */ + BYTE b_flag; /* buffer flags */ + UWORD b_blkno; /* block for this buffer */ + /* DOS-C: 0xffff for huge block numbers */ + BYTE b_copies; /* number of copies to write */ + UBYTE b_offset_lo; /* span between copies (low) */ + union + { + struct dpb FAR *_b_dpbp; /* pointer to DPB */ + LONG _b_huge_blkno; /* DOS-C: actual block number if >= 0xffff */ + } + _b; + UBYTE b_offset_hi; /* DOS-C: span between copies (high) */ + UBYTE b_unused; + BYTE b_buffer[BUFFERSIZE]; /* 512 byte sectors for now */ +}; + +#define b_dpbp _b._b_dpbp +#define b_huge_blkno _b._b_huge_blkno + +#define BFR_DIRTY 0x40 /* buffer modified */ +#define BFR_VALID 0x20 /* buffer contains valid data */ +#define BFR_DATA 0x08 /* buffer is from data area */ +#define BFR_DIR 0x04 /* buffer is from dir area */ +#define BFR_FAT 0x02 /* buffer is from fat area */ +#define BFR_BOOT 0x01 /* buffer is boot disk */ + +/* NLS character table type */ +typedef BYTE *UPMAP; + +/* */ +/* External Assembly variables */ +/* */ +extern struct dhdr +FAR clk_dev, /* Clock device driver */ + FAR con_dev, /* Console device driver */ + FAR prn_dev, /* Generic printer device driver */ + FAR aux_dev, /* Generic aux device driver */ + FAR blk_dev; /* Block device (Disk) driver */ +extern UWORD + ram_top, /* How much ram in Kbytes */ +#ifdef I86 + + api_sp, /* api stacks - for context */ +#endif + + api_ss, /* switching */ + usr_sp, /* user stack */ + usr_ss; +extern COUNT * +#ifdef MC68K + api_sp, /* api stacks - for context */ +#endif + + error_tos, /* error stack */ + disk_api_tos, /* API handler stack - disk fns */ + char_api_tos; /* API handler stack - char fns */ +extern BYTE + FAR last; /* first available byte of ram */ +extern struct ClockRecord + ClkRecord; + +/* */ +/* Global variables */ +/* */ +GLOBAL +seg master_env; /* Master environment segment */ + +GLOBAL BYTE + os_major, /* major version number */ + os_minor, /* minor version number */ + + rev_number /* minor version number */ +#ifdef MAIN += REV_NUMBER, +#else + , +#endif + + version_flags; /* minor version number */ +#ifdef DEBUG +GLOBAL WORD bDumpRegs +#ifdef MAIN += FALSE; +#else + ; +#endif +GLOBAL WORD bDumpRdWrParms +#ifdef MAIN += FALSE; +#else + ; +#endif +#endif + +GLOBAL BYTE *copyright +#if 0 += "(C) Copyright 1995, 1996, 1997, 1998\nPasquale J. Villani\nAll Rights Reserved\n"; +#else + ; +#endif + +GLOBAL BYTE *os_release +#ifdef MAIN +#if 0 += "DOS-C version %d.%d Beta %d [FreeDOS Release] (Build %d).\n\ +\n\ +DOS-C is free software; you can redistribute it and/or modify it under the\n\ +terms of the GNU General Public License as published by the Free Software\n\ +Foundation; either version 2, or (at your option) any later version.\n\n\ +For technical information and description of the DOS-C operating system\n\ +consult \"FreeDOS Kernel\" by Pat Villani, published by Miller\n\ +Freeman Publishing, Lawrence KS, USA (ISBN 0-87930-436-7).\n\ +\n"; +#else += "FreeDOS kernel version %d.%d.%d (Build %d) [" __DATE__ " " __TIME__ "]\n\n"; +#endif +#else + ; +#endif + +/* Globally referenced variables - WARNING: ORDER IS DEFINED IN */ +/* KERNAL.ASM AND MUST NOT BE CHANGED. DO NOT CHANGE ORDER BECAUSE THEY */ +/* ARE DOCUMENTED AS UNDOCUMENTED (?) AND HAVE MANY PROGRAMS AND TSR'S */ +/* ACCESSING THEM */ + +extern UWORD NetBios; +extern BYTE *net_name; +extern BYTE net_set_count; +extern BYTE NetDelay, + NetRetry; + +extern UWORD + first_mcb; /* Start of user memory */ +extern struct dpb +FAR *DPBp; /* First drive Parameter Block */ +extern sfttbl + FAR * sfthead; /* System File Table head */ +extern struct dhdr +FAR *clock, /* CLOCK$ device */ + FAR * syscon; /* console device */ +extern WORD + maxbksize; /* Number of Drives in system */ +extern struct buffer +FAR *firstbuf; /* head of buffers linked list */ +extern cdstbl + FAR * CDSp; /* Current Directory Structure */ +extern +struct cds FAR *current_ldt; +extern sfttbl + FAR * FCBp; /* FCB table pointer */ +extern WORD + nprotfcb; /* number of protected fcbs */ +extern BYTE + nblkdev, /* number of block devices */ + lastdrive; /* value of last drive */ +extern struct dhdr + nul_dev; +extern BYTE + LocalPath[PARSE_MAX + 3], /* Room for drive spec */ + mem_access_mode, /* memory allocation scheme */ + ErrorMode, /* Critical error flag */ + InDOS, /* In DOS critical section */ + OpenMode, /* File Open Attributes */ + SAttr, /* Attrib Mask for Dir Search */ + dosidle_flag, + njoined; /* number of joined devices */ + +extern UWORD Int21AX; + +extern struct dirent + SearchDir; + +extern struct +{ + COUNT nDrive; + BYTE szName[FNAME_SIZE + 1]; + BYTE szExt[FEXT_SIZE + 1]; +} +FcbSearchBuffer; + +extern union /* Path name parsing buffer */ +{ + BYTE _PriPathName[128]; + struct + { + BYTE _dname[NAMEMAX]; + BYTE _fname[FNAME_SIZE]; + BYTE _fext[FEXT_SIZE]; + } + _f; +} +_PriPathBuffer; +#define PriPathName _PriPathBuffer._PriPathName +#define szDirName _PriPathBuffer._f._dname +#define szFileName _PriPathBuffer._f._fname +#define szFileExt _PriPathBuffer._f._fext +#define szPriDirName _PriPathBuffer._f._dname +#define szPriFileName _PriPathBuffer._f._fname +#define szPriFileExt _PriPathBuffer._f._fext + +extern union /* Alternate path name parsing buffer */ +{ + BYTE _SecPathName[128]; + struct + { + BYTE _dname[NAMEMAX]; + BYTE _fname[FNAME_SIZE]; + BYTE _fext[FEXT_SIZE]; + } + _f; +} +_SecPathBuffer; +#define SecPathName _SecPathBuffer._SecPathName +#define szSecDirName _SecPathBuffer._f._dname +#define szSecFileName _SecPathBuffer._f._fname +#define szSecFileExt _SecPathBuffer._f._fext + +extern UWORD + wAttr; + +extern BYTE + default_drive; /* default drive for dos */ + +extern BYTE + TempBuffer[], /* Temporary general purpose buffer */ + FAR internal_data[], /* sda areas */ + FAR swap_always[], /* " " */ + FAR swap_indos[], /* " " */ + tsr, /* true if program is TSR */ + break_flg, /* true if break was detected */ + break_ena, /* break enabled flag */ + FAR * dta; /* Disk transfer area (kludge) */ +extern seg + cu_psp; /* current psp segment */ +extern iregs + FAR * user_r; /* User registers for int 21h call */ + +extern struct dirent /* Temporary directory entry */ + DirEntBuffer; + +extern request /* I/O Request packets */ + CharReqHdr, + IoReqHdr, + MediaReqHdr; + +extern fcb + FAR * lpFcb; /* Pointer to users fcb */ + +extern sfttbl + FAR * lpCurSft; + +extern BYTE + verify_ena, /* verify enabled flag */ + switchar, /* switch char */ + return_mode, /* Process termination rets */ + return_code; /* " " " */ + +extern BYTE + scr_pos; /* screen position for bs, ht, etc */ +extern WORD + BootDrive, /* Drive we came up from */ + NumFloppies; /* How many floppies we have */ + +extern keyboard + kb_buf; + +extern struct cds + TempCDS; + +/* start of uncontrolled variables */ +GLOBAL seg + RootPsp; /* Root process -- do not abort */ + +GLOBAL struct f_node + *pDirFileNode; + +GLOBAL iregs error_regs; /* registers for dump */ + +GLOBAL WORD + dump_regs; /* dump registers of bad call */ + +GLOBAL struct dpb + blk_devices[NDEVS]; + +GLOBAL struct f_node FAR +* f_nodes; /* pointer to the array */ + +GLOBAL struct buffer +FAR *lastbuf, /* tail of ditto */ + FAR * buffers; /* pointer to array of track buffers */ + +GLOBAL BYTE /* scratchpad used for working around */ + FAR * dma_scratch; /* DMA transfers during disk I/O */ + +GLOBAL iregs + FAR * ustackp, /* user stack */ + FAR * kstackp; /* kernel stack */ + +/* Start of configuration variables */ +GLOBAL struct config +{ + UBYTE cfgBuffers; /* number of buffers in the system */ + UBYTE cfgFiles; /* number of available files */ + UBYTE cfgFcbs; /* number of available FCBs */ + UBYTE cfgProtFcbs; /* number of protected FCBs */ + BYTE cfgInit[NAMEMAX]; /* init of command.com */ + BYTE cfgInitTail[NAMEMAX]; /* command.com's tail */ + BYTE cfgLastdrive; /* last drive */ + BYTE cfgStacks; /* number of stacks */ + UWORD cfgStackSize; /* stacks size for each stack */ +} +Config +#ifdef MAIN += +{ + NUMBUFF, + NFILES, + NFCBS, + 0, + "command.com", + " /P\r\n", + NLAST, + NSTACKS, + 128 +}; +#else +; +#endif + +/* */ +/* Function prototypes - automatically generated */ +/* */ +#include "proto.h" + +/* Process related functions - not under automatic generation. */ +/* Typically, these are in ".asm" files. */ +VOID +FAR cpm_entry(VOID), +INRPT FAR re_entry(VOID) /*, + INRPT FAR handle_break(VOID) */ ; +VOID +enable(VOID), +disable(VOID); +COUNT +CriticalError( + COUNT nFlag, COUNT nDrive, COUNT nError, struct dhdr FAR * lpDevice); + +#ifdef PROTO +VOID FAR CharMapSrvc(VOID); +VOID FAR set_stack(VOID); +VOID FAR restore_stack(VOID); +#ifndef IN_INIT_MOD +VOID execrh(request FAR *, struct dhdr FAR *); +#endif +VOID FAR init_call_execrh(request FAR *, struct dhdr FAR *); +VOID exit(COUNT); +/*VOID INRPT FAR handle_break(VOID); */ +VOID tmark(VOID); +BOOL tdelay(LONG); +BYTE FAR *device_end(VOID); +COUNT kb_data(VOID); +COUNT kb_input(VOID); +COUNT kb_init(VOID); +VOID setvec(UWORD, VOID(INRPT FAR *) ()); +BYTE FAR *getvec(UWORD); +COUNT con(COUNT); +VOID getdirent(BYTE FAR *, struct dirent FAR *); +VOID putdirent(struct dirent FAR *, BYTE FAR *); +#else +VOID FAR CharMapSrvc(); +VOID FAR set_stack(); +VOID FAR restore_stack(); +VOID execrh(); +VOID exit(); +/*VOID INRPT FAR handle_break(); */ +VOID tmark(); +BOOL tdelay(); +BYTE FAR *device_end(); +COUNT kb_data(); +COUNT kb_input(); +COUNT kb_init(); +VOID setvec(); +BYTE FAR *getvec(); +COUNT con(); +VOID getdirent(); +VOID putdirent(); +#endif + +/* */ +/* special word packing prototypes */ +/* */ +#ifdef NATIVE +#define getlong(vp, lp) (*(LONG *)(lp)=*(LONG *)(vp)) +#define getword(vp, wp) (*(WORD *)(wp)=*(WORD *)(vp)) +#define getbyte(vp, bp) (*(BYTE *)(bp)=*(BYTE *)(vp)) +#define fgetlong(vp, lp) (*(LONG FAR *)(lp)=*(LONG FAR *)(vp)) +#define fgetword(vp, wp) (*(WORD FAR *)(wp)=*(WORD FAR *)(vp)) +#define fgetbyte(vp, bp) (*(BYTE FAR *)(bp)=*(BYTE FAR *)(vp)) +#define fputlong(lp, vp) (*(LONG FAR *)(vp)=*(LONG FAR *)(lp)) +#define fputword(wp, vp) (*(WORD FAR *)(vp)=*(WORD FAR *)(wp)) +#define fputbyte(bp, vp) (*(BYTE FAR *)(vp)=*(BYTE FAR *)(bp)) +#else +#ifdef PROTO +VOID getword(VOID *, WORD *); +VOID getbyte(VOID *, BYTE *); +VOID fgetlong(VOID FAR *, LONG FAR *); +VOID fgetword(VOID FAR *, WORD FAR *); +VOID fgetbyte(VOID FAR *, BYTE FAR *); +VOID fputlong(LONG FAR *, VOID FAR *); +VOID fputword(WORD FAR *, VOID FAR *); +VOID fputbyte(BYTE FAR *, VOID FAR *); +#else +VOID getword(); +VOID getbyte(); +VOID fgetlong(); +VOID fgetword(); +VOID fgetbyte(); +VOID fputlong(); +VOID fputword(); +VOID fputbyte(); +#endif +#endif + +#ifdef I86 +#define setvec(n, isr) (void)(*(VOID (INRPT FAR * FAR *)())(4 * (n)) = (isr)) +#endif +#define is_leap_year(y) ((y) & 3 ? 0 : (y) % 100 ? 1 : (y) % 400 ? 1 : 0) + +/* ^Break handling */ +void spawn_int23(void); /* procsupt.asm */ +int control_break(void); /* break.c */ +void handle_break(void); /* break.c */ + + diff --git a/kernel/init-mod.h b/kernel/init-mod.h new file mode 100644 index 0000000..29f0411 --- /dev/null +++ b/kernel/init-mod.h @@ -0,0 +1,28 @@ +/* Used by `proto.h'. */ +#define IN_INIT_MOD +/* + * The null macro `INIT' can be used to allow the reader to differentiate + * between functions defined in `INIT_TEXT' and those defined in `_TEXT'. + */ +#define INIT +/* + * Functions in `INIT_TEXT' may need to call functions in `_TEXT'. The entry + * calls for the latter functions therefore need to be wrapped up with far + * entry points. + */ +#define DosExec init_call_DosExec +#define DosMemAlloc init_call_DosMemAlloc +#define dos_close init_call_dos_close +#define dos_getdate init_call_dos_getdate +#define dos_gettime init_call_dos_gettime +#define dos_open init_call_dos_open +#define dos_read init_call_dos_read +#define execrh init_call_execrh +#define fatal init_call_fatal +#define fbcopy init_call_fbcopy +#define printf init_call_printf +#define scopy init_call_scopy +#define sti init_call_sti +#define strcmp init_call_strcmp +#define strlen init_call_strlen +#define WritePCClock init_call_WritePCClock diff --git a/kernel/initoem.c b/kernel/initoem.c new file mode 100644 index 0000000..f16e1dd --- /dev/null +++ b/kernel/initoem.c @@ -0,0 +1,105 @@ +/****************************************************************/ +/* */ +/* initoem.c */ +/* */ +/* OEM Initializattion Functions */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/* */ +/****************************************************************/ + +#include "init-mod.h" + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:18 jhall1 + * Initial revision + * + * Revision 1.3 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.2 1999/08/25 03:18:08 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.1.1.1 1999/03/29 15:40:58 jprice + * New version without IPL.SYS + * + * Revision 1.5 1999/02/08 05:55:57 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.3 1999/01/30 08:28:11 jprice + * Clean up; Fixed bug with set attribute function. + * + * Revision 1.2 1999/01/22 04:13:26 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.4 04 Jan 1998 23:15:16 patv + * Changed Log for strip utility + * + * Rev 1.3 29 May 1996 21:03:48 patv + * bug fixes for v0.91a + * + * Rev 1.2 19 Feb 1996 3:21:34 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.1 01 Sep 1995 17:54:16 patv + * First GPL release. + * + * Rev 1.0 02 Jul 1995 8:31:54 patv + * Initial revision. + */ + +#ifdef __TURBOC__ +void __int__(int); /* TC 2.01 requires this. :( -- ror4 */ +#endif + +UWORD init_oem(void) +{ + UWORD top_k; + +#ifndef __TURBOC__ + _asm + { + int 12 h + mov top_k, + ax + } +#else + __int__(0x12); + top_k = _AX; +#endif + return top_k; +} diff --git a/kernel/int2f.asm b/kernel/int2f.asm new file mode 100644 index 0000000..4b7806f --- /dev/null +++ b/kernel/int2f.asm @@ -0,0 +1,232 @@ +; +; File: +; int2f.asm +; Description: +; multiplex interrupt support code +; +; Copyright (c) 1996, 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: D:/dos-c/src/kernel/int2f.asv $ +; +; $Id$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:35:18 jhall1 +; Initial revision +; +; Revision 1.3 2000/03/09 06:07:11 kernel +; 2017f updates by James Tabor +; +; Revision 1.2 1999/08/10 17:57:12 jprice +; ror4 2011-02 patch +; +; Revision 1.1.1.1 1999/03/29 15:40:59 jprice +; New version without IPL.SYS +; +; Revision 1.4 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; Revision 1.3 1999/02/01 01:48:41 jprice +; Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) +; +; Revision 1.2 1999/01/22 04:13:26 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:01 jprice +; Imported sources +; +; +; Rev 1.2 06 Dec 1998 8:48:12 patv +; Bug fixes. +; +; Rev 1.1 29 May 1996 21:03:46 patv +; bug fixes for v0.91a +; +; Rev 1.0 19 Feb 1996 3:34:38 patv +; Initial revision. +; $EndLog$ +; + + %include "segs.inc" + +segment _TEXT + extern _nul_dev:wrt DGROUP + + global _int2f_handler +_int2f_handler: + sti ; Enable interrupts + cmp ah,11h ; Network interrupt? + jne Int2f3 ; No, continue +Int2f1: + or al,al ; Installation check? + jz FarTabRetn ; yes, just return +Int2f2: + stc +FarTabRetn: + retf 2 ; Return far +Int2f3: + cmp ah,16h + je FarTabRetn ; Win Hook return fast + cmp ah,12h + je IntDosCal ; Dos Internal calls + cmp ah,10h ; SHARE.EXE interrupt? + je Int2f1 ; yes, do installation check + cmp ah,14h ; NLSFUNC.EXE interrupt? + je Int2f1 ; yes, do installation check + iret ; Default, interrupt return + +; +; added by James Tabor For Zip Drives +;Return Null Device Pointer +IntDosCal: + cmp al,02ch + jne Int2f2 + mov ax,_nul_dev + mov bx,seg _nul_dev + clc + jmp FarTabRetn + +; Int 2F Multipurpose Remote System Calls +; +; added by James Tabor jimtabor@infohwy.com +; +; int_2f_Remote_call(ax,bx,cx,dx,[es:di],si, return data * ptr) +; assume ss == ds after setup of stack in entry +; sumtimes return data *ptr is the push stack word +; + global _int2f_Remote_call +_int2f_Remote_call: + push bp + mov bp,sp + push es + push ds + push si + push di + push dx + push cx + push bx + + push ss ; hay, did I say assume + pop ds + + mov si,[bp+16] + les di,[bp+12] + mov dx,[bp+10] + mov cx,[bp+8] + mov bx,[bp+6] + mov ax,[bp+4] + + cmp al,08h ; R/W Remote File + je short int2f_r_1 + cmp al,09h + jne short int2f_r_2 +int2f_r_1: + call int2f_call + jc int2f_rfner + les di,[bp+18] ; do return data stuff + mov [es:di],cx + jmp short int2f_rfner +int2f_r_2: + cmp al,0ch ; Get Remote DPB + jne short int2f_r_3 + call int2f_call + jc int2f_rfner + les di,[bp+18] + mov [es:di+0],ax + mov [es:di+2],bx + mov [es:di+4],cx + mov [es:di+6],dx + jmp short int2f_rfner +int2f_r_3: + cmp al,0fh ; Get Remote File Attrib + jne short int2f_r_4 + call int2f_call + jc short int2f_rfner + mov si,di + les di,[bp+18] ; pointer to struct + mov [es:di+0],ax + mov [es:di+2],si ; lo + mov [es:di+4],bx ; high + mov [es:di+6],cx + mov [es:di+8],dx + mov ax,0000h + jmp short int2f_rfner +int2f_r_4: + cmp al,01eh + je short int2f_r_5 + cmp al,01fh + jne short int2f_r_6 +int2f_r_5: + push ds + push word [bp+20] + pop ds + call int2f_call + pop ds + jmp short int2f_rfner +int2f_r_6: +; +; everything else goes through here. +; + call int2f_call +int2f_rfner: + pop bx + pop cx + pop dx + pop di + pop si + pop ds + pop es + pop bp + ret +; +; Pull this one out of the Chain. +; + global _QRemote_Fn +_QRemote_Fn + push bp + mov bp,sp + push es + push ds + push si + push di + mov ax,1123h + lds si,[bp+4] + les di,[bp+8] + stc + int 2fh + pop di + pop si + pop ds + pop es + pop bp + ret + + +int2f_call: + push bp + push word [bp+18] ; very fakey, HaHa ;) + stc ; set to fail + int 2fh + pop bp + pop bp + ret + diff --git a/kernel/inthndlr.c b/kernel/inthndlr.c new file mode 100644 index 0000000..af5b30b --- /dev/null +++ b/kernel/inthndlr.c @@ -0,0 +1,1702 @@ +/****************************************************************/ +/* */ +/* inthndlr.c */ +/* */ +/* Interrupt Handler and Function dispatcher for Kernel */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/* */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:19 jhall1 + * Initial revision + * + * Revision 1.19 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.18 1999/09/23 04:40:47 jprice + * *** empty log message *** + * + * Revision 1.13 1999/09/14 01:18:36 jprice + * ror4: fix int25 & 26 are not cached. + * + * Revision 1.12 1999/09/13 22:16:47 jprice + * Fix 210B function + * + * Revision 1.11 1999/08/25 03:18:08 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.10 1999/08/10 18:07:57 jprice + * ror4 2011-04 patch + * + * Revision 1.9 1999/08/10 18:03:43 jprice + * ror4 2011-03 patch + * + * Revision 1.8 1999/05/03 06:25:45 jprice + * Patches from ror4 and many changed of signed to unsigned variables. + * + * Revision 1.7 1999/04/23 04:24:39 jprice + * Memory manager changes made by ska + * + * Revision 1.6 1999/04/16 12:21:22 jprice + * Steffen c-break handler changes + * + * Revision 1.5 1999/04/11 04:33:39 jprice + * ror4 patches + * + * Revision 1.3 1999/04/04 22:57:47 jprice + * no message + * + * Revision 1.2 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:41:04 jprice + * New version without IPL.SYS + * + * Revision 1.9 1999/03/23 23:38:49 jprice + * Now sets carry when we don't support a function + * + * Revision 1.8 1999/03/02 07:02:55 jprice + * Added some comments. Fixed some minor bugs. + * + * Revision 1.7 1999/03/01 05:45:08 jprice + * Added some DEBUG ifdef's so that it will compile without DEBUG defined. + * + * Revision 1.6 1999/02/08 05:55:57 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.5 1999/02/04 03:11:07 jprice + * Formating + * + * Revision 1.4 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.3 1999/01/30 08:28:11 jprice + * Clean up; Fixed bug with set attribute function. + * + * Revision 1.2 1999/01/22 04:13:26 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * + * Rev 1.14 06 Dec 1998 8:47:38 patv + * Expanded due to improved int 21h handler code. + * + * Rev 1.13 07 Feb 1998 20:38:46 patv + * Modified stack fram to match DOS standard + * + * Rev 1.12 22 Jan 1998 4:09:26 patv + * Fixed pointer problems affecting SDA + * + * Rev 1.11 06 Jan 1998 20:13:18 patv + * Broke apart int21_system from int21_handler. + * + * Rev 1.10 04 Jan 1998 23:15:22 patv + * Changed Log for strip utility + * + * Rev 1.9 04 Jan 1998 17:26:16 patv + * Corrected subdirectory bug + * + * Rev 1.8 03 Jan 1998 8:36:48 patv + * Converted data area to SDA format + * + * Rev 1.7 01 Aug 1997 2:00:10 patv + * COMPATIBILITY: Added return '$' in AL for function int 21h fn 09h + * + * Rev 1.6 06 Feb 1997 19:05:54 patv + * Added hooks for tsc command + * + * Rev 1.5 22 Jan 1997 13:18:32 patv + * pre-0.92 Svante Frey bug fixes. + * + * Rev 1.4 16 Jan 1997 12:46:46 patv + * pre-Release 0.92 feature additions + * + * Rev 1.3 29 May 1996 21:03:40 patv + * bug fixes for v0.91a + * + * Rev 1.2 19 Feb 1996 3:21:48 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.1 01 Sep 1995 17:54:20 patv + * First GPL release. + * + * Rev 1.0 02 Jul 1995 8:33:34 patv + * Initial revision. + */ + +#ifdef TSC +static VOID StartTrace(VOID); +static bTraceNext = FALSE; +#endif + +/* Special entry for far call into the kernel */ +#pragma argsused +VOID FAR int21_entry(iregs UserRegs) +{ + int21_handler(UserRegs); +} + +/* Normal entry. This minimizes user stack usage by avoiding local */ +/* variables needed for the rest of the handler. */ +VOID int21_syscall(iregs FAR * irp) +{ + Int21AX = irp->AX; + + switch (irp->AH) + { + /* DosVars - get/set dos variables */ + case 0x33: + switch (irp->AL) + { + /* Get Ctrl-C flag */ + case 0x00: + irp->DL = break_ena ? TRUE : FALSE; + break; + + /* Set Ctrl-C flag */ + case 0x01: + break_ena = irp->DL ? TRUE : FALSE; + break; + + /* Get Boot Drive */ + case 0x05: + irp->DL = BootDrive; + break; + + /* Get DOS-C version */ + case 0x06: + irp->BL = os_major; + irp->BH = os_minor; + irp->DL = rev_number; + irp->DH = version_flags; + break; + + default: + irp->AX = -DE_INVLDFUNC; + irp->FLAGS |= FLG_CARRY; + break; + + /* Toggle DOS-C rdwrblock trace dump */ + case 0xfd: +#ifdef DEBUG + bDumpRdWrParms = !bDumpRdWrParms; +#endif + break; + + /* Toggle DOS-C syscall trace dump */ + case 0xfe: +#ifdef DEBUG + bDumpRegs = !bDumpRegs; +#endif + break; + + /* Get DOS-C release string pointer */ + case 0xff: + irp->DX = FP_SEG(os_release); + irp->AX = FP_OFF(os_release); + break; + } + break; + + /* Set PSP */ + case 0x50: + cu_psp = irp->BX; + break; + + /* Get PSP */ + case 0x51: + irp->BX = cu_psp; + break; + + /* UNDOCUMENTED: return current psp */ + case 0x62: + irp->BX = cu_psp; + break; + + /* Normal DOS function - switch stacks */ + default: + int21_service(user_r); + break; + } +} + +VOID int21_service(iregs FAR * r) +{ + COUNT rc, + rc1; + ULONG lrc; + psp FAR *p = MK_FP(cu_psp, 0); + + p->ps_stack = (BYTE FAR *) r; + +#ifdef DEBUG + if (bDumpRegs) + { + fbcopy((VOID FAR *) user_r, (VOID FAR *) & error_regs, sizeof(iregs)); + printf("System call (21h): %02x\n", user_r->AX); + dump_regs = TRUE; + dump(); + } +#endif + +dispatch: + + /* Check for Ctrl-Break */ + switch (r->AH) + { + default: + if (!break_ena) + break; + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + if (control_break()) + handle_break(); + } + + /* The dispatch handler */ + switch (r->AH) + { + /* int 21h common error handler */ + case 0x64: + case 0x6b: + default: + error_invalid: + r->AX = -DE_INVLDFUNC; + goto error_out; + error_exit: + r->AX = -rc; + error_out: + r->FLAGS |= FLG_CARRY; + break; + +#if 0 + /* Moved to simulate a 0x4c00 -- 1999/04/21 ska */ + /* Terminate Program */ + case 0x00: + if (cu_psp == RootPsp) + break; + else if (((psp FAR *) (MK_FP(cu_psp, 0)))->ps_parent == cu_psp) + break; + tsr = FALSE; + return_mode = break_flg ? 1 : 0; + return_code = r->AL; + if (DosMemCheck() != SUCCESS) + panic("MCB chain corrupted"); +#ifdef TSC + StartTrace(); +#endif + return_user(); + break; +#endif + + /* Read Keyboard with Echo */ + case 0x01: + Do_DosIdle_loop(); + r->AL = _sti(); + sto(r->AL); + break; + + /* Display Character */ + case 0x02: + sto(r->DL); + break; + + /* Auxiliary Input */ + case 0x03: + r->AL = _sti(); + break; + + /* Auxiliary Output */ + case 0x04: + sto(r->DL); + break; + + /* Print Character */ + case 0x05: + sto(r->DL); + break; + + /* Direct Cosole I/O */ + case 0x06: + if (r->DL != 0xff) + sto(r->DL); + else if (StdinBusy()) + { + r->AL = 0x00; + r->FLAGS |= FLG_ZERO; + } + else + { + r->FLAGS &= ~FLG_ZERO; + r->AL = _sti(); + } + break; + + /* Direct Console Input */ + case 0x07: + /* Read Keyboard Without Echo */ + case 0x08: + Do_DosIdle_loop(); + r->AL = _sti(); + break; + + /* Display String */ + case 0x09: + { + static COUNT scratch; + BYTE FAR *p = MK_FP(r->DS, r->DX), + FAR * q; + q = p; + while (*q != '$') + ++q; + DosWrite(STDOUT, q - p, p, (COUNT FAR *) & scratch); + } + r->AL = '$'; + break; + + /* Buffered Keyboard Input */ + case 0x0a: + ((keyboard FAR *) MK_FP(r->DS, r->DX))->kb_count = 0; + sti((keyboard FAR *) MK_FP(r->DS, r->DX)); + ((keyboard FAR *) MK_FP(r->DS, r->DX))->kb_count -= 2; + break; + + /* Check Stdin Status */ + case 0x0b: + if (StdinBusy()) + r->AL = 0xFF; + else + r->AL = 0x00; + break; + + /* Flush Buffer, Read Keayboard */ + case 0x0c: + KbdFlush(); + switch (r->AL) + { + case 0x01: + case 0x06: + case 0x07: + case 0x08: + case 0x0a: + r->AH = r->AL; + goto dispatch; + + default: + r->AL = 0x00; + break; + } + break; + + /* Reset Drive */ + case 0x0d: + flush(); + break; + + /* Set Default Drive */ + case 0x0e: + r->AL = DosSelectDrv(r->DL); + break; + + case 0x0f: + if (FcbOpen(MK_FP(r->DS, r->DX))) + r->AL = 0; + else + r->AL = 0xff; + break; + + case 0x10: + if (FcbClose(MK_FP(r->DS, r->DX))) + r->AL = 0; + else + r->AL = 0xff; + break; + + case 0x11: + if (FcbFindFirst(MK_FP(r->DS, r->DX))) + r->AL = 0; + else + r->AL = 0xff; + break; + + case 0x12: + if (FcbFindNext(MK_FP(r->DS, r->DX))) + r->AL = 0; + else + r->AL = 0xff; + break; + + case 0x13: + if (FcbDelete(MK_FP(r->DS, r->DX))) + r->AL = 0; + else + r->AL = 0xff; + break; + + case 0x14: + { + COUNT nErrorCode; + + if (FcbRead(MK_FP(r->DS, r->DX), &nErrorCode)) + r->AL = 0; + else + r->AL = nErrorCode; + break; + } + + case 0x15: + { + COUNT nErrorCode; + + if (FcbWrite(MK_FP(r->DS, r->DX), &nErrorCode)) + r->AL = 0; + else + r->AL = nErrorCode; + break; + } + + case 0x16: + if (FcbCreate(MK_FP(r->DS, r->DX))) + r->AL = 0; + else + r->AL = 0xff; + break; + + case 0x17: + if (FcbRename(MK_FP(r->DS, r->DX))) + r->AL = 0; + else + r->AL = 0xff; + break; + + /* CP/M compatibility functions */ + case 0x18: + case 0x1d: + case 0x1e: + case 0x20: +#ifndef TSC + case 0x61: +#endif + r->AL = 0; + break; + + /* Get Default Drive */ + case 0x19: + r->AL = default_drive; + break; + + /* Set DTA */ + case 0x1a: + { + psp FAR *p = MK_FP(cu_psp, 0); + + p->ps_dta = MK_FP(r->DS, r->DX); + dos_setdta(p->ps_dta); + } + break; + + /* Get Default Drive Data */ + case 0x1b: + { + BYTE FAR *p; + + FatGetDrvData(0, + (COUNT FAR *) & r->AX, + (COUNT FAR *) & r->CX, + (COUNT FAR *) & r->DX, + (BYTE FAR **) & p); + r->DS = FP_SEG(p); + r->BX = FP_OFF(p); + } + break; + + /* Get Drive Data */ + case 0x1c: + { + BYTE FAR *p; + + FatGetDrvData(r->DL, + (COUNT FAR *) & r->AX, + (COUNT FAR *) & r->CX, + (COUNT FAR *) & r->DX, + (BYTE FAR **) & p); + r->DS = FP_SEG(p); + r->BX = FP_OFF(p); + } + break; + + /* Get default DPB */ + case 0x1f: + if (default_drive < lastdrive) + { + struct dpb FAR *dpb = (struct dpb FAR *)CDSp->cds_table[default_drive].cdsDpb; + if (dpb == 0) + { + r->AL = 0xff; + break; + } + + r->DS = FP_SEG(dpb); + r->BX = FP_OFF(dpb); + r->AL = 0; + } + else + r->AL = 0xff; + break; + + /* Random read using FCB */ + case 0x21: + { + COUNT nErrorCode; + + if (FcbRandomRead(MK_FP(r->DS, r->DX), &nErrorCode)) + r->AL = 0; + else + r->AL = nErrorCode; + break; + } + + /* Random write using FCB */ + case 0x22: + { + COUNT nErrorCode; + + if (FcbRandomWrite(MK_FP(r->DS, r->DX), &nErrorCode)) + r->AL = 0; + else + r->AL = nErrorCode; + break; + } + + /* Get file size in records using FCB */ + case 0x23: + if (FcbGetFileSize(MK_FP(r->DS, r->DX))) + r->AL = 0; + else + r->AL = 0xff; + break; + + /* Set random record field in FCB */ + case 0x24: + FcbSetRandom(MK_FP(r->DS, r->DX)); + break; + + /* Set Interrupt Vector */ + case 0x25: + { + VOID(INRPT FAR * p) () = MK_FP(r->DS, r->DX); + + setvec(r->AL, p); + } + break; + + /* Dos Create New Psp */ + case 0x26: + { + psp FAR *p = MK_FP(cu_psp, 0); + + new_psp((psp FAR *) MK_FP(r->DX, 0), p->ps_size); + } + break; + + /* Read random record(s) using FCB */ + case 0x27: + { + COUNT nErrorCode; + + if (FcbRandomBlockRead(MK_FP(r->DS, r->DX), r->CX, &nErrorCode)) + r->AL = 0; + else + r->AL = nErrorCode; + break; + } + + /* Write random record(s) using FCB */ + case 0x28: + { + COUNT nErrorCode; + + if (FcbRandomBlockWrite(MK_FP(r->DS, r->DX), r->CX, &nErrorCode)) + r->AL = 0; + else + r->AL = nErrorCode; + break; + } + + /* Parse File Name */ + case 0x29: + { + BYTE FAR *lpFileName; + + lpFileName = MK_FP(r->DS, r->SI); + r->AL = FcbParseFname(r->AL, + &lpFileName, + MK_FP(r->ES, r->DI)); + r->DS = FP_SEG(lpFileName); + r->SI = FP_OFF(lpFileName); + } + break; + + /* Get Date */ + case 0x2a: + DosGetDate( + (BYTE FAR *) & (r->AL), /* WeekDay */ + (BYTE FAR *) & (r->DH), /* Month */ + (BYTE FAR *) & (r->DL), /* MonthDay */ + (COUNT FAR *) & (r->CX)); /* Year */ + break; + + /* Set Date */ + case 0x2b: + rc = DosSetDate( + (BYTE FAR *) & (r->DH), /* Month */ + (BYTE FAR *) & (r->DL), /* MonthDay */ + (COUNT FAR *) & (r->CX)); /* Year */ + if (rc != SUCCESS) + r->AL = 0xff; + else + r->AL = 0; + break; + + /* Get Time */ + case 0x2c: + DosGetTime( + (BYTE FAR *) & (r->CH), /* Hour */ + (BYTE FAR *) & (r->CL), /* Minutes */ + (BYTE FAR *) & (r->DH), /* Seconds */ + (BYTE FAR *) & (r->DL)); /* Hundredths */ + break; + + /* Set Date */ + case 0x2d: + rc = DosSetTime( + (BYTE FAR *) & (r->CH), /* Hour */ + (BYTE FAR *) & (r->CL), /* Minutes */ + (BYTE FAR *) & (r->DH), /* Seconds */ + (BYTE FAR *) & (r->DL)); /* Hundredths */ + if (rc != SUCCESS) + r->AL = 0xff; + else + r->AL = 0; + break; + + /* Set verify flag */ + case 0x2e: + verify_ena = (r->AL ? TRUE : FALSE); + break; + + /* Get DTA */ + case 0x2f: + r->ES = FP_SEG(dta); + r->BX = FP_OFF(dta); + break; + + /* Get DOS Version */ + case 0x30: + r->AL = os_major; + r->AH = os_minor; + r->BH = OEM_ID; + r->CH = REVISION_MAJOR; /* JPP */ + r->CL = REVISION_MINOR; + r->BL = REVISION_SEQ; + break; + + /* Keep Program (Terminate and stay resident) */ + case 0x31: + DosMemChange(cu_psp, r->DX < 6 ? 6 : r->DX, 0); + return_mode = 3; + return_code = r->AL; + tsr = TRUE; + return_user(); + break; + + /* Get DPB */ + case 0x32: + if (r->DL < lastdrive) + { + struct dpb FAR *dpb = CDSp->cds_table[r->DL].cdsDpb; + if (dpb == 0) + { + r->AL = 0xff; + break; + } + r->DS = FP_SEG(dpb); + r->BX = FP_OFF(dpb); + r->AL = 0; + } + else + r->AL = 0xFF; + break; + + /* Get InDOS flag */ + case 0x34: + { + BYTE FAR *p; + + p = (BYTE FAR *) ((BYTE *) & InDOS); + r->ES = FP_SEG(p); + r->BX = FP_OFF(p); + } + break; + + /* Get Interrupt Vector */ + case 0x35: + { + BYTE FAR *p; + + p = getvec((COUNT) r->AL); + r->ES = FP_SEG(p); + r->BX = FP_OFF(p); + } + break; + + /* Dos Get Disk Free Space */ + case 0x36: + DosGetFree( + (COUNT) r->DL, + (COUNT FAR *) & r->AX, + (COUNT FAR *) & r->BX, + (COUNT FAR *) & r->CX, + (COUNT FAR *) & r->DX); + break; + + /* Undocumented Get/Set Switchar */ + case 0x37: + switch (r->AL) + { + /* Get switch character */ + case 0x00: + r->DL = switchar; + r->AL = 0x00; + break; + + /* Set switch character */ + case 0x01: + switchar = r->DL; + r->AL = 0x00; + break; + + default: + goto error_invalid; + } + break; + + /* Get/Set Country Info */ + case 0x38: + { + BYTE FAR *lpTable + = (BYTE FAR *) MK_FP(r->DS, r->DX); + BYTE nRetCode; + + if (0xffff == r->DX) + { + r->BX = SetCtryInfo( + (UBYTE FAR *) & (r->AL), + (UWORD FAR *) & (r->BX), + (BYTE FAR *) & lpTable, + (UBYTE *) & nRetCode); + + if (nRetCode != 0) + { + r->AX = 0xff; + r->FLAGS |= FLG_CARRY; + } + else + { + r->AX = nRetCode; + r->FLAGS &= ~FLG_CARRY; + } + } + else + { + r->BX = GetCtryInfo(&(r->AL), &(r->BX), lpTable); + r->FLAGS &= ~FLG_CARRY; + } + } + break; + + /* Dos Create Directory */ + case 0x39: + rc = dos_mkdir((BYTE FAR *) MK_FP(r->DS, r->DX)); + if (rc != SUCCESS) + goto error_exit; + else + { + r->FLAGS &= ~FLG_CARRY; + } + break; + + /* Dos Remove Directory */ + case 0x3a: + rc = dos_rmdir((BYTE FAR *) MK_FP(r->DS, r->DX)); + if (rc != SUCCESS) + goto error_exit; + else + { + r->FLAGS &= ~FLG_CARRY; + } + break; + + /* Dos Change Directory */ + case 0x3b: + if ((rc = DosChangeDir((BYTE FAR *) MK_FP(r->DS, r->DX))) < 0) + goto error_exit; + else + { + r->FLAGS &= ~FLG_CARRY; + } + break; + + /* Dos Create File */ + case 0x3c: + if ((rc = DosCreat(MK_FP(r->DS, r->DX), r->CX)) < 0) + goto error_exit; + else + { + r->AX = rc; + r->FLAGS &= ~FLG_CARRY; + } + break; + + /* Dos Open */ + case 0x3d: + if ((rc = DosOpen(MK_FP(r->DS, r->DX), r->AL)) < 0) + goto error_exit; + else + { + r->AX = rc; + r->FLAGS &= ~FLG_CARRY; + } + break; + + /* Dos Close */ + case 0x3e: + if ((rc = DosClose(r->BX)) < 0) + goto error_exit; + else + r->FLAGS &= ~FLG_CARRY; + break; + + /* Dos Read */ + case 0x3f: + rc = DosRead(r->BX, r->CX, MK_FP(r->DS, r->DX), (COUNT FAR *) & rc1); + + if (rc1 != SUCCESS) + { + r->FLAGS |= FLG_CARRY; + r->AX = -rc1; + } + else + { + r->FLAGS &= ~FLG_CARRY; + r->AX = rc; + } + break; + + /* Dos Write */ + case 0x40: + rc = DosWrite(r->BX, r->CX, MK_FP(r->DS, r->DX), (COUNT FAR *) & rc1); + if (rc1 != SUCCESS) + { + r->FLAGS |= FLG_CARRY; + r->AX = -rc1; + } + else + { + r->FLAGS &= ~FLG_CARRY; + r->AX = rc; + } + break; + + /* Dos Delete File */ + case 0x41: + rc = dos_delete((BYTE FAR *) MK_FP(r->DS, r->DX)); + if (rc < 0) + { + r->FLAGS |= FLG_CARRY; + r->AX = -rc1; + } + else + r->FLAGS &= ~FLG_CARRY; + break; + + /* Dos Seek */ + case 0x42: + if ((rc = DosSeek(r->BX, (LONG) ((((LONG) (r->CX)) << 16) + r->DX), r->AL, &lrc)) < 0) + goto error_exit; + else + { + r->DX = (lrc >> 16); + r->AX = lrc & 0xffff; + r->FLAGS &= ~FLG_CARRY; + } + break; + + /* Get/Set File Attributes */ + case 0x43: + switch (r->AL) + { + case 0x00: + rc = DosGetFattr((BYTE FAR *) MK_FP(r->DS, r->DX), (UWORD FAR *) & r->CX); + if (rc < SUCCESS) + goto error_exit; + else + { + r->FLAGS &= ~FLG_CARRY; + } + break; + + case 0x01: + rc = DosSetFattr((BYTE FAR *) MK_FP(r->DS, r->DX), (UWORD FAR *) & r->CX); + if (rc != SUCCESS) + goto error_exit; + else + r->FLAGS &= ~FLG_CARRY; + break; + + default: + goto error_invalid; + } + break; + + /* Device I/O Control */ + case 0x44: + { + rc = DosDevIOctl(r, (COUNT FAR *) & rc1); + + if (rc1 != SUCCESS) + { + r->FLAGS |= FLG_CARRY; + r->AX = -rc1; + } + else + { + r->FLAGS &= ~FLG_CARRY; + } + } + break; + + /* Duplicate File Handle */ + case 0x45: + rc = DosDup(r->BX); + if (rc < SUCCESS) + goto error_exit; + else + { + r->FLAGS &= ~FLG_CARRY; + r->AX = rc; + } + break; + + /* Force Duplicate File Handle */ + case 0x46: + rc = DosForceDup(r->BX, r->CX); + if (rc < SUCCESS) + goto error_exit; + else + r->FLAGS &= ~FLG_CARRY; + break; + + /* Get Current Directory */ + case 0x47: + if ((rc = DosGetCuDir(r->DL, MK_FP(r->DS, r->SI))) < 0) + goto error_exit; + else + { + r->FLAGS &= ~FLG_CARRY; + r->AX = 0x0100; /*jpp: from interrupt list */ + } + break; + + /* Allocate memory */ + case 0x48: + if ((rc = DosMemAlloc(r->BX, mem_access_mode, &(r->AX), &(r->BX))) < 0) + { + DosMemLargest(&(r->BX)); + goto error_exit; + } + else + { + ++(r->AX); /* DosMemAlloc() returns seg of MCB rather than data */ + r->FLAGS &= ~FLG_CARRY; + } + break; + + /* Free memory */ + case 0x49: + if ((rc = DosMemFree((r->ES) - 1)) < 0) + goto error_exit; + else + r->FLAGS &= ~FLG_CARRY; + break; + + /* Set memory block size */ + case 0x4a: + { + UWORD maxSize; + + if ((rc = DosMemChange(r->ES, r->BX, &maxSize)) < 0) + { + if (rc == DE_NOMEM) + r->BX = maxSize; + +#if 0 + if (cu_psp == r->ES) + { + + psp FAR *p; + + p = MK_FP(cu_psp, 0); + p->ps_size = r->BX + cu_psp; + } +#endif + goto error_exit; + } + else + r->FLAGS &= ~FLG_CARRY; + + break; + } + + /* Load and Execute Program */ + case 0x4b: + break_flg = FALSE; + + if ((rc = DosExec(r->AL, MK_FP(r->ES, r->BX), MK_FP(r->DS, r->DX))) + != SUCCESS) + goto error_exit; + else + r->FLAGS &= ~FLG_CARRY; + break; + + /* Terminate Program */ + case 0x00: + r->AX = 0x4c00; + + /* End Program */ + case 0x4c: + if (cu_psp == RootPsp + || ((psp FAR *) (MK_FP(cu_psp, 0)))->ps_parent == cu_psp) + break; + tsr = FALSE; +/* int2f_Remote_call(0x1122, 0, 0, 0, 0, 0, 0); + int2f_Remote_call(REM_CLOSEALL, 0, 0, 0, 0, 0, 0); + */ + if (ErrorMode) + { + ErrorMode = FALSE; + return_mode = 2; + } + else if (break_flg) + { + break_flg = FALSE; + return_mode = 1; + } + else + { + return_mode = 0; + } + return_code = r->AL; + if (DosMemCheck() != SUCCESS) + panic("MCB chain corrupted"); +#ifdef TSC + StartTrace(); +#endif + return_user(); + break; + + /* Get Child-program Return Value */ + case 0x4d: + r->AL = return_code; + r->AH = return_mode; + break; + + /* Dos Find First */ + case 0x4e: + { + /* dta for this call is set on entry. This */ + /* needs to be changed for new versions. */ + if ((rc = DosFindFirst((UCOUNT) r->CX, (BYTE FAR *) MK_FP(r->DS, r->DX))) < 0) + goto error_exit; + else + { + r->AX = 0; + r->FLAGS &= ~FLG_CARRY; + } + } + break; + + /* Dos Find Next */ + case 0x4f: + { + /* dta for this call is set on entry. This */ + /* needs to be changed for new versions. */ + if ((rc = DosFindNext()) < 0) + { + r->AX = -rc; + + if (r->AX == 2) + r->AX = 18; + + r->FLAGS |= FLG_CARRY; + } + else + { + r->FLAGS &= ~FLG_CARRY; + } + } + break; + + /* ************UNDOCUMENTED************************************* */ + /* Get List of Lists */ + case 0x52: + { + BYTE FAR *p; + + p = (BYTE FAR *) & DPBp; + r->ES = FP_SEG(p); + r->BX = FP_OFF(p); + } + break; + + /* Get verify state */ + case 0x54: + r->AL = (verify_ena ? TRUE : FALSE); + break; + + /* ************UNDOCUMENTED************************************* */ + /* Dos Create New Psp & set p_size */ + case 0x55: + new_psp((psp FAR *) MK_FP(r->DX, 0), r->SI); + break; + + /* Dos Rename */ + case 0x56: + rc = dos_rename( + (BYTE FAR *) MK_FP(r->DS, r->DX), /* OldName */ + (BYTE FAR *) MK_FP(r->ES, r->DI)); /* NewName */ + if (rc < SUCCESS) + goto error_exit; + else + { + r->FLAGS &= ~FLG_CARRY; + } + break; + + /* Get/Set File Date and Time */ + case 0x57: + switch (r->AL) + { + case 0x00: + rc = DosGetFtime( + (COUNT) r->BX, /* Handle */ + (date FAR *) & r->DX, /* FileDate */ + (time FAR *) & r->CX); /* FileTime */ + if (rc < SUCCESS) + goto error_exit; + else + r->FLAGS &= ~FLG_CARRY; + break; + + case 0x01: + rc = DosSetFtime( + (COUNT) r->BX, /* Handle */ + (date FAR *) & r->DX, /* FileDate */ + (time FAR *) & r->CX); /* FileTime */ + if (rc < SUCCESS) + goto error_exit; + else + r->FLAGS &= ~FLG_CARRY; + break; + + default: + goto error_invalid; + } + break; + + /* Get/Set Allocation Strategy */ + case 0x58: + switch (r->AL) + { + case 0x00: + r->AX = mem_access_mode; + break; + + case 0x01: + if (((COUNT) r->BX) < 0 || r->BX > 2) + goto error_invalid; + else + { + mem_access_mode = r->BX; + r->FLAGS &= ~FLG_CARRY; + } + break; + + default: + goto error_invalid; +#ifdef DEBUG + case 0xff: + show_chain(); + break; +#endif + } + break; + + /* Create Temporary File */ + case 0x5a: + if ((rc = DosMkTmp(MK_FP(r->DS, r->DX), r->CX)) < 0) + goto error_exit; + else + { + r->AX = rc; + r->FLAGS &= ~FLG_CARRY; + } + break; + + /* Create New File */ + case 0x5b: + if ((rc = DosOpen(MK_FP(r->DS, r->DX), 0)) >= 0) + { + DosClose(rc); + r->AX = 80; + r->FLAGS |= FLG_CARRY; + } + else + { + if ((rc = DosCreat(MK_FP(r->DS, r->DX), r->CX)) < 0) + goto error_exit; + else + { + r->AX = rc; + r->FLAGS &= ~FLG_CARRY; + } + } + break; + + /* UNDOCUMENTED: server, share.exe and sda function */ + case 0x5d: + switch (r->AL) + { + /* Remote Server Call */ + case 0x00: + { + UWORD FAR *x = MK_FP(r->DS, r->DX); + r->AX = x[0]; + r->BX = x[1]; + r->CX = x[2]; + r->DX = x[3]; + r->SI = x[4]; + r->DI = x[5]; + r->DS = x[6]; + r->ES = x[7]; + } + goto dispatch; + + case 0x06: + r->DS = FP_SEG(internal_data); + r->SI = FP_OFF(internal_data); + r->CX = swap_always - internal_data; + r->DX = swap_indos - internal_data; + r->FLAGS &= ~FLG_CARRY; + break; + + case 0x07: + case 0x08: + case 0x09: + int2f_Remote_call(REM_PRINTREDIR, 0, 0, r->DX, 0, 0, (MK_FP(0, Int21AX))); + break; + + default: + goto error_invalid; + } + break; + + case 0x5e: + switch (r->AL) + { + case 0x00: + r->CX = get_machine_name(MK_FP(r->DS, r->DX)); + break; + + case 0x01: + set_machine_name(MK_FP(r->DS, r->DX), r->CX); + break; + + default: + int2f_Remote_call(REM_PRINTSET, r->BX, r->CX, r->DX, (MK_FP(r->ES, r->DI)), r->SI, (MK_FP(r->DS, Int21AX))); + break; + } + break; + + case 0x5f: + switch (r->AL) + { + case 0x07: + CDSp->cds_table[r->DL].cdsFlags |= 0x100; + break; + + case 0x08: + CDSp->cds_table[r->DL].cdsFlags &= ~0x100; + break; + + default: + int2f_Remote_call(REM_DOREDIRECT, r->BX, r->CX, r->DX, (MK_FP(r->ES, r->DI)), r->SI, (MK_FP(r->DS, Int21AX))); + break; + } + break; + + case 0x60: /* TRUENAME */ + if ((rc = truename(MK_FP(r->DS, r->SI), + adjust_far(MK_FP(r->ES, r->DI)), TRUE)) != SUCCESS) + goto error_exit; + else + { + r->FLAGS &= ~FLG_CARRY; + } + break; + +#ifdef TSC + /* UNDOCUMENTED: no-op */ + /* */ + /* DOS-C: tsc support */ + case 0x61: +#ifdef DEBUG + switch (r->AL) + { + case 0x01: + bTraceNext = TRUE; + break; + + case 0x02: + bDumpRegs = FALSE; + break; + } +#endif + r->AL = 0x00; + break; +#endif + + /* UNDOCUMENTED: return current psp */ + case 0x62: + r->BX = cu_psp; + break; + + /* UNDOCUMENTED: Double byte and korean tables */ + case 0x63: + { +#ifdef DBLBYTE + static char dbcsTable[2] = + { + 0, 0 + }; + void FAR *dp = &dbcsTable; + + r->DS = FP_SEG(dp); + r->SI = FP_OFF(dp); + r->AL = 0; +#else + /* not really supported, but will pass. */ + r->AL = 0x00; /*jpp: according to interrupt list */ +#endif + break; + } + + /* Extended country info */ + case 0x65: + if (r->AL <= 0x7) + { + if (ExtCtryInfo( + r->AL, + r->BX, + r->CX, + MK_FP(r->ES, r->DI))) + r->FLAGS &= ~FLG_CARRY; + else + goto error_invalid; + } + else if ((r->AL >= 0x20) && (r->AL <= 0x22)) + { + switch (r->AL) + { + case 0x20: + r->DL = upChar(r->DL); + goto okay; + + case 0x21: + upMem( + MK_FP(r->DS, r->DX), + r->CX); + goto okay; + + case 0x22: + upString(MK_FP(r->DS, r->DX)); + okay: + r->FLAGS &= ~FLG_CARRY; + break; + + case 0x23: + r->AX = yesNo(r->DL); + goto okay; + + default: + goto error_invalid; + } + } + else + r->FLAGS |= FLG_CARRY; + break; + + /* Code Page functions */ + case 0x66: + switch (r->AL) + { + case 1: + GetGlblCodePage( + (UWORD FAR *) & (r->BX), + (UWORD FAR *) & (r->DX)); + goto okay_66; + + case 2: + SetGlblCodePage( + (UWORD FAR *) & (r->BX), + (UWORD FAR *) & (r->DX)); + okay_66: + r->FLAGS &= ~FLG_CARRY; + break; + + default: + goto error_invalid; + } + break; + + /* Set Max file handle count */ + case 0x67: + if ((rc = SetJFTSize(r->BX)) != SUCCESS) + goto error_exit; + else + { + r->FLAGS &= ~FLG_CARRY; + } + break; + + /* Flush file buffer -- dummy function right now. */ + case 0x68: + r->FLAGS &= ~FLG_CARRY; + break; + } + +#ifdef DEBUG + if (bDumpRegs) + { + fbcopy((VOID FAR *) user_r, (VOID FAR *) & error_regs, + sizeof(iregs)); + dump_regs = TRUE; + dump(); + } +#endif +} + +/* terminate handler */ +VOID INRPT FAR int22_handler(void) +{ +} + +#if 0 + /* No kernel INT-23 handler required no longer -- 1999/04/15 ska */ +/* ctrl-Break handler */ +#pragma argsused +VOID INRPT FAR int23_handler(int es, int ds, int di, int si, int bp, int sp, int bx, int dx, int cx, int ax, int ip, int cs, int flags) +{ + tsr = FALSE; + return_mode = 1; + return_code = -1; + mod_sto(CTL_C); + DosMemCheck(); +#ifdef TSC + StartTrace(); +#endif + return_user(); +} +#endif + +/* Structures needed for int 25 / int 26 */ +struct HugeSectorBlock +{ + ULONG blkno; + WORD nblks; + BYTE FAR *buf; +}; + +struct int25regs +{ + UWORD es, + ds; + UWORD di, + si, + bp, + sp; + UWORD bx, + dx, + cx, + ax; + UWORD flags, + ip, + cs; +}; + +/* this function is called from an assembler wrapper function */ +VOID int25_handler(struct int25regs FAR * r) +{ + ULONG blkno; + UWORD nblks; + BYTE FAR *buf; + UBYTE drv = r->ax & 0xFF; + + InDOS++; + + if (r->cx == 0xFFFF) + { + struct HugeSectorBlock FAR *lb = MK_FP(r->ds, r->bx); + blkno = lb->blkno; + nblks = lb->nblks; + buf = lb->buf; + } + else + { + nblks = r->cx; + blkno = r->dx; + buf = MK_FP(r->ds, r->bx); + } + + if (drv >= nblkdev) + { + r->ax = 0x202; + r->flags |= FLG_CARRY; + return; + } + + if (!dskxfer(drv, blkno, buf, nblks, DSKREAD)) + { + /* XXX: should tell the user exactly what the error was */ + r->ax = 0x202; + r->flags |= FLG_CARRY; + return; + } + + r->ax = 0; + r->flags &= ~FLG_CARRY; + --InDOS; +} + +VOID int26_handler(struct int25regs FAR * r) +{ + ULONG blkno; + UWORD nblks; + BYTE FAR *buf; + UBYTE drv = r->ax & 0xFF; + + InDOS++; + + if (r->cx == 0xFFFF) + { + struct HugeSectorBlock FAR *lb = MK_FP(r->ds, r->bx); + blkno = lb->blkno; + nblks = lb->nblks; + buf = lb->buf; + } + else + { + nblks = r->cx; + blkno = r->dx; + buf = MK_FP(r->ds, r->bx); + } + + if (drv >= nblkdev) + { + r->ax = 0x202; + r->flags |= FLG_CARRY; + return; + } + + if (!dskxfer(drv, blkno, buf, nblks, DSKWRITE)) + { + /* XXX: should tell the user exactly what the error was */ + r->ax = 0x202; + r->flags |= FLG_CARRY; + return; + } + + setinvld(drv); + + r->ax = 0; + r->flags &= ~FLG_CARRY; + --InDOS; +} + +VOID INRPT FAR int28_handler(void) +{ +} + +VOID INRPT FAR int2a_handler(void) +{ +} + +VOID INRPT FAR empty_handler(void) +{ +} + +#ifdef TSC +static VOID StartTrace(VOID) +{ + if (bTraceNext) + { +#ifdef DEBUG + bDumpRegs = TRUE; +#endif + bTraceNext = FALSE; + } +#ifdef DEBUG + else + bDumpRegs = FALSE; +#endif +} +#endif + diff --git a/kernel/io.asm b/kernel/io.asm new file mode 100644 index 0000000..bec1d6e --- /dev/null +++ b/kernel/io.asm @@ -0,0 +1,619 @@ +; +; File: +; io.asm +; Description: +; DOS-C I/O Subsystem +; +; Copyright (c) 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Header$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:35:20 jhall1 +; Initial revision +; +; Revision 1.3 2000/03/09 06:07:11 kernel +; 2017f updates by James Tabor +; +; Revision 1.2 1999/08/10 17:57:12 jprice +; ror4 2011-02 patch +; +; Revision 1.1.1.1 1999/03/29 15:41:07 jprice +; New version without IPL.SYS +; +; Revision 1.1 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; $EndLog$ +; + + %include "segs.inc" + + extern ConTable:wrt TGROUP + extern LptTable:wrt TGROUP + extern ComTable:wrt TGROUP + extern uPrtNo:wrt TGROUP + extern CommonNdRdExit:wrt TGROUP + extern _NumFloppies:wrt DGROUP + extern blk_stk_top:wrt DGROUP + extern clk_stk_top:wrt DGROUP + extern _blk_driver:wrt TGROUP + extern _clk_driver:wrt TGROUP + +;--------------------------------------------------- +; +; Device entry points +; +; This really should be a struct and go into a request.inc file +; +cmdlen equ 0 ; Length of this command +unit equ 1 ; Subunit Specified +cmd equ 2 ; Command Code +status equ 3 ; Status +media equ 13 ; Media Descriptor +trans equ 14 ; Transfer Address +count equ 18 ; Count of blocks or characters +start equ 20 ; First block to transfer +vid equ 22 ; Volume id pointer +huge equ 26 ; First block (32-bit) to transfer + +; +; The following is the "array" of device driver headers for the internal +; devices. There is one header per device including special aux: and prn: +; pseudo devices. These psuedo devices are necessary for printer +; redirection, i.e., serial or parallel ports, and com port aux selection. +; +; The devices are linked into each other and terminate with a -1 next +; pointer. This saves some time on boot up and also allows us to throw all +; device initialization into a single io_init function that may be placed +; into a discardable code segmemnt. +; +segment _IO_FIXED_DATA + + ; + ; The "CON" device + ; + ; This device is the standard console device used by + ; DOS-C and kernel + ; + global _con_dev +_con_dev equ $ + dw _prn_dev,TGROUP + dw 8013h ; con device (stdin & stdout) + dw GenStrategy + dw ConIntr + db 'CON ' + + ; + ; Generic prn device that can be redirected via mode + ; + global _prn_dev +_prn_dev dw _aux_dev,TGROUP + dw 0A040h + dw GenStrategy + dw PrnIntr + db 'PRN ' + + ; + ; Generic aux device that can be redirected via mode + ; + global _aux_dev +_aux_dev dw _Lpt1Dev,TGROUP + dw 8000h + dw GenStrategy + dw AuxIntr + db 'AUX ' + + ; + ; Printer device drivers + ; +_Lpt1Dev dw _Lpt2Dev,TGROUP + dw 0A040h + dw GenStrategy + dw Lpt1Intr + db 'LPT1 ' +_Lpt2Dev dw _Lpt3Dev,TGROUP + dw 0A040h + dw GenStrategy + dw Lpt2Intr + db 'LPT2 ' +_Lpt3Dev dw _Com1Dev,TGROUP + dw 0A040h + dw GenStrategy + dw Lpt3Intr + db 'LPT3 ' + + ; + ; Com device drivers + ; +_Com1Dev dw _Com2Dev,TGROUP + dw 8000h + dw GenStrategy + dw AuxIntr + db 'COM1 ' +_Com2Dev dw _Com3Dev,TGROUP + dw 8000h + dw GenStrategy + dw Com2Intr + db 'COM2 ' +_Com3Dev dw _Com4Dev,TGROUP + dw 8000h + dw GenStrategy + dw Com3Intr + db 'COM3 ' +_Com4Dev dw _clk_dev,TGROUP + dw 8000h + dw GenStrategy + dw Com4Intr + db 'COM4 ' + + ; + ; Header for clock device + ; + global _clk_dev +_clk_dev equ $ + dw _blk_dev,TGROUP + dw 8004h ; clock device + dw GenStrategy + dw clk_entry + db 'CLOCK$ ' + + ; + ; Header for device + ; + global _blk_dev +_blk_dev equ $ + dd -1 + dw 0000h ; block device + dw GenStrategy + dw blk_entry + global _nblk_rel +_nblk_rel db 4 + db 0,0,0,0,0,0,0 + + +; +; Temporary table until next release +; +segment _IO_FIXED_DATA +DiskTable db 0 + + +; +; Local storage +; + +segment _BSS +blk_dos_stk resw 1 +blk_dos_seg resw 1 +clk_dos_stk resw 1 +clk_dos_seg resw 1 + +segment _IO_TEXT + + global _ReqPktPtr +_ReqPktPtr dd 0 +uUnitNumber dw 0 + +; +; Name: +; GenStrategy +; +; Function: +; Store the pointer to the request packet passed in es:bx +; +; Description: +; Generic strategy routine. Unlike the original multitasking versions, +; this version assumes that no more thank one device driver is active +; at any time. The request is stored into memory in the one and only +; location available for that purpose. +; +GenStrategy: + mov word [cs:_ReqPktPtr],bx + mov word [cs:_ReqPktPtr+2],es + retf + + +; +; Name: +; XXXXIntr +; +; Function: +; Individual Interrupt routines for each device driver +; +; Description: +; This is actually a single routine with entry points for each device. +; The name used for the entry point is the device name with Intr +; appended to it. +; +; Funtionally, each device driver has an entry and an associated +; table. The table is a structure that consists of a control byte +; followed by an array of pointers to C functions or assembly +; subroutines that implement the individual device driver functions. +; This allows the usage of common error dummy filler code to be used. +; It also allows standardization of the calling procedure for these +; internal device driver functions. +; +; Assembler call/return convention: +; Each driver function is entered by a jump into the function and +; exits by a jump to the appropriate success or error exit routine. +; This speeds up the call and return and helps to minimize the stack +; useage. The contents of the request packet are passed to each +; routine in registers as follows: +; +; Register Function Description +; -------- -------- ----------- +; al unit Subunit Specified +; ah media Media Descriptor +; cx count Count of blocks or characters +; dx start First block to transfer +; es:di trans Transfer Address +; ds:bx reqptr Request pointer +; cs kernel code segment +; ds kernel data segment +; +; The exit routines generally set the status based on the individual +; routine. For example, _IOSuccess will clear the count where +; _IOErrCnt will subtract the remaining amount in cx from the original +; count. See each utility routine for expectations. +; +; C call/return convention: +; The C calling convention simply sets up the C stack and passes the +; request packet pointer as a far pointer to the function. Although +; the utility routine names are such that they are accesible from the +; C name space, they are cannot used. Instead, the common interrupt +; code expects a return status to set in the request packet. It is up +; to the device driver function to set the appropriate fields such as +; count when an error occurs. +; +; How to differntiate between the two calling conventions: +; This code is entirely table driven. The table is a structure that +; is generally in the _IO_FIXED_DATA segment. It consists of a flag +; byte followed by short pointers to the driver functions. Selecting +; a driver type is accomplished by setting the type bit in the flag +; (see below). +; +; 7 6 5 4 3 2 1 0 +; +---+---+---+---+---+---+---+---+ +; | | | | | | | | | +; +---+---+---+---+---+---+---+---+ +; | | | |--- Number of table entries +; | | +-------------------+ +; | | |----------------------- Reserved +; | +-------+ +; +--------------------------------- type bit (1 == C / 0 == asm) +; +ConIntr: + push si + mov si,ConTable + jmp short CharIntrEntry + +PrnIntr: + push si + push ax + xor ax,ax + jmp short LptCmnIntr + +Lpt1Intr: + push si + push ax + xor al,al + mov ah,1 + jmp short LptCmnIntr + +Lpt2Intr: + push si + push ax + mov al,1 + mov ah,2 + jmp short LptCmnIntr + +Lpt3Intr: + push si + push ax + mov al,2 + mov ah,3 + +LptCmnIntr: + mov si,LptTable + mov [cs:uPrtNo],ah + jmp short DiskIntrEntry + + +AuxIntr: + push si + push ax + xor al,al + jmp short ComCmnIntr + +Com2Intr: + push si + push ax + mov al,1 + jmp short ComCmnIntr + +Com3Intr: + push si + push ax + mov al,2 + jmp short ComCmnIntr + +Com4Intr: + push si + push ax + mov al,3 + jmp short ComCmnIntr + +ComCmnIntr: + mov si,ComTable + jmp short DiskIntrEntry + + +DskIntr: + push si + mov si,DiskTable +CharIntrEntry: + push ax +DiskIntrEntry: + push cx + push dx + push di + push bp + push ds + push es + push bx + mov byte [cs:uUnitNumber],al + lds bx,[cs:_ReqPktPtr] + test byte [cs:si],80h + je AsmType + + mov al,[bx+cmd] + cmp al,[cs:si] + ja _IOCommandError + cbw + shl ax,1 + add si,ax + xchg di,ax + + push ds + push bx + mov bp,sp + mov ax,DGROUP + mov ds,ax + cld + call word [cs:si+1] + pop cx + pop cx + jmp short StoreStatus + +AsmType: mov al,[bx+unit] + mov ah,[bx+media] + mov cx,[bx+count] + mov dx,[bx+start] + xchg di,ax + mov al,[bx+cmd] + cmp al,[cs:si] + ja _IOCommandError + cbw + shl ax,1 + add si,ax + xchg di,ax + + les di,[bx+trans] + push ax + mov ax,DGROUP + mov ds,ax + pop ax + cld + jmp word [cs:si+1] + +; +; Name: +; _IOXXXXXXX +; +; Function: +; Exit routines for internal device drivers. +; +; Description: +; These routines are the exit for internal device drivers. _IOSuccess +; is for read/write functions and correctly returns for a successful +; read/write operation by setting the remainng count to zero. _IOExit +; simply sets success bit and returns. _IODone returns complete and +; busy status. _IOCommandError returns and error status for invalid +; commands. _IOErrCnt corrects the remaining bytes for errors that +; occurred during partial read/write operation. _IOErrorExit is a +; generic error exit that sets done and error. +; + global _IOSuccess +_IOSuccess: + lds bx,[cs:_ReqPktPtr] + xor ax,ax + mov [bx+count],ax + + global _IOExit +_IOExit: + mov ah,1 + +StoreStatus: + lds bx,[cs:_ReqPktPtr] + mov [bx+status],ax + pop bx + pop es + pop ds + pop bp + pop di + pop dx + pop cx + pop ax + pop si + retf + + + global _IODone +_IODone: + mov ah,3 + jmp short StoreStatus + + global _IOCommandError +_IOCommandError: + mov al,3 + + global _IOErrCnt +_IOErrCnt: + lds bx,[cs:_ReqPktPtr] + sub [bx+count],cx + global _IOErrorExit +_IOErrorExit: + mov ah,81h + jmp short StoreStatus + +; +; Name: +; GetUnitNum +; +; Function: +; Return the internally set unit number. +; +; Description: +; Simply return the contents of uUnitNumber. This version relies on +; no segment registers and makes a safe call regardless of driver +; state. +; + global GetUnitNum +GetUnitNum: + mov dx,[cs:uUnitNumber] + ret + + ; + ; These are still old style DOS-C drivers. I'll replace + ; them in the next release + ; + + + ; + ; block device interrupt + ; + ; NOTE: This code is not standard device driver handlers + ; It is written for sperate code and data space. + ; +blk_entry: + pushf + push ax + push bx + push cx + push dx + push bp + push si + push di + push ds + push es + + ; small model + mov ax,DGROUP ; correct for segments + mov ds,ax ; ax to carry segment + mov word [blk_dos_stk],sp ; use internal stack + mov word [blk_dos_seg],ss + pushf ; put flags in bx + pop bx + cli ; no interrupts + mov ss,ax + mov sp,blk_stk_top + push bx + popf ; restore interrupt flag + mov bp,sp ; make a c frame + push word [cs:_ReqPktPtr+2] + push word [cs:_ReqPktPtr] + call _blk_driver + pop cx + pop cx + les bx,[cs:_ReqPktPtr] ; now return completion code + mov word [es:bx+status],ax ; mark operation complete + cli ; no interrupts + mov sp,[blk_dos_stk] ; use dos stack + mov ss,[blk_dos_seg] + pop es + pop ds + pop di + pop si + pop bp + pop dx + pop cx + pop bx + pop ax + popf + retf + + + + ; + ; clock device interrupt + ; + ; NOTE: This code is not standard device driver handlers + ; It is written for sperate code and data space. + ; +clk_entry: + pushf + push ax + push bx + push cx + push dx + push bp + push si + push di + push ds + push es + + ; small model + mov ax,DGROUP ; correct for segments + mov ds,ax ; ax to carry segment + mov word [clk_dos_stk],sp ; use internal stack + mov word [clk_dos_seg],ss + pushf ; put flags in bx + pop bx + cli ; no interrupts + mov ss,ax + mov sp,clk_stk_top + push bx + popf ; restore interrupt flag + mov bp,sp ; make a c frame + push word [cs:_ReqPktPtr+2] + push word [cs:_ReqPktPtr] + call _clk_driver + pop cx + pop cx + les bx,[cs:_ReqPktPtr] ; now return completion code + mov word [es:bx+status],ax ; mark operation complete + cli ; no interrupts + mov sp,[clk_dos_stk] ; use dos stack + mov ss,[clk_dos_seg] + pop es + pop ds + pop di + pop si + pop bp + pop dx + pop cx + pop bx + pop ax + popf + retf + diff --git a/kernel/io.inc b/kernel/io.inc new file mode 100644 index 0000000..4642129 --- /dev/null +++ b/kernel/io.inc @@ -0,0 +1,72 @@ +; +; File: +; io.inc +; Description: +; Segments and external common routines used by various device drivers +; +; Copyright (c) 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/usr/patv/dos-c/src/kernel/io.inv $ +; +; $Header$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:35:20 jhall1 +; Initial revision +; +; Revision 1.3 1999/08/10 17:57:12 jprice +; ror4 2011-02 patch +; +; Revision 1.2 1999/03/29 17:05:09 jprice +; ror4 changes +; +; Revision 1.1.1.1 1999/03/29 15:41:08 jprice +; New version without IPL.SYS +; +; Revision 1.1 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; +; Rev 1.0 06 Dec 1998 8:13:02 patv +; Initial revision. +; $EndLog$ +; + +group TGROUP _TEXT _IO_TEXT _IO_FIXED_DATA +group DGROUP _FIXED_DATA _DATA _BSS _BSSEND + +segment _TEXT class=CODE +segment _IO_TEXT class=CODE +segment _IO_FIXED_DATA class=CODE align=2 +segment _FIXED_DATA class=DATA align=16 +segment _DATA class=DATA align=2 +segment _BSS class=BSS align=2 +segment _BSSEND class=BSS + + extern _IOExit:wrt TGROUP + extern _IOSuccess:wrt TGROUP + extern _IOErrorExit:wrt TGROUP + extern _IOErrCnt:wrt TGROUP + extern _IODone:wrt TGROUP + extern _IOCommandError:wrt TGROUP + extern GetUnitNum:wrt TGROUP + extern _ReqPktPtr:wrt TGROUP diff --git a/kernel/ioctl.c b/kernel/ioctl.c new file mode 100644 index 0000000..c630495 --- /dev/null +++ b/kernel/ioctl.c @@ -0,0 +1,356 @@ +/****************************************************************/ +/* */ +/* ioctl.c */ +/* */ +/* DOS-C ioctl system call */ +/* */ +/* Copyright (c) 1995,1998 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:20 jhall1 + * Initial revision + * + * Revision 1.3 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.2 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:41:09 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/08 05:55:57 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.3 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.2 1999/01/22 04:13:26 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.7 06 Dec 1998 8:48:22 patv + * Expanded due to new I/O subsystem. + * + * Rev 1.6 11 Jan 1998 2:06:22 patv + * Added functionality to ioctl. + * + * Rev 1.5 04 Jan 1998 23:15:18 patv + * Changed Log for strip utility + * + * Rev 1.4 16 Jan 1997 12:46:54 patv + * pre-Release 0.92 feature additions + * + * Rev 1.3 29 May 1996 21:03:30 patv + * bug fixes for v0.91a + * + * Rev 1.2 19 Feb 1996 3:21:34 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.1 01 Sep 1995 17:54:16 patv + * First GPL release. + * + * Rev 1.0 02 Jul 1995 8:32:04 patv + * Initial revision. + */ + +#ifdef PROTO +sft FAR *get_sft(COUNT); +#else +sft FAR *get_sft(); +#endif + +/* + * WARNING: this code is non-portable (8086 specific). + */ + +COUNT DosDevIOctl(iregs FAR * r, COUNT FAR * err) +{ + sft FAR *s; + struct dpb FAR *dpbp; + BYTE FAR *pBuffer = MK_FP(r->DS, r->DX); + COUNT nMode; + + /* Test that the handle is valid */ + switch (r->AL) + { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x06: + case 0x07: + case 0x0a: + case 0x0c: + + /* Get the SFT block that contains the SFT */ + if ((s = get_sft(r->BX)) == (sft FAR *) - 1) + { + *err = DE_INVLDHNDL; + return 0; + } + break; + + case 0x04: + case 0x05: + case 0x08: + case 0x09: + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + case 0x11: + if (r->BL > nblkdev) + { + *err = DE_INVLDDRV; + return 0; + } + else + { +/* + This line previously returned the deviceheader at r->bl. But, + DOS numbers its drives starting at 1, not 0. A=1, B=2, and so + on. Changed this line so it is now zero-based. + + -SRM + */ +/* JPP - changed to use default drive if drive=0 */ + if (r->BL == 0) + dpbp = &blk_devices[default_drive]; + else + dpbp = &blk_devices[r->BL - 1]; + } + break; + + case 0x0b: + /* skip, it's a special case. */ + + NetDelay = r->CX; + if (!r->DX) + NetRetry = r->DX; + break; + + default: + *err = DE_INVLDFUNC; + return 0; + } + + switch (r->AL) + { + case 0x00: + /* Get the flags from the SFT */ + r->DX = r->AX = s->sft_flags; + + /* Test for file and network SFT. These return a 0 in */ + /* the AH register. */ + if ((s->sft_flags & SFT_FSHARED) + || !(s->sft_flags & SFT_FDEVICE)) + { + r->AH = 0; + } + break; + + case 0x01: + /* sft_flags is a file, return an error because you */ + /* can't set the status of a file. */ + if (!(s->sft_flags & SFT_FDEVICE)) + { + *err = DE_INVLDFUNC; + return 0; + } + + /* Set it to what we got in the DL register from the */ + /* user. */ + r->AL = s->sft_flags_lo = SFT_FDEVICE | r->DL; + break; + + case 0x0c: + nMode = C_GENIOCTL; + goto IoCharCommon; + case 0x02: + nMode = C_IOCTLIN; + goto IoCharCommon; + case 0x10: + nMode = C_IOCTLQRY; + goto IoCharCommon; + case 0x03: + nMode = C_IOCTLOUT; + IoCharCommon: + + if ((s->sft_flags & SFT_FDEVICE) + || ((r->AL == 0x10) && !(s->sft_dev->dh_attr & ATTR_QRYIOCTL)) + || ((r->AL == 0x0c) && !(s->sft_dev->dh_attr & ATTR_GENIOCTL))) + { + if (s->sft_dev->dh_attr & SFT_FIOCTL) + { + CharReqHdr.r_unit = 0; + CharReqHdr.r_length = sizeof(request); + CharReqHdr.r_command = nMode; + CharReqHdr.r_count = r->CX; + CharReqHdr.r_trans = pBuffer; + CharReqHdr.r_status = 0; + execrh((request FAR *) & CharReqHdr, s->sft_dev); + + if (CharReqHdr.r_status & S_ERROR) + return char_error(&CharReqHdr, s->sft_dev); + if (r->AL == 0x07) + { + r->AL = + CharReqHdr.r_status & S_BUSY ? + 00 : 0xff; + } + break; + } + } + *err = DE_INVLDFUNC; + return 0; + + case 0x0d: + nMode = C_GENIOCTL; + goto IoBlockCommon; + case 0x04: + nMode = C_IOCTLIN; + goto IoBlockCommon; + case 0x11: + nMode = C_IOCTLQRY; + goto IoBlockCommon; + case 0x05: + nMode = C_IOCTLOUT; + IoBlockCommon: + if ((dpbp->dpb_device->dh_attr & ATTR_IOCTL) + || ((r->AL == 0x11) && !(dpbp->dpb_device->dh_attr & ATTR_QRYIOCTL)) + || ((r->AL == 0x0d) && !(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL))) + { + *err = DE_INVLDFUNC; + return 0; + } + + CharReqHdr.r_unit = r->BL; + CharReqHdr.r_length = sizeof(request); + CharReqHdr.r_command = nMode; + CharReqHdr.r_count = r->CX; + CharReqHdr.r_trans = pBuffer; + CharReqHdr.r_status = 0; + execrh((request FAR *) & CharReqHdr, + dpbp->dpb_device); + if (r->AL == 0x08) + { + if (CharReqHdr.r_status & S_ERROR) + { + *err = DE_DEVICE; + return 0; + } + r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0; + } + else + { + if (CharReqHdr.r_status & S_ERROR) + { + *err = DE_DEVICE; + return 0; + } + } + break; + + case 0x06: + if (s->sft_flags & SFT_FDEVICE) + { + r->AL = s->sft_flags & SFT_FEOF ? 0 : 0xFF; + } + else + r->AL = s->sft_posit >= s->sft_size ? 0xFF : 0; + break; + + case 0x07: + if (s->sft_flags & SFT_FDEVICE) + { + goto IoCharCommon; + } + r->AL = 0; + break; + + case 0x08: + if (dpbp->dpb_device->dh_attr & ATTR_EXCALLS) + { + nMode = C_REMMEDIA; + goto IoBlockCommon; + } + *err = DE_INVLDFUNC; + return 0; + + case 0x09: + r->DX = dpbp->dpb_device->dh_attr; + break; + + case 0x0a: + r->DX = s->sft_dcb->dpb_device->dh_attr; + break; + + case 0x0e: + nMode = C_GETLDEV; + goto IoLogCommon; + case 0x0f: + nMode = C_SETLDEV; + IoLogCommon: + if ((dpbp->dpb_device->dh_attr & ATTR_GENIOCTL)) + { + if (r->BL == 0) + r->BL = default_drive; + + CharReqHdr.r_unit = r->BL; + CharReqHdr.r_length = sizeof(request); + CharReqHdr.r_command = nMode; + CharReqHdr.r_count = r->CX; + CharReqHdr.r_trans = pBuffer; + CharReqHdr.r_status = 0; + execrh((request FAR *) & CharReqHdr, + dpbp->dpb_device); + + if (CharReqHdr.r_status & S_ERROR) + *err = DE_ACCESS; + else + *err = SUCCESS; + return 0; + } + *err = DE_INVLDFUNC; + return 0; + + default: + *err = DE_INVLDFUNC; + return 0; + } + *err = SUCCESS; + return 0; +} + diff --git a/kernel/irqstack.asm b/kernel/irqstack.asm new file mode 100644 index 0000000..c3ae41d --- /dev/null +++ b/kernel/irqstack.asm @@ -0,0 +1,268 @@ +; File: +; irqstack.asm +; Description: +; Assembly support routines for hardware stack support +; +; Copyright (c) 1997, 1998 +; Svante Frey +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/dos-c/src/kernel/irqstack.asv $ +; +; $Id$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:35:21 jhall1 +; Initial revision +; +; Revision 1.3 1999/08/10 17:57:13 jprice +; ror4 2011-02 patch +; +; Revision 1.2 1999/04/16 12:21:22 jprice +; Steffen c-break handler changes +; +; Revision 1.1.1.1 1999/03/29 15:41:10 jprice +; New version without IPL.SYS +; +; Revision 1.4 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; Revision 1.3 1999/02/01 01:48:41 jprice +; Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) +; +; Revision 1.2 1999/01/22 04:13:26 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:01 jprice +; Imported sources +; +; +; Rev 1.2 06 Dec 1998 8:49:08 patv +; Bug fixes. +; +; Rev 1.1 22 Jan 1997 13:15:34 patv +; pre-0.92 Svante Frey bug fixes +; +; Rev 1.0 16 Jan 1997 21:43:44 patv +; Initial revision. +; $EndLog$ +; + + +; Code for stack switching during hardware interrupts. + +group TGROUP _TEXT + +segment _TEXT class=CODE + +old_vectors times 16 dd 0 +stack_size dw 0 +stack_top dw 0 +stack_offs dw 0 +stack_seg dw 0 + +irq_0: push bx + mov bx, 0 * 4 + jmp short general_irq_service + +irq_1: push bx + mov bx, 1 * 4 + jmp short general_irq_service + +irq_2: push bx + mov bx, 2 * 4 + jmp short general_irq_service + +irq_3: push bx + mov bx, 3 * 4 + jmp short general_irq_service + +irq_4: push bx + mov bx, 4 * 4 + jmp short general_irq_service + +irq_5: push bx + mov bx, 5 * 4 + jmp short general_irq_service + +irq_6: push bx + mov bx, 6 * 4 + jmp short general_irq_service + +irq_7: push bx + mov bx, 7 * 4 + jmp short general_irq_service + +irq_08: push bx + mov bx, 8 * 4 + jmp short general_irq_service + +irq_09: push bx + mov bx, 9 * 4 + jmp short general_irq_service + +irq_0a: push bx + mov bx, 0ah * 4 + jmp short general_irq_service + +irq_0b: push bx + mov bx, 0bh * 4 + jmp short general_irq_service + +irq_0c: push bx + mov bx, 0ch * 4 + jmp short general_irq_service + +irq_0d: push bx + mov bx, 0dh * 4 + jmp short general_irq_service + +irq_0e: push bx + mov bx, 0eh * 4 + jmp short general_irq_service + +irq_0f: push bx + mov bx, 0fh * 4 +; jmp short general_irq_service + +general_irq_service: + push dx + push ax + push ds + + mov ax, cs + mov ds, ax + + mov ax, [stack_top] + cmp ax, [stack_offs] + jbe dont_switch + + mov dx, ss + mov ax, sp + + mov ss, [stack_seg] + mov sp, [stack_top] + + push dx ; save old SS:SP on new stack + push ax + + mov ax, [stack_size] + sub [stack_top], ax + + pushf + call far word [old_vectors+bx] + + cli + add [stack_top], ax + + pop ax ; get stored SS:SP + pop dx + + mov ss, dx ; switch back to old stack + mov sp, ax + + pop ds ; restore registers and return + pop ax + pop dx + pop bx + iret + +dont_switch: pushf + call far word [old_vectors+bx] + pop ds + pop ax + pop dx + pop bx + iret + + +segment INIT_TEXT class=INIT + +global _init_stacks +; VOID init_stacks(VOID FAR *stack_base, COUNT nStacks, WORD stackSize); + +_init_stacks: + push bp + mov bp, sp + push ds + push di + push si + + + mov ax,_TEXT + mov ds,ax + + mov bx, [bp+4] + mov dx, [bp+6] + mov ax, [bp+8] + mov cx, [bp+0ah] + + mov [stack_size], cx + mov [stack_offs], bx + mov [stack_seg], dx + + mul cx + add ax, bx + mov [stack_top], ax + + xor ax, ax + mov ds, ax + + mov ax, _TEXT + mov es, ax + + mov di, old_vectors + mov si, 8 * 4 + mov cx, 10h + rep movsw + + mov si, 70h * 4 + mov cx, 10h + rep movsw + + push ds + pop es + + mov di, 8 * 4 + mov dx, irq_0 + call set_vect + + mov di, 70h * 4 + call set_vect + + pop si + pop di + pop ds + pop bp + ret + +set_vect: + mov cx, 8 + +set_next: mov ax, dx + cli + stosw + mov ax, _TEXT + stosw + sti + add dx, irq_1 - irq_0 + loop set_next + + ret diff --git a/kernel/kernel.asm b/kernel/kernel.asm new file mode 100644 index 0000000..96848eb --- /dev/null +++ b/kernel/kernel.asm @@ -0,0 +1,606 @@ +; +; File: +; kernel.asm +; Description: +; kernel start-up code +; +; Copyright (c) 1995, 1996 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Id$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:35:22 jhall1 +; Initial revision +; +; Revision 1.6 2000/03/09 06:07:11 kernel +; 2017f updates by James Tabor +; +; Revision 1.5 1999/09/23 04:40:47 jprice +; *** empty log message *** +; +; Revision 1.3 1999/08/10 17:57:13 jprice +; ror4 2011-02 patch +; +; Revision 1.2 1999/04/13 15:52:57 jprice +; changes for boot loader +; +; Revision 1.1.1.1 1999/03/29 15:41:14 jprice +; New version without IPL.SYS +; +; Revision 1.4 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; Revision 1.3 1999/02/01 01:48:41 jprice +; Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) +; +; Revision 1.2 1999/01/22 04:13:26 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:01 jprice +; Imported sources +; +; Rev 1.11 06 Dec 1998 8:48:04 patv +;Bug fixes. +; +; Rev 1.10 03 Feb 1998 23:30:08 patv +;Added a start-up stack for loadable device drivers. Need the separate +;stack so that all int 21h functions can be called. +; +; Rev 1.9 22 Jan 1998 4:09:24 patv +;Fixed pointer problems affecting SDA +; +; Rev 1.8 06 Jan 1998 20:12:32 patv +;Reduced device driver stack sizes. +; +; Rev 1.7 04 Jan 1998 17:26:18 patv +;Corrected subdirectory bug +; +; Rev 1.6 03 Jan 1998 8:36:50 patv +;Converted data area to SDA format +; +; Rev 1.5 06 Feb 1997 22:43:18 patv +;Reduced stack sizes for block and clock devices. +; +; Rev 1.4 06 Feb 1997 19:05:48 patv +;Added hooks for tsc command +; +; Rev 1.3 29 May 1996 21:03:44 patv +;bug fixes for v0.91a +; +; Rev 1.2 19 Feb 1996 3:24:06 patv +;Added NLS, int2f and config.sys processing +; +; Rev 1.1 01 Sep 1995 17:54:24 patv +;First GPL release. +; +; Rev 1.0 02 Jul 1995 9:05:44 patv +;Initial revision. +; +; $EndLog$ +; + + %include "segs.inc" + + +segment _TEXT + + extern _ReqPktPtr:wrt TGROUP + +STACK_SIZE equ 384/2 ; stack allocated in words + +..start: +entry: jmp far kernel_start + +segment INIT_TEXT + + extern _main:wrt IGROUP + + ; + ; kernel start-up + ; +kernel_start: + mov ax,DGROUP + cli + mov ss,ax + mov sp,tos + int 12h ; move the init code to higher memory + mov cl,6 + shl ax,cl + mov dx,init_end+15 + mov cl,4 + shr dx,cl + sub ax,dx + mov es,ax + mov ax,cs + mov ds,ax + xor si,si + xor di,di + mov cx,init_end+1 + shr cx,1 + cld + rep movsw + push es + mov ax,cont + push ax + retf +cont: ; inititalize api stacks for high water tests + mov di,seg apistk_bottom + mov es,di + mov di,apistk_bottom + mov ax,apistk_top + sub ax,di + sar ax,1 + mov cx,ax + mov ax,09090h + cld + rep stosw + ; Now set up call frame + mov ax,ss + mov ds,ax + mov es,ax + mov bp,sp ; and set up stack frame for c + sti ; now enable them + inc bl + jns floppy + add bl,3-1-128 +floppy: mov byte [_BootDrive],bl ; tell where we came from + int 11h + mov cl,6 + shr al,cl + inc al + mov byte [_NumFloppies],al ; and how many + + mov ax,ds + mov es,ax + jmp _main + +segment INIT_TEXT_END +init_end: + +segment _TEXT + + ; + ; NUL device strategy + ; + global _nul_strtgy +_nul_strtgy: + mov word [cs:_ReqPktPtr],bx ;save rq headr + mov word [cs:_ReqPktPtr+2],es + retf + + ; + ; NUL device interrupt + ; + global _nul_intr +_nul_intr: + push es + push bx + les bx,[cs:_ReqPktPtr] ;es:bx--> rqheadr + or word [es:bx+3],100h ;set "done" flag + pop bx + pop es + retf + + extern _init_call_printf:wrt TGROUP + + global _printf + +_printf: + pop ax + push cs + push ax + jmp _init_call_printf + + +segment _FIXED_DATA + +; Because of the following bytes of data, THIS MODULE MUST BE THE FIRST +; IN THE LINK SEQUENCE. THE BYTE AT DS:0004 determines the SDA format in +; use. A 0 indicates MS-DOS 3.X style, a 1 indicates MS-DOS 4.0-6.X style. + global DATASTART +DATASTART: +dos_data db 0 + dw kernel_start + db 0 ; padding + dw 1 ; Hardcoded MS-DOS 4.0+ style + + times (0eh - ($ - DATASTART)) db 0 + global _NetBios +_NetBios db 0 ; NetBios Number + global _Num_Name +_Num_Name db 0 + + times (26h - 0ch - ($ - DATASTART)) db 0 + +; Globally referenced variables - WARNING: DO NOT CHANGE ORDER +; BECAUSE THEY ARE DOCUMENTED AS UNDOCUMENTED (?) AND HAVE +; MANY MULTIPLEX PROGRAMS AND TSR'S ACCESSING THEM + global _NetRetry +_NetRetry dw 3 ;-000c network retry count + global _NetDelay +_NetDelay dw 1 ;-000a network delay count + global _DskBuffer +_DskBuffer dd -1 ;-0008 current dos disk buffer + dw 0 ;-0004 Unread con input + global _first_mcb +_first_mcb dw 0 ;-0002 Start of user memory + global _DPBp + global MARK0026H +; A reference seems to indicate that this should start at offset 26h. +MARK0026H equ $ +_DPBp dd 0 ; 0000 First drive Parameter Block + global _sfthead +_sfthead dd 0 ; 0004 System File Table head + global _clock +_clock dd 0 ; 0008 CLOCK$ device + global _syscon +_syscon dd 0 ; 000c console device + global _maxbksize +_maxbksize dw 0 ; 0010 Number of Drives in system + global _firstbuf; +_firstbuf dd 0 ; 0012 head of buffers linked list + global _CDSp +_CDSp dd 0 ; 0016 Current Directory Structure + global _FCBp +_FCBp dd 0 ; 001a FCB table pointer + global _nprotfcb +_nprotfcb dw 0 ; 001e number of protected fcbs + global _nblkdev +_nblkdev db 0 ; 0020 number of block devices + global _lastdrive +_lastdrive db 0 ; 0021 value of last drive + global _nul_dev +_nul_dev: ; 0022 device chain root + dd -1 + dw 8004h ; attributes = char device, NUL bit set + dw _nul_strtgy + dw _nul_intr + db 'NUL ' + global _njoined +_njoined db 0 ; 0034 number of joined devices + dw 0 ; 0035 DOS 4 pointer to special names (always zero in DOS 5) +setverPtr dw 0,0 ; 0037 setver list + dw 0 ; 003B cs offset for fix a20 + dw 0 ; 003D psp of last umb exec + dw 1 ; 003F number of buffers + dw 1 ; 0041 size of pre-read buffer + global _BootDrive +_BootDrive dw 0 ; 0043 drive we booted from + db 0 ; 0044 cpu type (1 if >=386) + dw 0 ; 0045 Extended memory in KBytes +buf_info dd 0 ; 0047 disk buffer chain + dw 0 ; 004B 0 (DOS 4 = # hashing chains) + dd 0 ; 004D pre-read buffer + dw 0 ; 0051 # of sectors + db 0 ; 0053 00=conv 01=HMA + dw 0 ; 0054 deblock buf in conv +deblock_seg dw 0 ; 0056 (offset always zero) + times 3 db 0 ; 0058 unknown + dw 0 ; 005B unknown + db 0, 0FFh, 0 ; 005D unknown + db 0 ; 0060 unknown + dw 0 ; 0061 unknown +dmd_upper_link db 0 ; 0063 upper memory link flag + dw 0 ; 0064 unknown +dmd_upper_root dw 0FFFFh ; 0066 dmd_upper_root + dw 0 ; 0068 para of last mem search +SysVarEnd: + + +; Some references seem to indicate that this data should start at 01fbh in +; order to maintain 100% MS-DOS compatibility. + times (01fbh - (SysVarEnd - DATASTART)) db 0 + + global MARK01FBH +MARK01FBH equ $ + times 128 db 0 + global _kb_buf +_kb_buf db 129,0 ; initialise buffer to empty + times 128+1 db 0 ; room for 128 byte readline + LF +; +; Variables that follow are documented as part of the DOS 4.0-6.X swappable +; data area in Ralf Browns Interrupt List #56 +; +; this byte is used for ^P support + global _PrinterEcho +_PrinterEcho db 0 ;-34 - 0 = no printer echo, ~0 echo + global _verify_ena +_verify_ena db 0 ; ~0, write with verify + +; this byte is used for TAB's + global _scr_pos +_scr_pos db 0 ; Current Cursor Column + global _switchar +_switchar db '/' ;-31 - switch char + global _mem_access_mode +_mem_access_mode db 0 ;-30 - memory allocation strategy + global sharing_flag +sharing_flag db 0 ; 00 = sharing module not loaded + ; 01 = sharing module loaded, but + ; open/close for block devices + ; disabled + ; FF = sharing module loaded, + ; open/close for block devices + ; enabled (not implemented) + global _net_set_count +_net_set_count db 1 ;-28 - count the name below was set + global _net_name +_net_name db ' ' ;-27 - 15 Character Network Name + db 00 ; Terminating 0 byte + + +; +; Variables contained the the "STATE_DATA" segment contain +; information about the STATE of the current DOS Process. These +; variables must be preserved regardless of the state of the INDOS +; flag. +; +; All variables that appear in "STATE_DATA" **MUST** be declared +; in this file as the offsets from the INTERNAL_DATA variable are +; critical to the DOS applications that modify this data area. +; +; + global _ErrorMode, _InDOS + global _CritErrLocus, _CritErrCode + global _CritErrAction, _CritErrClass + global _CritErrDev, _CritErrDrive + global _dta + global _cu_psp, _default_drive + global _break_ena + global _return_code, _return_mode + global _internal_data + + global _CritPatch +_CritPatch dw 0d0ch ;-11 zero list of patched critical + dw 0d0ch ; section variables + dw 0d0ch + dw 0d0ch + dw 0d0ch + db 0 ;-01 - unknown +_internal_data: ; <-- Address returned by INT21/5D06 +_ErrorMode db 0 ; 00 - Critical Error Flag +_InDOS db 0 ; 01 - Indos Flag +_CritErrDrive db 0 ; 02 - Drive on write protect error +_CritErrLocus db 0 ; 03 - Error Locus +_CritErrCode dw 0 ; 04 - DOS format error Code +_CritErrAction db 0 ; 06 - Error Action Code +_CritErrClass db 0 ; 07 - Error Class +_CritErrDev dd 0 ; 08 - Failing Device Address +_dta dd 0 ; 0C - current DTA +_cu_psp dw 0 ; 10 - Current PSP +break_sp dw 0 ; 12 - used in int 23 +_return_code db 0 ; 14 - return code from process +_return_mode db 0 ; 15 - reason for process terminate +_default_drive db 0 ; 16 - Current Drive +_break_ena db 0 ; 17 - Break Flag + db 0 ; 18 - flag, code page switching + db 0 ; 19 - flag, copy of 18 on int 24h abort + + global _swap_always, _swap_indos +_swap_always: + + global _Int21AX +_Int21AX dw 0 ; 1A - AX from last Int 21 + + global owning_psp, _MachineId +owning_psp dw 0 ; 1C - owning psp +_MachineId dw 0 ; 1E - remote machine ID + dw 0 ; 20 - First usable mcb + dw 0 ; 22 - Best usable mcb + dw 0 ; 24 - Last usable mcb + dw 0 ; 26 - memory size in paragraphs + dw 0 ; 28 - unknown + db 0 ; 2A - unknown + db 0 ; 2B - unknown + db 0 ; 2C - unknown + global _break_flg +_break_flg db 0 ; 2D - Program aborted by ^C + db 0 ; 2E - unknown + db 0 ; 2F - not referenced + global _DayOfMonth +_DayOfMonth db 1 ; 30 - day of month + global _Month +_Month db 1 ; 31 - month + global _YearsSince1980 +_YearsSince1980 dw 0 ; 32 - year since 1980 +daysSince1980 dw 0FFFFh ; 34 - number of days since epoch + ; force rebuild on first clock read + global _DayOfWeek +_DayOfWeek db 2 ; 36 - day of week + global _Year +_Year dw 1980 ; 37 - year + global _dosidle_flag +_dosidle_flag db 0 ; 39 - unknown *no more* + global _CharReqHdr +_CharReqHdr: + global _ClkReqHdr +_ClkReqHdr times 30 db 0 ; 3A - Device driver request header + dd 0 ; 58 - pointer to driver entry + global _MediaReqHdr +_MediaReqHdr times 22 db 0 ; 5C - Device driver request header + global _IoReqHdr +_IoReqHdr times 30 db 0 ; 72 - Device driver request header + times 6 db 0 ; 90 - unknown + global _ClkRecord +_ClkRecord times 6 db 0 ; 96 - CLOCK$ transfer record + dw 0 ; 9C - unknown + global __PriPathBuffer +__PriPathBuffer times 80h db 0 ; 9E - buffer for file name + global __SecPathBuffer +__SecPathBuffer times 80h db 0 ;11E - buffer for file name + global _TempBuffer +_TempBuffer times 21 db 0 ;19E - 21 byte srch state + global _SearchDir +_SearchDir times 32 db 0 ;1B3 - 32 byte dir entry + global _TempCDS +_TempCDS times 88 db 0 ;1D3 - TemporaryCDS buffer + global _DirEntBuffer +_DirEntBuffer times 32 db 0 ;22B - space enough for 1 dir entry + global _wAttr +_wAttr dw 0 ;24B - extended FCB file attribute + + + global _SAttr +_SAttr db 0 ;24D - Attribute Mask for Dir Search + global _OpenMode +_OpenMode db 0 ;24E - File Open Attribute + +; times 3 db 0 +; global _Server_Call +;_Server_Call db 0 ;252 - Server call Func 5D sub 0 + + + ; Pad to 0570h + times (250h - ($ - _internal_data)) db 0 + global _lpUserStack +_lpUserStack dd 0 ;250 - pointer to user stack frame + + ; Pad to 057Ch + times (25ch - ($ - _internal_data)) db 0 + + global _tsr ; used by break and critical error +_tsr db 0 ;25C - handlers during termination + db 0 ;25D - padding + global term_psp +term_psp dw 0 ;25E - 0?? + global int24_esbp +int24_esbp times 2 dw 0 ;260 - pointer to criticalerr DPB + global _user_r, int21regs_off, int21regs_seg +_user_r: +int21regs_off dw 0 ;264 - pointer to int21h stack frame +int21regs_seg dw 0 + global critical_sp +critical_sp dw 0 ;268 - critical error internal stack + global current_ddsc +current_ddsc times 2 dw 0 + + ; Pad to 059ah + times (27ah - ($ - _internal_data)) db 0 + global current_device +current_device times 2 dw 0 ;27A - 0?? + global _lpCurSft +_lpCurSft times 2 dw 0 ;27e - Current SFT + global _current_ldt +_current_ldt times 2 dw 0 ;282 - Current CDS + global _lpFcb +_lpFcb times 2 dw 0 ;286 - pointer to callers FCB + global current_ifn +current_ifn dw 0 ;28A - SFT index for next open + + ; Pad to 05ceh + times (2aeh - ($ - _internal_data)) db 0 + global current_filepos +current_filepos times 2 dw 0 ;2AE - current offset in file + + ; Pad to 05f0h + times (2d0h - ($ - _internal_data)) db 0 + global _prev_user_r + global prev_int21regs_off + global prev_int21regs_seg +_prev_user_r: +prev_int21regs_off dw 0 ;2D0 - pointer to prev int 21 frame +prev_int21regs_seg dw 0 + + ; Pad to 0620h + times (300h - ($ - _internal_data)) db 0 + + global _FcbSearchBuffer ; during FCB search 1st/next use bottom +_FcbSearchBuffer: ; of error stack as scratch buffer +; times 43 db 0 ; - only used during int 21 call + global _LocalPath +_LocalPath: +; times 67 db 0 + ; stacks are made to initialize to no-ops so that high-water + ; tesing can be performed +apistk_bottom: + times STACK_SIZE dw 0 ;300 - Error Processing Stack + global _error_tos +_error_tos: + times STACK_SIZE dw 0 ;480 - Disk Function Stack + global _disk_api_tos +_disk_api_tos: + times STACK_SIZE dw 0 ;600 - Char Function Stack + global _char_api_tos +_char_api_tos: +apistk_top: + +_VolChange db 0 ;781 - volume change +_VirtOpen db 0 ;782 - virtual open flag + + ; controlled variables end at offset 78Ch so pad to end + times (78ch - ($ - _internal_data)) db 0 +_swap_indos: +; +; end of controlled variables +; + +segment _BSS + global _NumFloppies +_NumFloppies resw 1 +intr_dos_stk resw 1 +intr_dos_seg resw 1 + + + global _api_sp +_api_sp dw 0 ; api stacks - for context + global _api_ss +_api_ss dw 0 ; switching + global _usr_sp +_usr_sp dw 0 ; user stacks + global _usr_ss +_usr_ss dw 0 + global _ram_top +_ram_top dw 0 + + + + +segment _BSSEND +; blockdev private stack + global blk_stk_top + times 256 dw 0 +blk_stk_top: + +; clockdev private stack + global clk_stk_top + times 256 dw 0 +clk_stk_top: + +; interrupt stack + times 256 dw 0 +intr_stk_top: + +; kernel startup stack + times 128 dw 0 +tos: + + global last +last: ; must always be end of stack area + global _last +_last: ; and c version + + +; The default stack (_TEXT:0) will overwrite the data area, so I create a dummy +; stack here to ease debugging. -- ror4 + +segment _STACK class=STACK stack + diff --git a/kernel/kernel.cfg b/kernel/kernel.cfg new file mode 100644 index 0000000..c92038f --- /dev/null +++ b/kernel/kernel.cfg @@ -0,0 +1,13 @@ +-1- +-f- +-ff- +-O +-Z +-d +-k- +-vi- +-wpro +-weas +-wpre +-I..\hdr +-v -X- -I. -D__STDC__=0 -DTSC -DDEBUG -DKERNEL -DI86 -DPROTO -DSHWR -DASMSUPT diff --git a/kernel/kernel.mak b/kernel/kernel.mak new file mode 100644 index 0000000..8482f06 --- /dev/null +++ b/kernel/kernel.mak @@ -0,0 +1,415 @@ +# +# Makefile for Borland C++ 3.1 for kernel.sys +# +# $Id$ +# + +# $Log$ +# Revision 1.1 2000/05/06 19:35:23 jhall1 +# Initial revision +# +# Revision 1.12 2000/03/09 06:07:11 kernel +# 2017f updates by James Tabor +# +# Revision 1.11 1999/09/23 04:40:47 jprice +# *** empty log message *** +# +# Revision 1.8 1999/09/13 20:41:41 jprice +# Some clean up. +# +# Revision 1.7 1999/08/25 03:18:09 jprice +# ror4 patches to allow TC 2.01 compile. +# +# Revision 1.6 1999/08/10 17:57:13 jprice +# ror4 2011-02 patch +# +# Revision 1.5 1999/04/23 04:25:15 jprice +# no message +# +# Revision 1.4 1999/04/23 03:45:11 jprice +# Improved by jprice +# +# Revision 1.3 1999/04/16 12:21:22 jprice +# Steffen c-break handler changes +# +# Revision 1.2 1999/04/13 15:48:21 jprice +# no message +# +# Revision 1.1.1.1 1999/03/29 15:41:15 jprice +# New version without IPL.SYS +# +# Revision 1.7 1999/03/01 06:04:37 jprice +# Fixed so it'll work with config.mak +# +# Revision 1.6 1999/03/01 05:46:43 jprice +# Turned off DEBUG define. +# +# Revision 1.5 1999/02/09 04:49:43 jprice +# Make makefile use common config.mak file +# +# Revision 1.4 1999/02/08 05:55:57 jprice +# Added Pat's 1937 kernel patches +# +# Revision 1.3 1999/02/04 03:09:59 jprice +# Added option to share constants (-d). +# +# Revision 1.2 1999/01/22 04:13:26 jprice +# Formating +# +# Revision 1.1.1.1 1999/01/20 05:51:01 jprice +# Imported sources +# +# +# Rev 1.8.1 10 Jan 1999 SRM +#Took out "/P-" from TLINK +#Changed "bcc" to "tcc" +# +# Rev 1.9 06 Dec 1998 8:45:40 patv +#Added new files for I/O subsystem. +# +# Rev 1.8 22 Jan 1998 14:50:06 patv +#Outdated stacks.asm. +# +# Rev 1.6 03 Jan 1998 8:36:50 patv +#Converted data area to SDA format +# +# Rev 1.5 30 Jan 1997 7:55:54 patv +#Added TSC flag for trace support. +# +# Rev 1.4 16 Jan 1997 12:46:42 patv +#pre-Release 0.92 feature additions +# +# Rev 1.3 29 Aug 1996 13:07:34 patv +#Bug fixes for v0.91b +# +# Rev 1.2 29 May 1996 21:03:32 patv +#bug fixes for v0.91a +# +# Rev 1.1 19 Feb 1996 3:35:38 patv +#Added NLS, int2f and config.sys processing +# +# Rev 1.0 02 Jul 1995 8:30:22 patv +#Initial revision. +# +# $EndLog$ +# + +!include "..\config.mak" + +RELEASE = 1.00 + +# +# Compiler and Options for Borland C++ +# ------------------------------------ +LIBPATH = . +INCLUDEPATH = ..\HDR +#AFLAGS = /Mx /DSTANDALONE=1 /I..\HDR +NASMFLAGS = -i../hdr/ +LIBS =..\LIB\DEVICE.LIB ..\LIB\LIBM.LIB +CFLAGS = -1- -O -Z -d -I..\hdr -I. \ + -D__STDC__=0;DEBUG;KERNEL;I86;PROTO;ASMSUPT +#CFLAGS = -1- -O -Z -d -I..\hdr -I. \ +# -D__STDC__=0;KERNEL;I86;PROTO;ASMSUPT +INITCFLAGS = $(CFLAGS) -zAINIT -zCINIT_TEXT -zPIGROUP +HDR=../hdr/ + +# *Implicit Rules* +.c.obj: + $(CC) $(CFLAGS) -c $< + +.cpp.obj: + $(CC) $(CFLAGS) -c $< + +.asm.obj: + $(NASM) $(NASMFLAGS) -f obj $< + +# *List Macros* + + +EXE_dependencies = \ + apisupt.obj \ + asmsupt.obj \ + blockio.obj \ + break.obj \ + chario.obj \ + config.obj \ + console.obj \ + dosidle.obj \ + dosfns.obj \ + dosnames.obj \ + dsk.obj \ + entry.obj \ + error.obj \ + execrh.obj \ + fatdir.obj \ + fatfs.obj \ + fattab.obj \ + fcbfns.obj \ + initoem.obj \ + int2f.obj \ + inthndlr.obj \ + io.obj \ + ioctl.obj \ + irqstack.obj \ + kernel.obj \ + main.obj \ + memmgr.obj \ + misc.obj \ + newstuff.obj \ + network.obj \ + nls.obj \ + nlssupt.obj \ + prf.obj \ + printer.obj \ + procsupt.obj \ + serial.obj \ + strings.obj \ + sysclk.obj \ + syspack.obj \ + systime.obj \ + task.obj + +# *Explicit Rules* + +production: ..\bin\kernel.sys + +..\bin\kernel.sys: kernel.sys + copy kernel.sys ..\bin + +kernel.sys: kernel.exe + ..\utils\exeflat kernel.exe kernel.sys 0x60 + +clobber: clean + $(RM) kernel.exe kernel.sys status.me + +clean: + $(RM) *.obj *.bak *.crf *.xrf *.map *.lst + +# XXX: This is a very ugly way of linking the kernel, forced upon us by the +# inability of Turbo `make' 2.0 to perform command line redirection. -- ror4 +kernel.exe: $(EXE_dependencies) $(LIBS) + del kernel.lib + $(LIBUTIL) kernel +entry +io +blockio +chario +dosfns +console + $(LIBUTIL) kernel +printer +serial +dsk +error +fatdir +fatfs + $(LIBUTIL) kernel +fattab +fcbfns +initoem +inthndlr +ioctl + $(LIBUTIL) kernel +main +config +memmgr +misc +newstuff +nls + $(LIBUTIL) kernel +dosnames +prf +strings +network +sysclk +syspack + $(LIBUTIL) kernel +systime +task +int2f +irqstack +apisupt + $(LIBUTIL) kernel +asmsupt +execrh +nlssupt +procsupt +break + $(LIBUTIL) kernel +dosidle + del kernel.bak + $(LINK) /m/c/L$(LIBPATH) kernel,kernel,kernel,kernel+$(LIBS); + del kernel.lib + +# *Individual File Dependencies* +kernel.obj: kernel.asm segs.inc + +console.obj: console.asm io.inc + +printer.obj: printer.asm io.inc + +serial.obj: serial.asm io.inc + +entry.obj: entry.asm segs.inc $(HDR)stacks.inc + +apisupt.obj: apisupt.asm segs.inc + +asmsupt.obj: asmsupt.asm segs.inc + +execrh.obj: execrh.asm segs.inc + +int2f.obj: int2f.asm segs.inc + +io.obj: io.asm segs.inc + +irqstack.obj: irqstack.asm + +nlssupt.obj: nlssupt.asm segs.inc + +procsupt.obj: procsupt.asm segs.inc $(HDR)stacks.inc + +dosidle.obj: dosidle.asm segs.inc + +# XXX: Special handling for initialization modules -- this is required because +# TC 2.01 cannot handle `#pragma option' like TC 3 can. -- ror4 +config.obj: config.c init-mod.h $(HDR)portab.h globals.h \ + $(HDR)device.h $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h \ + $(HDR)fat.h $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h \ + $(HDR)sft.h $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h \ + $(HDR)dirmatch.h $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h \ + $(HDR)error.h $(HDR)version.h proto.h + $(CC) $(INITCFLAGS) -c config.c + +initoem.obj: initoem.c init-mod.h $(HDR)portab.h globals.h \ + $(HDR)device.h $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h \ + $(HDR)fat.h $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h \ + $(HDR)sft.h $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h \ + $(HDR)dirmatch.h $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h \ + $(HDR)error.h $(HDR)version.h proto.h + $(CC) $(INITCFLAGS) -c initoem.c + +main.obj: main.c init-mod.h $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + $(CC) $(INITCFLAGS) -c main.c + +# XXX: I generated these using `gcc -MM' and `sed', so they may not be +# completely correct... -- ror4 +blockio.obj: blockio.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +break.obj: break.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +chario.obj: chario.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +dosfns.obj: dosfns.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +dosnames.obj: dosnames.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +dsk.obj: dsk.c $(HDR)portab.h globals.h $(HDR)device.h $(HDR)mcb.h \ + $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h $(HDR)fcb.h \ + $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h $(HDR)cds.h \ + $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h $(HDR)file.h \ + $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h $(HDR)version.h proto.h + +error.obj: error.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +fatdir.obj: fatdir.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +fatfs.obj: fatfs.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +fattab.obj: fattab.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +fcbfns.obj: fcbfns.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +inthndlr.obj: inthndlr.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +ioctl.obj: ioctl.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +memmgr.obj: memmgr.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +misc.obj: misc.c $(HDR)portab.h globals.h $(HDR)device.h $(HDR)mcb.h \ + $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h $(HDR)fcb.h \ + $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h $(HDR)cds.h \ + $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h $(HDR)file.h \ + $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h $(HDR)version.h proto.h + +newstuff.obj: newstuff.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +network.obj: network.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +nls.obj: nls.c $(HDR)portab.h globals.h $(HDR)device.h $(HDR)mcb.h \ + $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h $(HDR)fcb.h \ + $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h $(HDR)cds.h \ + $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h $(HDR)file.h \ + $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h $(HDR)version.h proto.h \ + 001-437.nls + +prf.obj: prf.c $(HDR)portab.h + +strings.obj: strings.c $(HDR)portab.h + +sysclk.obj: sysclk.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +syspack.obj: syspack.c $(HDR)portab.h globals.h $(HDR)device.h \ + $(HDR)mcb.h $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +systime.obj: systime.c $(HDR)portab.h $(HDR)time.h $(HDR)date.h \ + globals.h $(HDR)device.h $(HDR)mcb.h $(HDR)pcb.h $(HDR)fat.h \ + $(HDR)fcb.h $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h \ + $(HDR)cds.h $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h \ + $(HDR)file.h $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h \ + $(HDR)version.h proto.h + +task.obj: task.c $(HDR)portab.h globals.h $(HDR)device.h $(HDR)mcb.h \ + $(HDR)pcb.h $(HDR)date.h $(HDR)time.h $(HDR)fat.h $(HDR)fcb.h \ + $(HDR)tail.h $(HDR)process.h $(HDR)dcb.h $(HDR)sft.h $(HDR)cds.h \ + $(HDR)exe.h $(HDR)fnode.h $(HDR)dirmatch.h $(HDR)file.h \ + $(HDR)clock.h $(HDR)kbd.h $(HDR)error.h $(HDR)version.h proto.h + diff --git a/kernel/main.c b/kernel/main.c new file mode 100644 index 0000000..c5a37a6 --- /dev/null +++ b/kernel/main.c @@ -0,0 +1,524 @@ +/****************************************************************/ +/* */ +/* main.c */ +/* DOS-C */ +/* */ +/* Main Kernel Functions */ +/* */ +/* Copyright (c) 1995, 1996 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "init-mod.h" + +#define MAIN +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *mainRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:25 jhall1 + * Initial revision + * + * Revision 1.13 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.12 1999/09/23 04:40:48 jprice + * *** empty log message *** + * + * Revision 1.10 1999/08/25 03:18:09 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.9 1999/04/16 21:43:40 jprice + * ror4 multi-sector IO + * + * Revision 1.8 1999/04/16 12:21:22 jprice + * Steffen c-break handler changes + * + * Revision 1.7 1999/04/16 00:53:33 jprice + * Optimized FAT handling + * + * Revision 1.6 1999/04/12 03:21:17 jprice + * more ror4 patches. Changes for multi-block IO + * + * Revision 1.5 1999/04/11 04:33:39 jprice + * ror4 patches + * + * Revision 1.3 1999/04/04 22:57:47 jprice + * no message + * + * Revision 1.2 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:41:18 jprice + * New version without IPL.SYS + * + * Revision 1.5 1999/02/08 05:55:57 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.3 1999/01/30 08:28:12 jprice + * Clean up; Fixed bug with set attribute function. + * + * Revision 1.2 1999/01/22 04:13:26 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.12 06 Dec 1998 8:45:30 patv + * Changed due to new I/O subsystem. + * + * Rev 1.11 22 Jan 1998 4:09:24 patv + * Fixed pointer problems affecting SDA + * + * Rev 1.10 04 Jan 1998 23:15:20 patv + * Changed Log for strip utility + * + * Rev 1.9 04 Jan 1998 17:26:16 patv + * Corrected subdirectory bug + * + * Rev 1.8 03 Jan 1998 8:36:48 patv + * Converted data area to SDA format + * + * Rev 1.7 06 Feb 1997 21:35:46 patv + * Modified to support new version format and changed debug message to + * output drive letter instead of number. + * + * Rev 1.6 22 Jan 1997 13:05:02 patv + * Now does correct default drive initialization. + * + * Rev 1.5 16 Jan 1997 12:47:00 patv + * pre-Release 0.92 feature additions + * + * Rev 1.3 29 May 1996 21:03:32 patv + * bug fixes for v0.91a + * + * Rev 1.2 19 Feb 1996 3:21:36 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.1 01 Sep 1995 17:54:18 patv + * First GPL release. + * + * Rev 1.0 02 Jul 1995 8:33:18 patv + * Initial revision. + */ + +extern UWORD DaysSinceEpoch; +extern WORD days[2][13]; + +INIT BOOL ReadATClock(BYTE *, BYTE *, BYTE *, BYTE *); +VOID FAR init_call_WritePCClock(ULONG); + +INIT VOID configDone(VOID); +INIT static void InitIO(void); +INIT static COUNT BcdToByte(COUNT); +INIT static COUNT BcdToDay(BYTE *); + +INIT static VOID init_kernel(VOID); +INIT static VOID signon(VOID); +INIT VOID kernel(VOID); +INIT VOID FsConfig(VOID); + +INIT VOID main(void) +{ +#ifdef KDB + BootDrive = 1; +#endif + init_kernel(); +#ifdef DEBUG + /* Non-portable message kludge alert! */ + printf("KERNEL: Boot drive = %c\n", 'A' + BootDrive - 1); +#endif + signon(); + kernel(); +} + +INIT static VOID init_kernel(void) +{ + COUNT i; + os_major = MAJOR_RELEASE; + os_minor = MINOR_RELEASE; + cu_psp = DOS_PSP; + nblkdev = 0; + maxbksize = 0x200; + switchar = '/'; + dosidle_flag = 1; + + /* Init oem hook - returns memory size in KB */ + ram_top = init_oem(); + +#ifndef KDB + for (i = 0x20; i <= 0x3f; i++) + setvec(i, empty_handler); +#endif + + /* Initialize IO subsystem */ + InitIO(); + syscon = (struct dhdr FAR *)&con_dev; + clock = (struct dhdr FAR *)&clk_dev; + +#ifndef KDB + /* set interrupt vectors */ + setvec(0x1b, got_cbreak); + setvec(0x20, int20_handler); + setvec(0x21, int21_handler); + setvec(0x22, int22_handler); + setvec(0x23, empty_handler); + setvec(0x24, int24_handler); + setvec(0x25, low_int25_handler); + setvec(0x26, low_int26_handler); + setvec(0x27, int27_handler); + setvec(0x28, int28_handler); + setvec(0x2a, int2a_handler); + setvec(0x2f, int2f_handler); +#endif + + /* Initialize the screen handler for backspaces */ + scr_pos = 0; + break_ena = TRUE; + + /* Do first initialization of system variable buffers so that */ + /* we can read config.sys later. */ + lastdrive = Config.cfgLastdrive; + PreConfig(); + + /* Now config the temporary file system */ + FsConfig(); + +#ifndef KDB + /* Now process CONFIG.SYS */ + DoConfig(); + + lastdrive = Config.cfgLastdrive; + if (lastdrive < nblkdev) + lastdrive = nblkdev; + + /* and do final buffer allocation. */ + PostConfig(); + + /* Now config the final file system */ + FsConfig(); + + /* and process CONFIG.SYS one last time to load device drivers. */ + DoConfig(); + configDone(); +#endif + /* Now to initialize all special flags, etc. */ + mem_access_mode = FIRST_FIT; + verify_ena = FALSE; + InDOS = 0; + version_flags = 0; + pDirFileNode = 0; + dosidle_flag = 0; +} + +INIT VOID FsConfig(VOID) +{ + REG COUNT i; + date Date; + time Time; + BYTE x; + + /* Get the start-up date and time */ + Date = dos_getdate(); + Time = dos_gettime(); + + /* Initialize the file tables */ + for (i = 0; i < Config.cfgFiles; i++) + f_nodes[i].f_count = 0; + + /* The system file tables need special handling and are "hand */ + /* built. Included is the stdin, stdout, stdaux and atdprn. */ + sfthead->sftt_next = (sfttbl FAR *) - 1; + sfthead->sftt_count = Config.cfgFiles; + for (i = 0; i < sfthead->sftt_count; i++) + { + sfthead->sftt_table[i].sft_count = 0; + sfthead->sftt_table[i].sft_status = -1; + } + /* 0 is /dev/con (stdin) */ + sfthead->sftt_table[0].sft_count = 1; + sfthead->sftt_table[0].sft_mode = SFT_MREAD; + sfthead->sftt_table[0].sft_attrib = 0; + sfthead->sftt_table[0].sft_flags = + ((con_dev.dh_attr & ~SFT_MASK) & ~SFT_FSHARED) | SFT_FDEVICE | SFT_FEOF | SFT_FCONIN | SFT_FCONOUT; + sfthead->sftt_table[0].sft_psp = DOS_PSP; + sfthead->sftt_table[0].sft_date = Date; + sfthead->sftt_table[0].sft_time = Time; + fbcopy( + (VOID FAR *) "CON ", + (VOID FAR *) sfthead->sftt_table[0].sft_name, 11); + sfthead->sftt_table[0].sft_dev = (struct dhdr FAR *)&con_dev; + + /* 1 is /dev/con (stdout) */ + sfthead->sftt_table[1].sft_count = 1; + sfthead->sftt_table[1].sft_mode = SFT_MWRITE; + sfthead->sftt_table[1].sft_attrib = 0; + sfthead->sftt_table[1].sft_flags = + ((con_dev.dh_attr & ~SFT_MASK) & ~SFT_FSHARED) | SFT_FDEVICE | SFT_FEOF | SFT_FCONIN | SFT_FCONOUT; + sfthead->sftt_table[1].sft_psp = DOS_PSP; + sfthead->sftt_table[1].sft_date = Date; + sfthead->sftt_table[1].sft_time = Time; + fbcopy( + (VOID FAR *) "CON ", + (VOID FAR *) sfthead->sftt_table[1].sft_name, 11); + sfthead->sftt_table[1].sft_dev = (struct dhdr FAR *)&con_dev; + + /* 2 is /dev/con (stderr) */ + sfthead->sftt_table[2].sft_count = 1; + sfthead->sftt_table[2].sft_mode = SFT_MWRITE; + sfthead->sftt_table[2].sft_attrib = 0; + sfthead->sftt_table[2].sft_flags = + ((con_dev.dh_attr & ~SFT_MASK) & ~SFT_FSHARED) | SFT_FDEVICE | SFT_FEOF | SFT_FCONIN | SFT_FCONOUT; + sfthead->sftt_table[2].sft_psp = DOS_PSP; + sfthead->sftt_table[2].sft_date = Date; + sfthead->sftt_table[2].sft_time = Time; + fbcopy( + (VOID FAR *) "CON ", + (VOID FAR *) sfthead->sftt_table[2].sft_name, 11); + sfthead->sftt_table[2].sft_dev = (struct dhdr FAR *)&con_dev; + + /* 3 is /dev/aux */ + sfthead->sftt_table[3].sft_count = 1; + sfthead->sftt_table[3].sft_mode = SFT_MRDWR; + sfthead->sftt_table[3].sft_attrib = 0; + sfthead->sftt_table[3].sft_flags = + ((aux_dev.dh_attr & ~SFT_MASK) & ~SFT_FSHARED) | SFT_FDEVICE; + sfthead->sftt_table[3].sft_psp = DOS_PSP; + sfthead->sftt_table[3].sft_date = Date; + sfthead->sftt_table[3].sft_time = Time; + fbcopy( + (VOID FAR *) "AUX ", + (VOID FAR *) sfthead->sftt_table[3].sft_name, 11); + sfthead->sftt_table[3].sft_dev = (struct dhdr FAR *)&aux_dev; + + /* 4 is /dev/prn */ + sfthead->sftt_table[4].sft_count = 1; + sfthead->sftt_table[4].sft_mode = SFT_MWRITE; + sfthead->sftt_table[4].sft_attrib = 0; + sfthead->sftt_table[4].sft_flags = + ((prn_dev.dh_attr & ~SFT_MASK) & ~SFT_FSHARED) | SFT_FDEVICE; + sfthead->sftt_table[4].sft_psp = DOS_PSP; + sfthead->sftt_table[4].sft_date = Date; + sfthead->sftt_table[4].sft_time = Time; + fbcopy( + (VOID FAR *) "PRN ", + (VOID FAR *) sfthead->sftt_table[4].sft_name, 11); + sfthead->sftt_table[4].sft_dev = (struct dhdr FAR *)&prn_dev; + + /* Log-in the default drive. */ + /* Get the boot drive from the ipl and use it for default. */ + default_drive = BootDrive - 1; + + /* Initialzie the current directory structures */ + for (i = 0; i < lastdrive + 1; i++) + { + + fbcopy((VOID FAR *) "A:\\\0", + (VOID FAR *) CDSp->cds_table[i].cdsCurrentPath, 4); + CDSp->cds_table[i].cdsCurrentPath[0] += i; + + if (i < nblkdev) + { + CDSp->cds_table[i].cdsDpb = &blk_devices[i]; + CDSp->cds_table[i].cdsFlags = 0x4000; + } + else + { + CDSp->cds_table[i].cdsFlags = 0; + } + CDSp->cds_table[i].cdsStrtClst = 0xffff; + CDSp->cds_table[i].cdsParam = 0xffff; + CDSp->cds_table[i].cdsStoreUData = 0xffff; + CDSp->cds_table[i].cdsJoinOffset = 2; + } + + /* Initialze the disk buffer management functions */ + init_buffers(); +} + +INIT static VOID signon() +{ + printf("\nFreeDOS Kernel compatibility %d.%d\n%s\n", + os_major, os_minor, copyright); + printf(os_release, + REVISION_MAJOR, REVISION_MINOR, REVISION_SEQ, + BUILD); +} + +INIT static VOID kernel() +{ + seg asize; + BYTE FAR *ep, + *sp; + COUNT ret_code; +#ifndef KDB + static BYTE *path = "PATH=."; +#endif + +#ifdef KDB + kdb(); +#else + /* create the master environment area */ + if (DosMemAlloc(0x20, FIRST_FIT, (seg FAR *) & master_env, (seg FAR *) & asize) < 0) + fatal("cannot allocate master environment space"); + + /* populate it with the minimum environment */ + ++master_env; + ep = MK_FP(master_env, 0); + + for (sp = path; *sp != 0;) + *ep++ = *sp++; + + *ep++ = '\0'; + *ep++ = '\0'; + *((int FAR *)ep) = 0; + ep += sizeof(int); +#endif + RootPsp = ~0; + p_0(); +} + +extern BYTE FAR *lpBase; + +/* If cmdLine is NULL, this is an internal driver */ + +VOID init_device(struct dhdr FAR * dhp, BYTE FAR * cmdLine) +{ + request rq; + ULONG memtop = ((ULONG) ram_top) << 10; + ULONG maxmem = memtop - ((ULONG) FP_SEG(dhp) << 4); + + if (maxmem >= 0x10000) + maxmem = 0xFFFF; + + rq.r_unit = 0; + rq.r_status = 0; + rq.r_command = C_INIT; + rq.r_length = sizeof(request); + rq.r_endaddr = MK_FP(FP_SEG(dhp), maxmem); + rq.r_bpbptr = (void FAR *)(cmdLine ? cmdLine : "\n"); + rq.r_firstunit = nblkdev; + + execrh((request FAR *) & rq, dhp); + + if (cmdLine) + lpBase = rq.r_endaddr; + + /* check for a block device and update device control block */ + if (!(dhp->dh_attr & ATTR_CHAR) && (rq.r_nunits != 0)) + { + REG COUNT Index; + + for (Index = 0; Index < rq.r_nunits; Index++) + { + if (nblkdev) + blk_devices[nblkdev - 1].dpb_next = &blk_devices[nblkdev]; + + blk_devices[nblkdev].dpb_next = (void FAR *)0xFFFFFFFF; + blk_devices[nblkdev].dpb_unit = nblkdev; + blk_devices[nblkdev].dpb_subunit = Index; + blk_devices[nblkdev].dpb_device = dhp; + blk_devices[nblkdev].dpb_flags = M_CHANGED; + if ((CDSp) != 0) + { + CDSp->cds_table[nblkdev].cdsDpb = &blk_devices[nblkdev]; + CDSp->cds_table[nblkdev].cdsFlags = 0x4000; + } + ++nblkdev; + } + } + DPBp = &blk_devices[0]; +} + +struct dhdr FAR *link_dhdr(struct dhdr FAR * lp, struct dhdr FAR * dhp, BYTE FAR * cmdLine) +{ + lp->dh_next = dhp; + init_device(dhp, cmdLine); + return dhp; +} + +INIT static void InitIO(void) +{ + BYTE bcd_days[4], + bcd_minutes, + bcd_hours, + bcd_seconds; + ULONG ticks; + + /* Initialize driver chain */ + nul_dev.dh_next = (struct dhdr FAR *)&con_dev; + setvec(0x29, int29_handler); /* Requires Fast Con Driver */ + init_device((struct dhdr FAR *)&con_dev, NULL); + init_device((struct dhdr FAR *)&clk_dev, NULL); + init_device((struct dhdr FAR *)&blk_dev, NULL); + /* If AT clock exists, copy AT clock time to system clock */ + if (!ReadATClock(bcd_days, &bcd_hours, &bcd_minutes, &bcd_seconds)) + { + DaysSinceEpoch = BcdToDay(bcd_days); + /* + * This is a rather tricky calculation. The number of timer ticks per + * second is not exactly 18.2, but rather 0x1800b0 / 86400 = 19663 / 1080 + * (the timer interrupt updates the midnight flag when the tick count + * reaches 0x1800b0). Fortunately, 86400 * 19663 = 1698883200 < ULONG_MAX, + * so we can simply multiply the number of seconds by 19663 without + * worrying about overflow. :) -- ror4 + */ + ticks = (3600ul * BcdToByte(bcd_hours) + + 60ul * BcdToByte(bcd_minutes) + + BcdToByte(bcd_seconds)) * 19663ul / 1080ul; + WritePCClock(ticks); + } +} + +INIT static COUNT BcdToByte(COUNT x) +{ + return ((((x) >> 4) & 0xf) * 10 + ((x) & 0xf)); +} + +INIT static COUNT BcdToDay(BYTE * x) +{ + UWORD mon, + day, + yr; + + mon = BcdToByte(x[1]) - 1; + day = BcdToByte(x[0]) - 1; + yr = 100 * BcdToByte(x[3]) + BcdToByte(x[2]); + if (yr < 1980) + return 0; + else + { + day += days[is_leap_year(yr)][mon]; + while (--yr >= 1980) + day += is_leap_year(yr) ? 366 : 365; + return day; + } +} + diff --git a/kernel/memmgr.c b/kernel/memmgr.c new file mode 100644 index 0000000..8f6a665 --- /dev/null +++ b/kernel/memmgr.c @@ -0,0 +1,572 @@ +/****************************************************************/ +/* */ +/* memmgr.c */ +/* */ +/* Memory Manager for Core Allocation */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRING +static BYTE *memmgrRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:26 jhall1 + * Initial revision + * + * Revision 1.4 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.3 1999/08/25 03:18:09 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.2 1999/04/23 04:24:39 jprice + * Memory manager changes made by ska + * + * Revision 1.1.1.1 1999/03/29 15:41:20 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/08 05:55:57 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.3 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.2 1999/01/22 04:13:26 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.6 04 Jan 1998 23:15:18 patv + * Changed Log for strip utility + * + * Rev 1.5 16 Jan 1997 12:47:00 patv + * pre-Release 0.92 feature additions + * + * Rev 1.4 29 May 1996 21:03:34 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:21:36 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:54:20 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:51:58 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:33:08 patv + * Initial revision. + */ + +VOID mcb_init(); +VOID mcb_print(); +VOID show_chain(); + +#define nxtMCBsize(mcb,size) \ + MK_FP(far2para((VOID FAR *) (mcb)) + (size) + 1, 0) +#define nxtMCB(mcb) nxtMCBsize((mcb), (mcb)->m_size) + +#define mcbFree(mcb) ((mcb)->m_psp == FREE_PSP) +#define mcbValid(mcb) \ + ((mcb)->m_type == MCB_NORMAL || (mcb)->m_type == MCB_LAST) + +#define para2far(seg) (mcb FAR *)MK_FP((seg) , 0) + +/* + * Join any following unused MCBs to MCB 'p'. + * Return: + * SUCCESS: on success + * else: error number <> + */ +static COUNT joinMCBs(mcb FAR * p) +{ + mcb FAR *q; + + /* loop as long as the current MCB is not the last one in the chain + and the next MCB is unused */ + while (p->m_type == MCB_NORMAL && mcbFree(q = nxtMCB(p))) + { + if (!mcbValid(q)) + return DE_MCBDESTRY; + /* join both MCBs */ + p->m_type = q->m_type; /* possibly the next MCB is the last one */ + p->m_size += q->m_size + 1; /* one for q's MCB itself */ + q->m_type = 'K'; /* Invalidate the magic number */ + } + + return SUCCESS; +} + +seg far2para(VOID FAR * p) +{ + return FP_SEG(p) + (FP_OFF(p) >> 4); +} + +seg long2para(LONG size) +{ + return ((size + 0x0f) >> 4); +} + +/* + * Add a displacement to a far pointer and return the result normalized. + */ +VOID FAR *add_far(VOID FAR * fp, ULONG off) +{ + off += FP_OFF(fp); + + return MK_FP(FP_SEG(fp) + (UWORD) (off >> 4), (UWORD) off & 0xf); +} + +/* + * Return a normalized far pointer + */ +VOID FAR *adjust_far(VOID FAR * fp) +{ + /* and return an adddress adjusted to the nearest paragraph */ + /* boundary. */ + return MK_FP(FP_SEG(fp) + (FP_OFF(fp) >> 4), FP_OFF(fp) & 0xf); +} + +#undef REG +#define REG + +#ifdef KERNEL +/* Allocate a new memory area. *para is assigned to the segment of the + MCB rather then the segment of the data portion */ +/* If mode == LARGEST, asize MUST be != NULL and will always recieve the + largest available block, which is allocated. + If mode != LARGEST, asize maybe NULL, but if not, it is assigned to the + size of the largest available block only on failure. + size is the minimum size of the block to search for, + even if mode == LARGEST. + */ +COUNT DosMemAlloc(UWORD size, COUNT mode, seg FAR * para, UWORD FAR * asize) +{ + REG mcb FAR *p; + mcb FAR *foundSeg; + mcb FAR *biggestSeg; + + /* Initialize */ + p = para2far(first_mcb); + biggestSeg = foundSeg = NULL; + + /* Search through memory blocks */ + FOREVER + { + /* check for corruption */ + if (!mcbValid(p)) + return DE_MCBDESTRY; + + if (mcbFree(p)) + { /* unused block, check if it applies to the rule */ + if (joinMCBs(p) != SUCCESS) /* join following unused blocks */ + return DE_MCBDESTRY; /* error */ + + if (!biggestSeg || biggestSeg->m_size < p->m_size) + biggestSeg = p; + + if (p->m_size >= size) + { /* if the block is too small, ignore */ + /* this block has a "match" size, try the rule set */ + switch (mode) + { + case LAST_FIT: /* search for last possible */ + default: + foundSeg = p; + break; + + case LARGEST: /* grab the biggest block */ + /* it is calculated when the MCB chain + was completely checked */ + break; + + case BEST_FIT: /* first, but smallest block */ + if (!foundSeg || foundSeg->m_size > p->m_size) + /* better match found */ + foundSeg = p; + break; + + case FIRST_FIT: /* first possible */ + foundSeg = p; + goto stopIt; /* OK, rest of chain can be ignored */ + } + } + } + + if (p->m_type == MCB_LAST) + break; /* end of chain reached */ + + p = nxtMCB(p); /* advance to next MCB */ + } + + if (mode == LARGEST && biggestSeg && biggestSeg->m_size >= size) + *asize = (foundSeg = biggestSeg)->m_size; + + if (!foundSeg || !foundSeg->m_size) + { /* no block to fullfill the request */ + if (asize) + *asize = biggestSeg ? biggestSeg->m_size : 0; + return DE_NOMEM; + } + +stopIt: /* reached from FIRST_FIT on match */ + + if (mode != LARGEST && size != foundSeg->m_size) + { + /* Split the found buffer because it is larger than requested */ + /* foundSeg := pointer to allocated block + p := pointer to MCB that will form the rest of the block + */ + if (mode == LAST_FIT) + { + /* allocate the block from the end of the found block */ + p = foundSeg; + p->m_size -= size + 1; /* size+1 paragraphes are allocated by + the new segment (+1 for MCB itself) */ + foundSeg = nxtMCB(p); + + /* initialize stuff because foundSeg > p */ + foundSeg->m_type = p->m_type; + p->m_type = MCB_NORMAL; + } + else + { /* all other modes allocate from the beginning */ + p = nxtMCBsize(foundSeg, size); + p->m_size = foundSeg->m_size - size - 1; + + /* initialize stuff because p > foundSeg */ + p->m_type = foundSeg->m_type; + foundSeg->m_type = MCB_NORMAL; + } + + /* Already initialized: + p->m_size, ->m_type, foundSeg->m_type + */ + p->m_psp = FREE_PSP; /* unused */ + + foundSeg->m_size = size; + } + + /* Already initialized: + foundSeg->m_size, ->m_type + */ + foundSeg->m_psp = cu_psp; /* the new block is for current process */ + foundSeg->m_name[0] = '\0'; + + *para = far2para((VOID FAR *) (BYTE FAR *) foundSeg); + return SUCCESS; +} + +COUNT FAR init_call_DosMemAlloc(UWORD size, COUNT mode, seg FAR * para, UWORD FAR * asize) +{ + return DosMemAlloc(size, mode, para, asize); +} + +/* + * Unlike the name and the original prototype could suggest, this function + * is used to return the _size_ of the largest available block rather than + * the block itself. + * + * Known bug: a memory area with a size of the data area of 0 (zero) is + * not considered a "largest" block. <> + */ +COUNT DosMemLargest(UWORD FAR * size) +{ + REG mcb FAR *p; + mcb FAR *q; + COUNT found; + + /* Initialize */ + p = para2far(first_mcb); + + /* Cycle through the whole MCB chain to find the largest unused + area. Join all unused areas together. */ + *size = 0; /* nothing found */ + FOREVER + { + if (!mcbValid(p)) /* corrupted MCB chain */ + return DE_MCBDESTRY; + + if (mcbFree(p)) + { /* test if this is the largest block */ + /* first join this unused block with all following unused + blocks */ + if (joinMCBs(p) != SUCCESS) + return DE_MCBDESTRY; + + /* Now test */ + if (*size < p->m_size) + *size = p->m_size; + } + + if (p->m_type == MCB_LAST) /* that was last one in chain */ + break; + p = nxtMCB(p); + } + + /* If *size is still zero, aka nothing had changed, either no unused + block was found at all or a zero-length block only. + Both is considered as a failure */ + return *size ? SUCCESS : DE_NOMEM; +} + +/* + * Deallocate a memory block. para is the segment of the MCB itself + * This function can be called with para == 0, which eases other parts + * of the kernel. + */ +COUNT DosMemFree(UWORD para) +{ + REG mcb FAR *p; + COUNT i; + + if (!para) /* let esp. the kernel call this fct with para==0 */ + return DE_INVLDMCB; + + /* Initialize */ + p = para2far(para); + + /* check for corruption */ + if (!mcbValid(p)) + return DE_INVLDMCB; + + /* Mark the mcb as free so that we can later */ + /* merge with other surrounding free mcb's */ + p->m_psp = FREE_PSP; + for (i = 0; i < 8; i++) + p->m_name[i] = '\0'; + +#if 0 + /* Moved into allocating functions -- 1999/04/21 ska */ + /* Now merge free blocks */ + for (p = (mcb FAR *) (MK_FP(first_mcb, 0)); p->m_type != MCB_LAST; p = q) + { + /* make q a pointer to the next block */ + q = nxtMCB(p); + /* and test for corruption */ + if (q->m_type != MCB_NORMAL && q->m_type != MCB_LAST) + return DE_MCBDESTRY; + if (p->m_psp != FREE_PSP) + continue; + + /* test if next is free - if so merge */ + if (q->m_psp == FREE_PSP) + { + /* Always flow type down on free */ + p->m_type = q->m_type; + p->m_size += q->m_size + 1; + /* and make pointers the same */ + /* since the next free is now */ + /* this block */ + q = p; + } + } +#endif + return SUCCESS; +} + +/* + * Resize an allocated memory block. + * para is the segment of the data portion of the block rather than + * the segment of the MCB itself. + * + * If the block shall grow, it is resized to the maximal size less than + * or equal to size. This is the way MS DOS is reported to work. + */ +COUNT DosMemChange(UWORD para, UWORD size, UWORD * maxSize) +{ + REG mcb FAR *p, + FAR * q; + REG COUNT i; + + /* Initialize */ + p = para2far(para - 1); /* pointer to MCB */ + + /* check for corruption */ + if (!mcbValid(p)) + return DE_MCBDESTRY; + + /* check if to grow the block */ + if (size > p->m_size) + { + /* first try to make the MCB larger by joining with any following + unused blocks */ + if (joinMCBs(p) != SUCCESS) + return DE_MCBDESTRY; + + if (size > p->m_size) + { /* block is still too small */ + if (maxSize) + *maxSize = p->m_size; + return DE_NOMEM; + } + } + + /* shrink it down */ + /* From here on, nothing can fail */ + if (size < p->m_size) + { + /* make q a pointer to the new next block */ + q = nxtMCBsize(p, size); + /* reduce the size of p and add difference to q */ + q->m_type = p->m_type; + q->m_size = p->m_size - size - 1; + + p->m_size = size; + + /* Make certian the old psp is not last (if it was) */ + p->m_type = MCB_NORMAL; + + /* Mark the mcb as free so that we can later */ + /* merge with other surrounding free mcb's */ + q->m_psp = FREE_PSP; + for (i = 0; i < 8; i++) + q->m_name[i] = '\0'; + } + return SUCCESS; +} + +/* + * Check the MCB chain for allocation corruption + */ +COUNT DosMemCheck(void) +{ + REG mcb FAR *p; + + /* Initialize */ + p = para2far(first_mcb); + + /* Search through memory blocks */ + while (p->m_type != MCB_LAST) /* not all MCBs touched */ + { + /* check for corruption */ + if (p->m_type != MCB_NORMAL) + return DE_MCBDESTRY; + + /* not corrupted - but not end, bump the pointer */ + p = nxtMCB(p); + } + + return SUCCESS; +} + +COUNT FreeProcessMem(UWORD ps) +{ + mcb FAR *p; + + /* Initialize */ + p = para2far(first_mcb); + + /* Search through memory blocks */ + while (mcbValid(p)) /* check for corruption */ + { + if (p->m_psp == ps) + DosMemFree(FP_SEG(p)); + + /* not corrupted - if last we're OK! */ + if (p->m_type == MCB_LAST) + return SUCCESS; + + p = nxtMCB(p); + } + + return DE_MCBDESTRY; +} + +#if 0 + /* seems to be superceeded by DosMemLargest + -- 1999/04/21 ska */ +COUNT DosGetLargestBlock(UWORD FAR * block) +{ + UWORD sz = 0; + mcb FAR *p; + *block = sz; + + /* Initialize */ + p = (mcb FAR *) (MK_FP(first_mcb, 0)); + + /* Search through memory blocks */ + for (;;) + { + /* check for corruption */ + if (p->m_type != MCB_NORMAL && p->m_type != MCB_LAST) + return DE_MCBDESTRY; + + if (p->m_psp == FREE_PSP && p->m_size > sz) + sz = p->m_size; + + /* not corrupted - if last we're OK! */ + if (p->m_type == MCB_LAST) + break; + p = nxtMCB(p); + + } + *block = sz; + return SUCCESS; +} +#endif + +VOID show_chain(void) +{ + mcb FAR *p = para2far(first_mcb); + + for (;;) + { + mcb_print(p); + if (p->m_type == MCB_LAST || p->m_type != MCB_NORMAL) + return; + else + p = nxtMCB(p); + } +} + +VOID mcb_print(mcb FAR * mcbp) +{ + static BYTE buff[9]; + VOID _fmemcpy(); + + _fmemcpy((BYTE FAR *) buff, (BYTE FAR *) (mcbp->m_name), 8); + buff[8] = '\0'; + printf("%04x:%04x -> |%s| m_type = 0x%02x '%c'; m_psp = 0x%04x; m_size = 0x%04x\n", + FP_SEG(mcbp), + FP_OFF(mcbp), + *buff == '\0' ? "*NO-ID*" : buff, + mcbp->m_type, mcbp->m_type > ' ' ? mcbp->m_type : ' ', + mcbp->m_psp, + mcbp->m_size); +} + +VOID _fmemcpy(BYTE FAR * d, BYTE FAR * s, REG COUNT n) +{ + while (n--) + *d++ = *s++; + +} +#endif diff --git a/kernel/misc.c b/kernel/misc.c new file mode 100644 index 0000000..0fe5581 --- /dev/null +++ b/kernel/misc.c @@ -0,0 +1,140 @@ +/****************************************************************/ +/* */ +/* misc.c */ +/* */ +/* Miscellaneous Kernel Functions */ +/* */ +/* Copyright (c) 1993 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" + +#ifdef VERSION_STRINGS +static BYTE *miscRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:27 jhall1 + * Initial revision + * + * Revision 1.4 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.3 1999/05/03 06:25:45 jprice + * Patches from ror4 and many changed of signed to unsigned variables. + * + * Revision 1.2 1999/04/23 04:24:39 jprice + * Memory manager changes made by ska + * + * Revision 1.1.1.1 1999/03/29 15:42:19 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:43:28 jprice + * Fixed findfirst function to find volume label with Windows long filenames + * + * Revision 1.2 1999/01/22 04:15:28 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * + * Rev 1.5 04 Jan 1998 23:14:36 patv + * Changed Log for strip utility + * + * Rev 1.4 29 May 1996 21:15:18 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:20:12 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:48:46 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:50:28 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:06:28 patv + * Initial revision. + */ + +#include "globals.h" + +VOID scopy(REG BYTE * s, REG BYTE * d) +{ + while (*s) + *d++ = *s++; + *d = '\0'; +} + +VOID FAR init_call_scopy(REG BYTE * s, REG BYTE * d) +{ + scopy(s, d); +} + +VOID fscopy(REG BYTE FAR * s, REG BYTE FAR * d) +{ + while (*s) + *d++ = *s++; + *d = '\0'; +} + +VOID fsncopy(BYTE FAR * s, BYTE FAR * d, REG COUNT n) +{ + while (*s && n--) + *d++ = *s++; + *d = '\0'; +} + +#ifndef ASMSUPT +VOID bcopy(REG BYTE * s, REG BYTE * d, REG COUNT n) +{ + while (n--) + *d++ = *s++; +} + +VOID fbcopy(REG VOID FAR * s, REG VOID FAR * d, REG COUNT n) +{ + while (n--) + *((BYTE FAR *) d)++ = *((BYTE FAR *) s)++; +} + +VOID fmemset(REG VOID FAR * s, REG int ch, REG COUNT n) +{ + while (n--) + *((BYTE FAR *) s)++ = ch; +} + +#endif + +VOID FAR init_call_fbcopy(REG VOID FAR * s, REG VOID FAR * d, REG COUNT n) +{ + fbcopy(s, d, n); +} + +VOID fmemset(VOID FAR *, int, COUNT); + +VOID FAR init_call_fmemset(REG VOID FAR * s, REG int ch, REG COUNT n) +{ + fmemset(s, ch, n); +} diff --git a/kernel/network.c b/kernel/network.c new file mode 100644 index 0000000..f627d60 --- /dev/null +++ b/kernel/network.c @@ -0,0 +1,209 @@ +/****************************************************************/ +/* */ +/* network.c */ +/* DOS-C */ +/* */ +/* Networking Support functions */ +/* */ +/* Copyright (c) 1995, 1999 */ +/* James Tabor */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:27 jhall1 + * Initial revision + * + * Revision 1.3 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.2 1999/09/23 04:40:48 jprice + * *** empty log message *** + * + */ + +UWORD get_machine_name(BYTE FAR * netname) +{ + BYTE FAR *xn; + + xn = MK_FP(net_name, 0); + fbcopy((BYTE FAR *) netname, xn, 15); + return (NetBios); + +} + +VOID set_machine_name(BYTE FAR * netname, UWORD name_num) +{ + BYTE FAR *xn; + + xn = MK_FP(net_name, 0); + NetBios = name_num; + fbcopy(xn, (BYTE FAR *) netname, 15); + net_set_count++; + +} + +/* + * Read/Write from/to remote file. + * SFT gets updated with the amount of bytes r/w. + * + */ +UCOUNT Remote_RW(UWORD func, UCOUNT n, BYTE FAR * bp, sft FAR * s, COUNT FAR * err) +{ + + BYTE FAR *save_dta; + UWORD rc, + rx; + + save_dta = dta; + lpCurSft = (sfttbl FAR *) s; + dta = bp; + rx = int2f_Remote_call(func, 0, n, 0, (VOID FAR *) s, 0, (VOID FAR *) & rc); + dta = save_dta; + *err = rx; + return ((UCOUNT) rc); +} + +/* + + */ +COUNT Remote_find(UWORD func, UWORD attrib, BYTE FAR * name, REG dmatch FAR * dmp) +{ + COUNT i, + x; + BYTE FAR *p, + *q; + struct dirent FAR *SDp = (struct dirent FAR *)&SearchDir; + + if (func == REM_FINDFIRST) + { + truename(name, PriPathName, FALSE); + SAttr = (BYTE) attrib; + } + fsncopy(dta, (BYTE FAR *) & TempBuffer, 21); + p = dta; + dta = (BYTE FAR *) & TempBuffer; + i = int2f_Remote_call(func, 0, 0, 0, 0, 0, 0); + dta = p; + fsncopy((BYTE FAR *) & TempBuffer[1], &dta[1], 20); + + if (i != 0) + return i; + + dmp->dm_attr_fnd = (BYTE) SDp->dir_attrib; + dmp->dm_time = SDp->dir_time; + dmp->dm_date = SDp->dir_date; + dmp->dm_size = (LONG) SDp->dir_size; + +/* + Needed Code Rep-off.;) + */ + p = dmp->dm_name; + if (SDp->dir_name[0] == '.') + { + for (x = 0, q = (BYTE FAR *) SDp->dir_name; x < FNAME_SIZE; x++) + { + if (*q == ' ') + break; + *p++ = *q++; + } + } + else + { + for (x = 0, q = (BYTE FAR *) SDp->dir_name; x < FNAME_SIZE; x++) + { + if (*q == ' ') + break; + *p++ = *q++; + } + if (SDp->dir_ext[0] != ' ') + { + *p++ = '.'; + for (x = 0, q = (BYTE FAR *) SDp->dir_ext; x < FEXT_SIZE; x++) + { + if (*q == ' ') + break; + *p++ = *q++; + } + } + } + *p++ = NULL; + + return i; +} + +/* + * Open Existing Remote File, SDA First FN ptr -> Fully qualified name. + * open func 3d + * Create/Truncate w/o CDS Remote File + * Extended Open/Create File + */ +UWORD Remote_OCT(UWORD func, BYTE FAR * name, UWORD pw, sft FAR * s) +{ + truename(name, PriPathName, FALSE); + lpCurSft = (sfttbl FAR *) s; + return (int2f_Remote_call(func, 0, 0, 0, (VOID FAR *) s, 0, MK_FP(0, pw))); +} + +COUNT Remote_GSattr(UWORD func, BYTE FAR * name, UWORD FAR * attrp) +{ + static char srfa[10]; + COUNT drive; + struct cds FAR *p; + + truename(name, PriPathName, TRUE); + drive = PriPathName[0]; + drive -= 'A'; + truename(name, PriPathName, FALSE); + + if (CDSp->cds_table[drive].cdsFlags & 0x8000) + { + p = current_ldt; + current_ldt = &CDSp->cds_table[drive]; + if (func == REM_GETATTRZ) + { + + if (int2f_Remote_call(func, 0, 0, 0, 0, 0, (VOID FAR *) srfa) != 0) + { + current_ldt = p; + goto AEXIT; + } + *attrp = (UWORD) srfa[0]; + goto GEXIT; + } + int2f_Remote_call(func, 0, 0, 0, 0, 0, MK_FP(0, attrp)); + GEXIT: + current_ldt = p; + return (COUNT) 0; + } +AEXIT: + return (COUNT) 1; + +} + + diff --git a/kernel/newstuff.c b/kernel/newstuff.c new file mode 100644 index 0000000..f4d0e99 --- /dev/null +++ b/kernel/newstuff.c @@ -0,0 +1,326 @@ +/****************************************************************/ +/* */ +/* newstuff.c */ +/* DOS-C */ +/* */ +/* Copyright (c) 1996 */ +/* Svante Frey */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef VERSION_STRINGS +static BYTE *mainRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:27 jhall1 + * Initial revision + * + * Revision 1.5 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.4 1999/08/25 03:18:09 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.3 1999/04/11 04:33:39 jprice + * ror4 patches + * + * Revision 1.2 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:41:22 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/08 05:55:57 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.3 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.2 1999/01/22 04:13:26 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.4 06 Dec 1998 8:49:02 patv + * Bug fixes. + * + * Rev 1.3 04 Jan 1998 23:15:22 patv + * Changed Log for strip utility + * + * Rev 1.2 04 Jan 1998 17:26:14 patv + * Corrected subdirectory bug + * + * Rev 1.1 22 Jan 1997 13:21:22 patv + * pre-0.92 Svante Frey bug fixes. + */ + +#include "portab.h" +#include "globals.h" +#include "proto.h" + +int SetJFTSize(UWORD nHandles) +{ + UWORD block, + maxBlock; + psp FAR *ppsp = MK_FP(cu_psp, 0); + UBYTE FAR *newtab; + COUNT i; + + if (nHandles <= ppsp->ps_maxfiles) + { + ppsp->ps_maxfiles = nHandles; + return SUCCESS; + } + + if ((DosMemAlloc((nHandles + 0xf) >> 4, mem_access_mode, &block, &maxBlock)) < 0) + return DE_NOMEM; + + ++block; + newtab = MK_FP(block, 0); + + for (i = 0; i < ppsp->ps_maxfiles; i++) + newtab[i] = ppsp->ps_filetab[i]; + + for (; i < nHandles; i++) + newtab[i] = 0xff; + + ppsp->ps_maxfiles = nHandles; + ppsp->ps_filetab = newtab; + + return SUCCESS; +} + +int DosMkTmp(BYTE FAR * pathname, UWORD attr) +{ + /* create filename from current date and time */ + static const char tokens[] = "0123456789ABCDEF"; + char FAR *ptmp = pathname; + BYTE wd, + month, + day; + BYTE h, + m, + s, + hund; + WORD sh; + WORD year; + int rc; + + while (*ptmp) + ptmp++; + + if (ptmp == pathname || (ptmp[-1] != '\\' && ptmp[-1] != '/')) + *ptmp++ = '\\'; + + DosGetDate(&wd, &month, &day, (COUNT FAR *) & year); + DosGetTime(&h, &m, &s, &hund); + + sh = s * 100 + hund; + + ptmp[0] = tokens[year & 0xf]; + ptmp[1] = tokens[month]; + ptmp[2] = tokens[day & 0xf]; + ptmp[3] = tokens[h & 0xf]; + ptmp[4] = tokens[m & 0xf]; + ptmp[5] = tokens[(sh >> 8) & 0xf]; + ptmp[6] = tokens[(sh >> 4) & 0xf]; + ptmp[7] = tokens[sh & 0xf]; + ptmp[8] = '.'; + ptmp[9] = 'A'; + ptmp[10] = 'A'; + ptmp[11] = 'A'; + ptmp[12] = 0; + + while ((rc = DosOpen(pathname, 0)) >= 0) + { + DosClose(rc); + + if (++ptmp[11] > 'Z') + { + if (++ptmp[10] > 'Z') + { + if (++ptmp[9] > 'Z') + return DE_TOOMANY; + + ptmp[10] = 'A'; + } + ptmp[11] = 'A'; + } + } + + if (rc == DE_FILENOTFND) + { + rc = DosCreat(pathname, attr); + } + return rc; +} +/* + * Added support for external and internal calls. + * Clean buffer before use. Make the true path and expand file names. + * Example: *.* -> ????????.??? as in the currect way. + */ +int truename(char FAR * src, char FAR * dest, COUNT t) +{ + static char buf[128] = "A:\\"; + char *bufp = buf + 3; + COUNT i, + n; + BYTE far *test; + REG struct cds FAR *cdsp; + + fbcopy((VOID FAR *) "A:\\\0\0\0\0\0\0\0", (VOID FAR *) buf, 10); + + /* First, adjust the source pointer */ + src = adjust_far(src); + + /* Do we have a drive? */ + if (src[1] == ':') + { + buf[0] = (src[0] | 0x20) + 'A' - 'a'; + + if (buf[0] >= lastdrive + 'A') + return DE_PATHNOTFND; + + src += 2; + } + else + buf[0] = default_drive + 'A'; + + i = buf[0] - '@'; + + cdsp = &CDSp->cds_table[i - 1]; + + if (cdsp->cdsFlags & 0x8000) + { + QRemote_Fn(src, dest); + if (t == FALSE) + { + bufp += 4; + fsncopy((BYTE FAR *) & cdsp->cdsCurrentPath[0], (BYTE FAR *) & buf[0], cdsp->cdsJoinOffset); + *bufp++ = '\\'; + } + } + + if (*src != '\\' && *src != '/') /* append current dir */ + { + DosGetCuDir(i, bufp); + if (*bufp) + { + while (*bufp) + bufp++; + *bufp++ = '\\'; + } + } + else + src++; + + /* convert all forward slashes to backslashes, and uppercase all characters */ + while (*src) + { + char c; + + switch ((c = *src++)) + { +/* added *.*, *., * support. + */ + case '*': + if (*src == '.') + { + n = 8; + while (n--) + *bufp++ = '?'; + break; + } + else + { + if (src[-2] == '.') + { + n = 3; + while (n--) + *bufp++ = '?'; + break; + } + else + { + n = 8; + while (n--) + *bufp++ = '?'; + break; + } + } + + case '/': /* convert to backslash */ + case '\\': + + if (bufp[-1] != '\\') + *bufp++ = '\\'; + break; + + /* look for '.' and '..' dir entries */ + case '.': + if (bufp[-1] == '\\') + { + if (*src == '.' && (src[1] == '/' || src[1] == '\\' || !src[1])) + { + /* '..' dir entry: rewind bufp to last backslash */ + + for (bufp -= 2; *bufp != '\\'; bufp--) + { + if (bufp < buf + 2) /* '..' illegal in root dir */ + return DE_PATHNOTFND; + } + src++; + if (bufp[-1] == ':') + bufp++; + } + else if (*src == '/' || *src == '\\' || *src == 0) + --bufp; + } + else + *bufp++ = c; + break; + + default: + *bufp++ = c; + break; + } + } + /* remove trailing backslashes */ + while (bufp[-1] == '\\') + --bufp; + + if (bufp == buf + 2) + ++bufp; + + *bufp++ = 0; + + /* finally, uppercase everything */ + upString(buf); + + /* copy to user's buffer */ + fbcopy(buf, dest, bufp - buf); + + return SUCCESS; +} + diff --git a/kernel/nls.c b/kernel/nls.c new file mode 100644 index 0000000..582998f --- /dev/null +++ b/kernel/nls.c @@ -0,0 +1,667 @@ +/****************************************************************/ +/* */ +/* nls.c */ +/* DOS-C */ +/* */ +/* National Languge Support functions and data structures */ +/* */ +/* Copyright (c) 1995, 1996 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* Copyright (c) 1995, 1996 */ +/* Steffen Kaiser */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:29 jhall1 + * Initial revision + * + * Revision 1.7 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.6 1999/09/23 04:40:48 jprice + * *** empty log message *** + * + * Revision 1.4 1999/08/25 03:18:09 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.3 1999/05/03 06:25:45 jprice + * Patches from ror4 and many changed of signed to unsigned variables. + * + * Revision 1.2 1999/04/16 00:53:33 jprice + * Optimized FAT handling + * + * Revision 1.1.1.1 1999/03/29 15:41:24 jprice + * New version without IPL.SYS + * + * Revision 1.6 1999/02/08 05:55:57 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.5 1999/02/04 03:12:08 jprice + * Removed extra text. Made .exe smaller. + * + * Revision 1.4 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.3 1999/01/30 08:28:12 jprice + * Clean up; Fixed bug with set attribute function. + * + * Revision 1.2 1999/01/22 04:13:26 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.4 04 Jan 1998 23:15:16 patv + * Changed Log for strip utility + * + * Rev 1.3 16 Jan 1997 12:46:54 patv + * pre-Release 0.92 feature additions + * + * Rev 1.2 29 May 1996 21:03:46 patv + * bug fixes for v0.91a + * + * Rev 1.1 19 Feb 1996 4:34:46 patv + * Corrected typo + * + * Rev 1.0 19 Feb 1996 3:21:46 patv + * Added NLS, int2f and config.sys processing + */ + +extern UWORD internalUpcase(UWORD c); + +#ifdef __TURBOC__ +/* TC 2.01 require these. :( -- ror4 */ +void __int__(int); +void __emit__(); +#endif + +/* one byte alignment */ + +#if defined(_MSC_VER) +#define asm __asm +#pragma pack(1) +#elif defined(_QC) || defined(__WATCOM__) +#pragma pack(1) +#elif defined(__ZTC__) +#pragma ZTC align 1 +#elif defined(__TURBOC__) && (__TURBOC__ > 0x202) +#pragma option -a- +#endif + +struct ctryInfo +{ /* Country Information DOS-38 */ + WORD dateFmt; /* 0: USA, 1: Europe, 2: Japan */ + char curr[5]; /* ASCIZ of currency string */ + char thSep[2]; /* ASCIZ of thousand's separator */ + char point[2]; /* ASCIZ of decimal point */ + char dateSep[2]; /* ASCIZ of date separator */ + char timeSep[2]; /* ASCIZ of time separator */ + BYTE currFmt; /* format of currency: + bit 0: currency string is placed 0: before, 1: behind number + bit 1: currency string and number are separated by a space; 0: No, 1: Yes + */ + BYTE prescision; /* */ + BYTE timeFmt; /* time format: 0: 12 hours; 1: 24 houres */ + VOID(FAR * upCaseFct) (VOID); /* far call to a function mapping character in register AL */ + char dataSep[2]; /* ASCIZ of separator in data records */ +}; + +struct _VectorTable +{ + VOID FAR *Table; + BYTE FnCode; +}; + +struct _NlsInfo +{ + struct extCtryInfo + { + BYTE reserved[8]; + BYTE countryFname[64]; + WORD sysCodePage; + WORD nFnEntries; + struct _VectorTable VectorTable[6]; + + /* Extended Country Information DOS-65-01 */ + WORD countryCode; /* current COUNTRY= code */ + WORD codePage; /* current code page (CP) */ + + struct ctryInfo nlsCtryInfo; + } + nlsExtCtryInfo; + +/* characters of Yes/No prompt for DOS-65-23 */ + char yesCharacter; + char noCharacter; + +/* upcased characters for ECS-ASCII > 0x7f for DOS-65-02 */ + WORD upNCsize; /* number of entries in the following array */ + char upNormCh[128]; + +/* upcased characters for ECS-ASCII > 0x7f for file names for DOS-65-04 */ + WORD upFCsize; /* number of entries in the following array */ + char upFileCh[128]; + +/* collating sequence for ECS-ASCII 0..0xff for DOS-65-06 */ + WORD collSize; /* number of entries in the following array */ + char collSeq[256]; + +/* DBC support for DOS-65-07 */ + WORD dbcSize; /* number of entries in the following array */ + /* char dbcTable[1024]; no DBC support */ + WORD dbcEndMarker; /* contains always 0 */ + +/* in file names permittable characters for DOS-65-05 */ + struct chFileNames + { + WORD fnSize; /* size of this structure */ + BYTE dummy1; + char firstCh, + lastCh; /* first, last permittable character */ + BYTE dummy2; + char firstExcl, + lastExcl; /* first, last excluded character */ + BYTE dummy3; + BYTE numSep; /* number of file name separators */ + char fnSeparators[14]; + } + nlsFn; +} +nlsInfo +#ifdef INIT_NLS_049 += /* let's initialize it with values for Germany */ +#include "049-437.nls" +#else += /* let's initialize it with default values (USA) */ +#include "001-437.nls" +#endif + ; + +#define normalCh nlsInfo.upNormCh +#define fileCh nlsInfo.upFileCh +#define yesChar nlsInfo.yesCharacter +#define noChar nlsInfo.noCharacter + +#define PathSep(c) ((c)=='/'||(c)=='\\') +#define DriveChar(c) (((c)>='A'&&(c)<='Z')||((c)>='a'&&(c)<='z')) + +/* COUNTRY.SYS structures */ +struct CpiHeader +{ + BYTE name[8]; /* signature */ + BYTE reserved[8]; + WORD nPointers; /* size of following array */ + + struct + { + BYTE pointerType; /* always 1 */ + DWORD offset; /* offset to data */ + } + pointer[1]; +}; + +struct CountryRecord +{ + WORD length; /* size of record */ + WORD country; /* country code */ + WORD codePage; /* code page */ + WORD reserved[2]; + DWORD subCountryOffset; /* offset to data record */ +}; + +struct CountryTableDescr +{ + WORD length; /* size of structure */ + WORD id; /* table type id */ + DWORD offset; /* offset to table data */ +}; + +/* standard alignment */ + +#if defined (_MSC_VER) || defined(_QC) || defined(__WATCOMC__) +#pragma pack() +#elif defined (__ZTC__) +#pragma ZTC align +#elif defined(__TURBOC__) && (__TURBOC__ > 0x202) +#pragma option -a. +#endif + +COUNT NlsFuncInst(VOID) +{ + BYTE cNlsRet; + +#ifndef __TURBOC__ + asm + { + xor bx, + bx + mov ax, + 0x1400 + int 0x2F + mov cNlsRet, + al + } +#else + _BX = 0; + _AX = 0x1400; + __int__(0x2f); + cNlsRet = _AL; +#endif + + /* Return the al register as sign extended: */ + /* 0 == not installed, ok to install */ + /* 1 == not installed, not ok to install */ + /* -1 == installed */ + return cNlsRet; +} + +BOOL +GetGlblCodePage(UWORD FAR * ActvCodePage, UWORD FAR * SysCodePage) +{ + *ActvCodePage = nlsInfo.nlsExtCtryInfo.codePage; + *SysCodePage = nlsInfo.nlsExtCtryInfo.sysCodePage; + return TRUE; +} + +BOOL +SetGlblCodePage(UWORD FAR * ActvCodePage, UWORD FAR * SysCodePage) +{ + nlsInfo.nlsExtCtryInfo.codePage = *ActvCodePage; + nlsInfo.nlsExtCtryInfo.sysCodePage = *SysCodePage; + return TRUE; +} + +UWORD SetCtryInfo(UBYTE FAR * lpShrtCode, UWORD FAR * lpLongCode, + BYTE FAR * lpTable, UBYTE * nRetCode) +{ + UWORD CntryCode; + UBYTE nNlsEntry; + UWORD uSegTable, + uOffTable; + UBYTE nLclRet; + + /* Get the Country Code according to the DOS silly rules. */ + if (0xff != *lpShrtCode) + CntryCode = *lpShrtCode; + else + CntryCode = *lpLongCode; + + /* If it's the same country code as what's installed, just */ + /* return because there's nothing to do. */ + if (CntryCode == nlsInfo.nlsExtCtryInfo.countryCode) + { + *nRetCode = 0; + return CntryCode; + } + + /* Check if nlsfunc is installed */ + if (NlsFuncInst() >= 0) + { + *nRetCode = 0xff; + return 0xffff; + } + + /* Get the country information from nlsfunc */ + uSegTable = FP_SEG(lpTable); + uOffTable = FP_OFF(lpTable); + +#ifndef __TURBOC__ + asm + { + push ds + mov bx, + CntryCode + mov ax, + uSegTable + mov dx, + uOffTable + mov ds, + ax + mov ax, + 0x1404 + int 0x2F + pop ds + mov CntryCode, + bx + mov nLclRet, + al + } +#else + /* XXX: this is ugly... but needed on `tcc' 2.01 without `tasm'. -- ror4 */ + __emit__(0x1e); /* push ds */ + _BX = CntryCode; + _AX = uSegTable; + _DX = uOffTable; + _DS = _AX; + _AX = 0x1404; + __int__(0x2f); + __emit__(0x1f); /* pop ds */ + CntryCode = _BX; + nLclRet = _AL; +#endif + *nRetCode = nLclRet; + return CntryCode; +} + +UWORD GetCtryInfo(UBYTE FAR * lpShrtCode, UWORD FAR * lpLongCode, + BYTE FAR * lpTable) +{ + fbcopy((BYTE FAR *) & nlsInfo.nlsExtCtryInfo.nlsCtryInfo, + lpTable, sizeof(struct ctryInfo)); + return nlsInfo.nlsExtCtryInfo.countryCode; +} + +BOOL ExtCtryInfo(UBYTE nOpCode, UWORD CodePageID, UWORD InfoSize, VOID FAR * Information) +{ + VOID FAR *lpSource; + COUNT nIdx; + + if (0xffff != CodePageID) + { + UBYTE nNlsEntry; + + if (NlsFuncInst() >= 0) + return FALSE; + +#ifndef __TURBOC__ + asm + { + mov bp, + word ptr nOpCode + mov bx, + CodePageID + mov si, + word ptr Information + 2 + mov ds, + si + mov si, + word ptr Information + mov ax, + 0x1402 + int 0x2F + cmp al, + 0 + mov nNlsEntry, + al + } +#else + /* XXX: again, this is ugly... -- ror4 */ + __emit__(0x1e, 0x55, 0x56); /* push ds; push bp; push si */ + _BX = CodePageID; + _SI = ((WORD *) & Information)[1]; + _DS = _SI; + _SI = *(WORD *) & Information; + _BP = *(WORD *) & nOpCode; + _BP &= 0x00ff; + _AX = 0x1402; + __int__(0x2f); + nNlsEntry = _AL; + __emit__(0x5e, 0x5d, 0x1f); /* pop si; pop bp; pop ds */ +#endif + + if (0 != nNlsEntry) + return FALSE; + + return TRUE; + } + + CodePageID = nlsInfo.nlsExtCtryInfo.codePage; + + for (nIdx = 0; nIdx < nlsInfo.nlsExtCtryInfo.nFnEntries; nIdx++) + { + if (nlsInfo.nlsExtCtryInfo.VectorTable[nIdx].FnCode == nOpCode) + { + BYTE FAR *bp = Information; + lpSource = nlsInfo.nlsExtCtryInfo.VectorTable[nIdx].Table; + + if (nOpCode == 1) + { + bp++; /* first byte unused */ + + *bp = (BYTE) (sizeof(struct ctryInfo) + 4); + bp += 2; + + fbcopy(lpSource, bp, InfoSize > 3 ? InfoSize - 3 : 0); + } + else + { + *bp++ = nOpCode; + *((VOID FAR **) bp) = lpSource; + } + return TRUE; + } + } + + return FALSE; +} + +UWORD internalUpcase(UWORD c) +{ + if (!(c & 0x80)) + return c; + + return (c & 0xff00) | (nlsInfo.upNormCh[c & 0x7f] & 0xff); +} + +char upMChar(UPMAP map, char ch) +/* upcase character ch according to the map */ +{ + return (ch >= 'a' && ch <= 'z') ? ch + 'A' - 'a' : + ((unsigned)ch > 0x7f ? map[ch & 0x7f] : ch); +} + +VOID upMMem(UPMAP map, char FAR * str, unsigned len) +{ + REG unsigned c; + + if (len) + do + { + if ((c = *str) >= 'a' && c <= 'z') + *str += 'A' - 'a'; + else if (c > 0x7f) + *str = map[c & 0x7f]; + ++str; + } + while (--len); +} + +BYTE yesNo(char ch) /* returns: 0: ch == "No", 1: ch == "Yes", 2: ch crap */ +{ + ch = upMChar(normalCh, ch); + if (ch == noChar) + return 0; + if (ch == yesChar) + return 1; + return 2; +} + +char upChar(char ch) /* upcase a single character */ +{ + return upMChar(normalCh, ch); +} + +VOID upString(char FAR * str) /* upcase a string */ +{ + upMMem(normalCh, str, fstrlen(str)); +} + +VOID upMem(char FAR * str, unsigned len) /* upcase a memory area */ +{ + upMMem(normalCh, str, len); +} + +char upFChar(char ch) /* upcase a single character for file names */ +{ + return upMChar(fileCh, ch); +} + +VOID upFString(char FAR * str) /* upcase a string for file names */ +{ + upMMem(fileCh, str, fstrlen(str)); +} + +VOID upFMem(char FAR * str, unsigned len) /* upcase a memory area for file names */ +{ + upMMem(fileCh, str, len); +} + +/* ReadCountryTable(): + + * Loads a country information table. + */ + +static BOOL ReadCountryTable(COUNT file, WORD id, ULONG offset) +{ + VOID *buf; /* where to load the information */ + UWORD maxSize; /* max number of bytes to read */ + UWORD length; /* length of table in file */ + BOOL rc = TRUE; + + switch (id) + { + case 1: /* extended country information */ + buf = &nlsInfo.nlsExtCtryInfo.countryCode; + maxSize = sizeof(struct ctryInfo) + sizeof(WORD) * 2; + break; + + case 2: /* uppercase table */ + buf = &normalCh[0]; + maxSize = sizeof normalCh; + break; + + case 4: /* filename uppercase table */ + buf = &fileCh[0]; + maxSize = sizeof fileCh; + break; + + case 5: /* filename terminator table */ + buf = &nlsInfo.nlsFn.dummy1; + maxSize = sizeof(struct chFileNames) - sizeof(WORD); + break; + + case 6: /* collating sequence table */ + buf = &nlsInfo.collSeq[0]; + maxSize = sizeof nlsInfo.collSeq; + break; + + default: /* unknown or unsupported table - ignore */ + buf = 0; + break; + } + + if (buf) + { + dos_lseek(file, offset, 0); + dos_read(file, &length, sizeof(length)); + + if (length > maxSize) + length = maxSize; + + if (dos_read(file, buf, length) != length) + rc = FALSE; + + if (id == 1) + nlsInfo.nlsExtCtryInfo.nlsCtryInfo.upCaseFct = CharMapSrvc; + } + + return rc; +} + +/* LoadCountryInfo(): + + * Searches a file in the COUNTRY.SYS format for an entry + * matching the specified code page and country code, and loads + * the corresponding information into memory. If code page is 0, + * the default code page for the country will be used. + * + * Returns TRUE if successful, FALSE if not. + */ + +/* XXX: This function should be placed in `INIT_TEXT'. -- ror4 */ +BOOL FAR LoadCountryInfo(char FAR * filename, WORD ctryCode, WORD codePage) +{ + struct CpiHeader hdr; + struct CountryRecord ctry; + struct CountryTableDescr ct; + COUNT i, + nCountries, + nSubEntries; + ULONG currpos; + int rc = FALSE; + COUNT file; + + if ((file = dos_open(filename, 0)) < 0) + return rc; + + if (dos_read(file, &hdr, sizeof(hdr)) == sizeof(hdr)) + { + /* check signature */ + if (!fstrncmp(hdr.name, "\377COUNTRY", 8)) + { + dos_lseek(file, hdr.pointer[0].offset, 0); + dos_read(file, &nCountries, sizeof(nCountries)); + + /* search for matching country record */ + for (i = 0; i < nCountries; i++) + { + if (dos_read(file, &ctry, sizeof(ctry)) != sizeof(ctry)) + break; + + if (ctry.country == ctryCode && (!codePage || ctry.codePage == codePage)) + { + /* found country - now load the tables */ + dos_lseek(file, ctry.subCountryOffset, 0); + dos_read(file, &nSubEntries, sizeof(nSubEntries)); + currpos = ctry.subCountryOffset + sizeof(nSubEntries); + + for (i = 0; i < nSubEntries; i++) + { + dos_lseek(file, currpos, 0); + if (dos_read(file, &ct, sizeof(ct)) != sizeof(ct)) + break; + + currpos += ct.length + sizeof(ct.length); + ReadCountryTable(file, ct.id, ct.offset + 8); + } + + if (i == nSubEntries) + rc = TRUE; + + break; + } + } + } + } + dos_close(file); + return rc; +} diff --git a/kernel/nlssupt.asm b/kernel/nlssupt.asm new file mode 100644 index 0000000..1de71fa --- /dev/null +++ b/kernel/nlssupt.asm @@ -0,0 +1,103 @@ +; File: +; nls.asm +; Description: +; Assembly support routines for nls functions. +; +; Copyright (c) 1995, 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/dos-c/src/kernel/nlssupt.asv $ +; +; $Id$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:35:29 jhall1 +; Initial revision +; +; Revision 1.2 1999/08/10 17:57:13 jprice +; ror4 2011-02 patch +; +; Revision 1.1.1.1 1999/03/29 15:41:25 jprice +; New version without IPL.SYS +; +; Revision 1.4 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; Revision 1.3 1999/02/01 01:48:41 jprice +; Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) +; +; Revision 1.2 1999/01/22 04:13:26 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:01 jprice +; Imported sources +; +; Rev 1.3 06 Dec 1998 8:46:56 patv +; Bug fixes. +; +; Rev 1.2 16 Jan 1997 12:46:44 patv +; pre-Release 0.92 feature additions +; +; Rev 1.1 29 May 1996 21:03:38 patv +; bug fixes for v0.91a +; +; Rev 1.0 19 Feb 1996 3:24:04 patv +; Added NLS, int2f and config.sys processing +; $EndLog$ +; + + + %include "segs.inc" + +segment _TEXT + global _CharMapSrvc + extern _internalUpcase:wrt TGROUP +; +; CharMapSrvc: +; User callable character mapping service. +; Part of Function 38h +; +_CharMapSrvc: + push ds + push es + push bp + push si + push di + push dx + push cx + push bx + + mov dx, DGROUP + mov ds, dx + + push ax + call _internalUpcase + add sp, byte 2 + + pop bx + pop cx + pop dx + pop di + pop si + pop bp + pop es + pop ds + retf ; Return far diff --git a/kernel/prf.c b/kernel/prf.c new file mode 100644 index 0000000..c0eff70 --- /dev/null +++ b/kernel/prf.c @@ -0,0 +1,410 @@ +/****************************************************************/ +/* */ +/* prf.c */ +/* */ +/* Abbreviated printf Function */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" + +#ifdef VERSION_STRINGS +static BYTE *prfRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:29 jhall1 + * Initial revision + * + * Revision 1.3 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.2 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:42:20 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:43:28 jprice + * Fixed findfirst function to find volume label with Windows long filenames + * + * Revision 1.2 1999/01/22 04:15:28 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * + * Rev 1.4 04 Jan 1998 23:14:38 patv + * Changed Log for strip utility + * + * Rev 1.3 29 May 1996 21:15:10 patv + * bug fixes for v0.91a + * + * Rev 1.2 01 Sep 1995 17:48:42 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:50:26 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:05:10 patv + * Initial revision. + */ + +static BYTE *charp; + +#ifdef PROTO +VOID handle_char(COUNT); +VOID put_console(COUNT); +BYTE *ltob(LONG, BYTE *, COUNT); +static BYTE *itob(COUNT, BYTE *, COUNT); +COUNT do_printf(CONST BYTE *, REG BYTE **); +#else +VOID handle_char(); +VOID put_console(); +BYTE *ltob(); +static BYTE *itob(); +COUNT do_printf(); +#endif + +/* The following is user supplied and must match the following prototype */ +#ifdef PROTO +VOID cso(COUNT); +#else +VOID cso(); +#endif + +/* special console output routine */ +VOID +put_console(COUNT c) +{ + if (c == '\n') + cso('\r'); + cso(c); +} + +/* special handler to switch between sprintf and printf */ +static VOID + handle_char(COUNT c) +{ + if (charp == 0) + put_console(c); + else + *charp++ = c; +} + +/* ltob -- convert an long integer to a string in any base (2-16) */ +static BYTE * + ltob(LONG n, BYTE * s, COUNT base) +{ + ULONG u; + REG BYTE *p, + *q; + REG negative, + c; + + if (n < 0 && base == -10) + { + negative = 1; + u = -n; + } + else + { + negative = 0; + u = n; + } + if (base == -10) /* signals signed conversion */ + base = 10; + p = q = s; + do + { /* generate digits in reverse order */ + *p++ = "0123456789abcdef"[u % base]; + } + while ((u /= base) > 0); + if (negative) + *p++ = '-'; + *p = '\0'; /* terminate the string */ + while (q < --p) + { /* reverse the digits */ + c = *q; + *q++ = *p; + *p = c; + } + return s; +} + +/* itob -- convert an long integer to a string in any base (2-16) */ +static BYTE * + itob(COUNT n, BYTE * s, COUNT base) +{ + UWORD u; + REG BYTE *p, + *q; + REG negative, + c; + + if (n < 0 && base == -10) + { + negative = 1; + u = -n; + } + else + { + negative = 0; + u = n; + } + if (base == -10) /* signals signed conversion */ + base = 10; + p = q = s; + do + { /* generate digits in reverse order */ + *p++ = "0123456789abcdef"[u % base]; + } + while ((u /= base) > 0); + if (negative) + *p++ = '-'; + *p = '\0'; /* terminate the string */ + while (q < --p) + { /* reverse the digits */ + c = *q; + *q++ = *p; + *p = c; + } + return s; +} + +#define NONE 0 +#define LEFT 1 +#define RIGHT 2 + +/* printf -- short version of printf to conserve space */ +WORD FAR + init_call_printf(CONST BYTE * fmt, BYTE * args) +{ + charp = 0; + return do_printf(fmt, &args); +} + +WORD +sprintf(BYTE * buff, CONST BYTE * fmt, BYTE * args) +{ + WORD ret; + + charp = buff; + ret = do_printf(fmt, &args); + handle_char(NULL); + return ret; +} + +static COUNT + do_printf(CONST BYTE * fmt, REG BYTE ** arg) +{ + REG base; + BYTE s[11], + *p, + *ltob(); + BYTE c, + slen, + flag, + size, + fill; + + flag = NONE; + size = 0; + while ((c = *fmt++) != '\0') + { + if (size == 0 && flag == NONE && c != '%') + { + handle_char(c); + continue; + } + if (flag == NONE && *fmt == '0') + { + flag = RIGHT; + fill = '0'; + } + switch (*fmt) + { + case '-': + flag = RIGHT; + fill = *(fmt + 1) == '0' ? '0' : ' '; + continue; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (flag == NONE) + flag = LEFT; + size = *fmt++ - '0'; + while ((c = *fmt++) != '\0') + { + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + size = size * 10 + (c - '0'); + continue; + + default: + --fmt; + break; + } + break; + } + break; + } + switch (c = *fmt++) + { + case 'c': + handle_char(*(COUNT *) arg++); + continue; + + case 'd': + base = -10; + goto prt; + + case 'o': + base = 8; + goto prt; + + case 'u': + base = 10; + goto prt; + + case 'x': + base = 16; + + prt: + itob(*((COUNT *) arg)++, s, base); + if (flag == RIGHT || flag == LEFT) + { + for (slen = 0, p = s; *p != '\0'; p++) + ++slen; + } + if (flag == RIGHT && slen < size) + { + WORD i; + + for (i = size - slen; i > 0; i--) + handle_char(fill); + } + for (p = s; *p != '\0'; p++) + handle_char(*p); + if (flag == LEFT) + { + WORD i; + BYTE sp = ' '; + + for (i = size - slen; i > 0; i--) + handle_char(sp); + } + size = 0; + flag = NONE; + continue; + + case 'l': + switch (c = *fmt++) + { + case 'd': + base = -10; + goto lprt; + + case 'o': + base = 8; + goto lprt; + + case 'u': + base = 10; + goto lprt; + + case 'x': + base = 16; + + lprt: + ltob(*((LONG *) arg)++, s, base); + if (flag == RIGHT || flag == LEFT) + { + for (slen = 0, p = s; *p != '\0'; p++) + ++slen; + } + if (flag == RIGHT && slen < size) + { + WORD i; + + for (i = size - slen; i > 0; i--) + handle_char(fill); + } + for (p = s; *p != '\0'; p++) + handle_char(*p); + if (flag == LEFT) + { + WORD i; + BYTE sp = ' '; + + for (i = size - slen; i > 0; i--) + handle_char(sp); + } + size = 0; + flag = NONE; + continue; + + default: + handle_char(c); + } + + case 's': + for (p = *arg; *p != '\0'; p++) + { + --size; + handle_char(*p); + } + for (; size > 0; size--) + handle_char(' '); + ++arg; + size = 0; + flag = NONE; + continue; + + default: + handle_char(c); + continue; + } + } + return 0; +} diff --git a/kernel/printer.asm b/kernel/printer.asm new file mode 100644 index 0000000..d9834f6 --- /dev/null +++ b/kernel/printer.asm @@ -0,0 +1,201 @@ +; +; File: +; printer.asm +; Description: +; Printer device driver +; +; Copyright (c) 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Header$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:35:30 jhall1 +; Initial revision +; +; Revision 1.2 1999/08/10 17:57:13 jprice +; ror4 2011-02 patch +; +; Revision 1.1.1.1 1999/03/29 15:41:26 jprice +; New version without IPL.SYS +; +; Revision 1.1 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; $EndLog$ +; + + %include "io.inc" + +segment _IO_FIXED_DATA + + global LptTable +LptTable db 18h + dw _IOExit + dw _IOExit + dw _IOExit + dw _IOCommandError + dw _IOSuccess + dw _IODone + dw _IOExit + dw _IOExit + dw PrtWrite + dw PrtWrite + dw PrtOutStat + dw _IOExit + dw _IOExit + dw _IOExit + dw _IOExit + dw _IOExit + dw PrtOutBsy + dw _IOExit + dw _IOExit + dw PrtGenIoctl + dw _IOExit + dw _IOExit + dw _IOExit + dw _IOCommandError + dw _IOCommandError + + +segment _IO_TEXT + global uPrtNo +uPrtNo db 0 +uPrtQuantum dw 50h + dw 50h, 50h + db 50h, 00h + +PrtWrite: + jcxz PrtWr3 ; Exit if nothing to write +PrtWr1: + mov bx,2 +PrtWr2: + mov al,[es:di] + inc di + xor ah,ah ; Zero register + call PrtIOCall ; (0800) + jnz PrtWr4 ; Exit if done + loop PrtWr1 ; otherwise loop +PrtWr3: + jmp _IOExit +PrtWr4: + dec di + dec bx + jnz PrtWr2 +PrtWr5: + jmp _IOErrCnt + + + +PrtOutStat: + call GetPrtStat + jnz PrtWr5 + mov al,9 + test ah,20h + jnz PrtWr5 + test ah,80h + jnz PrtWr3 + jmp _IODone + + + +GetPrtStat: + mov ah,2 + +PrtIOCall: + call GetUnitNum + int 17h ; print char al, get status ah + test ah,8 + jz PrtIOCal2 + mov al,9 + test ah,20h + jnz PrtIOCal1 + inc al +PrtIOCal1: + retn +PrtIOCal2: + mov al,2 + test ah,1 + retn + + + +PrtOutBsy: + push ds + push es + pop ds + mov si,di +PrtOtBsy1: + push cx + push bx + xor bx,bx + mov bl,[cs:uPrtNo] + shl bx,1 + mov cx,[cs:uPrtQuantum+bx] + pop bx +PrtOtBsy2: + call GetPrtStat + jnz PrtOtBsy3 + test ah,80h + loopz PrtOtBsy2 + pop cx + jz PrtOtBsy4 + lodsb + xor ah,ah + call PrtIOCall + jnz PrtOtBsy4 + loop PrtOtBsy1 + pop ds + lds bx,[cs:_ReqPktPtr] + sub [bx+12h],cx + jmp _IOExit +PrtOtBsy3: + pop cx +PrtOtBsy4: + pop ds + lds bx,[cs:_ReqPktPtr] + sub [bx+12h],cx + jmp _IOErrorExit + + + +PrtGenIoctl: + les di,[cs:_ReqPktPtr] + cmp byte [es:di+0Dh],5 + je PrtGnIoctl2 +PrtGnIoctl1: + jmp _IOCommandError +PrtGnIoctl2: + mov al,[es:di+0Eh] + les di,[es:di+13h] + xor bx,bx + mov bl,[cs:uPrtNo] + shl bx,1 + mov cx,[cs:uPrtQuantum+bx] + cmp al,65h + je PrtGnIoctl3 + cmp al,45h + jne PrtGnIoctl1 + mov cx,[es:di] +PrtGnIoctl3: + mov [cs:uPrtQuantum+bx],cx + mov [es:di],cx + jmp _IOExit diff --git a/kernel/procsupt.asm b/kernel/procsupt.asm new file mode 100644 index 0000000..b1a9cbb --- /dev/null +++ b/kernel/procsupt.asm @@ -0,0 +1,312 @@ +; +; File: +; procsupt.asm +; Description: +; Assembly support routines for process handling, etc. +; +; Copyright (c) 1995,1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/usr/patv/dos-c/src/kernel/procsupt.asv $ +; +; $Id$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:35:30 jhall1 +; Initial revision +; +; Revision 1.4 1999/08/10 17:57:13 jprice +; ror4 2011-02 patch +; +; Revision 1.3 1999/04/23 22:38:36 jprice +; Fixed got_cbreak function. +; +; Revision 1.2 1999/04/16 12:21:22 jprice +; Steffen c-break handler changes +; +; Revision 1.1.1.1 1999/03/29 15:41:27 jprice +; New version without IPL.SYS +; +; Revision 1.4 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; Revision 1.3 1999/02/01 01:48:41 jprice +; Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) +; +; Revision 1.2 1999/01/22 04:13:27 jprice +; Formating +; +; Revision 1.1.1.1 1999/01/20 05:51:01 jprice +; Imported sources +; +; Rev 1.4 06 Dec 1998 8:46:44 patv +;Bug fixes. +; +; Rev 1.3 07 Feb 1998 20:42:08 patv +;Modified stack fram to match DOS standard +; +; Rev 1.2 29 May 1996 21:03:36 patv +;bug fixes for v0.91a +; +; Rev 1.1 01 Sep 1995 17:54:24 patv +;First GPL release. +; +; Rev 1.0 02 Jul 1995 9:05:58 patv +;Initial revision. +; $EndLog$ +; + + + %include "segs.inc" + + extern _api_sp:wrt DGROUP ; api stacks - for context + extern _api_ss:wrt DGROUP ; switching + extern _usr_sp:wrt DGROUP ; user stacks + extern _usr_ss:wrt DGROUP + + extern _kstackp:wrt TGROUP ; kernel stack + extern _ustackp:wrt TGROUP ; new task stack + + extern _break_flg:wrt DGROUP ; break detected flag + extern _int21_handler:wrt TGROUP ; far call system services + + %include "stacks.inc" + +segment _TEXT + +; +; Special call for switching processes +; +; void interrupt far exec_user(irp) +; iregs far *irp; +; + global _exec_user +_exec_user: + + PUSH$ALL + mov ax,DGROUP + mov ds,ax + mov bp,sp + cld + cli +; +; +; + mov ax,word [bp+irp_low] ; irp (user ss:sp) + mov dx,word [bp+irp_hi] + mov sp,ax ; set-up user stack + mov ss,dx + sti +; + POP$ALL + iret + + + + +;; Called whenever the BIOS detects a ^Break state + global _got_cbreak +_got_cbreak: + push ds + push ax + mov ax, 40h + mov ds, ax + or byte [71h], 80h ;; set the ^Break flag + pop ax + pop ds + iret + + +; +; Special call for switching processes during break handling +; +; void interrupt far spawn_int23() +; +; +; +---------------+ +; | flags | 22 +; +---------------+ +; | cs | 20 +; +---------------+ +; | ip | 18 +; +---------------+ +; | es | 16 +; +---------------+ +; | ds | 14 +; +---------------+ +; | bp | 12 +; +---------------+ +; | di | 10 +; +---------------+ +; | si | 8 +; +---------------+ +; | dx | 6 +; +---------------+ +; | cx | 4 +; +---------------+ +; | bx | 2 +; +---------------+ +; | ax | 0 <--- bp & sp after mov bp,sp +; +---------------+ +; + global _spawn_int23 +_spawn_int23: + +;; 1999/03/27 ska - comments: see cmt1.txt + mov ax, DGROUP ;; Make sure DS is OK + mov ds, ax + + ; restore to user stack + cli ;; Pre-8086 don't disable INT autom. + mov ss,[_usr_ss] + mov sp,[_usr_sp] + sti + + ; get all the user registers back + POP$ALL + + ;; Construct the piece of code into the stack + + ;; stack frame: during generation of code piece + ;; + ;; BP | SP | Meaning + ;; 7 | 11 | offset CALL FAR will push onto stack + ;; 5 | 9 | CALL FAR segment + ;; 3 | 7 | CALL FAR offset + ;; 2 | 6 | CALL FAR ??regain_control_int23 | instruction byte + ;; 0 | 4 | INT 23 <> + ;; -2 | 2 | segment of address of INT-23 \ To jump to INT 23 + ;; -4 | 0 | offset of address of INT-23 / via RETF + ;; Upon return from INT-23 the CALL FAR pushes the address of + ;; the byte immediately following the CALL FAR onto the stack. + ;; This value POPed and decremented by 7 is the value SP must + ;; contain, if the INT-23 was returned with RETF2/IRET. + + sub sp, byte 8 ;; code piece needs 7 bytes --> 4 words + push ss ;; prepare jump to INT-23 via RETF + push bp ;; will be offset / temp: saved BP + mov bp, sp + add bp, byte 4 ;; position BP onto INT-23 + mov word [bp], 23cdh ;; INT 23h + mov byte [bp+2], 9ah ;; CALL FAR immediate + mov word [bp+3], ??regain_control_int23 + mov word [bp+5], cs + + ;; complete the jump to INT-23 via RETF and restore BP + xchg word [bp-4], bp + + stc ;; set default action --> terminate + ; invoke the int 23 handler its address has been constructed + ;; on the stack + retf + +??regain_control_int23: + + ;; stack frame: constructed on entry to INT-23 + ;; + ; BP | SP | Meaning + ;; 7 | 11 | offset CALL FAR will push onto stack + ;; 5 | 9 | CALL FAR segment + ;; 3 | 7 | CALL FAR offset + ;; 2 | 6 | CALL FAR ??regain_control_int23 | instruction byte + ;; 0 | 4 | INT 23 <> + ;; -2 | 2 | segment of address of INT-23 \ To jump to INT 23 + ;; -4 | 0 | offset of address of INT-23 / via RETF + ;; Upon return from INT-23 the CALL FAR pushes the address of + ;; the byte immediately following the CALL FAR onto the stack. + ;; This value POPed and decremented by 7 is the value SP must + ;; contain, if the INT-23 was returned with RETF2/IRET. + + ;; stack frame: used during recovering from INT-23 + ;; + ;; BP | Meaning + ;; 1 | <> + ;; 0 | <> + ;; -1 | saved BP + ;; -3 | saved AX + ;; -7 | INT 23 <> + + ;; Somewhere on stack: + ;; SP | Meaning + ;; 4 | segment of return address of CALL FAR + ;; 2 | offset of return address of CALL FAR + ;; 0 | saved BP + + push bp + mov bp, sp + mov bp, [bp+2] ;; get should-be address + 7 + mov word [bp-3], ax ;; save AX + pop ax ;; old BP + mov word [bp-1], ax ;; preserve saved BP + mov ax, bp + dec ax ;; last used word of stack + dec ax ;; Don't use SUB to keep Carry flag + dec ax + xchg ax, sp ;; AX := current stack; SP corrected + ;; Currently: BP - 7 == address of INT-23 + ;; should be AX + 4 --> IRET or RETF 2 + ;; ==> Test if BP - 7 == AX + 4 + ;; ==> Test if AX + 4 - BP + 7 == 0 + pushf ;; preserve Carry flag + add ax, byte 4 + 7 + sub ax, bp ;; AX := SP + 4 + pop ax ;; saved Carry flag + jz ??int23_ign_carry ;; equal -> IRET --> ignore Carry + ;; Carry is already cleared + push ax + popf ;; restore Carry flag + +??int23_ign_carry: + pop ax ;; Restore the original register + jnc ??int23_respawn + ;; The user returned via RETF 0, Carry is set + ;; --> terminate program + ;; This is done by set the _break_flg and modify the + ;; AH value, which is passed to the _respawn_ call + ;; into 0, which is "Terminate program". + push ds ;; we need DGROUP + mov bp, DGROUP + mov ds, bp + inc byte [_break_flg] + pop ds + + xor ah, ah ;; clear ah --> perform DOS-00 --> terminate + +??int23_respawn: + pop bp ;; Restore the original register + jmp _int21_handler + + +; +; interrupt enable and disable routines +; +; public _enable +;_enable proc near +; sti +; ret +;_enable endp +; +; public _disable +;_disable proc near +; cli +; ret +;_disable endp + diff --git a/kernel/proto.h b/kernel/proto.h new file mode 100644 index 0000000..b60c5b7 --- /dev/null +++ b/kernel/proto.h @@ -0,0 +1,452 @@ +/****************************************************************/ +/* */ +/* proto.h */ +/* */ +/* Global Function Prototypes */ +/* */ +/* Copyright (c) 1995, 1996 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#ifdef MAIN +#ifdef VERSION_STRINGS +static BYTE *Proto_hRcsId = "$Id$"; +#endif +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:32 jhall1 + * Initial revision + * + * Revision 1.15 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.14 1999/09/23 04:40:48 jprice + * *** empty log message *** + * + * Revision 1.10 1999/08/25 03:18:09 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.9 1999/05/03 06:25:45 jprice + * Patches from ror4 and many changed of signed to unsigned variables. + * + * Revision 1.8 1999/04/23 04:24:39 jprice + * Memory manager changes made by ska + * + * Revision 1.7 1999/04/16 21:43:40 jprice + * ror4 multi-sector IO + * + * Revision 1.6 1999/04/16 12:21:22 jprice + * Steffen c-break handler changes + * + * Revision 1.5 1999/04/12 03:21:17 jprice + * more ror4 patches. Changes for multi-block IO + * + * Revision 1.4 1999/04/11 04:33:39 jprice + * ror4 patches + * + * Revision 1.2 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:41:30 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/08 05:55:57 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.3 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.2 1999/01/22 04:13:27 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.11 06 Dec 1998 8:47:18 patv + *Expanded due to new I/O subsystem. + * + * Rev 1.10 07 Feb 1998 20:38:00 patv + *Modified stack fram to match DOS standard + * + * Rev 1.9 22 Jan 1998 4:09:26 patv + *Fixed pointer problems affecting SDA + * + * Rev 1.8 11 Jan 1998 2:06:22 patv + *Added functionality to ioctl. + * + * Rev 1.7 04 Jan 1998 23:16:22 patv + *Changed Log for strip utility + * + * Rev 1.6 03 Jan 1998 8:36:48 patv + *Converted data area to SDA format + * + * Rev 1.5 16 Jan 1997 12:46:44 patv + *pre-Release 0.92 feature additions + * + * Rev 1.4 29 May 1996 21:03:40 patv + *bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:23:06 patv + *Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:54:26 patv + *First GPL release. + * + * Rev 1.1 30 Jul 1995 20:51:58 patv + *Eliminated version strings in ipl + * + * Rev 1.0 05 Jul 1995 11:32:16 patv + *Initial revision. + */ + +#define INIT + +#ifdef IN_INIT_MOD +#define __FAR_WRAPPER(ret, name, proto) \ + ret FAR name proto; /* will be expanded to `init_call_' */ +#else +#define __FAR_WRAPPER(ret, name, proto) \ + ret name proto; \ + ret FAR init_call_##name proto; +#endif + +/* blockio.c */ +VOID FAR init_buffers(void); +ULONG getblkno(struct buffer FAR *); +VOID setblkno(struct buffer FAR *, ULONG); +struct buffer FAR *getblock(ULONG blkno, COUNT dsk); +BOOL getbuf(struct buffer FAR ** pbp, ULONG blkno, COUNT dsk); +VOID setinvld(REG COUNT dsk); +BOOL flush_buffers(REG COUNT dsk); +BOOL flush1(struct buffer FAR * bp); +BOOL flush(void); +BOOL fill(REG struct buffer FAR * bp, ULONG blkno, COUNT dsk); +BOOL dskxfer(COUNT dsk, ULONG blkno, VOID FAR * buf, UWORD numblocks, COUNT mode); + +/* chario.c */ +VOID cso(COUNT c); +VOID sto(COUNT c); +VOID mod_sto(REG UCOUNT c); +VOID destr_bs(void); +UCOUNT _sti(void); +VOID con_hold(void); +BOOL con_break(void); +BOOL StdinBusy(void); +VOID KbdFlush(void); +VOID Do_DosIdle_loop(void); +__FAR_WRAPPER(VOID, sti, (keyboard FAR * kp)) + +sft FAR *get_sft(COUNT); + +/* config.c */ +INIT VOID PreConfig(VOID); +INIT VOID DoConfig(VOID); +INIT VOID PostConfig(VOID); +INIT BYTE *skipwh(BYTE * s); +INIT BYTE *scan(BYTE * s, BYTE * d); +INIT BOOL isnum(BYTE * pszString); +INIT BYTE *GetNumber(REG BYTE * pszString, REG COUNT * pnNum); +INIT COUNT tolower(COUNT c); +INIT COUNT toupper(COUNT c); +INIT VOID mcb_init(mcb FAR * mcbp, UWORD size); +INIT VOID strcat(REG BYTE * d, REG BYTE * s); + +/* dosfns.c */ +BOOL check_break(void); +UCOUNT GenericRead(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err, + BOOL force_binary); +UCOUNT DosRead(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err); +UCOUNT DosWrite(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err); +COUNT DosSeek(COUNT hndl, LONG new_pos, COUNT mode, ULONG * set_pos); +COUNT DosCreat(BYTE FAR * fname, COUNT attrib); +COUNT CloneHandle(COUNT hndl); +COUNT DosDup(COUNT Handle); +COUNT DosForceDup(COUNT OldHandle, COUNT NewHandle); +COUNT DosOpen(BYTE FAR * fname, COUNT mode); +COUNT DosClose(COUNT hndl); +VOID DosGetFree(COUNT drive, COUNT FAR * spc, COUNT FAR * navc, COUNT FAR * bps, COUNT FAR * nc); +COUNT DosGetCuDir(COUNT drive, BYTE FAR * s); +COUNT DosChangeDir(BYTE FAR * s); +COUNT DosFindFirst(UCOUNT attr, BYTE FAR * name); +COUNT DosFindNext(void); +COUNT DosGetFtime(COUNT hndl, date FAR * dp, time FAR * tp); +COUNT DosSetFtime(COUNT hndl, date FAR * dp, time FAR * tp); +COUNT DosGetFattr(BYTE FAR * name, UWORD FAR * attrp); +COUNT DosSetFattr(BYTE FAR * name, UWORD FAR * attrp); +BYTE DosSelectDrv(BYTE drv); + +/*dosidle.asm */ +VOID DosIdle_int(void); + +/* dosnames.c */ +VOID SpacePad(BYTE *, COUNT); +COUNT ParseDosName(BYTE FAR *, COUNT *, BYTE *, BYTE *, BYTE *, BOOL); +COUNT ParseDosPath(BYTE FAR *, COUNT *, BYTE *, BYTE FAR *); +BOOL IsDevice(BYTE * FileName); + +/* dsk.c */ +COUNT blk_driver(rqptr rp); + +/* error.c */ +VOID dump(void); +VOID panic(BYTE * s); +__FAR_WRAPPER(VOID, fatal, (BYTE * err_msg)) +COUNT char_error(request * rq, struct dhdr FAR * lpDevice); +COUNT block_error(request * rq, COUNT nDrive, struct dhdr FAR * lpDevice); + +/* fatdir.c */ +struct f_node FAR *dir_open(BYTE FAR * dirname); +COUNT dir_read(REG struct f_node FAR * fnp); +COUNT dir_write(REG struct f_node FAR * fnp); +VOID dir_close(REG struct f_node FAR * fnp); +COUNT dos_findfirst(UCOUNT attr, BYTE FAR * name); +COUNT dos_findnext(void); + +/* fatfs.c */ +__FAR_WRAPPER(COUNT, dos_open, (BYTE FAR * path, COUNT flag)) +BOOL fcmp(BYTE FAR * s1, BYTE FAR * s2, COUNT n); +BOOL fcmp_wild(BYTE FAR * s1, BYTE FAR * s2, COUNT n); +VOID touc(BYTE FAR * s, COUNT n); +__FAR_WRAPPER(COUNT, dos_close, (COUNT fd)) +COUNT dos_creat(BYTE FAR * path, COUNT attrib); +COUNT dos_delete(BYTE FAR * path); +COUNT dos_rmdir(BYTE FAR * path); +COUNT dos_rename(BYTE FAR * path1, BYTE FAR * path2); +__FAR_WRAPPER(date, dos_getdate, (void)) +__FAR_WRAPPER(time, dos_gettime, (void)) +COUNT dos_getftime(COUNT fd, date FAR * dp, time FAR * tp); +COUNT dos_setftime(COUNT fd, date FAR * dp, time FAR * tp); +LONG dos_getcufsize(COUNT fd); +LONG dos_getfsize(COUNT fd); +BOOL dos_setfsize(COUNT fd, LONG size); +COUNT dos_mkdir(BYTE FAR * dir); +BOOL last_link(struct f_node FAR * fnp); +COUNT map_cluster(REG struct f_node FAR * fnp, COUNT mode); +UCOUNT readblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err); +UCOUNT writeblock(COUNT fd, VOID FAR * buffer, UCOUNT count, COUNT * err); +__FAR_WRAPPER(COUNT, dos_read, (COUNT fd, VOID FAR * buffer, UCOUNT count)) +COUNT dos_write(COUNT fd, VOID FAR * buffer, UCOUNT count); +LONG dos_lseek(COUNT fd, LONG foffset, COUNT origin); +UWORD dos_free(struct dpb *dpbp); + +VOID dos_pwd(struct cds FAR * cdsp, BYTE FAR * s); + +VOID trim_path(BYTE FAR * s); + +COUNT dos_cd(struct cds FAR * cdsp, BYTE FAR * s); + +struct f_node FAR *get_f_node(void); +VOID release_f_node(struct f_node FAR * fnp); +VOID dos_setdta(BYTE FAR * newdta); +COUNT dos_getfattr(BYTE FAR * name, UWORD FAR * attrp); +COUNT dos_setfattr(BYTE FAR * name, UWORD FAR * attrp); +COUNT media_check(REG struct dpb *dpbp); +struct f_node FAR *xlt_fd(COUNT fd); +COUNT xlt_fnp(struct f_node FAR * fnp); +struct dhdr FAR *select_unit(COUNT drive); + +/* fattab.c */ +UCOUNT link_fat(struct dpb *dpbp, UCOUNT Cluster1, REG UCOUNT Cluster2); +UCOUNT link_fat16(struct dpb *dpbp, UCOUNT Cluster1, UCOUNT Cluster2); +UCOUNT link_fat12(struct dpb *dpbp, UCOUNT Cluster1, UCOUNT Cluster2); +UWORD next_cluster(struct dpb *dpbp, REG UCOUNT ClusterNum); +UWORD next_cl16(struct dpb *dpbp, REG UCOUNT ClusterNum); +UWORD next_cl12(struct dpb *dpbp, REG UCOUNT ClusterNum); + +/* fcbfns.c */ +VOID DosOutputString(BYTE FAR * s); +int DosCharInputEcho(VOID); +int DosCharInput(VOID); +VOID DosDirectConsoleIO(iregs FAR * r); +VOID DosCharOutput(COUNT c); +VOID DosDisplayOutput(COUNT c); +VOID FatGetDrvData(COUNT drive, COUNT FAR * spc, COUNT FAR * bps, COUNT FAR * nc, BYTE FAR ** mdp); +WORD FcbParseFname(int wTestMode, BYTE FAR ** lpFileName, fcb FAR * lpFcb); +BYTE FAR *ParseSkipWh(BYTE FAR * lpFileName); +BOOL TestCmnSeps(BYTE FAR * lpFileName); +BOOL TestFieldSeps(BYTE FAR * lpFileName); +BYTE FAR *GetNameField(BYTE FAR * lpFileName, BYTE FAR * lpDestField, COUNT nFieldSize, BOOL * pbWildCard); +BOOL FcbRead(xfcb FAR * lpXfcb, COUNT * nErrorCode); +BOOL FcbWrite(xfcb FAR * lpXfcb, COUNT * nErrorCode); +BOOL FcbGetFileSize(xfcb FAR * lpXfcb); +BOOL FcbSetRandom(xfcb FAR * lpXfcb); +BOOL FcbCalcRec(xfcb FAR * lpXfcb); +BOOL FcbRandomBlockRead(xfcb FAR * lpXfcb, COUNT nRecords, COUNT * nErrorCode); +BOOL FcbRandomBlockWrite(xfcb FAR * lpXfcb, COUNT nRecords, COUNT * nErrorCode); +BOOL FcbRandomRead(xfcb FAR * lpXfcb, COUNT * nErrorCode); +BOOL FcbRandomWrite(xfcb FAR * lpXfcb, COUNT * nErrorCode); +BOOL FcbCreate(xfcb FAR * lpXfcb); +void FcbNameInit(fcb FAR * lpFcb, BYTE * pszBuffer, COUNT * pCurDrive); +BOOL FcbOpen(xfcb FAR * lpXfcb); +BOOL FcbDelete(xfcb FAR * lpXfcb); +BOOL FcbRename(xfcb FAR * lpXfcb); +void MoveDirInfo(dmatch FAR * lpDmatch, struct dirent FAR * lpDir); +BOOL FcbClose(xfcb FAR * lpXfcb); +BOOL FcbFindFirst(xfcb FAR * lpXfcb); +BOOL FcbFindNext(xfcb FAR * lpXfcb); + +/* initoem.c */ +UWORD init_oem(void); + +/* inthndlr.c */ +VOID INRPT far got_cbreak(void); /* procsupt.asm */ +VOID INRPT far int20_handler(iregs UserRegs); +VOID INRPT far int21_handler(iregs UserRegs); +VOID far int21_entry(iregs UserRegs); +VOID int21_service(iregs far * r); +VOID INRPT FAR int22_handler(void); +VOID INRPT FAR int23_handler(int es, int ds, int di, int si, int bp, int sp, int bx, int dx, int cx, int ax, int ip, int cs, int flags); +VOID INRPT FAR int24_handler(void); +VOID INRPT FAR low_int25_handler(void); +VOID INRPT FAR low_int26_handler(void); +VOID int25_handler(); +VOID int26_handler(); +VOID INRPT FAR int27_handler(int es, int ds, int di, int si, int bp, int sp, int bx, int dx, int cx, int ax, int ip, int cs, int flags); +VOID INRPT FAR int28_handler(void); +VOID INRPT FAR int2a_handler(void); +VOID INRPT FAR int2f_handler(void); +VOID INRPT FAR empty_handler(void); + +/* ioctl.c */ +COUNT DosDevIOctl(iregs FAR * r, COUNT FAR * err); + +/* main.c */ +INIT VOID main(void); +INIT VOID init_device(struct dhdr FAR * dhp, BYTE FAR * cmdLine); +INIT struct dhdr FAR *link_dhdr(struct dhdr FAR * lp, struct dhdr FAR * dhp, BYTE FAR * cmdLine); + +/* memmgr.c */ +seg far2para(VOID FAR * p); +seg long2para(LONG size); +VOID FAR *add_far(VOID FAR * fp, ULONG off); +VOID FAR *adjust_far(VOID FAR * fp); +__FAR_WRAPPER(COUNT, DosMemAlloc, + (UWORD size, COUNT mode, seg FAR * para, UWORD FAR * asize)) +COUNT DosMemLargest(UWORD FAR * size); +COUNT DosMemFree(UWORD para); +COUNT DosMemChange(UWORD para, UWORD size, UWORD * maxSize); +COUNT DosMemCheck(void); +COUNT FreeProcessMem(UWORD ps); +COUNT DosGetLargestBlock(UWORD FAR * block); +VOID show_chain(void); +VOID mcb_print(mcb FAR * mcbp); +VOID _fmemcpy(BYTE FAR * d, BYTE FAR * s, REG COUNT n); + +/* misc.c */ +__FAR_WRAPPER(VOID, scopy, (REG BYTE * s, REG BYTE * d)) +VOID fscopy(REG BYTE FAR * s, REG BYTE FAR * d); +VOID fsncopy(BYTE FAR * s, BYTE FAR * d, REG COUNT n); +VOID bcopy(REG BYTE * s, REG BYTE * d, REG COUNT n); +__FAR_WRAPPER(VOID, fbcopy, (REG VOID FAR * s, REG VOID FAR * d, REG COUNT n)) + +/* nls.c */ +UWORD GetCtryInfo(UBYTE FAR * lpShrtCode, UWORD FAR * lpLongCode, BYTE FAR * lpTable); +UWORD SetCtryInfo(UBYTE FAR * lpShrtCode, UWORD FAR * lpLongCode, BYTE FAR * lpTable, UBYTE * nRetCode); +UWORD internalUpcase(UWORD c); +BOOL GetGlblCodePage(UWORD FAR * ActvCodePage, UWORD FAR * SysCodePage); +BOOL SetGlblCodePage(UWORD FAR * ActvCodePage, UWORD FAR * SysCodePage); +BOOL ExtCtryInfo(UBYTE nOpCode, UWORD CodePageID, UWORD InfoSize, VOID FAR * Information); +char upMChar(UPMAP map, char ch); +VOID upMMem(UPMAP map, char FAR * str, unsigned len); +BYTE yesNo(char ch); +char upChar(char ch); +VOID upString(char FAR * str); +VOID upMem(char FAR * str, unsigned len); +char upFChar(char ch); +VOID upFString(char FAR * str); +VOID upFMem(char FAR * str, unsigned len); +BOOL FAR LoadCountryInfo(char FAR * filename, WORD ctryCode, WORD codePage); + +/* prf.c */ +VOID put_console(COUNT c); +__FAR_WRAPPER(WORD, printf, (CONST BYTE * fmt,...)) +WORD sprintf(BYTE * buff, CONST BYTE * fmt,...); + +/* strings.c */ +__FAR_WRAPPER(COUNT, strlen, (REG BYTE * s)) +COUNT fstrlen(REG BYTE FAR * s); +VOID _fstrcpy(REG BYTE FAR * d, REG BYTE FAR * s); +VOID strncpy(REG BYTE * d, REG BYTE * s, COUNT l); +__FAR_WRAPPER(COUNT, strcmp, (REG BYTE * d, REG BYTE * s)) +COUNT fstrcmp(REG BYTE FAR * d, REG BYTE FAR * s); +COUNT fstrncmp(REG BYTE FAR * d, REG BYTE FAR * s, COUNT l); +COUNT strncmp(REG BYTE * d, REG BYTE * s, COUNT l); +VOID fstrncpy(REG BYTE FAR * d, REG BYTE FAR * s, COUNT l); +BYTE *strchr(BYTE * s, BYTE c); + +/* sysclk.c */ +WORD clk_driver(rqptr rp); +COUNT BcdToByte(COUNT x); +COUNT BcdToWord(BYTE * x, UWORD * mon, UWORD * day, UWORD * yr); +COUNT ByteToBcd(COUNT x); +LONG WordToBcd(BYTE * x, UWORD * mon, UWORD * day, UWORD * yr); + +/* syscon.c */ +WORD con_driver(rqptr rp); +VOID break_handler(void); +VOID INRPT FAR int29_handler(int es, int ds, int di, int si, int bp, int sp, int bx, int dx, int cx, int ax, int ip, int cs, int flags); + +/* syspack.c */ +VOID getdirent(BYTE FAR * vp, struct dirent FAR * dp); +VOID putdirent(struct dirent FAR * dp, BYTE FAR * vp); + +/* systime.c */ +VOID DosGetTime(BYTE FAR * hp, BYTE FAR * mp, BYTE FAR * sp, BYTE FAR * hdp); +COUNT DosSetTime(BYTE FAR * hp, BYTE FAR * mp, BYTE FAR * sp, BYTE FAR * hdp); +VOID DosGetDate(BYTE FAR * wdp, BYTE FAR * mp, BYTE FAR * mdp, COUNT FAR * yp); +COUNT DosSetDate(BYTE FAR * mp, BYTE FAR * mdp, COUNT FAR * yp); + +/* task.c */ +COUNT ChildEnv(exec_blk FAR * exp, UWORD * pChildEnvSeg, char far * pathname); +VOID new_psp(psp FAR * p, int psize); +VOID return_user(void); +__FAR_WRAPPER(COUNT, DosExec, (COUNT mode, exec_blk FAR * ep, BYTE FAR * lp)) +__FAR_WRAPPER(VOID, InitPSP, (VOID)) + +VOID FAR p_0(void); + +/* irqstack.asm */ +VOID init_stacks(VOID FAR * stack_base, COUNT nStacks, WORD stackSize); + +/* newstuff.c */ +int SetJFTSize(UWORD nHandles); +int DosMkTmp(BYTE FAR * pathname, UWORD attr); +int truename(char FAR * src, char FAR * dest, COUNT t); + +/* network.c */ +COUNT int2f_Remote_call(UWORD func, UWORD b, UCOUNT n, UWORD d, VOID FAR * s, UWORD i, VOID FAR * data); +COUNT QRemote_Fn(char FAR * s, char FAR * d); + +UWORD get_machine_name(BYTE FAR * netname); +VOID set_machine_name(BYTE FAR * netname, UWORD name_num); +UWORD Remote_OCT(UWORD func, BYTE FAR * name, UWORD pw, sft FAR * s); +UCOUNT Remote_RW(UWORD func, UCOUNT n, BYTE FAR * bp, sft FAR * s, COUNT FAR * err); +COUNT Remote_find(UWORD func, UWORD attrib, BYTE FAR * name, REG dmatch FAR * dmp); +COUNT Remote_GSattr(UWORD func, BYTE FAR * name, UWORD FAR * attrp); + +/* procsupt.asm */ +VOID INRPT FAR exec_user(iregs FAR * irp); + +#define strcpy(d, s) scopy(s, d) + diff --git a/kernel/segs.inc b/kernel/segs.inc new file mode 100644 index 0000000..e2e78c5 --- /dev/null +++ b/kernel/segs.inc @@ -0,0 +1,63 @@ +; File: +; segs.inc +; Description: +; Segment definitions for the kernel +; +; Copyright (c) 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/usr/patv/dos-c/src/kernel/segs.inv $ +; +; $Header$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:35:32 jhall1 +; Initial revision +; +; Revision 1.2 1999/08/10 17:57:13 jprice +; ror4 2011-02 patch +; +; Revision 1.1.1.1 1999/03/29 15:41:30 jprice +; New version without IPL.SYS +; +; Revision 1.1 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; +; Rev 1.0 06 Dec 1998 8:12:36 patv +; Initial revision. +; $EndLog +; + +group TGROUP _TEXT _IO_TEXT _IO_FIXED_DATA +group DGROUP _FIXED_DATA _DATA _BSS _BSSEND +group IGROUP INIT_TEXT_START INIT_TEXT INIT_TEXT_END + +segment _TEXT class=CODE +segment _IO_TEXT class=CODE +segment _IO_FIXED_DATA class=CODE align=2 +segment _FIXED_DATA class=DATA align=16 +segment _DATA class=DATA align=2 +segment _BSS class=BSS align=2 +segment _BSSEND class=BSS +segment INIT_TEXT_START class=INIT align=16 +segment INIT_TEXT class=INIT +segment INIT_TEXT_END class=INIT diff --git a/kernel/serial.asm b/kernel/serial.asm new file mode 100644 index 0000000..f769819 --- /dev/null +++ b/kernel/serial.asm @@ -0,0 +1,171 @@ +; +; File: +; serial.asm +; Description: +; Serial device driver +; +; Copyright (c) 1998 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C 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, or (at your option) any later version. +; +; DOS-C 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 DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Header$ +; +; $Log$ +; Revision 1.1 2000/05/06 19:35:33 jhall1 +; Initial revision +; +; Revision 1.2 1999/08/10 17:57:13 jprice +; ror4 2011-02 patch +; +; Revision 1.1.1.1 1999/03/29 15:41:31 jprice +; New version without IPL.SYS +; +; Revision 1.1 1999/02/08 05:55:57 jprice +; Added Pat's 1937 kernel patches +; +; $EndLog$ +; + + %include "io.inc" + +segment _IO_FIXED_DATA + + global ComTable +ComTable db 0Ah + dw _IOExit + dw _IOExit + dw _IOExit + dw _IOCommandError + dw ComRead + dw ComNdRead + dw _IOExit + dw ComInpFlush + dw ComWrite + dw ComWrite + dw ComOutStat + + + +segment _IO_TEXT + + extern CommonNdRdExit:wrt TGROUP + +ComRead: + jcxz ComRd3 + call GetComStat + xor ax,ax + xchg [bx],al + or al,al + jnz ComRd2 +ComRd1: + call BiosRdCom +ComRd2: + stosb + loop ComRd1 + +ComRd3: + jmp _IOExit + + +BiosRdCom: + mov ah,2 + call ComIOCall + test ah,0Eh + jz BiosRdRetn + add sp,byte 2 + xor al,al + or al,0B0h + jmp _IOErrCnt +BiosRdRetn: + retn + + + +ComNdRead: + call GetComStat + mov al,[bx] + or al,al + jnz ComNdRd1 + call ComRdStatus + test ah,1 + jz ComNdRtn + test al,20h + jz ComNdRtn + call BiosRdCom + call GetComStat + mov [bx],al +ComNdRd1: + jmp CommonNdRdExit +ComNdRtn: + jmp _IODone + + +ComOutStat: + call ComRdStatus + test al,20h + jz ComNdRtn + test ah,20h + jz ComNdRtn + jmp _IOExit + + +ComRdStatus: + mov ah,3 + call ComIOCall + retn + + +ComIOCall: + call GetUnitNum + int 14h ; RS-232 get char al, ah=return status + retn + + +ComInpFlush: + call GetComStat + mov byte [bx],0 + jmp _IOExit + + +ComWrite: + jcxz ComRd3 +ComWr1: + mov al,[es:di] + inc di + mov ah,1 + call ComIOCall + test ah,80h + jz ComWr2 + mov al,0Ah + jmp _IOErrCnt +ComWr2: + loop ComWr1 + jmp _IOExit + + +GetComStat: + call GetUnitNum + mov bx,dx + add bx,ComStatArray + retn + +segment _DATA + +ComStatArray db 0, 0, 0, 0 diff --git a/kernel/strings.c b/kernel/strings.c new file mode 100644 index 0000000..70605ae --- /dev/null +++ b/kernel/strings.c @@ -0,0 +1,199 @@ +/****************************************************************/ +/* */ +/* strings.c */ +/* */ +/* Global String Handling Functions */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" + +#ifdef VERSION_STRINGS +static BYTE *stringsRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:33 jhall1 + * Initial revision + * + * Revision 1.4 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.3 1999/08/25 03:18:09 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.2 1999/04/04 18:51:43 jprice + * no message + * + * Revision 1.1.1.1 1999/03/29 15:41:32 jprice + * New version without IPL.SYS + * + * Revision 1.4 1999/02/04 03:14:07 jprice + * Formating. Added comments. + * + * Revision 1.3 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.2 1999/01/22 04:13:27 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.6 04 Jan 1998 23:15:16 patv + * Changed Log for strip utility + * + * Rev 1.5 31 Dec 1997 3:59:30 patv + * Added new far string functions. + * + * Rev 1.4 29 May 1996 21:03:30 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:21:36 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:54:22 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:51:58 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:33:46 patv + * Initial revision. + */ + +COUNT strlen(REG BYTE * s) +{ + REG WORD cnt = 0; + + while (*s++ != 0) + ++cnt; + return cnt; +} + +COUNT FAR init_call_strlen(REG BYTE * s) +{ + return strlen(s); +} + +COUNT fstrlen(REG BYTE FAR * s) +{ + REG WORD cnt = 0; + + while (*s++ != 0) + ++cnt; + return cnt; +} + +VOID _fstrcpy(REG BYTE FAR * d, REG BYTE FAR * s) +{ + while (*s != 0) + *d++ = *s++; + *d = 0; +} + +VOID strncpy(REG BYTE * d, REG BYTE * s, COUNT l) +{ + COUNT idx = 1; + while (*s != 0 && idx++ <= l) + *d++ = *s++; + *d = 0; +} + +COUNT strcmp(REG BYTE * d, REG BYTE * s) +{ + while (*s != '\0' && *d != '\0') + { + if (*d == *s) + ++s, ++d; + else + return *d - *s; + } + return *d - *s; +} + +COUNT FAR init_call_strcmp(REG BYTE * d, REG BYTE * s) +{ + return strcmp(d, s); +} + +COUNT fstrcmp(REG BYTE FAR * d, REG BYTE FAR * s) +{ + while (*s != '\0' && *d != '\0') + { + if (*d == *s) + ++s, ++d; + else + return *d - *s; + } + return *d - *s; +} + +COUNT strncmp(REG BYTE * d, REG BYTE * s, COUNT l) +{ + COUNT index = 1; + while (*s != '\0' && *d != '\0' && index++ <= l) + { + if (*d == *s) + ++s, ++d; + else + return *d - *s; + } + return *d - *s; +} + +COUNT fstrncmp(REG BYTE FAR * d, REG BYTE FAR * s, COUNT l) +{ + COUNT index = 1; + while (*s != '\0' && *d != '\0' && index++ <= l) + { + if (*d == *s) + ++s, ++d; + else + return *d - *s; + } + return *d - *s; +} + +VOID fstrncpy(REG BYTE FAR * d, REG BYTE FAR * s, COUNT l) +{ + COUNT idx = 1; + while (*s != 0 && idx++ <= l) + *d++ = *s++; + *d = 0; +} + +BYTE *strchr(BYTE * s, BYTE c) +{ + REG BYTE *p; + p = s - 1; + do + { + if (*++p == c) + return p; + } + while (*p); + return 0; +} diff --git a/kernel/sysclk.c b/kernel/sysclk.c new file mode 100644 index 0000000..ddcc987 --- /dev/null +++ b/kernel/sysclk.c @@ -0,0 +1,321 @@ +/****************************************************************/ +/* */ +/* sysclk.c */ +/* */ +/* System Clock Driver */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:33 jhall1 + * Initial revision + * + * Revision 1.3 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.2 1999/04/12 03:21:17 jprice + * more ror4 patches. Changes for multi-block IO + * + * Revision 1.1.1.1 1999/03/29 15:41:33 jprice + * New version without IPL.SYS + * + * Revision 1.5 1999/02/08 05:55:58 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/04 03:14:07 jprice + * Formating. Added comments. + * + * Revision 1.3 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.2 1999/01/22 04:13:27 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.4 04 Jan 1998 23:15:16 patv + * Changed Log for strip utility + * + * Rev 1.3 29 May 1996 21:03:48 patv + * bug fixes for v0.91a + * + * Rev 1.2 19 Feb 1996 3:21:34 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.1 01 Sep 1995 17:54:18 patv + * First GPL release. + * + * Rev 1.0 02 Jul 1995 8:32:30 patv + * Initial revision. + */ + +#ifdef PROTO +BOOL ReadPCClock(ULONG *); +VOID WriteATClock(BYTE *, BYTE, BYTE, BYTE); +VOID WritePCClock(ULONG); +COUNT BcdToByte(COUNT); +COUNT BcdToWord(BYTE *, UWORD *, UWORD *, UWORD *); +COUNT ByteToBcd(COUNT); +VOID DayToBcd(BYTE *, UWORD *, UWORD *, UWORD *); +#else +BOOL ReadPCClock(); +VOID WriteATClock(); +VOID WritePCClock(); +COUNT BcdToByte(); +COUNT BcdToWord(); +COUNT ByteToBcd(); +VOID DayToBcd(); +#endif + +/* */ +/* WARNING - THIS DRIVER IS NON-PORTABLE!!!! */ +/* */ + +WORD days[2][13] = +{ + {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, + {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366} +}; + +static struct ClockRecord clk; + +static BYTE bcdDays[4]; +static UWORD Month, + Day, + Year; +static BYTE bcdMinutes; +static BYTE bcdHours; +static BYTE bcdHundredths; +static BYTE bcdSeconds; + +static ULONG Ticks; +UWORD DaysSinceEpoch = 0; + +WORD clk_driver(rqptr rp) +{ + REG COUNT count, + c; + BYTE FAR *cp; + + switch (rp->r_command) + { + case C_INIT: + rp->r_endaddr = device_end(); + rp->r_nunits = 0; + return S_DONE; + + case C_INPUT: + count = rp->r_count; + if (count > sizeof(struct ClockRecord)) + count = sizeof(struct ClockRecord); + { + ULONG remainder, + hs; + if (ReadPCClock(&Ticks)) + ++DaysSinceEpoch; + clk.clkDays = DaysSinceEpoch; + /* + * Another tricky calculation (after the one in `main.c'). This time + * we do have a problem with overflow, because we need to extract the + * 1/100s portion too. The scaling factor is now + * (100 x 86400) / 0x1800b0 = 108000 / 19663. -- ror4 + */ + hs = 0; + if (Ticks >= 64 * 19663ul) + { + hs += 64 * 108000ul; + Ticks -= 64 * 19663ul; + } + if (Ticks >= 32 * 19663ul) + { + hs += 32 * 108000ul; + Ticks -= 32 * 19663ul; + } + if (Ticks >= 16 * 19663ul) + { + hs += 16 * 108000ul; + Ticks -= 16 * 19663ul; + } + if (Ticks >= 8 * 19663ul) + { + hs += 8 * 108000ul; + Ticks -= 8 * 19663ul; + } + if (Ticks >= 4 * 19663ul) + { + hs += 4 * 108000ul; + Ticks -= 4 * 19663ul; + } + if (Ticks >= 2 * 19663ul) + { + hs += 2 * 108000ul; + Ticks -= 2 * 19663ul; + } + if (Ticks >= 19663ul) + { + hs += 108000ul; + Ticks -= 19663ul; + } + /* + * Now Ticks < 19663, so Ticks * 108000 < 2123604000 < ULONG_MAX. + * *phew* -- ror4 + */ + hs += Ticks * 108000ul / 19663ul; + clk.clkHours = hs / 360000ul; + remainder = hs % 360000ul; + clk.clkMinutes = remainder / 6000ul; + remainder %= 6000ul; + clk.clkSeconds = remainder / 100ul; + clk.clkHundredths = remainder % 100ul; + } + fbcopy((BYTE FAR *) & clk, rp->r_trans, count); + return S_DONE; + + case C_OUTPUT: + count = rp->r_count; + if (count > sizeof(struct ClockRecord)) + count = sizeof(struct ClockRecord); + rp->r_count = count; + fbcopy(rp->r_trans, (BYTE FAR *) & clk, count); + + /* Set PC Clock first */ + DaysSinceEpoch = clk.clkDays; + { + ULONG hs; + hs = 360000ul * clk.clkHours + + 6000ul * clk.clkMinutes + + 100ul * clk.clkSeconds + + clk.clkHundredths; + Ticks = 0; + if (hs >= 64 * 108000ul) + { + Ticks += 64 * 19663ul; + hs -= 64 * 108000ul; + } + if (hs >= 32 * 108000ul) + { + Ticks += 32 * 19663ul; + hs -= 32 * 108000ul; + } + if (hs >= 16 * 108000ul) + { + Ticks += 16 * 19663ul; + hs -= 16 * 108000ul; + } + if (hs >= 8 * 108000ul) + { + Ticks += 8 * 19663ul; + hs -= 8 * 108000ul; + } + if (hs >= 4 * 108000ul) + { + Ticks += 4 * 19663ul; + hs -= 4 * 108000ul; + } + if (hs >= 2 * 108000ul) + { + Ticks += 2 * 19663ul; + hs -= 2 * 108000ul; + } + if (hs >= 108000ul) + { + Ticks += 19663ul; + hs -= 108000ul; + } + Ticks += hs * 19663ul / 108000ul; + } + WritePCClock(Ticks); + + /* Now set AT clock */ + /* Fix year by looping through each year, subtracting */ + /* the appropriate number of days for that year. */ + for (Year = 1980, c = clk.clkDays; c > 0;) + { + count = is_leap_year(Year) ? 366 : 365; + if (c >= count) + { + ++Year; + c -= count; + } + else + break; + } + + /* c contains the days left and count the number of */ + /* days for that year. Use this to index the table. */ + for (Month = 1; Month < 13; ++Month) + { + if (days[count == 366][Month] > c) + { + Day = c - days[count == 366][Month - 1] + 1; + break; + } + } + DayToBcd((BYTE *) bcdDays, &Month, &Day, &Year); + bcdMinutes = ByteToBcd(clk.clkMinutes); + bcdHours = ByteToBcd(clk.clkHours); + bcdSeconds = ByteToBcd(clk.clkSeconds); + WriteATClock(bcdDays, bcdHours, bcdMinutes, bcdSeconds); + return S_DONE; + + case C_OFLUSH: + case C_IFLUSH: + return S_DONE; + + case C_OUB: + case C_NDREAD: + case C_OSTAT: + case C_ISTAT: + default: + return failure(E_FAILURE); /* general failure */ + } +} + +COUNT ByteToBcd(COUNT x) +{ + return ((x / 10) << 4) | (x % 10); +} + +VOID DayToBcd(BYTE * x, UWORD * mon, UWORD * day, UWORD * yr) +{ + x[1] = ByteToBcd(*mon); + x[0] = ByteToBcd(*day); + x[3] = ByteToBcd(*yr / 100); + x[2] = ByteToBcd(*yr % 100); +} + +/* Used by `main.c'. */ +VOID FAR init_call_WritePCClock(ULONG ticks) +{ + WritePCClock(ticks); +} diff --git a/kernel/syspack.c b/kernel/syspack.c new file mode 100644 index 0000000..c221675 --- /dev/null +++ b/kernel/syspack.c @@ -0,0 +1,157 @@ +/****************************************************************/ +/* */ +/* syspack.c */ +/* */ +/* System Disk Byte Order Packing Functions */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/* */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *syspackRcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:34 jhall1 + * Initial revision + * + * Revision 1.1.1.1 1999/03/29 15:42:21 jprice + * New version without IPL.SYS + * + * Revision 1.3 1999/02/01 01:43:28 jprice + * Fixed findfirst function to find volume label with Windows long filenames + * + * Revision 1.2 1999/01/22 04:15:28 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:00 jprice + * Imported sources + * + * + * Rev 1.4 04 Jan 1998 23:14:38 patv + * Changed Log for strip utility + * + * Rev 1.3 29 May 1996 21:15:12 patv + * bug fixes for v0.91a + * + * Rev 1.2 01 Sep 1995 17:48:42 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:50:26 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:05:34 patv + * Initial revision. + */ + +#ifdef NONNATIVE +VOID getlong(REG VOID * vp, LONG * lp) +{ + *lp = (((BYTE *) vp)[0] & 0xff) + + ((((BYTE *) vp)[1] & 0xff) << 8) + + ((((BYTE *) vp)[2] & 0xff) << 16) + + ((((BYTE *) vp)[3] & 0xff) << 24); +} + +VOID getword(REG VOID * vp, WORD * wp) +{ + *wp = (((BYTE *) vp)[0] & 0xff) + ((((BYTE *) vp)[1] & 0xff) << 8); +} + +VOID getbyte(VOID * vp, BYTE * bp) +{ + *bp = *((BYTE *) vp); +} + +VOID fgetword(REG VOID FAR * vp, WORD FAR * wp) +{ + *wp = (((BYTE FAR *) vp)[0] & 0xff) + ((((BYTE FAR *) vp)[1] & 0xff) << 8); +} + +VOID fgetlong(REG VOID FAR * vp, LONG FAR * lp) +{ + *lp = (((BYTE *) vp)[0] & 0xff) + + ((((BYTE *) vp)[1] & 0xff) << 8) + + ((((BYTE *) vp)[2] & 0xff) << 16) + + ((((BYTE *) vp)[3] & 0xff) << 24); +} + +VOID fgetbyte(VOID FAR * vp, BYTE FAR * bp) +{ + *bp = *((BYTE FAR *) vp); +} + +VOID fputlong(LONG FAR * lp, VOID FAR * vp) +{ + REG BYTE FAR *bp = (BYTE FAR *) vp; + + bp[0] = *lp & 0xff; + bp[1] = (*lp >> 8) & 0xff; + bp[2] = (*lp >> 16) & 0xff; + bp[3] = (*lp >> 24) & 0xff; +} + +VOID fputword(WORD FAR * wp, VOID FAR * vp) +{ + REG BYTE FAR *bp = (BYTE FAR *) vp; + + bp[0] = *wp & 0xff; + bp[1] = (*wp >> 8) & 0xff; +} + +VOID fputbyte(BYTE FAR * bp, VOID FAR * vp) +{ + *(BYTE FAR *) vp = *bp; +} +#endif + +VOID getdirent(BYTE FAR * vp, struct dirent FAR * dp) +{ + fbcopy(&vp[DIR_NAME], dp->dir_name, FNAME_SIZE); + fbcopy(&vp[DIR_EXT], dp->dir_ext, FEXT_SIZE); + fgetbyte(&vp[DIR_ATTRIB], (BYTE FAR *) & dp->dir_attrib); + fgetword(&vp[DIR_TIME], (WORD FAR *) & dp->dir_time); + fgetword(&vp[DIR_DATE], (WORD FAR *) & dp->dir_date); + fgetword(&vp[DIR_START], (WORD FAR *) & dp->dir_start); + fgetlong(&vp[DIR_SIZE], (LONG FAR *) & dp->dir_size); +} + +VOID putdirent(struct dirent FAR * dp, BYTE FAR * vp) +{ + REG COUNT i; + REG BYTE FAR *p; + + fbcopy(dp->dir_name, &vp[DIR_NAME], FNAME_SIZE); + fbcopy(dp->dir_ext, &vp[DIR_EXT], FEXT_SIZE); + fputbyte((BYTE FAR *) & dp->dir_attrib, &vp[DIR_ATTRIB]); + fputword((WORD FAR *) & dp->dir_time, &vp[DIR_TIME]); + fputword((WORD FAR *) & dp->dir_date, &vp[DIR_DATE]); + fputword((WORD FAR *) & dp->dir_start, &vp[DIR_START]); + fputlong((LONG FAR *) & dp->dir_size, &vp[DIR_SIZE]); + for (i = 0, p = (BYTE FAR *) & vp[DIR_RESERVED]; i < 10; i++) + *p++ = NULL; +} diff --git a/kernel/systime.c b/kernel/systime.c new file mode 100644 index 0000000..d4799ab --- /dev/null +++ b/kernel/systime.c @@ -0,0 +1,242 @@ +/****************************************************************/ +/* */ +/* systime.c */ +/* */ +/* DOS/C Date/Time Functions */ +/* */ +/* Copyright (c) 1998 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "time.h" +#include "date.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:34 jhall1 + * Initial revision + * + * Revision 1.3 1999/05/04 16:40:30 jprice + * ror4 date fix + * + * Revision 1.2 1999/04/12 03:21:18 jprice + * more ror4 patches. Changes for multi-block IO + * + * Revision 1.1.1.1 1999/03/29 15:41:34 jprice + * New version without IPL.SYS + * + * Revision 1.5 1999/02/08 05:55:58 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/04 03:14:07 jprice + * Formating. Added comments. + * + * Revision 1.3 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.2 1999/01/22 04:13:27 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.6 06 Dec 1998 8:47:30 patv + * Bug fixes. + * + * Rev 1.5 04 Jan 1998 23:15:22 patv + * Changed Log for strip utility + * + * Rev 1.4 03 Jan 1998 8:36:50 patv + * Converted data area to SDA format + * + * Rev 1.3 29 May 1996 21:03:40 patv + * bug fixes for v0.91a + * + * Rev 1.2 19 Feb 1996 3:21:34 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.1 01 Sep 1995 17:54:16 patv + * First GPL release. + * + * Rev 1.0 02 Jul 1995 8:32:20 patv + * Initial revision. + */ + +static WORD days[2][13] = +{ + {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, + {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366} +}; + +static WORD ndays[2][13] = +{ + /* 1 2 3 4 5 6 7 8 9 10 11 12 */ + {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, +}; + +extern BYTE + Month, + DayOfMonth, + DayOfWeek; + +extern COUNT + Year, + YearsSince1980; + +extern request + ClkReqHdr; + +VOID DosGetTime(BYTE FAR * hp, BYTE FAR * mp, BYTE FAR * sp, BYTE FAR * hdp) +{ + ClkReqHdr.r_length = sizeof(request); + ClkReqHdr.r_command = C_INPUT; + ClkReqHdr.r_count = sizeof(struct ClockRecord); + ClkReqHdr.r_trans = (BYTE FAR *) (&ClkRecord); + ClkReqHdr.r_status = 0; + execrh((request FAR *) & ClkReqHdr, (struct dhdr FAR *)clock); + if (ClkReqHdr.r_status & S_ERROR) + return; + + *hp = ClkRecord.clkHours; + *mp = ClkRecord.clkMinutes; + *sp = ClkRecord.clkSeconds; + *hdp = ClkRecord.clkHundredths; +} + +COUNT DosSetTime(BYTE FAR * hp, BYTE FAR * mp, BYTE FAR * sp, BYTE FAR * hdp) +{ + DosGetDate((BYTE FAR *) & DayOfWeek, (BYTE FAR *) & Month, + (BYTE FAR *) & DayOfMonth, (COUNT FAR *) & Year); + + ClkRecord.clkHours = *hp; + ClkRecord.clkMinutes = *mp; + ClkRecord.clkSeconds = *sp; + ClkRecord.clkHundredths = *hdp; + + YearsSince1980 = Year - 1980; + ClkRecord.clkDays = DayOfMonth - 1 + + days[is_leap_year(Year)][Month - 1] + + ((YearsSince1980) * 365) + + ((YearsSince1980 + 3) / 4); + + ClkReqHdr.r_length = sizeof(request); + ClkReqHdr.r_command = C_OUTPUT; + ClkReqHdr.r_count = sizeof(struct ClockRecord); + ClkReqHdr.r_trans = (BYTE FAR *) (&ClkRecord); + ClkReqHdr.r_status = 0; + execrh((request FAR *) & ClkReqHdr, (struct dhdr FAR *)clock); + if (ClkReqHdr.r_status & S_ERROR) + return char_error(&ClkReqHdr, (struct dhdr FAR *)clock); + return SUCCESS; +} + +VOID DosGetDate(wdp, mp, mdp, yp) +BYTE FAR *wdp, + FAR * mp, + FAR * mdp; +COUNT FAR *yp; +{ + COUNT count, + c; + + ClkReqHdr.r_length = sizeof(request); + ClkReqHdr.r_command = C_INPUT; + ClkReqHdr.r_count = sizeof(struct ClockRecord); + ClkReqHdr.r_trans = (BYTE FAR *) (&ClkRecord); + ClkReqHdr.r_status = 0; + execrh((request FAR *) & ClkReqHdr, (struct dhdr FAR *)clock); + if (ClkReqHdr.r_status & S_ERROR) + return; + + for (Year = 1980, c = ClkRecord.clkDays; c > 0;) + { + count = is_leap_year(Year) ? 366 : 365; + if (c >= count) + { + ++Year; + c -= count; + } + else + break; + } + + /* c contains the days left and count the number of days for */ + /* that year. Use this to index the table. */ + Month = 1; + while (c >= ndays[count == 366][Month]) + { + c -= ndays[count == 366][Month]; + ++Month; + } + + *mp = Month; + *mdp = c + 1; + *yp = Year; + + /* Day of week is simple. Take mod 7, add 2 (for Tuesday */ + /* 1-1-80) and take mod again */ + + DayOfWeek = (ClkRecord.clkDays % 7 + 2) % 7; + *wdp = DayOfWeek; +} + +COUNT DosSetDate(mp, mdp, yp) +BYTE FAR *mp, + FAR * mdp; +COUNT FAR *yp; +{ + Month = *mp; + DayOfMonth = *mdp; + Year = *yp; + if (Year < 1980 || Year > 2099 + || Month < 1 || Month > 12 + || DayOfMonth < 1 || DayOfMonth > ndays[is_leap_year(Year)][Month]) + return DE_INVLDDATA; + + DosGetTime((BYTE FAR *) & ClkRecord.clkHours, + (BYTE FAR *) & ClkRecord.clkMinutes, + (BYTE FAR *) & ClkRecord.clkSeconds, + (BYTE FAR *) & ClkRecord.clkHundredths); + + YearsSince1980 = Year - 1980; + ClkRecord.clkDays = DayOfMonth - 1 + + days[is_leap_year(Year)][Month - 1] + + ((YearsSince1980) * 365) + + ((YearsSince1980 + 3) / 4); + + ClkReqHdr.r_length = sizeof(request); + ClkReqHdr.r_command = C_OUTPUT; + ClkReqHdr.r_count = sizeof(struct ClockRecord); + ClkReqHdr.r_trans = (BYTE FAR *) (&ClkRecord); + ClkReqHdr.r_status = 0; + execrh((request FAR *) & ClkReqHdr, (struct dhdr FAR *)clock); + if (ClkReqHdr.r_status & S_ERROR) + return char_error(&ClkReqHdr, (struct dhdr FAR *)clock); + return SUCCESS; +} diff --git a/kernel/task.c b/kernel/task.c new file mode 100644 index 0000000..9c9928f --- /dev/null +++ b/kernel/task.c @@ -0,0 +1,914 @@ +/****************************************************************/ +/* */ +/* task.c */ +/* */ +/* Task Manager for DOS Processes */ +/* */ +/* Copyright (c) 1995 */ +/* Pasquale J. Villani */ +/* All Rights Reserved */ +/* */ +/* This file is part of DOS-C. */ +/* */ +/* DOS-C 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, or (at your option) any later version. */ +/* */ +/* DOS-C 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 DOS-C; see the file COPYING. If not, */ +/* write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/****************************************************************/ + +#include "portab.h" +#include "globals.h" + +#ifdef VERSION_STRINGS +static BYTE *RcsId = "$Id$"; +#endif + +/* + * $Log$ + * Revision 1.1 2000/05/06 19:35:36 jhall1 + * Initial revision + * + * Revision 1.7 2000/03/09 06:07:11 kernel + * 2017f updates by James Tabor + * + * Revision 1.6 1999/08/25 03:18:10 jprice + * ror4 patches to allow TC 2.01 compile. + * + * Revision 1.5 1999/04/23 04:24:39 jprice + * Memory manager changes made by ska + * + * Revision 1.4 1999/04/16 00:53:33 jprice + * Optimized FAT handling + * + * Revision 1.3 1999/04/11 04:33:39 jprice + * ror4 patches + * + * Revision 1.2 1999/03/29 17:05:09 jprice + * ror4 changes + * + * Revision 1.1.1.1 1999/03/29 15:41:41 jprice + * New version without IPL.SYS + * + * Revision 1.5 1999/02/08 05:55:58 jprice + * Added Pat's 1937 kernel patches + * + * Revision 1.4 1999/02/04 03:14:07 jprice + * Formating. Added comments. + * + * Revision 1.3 1999/02/01 01:48:41 jprice + * Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines) + * + * Revision 1.2 1999/01/22 04:13:27 jprice + * Formating + * + * Revision 1.1.1.1 1999/01/20 05:51:01 jprice + * Imported sources + * + * + * Rev 1.15 06 Dec 1998 8:46:28 patv + * Bug fixes. + * + * Rev 1.14 07 Feb 1998 20:38:32 patv + * Modified stack fram to match DOS standard + * + * Rev 1.13 31 Jan 1998 14:39:20 patv + * Corrected type in load high code. + * + * Rev 1.12 31 Jan 1998 14:02:52 patv + * Added load high in memory option in DosExeLoader. + * + * Rev 1.11 22 Jan 1998 22:17:14 patv + * Eliminated warnings. + * + * Rev 1.10 22 Jan 1998 21:31:36 patv + * Corrected short .COM problem. + * + * Rev 1.9 04 Jan 1998 23:15:16 patv + * Changed Log for strip utility + * + * Rev 1.8 22 Jan 1997 13:18:14 patv + * pre-0.92 Svante Frey bug fixes. + * + * Rev 1.7 16 Jan 1997 12:46:56 patv + * pre-Release 0.92 feature additions + * + * Rev 1.5 29 Aug 1996 13:07:22 patv + * Bug fixes for v0.91b + * + * Rev 1.4 29 May 1996 21:03:36 patv + * bug fixes for v0.91a + * + * Rev 1.3 19 Feb 1996 3:21:48 patv + * Added NLS, int2f and config.sys processing + * + * Rev 1.2 01 Sep 1995 17:54:22 patv + * First GPL release. + * + * Rev 1.1 30 Jul 1995 20:51:58 patv + * Eliminated version strings in ipl + * + * Rev 1.0 02 Jul 1995 8:34:06 patv + * Initial revision. + */ + +#define toupper(c) ((c) >= 'a' && (c) <= 'z' ? (c) + ('A' - 'a') : (c)) + +#define LOADNGO 0 +#define LOAD 1 +#define OVERLAY 3 + +static exe_header header; + +#define CHUNK 32256 +#define MAXENV 32768 +#define ENV_KEEPFREE 83 /* keep unallocated by environment variables */ + /* The '65' added to nEnvSize does not cover the additional stuff: + + 2 bytes: number of strings + + 80 bytes: maximum absolute filename + + 1 byte: '\0' + -- 1999/04/21 ska */ + +#ifndef PROTO +COUNT ChildEnv(exec_blk FAR *, UWORD *, char far *); +#else +COUNT ChildEnv(); +#endif + +LONG doslseek(COUNT fd, LONG foffset, COUNT origin) +{ + LONG set_pos; + DosSeek(fd, foffset, origin, (ULONG *) & set_pos); + return set_pos; +} + +LONG DosGetFsize(COUNT hndl) +{ + sft FAR *s; + sfttbl FAR *sp; + + /* Test that the handle is valid */ + if (hndl < 0) + return DE_INVLDHNDL; + + /* Get the SFT block that contains the SFT */ + if ((s = get_sft(hndl)) == (sft FAR *) - 1) + return DE_INVLDHNDL; + + /* If this is not opened another error */ + if (s->sft_count == 0) + return DE_ACCESS; + + /* If SFT entry refers to a device, return the date and time of opening */ + if (s->sft_flags & (SFT_FDEVICE | SFT_FSHARED)) + { + return s->sft_size; + } + + /* call file system handler */ + return dos_getfsize(s->sft_status); +} + +COUNT ChildEnv(exec_blk FAR * exp, UWORD * pChildEnvSeg, char far * pathname) +{ + BYTE FAR *pSrc; + BYTE FAR *pDest; + UWORD nEnvSize; + COUNT RetCode; +/* UWORD MaxEnvSize; not used -- 1999/04/21 ska */ + psp FAR *ppsp = MK_FP(cu_psp, 0); + + /* create a new environment for the process */ + /* copy parent's environment if exec.env_seg == 0 */ + + pDest = pSrc = exp->exec.env_seg ? + MK_FP(exp->exec.env_seg, 0) : + MK_FP(ppsp->ps_environ, 0); + +#if 0 + /* Every process requires an environment because of argv[0] + -- 1999/04/21 ska */ + */ + if (!pSrc) /* no environment to copy */ + { + *pChildEnvSeg = 0; + return SUCCESS; + } +#endif + + nEnvSize = 1; + /* This loop had not counted the very last '\0' + -- 1999/04/21 ska */ + if (pSrc) + { /* if no environment is available, one byte is required */ + while (*pSrc != '\0') + { + while (*pSrc != '\0' && pSrc < pDest + MAXENV - ENV_KEEPFREE) + { + ++pSrc; + ++nEnvSize; + } + /* account for terminating null */ + ++nEnvSize; + ++pSrc; + } + pSrc = pDest; + } + + /* Test env size and abort if greater than max */ + if (nEnvSize >= MAXENV) + return DE_INVLDENV; + + /* allocate enough space for env + path */ + if ((RetCode = DosMemAlloc(long2para(nEnvSize + ENV_KEEPFREE), + FIRST_FIT, (seg FAR *) pChildEnvSeg, + NULL /*(UWORD FAR *) MaxEnvSize ska */ )) < 0) + return RetCode; + pDest = MK_FP(*pChildEnvSeg + 1, 0); + + /* fill the new env and inform the process of its */ + /* location throught the psp */ + + /* copy the environment */ + if (pSrc) + { + fbcopy(pSrc, pDest, nEnvSize); + pDest += nEnvSize; + } + else + *pDest++ = '\0'; /* create an empty environment */ + +#if 0 + /* The size is already known, use a quicker copy function + -- 1999/04/21 ska */ + for (; *pSrc != '\0';) + { + while (*pSrc) + { + *pDest++ = *pSrc++; + } + pSrc++; + *pDest++ = 0; + } + *pDest++ = 0; +#endif + /* initialize 'extra strings' count */ + *((UWORD FAR *) pDest)++ = 1; + + /* copy complete pathname */ + truename(pathname, pDest, TRUE); + + /* Theoretically one could either: + + resize the already allocated block to best-fit behind the pathname, or + + generate the filename into a temporary buffer to allocate only the + minimum required environment -- 1999/04/21 ska */ + + return SUCCESS; +} + +/* The following code is 8086 dependant */ +VOID new_psp(psp FAR * p, int psize) +{ + REG COUNT i; + BYTE FAR *lpPspBuffer; + psp FAR *q = MK_FP(cu_psp, 0); + + /* Clear out new psp first */ + for (lpPspBuffer = (BYTE FAR *) p, i = 0; i < sizeof(psp); ++i) + *lpPspBuffer = 0; + + /* initialize all entries and exits */ + /* CP/M-like exit point */ + p->ps_exit = 0x20cd; + + /* CP/M-like entry point - jump to special entry */ + p->ps_farcall = 0xea; + p->ps_reentry = cpm_entry; + /* unix style call - 0xcd 0x21 0xcb (int 21, retf) */ + p->ps_unix[0] = 0xcd; + p->ps_unix[1] = 0x21; + p->ps_unix[2] = 0xcb; + + /* Now for parent-child relationships */ + /* parent psp segment */ + p->ps_parent = cu_psp; + /* previous psp pointer */ + p->ps_prevpsp = q; + + /* Environment and memory useage parameters */ + /* memory size in paragraphs */ + p->ps_size = psize; + /* environment paragraph */ + p->ps_environ = 0; + /* process dta */ + p->ps_dta = (BYTE FAR *) (&p->ps_cmd_count); + + /* terminate address */ + p->ps_isv22 = (VOID(interrupt FAR *) (void))getvec(0x22); + /* break address */ + p->ps_isv23 = (VOID(interrupt FAR *) (void))getvec(0x23); + /* critical error address */ + p->ps_isv24 = (VOID(interrupt FAR *) (void))getvec(0x24); + + /* File System parameters */ + /* user stack pointer - int 21 */ + p->ps_stack = (BYTE FAR *) - 1; + /* file table - 0xff is unused */ + for (i = 0; i < 20; i++) + p->ps_files[i] = 0xff; + + /* maximum open files */ + p->ps_maxfiles = 20; + /* open file table pointer */ + p->ps_filetab = p->ps_files; + + /* clone the file table */ + if (InDOS > 0) + { + REG COUNT i; + + for (i = 0; i < 20; i++) + { + if (q->ps_filetab[i] != 0xff && CloneHandle(i) >= 0) + p->ps_filetab[i] = q->ps_filetab[i]; + else + p->ps_filetab[i] = 0xff; + } + } + else + { + /* initialize stdin, stdout, etc */ + p->ps_files[STDIN] = 0; /* stdin */ + p->ps_files[STDOUT] = 1; /* stdout */ + p->ps_files[STDERR] = 2; /* stderr */ + p->ps_files[STDAUX] = 3; /* stdaux */ + p->ps_files[STDPRN] = 4; /* stdprn */ + } + + /* first command line argument */ + p->ps_fcb1.fcb_drive = 0; + /* second command line argument */ + p->ps_fcb2.fcb_drive = 0; + + /* local command line */ + p->ps_cmd_count = 0; /* command tail */ + p->ps_cmd[0] = 0; /* command tail */ + if (RootPsp == (seg) ~ 0) + RootPsp = FP_SEG(p); +} + +static VOID patchPSP(UWORD pspseg, UWORD envseg, CommandTail FAR * cmdline + ,BYTE FAR * fnam) +{ + psp FAR *psp; + mcb FAR *pspmcb; + int i; + BYTE FAR *np; + + pspmcb = MK_FP(pspseg, 0); + ++pspseg; + psp = MK_FP(pspseg, 0); + + /* complete the psp by adding the command line */ + fbcopy(cmdline->ctBuffer, psp->ps_cmd, 127); + psp->ps_cmd_count = cmdline->ctCount; + + /* identify the mcb as this functions' */ + pspmcb->m_psp = pspseg; + /* Patch in environment segment, if present, also adjust its MCB */ + if (envseg) + { + psp->ps_environ = envseg + 1; + ((mcb FAR *) MK_FP(envseg, 0))->m_psp = pspseg; + } + else + psp->ps_environ = 0; + + /* use the file name less extension - left adjusted and */ + np = fnam; + for (;;) + { + switch (*fnam++) + { + case '\0': + goto set_name; + case ':': + case '/': + case '\\': + np = fnam; + } + } +set_name: + for (i = 0; i < 8 && np[i] != '.' && np[i] != '\0'; i++) + { + pspmcb->m_name[i] = toupper(np[i]); + } + if (i < 8) + pspmcb->m_name[i] = '\0'; + +} + +static COUNT DosComLoader(BYTE FAR * namep, exec_blk FAR * exp, COUNT mode) +{ + COUNT rc, + err, + env_size; + COUNT nread; + UWORD mem; + UWORD env, + asize; + BYTE FAR *sp; + psp FAR *p; + psp FAR *q = MK_FP(cu_psp, 0); + iregs FAR *irp; + LONG com_size; + + if (mode != OVERLAY) + { + + if ((rc = ChildEnv(exp, &env, namep)) != SUCCESS) + { + return rc; + } + /* Allocate our memory and pass back any errors */ + if ((rc = DosMemAlloc(0, LARGEST, (seg FAR *) & mem, (UWORD FAR *) & asize)) < 0) + { + DosMemFree(env); /* env may be 0 */ + return rc; + } + ++mem; + } + else + mem = exp->load.load_seg; + + /* Now load the executable */ + /* If file not found - error */ + /* NOTE - this is fatal because we lost it in transit */ + /* from DosExec! */ + if ((rc = DosOpen(namep, 0)) < 0) + fatal("(DosComLoader) com file lost in transit"); + + /* do it in 32K chunks */ + if ((com_size = DosGetFsize(rc)) != 0) + { + if (mode == OVERLAY) /* memory already allocated */ + sp = MK_FP(mem, 0); + else + { /* test the filesize against the allocated memory */ + sp = MK_FP(mem, sizeof(psp)); + + /* This is a potential problem, what to do with .COM files larger than + the allocated memory? + MS DOS always only loads the very first 64KB - sizeof(psp) bytes. + -- 1999/04/21 ska */ + if (com_size > (LONG) asize << 4) /* less memory than the .COM file has */ + com_size = (LONG) asize << 4; + } + do + { + nread = DosRead(rc, CHUNK, sp, &err); + sp = add_far((VOID FAR *) sp, (ULONG) nread); + } + while ((com_size -= nread) > 0 && nread == CHUNK); + } + DosClose(rc); + + if (mode == OVERLAY) + return SUCCESS; + + /* point to the PSP so we can build it */ + p = MK_FP(mem, 0); + setvec(0x22, (VOID(INRPT FAR *) (VOID)) MK_FP(user_r->CS, user_r->IP)); + new_psp(p, mem + asize); + + patchPSP(mem - 1, env, exp->exec.cmd_line, namep); + + /* build the user area on the stack */ + *((UWORD FAR *) MK_FP(mem, 0xfffe)) = (UWORD) 0; + irp = MK_FP(mem, (0xfffe - sizeof(iregs))); + + /* start allocating REGs */ + irp->ES = irp->DS = mem; + irp->CS = mem; + irp->IP = 0x100; + irp->AX = 0xffff; /* for now, until fcb code is in */ + irp->BX = + irp->CX = + irp->DX = + irp->SI = + irp->DI = + irp->BP = 0; + irp->FLAGS = 0x200; + + /* Transfer control to the executable */ + p->ps_parent = cu_psp; + p->ps_prevpsp = (BYTE FAR *) MK_FP(cu_psp, 0); + q->ps_stack = (BYTE FAR *) user_r; + user_r->FLAGS &= ~FLG_CARRY; + + switch (mode) + { + case LOADNGO: + { + cu_psp = mem; + dta = p->ps_dta; + if (InDOS) + --InDOS; + exec_user(irp); + + /* We should never be here */ + fatal("KERNEL RETURNED!!!"); + break; + } + case LOAD: + cu_psp = mem; + exp->exec.stack = (BYTE FAR *) irp; + exp->exec.start_addr = MK_FP(irp->CS, irp->IP); + return SUCCESS; + } + + return DE_INVLDFMT; +} + +VOID return_user(void) +{ + psp FAR *p, + FAR * q; + REG COUNT i; + iregs FAR *irp; + long j; + + /* restore parent */ + p = MK_FP(cu_psp, 0); + + /* When process returns - restore the isv */ + setvec(0x22, p->ps_isv22); + setvec(0x23, p->ps_isv23); + setvec(0x24, p->ps_isv24); + + /* And free all process memory if not a TSR return */ + if (!tsr) + { + for (i = 0; i < p->ps_maxfiles; i++) + { + DosClose(i); + } + FreeProcessMem(cu_psp); + } + + cu_psp = p->ps_parent; + q = MK_FP(cu_psp, 0); + dta = q->ps_dta; + + irp = (iregs FAR *) q->ps_stack; + + irp->CS = FP_SEG(p->ps_isv22); + irp->IP = FP_OFF(p->ps_isv22); + + if (InDOS) + --InDOS; + exec_user((iregs FAR *) q->ps_stack); +} + +static COUNT DosExeLoader(BYTE FAR * namep, exec_blk FAR * exp, COUNT mode) +{ + COUNT rc, + err, + env_size, + i; + COUNT nBytesRead; + UWORD mem, + env, + asize, + start_seg; + ULONG image_size; + ULONG image_offset; + BYTE FAR *sp; + psp FAR *p; + psp FAR *q = MK_FP(cu_psp, 0); + mcb FAR *mp; + iregs FAR *irp; + UWORD reloc[2]; + seg FAR *spot; + LONG exe_size; + + /* Clone the environement and create a memory arena */ + if (mode != OVERLAY) + { + if ((rc = ChildEnv(exp, &env, namep)) != SUCCESS) + return rc; + } + else + mem = exp->load.load_seg; + + /* compute image offset from the header */ + image_offset = (ULONG) header.exHeaderSize * 16l; + + /* compute image size by removing the offset from the */ + /* number pages scaled to bytes plus the remainder and */ + /* the psp */ + /* First scale the size */ + image_size = (ULONG) (header.exPages) * 512l; + /* remove the offset */ + image_size -= image_offset; + + /* and finally add in the psp size */ + if (mode != OVERLAY) + image_size += (ULONG) long2para((LONG) sizeof(psp)); + + if (mode != OVERLAY) + { + /* Now find out how many paragraphs are available */ + if ((rc = DosMemLargest((seg FAR *) & asize)) != SUCCESS) + { + DosMemFree(env); + return rc; + } + + exe_size = (LONG) long2para(image_size) + header.exMinAlloc; + /* + long2para((LONG) sizeof(psp)); ?? see above + image_size += sizeof(psp) -- 1999/04/21 ska */ + if (exe_size > asize) + { + DosMemFree(env); + return DE_NOMEM; + } + exe_size = (LONG) long2para(image_size) + header.exMaxAlloc; + /* + long2para((LONG) sizeof(psp)); ?? -- 1999/04/21 ska */ + if (exe_size > asize) + exe_size = asize; + } + + /* Allocate our memory and pass back any errors */ + /* We can still get an error on first fit if the above */ + /* returned size was a bet fit case */ + if ((rc = DosMemAlloc((seg) exe_size, FIRST_FIT, (seg FAR *) & mem + ,(UWORD FAR *) & asize)) < 0) + { + if (rc == DE_NOMEM) + { + if ((rc = DosMemAlloc(0, LARGEST, (seg FAR *) & mem + ,(UWORD FAR *) & asize)) < 0) + { + DosMemFree(env); + return rc; + } + /* This should never happen, but ... */ + if (asize < exe_size) + { + DosMemFree(mem); + DosMemFree(env); + return rc; + } + } + else + { + DosMemFree(env); + return rc; + } + } + else + /* with no error, we got exactly what we asked for */ + asize = exe_size; + if (mode != OVERLAY) + { + /* memory found large enough - continue processing */ + mp = MK_FP(mem, 0); + ++mem; + } + else + mem = exp->load.load_seg; + + /* create the start seg for later computations */ + if (mode == OVERLAY) + start_seg = mem; + else + { + start_seg = mem + long2para((LONG) sizeof(psp)); + } + + /* Now load the executable */ + /* If file not found - error */ + /* NOTE - this is fatal because we lost it in transit */ + /* from DosExec! */ + if ((rc = DosOpen(namep, 0)) < 0) + { + fatal("(DosExeLoader) exe file lost in transit"); + } + /* offset to start of image */ + if (doslseek(rc, image_offset, 0) != image_offset) + { + if (mode != OVERLAY) + { + DosMemFree(--mem); + DosMemFree(env); + } + return DE_INVLDDATA; + } + + /* read in the image in 32K chunks */ + if (mode != OVERLAY) + { + exe_size = image_size - long2para((LONG) sizeof(psp)); + } + else + exe_size = image_size; + + if (exe_size > 0) + { + sp = MK_FP(start_seg, 0x0); + + if (mode != OVERLAY) + { + if ((header.exMinAlloc == 0) && (header.exMaxAlloc == 0)) + { + sp = MK_FP(start_seg + mp->m_size + - (image_size + 15) / 16, 0); + } + } + + do + { + nBytesRead = DosRead((COUNT) rc, (COUNT) (exe_size < CHUNK ? exe_size : CHUNK), (VOID FAR *) sp, &err); + sp = add_far((VOID FAR *) sp, (ULONG) nBytesRead); + exe_size -= nBytesRead; + } + while (nBytesRead && exe_size > 0); + } + + /* relocate the image for new segment */ + doslseek(rc, (LONG) header.exRelocTable, 0); + for (i = 0; i < header.exRelocItems; i++) + { + if (DosRead(rc, sizeof(reloc), (VOID FAR *) & reloc[0], &err) != sizeof(reloc)) + { + return DE_INVLDDATA; + } + if (mode == OVERLAY) + { + spot = MK_FP(reloc[1] + mem, reloc[0]); + *spot += exp->load.reloc; + } + else + { + /* spot = MK_FP(reloc[1] + mem + 0x10, reloc[0]); */ + spot = MK_FP(reloc[1] + start_seg, reloc[0]); + *spot += start_seg; + } + } + + /* and finally close the file */ + DosClose(rc); + + /* exit here for overlay */ + if (mode == OVERLAY) + return SUCCESS; + + /* point to the PSP so we can build it */ + p = MK_FP(mem, 0); + setvec(0x22, (VOID(INRPT FAR *) (VOID)) MK_FP(user_r->CS, user_r->IP)); + new_psp(p, mem + asize); + + patchPSP(mem - 1, env, exp->exec.cmd_line, namep); + + /* build the user area on the stack */ + irp = MK_FP(header.exInitSS + start_seg, + ((header.exInitSP - sizeof(iregs)) & 0xffff)); + + /* start allocating REGs */ + /* Note: must match es & ds memory segment */ + irp->ES = irp->DS = mem; + irp->CS = header.exInitCS + start_seg; + irp->IP = header.exInitIP; + irp->AX = 0xffff; /* for now, until fcb code is in */ + irp->BX = + irp->CX = + irp->DX = + irp->SI = + irp->DI = + irp->BP = 0; + irp->FLAGS = 0x200; + + /* Transfer control to the executable */ + p->ps_parent = cu_psp; + p->ps_prevpsp = (BYTE FAR *) MK_FP(cu_psp, 0); + q->ps_stack = (BYTE FAR *) user_r; + user_r->FLAGS &= ~FLG_CARRY; + + switch (mode) + { + case LOADNGO: + cu_psp = mem; + dta = p->ps_dta; + if (InDOS) + --InDOS; + exec_user(irp); + /* We should never be here */ + fatal("KERNEL RETURNED!!!"); + break; + + case LOAD: + cu_psp = mem; + exp->exec.stack = (BYTE FAR *) irp; + exp->exec.start_addr = MK_FP(irp->CS, irp->IP); + return SUCCESS; + } + return DE_INVLDFMT; +} + +/* mode = LOAD or EXECUTE + ep = EXE block + lp = filename to load (string) + + leb = local copy of exe block + */ +COUNT DosExec(COUNT mode, exec_blk FAR * ep, BYTE FAR * lp) +{ + COUNT rc, + err; + exec_blk leb = *ep; + BYTE FAR *cp; + BOOL bIsCom = FALSE; + + /* If file not found - free ram and return error */ + + if (cu_psp == DOS_PSP) + InitPSP(); + + if ((rc = DosOpen(lp, 0)) < 0) + { + return DE_FILENOTFND; + } + + if (DosRead(rc, sizeof(exe_header), (VOID FAR *) & header, &err) + != sizeof(exe_header)) + { + bIsCom = TRUE; + } + DosClose(rc); + + if (bIsCom || header.exSignature != MAGIC) + { + rc = DosComLoader(lp, &leb, mode); + } + else + { + rc = DosExeLoader(lp, &leb, mode); + } + if (mode == LOAD && rc == SUCCESS) + *ep = leb; + + return rc; +} + +COUNT FAR init_call_DosExec(COUNT mode, exec_blk FAR * ep, BYTE FAR * lp) +{ + return DosExec(mode, ep, lp); +} + +VOID InitPSP(VOID) +{ + psp FAR *p = MK_FP(DOS_PSP, 0); + new_psp(p, 0); +} + +/* process 0 */ +VOID FAR p_0(VOID) +{ + exec_blk exb; + CommandTail Cmd; + BYTE FAR *szfInitialPrgm = (BYTE FAR *) Config.cfgInit; + int rc; +/* init a fake psp file at seg 50:0000 */ + psp FAR *p = MK_FP(cu_psp, 0); + new_psp(p, 0); + + /* Execute command.com /P from the drive we just booted from */ + exb.exec.env_seg = master_env; + strcpy(Cmd.ctBuffer, Config.cfgInitTail); + + for (Cmd.ctCount = 0; Cmd.ctCount < 127; Cmd.ctCount++) + if (Cmd.ctBuffer[Cmd.ctCount] == '\r') + break; + + exb.exec.cmd_line = (CommandTail FAR *) & Cmd; + exb.exec.fcb_1 = exb.exec.fcb_2 = (fcb FAR *) 0; +#ifdef DEBUG + printf("Process 0 starting: %s\n\n", (BYTE *) szfInitialPrgm); +#endif + if ((rc = DosExec(0, (exec_blk FAR *) & exb, szfInitialPrgm)) != SUCCESS) + printf("\nBad or missing Command Interpreter: %d\n", rc); + else + printf("\nSystem shutdown complete\nReboot now.\n"); + for (;;) ; +} + diff --git a/lib/libm.mak b/lib/libm.mak new file mode 100644 index 0000000..b043ed7 --- /dev/null +++ b/lib/libm.mak @@ -0,0 +1,41 @@ +# +# makefile for libm.lib +# +# $Id$ +# + +# $Log$ +# Revision 1.1 2000/05/06 19:35:36 jhall1 +# Initial revision +# +# Revision 1.6 1999/09/14 17:32:20 jprice +# no message +# +# Revision 1.5 1999/09/13 20:13:15 jprice +# Added !if so we can use TC2 or TC3 to compile. +# +# Revision 1.4 1999/08/25 03:19:22 jprice +# ror4 patches to allow TC 2.01 compile. +# +# Revision 1.3 1999/04/23 03:45:18 jprice +# Improved by jprice +# + +!include "..\config.mak" + + +libm.lib: $(CLIB) +# use these for Turbo 2 + $(LIBUTIL) $(CLIB) *LDIV *LLSH *LURSH *LXMUL *LRSH *SPUSH *SCOPY + $(LIBUTIL) libm +LDIV +LLSH +LURSH +LXMUL +LRSH +SPUSH +SCOPY +# use these for Turbo 3 or better +# $(LIBUTIL) $(CLIB) *H_LDIV *H_LLSH *H_LURSH *N_LXMUL *F_LXMUL *H_LRSH *H_SPUSH *N_SCOPY +# $(LIBUTIL) libm +H_LDIV +H_LLSH +H_LURSH +N_LXMUL +F_LXMUL +H_LRSH +H_SPUSH +N_SCOPY + del *.OBJ + + +clobber: clean + $(RM) libm.lib status.me + +clean: + $(RM) *.obj *.bak diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..2be5beb --- /dev/null +++ b/readme.txt @@ -0,0 +1,36 @@ +INTRODUCTION +------------ +This archive contains FreeDOS Kernel version 1.1.18, build 2018, also +known as DOS-C, originally written by Pasquale J. Villani. + +The FreeDOS Kernel is available by anonymous ftp at +ftp://ftp.gcfl.net/freedos/kernel. It's also available from +http://www.dosemu.org (somewhere on there). + +The FreeDOS Kernel is also available through the FreeDOS project. An +ftp site is available for downloading Free-DOS at +ftp://metalab.unc.edu/pub/micro/pc-stuff/freedos. + +See the DOCS directory for more documentation and information about +the FreeDOS Kernel. + + +AGREEMENT +--------- +All users of the FreeDOS kernel must accept the disclaimer of +warranty and license terms contained in the file "COPYING" in order +to use it. You may not, under any circumstance, use this operating +system or any component without first reading and agreeing to the +terms of the license. + +BUG REPORTS +----------- +If you have found a bug, think you have found a bug, or would just +like to make a suggestion, go to the bug tracking web page at +http://www.gcfl.net/bugs/kernel or send email to +kernel-bugs@gcfl.net. + +Copyright +--------- +DOS-C is (c) Copyright 1995, 1996 by Pasquale J. Villani +All Rights Reserved. diff --git a/sys/bin2c.c b/sys/bin2c.c new file mode 100644 index 0000000..f53b3a7 --- /dev/null +++ b/sys/bin2c.c @@ -0,0 +1,51 @@ +#include + +int main(int argc, char **argv) +{ + FILE *in, *out; + int col; + int c; + + if (argc < 4) + { + fprintf(stderr, "Usage: bin2c \n"); + return 1; + } + + if ((in = fopen(argv[1], "rb")) == NULL) + { + fprintf(stderr, "Cannot open input file (%s).\n", argv[1]); + return 1; + } + + if ((out = fopen(argv[2], "wt")) == NULL) + { + fprintf(stderr, "Cannot open output file (%s).\n", argv[2]); + return 1; + } + + col = 0; + + fprintf(out, "unsigned char %s[] = {\n ", argv[3]); + + while ((c = fgetc(in)) != EOF) + { + if (col) + { + fprintf(out, ", "); + } + if (col >= 8) + { + fprintf(out, "\n "); + col = 0; + } + fprintf(out, "0x%02X", c); + col++; + } + + fprintf(out, "\n};\n"); + fclose(in); + fclose(out); + + return 0; +} diff --git a/sys/bin2c.mak b/sys/bin2c.mak new file mode 100644 index 0000000..aba8f41 --- /dev/null +++ b/sys/bin2c.mak @@ -0,0 +1,55 @@ +# +# makefile for bin2c.com +# +# $Id$ +# + +# $Log$ +# Revision 1.1 2000/05/06 19:35:36 jhall1 +# Initial revision +# +# Revision 1.6 1999/09/20 18:34:40 jprice +# *** empty log message *** +# +# Revision 1.5 1999/08/25 03:19:51 jprice +# ror4 patches to allow TC 2.01 compile. +# +# Revision 1.4 1999/05/03 05:01:38 jprice +# no message +# +# Revision 1.3 1999/04/23 03:45:33 jprice +# Improved by jprice +# + +!include "..\config.mak" + +CFLAGS = -mt -1- -v -vi- -k- -f- -ff- -O -Z -d -I$(INCLUDEPATH) -L$(LIBPATH) + +# *Implicit Rules* +.c.obj: + $(CC) $(CFLAGS) -c $< + +.cpp.obj: + $(CC) $(CFLAGS) -c $< + +# *List Macros* + +EXE_dependencies = \ + bin2c.obj + +# *Explicit Rules* +production: bin2c.com + +bin2c.com: $(EXE_dependencies) + $(LINK) /m/t/c $(LIBPATH)\c0t.obj+bin2c.obj,bin2c,,\ + $(LIBS)+$(CLIB); + + +clobber: clean + $(RM) bin2c.com + +clean: + ..\utils\rm -f *.obj *.bak *.crf *.xrf *.map *.lst *.las status.me + +# *Individual File Dependencies* +bin2c.obj: bin2c.c diff --git a/sys/sys.c b/sys/sys.c new file mode 100644 index 0000000..fa0900c --- /dev/null +++ b/sys/sys.c @@ -0,0 +1,666 @@ +/*************************************************************** + + sys.c + DOS-C + + sys utility for DOS-C + + Copyright (c) 1991 + Pasquale J. Villani + All Rights Reserved + + This file is part of DOS-C. + + DOS-C 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, or (at your option) any later version. + + DOS-C 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 + DOS-C; see the file COPYING. If not, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. + +***************************************************************/ + +/* $Log$ + * Revision 1.1 2000/05/06 19:35:37 jhall1 + * Initial revision + * +/* Revision 1.9 1999/09/20 18:34:40 jprice +/* *** empty log message *** +/* +/* Revision 1.8 1999/09/20 18:27:19 jprice +/* Changed open/creat to fopen to make TC2 happy. +/* +/* Revision 1.7 1999/09/15 05:39:02 jprice +/* Changed boot sector writing code so easier to read. +/* +/* Revision 1.6 1999/09/14 17:30:44 jprice +/* Added debug log creation to sys.com. +/* +/* Revision 1.5 1999/08/25 03:19:51 jprice +/* ror4 patches to allow TC 2.01 compile. +/* +/* Revision 1.4 1999/04/17 19:14:44 jprice +/* Fixed multi-sector code +/* +/* Revision 1.3 1999/04/01 07:24:05 jprice +/* SYS modified for new boot loader +/* +/* Revision 1.2 1999/03/29 16:24:48 jprice +/* Fixed error message +/* +/* Revision 1.1.1.1 1999/03/29 15:43:15 jprice +/* New version without IPL.SYS +/* Revision 1.3 1999/01/21 04:35:21 jprice Fixed comments. + Added indent program + +Revision 1.2 1999/01/21 04:13:52 jprice Added messages to sys. Also made + it create a .COM file. + +*/ + +#define STORE_BOOT_INFO + +#include +#include +#include +/*#include */ +#include +#include +#include +#include +#include "portab.h" +#include "device.h" + +#include "b_fat12.h" +#include "b_fat16.h" + +BYTE *pgm = "sys"; + +BOOL fl_reset(WORD); +COUNT fl_rd_status(WORD); +COUNT fl_read(WORD, WORD, WORD, WORD, WORD, BYTE FAR *); +COUNT fl_write(WORD, WORD, WORD, WORD, WORD, BYTE FAR *); +BOOL fl_verify(WORD, WORD, WORD, WORD, WORD, BYTE FAR *); +BOOL fl_format(WORD, BYTE FAR *); +VOID get_boot(COUNT); +VOID put_boot(COUNT); +BOOL check_space(COUNT, BYTE *); +COUNT ltop(WORD *, WORD *, WORD *, COUNT, COUNT, LONG, byteptr); +BOOL copy(COUNT, BYTE *); +BOOL DiskReset(COUNT); +COUNT DiskRead(WORD, WORD, WORD, WORD, WORD, BYTE FAR *); +COUNT DiskWrite(WORD, WORD, WORD, WORD, WORD, BYTE FAR *); + +/* special word packing prototypes */ + +#ifdef NATIVE +#define getlong(vp, lp) (*(LONG *)(lp)=*(LONG *)(vp)) +#define getword(vp, wp) (*(WORD *)(wp)=*(WORD *)(vp)) +#define getbyte(vp, bp) (*(BYTE *)(bp)=*(BYTE *)(vp)) +#define fgetlong(vp, lp) (*(LONG FAR *)(lp)=*(LONG FAR *)(vp)) +#define fgetword(vp, wp) (*(WORD FAR *)(wp)=*(WORD FAR *)(vp)) +#define fgetbyte(vp, bp) (*(BYTE FAR *)(bp)=*(BYTE FAR *)(vp)) +#define fputlong(lp, vp) (*(LONG FAR *)(vp)=*(LONG FAR *)(lp)) +#define fputword(wp, vp) (*(WORD FAR *)(vp)=*(WORD FAR *)(wp)) +#define fputbyte(bp, vp) (*(BYTE FAR *)(vp)=*(BYTE FAR *)(bp)) +#else +VOID getword(VOID *, WORD *); +VOID getbyte(VOID *, BYTE *); +VOID fgetlong(VOID FAR *, LONG FAR *); +VOID fgetword(VOID FAR *, WORD FAR *); +VOID fgetbyte(VOID FAR *, BYTE FAR *); +VOID fputlong(LONG FAR *, VOID FAR *); +VOID fputword(WORD FAR *, VOID FAR *); +VOID fputbyte(BYTE FAR *, VOID FAR *); +#endif + +#define SEC_SIZE 512 +#define NDEV 4 +#define COPY_SIZE 32768 +#define NRETRY 5 + +static struct media_info +{ + ULONG mi_size; /* physical sector size */ + UWORD mi_heads; /* number of heads (sides) */ + UWORD mi_cyls; /* number of cyl/drive */ + UWORD mi_sectors; /* number of sectors/cyl */ + ULONG mi_offset; /* relative partition offset */ +}; + +union +{ + BYTE bytes[2 * SEC_SIZE]; + boot boot_sector; +} + + buffer; + +static struct media_info miarray[NDEV] = +{ + {720l, 2, 40, 9, 0l}, + {720l, 2, 40, 9, 0l}, + {720l, 2, 40, 9, 0l}, + {720l, 2, 40, 9, 0l} +}; + +#define PARTOFF 0x1be +#define N_PART 4 + +static struct +{ + BYTE peBootable; + BYTE peBeginHead; + BYTE peBeginSector; + UWORD peBeginCylinder; + BYTE peFileSystem; + BYTE peEndHead; + BYTE peEndSector; + UWORD peEndCylinder; + LONG peStartSector; + LONG peSectors; +} partition[N_PART]; + +struct bootsectortype +{ + UBYTE bsJump[3]; + char OemName[8]; + UWORD bsBytesPerSec; + UBYTE bsSecPerClust; + UWORD bsResSectors; + UBYTE bsFATs; + UWORD bsRootDirEnts; + UWORD bsSectors; + UBYTE bsMedia; + UWORD bsFATsecs; + UWORD bsSecPerTrack; + UWORD bsHeads; + ULONG bsHiddenSecs; + ULONG bsHugeSectors; + UBYTE bsDriveNumber; + UBYTE bsReserved1; + UBYTE bsBootSignature; + ULONG bsVolumeID; + char bsVolumeLabel[11]; + char bsFileSysType[8]; + char unused[2]; + UWORD sysRootDirSecs; /* of sectors root dir uses */ + ULONG sysFatStart; /* first FAT sector */ + ULONG sysRootDirStart; /* first root directory sector */ + ULONG sysDataStart; /* first data sector */ +}; + + +static int DrvMap[4] = +{0, 1, 0x80, 0x81}; + +COUNT drive, active; +UBYTE newboot[SEC_SIZE], oldboot[SEC_SIZE]; + +#ifdef DEBUG +FILE *log; +#endif + +#define SBSIZE 51 +#define SBOFFSET 11 + +#define SIZEOF_PARTENT 16 + +#define FAT12 0x01 +#define FAT16SMALL 0x04 +#define EXTENDED 0x05 +#define FAT16LARGE 0x06 + +#define N_RETRY 5 + +COUNT get_part(COUNT drive, COUNT idx) +{ + REG retry = N_RETRY; + REG BYTE *p = (BYTE *) & buffer.bytes[PARTOFF + (idx * SIZEOF_PARTENT)]; + REG ret; + BYTE packed_byte, pb1; + + do + { + ret = fl_read((WORD) DrvMap[drive], (WORD) 0, (WORD) 0, (WORD) 1, (WORD) 1, (byteptr) & buffer); + } + while (ret != 0 && --retry > 0); + if (ret != 0) + return FALSE; + getbyte((VOID *) p, &partition[idx].peBootable); + ++p; + getbyte((VOID *) p, &partition[idx].peBeginHead); + ++p; + getbyte((VOID *) p, &packed_byte); + partition[idx].peBeginSector = packed_byte & 0x3f; + ++p; + getbyte((VOID *) p, &pb1); + ++p; + partition[idx].peBeginCylinder = pb1 + ((0xc0 & packed_byte) << 2); + getbyte((VOID *) p, &partition[idx].peFileSystem); + ++p; + getbyte((VOID *) p, &partition[idx].peEndHead); + ++p; + getbyte((VOID *) p, &packed_byte); + partition[idx].peEndSector = packed_byte & 0x3f; + ++p; + getbyte((VOID *) p, &pb1); + ++p; + partition[idx].peEndCylinder = pb1 + ((0xc0 & packed_byte) << 2); + getlong((VOID *) p, &partition[idx].peStartSector); + p += sizeof(LONG); + getlong((VOID *) p, &partition[idx].peSectors); + return TRUE; +} + +VOID main(COUNT argc, char **argv) +{ + if (argc != 2) + { + fprintf(stderr, "Usage: %s drive\n drive = A,B,etc.\n", pgm); + exit(1); + } + + drive = *argv[1] - (islower(*argv[1]) ? 'a' : 'A'); + if (drive < 0 || drive >= NDEV) + { + fprintf(stderr, "%s: drive out of range\n", pgm); + exit(1); + } + + if (!DiskReset(drive)) + { + fprintf(stderr, "%s: cannot reset drive %c:", + drive, 'A' + drive); + exit(1); + } + + get_boot(drive); + + if (!check_space(drive, oldboot)) + { + fprintf(stderr, "%s: Not enough space to transfer system files\n", pgm); + exit(1); + } + +#ifdef DEBUG + if ((log = fopen("sys.log", "w")) == NULL) + { + printf("Can't write log file.\n"); + log = NULL; + } +#endif + + printf("Writing boot sector...\n"); + put_boot(drive); + + printf("\nCopying KERNEL.SYS..."); + if (!copy(drive, "kernel.sys")) + { + fprintf(stderr, "\n%s: cannot copy \"KERNEL.SYS\"\n", pgm); +#ifdef DEBUG + fclose(log); +#endif + exit(1); + } + + printf("\nCopying COMMAND.COM..."); + if (!copy(drive, "command.com")) + { + fprintf(stderr, "\n%s: cannot copy \"COMMAND.COM\"\n", pgm); +#ifdef DEBUG + fclose(log); +#endif + exit(1); + } + printf("\nSystem transfered.\n"); +#ifdef DEBUG + fclose(log); +#endif + exit(0); +} + +#ifdef DEBUG +VOID dump_sector(unsigned char far * sec) +{ + if (log) + { + COUNT x, y; + char c; + + for (x = 0; x < 32; x++) + { + fprintf(log, "%03X ", x * 16); + for (y = 0; y < 16; y++) + { + fprintf(log, "%02X ", sec[x * 16 + y]); + } + for (y = 0; y < 16; y++) + { + c = oldboot[x * 16 + y]; + if (isprint(c)) + fprintf(log, "%c", c); + else + fprintf(log, "."); + } + fprintf(log, "\n"); + } + fprintf(log, "\n"); + } +} + +#endif + + +VOID put_boot(COUNT drive) +{ + COUNT i, z; + WORD head, track, sector, ret; + WORD count; + ULONG temp; + struct bootsectortype *bs; + + if (drive >= 2) + { + head = partition[active].peBeginHead; + sector = partition[active].peBeginSector; + track = partition[active].peBeginCylinder; + } + else + { + head = 0; + sector = 1; + track = 0; + } + + /* Read current boot sector */ + if ((i = DiskRead(DrvMap[drive], head, track, sector, 1, (BYTE far *) oldboot)) != 0) + { + fprintf(stderr, "%s: disk read error (code = 0x%02x)\n", pgm, i & 0xff); + exit(1); + } + +#ifdef DEBUG + fprintf(log, "Old Boot Sector:\n"); + dump_sector(oldboot); +#endif + + bs = (struct bootsectortype *) & oldboot; + if ((bs->bsFileSysType[4] == '6') && (bs->bsBootSignature == 0x29)) + { + memcpy(newboot, b_fat16, SEC_SIZE); /* copy FAT16 boot sector */ + printf("FAT type: FAT16\n"); +#ifdef DEBUG + fprintf(log, "FAT type: FAT16\n"); +#endif + } + else + { + memcpy(newboot, b_fat12, SEC_SIZE); /* copy FAT12 boot sector */ + printf("FAT type: FAT12\n"); +#ifdef DEBUG + fprintf(log, "FAT type: FAT12\n"); +#endif + } + + /* Copy disk parameter from old sector to new sector */ + memcpy(&newboot[SBOFFSET], &oldboot[SBOFFSET], SBSIZE); + + bs = (struct bootsectortype *) & newboot; + /* root directory sectors */ +#ifdef STORE_BOOT_INFO + bs->sysRootDirSecs = bs->bsRootDirEnts / 16; +#endif +#ifdef DEBUG + fprintf(log, "root dir entries = %u\n", bs->bsRootDirEnts); + fprintf(log, "root dir sectors = %u\n", bs->sysRootDirSecs); +#endif + + /* sector FAT starts on */ + temp = bs->bsHiddenSecs + bs->bsResSectors; +#ifdef STORE_BOOT_INFO + bs->sysFatStart = temp; +#endif +#ifdef DEBUG + fprintf(log, "FAT starts at sector %lu = (%lu + %u)\n", temp, + bs->bsHiddenSecs, bs->bsResSectors); +#endif + + /* sector root directory starts on */ + temp = temp + bs->bsFATsecs * bs->bsFATs; +#ifdef STORE_BOOT_INFO + bs->sysRootDirStart = temp; +#endif +#ifdef DEBUG + fprintf(log, "Root directory starts at sector %lu = (PREVIOUS + %u * %u)\n", + temp, bs->bsFATsecs, bs->bsFATs); +#endif + + /* sector data starts on */ + temp = temp + bs->sysRootDirSecs; +#ifdef STORE_BOOT_INFO + bs->sysDataStart = temp; +#endif +#ifdef DEBUG + fprintf(log, "DATA starts at sector %lu = (PREVIOUS + %u)\n", temp, + bs->sysRootDirSecs); +#endif + + +#ifdef DEBUG + fprintf(log, "\nNew Boot Sector:\n"); + dump_sector(newboot); +#endif + + if ((i = DiskWrite(DrvMap[drive], head, track, sector, 1, (BYTE far *) newboot)) != 0) + { + fprintf(stderr, "%s: disk write error (code = 0x%02x)\n", pgm, i & 0xff); + exit(1); + } +} + +VOID get_boot(COUNT drive) +{ + COUNT i; + COUNT ifd; + WORD head, track, sector, ret; + WORD count; + + if (drive >= 2) + { + head = partition[active].peBeginHead; + sector = partition[active].peBeginSector; + track = partition[active].peBeginCylinder; + } + else + { + head = 0; + sector = 1; + track = 0; + } + + if ((i = DiskRead(DrvMap[drive], head, track, sector, 1, (BYTE far *) oldboot)) != 0) + { + fprintf(stderr, "%s: disk read error (code = 0x%02x)\n", pgm, i & 0xff); + exit(1); + } +} + +BOOL check_space(COUNT drive, BYTE * BlkBuffer) +{ + BYTE *bpbp; + BYTE nfat; + UWORD nfsect; + ULONG hidden; + ULONG count; + ULONG block; + UBYTE nreserved; + UCOUNT i; + WORD track, head, sector; + UBYTE buffer[SEC_SIZE]; + ULONG bpb_huge; + UWORD bpb_nsize; + + /* get local information */ + getbyte((VOID *) & BlkBuffer[BT_BPB + BPB_NFAT], &nfat); + getword((VOID *) & BlkBuffer[BT_BPB + BPB_NFSECT], &nfsect); + getlong((VOID *) & BlkBuffer[BT_BPB + BPB_HIDDEN], &hidden); + getbyte((VOID *) & BlkBuffer[BT_BPB + BPB_NRESERVED], &nreserved); + + getlong((VOID *) & BlkBuffer[BT_BPB + BPB_HUGE], &bpb_huge); + getword((VOID *) & BlkBuffer[BT_BPB + BPB_NSIZE], &bpb_nsize); + + count = miarray[drive].mi_size = bpb_nsize == 0 ? + bpb_huge : bpb_nsize; + + /* Fix media information for disk */ + getword((&(((BYTE *) & BlkBuffer[BT_BPB])[BPB_NHEADS])), &miarray[drive].mi_heads); + head = miarray[drive].mi_heads; + getword((&(((BYTE *) & BlkBuffer[BT_BPB])[BPB_NSECS])), &miarray[drive].mi_sectors); + if (miarray[drive].mi_size == 0) + getlong(&((((BYTE *) & BlkBuffer[BT_BPB])[BPB_HUGE])), &miarray[drive].mi_size); + sector = miarray[drive].mi_sectors; + if (head == 0 || sector == 0) + { + fprintf(stderr, "Drive initialization failure.\n"); + exit(1); + } + miarray[drive].mi_cyls = count / (head * sector); + + return 1; +} + +/* */ +/* Do logical block number to physical head/track/sector mapping */ +/* */ +static COUNT ltop(trackp, sectorp, headp, unit, count, strt_sect, strt_addr) +WORD *trackp, *sectorp, *headp; +REG COUNT unit; +LONG strt_sect; +COUNT count; +byteptr strt_addr; +{ +#ifdef I86 + ULONG ltemp; +#endif + REG ls, ps; + +#ifdef I86 + /* Adjust for segmented architecture */ + ltemp = (((ULONG) mk_segment(strt_addr) << 4) + mk_offset(strt_addr)) & 0xffff; + /* Test for 64K boundary crossing and return count large */ + /* enough not to exceed the threshold. */ + count = (((ltemp + SEC_SIZE * count) & 0xffff0000l) != 0l) + ? (0xffffl - ltemp) / SEC_SIZE + : count; +#endif + + *trackp = strt_sect / (miarray[unit].mi_heads * miarray[unit].mi_sectors); + *sectorp = strt_sect % miarray[unit].mi_sectors + 1; + *headp = (strt_sect % (miarray[unit].mi_sectors * miarray[unit].mi_heads)) + / miarray[unit].mi_sectors; + if (((ls = *headp * miarray[unit].mi_sectors + *sectorp - 1) + count) > + (ps = miarray[unit].mi_heads * miarray[unit].mi_sectors)) + count = ps - ls; + return count; +} + +BOOL copy(COUNT drive, BYTE * file) +{ + BYTE dest[64]; + COUNT ifd, ofd, ret; + FILE *s, *d; + BYTE buffer[COPY_SIZE]; + struct ftime ftime; + + sprintf(dest, "%c:\\%s", 'A' + drive, file); + if ((s = fopen(file, "rb")) == NULL) + { + fprintf(stderr, "%s: \"%s\" not found\n", pgm, file); + return FALSE; + } + _fmode = O_BINARY; + if ((d = fopen(dest, "wb")) == NULL) + { + fclose(s); + fprintf(stderr, "%s: can't create\"%s\"\n", pgm, dest); + return FALSE; + } + + while ((ret = fread(buffer, 1, COPY_SIZE, s)) != 0) + fwrite(buffer, 1, ret, d); + + getftime(fileno(s), &ftime); + setftime(fileno(d), &ftime); + + fclose(s); + fclose(d); + + return TRUE; +} + +BOOL DiskReset(COUNT Drive) +{ + REG COUNT idx; + + /* Reset the drives */ + fl_reset(DrvMap[drive]); + + if (Drive >= 2 && Drive < NDEV) + { + COUNT RetCode; + + /* Retrieve all the partition information */ + for (RetCode = TRUE, idx = 0; RetCode && (idx < N_PART); idx++) + RetCode = get_part(Drive, idx); + if (!RetCode) + return FALSE; + + /* Search for the first DOS partition and start */ + /* building the map for the hard drive */ + for (idx = 0; idx < N_PART; idx++) + { + if (partition[idx].peFileSystem == FAT12 + || partition[idx].peFileSystem == FAT16SMALL + || partition[idx].peFileSystem == FAT16LARGE) + { + miarray[Drive].mi_offset + = partition[idx].peStartSector; + active = idx; + break; + } + } + } + + return TRUE; +} + +COUNT DiskRead(WORD drive, WORD head, WORD track, WORD sector, WORD count, BYTE FAR * buffer) +{ + int nRetriesLeft; + + for (nRetriesLeft = NRETRY; nRetriesLeft > 0; --nRetriesLeft) + { + if (fl_read(drive, head, track, sector, count, buffer) == count) + return count; + } + return 0; +} + +COUNT DiskWrite(WORD drive, WORD head, WORD track, WORD sector, WORD count, BYTE FAR * buffer) +{ + int nRetriesLeft; + + for (nRetriesLeft = NRETRY; nRetriesLeft > 0; --nRetriesLeft) + { + if (fl_write(drive, head, track, sector, count, buffer) == count) + return count; + } + return 0; +} diff --git a/sys/sys.mak b/sys/sys.mak new file mode 100644 index 0000000..1ebe575 --- /dev/null +++ b/sys/sys.mak @@ -0,0 +1,73 @@ +# +# makefile for sys.com +# +# $Id$ +# + +# $Log$ +# Revision 1.1 2000/05/06 19:35:37 jhall1 +# Initial revision +# +# Revision 1.10 1999/09/23 04:41:43 jprice +# *** empty log message *** +# +# Revision 1.9 1999/09/14 17:30:44 jprice +# Added debug log creation to sys.com. +# +# Revision 1.8 1999/08/25 03:19:51 jprice +# ror4 patches to allow TC 2.01 compile. +# +# Revision 1.7 1999/05/03 05:01:54 jprice +# no message +# +# Revision 1.6 1999/04/23 03:45:33 jprice +# Improved by jprice +# + + +!include "..\config.mak" + +#CFLAGS = -mt -1- -v -vi- -k- -f- -ff- -O -Z -d -I$(INCLUDEPATH);..\hdr \ +# -L$(LIBPATH) -DI86;PROTO;DEBUG +CFLAGS = -mt -1- -v -vi- -k- -f- -ff- -O -Z -d -I$(INCLUDEPATH);..\hdr \ + -L$(LIBPATH) -DI86;PROTO + +# *Implicit Rules* +.c.obj: + $(CC) $(CFLAGS) -c $< + +.cpp.obj: + $(CC) $(CFLAGS) -c $< + +# *List Macros* + +LIBS = ..\lib\device.lib + +EXE_dependencies = \ + sys.obj \ + $(LIBS) + +# *Explicit Rules* +production: ..\bin\sys.com + +..\bin\sys.com: sys.com + copy sys.com ..\bin + +b_fat12.h: ..\boot\b_fat12.bin bin2c.com + bin2c ..\boot\b_fat12.bin b_fat12.h b_fat12 + +b_fat16.h: ..\boot\b_fat16.bin bin2c.com + bin2c ..\boot\b_fat16.bin b_fat16.h b_fat16 + +sys.com: $(EXE_dependencies) + $(LINK) /m/t/c $(LIBPATH)\c0t.obj+sys.obj,sys,,\ + $(LIBS)+$(CLIB); + +clobber: clean + $(RM) sys.com b_fat12.h b_fat16.h + +clean: + $(RM) *.obj *.bak *.crf *.xrf *.map *.lst *.las status.me + +# *Individual File Dependencies* +sys.obj: sys.c ..\hdr\portab.h ..\hdr\device.h b_fat12.h b_fat16.h diff --git a/utils/indent.ini b/utils/indent.ini new file mode 100644 index 0000000..3f253c2 --- /dev/null +++ b/utils/indent.ini @@ -0,0 +1,17 @@ +-kr +-di2 +-nbc +-nfca +-bl +-bli0 +-ss +-npcs +-ncs +-nbs +-i2 +-ci4 +-nce +-sob +-ts80 +-nbad +-cli2 diff --git a/utils/proto.bat b/utils/proto.bat new file mode 100644 index 0000000..472b76f --- /dev/null +++ b/utils/proto.bat @@ -0,0 +1,2 @@ +for %%f in ( %1 %2 %3 %4 %5 %6 %7 %8 %9 ) do mkptypes %%f >>proto.h +