To do a decent interface between a user program and an interrupt enabled hardware device you should write a Kernel driver.
Now the user program (after a open() ) will do (e.g.) a read(). The Kernel driver implements the read function as a blocking read and thus the user program will stall in the read(). After the interrupt (and when it is finished doing the data transfer with the hardware), the Kernel driver unlocks the block and the user program continues to run.
If the user program is supposed to do any work while waiting on the data transfer, it can either be done as a multithreded application with one thread stalling in the read() while others keep running, or you can use select() or epoll() to have the program notified by the driver. select() and epoll() need additional interfaces in the Kernel driver.
-Michael