Starting with the normal basic information copied from
http://lateblt.tripod.com/atapi.htmPrimary IDE controller: 1F0h to 1F7h and 3F6h to 3F7h
Secondary IDE controller: 170h to 177h and 376h to 377h
1F0 (Read and Write): Data Register
1F1 (Read): Error Register
1F1 (Write): Features Register
1F2 (Read and Write): Sector Count Register
1F3 (Read and Write): LBA Low Register
1F4 (Read and Write): LBA Mid Register
1F5 (Read and Write): LBA High Register
1F6 (Read and Write): Drive/Head Register
1F7 (Read): Status Register
1F7 (Write): Command Register
3F6 (Read): Alternate Status Register
3F6 (Write): Device Control Register
So for your 4-port controller the equivalent would be:
I/O ports at 40b8 [size=8] = 40b8-40bf = Primary IDE controller: 1F0h to 1F7h
I/O ports at 40cc [size=4] = 40cc-40cf = Primary IDE controller: 3F6h to 3F7h (this is tricky, but normally the third byte (40ce in this case) is the equivalent to 3F6)
I/O ports at 40b0 [size=8] = 40b0-40b7 = Secondary IDE controller: 170h to 177h
I/O ports at 40c8 [size=4] = 40c8-40cb = Secondary IDE controller: 376h to 377h (40ca would = 376)
I/O ports at 4090 [size=16] - for DMA access, don't mess with these ports
I/O ports at 4080 [size=16] - for DMA access, don't mess with these ports
The 2-port controller works the same way except the secondary controller will always give results of no drives attached.