diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2001-01-10 05:27:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2001-01-10 05:27:25 +0000 |
commit | c9c06167e7933d93a6e396174c68abf242294abb (patch) | |
tree | d9a8bb30663e9a3405a1ef37ffb62bc14b9f019f /Documentation/parisc | |
parent | f79e8cc3c34e4192a3e5ef4cc9c6542fdef703c0 (diff) |
Merge with Linux 2.4.0-test12.
Diffstat (limited to 'Documentation/parisc')
-rw-r--r-- | Documentation/parisc/00-INDEX | 10 | ||||
-rw-r--r-- | Documentation/parisc/IODC.txt | 68 | ||||
-rw-r--r-- | Documentation/parisc/debugging | 39 | ||||
-rw-r--r-- | Documentation/parisc/mm | 31 | ||||
-rw-r--r-- | Documentation/parisc/registers | 126 |
5 files changed, 274 insertions, 0 deletions
diff --git a/Documentation/parisc/00-INDEX b/Documentation/parisc/00-INDEX new file mode 100644 index 000000000..7c8494ea2 --- /dev/null +++ b/Documentation/parisc/00-INDEX @@ -0,0 +1,10 @@ +00-INDEX + - this file. +IODC.txt + - Documentation IODC +debugging + - some debugging hints for real-mode code +mm + - Documentation on parisc mm status +registers + - current/planned usage of registers diff --git a/Documentation/parisc/IODC.txt b/Documentation/parisc/IODC.txt new file mode 100644 index 000000000..d686536f1 --- /dev/null +++ b/Documentation/parisc/IODC.txt @@ -0,0 +1,68 @@ +Some notes on IODC, its general brokenness, and how to work around it. + +Short Version + +IODC is HP's pre-PCI standard for device identification (a la PCI vendor, +device IDs), detection, configuration, initialization and so on. + +It also can provide firmware function to do the actual IO, which are slow, +not really defined for runtime usage and generally not desirable. (There +are other firmware standards, such as STI, to do real IO). + +Usually, there are two parts to IODC. The actual ROMs, which are laid out, +detected aso in a bus-specific manner (IO_DC_ADDRESS / IO_DC_DATA on +GSC/Runway, PCI spec - compliant ROMs for PCI, God-only-knows how on EISA), +and the slightly cooked data read by PDC_IODC. + +The ROM layout is generally icky (only one byte out of every 4-byte-word +might be valid, and many devices don't implement required options), so +using PDC_IODC is highly recommended. (In fact, you should use the device +lists set up by the kernel proper instead of calling PDC_IODC yourself). + +Now, let's have a look at what the cooked ROM looks like (see iodc.pdf for +the details, this is the simplified version). + +Basically, the first 8 bytes of IODC contain two 32-bit ids called HVERSION +and SVERSION. Those are further split up into bit fields, and +unfortunately just ignoring this split up isn't an option. + +SVERSION consists of a 4-bit revision field, a 20-bit model field and a +8-bit opt field. Now, forget the revision and opt fields exist. Basically, +the model field is equivalent to a PCI device id (there is no vendor id. +this is proprietary hardware we're talking about). That is, all your +driver cares for, in 90 % of the cases, is to find all devices that match +the model field. + +The rev field is - you guessed it - roughly equivalent to the revision +byte for PCI, with the exception that higher revisions should be strict +supersets of lower revisions. + +The last byte of HVERSION, "type", and the last byte of SVERSION, "opt", +belong together; type gives a very rough indication of what the device +is supposed to do, and opt contains some type-specific information. (For +example, the "bus converter" (ie bus bridge) type encodes the kind of +bus behind the bridge in the opt field. + +The rest of HVERSION contains, in most cases, a number identifying the +machine the chip was used in, or a revision indicator that just fixed +bugs and didn't add any features (or was done in a shrinked process or +whatever). + +So, here's the interface you actually should use to find your devices: + + +/* Find a device, matching the model field of sversion only (from=NULL + * for the first call */ +struct iodc_dev *iodc_find_device(u32 sversion, struct iodc_dev *from); + + +Here's a function you should use if you have special requirements, such +as finding devices by type rather than by model. Generally, if you're +using this, you should be me). + +/* Find a device, masking out bits as specified */ +struct iodc_dev *iodc_find_device_mask(u32 hversion, u32 sversion, + u32 hversion_mask, u32 sversion_mask, struct iodc_dev *from); + + + Philipp Rumpf <prumpf@tux.org> diff --git a/Documentation/parisc/debugging b/Documentation/parisc/debugging new file mode 100644 index 000000000..5e060917a --- /dev/null +++ b/Documentation/parisc/debugging @@ -0,0 +1,39 @@ +okay, here are some hints for debugging the lower-level parts of +linux/parisc. + + +1. Absolute addresses + +A lot of the assembly code currently runs in real mode, which means +absolute addresses are used instead of virtual addresses as in the +rest of the kernel. To translate an absolute address to a virtual +address you can lookup in System.map, add __PAGE_OFFSET (0xc0000000 +currently). + + +2. HPMCs + +When real-mode code tries to access non-existent memory, you'll get +an HPMC instead of a kernel oops. To debug an HPMC, try to find +the System Responder/Requestor addresses. The System Requestor +address should match (one of the) processor HPAs (high addresses in +the I/O range); the System Responder address is the address real-mode +code tried to access. + +Typical values for the System Responder address are addresses larger +than __PAGE_OFFSET (0xc0000000) which mean a virtual address didn't +get translated to a physical address before real-mode code tried to +access it. + + +3. Q bit fun + +Certain, very critical code has to clear the Q bit in the PSW. What +happens when the Q bit is cleared is the CPU does not update the +registers interruption handlers read to find out where the machine +was interrupted - so if you get an interruption between the instruction +that clears the Q bit and the RFI that sets it again you don't know +where exactly it happened. If you're lucky the IAOQ will point to the +instrucion that cleared the Q bit, if you're not it points anywhere +at all. Usually Q bit problems will show themselves in unexplainable +system hangs or running off the end of physical memory. diff --git a/Documentation/parisc/mm b/Documentation/parisc/mm new file mode 100644 index 000000000..d53b29508 --- /dev/null +++ b/Documentation/parisc/mm @@ -0,0 +1,31 @@ + +The current state of Linux/PA-RISC mm is BROKEN. + +Someone needs to sit down and thoroughly rewrite all the cache flushing +macro definitions. Here are some of the problems, followed by what I +think needs to be done about them. + +(1) We're using fdce / fice everywhere. This has to stop (except in +the routines which flush the entire cache). The right instructions to +be using are fdc/fic. + +(2) fdc/fic will throw exceptions if the address they reference isn't +mapped. Therefore we need to check the page is mapped before flushing +(we're guaranteed not to have the page dirty if we don't have a software +mapping for it any longer, right?) + +(3) the flush macros are right now tunnelled down to one routine to flush +the data cache and one routine to flush the insn cache. this is wrong. +we should take hints from how we're called and optimise our routines +accordingly. + +(4) fdc/fic actually take space register arguments. fic takes an 3-bit sr +argument and fdc takes a 2-bit sr argument. right now, there's a lot of +pissing about with %sr1 and all the macros use %sr1. This is crazy. We +normally _know_ what's being referred to, and it's the current task. So +if we want to flush that, just use %sr3. If it happens to be kernel, +use %sr0 for fdc and %sr4 for fic. + +(5) we need to write flush_kernel_dcache_range and use it on kernel +addresses. all the macros are defined to work on the _current task's_ +virtual address space. diff --git a/Documentation/parisc/registers b/Documentation/parisc/registers new file mode 100644 index 000000000..28097fe49 --- /dev/null +++ b/Documentation/parisc/registers @@ -0,0 +1,126 @@ +Register Usage for Linux/PA-RISC + +[ an asterisk is used for planned usage which is currently unimplemented ] + + General Registers as specified by ABI + + FPU Registers must not be used in kernel mode + + Control Registers + +CR 0 (Recovery Counter) used for ptrace +CR 1-CR 7(undefined) unused +CR 8 (Protection ID) per-process value* +CR 9, 12, 13 (PIDS) unused +CR10 (CCR) lazy FPU saving* +CR11 as specified by ABI +CR14 (interruption vector) initialized to fault_vector +CR15 (EIEM) initialized to all ones* +CR16 (Interval Timer) timer interrupt +CR17-CR22 interruption parameters +CR23 (EIRR) read for pending interrupts +CR24 (TR 0) Kernel Space Page Directory Pointer +CR25 (TR 1) User Space Page Directory Pointer +CR26 (TR 2) +CR27 (TR 3) +CR28 (TR 4) used by interruption handlers +CR29 (TR 5) used by interruption handlers +CR30 (TR 6) current / 0 +CR31 (TR 7) used by interruption handlers + + Space Registers (kernel mode) + +SR0 temporary space register +SR4-SR7 set to 0 +SR1 temporary space register +SR2 unused +SR3 used for userspace accesses (current process)* + + Space Registers (user mode) + +SR0 temporary space register +SR1 temporary space register +SR2 holds space of linux gateway page +SR3 holds user address space value while in kernel +SR4-SR7 Defines short address space for user/kernel + + + Processor Status Word + +W (64-bit addresses) 0 +E (Little-endian) 0 +S (Secure Interval Timer) 0 +T (Taken Branch Trap) 0 +H (Higher-privilege trap) 0 +L (Lower-privilege trap) 0 +N (Nullify next instruction) used by C code +X (Data memory break disable) 0 +B (Taken Branch) used by C code +C (code address translation) 1, 0 while executing real-mode code +V (divide step correction) used by C code +M (HPMC mask) 0, 1 while executing HPMC handler* +C/B (carry/borrow bits) used by C code +O (ordered references) 1* +F (performance monitor) 0 +R (Recovery Counter trap) 0 +Q (collect interruption state) 1 (0 in code directly preceding an rfi) +P (Protection Identifiers) 1* +D (Data address translation) 1, 0 while executing real-mode code +I (external interrupt mask) used by cli()/sti() macros + + "Invisible" Registers + +PSW default W value 0 +PSW default E value 0 +Shadow Registers used by interruption handler code +TOC enable bit 1 + +========================================================================= +Info from John Marvin: + +From: "John Marvin" <jsm@udlkern.fc.hp.com> +To: randolf@tausq.org +Subject: Re: parisc asm questions + +[...] + +For the general registers: + +r1,r2,r19-r26,r28,r29 & r31 can be used without saving them first. And of +course, you need to save them if you care about them, before calling +another procedure. Some of the above registers do have special meanings +that you should be aware of: + + r1: The addil instruction is hardwired to place its result in r1, + so if you use that instruction be aware of that. + + r2: This is the return pointer. In general you don't want to + use this, since you need the pointer to get back to your + caller. However, it is grouped with this set of registers + since the caller can't rely on the value being the same + when you return, i.e. you can copy r2 to another register + and return through that register after trashing r2, and + that should not cause a problem for the calling routine. + + r19-r22: these are generally regarded as temporary registers. + Note that in 64 bit they are arg7-arg4. + + r23-r26: these are arg3-arg0, i.e. you can use them if you + don't care about the values that were passed in anymore. + + r28,r29: are ret0 and ret1. They are what you pass return values + in. r28 is the primary return. I'm not sure I remember + under what circumstances stuff is returned in r29 (millicode + perhaps). + + r31: the ble instruction puts the return pointer in here. + + +r3-r18,r27,r30 need to be saved and restored. r3-r18 are just + general purpose registers. r27 is the data pointer, and is + used to make references to global variables easier. r30 is + the stack pointer. + +John + + |