1 /* $NetBSD: usbnet.h,v 1.22 2021/12/11 19:24:21 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 2019 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #ifndef _DEV_USB_USBNET_H 30 #define _DEV_USB_USBNET_H 31 32 /* 33 * Common code/data shared by all USB ethernet drivers (using these routines.) 34 * 35 * This framework provides the following features for USB ethernet drivers: 36 * 37 * - USB endpoint pipe handling 38 * - rx and tx chain handling 39 * - generic handlers or support for several struct ifnet callbacks 40 * - MII bus locking 41 * - interrupt handling 42 * - partial autoconf handling 43 * 44 * Consumers of this interface need to: 45 * 46 * - replace most softc members with "struct usbnet" usage, in particular 47 * use usbnet pointer for ifp->if_softc, and device_private (real softc 48 * can be stored in un_sc member) 49 * - use MII bus lock / access methods 50 * - usbnet_attach() to initialise and allocate rx/tx chains 51 * - usbnet_attach_ifp() to attach the interface, and either ether_ifattach() 52 * for ethernet devices, or if_alloc_sadl()/bpf_attach() pair otherwise. 53 * - usbnet_detach() to clean them up 54 * - usbnet_activate() for autoconf 55 * - interface ioctl and start have direct frontends with callbacks for 56 * device specific handling: 57 * - ioctl can use either a device-specific override (useful for special 58 * cases), but provides a normal handler with callback to handle 59 * ENETRESET conditions that should be sufficient for most users 60 * - start uses usbnet transmit prepare callback (uno_tx_prepare) 61 * - interface init and stop have helper functions 62 * - device specific init should use usbnet_init_rx_tx() to open pipes 63 * to the device and setup the rx/tx chains for use after any device 64 * specific setup 65 * - usbnet_stop() must be called with the un_lock held, and will 66 * call the device-specific usbnet stop callback, which enables the 67 * standard init calls stop idiom. 68 * - interrupt handling: 69 * - for rx, usbnet_init_rx_tx() will enable the receive pipes and 70 * call the rx_loop callback to handle device specific processing of 71 * packets, which can use usbnet_enqueue() to provide data to the 72 * higher layers 73 * - for tx, usbnet_start (if_start) will pull entries out of the 74 * transmit queue and use the transmit prepare callback (uno_tx_prepare) 75 * for the given mbuf. the usb callback will use usbnet_txeof() for 76 * the transmit completion function (internal to usbnet) 77 * - there is special interrupt pipe handling 78 * - timer/tick: 79 * - the uno_tick callback will be called once a second if present. 80 */ 81 82 #include <sys/device.h> 83 #include <sys/mbuf.h> 84 #include <sys/rndsource.h> 85 #include <sys/mutex.h> 86 #include <sys/module.h> 87 88 #include <net/bpf.h> 89 #include <net/if.h> 90 #include <net/if_arp.h> 91 #include <net/if_dl.h> 92 #include <net/if_ether.h> 93 #include <net/if_media.h> 94 95 #include <dev/mii/mii.h> 96 #include <dev/mii/miivar.h> 97 98 #include <dev/usb/usb.h> 99 #include <dev/usb/usbdi.h> 100 #include <dev/usb/usbdivar.h> 101 #include <dev/usb/usbdi_util.h> 102 #include <dev/usb/usbdevs.h> 103 104 /* 105 * Per-transfer data. 106 * 107 * Front-end must set un_rx_list_cnt and un_tx_list_cnt before 108 * calling usbnet_attach(), and then call usbnet_rx_tx_init() 109 * which will allocate the chain arrays, and must be NULL to 110 * indicate the first call. 111 */ 112 struct usbnet; 113 struct usbnet_chain { 114 struct usbnet *unc_un; 115 struct usbd_xfer *unc_xfer; 116 uint8_t *unc_buf; 117 }; 118 119 /* 120 * Extend this as necessary. axe(4) claims to want 6 total, but 121 * does not implement them. 122 */ 123 enum usbnet_ep { 124 USBNET_ENDPT_RX, 125 USBNET_ENDPT_TX, 126 USBNET_ENDPT_INTR, 127 USBNET_ENDPT_MAX, 128 }; 129 130 /* Interface stop callback. */ 131 typedef void (*usbnet_stop_cb)(struct ifnet *, int); 132 /* Interface ioctl callback. */ 133 typedef int (*usbnet_ioctl_cb)(struct ifnet *, u_long, void *); 134 /* Initialise device callback. */ 135 typedef int (*usbnet_init_cb)(struct ifnet *); 136 137 /* MII read register callback. */ 138 typedef int (*usbnet_mii_read_reg_cb)(struct usbnet *, int reg, 139 int phy, uint16_t *val); 140 /* MII write register callback. */ 141 typedef int (*usbnet_mii_write_reg_cb)(struct usbnet *, int reg, 142 int phy, uint16_t val); 143 /* MII status change callback. */ 144 typedef void (*usbnet_mii_statchg_cb)(struct ifnet *); 145 146 /* Prepare packet to send callback, returns length. */ 147 typedef unsigned (*usbnet_tx_prepare_cb)(struct usbnet *, struct mbuf *, 148 struct usbnet_chain *); 149 /* Receive some packets callback. */ 150 typedef void (*usbnet_rx_loop_cb)(struct usbnet *, struct usbnet_chain *, 151 uint32_t); 152 /* Tick callback. */ 153 typedef void (*usbnet_tick_cb)(struct usbnet *); 154 /* Interrupt pipe callback. */ 155 typedef void (*usbnet_intr_cb)(struct usbnet *, usbd_status); 156 157 /* 158 * LOCKING 159 * ======= 160 * 161 * The following annotations indicate which locks are held when 162 * usbnet_ops functions are invoked: 163 * 164 * I -> IFNET_LOCK (if_ioctl_lock) 165 * C -> CORE_LOCK (usbnet core_lock) 166 * T -> TX_LOCK (usbnet tx_lock) 167 * R -> RX_LOCK (usbnet rx_lock) 168 * n -> no locks held 169 * 170 * Note that when CORE_LOCK is held, IFNET_LOCK may or may not also 171 * be held. 172 * 173 * Note that the IFNET_LOCK **may not be held** for some ioctl 174 * operations (add/delete multicast addresses, for example). 175 * 176 * Busy reference counts are maintained across calls to: uno_stop, 177 * uno_read_reg, uno_write_reg, uno_statchg, and uno_tick. 178 */ 179 struct usbnet_ops { 180 usbnet_stop_cb uno_stop; /* C */ 181 usbnet_ioctl_cb uno_ioctl; /* I (maybe) */ 182 usbnet_ioctl_cb uno_override_ioctl; /* I (maybe) */ 183 usbnet_init_cb uno_init; /* I */ 184 usbnet_mii_read_reg_cb uno_read_reg; /* C */ 185 usbnet_mii_write_reg_cb uno_write_reg; /* C */ 186 usbnet_mii_statchg_cb uno_statchg; /* C */ 187 usbnet_tx_prepare_cb uno_tx_prepare; /* T */ 188 usbnet_rx_loop_cb uno_rx_loop; /* R */ 189 usbnet_tick_cb uno_tick; /* n */ 190 usbnet_intr_cb uno_intr; /* n */ 191 }; 192 193 /* 194 * USB interrupt pipe support. Use this if usbd_open_pipe_intr() should 195 * be used for the interrupt pipe. 196 */ 197 struct usbnet_intr { 198 /* 199 * Point un_intr to this structure to use usbd_open_pipe_intr() not 200 * usbd_open_pipe() for USBNET_ENDPT_INTR, with this buffer, size, 201 * and interval. 202 */ 203 void *uni_buf; 204 unsigned uni_bufsz; 205 unsigned uni_interval; 206 }; 207 208 /* 209 * Structure to setup MII. Use the USBNET_MII_DECL_DEFAULT() macro for 210 * sane default. Pass a copy to usbnet_attach_ifp(). Not used 211 * after the usbnet_attach_ifp() function returns. 212 */ 213 struct usbnet_mii { 214 int un_mii_flags; 215 int un_mii_capmask; 216 int un_mii_phyloc; 217 int un_mii_offset; 218 }; 219 220 #define USBNET_MII_DECL(name, capmask, loc, off, flags) \ 221 struct usbnet_mii name = { \ 222 .un_mii_capmask = capmask, \ 223 .un_mii_phyloc = loc, \ 224 .un_mii_offset = off, \ 225 .un_mii_flags = flags, \ 226 } 227 #define USBNET_MII_DECL_DEFAULT(name) \ 228 USBNET_MII_DECL(name, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0) 229 230 /* 231 * Generic USB ethernet structure. Use this as ifp->if_softc and set as 232 * device_private() in attach unless already using struct usbnet here. 233 * 234 * Devices without MII should call usbnet_attach_ifp() with have_mii set 235 * to true, and should ensure that the un_statchg_cb callback sets the 236 * un_link member. Devices without MII have this forced to true. 237 */ 238 struct usbnet_private; 239 struct usbnet { 240 /* 241 * This section should be filled in before calling 242 * usbnet_attach(). 243 */ 244 void *un_sc; /* real softc */ 245 device_t un_dev; 246 struct usbd_interface *un_iface; 247 struct usbd_device *un_udev; 248 const struct usbnet_ops *un_ops; 249 struct usbnet_intr *un_intr; 250 251 /* Inputs for rx/tx chain control. */ 252 unsigned un_rx_bufsz; 253 unsigned un_tx_bufsz; 254 unsigned un_rx_list_cnt; 255 unsigned un_tx_list_cnt; 256 int un_rx_xfer_flags; 257 int un_tx_xfer_flags; 258 259 /* 260 * This section should be filled in before calling 261 * usbnet_attach_ifp(). 262 * 263 * XXX This should be of type "uByte". enum usbnet_ep 264 * is the index. Fix this in a kernel version bump. 265 */ 266 enum usbnet_ep un_ed[USBNET_ENDPT_MAX]; 267 268 /* MII specific. Not used without MII. */ 269 int un_phyno; 270 /* Ethernet specific. All zeroes indicates non-Ethernet. */ 271 uint8_t un_eaddr[ETHER_ADDR_LEN]; 272 273 /* 274 * This section is for driver to use, not touched by usbnet. 275 */ 276 unsigned un_flags; 277 278 /* 279 * This section is private to usbnet. Don't touch. 280 */ 281 struct usbnet_private *un_pri; 282 }; 283 284 /* Various accessors. */ 285 286 void usbnet_set_link(struct usbnet *, bool); 287 void usbnet_set_dying(struct usbnet *, bool); 288 289 struct ifnet *usbnet_ifp(struct usbnet *); 290 struct ethercom *usbnet_ec(struct usbnet *); 291 struct mii_data *usbnet_mii(struct usbnet *); 292 krndsource_t *usbnet_rndsrc(struct usbnet *); 293 void *usbnet_softc(struct usbnet *); 294 295 bool usbnet_havelink(struct usbnet *); 296 bool usbnet_isdying(struct usbnet *); 297 298 299 /* 300 * Locking. Note that the isowned() are implemented here so that 301 * empty-KASSERT() causes them to be elided for non-DIAG builds. 302 */ 303 void usbnet_lock_core(struct usbnet *); 304 void usbnet_unlock_core(struct usbnet *); 305 kmutex_t *usbnet_mutex_core(struct usbnet *); 306 static __inline__ void 307 usbnet_isowned_core(struct usbnet *un) 308 { 309 KASSERT(mutex_owned(usbnet_mutex_core(un))); 310 } 311 312 void usbnet_busy(struct usbnet *); 313 void usbnet_unbusy(struct usbnet *); 314 315 void usbnet_lock_rx(struct usbnet *); 316 void usbnet_unlock_rx(struct usbnet *); 317 kmutex_t *usbnet_mutex_rx(struct usbnet *); 318 static __inline__ void 319 usbnet_isowned_rx(struct usbnet *un) 320 { 321 KASSERT(mutex_owned(usbnet_mutex_rx(un))); 322 } 323 324 void usbnet_lock_tx(struct usbnet *); 325 void usbnet_unlock_tx(struct usbnet *); 326 kmutex_t *usbnet_mutex_tx(struct usbnet *); 327 static __inline__ void 328 usbnet_isowned_tx(struct usbnet *un) 329 { 330 KASSERT(mutex_owned(usbnet_mutex_tx(un))); 331 } 332 333 /* 334 * Endpoint / rx/tx chain management: 335 * 336 * usbnet_attach() initialises usbnet and allocates rx and tx chains 337 * usbnet_init_rx_tx() open pipes, initialises the rx/tx chains for use 338 * usbnet_stop() stops pipes, cleans (not frees) rx/tx chains, locked 339 * version assumes un_lock is held 340 * usbnet_detach() frees the rx/tx chains 341 * 342 * Setup un_ed[] with valid end points before calling usbnet_attach(). 343 * Call usbnet_init_rx_tx() to initialise pipes, which will be open 344 * upon success. 345 */ 346 int usbnet_init_rx_tx(struct usbnet * const); 347 348 /* MII. */ 349 int usbnet_mii_readreg(device_t, int, int, uint16_t *); 350 int usbnet_mii_writereg(device_t, int, int, uint16_t); 351 void usbnet_mii_statchg(struct ifnet *); 352 353 /* interrupt handling */ 354 void usbnet_enqueue(struct usbnet * const, uint8_t *, size_t, int, 355 uint32_t, int); 356 void usbnet_input(struct usbnet * const, uint8_t *, size_t); 357 358 /* autoconf */ 359 void usbnet_attach(struct usbnet *un, const char *); 360 void usbnet_attach_ifp(struct usbnet *, unsigned, unsigned, 361 const struct usbnet_mii *); 362 int usbnet_detach(device_t, int); 363 int usbnet_activate(device_t, devact_t); 364 365 /* stop backend */ 366 void usbnet_stop(struct usbnet *, struct ifnet *, int); 367 368 /* module hook up */ 369 370 #ifdef _MODULE 371 #define USBNET_INIT(name) \ 372 error = config_init_component(cfdriver_ioconf_##name, \ 373 cfattach_ioconf_##name, cfdata_ioconf_##name); 374 #define USBNET_FINI(name) \ 375 error = config_fini_component(cfdriver_ioconf_##name, \ 376 cfattach_ioconf_##name, cfdata_ioconf_##name); 377 #else 378 #define USBNET_INIT(name) 379 #define USBNET_FINI(name) 380 #endif 381 382 #define USBNET_MODULE(name) \ 383 \ 384 MODULE(MODULE_CLASS_DRIVER, if_##name, "usbnet"); \ 385 \ 386 static int \ 387 if_##name##_modcmd(modcmd_t cmd, void *aux) \ 388 { \ 389 int error = 0; \ 390 \ 391 switch (cmd) { \ 392 case MODULE_CMD_INIT: \ 393 USBNET_INIT(name) \ 394 return error; \ 395 case MODULE_CMD_FINI: \ 396 USBNET_FINI(name) \ 397 return error; \ 398 default: \ 399 return ENOTTY; \ 400 } \ 401 } 402 403 #endif /* _DEV_USB_USBNET_H */ 404