This branch kinda rewrites a bunch of the DMAC code. Now, DMA channels
are capable of being dynamically allocated on demand using a cool atomic
bitset thingy, and released back to the DMAC pool when they're no longer
in use. This will allow us to have multiple drivers that consume
basically as many DMA channels as they want to, rather than having a
fixed assignment of DMA channels to drivers which has to be maintained
by manually updating the DMAC IRQ handler every time we add a new driver
that wants to do a DMA. A channel can be allocated from the pool once
and used for multiple transfers, if a driver needs to make a bunch of
transfers in sequence and doesn't want to have to round trip through the
channel pool, but they can also be grabbed for oneshot transfers and
immediately released.
I also fixed the cancel safety of the async Channel::transfer
(formerly Channel::run_descriptor) method, which would previously
leave the transfer running if the future is dropped. This means that if
a caller assumed dropping the transfer future meant that the transfer
descriptor's buffer could be freed, the transfer might complete later
and trample memory that has been reallocated. THAT SEEMS KINDA BAD LOL.
So, now, dropping a Channel::transfer future will cancel the transfer
if it hasn't finished yet, allowing fun stuff like attaching a timeout
to a transfer if you really want to. Of course, the transfer may still
have completed partially, and if we were writing to a device, the device
may be unhappy to have only gotten some of the data it wanted. But, at
least we don't have abandoned DMA transfers running around in random
parts of the heap you probably wanted to use for normal stuff like
having strings, or whatever it is that people do on the computer. So
that's better.
Unfortunately, while we can easily make the DMA transfers Drop-safe,
we can't really make them mem::forget-safe without passing the DMA
buffer into the future and leaking it if it gets forgetted. This is
probably a good idea but would require a nice higher-level interface
around constructing DMA descriptors from buffer-shaped memory regions,
which I didn't want to do tonight. So, the DMA transfer APIs are still
unsafe and maybe we can add a nicer thing on top later. In the
meantime, probably don't mem::forget DMA transfers. Honestly there is
no reason for normal people to do that so I don't feel super bad about
it.
This branch kinda rewrites a bunch of the DMAC code. Now, DMA channels are capable of being dynamically allocated on demand using a cool atomic bitset thingy, and released back to the DMAC pool when they're no longer in use. This will allow us to have multiple drivers that consume basically as many DMA channels as they want to, rather than having a fixed assignment of DMA channels to drivers which has to be maintained by manually updating the DMAC IRQ handler every time we add a new driver that wants to do a DMA. A channel can be allocated from the pool once and used for multiple transfers, if a driver needs to make a bunch of transfers in sequence and doesn't want to have to round trip through the channel pool, but they can also be grabbed for oneshot transfers and immediately released.
I also fixed the cancel safety of the async
Channel::transfer
(formerlyChannel::run_descriptor
) method, which would previously leave the transfer running if the future is dropped. This means that if a caller assumed dropping the transfer future meant that the transfer descriptor's buffer could be freed, the transfer might complete later and trample memory that has been reallocated. THAT SEEMS KINDA BAD LOL. So, now, dropping aChannel::transfer
future will cancel the transfer if it hasn't finished yet, allowing fun stuff like attaching a timeout to a transfer if you really want to. Of course, the transfer may still have completed partially, and if we were writing to a device, the device may be unhappy to have only gotten some of the data it wanted. But, at least we don't have abandoned DMA transfers running around in random parts of the heap you probably wanted to use for normal stuff like having strings, or whatever it is that people do on the computer. So that's better.Unfortunately, while we can easily make the DMA transfers
Drop
-safe, we can't really make themmem::forget
-safe without passing the DMA buffer into the future and leaking it if it gets forgetted. This is probably a good idea but would require a nice higher-level interface around constructing DMA descriptors from buffer-shaped memory regions, which I didn't want to do tonight. So, the DMA transfer APIs are stillunsafe
and maybe we can add a nicer thing on top later. In the meantime, probably don'tmem::forget
DMA transfers. Honestly there is no reason for normal people to do that so I don't feel super bad about it.