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
);
24 #include <gpxe/device.h>
25 #include <gpxe/init.h>
28 #include <undipreload.h>
34 * This is the UNDI driver without explicit support for PCI or any
35 * other bus type. It is capable only of using the preloaded UNDI
36 * device. It must not be combined in an image with any other
39 * If you want a PXE-loadable image that contains only the UNDI
40 * driver, build "bin/undionly.kpxe".
42 * If you want any other image format, or any other drivers in
43 * addition to the UNDI driver, build e.g. "bin/undi.dsk".
49 * @v rootdev UNDI bus root device
51 * Scans the UNDI bus for devices and registers all devices it can
54 static int undibus_probe ( struct root_device
*rootdev
) {
55 struct undi_device
*undi
= &preloaded_undi
;
58 /* Check for a valie preloaded UNDI device */
59 if ( ! undi
->entry
.segment
) {
60 DBG ( "No preloaded UNDI device found!\n" );
64 /* Add to device hierarchy */
65 strncpy ( undi
->dev
.name
, "UNDI",
66 ( sizeof ( undi
->dev
.name
) - 1 ) );
67 if ( undi
->pci_busdevfn
!= UNDI_NO_PCI_BUSDEVFN
) {
68 undi
->dev
.desc
.bus_type
= BUS_TYPE_PCI
;
69 undi
->dev
.desc
.location
= undi
->pci_busdevfn
;
70 undi
->dev
.desc
.vendor
= undi
->pci_vendor
;
71 undi
->dev
.desc
.device
= undi
->pci_device
;
72 } else if ( undi
->isapnp_csn
!= UNDI_NO_ISAPNP_CSN
) {
73 undi
->dev
.desc
.bus_type
= BUS_TYPE_ISAPNP
;
75 undi
->dev
.parent
= &rootdev
->dev
;
76 list_add ( &undi
->dev
.siblings
, &rootdev
->dev
.children
);
77 INIT_LIST_HEAD ( &undi
->dev
.children
);
79 /* Create network device */
80 if ( ( rc
= undinet_probe ( undi
) ) != 0 )
86 list_del ( &undi
->dev
.siblings
);
91 * Remove UNDI root bus
93 * @v rootdev UNDI bus root device
95 static void undibus_remove ( struct root_device
*rootdev __unused
) {
96 struct undi_device
*undi
= &preloaded_undi
;
98 undinet_remove ( undi
);
99 list_del ( &undi
->dev
.siblings
);
102 /** UNDI bus root device driver */
103 static struct root_driver undi_root_driver
= {
104 .probe
= undibus_probe
,
105 .remove
= undibus_remove
,
108 /** UNDI bus root device */
109 struct root_device undi_root_device __root_device
= {
110 .dev
= { .name
= "UNDI" },
111 .driver
= &undi_root_driver
,
117 * @v flags Shutdown flags
119 static void undionly_shutdown ( int flags
) {
120 /* If we are shutting down to boot an OS, clear the "keep PXE
123 if ( flags
& SHUTDOWN_BOOT
)
124 preloaded_undi
.flags
&= ~UNDI_FL_KEEP_ALL
;
127 struct startup_fn startup_undionly
__startup_fn ( STARTUP_LATE
) = {
128 .shutdown
= undionly_shutdown
,