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