From: Geert U. <ge...@li...> - 2000-07-19 11:27:29
|
On Tue, 18 Jul 2000, Arno Griffioen wrote: > > BTW Gerard said the driver should be MMIO and not IO_MAPPED. I may try > > turning off I/O mapped and see what happens. He also said he would have > > liked to work on MMIO, on non-PC hardware I presume, but has no hardware > > to do the work. Does anyone have any ideas on MMIO vs IO MAPPED? On > > first thought I'm not sure I understand the differences. > > Probably some subtle difference. MMIO should be the way we're used to on the > 680x0 and PPC. 'flat' register space in memory. No special tricks required, > just a base-address and some offsets. > > I'm not sure what the difference would be between MMIO and IO_MAPPED, but > perhaps it's some way of mapping the Intel I/O port concept onto > memory. That my require some tricks when accessing (eg. write register > number first, then read or write data). > > Perhaps Geert has seen this difference before in video-cards? They also > have all sorts of MMIO and I/O mapping stuff. Intel CPUs have separate memory and I/O spaces, while a 680x0 has memory space only. I/O space is meant for I/O devices (obviously) and uses special I/O instructions ({in,out}[bwl]) to access I/O registers. Memory space I/O (MMIO) means you just read/write from/to memory to access the I/O registers that are located at the specified memory address. I/O space allows you to have the full memory space populated with RAM, and still room for I/O devices in I/O space. But since you need more bus signals (to differentiate between memory and I/O accesses) and more instructions (normal memory access + special I/O instructions), modern CPUs don't have I/O space anymore. If they need it, they just reserve some piece of memory for it, and use the ordinary memory instructions to access it, while the host bridge takes care of converting them to I/O accesses on the I/O bus (usually PCI these days, with ISA behind a PCI/ISA bridge). Under Linux/m68k, inb() and friends don't do anything on Amiga, since Amiga doesn't have I/O space (except with your GG2, Arno :-). Under Linux/PPC, inb() and friends just access MMIO at isa_io_base+offset (cfr. <asm/io.h>). Indeed, on PReP and CHRP ISA and PCI I/O space is not real I/O space, but MMIO at some specific address. On APUS, there's no I/O space (AFAIK), so you always have to use MMIO. Since you used I/O space (through inb() and friends), data written ended up somewhere at the wrong address (uninitialized isa_io_base on APUS), which was probably a 16-bit only address of whatever. Reading it back thus gave the wrong value. Instead of inb() and friends you should read/write from/to memory space directly, using in_be32() and friends. These do eieio as well, to protect against reorderings. BTW, I see some things in <asm/io.h> that shouldn't be there: #if defined(CONFIG_APUS) #define inw(port) in_be16((u16 *)((port)+_IO_BASE)) #define outw(val, port) out_be16((u16 *)((port)+_IO_BASE), (val)) #define inl(port) in_be32((u32 *)((port)+_IO_BASE)) #define outl(val, port) out_be32((u32 *)((port)+_IO_BASE), (val)) #else Since APUS doesn't have I/O space, these should not be defined at all. [ Hmm, they are defined to in_be16() and friends. Why??? ] Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@li... In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds |