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