Hardware interaction is the place where mono fails most often in my experience; portability for something that actually touches the underlying hardware (of any type) is probably not possible using c#.
And for that you can always call the native methods written in C, from C# - the support for doing this is excellent on both Linux and Windows. You can reference a function in a .DLL on windows and in a .so on linux.