1

Based on what I know so far, when you plug an IO device into an IO port (for example, when you plug a printer into a parallel port), the printer will be represented to the CPU as just another RAM chip.

So if you want to create a device driver that communicates with the printer, the instructions that the device driver will contain are simply instructions to store data into the memory locations for the printer, and instructions to load data from the memory locations for the printer.

But can you send data to the printer by directly manipulating the pins of the parallel port, that is, does the CPU have some instruction like this:

send the number 3 to pin 0 of parallel port 1
  • Define "directly" – whatsisname Jun 1 '17 at 6:40
  • @whatsisname It is defined in my question: send the number 3 to pin 0 of parallel port 1 (note that I don't know anything about how parallel ports works, so I don't know if you can actually send a number to the parallel port at one go, I just know that some signals will eventually pass through the parallel port to communicate with the printer, so I am wondering if you can directly specify what to send, instead of sending something indirectly, which happens when you set a value for a register in the printer's device controller). – John Jun 1 '17 at 7:01
3

Based on what I know so far, when you plug an IO device into an IO port (for example, when you plug a printer into a parallel port), the printer will be represented to the CPU as just another RAM chip.

It's better to think of this scenario as 2 separate devices, where one device (the parallel port controller) may or may not be presented to the CPU as just another RAM chip (and almost never is), and the other device (the printer) is not presented to the CPU at all. To send a byte to the printer, the printer's driver asks the parallel port controller's driver to send a byte, and the parallel port controller's driver tells the parallel port controller to send the byte.

Note that RAM chips have a special characteristic - reads and writes have no side effects. Because there are no side effects it's easy to use a few tricks to improve performance; like having caches, or combining smaller reads or writes into fewer larger reads/writes, or doing read or writes in a different order. A device's registers almost always do have side effects, and therefore they often can't be treated the same as RAM chips.

But can you send data to the printer by directly manipulating the pins of the parallel port, that is, does the CPU have some instruction like this:

Let's start by assuming that the CPU has a physical address space, and that the physical address space is 4 GiB and that each physical address is a 32-bit address.

Let's assume that 2 GiB of the physical address space (addresses 0x00000000 to 0x7FFFFFFF) is used for RAM, and that for reads and writes in that area the CPU does tricks to improve performance (caching, etc).

Let's also assume that the remaining 2 GiB of the physical address space (addresses 0x80000000 to 0xFFFFFFFF) may be used for various devices (and the CPU does not do any tricks for reads and writes to this area).

Finally; let's assume that the CPU has instructions that read or write to any address. The same instruction that reads (e.g.) a variable in your application (with one address) can be used to read (e.g.) a parallel port controller's register (at a different address).

In this case there is no need for the CPU to have special instructions for devices.

However...

For some CPUs there are multiple address spaces. For example, for 80x86 there is the physical address space (like what I've described above), but there is also an "IO port address space". In this case the CPU would have some special instructions that are used to access the special address space (e.g. in and out instructions to access the "IO port address space") and these special instructions might have different behaviour to normal instructions that read or write to the physical address space (e.g. they might bypass the MMU, or involve completely different permission checks).

  • "where one device (the parallel port controller) may or may not be presented to the CPU as just another RAM chip (and almost never is)" But if the parallel port controller is not presented to the CPU as another RAM chip, then how can you set some register value in the parallel port controller? (note that that by "presented to the CPU as just another RAM chip" I simply mean that when the CPU wants to set/read a register value, it will use the same instructions to set/read a memory location (for example: mov). – John Jun 1 '17 at 14:03
  • The first parallel port on a traditional PC is IO-mapped in the IO port range 378-37a hex. These numbers identify registers on the parallel port controller which the processor can write to (e.g. using the instruction OUT 378h, al too send the contents of the AL register to the first controller register, which in the case of the parallel port will result in the bits that are set in the register driving associated pins on the port to logical high voltage) or read from (eg IN AL, 379h, which reads various status bits from the port). – Jules Jun 1 '17 at 15:04
  • @Jules Now I got it, to send data to or receive data from an IO port pins, you have to set/read some registers values in the IO port controller. But is this how all IO ports work? for example, if I want to send data through a USB port, do I also set some register value in the USB port controller? – John Jun 1 '17 at 15:37
  • USB is complicated, but in essence I believe it is still the same, yes. But not that while the USB controller may have directly accessible registers like this, USB attached devices don't. To control those, you have to place values in the USB controller's registers to ask it to make a request from an attached device. And to be quite honest, I'm not at all sure how PCI Express affects all this, because I think that may add another layer of abstraction to deal with too, so if your USB controller is connected on PCIe t may be even more complex. – Jules Jun 1 '17 at 15:48
2

It does not often work like that anymore (for personal computers). But in the old days, cheap computers used so called memory mapped I/O. Device controller chips were wired into the computer such that the CPU saw one contiguous memory address space, but part of the spectrum did not correlate to memory chip locations but rather to control and data registers of the device controller chip. The CPU did not "know" about this, only the programmer did. So you had to write bytes to certain memory locations in a particular order to make the controller chip do what you wanted it to do.

  • 2
    "It does not often work like that anymore (for personal computers)" How does it work nowadays? the only results I find when searching for something like "how does CPU communicate with IO devices" are about Memory Mapped IO and Port Mapped IO. – John Jun 1 '17 at 7:06
  • The only thing different today is that everything will be hidden in a device driver, invisible to any programmers except driver developers. – gnasher729 Jun 1 '17 at 8:30
  • 2
    Nowadays most external devices are attached to external buses like USB or SATA. or Thunderbolt. That is far more indirect and complex, it is no longer a matter of putting high-or-low voltages on external wires (typically 0 vs 5 V). Instead, messages are sent over a serial bus using complex protocols. And you probably can feed the bus controller on the computer side with data asynchronously, and the controller will take care of sending the data to the printer or whatever apparatus on its own. – Martin Maat Jun 1 '17 at 9:37
  • @Martin Maat Despite the complexities that exist nowadays in connecting IO devices to the computer, the CPU still sees an IO device as memory locations that it can store data to and load data from, correct? – John Jun 1 '17 at 10:17
  • @John I am not sure. It used to be like this for video hardware for a long time and it may still be. I have been out of touch with this for too long, perhaps can some informed hardware guru elaborate on this in another answer. Even older CPUs had specific I/O addressing modes although they were not always used (memory mapped I/O could be used instead). I do not know what is common today on a hardware level. – Martin Maat Jun 1 '17 at 10:33
1

Down at the device driver level, it's just memory-mapped access again. Write setup information and commands to specific addresses, and read specific addresses to see what the response it. Make sure you distinguish between the printer port (which is part of the computer) and the printer (which is on the other end of a cable, and not itself memory-mapped).

Also be aware that some peripheral interfaces these days are hiding behind some other type of controller. So a printer port might actually be connected to a USB interface, if that was easier to design. If that's the case, then the CPU would be talking to the USB bus controller, not directly to the printer port.

  • "Down at the device driver level, that's more or less how it works" You mean the device driver has instructions such as: send the number 3 to pin 0 of parallel port 1? I thought that a device driver communicate with a device just like it does with RAM (that is, storing values in memory locations, and loading values from memory locations). – John Jun 1 '17 at 10:06
  • @John I'll edit the post to clarify. – Simon B Jun 1 '17 at 10:42
  • It depends on a lot of things.One major factor is the type of cpu: most processor types can only talk to external devices via memory mapping, as you describe. But the x86 family is unusual in that it supports a separate bus for io devices, which is operated by a separate set of instructions ("in" and "out") rather than by memory mapping. But even there not all devices use that system mainly because it is a little less efficient fan memory mapping, although it makes the hardware design simpler. For simple devices like a parallel port you would use it but more complex devices use memory mapping. – Jules Jun 1 '17 at 10:45
  • @Jules I remember years ago, the Z80 had a completely different set of addresses for I/O - 64K addresses for RAM and another 64K for I/O, with two sets of instructions to match. To a large extent, this was actually implemented using what was effectively a 17th address pin. But that didn't stop you using memory-mapped hardware if you wanted. – Simon B Jun 1 '17 at 13:53
  • @simonb - yes, the Z80 had separate IO too. This arrangement is, however, quite unusual. Note that the z80 was an enhanced clone of the Intel 8080, and the 8086 was intended as a 16-bit replacement of the 8-bit 8080, so they really are very similar processors in many ways. – Jules Jun 1 '17 at 14:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.