Selaa lähdekoodia

[dm96xx] Add driver for Davicom DM96xx USB Ethernet NICs

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 vuotta sitten
vanhempi
commit
1ae94c903d
4 muutettua tiedostoa jossa 865 lisäystä ja 1 poistoa
  1. 667
    0
      src/drivers/net/dm96xx.c
  2. 194
    0
      src/drivers/net/dm96xx.h
  3. 1
    1
      src/include/ipxe/errfile.h
  4. 3
    0
      src/include/ipxe/usb.h

+ 667
- 0
src/drivers/net/dm96xx.c Näytä tiedosto

@@ -0,0 +1,667 @@
1
+/*
2
+ * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ */
19
+
20
+FILE_LICENCE ( GPL2_OR_LATER );
21
+
22
+#include <string.h>
23
+#include <unistd.h>
24
+#include <errno.h>
25
+#include <ipxe/ethernet.h>
26
+#include <ipxe/usb.h>
27
+#include <ipxe/usbnet.h>
28
+#include "dm96xx.h"
29
+
30
+/** @file
31
+ *
32
+ * Davicom DM96xx USB Ethernet driver
33
+ *
34
+ */
35
+
36
+/******************************************************************************
37
+ *
38
+ * Register operations
39
+ *
40
+ ******************************************************************************
41
+ */
42
+
43
+/**
44
+ * Reset device
45
+ *
46
+ * @v dm96xx		DM96xx device
47
+ * @ret rc		Return status code
48
+ */
49
+static int dm96xx_reset ( struct dm96xx_device *dm96xx ) {
50
+	int ncr;
51
+	int rc;
52
+
53
+	/* Reset device */
54
+	if ( ( rc = dm96xx_write_register ( dm96xx, DM96XX_NCR,
55
+					    DM96XX_NCR_RST ) ) != 0 ) {
56
+		DBGC ( dm96xx, "DM96XX %p could not reset: %s\n",
57
+		       dm96xx, strerror ( rc ) );
58
+		return rc;
59
+	}
60
+
61
+	/* Wait for reset to complete */
62
+	udelay ( DM96XX_RESET_DELAY_US );
63
+
64
+	/* Check that reset has completed */
65
+	ncr = dm96xx_read_register ( dm96xx, DM96XX_NCR );
66
+	if ( ncr < 0 ) {
67
+		rc = ncr;
68
+		DBGC ( dm96xx, "DM96XX %p failed to reset: %s\n",
69
+		       dm96xx, strerror ( rc ) );
70
+		return rc;
71
+	}
72
+	if ( ncr & DM96XX_NCR_RST ) {
73
+		DBGC ( dm96xx, "DM96XX %p failed to reset (NCR=%#02x)\n",
74
+		       dm96xx, ncr );
75
+		return -EIO;
76
+	}
77
+
78
+	return 0;
79
+}
80
+
81
+/**
82
+ * Read MAC address
83
+ *
84
+ * @v dm96xx		DM96xx device
85
+ * @v mac		MAC address to fill in
86
+ * @ret rc		Return status code
87
+ */
88
+static int dm96xx_read_mac ( struct dm96xx_device *dm96xx, uint8_t *mac ) {
89
+	int rc;
90
+
91
+	/* Read MAC address */
92
+	if ( ( rc = dm96xx_read_registers ( dm96xx, DM96XX_PAR, mac,
93
+					    ETH_ALEN ) ) != 0 ) {
94
+		DBGC ( dm96xx, "DM96XX %p could not read MAC address: %s\n",
95
+		       dm96xx, strerror ( rc ) );
96
+		return rc;
97
+	}
98
+
99
+	return 0;
100
+}
101
+
102
+/**
103
+ * Write MAC address
104
+ *
105
+ * @v dm96xx		DM96xx device
106
+ * @v mac		MAC address
107
+ * @ret rc		Return status code
108
+ */
109
+static int dm96xx_write_mac ( struct dm96xx_device *dm96xx, uint8_t *mac ) {
110
+	int rc;
111
+
112
+	/* Write MAC address */
113
+	if ( ( rc = dm96xx_write_registers ( dm96xx, DM96XX_PAR, mac,
114
+					     ETH_ALEN ) ) != 0 ) {
115
+		DBGC ( dm96xx, "DM96XX %p could not write MAC address: %s\n",
116
+		       dm96xx, strerror ( rc ) );
117
+		return rc;
118
+	}
119
+
120
+	return 0;
121
+}
122
+
123
+/**
124
+ * Update link status based on network status register
125
+ *
126
+ * @v dm96xx		DM96xx device
127
+ * @v nsr		Network status register
128
+ */
129
+static void dm96xx_link_nsr ( struct dm96xx_device *dm96xx, unsigned int nsr ) {
130
+	struct net_device *netdev = dm96xx->netdev;
131
+
132
+	if ( nsr & DM96XX_NSR_LINKST ) {
133
+		if ( ! netdev_link_ok ( netdev ) )
134
+			netdev_link_up ( netdev );
135
+	} else {
136
+		if ( netdev_link_ok ( netdev ) )
137
+			netdev_link_down ( netdev );
138
+	}
139
+}
140
+
141
+/**
142
+ * Get link status
143
+ *
144
+ * @v dm96xx		DM96xx device
145
+ * @ret rc		Return status code
146
+ */
147
+static int dm96xx_check_link ( struct dm96xx_device *dm96xx ) {
148
+	int nsr;
149
+	int rc;
150
+
151
+	/* Read network status register */
152
+	nsr = dm96xx_read_register ( dm96xx, DM96XX_NSR );
153
+	if ( nsr < 0 ) {
154
+		rc = nsr;
155
+		DBGC ( dm96xx, "DM96XX %p could not read network status: %s\n",
156
+		       dm96xx, strerror ( rc ) );
157
+		return rc;
158
+	}
159
+
160
+	/* Update link status */
161
+	dm96xx_link_nsr ( dm96xx, nsr );
162
+
163
+	return 0;
164
+}
165
+
166
+/**
167
+ * Set DM9601-compatible RX header mode
168
+ *
169
+ * @v dm96xx		DM96xx device
170
+ * @ret rc		Return status code
171
+ */
172
+static int dm96xx_rx_mode ( struct dm96xx_device *dm96xx ) {
173
+	int chipr;
174
+	int mode_ctl;
175
+	int rc;
176
+
177
+	/* Get chip revision */
178
+	chipr = dm96xx_read_register ( dm96xx, DM96XX_CHIPR );
179
+	if ( chipr < 0 ) {
180
+		rc = chipr;
181
+		DBGC ( dm96xx, "DM96XX %p could not read chip revision: %s\n",
182
+		       dm96xx, strerror ( rc ) );
183
+		return rc;
184
+	}
185
+
186
+	/* Do nothing if device is a DM9601 anyway */
187
+	if ( chipr == DM96XX_CHIPR_9601 )
188
+		return 0;
189
+
190
+	/* Read current mode control */
191
+	mode_ctl = dm96xx_read_register ( dm96xx, DM96XX_MODE_CTL );
192
+	if ( mode_ctl < 0 ) {
193
+		rc = mode_ctl;
194
+		DBGC ( dm96xx, "DM96XX %p could not read mode control: %s\n",
195
+		       dm96xx, strerror ( rc ) );
196
+		return rc;
197
+	}
198
+
199
+	/* Write mode control */
200
+	mode_ctl &= ~DM96XX_MODE_CTL_MODE;
201
+	if ( ( rc = dm96xx_write_register ( dm96xx, DM96XX_MODE_CTL,
202
+					    mode_ctl ) ) != 0 ) {
203
+		DBGC ( dm96xx, "DM96XX %p could not write mode control: %s\n",
204
+		       dm96xx, strerror ( rc ) );
205
+		return rc;
206
+	}
207
+
208
+	return 0;
209
+}
210
+
211
+/******************************************************************************
212
+ *
213
+ * Endpoint operations
214
+ *
215
+ ******************************************************************************
216
+ */
217
+
218
+/**
219
+ * Complete interrupt transfer
220
+ *
221
+ * @v ep		USB endpoint
222
+ * @v iobuf		I/O buffer
223
+ * @v rc		Completion status code
224
+ */
225
+static void dm96xx_intr_complete ( struct usb_endpoint *ep,
226
+				   struct io_buffer *iobuf, int rc ) {
227
+	struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
228
+						      usbnet.intr );
229
+	struct net_device *netdev = dm96xx->netdev;
230
+	struct dm96xx_interrupt *intr;
231
+	size_t len = iob_len ( iobuf );
232
+
233
+	/* Ignore packets cancelled when the endpoint closes */
234
+	if ( ! ep->open )
235
+		goto done;
236
+
237
+	/* Record USB errors against the network device */
238
+	if ( rc != 0 ) {
239
+		DBGC ( dm96xx, "DM96XX %p interrupt failed: %s\n",
240
+		       dm96xx, strerror ( rc ) );
241
+		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
242
+		netdev_rx_err ( netdev, NULL, rc );
243
+		goto done;
244
+	}
245
+
246
+	/* Extract message header */
247
+	if ( len < sizeof ( *intr ) ) {
248
+		DBGC ( dm96xx, "DM96XX %p underlength interrupt:\n", dm96xx );
249
+		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
250
+		netdev_rx_err ( netdev, NULL, -EINVAL );
251
+		goto done;
252
+	}
253
+	intr = iobuf->data;
254
+
255
+	/* Update link status */
256
+	dm96xx_link_nsr ( dm96xx, intr->nsr );
257
+
258
+ done:
259
+	/* Free I/O buffer */
260
+	free_iob ( iobuf );
261
+}
262
+
263
+/** Interrupt endpoint operations */
264
+static struct usb_endpoint_driver_operations dm96xx_intr_operations = {
265
+	.complete = dm96xx_intr_complete,
266
+};
267
+
268
+/**
269
+ * Complete bulk IN transfer
270
+ *
271
+ * @v ep		USB endpoint
272
+ * @v iobuf		I/O buffer
273
+ * @v rc		Completion status code
274
+ */
275
+static void dm96xx_in_complete ( struct usb_endpoint *ep,
276
+				 struct io_buffer *iobuf, int rc ) {
277
+	struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
278
+						      usbnet.in );
279
+	struct net_device *netdev = dm96xx->netdev;
280
+	struct dm96xx_rx_header *header;
281
+
282
+	/* Ignore packets cancelled when the endpoint closes */
283
+	if ( ! ep->open ) {
284
+		free_iob ( iobuf );
285
+		return;
286
+	}
287
+
288
+	/* Record USB errors against the network device */
289
+	if ( rc != 0 ) {
290
+		DBGC ( dm96xx, "DM96XX %p bulk IN failed: %s\n",
291
+		       dm96xx, strerror ( rc ) );
292
+		goto err;
293
+	}
294
+
295
+	/* Sanity check */
296
+	if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) {
297
+		DBGC ( dm96xx, "DM96XX %p underlength bulk IN\n", dm96xx );
298
+		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
299
+		rc = -EINVAL;
300
+		goto err;
301
+	}
302
+
303
+	/* Strip header and CRC */
304
+	header = iobuf->data;
305
+	iob_pull ( iobuf, sizeof ( *header ) );
306
+	iob_unput ( iobuf, 4 /* CRC */ );
307
+
308
+	/* Check status */
309
+	if ( header->rsr & ~DM96XX_RSR_MF ) {
310
+		DBGC ( dm96xx, "DM96XX %p receive error %02x:\n",
311
+		       dm96xx, header->rsr );
312
+		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
313
+		rc = -EIO;
314
+		goto err;
315
+	}
316
+
317
+	/* Hand off to network stack */
318
+	netdev_rx ( netdev, iob_disown ( iobuf ) );
319
+	return;
320
+
321
+ err:
322
+	/* Hand off to network stack */
323
+	netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
324
+}
325
+
326
+/** Bulk IN endpoint operations */
327
+static struct usb_endpoint_driver_operations dm96xx_in_operations = {
328
+	.complete = dm96xx_in_complete,
329
+};
330
+
331
+/**
332
+ * Transmit packet
333
+ *
334
+ * @v dm96xx		DM96xx device
335
+ * @v iobuf		I/O buffer
336
+ * @ret rc		Return status code
337
+ */
338
+static int dm96xx_out_transmit ( struct dm96xx_device *dm96xx,
339
+				 struct io_buffer *iobuf ) {
340
+	struct dm96xx_tx_header *header;
341
+	size_t len = iob_len ( iobuf );
342
+	int rc;
343
+
344
+	/* Prepend header */
345
+	if ( ( rc = iob_ensure_headroom ( iobuf, sizeof ( *header ) ) ) != 0 )
346
+		return rc;
347
+	header = iob_push ( iobuf, sizeof ( *header ) );
348
+	header->len = cpu_to_le16 ( len );
349
+
350
+	/* Enqueue I/O buffer */
351
+	if ( ( rc = usb_stream ( &dm96xx->usbnet.out, iobuf, 0 ) ) != 0 )
352
+		return rc;
353
+
354
+	return 0;
355
+}
356
+
357
+/**
358
+ * Complete bulk OUT transfer
359
+ *
360
+ * @v ep		USB endpoint
361
+ * @v iobuf		I/O buffer
362
+ * @v rc		Completion status code
363
+ */
364
+static void dm96xx_out_complete ( struct usb_endpoint *ep,
365
+				  struct io_buffer *iobuf, int rc ) {
366
+	struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
367
+						      usbnet.out );
368
+	struct net_device *netdev = dm96xx->netdev;
369
+
370
+	/* Report TX completion */
371
+	netdev_tx_complete_err ( netdev, iobuf, rc );
372
+}
373
+
374
+/** Bulk OUT endpoint operations */
375
+static struct usb_endpoint_driver_operations dm96xx_out_operations = {
376
+	.complete = dm96xx_out_complete,
377
+};
378
+
379
+/******************************************************************************
380
+ *
381
+ * Network device interface
382
+ *
383
+ ******************************************************************************
384
+ */
385
+
386
+/**
387
+ * Open network device
388
+ *
389
+ * @v netdev		Network device
390
+ * @ret rc		Return status code
391
+ */
392
+static int dm96xx_open ( struct net_device *netdev ) {
393
+	struct dm96xx_device *dm96xx = netdev->priv;
394
+	unsigned int rcr;
395
+	int rc;
396
+
397
+	/* Set DM9601-compatible RX header mode */
398
+	if ( ( rc = dm96xx_rx_mode ( dm96xx ) ) != 0 )
399
+		goto err_rx_mode;
400
+
401
+	/* Write MAC address */
402
+	if ( ( rc = dm96xx_write_mac ( dm96xx, netdev->ll_addr ) ) != 0 )
403
+		goto err_write_mac;
404
+
405
+	/* Open USB network device */
406
+	if ( ( rc = usbnet_open ( &dm96xx->usbnet ) ) != 0 ) {
407
+		DBGC ( dm96xx, "DM96XX %p could not open: %s\n",
408
+		       dm96xx, strerror ( rc ) );
409
+		goto err_open;
410
+	}
411
+
412
+	/* Set receive filters */
413
+	rcr = ( DM96XX_RCR_ALL | DM96XX_RCR_RUNT | DM96XX_RCR_PRMSC |
414
+		DM96XX_RCR_RXEN );
415
+	if ( ( rc = dm96xx_write_register ( dm96xx, DM96XX_RCR, rcr ) ) != 0 ) {
416
+		DBGC ( dm96xx, "DM96XX %p could not write receive filters: "
417
+		       "%s\n", dm96xx, strerror ( rc ) );
418
+		goto err_write_rcr;
419
+	}
420
+
421
+	/* Update link status */
422
+	if ( ( rc = dm96xx_check_link ( dm96xx ) ) != 0 )
423
+		goto err_check_link;
424
+
425
+	return 0;
426
+
427
+ err_check_link:
428
+ err_write_rcr:
429
+	usbnet_close ( &dm96xx->usbnet );
430
+ err_open:
431
+ err_write_mac:
432
+ err_rx_mode:
433
+	return rc;
434
+}
435
+
436
+/**
437
+ * Close network device
438
+ *
439
+ * @v netdev		Network device
440
+ */
441
+static void dm96xx_close ( struct net_device *netdev ) {
442
+	struct dm96xx_device *dm96xx = netdev->priv;
443
+
444
+	/* Close USB network device */
445
+	usbnet_close ( &dm96xx->usbnet );
446
+
447
+	/* Reset device */
448
+	dm96xx_reset ( dm96xx );
449
+}
450
+
451
+/**
452
+ * Transmit packet
453
+ *
454
+ * @v netdev		Network device
455
+ * @v iobuf		I/O buffer
456
+ * @ret rc		Return status code
457
+ */
458
+static int dm96xx_transmit ( struct net_device *netdev,
459
+			     struct io_buffer *iobuf ) {
460
+	struct dm96xx_device *dm96xx = netdev->priv;
461
+	int rc;
462
+
463
+	/* Transmit packet */
464
+	if ( ( rc = dm96xx_out_transmit ( dm96xx, iobuf ) ) != 0 )
465
+		return rc;
466
+
467
+	return 0;
468
+}
469
+
470
+/**
471
+ * Poll for completed and received packets
472
+ *
473
+ * @v netdev		Network device
474
+ */
475
+static void dm96xx_poll ( struct net_device *netdev ) {
476
+	struct dm96xx_device *dm96xx = netdev->priv;
477
+	int rc;
478
+
479
+	/* Poll USB bus */
480
+	usb_poll ( dm96xx->bus );
481
+
482
+	/* Refill endpoints */
483
+	if ( ( rc = usbnet_refill ( &dm96xx->usbnet ) ) != 0 )
484
+		netdev_rx_err ( netdev, NULL, rc );
485
+}
486
+
487
+/** DM96xx network device operations */
488
+static struct net_device_operations dm96xx_operations = {
489
+	.open		= dm96xx_open,
490
+	.close		= dm96xx_close,
491
+	.transmit	= dm96xx_transmit,
492
+	.poll		= dm96xx_poll,
493
+};
494
+
495
+/******************************************************************************
496
+ *
497
+ * USB interface
498
+ *
499
+ ******************************************************************************
500
+ */
501
+
502
+/**
503
+ * Probe device
504
+ *
505
+ * @v func		USB function
506
+ * @v config		Configuration descriptor
507
+ * @ret rc		Return status code
508
+ */
509
+static int dm96xx_probe ( struct usb_function *func,
510
+		       struct usb_configuration_descriptor *config ) {
511
+	struct usb_device *usb = func->usb;
512
+	struct net_device *netdev;
513
+	struct dm96xx_device *dm96xx;
514
+	int rc;
515
+
516
+	/* Allocate and initialise structure */
517
+	netdev = alloc_etherdev ( sizeof ( *dm96xx ) );
518
+	if ( ! netdev ) {
519
+		rc = -ENOMEM;
520
+		goto err_alloc;
521
+	}
522
+	netdev_init ( netdev, &dm96xx_operations );
523
+	netdev->dev = &func->dev;
524
+	dm96xx = netdev->priv;
525
+	memset ( dm96xx, 0, sizeof ( *dm96xx ) );
526
+	dm96xx->usb = usb;
527
+	dm96xx->bus = usb->port->hub->bus;
528
+	dm96xx->netdev = netdev;
529
+	usbnet_init ( &dm96xx->usbnet, func, &dm96xx_intr_operations,
530
+		      &dm96xx_in_operations, &dm96xx_out_operations );
531
+	usb_refill_init ( &dm96xx->usbnet.intr, 0, DM96XX_INTR_MAX_FILL );
532
+	usb_refill_init ( &dm96xx->usbnet.in, DM96XX_IN_MTU,
533
+			  DM96XX_IN_MAX_FILL );
534
+	DBGC ( dm96xx, "DM96XX %p on %s\n", dm96xx, func->name );
535
+
536
+	/* Describe USB network device */
537
+	if ( ( rc = usbnet_describe ( &dm96xx->usbnet, config ) ) != 0 ) {
538
+		DBGC ( dm96xx, "DM96XX %p could not describe: %s\n",
539
+		       dm96xx, strerror ( rc ) );
540
+		goto err_describe;
541
+	}
542
+
543
+	/* Reset device */
544
+	if ( ( rc = dm96xx_reset ( dm96xx ) ) != 0 )
545
+		goto err_reset;
546
+
547
+	/* Read MAC address */
548
+	if ( ( rc = dm96xx_read_mac ( dm96xx, netdev->hw_addr ) ) != 0 )
549
+		goto err_read_mac;
550
+
551
+	/* Get initial link status */
552
+	if ( ( rc = dm96xx_check_link ( dm96xx ) ) != 0 )
553
+		goto err_check_link;
554
+
555
+	/* Register network device */
556
+	if ( ( rc = register_netdev ( netdev ) ) != 0 )
557
+		goto err_register;
558
+
559
+	usb_func_set_drvdata ( func, netdev );
560
+	return 0;
561
+
562
+	unregister_netdev ( netdev );
563
+ err_register:
564
+ err_check_link:
565
+ err_read_mac:
566
+ err_reset:
567
+ err_describe:
568
+	netdev_nullify ( netdev );
569
+	netdev_put ( netdev );
570
+ err_alloc:
571
+	return rc;
572
+}
573
+
574
+/**
575
+ * Remove device
576
+ *
577
+ * @v func		USB function
578
+ */
579
+static void dm96xx_remove ( struct usb_function *func ) {
580
+	struct net_device *netdev = usb_func_get_drvdata ( func );
581
+
582
+	unregister_netdev ( netdev );
583
+	netdev_nullify ( netdev );
584
+	netdev_put ( netdev );
585
+}
586
+
587
+/** DM96xx device IDs */
588
+static struct usb_device_id dm96xx_ids[] = {
589
+	{
590
+		.name = "dm9601-corega",
591
+		.vendor = 0x07aa,
592
+		.product = 0x9601,
593
+	},
594
+	{
595
+		.name = "dm9601",
596
+		.vendor = 0x0a46,
597
+		.product = 0x9601,
598
+	},
599
+	{
600
+		.name = "zt6688",
601
+		.vendor = 0x0a46,
602
+		.product = 0x6688,
603
+	},
604
+	{
605
+		.name = "st268",
606
+		.vendor = 0x0a46,
607
+		.product = 0x0268,
608
+	},
609
+	{
610
+		.name = "adm8515",
611
+		.vendor = 0x0a46,
612
+		.product = 0x8515,
613
+	},
614
+	{
615
+		.name = "dm9601-hirose",
616
+		.vendor = 0x0a47,
617
+		.product = 0x9601,
618
+	},
619
+	{
620
+		.name = "dm9601-8101",
621
+		.vendor = 0x0fe6,
622
+		.product = 0x8101,
623
+	},
624
+	{
625
+		.name = "dm9601-9700",
626
+		.vendor = 0x0fe6,
627
+		.product = 0x9700,
628
+	},
629
+	{
630
+		.name = "dm9000e",
631
+		.vendor = 0x0a46,
632
+		.product = 0x9000,
633
+	},
634
+	{
635
+		.name = "dm9620",
636
+		.vendor = 0x0a46,
637
+		.product = 0x9620,
638
+	},
639
+	{
640
+		.name = "dm9621A",
641
+		.vendor = 0x0a46,
642
+		.product = 0x9621,
643
+	},
644
+	{
645
+		.name = "dm9622",
646
+		.vendor = 0x0a46,
647
+		.product = 0x9622,
648
+	},
649
+	{
650
+		.name = "dm962Oa",
651
+		.vendor = 0x0a46,
652
+		.product = 0x0269,
653
+	},
654
+	{
655
+		.name = "dm9621a",
656
+		.vendor = 0x0a46,
657
+		.product = 0x1269,
658
+	},
659
+};
660
+
661
+/** Davicom DM96xx driver */
662
+struct usb_driver dm96xx_driver __usb_driver = {
663
+	.ids = dm96xx_ids,
664
+	.id_count = ( sizeof ( dm96xx_ids ) / sizeof ( dm96xx_ids[0] ) ),
665
+	.probe = dm96xx_probe,
666
+	.remove = dm96xx_remove,
667
+};

+ 194
- 0
src/drivers/net/dm96xx.h Näytä tiedosto

@@ -0,0 +1,194 @@
1
+#ifndef _DM96XX_H
2
+#define _DM96XX_H
3
+
4
+/** @file
5
+ *
6
+ * Davicom DM96xx USB Ethernet driver
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#include <ipxe/usb.h>
13
+#include <ipxe/usbnet.h>
14
+#include <ipxe/if_ether.h>
15
+
16
+/** Read register(s) */
17
+#define DM96XX_READ_REGISTER					\
18
+	( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE |	\
19
+	  USB_REQUEST_TYPE ( 0x00 ) )
20
+
21
+/** Write register(s) */
22
+#define DM96XX_WRITE_REGISTER					\
23
+	( USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE |	\
24
+	  USB_REQUEST_TYPE ( 0x01 ) )
25
+
26
+/** Write single register */
27
+#define DM96XX_WRITE1_REGISTER					\
28
+	( USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE |	\
29
+	  USB_REQUEST_TYPE ( 0x03 ) )
30
+
31
+/** Network control register */
32
+#define DM96XX_NCR 0x00
33
+#define DM96XX_NCR_RST		0x01	/**< Software reset */
34
+
35
+/** Network status register */
36
+#define DM96XX_NSR 0x01
37
+#define DM96XX_NSR_LINKST	0x40	/**< Link status */
38
+
39
+/** Receive control register */
40
+#define DM96XX_RCR 0x05
41
+#define DM96XX_RCR_ALL		0x08	/**< Pass all multicast */
42
+#define DM96XX_RCR_RUNT		0x04	/**< Pass runt packet */
43
+#define DM96XX_RCR_PRMSC	0x02	/**< Promiscuous mode */
44
+#define DM96XX_RCR_RXEN		0x01	/**< RX enable */
45
+
46
+/** Receive status register */
47
+#define DM96XX_RSR 0x06
48
+#define DM96XX_RSR_MF		0x40	/**< Multicast frame */
49
+
50
+/** PHY address registers */
51
+#define DM96XX_PAR 0x10
52
+
53
+/** Chip revision register */
54
+#define DM96XX_CHIPR 0x2c
55
+#define DM96XX_CHIPR_9601	0x00	/**< DM9601 */
56
+#define DM96XX_CHIPR_9620	0x01	/**< DM9620 */
57
+
58
+/** RX header control/status register (DM9620+ only) */
59
+#define DM96XX_MODE_CTL 0x91
60
+#define DM96XX_MODE_CTL_MODE	0x80	/**< 4-byte header mode */
61
+
62
+/** DM96xx interrupt data */
63
+struct dm96xx_interrupt {
64
+	/** Network status register */
65
+	uint8_t nsr;
66
+	/** Transmit status registers */
67
+	uint8_t tsr[2];
68
+	/** Receive status register */
69
+	uint8_t rsr;
70
+	/** Receive overflow counter register */
71
+	uint8_t rocr;
72
+	/** Receive packet counter */
73
+	uint8_t rxc;
74
+	/** Transmit packet counter */
75
+	uint8_t txc;
76
+	/** General purpose register */
77
+	uint8_t gpr;
78
+} __attribute__ (( packed ));
79
+
80
+/** DM96xx receive header */
81
+struct dm96xx_rx_header {
82
+	/** Packet status */
83
+	uint8_t rsr;
84
+	/** Packet length (excluding this header, including CRC) */
85
+	uint16_t len;
86
+} __attribute__ (( packed ));
87
+
88
+/** DM96xx transmit header */
89
+struct dm96xx_tx_header {
90
+	/** Packet length (excluding this header) */
91
+	uint16_t len;
92
+} __attribute__ (( packed ));
93
+
94
+/** A DM96xx network device */
95
+struct dm96xx_device {
96
+	/** USB device */
97
+	struct usb_device *usb;
98
+	/** USB bus */
99
+	struct usb_bus *bus;
100
+	/** Network device */
101
+	struct net_device *netdev;
102
+	/** USB network device */
103
+	struct usbnet_device usbnet;
104
+};
105
+
106
+/**
107
+ * Read registers
108
+ *
109
+ * @v dm96xx		DM96xx device
110
+ * @v offset		Register offset
111
+ * @v data		Data buffer
112
+ * @v len		Length of data
113
+ * @ret rc		Return status code
114
+ */
115
+static inline __attribute__ (( always_inline )) int
116
+dm96xx_read_registers ( struct dm96xx_device *dm96xx, unsigned int offset,
117
+			void *data, size_t len ) {
118
+
119
+	return usb_control ( dm96xx->usb, DM96XX_READ_REGISTER, 0, offset,
120
+			     data, len );
121
+}
122
+
123
+/**
124
+ * Read register
125
+ *
126
+ * @v dm96xx		DM96xx device
127
+ * @v offset		Register offset
128
+ * @ret value		Register value, or negative error
129
+ */
130
+static inline __attribute__ (( always_inline )) int
131
+dm96xx_read_register ( struct dm96xx_device *dm96xx, unsigned int offset ) {
132
+	uint8_t value;
133
+	int rc;
134
+
135
+	if ( ( rc = dm96xx_read_registers ( dm96xx, offset, &value,
136
+					    sizeof ( value ) ) ) != 0 )
137
+		return rc;
138
+	return value;
139
+}
140
+
141
+/**
142
+ * Write registers
143
+ *
144
+ * @v dm96xx		DM96xx device
145
+ * @v offset		Register offset
146
+ * @v data		Data buffer
147
+ * @v len		Length of data
148
+ * @ret rc		Return status code
149
+ */
150
+static inline __attribute__ (( always_inline )) int
151
+dm96xx_write_registers ( struct dm96xx_device *dm96xx, unsigned int offset,
152
+			 void *data, size_t len ) {
153
+
154
+	return usb_control ( dm96xx->usb, DM96XX_WRITE_REGISTER, 0, offset,
155
+			     data, len );
156
+}
157
+
158
+/**
159
+ * Write register
160
+ *
161
+ * @v dm96xx		DM96xx device
162
+ * @v offset		Register offset
163
+ * @v value		Register value
164
+ * @ret rc		Return status code
165
+ */
166
+static inline __attribute__ (( always_inline )) int
167
+dm96xx_write_register ( struct dm96xx_device *dm96xx, unsigned int offset,
168
+			uint8_t value ) {
169
+
170
+	return usb_control ( dm96xx->usb, DM96XX_WRITE1_REGISTER, value,
171
+			     offset, NULL, 0 );
172
+}
173
+
174
+/** Reset delay (in microseconds) */
175
+#define DM96XX_RESET_DELAY_US 10
176
+
177
+/** Interrupt maximum fill level
178
+ *
179
+ * This is a policy decision.
180
+ */
181
+#define DM96XX_INTR_MAX_FILL 2
182
+
183
+/** Bulk IN maximum fill level
184
+ *
185
+ * This is a policy decision.
186
+ */
187
+#define DM96XX_IN_MAX_FILL 8
188
+
189
+/** Bulk IN buffer size */
190
+#define DM96XX_IN_MTU					\
191
+	( 4 /* DM96xx header */ + ETH_FRAME_LEN +	\
192
+	  4 /* possible VLAN header */ + 4 /* CRC */ )
193
+
194
+#endif /* _DM96XX_H */

+ 1
- 1
src/include/ipxe/errfile.h Näytä tiedosto

@@ -164,7 +164,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
164 164
 #define ERRFILE_ecm		     ( ERRFILE_DRIVER | 0x006c0000 )
165 165
 #define ERRFILE_ncm		     ( ERRFILE_DRIVER | 0x006d0000 )
166 166
 #define ERRFILE_usbnet		     ( ERRFILE_DRIVER | 0x006e0000 )
167
-
167
+#define ERRFILE_dm96xx		     ( ERRFILE_DRIVER | 0x006f0000 )
168 168
 #define ERRFILE_scsi		     ( ERRFILE_DRIVER | 0x00700000 )
169 169
 #define ERRFILE_arbel		     ( ERRFILE_DRIVER | 0x00710000 )
170 170
 #define ERRFILE_hermon		     ( ERRFILE_DRIVER | 0x00720000 )

+ 3
- 0
src/include/ipxe/usb.h Näytä tiedosto

@@ -78,6 +78,9 @@ struct usb_setup_packet {
78 78
 /** Class-specific request type */
79 79
 #define USB_TYPE_CLASS ( 1 << 5 )
80 80
 
81
+/** Vendor-specific request type */
82
+#define USB_TYPE_VENDOR ( 2 << 5 )
83
+
81 84
 /** Request recipient is the device */
82 85
 #define USB_RECIP_DEVICE ( 0 << 0 )
83 86
 

Loading…
Peruuta
Tallenna