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