Firewire has a particularly dumb design, especially for something meant for use *outside* the computer. The kinds of transfers used for SBP-2 are "asynchronous requests", which are commands like "write this data to this address". The address is a 48-bit number.
OHCI (i.e. pretty much every firewire controller) figures out what to do with an asynchronous request by inspecting its address. If the target address is below 0xffffffff, then the request is turned into phsyical DMA (but only if this feature is on). If the target address is above 0xffffffff, then the request is forwarded verbatim to the driver, and the driver can do whatever it wants. (The data is DMA'd to a normal DMA buffer, so the driver might need to do another copy.)
IMO the solution has two parts:
1. Turn off physical DMA. Rearrange the SBP-2 driver to use high (>0xffffffff) addresses and add the appropriate memcpys. Performance drops a little bit, but the security problem goes away.
2. (Only if you want to be super fancy) Rig up the ohci driver to operate in a different mode if to can assign itself a unique iommu domain and if the specific hardware supports a physical dma cutoff that's different from 0xffffffff: Divide the low address space into two regions. DMA used internally by the driver ends up at, say, iova < 2G. Memory mapped for "physical DMA" ends up with 2G < iova < 4G. Program the card to allow firewire-initiated physical DMA only between 2G and 4G. Then have the SBP-2 driver ask the core to "map" its buffers. If supported (in this iommu mode), the buffers will be mapped to iovas 2G and 4G. If not, then the buffers won't be mapped for DMA at all; instead they'll be "mapped" above 4G and something will emulate the DMA.