|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /* IOStub.m 1.0 01/29/91 (c) 1991 NeXT
25: *
26: * IOStub.m - Implementation for trivial I/O device subclass.
27: *
28: * HISTORY
29: * 29-Jan-91 Doug Mitchell at NeXT
30: * Created.
31: */
32:
33: #import "IOStub.h"
34: #import "IOStubThread.h"
35: #import "IOStubPrivate.h"
36: #import <bsd/sys/types.h>
37: #import <driverkit/deviceCommon.h>
38: #import <driverkit/libIO.h>
39: #import <mach/mach_user_internal.h>
40: #import <bsd/sys/param.h>
41: #import <mach/vm_param.h>
42: #import <bsd/dev/ldd.h>
43: #import <mach/mach_interface.h>
44: #import <machkit/NXLock.h>
45:
46: #define STUB_BLOCK_SIZE 1024
47:
48: @implementation IOStub
49:
50: /*
51: * Probe hardware for specified unit.
52: */
53: + stubProbe :(int)Unit
54: {
55: id stubId;
56: int rtn;
57:
58: xpr_stub("stubProbe unit %d\n", Unit, 2,3,4,5);
59: if(Unit >= NUM_IOSTUBS) {
60: IOLog("stubProbe: bogus Unit (%d)\n", Unit);
61: return(nil);
62: }
63: stubId = [self alloc];
64: if(rtn = [stubId stubInit:Unit]) {
65: xpr_stub("stubProbe: stubInit returned %d; aborting\n",
66: rtn, 2,3,4,5);
67: [stubId free];
68: return nil;
69: }
70:
71: [stubId registerDevice];
72: return(stubId);
73: }
74:
75: /*
76: * Initialize current instance. Returns non-zero on error.
77: */
78: - (int)stubInit :(int)Unit
79: {
80: u_int block_size, dev_size;
81:
82: xpr_stub("stubInit Unit %d\n", Unit, 2,3,4,5);
83: [self setUnit:Unit];
84: if(Unit == 0) {
85: /*
86: * read/write.
87: */
88: [self setWriteProtected:NO];
89: block_size = STUB_BLOCK_SIZE;
90: dev_size = 0x1000;
91: [self setDeviceName : "IOStub0"];
92: }
93: else {
94: /*
95: * Make this one read-only.
96: */
97: [self setWriteProtected:YES];
98: block_size = STUB_BLOCK_SIZE;
99: dev_size = 0x800;
100: [self setDeviceName : "IOStub1"];
101: }
102: [self setDeviceType:"Stub Device"];
103: [self setDriveName:"Stub Device"];
104: [self setLocation:NULL];
105: [self setBlockSize:block_size];
106: [self setDeviceSize:dev_size];
107: [self setFormattedInt:1];
108:
109:
110: /*
111: * Set up our instance's IOQueue.
112: */
113: queueLock = [NXConditionLock new];
114: [queueLock initWith:NO_WORK_AVAILABLE];
115: queue_init(&ioQueue);
116:
117: /*
118: * Start up an I/O thread to perform the actual work of this device.
119: */
120: IOForkThread((IOThreadFcn)IOStub_thread, self);
121:
122: [self initBufs];
123:
124: /*
125: * Let superclass take care of initializing inherited instance
126: * variables.
127: */
128: [super init];
129: xpr_stub("stubInit returning success\n", 1,2,3,4,5);
130: return(0);
131: }
132:
133: /*
134: * Free resources consumed by this instance.
135: */
136: - free
137: {
138: int data_size;
139: unsigned block_size, dev_size;
140: IOBuf *IOBuf;
141:
142: /*
143: * Kill the I/O thread.
144: */
145: IOBuf = IOMalloc(sizeof(*IOBuf));
146: IOBuf->cmd = STUB_ABORT;
147: IOBuf->waitLock = [NXConditionLock alloc];
148: [IOBuf->waitLock initWith:NO];
149: IOBuf->device = self;
150: [self enqueueIoBuf:IOBuf];
151: [IOBuf->waitLock lockWhen:YES];
152: [IOBuf->waitLock free];
153: IOFree(IOBuf, sizeof(*IOBuf));
154:
155: /*
156: * Free our "device" memory..
157: */
158: block_size = [self blockSize];
159: dev_size = [self deviceSize];
160: data_size = block_size * dev_size;
161: IOFree(stub_data, data_size);
162: [queueLock free];
163: return([super free]);
164: }
165:
166: /*
167: * Initialize "device memory".
168: */
169: - (int)initBufs
170: {
171: int data_size;
172: char *cp;
173: int i;
174:
175: /*
176: * allocate and initialize data for writing and reading.
177: */
178: data_size = [self blockSize] * [self deviceSize];
179: stub_data = IOMalloc(data_size);
180: if(stub_data == NULL) {
181: IOLog("***IOStub init: IOMalloc returned NULL");
182: return 1;
183: }
184:
185: /*
186: * initial data: incrementing bytes for unit 0, decrementing
187: * bytes for others.
188: */
189: cp = stub_data;
190: for(i=0; i<data_size; i++) {
191: if([self unit])
192: *cp++ = 0 - (char)i;
193: else
194: *cp++ = i;
195: }
196: return 0;
197: }
198:
199: /*
200: * These are the exported I/O methods, from the DiskDeviceRw category.
201: * Their main task is:
202: *
203: * -- verify valid input parameters.
204: * -- set up and enqueue an IOBuf for servicing by the I/O thread.
205: * -- Wait for I/O complete if synchronous request.
206: */
207:
208: - (IOReturn) readAt : (unsigned)offset
209: length : (unsigned)length
210: buffer : (out unsigned char *)buffer
211: actualLength : (out unsigned *)actualLength
212: client : (vm_task_t)client
213: {
214: IOReturn mrtn;
215: char *source;
216: IOBuf *IOBuf;
217: u_int block_size;
218: u_int dev_size;
219:
220: xpr_stub("IOStub read: unit %d offset 0x%x length 0x%x\n",
221: [self unit], offset, length, 4,5);
222:
223: block_size = [self blockSize];
224: dev_size = [self deviceSize];
225:
226: /*
227: * Verify legal parameters.
228: */
229: source = stub_data + offset * block_size;
230: if((source + length) > (stub_data + (block_size * dev_size))) {
231:
232: xpr_stub("IOStub read: invalid offset/byte count\n",
233: 1,2,3,4,5);
234: return(IO_R_INVALIDARG);
235: }
236:
237: /*
238: * OK, queue up an IOBuf.
239: */
240: IOBuf = IOMalloc(sizeof(*IOBuf));
241: IOBuf->cmd = STUB_READ;
242: IOBuf->offset = offset;
243: IOBuf->bytesReq = length;
244: IOBuf->buf = buffer;
245: IOBuf->bytesXfr = 0;
246: IOBuf->status = IO_R_INVALID;
247: IOBuf->pending = NULL;
248: IOBuf->waitLock = [NXConditionLock alloc];
249: [IOBuf->waitLock initWith:NO];
250: IOBuf->device = self;
251: IOBuf->dirRead = 1;
252: IOBuf->client = IOVmTaskSelf();
253: [self enqueueIoBuf:IOBuf];
254:
255: /*
256: * Wait for I/O complete.
257: */
258: [IOBuf->waitLock lockWhen:YES];
259: xpr_stub("stub read: DONE\n", 1,2,3,4,5);
260: mrtn = IOBuf->status;
261: *actualLength = IOBuf->bytesXfr;
262: [IOBuf->waitLock free];
263: IOFree(IOBuf, sizeof(*IOBuf));
264: return(mrtn);
265: }
266:
267: - (IOReturn) readAsyncAt : (unsigned)offset
268: length : (unsigned)length
269: buffer : (out unsigned char *)buffer
270: pending : (unsigned)pending
271: client : (vm_task_t)client
272: {
273: char *source;
274: IOBuf *IOBuf;
275: u_int block_size;
276: u_int dev_size;
277:
278: xpr_stub("IOStub readAsync: unit %d offset 0x%x length 0x%x\n",
279: [self unit], offset, length, 4,5);
280:
281: block_size = [self blockSize];
282: dev_size = [self deviceSize];
283:
284: /*
285: * Verify legal parameters.
286: */
287: source = stub_data + offset * block_size;
288: if((source + length) > (stub_data + (block_size * dev_size))) {
289:
290: xpr_stub("IOStub read: invalid offset/byte count\n",
291: 1,2,3,4,5);
292: return(IO_R_INVALIDARG);
293: }
294:
295: /*
296: * Just queue up an IOBuf.
297: */
298: IOBuf = IOMalloc(sizeof(*IOBuf));
299: IOBuf->cmd = STUB_READ;
300: IOBuf->offset = offset;
301: IOBuf->bytesReq = length;
302: IOBuf->buf = buffer;
303: IOBuf->status = IO_R_INVALID; /* must be filled in by
304: * I/O thread */
305: IOBuf->pending = (void *)pending;
306: IOBuf->device = self;
307: IOBuf->dirRead = 1;
308: IOBuf->client = client;
309: [self enqueueIoBuf:IOBuf];
310:
311: xpr_stub("stub readAsync: DONE\n", 1,2,3,4,5);
312: return(IO_R_SUCCESS);
313: }
314:
315: - (IOReturn) writeAt : (unsigned)offset
316: length : (unsigned)length
317: buffer : (in unsigned char *)buffer
318: actualLength : (out unsigned *)actualLength
319: client : (vm_task_t)client
320: {
321: IOReturn mrtn;
322: char *dest;
323: IOBuf *IOBuf;
324: u_int block_size;
325: u_int dev_size;
326:
327: xpr_stub("IOStub write: unit %d offset 0x%x length 0x%x\n",
328: [self unit], offset, length, 4,5);
329:
330: block_size = [self blockSize];
331: dev_size = [self deviceSize];
332:
333: /*
334: * Verify legal parameters.
335: */
336: if([self writeProtected]) {
337: return IO_R_NOTWRITEABLE;
338: }
339: dest = stub_data + offset * block_size;
340: if((dest + length) > (stub_data + (block_size * dev_size))) {
341:
342: xpr_stub("IOStub dest: invalid offset/byte count\n",
343: 1,2,3,4,5);
344: return(IO_R_INVALIDARG);
345: }
346:
347: /*
348: * OK, queue up an IOBuf.
349: */
350: IOBuf = IOMalloc(sizeof(*IOBuf));
351: IOBuf->cmd = STUB_WRITE;
352: IOBuf->offset = offset;
353: IOBuf->bytesReq = length;
354: IOBuf->buf = buffer;
355: IOBuf->status = IO_R_INVALID;
356: IOBuf->pending = NULL;
357: IOBuf->waitLock = [NXConditionLock alloc];
358: [IOBuf->waitLock initWith:NO];
359: IOBuf->device = self;
360: IOBuf->dirRead = 0;
361: IOBuf->client = IOVmTaskSelf();
362: [self enqueueIoBuf:IOBuf];
363:
364: /*
365: * Wait for I/O complete.
366: */
367: [IOBuf->waitLock lockWhen:YES];
368: xpr_stub("stub write: DONE\n", 1,2,3,4,5);
369: mrtn = IOBuf->status;
370: *actualLength = IOBuf->bytesXfr;
371: [IOBuf->waitLock free];
372: IOFree(IOBuf, sizeof(*IOBuf));
373: return(mrtn);
374: }
375:
376:
377: - (IOReturn) writeAsyncAt : (unsigned)offset
378: length : (unsigned)length
379: buffer : (in unsigned char *)buffer
380: pending : (unsigned)pending
381: client : (vm_task_t)client
382: {
383: char *source;
384: IOBuf *IOBuf;
385: u_int block_size;
386: u_int dev_size;
387:
388: xpr_stub("IOStub writeAsync: unit %d offset 0x%x length 0x%x\n",
389: [self unit], offset, length, 4,5);
390:
391: block_size = [self blockSize];
392: dev_size = [self deviceSize];
393:
394: if([self writeProtected]) {
395: return IO_R_NOTWRITEABLE;
396: }
397: source = stub_data + offset * block_size;
398: if((source + length) > (stub_data + (block_size * dev_size))) {
399:
400: xpr_stub("IOStub write: invalid offset/byte count\n",
401: 1,2,3,4,5);
402: return(IO_R_INVALIDARG);
403: }
404:
405: /*
406: * Just queue up an IOBuf.
407: */
408: IOBuf = IOMalloc(sizeof(*IOBuf));
409: IOBuf->cmd = STUB_WRITE;
410: IOBuf->offset = offset;
411: IOBuf->bytesReq = length;
412: IOBuf->buf = buffer;
413: IOBuf->status = IO_R_INVALID; /* must be filled in by
414: * I/O thread */
415: IOBuf->pending = (void *)pending;
416: IOBuf->device = self;
417: IOBuf->dirRead = 0;
418: IOBuf->client = client;
419: [self enqueueIoBuf:IOBuf];
420:
421: xpr_stub("stub writeAsync: DONE\n", 1,2,3,4,5);
422: return(IO_R_SUCCESS);
423: }
424:
425: @end
426:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.