blob: 1098a8854d435544c01505e301017a28c40d6a7f [file] [log] [blame]
Robert Mustacchi67164312016-04-11 14:20:14 -07001/*
2 * urf_usbgem.c : Realtek RTL8150 USB to Fast Ethernet Driver for Solaris
3 *
4 * Copyright (c) 2003-2012 Masayuki Murayama. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * 3. Neither the name of the author nor the names of its contributors may be
17 * used to endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 * DAMAGE.
32 */
33
34/*
35 * Changelog:
36 */
37
38/*
39 * TODO
40 */
41/* ======================================================= */
42
43/*
44 * Solaris system header files and macros
45 */
46
47/* minimum kernel headers for drivers */
48#include <sys/types.h>
49#include <sys/conf.h>
50#include <sys/debug.h>
51#include <sys/kmem.h>
52#include <sys/modctl.h>
53#include <sys/errno.h>
54#include <sys/ddi.h>
55#include <sys/sunddi.h>
56#include <sys/byteorder.h>
57
58/* ethernet stuff */
59#include <sys/ethernet.h>
60
61/* interface card depend stuff */
62#include <sys/stropts.h>
63#include <sys/stream.h>
64#include <sys/strlog.h>
65#include <sys/usb/usba.h>
66#include "usbgem.h"
67#include "usbgem_mii.h"
68#include "rtl8150reg.h"
69
70char ident[] = "rtl8150 usbnic driver v" VERSION;
71
72/*
73 * Useful macros
74 */
75#define ROUNDUP2(x, y) (((x)+(y)-1) & ~((y)-1))
76#define CHECK_AND_JUMP(err, label) if (err != USB_SUCCESS) goto label
77
78/*
79 * Debugging
80 */
81#ifdef DEBUG_LEVEL
82static int urf_debug = DEBUG_LEVEL;
83#define DPRINTF(n, args) if (urf_debug > (n)) cmn_err args
84#else
85#define DPRINTF(n, args)
86#endif
87
88/*
89 * Our configration for rtl8150
90 */
91/* timeouts */
92#define ONESEC (drv_usectohz(1*1000000))
93
94/*
95 * Local device definitions
96 */
97struct chip_info {
98 int flags;
99 char *name;
100 int type;
101};
102
103#define CHIPTABLESIZE (sizeof (chiptbl_8150) / sizeof (struct chip_info))
104
105struct urf_dev {
106 /*
107 * Misc HW information
108 */
109 struct chip_info *chip;
110 uint8_t cr;
111 uint8_t tsr;
112 uint16_t rcr;
113 uint8_t txok_cnt;
114};
115
116/*
117 * private functions
118 */
119
120/* mii operations */
121static uint16_t urf_mii_read(struct usbgem_dev *, uint_t, int *errp);
122static void urf_mii_write(struct usbgem_dev *, uint_t, uint16_t, int *errp);
123
124/* nic operations */
125static int urf_attach_chip(struct usbgem_dev *);
126static int urf_reset_chip(struct usbgem_dev *);
127static int urf_init_chip(struct usbgem_dev *);
128static int urf_start_chip(struct usbgem_dev *);
129static int urf_stop_chip(struct usbgem_dev *);
130static int urf_set_media(struct usbgem_dev *);
131static int urf_set_rx_filter(struct usbgem_dev *);
132static int urf_get_stats(struct usbgem_dev *);
133
134/* packet operations */
135static mblk_t *urf_tx_make_packet(struct usbgem_dev *, mblk_t *);
136static mblk_t *urf_rx_make_packet(struct usbgem_dev *, mblk_t *);
137
138/* =============================================================== */
139/*
140 * I/O functions
141 */
142/* =============================================================== */
143#define OUTB(dp, p, v, errp, label) \
144 if ((*(errp) = usbgem_ctrl_out_val((dp), \
145 /* bmRequestType */ USB_DEV_REQ_HOST_TO_DEV \
146 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
147 /* bRequest */ USB_REQ_SET_ADDRESS, \
148 /* wValue */ (p), \
149 /* wIndex */ 0, \
150 /* wLength */ 1, \
151 /* value */ (v))) != USB_SUCCESS) goto label
152
153#define OUTW(dp, p, v, errp, label) \
154 if ((*(errp) = usbgem_ctrl_out_val((dp), \
155 /* bmRequestType */ USB_DEV_REQ_HOST_TO_DEV \
156 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
157 /* bRequest */ USB_REQ_SET_ADDRESS, \
158 /* wValue */ (p), \
159 /* wIndex */ 0, \
160 /* wLength */ 2, \
161 /* value */ (v))) != USB_SUCCESS) goto label
162
163/* BEGIN CSTYLED */
164#define OUTS(dp, p, buf, len, errp, label) \
165 if ((*(errp) = usbgem_ctrl_out((dp), \
166 /* bmRequestType */ USB_DEV_REQ_HOST_TO_DEV \
167 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
168 /* bRequest */ USB_REQ_SET_ADDRESS, \
169 /* wValue */ (p), \
170 /* wIndex */ 0, \
171 /* wLength */ (len), \
172 /* value */ (buf), \
173 /* size */ (len))) != USB_SUCCESS) goto label
174/* END CSTYLED */
175
176#define IN(dp, p, vp, errp, label) \
177 if ((*(errp) = usbgem_ctrl_in_val((dp), \
178 /* bmRequestType */ USB_DEV_REQ_DEV_TO_HOST \
179 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
180 /* bRequest */ USB_REQ_SET_ADDRESS, \
181 /* wValue */ (p), \
182 /* wIndex */ 0, \
183 /* wLength */ sizeof ((*vp)), \
184 /* valuep */ (vp))) != USB_SUCCESS) goto label
185
186#define INS(dp, p, buf, len, errp, label) \
187 if ((*(errp) = usbgem_ctrl_in((dp), \
188 /* bmRequestType */ USB_DEV_REQ_DEV_TO_HOST \
189 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
190 /* bRequest */ USB_REQ_SET_ADDRESS, \
191 /* wValue */ (p), \
192 /* wIndex */ 0, \
193 /* wLength */ (len), \
194 /* valuep */ (buf), \
195 /* size */ (len))) != USB_SUCCESS) goto label
196
197/* =============================================================== */
198/*
199 * variables
200 */
201/* =============================================================== */
202static int urf_ppa = 0;
203
204/* =============================================================== */
205/*
206 * Hardware manupilation
207 */
208/* =============================================================== */
209static int
210urf_reset_chip(struct usbgem_dev *dp)
211{
212 int i;
213 int err;
214 uint8_t reg;
215 struct urf_dev *lp = dp->private;
216
217 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
218
219 lp->cr = 0;
220 OUTB(dp, CR, lp->cr | CR_SOFT_RST, &err, usberr);
221
222 for (i = 0; i < 100; i++) {
223 IN(dp, CR, &reg, &err, usberr);
224 if ((reg & CR_SOFT_RST) == 0) {
225 return (USB_SUCCESS);
226 }
227 }
228 /* time out */
229 cmn_err(CE_WARN, "%s: failed to reset: timeout", dp->name);
230 return (USB_FAILURE);
231
232usberr:
233 cmn_err(CE_NOTE, "!%s: %s: usberr detected", dp->name, __func__);
234 return (USB_FAILURE);
235}
236
237/*
238 * Setup rtl8150
239 */
240static int
241urf_init_chip(struct usbgem_dev *dp)
242{
243 int i;
244 uint32_t val;
245 int err;
246 struct urf_dev *lp = dp->private;
247
248 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
249
250 /* ID registers: set later by urf_set_rx_filter */
251
252 /* Multicast registers: set later by urf_set_rx_filter */
253
254 /* Command register : Enable Tx and Rx before writing TCR and RCR */
255 lp->cr |= CR_RE | CR_TE;
256 OUTB(dp, CR, lp->cr, &err, usberr);
257
258 /* Transmit configration register : */
259 OUTB(dp, TCR, TCR_IFG_802_3, &err, usberr);
260
261 /* Receive configuration register : disable rx filter */
262 lp->rcr = RCR_TAIL | RCR_AER | RCR_AR;
263 OUTW(dp, RCR, lp->rcr, &err, usberr);
264#ifdef notdef
265 /* Media status register */
266 err = urf_set_media(dp);
267 CHECK_AND_JUMP(err, usberr);
268#endif
269 /* Configuration register 0: no need to change */
270
271 DPRINTF(2, (CE_CONT, "!%s: %s: end (success)", dp->name, __func__));
272 return (USB_SUCCESS);
273
274usberr:
275 cmn_err(CE_NOTE, "!%s: %s: usberr detected", dp->name, __func__);
276 return (USB_FAILURE);
277}
278
279static int
280urf_start_chip(struct usbgem_dev *dp)
281{
282 struct urf_dev *lp = dp->private;
283
284 /* do nothing */
285 return (USB_SUCCESS);
286}
287
288static int
289urf_stop_chip(struct usbgem_dev *dp)
290{
291 return (urf_reset_chip(dp));
292}
293
294static int
295urf_get_stats(struct usbgem_dev *dp)
296{
297 /* do nothing */
298 return (USB_SUCCESS);
299}
300
301static uint_t
302urf_mcast_hash(struct usbgem_dev *dp, const uint8_t *addr)
303{
304 return (usbgem_ether_crc_be(addr));
305}
306
307static int
308urf_set_rx_filter(struct usbgem_dev *dp)
309{
310 int i;
311 uint16_t mode;
312 uint8_t mhash[8];
313 int err;
314 int16_t rcr;
315 struct urf_dev *lp = dp->private;
316
317 DPRINTF(2, (CE_CONT, "!%s: %s: called, rxmode:%x",
318 dp->name, __func__, dp->rxmode));
319
320 if (lp->rcr & (RCR_AB | RCR_AD | RCR_AAM | RCR_AAP | RCR_AM)) {
321#ifdef notdef
322 /* disable rx filter before changing it. */
323 lp->rcr &= ~(RCR_AB | RCR_AD | RCR_AAM | RCR_AAP | RCR_AM);
324 OUTW(dp, RCR, lp->rcr, &err, usberr);
325#else
326 /* receive all packets while we change rx filter */
327 OUTW(dp, RCR, lp->rcr | RCR_AAM | RCR_AAP, &err, usberr);
328#endif
329 }
330
331 mode = RCR_AB /* accept broadcast */
332 | RCR_AD; /* accept physical match */
333 bzero(mhash, sizeof (mhash));
334
335 if (dp->rxmode & RXMODE_PROMISC) {
336 /* promiscious mode implies all multicast and all physical */
337 mode |= RCR_AAM | RCR_AAP;
338 } else if ((dp->rxmode & RXMODE_ALLMULTI) || dp->mc_count > 64/2) {
339 /* accept all multicast packets */
340 mode |= RCR_AAM;
341 } else if (dp->mc_count > 0) {
342 /*
343 * make hash table to select interresting
344 * multicast address only.
345 */
346 mode |= RCR_AM;
347 for (i = 0; i < dp->mc_count; i++) {
348 uint_t h;
349 /* hash table is 64 = 2^6 bit width */
350 h = dp->mc_list[i].hash >> (32 - 6);
351 mhash[h / 8] |= 1 << (h % 8);
352 }
353 }
354 lp->rcr |= mode;
355
356 /* set mac address */
357 OUTS(dp, IDR, dp->cur_addr.ether_addr_octet, ETHERADDRL, &err, usberr);
358
359 /* set multicast hash table */
360 if (mode & RCR_AM) {
361 /* need to set up multicast hash table */
362 OUTS(dp, MAR, mhash, sizeof (mhash), &err, usberr);
363 }
364
365 OUTW(dp, RCR, lp->rcr, &err, usberr);
366
367#if DEBUG_LEVEL > 2
368 IN(dp, RCR, &rcr, &err, usberr);
369 cmn_err(CE_CONT, "!%s: %s: rcr:%b returned",
370 dp->name, __func__, rcr, RCR_BITS);
371#endif
372 return (USB_SUCCESS);
373
374usberr:
375 cmn_err(CE_NOTE, "!%s: %s: usberr detected", dp->name, __func__);
376 return (USB_FAILURE);
377}
378
379static int
380urf_set_media(struct usbgem_dev *dp)
381{
382 uint8_t new;
383 uint8_t old;
384 int err;
385 struct urf_dev *lp = dp->private;
386
387 DPRINTF(2, (CE_CONT, "!%s: %s: called", dp->name, __func__));
388
389 /* select duplex: do nothing */
390
391 /* select speed: do nothing */
392
393 /* flow control */
394 IN(dp, MSR, &old, &err, usberr);
395
396
397 /* setup flow control */
398 new = old & ~(MSR_TXFCE | MSR_RXFCE);
399 switch (dp->flow_control) {
400 case FLOW_CONTROL_SYMMETRIC:
401 new |= MSR_TXFCE | MSR_RXFCE;
402 break;
403
404 case FLOW_CONTROL_TX_PAUSE:
405 new |= MSR_TXFCE;
406 break;
407
408 case FLOW_CONTROL_RX_PAUSE:
409 new |= MSR_RXFCE;
410 break;
411
412 case FLOW_CONTROL_NONE:
413 default:
414 break;
415 }
416
417 if (new != old) {
418 OUTB(dp, MSR, new, &err, usberr);
419 }
420 DPRINTF(2, (CE_CONT, "!%s: %s: returned", dp->name, __func__));
421 return (USB_SUCCESS);
422
423usberr:
424 cmn_err(CE_NOTE, "!%s: %s: usberr detected", dp->name, __func__);
425 return (USB_FAILURE);
426}
427
428/*
429 * send/receive packet check
430 */
431static mblk_t *
432urf_tx_make_packet(struct usbgem_dev *dp, mblk_t *mp)
433{
434 size_t len;
435 mblk_t *new;
436 mblk_t *tp;
437 uint8_t *bp;
438 uint8_t *last_pos;
439
440 len = msgdsize(mp);
441
442 if (len < ETHERMIN || mp->b_cont != NULL || (len & 0x3f) == 0) {
443 /*
444 * re-allocate mp
445 */
446 len = max(len, ETHERMIN);
447
448 if ((len & 0x3f) == 0) {
449 /* workaround for buggy USB hba */
450 len++;
451 }
452
453 if ((new = allocb(len, 0)) == NULL) {
454 return (NULL);
455 }
456
457 /* copy contents of the buffer */
458 new->b_wptr = new->b_rptr + len;
459 bp = new->b_rptr;
460 for (tp = mp; tp; tp = tp->b_cont) {
461 len = (uintptr_t)tp->b_wptr - (uintptr_t)tp->b_rptr;
462 bcopy(tp->b_rptr, bp, len);
463 bp += len;
464 }
465
466 last_pos = new->b_wptr;
467 while (bp < last_pos) {
468 *bp++ = 0;
469 }
470
471 mp = new;
472 }
473
474 return (mp);
475}
476
477static void
478urf_dump_packet(struct usbgem_dev *dp, uint8_t *bp, int n)
479{
480 int i;
481
482 for (i = 0; i < n; i += 8, bp += 8) {
483 cmn_err(CE_CONT, "%02x %02x %02x %02x %02x %02x %02x %02x",
484 bp[0], bp[1], bp[2], bp[3], bp[4], bp[5], bp[6], bp[7]);
485 }
486}
487
488static mblk_t *
489urf_rx_make_packet(struct usbgem_dev *dp, mblk_t *mp)
490{
491 uint8_t *p;
492 uint16_t rxhd;
493 uint_t len;
494
495 ASSERT(mp != NULL);
496 len = msgdsize(mp);
497#ifdef DEBUG_LEVEL
498 DPRINTF(2, (CE_CONT, "!%s: time:%d %s: len:%d cont:%p",
499 dp->name, ddi_get_lbolt(), __func__, len, mp->b_cont));
500
501 if (urf_debug > 2) {
502 urf_dump_packet(dp, mp->b_rptr, max(6, len));
503 }
504#endif
505 if (len < ETHERMIN + ETHERFCSL) {
506 /* Too short */
507 dp->stats.runt++;
508 dp->stats.errrcv++;
509 return (NULL);
510 }
511
512 /* get Rx header which is placed at tail of the packet. */
513 p = mp->b_wptr - 4;
514 rxhd = (p[1] << 8) | p[0];
515 len = rxhd & RXHD_BYTECNT;
516
517 DPRINTF(2, (CE_CONT, "!%s: %s: rsr:%b len:%d",
518 dp->name, __func__, rxhd, RXHD_BITS, len));
519
520 /* check if error happen */
521 if ((rxhd & (RXHD_VALID)) == 0) {
522 DPRINTF(-1, (CE_CONT, "!%s: %s: rxhd:%b",
523 dp->name, __func__, rxhd, RXHD_BITS));
524 if (rxhd & RXHD_RUNT) {
525 dp->stats.runt++;
526 }
527
528 dp->stats.errrcv++;
529 return (NULL);
530 }
531#ifdef notdef
532 /* check packet size */
533 if (len > ETHERMAX + ETHERFCSL) {
534 /* too long */
535 dp->stats.frame_too_long++;
536 dp->stats.errrcv++;
537 return (NULL);
538 } else if (len < ETHERMIN + ETHERFCSL) {
539 dp->stats.runt++;
540 dp->stats.errrcv++;
541 return (NULL);
542 }
543#endif
544 /* remove tailing crc field */
545 mp->b_wptr -= ETHERFCSL;
546 return (mp);
547}
548
549/*
550 * MII Interfaces
551 */
552static uint16_t
553urf_mii_read(struct usbgem_dev *dp, uint_t index, int *errp)
554{
555 int reg;
556 uint16_t val;
557
558 DPRINTF(4, (CE_CONT, "!%s: %s: called, ix:%d",
559 dp->name, __func__, index));
560
561 *errp = USB_SUCCESS;
562
563 switch (index) {
564 case MII_CONTROL:
565 reg = BMCR;
566 break;
567
568 case MII_STATUS:
569 reg = BMSR;
570 break;
571
572 case MII_AN_ADVERT:
573 reg = ANAR;
574 break;
575
576 case MII_AN_LPABLE:
577 reg = ANLP;
578 break;
579
580 case MII_AN_EXPANSION:
581 reg = ANER;
582 break;
583
584 default:
585 return (0);
586 }
587
588 IN(dp, reg, &val, errp, usberr);
589
590 if (index == MII_STATUS) {
591 uint8_t msr;
592 /*
593 * Fix MII status register as it does't have LINKUP and
594 * MFPRMBLSUPR bits.
595 */
596 IN(dp, MSR, &msr, errp, usberr);
597
598 val |= (MII_STATUS_MFPRMBLSUPR | MII_STATUS_LINKUP);
599 if ((msr & MSR_LINK) == 0) {
600 val &= ~MII_STATUS_LINKUP;
601 }
602 }
603
604 return (val);
605
606usberr:
607 cmn_err(CE_CONT,
608 "!%s: %s: usberr(%d) detected", dp->name, __func__, *errp);
609
610 return (0);
611}
612
613static void
614urf_mii_write(struct usbgem_dev *dp, uint_t index, uint16_t val, int *errp)
615{
616 int reg;
617
618 DPRINTF(5, (CE_CONT, "!%s: %s called", dp->name, __func__));
619
620 *errp = USB_SUCCESS;
621
622 switch (index) {
623 case MII_CONTROL:
624 reg = BMCR;
625 break;
626
627 case MII_STATUS:
628 reg = BMSR;
629 break;
630
631 case MII_AN_ADVERT:
632 reg = ANAR;
633 break;
634
635 case MII_AN_LPABLE:
636 reg = ANLP;
637 break;
638
639 case MII_AN_EXPANSION:
640 reg = ANER;
641 break;
642
643 default:
644 return;
645 }
646
647 OUTW(dp, reg, val, errp, usberr);
648usberr:
649 ;
650}
651
652/* ======================================================== */
653/*
654 * OS depend (device driver DKI) routine
655 */
656/* ======================================================== */
657static void
658urf_eeprom_dump(struct usbgem_dev *dp, int size)
659{
660 int i;
661 int err;
662 uint16_t w0, w1, w2, w3;
663
664 cmn_err(CE_CONT, "!%s: eeprom dump:", dp->name);
665 for (i = URF_EEPROM_BASE; i < size + URF_EEPROM_BASE; i += 8) {
666 IN(dp, i + 0, &w0, &err, usberr);
667 IN(dp, i + 2, &w1, &err, usberr);
668 IN(dp, i + 4, &w2, &err, usberr);
669 IN(dp, i + 6, &w3, &err, usberr);
670 cmn_err(CE_CONT, "!0x%02x: 0x%04x 0x%04x 0x%04x 0x%04x",
671 i - URF_EEPROM_BASE, w0, w1, w2, w3);
672 }
673usberr:
674 ;
675}
676
677static int
678urf_attach_chip(struct usbgem_dev *dp)
679{
680 int i;
681 uint8_t old;
682 uint_t new;
683 uint8_t reg;
684 int err;
685 struct urf_dev *lp = dp->private;
686
687 /*
688 * setup flow control bit in eeprom
689 */
690 IN(dp, URF_EEPROM_BASE + 9, &old, &err, usberr);
691
692 DPRINTF(0, (CE_CONT, "!%s: eeprom offset 9: %02x", dp->name, old));
693
694 if (dp->ugc.usbgc_flow_control != FLOW_CONTROL_NONE) {
695 /* enable PAUSE bit */
696 new = old | 0x04;
697 } else {
698 /* clear PAUSE bit */
699 new = old & ~0x04;
700 }
701 if (new != old) {
702 /* make eeprom writable */
703 OUTB(dp, CR, lp->cr | CR_WEPROM, &err, usberr);
704
705 /* eerom allows only word access for writing */
706 IN(dp, URF_EEPROM_BASE + 8, &reg, &err, usberr);
707 new = (new << 8) | reg;
708
709 OUTW(dp, URF_EEPROM_BASE + 8, new, &err, usberr);
710
711 /* make eeprom non-writable */
712 OUTB(dp, CR, lp->cr, &err, usberr);
713 }
714
715 /*
716 * load EEPROM contents into nic
717 */
718 OUTB(dp, CR, lp->cr | CR_AUTOLOAD, &err, usberr);
719 CHECK_AND_JUMP(err, usberr);
720
721 for (i = 0; i < 100; i++) {
722 IN(dp, CR, &reg, &err, usberr);
723 if ((reg & CR_AUTOLOAD) == 0) {
724 goto autoload_done;
725 }
726 }
727 /* timeout */
728 cmn_err(CE_WARN, "%s: %s: failed to autoload: timeout",
729 dp->name, __func__);
730 goto usberr;
731
732autoload_done:
733 /*
734 * mac address in EEPROM has loaded to ID registers.
735 */
736 INS(dp, IDR, dp->dev_addr.ether_addr_octet, ETHERADDRL, &err, usberr);
737
738 /* no need to scan phy */
739 dp->mii_phy_addr = -1;
740
741#if DEBUG_LEVEL > 2
742 urf_eeprom_dump(dp, 0x80);
743#endif
744
745#ifdef CONFIG_VLAN
746 dp->misc_flag = USBGEM_VLAN;
747#endif
748 return (USB_SUCCESS);
749
750usberr:
751 cmn_err(CE_WARN, "%s: urf_attach_chip: usb error detected", dp->name);
752 return (USB_FAILURE);
753}
754
755static int
756urfattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
757{
758 int i;
759 ddi_iblock_cookie_t c;
760 int ret;
761 int unit;
762 struct chip_info *p;
763 const char *drv_name;
764 struct usbgem_dev *dp;
765 void *base;
766 struct usbgem_conf *ugcp;
767 struct urf_dev *lp;
768
769 unit = ddi_get_instance(dip);
770 drv_name = ddi_driver_name(dip);
771
772 DPRINTF(3, (CE_CONT, "!%s%d: %s: called, cmd:%d",
773 drv_name, __func__, unit, cmd));
774
775 if (cmd == DDI_ATTACH) {
776 /*
777 * Check if the chip is supported.
778 */
779
780 /*
781 * Check the chip if it is really realtek rtl8150
782 */
783
784 /*
785 * construct usbgem configration
786 */
787 ugcp = kmem_zalloc(sizeof (*ugcp), KM_SLEEP);
788
789 /* name */
790 (void) sprintf(ugcp->usbgc_name,
791 "%s%d(ppa=%d)", drv_name, unit, urf_ppa);
792#ifdef USBGEM_CONFIG_GLDv3
793 ugcp->usbgc_ppa = urf_ppa;
794#else
795 ugcp->usbgc_ppa = unit;
796#endif
797 ugcp->usbgc_ifnum = 0;
798 ugcp->usbgc_alt = 0;
799
800 ugcp->usbgc_tx_list_max = 16;
801
802 /* the rx status partially replaces FCS */
803 ugcp->usbgc_rx_header_len = 0;
804 ugcp->usbgc_rx_list_max = 64;
805
806 /* time out parameters */
807 ugcp->usbgc_tx_timeout = USBGEM_TX_TIMEOUT;
808 ugcp->usbgc_tx_timeout_interval = ONESEC;
809
810 /* flow control */
811 ugcp->usbgc_flow_control = FLOW_CONTROL_RX_PAUSE;
812
813 /* MII timeout parameters */
814 ugcp->usbgc_mii_link_watch_interval = ONESEC;
815 ugcp->usbgc_mii_an_watch_interval = ONESEC/5;
816 ugcp->usbgc_mii_reset_timeout = MII_RESET_TIMEOUT; /* 1 sec */
817 ugcp->usbgc_mii_an_timeout = MII_AN_TIMEOUT; /* 5 sec */
818 ugcp->usbgc_mii_an_wait = (25*ONESEC)/10;
819 ugcp->usbgc_mii_linkdown_timeout = MII_LINKDOWN_TIMEOUT;
820
821 ugcp->usbgc_mii_an_delay = ONESEC/10;
822 ugcp->usbgc_mii_linkdown_action = MII_ACTION_RSA;
823 ugcp->usbgc_mii_linkdown_timeout_action = MII_ACTION_RESET;
824 ugcp->usbgc_mii_dont_reset = B_FALSE;
825
826 /* I/O methods */
827
828 /* mac operation */
829 ugcp->usbgc_attach_chip = &urf_attach_chip;
830 ugcp->usbgc_reset_chip = &urf_reset_chip;
831 ugcp->usbgc_init_chip = &urf_init_chip;
832 ugcp->usbgc_start_chip = &urf_start_chip;
833 ugcp->usbgc_stop_chip = &urf_stop_chip;
834 ugcp->usbgc_multicast_hash = &urf_mcast_hash;
835
836 ugcp->usbgc_set_rx_filter = &urf_set_rx_filter;
837 ugcp->usbgc_set_media = &urf_set_media;
838 ugcp->usbgc_get_stats = &urf_get_stats;
839#ifdef notdef
840 ugcp->usbgc_interrupt = &urf_interrupt;
841#else
842 ugcp->usbgc_interrupt = NULL;
843#endif
844 /* packet operation */
845 ugcp->usbgc_tx_make_packet = &urf_tx_make_packet;
846 ugcp->usbgc_rx_make_packet = &urf_rx_make_packet;
847
848 /* mii operations */
849 ugcp->usbgc_mii_probe = &usbgem_mii_probe_default;
850 ugcp->usbgc_mii_init = &usbgem_mii_init_default;
851 ugcp->usbgc_mii_config = &usbgem_mii_config_default;
852 ugcp->usbgc_mii_read = &urf_mii_read;
853 ugcp->usbgc_mii_write = &urf_mii_write;
854
855 /* mtu */
856 ugcp->usbgc_min_mtu = ETHERMTU;
857 ugcp->usbgc_max_mtu = ETHERMTU;
858 ugcp->usbgc_default_mtu = ETHERMTU;
859
860 lp = kmem_zalloc(sizeof (struct urf_dev), KM_SLEEP);
861 lp->chip = NULL;
862
863 ddi_set_driver_private(dip, NULL);
864
865 dp = usbgem_do_attach(dip, ugcp, lp, sizeof (struct urf_dev));
866
867 kmem_free(ugcp, sizeof (*ugcp));
868
869 if (dp != NULL) {
870 urf_ppa++;
871 return (DDI_SUCCESS);
872 }
873
874err_free_mem:
875 kmem_free(lp, sizeof (struct urf_dev));
876err_close_pipe:
877err:
878 return (DDI_FAILURE);
879 }
880 if (cmd == DDI_RESUME) {
881 return (usbgem_resume(dip));
882 }
883 return (DDI_FAILURE);
884}
885
886static int
887urfdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
888{
889 int ret;
890
891 if (cmd == DDI_DETACH) {
892 ret = usbgem_do_detach(dip);
893 if (ret != DDI_SUCCESS) {
894 return (DDI_FAILURE);
895 }
896 urf_ppa--;
897 return (DDI_SUCCESS);
898 }
899 if (cmd == DDI_SUSPEND) {
900 return (usbgem_suspend(dip));
901 }
902 return (DDI_FAILURE);
903}
904
905/* ======================================================== */
906/*
907 * OS depend (loadable streams driver) routine
908 */
909/* ======================================================== */
910#ifdef USBGEM_CONFIG_GLDv3
911USBGEM_STREAM_OPS(urf_ops, urfattach, urfdetach);
912#else
913static struct module_info urfminfo = {
914 0, /* mi_idnum */
915 "urf", /* mi_idname */
916 0, /* mi_minpsz */
917 ETHERMTU, /* mi_maxpsz */
918 ETHERMTU*128, /* mi_hiwat */
919 1, /* mi_lowat */
920};
921
922static struct qinit urfrinit = {
923 (int (*)()) NULL, /* qi_putp */
924 usbgem_rsrv, /* qi_srvp */
925 usbgem_open, /* qi_qopen */
926 usbgem_close, /* qi_qclose */
927 (int (*)()) NULL, /* qi_qadmin */
928 &urfminfo, /* qi_minfo */
929 NULL /* qi_mstat */
930};
931
932static struct qinit urfwinit = {
933 usbgem_wput, /* qi_putp */
934 usbgem_wsrv, /* qi_srvp */
935 (int (*)()) NULL, /* qi_qopen */
936 (int (*)()) NULL, /* qi_qclose */
937 (int (*)()) NULL, /* qi_qadmin */
938 &urfminfo, /* qi_minfo */
939 NULL /* qi_mstat */
940};
941
942static struct streamtab urf_info = {
943 &urfrinit, /* st_rdinit */
944 &urfwinit, /* st_wrinit */
945 NULL, /* st_muxrinit */
946 NULL /* st_muxwrinit */
947};
948
949static struct cb_ops cb_urf_ops = {
950 nulldev, /* cb_open */
951 nulldev, /* cb_close */
952 nodev, /* cb_strategy */
953 nodev, /* cb_print */
954 nodev, /* cb_dump */
955 nodev, /* cb_read */
956 nodev, /* cb_write */
957 nodev, /* cb_ioctl */
958 nodev, /* cb_devmap */
959 nodev, /* cb_mmap */
960 nodev, /* cb_segmap */
961 nochpoll, /* cb_chpoll */
962 ddi_prop_op, /* cb_prop_op */
963 &urf_info, /* cb_stream */
964 D_NEW|D_MP /* cb_flag */
965};
966
967static struct dev_ops urf_ops = {
968 DEVO_REV, /* devo_rev */
969 0, /* devo_refcnt */
970 usbgem_getinfo, /* devo_getinfo */
971 nulldev, /* devo_identify */
972 nulldev, /* devo_probe */
973 urfattach, /* devo_attach */
974 urfdetach, /* devo_detach */
975 nodev, /* devo_reset */
976 &cb_urf_ops, /* devo_cb_ops */
977 NULL, /* devo_bus_ops */
978 usbgem_power, /* devo_power */
979#if DEVO_REV >= 4
980 usbgem_quiesce, /* devo_quiesce */
981#endif
982
983};
984#endif
985
986static struct modldrv modldrv = {
987 &mod_driverops, /* Type of module. This one is a driver */
988 ident,
989 &urf_ops, /* driver ops */
990};
991
992static struct modlinkage modlinkage = {
993 MODREV_1, &modldrv, NULL
994};
995
996/* ======================================================== */
997/*
998 * _init : done
999 */
1000/* ======================================================== */
1001int
1002_init(void)
1003{
1004 int status;
1005
1006 DPRINTF(2, (CE_CONT, "!urf: _init: called"));
1007
1008 status = usbgem_mod_init(&urf_ops, "urf");
1009 if (status != DDI_SUCCESS) {
1010 return (status);
1011 }
1012 status = mod_install(&modlinkage);
1013 if (status != DDI_SUCCESS) {
1014 usbgem_mod_fini(&urf_ops);
1015 }
1016 return (status);
1017}
1018
1019/*
1020 * _fini : done
1021 */
1022int
1023_fini(void)
1024{
1025 int status;
1026
1027 DPRINTF(2, (CE_CONT, "!urf: _fini: called"));
1028 status = mod_remove(&modlinkage);
1029 if (status == DDI_SUCCESS) {
1030 usbgem_mod_fini(&urf_ops);
1031 }
1032 return (status);
1033}
1034
1035int
1036_info(struct modinfo *modinfop)
1037{
1038 return (mod_info(&modlinkage, modinfop));
1039}