commit 7ea26e619b41ea0843b4d85f5061bac2f8ee6a14 Author: Mario Fetka Date: Sat Apr 22 14:09:10 2017 +0200 Imported Upstream version 0.4.1 diff --git a/AUTHOR b/AUTHOR new file mode 100644 index 0000000..3bc8b87 --- /dev/null +++ b/AUTHOR @@ -0,0 +1,3 @@ + +Other than the included megaraid2 driver code from LSI (GPLv2), and the SCSI header files from Joerg Schilling (GPLv2), this software was written entirely by Jefferson Ogata . + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..76b9a6d --- /dev/null +++ b/COPYING @@ -0,0 +1,348 @@ + +Note: This program includes megaraid2 driver source code, which was copied from +the kernel source of a Red Hat system, and header files from Joerg Schilling's +cdrecord, also as distributed on Red Hat, and also under GPL. + + +---------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 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/README b/README new file mode 100644 index 0000000..a76e0df --- /dev/null +++ b/README @@ -0,0 +1,205 @@ +LSI Megaraid Control and Monitoring Tools by Jefferson Ogata +------------------------------------------------------------ + + +Disclaimer +---------- + +WARNING: Use this software at your own risk. The author accepts no +responsibility for the consequences of your use of this software. + +WARNING: Use this software at your own risk. The author accepts no +responsibility for the consequences of your use of this software. + +WARNING: Use this software at your own risk. The author accepts no +responsibility for the consequences of your use of this software. + +These programs directly query megaraid adapters via the ioctl(2) driver +interface and do a number of undocumented things. I and my colleagues use this +software regularly and have had no problems, but your mileage may vary. If +something goes terribly wrong and your RAID configs all get blown away, the +author accepts no responsibility for the consequences. + +Please read this document carefully as it contains a warning or two. If you +have built the programs but are having any issues running them, please see the +Building, Device Nodes, and Limitations notes further down in this document. + + +Introduction +------------ + +I've spent a fair amount of time working out the low-level interface to +megaraid adapters. This stems from the fact that I use a lot of these beasts +and have had failures at one time or another. The adapters are fast and +extremely useful, but they aren't bulletproof. For example, disks showing a +certain number of media errors are not failed immediately by the adapters; the +adapters seem to want to pass some threshold of failure before they decide that +a disk really needs to be dropped from a RAID, and by that time it's possible +there could be consistency problems. I wrote these tools so I could more +effectively monitor media errors (dellmgr makes this very tedious) and also +take advantage of the device self-test functions provided with drives. +Self-tests are in my opinion a suitable way to detect imminent drive failures +without tying up the adapter and SCSI bandwidth doing patrol reads. It is also +very useful to be able to conduct a self-test on a spare disk before using it +for a rebuild. + +Another issue I've had with megaraids is keeping current documentation on RAID +configuration. You may choose a completely logical RAID layout when first +configuration a system, but that doesn't mean you'll remember it if you have to +reconstruct it in an emergency--did I leave out a disk for a hot spare? Which +one? Furthermore, as disks fail and hot spares are rotated in place, the +configuration changes over time. If you don't update your documentation every +time a disk fails, you lose track of it. While LSI's MegaCli program provides +methods for dumping the configuration (although verbosely) and saving and +restoring it from files, Dell's dellmgr doesn't give you any sensible way to +track down what spans comprise a logical disk. I wrote these programs in part +to solve this problem. + + +Programs +-------- + +This distribution contains three programs and a script: + + +*megactl* + +megactl queries PERC2, PERC3, and PERC4 adapters and reports adapter +configuration, physical and logical drive condition, drive log sense pages, and +various other useful information. This allows you to document the actual +configuration of the adapter, since, for one thing, Dell's dellmgr does not +tell you which specific logical drive a given disk belongs to. + +megactl has several features to query SCSI drive log pages, where each drive +controller saves accumulated error counts, drive temperature, self-test +results, et al. To get a list of supported log pages for a given drive, use +"megactl -vv -l 0 " where target is the name of the drive, e.g. a0c1t2 +for SCSI target 2 on channel 1 of adapter 0. In addition "-s" is shorthand for +"-l 0x10", "-t" is shorthand for "-l 0x0d", and "-e" is shorthand for "-l 0x02 +-l 0x03 -l 0x05". megactl knows how to parse several useful log pages, but +there are others where you'll have to interpret the results yourself. Feel free +to write more parsing code. + +megactl output is governed by a verbosity flag. At lower verbosity levels, the +program tends to minimize log page output unless it represents an actual +problem. So to see the full self-test log, you need to add "-vv". I usually run +the program with a single "-v". + +Self-test and most status operations allow you to designate either an entire +adapter (a0), a specific channel (a0c1), or a specific drive (a0c1t2). When +performing drive self-test operations (q.v.), be sure to specify the actual +drive you wish to test, or you will end up starting a test on every drive on +the system. You may designate as many objects as you please, e.g. +"a0c0t{1,2,3,4,5,8} a0c1 a1". + +megactl provides a health-check function, which inspects health check operation +allows only entire adapters to be designated. If no target is designated, the +program operates on all possible objects. + +megactl with the -H option performs a health check of all (or specified) +adapters. By default, the health check checks the state of the adapter battery, +the state of all logical drives, and for each physical drive, the media error +count logged by the adapter, the read, write,and verify error log pages, and +the temperature log page. You can tune the log pages the health check will +inspect by specifying them with "-e", "-s", "-t", or "-l"; note that if you do +this, there is no default and you must specify every log page you wish to +inspect ("-et" for the default behaviour). If a problem is found, the program +prints the adapter and relevant drive info. If everything is okay, the program +is completely silent. So "megactl -vH" can be a useful cron job. + +When using the health check you may specify which adapters you want to check, +but you may not designate specific channels or drives. + +megactl also allows you to instruct the drive to perform a long ("-T long") or +short ("-T short") background self-test procedure, which does not take the +drive offline. I have performed self-tests on drives that are part of an +operational RAID many times with no problems. I recommend that you self-test +only one drive in a given span at a time; if the self-test causes the drive to +log errors, the adapter may fail the drive, and you don't want that to happen +to two drives in a span simultaneously or you may lose data. + +You can get full usage info for megactl by executing it with the -? flag. + +I use megactl on a number of PERC models, especially PERC3/QCs and PERC4/DCs. +In the past, megactl was known to work well with PERC2/DC adapters but I no +longer operate any systems with these adapters, so this may have broken. Please +let me know if you have success or problems. + +megactl generally tries not to do anything harmful, so it's pretty safe. +Primarily it queries disks; the only instructions it issues in its current form +are to execute self-test operations. + + +*megasasctl* + +The second program, megasasctl, is just like megactl, but intended for PERC5 +adapters. The only syntactic difference is that instead of naming targets with +channels and ids, they are named with enclosures and slots, e.g. a0, a1e0, +a2e1s9. + +The SAS support is brand new, and I'm sure I've got some things wrong. I +haven't been able to fully test SAS support yet because I don't have any bad +SAS disks. + + +*megatrace* + +megatrace is a debugging program which can be used to trace PERC-related +ioctl() system calls that another program makes. You won't need that unless +you're trying to add features to megactl, or are exceptionally curious. This +program uses ptrace(2) and can inspect and modify data structures to help you +suss out what's going on in dellmgr and MegaCli. + + +*megarpt* + +megarpt is a script I run in a cron job each night. It performs a health check +on all adapters, and emails any problems, along with the adapter configuration, +to root. It is handy to have the adapter configuration logged in case you need +to reconstruct adapter state in a catastrophic failure. There are various +scenarios involving hot spares and multiple drive failures where the adapter +configuration may not be quite what you thought it was. To use megarpt, copy +megarpt and megactl into /root/ and add a cron entry for /root/megarpt. Or +tweak as you see fit; there isn't much to it. + +megarpt needs to be tweaked for megasasctl applications; it currently works +only with pre-SAS models. + + +*megasasrpt* + +megasasrpt is just like megarpt, but for PERC5 adapters. + + +Building +-------- + +This software has been built successfully on RHEL 3, 4, and 5, and Debian Etch, +using the default gcc compiler, and Red Hat Linux 7.3 or RHEL 2.1 should work +as well. Simply run make in the src directory. + + +Device Nodes +------------ + +megactl and megasasctl require the existence of an appropriate device node in +order to communicate with adapters. For megactl, this device node should be +/dev/megadev0, and is created automatically by Dell's dellmgr program. You may +create it yourself by finding the major device number for megadev in +/proc/devices and creating a character device with that major number and minor +number 0. See the megarpt shell script if this is not clear. For megasasctl, +the device node is /dev/megaraid_sas_ioctl_node, and is created automatically +by LSI's MegaCli program. It should have the major number of megaraid_sas_ioctl +from /proc/devices and minor number 0. See the megasasrpt shell script for an +example of how to create this. + + +Limitations +----------- + +Currently these programs only operate if built as 32-bit targets. On 64-bit +architectures, you therefore will need 32-bit compatibility libraries. This +should not require any special action on Red Hat, but on Debian you may need to +install a few things. + + diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..6bd185c --- /dev/null +++ b/src/Makefile @@ -0,0 +1,42 @@ + +SRCS= megactl.c adapter.c megaioctl.c megatrace.c callinfo.c dumpbytes.c logpage.c ntrim.c +INC= -I./schily -Iincludes-hack +HDRS= mega.h adapter.h megaioctl.h callinfo.h logpage.h dumpbytes.h +ARCH= -m32 +CFLAGS= -g -Wall $(INC) $(ARCH) +LDFLAGS= -g $(ARCH) +PROGRAMS= megactl megasasctl megatrace + +all: $(PROGRAMS) + +megatrace: megatrace.o callinfo.o dumpbytes.o + $(CC) $(LDFLAGS) -o $@ megatrace.o callinfo.o dumpbytes.o + +megactl: megactl.o adapter.o dumpbytes.o megaioctl.o logpage.o ntrim.o + $(CC) $(LDFLAGS) -o $@ megactl.o adapter.o dumpbytes.o megaioctl.o logpage.o ntrim.o + +megasasctl: megasasctl.o adapter.o dumpbytes.o megaioctl.o logpage.o ntrim.o + $(CC) $(LDFLAGS) -o $@ megasasctl.o adapter.o dumpbytes.o megaioctl.o logpage.o ntrim.o + +megasasctl.o: megactl.c + $(CC) $(CFLAGS) -c -o $@ -DMEGA_SAS_CTL megactl.c + +%.o: Makefile.bak %.c + $(CC) $(CFLAGS) -c -o $@ $*.c + +clean: + $(RM) $(PROGRAMS) *.o + +depend: + makedepend -- $(CFLAGS) -- $(SRCS) + +megactl.o: mega.h adapter.h megaioctl.h logpage.h dumpbytes.h +megasasctl.o: mega.h adapter.h megaioctl.h logpage.h dumpbytes.h +adapter.o: mega.h megaioctl.h logpage.h ntrim.h +megaioctl.o: mega.h megaioctl.h logpage.h +megatrace.o: mega.h megaioctl.h logpage.h callinfo.h dumpbytes.h +callinfo.o: callinfo.h +logpage.o: mega.h megaioctl.h logpage.h ntrim.h dumpbytes.h +ntrim.o: ntrim.h + +# DO NOT DELETE diff --git a/src/adapter.c b/src/adapter.c new file mode 100644 index 0000000..bd1b0cb --- /dev/null +++ b/src/adapter.c @@ -0,0 +1,845 @@ +/* + * High-level interface to adapter information. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "megaioctl.h" +#include "logpage.h" +#include "ntrim.h" + +#include +#include +#include +#include + +#include + + +static void batteryStatus (struct adapter_config *a, uint8_t status) +{ + a->battery.module_missing = (status & BATTERY_MODULE_MISSING) != 0; + a->battery.pack_missing = (status & BATTERY_PACK_MISSING) != 0; + a->battery.low_voltage = (status & BATTERY_LOW_VOLTAGE) != 0; + a->battery.high_temperature = (status & BATTERY_TEMP_HIGH) != 0; + a->battery.cycles_exceeded = (status & BATTERY_CYCLES_EXCEEDED) != 0; + switch (status & BATTERY_CHARGE_MASK) + { + case BATTERY_CHARGE_FAIL: a->battery.charger_state = ChargerStateFailed; break; + case BATTERY_CHARGE_DONE: a->battery.charger_state = ChargerStateComplete; break; + case BATTERY_CHARGE_INPROG: a->battery.charger_state = ChargerStateInProgress; break; + default: a->battery.charger_state = ChargerStateUnknown; break; + } + a->battery.voltage = -1; + a->battery.temperature = -1; + a->battery.healthy = !(a->battery.module_missing || a->battery.pack_missing || a->battery.low_voltage || a->battery.high_temperature || a->battery.cycles_exceeded || (a->battery.charger_state != ChargerStateComplete)); +} + +static void batteryStatus5 (struct adapter_config *a) +{ + struct mega_battery_state_sas *b = &a->q.v5.battery.state; + + a->battery.module_missing = !(a->q.v5.adapinfo.hw_present.bbu); + a->battery.pack_missing = b->type == MEGA_BATTERY_TYPE_NONE; + a->battery.low_voltage = b->remaining_capacity_alarm || b->remaining_time_alarm || b->fully_discharged; + a->battery.high_temperature = b->over_temperature != 0; + a->battery.over_charged = b->over_charged != 0; + switch (b->charger_status) + { + case 0: a->battery.charger_state = ChargerStateFailed; break; + case 1: a->battery.charger_state = ChargerStateComplete; break; + case 2: a->battery.charger_state = ChargerStateInProgress; break; + default: a->battery.charger_state = ChargerStateUnknown; break; + } + a->battery.voltage = b->voltage; + a->battery.temperature = b->temperature; + a->battery.healthy = !(a->battery.module_missing || a->battery.pack_missing || a->battery.low_voltage || a->battery.high_temperature || a->battery.cycles_exceeded || (a->battery.charger_state != ChargerStateComplete) || (!b->health)); + +} + + +static struct log_page_list *getPage (struct physical_drive_info *d, uint8_t page) +{ + struct log_page_list *p; + + if ((p = (struct log_page_list *) malloc (sizeof (*p))) == NULL) + return NULL; + memset (p, 0, sizeof (*p)); + + if (megaScsiLogSense (&d->adapter->target, d->target, &p->buf, sizeof (p->buf), 1, page, 0) < 0) + { + free (p); + return NULL; + } + + if (parseLogPage (&p->buf, sizeof (p->buf), &p->log) < 0) + { + free (p); + return NULL; + } + + return p; +} + + +struct log_page_list *getDriveLogPage (struct physical_drive_info *d, uint8_t page) +{ + struct supportedLogsPage *supported = NULL; + struct log_page_list *p; + + for (p = d->log; p; p = p->next) + { + if (p->log.h.page_code == page) + return p; + if (p->log.h.page_code == 0) + supported = &p->log.u.supported; + } + + if (supported == NULL) + { + if ((p = getPage (d, 0)) == NULL) + return NULL; + p->next = d->log; + d->log = p; + if (page == 0) + return p; + + supported = &p->log.u.supported; + } + + /* Is the requested page supported? */ + if (supported->page[page] == 0) + return NULL; + + if ((p = getPage (d, page)) == NULL) + return NULL; + p->next = d->log; + d->log = p; + + return p; +} + + +int cmpPhysical (const void *a, const void *b) +{ + struct physical_drive_info *x = *((struct physical_drive_info **) a); + struct physical_drive_info *y = *((struct physical_drive_info **) b); + + if (x->adapter->target.adapno != y->adapter->target.adapno) + return (int) (x->adapter->target.adapno) - (int) (y->adapter->target.adapno); + if (x->channel != y->channel) + return (int) (x->channel) - (int) (y->channel); + if (x->id != y->id) + return (int) (x->id) - (int) (y->id); + return 0; +} + +struct physical_drive_info *getPhysicalDriveInfo (struct adapter_config *a, uint16_t target, int fetch) +{ + int k; + struct physical_drive_info *d; + + /* Look for it. */ + for (k = 0, d = a->physical; k < a->num_physicals; ++k, ++d) + { + if (d->adapter == NULL) + break; + if (d->target == target) + return d->present ? d : NULL; + } + + /* Not there and no place for it. That's just wrong. */ + if (k >= a->num_physicals) + { + fprintf (stderr, "me so crazy, me think adapter crazy too. sorry, mister.\n"); + return NULL; + } + + /* If we don't want to query it, we're done. */ + if (!fetch) + return NULL; + + d->adapter = a; + d->target = target; + + if (a->is_sas) + { + struct mega_physical_disk_info_sas *info = &d->q.v5.info; + + if (megaSasGetDiskInfo (&a->target, target, info) < 0) + { + d->error_string = megaErrorString (); + d->present = 0; + return NULL; + } + + d->channel = info->enclosure; + d->id = info->slot; + + snprintf (d->name, sizeof (d->name), "%se%us%u", a->name, d->channel, d->id); + + d->inquiry = info->inquiry.inq; + strncpy (d->vendor, d->inquiry.vendor_info, sizeof (d->vendor) - 1); + d->vendor[sizeof (d->vendor) - 1] = '\0'; + ntrim (d->vendor); + strncpy (d->model, d->inquiry.prod_ident, sizeof (d->model) - 1); + d->model[sizeof (d->model) - 1] = '\0'; + ntrim (d->model); + strncpy (d->revision, d->inquiry.prod_revision, sizeof (d->revision) - 1); + d->revision[sizeof (d->revision) - 1] = '\0'; + ntrim (d->revision); + + if ((d->inquiry.qualifier == INQ_DEV_PRESENT) && (d->inquiry.type == INQ_DASD)) + { + d->present = 1; + } + else + { + d->present = 0; + return NULL; + } + + strncpy (d->serial, (char *) info->inquiry.buf + sizeof (info->inquiry.inq), sizeof (d->serial)); + d->serial[sizeof (d->serial) - 1] = '\0'; + ntrim (d->serial); + + if (info->configured) + { + if (info->online) + d->state = PdStateOnline; + else if (info->rebuild) + d->state = PdStateRebuild; + else if (info->failure) + d->state = PdStateFailed; + else + d->state = PdStateUnknown; + } + else + { + if (info->hotspare) + d->state = PdStateHotspare; + else if (info->failure) + d->state = PdStateUnconfiguredBad; + else + d->state = PdStateUnconfiguredGood; + } + d->blocks = info->raw_size; + d->media_errors = info->media_errors; + d->other_errors = info->other_errors; + d->predictive_failures = info->predictive_failures; + } + else + { + int status; + struct scsi_inquiry inq; + uint8_t evpd[128]; + struct mega_physical_drive_error_info errors; + + d->channel = (target >> 4) & 0xf; + d->id = target & 0xf; + + snprintf (d->name, sizeof (d->name), "%sc%ut%u", a->name, d->channel, d->id); + + if (megaScsiDriveInquiry (&a->target, target, &inq, sizeof (inq), 0, 0) == 0) + { + d->inquiry = inq; + strncpy (d->vendor, d->inquiry.vendor_info, sizeof (d->vendor) - 1); + d->vendor[sizeof (d->vendor) - 1] = '\0'; + ntrim (d->vendor); + strncpy (d->model, d->inquiry.prod_ident, sizeof (d->model) - 1); + d->model[sizeof (d->model) - 1] = '\0'; + ntrim (d->model); + strncpy (d->revision, d->inquiry.prod_revision, sizeof (d->revision) - 1); + d->revision[sizeof (d->revision) - 1] = '\0'; + ntrim (d->revision); + + if ((d->inquiry.qualifier == INQ_DEV_PRESENT) && (d->inquiry.type == INQ_DASD)) + { + d->present = 1; + } + else + { + d->present = 0; + return NULL; + } + } + else + { + d->error_string = megaErrorString (); + d->present = 0; + return NULL; + } + + if (megaScsiDriveInquiry (&a->target, target, evpd, sizeof evpd, 0x80, 1) == 0) + { + uint8_t len = evpd[3]; + + if ((evpd[1] == 0x80) && (len + 4 <= sizeof evpd)) + { + if (len > sizeof (d->serial) - 1) + len = sizeof (d->serial) - 1; + strncpy (d->serial, (char *) evpd + 4, len); + d->serial[len] = '\0'; + ntrim (d->serial); + } + } + + if ((status = megaGetDriveErrorCount (&a->target, target, &errors)) == 0) + { + d->media_errors = errors.media; + d->other_errors = errors.other; + } + else + d->error_string = megaErrorString (); + } + + /* Add it to the device list and sort it. */ + for (k = 0; k < a->num_physicals; ++k) + if (a->physical_list[k] == NULL) + break; + if (k >= a->num_physicals) + { + fprintf (stderr, "not ok at the ok corral. freak out, mama!\n"); + return NULL; + } + a->physical_list[k++] = d; + qsort (a->physical_list, k, sizeof (*a->physical_list), cmpPhysical); + + return d; +} + + +/* Adapter handling for PERC2. */ +static char *getAdapterConfig2 (struct adapter_config *a) +{ + int k; + logdrv_8ld_span8_t *ml; + int spanIndex; + mraid_adapinfo1_t *pinfo = &a->q.v2.inquiry.adapter_info; + mraid_inquiry1_t *inquiry = &a->q.v2.inquiry; + disk_array_8ld_span8_t *config = &a->q.v2.config; + + a->target.type = MEGA_ADAPTER_V2; + + if (megaGetAdapterInquiry (&a->target, inquiry) < 0) + return "cannot query adapter"; + if (megaGetAdapterConfig8 (&a->target, config) < 0) + return "cannot read adapter config"; + if (megaGetPredictiveMap (&a->target, &a->q.v2.map) < 0) + return "cannot read adapter predictive map"; + + a->rebuild_rate = pinfo->rebuild_rate; + a->dram_size = pinfo->dram_size; + + snprintf (a->name, sizeof (a->name), "a%u", a->target.adapno); + strcpy (a->product, "PERC2/"); + switch (pinfo->nchannels) + { + case 1: strcat (a->product, "SC"); break; + case 2: strcat (a->product, "DC"); break; + case 4: strcat (a->product, "QC"); break; + default: return "invalid number of channels"; + } + strncpy (a->bios, (char *) pinfo->bios_version, sizeof (a->bios)); + a->bios[sizeof (a->bios) - 1] = '\0'; + ntrim (a->bios); + strncpy (a->firmware, (char *) pinfo->fw_version, sizeof (a->firmware)); + a->firmware[sizeof (a->firmware) - 1] = '\0'; + ntrim (a->firmware); + + batteryStatus (a, pinfo->battery_status); + + if (config->numldrv > sizeof (config->ldrv) / sizeof (config->ldrv[0])) + return "invalid number of logical drives"; + + a->num_channels = pinfo->nchannels; + if ((a->channel = (uint8_t *) malloc (a->num_channels * sizeof (*a->channel))) == NULL) + return "out of memory (channels)"; + for (k = 0; k < a->num_channels; ++k) + a->channel[k] = k; + + a->num_physicals = FC_MAX_PHYSICAL_DEVICES; + if ((a->physical = (struct physical_drive_info *) malloc (a->num_physicals * sizeof (*a->physical))) == NULL) + return "out of memory (physical drives)"; + memset (a->physical, 0, a->num_physicals * sizeof (*a->physical)); + if ((a->physical_list = (struct physical_drive_info **) malloc (a->num_physicals * sizeof (*a->physical_list))) == NULL) + return "out of memory (physical drives)"; + memset (a->physical_list, 0, a->num_physicals * sizeof (*a->physical_list)); + + a->num_logicals = config->numldrv; + if ((a->logical = (struct logical_drive_info *) malloc (a->num_logicals * sizeof (*a->logical))) == NULL) + return "out of memory (logical drives)"; + memset (a->logical, 0, a->num_logicals * sizeof (*a->logical)); + + /* Count how many spans there are. */ + for (k = 0, ml = config->ldrv, a->num_spans = 0; k < config->numldrv; ++k, ++ml) + a->num_spans += ml->lparam.span_depth; + + if ((a->span = (struct span_info *) malloc (a->num_spans * sizeof (*a->span))) == NULL) + return "out of memory (spans)"; + memset (a->span, 0, a->num_spans * sizeof (*a->span)); + + /* Copy drive states. */ + for (k = 0; k < sizeof (inquiry->pdrv_info.pdrv_state) / sizeof (inquiry->pdrv_info.pdrv_state[0]); ++k) + switch (inquiry->pdrv_info.pdrv_state[k] & 0xf) + { + case PDRV_UNCNF: a->physical[k].state = PdStateUnconfiguredGood; continue; + case PDRV_ONLINE: a->physical[k].state = PdStateOnline; continue; + case PDRV_FAILED: a->physical[k].state = PdStateFailed; continue; + case PDRV_RBLD: a->physical[k].state = PdStateRebuild; continue; + case PDRV_HOTSPARE: a->physical[k].state = PdStateHotspare; continue; + default: a->physical[k].state = PdStateUnknown; continue; + } + + /* Copy drive sizes. */ + for (k = 0; k < sizeof (config->pdrv) / sizeof (config->pdrv[0]); ++k) + a->physical[k].blocks = config->pdrv[k].size; + + /* Copy drive predictive failures flag */ + for (k = 0; k < 8 * sizeof (a->q.v2.map.map) / sizeof (a->q.v2.map.map[0]); ++k) + a->physical[k].predictive_failures = ((a->q.v2.map.map[k >> 3] & (1 << (k & 0x7))) != 0); + + /* Examine all the logical drives. */ + for (k = 0, ml = config->ldrv, spanIndex = 0; k < config->numldrv; ++k, ++ml) + { + struct span_info *span; + adap_span_8ld_t *mr; + int j; + struct logical_drive_info *l = &a->logical[k]; + + l->adapter = a; + snprintf (l->name, sizeof (l->name), "a%ud%u", a->target.adapno, k); + l->target = k; + switch (ml->lparam.status) + { + case RDRV_OFFLINE: l->state = LdStateOffline; break; + case RDRV_DEGRADED: l->state = LdStateDegraded; break; + case RDRV_OPTIMAL: l->state = LdStateOptimal; break; + case RDRV_DELETED: l->state = LdStateDeleted; break; + default: l->state = LdStateUnknown; break; + } + l->raid_level = ml->lparam.level; + l->span_size = ml->lparam.row_size; + + l->num_spans = ml->lparam.span_depth; + if ((l->span = (struct span_reference *) malloc (l->num_spans * sizeof (*l->span))) == NULL) + return "out of memory (span references)"; + + for (j = 0, mr = ml->span; j < ml->lparam.span_depth; ++j, ++mr) + { + int i; + + span = &a->span[spanIndex++]; + span->adapter = a; + span->num_logical_drives = 1; + if ((span->logical_drive = (struct logical_drive_info **) malloc (span->num_logical_drives * sizeof (*span->logical_drive))) == NULL) + return "out of memory (span -> ldrv pointers)"; + span->logical_drive[0] = l; + span->blocks_per_disk = mr->num_blks; + span->num_disks = ml->lparam.row_size; + if ((span->disk = (struct physical_drive_info **) malloc (span->num_disks * sizeof (*span->disk))) == NULL) + return "out of memory (span -> disk pointers)"; + + /* Logical drives use the whole span. */ + l->span[j].offset = 0; + l->span[j].blocks_per_disk = span->blocks_per_disk; + l->span[j].span = span; + + for (i = 0; i < span->num_disks; ++i) + { + span->disk[i] = &a->physical[mr->device[i].target]; + span->disk[i]->span = span; + } + } + } + + return NULL; +} + + +/* Adapter handling for PERC3 and PERC4 adapters. */ +static char *getAdapterConfig3 (struct adapter_config *a) +{ + int k; + logdrv_40ld_t *ml; + int spanIndex; + mraid_pinfo_t *pinfo = &a->q.v3.adapinfo; + mraid_inquiry3_t *enquiry3 = &a->q.v3.enquiry3; + disk_array_40ld_t *config = &a->q.v3.config; + + a->target.type = MEGA_ADAPTER_V34; + + if (megaGetAdapterEnquiry3 (&a->target, &a->q.v3.enquiry3) < 0) + return "cannot query adapter"; + if (megaGetAdapterConfig40 (&a->target, config) < 0) + return "cannot read adapter config"; + if (megaGetPredictiveMap (&a->target, &a->q.v3.map) < 0) + return "cannot read adapter predictive map"; + + a->rebuild_rate = enquiry3->rebuild_rate; + a->dram_size = pinfo->dram_size; + + snprintf (a->name, sizeof (a->name), "a%u", a->target.adapno); + switch (pinfo->nchannels) + { + case 1: break; + case 2: break; + case 4: break; + default: return "invalid number of channels"; + } + strncpy (a->product, (char *) pinfo->product_name, sizeof (pinfo->product_name)); + a->product[sizeof (a->product) - 1] = '\0'; + ntrim (a->product); + strncpy (a->bios, (char *) pinfo->bios_version, sizeof (a->bios)); + a->bios[sizeof (a->bios) - 1] = '\0'; + ntrim (a->bios); + strncpy (a->firmware, (char *) pinfo->fw_version, sizeof (a->firmware)); + a->firmware[sizeof (a->firmware) - 1] = '\0'; + ntrim (a->firmware); + + batteryStatus (a, enquiry3->battery_status); + + if (config->numldrv > sizeof (config->ldrv) / sizeof (config->ldrv[0])) + return "invalid number of logical drives"; + + a->num_channels = pinfo->nchannels; + if ((a->channel = (uint8_t *) malloc (a->num_channels * sizeof (*a->channel))) == NULL) + return "out of memory (channels)"; + for (k = 0; k < a->num_channels; ++k) + a->channel[k] = k; + + a->num_physicals = FC_MAX_PHYSICAL_DEVICES; + if ((a->physical = (struct physical_drive_info *) malloc (a->num_physicals * sizeof (*a->physical))) == NULL) + return "out of memory (physical drives)"; + memset (a->physical, 0, a->num_physicals * sizeof (*a->physical)); + if ((a->physical_list = (struct physical_drive_info **) malloc (a->num_physicals * sizeof (*a->physical_list))) == NULL) + return "out of memory (physical drives)"; + memset (a->physical_list, 0, a->num_physicals * sizeof (*a->physical_list)); + + a->num_logicals = config->numldrv; + if ((a->logical = (struct logical_drive_info *) malloc (a->num_logicals * sizeof (*a->logical))) == NULL) + return "out of memory (logical drives)"; + memset (a->logical, 0, a->num_logicals * sizeof (*a->logical)); + + /* Count how many spans there are. */ + for (k = 0, ml = config->ldrv, a->num_spans = 0; k < config->numldrv; ++k, ++ml) + a->num_spans += ml->lparam.span_depth; + + if ((a->span = (struct span_info *) malloc (a->num_spans * sizeof (*a->span))) == NULL) + return "out of memory (spans)"; + memset (a->span, 0, a->num_spans * sizeof (*a->span)); + + /* Copy drive states. */ + for (k = 0; k < sizeof (enquiry3->pdrv_state) / sizeof (enquiry3->pdrv_state[0]); ++k) + switch (enquiry3->pdrv_state[k] & 0xf) + { + case PDRV_UNCNF: a->physical[k].state = PdStateUnconfiguredGood; continue; + case PDRV_ONLINE: a->physical[k].state = PdStateOnline; continue; + case PDRV_FAILED: a->physical[k].state = PdStateFailed; continue; + case PDRV_RBLD: a->physical[k].state = PdStateRebuild; continue; + case PDRV_HOTSPARE: a->physical[k].state = PdStateHotspare; continue; + default: a->physical[k].state = PdStateUnknown; continue; + } + + /* Copy drive sizes. */ + for (k = 0; k < sizeof (config->pdrv) / sizeof (config->pdrv[0]); ++k) + a->physical[k].blocks = config->pdrv[k].size; + + /* Copy drive predictive failures flag */ + for (k = 0; k < 8 * sizeof (a->q.v3.map.map) / sizeof (a->q.v3.map.map[0]); ++k) + a->physical[k].predictive_failures = ((a->q.v3.map.map[k >> 3] & (1 << (k & 0x7))) != 0); + + /* Examine all the logical drives. */ + for (k = 0, ml = config->ldrv, spanIndex = 0; k < config->numldrv; ++k, ++ml) + { + struct span_info *span; + adap_span_40ld_t *mr; + int j; + struct logical_drive_info *l = &a->logical[k]; + + l->adapter = a; + snprintf (l->name, sizeof (l->name), "a%ud%u", a->target.adapno, k); + l->target = k; + switch (ml->lparam.status) + { + case RDRV_OFFLINE: l->state = LdStateOffline; break; + case RDRV_DEGRADED: l->state = LdStateDegraded; break; + case RDRV_OPTIMAL: l->state = LdStateOptimal; break; + case RDRV_DELETED: l->state = LdStateDeleted; break; + default: l->state = LdStateUnknown; break; + } + l->raid_level = ml->lparam.level; + l->span_size = ml->lparam.row_size; + + l->num_spans = ml->lparam.span_depth; + if ((l->span = (struct span_reference *) malloc (l->num_spans * sizeof (*l->span))) == NULL) + return "out of memory (span references)"; + + for (j = 0, mr = ml->span; j < ml->lparam.span_depth; ++j, ++mr) + { + int i; + + span = &a->span[spanIndex++]; + span->adapter = a; + span->num_logical_drives = 1; + if ((span->logical_drive = (struct logical_drive_info **) malloc (span->num_logical_drives * sizeof (*span->logical_drive))) == NULL) + return "out of memory (span -> ldrv pointers)"; + span->logical_drive[0] = l; + span->blocks_per_disk = mr->num_blks; + span->num_disks = ml->lparam.row_size; + if ((span->disk = (struct physical_drive_info **) malloc (span->num_disks * sizeof (*span->disk))) == NULL) + return "out of memory (span -> disk pointers)"; + + /* Logical drives use the whole span. */ + l->span[j].offset = 0; + l->span[j].blocks_per_disk = span->blocks_per_disk; + l->span[j].span = span; + + for (i = 0; i < span->num_disks; ++i) + { + span->disk[i] = &a->physical[mr->device[i].target]; + span->disk[i]->span = span; + } + } + } + +#if 0 + /* Go ahead and hit all the other devices that have a non-zero scsi transfer rate. */ + for (k = 0; k < sizeof (a->q.v3.enquiry3.targ_xfer) / sizeof (a->q.v3.enquiry3.targ_xfer[0]); ++k) + if (a->q.v3.enquiry3.targ_xfer[k]) + (void) getPhysicalDriveInfo (a, (uint8_t) k, 1); +#endif + + return NULL; +} + + +int cmpChannel (const void *a, const void *b) +{ + int x = (int) *((uint8_t *) a); + int y = (int) *((uint8_t *) b); + return x - y; +} + +/* Adapter handling for PERC5 adapters. */ +static char *getAdapterConfig5 (struct adapter_config *a) +{ + int k; + struct mega_array_span_def_sas *ms; + struct mega_array_disk_def_sas *ml; + struct megasas_ctrl_info *pinfo = &a->q.v5.adapinfo; + struct mega_device_list_sas *device; + struct mega_array_config_sas *config = &a->q.v5.config; + + a->target.type = MEGA_ADAPTER_V5; + + if (megaSasGetDeviceList (&a->target, &(a->q.v5.device)) < 0) + return "cannot retrieve device list"; + device = a->q.v5.device; + if (megaSasGetArrayConfig (&a->target, &(a->q.v5.config)) < 0) + return "cannot retrieve array configuration"; + if (megaSasGetBatteryInfo (&a->target, &(a->q.v5.battery)) < 0) + return "cannot retrieve battery info"; + + a->rebuild_rate = pinfo->properties.rebuild_rate; + a->dram_size = pinfo->memory_size; + + snprintf (a->name, sizeof (a->name), "a%u", a->target.adapno); + strncpy (a->product, (char *) pinfo->product_name, sizeof (pinfo->product_name)); + a->product[sizeof (a->product) - 1] = '\0'; + ntrim (a->product); + + for (k = 0; k < pinfo->image_component_count; ++k) + { + if (!strcmp (pinfo->image_component[k].name, "BIOS")) + { + strncpy (a->bios, pinfo->image_component[k].version, sizeof (a->bios)); + a->bios[sizeof (a->bios) - 1] = '\0'; + ntrim (a->bios); + } + else if (!strcmp (pinfo->image_component[k].name, "APP ")) + { + strncpy (a->firmware, pinfo->image_component[k].version, sizeof (a->firmware)); + a->firmware[sizeof (a->firmware) - 1] = '\0'; + ntrim (a->firmware); + } + } + + batteryStatus5 (a); + + /* Build enclosure map. */ + for (k = 0, a->num_channels = 0, a->channel = NULL; k < device->num_devices; ++k) + { + int j; + + for (j = 0; j < a->num_channels; ++j) + if (device->device[k].enclosure == a->channel[j]) + break; + if (j < a->num_channels) + continue; + + /* Didn't find this enclosure; extend the map */ + ++a->num_channels; + if ((a->channel = (uint8_t *) realloc (a->channel, a->num_channels * sizeof (*a->channel))) == NULL) + return "out of memory (channels)"; + a->channel[a->num_channels - 1] = device->device[k].enclosure; + } + qsort (a->channel, a->num_channels, sizeof (*a->channel), cmpChannel); + + a->num_physicals = pinfo->pd_present_count; + if ((a->physical = (struct physical_drive_info *) malloc (a->num_physicals * sizeof (*a->physical))) == NULL) + return "out of memory (physical drives)"; + memset (a->physical, 0, a->num_physicals * sizeof (*a->physical)); + if ((a->physical_list = (struct physical_drive_info **) malloc (a->num_physicals * sizeof (*a->physical_list))) == NULL) + return "out of memory (physical drives)"; + memset (a->physical_list, 0, a->num_physicals * sizeof (*a->physical_list)); + + a->num_logicals = config->header->num_disk_defs; + if ((a->logical = (struct logical_drive_info *) malloc (a->num_logicals * sizeof (*a->logical))) == NULL) + return "out of memory (logical drives)"; + memset (a->logical, 0, a->num_logicals * sizeof (*a->logical)); + + a->num_spans = config->header->num_span_defs; + if ((a->span = (struct span_info *) malloc (a->num_spans * sizeof (*a->span))) == NULL) + return "out of memory (spans)"; + memset (a->span, 0, a->num_spans * sizeof (*a->span)); + + /* Get drive info. (This is fast on a PERC5.) */ + for (k = 0; k < device->num_devices; ++k) + if ((device->device[k].type == INQ_DASD) && (getPhysicalDriveInfo (a, device->device[k].device_id, 1) == NULL)) + return "cannot get physical device info"; + + /* Examine all the spans. */ + for (k = 0, ms = config->span; k < config->header->num_span_defs; ++k, ++ms) + { + struct span_info *span = &a->span[k]; + int i; + + span->adapter = a; + span->num_logical_drives = 0; + span->logical_drive = NULL; + span->blocks_per_disk = ms->sectors_per_disk; + span->num_disks = ms->span_size; + if ((span->disk = (struct physical_drive_info **) malloc (span->num_disks * sizeof (*span->disk))) == NULL) + return "out of memory (span -> disk pointers)"; + + for (i = 0; i < span->num_disks; ++i) + { + span->disk[i] = getPhysicalDriveInfo (a, ms->disk[i].device_id, 1); + span->disk[i]->span = span; + } + } + + /* Examine all the logical drives. */ + for (k = 0, ml = config->disk; k < config->header->num_disk_defs; ++k, ++ml) + { + struct span_info *span; + struct mega_array_disk_entry_sas *mr; + int j; + struct logical_drive_info *l = &a->logical[k]; + + l->adapter = a; + snprintf (l->name, sizeof (l->name), "a%ud%u", a->target.adapno, k); + l->target = k; + switch (ml->state) + { + case MEGA_SAS_LD_OFFLINE: l->state = LdStateOffline; break; + case MEGA_SAS_LD_PARTIALLY_DEGRADED: l->state = LdStatePartiallyDegraded; break; + case MEGA_SAS_LD_DEGRADED: l->state = LdStateDegraded; break; + case MEGA_SAS_LD_OPTIMAL: l->state = LdStateOptimal; break; + default: l->state = LdStateUnknown; break; + } + l->raid_level = ml->raid_level; + l->span_size = ml->disks_per_span; + + l->num_spans = ml->num_spans; + if ((l->span = (struct span_reference *) malloc (l->num_spans * sizeof (*l->span))) == NULL) + return "out of memory (span references)"; + + for (j = 0, mr = ml->span; j < ml->num_spans; ++j, ++mr) + { + span = &a->span[mr->span_index]; + ++(span->num_logical_drives); + if ((span->logical_drive = (struct logical_drive_info **) realloc (span->logical_drive, span->num_logical_drives * sizeof (*span->logical_drive))) == NULL) + return "out of memory (span -> ldrv pointers)"; + span->logical_drive[span->num_logical_drives - 1] = l; + + l->span[j].offset = mr->offset; + l->span[j].blocks_per_disk = mr->sectors_per_disk; + l->span[j].span = span; + } + } + + return NULL; +} + + +struct adapter_config *getAdapterConfig (int fd, uint8_t adapno, int sas) +{ + static struct adapter_config *cf = NULL; + struct adapter_config *a; + char *status; + + for (a = cf; a; a = a->next) + if ((a->target.adapno == adapno) && (a->is_sas == sas)) + return a; + + if ((a = (struct adapter_config *) malloc (sizeof (*a))) == NULL) + return NULL; + memset (a, 0, sizeof (*a)); + + a->target.fd = fd; + a->target.adapno = adapno; + a->is_sas = sas; + + if (sas) + { + if (megaSasGetAdapterProductInfo (fd, adapno, &a->q.v5.adapinfo) < 0) + return NULL; + + status = getAdapterConfig5 (a); + } + else + { + mraid_pinfo_t pinfo; + + if (megaGetAdapterProductInfo (fd, adapno, &pinfo) < 0) + return NULL; + + if (pinfo.data_size == 0) + status = getAdapterConfig2 (a); + else + { + a->q.v3.adapinfo = pinfo; + status = getAdapterConfig3 (a); + } + } + + if (status) + { + free (a); + fprintf (stderr, "adapter %d: %s\n", adapno, status); + return NULL; + } + + a->next = cf; + cf = a; + + return a; +} diff --git a/src/adapter.h b/src/adapter.h new file mode 100644 index 0000000..a9e2cbf --- /dev/null +++ b/src/adapter.h @@ -0,0 +1,34 @@ +#ifndef _ADAPTER_H +#define _ADAPTER_H +/* + * Definitions for high-level adapter interface. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include "mega.h" + +#include + +struct log_page_list *getDriveLogPage (struct physical_drive_info *d, uint8_t page); +struct physical_drive_info *getPhysicalDriveInfo (struct adapter_config *cf, uint16_t target, int fetch); +struct adapter_config *getAdapterConfig (int fd, uint8_t adapno, int sas); + +#endif diff --git a/src/callinfo.c b/src/callinfo.c new file mode 100644 index 0000000..d6a39e7 --- /dev/null +++ b/src/callinfo.c @@ -0,0 +1,413 @@ +/* + * Sysctl call data for ptrace(2). + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include "callinfo.h" + +#ifndef SYS_pread +#define SYS_pread SYS_pread64 +#endif + +#ifndef SYS_pwrite +#define SYS_pwrite SYS_pwrite64 +#endif + +struct callinfo callinfo[] = +{ + { 0, 0, NULL }, + { SYS_exit, 0, "exit" }, + { SYS_fork, 0, "fork" }, + { SYS_read, 0, "read" }, + { SYS_write, 0, "write" }, + { SYS_open, 0, "open" }, + { SYS_close, 0, "close" }, + { SYS_waitpid, 0, "waitpid" }, + { SYS_creat, 0, "creat" }, + { SYS_link, 0, "link" }, + { SYS_unlink, 0, "unlink" }, + { SYS_execve, 0, "execve" }, + { SYS_chdir, 0, "chdir" }, + { SYS_time, 0, "time" }, + { SYS_mknod, 0, "mknod" }, + { SYS_chmod, 0, "chmod" }, + { SYS_lchown, 0, "lchown" }, + { SYS_break, 0, "break" }, + { SYS_oldstat, 0, "oldstat" }, + { SYS_lseek, 0, "lseek" }, + { SYS_getpid, 0, "getpid" }, + { SYS_mount, 0, "mount" }, + { SYS_umount, 0, "umount" }, + { SYS_setuid, 0, "setuid" }, + { SYS_getuid, 0, "getuid" }, + { SYS_stime, 0, "stime" }, + { SYS_ptrace, 1, "ptrace" }, + { SYS_alarm, 0, "alarm" }, + { SYS_oldfstat, 0, "oldfstat" }, + { SYS_pause, 0, "pause" }, + { SYS_utime, 0, "utime" }, + { SYS_stty, 0, "stty" }, + { SYS_gtty, 0, "gtty" }, + { SYS_access, 0, "access" }, + { SYS_nice, 0, "nice" }, + { SYS_ftime, 0, "ftime" }, + { SYS_sync, 0, "sync" }, + { SYS_kill, 0, "kill" }, + { SYS_rename, 0, "rename" }, + { SYS_mkdir, 0, "mkdir" }, + { SYS_rmdir, 0, "rmdir" }, + { SYS_dup, 0, "dup" }, + { SYS_pipe, 0, "pipe" }, + { SYS_times, 0, "times" }, + { SYS_prof, 0, "prof" }, + { SYS_brk, 1, "brk" }, + { SYS_setgid, 0, "setgid" }, + { SYS_getgid, 0, "getgid" }, + { SYS_signal, 0, "signal" }, + { SYS_geteuid, 0, "geteuid" }, + { SYS_getegid, 0, "getegid" }, + { SYS_acct, 0, "acct" }, + { SYS_umount2, 0, "umount2" }, + { SYS_lock, 0, "lock" }, + { SYS_ioctl, 0, "ioctl" }, + { SYS_fcntl, 0, "fcntl" }, + { SYS_mpx, 0, "mpx" }, + { SYS_setpgid, 0, "setpgid" }, + { SYS_ulimit, 0, "ulimit" }, + { SYS_oldolduname, 0, "oldolduname" }, + { SYS_umask, 0, "umask" }, + { SYS_chroot, 0, "chroot" }, + { SYS_ustat, 0, "ustat" }, + { SYS_dup2, 0, "dup2" }, + { SYS_getppid, 0, "getppid" }, + { SYS_getpgrp, 0, "getpgrp" }, + { SYS_setsid, 0, "setsid" }, + { SYS_sigaction, 0, "sigaction" }, + { SYS_sgetmask, 0, "sgetmask" }, + { SYS_ssetmask, 0, "ssetmask" }, + { SYS_setreuid, 0, "setreuid" }, + { SYS_setregid, 0, "setregid" }, + { SYS_sigsuspend, 0, "sigsuspend" }, + { SYS_sigpending, 0, "sigpending" }, + { SYS_sethostname, 0, "sethostname" }, + { SYS_setrlimit, 0, "setrlimit" }, + { SYS_getrlimit, 0, "getrlimit" }, + { SYS_getrusage, 0, "getrusage" }, + { SYS_gettimeofday, 0, "gettimeofday" }, + { SYS_settimeofday, 0, "settimeofday" }, + { SYS_getgroups, 0, "getgroups" }, + { SYS_setgroups, 0, "setgroups" }, + { SYS_select, 0, "select" }, + { SYS_symlink, 0, "symlink" }, + { SYS_oldlstat, 0, "oldlstat" }, + { SYS_readlink, 0, "readlink" }, + { SYS_uselib, 0, "uselib" }, + { SYS_swapon, 0, "swapon" }, + { SYS_reboot, 0, "reboot" }, + { SYS_readdir, 0, "readdir" }, + { SYS_mmap2, 1, "mmap2" }, + { SYS_munmap, 0, "munmap" }, + { SYS_truncate, 0, "truncate" }, + { SYS_ftruncate, 0, "ftruncate" }, + { SYS_fchmod, 0, "fchmod" }, + { SYS_fchown, 0, "fchown" }, + { SYS_getpriority, 0, "getpriority" }, + { SYS_setpriority, 0, "setpriority" }, + { SYS_profil, 0, "profil" }, + { SYS_statfs, 0, "statfs" }, + { SYS_fstatfs, 0, "fstatfs" }, + { SYS_ioperm, 0, "ioperm" }, + { SYS_socketcall, 0, "socketcall" }, + { SYS_syslog, 0, "syslog" }, + { SYS_setitimer, 0, "setitimer" }, + { SYS_getitimer, 0, "getitimer" }, + { SYS_stat, 0, "stat" }, + { SYS_lstat, 0, "lstat" }, + { SYS_fstat, 0, "fstat" }, + { SYS_olduname, 0, "olduname" }, + { SYS_iopl, 0, "iopl" }, + { SYS_vhangup, 0, "vhangup" }, + { SYS_idle, 0, "idle" }, + { SYS_vm86old, 0, "vm86old" }, + { SYS_wait4, 0, "wait4" }, + { SYS_swapoff, 0, "swapoff" }, + { SYS_sysinfo, 0, "sysinfo" }, + { SYS_ipc, 0, "ipc" }, + { SYS_fsync, 0, "fsync" }, + { SYS_sigreturn, 0, "sigreturn" }, + { SYS_clone, 0, "clone" }, + { SYS_setdomainname, 0, "setdomainname" }, + { SYS_uname, 0, "uname" }, + { SYS_modify_ldt, 0, "modify_ldt" }, + { SYS_adjtimex, 0, "adjtimex" }, + { SYS_mprotect, 0, "mprotect" }, + { SYS_sigprocmask, 0, "sigprocmask" }, + { SYS_create_module, 0, "create_module" }, + { SYS_init_module, 0, "init_module" }, + { SYS_delete_module, 0, "delete_module" }, + { SYS_get_kernel_syms, 0, "get_kernel_syms" }, + { SYS_quotactl, 0, "quotactl" }, + { SYS_getpgid, 0, "getpgid" }, + { SYS_fchdir, 0, "fchdir" }, + { SYS_bdflush, 0, "bdflush" }, + { SYS_sysfs, 0, "sysfs" }, + { SYS_personality, 0, "personality" }, + { SYS_afs_syscall, 0, "afs_syscall" }, + { SYS_setfsuid, 0, "setfsuid" }, + { SYS_setfsgid, 0, "setfsgid" }, + { SYS__llseek, 0, "_llseek" }, + { SYS_getdents, 0, "getdents" }, + { SYS__newselect, 0, "_newselect" }, + { SYS_flock, 0, "flock" }, + { SYS_msync, 0, "msync" }, + { SYS_readv, 0, "readv" }, + { SYS_writev, 0, "writev" }, + { SYS_getsid, 0, "getsid" }, + { SYS_fdatasync, 0, "fdatasync" }, + { SYS__sysctl, 0, "_sysctl" }, + { SYS_mlock, 0, "mlock" }, + { SYS_munlock, 0, "munlock" }, + { SYS_mlockall, 0, "mlockall" }, + { SYS_munlockall, 0, "munlockall" }, + { SYS_sched_setparam, 0, "sched_setparam" }, + { SYS_sched_getparam, 0, "sched_getparam" }, + { SYS_sched_setscheduler, 0, "sched_setscheduler" }, + { SYS_sched_getscheduler, 0, "sched_getscheduler" }, + { SYS_sched_yield, 0, "sched_yield" }, + { SYS_sched_get_priority_max, 0, "sched_get_priority_max" }, + { SYS_sched_get_priority_min, 0, "sched_get_priority_min" }, + { SYS_sched_rr_get_interval, 0, "sched_rr_get_interval" }, + { SYS_nanosleep, 0, "nanosleep" }, + { SYS_mremap, 0, "mremap" }, + { SYS_setresuid, 0, "setresuid" }, + { SYS_getresuid, 0, "getresuid" }, + { SYS_vm86, 0, "vm86" }, + { SYS_query_module, 0, "query_module" }, + { SYS_poll, 0, "poll" }, + { SYS_nfsservctl, 0, "nfsservctl" }, + { SYS_setresgid, 0, "setresgid" }, + { SYS_getresgid, 0, "getresgid" }, + { SYS_prctl, 0, "prctl" }, + { SYS_rt_sigreturn, 0, "rt_sigreturn" }, + { SYS_rt_sigaction, 0, "rt_sigaction" }, + { SYS_rt_sigprocmask, 0, "rt_sigprocmask" }, + { SYS_rt_sigpending, 0, "rt_sigpending" }, + { SYS_rt_sigtimedwait, 0, "rt_sigtimedwait" }, + { SYS_rt_sigqueueinfo, 0, "rt_sigqueueinfo" }, + { SYS_rt_sigsuspend, 0, "rt_sigsuspend" }, + { SYS_pread, 0, "pread" }, + { SYS_pwrite, 0, "pwrite" }, + { SYS_chown, 0, "chown" }, + { SYS_getcwd, 0, "getcwd" }, + { SYS_capget, 0, "capget" }, + { SYS_capset, 0, "capset" }, + { SYS_sigaltstack, 0, "sigaltstack" }, + { SYS_sendfile, 0, "sendfile" }, + { SYS_getpmsg, 0, "getpmsg" }, + { SYS_putpmsg, 0, "putpmsg" }, + { SYS_vfork, 0, "vfork" }, + { SYS_ugetrlimit, 0, "ugetrlimit" }, + { SYS_mmap2, 1, "mmap2" }, + { SYS_truncate64, 0, "truncate64" }, + { SYS_ftruncate64, 0, "ftruncate64" }, + { SYS_stat64, 0, "stat64" }, + { SYS_lstat64, 0, "lstat64" }, + { SYS_fstat64, 0, "fstat64" }, + { SYS_lchown32, 0, "lchown32" }, + { SYS_getuid32, 0, "getuid32" }, + { SYS_getgid32, 0, "getgid32" }, + { SYS_geteuid32, 0, "geteuid32" }, + { SYS_getegid32, 0, "getegid32" }, + { SYS_setreuid32, 0, "setreuid32" }, + { SYS_setregid32, 0, "setregid32" }, + { SYS_getgroups32, 0, "getgroups32" }, + { SYS_setgroups32, 0, "setgroups32" }, + { SYS_fchown32, 0, "fchown32" }, + { SYS_setresuid32, 0, "setresuid32" }, + { SYS_getresuid32, 0, "getresuid32" }, + { SYS_setresgid32, 0, "setresgid32" }, + { SYS_getresgid32, 0, "getresgid32" }, + { SYS_chown32, 0, "chown32" }, + { SYS_setuid32, 0, "setuid32" }, + { SYS_setgid32, 0, "setgid32" }, + { SYS_setfsuid32, 0, "setfsuid32" }, + { SYS_setfsgid32, 0, "setfsgid32" }, + { SYS_pivot_root, 0, "pivot_root" }, + { SYS_mincore, 0, "mincore" }, + { SYS_madvise1, 0, "madvise1" }, + { SYS_getdents64, 0, "getdents64" }, + { SYS_fcntl64, 0, "fcntl64" }, + { 222, 0, NULL }, + { 223 /* SYS_security */, 0, NULL /* "security" */ }, + { SYS_gettid, 0, "gettid" }, + { SYS_readahead, 0, "readahead" }, + { SYS_setxattr, 0, "setxattr" }, + { SYS_lsetxattr, 0, "lsetxattr" }, + { SYS_fsetxattr, 0, "fsetxattr" }, + { SYS_getxattr, 0, "getxattr" }, + { SYS_lgetxattr, 0, "lgetxattr" }, + { SYS_fgetxattr, 0, "fgetxattr" }, + { SYS_listxattr, 0, "listxattr" }, + { SYS_llistxattr, 0, "llistxattr" }, + { SYS_flistxattr, 0, "flistxattr" }, + { SYS_removexattr, 0, "removexattr" }, + { SYS_lremovexattr, 0, "lremovexattr" }, + { SYS_fremovexattr, 0, "fremovexattr" }, + { SYS_tkill, 0, "tkill" }, + { SYS_sendfile64, 0, "sendfile64" }, + { SYS_futex, 0, "futex" }, + { SYS_sched_setaffinity, 0, "sched_setaffinity" }, + { SYS_sched_getaffinity, 0, "sched_getaffinity" }, +#ifdef SYS_set_thread_area + { SYS_set_thread_area, 0, "set_thread_area " }, +#else + { 243, 0, NULL }, +#endif +#ifdef SYS_get_thread_area + { SYS_get_thread_area, 0, "get_thread_area" }, +#else + { 244, 0, NULL }, +#endif +#ifdef SYS_io_setup + { SYS_io_setup, 0, "io_setup" }, +#else + { 245, 0, NULL }, +#endif +#ifdef SYS_io_destroy + { SYS_io_destroy, 0, "io_destroy" }, +#else + { 246, 0, NULL }, +#endif +#ifdef SYS_io_getevents + { SYS_io_getevents, 0, "io_getevents" }, +#else + { 247, 0, NULL }, +#endif +#ifdef SYS_io_submit + { SYS_io_submit, 0, "io_submit" }, +#else + { 248, 0, NULL }, +#endif +#ifdef SYS_io_cancel + { SYS_io_cancel, 0, "io_cancel" }, +#else + { 249, 0, NULL }, +#endif +#ifdef SYS_fadvise64 + { SYS_fadvise64, 0, "fadvise64" }, +#else + { 250, 0, NULL }, +#endif + { 251, 0, NULL }, +#ifdef SYS_exit_group + { SYS_exit_group, 0, "exit_group" }, +#else + { 252, 0, NULL }, +#endif +#ifdef SYS_lookup_dcookie + { SYS_lookup_dcookie, 0, "lookup_dcookie" }, +#else + { 253, 0, NULL }, +#endif +#ifdef SYS_epoll_create + { SYS_epoll_create, 0, "epoll_create" }, +#else + { 254, 0, NULL }, +#endif +#ifdef SYS_epoll_ctl + { SYS_epoll_ctl, 0, "epoll_ctl" }, +#else + { 255, 0, NULL }, +#endif +#ifdef SYS_epoll_wait + { SYS_epoll_wait, 0, "epoll_wait" }, +#else + { 256, 0, NULL }, +#endif +#ifdef SYS_remap_file_pages + { SYS_remap_file_pages, 0, "remap_file_pages" }, +#else + { 257, 0, NULL }, +#endif +#ifdef SYS_set_tid_address + { SYS_set_tid_address, 0, "set_tid_address" }, +#else + { 258, 0, NULL }, +#endif +#ifdef SYS_timer_create + { SYS_timer_create, 0, "timer_create" }, +#else + { 259, 0, NULL }, +#endif +#ifdef SYS_timer_settime + { SYS_timer_settime, 0, "timer_settime" }, +#else + { 260, 0, NULL }, +#endif +#ifdef SYS_timer_gettime + { SYS_timer_gettime, 0, "timer_gettime" }, +#else + { 261, 0, NULL }, +#endif +#ifdef SYS_timer_getoverrun + { SYS_timer_getoverrun, 0, "timer_getoverrun" }, +#else + { 262, 0, NULL }, +#endif +#ifdef SYS_timer_delete + { SYS_timer_delete, 0, "timer_delete" }, +#else + { 263, 0, NULL }, +#endif +#ifdef SYS_clock_settime + { SYS_clock_settime, 0, "clock_settime" }, +#else + { 264, 0, NULL }, +#endif +#ifdef SYS_clock_gettime + { SYS_clock_gettime, 0, "clock_gettime" }, +#else + { 265, 0, NULL }, +#endif +#ifdef SYS_clock_getres + { SYS_clock_getres, 0, "clock_getres" }, +#else + { 266, 0, NULL }, +#endif +#ifdef SYS_clock_nansleep + { SYS_clock_nanosleep, 0, "clock_nanosleep" }, +#else + { 267, 0, NULL }, +#endif + { 268, 0, NULL }, + { 269, 0, NULL }, +#ifdef SYS_tgkill + { SYS_tgkill, 0, "tgkill" }, +#else + { 270, 0, NULL }, +#endif +}; + +int callmax = sizeof (callinfo) / sizeof (callinfo[0]); + diff --git a/src/callinfo.h b/src/callinfo.h new file mode 100644 index 0000000..0eb7ad0 --- /dev/null +++ b/src/callinfo.h @@ -0,0 +1,35 @@ +#ifndef _CALLINFO_H +#define _CALLINFO_H +/* + * Definitions for syscall constants. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +struct callinfo +{ + int id; + int ptrval; + char *name; +}; + +extern struct callinfo callinfo[]; +extern int callmax; + +#endif diff --git a/src/dumpbytes.c b/src/dumpbytes.c new file mode 100644 index 0000000..5201640 --- /dev/null +++ b/src/dumpbytes.c @@ -0,0 +1,80 @@ +/* + * Hexadecimal dump for displaying ioctl data structures. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include +#include +#include +#include + + +void dumpbytes (FILE *f, void *z, size_t len, void *addr, char *prefix) +{ + off_t k; + int j = 15; + char abuf[20]; + unsigned char *buf = z; + + for (k = 0; k < len; ++k) + { + unsigned char c = buf[k]; + + j = k % 16; + if (j == 0) + { + if (prefix) + fprintf (f, " %s+%04lx:\t", prefix, k); + else + fprintf (f, " %08lx:\t", ((unsigned long) addr) + k); + memset (abuf, ' ', sizeof abuf - 1); + abuf[sizeof abuf - 1] = '\0'; + } + else + { + if (j % 4 == 0) + putc (' ', f); + if (j % 8 == 0) + putc (' ', f); + } + fprintf (f, "%02x", c); + abuf[j + j / 4] = isprint (c) ? c : '.'; + if (j == 15) + { + fprintf (f, " %s\n", abuf); + } + } + if (j != 15) + { + for ( ; j < 15; ++j) + { + if (j % 4 == 0) + putc (' ', f); + if (j % 8 == 0) + putc (' ', f); + putc (' ', f); + putc (' ', f); + } + fprintf (f, " %s\n", abuf); + } +} + + diff --git a/src/dumpbytes.h b/src/dumpbytes.h new file mode 100644 index 0000000..3873787 --- /dev/null +++ b/src/dumpbytes.h @@ -0,0 +1,29 @@ +#ifndef _DUMPBYTES_H +#define _DUMPBYTES_H +/* + * Definitions for hex dump routine. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +extern void dumpbytes (FILE *f, void *z, size_t len, void *addr, char *prefix); + +#endif diff --git a/src/includes-hack/asm/semaphore.h b/src/includes-hack/asm/semaphore.h new file mode 100644 index 0000000..e69de29 diff --git a/src/kernel-2.6.9-55.0.2.EL/megaraid b/src/kernel-2.6.9-55.0.2.EL/megaraid new file mode 120000 index 0000000..424de97 --- /dev/null +++ b/src/kernel-2.6.9-55.0.2.EL/megaraid @@ -0,0 +1 @@ +megaraid-2.20.4.6-rh2 \ No newline at end of file diff --git a/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/mbox_defs.h b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/mbox_defs.h new file mode 100644 index 0000000..18769e5 --- /dev/null +++ b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/mbox_defs.h @@ -0,0 +1,823 @@ +/* + * + * Linux MegaRAID Unified device driver + * + * Copyright (c) 2003-2004 LSI Logic Corporation. + * + * 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. + * + * FILE : mbox_defs.h + * + */ +#ifndef _MRAID_MBOX_DEFS_H_ +#define _MRAID_MBOX_DEFS_H_ + +#include + +/* + * Commands and states for mailbox based controllers + */ + +#define MBOXCMD_LREAD 0x01 +#define MBOXCMD_LWRITE 0x02 +#define MBOXCMD_PASSTHRU 0x03 +#define MBOXCMD_ADPEXTINQ 0x04 +#define MBOXCMD_ADAPTERINQ 0x05 +#define MBOXCMD_LREAD64 0xA7 +#define MBOXCMD_LWRITE64 0xA8 +#define MBOXCMD_PASSTHRU64 0xC3 +#define MBOXCMD_EXTPTHRU 0xE3 + +#define MAIN_MISC_OPCODE 0xA4 +#define GET_MAX_SG_SUPPORT 0x01 +#define SUPPORT_EXT_CDB 0x16 + +#define FC_NEW_CONFIG 0xA1 +#define NC_SUBOP_PRODUCT_INFO 0x0E +#define NC_SUBOP_ENQUIRY3 0x0F +#define ENQ3_GET_SOLICITED_FULL 0x02 +#define OP_DCMD_READ_CONFIG 0x04 +#define NEW_READ_CONFIG_8LD 0x67 +#define READ_CONFIG_8LD 0x07 +#define FLUSH_ADAPTER 0x0A +#define FLUSH_SYSTEM 0xFE + +/* + * Command for random deletion of logical drives + */ +#define FC_DEL_LOGDRV 0xA4 +#define OP_SUP_DEL_LOGDRV 0x2A +#define OP_GET_LDID_MAP 0x18 +#define OP_DEL_LOGDRV 0x1C + +/* + * BIOS commands + */ +#define IS_BIOS_ENABLED 0x62 +#define GET_BIOS 0x01 +#define CHNL_CLASS 0xA9 +#define GET_CHNL_CLASS 0x00 +#define SET_CHNL_CLASS 0x01 +#define CH_RAID 0x01 +#define CH_SCSI 0x00 +#define BIOS_PVT_DATA 0x40 +#define GET_BIOS_PVT_DATA 0x00 + + +/* + * Commands to support clustering + */ +#define GET_TARGET_ID 0x7D +#define CLUSTER_OP 0x70 +#define GET_CLUSTER_MODE 0x02 +#define CLUSTER_CMD 0x6E +#define RESERVE_LD 0x01 +#define RELEASE_LD 0x02 +#define RESET_RESERVATIONS 0x03 +#define RESERVATION_STATUS 0x04 +#define RESERVE_PD 0x05 +#define RELEASE_PD 0x06 + + +/* + * Module battery status + */ +#define BATTERY_MODULE_MISSING 0x01 +#define BATTERY_LOW_VOLTAGE 0x02 +#define BATTERY_TEMP_HIGH 0x04 +#define BATTERY_PACK_MISSING 0x08 +#define BATTERY_CHARGE_MASK 0x30 +#define BATTERY_CHARGE_DONE 0x00 +#define BATTERY_CHARGE_INPROG 0x10 +#define BATTERY_CHARGE_FAIL 0x20 +#define BATTERY_CYCLES_EXCEEDED 0x40 + +/* + * Physical drive states. + */ +#define PDRV_UNCNF 0 +#define PDRV_ONLINE 3 +#define PDRV_FAILED 4 +#define PDRV_RBLD 5 +#define PDRV_HOTSPARE 6 + + +/* + * Raid logical drive states. + */ +#define RDRV_OFFLINE 0 +#define RDRV_DEGRADED 1 +#define RDRV_OPTIMAL 2 +#define RDRV_DELETED 3 + +/* + * Read, write and cache policies + */ +#define NO_READ_AHEAD 0 +#define READ_AHEAD 1 +#define ADAP_READ_AHEAD 2 +#define WRMODE_WRITE_THRU 0 +#define WRMODE_WRITE_BACK 1 +#define CACHED_IO 0 +#define DIRECT_IO 1 + +#define MAX_LOGICAL_DRIVES_8LD 8 +#define MAX_LOGICAL_DRIVES_40LD 40 +#define FC_MAX_PHYSICAL_DEVICES 256 +#define MAX_MBOX_CHANNELS 5 +#define MAX_MBOX_TARGET 15 +#define MBOX_MAX_PHYSICAL_DRIVES MAX_MBOX_CHANNELS*MAX_MBOX_TARGET +#define MAX_ROW_SIZE_40LD 32 +#define MAX_ROW_SIZE_8LD 8 +#define SPAN_DEPTH_8_SPANS 8 +#define SPAN_DEPTH_4_SPANS 4 +#define MAX_REQ_SENSE_LEN 0x20 + + + +/** + * struct mbox_t - Driver and f/w handshake structure. + * @cmd : firmware command + * @cmdid : command id + * @numsectors : number of sectors to be transferred + * @lba : Logical Block Address on LD + * @xferaddr : DMA address for data transfer + * @logdrv : logical drive number + * @numsge : number of scatter gather elements in sg list + * @resvd : reserved + * @busy : f/w busy, must wait to issue more commands. + * @numstatus : number of commands completed. + * @status : status of the commands completed + * @completed : array of completed command ids. + * @poll : poll and ack sequence + * @ack : poll and ack sequence + * + * The central handshake structure between the driver and the firmware. This + * structure must be allocated by the driver and aligned at 8-byte boundary. + */ +#define MBOX_MAX_FIRMWARE_STATUS 46 +typedef struct { + uint8_t cmd; + uint8_t cmdid; + uint16_t numsectors; + uint32_t lba; + uint32_t xferaddr; + uint8_t logdrv; + uint8_t numsge; + uint8_t resvd; + uint8_t busy; + uint8_t numstatus; + uint8_t status; + uint8_t completed[MBOX_MAX_FIRMWARE_STATUS]; + uint8_t poll; + uint8_t ack; +} __attribute__ ((packed)) mbox_t; + + +/** + * mbox64_t - 64-bit extension for the mailbox + * @segment_lo : the low 32-bits of the address of the scatter-gather list + * @segment_hi : the upper 32-bits of the address of the scatter-gather list + * @mbox : 32-bit mailbox, whose xferadder field must be set to + * 0xFFFFFFFF + * + * This is the extension of the 32-bit mailbox to be able to perform DMA + * beyond 4GB address range. + */ +typedef struct { + uint32_t xferaddr_lo; + uint32_t xferaddr_hi; + mbox_t mbox32; +} __attribute__ ((packed)) mbox64_t; + +/* + * mailbox structure used for internal commands + */ +typedef struct { + u8 cmd; + u8 cmdid; + u8 opcode; + u8 subopcode; + u32 lba; + u32 xferaddr; + u8 logdrv; + u8 rsvd[3]; + u8 numstatus; + u8 status; +} __attribute__ ((packed)) int_mbox_t; + +/** + * mraid_passthru_t - passthru structure to issue commands to physical devices + * @timeout : command timeout, 0=6sec, 1=60sec, 2=10min, 3=3hr + * @ars : set if ARS required after check condition + * @islogical : set if command meant for logical devices + * @logdrv : logical drive number if command for LD + * @channel : Channel on which physical device is located + * @target : SCSI target of the device + * @queuetag : unused + * @queueaction : unused + * @cdb : SCSI CDB + * @cdblen : length of the CDB + * @reqsenselen : amount of request sense data to be returned + * @reqsensearea : Sense information buffer + * @numsge : number of scatter-gather elements in the sg list + * @scsistatus : SCSI status of the command completed. + * @dataxferaddr : DMA data transfer address + * @dataxferlen : amount of the data to be transferred. + */ +typedef struct { + uint8_t timeout :3; + uint8_t ars :1; + uint8_t reserved :3; + uint8_t islogical :1; + uint8_t logdrv; + uint8_t channel; + uint8_t target; + uint8_t queuetag; + uint8_t queueaction; + uint8_t cdb[10]; + uint8_t cdblen; + uint8_t reqsenselen; + uint8_t reqsensearea[MAX_REQ_SENSE_LEN]; + uint8_t numsge; + uint8_t scsistatus; + uint32_t dataxferaddr; + uint32_t dataxferlen; +} __attribute__ ((packed)) mraid_passthru_t; + +typedef struct { + + uint32_t dataxferaddr_lo; + uint32_t dataxferaddr_hi; + mraid_passthru_t pthru32; + +} __attribute__ ((packed)) mega_passthru64_t; + +/** + * mraid_epassthru_t - passthru structure to issue commands to physical devices + * @timeout : command timeout, 0=6sec, 1=60sec, 2=10min, 3=3hr + * @ars : set if ARS required after check condition + * @rsvd1 : reserved field + * @cd_rom : (?) + * @rsvd2 : reserved field + * @islogical : set if command meant for logical devices + * @logdrv : logical drive number if command for LD + * @channel : Channel on which physical device is located + * @target : SCSI target of the device + * @queuetag : unused + * @queueaction : unused + * @cdblen : length of the CDB + * @rsvd3 : reserved field + * @cdb : SCSI CDB + * @numsge : number of scatter-gather elements in the sg list + * @status : SCSI status of the command completed. + * @reqsenselen : amount of request sense data to be returned + * @reqsensearea : Sense information buffer + * @rsvd4 : reserved field + * @dataxferaddr : DMA data transfer address + * @dataxferlen : amount of the data to be transferred. + */ +typedef struct { + uint8_t timeout :3; + uint8_t ars :1; + uint8_t rsvd1 :1; + uint8_t cd_rom :1; + uint8_t rsvd2 :1; + uint8_t islogical :1; + uint8_t logdrv; + uint8_t channel; + uint8_t target; + uint8_t queuetag; + uint8_t queueaction; + uint8_t cdblen; + uint8_t rsvd3; + uint8_t cdb[16]; + uint8_t numsge; + uint8_t status; + uint8_t reqsenselen; + uint8_t reqsensearea[MAX_REQ_SENSE_LEN]; + uint8_t rsvd4; + uint32_t dataxferaddr; + uint32_t dataxferlen; +} __attribute__ ((packed)) mraid_epassthru_t; + + +/** + * mraid_pinfo_t - product info, static information about the controller + * @data_size : current size in bytes (not including resvd) + * @config_signature : Current value is 0x00282008 + * @fw_version : Firmware version + * @bios_version : version of the BIOS + * @product_name : Name given to the controller + * @max_commands : Maximum concurrent commands supported + * @nchannels : Number of SCSI Channels detected + * @fc_loop_present : Number of Fibre Loops detected + * @mem_type : EDO, FPM, SDRAM etc + * @signature : + * @dram_size : In terms of MB + * @subsysid : device PCI subsystem ID + * @subsysvid : device PCI subsystem vendor ID + * @notify_counters : + * @pad1k : 135 + 889 resvd = 1024 total size + * + * This structures holds the information about the controller which is not + * expected to change dynamically. + * + * The current value of config signature is 0x00282008: + * 0x28 = MAX_LOGICAL_DRIVES, + * 0x20 = Number of stripes and + * 0x08 = Number of spans + */ +typedef struct { + uint32_t data_size; + uint32_t config_signature; + uint8_t fw_version[16]; + uint8_t bios_version[16]; + uint8_t product_name[80]; + uint8_t max_commands; + uint8_t nchannels; + uint8_t fc_loop_present; + uint8_t mem_type; + uint32_t signature; + uint16_t dram_size; + uint16_t subsysid; + uint16_t subsysvid; + uint8_t notify_counters; + uint8_t pad1k[889]; +} __attribute__ ((packed)) mraid_pinfo_t; + + +/** + * mraid_notify_t - the notification structure + * @global_counter : Any change increments this counter + * @param_counter : Indicates any params changed + * @param_id : Param modified - defined below + * @param_val : New val of last param modified + * @write_config_counter : write config occurred + * @write_config_rsvd : + * @ldrv_op_counter : Indicates ldrv op started/completed + * @ldrv_opid : ldrv num + * @ldrv_opcmd : ldrv operation - defined below + * @ldrv_opstatus : status of the operation + * @ldrv_state_counter : Indicates change of ldrv state + * @ldrv_state_id : ldrv num + * @ldrv_state_new : New state + * @ldrv_state_old : old state + * @pdrv_state_counter : Indicates change of ldrv state + * @pdrv_state_id : pdrv id + * @pdrv_state_new : New state + * @pdrv_state_old : old state + * @pdrv_fmt_counter : Indicates pdrv format started/over + * @pdrv_fmt_id : pdrv id + * @pdrv_fmt_val : format started/over + * @pdrv_fmt_rsvd : + * @targ_xfer_counter : Indicates SCSI-2 Xfer rate change + * @targ_xfer_id : pdrv Id + * @targ_xfer_val : new Xfer params of last pdrv + * @targ_xfer_rsvd : + * @fcloop_id_chg_counter : Indicates loopid changed + * @fcloopid_pdrvid : pdrv id + * @fcloop_id0 : loopid on fc loop 0 + * @fcloop_id1 : loopid on fc loop 1 + * @fcloop_state_counter : Indicates loop state changed + * @fcloop_state0 : state of fc loop 0 + * @fcloop_state1 : state of fc loop 1 + * @fcloop_state_rsvd : + */ +typedef struct { + uint32_t global_counter; + uint8_t param_counter; + uint8_t param_id; + uint16_t param_val; + uint8_t write_config_counter; + uint8_t write_config_rsvd[3]; + uint8_t ldrv_op_counter; + uint8_t ldrv_opid; + uint8_t ldrv_opcmd; + uint8_t ldrv_opstatus; + uint8_t ldrv_state_counter; + uint8_t ldrv_state_id; + uint8_t ldrv_state_new; + uint8_t ldrv_state_old; + uint8_t pdrv_state_counter; + uint8_t pdrv_state_id; + uint8_t pdrv_state_new; + uint8_t pdrv_state_old; + uint8_t pdrv_fmt_counter; + uint8_t pdrv_fmt_id; + uint8_t pdrv_fmt_val; + uint8_t pdrv_fmt_rsvd; + uint8_t targ_xfer_counter; + uint8_t targ_xfer_id; + uint8_t targ_xfer_val; + uint8_t targ_xfer_rsvd; + uint8_t fcloop_id_chg_counter; + uint8_t fcloopid_pdrvid; + uint8_t fcloop_id0; + uint8_t fcloop_id1; + uint8_t fcloop_state_counter; + uint8_t fcloop_state0; + uint8_t fcloop_state1; + uint8_t fcloop_state_rsvd; +} __attribute__ ((packed)) mraid_notify_t; + + +/** + * mraid_inquiry3_t - enquiry for device information + * + * @data_size : current size in bytes (not including resvd) + * @notify : + * @notify_rsvd : + * @rebuild_rate : rebuild rate (0% - 100%) + * @cache_flush_int : cache flush interval in seconds + * @sense_alert : + * @drive_insert_count : drive insertion count + * @battery_status : + * @num_ldrv : no. of Log Drives configured + * @recon_state : state of reconstruct + * @ldrv_op_status : logdrv Status + * @ldrv_size : size of each log drv + * @ldrv_prop : + * @ldrv_state : state of log drives + * @pdrv_state : state of phys drvs. + * @pdrv_format : + * @targ_xfer : phys device transfer rate + * @pad1k : 761 + 263reserved = 1024 bytes total size + */ +#define MAX_NOTIFY_SIZE 0x80 +#define CUR_NOTIFY_SIZE sizeof(mraid_notify_t) + +typedef struct { + uint32_t data_size; + + mraid_notify_t notify; + + uint8_t notify_rsvd[MAX_NOTIFY_SIZE - CUR_NOTIFY_SIZE]; + + uint8_t rebuild_rate; + uint8_t cache_flush_int; + uint8_t sense_alert; + uint8_t drive_insert_count; + + uint8_t battery_status; + uint8_t num_ldrv; + uint8_t recon_state[MAX_LOGICAL_DRIVES_40LD / 8]; + uint16_t ldrv_op_status[MAX_LOGICAL_DRIVES_40LD / 8]; + + uint32_t ldrv_size[MAX_LOGICAL_DRIVES_40LD]; + uint8_t ldrv_prop[MAX_LOGICAL_DRIVES_40LD]; + uint8_t ldrv_state[MAX_LOGICAL_DRIVES_40LD]; + uint8_t pdrv_state[FC_MAX_PHYSICAL_DEVICES]; + uint16_t pdrv_format[FC_MAX_PHYSICAL_DEVICES / 16]; + + uint8_t targ_xfer[80]; + uint8_t pad1k[263]; +} __attribute__ ((packed)) mraid_inquiry3_t; + + +/** + * mraid_adapinfo_t - information about the adapter + * @max_commands : max concurrent commands supported + * @rebuild_rate : rebuild rate - 0% thru 100% + * @max_targ_per_chan : max targ per channel + * @nchannels : number of channels on HBA + * @fw_version : firmware version + * @age_of_flash : number of times FW has been flashed + * @chip_set_value : contents of 0xC0000832 + * @dram_size : in MB + * @cache_flush_interval : in seconds + * @bios_version : + * @board_type : + * @sense_alert : + * @write_config_count : increase with every configuration change + * @drive_inserted_count : increase with every drive inserted + * @inserted_drive : channel:Id of inserted drive + * @battery_status : bit 0: battery module missing + * bit 1: VBAD + * bit 2: temprature high + * bit 3: battery pack missing + * bit 4,5: + * 00 - charge complete + * 01 - fast charge in progress + * 10 - fast charge fail + * 11 - undefined + * bit 6: counter > 1000 + * bit 7: Undefined + * @dec_fault_bus_info : + */ +typedef struct { + uint8_t max_commands; + uint8_t rebuild_rate; + uint8_t max_targ_per_chan; + uint8_t nchannels; + uint8_t fw_version[4]; + uint16_t age_of_flash; + uint8_t chip_set_value; + uint8_t dram_size; + uint8_t cache_flush_interval; + uint8_t bios_version[4]; + uint8_t board_type; + uint8_t sense_alert; + uint8_t write_config_count; + uint8_t battery_status; + uint8_t dec_fault_bus_info; +} __attribute__ ((packed)) mraid_adapinfo_t; + + +/** + * mraid_ldrv_info_t - information about the logical drives + * @nldrv : Number of logical drives configured + * @rsvd : + * @size : size of each logical drive + * @prop : + * @state : state of each logical drive + */ +typedef struct { + uint8_t nldrv; + uint8_t rsvd[3]; + uint32_t size[MAX_LOGICAL_DRIVES_8LD]; + uint8_t prop[MAX_LOGICAL_DRIVES_8LD]; + uint8_t state[MAX_LOGICAL_DRIVES_8LD]; +} __attribute__ ((packed)) mraid_ldrv_info_t; + + +/** + * mraid_pdrv_info_t - information about the physical drives + * @pdrv_state : state of each physical drive + */ +typedef struct { + uint8_t pdrv_state[MBOX_MAX_PHYSICAL_DRIVES]; + uint8_t rsvd; +} __attribute__ ((packed)) mraid_pdrv_info_t; + + +/** + * mraid_inquiry_t - RAID inquiry, mailbox command 0x05 + * @mraid_adapinfo_t : adapter information + * @mraid_ldrv_info_t : logical drives information + * @mraid_pdrv_info_t : physical drives information + */ +typedef struct { + mraid_adapinfo_t adapter_info; + mraid_ldrv_info_t logdrv_info; + mraid_pdrv_info_t pdrv_info; +} __attribute__ ((packed)) mraid_inquiry_t; + + +/** + * mraid_extinq_t - RAID extended inquiry, mailbox command 0x04 + * + * @raid_inq : raid inquiry + * @phys_drv_format : + * @stack_attn : + * @modem_status : + * @rsvd : + */ +typedef struct { + mraid_inquiry_t raid_inq; + uint16_t phys_drv_format[MAX_MBOX_CHANNELS]; + uint8_t stack_attn; + uint8_t modem_status; + uint8_t rsvd[2]; +} __attribute__ ((packed)) mraid_extinq_t; + + +/** + * adap_device_t - device information + * @channel : channel fpor the device + * @target : target ID of the device + */ +typedef struct { + uint8_t channel; + uint8_t target; +}__attribute__ ((packed)) adap_device_t; + + +/** + * adap_span_40ld_t - 40LD span + * @start_blk : starting block + * @num_blks : number of blocks + */ +typedef struct { + uint32_t start_blk; + uint32_t num_blks; + adap_device_t device[MAX_ROW_SIZE_40LD]; +}__attribute__ ((packed)) adap_span_40ld_t; + + +/** + * adap_span_8ld_t - 8LD span + * @start_blk : starting block + * @num_blks : number of blocks + */ +typedef struct { + uint32_t start_blk; + uint32_t num_blks; + adap_device_t device[MAX_ROW_SIZE_8LD]; +}__attribute__ ((packed)) adap_span_8ld_t; + + +/** + * logdrv_param_t - logical drives parameters + * + * @span_depth : total number of spans + * @level : RAID level + * @read_ahead : read ahead, no read ahead, adaptive read ahead + * @stripe_sz : encoded stripe size + * @status : status of the logical drive + * @write_mode : write mode, write_through/write_back + * @direct_io : direct io or through cache + * @row_size : number of stripes in a row + */ +typedef struct { + uint8_t span_depth; + uint8_t level; + uint8_t read_ahead; + uint8_t stripe_sz; + uint8_t status; + uint8_t write_mode; + uint8_t direct_io; + uint8_t row_size; +} __attribute__ ((packed)) logdrv_param_t; + + +/** + * logdrv_40ld_t - logical drive definition for 40LD controllers + * @lparam : logical drives parameters + * @span : span + */ +typedef struct { + logdrv_param_t lparam; + adap_span_40ld_t span[SPAN_DEPTH_8_SPANS]; +}__attribute__ ((packed)) logdrv_40ld_t; + + +/** + * logdrv_8ld_span8_t - logical drive definition for 8LD controllers + * @lparam : logical drives parameters + * @span : span + * + * 8-LD logical drive with upto 8 spans + */ +typedef struct { + logdrv_param_t lparam; + adap_span_8ld_t span[SPAN_DEPTH_8_SPANS]; +}__attribute__ ((packed)) logdrv_8ld_span8_t; + + +/** + * logdrv_8ld_span4_t - logical drive definition for 8LD controllers + * @lparam : logical drives parameters + * @span : span + * + * 8-LD logical drive with upto 4 spans + */ +typedef struct { + logdrv_param_t lparam; + adap_span_8ld_t span[SPAN_DEPTH_4_SPANS]; +}__attribute__ ((packed)) logdrv_8ld_span4_t; + + +/** + * phys_drive_t - physical device information + * @type : Type of the device + * @cur_status : current status of the device + * @tag_depth : Level of tagging + * @sync_neg : sync negotiation - ENABLE or DISBALE + * @size : configurable size in terms of 512 byte + */ +typedef struct { + uint8_t type; + uint8_t cur_status; + uint8_t tag_depth; + uint8_t sync_neg; + uint32_t size; +}__attribute__ ((packed)) phys_drive_t; + + +/** + * disk_array_40ld_t - disk array for 40LD controllers + * @numldrv : number of logical drives + * @resvd : + * @ldrv : logical drives information + * @pdrv : physical drives information + */ +typedef struct { + uint8_t numldrv; + uint8_t resvd[3]; + logdrv_40ld_t ldrv[MAX_LOGICAL_DRIVES_40LD]; + phys_drive_t pdrv[MBOX_MAX_PHYSICAL_DRIVES]; +}__attribute__ ((packed)) disk_array_40ld_t; + + +/** + * disk_array_8ld_span8_t - disk array for 8LD controllers + * @numldrv : number of logical drives + * @resvd : + * @ldrv : logical drives information + * @pdrv : physical drives information + * + * Disk array for 8LD logical drives with upto 8 spans + */ +typedef struct { + uint8_t numldrv; + uint8_t resvd[3]; + logdrv_8ld_span8_t ldrv[MAX_LOGICAL_DRIVES_8LD]; + phys_drive_t pdrv[MBOX_MAX_PHYSICAL_DRIVES]; +}__attribute__ ((packed)) disk_array_8ld_span8_t; + + +/** + * disk_array_8ld_span4_t - disk array for 8LD controllers + * @numldrv : number of logical drives + * @resvd : + * @ldrv : logical drives information + * @pdrv : physical drives information + * + * Disk array for 8LD logical drives with upto 4 spans + */ +typedef struct { + uint8_t numldrv; + uint8_t resvd[3]; + logdrv_8ld_span4_t ldrv[MAX_LOGICAL_DRIVES_8LD]; + phys_drive_t pdrv[MBOX_MAX_PHYSICAL_DRIVES]; +}__attribute__ ((packed)) disk_array_8ld_span4_t; + + +/** + * private_bios_data - bios private data for boot devices + * @geometry : bits 0-3 - BIOS geometry, 0x0001 - 1GB, 0x0010 - 2GB, + * 0x1000 - 8GB, Others values are invalid + * @unused : bits 4-7 are unused + * @boot_drv : logical drive set as boot drive, 0..7 - for 8LD cards, + * 0..39 - for 40LD cards + * @cksum : 0-(sum of first 13 bytes of this structure) + */ +struct private_bios_data { + uint8_t geometry :4; + uint8_t unused :4; + uint8_t boot_drv; + uint8_t rsvd[12]; + uint16_t cksum; +} __attribute__ ((packed)); + + +/** + * mbox_sgl64 - 64-bit scatter list for mailbox based controllers + * @address : address of the buffer + * @length : data transfer length + */ +typedef struct { + uint64_t address; + uint32_t length; +} __attribute__ ((packed)) mbox_sgl64; + +/** + * mbox_sgl32 - 32-bit scatter list for mailbox based controllers + * @address : address of the buffer + * @length : data transfer length + */ +typedef struct { + uint32_t address; + uint32_t length; +} __attribute__ ((packed)) mbox_sgl32; + + +#undef wait_event +#define wait_event mraid_mm_diskdump_wait_event +#undef wake_up +#define wake_up mraid_mm_diskdump_wake_up +extern void mraid_mm_diskdump_schedule(void); +extern void mraid_mm_diskdump_wake_up(wait_queue_head_t *q); + + +#define __mraid_mm_diskdump_wait_event(wq, condition) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_UNINTERRUPTIBLE); \ + if (condition) \ + break; \ + mraid_mm_diskdump_schedule(); \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#define mraid_mm_diskdump_wait_event(wq, condition) \ +do { \ + if (condition) \ + break; \ + __mraid_mm_diskdump_wait_event(wq, condition); \ +} while (0) + + +#endif // _MRAID_MBOX_DEFS_H_ + +/* vim: set ts=8 sw=8 tw=78: */ diff --git a/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/mega_common.h b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/mega_common.h new file mode 100644 index 0000000..e8de441 --- /dev/null +++ b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/mega_common.h @@ -0,0 +1,290 @@ +/* + * + * Linux MegaRAID device driver + * + * Copyright (c) 2003-2004 LSI Logic Corporation. + * + * 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. + * + * FILE : mega_common.h + * + * Libaray of common routine used by all low-level megaraid drivers + */ + +#ifndef _MEGA_COMMON_H_ +#define _MEGA_COMMON_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define LSI_MAX_CHANNELS 16 +#define LSI_MAX_LOGICAL_DRIVES_64LD (64+1) + +#define HBA_SIGNATURE_64BIT 0x0299 +#define PCI_CONF_AMISIG64 0xa4 + +/** + * scb_t - scsi command control block + * @param ccb : command control block for individual driver + * @param list : list of control blocks + * @param gp : general purpose field for LLDs + * @param sno : all SCBs have a serial number + * @param scp : associated scsi command + * @param state : current state of scb + * @param dma_dir : direction of data transfer + * @param dma_type : transfer with sg list, buffer, or no data transfer + * @param dev_channel : actual channel on the device + * @param dev_target : actual target on the device + * @param status : completion status + * + * This is our central data structure to issue commands the each driver. + * Driver specific data structures are maintained in the ccb field. + * scb provides a field 'gp', which can be used by LLD for its own purposes + * + * dev_channel and dev_target must be initialized with the actual channel and + * target on the controller. + */ +typedef struct { + caddr_t ccb; + struct list_head list; + unsigned long gp; + unsigned int sno; + struct scsi_cmnd *scp; + uint32_t state; + uint32_t dma_direction; + uint32_t dma_type; + uint16_t dev_channel; + uint16_t dev_target; + uint32_t status; +} scb_t; + +/* + * SCB states as it transitions from one state to another + */ +#define SCB_FREE 0x0000 /* on the free list */ +#define SCB_ACTIVE 0x0001 /* off the free list */ +#define SCB_PENDQ 0x0002 /* on the pending queue */ +#define SCB_ISSUED 0x0004 /* issued - owner f/w */ +#define SCB_ABORT 0x0008 /* Got an abort for this one */ +#define SCB_RESET 0x0010 /* Got a reset for this one */ + +/* + * DMA types for scb + */ +#define MRAID_DMA_NONE 0x0000 /* no data transfer for this command */ +#define MRAID_DMA_WSG 0x0001 /* data transfer using a sg list */ +#define MRAID_DMA_WBUF 0x0002 /* data transfer using a contiguous buffer */ + + +/** + * struct adapter_t - driver's initialization structure + * @param dpc_h : tasklet handle + * @param pdev : pci configuration pointer for kernel + * @param host : pointer to host structure of mid-layer + * @param host_lock : pointer to appropriate lock + * @param lock : synchronization lock for mid-layer and driver + * @param quiescent : driver is quiescent for now. + * @param outstanding_cmds : number of commands pending in the driver + * @param kscb_list : pointer to the bulk of SCBs pointers for IO + * @param kscb_pool : pool of free scbs for IO + * @param kscb_pool_lock : lock for pool of free scbs + * @param pend_list : pending commands list + * @param pend_list_lock : exlusion lock for pending commands list + * @param completed_list : list of completed commands + * @param completed_list_lock : exclusion lock for list of completed commands + * @param sglen : max sg elements supported + * @param device_ids : to convert kernel device addr to our devices. + * @param raid_device : raid adapter specific pointer + * @param max_channel : maximum channel number supported - inclusive + * @param max_target : max target supported - inclusive + * @param max_lun : max lun supported - inclusive + * @param unique_id : unique identifier for each adapter + * @param irq : IRQ for this adapter + * @param ito : internal timeout value, (-1) means no timeout + * @param ibuf : buffer to issue internal commands + * @param ibuf_dma_h : dma handle for the above buffer + * @param uscb_list : SCB pointers for user cmds, common mgmt module + * @param uscb_pool : pool of SCBs for user commands + * @param uscb_pool_lock : exclusion lock for these SCBs + * @param max_cmds : max outstanding commands + * @param fw_version : firmware version + * @param bios_version : bios version + * @param max_cdb_sz : biggest CDB size supported. + * @param ha : is high availability present - clustering + * @param init_id : initiator ID, the default value should be 7 + * @param max_sectors : max sectors per request + * @param cmd_per_lun : max outstanding commands per LUN + * @param being_detached : set when unloading, no more mgmt calls + * + * + * mraid_setup_device_map() can be called anytime after the device map is + * available and MRAID_GET_DEVICE_MAP() can be called whenever the mapping is + * required, usually from LLD's queue entry point. The formar API sets up the + * MRAID_IS_LOGICAL(adapter_t *, struct scsi_cmnd *) to find out if the + * device in question is a logical drive. + * + * quiescent flag should be set by the driver if it is not accepting more + * commands + * + * NOTE: The fields of this structures are placed to minimize cache misses + */ + +// amount of space required to store the bios and firmware version strings +#define VERSION_SIZE 16 + +typedef struct { + struct tasklet_struct dpc_h; + struct pci_dev *pdev; + struct Scsi_Host *host; + spinlock_t *host_lock; + spinlock_t lock; + uint8_t quiescent; + int outstanding_cmds; + scb_t *kscb_list; + struct list_head kscb_pool; + spinlock_t kscb_pool_lock; + struct list_head pend_list; + spinlock_t pend_list_lock; + struct list_head completed_list; + spinlock_t completed_list_lock; + uint16_t sglen; + int device_ids[LSI_MAX_CHANNELS] + [LSI_MAX_LOGICAL_DRIVES_64LD]; + caddr_t raid_device; + uint8_t max_channel; + uint16_t max_target; + uint8_t max_lun; + + uint32_t unique_id; + uint8_t irq; + uint8_t ito; + caddr_t ibuf; + dma_addr_t ibuf_dma_h; + scb_t *uscb_list; + struct list_head uscb_pool; + spinlock_t uscb_pool_lock; + int max_cmds; + uint8_t fw_version[VERSION_SIZE]; + uint8_t bios_version[VERSION_SIZE]; + uint8_t max_cdb_sz; + uint8_t ha; + uint16_t init_id; + uint16_t max_sectors; + uint16_t cmd_per_lun; + atomic_t being_detached; +} adapter_t; + +#define SCSI_FREE_LIST_LOCK(adapter) (&adapter->kscb_pool_lock) +#define USER_FREE_LIST_LOCK(adapter) (&adapter->uscb_pool_lock) +#define PENDING_LIST_LOCK(adapter) (&adapter->pend_list_lock) +#define COMPLETED_LIST_LOCK(adapter) (&adapter->completed_list_lock) + + +// conversion from scsi command +#define SCP2HOST(scp) (scp)->device->host // to host +#define SCP2HOSTDATA(scp) SCP2HOST(scp)->hostdata // to soft state +#define SCP2CHANNEL(scp) (scp)->device->channel // to channel +#define SCP2TARGET(scp) (scp)->device->id // to target +#define SCP2LUN(scp) (scp)->device->lun // to LUN + +// generic macro to convert scsi command and host to controller's soft state +#define SCSIHOST2ADAP(host) (((caddr_t *)(host->hostdata))[0]) +#define SCP2ADAPTER(scp) (adapter_t *)SCSIHOST2ADAP(SCP2HOST(scp)) + + +/** + * MRAID_GET_DEVICE_MAP - device ids + * @param adp - Adapter's soft state + * @param scp - mid-layer scsi command pointer + * @param p_chan - physical channel on the controller + * @param target - target id of the device or logical drive number + * @param islogical - set if the command is for the logical drive + * + * Macro to retrieve information about device class, logical or physical and + * the corresponding physical channel and target or logical drive number + **/ +#define MRAID_IS_LOGICAL(adp, scp) \ + (SCP2CHANNEL(scp) == (adp)->max_channel) ? 1 : 0 + +#define MRAID_IS_LOGICAL_SDEV(adp, sdev) \ + (sdev->channel == (adp)->max_channel) ? 1 : 0 + +#define MRAID_GET_DEVICE_MAP(adp, scp, p_chan, target, islogical) \ + /* \ + * Is the request coming for the virtual channel \ + */ \ + islogical = MRAID_IS_LOGICAL(adp, scp); \ + \ + /* \ + * Get an index into our table of drive ids mapping \ + */ \ + if (islogical) { \ + p_chan = 0xFF; \ + target = \ + (adp)->device_ids[(adp)->max_channel][SCP2TARGET(scp)]; \ + } \ + else { \ + p_chan = ((adp)->device_ids[SCP2CHANNEL(scp)] \ + [SCP2TARGET(scp)] >> 8) & 0xFF; \ + target = ((adp)->device_ids[SCP2CHANNEL(scp)] \ + [SCP2TARGET(scp)] & 0xFF); \ + } + +/* + * ### Helper routines ### + */ +#define LSI_DBGLVL mraid_debug_level // each LLD must define a global + // mraid_debug_level + +#ifdef DEBUG +#if defined (_ASSERT_PANIC) +#define ASSERT_ACTION panic +#else +#define ASSERT_ACTION printk +#endif + +#define ASSERT(expression) \ + if (!(expression)) { \ + ASSERT_ACTION("assertion failed:(%s), file: %s, line: %d:%s\n", \ + #expression, __FILE__, __LINE__, __FUNCTION__); \ + } +#else +#define ASSERT(expression) +#endif + +/* + * struct mraid_pci_blk - structure holds DMA memory block info + * @param vaddr : virtual address to a memory block + * @param dma_addr : DMA handle to a memory block + * + * This structure is filled up for the caller. It is the responsibilty of the + * caller to allocate this array big enough to store addresses for all + * requested elements + */ +struct mraid_pci_blk { + caddr_t vaddr; + dma_addr_t dma_addr; +}; + +#endif // _MEGA_COMMON_H_ + +// vim: set ts=8 sw=8 tw=78: diff --git a/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_ioctl.h b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_ioctl.h new file mode 100644 index 0000000..b8aa342 --- /dev/null +++ b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_ioctl.h @@ -0,0 +1,300 @@ +/* + * + * Linux MegaRAID device driver + * + * Copyright (c) 2003-2004 LSI Logic Corporation. + * + * 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. + * + * FILE : megaraid_ioctl.h + * + * Definitions to interface with user level applications + */ + +#ifndef _MEGARAID_IOCTL_H_ +#define _MEGARAID_IOCTL_H_ + +#include +#include + +#include "mbox_defs.h" + +/** + * con_log() - console log routine + * @param level : indicates the severity of the message. + * @fparam mt : format string + * + * con_log displays the error messages on the console based on the current + * debug level. Also it attaches the appropriate kernel severity level with + * the message. + * + * + * consolge messages debug levels + */ +#define CL_ANN 0 /* print unconditionally, announcements */ +#define CL_DLEVEL1 1 /* debug level 1, informative */ +#define CL_DLEVEL2 2 /* debug level 2, verbose */ +#define CL_DLEVEL3 3 /* debug level 3, very verbose */ + +#define con_log(level, fmt) if (LSI_DBGLVL >= level) printk fmt; + +/* + * Definitions & Declarations needed to use common management module + */ + +#define MEGAIOC_MAGIC 'm' +#define MEGAIOCCMD _IOWR(MEGAIOC_MAGIC, 0, mimd_t) + +#define MEGAIOC_QNADAP 'm' /* Query # of adapters */ +#define MEGAIOC_QDRVRVER 'e' /* Query driver version */ +#define MEGAIOC_QADAPINFO 'g' /* Query adapter information */ + +#define USCSICMD 0x80 +#define UIOC_RD 0x00001 +#define UIOC_WR 0x00002 + +#define MBOX_CMD 0x00000 +#define GET_DRIVER_VER 0x10000 +#define GET_N_ADAP 0x20000 +#define GET_ADAP_INFO 0x30000 +#define GET_CAP 0x40000 +#define GET_STATS 0x50000 +#define GET_IOCTL_VERSION 0x01 + +#define EXT_IOCTL_SIGN_SZ 16 +#define EXT_IOCTL_SIGN "$$_EXTD_IOCTL_$$" + +#define MBOX_LEGACY 0x00 /* ioctl has legacy mbox*/ +#define MBOX_HPE 0x01 /* ioctl has hpe mbox */ + +#define APPTYPE_MIMD 0x00 /* old existing apps */ +#define APPTYPE_UIOC 0x01 /* new apps using uioc */ + +#define IOCTL_ISSUE 0x00000001 /* Issue ioctl */ +#define IOCTL_ABORT 0x00000002 /* Abort previous ioctl */ + +#define DRVRTYPE_MBOX 0x00000001 /* regular mbox driver */ +#define DRVRTYPE_HPE 0x00000002 /* new hpe driver */ + +#define MKADAP(adapno) (MEGAIOC_MAGIC << 8 | (adapno) ) +#define GETADAP(mkadap) ((mkadap) ^ MEGAIOC_MAGIC << 8) + +#define MAX_DMA_POOLS 5 /* 4k, 8k, 16k, 32k, 64k*/ + + +/** + * struct uioc_t - the common ioctl packet structure + * + * @signature : Must be "$$_EXTD_IOCTL_$$" + * @mb_type : Type of the mail box (MB_LEGACY or MB_HPE) + * @app_type : Type of the issuing application (existing or new) + * @opcode : Opcode of the command + * @adapno : Adapter number + * @cmdbuf : Pointer to buffer - can point to mbox or plain data buffer + * @xferlen : xferlen for DCMD and non mailbox commands + * @data_dir : Direction of the data transfer + * @status : Status from the driver + * @reserved : reserved bytes for future expansion + * + * @user_data : user data transfer address is saved in this + * @user_data_len: length of the data buffer sent by user app + * @user_pthru : user passthru address is saves in this (null if DCMD) + * @pthru32 : kernel address passthru (allocated per kioc) + * @pthru32_h : physicall address of @pthru32 + * @list : for kioc free pool list maintenance + * @done : call back routine for llds to call when kioc is completed + * @buf_vaddr : dma pool buffer attached to kioc for data transfer + * @buf_paddr : physical address of the dma pool buffer + * @pool_index : index of the dma pool that @buf_vaddr is taken from + * @free_buf : indicates if buffer needs to be freed after kioc completes + * + * Note : All LSI drivers understand only this packet. Any other + * : format sent by applications would be converted to this. + */ +typedef struct uioc { + +/* User Apps: */ + + uint8_t signature[EXT_IOCTL_SIGN_SZ]; + uint16_t mb_type; + uint16_t app_type; + uint32_t opcode; + uint32_t adapno; + uint64_t cmdbuf; + uint32_t xferlen; + uint32_t data_dir; + int32_t status; + uint8_t reserved[128]; + +/* Driver Data: */ + void __user * user_data; + uint32_t user_data_len; + + /* 64bit alignment */ + uint32_t pad_for_64bit_align; + + mraid_passthru_t __user *user_pthru; + + mraid_passthru_t *pthru32; + dma_addr_t pthru32_h; + + struct list_head list; + void (*done)(struct uioc*); + + caddr_t buf_vaddr; + dma_addr_t buf_paddr; + int8_t pool_index; + uint8_t free_buf; + + uint8_t timedout; + +} __attribute__ ((aligned(1024),packed)) uioc_t; + + +/** + * struct mraid_hba_info - information about the controller + * + * @param pci_vendor_id : PCI vendor id + * @param pci_device_id : PCI device id + * @param subsystem_vendor_id : PCI subsystem vendor id + * @param subsystem_device_id : PCI subsystem device id + * @param baseport : base port of hba memory + * @param pci_bus : PCI bus + * @param pci_dev_fn : PCI device/function values + * @param irq : interrupt vector for the device + * + * Extended information of 256 bytes about the controller. Align on the single + * byte boundary so that 32-bit applications can be run on 64-bit platform + * drivers withoug re-compilation. + * NOTE: reduce the number of reserved bytes whenever new field are added, so + * that total size of the structure remains 256 bytes. + */ +typedef struct mraid_hba_info { + + uint16_t pci_vendor_id; + uint16_t pci_device_id; + uint16_t subsys_vendor_id; + uint16_t subsys_device_id; + + uint64_t baseport; + uint8_t pci_bus; + uint8_t pci_dev_fn; + uint8_t pci_slot; + uint8_t irq; + + uint32_t unique_id; + uint32_t host_no; + + uint8_t num_ldrv; +} __attribute__ ((aligned(256), packed)) mraid_hba_info_t; + + +/** + * mcontroller : adapter info structure for old mimd_t apps + * + * @base : base address + * @irq : irq number + * @numldrv : number of logical drives + * @pcibus : pci bus + * @pcidev : pci device + * @pcifun : pci function + * @pciid : pci id + * @pcivendor : vendor id + * @pcislot : slot number + * @uid : unique id + */ +typedef struct mcontroller { + + uint64_t base; + uint8_t irq; + uint8_t numldrv; + uint8_t pcibus; + uint16_t pcidev; + uint8_t pcifun; + uint16_t pciid; + uint16_t pcivendor; + uint8_t pcislot; + uint32_t uid; + +} __attribute__ ((packed)) mcontroller_t; + + +/** + * mm_dmapool_t : Represents one dma pool with just one buffer + * + * @vaddr : Virtual address + * @paddr : DMA physicall address + * @bufsize : In KB - 4 = 4k, 8 = 8k etc. + * @handle : Handle to the dma pool + * @lock : lock to synchronize access to the pool + * @in_use : If pool already in use, attach new block + */ +typedef struct mm_dmapool { + caddr_t vaddr; + dma_addr_t paddr; + uint32_t buf_size; + struct dma_pool *handle; + spinlock_t lock; + uint8_t in_use; +} mm_dmapool_t; + + +/** + * mraid_mmadp_t: Structure that drivers pass during (un)registration + * + * @unique_id : Any unique id (usually PCI bus+dev+fn) + * @drvr_type : megaraid or hpe (DRVRTYPE_MBOX or DRVRTYPE_HPE) + * @drv_data : Driver specific; not touched by the common module + * @timeout : timeout for issued kiocs + * @max_kioc : Maximum ioctl packets acceptable by the lld + * @pdev : pci dev; used for allocating dma'ble memory + * @issue_uioc : Driver supplied routine to issue uioc_t commands + * : issue_uioc(drvr_data, kioc, ISSUE/ABORT, uioc_done) + * @quiescent : flag to indicate if ioctl can be issued to this adp + * @list : attach with the global list of adapters + * @kioc_list : block of mem for @max_kioc number of kiocs + * @kioc_pool : pool of free kiocs + * @kioc_pool_lock : protection for free pool + * @kioc_semaphore : so as not to exceed @max_kioc parallel ioctls + * @mbox_list : block of mem for @max_kioc number of mboxes + * @pthru_dma_pool : DMA pool to allocate passthru packets + * @dma_pool_list : array of dma pools + */ + +typedef struct mraid_mmadp { + +/* Filled by driver */ + + uint32_t unique_id; + uint32_t drvr_type; + unsigned long drvr_data; + uint16_t timeout; + uint8_t max_kioc; + + struct pci_dev *pdev; + + int(*issue_uioc)(unsigned long, uioc_t *, uint32_t); + +/* Maintained by common module */ + uint32_t quiescent; + + struct list_head list; + uioc_t *kioc_list; + struct list_head kioc_pool; + spinlock_t kioc_pool_lock; + struct semaphore kioc_semaphore; + + mbox64_t *mbox_list; + struct dma_pool *pthru_dma_pool; + mm_dmapool_t dma_pool_list[MAX_DMA_POOLS]; + +} mraid_mmadp_t; + +int mraid_mm_register_adp(mraid_mmadp_t *); +int mraid_mm_unregister_adp(uint32_t); +uint32_t mraid_mm_adapter_app_handle(uint32_t); + +#endif /* _MEGARAID_IOCTL_H_ */ diff --git a/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_mbox.c b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_mbox.c new file mode 100644 index 0000000..8cf8aa3 --- /dev/null +++ b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_mbox.c @@ -0,0 +1,4330 @@ +/* + * + * Linux MegaRAID device driver + * + * Copyright (c) 2003-2004 LSI Logic Corporation. + * + * 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. + * + * FILE : megaraid_mbox.c + * Version : v2.20.4.6-rh2 (Jun 28 2006) + * + * Authors: + * Atul Mukker + * Sreenivas Bagalkote + * Manoj Jose + * + * List of supported controllers + * + * OEM Product Name VID DID SSVID SSID + * --- ------------ --- --- ---- ---- + * Dell PERC3/QC 101E 1960 1028 0471 + * Dell PERC3/DC 101E 1960 1028 0493 + * Dell PERC3/SC 101E 1960 1028 0475 + * Dell PERC3/Di 1028 1960 1028 0123 + * Dell PERC4/SC 1000 1960 1028 0520 + * Dell PERC4/DC 1000 1960 1028 0518 + * Dell PERC4/QC 1000 0407 1028 0531 + * Dell PERC4/Di 1028 000F 1028 014A + * Dell PERC 4e/Si 1028 0013 1028 016c + * Dell PERC 4e/Di 1028 0013 1028 016d + * Dell PERC 4e/Di 1028 0013 1028 016e + * Dell PERC 4e/Di 1028 0013 1028 016f + * Dell PERC 4e/Di 1028 0013 1028 0170 + * Dell PERC 4e/DC 1000 0408 1028 0002 + * Dell PERC 4e/SC 1000 0408 1028 0001 + * + * + * LSI MegaRAID SCSI 320-0 1000 1960 1000 A520 + * LSI MegaRAID SCSI 320-1 1000 1960 1000 0520 + * LSI MegaRAID SCSI 320-2 1000 1960 1000 0518 + * LSI MegaRAID SCSI 320-0X 1000 0407 1000 0530 + * LSI MegaRAID SCSI 320-2X 1000 0407 1000 0532 + * LSI MegaRAID SCSI 320-4X 1000 0407 1000 0531 + * LSI MegaRAID SCSI 320-1E 1000 0408 1000 0001 + * LSI MegaRAID SCSI 320-2E 1000 0408 1000 0002 + * LSI MegaRAID SATA 150-4 1000 1960 1000 4523 + * LSI MegaRAID SATA 150-6 1000 1960 1000 0523 + * LSI MegaRAID SATA 300-4X 1000 0409 1000 3004 + * LSI MegaRAID SATA 300-8X 1000 0409 1000 3008 + * + * INTEL RAID Controller SRCU42X 1000 0407 8086 0532 + * INTEL RAID Controller SRCS16 1000 1960 8086 0523 + * INTEL RAID Controller SRCU42E 1000 0408 8086 0002 + * INTEL RAID Controller SRCZCRX 1000 0407 8086 0530 + * INTEL RAID Controller SRCS28X 1000 0409 8086 3008 + * INTEL RAID Controller SROMBU42E 1000 0408 8086 3431 + * INTEL RAID Controller SROMBU42E 1000 0408 8086 3499 + * INTEL RAID Controller SRCU51L 1000 1960 8086 0520 + * + * FSC MegaRAID PCI Express ROMB 1000 0408 1734 1065 + * + * ACER MegaRAID ROMB-2E 1000 0408 1025 004D + * + * NEC MegaRAID PCI Express ROMB 1000 0408 1033 8287 + * + * For history of changes, see Documentation/ChangeLog.megaraid + */ + +#include "megaraid_mbox.h" + +#undef msleep +#define msleep(X) \ +if (crashdump_mode()) { \ + megaraid_diskdump_sleep(X); \ +} else { \ + msleep(X); \ +} + +static int megaraid_init(void); +static void megaraid_exit(void); + +static int megaraid_probe_one(struct pci_dev*, const struct pci_device_id *); +static void megaraid_detach_one(struct pci_dev *); +static void megaraid_mbox_shutdown(struct device *); + +static int megaraid_io_attach(adapter_t *); +static void megaraid_io_detach(adapter_t *); + +static int megaraid_init_mbox(adapter_t *); +static void megaraid_fini_mbox(adapter_t *); + +static int megaraid_alloc_cmd_packets(adapter_t *); +static void megaraid_free_cmd_packets(adapter_t *); + +static int megaraid_mbox_setup_dma_pools(adapter_t *); +static void megaraid_mbox_teardown_dma_pools(adapter_t *); + +static int megaraid_sysfs_alloc_resources(adapter_t *); +static void megaraid_sysfs_free_resources(adapter_t *); + +static int megaraid_abort_handler(struct scsi_cmnd *); +static int megaraid_reset_handler(struct scsi_cmnd *); + +static int mbox_post_sync_cmd(adapter_t *, uint8_t []); +static int mbox_post_sync_cmd_fast(adapter_t *, uint8_t []); +static int megaraid_busywait_mbox(mraid_device_t *); +static int megaraid_mbox_product_info(adapter_t *); +static int megaraid_mbox_extended_cdb(adapter_t *); +static int megaraid_mbox_support_ha(adapter_t *, uint16_t *); +static int megaraid_mbox_support_random_del(adapter_t *); +static int megaraid_mbox_get_max_sg(adapter_t *); +static void megaraid_mbox_enum_raid_scsi(adapter_t *); +static void megaraid_mbox_flush_cache(adapter_t *); + +static void megaraid_mbox_display_scb(adapter_t *, scb_t *); +static void megaraid_mbox_setup_device_map(adapter_t *); + +static int megaraid_queue_command(struct scsi_cmnd *, + void (*)(struct scsi_cmnd *)); +static scb_t *megaraid_mbox_build_cmd(adapter_t *, struct scsi_cmnd *, int *); +static void megaraid_mbox_runpendq(adapter_t *, scb_t *); +static void megaraid_mbox_prepare_pthru(adapter_t *, scb_t *, + struct scsi_cmnd *); +static void megaraid_mbox_prepare_epthru(adapter_t *, scb_t *, + struct scsi_cmnd *); + +static irqreturn_t megaraid_isr(int, void *, struct pt_regs *); + +static void megaraid_mbox_dpc(unsigned long); + +static ssize_t megaraid_sysfs_show_app_hndl(struct class_device *, char *); +static ssize_t megaraid_sysfs_show_ldnum(struct device *, char *); + +static int megaraid_cmm_register(adapter_t *); +static int megaraid_cmm_unregister(adapter_t *); +static int megaraid_mbox_mm_handler(unsigned long, uioc_t *, uint32_t); +static int megaraid_mbox_mm_command(adapter_t *, uioc_t *); +static void megaraid_mbox_mm_done(adapter_t *, scb_t *); +static int gather_hbainfo(adapter_t *, mraid_hba_info_t *); +static int wait_till_fw_empty(adapter_t *); + +static int megaraid_sanity_check(struct scsi_device *device); +static int megaraid_quiesce(struct scsi_device *device); +static void megaraid_poll(struct scsi_device *device); +static void megaraid_diskdump_sleep(unsigned int timeout); + + +extern int mraid_mm_woken; + + +MODULE_AUTHOR("LSI Logic Corporation"); +MODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(MEGARAID_VERSION); + +/* + * ### modules parameters for driver ### + */ + +/** + * Set to enable driver to expose unconfigured disk to kernel + */ +static int megaraid_expose_unconf_disks = 0; +module_param_named(unconf_disks, megaraid_expose_unconf_disks, int, 0); +MODULE_PARM_DESC(unconf_disks, + "Set to expose unconfigured disks to kernel (default=0)"); + +/** + * driver wait time if the adapter's mailbox is busy + */ +static unsigned int max_mbox_busy_wait = MBOX_BUSY_WAIT; +module_param_named(busy_wait, max_mbox_busy_wait, int, 0); +MODULE_PARM_DESC(busy_wait, + "Max wait for mailbox in microseconds if busy (default=10)"); + +/** + * number of sectors per IO command + */ +static unsigned int megaraid_max_sectors = MBOX_MAX_SECTORS; +module_param_named(max_sectors, megaraid_max_sectors, int, 0); +MODULE_PARM_DESC(max_sectors, + "Maximum number of sectors per IO command (default=128)"); + +/** + * number of commands per logical unit + */ +static unsigned int megaraid_cmd_per_lun = MBOX_DEF_CMD_PER_LUN; +module_param_named(cmd_per_lun, megaraid_cmd_per_lun, int, 0); +MODULE_PARM_DESC(cmd_per_lun, + "Maximum number of commands per logical unit (default=64)"); + + +/** + * Fast driver load option, skip scanning for physical devices during load. + * This would result in non-disk devices being skipped during driver load + * time. These can be later added though, using /proc/scsi/scsi + */ +static unsigned int megaraid_fast_load = 0; +module_param_named(fast_load, megaraid_fast_load, int, 0); +MODULE_PARM_DESC(fast_load, + "Faster loading of the driver, skips physical devices! (default=0)"); + + +/** + * mraid_debug level - threshold for amount of information to be displayed by + * the driver. This level can be changed through modules parameters, ioctl or + * sysfs/proc interface. By default, print the announcement messages only. + */ +int mraid_debug_level = CL_ANN; +module_param_named(debug_level, mraid_debug_level, int, 0); +MODULE_PARM_DESC(debug_level, "Debug level for driver (default=0)"); + +/* + * ### global data ### + */ +static uint8_t megaraid_mbox_version[8] = + { 0x02, 0x20, 0x04, 0x06, 3, 7, 20, 5 }; + + +/* + * PCI table for all supported controllers. + */ +static struct pci_device_id pci_id_table_g[] = { + { + PCI_VENDOR_ID_DELL, + PCI_DEVICE_ID_PERC4_DI_DISCOVERY, + PCI_VENDOR_ID_DELL, + PCI_SUBSYS_ID_PERC4_DI_DISCOVERY, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_PERC4_SC, + PCI_VENDOR_ID_DELL, + PCI_SUBSYS_ID_PERC4_SC, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_PERC4_DC, + PCI_VENDOR_ID_DELL, + PCI_SUBSYS_ID_PERC4_DC, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_VERDE, + PCI_ANY_ID, + PCI_ANY_ID, + }, + { + PCI_VENDOR_ID_DELL, + PCI_DEVICE_ID_PERC4_DI_EVERGLADES, + PCI_VENDOR_ID_DELL, + PCI_SUBSYS_ID_PERC4_DI_EVERGLADES, + }, + { + PCI_VENDOR_ID_DELL, + PCI_DEVICE_ID_PERC4E_SI_BIGBEND, + PCI_VENDOR_ID_DELL, + PCI_SUBSYS_ID_PERC4E_SI_BIGBEND, + }, + { + PCI_VENDOR_ID_DELL, + PCI_DEVICE_ID_PERC4E_DI_KOBUK, + PCI_VENDOR_ID_DELL, + PCI_SUBSYS_ID_PERC4E_DI_KOBUK, + }, + { + PCI_VENDOR_ID_DELL, + PCI_DEVICE_ID_PERC4E_DI_CORVETTE, + PCI_VENDOR_ID_DELL, + PCI_SUBSYS_ID_PERC4E_DI_CORVETTE, + }, + { + PCI_VENDOR_ID_DELL, + PCI_DEVICE_ID_PERC4E_DI_EXPEDITION, + PCI_VENDOR_ID_DELL, + PCI_SUBSYS_ID_PERC4E_DI_EXPEDITION, + }, + { + PCI_VENDOR_ID_DELL, + PCI_DEVICE_ID_PERC4E_DI_GUADALUPE, + PCI_VENDOR_ID_DELL, + PCI_SUBSYS_ID_PERC4E_DI_GUADALUPE, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_DOBSON, + PCI_ANY_ID, + PCI_ANY_ID, + }, + { + PCI_VENDOR_ID_AMI, + PCI_DEVICE_ID_AMI_MEGARAID3, + PCI_VENDOR_ID_DELL, + PCI_SUBSYS_ID_PERC3_QC, + }, + { + PCI_VENDOR_ID_AMI, + PCI_DEVICE_ID_AMI_MEGARAID3, + PCI_VENDOR_ID_DELL, + PCI_SUBSYS_ID_PERC3_DC, + }, + { + PCI_VENDOR_ID_AMI, + PCI_DEVICE_ID_AMI_MEGARAID3, + PCI_VENDOR_ID_DELL, + PCI_SUBSYS_ID_PERC3_SC, + }, + { + PCI_VENDOR_ID_AMI, + PCI_DEVICE_ID_AMI_MEGARAID3, + PCI_VENDOR_ID_AMI, + PCI_SUBSYS_ID_PERC3_SC, + }, + { + PCI_VENDOR_ID_AMI, + PCI_DEVICE_ID_AMI_MEGARAID3, + PCI_VENDOR_ID_AMI, + PCI_SUBSYS_ID_PERC3_DC, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_MEGARAID_SCSI_320_0, + PCI_VENDOR_ID_LSI_LOGIC, + PCI_SUBSYS_ID_MEGARAID_SCSI_320_0, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_MEGARAID_SCSI_320_1, + PCI_VENDOR_ID_LSI_LOGIC, + PCI_SUBSYS_ID_MEGARAID_SCSI_320_1, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_MEGARAID_SCSI_320_2, + PCI_VENDOR_ID_LSI_LOGIC, + PCI_SUBSYS_ID_MEGARAID_SCSI_320_2, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_MEGARAID_I4_133_RAID, + PCI_VENDOR_ID_LSI_LOGIC, + PCI_SUBSYS_ID_MEGARAID_I4_133_RAID, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_MEGARAID_SATA_150_4, + PCI_VENDOR_ID_LSI_LOGIC, + PCI_SUBSYS_ID_MEGARAID_SATA_150_4, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_MEGARAID_SATA_150_6, + PCI_VENDOR_ID_LSI_LOGIC, + PCI_SUBSYS_ID_MEGARAID_SATA_150_6, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_LINDSAY, + PCI_ANY_ID, + PCI_ANY_ID, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_INTEL_RAID_SRCS16, + PCI_VENDOR_ID_INTEL, + PCI_SUBSYS_ID_INTEL_RAID_SRCS16, + }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK, + PCI_VENDOR_ID_INTEL, + PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK, + }, + {0} /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, pci_id_table_g); + + +static struct pci_driver megaraid_pci_driver_g = { + .name = "megaraid", + .id_table = pci_id_table_g, + .probe = megaraid_probe_one, + .remove = __devexit_p(megaraid_detach_one), + .driver = { + .shutdown = megaraid_mbox_shutdown, + } +}; + + + +// definitions for the device attributes for exporting logical drive number +// for a scsi address (Host, Channel, Id, Lun) + +CLASS_DEVICE_ATTR(megaraid_mbox_app_hndl, S_IRUSR, megaraid_sysfs_show_app_hndl, + NULL); + +// Host template initializer for megaraid mbox sysfs device attributes +static struct class_device_attribute *megaraid_shost_attrs[] = { + &class_device_attr_megaraid_mbox_app_hndl, + NULL, +}; + + +DEVICE_ATTR(megaraid_mbox_ld, S_IRUSR, megaraid_sysfs_show_ldnum, NULL); + +// Host template initializer for megaraid mbox sysfs device attributes +static struct device_attribute *megaraid_sdev_attrs[] = { + &dev_attr_megaraid_mbox_ld, + NULL, +}; + + +/* + * Scsi host template for megaraid unified driver + */ +static struct scsi_host_template megaraid_template_g = { + .module = THIS_MODULE, + .name = "LSI Logic MegaRAID driver", + .proc_name = "megaraid", + .queuecommand = megaraid_queue_command, + .eh_abort_handler = megaraid_abort_handler, + .eh_device_reset_handler = megaraid_reset_handler, + .eh_bus_reset_handler = megaraid_reset_handler, + .eh_host_reset_handler = megaraid_reset_handler, + .use_clustering = ENABLE_CLUSTERING, + .sdev_attrs = megaraid_sdev_attrs, + .shost_attrs = megaraid_shost_attrs, + .dump_sanity_check = megaraid_sanity_check, + .dump_quiesce = megaraid_quiesce, + .dump_poll = megaraid_poll, +}; + + +/** + * megaraid_init - module load hook + * + * We register ourselves as hotplug enabled module and let PCI subsystem + * discover our adaters + **/ +static int __init +megaraid_init(void) +{ + int rval; + + // Announce the driver version + con_log(CL_ANN, (KERN_INFO "megaraid: %s %s\n", MEGARAID_VERSION, + MEGARAID_EXT_VERSION)); + + // check validity of module parameters + if (megaraid_cmd_per_lun > MBOX_MAX_SCSI_CMDS) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid mailbox: max commands per lun reset to %d\n", + MBOX_MAX_SCSI_CMDS)); + + megaraid_cmd_per_lun = MBOX_MAX_SCSI_CMDS; + } + + + // register as a PCI hot-plug driver module + rval = pci_register_driver(&megaraid_pci_driver_g); + if (rval < 0) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: could not register hotplug support.\n")); + } + + return rval; +} + + +/** + * megaraid_exit - driver unload entry point + * + * We simply unwrap the megaraid_init routine here + */ +static void __exit +megaraid_exit(void) +{ + con_log(CL_DLEVEL1, (KERN_NOTICE "megaraid: unloading framework\n")); + + // unregister as PCI hotplug driver + pci_unregister_driver(&megaraid_pci_driver_g); + + return; +} + + +/** + * megaraid_probe_one - PCI hotplug entry point + * @param pdev : handle to this controller's PCI configuration space + * @param id : pci device id of the class of controllers + * + * This routine should be called whenever a new adapter is detected by the + * PCI hotplug susbsytem. + **/ +static int __devinit +megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + adapter_t *adapter; + + + // detected a new controller + con_log(CL_ANN, (KERN_INFO + "megaraid: probe new device %#4.04x:%#4.04x:%#4.04x:%#4.04x: ", + pdev->vendor, pdev->device, pdev->subsystem_vendor, + pdev->subsystem_device)); + + con_log(CL_ANN, ("bus %d:slot %d:func %d\n", pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn))); + + if (pci_enable_device(pdev)) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: pci_enable_device failed\n")); + + return -ENODEV; + } + + // Enable bus-mastering on this controller + pci_set_master(pdev); + + // Allocate the per driver initialization structure + adapter = kmalloc(sizeof(adapter_t), GFP_KERNEL); + + if (adapter == NULL) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: out of memory, %s %d.\n", __FUNCTION__, __LINE__)); + + goto out_probe_one; + } + memset(adapter, 0, sizeof(adapter_t)); + + + // set up PCI related soft state and other pre-known parameters + adapter->unique_id = pdev->bus->number << 8 | pdev->devfn; + adapter->irq = pdev->irq; + adapter->pdev = pdev; + + atomic_set(&adapter->being_detached, 0); + + // Setup the default DMA mask. This would be changed later on + // depending on hardware capabilities + if (pci_set_dma_mask(adapter->pdev, DMA_32BIT_MASK) != 0) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid: pci_set_dma_mask failed:%d\n", __LINE__)); + + goto out_free_adapter; + } + + + // Initialize the synchronization lock for kernel and LLD + spin_lock_init(&adapter->lock); + adapter->host_lock = &adapter->lock; + + + // Initialize the command queues: the list of free SCBs and the list + // of pending SCBs. + INIT_LIST_HEAD(&adapter->kscb_pool); + spin_lock_init(SCSI_FREE_LIST_LOCK(adapter)); + + INIT_LIST_HEAD(&adapter->pend_list); + spin_lock_init(PENDING_LIST_LOCK(adapter)); + + INIT_LIST_HEAD(&adapter->completed_list); + spin_lock_init(COMPLETED_LIST_LOCK(adapter)); + + + // Start the mailbox based controller + if (megaraid_init_mbox(adapter) != 0) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: maibox adapter did not initialize\n")); + + goto out_free_adapter; + } + + // Register with LSI Common Management Module + if (megaraid_cmm_register(adapter) != 0) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid: could not register with management module\n")); + + goto out_fini_mbox; + } + + // setup adapter handle in PCI soft state + pci_set_drvdata(pdev, adapter); + + // attach with scsi mid-layer + if (megaraid_io_attach(adapter) != 0) { + + con_log(CL_ANN, (KERN_WARNING "megaraid: io attach failed\n")); + + goto out_cmm_unreg; + } + + return 0; + +out_cmm_unreg: + pci_set_drvdata(pdev, NULL); + megaraid_cmm_unregister(adapter); +out_fini_mbox: + megaraid_fini_mbox(adapter); +out_free_adapter: + kfree(adapter); +out_probe_one: + pci_disable_device(pdev); + + return -ENODEV; +} + + +/** + * megaraid_detach_one - release the framework resources and call LLD release + * routine + * @param pdev : handle for our PCI cofiguration space + * + * This routine is called during driver unload. We free all the allocated + * resources and call the corresponding LLD so that it can also release all + * its resources. + * + * This routine is also called from the PCI hotplug system + **/ +static void +megaraid_detach_one(struct pci_dev *pdev) +{ + adapter_t *adapter; + struct Scsi_Host *host; + + + // Start a rollback on this adapter + adapter = pci_get_drvdata(pdev); + + if (!adapter) { + con_log(CL_ANN, (KERN_CRIT + "megaraid: Invalid detach on %#4.04x:%#4.04x:%#4.04x:%#4.04x\n", + pdev->vendor, pdev->device, pdev->subsystem_vendor, + pdev->subsystem_device)); + + return; + } + else { + con_log(CL_ANN, (KERN_NOTICE + "megaraid: detaching device %#4.04x:%#4.04x:%#4.04x:%#4.04x\n", + pdev->vendor, pdev->device, pdev->subsystem_vendor, + pdev->subsystem_device)); + } + + + host = adapter->host; + + // do not allow any more requests from the management module for this + // adapter. + // FIXME: How do we account for the request which might still be + // pending with us? + atomic_set(&adapter->being_detached, 1); + + // detach from the IO sub-system + megaraid_io_detach(adapter); + + // reset the device state in the PCI structure. We check this + // condition when we enter here. If the device state is NULL, + // that would mean the device has already been removed + pci_set_drvdata(pdev, NULL); + + // Unregister from common management module + // + // FIXME: this must return success or failure for conditions if there + // is a command pending with LLD or not. + megaraid_cmm_unregister(adapter); + + // finalize the mailbox based controller and release all resources + megaraid_fini_mbox(adapter); + + kfree(adapter); + + scsi_host_put(host); + + pci_disable_device(pdev); + + return; +} + + +/** + * megaraid_mbox_shutdown - PCI shutdown for megaraid HBA + * @param device : generice driver model device + * + * Shutdown notification, perform flush cache + */ +static void +megaraid_mbox_shutdown(struct device *device) +{ + adapter_t *adapter = pci_get_drvdata(to_pci_dev(device)); + static int counter; + + if (!adapter) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: null device in shutdown\n")); + return; + } + + // flush caches now + con_log(CL_ANN, (KERN_INFO "megaraid: flushing adapter %d...", + counter++)); + + megaraid_mbox_flush_cache(adapter); + + con_log(CL_ANN, ("done\n")); +} + + +/** + * megaraid_io_attach - attach a device with the IO subsystem + * @param adapter : controller's soft state + * + * Attach this device with the IO subsystem + **/ +static int +megaraid_io_attach(adapter_t *adapter) +{ + struct Scsi_Host *host; + + // Initialize SCSI Host structure + host = scsi_host_alloc(&megaraid_template_g, 8); + if (!host) { + con_log(CL_ANN, (KERN_WARNING + "megaraid mbox: scsi_register failed\n")); + + return -1; + } + + SCSIHOST2ADAP(host) = (caddr_t)adapter; + adapter->host = host; + + // export the parameters required by the mid-layer + scsi_assign_lock(host, adapter->host_lock); + scsi_set_device(host, &adapter->pdev->dev); + + host->irq = adapter->irq; + host->unique_id = adapter->unique_id; + host->can_queue = adapter->max_cmds; + host->this_id = adapter->init_id; + host->sg_tablesize = adapter->sglen; + host->max_sectors = adapter->max_sectors; + host->cmd_per_lun = adapter->cmd_per_lun; + host->max_channel = adapter->max_channel; + host->max_id = adapter->max_target; + host->max_lun = adapter->max_lun; + + + // notify mid-layer about the new controller + if (scsi_add_host(host, &adapter->pdev->dev)) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid mbox: scsi_add_host failed\n")); + + scsi_host_put(host); + + return -1; + } + + scsi_scan_host(host); + + return 0; +} + + +/** + * megaraid_io_detach - detach a device from the IO subsystem + * @param adapter : controller's soft state + * + * Detach this device from the IO subsystem + **/ +static void +megaraid_io_detach(adapter_t *adapter) +{ + struct Scsi_Host *host; + + con_log(CL_DLEVEL1, (KERN_INFO "megaraid: io detach\n")); + + host = adapter->host; + + scsi_remove_host(host); + + return; +} + + +/* + * START: Mailbox Low Level Driver + * + * This is section specific to the single mailbox based controllers + */ + +/** + * megaraid_init_mbox - initialize controller + * @param adapter - our soft state + * + * . Allocate 16-byte aligned mailbox memory for firmware handshake + * . Allocate controller's memory resources + * . Find out all initialization data + * . Allocate memory required for all the commands + * . Use internal library of FW routines, build up complete soft state + */ +static int __init +megaraid_init_mbox(adapter_t *adapter) +{ + struct pci_dev *pdev; + mraid_device_t *raid_dev; + int i; + unsigned int magic64; + + + adapter->ito = MBOX_TIMEOUT; + pdev = adapter->pdev; + + /* + * Allocate and initialize the init data structure for mailbox + * controllers + */ + raid_dev = kmalloc(sizeof(mraid_device_t), GFP_KERNEL); + if (raid_dev == NULL) return -1; + + memset(raid_dev, 0, sizeof(mraid_device_t)); + + /* + * Attach the adapter soft state to raid device soft state + */ + adapter->raid_device = (caddr_t)raid_dev; + raid_dev->fast_load = megaraid_fast_load; + + + // our baseport + raid_dev->baseport = pci_resource_start(pdev, 0); + + if (pci_request_regions(pdev, "MegaRAID: LSI Logic Corporation") != 0) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid: mem region busy\n")); + + goto out_free_raid_dev; + } + + raid_dev->baseaddr = ioremap_nocache(raid_dev->baseport, 128); + + if (!raid_dev->baseaddr) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid: could not map hba memory\n") ); + + goto out_release_regions; + } + + // + // Setup the rest of the soft state using the library of FW routines + // + + // request IRQ and register the interrupt service routine + if (request_irq(adapter->irq, megaraid_isr, SA_SHIRQ, "megaraid", + adapter)) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid: Couldn't register IRQ %d!\n", adapter->irq)); + + goto out_iounmap; + } + + + // initialize the mutual exclusion lock for the mailbox + spin_lock_init(&raid_dev->mailbox_lock); + + // allocate memory required for commands + if (megaraid_alloc_cmd_packets(adapter) != 0) { + goto out_free_irq; + } + + // Product info + if (megaraid_mbox_product_info(adapter) != 0) { + goto out_alloc_cmds; + } + + // Do we support extended CDBs + adapter->max_cdb_sz = 10; + if (megaraid_mbox_extended_cdb(adapter) == 0) { + adapter->max_cdb_sz = 16; + } + + /* + * Do we support cluster environment, if we do, what is the initiator + * id. + * NOTE: In a non-cluster aware firmware environment, the LLD should + * return 7 as initiator id. + */ + adapter->ha = 0; + adapter->init_id = -1; + if (megaraid_mbox_support_ha(adapter, &adapter->init_id) == 0) { + adapter->ha = 1; + } + + /* + * Prepare the device ids array to have the mapping between the kernel + * device address and megaraid device address. + * We export the physical devices on their actual addresses. The + * logical drives are exported on a virtual SCSI channel + */ + megaraid_mbox_setup_device_map(adapter); + + // If the firmware supports random deletion, update the device id map + if (megaraid_mbox_support_random_del(adapter)) { + + // Change the logical drives numbers in device_ids array one + // slot in device_ids is reserved for target id, that's why + // "<=" below + for (i = 0; i <= MAX_LOGICAL_DRIVES_40LD; i++) { + adapter->device_ids[adapter->max_channel][i] += 0x80; + } + adapter->device_ids[adapter->max_channel][adapter->init_id] = + 0xFF; + + raid_dev->random_del_supported = 1; + } + + /* + * find out the maximum number of scatter-gather elements supported by + * this firmware + */ + adapter->sglen = megaraid_mbox_get_max_sg(adapter); + + // enumerate RAID and SCSI channels so that all devices on SCSI + // channels can later be exported, including disk devices + megaraid_mbox_enum_raid_scsi(adapter); + + /* + * Other parameters required by upper layer + * + * maximum number of sectors per IO command + */ + adapter->max_sectors = megaraid_max_sectors; + + /* + * number of queued commands per LUN. + */ + adapter->cmd_per_lun = megaraid_cmd_per_lun; + + /* + * Allocate resources required to issue FW calls, when sysfs is + * accessed + */ + if (megaraid_sysfs_alloc_resources(adapter) != 0) { + goto out_alloc_cmds; + } + + // Set the DMA mask to 64-bit. All supported controllers as capable of + // DMA in this range + pci_read_config_dword(adapter->pdev, PCI_CONF_AMISIG64, &magic64); + + if (((magic64 == HBA_SIGNATURE_64BIT) && + ((adapter->pdev->subsystem_device != + PCI_SUBSYS_ID_MEGARAID_SATA_150_6) && + (adapter->pdev->subsystem_device != + PCI_SUBSYS_ID_MEGARAID_SATA_150_4))) || + (adapter->pdev->vendor == PCI_VENDOR_ID_DELL && + adapter->pdev->device == PCI_DEVICE_ID_PERC4_DI_EVERGLADES) || + (adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC && + adapter->pdev->device == PCI_DEVICE_ID_VERDE) || + (adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC && + adapter->pdev->device == PCI_DEVICE_ID_DOBSON) || + (adapter->pdev->vendor == PCI_VENDOR_ID_DELL && + adapter->pdev->device == PCI_DEVICE_ID_PERC4E_DI_KOBUK) || + (adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC && + adapter->pdev->device == PCI_DEVICE_ID_LINDSAY)) { + if (pci_set_dma_mask(adapter->pdev, DMA_64BIT_MASK) != 0) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: could not set DMA mask for 64-bit.\n")); + + goto out_free_sysfs_res; + } + } + + // setup tasklet for DPC + tasklet_init(&adapter->dpc_h, megaraid_mbox_dpc, + (unsigned long)adapter); + + con_log(CL_DLEVEL1, (KERN_INFO + "megaraid mbox hba successfully initialized\n")); + + return 0; + +out_free_sysfs_res: + megaraid_sysfs_free_resources(adapter); +out_alloc_cmds: + megaraid_free_cmd_packets(adapter); +out_free_irq: + free_irq(adapter->irq, adapter); +out_iounmap: + iounmap(raid_dev->baseaddr); +out_release_regions: + pci_release_regions(pdev); +out_free_raid_dev: + kfree(raid_dev); + + return -1; +} + + +/** + * megaraid_fini_mbox - undo controller initialization + * @param adapter : our soft state + */ +static void +megaraid_fini_mbox(adapter_t *adapter) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + + // flush all caches + megaraid_mbox_flush_cache(adapter); + + tasklet_kill(&adapter->dpc_h); + + megaraid_sysfs_free_resources(adapter); + + megaraid_free_cmd_packets(adapter); + + free_irq(adapter->irq, adapter); + + iounmap(raid_dev->baseaddr); + + pci_release_regions(adapter->pdev); + + kfree(raid_dev); + + return; +} + + +/** + * megaraid_alloc_cmd_packets - allocate shared mailbox + * @param adapter : soft state of the raid controller + * + * Allocate and align the shared mailbox. This maibox is used to issue + * all the commands. For IO based controllers, the mailbox is also regsitered + * with the FW. Allocate memory for all commands as well. + * This is our big allocator + */ +static int +megaraid_alloc_cmd_packets(adapter_t *adapter) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + struct pci_dev *pdev; + unsigned long align; + scb_t *scb; + mbox_ccb_t *ccb; + struct mraid_pci_blk *epthru_pci_blk; + struct mraid_pci_blk *sg_pci_blk; + struct mraid_pci_blk *mbox_pci_blk; + int i; + + pdev = adapter->pdev; + + /* + * Setup the mailbox + * Allocate the common 16-byte aligned memory for the handshake + * mailbox. + */ + raid_dev->una_mbox64 = pci_alloc_consistent(adapter->pdev, + sizeof(mbox64_t), &raid_dev->una_mbox64_dma); + + if (!raid_dev->una_mbox64) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: out of memory, %s %d\n", __FUNCTION__, + __LINE__)); + return -1; + } + memset(raid_dev->una_mbox64, 0, sizeof(mbox64_t)); + + /* + * Align the mailbox at 16-byte boundary + */ + raid_dev->mbox = &raid_dev->una_mbox64->mbox32; + + raid_dev->mbox = (mbox_t *)((((unsigned long)raid_dev->mbox) + 15) & + (~0UL ^ 0xFUL)); + + raid_dev->mbox64 = (mbox64_t *)(((unsigned long)raid_dev->mbox) - 8); + + align = ((void *)raid_dev->mbox - + ((void *)&raid_dev->una_mbox64->mbox32)); + + raid_dev->mbox_dma = (unsigned long)raid_dev->una_mbox64_dma + 8 + + align; + + // Allocate memory for commands issued internally + adapter->ibuf = pci_alloc_consistent(pdev, MBOX_IBUF_SIZE, + &adapter->ibuf_dma_h); + if (!adapter->ibuf) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid: out of memory, %s %d\n", __FUNCTION__, + __LINE__)); + + goto out_free_common_mbox; + } + memset(adapter->ibuf, 0, MBOX_IBUF_SIZE); + + // Allocate memory for our SCSI Command Blocks and their associated + // memory + + /* + * Allocate memory for the base list of scb. Later allocate memory for + * CCBs and embedded components of each CCB and point the pointers in + * scb to the allocated components + * NOTE: The code to allocate SCB will be duplicated in all the LLD + * since the calling routine does not yet know the number of available + * commands. + */ + adapter->kscb_list = kmalloc(sizeof(scb_t) * MBOX_MAX_SCSI_CMDS, + GFP_KERNEL); + + if (adapter->kscb_list == NULL) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: out of memory, %s %d\n", __FUNCTION__, + __LINE__)); + goto out_free_ibuf; + } + memset(adapter->kscb_list, 0, sizeof(scb_t) * MBOX_MAX_SCSI_CMDS); + + // memory allocation for our command packets + if (megaraid_mbox_setup_dma_pools(adapter) != 0) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: out of memory, %s %d\n", __FUNCTION__, + __LINE__)); + goto out_free_scb_list; + } + + // Adjust the scb pointers and link in the free pool + epthru_pci_blk = raid_dev->epthru_pool; + sg_pci_blk = raid_dev->sg_pool; + mbox_pci_blk = raid_dev->mbox_pool; + + for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) { + scb = adapter->kscb_list + i; + ccb = raid_dev->ccb_list + i; + + ccb->mbox = (mbox_t *)(mbox_pci_blk[i].vaddr + 16); + ccb->raw_mbox = (uint8_t *)ccb->mbox; + ccb->mbox64 = (mbox64_t *)(mbox_pci_blk[i].vaddr + 8); + ccb->mbox_dma_h = (unsigned long)mbox_pci_blk[i].dma_addr + 16; + + // make sure the mailbox is aligned properly + if (ccb->mbox_dma_h & 0x0F) { + con_log(CL_ANN, (KERN_CRIT + "megaraid mbox: not aligned on 16-bytes\n")); + + goto out_teardown_dma_pools; + } + + ccb->epthru = (mraid_epassthru_t *) + epthru_pci_blk[i].vaddr; + ccb->epthru_dma_h = epthru_pci_blk[i].dma_addr; + ccb->pthru = (mraid_passthru_t *)ccb->epthru; + ccb->pthru_dma_h = ccb->epthru_dma_h; + + + ccb->sgl64 = (mbox_sgl64 *)sg_pci_blk[i].vaddr; + ccb->sgl_dma_h = sg_pci_blk[i].dma_addr; + ccb->sgl32 = (mbox_sgl32 *)ccb->sgl64; + + scb->ccb = (caddr_t)ccb; + scb->gp = 0; + + scb->sno = i; // command index + + scb->scp = NULL; + scb->state = SCB_FREE; + scb->dma_direction = PCI_DMA_NONE; + scb->dma_type = MRAID_DMA_NONE; + scb->dev_channel = -1; + scb->dev_target = -1; + + // put scb in the free pool + list_add_tail(&scb->list, &adapter->kscb_pool); + } + + return 0; + +out_teardown_dma_pools: + megaraid_mbox_teardown_dma_pools(adapter); +out_free_scb_list: + kfree(adapter->kscb_list); +out_free_ibuf: + pci_free_consistent(pdev, MBOX_IBUF_SIZE, (void *)adapter->ibuf, + adapter->ibuf_dma_h); +out_free_common_mbox: + pci_free_consistent(adapter->pdev, sizeof(mbox64_t), + (caddr_t)raid_dev->una_mbox64, raid_dev->una_mbox64_dma); + + return -1; +} + + +/** + * megaraid_free_cmd_packets - free memory + * @param adapter : soft state of the raid controller + * + * Release memory resources allocated for commands + */ +static void +megaraid_free_cmd_packets(adapter_t *adapter) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + + megaraid_mbox_teardown_dma_pools(adapter); + + kfree(adapter->kscb_list); + + pci_free_consistent(adapter->pdev, MBOX_IBUF_SIZE, + (void *)adapter->ibuf, adapter->ibuf_dma_h); + + pci_free_consistent(adapter->pdev, sizeof(mbox64_t), + (caddr_t)raid_dev->una_mbox64, raid_dev->una_mbox64_dma); + return; +} + + +/** + * megaraid_mbox_setup_dma_pools - setup dma pool for command packets + * @param adapter : HBA soft state + * + * setup the dma pools for mailbox, passthru and extended passthru structures, + * and scatter-gather lists + */ +static int +megaraid_mbox_setup_dma_pools(adapter_t *adapter) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + struct mraid_pci_blk *epthru_pci_blk; + struct mraid_pci_blk *sg_pci_blk; + struct mraid_pci_blk *mbox_pci_blk; + int i; + + + + // Allocate memory for 16-bytes aligned mailboxes + raid_dev->mbox_pool_handle = pci_pool_create("megaraid mbox pool", + adapter->pdev, + sizeof(mbox64_t) + 16, + 16, 0); + + if (raid_dev->mbox_pool_handle == NULL) { + goto fail_setup_dma_pool; + } + + mbox_pci_blk = raid_dev->mbox_pool; + for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) { + mbox_pci_blk[i].vaddr = pci_pool_alloc( + raid_dev->mbox_pool_handle, + GFP_KERNEL, + &mbox_pci_blk[i].dma_addr); + if (!mbox_pci_blk[i].vaddr) { + goto fail_setup_dma_pool; + } + } + + /* + * Allocate memory for each embedded passthru strucuture pointer + * Request for a 128 bytes aligned structure for each passthru command + * structure + * Since passthru and extended passthru commands are exclusive, they + * share common memory pool. Passthru structures piggyback on memory + * allocted to extended passthru since passthru is smaller of the two + */ + raid_dev->epthru_pool_handle = pci_pool_create("megaraid mbox pthru", + adapter->pdev, sizeof(mraid_epassthru_t), 128, 0); + + if (raid_dev->epthru_pool_handle == NULL) { + goto fail_setup_dma_pool; + } + + epthru_pci_blk = raid_dev->epthru_pool; + for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) { + epthru_pci_blk[i].vaddr = pci_pool_alloc( + raid_dev->epthru_pool_handle, + GFP_KERNEL, + &epthru_pci_blk[i].dma_addr); + if (!epthru_pci_blk[i].vaddr) { + goto fail_setup_dma_pool; + } + } + + + // Allocate memory for each scatter-gather list. Request for 512 bytes + // alignment for each sg list + raid_dev->sg_pool_handle = pci_pool_create("megaraid mbox sg", + adapter->pdev, + sizeof(mbox_sgl64) * MBOX_MAX_SG_SIZE, + 512, 0); + + if (raid_dev->sg_pool_handle == NULL) { + goto fail_setup_dma_pool; + } + + sg_pci_blk = raid_dev->sg_pool; + for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) { + sg_pci_blk[i].vaddr = pci_pool_alloc( + raid_dev->sg_pool_handle, + GFP_KERNEL, + &sg_pci_blk[i].dma_addr); + if (!sg_pci_blk[i].vaddr) { + goto fail_setup_dma_pool; + } + } + + return 0; + +fail_setup_dma_pool: + megaraid_mbox_teardown_dma_pools(adapter); + return -1; +} + + +/** + * megaraid_mbox_teardown_dma_pools - teardown dma pools for command packets + * @param adapter : HBA soft state + * + * teardown the dma pool for mailbox, passthru and extended passthru + * structures, and scatter-gather lists + */ +static void +megaraid_mbox_teardown_dma_pools(adapter_t *adapter) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + struct mraid_pci_blk *epthru_pci_blk; + struct mraid_pci_blk *sg_pci_blk; + struct mraid_pci_blk *mbox_pci_blk; + int i; + + + sg_pci_blk = raid_dev->sg_pool; + for (i = 0; i < MBOX_MAX_SCSI_CMDS && sg_pci_blk[i].vaddr; i++) { + pci_pool_free(raid_dev->sg_pool_handle, sg_pci_blk[i].vaddr, + sg_pci_blk[i].dma_addr); + } + if (raid_dev->sg_pool_handle) + pci_pool_destroy(raid_dev->sg_pool_handle); + + + epthru_pci_blk = raid_dev->epthru_pool; + for (i = 0; i < MBOX_MAX_SCSI_CMDS && epthru_pci_blk[i].vaddr; i++) { + pci_pool_free(raid_dev->epthru_pool_handle, + epthru_pci_blk[i].vaddr, epthru_pci_blk[i].dma_addr); + } + if (raid_dev->epthru_pool_handle) + pci_pool_destroy(raid_dev->epthru_pool_handle); + + + mbox_pci_blk = raid_dev->mbox_pool; + for (i = 0; i < MBOX_MAX_SCSI_CMDS && mbox_pci_blk[i].vaddr; i++) { + pci_pool_free(raid_dev->mbox_pool_handle, + mbox_pci_blk[i].vaddr, mbox_pci_blk[i].dma_addr); + } + if (raid_dev->mbox_pool_handle) + pci_pool_destroy(raid_dev->mbox_pool_handle); + + return; +} + + +/** + * megaraid_alloc_scb - detach and return a scb from the free list + * @adapter : controller's soft state + * + * return the scb from the head of the free list. NULL if there are none + * available + **/ +static inline scb_t * +megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp) +{ + struct list_head *head = &adapter->kscb_pool; + scb_t *scb = NULL; + unsigned long flags; + + // detach scb from free pool + spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags); + + if (list_empty(head)) { + spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags); + return NULL; + } + + scb = list_entry(head->next, scb_t, list); + list_del_init(&scb->list); + + spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags); + + scb->state = SCB_ACTIVE; + scb->scp = scp; + scb->dma_type = MRAID_DMA_NONE; + + return scb; +} + + +/** + * megaraid_dealloc_scb - return the scb to the free pool + * @adapter : controller's soft state + * @scb : scb to be freed + * + * return the scb back to the free list of scbs. The caller must 'flush' the + * SCB before calling us. E.g., performing pci_unamp and/or pci_sync etc. + * NOTE NOTE: Make sure the scb is not on any list before calling this + * routine. + **/ +static inline void +megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb) +{ + unsigned long flags; + + // put scb in the free pool + scb->state = SCB_FREE; + scb->scp = NULL; + spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags); + + list_add(&scb->list, &adapter->kscb_pool); + + spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags); + + return; +} + + +/** + * megaraid_mbox_mksgl - make the scatter-gather list + * @adapter - controller's soft state + * @scb - scsi control block + * + * prepare the scatter-gather list + */ +static inline int +megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) +{ + struct scatterlist *sgl; + mbox_ccb_t *ccb; + struct page *page; + unsigned long offset; + struct scsi_cmnd *scp; + int sgcnt; + int i; + + + scp = scb->scp; + ccb = (mbox_ccb_t *)scb->ccb; + + // no mapping required if no data to be transferred + if (!scp->request_buffer || !scp->request_bufflen) + return 0; + + if (!scp->use_sg) { /* scatter-gather list not used */ + + page = virt_to_page(scp->request_buffer); + + offset = ((unsigned long)scp->request_buffer & ~PAGE_MASK); + + ccb->buf_dma_h = pci_map_page(adapter->pdev, page, offset, + scp->request_bufflen, + scb->dma_direction); + scb->dma_type = MRAID_DMA_WBUF; + + /* + * We need to handle special 64-bit commands that need a + * minimum of 1 SG + */ + sgcnt = 1; + ccb->sgl64[0].address = ccb->buf_dma_h; + ccb->sgl64[0].length = scp->request_bufflen; + + return sgcnt; + } + + sgl = (struct scatterlist *)scp->request_buffer; + + // The number of sg elements returned must not exceed our limit + sgcnt = pci_map_sg(adapter->pdev, sgl, scp->use_sg, + scb->dma_direction); + + if (sgcnt > adapter->sglen) { + con_log(CL_ANN, (KERN_CRIT + "megaraid critical: too many sg elements:%d\n", + sgcnt)); + BUG(); + } + + scb->dma_type = MRAID_DMA_WSG; + + for (i = 0; i < sgcnt; i++, sgl++) { + ccb->sgl64[i].address = sg_dma_address(sgl); + ccb->sgl64[i].length = sg_dma_len(sgl); + } + + // Return count of SG nodes + return sgcnt; +} + + +/** + * mbox_post_cmd - issue a mailbox command + * @adapter - controller's soft state + * @scb - command to be issued + * + * post the command to the controller if mailbox is availble. + */ +static inline int +mbox_post_cmd(adapter_t *adapter, scb_t *scb) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + mbox64_t *mbox64; + mbox_t *mbox; + mbox_ccb_t *ccb; + unsigned long flags; + unsigned int i = 0; + + + ccb = (mbox_ccb_t *)scb->ccb; + mbox = raid_dev->mbox; + mbox64 = raid_dev->mbox64; + + /* + * Check for busy mailbox. If it is, return failure - the caller + * should retry later. + */ + spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags); + + if (unlikely(mbox->busy)) { + do { + udelay(1); + i++; + rmb(); + } while(mbox->busy && (i < max_mbox_busy_wait)); + + if (mbox->busy) { + + spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags); + + return -1; + } + } + + + // Copy this command's mailbox data into "adapter's" mailbox + memcpy((caddr_t)mbox64, (caddr_t)ccb->mbox64, 22); + mbox->cmdid = scb->sno; + + adapter->outstanding_cmds++; + + if (scb->dma_direction == PCI_DMA_TODEVICE) { + if (!scb->scp->use_sg) { // sg list not used + pci_dma_sync_single_for_device(adapter->pdev, + ccb->buf_dma_h, + scb->scp->request_bufflen, + PCI_DMA_TODEVICE); + } + else { + pci_dma_sync_sg_for_device(adapter->pdev, + scb->scp->request_buffer, + scb->scp->use_sg, PCI_DMA_TODEVICE); + } + } + + mbox->busy = 1; // Set busy + mbox->poll = 0; + mbox->ack = 0; + wmb(); + + WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1); + + spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags); + + return 0; +} + + +/** + * megaraid_queue_command - generic queue entry point for all LLDs + * @scp : pointer to the scsi command to be executed + * @done : callback routine to be called after the cmd has be completed + * + * Queue entry point for mailbox based controllers. + */ +static int +megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *)) +{ + adapter_t *adapter; + scb_t *scb; + int if_busy; + + adapter = SCP2ADAPTER(scp); + scp->scsi_done = done; + scp->result = 0; + + ASSERT(spin_is_locked(adapter->host_lock)); + + spin_unlock(adapter->host_lock); + + /* + * Allocate and build a SCB request + * if_busy flag will be set if megaraid_mbox_build_cmd() command could + * not allocate scb. We will return non-zero status in that case. + * NOTE: scb can be null even though certain commands completed + * successfully, e.g., MODE_SENSE and TEST_UNIT_READY, it would + * return 0 in that case, and we would do the callback right away. + */ + if_busy = 0; + scb = megaraid_mbox_build_cmd(adapter, scp, &if_busy); + + if (scb) { + megaraid_mbox_runpendq(adapter, scb); + } + + spin_lock(adapter->host_lock); + + if (!scb) { // command already completed + done(scp); + return 0; + } + + return if_busy; +} + + +/** + * megaraid_mbox_build_cmd - transform the mid-layer scsi command to megaraid + * firmware lingua + * @adapter - controller's soft state + * @scp - mid-layer scsi command pointer + * @busy - set if request could not be completed because of lack of + * resources + * + * convert the command issued by mid-layer to format understood by megaraid + * firmware. We also complete certain command without sending them to firmware + */ +static scb_t * +megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) +{ + mraid_device_t *rdev = ADAP2RAIDDEV(adapter); + int channel; + int target; + int islogical; + mbox_ccb_t *ccb; + mraid_passthru_t *pthru; + mbox64_t *mbox64; + mbox_t *mbox; + scb_t *scb; + char skip[] = "skipping"; + char scan[] = "scanning"; + char *ss; + + + /* + * Get the appropriate device map for the device this command is + * intended for + */ + MRAID_GET_DEVICE_MAP(adapter, scp, channel, target, islogical); + + /* + * Logical drive commands + */ + if (islogical) { + switch (scp->cmnd[0]) { + case TEST_UNIT_READY: + /* + * Do we support clustering and is the support enabled + * If no, return success always + */ + if (!adapter->ha) { + scp->result = (DID_OK << 16); + return NULL; + } + + if (!(scb = megaraid_alloc_scb(adapter, scp))) { + scp->result = (DID_ERROR << 16); + *busy = 1; + return NULL; + } + + scb->dma_direction = scp->sc_data_direction; + scb->dev_channel = 0xFF; + scb->dev_target = target; + ccb = (mbox_ccb_t *)scb->ccb; + + /* + * The command id will be provided by the command + * issuance routine + */ + ccb->raw_mbox[0] = CLUSTER_CMD; + ccb->raw_mbox[2] = RESERVATION_STATUS; + ccb->raw_mbox[3] = target; + + return scb; + + case MODE_SENSE: + if (scp->use_sg) { + struct scatterlist *sgl; + caddr_t vaddr; + + sgl = (struct scatterlist *)scp->request_buffer; + if (sgl->page) { + vaddr = (caddr_t) + (page_address((&sgl[0])->page) + + (&sgl[0])->offset); + + memset(vaddr, 0, scp->cmnd[4]); + } + else { + con_log(CL_ANN, (KERN_WARNING + "megaraid mailbox: invalid sg:%d\n", + __LINE__)); + } + } + else { + memset(scp->request_buffer, 0, scp->cmnd[4]); + } + scp->result = (DID_OK << 16); + return NULL; + + case INQUIRY: + /* + * Display the channel scan for logical drives + * Do not display scan for a channel if already done. + */ + if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) { + + con_log(CL_ANN, (KERN_INFO + "scsi[%d]: scanning scsi channel %d", + adapter->host->host_no, + SCP2CHANNEL(scp))); + + con_log(CL_ANN, ( + " [virtual] for logical drives\n")); + + rdev->last_disp |= (1L << SCP2CHANNEL(scp)); + } + + /* + * The firmware ignores the EVPD bit, and the command + * allocation length. As a result, it may over-write + * the request buffer and corrupt memory. Don't let + * EVPD Inquirys through. + */ + if (scp->cmnd[1] & 0x01) { + scp->sense_buffer[0] = 0x70; + scp->sense_buffer[2] = ILLEGAL_REQUEST; + scp->sense_buffer[12] = 0x24; /* INVALID_IN_CDB */ + scp->result = CHECK_CONDITION << 1; + return NULL; + } + + /* Fall through */ + + case READ_CAPACITY: + /* + * Do not allow LUN > 0 for logical drives and + * requests for more than 40 logical drives + */ + if (SCP2LUN(scp)) { + scp->result = (DID_BAD_TARGET << 16); + return NULL; + } + if ((target % 0x80) >= MAX_LOGICAL_DRIVES_40LD) { + scp->result = (DID_BAD_TARGET << 16); + return NULL; + } + + + /* Allocate a SCB and initialize passthru */ + if (!(scb = megaraid_alloc_scb(adapter, scp))) { + scp->result = (DID_ERROR << 16); + *busy = 1; + return NULL; + } + + ccb = (mbox_ccb_t *)scb->ccb; + scb->dev_channel = 0xFF; + scb->dev_target = target; + pthru = ccb->pthru; + mbox = ccb->mbox; + mbox64 = ccb->mbox64; + + pthru->timeout = 0; + pthru->ars = 1; + pthru->reqsenselen = 14; + pthru->islogical = 1; + pthru->logdrv = target; + pthru->cdblen = scp->cmd_len; + memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); + + mbox->cmd = MBOXCMD_PASSTHRU64; + scb->dma_direction = scp->sc_data_direction; + + pthru->dataxferlen = scp->request_bufflen; + pthru->dataxferaddr = ccb->sgl_dma_h; + pthru->numsge = megaraid_mbox_mksgl(adapter, + scb); + + mbox->xferaddr = 0xFFFFFFFF; + mbox64->xferaddr_lo = (uint32_t )ccb->pthru_dma_h; + mbox64->xferaddr_hi = 0; + + return scb; + + case READ_6: + case WRITE_6: + case READ_10: + case WRITE_10: + case READ_12: + case WRITE_12: + + /* + * Allocate a SCB and initialize mailbox + */ + if (!(scb = megaraid_alloc_scb(adapter, scp))) { + scp->result = (DID_ERROR << 16); + *busy = 1; + return NULL; + } + ccb = (mbox_ccb_t *)scb->ccb; + scb->dev_channel = 0xFF; + scb->dev_target = target; + mbox = ccb->mbox; + mbox64 = ccb->mbox64; + mbox->logdrv = target; + + /* + * A little HACK: 2nd bit is zero for all scsi read + * commands and is set for all scsi write commands + */ + mbox->cmd = (scp->cmnd[0] & 0x02) ? MBOXCMD_LWRITE64: + MBOXCMD_LREAD64 ; + + /* + * 6-byte READ(0x08) or WRITE(0x0A) cdb + */ + if (scp->cmd_len == 6) { + mbox->numsectors = (uint32_t)scp->cmnd[4]; + mbox->lba = + ((uint32_t)scp->cmnd[1] << 16) | + ((uint32_t)scp->cmnd[2] << 8) | + (uint32_t)scp->cmnd[3]; + + mbox->lba &= 0x1FFFFF; + } + + /* + * 10-byte READ(0x28) or WRITE(0x2A) cdb + */ + else if (scp->cmd_len == 10) { + mbox->numsectors = + (uint32_t)scp->cmnd[8] | + ((uint32_t)scp->cmnd[7] << 8); + mbox->lba = + ((uint32_t)scp->cmnd[2] << 24) | + ((uint32_t)scp->cmnd[3] << 16) | + ((uint32_t)scp->cmnd[4] << 8) | + (uint32_t)scp->cmnd[5]; + } + + /* + * 12-byte READ(0xA8) or WRITE(0xAA) cdb + */ + else if (scp->cmd_len == 12) { + mbox->lba = + ((uint32_t)scp->cmnd[2] << 24) | + ((uint32_t)scp->cmnd[3] << 16) | + ((uint32_t)scp->cmnd[4] << 8) | + (uint32_t)scp->cmnd[5]; + + mbox->numsectors = + ((uint32_t)scp->cmnd[6] << 24) | + ((uint32_t)scp->cmnd[7] << 16) | + ((uint32_t)scp->cmnd[8] << 8) | + (uint32_t)scp->cmnd[9]; + } + else { + con_log(CL_ANN, (KERN_WARNING + "megaraid: unsupported CDB length\n")); + + megaraid_dealloc_scb(adapter, scb); + + scp->result = (DID_ERROR << 16); + return NULL; + } + + scb->dma_direction = scp->sc_data_direction; + + // Calculate Scatter-Gather info + mbox64->xferaddr_lo = (uint32_t )ccb->sgl_dma_h; + mbox->numsge = megaraid_mbox_mksgl(adapter, + scb); + mbox->xferaddr = 0xFFFFFFFF; + mbox64->xferaddr_hi = 0; + + return scb; + + case RESERVE: + case RELEASE: + /* + * Do we support clustering and is the support enabled + */ + if (!adapter->ha) { + scp->result = (DID_BAD_TARGET << 16); + return NULL; + } + + /* + * Allocate a SCB and initialize mailbox + */ + if (!(scb = megaraid_alloc_scb(adapter, scp))) { + scp->result = (DID_ERROR << 16); + *busy = 1; + return NULL; + } + + ccb = (mbox_ccb_t *)scb->ccb; + scb->dev_channel = 0xFF; + scb->dev_target = target; + ccb->raw_mbox[0] = CLUSTER_CMD; + ccb->raw_mbox[2] = (scp->cmnd[0] == RESERVE) ? + RESERVE_LD : RELEASE_LD; + + ccb->raw_mbox[3] = target; + scb->dma_direction = scp->sc_data_direction; + + return scb; + + case REQUEST_SENSE: + case MODE_SELECT: + case SYNCHRONIZE_CACHE: + if ( crashdump_mode() ) { + scp->result = (DID_OK << 16); + scp->scsi_done(scp); + return NULL; + } + default: + scp->result = (DID_BAD_TARGET << 16); + return NULL; + } + } + else { // Passthru device commands + + // Do not allow access to target id > 15 or LUN > 7 + if (target > 15 || SCP2LUN(scp) > 7) { + scp->result = (DID_BAD_TARGET << 16); + return NULL; + } + + // if fast load option was set and scan for last device is + // over, reset the fast_load flag so that during a possible + // next scan, devices can be made available + if (rdev->fast_load && (target == 15) && + (SCP2CHANNEL(scp) == adapter->max_channel -1)) { + + con_log(CL_ANN, (KERN_INFO + "megaraid[%d]: physical device scan re-enabled\n", + adapter->host->host_no)); + rdev->fast_load = 0; + } + + /* + * Display the channel scan for physical devices + */ + if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) { + + ss = rdev->fast_load ? skip : scan; + + con_log(CL_ANN, (KERN_INFO + "scsi[%d]: %s scsi channel %d [Phy %d]", + adapter->host->host_no, ss, SCP2CHANNEL(scp), + channel)); + + con_log(CL_ANN, ( + " for non-raid devices\n")); + + rdev->last_disp |= (1L << SCP2CHANNEL(scp)); + } + + // disable channel sweep if fast load option given + if (rdev->fast_load) { + scp->result = (DID_BAD_TARGET << 16); + return NULL; + } + + // Allocate a SCB and initialize passthru + if (!(scb = megaraid_alloc_scb(adapter, scp))) { + scp->result = (DID_ERROR << 16); + *busy = 1; + return NULL; + } + + ccb = (mbox_ccb_t *)scb->ccb; + scb->dev_channel = channel; + scb->dev_target = target; + scb->dma_direction = scp->sc_data_direction; + mbox = ccb->mbox; + mbox64 = ccb->mbox64; + + // Does this firmware support extended CDBs + if (adapter->max_cdb_sz == 16) { + mbox->cmd = MBOXCMD_EXTPTHRU; + + megaraid_mbox_prepare_epthru(adapter, scb, scp); + + mbox64->xferaddr_lo = (uint32_t)ccb->epthru_dma_h; + mbox64->xferaddr_hi = 0; + mbox->xferaddr = 0xFFFFFFFF; + } + else { + mbox->cmd = MBOXCMD_PASSTHRU64; + + megaraid_mbox_prepare_pthru(adapter, scb, scp); + + mbox64->xferaddr_lo = (uint32_t)ccb->pthru_dma_h; + mbox64->xferaddr_hi = 0; + mbox->xferaddr = 0xFFFFFFFF; + } + return scb; + } + + // NOT REACHED +} + + +/** + * megaraid_mbox_runpendq - execute commands queued in the pending queue + * @adapter : controller's soft state + * @scb : SCB to be queued in the pending list + * + * scan the pending list for commands which are not yet issued and try to + * post to the controller. The SCB can be a null pointer, which would indicate + * no SCB to be queue, just try to execute the ones in the pending list. + * + * NOTE: We do not actually traverse the pending list. The SCBs are plucked + * out from the head of the pending list. If it is successfully issued, the + * next SCB is at the head now. + */ +static void +megaraid_mbox_runpendq(adapter_t *adapter, scb_t *scb_q) +{ + scb_t *scb; + unsigned long flags; + + spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags); + + if (scb_q) { + scb_q->state = SCB_PENDQ; + list_add_tail(&scb_q->list, &adapter->pend_list); + } + + // if the adapter in not in quiescent mode, post the commands to FW + if (adapter->quiescent) { + spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags); + return; + } + + while (!list_empty(&adapter->pend_list)) { + + ASSERT(spin_is_locked(PENDING_LIST_LOCK(adapter))); + + scb = list_entry(adapter->pend_list.next, scb_t, list); + + // remove the scb from the pending list and try to + // issue. If we are unable to issue it, put back in + // the pending list and return + + list_del_init(&scb->list); + + spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags); + + // if mailbox was busy, return SCB back to pending + // list. Make sure to add at the head, since that's + // where it would have been removed from + + scb->state = SCB_ISSUED; + + if (mbox_post_cmd(adapter, scb) != 0) { + + spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags); + + scb->state = SCB_PENDQ; + + list_add(&scb->list, &adapter->pend_list); + + spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), + flags); + + return; + } + + spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags); + } + + spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags); + + + return; +} + + +/** + * megaraid_mbox_prepare_pthru - prepare a command for physical devices + * @adapter - pointer to controller's soft state + * @scb - scsi control block + * @scp - scsi command from the mid-layer + * + * prepare a command for the scsi physical devices + */ +static void +megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb, + struct scsi_cmnd *scp) +{ + mbox_ccb_t *ccb; + mraid_passthru_t *pthru; + uint8_t channel; + uint8_t target; + + ccb = (mbox_ccb_t *)scb->ccb; + pthru = ccb->pthru; + channel = scb->dev_channel; + target = scb->dev_target; + + // 0=6sec, 1=60sec, 2=10min, 3=3hrs, 4=NO timeout + pthru->timeout = 4; + pthru->ars = 1; + pthru->islogical = 0; + pthru->channel = 0; + pthru->target = (channel << 4) | target; + pthru->logdrv = SCP2LUN(scp); + pthru->reqsenselen = 14; + pthru->cdblen = scp->cmd_len; + + memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); + + if (scp->request_bufflen) { + pthru->dataxferlen = scp->request_bufflen; + pthru->dataxferaddr = ccb->sgl_dma_h; + pthru->numsge = megaraid_mbox_mksgl(adapter, scb); + } + else { + pthru->dataxferaddr = 0; + pthru->dataxferlen = 0; + pthru->numsge = 0; + } + return; +} + + +/** + * megaraid_mbox_prepare_epthru - prepare a command for physical devices + * @adapter - pointer to controller's soft state + * @scb - scsi control block + * @scp - scsi command from the mid-layer + * + * prepare a command for the scsi physical devices. This rountine prepares + * commands for devices which can take extended CDBs (>10 bytes) + */ +static void +megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb, + struct scsi_cmnd *scp) +{ + mbox_ccb_t *ccb; + mraid_epassthru_t *epthru; + uint8_t channel; + uint8_t target; + + ccb = (mbox_ccb_t *)scb->ccb; + epthru = ccb->epthru; + channel = scb->dev_channel; + target = scb->dev_target; + + // 0=6sec, 1=60sec, 2=10min, 3=3hrs, 4=NO timeout + epthru->timeout = 4; + epthru->ars = 1; + epthru->islogical = 0; + epthru->channel = 0; + epthru->target = (channel << 4) | target; + epthru->logdrv = SCP2LUN(scp); + epthru->reqsenselen = 14; + epthru->cdblen = scp->cmd_len; + + memcpy(epthru->cdb, scp->cmnd, scp->cmd_len); + + if (scp->request_bufflen) { + epthru->dataxferlen = scp->request_bufflen; + epthru->dataxferaddr = ccb->sgl_dma_h; + epthru->numsge = megaraid_mbox_mksgl(adapter, scb); + } + else { + epthru->dataxferaddr = 0; + epthru->dataxferlen = 0; + epthru->numsge = 0; + } + return; +} + + +/** + * megaraid_ack_sequence - interrupt ack sequence for memory mapped HBAs + * @adapter - controller's soft state + * + * Interrupt ackrowledgement sequence for memory mapped HBAs. Find out the + * completed command and put them on the completed list for later processing. + * + * Returns: 1 if the interrupt is valid, 0 otherwise + */ +static inline int +megaraid_ack_sequence(adapter_t *adapter) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + mbox_t *mbox; + scb_t *scb; + uint8_t nstatus; + uint8_t completed[MBOX_MAX_FIRMWARE_STATUS]; + struct list_head clist; + int handled; + uint32_t dword; + unsigned long flags; + int i, j; + + + mbox = raid_dev->mbox; + + // move the SCBs from the firmware completed array to our local list + INIT_LIST_HEAD(&clist); + + // loop till F/W has more commands for us to complete + handled = 0; + spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags); + do { + /* + * Check if a valid interrupt is pending. If found, force the + * interrupt line low. + */ + dword = RDOUTDOOR(raid_dev); + if (dword != 0x10001234) break; + + handled = 1; + + WROUTDOOR(raid_dev, 0x10001234); + + nstatus = 0; + // wait for valid numstatus to post + for (i = 0; i < 0xFFFFF; i++) { + if (mbox->numstatus != 0xFF) { + nstatus = mbox->numstatus; + break; + } + rmb(); + } + mbox->numstatus = 0xFF; + + adapter->outstanding_cmds -= nstatus; + + for (i = 0; i < nstatus; i++) { + + // wait for valid command index to post + for (j = 0; j < 0xFFFFF; j++) { + if (mbox->completed[i] != 0xFF) break; + rmb(); + } + completed[i] = mbox->completed[i]; + mbox->completed[i] = 0xFF; + + if (completed[i] == 0xFF) { + con_log(CL_ANN, (KERN_CRIT + "megaraid: command posting timed out\n")); + + BUG(); + continue; + } + + // Get SCB associated with this command id + if (completed[i] >= MBOX_MAX_SCSI_CMDS) { + // a cmm command + scb = adapter->uscb_list + (completed[i] - + MBOX_MAX_SCSI_CMDS); + } + else { + // an os command + scb = adapter->kscb_list + completed[i]; + } + + scb->status = mbox->status; + list_add_tail(&scb->list, &clist); + } + + // Acknowledge interrupt + WRINDOOR(raid_dev, 0x02); + + } while(1); + + spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags); + + + // put the completed commands in the completed list. DPC would + // complete these commands later + spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags); + + list_splice(&clist, &adapter->completed_list); + + spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags); + + + // schedule the DPC if there is some work for it + if (handled) + tasklet_schedule(&adapter->dpc_h); + + return handled; +} + + +/** + * megaraid_isr - isr for memory based mailbox based controllers + * @irq - irq + * @devp - pointer to our soft state + * @regs - unused + * + * Interrupt service routine for memory-mapped mailbox controllers. + */ +static irqreturn_t +megaraid_isr(int irq, void *devp, struct pt_regs *regs) +{ + adapter_t *adapter = devp; + int handled; + + handled = megaraid_ack_sequence(adapter); + + /* Loop through any pending requests */ + if (!adapter->quiescent) { + megaraid_mbox_runpendq(adapter, NULL); + } + + return IRQ_RETVAL(handled); +} + + +/** + * megaraid_mbox_sync_scb - sync kernel buffers + * @adapter : controller's soft state + * @scb : pointer to the resource packet + * + * DMA sync if required. + */ +static inline void +megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb) +{ + mbox_ccb_t *ccb; + + ccb = (mbox_ccb_t *)scb->ccb; + + switch (scb->dma_type) { + + case MRAID_DMA_WBUF: + if (scb->dma_direction == PCI_DMA_FROMDEVICE) { + pci_dma_sync_single_for_cpu(adapter->pdev, + ccb->buf_dma_h, + scb->scp->request_bufflen, + PCI_DMA_FROMDEVICE); + } + + pci_unmap_page(adapter->pdev, ccb->buf_dma_h, + scb->scp->request_bufflen, scb->dma_direction); + + break; + + case MRAID_DMA_WSG: + if (scb->dma_direction == PCI_DMA_FROMDEVICE) { + pci_dma_sync_sg_for_cpu(adapter->pdev, + scb->scp->request_buffer, + scb->scp->use_sg, PCI_DMA_FROMDEVICE); + } + + pci_unmap_sg(adapter->pdev, scb->scp->request_buffer, + scb->scp->use_sg, scb->dma_direction); + + break; + + default: + break; + } + + return; +} + + +/** + * megaraid_mbox_dpc - the tasklet to complete the commands from completed list + * @devp : pointer to HBA soft state + * + * Pick up the commands from the completed list and send back to the owners. + * This is a reentrant function and does not assume any locks are held while + * it is being called. + */ +static void +megaraid_mbox_dpc(unsigned long devp) +{ + adapter_t *adapter = (adapter_t *)devp; + mraid_device_t *raid_dev; + struct list_head clist; + struct scatterlist *sgl; + scb_t *scb; + scb_t *tmp; + struct scsi_cmnd *scp; + mraid_passthru_t *pthru; + mraid_epassthru_t *epthru; + mbox_ccb_t *ccb; + int islogical; + int pdev_index; + int pdev_state; + mbox_t *mbox; + unsigned long flags; + uint8_t c; + int status; + + + if (!adapter) return; + + raid_dev = ADAP2RAIDDEV(adapter); + + // move the SCBs from the completed list to our local list + INIT_LIST_HEAD(&clist); + + spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags); + + list_splice_init(&adapter->completed_list, &clist); + + spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags); + + + list_for_each_entry_safe(scb, tmp, &clist, list) { + + status = scb->status; + scp = scb->scp; + ccb = (mbox_ccb_t *)scb->ccb; + pthru = ccb->pthru; + epthru = ccb->epthru; + mbox = ccb->mbox; + + // Make sure f/w has completed a valid command + if (scb->state != SCB_ISSUED) { + con_log(CL_ANN, (KERN_CRIT + "megaraid critical err: invalid command %d:%d:%p\n", + scb->sno, scb->state, scp)); + BUG(); + continue; // Must never happen! + } + + // check for the management command and complete it right away + if (scb->sno >= MBOX_MAX_SCSI_CMDS) { + scb->state = SCB_FREE; + scb->status = status; + + // remove from local clist + list_del_init(&scb->list); + + megaraid_mbox_mm_done(adapter, scb); + + continue; + } + + // Was an abort issued for this command earlier + if (scb->state & SCB_ABORT) { + con_log(CL_ANN, (KERN_NOTICE + "megaraid: aborted cmd %lx[%x] completed\n", + scp->serial_number, scb->sno)); + } + + /* + * If the inquiry came of a disk drive which is not part of + * any RAID array, expose it to the kernel. For this to be + * enabled, user must set the "megaraid_expose_unconf_disks" + * flag to 1 by specifying it on module parameter list. + * This would enable data migration off drives from other + * configurations. + */ + islogical = MRAID_IS_LOGICAL(adapter, scp); + if (scp->cmnd[0] == INQUIRY && status == 0 && islogical == 0 + && IS_RAID_CH(raid_dev, scb->dev_channel)) { + + if (scp->use_sg) { + sgl = (struct scatterlist *) + scp->request_buffer; + + if (sgl->page) { + c = *(unsigned char *) + (page_address((&sgl[0])->page) + + (&sgl[0])->offset); + } + else { + con_log(CL_ANN, (KERN_WARNING + "megaraid mailbox: invalid sg:%d\n", + __LINE__)); + c = 0; + } + } + else { + c = *(uint8_t *)scp->request_buffer; + } + + if ((c & 0x1F ) == TYPE_DISK) { + pdev_index = (scb->dev_channel * 16) + + scb->dev_target; + pdev_state = + raid_dev->pdrv_state[pdev_index] & 0x0F; + + if (pdev_state == PDRV_ONLINE || + pdev_state == PDRV_FAILED || + pdev_state == PDRV_RBLD || + pdev_state == PDRV_HOTSPARE || + megaraid_expose_unconf_disks == 0) { + + status = 0xF0; + } + } + } + + // Convert MegaRAID status to Linux error code + switch (status) { + + case 0x00: + + scp->result = (DID_OK << 16); + break; + + case 0x02: + + /* set sense_buffer and result fields */ + if (mbox->cmd == MBOXCMD_PASSTHRU || + mbox->cmd == MBOXCMD_PASSTHRU64) { + + memcpy(scp->sense_buffer, pthru->reqsensearea, + 14); + + scp->result = DRIVER_SENSE << 24 | + DID_OK << 16 | CHECK_CONDITION << 1; + } + else { + if (mbox->cmd == MBOXCMD_EXTPTHRU) { + + memcpy(scp->sense_buffer, + epthru->reqsensearea, 14); + + scp->result = DRIVER_SENSE << 24 | + DID_OK << 16 | + CHECK_CONDITION << 1; + } else { + scp->sense_buffer[0] = 0x70; + scp->sense_buffer[2] = ABORTED_COMMAND; + scp->result = CHECK_CONDITION << 1; + } + } + break; + + case 0x08: + + scp->result = DID_BUS_BUSY << 16 | status; + break; + + default: + + /* + * If TEST_UNIT_READY fails, we know RESERVATION_STATUS + * failed + */ + if (scp->cmnd[0] == TEST_UNIT_READY) { + scp->result = DID_ERROR << 16 | + RESERVATION_CONFLICT << 1; + } + else + /* + * Error code returned is 1 if Reserve or Release + * failed or the input parameter is invalid + */ + if (status == 1 && (scp->cmnd[0] == RESERVE || + scp->cmnd[0] == RELEASE)) { + + scp->result = DID_ERROR << 16 | + RESERVATION_CONFLICT << 1; + } + else { + scp->result = DID_BAD_TARGET << 16 | status; + } + } + + // print a debug message for all failed commands + if (status) { + megaraid_mbox_display_scb(adapter, scb); + } + + // Free our internal resources and call the mid-layer callback + // routine + megaraid_mbox_sync_scb(adapter, scb); + + // remove from local clist + list_del_init(&scb->list); + + // put back in free list + megaraid_dealloc_scb(adapter, scb); + + // send the scsi packet back to kernel + spin_lock(adapter->host_lock); + scp->scsi_done(scp); + spin_unlock(adapter->host_lock); + } + + if (crashdump_mode()) + mraid_mm_woken = 1; + + return; +} + + +/** + * megaraid_abort_handler - abort the scsi command + * @scp : command to be aborted + * + * Abort a previous SCSI request. Only commands on the pending list can be + * aborted. All the commands issued to the F/W must complete. + **/ +static int +megaraid_abort_handler(struct scsi_cmnd *scp) +{ + adapter_t *adapter; + mraid_device_t *raid_dev; + scb_t *scb; + scb_t *tmp; + int found; + unsigned long flags; + int i; + + + adapter = SCP2ADAPTER(scp); + raid_dev = ADAP2RAIDDEV(adapter); + + ASSERT(spin_is_locked(adapter->host_lock)); + + con_log(CL_ANN, (KERN_WARNING + "megaraid: aborting-%ld cmd=%x \n", + scp->serial_number, scp->cmnd[0], SCP2CHANNEL(scp), + SCP2TARGET(scp), SCP2LUN(scp))); + + // If FW has stopped responding, simply return failure + if (raid_dev->hw_error) { + con_log(CL_ANN, (KERN_NOTICE + "megaraid: hw error, not aborting\n")); + return FAILED; + } + + // There might a race here, where the command was completed by the + // firmware and now it is on the completed list. Before we could + // complete the command to the kernel in dpc, the abort came. + // Find out if this is the case to avoid the race. + scb = NULL; + spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags); + list_for_each_entry_safe(scb, tmp, &adapter->completed_list, list) { + + if (scb->scp == scp) { // Found command + + list_del_init(&scb->list); // from completed list + + con_log(CL_ANN, (KERN_WARNING + "megaraid: %ld:%d[%d:%d], abort from completed list\n", + scp->serial_number, scb->sno, + scb->dev_channel, scb->dev_target)); + + scp->result = (DID_ABORT << 16); + scp->scsi_done(scp); + + megaraid_dealloc_scb(adapter, scb); + + spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), + flags); + + return SUCCESS; + } + } + spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags); + + + // Find out if this command is still on the pending list. If it is and + // was never issued, abort and return success. If the command is owned + // by the firmware, we must wait for it to complete by the FW. + spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags); + list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) { + + if (scb->scp == scp) { // Found command + + list_del_init(&scb->list); // from pending list + + ASSERT(!(scb->state & SCB_ISSUED)); + + con_log(CL_ANN, (KERN_WARNING + "megaraid abort: %ld[%d:%d], driver owner\n", + scp->serial_number, scb->dev_channel, + scb->dev_target)); + + scp->result = (DID_ABORT << 16); + scp->scsi_done(scp); + + megaraid_dealloc_scb(adapter, scb); + + spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), + flags); + + return SUCCESS; + } + } + spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags); + + + // Check do we even own this command, in which case this would be + // owned by the firmware. The only way to locate the FW scb is to + // traverse through the list of all SCB, since driver does not + // maintain these SCBs on any list + found = 0; + for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) { + scb = adapter->kscb_list + i; + + if (scb->scp == scp) { + + found = 1; + + if (!(scb->state & SCB_ISSUED)) { + con_log(CL_ANN, (KERN_WARNING + "megaraid abort: %ld%d[%d:%d], invalid state\n", + scp->serial_number, scb->sno, scb->dev_channel, + scb->dev_target)); + BUG(); + } + else { + con_log(CL_ANN, (KERN_WARNING + "megaraid abort: %ld:%d[%d:%d], fw owner\n", + scp->serial_number, scb->sno, scb->dev_channel, + scb->dev_target)); + } + } + } + + if (!found) { + con_log(CL_ANN, (KERN_WARNING + "megaraid abort: scsi cmd:%ld, do now own\n", + scp->serial_number)); + + // FIXME: Should there be a callback for this command? + return SUCCESS; + } + + // We cannot actually abort a command owned by firmware, return + // failure and wait for reset. In host reset handler, we will find out + // if the HBA is still live + return FAILED; +} + + +/** + * megaraid_reset_handler - device reset hadler for mailbox based driver + * @scp : reference command + * + * Reset handler for the mailbox based controller. First try to find out if + * the FW is still live, in which case the outstanding commands counter mut go + * down to 0. If that happens, also issue the reservation reset command to + * relinquish (possible) reservations on the logical drives connected to this + * host + **/ +static int +megaraid_reset_handler(struct scsi_cmnd *scp) +{ + adapter_t *adapter; + scb_t *scb; + scb_t *tmp; + mraid_device_t *raid_dev; + unsigned long flags; + uint8_t raw_mbox[sizeof(mbox_t)]; + int rval; + int recovery_window; + int recovering; + int i; + + adapter = SCP2ADAPTER(scp); + raid_dev = ADAP2RAIDDEV(adapter); + + ASSERT(spin_is_locked(adapter->host_lock)); + + con_log(CL_ANN, (KERN_WARNING "megaraid: resetting the host...\n")); + + // return failure if adapter is not responding + if (raid_dev->hw_error) { + con_log(CL_ANN, (KERN_NOTICE + "megaraid: hw error, cannot reset\n")); + return FAILED; + } + + + // Under exceptional conditions, FW can take up to 3 minutes to + // complete command processing. Wait for additional 2 minutes for the + // pending commands counter to go down to 0. If it doesn't, let the + // controller be marked offline + // Also, reset all the commands currently owned by the driver + spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags); + list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) { + + list_del_init(&scb->list); // from pending list + + con_log(CL_ANN, (KERN_WARNING + "megaraid: %ld:%d[%d:%d], reset from pending list\n", + scp->serial_number, scb->sno, + scb->dev_channel, scb->dev_target)); + + scp->result = (DID_RESET << 16); + if (scp->scsi_done) { + scp->scsi_done(scp); + } + + megaraid_dealloc_scb(adapter, scb); + } + spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags); + + if (adapter->outstanding_cmds) { + con_log(CL_ANN, (KERN_NOTICE + "megaraid: %d outstanding commands. Max wait %d sec\n", + adapter->outstanding_cmds, MBOX_RESET_WAIT)); + } + + spin_unlock(adapter->host_lock); + + recovery_window = MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT; + + recovering = adapter->outstanding_cmds; + + for (i = 0; i < recovery_window && adapter->outstanding_cmds; i++) { + + megaraid_ack_sequence(adapter); + + // print a message once every 5 seconds only + if (!(i % 5)) { + con_log(CL_ANN, ( + "megaraid mbox: Wait for %d commands to complete:%d\n", + adapter->outstanding_cmds, + MBOX_RESET_WAIT - i)); + } + + // bailout if no recovery happended in reset time + if ((i == MBOX_RESET_WAIT) && + (recovering == adapter->outstanding_cmds)) { + break; + } + + msleep(1000); + } + + spin_lock(adapter->host_lock); + + // If still outstanding commands, bail out + if (adapter->outstanding_cmds) { + con_log(CL_ANN, (KERN_WARNING + "megaraid mbox: critical hardware error!\n")); + + raid_dev->hw_error = 1; + + return FAILED; + } + else { + con_log(CL_ANN, (KERN_NOTICE + "megaraid mbox: reset sequence completed successfully\n")); + } + + + // If the controller supports clustering, reset reservations + if (!adapter->ha) return SUCCESS; + + // clear reservations if any + raw_mbox[0] = CLUSTER_CMD; + raw_mbox[2] = RESET_RESERVATIONS; + + rval = SUCCESS; + if (mbox_post_sync_cmd_fast(adapter, raw_mbox) == 0) { + con_log(CL_ANN, + (KERN_INFO "megaraid: reservation reset\n")); + } + else { + rval = FAILED; + con_log(CL_ANN, (KERN_WARNING + "megaraid: reservation reset failed\n")); + } + + return rval; +} + + +/* + * START: internal commands library + * + * This section of the driver has the common routine used by the driver and + * also has all the FW routines + */ + +/** + * mbox_post_sync_cmd() - blocking command to the mailbox based controllers + * @adapter - controller's soft state + * @raw_mbox - the mailbox + * + * Issue a scb in synchronous and non-interrupt mode for mailbox based + * controllers + */ +static int +mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[]) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + mbox64_t *mbox64; + mbox_t *mbox; + uint8_t status; + int i; + + + mbox64 = raid_dev->mbox64; + mbox = raid_dev->mbox; + + /* + * Wait until mailbox is free + */ + if (megaraid_busywait_mbox(raid_dev) != 0) + goto blocked_mailbox; + + /* + * Copy mailbox data into host structure + */ + memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16); + mbox->cmdid = 0xFE; + mbox->busy = 1; + mbox->poll = 0; + mbox->ack = 0; + mbox->numstatus = 0xFF; + mbox->status = 0xFF; + + wmb(); + WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1); + + // wait for maximum 1 second for status to post. If the status is not + // available within 1 second, assume FW is initializing and wait + // for an extended amount of time + if (mbox->numstatus == 0xFF) { // status not yet available + udelay(25);; + + for (i = 0; mbox->numstatus == 0xFF && i < 1000; i++) { + rmb(); + msleep(1); + } + + + if (i == 1000) { + con_log(CL_ANN, (KERN_NOTICE + "megaraid mailbox: wait for FW to boot ")); + + for (i = 0; (mbox->numstatus == 0xFF) && + (i < MBOX_RESET_WAIT); i++) { + rmb(); + con_log(CL_ANN, ("\b\b\b\b\b[%03d]", + MBOX_RESET_WAIT - i)); + msleep(1000); + } + + if (i == MBOX_RESET_WAIT) { + + con_log(CL_ANN, ( + "\nmegaraid mailbox: status not available\n")); + + return -1; + } + con_log(CL_ANN, ("\b\b\b\b\b[ok] \n")); + } + } + + // wait for maximum 1 second for poll semaphore + if (mbox->poll != 0x77) { + udelay(25); + + for (i = 0; (mbox->poll != 0x77) && (i < 1000); i++) { + rmb(); + msleep(1); + } + + if (i == 1000) { + con_log(CL_ANN, (KERN_WARNING + "megaraid mailbox: could not get poll semaphore\n")); + return -1; + } + } + + WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x2); + wmb(); + + // wait for maximum 1 second for acknowledgement + if (RDINDOOR(raid_dev) & 0x2) { + udelay(25); + + for (i = 0; (RDINDOOR(raid_dev) & 0x2) && (i < 1000); i++) { + rmb(); + msleep(1); + } + + if (i == 1000) { + con_log(CL_ANN, (KERN_WARNING + "megaraid mailbox: could not acknowledge\n")); + return -1; + } + } + mbox->poll = 0; + mbox->ack = 0x77; + + status = mbox->status; + + // invalidate the completed command id array. After command + // completion, firmware would write the valid id. + mbox->numstatus = 0xFF; + mbox->status = 0xFF; + for (i = 0; i < MBOX_MAX_FIRMWARE_STATUS; i++) { + mbox->completed[i] = 0xFF; + } + + return status; + +blocked_mailbox: + + con_log(CL_ANN, (KERN_WARNING "megaraid: blocked mailbox\n") ); + return -1; +} + + +/** + * mbox_post_sync_cmd_fast - blocking command to the mailbox based controllers + * @adapter - controller's soft state + * @raw_mbox - the mailbox + * + * Issue a scb in synchronous and non-interrupt mode for mailbox based + * controllers. This is a faster version of the synchronous command and + * therefore can be called in interrupt-context as well + */ +static int +mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[]) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + mbox_t *mbox; + long i; + + + mbox = raid_dev->mbox; + + // return immediately if the mailbox is busy + if (mbox->busy) return -1; + + // Copy mailbox data into host structure + memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 14); + mbox->cmdid = 0xFE; + mbox->busy = 1; + mbox->poll = 0; + mbox->ack = 0; + mbox->numstatus = 0xFF; + mbox->status = 0xFF; + + wmb(); + WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1); + + for (i = 0; i < MBOX_SYNC_WAIT_CNT; i++) { + if (mbox->numstatus != 0xFF) break; + rmb(); + udelay(MBOX_SYNC_DELAY_200); + } + + if (i == MBOX_SYNC_WAIT_CNT) { + // We may need to re-calibrate the counter + con_log(CL_ANN, (KERN_CRIT + "megaraid: fast sync command timed out\n")); + } + + WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x2); + wmb(); + + return mbox->status; +} + + +/** + * megaraid_busywait_mbox() - Wait until the controller's mailbox is available + * @raid_dev - RAID device (HBA) soft state + * + * wait until the controller's mailbox is available to accept more commands. + * wait for at most 1 second + */ +static int +megaraid_busywait_mbox(mraid_device_t *raid_dev) +{ + mbox_t *mbox = raid_dev->mbox; + int i = 0; + + if (mbox->busy) { + udelay(25); + for (i = 0; mbox->busy && i < 1000; i++) + msleep(1); + } + + if (i < 1000) return 0; + else return -1; +} + + +/** + * megaraid_mbox_product_info - some static information about the controller + * @adapter - our soft state + * + * issue commands to the controller to grab some parameters required by our + * caller. + */ +static int +megaraid_mbox_product_info(adapter_t *adapter) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + mbox_t *mbox; + uint8_t raw_mbox[sizeof(mbox_t)]; + mraid_pinfo_t *pinfo; + dma_addr_t pinfo_dma_h; + mraid_inquiry3_t *mraid_inq3; + int i; + + + memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox)); + mbox = (mbox_t *)raw_mbox; + + /* + * Issue an ENQUIRY3 command to find out certain adapter parameters, + * e.g., max channels, max commands etc. + */ + pinfo = pci_alloc_consistent(adapter->pdev, sizeof(mraid_pinfo_t), + &pinfo_dma_h); + + if (pinfo == NULL) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: out of memory, %s %d\n", __FUNCTION__, + __LINE__)); + + return -1; + } + memset(pinfo, 0, sizeof(mraid_pinfo_t)); + + mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h; + memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE); + + raw_mbox[0] = FC_NEW_CONFIG; + raw_mbox[2] = NC_SUBOP_ENQUIRY3; + raw_mbox[3] = ENQ3_GET_SOLICITED_FULL; + + // Issue the command + if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) { + + con_log(CL_ANN, (KERN_WARNING "megaraid: Inquiry3 failed\n")); + + pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t), + pinfo, pinfo_dma_h); + + return -1; + } + + /* + * Collect information about state of each physical drive + * attached to the controller. We will expose all the disks + * which are not part of RAID + */ + mraid_inq3 = (mraid_inquiry3_t *)adapter->ibuf; + for (i = 0; i < MBOX_MAX_PHYSICAL_DRIVES; i++) { + raid_dev->pdrv_state[i] = mraid_inq3->pdrv_state[i]; + } + + /* + * Get product info for information like number of channels, + * maximum commands supported. + */ + memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox)); + mbox->xferaddr = (uint32_t)pinfo_dma_h; + + raw_mbox[0] = FC_NEW_CONFIG; + raw_mbox[2] = NC_SUBOP_PRODUCT_INFO; + + if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid: product info failed\n")); + + pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t), + pinfo, pinfo_dma_h); + + return -1; + } + + /* + * Setup some parameters for host, as required by our caller + */ + adapter->max_channel = pinfo->nchannels; + + /* + * we will export all the logical drives on a single channel. + * Add 1 since inquires do not come for inititor ID + */ + adapter->max_target = MAX_LOGICAL_DRIVES_40LD + 1; + adapter->max_lun = 8; // up to 8 LUNs for non-disk devices + + /* + * These are the maximum outstanding commands for the scsi-layer + */ + adapter->max_cmds = MBOX_MAX_SCSI_CMDS; + + memset(adapter->fw_version, 0, VERSION_SIZE); + memset(adapter->bios_version, 0, VERSION_SIZE); + + memcpy(adapter->fw_version, pinfo->fw_version, 4); + adapter->fw_version[4] = 0; + + memcpy(adapter->bios_version, pinfo->bios_version, 4); + adapter->bios_version[4] = 0; + + con_log(CL_ANN, (KERN_NOTICE + "megaraid: fw version:[%s] bios version:[%s]\n", + adapter->fw_version, adapter->bios_version)); + + pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t), pinfo, + pinfo_dma_h); + + return 0; +} + + + +/** + * megaraid_mbox_extended_cdb - check for support for extended CDBs + * @adapter - soft state for the controller + * + * this routine check whether the controller in question supports extended + * ( > 10 bytes ) CDBs + */ +static int +megaraid_mbox_extended_cdb(adapter_t *adapter) +{ + mbox_t *mbox; + uint8_t raw_mbox[sizeof(mbox_t)]; + int rval; + + mbox = (mbox_t *)raw_mbox; + + memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox)); + mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h; + + memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE); + + raw_mbox[0] = MAIN_MISC_OPCODE; + raw_mbox[2] = SUPPORT_EXT_CDB; + + /* + * Issue the command + */ + rval = 0; + if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) { + rval = -1; + } + + return rval; +} + + +/** + * megaraid_mbox_support_ha - Do we support clustering + * @adapter - soft state for the controller + * @init_id - ID of the initiator + * + * Determine if the firmware supports clustering and the ID of the initiator. + */ +static int +megaraid_mbox_support_ha(adapter_t *adapter, uint16_t *init_id) +{ + mbox_t *mbox; + uint8_t raw_mbox[sizeof(mbox_t)]; + int rval; + + + mbox = (mbox_t *)raw_mbox; + + memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox)); + + mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h; + + memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE); + + raw_mbox[0] = GET_TARGET_ID; + + // Issue the command + *init_id = 7; + rval = -1; + if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) { + + *init_id = *(uint8_t *)adapter->ibuf; + + con_log(CL_ANN, (KERN_INFO + "megaraid: cluster firmware, initiator ID: %d\n", + *init_id)); + + rval = 0; + } + + return rval; +} + + +/** + * megaraid_mbox_support_random_del - Do we support random deletion + * @adapter - soft state for the controller + * + * Determine if the firmware supports random deletion + * Return: 1 is operation supported, 0 otherwise + */ +static int +megaraid_mbox_support_random_del(adapter_t *adapter) +{ + mbox_t *mbox; + uint8_t raw_mbox[sizeof(mbox_t)]; + int rval; + + + mbox = (mbox_t *)raw_mbox; + + memset((caddr_t)raw_mbox, 0, sizeof(mbox_t)); + + raw_mbox[0] = FC_DEL_LOGDRV; + raw_mbox[2] = OP_SUP_DEL_LOGDRV; + + // Issue the command + rval = 0; + if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) { + + con_log(CL_DLEVEL1, ("megaraid: supports random deletion\n")); + + rval = 1; + } + + return rval; +} + + +/** + * megaraid_mbox_get_max_sg - maximum sg elements supported by the firmware + * @adapter - soft state for the controller + * + * Find out the maximum number of scatter-gather elements supported by the + * firmware + */ +static int +megaraid_mbox_get_max_sg(adapter_t *adapter) +{ + mbox_t *mbox; + uint8_t raw_mbox[sizeof(mbox_t)]; + int nsg; + + + mbox = (mbox_t *)raw_mbox; + + memset((caddr_t)raw_mbox, 0, sizeof(mbox_t)); + + mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h; + + memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE); + + raw_mbox[0] = MAIN_MISC_OPCODE; + raw_mbox[2] = GET_MAX_SG_SUPPORT; + + // Issue the command + if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) { + nsg = *(uint8_t *)adapter->ibuf; + } + else { + nsg = MBOX_DEFAULT_SG_SIZE; + } + + if (nsg > MBOX_MAX_SG_SIZE) nsg = MBOX_MAX_SG_SIZE; + + return nsg; +} + + +/** + * megaraid_mbox_enum_raid_scsi - enumerate the RAID and SCSI channels + * @adapter - soft state for the controller + * + * Enumerate the RAID and SCSI channels for ROMB platoforms so that channels + * can be exported as regular SCSI channels + */ +static void +megaraid_mbox_enum_raid_scsi(adapter_t *adapter) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + mbox_t *mbox; + uint8_t raw_mbox[sizeof(mbox_t)]; + + + mbox = (mbox_t *)raw_mbox; + + memset((caddr_t)raw_mbox, 0, sizeof(mbox_t)); + + mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h; + + memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE); + + raw_mbox[0] = CHNL_CLASS; + raw_mbox[2] = GET_CHNL_CLASS; + + // Issue the command. If the command fails, all channels are RAID + // channels + raid_dev->channel_class = 0xFF; + if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) { + raid_dev->channel_class = *(uint8_t *)adapter->ibuf; + } + + return; +} + + +/** + * megaraid_mbox_flush_cache - flush adapter and disks cache + * @param adapter : soft state for the controller + * + * Flush adapter cache followed by disks cache + */ +static void +megaraid_mbox_flush_cache(adapter_t *adapter) +{ + mbox_t *mbox; + uint8_t raw_mbox[sizeof(mbox_t)]; + + + mbox = (mbox_t *)raw_mbox; + + memset((caddr_t)raw_mbox, 0, sizeof(mbox_t)); + + raw_mbox[0] = FLUSH_ADAPTER; + + if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) { + con_log(CL_ANN, ("megaraid: flush adapter failed\n")); + } + + raw_mbox[0] = FLUSH_SYSTEM; + + if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) { + con_log(CL_ANN, ("megaraid: flush disks cache failed\n")); + } + + return; +} + + +/** + * megaraid_mbox_display_scb - display SCB information, mostly debug purposes + * @param adapter : controllers' soft state + * @param scb : SCB to be displayed + * @param level : debug level for console print + * + * Diplay information about the given SCB iff the current debug level is + * verbose + */ +static void +megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb) +{ + mbox_ccb_t *ccb; + struct scsi_cmnd *scp; + mbox_t *mbox; + int level; + int i; + + + ccb = (mbox_ccb_t *)scb->ccb; + scp = scb->scp; + mbox = ccb->mbox; + + level = CL_DLEVEL3; + + con_log(level, (KERN_NOTICE + "megaraid mailbox: status:%#x cmd:%#x id:%#x ", scb->status, + mbox->cmd, scb->sno)); + + con_log(level, ("sec:%#x lba:%#x addr:%#x ld:%d sg:%d\n", + mbox->numsectors, mbox->lba, mbox->xferaddr, mbox->logdrv, + mbox->numsge)); + + if (!scp) return; + + con_log(level, (KERN_NOTICE "scsi cmnd: ")); + + for (i = 0; i < scp->cmd_len; i++) { + con_log(level, ("%#2.02x ", scp->cmnd[i])); + } + + con_log(level, ("\n")); + + return; +} + + +/** + * megaraid_mbox_setup_device_map - manage device ids + * @adapter : Driver's soft state + * + * Manange the device ids to have an appropraite mapping between the kernel + * scsi addresses and megaraid scsi and logical drive addresses. We export + * scsi devices on their actual addresses, whereas the logical drives are + * exported on a virtual scsi channel. + **/ +static void +megaraid_mbox_setup_device_map(adapter_t *adapter) +{ + uint8_t c; + uint8_t t; + + /* + * First fill the values on the logical drive channel + */ + for (t = 0; t < LSI_MAX_LOGICAL_DRIVES_64LD; t++) + adapter->device_ids[adapter->max_channel][t] = + (t < adapter->init_id) ? t : t - 1; + + adapter->device_ids[adapter->max_channel][adapter->init_id] = 0xFF; + + /* + * Fill the values on the physical devices channels + */ + for (c = 0; c < adapter->max_channel; c++) + for (t = 0; t < LSI_MAX_LOGICAL_DRIVES_64LD; t++) + adapter->device_ids[c][t] = (c << 8) | t; +} + + +/* + * END: internal commands library + */ + +/* + * START: Interface for the common management module + * + * This is the module, which interfaces with the common mangement module to + * provide support for ioctl and sysfs + */ + +/** + * megaraid_cmm_register - register with the mangement module + * @param adapter : HBA soft state + * + * Register with the management module, which allows applications to issue + * ioctl calls to the drivers. This interface is used by the management module + * to setup sysfs support as well. + */ +static int +megaraid_cmm_register(adapter_t *adapter) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + mraid_mmadp_t adp; + scb_t *scb; + mbox_ccb_t *ccb; + int rval; + int i; + + // Allocate memory for the base list of scb for management module. + adapter->uscb_list = kmalloc(sizeof(scb_t) * MBOX_MAX_USER_CMDS, + GFP_KERNEL); + + if (adapter->uscb_list == NULL) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: out of memory, %s %d\n", __FUNCTION__, + __LINE__)); + return -1; + } + memset(adapter->uscb_list, 0, sizeof(scb_t) * MBOX_MAX_USER_CMDS); + + + // Initialize the synchronization parameters for resources for + // commands for management module + INIT_LIST_HEAD(&adapter->uscb_pool); + + spin_lock_init(USER_FREE_LIST_LOCK(adapter)); + + + + // link all the packets. Note, CCB for commands, coming from the + // commom management module, mailbox physical address are already + // setup by it. We just need placeholder for that in our local command + // control blocks + for (i = 0; i < MBOX_MAX_USER_CMDS; i++) { + + scb = adapter->uscb_list + i; + ccb = raid_dev->uccb_list + i; + + scb->ccb = (caddr_t)ccb; + ccb->mbox64 = raid_dev->umbox64 + i; + ccb->mbox = &ccb->mbox64->mbox32; + ccb->raw_mbox = (uint8_t *)ccb->mbox; + + scb->gp = 0; + + // COMMAND ID 0 - (MBOX_MAX_SCSI_CMDS-1) ARE RESERVED FOR + // COMMANDS COMING FROM IO SUBSYSTEM (MID-LAYER) + scb->sno = i + MBOX_MAX_SCSI_CMDS; + + scb->scp = NULL; + scb->state = SCB_FREE; + scb->dma_direction = PCI_DMA_NONE; + scb->dma_type = MRAID_DMA_NONE; + scb->dev_channel = -1; + scb->dev_target = -1; + + // put scb in the free pool + list_add_tail(&scb->list, &adapter->uscb_pool); + } + + adp.unique_id = adapter->unique_id; + adp.drvr_type = DRVRTYPE_MBOX; + adp.drvr_data = (unsigned long)adapter; + adp.pdev = adapter->pdev; + adp.issue_uioc = megaraid_mbox_mm_handler; + adp.timeout = 300; + adp.max_kioc = MBOX_MAX_USER_CMDS; + + if ((rval = mraid_mm_register_adp(&adp)) != 0) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid mbox: did not register with CMM\n")); + + kfree(adapter->uscb_list); + } + + return rval; +} + + +/** + * megaraid_cmm_unregister - un-register with the mangement module + * @param adapter : HBA soft state + * + * Un-register with the management module. + * FIXME: mgmt module must return failure for unregister if it has pending + * commands in LLD + */ +static int +megaraid_cmm_unregister(adapter_t *adapter) +{ + kfree(adapter->uscb_list); + mraid_mm_unregister_adp(adapter->unique_id); + return 0; +} + + +/** + * megaraid_mbox_mm_handler - interface for CMM to issue commands to LLD + * @param drvr_data : LLD specific data + * @param kioc : CMM interface packet + * @param action : command action + * + * This routine is invoked whenever the Common Mangement Module (CMM) has a + * command for us. The 'action' parameter specifies if this is a new command + * or otherwise. + */ +static int +megaraid_mbox_mm_handler(unsigned long drvr_data, uioc_t *kioc, uint32_t action) +{ + adapter_t *adapter; + + if (action != IOCTL_ISSUE) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: unsupported management action:%#2x\n", + action)); + return (-ENOTSUPP); + } + + adapter = (adapter_t *)drvr_data; + + // make sure this adapter is not being detached right now. + if (atomic_read(&adapter->being_detached)) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: reject management request, detaching\n")); + return (-ENODEV); + } + + switch (kioc->opcode) { + + case GET_ADAP_INFO: + + kioc->status = gather_hbainfo(adapter, (mraid_hba_info_t *) + (unsigned long)kioc->buf_vaddr); + + kioc->done(kioc); + + return kioc->status; + + case MBOX_CMD: + + return megaraid_mbox_mm_command(adapter, kioc); + + default: + kioc->status = (-EINVAL); + kioc->done(kioc); + return (-EINVAL); + } + + return 0; // not reached +} + +/** + * megaraid_mbox_mm_command - issues commands routed through CMM + * @param adapter : HBA soft state + * @param kioc : management command packet + * + * Issues commands, which are routed through the management module. + */ +static int +megaraid_mbox_mm_command(adapter_t *adapter, uioc_t *kioc) +{ + struct list_head *head = &adapter->uscb_pool; + mbox64_t *mbox64; + uint8_t *raw_mbox; + scb_t *scb; + mbox_ccb_t *ccb; + unsigned long flags; + + // detach one scb from free pool + spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags); + + if (list_empty(head)) { // should never happen because of CMM + + con_log(CL_ANN, (KERN_WARNING + "megaraid mbox: bug in cmm handler, lost resources\n")); + + spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags); + + return (-EINVAL); + } + + scb = list_entry(head->next, scb_t, list); + list_del_init(&scb->list); + + spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags); + + scb->state = SCB_ACTIVE; + scb->dma_type = MRAID_DMA_NONE; + scb->dma_direction = PCI_DMA_NONE; + + ccb = (mbox_ccb_t *)scb->ccb; + mbox64 = (mbox64_t *)(unsigned long)kioc->cmdbuf; + raw_mbox = (uint8_t *)&mbox64->mbox32; + + memcpy(ccb->mbox64, mbox64, sizeof(mbox64_t)); + + scb->gp = (unsigned long)kioc; + + /* + * If it is a logdrv random delete operation, we have to wait till + * there are no outstanding cmds at the fw and then issue it directly + */ + if (raw_mbox[0] == FC_DEL_LOGDRV && raw_mbox[2] == OP_DEL_LOGDRV) { + + if (wait_till_fw_empty(adapter)) { + con_log(CL_ANN, (KERN_NOTICE + "megaraid mbox: LD delete, timed out\n")); + + kioc->status = -ETIME; + + scb->status = -1; + + megaraid_mbox_mm_done(adapter, scb); + + return (-ETIME); + } + + INIT_LIST_HEAD(&scb->list); + + scb->state = SCB_ISSUED; + if (mbox_post_cmd(adapter, scb) != 0) { + + con_log(CL_ANN, (KERN_NOTICE + "megaraid mbox: LD delete, mailbox busy\n")); + + kioc->status = -EBUSY; + + scb->status = -1; + + megaraid_mbox_mm_done(adapter, scb); + + return (-EBUSY); + } + + return 0; + } + + // put the command on the pending list and execute + megaraid_mbox_runpendq(adapter, scb); + + return 0; +} + + +static int +wait_till_fw_empty(adapter_t *adapter) +{ + unsigned long flags = 0; + int i; + + + /* + * Set the quiescent flag to stop issuing cmds to FW. + */ + spin_lock_irqsave(adapter->host_lock, flags); + adapter->quiescent++; + spin_unlock_irqrestore(adapter->host_lock, flags); + + /* + * Wait till there are no more cmds outstanding at FW. Try for at most + * 60 seconds + */ + for (i = 0; i < 60 && adapter->outstanding_cmds; i++) { + con_log(CL_DLEVEL1, (KERN_INFO + "megaraid: FW has %d pending commands\n", + adapter->outstanding_cmds)); + + msleep(1000); + } + + return adapter->outstanding_cmds; +} + + +/** + * megaraid_mbox_mm_done - callback for CMM commands + * @adapter : HBA soft state + * @scb : completed command + * + * Callback routine for internal commands originated from the management + * module. + */ +static void +megaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb) +{ + uioc_t *kioc; + mbox64_t *mbox64; + uint8_t *raw_mbox; + unsigned long flags; + + kioc = (uioc_t *)scb->gp; + kioc->status = 0; + mbox64 = (mbox64_t *)(unsigned long)kioc->cmdbuf; + mbox64->mbox32.status = scb->status; + raw_mbox = (uint8_t *)&mbox64->mbox32; + + + // put scb in the free pool + scb->state = SCB_FREE; + scb->scp = NULL; + + spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags); + + list_add(&scb->list, &adapter->uscb_pool); + + spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags); + + // if a delete logical drive operation succeeded, restart the + // controller + if (raw_mbox[0] == FC_DEL_LOGDRV && raw_mbox[2] == OP_DEL_LOGDRV) { + + adapter->quiescent--; + + megaraid_mbox_runpendq(adapter, NULL); + } + + kioc->done(kioc); + + return; +} + + +/** + * gather_hbainfo - HBA characteristics for the applications + * @param adapter : HBA soft state + * @param hinfo : pointer to the caller's host info strucuture + */ +static int +gather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo) +{ + uint8_t dmajor; + + dmajor = megaraid_mbox_version[0]; + + hinfo->pci_vendor_id = adapter->pdev->vendor; + hinfo->pci_device_id = adapter->pdev->device; + hinfo->subsys_vendor_id = adapter->pdev->subsystem_vendor; + hinfo->subsys_device_id = adapter->pdev->subsystem_device; + + hinfo->pci_bus = adapter->pdev->bus->number; + hinfo->pci_dev_fn = adapter->pdev->devfn; + hinfo->pci_slot = PCI_SLOT(adapter->pdev->devfn); + hinfo->irq = adapter->host->irq; + hinfo->baseport = ADAP2RAIDDEV(adapter)->baseport; + + hinfo->unique_id = (hinfo->pci_bus << 8) | adapter->pdev->devfn; + hinfo->host_no = adapter->host->host_no; + + return 0; +} + +/* + * END: Interface for the common management module + */ + + +extern struct scsi_device *mraid_mm_diskdump_poll_device; +extern void (*mraid_mm_poll_func)(struct scsi_device *device); + +static int +megaraid_sanity_check(struct scsi_device *device) +{ + adapter_t *adapter; + + adapter = (adapter_t *)SCSIHOST2ADAP(device->host); + if ( adapter == NULL ) { + return -ENXIO; + } +#ifdef SCSI_HAS_HOST_LOCK + if (spin_is_locked(adapter->host_lock)) { + return -EBUSY; + } +#endif + mraid_mm_poll_func = megaraid_poll; + mraid_mm_diskdump_poll_device = device; + return 0; +} + + +static int +megaraid_quiesce(struct scsi_device *device) +{ + adapter_t *adapter; + + adapter = (adapter_t *)SCSIHOST2ADAP(device->host); + /* + * In case of crash dump, the tasklet list has been already abandoned + * so the tasklet_struct must be reinitialized. + * If it is not done, the tasklet is not scheduled because of garbage. + */ + tasklet_init(&adapter->dpc_h, megaraid_mbox_dpc, + (unsigned long)adapter); + + return 0; +} + + +static void +megaraid_poll(struct scsi_device *device) +{ + adapter_t *adapter; + u32 dword = 0; + mraid_device_t *raid_dev; + + adapter = (adapter_t *)SCSIHOST2ADAP(device->host); + /* Check if a valid interrupt is pending */ + raid_dev = ADAP2RAIDDEV(adapter); + dword = RDOUTDOOR(raid_dev); + if ( dword != 0x10001234 ) { + /* + * No more pending commands + */ + return; + } + megaraid_isr(0, adapter, NULL); +} + + +static void +megaraid_diskdump_sleep(unsigned int timeout) +{ + unsigned long expire; + + if (!mraid_mm_diskdump_poll_device) { + return; + } + + expire = (unsigned long)timeout + jiffies; + mraid_mm_woken = 0; + while (time_before(jiffies, expire)) { + megaraid_poll(mraid_mm_diskdump_poll_device); + udelay(100); + diskdump_update(); + if (mraid_mm_woken) + return; + } + return; +} + + + +/** + * megaraid_sysfs_alloc_resources - allocate sysfs related resources + * + * Allocate packets required to issue FW calls whenever the sysfs attributes + * are read. These attributes would require up-to-date information from the + * FW. Also set up resources for mutual exclusion to share these resources and + * the wait queue. + * + * @param adapter : controller's soft state + * + * @return 0 on success + * @return -ERROR_CODE on failure + */ +static int +megaraid_sysfs_alloc_resources(adapter_t *adapter) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + int rval = 0; + + raid_dev->sysfs_uioc = kmalloc(sizeof(uioc_t), GFP_KERNEL); + + raid_dev->sysfs_mbox64 = kmalloc(sizeof(mbox64_t), GFP_KERNEL); + + raid_dev->sysfs_buffer = pci_alloc_consistent(adapter->pdev, + PAGE_SIZE, &raid_dev->sysfs_buffer_dma); + + if (!raid_dev->sysfs_uioc || !raid_dev->sysfs_mbox64 || + !raid_dev->sysfs_buffer) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid: out of memory, %s %d\n", __FUNCTION__, + __LINE__)); + + rval = -ENOMEM; + + megaraid_sysfs_free_resources(adapter); + } + + sema_init(&raid_dev->sysfs_sem, 1); + + init_waitqueue_head(&raid_dev->sysfs_wait_q); + + return rval; +} + + +/** + * megaraid_sysfs_free_resources - free sysfs related resources + * + * Free packets allocated for sysfs FW commands + * + * @param adapter : controller's soft state + */ +static void +megaraid_sysfs_free_resources(adapter_t *adapter) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + + if (raid_dev->sysfs_uioc) kfree(raid_dev->sysfs_uioc); + + if (raid_dev->sysfs_mbox64) kfree(raid_dev->sysfs_mbox64); + + if (raid_dev->sysfs_buffer) { + pci_free_consistent(adapter->pdev, PAGE_SIZE, + raid_dev->sysfs_buffer, raid_dev->sysfs_buffer_dma); + } +} + + +/** + * megaraid_sysfs_get_ldmap_done - callback for get ldmap + * + * Callback routine called in the ISR/tasklet context for get ldmap call + * + * @param uioc : completed packet + */ +static void +megaraid_sysfs_get_ldmap_done(uioc_t *uioc) +{ + adapter_t *adapter = (adapter_t *)uioc->buf_vaddr; + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + + uioc->status = 0; + + wake_up(&raid_dev->sysfs_wait_q); +} + + +/** + * megaraid_sysfs_get_ldmap_timeout - timeout handling for get ldmap + * + * Timeout routine to recover and return to application, in case the adapter + * has stopped responding. A timeout of 60 seconds for this command seem like + * a good value + * + * @param uioc : timed out packet + */ +static void +megaraid_sysfs_get_ldmap_timeout(unsigned long data) +{ + uioc_t *uioc = (uioc_t *)data; + adapter_t *adapter = (adapter_t *)uioc->buf_vaddr; + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + + uioc->status = -ETIME; + + wake_up(&raid_dev->sysfs_wait_q); +} + + +/** + * megaraid_sysfs_get_ldmap - get update logical drive map + * + * This routine will be called whenever user reads the logical drive + * attributes, go get the current logical drive mapping table from the + * firmware. We use the managment API's to issue commands to the controller. + * + * NOTE: The commands issuance functionality is not generalized and + * implemented in context of "get ld map" command only. If required, the + * command issuance logical can be trivially pulled out and implemented as a + * standalone libary. For now, this should suffice since there is no other + * user of this interface. + * + * @param adapter : controller's soft state + * + * @return 0 on success + * @return -1 on failure + */ +static int +megaraid_sysfs_get_ldmap(adapter_t *adapter) +{ + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + uioc_t *uioc; + mbox64_t *mbox64; + mbox_t *mbox; + char *raw_mbox; + struct timer_list sysfs_timer; + struct timer_list *timerp; + caddr_t ldmap; + int rval = 0; + + /* + * Allow only one read at a time to go through the sysfs attributes + */ + down(&raid_dev->sysfs_sem); + + uioc = raid_dev->sysfs_uioc; + mbox64 = raid_dev->sysfs_mbox64; + ldmap = raid_dev->sysfs_buffer; + + memset(uioc, 0, sizeof(uioc_t)); + memset(mbox64, 0, sizeof(mbox64_t)); + memset(ldmap, 0, sizeof(raid_dev->curr_ldmap)); + + mbox = &mbox64->mbox32; + raw_mbox = (char *)mbox; + uioc->cmdbuf = (uint64_t)(unsigned long)mbox64; + uioc->buf_vaddr = (caddr_t)adapter; + uioc->status = -ENODATA; + uioc->done = megaraid_sysfs_get_ldmap_done; + + /* + * Prepare the mailbox packet to get the current logical drive mapping + * table + */ + mbox->xferaddr = (uint32_t)raid_dev->sysfs_buffer_dma; + + raw_mbox[0] = FC_DEL_LOGDRV; + raw_mbox[2] = OP_GET_LDID_MAP; + + /* + * Setup a timer to recover from a non-responding controller + */ + timerp = &sysfs_timer; + init_timer(timerp); + + timerp->function = megaraid_sysfs_get_ldmap_timeout; + timerp->data = (unsigned long)uioc; + timerp->expires = jiffies + 60 * HZ; + + add_timer(timerp); + + /* + * Send the command to the firmware + */ + rval = megaraid_mbox_mm_command(adapter, uioc); + + if (rval == 0) { // command successfully issued + wait_event(raid_dev->sysfs_wait_q, (uioc->status != -ENODATA)); + + /* + * Check if the command timed out + */ + if (uioc->status == -ETIME) { + con_log(CL_ANN, (KERN_NOTICE + "megaraid: sysfs get ld map timed out\n")); + + rval = -ETIME; + } + else { + rval = mbox->status; + } + + if (rval == 0) { + memcpy(raid_dev->curr_ldmap, ldmap, + sizeof(raid_dev->curr_ldmap)); + } + else { + con_log(CL_ANN, (KERN_NOTICE + "megaraid: get ld map failed with %x\n", rval)); + } + } + else { + con_log(CL_ANN, (KERN_NOTICE + "megaraid: could not issue ldmap command:%x\n", rval)); + } + + + del_timer_sync(timerp); + + up(&raid_dev->sysfs_sem); + + return rval; +} + + +/** + * megaraid_sysfs_show_app_hndl - display application handle for this adapter + * + * Display the handle used by the applications while executing management + * tasks on the adapter. We invoke a management module API to get the adapter + * handle, since we do not interface with applications directly. + * + * @param cdev : class device object representation for the host + * @param buf : buffer to send data to + */ +static ssize_t +megaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + adapter_t *adapter = (adapter_t *)SCSIHOST2ADAP(shost); + uint32_t app_hndl; + + app_hndl = mraid_mm_adapter_app_handle(adapter->unique_id); + + return snprintf(buf, 8, "%u\n", app_hndl); +} + + +/** + * megaraid_sysfs_show_ldnum - display the logical drive number for this device + * + * Display the logical drive number for the device in question, if it a valid + * logical drive. For physical devices, "-1" is returned + * The logical drive number is displayed in following format + * + * + * + * + * @param dev : device object representation for the scsi device + * @param buf : buffer to send data to + */ +static ssize_t +megaraid_sysfs_show_ldnum(struct device *dev, char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + adapter_t *adapter = (adapter_t *)SCSIHOST2ADAP(sdev->host); + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + int scsi_id = -1; + int logical_drv = -1; + int ldid_map = -1; + uint32_t app_hndl = 0; + int mapped_sdev_id; + int rval; + int i; + + if (raid_dev->random_del_supported && + MRAID_IS_LOGICAL_SDEV(adapter, sdev)) { + + rval = megaraid_sysfs_get_ldmap(adapter); + if (rval == 0) { + + for (i = 0; i < MAX_LOGICAL_DRIVES_40LD; i++) { + + mapped_sdev_id = sdev->id; + + if (sdev->id > adapter->init_id) { + mapped_sdev_id -= 1; + } + + if (raid_dev->curr_ldmap[i] == mapped_sdev_id) { + + scsi_id = sdev->id; + + logical_drv = i; + + ldid_map = raid_dev->curr_ldmap[i]; + + app_hndl = mraid_mm_adapter_app_handle( + adapter->unique_id); + + break; + } + } + } + else { + con_log(CL_ANN, (KERN_NOTICE + "megaraid: sysfs get ld map failed: %x\n", + rval)); + } + } + + return snprintf(buf, 36, "%d %d %d %d\n", scsi_id, logical_drv, + ldid_map, app_hndl); +} + + +/* + * END: Mailbox Low Level Driver + */ +module_init(megaraid_init); +module_exit(megaraid_exit); + +/* vim: set ts=8 sw=8 tw=78 ai si: */ diff --git a/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_mbox.h b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_mbox.h new file mode 100644 index 0000000..6a89d21 --- /dev/null +++ b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_mbox.h @@ -0,0 +1,237 @@ +/* + * + * Linux MegaRAID device driver + * + * Copyright (c) 2003-2004 LSI Logic Corporation. + * + * 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. + * + * FILE : megaraid_mbox.h + */ + +#ifndef _MEGARAID_H_ +#define _MEGARAID_H_ + + +#include "mega_common.h" +#include "mbox_defs.h" +#include "megaraid_ioctl.h" + + +#define MEGARAID_VERSION "2.20.4.6-rh2" +#define MEGARAID_EXT_VERSION "(Release Date: Wed Jun 28 12:27:22 EST 2006)" + + +/* + * Define some PCI values here until they are put in the kernel + */ +#define PCI_DEVICE_ID_PERC4_DI_DISCOVERY 0x000E +#define PCI_SUBSYS_ID_PERC4_DI_DISCOVERY 0x0123 + +#define PCI_DEVICE_ID_PERC4_SC 0x1960 +#define PCI_SUBSYS_ID_PERC4_SC 0x0520 + +#define PCI_DEVICE_ID_PERC4_DC 0x1960 +#define PCI_SUBSYS_ID_PERC4_DC 0x0518 + +#define PCI_DEVICE_ID_VERDE 0x0407 + +#define PCI_DEVICE_ID_PERC4_DI_EVERGLADES 0x000F +#define PCI_SUBSYS_ID_PERC4_DI_EVERGLADES 0x014A + +#define PCI_DEVICE_ID_PERC4E_SI_BIGBEND 0x0013 +#define PCI_SUBSYS_ID_PERC4E_SI_BIGBEND 0x016c + +#define PCI_DEVICE_ID_PERC4E_DI_KOBUK 0x0013 +#define PCI_SUBSYS_ID_PERC4E_DI_KOBUK 0x016d + +#define PCI_DEVICE_ID_PERC4E_DI_CORVETTE 0x0013 +#define PCI_SUBSYS_ID_PERC4E_DI_CORVETTE 0x016e + +#define PCI_DEVICE_ID_PERC4E_DI_EXPEDITION 0x0013 +#define PCI_SUBSYS_ID_PERC4E_DI_EXPEDITION 0x016f + +#define PCI_DEVICE_ID_PERC4E_DI_GUADALUPE 0x0013 +#define PCI_SUBSYS_ID_PERC4E_DI_GUADALUPE 0x0170 + +#define PCI_DEVICE_ID_DOBSON 0x0408 + +#define PCI_DEVICE_ID_MEGARAID_SCSI_320_0 0x1960 +#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_0 0xA520 + +#define PCI_DEVICE_ID_MEGARAID_SCSI_320_1 0x1960 +#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_1 0x0520 + +#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2 0x1960 +#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2 0x0518 + +#define PCI_DEVICE_ID_MEGARAID_I4_133_RAID 0x1960 +#define PCI_SUBSYS_ID_MEGARAID_I4_133_RAID 0x0522 + +#define PCI_DEVICE_ID_MEGARAID_SATA_150_4 0x1960 +#define PCI_SUBSYS_ID_MEGARAID_SATA_150_4 0x4523 + +#define PCI_DEVICE_ID_MEGARAID_SATA_150_6 0x1960 +#define PCI_SUBSYS_ID_MEGARAID_SATA_150_6 0x0523 + +#define PCI_DEVICE_ID_LINDSAY 0x0409 + +#define PCI_DEVICE_ID_INTEL_RAID_SRCS16 0x1960 +#define PCI_SUBSYS_ID_INTEL_RAID_SRCS16 0x0523 + +#define PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK 0x1960 +#define PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK 0x0520 + +#define PCI_SUBSYS_ID_PERC3_QC 0x0471 +#define PCI_SUBSYS_ID_PERC3_DC 0x0493 +#define PCI_SUBSYS_ID_PERC3_SC 0x0475 + + +#define MBOX_MAX_SCSI_CMDS 128 // number of cmds reserved for kernel +#define MBOX_MAX_USER_CMDS 32 // number of cmds for applications +#define MBOX_DEF_CMD_PER_LUN 64 // default commands per lun +#define MBOX_DEFAULT_SG_SIZE 26 // default sg size supported by all fw +#define MBOX_MAX_SG_SIZE 32 // maximum scatter-gather list size +#define MBOX_MAX_SECTORS 128 // maximum sectors per IO +#define MBOX_TIMEOUT 30 // timeout value for internal cmds +#define MBOX_BUSY_WAIT 10 // max usec to wait for busy mailbox +#define MBOX_RESET_WAIT 180 // wait these many seconds in reset +#define MBOX_RESET_EXT_WAIT 120 // extended wait reset +#define MBOX_SYNC_WAIT_CNT 0xFFFF // wait loop index for synchronous mode + +#define MBOX_SYNC_DELAY_200 200 // 200 micro-secondes + +/* + * maximum transfer that can happen through the firmware commands issued + * internnaly from the driver. + */ +#define MBOX_IBUF_SIZE 4096 + + +/** + * mbox_ccb_t - command control block specific to mailbox based controllers + * @raw_mbox : raw mailbox pointer + * @mbox : mailbox + * @mbox64 : extended mailbox + * @mbox_dma_h : maibox dma address + * @sgl64 : 64-bit scatter-gather list + * @sgl32 : 32-bit scatter-gather list + * @sgl_dma_h : dma handle for the scatter-gather list + * @pthru : passthru structure + * @pthru_dma_h : dma handle for the passthru structure + * @epthru : extended passthru structure + * @epthru_dma_h : dma handle for extended passthru structure + * @buf_dma_h : dma handle for buffers w/o sg list + * + * command control block specific to the mailbox based controllers + */ +typedef struct { + uint8_t *raw_mbox; + mbox_t *mbox; + mbox64_t *mbox64; + dma_addr_t mbox_dma_h; + mbox_sgl64 *sgl64; + mbox_sgl32 *sgl32; + dma_addr_t sgl_dma_h; + mraid_passthru_t *pthru; + dma_addr_t pthru_dma_h; + mraid_epassthru_t *epthru; + dma_addr_t epthru_dma_h; + dma_addr_t buf_dma_h; +} mbox_ccb_t; + + +/** + * mraid_device_t - adapter soft state structure for mailbox controllers + * @param una_mbox64 : 64-bit mbox - unaligned + * @param una_mbox64_dma : mbox dma addr - unaligned + * @param mbox : 32-bit mbox - aligned + * @param mbox64 : 64-bit mbox - aligned + * @param mbox_dma : mbox dma addr - aligned + * @param mailbox_lock : exclusion lock for the mailbox + * @param baseport : base port of hba memory + * @param baseaddr : mapped addr of hba memory + * @param mbox_pool : pool of mailboxes + * @param mbox_pool_handle : handle for the mailbox pool memory + * @param epthru_pool : a pool for extended passthru commands + * @param epthru_pool_handle : handle to the pool above + * @param sg_pool : pool of scatter-gather lists for this driver + * @param sg_pool_handle : handle to the pool above + * @param ccb_list : list of our command control blocks + * @param uccb_list : list of cmd control blocks for mgmt module + * @param umbox64 : array of mailbox for user commands (cmm) + * @param pdrv_state : array for state of each physical drive. + * @param last_disp : flag used to show device scanning + * @param hw_error : set if FW not responding + * @param fast_load : If set, skip physical device scanning + * @channel_class : channel class, RAID or SCSI + * @sysfs_sem : semaphore to serialize access to sysfs res. + * @sysfs_uioc : management packet to issue FW calls from sysfs + * @sysfs_mbox64 : mailbox packet to issue FW calls from sysfs + * @sysfs_buffer : data buffer for FW commands issued from sysfs + * @sysfs_buffer_dma : DMA buffer for FW commands issued from sysfs + * @sysfs_wait_q : wait queue for sysfs operations + * @random_del_supported : set if the random deletion is supported + * @curr_ldmap : current LDID map + * + * Initialization structure for mailbox controllers: memory based and IO based + * All the fields in this structure are LLD specific and may be discovered at + * init() or start() time. + * + * NOTE: The fields of this structures are placed to minimize cache misses + */ +#define MAX_LD_EXTENDED64 64 +typedef struct { + mbox64_t *una_mbox64; + dma_addr_t una_mbox64_dma; + mbox_t *mbox; + mbox64_t *mbox64; + dma_addr_t mbox_dma; + spinlock_t mailbox_lock; + unsigned long baseport; + void __iomem * baseaddr; + struct mraid_pci_blk mbox_pool[MBOX_MAX_SCSI_CMDS]; + struct dma_pool *mbox_pool_handle; + struct mraid_pci_blk epthru_pool[MBOX_MAX_SCSI_CMDS]; + struct dma_pool *epthru_pool_handle; + struct mraid_pci_blk sg_pool[MBOX_MAX_SCSI_CMDS]; + struct dma_pool *sg_pool_handle; + mbox_ccb_t ccb_list[MBOX_MAX_SCSI_CMDS]; + mbox_ccb_t uccb_list[MBOX_MAX_USER_CMDS]; + mbox64_t umbox64[MBOX_MAX_USER_CMDS]; + + uint8_t pdrv_state[MBOX_MAX_PHYSICAL_DRIVES]; + uint32_t last_disp; + int hw_error; + int fast_load; + uint8_t channel_class; + struct semaphore sysfs_sem; + uioc_t *sysfs_uioc; + mbox64_t *sysfs_mbox64; + caddr_t sysfs_buffer; + dma_addr_t sysfs_buffer_dma; + wait_queue_head_t sysfs_wait_q; + int random_del_supported; + uint16_t curr_ldmap[MAX_LD_EXTENDED64]; +} mraid_device_t; + +// route to raid device from adapter +#define ADAP2RAIDDEV(adp) ((mraid_device_t *)((adp)->raid_device)) + +#define MAILBOX_LOCK(rdev) (&(rdev)->mailbox_lock) + +// Find out if this channel is a RAID or SCSI +#define IS_RAID_CH(rdev, ch) (((rdev)->channel_class >> (ch)) & 0x01) + + +#define RDINDOOR(rdev) readl((rdev)->baseaddr + 0x20) +#define RDOUTDOOR(rdev) readl((rdev)->baseaddr + 0x2C) +#define WRINDOOR(rdev, value) writel(value, (rdev)->baseaddr + 0x20) +#define WROUTDOOR(rdev, value) writel(value, (rdev)->baseaddr + 0x2C) + +#endif // _MEGARAID_H_ + +// vim: set ts=8 sw=8 tw=78: diff --git a/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_mm.c b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_mm.c new file mode 100644 index 0000000..fabbf76 --- /dev/null +++ b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_mm.c @@ -0,0 +1,1320 @@ +/* + * + * Linux MegaRAID device driver + * + * Copyright (c) 2003-2004 LSI Logic Corporation. + * + * 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. + * + * FILE : megaraid_mm.c + * Version : v2.20.2.6 (Mar 7 2005) + * + * Common management module + */ + +#include "megaraid_mm.h" + + +// Entry points for char node driver +static int mraid_mm_open(struct inode *, struct file *); +static int mraid_mm_ioctl(struct inode *, struct file *, uint, unsigned long); + + +// routines to convert to and from the old the format +static int mimd_to_kioc(mimd_t __user *, mraid_mmadp_t *, uioc_t *); +static int kioc_to_mimd(uioc_t *, mimd_t __user *); + + +// Helper functions +static int handle_drvrcmd(void __user *, uint8_t, int *); +static int lld_ioctl(mraid_mmadp_t *, uioc_t *); +static void ioctl_done(uioc_t *); +static void lld_timedout(unsigned long); +static void hinfo_to_cinfo(mraid_hba_info_t *, mcontroller_t *); +static mraid_mmadp_t *mraid_mm_get_adapter(mimd_t __user *, int *); +static uioc_t *mraid_mm_alloc_kioc(mraid_mmadp_t *); +static void mraid_mm_dealloc_kioc(mraid_mmadp_t *, uioc_t *); +static int mraid_mm_attach_buf(mraid_mmadp_t *, uioc_t *, int); +static int mraid_mm_setup_dma_pools(mraid_mmadp_t *); +static void mraid_mm_free_adp_resources(mraid_mmadp_t *); +static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *); + +#ifdef CONFIG_COMPAT +static int mraid_mm_compat_ioctl(unsigned int, unsigned int, unsigned long, + struct file *); +#endif + +MODULE_AUTHOR("LSI Logic Corporation"); +MODULE_DESCRIPTION("LSI Logic Management Module"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(LSI_COMMON_MOD_VERSION); + +static int dbglevel = CL_ANN; +module_param_named(dlevel, dbglevel, int, 0); +MODULE_PARM_DESC(dlevel, "Debug level (default=0)"); + +EXPORT_SYMBOL(mraid_mm_register_adp); +EXPORT_SYMBOL(mraid_mm_unregister_adp); +EXPORT_SYMBOL(mraid_mm_adapter_app_handle); +void (*mraid_mm_poll_func)(struct scsi_device *device) = NULL; +EXPORT_SYMBOL(mraid_mm_poll_func); +struct scsi_device *mraid_mm_diskdump_poll_device = NULL; +EXPORT_SYMBOL(mraid_mm_diskdump_poll_device); + +static int majorno; +static uint32_t drvr_ver = 0x02200206; + +static int adapters_count_g; +static struct list_head adapters_list_g; + +static wait_queue_head_t wait_q; + +static struct file_operations lsi_fops = { + .open = mraid_mm_open, + .ioctl = mraid_mm_ioctl, + .owner = THIS_MODULE, +}; + +int mraid_mm_woken; +EXPORT_SYMBOL(mraid_mm_woken); + +static void _mraid_mm_diskdump_schedule(void); +static void _mraid_mm_diskdump_wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive); +void mraid_mm_diskdump_schedule(void); +void mraid_mm_diskdump_wake_up(wait_queue_head_t *q); + + +/** + * mraid_mm_open - open routine for char node interface + * @inod : unused + * @filep : unused + * + * allow ioctl operations by apps only if they superuser privilege + */ +static int +mraid_mm_open(struct inode *inode, struct file *filep) +{ + /* + * Only allow superuser to access private ioctl interface + */ + if (!capable(CAP_SYS_ADMIN)) return (-EACCES); + + return 0; +} + +/** + * mraid_mm_ioctl - module entry-point for ioctls + * @inode : inode (ignored) + * @filep : file operations pointer (ignored) + * @cmd : ioctl command + * @arg : user ioctl packet + */ +static int +mraid_mm_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, + unsigned long arg) +{ + uioc_t *kioc; + char signature[EXT_IOCTL_SIGN_SZ] = {0}; + int rval; + mraid_mmadp_t *adp; + uint8_t old_ioctl; + int drvrcmd_rval; + void __user *argp = (void __user *)arg; + + /* + * Make sure only USCSICMD are issued through this interface. + * MIMD application would still fire different command. + */ + + if ((_IOC_TYPE(cmd) != MEGAIOC_MAGIC) && (cmd != USCSICMD)) { + return (-EINVAL); + } + + /* + * Look for signature to see if this is the new or old ioctl format. + */ + if (copy_from_user(signature, argp, EXT_IOCTL_SIGN_SZ)) { + con_log(CL_ANN, (KERN_WARNING + "megaraid cmm: copy from usr addr failed\n")); + return (-EFAULT); + } + + if (memcmp(signature, EXT_IOCTL_SIGN, EXT_IOCTL_SIGN_SZ) == 0) + old_ioctl = 0; + else + old_ioctl = 1; + + /* + * At present, we don't support the new ioctl packet + */ + if (!old_ioctl ) + return (-EINVAL); + + /* + * If it is a driver ioctl (as opposed to fw ioctls), then we can + * handle the command locally. rval > 0 means it is not a drvr cmd + */ + rval = handle_drvrcmd(argp, old_ioctl, &drvrcmd_rval); + + if (rval < 0) + return rval; + else if (rval == 0) + return drvrcmd_rval; + + rval = 0; + if ((adp = mraid_mm_get_adapter(argp, &rval)) == NULL) { + return rval; + } + + /* + * Check if adapter can accept ioctl. We may have marked it offline + * if any previous kioc had timedout on this controller. + */ + if (!adp->quiescent) { + con_log(CL_ANN, (KERN_WARNING + "megaraid cmm: controller cannot accept cmds due to " + "earlier errors\n" )); + return -EFAULT; + } + + /* + * The following call will block till a kioc is available + */ + kioc = mraid_mm_alloc_kioc(adp); + + /* + * User sent the old mimd_t ioctl packet. Convert it to uioc_t. + */ + if ((rval = mimd_to_kioc(argp, adp, kioc))) { + mraid_mm_dealloc_kioc(adp, kioc); + return rval; + } + + kioc->done = ioctl_done; + + /* + * Issue the IOCTL to the low level driver. After the IOCTL completes + * release the kioc if and only if it was _not_ timedout. If it was + * timedout, that means that resources are still with low level driver. + */ + if ((rval = lld_ioctl(adp, kioc))) { + + if (!kioc->timedout) + mraid_mm_dealloc_kioc(adp, kioc); + + return rval; + } + + /* + * Convert the kioc back to user space + */ + rval = kioc_to_mimd(kioc, argp); + + /* + * Return the kioc to free pool + */ + mraid_mm_dealloc_kioc(adp, kioc); + + return rval; +} + + +/** + * mraid_mm_get_adapter - Returns corresponding adapters for the mimd packet + * @umimd : User space mimd_t ioctl packet + * @adapter : pointer to the adapter (OUT) + */ +static mraid_mmadp_t * +mraid_mm_get_adapter(mimd_t __user *umimd, int *rval) +{ + mraid_mmadp_t *adapter; + mimd_t mimd; + uint32_t adapno; + int iterator; + + + if (copy_from_user(&mimd, umimd, sizeof(mimd_t))) { + *rval = -EFAULT; + return NULL; + } + + adapno = GETADAP(mimd.ui.fcs.adapno); + + if (adapno >= adapters_count_g) { + *rval = -ENODEV; + return NULL; + } + + adapter = NULL; + iterator = 0; + + list_for_each_entry(adapter, &adapters_list_g, list) { + if (iterator++ == adapno) break; + } + + if (!adapter) { + *rval = -ENODEV; + return NULL; + } + + return adapter; +} + +/* + * handle_drvrcmd - This routine checks if the opcode is a driver + * cmd and if it is, handles it. + * @arg : packet sent by the user app + * @old_ioctl : mimd if 1; uioc otherwise + */ +static int +handle_drvrcmd(void __user *arg, uint8_t old_ioctl, int *rval) +{ + mimd_t __user *umimd; + mimd_t kmimd; + uint8_t opcode; + uint8_t subopcode; + + if (old_ioctl) + goto old_packet; + else + goto new_packet; + +new_packet: + return (-ENOTSUPP); + +old_packet: + *rval = 0; + umimd = arg; + + if (copy_from_user(&kmimd, umimd, sizeof(mimd_t))) + return (-EFAULT); + + opcode = kmimd.ui.fcs.opcode; + subopcode = kmimd.ui.fcs.subopcode; + + /* + * If the opcode is 0x82 and the subopcode is either GET_DRVRVER or + * GET_NUMADP, then we can handle. Otherwise we should return 1 to + * indicate that we cannot handle this. + */ + if (opcode != 0x82) + return 1; + + switch (subopcode) { + + case MEGAIOC_QDRVRVER: + + if (copy_to_user(kmimd.data, &drvr_ver, sizeof(uint32_t))) + return (-EFAULT); + + return 0; + + case MEGAIOC_QNADAP: + + *rval = adapters_count_g; + + if (copy_to_user(kmimd.data, &adapters_count_g, + sizeof(uint32_t))) + return (-EFAULT); + + return 0; + + default: + /* cannot handle */ + return 1; + } + + return 0; +} + + +/** + * mimd_to_kioc - Converter from old to new ioctl format + * + * @umimd : user space old MIMD IOCTL + * @kioc : kernel space new format IOCTL + * + * Routine to convert MIMD interface IOCTL to new interface IOCTL packet. The + * new packet is in kernel space so that driver can perform operations on it + * freely. + */ + +static int +mimd_to_kioc(mimd_t __user *umimd, mraid_mmadp_t *adp, uioc_t *kioc) +{ + mbox64_t *mbox64; + mbox_t *mbox; + mraid_passthru_t *pthru32; + uint32_t adapno; + uint8_t opcode; + uint8_t subopcode; + mimd_t mimd; + + if (copy_from_user(&mimd, umimd, sizeof(mimd_t))) + return (-EFAULT); + + /* + * Applications are not allowed to send extd pthru + */ + if ((mimd.mbox[0] == MBOXCMD_PASSTHRU64) || + (mimd.mbox[0] == MBOXCMD_EXTPTHRU)) + return (-EINVAL); + + opcode = mimd.ui.fcs.opcode; + subopcode = mimd.ui.fcs.subopcode; + adapno = GETADAP(mimd.ui.fcs.adapno); + + if (adapno >= adapters_count_g) + return (-ENODEV); + + kioc->adapno = adapno; + kioc->mb_type = MBOX_LEGACY; + kioc->app_type = APPTYPE_MIMD; + + switch (opcode) { + + case 0x82: + + if (subopcode == MEGAIOC_QADAPINFO) { + + kioc->opcode = GET_ADAP_INFO; + kioc->data_dir = UIOC_RD; + kioc->xferlen = sizeof(mraid_hba_info_t); + + if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen)) + return (-ENOMEM); + } + else { + con_log(CL_ANN, (KERN_WARNING + "megaraid cmm: Invalid subop\n")); + return (-EINVAL); + } + + break; + + case 0x81: + + kioc->opcode = MBOX_CMD; + kioc->xferlen = mimd.ui.fcs.length; + kioc->user_data_len = kioc->xferlen; + kioc->user_data = mimd.ui.fcs.buffer; + + if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen)) + return (-ENOMEM); + + if (mimd.outlen) kioc->data_dir = UIOC_RD; + if (mimd.inlen) kioc->data_dir |= UIOC_WR; + + break; + + case 0x80: + + kioc->opcode = MBOX_CMD; + kioc->xferlen = (mimd.outlen > mimd.inlen) ? + mimd.outlen : mimd.inlen; + kioc->user_data_len = kioc->xferlen; + kioc->user_data = mimd.data; + + if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen)) + return (-ENOMEM); + + if (mimd.outlen) kioc->data_dir = UIOC_RD; + if (mimd.inlen) kioc->data_dir |= UIOC_WR; + + break; + + default: + return (-EINVAL); + } + + /* + * If driver command, nothing else to do + */ + if (opcode == 0x82) + return 0; + + /* + * This is a mailbox cmd; copy the mailbox from mimd + */ + mbox64 = (mbox64_t *)((unsigned long)kioc->cmdbuf); + mbox = &mbox64->mbox32; + memcpy(mbox, mimd.mbox, 14); + + if (mbox->cmd != MBOXCMD_PASSTHRU) { // regular DCMD + + mbox->xferaddr = (uint32_t)kioc->buf_paddr; + + if (kioc->data_dir & UIOC_WR) { + if (copy_from_user(kioc->buf_vaddr, kioc->user_data, + kioc->xferlen)) { + return (-EFAULT); + } + } + + return 0; + } + + /* + * This is a regular 32-bit pthru cmd; mbox points to pthru struct. + * Just like in above case, the beginning for memblk is treated as + * a mailbox. The passthru will begin at next 1K boundary. And the + * data will start 1K after that. + */ + pthru32 = kioc->pthru32; + kioc->user_pthru = &umimd->pthru; + mbox->xferaddr = (uint32_t)kioc->pthru32_h; + + if (copy_from_user(pthru32, kioc->user_pthru, + sizeof(mraid_passthru_t))) { + return (-EFAULT); + } + + pthru32->dataxferaddr = kioc->buf_paddr; + if (kioc->data_dir & UIOC_WR) { + if (copy_from_user(kioc->buf_vaddr, kioc->user_data, + pthru32->dataxferlen)) { + return (-EFAULT); + } + } + + return 0; +} + +/** + * mraid_mm_attch_buf - Attach a free dma buffer for required size + * + * @adp : Adapter softstate + * @kioc : kioc that the buffer needs to be attached to + * @xferlen : required length for buffer + * + * First we search for a pool with smallest buffer that is >= @xferlen. If + * that pool has no free buffer, we will try for the next bigger size. If none + * is available, we will try to allocate the smallest buffer that is >= + * @xferlen and attach it the pool. + */ +static int +mraid_mm_attach_buf(mraid_mmadp_t *adp, uioc_t *kioc, int xferlen) +{ + mm_dmapool_t *pool; + int right_pool = -1; + unsigned long flags; + int i; + + kioc->pool_index = -1; + kioc->buf_vaddr = NULL; + kioc->buf_paddr = 0; + kioc->free_buf = 0; + + /* + * We need xferlen amount of memory. See if we can get it from our + * dma pools. If we don't get exact size, we will try bigger buffer + */ + + for (i = 0; i < MAX_DMA_POOLS; i++) { + + pool = &adp->dma_pool_list[i]; + + if (xferlen > pool->buf_size) + continue; + + if (right_pool == -1) + right_pool = i; + + spin_lock_irqsave(&pool->lock, flags); + + if (!pool->in_use) { + + pool->in_use = 1; + kioc->pool_index = i; + kioc->buf_vaddr = pool->vaddr; + kioc->buf_paddr = pool->paddr; + + spin_unlock_irqrestore(&pool->lock, flags); + return 0; + } + else { + spin_unlock_irqrestore(&pool->lock, flags); + continue; + } + } + + /* + * If xferlen doesn't match any of our pools, return error + */ + if (right_pool == -1) + return -EINVAL; + + /* + * We did not get any buffer from the preallocated pool. Let us try + * to allocate one new buffer. NOTE: This is a blocking call. + */ + pool = &adp->dma_pool_list[right_pool]; + + spin_lock_irqsave(&pool->lock, flags); + + kioc->pool_index = right_pool; + kioc->free_buf = 1; + kioc->buf_vaddr = pci_pool_alloc(pool->handle, GFP_KERNEL, + &kioc->buf_paddr); + spin_unlock_irqrestore(&pool->lock, flags); + + if (!kioc->buf_vaddr) + return -ENOMEM; + + return 0; +} + +/** + * mraid_mm_alloc_kioc - Returns a uioc_t from free list + * @adp : Adapter softstate for this module + * + * The kioc_semaphore is initialized with number of kioc nodes in the + * free kioc pool. If the kioc pool is empty, this function blocks till + * a kioc becomes free. + */ +static uioc_t * +mraid_mm_alloc_kioc(mraid_mmadp_t *adp) +{ + uioc_t *kioc; + struct list_head* head; + unsigned long flags; + + down(&adp->kioc_semaphore); + + spin_lock_irqsave(&adp->kioc_pool_lock, flags); + + head = &adp->kioc_pool; + + if (list_empty(head)) { + up(&adp->kioc_semaphore); + spin_unlock_irqrestore(&adp->kioc_pool_lock, flags); + + con_log(CL_ANN, ("megaraid cmm: kioc list empty!\n")); + return NULL; + } + + kioc = list_entry(head->next, uioc_t, list); + list_del_init(&kioc->list); + + spin_unlock_irqrestore(&adp->kioc_pool_lock, flags); + + memset((caddr_t)(unsigned long)kioc->cmdbuf, 0, sizeof(mbox64_t)); + memset((caddr_t) kioc->pthru32, 0, sizeof(mraid_passthru_t)); + + kioc->buf_vaddr = NULL; + kioc->buf_paddr = 0; + kioc->pool_index =-1; + kioc->free_buf = 0; + kioc->user_data = NULL; + kioc->user_data_len = 0; + kioc->user_pthru = NULL; + kioc->timedout = 0; + + return kioc; +} + +/** + * mraid_mm_dealloc_kioc - Return kioc to free pool + * + * @adp : Adapter softstate + * @kioc : uioc_t node to be returned to free pool + */ +static void +mraid_mm_dealloc_kioc(mraid_mmadp_t *adp, uioc_t *kioc) +{ + mm_dmapool_t *pool; + unsigned long flags; + + if (kioc->pool_index != -1) { + pool = &adp->dma_pool_list[kioc->pool_index]; + + /* This routine may be called in non-isr context also */ + spin_lock_irqsave(&pool->lock, flags); + + /* + * While attaching the dma buffer, if we didn't get the + * required buffer from the pool, we would have allocated + * it at the run time and set the free_buf flag. We must + * free that buffer. Otherwise, just mark that the buffer is + * not in use + */ + if (kioc->free_buf == 1) + pci_pool_free(pool->handle, kioc->buf_vaddr, + kioc->buf_paddr); + else + pool->in_use = 0; + + spin_unlock_irqrestore(&pool->lock, flags); + } + + /* Return the kioc to the free pool */ + spin_lock_irqsave(&adp->kioc_pool_lock, flags); + list_add(&kioc->list, &adp->kioc_pool); + spin_unlock_irqrestore(&adp->kioc_pool_lock, flags); + + /* increment the free kioc count */ + up(&adp->kioc_semaphore); + + return; +} + +/** + * lld_ioctl - Routine to issue ioctl to low level drvr + * + * @adp : The adapter handle + * @kioc : The ioctl packet with kernel addresses + */ +static int +lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc) +{ + int rval; + struct timer_list timer; + struct timer_list *tp = NULL; + + kioc->status = -ENODATA; + rval = adp->issue_uioc(adp->drvr_data, kioc, IOCTL_ISSUE); + + if (rval) return rval; + + /* + * Start the timer + */ + if (adp->timeout > 0) { + tp = &timer; + init_timer(tp); + + tp->function = lld_timedout; + tp->data = (unsigned long)kioc; + tp->expires = jiffies + adp->timeout * HZ; + + add_timer(tp); + } + + /* + * Wait till the low level driver completes the ioctl. After this + * call, the ioctl either completed successfully or timedout. + */ + wait_event(wait_q, (kioc->status != -ENODATA)); + if (tp) { + del_timer_sync(tp); + } + + /* + * If the command had timedout, we mark the controller offline + * before returning + */ + if (kioc->timedout) { + adp->quiescent = 0; + } + + return kioc->status; +} + + +/** + * ioctl_done - callback from the low level driver + * + * @kioc : completed ioctl packet + */ +static void +ioctl_done(uioc_t *kioc) +{ + uint32_t adapno; + int iterator; + mraid_mmadp_t* adapter; + + /* + * When the kioc returns from driver, make sure it still doesn't + * have ENODATA in status. Otherwise, driver will hang on wait_event + * forever + */ + if (kioc->status == -ENODATA) { + con_log(CL_ANN, (KERN_WARNING + "megaraid cmm: lld didn't change status!\n")); + + kioc->status = -EINVAL; + } + + /* + * Check if this kioc was timedout before. If so, nobody is waiting + * on this kioc. We don't have to wake up anybody. Instead, we just + * have to free the kioc + */ + if (kioc->timedout) { + iterator = 0; + adapter = NULL; + adapno = kioc->adapno; + + con_log(CL_ANN, ( KERN_WARNING "megaraid cmm: completed " + "ioctl that was timedout before\n")); + + list_for_each_entry(adapter, &adapters_list_g, list) { + if (iterator++ == adapno) break; + } + + kioc->timedout = 0; + + if (adapter) { + mraid_mm_dealloc_kioc( adapter, kioc ); + } + } + else { + wake_up(&wait_q); + } +} + + +/* + * lld_timedout : callback from the expired timer + * + * @ptr : ioctl packet that timed out + */ +static void +lld_timedout(unsigned long ptr) +{ + uioc_t *kioc = (uioc_t *)ptr; + + kioc->status = -ETIME; + kioc->timedout = 1; + + con_log(CL_ANN, (KERN_WARNING "megaraid cmm: ioctl timed out\n")); + + wake_up(&wait_q); +} + + +/** + * kioc_to_mimd : Converter from new back to old format + * + * @kioc : Kernel space IOCTL packet (successfully issued) + * @mimd : User space MIMD packet + */ +static int +kioc_to_mimd(uioc_t *kioc, mimd_t __user *mimd) +{ + mimd_t kmimd; + uint8_t opcode; + uint8_t subopcode; + + mbox64_t *mbox64; + mraid_passthru_t __user *upthru32; + mraid_passthru_t *kpthru32; + mcontroller_t cinfo; + mraid_hba_info_t *hinfo; + + + if (copy_from_user(&kmimd, mimd, sizeof(mimd_t))) + return (-EFAULT); + + opcode = kmimd.ui.fcs.opcode; + subopcode = kmimd.ui.fcs.subopcode; + + if (opcode == 0x82) { + switch (subopcode) { + + case MEGAIOC_QADAPINFO: + + hinfo = (mraid_hba_info_t *)(unsigned long) + kioc->buf_vaddr; + + hinfo_to_cinfo(hinfo, &cinfo); + + if (copy_to_user(kmimd.data, &cinfo, sizeof(cinfo))) + return (-EFAULT); + + return 0; + + default: + return (-EINVAL); + } + + return 0; + } + + mbox64 = (mbox64_t *)(unsigned long)kioc->cmdbuf; + + if (kioc->user_pthru) { + + upthru32 = kioc->user_pthru; + kpthru32 = kioc->pthru32; + + if (copy_to_user(&upthru32->scsistatus, + &kpthru32->scsistatus, + sizeof(uint8_t))) { + return (-EFAULT); + } + } + + if (kioc->user_data) { + if (copy_to_user(kioc->user_data, kioc->buf_vaddr, + kioc->user_data_len)) { + return (-EFAULT); + } + } + + if (copy_to_user(&mimd->mbox[17], + &mbox64->mbox32.status, sizeof(uint8_t))) { + return (-EFAULT); + } + + return 0; +} + + +/** + * hinfo_to_cinfo - Convert new format hba info into old format + * + * @hinfo : New format, more comprehensive adapter info + * @cinfo : Old format adapter info to support mimd_t apps + */ +static void +hinfo_to_cinfo(mraid_hba_info_t *hinfo, mcontroller_t *cinfo) +{ + if (!hinfo || !cinfo) + return; + + cinfo->base = hinfo->baseport; + cinfo->irq = hinfo->irq; + cinfo->numldrv = hinfo->num_ldrv; + cinfo->pcibus = hinfo->pci_bus; + cinfo->pcidev = hinfo->pci_slot; + cinfo->pcifun = PCI_FUNC(hinfo->pci_dev_fn); + cinfo->pciid = hinfo->pci_device_id; + cinfo->pcivendor = hinfo->pci_vendor_id; + cinfo->pcislot = hinfo->pci_slot; + cinfo->uid = hinfo->unique_id; +} + + +/* + * mraid_mm_register_adp - Registration routine for low level drvrs + * + * @adp : Adapter objejct + */ +int +mraid_mm_register_adp(mraid_mmadp_t *lld_adp) +{ + mraid_mmadp_t *adapter; + mbox64_t *mbox_list; + uioc_t *kioc; + uint32_t rval; + int i; + + + if (lld_adp->drvr_type != DRVRTYPE_MBOX) + return (-EINVAL); + + adapter = kmalloc(sizeof(mraid_mmadp_t), GFP_KERNEL); + + if (!adapter) { + rval = -ENOMEM; + goto memalloc_error; + } + + memset(adapter, 0, sizeof(mraid_mmadp_t)); + + adapter->unique_id = lld_adp->unique_id; + adapter->drvr_type = lld_adp->drvr_type; + adapter->drvr_data = lld_adp->drvr_data; + adapter->pdev = lld_adp->pdev; + adapter->issue_uioc = lld_adp->issue_uioc; + adapter->timeout = lld_adp->timeout; + adapter->max_kioc = lld_adp->max_kioc; + adapter->quiescent = 1; + + /* + * Allocate single blocks of memory for all required kiocs, + * mailboxes and passthru structures. + */ + adapter->kioc_list = kmalloc(sizeof(uioc_t) * lld_adp->max_kioc, + GFP_KERNEL); + adapter->mbox_list = kmalloc(sizeof(mbox64_t) * lld_adp->max_kioc, + GFP_KERNEL); + adapter->pthru_dma_pool = pci_pool_create("megaraid mm pthru pool", + adapter->pdev, + sizeof(mraid_passthru_t), + 16, 0); + + if (!adapter->kioc_list || !adapter->mbox_list || + !adapter->pthru_dma_pool) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid cmm: out of memory, %s %d\n", __FUNCTION__, + __LINE__)); + + rval = (-ENOMEM); + + goto memalloc_error; + } + + /* + * Slice kioc_list and make a kioc_pool with the individiual kiocs + */ + INIT_LIST_HEAD(&adapter->kioc_pool); + spin_lock_init(&adapter->kioc_pool_lock); + sema_init(&adapter->kioc_semaphore, lld_adp->max_kioc); + + mbox_list = (mbox64_t *)adapter->mbox_list; + + for (i = 0; i < lld_adp->max_kioc; i++) { + + kioc = adapter->kioc_list + i; + kioc->cmdbuf = (uint64_t)(unsigned long)(mbox_list + i); + kioc->pthru32 = pci_pool_alloc(adapter->pthru_dma_pool, + GFP_KERNEL, &kioc->pthru32_h); + + if (!kioc->pthru32) { + + con_log(CL_ANN, (KERN_WARNING + "megaraid cmm: out of memory, %s %d\n", + __FUNCTION__, __LINE__)); + + rval = (-ENOMEM); + + goto pthru_dma_pool_error; + } + + list_add_tail(&kioc->list, &adapter->kioc_pool); + } + + // Setup the dma pools for data buffers + if ((rval = mraid_mm_setup_dma_pools(adapter)) != 0) { + goto dma_pool_error; + } + + list_add_tail(&adapter->list, &adapters_list_g); + + adapters_count_g++; + + return 0; + +dma_pool_error: + /* Do nothing */ + +pthru_dma_pool_error: + + for (i = 0; i < lld_adp->max_kioc; i++) { + kioc = adapter->kioc_list + i; + if (kioc->pthru32) { + pci_pool_free(adapter->pthru_dma_pool, kioc->pthru32, + kioc->pthru32_h); + } + } + +memalloc_error: + + if (adapter->kioc_list) + kfree(adapter->kioc_list); + + if (adapter->mbox_list) + kfree(adapter->mbox_list); + + if (adapter->pthru_dma_pool) + pci_pool_destroy(adapter->pthru_dma_pool); + + if (adapter) + kfree(adapter); + + return rval; +} + + +/** + * mraid_mm_adapter_app_handle - return the application handle for this adapter + * + * For the given driver data, locate the adadpter in our global list and + * return the corresponding handle, which is also used by applications to + * uniquely identify an adapter. + * + * @param unique_id : adapter unique identifier + * + * @return adapter handle if found in the list + * @return 0 if adapter could not be located, should never happen though + */ +uint32_t +mraid_mm_adapter_app_handle(uint32_t unique_id) +{ + mraid_mmadp_t *adapter; + mraid_mmadp_t *tmp; + int index = 0; + + list_for_each_entry_safe(adapter, tmp, &adapters_list_g, list) { + + if (adapter->unique_id == unique_id) { + + return MKADAP(index); + } + + index++; + } + + return 0; +} + + +/** + * mraid_mm_setup_dma_pools - Set up dma buffer pools per adapter + * + * @adp : Adapter softstate + * + * We maintain a pool of dma buffers per each adapter. Each pool has one + * buffer. E.g, we may have 5 dma pools - one each for 4k, 8k ... 64k buffers. + * We have just one 4k buffer in 4k pool, one 8k buffer in 8k pool etc. We + * dont' want to waste too much memory by allocating more buffers per each + * pool. + */ +static int +mraid_mm_setup_dma_pools(mraid_mmadp_t *adp) +{ + mm_dmapool_t *pool; + int bufsize; + int i; + + /* + * Create MAX_DMA_POOLS number of pools + */ + bufsize = MRAID_MM_INIT_BUFF_SIZE; + + for (i = 0; i < MAX_DMA_POOLS; i++){ + + pool = &adp->dma_pool_list[i]; + + pool->buf_size = bufsize; + spin_lock_init(&pool->lock); + + pool->handle = pci_pool_create("megaraid mm data buffer", + adp->pdev, bufsize, 16, 0); + + if (!pool->handle) { + goto dma_pool_setup_error; + } + + pool->vaddr = pci_pool_alloc(pool->handle, GFP_KERNEL, + &pool->paddr); + + if (!pool->vaddr) + goto dma_pool_setup_error; + + bufsize = bufsize * 2; + } + + return 0; + +dma_pool_setup_error: + + mraid_mm_teardown_dma_pools(adp); + return (-ENOMEM); +} + + +/* + * mraid_mm_unregister_adp - Unregister routine for low level drivers + * Assume no outstanding ioctls to llds. + * + * @unique_id : UID of the adpater + */ +int +mraid_mm_unregister_adp(uint32_t unique_id) +{ + mraid_mmadp_t *adapter; + mraid_mmadp_t *tmp; + + list_for_each_entry_safe(adapter, tmp, &adapters_list_g, list) { + + + if (adapter->unique_id == unique_id) { + + adapters_count_g--; + + list_del_init(&adapter->list); + + mraid_mm_free_adp_resources(adapter); + + kfree(adapter); + + con_log(CL_ANN, ( + "megaraid cmm: Unregistered one adapter:%#x\n", + unique_id)); + + return 0; + } + } + + return (-ENODEV); +} + +/** + * mraid_mm_free_adp_resources - Free adapter softstate + * + * @adp : Adapter softstate + */ +static void +mraid_mm_free_adp_resources(mraid_mmadp_t *adp) +{ + uioc_t *kioc; + int i; + + mraid_mm_teardown_dma_pools(adp); + + for (i = 0; i < adp->max_kioc; i++) { + + kioc = adp->kioc_list + i; + + pci_pool_free(adp->pthru_dma_pool, kioc->pthru32, + kioc->pthru32_h); + } + + kfree(adp->kioc_list); + + kfree(adp->mbox_list); + + pci_pool_destroy(adp->pthru_dma_pool); + + + return; +} + + +/** + * mraid_mm_teardown_dma_pools - Free all per adapter dma buffers + * + * @adp : Adapter softstate + */ +static void +mraid_mm_teardown_dma_pools(mraid_mmadp_t *adp) +{ + int i; + mm_dmapool_t *pool; + + for (i = 0; i < MAX_DMA_POOLS; i++) { + + pool = &adp->dma_pool_list[i]; + + if (pool->handle) { + + if (pool->vaddr) + pci_pool_free(pool->handle, pool->vaddr, + pool->paddr); + + pci_pool_destroy(pool->handle); + pool->handle = NULL; + } + } + + return; +} + +/** + * mraid_mm_init : Module entry point + */ +static int __init +mraid_mm_init(void) +{ + // Announce the driver version + con_log(CL_ANN, (KERN_INFO "megaraid cmm: %s %s\n", + LSI_COMMON_MOD_VERSION, LSI_COMMON_MOD_EXT_VERSION)); + + majorno = register_chrdev(0, "megadev", &lsi_fops); + + if (majorno < 0) { + con_log(CL_ANN, ("megaraid cmm: cannot get major\n")); + return majorno; + } + + init_waitqueue_head(&wait_q); + + INIT_LIST_HEAD(&adapters_list_g); + + register_ioctl32_conversion(MEGAIOCCMD, mraid_mm_compat_ioctl); + + return 0; +} + + +/** + * mraid_mm_compat_ioctl : 32bit to 64bit ioctl conversion routine + */ +#ifdef CONFIG_COMPAT +static int +mraid_mm_compat_ioctl(unsigned int fd, unsigned int cmd, + unsigned long arg, struct file *filep) +{ + int err; + struct inode *inode = filep->f_dentry->d_inode; + + err = mraid_mm_ioctl(inode, filep, cmd, arg); + + return err; +} +#endif + +/** + * mraid_mm_exit : Module exit point + */ +static void __exit +mraid_mm_exit(void) +{ + con_log(CL_DLEVEL1 , ("exiting common mod\n")); + + unregister_chrdev(majorno, "megadev"); + unregister_ioctl32_conversion(MEGAIOCCMD); +} + +void mraid_mm_diskdump_schedule(void) +{ + if (crashdump_mode()) + _mraid_mm_diskdump_schedule(); + else + schedule(); + return; +} +EXPORT_SYMBOL(mraid_mm_diskdump_schedule); + +void mraid_mm_diskdump_wake_up(wait_queue_head_t *q) +{ + if (crashdump_mode()) + _mraid_mm_diskdump_wake_up((q), TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1); + else + __wake_up((q), TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1, NULL); + return; +} +EXPORT_SYMBOL(mraid_mm_diskdump_wake_up); + +static void _mraid_mm_diskdump_schedule(void) +{ + mraid_mm_woken = 0; + + if (!mraid_mm_poll_func || !mraid_mm_diskdump_poll_device) { + return; + } + + while (!mraid_mm_woken) { + mraid_mm_poll_func(mraid_mm_diskdump_poll_device); + udelay(100); + diskdump_update(); + } +} + +static void _mraid_mm_diskdump_wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive) +{ + struct list_head *tmp; + wait_queue_t *curr; + task_t *p; + + list_for_each(tmp, &q->task_list) { + curr = list_entry(tmp, wait_queue_t, task_list); + p = curr->task; + if (p == current) { + if (p->state & mode) + mraid_mm_woken = 1; + } + } +} + +module_init(mraid_mm_init); +module_exit(mraid_mm_exit); + +/* vi: set ts=8 sw=8 tw=78: */ diff --git a/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_mm.h b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_mm.h new file mode 100644 index 0000000..f120bc2 --- /dev/null +++ b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_mm.h @@ -0,0 +1,105 @@ +/* + * + * Linux MegaRAID device driver + * + * Copyright (c) 2003-2004 LSI Logic Corporation. + * + * 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. + * + * FILE : megaraid_mm.h + */ + +#ifndef MEGARAID_MM_H +#define MEGARAID_MM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mbox_defs.h" +#include "megaraid_ioctl.h" + + +#define LSI_COMMON_MOD_VERSION "2.20.2.6rh" +#define LSI_COMMON_MOD_EXT_VERSION \ + "(Release Date: Tue Jan 16 12:35:06 PST 2007)" + + +#define LSI_DBGLVL dbglevel + +// The smallest dma pool +#define MRAID_MM_INIT_BUFF_SIZE 4096 + +/** + * mimd_t : Old style ioctl packet structure (deprecated) + * + * @inlen : + * @outlen : + * @fca : + * @opcode : + * @subopcode : + * @adapno : + * @buffer : + * @pad : + * @length : + * @mbox : + * @pthru : + * @data : + * @pad : + * + * Note : This structure is DEPRECATED. New applications must use + * : uioc_t structure instead. All new hba drivers use the new + * : format. If we get this mimd packet, we will convert it into + * : new uioc_t format and send it to the hba drivers. + */ + +typedef struct mimd { + + uint32_t inlen; + uint32_t outlen; + + union { + uint8_t fca[16]; + struct { + uint8_t opcode; + uint8_t subopcode; + uint16_t adapno; +#if BITS_PER_LONG == 32 + uint8_t __user *buffer; + uint8_t pad[4]; +#endif +#if BITS_PER_LONG == 64 + uint8_t __user *buffer; +#endif + uint32_t length; + } __attribute__ ((packed)) fcs; + } __attribute__ ((packed)) ui; + + uint8_t mbox[18]; /* 16 bytes + 2 status bytes */ + mraid_passthru_t pthru; + +#if BITS_PER_LONG == 32 + char __user *data; /* buffer <= 4096 for 0x80 commands */ + char pad[4]; +#endif +#if BITS_PER_LONG == 64 + char __user *data; +#endif + +} __attribute__ ((packed))mimd_t; + +#endif // MEGARAID_MM_H + +// vi: set ts=8 sw=8 tw=78: diff --git a/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_sas.c b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_sas.c new file mode 100644 index 0000000..fdea91c --- /dev/null +++ b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_sas.c @@ -0,0 +1,3159 @@ +/* + * + * Linux MegaRAID driver for SAS based RAID controllers + * + * Copyright (c) 2003-2005 LSI Logic Corporation. + * + * 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. + * + * FILE : megaraid_sas.c + * Version : v00.00.03.05 + * + * Authors: + * Sreenivas Bagalkote + * Sumant Patro + * + * List of supported controllers + * + * OEM Product Name VID DID SSVID SSID + * --- ------------ --- --- ---- ---- + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "megaraid_sas.h" + +MODULE_LICENSE("GPL"); +MODULE_VERSION(MEGASAS_VERSION); +MODULE_AUTHOR("sreenivas.bagalkote@lsil.com"); +MODULE_DESCRIPTION("LSI Logic MegaRAID SAS Driver"); + +/* + * diskdump helper function. We can't call msleep() or mdelay() while dumping. + */ +static void megasas_msleep(unsigned long ms) +{ + if(unlikely(crashdump_mode())) { + diskdump_mdelay(ms); + } else + msleep(ms); +} + +/* + * PCI ID table for all supported controllers + */ +static struct pci_device_id megasas_pci_table[] = { + + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064R)}, + /* xscale IOP */ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)}, + /* ppc IOP */ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)}, + /* xscale IOP, vega */ + {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, + /* xscale IOP */ + {} +}; + +MODULE_DEVICE_TABLE(pci, megasas_pci_table); + +static int megasas_mgmt_majorno; +static struct megasas_mgmt_info megasas_mgmt_info; +static struct fasync_struct *megasas_async_queue; +static DECLARE_MUTEX(megasas_async_queue_mutex); +static u32 megasas_dbg_lvl; + +static int +megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status); +static void megasas_flush_cache(struct megasas_instance *instance); +static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs); + +/** + * megasas_get_cmd - Get a command from the free pool + * @instance: Adapter soft state + * + * Returns a free command from the pool + */ +static inline struct megasas_cmd *megasas_get_cmd(struct megasas_instance + *instance) +{ + unsigned long flags; + struct megasas_cmd *cmd = NULL; + + spin_lock_irqsave(&instance->cmd_pool_lock, flags); + + if (!list_empty(&instance->cmd_pool)) { + cmd = list_entry((&instance->cmd_pool)->next, + struct megasas_cmd, list); + list_del_init(&cmd->list); + } else { + printk(KERN_ERR "megasas: Command pool empty!\n"); + } + + spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); + return cmd; +} + +/** + * megasas_return_cmd - Return a cmd to free command pool + * @instance: Adapter soft state + * @cmd: Command packet to be returned to free command pool + */ +static inline void +megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + unsigned long flags; + + spin_lock_irqsave(&instance->cmd_pool_lock, flags); + + cmd->scmd = NULL; + list_add_tail(&cmd->list, &instance->cmd_pool); + + spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); +} + +/** +* The following functions are defined for xscale +* (deviceid : 1064R, PERC5) controllers +*/ + +/** + * megasas_enable_intr_xscale - Enables interrupts + * @regs: MFI register set + */ +static inline void +megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs) +{ + writel(1, &(regs)->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_disable_intr_xscale -Disable interrupt + * @regs: MFI register set + */ +static inline void +megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs) +{ + u32 mask = 0x1f; + writel(mask, ®s->outbound_intr_mask); + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_read_fw_status_reg_xscale - returns the current FW status value + * @regs: MFI register set + */ +static u32 +megasas_read_fw_status_reg_xscale(struct megasas_register_set __iomem * regs) +{ + return readl(&(regs)->outbound_msg_0); +} + +/** + * megasas_clear_interrupt_xscale - Check & clear interrupt + * @regs: MFI register set + */ +static int +megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs) +{ + u32 status; + /* + * Check if it is our interrupt + */ + status = readl(®s->outbound_intr_status); + + if (!(status & MFI_OB_INTR_STATUS_MASK)) { + return 1; + } + + /* + * Clear the interrupt by writing back the same value + */ + writel(status, ®s->outbound_intr_status); + + return 0; +} + +/** + * megasas_fire_cmd_xscale - Sends command to the FW + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set + */ +static inline void +megasas_fire_cmd_xscale(dma_addr_t frame_phys_addr,u32 frame_count, struct megasas_register_set __iomem *regs) +{ + writel((frame_phys_addr >> 3)|(frame_count), + &(regs)->inbound_queue_port); +} + +static struct megasas_instance_template megasas_instance_template_xscale = { + + .fire_cmd = megasas_fire_cmd_xscale, + .enable_intr = megasas_enable_intr_xscale, + .disable_intr = megasas_disable_intr_xscale, + .clear_intr = megasas_clear_intr_xscale, + .read_fw_status_reg = megasas_read_fw_status_reg_xscale, +}; + +/** +* This is the end of set of functions & definitions specific +* to xscale (deviceid : 1064R, PERC5) controllers +*/ + +/** +* The following functions are defined for ppc (deviceid : 0x60) +* controllers +*/ + +/** + * megasas_enable_intr_ppc - Enables interrupts + * @regs: MFI register set + */ +static inline void +megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs) +{ + writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); + + writel(~0x80000004, &(regs)->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_disable_intr_ppc - Disable interrupt + * @regs: MFI register set + */ +static inline void +megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs) +{ + u32 mask = 0xFFFFFFFF; + writel(mask, ®s->outbound_intr_mask); + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_read_fw_status_reg_ppc - returns the current FW status value + * @regs: MFI register set + */ +static u32 +megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs) +{ + return readl(&(regs)->outbound_scratch_pad); +} + +/** + * megasas_clear_interrupt_ppc - Check & clear interrupt + * @regs: MFI register set + */ +static int +megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) +{ + u32 status; + /* + * Check if it is our interrupt + */ + status = readl(®s->outbound_intr_status); + + if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) { + return 1; + } + + /* + * Clear the interrupt by writing back the same value + */ + writel(status, ®s->outbound_doorbell_clear); + + return 0; +} +/** + * megasas_fire_cmd_ppc - Sends command to the FW + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set + */ +static inline void +megasas_fire_cmd_ppc(dma_addr_t frame_phys_addr, u32 frame_count, struct megasas_register_set __iomem *regs) +{ + writel((frame_phys_addr | (frame_count<<1))|1, + &(regs)->inbound_queue_port); +} + +static struct megasas_instance_template megasas_instance_template_ppc = { + + .fire_cmd = megasas_fire_cmd_ppc, + .enable_intr = megasas_enable_intr_ppc, + .disable_intr = megasas_disable_intr_ppc, + .clear_intr = megasas_clear_intr_ppc, + .read_fw_status_reg = megasas_read_fw_status_reg_ppc, +}; + +/** +* This is the end of set of functions & definitions +* specific to ppc (deviceid : 0x60) controllers +*/ + +/** + * megasas_issue_polled - Issues a polling command + * @instance: Adapter soft state + * @cmd: Command packet to be issued + * + * For polling, MFI requires the cmd_status to be set to 0xFF before posting. + */ +static int +megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + int i; + u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000; + + struct megasas_header *frame_hdr = &cmd->frame->hdr; + + frame_hdr->cmd_status = 0xFF; + frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; + + /* + * Issue the frame using inbound queue port + */ + instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); + + /* + * Wait for cmd_status to change + */ + for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) { + rmb(); + megasas_msleep(1); + } + + if (frame_hdr->cmd_status == 0xff) + return -ETIME; + + return 0; +} + +/** + * megasas_issue_blocked_cmd - Synchronous wrapper around regular FW cmds + * @instance: Adapter soft state + * @cmd: Command to be issued + * + * This function waits on an event for the command to be returned from ISR. + * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs + * Used to issue ioctl commands. + */ +static int +megasas_issue_blocked_cmd(struct megasas_instance *instance, + struct megasas_cmd *cmd) +{ + cmd->cmd_status = ENODATA; + + instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); + + wait_event_timeout(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA), + MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ); + + return 0; +} + +/** + * megasas_issue_blocked_abort_cmd - Aborts previously issued cmd + * @instance: Adapter soft state + * @cmd_to_abort: Previously issued cmd to be aborted + * + * MFI firmware can abort previously issued AEN comamnd (automatic event + * notification). The megasas_issue_blocked_abort_cmd() issues such abort + * cmd and waits for return status. + * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs + */ +static int +megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, + struct megasas_cmd *cmd_to_abort) +{ + struct megasas_cmd *cmd; + struct megasas_abort_frame *abort_fr; + + cmd = megasas_get_cmd(instance); + + if (!cmd) + return -1; + + abort_fr = &cmd->frame->abort; + + /* + * Prepare and issue the abort frame + */ + abort_fr->cmd = MFI_CMD_ABORT; + abort_fr->cmd_status = 0xFF; + abort_fr->flags = 0; + abort_fr->abort_context = cmd_to_abort->index; + abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr; + abort_fr->abort_mfi_phys_addr_hi = 0; + + cmd->sync_cmd = 1; + cmd->cmd_status = 0xFF; + + instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); + + /* + * Wait for this cmd to complete + */ + wait_event_timeout(instance->abort_cmd_wait_q, (cmd->cmd_status != 0xFF), + MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ); + + megasas_return_cmd(instance, cmd); + return 0; +} + +/** + * megasas_make_sgl32 - Prepares 32-bit SGL + * @instance: Adapter soft state + * @scp: SCSI command from the mid-layer + * @mfi_sgl: SGL to be filled in + * + * If successful, this function returns the number of SG elements. Otherwise, + * it returnes -1. + */ +static inline int +megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, + union megasas_sgl *mfi_sgl) +{ + int i; + int sge_count; + struct scatterlist *os_sgl; + + /* + * Return 0 if there is no data transfer + */ + if (!scp->request_buffer || !scp->request_bufflen) + return 0; + + if (!scp->use_sg) { + mfi_sgl->sge32[0].phys_addr = pci_map_single(instance->pdev, + scp-> + request_buffer, + scp-> + request_bufflen, + scp-> + sc_data_direction); + mfi_sgl->sge32[0].length = scp->request_bufflen; + + return 1; + } + + os_sgl = (struct scatterlist *)scp->request_buffer; + sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg, + scp->sc_data_direction); + + for (i = 0; i < sge_count; i++, os_sgl++) { + mfi_sgl->sge32[i].length = sg_dma_len(os_sgl); + mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl); + } + + return sge_count; +} + +/** + * megasas_make_sgl64 - Prepares 64-bit SGL + * @instance: Adapter soft state + * @scp: SCSI command from the mid-layer + * @mfi_sgl: SGL to be filled in + * + * If successful, this function returns the number of SG elements. Otherwise, + * it returnes -1. + */ +static inline int +megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, + union megasas_sgl *mfi_sgl) +{ + int i; + int sge_count; + struct scatterlist *os_sgl; + + /* + * Return 0 if there is no data transfer + */ + if (!scp->request_buffer || !scp->request_bufflen) + return 0; + + if (!scp->use_sg) { + mfi_sgl->sge64[0].phys_addr = pci_map_single(instance->pdev, + scp-> + request_buffer, + scp-> + request_bufflen, + scp-> + sc_data_direction); + + mfi_sgl->sge64[0].length = scp->request_bufflen; + + return 1; + } + + os_sgl = (struct scatterlist *)scp->request_buffer; + sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg, + scp->sc_data_direction); + + for (i = 0; i < sge_count; i++, os_sgl++) { + mfi_sgl->sge64[i].length = sg_dma_len(os_sgl); + mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl); + } + + return sge_count; +} + + /** + * megasas_get_frame_count - Computes the number of frames + * @sge_count : number of sg elements + * + * Returns the number of frames required for numnber of sge's (sge_count) + */ + +u32 megasas_get_frame_count(u8 sge_count) +{ + int num_cnt; + int sge_bytes; + u32 sge_sz; + u32 frame_count=0; + + sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : + sizeof(struct megasas_sge32); + + /* + * Main frame can contain 2 SGEs for 64-bit SGLs and + * 3 SGEs for 32-bit SGLs + */ + if (IS_DMA64) + num_cnt = sge_count - 2; + else + num_cnt = sge_count - 3; + + if(num_cnt>0){ + sge_bytes = sge_sz * num_cnt; + + frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) + + ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) ; + } + /* Main frame */ + frame_count +=1; + + if (frame_count > 7) + frame_count = 8; + return frame_count; +} + +/** + * megasas_build_dcdb - Prepares a direct cdb (DCDB) command + * @instance: Adapter soft state + * @scp: SCSI command + * @cmd: Command to be prepared in + * + * This function prepares CDB commands. These are typcially pass-through + * commands to the devices. + */ +static inline int +megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, + struct megasas_cmd *cmd) +{ + u32 is_logical; + u32 device_id; + u16 flags = 0; + struct megasas_pthru_frame *pthru; + + is_logical = MEGASAS_IS_LOGICAL(scp); + device_id = MEGASAS_DEV_INDEX(instance, scp); + pthru = (struct megasas_pthru_frame *)cmd->frame; + + if (scp->sc_data_direction == PCI_DMA_TODEVICE) + flags = MFI_FRAME_DIR_WRITE; + else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) + flags = MFI_FRAME_DIR_READ; + else if (scp->sc_data_direction == PCI_DMA_NONE) + flags = MFI_FRAME_DIR_NONE; + + /* + * Prepare the DCDB frame + */ + pthru->cmd = (is_logical) ? MFI_CMD_LD_SCSI_IO : MFI_CMD_PD_SCSI_IO; + pthru->cmd_status = 0x0; + pthru->scsi_status = 0x0; + pthru->target_id = device_id; + pthru->lun = scp->device->lun; + pthru->cdb_len = scp->cmd_len; + pthru->timeout = 0; + pthru->flags = flags; + pthru->data_xfer_len = scp->request_bufflen; + + memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); + + /* + * Construct SGL + */ + if (IS_DMA64) { + pthru->flags |= MFI_FRAME_SGL64; + pthru->sge_count = megasas_make_sgl64(instance, scp, + &pthru->sgl); + } else + pthru->sge_count = megasas_make_sgl32(instance, scp, + &pthru->sgl); + + /* + * Sense info specific + */ + pthru->sense_len = SCSI_SENSE_BUFFERSIZE; + pthru->sense_buf_phys_addr_hi = 0; + pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr; + + /* + * Compute the total number of frames this command consumes. FW uses + * this number to pull sufficient number of frames from host memory. + */ + cmd->frame_count = megasas_get_frame_count(pthru->sge_count); + + return cmd->frame_count; +} + +/** + * megasas_build_ldio - Prepares IOs to logical devices + * @instance: Adapter soft state + * @scp: SCSI command + * @cmd: Command to to be prepared + * + * Frames (and accompanying SGLs) for regular SCSI IOs use this function. + */ +static int +megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, + struct megasas_cmd *cmd) +{ + u32 device_id; + u8 sc = scp->cmnd[0]; + u16 flags = 0; + struct megasas_io_frame *ldio; + + device_id = MEGASAS_DEV_INDEX(instance, scp); + ldio = (struct megasas_io_frame *)cmd->frame; + + if (scp->sc_data_direction == PCI_DMA_TODEVICE) + flags = MFI_FRAME_DIR_WRITE; + else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) + flags = MFI_FRAME_DIR_READ; + + /* + * Prepare the Logical IO frame: 2nd bit is zero for all read cmds + */ + ldio->cmd = (sc & 0x02) ? MFI_CMD_LD_WRITE : MFI_CMD_LD_READ; + ldio->cmd_status = 0x0; + ldio->scsi_status = 0x0; + ldio->target_id = device_id; + ldio->timeout = 0; + ldio->reserved_0 = 0; + ldio->pad_0 = 0; + ldio->flags = flags; + ldio->start_lba_hi = 0; + ldio->access_byte = (scp->cmd_len != 6) ? scp->cmnd[1] : 0; + + /* + * 6-byte READ(0x08) or WRITE(0x0A) cdb + */ + if (scp->cmd_len == 6) { + ldio->lba_count = (u32) scp->cmnd[4]; + ldio->start_lba_lo = ((u32) scp->cmnd[1] << 16) | + ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3]; + + ldio->start_lba_lo &= 0x1FFFFF; + } + + /* + * 10-byte READ(0x28) or WRITE(0x2A) cdb + */ + else if (scp->cmd_len == 10) { + ldio->lba_count = (u32) scp->cmnd[8] | + ((u32) scp->cmnd[7] << 8); + ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) | + ((u32) scp->cmnd[3] << 16) | + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; + } + + /* + * 12-byte READ(0xA8) or WRITE(0xAA) cdb + */ + else if (scp->cmd_len == 12) { + ldio->lba_count = ((u32) scp->cmnd[6] << 24) | + ((u32) scp->cmnd[7] << 16) | + ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9]; + + ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) | + ((u32) scp->cmnd[3] << 16) | + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; + } + + /* + * 16-byte READ(0x88) or WRITE(0x8A) cdb + */ + else if (scp->cmd_len == 16) { + ldio->lba_count = ((u32) scp->cmnd[10] << 24) | + ((u32) scp->cmnd[11] << 16) | + ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13]; + + ldio->start_lba_lo = ((u32) scp->cmnd[6] << 24) | + ((u32) scp->cmnd[7] << 16) | + ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9]; + + ldio->start_lba_hi = ((u32) scp->cmnd[2] << 24) | + ((u32) scp->cmnd[3] << 16) | + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; + + } + + /* + * Construct SGL + */ + if (IS_DMA64) { + ldio->flags |= MFI_FRAME_SGL64; + ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); + } else + ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl); + + /* + * Sense info specific + */ + ldio->sense_len = SCSI_SENSE_BUFFERSIZE; + ldio->sense_buf_phys_addr_hi = 0; + ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr; + + /* + * Compute the total number of frames this command consumes. FW uses + * this number to pull sufficient number of frames from host memory. + */ + cmd->frame_count = megasas_get_frame_count(ldio->sge_count); + + return cmd->frame_count; +} + +/** + * megasas_is_ldio - Checks if the cmd is for logical drive + * @scmd: SCSI command + * + * Called by megasas_queue_command to find out if the command to be queued + * is a logical drive command + */ +static inline int megasas_is_ldio(struct scsi_cmnd *cmd) +{ + if (!MEGASAS_IS_LOGICAL(cmd)) + return 0; + switch (cmd->cmnd[0]) { + case READ_10: + case WRITE_10: + case READ_12: + case WRITE_12: + case READ_6: + case WRITE_6: + case READ_16: + case WRITE_16: + return 1; + default: + return 0; + } +} + + /** + * megasas_dump_pending_frames - Dumps the frame address of all pending cmds + * in FW + * @instance: Adapter soft state + */ +static inline void +megasas_dump_pending_frames(struct megasas_instance *instance) +{ + struct megasas_cmd *cmd; + int i,n; + union megasas_sgl *mfi_sgl; + struct megasas_io_frame *ldio; + struct megasas_pthru_frame *pthru; + u32 sgcount; + u32 max_cmd = instance->max_fw_cmds; + + printk(KERN_ERR "\nmegasas[%d]: Dumping Frame Phys Address of all pending cmds in FW\n",instance->host->host_no); + printk(KERN_ERR "megasas[%d]: Total OS Pending cmds : %d\n",instance->host->host_no,atomic_read(&instance->fw_outstanding)); + if (IS_DMA64) + printk(KERN_ERR "\nmegasas[%d]: 64 bit SGLs were sent to FW\n",instance->host->host_no); + else + printk(KERN_ERR "\nmegasas[%d]: 32 bit SGLs were sent to FW\n",instance->host->host_no); + + printk(KERN_ERR "megasas[%d]: Pending OS cmds in FW : \n",instance->host->host_no); + for (i = 0; i < max_cmd; i++) { + cmd = instance->cmd_list[i]; + if(!cmd->scmd) + continue; + printk(KERN_ERR "megasas[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr); + if (megasas_is_ldio(cmd->scmd)){ + ldio = (struct megasas_io_frame *)cmd->frame; + mfi_sgl = &ldio->sgl; + sgcount = ldio->sge_count; + printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lba lo : 0x%x, lba_hi : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no, cmd->frame_count,ldio->cmd,ldio->target_id, ldio->start_lba_lo,ldio->start_lba_hi,ldio->sense_buf_phys_addr_lo,sgcount); + } + else { + pthru = (struct megasas_pthru_frame *) cmd->frame; + mfi_sgl = &pthru->sgl; + sgcount = pthru->sge_count; + printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lun : 0x%x, cdb_len : 0x%x, data xfer len : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no,cmd->frame_count,pthru->cmd,pthru->target_id,pthru->lun,pthru->cdb_len , pthru->data_xfer_len,pthru->sense_buf_phys_addr_lo,sgcount); + } + if(megasas_dbg_lvl & MEGASAS_DBG_LVL){ + for (n = 0; n < sgcount; n++){ + if (IS_DMA64) + printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%08lx ",mfi_sgl->sge64[n].length , (unsigned long)mfi_sgl->sge64[n].phys_addr) ; + else + printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%x ",mfi_sgl->sge32[n].length , mfi_sgl->sge32[n].phys_addr) ; + } + } + printk(KERN_ERR "\n"); + } /*for max_cmd*/ + printk(KERN_ERR "\nmegasas[%d]: Pending Internal cmds in FW : \n",instance->host->host_no); + for (i = 0; i < max_cmd; i++) { + + cmd = instance->cmd_list[i]; + + if(cmd->sync_cmd == 1){ + printk(KERN_ERR "0x%08lx : ", (unsigned long)cmd->frame_phys_addr); + } + } + printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no); +} + +/** + * megasas_queue_command - Queue entry point + * @scmd: SCSI command to be queued + * @done: Callback entry point + */ +static int +megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) +{ + u32 frame_count; + struct megasas_cmd *cmd; + struct megasas_instance *instance; + + instance = (struct megasas_instance *) + scmd->device->host->hostdata; + scmd->scsi_done = done; + scmd->result = 0; + + if (MEGASAS_IS_LOGICAL(scmd) && + (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) { + scmd->result = DID_BAD_TARGET << 16; + goto out_done; + } + + if (MEGASAS_IS_LOGICAL(scmd)) { + switch (scmd->cmnd[0]) { + case SYNCHRONIZE_CACHE: + if (crashdump_mode()) + megasas_flush_cache(instance); + case REQUEST_SENSE: + case MODE_SELECT: + case MODE_SENSE: + if (crashdump_mode()) { + scmd->result = (DID_OK << 16); + goto out_done; + } + } + } + + cmd = megasas_get_cmd(instance); + if (!cmd) + return SCSI_MLQUEUE_HOST_BUSY; + + /* + * Logical drive command + */ + if (megasas_is_ldio(scmd)) + frame_count = megasas_build_ldio(instance, scmd, cmd); + else + frame_count = megasas_build_dcdb(instance, scmd, cmd); + + if (!frame_count) + goto out_return_cmd; + + cmd->scmd = scmd; + + /* + * Issue the command to the FW + */ + atomic_inc(&instance->fw_outstanding); + + instance->instancet->fire_cmd(cmd->frame_phys_addr , + cmd->frame_count-1,instance->reg_set); + + return 0; + + out_return_cmd: + megasas_return_cmd(instance, cmd); + out_done: + done(scmd); + return 0; +} + +/** + * megasas_wait_for_outstanding - Wait for all outstanding cmds + * @instance: Adapter soft state + * + * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to + * complete all its outstanding commands. Returns error if one or more IOs + * are pending after this time period. It also marks the controller dead. + */ +static int megasas_wait_for_outstanding(struct megasas_instance *instance) +{ + int i; + u32 wait_time = MEGASAS_RESET_WAIT_TIME; + + for (i = 0; i < wait_time; i++) { + + int outstanding = atomic_read(&instance->fw_outstanding); + + if (!outstanding) + break; + + if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { + printk(KERN_NOTICE "megasas: [%2d]waiting for %d " + "commands to complete\n",i,outstanding); + } + + /* + * In crash dump mode cannot complete cmds in interrupt context + * Complete cmds from here + */ + if (crashdump_mode()) { + megasas_deplete_reply_queue(instance, DID_OK); + diskdump_update(); + } + + megasas_msleep(1000); + } + + if (atomic_read(&instance->fw_outstanding)) { + /* + * Send signal to FW to stop processing any pending cmds. + * The controller will be taken offline by the OS now. + */ + writel(MFI_STOP_ADP, + &instance->reg_set->inbound_doorbell); + megasas_dump_pending_frames(instance); + instance->hw_crit_error = 1; + return FAILED; + } + + return SUCCESS; +} + +/** + * megasas_generic_reset - Generic reset routine + * @scmd: Mid-layer SCSI command + * + * This routine implements a generic reset handler for device, bus and host + * reset requests. Device, bus and host specific reset handlers can use this + * function after they do their specific tasks. + */ +static int megasas_generic_reset(struct scsi_cmnd *scmd) +{ + int ret_val; + struct megasas_instance *instance; + + instance = (struct megasas_instance *)scmd->device->host->hostdata; + + printk(KERN_NOTICE "megasas: RESET -%ld cmd=%x \n", + scmd->serial_number, scmd->cmnd[0], scmd->device->channel, + scmd->device->id, scmd->device->lun); + + if (instance->hw_crit_error) { + printk(KERN_ERR "megasas: cannot recover from previous reset " + "failures\n"); + return FAILED; + } + + spin_unlock(scmd->device->host->host_lock); + + ret_val = megasas_wait_for_outstanding(instance); + + if (ret_val == SUCCESS) + printk(KERN_NOTICE "megasas: reset successful \n"); + else + printk(KERN_ERR "megasas: failed to do reset\n"); + + spin_lock(scmd->device->host->host_lock); + + return ret_val; +} + +/** + * megasas_reset_device - Device reset handler entry point + */ +static int megasas_reset_device(struct scsi_cmnd *scmd) +{ + int ret; + + /* + * First wait for all commands to complete + */ + ret = megasas_generic_reset(scmd); + + return ret; +} + +/** + * megasas_reset_bus_host - Bus & host reset handler entry point + */ +static int megasas_reset_bus_host(struct scsi_cmnd *scmd) +{ + int ret; + + /* + * Frist wait for all commands to complete + */ + ret = megasas_generic_reset(scmd); + + return ret; +} + +/** + * megasas_service_aen - Processes an event notification + * @instance: Adapter soft state + * @cmd: AEN command completed by the ISR + * + * For AEN, driver sends a command down to FW that is held by the FW till an + * event occurs. When an event of interest occurs, FW completes the command + * that it was previously holding. + * + * This routines sends SIGIO signal to processes that have registered with the + * driver for AEN. + */ +static void +megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + /* + * Don't signal app if it is just an aborted previously registered aen + */ + if (!cmd->abort_aen) + kill_fasync(&megasas_async_queue, SIGIO, POLL_IN); + else + cmd->abort_aen = 0; + + instance->aen_cmd = NULL; + megasas_return_cmd(instance, cmd); +} + +static int megasas_slave_configure(struct scsi_device *sdev) +{ + /* + * The RAID firmware may require extended timeouts + */ + if(sdev->channel >= MEGASAS_MAX_PD_CHANNELS) + sdev->timeout = 90 * HZ ; + return 0; +} + +/** + * megasas_diskdump_sanity_check - Entry point for diskdump + */ +static int +megasas_diskdump_sanity_check(struct scsi_device *device) +{ + struct megasas_instance *instance; + + instance = (struct megasas_instance *)device->host->hostdata; + + if (!instance) + return -ENXIO; + + if (spin_is_locked(&instance->cmd_pool_lock)) + return -EBUSY; + + return 0; +} + +/** + * megasas_diskdump_poll - Interrupts are disabled during diskdump + * so this fn is called by diskdump driver to + * complete IO + */ +static void +megasas_diskdump_poll(struct scsi_device *device) +{ + struct megasas_instance *instance; + + instance = (struct megasas_instance *)device->host->hostdata; + + if (!instance) + return; + + megasas_isr(0, instance, NULL); +} + +/* + * Scsi host template for megaraid_sas driver + */ +static struct scsi_host_template megasas_template = { + + .module = THIS_MODULE, + .name = "LSI Logic SAS based MegaRAID driver", + .proc_name = "megaraid_sas", + .slave_configure = megasas_slave_configure, + .queuecommand = megasas_queue_command, + .eh_device_reset_handler = megasas_reset_device, + .eh_bus_reset_handler = megasas_reset_bus_host, + .eh_host_reset_handler = megasas_reset_bus_host, + .use_clustering = ENABLE_CLUSTERING, + .dump_sanity_check = megasas_diskdump_sanity_check, + .dump_poll = megasas_diskdump_poll, +}; + +/** + * megasas_complete_int_cmd - Completes an internal command + * @instance: Adapter soft state + * @cmd: Command to be completed + * + * The megasas_issue_blocked_cmd() function waits for a command to complete + * after it issues a command. This function wakes up that waiting routine by + * calling wake_up() on the wait queue. + */ +static void +megasas_complete_int_cmd(struct megasas_instance *instance, + struct megasas_cmd *cmd) +{ + cmd->cmd_status = cmd->frame->io.cmd_status; + + if (cmd->cmd_status == ENODATA) { + cmd->cmd_status = 0; + } + wake_up(&instance->int_cmd_wait_q); +} + +/** + * megasas_complete_abort - Completes aborting a command + * @instance: Adapter soft state + * @cmd: Cmd that was issued to abort another cmd + * + * The megasas_issue_blocked_abort_cmd() function waits on abort_cmd_wait_q + * after it issues an abort on a previously issued command. This function + * wakes up all functions waiting on the same wait queue. + */ +static void +megasas_complete_abort(struct megasas_instance *instance, + struct megasas_cmd *cmd) +{ + if (cmd->sync_cmd) { + cmd->sync_cmd = 0; + cmd->cmd_status = 0; + wake_up(&instance->abort_cmd_wait_q); + } + + return; +} + +/** + * megasas_unmap_sgbuf - Unmap SG buffers + * @instance: Adapter soft state + * @cmd: Completed command + */ +static inline void +megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + dma_addr_t buf_h; + u8 opcode; + + if (cmd->scmd->use_sg) { + pci_unmap_sg(instance->pdev, cmd->scmd->request_buffer, + cmd->scmd->use_sg, cmd->scmd->sc_data_direction); + return; + } + + if (!cmd->scmd->request_bufflen) + return; + + opcode = cmd->frame->hdr.cmd; + + if ((opcode == MFI_CMD_LD_READ) || (opcode == MFI_CMD_LD_WRITE)) { + if (IS_DMA64) + buf_h = cmd->frame->io.sgl.sge64[0].phys_addr; + else + buf_h = cmd->frame->io.sgl.sge32[0].phys_addr; + } else { + if (IS_DMA64) + buf_h = cmd->frame->pthru.sgl.sge64[0].phys_addr; + else + buf_h = cmd->frame->pthru.sgl.sge32[0].phys_addr; + } + + pci_unmap_single(instance->pdev, buf_h, cmd->scmd->request_bufflen, + cmd->scmd->sc_data_direction); + return; +} + +/** + * megasas_complete_cmd - Completes a command + * @instance: Adapter soft state + * @cmd: Command to be completed + * @alt_status: If non-zero, use this value as status to + * SCSI mid-layer instead of the value returned + * by the FW. This should be used if caller wants + * an alternate status (as in the case of aborted + * commands) + */ +static inline void +megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, + u8 alt_status) +{ + int exception = 0; + struct megasas_header *hdr = &cmd->frame->hdr; + + switch (hdr->cmd) { + + case MFI_CMD_PD_SCSI_IO: + case MFI_CMD_LD_SCSI_IO: + + /* + * MFI_CMD_PD_SCSI_IO and MFI_CMD_LD_SCSI_IO could have been + * issued either through an IO path or an IOCTL path. If it + * was via IOCTL, we will send it to internal completion. + */ + if (cmd->sync_cmd) { + cmd->sync_cmd = 0; + megasas_complete_int_cmd(instance, cmd); + break; + } + + /* + * Don't export physical disk devices to mid-layer. + */ + if (!MEGASAS_IS_LOGICAL(cmd->scmd) && + (hdr->cmd_status == MFI_STAT_OK) && + (cmd->scmd->cmnd[0] == INQUIRY)) { + + if (((*(u8 *) cmd->scmd->request_buffer) & 0x1F) == + TYPE_DISK) { + cmd->scmd->result = DID_BAD_TARGET << 16; + exception = 1; + } + } + + case MFI_CMD_LD_READ: + case MFI_CMD_LD_WRITE: + + if (alt_status) { + cmd->scmd->result = alt_status << 16; + exception = 1; + } + + if (exception) { + + atomic_dec(&instance->fw_outstanding); + + megasas_unmap_sgbuf(instance, cmd); + cmd->scmd->scsi_done(cmd->scmd); + megasas_return_cmd(instance, cmd); + + break; + } + + switch (hdr->cmd_status) { + + case MFI_STAT_OK: + cmd->scmd->result = DID_OK << 16; + break; + + case MFI_STAT_SCSI_IO_FAILED: + case MFI_STAT_LD_INIT_IN_PROGRESS: + cmd->scmd->result = + (DID_ERROR << 16) | hdr->scsi_status; + break; + + case MFI_STAT_SCSI_DONE_WITH_ERROR: + + cmd->scmd->result = (DID_OK << 16) | hdr->scsi_status; + + if (hdr->scsi_status == SAM_STAT_CHECK_CONDITION) { + memset(cmd->scmd->sense_buffer, 0, + SCSI_SENSE_BUFFERSIZE); + memcpy(cmd->scmd->sense_buffer, cmd->sense, + hdr->sense_len); + + cmd->scmd->result |= DRIVER_SENSE << 24; + } + + break; + + case MFI_STAT_LD_OFFLINE: + case MFI_STAT_DEVICE_NOT_FOUND: + cmd->scmd->result = DID_BAD_TARGET << 16; + break; + + default: + printk(KERN_DEBUG "megasas: MFI FW status %#x\n", + hdr->cmd_status); + cmd->scmd->result = DID_ERROR << 16; + break; + } + + atomic_dec(&instance->fw_outstanding); + + megasas_unmap_sgbuf(instance, cmd); + cmd->scmd->scsi_done(cmd->scmd); + megasas_return_cmd(instance, cmd); + + break; + + case MFI_CMD_SMP: + case MFI_CMD_STP: + case MFI_CMD_DCMD: + + /* + * See if got an event notification + */ + if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT) + megasas_service_aen(instance, cmd); + else + megasas_complete_int_cmd(instance, cmd); + + break; + + case MFI_CMD_ABORT: + /* + * Cmd issued to abort another cmd returned + */ + megasas_complete_abort(instance, cmd); + break; + + default: + printk("megasas: Unknown command completed! [0x%X]\n", + hdr->cmd); + break; + } +} + +/** + * megasas_deplete_reply_queue - Processes all completed commands + * @instance: Adapter soft state + * @alt_status: Alternate status to be returned to + * SCSI mid-layer instead of the status + * returned by the FW + */ +static int +megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) +{ + + /* + * Check if it is our interrupt + * Clear the interrupt + */ + if(instance->instancet->clear_intr(instance->reg_set)) + return IRQ_NONE; + + /* + * Schedule the tasklet for cmd completion + */ + tasklet_schedule(&instance->isr_tasklet); + + return IRQ_HANDLED; +} + +/** + * megasas_isr - isr entry point + */ +static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs) +{ + return megasas_deplete_reply_queue((struct megasas_instance *)devp, + DID_OK); +} + +/** + * megasas_transition_to_ready - Move the FW to READY state + * @instance: Adapter soft state + * + * During the initialization, FW passes can potentially be in any one of + * several possible states. If the FW in operational, waiting-for-handshake + * states, driver must take steps to bring it to ready state. Otherwise, it + * has to wait for the ready state. + */ +static int +megasas_transition_to_ready(struct megasas_instance* instance) +{ + int i; + u8 max_wait; + u32 fw_state; + u32 cur_state; + + fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK; + + if (fw_state != MFI_STATE_READY) + printk(KERN_INFO "megasas: Waiting for FW to come to ready" + " state\n"); + + while (fw_state != MFI_STATE_READY) { + + switch (fw_state) { + + case MFI_STATE_FAULT: + + printk(KERN_DEBUG "megasas: FW in FAULT state!!\n"); + return -ENODEV; + + case MFI_STATE_WAIT_HANDSHAKE: + /* + * Set the CLR bit in inbound doorbell + */ + writel(MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, + &instance->reg_set->inbound_doorbell); + + max_wait = 2; + cur_state = MFI_STATE_WAIT_HANDSHAKE; + break; + + case MFI_STATE_BOOT_MESSAGE_PENDING: + writel(MFI_INIT_HOTPLUG, + &instance->reg_set->inbound_doorbell); + + max_wait = 10; + cur_state = MFI_STATE_BOOT_MESSAGE_PENDING; + break; + + case MFI_STATE_OPERATIONAL: + /* + * Bring it to READY state; assuming max wait 10 secs + */ + instance->instancet->disable_intr(instance->reg_set); + writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell); + + max_wait = 10; + cur_state = MFI_STATE_OPERATIONAL; + break; + + case MFI_STATE_UNDEFINED: + /* + * This state should not last for more than 2 seconds + */ + max_wait = 2; + cur_state = MFI_STATE_UNDEFINED; + break; + + case MFI_STATE_BB_INIT: + max_wait = 2; + cur_state = MFI_STATE_BB_INIT; + break; + + case MFI_STATE_FW_INIT: + max_wait = 20; + cur_state = MFI_STATE_FW_INIT; + break; + + case MFI_STATE_FW_INIT_2: + max_wait = 20; + cur_state = MFI_STATE_FW_INIT_2; + break; + + case MFI_STATE_DEVICE_SCAN: + max_wait = 20; + cur_state = MFI_STATE_DEVICE_SCAN; + break; + + case MFI_STATE_FLUSH_CACHE: + max_wait = 20; + cur_state = MFI_STATE_FLUSH_CACHE; + break; + + default: + printk(KERN_DEBUG "megasas: Unknown state 0x%x\n", + fw_state); + return -ENODEV; + } + + /* + * The cur_state should not last for more than max_wait secs + */ + for (i = 0; i < (max_wait * 1000); i++) { + fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & + MFI_STATE_MASK ; + + if (fw_state == cur_state) { + megasas_msleep(1); + } else + break; + } + + /* + * Return error if fw_state hasn't changed after max_wait + */ + if (fw_state == cur_state) { + printk(KERN_DEBUG "FW state [%d] hasn't changed " + "in %d secs\n", fw_state, max_wait); + return -ENODEV; + } + }; + printk(KERN_INFO "megasas: FW now in Ready state\n"); + + return 0; +} + +/** + * megasas_teardown_frame_pool - Destroy the cmd frame DMA pool + * @instance: Adapter soft state + */ +static void megasas_teardown_frame_pool(struct megasas_instance *instance) +{ + int i; + u32 max_cmd = instance->max_fw_cmds; + struct megasas_cmd *cmd; + + if (!instance->frame_dma_pool) + return; + + /* + * Return all frames to pool + */ + for (i = 0; i < max_cmd; i++) { + + cmd = instance->cmd_list[i]; + + if (cmd->frame) + pci_pool_free(instance->frame_dma_pool, cmd->frame, + cmd->frame_phys_addr); + + if (cmd->sense) + pci_pool_free(instance->sense_dma_pool, cmd->frame, + cmd->sense_phys_addr); + } + + /* + * Now destroy the pool itself + */ + pci_pool_destroy(instance->frame_dma_pool); + pci_pool_destroy(instance->sense_dma_pool); + + instance->frame_dma_pool = NULL; + instance->sense_dma_pool = NULL; +} + +/** + * megasas_create_frame_pool - Creates DMA pool for cmd frames + * @instance: Adapter soft state + * + * Each command packet has an embedded DMA memory buffer that is used for + * filling MFI frame and the SG list that immediately follows the frame. This + * function creates those DMA memory buffers for each command packet by using + * PCI pool facility. + */ +static int megasas_create_frame_pool(struct megasas_instance *instance) +{ + int i; + u32 max_cmd; + u32 sge_sz; + u32 sgl_sz; + u32 total_sz; + u32 frame_count; + struct megasas_cmd *cmd; + + max_cmd = instance->max_fw_cmds; + + /* + * Size of our frame is 64 bytes for MFI frame, followed by max SG + * elements and finally SCSI_SENSE_BUFFERSIZE bytes for sense buffer + */ + sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : + sizeof(struct megasas_sge32); + + /* + * Calculated the number of 64byte frames required for SGL + */ + sgl_sz = sge_sz * instance->max_num_sge; + frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE; + + /* + * We need one extra frame for the MFI command + */ + frame_count++; + + total_sz = MEGAMFI_FRAME_SIZE * frame_count; + /* + * Use DMA pool facility provided by PCI layer + */ + instance->frame_dma_pool = pci_pool_create("megasas frame pool", + instance->pdev, total_sz, 64, + 0); + + if (!instance->frame_dma_pool) { + printk(KERN_DEBUG "megasas: failed to setup frame pool\n"); + return -ENOMEM; + } + + instance->sense_dma_pool = pci_pool_create("megasas sense pool", + instance->pdev, 128, 4, 0); + + if (!instance->sense_dma_pool) { + printk(KERN_DEBUG "megasas: failed to setup sense pool\n"); + + pci_pool_destroy(instance->frame_dma_pool); + instance->frame_dma_pool = NULL; + + return -ENOMEM; + } + + /* + * Allocate and attach a frame to each of the commands in cmd_list. + * By making cmd->index as the context instead of the &cmd, we can + * always use 32bit context regardless of the architecture + */ + for (i = 0; i < max_cmd; i++) { + + cmd = instance->cmd_list[i]; + + cmd->frame = pci_pool_alloc(instance->frame_dma_pool, + GFP_KERNEL, &cmd->frame_phys_addr); + + cmd->sense = pci_pool_alloc(instance->sense_dma_pool, + GFP_KERNEL, &cmd->sense_phys_addr); + + /* + * megasas_teardown_frame_pool() takes care of freeing + * whatever has been allocated + */ + if (!cmd->frame || !cmd->sense) { + printk(KERN_DEBUG "megasas: pci_pool_alloc failed \n"); + megasas_teardown_frame_pool(instance); + return -ENOMEM; + } + + cmd->frame->io.context = cmd->index; + } + + return 0; +} + +/** + * megasas_free_cmds - Free all the cmds in the free cmd pool + * @instance: Adapter soft state + */ +static void megasas_free_cmds(struct megasas_instance *instance) +{ + int i; + /* First free the MFI frame pool */ + megasas_teardown_frame_pool(instance); + + /* Free all the commands in the cmd_list */ + for (i = 0; i < instance->max_fw_cmds; i++) + kfree(instance->cmd_list[i]); + + /* Free the cmd_list buffer itself */ + kfree(instance->cmd_list); + instance->cmd_list = NULL; + + INIT_LIST_HEAD(&instance->cmd_pool); +} + +/** + * megasas_alloc_cmds - Allocates the command packets + * @instance: Adapter soft state + * + * Each command that is issued to the FW, whether IO commands from the OS or + * internal commands like IOCTLs, are wrapped in local data structure called + * megasas_cmd. The frame embedded in this megasas_cmd is actually issued to + * the FW. + * + * Each frame has a 32-bit field called context (tag). This context is used + * to get back the megasas_cmd from the frame when a frame gets completed in + * the ISR. Typically the address of the megasas_cmd itself would be used as + * the context. But we wanted to keep the differences between 32 and 64 bit + * systems to the mininum. We always use 32 bit integers for the context. In + * this driver, the 32 bit values are the indices into an array cmd_list. + * This array is used only to look up the megasas_cmd given the context. The + * free commands themselves are maintained in a linked list called cmd_pool. + */ +static int megasas_alloc_cmds(struct megasas_instance *instance) +{ + int i; + int j; + u32 max_cmd; + struct megasas_cmd *cmd; + + max_cmd = instance->max_fw_cmds; + + /* + * instance->cmd_list is an array of struct megasas_cmd pointers. + * Allocate the dynamic array first and then allocate individual + * commands. + */ + instance->cmd_list = kmalloc(sizeof(struct megasas_cmd *) * max_cmd, + GFP_KERNEL); + + if (!instance->cmd_list) { + printk(KERN_DEBUG "megasas: out of memory\n"); + return -ENOMEM; + } + + memset(instance->cmd_list, 0, sizeof(struct megasas_cmd *) * max_cmd); + + for (i = 0; i < max_cmd; i++) { + instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd), + GFP_KERNEL); + + if (!instance->cmd_list[i]) { + + for (j = 0; j < i; j++) + kfree(instance->cmd_list[j]); + + kfree(instance->cmd_list); + instance->cmd_list = NULL; + + return -ENOMEM; + } + } + + /* + * Add all the commands to command pool (instance->cmd_pool) + */ + for (i = 0; i < max_cmd; i++) { + cmd = instance->cmd_list[i]; + memset(cmd, 0, sizeof(struct megasas_cmd)); + cmd->index = i; + cmd->instance = instance; + + list_add_tail(&cmd->list, &instance->cmd_pool); + } + + /* + * Create a frame pool and assign one frame to each cmd + */ + if (megasas_create_frame_pool(instance)) { + printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n"); + megasas_free_cmds(instance); + } + + return 0; +} + +/** + * megasas_get_controller_info - Returns FW's controller structure + * @instance: Adapter soft state + * @ctrl_info: Controller information structure + * + * Issues an internal command (DCMD) to get the FW's controller structure. + * This information is mainly used to find out the maximum IO transfer per + * command supported by the FW. + */ +static int +megasas_get_ctrl_info(struct megasas_instance *instance, + struct megasas_ctrl_info *ctrl_info) +{ + int ret = 0; + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + struct megasas_ctrl_info *ci; + dma_addr_t ci_h = 0; + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + printk(KERN_DEBUG "megasas: Failed to get a free cmd\n"); + return -ENOMEM; + } + + dcmd = &cmd->frame->dcmd; + + ci = pci_alloc_consistent(instance->pdev, + sizeof(struct megasas_ctrl_info), &ci_h); + + if (!ci) { + printk(KERN_DEBUG "Failed to alloc mem for ctrl info\n"); + megasas_return_cmd(instance, cmd); + return -ENOMEM; + } + + memset(ci, 0, sizeof(*ci)); + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0xFF; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info); + dcmd->opcode = MR_DCMD_CTRL_GET_INFO; + dcmd->sgl.sge32[0].phys_addr = ci_h; + dcmd->sgl.sge32[0].length = sizeof(struct megasas_ctrl_info); + + if (!megasas_issue_polled(instance, cmd)) { + ret = 0; + memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info)); + } else { + ret = -1; + } + + pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info), + ci, ci_h); + + megasas_return_cmd(instance, cmd); + return ret; +} + +/** + * megasas_complete_cmd_dpc - Returns FW's controller structure + * @instance_addr: Address of adapter soft state + * + * Tasklet to complete cmds + */ +void megasas_complete_cmd_dpc(unsigned long instance_addr) +{ + u32 producer; + u32 consumer; + u32 context; + struct megasas_cmd *cmd; + struct megasas_instance *instance = (struct megasas_instance *)instance_addr; + + producer = *instance->producer; + consumer = *instance->consumer; + + while (consumer != producer) { + context = instance->reply_queue[consumer]; + + cmd = instance->cmd_list[context]; + + megasas_complete_cmd(instance, cmd, DID_OK); + + consumer++; + if (consumer == (instance->max_fw_cmds + 1)) { + consumer = 0; + } + } + + *instance->consumer = producer; +} + +/** + * megasas_init_mfi - Initializes the FW + * @instance: Adapter soft state + * + * This is the main function for initializing MFI firmware. + */ +static int megasas_init_mfi(struct megasas_instance *instance) +{ + u32 context_sz; + u32 reply_q_sz; + u32 max_sectors_1; + u32 max_sectors_2; + struct megasas_register_set __iomem *reg_set; + + struct megasas_cmd *cmd; + struct megasas_ctrl_info *ctrl_info; + + struct megasas_init_frame *init_frame; + struct megasas_init_queue_info *initq_info; + dma_addr_t init_frame_h; + dma_addr_t initq_info_h; + + /* + * Map the message registers + */ + instance->base_addr = pci_resource_start(instance->pdev, 0); + + if (pci_request_regions(instance->pdev, "megasas: LSI Logic")) { + printk(KERN_DEBUG "megasas: IO memory region busy!\n"); + return -EBUSY; + } + + instance->reg_set = ioremap_nocache(instance->base_addr, 8192); + + if (!instance->reg_set) { + printk(KERN_DEBUG "megasas: Failed to map IO mem\n"); + goto fail_ioremap; + } + + reg_set = instance->reg_set; + + switch(instance->pdev->device) + { + case PCI_DEVICE_ID_LSI_SAS1078R: + instance->instancet = &megasas_instance_template_ppc; + break; + case PCI_DEVICE_ID_LSI_SAS1064R: + case PCI_DEVICE_ID_DELL_PERC5: + default: + instance->instancet = &megasas_instance_template_xscale; + break; + } + + /* + * We expect the FW state to be READY + */ + if (megasas_transition_to_ready(instance)) + goto fail_ready_state; + + /* + * Get various operational parameters from status register + */ + instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF; + /* + * Reduce the max supported FW cmds by 1. This is to ensure that the + * reply_q_sz (1 more than the max cmd that driver may send) + * does not exceed max_fw_cmds + */ + instance->max_fw_cmds = instance->max_fw_cmds-1; + instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> + 0x10; + /* + * Create a pool of commands + */ + if (megasas_alloc_cmds(instance)) + goto fail_alloc_cmds; + + /* + * Allocate memory for reply queue. Length of reply queue should + * be _one_ more than the maximum commands handled by the firmware. + * + * Note: When FW completes commands, it places corresponding contex + * values in this circular reply queue. This circular queue is a fairly + * typical producer-consumer queue. FW is the producer (of completed + * commands) and the driver is the consumer. + */ + context_sz = sizeof(u32); + reply_q_sz = context_sz * (instance->max_fw_cmds + 1); + + instance->reply_queue = pci_alloc_consistent(instance->pdev, + reply_q_sz, + &instance->reply_queue_h); + + if (!instance->reply_queue) { + printk(KERN_DEBUG "megasas: Out of DMA mem for reply queue\n"); + goto fail_reply_queue; + } + + /* + * Prepare a init frame. Note the init frame points to queue info + * structure. Each frame has SGL allocated after first 64 bytes. For + * this frame - since we don't need any SGL - we use SGL's space as + * queue info structure + * + * We will not get a NULL command below. We just created the pool. + */ + cmd = megasas_get_cmd(instance); + + init_frame = (struct megasas_init_frame *)cmd->frame; + initq_info = (struct megasas_init_queue_info *) + ((unsigned long)init_frame + 64); + + init_frame_h = cmd->frame_phys_addr; + initq_info_h = init_frame_h + 64; + + memset(init_frame, 0, MEGAMFI_FRAME_SIZE); + memset(initq_info, 0, sizeof(struct megasas_init_queue_info)); + + initq_info->reply_queue_entries = instance->max_fw_cmds + 1; + initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h; + + initq_info->producer_index_phys_addr_lo = instance->producer_h; + initq_info->consumer_index_phys_addr_lo = instance->consumer_h; + + init_frame->cmd = MFI_CMD_INIT; + init_frame->cmd_status = 0xFF; + init_frame->queue_info_new_phys_addr_lo = initq_info_h; + + init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info); + + /* + * disable the intr before fire the init frame to FW + */ + instance->instancet->disable_intr(instance->reg_set); + + /* + * Issue the init frame in polled mode + */ + if (megasas_issue_polled(instance, cmd)) { + printk(KERN_DEBUG "megasas: Failed to init firmware\n"); + goto fail_fw_init; + } + + megasas_return_cmd(instance, cmd); + + ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); + + /* + * Compute the max allowed sectors per IO: The controller info has two + * limits on max sectors. Driver should use the minimum of these two. + * + * 1 << stripe_sz_ops.min = max sectors per strip + * + * Note that older firmwares ( < FW ver 30) didn't report information + * to calculate max_sectors_1. So the number ended up as zero always. + */ + if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) { + + max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) * + ctrl_info->max_strips_per_io; + max_sectors_2 = ctrl_info->max_request_size; + + instance->max_sectors_per_req = (max_sectors_1 < max_sectors_2) + ? max_sectors_1 : max_sectors_2; + } else + instance->max_sectors_per_req = instance->max_num_sge * + PAGE_SIZE / 512; + + kfree(ctrl_info); + + /* + * Setup tasklet for cmd completion + */ + + tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, + (unsigned long)instance); + + return 0; + + fail_fw_init: + megasas_return_cmd(instance, cmd); + + pci_free_consistent(instance->pdev, reply_q_sz, + instance->reply_queue, instance->reply_queue_h); + fail_reply_queue: + megasas_free_cmds(instance); + + fail_alloc_cmds: + fail_ready_state: + iounmap(instance->reg_set); + + fail_ioremap: + pci_release_regions(instance->pdev); + + return -EINVAL; +} + +/** + * megasas_release_mfi - Reverses the FW initialization + * @intance: Adapter soft state + */ +static void megasas_release_mfi(struct megasas_instance *instance) +{ + u32 reply_q_sz = sizeof(u32) * (instance->max_fw_cmds + 1); + + pci_free_consistent(instance->pdev, reply_q_sz, + instance->reply_queue, instance->reply_queue_h); + + megasas_free_cmds(instance); + + iounmap(instance->reg_set); + + pci_release_regions(instance->pdev); +} + +/** + * megasas_get_seq_num - Gets latest event sequence numbers + * @instance: Adapter soft state + * @eli: FW event log sequence numbers information + * + * FW maintains a log of all events in a non-volatile area. Upper layers would + * usually find out the latest sequence number of the events, the seq number at + * the boot etc. They would "read" all the events below the latest seq number + * by issuing a direct fw cmd (DCMD). For the future events (beyond latest seq + * number), they would subsribe to AEN (asynchronous event notification) and + * wait for the events to happen. + */ +static int +megasas_get_seq_num(struct megasas_instance *instance, + struct megasas_evt_log_info *eli) +{ + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + struct megasas_evt_log_info *el_info; + dma_addr_t el_info_h = 0; + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + return -ENOMEM; + } + + dcmd = &cmd->frame->dcmd; + el_info = pci_alloc_consistent(instance->pdev, + sizeof(struct megasas_evt_log_info), + &el_info_h); + + if (!el_info) { + megasas_return_cmd(instance, cmd); + return -ENOMEM; + } + + memset(el_info, 0, sizeof(*el_info)); + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0x0; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info); + dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO; + dcmd->sgl.sge32[0].phys_addr = el_info_h; + dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_log_info); + + megasas_issue_blocked_cmd(instance, cmd); + + /* + * Copy the data back into callers buffer + */ + memcpy(eli, el_info, sizeof(struct megasas_evt_log_info)); + + pci_free_consistent(instance->pdev, sizeof(struct megasas_evt_log_info), + el_info, el_info_h); + + megasas_return_cmd(instance, cmd); + + return 0; +} + +/** + * megasas_register_aen - Registers for asynchronous event notification + * @instance: Adapter soft state + * @seq_num: The starting sequence number + * @class_locale: Class of the event + * + * This function subscribes for AEN for events beyond the @seq_num. It requests + * to be notified if and only if the event is of type @class_locale + */ +static int +megasas_register_aen(struct megasas_instance *instance, u32 seq_num, + u32 class_locale_word) +{ + int ret_val; + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + union megasas_evt_class_locale curr_aen; + union megasas_evt_class_locale prev_aen; + + /* + * If there an AEN pending already (aen_cmd), check if the + * class_locale of that pending AEN is inclusive of the new + * AEN request we currently have. If it is, then we don't have + * to do anything. In other words, whichever events the current + * AEN request is subscribing to, have already been subscribed + * to. + * + * If the old_cmd is _not_ inclusive, then we have to abort + * that command, form a class_locale that is superset of both + * old and current and re-issue to the FW + */ + + curr_aen.word = class_locale_word; + + if (instance->aen_cmd) { + + prev_aen.word = instance->aen_cmd->frame->dcmd.mbox.w[1]; + + /* + * A class whose enum value is smaller is inclusive of all + * higher values. If a PROGRESS (= -1) was previously + * registered, then a new registration requests for higher + * classes need not be sent to FW. They are automatically + * included. + * + * Locale numbers don't have such hierarchy. They are bitmap + * values + */ + if ((prev_aen.members.class <= curr_aen.members.class) && + !((prev_aen.members.locale & curr_aen.members.locale) ^ + curr_aen.members.locale)) { + /* + * Previously issued event registration includes + * current request. Nothing to do. + */ + return 0; + } else { + curr_aen.members.locale |= prev_aen.members.locale; + + if (prev_aen.members.class < curr_aen.members.class) + curr_aen.members.class = prev_aen.members.class; + + instance->aen_cmd->abort_aen = 1; + ret_val = megasas_issue_blocked_abort_cmd(instance, + instance-> + aen_cmd); + + if (ret_val) { + printk(KERN_DEBUG "megasas: Failed to abort " + "previous AEN command\n"); + return ret_val; + } + } + } + + cmd = megasas_get_cmd(instance); + + if (!cmd) + return -ENOMEM; + + dcmd = &cmd->frame->dcmd; + + memset(instance->evt_detail, 0, sizeof(struct megasas_evt_detail)); + + /* + * Prepare DCMD for aen registration + */ + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0x0; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->data_xfer_len = sizeof(struct megasas_evt_detail); + dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT; + dcmd->mbox.w[0] = seq_num; + dcmd->mbox.w[1] = curr_aen.word; + dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h; + dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail); + + /* + * Store reference to the cmd used to register for AEN. When an + * application wants us to register for AEN, we have to abort this + * cmd and re-register with a new EVENT LOCALE supplied by that app + */ + instance->aen_cmd = cmd; + + /* + * Issue the aen registration frame + */ + instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); + + return 0; +} + +/** + * megasas_start_aen - Subscribes to AEN during driver load time + * @instance: Adapter soft state + */ +static int megasas_start_aen(struct megasas_instance *instance) +{ + struct megasas_evt_log_info eli; + union megasas_evt_class_locale class_locale; + + /* + * Get the latest sequence number from FW + */ + memset(&eli, 0, sizeof(eli)); + + if (megasas_get_seq_num(instance, &eli)) + return -1; + + /* + * Register AEN with FW for latest sequence number plus 1 + */ + class_locale.members.reserved = 0; + class_locale.members.locale = MR_EVT_LOCALE_ALL; + class_locale.members.class = MR_EVT_CLASS_DEBUG; + + return megasas_register_aen(instance, eli.newest_seq_num + 1, + class_locale.word); +} + +/** + * megasas_io_attach - Attaches this driver to SCSI mid-layer + * @instance: Adapter soft state + */ +static int megasas_io_attach(struct megasas_instance *instance) +{ + struct Scsi_Host *host = instance->host; + + /* + * Export parameters required by SCSI mid-layer + */ + host->irq = instance->pdev->irq; + host->unique_id = instance->unique_id; + host->can_queue = instance->max_fw_cmds - MEGASAS_INT_CMDS; + host->this_id = instance->init_id; + host->sg_tablesize = instance->max_num_sge; + host->max_sectors = instance->max_sectors_per_req; + host->cmd_per_lun = 128; + host->max_channel = MEGASAS_MAX_CHANNELS - 1; + host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL; + host->max_lun = MEGASAS_MAX_LUN; + host->max_cmd_len = 16; + + /* + * Notify the mid-layer about the new controller + */ + if (scsi_add_host(host, &instance->pdev->dev)) { + printk(KERN_DEBUG "megasas: scsi_add_host failed\n"); + return -ENODEV; + } + + /* + * Trigger SCSI to scan our drives + */ + scsi_scan_host(host); + return 0; +} + +/** + * megasas_probe_one - PCI hotplug entry point + * @pdev: PCI device structure + * @id: PCI ids of supported hotplugged adapter + */ +static int __devinit +megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int rval; + struct Scsi_Host *host; + struct megasas_instance *instance; + + /* + * Announce PCI information + */ + printk(KERN_INFO "megasas: %#4.04x:%#4.04x:%#4.04x:%#4.04x: ", + pdev->vendor, pdev->device, pdev->subsystem_vendor, + pdev->subsystem_device); + + printk("bus %d:slot %d:func %d\n", + pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + + /* + * PCI prepping: enable device set bus mastering and dma mask + */ + rval = pci_enable_device(pdev); + + if (rval) { + return rval; + } + + pci_set_master(pdev); + + /* + * All our contollers are capable of performing 64-bit DMA + */ + if (IS_DMA64) { + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) != 0) { + + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) + goto fail_set_dma_mask; + } + } else { + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) + goto fail_set_dma_mask; + } + + host = scsi_host_alloc(&megasas_template, + sizeof(struct megasas_instance)); + + if (!host) { + printk(KERN_DEBUG "megasas: scsi_host_alloc failed\n"); + goto fail_alloc_instance; + } + + instance = (struct megasas_instance *)host->hostdata; + memset(instance, 0, sizeof(*instance)); + + instance->producer = pci_alloc_consistent(pdev, sizeof(u32), + &instance->producer_h); + instance->consumer = pci_alloc_consistent(pdev, sizeof(u32), + &instance->consumer_h); + + if (!instance->producer || !instance->consumer) { + printk(KERN_DEBUG "megasas: Failed to allocate memory for " + "producer, consumer\n"); + goto fail_alloc_dma_buf; + } + + *instance->producer = 0; + *instance->consumer = 0; + + instance->evt_detail = pci_alloc_consistent(pdev, + sizeof(struct + megasas_evt_detail), + &instance->evt_detail_h); + + if (!instance->evt_detail) { + printk(KERN_DEBUG "megasas: Failed to allocate memory for " + "event detail structure\n"); + goto fail_alloc_dma_buf; + } + + /* + * Initialize locks and queues + */ + INIT_LIST_HEAD(&instance->cmd_pool); + + atomic_set(&instance->fw_outstanding,0); + + init_waitqueue_head(&instance->int_cmd_wait_q); + init_waitqueue_head(&instance->abort_cmd_wait_q); + + spin_lock_init(&instance->cmd_pool_lock); + + sema_init(&instance->aen_mutex, 1); + sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); + + /* + * Initialize PCI related and misc parameters + */ + instance->pdev = pdev; + instance->host = host; + instance->unique_id = pdev->bus->number << 8 | pdev->devfn; + instance->init_id = MEGASAS_DEFAULT_INIT_ID; + + megasas_dbg_lvl = 0; + + /* + * Initialize MFI Firmware + */ + if (megasas_init_mfi(instance)) + goto fail_init_mfi; + + /* + * Register IRQ + */ + if (request_irq(pdev->irq, megasas_isr, SA_SHIRQ, "megasas", instance)) { + printk(KERN_DEBUG "megasas: Failed to register IRQ\n"); + goto fail_irq; + } + + instance->instancet->enable_intr(instance->reg_set); + + /* + * Store instance in PCI softstate + */ + pci_set_drvdata(pdev, instance); + + /* + * Add this controller to megasas_mgmt_info structure so that it + * can be exported to management applications + */ + megasas_mgmt_info.count++; + megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = instance; + megasas_mgmt_info.max_index++; + + /* + * Initiate AEN (Asynchronous Event Notification) + */ + if (megasas_start_aen(instance)) { + printk(KERN_DEBUG "megasas: start aen failed\n"); + goto fail_start_aen; + } + + /* + * Register with SCSI mid-layer + */ + if (megasas_io_attach(instance)) + goto fail_io_attach; + + return 0; + + fail_start_aen: + fail_io_attach: + megasas_mgmt_info.count--; + megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL; + megasas_mgmt_info.max_index--; + + pci_set_drvdata(pdev, NULL); + instance->instancet->disable_intr(instance->reg_set); + free_irq(instance->pdev->irq, instance); + + megasas_release_mfi(instance); + + fail_irq: + fail_init_mfi: + fail_alloc_dma_buf: + if (instance->evt_detail) + pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), + instance->evt_detail, + instance->evt_detail_h); + + if (instance->producer) + pci_free_consistent(pdev, sizeof(u32), instance->producer, + instance->producer_h); + if (instance->consumer) + pci_free_consistent(pdev, sizeof(u32), instance->consumer, + instance->consumer_h); + scsi_host_put(host); + + fail_alloc_instance: + fail_set_dma_mask: + pci_disable_device(pdev); + + return -ENODEV; +} + +/** + * megasas_flush_cache - Requests FW to flush all its caches + * @instance: Adapter soft state + */ +static void megasas_flush_cache(struct megasas_instance *instance) +{ + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + + cmd = megasas_get_cmd(instance); + + if (!cmd) + return; + + dcmd = &cmd->frame->dcmd; + + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0x0; + dcmd->sge_count = 0; + dcmd->flags = MFI_FRAME_DIR_NONE; + dcmd->timeout = 0; + dcmd->data_xfer_len = 0; + dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH; + dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE; + + if (crashdump_mode()) + megasas_issue_polled(instance, cmd); + else + megasas_issue_blocked_cmd(instance, cmd); + + megasas_return_cmd(instance, cmd); + + return; +} + +/** + * megasas_shutdown_controller - Instructs FW to shutdown the controller + * @instance: Adapter soft state + */ +static void megasas_shutdown_controller(struct megasas_instance *instance) +{ + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + + cmd = megasas_get_cmd(instance); + + if (!cmd) + return; + + if (instance->aen_cmd) + megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd); + + dcmd = &cmd->frame->dcmd; + + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0x0; + dcmd->sge_count = 0; + dcmd->flags = MFI_FRAME_DIR_NONE; + dcmd->timeout = 0; + dcmd->data_xfer_len = 0; + dcmd->opcode = MR_DCMD_CTRL_SHUTDOWN; + + megasas_issue_blocked_cmd(instance, cmd); + + megasas_return_cmd(instance, cmd); + + return; +} + +/** + * megasas_detach_one - PCI hot"un"plug entry point + * @pdev: PCI device structure + */ +static void megasas_detach_one(struct pci_dev *pdev) +{ + int i; + struct Scsi_Host *host; + struct megasas_instance *instance; + + instance = pci_get_drvdata(pdev); + host = instance->host; + + scsi_remove_host(instance->host); + megasas_flush_cache(instance); + megasas_shutdown_controller(instance); + tasklet_kill(&instance->isr_tasklet); + + /* + * Take the instance off the instance array. Note that we will not + * decrement the max_index. We let this array be sparse array + */ + for (i = 0; i < megasas_mgmt_info.max_index; i++) { + if (megasas_mgmt_info.instance[i] == instance) { + megasas_mgmt_info.count--; + megasas_mgmt_info.instance[i] = NULL; + + break; + } + } + + pci_set_drvdata(instance->pdev, NULL); + + instance->instancet->disable_intr(instance->reg_set); + + free_irq(instance->pdev->irq, instance); + + megasas_release_mfi(instance); + + pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), + instance->evt_detail, instance->evt_detail_h); + + pci_free_consistent(pdev, sizeof(u32), instance->producer, + instance->producer_h); + + pci_free_consistent(pdev, sizeof(u32), instance->consumer, + instance->consumer_h); + + scsi_host_put(host); + + pci_set_drvdata(pdev, NULL); + + pci_disable_device(pdev); + + return; +} + +/** + * megasas_shutdown - Shutdown entry point + * @device: Generic device structure + */ +static void megasas_shutdown(struct device *device) +{ + struct megasas_instance *instance = (struct megasas_instance *) + dev_get_drvdata(device); + megasas_flush_cache(instance); +} + +/** + * megasas_mgmt_open - char node "open" entry point + */ +static int megasas_mgmt_open(struct inode *inode, struct file *filep) +{ + /* + * Allow only those users with admin rights + */ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + return 0; +} + +/** + * megasas_mgmt_release - char node "release" entry point + */ +static int megasas_mgmt_release(struct inode *inode, struct file *filep) +{ + filep->private_data = NULL; + fasync_helper(-1, filep, 0, &megasas_async_queue); + + return 0; +} + +/** + * megasas_mgmt_fasync - Async notifier registration from applications + * + * This function adds the calling process to a driver global queue. When an + * event occurs, SIGIO will be sent to all processes in this queue. + */ +static int megasas_mgmt_fasync(int fd, struct file *filep, int mode) +{ + int rc; + + down(&megasas_async_queue_mutex); + + rc = fasync_helper(fd, filep, mode, &megasas_async_queue); + + up(&megasas_async_queue_mutex); + + if (rc >= 0) { + /* For sanity check when we get ioctl */ + filep->private_data = filep; + return 0; + } + + printk(KERN_DEBUG "megasas: fasync_helper failed [%d]\n", rc); + + return rc; +} + +/** + * megasas_mgmt_fw_ioctl - Issues management ioctls to FW + * @instance: Adapter soft state + * @argp: User's ioctl packet + */ +static int +megasas_mgmt_fw_ioctl(struct megasas_instance *instance, + struct megasas_iocpacket __user * user_ioc, + struct megasas_iocpacket *ioc) +{ + struct megasas_sge32 *kern_sge32; + struct megasas_cmd *cmd; + void *kbuff_arr[MAX_IOCTL_SGE]; + dma_addr_t buf_handle = 0; + int error = 0, i; + void *sense = NULL; + dma_addr_t sense_handle; + u32 *sense_ptr; + + memset(kbuff_arr, 0, sizeof(kbuff_arr)); + + if (ioc->sge_count > MAX_IOCTL_SGE) { + printk(KERN_DEBUG "megasas: SGE count [%d] > max limit [%d]\n", + ioc->sge_count, MAX_IOCTL_SGE); + return -EINVAL; + } + + cmd = megasas_get_cmd(instance); + if (!cmd) { + printk(KERN_DEBUG "megasas: Failed to get a cmd packet\n"); + return -ENOMEM; + } + + /* + * User's IOCTL packet has 2 frames (maximum). Copy those two + * frames into our cmd's frames. cmd->frame's context will get + * overwritten when we copy from user's frames. So set that value + * alone separately + */ + memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); + cmd->frame->hdr.context = cmd->index; + + /* + * The management interface between applications and the fw uses + * MFI frames. E.g, RAID configuration changes, LD property changes + * etc are accomplishes through different kinds of MFI frames. The + * driver needs to care only about substituting user buffers with + * kernel buffers in SGLs. The location of SGL is embedded in the + * struct iocpacket itself. + */ + kern_sge32 = (struct megasas_sge32 *) + ((unsigned long)cmd->frame + ioc->sgl_off); + + /* + * For each user buffer, create a mirror buffer and copy in + */ + for (i = 0; i < ioc->sge_count; i++) { + kbuff_arr[i] = pci_alloc_consistent(instance->pdev, + ioc->sgl[i].iov_len, + &buf_handle); + if (!kbuff_arr[i]) { + printk(KERN_DEBUG "megasas: Failed to alloc " + "kernel SGL buffer for IOCTL \n"); + error = -ENOMEM; + goto out; + } + + /* + * We don't change the dma_coherent_mask, so + * pci_alloc_consistent only returns 32bit addresses + */ + kern_sge32[i].phys_addr = (u32) buf_handle; + kern_sge32[i].length = ioc->sgl[i].iov_len; + + /* + * We created a kernel buffer corresponding to the + * user buffer. Now copy in from the user buffer + */ + if (copy_from_user(kbuff_arr[i], ioc->sgl[i].iov_base, + (u32) (ioc->sgl[i].iov_len))) { + error = -EFAULT; + goto out; + } + } + + if (ioc->sense_len) { + sense = pci_alloc_consistent(instance->pdev, ioc->sense_len, + &sense_handle); + if (!sense) { + error = -ENOMEM; + goto out; + } + + sense_ptr = + (u32 *) ((unsigned long)cmd->frame + ioc->sense_off); + *sense_ptr = sense_handle; + } + + /* + * Set the sync_cmd flag so that the ISR knows not to complete this + * cmd to the SCSI mid-layer + */ + cmd->sync_cmd = 1; + megasas_issue_blocked_cmd(instance, cmd); + cmd->sync_cmd = 0; + + /* + * copy out the kernel buffers to user buffers + */ + for (i = 0; i < ioc->sge_count; i++) { + if (copy_to_user(ioc->sgl[i].iov_base, kbuff_arr[i], + ioc->sgl[i].iov_len)) { + error = -EFAULT; + goto out; + } + } + + /* + * copy out the sense + */ + if (ioc->sense_len) { + /* + * sense_ptr points to the location that has the user + * sense buffer address + */ + sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw + + ioc->sense_off); + + if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)), + sense, ioc->sense_len)) { + error = -EFAULT; + goto out; + } + } + + /* + * copy the status codes returned by the fw + */ + if (copy_to_user(&user_ioc->frame.hdr.cmd_status, + &cmd->frame->hdr.cmd_status, sizeof(u8))) { + printk(KERN_DEBUG "megasas: Error copying out cmd_status\n"); + error = -EFAULT; + } + + out: + if (sense) { + pci_free_consistent(instance->pdev, ioc->sense_len, + sense, sense_handle); + } + + for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) { + pci_free_consistent(instance->pdev, + kern_sge32[i].length, + kbuff_arr[i], kern_sge32[i].phys_addr); + } + + megasas_return_cmd(instance, cmd); + return error; +} + +static struct megasas_instance *megasas_lookup_instance(u16 host_no) +{ + int i; + + for (i = 0; i < megasas_mgmt_info.max_index; i++) { + + if ((megasas_mgmt_info.instance[i]) && + (megasas_mgmt_info.instance[i]->host->host_no == host_no)) + return megasas_mgmt_info.instance[i]; + } + + return NULL; +} + +static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) +{ + struct megasas_iocpacket __user *user_ioc = + (struct megasas_iocpacket __user *)arg; + struct megasas_iocpacket *ioc; + struct megasas_instance *instance; + int error; + + ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); + if (!ioc) + return -ENOMEM; + + if (copy_from_user(ioc, user_ioc, sizeof(*ioc))) { + error = -EFAULT; + goto out_kfree_ioc; + } + + instance = megasas_lookup_instance(ioc->host_no); + if (!instance) { + error = -ENODEV; + goto out_kfree_ioc; + } + + /* + * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds + */ + if (down_interruptible(&instance->ioctl_sem)) { + error = -ERESTARTSYS; + goto out_kfree_ioc; + } + error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc); + up(&instance->ioctl_sem); + + out_kfree_ioc: + kfree(ioc); + return error; +} + +static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) +{ + struct megasas_instance *instance; + struct megasas_aen aen; + int error; + + if (file->private_data != file) { + printk(KERN_DEBUG "megasas: fasync_helper was not " + "called first\n"); + return -EINVAL; + } + + if (copy_from_user(&aen, (void __user *)arg, sizeof(aen))) + return -EFAULT; + + instance = megasas_lookup_instance(aen.host_no); + + if (!instance) + return -ENODEV; + + down(&instance->aen_mutex); + error = megasas_register_aen(instance, aen.seq_num, + aen.class_locale_word); + up(&instance->aen_mutex); + return error; +} + +/** + * megasas_mgmt_ioctl - char node ioctl entry point + */ +static int +megasas_mgmt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + switch (cmd) { + case MEGASAS_IOC_FIRMWARE: + return megasas_mgmt_ioctl_fw(file, arg); + case MEGASAS_IOC_GET_AEN: + return megasas_mgmt_ioctl_aen(file, arg); + } + + return -ENOTTY; +} + +#ifdef CONFIG_COMPAT +static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) +{ + struct compat_megasas_iocpacket __user *cioc = + (struct compat_megasas_iocpacket __user *)arg; + struct megasas_iocpacket __user *ioc = + compat_alloc_user_space(sizeof(struct megasas_iocpacket)); + int i; + int error = 0; + + if (clear_user(ioc, sizeof(*ioc))) + return -EFAULT; + + if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) || + copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) || + copy_in_user(&ioc->sense_off, &cioc->sense_off, sizeof(u32)) || + copy_in_user(&ioc->sense_len, &cioc->sense_len, sizeof(u32)) || + copy_in_user(ioc->frame.raw, cioc->frame.raw, 128) || + copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32))) + return -EFAULT; + + for (i = 0; i < MAX_IOCTL_SGE; i++) { + compat_uptr_t ptr; + + if (get_user(ptr, &cioc->sgl[i].iov_base) || + put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) || + copy_in_user(&ioc->sgl[i].iov_len, + &cioc->sgl[i].iov_len, sizeof(compat_size_t))) + return -EFAULT; + } + + error = megasas_mgmt_ioctl_fw(file, (unsigned long)ioc); + + if (copy_in_user(&cioc->frame.hdr.cmd_status, + &ioc->frame.hdr.cmd_status, sizeof(u8))) { + printk(KERN_DEBUG "megasas: error copy_in_user cmd_status\n"); + return -EFAULT; + } + return error; +} + +static long +megasas_mgmt_compat_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, + struct file *file) +{ + switch (cmd) { + case MEGASAS_IOC_FIRMWARE32: + return megasas_mgmt_compat_ioctl_fw(file, arg); + case MEGASAS_IOC_GET_AEN: + return megasas_mgmt_ioctl_aen(file, arg); + } + + return -ENOTTY; +} +#endif + +/* + * File operations structure for management interface + */ +static struct file_operations megasas_mgmt_fops = { + .owner = THIS_MODULE, + .open = megasas_mgmt_open, + .release = megasas_mgmt_release, + .fasync = megasas_mgmt_fasync, + .ioctl = megasas_mgmt_ioctl, +}; + +/* + * PCI hotplug support registration structure + */ +static struct pci_driver megasas_pci_driver = { + + .name = "megaraid_sas", + .id_table = megasas_pci_table, + .probe = megasas_probe_one, + .remove = __devexit_p(megasas_detach_one), + .driver = { + .shutdown = megasas_shutdown, + } +}; + +/* + * Sysfs driver attributes + */ +static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf) +{ + return snprintf(buf, strlen(MEGASAS_VERSION) + 2, "%s\n", + MEGASAS_VERSION); +} + +static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL); + +static ssize_t +megasas_sysfs_show_release_date(struct device_driver *dd, char *buf) +{ + return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n", + MEGASAS_RELDATE); +} + +static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date, + NULL); + +static ssize_t +megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf) +{ + return sprintf(buf,"%u",megasas_dbg_lvl); +} + +static ssize_t +megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t count) +{ + int retval = count; + if(sscanf(buf,"%u",&megasas_dbg_lvl)<1){ + printk(KERN_ERR "megasas: could not set dbg_lvl\n"); + retval = -EINVAL; + } + return retval; +} + +static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl, + megasas_sysfs_set_dbg_lvl); + +/** + * megasas_init - Driver load entry point + */ +static int __init megasas_init(void) +{ + int rval; + + /* + * Announce driver version and other information + */ + printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, + MEGASAS_EXT_VERSION); + + memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info)); + + /* + * Register character device node + */ + rval = register_chrdev(0, "megaraid_sas_ioctl", &megasas_mgmt_fops); + + if (rval < 0) { + printk(KERN_DEBUG "megasas: failed to open device node\n"); + return rval; + } + + megasas_mgmt_majorno = rval; + + /* + * Register ourselves as PCI hotplug module + */ + rval = pci_module_init(&megasas_pci_driver); + + if (rval) { + printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n"); + goto err_pcidrv; + } + + rval = driver_create_file(&megasas_pci_driver.driver, + &driver_attr_version); + if (rval) + goto err_dcf_attr_ver; + rval = driver_create_file(&megasas_pci_driver.driver, + &driver_attr_release_date); + if (rval) + goto err_dcf_rel_date; + rval = driver_create_file(&megasas_pci_driver.driver, + &driver_attr_dbg_lvl); + if (rval) + goto err_dcf_dbg_lvl; + +#ifdef CONFIG_COMPAT + register_ioctl32_conversion(MEGASAS_IOC_FIRMWARE32, + megasas_mgmt_compat_ioctl); + register_ioctl32_conversion(MEGASAS_IOC_GET_AEN, + megasas_mgmt_compat_ioctl); +#endif + return rval; +err_dcf_dbg_lvl: + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_release_date); +err_dcf_rel_date: + driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); +err_dcf_attr_ver: + pci_unregister_driver(&megasas_pci_driver); +err_pcidrv: + unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); + return rval; +} + +/** + * megasas_exit - Driver unload entry point + */ +static void __exit megasas_exit(void) +{ +#ifdef CONFIG_COMPAT + unregister_ioctl32_conversion(MEGASAS_IOC_FIRMWARE32); + unregister_ioctl32_conversion(MEGASAS_IOC_GET_AEN); +#endif + driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_release_date); + + pci_unregister_driver(&megasas_pci_driver); + unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); +} + +module_init(megasas_init); +module_exit(megasas_exit); diff --git a/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_sas.h b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_sas.h new file mode 100644 index 0000000..082b641 --- /dev/null +++ b/src/kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2/megaraid_sas.h @@ -0,0 +1,1194 @@ +/* + * + * Linux MegaRAID driver for SAS based RAID controllers + * + * Copyright (c) 2003-2005 LSI Logic Corporation. + * + * 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. + * + * FILE : megaraid_sas.h + */ + +#ifndef LSI_MEGARAID_SAS_H +#define LSI_MEGARAID_SAS_H + +/** + * MegaRAID SAS Driver meta data + */ +#define MEGASAS_VERSION "00.00.03.05" +#define MEGASAS_RELDATE "Oct 02, 2006" +#define MEGASAS_EXT_VERSION "Mon Oct 02 11:21:32 PDT 2006" + +/* + * Device IDs + */ +#define PCI_DEVICE_ID_LSI_SAS1078R 0x0060 +#define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413 + +/* + * Device IDs + */ +#define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413 + +/* + * ===================================== + * MegaRAID SAS MFI firmware definitions + * ===================================== + */ + +/* + * MFI stands for MegaRAID SAS FW Interface. This is just a moniker for + * protocol between the software and firmware. Commands are issued using + * "message frames" + */ + +/** + * FW posts its state in upper 4 bits of outbound_msg_0 register + */ +#define MFI_STATE_MASK 0xF0000000 +#define MFI_STATE_UNDEFINED 0x00000000 +#define MFI_STATE_BB_INIT 0x10000000 +#define MFI_STATE_FW_INIT 0x40000000 +#define MFI_STATE_WAIT_HANDSHAKE 0x60000000 +#define MFI_STATE_FW_INIT_2 0x70000000 +#define MFI_STATE_DEVICE_SCAN 0x80000000 +#define MFI_STATE_BOOT_MESSAGE_PENDING 0x90000000 +#define MFI_STATE_FLUSH_CACHE 0xA0000000 +#define MFI_STATE_READY 0xB0000000 +#define MFI_STATE_OPERATIONAL 0xC0000000 +#define MFI_STATE_FAULT 0xF0000000 + +#define MEGAMFI_FRAME_SIZE 64 + +/** + * During FW init, clear pending cmds & reset state using inbound_msg_0 + * + * ABORT : Abort all pending cmds + * READY : Move from OPERATIONAL to READY state; discard queue info + * MFIMODE : Discard (possible) low MFA posted in 64-bit mode (??) + * CLR_HANDSHAKE: FW is waiting for HANDSHAKE from BIOS or Driver + * HOTPLUG : Resume from Hotplug + * MFI_STOP_ADP : Send signal to FW to stop processing + */ +#define MFI_INIT_ABORT 0x00000001 +#define MFI_INIT_READY 0x00000002 +#define MFI_INIT_MFIMODE 0x00000004 +#define MFI_INIT_CLEAR_HANDSHAKE 0x00000008 +#define MFI_INIT_HOTPLUG 0x00000010 +#define MFI_STOP_ADP 0x00000020 +#define MFI_RESET_FLAGS MFI_INIT_READY| \ + MFI_INIT_MFIMODE| \ + MFI_INIT_ABORT + +/** + * MFI frame flags + */ +#define MFI_FRAME_POST_IN_REPLY_QUEUE 0x0000 +#define MFI_FRAME_DONT_POST_IN_REPLY_QUEUE 0x0001 +#define MFI_FRAME_SGL32 0x0000 +#define MFI_FRAME_SGL64 0x0002 +#define MFI_FRAME_SENSE32 0x0000 +#define MFI_FRAME_SENSE64 0x0004 +#define MFI_FRAME_DIR_NONE 0x0000 +#define MFI_FRAME_DIR_WRITE 0x0008 +#define MFI_FRAME_DIR_READ 0x0010 +#define MFI_FRAME_DIR_BOTH 0x0018 + +/** + * Definition for cmd_status + */ +#define MFI_CMD_STATUS_POLL_MODE 0xFF + +/** + * MFI command opcodes + */ +#define MFI_CMD_INIT 0x00 +#define MFI_CMD_LD_READ 0x01 +#define MFI_CMD_LD_WRITE 0x02 +#define MFI_CMD_LD_SCSI_IO 0x03 +#define MFI_CMD_PD_SCSI_IO 0x04 +#define MFI_CMD_DCMD 0x05 +#define MFI_CMD_ABORT 0x06 +#define MFI_CMD_SMP 0x07 +#define MFI_CMD_STP 0x08 + +#define MR_DCMD_CTRL_GET_INFO 0x01010000 + +#define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000 +#define MR_FLUSH_CTRL_CACHE 0x01 +#define MR_FLUSH_DISK_CACHE 0x02 + +#define MR_DCMD_CTRL_SHUTDOWN 0x01050000 +#define MR_ENABLE_DRIVE_SPINDOWN 0x01 + +#define MR_DCMD_CTRL_EVENT_GET_INFO 0x01040100 +#define MR_DCMD_CTRL_EVENT_GET 0x01040300 +#define MR_DCMD_CTRL_EVENT_WAIT 0x01040500 +#define MR_DCMD_LD_GET_PROPERTIES 0x03030000 + +#define MR_DCMD_CLUSTER 0x08000000 +#define MR_DCMD_CLUSTER_RESET_ALL 0x08010100 +#define MR_DCMD_CLUSTER_RESET_LD 0x08010200 + +/** + * MFI command completion codes + */ +enum MFI_STAT { + MFI_STAT_OK = 0x00, + MFI_STAT_INVALID_CMD = 0x01, + MFI_STAT_INVALID_DCMD = 0x02, + MFI_STAT_INVALID_PARAMETER = 0x03, + MFI_STAT_INVALID_SEQUENCE_NUMBER = 0x04, + MFI_STAT_ABORT_NOT_POSSIBLE = 0x05, + MFI_STAT_APP_HOST_CODE_NOT_FOUND = 0x06, + MFI_STAT_APP_IN_USE = 0x07, + MFI_STAT_APP_NOT_INITIALIZED = 0x08, + MFI_STAT_ARRAY_INDEX_INVALID = 0x09, + MFI_STAT_ARRAY_ROW_NOT_EMPTY = 0x0a, + MFI_STAT_CONFIG_RESOURCE_CONFLICT = 0x0b, + MFI_STAT_DEVICE_NOT_FOUND = 0x0c, + MFI_STAT_DRIVE_TOO_SMALL = 0x0d, + MFI_STAT_FLASH_ALLOC_FAIL = 0x0e, + MFI_STAT_FLASH_BUSY = 0x0f, + MFI_STAT_FLASH_ERROR = 0x10, + MFI_STAT_FLASH_IMAGE_BAD = 0x11, + MFI_STAT_FLASH_IMAGE_INCOMPLETE = 0x12, + MFI_STAT_FLASH_NOT_OPEN = 0x13, + MFI_STAT_FLASH_NOT_STARTED = 0x14, + MFI_STAT_FLUSH_FAILED = 0x15, + MFI_STAT_HOST_CODE_NOT_FOUNT = 0x16, + MFI_STAT_LD_CC_IN_PROGRESS = 0x17, + MFI_STAT_LD_INIT_IN_PROGRESS = 0x18, + MFI_STAT_LD_LBA_OUT_OF_RANGE = 0x19, + MFI_STAT_LD_MAX_CONFIGURED = 0x1a, + MFI_STAT_LD_NOT_OPTIMAL = 0x1b, + MFI_STAT_LD_RBLD_IN_PROGRESS = 0x1c, + MFI_STAT_LD_RECON_IN_PROGRESS = 0x1d, + MFI_STAT_LD_WRONG_RAID_LEVEL = 0x1e, + MFI_STAT_MAX_SPARES_EXCEEDED = 0x1f, + MFI_STAT_MEMORY_NOT_AVAILABLE = 0x20, + MFI_STAT_MFC_HW_ERROR = 0x21, + MFI_STAT_NO_HW_PRESENT = 0x22, + MFI_STAT_NOT_FOUND = 0x23, + MFI_STAT_NOT_IN_ENCL = 0x24, + MFI_STAT_PD_CLEAR_IN_PROGRESS = 0x25, + MFI_STAT_PD_TYPE_WRONG = 0x26, + MFI_STAT_PR_DISABLED = 0x27, + MFI_STAT_ROW_INDEX_INVALID = 0x28, + MFI_STAT_SAS_CONFIG_INVALID_ACTION = 0x29, + MFI_STAT_SAS_CONFIG_INVALID_DATA = 0x2a, + MFI_STAT_SAS_CONFIG_INVALID_PAGE = 0x2b, + MFI_STAT_SAS_CONFIG_INVALID_TYPE = 0x2c, + MFI_STAT_SCSI_DONE_WITH_ERROR = 0x2d, + MFI_STAT_SCSI_IO_FAILED = 0x2e, + MFI_STAT_SCSI_RESERVATION_CONFLICT = 0x2f, + MFI_STAT_SHUTDOWN_FAILED = 0x30, + MFI_STAT_TIME_NOT_SET = 0x31, + MFI_STAT_WRONG_STATE = 0x32, + MFI_STAT_LD_OFFLINE = 0x33, + MFI_STAT_PEER_NOTIFICATION_REJECTED = 0x34, + MFI_STAT_PEER_NOTIFICATION_FAILED = 0x35, + MFI_STAT_RESERVATION_IN_PROGRESS = 0x36, + MFI_STAT_I2C_ERRORS_DETECTED = 0x37, + MFI_STAT_PCI_ERRORS_DETECTED = 0x38, + + MFI_STAT_INVALID_STATUS = 0xFF +}; + +/* + * Number of mailbox bytes in DCMD message frame + */ +#define MFI_MBOX_SIZE 12 + +enum MR_EVT_CLASS { + + MR_EVT_CLASS_DEBUG = -2, + MR_EVT_CLASS_PROGRESS = -1, + MR_EVT_CLASS_INFO = 0, + MR_EVT_CLASS_WARNING = 1, + MR_EVT_CLASS_CRITICAL = 2, + MR_EVT_CLASS_FATAL = 3, + MR_EVT_CLASS_DEAD = 4, + +}; + +enum MR_EVT_LOCALE { + + MR_EVT_LOCALE_LD = 0x0001, + MR_EVT_LOCALE_PD = 0x0002, + MR_EVT_LOCALE_ENCL = 0x0004, + MR_EVT_LOCALE_BBU = 0x0008, + MR_EVT_LOCALE_SAS = 0x0010, + MR_EVT_LOCALE_CTRL = 0x0020, + MR_EVT_LOCALE_CONFIG = 0x0040, + MR_EVT_LOCALE_CLUSTER = 0x0080, + MR_EVT_LOCALE_ALL = 0xffff, + +}; + +enum MR_EVT_ARGS { + + MR_EVT_ARGS_NONE, + MR_EVT_ARGS_CDB_SENSE, + MR_EVT_ARGS_LD, + MR_EVT_ARGS_LD_COUNT, + MR_EVT_ARGS_LD_LBA, + MR_EVT_ARGS_LD_OWNER, + MR_EVT_ARGS_LD_LBA_PD_LBA, + MR_EVT_ARGS_LD_PROG, + MR_EVT_ARGS_LD_STATE, + MR_EVT_ARGS_LD_STRIP, + MR_EVT_ARGS_PD, + MR_EVT_ARGS_PD_ERR, + MR_EVT_ARGS_PD_LBA, + MR_EVT_ARGS_PD_LBA_LD, + MR_EVT_ARGS_PD_PROG, + MR_EVT_ARGS_PD_STATE, + MR_EVT_ARGS_PCI, + MR_EVT_ARGS_RATE, + MR_EVT_ARGS_STR, + MR_EVT_ARGS_TIME, + MR_EVT_ARGS_ECC, + +}; + +/* + * SAS controller properties + */ +struct megasas_ctrl_prop { + + u16 seq_num; + u16 pred_fail_poll_interval; + u16 intr_throttle_count; + u16 intr_throttle_timeouts; + u8 rebuild_rate; + u8 patrol_read_rate; + u8 bgi_rate; + u8 cc_rate; + u8 recon_rate; + u8 cache_flush_interval; + u8 spinup_drv_count; + u8 spinup_delay; + u8 cluster_enable; + u8 coercion_mode; + u8 alarm_enable; + u8 disable_auto_rebuild; + u8 disable_battery_warn; + u8 ecc_bucket_size; + u16 ecc_bucket_leak_rate; + u8 restore_hotspare_on_insertion; + u8 expose_encl_devices; + u8 reserved[38]; + +} __attribute__ ((packed)); + +/* + * SAS controller information + */ +struct megasas_ctrl_info { + + /* + * PCI device information + */ + struct { + + u16 vendor_id; + u16 device_id; + u16 sub_vendor_id; + u16 sub_device_id; + u8 reserved[24]; + + } __attribute__ ((packed)) pci; + + /* + * Host interface information + */ + struct { + + u8 PCIX:1; + u8 PCIE:1; + u8 iSCSI:1; + u8 SAS_3G:1; + u8 reserved_0:4; + u8 reserved_1[6]; + u8 port_count; + u64 port_addr[8]; + + } __attribute__ ((packed)) host_interface; + + /* + * Device (backend) interface information + */ + struct { + + u8 SPI:1; + u8 SAS_3G:1; + u8 SATA_1_5G:1; + u8 SATA_3G:1; + u8 reserved_0:4; + u8 reserved_1[6]; + u8 port_count; + u64 port_addr[8]; + + } __attribute__ ((packed)) device_interface; + + /* + * List of components residing in flash. All str are null terminated + */ + u32 image_check_word; + u32 image_component_count; + + struct { + + char name[8]; + char version[32]; + char build_date[16]; + char built_time[16]; + + } __attribute__ ((packed)) image_component[8]; + + /* + * List of flash components that have been flashed on the card, but + * are not in use, pending reset of the adapter. This list will be + * empty if a flash operation has not occurred. All stings are null + * terminated + */ + u32 pending_image_component_count; + + struct { + + char name[8]; + char version[32]; + char build_date[16]; + char build_time[16]; + + } __attribute__ ((packed)) pending_image_component[8]; + + u8 max_arms; + u8 max_spans; + u8 max_arrays; + u8 max_lds; + + char product_name[80]; + char serial_no[32]; + + /* + * Other physical/controller/operation information. Indicates the + * presence of the hardware + */ + struct { + + u32 bbu:1; + u32 alarm:1; + u32 nvram:1; + u32 uart:1; + u32 reserved:28; + + } __attribute__ ((packed)) hw_present; + + u32 current_fw_time; + + /* + * Maximum data transfer sizes + */ + u16 max_concurrent_cmds; + u16 max_sge_count; + u32 max_request_size; + + /* + * Logical and physical device counts + */ + u16 ld_present_count; + u16 ld_degraded_count; + u16 ld_offline_count; + + u16 pd_present_count; + u16 pd_disk_present_count; + u16 pd_disk_pred_failure_count; + u16 pd_disk_failed_count; + + /* + * Memory size information + */ + u16 nvram_size; + u16 memory_size; + u16 flash_size; + + /* + * Error counters + */ + u16 mem_correctable_error_count; + u16 mem_uncorrectable_error_count; + + /* + * Cluster information + */ + u8 cluster_permitted; + u8 cluster_active; + + /* + * Additional max data transfer sizes + */ + u16 max_strips_per_io; + + /* + * Controller capabilities structures + */ + struct { + + u32 raid_level_0:1; + u32 raid_level_1:1; + u32 raid_level_5:1; + u32 raid_level_1E:1; + u32 raid_level_6:1; + u32 reserved:27; + + } __attribute__ ((packed)) raid_levels; + + struct { + + u32 rbld_rate:1; + u32 cc_rate:1; + u32 bgi_rate:1; + u32 recon_rate:1; + u32 patrol_rate:1; + u32 alarm_control:1; + u32 cluster_supported:1; + u32 bbu:1; + u32 spanning_allowed:1; + u32 dedicated_hotspares:1; + u32 revertible_hotspares:1; + u32 foreign_config_import:1; + u32 self_diagnostic:1; + u32 mixed_redundancy_arr:1; + u32 global_hot_spares:1; + u32 reserved:17; + + } __attribute__ ((packed)) adapter_operations; + + struct { + + u32 read_policy:1; + u32 write_policy:1; + u32 io_policy:1; + u32 access_policy:1; + u32 disk_cache_policy:1; + u32 reserved:27; + + } __attribute__ ((packed)) ld_operations; + + struct { + + u8 min; + u8 max; + u8 reserved[2]; + + } __attribute__ ((packed)) stripe_sz_ops; + + struct { + + u32 force_online:1; + u32 force_offline:1; + u32 force_rebuild:1; + u32 reserved:29; + + } __attribute__ ((packed)) pd_operations; + + struct { + + u32 ctrl_supports_sas:1; + u32 ctrl_supports_sata:1; + u32 allow_mix_in_encl:1; + u32 allow_mix_in_ld:1; + u32 allow_sata_in_cluster:1; + u32 reserved:27; + + } __attribute__ ((packed)) pd_mix_support; + + /* + * Define ECC single-bit-error bucket information + */ + u8 ecc_bucket_count; + u8 reserved_2[11]; + + /* + * Include the controller properties (changeable items) + */ + struct megasas_ctrl_prop properties; + + /* + * Define FW pkg version (set in envt v'bles on OEM basis) + */ + char package_version[0x60]; + + u8 pad[0x800 - 0x6a0]; + +} __attribute__ ((packed)); + +/* + * =============================== + * MegaRAID SAS driver definitions + * =============================== + */ +#define MEGASAS_MAX_PD_CHANNELS 2 +#define MEGASAS_MAX_LD_CHANNELS 2 +#define MEGASAS_MAX_CHANNELS (MEGASAS_MAX_PD_CHANNELS + \ + MEGASAS_MAX_LD_CHANNELS) +#define MEGASAS_MAX_DEV_PER_CHANNEL 128 +#define MEGASAS_DEFAULT_INIT_ID -1 +#define MEGASAS_MAX_LUN 8 +#define MEGASAS_MAX_LD 64 + +#define MEGASAS_DBG_LVL 1 + +/* + * When SCSI mid-layer calls driver's reset routine, driver waits for + * MEGASAS_RESET_WAIT_TIME seconds for all outstanding IO to complete. Note + * that the driver cannot _actually_ abort or reset pending commands. While + * it is waiting for the commands to complete, it prints a diagnostic message + * every MEGASAS_RESET_NOTICE_INTERVAL seconds + */ +#define MEGASAS_RESET_WAIT_TIME 180 +#define MEGASAS_INTERNAL_CMD_WAIT_TIME 180 +#define MEGASAS_RESET_NOTICE_INTERVAL 5 + +#define MEGASAS_IOCTL_CMD 0 + +/* + * FW reports the maximum of number of commands that it can accept (maximum + * commands that can be outstanding) at any time. The driver must report a + * lower number to the mid layer because it can issue a few internal commands + * itself (E.g, AEN, abort cmd, IOCTLs etc). The number of commands it needs + * is shown below + */ +#define MEGASAS_INT_CMDS 32 + +/* + * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit + * SGLs based on the size of dma_addr_t + */ +#define IS_DMA64 (sizeof(dma_addr_t) == 8) + +#define MFI_OB_INTR_STATUS_MASK 0x00000002 +#define MFI_POLL_TIMEOUT_SECS 10 + +#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000 + +/* +* register set for both 1068 and 1078 controllers +* structure extended for 1078 registers +*/ + +struct megasas_register_set { + u32 reserved_0[4]; /*0000h*/ + + u32 inbound_msg_0; /*0010h*/ + u32 inbound_msg_1; /*0014h*/ + u32 outbound_msg_0; /*0018h*/ + u32 outbound_msg_1; /*001Ch*/ + + u32 inbound_doorbell; /*0020h*/ + u32 inbound_intr_status; /*0024h*/ + u32 inbound_intr_mask; /*0028h*/ + + u32 outbound_doorbell; /*002Ch*/ + u32 outbound_intr_status; /*0030h*/ + u32 outbound_intr_mask; /*0034h*/ + + u32 reserved_1[2]; /*0038h*/ + + u32 inbound_queue_port; /*0040h*/ + u32 outbound_queue_port; /*0044h*/ + + u32 reserved_2[22]; /*0048h*/ + + u32 outbound_doorbell_clear; /*00A0h*/ + + u32 reserved_3[3]; /*00A4h*/ + + u32 outbound_scratch_pad ; /*00B0h*/ + + u32 reserved_4[3]; /*00B4h*/ + + u32 inbound_low_queue_port ; /*00C0h*/ + + u32 inbound_high_queue_port ; /*00C4h*/ + + u32 reserved_5; /*00C8h*/ + u32 index_registers[820]; /*00CCh*/ + +} __attribute__ ((packed)); + +struct megasas_sge32 { + + u32 phys_addr; + u32 length; + +} __attribute__ ((packed)); + +struct megasas_sge64 { + + u64 phys_addr; + u32 length; + +} __attribute__ ((packed)); + +union megasas_sgl { + + struct megasas_sge32 sge32[1]; + struct megasas_sge64 sge64[1]; + +} __attribute__ ((packed)); + +struct megasas_header { + + u8 cmd; /*00h */ + u8 sense_len; /*01h */ + u8 cmd_status; /*02h */ + u8 scsi_status; /*03h */ + + u8 target_id; /*04h */ + u8 lun; /*05h */ + u8 cdb_len; /*06h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + u32 data_xferlen; /*14h */ + +} __attribute__ ((packed)); + +union megasas_sgl_frame { + + struct megasas_sge32 sge32[8]; + struct megasas_sge64 sge64[5]; + +} __attribute__ ((packed)); + +struct megasas_init_frame { + + u8 cmd; /*00h */ + u8 reserved_0; /*01h */ + u8 cmd_status; /*02h */ + + u8 reserved_1; /*03h */ + u32 reserved_2; /*04h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 reserved_3; /*12h */ + u32 data_xfer_len; /*14h */ + + u32 queue_info_new_phys_addr_lo; /*18h */ + u32 queue_info_new_phys_addr_hi; /*1Ch */ + u32 queue_info_old_phys_addr_lo; /*20h */ + u32 queue_info_old_phys_addr_hi; /*24h */ + + u32 reserved_4[6]; /*28h */ + +} __attribute__ ((packed)); + +struct megasas_init_queue_info { + + u32 init_flags; /*00h */ + u32 reply_queue_entries; /*04h */ + + u32 reply_queue_start_phys_addr_lo; /*08h */ + u32 reply_queue_start_phys_addr_hi; /*0Ch */ + u32 producer_index_phys_addr_lo; /*10h */ + u32 producer_index_phys_addr_hi; /*14h */ + u32 consumer_index_phys_addr_lo; /*18h */ + u32 consumer_index_phys_addr_hi; /*1Ch */ + +} __attribute__ ((packed)); + +struct megasas_io_frame { + + u8 cmd; /*00h */ + u8 sense_len; /*01h */ + u8 cmd_status; /*02h */ + u8 scsi_status; /*03h */ + + u8 target_id; /*04h */ + u8 access_byte; /*05h */ + u8 reserved_0; /*06h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + u32 lba_count; /*14h */ + + u32 sense_buf_phys_addr_lo; /*18h */ + u32 sense_buf_phys_addr_hi; /*1Ch */ + + u32 start_lba_lo; /*20h */ + u32 start_lba_hi; /*24h */ + + union megasas_sgl sgl; /*28h */ + +} __attribute__ ((packed)); + +struct megasas_pthru_frame { + + u8 cmd; /*00h */ + u8 sense_len; /*01h */ + u8 cmd_status; /*02h */ + u8 scsi_status; /*03h */ + + u8 target_id; /*04h */ + u8 lun; /*05h */ + u8 cdb_len; /*06h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + u32 data_xfer_len; /*14h */ + + u32 sense_buf_phys_addr_lo; /*18h */ + u32 sense_buf_phys_addr_hi; /*1Ch */ + + u8 cdb[16]; /*20h */ + union megasas_sgl sgl; /*30h */ + +} __attribute__ ((packed)); + +struct megasas_dcmd_frame { + + u8 cmd; /*00h */ + u8 reserved_0; /*01h */ + u8 cmd_status; /*02h */ + u8 reserved_1[4]; /*03h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + + u32 data_xfer_len; /*14h */ + u32 opcode; /*18h */ + + union { /*1Ch */ + u8 b[12]; + u16 s[6]; + u32 w[3]; + } mbox; + + union megasas_sgl sgl; /*28h */ + +} __attribute__ ((packed)); + +struct megasas_abort_frame { + + u8 cmd; /*00h */ + u8 reserved_0; /*01h */ + u8 cmd_status; /*02h */ + + u8 reserved_1; /*03h */ + u32 reserved_2; /*04h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 reserved_3; /*12h */ + u32 reserved_4; /*14h */ + + u32 abort_context; /*18h */ + u32 pad_1; /*1Ch */ + + u32 abort_mfi_phys_addr_lo; /*20h */ + u32 abort_mfi_phys_addr_hi; /*24h */ + + u32 reserved_5[6]; /*28h */ + +} __attribute__ ((packed)); + +struct megasas_smp_frame { + + u8 cmd; /*00h */ + u8 reserved_1; /*01h */ + u8 cmd_status; /*02h */ + u8 connection_status; /*03h */ + + u8 reserved_2[3]; /*04h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + + u32 data_xfer_len; /*14h */ + u64 sas_addr; /*18h */ + + union { + struct megasas_sge32 sge32[2]; /* [0]: resp [1]: req */ + struct megasas_sge64 sge64[2]; /* [0]: resp [1]: req */ + } sgl; + +} __attribute__ ((packed)); + +struct megasas_stp_frame { + + u8 cmd; /*00h */ + u8 reserved_1; /*01h */ + u8 cmd_status; /*02h */ + u8 reserved_2; /*03h */ + + u8 target_id; /*04h */ + u8 reserved_3[2]; /*05h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + + u32 data_xfer_len; /*14h */ + + u16 fis[10]; /*18h */ + u32 stp_flags; + + union { + struct megasas_sge32 sge32[2]; /* [0]: resp [1]: data */ + struct megasas_sge64 sge64[2]; /* [0]: resp [1]: data */ + } sgl; + +} __attribute__ ((packed)); + +union megasas_frame { + + struct megasas_header hdr; + struct megasas_init_frame init; + struct megasas_io_frame io; + struct megasas_pthru_frame pthru; + struct megasas_dcmd_frame dcmd; + struct megasas_abort_frame abort; + struct megasas_smp_frame smp; + struct megasas_stp_frame stp; + + u8 raw_bytes[64]; +}; + +struct megasas_cmd; + +union megasas_evt_class_locale { + + struct { + u16 locale; + u8 reserved; + s8 class; + } __attribute__ ((packed)) members; + + u32 word; + +} __attribute__ ((packed)); + +struct megasas_evt_log_info { + u32 newest_seq_num; + u32 oldest_seq_num; + u32 clear_seq_num; + u32 shutdown_seq_num; + u32 boot_seq_num; + +} __attribute__ ((packed)); + +struct megasas_progress { + + u16 progress; + u16 elapsed_seconds; + +} __attribute__ ((packed)); + +struct megasas_evtarg_ld { + + u16 target_id; + u8 ld_index; + u8 reserved; + +} __attribute__ ((packed)); + +struct megasas_evtarg_pd { + u16 device_id; + u8 encl_index; + u8 slot_number; + +} __attribute__ ((packed)); + +struct megasas_evt_detail { + + u32 seq_num; + u32 time_stamp; + u32 code; + union megasas_evt_class_locale cl; + u8 arg_type; + u8 reserved1[15]; + + union { + struct { + struct megasas_evtarg_pd pd; + u8 cdb_length; + u8 sense_length; + u8 reserved[2]; + u8 cdb[16]; + u8 sense[64]; + } __attribute__ ((packed)) cdbSense; + + struct megasas_evtarg_ld ld; + + struct { + struct megasas_evtarg_ld ld; + u64 count; + } __attribute__ ((packed)) ld_count; + + struct { + u64 lba; + struct megasas_evtarg_ld ld; + } __attribute__ ((packed)) ld_lba; + + struct { + struct megasas_evtarg_ld ld; + u32 prevOwner; + u32 newOwner; + } __attribute__ ((packed)) ld_owner; + + struct { + u64 ld_lba; + u64 pd_lba; + struct megasas_evtarg_ld ld; + struct megasas_evtarg_pd pd; + } __attribute__ ((packed)) ld_lba_pd_lba; + + struct { + struct megasas_evtarg_ld ld; + struct megasas_progress prog; + } __attribute__ ((packed)) ld_prog; + + struct { + struct megasas_evtarg_ld ld; + u32 prev_state; + u32 new_state; + } __attribute__ ((packed)) ld_state; + + struct { + u64 strip; + struct megasas_evtarg_ld ld; + } __attribute__ ((packed)) ld_strip; + + struct megasas_evtarg_pd pd; + + struct { + struct megasas_evtarg_pd pd; + u32 err; + } __attribute__ ((packed)) pd_err; + + struct { + u64 lba; + struct megasas_evtarg_pd pd; + } __attribute__ ((packed)) pd_lba; + + struct { + u64 lba; + struct megasas_evtarg_pd pd; + struct megasas_evtarg_ld ld; + } __attribute__ ((packed)) pd_lba_ld; + + struct { + struct megasas_evtarg_pd pd; + struct megasas_progress prog; + } __attribute__ ((packed)) pd_prog; + + struct { + struct megasas_evtarg_pd pd; + u32 prevState; + u32 newState; + } __attribute__ ((packed)) pd_state; + + struct { + u16 vendorId; + u16 deviceId; + u16 subVendorId; + u16 subDeviceId; + } __attribute__ ((packed)) pci; + + u32 rate; + char str[96]; + + struct { + u32 rtc; + u32 elapsedSeconds; + } __attribute__ ((packed)) time; + + struct { + u32 ecar; + u32 elog; + char str[64]; + } __attribute__ ((packed)) ecc; + + u8 b[96]; + u16 s[48]; + u32 w[24]; + u64 d[12]; + } args; + + char description[128]; + +} __attribute__ ((packed)); + + struct megasas_instance_template { + void (*fire_cmd)(dma_addr_t ,u32 ,struct megasas_register_set __iomem *); + + void (*enable_intr)(struct megasas_register_set __iomem *) ; + void (*disable_intr)(struct megasas_register_set __iomem *); + + int (*clear_intr)(struct megasas_register_set __iomem *); + + u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *); + }; + +struct megasas_instance { + + u32 *producer; + dma_addr_t producer_h; + u32 *consumer; + dma_addr_t consumer_h; + + u32 *reply_queue; + dma_addr_t reply_queue_h; + + unsigned long base_addr; + struct megasas_register_set __iomem *reg_set; + + s8 init_id; + u8 reserved[3]; + + u16 max_num_sge; + u16 max_fw_cmds; + u32 max_sectors_per_req; + + struct megasas_cmd **cmd_list; + struct list_head cmd_pool; + spinlock_t cmd_pool_lock; + struct dma_pool *frame_dma_pool; + struct dma_pool *sense_dma_pool; + + struct megasas_evt_detail *evt_detail; + dma_addr_t evt_detail_h; + struct megasas_cmd *aen_cmd; + struct semaphore aen_mutex; + struct semaphore ioctl_sem; + + struct Scsi_Host *host; + + wait_queue_head_t int_cmd_wait_q; + wait_queue_head_t abort_cmd_wait_q; + + struct pci_dev *pdev; + u32 unique_id; + + atomic_t fw_outstanding; + u32 hw_crit_error; + + struct megasas_instance_template *instancet; + struct tasklet_struct isr_tasklet; +}; + +#define MEGASAS_IS_LOGICAL(scp) \ + (scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1 + +#define MEGASAS_DEV_INDEX(inst, scp) \ + ((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \ + scp->device->id + +struct megasas_cmd { + + union megasas_frame *frame; + dma_addr_t frame_phys_addr; + u8 *sense; + dma_addr_t sense_phys_addr; + + u32 index; + u8 sync_cmd; + u8 cmd_status; + u16 abort_aen; + + struct list_head list; + struct scsi_cmnd *scmd; + struct megasas_instance *instance; + u32 frame_count; +}; + +#define MAX_MGMT_ADAPTERS 1024 +#define MAX_IOCTL_SGE 16 + +struct megasas_iocpacket { + + u16 host_no; + u16 __pad1; + u32 sgl_off; + u32 sge_count; + u32 sense_off; + u32 sense_len; + union { + u8 raw[128]; + struct megasas_header hdr; + } frame; + + struct iovec sgl[MAX_IOCTL_SGE]; + +} __attribute__ ((packed)); + +struct megasas_aen { + u16 host_no; + u16 __pad1; + u32 seq_num; + u32 class_locale_word; +} __attribute__ ((packed)); + +#ifdef CONFIG_COMPAT +struct compat_megasas_iocpacket { + u16 host_no; + u16 __pad1; + u32 sgl_off; + u32 sge_count; + u32 sense_off; + u32 sense_len; + union { + u8 raw[128]; + struct megasas_header hdr; + } frame; + struct compat_iovec sgl[MAX_IOCTL_SGE]; +} __attribute__ ((packed)); + +#define MEGASAS_IOC_FIRMWARE32 _IOWR('M', 1, struct compat_megasas_iocpacket) +#endif + +#define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct megasas_iocpacket) +#define MEGASAS_IOC_GET_AEN _IOW('M', 3, struct megasas_aen) + +struct megasas_mgmt_info { + + u16 count; + struct megasas_instance *instance[MAX_MGMT_ADAPTERS]; + int max_index; +}; + +#endif /*LSI_MEGARAID_SAS_H */ diff --git a/src/logpage.c b/src/logpage.c new file mode 100644 index 0000000..39a7ff1 --- /dev/null +++ b/src/logpage.c @@ -0,0 +1,420 @@ +/* + * Parse and print SCSI log sense pages. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include "megaioctl.h" +#include "logpage.h" +#include "ntrim.h" +#include "dumpbytes.h" + +#include +#include +#include + + +static char *logPageType[] = { + /* 0 */ "supported log pages", + /* 1 */ "buffer over-run/under-run", + /* 2 */ "write error counter", + /* 3 */ "read error counter", + /* 4 */ "read reverse error counter", + /* 5 */ "verify error counter", + /* 6 */ "non-medium error", + /* 7 */ "last n error events", + /* 8 */ "format status", + /* 9 */ NULL, + /* a */ NULL, + /* b */ "last n deferred errors os asynchronous events", + /* c */ "sequential-access device", + /* d */ "temperature", + /* e */ "start-stop cycle counter", + /* f */ "application client", + /* 10 */ "self-test results", + /* 11 */ "DTD status", + /* 12 */ "TapeAlert response", + /* 13 */ "requested recover", + /* 14 */ "device statistics", + /* 15 */ NULL, + /* 16 */ NULL, + /* 17 */ "non-volatile cache", + /* 18 */ "protocol specific port", + /* 19 */ NULL, + /* 1a */ NULL, + /* 1b */ NULL, + /* 1c */ NULL, + /* 1d */ NULL, + /* 1e */ NULL, + /* 1f */ NULL, + /* 20 */ NULL, + /* 21 */ NULL, + /* 22 */ NULL, + /* 23 */ NULL, + /* 24 */ NULL, + /* 25 */ NULL, + /* 26 */ NULL, + /* 27 */ NULL, + /* 28 */ NULL, + /* 29 */ NULL, + /* 2a */ NULL, + /* 2b */ NULL, + /* 2c */ NULL, + /* 2d */ NULL, + /* 2e */ "TapeAlert", + /* 2f */ "informational exceptions", + /* 30 */ "vendor specific", + /* 31 */ "vendor specific", + /* 32 */ "vendor specific", + /* 33 */ "vendor specific", + /* 34 */ "vendor specific", + /* 35 */ "vendor specific", + /* 36 */ "vendor specific", + /* 37 */ "vendor specific", + /* 38 */ "vendor specific", + /* 39 */ "vendor specific", + /* 3a */ "vendor specific", + /* 3b */ "vendor specific", + /* 3c */ "vendor specific", + /* 3d */ "vendor specific", + /* 3e */ "vendor specific", + /* 3f */ NULL, +}; + + +static char *friendlySize (uint64_t b, char *unit) +{ + static char *suffix[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi", }; + int k; + static char bytes[128]; + + for (k = 0; (b >= 1024) && (k < sizeof (suffix) / sizeof (suffix[0]) - 1); ++k, b /= 1024) + ; + snprintf (bytes, sizeof bytes, "%3llu%s%s", b, suffix[k], unit); + return bytes; +} + + +static uint32_t blocksToGB (uint32_t blocks) +{ + return (long) (((uint64_t) blocks) * 512 / 1000000000); +} + + +static uint32_t blocksToGiB (uint32_t blocks) +{ + return blocks / 2 / 1024 / 1024; +} + + +static uint64_t extractInt64 (void *u, size_t len) +{ + uint64_t x; + uint8_t *v; + + for (x = 0, v = u; len > 0; --len, ++v) + x = (x << 8) + *v; + return x; +} + + +int parseLogPage (void *log, size_t len, struct logData *x) +{ + struct logPageHeader *h = log; + void *u = log + sizeof (*h); + struct logParameterHeader *p; + size_t pageLen; + + memset (x, 0, sizeof (*x)); + + if (len < sizeof (*h)) + return -1; + pageLen = ntohs (h->length) + sizeof (*h); + if (len > pageLen) + len = pageLen; + len -= sizeof (*h); + + x->h = *h; + x->h.length = pageLen; + + if (h->page_code == 0) + { + for ( ; len > 0; --len, ++u) + { + uint8_t code = *((unsigned char *) u); + + if (code < sizeof (x->u.supported.page) / sizeof (x->u.supported.page[0])) + x->u.supported.page[code] = 1; + } + return 0; + } + + while (len >= sizeof (*p)) + { + uint16_t code; + uint64_t e; + struct selfTestLogParameter *t; + + p = u; + if (p->length + sizeof (*p) > len) + break; + len -= sizeof (*p); + u += sizeof (*p); + + code = ntohs (p->parameter_code); + switch (h->page_code) + { + case 0x02: + case 0x03: + case 0x04: + case 0x05: + e = extractInt64 (u, p->length); + switch (code) + { + case 0x0000: x->u.error.corrected = e; break; + case 0x0001: x->u.error.delayed = e; break; + case 0x0002: x->u.error.reread = e; break; + case 0x0003: x->u.error.total_corrected = e; break; + case 0x0004: x->u.error.total_algorithm = e; break; + case 0x0005: x->u.error.total_bytes = e; break; + case 0x0006: x->u.error.total_uncorrected = e; if (e) x->problem = 1; break; + default: break; + } + break; + case 0x0d: + switch (code) + { + case 0x0000: x->u.temperature.current = ((uint8_t *) u)[1]; break; + case 0x0001: x->u.temperature.reference = ((uint8_t *) u)[1]; break; + default: break; + } + break; + case 0x0e: + switch (code) + { + case 0x0001: + strncpy (x->u.startstop.manufacture_year, u, sizeof (x->u.startstop.manufacture_year) - 1); + x->u.startstop.manufacture_year[sizeof (x->u.startstop.manufacture_year) - 1] = '\0'; + ntrim (x->u.startstop.manufacture_year); + strncpy (x->u.startstop.manufacture_week, u + 4, sizeof (x->u.startstop.manufacture_week) - 1); + x->u.startstop.manufacture_week[sizeof (x->u.startstop.manufacture_week) - 1] = '\0'; + ntrim (x->u.startstop.manufacture_week); + break; + case 0x0002: + strncpy (x->u.startstop.accounting_year, u, sizeof (x->u.startstop.accounting_year) - 1); + x->u.startstop.accounting_year[sizeof (x->u.startstop.accounting_year) - 1] = '\0'; + ntrim (x->u.startstop.accounting_year); + strncpy (x->u.startstop.accounting_week, u + 4, sizeof (x->u.startstop.accounting_week) - 1); + x->u.startstop.accounting_week[sizeof (x->u.startstop.accounting_week) - 1] = '\0'; + ntrim (x->u.startstop.accounting_week); + break; + case 0x0003: + x->u.startstop.recommended_starts = ntohl (*((uint32_t *) u)); + break; + case 0x0004: + x->u.startstop.accumulated_starts = ntohl (*((uint32_t *) u)); + break; + default: + break; + } + break; + case 0x10: + if ((code < 1) || (code > sizeof (x->u.selftest.entry) / sizeof (x->u.selftest.entry[0]))) + break; + if (p->length != sizeof (x->u.selftest.entry[0]) - sizeof (*p)) + break; + --code; + t = &x->u.selftest.entry[code]; + *t = *((struct selfTestLogParameter *) p); + t->h.parameter_code = code; + t->timestamp = ntohs (t->timestamp); + t->lba = extractInt64 (&t->lba, sizeof (t->lba)); + if (t->self_test_code || t->self_test_results || t->timestamp || t->number || t->lba) + if ((t->self_test_results >= 4) && (t->self_test_results <= 7)) + x->problem = 1; + break; + } + + len -= p->length; + u += p->length; + } + + /* flag any other problems */ + switch (h->page_code) + { + case 0x0d: + if (x->u.temperature.reference && (x->u.temperature.reference != 0xff) && (x->u.temperature.current >= x->u.temperature.reference)) + x->problem = 1; + break; + } + + return 0; +} + + +void dumpLogPage (FILE *f, struct logData *x, void *log, size_t len, int verbosity) +{ + struct logPageHeader *h = log; + void *u = log + sizeof (*h); + struct logParameterHeader *p; + size_t pageLen; + int k; + + switch (x->h.page_code) + { + case 0x00: + fprintf (f, " %s:", logPageType[h->page_code]); + if (verbosity > 1) + fprintf (f, "\n"); + for (k = 0; k < sizeof (x->u.supported.page) / sizeof (x->u.supported.page[0]); ++k) + { + if (!(x->u.supported.page[k])) + continue; + + if (verbosity > 1) + { + char *name; + if (logPageType[k]) + name = logPageType[k]; + else + name = "unknown log page"; + fprintf (f, " %02x %s\n", k, name); + } + else + fprintf (f, " %02x", k); + } + if (!(verbosity > 1)) + fprintf (f, "\n"); + break; + case 0x02: + case 0x03: + case 0x04: + case 0x05: + switch (x->h.page_code) + { + case 0x02: fprintf (f, " write errors:"); break; + case 0x03: fprintf (f, " read errors:"); break; + case 0x04: fprintf (f, " read/rev errors:"); break; + case 0x05: fprintf (f, " verify errors:"); break; + } + fprintf (f, " corr:%-6s", friendlySize (x->u.error.corrected, "")); + fprintf (f, " delay:%-6s", friendlySize (x->u.error.delayed, "")); + switch (x->h.page_code) + { + case 0x02: fprintf (f, " rewrit:%-6s", friendlySize (x->u.error.reread, "")); break; + case 0x03: fprintf (f, " reread:%-6s", friendlySize (x->u.error.reread, "")); break; + case 0x04: fprintf (f, " reread:%-6s", friendlySize (x->u.error.reread, "")); break; + case 0x05: fprintf (f, " revrfy:%-6s", friendlySize (x->u.error.reread, "")); break; + } + fprintf (f, " tot/corr:%-6s", friendlySize (x->u.error.total_corrected, "")); + if (verbosity > 1) + fprintf (f, " tot/alg:%-6s", friendlySize (x->u.error.total_algorithm, "")); + if (verbosity > 1) + fprintf (f, " tot/bytes:%-6s", friendlySize (x->u.error.total_bytes, "B")); + fprintf (f, " tot/uncorr:%-6s", friendlySize (x->u.error.total_uncorrected, "")); + fprintf (f, "\n"); + break; + case 0x0d: + fprintf (f, " temperature: current:%uC threshold:%uC%s\n", x->u.temperature.current, x->u.temperature.reference, x->problem ? " warning:temperature threshold exceeded" : ""); + break; + case 0x0e: + fprintf (f, " "); + if (strlen (x->u.startstop.manufacture_year) && strlen (x->u.startstop.manufacture_week)) + fprintf (f, " manufactured:%s/%s", x->u.startstop.manufacture_year, x->u.startstop.manufacture_week); + if (strlen (x->u.startstop.accounting_year) && strlen (x->u.startstop.accounting_week)) + fprintf (f, " accounting:%s/%s", x->u.startstop.accounting_year, x->u.startstop.accounting_week); + fprintf (f, " starts:%d/%d", x->u.startstop.accumulated_starts, x->u.startstop.recommended_starts); + fprintf (f, "\n"); + break; + case 0x10: + for (k = 0; k < sizeof (x->u.selftest.entry) / sizeof (x->u.selftest.entry[0]); ++k) + { + struct selfTestLogParameter *t = &x->u.selftest.entry[k]; + + if (t->self_test_code || t->self_test_results || t->timestamp || t->number || t->lba) + { + char *test; + char *result; + int notice = 0; + + switch (t->self_test_code) + { + case SCSI_SELFTEST_DEFAULT: test = "default"; break; + case SCSI_SELFTEST_BACKGROUND_SHORT: test = "bg short"; break; + case SCSI_SELFTEST_BACKGROUND_LONG: test = "bg long"; break; + case SCSI_SELFTEST_BACKGROUND_ABORT: test = "bg aborted"; break; + case SCSI_SELFTEST_FOREGROUND_SHORT: test = "fg short"; break; + case SCSI_SELFTEST_FOREGROUND_LONG: test = "fg long"; break; + default: test = "unknown"; break; + } + switch (t->self_test_results) + { + case 0x0: result = "completed without error"; notice = 1; break; + case 0x1: result = "aborted via send diagnostic"; notice = 1; break; + case 0x2: result = "aborted via other method"; notice = 1; break; + case 0x3: result = "unable to complete"; notice = 1; break; + case 0x4: result = "failed in unknown segment"; notice = 0; break; + case 0x5: result = "failed in segment 1"; notice = 0; break; + case 0x6: result = "failed in segment 2"; notice = 0; break; + case 0x7: result = "failed in other segment"; notice = 0; break; + case 0xf: result = "in progress"; notice = 0; break; + default: result = "unknown result"; notice = 0; break; + } + if (verbosity > notice) + fprintf (f, " %2d: timestamp %4ud%02uh: %10s %-30s seg:%u lba:%-8lld sk:%u asc:%u ascq:%u vs:%u\n", k, t->timestamp / 24, t->timestamp % 24, test, result, t->number, t->lba, t->sense_key, t->additional_sense_code, t->additional_sense_code_qualifier, t->vendor_specific); + } + } + break; + default: + break; + } + + if (!(verbosity > 2)) + return; + + if (len < sizeof (*h)) + return; + pageLen = ntohs (h->length) + sizeof (*h); + if (len > pageLen) + len = pageLen; + len -= sizeof (*h); + + fprintf (f, " log page %02x, length %u%s\n", h->page_code, ntohs (h->length), len < pageLen - sizeof (*h) ? " warning: truncated" : ""); + + while (len >= sizeof (*p)) + { + uint16_t code; + + p = u; + if (p->length + sizeof (*p) > len) + break; + len -= sizeof (*p); + u += sizeof (*p); + + code = ntohs (p->parameter_code); + fprintf (f, " param %04x, du %u, ds %u, tsd %u, etc %u, tmc %u, lbin %u, lp %u, length %u\n", code, p->du, p->ds, p->tsd, p->etc, p->tmc, p->lbin, p->lp, p->length); + dumpbytes (f, u, p->length, u, "param"); + + len -= p->length; + u += p->length; + } +} + + diff --git a/src/logpage.h b/src/logpage.h new file mode 100644 index 0000000..6b2f6b0 --- /dev/null +++ b/src/logpage.h @@ -0,0 +1,148 @@ +#ifndef _LOGPAGE_H +#define _LOGPAGE_H +/* + * Definitions for SCSI log sense page parsing and printing. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include +#include + +#include + + +struct logPageHeader +{ + uint8_t page_code; + uint8_t rsvd0; + uint16_t length; +} __attribute__ ((packed)); + +struct logParameterHeader +{ + uint16_t parameter_code; +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder (thanks, Schily) */ + uint8_t lp:1; + uint8_t lbin:1; + uint8_t tmc:2; + uint8_t etc:1; + uint8_t tsd:1; + uint8_t ds:1; + uint8_t du:1; +#else /* Motorola byteorder */ + uint8_t du:1; + uint8_t ds:1; + uint8_t tsd:1; + uint8_t etc:1; + uint8_t tmc:2; + uint8_t lbin:1; + uint8_t lp:1; +#endif + uint8_t length; +}; + +#define LOG_PAGE_MAX 0x40 + +struct supportedLogsPage +{ + uint8_t page[LOG_PAGE_MAX]; +}; + +struct errorLogPage +{ + uint64_t corrected; + uint64_t delayed; + uint64_t reread; + uint64_t total_corrected; + uint64_t total_algorithm; + uint64_t total_bytes; + uint64_t total_uncorrected; +}; + +struct selfTestLogParameter +{ + struct logParameterHeader h; +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder (thanks, Schily) */ + uint8_t self_test_results:4; + uint8_t rsvd0:1; + uint8_t self_test_code:3; +#else /* Motorola byteorder */ + uint8_t self_test_code:3; + uint8_t rsvd0:1; + uint8_t self_test_results:4; +#endif + uint8_t number; + uint16_t timestamp; + uint64_t lba; +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder (thanks, Schily) */ + uint8_t sense_key:4; + uint8_t rsvd1:4; +#else /* Motorola byteorder */ + uint8_t rsvd1:4; + uint8_t sense_key:4; +#endif + uint8_t additional_sense_code; + uint8_t additional_sense_code_qualifier; + uint8_t vendor_specific; +}; + +struct selfTestLogPage +{ + struct selfTestLogParameter entry[20]; +}; + +struct startStopCycleCounterLogPage +{ + char manufacture_year[5]; + char manufacture_week[3]; + char accounting_year[5]; + char accounting_week[3]; + uint32_t recommended_starts; + uint32_t accumulated_starts; +}; + +struct temperatureLogPage +{ + uint8_t current; + uint8_t reference; +}; + +struct logData +{ + struct logPageHeader h; + uint8_t problem; + uint8_t pad[3]; + union + { + struct supportedLogsPage supported; + struct errorLogPage error; + struct selfTestLogPage selftest; + struct startStopCycleCounterLogPage startstop; + struct temperatureLogPage temperature; + } u; +} __attribute__ ((packed)); + + +extern int parseLogPage (void *log, size_t len, struct logData *x); +extern void dumpLogPage (FILE *f, struct logData *x, void *log, size_t len, int verbosity); + + +#endif diff --git a/src/mega.h b/src/mega.h new file mode 100644 index 0000000..51889b9 --- /dev/null +++ b/src/mega.h @@ -0,0 +1,585 @@ +#ifndef _MEGA_H +#define _MEGA_H +/* + * Definitions of data structures used by the adapter and by our + * high-level interface. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include "logpage.h" + +#include +#include +#include + + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#define BITS_PER_LONG 32 + +#include +#ifdef NEED_UINT8_T + +typedef __u8 uint8_t; +typedef __u16 uint16_t; +typedef __u32 uint32_t; +typedef __u64 uint64_t; + +#endif + +/* DMA addresses come in generic and 64-bit flavours. */ + +#ifdef CONFIG_HIGHMEM +typedef u64 dma_addr_t; +#else +typedef u32 dma_addr_t; +#endif +typedef u64 dma64_addr_t; + +/* Hacks to get kernel module headers to compile. We're not using any data structures where these matter. */ +typedef struct +{ + volatile unsigned int lock; +} spinlock_t; +struct semaphore +{ + int foo; +}; + +typedef struct { volatile int counter; } atomic_t; +struct tasklet_struct +{ + struct tasklet_struct *next; + unsigned long state; + atomic_t count; + void (*func)(unsigned long); + unsigned long data; +}; + +#define __iomem + +#define __user +#define wait_queue_head_t void * +/* typedef void wait_queue_head_t; */ + +struct list_head { + struct list_head *next, *prev; +}; + + +/* Okay, should be able to include module headers now, hopefully. */ +#include "megaraid/mbox_defs.h" +#include "megaraid/megaraid_ioctl.h" +#include "megaraid/megaraid_sas.h" + +#define MAX_CONTROLLERS 32 + +#define M_RD_IOCTL_CMD 0x80 +#define M_RD_IOCTL_CMD_NEW 0x81 +#define M_RD_DRIVER_IOCTL_INTERFACE 0x82 + + +#define SCSI_SELFTEST_DEFAULT 0x00 +#define SCSI_SELFTEST_BACKGROUND_SHORT 0x01 +#define SCSI_SELFTEST_BACKGROUND_LONG 0x02 +#define SCSI_SELFTEST_BACKGROUND_ABORT 0x04 +#define SCSI_SELFTEST_FOREGROUND_SHORT 0x05 +#define SCSI_SELFTEST_FOREGROUND_LONG 0x06 + + +/* megaraid2 header file gets this wrong. */ +typedef struct { + uint8_t max_commands; + uint8_t rebuild_rate; + uint8_t max_targ_per_chan; + uint8_t nchannels; + uint8_t fw_version[4]; + uint16_t age_of_flash; + uint8_t chip_set_value; + uint8_t dram_size; + uint8_t cache_flush_interval; + uint8_t bios_version[4]; + uint8_t board_type; + uint8_t sense_alert; + uint8_t write_config_count; + uint8_t drive_inserted_count; + uint8_t inserted_drive; + uint8_t battery_status; + uint8_t dec_fault_bus_info; +} __attribute__ ((packed)) mraid_adapinfo1_t; + +typedef struct { + mraid_adapinfo1_t adapter_info; + mraid_ldrv_info_t logdrv_info; + mraid_pdrv_info_t pdrv_info; +} __attribute__ ((packed)) mraid_inquiry1_t; + +typedef struct { + mraid_inquiry1_t raid_inq; + uint16_t phys_drv_format[MAX_MBOX_CHANNELS]; + uint8_t stack_attn; + uint8_t modem_status; + uint8_t rsvd[2]; +} __attribute__ ((packed)) mraid_extinq1_t; + + +/* Structures we've figured out over many hours of staring at hex data. */ + +struct mega_physical_drive_error_info +{ + uint8_t media; + uint8_t other; +} __attribute__ ((packed)); + + +struct mega_predictive_map +{ + uint8_t map[FC_MAX_PHYSICAL_DEVICES / 8]; +} __attribute__ ((packed)); + + +struct mega_device_entry_sas { + uint16_t device_id; + uint16_t enclosure; + uint8_t value_1; /* ? 1, 2 enclosure number + 1? backend port number? */ + uint8_t slot; + uint8_t type; /* INQ_DASD, INQ_ENCL */ + uint8_t port; /* 1 << connected port number */ + uint64_t sas_address[2]; +} __attribute__ ((packed)); + +/* opcode 0x02010000 */ +struct mega_device_list_sas { + uint32_t length; + uint16_t num_devices; + uint16_t rsvd0; + struct mega_device_entry_sas device[32]; /* actually any number */ +} __attribute__ ((packed)); + + +struct mega_array_header_sas { + uint32_t length; + uint16_t num_span_defs; + uint16_t span_def_size; /* 0x0120 */ + uint16_t num_disk_defs; + uint16_t disk_def_size; /* 0x0100 */ + uint16_t num_hot_spares; + uint16_t value_0028; /* ? 0x0028 */ + uint32_t pad0[4]; +} __attribute__ ((packed)); + +struct mega_array_span_disk_sas +{ + uint16_t device_id; /* 0xffff if device missing */ + uint16_t sequence; /* ? 0x0002, 0x0004, 0x0006... as disks are created */ + uint8_t flag_0:1; + uint8_t hotspare:1; + uint8_t rebuild:1; + uint8_t online:1; + uint8_t present:1; + uint8_t flag_1; + uint8_t enclosure; + uint8_t slot; +} __attribute__ ((packed)); + +struct mega_array_span_def_sas +{ + uint64_t sectors_per_disk; + uint16_t span_size; /* number of disks in span */ + uint16_t span_index; /* 0, 1, 2... */ + uint32_t value_1; /* ? 0 */ + uint32_t pad0[4]; + struct mega_array_span_disk_sas disk[32]; /* real number is (config.span_def_size - offset .disks) / sizeof span_entry */ +} __attribute__ ((packed)); + +struct mega_array_disk_entry_sas +{ + uint64_t offset; /* offset in sectors of this vd */ + uint64_t sectors_per_disk; /* sectors used for this vd on each disk */ + uint16_t span_index; /* number of this span */ + uint16_t pad2; /* ? 0 */ + uint32_t pad3; /* ? 0 */ +} __attribute__ ((packed)); + +#define MEGA_SAS_LD_OFFLINE 0 +#define MEGA_SAS_LD_PARTIALLY_DEGRADED 1 +#define MEGA_SAS_LD_DEGRADED 2 +#define MEGA_SAS_LD_OPTIMAL 3 + +struct mega_array_disk_def_sas { + uint16_t disk_index; /* 0, 1, 2... */ + uint16_t sequence; /* ? 0x0004, 0x0003 */ + char name[16]; /* null-terminated, max 15 chars */ + uint32_t flags; /* ? 0x01000001, 0x00000000 */ + uint32_t pad0[2]; /* ? 0 */ + uint8_t raid_level; /* 0, 1, 5 */ + uint8_t raid_level_secondary; /* ? 3 for raid 5 with 4 spans, 0 for raid1 with 1 span */ + uint8_t raid_level_qualifier; /* ? 3 for raid 5 with 4 spans, 0 for raid1 with 1 span */ + uint8_t stripe_size; /* (2 << this) sectors per stripe; 4 == 8K, 5 == 16K, etc. */ + uint8_t disks_per_span; + uint8_t num_spans; + uint16_t state; /* ? 0 == offline, 1 == partially degraded, 2 == degraded, 3 == optimal */ + uint32_t value_4; /* ? 0x00000001, 0x00000000 */ + uint32_t pad1[5]; /* ? 0 */ + struct mega_array_disk_entry_sas span[8]; /* real number is (config.disk_def_size - offset .spans) / sizeof disk_entry */ +} __attribute__ ((packed)); + +struct mega_array_hotspare_def_sas +{ + uint16_t device_id; + uint16_t sequence; /* ? 0x001c, 0x001e, 0x0020 */ + uint32_t flags; /* ? 0x00000000 for global, 0x01000001 for dedicated */ + uint32_t array; /* dedicated array index */ + uint32_t pad0[7]; /* ? 0 */ +} __attribute__ ((packed)); + +/* opcode 0x04010000: array config is { header span_def* disk_def* hotspare_def* } */ +struct mega_array_config_sas +{ + struct mega_array_header_sas *header; + struct mega_array_span_def_sas *span; + struct mega_array_disk_def_sas *disk; + struct mega_array_hotspare_def_sas *hotspare; +}; + +/* opcode 0x05010000 */ +#define MEGA_BATTERY_TYPE_NONE 0 +#define MEGA_BATTERY_TYPE_ITBBU 1 +#define MEGA_BATTERY_TYPE_TBBU 2 + +struct mega_battery_state_sas +{ + uint8_t type; /* see above */ + uint8_t foo; /* ? */ + uint16_t voltage; /* millivolts */ + uint16_t current; /* milliamps */ + uint16_t temperature; /* celsius */ + uint32_t firmware_status; + uint32_t pad0[5]; /* ? 0 */ + + uint8_t pad1:4; + + uint8_t fully_discharged:1; + uint8_t fully_charged:1; + uint8_t discharging:1; + uint8_t initialized:1; + + uint8_t remaining_time_alarm:1; + uint8_t remaining_capacity_alarm:1; + uint8_t pad2:1; + uint8_t discharge_terminated:1; + + uint8_t over_temperature:1; + uint8_t pad3:1; + uint8_t charging_terminated:1; + uint8_t over_charged:1; + + uint16_t charge; /* percentage */ + uint16_t charger_status; /* charger status 0 == off, 1 == complete, 2 == in progress */ + uint16_t capacity_remaining; /* milliamp-hours */ + uint16_t capacity_full; /* milliamp-hours */ + uint16_t health; /* state of health 0 == no, * == good */ + uint32_t pad9[5]; /* ? 0 */ +} __attribute__ ((packed)); + +/* opcode 0x05020000 */ +struct mega_battery_capacity_sas +{ + uint16_t charge_relative; /* percentage */ + uint16_t charge_absolute; /* percentage */ + uint16_t capacity_remaining; /* milliamp-hours */ + uint16_t capacity_full; /* milliamp-hours */ + uint16_t time_empty_run; /* minutes */ + uint16_t time_empty_average; /* minutes */ + uint16_t time_full_average; /* minutes */ + uint16_t cycles; + uint16_t error_max; /* percentage */ + uint16_t alarm_capacity; /* milliamp-hours */ + uint16_t alarm_time; /* minutes */ + uint16_t pad0; /* ? 0 */ + uint32_t pad1[6]; /* ? 0 */ +} __attribute__ ((packed)); + +/* opcode 0x05030000 */ +struct mega_battery_design_sas +{ + uint32_t manufacture_date; /* weird encoding: 0xfae87 == 2007/04/07, 0xfaebf == 2007/05/31 */ + uint16_t design_capacity; /* milliamp-hours */ + uint16_t design_voltage; /* millivolts */ + uint16_t specification_info; + uint16_t serial_number; + uint16_t pack_stat_configuration; + char manufacturer[12]; + char device_name[8]; + char device_chemistry[5]; + char device_vendor[5]; + uint32_t pad0[5]; /* ? 0 */ +} __attribute__ ((packed)); + +/* opcode 0x05050100 */ +struct mega_battery_properties_sas +{ + uint32_t device_learn_period; /* seconds */ + uint32_t next_learn_time; /* seconds */ + uint32_t learn_delay_interval; /* ? hours */ + uint32_t auto_learn_mode; /* ? */ + uint32_t pad0[4]; /* ? 0 */ +} __attribute__ ((packed)); + +struct mega_battery_info_sas +{ + struct mega_battery_state_sas state; + struct mega_battery_capacity_sas capacity; + struct mega_battery_design_sas design; + struct mega_battery_properties_sas properties; +}; + + +/* opcode 0x02020000 */ +struct mega_physical_disk_info_sas +{ + uint16_t device_id; + uint16_t sequence; + union + { + struct scsi_inquiry inq; + uint8_t buf[96]; + } inquiry; + uint16_t value_x; /* ? 0x8300 */ /* 0x064 */ + uint16_t value_y; /* ? 0x4800, 0x2000 */ + struct + { + uint8_t value[60]; + } mystery_struct; /* 0x0a4 */ + uint16_t value_0; /* ? 0x0000 */ + uint8_t port; /* 1 << connected port number */ + uint8_t value_1; /* ? 0 */ + uint32_t media_errors; + uint32_t other_errors; + uint32_t predictive_failures; + uint32_t predictive_failure_event_sequence; + uint8_t failure:1; + uint8_t hotspare:1; + uint8_t rebuild:1; + uint8_t online:1; + uint8_t configured:1; + uint8_t flags_0:3; + uint8_t flags_1; + uint16_t value_4; /* ? 0x0000 */ + uint32_t value_5; /* ? 0x00002002, 0x00003003, 0x00003009 */ + uint32_t sas_address_count; /* number of sas addresses */ + uint32_t pad_sas_addr; /* ? 0x00000000 */ + uint64_t sas_address[4]; + uint64_t raw_size; /* sectors; MegaCli only sees 32 bits */ /* 0x0e8 */ + uint64_t noncoerced_size; /* sectors; MegaCli only sees 32 bits */ /* 0x0f0 */ + uint64_t coerced_size; /* sectors; MegaCli only sees 32 bits */ /* 0x0f8 */ + uint16_t enclosure; /* 0x100 */ + uint8_t value_9; /* 1 or 2, not sure what it means, goes with enclosure */ + uint8_t slot; + uint8_t value_10[0xfc]; +} __attribute__ ((packed)); + + +/* Unified config structures for generic high-level interface. */ + +enum mega_adapter_enum { + MEGA_ADAPTER_V2, /* PERC2 */ + MEGA_ADAPTER_V34, /* PERC3 or PERC4 */ + MEGA_ADAPTER_V5, /* PERC5 (SAS) */ +}; + +/* Structure for io to adapters. */ +struct mega_adapter_path +{ + int fd; /* block device descriptor for adapter access */ + uint8_t adapno; /* adapter number */ + enum mega_adapter_enum type; /* adapter variant */ +}; + + +struct log_page_list +{ + struct logData log; + uint8_t buf[4095]; /* rhl 7.3 croaks on >= 4096 */ + struct log_page_list *next; +}; + +enum physical_drive_state +{ + PdStateUnknown, + PdStateUnconfiguredGood, + PdStateUnconfiguredBad, + PdStateHotspare, + PdStateFailed, + PdStateRebuild, + PdStateOnline, +}; + +struct physical_drive_info +{ + uint8_t present; /* whether drive responds to inquiry */ + struct adapter_config *adapter; /* adapter this drive belongs to */ + struct span_info *span; /* span this disk is a member of */ + char name[16]; /* drive name (AxCyTz) */ + uint16_t target; /* scsi channel+id or device_id */ + uint16_t channel; /* channel or enclosure */ + uint8_t id; /* scsi id or enclosure slot */ + enum physical_drive_state state; /* drive state */ + char *error_string; /* status error string (NULL if okay) */ + uint64_t blocks; /* number of blocks */ + char vendor[9]; /* vendor name */ + char model[17]; /* vendor model */ + char revision[5]; /* firmware version */ + char serial[32]; /* serial number */ + uint32_t predictive_failures; /* predictive failure count */ + uint32_t media_errors; + uint32_t other_errors; + struct scsi_inquiry inquiry; /* scsi inquiry result */ + struct log_page_list *log; + + union + { + struct + { + struct mega_physical_disk_info_sas info; + } v5; + } q; +}; + +struct span_info +{ + struct adapter_config *adapter; /* adapter this span belongs to */ + uint32_t blocks_per_disk; /* blocks used per disk for this span */ + uint32_t num_disks; /* number of disks in this span */ + struct physical_drive_info **disk; /* pointers to component disks */ + uint32_t num_logical_drives; /* how many logical drives this span belongs to */ + struct logical_drive_info **logical_drive; /* pointers to logical drives */ +}; + +struct span_reference +{ + uint64_t offset; /* offset into each disk */ + uint64_t blocks_per_disk; /* number of blocks used per disk */ + struct span_info *span; /* the span */ +}; + +enum logical_drive_state +{ + LdStateUnknown, + LdStateOffline, + LdStatePartiallyDegraded, + LdStateDegraded, + LdStateOptimal, + LdStateDeleted, +}; + +struct logical_drive_info +{ + struct adapter_config *adapter; /* adapter this drive belongs to */ + char name[16]; /* logical drive name (AxLDy) */ + uint16_t target; /* logical drive number */ + enum logical_drive_state state; /* logical drive state */ + uint8_t raid_level; /* raid level */ + uint8_t num_spans; /* how many spans in this logical drive */ + struct span_reference *span; /* pointers to component spans */ + uint8_t span_size; /* number of disks per span */ +}; + +enum battery_charger_state +{ + ChargerStateUnknown, + ChargerStateFailed, + ChargerStateInProgress, + ChargerStateComplete, +}; + +struct adapter_config +{ + struct mega_adapter_path target; /* adapter access path */ + uint8_t is_sas; /* adapter is a sas adapter */ + char name[16]; /* adapter name (Ax) */ + char product[81]; /* adapter product name */ + char bios[17]; /* adapter bios version */ + char firmware[17]; /* adapter firmware version */ + struct + { + uint8_t healthy:1; + uint8_t module_missing:1; + uint8_t pack_missing:1; + uint8_t low_voltage:1; + uint8_t high_temperature:1; + uint8_t cycles_exceeded:1; + uint8_t over_charged:1; + enum battery_charger_state charger_state; + int16_t voltage; + int16_t temperature; + } battery; + uint16_t dram_size; /* size of DRAM in MB */ + uint16_t rebuild_rate; /* rebuild rate as percentage */ + uint16_t num_channels; /* number of channels or enclosures */ + uint8_t *channel; /* channel/enclosure map */ + uint16_t num_physicals; + struct physical_drive_info *physical; + struct physical_drive_info **physical_list; /* ordered list of physical devices */ + uint16_t num_spans; /* number of spans */ + struct span_info *span; + uint16_t num_logicals; /* number of logical drives */ + struct logical_drive_info *logical; /* logical drives */ + struct adapter_config *next; + + /* adapter-specific data structures */ + union + { + struct + { + mraid_inquiry1_t inquiry; + struct mega_predictive_map map; + disk_array_8ld_span8_t config; + } v2; + struct + { + mraid_pinfo_t adapinfo; + mraid_inquiry3_t enquiry3; + struct mega_predictive_map map; + disk_array_40ld_t config; + } v3; + struct + { + struct megasas_ctrl_info adapinfo; + struct mega_device_list_sas *device; + struct mega_array_config_sas config; + struct mega_battery_info_sas battery; + } v5; + } q; +}; + + +#endif diff --git a/src/megactl.c b/src/megactl.c new file mode 100644 index 0000000..6976580 --- /dev/null +++ b/src/megactl.c @@ -0,0 +1,926 @@ +/* + * Main program. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/******************************************************************** + +megactl/megasasctl + +Program to do the things you wish dellmgr or MegaCli could do, e.g. +report device log pages, run device self tests, report disk error +counts without having to pop in and out of countless dellmgr menus, +and actually document the adapter configuration concisely (dellmgr +gives you no way to do this). + +Author: Jefferson Ogata (JO317) +Date: 2006/01/23 + +Version 0.4.0 major changes, including SAS support: 2007/08/20 + +TODO: + +Other log page parsers. + +Cleaner log page output. + +Fixes for 64-bit systems. Currently builds only with -m32. + +********************************************************************/ + +#include "mega.h" +#include "megaioctl.h" +#include "adapter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dumpbytes.h" + +#include "logpage.h" + + +#ifdef MEGA_SAS_CTL + +#define MEGA_DEVICE "/dev/megaraid_sas_ioctl_node" + +#else + +#define MEGA_DEVICE "/dev/megadev0" + +#define MEGA_MIN_VERSION 0x118c + +#endif /* defined(MEGA_SAS_CTL) */ + + +static char *version = "0.4.1"; + + +static int verbosity = 0; + + +static char *me; +static char *usages[] = { +"usage: %p [-vest] [-H] [-l log-page-nr] [-T long|short] [target ...]", +"", +"Reports diagnostics on megaraid adapters and attached disks. Permits", +"dumping of controller log pages for inspection of error, temperature,", +"and self-test conditions, initiates self-test diagnostics, and documents", +"adapter and logical drive configuration. Target devices may be adapters,", +#ifdef MEGA_SAS_CTL +"(e.g. a0), enclosures (e.g. a0e0), or individual disks (e.g. a0e0s0). If", +#else +"(e.g. a0), channels (e.g. a0c0), or individual disks (e.g. a0c0t0). If", +#endif +"no target is specified, reports configuration and drive state on all", +"adapters. If a target matches a collection of disks, operations are", +"applied to all matching devices. Options are:", +"-v Increase program verbosity.", +"-e Dump read (0x03), write (0x02), and verify (0x05) error log", +" pages.", +"-s Dump self-test (0x10) log page.", +"-t Dump temperature (0x0d) log page.", +"-l page Dump the specified log page. Log page 0 documents the log pages", +" the device supports.", +"-p Do not report physical disks. Reports only adapters and logical", +" drives. Useful for concisely documenting adapter configuration.", +"-T test Initiate the background short or long self-test procedure. The", +" test may take up to an hour to complete, but does not inhibit", +" access to the device. The test may be monitored using the -s", +" option.", +"-H Perform an adapter health check. Inspects state of all logical", +" and physical drives and battery backup unit and reports problem", +" conditions. If all is well, generates no output. Useful in a", +" cron job.", +"-B When performing health check, do not treat battery problems as", +" failures.", +"-V Show version.", +"", +"N.B. The background long self test is a useful tool for diagnosing", +"problems with individual disks. But be cautious with program usage.", +"\"%p -T long\" with no targets will initiate a background long self", +"test on every drive on every adapter. This may not be what you want.", +"", +"By default, the health check option inspects log pages 0x02, 0x03, and", +"0x05 for uncorrected read, write, and verify errors, 0x0d for excess", +"temperature conditions, and 0x10 for failed self tests. If, however, any", +"of the log page options is specified, only the designated log pages are", +"inspected.", +"", +#ifdef MEGA_SAS_CTL +"This program requires the device file " MEGA_DEVICE " to be", +"present on the system. If your system does not have this device file,", +"you may create it either by executing LSI\'s \"MegaCli\" program once,", +"or by locating the megadev_sas_ioctl entry in /proc/devices and creating", +MEGA_DEVICE " as a character device with suitable", +"permissions with a matching major device number and a minor number of 0.", +#else +"This program requires the device file " MEGA_DEVICE " to be present on", +"the system. If your system does not have this device file, you may", +"create it either by executing Dell\'s \"dellmgr\" program once, or by", +"locating the megadev entry in /proc/devices and creating " MEGA_DEVICE, +"as a character device with suitable permissions with a matching major", +"device number and a minor number of 0.", +#endif + 0, +}; + + +void usage (const int ec, const char *format, ...) +{ + char **u; + va_list ap; + + va_start (ap, format); + if (format) + { + fprintf (stderr, "%s: ", me); + vfprintf (stderr, format, ap); + fprintf (stderr, "\n\n"); + } + for (u = usages; *u; ++u) + { + char *s; + int esc; + for (s = *u, esc = 0; *s; ++s) + { + if (esc) + { + switch (*s) + { + case 'p': fputs (me, stderr); break; + case '%': fputc ('%', stderr); break; + default: fputc ('%', stderr); fputc (*s, stderr); break; + } + esc = 0; + } + else + { + switch (*s) + { + case '%': esc = 1; break; + default: fputc (*s, stderr); break; + } + } + } + fputc ('\n', stderr); + } + + exit (ec); +} + + +static char *friendlySize (uint64_t b, char *unit) +{ + static char *suffix[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi", }; + int k; + static char bytes[128]; + + for (k = 0; (b >= 1024) && (k < sizeof (suffix) / sizeof (suffix[0]) - 1); ++k, b /= 1024) + ; + snprintf (bytes, sizeof bytes, "%3llu%s%s", b, suffix[k], unit); + return bytes; +} + + +void describePhysicalDrive (FILE *f, struct physical_drive_info *d, int verbosity) +{ + char *state; + + if (d->present) + switch (d->state) + { + case PdStateUnconfiguredGood: state = "ready"; break; + case PdStateUnconfiguredBad: state = "BAD"; break; + case PdStateOnline: state = "online"; break; + case PdStateFailed: state = d->span ? "FAILED" : "rdy/fail"; break; + case PdStateRebuild: state = "rebuild"; break; + case PdStateHotspare: state = "hotspare"; break; + default: state = "???"; break; + } + else + state = "absent"; + + fprintf (f, "%-8s", d->name); + if (verbosity > 0) + fprintf (f, " %8s %-16s", d->vendor, d->model); + if (verbosity > 1) + fprintf (f, " rev:%-4s s/n:%-20s", d->revision, d->serial); + fprintf (f, " %7s", friendlySize (d->blocks << 9, "B")); + fprintf (f, " %5s%c", d->span && d->span->num_logical_drives ? d->span->logical_drive[0]->name : "", d->span && (d->span->num_logical_drives > 1) ? '+' : ' '); + fprintf (f, " %-8s", state); + if (d->media_errors || d->other_errors) + fprintf (f, " errs: media:%-2u other:%u", d->media_errors, d->other_errors); + if (d->predictive_failures) + fprintf (f, " predictive-failure"); + fprintf (f, "\n"); + if (d->present && d->error_string) + fprintf (f, "\t%s\n", d->error_string); +} + + +void describeLogicalDrive (FILE *f, struct logical_drive_info *l, int verbosity) +{ + char *state; + uint64_t blocks; + int k; + struct span_reference *r; + + switch (l->state) + { + case LdStateOffline: state = "OFFLINE"; break; + case LdStatePartiallyDegraded: + case LdStateDegraded: state = "DEGRADED"; break; + case LdStateOptimal: state = "optimal"; break; + case LdStateDeleted: state = "deleted"; break; + default: state = "???"; break; + } + + for (k = 0, blocks = 0; k < l->num_spans; ++k) + { + r = &l->span[k]; + switch (l->raid_level) + { + case 0: blocks += r->blocks_per_disk * r->span->num_disks; break; + case 1: blocks += r->blocks_per_disk * r->span->num_disks / 2; break; + case 5: blocks += r->blocks_per_disk * (r->span->num_disks - 1); break; + } + } + + fprintf (f, "%-8s", l->name); + fprintf (f, " %s", friendlySize (blocks << 9, "B")); + fprintf (f, " RAID %u%s", l->raid_level, l->num_spans > 1 ? "0" : " "); + fprintf (f, " %2ux%-2u", l->num_spans, l->span_size); + fprintf (f, " %s", state); + fprintf (f, "\n"); + if (verbosity > 0) + { + for (k = 0; k < l->num_spans; ++k) + { + struct physical_drive_info **p; + int j; + + r = &l->span[k]; + fprintf (f, " row %2d:", k); + for (j = 0, p = r->span->disk; j < r->span->num_disks; ++j, ++p) + { + char *flag = (*p)->state != PdStateOnline ? "*" : " "; + fprintf (f, " %s%-8s", flag, (*p)->name); + } + fprintf (f, "\n"); + } + } +} + + +void describeBattery (FILE *f, struct adapter_config *a, int verbosity) +{ + if (a->battery.healthy) + fprintf (f, "good"); + else + { + fprintf (f, "FAULT"); + if (a->battery.module_missing) + fprintf (f, ", module missing"); + if (a->battery.pack_missing) + fprintf (f, ", pack missing"); + if (a->battery.low_voltage) + fprintf (f, ", low voltage"); + if (a->battery.high_temperature) + fprintf (f, ", high temperature"); + if (a->battery.cycles_exceeded) + fprintf (f, ", cycles exceeded"); + if (a->battery.over_charged) + fprintf (f, ", over charged"); + switch (a->battery.charger_state) + { + case ChargerStateComplete: break; + case ChargerStateFailed: fprintf (f, ", charge failed"); break; + case ChargerStateInProgress: fprintf (f, ", charging"); break; + default: fprintf (f, ", unknown charge state"); break; + } + } + if (verbosity) + { + if (a->battery.voltage >= 0) + fprintf (f, "/%dmV", a->battery.voltage); + if (a->battery.temperature >= 0) + fprintf (f, "/%dC", a->battery.temperature); + } +} + + +void describeAdapter (FILE *f, struct adapter_config *a, int verbosity) +{ + fprintf (f, "%-8s %-24s", a->name, a->product); + if (verbosity > 0) + fprintf (f, " bios:%s fw:%s", a->bios, a->firmware); + fprintf (f, " %s:%u ldrv:%-2u", a->is_sas ? "encl" : "chan", a->num_channels, a->num_logicals); + if (verbosity > 0) + fprintf (f, " rbld:%u%%", a->rebuild_rate); + if (verbosity > 1) + fprintf (f, " mem:%uMiB", a->dram_size); + fprintf (f, " batt:"); + describeBattery (f, a, verbosity); + fprintf (f, "\n"); +} + + +int main (int argc, char **argv) +{ + int k; + int fd; + uint32_t numAdapters; + uint32_t driverVersion; + int startSelfTest = -1; + int healthCheck = 0; + int checkBattery = 1; + char *device = MEGA_DEVICE; + struct query_object { + int adapter; + int channel; + int id; + } *object = NULL; + int numObjects = 0; + uint8_t readLog[LOG_PAGE_MAX] = { 0, }; + int reportPhysical = 1; + int showVersion = 0; +#ifdef MEGA_SAS_CTL + int sas = 1; +#else + int sas = 0; +#endif + + if ((me = strrchr (argv[0], '/'))) + ++me; + else + me = argv[0]; + + if (argc > 1) + { + if ((object = (struct query_object *) malloc ((argc - 1) * sizeof (*object))) == NULL) + { + perror ("malloc"); + return 1; + } + } + + for (k = 1; k < argc; ++k) + { + if (argv[k][0] == '-') + { + char *s; + + for (s = argv[k] + 1; *s; ++s) + { + if (*s == 'v') + { + ++verbosity; + continue; + } + if (*s == 'e') + { + /* read error log pages */ + readLog[0x02] = 1; /* write errors */ + readLog[0x03] = 1; /* read errors */ + readLog[0x05] = 1; /* read errors */ + continue; + } + if (*s == 's') + { + /* read self test log page */ + readLog[0x10] = 1; + continue; + } + if (*s == 't') + { + /* read temperature log page */ + readLog[0x0d] = 1; + continue; + } + if (*s == 'l') + { + /* read specific log page */ + char *t; + unsigned long u; + + if ((++k) >= argc) + usage (2, "no log page specified"); + u = strtoul (argv[k], &t, 0); + if (*t) + usage (2, "invalid log page \"%s\"", argv[k]); + if (u >= sizeof (readLog) / sizeof (readLog[0])) + usage (2, "log page out of range: \"%s\"", argv[k]); + readLog[u] = 1; + continue; + } + if (*s == 'D') + { + /* specify device file */ + if ((++k) >= argc) + usage (2, "no device specified"); + device = argv[k]; + continue; + } + if (*s == 'p') + { + reportPhysical = 0;; + continue; + } + if (*s == 'B') + { + /* skip battery check */ + checkBattery = 0; + continue; + } + if (*s == 'H') + { + /* perform adapter health check */ + ++healthCheck; + continue; + } + if (*s == 'T') + { + /* start self test */ + if ((++k) >= argc) + usage (2, "must specify short or long self-test"); + if (!strcmp (argv[k], "short")) + startSelfTest = SCSI_SELFTEST_BACKGROUND_SHORT; + else if (!strcmp (argv[k], "long")) + startSelfTest = SCSI_SELFTEST_BACKGROUND_LONG; + else + usage (2, "invalid self test: \"%s\"; must specify short or long", argv[k]); + continue; + } + else if ((*s == '?') || (*s == 'h')) + usage (0, NULL); + else if (*s == 'V') + { + ++showVersion; + continue; + } + usage (2, "invalid flag \"%s\"", s); + } + } + else + { + char *s; + char *t; + unsigned long l; + + s = argv[k]; + object[numObjects].adapter = -1; + object[numObjects].channel = -1; + object[numObjects].id = -1; + + if (*s) + { + if (tolower (*s) != 'a') + usage (2, "invalid specifier \"%s\"", argv[k]); + ++s; + l = strtoul (s, &t, 10); + if (s == t) + usage (2, "invalid specifier \"%s\"", argv[k]); +#ifndef MEGA_SAS_CTL + if (l >= MAX_CONTROLLERS) + usage (2, "adapter out of range: \"%s\"", argv[k]); +#endif + object[numObjects].adapter = l; + s = t; + } + + if (*s) + { + if (tolower (*s) != (sas ? 'e' : 'c')) + usage (2, "invalid specifier \"%s\"", argv[k]); + ++s; + l = strtoul (s, &t, 10); + if (s == t) + usage (2, "invalid specifier \"%s\"", argv[k]); +#ifndef MEGA_SAS_CTL + if (l >= MAX_MBOX_CHANNELS) + usage (2, "channel out of range: \"%s\"", argv[k]); +#endif + object[numObjects].channel = l; + s = t; + } + + if (*s) + { + if (tolower (*s) != (sas ? 's' : 't')) + usage (2, "invalid specifier \"%s\"", argv[k]); + ++s; + l = strtoul (s, &t, 10); + if (s == t) + usage (2, "invalid specifier \"%s\"", argv[k]); +#ifndef MEGA_SAS_CTL + if (l > MAX_MBOX_TARGET) + usage (2, "target out of range: \"%s\"", argv[k]); +#endif + object[numObjects].id = l; + s = t; + } + + ++numObjects; + } + } + + if (showVersion) + { + if (verbosity) + fprintf (stdout, "%s: version %s by Jefferson Ogata\n", me, version); + else + fprintf (stdout, "%s\n", version); + return 0; + } + + if (healthCheck) + { + int set = 0; + + for (k = 0; k < numObjects; ++k) + if ((object[k].channel >= 0) || (object[k].id >= 0)) + usage (2, "for health check, must specify adapter only"); + for (k = 0; k < sizeof readLog / sizeof (readLog[0]); ++k) + if (readLog[k]) + { + set = 1; + break; + } + if (set == 0) + { + /* No specific log pages requested; check read/write/verify errors and temperature. */ + readLog[0x02] = 1; + readLog[0x03] = 1; + readLog[0x05] = 1; + readLog[0x0d] = 1; + } + } + + if ((fd = open (device, O_RDONLY)) < 0) + { + fprintf (stderr, "unable to open device %s: %s\n", device, strerror (errno)); + return 1; + } + +#ifndef MEGA_SAS_CTL + if (megaGetDriverVersion (fd, &driverVersion) < 0) + { + fprintf (stderr, "unable to determine megaraid driver version: %s\n", megaErrorString ()); + return 1; + } + + if (driverVersion < MEGA_MIN_VERSION) + { + fprintf (stderr, "megaraid driver version %x too old.\n", driverVersion); + return 1; + } +#endif + + if (megaGetNumAdapters (fd, &numAdapters, sas) < 0) + { + fprintf (stderr, "unable to determine number of adapters: %s\n", megaErrorString ()); + return 1; + } + + if (verbosity > 2) + fprintf (stderr, "%u adapters, driver version %08x\n\n", numAdapters, driverVersion); + + /* Default to enumerating all adapters. */ + if (numObjects == 0) + { + if (object) + free (object); + if ((object = (struct query_object *) malloc (numAdapters * sizeof (*object))) == NULL) + { + perror ("malloc"); + return 1; + } + for (k = 0; k < numAdapters; ++k) + { + object[k].adapter = k; + object[k].channel = -1; + object[k].id = -1; + } + numObjects = k; + } + + for (k = 0; k < numObjects; ++k) + { + int adapter = object[k].adapter; + int channel = object[k].channel; + int id = object[k].id; + char name[32]; + struct adapter_config *a; + uint32_t c; + uint32_t i; + int j; + + if (id >= 0) + snprintf (name, sizeof name, "a%u%c%u%c%u", adapter, sas ? 'e' : 'c', channel, sas ? 's' : 't', id); + else if (channel >= 0) + snprintf (name, sizeof name, "a%u%c%u", adapter, sas ? 'e' : 'c', channel); + else + snprintf (name, sizeof name, "a%u", adapter); + + if (adapter >= numAdapters) + { + fprintf (stderr, "%s: no such adapter\n", name); + continue; + } + + if ((a = getAdapterConfig (fd, adapter, sas)) == NULL) + { + fprintf (stderr, "%s: cannot read adapter configuration: %s\n", name, megaErrorString ()); + break; + } + + if (healthCheck) + { + int adapterReported = 0; + struct logical_drive_info *l; + + if (checkBattery && (!a->battery.healthy)) + { + if (!(adapterReported++)) + describeAdapter (stdout, a, verbosity); + } + +#ifndef MEGA_SAS_CTL + /* Scan all physical devices. */ + for (c = 0; c < a->num_channels; ++c) + { + for (i = 0; i <= MAX_MBOX_TARGET; ++i) + { + uint8_t target = (a->channel[c] << 4) | i; + + (void) getPhysicalDriveInfo (a, target, 1); + } + } +#endif + + for (i = 0, l = a->logical; i < a->num_logicals; ++i, ++l) + { + int reportDrive = 0; + + if ((l->state != LdStateOptimal) && (l->state != LdStateDeleted)) + ++reportDrive; + + if (reportDrive) + { + if (!(adapterReported++)) + describeAdapter (stdout, a, verbosity); + describeLogicalDrive (stdout, l, verbosity); + } + } + + for (i = 0; i < a->num_physicals; ++i) + { + struct physical_drive_info *d = a->physical_list[i]; + int reportDrive = 0; + struct log_page_list *log; + + if (d == NULL) + break; + if (!(d->present)) + continue; + +//describePhysicalDrive (stdout, d, verbosity); + + /* check for drive problems */ + if ((d->state == PdStateRebuild) || (d->span && (d->state == PdStateFailed))) + ++reportDrive; + if (d->media_errors) + ++reportDrive; + if (d->predictive_failures) + ++reportDrive; + + /* check interesting log pages */ + for (j = 0; j < sizeof (readLog) / sizeof (readLog[0]); ++j) + { + if (readLog[j] == 0) + continue; + + if ((log = getDriveLogPage (d, j)) == NULL) + continue; + + if (log->log.problem) + ++reportDrive; + } + + if (reportDrive) + { + if (!(adapterReported++)) + describeAdapter (stdout, a, verbosity); + describePhysicalDrive (stdout, d, verbosity); + for (j = 0; j < sizeof (readLog) / sizeof (readLog[0]); ++j) + { + if (readLog[j] == 0) + continue; + + if ((log = getDriveLogPage (d, j)) == NULL) + continue; + + dumpLogPage (stdout, &log->log, NULL, 0, verbosity); + } + } + } + continue; + } + + if (channel >= 0) + { + for (c = 0; c < a->num_channels; ++c) + if (channel == a->channel[c]) + break; + if (c >= a->num_channels) + { + fprintf (stderr, "%s: no such channel\n", name); + continue; + } + } + + if ((channel < 0) && (id < 0)) + { + struct logical_drive_info *l; + int x; + + describeAdapter (stdout, a, verbosity); + +#ifndef MEGA_SAS_CTL + /* Scan all physical devices. */ + for (c = 0; c < a->num_channels; ++c) + { + for (i = 0; i <= MAX_MBOX_TARGET; ++i) + { + uint8_t target = (a->channel[c] << 4) | i; + + (void) getPhysicalDriveInfo (a, target, 1); + } + } +#endif + + for (i = 0, l = a->logical; i < a->num_logicals; ++i, ++l) + describeLogicalDrive (stdout, l, verbosity); + + x = 0; + + for (i = 0; i < a->num_physicals; ++i) + { + struct physical_drive_info *d = a->physical_list[i]; + + if (d == NULL) + break; + if (!(d->present)) + continue; + + if (d->state == PdStateHotspare) + { + if (x == 0) + fprintf (stdout, "hot spares :"); + else if ((x % 8) == 0) + fprintf (stdout, " :"); + fprintf (stdout, " %-8s", d->name); + if (((++x) % 8) == 0) + fprintf (stdout, "\n"); + } + } + if (x % 8) + fprintf (stdout, "\n"); + + x = 0; + for (i = 0; i < a->num_physicals; ++i) + { + struct physical_drive_info *d = a->physical_list[i]; + + if (d == NULL) + break; + if (!(d->present)) + continue; + + if ((!(d->span)) && (d->state != PdStateHotspare)) + { + if (x == 0) + fprintf (stdout, "unconfigured :"); + else if ((x % 8) == 0) + fprintf (stdout, " :"); + fprintf (stdout, " %-8s", d->name); + if (((++x) % 8) == 0) + fprintf (stdout, "\n"); + } + } + if (x % 8) + fprintf (stdout, "\n"); + } + + for (c = 0; c < a->num_channels; ++c) + { + if ((channel >= 0) && (channel != a->channel[c])) + continue; + +#ifndef MEGA_SAS_CTL + if (id >= 0) + { + uint8_t target = (a->channel[c] << 4) | id; + (void) getPhysicalDriveInfo (a, target, 1); + } + else + { + /* Scan all devices on this channel. */ + for (i = 0; i <= MAX_MBOX_TARGET; ++i) + { + uint8_t target = (a->channel[c] << 4) | i; + + (void) getPhysicalDriveInfo (a, target, 1); + } + } +#endif + + for (i = 0; i < a->num_physicals; ++i) + { + struct physical_drive_info *d = a->physical_list[i]; + + if (d == NULL) + break; + + if (d->channel != a->channel[c]) + continue; + + if ((id >= 0) && (id != d->id)) + continue; + + if (startSelfTest >= 0) + { + uint8_t diag[256]; + + memset (diag, 0, sizeof diag); + if (megaScsiSendDiagnostic (&a->target, d->target, diag, sizeof diag, startSelfTest, 0, 0) < 0) + fprintf (stderr, "self test: %s\n", megaErrorString ()); + } + + if (reportPhysical) + { + describePhysicalDrive (stdout, d, verbosity); + for (j = 0; j < sizeof (readLog) / sizeof (readLog[0]); ++j) + { + struct log_page_list *log; + + if (readLog[j] == 0) + continue; + + if ((log = getDriveLogPage (d, j)) == NULL) + continue; + + dumpLogPage (stdout, &log->log, &log->buf, sizeof (log->buf), verbosity); + } + } + } + } + + fprintf (stdout, "\n"); + } + + return 0; +} + + +#if 0 + if (0) + { + uint8_t modes[1024]; + + memset (modes, 0, sizeof modes); + megaScsiModeSense (fd, adapter, target, modes, sizeof modes, 0, 0x3f, 0xff); + } +#endif + + diff --git a/src/megaioctl.c b/src/megaioctl.c new file mode 100644 index 0000000..d696049 --- /dev/null +++ b/src/megaioctl.c @@ -0,0 +1,523 @@ +/* + * Low-level interface to adapter information. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include "megaioctl.h" + +/* Don't include */ + +#include +#include +#include +#include +#include + + +int megaErrno = 0; + + +static int doIoctl (struct mega_adapter_path *adapter, void *u) +{ + switch (adapter->type) + { + case MEGA_ADAPTER_V2: + case MEGA_ADAPTER_V34: + return ioctl (adapter->fd, _IOWR(MEGAIOC_MAGIC, 0, struct uioctl_t), u); + case MEGA_ADAPTER_V5: + return ioctl (adapter->fd, MEGASAS_IOC_FIRMWARE, u); + } + return -1; +} + + +static int driverQuery (int fd, uint16_t adap, void *data, uint32_t len, uint8_t subop) +{ + struct uioctl_t u; + struct mega_adapter_path adapter; + + memset (&u, 0, sizeof u); + u.outlen = len; + u.ui.fcs.opcode = M_RD_DRIVER_IOCTL_INTERFACE; + u.ui.fcs.subopcode = subop; + u.ui.fcs.length = len; + u.data = data; + if (data) + memset (data, 0, len); + + adapter.fd = fd; + adapter.type = MEGA_ADAPTER_V34; + if (doIoctl (&adapter, &u) < 0) + { + megaErrno = errno; + return -1; + } + return 0; +} + + +static int oldCommand (struct mega_adapter_path *adapter, void *data, uint32_t len, uint8_t cmd, uint8_t opcode, uint8_t subopcode) +{ + struct uioctl_t u; + int_mbox_t *m = (int_mbox_t *) &u.mbox; + + memset (&u, 0, sizeof u); + u.outlen = len; + u.ui.fcs.opcode = M_RD_IOCTL_CMD; + u.ui.fcs.adapno = MKADAP(adapter->adapno); + u.data = data; + m->cmd = cmd; + m->opcode = opcode; + m->subopcode = subopcode; + m->xferaddr = (uint32_t) data; + if (data) + memset (data, 0, len); + + if (doIoctl (adapter, &u) < 0) + { + megaErrno = errno; + return -1; + } + return 0; +} + + +static int newCommand (struct mega_adapter_path *adapter, void *data, uint32_t len, uint8_t cmd, uint8_t opcode, uint8_t subopcode) +{ + struct uioctl_t u; + int_mbox_t *m = (int_mbox_t *) &u.mbox; + + memset (&u, 0, sizeof u); + u.outlen = len; + u.ui.fcs.opcode = M_RD_IOCTL_CMD_NEW; + u.ui.fcs.adapno = MKADAP(adapter->adapno); + u.ui.fcs.buffer = data; + u.ui.fcs.length = len; + u.data = data; + m->cmd = cmd; + m->opcode = opcode; + m->subopcode = subopcode; + m->xferaddr = (uint32_t) data; + if (data) + memset (data, 0, len); + + if (doIoctl (adapter, &u) < 0) + { + megaErrno = errno; + return -1; + } + return 0; +} + + +static int sasCommand (struct mega_adapter_path *adapter, void *data, uint32_t len, uint32_t opcode, uint16_t flags, void *mbox, uint32_t mboxlen) +{ + struct megasas_iocpacket u; + struct megasas_dcmd_frame *f = (struct megasas_dcmd_frame *) &u.frame; + + memset (&u, 0, sizeof u); + u.host_no = (u16) adapter->adapno; + + f->cmd = MFI_CMD_DCMD; + f->flags = (u16) flags; + f->opcode = (u32) opcode; + + if ((data != NULL) && (len > 0)) + { + u.sgl_off = ((void *) &f->sgl) - ((void *) f); + u.sge_count = 1; + u.sgl[0].iov_base = data; + u.sgl[0].iov_len = len; + f->sge_count = 1; + f->data_xfer_len = (u32) len; + f->sgl.sge32[0].phys_addr = (u32) data; + f->sgl.sge32[0].length = (u32) len; + } + + if (mbox != NULL) + memcpy (&f->mbox, mbox, mboxlen); + + if (doIoctl (adapter, &u) < 0) + { + megaErrno = errno; + return -1; + } + return f->cmd_status; +} + + +static int passthruCommand (struct mega_adapter_path *adapter, void *data, uint32_t len, uint8_t target, uint8_t *cdb, uint8_t cdblen) +{ + if ((adapter->type == MEGA_ADAPTER_V2) || (adapter->type == MEGA_ADAPTER_V34)) + { + struct uioctl_t u; + int_mbox_t *m = (int_mbox_t *) &u.mbox; + mraid_passthru_t *p = &u.pthru; + + memset (&u, 0, sizeof u); + u.outlen = len; + u.ui.fcs.opcode = M_RD_IOCTL_CMD; + u.ui.fcs.adapno = MKADAP(adapter->adapno); + u.data = data; + m->cmd = MBOXCMD_PASSTHRU; + m->xferaddr = (uint32_t) p; + p->timeout = 3; + p->ars = 1; + p->target = target; + p->dataxferaddr = (uint32_t) data; + p->dataxferlen = len; + p->scsistatus = 239; /* HMMM */ + memcpy (p->cdb, cdb, cdblen); + p->cdblen = cdblen; + if (data) + memset (data, 0, len); + + if (doIoctl (adapter, &u) < 0) + { + megaErrno = errno; + return -1; + } + + if (m->status) + { + megaErrno = - (m->status); + return -1; + } + + if (p->scsistatus & CHECK_CONDITION) + { + megaErrno = - CHECK_CONDITION; + return -1; + } + if ((p->scsistatus & STATUS_MASK) != GOOD) + { + megaErrno = - (p->scsistatus & STATUS_MASK); + return -1; + } + } + else + { + struct megasas_iocpacket u; + struct megasas_pthru_frame *f = (struct megasas_pthru_frame *) &u.frame; + + memset (&u, 0, sizeof u); + u.host_no = (u16) adapter->adapno; + + f->cmd = MFI_CMD_PD_SCSI_IO; + f->target_id = target; + f->cdb_len = cdblen; + f->flags = MFI_FRAME_DIR_READ; + memcpy (f->cdb, cdb, cdblen); + + if ((data != NULL) && (len > 0)) + { + u.sgl_off = ((void *) &f->sgl) - ((void *) f); + u.sge_count = 1; + u.sgl[0].iov_base = data; + u.sgl[0].iov_len = len; + + f->sge_count = 1; + f->data_xfer_len = (u32) len; + f->sgl.sge32[0].phys_addr = (u32) data; + f->sgl.sge32[0].length = (u32) len; + } + + if (doIoctl (adapter, &u) < 0) + { + megaErrno = errno; + return -1; + } + + if (f->cmd_status) + { + megaErrno = - (f->cmd_status); + return -1; + } + + if ((f->scsi_status & STATUS_MASK) != GOOD) + { + megaErrno = - (f->scsi_status & STATUS_MASK); + return -1; + } + } + + return 0; +} + + +int megaScsiDriveInquiry (struct mega_adapter_path *adapter, uint8_t target, void *data, uint32_t len, uint8_t pageCode, uint8_t evpd) +{ + uint8_t cdb[6]; + + cdb[0] = INQUIRY; + cdb[1] = (evpd != 0); + cdb[2] = pageCode; + cdb[3] = (len >> 8) & 0xff; + cdb[4] = len & 0xff; + cdb[5] = 0; + + return passthruCommand (adapter, data, len, target, cdb, sizeof cdb); +} + + +int megaScsiModeSense (struct mega_adapter_path *adapter, uint8_t target, void *data, uint32_t len, uint8_t pageControl, uint8_t page, uint8_t subpage) +{ +#ifdef USE_MODE_SENSE_6 + uint8_t cdb[6]; + + cdb[0] = MODE_SENSE; + cdb[1] = 0; /* dbd in bit 3 */ + cdb[2] = ((pageControl & 0x3) << 6) | (page & 0x3f); + cdb[3] = subpage; + cdb[4] = len & 0xff; + cdb[5] = 0; +#else + uint8_t cdb[10]; + + cdb[0] = MODE_SENSE_10; + cdb[1] = 0; /* llbaa in bit 4, dbd in bit 3 */ + cdb[2] = ((pageControl & 0x3) << 6) | (page & 0x3f); + cdb[3] = subpage; + cdb[4] = 0; + cdb[5] = 0; + cdb[6] = 0; + cdb[7] = (len >> 8) & 0xff; + cdb[8] = len & 0xff; + cdb[9] = 0; +#endif + + return passthruCommand (adapter, data, len, target, cdb, sizeof cdb); +} + + +int megaScsiLogSense (struct mega_adapter_path *adapter, uint8_t target, void *data, uint32_t len, uint8_t pageControl, uint8_t page, uint16_t parameterPointer) +{ + uint8_t cdb[10]; + + cdb[0] = LOG_SENSE; + cdb[1] = 0; /* ppc in bit 1, sp in bit 1 */ + cdb[2] = ((pageControl & 0x3) << 6) | (page & 0x3f); + cdb[3] = 0; + cdb[4] = 0; + cdb[5] = (parameterPointer >> 8) & 0xff; + cdb[6] = parameterPointer & 0xff; + cdb[7] = (len >> 8) & 0xff; + cdb[8] = len & 0xff; + cdb[9] = 0; + + return passthruCommand (adapter, data, len, target, cdb, sizeof cdb); +} + + +int megaScsiSendDiagnostic (struct mega_adapter_path *adapter, uint8_t target, void *data, uint32_t len, uint8_t testCode, uint8_t unitOffline, uint8_t deviceOffline) +{ + uint8_t cdb[6]; + + cdb[0] = SEND_DIAGNOSTIC; + cdb[1] = ((testCode & 0x7) << 5) | ((deviceOffline != 0) << 1) | (unitOffline != 0); + cdb[2] = 0; + cdb[3] = 0; + cdb[4] = 0; + cdb[5] = 0; + + return passthruCommand (adapter, data, len, target, cdb, sizeof cdb); +} + + +int megaGetAdapterConfig8 (struct mega_adapter_path *adapter, disk_array_8ld_span8_t *config) +{ + return oldCommand (adapter, config, sizeof (*config), NEW_READ_CONFIG_8LD, 0, 0); +} + + +int megaGetAdapterConfig40 (struct mega_adapter_path *adapter, disk_array_40ld_t *config) +{ + return newCommand (adapter, config, sizeof (*config), FC_NEW_CONFIG, OP_DCMD_READ_CONFIG, 0); +} + + +int megaGetAdapterInquiry (struct mega_adapter_path *adapter, mraid_inquiry1_t *data) +{ + return oldCommand (adapter, data, sizeof (*data), MBOXCMD_ADAPTERINQ, 0, 0); +} + + +int megaGetAdapterExtendedInquiry (struct mega_adapter_path *adapter, mraid_extinq1_t *data) +{ + return oldCommand (adapter, data, sizeof (*data), MBOXCMD_ADPEXTINQ, 0, 0); +} + + +int megaGetAdapterEnquiry3 (struct mega_adapter_path *adapter, mraid_inquiry3_t *data) +{ + return newCommand (adapter, data, sizeof (*data), FC_NEW_CONFIG, NC_SUBOP_ENQUIRY3, 0); +} + + +int megaGetPredictiveMap (struct mega_adapter_path *adapter, struct mega_predictive_map *data) +{ + return oldCommand (adapter, data, sizeof (*data), MAIN_MISC_OPCODE, 0x0f, 0); +} + + +int megaGetDriveErrorCount (struct mega_adapter_path *adapter, uint8_t target, struct mega_physical_drive_error_info *data) +{ + return oldCommand (adapter, data, sizeof (*data), 0x77, 0, target); +} + + +int megaSasGetDeviceList (struct mega_adapter_path *adapter, struct mega_device_list_sas **data) +{ + unsigned char buf[0x20]; + uint32_t len; + + if (sasCommand (adapter, buf, sizeof buf, 0x02010000, MFI_FRAME_DIR_READ, NULL, 0) < 0) + return -1; + len = ((struct mega_device_list_sas *) buf)->length; + if ((*data = (struct mega_device_list_sas *) malloc (len)) == NULL) + { + megaErrno = errno; + return -1; + } + return sasCommand (adapter, *data, len, 0x02010000, MFI_FRAME_DIR_READ, NULL, 0); +} + + +int megaSasGetDiskInfo (struct mega_adapter_path *adapter, uint8_t target, struct mega_physical_disk_info_sas *data) +{ + uint8_t mbox[0xc]; + + memset (&mbox, 0, sizeof mbox); + mbox[0] = target; + return sasCommand (adapter, data, sizeof (*data), 0x02020000, MFI_FRAME_DIR_READ, mbox, sizeof mbox); +} + + +int megaSasGetArrayConfig (struct mega_adapter_path *adapter, struct mega_array_config_sas *data) +{ + unsigned char buf[0x20]; + uint32_t len; + + if (sasCommand (adapter, buf, sizeof buf, 0x04010000, MFI_FRAME_DIR_READ, NULL, 0) < 0) + return -1; + len = ((struct mega_array_header_sas *) buf)->length; + if ((data->header = (struct mega_array_header_sas *) malloc (len)) == NULL) + { + megaErrno = errno; + return -1; + } + if (sasCommand (adapter, data->header, len, 0x04010000, MFI_FRAME_DIR_READ, NULL, 0) < 0) + { + megaErrno = errno; + return -1; + } + + data->span = (struct mega_array_span_def_sas *) (data->header + 1); + data->disk = (struct mega_array_disk_def_sas *) (data->span + data->header->num_span_defs); + data->hotspare = (struct mega_array_hotspare_def_sas *) (data->disk + data->header->num_disk_defs); + + return 0; +} + +int megaSasGetBatteryInfo (struct mega_adapter_path *adapter, struct mega_battery_info_sas *data) +{ + if (sasCommand (adapter, &(data->state), sizeof (data->state), 0x05010000, MFI_FRAME_DIR_READ, NULL, 0) < 0) + return -1; + if (sasCommand (adapter, &(data->capacity), sizeof (data->capacity), 0x05020000, MFI_FRAME_DIR_READ, NULL, 0) < 0) + return -1; + if (sasCommand (adapter, &(data->design), sizeof (data->design), 0x05030000, MFI_FRAME_DIR_READ, NULL, 0) < 0) + return -1; + return sasCommand (adapter, &(data->properties), sizeof (data->properties), 0x05050100, MFI_FRAME_DIR_READ, NULL, 0); +} + + +int megaGetDriverVersion (int fd, uint32_t *version) +{ + return driverQuery (fd, 0, version, sizeof (*version), 'e'); +} + + +int megaGetNumAdapters (int fd, uint32_t *numAdapters, int sas) +{ + if (sas) + { + uint8_t k; + for (k = 0; k < 16; ++k) + if (megaSasAdapterPing (fd, k) < 0) + break; + *numAdapters = k; + return 0; + } + else + return driverQuery (fd, 0, numAdapters, sizeof (*numAdapters), 'm'); +} + + +int megaGetAdapterProductInfo (int fd, uint8_t adapno, mraid_pinfo_t *data) +{ + struct mega_adapter_path adapter; + adapter.fd = fd; + adapter.adapno = adapno; + adapter.type = MEGA_ADAPTER_V34; + return newCommand (&adapter, data, sizeof (*data), FC_NEW_CONFIG, NC_SUBOP_PRODUCT_INFO, 0); +} + + +int megaSasGetAdapterProductInfo (int fd, uint8_t adapno, struct megasas_ctrl_info *data) +{ + struct mega_adapter_path adapter; + adapter.fd = fd; + adapter.adapno = adapno; + adapter.type = MEGA_ADAPTER_V5; + return sasCommand (&adapter, data, sizeof (*data), MR_DCMD_CTRL_GET_INFO, MFI_FRAME_DIR_READ, NULL, 0); +} + + +int megaSasAdapterPing (int fd, uint8_t adapno) +{ + struct mega_adapter_path adapter; + unsigned char data[0xc4]; + adapter.fd = fd; + adapter.adapno = adapno; + adapter.type = MEGA_ADAPTER_V5; + return sasCommand (&adapter, data, sizeof data, 0x04060100, MFI_FRAME_DIR_READ, NULL, 0); +} + + +char *megaErrorString (void) +{ + if (megaErrno >= 0) + return strerror (megaErrno); + switch (-megaErrno) + { + case CHECK_CONDITION: return "scsi command status CHECK_CONDITION"; break; + case CONDITION_GOOD: return "scsi command status CONDITION_GOOD"; break; + case BUSY: return "scsi command status BUSY"; break; + case INTERMEDIATE_GOOD: return "scsi command status INTERMEDIATE_GOOD"; break; + case INTERMEDIATE_C_GOOD: return "scsi command status INTERMEDIATE_C_GOOD"; break; + case RESERVATION_CONFLICT: return "scsi command status RESERVATION_CONFLICT"; break; + case COMMAND_TERMINATED: return "scsi command status COMMAND_TERMINATED"; break; + case QUEUE_FULL: return "scsi command status QUEUE_FULL"; break; + default: return "scsi command status unknown"; break; + } +} + + diff --git a/src/megaioctl.h b/src/megaioctl.h new file mode 100644 index 0000000..37fd31f --- /dev/null +++ b/src/megaioctl.h @@ -0,0 +1,90 @@ +#ifndef _MEGAIOCTL_H +#define _MEGAIOCTL_H +/* + * Definitions for low-level adapter interface. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include "mega.h" + + +/* Old-style ioctl structure for megaraid 1 & 2 drivers. Cribbed from version 1 megaraid.h. */ +#pragma pack(1) +struct uioctl_t { + uint32_t inlen; + uint32_t outlen; + union { + uint8_t fca[16]; + struct { + uint8_t opcode; + uint8_t subopcode; + uint16_t adapno; +#if BITS_PER_LONG == 32 + uint8_t *buffer; + uint8_t pad[4]; +#endif +#if BITS_PER_LONG == 64 + uint8_t *buffer; +#endif + uint32_t length; + } fcs; + } ui; + uint8_t mbox[18]; /* 16 bytes + 2 status bytes */ + mraid_passthru_t pthru; +#if BITS_PER_LONG == 32 + char *data; /* buffer <= 4096 for 0x80 commands */ + char pad[4]; +#endif +#if BITS_PER_LONG == 64 + char *data; +#endif +}; +#pragma pack() + + +extern int megaErrno; + +extern int megaScsiDriveInquiry (struct mega_adapter_path *adapter, uint8_t target, void *data, uint32_t len, uint8_t pageCode, uint8_t evpd); +extern int megaScsiModeSense (struct mega_adapter_path *adapter, uint8_t target, void *data, uint32_t len, uint8_t pageControl, uint8_t page, uint8_t subpage); +extern int megaScsiLogSense (struct mega_adapter_path *adapter, uint8_t target, void *data, uint32_t len, uint8_t pageControl, uint8_t page, uint16_t parameterPointer); +extern int megaScsiSendDiagnostic (struct mega_adapter_path *adapter, uint8_t target, void *data, uint32_t len, uint8_t testCode, uint8_t unitOffline, uint8_t deviceOffline); +extern int megaGetAdapterConfig8 (struct mega_adapter_path *adapter, disk_array_8ld_span8_t *data); +extern int megaGetAdapterConfig40 (struct mega_adapter_path *adapter, disk_array_40ld_t *data); +extern int megaGetAdapterInquiry (struct mega_adapter_path *adapter, mraid_inquiry1_t *data); +extern int megaGetAdapterExtendedInquiry (struct mega_adapter_path *adapter, mraid_extinq1_t *data); +extern int megaGetAdapterEnquiry3 (struct mega_adapter_path *adapter, mraid_inquiry3_t *data); +extern int megaGetPredictiveMap (struct mega_adapter_path *adapter, struct mega_predictive_map *data); +extern int megaGetDriveErrorCount (struct mega_adapter_path *adapter, uint8_t target, struct mega_physical_drive_error_info *data); + +extern int megaSasGetDeviceList (struct mega_adapter_path *adapter, struct mega_device_list_sas **data); +extern int megaSasGetDiskInfo (struct mega_adapter_path *adapter, uint8_t target, struct mega_physical_disk_info_sas *data); +extern int megaSasGetArrayConfig (struct mega_adapter_path *adapter, struct mega_array_config_sas *data); +extern int megaSasGetBatteryInfo (struct mega_adapter_path *adapter, struct mega_battery_info_sas *data); + +extern int megaGetDriverVersion (int fd, uint32_t *version); +extern int megaGetNumAdapters (int fd, uint32_t *numAdapters, int sas); +extern int megaGetAdapterProductInfo (int fd, uint8_t adapno, mraid_pinfo_t *info); +extern int megaSasGetAdapterProductInfo (int fd, uint8_t adapno, struct megasas_ctrl_info *info); +extern int megaSasAdapterPing (int fd, uint8_t adapno); + +extern char *megaErrorString (void); + +#endif diff --git a/src/megaraid b/src/megaraid new file mode 120000 index 0000000..f02969e --- /dev/null +++ b/src/megaraid @@ -0,0 +1 @@ +kernel-2.6.9-55.0.2.EL/megaraid-2.20.4.6-rh2 \ No newline at end of file diff --git a/src/megarpt b/src/megarpt new file mode 100755 index 0000000..0286795 --- /dev/null +++ b/src/megarpt @@ -0,0 +1,66 @@ +#!/bin/sh +# +# megarpt +# +# Emails a message to root with megaraid configuration and any +# output from a health check. Useful as a nightly cron job. +# +# Author: Jefferson Ogata (JO317) +# Date: 2007/08/20 + +VERSION='0.3' +MEGACTL=/root/megactl +DEVICE=/dev/megadev0 +DEVICENAME=megadev +DEVICEPERM=644 +ME=`basename $0` + +if [ -x $MEGACTL ]; then + MEGACTLVERSION=`$MEGACTL -V` +else + echo "No megactl program in $MEGACTL" >&2 + exit 1 +fi + +MAJOR=`grep "$DEVICENAME" /proc/devices | awk '{print $1}'` + +if [ -n "$MAJOR" -a ! -e "$DEVICE" ]; then + mknod "$DEVICE" c "$MAJOR" 0 + chmod "$DEVICEPERM" "$DEVICE" +fi + +if [ -e "$DEVICE" ]; then + + WARN= + HOST=`/bin/uname -n` + DATE=`/bin/date '+%Y/%m/%d %H:%M:%S %Z'` + HC=/tmp/megactl.$$ + + $MEGACTL -vH > $HC 2>/dev/null + if [ -s $HC ]; then + WARN=' **WARNING**' + fi + + ( + if [ -s $HC ]; then + echo "megaraid health check" + echo "---------------------" + cat $HC + echo + echo + fi + + echo "megaraid configuration" + echo "----------------------" + $MEGACTL -vp + + echo + echo "--------------" + echo "$ME version: $VERSION" + echo "megactl version: $MEGACTLVERSION" + ) 2>/dev/null | + /bin/mail -s "RAID report:$WARN $HOST $DATE" root + + rm -f $HC +fi + diff --git a/src/megasasrpt b/src/megasasrpt new file mode 100755 index 0000000..0bf29a3 --- /dev/null +++ b/src/megasasrpt @@ -0,0 +1,66 @@ +#!/bin/sh +# +# megarpt +# +# Emails a message to root with megaraid configuration and any +# output from a health check. Useful as a nightly cron job. +# +# Author: Jefferson Ogata (JO317) +# Date: 2007/08/20 + +VERSION='0.3' +MEGACTL=/root/megasasctl +DEVICE=/dev/megaraid_sas_ioctl_node +DEVICENAME=megaraid_sas_ioctl +DEVICEPERM=400 +ME=`basename $0` + +if [ -x $MEGACTL ]; then + MEGACTLVERSION=`$MEGACTL -V` +else + echo "No megactl program in $MEGACTL" >&2 + exit 1 +fi + +MAJOR=`grep "$DEVICENAME" /proc/devices | awk '{print $1}'` + +if [ -n "$MAJOR" -a ! -e "$DEVICE" ]; then + mknod "$DEVICE" c "$MAJOR" 0 + chmod "$DEVICEPERM" "$DEVICE" +fi + +if [ -e "$DEVICE" ]; then + + WARN= + HOST=`/bin/uname -n` + DATE=`/bin/date '+%Y/%m/%d %H:%M:%S %Z'` + HC=/tmp/megactl.$$ + + $MEGACTL -vH > $HC 2>/dev/null + if [ -s $HC ]; then + WARN=' **WARNING**' + fi + + ( + if [ -s $HC ]; then + echo "megaraid health check" + echo "---------------------" + cat $HC + echo + echo + fi + + echo "megaraid configuration" + echo "----------------------" + $MEGACTL -vp + + echo + echo "--------------" + echo "$ME version: $VERSION" + echo "megactl version: $MEGACTLVERSION" + ) 2>/dev/null | + /bin/mail -s "RAID report:$WARN $HOST $DATE" root + + rm -f $HC +fi + diff --git a/src/megatrace.c b/src/megatrace.c new file mode 100644 index 0000000..b4cfd0a --- /dev/null +++ b/src/megatrace.c @@ -0,0 +1,468 @@ +/* + * Main program for ioctl tracer. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +/******************************************************************** + +megatrace + +Program to ptrace another program and inspect megaraid-related ioctl +syscalls it makes. + +Author: Jefferson Ogata (JO317) +Date: 2006/01/23 + +TODO: + +Fixes for 64-bit systems. + +********************************************************************/ + + +#include "mega.h" +#include "megaioctl.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "callinfo.h" +#include "dumpbytes.h" + +enum state { UNTRACED, INBOUND, OUTBOUND }; + + +void copyout (void *buf, size_t len, pid_t pid, uint32_t addr) +{ + off_t k; + uint32_t *z = (uint32_t *) buf; + uint32_t sd; + + for (k = 0; k < (len + 3) / 4; ++k) + { + sd = ptrace (PTRACE_PEEKDATA, pid, (void *) (addr + 4 * k), 0); + z[k] = sd; + } +} + + +void copyin (void *buf, size_t len, pid_t pid, uint32_t addr) +{ + off_t k; + uint32_t *z = (uint32_t *) buf; + + for (k = 0; k < (len + 3) / 4; ++k) + ptrace (PTRACE_POKEDATA, pid, (void *) (addr + 4 * k), z[k]); +} + + +int main (int argc, char **argv, char **environ) +{ + pid_t pid; + int state = UNTRACED; + struct timeval starttv; + int printproc = 0; + + if ((pid = fork ()) == 0) + { + ptrace (PTRACE_TRACEME); + ++argv; + execvp (argv[0], argv); + fprintf (stderr, "execve: %s: %s\n", argv[0], strerror (errno)); + _exit (1); + } + + if (pid < 0) + { + fprintf (stderr, "fork: %s\n", strerror (errno)); + exit (1); + } + + gettimeofday (&starttv, NULL); + + /*fprintf (stderr, "%d\n", sizeof (mega_host_config));*/ + + while (1) + { + pid_t w; + int st; + + w = waitpid (pid, &st, /*WNOHANG*/ 0); + + if (w == 0) + { + fprintf (stderr, "wait: no child\n"); + usleep (10); + continue; + } + + if (w < 0) + { + fprintf (stderr, "wait: %s\n", strerror (errno)); + exit (1); + } + + if (WIFEXITED (st)) + { + if (printproc) + fprintf (stderr, "child exited with status %d\n", WEXITSTATUS (st)); + break; + } + + if (WIFSTOPPED (st)) + { + if (WSTOPSIG (st) == SIGTRAP) + { + struct timeval tv; + long secs; + long usecs; + char tbuf[1024]; + int printcalls = (getenv ("LOG_CALLS") != NULL); + int printthis = 0; + int printregs = (getenv ("LOG_REGS") != NULL); + + struct user_regs_struct r; + u32 call; + + gettimeofday (&tv, NULL); + secs = tv.tv_sec - starttv.tv_sec; + usecs = tv.tv_usec - starttv.tv_usec; + if (usecs < 0) + { + usecs += 1000000; + secs -= 1; + } + snprintf (tbuf, sizeof tbuf, "%ld.%06ld", secs, usecs); + + if (ptrace (PTRACE_GETREGS, pid, 0, &r) < 0) + { + fprintf (stderr, "ptrace:getregs: %s\n", strerror (errno)); + exit (1); + } + call = r.orig_eax; + /*printthis = call == SYS_ioctl;*/ + + if (state == INBOUND) + { + if (printcalls || printthis) + { + if ((call >= 0) && (call < callmax) && (callinfo[call].name != NULL)) + fprintf (stderr, "%s()", callinfo[call].name); + else + fprintf (stderr, "syscall(%u)", call); + } + } + + if (state == OUTBOUND) + { + if ((call < 0) || (call > callmax) || (callinfo[call].name == NULL)) + { + fprintf (stderr, "= 0x%08lx\n", (unsigned long) r.eax); + } + else + { + if (callinfo[call].ptrval) + { + if (printcalls || printthis) + fprintf (stderr, " = 0x%08lx\n", r.eax); + } + else + { + long rv = r.eax; + if (rv < 0) + { + if (printcalls || printthis) + fprintf (stderr, " = -1 (%s)\n", strerror (-rv)); + } + else + { + if (printcalls || printthis) + fprintf (stderr, " = %lu\n", rv); + } + } + } + } + + if ((call == SYS_ioctl) && ((state == OUTBOUND) || getenv ("LOG_INBOUND"))) + { + unsigned int len = 16; + unsigned char buf[65536]; + + unsigned long fd = r.ebx; + + unsigned long ioc = r.ecx; + unsigned int iocdir = _IOC_DIR(ioc); + unsigned char ioctype = _IOC_TYPE(ioc); + unsigned int iocnr = _IOC_NR(ioc); + unsigned int iocsize = _IOC_SIZE(ioc); + char *iocdirname; + + unsigned long arg = r.edx; + + switch (iocdir) + { + case _IOC_READ: iocdirname = "r"; break; + case _IOC_WRITE: iocdirname = "w"; break; + case _IOC_READ|_IOC_WRITE: iocdirname = "rw"; break; + default: iocdirname = "none"; break; + } + + fprintf (stderr, "%s: ioctl(%ld, _IOC(\"%s\",'%c',0x%02x,0x%02x), 0x%08lx)", tbuf, fd, iocdirname, ioctype, iocnr, iocsize, arg); + if (state == OUTBOUND) + fprintf (stderr, " = %ld\n", r.eax); + if (getenv ("LOG_INBOUND")) + fprintf (stderr, "\n"); + + if (_IOC_SIZE(ioc) > len) + len = _IOC_SIZE(ioc); + if (len > sizeof buf) + len = sizeof buf; + + if (printregs) + fprintf (stderr, " ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx ebp=%08lx eax=%08lx ds=%04x __ds=%04x es=%04x __es=%04x fs=%04x __fs=%04x gs=%04x __gs=%04x orig_eax=%08lx eip=%08lx cs=%04x __cs=%04x eflags=%08lx esp=%08lx ss=%04x __ss=%04x\n", r.ebx, r.ecx, r.edx, r.esi, r.edi, r.ebp, r.eax, r.ds, r.__ds, r.es, r.__es, r.fs, r.__fs, r.gs, r.__gs, r.orig_eax, r.eip, r.cs, r.__cs, r.eflags, r.esp, r.ss, r.__ss); + + copyout (buf, len, pid, r.edx); + + if ((ioctype == 'm') && (iocnr == 0) && (iocsize == sizeof (struct uioctl_t))) + { + /* megaraid_mbox-style ioctl */ + struct uioctl_t *uio = (struct uioctl_t *) buf; + mraid_passthru_t p = uio->pthru; + unsigned long datalen; + int_mbox_t *m = (int_mbox_t *) uio->mbox; + + fprintf (stderr, " uio:\tinlen %u, outlen %u, { op %02x, subop %02x, adap %04x, buf %08lx, len %u }, data %08lx\n", uio->inlen, uio->outlen, uio->ui.fcs.opcode, uio->ui.fcs.subopcode, uio->ui.fcs.adapno, (unsigned long) uio->ui.fcs.buffer, uio->ui.fcs.length, (unsigned long) uio->data); + dumpbytes (stderr, uio, sizeof (*uio), uio, "uioc"); + fprintf (stderr, " mbox:\tcmd %02x, cmdid %02x, op %02x, subop %02x, lba %08x, xfer %08x, ldrv %02x, numsge %u, busy %u, nstatus %u, status %u\n", m->cmd, m->cmdid, m->opcode, m->subopcode, m->lba, m->xferaddr, m->logdrv, m->rsvd[0], m->rsvd[2], m->numstatus, m->status); + dumpbytes (stderr, uio->mbox, sizeof (uio->mbox), uio->mbox, "mbox"); + fprintf (stderr, " pass:\ttimeout %u, ars %u, isldrv %u, ldrv %u, chan %u, targ %02x, qtag %u, qact %u, numsge %u, scsistat %u\n", p.timeout, p.ars, p.islogical, p.logdrv, p.channel, p.target, p.queuetag, p.queueaction, p.numsge, p.scsistatus); + dumpbytes (stderr, &p.cdb, p.cdblen, &p.cdb, "cdb"); + dumpbytes (stderr, &p.reqsensearea, p.reqsenselen, &p.reqsensearea, "rqsense"); + dumpbytes (stderr, &uio->pthru, sizeof (uio->pthru), &uio->pthru, "pass"); + if (p.dataxferaddr && p.dataxferlen) + { + unsigned char data[4096]; + unsigned long len = p.dataxferlen; + if (len > sizeof data) + len = sizeof data; + copyout (data, len, pid, p.dataxferaddr); + dumpbytes (stderr, data, len, (void *) p.dataxferaddr, "parm"); + } + + datalen = uio->ui.fcs.length; + if (datalen < uio->outlen) + datalen = uio->outlen; + if (datalen > sizeof buf) + datalen = sizeof buf; + if (datalen < 16) + datalen = 16; + if (datalen && uio->data) + { +// if ((state == INBOUND) && (datalen > uio->inlen)) +// datalen = uio->inlen; +// else if ((state == OUTBOUND) && (datalen > uio->outlen)) +// datalen = uio->outlen; +// if (datalen) +// { + copyout (buf, datalen, pid, (unsigned long) uio->data); + dumpbytes (stderr, buf, datalen, uio->data, "data"); +// } + } + } + else if ((ioctype == 'M') && (iocnr == 1) && (iocsize == sizeof (struct megasas_iocpacket))) + { + /* megaraid_sas-style ioctl */ + struct megasas_iocpacket *iocp = (struct megasas_iocpacket *) buf; + struct megasas_header *mh = &(iocp->frame.hdr); + int k; + u8 cmd; + struct megasas_sge32 *sge = (struct megasas_sge32 *) ((u32) (&iocp->frame) + iocp->sgl_off); + int log = 1; + + cmd = mh->cmd; + if (cmd == MFI_CMD_DCMD) + { + struct megasas_dcmd_frame *f = (struct megasas_dcmd_frame *) mh; + + if ((getenv ("LOG_OPCODE") != 0) && (strtoul (getenv ("LOG_OPCODE"), NULL, 0) != f->opcode)) + { + log = 0; + } + +/* Lie like a rug. */ +if ((f->opcode == 0x02020000) && (state == OUTBOUND)) +{ + u32 sgbase = sge[0].phys_addr; + size_t sglen = sge[0].length; + struct mega_physical_disk_info_sas disk; + + if (sglen > sizeof disk) + sglen = sizeof disk; + + copyout (&disk, sglen, pid, sgbase); + +//if (!((disk.device_id == 16) || (disk.device_id == 15))) +// log = 0; + + copyin (&disk, sglen, pid, sgbase); +} + +if ((f->opcode == 0x04010000) && (state == OUTBOUND)) +{ + u32 sgbase = sge[0].phys_addr; + size_t sglen = sge[0].length; + u8 config[4096]; + + if (sglen > sizeof config) + sglen = sizeof config; + + copyout (&config, sglen, pid, sgbase); + + { + struct mega_array_header_sas *header = (struct mega_array_header_sas *) config; + struct mega_array_span_def_sas *span = (struct mega_array_span_def_sas *) (header + 1); + struct mega_array_disk_def_sas *disk = (struct mega_array_disk_def_sas *) (span + header->num_span_defs); + struct mega_array_hotspare_def_sas *hotspare = (struct mega_array_hotspare_def_sas *) (disk + header->num_disk_defs); + int k; + + for (k = 0; k < header->num_disk_defs; ++k) + { +// disk[k].state = 0xffff; + } + } + + copyin (&config, sglen, pid, sgbase); +} + +if ((f->opcode == 0x05010000) && (state == OUTBOUND)) +{ + u32 sgbase = sge[0].phys_addr; + size_t sglen = sge[0].length; + struct mega_battery_state_sas bs; + + if (sglen > sizeof bs) + sglen = sizeof bs; + + copyout (&bs, sglen, pid, sgbase); + + if (getenv ("BATTERY_X")) + bs.type = strtoul (getenv ("BATTERY_X"), NULL, 0); + if (getenv ("BATTERY_Y")) + bs.foo = strtoul (getenv ("BATTERY_Y"), NULL, 0); + bs.over_charged = 1; + + copyin (&bs, sglen, pid, sgbase); +} + + if (log) + { + fprintf (stderr, " host %d, off 0x%04x, count %d, sense_off 0x%08x, sense_len 0x%08x\n", iocp->host_no, iocp->sgl_off, iocp->sge_count, iocp->sense_off, iocp->sense_len); + fprintf (stderr, " DCMD: cmd_status %d, sge_count %d, context 0x%08x, flags 0x%04x, timeout %d, data_xfer_len 0x%x, opcode 0x%08x\n", f->cmd_status, f->sge_count, f->context, f->flags, f->timeout, f->data_xfer_len, f->opcode); + dumpbytes (stderr, &f->mbox, sizeof (f->mbox), &f->mbox, "mbox"); + } + } + else if (cmd == MFI_CMD_PD_SCSI_IO) + { + struct megasas_pthru_frame *f = (struct megasas_pthru_frame *) mh; + + fprintf (stderr, " host %d, off 0x%04x, count %d, sense_off 0x%08x, sense_len 0x%08x\n", iocp->host_no, iocp->sgl_off, iocp->sge_count, iocp->sense_off, iocp->sense_len); + fprintf (stderr, " SCSI: cmd_status %d, sge_count %d, context 0x%08x, flags 0x%04x, timeout %d, data_xfer_len 0x%x\n", f->cmd_status, f->sge_count, f->context, f->flags, f->timeout, f->data_xfer_len); + fprintf (stderr, " : scsi_status %d, target_id 0x%02x, lun %d, sense_len %d, sense_lo 0x%08x, sense_hi 0x%08x\n", f->scsi_status, f->target_id, f->lun, f->sense_len, f->sense_buf_phys_addr_lo, f->sense_buf_phys_addr_hi); + + dumpbytes (stderr, &f->cdb, f->cdb_len, &f->cdb, "cdb"); + } + else + { + fprintf (stderr, " host %d, off 0x%04x, count %d, sense_off 0x%08x, sense_len 0x%08x\n", iocp->host_no, iocp->sgl_off, iocp->sge_count, iocp->sense_off, iocp->sense_len); + dumpbytes (stderr, buf, len, (void *) r.edx, NULL); + } + if (log) + { + for (k = 0; k < iocp->sge_count; ++k) + { + u32 sgbase = sge[k].phys_addr; + size_t sglen = sge[k].length; + char sgname[16]; + char sgdata[4096]; + + snprintf (sgname, sizeof sgname, "sg%d", k); + fprintf (stderr, " %s at 0x%08x [0x%x]:\n", sgname, sgbase, sglen); + if (sglen > sizeof sgdata) + sglen = sizeof sgdata; + copyout (sgdata, sglen, pid, sgbase); + dumpbytes (stderr, sgdata, sglen, (void *) sgbase, sgname); + } + } + } + else + { + dumpbytes (stderr, buf, len, (void *) r.edx, NULL); + } + fprintf (stderr, "\n"); + } + + switch (state) + { + static u32 lasteip = 0; + + case UNTRACED: + /* We don't know whether we were inbound or outbound on the first signal; this + appears to differ between kernels. So we defer until we see the same eip in + two successive traps, at which point we know we were outbound, so the next + trap is inbound. */ + if (lasteip == r.eip) + state = INBOUND; + lasteip = r.eip; + break; + case INBOUND: state = OUTBOUND; break; + case OUTBOUND: state = INBOUND; break; + } + + if (ptrace (PTRACE_SYSCALL, pid, 0, 0) < 0) + { + fprintf (stderr, "ptrace:syscall: %s\n", strerror (errno)); + exit (1); + } + } + } + else + { + fprintf (stderr, "running\n"); + } + } + + exit (0); +} + + diff --git a/src/modepage.c b/src/modepage.c new file mode 100644 index 0000000..0a89cfd --- /dev/null +++ b/src/modepage.c @@ -0,0 +1,412 @@ +/* + * Incomplete code for handling mode sense data. Not used. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include "megactl.h" +#include "megaioctl.h" +#include "modepage.h" +#include "dumpbytes.h" + +#include +#include +#include + + +#if 0 +static char *logPageType[] = { + /* 0 */ "supported log pages", + /* 1 */ "buffer over-run/under-run", + /* 2 */ "write error counter", + /* 3 */ "read error counter", + /* 4 */ "read reverse error counter", + /* 5 */ "verify error counter", + /* 6 */ "non-medium error", + /* 7 */ "last n error events", + /* 8 */ "format status", + /* 9 */ NULL, + /* a */ NULL, + /* b */ "last n deferred errors os asynchronous events", + /* c */ "sequential-access device", + /* d */ "temperature", + /* e */ "start-stop cycle counter", + /* f */ "application client", + /* 10 */ "self-test results", + /* 11 */ "DTD status", + /* 12 */ "TapeAlert response", + /* 13 */ "requested recover", + /* 14 */ "device statistics", + /* 15 */ NULL, + /* 16 */ NULL, + /* 17 */ "non-volatile cache", + /* 18 */ "protocol specific port", + /* 19 */ NULL, + /* 1a */ NULL, + /* 1b */ NULL, + /* 1c */ NULL, + /* 1d */ NULL, + /* 1e */ NULL, + /* 1f */ NULL, + /* 20 */ NULL, + /* 21 */ NULL, + /* 22 */ NULL, + /* 23 */ NULL, + /* 24 */ NULL, + /* 25 */ NULL, + /* 26 */ NULL, + /* 27 */ NULL, + /* 28 */ NULL, + /* 29 */ NULL, + /* 2a */ NULL, + /* 2b */ NULL, + /* 2c */ NULL, + /* 2d */ NULL, + /* 2e */ "TapeAlert", + /* 2f */ "informational exceptions", + /* 30 */ "vendor specific", + /* 31 */ "vendor specific", + /* 32 */ "vendor specific", + /* 33 */ "vendor specific", + /* 34 */ "vendor specific", + /* 35 */ "vendor specific", + /* 36 */ "vendor specific", + /* 37 */ "vendor specific", + /* 38 */ "vendor specific", + /* 39 */ "vendor specific", + /* 3a */ "vendor specific", + /* 3b */ "vendor specific", + /* 3c */ "vendor specific", + /* 3d */ "vendor specific", + /* 3e */ "vendor specific", + /* 3f */ NULL, +}; + + +char *friendlySize (uint64_t b, char *unit) +{ + static char *suffix[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi", }; + int k; + static char bytes[128]; + + for (k = 0; (b >= 1024) && (k < sizeof (suffix) / sizeof (suffix[0]) - 1); ++k, b /= 1024) + ; + snprintf (bytes, sizeof bytes, "%3llu%s%s", b, suffix[k], unit); + return bytes; +} + + +uint32_t blocksToGB (uint32_t blocks) +{ + return (long) (((uint64_t) blocks) * 512 / 1000000000); +} + + +uint32_t blocksToGiB (uint32_t blocks) +{ + return blocks / 2 / 1024 / 1024; +} + + +static uint64_t extractInt64 (void *u, size_t len) +{ + uint64_t x; + uint8_t *v; + + for (x = 0, v = u; len > 0; --len, ++v) + x = (x << 8) + *v; + return x; +} + + +int parseLogPage (void *log, size_t len, struct logData *x) +{ + struct logPageHeader *h = log; + void *u = log + sizeof (*h); + struct logParameterHeader *p; + size_t pageLen; + + memset (x, 0, sizeof (*x)); + + if (len < sizeof (*h)) + return -1; + pageLen = ntohs (h->length) + sizeof (*h); + if (len > pageLen) + len = pageLen; + len -= sizeof (*h); + + x->h = *h; + x->h.length = pageLen; + + while (len >= sizeof (*p)) + { + uint16_t code; + uint64_t e; + + p = u; + if (p->length + sizeof (*p) > len) + break; + len -= sizeof (*p); + u += sizeof (*p); + + code = ntohs (p->parameter_code); + switch (h->page_code) + { + case 0x02: + case 0x03: + case 0x04: + case 0x05: + e = extractInt64 (u, p->length); + switch (code) + { + case 0x0000: x->u.error.corrected = e; break; + case 0x0001: x->u.error.delayed = e; break; + case 0x0002: x->u.error.reread = e; break; + case 0x0003: x->u.error.total_corrected = e; break; + case 0x0004: x->u.error.total_algorithm = e; break; + case 0x0005: x->u.error.total_bytes = e; break; + case 0x0006: x->u.error.total_uncorrected = e; break; + default: break; + } + break; + case 0x0d: + switch (code) + { + case 0x0000: x->u.temperature.current = ((uint8_t *) u)[1]; break; + case 0x0001: x->u.temperature.reference = ((uint8_t *) u)[1]; break; + default: break; + } + break; + case 0x0e: + switch (code) + { + case 0x0001: + strncpy (x->u.startstop.manufacture_year, u, sizeof (x->u.startstop.manufacture_year) - 1); + x->u.startstop.manufacture_year[sizeof (x->u.startstop.manufacture_year) - 1] = '\0'; + ntrim (x->u.startstop.manufacture_year); + strncpy (x->u.startstop.manufacture_week, u + 4, sizeof (x->u.startstop.manufacture_week) - 1); + x->u.startstop.manufacture_week[sizeof (x->u.startstop.manufacture_week) - 1] = '\0'; + ntrim (x->u.startstop.manufacture_week); + break; + case 0x0002: + strncpy (x->u.startstop.accounting_year, u, sizeof (x->u.startstop.accounting_year) - 1); + x->u.startstop.accounting_year[sizeof (x->u.startstop.accounting_year) - 1] = '\0'; + ntrim (x->u.startstop.accounting_year); + strncpy (x->u.startstop.accounting_week, u + 4, sizeof (x->u.startstop.accounting_week) - 1); + x->u.startstop.accounting_week[sizeof (x->u.startstop.accounting_week) - 1] = '\0'; + ntrim (x->u.startstop.accounting_week); + break; + case 0x0003: + x->u.startstop.recommended_starts = ntohl (*((uint32_t *) u)); + break; + case 0x0004: + x->u.startstop.accumulated_starts = ntohl (*((uint32_t *) u)); + break; + default: + break; + } + break; + case 0x10: + if ((code < 1) || (code > sizeof (x->u.selftest.entry) / sizeof (x->u.selftest.entry[0]))) + break; + if (p->length != sizeof (x->u.selftest.entry[0]) - sizeof (*p)) + break; + --code; + x->u.selftest.entry[code] = *((struct selfTestLogParameter *) p); + x->u.selftest.entry[code].h.parameter_code = code; + x->u.selftest.entry[code].timestamp = ntohs (x->u.selftest.entry[code].timestamp); + x->u.selftest.entry[code].lba = extractInt64 (&x->u.selftest.entry[code].lba, sizeof (x->u.selftest.entry[code].lba)); + break; + } + + len -= p->length; + u += p->length; + } + + /* flag any problems */ + switch (h->page_code) + { + case 0x02: + case 0x03: + case 0x04: + case 0x05: + if (x->u.error.total_uncorrected) + x->problem = 1; + break; + case 0x0d: + if (x->u.temperature.reference && (x->u.temperature.reference != 0xff) && (x->u.temperature.current >= x->u.temperature.reference)) + x->problem = 1; + break; + } + + return 0; +} +#endif + + +void dumpModePage (FILE *f, struct modeData *x, void *mode, size_t len, int verbosity) +{ + struct logPageHeader *h = log; + void *u = log + sizeof (*h); + struct logParameterHeader *p; + size_t pageLen; + int k; + + switch (x->h.page_code) + { + case 0x02: + case 0x03: + case 0x04: + case 0x05: + switch (x->h.page_code) + { + case 0x02: fprintf (f, " write errors:"); break; + case 0x03: fprintf (f, " read errors:"); break; + case 0x04: fprintf (f, " read/rev errors:"); break; + case 0x05: fprintf (f, " verify errors:"); break; + } + fprintf (f, " corr:%-6s", friendlySize (x->u.error.corrected, "")); + fprintf (f, " delay:%-6s", friendlySize (x->u.error.delayed, "")); + switch (x->h.page_code) + { + case 0x02: fprintf (f, " rewrit:%-6s", friendlySize (x->u.error.reread, "")); break; + case 0x03: fprintf (f, " reread:%-6s", friendlySize (x->u.error.reread, "")); break; + case 0x04: fprintf (f, " reread:%-6s", friendlySize (x->u.error.reread, "")); break; + case 0x05: fprintf (f, " revrfy:%-6s", friendlySize (x->u.error.reread, "")); break; + } + fprintf (f, " tot/corr:%-6s", friendlySize (x->u.error.total_corrected, "")); + if (verbosity > 1) + fprintf (f, " tot/alg:%-6s", friendlySize (x->u.error.total_algorithm, "")); + if (verbosity > 1) + fprintf (f, " tot/bytes:%-6s", friendlySize (x->u.error.total_bytes, "B")); + fprintf (f, " tot/uncorr:%-6s", friendlySize (x->u.error.total_uncorrected, "")); + fprintf (f, "\n"); + break; + case 0x0d: + fprintf (f, " temperature: current:%uC threshold:%uC%s\n", x->u.temperature.current, x->u.temperature.reference, x->problem ? " warning:temperature threshold exceeded" : ""); + break; + case 0x0e: + fprintf (f, " "); + if (strlen (x->u.startstop.manufacture_year) && strlen (x->u.startstop.manufacture_week)) + fprintf (f, " manufactured:%s/%s", x->u.startstop.manufacture_year, x->u.startstop.manufacture_week); + if (strlen (x->u.startstop.accounting_year) && strlen (x->u.startstop.accounting_week)) + fprintf (f, " accounting:%s/%s", x->u.startstop.accounting_year, x->u.startstop.accounting_week); + fprintf (f, " starts:%d/%d", x->u.startstop.accumulated_starts, x->u.startstop.recommended_starts); + fprintf (f, "\n"); + break; + case 0x10: + for (k = 0; k < sizeof (x->u.selftest.entry) / sizeof (x->u.selftest.entry[0]); ++k) + { + struct selfTestLogParameter *t = &x->u.selftest.entry[k]; + if (t->self_test_code || t->self_test_results || t->timestamp || t->number || t->lba) + { + char *test; + char *result; + + switch (t->self_test_code) + { + case SCSI_SELFTEST_DEFAULT: test = "default"; break; + case SCSI_SELFTEST_BACKGROUND_SHORT: test = "bg short"; break; + case SCSI_SELFTEST_BACKGROUND_LONG: test = "bg long"; break; + case SCSI_SELFTEST_BACKGROUND_ABORT: test = "bg aborted"; break; + case SCSI_SELFTEST_FOREGROUND_SHORT: test = "fg short"; break; + case SCSI_SELFTEST_FOREGROUND_LONG: test = "fg long"; break; + default: test = "unknown"; break; + } + switch (t->self_test_results) + { + case 0x0: result = "completed without error"; break; + case 0x1: result = "aborted via send diagnostic"; break; + case 0x2: result = "aborted via other method"; break; + case 0x3: result = "unable to complete"; break; + case 0x4: result = "failed in unknown segment"; break; + case 0x5: result = "failed in segment 1"; break; + case 0x6: result = "failed in segment 2"; break; + case 0x7: result = "failed in other segment"; break; + case 0xf: result = "in progress"; break; + default: result = "unknown result"; break; + } + fprintf (f, " %2d: timestamp %4ud%02uh: %10s %-30s seg:%u lba:%-8lld sk:%u asc:%u ascq:%u vs:%u\n", k, t->timestamp / 24, t->timestamp % 24, test, result, t->number, t->lba, t->sense_key, t->additional_sense_code, t->additional_sense_code_qualifier, t->vendor_specific); + } + } + break; + default: + break; + } + + if (!(verbosity > 2)) + return; + + if (len < sizeof (*h)) + return; + pageLen = ntohs (h->length) + sizeof (*h); + if (len > pageLen) + len = pageLen; + len -= sizeof (*h); + + switch (h->page_code) + { + case 0x00: + fprintf (f, " %s:", logPageType[h->page_code]); + if (verbosity > 1) + fprintf (f, "\n"); + for (k = len; k > 0; --k, ++u) + { + uint8_t code = *((unsigned char *) u); + + if (verbosity > 1) + { + char *name; + if ((code < sizeof logPageType / sizeof (logPageType[0])) && logPageType[code]) + name = logPageType[code]; + else + name = "unknown log page"; + fprintf (f, " %02x %s\n", code, name); + } + else + fprintf (f, " %02x", code); + } + if (verbosity <= 1) + fprintf (f, "\n"); + return; + default: + fprintf (f, " log page %02x, length %u%s\n", h->page_code, ntohs (h->length), len < pageLen - sizeof (*h) ? " warning: truncated" : ""); + break; + } + while (len >= sizeof (*p)) + { + uint16_t code; + + p = u; + if (p->length + sizeof (*p) > len) + break; + len -= sizeof (*p); + u += sizeof (*p); + + code = ntohs (p->parameter_code); + fprintf (f, " param %04x, du %u, ds %u, tsd %u, etc %u, tmc %u, lbin %u, lp %u, length %u\n", code, p->du, p->ds, p->tsd, p->etc, p->tmc, p->lbin, p->lp, p->length); + dumpbytes (f, u, p->length, u, "param"); + + len -= p->length; + u += p->length; + } +} + + diff --git a/src/modepage.h b/src/modepage.h new file mode 100644 index 0000000..edfcb56 --- /dev/null +++ b/src/modepage.h @@ -0,0 +1,75 @@ +#ifndef _MODEPAGE_H +#define _MODEPAGE_H +/* + * Definitions for unused mode page code. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include + + +struct modePage0Header +{ +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder (thanks, Schily) */ + uint8_t page_code:6; + uint8_t spf:1; + uint8_t ps:1; +#else /* Motorola byteorder */ + uint8_t ps:1; + uint8_t spf:1; + uint8_t page_code:6; +#endif + uint8_t length; +} __attribute__ ((packed)); + +struct modeSubPageHeader +{ +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder (thanks, Schily) */ + uint8_t page_code:6; + uint8_t spf:1; + uint8_t ps:1; +#else /* Motorola byteorder */ + uint8_t ps:1; + uint8_t spf:1; + uint8_t page_code:6; +#endif + uint8_t subpage_code; + uint16_t length; +} __attribute__ ((packed)); + +struct modeData +{ + union + { + struct modePage0Header error; + struct modeSubPageHeader selftest; + } u; +} __attribute__ ((packed)); + + +#if 0 +extern int parseLogPage (void *log, size_t len, struct logData *x); +#endif +extern void dumpModePage (FILE *f, struct modeData *x, void *mode, size_t len, int verbosity); + +#endif diff --git a/src/ntrim.c b/src/ntrim.c new file mode 100644 index 0000000..a6a2b6c --- /dev/null +++ b/src/ntrim.c @@ -0,0 +1,45 @@ +/* + * Little string-trimming function. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include "ntrim.h" + +void ntrim (char *s) +{ + char *t; + size_t len = strlen (s); + + for (t = s + len - 1; (t >= s) && isspace (*t); --t) + *t = '\0'; + for (t = s; isspace (*t); ++t) + ; + if (t > s) + { + for ( ; *t; ++t, ++s) + *s = *t; + *s = *t; + } +} + diff --git a/src/ntrim.h b/src/ntrim.h new file mode 100644 index 0000000..012082e --- /dev/null +++ b/src/ntrim.h @@ -0,0 +1,27 @@ +#ifndef _NTRIM_H +#define _NTRIM_H +/* + * Definitions for little string trimmer function. + * + * Copyright (c) 2007 by Jefferson Ogata + */ + +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +extern void ntrim (char *s); + +#endif diff --git a/src/schily/allocax.h b/src/schily/allocax.h new file mode 100644 index 0000000..320be47 --- /dev/null +++ b/src/schily/allocax.h @@ -0,0 +1,69 @@ +/* @(#)allocax.h 1.3 03/07/15 Copyright 2002 J. Schilling */ +/* + * Definitions for users of alloca() + * + * Important: #include this directly after + * and before any other include file. + * See comment in _AIX part below. + * + * Copyright (c) 2002 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifndef _ALLOCAX_H +#define _ALLOCAX_H + +#ifdef __GNUC__ +# ifndef alloca +# define alloca(s) __builtin_alloca(s) +# endif +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + /* + * Indent so pre-ANSI compilers will ignore it + * + * Some versions of AIX may require this to be + * first in the file and only preceded by + * comments and preprocessor directives/ + */ + #pragma alloca +# else +# ifndef alloca + /* + * predefined by HP cc +Olibcalls + */ +# ifdef PROTOTYPES + extern void *alloca(); +# else + extern char *alloca(); +# endif +# endif +# endif +# endif +# endif +#endif + + +#endif /* _ALLOCAX_H */ diff --git a/src/schily/btorder.h b/src/schily/btorder.h new file mode 100644 index 0000000..946c592 --- /dev/null +++ b/src/schily/btorder.h @@ -0,0 +1,120 @@ +/* @(#)btorder.h 1.16 03/06/15 Copyright 1996 J. Schilling */ +/* + * Definitions for Bit and Byte ordering + * + * Copyright (c) 1996 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifndef _BTORDER_H +#define _BTORDER_H + +#ifndef _INCL_SYS_TYPES_H +#include /* try to load isa_defs.h on Solaris */ +#define _INCL_SYS_TYPES_H +#endif + +#ifndef _MCONFIG_H +#include /* load bit/byte-oder from xmconfig.h*/ +#endif + +/* + * Convert bit-order definitions from xconfig.h into our values + * and verify them. + */ +#if defined(HAVE_C_BITFIELDS) && \ + defined(BITFIELDS_LTOH) +#define _BIT_FIELDS_LTOH +#endif + +#if defined(HAVE_C_BITFIELDS) && \ + defined(BITFIELDS_HTOL) +#define _BIT_FIELDS_HTOL +#endif + +#if defined(HAVE_C_BITFIELDS) && \ + !defined(BITFIELDS_HTOL) +#define BITFIELDS_LTOH +#define _BIT_FIELDS_LTOH +#endif + +#if defined(_BIT_FIELDS_LTOH) && defined(_BIT_FIELDS_HTOL) +/* + * #error will not work for all compilers (e.g. sunos4) + * The following line will abort compilation on all compilers + * if none of the above is defines. And that's what we want. + */ +error Only one of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL may be defined +#endif + + +/* + * Convert byte-order definitions from xconfig.h into our values + * and verify them. + * Note that we cannot use the definitions _LITTLE_ENDIAN and _BIG_ENDIAN + * because they are used on IRIX-6.5 with different meaning. + */ +#if defined(HAVE_C_BIGENDIAN) && \ + !defined(WORDS_BIGENDIAN) +#define WORDS_LITTLEENDIAN +/*#define _LITTLE_ENDIAN*/ +#endif + +#if defined(HAVE_C_BIGENDIAN) && \ + defined(WORDS_BIGENDIAN) +#undef WORDS_LITTLEENDIAN +/*#define _BIG_ENDIAN*/ +#endif + +#if defined(_BIT_FIELDS_LTOH) || defined(_BIT_FIELDS_HTOL) +/* + * Bitorder is already known. + */ +#else +/* + * Bitorder not yet known. + */ +# if defined(sun3) || defined(mc68000) || \ + defined(sun4) || defined(__sparc) || defined(sparc) || \ + defined(__hppa) || defined(_ARCH_PPC) || defined(_IBMR2) +# define _BIT_FIELDS_HTOL +# endif + +# if defined(__sgi) && defined(__mips) +# define _BIT_FIELDS_HTOL +# endif + +# if defined(__i386__) || defined(__i386) || defined(i386) || \ + defined(__ia64__) || defined(__ia64) || defined(ia64) || \ + defined(__alpha__) || defined(__alpha) || defined(alpha) || \ + defined(__arm__) || defined(__arm) || defined(arm) +# define _BIT_FIELDS_LTOH +# endif + +# if defined(__ppc__) || defined(ppc) || defined(__ppc) || \ + defined(__PPC) || defined(powerpc) || defined(__powerpc__) + +# if defined(__BIG_ENDIAN__) +# define _BIT_FIELDS_HTOL +# else +# define _BIT_FIELDS_LTOH +# endif +# endif +#endif + +#endif /* _BTORDER_H */ diff --git a/src/schily/btorder.h.endian b/src/schily/btorder.h.endian new file mode 100644 index 0000000..b052043 --- /dev/null +++ b/src/schily/btorder.h.endian @@ -0,0 +1,119 @@ +/* @(#)btorder.h 1.16 03/06/15 Copyright 1996 J. Schilling */ +/* + * Definitions for Bit and Byte ordering + * + * Copyright (c) 1996 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifndef _BTORDER_H +#define _BTORDER_H + +#ifndef _INCL_SYS_TYPES_H +#include /* try to load isa_defs.h on Solaris */ +#define _INCL_SYS_TYPES_H +#endif + +#ifndef _MCONFIG_H +#include /* load bit/byte-oder from xmconfig.h*/ +#endif + +/* + * Convert bit-order definitions from xconfig.h into our values + * and verify them. + */ +#if defined(HAVE_C_BITFIELDS) && \ + defined(BITFIELDS_LTOH) +#define _BIT_FIELDS_LTOH +#endif + +#if defined(HAVE_C_BITFIELDS) && \ + defined(BITFIELDS_HTOL) +#define _BIT_FIELDS_HTOL +#endif + +#if defined(HAVE_C_BITFIELDS) && \ + !defined(BITFIELDS_HTOL) +#define BITFIELDS_LTOH +#define _BIT_FIELDS_LTOH +#endif + +#if defined(_BIT_FIELDS_LTOH) && defined(_BIT_FIELDS_HTOL) +/* + * #error will not work for all compilers (e.g. sunos4) + * The following line will abort compilation on all compilers + * if none of the above is defines. And that's what we want. + */ +error Only one of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL may be defined +#endif + + +/* + * Convert byte-order definitions from xconfig.h into our values + * and verify them. + * Note that we cannot use the definitions _LITTLE_ENDIAN and _BIG_ENDIAN + * because they are used on IRIX-6.5 with different meaning. + */ +#if defined(HAVE_C_BIGENDIAN) && \ + !defined(WORDS_BIGENDIAN) +#define WORDS_LITTLEENDIAN +/*#define _LITTLE_ENDIAN*/ +#endif + +#if defined(HAVE_C_BIGENDIAN) && \ + defined(WORDS_BIGENDIAN) +#undef WORDS_LITTLEENDIAN +/*#define _BIG_ENDIAN*/ +#endif + +#if defined(_BIT_FIELDS_LTOH) || defined(_BIT_FIELDS_HTOL) +/* + * Bitorder is already known. + */ +#else +/* + * Bitorder not yet known. + */ +# if defined(sun3) || defined(mc68000) || \ + defined(sun4) || defined(__sparc) || defined(sparc) || \ + defined(__hppa) || defined(_ARCH_PPC) || defined(_IBMR2) +# define _BIT_FIELDS_HTOL +# endif + +# if defined(__sgi) && defined(__mips) +# define _BIT_FIELDS_HTOL +# endif + +# if defined(__i386__) || defined(__i386) || defined(i386) || \ + defined(__alpha__) || defined(__alpha) || defined(alpha) || \ + defined(__arm__) || defined(__arm) || defined(arm) +# define _BIT_FIELDS_LTOH +# endif + +# if defined(__ppc__) || defined(ppc) || defined(__ppc) || \ + defined(__PPC) || defined(powerpc) || defined(__powerpc__) + +# if defined(__BIG_ENDIAN__) +# define _BIT_FIELDS_HTOL +# else +# define _BIT_FIELDS_LTOH +# endif +# endif +#endif + +#endif /* _BTORDER_H */ diff --git a/src/schily/ccomdefs.h b/src/schily/ccomdefs.h new file mode 100644 index 0000000..baba8ae --- /dev/null +++ b/src/schily/ccomdefs.h @@ -0,0 +1,67 @@ +/* @(#)ccomdefs.h 1.3 03/06/15 Copyright 2000 J. Schilling */ +/* + * Various compiler dependant macros. + * + * Copyright (c) 2000 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _CCOMDEFS_H +#define _CCOMDEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Compiler-dependent macros to declare that functions take printf-like + * or scanf-like arguments. They are defined to nothing for versions of gcc + * that are not known to support the features properly (old versions of gcc-2 + * didn't permit keeping the keywords out of the application namespace). + */ +#if __GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 7 + +#define __printflike__(fmtarg, firstvararg) +#define __printf0like__(fmtarg, firstvararg) +#define __scanflike__(fmtarg, firstvararg) + +#else /* We found GCC that supports __attribute__ */ + +#define __printflike__(fmtarg, firstvararg) \ + __attribute__((__format__(__printf__, fmtarg, firstvararg))) +#define __printf0like__(fmtarg, firstvararg) \ + __attribute__((__format__(__printf0__, fmtarg, firstvararg))) + +/* + * FreeBSD GCC implements printf0 that allows the format string to + * be a NULL pointer. + */ +#if __FreeBSD_cc_version < 300001 +#undef __printf0like__ +#define __printf0like__ __printflike__ +#endif + +#define __scanflike__(fmtarg, firstvararg) \ + __attribute__((__format__(__scanf__, fmtarg, firstvararg))) + +#endif /* GNUC */ + +#ifdef __cplusplus +} +#endif + +#endif /* _CCOMDEFS_H */ diff --git a/src/schily/deflts.h b/src/schily/deflts.h new file mode 100644 index 0000000..bebaff6 --- /dev/null +++ b/src/schily/deflts.h @@ -0,0 +1,76 @@ +/* @(#)deflts.h 1.6 02/08/26 Copyright 1997 J. Schilling */ +/* + * Definitions for reading program defaults. + * + * Copyright (c) 1997 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _DEFLTS_H +#define _DEFLTS_H + +#ifndef _MCONFIG_H +#include +#endif +#ifndef _PROTOTYP_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEFLT "/etc/default" + +/* + * cmd's to defltcntl() + */ +#define DC_GETFLAGS 0 /* Get actual flags */ +#define DC_SETFLAGS 1 /* Set new flags */ + +/* + * flags to defltcntl() + * + * Make sure that when adding features, the default behaviour + * is the same as old behaviour. + */ +#define DC_CASE 0x0001 /* Don't ignore case */ + +#define DC_STD DC_CASE /* Default flags */ + +/* + * Macros to handle flags + */ +#ifndef TURNON +#define TURNON(flags, mask) flags |= mask +#define TURNOFF(flags, mask) flags &= ~(mask) +#define ISON(flags, mask) (((flags) & (mask)) == (mask)) +#define ISOFF(flags, mask) (((flags) & (mask)) != (mask)) +#endif + +extern int defltopen __PR((const char *name)); +extern int defltclose __PR((void)); +extern void defltfirst __PR((void)); +extern char *defltread __PR((const char *name)); +extern char *defltnext __PR((const char *name)); +extern int defltcntl __PR((int cmd, int flags)); + +#ifdef __cplusplus +} +#endif + +#endif /* _DEFLTS_H */ diff --git a/src/schily/device.h b/src/schily/device.h new file mode 100644 index 0000000..0be0487 --- /dev/null +++ b/src/schily/device.h @@ -0,0 +1,145 @@ +/* @(#)device.h 1.12 03/06/15 Copyright 1995 J. Schilling */ +/* + * Generic header for users of major(), minor() and makedev() + * + * Copyright (c) 1995 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _DEVICE_H +#define _DEVICE_H + +#ifndef _MCONFIG_H +#include +#endif +#ifndef _PROTOTYP_H +#include +#endif + +/* + * On generic SVR4, major is a function (defined in sys/mkdev.h). + * On Solaris it is defined ... + * As we cannot just test if major is #define'd, we have to + * define _FOUND_MAJOR_ instead. + * + * WARNING: Do never include in SVR4, it contains + * an old definition for major()/minor() defining 8 minorbits. + * Use instead. + */ +#ifndef _INCL_SYS_TYPES_H +#include +#define _INCL_SYS_TYPES_H +#endif +/* + * Some systems define major in . + * We are ready... + */ +#ifdef major +# define _FOUND_MAJOR_ +#endif + +#ifdef MAJOR_IN_MKDEV +# ifndef _INCL_SYS_MKDEV_H +# include +# define _INCL_SYS_MKDEV_H +# endif +# define _FOUND_MAJOR_ +#endif + +#ifndef _FOUND_MAJOR_ +# ifdef MAJOR_IN_SYSMACROS +# ifndef _INCL_SYS_SYSMACROS_H +# include +# define _INCL_SYS_SYSMACROS_H +# endif +# define _FOUND_MAJOR_ +# endif +#endif + +/* + * If we are on HP/UX before HP/UX 8, + * major/minor are not in . + */ +#ifndef _FOUND_MAJOR_ +# if defined(hpux) || defined(__hpux__) || defined(__hpux) +# ifndef _INCL_SYS_MKOD_H +# include +# define _INCL_SYS_MKOD_H +# endif +# define _FOUND_MAJOR_ +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * For all other systems define major()/minor() here. + * XXX Check if this definition will be usefull for ms dos too. + */ +#ifndef _FOUND_MAJOR_ +# define major(dev) (((dev) >> 8) & 0xFF) +# define minor(dev) ((dev) & 0xFF) +# define makedev(majo, mino) (((majo) << 8) | (mino)) +#endif + +/* + * Don't pollute namespace... + */ +#undef _FOUND_MAJOR_ + +#ifdef __XDEV__ +/* + * The following defines are currently only needed for 'star'. + * We make it conditional code to avoid to pollute the namespace. + */ +#define XDEV_T unsigned long + +extern int minorbits; +extern XDEV_T minormask; +extern XDEV_T _dev_mask[]; + +#define dev_major(dev) (((XDEV_T)(dev)) >> minorbits) +#define _dev_major(mbits, dev) (((XDEV_T)(dev)) >> (mbits)) + +#define dev_minor(dev) (((XDEV_T)(dev)) & minormask) +#define _dev_minor(mbits, dev) (((XDEV_T)(dev)) & _dev_mask[(mbits)]) + + +#define dev_make(majo, mino) ((((XDEV_T)(majo)) << minorbits) | \ + ((XDEV_T)(mino))) +#define _dev_make(mbits, majo, mino) ((((XDEV_T)(majo)) << (mbits) | \ + ((XDEV_T)(mino))) + +extern void dev_init __PR((BOOL debug)); +#ifndef dev_major +extern XDEV_T dev_major __PR((XDEV_T dev)); +extern XDEV_T _dev_major __PR((int mbits, XDEV_T dev)); +extern XDEV_T dev_minor __PR((XDEV_T dev)); +extern XDEV_T _dev_minor __PR((int mbits, XDEV_T dev)); +extern XDEV_T dev_make __PR((XDEV_T majo, XDEV_T mino)); +extern XDEV_T _dev_make __PR((int mbits, XDEV_T majo, XDEV_T mino)); +#endif + +#endif /* __XDEV__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _DEVICE_H */ diff --git a/src/schily/dirdefs.h b/src/schily/dirdefs.h new file mode 100644 index 0000000..30ab6c8 --- /dev/null +++ b/src/schily/dirdefs.h @@ -0,0 +1,177 @@ +/* @(#)dirdefs.h 1.15 04/06/16 Copyright 1987, 1998 J. Schilling */ +/* + * Copyright (c) 1987, 1998 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _DIRDEFS_H +#define _DIRDEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef JOS +# ifndef _INCL_SYS_STYPES_H +# include +# define _INCL_SYS_STYPES_H +# endif +# ifndef _INCL_SYS_FILEDESC_H +# include +# define _INCL_SYS_FILEDESC_H +# endif +# define NEED_READDIR +# define dirent _direct +# define DIR_NAMELEN(dirent) strlen((dirent)->d_name) +# define DIRSIZE 30 +# define FOUND_DIRSIZE + typedef struct _dirent { + char name[DIRSIZE]; + short ino; + } dirent; + +#else /* !JOS */ + +# ifndef _INCL_SYS_TYPES_H +# include +# define _INCL_SYS_TYPES_H +# endif +# ifndef _INCL_SYS_STAT_H +# include +# define _INCL_SYS_STAT_H +# endif +# ifdef HAVE_LIMITS_H +# ifndef _INCL_LIMITS_H +# include +# define _INCL_LIMITS_H +# endif +# endif +# ifdef HAVE_SYS_PARAM_H +# ifndef _INCL_SYS_PARAM_H +# include +# define _INCL_SYS_PARAM_H +# endif +# endif + +# ifdef HAVE_DIRENT_H /* This a POSIX compliant system */ +# ifndef _INCL_DIRENT_H +# include +# define _INCL_DIRENT_H +# endif +# define DIR_NAMELEN(dirent) strlen((dirent)->d_name) +# define _FOUND_DIR_ +# else /* This is a Pre POSIX system */ + +# define dirent direct +# define DIR_NAMELEN(dirent) (dirent)->d_namlen + +# if defined(HAVE_SYS_DIR_H) +# ifndef _INCL_SYS_DIR_H +# include +# define _INCL_SYS_DIR_H +# endif +# define _FOUND_DIR_ +# endif + +# if defined(HAVE_NDIR_H) && !defined(_FOUND_DIR_) +# ifndef _INCL_NDIR_H +# include +# define _INCL_NDIR_H +# endif +# define _FOUND_DIR_ +# endif + +# if defined(HAVE_SYS_NDIR_H) && !defined(_FOUND_DIR_) +# ifndef _INCL_SYS_NDIR_H +# include +# define _INCL_SYS_NDIR_H +# endif +# define _FOUND_DIR_ +# endif +# endif /* HAVE_DIRENT_H */ + +# if defined(_FOUND_DIR_) +/* + * Don't use defaults here to allow recognition of problems. + */ +# ifdef MAXNAMELEN +# define DIRSIZE MAXNAMELEN /* From sys/param.h */ +# define FOUND_DIRSIZE +# else +# ifdef MAXNAMLEN +# define DIRSIZE MAXNAMLEN /* From dirent.h */ +# define FOUND_DIRSIZE +# else +# ifdef DIRSIZ +# define DIRSIZE DIRSIZ /* From sys/dir.h */ +# define FOUND_DIRSIZE +# endif +# endif +# endif +# else /* !_FOUND_DIR_ */ + +# define NEED_DIRENT +# define NEED_READDIR +# define dirent _direct +# define DIR_NAMELEN(dirent) strlen((dirent)->d_name) + +# endif /* _FOUND_DIR_ */ + + +#ifdef NEED_DIRENT + +#ifndef FOUND_DIRSIZE +#define DIRSIZE 14 /* The old UNIX standard value */ +#define FOUND_DIRSIZE +#endif + +typedef struct _dirent { + short ino; + char name[DIRSIZE]; +} dirent; + +#endif /* NEED_DIRENT */ + +#endif /* !JOS */ + +#ifdef NEED_READDIR + typedef struct __dirdesc { + FILE *dd_fd; + } DIR; + + struct _direct { + unsigned long d_ino; + unsigned short d_reclen; + unsigned short d_namlen; + char d_name[DIRSIZE +1]; + }; + +extern DIR *opendir(); +extern closedir(); +extern struct dirent *readdir(); + +#endif /* NEED_READDIR */ + +#ifdef __cplusplus +} +#endif + +#endif /* _DIRDEFS_H */ diff --git a/src/schily/fctldefs.h b/src/schily/fctldefs.h new file mode 100644 index 0000000..4889b96 --- /dev/null +++ b/src/schily/fctldefs.h @@ -0,0 +1,82 @@ +/* @(#)fctldefs.h 1.13 03/02/23 Copyright 1996 J. Schilling */ +/* + * Generic header for users of open(), creat() and chmod() + * + * Copyright (c) 1996 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _FCTLDEFS_H +#define _FCTLDEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifndef _STATDEFS_H +#include /* For 3rd arg of open() and chmod() */ +#endif + +#ifndef _INCL_SYS_TYPES_H +#include /* Needed for fcntl.h */ +#define _INCL_SYS_TYPES_H +#endif + +#ifdef HAVE_SYS_FILE_H +/* + * Historical systems with flock() only need sys/file.h + */ +# ifndef _INCL_SYS_FILE_H +# include +# define _INCL_SYS_FILE_H +# endif +#endif +#ifdef HAVE_FCNTL_H +# ifndef _INCL_FCNTL_H +# include +# define _INCL_FCNTL_H +#endif +#endif + +/* + * Do not define more than O_RDONLY / O_WRONLY / O_RDWR / O_BINARY + * The values may differ. + * + * O_BINARY is defined here to allow all applications to compile on a non DOS + * environment without repeating this definition. + */ +#ifndef O_RDONLY +# define O_RDONLY 0 +#endif +#ifndef O_WRONLY +# define O_WRONLY 1 +#endif +#ifndef O_RDWR +# define O_RDWR 2 +#endif +#ifndef O_BINARY /* Only present on DOS or similar */ +# define O_BINARY 0 +#endif +#ifndef O_NDELAY /* This is undefined on BeOS :-( */ +# define O_NDELAY 0 +#endif + +#ifndef O_ACCMODE +#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) +#endif + +#endif /* _FCTLDEFS_H */ diff --git a/src/schily/getargs.h b/src/schily/getargs.h new file mode 100644 index 0000000..3c5787f --- /dev/null +++ b/src/schily/getargs.h @@ -0,0 +1,49 @@ +/* @(#)getargs.h 1.9 03/06/15 Copyright 1985 J. Schilling */ +/* + * Definitions for getargs()/getallargs()/getfiles() + * + * Copyright (c) 1985 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _GETARGS_H +#define _GETARGS_H + +#ifndef _MCONFIG_H +#include +#endif +#ifndef _PROTOTYP_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define NOARGS 0 /* No more args */ +#define NOTAFLAG 1 /* Not a flag type argument */ +#define BADFLAG (-1) /* Not a valid flag argument */ +#define BADFMT (-2) /* Error in format string */ +#define NOTAFILE (-3) /* Seems to be a flag type */ + +typedef int (*getargfun) __PR((const void *, void *)); + +#ifdef __cplusplus +} +#endif + +#endif /* _GETARGS_H */ diff --git a/src/schily/getcwd.h b/src/schily/getcwd.h new file mode 100644 index 0000000..9c4a35c --- /dev/null +++ b/src/schily/getcwd.h @@ -0,0 +1,43 @@ +/* @(#)getcwd.h 1.3 01/07/15 Copyright 1998 J. Schilling */ +/* + * Definitions for getcwd() + * + * Copyright (c) 1998 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GETCWD_H +#define _GETCWD_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifdef JOS +# ifndef _INCL_SYS_STYPES_H +# include +# define _INCL_SYS_STYPES_H +# endif + extern char *gwd(); +# define getcwd(b, len) gwd(b) +#else +# ifndef HAVE_GETCWD +# define getcwd(b, len) getwd(b) +# endif +#endif + +#endif /* _GETCWD_H */ diff --git a/src/schily/intcvt.h b/src/schily/intcvt.h new file mode 100644 index 0000000..8d89683 --- /dev/null +++ b/src/schily/intcvt.h @@ -0,0 +1,113 @@ +/* @(#)intcvt.h 1.4 03/12/29 Copyright 1986-2003 J. Schilling */ +/* + * Definitions for conversion to/from integer data types of various size. + * + * Copyright (c) 1986-2003 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _INTCVT_H +#define _INTCVT_H + +#ifndef _MCONFIG_H +#include +#endif + +#define i_to_2_byte(a, i) (((Uchar *)(a))[0] = ((i) >> 8) & 0xFF,\ + ((Uchar *)(a))[1] = (i) & 0xFF) + +#define i_to_3_byte(a, i) (((Uchar *)(a))[0] = ((i) >> 16)& 0xFF,\ + ((Uchar *)(a))[1] = ((i) >> 8) & 0xFF,\ + ((Uchar *)(a))[2] = (i) & 0xFF) + +#define i_to_4_byte(a, i) (((Uchar *)(a))[0] = ((i) >> 24)& 0xFF,\ + ((Uchar *)(a))[1] = ((i) >> 16)& 0xFF,\ + ((Uchar *)(a))[2] = ((i) >> 8) & 0xFF,\ + ((Uchar *)(a))[3] = (i) & 0xFF) + + + +#define a_to_byte(a) (((Int8_t *) a)[0]) + +#define a_to_u_byte(a) ((UInt8_t) \ + (((Uchar *) a)[0] & 0xFF)) + +#define a_to_u_2_byte(a) ((UInt16_t) \ + ((((Uchar *) a)[1] & 0xFF) | \ + (((Uchar *) a)[0] << 8 & 0xFF00))) + +#define a_to_2_byte(a) (int)(Int16_t)a_to_u_2_byte(a) + +#define a_to_u_3_byte(a) ((Ulong) \ + ((((Uchar *) a)[2] & 0xFF) | \ + (((Uchar *) a)[1] << 8 & 0xFF00) | \ + (((Uchar *) a)[0] << 16 & 0xFF0000))) + +#define a_to_3_byte(a) a_to_u_3_byte(a) /* XXX Is there a signed version ? */ + +#ifdef __STDC__ +# define __TOP_4BYTE 0xFF000000UL +#else +# define __TOP_4BYTE 0xFF000000 +#endif + +#define a_to_u_4_byte(a) ((Ulong) \ + ((((Uchar*) a)[3] & 0xFF) | \ + (((Uchar*) a)[2] << 8 & 0xFF00) | \ + (((Uchar*) a)[1] << 16 & 0xFF0000) | \ + (((Uchar*) a)[0] << 24 & __TOP_4BYTE))) + +#define a_to_4_byte(a) (long)(Int32_t)a_to_u_4_byte(a) + +/* + * Little Endian versions of above macros + */ +#define li_to_2_byte(a, i) (((Uchar *)(a))[1] = ((i) >> 8) & 0xFF,\ + ((Uchar *)(a))[0] = (i) & 0xFF) + +#define li_to_3_byte(a, i) (((Uchar *)(a))[2] = ((i) >> 16)& 0xFF,\ + ((Uchar *)(a))[1] = ((i) >> 8) & 0xFF,\ + ((Uchar *)(a))[0] = (i) & 0xFF) + +#define li_to_4_byte(a, i) (((Uchar *)(a))[3] = ((i) >> 24)& 0xFF,\ + ((Uchar *)(a))[2] = ((i) >> 16)& 0xFF,\ + ((Uchar *)(a))[1] = ((i) >> 8) & 0xFF,\ + ((Uchar *)(a))[0] = (i) & 0xFF) + + +#define la_to_u_2_byte(a) ((UInt16_t) \ + ((((Uchar*) a)[0] & 0xFF) | \ + (((Uchar*) a)[1] << 8 & 0xFF00))) + +#define la_to_2_byte(a) (int)(Int16_t)la_to_u_2_byte(a) + +#define la_to_u_3_byte(a) ((Ulong) \ + ((((Uchar*) a)[0] & 0xFF) | \ + (((Uchar*) a)[1] << 8 & 0xFF00) | \ + (((Uchar*) a)[2] << 16 & 0xFF0000))) + +#define la_to_3_byte(a) la_to_u_3_byte(a) /* XXX Is there a signed version ? */ + +#define la_to_u_4_byte(a) ((Ulong) \ + ((((Uchar*) a)[0] & 0xFF) | \ + (((Uchar*) a)[1] << 8 & 0xFF00) | \ + (((Uchar*) a)[2] << 16 & 0xFF0000) | \ + (((Uchar*) a)[3] << 24 & __TOP_4BYTE))) + +#define la_to_4_byte(a) (long)(Int32_t)la_to_u_4_byte(a) + +#endif /* _INTCVT_H */ diff --git a/src/schily/jmpdefs.h b/src/schily/jmpdefs.h new file mode 100644 index 0000000..f4cbce4 --- /dev/null +++ b/src/schily/jmpdefs.h @@ -0,0 +1,38 @@ +/* @(#)jmpdefs.h 1.2 00/11/08 Copyright 1999 J. Schilling */ +/* + * Definitions that help to handle a jmp_buf + * + * Copyright (c) 1998 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _JMPDEFS_H +#define _JMPDEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + jmp_buf jb; +} jmps_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _JMPDEFS_H */ diff --git a/src/schily/libport.h b/src/schily/libport.h new file mode 100644 index 0000000..6870875 --- /dev/null +++ b/src/schily/libport.h @@ -0,0 +1,111 @@ +/* @(#)libport.h 1.9 03/06/15 Copyright 1995 J. Schilling */ +/* + * Copyright (c) 1995 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifndef _LIBPORT_H +#define _LIBPORT_H + +#ifndef _MCONFIG_H +#include +#endif +#ifndef _PROTOTYP_H +#include +#endif +#ifndef _STANDARD_H +#include +#endif + +/* + * Try to get HOST_NAME_MAX for gethostname() + */ +#ifndef _UNIXSTD_H +#include +#endif + +#ifndef HOST_NAME_MAX +#if defined(HAVE_NETDB_H) && !defined(HOST_NOT_FOUND) && \ + !defined(_INCL_NETDB_H) +#include +#define _INCL_NETDB_H +#endif +#ifdef MAXHOSTNAMELEN +#define HOST_NAME_MAX MAXHOSTNAMELEN +#endif +#endif + +#ifndef HOST_NAME_MAX +#ifdef HAVE_SYS_PARAM_H +#include /* Include various defs needed with some OS */ + /* Linux MAXHOSTNAMELEN */ +#endif +#ifdef MAXHOSTNAMELEN +#define HOST_NAME_MAX MAXHOSTNAMELEN +#endif +#endif + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 255 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef OPENSERVER +/* + * Don't use the usleep() from libc on SCO's OPENSERVER. + * It will kill our processes with SIGALRM. + */ +/* + * Don't #undef HAVE_USLEEP in this file, SCO has a + * usleep() prototype in unistd.h + */ +/*#undef HAVE_USLEEP*/ +#endif + +#ifndef HAVE_GETHOSTID +extern long gethostid __PR((void)); +#endif +#ifndef HAVE_GETHOSTNAME +extern int gethostname __PR((char *name, int namelen)); +#endif +#ifndef HAVE_GETDOMAINNAME +extern int getdomainname __PR((char *name, int namelen)); +#endif +#ifndef HAVE_GETPAGESIZE +EXPORT int getpagesize __PR((void)); +#endif +#ifndef HAVE_USLEEP +extern int usleep __PR((int usec)); +#endif + +#if !defined(HAVE_STRDUP) || defined(__SVR4) +extern char *strdup __PR((const char *s)); +#endif + +#ifndef HAVE_RENAME +extern int rename __PR((const char *old, const char *new)); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBPORT_H */ diff --git a/src/schily/librmt.h b/src/schily/librmt.h new file mode 100644 index 0000000..792b088 --- /dev/null +++ b/src/schily/librmt.h @@ -0,0 +1,64 @@ +/* @(#)librmt.h 1.16 03/06/15 Copyright 1996 J. Schilling */ +/* + * Prototypes for rmt client subroutines + * + * Copyright (c) 1995,1996,2000-2002 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _LIBRMT_H +#define _LIBRMT_H + +#ifndef _MCONFIG_H +#include +#endif +#ifndef _PROTOTYP_H +#include +#endif + +#ifndef _INCL_SYS_TYPES_H +#include +#define _INCL_SYS_TYPES_H +#endif + +#include + +/* + * remote.c + */ +extern void rmtinit __PR((int (*errmsgn)(int, const char *, ...), + void (*eexit)(int))); +extern int rmtdebug __PR((int dlevel)); +extern char *rmtfilename __PR((char *name)); +extern char *rmthostname __PR((char *hostname, int hnsize, char *rmtspec)); +extern int rmtgetconn __PR((char *host, int trsize, int excode)); +extern int rmtopen __PR((int fd, char *fname, int fmode)); +extern int rmtclose __PR((int fd)); +extern int rmtread __PR((int fd, char *buf, int count)); +extern int rmtwrite __PR((int fd, char *buf, int count)); +extern off_t rmtseek __PR((int fd, off_t offset, int whence)); +extern int rmtioctl __PR((int fd, int cmd, int count)); +#ifdef MTWEOF +extern int rmtstatus __PR((int fd, struct mtget *mtp)); +#endif +extern int rmtxstatus __PR((int fd, struct rmtget *mtp)); +#ifdef MTWEOF +extern void _rmtg2mtg __PR((struct mtget *mtp, struct rmtget *rmtp)); +extern int _mtg2rmtg __PR((struct rmtget *rmtp, struct mtget *mtp)); +#endif + +#endif /* _LIBRMT_H */ diff --git a/src/schily/maxpath.h b/src/schily/maxpath.h new file mode 100644 index 0000000..2b412c9 --- /dev/null +++ b/src/schily/maxpath.h @@ -0,0 +1,75 @@ +/* @(#)maxpath.h 1.6 03/08/23 Copyright 1985, 1995, 1998 J. Schilling */ +/* + * Definitions for dealing with statically limitations on pathnames + * + * Copyright (c) 1985, 1995, 1998 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _MAXPATH_H +#define _MAXPATH_H + +#ifndef _DIRDEFS_H +#include /* Includes mconfig.h if needed */ +#endif + +#ifdef JOS +#ifndef _JOS_MAXP_H +# include +#endif +# define FOUND_MAXPATHNAME +# define FOUND_MAXFILENAME +#else + +# ifdef MAXPATHLEN +# define MAXPATHNAME MAXPATHLEN /* From sys/param.h */ +# define FOUND_MAXPATHNAME +# else +# ifdef PATH_MAX +# define MAXPATHNAME PATH_MAX /* From limits.h */ +# define FOUND_MAXPATHNAME +# else +# define MAXPATHNAME 256 /* Is there a limit? */ +# endif +# endif + +/* + * Don't use defaults here to allow recognition of problems. + */ +# ifdef MAXNAMELEN +# define MAXFILENAME MAXNAMELEN /* From sys/param.h */ +# define FOUND_MAXFILENAME +# else +# ifdef MAXNAMLEN +# define MAXFILENAME MAXNAMLEN /* From dirent.h */ +# define FOUND_MAXFILENAME +# else +# ifdef DIRSIZ +# define MAXFILENAME DIRSIZ /* From sys/dir.h */ +# define FOUND_MAXFILENAME +# endif +# endif +# endif + +#if !defined(FOUND_MAXFILENAME) && defined(FOUND_DIRSIZE) +# define MAXFILENAME DIRSIZE /* From dirdefs.h */ +# define FOUND_MAXFILENAME +#endif + +#endif /* JOS */ + +#endif /* _MAXPATH_H */ diff --git a/src/schily/mconfig.h b/src/schily/mconfig.h new file mode 100644 index 0000000..3ed8acf --- /dev/null +++ b/src/schily/mconfig.h @@ -0,0 +1,483 @@ +/* @(#)mconfig.h 1.50 04/07/11 Copyright 1995 J. Schilling */ +/* + * definitions for machine configuration + * + * Copyright (c) 1995 J. Schilling + * + * This file must be included before any other file. + * If this file is not included before stdio.h you will not be + * able to get LARGEFILE support + * + * Use only cpp instructions. + * + * NOTE: SING: (Schily Is Not Gnu) + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _MCONFIG_H +#define _MCONFIG_H + +/* + * Tell our users that this is a Schily SING compile environment. + */ +#define IS_SCHILY + +/* + * This hack that is needed as long as VMS has no POSIX shell. + */ +#ifdef VMS +# define USE_STATIC_CONF +#endif + +#ifdef USE_STATIC_CONF +#include /* This is the current static autoconf stuff */ +#else +#include /* This is the current dynamic autoconf stuff */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The NetBSD people want to bother us. + * They removed the definition for 'unix' and are bleating for every test + * for #if defined(unix). So we need to check for NetBSD early. + */ +#ifndef IS_UNIX +# if defined(__NetBSD__) +# define IS_UNIX +# endif +#endif + +#ifndef IS_UNIX +# if (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__DJGPP__) +# define IS_UNIX +# endif +#endif + +#ifdef __MSDOS__ +# define IS_MSDOS +#endif + +#if defined(tos) || defined(__tos) +# define IS_TOS +#endif + +#ifdef THINK_C +# define IS_MAC +#endif + +#if defined(sun) || defined(__sun) || defined(__sun__) +# define IS_SUN +#endif + +#if defined(__CYGWIN32__) || defined(__CYGWIN__) +# define IS_GCC_WIN32 +# define IS_CYGWIN + +#if defined(unix) || defined(_X86) +# define IS_CYGWIN_1 +#endif +#endif + +/*--------------------------------------------------------------------------*/ +/* + * Some magic that cannot (yet) be figured out with autoconf. + */ + +#if defined(sun3) || defined(mc68000) || defined(mc68020) +# ifndef HAVE_SCANSTACK +# define HAVE_SCANSTACK +# endif +#endif +#ifdef sparc +# ifndef HAVE_LDSTUB +# define HAVE_LDSTUB +# endif +# ifndef HAVE_SCANSTACK +# define HAVE_SCANSTACK +# endif +#endif +#if defined(__i386_) || defined(i386) +# ifndef HAVE_XCHG +# define HAVE_XCHG +# endif +# ifndef HAVE_SCANSTACK +# define HAVE_SCANSTACK +# endif +#endif + +/* + * Use of SCANSTACK is disabled by default + */ +#ifndef USE_SCANSTACK +# undef HAVE_SCANSTACK +#else +/* + * But .... + * The tests are much better now, so always give it a chance. + */ +#ifndef HAVE_SCANSTACK +# define HAVE_SCANSTACK +#endif +#endif + +/* + * Allow to overwrite the defines in the makefiles by calling + * + * make COPTX=-DFORCE_SCANSTACK + */ +#ifdef FORCE_SCANSTACK +# undef NO_SCANSTACK +#ifndef HAVE_SCANSTACK +# define HAVE_SCANSTACK +#endif +#ifndef USE_SCANSTACK +# define USE_SCANSTACK +#endif +#endif + +/* + * This is the global switch to deactivate stack scanning + */ +#ifdef NO_SCANSTACK +# ifdef HAVE_SCANSTACK +# undef HAVE_SCANSTACK +# endif +#endif + +#ifdef NO_FORK +# ifdef HAVE_FORK +# undef HAVE_FORK +# endif +# ifdef HAVE_VFORK +# undef HAVE_VFORK +# endif +#endif +#ifdef NO_VFORK +# ifdef HAVE_VFORK +# undef HAVE_VFORK +# endif +#endif + +#if defined(SOL2) || defined(SOL2) || \ + defined(S5R4) || defined(__S5R4) || defined(SVR4) +# ifndef __SVR4 +# define __SVR4 +# endif +#endif + +#ifdef __SVR4 +# ifndef SVR4 +# define SVR4 +# endif +#endif + +/* + * SunOS 4.x / SunOS 5.x + */ +#if defined(IS_SUN) +# define HAVE_GETAV0 +#endif + +/* + * AIX + */ +#if defined(_IBMR2) || defined(_AIX) +# ifndef IS_UNIX +# define IS_UNIX /* ??? really ??? */ +# endif +#endif + +/* + * QNX + */ +#if defined(__QNX__) +# ifndef IS_UNIX +# define IS_UNIX +# endif +#endif + +/* + * Silicon Graphics (must be before SVR4) + */ +#if defined(sgi) || defined(__sgi) +# define __NOT_SVR4__ /* Not a real SVR4 implementation */ +#endif + +/* + * Data General + */ +#if defined(__DGUX__) +#ifdef XXXXXXX +# undef HAVE_MTGET_DSREG +# undef HAVE_MTGET_RESID +# undef HAVE_MTGET_FILENO +# undef HAVE_MTGET_BLKNO +#endif +# define mt_type mt_model +# define mt_dsreg mt_status1 +# define mt_erreg mt_status2 + /* + * DGUX hides its flock as dg_flock. + */ +# define HAVE_FLOCK +# define flock dg_flock + /* + * Use the BSD style wait on DGUX to get the resource usages of child + * processes. + */ +# define _BSD_WAIT_FLAVOR +#endif + +/* + * Apple Rhapsody (This is the name for Mac OS X beta) + */ +#if defined(__NeXT__) && defined(__TARGET_OSNAME) && __TARGET_OSNAME == rhapsody +# define HAVE_OSDEF /* prevent later definitions to overwrite current */ +# ifndef IS_UNIX +# define IS_UNIX +# endif +#endif + +/* + * NextStep + */ +#if defined(__NeXT__) && !defined(HAVE_OSDEF) +#define NO_PRINT_OVR +#undef HAVE_USG_STDIO /* + * NeXT Step 3.x uses __flsbuf(unsigned char, FILE *) + * instead of __flsbuf(int, FILE *) + */ +# ifndef IS_UNIX +# define IS_UNIX +# endif +#endif + +/* + * Mac OS X + */ +#if defined(__APPLE__) && defined(__MACH__) +# ifndef IS_UNIX +# define IS_UNIX +# endif +# define IS_MACOS_X +#endif + +/* + * NextStep 3.x has a broken linker that does not allow us to override + * these functions. + */ +#ifndef __OPRINTF__ + +#ifdef NO_PRINT_OVR +# define printf Xprintf +# define fprintf Xfprintf +# define sprintf Xsprintf +#endif + +#endif /* __OPRINTF__ */ + +/*--------------------------------------------------------------------------*/ +/* + * If there is no flock defined by the system, use emulation + * through fcntl record locking. + */ +#ifndef HAVE_FLOCK +#define LOCK_SH 1 /* shared lock */ +#define LOCK_EX 2 /* exclusive lock */ +#define LOCK_NB 4 /* don't block when locking */ +#define LOCK_UN 8 /* unlock */ +#endif + +#ifndef _PROTOTYP_H +#include +#endif + +/* + * gcc 2.x generally implements the long long type. + */ +#ifdef __GNUC__ +# if __GNUC__ > 1 +# ifndef HAVE_LONGLONG +# define HAVE_LONGLONG +# endif +# endif +#endif + +#ifdef __CHAR_UNSIGNED__ /* GNU GCC define (dynamic) */ +#ifndef CHAR_IS_UNSIGNED +#define CHAR_IS_UNSIGNED /* Sing Schily define (static) */ +#endif +#endif + +/* + * Convert to GNU name + */ +#ifdef HAVE_STDC_HEADERS +# ifndef STDC_HEADERS +# define STDC_HEADERS +# endif +#endif +/* + * Convert to SCHILY name + */ +#ifdef STDC_HEADERS +# ifndef HAVE_STDC_HEADERS +# define HAVE_STDC_HEADERS +# endif +#endif + +#ifdef IS_UNIX +# define HAVE_PATH_DELIM +# define PATH_DELIM '/' +# define PATH_DELIM_STR "/" +# define PATH_ENV_DELIM ':' +# define PATH_ENV_DELIM_STR ":" +# define far +# define near +#endif + +/* + * Win32 with Gygwin + */ +#ifdef IS_GCC_WIN32 +# define HAVE_PATH_DELIM +# define PATH_DELIM '/' +# define PATH_DELIM_STR "/" +# define PATH_ENV_DELIM ':' +# define PATH_ENV_DELIM_STR ":" +# define HAVE_DOS_DRIVELETTER +# define far +# define near +# define NEED_O_BINARY +#endif + +/* + * Win32 with Mingw32 + */ +#ifdef __MINGW32__ +# define HAVE_PATH_DELIM +# define PATH_DELIM '/' +# define PATH_DELIM_STR "/" +# define PATH_ENV_DELIM ';' +# define PATH_ENV_DELIM_STR ";" +# define HAVE_DOS_DRIVELETTER +# define far +# define near +# define NEED_O_BINARY +#endif + +/* + * OS/2 EMX + */ +#ifdef __EMX__ /* We don't want to call it UNIX */ +# define HAVE_PATH_DELIM +# define PATH_DELIM '/' +# define PATH_DELIM_STR "/" +# define PATH_ENV_DELIM ';' +# define PATH_ENV_DELIM_STR ";" +# define HAVE_DOS_DRIVELETTER +# define far +# define near +# define NEED_O_BINARY +#endif + +#ifdef __BEOS__ /* We don't want to call it UNIX */ +# define HAVE_PATH_DELIM +# define PATH_DELIM '/' +# define PATH_DELIM_STR "/" +# define PATH_ENV_DELIM ':' +# define PATH_ENV_DELIM_STR ":" +# define far +# define near +#endif + +/* + * DOS with DJGPP + */ +#ifdef __DJGPP__ /* We don't want to call it UNIX */ +# define HAVE_PATH_DELIM +# define PATH_DELIM '/' +# define PATH_DELIM_STR "/" +# define PATH_ENV_DELIM ';' +# define PATH_ENV_DELIM_STR ";" +# define HAVE_DOS_DRIVELETTER + +# define NEED_O_BINARY +#endif + +/* + * Vanilla DOS + */ +#if defined(IS_MSDOS) && !defined(__DJGPP__) +# define HAVE_PATH_DELIM +# define PATH_DELIM '\\' +# define PATH_DELIM_STR "\\" +# define PATH_ENV_DELIM ';' +# define PATH_ENV_DELIM_STR ";" +# define HAVE_DOS_DRIVELETTER + +# define NEED_O_BINARY +#endif + +/* + * ATARI TOS + */ +#ifdef IS_TOS +# define HAVE_PATH_DELIM +# define PATH_DELIM '\\' +# define PATH_DELIM_STR "\\" +# define PATH_ENV_DELIM ',' +# define PATH_ENV_DELIM_STR "," +# define HAVE_DOS_DRIVELETTER +# define far +# define near +#endif + +/* + * Mac OS 9 + */ +#ifdef IS_MAC +# define HAVE_PATH_DELIM +# define PATH_DELIM ':' +# define PATH_DELIM_STR ":" +# define PATH_ENV_DELIM ';' /* ??? */ +# define PATH_ENV_DELIM_STR ";" /* ??? */ +# define far +# define near +#endif + +/* + * I hope this will make compilation on unknown OS easier. + */ +#ifndef HAVE_PATH_DELIM /* Default to POSIX rules */ +# define HAVE_PATH_DELIM +# define PATH_DELIM '/' +# define PATH_DELIM_STR "/" +# define PATH_ENV_DELIM ':' +# define PATH_ENV_DELIM_STR ":" +# define far +# define near +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _MCONFIG_H */ diff --git a/src/schily/mmapdefs.h b/src/schily/mmapdefs.h new file mode 100644 index 0000000..799f696 --- /dev/null +++ b/src/schily/mmapdefs.h @@ -0,0 +1,63 @@ +/* @(#)mmapdefs.h 1.1 01/02/25 Copyright 2001 J. Schilling */ +/* + * Definitions to be used for mmap() + * + * Copyright (c) 2001 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _MMAPDEFS_H +#define _MMAPDEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifndef _INCL_SYS_TYPES_H +#include +#define _INCL_SYS_TYPES_H +#endif + +#if defined(HAVE_SMMAP) + +#ifndef _INCL_SYS_MMAN_H +#include +#define _INCL_SYS_MMAN_H +#endif + +#ifndef MAP_ANONYMOUS +# ifdef MAP_ANON +# define MAP_ANONYMOUS MAP_ANON +# endif +#endif + +#ifndef MAP_FILE +# define MAP_FILE 0 /* Needed on Apollo Domain/OS */ +#endif + +/* + * Needed for Apollo Domain/OS and may be for others? + */ +#ifdef _MMAP_WITH_SIZEP +# define mmap_sizeparm(s) (&(s)) +#else +# define mmap_sizeparm(s) (s) +#endif + +#endif /* defined(HAVE_SMMAP) */ + +#endif /* _MMAPDEFS_H */ diff --git a/src/schily/mtiodefs.h b/src/schily/mtiodefs.h new file mode 100644 index 0000000..7565ea4 --- /dev/null +++ b/src/schily/mtiodefs.h @@ -0,0 +1,103 @@ +/* @(#)mtiodefs.h 1.4 02/08/26 Copyright 1995,2000-2002 J. Schilling */ +/* + * Generic header for users of magnetic tape ioctl interface. + * + * If there is no local mtio.h or equivalent, define + * simplified mtio definitions here in order + * to be able to do at least remote mtio on systems + * that have no local mtio + * + * Copyright (c) 1995,2000-2002 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _MTIODEFS_H +#define _MTIODEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifdef HAVE_SYS_MTIO_H + +#include + +#else /* ! HAVE_SYS_MTIO_H */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Definitions for magnetic tape io control commands + */ + +/* + * structure for MTIOCTOP - magnetic tape operation command + */ +struct mtop { + short mt_op; /* op code (see below) */ + daddr_t mt_count; /* repeat count or param */ +}; + +/* + * op code values for mt_op + */ +#define MTWEOF 0 /* write EOF record(s) */ +#define MTFSF 1 /* fwd space over file mark(s) */ +#define MTBSF 2 /* back space over file mark(s) (1/2" only ) */ +#define MTFSR 3 /* fwd space record(s) (to inter-record gap) */ +#define MTBSR 4 /* back space record(s) (to inter-record gap)*/ +#define MTREW 5 /* rewind tape */ +#define MTOFFL 6 /* rewind and put the drive offline */ +#define MTNOP 7 /* no operation (sets status ?) */ + +/* + * structure for MTIOCGET - magnetic tape get status command + */ +struct mtget { + short mt_type; /* type of magnetic tape device */ + /* the next two regs are device dependent */ + short mt_dsreg; /* drive status 'register' */ + short mt_erreg; /* error 'register' */ + daddr_t mt_resid; /* transfer residual count */ + daddr_t mt_fileno; /* file # for current position */ + daddr_t mt_blkno; /* block # for current position */ +}; + +#define HAVE_MTGET_TYPE +#define HAVE_MTGET_DSREG +#define HAVE_MTGET_ERREG +#define HAVE_MTGET_RESID +#define HAVE_MTGET_FILENO +#define HAVE_MTGET_BLKNO + +/* + * Define some junk here as software may assume that these two definitions + * are always present. + */ +#define MTIOCGET 0x12340001 +#define MTIOCTOP 0x12340002 + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_SYS_MTIO_H */ + +#endif /* _MTIODEFS_H */ diff --git a/src/schily/patmatch.h b/src/schily/patmatch.h new file mode 100644 index 0000000..96fac4f --- /dev/null +++ b/src/schily/patmatch.h @@ -0,0 +1,105 @@ +/* @(#)patmatch.h 1.10 03/08/24 Copyright 1985 J. Schilling */ + +#ifndef _PATMATCH_H +#define _PATMATCH_H +/* + * Definitions for the pattern matching functions. + * + * Copyright (c) 1985,1995 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +/* + * The pattern matching functions are based on the algorithm + * presented by Martin Richards in: + * + * "A Compact Function for Regular Expression Pattern Matching", + * Software-Practice and Experience, Vol. 9, 527-534 (1979) + * + * Several changes have been made to the original source which has been + * written in BCPL: + * + * '/' is replaced by '!' (to allow UNIX filenames) + * '(',')' are replaced by '{', '}' + * '\'' is replaced by '\\' (UNIX compatible quote) + * + * Character classes have been added to allow "[]" + * to be used. + * Start of line '^' and end of line '$' have been added. + * + * Any number in the following comment is zero or more occurrencies + */ +#ifndef _MCONFIG_H +#include +#endif +#ifndef _PROTOTYP_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ALT '!' /* Alternation in match i.e. this!that!the_other */ +#define REP '#' /* Any number of occurrences of the following expr */ +#define NIL '%' /* Empty string (exactly nothing) */ +#define STAR '*' /* Any number of any character (equivalent of #?) */ +#define ANY '?' /* Any one character */ +#define QUOTE '\\' /* Quotes the next character */ +#define LBRACK '{' /* Begin of precedence grouping */ +#define RBRACK '}' /* End of precedence grouping */ +#define LCLASS '[' /* Begin of character set */ +#define RCLASS ']' /* End of character set */ +#define NOT '^' /* If first in set: invert set content */ +#define RANGE '-' /* Range notation in sets */ +#define START '^' /* Begin of a line */ +#define END '$' /* End of a line */ + +/* + * A list of case statements that may be used for a issimple() or ispattern() + * funtion that checks whether a string conrtains characters that need the + * pattern matcher. + * + * Note that this list does not contain NOT or RANGE because you need + * LCLASS and RCLASS in addition. + */ +#define casePAT case ALT: case REP: case NIL: case STAR: case ANY: \ + case QUOTE: case LBRACK: case RBRACK: \ + case LCLASS: case RCLASS: case START: case END: + + +#define MAXPAT 128 /* Maximum length of pattern */ + +extern int patcompile __PR((const unsigned char * __pat, int __patlen, int * __aux)); + +extern unsigned char *opatmatch __PR((const unsigned char * __pat, const int * __aux, + const unsigned char * __str, int __soff, int __slen, + int __alt)); +extern unsigned char *opatlmatch __PR((const unsigned char * __pat, const int * __aux, + const unsigned char * __str, int __soff, int __slen, + int __alt)); +extern unsigned char *patmatch __PR((const unsigned char * __pat, const int * __aux, + const unsigned char * __str, int __soff, int __slen, + int __alt, int __state[])); +extern unsigned char *patlmatch __PR((const unsigned char * __pat, const int * __aux, + const unsigned char * __str, int __soff, int __slen, + int __alt, int __state[])); + +#ifdef __cplusplus +} +#endif + +#endif /* _PATMATCH_H */ diff --git a/src/schily/prototyp.h b/src/schily/prototyp.h new file mode 100644 index 0000000..45bb9c1 --- /dev/null +++ b/src/schily/prototyp.h @@ -0,0 +1,95 @@ +/* @(#)prototyp.h 1.11 03/08/23 Copyright 1995 J. Schilling */ +/* + * Definitions for dealing with ANSI / KR C-Compilers + * + * Copyright (c) 1995 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * mconfig.h includes prototype.h so we must do this include before we test + * for _PROTOTYP_H + */ +#ifndef _MCONFIG_H +#include +#endif + +#ifndef _PROTOTYP_H +#define _PROTOTYP_H + +#ifndef PROTOTYPES + /* + * If this has already been defined, + * someone else knows better than us... + */ +# ifdef __STDC__ +# if __STDC__ /* ANSI C */ +# define PROTOTYPES +# endif +# if defined(sun) && __STDC__ - 0 == 0 /* Sun C */ +# define PROTOTYPES +# endif +# endif +#endif /* PROTOTYPES */ + +#if !defined(PROTOTYPES) && (defined(__cplusplus) || defined(_MSC_VER)) + /* + * C++ always supports prototypes. + * Define PROTOTYPES so we are not forced to make + * a separtate autoconf run for C++ + * + * Microsoft C has prototypes but does not define __STDC__ + */ +# define PROTOTYPES +#endif + +/* + * If we have prototypes, we should have stdlib.h string.h stdarg.h + */ +#ifdef PROTOTYPES +#if !(defined(SABER) && defined(sun)) +# ifndef HAVE_STDARG_H +# define HAVE_STDARG_H +# endif +#endif +#ifndef JOS +# ifndef HAVE_STDLIB_H +# define HAVE_STDLIB_H +# endif +# ifndef HAVE_STRING_H +# define HAVE_STRING_H +# endif +# ifndef HAVE_STDC_HEADERS +# define HAVE_STDC_HEADERS +# endif +# ifndef STDC_HEADERS +# define STDC_HEADERS /* GNU name */ +# endif +#endif +#endif + +#ifdef NO_PROTOTYPES /* Force not to use prototypes */ +# undef PROTOTYPES +#endif + +#ifdef PROTOTYPES +# define __PR(a) a +#else +# define __PR(a) () +#endif + +#endif /* _PROTOTYP_H */ diff --git a/src/schily/rmtio.h b/src/schily/rmtio.h new file mode 100644 index 0000000..b934814 --- /dev/null +++ b/src/schily/rmtio.h @@ -0,0 +1,156 @@ +/* @(#)rmtio.h 1.5 03/06/15 Copyright 1995,2000 J. Schilling */ +/* + * Definition for enhanced remote tape IO + * + * Copyright (c) 1995,2000-2002 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _RMTIO_H +#define _RMTIO_H + +#ifndef _MCONFIG_H +#include +#endif +#ifndef _UTYPES_H +#include +#endif + +/* + * values for mt_op + */ +#define RMTWEOF 0 /* write an end-of-file record */ +#define RMTFSF 1 /* forward space over file mark */ +#define RMTBSF 2 /* backward space over file mark (1/2" only ) */ +#define RMTFSR 3 /* forward space to inter-record gap */ +#define RMTBSR 4 /* backward space to inter-record gap */ +#define RMTREW 5 /* rewind */ +#define RMTOFFL 6 /* rewind and put the drive offline */ +#define RMTNOP 7 /* no operation, sets status only */ + +#ifdef __needed__ +#define MTRETEN 8 /* retension the tape (cartridge tape only) */ +#define MTERASE 9 /* erase the entire tape */ +#define MTEOM 10 /* position to end of media */ +#define MTNBSF 11 /* backward space file to BOF */ + +#define MTSRSZ 12 /* set record size */ +#define MTGRSZ 13 /* get record size */ +#define MTLOAD 14 /* for loading a tape (use o_delay to open */ + /* the tape device) */ +#endif + +/* + * Definitions for the new RMT Protocol version 1 + * + * The new Protocol version tries to make the use + * of rmtioctl() more portable between different platforms. + */ +#define RMTIVERSION -1 /* Opcode to request version */ +#define RMT_NOVERSION -1 /* Old version code */ +#define RMT_VERSION 1 /* New (current) version code */ + +/* + * Support for commands bejond MTWEOF..MTNOP (0..7) + */ +#define RMTICACHE 0 /* enable controller cache */ +#define RMTINOCACHE 1 /* disable controller cache */ +#define RMTIRETEN 2 /* retension the tape (cartridge tape only) */ +#define RMTIERASE 3 /* erase the entire tape */ +#define RMTIEOM 4 /* position to end of media */ +#define RMTINBSF 5 /* backward space file to BOF */ + +/* + * Old MTIOCGET copies a binary version of struct mtget back + * over the wire. This is highly non portable. + * MTS_* retrieves ascii versions (%d format) of a single + * field in the struct mtget. + * NOTE: MTS_ERREG may only be valid on the first call and + * must be retrived first. + */ +#define MTS_TYPE 'T' /* mtget.mt_type */ +#define MTS_DSREG 'D' /* mtget.mt_dsreg */ +#define MTS_ERREG 'E' /* mtget.mt_erreg */ +#define MTS_RESID 'R' /* mtget.mt_resid */ +#define MTS_FILENO 'F' /* mtget.mt_fileno */ +#define MTS_BLKNO 'B' /* mtget.mt_blkno */ +#define MTS_FLAGS 'f' /* mtget.mt_flags */ +#define MTS_BF 'b' /* mtget.mt_bf */ + +/* + * structure for remote MTIOCGET - mag tape get status command + */ +struct rmtget { + Llong mt_type; /* type of magtape device */ + /* the following two registers are grossly device dependent */ + Llong mt_dsreg; /* ``drive status'' register */ + Int32_t mt_dsreg1; /* ``drive status'' register */ + Int32_t mt_dsreg2; /* ``drive status'' register */ + Llong mt_gstat; /* ``generic status'' register */ + Llong mt_erreg; /* ``error'' register */ + /* optional error info. */ + Llong mt_resid; /* residual count */ + Llong mt_fileno; /* file number of current position */ + Llong mt_blkno; /* block number of current position */ + Llong mt_flags; + Llong mt_gflags; /* generic flags */ + long mt_bf; /* optimum blocking factor */ + int mt_xflags; /* eXistence flags for struct members */ +}; + +/* + * Values for mt_xflags + */ +#define RMT_TYPE 0x0001 /* mt_type/mt_model present */ +#define RMT_DSREG 0x0002 /* mt_dsreg present */ +#define RMT_DSREG1 0x0004 /* mt_dsreg1 present */ +#define RMT_DSREG2 0x0008 /* mt_dsreg2 present */ +#define RMT_GSTAT 0x0010 /* mt_gstat present */ +#define RMT_ERREG 0x0020 /* mt_erreg present */ +#define RMT_RESID 0x0040 /* mt_resid present */ +#define RMT_FILENO 0x0080 /* mt_fileno present */ +#define RMT_BLKNO 0x0100 /* mt_blkno present */ +#define RMT_FLAGS 0x0200 /* mt_flags present */ +#define RMT_BF 0x0400 /* mt_bf present */ +#define RMT_COMPAT 0x0800 /* Created from old compat data */ + +/* + * values for mt_flags + */ +#define RMTF_SCSI 0x01 +#define RMTF_REEL 0x02 +#define RMTF_ASF 0x04 +#define RMTF_TAPE_HEAD_DIRTY 0x08 +#define RMTF_TAPE_CLN_SUPPORTED 0x10 + +/* + * these are recommended + */ +#ifdef __needed__ +#define MT_ISQIC 0x32 /* generic QIC tape drive */ +#define MT_ISREEL 0x33 /* generic reel tape drive */ +#define MT_ISDAT 0x34 /* generic DAT tape drive */ +#define MT_IS8MM 0x35 /* generic 8mm tape drive */ +#define MT_ISOTHER 0x36 /* generic other type of tape drive */ + +/* more Sun devices */ +#define MT_ISTAND25G 0x37 /* sun: SCSI Tandberg 2.5 Gig QIC */ +#define MT_ISDLT 0x38 /* sun: SCSI DLT tape drive */ +#define MT_ISSTK9840 0x39 /* sun: STK 9840 (Ironsides) */ +#endif + +#endif /* _RMTIO_H */ diff --git a/src/schily/scg/aspi-dos.h b/src/schily/scg/aspi-dos.h new file mode 100644 index 0000000..0affa60 --- /dev/null +++ b/src/schily/scg/aspi-dos.h @@ -0,0 +1,155 @@ +#ifndef __ASPI16_H_ +#define __ASPI16_H_ + +#define PACKED __attribute__((packed)) +#define FAR +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; + +//***************************************************************************** +// %%% SCSI MISCELLANEOUS EQUATES %%% +//***************************************************************************** + +#define SENSE_LEN 14 // Default sense buffer length +#define SRB_DIR_SCSI 0x00 // Direction determined by SCSI +#define SRB_POSTING 0x01 // Enable ASPI posting +#define SRB_ENABLE_RESIDUAL_COUNT 0x04 // Enable residual byte count reporting +#define SRB_DIR_IN 0x08 // Transfer from SCSI target to host +#define SRB_DIR_OUT 0x10 // Transfer from host to SCSI target + +//***************************************************************************** +// %%% ASPI Command Definitions %%% +//***************************************************************************** + +#define SC_HA_INQUIRY 0x00 // Host adapter inquiry +#define SC_GET_DEV_TYPE 0x01 // Get device type +#define SC_EXEC_SCSI_CMD 0x02 // Execute SCSI command +#define SC_ABORT_SRB 0x03 // Abort an SRB +#define SC_RESET_DEV 0x04 // SCSI bus device reset +#define SC_SET_HA_PARMS 0x05 // Set HA parameters +#define SC_GET_DISK_INFO 0x06 // Get Disk information + +//***************************************************************************** +// %%% SRB Status %%% +//***************************************************************************** + +#define SS_PENDING 0x00 // SRB being processed +#define SS_COMP 0x01 // SRB completed without error +#define SS_ABORTED 0x02 // SRB aborted +#define SS_ABORT_FAIL 0x03 // Unable to abort SRB +#define SS_ERR 0x04 // SRB completed with error + +#define SS_INVALID_CMD 0x80 // Invalid ASPI command +#define SS_INVALID_HA 0x81 // Invalid host adapter number +#define SS_NO_DEVICE 0x82 // SCSI device not installed + +//***************************************************************************** +// %%% Host Adapter Status %%% +//***************************************************************************** + +#define HASTAT_OK 0x00 // Host adapter did not detect an // error +#define HASTAT_SEL_TO 0x11 // Selection Timeout +#define HASTAT_DO_DU 0x12 // Data overrun data underrun +#define HASTAT_BUS_FREE 0x13 // Unexpected bus free +#define HASTAT_PHASE_ERR 0x14 // Target bus phase sequence // failure +#define HASTAT_TIMEOUT 0x09 // Timed out while SRB was waiting to beprocessed. +#define HASTAT_COMMAND_TIMEOUT 0x0B // Adapter timed out processing SRB. +#define HASTAT_MESSAGE_REJECT 0x0D // While processing SRB, the // adapter received a MESSAGE +#define HASTAT_BUS_RESET 0x0E // A bus reset was detected. +#define HASTAT_PARITY_ERROR 0x0F // A parity error was detected. +#define HASTAT_REQUEST_SENSE_FAILED 0x10 // The adapter failed in issuing + +typedef struct { + + BYTE Cmd; // 00/000 ASPI command code = SC_EXEC_SCSI_CMD + BYTE Status; // 01/001 ASPI command status byte + BYTE HaId; // 02/002 ASPI host adapter number + BYTE Flags; // 03/003 ASPI request flags + DWORD Hdr_Rsvd; // 04/004 Reserved, MUST = 0 + + union { + + struct { + + BYTE Count; // 08/008 Number of host adapters present + BYTE SCSI_ID; // 09/009 SCSI ID of host adapter + BYTE ManagerId[16]; // 0A/010 String describing the manager + BYTE Identifier[16]; // 1A/026 String describing the host adapter + BYTE Unique[16]; // 2A/042 Host Adapter Unique parameters + BYTE ExtBuffer[8]; // 3A/058 Extended inquiry data + + } PACKED HAInquiry; + + struct { + + BYTE Target; // 08/008 Target's SCSI ID + BYTE Lun; // 09/009 Target's LUN number + BYTE DeviceType; // 0A/010 Target's peripheral device type + + } PACKED GetDeviceType; + + struct { + + BYTE Target; // 08/008 Target's SCSI ID + BYTE Lun; // 09/009 Target's LUN number + DWORD BufLen; // 0A/010 Data Allocation Length + BYTE SenseLen; // 0E/014 Sense Allocation Length + BYTE FAR *BufPointer; // 0F/015 Data Buffer Pointer + DWORD Rsvd1; // 13/019 Reserved, MUST = 0 + BYTE CDBLen; // 17/023 CDB Length = 6/10/12 + BYTE HaStat; // 18/024 Host Adapter Status + BYTE TargStat; // 19/025 Target Status + VOID FAR *PostProc; // 1A/026 Post routine + BYTE Rsvd2[34]; // 1E/030 Reserved, MUST = 0 + + union { + + struct { + + BYTE CDBByte[6]; // 40/064 SCSI CDB + BYTE SenseArea[SENSE_LEN+2]; // 46/070 Request Sense buffer + + } PACKED _6; + + struct { + + BYTE CDBByte[10]; // 40/064 SCSI CDB + BYTE SenseArea[SENSE_LEN+2]; // 4A/074 Request Sense buffer + + } PACKED _10; + + struct { + + BYTE CDBByte[12]; // 40/064 SCSI CDB + BYTE SenseArea[SENSE_LEN+2]; // 4C/076 Request Sense buffer + + } PACKED _12; + + } PACKED CmdLen; + + } PACKED ExecSCSICmd; + + struct { + + VOID FAR *SRBToAbort; // 08/008 Pointer to SRB to abort + + } PACKED Abort; + + struct { + + BYTE Target; // 08/008 Target's SCSI ID + BYTE Lun; // 09/009 Target's LUN number + BYTE ResetRsvd1[14]; // 0A/010 Reserved, MUST = 0 + BYTE HaStat; // 18/024 Host Adapter Status + BYTE TargStat; // 19/025 Target Status + VOID FAR *PostProc; // 1A/026 Post routine + BYTE ResetRsvd2[34]; // 1E/030 Reserved, MUST = 0 + + } Reset; + + } PACKED Type; + + } PACKED SRB; + +#endif //__ASPI16_H_ diff --git a/src/schily/scg/aspi-win32.h b/src/schily/scg/aspi-win32.h new file mode 100644 index 0000000..02fb5ef --- /dev/null +++ b/src/schily/scg/aspi-win32.h @@ -0,0 +1,196 @@ +#ifndef __ASPI_WIN32_H_ +#define __ASPI_WIN32_H_ + +#include + +/*************************************************************************** + ** SCSI MISCELLANEOUS EQUATES + ***************************************************************************/ +#define SENSE_LEN 14 /* Default sense buffer length */ +#define SRB_DIR_SCSI 0x00 /* Direction determined by SCSI */ +#define SRB_POSTING 0x01 /* Enable ASPI posting */ +#define SRB_ENABLE_RESIDUAL_COUNT 0x04 /* Enable residual byte count */ + /* reporting */ +#define SRB_DIR_IN 0x08 /* Transfer from SCSI target to */ + /* host */ +#define SRB_DIR_OUT 0x10 /* Transfer from host to SCSI */ + /* target */ +#define SRB_EVENT_NOTIFY 0x40 /* Enable ASPI event notification */ +#define RESIDUAL_COUNT_SUPPORTED 0x02 /* Extended buffer flag */ +#define MAX_SRB_TIMEOUT 1080001u /* 30 hour maximum timeout in sec */ +#define DEFAULT_SRB_TIMEOUT 1080001u /* use max.timeout by default */ + +/*************************************************************************** + ** ASPI command definitions + ***************************************************************************/ +#define SC_HA_INQUIRY 0x00 /* Host adapter inquiry */ +#define SC_GET_DEV_TYPE 0x01 /* Get device type */ +#define SC_EXEC_SCSI_CMD 0x02 /* Execute SCSI command */ +#define SC_ABORT_SRB 0x03 /* Abort an SRB */ +#define SC_RESET_DEV 0x04 /* SCSI bus device reset */ +#define SC_SET_HA_PARMS 0x05 /* Set HA parameters */ +#define SC_GET_DISK_INFO 0x06 /* Get Disk */ +#define SC_RESCAN_SCSI_BUS 0x07 /* Rebuild SCSI device map */ +#define SC_GETSET_TIMEOUTS 0x08 /* Get/Set target timeouts */ + + +/*************************************************************************** + ** SRB Status + ***************************************************************************/ +#define SS_PENDING 0x00 /* SRB being processed */ +#define SS_COMP 0x01 /* SRB completed without error */ +#define SS_ABORTED 0x02 /* SRB aborted */ +#define SS_ABORT_FAIL 0x03 /* Unable to abort SRB */ +#define SS_ERR 0x04 /* SRB completed with error */ +#define SS_INVALID_CMD 0x80 /* Invalid ASPI command */ +#define SS_INVALID_HA 0x81 /* Invalid host adapter number */ +#define SS_NO_DEVICE 0x82 /* SCSI device not installed */ +#define SS_INVALID_SRB 0xE0 /* Invalid parameter set in SRB */ +#define SS_OLD_MANAGER 0xE1 /* ASPI manager doesn't support */ + /* windows */ +#define SS_BUFFER_ALIGN 0xE1 /* Buffer not aligned (replaces */ + /* SS_OLD_MANAGER in Win32) */ +#define SS_ILLEGAL_MODE 0xE2 /* Unsupported Windows mode */ +#define SS_NO_ASPI 0xE3 /* No ASPI managers */ +#define SS_FAILED_INIT 0xE4 /* ASPI for windows failed init */ +#define SS_ASPI_IS_BUSY 0xE5 /* No resources available to */ + /* execute command */ +#define SS_BUFFER_TO_BIG 0xE6 /* Buffer size too big to handle */ +#define SS_BUFFER_TOO_BIG 0xE6 /* Correct spelling of 'too' */ +#define SS_MISMATCHED_COMPONENTS 0xE7 /* The DLLs/EXEs of ASPI don't */ + /* version check */ +#define SS_NO_ADAPTERS 0xE8 /* No host adapters to manager */ +#define SS_INSUFFICIENT_RESOURCES 0xE9 /* Couldn't allocate resources */ + /* needed to init */ +#define SS_ASPI_IS_SHUTDOWN 0xEA /* Call came to ASPI after */ + /* PROCESS_DETACH */ +#define SS_BAD_INSTALL 0xEB /* The DLL or other components */ + /* are installed wrong */ + +/*************************************************************************** + ** Host Adapter Status + ***************************************************************************/ +#define HASTAT_OK 0x00 /* No error detected by HA */ +#define HASTAT_SEL_TO 0x11 /* Selection Timeout */ +#define HASTAT_DO_DU 0x12 /* Data overrun/data underrun */ +#define HASTAT_BUS_FREE 0x13 /* Unexpected bus free */ +#define HASTAT_PHASE_ERR 0x14 /* Target bus phase sequence */ +#define HASTAT_TIMEOUT 0x09 /* Timed out while SRB was */ + /* waiting to be processed */ +#define HASTAT_COMMAND_TIMEOUT 0x0B /* Adapter timed out while */ + /* processing SRB */ +#define HASTAT_MESSAGE_REJECT 0x0D /* While processing the SRB, the */ + /* adapter received a MESSAGE */ +#define HASTAT_BUS_RESET 0x0E /* A bus reset was detected */ +#define HASTAT_PARITY_ERROR 0x0F /* A parity error was detected */ +#define HASTAT_REQUEST_SENSE_FAILED 0x10 /* The adapter failed in issuing */ + + +/*************************************************************************** + ** SRB - HOST ADAPTER INQUIRIY - SC_HA_INQUIRY (0) + ***************************************************************************/ +typedef struct { + BYTE SRB_Cmd; /* 00/000 ASPI command code == SC_HA_INQUIRY */ + BYTE SRB_Status; /* 01/001 ASPI command status byte */ + BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ + BYTE SRB_Flags; /* 03/003 ASPI request flags */ + DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ + BYTE HA_Count; /* 08/008 Number of host adapters present */ + BYTE HA_SCSI_ID; /* 09/009 SCSI ID of host adapter */ + BYTE HA_ManagerId[16]; /* 0a/010 String describing the manager */ + BYTE HA_Identifier[16]; /* 1a/026 String describing the host adapter */ + BYTE HA_Unique[16]; /* 2a/042 Host Adapter Unique parameters */ + WORD HA_Rsvd1; /* 3a/058 Reserved, must = 0 */ +} PACKED SRB_HAInquiry, *PSRB_HAInquiry, FAR *LPSRB_HAInquiry; + + +/*************************************************************************** + ** SRB - GET DEVICE TYPE - SC_GET_DEV_TYPE (1) + ***************************************************************************/ +typedef struct +{ + BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_GET_DEV_TYPE */ + BYTE SRB_Status; /* 01/001 ASPI command status byte */ + BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ + BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */ + DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ + BYTE SRB_Target; /* 08/008 Target's SCSI ID */ + BYTE SRB_Lun; /* 09/009 Target's LUN number */ + BYTE SRB_DeviceType; /* 0a/010 Target's peripheral device type */ + BYTE SRB_Rsvd1; /* 0b/011 Reserved, must = 0 */ +} PACKED SRB_GDEVBlock, *PSRB_GDEVBlock, FAR *LPSRB_GDEVBlock; + + +/*************************************************************************** + ** SRB - EXECUTE SCSI COMMAND - SC_EXEC_SCSI_CMD (2) + ***************************************************************************/ +typedef struct +{ + BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_EXEC_SCSI_CMD */ + BYTE SRB_Status; /* 01/001 ASPI command status byte */ + BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ + BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */ + DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ + BYTE SRB_Target; /* 08/008 Target's SCSI ID */ + BYTE SRB_Lun; /* 09/009 Target's LUN */ + WORD SRB_Rsvd1; /* 0a/010 Reserved for alignment */ + DWORD SRB_BufLen; /* 0c/012 Data Allocation Length */ + BYTE FAR *SRB_BufPointer; /* 10/016 Data Buffer Pointer */ + BYTE SRB_SenseLen; /* 14/020 Sense Allocation Length */ + BYTE SRB_CDBLen; /* 15/021 CDB Length */ + BYTE SRB_HaStat; /* 16/022 Host Adapter Status */ + BYTE SRB_TargStat; /* 17/023 Target Status */ + VOID FAR *SRB_PostProc; /* 18/024 Post routine */ + BYTE SRB_Rsvd2[20]; /* 1c/028 Reserved, must = 0 */ + BYTE CDBByte[16]; /* 30/048 SCSI CDB */ + BYTE SenseArea[SENSE_LEN+2]; /* 40/064 Request Sense buffer */ +} PACKED SRB_ExecSCSICmd, *PSRB_ExecSCSICmd, FAR *LPSRB_ExecSCSICmd; + + +typedef struct +{ + BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_ABORT_SRB */ + BYTE SRB_Status; /* 01/001 ASPI command status byte */ + BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ + BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */ + DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ + void *SRB_ToAbort; /* 08/008 Pointer to SRB to abort */ +} PACKED SRB_Abort, *PSRB_Abort, FAR *LPSRB_Abort; + + +/*************************************************************************** + ** SRB - BUS DEVICE RESET - SC_RESET_DEV (4) + ***************************************************************************/ +typedef struct +{ + BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_RESET_DEV */ + BYTE SRB_Status; /* 01/001 ASPI command status byte */ + BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ + DWORD SRB_Flags; /* 04/004 Reserved */ + BYTE SRB_Target; /* 08/008 Target's SCSI ID */ + BYTE SRB_Lun; /* 09/009 Target's LUN number */ + BYTE SRB_Rsvd1[12]; /* 0A/010 Reserved for alignment */ + BYTE SRB_HaStat; /* 16/022 Host Adapter Status */ + BYTE SRB_TargStat; /* 17/023 Target Status */ + VOID FAR *SRB_PostProc; /* 18/024 Post routine */ + BYTE SRB_Rsvd2[36]; /* 1C/028 Reserved, must = 0 */ +} SRB_BusDeviceReset, *PSRB_BusDeviceReset, FAR *LPSRB_BusDeviceReset; + +typedef struct tag_ASPI32BUFF +{ + PBYTE AB_BufPointer; + DWORD AB_BufLen; + DWORD AB_ZeroFill; + DWORD AB_Reserved; +} PACKED ASPI32BUFF, *PASPI32BUFF, FAR *LPASPI32BUFF; + +typedef struct +{ + BYTE SRB_Cmd; + BYTE SRB_Status; + BYTE SRB_HaId; + BYTE SRB_Flags; + DWORD SRB_Hdr_Rsvd; +} SRB, *PSRB, FAR *LPSRB; + +#endif diff --git a/src/schily/scg/scgcmd.h b/src/schily/scg/scgcmd.h new file mode 100644 index 0000000..4ce801b --- /dev/null +++ b/src/schily/scg/scgcmd.h @@ -0,0 +1,200 @@ +/* @(#)scgcmd.h 2.22 04/09/04 Copyright 1986 J. Schilling */ +/* + * Definitions for the SCSI 'scg_cmd' structure that has been created + * for the SCSI general driver 'scg' for SunOS and Solaris but + * now is used for wrapping general libscg SCSI transport requests. + * + * Copyright (c) 1986 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SCG_SCGCMD_H +#define _SCG_SCGCMD_H + +#include +#include + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ +#else +# if defined(_BIT_FIELDS_HTOL) /* Motorola byteorder */ +# else +/* + * #error will not work for all compilers (e.g. sunos4) + * The following line will abort compilation on all compilers + * if none of the above is defines. And that's what we want. + */ +error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined +# endif +#endif + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Leave these definitions here if possible to avoid the need to + * include scsireg.h which makes problems on some OS because these + * OS define the same types as in scsireg.h + */ + +/* + * SCSI status bits. + */ +#define ST_VU_00 0x01 /* Vendor unique */ +#define ST_CHK_COND 0x02 /* Check condition */ +#define ST_COND_MET 0x04 /* Condition met */ +#define ST_BUSY 0x08 /* Busy */ +#define ST_IS_SEND 0x10 /* Intermediate status send */ +#define ST_VU_05 0x20 /* Vendor unique */ +#define ST_VU_06 0x40 /* Vendor unique */ +#define ST_RSVD_07 0x80 /* Reserved */ + +/* + * Sense key values for extended sense. + */ +#define SC_NO_SENSE 0x00 +#define SC_RECOVERABLE_ERROR 0x01 +#define SC_NOT_READY 0x02 +#define SC_MEDIUM_ERROR 0x03 +#define SC_HARDWARE_ERROR 0x04 +#define SC_ILLEGAL_REQUEST 0x05 +#define SC_UNIT_ATTENTION 0x06 +#define SC_WRITE_PROTECT 0x07 +#define SC_BLANK_CHECK 0x08 +#define SC_VENDOR_UNIQUE 0x09 +#define SC_COPY_ABORTED 0x0A +#define SC_ABORTED_COMMAND 0x0B +#define SC_EQUAL 0x0C +#define SC_VOLUME_OVERFLOW 0x0D +#define SC_MISCOMPARE 0x0E +#define SC_RESERVED 0x0F + +/* + * Messages that SCSI can send. + */ +#define SC_COMMAND_COMPLETE 0x00 +#define SC_SYNCHRONOUS 0x01 +#define SC_SAVE_DATA_PTR 0x02 +#define SC_RESTORE_PTRS 0x03 +#define SC_DISCONNECT 0x04 +#define SC_ABORT 0x06 +#define SC_MSG_REJECT 0x07 +#define SC_NO_OP 0x08 +#define SC_PARITY 0x09 +#define SC_IDENTIFY 0x80 +#define SC_DR_IDENTIFY 0xc0 +#define SC_DEVICE_RESET 0x0c + +#define SC_G0_CDBLEN 6 /* Len of Group 0 commands */ +#define SC_G1_CDBLEN 10 /* Len of Group 1 commands */ +#define SC_G5_CDBLEN 12 /* Len of Group 5 commands */ + +#define SCG_MAX_CMD 24 /* 24 bytes max. size is supported */ +#define SCG_MAX_STATUS 3 /* XXX (sollte 4 allign.) Mamimum Status Len */ +#define SCG_MAX_SENSE 32 /* Mamimum Sense Len for auto Req. Sense */ + +#define DEF_SENSE_LEN 16 /* Default Sense Len */ +#define CCS_SENSE_LEN 18 /* Sense Len for CCS compatible devices */ + +struct scg_cmd { + caddr_t addr; /* Address of data in user space */ + int size; /* DMA count for data transfer */ + int flags; /* see below for definition */ + int cdb_len; /* Size of SCSI command in bytes */ + /* NOTE: rel 4 uses this field only */ + /* with commands not in group 1 or 2*/ + int sense_len; /* for intr() if -1 don't get sense */ + int timeout; /* timeout in seconds */ + /* NOTE: actual resolution depends */ + /* on driver implementation */ + int kdebug; /* driver kernel debug level */ + int resid; /* Bytes not transfered */ + int error; /* Error code from scgintr() */ + int ux_errno; /* UNIX error code */ +#ifdef comment +XXX struct scsi_status scb; ??? /* Status returnd by command */ +#endif + union { + struct scsi_status Scb; /* Status returnd by command */ + Uchar cmd_scb[SCG_MAX_STATUS]; + } u_scb; +#define scb u_scb.Scb +#ifdef comment +XXX struct scsi_sense sense; ??? /* Sense bytes from command */ +#endif + union { + struct scsi_sense Sense; /* Sense bytes from command */ + Uchar cmd_sense[SCG_MAX_SENSE]; + } u_sense; +#define sense u_sense.Sense + int sense_count; /* Number of bytes valid in sense */ + int target; /* SCSI target id */ + /* NOTE: The SCSI target id field */ + /* does not need to be filled unless */ + /* the low level transport is a real */ + /* scg driver. In this case the low */ + /* level transport routine of libscg */ + /* will fill in the needed value */ + union { /* SCSI command descriptor block */ + struct scsi_g0cdb g0_cdb; + struct scsi_g1cdb g1_cdb; + struct scsi_g5cdb g5_cdb; + Uchar cmd_cdb[SCG_MAX_CMD]; + } cdb; /* 24 bytes max. size is supported */ +}; + +#define dma_read flags /* 1 if DMA to Sun, 0 otherwise */ + +/* + * definition for flags field in scg_cmd struct + */ +#define SCG_RECV_DATA 0x0001 /* DMA direction to Sun */ +#define SCG_DISRE_ENA 0x0002 /* enable disconnect/reconnect */ +#define SCG_SILENT 0x0004 /* be silent on errors */ +#define SCG_CMD_RETRY 0x0008 /* enable retries */ +#define SCG_NOPARITY 0x0010 /* disable parity for this command */ + +/* + * definition for error field in scg_cmd struct + * + * The codes refer to SCSI general errors, not to device + * specific errors. Device specific errors are discovered + * by checking the sense data. + * The distinction between retryable and fatal is somewhat ad hoc. + */ +#define SCG_NO_ERROR 0 /* cdb transported without error */ + /* SCG_NO_ERROR incudes all commands */ + /* where the SCSI status is valid */ + +#define SCG_RETRYABLE 1 /* any other case e.g. SCSI bus busy */ + /* SCSI cdb could not be send, */ + /* includes DMA errors other than */ + /* DMA underrun */ + +#define SCG_FATAL 2 /* could not select target */ +#define SCG_TIMEOUT 3 /* driver timed out */ + + +#ifdef __cplusplus +} +#endif + +#endif /* _SCG_SCGCMD_H */ diff --git a/src/schily/scg/scgio.h b/src/schily/scg/scgio.h new file mode 100644 index 0000000..0080656 --- /dev/null +++ b/src/schily/scg/scgio.h @@ -0,0 +1,68 @@ +/* @(#)scgio.h 2.16 00/11/07 Copyright 1986 J. Schilling */ +/* + * Definitions for the SCSI general driver 'scg' + * + * Copyright (c) 1986 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _SCG_SCGIO_H +#define _SCG_SCGIO_H + +#ifndef _SCG_SCGCMD_H +#include +#endif + +#if defined(SVR4) +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__STDC__) || defined(SVR4) +#define SCGIOCMD _IOWR('G', 1, struct scg_cmd) /* do a SCSI cmd */ +#define SCGIORESET _IO('G', 2) /* reset SCSI bus */ +#define SCGIOGDISRE _IOR('G', 4, int) /* get sc disre Val*/ +#define SCGIOSDISRE _IOW('G', 5, int) /* set sc disre Val*/ +#define SCGIOIDBG _IO('G', 100) /* Inc Debug Val */ +#define SCGIODDBG _IO('G', 101) /* Dec Debug Val */ +#define SCGIOGDBG _IOR('G', 102, int) /* get Debug Val */ +#define SCGIOSDBG _IOW('G', 103, int) /* set Debug Val */ +#define SCIOGDBG _IOR('G', 104, int) /* get sc Debug Val*/ +#define SCIOSDBG _IOW('G', 105, int) /* set sc Debug Val*/ +#else +#define SCGIOCMD _IOWR(G, 1, struct scg_cmd) /* do a SCSI cmd */ +#define SCGIORESET _IO(G, 2) /* reset SCSI bus */ +#define SCGIOGDISRE _IOR(G, 4, int) /* get sc disre Val*/ +#define SCGIOSDISRE _IOW(G, 5, int) /* set sc disre Val*/ +#define SCGIOIDBG _IO(G, 100) /* Inc Debug Val */ +#define SCGIODDBG _IO(G, 101) /* Dec Debug Val */ +#define SCGIOGDBG _IOR(G, 102, int) /* get Debug Val */ +#define SCGIOSDBG _IOW(G, 103, int) /* set Debug Val */ +#define SCIOGDBG _IOR(G, 104, int) /* get sc Debug Val*/ +#define SCIOSDBG _IOW(G, 105, int) /* set sc Debug Val*/ +#endif + +#define SCGIO_CMD SCGIOCMD /* backward ccompatibility */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SCG_SCGIO_H */ diff --git a/src/schily/scg/scgops.h b/src/schily/scg/scgops.h new file mode 100644 index 0000000..7df3897 --- /dev/null +++ b/src/schily/scg/scgops.h @@ -0,0 +1,69 @@ +/* @(#)scgops.h 1.5 02/10/19 Copyright 2000 J. Schilling */ +/* + * Copyright (c) 2000 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _SCG_SCGOPS_H +#define _SCG_SCGOPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scg_ops { + int (*scgo_send) __PR((SCSI *scgp)); + + char * (*scgo_version) __PR((SCSI *scgp, int what)); +#ifdef EOF /* stdio.h has been included */ + int (*scgo_help) __PR((SCSI *scgp, FILE *f)); +#else + int (*scgo_help) __PR((SCSI *scgp, void *f)); +#endif + int (*scgo_open) __PR((SCSI *scgp, char *device)); + int (*scgo_close) __PR((SCSI *scgp)); + long (*scgo_maxdma) __PR((SCSI *scgp, long amt)); + void * (*scgo_getbuf) __PR((SCSI *scgp, long amt)); + void (*scgo_freebuf) __PR((SCSI *scgp)); + + + BOOL (*scgo_havebus) __PR((SCSI *scgp, int busno)); + int (*scgo_fileno) __PR((SCSI *scgp, int busno, int tgt, int tlun)); + int (*scgo_initiator_id) __PR((SCSI *scgp)); + int (*scgo_isatapi) __PR((SCSI *scgp)); + int (*scgo_reset) __PR((SCSI *scgp, int what)); +} scg_ops_t; + +#define SCGO_SEND(scgp) (*(scgp)->ops->scgo_send)(scgp) +#define SCGO_VERSION(scgp, what) (*(scgp)->ops->scgo_version)(scgp, what) +#define SCGO_HELP(scgp, f) (*(scgp)->ops->scgo_help)(scgp, f) +#define SCGO_OPEN(scgp, device) (*(scgp)->ops->scgo_open)(scgp, device) +#define SCGO_CLOSE(scgp) (*(scgp)->ops->scgo_close)(scgp) +#define SCGO_MAXDMA(scgp, amt) (*(scgp)->ops->scgo_maxdma)(scgp, amt) +#define SCGO_GETBUF(scgp, amt) (*(scgp)->ops->scgo_getbuf)(scgp, amt) +#define SCGO_FREEBUF(scgp) (*(scgp)->ops->scgo_freebuf)(scgp) +#define SCGO_HAVEBUS(scgp, busno) (*(scgp)->ops->scgo_havebus)(scgp, busno) +#define SCGO_FILENO(scgp, busno, tgt, tlun) (*(scgp)->ops->scgo_fileno)(scgp, busno, tgt, tlun) +#define SCGO_INITIATOR_ID(scgp) (*(scgp)->ops->scgo_initiator_id)(scgp) +#define SCGO_ISATAPI(scgp) (*(scgp)->ops->scgo_isatapi)(scgp) +#define SCGO_RESET(scgp, what) (*(scgp)->ops->scgo_reset)(scgp, what) + +#ifdef __cplusplus +} +#endif + +#endif /* _SCG_SCGOPS_H */ diff --git a/src/schily/scg/scsicdb.h b/src/schily/scg/scsicdb.h new file mode 100644 index 0000000..55e8188 --- /dev/null +++ b/src/schily/scg/scsicdb.h @@ -0,0 +1,249 @@ +/* @(#)scsicdb.h 2.19 04/09/04 Copyright 1986 J. Schilling */ +/* + * Definitions for the SCSI Command Descriptor Block + * + * Copyright (c) 1986 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SCG_SCSICDB_H +#define _SCG_SCSICDB_H + +#ifndef _UTYPES_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif +/* + * SCSI Operation codes. + */ +#define SC_TEST_UNIT_READY 0x00 +#define SC_REZERO_UNIT 0x01 +#define SC_REQUEST_SENSE 0x03 +#define SC_FORMAT 0x04 +#define SC_FORMAT_TRACK 0x06 +#define SC_REASSIGN_BLOCK 0x07 /* CCS only */ +#define SC_SEEK 0x0b +#define SC_TRANSLATE 0x0f /* ACB4000 only */ +#define SC_INQUIRY 0x12 /* CCS only */ +#define SC_MODE_SELECT 0x15 +#define SC_RESERVE 0x16 +#define SC_RELEASE 0x17 +#define SC_MODE_SENSE 0x1a +#define SC_START 0x1b +#define SC_READ_DEFECT_LIST 0x37 /* CCS only, group 1 */ +#define SC_READ_BUFFER 0x3c /* CCS only, group 1 */ + /* + * Note, these two commands use identical command blocks for all + * controllers except the Adaptec ACB 4000 which sets bit 1 of byte 1. + */ +#define SC_READ 0x08 +#define SC_WRITE 0x0a +#define SC_EREAD 0x28 /* 10 byte read */ +#define SC_EWRITE 0x2a /* 10 byte write */ +#define SC_WRITE_VERIFY 0x2e /* 10 byte write+verify */ +#define SC_WRITE_FILE_MARK 0x10 +#define SC_UNKNOWN 0xff /* cmd list terminator */ + + +/* + * Standard SCSI control blocks. + * These go in or out over the SCSI bus. + */ + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_g0cdb { /* scsi group 0 command description block */ + Uchar cmd; /* command code */ + Ucbit high_addr : 5; /* high part of block address */ + Ucbit lun : 3; /* logical unit number */ + Uchar mid_addr; /* middle part of block address */ + Uchar low_addr; /* low part of block address */ + Uchar count; /* transfer length */ + Ucbit link : 1; /* link (another command follows) */ + Ucbit fr : 1; /* flag request (interrupt at completion) */ + Ucbit naca : 1; /* Normal ACA (Auto Contingent Allegiance) */ + Ucbit rsvd : 3; /* reserved */ + Ucbit vu_56 : 1; /* vendor unique (byte 5 bit 6) */ + Ucbit vu_57 : 1; /* vendor unique (byte 5 bit 7) */ +}; + +#else /* Motorola byteorder */ + +struct scsi_g0cdb { /* scsi group 0 command description block */ + Uchar cmd; /* command code */ + Ucbit lun : 3; /* logical unit number */ + Ucbit high_addr : 5; /* high part of block address */ + Uchar mid_addr; /* middle part of block address */ + Uchar low_addr; /* low part of block address */ + Uchar count; /* transfer length */ + Ucbit vu_57 : 1; /* vendor unique (byte 5 bit 7) */ + Ucbit vu_56 : 1; /* vendor unique (byte 5 bit 6) */ + Ucbit rsvd : 3; /* reserved */ + Ucbit naca : 1; /* Normal ACA (Auto Contingent Allegiance) */ + Ucbit fr : 1; /* flag request (interrupt at completion) */ + Ucbit link : 1; /* link (another command follows) */ +}; +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_g1cdb { /* scsi group 1 command description block */ + Uchar cmd; /* command code */ + Ucbit reladr : 1; /* address is relative */ + Ucbit res : 4; /* reserved bits 1-4 of byte 1 */ + Ucbit lun : 3; /* logical unit number */ + Uchar addr[4]; /* logical block address */ + Uchar res6; /* reserved byte 6 */ + Uchar count[2]; /* transfer length */ + Ucbit link : 1; /* link (another command follows) */ + Ucbit fr : 1; /* flag request (interrupt at completion) */ + Ucbit naca : 1; /* Normal ACA (Auto Contingent Allegiance) */ + Ucbit rsvd : 3; /* reserved */ + Ucbit vu_96 : 1; /* vendor unique (byte 5 bit 6) */ + Ucbit vu_97 : 1; /* vendor unique (byte 5 bit 7) */ +}; + +#else /* Motorola byteorder */ + +struct scsi_g1cdb { /* scsi group 1 command description block */ + Uchar cmd; /* command code */ + Ucbit lun : 3; /* logical unit number */ + Ucbit res : 4; /* reserved bits 1-4 of byte 1 */ + Ucbit reladr : 1; /* address is relative */ + Uchar addr[4]; /* logical block address */ + Uchar res6; /* reserved byte 6 */ + Uchar count[2]; /* transfer length */ + Ucbit vu_97 : 1; /* vendor unique (byte 5 bit 7) */ + Ucbit vu_96 : 1; /* vendor unique (byte 5 bit 6) */ + Ucbit rsvd : 3; /* reserved */ + Ucbit naca : 1; /* Normal ACA (Auto Contingent Allegiance) */ + Ucbit fr : 1; /* flag request (interrupt at completion) */ + Ucbit link : 1; /* link (another command follows) */ +}; +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_g5cdb { /* scsi group 5 command description block */ + Uchar cmd; /* command code */ + Ucbit reladr : 1; /* address is relative */ + Ucbit res : 4; /* reserved bits 1-4 of byte 1 */ + Ucbit lun : 3; /* logical unit number */ + Uchar addr[4]; /* logical block address */ + Uchar count[4]; /* transfer length */ + Uchar res10; /* reserved byte 10 */ + Ucbit link : 1; /* link (another command follows) */ + Ucbit fr : 1; /* flag request (interrupt at completion) */ + Ucbit naca : 1; /* Normal ACA (Auto Contingent Allegiance) */ + Ucbit rsvd : 3; /* reserved */ + Ucbit vu_B6 : 1; /* vendor unique (byte B bit 6) */ + Ucbit vu_B7 : 1; /* vendor unique (byte B bit 7) */ +}; + +#else /* Motorola byteorder */ + +struct scsi_g5cdb { /* scsi group 5 command description block */ + Uchar cmd; /* command code */ + Ucbit lun : 3; /* logical unit number */ + Ucbit res : 4; /* reserved bits 1-4 of byte 1 */ + Ucbit reladr : 1; /* address is relative */ + Uchar addr[4]; /* logical block address */ + Uchar count[4]; /* transfer length */ + Uchar res10; /* reserved byte 10 */ + Ucbit vu_B7 : 1; /* vendor unique (byte B bit 7) */ + Ucbit vu_B6 : 1; /* vendor unique (byte B bit 6) */ + Ucbit rsvd : 3; /* reserved */ + Ucbit naca : 1; /* Normal ACA (Auto Contingent Allegiance) */ + Ucbit fr : 1; /* flag request (interrupt at completion) */ + Ucbit link : 1; /* link (another command follows) */ +}; +#endif + +#define g0_cdbaddr(cdb, a) ((cdb)->high_addr = (a) >> 16,\ + (cdb)->mid_addr = ((a) >> 8) & 0xFF,\ + (cdb)->low_addr = (a) & 0xFF) + +#define g1_cdbaddr(cdb, a) ((cdb)->addr[0] = (a) >> 24,\ + (cdb)->addr[1] = ((a) >> 16)& 0xFF,\ + (cdb)->addr[2] = ((a) >> 8) & 0xFF,\ + (cdb)->addr[3] = (a) & 0xFF) + +#define g5_cdbaddr(cdb, a) g1_cdbaddr(cdb, a) + + +#define g0_cdblen(cdb, len) ((cdb)->count = (len)) + +#define g1_cdblen(cdb, len) ((cdb)->count[0] = ((len) >> 8) & 0xFF,\ + (cdb)->count[1] = (len) & 0xFF) + +#define g5_cdblen(cdb, len) ((cdb)->count[0] = (len) >> 24L,\ + (cdb)->count[1] = ((len) >> 16L)& 0xFF,\ + (cdb)->count[2] = ((len) >> 8L) & 0xFF,\ + (cdb)->count[3] = (len) & 0xFF) + +/*#define XXXXX*/ +#ifdef XXXXX +#define i_to_long(a, i) (((Uchar *)(a))[0] = ((i) >> 24)& 0xFF,\ + ((Uchar *)(a))[1] = ((i) >> 16)& 0xFF,\ + ((Uchar *)(a))[2] = ((i) >> 8) & 0xFF,\ + ((Uchar *)(a))[3] = (i) & 0xFF) + +#define i_to_3_byte(a, i) (((Uchar *)(a))[0] = ((i) >> 16)& 0xFF,\ + ((Uchar *)(a))[1] = ((i) >> 8) & 0xFF,\ + ((Uchar *)(a))[2] = (i) & 0xFF) + +#define i_to_4_byte(a, i) (((Uchar *)(a))[0] = ((i) >> 24)& 0xFF,\ + ((Uchar *)(a))[1] = ((i) >> 16)& 0xFF,\ + ((Uchar *)(a))[2] = ((i) >> 8) & 0xFF,\ + ((Uchar *)(a))[3] = (i) & 0xFF) + +#define i_to_short(a, i) (((Uchar *)(a))[0] = ((i) >> 8) & 0xFF,\ + ((Uchar *)(a))[1] = (i) & 0xFF) + +#define a_to_u_short(a) ((unsigned short) \ + ((((Uchar*) a)[1] & 0xFF) | \ + (((Uchar*) a)[0] << 8 & 0xFF00))) + +#define a_to_3_byte(a) ((Ulong) \ + ((((Uchar*) a)[2] & 0xFF) | \ + (((Uchar*) a)[1] << 8 & 0xFF00) | \ + (((Uchar*) a)[0] << 16 & 0xFF0000))) + +#ifdef __STDC__ +#define a_to_u_long(a) ((Ulong) \ + ((((Uchar*) a)[3] & 0xFF) | \ + (((Uchar*) a)[2] << 8 & 0xFF00) | \ + (((Uchar*) a)[1] << 16 & 0xFF0000) | \ + (((Uchar*) a)[0] << 24 & 0xFF000000UL))) +#else +#define a_to_u_long(a) ((Ulong) \ + ((((Uchar*) a)[3] & 0xFF) | \ + (((Uchar*) a)[2] << 8 & 0xFF00) | \ + (((Uchar*) a)[1] << 16 & 0xFF0000) | \ + (((Uchar*) a)[0] << 24 & 0xFF000000))) +#endif +#endif /* XXXX */ + + +#ifdef __cplusplus +} +#endif + +#endif /* _SCG_SCSICDB_H */ diff --git a/src/schily/scg/scsidefs.h b/src/schily/scg/scsidefs.h new file mode 100644 index 0000000..b01c9bc --- /dev/null +++ b/src/schily/scg/scsidefs.h @@ -0,0 +1,111 @@ +/* @(#)scsidefs.h 1.28 04/09/04 Copyright 1988 J. Schilling */ +/* + * Definitions for SCSI devices i.e. for error strings in scsierrs.c + * + * Copyright (c) 1988 J. Schilling + */ +/*@@C@@*/ + +#ifndef _SCG_SCSIDEFS_H +#define _SCG_SCSIDEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Disks + */ +#ifdef DEV_UNKNOWN +/* + * True64 defines DEV_UNKNOWN in /usr/include/sys/devio.h as "UNKNOWN" + */ +#undef DEV_UNKNOWN +#endif +#define DEV_UNKNOWN 0 +#define DEV_ACB40X0 1 +#define DEV_ACB4000 2 +#define DEV_ACB4010 3 +#define DEV_ACB4070 4 +#define DEV_ACB5500 5 +#define DEV_ACB4520A 6 +#define DEV_ACB4525 7 +#define DEV_MD21 8 +#define DEV_MD23 9 +#define DEV_NON_CCS_DSK 10 +#define DEV_CCS_GENDISK 11 + +/* + * Tapes + */ +#define DEV_MT02 100 +#define DEV_SC4000 101 + +/* + * Printer + */ +#define DEV_PRT 200 + +/* + * Processors + */ +#define DEV_PROC 300 + +/* + * Worm + */ +#define DEV_WORM 400 +#define DEV_RXT800S 401 + +/* + * CD-ROM + */ +#define DEV_CDROM 500 +#define DEV_MMC_CDROM 501 +#define DEV_MMC_CDR 502 +#define DEV_MMC_CDRW 503 +#define DEV_MMC_DVD 504 +#define DEV_MMC_DVD_WR 505 + +#define DEV_CDD_521_OLD 510 +#define DEV_CDD_521 511 +#define DEV_CDD_522 512 +#define DEV_PCD_600 513 +#define DEV_CDD_2000 514 +#define DEV_CDD_2600 515 +#define DEV_TYUDEN_EW50 516 +#define DEV_YAMAHA_CDR_100 520 +#define DEV_YAMAHA_CDR_400 521 +#define DEV_PLASMON_RF_4100 530 +#define DEV_SONY_CDU_924 540 +#define DEV_RICOH_RO_1420C 550 +#define DEV_RICOH_RO_1060C 551 +#define DEV_TEAC_CD_R50S 560 +#define DEV_MATSUSHITA_7501 570 +#define DEV_MATSUSHITA_7502 571 +#define DEV_PIONEER_DW_S114X 580 +#define DEV_PIONEER_DVDR_S101 581 + +/* + * Scanners + */ +#define DEV_HRSCAN 600 +#define DEV_MS300A 601 + +/* + * Optical memory + */ +#define DEV_SONY_SMO 700 + + +#define old_acb(d) (((d) == DEV_ACB40X0) || \ + ((d) == DEV_ACB4000) || ((d) == DEV_ACB4010) || \ + ((d) == DEV_ACB4070) || ((d) == DEV_ACB5500)) + +#define is_ccs(d) (!old_acb(d)) + +#ifdef __cplusplus +} +#endif + +#endif /* _SCG_SCSIDEFS_H */ diff --git a/src/schily/scg/scsireg.h b/src/schily/scg/scsireg.h new file mode 100644 index 0000000..f835fb6 --- /dev/null +++ b/src/schily/scg/scsireg.h @@ -0,0 +1,1229 @@ +/* @(#)scsireg.h 1.31 04/09/04 Copyright 1987 J. Schilling */ +/* + * usefull definitions for dealing with CCS SCSI - devices + * + * Copyright (c) 1987 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SCG_SCSIREG_H +#define _SCG_SCSIREG_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_inquiry { + Ucbit type : 5; /* 0 */ + Ucbit qualifier : 3; /* 0 */ + + Ucbit type_modifier : 7; /* 1 */ + Ucbit removable : 1; /* 1 */ + + Ucbit ansi_version : 3; /* 2 */ + Ucbit ecma_version : 3; /* 2 */ + Ucbit iso_version : 2; /* 2 */ + + Ucbit data_format : 4; /* 3 */ + Ucbit res3_54 : 2; /* 3 */ + Ucbit termiop : 1; /* 3 */ + Ucbit aenc : 1; /* 3 */ + + Ucbit add_len : 8; /* 4 */ + Ucbit sense_len : 8; /* 5 */ /* only Emulex ??? */ + Ucbit res2 : 8; /* 6 */ + + Ucbit softreset : 1; /* 7 */ + Ucbit cmdque : 1; + Ucbit res7_2 : 1; + Ucbit linked : 1; + Ucbit sync : 1; + Ucbit wbus16 : 1; + Ucbit wbus32 : 1; + Ucbit reladr : 1; /* 7 */ + + char vendor_info[8]; /* 8 */ + char prod_ident[16]; /* 16 */ + char prod_revision[4]; /* 32 */ +#ifdef comment + char vendor_uniq[20]; /* 36 */ + char reserved[40]; /* 56 */ +#endif +}; /* 96 */ + +#else /* Motorola byteorder */ + +struct scsi_inquiry { + Ucbit qualifier : 3; /* 0 */ + Ucbit type : 5; /* 0 */ + + Ucbit removable : 1; /* 1 */ + Ucbit type_modifier : 7; /* 1 */ + + Ucbit iso_version : 2; /* 2 */ + Ucbit ecma_version : 3; + Ucbit ansi_version : 3; /* 2 */ + + Ucbit aenc : 1; /* 3 */ + Ucbit termiop : 1; + Ucbit res3_54 : 2; + Ucbit data_format : 4; /* 3 */ + + Ucbit add_len : 8; /* 4 */ + Ucbit sense_len : 8; /* 5 */ /* only Emulex ??? */ + Ucbit res2 : 8; /* 6 */ + Ucbit reladr : 1; /* 7 */ + Ucbit wbus32 : 1; + Ucbit wbus16 : 1; + Ucbit sync : 1; + Ucbit linked : 1; + Ucbit res7_2 : 1; + Ucbit cmdque : 1; + Ucbit softreset : 1; + char vendor_info[8]; /* 8 */ + char prod_ident[16]; /* 16 */ + char prod_revision[4]; /* 32 */ +#ifdef comment + char vendor_uniq[20]; /* 36 */ + char reserved[40]; /* 56 */ +#endif +}; /* 96 */ +#endif + +#ifdef __SCG_COMPAT__ +#define info vendor_info +#define ident prod_ident +#define revision prod_revision +#endif + +/* Peripheral Device Qualifier */ + +#define INQ_DEV_PRESENT 0x00 /* Physical device present */ +#define INQ_DEV_NOTPR 0x01 /* Physical device not present */ +#define INQ_DEV_RES 0x02 /* Reserved */ +#define INQ_DEV_NOTSUP 0x03 /* Logical unit not supported */ + +/* Peripheral Device Type */ + +#define INQ_DASD 0x00 /* Direct-access device (disk) */ +#define INQ_SEQD 0x01 /* Sequential-access device (tape) */ +#define INQ_PRTD 0x02 /* Printer device */ +#define INQ_PROCD 0x03 /* Processor device */ +#define INQ_OPTD 0x04 /* Write once device (optical disk) */ +#define INQ_WORM 0x04 /* Write once device (optical disk) */ +#define INQ_ROMD 0x05 /* CD-ROM device */ +#define INQ_SCAN 0x06 /* Scanner device */ +#define INQ_OMEM 0x07 /* Optical Memory device */ +#define INQ_JUKE 0x08 /* Medium Changer device (jukebox) */ +#define INQ_COMM 0x09 /* Communications device */ +#define INQ_IT8_1 0x0A /* IT8 */ +#define INQ_IT8_2 0x0B /* IT8 */ +#define INQ_STARR 0x0C /* Storage array device */ +#define INQ_ENCL 0x0D /* Enclosure services device */ +#define INQ_SDAD 0x0E /* Simplyfied direct-access device */ +#define INQ_OCRW 0x0F /* Optical card reader/writer device */ +#define INQ_BRIDGE 0x10 /* Bridging expander device */ +#define INQ_OSD 0x11 /* Object based storage device */ +#define INQ_ADC 0x12 /* Automation/Drive interface */ +#define INQ_WELLKNOWN 0x1E /* Well known logical unit */ +#define INQ_NODEV 0x1F /* Unknown or no device */ +#define INQ_NOTPR 0x1F /* Logical unit not present (SCSI-1) */ + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_mode_header { + Ucbit sense_data_len : 8; + Uchar medium_type; + Ucbit res2 : 4; + Ucbit cache : 1; + Ucbit res : 2; + Ucbit write_prot : 1; + Uchar blockdesc_len; +}; + +#else /* Motorola byteorder */ + +struct scsi_mode_header { + Ucbit sense_data_len : 8; + Uchar medium_type; + Ucbit write_prot : 1; + Ucbit res : 2; + Ucbit cache : 1; + Ucbit res2 : 4; + Uchar blockdesc_len; +}; +#endif + +struct scsi_modesel_header { + Ucbit sense_data_len : 8; + Uchar medium_type; + Ucbit res2 : 8; + Uchar blockdesc_len; +}; + +struct scsi_mode_blockdesc { + Uchar density; + Uchar nlblock[3]; + Ucbit res : 8; + Uchar lblen[3]; +}; + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct acb_mode_data { + Uchar listformat; + Uchar ncyl[2]; + Uchar nhead; + Uchar start_red_wcurrent[2]; + Uchar start_precomp[2]; + Uchar landing_zone; + Uchar step_rate; + Ucbit : 2; + Ucbit hard_sec : 1; + Ucbit fixed_media : 1; + Ucbit : 4; + Uchar sect_per_trk; +}; + +#else /* Motorola byteorder */ + +struct acb_mode_data { + Uchar listformat; + Uchar ncyl[2]; + Uchar nhead; + Uchar start_red_wcurrent[2]; + Uchar start_precomp[2]; + Uchar landing_zone; + Uchar step_rate; + Ucbit : 4; + Ucbit fixed_media : 1; + Ucbit hard_sec : 1; + Ucbit : 2; + Uchar sect_per_trk; +}; +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_mode_page_header { + Ucbit p_code : 6; + Ucbit res : 1; + Ucbit parsave : 1; + Uchar p_len; +}; + +/* + * This is a hack that allows mode pages without + * any further bitfileds to be defined bitorder independent. + */ +#define MP_P_CODE \ + Ucbit p_code : 6; \ + Ucbit p_res : 1; \ + Ucbit parsave : 1 + +#else /* Motorola byteorder */ + +struct scsi_mode_page_header { + Ucbit parsave : 1; + Ucbit res : 1; + Ucbit p_code : 6; + Uchar p_len; +}; + +/* + * This is a hack that allows mode pages without + * any further bitfileds to be defined bitorder independent. + */ +#define MP_P_CODE \ + Ucbit parsave : 1; \ + Ucbit p_res : 1; \ + Ucbit p_code : 6 + +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_mode_page_01 { /* Error recovery Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x0A = 12 Bytes */ + Ucbit disa_correction : 1; /* Byte 2 */ + Ucbit term_on_rec_err : 1; + Ucbit report_rec_err : 1; + Ucbit en_early_corr : 1; + Ucbit read_continuous : 1; + Ucbit tranfer_block : 1; + Ucbit en_auto_reall_r : 1; + Ucbit en_auto_reall_w : 1; /* Byte 2 */ + Uchar rd_retry_count; /* Byte 3 */ + Uchar correction_span; + char head_offset_count; + char data_strobe_offset; + Uchar res; + Uchar wr_retry_count; + Uchar res_tape[2]; + Uchar recov_timelim[2]; +}; + +#else /* Motorola byteorder */ + +struct scsi_mode_page_01 { /* Error recovery Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x0A = 12 Bytes */ + Ucbit en_auto_reall_w : 1; /* Byte 2 */ + Ucbit en_auto_reall_r : 1; + Ucbit tranfer_block : 1; + Ucbit read_continuous : 1; + Ucbit en_early_corr : 1; + Ucbit report_rec_err : 1; + Ucbit term_on_rec_err : 1; + Ucbit disa_correction : 1; /* Byte 2 */ + Uchar rd_retry_count; /* Byte 3 */ + Uchar correction_span; + char head_offset_count; + char data_strobe_offset; + Uchar res; + Uchar wr_retry_count; + Uchar res_tape[2]; + Uchar recov_timelim[2]; +}; +#endif + + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_mode_page_02 { /* Device dis/re connect Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x0E = 16 Bytes */ + Uchar buf_full_ratio; + Uchar buf_empt_ratio; + Uchar bus_inact_limit[2]; + Uchar disc_time_limit[2]; + Uchar conn_time_limit[2]; + Uchar max_burst_size[2]; /* Start SCSI-2 */ + Ucbit data_tr_dis_ctl : 2; + Ucbit : 6; + Uchar res[3]; +}; + +#else /* Motorola byteorder */ + +struct scsi_mode_page_02 { /* Device dis/re connect Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x0E = 16 Bytes */ + Uchar buf_full_ratio; + Uchar buf_empt_ratio; + Uchar bus_inact_limit[2]; + Uchar disc_time_limit[2]; + Uchar conn_time_limit[2]; + Uchar max_burst_size[2]; /* Start SCSI-2 */ + Ucbit : 6; + Ucbit data_tr_dis_ctl : 2; + Uchar res[3]; +}; +#endif + +#define DTDC_DATADONE 0x01 /* + * Target may not disconnect once + * data transfer is started until + * all data successfully transferred. + */ + +#define DTDC_CMDDONE 0x03 /* + * Target may not disconnect once + * data transfer is started until + * command completed. + */ + + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_mode_page_03 { /* Direct access format Paramters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x16 = 24 Bytes */ + Uchar trk_per_zone[2]; + Uchar alt_sec_per_zone[2]; + Uchar alt_trk_per_zone[2]; + Uchar alt_trk_per_vol[2]; + Uchar sect_per_trk[2]; + Uchar bytes_per_phys_sect[2]; + Uchar interleave[2]; + Uchar trk_skew[2]; + Uchar cyl_skew[2]; + Ucbit : 3; + Ucbit inhibit_save : 1; + Ucbit fmt_by_surface : 1; + Ucbit removable : 1; + Ucbit hard_sec : 1; + Ucbit soft_sec : 1; + Uchar res[3]; +}; + +#else /* Motorola byteorder */ + +struct scsi_mode_page_03 { /* Direct access format Paramters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x16 = 24 Bytes */ + Uchar trk_per_zone[2]; + Uchar alt_sec_per_zone[2]; + Uchar alt_trk_per_zone[2]; + Uchar alt_trk_per_vol[2]; + Uchar sect_per_trk[2]; + Uchar bytes_per_phys_sect[2]; + Uchar interleave[2]; + Uchar trk_skew[2]; + Uchar cyl_skew[2]; + Ucbit soft_sec : 1; + Ucbit hard_sec : 1; + Ucbit removable : 1; + Ucbit fmt_by_surface : 1; + Ucbit inhibit_save : 1; + Ucbit : 3; + Uchar res[3]; +}; +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_mode_page_04 { /* Rigid disk Geometry Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x16 = 24 Bytes */ + Uchar ncyl[3]; + Uchar nhead; + Uchar start_precomp[3]; + Uchar start_red_wcurrent[3]; + Uchar step_rate[2]; + Uchar landing_zone[3]; + Ucbit rot_pos_locking : 2; /* Start SCSI-2 */ + Ucbit : 6; /* Start SCSI-2 */ + Uchar rotational_off; + Uchar res1; + Uchar rotation_rate[2]; + Uchar res2[2]; +}; + +#else /* Motorola byteorder */ + +struct scsi_mode_page_04 { /* Rigid disk Geometry Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x16 = 24 Bytes */ + Uchar ncyl[3]; + Uchar nhead; + Uchar start_precomp[3]; + Uchar start_red_wcurrent[3]; + Uchar step_rate[2]; + Uchar landing_zone[3]; + Ucbit : 6; /* Start SCSI-2 */ + Ucbit rot_pos_locking : 2; /* Start SCSI-2 */ + Uchar rotational_off; + Uchar res1; + Uchar rotation_rate[2]; + Uchar res2[2]; +}; +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_mode_page_05 { /* Flexible disk Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x1E = 32 Bytes */ + Uchar transfer_rate[2]; + Uchar nhead; + Uchar sect_per_trk; + Uchar bytes_per_phys_sect[2]; + Uchar ncyl[2]; + Uchar start_precomp[2]; + Uchar start_red_wcurrent[2]; + Uchar step_rate[2]; + Uchar step_pulse_width; + Uchar head_settle_delay[2]; + Uchar motor_on_delay; + Uchar motor_off_delay; + Ucbit spc : 4; + Ucbit : 4; + Ucbit : 5; + Ucbit mo : 1; + Ucbit ssn : 1; + Ucbit trdy : 1; + Uchar write_compensation; + Uchar head_load_delay; + Uchar head_unload_delay; + Ucbit pin_2_use : 4; + Ucbit pin_34_use : 4; + Ucbit pin_1_use : 4; + Ucbit pin_4_use : 4; + Uchar rotation_rate[2]; + Uchar res[2]; +}; + +#else /* Motorola byteorder */ + +struct scsi_mode_page_05 { /* Flexible disk Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x1E = 32 Bytes */ + Uchar transfer_rate[2]; + Uchar nhead; + Uchar sect_per_trk; + Uchar bytes_per_phys_sect[2]; + Uchar ncyl[2]; + Uchar start_precomp[2]; + Uchar start_red_wcurrent[2]; + Uchar step_rate[2]; + Uchar step_pulse_width; + Uchar head_settle_delay[2]; + Uchar motor_on_delay; + Uchar motor_off_delay; + Ucbit trdy : 1; + Ucbit ssn : 1; + Ucbit mo : 1; + Ucbit : 5; + Ucbit : 4; + Ucbit spc : 4; + Uchar write_compensation; + Uchar head_load_delay; + Uchar head_unload_delay; + Ucbit pin_34_use : 4; + Ucbit pin_2_use : 4; + Ucbit pin_4_use : 4; + Ucbit pin_1_use : 4; + Uchar rotation_rate[2]; + Uchar res[2]; +}; +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_mode_page_07 { /* Verify Error recovery */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x0A = 12 Bytes */ + Ucbit disa_correction : 1; /* Byte 2 */ + Ucbit term_on_rec_err : 1; + Ucbit report_rec_err : 1; + Ucbit en_early_corr : 1; + Ucbit res : 4; /* Byte 2 */ + Uchar ve_retry_count; /* Byte 3 */ + Uchar ve_correction_span; + char res2[5]; /* Byte 5 */ + Uchar ve_recov_timelim[2]; /* Byte 10 */ +}; + +#else /* Motorola byteorder */ + +struct scsi_mode_page_07 { /* Verify Error recovery */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x0A = 12 Bytes */ + Ucbit res : 4; /* Byte 2 */ + Ucbit en_early_corr : 1; + Ucbit report_rec_err : 1; + Ucbit term_on_rec_err : 1; + Ucbit disa_correction : 1; /* Byte 2 */ + Uchar ve_retry_count; /* Byte 3 */ + Uchar ve_correction_span; + char res2[5]; /* Byte 5 */ + Uchar ve_recov_timelim[2]; /* Byte 10 */ +}; +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_mode_page_08 { /* Caching Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x0A = 12 Bytes */ + Ucbit disa_rd_cache : 1; /* Byte 2 */ + Ucbit muliple_fact : 1; + Ucbit en_wt_cache : 1; + Ucbit res : 5; /* Byte 2 */ + Ucbit wt_ret_pri : 4; /* Byte 3 */ + Ucbit demand_rd_ret_pri: 4; /* Byte 3 */ + Uchar disa_pref_tr_len[2]; /* Byte 4 */ + Uchar min_pref[2]; /* Byte 6 */ + Uchar max_pref[2]; /* Byte 8 */ + Uchar max_pref_ceiling[2]; /* Byte 10 */ +}; + +#else /* Motorola byteorder */ + +struct scsi_mode_page_08 { /* Caching Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x0A = 12 Bytes */ + Ucbit res : 5; /* Byte 2 */ + Ucbit en_wt_cache : 1; + Ucbit muliple_fact : 1; + Ucbit disa_rd_cache : 1; /* Byte 2 */ + Ucbit demand_rd_ret_pri: 4; /* Byte 3 */ + Ucbit wt_ret_pri : 4; + Uchar disa_pref_tr_len[2]; /* Byte 4 */ + Uchar min_pref[2]; /* Byte 6 */ + Uchar max_pref[2]; /* Byte 8 */ + Uchar max_pref_ceiling[2]; /* Byte 10 */ +}; +#endif + +struct scsi_mode_page_09 { /* Peripheral device Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* >= 0x06 = 8 Bytes */ + Uchar interface_id[2]; /* Byte 2 */ + Uchar res[4]; /* Byte 4 */ + Uchar vendor_specific[1]; /* Byte 8 */ +}; + +#define PDEV_SCSI 0x0000 /* scsi interface */ +#define PDEV_SMD 0x0001 /* SMD interface */ +#define PDEV_ESDI 0x0002 /* ESDI interface */ +#define PDEV_IPI2 0x0003 /* IPI-2 interface */ +#define PDEV_IPI3 0x0004 /* IPI-3 interface */ + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_mode_page_0A { /* Common device Control Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x06 = 8 Bytes */ + Ucbit rep_log_exeption: 1; /* Byte 2 */ + Ucbit res : 7; /* Byte 2 */ + Ucbit dis_queuing : 1; /* Byte 3 */ + Ucbit queuing_err_man : 1; + Ucbit res2 : 2; + Ucbit queue_alg_mod : 4; /* Byte 3 */ + Ucbit EAENP : 1; /* Byte 4 */ + Ucbit UAENP : 1; + Ucbit RAENP : 1; + Ucbit res3 : 4; + Ucbit en_ext_cont_all : 1; /* Byte 4 */ + Ucbit res4 : 8; + Uchar ready_aen_hold_per[2]; /* Byte 6 */ +}; + +#else /* Motorola byteorder */ + +struct scsi_mode_page_0A { /* Common device Control Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x06 = 8 Bytes */ + Ucbit res : 7; /* Byte 2 */ + Ucbit rep_log_exeption: 1; /* Byte 2 */ + Ucbit queue_alg_mod : 4; /* Byte 3 */ + Ucbit res2 : 2; + Ucbit queuing_err_man : 1; + Ucbit dis_queuing : 1; /* Byte 3 */ + Ucbit en_ext_cont_all : 1; /* Byte 4 */ + Ucbit res3 : 4; + Ucbit RAENP : 1; + Ucbit UAENP : 1; + Ucbit EAENP : 1; /* Byte 4 */ + Ucbit res4 : 8; + Uchar ready_aen_hold_per[2]; /* Byte 6 */ +}; +#endif + +#define CTRL_QMOD_RESTRICT 0x0 +#define CTRL_QMOD_UNRESTRICT 0x1 + + +struct scsi_mode_page_0B { /* Medium Types Supported Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x06 = 8 Bytes */ + Uchar res[2]; /* Byte 2 */ + Uchar medium_one_supp; /* Byte 4 */ + Uchar medium_two_supp; /* Byte 5 */ + Uchar medium_three_supp; /* Byte 6 */ + Uchar medium_four_supp; /* Byte 7 */ +}; + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_mode_page_0C { /* Notch & Partition Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x16 = 24 Bytes */ + Ucbit res : 6; /* Byte 2 */ + Ucbit logical_notch : 1; + Ucbit notched_drive : 1; /* Byte 2 */ + Uchar res2; /* Byte 3 */ + Uchar max_notches[2]; /* Byte 4 */ + Uchar active_notch[2]; /* Byte 6 */ + Uchar starting_boundary[4]; /* Byte 8 */ + Uchar ending_boundary[4]; /* Byte 12 */ + Uchar pages_notched[8]; /* Byte 16 */ +}; + +#else /* Motorola byteorder */ + +struct scsi_mode_page_0C { /* Notch & Partition Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x16 = 24 Bytes */ + Ucbit notched_drive : 1; /* Byte 2 */ + Ucbit logical_notch : 1; + Ucbit res : 6; /* Byte 2 */ + Uchar res2; /* Byte 3 */ + Uchar max_notches[2]; /* Byte 4 */ + Uchar active_notch[2]; /* Byte 6 */ + Uchar starting_boundary[4]; /* Byte 8 */ + Uchar ending_boundary[4]; /* Byte 12 */ + Uchar pages_notched[8]; /* Byte 16 */ +}; +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_mode_page_0D { /* CD-ROM Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x06 = 8 Bytes */ + Uchar res; /* Byte 2 */ + Ucbit inact_timer_mult: 4; /* Byte 3 */ + Ucbit res2 : 4; /* Byte 3 */ + Uchar s_un_per_m_un[2]; /* Byte 4 */ + Uchar f_un_per_s_un[2]; /* Byte 6 */ +}; + +#else /* Motorola byteorder */ + +struct scsi_mode_page_0D { /* CD-ROM Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x06 = 8 Bytes */ + Uchar res; /* Byte 2 */ + Ucbit res2 : 4; /* Byte 3 */ + Ucbit inact_timer_mult: 4; /* Byte 3 */ + Uchar s_un_per_m_un[2]; /* Byte 4 */ + Uchar f_un_per_s_un[2]; /* Byte 6 */ +}; +#endif + +struct sony_mode_page_20 { /* Sony Format Mode Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x0A = 12 Bytes */ + Uchar format_mode; + Uchar format_type; +#define num_bands user_band_size /* Gilt bei Type 1 */ + Uchar user_band_size[4]; /* Gilt bei Type 0 */ + Uchar spare_band_size[2]; + Uchar res[2]; +}; + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct toshiba_mode_page_20 { /* Toshiba Speed Control Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x01 = 3 Bytes */ + Ucbit speed : 1; + Ucbit res : 7; +}; + +#else /* Motorola byteorder */ + +struct toshiba_mode_page_20 { /* Toshiba Speed Control Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x01 = 3 Bytes */ + Ucbit res : 7; + Ucbit speed : 1; +}; +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct ccs_mode_page_38 { /* CCS Caching Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x0E = 14 Bytes */ + + Ucbit cache_table_size: 4; /* Byte 3 */ + Ucbit cache_en : 1; + Ucbit res2 : 1; + Ucbit wr_index_en : 1; + Ucbit res : 1; /* Byte 3 */ + Uchar threshold; /* Byte 4 Prefetch threshold */ + Uchar max_prefetch; /* Byte 5 Max. prefetch */ + Uchar max_multiplier; /* Byte 6 Max. prefetch multiplier */ + Uchar min_prefetch; /* Byte 7 Min. prefetch */ + Uchar min_multiplier; /* Byte 8 Min. prefetch multiplier */ + Uchar res3[8]; /* Byte 9 */ +}; + +#else /* Motorola byteorder */ + +struct ccs_mode_page_38 { /* CCS Caching Parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x0E = 14 Bytes */ + + Ucbit res : 1; /* Byte 3 */ + Ucbit wr_index_en : 1; + Ucbit res2 : 1; + Ucbit cache_en : 1; + Ucbit cache_table_size: 4; /* Byte 3 */ + Uchar threshold; /* Byte 4 Prefetch threshold */ + Uchar max_prefetch; /* Byte 5 Max. prefetch */ + Uchar max_multiplier; /* Byte 6 Max. prefetch multiplier */ + Uchar min_prefetch; /* Byte 7 Min. prefetch */ + Uchar min_multiplier; /* Byte 8 Min. prefetch multiplier */ + Uchar res3[8]; /* Byte 9 */ +}; +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct cd_mode_page_05 { /* write parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x32 = 50 Bytes */ + Ucbit write_type : 4; /* Session write type (PACKET/TAO...)*/ + Ucbit test_write : 1; /* Do not actually write data */ + Ucbit LS_V : 1; /* Link size valid */ + Ucbit BUFE : 1; /* Enable Bufunderrun free rec. */ + Ucbit res_2_7 : 1; + Ucbit track_mode : 4; /* Track mode (Q-sub control nibble) */ + Ucbit copy : 1; /* 1st higher gen of copy prot track ~*/ + Ucbit fp : 1; /* Fixed packed (if in packet mode) */ + Ucbit multi_session : 2; /* Multi session write type */ + Ucbit dbtype : 4; /* Data block type */ + Ucbit res_4 : 4; /* Reserved */ + Uchar link_size; /* Link Size (default is 7) */ + Uchar res_6; /* Reserved */ + Ucbit host_appl_code : 6; /* Host application code of disk */ + Ucbit res_7 : 2; /* Reserved */ + Uchar session_format; /* Session format (DA/CDI/XA) */ + Uchar res_9; /* Reserved */ + Uchar packet_size[4]; /* # of user datablocks/fixed packet */ + Uchar audio_pause_len[2]; /* # of blocks where index is zero */ + Uchar media_cat_number[16]; /* Media catalog Number (MCN) */ + Uchar ISRC[14]; /* ISRC for this track */ + Uchar sub_header[4]; + Uchar vendor_uniq[4]; +}; + +#else /* Motorola byteorder */ + +struct cd_mode_page_05 { /* write parameters */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x32 = 50 Bytes */ + Ucbit res_2_7 : 1; + Ucbit BUFE : 1; /* Enable Bufunderrun free rec. */ + Ucbit LS_V : 1; /* Link size valid */ + Ucbit test_write : 1; /* Do not actually write data */ + Ucbit write_type : 4; /* Session write type (PACKET/TAO...)*/ + Ucbit multi_session : 2; /* Multi session write type */ + Ucbit fp : 1; /* Fixed packed (if in packet mode) */ + Ucbit copy : 1; /* 1st higher gen of copy prot track */ + Ucbit track_mode : 4; /* Track mode (Q-sub control nibble) */ + Ucbit res_4 : 4; /* Reserved */ + Ucbit dbtype : 4; /* Data block type */ + Uchar link_size; /* Link Size (default is 7) */ + Uchar res_6; /* Reserved */ + Ucbit res_7 : 2; /* Reserved */ + Ucbit host_appl_code : 6; /* Host application code of disk */ + Uchar session_format; /* Session format (DA/CDI/XA) */ + Uchar res_9; /* Reserved */ + Uchar packet_size[4]; /* # of user datablocks/fixed packet */ + Uchar audio_pause_len[2]; /* # of blocks where index is zero */ + Uchar media_cat_number[16]; /* Media catalog Number (MCN) */ + Uchar ISRC[14]; /* ISRC for this track */ + Uchar sub_header[4]; + Uchar vendor_uniq[4]; +}; + +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct cd_wr_speed_performance { + Uchar res0; /* Reserved */ + Ucbit rot_ctl_sel : 2; /* Rotational control selected */ + Ucbit res_1_27 : 6; /* Reserved */ + Uchar wr_speed_supp[2]; /* Supported write speed */ +}; + +struct cd_mode_page_2A { /* CD Cap / mech status */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x14 = 20 Bytes (MMC) */ + /* 0x18 = 24 Bytes (MMC-2) */ + /* 0x1C >= 28 Bytes (MMC-3) */ + Ucbit cd_r_read : 1; /* Reads CD-R media */ + Ucbit cd_rw_read : 1; /* Reads CD-RW media */ + Ucbit method2 : 1; /* Reads fixed packet method2 media */ + Ucbit dvd_rom_read : 1; /* Reads DVD ROM media */ + Ucbit dvd_r_read : 1; /* Reads DVD-R media */ + Ucbit dvd_ram_read : 1; /* Reads DVD-RAM media */ + Ucbit res_2_67 : 2; /* Reserved */ + Ucbit cd_r_write : 1; /* Supports writing CD-R media */ + Ucbit cd_rw_write : 1; /* Supports writing CD-RW media */ + Ucbit test_write : 1; /* Supports emulation write */ + Ucbit res_3_3 : 1; /* Reserved */ + Ucbit dvd_r_write : 1; /* Supports writing DVD-R media */ + Ucbit dvd_ram_write : 1; /* Supports writing DVD-RAM media */ + Ucbit res_3_67 : 2; /* Reserved */ + Ucbit audio_play : 1; /* Supports Audio play operation */ + Ucbit composite : 1; /* Deliveres composite A/V stream */ + Ucbit digital_port_2 : 1; /* Supports digital output on port 2 */ + Ucbit digital_port_1 : 1; /* Supports digital output on port 1 */ + Ucbit mode_2_form_1 : 1; /* Reads Mode-2 form 1 media (XA) */ + Ucbit mode_2_form_2 : 1; /* Reads Mode-2 form 2 media */ + Ucbit multi_session : 1; /* Reads multi-session media */ + Ucbit BUF : 1; /* Supports Buffer under. free rec. */ + Ucbit cd_da_supported : 1; /* Reads audio data with READ CD cmd */ + Ucbit cd_da_accurate : 1; /* READ CD data stream is accurate */ + Ucbit rw_supported : 1; /* Reads R-W sub channel information */ + Ucbit rw_deint_corr : 1; /* Reads de-interleved R-W sub chan */ + Ucbit c2_pointers : 1; /* Supports C2 error pointers */ + Ucbit ISRC : 1; /* Reads ISRC information */ + Ucbit UPC : 1; /* Reads media catalog number (UPC) */ + Ucbit read_bar_code : 1; /* Supports reading bar codes */ + Ucbit lock : 1; /* PREVENT/ALLOW may lock media */ + Ucbit lock_state : 1; /* Lock state 0=unlocked 1=locked */ + Ucbit prevent_jumper : 1; /* State of prev/allow jumper 0=pres */ + Ucbit eject : 1; /* Ejects disc/cartr with STOP LoEj */ + Ucbit res_6_4 : 1; /* Reserved */ + Ucbit loading_type : 3; /* Loading mechanism type */ + Ucbit sep_chan_vol : 1; /* Vol controls each channel separat */ + Ucbit sep_chan_mute : 1; /* Mute controls each channel separat*/ + Ucbit disk_present_rep: 1; /* Changer supports disk present rep */ + Ucbit sw_slot_sel : 1; /* Load empty slot in changer */ + Ucbit side_change : 1; /* Side change capable */ + Ucbit pw_in_lead_in : 1; /* Reads raw P-W sucode from lead in */ + Ucbit res_7 : 2; /* Reserved */ + Uchar max_read_speed[2]; /* Max. read speed in KB/s */ + Uchar num_vol_levels[2]; /* # of supported volume levels */ + Uchar buffer_size[2]; /* Buffer size for the data in KB */ + Uchar cur_read_speed[2]; /* Current read speed in KB/s */ + Uchar res_16; /* Reserved */ + Ucbit res_17_0 : 1; /* Reserved */ + Ucbit BCK : 1; /* Data valid on falling edge of BCK */ + Ucbit RCK : 1; /* Set: HIGH high LRCK=left channel */ + Ucbit LSBF : 1; /* Set: LSB first Clear: MSB first */ + Ucbit length : 2; /* 0=32BCKs 1=16BCKs 2=24BCKs 3=24I2c*/ + Ucbit res_17 : 2; /* Reserved */ + Uchar max_write_speed[2]; /* Max. write speed supported in KB/s*/ + Uchar cur_write_speed[2]; /* Current write speed in KB/s */ + + /* Byte 22 ... Only in MMC-2 */ + Uchar copy_man_rev[2]; /* Copy management revision supported*/ + Uchar res_24; /* Reserved */ + Uchar res_25; /* Reserved */ + + /* Byte 26 ... Only in MMC-3 */ + Uchar res_26; /* Reserved */ + Ucbit res_27_27 : 6; /* Reserved */ + Ucbit rot_ctl_sel : 2; /* Rotational control selected */ + Uchar v3_cur_write_speed[2]; /* Current write speed in KB/s */ + Uchar num_wr_speed_des[2]; /* # of wr speed perf descr. tables */ + struct cd_wr_speed_performance + wr_speed_des[1]; /* wr speed performance descriptor */ + /* Actually more (num_wr_speed_des) */ +}; + +#else /* Motorola byteorder */ + +struct cd_wr_speed_performance { + Uchar res0; /* Reserved */ + Ucbit res_1_27 : 6; /* Reserved */ + Ucbit rot_ctl_sel : 2; /* Rotational control selected */ + Uchar wr_speed_supp[2]; /* Supported write speed */ +}; + +struct cd_mode_page_2A { /* CD Cap / mech status */ + MP_P_CODE; /* parsave & pagecode */ + Uchar p_len; /* 0x14 = 20 Bytes (MMC) */ + /* 0x18 = 24 Bytes (MMC-2) */ + /* 0x1C >= 28 Bytes (MMC-3) */ + Ucbit res_2_67 : 2; /* Reserved */ + Ucbit dvd_ram_read : 1; /* Reads DVD-RAM media */ + Ucbit dvd_r_read : 1; /* Reads DVD-R media */ + Ucbit dvd_rom_read : 1; /* Reads DVD ROM media */ + Ucbit method2 : 1; /* Reads fixed packet method2 media */ + Ucbit cd_rw_read : 1; /* Reads CD-RW media */ + Ucbit cd_r_read : 1; /* Reads CD-R media */ + Ucbit res_3_67 : 2; /* Reserved */ + Ucbit dvd_ram_write : 1; /* Supports writing DVD-RAM media */ + Ucbit dvd_r_write : 1; /* Supports writing DVD-R media */ + Ucbit res_3_3 : 1; /* Reserved */ + Ucbit test_write : 1; /* Supports emulation write */ + Ucbit cd_rw_write : 1; /* Supports writing CD-RW media */ + Ucbit cd_r_write : 1; /* Supports writing CD-R media */ + Ucbit BUF : 1; /* Supports Buffer under. free rec. */ + Ucbit multi_session : 1; /* Reads multi-session media */ + Ucbit mode_2_form_2 : 1; /* Reads Mode-2 form 2 media */ + Ucbit mode_2_form_1 : 1; /* Reads Mode-2 form 1 media (XA) */ + Ucbit digital_port_1 : 1; /* Supports digital output on port 1 */ + Ucbit digital_port_2 : 1; /* Supports digital output on port 2 */ + Ucbit composite : 1; /* Deliveres composite A/V stream */ + Ucbit audio_play : 1; /* Supports Audio play operation */ + Ucbit read_bar_code : 1; /* Supports reading bar codes */ + Ucbit UPC : 1; /* Reads media catalog number (UPC) */ + Ucbit ISRC : 1; /* Reads ISRC information */ + Ucbit c2_pointers : 1; /* Supports C2 error pointers */ + Ucbit rw_deint_corr : 1; /* Reads de-interleved R-W sub chan */ + Ucbit rw_supported : 1; /* Reads R-W sub channel information */ + Ucbit cd_da_accurate : 1; /* READ CD data stream is accurate */ + Ucbit cd_da_supported : 1; /* Reads audio data with READ CD cmd */ + Ucbit loading_type : 3; /* Loading mechanism type */ + Ucbit res_6_4 : 1; /* Reserved */ + Ucbit eject : 1; /* Ejects disc/cartr with STOP LoEj */ + Ucbit prevent_jumper : 1; /* State of prev/allow jumper 0=pres */ + Ucbit lock_state : 1; /* Lock state 0=unlocked 1=locked */ + Ucbit lock : 1; /* PREVENT/ALLOW may lock media */ + Ucbit res_7 : 2; /* Reserved */ + Ucbit pw_in_lead_in : 1; /* Reads raw P-W sucode from lead in */ + Ucbit side_change : 1; /* Side change capable */ + Ucbit sw_slot_sel : 1; /* Load empty slot in changer */ + Ucbit disk_present_rep: 1; /* Changer supports disk present rep */ + Ucbit sep_chan_mute : 1; /* Mute controls each channel separat*/ + Ucbit sep_chan_vol : 1; /* Vol controls each channel separat */ + Uchar max_read_speed[2]; /* Max. read speed in KB/s */ + Uchar num_vol_levels[2]; /* # of supported volume levels */ + Uchar buffer_size[2]; /* Buffer size for the data in KB */ + Uchar cur_read_speed[2]; /* Current read speed in KB/s */ + Uchar res_16; /* Reserved */ + Ucbit res_17 : 2; /* Reserved */ + Ucbit length : 2; /* 0=32BCKs 1=16BCKs 2=24BCKs 3=24I2c*/ + Ucbit LSBF : 1; /* Set: LSB first Clear: MSB first */ + Ucbit RCK : 1; /* Set: HIGH high LRCK=left channel */ + Ucbit BCK : 1; /* Data valid on falling edge of BCK */ + Ucbit res_17_0 : 1; /* Reserved */ + Uchar max_write_speed[2]; /* Max. write speed supported in KB/s*/ + Uchar cur_write_speed[2]; /* Current write speed in KB/s */ + + /* Byte 22 ... Only in MMC-2 */ + Uchar copy_man_rev[2]; /* Copy management revision supported*/ + Uchar res_24; /* Reserved */ + Uchar res_25; /* Reserved */ + + /* Byte 26 ... Only in MMC-3 */ + Uchar res_26; /* Reserved */ + Ucbit res_27_27 : 6; /* Reserved */ + Ucbit rot_ctl_sel : 2; /* Rotational control selected */ + Uchar v3_cur_write_speed[2]; /* Current write speed in KB/s */ + Uchar num_wr_speed_des[2]; /* # of wr speed perf descr. tables */ + struct cd_wr_speed_performance + wr_speed_des[1]; /* wr speed performance descriptor */ + /* Actually more (num_wr_speed_des) */ +}; + +#endif + +#define LT_CADDY 0 +#define LT_TRAY 1 +#define LT_POP_UP 2 +#define LT_RES3 3 +#define LT_CHANGER_IND 4 +#define LT_CHANGER_CART 5 +#define LT_RES6 6 +#define LT_RES7 7 + + +struct scsi_mode_data { + struct scsi_mode_header header; + struct scsi_mode_blockdesc blockdesc; + union pagex { + struct acb_mode_data acb; + struct scsi_mode_page_01 page1; + struct scsi_mode_page_02 page2; + struct scsi_mode_page_03 page3; + struct scsi_mode_page_04 page4; + struct scsi_mode_page_05 page5; + struct scsi_mode_page_07 page7; + struct scsi_mode_page_08 page8; + struct scsi_mode_page_09 page9; + struct scsi_mode_page_0A pageA; + struct scsi_mode_page_0B pageB; + struct scsi_mode_page_0C pageC; + struct scsi_mode_page_0D pageD; + struct sony_mode_page_20 sony20; + struct toshiba_mode_page_20 toshiba20; + struct ccs_mode_page_38 ccs38; + } pagex; +}; + +struct scsi_capacity { + Int32_t c_baddr; /* must convert byteorder!! */ + Int32_t c_bsize; /* must convert byteorder!! */ +}; + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_def_header { + Ucbit : 8; + Ucbit format : 3; + Ucbit gdl : 1; + Ucbit mdl : 1; + Ucbit : 3; + Uchar length[2]; +}; + +#else /* Motorola byteorder */ + +struct scsi_def_header { + Ucbit : 8; + Ucbit : 3; + Ucbit mdl : 1; + Ucbit gdl : 1; + Ucbit format : 3; + Uchar length[2]; +}; +#endif + + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_format_header { + Ucbit res : 8; /* Adaptec 5500: 1 --> format track */ + Ucbit vu : 1; /* Vendor Unique */ + Ucbit immed : 1; /* Return Immediately from Format */ + Ucbit tryout : 1; /* Check if format parameters OK */ + Ucbit ipattern : 1; /* Init patter descriptor present */ + Ucbit serr : 1; /* Stop on error */ + Ucbit dcert : 1; /* Disable certification */ + Ucbit dmdl : 1; /* Disable manufacturer defect list */ + Ucbit enable : 1; /* Enable to use the next 3 bits */ + Uchar length[2]; /* Length of following list in bytes*/ +}; + +#else /* Motorola byteorder */ + +struct scsi_format_header { + Ucbit res : 8; /* Adaptec 5500: 1 --> format track */ + Ucbit enable : 1; /* Enable to use the next 3 bits */ + Ucbit dmdl : 1; /* Disable manufacturer defect list */ + Ucbit dcert : 1; /* Disable certification */ + Ucbit serr : 1; /* Stop on error */ + Ucbit ipattern : 1; /* Init patter descriptor present */ + Ucbit tryout : 1; /* Check if format parameters OK */ + Ucbit immed : 1; /* Return Immediately from Format */ + Ucbit vu : 1; /* Vendor Unique */ + Uchar length[2]; /* Length of following list in bytes*/ +}; +#endif + +struct scsi_def_bfi { + Uchar cyl[3]; + Uchar head; + Uchar bfi[4]; +}; + +struct scsi_def_phys { + Uchar cyl[3]; + Uchar head; + Uchar sec[4]; +}; + +struct scsi_def_list { + struct scsi_def_header hd; + union { + Uchar list_block[1][4]; + struct scsi_def_bfi list_bfi[1]; + struct scsi_def_phys list_phys[1]; + } def_list; +}; + +struct scsi_format_data { + struct scsi_format_header hd; + union { + Uchar list_block[1][4]; + struct scsi_def_bfi list_bfi[1]; + struct scsi_def_phys list_phys[1]; + } def_list; +}; + +#define def_block def_list.list_block +#define def_bfi def_list.list_bfi +#define def_phys def_list.list_phys + +#define SC_DEF_BLOCK 0 +#define SC_DEF_BFI 4 +#define SC_DEF_PHYS 5 +#define SC_DEF_VU 6 +#define SC_DEF_RES 7 + +struct scsi_format_cap_header { + Uchar res[3]; /* Reserved */ + Uchar len; /* Len (a multiple of 8) */ +}; + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_format_cap_desc { + Uchar nblock[4]; /* Number of blocks */ + Ucbit desc_type : 2; /* Descriptor type */ + Ucbit fmt_type : 6; /* Format Taype */ + Uchar blen[3]; /* Logical block length */ +}; + +#else /* Motorola byteorder */ + +struct scsi_format_cap_desc { + Uchar nblock[4]; /* Number of blocks */ + Ucbit fmt_type : 6; /* Format Taype */ + Ucbit desc_type : 2; /* Descriptor type */ + Uchar blen[3]; /* Logical block length */ +}; +#endif + +/* + * Defines for 'fmt_type'. + */ +#define FCAP_TYPE_DVDPLUS_FULL 0x26 /* DVD+RW Full Format */ + +/* + * Defines for 'desc_type'. + * In case of FCAP_DESC_RES, the descriptor is a formatted capacity descriptor + * and the 'blen' field is type dependent. + * For all other cases, this is the Current/Maximum Capacity descriptor and + * the value of 'fmt_type' is reserved and must be zero. + */ +#define FCAP_DESC_RES 0 /* Reserved */ +#define FCAP_DESC_UNFORM 1 /* Unformatted Media */ +#define FCAP_DESC_FORM 2 /* Formatted Media */ +#define FCAP_DESC_NOMEDIA 3 /* No Media */ + +struct scsi_cap_data { + struct scsi_format_cap_header hd; + struct scsi_format_cap_desc list[1]; +}; + + +struct scsi_send_diag_cmd { + Uchar cmd; + Uchar addr[4]; + Ucbit : 8; +}; + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_sector_header { + Uchar cyl[2]; + Uchar head; + Uchar sec; + Ucbit : 5; + Ucbit rp : 1; + Ucbit sp : 1; + Ucbit dt : 1; +}; + +#else /* Motorola byteorder */ + +struct scsi_sector_header { + Uchar cyl[2]; + Uchar head; + Uchar sec; + Ucbit dt : 1; + Ucbit sp : 1; + Ucbit rp : 1; + Ucbit : 5; +}; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _SCG_SCSIREG_H */ diff --git a/src/schily/scg/scsisense.h b/src/schily/scg/scsisense.h new file mode 100644 index 0000000..f0b53e6 --- /dev/null +++ b/src/schily/scg/scsisense.h @@ -0,0 +1,191 @@ +/* @(#)scsisense.h 2.18 04/09/04 Copyright 1986 J. Schilling */ +/* + * Definitions for the SCSI status code and sense structure + * + * Copyright (c) 1986 J. Schilling + */ +/*@@C@@*/ + +#ifndef _SCG_SCSISENSE_H +#define _SCG_SCSISENSE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SCSI status completion block. + */ +#define SCSI_EXTENDED_STATUS + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_status { + Ucbit vu_00 : 1; /* vendor unique */ + Ucbit chk : 1; /* check condition: sense data available */ + Ucbit cm : 1; /* condition met */ + Ucbit busy : 1; /* device busy or reserved */ + Ucbit is : 1; /* intermediate status sent */ + Ucbit vu_05 : 1; /* vendor unique */ +#define st_scsi2 vu_05 /* SCSI-2 modifier bit */ + Ucbit vu_06 : 1; /* vendor unique */ + Ucbit st_rsvd : 1; /* reserved */ + +#ifdef SCSI_EXTENDED_STATUS +#define ext_st1 st_rsvd /* extended status (next byte valid) */ + /* byte 1 */ + Ucbit ha_er : 1; /* host adapter detected error */ + Ucbit reserved: 6; /* reserved */ + Ucbit ext_st2 : 1; /* extended status (next byte valid) */ + /* byte 2 */ + Uchar byte2; /* third byte */ +#endif /* SCSI_EXTENDED_STATUS */ +}; + +#else /* Motorola byteorder */ + +struct scsi_status { + Ucbit st_rsvd : 1; /* reserved */ + Ucbit vu_06 : 1; /* vendor unique */ + Ucbit vu_05 : 1; /* vendor unique */ +#define st_scsi2 vu_05 /* SCSI-2 modifier bit */ + Ucbit is : 1; /* intermediate status sent */ + Ucbit busy : 1; /* device busy or reserved */ + Ucbit cm : 1; /* condition met */ + Ucbit chk : 1; /* check condition: sense data available */ + Ucbit vu_00 : 1; /* vendor unique */ +#ifdef SCSI_EXTENDED_STATUS +#define ext_st1 st_rsvd /* extended status (next byte valid) */ + /* byte 1 */ + Ucbit ext_st2 : 1; /* extended status (next byte valid) */ + Ucbit reserved: 6; /* reserved */ + Ucbit ha_er : 1; /* host adapter detected error */ + /* byte 2 */ + Uchar byte2; /* third byte */ +#endif /* SCSI_EXTENDED_STATUS */ +}; +#endif + +/* + * OLD Standard (Non Extended) SCSI Sense. Used mainly by the + * Adaptec ACB 4000 which is the only controller that + * does not support the Extended sense format. + */ +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_sense { /* scsi sense for error classes 0-6 */ + Ucbit code : 7; /* error class/code */ + Ucbit adr_val : 1; /* sense data is valid */ +#ifdef comment + Ucbit high_addr:5; /* high byte of block addr */ + Ucbit rsvd : 3; +#else + Uchar high_addr; /* high byte of block addr */ +#endif + Uchar mid_addr; /* middle byte of block addr */ + Uchar low_addr; /* low byte of block addr */ +}; + +#else /* Motorola byteorder */ + +struct scsi_sense { /* scsi sense for error classes 0-6 */ + Ucbit adr_val : 1; /* sense data is valid */ + Ucbit code : 7; /* error class/code */ +#ifdef comment + Ucbit rsvd : 3; + Ucbit high_addr:5; /* high byte of block addr */ +#else + Uchar high_addr; /* high byte of block addr */ +#endif + Uchar mid_addr; /* middle byte of block addr */ + Uchar low_addr; /* low byte of block addr */ +}; +#endif + +/* + * SCSI extended sense parameter block. + */ +#ifdef comment +#define SC_CLASS_EXTENDED_SENSE 0x7 /* indicates extended sense */ +#endif + +#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ + +struct scsi_ext_sense { /* scsi extended sense for error class 7 */ + /* byte 0 */ + Ucbit type : 7; /* fixed at 0x70 */ + Ucbit adr_val : 1; /* sense data is valid */ + /* byte 1 */ + Uchar seg_num; /* segment number, applies to copy cmd only */ + /* byte 2 */ + Ucbit key : 4; /* sense key, see below */ + Ucbit : 1; /* reserved */ + Ucbit ili : 1; /* incorrect length indicator */ + Ucbit eom : 1; /* end of media */ + Ucbit fil_mk : 1; /* file mark on device */ + /* bytes 3 through 7 */ + Uchar info_1; /* information byte 1 */ + Uchar info_2; /* information byte 2 */ + Uchar info_3; /* information byte 3 */ + Uchar info_4; /* information byte 4 */ + Uchar add_len; /* number of additional bytes */ + /* bytes 8 through 13, CCS additions */ + Uchar optional_8; /* CCS search and copy only */ + Uchar optional_9; /* CCS search and copy only */ + Uchar optional_10; /* CCS search and copy only */ + Uchar optional_11; /* CCS search and copy only */ + Uchar sense_code; /* sense code */ + Uchar qual_code; /* sense code qualifier */ + Uchar fru_code; /* Field replacable unit code */ + Ucbit bptr : 3; /* bit pointer for failure (if bpv) */ + Ucbit bpv : 1; /* bit pointer is valid */ + Ucbit : 2; + Ucbit cd : 1; /* pointers refer to command not data */ + Ucbit sksv : 1; /* sense key specific valid */ + Uchar field_ptr[2]; /* field pointer for failure */ + Uchar add_info[2]; /* round up to 20 bytes */ +}; + +#else /* Motorola byteorder */ + +struct scsi_ext_sense { /* scsi extended sense for error class 7 */ + /* byte 0 */ + Ucbit adr_val : 1; /* sense data is valid */ + Ucbit type : 7; /* fixed at 0x70 */ + /* byte 1 */ + Uchar seg_num; /* segment number, applies to copy cmd only */ + /* byte 2 */ + Ucbit fil_mk : 1; /* file mark on device */ + Ucbit eom : 1; /* end of media */ + Ucbit ili : 1; /* incorrect length indicator */ + Ucbit : 1; /* reserved */ + Ucbit key : 4; /* sense key, see below */ + /* bytes 3 through 7 */ + Uchar info_1; /* information byte 1 */ + Uchar info_2; /* information byte 2 */ + Uchar info_3; /* information byte 3 */ + Uchar info_4; /* information byte 4 */ + Uchar add_len; /* number of additional bytes */ + /* bytes 8 through 13, CCS additions */ + Uchar optional_8; /* CCS search and copy only */ + Uchar optional_9; /* CCS search and copy only */ + Uchar optional_10; /* CCS search and copy only */ + Uchar optional_11; /* CCS search and copy only */ + Uchar sense_code; /* sense code */ + Uchar qual_code; /* sense code qualifier */ + Uchar fru_code; /* Field replacable unit code */ + Ucbit sksv : 1; /* sense key specific valid */ + Ucbit cd : 1; /* pointers refer to command not data */ + Ucbit : 2; + Ucbit bpv : 1; /* bit pointer is valid */ + Ucbit bptr : 3; /* bit pointer for failure (if bpv) */ + Uchar field_ptr[2]; /* field pointer for failure */ + Uchar add_info[2]; /* round up to 20 bytes */ +}; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _SCG_SCSISENSE_H */ diff --git a/src/schily/scg/scsitransp.h b/src/schily/scg/scsitransp.h new file mode 100644 index 0000000..d413c85 --- /dev/null +++ b/src/schily/scg/scsitransp.h @@ -0,0 +1,257 @@ +/* @(#)scsitransp.h 1.54 03/05/03 Copyright 1995 J. Schilling */ +/* + * Definitions for commands that use functions from scsitransp.c + * + * Copyright (c) 1995 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SCG_SCSITRANSP_H +#define _SCG_SCSITRANSP_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scg_scsi SCSI; + +typedef struct { + int scsibus; /* SCSI bus # for next I/O */ + int target; /* SCSI target # for next I/O */ + int lun; /* SCSI lun # for next I/O */ +} scg_addr_t; + +#ifndef _SCG_SCGOPS_H +#include +#endif + +typedef int (*scg_cb_t) __PR((void *)); + +struct scg_scsi { + scg_ops_t *ops; /* Ptr to low level SCSI transport ops */ + int fd; /* File descriptor for next I/O */ + scg_addr_t addr; /* SCSI address for next I/O */ + int flags; /* Libscg flags (see below) */ + int dflags; /* Drive specific flags (see below) */ + int kdebug; /* Kernel debug value for next I/O */ + int debug; /* Debug value for SCSI library */ + int silent; /* Be silent if value > 0 */ + int verbose; /* Be verbose if value > 0 */ + int overbose; /* Be verbose in open() if value > 0 */ + int disre_disable; + int deftimeout; + int noparity; /* Do not use SCSI parity fo next I/O */ + int dev; /* from scsi_cdr.c */ + struct scg_cmd *scmd; + char *cmdname; + char *curcmdname; + BOOL running; + int error; /* libscg error number */ + + long maxdma; /* Max DMA limit for this open instance */ + long maxbuf; /* Cur DMA buffer limit for this inst. */ + /* This is the size behind bufptr */ + struct timeval *cmdstart; + struct timeval *cmdstop; + const char **nonstderrs; + void *local; /* Local data from the low level code */ + void *bufbase; /* needed for scsi_freebuf() */ + void *bufptr; /* DMA buffer pointer for appl. use */ + char *errstr; /* Error string for scsi_open/sendmcd */ + char *errbeg; /* Pointer to begin of not flushed data */ + char *errptr; /* Actual write pointer into errstr */ + void *errfile; /* FILE to write errors to. NULL for not*/ + /* writing and leaving errs in errstr */ + scg_cb_t cb_fun; + void *cb_arg; + + struct scsi_inquiry *inq; + struct scsi_capacity *cap; +}; + +/* + * Macros for accessing members of the scg address structure. + * scg_settarget() is the only function that is allowed to modify + * the values of the SCSI address. + */ +#define scg_scsibus(scgp) (scgp)->addr.scsibus +#define scg_target(scgp) (scgp)->addr.target +#define scg_lun(scgp) (scgp)->addr.lun + +/* + * Flags for struct SCSI: + */ +/* NONE yet */ + +/* + * Drive specific flags for struct SCSI: + */ +#define DRF_MODE_DMA_OVR 0x0001 /* Drive gives DMA overrun */ + /* on mode sense */ + +#define SCSI_ERRSTR_SIZE 4096 + +/* + * Libscg error codes: + */ +#define SCG_ERRBASE 1000000 +#define SCG_NOMEM 1000001 + +/* + * Function codes for scg_version(): + */ +#define SCG_VERSION 0 /* libscg or transport version */ +#define SCG_AUTHOR 1 /* Author of above */ +#define SCG_SCCS_ID 2 /* SCCS id of above */ +#define SCG_RVERSION 10 /* Remote transport version */ +#define SCG_RAUTHOR 11 /* Remote transport author */ +#define SCG_RSCCS_ID 12 /* Remote transport SCCS ID */ +#define SCG_KVERSION 20 /* Kernel transport version */ + +/* + * Function codes for scg_reset(): + */ +#define SCG_RESET_NOP 0 /* Test if reset is supported */ +#define SCG_RESET_TGT 1 /* Reset Target only */ +#define SCG_RESET_BUS 2 /* Reset complete SCSI Bus */ + +/* + * Helpers for the error buffer in SCSI* + */ +#define scg_errsize(scgp) ((scgp)->errptr - (scgp)->errstr) +#define scg_errrsize(scgp) (SCSI_ERRSTR_SIZE - scg_errsize(scgp)) + +/* + * From scsitransp.c: + */ +extern char *scg_version __PR((SCSI *scgp, int what)); +extern int scg__open __PR((SCSI *scgp, char *device)); +extern int scg__close __PR((SCSI *scgp)); +extern BOOL scg_havebus __PR((SCSI *scgp, int)); +extern int scg_initiator_id __PR((SCSI *scgp)); +extern int scg_isatapi __PR((SCSI *scgp)); +extern int scg_reset __PR((SCSI *scgp, int what)); +extern void *scg_getbuf __PR((SCSI *scgp, long)); +extern void scg_freebuf __PR((SCSI *scgp)); +extern long scg_bufsize __PR((SCSI *scgp, long)); +extern void scg_setnonstderrs __PR((SCSI *scgp, const char **)); +extern BOOL scg_yes __PR((char *)); +extern int scg_cmd __PR((SCSI *scgp)); +extern void scg_vhead __PR((SCSI *scgp)); +extern int scg_svhead __PR((SCSI *scgp, char *buf, int maxcnt)); +extern int scg_vtail __PR((SCSI *scgp)); +extern int scg_svtail __PR((SCSI *scgp, int *retp, char *buf, int maxcnt)); +extern void scg_vsetup __PR((SCSI *scgp)); +extern int scg_getresid __PR((SCSI *scgp)); +extern int scg_getdmacnt __PR((SCSI *scgp)); +extern BOOL scg_cmd_err __PR((SCSI *scgp)); +extern void scg_printerr __PR((SCSI *scgp)); +#ifdef EOF /* stdio.h has been included */ +extern void scg_fprinterr __PR((SCSI *scgp, FILE *f)); +#endif +extern int scg_sprinterr __PR((SCSI *scgp, char *buf, int maxcnt)); +extern int scg__sprinterr __PR((SCSI *scgp, char *buf, int maxcnt)); +extern void scg_printcdb __PR((SCSI *scgp)); +extern int scg_sprintcdb __PR((SCSI *scgp, char *buf, int maxcnt)); +extern void scg_printwdata __PR((SCSI *scgp)); +extern int scg_sprintwdata __PR((SCSI *scgp, char *buf, int maxcnt)); +extern void scg_printrdata __PR((SCSI *scgp)); +extern int scg_sprintrdata __PR((SCSI *scgp, char *buf, int maxcnt)); +extern void scg_printresult __PR((SCSI *scgp)); +extern int scg_sprintresult __PR((SCSI *scgp, char *buf, int maxcnt)); +extern void scg_printstatus __PR((SCSI *scgp)); +extern int scg_sprintstatus __PR((SCSI *scgp, char *buf, int maxcnt)); +#ifdef EOF /* stdio.h has been included */ +extern void scg_fprbytes __PR((FILE *, char *, unsigned char *, int)); +extern void scg_fprascii __PR((FILE *, char *, unsigned char *, int)); +#endif +extern void scg_prbytes __PR((char *, unsigned char *, int)); +extern void scg_prascii __PR((char *, unsigned char *, int)); +extern int scg_sprbytes __PR((char *buf, int maxcnt, char *, unsigned char *, int)); +extern int scg_sprascii __PR((char *buf, int maxcnt, char *, unsigned char *, int)); +#ifdef EOF /* stdio.h has been included */ +extern void scg_fprsense __PR((FILE *f, unsigned char *, int)); +#endif +extern void scg_prsense __PR((unsigned char *, int)); +extern int scg_sprsense __PR((char *buf, int maxcnt, unsigned char *, int)); +extern int scg_cmd_status __PR((SCSI *scgp)); +extern int scg_sense_key __PR((SCSI *scgp)); +extern int scg_sense_code __PR((SCSI *scgp)); +extern int scg_sense_qual __PR((SCSI *scgp)); +#ifdef _SCG_SCSIREG_H +#ifdef EOF /* stdio.h has been included */ +extern void scg_fprintdev __PR((FILE *, struct scsi_inquiry *)); +#endif +extern void scg_printdev __PR((struct scsi_inquiry *)); +#endif +extern int scg_printf __PR((SCSI *scgp, const char *form, ...)); +extern int scg_errflush __PR((SCSI *scgp)); +#ifdef EOF /* stdio.h has been included */ +extern int scg_errfflush __PR((SCSI *scgp, FILE *f)); +#endif + +/* + * From scsierrmsg.c: + */ +extern const char *scg_sensemsg __PR((int, int, int, + const char **, char *, int maxcnt)); +#ifdef _SCG_SCSISENSE_H +extern int scg__errmsg __PR((SCSI *scgp, char *obuf, int maxcnt, + struct scsi_sense *, + struct scsi_status *, + int)); +#endif + +/* + * From scsiopen.c: + */ +#ifdef EOF /* stdio.h has been included */ +extern int scg_help __PR((FILE *f)); +#endif +extern SCSI *scg_open __PR((char *scsidev, char *errs, int slen, int odebug, int be_verbose)); +extern int scg_close __PR((SCSI * scgp)); +extern void scg_settimeout __PR((SCSI * scgp, int timeout)); +extern SCSI *scg_smalloc __PR((void)); +extern void scg_sfree __PR((SCSI *scgp)); + +/* + * From scgsettarget.c: + */ +extern int scg_settarget __PR((SCSI *scgp, int scsibus, int target, int lun)); + +/* + * From scsi-remote.c: + */ +extern scg_ops_t *scg_remote __PR((void)); + +/* + * From scsihelp.c: + */ +#ifdef EOF /* stdio.h has been included */ +extern void __scg_help __PR((FILE *f, char *name, char *tcomment, + char *tind, + char *tspec, + char *texample, + BOOL mayscan, + BOOL bydev)); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _SCG_SCSITRANSP_H */ diff --git a/src/schily/scg/spti-wnt.h b/src/schily/scg/spti-wnt.h new file mode 100644 index 0000000..cad384e --- /dev/null +++ b/src/schily/scg/spti-wnt.h @@ -0,0 +1,131 @@ +/* + * distilled information from various header files from Microsoft's + * DDK for Windows NT 4.0 + */ +#ifndef _SCSIPT_H_INC +#define _SCSIPT_H_INC + +#include + +typedef struct { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + ULONG DataBufferOffset; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; + + +typedef struct { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + PVOID DataBuffer; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; + + +typedef struct { + SCSI_PASS_THROUGH spt; + ULONG Filler; + UCHAR ucSenseBuf[32]; + UCHAR ucDataBuf[512]; +} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; + + +typedef struct { + SCSI_PASS_THROUGH_DIRECT spt; + ULONG Filler; + UCHAR ucSenseBuf[32]; +} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; + + + +typedef struct { + UCHAR NumberOfLogicalUnits; + UCHAR InitiatorBusId; + ULONG InquiryDataOffset; +} SCSI_BUS_DATA, *PSCSI_BUS_DATA; + + +typedef struct { + UCHAR NumberOfBusses; + SCSI_BUS_DATA BusData[1]; +} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; + + +typedef struct { + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + BOOLEAN DeviceClaimed; + ULONG InquiryDataLength; + ULONG NextInquiryDataOffset; + UCHAR InquiryData[1]; +} SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; + + +typedef struct { + ULONG Length; + UCHAR PortNumber; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; +} SCSI_ADDRESS, *PSCSI_ADDRESS; + + +/* + * method codes + */ +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 + +/* + * file access values + */ +#define FILE_ANY_ACCESS 0 +#define FILE_READ_ACCESS 0x0001 +#define FILE_WRITE_ACCESS 0x0002 + + +#define IOCTL_SCSI_BASE 0x00000004 + +/* + * constants for DataIn member of SCSI_PASS_THROUGH* structures + */ +#define SCSI_IOCTL_DATA_OUT 0 +#define SCSI_IOCTL_DATA_IN 1 +#define SCSI_IOCTL_DATA_UNSPECIFIED 2 + +/* + * Standard IOCTL define + */ +#define CTL_CODE(DevType, Function, Method, Access) \ + (((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) + +#define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE(IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_SCSI_GET_ADDRESS CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#endif diff --git a/src/schily/scg/srb_os2.h b/src/schily/scg/srb_os2.h new file mode 100644 index 0000000..b1d3aa6 --- /dev/null +++ b/src/schily/scg/srb_os2.h @@ -0,0 +1,169 @@ +/* @(#)srb_os2.h 1.0 98/10/28 Copyright 1998 D. Dorau, C. Wohlgemuth */ +/* + * Definitions for ASPI-Router (ASPIROUT.SYS). + * + * Copyright (c) 1998 D. Dorau, C. Wohlgemuth + */ + + +/* + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#pragma pack(1) + + /* SRB command */ +#define SRB_Inquiry 0x00 +#define SRB_Device 0x01 +#define SRB_Command 0x02 +#define SRB_Abort 0x03 +#define SRB_Reset 0x04 +#define SRB_Param 0x05 + + /* SRB status */ +#define SRB_Busy 0x00 /* SCSI request in progress */ +#define SRB_Done 0x01 /* SCSI request completed without error */ +#define SRB_Aborted 0x02 /* SCSI aborted by host */ +#define SRB_BadAbort 0x03 /* Unable to abort SCSI request */ +#define SRB_Error 0x04 /* SCSI request completed with error */ +#define SRB_BusyPost 0x10 /* SCSI request in progress with POST - Nokia */ +#define SRB_InvalidCmd 0x80 /* Invalid SCSI request */ +#define SRB_InvalidHA 0x81 /* Invalid Hhost adapter number */ +#define SRB_BadDevice 0x82 /* SCSI device not installed */ + + /* SRB flags */ +#define SRB_Post 0x01 /* Post vector valid */ +#define SRB_Link 0x02 /* Link vector valid */ +#define SRB_SG 0x04 /* Nokia: scatter/gather */ + /* S/G: n * (4 bytes length, 4 bytes addr) */ + /* No of s/g items not limited by HA spec. */ +#define SRB_NoCheck 0x00 /* determined by command, not checked */ +#define SRB_Read 0x08 /* target to host, length checked */ +#define SRB_Write 0x10 /* host to target, length checked */ +#define SRB_NoTransfer 0x18 /* no data transfer */ +#define SRB_DirMask 0x18 /* bit mask */ + + /* SRB host adapter status */ +#define SRB_NoError 0x00 /* No host adapter detected error */ +#define SRB_Timeout 0x11 /* Selection timeout */ +#define SRB_DataLength 0x12 /* Data over/underrun */ +#define SRB_BusFree 0x13 /* Unexpected bus free */ +#define SRB_BusSequence 0x14 /* Target bus sequence failure */ + + /* SRB target status field */ +#define SRB_NoStatus 0x00 /* No target status */ +#define SRB_CheckStatus 0x02 /* Check status (sense data valid) */ +#define SRB_LUN_Busy 0x08 /* Specified LUN is busy */ +#define SRB_Reserved 0x18 /* Reservation conflict */ + +#define MaxCDBStatus 64 /* max size of CDB + status */ + + +typedef struct SRb { + unsigned char cmd, /* 00 */ + status, /* 01 */ + ha_num, /* 02 */ + flags; /* 03 */ + unsigned long res_04_07; /* 04..07 */ + union { /* 08 */ + + /* SRB_Inquiry */ + struct { + unsigned char num_ha, /* 08 */ + ha_target, /* 09 */ + aspimgr_id[16], /* 0A..19 */ + host_id[16], /* 1A..29 */ + unique_id[16]; /* 2A..39 */ + } inq; + + /* SRB_Device */ + struct { + unsigned char target, /* 08 */ + lun, /* 09 */ + devtype; /* 0A */ + } dev; + + /* SRB_Command */ + struct { + unsigned char target, /* 08 */ + lun; /* 09 */ + unsigned long data_len; /* 0A..0D */ + unsigned char sense_len; /* 0E */ + unsigned long data_ptr; /* 0F..12 */ + unsigned long link_ptr; /* 13..16 */ + // void * _Seg16 data_ptr; /* 0F..12 */ + // void * _Seg16 link_ptr; /* 13..16 */ + unsigned char cdb_len, /* 17 */ + ha_status, /* 18 */ + target_status; /* 19 */ + unsigned char _Seg16postSRB[4]; + // void (* _Seg16 post) (SRB *); /* 1A..1D */ + unsigned char res_1E_29[12]; /* 1E..29 */ + unsigned char res_2A_3F[22]; /* 2A..3F */ + unsigned char cdb_st[64]; /* 40..7F CDB+status */ + unsigned char res_80_BF[64]; /* 80..BF */ + } cmd; + + /* SRB_Abort */ + struct { + unsigned char _Seg16srb[4]; + // void * _Seg16 srb; /* 08..0B */ + } abt; + + /* SRB_Reset */ + struct { + unsigned char target, /* 08 */ + lun, /* 09 */ + res_0A_17[14], /* 0A..17 */ + ha_status, /* 18 */ + target_status; /* 19 */ + } res; + + /* SRB_Param - unused by ASPI4OS2 */ + struct { + unsigned char unique[16]; /* 08..17 */ + } par; + + } u; +} SRB; + + +// SCSI sense codes +// Note! This list may not be complete. I did this compilation for use with tape drives. + +#define Sense_Current 0x70; // Current Error +#define Sense_Deferred 0x71; // Deferred Error +#define Sense_Filemark 0x80; // Filemark detected +#define Sense_EOM 0x40; // End of medium detected +#define Sense_ILI 0x20; // Incorrect length indicator + +// Sense Keys + +#define SK_NoSense 0x00; // No Sense +#define SK_RcvrdErr 0x01; // Recovered Error +#define SK_NotReady 0x02; // Not ready +#define SK_MedErr 0x03; // Medium Error +#define SK_HWErr 0x04; // Hardware Error +#define SK_IllReq 0x05; // Illegal Request +#define SK_UnitAtt 0x06; // Unit attention +#define SK_DataProt 0x07: // Data Protect +#define SK_BlankChk 0x08: // Blank Check +#define SK_VndSpec 0x09; // Vendor Specific +#define SK_CopyAbort 0x0A; // Copy Aborted +#define SK_AbtdCmd 0x0B; // Aborted Command +#define SK_Equal 0x0C; // Equal +#define SK_VolOvfl 0x0D; // Volume Overflow +#define SK_MisComp 0x0E; // Miscompare +#define SK_Reserved 0x0F; // Reserved diff --git a/src/schily/schily.h b/src/schily/schily.h new file mode 100644 index 0000000..8163a16 --- /dev/null +++ b/src/schily/schily.h @@ -0,0 +1,308 @@ +/* @(#)schily.h 1.52 04/03/05 Copyright 1985-2002 J. Schilling */ +/* + * Definitions for libschily + * + * This file should be included past: + * + * mconfig.h / config.h + * standard.h + * stdio.h + * stdlib.h (better use stdxlib.h) + * unistd.h (better use unixstd.h) needed LARGEFILE support + * string.h + * sys/types.h + * + * If you need stdio.h, you must include it before schily.h + * + * NOTE: If you need ctype.h and did not include stdio.h you need to + * include ctype.h past schily.h as OpenBSD does not follow POSIX and + * defines EOF in ctype.h + * + * Copyright (c) 1985-2002 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SCHILY_H +#define _SCHILY_H + +#ifndef _STANDARD_H +#include +#endif +#ifndef _CCOMDEFS_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_INCL_SYS_TYPES_H) || defined(off_t) +# ifndef FOUND_OFF_T +# define FOUND_OFF_T +# endif +#endif +#if defined(_INCL_SYS_TYPES_H) || defined(size_t) +# ifndef FOUND_SIZE_T +# define FOUND_SIZE_T +# endif +#endif + +#ifdef __never_def__ +/* + * It turns out that we cannot use the folloginw definition because there are + * some platforms that do not behave application friendly. These are mainly + * BSD-4.4 based systems (which #undef a definition when size_t is available. + * We actually removed this code because of a problem with QNX Neutrino. + * For this reason, it is important not to include directly but + * via the Schily SING include files so we know whether it has been included + * before we come here. + */ +#if defined(_SIZE_T) || defined(_T_SIZE_) || defined(_T_SIZE) || \ + defined(__SIZE_T) || defined(_SIZE_T_) || \ + defined(_GCC_SIZE_T) || defined(_SIZET_) || \ + defined(__sys_stdtypes_h) || defined(___int_size_t_h) || defined(size_t) + +#ifndef FOUND_SIZE_T +# define FOUND_SIZE_T /* We already included a size_t definition */ +#endif +#endif +#endif /* __never_def__ */ + +#if defined(HAVE_LARGEFILES) +# define _fcons _fcons64 +# define fdup fdup64 +# define fileluopen fileluopen64 +# define fileopen fileopen64 +# define filemopen filemopen64 +# define filepos filepos64 +# define filereopen filereopen64 +# define fileseek fileseek64 +# define filesize filesize64 +# define filestat filestat64 +# define _openfd _openfd64 +#endif + +#ifdef EOF /* stdio.h has been included */ +extern int _cvmod __PR((const char *, int *, int *)); +extern FILE *_fcons __PR((FILE *, int, int)); +extern FILE *fdup __PR((FILE *)); +extern int fdown __PR((FILE *)); +extern int fexecl __PR((const char *, FILE *, FILE *, FILE *, + const char *, ...)); +extern int fexecle __PR((const char *, FILE *, FILE *, FILE *, + const char *, ...)); + /* 6th arg not const, fexecv forces av[ac] = NULL */ +extern int fexecv __PR((const char *, FILE *, FILE *, FILE *, int, + char **)); +extern int fexecve __PR((const char *, FILE *, FILE *, FILE *, + char * const *, char * const *)); +extern int fspawnv __PR((FILE *, FILE *, FILE *, int, char * const *)); +extern int fspawnl __PR((FILE *, FILE *, FILE *, + const char *, const char *, ...)); +extern int fspawnv_nowait __PR((FILE *, FILE *, FILE *, + const char *, int, char *const*)); +extern int fgetline __PR((FILE *, char *, int)); +extern int fgetstr __PR((FILE *, char *, int)); +extern void file_raise __PR((FILE *, int)); +extern int fileclose __PR((FILE *)); +extern FILE *fileluopen __PR((int, const char *)); +extern FILE *fileopen __PR((const char *, const char *)); +#ifdef _INCL_SYS_TYPES_H +extern FILE *filemopen __PR((const char *, const char *, mode_t)); +#endif +#ifdef FOUND_OFF_T +extern off_t filepos __PR((FILE *)); +#endif +extern int fileread __PR((FILE *, void *, int)); +extern int ffileread __PR((FILE *, void *, int)); +extern FILE *filereopen __PR((const char *, const char *, FILE *)); +#ifdef FOUND_OFF_T +extern int fileseek __PR((FILE *, off_t)); +extern off_t filesize __PR((FILE *)); +#endif +#ifdef S_IFMT +extern int filestat __PR((FILE *, struct stat *)); +#endif +extern int filewrite __PR((FILE *, void *, int)); +extern int ffilewrite __PR((FILE *, void *, int)); +extern int flush __PR((void)); +extern int fpipe __PR((FILE **)); +/*extern int fprintf __PR((FILE *, const char *, ...)) __printflike__(2, 3);*/ +extern int getbroken __PR((FILE *, char *, char, char **, int)); +extern int ofindline __PR((FILE *, char, const char *, int, + char **, int)); +extern int peekc __PR((FILE *)); + +#ifdef __never_def__ +/* + * We cannot define this or we may get into problems with DOS based systems. + */ +extern int spawnv __PR((FILE *, FILE *, FILE *, int, char * const *)); +extern int spawnl __PR((FILE *, FILE *, FILE *, + const char *, const char *, ...)); +extern int spawnv_nowait __PR((FILE *, FILE *, FILE *, + const char *, int, char *const*)); +#endif /* __never_def__m */ +#endif /* EOF */ + +extern int _niread __PR((int, void *, int)); +extern int _niwrite __PR((int, void *, int)); +extern int _nixread __PR((int, void *, int)); +extern int _nixwrite __PR((int, void *, int)); +extern int _openfd __PR((const char *, int)); +extern int on_comerr __PR((void (*fun)(int, void *), void *arg)); +/*PRINTFLIKE1*/ +extern void comerr __PR((const char *, ...)) __printflike__(1, 2); +/*PRINTFLIKE2*/ +extern void comerrno __PR((int, const char *, ...)) __printflike__(2, 3); +/*PRINTFLIKE1*/ +extern int errmsg __PR((const char *, ...)) __printflike__(1, 2); +/*PRINTFLIKE2*/ +extern int errmsgno __PR((int, const char *, ...)) __printflike__(2, 3); +#ifdef FOUND_SIZE_T +/*PRINTFLIKE3*/ +extern int serrmsg __PR((char *, size_t, const char *, ...)) __printflike__(3, 4); +/*PRINTFLIKE4*/ +extern int serrmsgno __PR((int, char *, size_t, const char *, ...)) __printflike__(4, 5); +#endif +extern void comexit __PR((int)); +extern char *errmsgstr __PR((int)); +/*PRINTFLIKE1*/ +extern int error __PR((const char *, ...)) __printflike__(1, 2); +extern char *fillbytes __PR((void *, int, char)); +extern char *findbytes __PR((const void *, int, char)); +extern int findline __PR((const char *, char, const char *, + int, char **, int)); +extern int getline __PR((char *, int)); +extern int getstr __PR((char *, int)); +extern int breakline __PR((char *, char, char **, int)); +extern int getallargs __PR((int *, char * const**, const char *, ...)); +extern int getargs __PR((int *, char * const**, const char *, ...)); +extern int getfiles __PR((int *, char * const**, const char *)); +extern char *astoi __PR((const char *, int *)); +extern char *astol __PR((const char *, long *)); +extern char *astolb __PR((const char *, long *, int base)); +#ifdef _UTYPES_H +extern char *astoll __PR((const char *, Llong *)); +extern char *astollb __PR((const char *, Llong *, int base)); +#endif + +/*extern void handlecond __PR((const char *, SIGBLK *, int(*)(const char *, long, long), long));*/ +/*extern void unhandlecond __PR((SIGBLK *));*/ + +extern int patcompile __PR((const unsigned char *, int, int *)); +extern unsigned char *patmatch __PR((const unsigned char *, const int *, + const unsigned char *, int, int, int, int[])); +extern unsigned char *patlmatch __PR((const unsigned char *, const int *, + const unsigned char *, int, int, int, int[])); + +/*extern int printf __PR((const char *, ...)) __printflike__(1, 2);*/ +extern char *movebytes __PR((const void *, void *, int)); + +extern void save_args __PR((int, char **)); +extern int saved_ac __PR((void)); +extern char **saved_av __PR((void)); +extern char *saved_av0 __PR((void)); +#ifndef seterrno +extern int seterrno __PR((int)); +#endif +extern void set_progname __PR((const char *)); +extern char *get_progname __PR((void)); + +extern void setfp __PR((void * const *)); +extern int wait_chld __PR((int)); /* for fspawnv_nowait() */ +extern int geterrno __PR((void)); +extern void raisecond __PR((const char *, long)); +#ifdef FOUND_SIZE_T +/* + * We currently cannot define this here because there IXIX has a definition + * than violates the standard. + */ +#ifndef HAVE_SNPRINTF +/*PRINTFLIKE3*/ +extern int snprintf __PR((char *, size_t, const char *, ...)) __printflike__(3, 4); +#endif +#endif +/*extern int sprintf __PR((char *, const char *, ...)); ist woanders falsch deklariert !!!*/ +extern char *strcatl __PR((char *, ...)); +extern int streql __PR((const char *, const char *)); +#ifdef va_arg +extern int format __PR((void (*)(char, long), long, const char *, va_list)); +#else +extern int format __PR((void (*)(char, long), long, const char *, void *)); +#endif + +extern int ftoes __PR((char *, double, int, int)); +extern int ftofs __PR((char *, double, int, int)); + +#ifdef EOF /* stdio.h has been included */ +/*PRINTFLIKE2*/ +extern int js_fprintf __PR((FILE *, const char *, ...)) __printflike__(2, 3); +/*PRINTFLIKE1*/ +extern int js_printf __PR((const char *, ...)) __printflike__(1, 2); +#ifdef FOUND_SIZE_T +/*PRINTFLIKE3*/ +extern int js_snprintf __PR((char *, size_t, const char *, ...)) __printflike__(3, 4); +#endif +/*PRINTFLIKE2*/ +extern int js_sprintf __PR((char *, const char *, ...)) __printflike__(2, 3); +#endif /* EOF */ + +extern void swabbytes __PR((void *, int)); +extern char **getmainfp __PR((void)); +extern char **getavp __PR((void)); +extern char *getav0 __PR((void)); +extern void **getfp __PR((void)); +extern int flush_reg_windows __PR((int)); +extern int cmpbytes __PR((const void *, const void *, int)); +extern int cmpnullbytes __PR((const void *, int)); + +#ifdef nonono +#if defined(HAVE_LARGEFILES) +/* + * To allow this, we need to figure out how to do autoconfiguration for off64_t + */ +extern FILE *_fcons64 __PR((FILE *, int, int)); +extern FILE *fdup64 __PR((FILE *)); +extern FILE *fileluopen64 __PR((int, const char *)); +extern FILE *fileopen64 __PR((const char *, const char *)); +#ifdef FOUND_OFF_T +extern off64_t filepos64 __PR((FILE *)); +#endif +extern FILE *filereopen64 __PR((const char *, const char *, FILE *)); +#ifdef FOUND_OFF_T +extern int fileseek64 __PR((FILE *, off64_t)); +extern off64_t filesize64 __PR((FILE *)); +#endif +#ifdef S_IFMT +extern int filestat64 __PR((FILE *, struct stat *)); +#endif +extern int _openfd64 __PR((const char *, int)); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#if defined(_JOS) || defined(JOS) +# ifndef _JOS_IO_H +# include +# endif +#endif + +#endif /* _SCHILY_H */ diff --git a/src/schily/sigblk.h b/src/schily/sigblk.h new file mode 100644 index 0000000..4eefba0 --- /dev/null +++ b/src/schily/sigblk.h @@ -0,0 +1,69 @@ +/* @(#)sigblk.h 1.10 03/07/10 Copyright 1985, 1995-2003 J. Schilling */ +/* + * software signal block definition + * + * Copyright (c) 1985, 1995-2003 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SIGBLK_H +#define _SIGBLK_H + +#ifndef _MCONFIG_H +#include +#endif +#ifndef _STANDARD_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct sigblk { + long **sb_savfp; /* Real saved framepointer */ + struct sigblk *sb_signext; /* Next sw signal blk for this func */ + short sb_siglen; /* Strlen for sb_signame */ + const char *sb_signame; /* Name of software signal */ + + /* sb_sigfun: function to call */ + int (*sb_sigfun) __PR((const char *, long, long)); + + long sb_sigarg; /* Second arg for sb_sigfun */ +} SIGBLK; + +/* + * The handler function is called with three arguments: + * + * 1) The name of the software signal + * 2) The argument from the handlecond() call + * 3) The argument from the raisecond() call + */ +typedef int (*handlefunc_t) __PR((const char *, long, long)); + +extern void handlecond __PR((const char *, SIGBLK *, + int(*)(const char *, long, long), + long)); +extern void raisecond __PR((const char *, long)); +extern void starthandlecond __PR((SIGBLK *)); +extern void unhandlecond __PR((SIGBLK *)); + +#ifdef __cplusplus +} +#endif + +#endif /* _SIGBLK_H */ diff --git a/src/schily/sigdefs.h b/src/schily/sigdefs.h new file mode 100644 index 0000000..6344599 --- /dev/null +++ b/src/schily/sigdefs.h @@ -0,0 +1,70 @@ +/* @(#)sigdefs.h 1.5 02/01/19 Copyright 1997 J. Schilling */ +/* + * Signal abstraction for BSD/SVR4 signals + * + * Copyright (c) 1997 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _SIGDEFS_H +#define _SIGDEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifdef HAVE_SIGSET +/* + * Try to by default use the function that sets up signal handlers in a way + * that does not reset the handler after it has been called. + */ +#define signal sigset +#endif + +#ifdef HAVE_SIGPROCMASK +#define block_sigs(a) { \ + sigset_t __new; \ + \ + sigfillset(&__new); \ + sigprocmask(SIG_BLOCK, &__new, &a);\ + } +#define unblock_sig(s) { \ + sigset_t __new; \ + \ + sigemptyset(&__new); \ + sigaddset(&__new, (s)); \ + sigprocmask(SIG_UNBLOCK, &__new, NULL);\ + } +#define restore_sigs(a) sigprocmask(SIG_SETMASK, &a, 0); + +#else /* !HAVE_SIGPROCMASK */ + +#define sigset_t int +#define block_sigs(a) a = sigblock(0xFFFFFFFF) +#define restore_sigs(a) sigsetmask(a); +#define unblock_sig(s) { \ + int __old, __new; \ + \ + block_sigs(__old); \ + __new = sigmask(s); \ + __new = __old & ~__new; \ + sigsetmask(__new); \ + } + +#endif /* HAVE_SIGPROCMASK */ + +#endif /* _SIGDEFS_H */ diff --git a/src/schily/standard.h b/src/schily/standard.h new file mode 100644 index 0000000..b8e576d --- /dev/null +++ b/src/schily/standard.h @@ -0,0 +1,154 @@ +/* @(#)standard.h 1.31 03/08/23 Copyright 1985 J. Schilling */ +/* + * standard definitions + * + * This file should be included past: + * + * mconfig.h / config.h + * stdio.h + * stdlib.h (better use stdxlib.h) + * unistd.h (better use unixstd.h) needed LARGEFILE support + * + * If you need stdio.h, you must include it before standard.h + * + * Copyright (c) 1985 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STANDARD_H +#define _STANDARD_H + +#ifndef _MCONFIG_H +#include +#endif +#ifndef _PROTOTYP_H +#include +#endif + +#ifdef M68000 +# ifndef tos +# define JOS 1 +# endif +#endif + +/* + * fundamental constants + */ +#ifndef NULL +# define NULL 0 +#endif +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +/* + * Program exit codes + */ +#define EX_BAD (-1) + +/* + * standard storage class definitions + */ +#define GLOBAL extern +#define IMPORT extern +#define EXPORT +#define INTERN static +#define LOCAL static +#define FAST register + +#ifndef PROTOTYPES +# ifndef const +# define const +# endif +# ifndef signed +# define signed +# endif +# ifndef volatile +# define volatile +# endif +#endif /* PROTOTYPES */ + +/* + * standard type definitions + * + * The hidden Schily BOOL definition is used in case we need to deal + * with other BOOL defines on systems we like to port to. + */ +typedef int __SBOOL; +typedef int BOOL; +#ifdef JOS +# ifndef __GNUC__ +# define NO_VOID +# endif +#endif +#ifdef NO_VOID + typedef int VOID; +# ifndef lint + typedef int void; +# endif +#else + typedef void VOID; +#endif + +#if defined(_INCL_SYS_TYPES_H) || defined(off_t) +# ifndef FOUND_OFF_T +# define FOUND_OFF_T +# endif +#endif +#if defined(_INCL_SYS_TYPES_H) || defined(size_t) +# ifndef FOUND_SIZE_T +# define FOUND_SIZE_T +# endif +#endif + +#ifdef __never_def__ +/* + * It turns out that we cannot use the folloginw definition because there are + * some platforms that do not behave application friendly. These are mainly + * BSD-4.4 based systems (which #undef a definition when size_t is available. + * We actually removed this code because of a problem with QNX Neutrino. + * For this reason, it is important not to include directly but + * via the Schily SING include files so we know whether it has been included + * before we come here. + */ +#if defined(_SIZE_T) || defined(_T_SIZE_) || defined(_T_SIZE) || \ + defined(__SIZE_T) || defined(_SIZE_T_) || \ + defined(_GCC_SIZE_T) || defined(_SIZET_) || \ + defined(__sys_stdtypes_h) || defined(___int_size_t_h) || defined(size_t) + +#ifndef FOUND_SIZE_T +# define FOUND_SIZE_T /* We already included a size_t definition */ +#endif +#endif +#endif /* __never_def__ */ + +#if defined(_JOS) || defined(JOS) +# ifndef _SCHILY_H +# include +# endif + +# ifndef _JOS_DEFS_H +# include +# endif + +# ifndef _JOS_IO_H +# include +# endif +#endif + +#endif /* _STANDARD_H */ diff --git a/src/schily/statdefs.h b/src/schily/statdefs.h new file mode 100644 index 0000000..9a28dae --- /dev/null +++ b/src/schily/statdefs.h @@ -0,0 +1,339 @@ +/* @(#)statdefs.h 1.9 03/06/15 Copyright 1998 J. Schilling */ +/* + * Definitions for stat() file mode + * + * Copyright (c) 1998 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STATDEFS_H +#define _STATDEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifndef _INCL_SYS_TYPES_H +#include /* Needed for sys/stat.h */ +#define _INCL_SYS_TYPES_H +#endif +#ifndef _INCL_SYS_STAT_H +#include /* For S_IS* and S_IF* */ +#define _INCL_SYS_STAT_H +#endif + +/* + * Apollo Domain/OS has a broken sys/stat.h that defines + * S_IFIFO == S_IFSOCK and creates trouble if the constants + * are used as case labels. + */ +#if S_IFIFO == S_IFSOCK +# undef S_IFSOCK +#endif + +#ifdef STAT_MACROS_BROKEN +#undef S_ISFIFO /* Named pipe */ +#undef S_ISCHR /* Character special */ +#undef S_ISMPC /* UNUSED multiplexed c */ +#undef S_ISDIR /* Directory */ +#undef S_ISNAM /* Named file (XENIX) */ +#undef S_ISBLK /* Block special */ +#undef S_ISMPB /* UNUSED multiplexed b */ +#undef S_ISREG /* Regular file */ +#undef S_ISCNT /* Contiguous file */ +#undef S_ISLNK /* Symbolic link */ +#undef S_ISSHAD /* Solaris shadow inode */ +#undef S_ISSOCK /* UNIX domain socket */ +#undef S_ISDOOR /* Solaris DOOR */ +#undef S_ISWHT /* BSD whiteout */ +#undef S_ISEVC /* UNOS eventcount */ +#endif + +#ifndef S_ISFIFO /* 1 Named pipe */ +# ifdef S_IFIFO +# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +# else +# define S_ISFIFO(m) (0) +# endif +#endif +#ifndef S_ISCHR /* 2 Character special */ +# ifdef S_IFCHR +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +# else +# define S_ISCHR(m) (0) +# endif +#endif +#ifndef S_ISMPC /* 3 UNUSED multiplexed char */ +# ifdef S_IFMPC +# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) +# else +# define S_ISMPC(m) (0) +# endif +#endif +#ifndef S_ISDIR /* 4 Directory */ +# ifdef S_IFDIR +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# else +# define S_ISDIR(m) (0) +# endif +#endif +#ifndef S_ISNAM /* 5 Named file (XENIX) */ +# ifdef S_IFNAM +# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM) +# else +# define S_ISNAM(m) (0) +# endif +#endif +#ifndef S_ISBLK /* 6 Block special */ +# ifdef S_IFBLK +# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +# else +# define S_ISBLK(m) (0) +# endif +#endif +#ifndef S_ISMPB /* 7 UNUSED multiplexed block */ +# ifdef S_IFMPB +# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) +# else +# define S_ISMPB(m) (0) +# endif +#endif +#ifndef S_ISREG /* 8 Regular file */ +# ifdef S_IFREG +# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +# else +# define S_ISREG(m) (0) +# endif +#endif +#ifndef S_ISCNT /* 9 Contiguous file */ +# ifdef S_IFCNT +# define S_ISCNT(m) (((m) & S_IFMT) == S_IFCNT) +# else +# define S_ISCNT(m) (0) +# endif +#endif +#ifndef S_ISLNK /* 10 Symbolic link */ +# ifdef S_IFLNK +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +# else +# define S_ISLNK(m) (0) +# endif +#endif +#ifndef S_ISSHAD /* 11 Solaris shadow inode */ +# ifdef S_IFSHAD +# define S_ISSHAD(m) (((m) & S_IFMT) == S_IFSHAD) +# else +# define S_ISSHAD(m) (0) +# endif +#endif +#ifndef S_ISSOCK /* 12 UNIX domain socket */ +# ifdef S_IFSOCK +# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +# else +# define S_ISSOCK(m) (0) +# endif +#endif +#ifndef S_ISDOOR /* 13 Solaris DOOR */ +# ifdef S_IFDOOR +# define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR) +# else +# define S_ISDOOR(m) (0) +# endif +#endif +#ifndef S_ISWHT /* 14 BSD whiteout */ +# ifdef S_IFWHT +# define S_ISWHT(m) (((m) & S_IFMT) == S_ISWHT) +# else +# define S_ISWHT(m) (0) +# endif +#endif +#ifndef S_IFEVC /* 15 UNOS eventcount */ +# ifdef S_IFEVC +# define S_ISEVC(m) (((m) & S_IFMT) == S_IFEVC) +# else +# define S_ISEVC(m) (0) +# endif +#endif + +#ifndef S_TYPEISMQ +/* + * XXX ??? where is a definition of a message queue ??? + */ +# define S_TYPEISMQ(_stbuf) (0) +#endif +#ifndef S_TYPEISSEM +# ifdef S_INSEM +# define S_TYPEISSEM(_stbuf) (S_ISNAM((_stbuf)->st_mode) && (_stbuf)->st_rdev == S_INSEM) +# else +# define S_TYPEISSEM(_stbuf) (0) +# endif +#endif +#ifndef S_TYPEISSHM +# ifdef S_INSHD +# define S_TYPEISSHM(_stbuf) (S_ISNAM((_stbuf)->st_mode) && (_stbuf)->st_rdev == S_INSHD) +# else +# define S_TYPEISSHM(_stbuf) (0) +# endif +#endif + +/* + * Mode permission bits. + * UNIX V.7 has only S_ISUID/S_ISGID/S_ISVTX and S_IREAD/S_IWRITE/S_IEXEC + */ +#ifndef S_ISUID /* Set-user-ID on execution */ +#define S_ISUID 0 /* If it is not defined, it is not supported */ +#endif +#ifndef S_ISGID /* Set-group-ID on execution */ +#define S_ISGID 0 /* If it is not defined, it is not supported */ +#endif +#ifndef S_ISVTX /* On directories, restricted deletion flag */ +#define S_ISVTX 0 /* If it is not defined, it is not supported */ +#endif + +#ifndef S_IRUSR /* Read permission, owner */ +#ifdef S_IREAD +#define S_IRUSR S_IREAD /* Needed on old UNIX systems */ +#else +#define S_IRUSR 0400 +#endif +#endif +#ifndef S_IWUSR /* Write permission, owner */ +#ifdef S_IWRITE +#define S_IWUSR S_IWRITE /* Needed on old UNIX systems */ +#else +#define S_IWUSR 0200 +#endif +#endif +#ifndef S_IXUSR /* Execute/search permission, owner */ +#ifdef S_IEXEC +#define S_IXUSR S_IEXEC /* Needed on old UNIX systems */ +#else +#define S_IXUSR 0100 +#endif +#endif +#ifndef S_IRGRP /* Read permission, group */ +#ifdef S_IREAD +#define S_IRGRP (S_IREAD >> 3) /* Needed on old UNIX systems */ +#else +#define S_IRGRP 040 +#endif +#endif +#ifndef S_IWGRP /* Write permission, group */ +#ifdef S_IWRITE +#define S_IWGRP (S_IWRITE >> 3) /* Needed on old UNIX systems */ +#else +#define S_IWGRP 020 +#endif +#endif +#ifndef S_IXGRP /* Execute/search permission, group */ +#ifdef S_IEXEC +#define S_IXGRP (S_IEXEC >> 3) /* Needed on old UNIX systems */ +#else +#define S_IXGRP 010 +#endif +#endif +#ifndef S_IROTH /* Read permission, others */ +#ifdef S_IREAD +#define S_IROTH (S_IREAD >> 6) /* Needed on old UNIX systems */ +#else +#define S_IROTH 004 +#endif +#endif +#ifndef S_IWOTH /* Write permission, others */ +#ifdef S_IWRITE +#define S_IWOTH (S_IWRITE >> 6) /* Needed on old UNIX systems */ +#else +#define S_IWOTH 002 +#endif +#endif +#ifndef S_IXOTH /* Execute/search permission, others */ +#ifdef S_IEXEC +#define S_IXOTH (S_IEXEC >> 6) /* Needed on old UNIX systems */ +#else +#define S_IXOTH 001 +#endif +#endif + +#ifndef S_IRWXU /* Read, write, execute/search by owner */ +#define S_IRWXU (S_IRUSR|S_IWUSR|S_IXUSR) +#endif +#ifndef S_IRWXG /* Read, write, execute/search by group */ +#define S_IRWXG (S_IRGRP|S_IWGRP|S_IXGRP) +#endif +#ifndef S_IRWXO /* Read, write, execute/search by others */ +#define S_IRWXO (S_IROTH|S_IWOTH|S_IXOTH) +#endif + +/* + * SCO UnixWare has st_atim.st__tim.tv_nsec but the st_atim.tv_nsec tests also + * succeeds. If we use st_atim.tv_nsec on UnixWare, we get a warning about + * illegal structure usage. For this reason, our code needs to have + * #ifdef HAVE_ST__TIM before #ifdef HAVE_ST_NSEC. + */ +#if defined(HAVE_ST_ATIMENSEC) + +#define stat_ansecs(s) ((s)->st_atimensec) +#define stat_mnsecs(s) ((s)->st_mtimensec) +#define stat_cnsecs(s) ((s)->st_ctimensec) + +#define _FOUND_STAT_NSECS_ +#endif + +#if defined(HAVE_ST_SPARE1) && !defined(_FOUND_STAT_NSECS_) + +#define stat_ansecs(s) ((s)->st_spare1 * 1000) +#define stat_mnsecs(s) ((s)->st_spare2 * 1000) +#define stat_cnsecs(s) ((s)->st_spare3 * 1000) + +#define _FOUND_STAT_USECS_ +#define _FOUND_STAT_NSECS_ +#endif + +#if defined(HAVE_ST__TIM) && !defined(_FOUND_STAT_NSECS_) + +#define stat_ansecs(s) ((s)->st_atim.st__tim.tv_nsec) +#define stat_mnsecs(s) ((s)->st_mtim.st__tim.tv_nsec) +#define stat_cnsecs(s) ((s)->st_ctim.st__tim.tv_nsec) + +#define _FOUND_STAT_NSECS_ +#endif + +#if defined(HAVE_ST_NSEC) && !defined(_FOUND_STAT_NSECS_) + +#define stat_ansecs(s) ((s)->st_atim.tv_nsec) +#define stat_mnsecs(s) ((s)->st_mtim.tv_nsec) +#define stat_cnsecs(s) ((s)->st_ctim.tv_nsec) + +#define _FOUND_STAT_NSECS_ +#endif + +#if defined(HAVE_ST_ATIMESPEC) && !defined(_FOUND_STAT_NSECS_) + +#define stat_ansecs(s) ((s)->st_atimespec.tv_nsec) +#define stat_mnsecs(s) ((s)->st_mtimespec.tv_nsec) +#define stat_cnsecs(s) ((s)->st_ctimespec.tv_nsec) + +#define _FOUND_STAT_NSECS_ +#endif + +#if !defined(_FOUND_STAT_NSECS_) +#define stat_ansecs(s) (0) +#define stat_mnsecs(s) (0) +#define stat_cnsecs(s) (0) +#endif + +#endif /* _STATDEFS_H */ diff --git a/src/schily/stdxlib.h b/src/schily/stdxlib.h new file mode 100644 index 0000000..3622ec6 --- /dev/null +++ b/src/schily/stdxlib.h @@ -0,0 +1,54 @@ +/* @(#)stdxlib.h 1.6 01/07/15 Copyright 1996 J. Schilling */ +/* + * Definitions for stdlib + * + * Copyright (c) 1996 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _STDXLIB_H +#define _STDXLIB_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#ifndef _INCL_STDLIB_H +#include +#define _INCL_STDLIB_H +#endif +#else + +extern char *malloc(); +extern char *realloc(); + +extern double atof(); + +#endif /* HAVE_STDLIB_H */ + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif +#ifndef RAND_MAX +#define RAND_MAX 32767 +#endif + +#endif /* _STDXLIB_H */ diff --git a/src/schily/stkframe.h b/src/schily/stkframe.h new file mode 100644 index 0000000..10aed2b --- /dev/null +++ b/src/schily/stkframe.h @@ -0,0 +1,90 @@ +/* @(#)stkframe.h 1.10 03/06/15 Copyright 1995 J. Schilling */ +/* + * Common definitions for routines that parse the stack frame. + * + * This file has to be fixed if you want to port routines which use getfp(). + * Have a look at struct frame below and use it as a sample, + * the new struct frame must at least contain a member 'fr_savfp'. + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STKFRAME_H +#define _STKFRAME_H + +#ifndef _MCONFIG_H +#include +#endif + +#if defined(sun) && (defined(SVR4) || defined(__SVR4) || defined(__SVR4__)) + /* + * Solaris 2.x aka SunOS 5.x + */ +# ifdef i386 + /* + * On Solaris 2.1 x86 sys/frame.h is not useful at all + * On Solaris 2.4 x86 sys/frame.h is buggy (fr_savfp is int!!) + */ +# ifndef _INCL_SYS_REG_H +# include +# define _INCL_SYS_REG_H +# endif +# endif +# ifndef _INCL_SYS_FRAME_H +# include +# define _INCL_SYS_FRAME_H +# endif + +#else +# if defined(sun) + /* + * SunOS 4.x + */ +# ifndef _INCL_MACHINE_FRAME_H +# include +# define _INCL_MACHINE_FRAME_H +# endif +# else + /* + * Anything that is not SunOS + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * XXX: I hope this will be useful on other machines (no guarantee) + * XXX: It is taken from a sun Motorola system, but should also be useful + * XXX: on a i386. + * XXX: In general you have to write a sample program, set a breakpoint + * XXX: on a small function and inspect the stackframe with adb. + */ + +struct frame { + struct frame *fr_savfp; /* saved frame pointer */ + int fr_savpc; /* saved program counter */ + int fr_arg[1]; /* array of arguments */ +}; + +#ifdef __cplusplus +} +#endif + +# endif /* ! defined (sun) */ +#endif /* ! defined (sun) && (defined(SVR4) || defined(__SVR4) || defined(__SVR4__)) */ + +#endif /* _STKFRAME_H */ diff --git a/src/schily/strdefs.h b/src/schily/strdefs.h new file mode 100644 index 0000000..4564c0a --- /dev/null +++ b/src/schily/strdefs.h @@ -0,0 +1,114 @@ +/* @(#)strdefs.h 1.8 03/03/09 Copyright 1996 J. Schilling */ +/* + * Definitions for strings + * + * Copyright (c) 1996 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRDEFS_H +#define _STRDEFS_H + +#ifndef _MCONFIG_H +#include +#endif +#ifndef _PROTOTYP_H +#include +#endif + +/* + * It may be that IBM's AIX has problems when doing + * #include + * #include + * So I moved the #include to the top. As the file strings.h + * defines strcasecmp() we may need it... + * + * Note that the only real problem appears if we use rubbish FSF based code that + * #defines _NO_PROTO + */ +#ifdef HAVE_STRINGS_H +#ifndef _INCL_STRINGS_H +#include +#define _INCL_STRINGS_H +#endif +#endif /* HAVE_STRINGS_H */ + + +#ifdef HAVE_STRING_H +#ifndef _INCL_STRING_H +#include +#define _INCL_STRING_H +#endif +#else /* HAVE_STRING_H */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NULL +#define NULL 0 +#endif + +extern void *memcpy __PR((void *, const void *, int)); +extern void *memmove __PR((void *, const void *, int)); +extern char *strcpy __PR((char *, const char *)); +extern char *strncpy __PR((char *, const char *, int)); + +extern char *strcat __PR((char *, const char *)); +extern char *strncat __PR((char *, const char *, int)); + +extern int memcmp __PR((const void *, const void *, int)); +extern int strcmp __PR((const char *, const char *)); +extern int strcoll __PR((const char *, const char *)); +extern int strncmp __PR((const char *, const char *, int)); +extern int strxfrm __PR((char *, const char *, int)); + +extern void *memchr __PR((const void *, int, int)); +extern char *strchr __PR((const char *, int)); + +extern int strcspn __PR((const char *, const char *)); +/*#pragma int_to_unsigned strcspn*/ + +extern char *strpbrk __PR((const char *, const char *)); +extern char *strrchr __PR((const char *, int)); + +extern int strspn __PR((const char *, const char *)); +/*#pragma int_to_unsigned strspn*/ + +extern char *strstr __PR((const char *, const char *)); +extern char *strtok __PR((char *, const char *)); +extern void *memset __PR((void *, int, int)); +extern char *strerror __PR((int)); + +extern int strlen __PR((const char *)); +/*#pragma int_to_unsigned strlen*/ + +extern void *memccpy __PR((void *, const void *, int, int)); + +extern int strcasecmp __PR((const char *, const char *)); +extern int strncasecmp __PR((const char *, const char *, int)); + +/*#define index strchr*/ +/*#define rindex strrchr*/ + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_STRING_H */ + +#endif /* _STRDEFS_H */ diff --git a/src/schily/termcap.h b/src/schily/termcap.h new file mode 100644 index 0000000..957ca59 --- /dev/null +++ b/src/schily/termcap.h @@ -0,0 +1,62 @@ +/* @(#)termcap.h 1.6 03/06/15 Copyright 1995 J. Schilling */ +/* + * Copyright (c) 1995 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _TERMCAP_H +#define _TERMCAP_H + +#ifndef _MCONFIG_H +#include +#endif +#ifndef _PROTOTYP_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Flags for tcsetflags() + */ +#define TCF_NO_TC 0x0001 /* Don't follow tc= entries */ +#define TCF_NO_SIZE 0x0002 /* Don't get actual ttysize (li#/co#)*/ +#define TCF_NO_STRIP 0x0004 /* Don't strip down termcap buffer */ + +extern char PC; /* Pad character */ +extern char *BC; /* Backspace if not "\b" from "bc" capability*/ +extern char *UP; /* Cursor up string from "up" capability */ +extern short ospeed; /* output speed coded as in ioctl */ + +extern int tgetent __PR((char *bp, char *name)); +extern int tcsetflags __PR((int flags)); +extern char *tcgetbuf __PR((void)); +extern int tgetnum __PR((char *ent)); +extern BOOL tgetflag __PR((char *ent)); +extern char *tgetstr __PR((char *ent, char **array)); +extern char *tdecode __PR((char *ep, char **array)); + +extern int tputs __PR((char *cp, int affcnt, int (*outc)(int c))); +extern char *tgoto __PR((char *cm, int destcol, int destline)); + +#ifdef __cplusplus +} +#endif + +#endif /* _TERMCAP_H */ diff --git a/src/schily/timedefs.h b/src/schily/timedefs.h new file mode 100644 index 0000000..7e56197 --- /dev/null +++ b/src/schily/timedefs.h @@ -0,0 +1,101 @@ +/* @(#)timedefs.h 1.11 03/11/24 Copyright 1996 J. Schilling */ +/* + * Generic header for users of time(), gettimeofday() ... + * + * It includes definitions for time_t, struct timeval, ... + * + * Copyright (c) 1996 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _TIMEDEFS_H +#define _TIMEDEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifndef _INCL_SYS_TYPES_H +#include /* Needed for time_t */ +#define _INCL_SYS_TYPES_H +#endif + +#ifdef TIME_WITH_SYS_TIME +# ifndef _INCL_SYS_TIME_H +# include +# define _INCL_SYS_TIME_H +# endif +# ifndef _INCL_TIME_H +# include +# define _INCL_TIME_H +# endif +#else +#ifdef HAVE_SYS_TIME_H +# ifndef _INCL_SYS_TIME_H +# include +# define _INCL_SYS_TIME_H +# endif +#else +# ifndef _INCL_TIME_H +# include +# define _INCL_TIME_H +# endif +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__CYGWIN32__) || defined(__EMX__) || defined(__linux__) || defined(__DJGPP__) +/* + * Cygnus defines struct timeval in sys/time.h but not timerclear + * timerclear is defined in windows32/Sockets.h ??? + * + * EMX for OS/2 defines struct timeval in sys/time.h but not timerclear + * + * Linux defines struct timeval in sys/time.h but if __USE_BSD is not + * defined, timerclear is missing. + */ +#ifndef timerclear +#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 +#endif +#endif + +#ifndef timerclear + +#ifndef VMS +struct timeval { + long tv_sec; + long tv_usec; +}; +#endif + +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _TIMEDEFS_H */ diff --git a/src/schily/ttydefs.h b/src/schily/ttydefs.h new file mode 100644 index 0000000..9081523 --- /dev/null +++ b/src/schily/ttydefs.h @@ -0,0 +1,120 @@ +/* @(#)ttydefs.h 1.26 03/02/28 Copyright 1984-2003 J. Schilling */ +/* + * Terminal driver tty mode handling + * + * Copyright (c) 1984-2003 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifndef _TTYDEFS_H +#define _TTYDEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifndef _INCL_SYS_TYPES_H +#include +#define _INCL_SYS_TYPES_H +#endif + +#ifdef JOS +# include +# include +#else +#ifdef HAVE_TERMIOS_H +# include +# define _INCL_TERMIOS_H +# ifdef TIOCGETA /* FreeBSD */ +# define TCGETS TIOCGETA +# define TCSETSW TIOCSETAW +# endif +# ifdef TCGETATTR +# define TCGETS TCGETATTR +# define TCSETSW TCSETATTRD +# endif +#else +# ifdef HAVE_TERMIO_H +# include +# define _INCL_TERMIO_H +# ifndef TCGETS +# define termios termio +# define TCGETS TCGETA +# define TCSETSW TCSETAW +# endif +# else +# define USE_V7_TTY +# endif +#endif +#endif + +#if !defined(HAVE_TCGETATTR) || !defined(HAVE_TCSETATTR) +# undef TCSANOW +#endif + +#ifndef TCSANOW +# if !defined(TCGETS) || !defined(TCSETSW) +# define USE_V7_TTY +# endif +#endif + +#if !defined(_INCL_TERMIOS_H) && !defined(_INCL_TERMIO_H) +#ifdef HAVE_SYS_IOCTL_H +# ifndef _INCL_SYS_IOCTl_H +# include +# define _INCL_SYS_IOCTL_H +# endif +#endif +#endif + +#ifdef HAVE_SYS_BSDTTY_H +#include +#endif + +#if !defined(TIOCGWINSZ) && ! defined(TIOCGSIZE) +# ifndef _INCL_SYS_IOCTl_H +# include +# define _INCL_SYS_IOCTL_H +# endif +#endif + +#ifndef OXTABS /* OS/2 EMX */ +#define OXTABS 0 +#endif +#ifndef XTABS +# ifndef TAB3 /* FreeBSD */ +# define TABDLY OXTABS +# define XTABS OXTABS +# else +# define XTABS TAB3 +# endif +#endif +#ifndef ONLCR /* OS/2 EMX */ +#define ONLCR 0 +#endif +#ifndef OCRNL /* FreeBSD */ +# define OCRNL 0 +#endif +#ifndef ONLRET /* FreeBSD */ +# define ONLRET 0 +#endif +#ifndef _POSIX_VDISABLE +# define _POSIX_VDISABLE 0 +#endif + +#endif /* _TTYDEFS_H */ diff --git a/src/schily/unixstd.h b/src/schily/unixstd.h new file mode 100644 index 0000000..93cbc37 --- /dev/null +++ b/src/schily/unixstd.h @@ -0,0 +1,121 @@ +/* @(#)unixstd.h 1.12 04/06/17 Copyright 1996 J. Schilling */ +/* + * Definitions for unix system interface + * + * Copyright (c) 1996 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _UNIXSTD_H +#define _UNIXSTD_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifdef HAVE_UNISTD_H + +#ifndef _INCL_SYS_TYPES_H +#include +#define _INCL_SYS_TYPES_H +#endif +#ifndef _INCL_UNISTD_H +#include +#define _INCL_UNISTD_H +#endif + +#ifndef _SC_PAGESIZE +#ifdef _SC_PAGE_SIZE /* HP/UX & OSF */ +#define _SC_PAGESIZE _SC_PAGE_SIZE +#endif +#endif + +#else /* HAVE_UNISTD_H */ + +/* + * unistd.h grants things like off_t to be typedef'd. + */ +#ifndef _INCL_SYS_TYPES_H +#include +#define _INCL_SYS_TYPES_H +#endif + +#endif /* HAVE_UNISTD_H */ + +#ifndef STDIN_FILENO +# ifdef JOS +# ifndef _JOS_IO_H +# include +# endif +# else +# define STDIN_FILENO 0 +# define STDOUT_FILENO 1 +# define STDERR_FILENO 2 +# endif +#endif + +#ifndef R_OK +/* Symbolic constants for the "access" routine: */ +#define R_OK 4 /* Test for Read permission */ +#define W_OK 2 /* Test for Write permission */ +#define X_OK 1 /* Test for eXecute permission */ +#define F_OK 0 /* Test for existence of File */ +#endif +#ifndef E_OK +#ifdef HAVE_ACCESS_E_OK +#ifdef EFF_ONLY_OK +#define E_OK EFF_ONLY_OK /* Irix */ +#else +#ifdef EUID_OK +#define E_OK EUID_OK /* UNICOS (0400) */ +#else +#define E_OK 010 /* Test effective uids */ +#endif /* EUID_OK */ +#endif /* EFF_ONLY_OK */ +#else +#define E_OK 0 +#endif /* HAVE_ACCESS_E_OK */ +#endif /* !E_OK */ + +/* Symbolic constants for the "lseek" routine: */ +#ifndef SEEK_SET +#define SEEK_SET 0 /* Set file pointer to "offset" */ +#endif +#ifndef SEEK_CUR +#define SEEK_CUR 1 /* Set file pointer to current plus "offset" */ +#endif +#ifndef SEEK_END +#define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#if !defined(HAVE_UNISTD_H) || !defined(_POSIX_VERSION) +/* + * Maybe we need a lot more definitions here... + * It is not clear whether we should have prototyped definitions. + */ +extern int access __PR((const char *, int)); +extern int close __PR((int)); +extern int dup __PR((int)); +extern int dup2 __PR((int, int)); +extern void _exit __PR((int)); +extern int link __PR((const char *, const char *)); +extern int read __PR((int, void *, size_t)); +extern int unlink __PR((const char *)); +extern int write __PR((int, void *, size_t)); +#endif + +#endif /* _UNIXSTD_H */ diff --git a/src/schily/unls.h b/src/schily/unls.h new file mode 100644 index 0000000..3a6e611 --- /dev/null +++ b/src/schily/unls.h @@ -0,0 +1,76 @@ +/* @(#)unls.h 1.5 03/06/15 2000 J. Schilling */ +/* + * Modifications to make the code portable Copyright (c) 2000 J. Schilling + * + * Code taken from the Linux kernel. + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _UNLS_H +#define _UNLS_H + +#ifndef _MCONFIG_H +#include +#endif +#ifndef _PROTOTYP_H +#include +#endif + +#ifdef USE_ICONV +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct nls_unicode { + unsigned char uni1; + unsigned char uni2; +}; + +struct nls_table { + char *charset; + unsigned char **page_uni2charset; + struct nls_unicode *charset2uni; +#ifdef USE_ICONV + iconv_t iconv_d; +#endif + + void (*inc_use_count) __PR((void)); + void (*dec_use_count) __PR((void)); + struct nls_table *next; +}; + +extern int init_nls __PR((void)); +extern int register_nls __PR((struct nls_table *)); +extern int unregister_nls __PR((struct nls_table *)); +extern struct nls_table *find_nls __PR((char *)); +extern void list_nls __PR((void)); +extern struct nls_table *load_nls __PR((char *)); +extern void unload_nls __PR((struct nls_table *)); +extern struct nls_table *load_nls_default __PR((void)); +extern int init_nls_file __PR((char * name)); +#ifdef USE_ICONV +extern int init_nls_iconv __PR((char * name)); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _UNLS_H */ diff --git a/src/schily/unls.h.utf8 b/src/schily/unls.h.utf8 new file mode 100644 index 0000000..bb06500 --- /dev/null +++ b/src/schily/unls.h.utf8 @@ -0,0 +1,66 @@ +/* @(#)unls.h 1.5 03/06/15 2000 J. Schilling */ +/* + * Modifications to make the code portable Copyright (c) 2000 J. Schilling + * + * Code taken from the Linux kernel. + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _UNLS_H +#define _UNLS_H + +#ifndef _MCONFIG_H +#include +#endif +#ifndef _PROTOTYP_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct nls_unicode { + unsigned char uni1; + unsigned char uni2; +}; + +struct nls_table { + char *charset; + unsigned char **page_uni2charset; + struct nls_unicode *charset2uni; + + void (*inc_use_count) __PR((void)); + void (*dec_use_count) __PR((void)); + struct nls_table *next; +}; + +extern int init_nls __PR((void)); +extern int register_nls __PR((struct nls_table *)); +extern int unregister_nls __PR((struct nls_table *)); +extern struct nls_table *find_nls __PR((char *)); +extern void list_nls __PR((void)); +extern struct nls_table *load_nls __PR((char *)); +extern void unload_nls __PR((struct nls_table *)); +extern struct nls_table *load_nls_default __PR((void)); +extern int init_nls_file __PR((char * name)); + +#ifdef __cplusplus +} +#endif + +#endif /* _UNLS_H */ diff --git a/src/schily/utimdefs.h b/src/schily/utimdefs.h new file mode 100644 index 0000000..a90f011 --- /dev/null +++ b/src/schily/utimdefs.h @@ -0,0 +1,76 @@ +/* @(#)utimdefs.h 1.5 03/06/15 Copyright 2001 J. Schilling */ +/* + * Defines for utimes() / utime() + * + * Copyright (c) 2001 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _UTIMDEFS_H +#define _UTIMDEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifndef _INCL_SYS_TYPES_H +#include +#define _INCL_SYS_TYPES_H +#endif + +#ifdef HAVE_UTIMES +#ifndef _TIMEDEFS_H +#include +#endif +#endif + +#ifdef HAVE_UTIME_H +#ifndef _INCL_UTIME_H +#include +#define _INCL_UTIME_H +#endif +#else +#ifdef HAVE_SYS_UTIME_H +#ifndef _INCL_SYS_UTIME_H +#include +#define _INCL_SYS_UTIME_H +#endif +#else +struct utimbuf { + time_t actime; + time_t modtime; +}; +#endif +#endif + +#ifdef __comment__ +/* + * file.c contains this + * I am not sure if it is really needed. + * It may be a good idea to add a test for HAVE_STRUCT_UTIMBUF + * as in gnutar. + */ +#if (__COHERENT__ >= 0x420) +# include +#else +# include +#endif + +#endif /* __comment__ */ + + +#endif /* _UTIMDEFS_H */ diff --git a/src/schily/utypes.h b/src/schily/utypes.h new file mode 100644 index 0000000..b341b9c --- /dev/null +++ b/src/schily/utypes.h @@ -0,0 +1,339 @@ +/* @(#)utypes.h 1.11 03/06/15 Copyright 1997 J. Schilling */ +/* + * Definitions for some user defined types + * + * Copyright (c) 1997 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _UTYPES_H +#define _UTYPES_H + +#ifndef _MCONFIG_H +#include +#endif + +/* + * Include limits.h for CHAR_BIT + */ +#ifdef HAVE_LIMITS_H +#ifndef _INCL_LIMITS_H +#include +#define _INCL_LIMITS_H +#endif +#endif + +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif + +/* + * These macros may not work on all platforms but as we depend + * on two's complement in many places, they do not reduce portability. + */ +#define TYPE_ISSIGNED(t) (((t)-1) < ((t)0)) +#define TYPE_MSBVAL(t) ((t)(~((t)0) << (sizeof (t)*CHAR_BIT - 1))) +#define TYPE_MINVAL(t) (TYPE_ISSIGNED(t) \ + ? TYPE_MSBVAL(t) \ + : ((t)0)) +#define TYPE_MAXVAL(t) ((t)(~((t)0) - TYPE_MINVAL(t))) + +/* + * Let us include system defined types too. + */ +#ifndef _INCL_SYS_TYPES_H +#include +#define _INCL_SYS_TYPES_H +#endif + +#ifdef __CHAR_UNSIGNED__ /* GNU GCC define (dynamic) */ +#ifndef CHAR_IS_UNSIGNED +#define CHAR_IS_UNSIGNED /* Sing Schily define (static) */ +#endif +#endif + +/* + * Several unsigned cardinal types + */ +typedef unsigned long Ulong; +typedef unsigned int Uint; +typedef unsigned short Ushort; +typedef unsigned char Uchar; + +/* + * This is a definition for a compiler dependant 64 bit type. + * It currently is silently a long if the compiler does not + * support it. Check if this is the right way. + */ +#ifndef NO_LONGLONG +# if defined(HAVE_LONGLONG) +# define USE_LONGLONG +# endif +#endif + +#ifdef USE_LONGLONG + +typedef long long Llong; +typedef unsigned long long Ullong; + +#define SIZEOF_LLONG SIZEOF_LONG_LONG +#define SIZEOF_ULLONG SIZEOF_UNSIGNED_LONG_LONG + +#else + +typedef long Llong; +typedef unsigned long Ullong; + +#define SIZEOF_LLONG SIZEOF_LONG +#define SIZEOF_ULLONG SIZEOF_UNSIGNED_LONG + +#endif + +/* + * The IBM AIX C-compiler seems to be the only compiler on the world + * which does not allow to use unsigned char bit fields as a hint + * for packed bit fields. Define a pesical type to avoid warnings. + * The packed attribute is honored wit unsigned int in this case too. + */ +#if defined(_AIX) && !defined(__GNUC__) + +typedef unsigned int Ucbit; + +#else + +typedef unsigned char Ucbit; + +#endif + +/* + * Start inttypes.h emulation. + * + * Thanks to Solaris 2.4 and even recent 1999 Linux versions, we + * cannot use the official UNIX-98 names here. Old Solaris versions + * define parts of the types in some exotic include files. + * Linux even defines incompatible types in . + */ + +#ifdef HAVE_INTTYPES_H +# ifndef _INCL_INTTYPES_H +# include +# define _INCL_INTTYPES_H +# endif +# define HAVE_INT64_T +# define HAVE_UINT64_T + +#define Int8_t int8_t +#define Int16_t int16_t +#define Int32_t int32_t +#define Int64_t int64_t +#define Intmax_t intmax_t +#define UInt8_t uint8_t +#define UInt16_t uint16_t +#define UInt32_t uint32_t +#define UInt64_t uint64_t +#define UIntmax_t uintmax_t + +#define Intptr_t intptr_t +#define UIntptr_t uintptr_t + +#else /* !HAVE_INTTYPES_H */ + +#if SIZEOF_CHAR != 1 || SIZEOF_UNSIGNED_CHAR != 1 +/* + * #error will not work for all compilers (e.g. sunos4) + * The following line will abort compilation on all compilers + * if the above is true. And that's what we want. + */ +error Sizeof char is not equal 1 +#endif + +#if defined(__STDC__) || defined(CHAR_IS_UNSIGNED) + typedef signed char Int8_t; +#else + typedef char Int8_t; +#endif + +#if SIZEOF_SHORT_INT == 2 + typedef short Int16_t; +#else + error No int16_t found +#endif + +#if SIZEOF_INT == 4 + typedef int Int32_t; +#else + error No int32_t found +#endif + +#if SIZEOF_LONG_INT == 8 + typedef long Int64_t; +# define HAVE_INT64_T +#else +#if SIZEOF_LONG_LONG == 8 + typedef long long Int64_t; +# define HAVE_INT64_T +#else +/* error No int64_t found*/ +#endif +#endif + +#if SIZEOF_CHAR_P == SIZEOF_INT + typedef int Intptr_t; +#else +#if SIZEOF_CHAR_P == SIZEOF_LONG_INT + typedef long Intptr_t; +#else + error No intptr_t found +#endif +#endif + +typedef unsigned char UInt8_t; + +#if SIZEOF_UNSIGNED_SHORT_INT == 2 + typedef unsigned short UInt16_t; +#else + error No uint16_t found +#endif + +#if SIZEOF_UNSIGNED_INT == 4 + typedef unsigned int UInt32_t; +#else + error No int32_t found +#endif + +#if SIZEOF_UNSIGNED_LONG_INT == 8 + typedef unsigned long UInt64_t; +# define HAVE_UINT64_T +#else +#if SIZEOF_UNSIGNED_LONG_LONG == 8 + typedef unsigned long long UInt64_t; +# define HAVE_UINT64_T +#else +/* error No uint64_t found*/ +#endif +#endif + +#define Intmax_t Llong +#define UIntmax_t Ullong + +#if SIZEOF_CHAR_P == SIZEOF_UNSIGNED_INT + typedef unsigned int UIntptr_t; +#else +#if SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG_INT + typedef unsigned long UIntptr_t; +#else + error No uintptr_t found +#endif +#endif + +#endif /* HAVE_INTTYPES_H */ + +#ifndef CHAR_MIN +#define CHAR_MIN TYPE_MINVAL(char) +#endif +#ifndef CHAR_MAX +#define CHAR_MAX TYPE_MAXVAL(char) +#endif +#ifndef UCHAR_MAX +#define UCHAR_MAX TYPE_MAXVAL(unsigned char) +#endif + +#ifndef SHRT_MIN +#define SHRT_MIN TYPE_MINVAL(short) +#endif +#ifndef SHRT_MAX +#define SHRT_MAX TYPE_MAXVAL(short) +#endif +#ifndef USHRT_MAX +#define USHRT_MAX TYPE_MAXVAL(unsigned short) +#endif + +#ifndef INT_MIN +#define INT_MIN TYPE_MINVAL(int) +#endif +#ifndef INT_MAX +#define INT_MAX TYPE_MAXVAL(int) +#endif +#ifndef UINT_MAX +#define UINT_MAX TYPE_MAXVAL(unsigned int) +#endif + +#ifndef LONG_MIN +#define LONG_MIN TYPE_MINVAL(long) +#endif +#ifndef LONG_MAX +#define LONG_MAX TYPE_MAXVAL(long) +#endif +#ifndef ULONG_MAX +#define ULONG_MAX TYPE_MAXVAL(unsigned long) +#endif + +#ifndef INT8_MIN +#define INT8_MIN TYPE_MINVAL(Int8_t) +#endif +#ifndef INT8_MAX +#define INT8_MAX TYPE_MAXVAL(Int8_t) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX TYPE_MAXVAL(UInt8_t) +#endif + +#ifndef INT16_MIN +#define INT16_MIN TYPE_MINVAL(Int16_t) +#endif +#ifndef INT16_MAX +#define INT16_MAX TYPE_MAXVAL(Int16_t) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX TYPE_MAXVAL(UInt16_t) +#endif + +#ifndef INT32_MIN +#define INT32_MIN TYPE_MINVAL(Int32_t) +#endif +#ifndef INT32_MAX +#define INT32_MAX TYPE_MAXVAL(Int32_t) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX TYPE_MAXVAL(UInt32_t) +#endif + +#ifdef HAVE_INT64_T +#ifndef INT64_MIN +#define INT64_MIN TYPE_MINVAL(Int64_t) +#endif +#ifndef INT64_MAX +#define INT64_MAX TYPE_MAXVAL(Int64_t) +#endif +#endif +#ifdef HAVE_UINT64_T +#ifndef UINT64_MAX +#define UINT64_MAX TYPE_MAXVAL(UInt64_t) +#endif +#endif + +#ifndef INTMAX_MIN +#define INTMAX_MIN TYPE_MINVAL(Intmax_t) +#endif +#ifndef INTMAX_MAX +#define INTMAX_MAX TYPE_MAXVAL(Intmax_t) +#endif +#ifndef UINTMAX_MAX +#define UINTMAX_MAX TYPE_MAXVAL(UIntmax_t) +#endif + +#endif /* _UTYPES_H */ diff --git a/src/schily/vadefs.h b/src/schily/vadefs.h new file mode 100644 index 0000000..9b26fa2 --- /dev/null +++ b/src/schily/vadefs.h @@ -0,0 +1,120 @@ +/* @(#)vadefs.h 1.5 01/07/15 Copyright 1998 J. Schilling */ +/* + * Generic header for users of var args ... + * + * Includes a default definition for va_copy() + * and some magic know how about the SVr4 Power PC var args ABI + * to create a __va_arg_list() macro. + * + * Copyright (c) 1998 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _VADEFS_H +#define _VADEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifdef PROTOTYPES +/* + * For ANSI C-compilers prefer stdarg.h + */ +# ifdef HAVE_STDARG_H +# ifndef _INCL_STDARG_H +# include +# define _INCL_STDARG_H +# endif +# else +# ifndef _INCL_VARARGS_H +# include +# define _INCL_VARARGS_H +# endif +# endif +#else +/* + * For K&R C-compilers prefer varargs.h + */ +# ifdef HAVE_VARARGS_H +# ifndef _INCL_VARARGS_H +# include +# define _INCL_VARARGS_H +# endif +# else +# ifndef _INCL_STDARG_H +# include +# define _INCL_STDARG_H +# endif +# endif +#endif + +#if (defined(__linux__) || defined(__linux) || defined(sun)) && \ + (defined(__ppc) || defined(__PPC) || defined(powerpc) || defined(__powerpc__)) + +# ifndef VA_LIST_IS_ARRAY +# define VA_LIST_IS_ARRAY +# endif +#endif + + +/* + * __va_copy() is used by GCC 2.8 or newer until va_copy() becomes + * a final ISO standard. + */ +#if !defined(va_copy) && !defined(HAVE_VA_COPY) +# if defined(__va_copy) +# define va_copy(to, from) __va_copy(to, from) +# endif +#endif + +/* + * va_copy() is a Solaris extension to provide a portable way to perform a + * variable argument list "bookmarking" function. + * If it is not available via stdarg.h, use a simple assignement for backward + * compatibility. + */ +#if !defined(va_copy) && !defined(HAVE_VA_COPY) +#ifdef VA_LIST_IS_ARRAY +# define va_copy(to, from) ((to)[0] = (from)[0]) +#else +# define va_copy(to, from) ((to) = (from)) +#endif +#endif + +/* + * I don't know any portable way to get an arbitrary + * C object from a var arg list so I use a + * system-specific routine __va_arg_list() that knows + * if 'va_list' is an array. You will not be able to + * assign the value of __va_arg_list() but it works + * to be used as an argument of a function. + * It is a requirement for recursive printf to be able + * to use this function argument. If your system + * defines va_list to be an array you need to know this + * via autoconf or another mechanism. + * It would be nice to have something like + * __va_arg_list() in stdarg.h + */ + +#ifdef VA_LIST_IS_ARRAY +# define __va_arg_list(list) va_arg(list, void *) +#else +# define __va_arg_list(list) va_arg(list, va_list) +#endif + +#endif /* _VADEFS_H */ diff --git a/src/schily/waitdefs.h b/src/schily/waitdefs.h new file mode 100644 index 0000000..bba1115 --- /dev/null +++ b/src/schily/waitdefs.h @@ -0,0 +1,141 @@ +/* @(#)waitdefs.h 1.10 03/02/25 Copyright 1995-2003 J. Schilling */ +/* + * Definitions to deal with various kinds of wait flavour + * + * Copyright (c) 1995-2003 J. Schilling + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _WAITDEFS_H +#define _WAITDEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +/* + * Needed for SysVr4 + */ +#ifndef _INCL_SYS_TYPES_H +#include +#define _INCL_SYS_TYPES_H +#endif + +#if defined(HAVE_WAIT_H) +# ifndef _INCL_WAIT_H +# include +# define _INCL_WAIT_H +# endif +#else +/* + * K&R Compiler doesn't like #elif + */ +# if defined(HAVE_SYS_WAIT_H) /* POSIX.1 compl. sys/wait.h */ +# undef HAVE_UNION_WAIT /* POSIX.1 doesn't use U_W */ +# ifndef _INCL_SYS_WAIT_H +# include +# define _INCL_SYS_WAIT_H +# endif +# else +# if defined(HAVE_UNION_WAIT) /* Pure BSD U_W / sys/wait.h */ +# ifndef _INCL_SYS_WAIT_H +# include +# define _INCL_SYS_WAIT_H +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_UNION_WAIT +# define WAIT_T union wait +# ifndef WSTOPPED +# define WSTOPPED 0x7F +# endif +# ifndef WTERMSIG +# define WTERMSIG(status) ((status).w_termsig) +# endif +# ifndef WCOREDUMP +# define WCOREDUMP(status) ((status).w_coredump) +# endif +# ifndef WEXITSTATUS +# define WEXITSTATUS(status) ((status).w_retcode) +# endif +# ifndef WSTOPSIG +# define WSTOPSIG(status) ((status).w_stopsig) +# endif +# ifndef WIFSTOPPED +# define WIFSTOPPED(status) ((status).w_stopval == \ + WSTOPPED) +# endif +# ifndef WIFSIGNALED +# define WIFSIGNALED(status) ((status).w_stopval != \ + WSTOPPED && \ + (status).w_termsig != 0) +# endif +# ifndef WIFEXITED +# define WIFEXITED(status) ((status).w_stopval != \ + WSTOPPED && \ + (status).w_termsig == 0) +# endif +#else +# define WAIT_T int +# ifndef WTERMSIG +# define WTERMSIG(status) ((status) & 0x7F) +# endif +# ifndef WCOREDUMP +# define WCOREDUMP(status) ((status) & 0x80) +# endif +# ifndef WEXITSTATUS +# define WEXITSTATUS(status) (((status) >> 8) & 0xFF) +# endif +# ifndef WSTOPSIG +# define WSTOPSIG(status) (((status) >> 8) & 0xFF) +# endif +# ifndef WIFSTOPPED +# define WIFSTOPPED(status) (((status) & 0xFF) == 0x7F) +# endif +# ifndef WIFSIGNALED +# define WIFSIGNALED(status) (((status) & 0xFF) != 0x7F && \ + WTERMSIG(status) != 0) +# endif +# ifndef WIFEXITED +# define WIFEXITED(status) (((status) & 0xFF) == 0) +# endif +#endif + + +#ifndef WCOREFLG +#define WCOREFLG 0x80 +#endif + +#ifndef WSTOPFLG +#define WSTOPFLG 0x7F +#endif + +#ifndef WCONTFLG +#define WCONTFLG 0xFFFF +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _WAITDEFS_H */ diff --git a/src/schily/xconfig.h b/src/schily/xconfig.h new file mode 100644 index 0000000..eaa2b79 --- /dev/null +++ b/src/schily/xconfig.h @@ -0,0 +1,550 @@ +/* xconfig.h. Generated automatically by configure. */ +/* @(#)xconfig.h.in 1.76 04/07/26 Copyright 1998-2003 J. Schilling */ +/* + * Dynamic autoconf C-include code. + * + * Copyright (c) 1998-2003 J. Schilling + */ + +/* + * Header Files + */ +#define PROTOTYPES 1 /* if Compiler supports ANSI C prototypes */ +#define HAVE_STDARG_H 1 /* to use stdarg.h, else use varargs.h NOTE: SaberC on a Sun has prototypes but no stdarg.h */ +/* #undef HAVE_VARARGS_H */ /* to use use varargs.h NOTE: The free HP-UX C-compiler has stdarg.h but no PROTOTYPES */ +#define HAVE_STDLIB_H 1 /* to use general utility defines (malloc(), size_t ...) and general C library prototypes */ +#define HAVE_STDDEF_H 1 /* to use offsetof(), ptrdiff_t, wchar>t, size_t */ +#define HAVE_STRING_H 1 /* to get NULL and ANSI C string function prototypes */ +#define HAVE_STRINGS_H 1 /* to get BSD string function prototypes */ +#define STDC_HEADERS 1 /* if ANSI compliant stdlib.h, stdarg.h, string.h, float.h are present */ +#define HAVE_UNISTD_H 1 /* to get POSIX syscall prototypes XXX sys/file.h fcntl.h (unixstd/fctl)XXX*/ +#define HAVE_GETOPT_H 1 /* to get getopt() prototype from getopt.h instead of unistd.h */ +#define HAVE_LIMITS_H 1 /* to get POSIX numeric limits constants */ +#define HAVE_A_OUT_H 1 /* if a.out.h is present (may be a system using a.out format) */ +/* #undef HAVE_AOUTHDR_H */ /* if aouthdr.h is present. This is a COFF system */ +#define HAVE_ELF_H 1 /* if elf.h is present. This is an ELF system */ +#define HAVE_FCNTL_H 1 /* to access, O_XXX constants for open(), otherwise use sys/file.h */ +#define HAVE_SYS_FILE_H 1 /* to use O_XXX constants for open() and flock() defs */ +#define HAVE_INTTYPES_H 1 /* to use UNIX-98 inttypes.h */ +#define HAVE_DIRENT_H 1 /* to use POSIX dirent.h */ +/* #undef HAVE_SYS_DIR_H */ /* to use BSD sys/dir.h */ +/* #undef HAVE_NDIR_H */ /* to use ndir.h */ +/* #undef HAVE_SYS_NDIR_H */ /* to use sys/ndir.h */ +#define HAVE_ALLOCA_H 1 /* if alloca.h exists */ +#define HAVE_MALLOC_H 1 /* if malloc.h exists */ +#define HAVE_TERMIOS_H 1 /* to use POSIX termios.h */ +#define HAVE_TERMIO_H 1 /* to use SVR4 termio.h */ +#define HAVE_PWD_H 1 /* if pwd.h exists */ +#define HAVE_GRP_H 1 /* if grp.h exists */ +#define HAVE_SYS_ACL_H 1 /* to use for ACL definitions */ +/* #undef HAVE_ACLLIB_H */ /* if HP-UX is present */ +#define HAVE_SHADOW_H 1 /* if shadow.h exists */ +#define HAVE_SYSLOG_H 1 /* if syslog.h exists */ +#define HAVE_SYS_TIME_H 1 /* may include sys/time.h for struct timeval */ +#define TIME_WITH_SYS_TIME 1 /* may include both time.h and sys/time.h */ +#define HAVE_TIMES 1 /* to use times() and sys/times.h */ +#define HAVE_SYS_TIMES_H 1 /* may include sys/times.h for struct tms */ +#define HAVE_UTIME 1 /* to use AT&T utime() and utimbuf */ +#define HAVE_UTIMES 1 /* to use BSD utimes() and sys/time.h */ +#define HAVE_UTIME_H 1 /* to use utime.h for the utimbuf structure declaration, else declare struct utimbuf yourself */ +/* #undef HAVE_SYS_UTIME_H */ /* to use sys/utime.h if utime.h does not exist */ +#define HAVE_SYS_IOCTL_H 1 /* if sys/ioctl.h is present */ +/* #undef HAVE_SYS_FILIO_H */ /* if sys/ioctl.h is present */ +#define HAVE_SYS_PARAM_H 1 /* if sys/param.h is present */ +#define HAVE_MNTENT_H 1 /* if mntent.h is present */ +/* #undef HAVE_SYS_MNTENT_H */ /* if sys/mntent.h is present */ +/* #undef HAVE_SYS_MNTTAB_H */ /* if sys/mnttab.h is present */ +#define HAVE_SYS_MOUNT_H 1 /* if sys/mount.h is present */ +#define HAVE_WAIT_H 1 /* to use wait.h for prototypes and union wait */ +#define HAVE_SYS_WAIT_H 1 /* else use sys/wait.h */ +#define HAVE_SYS_RESOURCE_H 1 /* to use sys/resource.h for rlimit() and wait3() */ +#define HAVE_SYS_PROCFS_H 1 /* to use sys/procfs.h for wait3() emulation */ +/* #undef HAVE_SYS_SYSTEMINFO_H */ /* to use SVr4 sysinfo() */ +#define HAVE_SYS_UTSNAME_H 1 /* to use uname() */ +/* #undef HAVE_SYS_PRIOCNTL_H */ /* to use SVr4 priocntl() instead of nice()/setpriority() */ +/* #undef HAVE_SYS_RTPRIOCNTL_H */ /* if the system supports SVr4 real time classes */ +#define HAVE_SYS_SYSCALL_H 1 /* to use syscall() */ +#define HAVE_SYS_MTIO_H 1 /* to use mtio definitions from sys/mtio.h */ +/* #undef HAVE_SYS_TAPE_H */ /* to use mtio definitions from AIX sys/tape.h */ +#define HAVE_SYS_MMAN_H 1 /* to use definitions for mmap()/madvise()... from sys/mman.h */ +#define HAVE_SYS_SHM_H 1 /* to use definitions for shmget() ... from sys/shm.h */ +#define HAVE_SYS_IPC_H 1 /* to use definitions for shmget() ... from sys/ipc.h */ +/* #undef MAJOR_IN_MKDEV */ /* if we should include sys/mkdev.h to get major()/minor()/makedev() */ +#define MAJOR_IN_SYSMACROS 1 /* if we should include sys/sysmacros.h to get major()/minor()/makedev() */ +/* #undef HAVE_SYS_DKIO_H */ /* if we may include sys/dkio.h for disk ioctls */ +/* #undef HAVE_SYS_DKLABEL_H */ /* if we may include sys/dklabel.h for disk label */ +/* #undef HAVE_SUN_DKIO_H */ /* if we may include sun/dkio.h for disk ioctls */ +/* #undef HAVE_SUN_DKLABEL_H */ /* if we may include sun/dklabel.h for disk label */ +#define HAVE_SYS_TYPES_H 1 /* if we may include sys/types.h (the standard) */ +#define HAVE_SYS_STAT_H 1 /* if we may include sys/stat.h (the standard) */ +/* #undef HAVE_TYPES_H */ /* if we may include types.h (rare cases e.g. ATARI TOS) */ +/* #undef HAVE_STAT_H */ /* if we may include stat.h (rare cases e.g. ATARI TOS) */ +#define HAVE_POLL_H 1 /* if we may include poll.h to use poll() */ +#define HAVE_SYS_POLL_H 1 /* if we may include sys/poll.h to use poll() */ +#define HAVE_SYS_SELECT_H 1 /* if we may have sys/select.h nonstandard use for select() on some systems*/ +/* #undef NEED_SYS_SELECT_H */ /* if we need sys/select.h to use select() (this is nonstandard) */ +#define HAVE_NETDB_H 1 /* if we have netdb.h for get*by*() and rcmd() */ +#define HAVE_SYS_SOCKET_H 1 /* if we have sys/socket.h for socket() */ +/* #undef NEED_SYS_SOCKET_H */ /* if we need sys/socket.h to use select() (this is nonstandard) */ +#define HAVE_LINUX_PG_H 1 /* if we may include linux/pg.h for PP ATAPI sypport */ +/* #undef HAVE_CAMLIB_H */ /* if we may include camlib.h for CAM SCSI transport definitions */ +/* #undef HAVE_IEEEFP_H */ /* if we may include ieeefp.h for finite()/isnand() */ +/* #undef HAVE_FP_H */ /* if we may include fp.h for FINITE()/IS_INF()/IS_NAN() */ +#define HAVE_VALUES_H 1 /* if we may include values.h for MAXFLOAT */ +#define HAVE_FLOAT_H 1 /* if we may include float.h for FLT_MAX */ +/* #undef HAVE__FILBUF */ /* if we have _filbuf() for USG derived STDIO */ +/* #undef HAVE___FILBUF */ /* if we have __filbuf() for USG derived STDIO */ +/* #undef HAVE_USG_STDIO */ /* if we have USG derived STDIO */ +#define HAVE_ERRNO_DEF 1 /* if we have errno definition in */ +/* #undef HAVE_VFORK_H */ /* if we should include vfork.h for vfork() definitions */ +#define HAVE_ARPA_INET_H 1 /* if we have arpa/inet.h (missing on BeOS) */ + /* BeOS has inet_ntoa() in */ +/* #undef HAVE_BSD_DEV_SCSIREG_H */ /* if we have a NeXT Step compatible sg driver */ +/* #undef HAVE_SYS_BSDTTY_H */ /* if we have sys/bsdtty.h on HP-UX for TIOCGPGRP */ +/* #undef HAVE_OS_H */ /* if we have the BeOS kernel definitions in OS.h */ +#define HAVE_ATTR_XATTR_H 1 /* if we have the Linux Extended File Attr definitions in attr/xattr.h */ +#define HAVE_FNMATCH_H 1 /* if we may include fnmatch.h */ + +/* + * Convert to SCHILY name + */ +#ifdef STDC_HEADERS +# ifndef HAVE_STDC_HEADERS +# define HAVE_STDC_HEADERS +# endif +#endif + +#ifdef HAVE_ELF_H +#define HAVE_ELF /* This system uses ELF */ +#else +# ifdef HAVE_AOUTHDR_H +# define HAVE_COFF /* This system uses COFF */ +# else +# ifdef HAVE_A_OUT_H +# define HAVE_AOUT /* This system uses AOUT */ +# endif +# endif +#endif + +/* + * Library Functions + */ +#define HAVE_ACCESS 1 /* access() is present in libc */ +/* #undef HAVE_EACCESS */ /* eaccess() is present in libc */ +#define HAVE_EUIDACCESS 1 /* euidaccess() is present in libc */ +/* #undef HAVE_ACCESS_E_OK */ /* access() implements E_OK (010) for effective UIDs */ +#define HAVE_CRYPT 1 /* crypt() is present in libc or libcrypt */ +#define HAVE_STRERROR 1 /* strerror() is present in libc */ +#define HAVE_MEMMOVE 1 /* memmove() is present in libc */ +#define HAVE_MADVISE 1 /* madvise() is present in libc */ +#define HAVE_MLOCK 1 /* mlock() is present in libc */ +#define HAVE_MLOCKALL 1 /* working mlockall() is present in libc */ +#define HAVE_MMAP 1 /* working mmap() is present in libc */ +/* #undef _MMAP_WITH_SIZEP */ /* mmap() needs address of size parameter */ +#define HAVE_FLOCK 1 /* *BSD flock() is present in libc */ +#define HAVE_LOCKF 1 /* lockf() is present in libc (XOPEN) */ +#define HAVE_FCNTL_LOCKF 1 /* file locking via fcntl() is present in libc */ +#define HAVE_FCHDIR 1 /* fchdir() is present in libc */ +#define HAVE_STATVFS 1 /* statvfs() is present in libc */ +#define HAVE_QUOTACTL 1 /* quotactl() is present in libc */ +/* #undef HAVE_QUOTAIOCTL */ /* use ioctl(f, Q_QUOTACTL, &q) instead of quotactl() */ +#define HAVE_SETREUID 1 /* setreuid() is present in libc */ +#define HAVE_SETRESUID 1 /* setresuid() is present in libc */ +#define HAVE_SETEUID 1 /* seteuid() is present in libc */ +#define HAVE_SETUID 1 /* setuid() is present in libc */ +#define HAVE_SETREGID 1 /* setregid() is present in libc */ +#define HAVE_SETRESGID 1 /* setresgid() is present in libc */ +#define HAVE_SETEGID 1 /* setegid() is present in libc */ +#define HAVE_SETGID 1 /* setgid() is present in libc */ +#define HAVE_GETPGID 1 /* getpgid() is present in libc (POSIX) */ +#define HAVE_SETPGID 1 /* setpgid() is present in libc (POSIX) */ +#define HAVE_GETPGRP 1 /* getpgrp() is present in libc (ANY) */ +#define HAVE_SETPGRP 1 /* setpgrp() is present in libc (ANY) */ +/* #undef HAVE_BSD_GETPGRP */ /* getpgrp() in libc is BSD-4.2 compliant */ +/* #undef HAVE_BSD_SETPGRP */ /* setpgrp() in libc is BSD-4.2 compliant */ +#define HAVE_GETSPNAM 1 /* getspnam() in libc (SVR4 compliant) */ +/* #undef HAVE_GETSPWNAM */ /* getspwnam() in libsec.a (HP-UX) */ +#define HAVE_SYNC 1 /* sync() is present in libc */ +#define HAVE_FSYNC 1 /* fsync() is present in libc */ +#define HAVE_TCGETATTR 1 /* tcgetattr() is present in libc */ +#define HAVE_TCSETATTR 1 /* tcsetattr() is present in libc */ +#define HAVE_WAIT3 1 /* working wait3() is present in libc */ +#define HAVE_WAIT4 1 /* wait4() is present in libc */ +#define HAVE_WAITID 1 /* waitid() is present in libc */ +#define HAVE_WAITPID 1 /* waitpid() is present in libc */ +#define HAVE_GETHOSTID 1 /* gethostid() is present in libc */ +#define HAVE_GETHOSTNAME 1 /* gethostname() is present in libc */ +#define HAVE_GETDOMAINNAME 1 /* getdomainname() is present in libc */ +#define HAVE_GETPAGESIZE 1 /* getpagesize() is present in libc */ +#define HAVE_GETDTABLESIZE 1 /* getdtablesize() is present in libc */ +#define HAVE_GETRUSAGE 1 /* getrusage() is present in libc */ +#define HAVE_GETRLIMIT 1 /* getrlimit() is present in libc */ +#define HAVE_SETRLIMIT 1 /* setrlimit() is present in libc */ +#define HAVE_ULIMIT 1 /* ulimit() is present in libc */ +#define HAVE_GETTIMEOFDAY 1 /* gettimeofday() is present in libc */ +#define HAVE_SETTIMEOFDAY 1 /* settimeofday() is present in libc */ +#define HAVE_TIME 1 /* time() is present in libc */ +#define HAVE_STIME 1 /* stime() is present in libc */ +#define HAVE_POLL 1 /* poll() is present in libc */ +#define HAVE_SELECT 1 /* select() is present in libc */ +#define HAVE_CHOWN 1 /* chown() is present in libc */ +#define HAVE_LCHOWN 1 /* lchown() is present in libc */ +#define HAVE_BRK 1 /* brk() is present in libc */ +#define HAVE_SBRK 1 /* sbrk() is present in libc */ +#define HAVE_VA_COPY 1 /* va_copy() is present in varargs.h/stdarg.h */ +#define HAVE__VA_COPY 1 /* __va_copy() is present in varargs.h/stdarg.h */ +/* #undef HAVE_DTOA */ /* BSD-4.4 __dtoa() is present in libc */ +/* #undef HAVE_DTOA_R */ /* BSD-4.4 __dtoa() with result ptr (reentrant) */ +#define HAVE_DUP2 1 /* dup2() is present in libc */ +#define HAVE_GETCWD 1 /* POSIX getcwd() is present in libc */ +#define HAVE_SMMAP 1 /* may map anonymous memory to get shared mem */ +#define HAVE_SHMAT 1 /* shmat() is present in libc */ +#define HAVE_SEMGET 1 /* semget() is present in libc */ +#define HAVE_LSTAT 1 /* lstat() is present in libc */ +#define HAVE_READLINK 1 /* readlink() is present in libc */ +#define HAVE_SYMLINK 1 /* symlink() is present in libc */ +#define HAVE_LINK 1 /* link() is present in libc */ +#define HAVE_HARD_SYMLINKS 1 /* link() allows hard links on symlinks */ +#define HAVE_LINK_NOFOLLOW 1 /* link() does not follow symlinks when hard linking symlinks */ +#define HAVE_RENAME 1 /* rename() is present in libc */ +#define HAVE_MKFIFO 1 /* mkfifo() is present in libc */ +#define HAVE_MKNOD 1 /* mknod() is present in libc */ +#define HAVE_ECVT 1 /* ecvt() is present in libc */ +#define HAVE_FCVT 1 /* fcvt() is present in libc */ +#define HAVE_GCVT 1 /* gcvt() is present in libc */ +#define HAVE_ECVT_R 1 /* ecvt_r() is present in libc */ +#define HAVE_FCVT_R 1 /* fcvt_r() is present in libc */ +/* #undef HAVE_GCVT_R */ /* gcvt_r() is present in libc */ +/* #undef HAVE_ECONVERT */ /* econvert() is present in libc */ +/* #undef HAVE_FCONVERT */ /* fconvert() is present in libc */ +/* #undef HAVE_GCONVERT */ /* gconvert() is present in libc */ +#define HAVE_ISINF 1 /* isinf() is present in libc */ +#define HAVE_ISNAN 1 /* isnan() is present in libc */ +#define HAVE_RAND 1 /* rand() is present in libc */ +#define HAVE_DRAND48 1 /* drand48() is present in libc */ +#define HAVE_SETPRIORITY 1 /* setpriority() is present in libc */ +#define HAVE_NICE 1 /* nice() is present in libc */ +/* #undef HAVE_DOSSETPRIORITY */ /* DosSetPriority() is present in libc */ +/* #undef HAVE_DOSALLOCSHAREDMEM */ /* DosAllocSharedMem() is present in libc */ +#define HAVE_SEEKDIR 1 /* seekdir() is present in libc */ +#define HAVE_PUTENV 1 /* putenv() is present in libc (preferred function) */ +#define HAVE_SETENV 1 /* setenv() is present in libc (use instead of putenv()) */ +#define HAVE_UNAME 1 /* uname() is present in libc */ +#define HAVE_SNPRINTF 1 /* snprintf() is present in libc */ +#define HAVE_STRCASECMP 1 /* strcasecmp() is present in libc */ +#define HAVE_STRDUP 1 /* strdup() is present in libc */ +#define HAVE_STRSIGNAL 1 /* strsignal() is present in libc */ +/* #undef HAVE_STR2SIG */ /* str2sig() is present in libc */ +/* #undef HAVE_SIG2STR */ /* sig2str() is present in libc */ +#define HAVE_KILLPG 1 /* killpg() is present in libc */ +#define HAVE_SIGRELSE 1 /* sigrelse() is present in libc */ +#define HAVE_SIGPROCMASK 1 /* sigprocmask() is present in libc (POSIX) */ +#define HAVE_SIGSETMASK 1 /* sigsetmask() is present in libc (BSD) */ +#define HAVE_SIGSET 1 /* sigset() is present in libc (POSIX) */ +#define HAVE_SYS_SIGLIST 1 /* char *sys_siglist[] is present in libc */ +#define HAVE_NANOSLEEP 1 /* nanosleep() is present in libc */ +#define HAVE_USLEEP 1 /* usleep() is present in libc */ +#define HAVE_FORK 1 /* fork() is present in libc */ +#define HAVE_EXECL 1 /* execl() is present in libc */ +#define HAVE_EXECLE 1 /* execle() is present in libc */ +#define HAVE_EXECLP 1 /* execlp() is present in libc */ +#define HAVE_EXECV 1 /* execv() is present in libc */ +#define HAVE_EXECVE 1 /* execve() is present in libc */ +#define HAVE_EXECVP 1 /* execvp() is present in libc */ +#define HAVE_ALLOCA 1 /* alloca() is present (else use malloc())*/ +#define HAVE_VALLOC 1 /* valloc() is present in libc (else use malloc())*/ +/* #undef vfork */ + +/* #undef HAVE_CHFLAGS */ /* chflags() is present in libc */ +/* #undef HAVE_FCHFLAGS */ /* fchflags() is present in libc */ +/* #undef HAVE_FFLAGSTOSTR */ /* fflagstostr() is present in libc */ +/* #undef HAVE_STRTOFFLAGS */ /* strtofflags() is present in libc */ + +#define HAVE_FNMATCH 1 /* fnmatch() is present in libc */ + +/* + * Linux Extended File Attributes + */ +#define HAVE_GETXATTR 1 /* getxattr() */ +#define HAVE_SETXATTR 1 /* setxattr() */ +#define HAVE_LISTXATTR 1 /* listxattr() */ + +/* + * Important: This must be a result from a check _before_ the Large File test + * has been run. It then tells us whether these functions are + * available even when not in Large File mode. + * + * Do not run the AC_FUNC_FSEEKO test from the GNU tar Large File test + * siute. It will use the same cache names and interfere with our test. + * Instead use the tests AC_SMALL_FSEEKO/AC_SMALL/STELLO and make sure + * they are placed before the large file tests. + */ +/* #undef HAVE_FSEEKO */ /* fseeko() is present in default compile mode */ +/* #undef HAVE_FTELLO */ /* ftello() is present in default compile mode */ + +#define HAVE_RCMD 1 /* rcmd() is present in libc/libsocket */ +#define HAVE_SOCKET 1 /* socket() is present in libc/libsocket */ +#define HAVE_SOCKETPAIR 1 /* socketpair() is present in libc/libsocket */ +#define HAVE_GETSERVBYNAME 1 /* getservbyname() is present in libc/libsocket */ +#define HAVE_INET_NTOA 1 /* inet_ntoa() is present in libc/libsocket */ +#define HAVE_GETADDRINFO 1 /* getaddrinfo() is present in libc/libsocket */ +#define HAVE_GETNAMEINFO 1 /* getnameinfo() is present in libc/libsocket */ + +#if defined(HAVE_QUOTACTL) || defined(HAVE_QUOTAIOCTL) +# define HAVE_QUOTA /* The system inludes quota */ +#endif + +/* + * We need to test for the include files too because Apollo Domain/OS has a + * libc that includes the functions but the includes files are not visible + * from the BSD compile environment. + */ +#if defined(HAVE_SHMAT) && defined(HAVE_SYS_SHM_H) && defined(HAVE_SYS_IPC_H) +# define HAVE_USGSHM /* USG shared memory is present */ +#endif +#if defined(HAVE_SEMGET) && defined(HAVE_SYS_SHM_H) && defined(HAVE_SYS_IPC_H) +# define HAVE_USGSEM /* USG semaphores are present */ +#endif + +#if defined(HAVE_GETPGRP) && !defined(HAVE_BSD_GETPGRP) +#define HAVE_POSIX_GETPGRP 1 /* getpgrp() in libc is POSIX compliant */ +#endif +#if defined(HAVE_SETPGRP) && !defined(HAVE_BSD_SETPGRP) +#define HAVE_POSIX_SETPGRP 1 /* setpgrp() in libc is POSIX compliant */ +#endif + +/* + * Structures + */ +#define HAVE_MTGET_TYPE 1 /* if struct mtget contains mt_type (drive type) */ +/* #undef HAVE_MTGET_MODEL */ /* if struct mtget contains mt_model (drive type) */ +#define HAVE_MTGET_DSREG 1 /* if struct mtget contains mt_dsreg (drive status) */ +/* #undef HAVE_MTGET_DSREG1 */ /* if struct mtget contains mt_dsreg1 (drive status msb) */ +/* #undef HAVE_MTGET_DSREG2 */ /* if struct mtget contains mt_dsreg2 (drive status lsb) */ +#define HAVE_MTGET_GSTAT 1 /* if struct mtget contains mt_gstat (generic status) */ +#define HAVE_MTGET_ERREG 1 /* if struct mtget contains mt_erreg (error register) */ +#define HAVE_MTGET_RESID 1 /* if struct mtget contains mt_resid (residual count) */ +#define HAVE_MTGET_FILENO 1 /* if struct mtget contains mt_fileno (file #) */ +#define HAVE_MTGET_BLKNO 1 /* if struct mtget contains mt_blkno (block #) */ +/* #undef HAVE_MTGET_FLAGS */ /* if struct mtget contains mt_flags (flags) */ +/* #undef HAVE_MTGET_BF */ /* if struct mtget contains mt_bf (optimum blocking factor) */ +#define HAVE_STRUCT_RUSAGE 1 /* have struct rusage in sys/resource.h */ +/* #undef HAVE_SI_UTIME */ /* if struct siginfo contains si_utime */ +/* #undef HAVE_UNION_SEMUN */ /* have an illegal definition for union semun in sys/sem.h */ +#define HAVE_UNION_WAIT 1 /* have union wait in wait.h */ +/* + * SCO UnixWare has st_atim.st__tim.tv_nsec but the st_atim.tv_nsec tests also + * succeeds. If you use st_atim.tv_nsec on UnixWare, you get a warning about + * illegal structure usage. For this reason, your code needs to have + * #ifdef HAVE_ST__TIM before #ifdef HAVE_ST_NSEC. + */ +/* #undef HAVE_ST_SPARE1 */ /* if struct stat contains st_spare1 (usecs) */ +/* #undef HAVE_ST_ATIMENSEC */ /* if struct stat contains st_atimensec (nanosecs) */ +#define HAVE_ST_NSEC 1 /* if struct stat contains st_atim.tv_nsec (nanosecs) */ +/* #undef HAVE_ST__TIM */ /* if struct stat contains st_atim.st__tim.tv_nsec (nanosecs) */ +/* #undef HAVE_ST_ATIMESPEC */ /* if struct stat contains st_atimespec.tv_nsec (nanosecs) */ +#define HAVE_ST_BLKSIZE 1 /* if struct stat contains st_blksize */ +#define HAVE_ST_BLOCKS 1 /* if struct stat contains st_blocks */ +/* #undef HAVE_ST_FSTYPE */ /* if struct stat contains st_fstype */ +#define HAVE_ST_RDEV 1 /* if struct stat contains st_rdev */ +/* #undef HAVE_ST_FLAGS */ /* if struct stat contains st_flags */ +/* #undef STAT_MACROS_BROKEN */ /* if the macros S_ISDIR, S_ISREG .. don't work */ + +#define DEV_MINOR_BITS 32 /* # if bits needed to hold minor device number */ +#define DEV_MINOR_NONCONTIG 1 /* if bits in minor device number are noncontiguous */ + +#define HAVE_SOCKADDR_STORAGE 1 /* if socket.h defines struct sockaddr_storage */ + + +/* + * Byteorder/Bitorder + */ +#define HAVE_C_BIGENDIAN /* Flag that WORDS_BIGENDIAN test was done */ +/* #undef WORDS_BIGENDIAN */ /* If using network byte order */ +#define HAVE_C_BITFIELDS /* Flag that BITFIELDS_HTOL test was done */ +/* #undef BITFIELDS_HTOL */ /* If high bits come first in structures */ + +/* + * Types/Keywords + */ +#define SIZEOF_CHAR 1 +#define SIZEOF_SHORT_INT 2 +#define SIZEOF_INT 4 +#define SIZEOF_LONG_INT 4 +#define SIZEOF_LONG_LONG 8 +#define SIZEOF_CHAR_P 4 +#define SIZEOF_UNSIGNED_CHAR 1 +#define SIZEOF_UNSIGNED_SHORT_INT 2 +#define SIZEOF_UNSIGNED_INT 4 +#define SIZEOF_UNSIGNED_LONG_INT 4 +#define SIZEOF_UNSIGNED_LONG_LONG 8 +#define SIZEOF_UNSIGNED_CHAR_P 4 + +#define HAVE_LONGLONG 1 /* Compiler defines long long type */ +/* #undef CHAR_IS_UNSIGNED */ /* Compiler defines char to be unsigned */ + +/* #undef const */ /* Define to empty if const doesn't work */ +/* #undef uid_t */ /* To be used if uid_t is not present */ +/* #undef gid_t */ /* To be used if gid_t is not present */ +/* #undef size_t */ /* To be used if size_t is not present */ +/* #undef ssize_t */ /* To be used if ssize_t is not present */ +/* #undef pid_t */ /* To be used if pid_t is not present */ +/* #undef off_t */ /* To be used if off_t is not present */ +/* #undef mode_t */ /* To be used if mode_t is not present */ +/* #undef time_t */ /* To be used if time_t is not present */ +/* #undef caddr_t */ /* To be used if caddr_t is not present */ +/* #undef daddr_t */ /* To be used if daddr_t is not present */ +/* #undef dev_t */ /* To be used if dev_t is not present */ +/* #undef ino_t */ /* To be used if ino_t is not present */ +/* #undef nlink_t */ /* To be used if nlink_t is not present */ +#define blksize_t long /* To be used if blksize_t is not present */ +/* #undef blkcnt_t */ /* To be used if blkcnt_t is not present */ +/* + * Important: Next Step needs time.h for clock_t (because of a bug) + */ +/* #undef clock_t */ /* To be used if clock_t is not present */ +/* #undef socklen_t */ /* To be used if socklen_t is not present */ + +/* + * These types are present on all UNIX systems but should be avoided + * for portability. + * On Apollo/Domain OS we don't have them.... + * + * Better include and use Uchar, Uint & Ulong + */ +/* #undef u_char */ /* To be used if u_char is not present */ +/* #undef u_short */ /* To be used if u_short is not present */ +/* #undef u_int */ /* To be used if u_int is not present */ +/* #undef u_long */ /* To be used if u_long is not present */ + +/*#undef HAVE_SIZE_T*/ +/*#undef NO_SIZE_T*/ +/* #undef VA_LIST_IS_ARRAY */ /* va_list is an array */ +#define GETGROUPS_T gid_t +#define GID_T GETGROUPS_T + +/* + * Define as the return type of signal handlers (int or void). + */ +#define RETSIGTYPE void + +/* + * Defines needed to get large file support. + */ +#ifdef USE_LARGEFILES + +#define HAVE_LARGEFILES 1 + +#ifdef HAVE_LARGEFILES /* If we have working largefiles at all */ + /* This is not defined with glibc-2.1.3 */ + +#define _FILE_OFFSET_BITS 64 /* # of bits in off_t if settable */ +#define _LARGEFILE_SOURCE 1 /* To make ftello() visible (HP-UX 10.20). */ +/* #undef _LARGE_FILES */ /* Large file defined on AIX-style hosts. */ +/* #undef _XOPEN_SOURCE */ /* To make ftello() visible (glibc 2.1.3). */ + /* XXX We don't use this because glibc2.1.3*/ + /* XXX is bad anyway. If we define */ + /* XXX _XOPEN_SOURCE we will loose caddr_t */ + +/* #undef HAVE_FSEEKO */ /* Do we need this? If HAVE_LARGEFILES is */ + /* defined, we have fseeko() */ + +#endif /* HAVE_LARGEFILES */ +#endif /* USE_LARGEFILES */ + +#ifdef USE_ACL /* Enable/disable ACL support */ +/* + * POSIX ACL support + */ +#define HAVE_ACL_GET_FILE 1 /* acl_get_file() function */ +#define HAVE_ACL_SET_FILE 1 /* acl_set_file() function */ +#define HAVE_ACL_FROM_TEXT 1 /* acl_from_text() function */ +#define HAVE_ACL_TO_TEXT 1 /* acl_to_text() function */ +#define HAVE_ACL_FREE 1 /* acl_free() function */ +#define HAVE_ACL_DELETE_DEF_FILE 1 /* acl_delete_def_file() function */ + +#if defined(HAVE_ACL_GET_FILE) && defined(HAVE_ACL_SET_FILE) && \ + defined(HAVE_ACL_FROM_TEXT) && defined(HAVE_ACL_TO_TEXT) && \ + defined(HAVE_ACL_FREE) +# define HAVE_POSIX_ACL 1 /* POSIX ACL's present */ +#endif + +/* + * Sun ACL support. + * Note: unfortunately, HP-UX has an (undocumented) acl() function in libc. + */ +/* #undef HAVE_ACL */ /* acl() function */ +/* #undef HAVE_FACL */ /* facl() function */ +/* #undef HAVE_ACLFROMTEXT */ /* aclfromtext() function */ +/* #undef HAVE_ACLTOTEXT */ /* acltotext() function */ + +#if defined(HAVE_ACL) && defined(HAVE_FACL) && \ + defined(HAVE_ACLFROMTEXT) && defined(HAVE_ACLTOTEXT) +# define HAVE_SUN_ACL 1 /* Sun ACL's present */ +#endif + +/* + * HP-UX ACL support. + * Note: unfortunately, HP-UX has an (undocumented) acl() function in libc. + */ +/* #undef HAVE_GETACL */ /* getacl() function */ +/* #undef HAVE_FGETACL */ /* fgetacl() function */ +/* #undef HAVE_SETACL */ /* setacl() function */ +/* #undef HAVE_FSETACL */ /* fsetacl() function */ +/* #undef HAVE_STRTOACL */ /* strtoacl() function */ +/* #undef HAVE_ACLTOSTR */ /* acltostr() function */ +/* #undef HAVE_CPACL */ /* cpacl() function */ +/* #undef HAVE_FCPACL */ /* fcpacl() function */ +/* #undef HAVE_CHOWNACL */ /* chownacl() function */ +/* #undef HAVE_SETACLENTRY */ /* setaclentry() function */ +/* #undef HAVE_FSETACLENTRY */ /* fsetaclentry() function */ + +#if defined(HAVE_GETACL) && defined(HAVE_FGETACL) && \ + defined(HAVE_SETACL) && defined(HAVE_FSETACL) && \ + defined(HAVE_STRTOACL) && defined(HAVE_ACLTOTEXT) +# define HAVE_HP_ACL 1 /* HP-UX ACL's present */ +#endif + +/* + * Global definition whether ACL support is present. + * As HP-UX differs too much from other implementations, HAVE_HP_ACL is not + * included in HAVE_ANY_ACL. + */ +#if defined(HAVE_POSIX_ACL) || defined(HAVE_SUN_ACL) +# define HAVE_ANY_ACL 1 /* Any ACL implementation present */ +#endif + +#endif /* USE_ACL */ + +/* + * Misc CC / LD related stuff + */ +/* #undef NO_USER_MALLOC */ /* If we cannot define our own malloc() */ +#define HAVE_DYN_ARRAYS 1 /* If the compiler allows dynamic sized arrays */ + +/* + * Strings that help to maintain OS/platform id's in C-programs + */ +#define HOST_ALIAS "i686-pc-linux-gnu" /* Output from config.guess (orig) */ +#define HOST_SUB "i686-pc-linux-gnu" /* Output from config.sub (modified) */ +#define HOST_CPU "i686" /* CPU part from HOST_SUB */ +#define HOST_VENDOR "pc" /* VENDOR part from HOST_SUB */ +#define HOST_OS "linux-gnu" /* CPU part from HOST_SUB */ + + +/* + * Begin restricted code for quality assurance. + * + * Warning: you are not allowed to include the #define below if you are not + * using the Schily makefile system or if you modified the autoconfiguration + * tests. + * + * If you only added other tests you are allowed to keep this #define. + * + * This restiction is introduced because this way, I hope that people + * contribute to the project instead of creating branches. + */ +#define IS_SCHILY_XCONFIG +/* + * End restricted code for quality assurance. + */ diff --git a/src/schily/xmconfig.h b/src/schily/xmconfig.h new file mode 100644 index 0000000..3d32634 --- /dev/null +++ b/src/schily/xmconfig.h @@ -0,0 +1,1356 @@ +/* @(#)xmconfig.h 1.29 03/06/15 Copyright 1995 J. Schilling */ +/* + * Manual generated static definitions for machine configuration + * + * Copyright (c) 1995 J. Schilling + * + * This file is made to be included from and may be used + * instead of configurations that are dynamically autogenerated. + * Use only cpp instructions. + * + * NOTE: SING: (Schily Is Not Gnu) + */ +/* + * 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, 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _XMCONFIG_H +#define _XMCONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * 1) Compiler and language related headers + * + * define PROTOTYPES to use ansi C prototypes + * + * define HAVE_ELF Object files are stored in System V.4 ELF format. + * + * define HAVE_COFF Object files are stored in System V.2 COFF format. + * + * define HAVE_AOUT Object files are stored in ATT/BSD a.out format. + * + * define HAVE_STDARG_H to use stdarg.h, else use varargs.h + * NOTE: SaberC on a Sun has prototypes but no stdarg.h. + * + * define HAVE_VA_COPY have va_copy() to do assignements of va_list type objects. + * define HAVE__VA_COPY have __va_copy() to do assignements of va_list type objects. + * + * define HAVE_STDLIB_H to use general utility defines (malloc(), size_t ...) + * some C library prototypes my be found here + * + * define HAVE_STRING_H to get NULL and string function prototypes + * + * define HAVE_STRINGS_H to get BSD string function prototypes + * + * define HAVE_STDC_HEADERS to declare the presence of other ansi C headers + * define STDC_HEADERS same as above (GNU name) + * + * define HAVE_LONGLONG to use long long for space/transfer calculations + * + * define HAVE_SIZE_T The type size_t is present + * define NO_SIZE_T The type size_t is not present + * + * + * 2) Operating system related headers + * + * define HAVE_OSDEF to prevent later definitions to overwrite current + * + * define __NOT_SVR4__ Not a real SVR4 implementation + * + * define HAVE_UNISTD_H to use access, lockf and lseek constants + * syscall prototypes may be found here also + * use sys/file.h otherwise for above constants + * + * define HAVE_FCNTL_H to use access, O_XXX constants for open() + * and open(), creat(), fcntl() prototypes + * use sys/file.h otherwise for above constants + * + * define HAVE_DIRENT_H to use dirent.h instead of the old BSD sys/dir.h + * define HAVE_SYS_DIR_H to use the old BSD sys/dir.h, otherwise no readdir() + * define HAVE_NDIR_H to use ndir.h + * define HAVE_SYS_NDIR_H to use sys/ndir.h + * + * define HAVE_MALLOC_H if malloc.h exists + * + * define HAVE_TERMIOS_H to use posix terminal and session control (termios.h) + * define HAVE_TERMIO_H to use SV terminal control (termio.h) *- no setpgrp -* + * Else use BSD style sgttyb and setpgrp (ioctl.h) + * XXX session control should be another define XXX + * + * define HAVE_SYS_TIME_H may include sys/time.h for struct timeval + * used internally in timedefs.h + * + * define HAVE_UTIMES to use BSD utimes() and sys/time.h + * define HAVE_UTIME_H to use utime.h for the utimbuf structure declaration + * Else declare struct utimbuf yourself. + * + * define HAVE_WAIT_H to use wait.h for prototypes and union wait + * define HAVE_SYS_WAIT_H else use sys/wait.h + * Else declare it by yourself. + * + * define HAVE_SYS_PARAM_H if it is ok to include sys/param.h + * + * define HAVE_SYS_SYSTEMINFO_H to use sysinfo() + * define HAVE_SYS_UTSNAME_H to use uname() + * + * define HAVE_SYS_PRIOCNTL_H to use priocntl() instead of nice()/setpriority() + * define HAVE_SYS_RTPRIOCNTL_H if the system supports real time classes. + * + * define HAVE_SYS_MTIO_H to use mtio definitions from sys/mtio.h + * define HAVE_MTGET_DSREG if struct mtget contains mt_dsreg (drive status) + * define HAVE_MTGET_RESID if struct mtget contains mt_resid (residual count) + * define HAVE_MTGET_FILENO if struct mtget contains mt_fileno (file #) + * define HAVE_MTGET_BLKNO if struct mtget contains mt_blkno (block #0 + * + * define MAJOR_IN_MKDEV if we should include sys/mkdev.h to get + * major(), minor() and makedev() + * + * define MAJOR_IN_SYSMACROS if we should include sys/sysmacros.h to get + * major(), minor() and makedev() + * + * ... else look in sys/types.h for major() + * + * 3) Miscellaneous operating system/library/processor related things + * + * define HAVE_USG_STDIO to enable the use USG stdio.h internals + * To to this we need: + * f->_flag & _IONBF ... Unbuffered + * f->_flag & _IOERR ... I/O error + * f->_flag & _IOEOF ... End of File + * f->_cnt ... r/w count in buf + * f->_ptr ... pointer into buf + * _filbuf(FILE * f) ... fill buffer, return 1st ch + * _flsbuf(unsigned char *, FILE * f) ... flush buffer + * + * define HAVE_BRK may use brk() + * + * define HAVE_SBRK may use sbrk() + * + * + * define HAVE_DTOA use the 4.4BSD function __dtoa() instead of + * the AT&T standard functions ecvt()/fcvt()/gcvt() + * + * define HAVE_GETCWD use SysV getcwd() instead of BSD getwd() + * + * define HAVE_STRERROR may use strerror() instead of sys_errlist[] and sys_nerr + * + * define HAVE_MEMMOVE should use memmove() instead of bcopy() + * + * define HAVE_MLOCKALL may use mlockall() to lock the whole process into memory + * + * define HAVE_MMAP may map memory (sys/types.h + sys/mman.h) + * define HAVE_SMMAP may map anonymous memory to get shared mem + * + * define HAVE_USGSHM may get shared memory SV style (sys/types.h + sys/ipc.h) + * + * define HAVE_USGSEM may use SysV style shared memory and semaphores. + * May use shared memory and semaphores to manage a + * sharing buffer and its synchronization. + * If this is not defined, use mmap and flock. + * + * define HAVE_MSEM Has OSF/1 style memory semaphores. + * Use instead of SysV semaphores or flock + * for shared memory synchronisation. + * + * define HAVE_LDSTUB Has SPARC ldstub atomic instruction. + * May be used instead of system V semaphores or flock + * for shared memory synchronisation. + * + * define HAVE_XCHG Has i386 xchg atomic instruction. + * May be used instead of system V semaphores or flock + * for shared memory synchronisation. + * + * define HAVE_FLOCK Use flock for synchronization on logfiles. + * If this is not defined use lockf. + * + * define HAVE_FCHDIR The fchdir system call may be used + * to change the current directory and back. + * Else remember the pathname and use chdir. + * + * define HAVE_STATVFS The statvfs and fstatvfs calls are available. + * Else get filesystem statistics with + * statfs or getmnt (on ultrix). + * + * define HAVE_QUOTA The quota or quotactl system calls are available. + * + * define HAVE_YP To use yellow pages. + * + * define HAVE_SHADOW To use shadow password file. + * + * define HAVE_SETREUID have BSD setreuid() + * define HAVE_SETRESUID have HPUX only ??? setresuid() + * define HAVE_SETEUID have SVr4 seteuid() + * + * define HAVE_LCHOWN Need to use lchown() instead of chown() on symlinks. + * + * define HAVE_PROCFS SVr4 style procfs is available. + * + * define HAVE_PROCFS2 SVr4.2 (SMP) style procfs is available. + * + * define HAVE_SIGINFO Use waitid and the siginfo_t structure for waiting + * for child processes. + * Else use wait3 and union wait. + * + * define HAVE_WAIT3 Have wait3. + * + * define HAVE_WAITPID Use waitpid and no resource usage instead of wait3. + * + * define HAVE_UNION_WAIT Have union wait in wait.h + * + * define HAVE_GETHOSTNAME to use gethostname() + * + * define HAVE_STREAMS Use streams networking calls. Else use sockets. + * + * define HAVE_STRPTYS Use SVr4 style streams pseudo ttys. + * + * define HAVE_POLL Use the poll system call to wait for I/O. + * Else use select. + * + * define HAVE_SELECT Use the select system call to wait for I/O. + * + * define HAVE_TIRPC The remote procedure call library is of the + * transport independent flavour. + * + * define GID_T The type to use for the getgroups() array. + * This should be gid_t, but some BSD based systems + * must have int there. + * + * + * 4) Specials for libschily + * + * define HAVE_SCANSTACK Scanning of the stack is implemented for this + * architecture: + * getfp() + * and the derived functions: + * handlecond(), raisecond() + * are working. + * + * XXX It is most likely that getfp() does not really work correctly + * XXX if getav0() is not working. + * XXX For this reason, HAVE_GETAV0 is not used anymore. + * XXX Instead avoffset.h is included and the existence of + * XXX AV_OFFSET and FP_INDIR is checked instead. + * + * define HAVE_GETAV0 Scanning of stack and locating the arg vector + * is implemented for this architecture: + * getav0() + * is working. + * get_progname() in saveargs.c will work in the main + * thread without a prior call to save_args(). + * + */ + +#if defined(sun) || defined(__sun) || defined(__sun__) +# ifndef IS_SUN +# define IS_SUN +# endif +#endif + +#if defined(SOL2) || defined(SOL2) || \ + defined(S5R4) || defined(__S5R4) || defined(SVR4) + +# ifndef __SVR4 +# define __SVR4 +# endif +#endif + +#ifdef __SVR4 +# ifndef SVR4 +# define SVR4 +# endif +#endif + +/* + * SunOS 4.x + */ +#if defined(IS_SUN) && !defined(__SVR4) + /* + * Sun C defines __STDC__ as zero. + */ +# ifdef __STDC__ +# define PROTOTYPES +# ifndef SABER +# define HAVE_STDARG_H +# define HAVE_LONGLONG +# endif +# endif +# define HAVE_AOUT +# define HAVE_STDLIB_H +# define HAVE_STRING_H +# define HAVE_UNISTD_H +# define HAVE_FCNTL_H +# define HAVE_DIRENT_H +# define HAVE_SYS_DIR_H +# define HAVE_TERMIOS_H +# define HAVE_TERMIO_H +# define HAVE_SYS_TIME_H +# define HAVE_UTIMES +# define HAVE_UTIME_H +# define HAVE_SYS_WAIT_H +# define HAVE_SYS_PARAM_H +# define HAVE_SYS_UTSNAME_H +# define HAVE_SYS_MTIO_H +# define HAVE_MTGET_DSREG +# define HAVE_MTGET_RESID +# define HAVE_MTGET_FILENO +# define HAVE_MTGET_BLKNO +# define MAJOR_IN_SYSMACROS +# define HAVE_UNION_WAIT +# define HAVE_USG_STDIO +# define HAVE_GETCWD +# define HAVE_MLOCKALL +# define HAVE_MMAP +# define HAVE_SMMAP +# define HAVE_USGSHM +# define HAVE_USGSEM +# ifdef sparc +# define HAVE_LDSTUB +# endif +# define HAVE_FLOCK +# define HAVE_FCHDIR +# define HAVE_QUOTA +# define HAVE_YP +# define HAVE_SETREUID +# define HAVE_WAIT3 +# define HAVE_GETHOSTNAME +# define HAVE_SELECT +# define GID_T int +# define USLEEPRETURN_T unsigned int +# define HAVE_GETAV0 /* SunOS < 5 only runs on sparc/mc680xx */ +# define HAVE_SCANSTACK /* SunOS < 5 only runs on sparc/mc680xx */ +#endif + +/* + * AIX + */ +#if defined(_IBMR2) || defined(_AIX) +# define IS_UNIX /* ??? really ??? */ +# define NO_FLOATINGPOINT /* XXX until isinf()/isnan() is solved */ +# define USE_FLOATINGARGS /* Use up args from floatingpoint format */ +#ifndef PROTOTYPES +# define PROTOTYPES +#endif +# define HAVE_COFF +# define HAVE_STDARG_H +# define HAVE_STDLIB_H +# define HAVE_STRING_H +# define HAVE_LONGLONG +# define HAVE_UNISTD_H +# define HAVE_FCNTL_H +# define HAVE_DIRENT_H +# define HAVE_TERMIOS_H +# define HAVE_TERMIO_H +# define HAVE_SYS_TIME_H +# define HAVE_UTIMES +# define HAVE_UTIME_H +# define HAVE_SYS_WAIT_H +# define HAVE_SYS_PARAM_H +# define HAVE_SYS_UTSNAME_H +# define MAJOR_IN_SYSMACROS +/*# define HAVE_USG_STDIO*/ +# define HAVE_GETCWD +# define HAVE_STRERROR +# define HAVE_MEMMOVE +# define HAVE_MMAP +# define HAVE_SMMAP +# define HAVE_USGSHM +# define HAVE_USGSEM +# define HAVE_MSEM +# define HAVE_FLOCK +# define HAVE_QUOTA +# define HAVE_YP +# define HAVE_WAIT3 +# define HAVE_WAITPID +# define HAVE_GETHOSTNAME +# define HAVE_STREAMS +# define HAVE_POLL +# define HAVE_SELECT + +# define GID_T gid_t +# define USLEEPRETURN_T int +#endif + +/* + * Silicon Graphics (must be before SVR4) + */ +#if defined(sgi) || defined(__sgi) +# define __NOT_SVR4__ /* Not a real SVR4 implementation */ + +# define PROTOTYPES +# define HAVE_ELF +# define HAVE_COFF +# define HAVE_STDARG_H +# define HAVE_LONGLONG +# define HAVE_UNISTD_H +# define HAVE_FCNTL_H +# define HAVE_DIRENT_H +# define HAVE_TERMIOS_H +# define HAVE_TERMIO_H +# define HAVE_SYS_TIME_H +# define HAVE_UTIMES +# define HAVE_UTIME_H +# define HAVE_WAIT_H +# define HAVE_SYS_WAIT_H +# define HAVE_SYS_PARAM_H +# define HAVE_SYS_SYSTEMINFO_H +# define HAVE_SYS_UTSNAME_H +# define HAVE_SYS_MTIO_H +# define HAVE_MTGET_DSREG +# define HAVE_MTGET_RESID +# define HAVE_MTGET_FILENO +# define HAVE_MTGET_BLKNO +# define MAJOR_IN_MKDEV +# define HAVE_USG_STDIO +# define HAVE_GETCWD +# define HAVE_STRERROR +# define HAVE_MEMMOVE +# define HAVE_MMAP +# define HAVE_SMMAP +# define HAVE_USGSHM +# define HAVE_USGSEM +# define HAVE_FLOCK +# define HAVE_FCHDIR +# define HAVE_STATVFS +# define HAVE_QUOTA +# define HAVE_YP +# define HAVE_SHADOW +# define HAVE_PROCFS +# define HAVE_SIGINFO +# define HAVE_WAIT3 +# define HAVE_WAITPID +# define HAVE_GETHOSTNAME +# define HAVE_STREAMS +# define HAVE_STRPTYS +# define HAVE_POLL +# define HAVE_SELECT +# define HAVE_STRPTYS +# define GID_T gid_t +/*# define USLEEPRETURN_T unsigned int*/ +# define vfork fork +#endif + +#if defined(mips) && !(defined(ultrix) || defined(sony) || defined(sgi)) +# define HAVE_COFF +# define HAVE_UNISTD_H +# define HAVE_USGSHM +# define HAVE_USGSEM +# define HAVE_FLOCK +# define HAVE_YP +# define GID_T int +# define USLEEPRETURN_T unsigned int +#endif + +#if defined(sony) +# ifdef mips +# define HAVE_COFF +# else +# define HAVE_AOUT +# endif +# define HAVE_USGSHM +# define HAVE_USGSEM +# define HAVE_FLOCK +# define HAVE_QUOTA +# define HAVE_YP +# define GID_T int +# define USLEEPRETURN_T unsigned int +# ifndef SEEK_SET +# define SEEK_SET 0 /* Set file pointer to "offset" */ +# define SEEK_CUR 1 /* Set file pointer to current plus "offset" */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +# endif +#endif + +/* + * Digital UNIX (OSF1) + */ +#if defined(__osf__) +# define PROTOTYPES +# define HAVE_OSDEF /* prevent later definitions to overwrite current */ +/*# define __NOT_SVR4__*/ /* Not a real SVR4 implementation */ + +/*# define HAVE_ELF*/ +# define HAVE_COFF +/*# define HAVE_AOUT*/ +# define HAVE_STDARG_H +/*# define HAVE_VA_COPY*/ +# define HAVE_STDLIB_H +# define HAVE_STRING_H +# define HAVE_STDC_HEADERS +# define STDC_HEADERS /* GNU name */ +# define HAVE_LONGLONG + +# define HAVE_UNISTD_H +# define HAVE_FCNTL_H +# define HAVE_DIRENT_H +# define HAVE_SYS_DIR_H +/*# define HAVE_NDIR_H*/ +/*# define HAVE_SYS_NDIR_H*/ +# define HAVE_TERMIOS_H +# define HAVE_TERMIO_H +# define HAVE_SYS_TIME_H +# define HAVE_UTIMES +# define HAVE_UTIME_H +# define HAVE_WAIT_H +# define HAVE_SYS_WAIT_H +# define HAVE_SYS_PARAM_H +# define HAVE_SYS_SYSTEMINFO_H +# define HAVE_SYS_UTSNAME_H +# define HAVE_SYS_PRIOCNTL_H +# define HAVE_SYS_RTPRIOCNTL_H +# define HAVE_SYS_MTIO_H +# define HAVE_MTGET_DSREG +# define HAVE_MTGET_RESID +# define HAVE_MTGET_FILENO +# define HAVE_MTGET_BLKNO +/*# define MAJOR_IN_MKDEV*/ +# define MAJOR_IN_SYSMACROS +# define HAVE_USG_STDIO +/*# define HAVE_DTOA*/ +# define HAVE_GETCWD +# define HAVE_STRERROR +# define HAVE_MEMMOVE +# define HAVE_MLOCKALL +# define HAVE_MMAP +# define HAVE_SMMAP +# define HAVE_USGSHM +# define HAVE_USGSEM +# define HAVE_MSEM +/*# define HAVE_LDSTUB*/ +/*# define HAVE_XCHG*/ +# define HAVE_FLOCK +# define HAVE_FCHDIR +# define HAVE_STATVFS +# define HAVE_QUOTA +# define HAVE_YP +/*# define HAVE_SHADOW*/ /* No, but C2 */ +# define HAVE_SETREUID +/*# define HAVE_SETRESUID*/ +# define HAVE_SETEUID +# define HAVE_LCHOWN +# define HAVE_PROCFS +/*# define HAVE_PROCFS2*/ /* No */ +# define HAVE_SIGINFO +# define HAVE_WAIT3 +# define HAVE_WAITPID +# define HAVE_UNION_WAIT +# define HAVE_GETHOSTNAME +# define HAVE_STREAMS +# define HAVE_STRPTYS +# define HAVE_POLL +# define HAVE_SELECT /* XXX needs sys/select.h */ +/*# define HAVE_TIRPC*/ +# define GID_T gid_t +# define USLEEPRETURN_T int +/*# define USLEEPRETURN_T void*/ +/*# define USLEEPISVOID*/ + +/*# define HAVE_GETAV0*/ +/*# define HAVE_SCANSTACK*/ +#endif + +#if defined(ultrix) +# ifdef mips +# define HAVE_COFF +# else +# define HAVE_AOUT +# endif +# define HAVE_STDLIB_H +# define HAVE_UNISTD_H +# define HAVE_SYS_DIR_H +# define HAVE_TERMIOS_H +# define HAVE_UTIME_H +# define HAVE_USGSHM +# define HAVE_USGSEM +# define HAVE_FLOCK +# define HAVE_QUOTA +# define HAVE_YP +# define GID_T int +# define USLEEPRETURN_T unsigned int +#endif + +/* + * HP/UX + */ +#if defined(__hpux) || defined(hpux) +/*# define PROTOTYPES*/ +# define HAVE_AOUT +# define HAVE_STDARG_H +# define HAVE_UNISTD_H +# define HAVE_FCNTL_H +# define HAVE_DIRENT_H +# define HAVE_TERMIOS_H +# define HAVE_TERMIO_H +# define HAVE_SYS_TIME_H +# define HAVE_UTIME_H +# define HAVE_SYS_WAIT_H +# define HAVE_SYS_PARAM_H +# define HAVE_SYS_UTSNAME_H +# define HAVE_SYS_MTIO_H +# define MAJOR_IN_SYSMACROS +# define HAVE_GETCWD +# define HAVE_STRERROR +# define HAVE_MEMMOVE +# define HAVE_MMAP +# define HAVE_SMMAP +# define HAVE_USGSHM +# define HAVE_USGSEM +#if 0 +# define HAVE_MSEM +# endif +# define HAVE_FCHDIR +# define HAVE_QUOTA +# define HAVE_YP +# define HAVE_SETRESUID +# define HAVE_WAIT3 +# define HAVE_WAITPID +# define HAVE_GETHOSTNAME +# define HAVE_STREAMS +# define HAVE_STRPTYS +# define HAVE_POLL +# define HAVE_SELECT +# define GID_T gid_t +/*# define USLEEPRETURN_T unsigned int*/ +#endif + +/* + * Data General + */ +#if defined(__DGUX__) +# define PROTOTYPES +# define HAVE_ELF +# define HAVE_STDARG_H +# define HAVE_UNISTD_H +# define HAVE_DIRENT_H +# define HAVE_TERMIOS_H +# define HAVE_SYS_TIME_H +# define HAVE_UTIMES +# define HAVE_UTIME_H +# define HAVE_SYS_PARAM_H +# undef HAVE_MTGET_DSREG +# undef HAVE_MTGET_RESID +# undef HAVE_MTGET_FILENO +# undef HAVE_MTGET_BLKNO +# define mt_type mt_model +# define mt_dsreg mt_status1 +# define mt_erreg mt_status2 +# define HAVE_GETCWD +# define HAVE_STRERROR +# define HAVE_MEMMOVE +# define HAVE_USGSEM +# if defined(__i386_) || defined(i386) +# define HAVE_XCHG +# endif + /* + * DGUX hides its flock as dg_flock. + */ +# define HAVE_FLOCK +# define flock dg_flock +# define HAVE_FCHDIR +# define HAVE_STATVFS +# undef HAVE_QUOTA +# define HAVE_YP +# define HAVE_SHADOW +# undef HAVE_PROCFS +# undef HAVE_PROCFS2 +# define HAVE_WAIT3 +# define HAVE_UNION_WAIT +/*# define HAVE_GETHOSTNAME*/ +# define HAVE_STREAMS +# define HAVE_STRPTYS +# define HAVE_POLL +# define HAVE_SELECT +# undef HAVE_TIRPC +# define GID_T gid_t +# define USLEEPRETURN_T unsigned int + /* + * Use the BSD style wait on DGUX to get the resource usages of child + * processes. + */ +# define _BSD_WAIT_FLAVOR + +/*# define HAVE_GETAV0*/ +# ifdef i386 +# define HAVE_SCANSTACK +# endif +#endif + +/* + * Linux + */ +#if defined(__linux__) || defined(__linux) +# define PROTOTYPES +# ifdef __ELF__ +# define HAVE_ELF +# else +# define HAVE_AOUT +# endif +# define HAVE_STDARG_H +# define HAVE_STDLIB_H +# define HAVE_STRING_H +# define HAVE_STDC_HEADERS +# define STDC_HEADERS /* GNU name */ +# define HAVE_LONGLONG +# define HAVE_UNISTD_H +# define HAVE_FCNTL_H +# define HAVE_DIRENT_H +# define HAVE_TERMIOS_H +# define HAVE_TERMIO_H +# define HAVE_SYS_TIME_H +# define HAVE_UTIMES +# define HAVE_UTIME_H +/*# define HAVE_WAIT_H*/ +# define HAVE_SYS_WAIT_H +# define HAVE_SYS_PARAM_H +# define HAVE_SYS_UTSNAME_H +# define HAVE_SYS_MTIO_H +# define HAVE_MTGET_DSREG +# define HAVE_MTGET_RESID +# define HAVE_MTGET_FILENO +# define HAVE_MTGET_BLKNO +# define MAJOR_IN_SYSMACROS +# define HAVE_GETCWD +# define HAVE_STRERROR +# define HAVE_MEMMOVE +# define HAVE_MLOCKALL +# define HAVE_MMAP +/*# define HAVE_SMMAP*/ +# define HAVE_USGSHM +# define HAVE_USGSEM +# define HAVE_FLOCK +# define HAVE_FCHDIR +# define HAVE_STATVFS +# define HAVE_QUOTA +# define HAVE_YP +# define HAVE_SETREUID /* >= Linux 1.1.37 */ +# define HAVE_SETEUID +/*# define HAVE_PROCFS*/ /* ??? */ +/*# define HAVE_PROCFS2*/ +# define HAVE_WAIT3 +# define HAVE_WAITPID +# define HAVE_GETHOSTNAME +# define HAVE_SELECT + +# define GID_T gid_t +# define USLEEPRETURN_T void +# define USLEEPISVOID + +/*# define HAVE_GETAV0*/ +# define HAVE_SCANSTACK +#endif + + +#if defined(OLD__bsdi__) +# define HAVE_MSEM /* ??? */ +# define F_ULOCK 0 /* Unlock a previously locked region */ +# define F_LOCK 1 /* Lock a region for exclusive use */ +# define F_TLOCK 2 /* Test and lock a region for exclusive use */ +# define F_TEST 3 /* Test a region for other processes locks */ +#endif + +/* + * Prototype for FreeBSD / NetBSD / OpenBSD / BSD/OS + */ +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) +# define PROTOTYPES +# define HAVE_AOUT +# define HAVE_STDARG_H +# define HAVE_STDLIB_H +# define HAVE_STRING_H +# define HAVE_STDC_HEADERS +# define STDC_HEADERS /* GNU name */ +# define HAVE_LONGLONG +# define HAVE_UNISTD_H +# define HAVE_FCNTL_H +# define HAVE_DIRENT_H +# define HAVE_TERMIOS_H +# define HAVE_SYS_TIME_H +# define HAVE_UTIMES +# define HAVE_UTIME_H +# define HAVE_SYS_WAIT_H +# define HAVE_SYS_PARAM_H +# define HAVE_SYS_UTSNAME_H +# define HAVE_SYS_MTIO_H +# define HAVE_MTGET_DSREG +# define HAVE_MTGET_RESID +# define HAVE_MTGET_FILENO +# define HAVE_MTGET_BLKNO +/*# define HAVE_USG_STDIO*/ +# define HAVE_DTOA +# define HAVE_GETCWD +# define HAVE_STRERROR +# define HAVE_MEMMOVE +# define HAVE_MMAP +# define HAVE_SMMAP +# define HAVE_USGSHM +# define HAVE_USGSEM +# ifdef sparc +# define HAVE_LDSTUB +# endif +# ifdef i386 +# define HAVE_XCHG +# endif +# define HAVE_FLOCK +# define HAVE_FCHDIR +# define HAVE_QUOTA +# define HAVE_YP +# define HAVE_SETREUID +/*# define HAVE_SETRESUID*/ +# define HAVE_SETEUID +/*# define HAVE_LCHOWN*/ +# define HAVE_WAIT3 +# define HAVE_WAITPID +# define HAVE_UNION_WAIT +# define HAVE_GETHOSTNAME +# define HAVE_SELECT +# define GID_T gid_t +/*# define USLEEPRETURN_T unsigned int*/ +# define USLEEPRETURN_T void +# define USLEEPISVOID + +/*# define HAVE_GETAV0*/ +/*# define HAVE_SCANSTACK*/ +#endif + +/* + * SysVr4 + */ +#if defined(__SVR4) && !defined(__NOT_SVR4__) +# define PROTOTYPES +# define HAVE_ELF +# define HAVE_STDARG_H +# if defined(IS_SUN) +# define HAVE_LONGLONG +# define HAVE_UTIMES +# define HAVE_QUOTA +# define HAVE_GETAV0 /* XXX what about PPC ??? */ +# define HAVE_SCANSTACK /* XXX what about PPC ??? */ +# define HAVE_STRSIGNAL +# define HAVE_STR2SIG +# define HAVE_SIG2STR +# endif +# define HAVE_UNISTD_H +# define HAVE_FCNTL_H +# define HAVE_DIRENT_H +# define HAVE_TERMIOS_H +# define HAVE_TERMIO_H +# define HAVE_SYS_TIME_H +# define HAVE_UTIME_H +# define HAVE_WAIT_H +# define HAVE_SYS_WAIT_H +# define HAVE_SYS_PARAM_H +# define HAVE_SYS_SYSTEMINFO_H +# define HAVE_SYS_UTSNAME_H +# define HAVE_SYS_PRIOCNTL_H +# define HAVE_SYS_RTPRIOCNTL_H +# define HAVE_SYS_MTIO_H +# define HAVE_MTGET_DSREG +# define HAVE_MTGET_RESID +# define HAVE_MTGET_FILENO +# define HAVE_MTGET_BLKNO +# define MAJOR_IN_MKDEV +# define HAVE_USG_STDIO +# define HAVE_GETCWD +# define HAVE_STRERROR +# define HAVE_MEMMOVE +# define HAVE_MLOCKALL +# define HAVE_MMAP +# define HAVE_SMMAP +# define HAVE_USGSHM +# define HAVE_USGSEM +# ifdef sparc +# define HAVE_LDSTUB +# endif +# ifdef i386 +# define HAVE_XCHG +# endif +# define HAVE_FCHDIR +# define HAVE_STATVFS +# define HAVE_YP +# define HAVE_SHADOW +# define HAVE_SETEUID +# define HAVE_LCHOWN +# define HAVE_PROCFS +# if (defined(i386) && !defined(IS_SUN)) +# define HAVE_PROCFS2 +# define HAVE_QUOTA +# endif +# define HAVE_SIGINFO +# define HAVE_WAITPID +# define HAVE_STREAMS +# define HAVE_STRPTYS +# define HAVE_POLL +# define HAVE_SELECT +# define HAVE_TIRPC +# define GID_T gid_t +# define USLEEPRETURN_T unsigned int +#endif + +/* + * Apple Rhapsody + */ +#if defined(__NeXT__) && defined(__TARGET_OSNAME) && __TARGET_OSNAME == rhapsody +# define HAVE_OSDEF /* prevent later definitions to overwrite current */ + +# define PROTOTYPES +/*# define HAVE_ELF*/ +/*# define HAVE_COFF*/ +/*# define HAVE_AOUT*/ +# define HAVE_STDARG_H +# define HAVE_STDLIB_H +# define HAVE_STRING_H +# define HAVE_STDC_HEADERS +# define STDC_HEADERS /* GNU name */ +# define HAVE_LONGLONG +# define HAVE_UNISTD_H +# define HAVE_FCNTL_H +# define HAVE_DIRENT_H +# define HAVE_SYS_DIR_H +/*# define HAVE_NDIR_H*/ +/*# define HAVE_SYS_NDIR_H*/ +# define HAVE_TERMIOS_H +/*# define HAVE_TERMIO_H*/ +# define HAVE_SYS_TIME_H +# define HAVE_UTIMES +# define HAVE_UTIME_H +/*# define HAVE_WAIT_H*/ +# define HAVE_SYS_WAIT_H +# define HAVE_SYS_PARAM_H +/*# define HAVE_SYS_SYSTEMINFO_H*/ +# define HAVE_SYS_UTSNAME_H +/*# define HAVE_SYS_PRIOCNTL_H*/ +/*# define HAVE_SYS_RTPRIOCNTL_H*/ +# define HAVE_SYS_MTIO_H +# define HAVE_MTGET_DSREG +# define HAVE_MTGET_RESID +# define HAVE_MTGET_FILENO +# define HAVE_MTGET_BLKNO +/*# define MAJOR_IN_MKDEV*/ +/*# define MAJOR_IN_SYSMACROS*/ +/*# define HAVE_USG_STDIO*/ +# define HAVE_DTOA +# define HAVE_GETCWD +# define HAVE_STRERROR +# define HAVE_MEMMOVE +# define HAVE_MMAP +# define HAVE_SMMAP +# define HAVE_USGSHM +# define HAVE_USGSEM +/*# define HAVE_MSEM*/ +/*# define HAVE_LDSTUB*/ +# if defined(__i386_) || defined(i386) +# define HAVE_XCHG +# endif +# define HAVE_FLOCK +/*# define HAVE_FCHDIR*/ +/*# define HAVE_STATVFS*/ +# define HAVE_QUOTA +# define HAVE_YP +/*# define HAVE_SHADOW*/ +# define HAVE_SETREUID +/*# define HAVE_SETRESUID*/ +# define HAVE_SETEUID +/*# define HAVE_LCHOWN*/ +/*# define HAVE_PROCFS*/ +/*# define HAVE_PROCFS2*/ +/*# define HAVE_SIGINFO*/ +# define HAVE_WAIT3 +/*# define HAVE_WAITPID*/ +# define HAVE_UNION_WAIT +# define HAVE_GETHOSTNAME +/*# define HAVE_STREAMS*/ +/*# define HAVE_STRPTYS*/ +# define HAVE_POLL +# define HAVE_SELECT +/*# define HAVE_TIRPC*/ +/*# define GID_T gid_t*/ +/*# define USLEEPRETURN_T unsigned int*/ +/*# define USLEEPRETURN_T void*/ +# define USLEEPISVOID + +/*# define HAVE_GETAV0*/ +/*# define HAVE_SCANSTACK*/ +#endif + +/* + * NextStep + */ +#if defined(__NeXT__) && !defined(HAVE_OSDEF) + +#define printf Xprintf +#define fprintf Xfprintf +#define sprintf Xsprintf +#ifdef XXX +# define __NOT_SVR4__ /* Not a real SVR4 implementation */ +#endif + +# define PROTOTYPES +/*# define HAVE_ELF*/ +/*# define HAVE_COFF*/ +/*# define HAVE_AOUT*/ +# define HAVE_STDARG_H +# define HAVE_STDLIB_H +# define HAVE_STRING_H +# define HAVE_STDC_HEADERS +# define STDC_HEADERS /* GNU name */ +# define HAVE_LONGLONG +# define HAVE_UNISTD_H +# define HAVE_FCNTL_H +/*# define HAVE_DIRENT_H XXX not posix compliant */ +# define HAVE_SYS_DIR_H +/*# define HAVE_NDIR_H*/ +/*# define HAVE_SYS_NDIR_H*/ +/*# define HAVE_TERMIOS_H XXX need buggy -lposix */ +/*# define HAVE_TERMIO_H*/ +# define HAVE_SYS_TIME_H +# define HAVE_UTIMES +# define HAVE_UTIME_H +/*# define HAVE_WAIT_H*/ +# define HAVE_SYS_WAIT_H +# define HAVE_SYS_PARAM_H +/*# define HAVE_SYS_SYSTEMINFO_H*/ +/*# define HAVE_SYS_UTSNAME_H XXX needs buggy -lposix */ +/*# define HAVE_SYS_PRIOCNTL_H*/ +/*# define HAVE_SYS_RTPRIOCNTL_H*/ +# define HAVE_SYS_MTIO_H +# define HAVE_MTGET_DSREG +# define HAVE_MTGET_RESID +# define HAVE_MTGET_FILENO +# define HAVE_MTGET_BLKNO +/*# define MAJOR_IN_MKDEV*/ +/*# define MAJOR_IN_SYSMACROS*/ +/*# define HAVE_USG_STDIO XXX different _flsbuf() */ +# define HAVE_STRERROR +/*# define HAVE_MEMMOVE*/ +/*# define HAVE_MMAP*/ +/*# define HAVE_SMMAP*/ +/*# define HAVE_USGSHM*/ +/*# define HAVE_USGSEM*/ +/*# define HAVE_MSEM*/ +/*# define HAVE_LDSTUB*/ +/*# define HAVE_XCHG*/ +# define HAVE_FLOCK +/*# define HAVE_FCHDIR*/ +/*# define HAVE_STATVFS*/ +/*# define HAVE_QUOTA*/ +/*# define HAVE_YP*/ +/*# define HAVE_SHADOW*/ +# define HAVE_SETREUID +/*# define HAVE_SETRESUID*/ +# define HAVE_SETEUID +/*# define HAVE_LCHOWN*/ +/*# define HAVE_PROCFS*/ +/*# define HAVE_PROCFS2*/ +/*# define HAVE_SIGINFO*/ +# define HAVE_WAIT3 +/*# define HAVE_WAITPID*/ +# define HAVE_UNION_WAIT +# define HAVE_GETHOSTNAME +/*# define HAVE_STREAMS*/ +/*# define HAVE_STRPTYS*/ +/*# define HAVE_POLL*/ +# define HAVE_SELECT +/*# define HAVE_TIRPC*/ +# define GID_T gid_t +# define USLEEPRETURN_T int +/*# define USLEEPRETURN_T void*/ +/*# define USLEEPISVOID*/ + +/*# define HAVE_GETAV0*/ +/*# define HAVE_SCANSTACK*/ +#endif + +/* + * Cygwin 32 (NT) + */ +#if defined(__CYGWIN32__) +# define PROTOTYPES +# define HAVE_OSDEF /* prevent later definitions to overwrite current */ +# define __NOT_SVR4__ /* Not a real SVR4 implementation */ + +/*# define HAVE_ELF*/ +/*# define HAVE_COFF*/ +# define HAVE_AOUT +# define HAVE_STDARG_H +/*# define HAVE_VA_COPY*/ +# define HAVE_STDLIB_H +# define HAVE_STRING_H +# define HAVE_STDC_HEADERS +# define STDC_HEADERS /* GNU name */ +# define HAVE_LONGLONG + +# define HAVE_UNISTD_H +# define HAVE_FCNTL_H +# define HAVE_DIRENT_H +/*# define HAVE_SYS_DIR_H*/ +/*# define HAVE_NDIR_H*/ +/*# define HAVE_SYS_NDIR_H*/ +# define HAVE_TERMIOS_H +# define HAVE_TERMIO_H +# define HAVE_SYS_TIME_H +/*# define HAVE_UTIMES*/ +# define HAVE_UTIME_H +/*# define HAVE_WAIT_H*/ +# define HAVE_SYS_WAIT_H +# define HAVE_SYS_PARAM_H +/*# define HAVE_SYS_SYSTEMINFO_H*/ +# define HAVE_SYS_UTSNAME_H +/*# define HAVE_SYS_PRIOCNTL_H*/ +/*# define HAVE_SYS_RTPRIOCNTL_H*/ +/*# define HAVE_SYS_MTIO_H*/ +/*# define HAVE_MTGET_DSREG*/ +/*# define HAVE_MTGET_RESID*/ +/*# define HAVE_MTGET_FILENO*/ +/*# define HAVE_MTGET_BLKNO*/ +/*# define MAJOR_IN_MKDEV*/ +/*# define MAJOR_IN_SYSMACROS*/ +/*# define HAVE_USG_STDIO*/ +/*# define HAVE_DTOA*/ /* XXX eigentlich doch da */ +# define HAVE_GETCWD +# define HAVE_STRERROR +# define HAVE_MEMMOVE +# define HAVE_MMAP +# define HAVE_SMMAP +/*# define HAVE_USGSHM*/ +/*# define HAVE_USGSEM*/ +/*# define HAVE_MSEM*/ +/*# define HAVE_LDSTUB*/ +# if defined(__i386_) || defined(i386) +# define HAVE_XCHG +# endif +/*# define HAVE_FLOCK*/ +/*# define HAVE_FCHDIR*/ +/*# define HAVE_STATVFS*/ +/*# define HAVE_QUOTA*/ +/*# define HAVE_YP*/ +/*# define HAVE_SHADOW*/ +/*# define HAVE_SETREUID*/ +/*# define HAVE_SETRESUID*/ +/*# define HAVE_SETEUID*/ +/*# define HAVE_LCHOWN*/ +/*# define HAVE_PROCFS*/ +/*# define HAVE_PROCFS2*/ +/*# define HAVE_SIGINFO*/ +# define HAVE_WAIT3 +# define HAVE_WAITPID +# define HAVE_UNION_WAIT +# define HAVE_GETHOSTNAME +/*# define HAVE_STREAMS*/ +/*# define HAVE_STRPTYS*/ +/*# define HAVE_POLL*/ +# define HAVE_SELECT +/*# define HAVE_TIRPC*/ +# define GID_T gid_t +# define USLEEPRETURN_T unsigned int +/*# define USLEEPRETURN_T void*/ +/*# define USLEEPISVOID*/ + +/*# define HAVE_GETAV0*/ +/*# define HAVE_SCANSTACK*/ +#endif /* __CYGWIN32__ */ + +#if defined(VMS) +# define PROTOTYPES +# define HAVE_OSDEF /* prevent later definitions to overwrite current */ +# define __NOT_SVR4__ /* Not a real SVR4 implementation */ + +# define HAVE_UNISTD_H +/* # define HAVE_SYS_TIME_H */ +# define HAVE_FCNTL_H +# define HAVE_USLEEP +# define HAVE_INTTYPES_H +# include +# define HOST_CPU "Alpha/VAX" +# define HOST_VENDOR "CPQ" +# define HOST_OS "VMS/OpenVMS" +# define RETSIGTYPE void +/*# define HAVE_ELF */ +/*# define HAVE_COFF */ +/*# define HAVE_AOUT */ +/*# define HAVE_STDARG_H */ +/*# define HAVE_VA_COPY */ +/*# define HAVE_STDLIB_H */ +/*# define HAVE_STRING_H */ +/*# define HAVE_STDC_HEADERS */ +/*# define STDC_HEADERS */ +/*# define HAVE_LONGLONG */ + +/*# define HAVE_UNISTD_H */ +/*# define HAVE_FCNTL_H */ +/*# define HAVE_DIRENT_H */ +/*# define HAVE_SYS_DIR_H */ +/*# define HAVE_NDIR_H */ +/*# define HAVE_SYS_NDIR_H */ +/*# define HAVE_TERMIOS_H */ +/*# define HAVE_TERMIO_H */ +/*# define HAVE_SYS_TIME_H */ +/*# define HAVE_UTIMES */ +/*# define HAVE_UTIME_H */ +/*# define HAVE_WAIT_H */ +/*# define HAVE_SYS_WAIT_H */ +/*# define HAVE_SYS_SYSTEMINFO_H */ +/*# define HAVE_SYS_UTSNAME_H */ +/*# define HAVE_SYS_PRIOCNTL_H */ +/*# define HAVE_SYS_RTPRIOCNTL_H */ +/*# define HAVE_SYS_MTIO_H */ +/*# define HAVE_MTGET_DSREG */ +/*# define HAVE_MTGET_RESID */ +/*# define HAVE_MTGET_FILENO */ +/*# define HAVE_MTGET_BLKNO */ +/*# define MAJOR_IN_MKDEV */ +/*# define MAJOR_IN_SYSMACROS */ +/*# define HAVE_USG_STDIO */ +/*# define HAVE_DTOA */ +/*# define HAVE_STRERROR */ +# define HAVE_MEMMOVE +/*# define HAVE_MMAP */ +/*# define HAVE_SMMAP */ +/*# define HAVE_USGSHM */ +/*# define HAVE_USGSEM */ +/*# define HAVE_MSEM */ +/*# define HAVE_LDSTUB */ +/*# define HAVE_XCHG */ +/*# define HAVE_FLOCK */ +/*# define HAVE_FCHDIR */ +/*# define HAVE_STATVFS */ +/*# define HAVE_QUOTA */ +/*# define HAVE_YP */ +/*# define HAVE_SHADOW */ +/*# define HAVE_SETREUID */ +/*# define HAVE_SETRESUID */ +/*# define HAVE_SETEUID */ +/*# define HAVE_LCHOWN */ +/*# define HAVE_PROCFS */ +/*# define HAVE_PROCFS2 */ +/*# define HAVE_SIGINFO */ +/*# define HAVE_WAIT3 */ +/*# define HAVE_WAITPID */ +/*# define HAVE_UNION_WAIT */ +# define HAVE_GETHOSTNAME +/*# define HAVE_STREAMS */ +/*# define HAVE_STRPTYS */ +/*# define HAVE_POLL */ +# define HAVE_SELECT +/*# define HAVE_TIRPC */ +/*# define GID_T gid_t */ +# define USLEEPRETURN_T uint +/*# define USLEEPRETURN_T void */ +/*# define USLEEPISVOID */ +/*# define HAVE_GETAV0 */ +/*# define HAVE_SCANSTACK */ +#endif + +/* + * Prototype for new systems + */ +#if defined(__NEW_SYSTEM_TO_DEFINE__) +# define PROTOTYPES +# define HAVE_OSDEF /* prevent later definitions to overwrite current */ +# define __NOT_SVR4__ /* Not a real SVR4 implementation */ + +# define HAVE_ELF +# define HAVE_COFF +# define HAVE_AOUT +# define HAVE_STDARG_H +# define HAVE_VA_COPY +# define HAVE__VA_COPY +# define HAVE_STDLIB_H +# define HAVE_STRING_H +# define HAVE_STRINGS_H +# define HAVE_STDC_HEADERS +# define STDC_HEADERS /* GNU name */ +# define HAVE_LONGLONG +# define HAVE_SIZE_T +# define NO_SIZE_T + +# define HAVE_UNISTD_H +# define HAVE_FCNTL_H +# define HAVE_DIRENT_H +# define HAVE_SYS_DIR_H +# define HAVE_NDIR_H +# define HAVE_MALLOC_H +# define HAVE_SYS_NDIR_H +# define HAVE_TERMIOS_H +# define HAVE_TERMIO_H +# define HAVE_SYS_TIME_H +# define HAVE_UTIMES +# define HAVE_UTIME_H +# define HAVE_WAIT_H +# define HAVE_SYS_WAIT_H +# define HAVE_SYS_PARAM_H +# define HAVE_SYS_SYSTEMINFO_H +# define HAVE_SYS_UTSNAME_H +# define HAVE_SYS_PRIOCNTL_H +# define HAVE_SYS_RTPRIOCNTL_H +# define HAVE_SYS_MTIO_H +# define HAVE_MTGET_DSREG +# define HAVE_MTGET_RESID +# define HAVE_MTGET_FILENO +# define HAVE_MTGET_BLKNO +# define MAJOR_IN_MKDEV +# define MAJOR_IN_SYSMACROS +# define HAVE_USG_STDIO +# define HAVE_BRK +# define HAVE_SBRK +# define HAVE_DTOA +# define HAVE_GETCWD +# define HAVE_STRERROR +# define HAVE_MEMMOVE +# define HAVE_MLOCKALL +# define HAVE_MMAP +# define HAVE_SMMAP +# define HAVE_USGSHM +# define HAVE_USGSEM +# define HAVE_MSEM +# define HAVE_LDSTUB +# define HAVE_XCHG +# define HAVE_FLOCK +# define HAVE_FCHDIR +# define HAVE_STATVFS +# define HAVE_QUOTA +# define HAVE_YP +# define HAVE_SHADOW +# define HAVE_SETREUID +# define HAVE_SETRESUID +# define HAVE_SETEUID +# define HAVE_LCHOWN +# define HAVE_PROCFS +# define HAVE_PROCFS2 +# define HAVE_SIGINFO +# define HAVE_WAIT3 +# define HAVE_WAITPID +# define HAVE_UNION_WAIT +# define HAVE_GETHOSTNAME +# define HAVE_STREAMS +# define HAVE_STRPTYS +# define HAVE_POLL +# define HAVE_SELECT +# define HAVE_TIRPC +# define GID_T gid_t +# define USLEEPRETURN_T unsigned int +# define USLEEPRETURN_T void +# define USLEEPISVOID + +# define HAVE_GETAV0 +# define HAVE_SCANSTACK +#endif /* __NEW_SYSTEM_TO_DEFINE__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _XMCONFIG_H */