It should be noted that in early hardware (before 1960), I/O was much simplier. You could read a card, or punch a card or print a line on the printer, each with a single instruction: the buffer size was fixed, and often the buffer address was fixed too.
Even in the early 60s, with more sophisticated processors (eg. the 7090), you could still read or punch cards with a small routine (about 20 instructions), that was easily copied into each program.
Since the computer was entirely dedicated to a single job, it didn't matter if the processor was idle while waiting for the card reader to be ready to read the next card, or for the line printer to feed up the next line.
Well, it did matter, because computing time was expensive actually. This is why people invented multi-processing, time-sharing, added asynchronous I/O, and interrupts and device drivers and operating systems. The hardware device interfaces became more complex, for the programmer, giving access to lower level I/O registers, which required more complexity from the device drivers. This complexity cost (memory, programming time) was amortized over the several programs using the devices "simultaneously", multiplexed by the operating system.
Still in the 80's I was using a micro-processor based computer, emulating one of those older systems. The machine instructions had a uniform format over 80 bits (10 octets), and the instruction to read the first sector of the first hard disk and store it into the memory at address 0 was very conveniently: 0000000000. So the boot procedure consisted every morning to type this instruction on the terminal, which stored it at address 0 and executed it, which then loaded the boot sector and continued execution at the next instruction (at address 10). The file system consisted in a static table mapping file "names" to ranges of sectors, which were manually allocated! I/O was done in assembler to those files by directly reading or writing the sectors, offset by the position of the file on the hard disk which was recovered by the "open" routine.