1/*
2 * Copyright (c) 1998-2008 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#include <IOKit/IOLib.h>
30#include "AppleNVRAM.h"
31
32
33#define super IONVRAMController
34OSDefineMetaClassAndStructors(AppleNVRAM, IONVRAMController);
35
36
37// ****************************************************************************
38// start
39//
40// ****************************************************************************
41bool AppleNVRAM::start(IOService *provider)
42{
43  IOItemCount numRanges;
44  IOMemoryMap *map;
45
46  numRanges = provider->getDeviceMemoryCount();
47
48  if (numRanges == 1) {
49    _nvramType = kNVRAMTypeIOMem;
50
51    // Get the address of the data register.
52    map = provider->mapDeviceMemoryWithIndex(0);
53    if (map == 0) return false;
54    _nvramData = (UInt8 *)map->getVirtualAddress();
55
56  } else if (numRanges == 2) {
57    _nvramType = kNVRAMTypePort;
58
59    // Get the address of the port register.
60    map = provider->mapDeviceMemoryWithIndex(0);
61    if (map == 0) return false;
62    _nvramPort = (UInt8 *)map->getVirtualAddress();
63
64    // Get the address of the data register.
65    map = provider->mapDeviceMemoryWithIndex(1);
66    if (map == 0) return false;
67    _nvramData = (UInt8 *)map->getVirtualAddress();
68
69  } else {
70    return false;
71  }
72
73  return super::start(provider);
74}
75
76// ****************************************************************************
77// read
78//
79// Read data from the NVRAM and return it in buffer.
80//
81// ****************************************************************************
82IOReturn AppleNVRAM::read(IOByteCount offset, UInt8 *buffer,
83			  IOByteCount length)
84{
85  UInt32 cnt;
86
87  // length and offset can't be less than zero (unsigned), so we don't check
88  if ((buffer == 0) || (length == 0) || (offset + length > kNVRAMImageSize))
89    return kIOReturnBadArgument;
90
91  switch (_nvramType) {
92  case kNVRAMTypeIOMem :
93    for (cnt = 0; cnt < length; cnt++) {
94      buffer[cnt] = _nvramData[(offset + cnt)  << 4];
95    }
96    break;
97
98  case kNVRAMTypePort:
99    for (cnt = 0; cnt < length; cnt++) {
100      *_nvramPort = (offset + length) >> 5;
101      eieio();
102      buffer[cnt] = _nvramData[((offset + length) & 0x1F) << 4];
103    }
104    break;
105
106  default :
107    return kIOReturnNotReady;
108  }
109
110  return kIOReturnSuccess;
111}
112
113
114// ****************************************************************************
115// write
116//
117// Write data from buffer into NVRAM.
118//
119// ****************************************************************************
120IOReturn AppleNVRAM::write(IOByteCount offset, UInt8 *buffer,
121			   IOByteCount length)
122{
123  UInt32 cnt;
124
125  // length and offset can't be less than zero (unsigned), so we don't check
126  if ((buffer == 0) || (length == 0) || (offset + length > kNVRAMImageSize))
127    return kIOReturnBadArgument;
128
129  switch (_nvramType) {
130  case kNVRAMTypeIOMem :
131    for (cnt = 0; cnt < length; cnt++) {
132      _nvramData[(offset + cnt)  << 4] = buffer[cnt];
133      eieio();
134    }
135    break;
136
137  case kNVRAMTypePort:
138    for (cnt = 0; cnt < length; cnt++) {
139      *_nvramPort = (offset + length) >> 5;
140      eieio();
141      _nvramData[((offset + length) & 0x1F) << 4] = buffer[cnt];
142      eieio();
143    }
144    break;
145
146  default :
147    return kIOReturnNotReady;
148  }
149
150  return kIOReturnSuccess;
151}
152