1 /*
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
70 char 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
82 static 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 */
97 struct chip_info {
98 int flags;
99 char *name;
100 int type;
101 };
102
103 #define CHIPTABLESIZE (sizeof (chiptbl_8150) / sizeof (struct chip_info))
104
105 struct 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 */
121 static uint16_t urf_mii_read(struct usbgem_dev *, uint_t, int *errp);
122 static void urf_mii_write(struct usbgem_dev *, uint_t, uint16_t, int *errp);
123
124 /* nic operations */
125 static int urf_attach_chip(struct usbgem_dev *);
126 static int urf_reset_chip(struct usbgem_dev *);
127 static int urf_init_chip(struct usbgem_dev *);
128 static int urf_start_chip(struct usbgem_dev *);
129 static int urf_stop_chip(struct usbgem_dev *);
130 static int urf_set_media(struct usbgem_dev *);
131 static int urf_set_rx_filter(struct usbgem_dev *);
132 static int urf_get_stats(struct usbgem_dev *);
133
134 /* packet operations */
135 static mblk_t *urf_tx_make_packet(struct usbgem_dev *, mblk_t *);
136 static 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 /* =============================================================== */
202 static int urf_ppa = 0;
203
204 /* =============================================================== */
205 /*
206 * Hardware manupilation
207 */
208 /* =============================================================== */
209 static int
urf_reset_chip(struct usbgem_dev * dp)210 urf_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, ®, &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
232 usberr:
233 cmn_err(CE_NOTE, "!%s: %s: usberr detected", dp->name, __func__);
234 return (USB_FAILURE);
235 }
236
237 /*
238 * Setup rtl8150
239 */
240 static int
urf_init_chip(struct usbgem_dev * dp)241 urf_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
274 usberr:
275 cmn_err(CE_NOTE, "!%s: %s: usberr detected", dp->name, __func__);
276 return (USB_FAILURE);
277 }
278
279 static int
urf_start_chip(struct usbgem_dev * dp)280 urf_start_chip(struct usbgem_dev *dp)
281 {
282 struct urf_dev *lp = dp->private;
283
284 /* do nothing */
285 return (USB_SUCCESS);
286 }
287
288 static int
urf_stop_chip(struct usbgem_dev * dp)289 urf_stop_chip(struct usbgem_dev *dp)
290 {
291 return (urf_reset_chip(dp));
292 }
293
294 static int
urf_get_stats(struct usbgem_dev * dp)295 urf_get_stats(struct usbgem_dev *dp)
296 {
297 /* do nothing */
298 return (USB_SUCCESS);
299 }
300
301 static uint_t
urf_mcast_hash(struct usbgem_dev * dp,const uint8_t * addr)302 urf_mcast_hash(struct usbgem_dev *dp, const uint8_t *addr)
303 {
304 return (usbgem_ether_crc_be(addr));
305 }
306
307 static int
urf_set_rx_filter(struct usbgem_dev * dp)308 urf_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
374 usberr:
375 cmn_err(CE_NOTE, "!%s: %s: usberr detected", dp->name, __func__);
376 return (USB_FAILURE);
377 }
378
379 static int
urf_set_media(struct usbgem_dev * dp)380 urf_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
423 usberr:
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 */
431 static mblk_t *
urf_tx_make_packet(struct usbgem_dev * dp,mblk_t * mp)432 urf_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
477 static void
urf_dump_packet(struct usbgem_dev * dp,uint8_t * bp,int n)478 urf_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
488 static mblk_t *
urf_rx_make_packet(struct usbgem_dev * dp,mblk_t * mp)489 urf_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 */
552 static uint16_t
urf_mii_read(struct usbgem_dev * dp,uint_t index,int * errp)553 urf_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
606 usberr:
607 cmn_err(CE_CONT,
608 "!%s: %s: usberr(%d) detected", dp->name, __func__, *errp);
609
610 return (0);
611 }
612
613 static void
urf_mii_write(struct usbgem_dev * dp,uint_t index,uint16_t val,int * errp)614 urf_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);
648 usberr:
649 ;
650 }
651
652 /* ======================================================== */
653 /*
654 * OS depend (device driver DKI) routine
655 */
656 /* ======================================================== */
657 static void
urf_eeprom_dump(struct usbgem_dev * dp,int size)658 urf_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 }
673 usberr:
674 ;
675 }
676
677 static int
urf_attach_chip(struct usbgem_dev * dp)678 urf_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, ®, &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, ®, &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
732 autoload_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
750 usberr:
751 cmn_err(CE_WARN, "%s: urf_attach_chip: usb error detected", dp->name);
752 return (USB_FAILURE);
753 }
754
755 static int
urfattach(dev_info_t * dip,ddi_attach_cmd_t cmd)756 urfattach(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
874 err_free_mem:
875 kmem_free(lp, sizeof (struct urf_dev));
876 err_close_pipe:
877 err:
878 return (DDI_FAILURE);
879 }
880 if (cmd == DDI_RESUME) {
881 return (usbgem_resume(dip));
882 }
883 return (DDI_FAILURE);
884 }
885
886 static int
urfdetach(dev_info_t * dip,ddi_detach_cmd_t cmd)887 urfdetach(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 USBGEM_STREAM_OPS(urf_ops, urfattach, urfdetach);
911
912 static struct modldrv modldrv = {
913 &mod_driverops, /* Type of module. This one is a driver */
914 ident,
915 &urf_ops, /* driver ops */
916 };
917
918 static struct modlinkage modlinkage = {
919 MODREV_1, &modldrv, NULL
920 };
921
922 /* ======================================================== */
923 /*
924 * _init : done
925 */
926 /* ======================================================== */
927 int
_init(void)928 _init(void)
929 {
930 int status;
931
932 DPRINTF(2, (CE_CONT, "!urf: _init: called"));
933
934 status = usbgem_mod_init(&urf_ops, "urf");
935 if (status != DDI_SUCCESS) {
936 return (status);
937 }
938 status = mod_install(&modlinkage);
939 if (status != DDI_SUCCESS) {
940 usbgem_mod_fini(&urf_ops);
941 }
942 return (status);
943 }
944
945 /*
946 * _fini : done
947 */
948 int
_fini(void)949 _fini(void)
950 {
951 int status;
952
953 DPRINTF(2, (CE_CONT, "!urf: _fini: called"));
954 status = mod_remove(&modlinkage);
955 if (status == DDI_SUCCESS) {
956 usbgem_mod_fini(&urf_ops);
957 }
958 return (status);
959 }
960
961 int
_info(struct modinfo * modinfop)962 _info(struct modinfo *modinfop)
963 {
964 return (mod_info(&modlinkage, modinfop));
965 }
966