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
open_imb(void)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
open_imb(void)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 *---------------------------------------------------------------------*/
ipmi_open_ia(void)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
ipmi_close_ia(void)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
DeviceIoControl(HANDLE dummey_hDevice,DWORD dwIoControlCode,LPVOID lpvInBuffer,DWORD cbInBuffer,LPVOID lpvOutBuffer,DWORD cbOutBuffer,LPDWORD lpcbBytesReturned,LPOVERLAPPED lpoOverlapped)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
StartAsyncMesgPoll()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
SendTimedI2cRequest(I2CREQUESTDATA * reqPtr,int timeOut,BYTE * respDataPtr,int * respDataLen,BYTE * completionCode)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
SendTimedEmpMessageResponse(ImbPacket * ptr,char * responseDataBuf,int responseDataLen,int timeOut)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
SendTimedEmpMessageResponse_Ex(ImbPacket * ptr,char * responseDataBuf,int responseDataLen,int timeOut,BYTE sessionHandle,BYTE channelNumber)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
SendTimedLanMessageResponse(ImbPacket * ptr,char * responseDataBuf,int responseDataLen,int timeOut)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
SendTimedLanMessageResponse_Ex(ImbPacket * ptr,char * responseDataBuf,int responseDataLen,int timeOut,BYTE sessionHandle,BYTE channelNumber)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
SendTimedImbpRequest(IMBPREQUESTDATA * reqPtr,int timeOut,BYTE * respDataPtr,int * respDataLen,BYTE * completionCode)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
SendAsyncImbpRequest(IMBPREQUESTDATA * reqPtr,BYTE * seqNo)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
GetAsyncImbpMessage(ImbPacket * msgPtr,DWORD * msgLen,DWORD timeOut,ImbAsyncSeq * seqNo,DWORD channelNumber)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
GetAsyncImbpMessage_Ex(ImbPacket * msgPtr,DWORD * msgLen,DWORD timeOut,ImbAsyncSeq * seqNo,DWORD channelNumber,BYTE * sessionHandle,BYTE * privilege)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
IsAsyncMessageAvailable(unsigned int eventId)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
RegisterForImbAsyncMessageNotification(unsigned int * handleId)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
UnRegisterForImbAsyncMessageNotification(unsigned int handleId,int iFlag)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
SetShutDownCode(int delayTime,int code)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
MapPhysicalMemory(int startAddress,int addressLength,int * virtualAddress)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
UnmapPhysicalMemory(int virtualAddress,int Length)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
MapPhysicalMemory(int startAddress,int addressLength,int * virtualAddress)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
UnmapPhysicalMemory(int virtualAddress,int Length)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*/
GetIpmiVersion()2089 BYTE GetIpmiVersion()
2090 {
2091 return IpmiVersion;
2092 }
2093
2094