linux/drivers/mca/mca-legacy.c
<<
>>
Prefs
   1/* -*- mode: c; c-basic-offset: 8 -*- */
   2
   3/*
   4 * MCA bus support functions for legacy (2.4) API.
   5 *
   6 * Legacy API means the API that operates in terms of MCA slot number
   7 *
   8 * (C) 2002 James Bottomley <James.Bottomley@HansenPartnership.com>
   9 *
  10**-----------------------------------------------------------------------------
  11**  
  12**  This program is free software; you can redistribute it and/or modify
  13**  it under the terms of the GNU General Public License as published by
  14**  the Free Software Foundation; either version 2 of the License, or
  15**  (at your option) any later version.
  16**
  17**  This program is distributed in the hope that it will be useful,
  18**  but WITHOUT ANY WARRANTY; without even the implied warranty of
  19**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20**  GNU General Public License for more details.
  21**
  22**  You should have received a copy of the GNU General Public License
  23**  along with this program; if not, write to the Free Software
  24**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25**
  26**-----------------------------------------------------------------------------
  27 */
  28
  29#include <linux/module.h>
  30#include <linux/device.h>
  31#include <linux/mca-legacy.h>
  32#include <asm/io.h>
  33
  34/* NOTE: This structure is stack allocated */
  35struct mca_find_adapter_info {
  36        int                     id;
  37        int                     slot;
  38        struct mca_device       *mca_dev;
  39};
  40
  41/* The purpose of this iterator is to loop over all the devices and
  42 * find the one with the smallest slot number that's just greater than
  43 * or equal to the required slot with a matching id */
  44static int mca_find_adapter_callback(struct device *dev, void *data)
  45{
  46        struct mca_find_adapter_info *info = data;
  47        struct mca_device *mca_dev = to_mca_device(dev);
  48
  49        if(mca_dev->pos_id != info->id)
  50                return 0;
  51
  52        if(mca_dev->slot < info->slot)
  53                return 0;
  54
  55        if(!info->mca_dev || info->mca_dev->slot >= mca_dev->slot)
  56                info->mca_dev = mca_dev;
  57
  58        return 0;
  59}
  60
  61/**
  62 *      mca_find_adapter - scan for adapters
  63 *      @id:    MCA identification to search for
  64 *      @start: starting slot
  65 *
  66 *      Search the MCA configuration for adapters matching the 16bit
  67 *      ID given. The first time it should be called with start as zero
  68 *      and then further calls made passing the return value of the
  69 *      previous call until %MCA_NOTFOUND is returned.
  70 *
  71 *      Disabled adapters are not reported.
  72 */
  73
  74int mca_find_adapter(int id, int start)
  75{
  76        struct mca_find_adapter_info info;
  77
  78        if(id == 0xffff)
  79                return MCA_NOTFOUND;
  80
  81        info.slot = start;
  82        info.id = id;
  83        info.mca_dev = NULL;
  84
  85        for(;;) {
  86                bus_for_each_dev(&mca_bus_type, NULL, &info, mca_find_adapter_callback);
  87
  88                if(info.mca_dev == NULL)
  89                        return MCA_NOTFOUND;
  90
  91                if(info.mca_dev->status != MCA_ADAPTER_DISABLED)
  92                        break;
  93
  94                /* OK, found adapter but it was disabled.  Go around
  95                 * again, excluding the slot we just found */
  96
  97                info.slot = info.mca_dev->slot + 1;
  98                info.mca_dev = NULL;
  99        }
 100                
 101        return info.mca_dev->slot;
 102}
 103EXPORT_SYMBOL(mca_find_adapter);
 104
 105/*--------------------------------------------------------------------*/
 106
 107/**
 108 *      mca_find_unused_adapter - scan for unused adapters
 109 *      @id:    MCA identification to search for
 110 *      @start: starting slot
 111 *
 112 *      Search the MCA configuration for adapters matching the 16bit
 113 *      ID given. The first time it should be called with start as zero
 114 *      and then further calls made passing the return value of the
 115 *      previous call until %MCA_NOTFOUND is returned.
 116 *
 117 *      Adapters that have been claimed by drivers and those that
 118 *      are disabled are not reported. This function thus allows a driver
 119 *      to scan for further cards when some may already be driven.
 120 */
 121
 122int mca_find_unused_adapter(int id, int start)
 123{
 124        struct mca_find_adapter_info info = { 0 };
 125
 126        if (!MCA_bus || id == 0xffff)
 127                return MCA_NOTFOUND;
 128
 129        info.slot = start;
 130        info.id = id;
 131        info.mca_dev = NULL;
 132
 133        for(;;) {
 134                bus_for_each_dev(&mca_bus_type, NULL, &info, mca_find_adapter_callback);
 135
 136                if(info.mca_dev == NULL)
 137                        return MCA_NOTFOUND;
 138
 139                if(info.mca_dev->status != MCA_ADAPTER_DISABLED
 140                   && !info.mca_dev->driver_loaded)
 141                        break;
 142
 143                /* OK, found adapter but it was disabled or already in
 144                 * use.  Go around again, excluding the slot we just
 145                 * found */
 146
 147                info.slot = info.mca_dev->slot + 1;
 148                info.mca_dev = NULL;
 149        }
 150                
 151        return info.mca_dev->slot;
 152}
 153EXPORT_SYMBOL(mca_find_unused_adapter);
 154
 155/* NOTE: stack allocated structure */
 156struct mca_find_device_by_slot_info {
 157        int                     slot;
 158        struct mca_device       *mca_dev;
 159};
 160
 161static int mca_find_device_by_slot_callback(struct device *dev, void *data)
 162{
 163        struct mca_find_device_by_slot_info *info = data;
 164        struct mca_device *mca_dev = to_mca_device(dev);
 165
 166        if(mca_dev->slot == info->slot)
 167                info->mca_dev = mca_dev;
 168
 169        return 0;
 170}
 171
 172struct mca_device *mca_find_device_by_slot(int slot)
 173{
 174        struct mca_find_device_by_slot_info info;
 175
 176        info.slot = slot;
 177        info.mca_dev = NULL;
 178
 179        bus_for_each_dev(&mca_bus_type, NULL, &info, mca_find_device_by_slot_callback);
 180
 181        return info.mca_dev;
 182}
 183
 184/**
 185 *      mca_read_stored_pos - read POS register from boot data
 186 *      @slot: slot number to read from
 187 *      @reg:  register to read from
 188 *
 189 *      Fetch a POS value that was stored at boot time by the kernel
 190 *      when it scanned the MCA space. The register value is returned.
 191 *      Missing or invalid registers report 0.
 192 */
 193unsigned char mca_read_stored_pos(int slot, int reg)
 194{
 195        struct mca_device *mca_dev = mca_find_device_by_slot(slot);
 196
 197        if(!mca_dev)
 198                return 0;
 199
 200        return mca_device_read_stored_pos(mca_dev, reg);
 201}
 202EXPORT_SYMBOL(mca_read_stored_pos);
 203
 204
 205/**
 206 *      mca_read_pos - read POS register from card
 207 *      @slot: slot number to read from
 208 *      @reg:  register to read from
 209 *
 210 *      Fetch a POS value directly from the hardware to obtain the
 211 *      current value. This is much slower than mca_read_stored_pos and
 212 *      may not be invoked from interrupt context. It handles the
 213 *      deep magic required for onboard devices transparently.
 214 */
 215
 216unsigned char mca_read_pos(int slot, int reg)
 217{
 218        struct mca_device *mca_dev = mca_find_device_by_slot(slot);
 219
 220        if(!mca_dev)
 221                return 0;
 222
 223        return mca_device_read_pos(mca_dev, reg);
 224}
 225EXPORT_SYMBOL(mca_read_pos);
 226
 227                
 228/**
 229 *      mca_write_pos - read POS register from card
 230 *      @slot: slot number to read from
 231 *      @reg:  register to read from
 232 *      @byte: byte to write to the POS registers
 233 *
 234 *      Store a POS value directly from the hardware. You should not
 235 *      normally need to use this function and should have a very good
 236 *      knowledge of MCA bus before you do so. Doing this wrongly can
 237 *      damage the hardware.
 238 *
 239 *      This function may not be used from interrupt context.
 240 *
 241 *      Note that this a technically a Bad Thing, as IBM tech stuff says
 242 *      you should only set POS values through their utilities.
 243 *      However, some devices such as the 3c523 recommend that you write
 244 *      back some data to make sure the configuration is consistent.
 245 *      I'd say that IBM is right, but I like my drivers to work.
 246 *
 247 *      This function can't do checks to see if multiple devices end up
 248 *      with the same resources, so you might see magic smoke if someone
 249 *      screws up.
 250 */
 251
 252void mca_write_pos(int slot, int reg, unsigned char byte)
 253{
 254        struct mca_device *mca_dev = mca_find_device_by_slot(slot);
 255
 256        if(!mca_dev)
 257                return;
 258
 259        mca_device_write_pos(mca_dev, reg, byte);
 260}
 261EXPORT_SYMBOL(mca_write_pos);
 262
 263/**
 264 *      mca_set_adapter_name - Set the description of the card
 265 *      @slot: slot to name
 266 *      @name: text string for the namen
 267 *
 268 *      This function sets the name reported via /proc for this
 269 *      adapter slot. This is for user information only. Setting a
 270 *      name deletes any previous name.
 271 */
 272
 273void mca_set_adapter_name(int slot, char* name)
 274{
 275        struct mca_device *mca_dev = mca_find_device_by_slot(slot);
 276
 277        if(!mca_dev)
 278                return;
 279
 280        mca_device_set_name(mca_dev, name);
 281}
 282EXPORT_SYMBOL(mca_set_adapter_name);
 283
 284/**
 285 *      mca_mark_as_used - claim an MCA device
 286 *      @slot:  slot to claim
 287 *      FIXME:  should we make this threadsafe
 288 *
 289 *      Claim an MCA slot for a device driver. If the
 290 *      slot is already taken the function returns 1,
 291 *      if it is not taken it is claimed and 0 is
 292 *      returned.
 293 */
 294
 295int mca_mark_as_used(int slot)
 296{
 297        struct mca_device *mca_dev = mca_find_device_by_slot(slot);
 298
 299        if(!mca_dev)
 300                /* FIXME: this is actually a severe error */
 301                return 1;
 302
 303        if(mca_device_claimed(mca_dev))
 304                return 1;
 305
 306        mca_device_set_claim(mca_dev, 1);
 307
 308        return 0;
 309}
 310EXPORT_SYMBOL(mca_mark_as_used);
 311
 312/**
 313 *      mca_mark_as_unused - release an MCA device
 314 *      @slot:  slot to claim
 315 *
 316 *      Release the slot for other drives to use.
 317 */
 318
 319void mca_mark_as_unused(int slot)
 320{
 321        struct mca_device *mca_dev = mca_find_device_by_slot(slot);
 322
 323        if(!mca_dev)
 324                return;
 325
 326        mca_device_set_claim(mca_dev, 0);
 327}
 328EXPORT_SYMBOL(mca_mark_as_unused);
 329
 330