Device drivers form an interface between an OS's device API and actual hardware registers.
The linux device API model is a continuation of the broader linux concept that everything is a file, and that an application can accomplish anything it needs to with the open(), read(), write(), ioctl(), and close() interface. Under the hood, there's an install() routine, but the OS decides when to call that.
The other side of the coin is hardware. The CPU accesses device registers either with special I/O instructions, or ordinary memory accesses to special memory locations that are connected to hardware. While hardware registers can act like memory, they can do things that memory cannot. Quite frequently, writing to one of a device's registers can change values some of its other registers, and to the point, can change or be changed by electrical activity in the connected hardware.
Device drivers bridge this gap. Since the possibilities for devices types are almost unlimited, it's hard to generalize about how functions are mapped, beyond just a few points. The install() routine is hit at system start up time, configures registers for proper operation, normally this includes setting up interrupt service and handling; the open() routine gives an application a logical connection to the device; there's usually an effort to make read() and write() move data in some sensible way, though sometimes you see these implemented as no-ops; and on-the-fly device settings are operated through ioctl(). And of course, the main job of close() is to undo the work of open(), taking special care to release any system resources grabbed by open().
Well, that's the linux-centric take, anyway. The windows model, at least the one I'm familiar with (probably dated), tends to offer libraries of device-specific function calls.