linux/drivers/firmware/dcdbas.c
<<
>>
Prefs
   1/*
   2 *  dcdbas.c: Dell Systems Management Base Driver
   3 *
   4 *  The Dell Systems Management Base Driver provides a sysfs interface for
   5 *  systems management software to perform System Management Interrupts (SMIs)
   6 *  and Host Control Actions (power cycle or power off after OS shutdown) on
   7 *  Dell systems.
   8 *
   9 *  See Documentation/dcdbas.txt for more information.
  10 *
  11 *  Copyright (C) 1995-2006 Dell Inc.
  12 *
  13 *  This program is free software; you can redistribute it and/or modify
  14 *  it under the terms of the GNU General Public License v2.0 as published by
  15 *  the Free Software Foundation.
  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
  23#include <linux/platform_device.h>
  24#include <linux/dma-mapping.h>
  25#include <linux/errno.h>
  26#include <linux/gfp.h>
  27#include <linux/init.h>
  28#include <linux/kernel.h>
  29#include <linux/mc146818rtc.h>
  30#include <linux/module.h>
  31#include <linux/reboot.h>
  32#include <linux/sched.h>
  33#include <linux/smp.h>
  34#include <linux/spinlock.h>
  35#include <linux/string.h>
  36#include <linux/types.h>
  37#include <linux/mutex.h>
  38#include <asm/io.h>
  39
  40#include "dcdbas.h"
  41
  42#define DRIVER_NAME             "dcdbas"
  43#define DRIVER_VERSION          "5.6.0-3.2"
  44#define DRIVER_DESCRIPTION      "Dell Systems Management Base Driver"
  45
  46static struct platform_device *dcdbas_pdev;
  47
  48static u8 *smi_data_buf;
  49static dma_addr_t smi_data_buf_handle;
  50static unsigned long smi_data_buf_size;
  51static u32 smi_data_buf_phys_addr;
  52static DEFINE_MUTEX(smi_data_lock);
  53
  54static unsigned int host_control_action;
  55static unsigned int host_control_smi_type;
  56static unsigned int host_control_on_shutdown;
  57
  58/**
  59 * smi_data_buf_free: free SMI data buffer
  60 */
  61static void smi_data_buf_free(void)
  62{
  63        if (!smi_data_buf)
  64                return;
  65
  66        dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
  67                __func__, smi_data_buf_phys_addr, smi_data_buf_size);
  68
  69        dma_free_coherent(&dcdbas_pdev->dev, smi_data_buf_size, smi_data_buf,
  70                          smi_data_buf_handle);
  71        smi_data_buf = NULL;
  72        smi_data_buf_handle = 0;
  73        smi_data_buf_phys_addr = 0;
  74        smi_data_buf_size = 0;
  75}
  76
  77/**
  78 * smi_data_buf_realloc: grow SMI data buffer if needed
  79 */
  80static int smi_data_buf_realloc(unsigned long size)
  81{
  82        void *buf;
  83        dma_addr_t handle;
  84
  85        if (smi_data_buf_size >= size)
  86                return 0;
  87
  88        if (size > MAX_SMI_DATA_BUF_SIZE)
  89                return -EINVAL;
  90
  91        /* new buffer is needed */
  92        buf = dma_alloc_coherent(&dcdbas_pdev->dev, size, &handle, GFP_KERNEL);
  93        if (!buf) {
  94                dev_dbg(&dcdbas_pdev->dev,
  95                        "%s: failed to allocate memory size %lu\n",
  96                        __func__, size);
  97                return -ENOMEM;
  98        }
  99        /* memory zeroed by dma_alloc_coherent */
 100
 101        if (smi_data_buf)
 102                memcpy(buf, smi_data_buf, smi_data_buf_size);
 103
 104        /* free any existing buffer */
 105        smi_data_buf_free();
 106
 107        /* set up new buffer for use */
 108        smi_data_buf = buf;
 109        smi_data_buf_handle = handle;
 110        smi_data_buf_phys_addr = (u32) virt_to_phys(buf);
 111        smi_data_buf_size = size;
 112
 113        dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
 114                __func__, smi_data_buf_phys_addr, smi_data_buf_size);
 115
 116        return 0;
 117}
 118
 119static ssize_t smi_data_buf_phys_addr_show(struct device *dev,
 120                                           struct device_attribute *attr,
 121                                           char *buf)
 122{
 123        return sprintf(buf, "%x\n", smi_data_buf_phys_addr);
 124}
 125
 126static ssize_t smi_data_buf_size_show(struct device *dev,
 127                                      struct device_attribute *attr,
 128                                      char *buf)
 129{
 130        return sprintf(buf, "%lu\n", smi_data_buf_size);
 131}
 132
 133static ssize_t smi_data_buf_size_store(struct device *dev,
 134                                       struct device_attribute *attr,
 135                                       const char *buf, size_t count)
 136{
 137        unsigned long buf_size;
 138        ssize_t ret;
 139
 140        buf_size = simple_strtoul(buf, NULL, 10);
 141
 142        /* make sure SMI data buffer is at least buf_size */
 143        mutex_lock(&smi_data_lock);
 144        ret = smi_data_buf_realloc(buf_size);
 145        mutex_unlock(&smi_data_lock);
 146        if (ret)
 147                return ret;
 148
 149        return count;
 150}
 151
 152static ssize_t smi_data_read(struct file *filp, struct kobject *kobj,
 153                             struct bin_attribute *bin_attr,
 154                             char *buf, loff_t pos, size_t count)
 155{
 156        ssize_t ret;
 157
 158        mutex_lock(&smi_data_lock);
 159        ret = memory_read_from_buffer(buf, count, &pos, smi_data_buf,
 160                                        smi_data_buf_size);
 161        mutex_unlock(&smi_data_lock);
 162        return ret;
 163}
 164
 165static ssize_t smi_data_write(struct file *filp, struct kobject *kobj,
 166                              struct bin_attribute *bin_attr,
 167                              char *buf, loff_t pos, size_t count)
 168{
 169        ssize_t ret;
 170
 171        if ((pos + count) > MAX_SMI_DATA_BUF_SIZE)
 172                return -EINVAL;
 173
 174        mutex_lock(&smi_data_lock);
 175
 176        ret = smi_data_buf_realloc(pos + count);
 177        if (ret)
 178                goto out;
 179
 180        memcpy(smi_data_buf + pos, buf, count);
 181        ret = count;
 182out:
 183        mutex_unlock(&smi_data_lock);
 184        return ret;
 185}
 186
 187static ssize_t host_control_action_show(struct device *dev,
 188                                        struct device_attribute *attr,
 189                                        char *buf)
 190{
 191        return sprintf(buf, "%u\n", host_control_action);
 192}
 193
 194static ssize_t host_control_action_store(struct device *dev,
 195                                         struct device_attribute *attr,
 196                                         const char *buf, size_t count)
 197{
 198        ssize_t ret;
 199
 200        /* make sure buffer is available for host control command */
 201        mutex_lock(&smi_data_lock);
 202        ret = smi_data_buf_realloc(sizeof(struct apm_cmd));
 203        mutex_unlock(&smi_data_lock);
 204        if (ret)
 205                return ret;
 206
 207        host_control_action = simple_strtoul(buf, NULL, 10);
 208        return count;
 209}
 210
 211static ssize_t host_control_smi_type_show(struct device *dev,
 212                                          struct device_attribute *attr,
 213                                          char *buf)
 214{
 215        return sprintf(buf, "%u\n", host_control_smi_type);
 216}
 217
 218static ssize_t host_control_smi_type_store(struct device *dev,
 219                                           struct device_attribute *attr,
 220                                           const char *buf, size_t count)
 221{
 222        host_control_smi_type = simple_strtoul(buf, NULL, 10);
 223        return count;
 224}
 225
 226static ssize_t host_control_on_shutdown_show(struct device *dev,
 227                                             struct device_attribute *attr,
 228                                             char *buf)
 229{
 230        return sprintf(buf, "%u\n", host_control_on_shutdown);
 231}
 232
 233static ssize_t host_control_on_shutdown_store(struct device *dev,
 234                                              struct device_attribute *attr,
 235                                              const char *buf, size_t count)
 236{
 237        host_control_on_shutdown = simple_strtoul(buf, NULL, 10);
 238        return count;
 239}
 240
 241/**
 242 * dcdbas_smi_request: generate SMI request
 243 *
 244 * Called with smi_data_lock.
 245 */
 246int dcdbas_smi_request(struct smi_cmd *smi_cmd)
 247{
 248        cpumask_var_t old_mask;
 249        int ret = 0;
 250
 251        if (smi_cmd->magic != SMI_CMD_MAGIC) {
 252                dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n",
 253                         __func__);
 254                return -EBADR;
 255        }
 256
 257        /* SMI requires CPU 0 */
 258        if (!alloc_cpumask_var(&old_mask, GFP_KERNEL))
 259                return -ENOMEM;
 260
 261        cpumask_copy(old_mask, &current->cpus_allowed);
 262        set_cpus_allowed_ptr(current, cpumask_of(0));
 263        if (smp_processor_id() != 0) {
 264                dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
 265                        __func__);
 266                ret = -EBUSY;
 267                goto out;
 268        }
 269
 270        /* generate SMI */
 271        /* inb to force posted write through and make SMI happen now */
 272        asm volatile (
 273                "outb %b0,%w1\n"
 274                "inb %w1"
 275                : /* no output args */
 276                : "a" (smi_cmd->command_code),
 277                  "d" (smi_cmd->command_address),
 278                  "b" (smi_cmd->ebx),
 279                  "c" (smi_cmd->ecx)
 280                : "memory"
 281        );
 282
 283out:
 284        set_cpus_allowed_ptr(current, old_mask);
 285        free_cpumask_var(old_mask);
 286        return ret;
 287}
 288
 289/**
 290 * smi_request_store:
 291 *
 292 * The valid values are:
 293 * 0: zero SMI data buffer
 294 * 1: generate calling interface SMI
 295 * 2: generate raw SMI
 296 *
 297 * User application writes smi_cmd to smi_data before telling driver
 298 * to generate SMI.
 299 */
 300static ssize_t smi_request_store(struct device *dev,
 301                                 struct device_attribute *attr,
 302                                 const char *buf, size_t count)
 303{
 304        struct smi_cmd *smi_cmd;
 305        unsigned long val = simple_strtoul(buf, NULL, 10);
 306        ssize_t ret;
 307
 308        mutex_lock(&smi_data_lock);
 309
 310        if (smi_data_buf_size < sizeof(struct smi_cmd)) {
 311                ret = -ENODEV;
 312                goto out;
 313        }
 314        smi_cmd = (struct smi_cmd *)smi_data_buf;
 315
 316        switch (val) {
 317        case 2:
 318                /* Raw SMI */
 319                ret = dcdbas_smi_request(smi_cmd);
 320                if (!ret)
 321                        ret = count;
 322                break;
 323        case 1:
 324                /* Calling Interface SMI */
 325                smi_cmd->ebx = (u32) virt_to_phys(smi_cmd->command_buffer);
 326                ret = dcdbas_smi_request(smi_cmd);
 327                if (!ret)
 328                        ret = count;
 329                break;
 330        case 0:
 331                memset(smi_data_buf, 0, smi_data_buf_size);
 332                ret = count;
 333                break;
 334        default:
 335                ret = -EINVAL;
 336                break;
 337        }
 338
 339out:
 340        mutex_unlock(&smi_data_lock);
 341        return ret;
 342}
 343EXPORT_SYMBOL(dcdbas_smi_request);
 344
 345/**
 346 * host_control_smi: generate host control SMI
 347 *
 348 * Caller must set up the host control command in smi_data_buf.
 349 */
 350static int host_control_smi(void)
 351{
 352        struct apm_cmd *apm_cmd;
 353        u8 *data;
 354        unsigned long flags;
 355        u32 num_ticks;
 356        s8 cmd_status;
 357        u8 index;
 358
 359        apm_cmd = (struct apm_cmd *)smi_data_buf;
 360        apm_cmd->status = ESM_STATUS_CMD_UNSUCCESSFUL;
 361
 362        switch (host_control_smi_type) {
 363        case HC_SMITYPE_TYPE1:
 364                spin_lock_irqsave(&rtc_lock, flags);
 365                /* write SMI data buffer physical address */
 366                data = (u8 *)&smi_data_buf_phys_addr;
 367                for (index = PE1300_CMOS_CMD_STRUCT_PTR;
 368                     index < (PE1300_CMOS_CMD_STRUCT_PTR + 4);
 369                     index++, data++) {
 370                        outb(index,
 371                             (CMOS_BASE_PORT + CMOS_PAGE2_INDEX_PORT_PIIX4));
 372                        outb(*data,
 373                             (CMOS_BASE_PORT + CMOS_PAGE2_DATA_PORT_PIIX4));
 374                }
 375
 376                /* first set status to -1 as called by spec */
 377                cmd_status = ESM_STATUS_CMD_UNSUCCESSFUL;
 378                outb((u8) cmd_status, PCAT_APM_STATUS_PORT);
 379
 380                /* generate SMM call */
 381                outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
 382                spin_unlock_irqrestore(&rtc_lock, flags);
 383
 384                /* wait a few to see if it executed */
 385                num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
 386                while ((cmd_status = inb(PCAT_APM_STATUS_PORT))
 387                       == ESM_STATUS_CMD_UNSUCCESSFUL) {
 388                        num_ticks--;
 389                        if (num_ticks == EXPIRED_TIMER)
 390                                return -ETIME;
 391                }
 392                break;
 393
 394        case HC_SMITYPE_TYPE2:
 395        case HC_SMITYPE_TYPE3:
 396                spin_lock_irqsave(&rtc_lock, flags);
 397                /* write SMI data buffer physical address */
 398                data = (u8 *)&smi_data_buf_phys_addr;
 399                for (index = PE1400_CMOS_CMD_STRUCT_PTR;
 400                     index < (PE1400_CMOS_CMD_STRUCT_PTR + 4);
 401                     index++, data++) {
 402                        outb(index, (CMOS_BASE_PORT + CMOS_PAGE1_INDEX_PORT));
 403                        outb(*data, (CMOS_BASE_PORT + CMOS_PAGE1_DATA_PORT));
 404                }
 405
 406                /* generate SMM call */
 407                if (host_control_smi_type == HC_SMITYPE_TYPE3)
 408                        outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
 409                else
 410                        outb(ESM_APM_CMD, PE1400_APM_CONTROL_PORT);
 411
 412                /* restore RTC index pointer since it was written to above */
 413                CMOS_READ(RTC_REG_C);
 414                spin_unlock_irqrestore(&rtc_lock, flags);
 415
 416                /* read control port back to serialize write */
 417                cmd_status = inb(PE1400_APM_CONTROL_PORT);
 418
 419                /* wait a few to see if it executed */
 420                num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
 421                while (apm_cmd->status == ESM_STATUS_CMD_UNSUCCESSFUL) {
 422                        num_ticks--;
 423                        if (num_ticks == EXPIRED_TIMER)
 424                                return -ETIME;
 425                }
 426                break;
 427
 428        default:
 429                dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n",
 430                        __func__, host_control_smi_type);
 431                return -ENOSYS;
 432        }
 433
 434        return 0;
 435}
 436
 437/**
 438 * dcdbas_host_control: initiate host control
 439 *
 440 * This function is called by the driver after the system has
 441 * finished shutting down if the user application specified a
 442 * host control action to perform on shutdown.  It is safe to
 443 * use smi_data_buf at this point because the system has finished
 444 * shutting down and no userspace apps are running.
 445 */
 446static void dcdbas_host_control(void)
 447{
 448        struct apm_cmd *apm_cmd;
 449        u8 action;
 450
 451        if (host_control_action == HC_ACTION_NONE)
 452                return;
 453
 454        action = host_control_action;
 455        host_control_action = HC_ACTION_NONE;
 456
 457        if (!smi_data_buf) {
 458                dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __func__);
 459                return;
 460        }
 461
 462        if (smi_data_buf_size < sizeof(struct apm_cmd)) {
 463                dev_dbg(&dcdbas_pdev->dev, "%s: SMI buffer too small\n",
 464                        __func__);
 465                return;
 466        }
 467
 468        apm_cmd = (struct apm_cmd *)smi_data_buf;
 469
 470        /* power off takes precedence */
 471        if (action & HC_ACTION_HOST_CONTROL_POWEROFF) {
 472                apm_cmd->command = ) {
ETIME;
) {
 373 4     4                     (=apm_cmd" class="sref">apm_cmd->apm_cmd-&greserve"="+codeivers/firmware/dcdbas.c#L435" id="L435" class="li4e" name="L374"> 374 4     4        }
apm_cmd->apm_cmd-&gpar4apm_cmd-&gparmef="[0])code=u8" class="srese" name="L4_buf 375
4a hre47       host_control_smi(void)
 376 4     4        action & ETIME;
 377 4     4        apm_cmd->command = ) {
ETIME;
) {
 378 4     4        apm_cmd->apm_cmd-&greserve"="+codeivers/firmware/dcdbas.c#L435" id="L435" class="line" name="L379"> 379
4a hre47       return;
apm_cmd->apm_cmd-&gpar4apm_cmd-&gparmef="[0])code=u8" class="srese" name="L4_buf 380 4     4        host_control_smi(void)
 381 4     4         382 4     48="drivers/firmware/dcdbas.c#L343" id="L343"4class="li4e" name="L383"> 383
4a hre4="drivers/firmware/dcdbas.c#L384" id="L384"4class="li4e" name="L384"> 384 4     48ss="comment"> * shutting dohref="drivers/firmware/dcdbas.c#L438" id="L438" class="li4e" name="L385"> 385 4     48ss="comment"> */

 386 4     48ss="comment"> * host_control_ef="drivers/firmware/dcdbas.c#L471" id="L471" class="li4e" name="L387"> 387 4     4      href="+code=host_control_sntrol: reboot_notify>dcdbas_pdev->rtc_lock, notifier_bref""+code=apm_cmd" classf">inb( 388 4     4                apm_cmd-&gunuse""drivers/firmware/dcdbas.c#L452" id="L452" class="li4e" name="L389"> 389 4     4      vers/firmware/dcdbas.c#L472" id="L472" class="li4e" name="L390"> 390 4     4              f="+code=host_control_sass=>command =  391 4     4        }
command = SYS_DOWN    vers/firmware/dcdbas.c#L429" id="L429" class="li4e" name="L392"> 392 4     4        break;+code=HC_SMITYPE_TYPSYS_HAL">PE1400_APM_CONSYS_HAL"    vers/firmware/dcdbas.c#L429" id="L429" class="li4e" name="L393"> 393
4a hre49ase HC_ACTION_HOSTSYS_ 394 4     49       }
host_control_smi(void)
on_is safe of(srivers/firmware/dcdbas.c#L472" id="L472" class="li4e" name="L395"> 395 4     49       /* first set status #L472pan>goo usshutdown.  ction to perform on _ef="drivers/firmware/dcdbas.c#L471" id="L471" class="li4e" name="L396"> 396 4     4        rtc_lock, prcod"href=onum_ticks" claKERN_WARNef">TIMEOUT_USEC_SKERN_WARNef"+code=ring">"%s: SMI buPlecodesee i+codis safe  
 397 4     4        /* fi%s: SMI buorm on shurstpl/tc...>,
 398 4     4        dcdbas_host_control(void)
 399 4     4        for ( 400 5     5              401 5     50        402 5     5      ers/firmware/dcdbas.c#L467" id="L467"5c3ass="li5e" name="L393"> 393
5     5              ="+code=ret" class="srNOTIFY_DOf">HC_ACTION_NONENOTIFY_DOf""drivers/firmware/dcdbas.c#L469" id="L469"5class="li5e" name="L404"> 404 5     5      vers/firmware/dcdbas.c#L467" id="L467"5c5ass="li5e" name="L395"> 395 5a hre5="drivers/firmware/dcdbas.c#L406" id="L406"5class="li5e" name="L406"> 406 5     50id rtc_lock, notifier_bref""+cod=host_control_sntrol: reboot_n">inb( 407 5     5        if (rtc_lock, notifier_driv="+code= name="L2teOFFntrol: reboot_notify>dcdbas_pdev-> 408 5     5              .=cmd_status" clnex">dcdbas_smi_reqnex"="+code= name="L2teOFFNUL">ESM_STATUS_CMDNUL"hrefvers/firmware/dcdbas.c#L464" id="L464"5c9ass="li5e" name="L399"> 399 5     5        else
<.=cmd_status" clpriority>dcdbas_pdev 410 5     5      }vers/firmware/dcdbas.c#L469" id="L469"5class="li5e" name="L411"> 411
5a hre5="drivers/firmware/dcdbas.c#L412" id="L412"5class="li5e" name="L412"> 412 5     5       href="= name="L2teOFFDCDBAS_BIN_ATTR_RW>command = DCDBAS_BIN_ATTR_RWhref=onum_ticks" claa>;
smi_data_buf;
 413 5     51"drivers/firmware/dcdbas.c#L384" id="L384"5class="li5e" name="L414"> 414 5     5       href="="+code=apm_cmd" classbin_at#37but=>command = bin_at#37but="+code=apm_cmd" class>->apm_cmd-&g>-> 415
5a hre51       ;
smi_data_buf;
 416 5     51a href="+code=s8" class="sreNUL">ESM_STATUS_CMDNUL"hrefers/firmware/dcdbas.c#L464" id="L464"5class="li5e" name="L417"> 417 5     5      }vers/firmware/dcdbas.c#L469" id="L469"5class="li5e" name="L418"> 418
5a hre5="drivers/firmware/dcdbas.c#L419" id="L419"5class="li5e" name="L419"> 419 5     5       href="= name="L2teOFFDCDBAS_DEV_ATTR_RW>command = DCDBAS_DEV_ATTR_RWhref=onum_ticks" claa>;
smi_data_buf_size < sizeof(sivers/firmware/dcdbas.c#L465" id="L465"5class="li5e" name="L420"> 420 5     520     href="= name="L2teOFFDCDBAS_DEV_ATTR_RO>command = DCDBAS_DEV_ATTR_ROhref=onum_ticks" claa>;
smi_data_buf_phys_addr;
 421 5     5       href="= name="L2teOFFDCDBAS_DEV_ATTR_WO>command = DCDBAS_DEV_ATTR_WOhref=onum_ticks" claa>;
="sref">dcdbas_smi_req>);
 422 5     52      href="= name="L2teOFFDCDBAS_DEV_ATTR_RW>command = DCDBAS_DEV_ATTR_RWhref=onum_ticks" claction" class="sref">host_control_action =  423 5     5       href="= name="L2teOFFDCDBAS_DEV_ATTR_RW>command = DCDBAS_DEV_ATTR_RWhref=onum_ticks" claction" class=s="sref">host_control_smi_type);
 424 5     524     href="= name="L2teOFFDCDBAS_DEV_ATTR_RW>command = DCDBAS_DEV_ATTR_RWhref=onum_ticks" claction" class=on_is safe >host_control_smi(void)
on_is safe of(srvers/firmware/dcdbas.c#L431" id="L431"5class="li5e" name="L425"> 425 5     52"drivers/firmware/dcdbas.c#L406" id="L406"5class="li5e" name="L426"> 426 5     52id command = at#37but="+code=apm_cmd" class>->apm_cmd-&g>-> 427
5a hre527      ;
smi_data_buf_smp;;
command = at#3hrefvers/firmware/dcdbas.c#L464" id="L464"5class="li5e" name="L428"> 428 5     5default:
;
smi_data_buf_pmp;;
command = at#3hrefvers/firmware/dcdbas.c#L464" id="L464"5class="li5e" name="L429"> 429 5     5        ;
="sref">dcdbas_smi_reqmp;;
="sref"ef=".=cmd_status" clat#3>command = at#3hrefvers/firmware/dcdbas.c#L464" id="L464"5class="li5e" name="L430"> 430 5     5              +code=smi_data_buf_pmp;host_control_amp;command = at#3hrefvers/firmware/dcdbas.c#L464" id="L464"5class="li5e" name="L431"> 431 5     5        return+code=smi_data_buf_pmp;host_control_smp;command = at#3hrefvers/firmware/dcdbas.c#L464" id="L464"5class="li5e" name="L432"> 432 5     5}
host_control_smp;command = at#3hrefvers/firmware/dcdbas.c#L464" id="L464"5class="li5e" name="L433"> 433
5a hre53             =s8" class="sreNUL">ESM_STATUS_CMDNUL"hrefers/firmware/dcdbas.c#L464" id="L464"5class="li5e" name="L434"> 434 5     5return}vers/firmware/dcdbas.c#L469" id="L469"5class="li5e" name="L435"> 435}5 436
5a hre53id command = at#37but=_group"+cod=host_control_sntrol: at#3_group>command = ntrol: at#3_group="+codevers/firmware/dcdbas.c#L472" id="L472"5class="li5e" name="L437"> 437<5pan c53       if (apm_cmd-&gat#3bef="ode= name="L2teOFFntrol: mp;apm_cmd-&g>-> 438<5pan c5ass="c}vers/firmware/dcdbas.c#L469" id="L469"5class="li5e" name="L439"> 439<5pan c53"drivers/firmware/dcdbas.c#L470" id="L470"5class="li5e" name="L440"> 440<5pan c540     href="code=host_control_s_apm_cmd-&g_host_control_smtrol: prob"href=="+code=apm_cmd" classplatwn. host_control_splatwn. f">dev,  441<5pan c5ass="cvers/firmware/dcdbas.c#L472" id="L472"5class="li5e" name="L442"> 442<5pan c54f (host_control_si+cod, =host_control_serro3>command = erro3"drivers/firmware/dcdbas.c#L469" id="L469"5class="li5e" name="L443"> 443<5pan c54"drivers/firmware/dcdbas.c#L384" id="L384"5class="li5e" name="L444"> 444<5pan c54a href="+code=action" class=ction" class="sref">host_control_action = HC_ACTION_NONE;
 445<5pan c54a href="+code=host_control_action" class=s="sref">host_control_smi_type == HC_ACTION_NONE 446s5atic 54"drivers/firmware/dcdbas.c#L457" id="L457"5class="li5e" name="L447"> 447{5/* first set staef="driers/firmware/dcdbas.c#L471" id="L471"5class="li5e" name="L448"> 448 5     54ss="comment"> * dcdbas_host_________* BIOSo smadrivs ="srireall\n&quan>

 449 5     54ss="comment"> *

e no us finDMA mask belowef="drivers/firmware/dcdbas.c#L445" id="L445"5class="li5e" name="L450"> 450
5a hre55ss="comment"> * This functio________*ef="drivers/firmware/dcdbas.c#L471" id="L471"5class="li5e" name="L451"> 451 5     5if (dcdbas_pdev->dev, command = ;
command = D>;
 452 5     5        return=host_control_sntrol: pef">dcdbas_pdev->dev, command = dma_maskf="+coe+code=dcdbas_pdev" class="sref">dcdbas_pdev->dev, command =  453
5a hre5="drivers/firmware/dcdbas.c#L454" id="L454"5class="li5e" name="L454"> 454 5     5command = erro3"dricoe=HC_SMITYPE_TYPsysfs_creat=_group>command = sysfs_creat=_grouphref=+code=smi_data_buf_pmp;>dev, dev, dev,  455 5     5 456
5a hre55        457 5     55"drivers/firmware/dcdbas.c#L468" id="L468"5class="li5e" name="L458"> 458 5     5         459 5     5        return;
command = erro3"dricoe=HC_SMITYPE_TYPsysfs_creat=_bin_fil">smi_data_buf_siysfs_creat=_bin_fil"href=+code=smi_data_buf_pmp;>dev, dev, dev,  460 5     56                       return -apm_cmd-&g>-> 461
5a hre56       return -command = erro3"drivivers/firmware/dcdbas.c#L402" id="L402"5class="li5e" name="L462"> 462 5     56               host_control_si+codocodedeivers/firmware/dcdbas.c#L452" id="L452"5class="li5e" name="L463"> 463 5     5        smi_data_buf_siysfs_remov=_bin_fil"href=+code=smi_data_buf_pmp;>dev, dev, dev,  464 5     5                apm_cmd-&g>-> 465 5     5        return;
command = sysfs_remov=_grouphref=+code=smi_data_buf_pmp;>dev, dev, dev,  466 5     56        467
5a hre56        468 5     5 469
5a hre5="drivers/firmware/dcdbas.c#L470" id="L470"5class="li5e" name="L470"> 470 5     5inb( 471 5     57"drivers/firmware/dcdbas.c#L412" id="L412"5class="li5e" name="L472"> 472 5     57       return=host_control_snev_info>host_control_smp;dev, dev, "%s: SMI buffer t (dcdb on ffer t)>,
 373 5     5                     (e=HC_SMITYPE_TYPDRIVER_DESCRIP
command = DRIVER_DESCRIP
command = DRIVER_VERS 374 5     5      ers/firmware/dcdbas.c#L431" id="L431"5class="li5e" name="L375"> 375
5a hre57        376 5     5      vers/firmware/dcdbas.c#L467" id="L467"5class="li5e" name="L377"> 377 5     57"drivers/firmware/dcdbas.c#L468" id="L468"5class="li5e" name="L378"> 378 5     5       href="code=host_control_s_apm_cmd-&g_inb(host_control_splatwn. f">dev,  379
5a hre57     vers/firmware/dcdbas.c#L472" id="L472"5class="li5e" name="L380"> 380 5     5        host_control_si+codvers/firmware/dcdbas.c#L435" id="L435"5class="li5e" name="L381"> 381 5     58"drivers/firmware/dcdbas.c#L412" id="L412"5class="li5e" name="L382"> 382 5     58       return=host_control_sunregistercommand = unregisterinb( 383
5a hre58             +code=index" class="s>host_control_si+cododeivn=host_control_sntrol: bin_at#3b>apm_cmd-&g>-> 384 5     58       smi_data_buf_siysfs_remov=_bin_fil"href=+code=smi_data_buf_pmp;>dev, dev, dev, apm_cmd-&g>-> 385 5     58a href="+code=host_control_aiysfs_remov=_group>command = sysfs_remov=_grouphref=+code=smi_data_buf_pmp;>dev, dev, dev,  386 5     58"drivers/firmware/dcdbas.c#L457" id="L457"5class="li5e" name="L387"> 387 5     58        388 5     5      vers/firmware/dcdbas.c#L467" id="L467"5class="li5e" name="L389"> 389 5     58"drivers/firmware/dcdbas.c#L470" id="L470"5class="li5e" name="L390"> 390 5     590     href="="+code=apm_cmd" classplatwn. host_control_splatwn. host_control_sntrol: me/dcd+cododevers/firmware/dcdbas.c#L472" id="L472"5class="li5e" name="L391"> 391 5     5        }
host_control_sne/dcd+codooooooooodevers/firmware/dcdbas.c#L472" id="L472"5class="li5e" name="L392"> 392 5     59               host_control_sn2ETIME;
 393
5a hre59                    (.=cmd_status" clowncd>host_control_sowncd      de=TIMEOUT_USEC_SHHIS_MODUL">ETIME;
 394 5     59       }
 395 5     59       host_control_sprob"href         (de= name="L2teOFFntrol: prob">host_control_smtrol: prob"href,ers/firmware/dcdbas.c#L402" id="L402"5class="li5e" name="L396"> 396 5     5        inb(command = _inb( 397 5     59     }vers/firmware/dcdbas.c#L469" id="L469"5class="li5e" name="L398"> 398 5     59"drivers/firmware/dcdbas.c#L419" id="L419"5class="li5e" name="L399"> 399 5     59ss="comment"> *
 400 6     60ss="comment"> * This function ntrol: contt contro/spanne/dcd+c"drivers/firmware/dcdbas.c#L438" id="L438"6c1ass="li6e" name="L391"> 391 6     60ss="comment"> * finished shutef="drivers/firmware/dcdbas.c#L471" id="L471"6class="li6e" name="L402"> 402 6     60      href="code=host_control_s_apm_cmd-&g_apm_cmd-&gntrol: conthref="drivers/firmware/dcdbas.c#L447" id="L447"6c3ass="li6e" name="L393"> 393
6     6      vers/firmware/dcdbas.c#L472" id="L472"6class="li6e" name="L404"> 404 6     60       }
command = erro3"drivers/firmware/dcdbas.c#L469" id="L469"6c5ass="li6e" name="L395"> 395 6a hre6="drivers/firmware/dcdbas.c#L406" id="L406"6class="li6e" name="L406"> 406 6     60a href="+code=s8" class="sreerro3>command = erro3"dricoe=HC_SMITYPE_TYPplatwn. host_control_splatwn. host_control_sntrol: me/dcd+codrvers/firmware/dcdbas.c#L431" id="L431"6class="li6e" name="L407"> 407 6     60f (! 408 6     60        399 6     60"drivers/firmware/dcdbas.c#L470" id="L470"6class="li6e" name="L410"> 410 6     61span class="coret" class="srlass="sref">dcdbas_pdev->host_control_splatwn. ETIME;
 411
6a hre61f (dcdbas_pdev-> 412 6     61       command = erro3"dricoee=ENOSYS" class="srMEM>command = "srMEM"drivers/firmware/dcdbas.c#L469" id="L469"6class="li6e" name="L413"> 413 6     61                    (gotoe=apm_cmd" classerr_unregisterhost_control_serr_unregister 414 6     61       }
 415
6a hre61"drivers/firmware/dcdbas.c#L406" id="L406"6class="li6e" name="L416"> 416 6     61a href="+code=s8" class="sreerro3>command = erro3"dricoe=HC_SMITYPE_TYPplatwn. apm_cmd-&gplatwn. dcdbas_pdev-> 417 6     61f (! 418
6a hre61       host_control_serr_free 419 6     61"drivers/firmware/dcdbas.c#L470" id="L470"6class="li6e" name="L420"> 420 6     62span class="cref="drivers/firmware/dcdbas.c#L435" id="L435"6class="li6e" name="L421"> 421 6     62"drivers/firmware/dcdbas.c#L412" id="L412"6class="li6e" name="L422"> 422 6     62     e=apm_cmd" classerr_freehost_control_serr_free 423 6     62             =s8" class="sreplatwn. apm_cmd-&gplatwn. dcdbas_pdev-> 424 6     624    e=apm_cmd" classerr_unregisterhost_control_serr_unregister 425 6     62a href="+code=host_control_aplatwn. host_control_splatwn. host_control_sntrol: me/dcd+codrvers/firmware/dcdbas.c#L431" id="L431"6class="li6e" name="L426"> 426 6     626pan class="cref="dr=ret" class="srerro3>command = erro3"drivers/firmware/dcdbas.c#L469" id="L469"6class="li6e" name="L427"> 427
6a hre627    }ers/firmware/dcdbas.c#L469" id="L469"6class="li6e" name="L428"> 428 6     62"drivers/firmware/dcdbas.c#L419" id="L419"6class="li6e" name="L429"> 429 6     62ss="comment"> *
 430 ss="li5e" name="L263> * This function ntrol: contt controhost:on to perL438" unceanfirmmware/dcdbas.c#L438" id="L438"6L464" id=6e" name="L421"> 431 5     5     6  ret63> * finished shutef="drivers/firmware/dcdbas.c#L471" id="L471"6class="li6e" name="L462"> 432 5     5}
-&g_inb-&g_inbs/firmware/dcdbas.c#L447" id="L447"6c3ass="li6e" name="L463"> 433
5a hre53    6     63rmware/dcdbas.c#L472" id="L472"6class="li6e" name="L464"> 434 5     5retur6}vers63e=action" clasrst set staef="driers/firmware/dcdbas.c#L471" id="L471"5class="li5e6 name="L465"> 435}5 */
 436
5a hre53id <6 href63> * host_control_ef="driversbbbbbbbb* beo pe cc"_puthref==hosef=+code=smimware/dcdbas.c#L471" id="L471"5class="li5e6 name="L427"> 437<5pan c53    6  if 6 438<5pan c5ass="6}vers63e=apm_cmd" class="sref">apm_eboot_notifie3>command = unregisterinb( 439<5pan c53"dri6ers/f6rmware/dcdbas.c#L470" id="L470"5class="li5e6 name="L460"> 440<5pan c540   6 href64comment">/* power off takes precedencirmware/dcdbas.c#L471" id="L471"5class="li5e6 name="L461"> 441<5pan c5ass="6vers/64> * finished shutef="driversbbbbbbbb* We have...>drivk bela es beaskf innotad ofot_notify:s/firmmware/dcdbas.c#L471" id="L471"5class="li5e6 name="L462"> 442<5pan c54f (<6 href6"+codeost_control_ef="driversbbbbbbbb* because onlyn>
 ers/HC_A w5rean ifnsure thatrmmware/dcdbas.c#L471" id="L471"5class="li5e6 name="L463"> 443<5pan c54"dri6ers/f6rmwareost_control_ef="driversbbbbbbbb* all _grou oup"+cod=siversng.  ctiotan>
module have.beenrmmware/dcdbas.c#L471" id="L471"5class="li5e6 name="L464"> 444<5pan c54a hr6f="+c64> * shutting dohref="driversbbbbbbbb* recodisdfirmware/dcdbas.c#L445" id="L445"5class="li5e6 name="L465"> 445<5pan c54a hr6f="+c64> */
 446s5atic 54"dri6ers/f64e=s8" class="sreerro3>commansss="sref"ef=driv = sysfs_remov=_ss="sref"ef=drivmi_dare/dcdbas.c#L431" id="L431"5class="li5e6 name="L467"> 447{5/* fireplatwn. apm_cmddcdbas_pdev-> 448 5     54ss="6ommen64e=apm_cmd" class="sref">apm_dcd_unregister>host_control_splatwn. host_control_sntrol: me/dcd+codrvers/firmware/dcdbas.c#L431" id="L431"6class="li6e" name="L469"> 449 5     54ss="6ommen6"> * 450
5a hre55ss="6ommen6"> * T/dcdbas.c#L469" id="L469"6class="li6e" name="L461"> 451 5     5if (<6 href6"+=hosf_pmtrol: me/dcmoduled-&gntrol: conthmoduledmitrol_sntrol: ref">dcdbas_-&gntrol: conthref="drivers/fire/dcdbas.c#L431" id="L431"6class="li6e" name="L462"> 452 5     5     6  ret6rn=hosf_pmtrol: me/dcmoduled-&g_mitrol_sntrol: ref">dcdbas_-&g_inbs/fire/dcdbas.c#L431" id="L431"6class="li6e" name="L463"> 453
5a hre5="dri6ers/f6rmware/dcdbas.c#L454" id="L454"5class="li5e6 name="L464"> 454 5     5rs/fir>command = DRIVER_DESCRrs/fir>commandontrol_sDRIVER_NAf">ETIME = DRIVER_DESCRIP
,
command = DRIVER_VERS 455 5     5rs/fir>and = DRIVER_VERSandontrol_sDRIVER_NAf">ETIME = DRIVER_VERS 456
5a hre55    6  rs/fir>AUTHOR = DRIVER_VERSAUTHORontrol%s: SMI buffer t (dcdbDell Inc.iivers/firmware/dcdbas.c#L465" id="L465" class="li4e6 name="L467"> 457 5     55"dri6ers/f6rmwarel_sntrol: ref">rs/fir>LICENS
LICENS
ontrol%s: SMI buffer t (dcdbGPLiivers/firmware/dcdbas.c#L465" id="L465" class="li4e6 name="L468"> 458 5     5     6   * dcdbas_host_________* B/* Any Syde=m orivs ="hosim.  ctiobs finDell *firmware/dcdbas.c#L471" id="L471"5class="li5e6 name="L469"> 459 5     5     6  ret6rn;
rs/fir>ALIAS = DRIVER_VERSALIASontrol%s: SMI buffer t (dcdbdmi:*:[bs]vnD[Ee][Ll][Ll]*:*iivers/firmware/dcdbas.c#L465" id="L465" class="li4e6 name="L460"> 460 5     56    6     6      
fersrol> Tbelorig. al LXR soft65" fin beldcdbas.c#http://sourceo pge.net/projects/lxol>LXR ____unname="L,otan> experi___*al t)>, lxo@ 5 ux.noe="L.
subfersrol> lxo. 5 ux.no kindlyn== Redpill L5 pro ASontr, provid beofoL5 ux on sul maskand operaHC_As eive=hos eince 1995.