1/*
2 * Copyright (c) 2001-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23#include "AppleRAID.h"
24
25#define super AppleRAIDSet
26OSDefineMetaClassAndStructors(AppleRAIDStripeSet, AppleRAIDSet);
27
28AppleRAIDSet * AppleRAIDStripeSet::createRAIDSet(AppleRAIDMember * firstMember)
29{
30    AppleRAIDStripeSet *raidSet = new AppleRAIDStripeSet;
31
32    IOLog1("AppleRAIDStripeSet::createRAIDSet(%p) called, new set = %p  *********\n", firstMember, raidSet);
33
34    while (raidSet){
35
36	if (!raidSet->init()) break;
37	if (!raidSet->initWithHeader(firstMember->getHeader(), true)) break;
38	if (raidSet->resizeSet(raidSet->getMemberCount())) return raidSet;
39
40	break;
41    }
42
43    if (raidSet) raidSet->release();
44
45    return 0;
46}
47
48
49bool AppleRAIDStripeSet::init()
50{
51    IOLog1("AppleRAIDStripeSet::init() called\n");
52
53    if (super::init() == false) return false;
54
55    setProperty(kAppleRAIDLevelNameKey, kAppleRAIDLevelNameStripe);
56
57    arAllocateRequestMethod = OSMemberFunctionCast(IOCommandGate::Action, this, &AppleRAIDSet::allocateRAIDRequest);
58
59    return true;
60}
61
62void AppleRAIDStripeSet::free(void)
63{
64    super::free();
65}
66
67//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
68//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
69//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
70
71bool AppleRAIDStripeSet::addSpare(AppleRAIDMember * member)
72{
73    if (super::addSpare(member) == false) return false;
74
75    member->changeMemberState(kAppleRAIDMemberStateBroken);
76
77    return true;
78}
79
80bool AppleRAIDStripeSet::addMember(AppleRAIDMember * member)
81{
82    if (super::addMember(member) == false) return false;
83
84    // block count = # of stripes * per member block count
85    OSNumber * number = OSDynamicCast(OSNumber, member->getHeaderProperty(kAppleRAIDChunkCountKey));
86    if (!number) return false;
87    arSetBlockCount = number->unsigned64BitValue() * arMemberCount;
88    arSetMediaSize = arSetBlockCount * arSetBlockSize;
89
90    return true;
91}
92
93bool AppleRAIDStripeSet::startSet(void)
94{
95    if (super::startSet() == false) return false;
96
97    // scale up these properties by the member count of the stripe
98    setSmallest64BitMemberPropertyFor(kIOMaximumBlockCountReadKey, arMemberCount);
99    setSmallest64BitMemberPropertyFor(kIOMaximumBlockCountWriteKey, arMemberCount);
100    setSmallest64BitMemberPropertyFor(kIOMaximumByteCountReadKey, arMemberCount);
101    setSmallest64BitMemberPropertyFor(kIOMaximumByteCountWriteKey, arMemberCount);
102
103    setSmallest64BitMemberPropertyFor(kIOMaximumSegmentCountReadKey, arMemberCount);
104    setSmallest64BitMemberPropertyFor(kIOMaximumSegmentCountWriteKey, arMemberCount);
105
106    return true;
107}
108
109AppleRAIDMemoryDescriptor * AppleRAIDStripeSet::allocateMemoryDescriptor(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex)
110{
111    return AppleRAIDStripeMemoryDescriptor::withStorageRequest(storageRequest, memberIndex);
112}
113
114// AppleRAIDStripeMemoryDescriptor
115// AppleRAIDStripeMemoryDescriptor
116// AppleRAIDStripeMemoryDescriptor
117
118#undef super
119#define super AppleRAIDMemoryDescriptor
120OSDefineMetaClassAndStructors(AppleRAIDStripeMemoryDescriptor, AppleRAIDMemoryDescriptor);
121
122AppleRAIDMemoryDescriptor *
123AppleRAIDStripeMemoryDescriptor::withStorageRequest(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex)
124{
125    AppleRAIDMemoryDescriptor *memoryDescriptor = new AppleRAIDStripeMemoryDescriptor;
126
127    if (memoryDescriptor != 0) {
128        if (!memoryDescriptor->initWithStorageRequest(storageRequest, memberIndex)) {
129            memoryDescriptor->release();
130            memoryDescriptor = 0;
131        }
132    }
133
134    return memoryDescriptor;
135}
136
137bool AppleRAIDStripeMemoryDescriptor::initWithStorageRequest(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex)
138{
139    if (!super::initWithStorageRequest(storageRequest, memberIndex)) return false;
140
141    mdMemberCount = storageRequest->srMemberCount;
142    mdSetBlockSize = storageRequest->srSetBlockSize;
143
144    return true;
145}
146
147bool AppleRAIDStripeMemoryDescriptor::configureForMemoryDescriptor(IOMemoryDescriptor *memoryDescriptor, UInt64 byteStart, UInt32 activeIndex)
148{
149    UInt32 byteCount = memoryDescriptor->getLength();
150    UInt32 blockCount, memberBlockCount;
151    UInt64 memberBlockStart, setBlockStop;
152    UInt32 setBlockEndOffset;
153    UInt32 startMember, stopMember;
154
155    mdSetBlockStart	= byteStart / mdSetBlockSize;
156    mdSetBlockOffset	= byteStart % mdSetBlockSize;
157    setBlockStop	= (byteStart + byteCount - 1) / mdSetBlockSize;
158    setBlockEndOffset	= (byteStart + byteCount - 1) % mdSetBlockSize;
159    blockCount		= setBlockStop - mdSetBlockStart + 1;
160    memberBlockCount	= blockCount / mdMemberCount;
161    memberBlockStart	= mdSetBlockStart / mdMemberCount;
162    startMember		= mdSetBlockStart % mdMemberCount;
163    stopMember		= setBlockStop % mdMemberCount;
164
165    // per member stuff
166    assert(mdMemberIndex == activeIndex);
167    if (((mdMemberCount + mdMemberIndex - startMember) % mdMemberCount) < (blockCount % mdMemberCount)) memberBlockCount++;
168
169    if (startMember > mdMemberIndex) memberBlockStart++;
170
171    mdMemberByteStart = memberBlockStart * mdSetBlockSize;
172    _length = memberBlockCount * mdSetBlockSize;
173
174    if (startMember == mdMemberIndex) {
175        mdMemberByteStart += mdSetBlockOffset;
176        _length -= mdSetBlockOffset;
177    }
178
179    if (stopMember == mdMemberIndex) _length -= mdSetBlockSize - setBlockEndOffset - 1;
180
181    mdMemoryDescriptor = memoryDescriptor;
182
183    _flags = (_flags & ~kIOMemoryDirectionMask) | memoryDescriptor->getDirection();
184
185    return _length != 0;
186}
187
188addr64_t AppleRAIDStripeMemoryDescriptor::getPhysicalSegment(IOByteCount offset, IOByteCount *length, IOOptionBits options)
189{
190    UInt32		memberBlockStart = (mdMemberByteStart + offset) / mdSetBlockSize;
191    UInt32		memberBlockOffset = (mdMemberByteStart + offset) % mdSetBlockSize;
192    UInt32		setBlockNumber = memberBlockStart * mdMemberCount + mdMemberIndex - mdSetBlockStart;
193    IOByteCount		setOffset = setBlockNumber * mdSetBlockSize + memberBlockOffset - mdSetBlockOffset;
194    addr64_t		physAddress;
195
196    physAddress = mdMemoryDescriptor->getPhysicalSegment(setOffset, length, options);
197
198    memberBlockOffset = mdSetBlockSize - memberBlockOffset;
199    if (length && (*length > memberBlockOffset)) *length = memberBlockOffset;
200
201    return physAddress;
202}
203