IORW allows to do both write-and-read in one call, if you need to pass params for the "read" operation , the ioctl alllows you to pass a struct with BOTH the params by "write" , and then do a "read" to pass data from kernel to user.
i.e. the kernel code will do "copy from user" + preare the data + "copy to user".
Also read/write are blocking , only one thread can call it , i think ioctl can be called by multiple user threads, same as poll()