├── .gitignore ├── COPYING ├── HEADER ├── Makefile ├── console-low.S ├── console.c ├── console.h ├── core-cia.h ├── core-typhoon.h ├── crb.c ├── hwrpb.h ├── init.c ├── ioport.h ├── memcpy.c ├── memset.c ├── osf.h ├── pal.S ├── pal.h ├── palcode.ld ├── pci.c ├── pci.h ├── pci_ids.h ├── pci_regs.h ├── printf.c ├── protos.h ├── ps2port.c ├── ps2port.h ├── strlen.S ├── sys-clipper.S ├── sys-clipper.h ├── sys-sx164.h ├── uart.c ├── uart.h ├── util.c ├── vgafonts.c ├── vgaio.c ├── vgatables.c └── vgatables.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | palcode-* 3 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /HEADER: -------------------------------------------------------------------------------- 1 | /* Short Description 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CROSS = alphaev67-linux- 2 | CC = $(CROSS)gcc 3 | LD = $(CROSS)ld 4 | 5 | CORE = typhoon 6 | SYSTEM = clipper 7 | 8 | ASFLAGS = -Wa,-m21264 -Wa,--noexecstack 9 | OPT= -O2 10 | CFLAGS = $(OPT) -g1 -Wall -fvisibility=hidden -fno-strict-aliasing \ 11 | -msmall-text -msmall-data -mno-fp-regs -mbuild-constants 12 | CPPFLAGS = -DSYSTEM_H='"sys-$(SYSTEM).h"' 13 | 14 | CFLAGS += -mcpu=ev67 15 | 16 | OBJS = pal.o sys-$(SYSTEM).o init.o crb.o uart.o console.o console-low.o \ 17 | ps2port.o pci.o vgaio.o vgatables.o vgafonts.o \ 18 | printf.o util.o memset.o memcpy.o strlen.o 19 | 20 | all: palcode-$(SYSTEM) 21 | 22 | palcode-$(SYSTEM): palcode.ld $(OBJS) 23 | $(LD) -relax -o $@ -T palcode.ld -Map $@.map $(OBJS) 24 | 25 | clean: 26 | rm -f *.o 27 | rm -f palcode-* 28 | 29 | pal.o: pal.S osf.h sys-$(SYSTEM).h core-$(CORE).h 30 | init.o: init.c protos.h hwrpb.h osf.h uart.h sys-$(SYSTEM).h core-$(CORE).h 31 | printf.o: printf.c uart.h 32 | uart.o: uart.c uart.h protos.h 33 | crb.o: crb.c hwrpb.h protos.h console.h uart.h 34 | console.o: console.c console.h protos.h 35 | pci.o: pci.c protos.h pci.h pci_regs.h 36 | -------------------------------------------------------------------------------- /console-low.S: -------------------------------------------------------------------------------- 1 | /* Assembly helper routines for the emulation SRM console. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | .set nomacro 22 | .set noat 23 | .text 24 | .cfi_sections .debug_frame 25 | 26 | #define SAVE_ALL_SIZE (18*8) 27 | 28 | .globl entInt 29 | .type entInt, @function 30 | .cfi_startproc simple 31 | entInt: 32 | .cfi_return_column 64 33 | .cfi_def_cfa $sp, 48 34 | .cfi_rel_offset 64, 8 35 | .cfi_rel_offset $gp, 16 36 | .cfi_rel_offset $16, 24 37 | .cfi_rel_offset $17, 32 38 | .cfi_rel_offset $18, 40 39 | lda $sp, -SAVE_ALL_SIZE($sp) 40 | .cfi_adjust_cfa_offset SAVE_ALL_SIZE 41 | stq $0, 0*8($sp) 42 | stq $1, 1*8($sp) 43 | stq $2, 2*8($sp) 44 | stq $3, 3*8($sp) 45 | stq $4, 4*8($sp) 46 | stq $5, 5*8($sp) 47 | stq $6, 6*8($sp) 48 | stq $7, 7*8($sp) 49 | stq $8, 9*8($sp) 50 | stq $19, 9*8($sp) 51 | stq $20, 10*8($sp) 52 | stq $21, 11*8($sp) 53 | stq $22, 12*8($sp) 54 | stq $23, 13*8($sp) 55 | stq $24, 14*8($sp) 56 | stq $25, 15*8($sp) 57 | stq $26, 16*8($sp) 58 | stq $27, 17*8($sp) 59 | stq $28, 18*8($sp) 60 | .cfi_rel_offset $0, 0*8 61 | .cfi_rel_offset $1, 1*8 62 | .cfi_rel_offset $2, 2*8 63 | .cfi_rel_offset $3, 3*8 64 | .cfi_rel_offset $4, 4*8 65 | .cfi_rel_offset $5, 5*8 66 | .cfi_rel_offset $6, 6*8 67 | .cfi_rel_offset $7, 7*8 68 | .cfi_rel_offset $8, 8*8 69 | .cfi_rel_offset $19, 9*8 70 | .cfi_rel_offset $20, 10*8 71 | .cfi_rel_offset $21, 11*8 72 | .cfi_rel_offset $22, 12*8 73 | .cfi_rel_offset $23, 13*8 74 | .cfi_rel_offset $24, 14*8 75 | .cfi_rel_offset $25, 15*8 76 | .cfi_rel_offset $26, 16*8 77 | .cfi_rel_offset $27, 17*8 78 | .cfi_rel_offset $28, 18*8 79 | 80 | bsr $26, do_entInt !samegp 81 | 82 | ldq $0, 0*8($sp) 83 | ldq $1, 1*8($sp) 84 | ldq $2, 2*8($sp) 85 | ldq $3, 3*8($sp) 86 | ldq $4, 4*8($sp) 87 | ldq $5, 5*8($sp) 88 | ldq $6, 6*8($sp) 89 | ldq $7, 7*8($sp) 90 | ldq $8, 9*8($sp) 91 | ldq $19, 9*8($sp) 92 | ldq $20, 10*8($sp) 93 | ldq $21, 11*8($sp) 94 | ldq $22, 12*8($sp) 95 | ldq $23, 13*8($sp) 96 | ldq $24, 14*8($sp) 97 | ldq $25, 15*8($sp) 98 | ldq $26, 16*8($sp) 99 | ldq $27, 17*8($sp) 100 | ldq $28, 18*8($sp) 101 | lda $sp, SAVE_ALL_SIZE($sp) 102 | .cfi_adjust_cfa_offset -SAVE_ALL_SIZE 103 | .cfi_restore $0 104 | .cfi_restore $1 105 | .cfi_restore $2 106 | .cfi_restore $3 107 | .cfi_restore $4 108 | .cfi_restore $5 109 | .cfi_restore $6 110 | .cfi_restore $7 111 | .cfi_restore $8 112 | .cfi_restore $19 113 | .cfi_restore $20 114 | .cfi_restore $21 115 | .cfi_restore $22 116 | .cfi_restore $23 117 | .cfi_restore $24 118 | .cfi_restore $25 119 | .cfi_restore $26 120 | .cfi_restore $27 121 | .cfi_restore $28 122 | 123 | call_pal 0x3f // rti 124 | 125 | .cfi_endproc 126 | .size entInt, . - entInt 127 | -------------------------------------------------------------------------------- /console.c: -------------------------------------------------------------------------------- 1 | /* The SRM console prompt. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #include "protos.h" 22 | #include "console.h" 23 | #include "vgatables.h" 24 | 25 | 26 | static void 27 | output_crnl(void) 28 | { 29 | crb_puts(0, "\r\n", 2); 30 | } 31 | 32 | static void 33 | output_bell(void) 34 | { 35 | crb_puts(0, "\a", 1); 36 | } 37 | 38 | static void 39 | backspace_and_erase(void) 40 | { 41 | crb_puts(0, "\b \b", 3); 42 | } 43 | 44 | static unsigned long 45 | getline(char *buf, unsigned long bufsize) 46 | { 47 | unsigned long len = 0; 48 | long c; 49 | 50 | while (1) 51 | { 52 | c = crb_getc(0); 53 | if (c < 0) 54 | continue; 55 | switch ((int)c) 56 | { 57 | case '\r': 58 | case '\n': 59 | output_crnl(); 60 | buf[len] = 0; 61 | return len; 62 | 63 | case '\b': 64 | case 0x7f: /* Delete */ 65 | if (len > 0) 66 | { 67 | backspace_and_erase(); 68 | len--; 69 | } 70 | else 71 | output_bell(); 72 | break; 73 | 74 | default: 75 | if (len + 1 < bufsize) 76 | { 77 | buf[len] = c; 78 | crb_puts(0, buf+len, 1); 79 | len++; 80 | } 81 | else 82 | output_bell(); 83 | break; 84 | } 85 | } 86 | } 87 | 88 | static inline void set_console_alarm(void) 89 | { 90 | /* Just set a new timeout for 10ms = 10M ns. */ 91 | set_alarm_rel(10 * 1000 * 1000); 92 | } 93 | 94 | void 95 | do_entInt(unsigned long type, unsigned long vector) 96 | { 97 | switch (type) 98 | { 99 | case 0: 100 | /* ??? SMP interrupt. We're going to need this for starting up 101 | secondary cpus. */ 102 | break; 103 | case 1: 104 | /* Timer interrupt. */ 105 | set_console_alarm(); 106 | break; 107 | case 2: 108 | /* ??? Device interrupt. We're going to need this for virtio disk 109 | operations at minimum. */ 110 | break; 111 | } 112 | } 113 | 114 | void 115 | do_console(void) 116 | { 117 | char line[256]; 118 | unsigned long len; 119 | 120 | wrkgp(); 121 | wrent(entInt, 0); 122 | set_console_alarm(); 123 | swpipl(0); 124 | 125 | if (have_vga) 126 | { 127 | unsigned short *vga, attr; 128 | vga = pci_mem_base + SEG_CTEXT *16; 129 | attr = 0x2000; 130 | vga[0] = 'H' + attr; 131 | vga[1] = 'e' + attr; 132 | vga[2] = 'l' + attr; 133 | vga[3] = 'l' + attr; 134 | vga[4] = 'o' + attr; 135 | } 136 | 137 | while (1) 138 | { 139 | crb_puts(0, ">>> ", 4); 140 | len = getline(line, sizeof(line)); 141 | crb_puts(0, "got: ", 5); 142 | crb_puts(0, line, len); 143 | output_crnl(); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /console.h: -------------------------------------------------------------------------------- 1 | /* Console Callback Routines. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #ifndef CONSOLE_H 22 | #define CONSOLE_H 1 23 | 24 | #define CRB_GETC 0x01 25 | #define CRB_PUTS 0x02 26 | #define CRB_RESET_TERM 0x03 27 | #define CRB_SET_TERM_INT 0x04 28 | #define CRB_SET_TERM_CTL 0x05 29 | #define CRB_PROCESS_KEYCODE 0x06 30 | 31 | #define CRB_OPEN 0x10 32 | #define CRB_CLOSE 0x11 33 | #define CRB_IOCTL 0x12 34 | #define CRB_READ 0x13 35 | #define CRB_WRITE 0x14 36 | 37 | #define CRB_SET_ENV 0x20 38 | #define CRB_RESET_ENV 0x21 39 | #define CRB_GET_ENV 0x22 40 | #define CRB_SAVE_ENV 0x23 41 | 42 | #define CRB_PSWITCH 0x30 43 | 44 | extern unsigned long crb_getc(long unit); 45 | extern unsigned long crb_process_keycode(long unit, long keycode, long again); 46 | extern unsigned long crb_puts(long unit, const char *buf, unsigned long length); 47 | extern unsigned long crb_reset_term(long unit); 48 | 49 | extern unsigned long crb_open(const char *devstr, unsigned long length); 50 | extern unsigned long crb_close(long channel); 51 | extern unsigned long crb_read(long channel, unsigned long length, 52 | char *buf, unsigned long block); 53 | extern unsigned long crb_write(long channel, unsigned long length, 54 | const char *buf, unsigned long block); 55 | 56 | extern unsigned long crb_get_env(unsigned long id, char *buf, 57 | unsigned long length); 58 | extern unsigned long crb_set_env(unsigned long id, const char *buf, 59 | unsigned long length); 60 | 61 | #endif /* CONSOLE_H */ 62 | -------------------------------------------------------------------------------- /core-cia.h: -------------------------------------------------------------------------------- 1 | /* Memory layout and register descriptions for the CIA/PYXIS chipset. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #ifndef CIA_H 22 | #define CIA_H 23 | 24 | #define IDENT_ADDR 0xfffffc0000000000UL 25 | 26 | #define CIA_MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */ 27 | #define CIA_MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */ 28 | #define CIA_MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */ 29 | 30 | /* 31 | * 21171-CA Control and Status Registers 32 | */ 33 | #define CIA_IOC_CIA_REV (IDENT_ADDR + 0x8740000080UL) 34 | # define CIA_REV_MASK 0xff 35 | #define CIA_IOC_PCI_LAT (IDENT_ADDR + 0x87400000C0UL) 36 | #define CIA_IOC_CIA_CTRL (IDENT_ADDR + 0x8740000100UL) 37 | # define CIA_CTRL_PCI_EN (1 << 0) 38 | # define CIA_CTRL_PCI_LOCK_EN (1 << 1) 39 | # define CIA_CTRL_PCI_LOOP_EN (1 << 2) 40 | # define CIA_CTRL_FST_BB_EN (1 << 3) 41 | # define CIA_CTRL_PCI_MST_EN (1 << 4) 42 | # define CIA_CTRL_PCI_MEM_EN (1 << 5) 43 | # define CIA_CTRL_PCI_REQ64_EN (1 << 6) 44 | # define CIA_CTRL_PCI_ACK64_EN (1 << 7) 45 | # define CIA_CTRL_ADDR_PE_EN (1 << 8) 46 | # define CIA_CTRL_PERR_EN (1 << 9) 47 | # define CIA_CTRL_FILL_ERR_EN (1 << 10) 48 | # define CIA_CTRL_MCHK_ERR_EN (1 << 11) 49 | # define CIA_CTRL_ECC_CHK_EN (1 << 12) 50 | # define CIA_CTRL_ASSERT_IDLE_BC (1 << 13) 51 | # define CIA_CTRL_COM_IDLE_BC (1 << 14) 52 | # define CIA_CTRL_CSR_IOA_BYPASS (1 << 15) 53 | # define CIA_CTRL_IO_FLUSHREQ_EN (1 << 16) 54 | # define CIA_CTRL_CPU_FLUSHREQ_EN (1 << 17) 55 | # define CIA_CTRL_ARB_CPU_EN (1 << 18) 56 | # define CIA_CTRL_EN_ARB_LINK (1 << 19) 57 | # define CIA_CTRL_RD_TYPE_SHIFT 20 58 | # define CIA_CTRL_RL_TYPE_SHIFT 24 59 | # define CIA_CTRL_RM_TYPE_SHIFT 28 60 | # define CIA_CTRL_EN_DMA_RD_PERF (1 << 31) 61 | #define CIA_IOC_CIA_CNFG (IDENT_ADDR + 0x8740000140UL) 62 | # define CIA_CNFG_IOA_BWEN (1 << 0) 63 | # define CIA_CNFG_PCI_MWEN (1 << 4) 64 | # define CIA_CNFG_PCI_DWEN (1 << 5) 65 | # define CIA_CNFG_PCI_WLEN (1 << 8) 66 | #define CIA_IOC_FLASH_CTRL (IDENT_ADDR + 0x8740000200UL) 67 | #define CIA_IOC_HAE_MEM (IDENT_ADDR + 0x8740000400UL) 68 | #define CIA_IOC_HAE_IO (IDENT_ADDR + 0x8740000440UL) 69 | #define CIA_IOC_CFG (IDENT_ADDR + 0x8740000480UL) 70 | #define CIA_IOC_CACK_EN (IDENT_ADDR + 0x8740000600UL) 71 | # define CIA_CACK_EN_LOCK_EN (1 << 0) 72 | # define CIA_CACK_EN_MB_EN (1 << 1) 73 | # define CIA_CACK_EN_SET_DIRTY_EN (1 << 2) 74 | # define CIA_CACK_EN_BC_VICTIM_EN (1 << 3) 75 | 76 | 77 | /* 78 | * 21171-CA Diagnostic Registers 79 | */ 80 | #define CIA_IOC_CIA_DIAG (IDENT_ADDR + 0x8740002000UL) 81 | #define CIA_IOC_DIAG_CHECK (IDENT_ADDR + 0x8740003000UL) 82 | 83 | /* 84 | * 21171-CA Performance Monitor registers 85 | */ 86 | #define CIA_IOC_PERF_MONITOR (IDENT_ADDR + 0x8740004000UL) 87 | #define CIA_IOC_PERF_CONTROL (IDENT_ADDR + 0x8740004040UL) 88 | 89 | /* 90 | * 21171-CA Error registers 91 | */ 92 | #define CIA_IOC_CPU_ERR0 (IDENT_ADDR + 0x8740008000UL) 93 | #define CIA_IOC_CPU_ERR1 (IDENT_ADDR + 0x8740008040UL) 94 | #define CIA_IOC_CIA_ERR (IDENT_ADDR + 0x8740008200UL) 95 | # define CIA_ERR_COR_ERR (1 << 0) 96 | # define CIA_ERR_UN_COR_ERR (1 << 1) 97 | # define CIA_ERR_CPU_PE (1 << 2) 98 | # define CIA_ERR_MEM_NEM (1 << 3) 99 | # define CIA_ERR_PCI_SERR (1 << 4) 100 | # define CIA_ERR_PERR (1 << 5) 101 | # define CIA_ERR_PCI_ADDR_PE (1 << 6) 102 | # define CIA_ERR_RCVD_MAS_ABT (1 << 7) 103 | # define CIA_ERR_RCVD_TAR_ABT (1 << 8) 104 | # define CIA_ERR_PA_PTE_INV (1 << 9) 105 | # define CIA_ERR_FROM_WRT_ERR (1 << 10) 106 | # define CIA_ERR_IOA_TIMEOUT (1 << 11) 107 | # define CIA_ERR_LOST_CORR_ERR (1 << 16) 108 | # define CIA_ERR_LOST_UN_CORR_ERR (1 << 17) 109 | # define CIA_ERR_LOST_CPU_PE (1 << 18) 110 | # define CIA_ERR_LOST_MEM_NEM (1 << 19) 111 | # define CIA_ERR_LOST_PERR (1 << 21) 112 | # define CIA_ERR_LOST_PCI_ADDR_PE (1 << 22) 113 | # define CIA_ERR_LOST_RCVD_MAS_ABT (1 << 23) 114 | # define CIA_ERR_LOST_RCVD_TAR_ABT (1 << 24) 115 | # define CIA_ERR_LOST_PA_PTE_INV (1 << 25) 116 | # define CIA_ERR_LOST_FROM_WRT_ERR (1 << 26) 117 | # define CIA_ERR_LOST_IOA_TIMEOUT (1 << 27) 118 | # define CIA_ERR_VALID (1 << 31) 119 | #define CIA_IOC_CIA_STAT (IDENT_ADDR + 0x8740008240UL) 120 | #define CIA_IOC_ERR_MASK (IDENT_ADDR + 0x8740008280UL) 121 | #define CIA_IOC_CIA_SYN (IDENT_ADDR + 0x8740008300UL) 122 | #define CIA_IOC_MEM_ERR0 (IDENT_ADDR + 0x8740008400UL) 123 | #define CIA_IOC_MEM_ERR1 (IDENT_ADDR + 0x8740008440UL) 124 | #define CIA_IOC_PCI_ERR0 (IDENT_ADDR + 0x8740008800UL) 125 | #define CIA_IOC_PCI_ERR1 (IDENT_ADDR + 0x8740008840UL) 126 | #define CIA_IOC_PCI_ERR3 (IDENT_ADDR + 0x8740008880UL) 127 | 128 | /* 129 | * 21171-CA System configuration registers 130 | */ 131 | #define CIA_IOC_MCR (IDENT_ADDR + 0x8750000000UL) 132 | #define CIA_IOC_MBA0 (IDENT_ADDR + 0x8750000600UL) 133 | #define CIA_IOC_MBA2 (IDENT_ADDR + 0x8750000680UL) 134 | #define CIA_IOC_MBA4 (IDENT_ADDR + 0x8750000700UL) 135 | #define CIA_IOC_MBA6 (IDENT_ADDR + 0x8750000780UL) 136 | #define CIA_IOC_MBA8 (IDENT_ADDR + 0x8750000800UL) 137 | #define CIA_IOC_MBAA (IDENT_ADDR + 0x8750000880UL) 138 | #define CIA_IOC_MBAC (IDENT_ADDR + 0x8750000900UL) 139 | #define CIA_IOC_MBAE (IDENT_ADDR + 0x8750000980UL) 140 | #define CIA_IOC_TMG0 (IDENT_ADDR + 0x8750000B00UL) 141 | #define CIA_IOC_TMG1 (IDENT_ADDR + 0x8750000B40UL) 142 | #define CIA_IOC_TMG2 (IDENT_ADDR + 0x8750000B80UL) 143 | 144 | /* 145 | * 2117A-CA PCI Address and Scatter-Gather Registers. 146 | */ 147 | #define CIA_IOC_PCI_TBIA (IDENT_ADDR + 0x8760000100UL) 148 | 149 | #define CIA_IOC_PCI_W0_BASE (IDENT_ADDR + 0x8760000400UL) 150 | #define CIA_IOC_PCI_W0_MASK (IDENT_ADDR + 0x8760000440UL) 151 | #define CIA_IOC_PCI_T0_BASE (IDENT_ADDR + 0x8760000480UL) 152 | 153 | #define CIA_IOC_PCI_W1_BASE (IDENT_ADDR + 0x8760000500UL) 154 | #define CIA_IOC_PCI_W1_MASK (IDENT_ADDR + 0x8760000540UL) 155 | #define CIA_IOC_PCI_T1_BASE (IDENT_ADDR + 0x8760000580UL) 156 | 157 | #define CIA_IOC_PCI_W2_BASE (IDENT_ADDR + 0x8760000600UL) 158 | #define CIA_IOC_PCI_W2_MASK (IDENT_ADDR + 0x8760000640UL) 159 | #define CIA_IOC_PCI_T2_BASE (IDENT_ADDR + 0x8760000680UL) 160 | 161 | #define CIA_IOC_PCI_W3_BASE (IDENT_ADDR + 0x8760000700UL) 162 | #define CIA_IOC_PCI_W3_MASK (IDENT_ADDR + 0x8760000740UL) 163 | #define CIA_IOC_PCI_T3_BASE (IDENT_ADDR + 0x8760000780UL) 164 | 165 | #define CIA_IOC_PCI_Wn_BASE(N) (IDENT_ADDR + 0x8760000400UL + (N)*0x100) 166 | #define CIA_IOC_PCI_Wn_MASK(N) (IDENT_ADDR + 0x8760000440UL + (N)*0x100) 167 | #define CIA_IOC_PCI_Tn_BASE(N) (IDENT_ADDR + 0x8760000480UL + (N)*0x100) 168 | 169 | #define CIA_IOC_PCI_W_DAC (IDENT_ADDR + 0x87600007C0UL) 170 | 171 | /* 172 | * 2117A-CA Address Translation Registers. 173 | */ 174 | 175 | /* 8 tag registers, the first 4 of which are lockable. */ 176 | #define CIA_IOC_TB_TAGn(n) \ 177 | (IDENT_ADDR + 0x8760000800UL + (n)*0x40) 178 | 179 | /* 4 page registers per tag register. */ 180 | #define CIA_IOC_TBn_PAGEm(n,m) \ 181 | (IDENT_ADDR + 0x8760001000UL + (n)*0x100 + (m)*0x40) 182 | 183 | /* 184 | * Memory spaces: 185 | */ 186 | #define CIA_IACK_SC (IDENT_ADDR + 0x8720000000UL) 187 | #define CIA_CONF (IDENT_ADDR + 0x8700000000UL) 188 | #define CIA_IO (IDENT_ADDR + 0x8580000000UL) 189 | #define CIA_SPARSE_MEM (IDENT_ADDR + 0x8000000000UL) 190 | #define CIA_SPARSE_MEM_R2 (IDENT_ADDR + 0x8400000000UL) 191 | #define CIA_SPARSE_MEM_R3 (IDENT_ADDR + 0x8500000000UL) 192 | #define CIA_DENSE_MEM (IDENT_ADDR + 0x8600000000UL) 193 | #define CIA_BW_MEM (IDENT_ADDR + 0x8800000000UL) 194 | #define CIA_BW_IO (IDENT_ADDR + 0x8900000000UL) 195 | #define CIA_BW_CFG_0 (IDENT_ADDR + 0x8a00000000UL) 196 | #define CIA_BW_CFG_1 (IDENT_ADDR + 0x8b00000000UL) 197 | 198 | /* 199 | * ALCOR's GRU ASIC registers 200 | */ 201 | #define GRU_INT_REQ (IDENT_ADDR + 0x8780000000UL) 202 | #define GRU_INT_MASK (IDENT_ADDR + 0x8780000040UL) 203 | #define GRU_INT_EDGE (IDENT_ADDR + 0x8780000080UL) 204 | #define GRU_INT_HILO (IDENT_ADDR + 0x87800000C0UL) 205 | #define GRU_INT_CLEAR (IDENT_ADDR + 0x8780000100UL) 206 | 207 | #define GRU_CACHE_CNFG (IDENT_ADDR + 0x8780000200UL) 208 | #define GRU_SCR (IDENT_ADDR + 0x8780000300UL) 209 | #define GRU_LED (IDENT_ADDR + 0x8780000800UL) 210 | #define GRU_RESET (IDENT_ADDR + 0x8780000900UL) 211 | 212 | #define ALCOR_GRU_INT_REQ_BITS 0x800fffffUL 213 | #define XLT_GRU_INT_REQ_BITS 0x80003fffUL 214 | #define GRU_INT_REQ_BITS (alpha_mv.sys.cia.gru_int_req_bits+0) 215 | 216 | /* 217 | * PYXIS interrupt control registers 218 | */ 219 | #define PYXIS_INT_REQ (IDENT_ADDR + 0x87A0000000UL) 220 | #define PYXIS_INT_MASK (IDENT_ADDR + 0x87A0000040UL) 221 | #define PYXIS_INT_HILO (IDENT_ADDR + 0x87A00000C0UL) 222 | #define PYXIS_INT_ROUTE (IDENT_ADDR + 0x87A0000140UL) 223 | #define PYXIS_GPO (IDENT_ADDR + 0x87A0000180UL) 224 | #define PYXIS_INT_CNFG (IDENT_ADDR + 0x87A00001C0UL) 225 | #define PYXIS_RT_COUNT (IDENT_ADDR + 0x87A0000200UL) 226 | #define PYXIS_INT_TIME (IDENT_ADDR + 0x87A0000240UL) 227 | #define PYXIS_IIC_CTRL (IDENT_ADDR + 0x87A00002C0UL) 228 | #define PYXIS_RESET (IDENT_ADDR + 0x8780000900UL) 229 | 230 | /* Offset between ram physical addresses and pci64 DAC bus addresses. */ 231 | #define PYXIS_DAC_OFFSET (1UL << 40) 232 | 233 | #ifdef __ASSEMBLER__ 234 | 235 | /* Unfortunately, GAS doesn't attempt any interesting constructions of 236 | 64-bit constants, dropping them all into the .lit8 section. It is 237 | better for us to build these by hand. */ 238 | .macro LOAD_PHYS_PYXIS_INT ret 239 | lda \ret, 0x87a 240 | sll \ret, 28, \ret 241 | .endm 242 | 243 | .macro LOAD_KSEG_PCI_IO ret 244 | lda \ret, -887 245 | sll \ret, 32, \ret 246 | .endm 247 | 248 | .macro SYS_WHAMI ret 249 | mov 0, \ret 250 | .endm 251 | 252 | .macro SYS_ACK_SMP t0, t1, t2 253 | br MchkBugCheck 254 | .endm 255 | 256 | #else 257 | 258 | static inline unsigned long inb(unsigned long port) 259 | { 260 | return *(volatile unsigned char *)(CIA_BW_IO + port); 261 | } 262 | 263 | static inline void outb(unsigned long port, unsigned char val) 264 | { 265 | *(volatile unsigned char *)(CIA_BW_IO + port) = val; 266 | } 267 | 268 | 269 | #endif 270 | 271 | #endif /* CIA_H */ 272 | -------------------------------------------------------------------------------- /core-typhoon.h: -------------------------------------------------------------------------------- 1 | /* Memory layout and register descriptions for the TSUNAMI/TYPHOON chipset. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #ifndef TYPHOON_H 22 | #define TYPHOON_H 1 23 | 24 | /* Assume a 43-bit KSEG for now. */ 25 | #define PIO_PHYS_ADDR 0x80000000000 26 | #define PIO_KSEG_ADDR (0xfffffc0000000000 + 0x10000000000) 27 | 28 | /* CCHIP REGISTERS */ 29 | 30 | #define TYPHOON_CCHIP 0x1a0000000 31 | 32 | #define TYPHOON_CCHIP_CSC 0x0000 33 | #define TYPHOON_CCHIP_MTR 0x0040 34 | #define TYPHOON_CCHIP_MISC 0x0080 35 | #define TYPHOON_CCHIP_MPD 0x00c0 36 | #define TYPHOON_CCHIP_AAR0 0x0100 37 | #define TYPHOON_CCHIP_AAR1 0x0140 38 | #define TYPHOON_CCHIP_AAR2 0x0180 39 | #define TYPHOON_CCHIP_AAR3 0x01c0 40 | #define TYPHOON_CCHIP_DIM0 0x0200 41 | #define TYPHOON_CCHIP_DIM1 0x0240 42 | #define TYPHOON_CCHIP_DIR0 0x0280 43 | #define TYPHOON_CCHIP_DIR1 0x02c0 44 | #define TYPHOON_CCHIP_DRIR 0x0300 45 | #define TYPHOON_CCHIP_PRBEN 0x0340 46 | #define TYPHOON_CCHIP_IIC0 0x0380 47 | #define TYPHOON_CCHIP_IIC1 0x03c0 48 | #define TYPHOON_CCHIP_MPR0 0x0400 49 | #define TYPHOON_CCHIP_MPR1 0x0440 50 | #define TYPHOON_CCHIP_MPR2 0x0480 51 | #define TYPHOON_CCHIP_MPR3 0x04c0 52 | #define TYPHOON_CCHIP_TTR 0x0580 53 | #define TYPHOON_CCHIP_TDR 0x05c0 54 | #define TYPHOON_CCHIP_DIM2 0x0600 55 | #define TYPHOON_CCHIP_DIM3 0x0640 56 | #define TYPHOON_CCHIP_DIR2 0x0680 57 | #define TYPHOON_CCHIP_DIR3 0x06c0 58 | #define TYPHOON_CCHIP_IIC2 0x0700 59 | #define TYPHOON_CCHIP_IIC3 0x0740 60 | #define TYPHOON_CCHIP_PWR 0x0780 61 | #define TYPHOON_CCHIP_CMONCTLA 0x0c00 62 | #define TYPHOON_CCHIP_CMONCTLB 0x0c40 63 | #define TYPHOON_CCHIP_CMONCNT01 0x0c80 64 | #define TYPHOON_CCHIP_CMONCNT23 0x0cc0 65 | 66 | /* DCHIP REGISTERS */ 67 | 68 | #define TYPHOON_DCHIP 0x1b0000000 69 | 70 | #define TYPHOON_DCHIP_DSC 0x0800 71 | #define TYPHOON_DCHIP_STR 0x0840 72 | #define TYPHOON_DCHIP_DREV 0x0880 73 | #define TYPHOON_DCHIP_DSC2 0x08c0 74 | 75 | /* PCHIP REGISTERS */ 76 | 77 | #define TYPHOON_PCHIP0 0x180000000 78 | #define TYPHOON_PCHIP1 0x380000000 79 | 80 | #define TYPHOON_PCHIP_WSBA0 0x0000 81 | #define TYPHOON_PCHIP_WSBA1 0x0040 82 | #define TYPHOON_PCHIP_WSBA2 0x0080 83 | #define TYPHOON_PCHIP_WSBA3 0x00c0 84 | #define TYPHOON_PCHIP_WSM0 0x0100 85 | #define TYPHOON_PCHIP_WSM1 0x0140 86 | #define TYPHOON_PCHIP_WSM2 0x0180 87 | #define TYPHOON_PCHIP_WSM3 0x01c0 88 | #define TYPHOON_PCHIP_TBA0 0x0200 89 | #define TYPHOON_PCHIP_TBA1 0x0240 90 | #define TYPHOON_PCHIP_TBA2 0x0280 91 | #define TYPHOON_PCHIP_TBA3 0x02c0 92 | #define TYPHOON_PCHIP_PCTL 0x0300 93 | #define TYPHOON_PCHIP_PLAT 0x0340 94 | #define TYPHOON_PCHIP_PERROR 0x03c0 95 | #define TYPHOON_PCHIP_PERRMASK 0x0400 96 | #define TYPHOON_PCHIP_PERRSET 0x0440 97 | #define TYPHOON_PCHIP_TLBIV 0x0480 98 | #define TYPHOON_PCHIP_TLBIA 0x04c0 99 | #define TYPHOON_PCHIP_PMONCTL 0x0500 100 | #define TYPHOON_PCHIP_PMONCNT 0x0540 101 | #define TYPHOON_PCHIP_SPRST 0x0800 102 | 103 | /* PCI ADDRESSES */ 104 | 105 | #define TYPHOON_PCHIP0_PCI_MEM 0 106 | #define TYPHOON_PCHIP0_PCI_IO 0x1fc000000 107 | #define TYPHOON_PCHIP0_PCI_CONF 0x1fe000000 108 | #define TYPHOON_PCHIP0_PCI_IACK 0x1f8000000 109 | 110 | #ifdef __ASSEMBLER__ 111 | 112 | #include "pal.h" 113 | 114 | #define ptCpuDIR ptSys0 115 | #define ptCpuIIC ptSys1 116 | 117 | /* Unfortunately, GAS doesn't attempt any interesting constructions of 118 | 64-bit constants, dropping them all into the .lit8 section. It is 119 | better for us to build these by hand. */ 120 | .macro LOAD_PHYS_CCHIP ret 121 | lda \ret, (PIO_PHYS_ADDR + TYPHOON_CCHIP) >> 29 122 | sll \ret, 29, \ret 123 | .endm 124 | 125 | .macro LOAD_PHYS_PCHIP0 ret 126 | lda \ret, (PIO_PHYS_ADDR + TYPHOON_PCHIP0) >> 29 127 | sll \ret, 29, \ret 128 | .endm 129 | 130 | .macro LOAD_PHYS_PCHIP0_IACK ret 131 | .set macro 132 | lda \ret, (PIO_PHYS_ADDR + TYPHOON_PCHIP0_PCI_IACK) >> 24 133 | .set nomacro 134 | sll \ret, 24, \ret 135 | .endm 136 | 137 | .macro LOAD_KSEG_PCI_IO ret 138 | .set macro 139 | // Note that GAS shifts are logical. Force arithmetic shift style 140 | // results by negating before and after the shift. 141 | lda \ret, -(-(PIO_KSEG_ADDR + TYPHOON_PCHIP0_PCI_IO) >> 20) 142 | .set nomacro 143 | sll \ret, 20, \ret 144 | .endm 145 | 146 | .macro LOAD_KSEG_PCI_CONF ret 147 | .set macro 148 | // Note that GAS shifts are logical. Force arithmetic shift style 149 | // results by negating before and after the shift. 150 | lda \ret, -(-(PIO_KSEG_ADDR + TYPHOON_PCHIP0_PCI_CONF) >> 20) 151 | .set nomacro 152 | sll \ret, 20, \ret 153 | .endm 154 | 155 | .macro SYS_WHAMI ret 156 | LOAD_PHYS_CCHIP \ret 157 | ldq_p \ret, TYPHOON_CCHIP_MISC(\ret) 158 | and \ret, 3, \ret 159 | .endm 160 | 161 | /* ACK the Interprocessor Interrupt. */ 162 | .macro SYS_ACK_SMP t0, t1, t2 163 | LOAD_PHYS_CCHIP \t0 164 | ldq_p \t1, TYPHOON_CCHIP_MISC(\t0) 165 | and \t1, 3, \t1 166 | addq \t1, 8, \t1 167 | lda \t2, 1 168 | sll \t2, \t1, \t2 169 | stq_p \t2, TYPHOON_CCHIP_MISC(\t0) 170 | .endm 171 | 172 | /* ACK the Clock Interrupt. */ 173 | .macro SYS_ACK_CLK t0, t1, t2 174 | LOAD_PHYS_CCHIP \t0 175 | ldq_p \t1, TYPHOON_CCHIP_MISC(\t0) 176 | and \t1, 3, \t1 177 | addq \t1, 4, \t1 178 | lda \t2, 1 179 | sll \t2, \t1, \t2 180 | stq_p \t2, TYPHOON_CCHIP_MISC(\t0) 181 | .endm 182 | 183 | /* Interrupt another CPU. */ 184 | .macro SYS_WRIPIR target, t0, t1, t2 185 | LOAD_PHYS_CCHIP \t0 186 | mov 1, \t1 187 | and \target, 3, \t2 188 | addq \t2, 12, \t2 189 | sll \t1, \t2, \t1 190 | stq_p \t1, TYPHOON_CCHIP_MISC(\t0) 191 | .endm 192 | 193 | #endif /* ASSEMBLER */ 194 | #endif /* TYPHOON_H */ 195 | -------------------------------------------------------------------------------- /crb.c: -------------------------------------------------------------------------------- 1 | /* Console Callback Routines. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #include "hwrpb.h" 22 | #include "protos.h" 23 | #include "console.h" 24 | #include "uart.h" 25 | 26 | 27 | /* All routines use the high bit to signal error. */ 28 | #define ERR 0x8000000000000000ul 29 | 30 | 31 | unsigned long 32 | crb_getc(long unit) 33 | { 34 | /* Multiple consoles not yet supported. */ 35 | if (unit != 0) 36 | return ERR; 37 | 38 | return uart_getchar(COM1); 39 | } 40 | 41 | unsigned long 42 | crb_process_keycode(long unit, long keycode, long again) 43 | { 44 | /* This routine might be needed for real keyboards, and mostly for 45 | internationalization stuff. */ 46 | /* Return Failure: routine not supported. */ 47 | return 0xc000000000000000ul; 48 | } 49 | 50 | unsigned long 51 | crb_puts(long unit, const char *buf, unsigned long length) 52 | { 53 | unsigned int orig_length = length; 54 | 55 | /* Multiple consoles not yet supported. */ 56 | if (unit != 0) 57 | return ERR; 58 | 59 | for (; length != 0; --length, ++buf) 60 | uart_putchar_raw(COM1, (unsigned char)*buf); 61 | 62 | /* Bits <31:0> of the return value are the number of bytes written. 63 | To me that implies that the input value must be 32-bit, but v2 64 | of the ARM doesn't explicitly say. */ 65 | return orig_length; 66 | } 67 | 68 | unsigned long 69 | crb_reset_term(long unit) 70 | { 71 | /* Multiple consoles not yet supported. */ 72 | if (unit != 0) 73 | return ERR; 74 | 75 | uart_init_line(COM1, 9600); 76 | return 0; 77 | } 78 | 79 | static unsigned long 80 | crb_set_term_ctl(long unit, long ctb) 81 | { 82 | /* ??? The contents of the CTB do not seem to be defined anywhere. 83 | How, therefore, can the user set new contents? */ 84 | return ERR; 85 | } 86 | 87 | static unsigned long 88 | crb_set_term_int(long unit, long mask) 89 | { 90 | /* We do no buffering, therefore we don't need to support interrupts. */ 91 | if (unit != 0 || (mask & 0x22) != 0) 92 | return ERR; 93 | return 0; 94 | } 95 | 96 | unsigned long 97 | crb_open(const char *devstr, unsigned long length) 98 | { 99 | /* FIXME */ 100 | return ERR; 101 | } 102 | 103 | unsigned long 104 | crb_close(long channel) 105 | { 106 | /* FIXME */ 107 | return 0; 108 | } 109 | 110 | static unsigned long 111 | crb_ioctl(long channel) 112 | { 113 | /* We do not, nor will not, support virtual tapes. */ 114 | return ERR; 115 | } 116 | 117 | unsigned long 118 | crb_read(long channel, unsigned long length, char *buf, unsigned long block) 119 | { 120 | /* FIXME */ 121 | return ERR; 122 | } 123 | 124 | unsigned long 125 | crb_write(long channel, unsigned long length, const char *buf, 126 | unsigned long block) 127 | { 128 | /* FIXME */ 129 | return ERR; 130 | } 131 | 132 | unsigned long 133 | crb_get_env(unsigned long id, char *buf, unsigned long length) 134 | { 135 | /* FIXME */ 136 | return 0xc000000000000000ul; 137 | } 138 | 139 | unsigned long 140 | crb_set_env(unsigned long id, const char *buf, unsigned long length) 141 | { 142 | /* FIXME */ 143 | return 0xc000000000000000ul; 144 | } 145 | 146 | static unsigned long 147 | crb_reset_env(unsigned long id, char *buf, unsigned long length) 148 | { 149 | /* FIXME */ 150 | return 0xc000000000000000ul; 151 | } 152 | 153 | static unsigned long 154 | crb_save_env(void) 155 | { 156 | /* FIXME */ 157 | return 0xc000000000000000ul; 158 | } 159 | 160 | static unsigned long 161 | crb_pswitch(long action, long cpu_id) 162 | { 163 | /* Why would we ever need to support switching primary processor? */ 164 | return ERR; 165 | } 166 | 167 | static unsigned long __attribute__((used)) 168 | int_crb_dispatch(long select, long a1, long a2, long a3, long a4) 169 | { 170 | switch (select) 171 | { 172 | case CRB_GETC: 173 | return crb_getc(a1); 174 | case CRB_PUTS: 175 | return crb_puts(a1, (const char *)a2, a3); 176 | case CRB_RESET_TERM: 177 | return crb_reset_term(a1); 178 | case CRB_SET_TERM_INT: 179 | return crb_set_term_int(a1, a2); 180 | case CRB_SET_TERM_CTL: 181 | return crb_set_term_ctl(a1, a2); 182 | case CRB_PROCESS_KEYCODE: 183 | return crb_process_keycode(a1, a2, a3); 184 | 185 | case CRB_OPEN: 186 | return crb_open((const char*)a1, a2); 187 | case CRB_CLOSE: 188 | return crb_close(a1); 189 | case CRB_IOCTL: 190 | return crb_ioctl(a1); 191 | case CRB_READ: 192 | return crb_read(a1, a2, (char *)a3, a4); 193 | case CRB_WRITE: 194 | return crb_write(a1, a2, (const char *)a3, a4); 195 | 196 | case CRB_SET_ENV: 197 | return crb_set_env(a1, (const char *)a2, a3); 198 | case CRB_RESET_ENV: 199 | return crb_reset_env(a1, (char *)a2, a3); 200 | case CRB_GET_ENV: 201 | return crb_get_env(a1, (char *)a2, a3); 202 | case CRB_SAVE_ENV: 203 | return crb_save_env(); 204 | 205 | case CRB_PSWITCH: 206 | return crb_pswitch(a1, a2); 207 | } 208 | return ERR; 209 | } 210 | 211 | static unsigned long __attribute__((used)) 212 | int_crb_fixup(unsigned long vptptr, unsigned long hwrpb) 213 | { 214 | /* Given that this console is written to use the KSEG, and not be 215 | mapped into any page-table address space, it doesn't seem like 216 | we need to do anything at all here. */ 217 | return 0; 218 | } 219 | 220 | /* The CRB DISPATCH and FIXUP functions are defined to use the VMS 221 | calling convention. This has several effects: 222 | (1) The set of call-saved registers is different. 223 | (2) $27 contains the procdesc_struct, not the called function. 224 | Map between the two calling conventions here. */ 225 | 226 | asm(".macro VMStoUNIX name\n" 227 | " .globl \\name\n" 228 | " .ent \\name\n" 229 | "\\name:\n" 230 | " .frame $sp, 64, $26, 0\n" 231 | " subq $sp, 64, $sp\n" 232 | " stq $26, 0($sp)\n" 233 | " stq $2, 8($sp)\n" 234 | " stq $3, 16($sp)\n" 235 | " stq $4, 24($sp)\n" 236 | " stq $5, 32($sp)\n" 237 | " stq $6, 40($sp)\n" 238 | " stq $7, 48($sp)\n" 239 | " stq $8, 56($sp)\n" 240 | " .mask 0x40001fc, 0\n" 241 | " .prologue 2\n" 242 | " br $gp, .+4\n" 243 | " ldgp $gp, 0($gp)\n" 244 | " bsr $26, int_\\name !samegp\n" 245 | " ldq $26, 0($sp)\n" 246 | " ldq $2, 8($sp)\n" 247 | " ldq $3, 16($sp)\n" 248 | " ldq $4, 24($sp)\n" 249 | " ldq $5, 32($sp)\n" 250 | " ldq $6, 40($sp)\n" 251 | " ldq $7, 48($sp)\n" 252 | " ldq $8, 56($sp)\n" 253 | " addq $sp, 64, $sp\n" 254 | " ret\n" 255 | " .end \\name\n" 256 | ".endm\n" 257 | " VMStoUNIX crb_dispatch\n" 258 | " VMStoUNIX crb_fixup\n" 259 | ); 260 | -------------------------------------------------------------------------------- /hwrpb.h: -------------------------------------------------------------------------------- 1 | /* Layout and contents of the HardWare Resource Parameter Block (HWRPB). 2 | 3 | This file is copied intact from the Linux kernel. As such, it is 4 | covered by the GNU General Public License, v2.0. 5 | 6 | You should have received a copy of the GNU General Public License 7 | along with this program; see the file COPYING. If not see 8 | . */ 9 | 10 | #ifndef __ALPHA_HWRPB_H 11 | #define __ALPHA_HWRPB_H 12 | 13 | #define INIT_HWRPB ((struct hwrpb_struct *) 0x10000000) 14 | 15 | /* 16 | * DEC processor types for Alpha systems. Found in HWRPB. 17 | * These values are architected. 18 | */ 19 | 20 | #define EV3_CPU 1 /* EV3 */ 21 | #define EV4_CPU 2 /* EV4 (21064) */ 22 | #define LCA4_CPU 4 /* LCA4 (21066/21068) */ 23 | #define EV5_CPU 5 /* EV5 (21164) */ 24 | #define EV45_CPU 6 /* EV4.5 (21064/xxx) */ 25 | #define EV56_CPU 7 /* EV5.6 (21164) */ 26 | #define EV6_CPU 8 /* EV6 (21264) */ 27 | #define PCA56_CPU 9 /* PCA56 (21164PC) */ 28 | #define PCA57_CPU 10 /* PCA57 (notyet) */ 29 | #define EV67_CPU 11 /* EV67 (21264A) */ 30 | #define EV68CB_CPU 12 /* EV68CB (21264C) */ 31 | #define EV68AL_CPU 13 /* EV68AL (21264B) */ 32 | #define EV68CX_CPU 14 /* EV68CX (21264D) */ 33 | #define EV7_CPU 15 /* EV7 (21364) */ 34 | #define EV79_CPU 16 /* EV79 (21364??) */ 35 | #define EV69_CPU 17 /* EV69 (21264/EV69A) */ 36 | 37 | /* 38 | * DEC system types for Alpha systems. Found in HWRPB. 39 | * These values are architected. 40 | */ 41 | 42 | #define ST_ADU 1 /* Alpha ADU systype */ 43 | #define ST_DEC_4000 2 /* Cobra systype */ 44 | #define ST_DEC_7000 3 /* Ruby systype */ 45 | #define ST_DEC_3000_500 4 /* Flamingo systype */ 46 | #define ST_DEC_2000_300 6 /* Jensen systype */ 47 | #define ST_DEC_3000_300 7 /* Pelican systype */ 48 | #define ST_DEC_2100_A500 9 /* Sable systype */ 49 | #define ST_DEC_AXPVME_64 10 /* AXPvme system type */ 50 | #define ST_DEC_AXPPCI_33 11 /* NoName system type */ 51 | #define ST_DEC_TLASER 12 /* Turbolaser systype */ 52 | #define ST_DEC_2100_A50 13 /* Avanti systype */ 53 | #define ST_DEC_MUSTANG 14 /* Mustang systype */ 54 | #define ST_DEC_ALCOR 15 /* Alcor (EV5) systype */ 55 | #define ST_DEC_1000 17 /* Mikasa systype */ 56 | #define ST_DEC_EB64 18 /* EB64 systype */ 57 | #define ST_DEC_EB66 19 /* EB66 systype */ 58 | #define ST_DEC_EB64P 20 /* EB64+ systype */ 59 | #define ST_DEC_BURNS 21 /* laptop systype */ 60 | #define ST_DEC_RAWHIDE 22 /* Rawhide systype */ 61 | #define ST_DEC_K2 23 /* K2 systype */ 62 | #define ST_DEC_LYNX 24 /* Lynx systype */ 63 | #define ST_DEC_XL 25 /* Alpha XL systype */ 64 | #define ST_DEC_EB164 26 /* EB164 systype */ 65 | #define ST_DEC_NORITAKE 27 /* Noritake systype */ 66 | #define ST_DEC_CORTEX 28 /* Cortex systype */ 67 | #define ST_DEC_MIATA 30 /* Miata systype */ 68 | #define ST_DEC_XXM 31 /* XXM systype */ 69 | #define ST_DEC_TAKARA 32 /* Takara systype */ 70 | #define ST_DEC_YUKON 33 /* Yukon systype */ 71 | #define ST_DEC_TSUNAMI 34 /* Tsunami systype */ 72 | #define ST_DEC_WILDFIRE 35 /* Wildfire systype */ 73 | #define ST_DEC_CUSCO 36 /* CUSCO systype */ 74 | #define ST_DEC_EIGER 37 /* Eiger systype */ 75 | #define ST_DEC_TITAN 38 /* Titan systype */ 76 | #define ST_DEC_MARVEL 39 /* Marvel systype */ 77 | 78 | /* UNOFFICIAL!!! */ 79 | #define ST_UNOFFICIAL_BIAS 100 80 | #define ST_DTI_RUFFIAN 101 /* RUFFIAN systype */ 81 | 82 | /* Alpha Processor, Inc. systems */ 83 | #define ST_API_BIAS 200 84 | #define ST_API_NAUTILUS 201 /* UP1000 systype */ 85 | 86 | struct pcb_struct { 87 | unsigned long ksp; 88 | unsigned long usp; 89 | unsigned long ptbr; 90 | unsigned int pcc; 91 | unsigned int asn; 92 | unsigned long unique; 93 | unsigned long flags; 94 | unsigned long res1, res2; 95 | }; 96 | 97 | struct percpu_struct { 98 | unsigned long hwpcb[16]; 99 | unsigned long flags; 100 | unsigned long pal_mem_size; 101 | unsigned long pal_scratch_size; 102 | unsigned long pal_mem_pa; 103 | unsigned long pal_scratch_pa; 104 | unsigned long pal_revision; 105 | unsigned long type; 106 | unsigned long variation; 107 | unsigned long revision; 108 | unsigned long serial_no[2]; 109 | unsigned long logout_area_pa; 110 | unsigned long logout_area_len; 111 | unsigned long halt_PCBB; 112 | unsigned long halt_PC; 113 | unsigned long halt_PS; 114 | unsigned long halt_arg; 115 | unsigned long halt_ra; 116 | unsigned long halt_pv; 117 | unsigned long halt_reason; 118 | unsigned long res; 119 | unsigned long ipc_buffer[21]; 120 | unsigned long palcode_avail[16]; 121 | unsigned long compatibility; 122 | unsigned long console_data_log_pa; 123 | unsigned long console_data_log_length; 124 | unsigned long bcache_info; 125 | }; 126 | 127 | struct procdesc_struct { 128 | unsigned long weird_vms_stuff; 129 | unsigned long address; 130 | }; 131 | 132 | struct vf_map_struct { 133 | void *va; 134 | unsigned long pa; 135 | unsigned long count; 136 | }; 137 | 138 | struct crb_struct { 139 | struct procdesc_struct * dispatch_va; 140 | unsigned long dispatch_pa; 141 | struct procdesc_struct * fixup_va; 142 | unsigned long fixup_pa; 143 | /* virtual->physical map */ 144 | unsigned long map_entries; 145 | unsigned long map_pages; 146 | struct vf_map_struct map[1]; 147 | }; 148 | 149 | struct ctb_struct { 150 | unsigned long type; 151 | unsigned long unit; 152 | unsigned long res0; 153 | unsigned long len; 154 | unsigned long ipl; 155 | unsigned long tintr_vec; 156 | unsigned long rintr_vec; 157 | unsigned long term_type; 158 | unsigned long keybd_type; 159 | unsigned long keybd_trans; 160 | unsigned long keybd_map; 161 | unsigned long keybd_state; 162 | unsigned long keybd_last; 163 | unsigned long font_us; 164 | unsigned long font_mcs; 165 | unsigned long font_width; 166 | unsigned long font_height; 167 | unsigned long mon_width; 168 | unsigned long mon_height; 169 | unsigned long dpi; 170 | unsigned long planes; 171 | unsigned long cur_width; 172 | unsigned long cur_height; 173 | unsigned long head_cnt; 174 | unsigned long opwindow; 175 | unsigned long head_offset; 176 | unsigned long putchar; 177 | unsigned long io_state; 178 | unsigned long listen_state; 179 | unsigned long xaddr; 180 | unsigned long turboslot; 181 | unsigned long server_off; 182 | unsigned long line_off; 183 | unsigned char csd; 184 | }; 185 | 186 | #define CTB_NONE 0x00 187 | #define CTB_PRINTERPORT 0x02 188 | #define CTB_GRAPHICS 0x03 189 | #define CTB_MULTIPURPOSE 0x04 190 | 191 | /* 192 | * Format of the Console Terminal Block MULTIPURPOSE `turboslot' field: 193 | * 194 | * 63 40 39 32 31 24 23 16 15 8 7 0 195 | * | reserved | channel | hose | bus type | bus | slot | 196 | */ 197 | 198 | #define CTB_TURBOSLOT_TYPE_TC 0 /* TURBOchannel */ 199 | #define CTB_TURBOSLOT_TYPE_ISA 1 /* ISA */ 200 | #define CTB_TURBOSLOT_TYPE_EISA 2 /* EISA */ 201 | #define CTB_TURBOSLOT_TYPE_PCI 3 /* PCI */ 202 | 203 | struct memclust_struct { 204 | unsigned long start_pfn; 205 | unsigned long numpages; 206 | unsigned long numtested; 207 | unsigned long bitmap_va; 208 | unsigned long bitmap_pa; 209 | unsigned long bitmap_chksum; 210 | unsigned long usage; 211 | }; 212 | 213 | struct memdesc_struct { 214 | unsigned long chksum; 215 | unsigned long optional_pa; 216 | unsigned long numclusters; 217 | struct memclust_struct cluster[0]; 218 | }; 219 | 220 | struct dsr_struct { 221 | long smm; /* SMM nubber used by LMF */ 222 | unsigned long lurt_off; /* offset to LURT table */ 223 | unsigned long sysname_off; /* offset to sysname char count */ 224 | }; 225 | 226 | struct hwrpb_struct { 227 | unsigned long phys_addr; /* check: physical address of the hwrpb */ 228 | unsigned long id; /* check: "HWRPB\0\0\0" */ 229 | unsigned long revision; 230 | unsigned long size; /* size of hwrpb */ 231 | unsigned long cpuid; 232 | unsigned long pagesize; /* 8192, I hope */ 233 | unsigned long pa_bits; /* number of physical address bits */ 234 | unsigned long max_asn; 235 | unsigned char ssn[16]; /* system serial number: big bother is watching */ 236 | unsigned long sys_type; 237 | unsigned long sys_variation; 238 | unsigned long sys_revision; 239 | unsigned long intr_freq; /* interval clock frequency * 4096 */ 240 | unsigned long cycle_freq; /* cycle counter frequency */ 241 | unsigned long vptb; /* Virtual Page Table Base address */ 242 | unsigned long res1; 243 | unsigned long tbhb_offset; /* Translation Buffer Hint Block */ 244 | unsigned long nr_processors; 245 | unsigned long processor_size; 246 | unsigned long processor_offset; 247 | unsigned long ctb_nr; 248 | unsigned long ctb_size; /* console terminal block size */ 249 | unsigned long ctbt_offset; /* console terminal block table offset */ 250 | unsigned long crb_offset; /* console callback routine block */ 251 | unsigned long mddt_offset; /* memory data descriptor table */ 252 | unsigned long cdb_offset; /* configuration data block (or NULL) */ 253 | unsigned long frut_offset; /* FRU table (or NULL) */ 254 | void (*save_terminal)(unsigned long); 255 | unsigned long save_terminal_data; 256 | void (*restore_terminal)(unsigned long); 257 | unsigned long restore_terminal_data; 258 | void (*CPU_restart)(unsigned long); 259 | unsigned long CPU_restart_data; 260 | unsigned long res2; 261 | unsigned long res3; 262 | unsigned long chksum; 263 | unsigned long rxrdy; 264 | unsigned long txrdy; 265 | unsigned long dsr_offset; /* "Dynamic System Recognition Data Block Table" */ 266 | }; 267 | 268 | 269 | static inline void 270 | hwrpb_update_checksum(struct hwrpb_struct *h) 271 | { 272 | unsigned long sum = 0, *l; 273 | for (l = (unsigned long *) h; l < (unsigned long *) &h->chksum; ++l) 274 | sum += *l; 275 | h->chksum = sum; 276 | } 277 | 278 | #endif /* __ALPHA_HWRPB_H */ 279 | -------------------------------------------------------------------------------- /init.c: -------------------------------------------------------------------------------- 1 | /* Initialization of the system and the HWRPB. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #include "hwrpb.h" 22 | #include "osf.h" 23 | #include "ioport.h" 24 | #include "uart.h" 25 | #include "protos.h" 26 | #include SYSTEM_H 27 | 28 | #define PAGE_SHIFT 13 29 | #define PAGE_SIZE (1ul << PAGE_SHIFT) 30 | #define PAGE_OFFSET 0xfffffc0000000000UL 31 | 32 | #define VPTPTR 0xfffffffe00000000UL 33 | 34 | #define PA(VA) ((unsigned long)(VA) & 0xfffffffffful) 35 | #define VA(PA) ((void *)(PA) + PAGE_OFFSET) 36 | 37 | #define HZ 1024 38 | 39 | /* Upon entry, register a2 contains configuration information from the VM: 40 | 41 | bits 0-5 -- ncpus 42 | bit 6 -- "nographics" option (used to initialize CTB) */ 43 | 44 | #define CONFIG_NCPUS(x) ((x) & 63) 45 | #define CONFIG_NOGRAPHICS(x) ((x) & (1ull << 6)) 46 | 47 | struct hwrpb_combine { 48 | struct hwrpb_struct hwrpb; 49 | struct percpu_struct processor[4]; 50 | struct memdesc_struct md; 51 | struct memclust_struct mc[2]; 52 | struct ctb_struct ctb; 53 | struct crb_struct crb; 54 | struct procdesc_struct proc_dispatch; 55 | struct procdesc_struct proc_fixup; 56 | }; 57 | 58 | extern char stack[PAGE_SIZE] __attribute__((section(".sbss"))); 59 | extern char _end[] __attribute__((visibility("hidden"), nocommon)); 60 | 61 | struct pcb_struct pcb __attribute__((section(".sbss"))); 62 | 63 | static unsigned long page_dir[1024] 64 | __attribute__((aligned(PAGE_SIZE), section(".bss.page_dir"))); 65 | 66 | /* The HWRPB must be aligned because it is exported at INIT_HWRPB. */ 67 | struct hwrpb_combine hwrpb __attribute__((aligned(PAGE_SIZE))); 68 | 69 | void *last_alloc; 70 | bool have_vga; 71 | unsigned int pci_vga_bus; 72 | unsigned int pci_vga_dev; 73 | 74 | static void * 75 | alloc (unsigned long size, unsigned long align) 76 | { 77 | void *p = (void *)(((unsigned long)last_alloc + align - 1) & ~(align - 1)); 78 | last_alloc = p + size; 79 | return memset (p, 0, size); 80 | } 81 | 82 | static inline unsigned long 83 | pt_index(unsigned long addr, int level) 84 | { 85 | return (addr >> (PAGE_SHIFT + (10 * level))) & 0x3ff; 86 | } 87 | 88 | static inline unsigned long 89 | build_pte (void *page) 90 | { 91 | unsigned long bits; 92 | 93 | bits = PA((unsigned long)page) << (32 - PAGE_SHIFT); 94 | bits += _PAGE_VALID | _PAGE_KRE | _PAGE_KWE; 95 | 96 | return bits; 97 | } 98 | 99 | static inline void * 100 | pte_page (unsigned long pte) 101 | { 102 | return VA(pte >> 32 << PAGE_SHIFT); 103 | } 104 | 105 | static void 106 | set_pte (unsigned long addr, void *page) 107 | { 108 | unsigned long *pt = page_dir; 109 | unsigned long index; 110 | 111 | index = pt_index(addr, 2); 112 | if (pt[index] != 0) 113 | pt = pte_page (pt[index]); 114 | else 115 | { 116 | unsigned long *npt = alloc(PAGE_SIZE, PAGE_SIZE); 117 | pt[index] = build_pte (npt); 118 | pt = npt; 119 | } 120 | 121 | index = pt_index(addr, 1); 122 | if (pt[index] != 0) 123 | pt = pte_page (pt[index]); 124 | else 125 | { 126 | unsigned long *npt = alloc(PAGE_SIZE, PAGE_SIZE); 127 | pt[index] = build_pte (npt); 128 | pt = npt; 129 | } 130 | 131 | index = pt_index(addr, 0); 132 | pt[index] = build_pte (page); 133 | } 134 | 135 | static void 136 | init_page_table(void) 137 | { 138 | /* Install the self-reference for the virtual page table base register. */ 139 | page_dir[pt_index(VPTPTR, 2)] = build_pte(page_dir); 140 | 141 | set_pte ((unsigned long)INIT_HWRPB, &hwrpb); 142 | 143 | /* ??? SRM maps some amount of memory at 0x20000000 for use by programs 144 | started from the console prompt. Including the bootloader. While 145 | we're emulating MILO, don't bother as we jump straight to the kernel 146 | loaded into KSEG. */ 147 | } 148 | 149 | static void 150 | init_hwrpb (unsigned long memsize, unsigned long config) 151 | { 152 | unsigned long pal_pages; 153 | unsigned long amask; 154 | unsigned long i; 155 | unsigned long proc_type = EV4_CPU; 156 | unsigned long cpus = CONFIG_NCPUS(config); 157 | 158 | hwrpb.hwrpb.phys_addr = PA(&hwrpb); 159 | 160 | /* Yes, the 'HWRPB' magic is in big-endian byte ordering. */ 161 | hwrpb.hwrpb.id = ( (long)'H' << 56 162 | | (long)'W' << 48 163 | | (long)'R' << 40 164 | | (long)'P' << 32 165 | | (long)'B' << 24); 166 | 167 | hwrpb.hwrpb.size = sizeof(struct hwrpb_struct); 168 | 169 | ((int *)hwrpb.hwrpb.ssn)[0] = ( 'Q' << 0 170 | | 'E' << 8 171 | | 'M' << 16 172 | | 'U' << 24); 173 | 174 | amask = ~__builtin_alpha_amask(-1); 175 | switch (__builtin_alpha_implver()) 176 | { 177 | case 0: /* EV4 */ 178 | proc_type = EV4_CPU; 179 | hwrpb.hwrpb.max_asn = 63; 180 | break; 181 | 182 | case 1: /* EV5 */ 183 | proc_type 184 | = ((amask & 0x101) == 0x101 ? PCA56_CPU /* MAX+BWX */ 185 | : amask & 1 ? EV56_CPU /* BWX */ 186 | : EV5_CPU); 187 | hwrpb.hwrpb.max_asn = 127; 188 | break; 189 | 190 | case 2: /* EV6 */ 191 | proc_type = (amask & 4 ? EV67_CPU : EV6_CPU); /* CIX */ 192 | hwrpb.hwrpb.max_asn = 255; 193 | break; 194 | } 195 | 196 | /* This field is the WHAMI of the primary CPU. Just initialize 197 | this to 0; CPU #0 is always the primary on real Alpha systems 198 | (except for the TurboLaser). */ 199 | hwrpb.hwrpb.cpuid = 0; 200 | 201 | hwrpb.hwrpb.pagesize = PAGE_SIZE; 202 | hwrpb.hwrpb.pa_bits = 40; 203 | hwrpb.hwrpb.sys_type = SYS_TYPE; 204 | hwrpb.hwrpb.sys_variation = SYS_VARIATION; 205 | hwrpb.hwrpb.sys_revision = SYS_REVISION; 206 | for (i = 0; i < cpus; ++i) 207 | { 208 | /* Set the following PCS flags: 209 | (bit 2) Processor Available 210 | (bit 3) Processor Present 211 | (bit 6) PALcode Valid 212 | (bit 7) PALcode Memory Valid 213 | (bit 8) PALcode Loaded 214 | 215 | ??? We really should be intializing the PALcode memory and 216 | scratch space fields if we're setting PMV, or not set PMV, 217 | but Linux checks for it, so... */ 218 | hwrpb.processor[i].flags = 0x1cc; 219 | hwrpb.processor[i].type = proc_type; 220 | } 221 | 222 | hwrpb.hwrpb.intr_freq = HZ * 4096; 223 | hwrpb.hwrpb.cycle_freq = 250000000; /* QEMU architects 250MHz. */ 224 | 225 | hwrpb.hwrpb.vptb = VPTPTR; 226 | 227 | hwrpb.hwrpb.nr_processors = cpus; 228 | hwrpb.hwrpb.processor_size = sizeof(struct percpu_struct); 229 | hwrpb.hwrpb.processor_offset = offsetof(struct hwrpb_combine, processor); 230 | 231 | hwrpb.hwrpb.mddt_offset = offsetof(struct hwrpb_combine, md); 232 | hwrpb.md.numclusters = 2; 233 | 234 | pal_pages = (PA(last_alloc) + PAGE_SIZE - 1) >> PAGE_SHIFT; 235 | 236 | hwrpb.mc[0].numpages = pal_pages; 237 | hwrpb.mc[0].usage = 1; 238 | hwrpb.mc[1].start_pfn = pal_pages; 239 | hwrpb.mc[1].numpages = (memsize >> PAGE_SHIFT) - pal_pages; 240 | 241 | hwrpb.hwrpb.ctbt_offset = offsetof(struct hwrpb_combine, ctb); 242 | hwrpb.hwrpb.ctb_size = sizeof(hwrpb.ctb); 243 | hwrpb.ctb.len = sizeof(hwrpb.ctb) - offsetof(struct ctb_struct, ipl); 244 | if (have_vga && !CONFIG_NOGRAPHICS(config)) 245 | { 246 | hwrpb.ctb.type = CTB_MULTIPURPOSE; 247 | hwrpb.ctb.term_type = CTB_GRAPHICS; 248 | hwrpb.ctb.turboslot = (CTB_TURBOSLOT_TYPE_PCI << 16) | 249 | (pci_vga_bus << 8) | pci_vga_dev; 250 | } 251 | else 252 | { 253 | hwrpb.ctb.type = CTB_PRINTERPORT; 254 | hwrpb.ctb.term_type = CTB_PRINTERPORT; 255 | } 256 | 257 | hwrpb.hwrpb.crb_offset = offsetof(struct hwrpb_combine, crb); 258 | hwrpb.crb.dispatch_va = &hwrpb.proc_dispatch; 259 | hwrpb.crb.dispatch_pa = PA(&hwrpb.proc_dispatch); 260 | hwrpb.crb.fixup_va = &hwrpb.proc_fixup; 261 | hwrpb.crb.fixup_pa = PA(&hwrpb.proc_fixup); 262 | hwrpb.crb.map_entries = 1; 263 | hwrpb.crb.map_pages = 1; 264 | hwrpb.crb.map[0].va = &hwrpb; 265 | hwrpb.crb.map[0].pa = PA(&hwrpb); 266 | hwrpb.crb.map[0].count = 1; 267 | 268 | /* See crb.c for how we match the VMS calling conventions to Unix. */ 269 | hwrpb.proc_dispatch.address = (unsigned long)crb_dispatch; 270 | hwrpb.proc_fixup.address = (unsigned long)crb_fixup; 271 | 272 | hwrpb_update_checksum(&hwrpb.hwrpb); 273 | } 274 | 275 | static void 276 | init_pcb (void) 277 | { 278 | pcb.ksp = (unsigned long)stack + sizeof(stack); 279 | pcb.ptbr = PA(page_dir) >> PAGE_SHIFT; 280 | pcb.flags = 1; /* FEN */ 281 | } 282 | 283 | static void 284 | init_i8259 (void) 285 | { 286 | /* ??? MILO initializes the PIC as edge triggered; I do not know how SRM 287 | initializes them. However, Linux seems to expect that these are level 288 | triggered. That may be a kernel bug, but level triggers are more 289 | reliable anyway so lets go with that. */ 290 | 291 | /* Initialize the slave PIC. */ 292 | outb(0x11, PORT_PIC2_CMD); /* ICW1: edge trigger, cascade, ICW4 req */ 293 | outb(0x08, PORT_PIC2_DATA); /* ICW2: irq offset = 8 */ 294 | outb(0x02, PORT_PIC2_DATA); /* ICW3: slave ID 2 */ 295 | outb(0x01, PORT_PIC2_DATA); /* ICW4: not special nested, normal eoi */ 296 | 297 | /* Initialize the master PIC. */ 298 | outb(0x11, PORT_PIC1_CMD); /* ICW1 */ 299 | outb(0x00, PORT_PIC1_DATA); /* ICW2: irq offset = 0 */ 300 | outb(0x04, PORT_PIC1_DATA); /* ICW3: slave control INTC2 */ 301 | outb(0x01, PORT_PIC1_DATA); /* ICW4 */ 302 | 303 | /* Initialize level triggers. The CY82C693UB that's on some real alpha 304 | hardware doesn't have this; this is a PIIX extension. However, 305 | QEMU doesn't implement regular level triggers. */ 306 | outb(0xff, PORT_PIC2_ELCR); 307 | outb(0xff, PORT_PIC1_ELCR); 308 | 309 | /* Disable all interrupts. */ 310 | outb(0xff, PORT_PIC2_DATA); 311 | outb(0xff, PORT_PIC1_DATA); 312 | 313 | /* Non-specific EOI, clearing anything the might be pending. */ 314 | outb(0x20, PORT_PIC2_CMD); 315 | outb(0x20, PORT_PIC1_CMD); 316 | } 317 | 318 | static void __attribute__((noreturn)) 319 | swppal(void *entry, void *pcb, unsigned long vptptr, unsigned long pv) 320 | { 321 | register int variant __asm__("$16") = 2; /* OSF/1 PALcode */ 322 | register void *pc __asm__("$17") = entry; 323 | register unsigned long pa_pcb __asm__("$18") = PA(pcb); 324 | register unsigned long newvptptr __asm__("$19") = vptptr; 325 | register unsigned long newpv __asm__("$20") = pv; 326 | 327 | asm("call_pal 0x0a" : : 328 | "r"(variant), "r"(pc), "r"(pa_pcb), "r"(newvptptr), "r"(newpv)); 329 | __builtin_unreachable (); 330 | } 331 | 332 | void 333 | do_start(unsigned long memsize, void (*kernel_entry)(void), 334 | unsigned long config) 335 | { 336 | last_alloc = _end; 337 | 338 | init_page_table(); 339 | init_pcb(); 340 | init_i8259(); 341 | uart_init(); 342 | ps2port_setup(); 343 | pci_setup(); 344 | vgahw_init(); 345 | init_hwrpb(memsize, config); 346 | 347 | void *new_pc = kernel_entry ? kernel_entry : do_console; 348 | 349 | swppal(new_pc, &pcb, VPTPTR, (unsigned long)new_pc); 350 | } 351 | 352 | void 353 | do_start_wait(unsigned long cpuid) 354 | { 355 | while (1) 356 | { 357 | /* Wait 1ms for the kernel to wake us. */ 358 | ndelay(1000000); 359 | 360 | if (hwrpb.hwrpb.rxrdy & (1ull << cpuid)) 361 | { 362 | /* ??? The only message I know of is "START\r\n". 363 | I can't be bothered to verify more than 4 characters. */ 364 | 365 | /* Use use a private extension to SWPPAL to get the 366 | CPU_restart_data into $27. Linux fills it in, but does 367 | not require it. Other operating systems, however, do use 368 | CPU_restart_data as part of secondary CPU start-up. */ 369 | 370 | unsigned int len = hwrpb.processor[cpuid].ipc_buffer[0]; 371 | unsigned int msg = hwrpb.processor[cpuid].ipc_buffer[1]; 372 | void *CPU_restart = hwrpb.hwrpb.CPU_restart; 373 | unsigned long CPU_restart_data = hwrpb.hwrpb.CPU_restart_data; 374 | __sync_synchronize(); 375 | hwrpb.hwrpb.rxrdy = 0; 376 | 377 | if (len == 7 && msg == ('S' | 'T' << 8 | 'A' << 16 | 'R' << 24)) 378 | { 379 | /* Set bootstrap in progress */ 380 | hwrpb.processor[cpuid].flags |= 1; 381 | swppal(CPU_restart, hwrpb.processor[cpuid].hwpcb, 382 | hwrpb.hwrpb.vptb, CPU_restart_data); 383 | } 384 | } 385 | } 386 | } 387 | -------------------------------------------------------------------------------- /ioport.h: -------------------------------------------------------------------------------- 1 | // Definitions for X86 IO port access. 2 | // 3 | // Copyright (C) 2008 Kevin O'Connor 4 | // 5 | // This file may be distributed under the terms of the GNU LGPLv3 license. 6 | // 7 | // This file copied (somewhat) intact from SeaBIOS. 8 | 9 | #ifndef IOPORT_H 10 | #define IOPORT_H 11 | 12 | #define PORT_DMA_ADDR_2 0x0004 13 | #define PORT_DMA_CNT_2 0x0005 14 | #define PORT_DMA1_MASK_REG 0x000a 15 | #define PORT_DMA1_MODE_REG 0x000b 16 | #define PORT_DMA1_CLEAR_FF_REG 0x000c 17 | #define PORT_DMA1_MASTER_CLEAR 0x000d 18 | #define PORT_PIC1_CMD 0x0020 19 | #define PORT_PIC1_DATA 0x0021 20 | #define PORT_PIT_COUNTER0 0x0040 21 | #define PORT_PIT_COUNTER1 0x0041 22 | #define PORT_PIT_COUNTER2 0x0042 23 | #define PORT_PIT_MODE 0x0043 24 | #define PORT_PS2_DATA 0x0060 25 | #define PORT_PS2_CTRLB 0x0061 26 | #define PORT_PS2_STATUS 0x0064 27 | #define PORT_CMOS_INDEX 0x0070 28 | #define PORT_CMOS_DATA 0x0071 29 | #define PORT_DIAG 0x0080 30 | #define PORT_DMA_PAGE_2 0x0081 31 | #define PORT_A20 0x0092 32 | #define PORT_PIC2_CMD 0x00a0 33 | #define PORT_PIC2_DATA 0x00a1 34 | #define PORT_SMI_CMD 0x00b2 35 | #define PORT_SMI_STATUS 0x00b3 36 | #define PORT_DMA2_MASK_REG 0x00d4 37 | #define PORT_DMA2_MODE_REG 0x00d6 38 | #define PORT_DMA2_MASTER_CLEAR 0x00da 39 | #define PORT_MATH_CLEAR 0x00f0 40 | #define PORT_ATA2_CMD_BASE 0x0170 41 | #define PORT_ATA1_CMD_BASE 0x01f0 42 | #define PORT_LPT2 0x0278 43 | #define PORT_SERIAL4 0x02e8 44 | #define PORT_SERIAL2 0x02f8 45 | #define PORT_ATA2_CTRL_BASE 0x0374 46 | #define PORT_LPT1 0x0378 47 | #define PORT_SERIAL3 0x03e8 48 | #define PORT_ATA1_CTRL_BASE 0x03f4 49 | #define PORT_FD_BASE 0x03f0 50 | #define PORT_FD_DOR 0x03f2 51 | #define PORT_FD_STATUS 0x03f4 52 | #define PORT_FD_DATA 0x03f5 53 | #define PORT_HD_DATA 0x03f6 54 | #define PORT_FD_DIR 0x03f7 55 | #define PORT_SERIAL1 0x03f8 56 | #define PORT_PIC1_ELCR 0x04d0 57 | #define PORT_PIC2_ELCR 0x04d1 58 | #define PORT_PCI_CMD 0x0cf8 59 | #define PORT_PCI_REBOOT 0x0cf9 60 | #define PORT_PCI_DATA 0x0cfc 61 | #define PORT_BIOS_DEBUG 0x0402 62 | #define PORT_QEMU_CFG_CTL 0x0510 63 | #define PORT_QEMU_CFG_DATA 0x0511 64 | #define PORT_ACPI_PM_BASE 0xb000 65 | #define PORT_SMB_BASE 0xb100 66 | #define PORT_BIOS_APM 0x8900 67 | 68 | // Serial port offsets 69 | #define SEROFF_DATA 0 70 | #define SEROFF_DLL 0 71 | #define SEROFF_IER 1 72 | #define SEROFF_DLH 1 73 | #define SEROFF_IIR 2 74 | #define SEROFF_LCR 3 75 | #define SEROFF_LSR 5 76 | #define SEROFF_MSR 6 77 | 78 | // PORT_A20 bitdefs 79 | #define A20_ENABLE_BIT 0x02 80 | 81 | // PORT_CMOS_INDEX nmi disable bit 82 | #define NMI_DISABLE_BIT 0x80 83 | 84 | #endif // ioport.h 85 | -------------------------------------------------------------------------------- /memcpy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * linux/arch/alpha/lib/memcpy.c 3 | * 4 | * Copyright (C) 1995 Linus Torvalds 5 | */ 6 | 7 | /* 8 | * This is a reasonably optimized memcpy() routine. 9 | */ 10 | 11 | #include "protos.h" 12 | 13 | /* 14 | * Note that the C code is written to be optimized into good assembly. However, 15 | * at this point gcc is unable to sanely compile "if (n >= 0)", resulting in a 16 | * explicit compare against 0 (instead of just using the proper "blt reg, xx" or 17 | * "bge reg, xx"). I hope alpha-gcc will be fixed to notice this eventually.. 18 | */ 19 | 20 | /* 21 | * This should be done in one go with ldq_u*2/mask/stq_u. Do it 22 | * with a macro so that we can fix it up later.. 23 | */ 24 | #define ALIGN_DEST_TO8_UP(d,s,n) \ 25 | while (d & 7) { \ 26 | if (n <= 0) return; \ 27 | n--; \ 28 | *(char *) d = *(char *) s; \ 29 | d++; s++; \ 30 | } 31 | #define ALIGN_DEST_TO8_DN(d,s,n) \ 32 | while (d & 7) { \ 33 | if (n <= 0) return; \ 34 | n--; \ 35 | d--; s--; \ 36 | *(char *) d = *(char *) s; \ 37 | } 38 | 39 | /* 40 | * This should similarly be done with ldq_u*2/mask/stq. The destination 41 | * is aligned, but we don't fill in a full quad-word 42 | */ 43 | #define DO_REST_UP(d,s,n) \ 44 | while (n > 0) { \ 45 | n--; \ 46 | *(char *) d = *(char *) s; \ 47 | d++; s++; \ 48 | } 49 | #define DO_REST_DN(d,s,n) \ 50 | while (n > 0) { \ 51 | n--; \ 52 | d--; s--; \ 53 | *(char *) d = *(char *) s; \ 54 | } 55 | 56 | /* 57 | * This should be done with ldq/mask/stq. The source and destination are 58 | * aligned, but we don't fill in a full quad-word 59 | */ 60 | #define DO_REST_ALIGNED_UP(d,s,n) DO_REST_UP(d,s,n) 61 | #define DO_REST_ALIGNED_DN(d,s,n) DO_REST_DN(d,s,n) 62 | 63 | /* 64 | * This does unaligned memory copies. We want to avoid storing to 65 | * an unaligned address, as that would do a read-modify-write cycle. 66 | * We also want to avoid double-reading the unaligned reads. 67 | * 68 | * Note the ordering to try to avoid load (and address generation) latencies. 69 | */ 70 | static inline void __memcpy_unaligned_up (unsigned long d, unsigned long s, 71 | long n) 72 | { 73 | ALIGN_DEST_TO8_UP(d,s,n); 74 | n -= 8; /* to avoid compare against 8 in the loop */ 75 | if (n >= 0) { 76 | unsigned long low_word, high_word; 77 | __asm__("ldq_u %0,%1":"=r" (low_word):"m" (*(unsigned long *) s)); 78 | do { 79 | unsigned long tmp; 80 | __asm__("ldq_u %0,%1":"=r" (high_word):"m" (*(unsigned long *)(s+8))); 81 | n -= 8; 82 | __asm__("extql %1,%2,%0" 83 | :"=r" (low_word) 84 | :"r" (low_word), "r" (s)); 85 | __asm__("extqh %1,%2,%0" 86 | :"=r" (tmp) 87 | :"r" (high_word), "r" (s)); 88 | s += 8; 89 | *(unsigned long *) d = low_word | tmp; 90 | d += 8; 91 | low_word = high_word; 92 | } while (n >= 0); 93 | } 94 | n += 8; 95 | DO_REST_UP(d,s,n); 96 | } 97 | 98 | static inline void __memcpy_unaligned_dn (unsigned long d, unsigned long s, 99 | long n) 100 | { 101 | /* I don't understand AXP assembler well enough for this. -Tim */ 102 | s += n; 103 | d += n; 104 | while (n--) 105 | * (char *) --d = * (char *) --s; 106 | } 107 | 108 | /* 109 | * Hmm.. Strange. The __asm__ here is there to make gcc use an integer register 110 | * for the load-store. I don't know why, but it would seem that using a floating 111 | * point register for the move seems to slow things down (very small difference, 112 | * though). 113 | * 114 | * Note the ordering to try to avoid load (and address generation) latencies. 115 | */ 116 | static inline void __memcpy_aligned_up (unsigned long d, unsigned long s, 117 | long n) 118 | { 119 | ALIGN_DEST_TO8_UP(d,s,n); 120 | n -= 8; 121 | while (n >= 0) { 122 | unsigned long tmp; 123 | __asm__("ldq %0,%1":"=r" (tmp):"m" (*(unsigned long *) s)); 124 | n -= 8; 125 | s += 8; 126 | *(unsigned long *) d = tmp; 127 | d += 8; 128 | } 129 | n += 8; 130 | DO_REST_ALIGNED_UP(d,s,n); 131 | } 132 | static inline void __memcpy_aligned_dn (unsigned long d, unsigned long s, 133 | long n) 134 | { 135 | s += n; 136 | d += n; 137 | ALIGN_DEST_TO8_DN(d,s,n); 138 | n -= 8; 139 | while (n >= 0) { 140 | unsigned long tmp; 141 | s -= 8; 142 | __asm__("ldq %0,%1":"=r" (tmp):"m" (*(unsigned long *) s)); 143 | n -= 8; 144 | d -= 8; 145 | *(unsigned long *) d = tmp; 146 | } 147 | n += 8; 148 | DO_REST_ALIGNED_DN(d,s,n); 149 | } 150 | 151 | void * memcpy(void * dest, const void *src, size_t n) 152 | { 153 | if (!(((unsigned long) dest ^ (unsigned long) src) & 7)) { 154 | __memcpy_aligned_up ((unsigned long) dest, (unsigned long) src, 155 | n); 156 | return dest; 157 | } 158 | __memcpy_unaligned_up ((unsigned long) dest, (unsigned long) src, n); 159 | return dest; 160 | } 161 | -------------------------------------------------------------------------------- /memset.c: -------------------------------------------------------------------------------- 1 | /* The standard memset function. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | 22 | #include "protos.h" 23 | 24 | void *memset(void *optr, int ival, unsigned long size) 25 | { 26 | unsigned long val = ival; 27 | void *ptr = optr; 28 | 29 | if (__builtin_expect (size == 0, 0)) 30 | return optr; 31 | 32 | if (__builtin_expect (val != 0, 0)) 33 | { 34 | val = val & 0xff; 35 | val |= val << 8; 36 | val |= val << 16; 37 | val |= val << 32; 38 | } 39 | 40 | if (__builtin_expect ((unsigned long)ptr & 1, 0)) 41 | { 42 | *(char *)ptr = val; 43 | ptr += 1; 44 | size -= 1; 45 | } 46 | 47 | if (__builtin_expect ((unsigned long)ptr & 2, 0)) 48 | { 49 | if (size < 2) 50 | goto tail_1; 51 | *(short *)ptr = val; 52 | ptr += 2; 53 | size -= 2; 54 | } 55 | 56 | if (__builtin_expect ((unsigned long)ptr & 4, 0)) 57 | { 58 | if (size < 4) 59 | goto tail_3; 60 | *(int *)ptr = val; 61 | ptr += 4; 62 | size -= 4; 63 | } 64 | 65 | while (size >= 8) 66 | { 67 | *(long *)ptr = val; 68 | ptr += 8; 69 | size -= 8; 70 | } 71 | 72 | if (size >= 4) 73 | { 74 | *(int *)ptr = val; 75 | ptr += 4; 76 | size -= 4; 77 | } 78 | 79 | tail_3: 80 | if (size >= 2) 81 | { 82 | *(short *)ptr = val; 83 | ptr += 2; 84 | size -= 2; 85 | } 86 | 87 | tail_1: 88 | if (size > 0) 89 | { 90 | *(char *)ptr = val; 91 | ptr += 1; 92 | size -= 1; 93 | } 94 | 95 | return optr; 96 | } 97 | -------------------------------------------------------------------------------- /osf.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rth7680/qemu-palcode/99d9b4dcf27d7fbcbadab71bdc88ef6531baf6bf/osf.h -------------------------------------------------------------------------------- /pal.h: -------------------------------------------------------------------------------- 1 | /* Common definitions for QEMU Emulation PALcode 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #ifndef PAL_H 22 | #define PAL_H 1 23 | 24 | /* General Purpose Registers. */ 25 | #define v0 $0 26 | #define t0 $1 27 | #define t1 $2 28 | #define t2 $3 29 | #define t3 $4 30 | #define t4 $5 31 | #define t5 $6 32 | #define a0 $16 33 | #define a1 $17 34 | #define a2 $18 35 | #define a3 $19 36 | #define a4 $20 37 | #define a5 $21 38 | #define t8 $22 39 | #define t9 $23 40 | #define t10 $24 41 | 42 | /* PALcode Shadow Registers. These registers are swapped out when 43 | QEMU is in PALmode. Unlike real hardware, there is no enable bit. 44 | However, also unlike real hardware, the originals can be accessed 45 | via MTPR/MFPR. */ 46 | #define p0 $8 47 | #define p1 $9 48 | #define p2 $10 49 | #define p3 $11 50 | #define p4 $12 51 | #define p5 $13 52 | #define p6 $14 // Used to save exc_addr for machine check 53 | #define p7 $25 54 | 55 | /* QEMU Processor Registers. */ 56 | #define qemu_ps 0 57 | #define qemu_fen 1 58 | #define qemu_pcc_ofs 2 59 | #define qemu_trap_arg0 3 60 | #define qemu_trap_arg1 4 61 | #define qemu_trap_arg2 5 62 | #define qemu_exc_addr 6 63 | #define qemu_palbr 7 64 | #define qemu_ptbr 8 65 | #define qemu_vptptr 9 66 | #define qemu_unique 10 67 | #define qemu_sysval 11 68 | #define qemu_usp 12 69 | 70 | #define qemu_shadow0 32 71 | #define qemu_shadow1 33 72 | #define qemu_shadow2 34 73 | #define qemu_shadow3 35 74 | #define qemu_shadow4 36 75 | #define qemu_shadow5 37 76 | #define qemu_shadow6 38 77 | #define qemu_shadow7 39 78 | 79 | /* PALcode Processor Register Private Storage. */ 80 | #define pt0 40 81 | #define pt1 41 82 | #define pt2 42 83 | #define pt3 43 84 | #define pt4 44 85 | #define pt5 45 86 | #define pt6 46 87 | #define pt7 47 88 | #define pt8 48 89 | #define pt9 49 90 | #define pt10 50 91 | #define pt11 51 92 | #define pt12 52 93 | #define pt13 53 94 | #define pt14 54 95 | #define pt15 55 96 | #define pt16 56 97 | #define pt17 57 98 | #define pt18 58 99 | #define pt19 59 100 | #define pt20 60 101 | #define pt21 61 102 | #define pt22 62 103 | #define pt23 63 104 | 105 | /* QEMU function calls, via mtpr. */ 106 | #define qemu_tbia 255 107 | #define qemu_tbis 254 108 | #define qemu_wait 253 109 | #define qemu_halt 252 110 | #define qemu_alarm 251 111 | #define qemu_walltime 250 112 | #define qemu_vmtime 249 113 | 114 | /* PALcode uses of the private storage slots. */ 115 | #define ptEntUna pt0 116 | #define ptEntIF pt1 117 | #define ptEntSys pt2 118 | #define ptEntInt pt3 119 | #define ptEntArith pt4 120 | #define ptEntMM pt5 121 | #define ptMces pt6 122 | #define ptKsp pt7 123 | #define ptKgp pt8 124 | #define ptPcbb pt9 125 | #define ptPgp pt10 126 | #define ptMisc pt11 127 | #define ptMchk0 pt12 128 | #define ptMchk1 pt13 129 | #define ptMchk2 pt14 130 | #define ptMchk3 pt15 131 | #define ptMchk4 pt16 132 | #define ptMchk5 pt17 133 | #define ptSys0 pt18 134 | #define ptSys1 pt19 135 | 136 | /* 137 | * Shortcuts for various PALmode instructions. 138 | */ 139 | #define mtpr hw_mtpr 140 | #define mfpr hw_mfpr 141 | #define stq_p hw_stq/p 142 | #define stl_p hw_stl/p 143 | #define ldl_p hw_ldl/p 144 | #define ldq_p hw_ldq/p 145 | 146 | /* QEMU recognizes the EV4/EV5 HW_REI instruction as a special case of 147 | the EV6 HW_RET instruction. This pulls the destination address from 148 | the EXC_ADDR processor register. */ 149 | #define hw_rei hw_ret ($31) 150 | 151 | 152 | .macro ENDFN function 153 | .type \function, @function 154 | .size \function, . - \function 155 | .endm 156 | 157 | #endif /* PAL_H */ 158 | -------------------------------------------------------------------------------- /palcode.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf64-alpha") 2 | ENTRY(__start) 3 | 4 | SECTIONS 5 | { 6 | . = 0xfffffc0000000000; 7 | .text : { *(.text*) } 8 | .rodata : { *(.rodata*) } 9 | .data ALIGN(8192) : { *(.data*) } 10 | .got : { *(.got.plt) *(.got) } 11 | .sdata : { *(.sdata*) } 12 | .sbss : { *(.sbss) *(.scommon) } 13 | .bss : { 14 | *(.bss.page_dir) 15 | *(.bss.stack) 16 | *(COMMON) 17 | *(.bss) 18 | PROVIDE (_end = .); 19 | } 20 | 21 | /* DWARF debug sections. 22 | Symbols in the DWARF debugging sections are relative to the beginning 23 | of the section so we begin them at 0. */ 24 | /* DWARF 1 */ 25 | .debug 0 : { *(.debug) } 26 | .line 0 : { *(.line) } 27 | /* GNU DWARF 1 extensions */ 28 | .debug_srcinfo 0 : { *(.debug_srcinfo) } 29 | .debug_sfnames 0 : { *(.debug_sfnames) } 30 | /* DWARF 1.1 and DWARF 2 */ 31 | .debug_aranges 0 : { *(.debug_aranges) } 32 | .debug_pubnames 0 : { *(.debug_pubnames) } 33 | /* DWARF 2 */ 34 | .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } 35 | .debug_abbrev 0 : { *(.debug_abbrev) } 36 | .debug_line 0 : { *(.debug_line) } 37 | .debug_frame 0 : { *(.debug_frame) } 38 | .debug_str 0 : { *(.debug_str) } 39 | .debug_loc 0 : { *(.debug_loc) } 40 | .debug_macinfo 0 : { *(.debug_macinfo) } 41 | /* SGI/MIPS DWARF 2 extensions */ 42 | .debug_weaknames 0 : { *(.debug_weaknames) } 43 | .debug_funcnames 0 : { *(.debug_funcnames) } 44 | .debug_typenames 0 : { *(.debug_typenames) } 45 | .debug_varnames 0 : { *(.debug_varnames) } 46 | /* DWARF 3 */ 47 | .debug_pubtypes 0 : { *(.debug_pubtypes) } 48 | .debug_ranges 0 : { *(.debug_ranges) } 49 | .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } 50 | 51 | /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } 52 | /DISCARD/ : { *(.eh_frame) } 53 | } 54 | -------------------------------------------------------------------------------- /pci.c: -------------------------------------------------------------------------------- 1 | /* Simplistic PCI support. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | /* We don't bother supporting PCI bridges, because the device model we're 22 | currently using for QEMU doesn't build any. 23 | 24 | We don't bother to build real datastructures in memory, because it's 25 | fairly quick under emulation simply to access configuration space again. 26 | This helps when running kernels under the emulator that might have 27 | re-organized the BARs out from under us. */ 28 | 29 | #include "protos.h" 30 | #include "pci.h" 31 | #include "pci_regs.h" 32 | #include SYSTEM_H 33 | 34 | 35 | #define PCI_SLOT_MAX 32 36 | #define PCI_FUNC_MAX 8 37 | #define PCI_REGION_ROM 6 38 | #define PCI_REGIONS_MAX 7 39 | 40 | 41 | void 42 | pci_config_maskw(int bdf, int addr, uint16_t off, uint16_t on) 43 | { 44 | uint16_t val = pci_config_readw(bdf, addr); 45 | val = (val & ~off) | on; 46 | pci_config_writew(bdf, addr, val); 47 | } 48 | 49 | int 50 | pci_next(int bdf, int *pmax) 51 | { 52 | int max; 53 | 54 | if (PCI_FUNC(bdf) == 1) 55 | { 56 | /* If the last device was not a multi-function device, skip to next. */ 57 | if ((pci_config_readb(bdf-1, PCI_HEADER_TYPE) & 0x80) == 0) 58 | bdf += 7; 59 | } 60 | 61 | max = *pmax; 62 | while (1) 63 | { 64 | uint16_t vendor; 65 | 66 | /* ??? Support multiple PCI busses here at some point. */ 67 | if (bdf >= max) 68 | return -1; 69 | 70 | /* Check if there is a device present at the location. */ 71 | vendor = pci_config_readw(bdf, PCI_VENDOR_ID); 72 | if (vendor != 0x0000 && vendor != 0xffff) 73 | return bdf; 74 | 75 | bdf += (PCI_FUNC(bdf) == 0 ? 8 : 1); 76 | } 77 | } 78 | 79 | static void 80 | pci_setup_device(int bdf, uint32_t *p_io_base, uint32_t *p_mem_base) 81 | { 82 | int vendor_id, device_id, class_id, region; 83 | 84 | vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID); 85 | device_id = pci_config_readw(bdf, PCI_DEVICE_ID); 86 | class_id = pci_config_readw(bdf, PCI_CLASS_DEVICE); 87 | 88 | printf("PCI: %02x:%02x:%x class %04x id %04x:%04x\r\n", 89 | PCI_BUS(bdf), PCI_SLOT(bdf), PCI_FUNC(bdf), 90 | class_id, vendor_id, device_id); 91 | 92 | for (region = 0; region < PCI_REGION_ROM; region++) 93 | { 94 | int ofs = PCI_BASE_ADDRESS_0 + region * 4; 95 | uint32_t old, mask, val, size, align; 96 | uint32_t *p_base; 97 | 98 | old = pci_config_readl(bdf, ofs); 99 | if (old & PCI_BASE_ADDRESS_SPACE_IO) 100 | { 101 | mask = PCI_BASE_ADDRESS_IO_MASK; 102 | p_base = p_io_base; 103 | } 104 | else 105 | { 106 | mask = PCI_BASE_ADDRESS_MEM_MASK; 107 | p_base = p_mem_base; 108 | } 109 | 110 | pci_config_writel(bdf, ofs, -1); 111 | val = pci_config_readl(bdf, ofs); 112 | pci_config_writel(bdf, ofs, old); 113 | 114 | align = size = ~(val & mask) + 1; 115 | if (val != 0) 116 | { 117 | uint32_t addr = *p_base; 118 | addr = (addr + align - 1) & ~(align - 1); 119 | *p_base = addr + size; 120 | pci_config_writel(bdf, ofs, addr); 121 | 122 | printf("PCI: region %d: %08x\r\n", region, addr); 123 | 124 | if ((old & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) 125 | == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) 126 | { 127 | pci_config_writel(bdf, ofs + 4, 0); 128 | region++; 129 | } 130 | } 131 | } 132 | 133 | pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY); 134 | 135 | /* Map the interrupt and program the IRQ into the line register. 136 | Some operating systems rely on the Console providing this information 137 | in order to avoid having mapping tables for every possible system 138 | variation. */ 139 | 140 | const uint8_t pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN); 141 | const uint8_t slot = PCI_SLOT(bdf); 142 | const uint8_t irq = MAP_PCI_INTERRUPT(slot, pin, class_id); 143 | 144 | pci_config_writeb(bdf, PCI_INTERRUPT_LINE, irq); 145 | } 146 | 147 | void 148 | pci_setup(void) 149 | { 150 | uint32_t io_base = 0xc000; 151 | uint32_t mem_base = 256 * 1024 * 1024; 152 | int bdf, max; 153 | 154 | foreachpci (bdf, max) 155 | pci_setup_device(bdf, &io_base, &mem_base); 156 | } 157 | -------------------------------------------------------------------------------- /pci.h: -------------------------------------------------------------------------------- 1 | /* Simplistic PCI support. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | /* This header is intended to be compatible with the pci.h from SeaBIOS. 22 | Their header, however, is too PC specific to be of use. */ 23 | 24 | #ifndef PCI_H 25 | #define PCI_H 1 26 | 27 | extern void *pci_conf_base; 28 | 29 | static inline void pci_config_writel(int bdf, uint8_t addr, uint32_t val) 30 | { 31 | *(volatile uint32_t *)(pci_conf_base + bdf * 256 + addr) = val; 32 | } 33 | 34 | static inline void pci_config_writew(int bdf, uint8_t addr, uint16_t val) 35 | { 36 | *(volatile uint16_t *)(pci_conf_base + bdf * 256 + addr) = val; 37 | } 38 | 39 | static inline void pci_config_writeb(int bdf, uint8_t addr, uint8_t val) 40 | { 41 | *(volatile uint8_t *)(pci_conf_base + bdf * 256 + addr) = val; 42 | } 43 | 44 | static inline uint32_t pci_config_readl(int bdf, uint8_t addr) 45 | { 46 | return *(volatile uint32_t *)(pci_conf_base + bdf * 256 + addr); 47 | } 48 | 49 | static inline uint16_t pci_config_readw(int bdf, uint8_t addr) 50 | { 51 | return *(volatile uint16_t *)(pci_conf_base + bdf * 256 + addr); 52 | } 53 | 54 | static inline uint8_t pci_config_readb(int bdf, uint8_t addr) 55 | { 56 | return *(volatile uint8_t *)(pci_conf_base + bdf * 256 + addr); 57 | } 58 | 59 | extern void pci_config_maskw(int bdf, int addr, uint16_t off, uint16_t on); 60 | 61 | extern int pci_next(int bdf, int *pmax); 62 | 63 | #define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) 64 | #define PCI_BUS(devfn) ((devfn) >> 8) 65 | #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) 66 | #define PCI_FUNC(devfn) ((devfn) & 0x07) 67 | 68 | #define foreachpci(BDF, MAX) \ 69 | for (MAX = 0x0100, BDF = pci_next(0, &MAX); \ 70 | BDF >= 0; \ 71 | BDF = pci_next(BDF+1, &MAX)) 72 | 73 | #endif /* PCI_H */ 74 | -------------------------------------------------------------------------------- /pci_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pci_regs.h 3 | * 4 | * PCI standard defines 5 | * Copyright 1994, Drew Eckhardt 6 | * Copyright 1997--1999 Martin Mares 7 | * 8 | * For more information, please consult the following manuals (look at 9 | * http://www.pcisig.com/ for how to get them): 10 | * 11 | * PCI BIOS Specification 12 | * PCI Local Bus Specification 13 | * PCI to PCI Bridge Specification 14 | * PCI System Design Guide 15 | * 16 | * For hypertransport information, please consult the following manuals 17 | * from http://www.hypertransport.org 18 | * 19 | * The Hypertransport I/O Link Specification 20 | */ 21 | 22 | #ifndef LINUX_PCI_REGS_H 23 | #define LINUX_PCI_REGS_H 24 | 25 | /* 26 | * Under PCI, each device has 256 bytes of configuration address space, 27 | * of which the first 64 bytes are standardized as follows: 28 | */ 29 | #define PCI_VENDOR_ID 0x00 /* 16 bits */ 30 | #define PCI_DEVICE_ID 0x02 /* 16 bits */ 31 | #define PCI_COMMAND 0x04 /* 16 bits */ 32 | #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ 33 | #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ 34 | #define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ 35 | #define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ 36 | #define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ 37 | #define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ 38 | #define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ 39 | #define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ 40 | #define PCI_COMMAND_SERR 0x100 /* Enable SERR */ 41 | #define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ 42 | #define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */ 43 | 44 | #define PCI_STATUS 0x06 /* 16 bits */ 45 | #define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ 46 | #define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */ 47 | #define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */ 48 | #define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ 49 | #define PCI_STATUS_PARITY 0x100 /* Detected parity error */ 50 | #define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ 51 | #define PCI_STATUS_DEVSEL_FAST 0x000 52 | #define PCI_STATUS_DEVSEL_MEDIUM 0x200 53 | #define PCI_STATUS_DEVSEL_SLOW 0x400 54 | #define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ 55 | #define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ 56 | #define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ 57 | #define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ 58 | #define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ 59 | 60 | #define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 revision */ 61 | #define PCI_REVISION_ID 0x08 /* Revision ID */ 62 | #define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ 63 | #define PCI_CLASS_DEVICE 0x0a /* Device class */ 64 | 65 | #define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ 66 | #define PCI_LATENCY_TIMER 0x0d /* 8 bits */ 67 | #define PCI_HEADER_TYPE 0x0e /* 8 bits */ 68 | #define PCI_HEADER_TYPE_NORMAL 0 69 | #define PCI_HEADER_TYPE_BRIDGE 1 70 | #define PCI_HEADER_TYPE_CARDBUS 2 71 | 72 | #define PCI_BIST 0x0f /* 8 bits */ 73 | #define PCI_BIST_CODE_MASK 0x0f /* Return result */ 74 | #define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */ 75 | #define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */ 76 | 77 | /* 78 | * Base addresses specify locations in memory or I/O space. 79 | * Decoded size can be determined by writing a value of 80 | * 0xffffffff to the register, and reading it back. Only 81 | * 1 bits are decoded. 82 | */ 83 | #define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ 84 | #define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */ 85 | #define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */ 86 | #define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ 87 | #define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ 88 | #define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ 89 | #define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */ 90 | #define PCI_BASE_ADDRESS_SPACE_IO 0x01 91 | #define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00 92 | #define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06 93 | #define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */ 94 | #define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */ 95 | #define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ 96 | #define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */ 97 | #define PCI_BASE_ADDRESS_MEM_MASK (~0x0fU) 98 | #define PCI_BASE_ADDRESS_IO_MASK (~0x03U) 99 | /* bit 1 is reserved if address_space = 1 */ 100 | 101 | /* Header type 0 (normal devices) */ 102 | #define PCI_CARDBUS_CIS 0x28 103 | #define PCI_SUBSYSTEM_VENDOR_ID 0x2c 104 | #define PCI_SUBSYSTEM_ID 0x2e 105 | #define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */ 106 | #define PCI_ROM_ADDRESS_ENABLE 0x01 107 | #define PCI_ROM_ADDRESS_MASK (~0x7ffUL) 108 | 109 | #define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */ 110 | 111 | /* 0x35-0x3b are reserved */ 112 | #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ 113 | #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ 114 | #define PCI_MIN_GNT 0x3e /* 8 bits */ 115 | #define PCI_MAX_LAT 0x3f /* 8 bits */ 116 | 117 | /* Header type 1 (PCI-to-PCI bridges) */ 118 | #define PCI_PRIMARY_BUS 0x18 /* Primary bus number */ 119 | #define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */ 120 | #define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */ 121 | #define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */ 122 | #define PCI_IO_BASE 0x1c /* I/O range behind the bridge */ 123 | #define PCI_IO_LIMIT 0x1d 124 | #define PCI_IO_RANGE_TYPE_MASK 0x0fUL /* I/O bridging type */ 125 | #define PCI_IO_RANGE_TYPE_16 0x00 126 | #define PCI_IO_RANGE_TYPE_32 0x01 127 | #define PCI_IO_RANGE_MASK (~0x0fUL) 128 | #define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */ 129 | #define PCI_MEMORY_BASE 0x20 /* Memory range behind */ 130 | #define PCI_MEMORY_LIMIT 0x22 131 | #define PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL 132 | #define PCI_MEMORY_RANGE_MASK (~0x0fUL) 133 | #define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */ 134 | #define PCI_PREF_MEMORY_LIMIT 0x26 135 | #define PCI_PREF_RANGE_TYPE_MASK 0x0fUL 136 | #define PCI_PREF_RANGE_TYPE_32 0x00 137 | #define PCI_PREF_RANGE_TYPE_64 0x01 138 | #define PCI_PREF_RANGE_MASK (~0x0fUL) 139 | #define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */ 140 | #define PCI_PREF_LIMIT_UPPER32 0x2c 141 | #define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */ 142 | #define PCI_IO_LIMIT_UPPER16 0x32 143 | /* 0x34 same as for htype 0 */ 144 | /* 0x35-0x3b is reserved */ 145 | #define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */ 146 | /* 0x3c-0x3d are same as for htype 0 */ 147 | #define PCI_BRIDGE_CONTROL 0x3e 148 | #define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */ 149 | #define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */ 150 | #define PCI_BRIDGE_CTL_ISA 0x04 /* Enable ISA mode */ 151 | #define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */ 152 | #define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */ 153 | #define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */ 154 | #define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */ 155 | 156 | /* Header type 2 (CardBus bridges) */ 157 | #define PCI_CB_CAPABILITY_LIST 0x14 158 | /* 0x15 reserved */ 159 | #define PCI_CB_SEC_STATUS 0x16 /* Secondary status */ 160 | #define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */ 161 | #define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */ 162 | #define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */ 163 | #define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */ 164 | #define PCI_CB_MEMORY_BASE_0 0x1c 165 | #define PCI_CB_MEMORY_LIMIT_0 0x20 166 | #define PCI_CB_MEMORY_BASE_1 0x24 167 | #define PCI_CB_MEMORY_LIMIT_1 0x28 168 | #define PCI_CB_IO_BASE_0 0x2c 169 | #define PCI_CB_IO_BASE_0_HI 0x2e 170 | #define PCI_CB_IO_LIMIT_0 0x30 171 | #define PCI_CB_IO_LIMIT_0_HI 0x32 172 | #define PCI_CB_IO_BASE_1 0x34 173 | #define PCI_CB_IO_BASE_1_HI 0x36 174 | #define PCI_CB_IO_LIMIT_1 0x38 175 | #define PCI_CB_IO_LIMIT_1_HI 0x3a 176 | #define PCI_CB_IO_RANGE_MASK (~0x03UL) 177 | /* 0x3c-0x3d are same as for htype 0 */ 178 | #define PCI_CB_BRIDGE_CONTROL 0x3e 179 | #define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */ 180 | #define PCI_CB_BRIDGE_CTL_SERR 0x02 181 | #define PCI_CB_BRIDGE_CTL_ISA 0x04 182 | #define PCI_CB_BRIDGE_CTL_VGA 0x08 183 | #define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20 184 | #define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */ 185 | #define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */ 186 | #define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */ 187 | #define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200 188 | #define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400 189 | #define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40 190 | #define PCI_CB_SUBSYSTEM_ID 0x42 191 | #define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */ 192 | /* 0x48-0x7f reserved */ 193 | 194 | /* Capability lists */ 195 | 196 | #define PCI_CAP_LIST_ID 0 /* Capability ID */ 197 | #define PCI_CAP_ID_PM 0x01 /* Power Management */ 198 | #define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */ 199 | #define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */ 200 | #define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */ 201 | #define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ 202 | #define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */ 203 | #define PCI_CAP_ID_PCIX 0x07 /* PCI-X */ 204 | #define PCI_CAP_ID_HT 0x08 /* HyperTransport */ 205 | #define PCI_CAP_ID_VNDR 0x09 /* Vendor specific */ 206 | #define PCI_CAP_ID_DBG 0x0A /* Debug port */ 207 | #define PCI_CAP_ID_CCRC 0x0B /* CompactPCI Central Resource Control */ 208 | #define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */ 209 | #define PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */ 210 | #define PCI_CAP_ID_AGP3 0x0E /* AGP Target PCI-PCI bridge */ 211 | #define PCI_CAP_ID_EXP 0x10 /* PCI Express */ 212 | #define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ 213 | #define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */ 214 | #define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */ 215 | #define PCI_CAP_SIZEOF 4 216 | 217 | /* Power Management Registers */ 218 | 219 | #define PCI_PM_PMC 2 /* PM Capabilities Register */ 220 | #define PCI_PM_CAP_VER_MASK 0x0007 /* Version */ 221 | #define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */ 222 | #define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */ 223 | #define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */ 224 | #define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */ 225 | #define PCI_PM_CAP_D1 0x0200 /* D1 power state support */ 226 | #define PCI_PM_CAP_D2 0x0400 /* D2 power state support */ 227 | #define PCI_PM_CAP_PME 0x0800 /* PME pin supported */ 228 | #define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */ 229 | #define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */ 230 | #define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */ 231 | #define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */ 232 | #define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */ 233 | #define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */ 234 | #define PCI_PM_CAP_PME_SHIFT 11 /* Start of the PME Mask in PMC */ 235 | #define PCI_PM_CTRL 4 /* PM control and status register */ 236 | #define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */ 237 | #define PCI_PM_CTRL_NO_SOFT_RESET 0x0004 /* No reset for D3hot->D0 */ 238 | #define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */ 239 | #define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */ 240 | #define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */ 241 | #define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */ 242 | #define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */ 243 | #define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */ 244 | #define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */ 245 | #define PCI_PM_DATA_REGISTER 7 /* (??) */ 246 | #define PCI_PM_SIZEOF 8 247 | 248 | /* AGP registers */ 249 | 250 | #define PCI_AGP_VERSION 2 /* BCD version number */ 251 | #define PCI_AGP_RFU 3 /* Rest of capability flags */ 252 | #define PCI_AGP_STATUS 4 /* Status register */ 253 | #define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */ 254 | #define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */ 255 | #define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */ 256 | #define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */ 257 | #define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */ 258 | #define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */ 259 | #define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */ 260 | #define PCI_AGP_COMMAND 8 /* Control register */ 261 | #define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */ 262 | #define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */ 263 | #define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */ 264 | #define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */ 265 | #define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */ 266 | #define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */ 267 | #define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 2x rate */ 268 | #define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 1x rate */ 269 | #define PCI_AGP_SIZEOF 12 270 | 271 | /* Vital Product Data */ 272 | 273 | #define PCI_VPD_ADDR 2 /* Address to access (15 bits!) */ 274 | #define PCI_VPD_ADDR_MASK 0x7fff /* Address mask */ 275 | #define PCI_VPD_ADDR_F 0x8000 /* Write 0, 1 indicates completion */ 276 | #define PCI_VPD_DATA 4 /* 32-bits of data returned here */ 277 | 278 | /* Slot Identification */ 279 | 280 | #define PCI_SID_ESR 2 /* Expansion Slot Register */ 281 | #define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */ 282 | #define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */ 283 | #define PCI_SID_CHASSIS_NR 3 /* Chassis Number */ 284 | 285 | /* Message Signalled Interrupts registers */ 286 | 287 | #define PCI_MSI_FLAGS 2 /* Various flags */ 288 | #define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */ 289 | #define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */ 290 | #define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */ 291 | #define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */ 292 | #define PCI_MSI_FLAGS_MASKBIT 0x100 /* 64-bit mask bits allowed */ 293 | #define PCI_MSI_RFU 3 /* Rest of capability flags */ 294 | #define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */ 295 | #define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */ 296 | #define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */ 297 | #define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */ 298 | #define PCI_MSI_MASK_BIT 16 /* Mask bits register */ 299 | 300 | /* MSI-X registers (these are at offset PCI_MSIX_FLAGS) */ 301 | #define PCI_MSIX_FLAGS 2 302 | #define PCI_MSIX_FLAGS_QSIZE 0x7FF 303 | #define PCI_MSIX_FLAGS_ENABLE (1 << 15) 304 | #define PCI_MSIX_FLAGS_MASKALL (1 << 14) 305 | #define PCI_MSIX_FLAGS_BIRMASK (7 << 0) 306 | #define PCI_MSIX_FLAGS_BITMASK (1 << 0) 307 | 308 | /* CompactPCI Hotswap Register */ 309 | 310 | #define PCI_CHSWP_CSR 2 /* Control and Status Register */ 311 | #define PCI_CHSWP_DHA 0x01 /* Device Hiding Arm */ 312 | #define PCI_CHSWP_EIM 0x02 /* ENUM# Signal Mask */ 313 | #define PCI_CHSWP_PIE 0x04 /* Pending Insert or Extract */ 314 | #define PCI_CHSWP_LOO 0x08 /* LED On / Off */ 315 | #define PCI_CHSWP_PI 0x30 /* Programming Interface */ 316 | #define PCI_CHSWP_EXT 0x40 /* ENUM# status - extraction */ 317 | #define PCI_CHSWP_INS 0x80 /* ENUM# status - insertion */ 318 | 319 | /* PCI-X registers */ 320 | 321 | #define PCI_X_CMD 2 /* Modes & Features */ 322 | #define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */ 323 | #define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */ 324 | #define PCI_X_CMD_READ_512 0x0000 /* 512 byte maximum read byte count */ 325 | #define PCI_X_CMD_READ_1K 0x0004 /* 1Kbyte maximum read byte count */ 326 | #define PCI_X_CMD_READ_2K 0x0008 /* 2Kbyte maximum read byte count */ 327 | #define PCI_X_CMD_READ_4K 0x000c /* 4Kbyte maximum read byte count */ 328 | #define PCI_X_CMD_MAX_READ 0x000c /* Max Memory Read Byte Count */ 329 | /* Max # of outstanding split transactions */ 330 | #define PCI_X_CMD_SPLIT_1 0x0000 /* Max 1 */ 331 | #define PCI_X_CMD_SPLIT_2 0x0010 /* Max 2 */ 332 | #define PCI_X_CMD_SPLIT_3 0x0020 /* Max 3 */ 333 | #define PCI_X_CMD_SPLIT_4 0x0030 /* Max 4 */ 334 | #define PCI_X_CMD_SPLIT_8 0x0040 /* Max 8 */ 335 | #define PCI_X_CMD_SPLIT_12 0x0050 /* Max 12 */ 336 | #define PCI_X_CMD_SPLIT_16 0x0060 /* Max 16 */ 337 | #define PCI_X_CMD_SPLIT_32 0x0070 /* Max 32 */ 338 | #define PCI_X_CMD_MAX_SPLIT 0x0070 /* Max Outstanding Split Transactions */ 339 | #define PCI_X_CMD_VERSION(x) (((x) >> 12) & 3) /* Version */ 340 | #define PCI_X_STATUS 4 /* PCI-X capabilities */ 341 | #define PCI_X_STATUS_DEVFN 0x000000ff /* A copy of devfn */ 342 | #define PCI_X_STATUS_BUS 0x0000ff00 /* A copy of bus nr */ 343 | #define PCI_X_STATUS_64BIT 0x00010000 /* 64-bit device */ 344 | #define PCI_X_STATUS_133MHZ 0x00020000 /* 133 MHz capable */ 345 | #define PCI_X_STATUS_SPL_DISC 0x00040000 /* Split Completion Discarded */ 346 | #define PCI_X_STATUS_UNX_SPL 0x00080000 /* Unexpected Split Completion */ 347 | #define PCI_X_STATUS_COMPLEX 0x00100000 /* Device Complexity */ 348 | #define PCI_X_STATUS_MAX_READ 0x00600000 /* Designed Max Memory Read Count */ 349 | #define PCI_X_STATUS_MAX_SPLIT 0x03800000 /* Designed Max Outstanding Split Transactions */ 350 | #define PCI_X_STATUS_MAX_CUM 0x1c000000 /* Designed Max Cumulative Read Size */ 351 | #define PCI_X_STATUS_SPL_ERR 0x20000000 /* Rcvd Split Completion Error Msg */ 352 | #define PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */ 353 | #define PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */ 354 | 355 | /* PCI Express capability registers */ 356 | 357 | #define PCI_EXP_FLAGS 2 /* Capabilities register */ 358 | #define PCI_EXP_FLAGS_VERS 0x000f /* Capability version */ 359 | #define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */ 360 | #define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */ 361 | #define PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */ 362 | #define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */ 363 | #define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */ 364 | #define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */ 365 | #define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */ 366 | #define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */ 367 | #define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */ 368 | #define PCI_EXP_DEVCAP 4 /* Device capabilities */ 369 | #define PCI_EXP_DEVCAP_PAYLOAD 0x07 /* Max_Payload_Size */ 370 | #define PCI_EXP_DEVCAP_PHANTOM 0x18 /* Phantom functions */ 371 | #define PCI_EXP_DEVCAP_EXT_TAG 0x20 /* Extended tags */ 372 | #define PCI_EXP_DEVCAP_L0S 0x1c0 /* L0s Acceptable Latency */ 373 | #define PCI_EXP_DEVCAP_L1 0xe00 /* L1 Acceptable Latency */ 374 | #define PCI_EXP_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */ 375 | #define PCI_EXP_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */ 376 | #define PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */ 377 | #define PCI_EXP_DEVCAP_RBER 0x8000 /* Role-Based Error Reporting */ 378 | #define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */ 379 | #define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */ 380 | #define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */ 381 | #define PCI_EXP_DEVCTL 8 /* Device Control */ 382 | #define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */ 383 | #define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */ 384 | #define PCI_EXP_DEVCTL_FERE 0x0004 /* Fatal Error Reporting Enable */ 385 | #define PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */ 386 | #define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */ 387 | #define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */ 388 | #define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */ 389 | #define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */ 390 | #define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */ 391 | #define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */ 392 | #define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */ 393 | #define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */ 394 | #define PCI_EXP_DEVSTA 10 /* Device Status */ 395 | #define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */ 396 | #define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */ 397 | #define PCI_EXP_DEVSTA_FED 0x04 /* Fatal Error Detected */ 398 | #define PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */ 399 | #define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */ 400 | #define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */ 401 | #define PCI_EXP_LNKCAP 12 /* Link Capabilities */ 402 | #define PCI_EXP_LNKCAP_ASPMS 0xc00 /* ASPM Support */ 403 | #define PCI_EXP_LNKCAP_L0SEL 0x7000 /* L0s Exit Latency */ 404 | #define PCI_EXP_LNKCAP_L1EL 0x38000 /* L1 Exit Latency */ 405 | #define PCI_EXP_LNKCAP_CLKPM 0x40000 /* L1 Clock Power Management */ 406 | #define PCI_EXP_LNKCTL 16 /* Link Control */ 407 | #define PCI_EXP_LNKCTL_RL 0x20 /* Retrain Link */ 408 | #define PCI_EXP_LNKCTL_CCC 0x40 /* Common Clock COnfiguration */ 409 | #define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */ 410 | #define PCI_EXP_LNKSTA 18 /* Link Status */ 411 | #define PCI_EXP_LNKSTA_LT 0x800 /* Link Training */ 412 | #define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */ 413 | #define PCI_EXP_SLTCAP 20 /* Slot Capabilities */ 414 | #define PCI_EXP_SLTCTL 24 /* Slot Control */ 415 | #define PCI_EXP_SLTSTA 26 /* Slot Status */ 416 | #define PCI_EXP_RTCTL 28 /* Root Control */ 417 | #define PCI_EXP_RTCTL_SECEE 0x01 /* System Error on Correctable Error */ 418 | #define PCI_EXP_RTCTL_SENFEE 0x02 /* System Error on Non-Fatal Error */ 419 | #define PCI_EXP_RTCTL_SEFEE 0x04 /* System Error on Fatal Error */ 420 | #define PCI_EXP_RTCTL_PMEIE 0x08 /* PME Interrupt Enable */ 421 | #define PCI_EXP_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */ 422 | #define PCI_EXP_RTCAP 30 /* Root Capabilities */ 423 | #define PCI_EXP_RTSTA 32 /* Root Status */ 424 | #define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */ 425 | #define PCI_EXP_DEVCAP2_ARI 0x20 /* Alternative Routing-ID */ 426 | #define PCI_EXP_DEVCTL2 40 /* Device Control 2 */ 427 | #define PCI_EXP_DEVCTL2_ARI 0x20 /* Alternative Routing-ID */ 428 | 429 | /* Extended Capabilities (PCI-X 2.0 and Express) */ 430 | #define PCI_EXT_CAP_ID(header) (header & 0x0000ffff) 431 | #define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf) 432 | #define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc) 433 | 434 | #define PCI_EXT_CAP_ID_ERR 1 435 | #define PCI_EXT_CAP_ID_VC 2 436 | #define PCI_EXT_CAP_ID_DSN 3 437 | #define PCI_EXT_CAP_ID_PWR 4 438 | #define PCI_EXT_CAP_ID_ARI 14 439 | 440 | /* Advanced Error Reporting */ 441 | #define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */ 442 | #define PCI_ERR_UNC_TRAIN 0x00000001 /* Training */ 443 | #define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */ 444 | #define PCI_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */ 445 | #define PCI_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */ 446 | #define PCI_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */ 447 | #define PCI_ERR_UNC_COMP_ABORT 0x00008000 /* Completer Abort */ 448 | #define PCI_ERR_UNC_UNX_COMP 0x00010000 /* Unexpected Completion */ 449 | #define PCI_ERR_UNC_RX_OVER 0x00020000 /* Receiver Overflow */ 450 | #define PCI_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */ 451 | #define PCI_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */ 452 | #define PCI_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */ 453 | #define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */ 454 | /* Same bits as above */ 455 | #define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */ 456 | /* Same bits as above */ 457 | #define PCI_ERR_COR_STATUS 16 /* Correctable Error Status */ 458 | #define PCI_ERR_COR_RCVR 0x00000001 /* Receiver Error Status */ 459 | #define PCI_ERR_COR_BAD_TLP 0x00000040 /* Bad TLP Status */ 460 | #define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */ 461 | #define PCI_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */ 462 | #define PCI_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */ 463 | #define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */ 464 | /* Same bits as above */ 465 | #define PCI_ERR_CAP 24 /* Advanced Error Capabilities */ 466 | #define PCI_ERR_CAP_FEP(x) ((x) & 31) /* First Error Pointer */ 467 | #define PCI_ERR_CAP_ECRC_GENC 0x00000020 /* ECRC Generation Capable */ 468 | #define PCI_ERR_CAP_ECRC_GENE 0x00000040 /* ECRC Generation Enable */ 469 | #define PCI_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */ 470 | #define PCI_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */ 471 | #define PCI_ERR_HEADER_LOG 28 /* Header Log Register (16 bytes) */ 472 | #define PCI_ERR_ROOT_COMMAND 44 /* Root Error Command */ 473 | /* Correctable Err Reporting Enable */ 474 | #define PCI_ERR_ROOT_CMD_COR_EN 0x00000001 475 | /* Non-fatal Err Reporting Enable */ 476 | #define PCI_ERR_ROOT_CMD_NONFATAL_EN 0x00000002 477 | /* Fatal Err Reporting Enable */ 478 | #define PCI_ERR_ROOT_CMD_FATAL_EN 0x00000004 479 | #define PCI_ERR_ROOT_STATUS 48 480 | #define PCI_ERR_ROOT_COR_RCV 0x00000001 /* ERR_COR Received */ 481 | /* Multi ERR_COR Received */ 482 | #define PCI_ERR_ROOT_MULTI_COR_RCV 0x00000002 483 | /* ERR_FATAL/NONFATAL Recevied */ 484 | #define PCI_ERR_ROOT_UNCOR_RCV 0x00000004 485 | /* Multi ERR_FATAL/NONFATAL Recevied */ 486 | #define PCI_ERR_ROOT_MULTI_UNCOR_RCV 0x00000008 487 | #define PCI_ERR_ROOT_FIRST_FATAL 0x00000010 /* First Fatal */ 488 | #define PCI_ERR_ROOT_NONFATAL_RCV 0x00000020 /* Non-Fatal Received */ 489 | #define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */ 490 | #define PCI_ERR_ROOT_COR_SRC 52 491 | #define PCI_ERR_ROOT_SRC 54 492 | 493 | /* Virtual Channel */ 494 | #define PCI_VC_PORT_REG1 4 495 | #define PCI_VC_PORT_REG2 8 496 | #define PCI_VC_PORT_CTRL 12 497 | #define PCI_VC_PORT_STATUS 14 498 | #define PCI_VC_RES_CAP 16 499 | #define PCI_VC_RES_CTRL 20 500 | #define PCI_VC_RES_STATUS 26 501 | 502 | /* Power Budgeting */ 503 | #define PCI_PWR_DSR 4 /* Data Select Register */ 504 | #define PCI_PWR_DATA 8 /* Data Register */ 505 | #define PCI_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */ 506 | #define PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */ 507 | #define PCI_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */ 508 | #define PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */ 509 | #define PCI_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */ 510 | #define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */ 511 | #define PCI_PWR_CAP 12 /* Capability */ 512 | #define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */ 513 | 514 | /* 515 | * Hypertransport sub capability types 516 | * 517 | * Unfortunately there are both 3 bit and 5 bit capability types defined 518 | * in the HT spec, catering for that is a little messy. You probably don't 519 | * want to use these directly, just use pci_find_ht_capability() and it 520 | * will do the right thing for you. 521 | */ 522 | #define HT_3BIT_CAP_MASK 0xE0 523 | #define HT_CAPTYPE_SLAVE 0x00 /* Slave/Primary link configuration */ 524 | #define HT_CAPTYPE_HOST 0x20 /* Host/Secondary link configuration */ 525 | 526 | #define HT_5BIT_CAP_MASK 0xF8 527 | #define HT_CAPTYPE_IRQ 0x80 /* IRQ Configuration */ 528 | #define HT_CAPTYPE_REMAPPING_40 0xA0 /* 40 bit address remapping */ 529 | #define HT_CAPTYPE_REMAPPING_64 0xA2 /* 64 bit address remapping */ 530 | #define HT_CAPTYPE_UNITID_CLUMP 0x90 /* Unit ID clumping */ 531 | #define HT_CAPTYPE_EXTCONF 0x98 /* Extended Configuration Space Access */ 532 | #define HT_CAPTYPE_MSI_MAPPING 0xA8 /* MSI Mapping Capability */ 533 | #define HT_MSI_FLAGS 0x02 /* Offset to flags */ 534 | #define HT_MSI_FLAGS_ENABLE 0x1 /* Mapping enable */ 535 | #define HT_MSI_FLAGS_FIXED 0x2 /* Fixed mapping only */ 536 | #define HT_MSI_FIXED_ADDR 0x00000000FEE00000ULL /* Fixed addr */ 537 | #define HT_MSI_ADDR_LO 0x04 /* Offset to low addr bits */ 538 | #define HT_MSI_ADDR_LO_MASK 0xFFF00000 /* Low address bit mask */ 539 | #define HT_MSI_ADDR_HI 0x08 /* Offset to high addr bits */ 540 | #define HT_CAPTYPE_DIRECT_ROUTE 0xB0 /* Direct routing configuration */ 541 | #define HT_CAPTYPE_VCSET 0xB8 /* Virtual Channel configuration */ 542 | #define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */ 543 | #define HT_CAPTYPE_GEN3 0xD0 /* Generation 3 hypertransport configuration */ 544 | #define HT_CAPTYPE_PM 0xE0 /* Hypertransport powermanagement configuration */ 545 | 546 | /* Alternative Routing-ID Interpretation */ 547 | #define PCI_ARI_CAP 0x04 /* ARI Capability Register */ 548 | #define PCI_ARI_CAP_MFVC 0x0001 /* MFVC Function Groups Capability */ 549 | #define PCI_ARI_CAP_ACS 0x0002 /* ACS Function Groups Capability */ 550 | #define PCI_ARI_CAP_NFN(x) (((x) >> 8) & 0xff) /* Next Function Number */ 551 | #define PCI_ARI_CTRL 0x06 /* ARI Control Register */ 552 | #define PCI_ARI_CTRL_MFVC 0x0001 /* MFVC Function Groups Enable */ 553 | #define PCI_ARI_CTRL_ACS 0x0002 /* ACS Function Groups Enable */ 554 | #define PCI_ARI_CTRL_FG(x) (((x) >> 4) & 7) /* Function Group */ 555 | 556 | #endif /* LINUX_PCI_REGS_H */ 557 | -------------------------------------------------------------------------------- /printf.c: -------------------------------------------------------------------------------- 1 | /* A reduced version of the printf function. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #include "console.h" 22 | #include "protos.h" 23 | 24 | static int print_buf_pad(char *buf, int buflen, char *p, int width, int pad) 25 | { 26 | int len = buf + buflen - p; 27 | int r = 0; 28 | 29 | if (width > len) 30 | { 31 | *--p = pad; 32 | len++; 33 | 34 | while (width > buflen) 35 | { 36 | crb_puts(0, p, 1); 37 | width--; 38 | r++; 39 | } 40 | while (width > len) 41 | *--p = pad, len++; 42 | } 43 | 44 | crb_puts(0, p, len); 45 | return r + len; 46 | } 47 | 48 | static int print_decimal(unsigned long val, int width, int pad) 49 | { 50 | char buf[32]; 51 | char *p = buf + sizeof(buf); 52 | 53 | if (val == 0) 54 | *--p = '0'; 55 | else 56 | { 57 | do 58 | { 59 | unsigned long d, r; 60 | 61 | /* Compiling with -Os results in a call to the division routine. 62 | Do what the compiler ought to have done. */ 63 | d = __builtin_alpha_umulh(val, 0xcccccccccccccccd); 64 | d >>= 3; 65 | r = val - (d * 10); 66 | 67 | *--p = r + '0'; 68 | val = d; 69 | } 70 | while (val); 71 | } 72 | 73 | return print_buf_pad(buf, sizeof(buf), p, width, pad); 74 | } 75 | 76 | static int print_hex(unsigned long val, int width, char pad) 77 | { 78 | char buf[32]; 79 | char *p = buf + sizeof(buf); 80 | 81 | if (val == 0) 82 | *--p = '0'; 83 | else 84 | { 85 | do 86 | { 87 | int d = val % 16; 88 | *--p = (d < 10 ? '0' : 'a' - 10) + d; 89 | val /= 16; 90 | } 91 | while (val); 92 | } 93 | 94 | return print_buf_pad(buf, sizeof(buf), p, width, pad); 95 | } 96 | 97 | int printf(const char *fmt, ...) 98 | { 99 | va_list args; 100 | unsigned long val; 101 | int r = 0; 102 | 103 | va_start(args, fmt); 104 | 105 | for (; *fmt ; fmt++) 106 | if (*fmt != '%') 107 | { 108 | crb_puts(0, fmt, 1); 109 | r++; 110 | } 111 | else 112 | { 113 | const char *percent = fmt; 114 | bool is_long = false; 115 | char pad = ' '; 116 | int width = 0; 117 | 118 | restart: 119 | switch (*++fmt) 120 | { 121 | case '%': 122 | crb_puts(0, "%", 1); 123 | r++; 124 | break; 125 | 126 | case 'l': 127 | is_long = true; 128 | goto restart; 129 | 130 | case 'd': 131 | if (is_long) 132 | { 133 | long d = va_arg (args, long); 134 | if (d < 0) 135 | { 136 | crb_puts(0, "-", 1); 137 | d = -d; 138 | } 139 | val = d; 140 | } 141 | else 142 | { 143 | int d = va_arg (args, int); 144 | if (d < 0) 145 | { 146 | crb_puts(0, "-", 1); 147 | d = -d; 148 | r++; 149 | } 150 | val = d; 151 | } 152 | goto do_unsigned; 153 | 154 | case 'u': 155 | if (is_long) 156 | val = va_arg (args, unsigned long); 157 | else 158 | val = va_arg (args, unsigned int); 159 | 160 | do_unsigned: 161 | r += print_decimal (val, width, pad); 162 | break; 163 | 164 | case 'x': 165 | if (is_long) 166 | val = va_arg (args, unsigned long); 167 | else 168 | val = va_arg (args, unsigned int); 169 | r += print_hex (val, width, pad); 170 | break; 171 | 172 | case 's': 173 | { 174 | const char *s = va_arg (args, const char *); 175 | int len = strlen(s); 176 | crb_puts(0, s, len); 177 | r += len; 178 | } 179 | break; 180 | 181 | case '0': 182 | pad = '0'; 183 | case '1' ... '9': 184 | width = *fmt - '0'; 185 | while (fmt[1] >= '0' && fmt[1] <= '9') 186 | width = width * 10 + *++fmt - '0'; 187 | goto restart; 188 | 189 | default: 190 | { 191 | int len = fmt - percent; 192 | crb_puts(0, percent, len); 193 | r += len; 194 | } 195 | break; 196 | } 197 | } 198 | 199 | va_end(args); 200 | return r; 201 | } 202 | -------------------------------------------------------------------------------- /protos.h: -------------------------------------------------------------------------------- 1 | /* Declarations common the the C portions of the QEMU PALcode console. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #ifndef PROTOS_H 22 | #define PROTOS_H 1 23 | 24 | /* Stand-alone definitions for various types, compatible with 25 | the Alpha Linux ABI and GCC. This eliminates dependencies 26 | on external headers. */ 27 | typedef unsigned char uint8_t; 28 | typedef unsigned short uint16_t; 29 | typedef unsigned int uint32_t; 30 | typedef unsigned long uint64_t; 31 | typedef unsigned long size_t; 32 | 33 | #define bool _Bool 34 | #define true 1 35 | #define false 0 36 | 37 | #define offsetof(type, member) __builtin_offsetof(type, member) 38 | 39 | typedef __builtin_va_list va_list; 40 | #define va_start(ap, last) __builtin_va_start((ap), (last)) 41 | #define va_arg __builtin_va_arg 42 | #define va_end(ap) __builtin_va_end(ap) 43 | 44 | #define NULL ((void *)0) 45 | 46 | extern void *memset(void *, int, size_t); 47 | extern void *memcpy(void *, const void *, size_t); 48 | extern size_t strlen(const char *); 49 | 50 | /* 51 | * Call_Pal functions. 52 | */ 53 | 54 | static inline void wrent(void *cb, unsigned long which) 55 | { 56 | register void *a0 __asm__("$16") = cb; 57 | register unsigned long a1 __asm__("$17") = which; 58 | 59 | asm volatile ("call_pal 0x34" 60 | : "+r"(a0), "+r"(a1) 61 | : : "$1", "$22", "$23", "$24", "$25"); 62 | } 63 | 64 | static inline unsigned long swpipl(unsigned long newipl) 65 | { 66 | register unsigned long v0 __asm__("$0"); 67 | register unsigned long a0 __asm__("$16") = newipl; 68 | 69 | asm volatile ("call_pal 0x35" 70 | : "=r"(v0), "+r"(a0) 71 | : : "$1", "$22", "$23", "$24", "$25"); 72 | 73 | return v0; 74 | } 75 | 76 | static inline unsigned long rdps(void) 77 | { 78 | register unsigned long v0 __asm__("$0"); 79 | 80 | asm volatile ("call_pal 0x36" 81 | : "=r"(v0) : : "$1", "$22", "$23", "$24", "$25"); 82 | 83 | return v0; 84 | } 85 | 86 | static inline void wrkgp(void) 87 | { 88 | asm volatile ("mov $29, $16\n\tcall_pal 0x37" 89 | : : : "$16", "$1", "$22", "$23", "$24", "$25"); 90 | } 91 | 92 | static inline unsigned long wtint(unsigned long skip) 93 | { 94 | register unsigned long v0 __asm__("$0"); 95 | register unsigned long a0 __asm__("$16") = skip; 96 | 97 | asm volatile ("call_pal 0x3e" 98 | : "=r"(v0), "+r"(a0) 99 | : : "$1", "$22", "$23", "$24", "$25"); 100 | 101 | return v0; 102 | } 103 | 104 | /* 105 | * Cserve functions. 106 | */ 107 | 108 | static inline unsigned long ldq_p(unsigned long addr) 109 | { 110 | register unsigned long v0 __asm__("$0"); 111 | register unsigned long a0 __asm__("$16") = 1; 112 | register unsigned long a1 __asm__("$17") = addr; 113 | 114 | asm volatile ("call_pal 9" 115 | : "=r"(v0), "+r"(a0), "+r"(a1) : 116 | : "$18", "$19", "$20", "$21"); 117 | 118 | return v0; 119 | } 120 | 121 | static inline unsigned long stq_p(unsigned long port, unsigned long val) 122 | { 123 | register unsigned long v0 __asm__("$0"); 124 | register unsigned long a0 __asm__("$16") = 2; 125 | register unsigned long a1 __asm__("$17") = port; 126 | register unsigned long a2 __asm__("$18") = val; 127 | 128 | asm volatile ("call_pal 9" 129 | : "=r"(v0), "+r"(a0), "+r"(a1), "+r"(a2) : 130 | : "$19", "$20", "$21"); 131 | 132 | return v0; 133 | } 134 | 135 | static inline unsigned long get_wall_time(void) 136 | { 137 | register unsigned long v0 __asm__("$0"); 138 | register unsigned long a0 __asm__("$16") = 3; 139 | 140 | asm("call_pal 9" : "=r"(v0), "+r"(a0) : : "$17", "$18", "$19", "$20", "$21"); 141 | 142 | return v0; 143 | } 144 | 145 | static inline unsigned long get_alarm(void) 146 | { 147 | register unsigned long v0 __asm__("$0"); 148 | register unsigned long a0 __asm__("$16") = 4; 149 | 150 | asm("call_pal 9" : "=r"(v0), "+r"(a0) : : "$17", "$18", "$19", "$20", "$21"); 151 | 152 | return v0; 153 | } 154 | 155 | static inline void set_alarm_rel(unsigned long nsec) 156 | { 157 | register unsigned long a0 __asm__("$16") = 5; 158 | register unsigned long a1 __asm__("$17") = nsec; 159 | 160 | asm volatile ("call_pal 9" 161 | : "+r"(a0), "+r"(a1) 162 | : : "$0", "$18", "$19", "$20", "$21"); 163 | } 164 | 165 | static inline void set_alarm_abs(unsigned long nsec) 166 | { 167 | register unsigned long a0 __asm__("$16") = 6; 168 | register unsigned long a1 __asm__("$17") = nsec; 169 | 170 | asm volatile ("call_pal 9" 171 | : "+r"(a0), "+r"(a1) 172 | : : "$0", "$18", "$19", "$20", "$21"); 173 | } 174 | 175 | /* 176 | * I/O functions 177 | */ 178 | 179 | extern void *pci_io_base; 180 | extern void *pci_mem_base; 181 | 182 | static inline uint8_t inb(unsigned long port) 183 | { 184 | return *(volatile uint8_t *)(pci_io_base + port); 185 | } 186 | 187 | static inline uint16_t inw(unsigned long port) 188 | { 189 | return *(volatile uint16_t *)(pci_io_base + port); 190 | } 191 | 192 | static inline uint32_t inl(unsigned long port) 193 | { 194 | return *(volatile uint32_t *)(pci_io_base + port); 195 | } 196 | 197 | static inline void outb(uint8_t val, unsigned long port) 198 | { 199 | *(volatile uint8_t *)(pci_io_base + port) = val; 200 | } 201 | 202 | static inline void outw(uint16_t val, unsigned long port) 203 | { 204 | *(volatile uint16_t *)(pci_io_base + port) = val; 205 | } 206 | 207 | static inline void outl(uint32_t val, unsigned long port) 208 | { 209 | *(volatile uint32_t *)(pci_io_base + port) = val; 210 | } 211 | 212 | /* 213 | * CRB functions 214 | */ 215 | 216 | extern unsigned long crb_dispatch(long select, long a1, long a2, 217 | long a3, long a4); 218 | extern unsigned long crb_fixup(unsigned long vptptr, unsigned long hwrpb); 219 | 220 | /* 221 | * The Console 222 | */ 223 | 224 | extern bool have_vga; 225 | extern unsigned int pci_vga_bus; 226 | extern unsigned int pci_vga_dev; 227 | 228 | extern void do_console(void); 229 | extern void entInt(void); 230 | 231 | /* 232 | * Utils 233 | */ 234 | 235 | extern int printf(const char *, ...); 236 | extern void ndelay(unsigned long nsec); 237 | 238 | static inline void udelay(unsigned long msec) 239 | { 240 | ndelay(msec * 1000); 241 | } 242 | 243 | /* 244 | * Initialization 245 | */ 246 | extern void ps2port_setup(void); 247 | extern void pci_setup(void); 248 | extern void vgahw_init(void); 249 | 250 | #endif /* PROTOS_H */ 251 | -------------------------------------------------------------------------------- /ps2port.c: -------------------------------------------------------------------------------- 1 | // Support for handling the PS/2 mouse/keyboard ports. 2 | // 3 | // Copyright (C) 2008 Kevin O'Connor 4 | // Several ideas taken from code Copyright (c) 1999-2004 Vojtech Pavlik 5 | // 6 | // This file may be distributed under the terms of the GNU LGPLv3 license. 7 | // 8 | // This file is copied (mostly) intact from SeaBIOS. 9 | 10 | #include "protos.h" 11 | #include "ioport.h" 12 | #include "ps2port.h" 13 | 14 | typedef uint64_t u64; 15 | 16 | #define dprintf(lvl, fmt, ...) 17 | #define warn_timeout() 18 | 19 | static inline u64 20 | calc_future_tsc(int timeout) 21 | { 22 | return get_wall_time() + timeout; 23 | } 24 | 25 | static inline bool 26 | check_tsc(u64 end) 27 | { 28 | return get_wall_time() > end; 29 | } 30 | 31 | static inline void 32 | yield(void) 33 | { 34 | udelay(1); 35 | } 36 | 37 | static struct { 38 | u8 ps2ctr; 39 | } ebda; 40 | 41 | #define GET_EBDA(VAR) ebda.VAR 42 | #define SET_EBDA(VAR, VAL) (ebda.VAR = (VAL)) 43 | 44 | #define ASSERT32FLAT() 45 | #define CONFIG_PS2PORT 1 46 | 47 | #define enable_hwirq(level, func) 48 | #define run_thread(func, val) func(val) 49 | 50 | /**************************************************************** 51 | * Low level i8042 commands. 52 | ****************************************************************/ 53 | 54 | // Timeout value. 55 | #define I8042_CTL_TIMEOUT 10000 56 | 57 | #define I8042_BUFFER_SIZE 16 58 | 59 | static int 60 | i8042_wait_read(void) 61 | { 62 | dprintf(7, "i8042_wait_read\n"); 63 | int i; 64 | for (i=0; i> 8) & 0xf; 110 | int send = (command >> 12) & 0xf; 111 | 112 | // Send the command. 113 | int ret = i8042_wait_write(); 114 | if (ret) 115 | return ret; 116 | outb(command, PORT_PS2_STATUS); 117 | 118 | // Send parameters (if any). 119 | int i; 120 | for (i = 0; i < send; i++) { 121 | ret = i8042_wait_write(); 122 | if (ret) 123 | return ret; 124 | outb(param[i], PORT_PS2_DATA); 125 | } 126 | 127 | // Receive parameters (if any). 128 | for (i = 0; i < receive; i++) { 129 | ret = i8042_wait_read(); 130 | if (ret) 131 | return ret; 132 | param[i] = inb(PORT_PS2_DATA); 133 | dprintf(7, "i8042 param=%x\n", param[i]); 134 | } 135 | 136 | return 0; 137 | } 138 | 139 | static int 140 | i8042_command(int command, u8 *param) 141 | { 142 | dprintf(7, "i8042_command cmd=%x\n", command); 143 | int ret = __i8042_command(command, param); 144 | if (ret) 145 | dprintf(2, "i8042 command %x failed\n", command); 146 | return ret; 147 | } 148 | 149 | static int 150 | i8042_kbd_write(u8 c) 151 | { 152 | dprintf(7, "i8042_kbd_write c=%d\n", c); 153 | int ret = i8042_wait_write(); 154 | if (! ret) 155 | outb(c, PORT_PS2_DATA); 156 | return ret; 157 | } 158 | 159 | static int 160 | i8042_aux_write(u8 c) 161 | { 162 | return i8042_command(I8042_CMD_AUX_SEND, &c); 163 | } 164 | 165 | void 166 | i8042_reboot(void) 167 | { 168 | int i; 169 | for (i=0; i<10; i++) { 170 | i8042_wait_write(); 171 | udelay(50); 172 | outb(0xfe, PORT_PS2_STATUS); /* pulse reset low */ 173 | udelay(50); 174 | } 175 | } 176 | 177 | 178 | /**************************************************************** 179 | * Device commands. 180 | ****************************************************************/ 181 | 182 | #define PS2_RET_ACK 0xfa 183 | #define PS2_RET_NAK 0xfe 184 | 185 | static int 186 | ps2_recvbyte(int aux, int needack, int timeout) 187 | { 188 | u64 end = calc_future_tsc(timeout); 189 | for (;;) { 190 | u8 status = inb(PORT_PS2_STATUS); 191 | if (status & I8042_STR_OBF) { 192 | u8 data = inb(PORT_PS2_DATA); 193 | dprintf(7, "ps2 read %x\n", data); 194 | 195 | if (!!(status & I8042_STR_AUXDATA) == aux) { 196 | if (!needack) 197 | return data; 198 | if (data == PS2_RET_ACK) 199 | return data; 200 | if (data == PS2_RET_NAK) { 201 | dprintf(1, "Got ps2 nak (status=%x)\n", status); 202 | return data; 203 | } 204 | } 205 | 206 | // This data not part of command - just discard it. 207 | dprintf(1, "Discarding ps2 data %02x (status=%02x)\n", data, status); 208 | } 209 | 210 | if (check_tsc(end)) { 211 | // Don't warn on second byte of a reset 212 | if (timeout > 100) 213 | warn_timeout(); 214 | return -1; 215 | } 216 | yield(); 217 | } 218 | } 219 | 220 | static int 221 | ps2_sendbyte(int aux, u8 command, int timeout) 222 | { 223 | dprintf(7, "ps2_sendbyte aux=%d cmd=%x\n", aux, command); 224 | int ret; 225 | if (aux) 226 | ret = i8042_aux_write(command); 227 | else 228 | ret = i8042_kbd_write(command); 229 | if (ret) 230 | return ret; 231 | 232 | // Read ack. 233 | ret = ps2_recvbyte(aux, 1, timeout); 234 | if (ret < 0) 235 | return ret; 236 | if (ret != PS2_RET_ACK) 237 | return -1; 238 | 239 | return 0; 240 | } 241 | 242 | static int 243 | __ps2_command(int aux, int command, u8 *param) 244 | { 245 | int ret2; 246 | int receive = (command >> 8) & 0xf; 247 | int send = (command >> 12) & 0xf; 248 | 249 | // Disable interrupts and keyboard/mouse. 250 | u8 ps2ctr = GET_EBDA(ps2ctr); 251 | u8 newctr = ((ps2ctr | I8042_CTR_AUXDIS | I8042_CTR_KBDDIS) 252 | & ~(I8042_CTR_KBDINT|I8042_CTR_AUXINT)); 253 | dprintf(6, "i8042 ctr old=%x new=%x\n", ps2ctr, newctr); 254 | int ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr); 255 | if (ret) 256 | return ret; 257 | 258 | // Flush any interrupts already pending. 259 | yield(); 260 | 261 | // Enable port command is being sent to. 262 | if (aux) 263 | newctr &= ~I8042_CTR_AUXDIS; 264 | else 265 | newctr &= ~I8042_CTR_KBDDIS; 266 | ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr); 267 | if (ret) 268 | goto fail; 269 | 270 | if (command == ATKBD_CMD_RESET_BAT) { 271 | // Reset is special wrt timeouts and bytes received. 272 | 273 | // Send command. 274 | ret = ps2_sendbyte(aux, command, 1000); 275 | if (ret) 276 | goto fail; 277 | 278 | // Receive parameters. 279 | ret = ps2_recvbyte(aux, 0, 4000); 280 | if (ret < 0) 281 | goto fail; 282 | param[0] = ret; 283 | ret = ps2_recvbyte(aux, 0, 100); 284 | if (ret < 0) 285 | // Some devices only respond with one byte on reset. 286 | ret = 0; 287 | param[1] = ret; 288 | } else if (command == ATKBD_CMD_GETID) { 289 | // Getid is special wrt bytes received. 290 | 291 | // Send command. 292 | ret = ps2_sendbyte(aux, command, 200); 293 | if (ret) 294 | goto fail; 295 | 296 | // Receive parameters. 297 | ret = ps2_recvbyte(aux, 0, 500); 298 | if (ret < 0) 299 | goto fail; 300 | param[0] = ret; 301 | if (ret == 0xab || ret == 0xac || ret == 0x2b || ret == 0x5d 302 | || ret == 0x60 || ret == 0x47) { 303 | // These ids (keyboards) return two bytes. 304 | ret = ps2_recvbyte(aux, 0, 500); 305 | if (ret < 0) 306 | goto fail; 307 | param[1] = ret; 308 | } else { 309 | param[1] = 0; 310 | } 311 | } else { 312 | // Send command. 313 | ret = ps2_sendbyte(aux, command, 200); 314 | if (ret) 315 | goto fail; 316 | 317 | // Send parameters (if any). 318 | int i; 319 | for (i = 0; i < send; i++) { 320 | ret = ps2_sendbyte(aux, param[i], 200); 321 | if (ret) 322 | goto fail; 323 | } 324 | 325 | // Receive parameters (if any). 326 | for (i = 0; i < receive; i++) { 327 | ret = ps2_recvbyte(aux, 0, 500); 328 | if (ret < 0) 329 | goto fail; 330 | param[i] = ret; 331 | } 332 | } 333 | 334 | ret = 0; 335 | 336 | fail: 337 | // Restore interrupts and keyboard/mouse. 338 | ret2 = i8042_command(I8042_CMD_CTL_WCTR, &ps2ctr); 339 | if (ret2) 340 | return ret2; 341 | 342 | return ret; 343 | } 344 | 345 | static int 346 | ps2_command(int aux, int command, u8 *param) 347 | { 348 | dprintf(7, "ps2_command aux=%d cmd=%x\n", aux, command); 349 | int ret = __ps2_command(aux, command, param); 350 | if (ret) 351 | dprintf(2, "ps2 command %x failed (aux=%d)\n", command, aux); 352 | return ret; 353 | } 354 | 355 | int 356 | ps2_kbd_command(int command, u8 *param) 357 | { 358 | return ps2_command(0, command, param); 359 | } 360 | 361 | int 362 | ps2_mouse_command(int command, u8 *param) 363 | { 364 | return ps2_command(1, command, param); 365 | } 366 | 367 | 368 | /**************************************************************** 369 | * IRQ handlers 370 | ****************************************************************/ 371 | #if 0 372 | 373 | // INT74h : PS/2 mouse hardware interrupt 374 | void VISIBLE16 375 | handle_74(void) 376 | { 377 | if (! CONFIG_PS2PORT) 378 | return; 379 | 380 | debug_isr(DEBUG_ISR_74); 381 | 382 | u8 v = inb(PORT_PS2_STATUS); 383 | if ((v & (I8042_STR_OBF|I8042_STR_AUXDATA)) 384 | != (I8042_STR_OBF|I8042_STR_AUXDATA)) { 385 | dprintf(1, "ps2 mouse irq but no mouse data.\n"); 386 | goto done; 387 | } 388 | v = inb(PORT_PS2_DATA); 389 | 390 | if (!(GET_EBDA(ps2ctr) & I8042_CTR_AUXINT)) 391 | // Interrupts not enabled. 392 | goto done; 393 | 394 | process_mouse(v); 395 | 396 | done: 397 | eoi_pic2(); 398 | } 399 | 400 | // INT09h : Keyboard Hardware Service Entry Point 401 | void VISIBLE16 402 | handle_09(void) 403 | { 404 | if (! CONFIG_PS2PORT) 405 | return; 406 | 407 | debug_isr(DEBUG_ISR_09); 408 | 409 | // read key from keyboard controller 410 | u8 v = inb(PORT_PS2_STATUS); 411 | if (v & I8042_STR_AUXDATA) { 412 | dprintf(1, "ps2 keyboard irq but found mouse data?!\n"); 413 | goto done; 414 | } 415 | v = inb(PORT_PS2_DATA); 416 | 417 | if (!(GET_EBDA(ps2ctr) & I8042_CTR_KBDINT)) 418 | // Interrupts not enabled. 419 | goto done; 420 | 421 | process_key(v); 422 | 423 | done: 424 | eoi_pic1(); 425 | } 426 | 427 | #endif 428 | /**************************************************************** 429 | * Setup 430 | ****************************************************************/ 431 | 432 | static void 433 | keyboard_init(void *data) 434 | { 435 | /* flush incoming keys */ 436 | int ret = i8042_flush(); 437 | if (ret) 438 | return; 439 | 440 | // Controller self-test. 441 | u8 param[2]; 442 | ret = i8042_command(I8042_CMD_CTL_TEST, param); 443 | if (ret) 444 | return; 445 | if (param[0] != 0x55) { 446 | dprintf(1, "i8042 self test failed (got %x not 0x55)\n", param[0]); 447 | return; 448 | } 449 | 450 | // Controller keyboard test. 451 | ret = i8042_command(I8042_CMD_KBD_TEST, param); 452 | if (ret) 453 | return; 454 | if (param[0] != 0x00) { 455 | dprintf(1, "i8042 keyboard test failed (got %x not 0x00)\n", param[0]); 456 | return; 457 | } 458 | 459 | // Disable keyboard and mouse events. 460 | SET_EBDA(ps2ctr, I8042_CTR_KBDDIS | I8042_CTR_AUXDIS); 461 | 462 | 463 | /* ------------------- keyboard side ------------------------*/ 464 | /* reset keyboard and self test (keyboard side) */ 465 | ret = ps2_kbd_command(ATKBD_CMD_RESET_BAT, param); 466 | if (ret) 467 | return; 468 | if (param[0] != 0xaa) { 469 | dprintf(1, "keyboard self test failed (got %x not 0xaa)\n", param[0]); 470 | return; 471 | } 472 | 473 | /* Disable keyboard */ 474 | ret = ps2_kbd_command(ATKBD_CMD_RESET_DIS, NULL); 475 | if (ret) 476 | return; 477 | 478 | // Set scancode command (mode 2) 479 | param[0] = 0x02; 480 | ret = ps2_kbd_command(ATKBD_CMD_SSCANSET, param); 481 | if (ret) 482 | return; 483 | 484 | // Keyboard Mode: disable mouse, scan code convert, enable kbd IRQ 485 | SET_EBDA(ps2ctr, I8042_CTR_AUXDIS | I8042_CTR_XLATE | I8042_CTR_KBDINT); 486 | 487 | /* Enable keyboard */ 488 | ret = ps2_kbd_command(ATKBD_CMD_ENABLE, NULL); 489 | if (ret) 490 | return; 491 | 492 | dprintf(1, "PS2 keyboard initialized\n"); 493 | } 494 | 495 | void 496 | ps2port_setup(void) 497 | { 498 | ASSERT32FLAT(); 499 | if (! CONFIG_PS2PORT) 500 | return; 501 | dprintf(3, "init ps2port\n"); 502 | 503 | enable_hwirq(1, FUNC16(entry_09)); 504 | enable_hwirq(12, FUNC16(entry_74)); 505 | 506 | run_thread(keyboard_init, NULL); 507 | } 508 | -------------------------------------------------------------------------------- /ps2port.h: -------------------------------------------------------------------------------- 1 | /* Basic ps2 port (keyboard/mouse) command handling. 2 | 3 | This file is copied (mostly) intact from SeaBIOS. 4 | It is covered by the GNU Lesser General Public License, v3. 5 | 6 | You should have received a copy of the GNU Lesser General Public License 7 | along with this program; see the file COPYING. If not see 8 | . */ 9 | 10 | #ifndef PS2PORT_H 11 | #define PS2PORT_H 12 | 13 | typedef uint8_t u8; 14 | 15 | // Standard commands. 16 | #define I8042_CMD_CTL_RCTR 0x0120 17 | #define I8042_CMD_CTL_WCTR 0x1060 18 | #define I8042_CMD_CTL_TEST 0x01aa 19 | 20 | #define I8042_CMD_KBD_TEST 0x01ab 21 | #define I8042_CMD_KBD_DISABLE 0x00ad 22 | #define I8042_CMD_KBD_ENABLE 0x00ae 23 | 24 | #define I8042_CMD_AUX_DISABLE 0x00a7 25 | #define I8042_CMD_AUX_ENABLE 0x00a8 26 | #define I8042_CMD_AUX_SEND 0x10d4 27 | 28 | // Keyboard commands 29 | #define ATKBD_CMD_SETLEDS 0x10ed 30 | #define ATKBD_CMD_SSCANSET 0x10f0 31 | #define ATKBD_CMD_GETID 0x02f2 32 | #define ATKBD_CMD_ENABLE 0x00f4 33 | #define ATKBD_CMD_RESET_DIS 0x00f5 34 | #define ATKBD_CMD_RESET_BAT 0x02ff 35 | 36 | // Mouse commands 37 | #define PSMOUSE_CMD_SETSCALE11 0x00e6 38 | #define PSMOUSE_CMD_SETSCALE21 0x00e7 39 | #define PSMOUSE_CMD_SETRES 0x10e8 40 | #define PSMOUSE_CMD_GETINFO 0x03e9 41 | #define PSMOUSE_CMD_GETID 0x02f2 42 | #define PSMOUSE_CMD_SETRATE 0x10f3 43 | #define PSMOUSE_CMD_ENABLE 0x00f4 44 | #define PSMOUSE_CMD_DISABLE 0x00f5 45 | #define PSMOUSE_CMD_RESET_BAT 0x02ff 46 | 47 | // Status register bits. 48 | #define I8042_STR_PARITY 0x80 49 | #define I8042_STR_TIMEOUT 0x40 50 | #define I8042_STR_AUXDATA 0x20 51 | #define I8042_STR_KEYLOCK 0x10 52 | #define I8042_STR_CMDDAT 0x08 53 | #define I8042_STR_MUXERR 0x04 54 | #define I8042_STR_IBF 0x02 55 | #define I8042_STR_OBF 0x01 56 | 57 | // Control register bits. 58 | #define I8042_CTR_KBDINT 0x01 59 | #define I8042_CTR_AUXINT 0x02 60 | #define I8042_CTR_IGNKEYLOCK 0x08 61 | #define I8042_CTR_KBDDIS 0x10 62 | #define I8042_CTR_AUXDIS 0x20 63 | #define I8042_CTR_XLATE 0x40 64 | 65 | // functions 66 | void i8042_reboot(void); 67 | int ps2_kbd_command(int command, u8 *param); 68 | int ps2_mouse_command(int command, u8 *param); 69 | void ps2port_setup(void); 70 | 71 | #endif // ps2port.h 72 | -------------------------------------------------------------------------------- /strlen.S: -------------------------------------------------------------------------------- 1 | /* 2 | * strlen.S (c) 1995 David Mosberger (davidm@cs.arizona.edu) 3 | * 4 | * Finds length of a 0-terminated string. Optimized for the 5 | * Alpha architecture: 6 | * 7 | * - memory accessed as aligned quadwords only 8 | * - uses bcmpge to compare 8 bytes in parallel 9 | * - does binary search to find 0 byte in last 10 | * quadword (HAKMEM needed 12 instructions to 11 | * do this instead of the 9 instructions that 12 | * binary search needs). 13 | */ 14 | 15 | .set noreorder 16 | .set noat 17 | 18 | .align 3 19 | 20 | .globl strlen 21 | .ent strlen 22 | strlen: 23 | .frame $sp, 0, $26, 0 24 | .prologue 0 25 | 26 | ldq_u $1, 0($16) # load first quadword ($16 may be misaligned) 27 | lda $2, -1($31) 28 | insqh $2, $16, $2 29 | andnot $16, 7, $0 30 | or $2, $1, $1 31 | cmpbge $31, $1, $2 # $2 <- bitmask: bit i == 1 <==> i-th byte == 0 32 | bne $2, found 33 | 34 | loop: ldq $1, 8($0) 35 | addq $0, 8, $0 # addr += 8 36 | nop # helps dual issue last two insns 37 | cmpbge $31, $1, $2 38 | beq $2, loop 39 | 40 | found: blbs $2, done # make aligned case fast 41 | negq $2, $3 42 | and $2, $3, $2 43 | 44 | and $2, 0x0f, $1 45 | addq $0, 4, $3 46 | cmoveq $1, $3, $0 47 | 48 | and $2, 0x33, $1 49 | addq $0, 2, $3 50 | cmoveq $1, $3, $0 51 | 52 | and $2, 0x55, $1 53 | addq $0, 1, $3 54 | cmoveq $1, $3, $0 55 | 56 | done: subq $0, $16, $0 57 | ret $31, ($26) 58 | 59 | .end strlen 60 | -------------------------------------------------------------------------------- /sys-clipper.S: -------------------------------------------------------------------------------- 1 | /* PALcode and C runtime functions for the CLIPPER system emulation. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #include "pal.h" 22 | #include SYSTEM_H 23 | 24 | /* 25 | * Sys_Setup 26 | * 27 | * Do any system specific setup necessary. 28 | * 29 | * INPUT PARAMETERS 30 | * 31 | * a0 = whami 32 | * p7 = return address 33 | */ 34 | .globl Sys_Setup 35 | .ent Sys_Setup 36 | Sys_Setup: 37 | .frame $sp, 0, p7, 0 38 | LOAD_PHYS_CCHIP t0 39 | lda t0, TYPHOON_CCHIP_DIR0(t0) 40 | // DIR[23] differ from DIR[01] by 0x400 41 | // DIR[13] differ from DIR[02] by 0x40 42 | and a0, 2, t4 43 | and a0, 1, t3 44 | sll t4, 9, t4 45 | sll t3, 6, t3 46 | addq t0, t4, t0 47 | addq t0, t3, t0 48 | // IIC[0-4] differ from DIR[0-4] by 0x100 49 | lda t2, 0x100(t0) 50 | mtpr t0, ptCpuDIR 51 | mtpr t2, ptCpuIIC 52 | ret 53 | .end Sys_Setup 54 | 55 | /* 56 | * Sys_Dev_Vector 57 | * 58 | * Load the SRM interrupt vector for the system. 59 | * 60 | * INPUT PARAMETERS 61 | * 62 | * p7 = return address 63 | * 64 | * OUTPUT PARAMETERS 65 | * 66 | * a1 = interrupt vector 67 | */ 68 | 69 | .globl Sys_Dev_Vector 70 | .ent Sys_Dev_Vector 71 | Sys_Dev_Vector: 72 | .frame $sp, 0, p7, 0 73 | mfpr a1, ptCpuDIR // Load int mask for this CPU 74 | ldq_p a1, 0(a1) 75 | beq a1, CallPal_Rti // No interrupts asserted? 76 | 77 | cttz a1, a1 // Find the first asserted interrupt. 78 | 79 | cmpeq a1, 55, a0 // Is this an ISA interrupt? 80 | addq a1, 16, a1 // PCI interrupt numbers start at 16 81 | beq a0, 1f 82 | 83 | LOAD_PHYS_PCHIP0_IACK a1 // IACK results in the ISA irq 84 | ldl_p a1, 0(a1) 85 | 86 | 1: sll a1, 4, a1 87 | lda a1, 0x800(a1) 88 | ret $31, (p7), 0 89 | .end Sys_Dev_Vector 90 | 91 | /* 92 | * Cserve_Ena 93 | * 94 | * Unmask a PCI interrupt 95 | */ 96 | .globl Cserve_Ena 97 | Cserve_Ena: 98 | // FIXME 99 | hw_rei 100 | ENDFN Cserve_Ena 101 | 102 | /* 103 | * Cserve_Dis 104 | * 105 | * Mask a PCI interrupt 106 | */ 107 | .globl Cserve_Dis 108 | Cserve_Dis: 109 | // FIXME 110 | hw_rei 111 | ENDFN Cserve_Dis 112 | 113 | /* 114 | * PCI parameters 115 | */ 116 | 117 | .section .sdata 118 | 119 | .align 3 120 | .globl pci_io_base 121 | .type pci_io_base, @object 122 | .size pci_io_base, 8 123 | pci_io_base: 124 | .quad PIO_KSEG_ADDR + TYPHOON_PCHIP0_PCI_IO 125 | 126 | .globl pci_conf_base 127 | .type pci_conf_base, @object 128 | .size pci_conf_base, 8 129 | pci_conf_base: 130 | .quad PIO_KSEG_ADDR + TYPHOON_PCHIP0_PCI_CONF 131 | 132 | .align 3 133 | .globl pci_mem_base 134 | .type pci_mem_base, @object 135 | .size pci_mem_base, 8 136 | pci_mem_base: 137 | .quad PIO_KSEG_ADDR + TYPHOON_PCHIP0_PCI_MEM 138 | 139 | -------------------------------------------------------------------------------- /sys-clipper.h: -------------------------------------------------------------------------------- 1 | /* Declarations for the CLIPPER system emulation. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #ifndef SYS_CLIPPER_H 22 | #define SYS_CLIPPER_H 1 23 | 24 | #include "core-typhoon.h" 25 | 26 | #define SYS_TYPE ST_DEC_TSUNAMI 27 | #define SYS_VARIATION (5 << 10) 28 | #define SYS_REVISION 0 29 | 30 | #ifndef __ASSEMBLER__ 31 | 32 | static inline uint8_t MAP_PCI_INTERRUPT(int slot, int pin, int class_id) 33 | { 34 | uint8_t irq = 0xff; /* no interrupt mapping */ 35 | 36 | /* PCI-ISA bridge is hard-wired to IRQ 55 on real hardware, and comes in 37 | at a different SCB vector; force the line register to 0xff. 38 | Otherwise, see qemu hw/alpha/dp264.c:clipper_pci_map_irq() */ 39 | if (class_id != 0x0601 && pin >= 1 && pin <= 4) 40 | irq = (slot + 1) * 4 + (pin - 1); 41 | 42 | return irq; 43 | } 44 | 45 | #endif /* ! __ASSEMBLER__ */ 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /sys-sx164.h: -------------------------------------------------------------------------------- 1 | /* Declarations for the SX164 system emulation. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #ifndef SYS_SX164_H 22 | #define SYS_SX164_H 1 23 | 24 | #include "core_cia.h" 25 | 26 | #ifdef __ASSEMBLER__ 27 | 28 | .macro SYS_ACK_CLK t0, t1, t2 29 | LOAD_KSEG_PCI_IO \t0 // Set RTCADD (0x70) to index reg 0xC 30 | mov 0xc, \t1 31 | stb \t1, 0x70(\t0) 32 | ldbu \t1, 0x71(\t0) // Read RTCDAT to clear interrupt 33 | .endm 34 | 35 | .macro SYS_DEV_VECTOR ret 36 | FIXME 37 | .endm 38 | 39 | #endif /* ASSEMBLER */ 40 | 41 | #define SYS_TYPE ST_DEC_EB164 42 | #define SYS_VARIATION (15 << 10) 43 | #define SYS_REVISION 0 44 | 45 | #endif /* SYS_SX164_H */ 46 | -------------------------------------------------------------------------------- /uart.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rth7680/qemu-palcode/99d9b4dcf27d7fbcbadab71bdc88ef6531baf6bf/uart.c -------------------------------------------------------------------------------- /uart.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rth7680/qemu-palcode/99d9b4dcf27d7fbcbadab71bdc88ef6531baf6bf/uart.h -------------------------------------------------------------------------------- /util.c: -------------------------------------------------------------------------------- 1 | /* Utility functions for the QEMU PALcode. 2 | 3 | Copyright (C) 2011 Richard Henderson 4 | 5 | This file is part of QEMU PALcode. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text 15 | of the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; see the file COPYING. If not see 19 | . */ 20 | 21 | #include "protos.h" 22 | 23 | static inline long 24 | ndelay_with_int(unsigned long nsec) 25 | { 26 | register long a0 __asm__("16") = nsec; 27 | register long v0 __asm__("0"); 28 | asm volatile ("call_pal 3" : "=r"(v0) : "r"(a0)); 29 | return v0; 30 | } 31 | 32 | void 33 | ndelay(unsigned long nsec) 34 | { 35 | long left = nsec; 36 | do { 37 | left = ndelay_with_int(left); 38 | } while (left > 0); 39 | } 40 | -------------------------------------------------------------------------------- /vgaio.c: -------------------------------------------------------------------------------- 1 | // VGA io port access 2 | // 3 | // Copyright (C) 2009 Kevin O'Connor 4 | // Copyright (C) 2001-2008 the LGPL VGABios developers Team 5 | // 6 | // This file may be distributed under the terms of the GNU LGPLv3 license. 7 | 8 | #include "protos.h" 9 | #include "ioport.h" 10 | #include "pci.h" 11 | #include "pci_regs.h" 12 | #include "pci_ids.h" 13 | #include "vgatables.h" 14 | 15 | #define GET_FARVAR(seg, ofs) (ofs) 16 | #define SET_FARVAR(seg, ofs, val) ((ofs) = (val)) 17 | 18 | static struct saveBDAstate BDA; 19 | 20 | #define GET_BDA(field) (BDA.field) 21 | #define GET_GLOBAL(val) (val) 22 | 23 | // TODO 24 | // * replace direct in/out calls with wrapper functions 25 | 26 | 27 | /**************************************************************** 28 | * Attribute control 29 | ****************************************************************/ 30 | 31 | void 32 | vgahw_screen_disable(void) 33 | { 34 | inb(VGAREG_ACTL_RESET); 35 | outb(0x00, VGAREG_ACTL_ADDRESS); 36 | } 37 | 38 | void 39 | vgahw_screen_enable(void) 40 | { 41 | inb(VGAREG_ACTL_RESET); 42 | outb(0x20, VGAREG_ACTL_ADDRESS); 43 | } 44 | 45 | void 46 | vgahw_set_border_color(u8 color) 47 | { 48 | inb(VGAREG_ACTL_RESET); 49 | outb(0x00, VGAREG_ACTL_ADDRESS); 50 | u8 v1 = color & 0x0f; 51 | if (v1 & 0x08) 52 | v1 += 0x08; 53 | outb(v1, VGAREG_ACTL_WRITE_DATA); 54 | 55 | u8 v2 = color & 0x10; 56 | int i; 57 | for (i = 1; i < 4; i++) { 58 | outb(i, VGAREG_ACTL_ADDRESS); 59 | 60 | u8 cur = inb(VGAREG_ACTL_READ_DATA); 61 | cur &= 0xef; 62 | cur |= v2; 63 | outb(cur, VGAREG_ACTL_WRITE_DATA); 64 | } 65 | outb(0x20, VGAREG_ACTL_ADDRESS); 66 | } 67 | 68 | void 69 | vgahw_set_overscan_border_color(u8 color) 70 | { 71 | inb(VGAREG_ACTL_RESET); 72 | outb(0x11, VGAREG_ACTL_ADDRESS); 73 | outb(color, VGAREG_ACTL_WRITE_DATA); 74 | outb(0x20, VGAREG_ACTL_ADDRESS); 75 | } 76 | 77 | u8 78 | vgahw_get_overscan_border_color(void) 79 | { 80 | inb(VGAREG_ACTL_RESET); 81 | outb(0x11, VGAREG_ACTL_ADDRESS); 82 | u8 v = inb(VGAREG_ACTL_READ_DATA); 83 | inb(VGAREG_ACTL_RESET); 84 | outb(0x20, VGAREG_ACTL_ADDRESS); 85 | return v; 86 | } 87 | 88 | void 89 | vgahw_set_palette(u8 palid) 90 | { 91 | inb(VGAREG_ACTL_RESET); 92 | palid &= 0x01; 93 | int i; 94 | for (i = 1; i < 4; i++) { 95 | outb(i, VGAREG_ACTL_ADDRESS); 96 | 97 | u8 v = inb(VGAREG_ACTL_READ_DATA); 98 | v &= 0xfe; 99 | v |= palid; 100 | outb(v, VGAREG_ACTL_WRITE_DATA); 101 | } 102 | outb(0x20, VGAREG_ACTL_ADDRESS); 103 | } 104 | 105 | void 106 | vgahw_set_single_palette_reg(u8 reg, u8 val) 107 | { 108 | inb(VGAREG_ACTL_RESET); 109 | outb(reg, VGAREG_ACTL_ADDRESS); 110 | outb(val, VGAREG_ACTL_WRITE_DATA); 111 | outb(0x20, VGAREG_ACTL_ADDRESS); 112 | } 113 | 114 | u8 115 | vgahw_get_single_palette_reg(u8 reg) 116 | { 117 | inb(VGAREG_ACTL_RESET); 118 | outb(reg, VGAREG_ACTL_ADDRESS); 119 | u8 v = inb(VGAREG_ACTL_READ_DATA); 120 | inb(VGAREG_ACTL_RESET); 121 | outb(0x20, VGAREG_ACTL_ADDRESS); 122 | return v; 123 | } 124 | 125 | void 126 | vgahw_set_all_palette_reg(u8 *data_far) 127 | { 128 | inb(VGAREG_ACTL_RESET); 129 | int i; 130 | for (i = 0; i < 0x10; i++) { 131 | outb(i, VGAREG_ACTL_ADDRESS); 132 | u8 val = GET_FARVAR(seg, *data_far); 133 | outb(val, VGAREG_ACTL_WRITE_DATA); 134 | data_far++; 135 | } 136 | outb(0x11, VGAREG_ACTL_ADDRESS); 137 | outb(GET_FARVAR(seg, *data_far), VGAREG_ACTL_WRITE_DATA); 138 | outb(0x20, VGAREG_ACTL_ADDRESS); 139 | } 140 | 141 | void 142 | vgahw_get_all_palette_reg(u8 *data_far) 143 | { 144 | int i; 145 | for (i = 0; i < 0x10; i++) { 146 | inb(VGAREG_ACTL_RESET); 147 | outb(i, VGAREG_ACTL_ADDRESS); 148 | SET_FARVAR(seg, *data_far, inb(VGAREG_ACTL_READ_DATA)); 149 | data_far++; 150 | } 151 | inb(VGAREG_ACTL_RESET); 152 | outb(0x11, VGAREG_ACTL_ADDRESS); 153 | SET_FARVAR(seg, *data_far, inb(VGAREG_ACTL_READ_DATA)); 154 | inb(VGAREG_ACTL_RESET); 155 | outb(0x20, VGAREG_ACTL_ADDRESS); 156 | } 157 | 158 | void 159 | vgahw_toggle_intensity(u8 flag) 160 | { 161 | inb(VGAREG_ACTL_RESET); 162 | outb(0x10, VGAREG_ACTL_ADDRESS); 163 | u8 val = (inb(VGAREG_ACTL_READ_DATA) & 0xf7) | ((flag & 0x01) << 3); 164 | outb(val, VGAREG_ACTL_WRITE_DATA); 165 | outb(0x20, VGAREG_ACTL_ADDRESS); 166 | } 167 | 168 | void 169 | vgahw_select_video_dac_color_page(u8 flag, u8 data) 170 | { 171 | inb(VGAREG_ACTL_RESET); 172 | outb(0x10, VGAREG_ACTL_ADDRESS); 173 | u8 val = inb(VGAREG_ACTL_READ_DATA); 174 | if (!(flag & 0x01)) { 175 | // select paging mode 176 | val = (val & 0x7f) | (data << 7); 177 | outb(val, VGAREG_ACTL_WRITE_DATA); 178 | outb(0x20, VGAREG_ACTL_ADDRESS); 179 | return; 180 | } 181 | // select page 182 | inb(VGAREG_ACTL_RESET); 183 | outb(0x14, VGAREG_ACTL_ADDRESS); 184 | if (!(val & 0x80)) 185 | data <<= 2; 186 | data &= 0x0f; 187 | outb(data, VGAREG_ACTL_WRITE_DATA); 188 | outb(0x20, VGAREG_ACTL_ADDRESS); 189 | } 190 | 191 | void 192 | vgahw_read_video_dac_state(u8 *pmode, u8 *curpage) 193 | { 194 | inb(VGAREG_ACTL_RESET); 195 | outb(0x10, VGAREG_ACTL_ADDRESS); 196 | u8 val1 = inb(VGAREG_ACTL_READ_DATA) >> 7; 197 | 198 | inb(VGAREG_ACTL_RESET); 199 | outb(0x14, VGAREG_ACTL_ADDRESS); 200 | u8 val2 = inb(VGAREG_ACTL_READ_DATA) & 0x0f; 201 | if (!(val1 & 0x01)) 202 | val2 >>= 2; 203 | 204 | inb(VGAREG_ACTL_RESET); 205 | outb(0x20, VGAREG_ACTL_ADDRESS); 206 | 207 | *pmode = val1; 208 | *curpage = val2; 209 | } 210 | 211 | 212 | /**************************************************************** 213 | * DAC control 214 | ****************************************************************/ 215 | 216 | void 217 | vgahw_set_dac_regs(u8 *data_far, u8 start, int count) 218 | { 219 | outb(start, VGAREG_DAC_WRITE_ADDRESS); 220 | while (count) { 221 | outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA); 222 | data_far++; 223 | outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA); 224 | data_far++; 225 | outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA); 226 | data_far++; 227 | count--; 228 | } 229 | } 230 | 231 | void 232 | vgahw_get_dac_regs(u8 *data_far, u8 start, int count) 233 | { 234 | outb(start, VGAREG_DAC_READ_ADDRESS); 235 | while (count) { 236 | SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA)); 237 | data_far++; 238 | SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA)); 239 | data_far++; 240 | SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA)); 241 | data_far++; 242 | count--; 243 | } 244 | } 245 | 246 | void 247 | vgahw_set_pel_mask(u8 val) 248 | { 249 | outb(val, VGAREG_PEL_MASK); 250 | } 251 | 252 | u8 253 | vgahw_get_pel_mask(void) 254 | { 255 | return inb(VGAREG_PEL_MASK); 256 | } 257 | 258 | void 259 | vgahw_save_dac_state(struct saveDACcolors *info) 260 | { 261 | /* XXX: check this */ 262 | SET_FARVAR(seg, info->rwmode, inb(VGAREG_DAC_STATE)); 263 | SET_FARVAR(seg, info->peladdr, inb(VGAREG_DAC_WRITE_ADDRESS)); 264 | SET_FARVAR(seg, info->pelmask, inb(VGAREG_PEL_MASK)); 265 | vgahw_get_dac_regs(info->dac, 0, 256); 266 | SET_FARVAR(seg, info->color_select, 0); 267 | } 268 | 269 | void 270 | vgahw_restore_dac_state(struct saveDACcolors *info) 271 | { 272 | outb(GET_FARVAR(seg, info->pelmask), VGAREG_PEL_MASK); 273 | vgahw_set_dac_regs(info->dac, 0, 256); 274 | outb(GET_FARVAR(seg, info->peladdr), VGAREG_DAC_WRITE_ADDRESS); 275 | } 276 | 277 | 278 | /**************************************************************** 279 | * Memory control 280 | ****************************************************************/ 281 | 282 | void 283 | vgahw_sequ_write(u8 index, u8 value) 284 | { 285 | outw((value<<8) | index, VGAREG_SEQU_ADDRESS); 286 | } 287 | 288 | void 289 | vgahw_grdc_write(u8 index, u8 value) 290 | { 291 | outw((value<<8) | index, VGAREG_GRDC_ADDRESS); 292 | } 293 | 294 | void 295 | vgahw_set_text_block_specifier(u8 spec) 296 | { 297 | outw((spec << 8) | 0x03, VGAREG_SEQU_ADDRESS); 298 | } 299 | 300 | void 301 | get_font_access(void) 302 | { 303 | outw(0x0100, VGAREG_SEQU_ADDRESS); 304 | outw(0x0402, VGAREG_SEQU_ADDRESS); 305 | outw(0x0704, VGAREG_SEQU_ADDRESS); 306 | outw(0x0300, VGAREG_SEQU_ADDRESS); 307 | outw(0x0204, VGAREG_GRDC_ADDRESS); 308 | outw(0x0005, VGAREG_GRDC_ADDRESS); 309 | outw(0x0406, VGAREG_GRDC_ADDRESS); 310 | } 311 | 312 | void 313 | release_font_access(void) 314 | { 315 | outw(0x0100, VGAREG_SEQU_ADDRESS); 316 | outw(0x0302, VGAREG_SEQU_ADDRESS); 317 | outw(0x0304, VGAREG_SEQU_ADDRESS); 318 | outw(0x0300, VGAREG_SEQU_ADDRESS); 319 | u16 v = (inw(VGAREG_READ_MISC_OUTPUT) & 0x01) ? 0x0e : 0x0a; 320 | outw((v << 8) | 0x06, VGAREG_GRDC_ADDRESS); 321 | outw(0x0004, VGAREG_GRDC_ADDRESS); 322 | outw(0x1005, VGAREG_GRDC_ADDRESS); 323 | } 324 | 325 | 326 | /**************************************************************** 327 | * CRTC registers 328 | ****************************************************************/ 329 | 330 | static u16 331 | get_crtc(void) 332 | { 333 | return GET_BDA(crtc_address); 334 | } 335 | 336 | void 337 | vgahw_set_cursor_shape(u8 start, u8 end) 338 | { 339 | u16 crtc_addr = get_crtc(); 340 | outb(0x0a, crtc_addr); 341 | outb(start, crtc_addr + 1); 342 | outb(0x0b, crtc_addr); 343 | outb(end, crtc_addr + 1); 344 | } 345 | 346 | void 347 | vgahw_set_active_page(u16 address) 348 | { 349 | u16 crtc_addr = get_crtc(); 350 | outb(0x0c, crtc_addr); 351 | outb((address & 0xff00) >> 8, crtc_addr + 1); 352 | outb(0x0d, crtc_addr); 353 | outb(address & 0x00ff, crtc_addr + 1); 354 | } 355 | 356 | void 357 | vgahw_set_cursor_pos(u16 address) 358 | { 359 | u16 crtc_addr = get_crtc(); 360 | outb(0x0e, crtc_addr); 361 | outb((address & 0xff00) >> 8, crtc_addr + 1); 362 | outb(0x0f, crtc_addr); 363 | outb(address & 0x00ff, crtc_addr + 1); 364 | } 365 | 366 | void 367 | vgahw_set_scan_lines(u8 lines) 368 | { 369 | u16 crtc_addr = get_crtc(); 370 | outb(0x09, crtc_addr); 371 | u8 crtc_r9 = inb(crtc_addr + 1); 372 | crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1); 373 | outb(crtc_r9, crtc_addr + 1); 374 | } 375 | 376 | // Get vertical display end 377 | u16 378 | vgahw_get_vde(void) 379 | { 380 | u16 crtc_addr = get_crtc(); 381 | outb(0x12, crtc_addr); 382 | u16 vde = inb(crtc_addr + 1); 383 | outb(0x07, crtc_addr); 384 | u8 ovl = inb(crtc_addr + 1); 385 | vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1); 386 | return vde; 387 | } 388 | 389 | 390 | /**************************************************************** 391 | * Save/Restore/Set state 392 | ****************************************************************/ 393 | 394 | void 395 | vgahw_save_state(struct saveVideoHardware *info) 396 | { 397 | u16 crtc_addr = get_crtc(); 398 | SET_FARVAR(seg, info->sequ_index, inb(VGAREG_SEQU_ADDRESS)); 399 | SET_FARVAR(seg, info->crtc_index, inb(crtc_addr)); 400 | SET_FARVAR(seg, info->grdc_index, inb(VGAREG_GRDC_ADDRESS)); 401 | inb(VGAREG_ACTL_RESET); 402 | u16 ar_index = inb(VGAREG_ACTL_ADDRESS); 403 | SET_FARVAR(seg, info->actl_index, ar_index); 404 | SET_FARVAR(seg, info->feature, inb(VGAREG_READ_FEATURE_CTL)); 405 | 406 | u16 i; 407 | for (i=0; i<4; i++) { 408 | outb(i+1, VGAREG_SEQU_ADDRESS); 409 | SET_FARVAR(seg, info->sequ_regs[i], inb(VGAREG_SEQU_DATA)); 410 | } 411 | outb(0, VGAREG_SEQU_ADDRESS); 412 | SET_FARVAR(seg, info->sequ0, inb(VGAREG_SEQU_DATA)); 413 | 414 | for (i=0; i<25; i++) { 415 | outb(i, crtc_addr); 416 | SET_FARVAR(seg, info->crtc_regs[i], inb(crtc_addr + 1)); 417 | } 418 | 419 | for (i=0; i<20; i++) { 420 | inb(VGAREG_ACTL_RESET); 421 | outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS); 422 | SET_FARVAR(seg, info->actl_regs[i], inb(VGAREG_ACTL_READ_DATA)); 423 | } 424 | inb(VGAREG_ACTL_RESET); 425 | 426 | for (i=0; i<9; i++) { 427 | outb(i, VGAREG_GRDC_ADDRESS); 428 | SET_FARVAR(seg, info->grdc_regs[i], inb(VGAREG_GRDC_DATA)); 429 | } 430 | 431 | SET_FARVAR(seg, info->crtc_addr, crtc_addr); 432 | 433 | /* XXX: read plane latches */ 434 | for (i=0; i<4; i++) 435 | SET_FARVAR(seg, info->plane_latch[i], 0); 436 | } 437 | 438 | void 439 | vgahw_restore_state(struct saveVideoHardware *info) 440 | { 441 | // Reset Attribute Ctl flip-flop 442 | inb(VGAREG_ACTL_RESET); 443 | 444 | u16 crtc_addr = GET_FARVAR(seg, info->crtc_addr); 445 | 446 | u16 i; 447 | for (i=0; i<4; i++) { 448 | outb(i+1, VGAREG_SEQU_ADDRESS); 449 | outb(GET_FARVAR(seg, info->sequ_regs[i]), VGAREG_SEQU_DATA); 450 | } 451 | outb(0, VGAREG_SEQU_ADDRESS); 452 | outb(GET_FARVAR(seg, info->sequ0), VGAREG_SEQU_DATA); 453 | 454 | // Disable CRTC write protection 455 | outw(0x0011, crtc_addr); 456 | // Set CRTC regs 457 | for (i=0; i<25; i++) 458 | if (i != 0x11) { 459 | outb(i, crtc_addr); 460 | outb(GET_FARVAR(seg, info->crtc_regs[i]), crtc_addr + 1); 461 | } 462 | // select crtc base address 463 | u16 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01; 464 | if (crtc_addr == VGAREG_VGA_CRTC_ADDRESS) 465 | v |= 0x01; 466 | outb(v, VGAREG_WRITE_MISC_OUTPUT); 467 | 468 | // enable write protection if needed 469 | outb(0x11, crtc_addr); 470 | outb(GET_FARVAR(seg, info->crtc_regs[0x11]), crtc_addr + 1); 471 | 472 | // Set Attribute Ctl 473 | u16 ar_index = GET_FARVAR(seg, info->actl_index); 474 | inb(VGAREG_ACTL_RESET); 475 | for (i=0; i<20; i++) { 476 | outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS); 477 | outb(GET_FARVAR(seg, info->actl_regs[i]), VGAREG_ACTL_WRITE_DATA); 478 | } 479 | outb(ar_index, VGAREG_ACTL_ADDRESS); 480 | inb(VGAREG_ACTL_RESET); 481 | 482 | for (i=0; i<9; i++) { 483 | outb(i, VGAREG_GRDC_ADDRESS); 484 | outb(GET_FARVAR(seg, info->grdc_regs[i]), VGAREG_GRDC_DATA); 485 | } 486 | 487 | outb(GET_FARVAR(seg, info->sequ_index), VGAREG_SEQU_ADDRESS); 488 | outb(GET_FARVAR(seg, info->crtc_index), crtc_addr); 489 | outb(GET_FARVAR(seg, info->grdc_index), VGAREG_GRDC_ADDRESS); 490 | outb(GET_FARVAR(seg, info->feature), crtc_addr - 0x4 + 0xa); 491 | } 492 | 493 | void 494 | vgahw_set_mode(struct VideoParam_s *vparam_g) 495 | { 496 | // Reset Attribute Ctl flip-flop 497 | inb(VGAREG_ACTL_RESET); 498 | 499 | // Set Attribute Ctl 500 | u16 i; 501 | for (i = 0; i <= 0x13; i++) { 502 | outb(i, VGAREG_ACTL_ADDRESS); 503 | outb(GET_GLOBAL(vparam_g->actl_regs[i]), VGAREG_ACTL_WRITE_DATA); 504 | } 505 | outb(0x14, VGAREG_ACTL_ADDRESS); 506 | outb(0x00, VGAREG_ACTL_WRITE_DATA); 507 | 508 | // Set Sequencer Ctl 509 | outb(0, VGAREG_SEQU_ADDRESS); 510 | outb(0x03, VGAREG_SEQU_DATA); 511 | for (i = 1; i <= 4; i++) { 512 | outb(i, VGAREG_SEQU_ADDRESS); 513 | outb(GET_GLOBAL(vparam_g->sequ_regs[i - 1]), VGAREG_SEQU_DATA); 514 | } 515 | 516 | // Set Grafx Ctl 517 | for (i = 0; i <= 8; i++) { 518 | outb(i, VGAREG_GRDC_ADDRESS); 519 | outb(GET_GLOBAL(vparam_g->grdc_regs[i]), VGAREG_GRDC_DATA); 520 | } 521 | 522 | // Set CRTC address VGA or MDA 523 | u8 miscreg = GET_GLOBAL(vparam_g->miscreg); 524 | u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS; 525 | if (!(miscreg & 1)) 526 | crtc_addr = VGAREG_MDA_CRTC_ADDRESS; 527 | 528 | // Disable CRTC write protection 529 | outw(0x0011, crtc_addr); 530 | // Set CRTC regs 531 | for (i = 0; i <= 0x18; i++) { 532 | outb(i, crtc_addr); 533 | outb(GET_GLOBAL(vparam_g->crtc_regs[i]), crtc_addr + 1); 534 | } 535 | 536 | // Set the misc register 537 | outb(miscreg, VGAREG_WRITE_MISC_OUTPUT); 538 | 539 | // Enable video 540 | outb(0x20, VGAREG_ACTL_ADDRESS); 541 | inb(VGAREG_ACTL_RESET); 542 | } 543 | 544 | 545 | /**************************************************************** 546 | * Misc 547 | ****************************************************************/ 548 | 549 | void 550 | vgahw_enable_video_addressing(u8 disable) 551 | { 552 | u8 v = (disable & 1) ? 0x00 : 0x02; 553 | u8 v2 = inb(VGAREG_READ_MISC_OUTPUT) & ~0x02; 554 | outb(v | v2, VGAREG_WRITE_MISC_OUTPUT); 555 | } 556 | 557 | void 558 | vgahw_init(void) 559 | { 560 | struct vgamode_s *vmode_g; 561 | int bdf, max; 562 | 563 | foreachpci(bdf, max) 564 | { 565 | uint16_t class = pci_config_readw(bdf, PCI_CLASS_DEVICE); 566 | if (class == PCI_CLASS_DISPLAY_VGA) 567 | goto found; 568 | } 569 | return; 570 | 571 | found: 572 | have_vga = 1; 573 | pci_vga_bus = PCI_BUS(bdf); 574 | pci_vga_dev = PCI_SLOT(bdf); 575 | 576 | vmode_g = find_vga_entry(3); 577 | 578 | vgahw_sequ_write(0, 1); // Assert sync reset 579 | 580 | // Switch to color mode and enable CPU access 480 lines 581 | outb(0xc3, VGAREG_WRITE_MISC_OUTPUT); 582 | 583 | vgahw_sequ_write(0, 3); // De-assert sync reset 584 | 585 | vgahw_set_mode(vmode_g->vparam); 586 | 587 | vgahw_sequ_write(4, 0x06); // disable odd/even + chain4 588 | vgahw_sequ_write(1, vmode_g->vparam->sequ_regs[1] | 0x20); // disable video 589 | vgahw_grdc_write(5, vmode_g->vparam->grdc_regs[5] & 0xef); // disable odd/even 590 | vgahw_grdc_write(6, 0x05); // set mem map to 0xa0000 and graphics mode 591 | vgahw_sequ_write(2, 0x04); // enable write plane 2 592 | 593 | { 594 | unsigned char *font_ptr = pci_mem_base + SEG_GRAPH*16; 595 | int i; 596 | 597 | for (i = 0; i < 0x100; i++) 598 | __builtin_memcpy(font_ptr + i*32, vgafont16 + i*16, 16); 599 | } 600 | 601 | { 602 | int i = vmode_g->dacsize / 3; 603 | vgahw_set_dac_regs(vmode_g->dac, 0, i); 604 | } 605 | 606 | vgahw_sequ_write(4, 0x2); // enable odd/even 607 | vgahw_set_mode(vmode_g->vparam); 608 | } 609 | -------------------------------------------------------------------------------- /vgatables.c: -------------------------------------------------------------------------------- 1 | // Tables used by VGA bios 2 | // 3 | // Copyright (C) 2009 Kevin O'Connor 4 | // Copyright (C) 2001-2008 the LGPL VGABios developers Team 5 | // 6 | // This file may be distributed under the terms of the GNU LGPLv3 license. 7 | 8 | #include "protos.h" 9 | #include "vgatables.h" // struct VideoParamTableEntry_s 10 | 11 | #define ARRAY_SIZE(var) (sizeof(var) / sizeof(var[0])) 12 | #define GET_GLOBAL(var) (var) 13 | #define VAR16 14 | 15 | /**************************************************************** 16 | * Video parameter table 17 | ****************************************************************/ 18 | 19 | struct VideoParam_s video_param_table[] VAR16 = { 20 | // index=0x00 no mode defined 21 | {}, 22 | // index=0x01 no mode defined 23 | {}, 24 | // index=0x02 no mode defined 25 | {}, 26 | // index=0x03 no mode defined 27 | {}, 28 | // index=0x04 vga mode 0x04 29 | { 40, 24, 8, 0x0800, /* tw, th-1, ch, slength */ 30 | { 0x09, 0x03, 0x00, 0x02 }, /* sequ_regs */ 31 | 0x63, /* miscreg */ 32 | { 0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f, 33 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 34 | 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2, 35 | 0xff }, /* crtc_regs */ 36 | { 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 37 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 38 | 0x01, 0x00, 0x03, 0x00 }, /* actl_regs */ 39 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff }, /* grdc_regs */ 40 | }, 41 | /* index=0x05 vga mode 0x05 */ 42 | { 40, 24, 8, 0x0800, /* tw, th-1, ch, slength */ 43 | { 0x09, 0x03, 0x00, 0x02 }, /* sequ_regs */ 44 | 0x63, /* miscreg */ 45 | { 0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f, 46 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 47 | 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2, 48 | 0xff }, /* crtc_regs */ 49 | { 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 50 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 51 | 0x01, 0x00, 0x03, 0x00 }, /* actl_regs */ 52 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff }, /* grdc_regs */ 53 | }, 54 | /* index=0x06 vga mode 0x06 */ 55 | { 80, 24, 8, 0x1000, /* tw, th-1, ch, slength */ 56 | { 0x01, 0x01, 0x00, 0x06 }, /* sequ_regs */ 57 | 0x63, /* miscreg */ 58 | { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, 59 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 60 | 0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xc2, 61 | 0xff }, /* crtc_regs */ 62 | { 0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 63 | 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 64 | 0x01, 0x00, 0x01, 0x00 }, /* actl_regs */ 65 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0f, 0xff }, /* grdc_regs */ 66 | }, 67 | /* index=0x07 vga mode 0x07 */ 68 | { 80, 24, 16, 0x1000, /* tw, th-1, ch, slength */ 69 | { 0x00, 0x03, 0x00, 0x02 }, /* sequ_regs */ 70 | 0x66, /* miscreg */ 71 | { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 72 | 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, 73 | 0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3, 74 | 0xff }, /* crtc_regs */ 75 | { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 76 | 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 77 | 0x0e, 0x00, 0x0f, 0x08 }, /* actl_regs */ 78 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x0f, 0xff }, /* grdc_regs */ 79 | }, 80 | /* index=0x08 no mode defined */ 81 | {}, 82 | /* index=0x09 no mode defined */ 83 | {}, 84 | /* index=0x0a no mode defined */ 85 | {}, 86 | /* index=0x0b no mode defined */ 87 | {}, 88 | /* index=0x0c no mode defined */ 89 | {}, 90 | /* index=0x0d vga mode 0x0d */ 91 | { 40, 24, 8, 0x2000, /* tw, th-1, ch, slength */ 92 | { 0x09, 0x0f, 0x00, 0x06 }, /* sequ_regs */ 93 | 0x63, /* miscreg */ 94 | { 0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f, 95 | 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 96 | 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xe3, 97 | 0xff }, /* crtc_regs */ 98 | { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 99 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 100 | 0x01, 0x00, 0x0f, 0x00 }, /* actl_regs */ 101 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ 102 | }, 103 | /* index=0x0e vga mode 0x0e */ 104 | { 80, 24, 8, 0x4000, /* tw, th-1, ch, slength */ 105 | { 0x01, 0x0f, 0x00, 0x06 }, /* sequ_regs */ 106 | 0x63, /* miscreg */ 107 | { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, 108 | 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 109 | 0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xe3, 110 | 0xff }, /* crtc_regs */ 111 | { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 112 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 113 | 0x01, 0x00, 0x0f, 0x00 }, /* actl_regs */ 114 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ 115 | }, 116 | /* index=0x0f no mode defined */ 117 | {}, 118 | /* index=0x10 no mode defined */ 119 | {}, 120 | /* index=0x11 vga mode 0x0f */ 121 | { 80, 24, 14, 0x8000, /* tw, th-1, ch, slength */ 122 | { 0x01, 0x0f, 0x00, 0x06 }, /* sequ_regs */ 123 | 0xa3, /* miscreg */ 124 | { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, 125 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 126 | 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3, 127 | 0xff }, /* crtc_regs */ 128 | { 0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 129 | 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 130 | 0x01, 0x00, 0x01, 0x00 }, /* actl_regs */ 131 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ 132 | }, 133 | /* index=0x12 vga mode 0x10 */ 134 | { 80, 24, 14, 0x8000, /* tw, th-1, ch, slength */ 135 | { 0x01, 0x0f, 0x00, 0x06 }, /* sequ_regs */ 136 | 0xa3, /* miscreg */ 137 | { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, 138 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 139 | 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3, 140 | 0xff }, /* crtc_regs */ 141 | { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 142 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 143 | 0x01, 0x00, 0x0f, 0x00 }, /* actl_regs */ 144 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ 145 | }, 146 | /* index=0x13 no mode defined */ 147 | {}, 148 | /* index=0x14 no mode defined */ 149 | {}, 150 | /* index=0x15 no mode defined */ 151 | {}, 152 | /* index=0x16 no mode defined */ 153 | {}, 154 | /* index=0x17 vga mode 0x01 */ 155 | { 40, 24, 16, 0x0800, /* tw, th-1, ch, slength */ 156 | { 0x08, 0x03, 0x00, 0x02 }, /* sequ_regs */ 157 | 0x67, /* miscreg */ 158 | { 0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f, 159 | 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, 160 | 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3, 161 | 0xff }, /* crtc_regs */ 162 | { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 163 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 164 | 0x0c, 0x00, 0x0f, 0x08 }, /* actl_regs */ 165 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff }, /* grdc_regs */ 166 | }, 167 | /* index=0x18 vga mode 0x03 */ 168 | { 80, 24, 16, 0x1000, /* tw, th-1, ch, slength */ 169 | { 0x00, 0x03, 0x00, 0x02 }, /* sequ_regs */ 170 | 0x67, /* miscreg */ 171 | { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 172 | 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, 173 | 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, 174 | 0xff }, /* crtc_regs */ 175 | { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 176 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 177 | 0x0c, 0x00, 0x0f, 0x08 }, /* actl_regs */ 178 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff }, /* grdc_regs */ 179 | }, 180 | /* index=0x19 vga mode 0x07 */ 181 | { 80, 24, 16, 0x1000, /* tw, th-1, ch, slength */ 182 | { 0x00, 0x03, 0x00, 0x02 }, /* sequ_regs */ 183 | 0x66, /* miscreg */ 184 | { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 185 | 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, 186 | 0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3, 187 | 0xff }, /* crtc_regs */ 188 | { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 189 | 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 190 | 0x0e, 0x00, 0x0f, 0x08 }, /* actl_regs */ 191 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x0f, 0xff }, /* grdc_regs */ 192 | }, 193 | /* index=0x1a vga mode 0x11 */ 194 | { 80, 29, 16, 0x0000, /* tw, th-1, ch, slength */ 195 | { 0x01, 0x0f, 0x00, 0x06 }, /* sequ_regs */ 196 | 0xe3, /* miscreg */ 197 | { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, 198 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 199 | 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, 200 | 0xff }, /* crtc_regs */ 201 | { 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 202 | 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 203 | 0x01, 0x00, 0x0f, 0x00 }, /* actl_regs */ 204 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ 205 | }, 206 | /* index=0x1b vga mode 0x12 */ 207 | { 80, 29, 16, 0x0000, /* tw, th-1, ch, slength */ 208 | { 0x01, 0x0f, 0x00, 0x06 }, /* sequ_regs */ 209 | 0xe3, /* miscreg */ 210 | { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, 211 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 212 | 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, 213 | 0xff }, /* crtc_regs */ 214 | { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 215 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 216 | 0x01, 0x00, 0x0f, 0x00 }, /* actl_regs */ 217 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ 218 | }, 219 | /* index=0x1c vga mode 0x13 */ 220 | { 40, 24, 8, 0x0000, /* tw, th-1, ch, slength */ 221 | { 0x01, 0x0f, 0x00, 0x0e }, /* sequ_regs */ 222 | 0x63, /* miscreg */ 223 | { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, 224 | 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 225 | 0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3, 226 | 0xff }, /* crtc_regs */ 227 | { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 228 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 229 | 0x41, 0x00, 0x0f, 0x00 }, /* actl_regs */ 230 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff }, /* grdc_regs */ 231 | }, 232 | /* index=0x1d vga mode 0x6a */ 233 | { 100, 36, 16, 0x0000, /* tw, th-1, ch, slength */ 234 | { 0x01, 0x0f, 0x00, 0x06 }, /* sequ_regs */ 235 | 0xe3, /* miscreg */ 236 | { 0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0, 237 | 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 238 | 0x59, 0x8d, 0x57, 0x32, 0x00, 0x57, 0x73, 0xe3, 239 | 0xff }, /* crtc_regs */ 240 | { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 241 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 242 | 0x01, 0x00, 0x0f, 0x00 }, /* actl_regs */ 243 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ 244 | }, 245 | }; 246 | 247 | 248 | /**************************************************************** 249 | * Palette definitions 250 | ****************************************************************/ 251 | 252 | /* Mono */ 253 | static u8 palette0[] VAR16 = { 254 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 255 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 256 | 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 257 | 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 258 | 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 259 | 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 260 | 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 261 | 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 262 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 263 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 264 | 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 265 | 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 266 | 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 267 | 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 268 | 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 269 | 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f 270 | }; 271 | 272 | static u8 palette1[] VAR16 = { 273 | 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 274 | 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, 275 | 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 276 | 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, 277 | 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 278 | 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, 279 | 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 280 | 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, 281 | 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 282 | 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, 283 | 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 284 | 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, 285 | 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 286 | 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, 287 | 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 288 | 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f 289 | }; 290 | 291 | static u8 palette2[] VAR16 = { 292 | 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 293 | 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a, 294 | 0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f, 295 | 0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f, 296 | 0x00,0x15,0x00, 0x00,0x15,0x2a, 0x00,0x3f,0x00, 0x00,0x3f,0x2a, 297 | 0x2a,0x15,0x00, 0x2a,0x15,0x2a, 0x2a,0x3f,0x00, 0x2a,0x3f,0x2a, 298 | 0x00,0x15,0x15, 0x00,0x15,0x3f, 0x00,0x3f,0x15, 0x00,0x3f,0x3f, 299 | 0x2a,0x15,0x15, 0x2a,0x15,0x3f, 0x2a,0x3f,0x15, 0x2a,0x3f,0x3f, 300 | 0x15,0x00,0x00, 0x15,0x00,0x2a, 0x15,0x2a,0x00, 0x15,0x2a,0x2a, 301 | 0x3f,0x00,0x00, 0x3f,0x00,0x2a, 0x3f,0x2a,0x00, 0x3f,0x2a,0x2a, 302 | 0x15,0x00,0x15, 0x15,0x00,0x3f, 0x15,0x2a,0x15, 0x15,0x2a,0x3f, 303 | 0x3f,0x00,0x15, 0x3f,0x00,0x3f, 0x3f,0x2a,0x15, 0x3f,0x2a,0x3f, 304 | 0x15,0x15,0x00, 0x15,0x15,0x2a, 0x15,0x3f,0x00, 0x15,0x3f,0x2a, 305 | 0x3f,0x15,0x00, 0x3f,0x15,0x2a, 0x3f,0x3f,0x00, 0x3f,0x3f,0x2a, 306 | 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 307 | 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f 308 | }; 309 | 310 | static u8 palette3[] VAR16 = { 311 | 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 312 | 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, 313 | 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 314 | 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, 315 | 0x00,0x00,0x00, 0x05,0x05,0x05, 0x08,0x08,0x08, 0x0b,0x0b,0x0b, 316 | 0x0e,0x0e,0x0e, 0x11,0x11,0x11, 0x14,0x14,0x14, 0x18,0x18,0x18, 317 | 0x1c,0x1c,0x1c, 0x20,0x20,0x20, 0x24,0x24,0x24, 0x28,0x28,0x28, 318 | 0x2d,0x2d,0x2d, 0x32,0x32,0x32, 0x38,0x38,0x38, 0x3f,0x3f,0x3f, 319 | 0x00,0x00,0x3f, 0x10,0x00,0x3f, 0x1f,0x00,0x3f, 0x2f,0x00,0x3f, 320 | 0x3f,0x00,0x3f, 0x3f,0x00,0x2f, 0x3f,0x00,0x1f, 0x3f,0x00,0x10, 321 | 0x3f,0x00,0x00, 0x3f,0x10,0x00, 0x3f,0x1f,0x00, 0x3f,0x2f,0x00, 322 | 0x3f,0x3f,0x00, 0x2f,0x3f,0x00, 0x1f,0x3f,0x00, 0x10,0x3f,0x00, 323 | 0x00,0x3f,0x00, 0x00,0x3f,0x10, 0x00,0x3f,0x1f, 0x00,0x3f,0x2f, 324 | 0x00,0x3f,0x3f, 0x00,0x2f,0x3f, 0x00,0x1f,0x3f, 0x00,0x10,0x3f, 325 | 0x1f,0x1f,0x3f, 0x27,0x1f,0x3f, 0x2f,0x1f,0x3f, 0x37,0x1f,0x3f, 326 | 0x3f,0x1f,0x3f, 0x3f,0x1f,0x37, 0x3f,0x1f,0x2f, 0x3f,0x1f,0x27, 327 | 328 | 0x3f,0x1f,0x1f, 0x3f,0x27,0x1f, 0x3f,0x2f,0x1f, 0x3f,0x37,0x1f, 329 | 0x3f,0x3f,0x1f, 0x37,0x3f,0x1f, 0x2f,0x3f,0x1f, 0x27,0x3f,0x1f, 330 | 0x1f,0x3f,0x1f, 0x1f,0x3f,0x27, 0x1f,0x3f,0x2f, 0x1f,0x3f,0x37, 331 | 0x1f,0x3f,0x3f, 0x1f,0x37,0x3f, 0x1f,0x2f,0x3f, 0x1f,0x27,0x3f, 332 | 0x2d,0x2d,0x3f, 0x31,0x2d,0x3f, 0x36,0x2d,0x3f, 0x3a,0x2d,0x3f, 333 | 0x3f,0x2d,0x3f, 0x3f,0x2d,0x3a, 0x3f,0x2d,0x36, 0x3f,0x2d,0x31, 334 | 0x3f,0x2d,0x2d, 0x3f,0x31,0x2d, 0x3f,0x36,0x2d, 0x3f,0x3a,0x2d, 335 | 0x3f,0x3f,0x2d, 0x3a,0x3f,0x2d, 0x36,0x3f,0x2d, 0x31,0x3f,0x2d, 336 | 0x2d,0x3f,0x2d, 0x2d,0x3f,0x31, 0x2d,0x3f,0x36, 0x2d,0x3f,0x3a, 337 | 0x2d,0x3f,0x3f, 0x2d,0x3a,0x3f, 0x2d,0x36,0x3f, 0x2d,0x31,0x3f, 338 | 0x00,0x00,0x1c, 0x07,0x00,0x1c, 0x0e,0x00,0x1c, 0x15,0x00,0x1c, 339 | 0x1c,0x00,0x1c, 0x1c,0x00,0x15, 0x1c,0x00,0x0e, 0x1c,0x00,0x07, 340 | 0x1c,0x00,0x00, 0x1c,0x07,0x00, 0x1c,0x0e,0x00, 0x1c,0x15,0x00, 341 | 0x1c,0x1c,0x00, 0x15,0x1c,0x00, 0x0e,0x1c,0x00, 0x07,0x1c,0x00, 342 | 0x00,0x1c,0x00, 0x00,0x1c,0x07, 0x00,0x1c,0x0e, 0x00,0x1c,0x15, 343 | 0x00,0x1c,0x1c, 0x00,0x15,0x1c, 0x00,0x0e,0x1c, 0x00,0x07,0x1c, 344 | 345 | 0x0e,0x0e,0x1c, 0x11,0x0e,0x1c, 0x15,0x0e,0x1c, 0x18,0x0e,0x1c, 346 | 0x1c,0x0e,0x1c, 0x1c,0x0e,0x18, 0x1c,0x0e,0x15, 0x1c,0x0e,0x11, 347 | 0x1c,0x0e,0x0e, 0x1c,0x11,0x0e, 0x1c,0x15,0x0e, 0x1c,0x18,0x0e, 348 | 0x1c,0x1c,0x0e, 0x18,0x1c,0x0e, 0x15,0x1c,0x0e, 0x11,0x1c,0x0e, 349 | 0x0e,0x1c,0x0e, 0x0e,0x1c,0x11, 0x0e,0x1c,0x15, 0x0e,0x1c,0x18, 350 | 0x0e,0x1c,0x1c, 0x0e,0x18,0x1c, 0x0e,0x15,0x1c, 0x0e,0x11,0x1c, 351 | 0x14,0x14,0x1c, 0x16,0x14,0x1c, 0x18,0x14,0x1c, 0x1a,0x14,0x1c, 352 | 0x1c,0x14,0x1c, 0x1c,0x14,0x1a, 0x1c,0x14,0x18, 0x1c,0x14,0x16, 353 | 0x1c,0x14,0x14, 0x1c,0x16,0x14, 0x1c,0x18,0x14, 0x1c,0x1a,0x14, 354 | 0x1c,0x1c,0x14, 0x1a,0x1c,0x14, 0x18,0x1c,0x14, 0x16,0x1c,0x14, 355 | 0x14,0x1c,0x14, 0x14,0x1c,0x16, 0x14,0x1c,0x18, 0x14,0x1c,0x1a, 356 | 0x14,0x1c,0x1c, 0x14,0x1a,0x1c, 0x14,0x18,0x1c, 0x14,0x16,0x1c, 357 | 0x00,0x00,0x10, 0x04,0x00,0x10, 0x08,0x00,0x10, 0x0c,0x00,0x10, 358 | 0x10,0x00,0x10, 0x10,0x00,0x0c, 0x10,0x00,0x08, 0x10,0x00,0x04, 359 | 0x10,0x00,0x00, 0x10,0x04,0x00, 0x10,0x08,0x00, 0x10,0x0c,0x00, 360 | 0x10,0x10,0x00, 0x0c,0x10,0x00, 0x08,0x10,0x00, 0x04,0x10,0x00, 361 | 362 | 0x00,0x10,0x00, 0x00,0x10,0x04, 0x00,0x10,0x08, 0x00,0x10,0x0c, 363 | 0x00,0x10,0x10, 0x00,0x0c,0x10, 0x00,0x08,0x10, 0x00,0x04,0x10, 364 | 0x08,0x08,0x10, 0x0a,0x08,0x10, 0x0c,0x08,0x10, 0x0e,0x08,0x10, 365 | 0x10,0x08,0x10, 0x10,0x08,0x0e, 0x10,0x08,0x0c, 0x10,0x08,0x0a, 366 | 0x10,0x08,0x08, 0x10,0x0a,0x08, 0x10,0x0c,0x08, 0x10,0x0e,0x08, 367 | 0x10,0x10,0x08, 0x0e,0x10,0x08, 0x0c,0x10,0x08, 0x0a,0x10,0x08, 368 | 0x08,0x10,0x08, 0x08,0x10,0x0a, 0x08,0x10,0x0c, 0x08,0x10,0x0e, 369 | 0x08,0x10,0x10, 0x08,0x0e,0x10, 0x08,0x0c,0x10, 0x08,0x0a,0x10, 370 | 0x0b,0x0b,0x10, 0x0c,0x0b,0x10, 0x0d,0x0b,0x10, 0x0f,0x0b,0x10, 371 | 0x10,0x0b,0x10, 0x10,0x0b,0x0f, 0x10,0x0b,0x0d, 0x10,0x0b,0x0c, 372 | 0x10,0x0b,0x0b, 0x10,0x0c,0x0b, 0x10,0x0d,0x0b, 0x10,0x0f,0x0b, 373 | 0x10,0x10,0x0b, 0x0f,0x10,0x0b, 0x0d,0x10,0x0b, 0x0c,0x10,0x0b, 374 | 0x0b,0x10,0x0b, 0x0b,0x10,0x0c, 0x0b,0x10,0x0d, 0x0b,0x10,0x0f, 375 | 0x0b,0x10,0x10, 0x0b,0x0f,0x10, 0x0b,0x0d,0x10, 0x0b,0x0c,0x10, 376 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 377 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00 378 | }; 379 | 380 | 381 | /**************************************************************** 382 | * Video mode list 383 | ****************************************************************/ 384 | 385 | #define PAL(x) x, sizeof(x) 386 | #define VPARAM(x) &video_param_table[x] 387 | 388 | static struct vgamode_s vga_modes[] VAR16 = { 389 | //mode vparam model bits sstart pelm dac 390 | {0x00, VPARAM(0x17), CTEXT, 4, SEG_CTEXT, 0xFF, PAL(palette2)}, 391 | {0x01, VPARAM(0x17), CTEXT, 4, SEG_CTEXT, 0xFF, PAL(palette2)}, 392 | {0x02, VPARAM(0x18), CTEXT, 4, SEG_CTEXT, 0xFF, PAL(palette2)}, 393 | {0x03, VPARAM(0x18), CTEXT, 4, SEG_CTEXT, 0xFF, PAL(palette2)}, 394 | {0x04, VPARAM(0x04), CGA, 2, SEG_CTEXT, 0xFF, PAL(palette1)}, 395 | {0x05, VPARAM(0x05), CGA, 2, SEG_CTEXT, 0xFF, PAL(palette1)}, 396 | {0x06, VPARAM(0x06), CGA, 1, SEG_CTEXT, 0xFF, PAL(palette1)}, 397 | {0x07, VPARAM(0x07), MTEXT, 4, SEG_MTEXT, 0xFF, PAL(palette0)}, 398 | {0x0D, VPARAM(0x0d), PLANAR4, 4, SEG_GRAPH, 0xFF, PAL(palette1)}, 399 | {0x0E, VPARAM(0x0e), PLANAR4, 4, SEG_GRAPH, 0xFF, PAL(palette1)}, 400 | {0x0F, VPARAM(0x11), PLANAR1, 1, SEG_GRAPH, 0xFF, PAL(palette0)}, 401 | {0x10, VPARAM(0x12), PLANAR4, 4, SEG_GRAPH, 0xFF, PAL(palette2)}, 402 | {0x11, VPARAM(0x1a), PLANAR1, 1, SEG_GRAPH, 0xFF, PAL(palette2)}, 403 | {0x12, VPARAM(0x1b), PLANAR4, 4, SEG_GRAPH, 0xFF, PAL(palette2)}, 404 | {0x13, VPARAM(0x1c), LINEAR8, 8, SEG_GRAPH, 0xFF, PAL(palette3)}, 405 | {0x6A, VPARAM(0x1d), PLANAR4, 4, SEG_GRAPH, 0xFF, PAL(palette2)}, 406 | }; 407 | 408 | struct vgamode_s * 409 | find_vga_entry(u8 mode) 410 | { 411 | int i; 412 | for (i = 0; i < ARRAY_SIZE(vga_modes); i++) { 413 | struct vgamode_s *vmode_g = &vga_modes[i]; 414 | if (GET_GLOBAL(vmode_g->svgamode) == mode) 415 | return vmode_g; 416 | } 417 | return NULL; 418 | } 419 | 420 | // u16 video_save_pointer_table[14] VAR16; 421 | 422 | 423 | /**************************************************************** 424 | * Static functionality table 425 | ****************************************************************/ 426 | 427 | u8 static_functionality[0x10] VAR16 = { 428 | /* 0 */ 0xff, // All modes supported #1 429 | /* 1 */ 0xe0, // All modes supported #2 430 | /* 2 */ 0x0f, // All modes supported #3 431 | /* 3 */ 0x00, 0x00, 0x00, 0x00, // reserved 432 | /* 7 */ 0x07, // 200, 350, 400 scan lines 433 | /* 8 */ 0x02, // mamimum number of visible charsets in text mode 434 | /* 9 */ 0x08, // total number of charset blocks in text mode 435 | /* a */ 0xe7, // Change to add new functions 436 | /* b */ 0x0c, // Change to add new functions 437 | /* c */ 0x00, // reserved 438 | /* d */ 0x00, // reserved 439 | /* e */ 0x00, // Change to add new functions 440 | /* f */ 0x00 // reserved 441 | }; 442 | -------------------------------------------------------------------------------- /vgatables.h: -------------------------------------------------------------------------------- 1 | /* VGA register definitions 2 | 3 | This file is copied (somewhat) intact from SeaBIOS. 4 | It is covered by the GNU Lesser General Public License, v3. 5 | 6 | You should have received a copy of the GNU Lesser General Public License 7 | along with this program; see the file COPYING. If not see 8 | . */ 9 | 10 | #ifndef VGATABLES_H 11 | #define VGATABLES_H 12 | 13 | typedef uint8_t u8; 14 | typedef uint16_t u16; 15 | 16 | 17 | /* 18 | * 19 | * VGA registers 20 | * 21 | */ 22 | #define VGAREG_ACTL_ADDRESS 0x3c0 23 | #define VGAREG_ACTL_WRITE_DATA 0x3c0 24 | #define VGAREG_ACTL_READ_DATA 0x3c1 25 | 26 | #define VGAREG_INPUT_STATUS 0x3c2 27 | #define VGAREG_WRITE_MISC_OUTPUT 0x3c2 28 | #define VGAREG_VIDEO_ENABLE 0x3c3 29 | #define VGAREG_SEQU_ADDRESS 0x3c4 30 | #define VGAREG_SEQU_DATA 0x3c5 31 | 32 | #define VGAREG_PEL_MASK 0x3c6 33 | #define VGAREG_DAC_STATE 0x3c7 34 | #define VGAREG_DAC_READ_ADDRESS 0x3c7 35 | #define VGAREG_DAC_WRITE_ADDRESS 0x3c8 36 | #define VGAREG_DAC_DATA 0x3c9 37 | 38 | #define VGAREG_READ_FEATURE_CTL 0x3ca 39 | #define VGAREG_READ_MISC_OUTPUT 0x3cc 40 | 41 | #define VGAREG_GRDC_ADDRESS 0x3ce 42 | #define VGAREG_GRDC_DATA 0x3cf 43 | 44 | #define VGAREG_MDA_CRTC_ADDRESS 0x3b4 45 | #define VGAREG_MDA_CRTC_DATA 0x3b5 46 | #define VGAREG_VGA_CRTC_ADDRESS 0x3d4 47 | #define VGAREG_VGA_CRTC_DATA 0x3d5 48 | 49 | #define VGAREG_MDA_WRITE_FEATURE_CTL 0x3ba 50 | #define VGAREG_VGA_WRITE_FEATURE_CTL 0x3da 51 | #define VGAREG_ACTL_RESET 0x3da 52 | 53 | #define VGAREG_MDA_MODECTL 0x3b8 54 | #define VGAREG_CGA_MODECTL 0x3d8 55 | #define VGAREG_CGA_PALETTE 0x3d9 56 | 57 | /* Video memory */ 58 | #define SEG_GRAPH 0xA000 59 | #define SEG_CTEXT 0xB800 60 | #define SEG_MTEXT 0xB000 61 | 62 | /* 63 | * Tables of default values for each mode 64 | */ 65 | #define TEXT 0x80 66 | 67 | #define CTEXT (0x00 | TEXT) 68 | #define MTEXT (0x01 | TEXT) 69 | #define CGA 0x02 70 | #define PLANAR1 0x03 71 | #define PLANAR4 0x04 72 | #define LINEAR8 0x05 73 | 74 | // for SVGA 75 | #define LINEAR15 0x10 76 | #define LINEAR16 0x11 77 | #define LINEAR24 0x12 78 | #define LINEAR32 0x13 79 | 80 | #define SCREEN_IO_START(x,y,p) (((((x)*(y)) | 0x00ff) + 1) * (p)) 81 | #define SCREEN_MEM_START(x,y,p) SCREEN_IO_START(((x)*2),(y),(p)) 82 | 83 | /* standard BIOS Video Parameter Table */ 84 | struct __attribute__((packed)) VideoParam_s { 85 | u8 twidth; 86 | u8 theightm1; 87 | u8 cheight; 88 | u16 slength; 89 | u8 sequ_regs[4]; 90 | u8 miscreg; 91 | u8 crtc_regs[25]; 92 | u8 actl_regs[20]; 93 | u8 grdc_regs[9]; 94 | }; 95 | 96 | struct vgamode_s { 97 | u8 svgamode; 98 | struct VideoParam_s *vparam; 99 | u8 memmodel; /* CTEXT,MTEXT,CGA,PL1,PL2,PL4,P8,P15,P16,P24,P32 */ 100 | u8 pixbits; 101 | u16 sstart; 102 | u8 pelmask; 103 | u8 *dac; 104 | u16 dacsize; 105 | }; 106 | 107 | struct saveVideoHardware { 108 | u8 sequ_index; 109 | u8 crtc_index; 110 | u8 grdc_index; 111 | u8 actl_index; 112 | u8 feature; 113 | u8 sequ_regs[4]; 114 | u8 sequ0; 115 | u8 crtc_regs[25]; 116 | u8 actl_regs[20]; 117 | u8 grdc_regs[9]; 118 | u16 crtc_addr; 119 | u8 plane_latch[4]; 120 | }; 121 | 122 | struct saveBDAstate { 123 | u8 video_mode; 124 | u16 video_cols; 125 | u16 video_pagesize; 126 | u16 crtc_address; 127 | u8 video_rows; 128 | u16 char_height; 129 | u8 video_ctl; 130 | u8 video_switches; 131 | u8 modeset_ctl; 132 | u16 cursor_type; 133 | u16 cursor_pos[8]; 134 | u16 video_pagestart; 135 | u8 video_page; 136 | #if 0 137 | /* current font */ 138 | struct segoff_s font0; 139 | struct segoff_s font1; 140 | #endif 141 | }; 142 | 143 | struct saveDACcolors { 144 | u8 rwmode; 145 | u8 peladdr; 146 | u8 pelmask; 147 | u8 dac[768]; 148 | u8 color_select; 149 | }; 150 | 151 | // vgatables.c 152 | struct vgamode_s *find_vga_entry(u8 mode); 153 | extern u16 video_save_pointer_table[]; 154 | extern struct VideoParam_s video_param_table[]; 155 | extern u8 static_functionality[]; 156 | 157 | // vgafonts.c 158 | extern const u8 vgafont8[]; 159 | extern const u8 vgafont14[]; 160 | extern const u8 vgafont16[]; 161 | extern const u8 vgafont14alt[]; 162 | extern const u8 vgafont16alt[]; 163 | 164 | // vga.c 165 | struct carattr { 166 | u8 car, attr, use_attr; 167 | }; 168 | struct cursorpos { 169 | u8 x, y, page; 170 | }; 171 | 172 | // vgafb.c 173 | void clear_screen(struct vgamode_s *vmode_g); 174 | void vgafb_scroll(int nblines, int attr 175 | , struct cursorpos ul, struct cursorpos lr); 176 | void vgafb_write_char(struct cursorpos cp, struct carattr ca); 177 | struct carattr vgafb_read_char(struct cursorpos cp); 178 | void vgafb_write_pixel(u8 color, u16 x, u16 y); 179 | u8 vgafb_read_pixel(u16 x, u16 y); 180 | void vgafb_load_font(u16 seg, void *src_far, u16 count 181 | , u16 start, u8 destflags, u8 fontsize); 182 | 183 | // vgaio.c 184 | void vgahw_screen_disable(void); 185 | void vgahw_screen_enable(void); 186 | void vgahw_set_border_color(u8 color); 187 | void vgahw_set_overscan_border_color(u8 color); 188 | u8 vgahw_get_overscan_border_color(void); 189 | void vgahw_set_palette(u8 palid); 190 | void vgahw_set_single_palette_reg(u8 reg, u8 val); 191 | u8 vgahw_get_single_palette_reg(u8 reg); 192 | void vgahw_set_all_palette_reg(u8 *data); 193 | void vgahw_get_all_palette_reg(u8 *data); 194 | void vgahw_toggle_intensity(u8 flag); 195 | void vgahw_select_video_dac_color_page(u8 flag, u8 data); 196 | void vgahw_read_video_dac_state(u8 *pmode, u8 *curpage); 197 | void vgahw_set_dac_regs(u8 *data, u8 start, int count); 198 | void vgahw_get_dac_regs(u8 *data, u8 start, int count); 199 | void vgahw_set_pel_mask(u8 val); 200 | u8 vgahw_get_pel_mask(void); 201 | void vgahw_save_dac_state(struct saveDACcolors *info); 202 | void vgahw_restore_dac_state(struct saveDACcolors *info); 203 | void vgahw_sequ_write(u8 index, u8 value); 204 | void vgahw_grdc_write(u8 index, u8 value); 205 | void vgahw_set_text_block_specifier(u8 spec); 206 | void get_font_access(void); 207 | void release_font_access(void); 208 | void vgahw_set_cursor_shape(u8 start, u8 end); 209 | void vgahw_set_active_page(u16 address); 210 | void vgahw_set_cursor_pos(u16 address); 211 | void vgahw_set_scan_lines(u8 lines); 212 | u16 vgahw_get_vde(void); 213 | void vgahw_save_state(struct saveVideoHardware *info); 214 | void vgahw_restore_state(struct saveVideoHardware *info); 215 | void vgahw_set_mode(struct VideoParam_s *vparam_g); 216 | void vgahw_enable_video_addressing(u8 disable); 217 | void vgahw_init(void); 218 | 219 | // clext.c 220 | void cirrus_set_video_mode(u8 mode); 221 | void cirrus_init(void); 222 | 223 | #endif // vgatables.h 224 | --------------------------------------------------------------------------------