1 /* $NetBSD: pci_bootdev.c,v 1.1 2025/03/09 01:06:42 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1995, 1996, 1997 Carnegie-Mellon University. 5 * All rights reserved. 6 * 7 * Author: Chris G. Demetriou 8 * 9 * Permission to use, copy, modify and distribute this software and 10 * its documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 */ 29 30 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 31 32 __KERNEL_RCSID(0, "$NetBSD: pci_bootdev.c,v 1.1 2025/03/09 01:06:42 thorpej Exp $"); 33 34 #include <sys/systm.h> 35 #include <sys/device.h> 36 37 #include <machine/alpha.h> 38 #include <machine/autoconf.h> 39 40 #include <dev/ata/atavar.h> 41 #include <dev/pci/pcivar.h> 42 #include <dev/scsipi/scsiconf.h> 43 44 #include <dev/ic/mlxio.h> /* XXX */ 45 #include <dev/ic/mlxvar.h> /* XXX */ 46 47 #include <dev/i2o/i2o.h> /* XXX */ 48 #include <dev/i2o/iopio.h> /* XXX */ 49 #include <dev/i2o/iopvar.h> /* XXX */ 50 51 #define DPRINTF(x) if (bootdev_debug) printf x 52 53 void 54 pci_find_bootdev(device_t hosedev, device_t dev, void *aux) 55 { 56 static device_t pcidev, ctrlrdev; 57 struct bootdev_data *b = bootdev_data; 58 device_t parent = device_parent(dev); 59 60 if (booted_device != NULL || b == NULL) { 61 return; 62 } 63 64 if (pcidev == NULL) { 65 if (device_is_a(dev, "pci")) { 66 struct pcibus_attach_args *pba = aux; 67 68 /* 69 * If a hose device was specified, ensure that 70 * this PCI instance has that device as an ancestor. 71 */ 72 if (hosedev) { 73 while (parent) { 74 if (parent == hosedev) { 75 break; 76 } 77 parent = device_parent(parent); 78 } 79 if (!parent) { 80 return; 81 } 82 } 83 if ((b->slot / 1000) == pba->pba_bus) { 84 pcidev = dev; 85 DPRINTF(("\npcidev = %s\n", device_xname(dev))); 86 } 87 } 88 return; 89 } 90 91 if (ctrlrdev == NULL) { 92 if (parent == pcidev) { 93 struct pci_attach_args *pa = aux; 94 int slot = pa->pa_bus * 1000 + pa->pa_function * 100 + 95 pa->pa_device; 96 97 if (b->slot == slot) { 98 if (bootdev_is_net) { 99 goto foundit; 100 } else { 101 ctrlrdev = dev; 102 DPRINTF(("\nctrlrdev = %s\n", 103 device_xname(dev))); 104 } 105 } 106 } 107 return; 108 } 109 110 if (!bootdev_is_disk) { 111 return; 112 } 113 114 if (device_is_a(dev, "sd") || 115 device_is_a(dev, "st") || 116 device_is_a(dev, "cd")) { 117 struct scsipibus_attach_args *sa = aux; 118 struct scsipi_periph *periph = sa->sa_periph; 119 int unit; 120 121 if (device_parent(parent) != ctrlrdev) { 122 return; 123 } 124 125 unit = periph->periph_target * 100 + periph->periph_lun; 126 if (b->unit != unit || 127 b->channel != periph->periph_channel->chan_channel) { 128 return; 129 } 130 goto foundit; 131 } 132 133 if (device_is_a(dev, "wd")) { 134 struct ata_device *adev = aux; 135 136 if (!device_is_a(parent, "atabus")) { 137 return; 138 } 139 if (device_parent(parent) != ctrlrdev) { 140 return; 141 } 142 143 DPRINTF(("\natapi info: drive %d, channel %d\n", 144 adev->adev_drv_data->drive, adev->adev_channel)); 145 DPRINTF(("bootdev info: unit: %d, channel: %d\n", 146 b->unit, b->channel)); 147 if (b->unit != adev->adev_drv_data->drive || 148 b->channel != adev->adev_channel) { 149 return; 150 } 151 goto foundit; 152 } 153 154 if (device_is_a(dev, "ld")) { 155 /* 156 * XXX Attach arguments for ld devices is not consistent, 157 * XXX so we have to special-case each supported RAID 158 * XXX controller. 159 */ 160 if (parent != ctrlrdev) { 161 return; 162 } 163 164 if (device_is_a(parent, "mlx")) { 165 struct mlx_attach_args *mlxa = aux; 166 167 if (b->unit != mlxa->mlxa_unit) { 168 return; 169 } 170 goto foundit; 171 } 172 173 if (device_is_a(parent, "iop")) { 174 struct iop_attach_args *iopa = aux; 175 176 if (b->unit != iopa->ia_tid) { 177 return; 178 } 179 goto foundit; 180 } 181 } 182 183 return; 184 185 foundit: 186 booted_device = dev; 187 DPRINTF(("\nbooted_device = %s\n", device_xname(dev))); 188 } 189