pub macro pci_driver_match {
    (class ($class:literal:$subclass:literal:$prog_if:literal)) => {
        $crate::driver::PciMatch::Class($class, Some($subclass), Some($prog_if))
    },
    (class ($class:literal:$subclass:literal)) => {
        $crate::driver::PciMatch::Class($class, Some($subclass), None)
    },
    (class $class:literal) => {
        $crate::driver::PciMatch::Class($class, None, None)
    },
    (device ($vendor:literal:$device:literal)) => {
        $crate::driver::PciMatch::Vendor($vendor, $device)
    }
}

pub macro pci_driver(
    matches: [$($kind:ident $match:tt),+ $(,)?],
    driver: $driver:tt
) {
    #[link_section = ".init_array"]
    #[used]
    static __REGISTER_FN: extern "C" fn() = __register_fn;

    extern "C" fn __register_fn() {
        struct Driver;
        impl $crate::driver::PciDriver for Driver $driver
        static DRIVER: Driver = Driver;

        log::info!("register pci driver: {:?}", $crate::driver::PciDriver::driver_name(&Driver));
        $(
            let pmatch = $crate::macros::pci_driver_match!($kind $match);
            $crate::driver::register_match(pmatch, &DRIVER);
        )+
    }
}
