|
|
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 <bsd/sys/types.h>
34: #import <mach/mach.h>
35: #import <mach/vm_param.h>
36: #import <mach/mach_error.h>
37: #import <bsd/libc.h>
38: #import <driverkit/return.h>
39: #import <driverkit/IODevice.h>
40: #import "IOStub.h"
41: #import "IOStubThread.h"
42: #import "IOStubDevice.h"
43: #import "IOStubUxpr.h"
44: #import <machkit/NXLock.h>
45:
46: @implementation IOStub
47:
48: /*
49: * Initialize current instance. Returns non-zero on error.
50: */
51: - initStub : (int)unitNum
52: {
53: int data_size;
54: int i;
55: char *cp;
56: kern_return_t krtn;
57: u_int block_size, dev_size;
58:
59: xpr_stub("IOStub : init: unitNum %d\n", unitNum, 2,3,4,5);
60:
61:
62: [self setUnit:unitNum];
63: if(unitNum == 0) {
64: /*
65: * read/write.
66: */
67: block_size = 0x20;
68: dev_size = 0x1000;
69: [self setName : "IOStub0"];
70: [self setWriteProtected:NO];
71: }
72: else {
73: /*
74: * Make this one read-only, non-queuing.
75: */
76: block_size = 0x40;
77: dev_size = 0x800;
78: [self setName : "IOStub1"];
79: [self setWriteProtected:YES];
80: }
81: [self setDeviceKind:"Stub Device"];
82: [self setLocation:NULL];
83: [self setDiskSize:dev_size];
84: [self setBlockSize:block_size];
85: [self setFormattedInternal:1];
86:
87: /*
88: * allocate and initialize data for writing and reading.
89: */
90: data_size = block_size * dev_size;
91: krtn = vm_allocate(task_self(),
92: (vm_address_t *)&stub_data,
93: (vm_size_t)round_page(data_size),
94: YES);
95: if(krtn != KERN_SUCCESS) {
96: mach_error("***IOStub init: vm_allocate", krtn);
97: return(self);
98: }
99:
100: /*
101: * initial data: incrementing bytes for unit 0, decrementing
102: * bytes for others.
103: */
104: cp = (char *)stub_data;
105: for(i=0; i<data_size; i++) {
106: if(unitNum)
107: *cp++ = 0 - (char)i;
108: else
109: *cp++ = i;
110: }
111:
112: /*
113: * Set up our instance's IOQueue.
114: */
115: ioQLock = [NXConditionLock alloc];
116: [ioQLock initWith:NO_WORK_AVAILABLE];
117: queue_init(&ioQueue);
118:
119: /*
120: * Start up an I/O thread to perform the actual work of this device.
121: */
122: IOForkThread((IOThreadFunc)IOStub_thread, self);
123:
124: [self registerDevice];
125:
126: /*
127: * Let superclass take care of initializing inherited instance
128: * variables.
129: */
130: [super init];
131: return self;
132: }
133:
134: /*
135: * Free resources consumed by this instance.
136: */
137: - free
138: {
139: int data_size;
140: kern_return_t krtn;
141: u_int block_size, dev_size;
142: IOBuf_t *IOBuf;
143:
144: /*
145: * Kill the I/O thread.
146: */
147: IOBuf = IOMalloc(sizeof(*IOBuf));
148: IOBuf->cmd = STUB_ABORT;
149: IOBuf->pending = 0;
150: IOBuf->waitLock = [NXConditionLock alloc];
151: [IOBuf->waitLock initWith:NO];
152: [self enqueueIoBuf:IOBuf];
153:
154: /*
155: * Wait for I/O complete.
156: */
157: [IOBuf->waitLock lockWhen:YES];
158: [IOBuf->waitLock unlock];
159: [IOBuf->waitLock free];
160: IOFree(IOBuf, sizeof(IOBuf_t));
161:
162: /*
163: * Free up our VM.
164: */
165: block_size = [self blockSize];
166: dev_size = [self diskSize];
167: data_size = block_size * dev_size;
168: krtn = vm_deallocate(task_self(),
169: (vm_address_t)stub_data,
170: (vm_size_t)round_page(data_size));
171: if(krtn != KERN_SUCCESS) {
172: mach_error("***IOStub free: vm_deallocate", krtn);
173: }
174: return([super free]);
175: }
176:
177: /*
178: * These override the superclass's methods which are no-op stubs.
179: */
180:
181: - (int)deviceOpen:(u_int)intentions
182: {
183: xpr_stub("IOStub deviceOpen: unit %d\n", [self unit], 2,3,4,5);
184: return(IO_R_SUCCESS);
185: }
186:
187: - (void)deviceClose
188: {
189: xpr_stub("IOStub deviceClose: unit %d\n", [self unit], 2,3,4,5);
190: }
191:
192: /*
193: * These are the exported I/O methods, from the
194: * IODiskDeviceReadingAndWriting category. Their main task is:
195: *
196: * -- verify valid input parameters.
197: * -- set up and enqueue an IOBuf for servicing by the I/O thread.
198: * -- Wait for I/O complete if synchronous request.
199: */
200:
201: - (IOReturn) readAt : (unsigned)offset
202: length : (unsigned)length
203: buffer : (unsigned char *)buffer
204: actualLength : (unsigned *)actualLength
205: {
206: IOReturn mrtn;
207: char *source;
208: IOBuf_t *IOBuf;
209: u_int block_size;
210: u_int dev_size;
211:
212: xpr_stub("IOStub read: unit %d offset 0x%x length 0x%x\n",
213: [self unit], offset, length, 4,5);
214:
215: block_size = [self blockSize];
216: dev_size = [self diskSize];
217:
218: /*
219: * Verify legal parameters.
220: */
221: source = stub_data + offset * block_size;
222: if((source + length) > (stub_data + (block_size * dev_size))) {
223:
224: xpr_stub("IOStub read: invalid offset/byte count\n",
225: 1,2,3,4,5);
226: return(IO_R_INVALID_ARG);
227: }
228:
229: /*
230: * OK, queue up an IOBuf.
231: */
232: IOBuf = IOMalloc(sizeof(*IOBuf));
233: IOBuf->cmd = STUB_READ;
234: IOBuf->offset = offset;
235: IOBuf->bytesReq = length;
236: IOBuf->buf = buffer;
237: IOBuf->bytesXfr = actualLength;
238: IOBuf->status = IO_R_INVALID;
239: IOBuf->pending = 0;
240: IOBuf->waitLock = [NXConditionLock alloc];
241: [IOBuf->waitLock initWith:NO];
242: IOBuf->dirRead = 1;
243: [self enqueueIoBuf:IOBuf];
244:
245: /*
246: * Wait for I/O complete.
247: */
248: [IOBuf->waitLock lockWhen:YES];
249: [IOBuf->waitLock unlock];
250: xpr_stub("stub read: DONE\n", 1,2,3,4,5);
251: mrtn = IOBuf->status;
252: [IOBuf->waitLock free];
253: IOFree(IOBuf, sizeof(*IOBuf));
254: return(mrtn);
255: }
256:
257: - (IOReturn) readAsyncAt : (unsigned)offset
258: length : (unsigned)length
259: buffer : (unsigned char *)buffer
260: pending : (void *)pending
261: {
262: char *source;
263: IOBuf_t *IOBuf;
264: unsigned block_size;
265: unsigned dev_size;
266:
267: xpr_stub("IOStub readAsync: unit %d offset 0x%x length 0x%x\n",
268: [self unit], offset, length, 4,5);
269:
270: block_size = [self blockSize];
271: dev_size = [self diskSize];
272:
273: /*
274: * Verify legal parameters.
275: */
276: source = stub_data + offset * block_size;
277: if((source + length) > (stub_data + (block_size * dev_size))) {
278:
279: xpr_stub("IOStub read: invalid offset/byte count\n",
280: 1,2,3,4,5);
281: return(IO_R_INVALID_ARG);
282: }
283:
284: /*
285: * Just queue up an IOBuf.
286: */
287: IOBuf = IOMalloc(sizeof(*IOBuf));
288: IOBuf->cmd = STUB_READ;
289: IOBuf->offset = offset;
290: IOBuf->bytesReq = length;
291: IOBuf->buf = buffer;
292: IOBuf->status = IO_R_INVALID; /* must be filled in by
293: * I/O thread */
294: IOBuf->pending = pending;
295: IOBuf->dirRead = 1;
296: [self enqueueIoBuf:IOBuf];
297:
298: xpr_stub("stub readAsync: DONE\n", 1,2,3,4,5);
299: return(IO_R_SUCCESS);
300: }
301:
302: - (IOReturn) writeAt : (unsigned)offset
303: length : (unsigned)length
304: buffer : (unsigned char *)buffer
305: actualLength : (unsigned *)actualLength
306: {
307: IOReturn mrtn;
308: char *dest;
309: IOBuf_t *IOBuf;
310: unsigned block_size;
311: unsigned dev_size;
312:
313: xpr_stub("IOStub write: unit %d offset 0x%x length 0x%x\n",
314: [self unit], offset, length, 4,5);
315:
316: block_size = [self blockSize];
317: dev_size = [self diskSize];
318:
319: /*
320: * Verify legal parameters.
321: */
322: if([self isWriteProtected]) {
323: return IO_R_NOT_WRITABLE;
324: }
325: dest = stub_data + offset * block_size;
326: if((dest + length) > (stub_data + (block_size * dev_size))) {
327:
328: xpr_stub("IOStub dest: invalid offset/byte count\n",
329: 1,2,3,4,5);
330: return(IO_R_INVALID_ARG);
331: }
332:
333: /*
334: * OK, queue up an IOBuf.
335: */
336: IOBuf = IOMalloc(sizeof(*IOBuf));
337: IOBuf->cmd = STUB_WRITE;
338: IOBuf->offset = offset;
339: IOBuf->bytesReq = length;
340: IOBuf->buf = buffer;
341: IOBuf->bytesXfr = actualLength;
342: IOBuf->status = IO_R_INVALID;
343: IOBuf->pending = 0;
344: IOBuf->waitLock = [NXConditionLock alloc];
345: [IOBuf->waitLock initWith:NO];
346: IOBuf->dirRead = 0;
347: [self enqueueIoBuf:IOBuf];
348:
349: /*
350: * Wait for I/O complete.
351: */
352: [IOBuf->waitLock lockWhen:YES];
353: [IOBuf->waitLock unlock];
354: xpr_stub("stub write: DONE\n", 1,2,3,4,5);
355: mrtn = IOBuf->status;
356: [IOBuf->waitLock free];
357: IOFree(IOBuf, sizeof(*IOBuf));
358: return(mrtn);
359: }
360:
361: - (IOReturn) writeAsyncAt : (unsigned)offset
362: length : (unsigned)length
363: buffer : (unsigned char *)buffer
364: pending : (void *)pending;
365: {
366: char *source;
367: IOBuf_t *IOBuf;
368: unsigned block_size;
369: unsigned dev_size;
370:
371: xpr_stub("IOStub writeAsync: unit %d offset 0x%x length 0x%x\n",
372: [self unit], offset, length, 4,5);
373:
374: block_size = [self blockSize];
375: dev_size = [self diskSize];
376:
377: /*
378: * Verify legal parameters.
379: */
380: if([self isWriteProtected]) {
381: return IO_R_NOT_WRITABLE;
382: }
383: source = stub_data + offset * block_size;
384: if((source + length) > (stub_data + (block_size * dev_size))) {
385:
386: xpr_stub("IOStub write: invalid offset/byte count\n",
387: 1,2,3,4,5);
388: return(IO_R_INVALID_ARG);
389: }
390:
391: /*
392: * Just queue up an IOBuf.
393: */
394: IOBuf = IOMalloc(sizeof(*IOBuf));
395: IOBuf->cmd = STUB_WRITE;
396: IOBuf->offset = offset;
397: IOBuf->bytesReq = length;
398: IOBuf->buf = buffer;
399: IOBuf->status = IO_R_INVALID; /* must be filled in by
400: * I/O thread */
401: IOBuf->pending = pending;
402: IOBuf->dirRead = 0;
403: [self enqueueIoBuf:IOBuf];
404:
405: xpr_stub("stub writeAsync: DONE\n", 1,2,3,4,5);
406: return(IO_R_SUCCESS);
407: }
408:
409: /*
410: * Distributed Objects R/W protocol.
411: */
412: - (IOReturn) readAt : (unsigned)offset // in blocks
413: length : (unsigned)length // in bytes
414: data : (out IOData **)data
415: actualLength : (out unsigned *)actualLength
416: {
417: IOReturn rtn;
418: IOData *ldata = [[IOData alloc] initWithSize:length];
419:
420: /*
421: * FIXME - when freeFlag is set to YES (which is what we really
422: * want), this method crashes with the following error messages
423: * when run with the DiskTest app:
424: *
425: * finishEncoding: send error -101:invalid memory
426: * uncaught exception : 11001
427: * objc: FREED(id): message free sent to freed object=0x9c01c
428: *
429: * When run with the test programs in ../tests, everything works
430: * OK...
431: *
432: * When we set freeFlag to NO, everything works, but the IOStub
433: * server leaks memory.
434: *
435: * Update 15-Oct-92 - this error only happens when moving at least
436: * one entire page of data. Moving less than a page is OK.
437: */
438: [ldata setFreeFlag:YES];
439: rtn = [self readAt:offset
440: length:length
441: buffer:[ldata data]
442: actualLength:actualLength];
443: if(*actualLength) {
444: *data = ldata;
445: }
446:
447: /*
448: * FIXME - when does the IOData get deallocated??
449: */
450: return rtn;
451: }
452:
453: /*
454: * DiskRwDistributed protocol.
455: */
456: - (IOData *)rreadAt : (unsigned)offset
457: length : (unsigned)length
458: rtn : (out IOReturn *)rtn
459: actualLength : (out unsigned *)actualLength
460: {
461: IOReturn lrtn;
462: IOData *ldata = [[IOData alloc] initWithSize:length];
463:
464: [ldata setFreeFlag:YES];
465: lrtn = [self readAt:offset
466: length:length
467: buffer:[ldata data]
468: actualLength:actualLength];
469: *rtn = lrtn;
470: return ldata;
471: }
472:
473: - (IOReturn) readAsyncAt : (unsigned)offset
474: length : (unsigned)length
475: ioKey : (unsigned)ioKey
476: caller : (id)caller
477: {
478: /* TBD */
479: return IO_R_UNSUPPORTED;
480: }
481:
482:
483: - (IOReturn) writeAt : (unsigned)offset // in blocks
484: length : (unsigned)length // in bytes
485: data : (in IOData *)data
486: actualLength : (out unsigned *)actualLength
487: {
488: IOReturn rtn;
489:
490: if([data size] < length) {
491: IOLog("%s writeAt: insufficient memory in IOData\n",
492: [self name]);
493: }
494: rtn = [self writeAt:offset
495: length:length
496: buffer:[data data]
497: actualLength:actualLength];
498: [data free];
499: return rtn;
500: }
501:
502: - (IOReturn)writeAsyncAt : (unsigned)offset // in blocks
503: length : (unsigned)length // in bytes
504: data : (in IOData *)data
505: ioKey : (unsigned)ioKey
506: caller : (id)caller
507: {
508: return IO_R_UNSUPPORTED;
509: }
510: @end
511:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.