2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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.
19 FILE_LICENCE ( GPL2_OR_LATER
);
30 #include <undipreload.h>
39 * Find UNDI ROM for PCI device
42 * @ret undirom UNDI ROM, or NULL
44 * Try to find a driver for this device. Try an exact match on the
45 * ROM address first, then fall back to a vendor/device ID match only
47 static struct undi_rom
* undipci_find_rom ( struct pci_device
*pci
) {
48 struct undi_rom
*undirom
;
49 unsigned long rombase
;
51 rombase
= pci_bar_start ( pci
, PCI_ROM_ADDRESS
);
52 undirom
= undirom_find_pci ( pci
->vendor
, pci
->device
, rombase
);
54 undirom
= undirom_find_pci ( pci
->vendor
, pci
->device
, 0 );
63 * @ret rc Return status code
65 static int undipci_probe ( struct pci_device
*pci
,
66 const struct pci_device_id
*id __unused
) {
67 struct undi_device
*undi
;
68 struct undi_rom
*undirom
;
69 unsigned int busdevfn
= PCI_BUSDEVFN ( pci
->bus
, pci
->devfn
);
72 /* Ignore non-network devices */
73 if ( PCI_BASE_CLASS ( pci
->class ) != PCI_BASE_CLASS_NETWORK
)
76 /* Allocate UNDI device structure */
77 undi
= zalloc ( sizeof ( *undi
) );
80 pci_set_drvdata ( pci
, undi
);
82 /* Find/create our pixie */
83 if ( preloaded_undi
.pci_busdevfn
== busdevfn
) {
84 /* Claim preloaded UNDI device */
85 DBGC ( undi
, "UNDI %p using preloaded UNDI device\n", undi
);
86 memcpy ( undi
, &preloaded_undi
, sizeof ( *undi
) );
87 memset ( &preloaded_undi
, 0, sizeof ( preloaded_undi
) );
89 /* Find UNDI ROM for PCI device */
90 if ( ! ( undirom
= undipci_find_rom ( pci
) ) ) {
95 /* Call UNDI ROM loader to create pixie */
96 if ( ( rc
= undi_load_pci ( undi
, undirom
, busdevfn
) ) != 0 )
100 /* Add to device hierarchy */
101 snprintf ( undi
->dev
.name
, sizeof ( undi
->dev
.name
),
102 "UNDI-%s", pci
->dev
.name
);
103 memcpy ( &undi
->dev
.desc
, &pci
->dev
.desc
, sizeof ( undi
->dev
.desc
) );
104 undi
->dev
.parent
= &pci
->dev
;
105 INIT_LIST_HEAD ( &undi
->dev
.children
);
106 list_add ( &undi
->dev
.siblings
, &pci
->dev
.children
);
108 /* Create network device */
109 if ( ( rc
= undinet_probe ( undi
) ) != 0 )
110 goto err_undinet_probe
;
115 undi_unload ( undi
);
116 list_del ( &undi
->dev
.siblings
);
120 pci_set_drvdata ( pci
, NULL
);
129 static void undipci_remove ( struct pci_device
*pci
) {
130 struct undi_device
*undi
= pci_get_drvdata ( pci
);
132 undinet_remove ( undi
);
133 undi_unload ( undi
);
134 list_del ( &undi
->dev
.siblings
);
136 pci_set_drvdata ( pci
, NULL
);
139 static struct pci_device_id undipci_nics
[] = {
140 PCI_ROM ( 0xffff, 0xffff, "undipci", "UNDI (PCI)", 0 ),
143 struct pci_driver undipci_driver __pci_driver
= {
145 .id_count
= ( sizeof ( undipci_nics
) / sizeof ( undipci_nics
[0] ) ),
146 .probe
= undipci_probe
,
147 .remove
= undipci_remove
,