1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Device Attach routines File: cfe_attach.c 5 * 6 * This module manages the list of device drivers. When a driver 7 * is probed, it can call cfe_attach to create actual device 8 * instances. The routines in this module manage the 9 * device list and the assignment of device names. 10 * 11 * Author: Mitch Lichtenberg (mpl@broadcom.com) 12 * 13 ********************************************************************* 14 * 15 * Copyright 2000,2001,2002,2003 16 * Broadcom Corporation. All rights reserved. 17 * 18 * This software is furnished under license and may be used and 19 * copied only in accordance with the following terms and 20 * conditions. Subject to these conditions, you may download, 21 * copy, install, use, modify and distribute modified or unmodified 22 * copies of this software in source and/or binary form. No title 23 * or ownership is transferred hereby. 24 * 25 * 1) Any source code used, modified or distributed must reproduce 26 * and retain this copyright notice and list of conditions 27 * as they appear in the source file. 28 * 29 * 2) No right is granted to use any trade name, trademark, or 30 * logo of Broadcom Corporation. The "Broadcom Corporation" 31 * name may not be used to endorse or promote products derived 32 * from this software without the prior written permission of 33 * Broadcom Corporation. 34 * 35 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 36 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 37 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 38 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 39 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 40 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 41 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 43 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 44 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 45 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 46 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 47 * THE POSSIBILITY OF SUCH DAMAGE. 48 ********************************************************************* */ 49 50 51#include "lib_types.h" 52#include "lib_malloc.h" 53#include "lib_queue.h" 54#include "lib_printf.h" 55#include "lib_string.h" 56#include "cfe_iocb.h" 57#include "cfe_device.h" 58 59/* ********************************************************************* 60 * Constants 61 ********************************************************************* */ 62 63#define CFE_MAX_DEVINST 64 /* max # of instances of devices */ 64 65/* ********************************************************************* 66 * Globals 67 ********************************************************************* */ 68 69/* 70 * Our device list. 71 */ 72 73queue_t cfe_devices = {&cfe_devices, &cfe_devices}; 74 75/* ********************************************************************* 76 * cfe_finddev(name) 77 * 78 * Locate a device in the device list by its name and return 79 * a pointer to the device structure. 80 * 81 * Input parameters: 82 * name - name of device, e.g., "uart0" 83 * 84 * Return value: 85 * cfe_device_t pointer or NULL 86 ********************************************************************* */ 87 88cfe_device_t *cfe_finddev(char *name) 89{ 90 queue_t *qb; 91 cfe_device_t *dev; 92 93 for (qb = cfe_devices.q_next; qb != &cfe_devices; qb = qb->q_next) { 94 dev = (cfe_device_t *) qb; 95 if (strcmp(dev->dev_fullname,name) == 0) { 96 return dev; 97 } 98 } 99 100 return NULL; 101} 102 103 104/* ********************************************************************* 105 * cfe_device_reset() 106 * 107 * Call all the "reset" methods in the devices on the device 108 * list. Note that the methods get called even when the 109 * devices are closed! 110 * 111 * Input parameters: 112 * nothing 113 * 114 * Return value: 115 * nothing 116 ********************************************************************* */ 117 118void cfe_device_reset(void) 119{ 120 queue_t *qb; 121 cfe_device_t *dev; 122 123 for (qb = cfe_devices.q_next; qb != &cfe_devices; qb = qb->q_next) { 124 dev = (cfe_device_t *) qb; 125 if (dev->dev_dispatch->dev_reset) { 126 (*(dev->dev_dispatch->dev_reset))(dev->dev_softc); 127 } 128 } 129} 130 131/* ********************************************************************* 132 * cfe_attach_idx(drv,idx,softc,bootinfo,description) 133 * 134 * Add a device to the device list at a specific index. This 135 * is mainly used for devices like SCSI disks or CD-ROMs so 136 * we can use an index that matches the target ID or LUN. 137 * 138 * Input parameters: 139 * drv - driver structure (from the device driver module) 140 * idx - requested index (e.g., uartn where 'n' is the idx) 141 * softc - Unique information maintained for this device 142 * bootinfo - suffix for long form of the device name. For 143 * example, scsi0.3.1 might mean SCSI controller 144 * 0, device ID 3, LUN 1. The bootinfo would be 145 * "3.1" 146 * description - something nice to say for the devices command 147 * 148 * Return value: 149 * 0 if device has already been added at this index 150 * <0 for other problems 151 * 1 if we were successful. 152 ********************************************************************* */ 153 154int cfe_attach_idx(cfe_driver_t *drv,int idx,void *softc, 155 char *bootinfo,char *description) 156{ 157 char name[64]; 158 cfe_device_t *dev; 159 160 xsprintf(name,"%s%d",drv->drv_bootname,idx); 161 162 if (bootinfo) { 163 strcat(name,"."); 164 strcat(name,bootinfo); 165 } 166 167 if (cfe_finddev(name) != NULL) { 168 return 0; 169 } 170 171 dev = (cfe_device_t *) KMALLOC(sizeof(cfe_device_t),0); 172 if (!dev) return -1; 173 174 dev->dev_fullname = strdup(name); 175 dev->dev_softc = softc; 176 dev->dev_class = drv->drv_class; 177 dev->dev_dispatch = drv->drv_dispatch; 178 dev->dev_description = description ? strdup(description) : NULL; 179 dev->dev_opencount = 0; 180 181 q_enqueue(&cfe_devices,(queue_t *) dev); 182 183 return 1; 184 185} 186 187 188 189/* ********************************************************************* 190 * cfe_attach(drv,softc,bootinfo,description 191 * 192 * Add a device to the system. This is a callback from the 193 * probe routine, and is used to actually add devices to CFE's 194 * device list. 195 * 196 * Input parameters: 197 * drv - driver structure (from the device driver module) 198 * softc - Unique information maintained for this device 199 * bootinfo - suffix for long form of the device name. For 200 * example, scsi0.3.1 might mean SCSI controller 201 * 0, device ID 3, LUN 1. The bootinfo would be 202 * "3.1" 203 * description - something nice to say for the devices command 204 * 205 * Return value: 206 * nothing 207 ********************************************************************* */ 208 209void cfe_attach(cfe_driver_t *drv,void *softc, 210 char *bootinfo, 211 char *description) 212{ 213 int idx; 214 int res; 215 216 /* 217 * Try device indicies 0..CFE_MAX_DEVINST to assign a unique 218 * device name for this device. This is a really braindead way to 219 * do this, but how many devices are we expecting anyway? 220 */ 221 222 for (idx = 0; idx < CFE_MAX_DEVINST; idx++) { 223 224 res = cfe_attach_idx(drv,idx,softc,bootinfo,description); 225 226 if (res < 0) break; /* out of memory or other badness */ 227 if (res > 0) break; /* success! */ 228 /* otherwise, try again, slot is taken */ 229 } 230 231} 232 233/* ********************************************************************* 234 * cfe_attach_init() 235 * 236 * Initialize this module. 237 * 238 * Input parameters: 239 * nothing 240 * 241 * Return value: 242 * nothing 243 ********************************************************************* */ 244void cfe_attach_init(void) 245{ 246 q_init(&(cfe_devices)); 247} 248 249 250/* ********************************************************************* 251 * cfe_device_name(ctx) 252 * 253 * Given a device context, return a device name 254 * 255 * Input parameters: 256 * ctx - context 257 * 258 * Return value: 259 * name 260 ********************************************************************* */ 261 262char *cfe_device_name(cfe_devctx_t *ctx) 263{ 264 return ctx->dev_dev->dev_fullname; 265} 266