|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, 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: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
24: *
25: * HISTORY
26: * 8 June 1999 wgulland created.
27: *
28: */
29: #include <IOKit/assert.h>
30: #include <IOKit/IOLib.h>
31: #include <IOKit/firewire/IOFireWireDevice.h>
32: #include <IOKit/firewire/IOFireWireController.h>
33: #include <IOKit/firewire/IOFWIsochChannel.h>
34: #include <IOKit/firewire/IOFWIsochPort.h>
35: #include <IOKit/firewire/IOFWIsoch.h>
36:
37: #include <IOKit/IOBufferMemoryDescriptor.h>
38:
39: #include "IOFireWireUserClient.h"
40:
41: #define super IOUserClient
42: #define DEBUGGING_LEVEL 0
43:
44: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
45:
46: OSDefineMetaClassAndStructors(IOFireWireUserClient, IOUserClient)
47:
48: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
49:
50: class DVPort : public IOFWIsochPort
51: {
52: OSDeclareDefaultStructors(DVPort)
53:
54: public:
55: virtual bool init(IOFireWireDevice *device);
56: // Return maximum speed and channels supported
57: // (bit n set = chan n supported)
58: virtual IOReturn getSupported(IOFWSpeed &maxSpeed, UInt64 &chanSupported);
59:
60: // Allocate hardware resources for port
61: virtual IOReturn allocatePort(IOFWSpeed speed, UInt32 chan);
62: virtual IOReturn releasePort(); // Free hardware resources
63: virtual IOReturn start(); // Start port processing packets
64: virtual IOReturn stop(); // Stop processing packets
65: };
66:
67: OSDefineMetaClassAndStructors(DVPort, IOFWIsochPort)
68:
69: bool DVPort::init(IOFireWireDevice *device)
70: {
71: return IOFWIsochPort::init();
72: }
73:
74: IOReturn DVPort::getSupported(IOFWSpeed &maxSpeed, UInt64 &chanSupported)
75: {
76: //kprintf("DVPort::getSupported\n");
77: maxSpeed = kFWSpeed100MBit;
78: chanSupported = (UInt64)1;
79: return kIOReturnSuccess;
80: }
81:
82: IOReturn DVPort::allocatePort(IOFWSpeed speed, UInt32 chan)
83: {
84: //kprintf("DVPort::allocatePort(%d, %d)\n", speed, chan);
85: return kIOReturnSuccess;
86: }
87:
88: IOReturn DVPort::releasePort()
89: {
90: //kprintf("DVPort::releasePort()\n");
91: return kIOReturnSuccess;
92: }
93:
94: IOReturn DVPort::start()
95: {
96: //kprintf("DVPort::start()\n");
97: return kIOReturnSuccess;
98: }
99:
100: IOReturn DVPort::stop()
101: {
102: //kprintf("DVPort::stop()\n");
103: return kIOReturnSuccess;
104: }
105:
106:
107: struct dclStuff {
108: int fState;
109: IOFWIsochChannel *chan;
110: IOFWIsochPort *port;
111: DVPort * dvPort;
112: OSAsyncReference asyncRef;
113: };
114:
115: static dclStuff theProg;
116: /*static*/ int donePings;
117:
118: IOFireWireUserClient *IOFireWireUserClient::withTask(task_t owningTask)
119: {
120: IOFireWireUserClient *me;
121:
122: me = new IOFireWireUserClient;
123: if(me) {
124: if(!me->init()) {
125: me->release();
126: return NULL;
127: }
128: me->fTask = owningTask;
129: }
130: return me;
131: }
132:
133: bool IOFireWireUserClient::start( IOService * provider )
134: {
135: assert(OSDynamicCast(IOFireWireDevice, provider));
136: if(!super::start(provider))
137: return false;
138: fOwner = (IOFireWireDevice *)provider;
139:
140: // Got the owner, so initialize the call structures
141: fMethods[kFireWireRead].object = this;
142: fMethods[kFireWireRead].func =
143: (IOMethod)&IOFireWireUserClient::Read;
144: fMethods[kFireWireRead].count0 = 2;
145: fMethods[kFireWireRead].count1 = 0xffffffff; // variable
146: fMethods[kFireWireRead].flags = kIOUCScalarIStructO;
147:
148: fMethods[kFireWireWrite].object = this;
149: fMethods[kFireWireWrite].func =
150: (IOMethod)&IOFireWireUserClient::Write;
151: fMethods[kFireWireWrite].count0 = 2;
152: fMethods[kFireWireWrite].count1 = 0xffffffff; // variable
153: fMethods[kFireWireWrite].flags = kIOUCScalarIStructI;
154:
155: fMethods[kFireWireCompareSwap].object = this;
156: fMethods[kFireWireCompareSwap].func =
157: (IOMethod)&IOFireWireUserClient::CompareSwap;
158: fMethods[kFireWireCompareSwap].count0 = 4;
159: fMethods[kFireWireCompareSwap].count1 = 0;
160: fMethods[kFireWireCompareSwap].flags = kIOUCScalarIScalarO;
161:
162: fMethods[kFireWireBusReset].object = this;
163: fMethods[kFireWireBusReset].func =
164: (IOMethod)&IOFireWireUserClient::BusReset;
165: fMethods[kFireWireBusReset].count0 = 0;
166: fMethods[kFireWireBusReset].count1 = 0;
167: fMethods[kFireWireBusReset].flags = kIOUCScalarIScalarO;
168:
169: fMethods[kFireWireTest].object = this;
170: fMethods[kFireWireTest].func =
171: (IOMethod)&IOFireWireUserClient::Test;
172: fMethods[kFireWireTest].count0 = 0;
173: fMethods[kFireWireTest].count1 = 0;
174: fMethods[kFireWireTest].flags = kIOUCScalarIScalarO;
175:
176: fMethods[kFireWireCycleTime].object = fOwner->fControl;
177: fMethods[kFireWireCycleTime].func =
178: (IOMethod)&IOFireWireController::getCycleTime;
179: fMethods[kFireWireCycleTime].count0 = 0;
180: fMethods[kFireWireCycleTime].count1 = 1;
181: fMethods[kFireWireCycleTime].flags = kIOUCScalarIScalarO;
182:
183: fMethods[kFireWireCompileDCL].object = this;
184: fMethods[kFireWireCompileDCL].func =
185: (IOMethod)&CompileDCL;
186: fMethods[kFireWireCompileDCL].count0 = 5;
187: fMethods[kFireWireCompileDCL].count1 = 1;
188: fMethods[kFireWireCompileDCL].flags = kIOUCScalarIScalarO;
189:
190: fMethods[kFireWireStopDCL].object = this;
191: fMethods[kFireWireStopDCL].func =
192: (IOMethod)&StopDCL;
193: fMethods[kFireWireStopDCL].count0 = 1;
194: fMethods[kFireWireStopDCL].count1 = 0;
195: fMethods[kFireWireStopDCL].flags = kIOUCScalarIScalarO;
196:
197: fAsyncMethods[kFireWireRunDCL].object = this;
198: fAsyncMethods[kFireWireRunDCL].func =
199: (IOAsyncMethod)&RunDCL;
200: fAsyncMethods[kFireWireRunDCL].count0 = 1;
201: fAsyncMethods[kFireWireRunDCL].count1 = 0;
202: fAsyncMethods[kFireWireRunDCL].flags = kIOUCScalarIScalarO;
203:
204:
205:
206: return true;
207: }
208:
209: IOReturn IOFireWireUserClient::clientClose( void )
210: {
211: if(theProg.fState != 0)
212: IOLog("Client close, DCL state = %d\n", theProg.fState);
213:
214: if(theProg.fState == 2) {
215: StopDCL((UInt32)&theProg);
216: }
217: if(theProg.fState == 1) {
218: StopDCL((UInt32)&theProg);
219: }
220: detach( fOwner);
221:
222: return kIOReturnSuccess;
223: }
224:
225: IOReturn IOFireWireUserClient::clientDied( void )
226: {
227: return( clientClose());
228: }
229:
230: IOExternalMethod *
231: IOFireWireUserClient::getExternalMethodForIndex( UInt32 index )
232: {
233: if(index >= kNumFireWireMethods)
234: return NULL;
235: else
236: return &fMethods[index];
237: }
238:
239: IOExternalAsyncMethod *
240: IOFireWireUserClient::getExternalAsyncMethodForIndex( UInt32 index )
241: {
242: if(index >= kNumFireWireMethods || fAsyncMethods[index].object == NULL)
243: return NULL;
244: else
245: return &fAsyncMethods[index];
246: }
247:
248:
249:
250: IOReturn
251: IOFireWireUserClient::Read(UInt32 addrHi, UInt32 addrLo, void *buf, UInt32 *size)
252: {
253: IOReturn res;
254: IOMemoryDescriptor * mem = NULL;
255: IOFWCommand * cmd = NULL;
256: UInt32 req = *size;
257:
258: do {
259: *size = 0;
260: if(req == 4 || req == 8) {
261: cmd = fOwner->createReadQuadCommand(FWAddress(addrHi, addrLo), (UInt32 *)buf, req/4);
262: if(!cmd) {
263: res = kIOReturnNoMemory;
264: break;
265: }
266: }
267: else {
268: mem = IOMemoryDescriptor::withAddress(buf, req, kIODirectionIn);
269: if(!mem) {
270: res = kIOReturnNoMemory;
271: break;
272: }
273:
274: cmd = fOwner->createReadCommand(FWAddress(addrHi, addrLo), mem);
275: if(!cmd) {
276: res = kIOReturnNoMemory;
277: break;
278: }
279: }
280: res = cmd->submit();
281: // We block here until the command finishes
282: if(kIOReturnSuccess == res)
283: res = cmd->fStatus;
284: if(kIOReturnSuccess == res) {
285: if(mem)
286: *size = cmd->fBytesTransferred;
287: else
288: *size = req;
289: }
290:
291: } while(false);
292:
293: if(cmd)
294: cmd->release();
295: if(mem)
296: mem->release();
297:
298: return res;
299: }
300:
301: IOReturn
302: IOFireWireUserClient::Write(UInt32 addrHi, UInt32 addrLo, void *buf, UInt32 size)
303: {
304: IOReturn res;
305: IOMemoryDescriptor * mem = NULL;
306: IOFWCommand * cmd = NULL;
307:
308: do {
309: if(size == 4 || size == 8) {
310: cmd = fOwner->createWriteQuadCommand(FWAddress(addrHi, addrLo), (UInt32 *)buf, size/4);
311: if(!cmd) {
312: res = kIOReturnNoMemory;
313: break;
314: }
315: }
316: else {
317: mem = IOMemoryDescriptor::withAddress(buf, size, kIODirectionOut);
318: if(!mem) {
319: res = kIOReturnNoMemory;
320: break;
321: }
322:
323: cmd = fOwner->createWriteCommand(FWAddress(addrHi, addrLo), mem);
324: if(!cmd) {
325: res = kIOReturnNoMemory;
326: break;
327: }
328: }
329: res = cmd->submit();
330: // We block here until the command finishes
331: if(kIOReturnSuccess == res)
332: res = cmd->fStatus;
333:
334: } while(false);
335:
336: if(cmd)
337: cmd->release();
338: if(mem)
339: mem->release();
340:
341: return res;
342: }
343:
344: IOReturn
345: IOFireWireUserClient::CompareSwap(UInt32 addrHi, UInt32 addrLo, UInt32 cmpVal, UInt32 newVal)
346: {
347: IOReturn res;
348: IOFWCompareAndSwapCommand * cmd = NULL;
349:
350: cmd = fOwner->createCompareAndSwapCommand(FWAddress(addrHi, addrLo), &cmpVal, &newVal, 1);
351: if(!cmd) {
352: return kIOReturnNoMemory;
353: }
354:
355: res = cmd->submit();
356: // We block here until the command finishes
357: if(kIOReturnSuccess == res) {
358: UInt32 oldVal;
359: res = cmd->fStatus;
360: if(kIOReturnSuccess == res && !cmd->locked(&oldVal))
361: res = kIOReturnCannotLock;
362: }
363:
364: if(cmd)
365: cmd->release();
366:
367: return res;
368: }
369:
370:
371: IOReturn
372: IOFireWireUserClient::clientMemoryForType( UInt32 type,
373: UInt32 * flags, IOMemoryDescriptor ** memory )
374: {
375: // This is a wonderful hack.
376: // Create some memory, map it out to the user and off we go!!
377: // We abuse the type as the low part of a fire wire address.
378: // The high part is 0xf1d0. Woof Woof!!
379: // The size is one page.
380: IOBufferMemoryDescriptor * desc;
381: IOFWAddressSpace * space;
382: IOFWAllocAddressCommand * cmd = NULL;
383: void * buf;
384: IOReturn res;
385:
386: desc = IOBufferMemoryDescriptor::withCapacity(PAGE_SIZE,
387: kIODirectionOutIn, true);
388: if(!desc)
389: return kIOReturnNoMemory;
390: desc->setLength(PAGE_SIZE);
391: buf = desc->getBytesNoCopy();
392: desc->retain();
393: *memory = desc;
394:
395: space = IOFWPseudoAddressSpace::simpleRW(FWAddress(0xf1d0, type), PAGE_SIZE, buf);
396: if(!space)
397: return kIOReturnNoMemory;
398: cmd = fOwner->createAllocAddrCommand(space);
399: if(!cmd)
400: return kIOReturnNoMemory;
401: res = cmd->submit();
402: // We block here until the command finishes
403: if(kIOReturnSuccess == res)
404: res = cmd->fStatus;
405: if(cmd)
406: cmd->release();
407:
408: if(kIOReturnSuccess == res) {
409: space = fOwner->createPhysicalAddressSpace(desc);
410: if(space) {
411: cmd = fOwner->createAllocAddrCommand(space);
412: if(!cmd)
413: return kIOReturnNoMemory;
414: res = cmd->submit();
415: // We block here until the command finishes
416: if(kIOReturnSuccess == res)
417: res = cmd->fStatus;
418: if(cmd)
419: cmd->release();
420: }
421: }
422: return res;
423: }
424:
425: IOReturn IOFireWireUserClient::BusReset()
426: {
427: IOFWUpdateROM *reset;
428: IOReturn res = kIOReturnNoMemory;
429: kprintf("Bus Reset!!!\n");
430: reset = new IOFWUpdateROM;
431: if(reset) {
432: if(reset->initWithController(fOwner->fControl)) {
433: res = reset->submit();
434: // We block here until the command finishes
435: if(kIOReturnSuccess == res)
436: res = reset->fStatus;
437: }
438: }
439: if(reset)
440: reset->release();
441:
442: return kIOReturnSuccess;
443: }
444:
445: static int state;
446: IOReturn IOFireWireUserClient::message( UInt32 type, IOService * provider, void * arg )
447: {
448: kprintf("IOFireWireUserClient(0x%x)::message(0x%x, 0x%x, 0x%x)\n",
449: this, type, provider, arg);
450: kprintf("state = 0x%x\n", state);
451: return kIOReturnSuccess;
452: }
453:
454: #if 1
455: static void PingPongProc(DCLCommandPtr pDCLCommand)
456: {
457: if(donePings++ < 2)
458: IOLog("Ping! (or Pong!) %0x\n", pDCLCommand);
459: }
460:
461: #if 0
462: IOReturn IOFireWireUserClient::Test()
463: {
464: IOFWIsochChannel *chan;
465: IOFWIsochPort *port;
466: DVPort * dvPort;
467: DCLCommandStruct *opcodes;
468:
469: enum
470: {
471: kNumPingPongs = 2,
472: kNumPacketsPerPingPong = 10,
473: kNumDCLsPerPingPongPacket = 1,
474: kRecordNumDCLs =
475: kNumPingPongs * kNumPacketsPerPingPong * kNumDCLsPerPingPongPacket,
476: kMaxDCLSize = 32,
477: kRecordDCLProgramSize = kMaxDCLSize * kRecordNumDCLs,
478: kReceiveDVPacketSize = 492,
479: kPingPongBufferSize =
480: kNumPingPongs * kNumPacketsPerPingPong * kReceiveDVPacketSize
481: };
482:
483: const UInt32 blockSize = kRecordDCLProgramSize;
484:
485: UInt8 * pingPongBuffer = NULL;
486: UInt8 * pingPongPtr;
487: UInt8 * pDCLCommand;
488: DCLLabelPtr pStartDCLLabel;
489: DCLTransferPacketPtr pDCLTransferPacket;
490: DCLCallProcPtr pDCLPingPongProc;
491: DCLJumpPtr pDCLPingPongLoop;
492: int pingPongNum, packetNum;
493:
494: kprintf("IOFireWireUserClient::Test()!!\n");
495:
496: opcodes = (DCLCommandStruct *)IOMalloc(blockSize);
497:
498: // Create ping pong buffer.
499: //zzz should allocate in initialization routine.
500: pingPongBuffer = (UInt8 *)IOMalloc(kPingPongBufferSize);
501:
502: // Get pointer to start of DCL commands and update list.
503: pDCLCommand = (UInt8 *)opcodes;
504:
505: // Create label for start of loop.
506: pStartDCLLabel = (DCLLabelPtr) pDCLCommand;
507: pDCLCommand += sizeof (DCLLabel);
508: pStartDCLLabel->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
509: pStartDCLLabel->opcode = kDCLLabelOp;
510: pingPongPtr = pingPongBuffer;
511:
512: // Create 2 ping pong buffer lists of 10 packets each.
513: for (pingPongNum = 0; pingPongNum < kNumPingPongs; pingPongNum++)
514: {
515:
516: // Create transfer DCL for each packet.
517: for (packetNum = 0; packetNum < kNumPacketsPerPingPong; packetNum++)
518: {
519: // Receive one packet up to kReceiveDVPacketSize bytes.
520: pDCLTransferPacket = (DCLTransferPacketPtr) pDCLCommand;
521: pDCLCommand += sizeof (DCLTransferPacket);
522: pDCLTransferPacket->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
523: pDCLTransferPacket->opcode = kDCLReceivePacketStartOp;
524: pDCLTransferPacket->buffer = pingPongPtr;
525: pDCLTransferPacket->size = kReceiveDVPacketSize;
526:
527: pingPongPtr += kReceiveDVPacketSize;
528: }
529:
530: // Call the ping pong proc.
531: pDCLPingPongProc = (DCLCallProcPtr) pDCLCommand;
532: pDCLCommand += sizeof (DCLCallProc);
533: pDCLPingPongProc->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
534: pDCLPingPongProc->opcode = kDCLCallProcOp;
535: pDCLPingPongProc->proc = PingPongProc;
536: pDCLPingPongProc->procData = (UInt32) this;
537: }
538:
539: // Loop to start of ping pong.
540: pDCLPingPongLoop = (DCLJumpPtr) pDCLCommand;
541: pDCLPingPongLoop->pNextDCLCommand = NULL;
542: pDCLPingPongLoop->opcode = kDCLJumpOp;
543: pDCLPingPongLoop->pJumpDCLLabel = pStartDCLLabel;
544:
545: donePings = 0;
546:
547: chan = fOwner->fControl->createIsochChannel(false, 488*8*8000, kFWSpeed100MBit);
548: port = fOwner->fControl->createLocalIsochPort(false, opcodes);
549: dvPort = new DVPort;
550: dvPort->init(fOwner);
551: chan->addListener(port);
552: chan->setTalker(dvPort);
553: chan->allocateChannel();
554: chan->start();
555:
556: IOSleep(10000);
557:
558: chan->stop();
559: chan->releaseChannel();
560: dvPort->release();
561: port->release();
562: chan->release();
563:
564: /*
565: for (packetNum = 0; packetNum < kNumPacketsPerPingPong*kNumPingPongs; packetNum++) {
566: kprintf("Pack Header: 0x%x 0x%x 0x%x 0x%x\n",
567: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize),
568: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize+4),
569: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize+8),
570: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize+12)
571: );
572: }
573: */
574:
575: IOFree(pingPongBuffer, kPingPongBufferSize);
576: IOFree(opcodes, blockSize);
577:
578: return kIOReturnSuccess;
579: }
580:
581: #else
582:
583: IOReturn IOFireWireUserClient::Test()
584: {
585: IOFWIsochChannel *chan;
586: IOFWIsochPort *port;
587: DVPort * dvPort;
588: DCLCommandStruct *opcodes;
589:
590: enum
591: {
592: kNumPingPongs = 2,
593: kNumPacketsPerPingPong = 10,
594: kNumDCLsPerPingPongPacket = 2,
595: kPlayNumDCLs =
596: kNumPingPongs * kNumPacketsPerPingPong * kNumDCLsPerPingPongPacket,
597: kMaxDCLSize = 32,
598: kPlayDCLProgramSize = kMaxDCLSize * kPlayNumDCLs,
599: kSendDVPacketSize = 492,
600: kDVPacketHdrSize = 8,
601: kDVPacketDataSize = 480,
602: kPingPongBufferSize =
603: kNumPingPongs * kNumPacketsPerPingPong * kSendDVPacketSize
604: };
605:
606: const UInt32 blockSize = kPlayDCLProgramSize;
607:
608: UInt8 * pingPongBuffer = NULL;
609: UInt8 * pingPongPtr;
610: UInt8 * pDCLCommand;
611: DCLLabelPtr pStartDCLLabel;
612: DCLTransferPacketPtr pDCLTransferPacket;
613: DCLCallProcPtr pDCLPingPongProc;
614: DCLJumpPtr pDCLPingPongLoop;
615: int pingPongNum, packetNum;
616:
617: kprintf("IOFireWireUserClient::Test()!!\n");
618:
619: opcodes = (DCLCommandStruct *)IOMalloc(blockSize);
620:
621: // Create ping pong buffer.
622: //zzz should allocate in initialization routine.
623: pingPongBuffer = (UInt8 *)IOMalloc(kPingPongBufferSize);
624:
625: // Get pointer to start of DCL commands and update list.
626: pDCLCommand = (UInt8 *)opcodes;
627:
628: // Create label for start of loop.
629: pStartDCLLabel = (DCLLabelPtr) pDCLCommand;
630: pDCLCommand += sizeof (DCLLabel);
631: pStartDCLLabel->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
632: pStartDCLLabel->opcode = kDCLLabelOp;
633: pingPongPtr = pingPongBuffer;
634:
635: // Create 2 ping pong buffer lists of 10 packets each.
636: for (pingPongNum = 0; pingPongNum < kNumPingPongs; pingPongNum++)
637: {
638:
639: // Create transfer DCL for each packet.
640: for (packetNum = 0; packetNum < kNumPacketsPerPingPong; packetNum++)
641: {
642: // Send a packet with a header (CIP) and Mystery D/V Data
643: pDCLTransferPacket = (DCLTransferPacketPtr) pDCLCommand;
644: pDCLCommand += sizeof (DCLTransferPacket);
645: pDCLTransferPacket->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
646: pDCLTransferPacket->opcode = kDCLSendPacketStartOp;
647: pDCLTransferPacket->buffer = pingPongPtr;
648: pDCLTransferPacket->size = kDVPacketHdrSize;
649: pingPongPtr += kDVPacketHdrSize;
650:
651: pDCLTransferPacket = (DCLTransferPacketPtr) pDCLCommand;
652: pDCLCommand += sizeof (DCLTransferPacket);
653: pDCLTransferPacket->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
654: pDCLTransferPacket->opcode = kDCLSendPacketOp;
655: pDCLTransferPacket->buffer = pingPongPtr;
656: pDCLTransferPacket->size = kDVPacketDataSize;
657: pingPongPtr += kDVPacketDataSize;
658:
659: }
660:
661: // Call the ping pong proc.
662: pDCLPingPongProc = (DCLCallProcPtr) pDCLCommand;
663: pDCLCommand += sizeof (DCLCallProc);
664: pDCLPingPongProc->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
665: pDCLPingPongProc->opcode = kDCLCallProcOp;
666: pDCLPingPongProc->proc = PingPongProc;
667: pDCLPingPongProc->procData = (UInt32) this;
668: }
669:
670: // Loop to start of ping pong.
671: pDCLPingPongLoop = (DCLJumpPtr) pDCLCommand;
672: pDCLPingPongLoop->pNextDCLCommand = NULL;
673: pDCLPingPongLoop->opcode = kDCLJumpOp;
674: pDCLPingPongLoop->pJumpDCLLabel = pStartDCLLabel;
675:
676: donePings = 0;
677:
678: chan = fOwner->fControl->createIsochChannel(true, 488*8*8000, kFWSpeed100MBit);
679: port = fOwner->fControl->createLocalIsochPort(true, opcodes);
680: dvPort = new DVPort;
681: dvPort->init(fOwner);
682: chan->addListener(dvPort);
683: chan->setTalker(port);
684: chan->allocateChannel();
685: chan->start();
686:
687: IOSleep(10);
688:
689: chan->stop();
690: chan->releaseChannel();
691: dvPort->release();
692: port->release();
693: chan->release();
694:
695: /*
696: for (packetNum = 0; packetNum < kNumPacketsPerPingPong*kNumPingPongs; packetNum++) {
697: kprintf("Pack Header: 0x%x 0x%x 0x%x 0x%x\n",
698: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize),
699: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize+4),
700: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize+8),
701: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize+12)
702: );
703: }
704: */
705:
706: IOFree(pingPongBuffer, kPingPongBufferSize);
707: IOFree(opcodes, blockSize);
708:
709: return kIOReturnSuccess;
710: }
711: #endif
712:
713: #endif
714: #if 0
715:
716: static IOFWCommand *cmd1 = 0;
717: static IOFWCommand *cmd2 = 0;
718: static IOFWCommand *cmd3 = 0;
719:
720: static void Complete(void *refcon, IOReturn status, IOFireWireDevice *device, IOFWCommand *fwCmd)
721: {
722: // if(status != kIOReturnSuccess)
723: // kprintf("%x Completed with error %x\n", refcon, status);
724: if(fwCmd == cmd1) {
725: state |= 2;
726: cmd1->release();
727: cmd1 = 0;
728: cmd2->execute();
729: }
730: else if(fwCmd == cmd2) {
731: cmd2->release();
732: cmd2 = 0;
733: state |= 4;
734: }
735: else
736: kprintf("Complete(): Bad refcon: 0x%x\n", refcon);
737: }
738:
739: IOReturn IOFireWireUserClient::Test()
740: {
741: FWAddress testAddr(0xf1d0, 0);
742: UInt32 quad = 0x12345677;
743: UInt32 quad1 = 0x12345678;
744: UInt32 quad2 = 0x12345679;
745: IOReturn status;
746:
747: if(cmd1 != 0 || cmd2 != 0)
748: return state; // Still busy.
749:
750: cmd1 = fOwner->createWriteQuadCommand(testAddr, &quad, 1, Complete, (void *)quad);
751: cmd2 = fOwner->createWriteQuadCommand(testAddr, &quad1, 1, Complete, (void *)(quad+1));
752: cmd3 = fOwner->createWriteQuadCommand(testAddr, &quad2, 1);
753: state = 0;
754: cmd1->submit();
755: state |= 1;
756: //cmd2->submit();
757: cmd3->submit();
758: state |= 8;
759: status = cmd3->fStatus;
760:
761: cmd3->release();
762: return status;
763: }
764: #endif
765:
766: #if 0
767: IOReturn IOFireWireUserClient::Test()
768: {
769: IOBufferMemoryDescriptor * desc;
770: IOFWAddressSpace * space;
771: IOFWBusCommand * cmd = NULL;
772:
773: desc = IOBufferMemoryDescriptor::withCapacity(PAGE_SIZE,
774: kIODirectionOutIn, true);
775: if(!desc)
776: return kIOReturnNoMemory;
777: desc->setLength(PAGE_SIZE);
778: space = fOwner->createPhysicalAddressSpace(desc);
779: if(!space)
780: return kIOReturnNoMemory;
781: cmd = fOwner->createAllocAddrCommand(space);
782: if(!cmd)
783: return kIOReturnNoMemory;
784: cmd->submit();
785: cmd->release();
786: cmd = fOwner->createDeallocAddrCommand(space);
787: if(!cmd)
788: return kIOReturnNoMemory;
789: cmd->submit();
790: cmd->release();
791: space->release();
792: desc->release();
793:
794: return kIOReturnSuccess;
795: }
796: #endif
797:
798: // from IOKitLibPrivate.h!
799: enum {
800: kIOAsyncReservedIndex = 0,
801:
802: kIOAsyncCalloutFuncIndex = 1,
803: kIOAsyncCalloutRefconIndex,
804: kIOAsyncCalloutCount,
805: };
806:
807: void IOFireWireUserClient::kernPongProc(void *refcon, void * userProc, void * dclCommand)
808: {
809: IOReturn kr;
810: IOFireWireUserClient * me;
811: #if 0
812: if(donePings++ < 2)
813: IOLog("Ping! (or Pong!) %0x ->0x%x\n", dclCommand,
814: userProc);
815: #endif
816: me = (IOFireWireUserClient *)refcon;
817: theProg.asyncRef[kIOAsyncCalloutFuncIndex] = (natural_t) userProc;
818: theProg.asyncRef[kIOAsyncCalloutRefconIndex] = (natural_t) dclCommand;
819: kr = me->sendAsyncResult(theProg.asyncRef, kIOReturnSuccess, NULL, 0);
820: }
821:
822:
823: IOReturn IOFireWireUserClient::CompileDCL(UInt32 dclStart, UInt32 dclBase,
824: UInt32 dclSize, UInt32 dataBase, UInt32 dataSize, UInt32 *program)
825: {
826: IOReturn res;
827: // IOLog("DCL start:0x%x base:0x%x size:%d, Data base:0x%x, size:%d\n",
828: // dclStart, dclBase, dclSize, dataBase, dataSize);
829:
830: // Check that DCL program and data buffers are in single regions
831: vm_region_basic_info_data_t regionInfo;
832: mach_msg_type_number_t regionInfoSize = sizeof(regionInfo);
833: vm_size_t regionSize;
834: vm_offset_t checkBase = trunc_page(dclBase);
835: vm_size_t checkSize = round_page(dclSize);
836:
837: res = vm_region(
838: /* map */ get_task_map(fTask),
839: /* address */ &checkBase,
840: /* size */ ®ionSize,
841: /* flavor */ VM_REGION_BASIC_INFO,
842: /* info */ (vm_region_info_t) ®ionInfo,
843: /* info size */ ®ionInfoSize,
844: /* object name */ 0 );
845: if(res != kIOReturnSuccess)
846: return res;
847:
848: if(checkBase + regionSize < dclBase + dclSize)
849: return kIOReturnVMError;
850:
851: checkBase = trunc_page(dataBase);
852: checkSize = round_page(dataSize);
853: res = vm_region(
854: /* map */ get_task_map(fTask),
855: /* address */ &checkBase,
856: /* size */ ®ionSize,
857: /* flavor */ VM_REGION_BASIC_INFO,
858: /* info */ (vm_region_info_t) ®ionInfo,
859: /* info size */ ®ionInfoSize,
860: /* object name */ 0 );
861: if(res != kIOReturnSuccess)
862: return res;
863:
864: if(checkBase + regionSize < dataBase + dataSize)
865: return kIOReturnVMError;
866:
867: *program = &theProg;
868: IOFireWireBus::DCLTaskInfo info;
869: info.fTask = fTask;
870: info.fDCLBaseAddr = dclBase;
871: info.fDCLSize = dclSize;
872: info.fDataBaseAddr = dataBase;
873: info.fDataSize = dataSize;
874: info.fCallUser = kernPongProc;
875: info.fCallRefCon = this;
876: theProg.port = fOwner->fControl->createLocalIsochPort(false, (DCLCommand *)dclStart, &info);
877:
878: theProg.chan = fOwner->fControl->createIsochChannel(false, 488*8*8000, kFWSpeed100MBit);
879: theProg.dvPort = new DVPort;
880: theProg.dvPort->init(fOwner);
881: theProg.chan->addListener(theProg.port);
882: theProg.chan->setTalker(theProg.dvPort);
883: theProg.fState = 1;
884:
885: return kIOReturnSuccess;
886: }
887:
888: IOReturn IOFireWireUserClient::RunDCL(OSAsyncReference asyncRef, UInt32 program)
889: {
890: donePings = 0;
891: if(theProg.fState == 1) {
892: bcopy(asyncRef, theProg.asyncRef, sizeof(OSAsyncReference));
893: theProg.chan->allocateChannel();
894: theProg.chan->start();
895: theProg.fState = 2;
896: return kIOReturnSuccess;
897: }
898: else {
899: IOLog("RunDCL, state is %d not 1!\n", theProg.fState);
900: return kIOReturnNotReady;
901: }
902:
903: }
904:
905: IOReturn IOFireWireUserClient::StopDCL(UInt32 program)
906: {
907: if(theProg.fState == 2) {
908: theProg.chan->stop();
909: theProg.chan->releaseChannel();
910: }
911: theProg.chan->release();
912: theProg.dvPort->release();
913: theProg.port->release();
914:
915: theProg.fState = 0;
916: return kIOReturnSuccess;
917: }
918:
919:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.