reading from block devices is done using the block cache (bcache).
This cache stores sectors from a block device in pages of memory
marked as 'cached', which will allow them to be reclaimed when
memory pressure is high (TODO).
while block device drivers implement callbacks allowing reading/writing
at block-granularity, the device subsystem uses the block cache to
implement reading/writing at byte-granularity in a driver-agnostic way.
block drivers can disable the block cache for their devices, but this
will require that any clients communicate with the devices at
block-granularity.
also added an offset parameter to device and object read/write functions/callbacks.
generic devices don't have a type (char, block, etc) and are created
by bus drivers to represent the device until a suitable driver is found.
generic devices are registered by the bus driver. once a more suitable
driver is found, that driver will re-register the device under itself.