xref: /openbmc/ipmitool/src/plugins/imb/imbapi.c (revision 89e9e634)
1 /*M*
2 //  PVCS:
3 //      $Workfile:   imbapi.c  $
4 //      $Revision: 1.5 $
5 //      $Modtime:   06 Aug 2001 13:16:56  $
6 //      $Author: stybla $
7 //
8 //  Purpose:    This file contains the entry point that opens the IMB device in
9 //              order to issue the  IMB driver API related IOCTLs.
10 //              This file implements the IMB driver API for the Server
11 //				Management Agents
12 //
13 //
14 *M*/
15 /*----------------------------------------------------------------------*
16 The BSD License
17 Copyright (c) 2002, Intel Corporation
18 All rights reserved.
19 Redistribution and use in source and binary forms, with or without
20 modification, are permitted provided that the following conditions are met:
21   a.. Redistributions of source code must retain the above copyright notice,
22       this list of conditions and the following disclaimer.
23   b.. Redistributions in binary form must reproduce the above copyright notice,
24       this list of conditions and the following disclaimer in the documentation
25       and/or other materials provided with the distribution.
26   c.. Neither the name of Intel Corporation nor the names of its contributors
27       may be used to endorse or promote products derived from this software
28       without specific prior written permission.
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
30 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
33 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
36 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  *----------------------------------------------------------------------*/
40 /*
41  * $Log: imbapi.c,v $
42  * Revision 1.5  2013/07/22 08:35:23  stybla
43  * ID: 65 - Fixes for configure.in for cross compilation
44  *
45  * 'src/plugins/imb/imbapi.c' - don't cast NULL to int, ever!!!
46  *
47  * Revision 1.4  2013/07/21 11:33:57  stybla
48  * ID: 65 - Fixes for configure.in for cross compilation
49  *
50  * NULL should never be cast to an int.
51  *
52  * Commit for Dan Gora
53  *
54  * Revision 1.3  2013/01/18 12:46:52  ledva
55  * 3600962 descriptor leaks
56  *
57  * Revision 1.2  2004/08/31 23:52:58  iceblink
58  * fix lots of little errors that show up with -Werror -Wall
59  *
60  * Revision 1.1  2004/08/27 16:33:25  iceblink
61  * add support for Intel IMB kernel driver (for legacy kernel support)
62  * imbapi.[ch] code is BSD licensed and taken from panicsel.sf.net
63  *
64  *
65  *    Rev 1.12ac 04 Apr 2002 13:17:58   arcress
66  * Mods for open-source & various compile cleanup mods
67  *
68  *    Rev 1.12   06 Aug 2001 13:17:58   spoola
69  * Fixed tracker items #15667, #15666, #15664
70  *
71  *    Rev 1.0   05 Sep 1999 17:20:30   mramacha
72  * Linux checkin
73  *
74  *	Note: This file is derived from the NTWORK version of the imbapi.c
75  *	It was decided to create OS specific ones for Linux and Solaris.
76  *	It has all the fixes that went into the imbapi.c up to Rev 1.12
77  *      in the 2.2 NTWORK branch.
78  */
79 
80 #define IMB_API
81 
82 #ifdef WIN32
83 #define NO_MACRO_ARGS  1
84 #include <windows.h>
85 #include <stdio.h>
86 
87 #else  /* LINUX, SCO_UW, UNIX */
88 #include <unistd.h>
89 #include <sys/param.h>
90 #include <sys/types.h>
91 #include <sys/stat.h>
92 #include <sys/mman.h>
93 #include <sys/ioctl.h>
94 #include <stdio.h>
95 #include <stdlib.h>
96 #include <fcntl.h>
97 #include <string.h>
98 #endif
99 #include "imbapi.h"
100 #include <asm/socket.h>
101 
102 #ifdef SCO_UW
103 #define NO_MACRO_ARGS  1
104 #define __FUNCTION__ "func"
105 #define IMB_DEVICE "/dev/instru/mismic"
106 #else
107 #define IMB_DEVICE "/dev/imb"
108 #ifndef PAGESIZE
109 # define PAGESIZE EXEC_PAGESIZE
110 #endif
111 #endif
112 
113 /*Just to make the DEBUG code cleaner.*/
114 #ifndef NO_MACRO_ARGS
115 #ifdef LINUX_DEBUG
116 #define DEBUG(format, args...) printf(format, ##args)
117 #else
118 #define DEBUG(format, args...)
119 #endif
120 #endif
121 
122 /* uncomment out the #define below or use -DLINUX_DEBUG_MAX in the makefile
123 // if you want a dump of the memory to debug mmap system call in
124 // MapPhysicalMemory() below.
125 //
126 //#define LINUX_DEBUG_MAX */
127 
128 
129 /*keep it simple. use global varibles for event objects and handles
130 //pai 10/8 */
131 
132 /* UnixWare should eventually have its own source code file. Right now
133 // new code has been added based on the exsisting policy of using
134 // pre-processor directives to separate os-specific code (pai 11/21) */
135 
136 HANDLE  AsyncEventHandle = 0;
137 //static void *  AsyncEventObject = 0;
138 static int  IpmiVersion;
139 
140 /*////////////////////////////////////////////////////////////////////////////
141 //  GLOBAL VARIABLES
142 ///////////////////////////////////////////////////////////////////////////// */
143 
144 IO_STATUS_BLOCK NTstatus; /*dummy place holder. See deviceiocontrol. */
145 static HANDLE   hDevice1;
146 static HANDLE   hDevice;
147 /*mutex_t deviceMutex; */
148 static int fDriverTyp;    /*from ipmicmd.c*/
149 
150 /*////////////////////////////////////////////////////////////////////
151 // open_imb
152 ////////////////////////////////////////////////////////////////////// */
153 /*F*
154 //  Name:       open_imb
155 //  Purpose:    To open imb device
156 //  Context:    Called from each routine to make sure that open is done.
157 //  Returns:    returns 0 for Fail and 1 for Success, sets hDevice to open
158 //              handle.
159 //  Parameters: none
160 //  Notes:      none
161 *F*/
162 #ifdef WIN32
163 int open_imb(void)
164 {
165 /* This routine will be called from all other routines before doing any
166    interfacing with imb driver. It will open only once. */
167 	IMBPREQUESTDATA                requestData;
168 	BYTE						   respBuffer[16];
169 	DWORD						   respLength;
170 	BYTE						   completionCode;
171 
172   if (hDevice1 == 0)  /*INVALID_HANDLE_VALUE*/
173   {
174         //
175         // Open IMB driver device
176         //
177         hDevice = CreateFile(   "\\\\.\\Imb",
178                                 GENERIC_READ | GENERIC_WRITE,
179                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
180                                 NULL,
181                                 OPEN_EXISTING,
182                                 FILE_ATTRIBUTE_NORMAL,
183                                 NULL
184                             );
185         if (hDevice == NULL || hDevice == INVALID_HANDLE_VALUE)
186             return (0);  /*FALSE*/
187 
188         // Detect the IPMI version for processing requests later.
189         // This is a crude but most reliable method to differentiate
190         // between old IPMI versions and the 1.0 version. If we had used the
191         // version field instead then we would have had to revalidate all the
192         // older platforms (pai 4/27/99)
193         requestData.cmdType            = GET_DEVICE_ID;
194         requestData.rsSa               = BMC_SA;
195         requestData.rsLun              = BMC_LUN;
196         requestData.netFn              = APP_NETFN ;
197         requestData.busType            = PUBLIC_BUS;
198         requestData.data               = NULL;
199         requestData.dataLength         = 0;
200         respLength                     = 16;
201         if ( (SendTimedImbpRequest ( &requestData, (DWORD)400,
202                          respBuffer, &respLength, &completionCode
203                         )  != ACCESN_OK ) || ( completionCode != 0) )
204         {
205                     CloseHandle(hDevice);
206                     return (0);  /*FALSE*/
207         }
208         hDevice1 = hDevice;
209 
210         if (respLength < (IPMI10_GET_DEVICE_ID_RESP_LENGTH-1))
211             IpmiVersion = IPMI_09_VERSION;
212 		else {
213 				if ( respBuffer[4] == 0x51 )
214 					IpmiVersion = IPMI_15_VERSION;
215 				else
216 					IpmiVersion = IPMI_10_VERSION;
217 			}
218    }
219    return (1);  /*TRUE*/
220 
221 } /*end open_imb for Win32 */
222 
223 #else  /* LINUX, SCO_UW, etc. */
224 
225 int open_imb(void)
226 {
227 /* This routine will be called from all other routines before doing any
228    interfacing with imb driver. It will open only once. */
229 	IMBPREQUESTDATA                requestData;
230 	BYTE						   respBuffer[16];
231 	DWORD						   respLength;
232 	BYTE						   completionCode;
233 
234 	int my_ret_code;
235 
236   if (hDevice1 == 0)
237   {
238 #ifndef NO_MACRO_ARGS
239 			DEBUG("%s: opening the driver\n", __FUNCTION__);
240 #endif
241 	/*
242       printf("open_imb: "
243 	"IOCTL_IMB_SEND_MESSAGE =%x \n" "IOCTL_IMB_GET_ASYNC_MSG=%x \n"
244 	"IOCTL_IMB_MAP_MEMORY  = %x \n" "IOCTL_IMB_UNMAP_MEMORY= %x \n"
245 	"IOCTL_IMB_SHUTDOWN_CODE=%x \n" "IOCTL_IMB_REGISTER_ASYNC_OBJ  =%x \n"
246 	"IOCTL_IMB_DEREGISTER_ASYNC_OBJ=%x \n"
247 	"IOCTL_IMB_CHECK_EVENT  =%x \n" "IOCTL_IMB_POLL_ASYNC   =%x \n",
248              IOCTL_IMB_SEND_MESSAGE, IOCTL_IMB_GET_ASYNC_MSG,
249 	IOCTL_IMB_MAP_MEMORY, IOCTL_IMB_UNMAP_MEMORY, IOCTL_IMB_SHUTDOWN_CODE,
250 	IOCTL_IMB_REGISTER_ASYNC_OBJ, IOCTL_IMB_DEREGISTER_ASYNC_OBJ,
251 	IOCTL_IMB_CHECK_EVENT , IOCTL_IMB_POLL_ASYNC);  *%%%%*/
252 
253 		/*O_NDELAY flag will cause problems later when driver makes
254 		//you wait. Hence removing it. */
255 		    /*if ((hDevice1 = open(IMB_DEVICE,O_RDWR|O_NDELAY)) <0)  */
256 		    if ((hDevice1 = open(IMB_DEVICE,O_RDWR)) <0)
257 			{
258 				char buf[128];
259 
260 				hDevice1  = 0;
261 				if (fDriverTyp != 0) {  /*not 1st time*/
262 				  sprintf(buf,"%s %s: open(%s) failed",
263 					__FILE__,__FUNCTION__,IMB_DEVICE);
264 				  perror(buf);
265 				}
266 				return (0);
267 			}
268 
269 			/* Detect the IPMI version for processing requests later.
270 			// This is a crude but most reliable method to differentiate
271 			// between old IPMI versions and the 1.0 version. If we had used the
272 			// version field instead then we would have had to revalidate all
273 			// the older platforms (pai 4/27/99) */
274 			requestData.cmdType            = GET_DEVICE_ID;
275 			requestData.rsSa               = BMC_SA;
276 			requestData.rsLun              = BMC_LUN;
277 			requestData.netFn              = APP_NETFN ;
278 			requestData.busType            = PUBLIC_BUS;
279 			requestData.data               = NULL;
280 			requestData.dataLength			= 0;
281 			respLength					    = 16;
282 #ifndef NO_MACRO_ARGS
283 			DEBUG("%s: opened driver, getting IPMI version\n", __FUNCTION__);
284 #endif
285 			if ( ((my_ret_code = SendTimedImbpRequest(&requestData, (DWORD)400,
286 						 respBuffer, (int *)&respLength, &completionCode)
287 						)  != ACCESN_OK ) || ( completionCode != 0) )
288 			{
289 				printf("%s: SendTimedImbpRequest error. Ret = %d CC = 0x%X\n",
290 					__FUNCTION__, my_ret_code, completionCode);
291 					close(hDevice1);
292 					hDevice1 = 0;
293 					return (0);
294 			}
295 
296 			if (respLength < (IPMI10_GET_DEVICE_ID_RESP_LENGTH-1))
297 				IpmiVersion = IPMI_09_VERSION;
298 			else {
299 				if ( respBuffer[4] == 0x51 )
300 					IpmiVersion = IPMI_15_VERSION;
301 				else
302 					IpmiVersion = IPMI_10_VERSION;
303 			}
304 #ifndef NO_MACRO_ARGS
305 			DEBUG("%s: IPMI version 0x%x\n", __FUNCTION__, IpmiVersion);
306 #endif
307 
308 /*
309 //initialise a mutex
310 		if(mutex_init(&deviceMutex , USYNC_THREAD, NULL) != 0)
311 		{
312 			return(0);
313 		}
314 */
315 
316 	}
317 
318 	return (1);
319 }  /*end open_imb()*/
320 #endif
321 
322 /*---------------------------------------------------------------------*
323  * ipmi_open_ia  & ipmi_close_ia
324  *---------------------------------------------------------------------*/
325 int ipmi_open_ia(void)
326 {
327    int rc = 0;
328    rc = open_imb();    /*sets hDevice1*/
329    if (rc == 1) rc = 0;
330    else rc = -1;
331    return(rc);
332 }
333 
334 int ipmi_close_ia(void)
335 {
336    int rc = 0;
337    if (hDevice1 != 0) {
338 #ifdef WIN32
339         CloseHandle(hDevice1);
340 #else
341         rc = close(hDevice1);
342 #endif
343    }
344    return(rc);
345 }
346 
347 #ifndef WIN32
348 /*///////////////////////////////////////////////////////////////////////////
349 // DeviceIoControl
350 ///////////////////////////////////////////////////////////////////////////// */
351 /*F*
352 //  Name:       DeviceIoControl
353 //  Purpose:    Simulate NT DeviceIoControl using unix calls and structures.
354 //  Context:    called for every NT DeviceIoControl
355 //  Returns:    FALSE for fail and TRUE for success. Same as standarad NTOS call
356 //              as it also sets Ntstatus.status.
357 //  Parameters: Standard NT call parameters, see below.
358 //  Notes:      none
359 *F*/
360 static BOOL
361 DeviceIoControl(
362 	HANDLE 			dummey_hDevice, /* handle of device */
363 	DWORD 			dwIoControlCode, /* control code of operation to perform*/
364 	LPVOID 			lpvInBuffer, /* address of buffer for input data */
365 	DWORD 			cbInBuffer, /* size of input buffer */
366 	LPVOID 			lpvOutBuffer, /* address of output buffer */
367 	DWORD 			cbOutBuffer, /* size of output buffer */
368 	LPDWORD 		lpcbBytesReturned, /* address of actual bytes of output */
369 	LPOVERLAPPED 	lpoOverlapped /* address of overlapped struct */
370 	)
371 {
372 	struct smi s;
373 	int rc;
374 	int ioctl_status;
375 
376   	rc = open_imb();
377   	if (rc == 0) {
378     	return FALSE;
379     }
380 
381 	/*
382 		//lock the mutex, before making the request....
383 		if(mutex_lock(&deviceMutex) != 0)
384 		{
385 			return(FALSE);
386 		}
387 	*/
388 #ifndef NO_MACRO_ARGS
389 	DEBUG("%s: ioctl cmd = 0x%lx ", __FUNCTION__,dwIoControlCode);
390 	DEBUG("cbInBuffer %d cbOutBuffer %d\n", cbInBuffer, cbOutBuffer);
391 #endif
392 	if (cbInBuffer > 41) cbInBuffer = 41;  /* Intel driver max buf */
393 
394   	s.lpvInBuffer = lpvInBuffer;
395   	s.cbInBuffer = cbInBuffer;
396   	s.lpvOutBuffer = lpvOutBuffer;
397   	s.cbOutBuffer = cbOutBuffer;
398   	s.lpcbBytesReturned = lpcbBytesReturned;
399   	s.lpoOverlapped = lpoOverlapped;
400   	s.ntstatus = (LPVOID)&NTstatus; /*dummy place holder. Linux IMB driver
401 					//doesnt return status or info via it.*/
402 
403   	if ( (ioctl_status = ioctl(hDevice1, dwIoControlCode,&s) ) <0) {
404 #ifndef NO_MACRO_ARGS
405  	  	DEBUG("%s %s: ioctl cmd = 0x%x failed",
406 			__FILE__,__FUNCTION__,dwIoControlCode);
407 #endif
408 		/*      mutex_unlock(&deviceMutex); */
409     	return FALSE;
410     }
411 	/*      mutex_unlock(&deviceMutex); */
412 
413 #ifndef NO_MACRO_ARGS
414 	DEBUG("%s: ioctl_status %d  bytes returned =  %d \n",
415 		 __FUNCTION__, ioctl_status,  *lpcbBytesReturned);
416 #endif
417 
418 /*MR commented this just as in Sol1.10. lpcbBytesReturned has the right data
419 //  	*lpcbBytesReturned = NTstatus.Information; */
420 
421 	if (ioctl_status == STATUS_SUCCESS) {
422 #ifndef NO_MACRO_ARGS
423 		DEBUG("%s returning true\n", __FUNCTION__);
424 #endif
425      	return (TRUE);
426 	}
427 	else {
428 #ifndef NO_MACRO_ARGS
429 		DEBUG("%s returning false\n", __FUNCTION__);
430 #endif
431      	return (FALSE);
432      }
433 }
434 #endif
435 
436 /*Used only by UW. Left here for now. IMB driver will not accept this
437 //ioctl. */
438 ACCESN_STATUS
439 StartAsyncMesgPoll()
440 {
441 
442 	DWORD   retLength;
443 	BOOL    status;
444 
445 #ifndef NO_MACRO_ARGS
446 	DEBUG("%s: DeviceIoControl cmd = %x\n",__FUNCTION__,IOCTL_IMB_POLL_ASYNC);
447 #endif
448 	status = DeviceIoControl (      hDevice,
449 								IOCTL_IMB_POLL_ASYNC,
450 								NULL,
451 								0,
452 								NULL,
453 								0,
454 								& retLength,
455 								0
456 							);
457 
458 #ifndef NO_MACRO_ARGS
459 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
460 #endif
461 
462 	if( status == TRUE ) {
463 		return ACCESN_OK;
464 	} else {
465 		return ACCESN_ERROR;
466 	}
467 
468 }
469 
470 /*/////////////////////////////////////////////////////////////////////////////
471 // SendTimedI2cRequest
472 ///////////////////////////////////////////////////////////////////////////// */
473 /*F*
474 //  Name:       SendTimedI2cRequest
475 //  Purpose:    This function sends a request to a I2C device
476 //  Context:    Used by Upper level agents (sis modules) to access dumb I2c devices
477 //  Returns:    ACCESN_OK  else error status code
478 //  Parameters:
479 //     reqPtr
480 //     timeOut
481 //     respDataPtr
482 //     respLen
483 //  Notes:      none
484 *F*/
485 
486 ACCESN_STATUS
487 SendTimedI2cRequest (
488 		I2CREQUESTDATA 	*reqPtr,         /* I2C request */
489 		int     timeOut,         /* how long to wait, mSec units */
490 		BYTE 	*respDataPtr,    /* where to put response data */
491 		int 	*respDataLen,    /* size of response buffer and */
492 					 /* size of returned data */
493 		BYTE 	*completionCode  /* request status from BMC */
494 	)
495 {
496 	BOOL  					status;
497     BYTE                  	responseData[MAX_IMB_RESP_SIZE];
498 	ImbResponseBuffer *     resp = (ImbResponseBuffer *) responseData;
499 	DWORD                   respLength = sizeof( responseData );
500     BYTE                    requestData[MAX_IMB_RESP_SIZE];
501 	ImbRequestBuffer *      req = (ImbRequestBuffer *) requestData;
502 
503 	struct WriteReadI2C {   /* format of a write/read I2C request */
504 		BYTE    busType;
505 		BYTE    rsSa;
506 		BYTE    count;
507 		BYTE    data[1];
508 	} * wrReq = (struct WriteReadI2C *) req->req.data;
509 
510 #define MIN_WRI2C_SIZE  3       /* size of write/read request minus any data */
511 
512 
513 	/*
514 	// If the Imb driver is not present return AccessFailed
515 	*/
516 
517 	req->req.rsSa           = BMC_SA;
518 	req->req.cmd            = WRITE_READ_I2C;
519 	req->req.netFn          = APP_NETFN;
520 	req->req.rsLun          = BMC_LUN;
521 	req->req.dataLength     = reqPtr->dataLength + MIN_WRI2C_SIZE;
522 
523 	wrReq->busType          = reqPtr->busType;
524 	wrReq->rsSa                     = reqPtr->rsSa;
525 	wrReq->count            = reqPtr->numberOfBytesToRead;
526 
527 	memcpy( wrReq->data, reqPtr->data, reqPtr->dataLength );
528 
529 	req->flags      = 0;
530 	req->timeOut    = timeOut * 1000;       /* convert to uSec units */
531 
532 	status = DeviceIoControl(       hDevice,
533 					IOCTL_IMB_SEND_MESSAGE,
534 					requestData,
535 					sizeof( requestData ),
536 					& responseData,
537 					sizeof( responseData ),
538 					& respLength,
539 					NULL
540 				  );
541 #ifndef NO_MACRO_ARGS
542 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
543 #endif
544 
545 	if( status != TRUE ) {
546 		DWORD error;
547 		error = GetLastError();
548 		return ACCESN_ERROR;
549 	}
550 	if( respLength == 0 ) {
551 		return ACCESN_ERROR;
552 	}
553 
554 	/*
555 	// give the caller his response
556 	*/
557 	*completionCode = resp->cCode;
558 	*respDataLen    = respLength - 1;
559 
560 	if(( *respDataLen ) && (respDataPtr))
561 		memcpy( respDataPtr, resp->data, *respDataLen);
562 
563 	return ACCESN_OK;
564 
565 }
566 
567 /*This is not a  API exported by the driver in stricter sense. It is
568 //added to support EMP functionality. Upper level software could have
569 //implemented this function.(pai 5/4/99)  */
570 /*/////////////////////////////////////////////////////////////////////////////
571 // SendTimedEmpMessageResponse
572 ///////////////////////////////////////////////////////////////////////////// */
573 
574 /*F*
575 //  Name:       SendTimedEmpMessageResponse
576 //  Purpose:    This function sends a response message to the EMP port
577 //  Context:
578 //  Returns:    OK  else error status code
579 //  Parameters:
580 //
581 //  Notes:      none
582 *F*/
583 
584 ACCESN_STATUS
585 SendTimedEmpMessageResponse (
586 		ImbPacket *ptr,       /* pointer to the original request from EMP */
587 		char      *responseDataBuf,
588 		int       responseDataLen,
589 		int       timeOut         /* how long to wait, in mSec units */
590 	)
591 {
592 	BOOL                    status;
593     BYTE                    responseData[MAX_IMB_RESP_SIZE];
594 	/*ImbResponseBuffer *     resp = (ImbResponseBuffer *) responseData; */
595 	DWORD                   respLength = sizeof( responseData );
596     BYTE                    requestData[MAX_IMB_RESP_SIZE];
597 	ImbRequestBuffer *      req = (ImbRequestBuffer *) requestData;
598 	int 					i,j;
599 
600 	/*form the response packet first */
601 	req->req.rsSa           =  BMC_SA;
602 	if (IpmiVersion ==	IPMI_09_VERSION)
603 	req->req.cmd            =  WRITE_EMP_BUFFER;
604 	else
605 	req->req.cmd            =  SEND_MESSAGE;
606 	req->req.netFn          =  APP_NETFN;
607 	req->req.rsLun          =  0;
608 
609 	i = 0;
610 	if (IpmiVersion !=	IPMI_09_VERSION)
611 		req->req.data[i++] 	= EMP_CHANNEL;
612 
613 	req->req.data[i++]    =  ptr->rqSa;
614 	req->req.data[i++]      =  (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3));
615 	if (IpmiVersion ==	IPMI_09_VERSION)
616 		req->req.data[i++]    = ((~(req->req.data[0] +  req->req.data[1])) +1);
617 	else
618 		req->req.data[i++]    = ((~(req->req.data[1] +  req->req.data[2])) +1);
619 
620 	req->req.data[i++]      =  BMC_SA; /*though software is responding, we have to
621 					   //provide BMCs slave address as responder
622 					   //address.  */
623 
624 	req->req.data[i++]      = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) );
625 
626 	req->req.data[i++]      = ptr->cmd;
627 	for ( j = 0 ; j < responseDataLen ; ++j,++i)
628 	   req->req.data[i] = responseDataBuf[j];
629 
630 	 req->req.data[i] = 0;
631 	 if (IpmiVersion ==	IPMI_09_VERSION)
632 		 j = 0;
633 	 else
634 		 j = 1;
635 	for ( ; j < ( i -3); ++j)
636 		 req->req.data[i] += req->req.data[j+3];
637 	req->req.data[i]  = ~(req->req.data[i]) +1;
638 	++i;
639 	req->req.dataLength     = i;
640 
641 	req->flags      = 0;
642 	req->timeOut    = timeOut * 1000;       /* convert to uSec units */
643 
644 
645 	status = DeviceIoControl(       hDevice,
646 					IOCTL_IMB_SEND_MESSAGE,
647 					requestData,
648 					sizeof(requestData),
649 					responseData,
650 					sizeof( responseData ),
651 					& respLength,
652 					NULL
653 				  );
654 
655 #ifndef NO_MACRO_ARGS
656 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
657 #endif
658 
659 
660 	if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) )
661 	{
662 		return ACCESN_ERROR;
663 	}
664 	return ACCESN_OK;
665 }
666 
667 
668 /*This is not a  API exported by the driver in stricter sense. It is added to support
669 // EMP functionality. Upper level software could have implemented this function.(pai 5/4/99) */
670 /*///////////////////////////////////////////////////////////////////////////
671 // SendTimedEmpMessageResponse_Ex
672 //////////////////////////////////////////////////////////////////////////// */
673 
674 /*F*
675 //  Name:       SendTimedEmpMessageResponse_Ex
676 //  Purpose:    This function sends a response message to the EMP port
677 //  Context:
678 //  Returns:    OK  else error status code
679 //  Parameters:
680 //
681 //  Notes:      none
682 *F*/
683 
684 
685 
686 ACCESN_STATUS
687 SendTimedEmpMessageResponse_Ex (
688 
689 		ImbPacket *      ptr,       /* pointer to the original request from EMP */
690 		char      *responseDataBuf,
691 		int        responseDataLen,
692 		int         timeOut,        /* how long to wait, in mSec units*/
693 		BYTE		sessionHandle,	/*This is introduced in IPMI1.5,this is required to be sent in
694 			//send message command as a parameter,which is then used by BMC
695 			//to identify the correct DPC session to send the mesage to. */
696 		BYTE		channelNumber	/*There are 3 different channels on which DPC communication goes on
697 			//Emp - 1,Lan channel one - 6,Lan channel two(primary channel) - 7. */
698 	)
699 {
700 	BOOL                    status;
701     BYTE                    responseData[MAX_IMB_RESP_SIZE];
702 	/* ImbResponseBuffer *  resp = (ImbResponseBuffer *) responseData; */
703 	DWORD                   respLength = sizeof( responseData );
704     BYTE                    requestData[MAX_IMB_RESP_SIZE];
705 	ImbRequestBuffer *      req = (ImbRequestBuffer *) requestData;
706 	int 					i,j;
707 
708 	/*form the response packet first */
709 	req->req.rsSa           =  BMC_SA;
710 	if (IpmiVersion ==	IPMI_09_VERSION)
711 	req->req.cmd            =  WRITE_EMP_BUFFER;
712 	else
713 	req->req.cmd            =  SEND_MESSAGE;
714 	req->req.netFn          =  APP_NETFN;
715 	req->req.rsLun          =  0;
716 
717 	i = 0;
718 
719 	/*checking for the IPMI version & then assigning the channel number for EMP
720 	//Actually the channel number is same in both the versions.This is just to
721 	//maintain the consistancy with the same method for LAN.
722 	//This is the 1st byte of the SEND MESSAGE command. */
723 	if (IpmiVersion ==	IPMI_10_VERSION)
724 		req->req.data[i++] 	= EMP_CHANNEL;
725 	else if (IpmiVersion ==	IPMI_15_VERSION)
726 		req->req.data[i++] 	= channelNumber;
727 
728 	/*The second byte of data for SEND MESSAGE starts with session handle */
729 	req->req.data[i++] = sessionHandle;
730 
731 	/*Then it is the response slave address for SEND MESSAGE. */
732 	req->req.data[i++]    =  ptr->rqSa;
733 
734 	/*Then the net function + lun for SEND MESSAGE command. */
735 	req->req.data[i++]      =  (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3));
736 
737 	/*Here the checksum is calculated.The checksum calculation starts after the channel number.
738 	//so for the IPMI 1.5 version its a checksum of 3 bytes that is session handle,response slave
739 	//address & netfun+lun. */
740 	if (IpmiVersion ==	IPMI_09_VERSION)
741 		req->req.data[i++]    = ((~(req->req.data[0] +  req->req.data[1])) +1);
742 	else
743 	{
744 		if (IpmiVersion == IPMI_10_VERSION)
745 			req->req.data[i++]    = ((~(req->req.data[1] +  req->req.data[2])) +1);
746         else
747 			req->req.data[i++]    = ((~(req->req.data[2]+  req->req.data[3])) +1);
748 	}
749 
750 	/*This is the next byte of the message data for SEND MESSAGE command.It is the request
751 	//slave address. */
752 	req->req.data[i++]      =  BMC_SA; /*though software is responding, we have to
753 					   //provide BMCs slave address as responder
754 					   //address. */
755 
756 	/*This is just the sequence number,which is the next byte of data for SEND MESSAGE */
757 	req->req.data[i++]      = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) );
758 
759 	/*The next byte is the command like get software ID(00).*/
760 	req->req.data[i++]      = ptr->cmd;
761 
762 	/*after the cmd the data ,which is sent by DPC & is retrived using the get message earlier
763 	// is sent back to DPC. */
764 	for ( j = 0 ; j < responseDataLen ; ++j,++i)
765 	   req->req.data[i] = responseDataBuf[j];
766 
767 	 req->req.data[i] = 0;
768 
769 	 /*The last byte of data for SEND MESSAGE command is the check sum ,which is calculated
770 	 //from the next byte of the previous checksum that is the request slave address. */
771 	 if (IpmiVersion ==	IPMI_09_VERSION)
772 		 j = 0;
773 	 else
774 	 {
775 		if (IpmiVersion ==	IPMI_10_VERSION)
776 			j = 1;
777 		else
778 			j = 2;
779 	 }
780 	for ( ; j < ( i -3); ++j)
781 		 req->req.data[i] += req->req.data[j+3];
782 	req->req.data[i]  = ~(req->req.data[i]) +1;
783 	++i;
784 	req->req.dataLength     = i;
785 
786 	/*The flags & timeouts are used by the driver internally. */
787 	req->flags      = 0;
788 	req->timeOut    = timeOut * 1000;       /* convert to uSec units */
789 
790 	status = DeviceIoControl(       hDevice,
791 					IOCTL_IMB_SEND_MESSAGE,
792 					requestData,
793 					sizeof(requestData),
794 					responseData,
795 					sizeof( responseData ),
796 					& respLength,
797 					NULL
798 				  );
799 
800 
801 #ifndef NO_MACRO_ARGS
802 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
803 #endif
804 
805 
806 	if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) )
807 	{
808 		return ACCESN_ERROR;
809 	}
810 	return ACCESN_OK;
811 
812 
813 
814 }
815 
816 /*This is not a  API exported by the driver in stricter sense. It is
817 //added to support EMP functionality. Upper level software could have
818 //implemented this function.(pai 5/4/99) */
819 /*///////////////////////////////////////////////////////////////////////////
820 // SendTimedLanMessageResponse
821 ///////////////////////////////////////////////////////////////////////////// */
822 
823 /*F*
824 //  Name:       SendTimedLanMessageResponse
825 //  Purpose:    This function sends a response message to the DPC Over Lan
826 //  Context:
827 //  Returns:    OK  else error status code
828 //  Parameters:
829 //
830 //  Notes:      none
831 *F*/
832 
833 ACCESN_STATUS
834 SendTimedLanMessageResponse(
835 		ImbPacket *ptr,       /* pointer to the original request from EMP */
836 		char      *responseDataBuf,
837 		int       responseDataLen,
838 		int       timeOut         /* how long to wait, in mSec units */
839 	)
840 {
841 	BOOL                    status;
842     BYTE                    responseData[MAX_IMB_RESP_SIZE];
843 	/* ImbResponseBuffer *     resp = (ImbResponseBuffer *) responseData; */
844 	DWORD                   respLength = sizeof( responseData );
845     BYTE                    requestData[MAX_IMB_RESP_SIZE];
846 	ImbRequestBuffer *      req = (ImbRequestBuffer *) requestData;
847 	int 					i,j;
848 
849 	/*form the response packet first */
850 	req->req.rsSa           =  BMC_SA;
851 	if (IpmiVersion ==	IPMI_09_VERSION)
852 	req->req.cmd            =  WRITE_EMP_BUFFER;
853 	else
854 	req->req.cmd            =  SEND_MESSAGE;
855 	req->req.netFn          =  APP_NETFN;
856 
857 	/* After discussion with firmware team (Shailendra), the lun number needs to stay at 0
858 	// even though the DPC over Lan firmware EPS states that the lun should be 1 for DPC
859 	// Over Lan. - Simont (5/17/00) */
860 	req->req.rsLun          =  0;
861 
862 	i = 0;
863 	if (IpmiVersion !=	IPMI_09_VERSION)
864 		req->req.data[i++] 	= LAN_CHANNEL;
865 
866 	req->req.data[i++]    =  ptr->rqSa;
867 	req->req.data[i++]      =  (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3));
868 	if (IpmiVersion ==	IPMI_09_VERSION)
869 		req->req.data[i++]    = ((~(req->req.data[0] +  req->req.data[1])) +1);
870 	else
871 		req->req.data[i++]    = ((~(req->req.data[1] +  req->req.data[2])) +1);
872 
873 	req->req.data[i++]      =  BMC_SA; /*though software is responding, we have to
874 					   //provide BMCs slave address as responder
875 					   //address. */
876 
877 	req->req.data[i++]      = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) );
878 
879 	req->req.data[i++]      = ptr->cmd;
880 	for ( j = 0 ; j < responseDataLen ; ++j,++i)
881 	   req->req.data[i] = responseDataBuf[j];
882 
883 	 req->req.data[i] = 0;
884 	 if (IpmiVersion ==	IPMI_09_VERSION)
885 		 j = 0;
886 	 else
887 		 j = 1;
888 	for ( ; j < ( i -3); ++j)
889 		 req->req.data[i] += req->req.data[j+3];
890 	req->req.data[i]  = ~(req->req.data[i]) +1;
891 	++i;
892 	req->req.dataLength     = i;
893 
894 	req->flags      = 0;
895 	req->timeOut    = timeOut * 1000;       /* convert to uSec units */
896 
897 
898 	status = DeviceIoControl(       hDevice,
899 					IOCTL_IMB_SEND_MESSAGE,
900 					requestData,
901 					sizeof(requestData),
902 					responseData,
903 					sizeof( responseData ),
904 					& respLength,
905 					NULL
906 				  );
907 
908 #ifndef NO_MACRO_ARGS
909 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
910 #endif
911 
912 	if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) )
913 	{
914 		return ACCESN_ERROR;
915 	}
916 	return ACCESN_OK;
917 }
918 
919 /*This is not a  API exported by the driver in stricter sense. It is
920 //added to support EMP functionality. Upper level software could have
921 //implemented this function.(pai 5/4/99) */
922 /*///////////////////////////////////////////////////////////////////////////
923 // SendTimedLanMessageResponse_Ex
924 ///////////////////////////////////////////////////////////////////////////// */
925 
926 /*F*
927 //  Name:       SendTimedLanMessageResponse_Ex
928 //  Purpose:    This function sends a response message to the DPC Over Lan
929 //  Context:
930 //  Returns:    OK  else error status code
931 //  Parameters:
932 //
933 //  Notes:      none
934 *F*/
935 
936 ACCESN_STATUS
937 SendTimedLanMessageResponse_Ex(
938 		ImbPacket *ptr,       /* pointer to the original request from EMP */
939 		char      *responseDataBuf,
940 		int       responseDataLen,
941 		int       timeOut  ,		/* how long to wait, in mSec units */
942 		BYTE		sessionHandle,	/*This is introduced in IPMI1.5,this is required to be sent in
943 			//send message command as a parameter,which is then used by BMC
944 			//to identify the correct DPC session to send the mesage to. */
945 		BYTE		channelNumber	/*There are 3 different channels on which DPC communication goes on
946 			//Emp - 1,Lan channel one - 6,Lan channel two(primary channel) - 7. */
947 	)
948 {
949 	BOOL                    status;
950     BYTE                    responseData[MAX_IMB_RESP_SIZE];
951 	/* ImbResponseBuffer *     resp = (ImbResponseBuffer *) responseData; */
952 	DWORD                   respLength = sizeof( responseData );
953     BYTE                    requestData[MAX_IMB_RESP_SIZE];
954 	ImbRequestBuffer *      req = (ImbRequestBuffer *) requestData;
955 	int 					i,j;
956 
957 	/*form the response packet first */
958 	req->req.rsSa           =  BMC_SA;
959 	if (IpmiVersion ==	IPMI_09_VERSION)
960 	req->req.cmd            =  WRITE_EMP_BUFFER;
961 	else
962 	req->req.cmd            =  SEND_MESSAGE;
963 	req->req.netFn          =  APP_NETFN;
964 
965 	/* After discussion with firmware team (Shailendra), the lun number needs to stay at 0
966 	// even though the DPC over Lan firmware EPS states that the lun should be 1 for DPC
967 	// Over Lan. - Simont (5/17/00) */
968 	req->req.rsLun          =  0;
969 
970 	i = 0;
971 
972 	/*checking for the IPMI version & then assigning the channel number for Lan accordingly.
973 	//This is the 1st byte of the SEND MESSAGE command. */
974 	if (IpmiVersion ==	IPMI_10_VERSION)
975 		req->req.data[i++] 	= LAN_CHANNEL;
976 	else if (IpmiVersion ==	IPMI_15_VERSION)
977 		req->req.data[i++] 	= channelNumber;
978 
979 	/*The second byte of data for SEND MESSAGE starts with session handle */
980 	req->req.data[i++] = sessionHandle;
981 
982 	/*Then it is the response slave address for SEND MESSAGE. */
983 	req->req.data[i++]    =  ptr->rqSa;
984 
985 	/*Then the net function + lun for SEND MESSAGE command. */
986 	req->req.data[i++]      =  (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3));
987 
988 	/*Here the checksum is calculated.The checksum calculation starts after the channel number.
989 	//so for the IPMI 1.5 version its a checksum of 3 bytes that is session handle,response slave
990 	//address & netfun+lun. */
991 	if (IpmiVersion ==	IPMI_09_VERSION)
992 		req->req.data[i++]    = ((~(req->req.data[0] +  req->req.data[1])) +1);
993 	else
994 	{
995 		if (IpmiVersion == IPMI_10_VERSION)
996 			req->req.data[i++]    = ((~(req->req.data[1] +  req->req.data[2])) +1);
997         else
998 			req->req.data[i++]    = ((~(req->req.data[2]+  req->req.data[3])) +1);
999 	}
1000 
1001 	/*This is the next byte of the message data for SEND MESSAGE command.It is the request
1002 	//slave address. */
1003 	req->req.data[i++]      =  BMC_SA; /*though software is responding, we have to
1004 					   //provide BMC's slave address as responder
1005 					   //address. */
1006 
1007 	/*This is just the sequence number,which is the next byte of data for SEND MESSAGE */
1008 	req->req.data[i++]      = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) );
1009 
1010 	/*The next byte is the command like get software ID(00). */
1011 	req->req.data[i++]      = ptr->cmd;
1012 
1013 	/*after the cmd the data ,which is sent by DPC & is retrived using the get message earlier
1014 	// is sent back to DPC. */
1015 	for ( j = 0 ; j < responseDataLen ; ++j,++i)
1016 	   req->req.data[i] = responseDataBuf[j];
1017 
1018 	 req->req.data[i] = 0;
1019 
1020 	 /*The last byte of data for SEND MESSAGE command is the check sum ,which is calculated
1021 	 //from the next byte of the previous checksum that is the request slave address. */
1022 	 if (IpmiVersion ==	IPMI_09_VERSION)
1023 		 j = 0;
1024 	 else
1025 	{
1026 		if (IpmiVersion ==	IPMI_10_VERSION)
1027 			j = 1;
1028 		else
1029 			j = 2;
1030 	 }
1031 	 for ( ; j < ( i -3); ++j)
1032 		req->req.data[i] += req->req.data[j+3];
1033 	req->req.data[i]  = ~(req->req.data[i]) +1;
1034 	++i;
1035 	req->req.dataLength     = i;
1036 
1037 	/*The flags & timeouts are used by the driver internally */
1038 	req->flags      = 0;
1039 	req->timeOut    = timeOut * 1000;       /* convert to uSec units */
1040 
1041 
1042 	status = DeviceIoControl(       hDevice,
1043 					IOCTL_IMB_SEND_MESSAGE,
1044 					requestData,
1045 					sizeof(requestData),
1046 					responseData,
1047 					sizeof( responseData ),
1048 					& respLength,
1049 					NULL
1050 				  );
1051 
1052 #ifndef NO_MACRO_ARGS
1053 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
1054 #endif
1055 
1056 	if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) )
1057 	{
1058 		return ACCESN_ERROR;
1059 	}
1060 	return ACCESN_OK;
1061 }
1062 
1063 /*///////////////////////////////////////////////////////////////////////////
1064 // SendTimedImbpRequest
1065 ///////////////////////////////////////////////////////////////////////////// */
1066 /*F*
1067 //  Name:       SendTimedImbpRequest
1068 //  Purpose:    This function sends a request for BMC implemented function
1069 //  Context:    Used by Upper level agents (sis modules) to access BMC implemented functionality.
1070 //  Returns:    OK  else error status code
1071 //  Parameters:
1072 //     reqPtr
1073 //     timeOut
1074 //     respDataPtr
1075 //     respLen
1076 //  Notes:      none
1077 *F*/
1078 ACCESN_STATUS
1079 SendTimedImbpRequest (
1080 		IMBPREQUESTDATA *reqPtr,         /* request info and data */
1081 		int     timeOut,         /* how long to wait, in mSec units */
1082 		BYTE 	*respDataPtr,    /* where to put response data */
1083 		int 	*respDataLen,    /* how much response data there is */
1084 		BYTE 	*completionCode  /* request status from dest controller */
1085 	)
1086 {
1087 	BYTE                    responseData[MAX_BUFFER_SIZE];
1088 	ImbResponseBuffer *     resp = (ImbResponseBuffer *) responseData;
1089 	DWORD                   respLength = sizeof( responseData );
1090 	BYTE                    requestData[MAX_BUFFER_SIZE];
1091 	ImbRequestBuffer *      req = (ImbRequestBuffer *) requestData;
1092 	BOOL                    status;
1093 
1094 
1095 	req->req.rsSa           = reqPtr->rsSa;
1096 	req->req.cmd            = reqPtr->cmdType;
1097 	req->req.netFn          = reqPtr->netFn;
1098 	req->req.rsLun          = reqPtr->rsLun;
1099 	req->req.dataLength     = reqPtr->dataLength;
1100 
1101 #ifndef NO_MACRO_ARGS
1102 	DEBUG("cmd=%02x, pdata=%p, datalen=%x\n", req->req.cmd,
1103 	      reqPtr->data, reqPtr->dataLength );
1104 #endif
1105 	memcpy( req->req.data, reqPtr->data, reqPtr->dataLength );
1106 
1107 	req->flags              = 0;
1108 	req->timeOut    = timeOut * 1000;       /* convert to uSec units */
1109 
1110 #ifndef NO_MACRO_ARGS
1111 	DEBUG("%s: rsSa 0x%x cmd 0x%x netFn 0x%x rsLun 0x%x\n", __FUNCTION__,
1112 			req->req.rsSa, req->req.cmd, req->req.netFn, req->req.rsLun);
1113 #endif
1114 
1115 
1116 	status = DeviceIoControl(       hDevice,
1117 					IOCTL_IMB_SEND_MESSAGE,
1118 					requestData,
1119 					sizeof( requestData ),
1120 					& responseData,
1121 					sizeof( responseData ),
1122 					& respLength,
1123 					NULL
1124 				  );
1125 #ifndef NO_MACRO_ARGS
1126 	DEBUG("%s: DeviceIoControl returned status = %d\n",__FUNCTION__, status);
1127 #endif
1128 #ifdef DBG_IPMI
1129 	printf("%s: rsSa %x cmd %x netFn %x lun %x, status=%d, cc=%x, rlen=%d\n",
1130             __FUNCTION__, req->req.rsSa, req->req.cmd, req->req.netFn,
1131             req->req.rsLun, status,  resp->cCode, respLength );
1132 #endif
1133 
1134 	if( status != TRUE ) {
1135 		DWORD error;
1136 		error = GetLastError();
1137 		return ACCESN_ERROR;
1138 	}
1139 	if( respLength == 0 ) {
1140 		return ACCESN_ERROR;
1141 	}
1142 
1143 	/*
1144 	 * give the caller his response
1145 	 */
1146 	*completionCode = resp->cCode;
1147 	*respDataLen    = 0;
1148 
1149     if(( respLength > 1 ) && ( respDataPtr))
1150 	{
1151 		*respDataLen    = respLength - 1;
1152 		memcpy( respDataPtr, resp->data, *respDataLen);
1153 	}
1154 
1155 
1156 	return ACCESN_OK;
1157 }
1158 
1159 
1160 /*/////////////////////////////////////////////////////////////////////////
1161 //SendAsyncImbpRequest
1162 /////////////////////////////////////////////////////////////////////////// */
1163 /*F*
1164 //  Name:       SendAsyncImbpRequest
1165 //  Purpose:    This function sends a request for Asynchronous IMB implemented function
1166 //  Context:    Used by Upper level agents (sis modules) to access Asynchronous IMB implemented functionality.
1167 //  Returns:    OK  else error status code
1168 //  Parameters:
1169 //     reqPtr  Pointer to Async IMB request
1170 //     seqNo   Sequence Munber
1171 //  Notes:      none
1172 *F*/
1173 ACCESN_STATUS
1174 SendAsyncImbpRequest (
1175 		IMBPREQUESTDATA *reqPtr,  /* request info and data */
1176 		BYTE *          seqNo     /* sequence number used in creating IMB msg */
1177 	)
1178 {
1179 
1180 	BOOL                    status;
1181     BYTE                    responseData[MAX_IMB_RESP_SIZE];
1182 	ImbResponseBuffer *     resp = (ImbResponseBuffer *) responseData;
1183 	DWORD                   respLength = sizeof( responseData );
1184     BYTE                    requestData[MAX_IMB_RESP_SIZE];
1185 	ImbRequestBuffer *      req = (ImbRequestBuffer *) requestData;
1186 
1187 	req->req.rsSa           = reqPtr->rsSa;
1188 	req->req.cmd            = reqPtr->cmdType;
1189 	req->req.netFn          = reqPtr->netFn;
1190 	req->req.rsLun          = reqPtr->rsLun;
1191 	req->req.dataLength     = reqPtr->dataLength;
1192 
1193 	memcpy( req->req.data, reqPtr->data, reqPtr->dataLength );
1194 
1195 	req->flags              = NO_RESPONSE_EXPECTED;
1196 	req->timeOut    = 0;    /* no timeouts for async sends */
1197 
1198 	status = DeviceIoControl(       hDevice,
1199 					IOCTL_IMB_SEND_MESSAGE,
1200 					requestData,
1201 					sizeof( requestData ),
1202 					& responseData,
1203 					sizeof( responseData ),
1204 					& respLength,
1205 					NULL
1206 				  );
1207 #ifndef NO_MACRO_ARGS
1208 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
1209 #endif
1210 
1211 	if( status != TRUE ) {
1212 		DWORD error;
1213 		error = GetLastError();
1214 		return ACCESN_ERROR;
1215 	}
1216 	if( respLength != 2 ) {
1217 		return ACCESN_ERROR;
1218 	}
1219 	/*
1220 	// give the caller his sequence number
1221 	*/
1222 	*seqNo = resp->data[0];
1223 
1224 	return ACCESN_OK;
1225 
1226 }
1227 
1228 /*///////////////////////////////////////////////////////////////////////////
1229 //GetAsyncImbpMessage
1230 ///////////////////////////////////////////////////////////////////////////// */
1231 /*F*
1232 //  Name:       GetAsyncImbpMessage
1233 //  Purpose:    This function gets the next available async message with a message id
1234 //                              greater than SeqNo. The message looks like an IMB packet
1235 //                              and the length and Sequence number is returned
1236 //  Context:    Used by Upper level agents (sis modules) to access Asynchronous IMB implemented functionality.
1237 //  Returns:    OK  else error status code
1238 //  Parameters:
1239 //     msgPtr  Pointer to Async IMB request
1240 //     msgLen  Length
1241 //     timeOut Time to wait
1242 //     seqNo   Sequence Munber
1243 //  Notes:      none
1244 *F*/
1245 
1246 ACCESN_STATUS
1247 GetAsyncImbpMessage (
1248 		ImbPacket *     msgPtr,         /* request info and data */
1249 		DWORD 		*msgLen,        /* IN - length of buffer, OUT - msg len */
1250 		DWORD		timeOut,        /* how long to wait for the message */
1251 		ImbAsyncSeq 	*seqNo,         /* previously returned seq number */
1252 										/* (or ASYNC_SEQ_START) */
1253 		DWORD		channelNumber
1254 	)
1255 {
1256 
1257 	BOOL                   status;
1258     BYTE                   responseData[MAX_ASYNC_RESP_SIZE], lun;
1259 	ImbAsyncResponse *     resp = (ImbAsyncResponse *) responseData;
1260 	DWORD                  respLength = sizeof( responseData );
1261 	ImbAsyncRequest        req;
1262 
1263 	while(1)
1264 	{
1265 
1266 
1267 		if( (msgPtr == NULL) || (msgLen == NULL) || ( seqNo == NULL) )
1268 				return ACCESN_ERROR;
1269 
1270 				req.timeOut   = timeOut * 1000;       /* convert to uSec units */
1271 				req.lastSeq   = *seqNo;
1272 
1273 
1274 			status = DeviceIoControl(       hDevice,
1275 						IOCTL_IMB_GET_ASYNC_MSG,
1276 						& req,
1277 						sizeof( req ),
1278 						& responseData,
1279 						sizeof( responseData ),
1280 						& respLength,
1281 						NULL
1282 					  );
1283 
1284 #ifndef NO_MACRO_ARGS
1285 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
1286 #endif
1287 
1288 			if( status != TRUE ) {
1289 				DWORD error = GetLastError();
1290 				/*
1291 				// handle "msg not available" specially. it is
1292 				// different from a random old error.
1293 				*/
1294 				switch( error ) {
1295 					case IMB_MSG_NOT_AVAILABLE:
1296 												return ACCESN_END_OF_DATA;
1297 					default:
1298 											return ACCESN_ERROR;
1299 				}
1300 				return ACCESN_ERROR;
1301 			}
1302 			if( respLength < MIN_ASYNC_RESP_SIZE ) {
1303 					return ACCESN_ERROR;
1304 			}
1305 			respLength -= MIN_ASYNC_RESP_SIZE;
1306 
1307 			if( *msgLen < respLength ) {
1308 					return ACCESN_ERROR;
1309 			}
1310 
1311 
1312 			/*same code as in NT section */
1313 			if ( IpmiVersion == IPMI_09_VERSION)
1314 			{
1315 
1316 				switch( channelNumber) {
1317 					case IPMB_CHANNEL:
1318 								lun = IPMB_LUN;
1319 								 break;
1320 
1321 					case  EMP_CHANNEL:
1322 								lun = EMP_LUN;
1323 							  	break;
1324 
1325 					default:
1326 								lun = RESERVED_LUN;
1327 								break;
1328 				}
1329 
1330 				if ( (lun == RESERVED_LUN) ||
1331 					 (lun !=  ((((ImbPacket *)(resp->data))->nfLn) & 0x3 ))
1332 					)
1333 				{
1334 						*seqNo = resp->thisSeq;
1335 						continue;
1336 				}
1337 
1338 
1339 				memcpy( msgPtr, resp->data, respLength );
1340 				*msgLen = respLength;
1341 
1342 			}
1343 			else
1344 			{
1345 				/* it is a 1.0 or  above version 	 */
1346 
1347 				if (resp->data[0] != (BYTE)channelNumber)
1348 				{
1349 					*seqNo = resp->thisSeq;
1350 					continue;
1351 				}
1352 
1353 				memcpy( msgPtr, &(resp->data[1]), respLength-1 );
1354 				*msgLen = respLength-1;
1355 
1356 
1357 			}
1358 
1359 		/*
1360 		// give the caller his sequence number
1361 		*/
1362 		*seqNo = resp->thisSeq;
1363 
1364 		return ACCESN_OK;
1365 
1366 	} /*while (1)  */
1367 }
1368 
1369 
1370 /*///////////////////////////////////////////////////////////////////////////
1371 //GetAsyncImbpMessage_Ex
1372 ///////////////////////////////////////////////////////////////////////////// */
1373 /*F*
1374 //  Name:       GetAsyncImbpMessage_Ex
1375 //  Purpose:    This function gets the next available async message with a message id
1376 //                              greater than SeqNo. The message looks like an IMB packet
1377 //                              and the length and Sequence number is returned
1378 //  Context:    Used by Upper level agents (sis modules) to access Asynchronous IMB implemented functionality.
1379 //  Returns:    OK  else error status code
1380 //  Parameters:
1381 //     msgPtr  Pointer to Async IMB request
1382 //     msgLen  Length
1383 //     timeOut Time to wait
1384 //     seqNo   Sequence Munber
1385 //  Notes:      none
1386 *F*/
1387 
1388 ACCESN_STATUS
1389 GetAsyncImbpMessage_Ex (
1390 		ImbPacket *     msgPtr,         /* request info and data */
1391 		DWORD 			*msgLen,        /* IN - length of buffer, OUT - msg len */
1392 		DWORD			timeOut,        /* how long to wait for the message */
1393 		ImbAsyncSeq 	*seqNo,         /* previously returned seq number */
1394 										/* (or ASYNC_SEQ_START) */
1395 		DWORD			channelNumber,
1396 		BYTE *					sessionHandle,
1397 		BYTE *					privilege
1398 	)
1399 {
1400 
1401 	BOOL                   status;
1402     BYTE                   responseData[MAX_ASYNC_RESP_SIZE], lun;
1403 	ImbAsyncResponse *     resp = (ImbAsyncResponse *) responseData;
1404 	DWORD                  respLength = sizeof( responseData );
1405 	ImbAsyncRequest        req;
1406 
1407 	while(1)
1408 	{
1409 
1410 
1411 		if( (msgPtr == NULL) || (msgLen == NULL) || ( seqNo == NULL) )
1412 				return ACCESN_ERROR;
1413 
1414 				req.timeOut   = timeOut * 1000;       /* convert to uSec units */
1415 				req.lastSeq   = *seqNo;
1416 
1417 
1418 			status = DeviceIoControl(       hDevice,
1419 							IOCTL_IMB_GET_ASYNC_MSG,
1420 							& req,
1421 							sizeof( req ),
1422 							& responseData,
1423 							sizeof( responseData ),
1424 							& respLength,
1425 							NULL
1426 						  );
1427 
1428 #ifndef NO_MACRO_ARGS
1429 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
1430 #endif
1431 
1432 			if( status != TRUE ) {
1433 				DWORD error = GetLastError();
1434 				/*
1435 				// handle "msg not available" specially. it is
1436 				// different from a random old error.
1437 				*/
1438 				switch( error ) {
1439 					case IMB_MSG_NOT_AVAILABLE:
1440 												return ACCESN_END_OF_DATA;
1441 					default:
1442 											return ACCESN_ERROR;
1443 				}
1444 				return ACCESN_ERROR;
1445 			}
1446 			if( respLength < MIN_ASYNC_RESP_SIZE ) {
1447 					return ACCESN_ERROR;
1448 			}
1449 			respLength -= MIN_ASYNC_RESP_SIZE;
1450 
1451 			if( *msgLen < respLength ) {
1452 					return ACCESN_ERROR;
1453 			}
1454 
1455 
1456 			/*same code as in NT section */
1457 			if ( IpmiVersion == IPMI_09_VERSION)
1458 			{
1459 
1460 				switch( channelNumber) {
1461 					case IPMB_CHANNEL:
1462 								lun = IPMB_LUN;
1463 								 break;
1464 
1465 					case  EMP_CHANNEL:
1466 								lun = EMP_LUN;
1467 							  	break;
1468 
1469 					default:
1470 								lun = RESERVED_LUN;
1471 								break;
1472 				}
1473 
1474 				if ( (lun == RESERVED_LUN) ||
1475 					 (lun !=  ((((ImbPacket *)(resp->data))->nfLn) & 0x3 ))
1476 					)
1477 				{
1478 						*seqNo = resp->thisSeq;
1479 						continue;
1480 				}
1481 
1482 
1483 				memcpy( msgPtr, resp->data, respLength );
1484 				*msgLen = respLength;
1485 
1486 			}
1487 			else
1488 			{
1489 				if((sessionHandle ==NULL) || (privilege ==NULL))
1490 					return ACCESN_ERROR;
1491 
1492 				/*With the new IPMI version the get message command returns the
1493 				//channel number along with the privileges.The 1st 4 bits of the
1494 				//second byte of the response data for get message command represent
1495 				//the channel number & the last 4 bits are the privileges. */
1496 				*privilege = (resp->data[0] & 0xf0)>> 4;
1497 
1498 				if ((resp->data[0] & 0x0f) != (BYTE)channelNumber)
1499 				{
1500 					*seqNo = resp->thisSeq;
1501 					continue;
1502 				}
1503 
1504 
1505 				/*The get message command according to IPMI 1.5 spec now even
1506 				//returns the session handle.This is required to be captured
1507 				//as it is required as request data for send message command. */
1508 				*sessionHandle = resp->data[1];
1509 				memcpy( msgPtr, &(resp->data[2]), respLength-1 );
1510 				*msgLen = respLength-1;
1511 
1512 
1513 			}
1514 
1515 		/*
1516 		// give the caller his sequence number
1517 		*/
1518 		*seqNo = resp->thisSeq;
1519 
1520 		return ACCESN_OK;
1521 
1522 	} /*while (1) */
1523 }
1524 
1525 
1526 
1527 /*//////////////////////////////////////////////////////////////////////////////
1528 //IsAsyncMessageAvailable
1529 ///////////////////////////////////////////////////////////////////////////// */
1530 /*F*
1531 //  Name:       IsMessageAvailable
1532 //  Purpose:    This function waits for an Async Message
1533 //
1534 //  Context:    Used by Upper level agents access Asynchronous IMB based
1535 //              messages
1536 //  Returns:    OK  else error status code
1537 //  Parameters:
1538 //               eventId
1539 //
1540 //  Notes:     This call will block the calling thread if no Async events are
1541 //                              are available in the queue.
1542 //
1543 *F*/
1544 ACCESN_STATUS
1545 IsAsyncMessageAvailable (unsigned int   eventId )
1546 {
1547     int 	dummy;
1548     int 	respLength = 0;
1549     BOOL  	status;
1550 
1551  /* confirm that app is not using a bad Id */
1552 
1553 
1554 	if (  AsyncEventHandle  != (HANDLE) eventId)
1555 	  	return ACCESN_ERROR;
1556 
1557 	status = DeviceIoControl(hDevice,
1558 				   IOCTL_IMB_CHECK_EVENT,
1559 				   &AsyncEventHandle,
1560 				    sizeof(HANDLE ),
1561 				    &dummy,
1562 					sizeof(int),
1563 					(LPDWORD) & respLength,
1564 					NULL
1565 				  );
1566 #ifndef NO_MACRO_ARGS
1567 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
1568 #endif
1569 
1570 	if( status != TRUE )
1571 		return  ACCESN_ERROR;
1572 
1573 
1574 	return ACCESN_OK;
1575 }
1576 
1577 
1578 /*I have retained this commented code because later we may want to use
1579 //DPC message specific Processing (pai 11/21) */
1580 
1581 #ifdef NOT_COMPILED_BUT_LEFT_HERE_FOR_NOW
1582 
1583 /*//////////////////////////////////////////////////////////////////////////////
1584 //GetAsyncDpcMessage
1585 ///////////////////////////////////////////////////////////////////////////// */
1586 /*F*
1587 //  Name:       GetAsyncDpcMessage
1588 //  Purpose:    This function gets the next available async message from
1589 //                              the DPC client.
1590 //
1591 //  Context:    Used by Upper level agents access Asynchronous IMB based
1592 //              messages sent by the DPC client.
1593 //  Returns:    OK  else error status code
1594 //  Parameters:
1595 //     msgPtr  Pointer to Async IMB request
1596 //         msgLen  Length
1597 //         timeOut Time to wait
1598 //     seqNo   Sequence Munber
1599 //  Notes:     This call will block the calling thread if no Async events are
1600 //                              are available in the queue.
1601 //
1602 *F*/
1603 
1604 ACCESN_STATUS
1605 GetAsyncDpcMessage (
1606 		ImbPacket *             msgPtr,         /* request info and data */
1607 		DWORD *                 msgLen,         /* IN - length of buffer, OUT - msg len */
1608 		DWORD                   timeOut,        /* how long to wait for the message */
1609 		ImbAsyncSeq *   seqNo,          /* previously returned seq number (or ASYNC_SEQ_START) */
1610 	)
1611 {
1612 	BOOL                            status;
1613     BYTE                                responseData[MAX_ASYNC_RESP_SIZE];
1614 	ImbAsyncResponse *      resp = (ImbAsyncResponse *) responseData;
1615 	DWORD                           respLength = sizeof( responseData );
1616 	ImbAsyncRequest         req;
1617 
1618 	if( msgPtr == NULL || msgLen == NULL || seqNo == NULL )
1619 		return ACCESN_ERROR;
1620 
1621 	req.lastSeq             = *seqNo;
1622 
1623 
1624 	hEvt = CreateEvent (NULL, TRUE, FALSE, NULL) ;
1625 	if (!hEvt) {
1626 		return ACCESN_ERROR;
1627 	}
1628 
1629 	status = DeviceIoControl(       hDevice,
1630 					IOCTL_IMB_GET_DPC_MSG,
1631 					& req,
1632 					sizeof( req ),
1633 					& responseData,
1634 					sizeof( responseData ),
1635 					& respLength,
1636 					&ovl
1637 				  );
1638 
1639 	if( status != TRUE ) {
1640 		DWORD error = GetLastError();
1641 		/*
1642 		// handle "msg not available" specially. it is different from
1643 		// a random old error.
1644 		//
1645 		*/
1646 	if (!status)
1647 	{
1648 			switch (error )
1649 				{
1650 						case ERROR_IO_PENDING:
1651 
1652 								WaitForSingleObject (hEvt, INFINITE) ;
1653 								ResetEvent (hEvt) ;
1654 								break;
1655 
1656 						case IMB_MSG_NOT_AVAILABLE:
1657 
1658 							    CloseHandle(hEvt);
1659 								return ACCESN_END_OF_DATA;
1660 
1661 						default:
1662 								CloseHandle(hEvt);
1663 								return ACCESN_ERROR;
1664 
1665 			}
1666 	}
1667 
1668 
1669 
1670 		if (
1671 		( GetOverlappedResult(hDevice,
1672 							&ovl,
1673 							(LPDWORD)&respLength,
1674 							TRUE
1675 					) == 0 ) || (respLength <= 0)
1676 		)
1677 
1678 		{
1679 
1680 			CloseHandle(hEvt);
1681 			return ACCESN_ERROR;
1682 
1683 		}
1684 
1685 
1686 	}
1687 
1688 	if( respLength < MIN_ASYNC_RESP_SIZE ) {
1689 		CloseHandle(hEvt);
1690 		return ACCESN_ERROR;
1691 	}
1692 
1693 	respLength -= MIN_ASYNC_RESP_SIZE;
1694 
1695 	if( *msgLen < respLength ) {
1696 
1697 		/* The following code should have been just return ACCESN_out_of_range */
1698 		CloseHandle(hEvt);
1699 		return ACCESN_ERROR;
1700 	}
1701 
1702 	memcpy( msgPtr, resp->data, respLength );
1703 
1704 	*msgLen = respLength;
1705 	/*
1706 	// give the caller his sequence number
1707 	*/
1708 	*seqNo = resp->thisSeq;
1709 
1710 	CloseHandle(hEvt);
1711 
1712 
1713 	return ACCESN_OK;
1714 
1715 }
1716 #endif /*NOT_COMPILED_BUT_LEFT_HERE_FOR_NOW*/
1717 
1718 
1719 
1720 /*/////////////////////////////////////////////////////////////////////////////
1721 //RegisterForImbAsyncMessageNotification
1722 ///////////////////////////////////////////////////////////////////////////// */
1723 /*F*
1724 //  Name:       RegisterForImbAsyncMessageNotification
1725 //  Purpose:    This function Registers the calling application
1726 //                              for Asynchronous notification when a sms message
1727 //                              is available with the IMB driver.
1728 //
1729 //  Context:    Used by Upper level agents to know that an async
1730 //                              SMS message is available with the driver.
1731 //  Returns:    OK  else error status code
1732 //  Parameters:
1733 //    handleId  pointer to the registration handle
1734 //
1735 //  Notes:      The calling application should use the returned handle to
1736 //              get the Async messages..
1737 *F*/
1738 ACCESN_STATUS
1739 RegisterForImbAsyncMessageNotification (unsigned int *handleId)
1740 
1741 {
1742 	BOOL      status;
1743 	DWORD     respLength ;
1744 	int       dummy;
1745 
1746 	/*allow  only one app to register  */
1747 
1748 	if( (handleId  == NULL ) || (AsyncEventHandle) )
1749 		return ACCESN_ERROR;
1750 
1751 
1752 	status = DeviceIoControl(hDevice,
1753 				IOCTL_IMB_REGISTER_ASYNC_OBJ,
1754 				&dummy,
1755 				sizeof( int ),
1756 				&AsyncEventHandle,
1757 				(DWORD)sizeof(HANDLE ),
1758 				(LPDWORD) & respLength,
1759 				NULL
1760 			  );
1761 #ifndef NO_MACRO_ARGS
1762 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
1763 #endif
1764 
1765 	if( (respLength != sizeof(int))  || (status != TRUE ))
1766 		return  ACCESN_ERROR;
1767 
1768 	/* printf("imbapi: Register handle = %x\n",AsyncEventHandle); *//*++++*/
1769 	*handleId = (unsigned int) AsyncEventHandle;
1770 
1771 #ifndef NO_MACRO_ARGS
1772 	DEBUG("handleId = %x AsyncEventHandle %x\n", *handleId, AsyncEventHandle);
1773 #endif
1774 	return ACCESN_OK;
1775 }
1776 
1777 
1778 
1779 
1780 
1781 /*/////////////////////////////////////////////////////////////////////////////
1782 //UnRegisterForImbAsyncMessageNotification
1783 ///////////////////////////////////////////////////////////////////////////// */
1784 /*F*
1785 //  Name:       UnRegisterForImbAsyncMessageNotification
1786 //  Purpose:    This function un-registers the calling application
1787 //                              for Asynchronous notification when a sms message
1788 //                              is available with the IMB driver.
1789 //
1790 //  Context:    Used by Upper level agents to un-register
1791 //                              for  async. notification of sms messages
1792 //  Returns:    OK  else error status code
1793 //  Parameters:
1794 //    handleId  pointer to the registration handle
1795 //	  iFlag		value used to determine where this function was called from
1796 //				_it is used currently on in NetWare environment_
1797 //
1798 //  Notes:
1799 *F*/
1800 ACCESN_STATUS
1801 UnRegisterForImbAsyncMessageNotification (unsigned int handleId, int iFlag)
1802 
1803 {
1804 	BOOL		status;
1805 	DWORD		respLength ;
1806 	int			dummy;
1807 
1808 	iFlag = iFlag;	/* to keep compiler happy  We are not using this flag*/
1809 
1810 	if (  AsyncEventHandle  != (HANDLE) handleId)
1811 	  return ACCESN_ERROR;
1812 
1813 	status = DeviceIoControl(hDevice,
1814 					IOCTL_IMB_DEREGISTER_ASYNC_OBJ,
1815 					&AsyncEventHandle,
1816 					(DWORD)sizeof(HANDLE ),
1817 					&dummy,
1818 					(DWORD)sizeof(int ),
1819 					(LPDWORD) & respLength,
1820 					NULL
1821 				  );
1822 #ifndef NO_MACRO_ARGS
1823 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
1824 #endif
1825 
1826 	if( status != TRUE )
1827 		return  ACCESN_ERROR;
1828 
1829 	return ACCESN_OK;
1830 }
1831 
1832 
1833 /*///////////////////////////////////////////////////////////////////////////
1834 // SetShutDownCode
1835 ///////////////////////////////////////////////////////////////////////////// */
1836 /*F*
1837 //  Name:       SetShutDownCode
1838 //  Purpose:    To set the shutdown  action code
1839 //  Context:    Called by the System Control Subsystem
1840 //  Returns:    none
1841 //  Parameters:
1842 //              code  shutdown action code which can be either
1843 //              SD_NO_ACTION, SD_RESET, SD_POWER_OFF as defined in imb_if.h
1844 *F*/
1845 
1846 ACCESN_STATUS
1847 SetShutDownCode (
1848 		int 	delayTime,	 /* time to delay in 100ms units */
1849 		int 	code             /* what to do when time expires */
1850 	)
1851 {
1852 	DWORD					retLength;
1853 	BOOL                    status;
1854 	ShutdownCmdBuffer       cmd;
1855 
1856 	/*
1857 	// If Imb driver is not present return AccessFailed
1858 	*/
1859 	if(hDevice == INVALID_HANDLE_VALUE)
1860 		return ACCESN_ERROR;
1861 
1862 	cmd.code        = code;
1863 	cmd.delayTime   = delayTime;
1864 
1865 	status = DeviceIoControl( hDevice,
1866 					IOCTL_IMB_SHUTDOWN_CODE,
1867 					& cmd,
1868 					sizeof( cmd ),
1869 					NULL,
1870 					0,
1871 					& retLength,
1872 					NULL
1873 				  );
1874 #ifndef NO_MACRO_ARGS
1875 	DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
1876 #endif
1877 
1878 	if(status == TRUE)
1879 		return ACCESN_OK;
1880 	else
1881 		return ACCESN_ERROR;
1882 }
1883 
1884 /*/////////////////////////////////////////////////////////////////////////
1885 // MapPhysicalMemory
1886 /////////////////////////////////////////////////////////////////////////// */
1887 /*F*
1888 //  Name:       MapPhysicalMemory
1889 //  Purpose:    This function maps specified range of physical memory in calling
1890 //              pocesse's address space
1891 //  Context:    Used by Upper level agents (sis modules) to access
1892 //				system physical memory
1893 //  Returns:    ACCESN_OK  else error status code
1894 //  Parameters:
1895 //
1896 //     startAddress   starting physical address of the  memory to be mapped
1897 //     addressLength  length of the physical memory to be mapped
1898 //     virtualAddress pointer to the mapped virtual address
1899 //  Notes:      none
1900 *F*/
1901 /*///////////////////////////////////////////////////////////////////////////
1902 // UnmapPhysicalMemory
1903 //////////////////////////////////////////////////////////////////////////// */
1904 /*F*
1905 //  Name:       UnMapPhysicalMemory
1906 //  Purpose:    This function unmaps the previously mapped physical memory
1907 //  Context:    Used by Upper level agents (sis modules)
1908 //  Returns:    ACCESN_OK  else error status code
1909 //  Parameters:
1910 //
1911 //     addressLength  length of the physical memory to be mapped
1912 //     virtualAddress pointer to the mapped virtual address
1913 //  Notes:      none
1914 *F*/
1915 #ifdef WIN32
1916 ACCESN_STATUS
1917 MapPhysicalMemory (
1918 		int startAddress,       // physical address to map in
1919 		int addressLength,      // how much to map
1920 		int *virtualAddress     // where it got mapped to
1921 	)
1922 {
1923 	DWORD                retLength;
1924 	BOOL                 status;
1925 	PHYSICAL_MEMORY_INFO pmi;
1926 
1927 	if (startAddress == 0 || addressLength <= 0)
1928 		return ACCESN_OUT_OF_RANGE;
1929 
1930 	pmi.InterfaceType       = Internal;
1931 	pmi.BusNumber           = 0;
1932 	pmi.BusAddress.HighPart = (LONG)0x0;
1933 	pmi.BusAddress.LowPart  = (LONG)startAddress;
1934 	pmi.AddressSpace        = (LONG) 0;
1935 	pmi.Length              = addressLength;
1936 
1937 	status = DeviceIoControl (      hDevice,
1938 								IOCTL_IMB_MAP_MEMORY,
1939 								& pmi,
1940 								sizeof(PHYSICAL_MEMORY_INFO),
1941 								virtualAddress,
1942 								sizeof(PVOID),
1943 								& retLength,
1944 								0
1945 							);
1946 	if( status == TRUE ) {
1947 		return ACCESN_OK;
1948 	} else {
1949 		return ACCESN_ERROR;
1950 	}
1951 }
1952 
1953 ACCESN_STATUS
1954 UnmapPhysicalMemory (
1955 		int virtualAddress,     // what memory to unmap
1956         int Length )
1957 {
1958 	DWORD   retLength;
1959 	BOOL    status;
1960 
1961 	status = DeviceIoControl (      hDevice,
1962 								IOCTL_IMB_UNMAP_MEMORY,
1963 								& virtualAddress,
1964 								sizeof(PVOID),
1965 								NULL,
1966 								0,
1967 								& retLength,
1968 								0
1969 							);
1970 
1971 	if( status == TRUE ) {
1972 		return ACCESN_OK;
1973 	} else {
1974 		return ACCESN_ERROR;
1975 	}
1976 }
1977 
1978 #else   /*Linux, SCO, UNIX, etc.*/
1979 
1980 ACCESN_STATUS
1981 MapPhysicalMemory(int startAddress,int addressLength, int *virtualAddress )
1982 {
1983 	int 				fd;
1984 	unsigned int 		length = addressLength;
1985 	off_t 				startpAddress = (off_t)startAddress;
1986 	unsigned int 		diff;
1987 	char 				*startvAddress;
1988 
1989 	if ((startAddress == 0) || (addressLength <= 0))
1990 		return ACCESN_ERROR;
1991 
1992 	if ( (fd = open("/dev/mem", O_RDONLY)) < 0) {
1993 		char buf[128];
1994 
1995 		sprintf(buf,"%s %s: open(%s) failed",
1996                             __FILE__,__FUNCTION__,IMB_DEVICE);
1997 		perror(buf);
1998 		return ACCESN_ERROR ;
1999 	}
2000 
2001 	/* aliging the offset to a page boundary and adjusting the length */
2002 	diff = (int)startpAddress % PAGESIZE;
2003 	startpAddress -= diff;
2004 	length += diff;
2005 
2006 	if ( (startvAddress = mmap(0,
2007 								length,
2008 								PROT_READ,
2009 								MAP_SHARED,
2010 								fd,
2011 								startpAddress
2012 								) ) == MAP_FAILED)
2013 	{
2014 		char buf[128];
2015 
2016 		sprintf(buf,"%s %s: mmap failed", __FILE__,__FUNCTION__);
2017 		perror(buf);
2018 		close(fd);
2019 		return ACCESN_ERROR;
2020 	}
2021 #ifndef NO_MACRO_ARGS
2022 	DEBUG("%s: mmap of 0x%x success\n",__FUNCTION__,startpAddress);
2023 #endif
2024 #ifdef LINUX_DEBUG_MAX
2025 /* dont want this memory dump for normal level of debugging.
2026 // So, I have put it under a stronger debug symbol. mahendra */
2027 
2028 	for(i=0; i < length; i++)
2029 	{
2030 		printf("0x%x ", (startvAddress[i]));
2031 		if(isascii(startvAddress[i])) {
2032 			printf("%c ", (startvAddress[i]));
2033 		}
2034 	}
2035 #endif /*LINUX_DEBUG_MAX */
2036 
2037 	*virtualAddress = (long)(startvAddress + diff);
2038 	close(fd);
2039 	return ACCESN_OK;
2040 }
2041 
2042 ACCESN_STATUS
2043 UnmapPhysicalMemory( int virtualAddress, int Length )
2044 {
2045 	unsigned int diff = 0;
2046 
2047 	/* page align the virtual address and adjust length accordingly  */
2048 	diff = 	((unsigned int) virtualAddress) % PAGESIZE;
2049 	virtualAddress -= diff;
2050 	Length += diff;
2051 #ifndef NO_MACRO_ARGS
2052 	DEBUG("%s: calling munmap(0x%x,%d)\n",__FUNCTION__,virtualAddress,Length);
2053 #endif
2054 
2055 	if(munmap(&virtualAddress, Length) != 0)
2056 	{
2057 		char buf[128];
2058 
2059 		sprintf(buf,"%s %s: munmap failed", __FILE__,__FUNCTION__);
2060 		perror(buf);
2061 		return ACCESN_ERROR;
2062 
2063 	}
2064 #ifndef NO_MACRO_ARGS
2065 	DEBUG("%s: munmap(0x%x,%d) success\n",__FUNCTION__,virtualAddress,Length);
2066 #endif
2067 
2068 	return ACCESN_OK;
2069 }
2070 #endif    /*unix*/
2071 
2072 
2073 /*/////////////////////////////////////////////////////////////////////////////
2074 // GetIpmiVersion
2075 //////////////////////////////////////////////////////////////////////////// */
2076 
2077 /*F*
2078 //  Name:       GetIpmiVersion
2079 //  Purpose:    This function returns current IPMI version
2080 //  Context:
2081 //  Returns:    IPMI version
2082 //  Parameters:
2083 //     reqPtr
2084 //     timeOut
2085 //     respDataPtr
2086 //     respLen
2087 //  Notes:      svuppula
2088 *F*/
2089 BYTE	GetIpmiVersion()
2090 {
2091 	return	IpmiVersion;
2092 }
2093 
2094