4 Copyright (c) 1999- 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "I2CDelayPei.h"
16 #include "I2CIoLibPei.h"
17 #include "I2CAccess.h"
18 #include "I2CLibPei.h"
19 #include <PlatformBaseAddresses.h>
20 #include <Library/DebugLib.h>
21 #include <Library/BaseMemoryLib.h>
22 #include <Library/PeiServicesTablePointerLib.h>
23 #include <Library/HobLib.h>
24 #include <PchRegs/PchRegsPcu.h>
25 #include <PchRegs/PchRegsLpss.h>
27 #define LPSS_PCI_DEVICE_NUMBER 8
29 #define R_PCH_LPIO_I2C_MEM_RESETS 0x804 // Software Reset
30 #define B_PCH_LPIO_I2C_MEM_RESETS_FUNC BIT1 // Function Clock Domain Reset
31 #define B_PCH_LPIO_I2C_MEM_RESETS_APB BIT0 // APB Domain Reset
32 #define R_PCH_LPSS_I2C_MEM_PCP 0x800 // Private Clock Parameters
34 #define PEI_TEPM_LPSS_DMA_BAR 0xFE900000
35 #define PEI_TEPM_LPSS_I2C0_BAR 0xFE910000
36 #define PCI_CONFIG_SPACE_SIZE 0x10000
38 EFI_GUID mI2CPeiInitGuid
= {
39 0x96DED71A, 0xB9E7, 0x4EAD, 0x96, 0x2C, 0x01, 0x69, 0x3C, 0xED, 0x2A, 0x64
46 // I2C0_SDA-OD-O - write 0x2003CC81 to IOBASE + 0x0210
47 // I2C0_SCL-OD-O - write 0x2003CC81 to IOBASE + 0x0200
54 // I2C1_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x01F0
55 // I2C1_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x01E0
62 // I2C2_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x01D0
63 // I2C2_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x01B0
70 // I2C3_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x0190
71 // I2C3_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x01C0
78 // I2C4_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x01A0
79 // I2C4_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x0170
86 // I2C5_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x0150
87 // I2C5_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x0140
94 // I2C6_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x0180
95 // I2C6_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x0160
102 Constructor of this library.
110 IntelI2CPeiLibConstructor (
111 IN EFI_PEI_FILE_HANDLE FileHandle
,
112 IN CONST EFI_PEI_SERVICES
**PeiServices
117 for (Index
= 0; Index
< sizeof(I2CGPIO
)/sizeof(UINT16
); Index
++) {
118 I2CLibPeiMmioWrite32(IO_BASE_ADDRESS
+I2CGPIO
[Index
], 0x2003CC81);
125 Programe all I2C controllers on LPSS.
127 I2C0 is function 1 of LPSS. I2C1 is function 2 of LPSS, etc..
144 DEBUG ((EFI_D_INFO
, "Pei ProgramPciLpssI2C() Start\n"));
147 // Set the VLV Function Disable Register to ZERO
149 PmcBase
= I2CLibPeiMmioRead32(PciD31F0RegBase
+ R_PCH_LPC_PMC_BASE
) & B_PCH_LPC_PMC_BASE_BAR
;
151 if(I2CLibPeiMmioRead32(PmcBase
+ R_PCH_PMC_FUNC_DIS
)&
152 (B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1
| B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2
153 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3
| B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4
| B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5
154 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6
| B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7
)) {
155 I2CLibPeiMmioWrite32(
156 PmcBase
+R_PCH_PMC_FUNC_DIS
,
157 I2CLibPeiMmioRead32(PmcBase
+ R_PCH_PMC_FUNC_DIS
)& \
158 ~(B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1
| B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2 \
159 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3
| B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4 \
160 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5
| B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6
|B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7
)
162 DEBUG ((EFI_D_INFO
, "ProgramPciLpssI2C() enable all I2C controllers\n"));
165 for(Index
= 0; Index
< LPSS_PCI_DEVICE_NUMBER
; Index
++) {
167 PciMmBase
= MmPciAddress (
169 DEFAULT_PCI_BUS_NUMBER_PCH
,
170 PCI_DEVICE_NUMBER_PCH_LPSS_I2C
,
174 DevID
= I2CLibPeiMmioRead32(PciMmBase
);
176 Bar0
= PEI_TEPM_LPSS_DMA_BAR
+ (Index
* PCI_CONFIG_SPACE_SIZE
);
177 Bar1
= Bar0
+ 0x8000;
179 DEBUG((EFI_D_ERROR
, "Program Pci Lpss I2C Device Function=%x DevID=%08x\n", Index
, DevID
));
182 // Check if device present
184 if (DevID
!= 0xFFFFFFFF) {
185 if(!(I2CLibPeiMmioRead32 (PciMmBase
+ R_PCH_LPSS_I2C_STSCMD
) & B_PCH_LPSS_I2C_STSCMD_MSE
)) {
189 I2CLibPeiMmioWrite32((UINTN
) (PciMmBase
+ R_PCH_LPSS_I2C_BAR
), (UINT32
)(Bar0
& B_PCH_LPSS_I2C_BAR_BA
));
191 DEBUG ((EFI_D_ERROR
, "I2CBaseAddress1 = 0x%x \n",I2CLibPeiMmioRead32 (PciMmBase
+R_PCH_LPSS_I2C_BAR
)));
196 I2CLibPeiMmioWrite32 ((UINTN
)(PciMmBase
+ R_PCH_LPSS_I2C_BAR1
), (UINT32
)(Bar1
& B_PCH_LPSS_I2C_BAR1_BA
));
197 DEBUG ((EFI_D_ERROR
, "I2CBaseAddress1 = 0x%x \n",I2CLibPeiMmioRead32(PciMmBase
+R_PCH_LPSS_I2C_BAR1
)));
200 // Bus Master Enable & Memory Space Enable
202 I2CLibPeiMmioWrite32((UINTN
) (PciMmBase
+ R_PCH_LPSS_I2C_STSCMD
), (UINT32
)(B_PCH_LPSS_I2C_STSCMD_BME
| B_PCH_LPSS_I2C_STSCMD_MSE
));
208 I2CLibPeiMmioWrite32 (Bar0
+ R_PCH_LPIO_I2C_MEM_RESETS
, (B_PCH_LPIO_I2C_MEM_RESETS_FUNC
| B_PCH_LPIO_I2C_MEM_RESETS_APB
));
213 I2CLibPeiMmioWrite32 (Bar0
+ R_PCH_LPSS_I2C_MEM_PCP
, 0x80020003);//No use for A0
215 DEBUG ((EFI_D_INFO
, "ProgramPciLpssI2C() Programmed()\n"));
220 DEBUG ((EFI_D_INFO
, "Pei ProgramPciLpssI2C() End\n"));
228 @param I2cControllerIndex Index of I2C controller.
234 IN UINT8 I2cControllerIndex
237 UINTN I2CBaseAddress
;
238 UINT32 NumTries
= 10000; // 0.1 seconds
240 I2CBaseAddress
= (UINT32
) PEI_TEPM_LPSS_I2C0_BAR
+ I2cControllerIndex
* PCI_CONFIG_SPACE_SIZE
;
242 I2CLibPeiMmioWrite16 (I2CBaseAddress
+ R_IC_ENABLE
, 0);
243 while (0 != ( I2CLibPeiMmioRead16 (I2CBaseAddress
+ R_IC_ENABLE_STATUS
) & 1)) {
244 MicroSecondDelay (10);
246 if(0 == NumTries
) return EFI_NOT_READY
;
255 @param I2cControllerIndex Index of I2C controller.
261 IN UINT8 I2cControllerIndex
264 UINTN I2CBaseAddress
;
265 UINT32 NumTries
= 10000; // 0.1 seconds
267 I2CBaseAddress
= (UINT32
) PEI_TEPM_LPSS_I2C0_BAR
+ I2cControllerIndex
* PCI_CONFIG_SPACE_SIZE
;
268 I2CLibPeiMmioWrite16 (I2CBaseAddress
+ R_IC_ENABLE
, 1);
269 while (0 == ( I2CLibPeiMmioRead16 ( I2CBaseAddress
+ R_IC_ENABLE_STATUS
) & 1)) {
270 MicroSecondDelay (10);
272 if(0 == NumTries
) return EFI_NOT_READY
;
280 Set the I2C controller bus clock frequency.
282 @param[in] This Address of the library's I2C context structure
283 @param[in] PlatformData Address of the platform configuration data
284 @param[in] BusClockHertz New I2C bus clock frequency in Hertz
286 @retval RETURN_SUCCESS The bus frequency was set successfully.
287 @retval RETURN_UNSUPPORTED The controller does not support this frequency.
292 IN UINTN I2CBaseAddress
,
293 IN UINTN BusClockHertz
,
297 DEBUG((EFI_D_INFO
,"InputFreq BusClockHertz: %d\r\n",BusClockHertz
));
299 *I2cMode
= B_IC_RESTART_EN
| B_IC_SLAVE_DISABLE
| B_MASTER_MODE
;
302 // Set the 100 KHz clock divider
304 // From Table 10 of the I2C specification
309 I2CLibPeiMmioWrite16 ( I2CBaseAddress
+ R_IC_SS_SCL_HCNT
, (UINT16
)0x214 );
310 I2CLibPeiMmioWrite16 ( I2CBaseAddress
+ R_IC_SS_SCL_LCNT
, (UINT16
)0x272 );
313 // Set the 400 KHz clock divider
315 // From Table 10 of the I2C specification
320 I2CLibPeiMmioWrite16 ( I2CBaseAddress
+ R_IC_FS_SCL_HCNT
, (UINT16
)0x50 );
321 I2CLibPeiMmioWrite16 ( I2CBaseAddress
+ R_IC_FS_SCL_LCNT
, (UINT16
)0xAD );
323 switch ( BusClockHertz
) {
325 I2CLibPeiMmioWrite32 ( I2CBaseAddress
+ R_IC_SDA_HOLD
, (UINT16
)0x40);//100K
326 *I2cMode
|= V_SPEED_STANDARD
;
329 I2CLibPeiMmioWrite32 ( I2CBaseAddress
+ R_IC_SDA_HOLD
, (UINT16
)0x32);//400K
330 *I2cMode
|= V_SPEED_FAST
;
333 I2CLibPeiMmioWrite32 ( I2CBaseAddress
+ R_IC_SDA_HOLD
, (UINT16
)0x09);//3.4M
334 *I2cMode
|= V_SPEED_HIGH
;
341 Initializes the host controller to execute I2C commands.
343 @param I2cControllerIndex Index of I2C controller in LPSS device. 0 represents I2C0, which is PCI function 1 of LPSS device.
345 @return EFI_SUCCESS Opcode initialization on the I2C host controller completed.
346 @return EFI_DEVICE_ERROR Device error, operation failed.
350 UINT8 I2cControllerIndex
,
356 UINTN I2CBaseAddress
;
361 PciMmBase
= MmPciAddress (
363 DEFAULT_PCI_BUS_NUMBER_PCH
,
364 PCI_DEVICE_NUMBER_PCH_LPSS_I2C
,
365 (I2cControllerIndex
+ 1),
369 I2CBaseAddress
= I2CLibPeiMmioRead32 (PciMmBase
+R_PCH_LPSS_I2C_BAR
);
372 // Verify the parameters
374 if (1023 < SlaveAddress
) {
375 Status
= EFI_INVALID_PARAMETER
;
376 DEBUG((EFI_D_INFO
,"I2cStartRequest Exit with Status %r\r\n", Status
));
380 if(I2CBaseAddress
== (PEI_TEPM_LPSS_I2C0_BAR
+ I2cControllerIndex
* PCI_CONFIG_SPACE_SIZE
)) {
385 I2CBaseAddress
= (UINT32
) (PEI_TEPM_LPSS_I2C0_BAR
+ I2cControllerIndex
* PCI_CONFIG_SPACE_SIZE
);
386 DEBUG ((EFI_D_ERROR
, "I2CBaseAddress = 0x%x \n",I2CBaseAddress
));
387 NumTries
= 10000; // 1 seconds
388 while ((1 == ( I2CLibPeiMmioRead32 ( I2CBaseAddress
+ R_IC_STATUS
) & STAT_MST_ACTIVITY
))) {
389 MicroSecondDelay(10);
392 return EFI_DEVICE_ERROR
;
395 Status
= I2cDisable (I2cControllerIndex
);
396 DEBUG((EFI_D_INFO
, "I2cDisable Status = %r\r\n", Status
));
398 I2cBusFrequencySet(I2CBaseAddress
, 400 * 1000, &I2cMode
);//Set I2cMode
400 I2CLibPeiMmioWrite16(I2CBaseAddress
+ R_IC_INTR_MASK
, 0x0);
401 if (0x7F < SlaveAddress
) {
402 SlaveAddress
= (SlaveAddress
& 0x3ff ) | IC_TAR_10BITADDR_MASTER
;
404 I2CLibPeiMmioWrite16 (I2CBaseAddress
+ R_IC_TAR
, (UINT16
) SlaveAddress
);
405 I2CLibPeiMmioWrite16 (I2CBaseAddress
+ R_IC_RX_TL
, 0);
406 I2CLibPeiMmioWrite16 (I2CBaseAddress
+ R_IC_TX_TL
, 0 );
407 I2CLibPeiMmioWrite16 (I2CBaseAddress
+ R_IC_CON
, I2cMode
);
409 Status
= I2cEnable(I2cControllerIndex
);
410 DEBUG((EFI_D_INFO
, "I2cEnable Status = %r\r\n", Status
));
411 I2CLibPeiMmioRead16 ( I2CBaseAddress
+ R_IC_CLR_TX_ABRT
);
417 Reads a Byte from I2C Device.
419 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected
420 @param SlaveAddress Device Address from which the byte value has to be read
421 @param Offset Offset from which the data has to be read
422 @param *Byte Address to which the value read has to be stored
424 @return EFI_SUCCESS If the byte value has been successfully read
425 @return EFI_DEVICE_ERROR Operation Failed, Device Error
427 EFI_STATUS
ByteReadI2CBasic(
428 IN UINT8 I2cControllerIndex
,
429 IN UINT8 SlaveAddress
,
431 OUT UINT8
*ReadBuffer
,
440 UINT8
*ReceiveDataEnd
;
441 UINT8
*ReceiveRequest
;
443 UINTN I2CBaseAddress
;
445 I2CBaseAddress
= (UINT32
)(PEI_TEPM_LPSS_I2C0_BAR
+ I2cControllerIndex
* PCI_CONFIG_SPACE_SIZE
);
447 Status
= EFI_SUCCESS
;
449 I2CInit(I2cControllerIndex
, SlaveAddress
);
451 ReceiveDataEnd
= &ReadBuffer
[ReadBytes
];
453 ReceiveRequest
= ReadBuffer
;
454 DEBUG((EFI_D_INFO
,"Read: ---------------%d bytes to RX\r\n",ReceiveDataEnd
- ReceiveRequest
));
456 while ((ReceiveDataEnd
> ReceiveRequest
) || (ReceiveDataEnd
> ReadBuffer
)) {
460 RawIntrStat
= I2CLibPeiMmioRead16 (I2CBaseAddress
+ R_IC_RawIntrStat
);
461 if ( 0 != (RawIntrStat
& I2C_INTR_TX_ABRT
)) {
462 I2CLibPeiMmioRead16 ( I2CBaseAddress
+ R_IC_CLR_TX_ABRT
);
463 Status
= RETURN_DEVICE_ERROR
;
464 DEBUG((EFI_D_INFO
,"TX ABRT ,%d bytes hasn't been transferred\r\n",ReceiveDataEnd
- ReceiveRequest
));
469 // Determine if another byte was received
471 I2cStatus
= I2CLibPeiMmioRead16 ( I2CBaseAddress
+ R_IC_STATUS
);
472 if ( 0 != ( I2cStatus
& STAT_RFNE
)) {
473 ReceiveData
= I2CLibPeiMmioRead16 ( I2CBaseAddress
+ R_IC_DATA_CMD
);
474 *ReadBuffer
++ = (UINT8
)ReceiveData
;
475 DEBUG((EFI_D_INFO
,"MmioRead32 ,1 byte 0x:%x is received\r\n",ReceiveData
));
478 if(ReceiveDataEnd
==ReceiveRequest
) {
480 // Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.
486 // Wait until a read request will fit
488 if ( 0 == ( I2cStatus
& STAT_TFNF
)) {
489 MicroSecondDelay ( 10 );
494 // Issue the next read request
497 I2CLibPeiMmioWrite16 ( I2CBaseAddress
+ R_IC_DATA_CMD
, B_READ_CMD
|B_CMD_RESTART
|B_CMD_STOP
);
498 } else if (!End
&& Start
) {
499 I2CLibPeiMmioWrite16 ( I2CBaseAddress
+ R_IC_DATA_CMD
, B_READ_CMD
|B_CMD_RESTART
);
500 } else if (End
&& !Start
) {
501 I2CLibPeiMmioWrite16 ( I2CBaseAddress
+ R_IC_DATA_CMD
, B_READ_CMD
|B_CMD_STOP
);
502 } else if (!End
&& !Start
) {
503 I2CLibPeiMmioWrite16 ( I2CBaseAddress
+ R_IC_DATA_CMD
, B_READ_CMD
);
514 Writes a Byte to I2C Device.
516 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected
517 @param SlaveAddress Device Address from which the byte value has to be written
518 @param Offset Offset from which the data has to be read
519 @param *Byte Address to which the value written is stored
521 @return EFI_SUCCESS IF the byte value has been successfully written
522 @return EFI_DEVICE_ERROR Operation Failed, Device Error
526 IN UINT8 I2cControllerIndex
,
527 IN UINT8 SlaveAddress
,
529 IN UINT8
*WriteBuffer
,
539 UINTN I2CBaseAddress
;
541 I2CBaseAddress
= (UINT32
)PEI_TEPM_LPSS_I2C0_BAR
+ I2cControllerIndex
* PCI_CONFIG_SPACE_SIZE
;
543 Status
= EFI_SUCCESS
;
545 I2CInit(I2cControllerIndex
, SlaveAddress
);
547 TransmitEnd
= &WriteBuffer
[WriteBytes
];
550 DEBUG((EFI_D_INFO
,"Write: --------------%d bytes to TX\r\n", TransmitEnd
- WriteBuffer
));
552 while ( TransmitEnd
> WriteBuffer
) {
553 I2cStatus
= I2CLibPeiMmioRead16 (I2CBaseAddress
+ R_IC_STATUS
);
554 RawIntrStat
= I2CLibPeiMmioRead16 (I2CBaseAddress
+ R_IC_RawIntrStat
);
555 if ( 0 != (RawIntrStat
& I2C_INTR_TX_ABRT
)) {
556 I2CLibPeiMmioRead16 (I2CBaseAddress
+ R_IC_CLR_TX_ABRT
);
557 Status
= RETURN_DEVICE_ERROR
;
558 DEBUG((EFI_D_ERROR
,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd
, WriteBuffer
));
561 if (0 == ( I2cStatus
& STAT_TFNF
)) {
565 I2CLibPeiMmioWrite16 (I2CBaseAddress
+ R_IC_DATA_CMD
, (*WriteBuffer
++) | B_CMD_RESTART
| B_CMD_STOP
);
566 } else if (!End
&& Start
) {
567 I2CLibPeiMmioWrite16 (I2CBaseAddress
+ R_IC_DATA_CMD
, (*WriteBuffer
++) | B_CMD_RESTART
);
568 } else if (End
&& !Start
) {
569 I2CLibPeiMmioWrite16 (I2CBaseAddress
+ R_IC_DATA_CMD
, (*WriteBuffer
++) | B_CMD_STOP
);
570 } else if (!End
&& !Start
) {
571 I2CLibPeiMmioWrite16 (I2CBaseAddress
+ R_IC_DATA_CMD
, (*WriteBuffer
++));
574 // Add a small delay to work around some odd behavior being seen. Without this delay bytes get dropped.
575 MicroSecondDelay ( FIFO_WRITE_DELAY
);
580 if(EFI_ERROR(Status
)) {
581 DEBUG((EFI_D_INFO
,"I2cStartRequest Exit with Status %r\r\n",Status
));
588 Reads a Byte from I2C Device.
590 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected
591 @param SlaveAddress Device Address from which the byte value has to be read
592 @param Offset Offset from which the data has to be read
593 @param ReadBytes Number of bytes to be read
594 @param *ReadBuffer Address to which the value read has to be stored
596 @return EFI_SUCCESS IF the byte value has been successfully read
597 @return EFI_DEVICE_ERROR Operation Failed, Device Error
601 IN UINT8 I2cControllerIndex
,
602 IN UINT8 SlaveAddress
,
605 OUT UINT8
*ReadBuffer
610 DEBUG ((EFI_D_ERROR
, "ByteReadI2C:---offset:0x%x\n",Offset
));
611 Status
= ByteWriteI2CBasic(I2cControllerIndex
, SlaveAddress
, 1, &Offset
,TRUE
,FALSE
);
612 Status
= ByteReadI2CBasic(I2cControllerIndex
, SlaveAddress
, ReadBytes
, ReadBuffer
, TRUE
, TRUE
);
618 Writes a Byte to I2C Device.
620 @param I2cControllerIndex I2C Bus no to which the I2C device has been connected
621 @param SlaveAddress Device Address from which the byte value has to be written
622 @param Offset Offset from which the data has to be written
623 @param WriteBytes Number of bytes to be written
624 @param *Byte Address to which the value written is stored
626 @return EFI_SUCCESS IF the byte value has been successfully read
627 @return EFI_DEVICE_ERROR Operation Failed, Device Error
629 EFI_STATUS
ByteWriteI2C(
630 IN UINT8 I2cControllerIndex
,
631 IN UINT8 SlaveAddress
,
634 IN UINT8
*WriteBuffer
639 DEBUG ((EFI_D_ERROR
, "ByteWriteI2C:---offset/bytes/buf:0x%x,0x%x,0x%x,0x%x\n",Offset
,WriteBytes
,WriteBuffer
,*WriteBuffer
));
640 Status
= ByteWriteI2CBasic(I2cControllerIndex
, SlaveAddress
, 1, &Offset
, TRUE
, FALSE
);
641 Status
= ByteWriteI2CBasic(I2cControllerIndex
, SlaveAddress
, WriteBytes
, WriteBuffer
, FALSE
, TRUE
);