Browse Source

Added any-PCI-device UNDI driver

tags/v0.9.3
Michael Brown 18 years ago
parent
commit
07e5d4e3dc
1 changed files with 119 additions and 0 deletions
  1. 119
    0
      src/arch/i386/drivers/net/undi.c

+ 119
- 0
src/arch/i386/drivers/net/undi.c View File

@@ -0,0 +1,119 @@
1
+/*
2
+ * Copyright (C) 2007 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <stdint.h>
20
+#include <stdlib.h>
21
+#include <string.h>
22
+#include <gpxe/pci.h>
23
+#include <undi.h>
24
+#include <undirom.h>
25
+#include <undiload.h>
26
+#include <undinet.h>
27
+
28
+/** @file
29
+ *
30
+ * UNDI PCI driver
31
+ *
32
+ */
33
+
34
+/**
35
+ * Probe PCI device
36
+ *
37
+ * @v pci	PCI device
38
+ * @v id	PCI ID
39
+ * @ret rc	Return status code
40
+ */
41
+static int undipci_probe ( struct pci_device *pci,
42
+			   const struct pci_device_id *id __unused ) {
43
+	struct undi_device *undi;
44
+	struct undi_rom *undirom;
45
+	unsigned long rombase;
46
+	int rc;
47
+
48
+	/* Ignore non-network devices */
49
+	if ( PCI_BASE_CLASS ( pci->class ) != PCI_BASE_CLASS_NETWORK )
50
+		return -ENOTTY;
51
+
52
+	/* Try to find a driver for this device.  Try an exact match
53
+	 * on the ROM address first, then fall back to a vendor/device
54
+	 * ID match only
55
+	 */
56
+	rombase = pci_bar_start ( pci, PCI_ROM_ADDRESS );
57
+	undirom = undirom_find_pci ( pci->vendor, pci->device, rombase );
58
+	if ( ! undirom )
59
+		undirom = undirom_find_pci ( pci->vendor, pci->device, 0 );
60
+	if ( ! undirom )
61
+		return -ENODEV;
62
+
63
+	/* Allocate UNDI device structure */
64
+	undi = malloc ( sizeof ( *undi ) );
65
+	if ( ! undi )
66
+		return -ENOMEM;
67
+	memset ( undi, 0, sizeof ( *undi ) );
68
+	pci_set_drvdata ( pci, undi );
69
+
70
+	/* Add to device hierarchy */
71
+	undi->dev.parent = &pci->dev;
72
+	INIT_LIST_HEAD ( &undi->dev.children );
73
+	list_add ( &undi->dev.siblings, &pci->dev.children );
74
+
75
+	/* Call UNDI ROM loader to create pixie */
76
+	DBGC ( undi, "UNDI %p using UNDI ROM %p\n", undi, undirom );
77
+	if ( ( rc = undi_load_pci ( undi, undirom, pci->bus,
78
+				    pci->devfn ) ) != 0 )
79
+		goto err_load_pci;
80
+
81
+	/* Create network device */
82
+	if ( ( rc = undinet_probe ( undi ) ) != 0 )
83
+		goto err_undinet_probe;
84
+	
85
+	return 0;
86
+
87
+ err_undinet_probe:
88
+	undi_unload ( undi );
89
+ err_load_pci:
90
+	list_del ( &undi->dev.siblings );
91
+	free ( undi );
92
+	pci_set_drvdata ( pci, NULL );
93
+	return rc;
94
+}
95
+
96
+/**
97
+ * Remove PCI device
98
+ *
99
+ * @v pci	PCI device
100
+ */
101
+static void undipci_remove ( struct pci_device *pci ) {
102
+	struct undi_device *undi = pci_get_drvdata ( pci );
103
+
104
+	undi_unload ( undi );
105
+	list_del ( &undi->dev.siblings );
106
+	free ( undi );
107
+	pci_set_drvdata ( pci, NULL );
108
+}
109
+
110
+static struct pci_device_id undipci_nics[] = {
111
+PCI_ROM ( 0xffff, 0xffff, "undipci", "UNDI (PCI)" ),
112
+};
113
+
114
+struct pci_driver undipci_driver __pci_driver = {
115
+	.ids = undipci_nics,
116
+	.id_count = ( sizeof ( undipci_nics ) / sizeof ( undipci_nics[0] ) ),
117
+	.probe = undipci_probe,
118
+	.remove = undipci_remove,
119
+};

Loading…
Cancel
Save