1 // SPDX-License-Identifier: GPL-2.0 2 3 // Copyright (C) 2023 FUJITA Tomonori <fujita.tomonori@gmail.com> 4 5 //! Network PHY device. 6 //! 7 //! C headers: [`include/linux/phy.h`](srctree/include/linux/phy.h). 8 9 use crate::{bindings, error::*, prelude::*, str::CStr, types::Opaque}; 10 11 use core::marker::PhantomData; 12 13 /// PHY state machine states. 14 /// 15 /// Corresponds to the kernel's [`enum phy_state`]. 16 /// 17 /// Some of PHY drivers access to the state of PHY's software state machine. 18 /// 19 /// [`enum phy_state`]: srctree/include/linux/phy.h 20 #[derive(PartialEq, Eq)] 21 pub enum DeviceState { 22 /// PHY device and driver are not ready for anything. 23 Down, 24 /// PHY is ready to send and receive packets. 25 Ready, 26 /// PHY is up, but no polling or interrupts are done. 27 Halted, 28 /// PHY is up, but is in an error state. 29 Error, 30 /// PHY and attached device are ready to do work. 31 Up, 32 /// PHY is currently running. 33 Running, 34 /// PHY is up, but not currently plugged in. 35 NoLink, 36 /// PHY is performing a cable test. 37 CableTest, 38 } 39 40 /// A mode of Ethernet communication. 41 /// 42 /// PHY drivers get duplex information from hardware and update the current state. 43 pub enum DuplexMode { 44 /// PHY is in full-duplex mode. 45 Full, 46 /// PHY is in half-duplex mode. 47 Half, 48 /// PHY is in unknown duplex mode. 49 Unknown, 50 } 51 52 /// An instance of a PHY device. 53 /// 54 /// Wraps the kernel's [`struct phy_device`]. 55 /// 56 /// A [`Device`] instance is created when a callback in [`Driver`] is executed. A PHY driver 57 /// executes [`Driver`]'s methods during the callback. 58 /// 59 /// # Invariants 60 /// 61 /// Referencing a `phy_device` using this struct asserts that you are in 62 /// a context where all methods defined on this struct are safe to call. 63 /// 64 /// [`struct phy_device`]: srctree/include/linux/phy.h 65 // During the calls to most functions in [`Driver`], the C side (`PHYLIB`) holds a lock that is 66 // unique for every instance of [`Device`]. `PHYLIB` uses a different serialization technique for 67 // [`Driver::resume`] and [`Driver::suspend`]: `PHYLIB` updates `phy_device`'s state with 68 // the lock held, thus guaranteeing that [`Driver::resume`] has exclusive access to the instance. 69 // [`Driver::resume`] and [`Driver::suspend`] also are called where only one thread can access 70 // to the instance. 71 #[repr(transparent)] 72 pub struct Device(Opaque<bindings::phy_device>); 73 74 impl Device { 75 /// Creates a new [`Device`] instance from a raw pointer. 76 /// 77 /// # Safety 78 /// 79 /// For the duration of 'a, the pointer must point at a valid `phy_device`, 80 /// and the caller must be in a context where all methods defined on this struct 81 /// are safe to call. 82 unsafe fn from_raw<'a>(ptr: *mut bindings::phy_device) -> &'a mut Self { 83 // CAST: `Self` is a `repr(transparent)` wrapper around `bindings::phy_device`. 84 let ptr = ptr.cast::<Self>(); 85 // SAFETY: by the function requirements the pointer is valid and we have unique access for 86 // the duration of `'a`. 87 unsafe { &mut *ptr } 88 } 89 90 /// Gets the id of the PHY. 91 pub fn phy_id(&self) -> u32 { 92 let phydev = self.0.get(); 93 // SAFETY: The struct invariant ensures that we may access 94 // this field without additional synchronization. 95 unsafe { (*phydev).phy_id } 96 } 97 98 /// Gets the state of PHY state machine states. 99 pub fn state(&self) -> DeviceState { 100 let phydev = self.0.get(); 101 // SAFETY: The struct invariant ensures that we may access 102 // this field without additional synchronization. 103 let state = unsafe { (*phydev).state }; 104 // TODO: this conversion code will be replaced with automatically generated code by bindgen 105 // when it becomes possible. 106 match state { 107 bindings::phy_state_PHY_DOWN => DeviceState::Down, 108 bindings::phy_state_PHY_READY => DeviceState::Ready, 109 bindings::phy_state_PHY_HALTED => DeviceState::Halted, 110 bindings::phy_state_PHY_ERROR => DeviceState::Error, 111 bindings::phy_state_PHY_UP => DeviceState::Up, 112 bindings::phy_state_PHY_RUNNING => DeviceState::Running, 113 bindings::phy_state_PHY_NOLINK => DeviceState::NoLink, 114 bindings::phy_state_PHY_CABLETEST => DeviceState::CableTest, 115 _ => DeviceState::Error, 116 } 117 } 118 119 /// Gets the current link state. 120 /// 121 /// It returns true if the link is up. 122 pub fn is_link_up(&self) -> bool { 123 const LINK_IS_UP: u64 = 1; 124 // TODO: the code to access to the bit field will be replaced with automatically 125 // generated code by bindgen when it becomes possible. 126 // SAFETY: The struct invariant ensures that we may access 127 // this field without additional synchronization. 128 let bit_field = unsafe { &(*self.0.get())._bitfield_1 }; 129 bit_field.get(14, 1) == LINK_IS_UP 130 } 131 132 /// Gets the current auto-negotiation configuration. 133 /// 134 /// It returns true if auto-negotiation is enabled. 135 pub fn is_autoneg_enabled(&self) -> bool { 136 // TODO: the code to access to the bit field will be replaced with automatically 137 // generated code by bindgen when it becomes possible. 138 // SAFETY: The struct invariant ensures that we may access 139 // this field without additional synchronization. 140 let bit_field = unsafe { &(*self.0.get())._bitfield_1 }; 141 bit_field.get(13, 1) == bindings::AUTONEG_ENABLE as u64 142 } 143 144 /// Gets the current auto-negotiation state. 145 /// 146 /// It returns true if auto-negotiation is completed. 147 pub fn is_autoneg_completed(&self) -> bool { 148 const AUTONEG_COMPLETED: u64 = 1; 149 // TODO: the code to access to the bit field will be replaced with automatically 150 // generated code by bindgen when it becomes possible. 151 // SAFETY: The struct invariant ensures that we may access 152 // this field without additional synchronization. 153 let bit_field = unsafe { &(*self.0.get())._bitfield_1 }; 154 bit_field.get(15, 1) == AUTONEG_COMPLETED 155 } 156 157 /// Sets the speed of the PHY. 158 pub fn set_speed(&mut self, speed: u32) { 159 let phydev = self.0.get(); 160 // SAFETY: The struct invariant ensures that we may access 161 // this field without additional synchronization. 162 unsafe { (*phydev).speed = speed as i32 }; 163 } 164 165 /// Sets duplex mode. 166 pub fn set_duplex(&mut self, mode: DuplexMode) { 167 let phydev = self.0.get(); 168 let v = match mode { 169 DuplexMode::Full => bindings::DUPLEX_FULL as i32, 170 DuplexMode::Half => bindings::DUPLEX_HALF as i32, 171 DuplexMode::Unknown => bindings::DUPLEX_UNKNOWN as i32, 172 }; 173 // SAFETY: The struct invariant ensures that we may access 174 // this field without additional synchronization. 175 unsafe { (*phydev).duplex = v }; 176 } 177 178 /// Reads a given C22 PHY register. 179 // This function reads a hardware register and updates the stats so takes `&mut self`. 180 pub fn read(&mut self, regnum: u16) -> Result<u16> { 181 let phydev = self.0.get(); 182 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 183 // So it's just an FFI call, open code of `phy_read()` with a valid `phy_device` pointer 184 // `phydev`. 185 let ret = unsafe { 186 bindings::mdiobus_read((*phydev).mdio.bus, (*phydev).mdio.addr, regnum.into()) 187 }; 188 if ret < 0 { 189 Err(Error::from_errno(ret)) 190 } else { 191 Ok(ret as u16) 192 } 193 } 194 195 /// Writes a given C22 PHY register. 196 pub fn write(&mut self, regnum: u16, val: u16) -> Result { 197 let phydev = self.0.get(); 198 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 199 // So it's just an FFI call, open code of `phy_write()` with a valid `phy_device` pointer 200 // `phydev`. 201 to_result(unsafe { 202 bindings::mdiobus_write((*phydev).mdio.bus, (*phydev).mdio.addr, regnum.into(), val) 203 }) 204 } 205 206 /// Reads a paged register. 207 pub fn read_paged(&mut self, page: u16, regnum: u16) -> Result<u16> { 208 let phydev = self.0.get(); 209 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 210 // So it's just an FFI call. 211 let ret = unsafe { bindings::phy_read_paged(phydev, page.into(), regnum.into()) }; 212 if ret < 0 { 213 Err(Error::from_errno(ret)) 214 } else { 215 Ok(ret as u16) 216 } 217 } 218 219 /// Resolves the advertisements into PHY settings. 220 pub fn resolve_aneg_linkmode(&mut self) { 221 let phydev = self.0.get(); 222 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 223 // So it's just an FFI call. 224 unsafe { bindings::phy_resolve_aneg_linkmode(phydev) }; 225 } 226 227 /// Executes software reset the PHY via `BMCR_RESET` bit. 228 pub fn genphy_soft_reset(&mut self) -> Result { 229 let phydev = self.0.get(); 230 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 231 // So it's just an FFI call. 232 to_result(unsafe { bindings::genphy_soft_reset(phydev) }) 233 } 234 235 /// Initializes the PHY. 236 pub fn init_hw(&mut self) -> Result { 237 let phydev = self.0.get(); 238 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 239 // So it's just an FFI call. 240 to_result(unsafe { bindings::phy_init_hw(phydev) }) 241 } 242 243 /// Starts auto-negotiation. 244 pub fn start_aneg(&mut self) -> Result { 245 let phydev = self.0.get(); 246 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 247 // So it's just an FFI call. 248 to_result(unsafe { bindings::_phy_start_aneg(phydev) }) 249 } 250 251 /// Resumes the PHY via `BMCR_PDOWN` bit. 252 pub fn genphy_resume(&mut self) -> Result { 253 let phydev = self.0.get(); 254 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 255 // So it's just an FFI call. 256 to_result(unsafe { bindings::genphy_resume(phydev) }) 257 } 258 259 /// Suspends the PHY via `BMCR_PDOWN` bit. 260 pub fn genphy_suspend(&mut self) -> Result { 261 let phydev = self.0.get(); 262 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 263 // So it's just an FFI call. 264 to_result(unsafe { bindings::genphy_suspend(phydev) }) 265 } 266 267 /// Checks the link status and updates current link state. 268 pub fn genphy_read_status(&mut self) -> Result<u16> { 269 let phydev = self.0.get(); 270 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 271 // So it's just an FFI call. 272 let ret = unsafe { bindings::genphy_read_status(phydev) }; 273 if ret < 0 { 274 Err(Error::from_errno(ret)) 275 } else { 276 Ok(ret as u16) 277 } 278 } 279 280 /// Updates the link status. 281 pub fn genphy_update_link(&mut self) -> Result { 282 let phydev = self.0.get(); 283 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 284 // So it's just an FFI call. 285 to_result(unsafe { bindings::genphy_update_link(phydev) }) 286 } 287 288 /// Reads link partner ability. 289 pub fn genphy_read_lpa(&mut self) -> Result { 290 let phydev = self.0.get(); 291 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 292 // So it's just an FFI call. 293 to_result(unsafe { bindings::genphy_read_lpa(phydev) }) 294 } 295 296 /// Reads PHY abilities. 297 pub fn genphy_read_abilities(&mut self) -> Result { 298 let phydev = self.0.get(); 299 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 300 // So it's just an FFI call. 301 to_result(unsafe { bindings::genphy_read_abilities(phydev) }) 302 } 303 } 304 305 /// Defines certain other features this PHY supports (like interrupts). 306 /// 307 /// These flag values are used in [`Driver::FLAGS`]. 308 pub mod flags { 309 /// PHY is internal. 310 pub const IS_INTERNAL: u32 = bindings::PHY_IS_INTERNAL; 311 /// PHY needs to be reset after the refclk is enabled. 312 pub const RST_AFTER_CLK_EN: u32 = bindings::PHY_RST_AFTER_CLK_EN; 313 /// Polling is used to detect PHY status changes. 314 pub const POLL_CABLE_TEST: u32 = bindings::PHY_POLL_CABLE_TEST; 315 /// Don't suspend. 316 pub const ALWAYS_CALL_SUSPEND: u32 = bindings::PHY_ALWAYS_CALL_SUSPEND; 317 } 318 319 /// An adapter for the registration of a PHY driver. 320 struct Adapter<T: Driver> { 321 _p: PhantomData<T>, 322 } 323 324 impl<T: Driver> Adapter<T> { 325 /// # Safety 326 /// 327 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 328 unsafe extern "C" fn soft_reset_callback( 329 phydev: *mut bindings::phy_device, 330 ) -> core::ffi::c_int { 331 from_result(|| { 332 // SAFETY: This callback is called only in contexts 333 // where we hold `phy_device->lock`, so the accessors on 334 // `Device` are okay to call. 335 let dev = unsafe { Device::from_raw(phydev) }; 336 T::soft_reset(dev)?; 337 Ok(0) 338 }) 339 } 340 341 /// # Safety 342 /// 343 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 344 unsafe extern "C" fn get_features_callback( 345 phydev: *mut bindings::phy_device, 346 ) -> core::ffi::c_int { 347 from_result(|| { 348 // SAFETY: This callback is called only in contexts 349 // where we hold `phy_device->lock`, so the accessors on 350 // `Device` are okay to call. 351 let dev = unsafe { Device::from_raw(phydev) }; 352 T::get_features(dev)?; 353 Ok(0) 354 }) 355 } 356 357 /// # Safety 358 /// 359 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 360 unsafe extern "C" fn suspend_callback(phydev: *mut bindings::phy_device) -> core::ffi::c_int { 361 from_result(|| { 362 // SAFETY: The C core code ensures that the accessors on 363 // `Device` are okay to call even though `phy_device->lock` 364 // might not be held. 365 let dev = unsafe { Device::from_raw(phydev) }; 366 T::suspend(dev)?; 367 Ok(0) 368 }) 369 } 370 371 /// # Safety 372 /// 373 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 374 unsafe extern "C" fn resume_callback(phydev: *mut bindings::phy_device) -> core::ffi::c_int { 375 from_result(|| { 376 // SAFETY: The C core code ensures that the accessors on 377 // `Device` are okay to call even though `phy_device->lock` 378 // might not be held. 379 let dev = unsafe { Device::from_raw(phydev) }; 380 T::resume(dev)?; 381 Ok(0) 382 }) 383 } 384 385 /// # Safety 386 /// 387 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 388 unsafe extern "C" fn config_aneg_callback( 389 phydev: *mut bindings::phy_device, 390 ) -> core::ffi::c_int { 391 from_result(|| { 392 // SAFETY: This callback is called only in contexts 393 // where we hold `phy_device->lock`, so the accessors on 394 // `Device` are okay to call. 395 let dev = unsafe { Device::from_raw(phydev) }; 396 T::config_aneg(dev)?; 397 Ok(0) 398 }) 399 } 400 401 /// # Safety 402 /// 403 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 404 unsafe extern "C" fn read_status_callback( 405 phydev: *mut bindings::phy_device, 406 ) -> core::ffi::c_int { 407 from_result(|| { 408 // SAFETY: This callback is called only in contexts 409 // where we hold `phy_device->lock`, so the accessors on 410 // `Device` are okay to call. 411 let dev = unsafe { Device::from_raw(phydev) }; 412 T::read_status(dev)?; 413 Ok(0) 414 }) 415 } 416 417 /// # Safety 418 /// 419 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 420 unsafe extern "C" fn match_phy_device_callback( 421 phydev: *mut bindings::phy_device, 422 ) -> core::ffi::c_int { 423 // SAFETY: This callback is called only in contexts 424 // where we hold `phy_device->lock`, so the accessors on 425 // `Device` are okay to call. 426 let dev = unsafe { Device::from_raw(phydev) }; 427 T::match_phy_device(dev) as i32 428 } 429 430 /// # Safety 431 /// 432 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 433 unsafe extern "C" fn read_mmd_callback( 434 phydev: *mut bindings::phy_device, 435 devnum: i32, 436 regnum: u16, 437 ) -> i32 { 438 from_result(|| { 439 // SAFETY: This callback is called only in contexts 440 // where we hold `phy_device->lock`, so the accessors on 441 // `Device` are okay to call. 442 let dev = unsafe { Device::from_raw(phydev) }; 443 // CAST: the C side verifies devnum < 32. 444 let ret = T::read_mmd(dev, devnum as u8, regnum)?; 445 Ok(ret.into()) 446 }) 447 } 448 449 /// # Safety 450 /// 451 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 452 unsafe extern "C" fn write_mmd_callback( 453 phydev: *mut bindings::phy_device, 454 devnum: i32, 455 regnum: u16, 456 val: u16, 457 ) -> i32 { 458 from_result(|| { 459 // SAFETY: This callback is called only in contexts 460 // where we hold `phy_device->lock`, so the accessors on 461 // `Device` are okay to call. 462 let dev = unsafe { Device::from_raw(phydev) }; 463 T::write_mmd(dev, devnum as u8, regnum, val)?; 464 Ok(0) 465 }) 466 } 467 468 /// # Safety 469 /// 470 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 471 unsafe extern "C" fn link_change_notify_callback(phydev: *mut bindings::phy_device) { 472 // SAFETY: This callback is called only in contexts 473 // where we hold `phy_device->lock`, so the accessors on 474 // `Device` are okay to call. 475 let dev = unsafe { Device::from_raw(phydev) }; 476 T::link_change_notify(dev); 477 } 478 } 479 480 /// Driver structure for a particular PHY type. 481 /// 482 /// Wraps the kernel's [`struct phy_driver`]. 483 /// This is used to register a driver for a particular PHY type with the kernel. 484 /// 485 /// # Invariants 486 /// 487 /// `self.0` is always in a valid state. 488 /// 489 /// [`struct phy_driver`]: srctree/include/linux/phy.h 490 #[repr(transparent)] 491 pub struct DriverVTable(Opaque<bindings::phy_driver>); 492 493 // SAFETY: `DriverVTable` doesn't expose any &self method to access internal data, so it's safe to 494 // share `&DriverVTable` across execution context boundries. 495 unsafe impl Sync for DriverVTable {} 496 497 /// Creates a [`DriverVTable`] instance from [`Driver`]. 498 /// 499 /// This is used by [`module_phy_driver`] macro to create a static array of `phy_driver`. 500 /// 501 /// [`module_phy_driver`]: crate::module_phy_driver 502 pub const fn create_phy_driver<T: Driver>() -> DriverVTable { 503 // INVARIANT: All the fields of `struct phy_driver` are initialized properly. 504 DriverVTable(Opaque::new(bindings::phy_driver { 505 name: T::NAME.as_char_ptr().cast_mut(), 506 flags: T::FLAGS, 507 phy_id: T::PHY_DEVICE_ID.id, 508 phy_id_mask: T::PHY_DEVICE_ID.mask_as_int(), 509 soft_reset: if T::HAS_SOFT_RESET { 510 Some(Adapter::<T>::soft_reset_callback) 511 } else { 512 None 513 }, 514 get_features: if T::HAS_GET_FEATURES { 515 Some(Adapter::<T>::get_features_callback) 516 } else { 517 None 518 }, 519 match_phy_device: if T::HAS_MATCH_PHY_DEVICE { 520 Some(Adapter::<T>::match_phy_device_callback) 521 } else { 522 None 523 }, 524 suspend: if T::HAS_SUSPEND { 525 Some(Adapter::<T>::suspend_callback) 526 } else { 527 None 528 }, 529 resume: if T::HAS_RESUME { 530 Some(Adapter::<T>::resume_callback) 531 } else { 532 None 533 }, 534 config_aneg: if T::HAS_CONFIG_ANEG { 535 Some(Adapter::<T>::config_aneg_callback) 536 } else { 537 None 538 }, 539 read_status: if T::HAS_READ_STATUS { 540 Some(Adapter::<T>::read_status_callback) 541 } else { 542 None 543 }, 544 read_mmd: if T::HAS_READ_MMD { 545 Some(Adapter::<T>::read_mmd_callback) 546 } else { 547 None 548 }, 549 write_mmd: if T::HAS_WRITE_MMD { 550 Some(Adapter::<T>::write_mmd_callback) 551 } else { 552 None 553 }, 554 link_change_notify: if T::HAS_LINK_CHANGE_NOTIFY { 555 Some(Adapter::<T>::link_change_notify_callback) 556 } else { 557 None 558 }, 559 // SAFETY: The rest is zeroed out to initialize `struct phy_driver`, 560 // sets `Option<&F>` to be `None`. 561 ..unsafe { core::mem::MaybeUninit::<bindings::phy_driver>::zeroed().assume_init() } 562 })) 563 } 564 565 /// Driver implementation for a particular PHY type. 566 /// 567 /// This trait is used to create a [`DriverVTable`]. 568 #[vtable] 569 pub trait Driver { 570 /// Defines certain other features this PHY supports. 571 /// It is a combination of the flags in the [`flags`] module. 572 const FLAGS: u32 = 0; 573 574 /// The friendly name of this PHY type. 575 const NAME: &'static CStr; 576 577 /// This driver only works for PHYs with IDs which match this field. 578 /// The default id and mask are zero. 579 const PHY_DEVICE_ID: DeviceId = DeviceId::new_with_custom_mask(0, 0); 580 581 /// Issues a PHY software reset. 582 fn soft_reset(_dev: &mut Device) -> Result { 583 kernel::build_error(VTABLE_DEFAULT_ERROR) 584 } 585 586 /// Probes the hardware to determine what abilities it has. 587 fn get_features(_dev: &mut Device) -> Result { 588 kernel::build_error(VTABLE_DEFAULT_ERROR) 589 } 590 591 /// Returns true if this is a suitable driver for the given phydev. 592 /// If not implemented, matching is based on [`Driver::PHY_DEVICE_ID`]. 593 fn match_phy_device(_dev: &Device) -> bool { 594 false 595 } 596 597 /// Configures the advertisement and resets auto-negotiation 598 /// if auto-negotiation is enabled. 599 fn config_aneg(_dev: &mut Device) -> Result { 600 kernel::build_error(VTABLE_DEFAULT_ERROR) 601 } 602 603 /// Determines the negotiated speed and duplex. 604 fn read_status(_dev: &mut Device) -> Result<u16> { 605 kernel::build_error(VTABLE_DEFAULT_ERROR) 606 } 607 608 /// Suspends the hardware, saving state if needed. 609 fn suspend(_dev: &mut Device) -> Result { 610 kernel::build_error(VTABLE_DEFAULT_ERROR) 611 } 612 613 /// Resumes the hardware, restoring state if needed. 614 fn resume(_dev: &mut Device) -> Result { 615 kernel::build_error(VTABLE_DEFAULT_ERROR) 616 } 617 618 /// Overrides the default MMD read function for reading a MMD register. 619 fn read_mmd(_dev: &mut Device, _devnum: u8, _regnum: u16) -> Result<u16> { 620 kernel::build_error(VTABLE_DEFAULT_ERROR) 621 } 622 623 /// Overrides the default MMD write function for writing a MMD register. 624 fn write_mmd(_dev: &mut Device, _devnum: u8, _regnum: u16, _val: u16) -> Result { 625 kernel::build_error(VTABLE_DEFAULT_ERROR) 626 } 627 628 /// Callback for notification of link change. 629 fn link_change_notify(_dev: &mut Device) {} 630 } 631 632 /// Registration structure for PHY drivers. 633 /// 634 /// Registers [`DriverVTable`] instances with the kernel. They will be unregistered when dropped. 635 /// 636 /// # Invariants 637 /// 638 /// The `drivers` slice are currently registered to the kernel via `phy_drivers_register`. 639 pub struct Registration { 640 drivers: Pin<&'static mut [DriverVTable]>, 641 } 642 643 impl Registration { 644 /// Registers a PHY driver. 645 pub fn register( 646 module: &'static crate::ThisModule, 647 drivers: Pin<&'static mut [DriverVTable]>, 648 ) -> Result<Self> { 649 if drivers.is_empty() { 650 return Err(code::EINVAL); 651 } 652 // SAFETY: The type invariants of [`DriverVTable`] ensure that all elements of 653 // the `drivers` slice are initialized properly. `drivers` will not be moved. 654 // So it's just an FFI call. 655 to_result(unsafe { 656 bindings::phy_drivers_register(drivers[0].0.get(), drivers.len().try_into()?, module.0) 657 })?; 658 // INVARIANT: The `drivers` slice is successfully registered to the kernel via `phy_drivers_register`. 659 Ok(Registration { drivers }) 660 } 661 } 662 663 impl Drop for Registration { 664 fn drop(&mut self) { 665 // SAFETY: The type invariants guarantee that `self.drivers` is valid. 666 // So it's just an FFI call. 667 unsafe { 668 bindings::phy_drivers_unregister(self.drivers[0].0.get(), self.drivers.len() as i32) 669 }; 670 } 671 } 672 673 /// An identifier for PHY devices on an MDIO/MII bus. 674 /// 675 /// Represents the kernel's `struct mdio_device_id`. This is used to find an appropriate 676 /// PHY driver. 677 pub struct DeviceId { 678 id: u32, 679 mask: DeviceMask, 680 } 681 682 impl DeviceId { 683 /// Creates a new instance with the exact match mask. 684 pub const fn new_with_exact_mask(id: u32) -> Self { 685 DeviceId { 686 id, 687 mask: DeviceMask::Exact, 688 } 689 } 690 691 /// Creates a new instance with the model match mask. 692 pub const fn new_with_model_mask(id: u32) -> Self { 693 DeviceId { 694 id, 695 mask: DeviceMask::Model, 696 } 697 } 698 699 /// Creates a new instance with the vendor match mask. 700 pub const fn new_with_vendor_mask(id: u32) -> Self { 701 DeviceId { 702 id, 703 mask: DeviceMask::Vendor, 704 } 705 } 706 707 /// Creates a new instance with a custom match mask. 708 pub const fn new_with_custom_mask(id: u32, mask: u32) -> Self { 709 DeviceId { 710 id, 711 mask: DeviceMask::Custom(mask), 712 } 713 } 714 715 /// Creates a new instance from [`Driver`]. 716 pub const fn new_with_driver<T: Driver>() -> Self { 717 T::PHY_DEVICE_ID 718 } 719 720 /// Get a `mask` as u32. 721 pub const fn mask_as_int(&self) -> u32 { 722 self.mask.as_int() 723 } 724 725 // macro use only 726 #[doc(hidden)] 727 pub const fn mdio_device_id(&self) -> bindings::mdio_device_id { 728 bindings::mdio_device_id { 729 phy_id: self.id, 730 phy_id_mask: self.mask.as_int(), 731 } 732 } 733 } 734 735 enum DeviceMask { 736 Exact, 737 Model, 738 Vendor, 739 Custom(u32), 740 } 741 742 impl DeviceMask { 743 const MASK_EXACT: u32 = !0; 744 const MASK_MODEL: u32 = !0 << 4; 745 const MASK_VENDOR: u32 = !0 << 10; 746 747 const fn as_int(&self) -> u32 { 748 match self { 749 DeviceMask::Exact => Self::MASK_EXACT, 750 DeviceMask::Model => Self::MASK_MODEL, 751 DeviceMask::Vendor => Self::MASK_VENDOR, 752 DeviceMask::Custom(mask) => *mask, 753 } 754 } 755 } 756 757 /// Declares a kernel module for PHYs drivers. 758 /// 759 /// This creates a static array of kernel's `struct phy_driver` and registers it. 760 /// This also corresponds to the kernel's `MODULE_DEVICE_TABLE` macro, which embeds the information 761 /// for module loading into the module binary file. Every driver needs an entry in `device_table`. 762 /// 763 /// # Examples 764 /// 765 /// ``` 766 /// # mod module_phy_driver_sample { 767 /// use kernel::c_str; 768 /// use kernel::net::phy::{self, DeviceId}; 769 /// use kernel::prelude::*; 770 /// 771 /// kernel::module_phy_driver! { 772 /// drivers: [PhySample], 773 /// device_table: [ 774 /// DeviceId::new_with_driver::<PhySample>() 775 /// ], 776 /// name: "rust_sample_phy", 777 /// author: "Rust for Linux Contributors", 778 /// description: "Rust sample PHYs driver", 779 /// license: "GPL", 780 /// } 781 /// 782 /// struct PhySample; 783 /// 784 /// #[vtable] 785 /// impl phy::Driver for PhySample { 786 /// const NAME: &'static CStr = c_str!("PhySample"); 787 /// const PHY_DEVICE_ID: phy::DeviceId = phy::DeviceId::new_with_exact_mask(0x00000001); 788 /// } 789 /// # } 790 /// ``` 791 /// 792 /// This expands to the following code: 793 /// 794 /// ```ignore 795 /// use kernel::c_str; 796 /// use kernel::net::phy::{self, DeviceId}; 797 /// use kernel::prelude::*; 798 /// 799 /// struct Module { 800 /// _reg: ::kernel::net::phy::Registration, 801 /// } 802 /// 803 /// module! { 804 /// type: Module, 805 /// name: "rust_sample_phy", 806 /// author: "Rust for Linux Contributors", 807 /// description: "Rust sample PHYs driver", 808 /// license: "GPL", 809 /// } 810 /// 811 /// struct PhySample; 812 /// 813 /// #[vtable] 814 /// impl phy::Driver for PhySample { 815 /// const NAME: &'static CStr = c_str!("PhySample"); 816 /// const PHY_DEVICE_ID: phy::DeviceId = phy::DeviceId::new_with_exact_mask(0x00000001); 817 /// } 818 /// 819 /// const _: () = { 820 /// static mut DRIVERS: [::kernel::net::phy::DriverVTable; 1] = 821 /// [::kernel::net::phy::create_phy_driver::<PhySample>()]; 822 /// 823 /// impl ::kernel::Module for Module { 824 /// fn init(module: &'static ThisModule) -> Result<Self> { 825 /// let drivers = unsafe { &mut DRIVERS }; 826 /// let mut reg = ::kernel::net::phy::Registration::register( 827 /// module, 828 /// ::core::pin::Pin::static_mut(drivers), 829 /// )?; 830 /// Ok(Module { _reg: reg }) 831 /// } 832 /// } 833 /// }; 834 /// 835 /// #[cfg(MODULE)] 836 /// #[no_mangle] 837 /// static __mod_mdio__phydev_device_table: [::kernel::bindings::mdio_device_id; 2] = [ 838 /// ::kernel::bindings::mdio_device_id { 839 /// phy_id: 0x00000001, 840 /// phy_id_mask: 0xffffffff, 841 /// }, 842 /// ::kernel::bindings::mdio_device_id { 843 /// phy_id: 0, 844 /// phy_id_mask: 0, 845 /// }, 846 /// ]; 847 /// ``` 848 #[macro_export] 849 macro_rules! module_phy_driver { 850 (@replace_expr $_t:tt $sub:expr) => {$sub}; 851 852 (@count_devices $($x:expr),*) => { 853 0usize $(+ $crate::module_phy_driver!(@replace_expr $x 1usize))* 854 }; 855 856 (@device_table [$($dev:expr),+]) => { 857 // SAFETY: C will not read off the end of this constant since the last element is zero. 858 #[cfg(MODULE)] 859 #[no_mangle] 860 static __mod_mdio__phydev_device_table: [$crate::bindings::mdio_device_id; 861 $crate::module_phy_driver!(@count_devices $($dev),+) + 1] = [ 862 $($dev.mdio_device_id()),+, 863 $crate::bindings::mdio_device_id { 864 phy_id: 0, 865 phy_id_mask: 0 866 } 867 ]; 868 }; 869 870 (drivers: [$($driver:ident),+ $(,)?], device_table: [$($dev:expr),+ $(,)?], $($f:tt)*) => { 871 struct Module { 872 _reg: $crate::net::phy::Registration, 873 } 874 875 $crate::prelude::module! { 876 type: Module, 877 $($f)* 878 } 879 880 const _: () = { 881 static mut DRIVERS: [$crate::net::phy::DriverVTable; 882 $crate::module_phy_driver!(@count_devices $($driver),+)] = 883 [$($crate::net::phy::create_phy_driver::<$driver>()),+]; 884 885 impl $crate::Module for Module { 886 fn init(module: &'static ThisModule) -> Result<Self> { 887 // SAFETY: The anonymous constant guarantees that nobody else can access 888 // the `DRIVERS` static. The array is used only in the C side. 889 let drivers = unsafe { &mut DRIVERS }; 890 let mut reg = $crate::net::phy::Registration::register( 891 module, 892 ::core::pin::Pin::static_mut(drivers), 893 )?; 894 Ok(Module { _reg: reg }) 895 } 896 } 897 }; 898 899 $crate::module_phy_driver!(@device_table [$($dev),+]); 900 } 901 } 902