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